summaryrefslogtreecommitdiffstats
path: root/src/pybind
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind')
-rw-r--r--src/pybind/CMakeLists.txt100
-rw-r--r--src/pybind/ceph_argparse.py1468
-rw-r--r--src/pybind/ceph_daemon.py412
-rw-r--r--src/pybind/ceph_volume_client.py1586
-rw-r--r--src/pybind/cephfs/CMakeLists.txt3
-rw-r--r--src/pybind/cephfs/MANIFEST.in1
-rw-r--r--src/pybind/cephfs/cephfs.pyx1691
-rwxr-xr-xsrc/pybind/cephfs/setup.py224
-rw-r--r--src/pybind/mgr/.gitignore1
-rw-r--r--src/pybind/mgr/CMakeLists.txt14
-rw-r--r--src/pybind/mgr/alerts/__init__.py1
-rw-r--r--src/pybind/mgr/alerts/module.py259
-rw-r--r--src/pybind/mgr/ansible/.gitignore1
-rw-r--r--src/pybind/mgr/ansible/CMakeLists.txt7
-rw-r--r--src/pybind/mgr/ansible/__init__.py9
-rw-r--r--src/pybind/mgr/ansible/ansible_runner_svc.py326
-rw-r--r--src/pybind/mgr/ansible/module.py729
-rw-r--r--src/pybind/mgr/ansible/output_wizards.py158
-rw-r--r--src/pybind/mgr/ansible/requirements.txt2
-rw-r--r--src/pybind/mgr/ansible/run-tox.sh43
-rw-r--r--src/pybind/mgr/ansible/tests/__init__.py0
-rw-r--r--src/pybind/mgr/ansible/tests/pb_execution_events.data183
-rw-r--r--src/pybind/mgr/ansible/tests/test_client_playbooks.py287
-rw-r--r--src/pybind/mgr/ansible/tests/test_output_wizards.py207
-rw-r--r--src/pybind/mgr/ansible/tox.ini18
-rw-r--r--src/pybind/mgr/balancer/__init__.py1
-rw-r--r--src/pybind/mgr/balancer/module.py1324
-rw-r--r--src/pybind/mgr/crash/__init__.py1
-rw-r--r--src/pybind/mgr/crash/module.py369
-rw-r--r--src/pybind/mgr/dashboard/.coveragerc7
-rw-r--r--src/pybind/mgr/dashboard/.editorconfig29
-rw-r--r--src/pybind/mgr/dashboard/.gitignore16
-rw-r--r--src/pybind/mgr/dashboard/.pylintrc535
-rw-r--r--src/pybind/mgr/dashboard/CMakeLists.txt133
-rw-r--r--src/pybind/mgr/dashboard/HACKING.rst1784
-rw-r--r--src/pybind/mgr/dashboard/README.rst37
-rw-r--r--src/pybind/mgr/dashboard/__init__.py54
-rw-r--r--src/pybind/mgr/dashboard/awsauth.py183
-rw-r--r--src/pybind/mgr/dashboard/cherrypy_backports.py203
-rw-r--r--src/pybind/mgr/dashboard/ci/check_grafana_uids.py155
-rw-r--r--src/pybind/mgr/dashboard/constraints.txt9
-rw-r--r--src/pybind/mgr/dashboard/controllers/__init__.py957
-rw-r--r--src/pybind/mgr/dashboard/controllers/auth.py96
-rw-r--r--src/pybind/mgr/dashboard/controllers/cephfs.py294
-rw-r--r--src/pybind/mgr/dashboard/controllers/cluster_configuration.py106
-rw-r--r--src/pybind/mgr/dashboard/controllers/docs.py427
-rw-r--r--src/pybind/mgr/dashboard/controllers/erasure_code_profile.py66
-rw-r--r--src/pybind/mgr/dashboard/controllers/grafana.py50
-rw-r--r--src/pybind/mgr/dashboard/controllers/health.py189
-rw-r--r--src/pybind/mgr/dashboard/controllers/home.py133
-rw-r--r--src/pybind/mgr/dashboard/controllers/host.py12
-rw-r--r--src/pybind/mgr/dashboard/controllers/iscsi.py1049
-rw-r--r--src/pybind/mgr/dashboard/controllers/logging.py10
-rw-r--r--src/pybind/mgr/dashboard/controllers/logs.py51
-rw-r--r--src/pybind/mgr/dashboard/controllers/mgr_modules.py172
-rw-r--r--src/pybind/mgr/dashboard/controllers/monitor.py40
-rw-r--r--src/pybind/mgr/dashboard/controllers/nfsganesha.py315
-rw-r--r--src/pybind/mgr/dashboard/controllers/osd.py242
-rw-r--r--src/pybind/mgr/dashboard/controllers/perf_counters.py85
-rw-r--r--src/pybind/mgr/dashboard/controllers/pool.py234
-rw-r--r--src/pybind/mgr/dashboard/controllers/prometheus.py83
-rw-r--r--src/pybind/mgr/dashboard/controllers/rbd.py526
-rw-r--r--src/pybind/mgr/dashboard/controllers/rbd_mirroring.py460
-rw-r--r--src/pybind/mgr/dashboard/controllers/rgw.py385
-rw-r--r--src/pybind/mgr/dashboard/controllers/role.py110
-rw-r--r--src/pybind/mgr/dashboard/controllers/saml2.py113
-rw-r--r--src/pybind/mgr/dashboard/controllers/settings.py68
-rw-r--r--src/pybind/mgr/dashboard/controllers/summary.py87
-rw-r--r--src/pybind/mgr/dashboard/controllers/task.py15
-rw-r--r--src/pybind/mgr/dashboard/controllers/user.py91
-rw-r--r--src/pybind/mgr/dashboard/exceptions.py107
-rw-r--r--src/pybind/mgr/dashboard/frontend/.babelrc3
-rw-r--r--src/pybind/mgr/dashboard/frontend/.editorconfig13
-rw-r--r--src/pybind/mgr/dashboard/frontend/.gitignore49
-rw-r--r--src/pybind/mgr/dashboard/frontend/.prettierignore1
-rw-r--r--src/pybind/mgr/dashboard/frontend/.prettierrc5
-rw-r--r--src/pybind/mgr/dashboard/frontend/angular.json233
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/2.22b12bf9358f95829e55.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/3rdpartylicenses.txt1462
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/6.f054f1f260c137d64363.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/7.76846491986b0ea6c0bd.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/8.7550b99d388b9ca165da.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/9.b19f6391d5c667b85d12.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/Ceph_Logo_Stacked_RGB_120411_fa_228x228.1ed169ccc35367a2dab2.pngbin0 -> 12949 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Mimic_Octopus2.jpgbin0 -> 452518 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Nautilus_Octopus.jpgbin0 -> 86126 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.pngbin0 -> 12949 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.pngbin0 -> 18960 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.pngbin0 -> 8330 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Standard_RGB_White_120411_fa.pngbin0 -> 4801 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/loading.gifbin0 -> 35386 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/logo-mini.pngbin0 -> 1811 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/notification-icons.pngbin0 -> 3397 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/assets/prometheus_logo.svg50
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/common.8a53d98b04768bd15706.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/favicon.icobin0 -> 1150 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.35e77a38ca9d85c4e897.eotbin0 -> 188946 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.3a9e014c2469ffa65a0e.woff2bin0 -> 91624 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woffbin0 -> 115148 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.78dcc9c4999659b8026a.svg2849
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.fc46f3dae03b2b2e1cee.ttfbin0 -> 188756 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.448c34a56d699c29117a.woff2bin0 -> 18028 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.89889688147bd7575d63.svg288
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttfbin0 -> 45404 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.f4769f9bdb7466be6508.eotbin0 -> 20127 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.fa2772327f55d8198301.woffbin0 -> 23424 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/index.html28
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/main.a8acf27ca1415ab0d94b.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/polyfills.f31db31652a3fd9f4bca.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/prometheus_logo.074db273ef932a67d91b.svg50
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/runtime.ff444394af058f159c51.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/scripts.fc88ef4a23399c760d0b.js1
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/styles.f5317b15474518dffebc.css27
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui-bundle.js134
-rw-r--r--src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui.css4
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/images.e2e-spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/images.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.e2e-spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.e2e-spec.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.e2e-spec.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.po.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.e2e-spec.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts48
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.e2e-spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/pools/pools.e2e-spec.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/pools/pools.po.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/e2e/tsconfig.e2e.json15
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/environment.build.js74
-rw-r--r--src/pybind/mgr/dashboard/frontend/html-linter.config.json12
-rw-r--r--src/pybind/mgr/dashboard/frontend/i18n.config.json12
-rw-r--r--src/pybind/mgr/dashboard/frontend/package-lock.json15346
-rw-r--r--src/pybind/mgr/dashboard/frontend/package.json139
-rw-r--r--src/pybind/mgr/dashboard/frontend/protractor.conf.js58
-rw-r--r--src/pybind/mgr/dashboard/frontend/proxy.conf.json.sample12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts268
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app.component.html8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app.component.scss31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app.component.spec.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app.component.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/app.module.ts77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts172
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.html58
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.spec.ts37
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.spec.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.ts22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.html35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.spec.ts206
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.ts333
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html147
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.spec.ts138
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.ts123
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html721
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts538
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts813
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html102
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.spec.ts98
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.ts82
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html40
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.spec.ts71
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.ts55
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.html48
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.scss9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts431
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.ts231
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.html55
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.spec.ts79
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.ts114
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.ts63
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.html47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.ts97
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.spec.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirroring.module.ts51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.html25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.spec.ts51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.html50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.spec.ts83
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.ts109
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-response.model.ts3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.html115
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.spec.ts152
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.ts134
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-response.model.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.html21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.spec.ts42
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.ts171
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.html77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.scss4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.spec.ts305
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.ts152
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts102
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.ts67
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.html144
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.spec.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-feature.interface.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-clone-request.model.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-copy-request.model.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-create-request.model.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-edit-request.model.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-mode.enum.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-response.model.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html317
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.spec.ts343
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts678
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.model.ts16
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-parent.model.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html43
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts367
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts353
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-model.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.html53
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.spec.ts64
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.ts136
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-actions.model.ts89
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.html27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts425
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts286
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot.model.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts163
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts212
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.html49
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.scss5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.spec.ts100
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.ts88
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.html52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.spec.ts102
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.ts72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.html49
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.spec.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.ts61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.scss8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts76
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts198
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.html6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.spec.ts35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html65
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.spec.ts52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.ts143
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.spec.ts35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.ts56
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts98
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.html108
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.scss0
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.spec.ts29
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form-create-request.model.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.html168
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.scss12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts107
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts173
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.html39
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.ts157
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.html29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.scss21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.spec.ts151
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.ts80
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts84
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts98
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html107
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss143
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.spec.ts138
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts115
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.html6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.spec.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.html123
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.spec.ts93
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.ts146
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.html18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts176
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.ts192
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-modules.module.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.html60
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.spec.ts86
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.ts77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.scss5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.spec.ts100
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.ts162
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html95
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts292
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts351
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.html9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.spec.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.ts60
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.html50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.spec.ts65
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.ts70
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.options.ts39
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html98
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss0
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts318
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts238
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.spec.ts52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.spec.ts49
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.ts54
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.spec.ts132
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts97
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts70
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.html9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.spec.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts44
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.html219
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts606
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts333
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.spec.ts319
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts201
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.html98
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.spec.ts163
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.ts79
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts44
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.html13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie-color.enum.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.html15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.scss22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.spec.ts74
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.ts187
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html267
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.scss89
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts338
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.ts225
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card-popover.scss42
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.html14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.scss135
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.spec.ts65
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.html4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.spec.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.ts11
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts83
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts53
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.spec.ts40
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.ts22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts127
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts62
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.html5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.spec.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.ts50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.html19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.spec.ts114
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.ts73
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.html104
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.spec.ts72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.ts88
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html530
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts229
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts597
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.html28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.spec.ts325
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts221
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs.module.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter.module.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.html4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.spec.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.html13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.spec.ts63
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.ts74
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html330
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.spec.ts325
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.ts259
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.html34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.spec.ts102
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.ts77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form-data.ts46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html459
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts1140
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts674
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html42
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.scss17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.spec.ts489
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.ts300
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-stat.ts16
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.module.ts61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.ts73
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capabilities.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capability.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-s3-key.ts6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-subuser.ts6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-swift-key.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.html5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.spec.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html101
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html108
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts131
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts160
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.html39
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts291
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts189
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.spec.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts65
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.html84
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.spec.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.ts94
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.html155
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.spec.ts85
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.ts122
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html623
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.scss6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts339
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts713
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.html18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.spec.ts196
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.ts152
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.html144
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.spec.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts86
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.html146
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.spec.ts71
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts132
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.html61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.spec.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.ts35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts134
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/ceph-shared.module.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.model.ts71
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.spec.ts55
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.ts63
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/auth.module.ts86
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.html69
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.scss31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.spec.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.ts68
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.html13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.scss12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.spec.ts77
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.ts83
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form-mode.enum.ts3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html125
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.scss4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts222
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts314
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.model.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.html19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.spec.ts203
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.ts138
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.html15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.scss11
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.spec.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-mode.enum.ts3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-role.model.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html163
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts231
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts234
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.model.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.html22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.spec.ts202
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.ts145
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.spec.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.ts22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/core.module.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.html10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.scss13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.spec.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.html60
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.scss36
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.spec.ts55
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.ts74
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.html21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.spec.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html11
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.scss18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.spec.ts131
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.ts126
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.html36
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.spec.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.ts48
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.html31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.spec.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation.module.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html241
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss210
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts64
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.html57
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.scss1
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.spec.ts89
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.ts58
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.html85
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.scss1
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.spec.ts86
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.ts55
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.html14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.scss11
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.spec.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/api.module.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.spec.ts54
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.ts43
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.spec.ts52
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.spec.ts80
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.spec.ts67
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.ts107
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.spec.ts40
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.spec.ts38
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts20
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.spec.ts97
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.ts61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.spec.ts39
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.ts20
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.spec.ts66
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.ts67
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.spec.ts90
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.ts113
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.spec.ts114
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.ts116
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.spec.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.spec.ts123
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.spec.ts238
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.ts92
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.spec.ts130
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.ts84
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.model.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.spec.ts137
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.ts150
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.spec.ts40
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.spec.ts156
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.ts159
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.spec.ts68
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.ts46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts128
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.spec.ts73
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.html6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.spec.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.ts16
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts92
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.html72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.scss30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.spec.ts295
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.ts118
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.model.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.spec.ts272
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.ts144
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.html26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.spec.ts37
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.ts43
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.html59
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.scss9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts250
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.ts58
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.html28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.spec.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.ts22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html53
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.scss44
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.spec.ts83
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts221
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.spec.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.html18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.scss7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.spec.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.html26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.spec.ts90
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.ts59
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/supported-languages.enum.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.html7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.spec.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.html13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.scss17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.spec.ts42
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.html18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.scss26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.spec.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.html22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.scss8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.spec.ts61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.ts36
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-messages.model.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-option.model.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.html79
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.scss19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.spec.ts278
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.ts150
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.html13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.scss5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.spec.ts53
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.ts123
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.html9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.spec.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.ts86
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.html26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.spec.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.ts27
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts20
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.html18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.scss9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.spec.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts198
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html39
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.scss4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.spec.ts334
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts148
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.scss0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts317
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts224
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html191
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.scss282
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts431
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts582
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.spec.ts41
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts79
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.spec.ts61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts48
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.spec.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts132
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.spec.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.ts122
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/directives.module.ts41
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.spec.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.ts31
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.ts46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.spec.ts50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.ts21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/cell-template.enum.ts18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/components.enum.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/unix_errno.enum.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/enum/view-cache-status.enum.ts6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.spec.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.ts20
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.spec.ts184
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.ts75
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts478
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts284
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/alertmanager-silence.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts59
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.spec.ts95
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts40
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-column.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-fetch-data-context.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-selection.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-user-config.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/chart-tooltip.ts115
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/configuration.ts43
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/credentials.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-rule.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-step.ts7
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/erasure-code-profile.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/executing-task.ts6
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/finished-task.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/login-response.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts62
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/pool-form-info.ts14
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/prometheus-alerts.ts85
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/task-exception.ts9
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/models/task.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.spec.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.ts18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.ts20
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.spec.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts21
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.spec.ts56
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.spec.ts56
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts47
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.spec.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.spec.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.spec.ts54
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.spec.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.ts18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.spec.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.spec.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.spec.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.ts18
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.spec.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.spec.ts32
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.ts16
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.spec.ts8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.ts25
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts106
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.spec.ts22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.ts15
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.spec.ts30
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.spec.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.spec.ts17
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.ts12
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.spec.ts217
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts109
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.spec.ts54
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.spec.ts35
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.ts33
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.spec.ts72
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts29
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.spec.ts54
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.spec.ts90
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.ts79
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/js-error-handler.service.ts16
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.spec.ts34
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.ts24
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.spec.ts82
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts68
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts262
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts207
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.spec.ts98
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.ts73
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.spec.ts190
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts91
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.spec.ts232
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.ts53
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.spec.ts133
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.ts82
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.spec.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.ts146
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.spec.ts45
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.ts42
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.spec.ts117
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.ts85
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.spec.ts136
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts106
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.spec.ts74
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.ts62
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.spec.ts274
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts396
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.spec.ts98
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.ts65
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts66
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts51
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.spec.ts37
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.ts50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/shared.module.ts26
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/.gitkeep0
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/1280px-Mimic_Octopus2.jpgbin0 -> 452518 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/1280px-Nautilus_Octopus.jpgbin0 -> 86126 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.pngbin0 -> 12949 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.pngbin0 -> 18960 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.pngbin0 -> 8330 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Standard_RGB_White_120411_fa.pngbin0 -> 4801 bytes
-rwxr-xr-xsrc/pybind/mgr/dashboard/frontend/src/assets/loading.gifbin0 -> 35386 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/logo-mini.pngbin0 -> 1811 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/notification-icons.pngbin0 -> 3397 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/assets/prometheus_logo.svg50
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/defaults.scss188
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/environments/environment.tpl.ts10
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/favicon.icobin0 -> 1150 bytes
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/index.html28
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/jestGlobalMocks.ts19
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.cs.xlf4365
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.de-DE.xlf4365
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.es-ES.xlf4371
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.fr-FR.xlf4367
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.id-ID.xlf4363
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.it-IT.xlf4367
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.ja-JP.xlf4368
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.ko-KR.xlf4340
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.pl-PL.xlf4360
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.pt-BR.xlf4366
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-CN.xlf4365
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-TW.xlf4371
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/main.ts13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/polyfills.ts67
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/setupJest.ts4
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/styles.scss392
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/styles/chart-tooltip.scss64
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/styles/popover.scss46
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/testing/activated-route-stub.ts23
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts344
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/tsconfig.app.json13
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/tsconfig.spec.json22
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/typings.d.ts5
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/unit-test-configuration.ts.sample1
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/vendor.overrides.scss3
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/vendor.variables.scss1
-rw-r--r--src/pybind/mgr/dashboard/frontend/tsconfig.json16
-rw-r--r--src/pybind/mgr/dashboard/frontend/tslint.json90
-rw-r--r--src/pybind/mgr/dashboard/grafana.py134
-rw-r--r--src/pybind/mgr/dashboard/module.py517
-rw-r--r--src/pybind/mgr/dashboard/plugins/__init__.py74
-rw-r--r--src/pybind/mgr/dashboard/plugins/debug.py91
-rw-r--r--src/pybind/mgr/dashboard/plugins/feature_toggles.py140
-rw-r--r--src/pybind/mgr/dashboard/plugins/interfaces.py82
-rw-r--r--src/pybind/mgr/dashboard/plugins/lru_cache.py47
-rw-r--r--src/pybind/mgr/dashboard/plugins/pluggy.py111
-rw-r--r--src/pybind/mgr/dashboard/plugins/plugin.py33
-rw-r--r--src/pybind/mgr/dashboard/plugins/ttl_cache.py55
-rw-r--r--src/pybind/mgr/dashboard/requirements-py27.txt3
-rw-r--r--src/pybind/mgr/dashboard/requirements-py3.txt3
-rw-r--r--src/pybind/mgr/dashboard/requirements.txt36
-rw-r--r--src/pybind/mgr/dashboard/rest_client.py531
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-backend-api-request.sh23
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-backend-api-tests.sh166
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-backend-rook-api-request.sh40
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-frontend-e2e-tests.sh85
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-frontend-unittests.sh56
-rwxr-xr-xsrc/pybind/mgr/dashboard/run-tox.sh51
-rw-r--r--src/pybind/mgr/dashboard/security.py61
-rw-r--r--src/pybind/mgr/dashboard/services/__init__.py2
-rw-r--r--src/pybind/mgr/dashboard/services/access_control.py670
-rw-r--r--src/pybind/mgr/dashboard/services/auth.py207
-rw-r--r--src/pybind/mgr/dashboard/services/ceph_service.py254
-rw-r--r--src/pybind/mgr/dashboard/services/cephfs.py77
-rw-r--r--src/pybind/mgr/dashboard/services/cephx.py29
-rw-r--r--src/pybind/mgr/dashboard/services/exception.py122
-rw-r--r--src/pybind/mgr/dashboard/services/ganesha.py998
-rw-r--r--src/pybind/mgr/dashboard/services/iscsi_cli.py50
-rw-r--r--src/pybind/mgr/dashboard/services/iscsi_client.py257
-rw-r--r--src/pybind/mgr/dashboard/services/iscsi_config.py135
-rw-r--r--src/pybind/mgr/dashboard/services/orchestrator.py38
-rw-r--r--src/pybind/mgr/dashboard/services/rbd.py177
-rw-r--r--src/pybind/mgr/dashboard/services/rgw_client.py437
-rw-r--r--src/pybind/mgr/dashboard/services/sso.py268
-rw-r--r--src/pybind/mgr/dashboard/services/tcmu_service.py96
-rw-r--r--src/pybind/mgr/dashboard/settings.py201
-rw-r--r--src/pybind/mgr/dashboard/tests/__init__.py262
-rw-r--r--src/pybind/mgr/dashboard/tests/helper.py56
-rw-r--r--src/pybind/mgr/dashboard/tests/test_access_control.py695
-rw-r--r--src/pybind/mgr/dashboard/tests/test_api_auditing.py94
-rw-r--r--src/pybind/mgr/dashboard/tests/test_auth.py20
-rw-r--r--src/pybind/mgr/dashboard/tests/test_ceph_service.py67
-rw-r--r--src/pybind/mgr/dashboard/tests/test_cephfs.py48
-rw-r--r--src/pybind/mgr/dashboard/tests/test_controllers.py192
-rw-r--r--src/pybind/mgr/dashboard/tests/test_docs.py71
-rw-r--r--src/pybind/mgr/dashboard/tests/test_erasure_code_profile.py36
-rw-r--r--src/pybind/mgr/dashboard/tests/test_exceptions.py157
-rw-r--r--src/pybind/mgr/dashboard/tests/test_feature_toggles.py61
-rw-r--r--src/pybind/mgr/dashboard/tests/test_ganesha.py642
-rw-r--r--src/pybind/mgr/dashboard/tests/test_grafana.py116
-rw-r--r--src/pybind/mgr/dashboard/tests/test_home.py68
-rw-r--r--src/pybind/mgr/dashboard/tests/test_iscsi.py998
-rw-r--r--src/pybind/mgr/dashboard/tests/test_notification.py138
-rw-r--r--src/pybind/mgr/dashboard/tests/test_osd.py240
-rw-r--r--src/pybind/mgr/dashboard/tests/test_plugin_debug.py38
-rw-r--r--src/pybind/mgr/dashboard/tests/test_pool.py117
-rw-r--r--src/pybind/mgr/dashboard/tests/test_prometheus.py128
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py95
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rbd_service.py37
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rest_client.py94
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rest_tasks.py86
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rgw.py129
-rw-r--r--src/pybind/mgr/dashboard/tests/test_rgw_client.py112
-rw-r--r--src/pybind/mgr/dashboard/tests/test_settings.py191
-rw-r--r--src/pybind/mgr/dashboard/tests/test_sso.py157
-rw-r--r--src/pybind/mgr/dashboard/tests/test_task.py433
-rw-r--r--src/pybind/mgr/dashboard/tests/test_tools.py188
-rw-r--r--src/pybind/mgr/dashboard/tools.py932
-rw-r--r--src/pybind/mgr/dashboard/tox.ini30
-rw-r--r--src/pybind/mgr/deepsea/__init__.py1
-rw-r--r--src/pybind/mgr/deepsea/module.py527
-rw-r--r--src/pybind/mgr/devicehealth/__init__.py2
-rw-r--r--src/pybind/mgr/devicehealth/module.py651
-rw-r--r--src/pybind/mgr/diskprediction_cloud/__init__.py1
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/__init__.py38
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/__init__.py61
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_cluster.py145
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_mon_osd.py222
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_pool.py57
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/db_relay.py703
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_agent.py70
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_cluster.py35
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk.py175
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk_smart.py182
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_host.py105
-rw-r--r--src/pybind/mgr/diskprediction_cloud/agent/predictor.py48
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/__init__.py61
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/client_pb2.py1775
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/client_pb2_grpc.py395
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/clusterdata.py464
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/cypher.py71
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/grpcclient.py242
-rw-r--r--src/pybind/mgr/diskprediction_cloud/common/server.crt17
-rw-r--r--src/pybind/mgr/diskprediction_cloud/module.py454
-rw-r--r--src/pybind/mgr/diskprediction_cloud/requirements.txt12
-rw-r--r--src/pybind/mgr/diskprediction_cloud/task.py181
-rw-r--r--src/pybind/mgr/diskprediction_local/__init__.py1
-rw-r--r--src/pybind/mgr/diskprediction_local/models/config.json77
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_1.pklbin0 -> 281292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_10.pklbin0 -> 217792 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_104.pklbin0 -> 492492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_105.pklbin0 -> 217192 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_109.pklbin0 -> 256392 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_112.pklbin0 -> 499492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_114.pklbin0 -> 276492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_115.pklbin0 -> 509592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_118.pklbin0 -> 315192 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_119.pklbin0 -> 485992 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_12.pklbin0 -> 275692 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_120.pklbin0 -> 307592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_123.pklbin0 -> 246792 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_124.pklbin0 -> 310292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_125.pklbin0 -> 452492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_128.pklbin0 -> 550492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_131.pklbin0 -> 493192 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_134.pklbin0 -> 266692 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_138.pklbin0 -> 488292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_14.pklbin0 -> 244892 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_141.pklbin0 -> 422368 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_145.pklbin0 -> 359512 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_151.pklbin0 -> 305944 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_16.pklbin0 -> 308192 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_161.pklbin0 -> 305188 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_168.pklbin0 -> 301516 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_169.pklbin0 -> 363400 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_174.pklbin0 -> 323764 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_18.pklbin0 -> 312692 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_182.pklbin0 -> 354652 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_185.pklbin0 -> 317176 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_186.pklbin0 -> 276352 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_195.pklbin0 -> 489544 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_201.pklbin0 -> 307888 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_204.pklbin0 -> 567088 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_206.pklbin0 -> 474856 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_208.pklbin0 -> 283588 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_210.pklbin0 -> 617200 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_212.pklbin0 -> 345148 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_213.pklbin0 -> 357568 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_219.pklbin0 -> 342232 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_221.pklbin0 -> 365128 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_222.pklbin0 -> 314800 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_223.pklbin0 -> 342124 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_225.pklbin0 -> 329812 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_227.pklbin0 -> 296440 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_229.pklbin0 -> 572380 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_230.pklbin0 -> 251188 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_234.pklbin0 -> 277972 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_235.pklbin0 -> 243736 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_236.pklbin0 -> 377872 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_239.pklbin0 -> 571732 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_243.pklbin0 -> 534148 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_27.pklbin0 -> 504592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_3.pklbin0 -> 557192 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_33.pklbin0 -> 547392 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_36.pklbin0 -> 516692 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_44.pklbin0 -> 546592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_50.pklbin0 -> 448292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_57.pklbin0 -> 328292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_59.pklbin0 -> 494292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_6.pklbin0 -> 314092 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_61.pklbin0 -> 499492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_62.pklbin0 -> 483492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_67.pklbin0 -> 492592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_69.pklbin0 -> 288292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_71.pklbin0 -> 228792 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_72.pklbin0 -> 489492 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_78.pklbin0 -> 491392 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_79.pklbin0 -> 284992 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_82.pklbin0 -> 255292 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_85.pklbin0 -> 522092 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_88.pklbin0 -> 502392 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_93.pklbin0 -> 302592 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/models/svm_97.pklbin0 -> 272392 bytes
-rw-r--r--src/pybind/mgr/diskprediction_local/module.py266
-rw-r--r--src/pybind/mgr/diskprediction_local/predictor.py265
-rw-r--r--src/pybind/mgr/hello/__init__.py1
-rw-r--r--src/pybind/mgr/hello/module.py82
-rw-r--r--src/pybind/mgr/influx/__init__.py1
-rw-r--r--src/pybind/mgr/influx/module.py489
-rw-r--r--src/pybind/mgr/insights/CMakeLists.txt7
-rw-r--r--src/pybind/mgr/insights/__init__.py9
-rw-r--r--src/pybind/mgr/insights/health.py191
-rw-r--r--src/pybind/mgr/insights/module.py322
-rw-r--r--src/pybind/mgr/insights/run-tox.sh43
-rw-r--r--src/pybind/mgr/insights/tests/__init__.py0
-rw-r--r--src/pybind/mgr/insights/tests/test_health.py273
-rw-r--r--src/pybind/mgr/insights/tox.ini17
-rw-r--r--src/pybind/mgr/iostat/__init__.py1
-rw-r--r--src/pybind/mgr/iostat/module.py73
-rw-r--r--src/pybind/mgr/k8sevents/README.md81
-rw-r--r--src/pybind/mgr/k8sevents/__init__.py1
-rw-r--r--src/pybind/mgr/k8sevents/module.py1460
-rw-r--r--src/pybind/mgr/k8sevents/rbac_sample.yaml45
-rw-r--r--src/pybind/mgr/localpool/__init__.py1
-rw-r--r--src/pybind/mgr/localpool/module.py136
-rw-r--r--src/pybind/mgr/mgr_module.py1504
-rw-r--r--src/pybind/mgr/mgr_util.py300
-rw-r--r--src/pybind/mgr/orchestrator.py1085
-rw-r--r--src/pybind/mgr/orchestrator_cli/.gitignore1
-rw-r--r--src/pybind/mgr/orchestrator_cli/CMakeLists.txt7
-rw-r--r--src/pybind/mgr/orchestrator_cli/README.md16
-rw-r--r--src/pybind/mgr/orchestrator_cli/__init__.py10
-rw-r--r--src/pybind/mgr/orchestrator_cli/module.py437
-rw-r--r--src/pybind/mgr/orchestrator_cli/requirements.txt2
-rw-r--r--src/pybind/mgr/orchestrator_cli/run-tox.sh46
-rw-r--r--src/pybind/mgr/orchestrator_cli/test_orchestrator.py48
-rw-r--r--src/pybind/mgr/orchestrator_cli/tox.ini18
-rw-r--r--src/pybind/mgr/osd_perf_query/__init__.py1
-rw-r--r--src/pybind/mgr/osd_perf_query/module.py194
-rw-r--r--src/pybind/mgr/pg_autoscaler/__init__.py1
-rw-r--r--src/pybind/mgr/pg_autoscaler/module.py507
-rw-r--r--src/pybind/mgr/progress/__init__.py2
-rw-r--r--src/pybind/mgr/progress/module.py693
-rw-r--r--src/pybind/mgr/prometheus/__init__.py2
-rw-r--r--src/pybind/mgr/prometheus/module.py1324
-rw-r--r--src/pybind/mgr/rbd_support/__init__.py1
-rw-r--r--src/pybind/mgr/rbd_support/module.py1427
-rw-r--r--src/pybind/mgr/restful/__init__.py1
-rw-r--r--src/pybind/mgr/restful/api/__init__.py39
-rw-r--r--src/pybind/mgr/restful/api/config.py86
-rw-r--r--src/pybind/mgr/restful/api/crush.py26
-rw-r--r--src/pybind/mgr/restful/api/doc.py15
-rw-r--r--src/pybind/mgr/restful/api/mon.py40
-rw-r--r--src/pybind/mgr/restful/api/osd.py135
-rw-r--r--src/pybind/mgr/restful/api/perf.py27
-rw-r--r--src/pybind/mgr/restful/api/pool.py140
-rw-r--r--src/pybind/mgr/restful/api/request.py93
-rw-r--r--src/pybind/mgr/restful/api/server.py35
-rw-r--r--src/pybind/mgr/restful/common.py156
-rw-r--r--src/pybind/mgr/restful/context.py2
-rw-r--r--src/pybind/mgr/restful/decorators.py79
-rw-r--r--src/pybind/mgr/restful/hooks.py11
-rw-r--r--src/pybind/mgr/restful/module.py610
-rw-r--r--src/pybind/mgr/rook/__init__.py2
-rw-r--r--src/pybind/mgr/rook/module.py469
-rw-r--r--src/pybind/mgr/rook/rook_cluster.py442
-rw-r--r--src/pybind/mgr/selftest/__init__.py3
-rw-r--r--src/pybind/mgr/selftest/module.py489
-rw-r--r--src/pybind/mgr/ssh/.gitignore1
-rw-r--r--src/pybind/mgr/ssh/README.md93
-rw-r--r--src/pybind/mgr/ssh/Vagrantfile39
-rw-r--r--src/pybind/mgr/ssh/__init__.py1
-rw-r--r--src/pybind/mgr/ssh/ceph.repo23
-rw-r--r--src/pybind/mgr/ssh/module.py740
-rw-r--r--src/pybind/mgr/ssh/remotes.py81
-rw-r--r--src/pybind/mgr/status/__init__.py1
-rw-r--r--src/pybind/mgr/status/module.py261
-rw-r--r--src/pybind/mgr/telegraf/__init__.py1
-rw-r--r--src/pybind/mgr/telegraf/basesocket.py45
-rw-r--r--src/pybind/mgr/telegraf/module.py301
-rw-r--r--src/pybind/mgr/telegraf/protocol.py44
-rw-r--r--src/pybind/mgr/telegraf/utils.py20
-rw-r--r--src/pybind/mgr/telemetry/__init__.py1
-rw-r--r--src/pybind/mgr/telemetry/module.py854
-rw-r--r--src/pybind/mgr/test_orchestrator/__init__.py1
-rw-r--r--src/pybind/mgr/test_orchestrator/module.py259
-rw-r--r--src/pybind/mgr/volumes/__init__.py2
-rw-r--r--src/pybind/mgr/volumes/fs/__init__.py0
-rw-r--r--src/pybind/mgr/volumes/fs/async_cloner.py345
-rw-r--r--src/pybind/mgr/volumes/fs/async_job.py279
-rw-r--r--src/pybind/mgr/volumes/fs/exception.py63
-rw-r--r--src/pybind/mgr/volumes/fs/fs_util.py161
-rw-r--r--src/pybind/mgr/volumes/fs/operations/__init__.py0
-rw-r--r--src/pybind/mgr/volumes/fs/operations/access.py142
-rw-r--r--src/pybind/mgr/volumes/fs/operations/clone_index.py98
-rw-r--r--src/pybind/mgr/volumes/fs/operations/group.py186
-rw-r--r--src/pybind/mgr/volumes/fs/operations/index.py23
-rw-r--r--src/pybind/mgr/volumes/fs/operations/lock.py42
-rw-r--r--src/pybind/mgr/volumes/fs/operations/rankevicter.py114
-rw-r--r--src/pybind/mgr/volumes/fs/operations/resolver.py26
-rw-r--r--src/pybind/mgr/volumes/fs/operations/snapshot_util.py30
-rw-r--r--src/pybind/mgr/volumes/fs/operations/subvolume.py74
-rw-r--r--src/pybind/mgr/volumes/fs/operations/template.py173
-rw-r--r--src/pybind/mgr/volumes/fs/operations/trash.py145
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/__init__.py109
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/auth_metadata.py208
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py144
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/op_sm.py114
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/subvolume_attrs.py61
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py331
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py780
-rw-r--r--src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py370
-rw-r--r--src/pybind/mgr/volumes/fs/operations/volume.py348
-rw-r--r--src/pybind/mgr/volumes/fs/purge_queue.py109
-rw-r--r--src/pybind/mgr/volumes/fs/vol_spec.py37
-rw-r--r--src/pybind/mgr/volumes/fs/volume.py660
-rw-r--r--src/pybind/mgr/volumes/module.py576
-rw-r--r--src/pybind/mgr/zabbix/__init__.py1
-rw-r--r--src/pybind/mgr/zabbix/module.py380
-rw-r--r--src/pybind/mgr/zabbix/zabbix_template.xml2569
-rw-r--r--src/pybind/rados/CMakeLists.txt3
-rw-r--r--src/pybind/rados/MANIFEST.in2
-rw-r--r--src/pybind/rados/rados.pxd39
-rw-r--r--src/pybind/rados/rados.pyx4110
-rwxr-xr-xsrc/pybind/rados/setup.py215
-rw-r--r--src/pybind/rbd/CMakeLists.txt3
-rw-r--r--src/pybind/rbd/MANIFEST.in1
-rw-r--r--src/pybind/rbd/rbd.pyx5348
-rwxr-xr-xsrc/pybind/rbd/setup.py223
-rw-r--r--src/pybind/rgw/CMakeLists.txt3
-rw-r--r--src/pybind/rgw/MANIFEST.in1
-rw-r--r--src/pybind/rgw/rgw.pyx694
-rwxr-xr-xsrc/pybind/rgw/setup.py224
-rw-r--r--src/pybind/tox.ini2
1279 files changed, 209433 insertions, 0 deletions
diff --git a/src/pybind/CMakeLists.txt b/src/pybind/CMakeLists.txt
new file mode 100644
index 00000000..66454317
--- /dev/null
+++ b/src/pybind/CMakeLists.txt
@@ -0,0 +1,100 @@
+include(Distutils)
+
+set(CYTHON_MODULE_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cython_modules)
+
+# Keep the default version last
+if(WITH_PYTHON3)
+ list(APPEND py_vers 3)
+endif()
+if(WITH_PYTHON2)
+ list(APPEND py_vers 2)
+endif()
+if(NOT py_vers)
+ message(FATAL_ERROR "No Python binding enabled. Please enable WITH_PYTHON2 and/or WITH_PYTHON3.")
+endif()
+
+foreach(python_version ${py_vers})
+ if(${python_version} EQUAL 2)
+ set(PYTHON_VERSION "")
+ else(${python_version} EQUAL 2)
+ set(PYTHON_VERSION ${python_version})
+ endif(${python_version} EQUAL 2)
+
+ find_package(Cython REQUIRED)
+
+ add_subdirectory(rados rados${PYTHON_VERSION})
+ add_custom_target(cython${PYTHON_VERSION}_modules ALL
+ DEPENDS cython${PYTHON_VERSION}_rados)
+
+ if(WITH_RBD)
+ add_subdirectory(rbd rbd${PYTHON_VERSION})
+ add_dependencies(cython${PYTHON_VERSION}_modules cython${PYTHON_VERSION}_rbd)
+ endif()
+ if(WITH_CEPHFS)
+ add_subdirectory(cephfs cephfs${PYTHON_VERSION})
+ add_dependencies(cython${PYTHON_VERSION}_modules cython${PYTHON_VERSION}_cephfs)
+ endif()
+ if(WITH_RADOSGW)
+ add_subdirectory(rgw rgw${PYTHON_VERSION})
+ add_dependencies(cython${PYTHON_VERSION}_modules cython${PYTHON_VERSION}_rgw)
+ endif()
+
+ # if CMAKE_INSTALL_PREFIX is an empty string, must replace
+ # it with "/" to make PYTHON_INSTALL_TEMPLATE an absolute path to be
+ # consistent with all other installation paths.
+ if(CMAKE_INSTALL_PREFIX)
+ set(PYTHON_INSTALL_TEMPLATE "${CMAKE_INSTALL_PREFIX}")
+ else(CMAKE_INSTALL_PREFIX)
+ set(PYTHON_INSTALL_TEMPLATE "/")
+ endif(CMAKE_INSTALL_PREFIX)
+
+ execute_process(
+ COMMAND
+ ${PYTHON${PYTHON_VERSION}_EXECUTABLE} -c "from distutils import sysconfig; print(sysconfig.get_python_lib(prefix='${PYTHON_INSTALL_TEMPLATE}'))"
+ OUTPUT_VARIABLE "PYTHON${PYTHON_VERSION}_INSTDIR"
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ install(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/ceph_argparse.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/ceph_daemon.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/ceph_volume_client.py
+ DESTINATION ${PYTHON${PYTHON_VERSION}_INSTDIR})
+endforeach()
+
+if(WITH_MGR)
+ if(NOT WITH_PYTHON2 AND MGR_PYTHON_VERSION_MAJOR EQUAL 2)
+ message(FATAL_ERROR "mgr plugins require python2 binding")
+ elseif(NOT WITH_PYTHON3 AND MGR_PYTHON_VERSION_MAJOR EQUAL 3)
+ message(FATAL_ERROR "mgr plugins require python3 binding")
+ endif()
+
+ if(USE_OPENSSL)
+ execute_process(
+ COMMAND ${PYTHON${PYTHON_VERSION}_EXECUTABLE} -c "import ssl; print('.'.join(map(str,ssl.OPENSSL_VERSION_INFO[0:3])))"
+ RESULT_VARIABLE PYSSL_RESULT
+ OUTPUT_VARIABLE PYSSL_VER
+ ERROR_QUIET)
+ if (NOT ${PYSSL_RESULT})
+ # the ideal way to get the soversion is to parse the suffix of file name of
+ # `/lib/x86_64-linux-gnu/libssl.so.1.0.0`, but since we're lazy, and will just
+ # trust the version number here.
+ macro(get_openssl_soversion version prefix)
+ string(REPLACE "." ";" ssl_version_list ${version})
+ list(GET ssl_version_list 0 ssl_version_major)
+ list(GET ssl_version_list 1 ssl_version_minor)
+ set(${prefix}_SOVERSION ${ssl_version_major}.${ssl_version_minor})
+ unset(ssl_version_list)
+ unset(ssl_version_major)
+ unset(ssl_version_minor)
+ endmacro()
+ get_openssl_soversion(${OPENSSL_VERSION} OPENSSL)
+ get_openssl_soversion(${PYSSL_VER} PYSSL)
+ if(NOT (OPENSSL_SOVERSION VERSION_EQUAL PYSSL_SOVERSION))
+ message(FATAL_ERROR "Python and Ceph link to different OpenSSL versions: ${PYSSL_VER} vs ${OPENSSL_VERSION}")
+ endif()
+ else()
+ message(WARNING "could not determine ssl version of python crypto lib")
+ endif()
+ endif(USE_OPENSSL)
+ add_subdirectory(mgr)
+endif(WITH_MGR)
diff --git a/src/pybind/ceph_argparse.py b/src/pybind/ceph_argparse.py
new file mode 100644
index 00000000..255e0f47
--- /dev/null
+++ b/src/pybind/ceph_argparse.py
@@ -0,0 +1,1468 @@
+"""
+Types and routines used by the ceph CLI as well as the RESTful
+interface. These have to do with querying the daemons for
+command-description information, validating user command input against
+those descriptions, and submitting the command to the appropriate
+daemon.
+
+Copyright (C) 2013 Inktank Storage, Inc.
+
+LGPL2.1. See file COPYING.
+"""
+from __future__ import print_function
+import copy
+import errno
+import math
+import json
+import os
+import pprint
+import re
+import socket
+import stat
+import sys
+import threading
+import uuid
+
+# Flags are from MonCommand.h
+class Flag:
+ NOFORWARD = (1 << 0)
+ OBSOLETE = (1 << 1)
+ DEPRECATED = (1 << 2)
+ MGR = (1<<3)
+ POLL = (1 << 4)
+ HIDDEN = (1 << 5)
+
+KWARG_EQUALS = "--([^=]+)=(.+)"
+KWARG_SPACE = "--([^=]+)"
+
+try:
+ basestring
+except NameError:
+ basestring = str
+
+
+class ArgumentError(Exception):
+ """
+ Something wrong with arguments
+ """
+ pass
+
+
+class ArgumentNumber(ArgumentError):
+ """
+ Wrong number of a repeated argument
+ """
+ pass
+
+
+class ArgumentFormat(ArgumentError):
+ """
+ Argument value has wrong format
+ """
+ pass
+
+
+class ArgumentMissing(ArgumentError):
+ """
+ Argument value missing in a command
+ """
+ pass
+
+
+class ArgumentValid(ArgumentError):
+ """
+ Argument value is otherwise invalid (doesn't match choices, for instance)
+ """
+ pass
+
+
+class ArgumentTooFew(ArgumentError):
+ """
+ Fewer arguments than descriptors in signature; may mean to continue
+ the search, so gets a special exception type
+ """
+
+
+class ArgumentPrefix(ArgumentError):
+ """
+ Special for mismatched prefix; less severe, don't report by default
+ """
+ pass
+
+
+class JsonFormat(Exception):
+ """
+ some syntactic or semantic issue with the JSON
+ """
+ pass
+
+
+class CephArgtype(object):
+ """
+ Base class for all Ceph argument types
+
+ Instantiating an object sets any validation parameters
+ (allowable strings, numeric ranges, etc.). The 'valid'
+ method validates a string against that initialized instance,
+ throwing ArgumentError if there's a problem.
+ """
+ def __init__(self, **kwargs):
+ """
+ set any per-instance validation parameters here
+ from kwargs (fixed string sets, integer ranges, etc)
+ """
+ pass
+
+ def valid(self, s, partial=False):
+ """
+ Run validation against given string s (generally one word);
+ partial means to accept partial string matches (begins-with).
+ If cool, set self.val to the value that should be returned
+ (a copy of the input string, or a numeric or boolean interpretation
+ thereof, for example)
+ if not, throw ArgumentError(msg-as-to-why)
+ """
+ self.val = s
+
+ def __repr__(self):
+ """
+ return string representation of description of type. Note,
+ this is not a representation of the actual value. Subclasses
+ probably also override __str__() to give a more user-friendly
+ 'name/type' description for use in command format help messages.
+ """
+ a = ''
+ if hasattr(self, 'typeargs'):
+ a = self.typeargs
+ return '{0}(\'{1}\')'.format(self.__class__.__name__, a)
+
+ def __str__(self):
+ """
+ where __repr__ (ideally) returns a string that could be used to
+ reproduce the object, __str__ returns one you'd like to see in
+ print messages. Use __str__ to format the argtype descriptor
+ as it would be useful in a command usage message.
+ """
+ return '<{0}>'.format(self.__class__.__name__)
+
+ def complete(self, s):
+ return []
+
+
+class CephInt(CephArgtype):
+ """
+ range-limited integers, [+|-][0-9]+ or 0x[0-9a-f]+
+ range: list of 1 or 2 ints, [min] or [min,max]
+ """
+ def __init__(self, range=''):
+ if range == '':
+ self.range = list()
+ else:
+ self.range = list(range.split('|'))
+ self.range = [int(x) for x in self.range]
+
+ def valid(self, s, partial=False):
+ try:
+ val = int(s, 0)
+ except ValueError:
+ raise ArgumentValid("{0} doesn't represent an int".format(s))
+ if len(self.range) == 2:
+ if val < self.range[0] or val > self.range[1]:
+ raise ArgumentValid("{0} not in range {1}".format(val, self.range))
+ elif len(self.range) == 1:
+ if val < self.range[0]:
+ raise ArgumentValid("{0} not in range {1}".format(val, self.range))
+ self.val = val
+
+ def __str__(self):
+ r = ''
+ if len(self.range) == 1:
+ r = '[{0}-]'.format(self.range[0])
+ if len(self.range) == 2:
+ r = '[{0}-{1}]'.format(self.range[0], self.range[1])
+
+ return '<int{0}>'.format(r)
+
+
+class CephFloat(CephArgtype):
+ """
+ range-limited float type
+ range: list of 1 or 2 floats, [min] or [min, max]
+ """
+ def __init__(self, range=''):
+ if range == '':
+ self.range = list()
+ else:
+ self.range = list(range.split('|'))
+ self.range = [float(x) for x in self.range]
+
+ def valid(self, s, partial=False):
+ try:
+ val = float(s)
+ except ValueError:
+ raise ArgumentValid("{0} doesn't represent a float".format(s))
+ if len(self.range) == 2:
+ if val < self.range[0] or val > self.range[1]:
+ raise ArgumentValid("{0} not in range {1}".format(val, self.range))
+ elif len(self.range) == 1:
+ if val < self.range[0]:
+ raise ArgumentValid("{0} not in range {1}".format(val, self.range))
+ self.val = val
+
+ def __str__(self):
+ r = ''
+ if len(self.range) == 1:
+ r = '[{0}-]'.format(self.range[0])
+ if len(self.range) == 2:
+ r = '[{0}-{1}]'.format(self.range[0], self.range[1])
+ return '<float{0}>'.format(r)
+
+
+class CephString(CephArgtype):
+ """
+ String; pretty generic. goodchars is a RE char class of valid chars
+ """
+ def __init__(self, goodchars=''):
+ from string import printable
+ try:
+ re.compile(goodchars)
+ except:
+ raise ValueError('CephString(): "{0}" is not a valid RE'.
+ format(goodchars))
+ self.goodchars = goodchars
+ self.goodset = frozenset(
+ [c for c in printable if re.match(goodchars, c)]
+ )
+
+ def valid(self, s, partial=False):
+ sset = set(s)
+ if self.goodset and not sset <= self.goodset:
+ raise ArgumentFormat("invalid chars {0} in {1}".
+ format(''.join(sset - self.goodset), s))
+ self.val = s
+
+ def __str__(self):
+ b = ''
+ if self.goodchars:
+ b += '(goodchars {0})'.format(self.goodchars)
+ return '<string{0}>'.format(b)
+
+ def complete(self, s):
+ if s == '':
+ return []
+ else:
+ return [s]
+
+
+class CephSocketpath(CephArgtype):
+ """
+ Admin socket path; check that it's readable and S_ISSOCK
+ """
+ def valid(self, s, partial=False):
+ mode = os.stat(s).st_mode
+ if not stat.S_ISSOCK(mode):
+ raise ArgumentValid('socket path {0} is not a socket'.format(s))
+ self.val = s
+
+ def __str__(self):
+ return '<admin-socket-path>'
+
+
+class CephIPAddr(CephArgtype):
+ """
+ IP address (v4 or v6) with optional port
+ """
+ def valid(self, s, partial=False):
+ # parse off port, use socket to validate addr
+ type = 6
+ if s.startswith('['):
+ type = 6
+ elif s.find('.') != -1:
+ type = 4
+ if type == 4:
+ port = s.find(':')
+ if port != -1:
+ a = s[:port]
+ p = s[port + 1:]
+ if int(p) > 65535:
+ raise ArgumentValid('{0}: invalid IPv4 port'.format(p))
+ else:
+ a = s
+ p = None
+ try:
+ socket.inet_pton(socket.AF_INET, a)
+ except:
+ raise ArgumentValid('{0}: invalid IPv4 address'.format(a))
+ else:
+ # v6
+ if s.startswith('['):
+ end = s.find(']')
+ if end == -1:
+ raise ArgumentFormat('{0} missing terminating ]'.format(s))
+ if s[end + 1] == ':':
+ try:
+ p = int(s[end + 2])
+ except:
+ raise ArgumentValid('{0}: bad port number'.format(s))
+ a = s[1:end]
+ else:
+ a = s
+ p = None
+ try:
+ socket.inet_pton(socket.AF_INET6, a)
+ except:
+ raise ArgumentValid('{0} not valid IPv6 address'.format(s))
+ if p is not None and int(p) > 65535:
+ raise ArgumentValid("{0} not a valid port number".format(p))
+ self.val = s
+ self.addr = a
+ self.port = p
+
+ def __str__(self):
+ return '<IPaddr[:port]>'
+
+
+class CephEntityAddr(CephIPAddr):
+ """
+ EntityAddress, that is, IP address[/nonce]
+ """
+ def valid(self, s, partial=False):
+ nonce = None
+ if '/' in s:
+ ip, nonce = s.split('/')
+ else:
+ ip = s
+ super(self.__class__, self).valid(ip)
+ if nonce:
+ nonce_int = None
+ try:
+ nonce_int = int(nonce)
+ except ValueError:
+ pass
+ if nonce_int is None or nonce_int < 0:
+ raise ArgumentValid(
+ '{0}: invalid entity, nonce {1} not integer > 0'.
+ format(s, nonce)
+ )
+ self.val = s
+
+ def __str__(self):
+ return '<EntityAddr>'
+
+
+class CephPoolname(CephArgtype):
+ """
+ Pool name; very little utility
+ """
+ def __str__(self):
+ return '<poolname>'
+
+
+class CephObjectname(CephArgtype):
+ """
+ Object name. Maybe should be combined with Pool name as they're always
+ present in pairs, and then could be checked for presence
+ """
+ def __str__(self):
+ return '<objectname>'
+
+
+class CephPgid(CephArgtype):
+ """
+ pgid, in form N.xxx (N = pool number, xxx = hex pgnum)
+ """
+ def valid(self, s, partial=False):
+ if s.find('.') == -1:
+ raise ArgumentFormat('pgid has no .')
+ poolid, pgnum = s.split('.', 1)
+ try:
+ poolid = int(poolid)
+ except ValueError:
+ raise ArgumentFormat('pool {0} not integer'.format(poolid))
+ if poolid < 0:
+ raise ArgumentFormat('pool {0} < 0'.format(poolid))
+ try:
+ pgnum = int(pgnum, 16)
+ except ValueError:
+ raise ArgumentFormat('pgnum {0} not hex integer'.format(pgnum))
+ self.val = s
+
+ def __str__(self):
+ return '<pgid>'
+
+
+class CephName(CephArgtype):
+ """
+ Name (type.id) where:
+ type is osd|mon|client|mds
+ id is a base10 int, if type == osd, or a string otherwise
+
+ Also accept '*'
+ """
+ def __init__(self):
+ self.nametype = None
+ self.nameid = None
+
+ def valid(self, s, partial=False):
+ if s == '*':
+ self.val = s
+ return
+ elif s == "mgr":
+ self.nametype = "mgr"
+ self.val = s
+ return
+ elif s == "mon":
+ self.nametype = "mon"
+ self.val = s
+ return
+ if s.find('.') == -1:
+ raise ArgumentFormat('CephName: no . in {0}'.format(s))
+ else:
+ t, i = s.split('.', 1)
+ if t not in ('osd', 'mon', 'client', 'mds', 'mgr'):
+ raise ArgumentValid('unknown type ' + t)
+ if t == 'osd':
+ if i != '*':
+ try:
+ i = int(i)
+ except:
+ raise ArgumentFormat('osd id ' + i + ' not integer')
+ self.nametype = t
+ self.val = s
+ self.nameid = i
+
+ def __str__(self):
+ return '<name (type.id)>'
+
+
+class CephOsdName(CephArgtype):
+ """
+ Like CephName, but specific to osds: allow <id> alone
+
+ osd.<id>, or <id>, or *, where id is a base10 int
+ """
+ def __init__(self):
+ self.nametype = None
+ self.nameid = None
+
+ def valid(self, s, partial=False):
+ if s == '*':
+ self.val = s
+ return
+ if s.find('.') != -1:
+ t, i = s.split('.', 1)
+ if t != 'osd':
+ raise ArgumentValid('unknown type ' + t)
+ else:
+ t = 'osd'
+ i = s
+ try:
+ i = int(i)
+ except:
+ raise ArgumentFormat('osd id ' + i + ' not integer')
+ if i < 0:
+ raise ArgumentFormat('osd id {0} is less than 0'.format(i))
+ self.nametype = t
+ self.nameid = i
+ self.val = i
+
+ def __str__(self):
+ return '<osdname (id|osd.id)>'
+
+
+class CephChoices(CephArgtype):
+ """
+ Set of string literals; init with valid choices
+ """
+ def __init__(self, strings='', **kwargs):
+ self.strings = strings.split('|')
+
+ def valid(self, s, partial=False):
+ if not partial:
+ if s not in self.strings:
+ # show as __str__ does: {s1|s2..}
+ raise ArgumentValid("{0} not in {1}".format(s, self))
+ self.val = s
+ return
+
+ # partial
+ for t in self.strings:
+ if t.startswith(s):
+ self.val = s
+ return
+ raise ArgumentValid("{0} not in {1}". format(s, self))
+
+ def __str__(self):
+ if len(self.strings) == 1:
+ return '{0}'.format(self.strings[0])
+ else:
+ return '{0}'.format('|'.join(self.strings))
+
+ def complete(self, s):
+ all_elems = [token for token in self.strings if token.startswith(s)]
+ return all_elems
+
+
+class CephBool(CephArgtype):
+ """
+ A boolean argument, values may be case insensitive 'true', 'false', '0',
+ '1'. In keyword form, value may be left off (implies true).
+ """
+ def __init__(self, strings='', **kwargs):
+ self.strings = strings.split('|')
+
+ def valid(self, s, partial=False):
+ lower_case = s.lower()
+ if lower_case in ['true', '1']:
+ self.val = True
+ elif lower_case in ['false', '0']:
+ self.val = False
+ else:
+ raise ArgumentValid("{0} not one of 'true', 'false'".format(s))
+
+ def __str__(self):
+ return '<bool>'
+
+
+class CephFilepath(CephArgtype):
+ """
+ Openable file
+ """
+ def valid(self, s, partial=False):
+ # set self.val if the specified path is readable or writable
+ s = os.path.abspath(s)
+ if not os.access(s, os.R_OK):
+ self._validate_writable_file(s)
+ self.val = s
+
+ def _validate_writable_file(self, fname):
+ if os.path.exists(fname):
+ if os.path.isfile(fname):
+ if not os.access(fname, os.W_OK):
+ raise ArgumentValid('{0} is not writable'.format(fname))
+ else:
+ raise ArgumentValid('{0} is not file'.format(fname))
+ else:
+ dirname = os.path.dirname(fname)
+ if not os.access(dirname, os.W_OK):
+ raise ArgumentValid('cannot create file in {0}'.format(dirname))
+
+ def __str__(self):
+ return '<outfilename>'
+
+
+class CephFragment(CephArgtype):
+ """
+ 'Fragment' ??? XXX
+ """
+ def valid(self, s, partial=False):
+ if s.find('/') == -1:
+ raise ArgumentFormat('{0}: no /'.format(s))
+ val, bits = s.split('/')
+ # XXX is this right?
+ if not val.startswith('0x'):
+ raise ArgumentFormat("{0} not a hex integer".format(val))
+ try:
+ int(val)
+ except:
+ raise ArgumentFormat('can\'t convert {0} to integer'.format(val))
+ try:
+ int(bits)
+ except:
+ raise ArgumentFormat('can\'t convert {0} to integer'.format(bits))
+ self.val = s
+
+ def __str__(self):
+ return "<CephFS fragment ID (0xvvv/bbb)>"
+
+
+class CephUUID(CephArgtype):
+ """
+ CephUUID: pretty self-explanatory
+ """
+ def valid(self, s, partial=False):
+ try:
+ uuid.UUID(s)
+ except Exception as e:
+ raise ArgumentFormat('invalid UUID {0}: {1}'.format(s, e))
+ self.val = s
+
+ def __str__(self):
+ return '<uuid>'
+
+
+class CephPrefix(CephArgtype):
+ """
+ CephPrefix: magic type for "all the first n fixed strings"
+ """
+ def __init__(self, prefix=''):
+ self.prefix = prefix
+
+ def valid(self, s, partial=False):
+ try:
+ s = str(s)
+ if isinstance(s, bytes):
+ # `prefix` can always be converted into unicode when being compared,
+ # but `s` could be anything passed by user.
+ s = s.decode('ascii')
+ except UnicodeEncodeError:
+ raise ArgumentPrefix(u"no match for {0}".format(s))
+ except UnicodeDecodeError:
+ raise ArgumentPrefix("no match for {0}".format(s))
+
+ if partial:
+ if self.prefix.startswith(s):
+ self.val = s
+ return
+ else:
+ if s == self.prefix:
+ self.val = s
+ return
+
+ raise ArgumentPrefix("no match for {0}".format(s))
+
+ def __str__(self):
+ return self.prefix
+
+ def complete(self, s):
+ if self.prefix.startswith(s):
+ return [self.prefix.rstrip(' ')]
+ else:
+ return []
+
+
+class argdesc(object):
+ """
+ argdesc(typename, name='name', n=numallowed|N,
+ req=False, helptext=helptext, **kwargs (type-specific))
+
+ validation rules:
+ typename: type(**kwargs) will be constructed
+ later, type.valid(w) will be called with a word in that position
+
+ name is used for parse errors and for constructing JSON output
+ n is a numeric literal or 'n|N', meaning "at least one, but maybe more"
+ req=False means the argument need not be present in the list
+ helptext is the associated help for the command
+ anything else are arguments to pass to the type constructor.
+
+ self.instance is an instance of type t constructed with typeargs.
+
+ valid() will later be called with input to validate against it,
+ and will store the validated value in self.instance.val for extraction.
+ """
+ def __init__(self, t, name=None, n=1, req=True, **kwargs):
+ if isinstance(t, basestring):
+ self.t = CephPrefix
+ self.typeargs = {'prefix': t}
+ self.req = True
+ else:
+ self.t = t
+ self.typeargs = kwargs
+ self.req = req in (True, 'True', 'true')
+
+ self.name = name
+ self.N = (n in ['n', 'N'])
+ if self.N:
+ self.n = 1
+ else:
+ self.n = int(n)
+
+ self.numseen = 0
+
+ self.instance = self.t(**self.typeargs)
+
+ def __repr__(self):
+ r = 'argdesc(' + str(self.t) + ', '
+ internals = ['N', 'typeargs', 'instance', 't']
+ for (k, v) in self.__dict__.items():
+ if k.startswith('__') or k in internals:
+ pass
+ else:
+ # undo modification from __init__
+ if k == 'n' and self.N:
+ v = 'N'
+ r += '{0}={1}, '.format(k, v)
+ for (k, v) in self.typeargs.items():
+ r += '{0}={1}, '.format(k, v)
+ return r[:-2] + ')'
+
+ def __str__(self):
+ if ((self.t == CephChoices and len(self.instance.strings) == 1)
+ or (self.t == CephPrefix)):
+ s = str(self.instance)
+ else:
+ s = '{0}({1})'.format(self.name, str(self.instance))
+ if self.N:
+ s += ' [' + str(self.instance) + '...]'
+ if not self.req:
+ s = '{' + s + '}'
+ return s
+
+ def helpstr(self):
+ """
+ like str(), but omit parameter names (except for CephString,
+ which really needs them)
+ """
+ if self.t == CephString:
+ chunk = '<{0}>'.format(self.name)
+ elif self.t == CephBool:
+ chunk = "--{0}".format(self.name.replace("_", "-"))
+ else:
+ chunk = str(self.instance)
+ s = chunk
+ if self.N:
+ s += ' [' + chunk + '...]'
+ if not self.req:
+ s = '{' + s + '}'
+ return s
+
+ def complete(self, s):
+ return self.instance.complete(s)
+
+
+def concise_sig(sig):
+ """
+ Return string representation of sig useful for syntax reference in help
+ """
+ return ' '.join([d.helpstr() for d in sig])
+
+
+def descsort_key(sh):
+ """
+ sort descriptors by prefixes, defined as the concatenation of all simple
+ strings in the descriptor; this works out to just the leading strings.
+ """
+ return concise_sig(sh['sig'])
+
+
+def descsort(sh1, sh2):
+ """
+ Deprecated; use (key=descsort_key) instead of (cmp=descsort)
+ """
+ return cmp(descsort_key(sh1), descsort_key(sh2))
+
+
+def parse_funcsig(sig):
+ """
+ parse a single descriptor (array of strings or dicts) into a
+ dict of function descriptor/validators (objects of CephXXX type)
+
+ :returns: list of ``argdesc``
+ """
+ newsig = []
+ argnum = 0
+ for desc in sig:
+ argnum += 1
+ if isinstance(desc, basestring):
+ t = CephPrefix
+ desc = {'type': t, 'name': 'prefix', 'prefix': desc}
+ else:
+ # not a simple string, must be dict
+ if 'type' not in desc:
+ s = 'JSON descriptor {0} has no type'.format(sig)
+ raise JsonFormat(s)
+ # look up type string in our globals() dict; if it's an
+ # object of type `type`, it must be a
+ # locally-defined class. otherwise, we haven't a clue.
+ if desc['type'] in globals():
+ t = globals()[desc['type']]
+ if not isinstance(t, type):
+ s = 'unknown type {0}'.format(desc['type'])
+ raise JsonFormat(s)
+ else:
+ s = 'unknown type {0}'.format(desc['type'])
+ raise JsonFormat(s)
+
+ kwargs = dict()
+ for key, val in desc.items():
+ if key not in ['type', 'name', 'n', 'req']:
+ kwargs[key] = val
+ newsig.append(argdesc(t,
+ name=desc.get('name', None),
+ n=desc.get('n', 1),
+ req=desc.get('req', True),
+ **kwargs))
+ return newsig
+
+
+def parse_json_funcsigs(s, consumer):
+ """
+ A function signature is mostly an array of argdesc; it's represented
+ in JSON as
+ {
+ "cmd001": {"sig":[ "type": type, "name": name, "n": num, "req":true|false <other param>], "help":helptext, "module":modulename, "perm":perms, "avail":availability}
+ .
+ .
+ .
+ ]
+
+ A set of sigs is in an dict mapped by a unique number:
+ {
+ "cmd1": {
+ "sig": ["type.. ], "help":helptext...
+ }
+ "cmd2"{
+ "sig": [.. ], "help":helptext...
+ }
+ }
+
+ Parse the string s and return a dict of dicts, keyed by opcode;
+ each dict contains 'sig' with the array of descriptors, and 'help'
+ with the helptext, 'module' with the module name, 'perm' with a
+ string representing required permissions in that module to execute
+ this command (and also whether it is a read or write command from
+ the cluster state perspective), and 'avail' as a hint for
+ whether the command should be advertised by CLI, REST, or both.
+ If avail does not contain 'consumer', don't include the command
+ in the returned dict.
+ """
+ try:
+ overall = json.loads(s)
+ except Exception as e:
+ print("Couldn't parse JSON {0}: {1}".format(s, e), file=sys.stderr)
+ raise e
+ sigdict = {}
+ for cmdtag, cmd in overall.items():
+ if 'sig' not in cmd:
+ s = "JSON descriptor {0} has no 'sig'".format(cmdtag)
+ raise JsonFormat(s)
+ # check 'avail' and possibly ignore this command
+ if 'avail' in cmd:
+ if consumer not in cmd['avail']:
+ continue
+ # rewrite the 'sig' item with the argdesc-ized version, and...
+ cmd['sig'] = parse_funcsig(cmd['sig'])
+ # just take everything else as given
+ sigdict[cmdtag] = cmd
+ return sigdict
+
+
+def validate_one(word, desc, partial=False):
+ """
+ validate_one(word, desc, partial=False)
+
+ validate word against the constructed instance of the type
+ in desc. May raise exception. If it returns false (and doesn't
+ raise an exception), desc.instance.val will
+ contain the validated value (in the appropriate type).
+ """
+ desc.instance.valid(word, partial)
+ desc.numseen += 1
+ if desc.N:
+ desc.n = desc.numseen + 1
+
+
+def matchnum(args, signature, partial=False):
+ """
+ matchnum(s, signature, partial=False)
+
+ Returns number of arguments matched in s against signature.
+ Can be used to determine most-likely command for full or partial
+ matches (partial applies to string matches).
+ """
+ words = args[:]
+ mysig = copy.deepcopy(signature)
+ matchcnt = 0
+ for desc in mysig:
+ desc.numseen = 0
+ while desc.numseen < desc.n:
+ # if there are no more arguments, return
+ if not words:
+ return matchcnt
+ word = words.pop(0)
+
+ try:
+ # only allow partial matching if we're on the last supplied
+ # word; avoid matching foo bar and foot bar just because
+ # partial is set
+ validate_one(word, desc, partial and (len(words) == 0))
+ valid = True
+ except ArgumentError:
+ # matchnum doesn't care about type of error
+ valid = False
+
+ if not valid:
+ if not desc.req:
+ # this wasn't required, so word may match the next desc
+ words.insert(0, word)
+ break
+ else:
+ # it was required, and didn't match, return
+ return matchcnt
+ if desc.req:
+ matchcnt += 1
+ return matchcnt
+
+
+def store_arg(desc, d):
+ '''
+ Store argument described by, and held in, thanks to valid(),
+ desc into the dictionary d, keyed by desc.name. Three cases:
+
+ 1) desc.N is set: value in d is a list
+ 2) prefix: multiple args are joined with ' ' into one d{} item
+ 3) single prefix or other arg: store as simple value
+
+ Used in validate() below.
+ '''
+ if desc.N:
+ # value should be a list
+ if desc.name in d:
+ d[desc.name] += [desc.instance.val]
+ else:
+ d[desc.name] = [desc.instance.val]
+ elif (desc.t == CephPrefix) and (desc.name in d):
+ # prefixes' values should be a space-joined concatenation
+ d[desc.name] += ' ' + desc.instance.val
+ else:
+ # if first CephPrefix or any other type, just set it
+ d[desc.name] = desc.instance.val
+
+
+def validate(args, signature, flags=0, partial=False):
+ """
+ validate(args, signature, flags=0, partial=False)
+
+ args is a list of strings representing a possible
+ command input following format of signature. Runs a validation; no
+ exception means it's OK. Return a dict containing all arguments keyed
+ by their descriptor name, with duplicate args per name accumulated
+ into a list (or space-separated value for CephPrefix).
+
+ Mismatches of prefix are non-fatal, as this probably just means the
+ search hasn't hit the correct command. Mismatches of non-prefix
+ arguments are treated as fatal, and an exception raised.
+
+ This matching is modified if partial is set: allow partial matching
+ (with partial dict returned); in this case, there are no exceptions
+ raised.
+ """
+
+ myargs = copy.deepcopy(args)
+ mysig = copy.deepcopy(signature)
+ reqsiglen = len([desc for desc in mysig if desc.req])
+ matchcnt = 0
+ d = dict()
+ save_exception = None
+
+ arg_descs_by_name = dict([desc.name, desc] for desc in mysig
+ if desc.t != CephPrefix)
+
+ # Special case: detect "injectargs" (legacy way of modifying daemon
+ # configs) and permit "--" string arguments if so.
+ injectargs = myargs and myargs[0] == "injectargs"
+
+ # Make a pass through all arguments
+ for desc in mysig:
+ desc.numseen = 0
+
+ while desc.numseen < desc.n:
+ if myargs:
+ myarg = myargs.pop(0)
+ else:
+ myarg = None
+
+ # no arg, but not required? Continue consuming mysig
+ # in case there are later required args
+ if myarg in (None, []) and not desc.req:
+ break
+
+ # A keyword argument?
+ if myarg:
+ # argdesc for the keyword argument, if we find one
+ kwarg_desc = None
+
+ # Track whether we need to push value back onto
+ # myargs in the case that this isn't a valid k=v
+ consumed_next = False
+
+ # Try both styles of keyword argument
+ kwarg_match = re.match(KWARG_EQUALS, myarg)
+ if kwarg_match:
+ # We have a "--foo=bar" style argument
+ kwarg_k, kwarg_v = kwarg_match.groups()
+
+ # Either "--foo-bar" or "--foo_bar" style is accepted
+ kwarg_k = kwarg_k.replace('-', '_')
+
+ kwarg_desc = arg_descs_by_name.get(kwarg_k, None)
+ else:
+ # Maybe this is a "--foo bar" or "--bool" style argument
+ key_match = re.match(KWARG_SPACE, myarg)
+ if key_match:
+ kwarg_k = key_match.group(1)
+
+ # Permit --foo-bar=123 form or --foo_bar=123 form,
+ # assuming all command definitions use foo_bar argument
+ # naming style
+ kwarg_k = kwarg_k.replace('-', '_')
+
+ kwarg_desc = arg_descs_by_name.get(kwarg_k, None)
+ if kwarg_desc:
+ if kwarg_desc.t == CephBool:
+ kwarg_v = 'true'
+ elif len(myargs): # Some trailing arguments exist
+ kwarg_v = myargs.pop(0)
+ else:
+ # Forget it, this is not a valid kwarg
+ kwarg_desc = None
+
+ if kwarg_desc:
+ validate_one(kwarg_v, kwarg_desc)
+ matchcnt += 1
+ store_arg(kwarg_desc, d)
+ continue
+
+ # Don't handle something as a positional argument if it
+ # has a leading "--" unless it's a CephChoices (used for
+ # "--yes-i-really-mean-it")
+ if myarg and myarg.startswith("--"):
+ # Special cases for instances of confirmation flags
+ # that were defined as CephString/CephChoices instead of CephBool
+ # in pre-nautilus versions of Ceph daemons.
+ is_value = desc.t == CephChoices \
+ or myarg == "--yes-i-really-mean-it" \
+ or myarg == "--yes-i-really-really-mean-it" \
+ or myarg == "--yes-i-really-really-mean-it-not-faking" \
+ or myarg == "--force" \
+ or injectargs
+
+ if not is_value:
+ # Didn't get caught by kwarg handling, but has a "--", so
+ # we must assume it's something invalid, to avoid naively
+ # passing through mis-typed options as the values of
+ # positional arguments.
+ raise ArgumentValid("Unexpected argument '{0}'".format(
+ myarg))
+
+ # out of arguments for a required param?
+ # Either return (if partial validation) or raise
+ if myarg in (None, []) and desc.req:
+ if desc.N and desc.numseen < 1:
+ # wanted N, didn't even get 1
+ if partial:
+ return d
+ raise ArgumentNumber(
+ 'saw {0} of {1}, expected at least 1'.
+ format(desc.numseen, desc)
+ )
+ elif not desc.N and desc.numseen < desc.n:
+ # wanted n, got too few
+ if partial:
+ return d
+ # special-case the "0 expected 1" case
+ if desc.numseen == 0 and desc.n == 1:
+ raise ArgumentMissing(
+ 'missing required parameter {0}'.format(desc)
+ )
+ raise ArgumentNumber(
+ 'saw {0} of {1}, expected {2}'.
+ format(desc.numseen, desc, desc.n)
+ )
+ break
+
+ # Have an arg; validate it
+ try:
+ validate_one(myarg, desc)
+ valid = True
+ except ArgumentError as e:
+ valid = False
+
+ # argument mismatch
+ if not desc.req:
+ # if not required, just push back; it might match
+ # the next arg
+ save_exception = [ myarg, e ]
+ myargs.insert(0, myarg)
+ break
+ else:
+ # hm, it was required, so time to return/raise
+ if partial:
+ return d
+ raise
+
+ # Whew, valid arg acquired. Store in dict
+ matchcnt += 1
+ store_arg(desc, d)
+ # Clear prior exception
+ save_exception = None
+
+ # Done with entire list of argdescs
+ if matchcnt < reqsiglen:
+ raise ArgumentTooFew("not enough arguments given")
+
+ if myargs and not partial:
+ if save_exception:
+ print(save_exception[0], 'not valid: ', save_exception[1], file=sys.stderr)
+ raise ArgumentError("unused arguments: " + str(myargs))
+
+ if flags & Flag.MGR:
+ d['target'] = ('mgr','')
+
+ if flags & Flag.POLL:
+ d['poll'] = True
+
+ # Finally, success
+ return d
+
+
+def validate_command(sigdict, args, verbose=False):
+ """
+ Parse positional arguments into a parameter dict, according to
+ the command descriptions.
+
+ Writes advice about nearly-matching commands ``sys.stderr`` if
+ the arguments do not match any command.
+
+ :param sigdict: A command description dictionary, as returned
+ from Ceph daemons by the get_command_descriptions
+ command.
+ :param args: List of strings, should match one of the command
+ signatures in ``sigdict``
+
+ :returns: A dict of parsed parameters (including ``prefix``),
+ or an empty dict if the args did not match any signature
+ """
+ if verbose:
+ print("validate_command: " + " ".join(args), file=sys.stderr)
+ found = []
+ valid_dict = {}
+
+ # look for best match, accumulate possibles in bestcmds
+ # (so we can maybe give a more-useful error message)
+ best_match_cnt = 0
+ bestcmds = []
+ for cmd in sigdict.values():
+ flags = cmd.get('flags', 0)
+ if flags & Flag.OBSOLETE:
+ continue
+ sig = cmd['sig']
+ matched = matchnum(args, sig, partial=True)
+ if (matched >= math.floor(best_match_cnt) and
+ matched == matchnum(args, sig, partial=False)):
+ # prefer those fully matched over partial patch
+ matched += 0.5
+ if matched < best_match_cnt:
+ continue
+ if verbose:
+ print("better match: {0} > {1}: {2} ".format(
+ matched, best_match_cnt, concise_sig(sig)
+ ), file=sys.stderr)
+ if matched > best_match_cnt:
+ best_match_cnt = matched
+ bestcmds = [cmd]
+ else:
+ bestcmds.append(cmd)
+
+ # Sort bestcmds by number of args so we can try shortest first
+ # (relies on a cmdsig being key,val where val is a list of len 1)
+ bestcmds_sorted = sorted(bestcmds, key=lambda c: len(c['sig']))
+
+ if verbose:
+ print("bestcmds_sorted: ", file=sys.stderr)
+ pprint.PrettyPrinter(stream=sys.stderr).pprint(bestcmds_sorted)
+
+ ex = None
+ # for everything in bestcmds, look for a true match
+ for cmd in bestcmds_sorted:
+ sig = cmd['sig']
+ try:
+ valid_dict = validate(args, sig, flags=cmd.get('flags', 0))
+ found = cmd
+ break
+ except ArgumentPrefix:
+ # ignore prefix mismatches; we just haven't found
+ # the right command yet
+ pass
+ except ArgumentMissing as e:
+ ex = e
+ if len(bestcmds) == 1:
+ found = cmd
+ break
+ except ArgumentTooFew:
+ # It looked like this matched the beginning, but it
+ # didn't have enough args supplied. If we're out of
+ # cmdsigs we'll fall out unfound; if we're not, maybe
+ # the next one matches completely. Whine, but pass.
+ if verbose:
+ print('Not enough args supplied for ',
+ concise_sig(sig), file=sys.stderr)
+ except ArgumentError as e:
+ ex = e
+ # Solid mismatch on an arg (type, range, etc.)
+ # Stop now, because we have the right command but
+ # some other input is invalid
+ found = cmd
+ break
+
+ if found:
+ if not valid_dict:
+ print("Invalid command:", ex, file=sys.stderr)
+ print(concise_sig(sig), ': ', cmd['help'], file=sys.stderr)
+ else:
+ bestcmds = [c for c in bestcmds
+ if not c.get('flags', 0) & (Flag.DEPRECATED | Flag.HIDDEN)]
+ bestcmds = bestcmds[:10] # top 10
+ print('no valid command found; {0} closest matches:'.format(len(bestcmds)), file=sys.stderr)
+ for cmd in bestcmds:
+ print(concise_sig(cmd['sig']), file=sys.stderr)
+ return valid_dict
+
+
+
+def find_cmd_target(childargs):
+ """
+ Using a minimal validation, figure out whether the command
+ should be sent to a monitor or an osd. We do this before even
+ asking for the 'real' set of command signatures, so we can ask the
+ right daemon.
+ Returns ('osd', osdid), ('pg', pgid), ('mgr', '') or ('mon', '')
+ """
+ sig = parse_funcsig(['tell', {'name': 'target', 'type': 'CephName'}])
+ try:
+ valid_dict = validate(childargs, sig, partial=True)
+ except ArgumentError:
+ pass
+ else:
+ if len(valid_dict) == 2:
+ # revalidate to isolate type and id
+ name = CephName()
+ # if this fails, something is horribly wrong, as it just
+ # validated successfully above
+ name.valid(valid_dict['target'])
+ return name.nametype, name.nameid
+
+ sig = parse_funcsig(['tell', {'name': 'pgid', 'type': 'CephPgid'}])
+ try:
+ valid_dict = validate(childargs, sig, partial=True)
+ except ArgumentError:
+ pass
+ else:
+ if len(valid_dict) == 2:
+ # pg doesn't need revalidation; the string is fine
+ return 'pg', valid_dict['pgid']
+
+ # If we reached this far it must mean that so far we've been unable to
+ # obtain a proper target from childargs. This may mean that we are not
+ # dealing with a 'tell' command, or that the specified target is invalid.
+ # If the latter, we likely were unable to catch it because we were not
+ # really looking for it: first we tried to parse a 'CephName' (osd, mon,
+ # mds, followed by and id); given our failure to parse, we tried to parse
+ # a 'CephPgid' instead (e.g., 0.4a). Considering we got this far though
+ # we were unable to do so.
+ #
+ # We will now check if this is a tell and, if so, forcefully validate the
+ # target as a 'CephName'. This must be so because otherwise we will end
+ # up sending garbage to a monitor, which is the default target when a
+ # target is not explicitly specified.
+ # e.g.,
+ # 'ceph status' -> target is any one monitor
+ # 'ceph tell mon.* status -> target is all monitors
+ # 'ceph tell foo status -> target is invalid!
+ if len(childargs) > 1 and childargs[0] == 'tell':
+ name = CephName()
+ # CephName.valid() raises on validation error; find_cmd_target()'s
+ # caller should handle them
+ name.valid(childargs[1])
+ return name.nametype, name.nameid
+
+ sig = parse_funcsig(['pg', {'name': 'pgid', 'type': 'CephPgid'}])
+ try:
+ valid_dict = validate(childargs, sig, partial=True)
+ except ArgumentError:
+ pass
+ else:
+ if len(valid_dict) == 2:
+ return 'pg', valid_dict['pgid']
+
+ return 'mon', ''
+
+
+class RadosThread(threading.Thread):
+ def __init__(self, func, *args, **kwargs):
+ self.args = args
+ self.kwargs = kwargs
+ self.func = func
+ self.exception = None
+ threading.Thread.__init__(self)
+
+ def run(self):
+ try:
+ self.retval = self.func(*self.args, **self.kwargs)
+ except Exception as e:
+ self.exception = e
+
+
+def run_in_thread(func, *args, **kwargs):
+ interrupt = False
+ timeout = kwargs.pop('timeout', 0)
+ if timeout == 0 or timeout == None:
+ # python threading module will just get blocked if timeout is `None`,
+ # otherwise it will keep polling until timeout or thread stops.
+ timeout = 2 ** 32
+ t = RadosThread(func, *args, **kwargs)
+
+ # allow the main thread to exit (presumably, avoid a join() on this
+ # subthread) before this thread terminates. This allows SIGINT
+ # exit of a blocked call. See below.
+ t.daemon = True
+
+ t.start()
+ t.join(timeout=timeout)
+ # ..but allow SIGINT to terminate the waiting. Note: this
+ # relies on the Linux kernel behavior of delivering the signal
+ # to the main thread in preference to any subthread (all that's
+ # strictly guaranteed is that *some* thread that has the signal
+ # unblocked will receive it). But there doesn't seem to be
+ # any interface to create a thread with SIGINT blocked.
+ if t.is_alive():
+ raise Exception("timed out")
+ elif t.exception:
+ raise t.exception
+ else:
+ return t.retval
+
+
+def send_command_retry(*args, **kwargs):
+ while True:
+ try:
+ return send_command(*args, **kwargs)
+ except Exception as e:
+ # If our librados instance has not reached state 'connected'
+ # yet, we'll see an exception like this and retry
+ if ('get_command_descriptions' in str(e) and
+ 'object in state configuring' in str(e)):
+ continue
+ else:
+ raise
+
+def send_command(cluster, target=('mon', ''), cmd=None, inbuf=b'', timeout=0,
+ verbose=False):
+ """
+ Send a command to a daemon using librados's
+ mon_command, osd_command, mgr_command, or pg_command. Any bulk input data
+ comes in inbuf.
+
+ Returns (ret, outbuf, outs); ret is the return code, outbuf is
+ the outbl "bulk useful output" buffer, and outs is any status
+ or error message (intended for stderr).
+
+ If target is osd.N, send command to that osd (except for pgid cmds)
+ """
+ cmd = cmd or []
+ try:
+ if target[0] == 'osd':
+ osdid = target[1]
+
+ if verbose:
+ print('submit {0} to osd.{1}'.format(cmd, osdid),
+ file=sys.stderr)
+ ret, outbuf, outs = run_in_thread(
+ cluster.osd_command, osdid, cmd, inbuf, timeout=timeout)
+
+ elif target[0] == 'mgr':
+ ret, outbuf, outs = run_in_thread(
+ cluster.mgr_command, cmd, inbuf, timeout=timeout)
+
+ elif target[0] == 'pg':
+ pgid = target[1]
+ # pgid will already be in the command for the pg <pgid>
+ # form, but for tell <pgid>, we need to put it in
+ if cmd:
+ cmddict = json.loads(cmd[0])
+ cmddict['pgid'] = pgid
+ else:
+ cmddict = dict(pgid=pgid)
+ cmd = [json.dumps(cmddict)]
+ if verbose:
+ print('submit {0} for pgid {1}'.format(cmd, pgid),
+ file=sys.stderr)
+ ret, outbuf, outs = run_in_thread(
+ cluster.pg_command, pgid, cmd, inbuf, timeout=timeout)
+
+ elif target[0] == 'mon':
+ if verbose:
+ print('{0} to {1}'.format(cmd, target[0]),
+ file=sys.stderr)
+ if len(target) < 2 or target[1] == '':
+ ret, outbuf, outs = run_in_thread(
+ cluster.mon_command, cmd, inbuf, timeout=timeout)
+ else:
+ ret, outbuf, outs = run_in_thread(
+ cluster.mon_command, cmd, inbuf, timeout=timeout, target=target[1])
+ elif target[0] == 'mds':
+ mds_spec = target[1]
+
+ if verbose:
+ print('submit {0} to mds.{1}'.format(cmd, mds_spec),
+ file=sys.stderr)
+
+ try:
+ from cephfs import LibCephFS
+ except ImportError:
+ raise RuntimeError("CephFS unavailable, have you installed libcephfs?")
+
+ filesystem = LibCephFS(rados_inst=cluster)
+ filesystem.init()
+ ret, outbuf, outs = \
+ filesystem.mds_command(mds_spec, cmd, inbuf)
+ filesystem.shutdown()
+ else:
+ raise ArgumentValid("Bad target type '{0}'".format(target[0]))
+
+ except Exception as e:
+ if not isinstance(e, ArgumentError):
+ raise RuntimeError('"{0}": exception {1}'.format(cmd, e))
+ else:
+ raise
+
+ return ret, outbuf, outs
+
+
+def json_command(cluster, target=('mon', ''), prefix=None, argdict=None,
+ inbuf=b'', timeout=0, verbose=False):
+ """
+ Serialize a command and up a JSON command and send it with send_command() above.
+ Prefix may be supplied separately or in argdict. Any bulk input
+ data comes in inbuf.
+
+ If target is osd.N, send command to that osd (except for pgid cmds)
+
+ :param cluster: ``rados.Rados`` instance
+ :param prefix: String to inject into command arguments as 'prefix'
+ :param argdict: Command arguments
+ """
+ cmddict = {}
+ if prefix:
+ cmddict.update({'prefix': prefix})
+
+ if argdict:
+ cmddict.update(argdict)
+ if 'target' in argdict:
+ target = argdict.get('target')
+
+ try:
+ if target[0] == 'osd':
+ osdtarg = CephName()
+ osdtarget = '{0}.{1}'.format(*target)
+ # prefer target from cmddict if present and valid
+ if 'target' in cmddict:
+ osdtarget = cmddict.pop('target')
+ try:
+ osdtarg.valid(osdtarget)
+ target = ('osd', osdtarg.nameid)
+ except:
+ # use the target we were originally given
+ pass
+ ret, outbuf, outs = send_command_retry(cluster,
+ target, [json.dumps(cmddict)],
+ inbuf, timeout, verbose)
+
+ except Exception as e:
+ if not isinstance(e, ArgumentError):
+ raise RuntimeError('"{0}": exception {1}'.format(argdict, e))
+ else:
+ raise
+
+ return ret, outbuf, outs
diff --git a/src/pybind/ceph_daemon.py b/src/pybind/ceph_daemon.py
new file mode 100644
index 00000000..9b55613f
--- /dev/null
+++ b/src/pybind/ceph_daemon.py
@@ -0,0 +1,412 @@
+# -*- mode:python -*-
+# vim: ts=4 sw=4 smarttab expandtab
+
+"""
+Copyright (C) 2015 Red Hat
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License version 2, as published by the Free Software
+Foundation. See file COPYING.
+"""
+
+import sys
+import json
+import socket
+import struct
+import time
+try:
+ from collections.abc import OrderedDict
+except ImportError:
+ from collections import OrderedDict
+from fcntl import ioctl
+from fnmatch import fnmatch
+from prettytable import PrettyTable, HEADER
+from signal import signal, SIGWINCH
+from termios import TIOCGWINSZ
+
+from ceph_argparse import parse_json_funcsigs, validate_command
+
+COUNTER = 0x8
+LONG_RUNNING_AVG = 0x4
+READ_CHUNK_SIZE = 4096
+
+
+def admin_socket(asok_path, cmd, format=''):
+ """
+ Send a daemon (--admin-daemon) command 'cmd'. asok_path is the
+ path to the admin socket; cmd is a list of strings; format may be
+ set to one of the formatted forms to get output in that form
+ (daemon commands don't support 'plain' output).
+ """
+
+ def do_sockio(path, cmd_bytes):
+ """ helper: do all the actual low-level stream I/O """
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ sock.connect(path)
+ try:
+ sock.sendall(cmd_bytes + b'\0')
+ len_str = sock.recv(4)
+ if len(len_str) < 4:
+ raise RuntimeError("no data returned from admin socket")
+ l, = struct.unpack(">I", len_str)
+ sock_ret = b''
+
+ got = 0
+ while got < l:
+ # recv() receives signed int, i.e max 2GB
+ # workaround by capping READ_CHUNK_SIZE per call.
+ want = min(l - got, READ_CHUNK_SIZE)
+ bit = sock.recv(want)
+ sock_ret += bit
+ got += len(bit)
+
+ except Exception as sock_e:
+ raise RuntimeError('exception: ' + str(sock_e))
+ return sock_ret
+
+ try:
+ cmd_json = do_sockio(asok_path,
+ b'{"prefix": "get_command_descriptions"}')
+ except Exception as e:
+ raise RuntimeError('exception getting command descriptions: ' + str(e))
+
+ if cmd == 'get_command_descriptions':
+ return cmd_json
+
+ sigdict = parse_json_funcsigs(cmd_json.decode('utf-8'), 'cli')
+ valid_dict = validate_command(sigdict, cmd)
+ if not valid_dict:
+ raise RuntimeError('invalid command')
+
+ if format:
+ valid_dict['format'] = format
+
+ try:
+ ret = do_sockio(asok_path, json.dumps(valid_dict).encode('utf-8'))
+ except Exception as e:
+ raise RuntimeError('exception: ' + str(e))
+
+ return ret
+
+
+class Termsize(object):
+ DEFAULT_SIZE = (25, 80)
+ def __init__(self):
+ self.rows, self.cols = self._gettermsize()
+ self.changed = False
+
+ def _gettermsize(self):
+ try:
+ fd = sys.stdin.fileno()
+ sz = struct.pack('hhhh', 0, 0, 0, 0)
+ rows, cols = struct.unpack('hhhh', ioctl(fd, TIOCGWINSZ, sz))[:2]
+ return rows, cols
+ except IOError:
+ return self.DEFAULT_SIZE
+
+ def update(self):
+ rows, cols = self._gettermsize()
+ if not self.changed:
+ self.changed = (self.rows, self.cols) != (rows, cols)
+ self.rows, self.cols = rows, cols
+
+ def reset_changed(self):
+ self.changed = False
+
+ def __str__(self):
+ return '%s(%dx%d, changed %s)' % (self.__class__,
+ self.rows, self.cols, self.changed)
+
+ def __repr__(self):
+ return 'Termsize(%d,%d,%s)' % (self.__class__,
+ self.rows, self.cols, self.changed)
+
+
+class DaemonWatcher(object):
+ """
+ Given a Ceph daemon's admin socket path, poll its performance counters
+ and output a series of output lines showing the momentary values of
+ counters of interest (those with the 'nick' property in Ceph's schema)
+ """
+ (
+ BLACK,
+ RED,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ GRAY
+ ) = range(8)
+
+ RESET_SEQ = "\033[0m"
+ COLOR_SEQ = "\033[1;%dm"
+ COLOR_DARK_SEQ = "\033[0;%dm"
+ BOLD_SEQ = "\033[1m"
+ UNDERLINE_SEQ = "\033[4m"
+
+ def __init__(self, asok, statpats=None, min_prio=0):
+ self.asok_path = asok
+ self._colored = False
+
+ self._stats = None
+ self._schema = None
+ self._statpats = statpats
+ self._stats_that_fit = dict()
+ self._min_prio = min_prio
+ self.termsize = Termsize()
+
+ def supports_color(self, ostr):
+ """
+ Returns True if the running system's terminal supports color, and False
+ otherwise.
+ """
+ unsupported_platform = (sys.platform in ('win32', 'Pocket PC'))
+ # isatty is not always implemented, #6223.
+ is_a_tty = hasattr(ostr, 'isatty') and ostr.isatty()
+ if unsupported_platform or not is_a_tty:
+ return False
+ return True
+
+ def colorize(self, msg, color, dark=False):
+ """
+ Decorate `msg` with escape sequences to give the requested color
+ """
+ return (self.COLOR_DARK_SEQ if dark else self.COLOR_SEQ) % (30 + color) \
+ + msg + self.RESET_SEQ
+
+ def bold(self, msg):
+ """
+ Decorate `msg` with escape sequences to make it appear bold
+ """
+ return self.BOLD_SEQ + msg + self.RESET_SEQ
+
+ def format_dimless(self, n, width):
+ """
+ Format a number without units, so as to fit into `width` characters, substituting
+ an appropriate unit suffix.
+ """
+ units = [' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']
+ unit = 0
+ while len("%s" % (int(n) // (1000**unit))) > width - 1:
+ if unit >= len(units) - 1:
+ break;
+ unit += 1
+
+ if unit > 0:
+ truncated_float = ("%f" % (n / (1000.0 ** unit)))[0:width - 1]
+ if truncated_float[-1] == '.':
+ truncated_float = " " + truncated_float[0:-1]
+ else:
+ truncated_float = "%{wid}d".format(wid=width-1) % n
+ formatted = "%s%s" % (truncated_float, units[unit])
+
+ if self._colored:
+ if n == 0:
+ color = self.BLACK, False
+ else:
+ color = self.YELLOW, False
+ return self.bold(self.colorize(formatted[0:-1], color[0], color[1])) \
+ + self.bold(self.colorize(formatted[-1], self.BLACK, False))
+ else:
+ return formatted
+
+ def col_width(self, nick):
+ """
+ Given the short name `nick` for a column, how many characters
+ of width should the column be allocated? Does not include spacing
+ between columns.
+ """
+ return max(len(nick), 4)
+
+ def get_stats_that_fit(self):
+ '''
+ Get a possibly-truncated list of stats to display based on
+ current terminal width. Allow breaking mid-section.
+ '''
+ current_fit = OrderedDict()
+ if self.termsize.changed or not self._stats_that_fit:
+ width = 0
+ for section_name, names in self._stats.items():
+ for name, stat_data in names.items():
+ width += self.col_width(stat_data) + 1
+ if width > self.termsize.cols:
+ break
+ if section_name not in current_fit:
+ current_fit[section_name] = OrderedDict()
+ current_fit[section_name][name] = stat_data
+ if width > self.termsize.cols:
+ break
+
+ self.termsize.reset_changed()
+ changed = current_fit and (current_fit != self._stats_that_fit)
+ if changed:
+ self._stats_that_fit = current_fit
+ return self._stats_that_fit, changed
+
+ def _print_headers(self, ostr):
+ """
+ Print a header row to `ostr`
+ """
+ header = ""
+ stats, _ = self.get_stats_that_fit()
+ for section_name, names in stats.items():
+ section_width = \
+ sum([self.col_width(x) + 1 for x in names.values()]) - 1
+ pad = max(section_width - len(section_name), 0)
+ pad_prefix = pad // 2
+ header += (pad_prefix * '-')
+ header += (section_name[0:section_width])
+ header += ((pad - pad_prefix) * '-')
+ header += ' '
+ header += "\n"
+ ostr.write(self.colorize(header, self.BLUE, True))
+
+ sub_header = ""
+ for section_name, names in stats.items():
+ for stat_name, stat_nick in names.items():
+ sub_header += self.UNDERLINE_SEQ \
+ + self.colorize(
+ stat_nick.ljust(self.col_width(stat_nick)),
+ self.BLUE) \
+ + ' '
+ sub_header = sub_header[0:-1] + self.colorize('|', self.BLUE)
+ sub_header += "\n"
+ ostr.write(sub_header)
+
+ def _print_vals(self, ostr, dump, last_dump):
+ """
+ Print a single row of values to `ostr`, based on deltas between `dump` and
+ `last_dump`.
+ """
+ val_row = ""
+ fit, changed = self.get_stats_that_fit()
+ if changed:
+ self._print_headers(ostr)
+ for section_name, names in fit.items():
+ for stat_name, stat_nick in names.items():
+ stat_type = self._schema[section_name][stat_name]['type']
+ if bool(stat_type & COUNTER):
+ n = max(dump[section_name][stat_name] -
+ last_dump[section_name][stat_name], 0)
+ elif bool(stat_type & LONG_RUNNING_AVG):
+ entries = dump[section_name][stat_name]['avgcount'] - \
+ last_dump[section_name][stat_name]['avgcount']
+ if entries:
+ n = (dump[section_name][stat_name]['sum'] -
+ last_dump[section_name][stat_name]['sum']) \
+ / float(entries)
+ n *= 1000.0 # Present in milliseconds
+ else:
+ n = 0
+ else:
+ n = dump[section_name][stat_name]
+
+ val_row += self.format_dimless(n, self.col_width(stat_nick))
+ val_row += " "
+ val_row = val_row[0:-1]
+ val_row += self.colorize("|", self.BLUE)
+ val_row = val_row[0:-len(self.colorize("|", self.BLUE))]
+ ostr.write("{0}\n".format(val_row))
+
+ def _should_include(self, sect, name, prio):
+ '''
+ boolean: should we output this stat?
+
+ 1) If self._statpats exists and the name filename-glob-matches
+ anything in the list, and prio is high enough, or
+ 2) If self._statpats doesn't exist and prio is high enough
+
+ then yes.
+ '''
+ if self._statpats:
+ sectname = '.'.join((sect, name))
+ if not any([
+ p for p in self._statpats
+ if fnmatch(name, p) or fnmatch(sectname, p)
+ ]):
+ return False
+
+ if self._min_prio is not None and prio is not None:
+ return (prio >= self._min_prio)
+
+ return True
+
+ def _load_schema(self):
+ """
+ Populate our instance-local copy of the daemon's performance counter
+ schema, and work out which stats we will display.
+ """
+ self._schema = json.loads(
+ admin_socket(self.asok_path, ["perf", "schema"]).decode('utf-8'),
+ object_pairs_hook=OrderedDict)
+
+ # Build list of which stats we will display
+ self._stats = OrderedDict()
+ for section_name, section_stats in self._schema.items():
+ for name, schema_data in section_stats.items():
+ prio = schema_data.get('priority', 0)
+ if self._should_include(section_name, name, prio):
+ if section_name not in self._stats:
+ self._stats[section_name] = OrderedDict()
+ self._stats[section_name][name] = schema_data['nick']
+ if not len(self._stats):
+ raise RuntimeError("no stats selected by filters")
+
+ def _handle_sigwinch(self, signo, frame):
+ self.termsize.update()
+
+ def run(self, interval, count=None, ostr=sys.stdout):
+ """
+ Print output at regular intervals until interrupted.
+
+ :param ostr: Stream to which to send output
+ """
+
+ self._load_schema()
+ self._colored = self.supports_color(ostr)
+
+ self._print_headers(ostr)
+
+ last_dump = json.loads(admin_socket(self.asok_path, ["perf", "dump"]).decode('utf-8'))
+ rows_since_header = 0
+
+ try:
+ signal(SIGWINCH, self._handle_sigwinch)
+ while True:
+ dump = json.loads(admin_socket(self.asok_path, ["perf", "dump"]).decode('utf-8'))
+ if rows_since_header >= self.termsize.rows - 2:
+ self._print_headers(ostr)
+ rows_since_header = 0
+ self._print_vals(ostr, dump, last_dump)
+ if count is not None:
+ count -= 1
+ if count <= 0:
+ break
+ rows_since_header += 1
+ last_dump = dump
+
+ # time.sleep() is interrupted by SIGWINCH; avoid that
+ end = time.time() + interval
+ while time.time() < end:
+ time.sleep(end - time.time())
+
+ except KeyboardInterrupt:
+ return
+
+ def list(self, ostr=sys.stdout):
+ """
+ Show all selected stats with section, full name, nick, and prio
+ """
+ table = PrettyTable(('section', 'name', 'nick', 'prio'))
+ table.align['section'] = 'l'
+ table.align['name'] = 'l'
+ table.align['nick'] = 'l'
+ table.align['prio'] = 'r'
+ self._load_schema()
+ for section_name, section_stats in self._stats.items():
+ for name, nick in section_stats.items():
+ prio = self._schema[section_name][name].get('priority') or 0
+ table.add_row((section_name, name, nick, prio))
+ ostr.write(table.get_string(hrules=HEADER) + '\n')
diff --git a/src/pybind/ceph_volume_client.py b/src/pybind/ceph_volume_client.py
new file mode 100644
index 00000000..8fcb0cf8
--- /dev/null
+++ b/src/pybind/ceph_volume_client.py
@@ -0,0 +1,1586 @@
+"""
+Copyright (C) 2015 Red Hat, Inc.
+
+LGPL2.1. See file COPYING.
+"""
+
+from contextlib import contextmanager
+import errno
+import fcntl
+import json
+import logging
+import os
+import re
+import struct
+import sys
+import threading
+import time
+import uuid
+
+from ceph_argparse import json_command
+
+import cephfs
+import rados
+
+def to_bytes(param):
+ '''
+ Helper method that returns byte representation of the given parameter.
+ '''
+ if isinstance(param, str):
+ return param.encode('utf-8')
+ elif param is None:
+ return param
+ else:
+ return str(param).encode('utf-8')
+
+class RadosError(Exception):
+ """
+ Something went wrong talking to Ceph with librados
+ """
+ pass
+
+
+RADOS_TIMEOUT = 10
+
+log = logging.getLogger(__name__)
+
+# Reserved volume group name which we use in paths for volumes
+# that are not assigned to a group (i.e. created with group=None)
+NO_GROUP_NAME = "_nogroup"
+
+# Filename extensions for meta files.
+META_FILE_EXT = ".meta"
+
+class VolumePath(object):
+ """
+ Identify a volume's path as group->volume
+ The Volume ID is a unique identifier, but this is a much more
+ helpful thing to pass around.
+ """
+ def __init__(self, group_id, volume_id):
+ self.group_id = group_id
+ self.volume_id = volume_id
+ assert self.group_id != NO_GROUP_NAME
+ assert self.volume_id != "" and self.volume_id is not None
+
+ def __str__(self):
+ return "{0}/{1}".format(self.group_id, self.volume_id)
+
+
+class ClusterTimeout(Exception):
+ """
+ Exception indicating that we timed out trying to talk to the Ceph cluster,
+ either to the mons, or to any individual daemon that the mons indicate ought
+ to be up but isn't responding to us.
+ """
+ pass
+
+
+class ClusterError(Exception):
+ """
+ Exception indicating that the cluster returned an error to a command that
+ we thought should be successful based on our last knowledge of the cluster
+ state.
+ """
+ def __init__(self, action, result_code, result_str):
+ self._action = action
+ self._result_code = result_code
+ self._result_str = result_str
+
+ def __str__(self):
+ return "Error {0} (\"{1}\") while {2}".format(
+ self._result_code, self._result_str, self._action)
+
+
+class RankEvicter(threading.Thread):
+ """
+ Thread for evicting client(s) from a particular MDS daemon instance.
+
+ This is more complex than simply sending a command, because we have to
+ handle cases where MDS daemons might not be fully up yet, and/or might
+ be transiently unresponsive to commands.
+ """
+ class GidGone(Exception):
+ pass
+
+ POLL_PERIOD = 5
+
+ def __init__(self, volume_client, client_spec, rank, gid, mds_map, ready_timeout):
+ """
+ :param client_spec: list of strings, used as filter arguments to "session evict"
+ pass ["id=123"] to evict a single client with session id 123.
+ """
+ self.rank = rank
+ self.gid = gid
+ self._mds_map = mds_map
+ self._client_spec = client_spec
+ self._volume_client = volume_client
+ self._ready_timeout = ready_timeout
+ self._ready_waited = 0
+
+ self.success = False
+ self.exception = None
+
+ super(RankEvicter, self).__init__()
+
+ def _ready_to_evict(self):
+ if self._mds_map['up'].get("mds_{0}".format(self.rank), None) != self.gid:
+ log.info("Evicting {0} from {1}/{2}: rank no longer associated with gid, done.".format(
+ self._client_spec, self.rank, self.gid
+ ))
+ raise RankEvicter.GidGone()
+
+ info = self._mds_map['info']["gid_{0}".format(self.gid)]
+ log.debug("_ready_to_evict: state={0}".format(info['state']))
+ return info['state'] in ["up:active", "up:clientreplay"]
+
+ def _wait_for_ready(self):
+ """
+ Wait for that MDS rank to reach an active or clientreplay state, and
+ not be laggy.
+ """
+ while not self._ready_to_evict():
+ if self._ready_waited > self._ready_timeout:
+ raise ClusterTimeout()
+
+ time.sleep(self.POLL_PERIOD)
+ self._ready_waited += self.POLL_PERIOD
+
+ self._mds_map = self._volume_client.get_mds_map()
+
+ def _evict(self):
+ """
+ Run the eviction procedure. Return true on success, false on errors.
+ """
+
+ # Wait til the MDS is believed by the mon to be available for commands
+ try:
+ self._wait_for_ready()
+ except self.GidGone:
+ return True
+
+ # Then send it an evict
+ ret = errno.ETIMEDOUT
+ while ret == errno.ETIMEDOUT:
+ log.debug("mds_command: {0}, {1}".format(
+ "%s" % self.gid, ["session", "evict"] + self._client_spec
+ ))
+ ret, outb, outs = self._volume_client.fs.mds_command(
+ "%s" % self.gid,
+ json.dumps({
+ "prefix": "session evict",
+ "filters": self._client_spec
+ }), "")
+ log.debug("mds_command: complete {0} {1}".format(ret, outs))
+
+ # If we get a clean response, great, it's gone from that rank.
+ if ret == 0:
+ return True
+ elif ret == errno.ETIMEDOUT:
+ # Oh no, the MDS went laggy (that's how libcephfs knows to emit this error)
+ self._mds_map = self._volume_client.get_mds_map()
+ try:
+ self._wait_for_ready()
+ except self.GidGone:
+ return True
+ else:
+ raise ClusterError("Sending evict to mds.{0}".format(self.gid), ret, outs)
+
+ def run(self):
+ try:
+ self._evict()
+ except Exception as e:
+ self.success = False
+ self.exception = e
+ else:
+ self.success = True
+
+
+class EvictionError(Exception):
+ pass
+
+
+class CephFSVolumeClientError(Exception):
+ """
+ Something went wrong talking to Ceph using CephFSVolumeClient.
+ """
+ pass
+
+
+CEPHFSVOLUMECLIENT_VERSION_HISTORY = """
+
+ CephFSVolumeClient Version History:
+
+ * 1 - Initial version
+ * 2 - Added get_object, put_object, delete_object methods to CephFSVolumeClient
+ * 3 - Allow volumes to be created without RADOS namespace isolation
+ * 4 - Added get_object_and_version, put_object_versioned method to CephFSVolumeClient
+ * 5 - Disallow authorize API for users not created by CephFSVolumeClient
+ * 6 - The 'volumes' key in auth-metadata-file is changed to 'subvolumes'.
+"""
+
+
+class CephFSVolumeClient(object):
+ """
+ Combine libcephfs and librados interfaces to implement a
+ 'Volume' concept implemented as a cephfs directory and
+ client capabilities which restrict mount access to this
+ directory.
+
+ Additionally, volumes may be in a 'Group'. Conveniently,
+ volumes are a lot like manila shares, and groups are a lot
+ like manila consistency groups.
+
+ Refer to volumes with VolumePath, which specifies the
+ volume and group IDs (both strings). The group ID may
+ be None.
+
+ In general, functions in this class are allowed raise rados.Error
+ or cephfs.Error exceptions in unexpected situations.
+ """
+
+ # Current version
+ version = 6
+
+ # Where shall we create our volumes?
+ POOL_PREFIX = "fsvolume_"
+ DEFAULT_VOL_PREFIX = "/volumes"
+ DEFAULT_NS_PREFIX = "fsvolumens_"
+
+ def __init__(self, auth_id=None, conf_path=None, cluster_name=None,
+ volume_prefix=None, pool_ns_prefix=None, rados=None,
+ fs_name=None):
+ """
+ Either set all three of ``auth_id``, ``conf_path`` and
+ ``cluster_name`` (rados constructed on connect), or
+ set ``rados`` (existing rados instance).
+ """
+ self.fs = None
+ self.fs_name = fs_name
+ self.connected = False
+
+ self.conf_path = conf_path
+ self.cluster_name = cluster_name
+ self.auth_id = auth_id
+
+ self.rados = rados
+ if self.rados:
+ # Using an externally owned rados, so we won't tear it down
+ # on disconnect
+ self.own_rados = False
+ else:
+ # self.rados will be constructed in connect
+ self.own_rados = True
+
+ self.volume_prefix = volume_prefix if volume_prefix else self.DEFAULT_VOL_PREFIX
+ self.pool_ns_prefix = pool_ns_prefix if pool_ns_prefix else self.DEFAULT_NS_PREFIX
+ # For flock'ing in cephfs, I want a unique ID to distinguish me
+ # from any other manila-share services that are loading this module.
+ # We could use pid, but that's unnecessary weak: generate a
+ # UUID
+ self._id = struct.unpack(">Q", uuid.uuid1().bytes[0:8])[0]
+
+ # TODO: version the on-disk structures
+
+ def recover(self):
+ # Scan all auth keys to see if they're dirty: if they are, they have
+ # state that might not have propagated to Ceph or to the related
+ # volumes yet.
+
+ # Important: we *always* acquire locks in the order auth->volume
+ # That means a volume can never be dirty without the auth key
+ # we're updating it with being dirty at the same time.
+
+ # First list the auth IDs that have potentially dirty on-disk metadata
+ log.debug("Recovering from partial auth updates (if any)...")
+
+ try:
+ dir_handle = self.fs.opendir(self.volume_prefix)
+ except cephfs.ObjectNotFound:
+ log.debug("Nothing to recover. No auth meta files.")
+ return
+
+ d = self.fs.readdir(dir_handle)
+ auth_ids = []
+
+ if not d:
+ log.debug("Nothing to recover. No auth meta files.")
+
+ while d:
+ # Identify auth IDs from auth meta filenames. The auth meta files
+ # are named as, "$<auth_id><meta filename extension>"
+ regex = "^\$(.*){0}$".format(re.escape(META_FILE_EXT))
+ match = re.search(regex, d.d_name.decode(encoding='utf-8'))
+ if match:
+ auth_ids.append(match.group(1))
+
+ d = self.fs.readdir(dir_handle)
+
+ self.fs.closedir(dir_handle)
+
+ # Key points based on ordering:
+ # * Anything added in VMeta is already added in AMeta
+ # * Anything added in Ceph is already added in VMeta
+ # * Anything removed in VMeta is already removed in Ceph
+ # * Anything removed in AMeta is already removed in VMeta
+
+ # Deauthorization: because I only update metadata AFTER the
+ # update of the next level down, I have the same ordering of
+ # -> things which exist in the AMeta should also exist
+ # in the VMeta, should also exist in Ceph, and the same
+ # recovery procedure that gets me consistent after crashes
+ # during authorization will also work during deauthorization
+
+ # Now for each auth ID, check for dirty flag and apply updates
+ # if dirty flag is found
+ for auth_id in auth_ids:
+ with self._auth_lock(auth_id):
+ auth_meta = self._auth_metadata_get(auth_id)
+ # Update 'volumes' key (old style auth metadata file) to 'subvolumes' key
+ if auth_meta and 'volumes' in auth_meta:
+ auth_meta['subvolumes'] = auth_meta.pop('volumes')
+ if not auth_meta or not auth_meta['subvolumes']:
+ # Clean up auth meta file
+ self.fs.unlink(self._auth_metadata_path(auth_id))
+ continue
+ if not auth_meta['dirty']:
+ continue
+ self._recover_auth_meta(auth_id, auth_meta)
+
+ log.debug("Recovered from partial auth updates (if any).")
+
+ def _recover_auth_meta(self, auth_id, auth_meta):
+ """
+ Call me after locking the auth meta file.
+ """
+ remove_volumes = []
+
+ for volume, volume_data in auth_meta['subvolumes'].items():
+ if not volume_data['dirty']:
+ continue
+
+ (group_id, volume_id) = volume.split('/')
+ group_id = group_id if group_id != 'None' else None
+ volume_path = VolumePath(group_id, volume_id)
+ access_level = volume_data['access_level']
+
+ with self._volume_lock(volume_path):
+ vol_meta = self._volume_metadata_get(volume_path)
+
+ # No VMeta update indicates that there was no auth update
+ # in Ceph either. So it's safe to remove corresponding
+ # partial update in AMeta.
+ if not vol_meta or auth_id not in vol_meta['auths']:
+ remove_volumes.append(volume)
+ continue
+
+ want_auth = {
+ 'access_level': access_level,
+ 'dirty': False,
+ }
+ # VMeta update looks clean. Ceph auth update must have been
+ # clean.
+ if vol_meta['auths'][auth_id] == want_auth:
+ auth_meta['subvolumes'][volume]['dirty'] = False
+ self._auth_metadata_set(auth_id, auth_meta)
+ continue
+
+ readonly = access_level == 'r'
+ client_entity = "client.{0}".format(auth_id)
+ try:
+ existing_caps = self._rados_command(
+ 'auth get',
+ {
+ 'entity': client_entity
+ }
+ )
+ # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
+ except rados.Error:
+ existing_caps = None
+ self._authorize_volume(volume_path, auth_id, readonly, existing_caps)
+
+ # Recovered from partial auth updates for the auth ID's access
+ # to a volume.
+ auth_meta['subvolumes'][volume]['dirty'] = False
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ for volume in remove_volumes:
+ del auth_meta['subvolumes'][volume]
+
+ if not auth_meta['subvolumes']:
+ # Clean up auth meta file
+ self.fs.unlink(self._auth_metadata_path(auth_id))
+ return
+
+ # Recovered from all partial auth updates for the auth ID.
+ auth_meta['dirty'] = False
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ def get_mds_map(self):
+ fs_map = self._rados_command("fs dump", {})
+ return fs_map['filesystems'][0]['mdsmap']
+
+ def evict(self, auth_id, timeout=30, volume_path=None):
+ """
+ Evict all clients based on the authorization ID and optionally based on
+ the volume path mounted. Assumes that the authorization key has been
+ revoked prior to calling this function.
+
+ This operation can throw an exception if the mon cluster is unresponsive, or
+ any individual MDS daemon is unresponsive for longer than the timeout passed in.
+ """
+
+ client_spec = ["auth_name={0}".format(auth_id), ]
+ if volume_path:
+ client_spec.append("client_metadata.root={0}".
+ format(self._get_path(volume_path)))
+
+ log.info("evict clients with {0}".format(', '.join(client_spec)))
+
+ mds_map = self.get_mds_map()
+ up = {}
+ for name, gid in mds_map['up'].items():
+ # Quirk of the MDSMap JSON dump: keys in the up dict are like "mds_0"
+ assert name.startswith("mds_")
+ up[int(name[4:])] = gid
+
+ # For all MDS ranks held by a daemon
+ # Do the parallelism in python instead of using "tell mds.*", because
+ # the latter doesn't give us per-mds output
+ threads = []
+ for rank, gid in up.items():
+ thread = RankEvicter(self, client_spec, rank, gid, mds_map,
+ timeout)
+ thread.start()
+ threads.append(thread)
+
+ for t in threads:
+ t.join()
+
+ log.info("evict: joined all")
+
+ for t in threads:
+ if not t.success:
+ msg = ("Failed to evict client with {0} from mds {1}/{2}: {3}".
+ format(', '.join(client_spec), t.rank, t.gid, t.exception)
+ )
+ log.error(msg)
+ raise EvictionError(msg)
+
+ def _get_path(self, volume_path):
+ """
+ Determine the path within CephFS where this volume will live
+ :return: absolute path (string)
+ """
+ return os.path.join(
+ self.volume_prefix,
+ volume_path.group_id if volume_path.group_id is not None else NO_GROUP_NAME,
+ volume_path.volume_id)
+
+ def _get_group_path(self, group_id):
+ if group_id is None:
+ raise ValueError("group_id may not be None")
+
+ return os.path.join(
+ self.volume_prefix,
+ group_id
+ )
+
+ def _connect(self, premount_evict):
+ log.debug("Connecting to cephfs...")
+ self.fs = cephfs.LibCephFS(rados_inst=self.rados)
+ log.debug("CephFS initializing...")
+ self.fs.init()
+ if premount_evict is not None:
+ log.debug("Premount eviction of {0} starting".format(premount_evict))
+ self.evict(premount_evict)
+ log.debug("Premount eviction of {0} completes".format(premount_evict))
+ log.debug("CephFS mounting...")
+ self.fs.mount(filesystem_name=to_bytes(self.fs_name))
+ log.debug("Connection to cephfs complete")
+
+ # Recover from partial auth updates due to a previous
+ # crash.
+ self.recover()
+
+ def connect(self, premount_evict = None):
+ """
+
+ :param premount_evict: Optional auth_id to evict before mounting the filesystem: callers
+ may want to use this to specify their own auth ID if they expect
+ to be a unique instance and don't want to wait for caps to time
+ out after failure of another instance of themselves.
+ """
+ if self.own_rados:
+ log.debug("Configuring to RADOS with config {0}...".format(self.conf_path))
+ self.rados = rados.Rados(
+ name="client.{0}".format(self.auth_id),
+ clustername=self.cluster_name,
+ conffile=self.conf_path,
+ conf={}
+ )
+ if self.rados.state != "connected":
+ log.debug("Connecting to RADOS...")
+ self.rados.connect()
+ log.debug("Connection to RADOS complete")
+ self._connect(premount_evict)
+
+ def get_mon_addrs(self):
+ log.info("get_mon_addrs")
+ result = []
+ mon_map = self._rados_command("mon dump")
+ for mon in mon_map['mons']:
+ ip_port = mon['addr'].split("/")[0]
+ result.append(ip_port)
+
+ return result
+
+ def disconnect(self):
+ log.info("disconnect")
+ if self.fs:
+ log.debug("Disconnecting cephfs...")
+ self.fs.shutdown()
+ self.fs = None
+ log.debug("Disconnecting cephfs complete")
+
+ if self.rados and self.own_rados:
+ log.debug("Disconnecting rados...")
+ self.rados.shutdown()
+ self.rados = None
+ log.debug("Disconnecting rados complete")
+
+ def __enter__(self):
+ self.connect()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.disconnect()
+
+ def __del__(self):
+ self.disconnect()
+
+ def _get_pool_id(self, osd_map, pool_name):
+ # Maybe borrow the OSDMap wrapper class from calamari if more helpers
+ # like this are needed.
+ for pool in osd_map['pools']:
+ if pool['pool_name'] == pool_name:
+ return pool['pool']
+
+ return None
+
+ def _create_volume_pool(self, pool_name):
+ """
+ Idempotently create a pool for use as a CephFS data pool, with the given name
+
+ :return The ID of the created pool
+ """
+ osd_map = self._rados_command('osd dump', {})
+
+ existing_id = self._get_pool_id(osd_map, pool_name)
+ if existing_id is not None:
+ log.info("Pool {0} already exists".format(pool_name))
+ return existing_id
+
+ osd_count = len(osd_map['osds'])
+
+ # We can't query the actual cluster config remotely, but since this is
+ # just a heuristic we'll assume that the ceph.conf we have locally reflects
+ # that in use in the rest of the cluster.
+ pg_warn_max_per_osd = int(self.rados.conf_get('mon_max_pg_per_osd'))
+
+ other_pgs = 0
+ for pool in osd_map['pools']:
+ if not pool['pool_name'].startswith(self.POOL_PREFIX):
+ other_pgs += pool['pg_num']
+
+ # A basic heuristic for picking pg_num: work out the max number of
+ # PGs we can have without tripping a warning, then subtract the number
+ # of PGs already created by non-manila pools, then divide by ten. That'll
+ # give you a reasonable result on a system where you have "a few" manila
+ # shares.
+ pg_num = ((pg_warn_max_per_osd * osd_count) - other_pgs) // 10
+ # TODO Alternatively, respect an override set by the user.
+
+ self._rados_command(
+ 'osd pool create',
+ {
+ 'pool': pool_name,
+ 'pg_num': int(pg_num),
+ }
+ )
+
+ osd_map = self._rados_command('osd dump', {})
+ pool_id = self._get_pool_id(osd_map, pool_name)
+
+ if pool_id is None:
+ # If the pool isn't there, that's either a ceph bug, or it's some outside influence
+ # removing it right after we created it.
+ log.error("OSD map doesn't contain expected pool '{0}':\n{1}".format(
+ pool_name, json.dumps(osd_map, indent=2)
+ ))
+ raise RuntimeError("Pool '{0}' not present in map after creation".format(pool_name))
+ else:
+ return pool_id
+
+ def create_group(self, group_id, mode=0o755):
+ # Prevent craftily-named volume groups from colliding with the meta
+ # files.
+ if group_id.endswith(META_FILE_EXT):
+ raise ValueError("group ID cannot end with '{0}'.".format(
+ META_FILE_EXT))
+ path = self._get_group_path(group_id)
+ self._mkdir_p(path, mode)
+
+ def destroy_group(self, group_id):
+ path = self._get_group_path(group_id)
+ try:
+ self.fs.stat(self.volume_prefix)
+ except cephfs.ObjectNotFound:
+ pass
+ else:
+ self.fs.rmdir(path)
+
+ def _mkdir_p(self, path, mode=0o755):
+ try:
+ self.fs.stat(path)
+ except cephfs.ObjectNotFound:
+ pass
+ else:
+ return
+
+ parts = path.split(os.path.sep)
+
+ for i in range(1, len(parts) + 1):
+ subpath = os.path.join(*parts[0:i])
+ try:
+ self.fs.stat(subpath)
+ except cephfs.ObjectNotFound:
+ self.fs.mkdir(subpath, mode)
+
+ def create_volume(self, volume_path, size=None, data_isolated=False, namespace_isolated=True,
+ mode=0o755):
+ """
+ Set up metadata, pools and auth for a volume.
+
+ This function is idempotent. It is safe to call this again
+ for an already-created volume, even if it is in use.
+
+ :param volume_path: VolumePath instance
+ :param size: In bytes, or None for no size limit
+ :param data_isolated: If true, create a separate OSD pool for this volume
+ :param namespace_isolated: If true, use separate RADOS namespace for this volume
+ :return:
+ """
+ path = self._get_path(volume_path)
+ log.info("create_volume: {0}".format(path))
+
+ self._mkdir_p(path, mode)
+
+ if size is not None:
+ self.fs.setxattr(path, 'ceph.quota.max_bytes', to_bytes(size), 0)
+
+ # data_isolated means create a separate pool for this volume
+ if data_isolated:
+ pool_name = "{0}{1}".format(self.POOL_PREFIX, volume_path.volume_id)
+ log.info("create_volume: {0}, create pool {1} as data_isolated =True.".format(volume_path, pool_name))
+ pool_id = self._create_volume_pool(pool_name)
+ mds_map = self.get_mds_map()
+ if pool_id not in mds_map['data_pools']:
+ self._rados_command("fs add_data_pool", {
+ 'fs_name': mds_map['fs_name'],
+ 'pool': pool_name
+ })
+ time.sleep(5) # time for MDSMap to be distributed
+ self.fs.setxattr(path, 'ceph.dir.layout.pool', to_bytes(pool_name), 0)
+
+ # enforce security isolation, use separate namespace for this volume
+ if namespace_isolated:
+ namespace = "{0}{1}".format(self.pool_ns_prefix, volume_path.volume_id)
+ log.info("create_volume: {0}, using rados namespace {1} to isolate data.".format(volume_path, namespace))
+ self.fs.setxattr(path, 'ceph.dir.layout.pool_namespace',
+ to_bytes(namespace), 0)
+ else:
+ # If volume's namespace layout is not set, then the volume's pool
+ # layout remains unset and will undesirably change with ancestor's
+ # pool layout changes.
+ pool_name = self._get_ancestor_xattr(path, "ceph.dir.layout.pool")
+ self.fs.setxattr(path, 'ceph.dir.layout.pool',
+ to_bytes(pool_name), 0)
+
+ # Create a volume meta file, if it does not already exist, to store
+ # data about auth ids having access to the volume
+ fd = self.fs.open(self._volume_metadata_path(volume_path),
+ os.O_CREAT, 0o755)
+ self.fs.close(fd)
+
+ return {
+ 'mount_path': path
+ }
+
+ def delete_volume(self, volume_path, data_isolated=False):
+ """
+ Make a volume inaccessible to guests. This function is
+ idempotent. This is the fast part of tearing down a volume: you must
+ also later call purge_volume, which is the slow part.
+
+ :param volume_path: Same identifier used in create_volume
+ :return:
+ """
+
+ path = self._get_path(volume_path)
+ log.info("delete_volume: {0}".format(path))
+
+ # Create the trash folder if it doesn't already exist
+ trash = os.path.join(self.volume_prefix, "_deleting")
+ self._mkdir_p(trash)
+
+ # We'll move it to here
+ trashed_volume = os.path.join(trash, volume_path.volume_id)
+
+ # Move the volume's data to the trash folder
+ try:
+ self.fs.stat(path)
+ except cephfs.ObjectNotFound:
+ log.warning("Trying to delete volume '{0}' but it's already gone".format(
+ path))
+ else:
+ self.fs.rename(path, trashed_volume)
+
+ # Delete the volume meta file, if it's not already deleted
+ vol_meta_path = self._volume_metadata_path(volume_path)
+ try:
+ self.fs.unlink(vol_meta_path)
+ except cephfs.ObjectNotFound:
+ pass
+
+ def purge_volume(self, volume_path, data_isolated=False):
+ """
+ Finish clearing up a volume that was previously passed to delete_volume. This
+ function is idempotent.
+ """
+
+ trash = os.path.join(self.volume_prefix, "_deleting")
+ trashed_volume = os.path.join(trash, volume_path.volume_id)
+
+ try:
+ self.fs.stat(trashed_volume)
+ except cephfs.ObjectNotFound:
+ log.warning("Trying to purge volume '{0}' but it's already been purged".format(
+ trashed_volume))
+ return
+
+ def rmtree(root_path):
+ log.debug("rmtree {0}".format(root_path))
+ dir_handle = self.fs.opendir(root_path)
+ d = self.fs.readdir(dir_handle)
+ while d:
+ d_name = d.d_name.decode(encoding='utf-8')
+ if d_name not in [".", ".."]:
+ # Do not use os.path.join because it is sensitive
+ # to string encoding, we just pass through dnames
+ # as byte arrays
+ d_full = u"{0}/{1}".format(root_path, d_name)
+ if d.is_dir():
+ rmtree(d_full)
+ else:
+ self.fs.unlink(d_full)
+
+ d = self.fs.readdir(dir_handle)
+ self.fs.closedir(dir_handle)
+
+ self.fs.rmdir(root_path)
+
+ rmtree(trashed_volume)
+
+ if data_isolated:
+ pool_name = "{0}{1}".format(self.POOL_PREFIX, volume_path.volume_id)
+ osd_map = self._rados_command("osd dump", {})
+ pool_id = self._get_pool_id(osd_map, pool_name)
+ mds_map = self.get_mds_map()
+ if pool_id in mds_map['data_pools']:
+ self._rados_command("fs rm_data_pool", {
+ 'fs_name': mds_map['fs_name'],
+ 'pool': pool_name
+ })
+ self._rados_command("osd pool delete",
+ {
+ "pool": pool_name,
+ "pool2": pool_name,
+ "yes_i_really_really_mean_it": True
+ })
+
+ def _get_ancestor_xattr(self, path, attr):
+ """
+ Helper for reading layout information: if this xattr is missing
+ on the requested path, keep checking parents until we find it.
+ """
+ try:
+ result = self.fs.getxattr(path, attr).decode()
+ if result == "":
+ # Annoying! cephfs gives us empty instead of an error when attr not found
+ raise cephfs.NoData()
+ else:
+ return result
+ except cephfs.NoData:
+ if path == "/":
+ raise
+ else:
+ return self._get_ancestor_xattr(os.path.split(path)[0], attr)
+
+ def _check_compat_version(self, compat_version):
+ if self.version < compat_version:
+ msg = ("The current version of CephFSVolumeClient, version {0} "
+ "does not support the required feature. Need version {1} "
+ "or greater".format(self.version, compat_version)
+ )
+ log.error(msg)
+ raise CephFSVolumeClientError(msg)
+
+ def _metadata_get(self, path):
+ """
+ Return a deserialized JSON object, or None
+ """
+ fd = self.fs.open(path, "r")
+ # TODO iterate instead of assuming file < 4MB
+ read_bytes = self.fs.read(fd, 0, 4096 * 1024)
+ self.fs.close(fd)
+ if read_bytes:
+ return json.loads(read_bytes.decode())
+ else:
+ return None
+
+ def _metadata_set(self, path, data):
+ serialized = json.dumps(data)
+ fd = self.fs.open(path, "w")
+ try:
+ self.fs.write(fd, to_bytes(serialized), 0)
+ self.fs.fsync(fd, 0)
+ finally:
+ self.fs.close(fd)
+
+ def _lock(self, path):
+ @contextmanager
+ def fn():
+ while(1):
+ fd = self.fs.open(path, os.O_CREAT, 0o755)
+ self.fs.flock(fd, fcntl.LOCK_EX, self._id)
+
+ # The locked file will be cleaned up sometime. It could be
+ # unlinked e.g., by an another manila share instance, before
+ # lock was applied on it. Perform checks to ensure that this
+ # does not happen.
+ try:
+ statbuf = self.fs.stat(path)
+ except cephfs.ObjectNotFound:
+ self.fs.close(fd)
+ continue
+
+ fstatbuf = self.fs.fstat(fd)
+ if statbuf.st_ino == fstatbuf.st_ino:
+ break
+
+ try:
+ yield
+ finally:
+ self.fs.flock(fd, fcntl.LOCK_UN, self._id)
+ self.fs.close(fd)
+
+ return fn()
+
+ def _auth_metadata_path(self, auth_id):
+ return os.path.join(self.volume_prefix, "${0}{1}".format(
+ auth_id, META_FILE_EXT))
+
+ def _auth_lock(self, auth_id):
+ return self._lock(self._auth_metadata_path(auth_id))
+
+ def _auth_metadata_get(self, auth_id):
+ """
+ Call me with the metadata locked!
+
+ Check whether a auth metadata structure can be decoded by the current
+ version of CephFSVolumeClient.
+
+ Return auth metadata that the current version of CephFSVolumeClient
+ can decode.
+ """
+ auth_metadata = self._metadata_get(self._auth_metadata_path(auth_id))
+
+ if auth_metadata:
+ self._check_compat_version(auth_metadata['compat_version'])
+
+ return auth_metadata
+
+ def _auth_metadata_set(self, auth_id, data):
+ """
+ Call me with the metadata locked!
+
+ Fsync the auth metadata.
+
+ Add two version attributes to the auth metadata,
+ 'compat_version', the minimum CephFSVolumeClient version that can
+ decode the metadata, and 'version', the CephFSVolumeClient version
+ that encoded the metadata.
+ """
+ data['compat_version'] = 6
+ data['version'] = self.version
+ return self._metadata_set(self._auth_metadata_path(auth_id), data)
+
+ def _volume_metadata_path(self, volume_path):
+ return os.path.join(self.volume_prefix, "_{0}:{1}{2}".format(
+ volume_path.group_id if volume_path.group_id else "",
+ volume_path.volume_id,
+ META_FILE_EXT
+ ))
+
+ def _volume_lock(self, volume_path):
+ """
+ Return a ContextManager which locks the authorization metadata for
+ a particular volume, and persists a flag to the metadata indicating
+ that it is currently locked, so that we can detect dirty situations
+ during recovery.
+
+ This lock isn't just to make access to the metadata safe: it's also
+ designed to be used over the two-step process of checking the
+ metadata and then responding to an authorization request, to
+ ensure that at the point we respond the metadata hasn't changed
+ in the background. It's key to how we avoid security holes
+ resulting from races during that problem ,
+ """
+ return self._lock(self._volume_metadata_path(volume_path))
+
+ def _volume_metadata_get(self, volume_path):
+ """
+ Call me with the metadata locked!
+
+ Check whether a volume metadata structure can be decoded by the current
+ version of CephFSVolumeClient.
+
+ Return a volume_metadata structure that the current version of
+ CephFSVolumeClient can decode.
+ """
+ volume_metadata = self._metadata_get(self._volume_metadata_path(volume_path))
+
+ if volume_metadata:
+ self._check_compat_version(volume_metadata['compat_version'])
+
+ return volume_metadata
+
+ def _volume_metadata_set(self, volume_path, data):
+ """
+ Call me with the metadata locked!
+
+ Add two version attributes to the volume metadata,
+ 'compat_version', the minimum CephFSVolumeClient version that can
+ decode the metadata and 'version', the CephFSVolumeClient version
+ that encoded the metadata.
+ """
+ data['compat_version'] = 1
+ data['version'] = self.version
+ return self._metadata_set(self._volume_metadata_path(volume_path), data)
+
+ def _prepare_updated_caps_list(self, existing_caps, mds_cap_str, osd_cap_str, authorize=True):
+ caps_list = []
+ for k, v in existing_caps['caps'].items():
+ if k == 'mds' or k == 'osd':
+ continue
+ elif k == 'mon':
+ if not authorize and v == 'allow r':
+ continue
+ caps_list.extend((k,v))
+
+ if mds_cap_str:
+ caps_list.extend(('mds', mds_cap_str))
+ if osd_cap_str:
+ caps_list.extend(('osd', osd_cap_str))
+
+ if authorize and 'mon' not in caps_list:
+ caps_list.extend(('mon', 'allow r'))
+
+ return caps_list
+
+ def authorize(self, volume_path, auth_id, readonly=False, tenant_id=None, allow_existing_id=False):
+ """
+ Get-or-create a Ceph auth identity for `auth_id` and grant them access
+ to
+ :param volume_path:
+ :param auth_id:
+ :param readonly:
+ :param tenant_id: Optionally provide a stringizable object to
+ restrict any created cephx IDs to other callers
+ passing the same tenant ID.
+ :allow_existing_id: Optionally authorize existing auth-ids not
+ created by ceph_volume_client
+ :return:
+ """
+
+ with self._auth_lock(auth_id):
+ client_entity = "client.{0}".format(auth_id)
+ try:
+ existing_caps = self._rados_command(
+ 'auth get',
+ {
+ 'entity': client_entity
+ }
+ )
+ # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
+ except rados.Error:
+ existing_caps = None
+
+ # Existing meta, or None, to be updated
+ auth_meta = self._auth_metadata_get(auth_id)
+
+ # subvolume data to be inserted
+ volume_path_str = str(volume_path)
+ subvolume = {
+ volume_path_str : {
+ # The access level at which the auth_id is authorized to
+ # access the volume.
+ 'access_level': 'r' if readonly else 'rw',
+ 'dirty': True,
+ }
+ }
+
+ if auth_meta is None:
+ if not allow_existing_id and existing_caps is not None:
+ msg = "auth ID: {0} exists and not created by ceph_volume_client. Not allowed to modify".format(auth_id)
+ log.error(msg)
+ raise CephFSVolumeClientError(msg)
+
+ # non-existent auth IDs
+ sys.stderr.write("Creating meta for ID {0} with tenant {1}\n".format(
+ auth_id, tenant_id
+ ))
+ log.debug("Authorize: no existing meta")
+ auth_meta = {
+ 'dirty': True,
+ 'tenant_id': tenant_id.__str__() if tenant_id else None,
+ 'subvolumes': subvolume
+ }
+ else:
+ # Update 'volumes' key (old style auth metadata file) to 'subvolumes' key
+ if 'volumes' in auth_meta:
+ auth_meta['subvolumes'] = auth_meta.pop('volumes')
+
+ # Disallow tenants to share auth IDs
+ if auth_meta['tenant_id'].__str__() != tenant_id.__str__():
+ msg = "auth ID: {0} is already in use".format(auth_id)
+ log.error(msg)
+ raise CephFSVolumeClientError(msg)
+
+ if auth_meta['dirty']:
+ self._recover_auth_meta(auth_id, auth_meta)
+
+ log.debug("Authorize: existing tenant {tenant}".format(
+ tenant=auth_meta['tenant_id']
+ ))
+ auth_meta['dirty'] = True
+ auth_meta['subvolumes'].update(subvolume)
+
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ with self._volume_lock(volume_path):
+ key = self._authorize_volume(volume_path, auth_id, readonly, existing_caps)
+
+ auth_meta['dirty'] = False
+ auth_meta['subvolumes'][volume_path_str]['dirty'] = False
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ if tenant_id:
+ return {
+ 'auth_key': key
+ }
+ else:
+ # Caller wasn't multi-tenant aware: be safe and don't give
+ # them a key
+ return {
+ 'auth_key': None
+ }
+
+ def _authorize_volume(self, volume_path, auth_id, readonly, existing_caps):
+ vol_meta = self._volume_metadata_get(volume_path)
+
+ access_level = 'r' if readonly else 'rw'
+ auth = {
+ auth_id: {
+ 'access_level': access_level,
+ 'dirty': True,
+ }
+ }
+
+ if vol_meta is None:
+ vol_meta = {
+ 'auths': auth
+ }
+ else:
+ vol_meta['auths'].update(auth)
+ self._volume_metadata_set(volume_path, vol_meta)
+
+ key = self._authorize_ceph(volume_path, auth_id, readonly, existing_caps)
+
+ vol_meta['auths'][auth_id]['dirty'] = False
+ self._volume_metadata_set(volume_path, vol_meta)
+
+ return key
+
+ def _authorize_ceph(self, volume_path, auth_id, readonly, existing_caps):
+ path = self._get_path(volume_path)
+ log.debug("Authorizing Ceph id '{0}' for path '{1}'".format(
+ auth_id, path
+ ))
+
+ # First I need to work out what the data pool is for this share:
+ # read the layout
+ pool_name = self._get_ancestor_xattr(path, "ceph.dir.layout.pool")
+
+ try:
+ namespace = self.fs.getxattr(path, "ceph.dir.layout.pool_"
+ "namespace").decode()
+ except cephfs.NoData:
+ namespace = None
+
+ # Now construct auth capabilities that give the guest just enough
+ # permissions to access the share
+ client_entity = "client.{0}".format(auth_id)
+ want_access_level = 'r' if readonly else 'rw'
+ want_mds_cap = 'allow {0} path={1}'.format(want_access_level, path)
+ if namespace:
+ want_osd_cap = 'allow {0} pool={1} namespace={2}'.format(
+ want_access_level, pool_name, namespace)
+ else:
+ want_osd_cap = 'allow {0} pool={1}'.format(want_access_level,
+ pool_name)
+
+ if existing_caps is None:
+ caps = self._rados_command(
+ 'auth get-or-create',
+ {
+ 'entity': client_entity,
+ 'caps': [
+ 'mds', want_mds_cap,
+ 'osd', want_osd_cap,
+ 'mon', 'allow r']
+ })
+ else:
+ # entity exists, update it
+ cap = existing_caps[0]
+
+ # Construct auth caps that if present might conflict with the desired
+ # auth caps.
+ unwanted_access_level = 'r' if want_access_level == 'rw' else 'rw'
+ unwanted_mds_cap = 'allow {0} path={1}'.format(unwanted_access_level, path)
+ if namespace:
+ unwanted_osd_cap = 'allow {0} pool={1} namespace={2}'.format(
+ unwanted_access_level, pool_name, namespace)
+ else:
+ unwanted_osd_cap = 'allow {0} pool={1}'.format(
+ unwanted_access_level, pool_name)
+
+ def cap_update(
+ orig_mds_caps, orig_osd_caps, want_mds_cap,
+ want_osd_cap, unwanted_mds_cap, unwanted_osd_cap):
+
+ if not orig_mds_caps:
+ return want_mds_cap, want_osd_cap
+
+ mds_cap_tokens = [x.strip() for x in orig_mds_caps.split(",")]
+ osd_cap_tokens = [x.strip() for x in orig_osd_caps.split(",")]
+
+ if want_mds_cap in mds_cap_tokens:
+ return orig_mds_caps, orig_osd_caps
+
+ if unwanted_mds_cap in mds_cap_tokens:
+ mds_cap_tokens.remove(unwanted_mds_cap)
+ osd_cap_tokens.remove(unwanted_osd_cap)
+
+ mds_cap_tokens.append(want_mds_cap)
+ osd_cap_tokens.append(want_osd_cap)
+
+ return ",".join(mds_cap_tokens), ",".join(osd_cap_tokens)
+
+ orig_mds_caps = cap['caps'].get('mds', "")
+ orig_osd_caps = cap['caps'].get('osd', "")
+
+ mds_cap_str, osd_cap_str = cap_update(
+ orig_mds_caps, orig_osd_caps, want_mds_cap, want_osd_cap,
+ unwanted_mds_cap, unwanted_osd_cap)
+
+ caps_list = self._prepare_updated_caps_list(cap, mds_cap_str, osd_cap_str)
+ caps = self._rados_command(
+ 'auth caps',
+ {
+ 'entity': client_entity,
+ 'caps': caps_list
+ })
+
+ caps = self._rados_command(
+ 'auth get',
+ {
+ 'entity': client_entity
+ }
+ )
+
+ # Result expected like this:
+ # [
+ # {
+ # "entity": "client.foobar",
+ # "key": "AQBY0\/pViX\/wBBAAUpPs9swy7rey1qPhzmDVGQ==",
+ # "caps": {
+ # "mds": "allow *",
+ # "mon": "allow *"
+ # }
+ # }
+ # ]
+ assert len(caps) == 1
+ assert caps[0]['entity'] == client_entity
+ return caps[0]['key']
+
+ def deauthorize(self, volume_path, auth_id):
+ with self._auth_lock(auth_id):
+ # Existing meta, or None, to be updated
+ auth_meta = self._auth_metadata_get(auth_id)
+
+ # Update 'volumes' key (old style auth metadata file) to 'subvolumes' key
+ if auth_meta and 'volumes' in auth_meta:
+ auth_meta['subvolumes'] = auth_meta.pop('volumes')
+
+ volume_path_str = str(volume_path)
+ if (auth_meta is None) or (not auth_meta['subvolumes']):
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for volume ID '{volume}'".format(
+ auth_id=auth_id, volume=volume_path.volume_id
+ ))
+ # Clean up the auth meta file of an auth ID
+ self.fs.unlink(self._auth_metadata_path(auth_id))
+ return
+
+ if volume_path_str not in auth_meta['subvolumes']:
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for volume ID '{volume}'".format(
+ auth_id=auth_id, volume=volume_path.volume_id
+ ))
+ return
+
+ if auth_meta['dirty']:
+ self._recover_auth_meta(auth_id, auth_meta)
+
+ auth_meta['dirty'] = True
+ auth_meta['subvolumes'][volume_path_str]['dirty'] = True
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ self._deauthorize_volume(volume_path, auth_id)
+
+ # Filter out the volume we're deauthorizing
+ del auth_meta['subvolumes'][volume_path_str]
+
+ # Clean up auth meta file
+ if not auth_meta['subvolumes']:
+ self.fs.unlink(self._auth_metadata_path(auth_id))
+ return
+
+ auth_meta['dirty'] = False
+ self._auth_metadata_set(auth_id, auth_meta)
+
+ def _deauthorize_volume(self, volume_path, auth_id):
+ with self._volume_lock(volume_path):
+ vol_meta = self._volume_metadata_get(volume_path)
+
+ if (vol_meta is None) or (auth_id not in vol_meta['auths']):
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for volume ID '{volume}'".format(
+ auth_id=auth_id, volume=volume_path.volume_id
+ ))
+ return
+
+ vol_meta['auths'][auth_id]['dirty'] = True
+ self._volume_metadata_set(volume_path, vol_meta)
+
+ self._deauthorize(volume_path, auth_id)
+
+ # Remove the auth_id from the metadata *after* removing it
+ # from ceph, so that if we crashed here, we would actually
+ # recreate the auth ID during recovery (i.e. end up with
+ # a consistent state).
+
+ # Filter out the auth we're removing
+ del vol_meta['auths'][auth_id]
+ self._volume_metadata_set(volume_path, vol_meta)
+
+ def _deauthorize(self, volume_path, auth_id):
+ """
+ The volume must still exist.
+ """
+ client_entity = "client.{0}".format(auth_id)
+ path = self._get_path(volume_path)
+ pool_name = self._get_ancestor_xattr(path, "ceph.dir.layout.pool")
+ try:
+ namespace = self.fs.getxattr(path, "ceph.dir.layout.pool_"
+ "namespace").decode()
+ except cephfs.NoData:
+ namespace = None
+
+ # The auth_id might have read-only or read-write mount access for the
+ # volume path.
+ access_levels = ('r', 'rw')
+ want_mds_caps = ['allow {0} path={1}'.format(access_level, path)
+ for access_level in access_levels]
+ if namespace:
+ want_osd_caps = ['allow {0} pool={1} namespace={2}'.format(access_level, pool_name, namespace)
+ for access_level in access_levels]
+ else:
+ want_osd_caps = ['allow {0} pool={1}'.format(access_level, pool_name)
+ for access_level in access_levels]
+
+
+ try:
+ existing = self._rados_command(
+ 'auth get',
+ {
+ 'entity': client_entity
+ }
+ )
+
+ def cap_remove(orig_mds_caps, orig_osd_caps, want_mds_caps, want_osd_caps):
+ mds_cap_tokens = [x.strip() for x in orig_mds_caps.split(",")]
+ osd_cap_tokens = [x.strip() for x in orig_osd_caps.split(",")]
+
+ for want_mds_cap, want_osd_cap in zip(want_mds_caps, want_osd_caps):
+ if want_mds_cap in mds_cap_tokens:
+ mds_cap_tokens.remove(want_mds_cap)
+ osd_cap_tokens.remove(want_osd_cap)
+ break
+
+ return ",".join(mds_cap_tokens), ",".join(osd_cap_tokens)
+
+ cap = existing[0]
+ orig_mds_caps = cap['caps'].get('mds', "")
+ orig_osd_caps = cap['caps'].get('osd', "")
+ mds_cap_str, osd_cap_str = cap_remove(orig_mds_caps, orig_osd_caps,
+ want_mds_caps, want_osd_caps)
+
+ caps_list = self._prepare_updated_caps_list(cap, mds_cap_str, osd_cap_str, authorize=False)
+ if not caps_list:
+ self._rados_command('auth del', {'entity': client_entity}, decode=False)
+ else:
+ self._rados_command(
+ 'auth caps',
+ {
+ 'entity': client_entity,
+ 'caps': caps_list
+ })
+
+ # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
+ except rados.Error:
+ # Already gone, great.
+ return
+
+ def get_authorized_ids(self, volume_path):
+ """
+ Expose a list of auth IDs that have access to a volume.
+
+ return: a list of (auth_id, access_level) tuples, where
+ the access_level can be 'r' , or 'rw'.
+ None if no auth ID is given access to the volume.
+ """
+ with self._volume_lock(volume_path):
+ meta = self._volume_metadata_get(volume_path)
+ auths = []
+ if not meta or not meta['auths']:
+ return None
+
+ for auth, auth_data in meta['auths'].items():
+ # Skip partial auth updates.
+ if not auth_data['dirty']:
+ auths.append((auth, auth_data['access_level']))
+
+ return auths
+
+ def _rados_command(self, prefix, args=None, decode=True):
+ """
+ Safer wrapper for ceph_argparse.json_command, which raises
+ Error exception instead of relying on caller to check return
+ codes.
+
+ Error exception can result from:
+ * Timeout
+ * Actual legitimate errors
+ * Malformed JSON output
+
+ return: Decoded object from ceph, or None if empty string returned.
+ If decode is False, return a string (the data returned by
+ ceph command)
+ """
+ if args is None:
+ args = {}
+
+ argdict = args.copy()
+ argdict['format'] = 'json'
+
+ ret, outbuf, outs = json_command(self.rados,
+ prefix=prefix,
+ argdict=argdict,
+ timeout=RADOS_TIMEOUT)
+ if ret != 0:
+ raise rados.Error(outs)
+ else:
+ if decode:
+ if outbuf:
+ try:
+ return json.loads(outbuf.decode())
+ except (ValueError, TypeError):
+ raise RadosError("Invalid JSON output for command {0}".format(argdict))
+ else:
+ return None
+ else:
+ return outbuf
+
+ def get_used_bytes(self, volume_path):
+ return int(self.fs.getxattr(self._get_path(volume_path), "ceph.dir."
+ "rbytes").decode())
+
+ def set_max_bytes(self, volume_path, max_bytes):
+ self.fs.setxattr(self._get_path(volume_path), 'ceph.quota.max_bytes',
+ to_bytes(max_bytes if max_bytes else 0), 0)
+
+ def _snapshot_path(self, dir_path, snapshot_name):
+ return os.path.join(
+ dir_path, self.rados.conf_get('client_snapdir'), snapshot_name
+ )
+
+ def _snapshot_create(self, dir_path, snapshot_name, mode=0o755):
+ # TODO: raise intelligible exception for clusters where snaps are disabled
+ self.fs.mkdir(self._snapshot_path(dir_path, snapshot_name), mode)
+
+ def _snapshot_destroy(self, dir_path, snapshot_name):
+ """
+ Remove a snapshot, or do nothing if it already doesn't exist.
+ """
+ try:
+ self.fs.rmdir(self._snapshot_path(dir_path, snapshot_name))
+ except cephfs.ObjectNotFound:
+ log.warning("Snapshot was already gone: {0}".format(snapshot_name))
+
+ def create_snapshot_volume(self, volume_path, snapshot_name, mode=0o755):
+ self._snapshot_create(self._get_path(volume_path), snapshot_name, mode)
+
+ def destroy_snapshot_volume(self, volume_path, snapshot_name):
+ self._snapshot_destroy(self._get_path(volume_path), snapshot_name)
+
+ def create_snapshot_group(self, group_id, snapshot_name, mode=0o755):
+ if group_id is None:
+ raise RuntimeError("Group ID may not be None")
+
+ return self._snapshot_create(self._get_group_path(group_id), snapshot_name,
+ mode)
+
+ def destroy_snapshot_group(self, group_id, snapshot_name):
+ if group_id is None:
+ raise RuntimeError("Group ID may not be None")
+ if snapshot_name is None:
+ raise RuntimeError("Snapshot name may not be None")
+
+ return self._snapshot_destroy(self._get_group_path(group_id), snapshot_name)
+
+ def _cp_r(self, src, dst):
+ # TODO
+ raise NotImplementedError()
+
+ def clone_volume_to_existing(self, dest_volume_path, src_volume_path, src_snapshot_name):
+ dest_fs_path = self._get_path(dest_volume_path)
+ src_snapshot_path = self._snapshot_path(self._get_path(src_volume_path), src_snapshot_name)
+
+ self._cp_r(src_snapshot_path, dest_fs_path)
+
+ def put_object(self, pool_name, object_name, data):
+ """
+ Synchronously write data to an object.
+
+ :param pool_name: name of the pool
+ :type pool_name: str
+ :param object_name: name of the object
+ :type object_name: str
+ :param data: data to write
+ :type data: bytes
+ """
+ return self.put_object_versioned(pool_name, object_name, data)
+
+ def put_object_versioned(self, pool_name, object_name, data, version=None):
+ """
+ Synchronously write data to an object only if version of the object
+ version matches the expected version.
+
+ :param pool_name: name of the pool
+ :type pool_name: str
+ :param object_name: name of the object
+ :type object_name: str
+ :param data: data to write
+ :type data: bytes
+ :param version: expected version of the object to write
+ :type version: int
+ """
+ ioctx = self.rados.open_ioctx(pool_name)
+
+ max_size = int(self.rados.conf_get('osd_max_write_size')) * 1024 * 1024
+ if len(data) > max_size:
+ msg = ("Data to be written to object '{0}' exceeds "
+ "{1} bytes".format(object_name, max_size))
+ log.error(msg)
+ raise CephFSVolumeClientError(msg)
+
+ try:
+ with rados.WriteOpCtx() as wop:
+ if version is not None:
+ wop.assert_version(version)
+ wop.write_full(data)
+ ioctx.operate_write_op(wop, object_name)
+ except rados.OSError as e:
+ log.error(e)
+ raise e
+ finally:
+ ioctx.close()
+
+ def get_object(self, pool_name, object_name):
+ """
+ Synchronously read data from object.
+
+ :param pool_name: name of the pool
+ :type pool_name: str
+ :param object_name: name of the object
+ :type object_name: str
+
+ :returns: bytes - data read from object
+ """
+ return self.get_object_and_version(pool_name, object_name)[0]
+
+ def get_object_and_version(self, pool_name, object_name):
+ """
+ Synchronously read data from object and get its version.
+
+ :param pool_name: name of the pool
+ :type pool_name: str
+ :param object_name: name of the object
+ :type object_name: str
+
+ :returns: tuple of object data and version
+ """
+ ioctx = self.rados.open_ioctx(pool_name)
+ max_size = int(self.rados.conf_get('osd_max_write_size')) * 1024 * 1024
+ try:
+ bytes_read = ioctx.read(object_name, max_size)
+ if ((len(bytes_read) == max_size) and
+ (ioctx.read(object_name, 1, offset=max_size))):
+ log.warning("Size of object {0} exceeds '{1}' bytes "
+ "read".format(object_name, max_size))
+ obj_version = ioctx.get_last_version()
+ finally:
+ ioctx.close()
+ return (bytes_read, obj_version)
+
+ def delete_object(self, pool_name, object_name):
+ ioctx = self.rados.open_ioctx(pool_name)
+ try:
+ ioctx.remove_object(object_name)
+ except rados.ObjectNotFound:
+ log.warning("Object '{0}' was already removed".format(object_name))
+ finally:
+ ioctx.close()
diff --git a/src/pybind/cephfs/CMakeLists.txt b/src/pybind/cephfs/CMakeLists.txt
new file mode 100644
index 00000000..6d4a22b3
--- /dev/null
+++ b/src/pybind/cephfs/CMakeLists.txt
@@ -0,0 +1,3 @@
+distutils_add_cython_module(cython${PYTHON_VERSION}_cephfs ${CMAKE_CURRENT_SOURCE_DIR}/cephfs.pyx)
+add_dependencies(cython${PYTHON_VERSION}_cephfs cephfs)
+distutils_install_cython_module(cython${PYTHON_VERSION}_cephfs)
diff --git a/src/pybind/cephfs/MANIFEST.in b/src/pybind/cephfs/MANIFEST.in
new file mode 100644
index 00000000..abd9275e
--- /dev/null
+++ b/src/pybind/cephfs/MANIFEST.in
@@ -0,0 +1 @@
+include cephfs.pyx
diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx
new file mode 100644
index 00000000..9fcf187e
--- /dev/null
+++ b/src/pybind/cephfs/cephfs.pyx
@@ -0,0 +1,1691 @@
+"""
+This module is a thin wrapper around libcephfs.
+"""
+
+from cpython cimport PyObject, ref, exc
+from libc cimport errno
+from libc.stdint cimport *
+from libc.stdlib cimport malloc, realloc, free
+
+cimport rados
+
+from collections import namedtuple
+from datetime import datetime
+import errno
+import os
+import sys
+import time
+
+# Are we running Python 2.x
+if sys.version_info[0] < 3:
+ str_type = basestring
+else:
+ str_type = str
+
+AT_NO_ATTR_SYNC = 0x4000
+AT_SYMLINK_NOFOLLOW = 0x100
+cdef int AT_SYMLINK_NOFOLLOW_CDEF = AT_SYMLINK_NOFOLLOW
+CEPH_STATX_BASIC_STATS = 0x7ff
+cdef int CEPH_STATX_BASIC_STATS_CDEF = CEPH_STATX_BASIC_STATS
+CEPH_STATX_MODE = 0x1
+CEPH_STATX_NLINK = 0x2
+CEPH_STATX_UID = 0x4
+CEPH_STATX_GID = 0x8
+CEPH_STATX_RDEV = 0x10
+CEPH_STATX_ATIME = 0x20
+CEPH_STATX_MTIME = 0x40
+CEPH_STATX_CTIME = 0x80
+CEPH_STATX_INO = 0x100
+CEPH_STATX_SIZE = 0x200
+CEPH_STATX_BLOCKS = 0x400
+CEPH_STATX_BTIME = 0x800
+CEPH_STATX_VERSION = 0x1000
+
+cdef extern from "Python.h":
+ # These are in cpython/string.pxd, but use "object" types instead of
+ # PyObject*, which invokes assumptions in cpython that we need to
+ # legitimately break to implement zero-copy string buffers in Image.read().
+ # This is valid use of the Python API and documented as a special case.
+ PyObject *PyBytes_FromStringAndSize(char *v, Py_ssize_t len) except NULL
+ char* PyBytes_AsString(PyObject *string) except NULL
+ int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
+ void PyEval_InitThreads()
+
+
+cdef extern from "sys/statvfs.h":
+ cdef struct statvfs:
+ unsigned long int f_bsize
+ unsigned long int f_frsize
+ unsigned long int f_blocks
+ unsigned long int f_bfree
+ unsigned long int f_bavail
+ unsigned long int f_files
+ unsigned long int f_ffree
+ unsigned long int f_favail
+ unsigned long int f_fsid
+ unsigned long int f_flag
+ unsigned long int f_namemax
+ unsigned long int f_padding[32]
+
+
+IF UNAME_SYSNAME == "FreeBSD":
+ cdef extern from "dirent.h":
+ cdef struct dirent:
+ long int d_ino
+ unsigned short int d_reclen
+ unsigned char d_type
+ char d_name[256]
+ELSE:
+ cdef extern from "dirent.h":
+ cdef struct dirent:
+ long int d_ino
+ unsigned long int d_off
+ unsigned short int d_reclen
+ unsigned char d_type
+ char d_name[256]
+
+
+cdef extern from "time.h":
+ ctypedef long int time_t
+
+cdef extern from "time.h":
+ cdef struct timespec:
+ time_t tv_sec
+ long int tv_nsec
+
+cdef extern from "sys/types.h":
+ ctypedef unsigned long mode_t
+
+cdef extern from "<utime.h>":
+ cdef struct utimbuf:
+ time_t actime
+ time_t modtime
+
+cdef extern from "sys/time.h":
+ cdef struct timeval:
+ long tv_sec
+ long tv_usec
+
+cdef extern from "cephfs/ceph_ll_client.h":
+ cdef struct statx "ceph_statx":
+ uint32_t stx_mask
+ uint32_t stx_blksize
+ uint32_t stx_nlink
+ uint32_t stx_uid
+ uint32_t stx_gid
+ uint16_t stx_mode
+ uint64_t stx_ino
+ uint64_t stx_size
+ uint64_t stx_blocks
+ uint64_t stx_dev
+ uint64_t stx_rdev
+ timespec stx_atime
+ timespec stx_ctime
+ timespec stx_mtime
+ timespec stx_btime
+ uint64_t stx_version
+
+cdef extern from "cephfs/libcephfs.h" nogil:
+ cdef struct ceph_mount_info:
+ pass
+
+ cdef struct ceph_dir_result:
+ pass
+
+ ctypedef void* rados_t
+
+ const char *ceph_version(int *major, int *minor, int *patch)
+
+ int ceph_create(ceph_mount_info **cmount, const char * const id)
+ int ceph_create_from_rados(ceph_mount_info **cmount, rados_t cluster)
+ int ceph_init(ceph_mount_info *cmount)
+ void ceph_shutdown(ceph_mount_info *cmount)
+
+ int ceph_conf_read_file(ceph_mount_info *cmount, const char *path_list)
+ int ceph_conf_parse_argv(ceph_mount_info *cmount, int argc, const char **argv)
+ int ceph_conf_get(ceph_mount_info *cmount, const char *option, char *buf, size_t len)
+ int ceph_conf_set(ceph_mount_info *cmount, const char *option, const char *value)
+
+ int ceph_mount(ceph_mount_info *cmount, const char *root)
+ int ceph_select_filesystem(ceph_mount_info *cmount, const char *fs_name)
+ int ceph_unmount(ceph_mount_info *cmount)
+ int ceph_abort_conn(ceph_mount_info *cmount)
+ uint64_t ceph_get_instance_id(ceph_mount_info *cmount)
+ int ceph_fstatx(ceph_mount_info *cmount, int fd, statx *stx, unsigned want, unsigned flags)
+ int ceph_statx(ceph_mount_info *cmount, const char *path, statx *stx, unsigned want, unsigned flags)
+ int ceph_statfs(ceph_mount_info *cmount, const char *path, statvfs *stbuf)
+
+ int ceph_mds_command(ceph_mount_info *cmount, const char *mds_spec, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen, char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int ceph_rename(ceph_mount_info *cmount, const char *from_, const char *to)
+ int ceph_link(ceph_mount_info *cmount, const char *existing, const char *newname)
+ int ceph_unlink(ceph_mount_info *cmount, const char *path)
+ int ceph_symlink(ceph_mount_info *cmount, const char *existing, const char *newname)
+ int ceph_readlink(ceph_mount_info *cmount, const char *path, char *buf, int64_t size)
+ int ceph_setxattr(ceph_mount_info *cmount, const char *path, const char *name,
+ const void *value, size_t size, int flags)
+ int ceph_getxattr(ceph_mount_info *cmount, const char *path, const char *name,
+ void *value, size_t size)
+ int ceph_write(ceph_mount_info *cmount, int fd, const char *buf, int64_t size, int64_t offset)
+ int ceph_read(ceph_mount_info *cmount, int fd, char *buf, int64_t size, int64_t offset)
+ int ceph_flock(ceph_mount_info *cmount, int fd, int operation, uint64_t owner)
+ int ceph_close(ceph_mount_info *cmount, int fd)
+ int ceph_open(ceph_mount_info *cmount, const char *path, int flags, mode_t mode)
+ int ceph_mkdir(ceph_mount_info *cmount, const char *path, mode_t mode)
+ int ceph_mkdirs(ceph_mount_info *cmount, const char *path, mode_t mode)
+ int ceph_closedir(ceph_mount_info *cmount, ceph_dir_result *dirp)
+ int ceph_opendir(ceph_mount_info *cmount, const char *name, ceph_dir_result **dirpp)
+ void ceph_rewinddir(ceph_mount_info *cmount, ceph_dir_result *dirp)
+ int ceph_chdir(ceph_mount_info *cmount, const char *path)
+ dirent * ceph_readdir(ceph_mount_info *cmount, ceph_dir_result *dirp)
+ int ceph_rmdir(ceph_mount_info *cmount, const char *path)
+ const char* ceph_getcwd(ceph_mount_info *cmount)
+ int ceph_sync_fs(ceph_mount_info *cmount)
+ int ceph_fsync(ceph_mount_info *cmount, int fd, int syncdataonly)
+ int ceph_conf_parse_argv(ceph_mount_info *cmount, int argc, const char **argv)
+ int ceph_chmod(ceph_mount_info *cmount, const char *path, mode_t mode)
+ int ceph_chown(ceph_mount_info *cmount, const char *path, int uid, int gid)
+ int ceph_lchown(ceph_mount_info *cmount, const char *path, int uid, int gid)
+ int64_t ceph_lseek(ceph_mount_info *cmount, int fd, int64_t offset, int whence)
+ void ceph_buffer_free(char *buf)
+ mode_t ceph_umask(ceph_mount_info *cmount, mode_t mode)
+ int ceph_utime(ceph_mount_info *cmount, const char *path, utimbuf *buf)
+ int ceph_futime(ceph_mount_info *cmount, int fd, utimbuf *buf)
+ int ceph_utimes(ceph_mount_info *cmount, const char *path, timeval times[2])
+ int ceph_lutimes(ceph_mount_info *cmount, const char *path, timeval times[2])
+ int ceph_futimes(ceph_mount_info *cmount, int fd, timeval times[2])
+ int ceph_futimens(ceph_mount_info *cmount, int fd, timespec times[2])
+
+
+class Error(Exception):
+ pass
+
+
+class OSError(Error):
+ def __init__(self, errno, strerror):
+ super(OSError, self).__init__(errno, strerror)
+ self.errno = errno
+ self.strerror = strerror
+
+ def __str__(self):
+ return '{0}: {1} [Errno {2}]'.format(self.strerror, os.strerror(self.errno), self.errno)
+
+
+class PermissionError(OSError):
+ pass
+
+
+class ObjectNotFound(OSError):
+ pass
+
+
+class NoData(OSError):
+ pass
+
+
+class ObjectExists(OSError):
+ pass
+
+
+class IOError(OSError):
+ pass
+
+
+class NoSpace(OSError):
+ pass
+
+
+class InvalidValue(OSError):
+ pass
+
+
+class OperationNotSupported(OSError):
+ pass
+
+
+class LibCephFSStateError(Error):
+ pass
+
+
+class WouldBlock(OSError):
+ pass
+
+
+class OutOfRange(OSError):
+ pass
+
+
+class ObjectNotEmpty(OSError):
+ pass
+
+
+class DiskQuotaExceeded(OSError):
+ pass
+
+
+IF UNAME_SYSNAME == "FreeBSD":
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.ENOATTR : NoData,
+ errno.EINVAL : InvalidValue,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ errno.ERANGE : OutOfRange,
+ errno.EWOULDBLOCK: WouldBlock,
+ errno.ENOTEMPTY : ObjectNotEmpty,
+ errno.EDQUOT : DiskQuotaExceeded,
+ }
+ELSE:
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.ENODATA : NoData,
+ errno.EINVAL : InvalidValue,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ errno.ERANGE : OutOfRange,
+ errno.EWOULDBLOCK: WouldBlock,
+ errno.ENOTEMPTY : ObjectNotEmpty,
+ errno.EDQUOT : DiskQuotaExceeded,
+ }
+
+
+cdef make_ex(ret, msg):
+ """
+ Translate a libcephfs return code into an exception.
+
+ :param ret: the return code
+ :type ret: int
+ :param msg: the error message to use
+ :type msg: str
+ :returns: a subclass of :class:`Error`
+ """
+ ret = abs(ret)
+ if ret in errno_to_exception:
+ return errno_to_exception[ret](ret, msg)
+ else:
+ return OSError(ret, msg)
+
+
+class DirEntry(namedtuple('DirEntry',
+ ['d_ino', 'd_off', 'd_reclen', 'd_type', 'd_name'])):
+ DT_DIR = 0x4
+ DT_REG = 0xA
+ DT_LNK = 0xC
+ def is_dir(self):
+ return self.d_type == self.DT_DIR
+
+ def is_symbol_file(self):
+ return self.d_type == self.DT_LNK
+
+ def is_file(self):
+ return self.d_type == self.DT_REG
+
+StatResult = namedtuple('StatResult',
+ ["st_dev", "st_ino", "st_mode", "st_nlink", "st_uid",
+ "st_gid", "st_rdev", "st_size", "st_blksize",
+ "st_blocks", "st_atime", "st_mtime", "st_ctime"])
+
+cdef class DirResult(object):
+ cdef LibCephFS lib
+ cdef ceph_dir_result* handle
+
+# Bug in older Cython instances prevents this from being a static method.
+# @staticmethod
+# cdef create(LibCephFS lib, ceph_dir_result* handle):
+# d = DirResult()
+# d.lib = lib
+# d.handle = handle
+# return d
+
+ def __dealloc__(self):
+ self.close()
+
+ def __enter__(self):
+ if not self.handle:
+ raise make_ex(errno.EBADF, "dir is not open")
+ self.lib.require_state("mounted")
+ with nogil:
+ ceph_rewinddir(self.lib.cluster, self.handle)
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ self.close()
+ return False
+
+ def readdir(self):
+ self.lib.require_state("mounted")
+
+ with nogil:
+ dirent = ceph_readdir(self.lib.cluster, self.handle)
+ if not dirent:
+ return None
+
+ IF UNAME_SYSNAME == "FreeBSD":
+ return DirEntry(d_ino=dirent.d_ino,
+ d_off=0,
+ d_reclen=dirent.d_reclen,
+ d_type=dirent.d_type,
+ d_name=dirent.d_name)
+ ELSE:
+ return DirEntry(d_ino=dirent.d_ino,
+ d_off=dirent.d_off,
+ d_reclen=dirent.d_reclen,
+ d_type=dirent.d_type,
+ d_name=dirent.d_name)
+
+ def close(self):
+ if self.handle:
+ self.lib.require_state("mounted")
+ with nogil:
+ ret = ceph_closedir(self.lib.cluster, self.handle)
+ if ret < 0:
+ raise make_ex(ret, "closedir failed")
+ self.handle = NULL
+
+def cstr(val, name, encoding="utf-8", opt=False):
+ """
+ Create a byte string from a Python string
+
+ :param basestring val: Python string
+ :param str name: Name of the string parameter, for exceptions
+ :param str encoding: Encoding to use
+ :param bool opt: If True, None is allowed
+ :rtype: bytes
+ :raises: :class:`InvalidArgument`
+ """
+ if opt and val is None:
+ return None
+ if isinstance(val, bytes):
+ return val
+ else:
+ try:
+ v = val.encode(encoding)
+ except:
+ raise TypeError('%s must be encodeable as a bytearray' % name)
+ assert isinstance(v, bytes)
+ return v
+
+def cstr_list(list_str, name, encoding="utf-8"):
+ return [cstr(s, name) for s in list_str]
+
+
+def decode_cstr(val, encoding="utf-8"):
+ """
+ Decode a byte string into a Python string.
+
+ :param bytes val: byte string
+ :rtype: unicode or None
+ """
+ if val is None:
+ return None
+
+ return val.decode(encoding)
+
+cdef timeval to_timeval(t):
+ """
+ return timeval equivalent from time
+ """
+ tt = int(t)
+ cdef timeval buf = timeval(tt, (t - tt) * 1000000)
+ return buf
+
+cdef timespec to_timespec(t):
+ """
+ return timespec equivalent from time
+ """
+ tt = int(t)
+ cdef timespec buf = timespec(tt, (t - tt) * 1000000000)
+ return buf
+
+cdef char* opt_str(s) except? NULL:
+ if s is None:
+ return NULL
+ return s
+
+
+cdef char ** to_bytes_array(list_bytes):
+ cdef char **ret = <char **>malloc(len(list_bytes) * sizeof(char *))
+ if ret == NULL:
+ raise MemoryError("malloc failed")
+ for i in range(len(list_bytes)):
+ ret[i] = <char *>list_bytes[i]
+ return ret
+
+
+cdef void* realloc_chk(void* ptr, size_t size) except NULL:
+ cdef void *ret = realloc(ptr, size)
+ if ret == NULL:
+ raise MemoryError("realloc failed")
+ return ret
+
+
+cdef class LibCephFS(object):
+ """libcephfs python wrapper"""
+
+ cdef public object state
+ cdef ceph_mount_info *cluster
+
+ def require_state(self, *args):
+ if self.state in args:
+ return
+ raise LibCephFSStateError("You cannot perform that operation on a "
+ "CephFS object in state %s." % (self.state))
+
+ def __cinit__(self, conf=None, conffile=None, auth_id=None, rados_inst=None):
+ """Create a libcephfs wrapper
+
+ :param conf dict opt: settings overriding the default ones and conffile
+ :param conffile str opt: the path to ceph.conf to override the default settings
+ :auth_id str opt: the id used to authenticate the client entity
+ :rados_inst Rados opt: a rados.Rados instance
+ """
+ PyEval_InitThreads()
+ self.state = "uninitialized"
+ if rados_inst is not None:
+ if auth_id is not None or conffile is not None or conf is not None:
+ raise make_ex(errno.EINVAL,
+ "May not pass RADOS instance as well as other configuration")
+
+ self.create_with_rados(rados_inst)
+ else:
+ self.create(conf, conffile, auth_id)
+
+ def create_with_rados(self, rados.Rados rados_inst):
+ cdef int ret
+ with nogil:
+ ret = ceph_create_from_rados(&self.cluster, rados_inst.cluster)
+ if ret != 0:
+ raise Error("libcephfs_initialize failed with error code: %d" % ret)
+ self.state = "configuring"
+
+ NO_CONF_FILE = -1
+ "special value that indicates no conffile should be read when creating a mount handle"
+ DEFAULT_CONF_FILES = -2
+ "special value that indicates the default conffiles should be read when creating a mount handle"
+
+ def create(self, conf=None, conffile=NO_CONF_FILE, auth_id=None):
+ """
+ Create a mount handle for interacting with Ceph. All libcephfs
+ functions operate on a mount info handle.
+
+ :param conf dict opt: settings overriding the default ones and conffile
+ :param conffile Union[int,str], optional: the path to ceph.conf to override the default settings
+ :auth_id str opt: the id used to authenticate the client entity
+ """
+ if conf is not None and not isinstance(conf, dict):
+ raise TypeError("conf must be dict or None")
+ cstr(conffile, 'configfile', opt=True)
+ auth_id = cstr(auth_id, 'auth_id', opt=True)
+
+ cdef:
+ char* _auth_id = opt_str(auth_id)
+ int ret
+
+ with nogil:
+ ret = ceph_create(&self.cluster, <const char*>_auth_id)
+ if ret != 0:
+ raise Error("libcephfs_initialize failed with error code: %d" % ret)
+
+ self.state = "configuring"
+ if conffile in (self.NO_CONF_FILE, None):
+ pass
+ elif conffile in (self.DEFAULT_CONF_FILES, ''):
+ self.conf_read_file(None)
+ else:
+ self.conf_read_file(conffile)
+ if conf is not None:
+ for key, value in conf.iteritems():
+ self.conf_set(key, value)
+
+ def conf_read_file(self, conffile=None):
+ """
+ Load the ceph configuration from the specified config file.
+
+ :param conffile str opt: the path to ceph.conf to override the default settings
+ """
+ conffile = cstr(conffile, 'conffile', opt=True)
+ cdef:
+ char *_conffile = opt_str(conffile)
+ with nogil:
+ ret = ceph_conf_read_file(self.cluster, <const char*>_conffile)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_read_file")
+
+ def conf_parse_argv(self, argv):
+ """
+ Parse the command line arguments and load the configuration parameters.
+
+ :param argv: the argument list
+ """
+ self.require_state("configuring")
+ cargv = cstr_list(argv, 'argv')
+ cdef:
+ int _argc = len(argv)
+ char **_argv = to_bytes_array(cargv)
+
+ try:
+ with nogil:
+ ret = ceph_conf_parse_argv(self.cluster, _argc,
+ <const char **>_argv)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_parse_argv")
+ finally:
+ free(_argv)
+
+ def shutdown(self):
+ """
+ Unmount and destroy the ceph mount handle.
+ """
+ if self.state in ["initialized", "mounted"]:
+ with nogil:
+ ceph_shutdown(self.cluster)
+ self.state = "shutdown"
+
+ def __enter__(self):
+ self.mount()
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ self.shutdown()
+ return False
+
+ def __dealloc__(self):
+ self.shutdown()
+
+ def version(self):
+ """
+ Get the version number of the ``libcephfs`` C library.
+
+ :returns: a tuple of ``(major, minor, extra)`` components of the
+ libcephfs version
+ """
+ cdef:
+ int major = 0
+ int minor = 0
+ int extra = 0
+ with nogil:
+ ceph_version(&major, &minor, &extra)
+ return (major, minor, extra)
+
+ def conf_get(self, option):
+ """
+ Gets the configuration value as a string.
+
+ :param option: the config option to get
+ """
+ self.require_state("configuring", "initialized", "mounted")
+
+ option = cstr(option, 'option')
+ cdef:
+ char *_option = option
+ size_t length = 20
+ char *ret_buf = NULL
+
+ try:
+ while True:
+ ret_buf = <char *>realloc_chk(ret_buf, length)
+ with nogil:
+ ret = ceph_conf_get(self.cluster, _option, ret_buf, length)
+ if ret == 0:
+ return decode_cstr(ret_buf)
+ elif ret == -errno.ENAMETOOLONG:
+ length = length * 2
+ elif ret == -errno.ENOENT:
+ return None
+ else:
+ raise make_ex(ret, "error calling conf_get")
+ finally:
+ free(ret_buf)
+
+ def conf_set(self, option, val):
+ """
+ Sets a configuration value from a string.
+
+ :param option: the configuration option to set
+ :param value: the value of the configuration option to set
+ """
+ self.require_state("configuring", "initialized", "mounted")
+
+ option = cstr(option, 'option')
+ val = cstr(val, 'val')
+ cdef:
+ char *_option = option
+ char *_val = val
+
+ with nogil:
+ ret = ceph_conf_set(self.cluster, _option, _val)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_set")
+
+ def init(self):
+ """
+ Initialize the filesystem client (but do not mount the filesystem yet)
+ """
+ self.require_state("configuring")
+ with nogil:
+ ret = ceph_init(self.cluster)
+ if ret != 0:
+ raise make_ex(ret, "error calling ceph_init")
+ self.state = "initialized"
+
+ def mount(self, mount_root=None, filesystem_name=None):
+ """
+ Perform a mount using the path for the root of the mount.
+ """
+ if self.state == "configuring":
+ self.init()
+ self.require_state("initialized")
+
+ # Configure which filesystem to mount if one was specified
+ if filesystem_name is None:
+ filesystem_name = b""
+ cdef:
+ char *_filesystem_name = filesystem_name
+ if filesystem_name:
+ with nogil:
+ ret = ceph_select_filesystem(self.cluster,
+ _filesystem_name)
+ if ret != 0:
+ raise make_ex(ret, "error calling ceph_select_filesystem")
+
+ # Prepare mount_root argument, default to "/"
+ root = b"/" if mount_root is None else mount_root
+ cdef:
+ char *_mount_root = root
+
+ with nogil:
+ ret = ceph_mount(self.cluster, _mount_root)
+ if ret != 0:
+ raise make_ex(ret, "error calling ceph_mount")
+ self.state = "mounted"
+
+ def unmount(self):
+ """
+ Unmount a mount handle.
+ """
+ self.require_state("mounted")
+ with nogil:
+ ret = ceph_unmount(self.cluster)
+ if ret != 0:
+ raise make_ex(ret, "error calling ceph_unmount")
+ self.state = "initialized"
+
+ def abort_conn(self):
+ """
+ Abort mds connections.
+ """
+ self.require_state("mounted")
+ with nogil:
+ ret = ceph_abort_conn(self.cluster)
+ if ret != 0:
+ raise make_ex(ret, "error calling ceph_abort_conn")
+ self.state = "initialized"
+
+ def get_instance_id(self):
+ """
+ Get a global id for current instance
+ """
+ self.require_state("initialized", "mounted")
+ with nogil:
+ ret = ceph_get_instance_id(self.cluster)
+ return ret;
+
+ def statfs(self, path):
+ """
+ Perform a statfs on the ceph file system. This call fills in file system wide statistics
+ into the passed in buffer.
+
+ :param path: any path within the mounted filesystem
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ cdef:
+ char* _path = path
+ statvfs statbuf
+
+ with nogil:
+ ret = ceph_statfs(self.cluster, _path, &statbuf)
+ if ret < 0:
+ raise make_ex(ret, "statfs failed: %s" % path)
+ return {'f_bsize': statbuf.f_bsize,
+ 'f_frsize': statbuf.f_frsize,
+ 'f_blocks': statbuf.f_blocks,
+ 'f_bfree': statbuf.f_bfree,
+ 'f_bavail': statbuf.f_bavail,
+ 'f_files': statbuf.f_files,
+ 'f_ffree': statbuf.f_ffree,
+ 'f_favail': statbuf.f_favail,
+ 'f_fsid': statbuf.f_fsid,
+ 'f_flag': statbuf.f_flag,
+ 'f_namemax': statbuf.f_namemax}
+
+ def sync_fs(self):
+ """
+ Synchronize all filesystem data to persistent media
+ """
+ self.require_state("mounted")
+ with nogil:
+ ret = ceph_sync_fs(self.cluster)
+ if ret < 0:
+ raise make_ex(ret, "sync_fs failed")
+
+ def fsync(self, int fd, int syncdataonly):
+ """
+ Synchronize an open file to persistent media.
+
+ :param fd: the file descriptor of the file to sync.
+ :param syncdataonly: a boolean whether to synchronize metadata and data (0)
+ or just data (1).
+ """
+ self.require_state("mounted")
+ with nogil:
+ ret = ceph_fsync(self.cluster, fd, syncdataonly)
+ if ret < 0:
+ raise make_ex(ret, "fsync failed")
+
+ def getcwd(self):
+ """
+ Get the current working directory.
+
+ :rtype the path to the current working directory
+ """
+ self.require_state("mounted")
+ with nogil:
+ ret = ceph_getcwd(self.cluster)
+ return ret
+
+ def chdir(self, path):
+ """
+ Change the current working directory.
+
+ :param path the path to the working directory to change into.
+ """
+ self.require_state("mounted")
+
+ path = cstr(path, 'path')
+ cdef char* _path = path
+ with nogil:
+ ret = ceph_chdir(self.cluster, _path)
+ if ret < 0:
+ raise make_ex(ret, "chdir failed")
+
+ def opendir(self, path):
+ """
+ Open the given directory.
+
+ :param path: the path name of the directory to open. Must be either an absolute path
+ or a path relative to the current working directory.
+ :rtype handle: the open directory stream handle
+ """
+ self.require_state("mounted")
+
+ path = cstr(path, 'path')
+ cdef:
+ char* _path = path
+ ceph_dir_result* handle
+ with nogil:
+ ret = ceph_opendir(self.cluster, _path, &handle);
+ if ret < 0:
+ raise make_ex(ret, "opendir failed")
+ d = DirResult()
+ d.lib = self
+ d.handle = handle
+ return d
+
+ def readdir(self, DirResult handle):
+ """
+ Get the next entry in an open directory.
+
+ :param handle: the open directory stream handle
+ :rtype dentry: the next directory entry or None if at the end of the
+ directory (or the directory is empty. This pointer
+ should not be freed by the caller, and is only safe to
+ access between return and the next call to readdir or
+ closedir.
+ """
+ self.require_state("mounted")
+
+ return handle.readdir()
+
+ def closedir(self, DirResult handle):
+ """
+ Close the open directory.
+
+ :param handle: the open directory stream handle
+ """
+ self.require_state("mounted")
+
+ return handle.close()
+
+ def mkdir(self, path, mode):
+ """
+ Create a directory.
+
+ :param path: the path of the directory to create. This must be either an
+ absolute path or a relative path off of the current working directory.
+ :param mode the permissions the directory should have once created.
+ """
+
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if not isinstance(mode, int):
+ raise TypeError('mode must be an int')
+ cdef:
+ char* _path = path
+ int _mode = mode
+ with nogil:
+ ret = ceph_mkdir(self.cluster, _path, _mode)
+ if ret < 0:
+ raise make_ex(ret, "error in mkdir {}".format(path.decode('utf-8')))
+
+ def chmod(self, path, mode) :
+ """
+ Change directory mode.
+ :param path: the path of the directory to create. This must be either an
+ absolute path or a relative path off of the current working directory.
+ :param mode the permissions the directory should have once created.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if not isinstance(mode, int):
+ raise TypeError('mode must be an int')
+ cdef:
+ char* _path = path
+ int _mode = mode
+ with nogil:
+ ret = ceph_chmod(self.cluster, _path, _mode)
+ if ret < 0:
+ raise make_ex(ret, "error in chmod {}".format(path.decode('utf-8')))
+
+ def chown(self, path, uid, gid, follow_symlink=True):
+ """
+ Change directory ownership
+ :param path: the path of the directory to change.
+ :param uid: the uid to set
+ :param gid: the gid to set
+ :param follow_symlink: perform the operation on the target file if @path
+ is a symbolic link (default)
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if not isinstance(uid, int):
+ raise TypeError('uid must be an int')
+ elif not isinstance(gid, int):
+ raise TypeError('gid must be an int')
+
+ cdef:
+ char* _path = path
+ int _uid = uid
+ int _gid = gid
+ if follow_symlink:
+ with nogil:
+ ret = ceph_chown(self.cluster, _path, _uid, _gid)
+ else:
+ with nogil:
+ ret = ceph_lchown(self.cluster, _path, _uid, _gid)
+ if ret < 0:
+ raise make_ex(ret, "error in chown {}".format(path.decode('utf-8')))
+
+ def lchown(self, path, uid, gid):
+ """
+ Change ownership of a symbolic link
+ :param path: the path of the symbolic link to change.
+ :param uid: the uid to set
+ :param gid: the gid to set
+ """
+ self.chown(path, uid, gid, follow_symlink=False)
+
+ def mkdirs(self, path, mode):
+ """
+ Create multiple directories at once.
+
+ :param path: the full path of directories and sub-directories that should
+ be created.
+ :param mode the permissions the directory should have once created
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if not isinstance(mode, int):
+ raise TypeError('mode must be an int')
+ cdef:
+ char* _path = path
+ int _mode = mode
+
+ with nogil:
+ ret = ceph_mkdirs(self.cluster, _path, _mode)
+ if ret < 0:
+ raise make_ex(ret, "error in mkdirs {}".format(path.decode('utf-8')))
+
+ def rmdir(self, path):
+ """
+ Remove a directory.
+
+ :param path: the path of the directory to remove.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ cdef char* _path = path
+ ret = ceph_rmdir(self.cluster, _path)
+ if ret < 0:
+ raise make_ex(ret, "error in rmdir {}".format(path.decode('utf-8')))
+
+ def open(self, path, flags, mode=0):
+ """
+ Create and/or open a file.
+
+ :param path: the path of the file to open. If the flags parameter includes O_CREAT,
+ the file will first be created before opening.
+ :param flags: set of option masks that control how the file is created/opened.
+ :param mode: the permissions to place on the file if the file does not exist and O_CREAT
+ is specified in the flags.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+
+ if not isinstance(mode, int):
+ raise TypeError('mode must be an int')
+ if isinstance(flags, str):
+ cephfs_flags = 0
+ if flags == '':
+ cephfs_flags = os.O_RDONLY
+ else:
+ access_flags = 0;
+ for c in flags:
+ if c == 'r':
+ access_flags = 1;
+ elif c == 'w':
+ access_flags = 2;
+ cephfs_flags |= os.O_TRUNC | os.O_CREAT
+ elif access_flags > 0 and c == '+':
+ access_flags = 3;
+ else:
+ raise make_ex(errno.EOPNOTSUPP,
+ "open flags doesn't support %s" % c)
+
+ if access_flags == 1:
+ cephfs_flags |= os.O_RDONLY;
+ elif access_flags == 2:
+ cephfs_flags |= os.O_WRONLY;
+ else:
+ cephfs_flags |= os.O_RDWR;
+
+ elif isinstance(flags, int):
+ cephfs_flags = flags
+ else:
+ raise TypeError("flags must be a string or an integer")
+
+ cdef:
+ char* _path = path
+ int _flags = cephfs_flags
+ int _mode = mode
+
+ with nogil:
+ ret = ceph_open(self.cluster, _path, _flags, _mode)
+ if ret < 0:
+ raise make_ex(ret, "error in open {}".format(path.decode('utf-8')))
+ return ret
+
+ def close(self, fd):
+ """
+ Close the open file.
+
+ :param fd: the file descriptor referring to the open file.
+ """
+
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ cdef int _fd = fd
+ with nogil:
+ ret = ceph_close(self.cluster, _fd)
+ if ret < 0:
+ raise make_ex(ret, "error in close")
+
+ def read(self, fd, offset, l):
+ """
+ Read data from the file.
+
+ :param fd : the file descriptor of the open file to read from.
+ :param offset : the offset in the file to read from. If this value is negative, the
+ function reads from the current offset of the file descriptor.
+ :param l : the flag to indicate what type of seeking to perform
+ """
+ self.require_state("mounted")
+ if not isinstance(offset, int):
+ raise TypeError('offset must be an int')
+ if not isinstance(l, int):
+ raise TypeError('l must be an int')
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ cdef:
+ int _fd = fd
+ int64_t _offset = offset
+ int64_t _length = l
+
+ char *ret_buf
+ PyObject* ret_s = NULL
+
+ ret_s = PyBytes_FromStringAndSize(NULL, _length)
+ try:
+ ret_buf = PyBytes_AsString(ret_s)
+ with nogil:
+ ret = ceph_read(self.cluster, _fd, ret_buf, _length, _offset)
+ if ret < 0:
+ raise make_ex(ret, "error in read")
+
+ if ret != _length:
+ _PyBytes_Resize(&ret_s, ret)
+
+ return <object>ret_s
+ finally:
+ # We DECREF unconditionally: the cast to object above will have
+ # INCREFed if necessary. This also takes care of exceptions,
+ # including if _PyString_Resize fails (that will free the string
+ # itself and set ret_s to NULL, hence XDECREF).
+ ref.Py_XDECREF(ret_s)
+
+ def write(self, fd, buf, offset):
+ """
+ Write data to a file.
+
+ :param fd : the file descriptor of the open file to write to
+ :param buf : the bytes to write to the file
+ :param offset : the offset of the file write into. If this value is negative, the
+ function writes to the current offset of the file descriptor.
+ """
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if not isinstance(buf, bytes):
+ raise TypeError('buf must be a bytes')
+ if not isinstance(offset, int):
+ raise TypeError('offset must be an int')
+
+ cdef:
+ int _fd = fd
+ char *_data = buf
+ int64_t _offset = offset
+
+ size_t length = len(buf)
+
+ with nogil:
+ ret = ceph_write(self.cluster, _fd, _data, length, _offset)
+ if ret < 0:
+ raise make_ex(ret, "error in write")
+ return ret
+
+ def flock(self, fd, operation, owner):
+ """
+ Apply or remove an advisory lock.
+
+ :param fd: the open file descriptor to change advisory lock.
+ :param operation: the advisory lock operation to be performed on the file
+ :param owner: the user-supplied owner identifier (an arbitrary integer)
+ """
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if not isinstance(operation, int):
+ raise TypeError('operation must be an int')
+
+ cdef:
+ int _fd = fd
+ int _op = operation
+ uint64_t _owner = owner
+
+ with nogil:
+ ret = ceph_flock(self.cluster, _fd, _op, _owner)
+ if ret < 0:
+ raise make_ex(ret, "error in write")
+ return ret
+
+ def getxattr(self, path, name, size=255):
+ """
+ Get an extended attribute.
+
+ :param path: the path to the file
+ :param name: the name of the extended attribute to get
+ :param size: the size of the pre-allocated buffer
+ """
+ self.require_state("mounted")
+
+ path = cstr(path, 'path')
+ name = cstr(name, 'name')
+
+ cdef:
+ char* _path = path
+ char* _name = name
+
+ size_t ret_length = size
+ char *ret_buf = NULL
+
+ try:
+ ret_buf = <char *>realloc_chk(ret_buf, ret_length)
+ with nogil:
+ ret = ceph_getxattr(self.cluster, _path, _name, ret_buf,
+ ret_length)
+
+ if ret < 0:
+ raise make_ex(ret, "error in getxattr")
+
+ return ret_buf[:ret]
+ finally:
+ free(ret_buf)
+
+ def setxattr(self, path, name, value, flags):
+ """
+ Set an extended attribute on a file.
+
+ :param path: the path to the file.
+ :param name: the name of the extended attribute to set.
+ :param value: the bytes of the extended attribute value
+ """
+ self.require_state("mounted")
+
+ name = cstr(name, 'name')
+ path = cstr(path, 'path')
+ if not isinstance(flags, int):
+ raise TypeError('flags must be a int')
+ if not isinstance(value, bytes):
+ raise TypeError('value must be a bytes')
+
+ cdef:
+ char *_path = path
+ char *_name = name
+ char *_value = value
+ size_t _value_len = len(value)
+ int _flags = flags
+
+ with nogil:
+ ret = ceph_setxattr(self.cluster, _path, _name,
+ _value, _value_len, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in setxattr")
+
+
+ def stat(self, path, follow_symlink=True):
+ """
+ Get a file's extended statistics and attributes.
+
+ :param path: the file or directory to get the statistics of.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+
+ cdef:
+ char* _path = path
+ statx stx
+
+ if follow_symlink:
+ with nogil:
+ ret = ceph_statx(self.cluster, _path, &stx,
+ CEPH_STATX_BASIC_STATS_CDEF, 0)
+ else:
+ with nogil:
+ ret = ceph_statx(self.cluster, _path, &stx,
+ CEPH_STATX_BASIC_STATS_CDEF, AT_SYMLINK_NOFOLLOW_CDEF)
+
+ if ret < 0:
+ raise make_ex(ret, "error in stat: {}".format(path.decode('utf-8')))
+ return StatResult(st_dev=stx.stx_dev, st_ino=stx.stx_ino,
+ st_mode=stx.stx_mode, st_nlink=stx.stx_nlink,
+ st_uid=stx.stx_uid, st_gid=stx.stx_gid,
+ st_rdev=stx.stx_rdev, st_size=stx.stx_size,
+ st_blksize=stx.stx_blksize,
+ st_blocks=stx.stx_blocks,
+ st_atime=datetime.fromtimestamp(stx.stx_atime.tv_sec),
+ st_mtime=datetime.fromtimestamp(stx.stx_mtime.tv_sec),
+ st_ctime=datetime.fromtimestamp(stx.stx_ctime.tv_sec))
+
+ def lstat(self, path):
+ """
+ Get a file's extended statistics and attributes. When file's a
+ symbolic link, return the informaion of the link itself rather
+ than that of the file it points too.
+
+ :param path: the file or directory to get the statistics of.
+ """
+ return self.stat(path, follow_symlink=False)
+
+ def fstat(self, fd):
+ """
+ Get an open file's extended statistics and attributes.
+
+ :param fd: the file descriptor of the file to get statistics of.
+ """
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+
+ cdef:
+ int _fd = fd
+ statx stx
+
+ with nogil:
+ ret = ceph_fstatx(self.cluster, _fd, &stx,
+ CEPH_STATX_BASIC_STATS_CDEF, 0)
+ if ret < 0:
+ raise make_ex(ret, "error in fsat")
+ return StatResult(st_dev=stx.stx_dev, st_ino=stx.stx_ino,
+ st_mode=stx.stx_mode, st_nlink=stx.stx_nlink,
+ st_uid=stx.stx_uid, st_gid=stx.stx_gid,
+ st_rdev=stx.stx_rdev, st_size=stx.stx_size,
+ st_blksize=stx.stx_blksize,
+ st_blocks=stx.stx_blocks,
+ st_atime=datetime.fromtimestamp(stx.stx_atime.tv_sec),
+ st_mtime=datetime.fromtimestamp(stx.stx_mtime.tv_sec),
+ st_ctime=datetime.fromtimestamp(stx.stx_ctime.tv_sec))
+
+ def statx(self, path, mask, flag):
+ """
+ Get a file's extended statistics and attributes.
+
+ :param path: the file or directory to get the statistics of.
+ :param mask: want bitfield of CEPH_STATX_* flags showing designed attributes.
+ :param flag: bitfield that can be used to set AT_* modifier flags (only AT_NO_ATTR_SYNC and AT_SYMLINK_NOFOLLOW)
+ """
+
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if not isinstance(mask, int):
+ raise TypeError('flag must be a int')
+ if not isinstance(flag, int):
+ raise TypeError('flag must be a int')
+
+ cdef:
+ char* _path = path
+ statx stx
+ int _mask = mask
+ int _flag = flag
+ dict_result = dict()
+
+ with nogil:
+ ret = ceph_statx(self.cluster, _path, &stx, _mask, _flag)
+ if ret < 0:
+ raise make_ex(ret, "error in stat: %s" % path)
+
+ if (_mask & CEPH_STATX_MODE):
+ dict_result["mode"] = stx.stx_mode
+ if (_mask & CEPH_STATX_NLINK):
+ dict_result["nlink"] = stx.stx_nlink
+ if (_mask & CEPH_STATX_UID):
+ dict_result["uid"] = stx.stx_uid
+ if (_mask & CEPH_STATX_GID):
+ dict_result["gid"] = stx.stx_gid
+ if (_mask & CEPH_STATX_RDEV):
+ dict_result["rdev"] = stx.stx_rdev
+ if (_mask & CEPH_STATX_ATIME):
+ dict_result["atime"] = datetime.fromtimestamp(stx.stx_atime.tv_sec)
+ if (_mask & CEPH_STATX_MTIME):
+ dict_result["mtime"] = datetime.fromtimestamp(stx.stx_mtime.tv_sec)
+ if (_mask & CEPH_STATX_CTIME):
+ dict_result["ctime"] = datetime.fromtimestamp(stx.stx_ctime.tv_sec)
+ if (_mask & CEPH_STATX_INO):
+ dict_result["ino"] = stx.stx_ino
+ if (_mask & CEPH_STATX_SIZE):
+ dict_result["size"] = stx.stx_size
+ if (_mask & CEPH_STATX_BLOCKS):
+ dict_result["blocks"] = stx.stx_blocks
+ if (_mask & CEPH_STATX_BTIME):
+ dict_result["btime"] = datetime.fromtimestamp(stx.stx_btime.tv_sec)
+ if (_mask & CEPH_STATX_VERSION):
+ dict_result["version"] = stx.stx_version
+
+ return dict_result
+
+ def symlink(self, existing, newname):
+ """
+ Creates a symbolic link.
+
+ :param existing: the path to the existing file/directory to link to.
+ :param newname: the path to the new file/directory to link from.
+ """
+ self.require_state("mounted")
+ existing = cstr(existing, 'existing')
+ newname = cstr(newname, 'newname')
+ cdef:
+ char* _existing = existing
+ char* _newname = newname
+
+ with nogil:
+ ret = ceph_symlink(self.cluster, _existing, _newname)
+ if ret < 0:
+ raise make_ex(ret, "error in symlink")
+
+ def link(self, existing, newname):
+ """
+ Create a link.
+
+ :param existing: the path to the existing file/directory to link to.
+ :param newname: the path to the new file/directory to link from.
+ """
+
+ self.require_state("mounted")
+ existing = cstr(existing, 'existing')
+ newname = cstr(newname, 'newname')
+ cdef:
+ char* _existing = existing
+ char* _newname = newname
+
+ with nogil:
+ ret = ceph_link(self.cluster, _existing, _newname)
+ if ret < 0:
+ raise make_ex(ret, "error in link")
+
+ def readlink(self, path, size):
+ """
+ Read a symbolic link.
+
+ :param path: the path to the symlink to read
+ :param size: the length of the buffer
+ :rtype buf: buffer to hold the path of the file that the symlink points to.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+
+ cdef:
+ char* _path = path
+ int64_t _size = size
+ char *buf = NULL
+
+ try:
+ buf = <char *>realloc_chk(buf, _size)
+ with nogil:
+ ret = ceph_readlink(self.cluster, _path, buf, _size)
+ if ret < 0:
+ raise make_ex(ret, "error in readlink")
+ return buf[:ret]
+ finally:
+ free(buf)
+
+ def unlink(self, path):
+ """
+ Removes a file, link, or symbolic link. If the file/link has multiple links to it, the
+ file will not disappear from the namespace until all references to it are removed.
+
+ :param path: the path of the file or link to unlink.
+ """
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ cdef char* _path = path
+ with nogil:
+ ret = ceph_unlink(self.cluster, _path)
+ if ret < 0:
+ raise make_ex(ret, "error in unlink: {}".format(path.decode('utf-8')))
+
+ def rename(self, src, dst):
+ """
+ Rename a file or directory.
+
+ :param src: the path to the existing file or directory.
+ :param dst: the new name of the file or directory.
+ """
+
+ self.require_state("mounted")
+
+ src = cstr(src, 'source')
+ dst = cstr(dst, 'destination')
+
+ cdef:
+ char* _src = src
+ char* _dst = dst
+
+ with nogil:
+ ret = ceph_rename(self.cluster, _src, _dst)
+ if ret < 0:
+ raise make_ex(ret, "error in rename {} to {}".format(src.decode(
+ 'utf-8'), dst.decode('utf-8')))
+
+ def mds_command(self, mds_spec, args, input_data):
+ """
+ :return 3-tuple of output status int, output status string, output data
+ """
+ mds_spec = cstr(mds_spec, 'mds_spec')
+ args = cstr_list(args, 'args')
+ input_data = cstr(input_data, 'input_data')
+
+ cdef:
+ char *_mds_spec = opt_str(mds_spec)
+ char **_cmd = to_bytes_array(args)
+ size_t _cmdlen = len(args)
+
+ char *_inbuf = input_data
+ size_t _inbuf_len = len(input_data)
+
+ char *_outbuf = NULL
+ size_t _outbuf_len = 0
+ char *_outs = NULL
+ size_t _outs_len = 0
+
+ try:
+ with nogil:
+ ret = ceph_mds_command(self.cluster, _mds_spec,
+ <const char **>_cmd, _cmdlen,
+ <const char*>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+ my_outs = decode_cstr(_outs[:_outs_len])
+ my_outbuf = _outbuf[:_outbuf_len]
+ if _outs_len:
+ ceph_buffer_free(_outs)
+ if _outbuf_len:
+ ceph_buffer_free(_outbuf)
+ return (ret, my_outbuf, my_outs)
+ finally:
+ free(_cmd)
+
+ def umask(self, mode) :
+ self.require_state("mounted")
+ cdef:
+ mode_t _mode = mode
+ with nogil:
+ ret = ceph_umask(self.cluster, _mode)
+ if ret < 0:
+ raise make_ex(ret, "error in umask")
+ return ret
+
+ def lseek(self, fd, offset, whence):
+ """
+ Set the file's current position.
+
+ :param fd : the file descriptor of the open file to read from.
+ :param offset : the offset in the file to read from. If this value is negative, the
+ function reads from the current offset of the file descriptor.
+ :param whence : the flag to indicate what type of seeking to performs:SEEK_SET, SEEK_CUR, SEEK_END
+ """
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if not isinstance(offset, int):
+ raise TypeError('offset must be an int')
+ if not isinstance(whence, int):
+ raise TypeError('whence must be an int')
+
+ cdef:
+ int _fd = fd
+ int64_t _offset = offset
+ int64_t _whence = whence
+
+ with nogil:
+ ret = ceph_lseek(self.cluster, _fd, _offset, _whence)
+
+ if ret < 0:
+ raise make_ex(ret, "error in lseek")
+
+ return ret
+
+ def utime(self, path, times=None):
+ """
+ Set access and modification time for path
+
+ :param path: file path for which timestamps have to be changed
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ """
+
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if times:
+ if not isinstance(times, tuple):
+ raise TypeError('times must be a tuple')
+ if not isinstance(times[0], int):
+ raise TypeError('atime must be an int')
+ if not isinstance(times[1], int):
+ raise TypeError('mtime must be an int')
+ actime = modtime = int(time.time())
+ if times:
+ actime = times[0]
+ modtime = times[1]
+
+ cdef:
+ char *pth = path
+ utimbuf buf = utimbuf(actime, modtime)
+ with nogil:
+ ret = ceph_utime(self.cluster, pth, &buf)
+ if ret < 0:
+ raise make_ex(ret, "error in utime {}".format(path.decode('utf-8')))
+
+ def futime(self, fd, times=None):
+ """
+ Set access and modification time for a file pointed by descriptor
+
+ :param fd: file descriptor of the open file
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ """
+
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if times:
+ if not isinstance(times, tuple):
+ raise TypeError('times must be a tuple')
+ if not isinstance(times[0], int):
+ raise TypeError('atime must be an int')
+ if not isinstance(times[1], int):
+ raise TypeError('mtime must be an int')
+ actime = modtime = int(time.time())
+ if times:
+ actime = times[0]
+ modtime = times[1]
+
+ cdef:
+ int _fd = fd
+ utimbuf buf = utimbuf(actime, modtime)
+ with nogil:
+ ret = ceph_futime(self.cluster, _fd, &buf)
+ if ret < 0:
+ raise make_ex(ret, "error in futime")
+
+ def utimes(self, path, times=None, follow_symlink=True):
+ """
+ Set access and modification time for path
+
+ :param path: file path for which timestamps have to be changed
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ :param follow_symlink: perform the operation on the target file if @path
+ is a symbolic link (default)
+ """
+
+ self.require_state("mounted")
+ path = cstr(path, 'path')
+ if times:
+ if not isinstance(times, tuple):
+ raise TypeError('times must be a tuple')
+ if not isinstance(times[0], (int, float)):
+ raise TypeError('atime must be an int or a float')
+ if not isinstance(times[1], (int, float)):
+ raise TypeError('mtime must be an int or a float')
+ actime = modtime = time.time()
+ if times:
+ actime = float(times[0])
+ modtime = float(times[1])
+
+ cdef:
+ char *pth = path
+ timeval *buf = [to_timeval(actime), to_timeval(modtime)]
+ if follow_symlink:
+ with nogil:
+ ret = ceph_utimes(self.cluster, pth, buf)
+ else:
+ with nogil:
+ ret = ceph_lutimes(self.cluster, pth, buf)
+ if ret < 0:
+ raise make_ex(ret, "error in utimes {}".format(path.decode('utf-8')))
+
+ def lutimes(self, path, times=None):
+ """
+ Set access and modification time for a file. If the file is a symbolic
+ link do not follow to the target.
+
+ :param path: file path for which timestamps have to be changed
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ """
+ self.utimes(path, times=times, follow_symlink=False)
+
+ def futimes(self, fd, times=None):
+ """
+ Set access and modification time for a file pointer by descriptor
+
+ :param fd: file descriptor of the open file
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ """
+
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if times:
+ if not isinstance(times, tuple):
+ raise TypeError('times must be a tuple')
+ if not isinstance(times[0], (int, float)):
+ raise TypeError('atime must be an int or a float')
+ if not isinstance(times[1], (int, float)):
+ raise TypeError('mtime must be an int or a float')
+ actime = modtime = time.time()
+ if times:
+ actime = float(times[0])
+ modtime = float(times[1])
+
+ cdef:
+ int _fd = fd
+ timeval *buf = [to_timeval(actime), to_timeval(modtime)]
+ with nogil:
+ ret = ceph_futimes(self.cluster, _fd, buf)
+ if ret < 0:
+ raise make_ex(ret, "error in futimes")
+
+ def futimens(self, fd, times=None):
+ """
+ Set access and modification time for a file pointer by descriptor
+
+ :param fd: file descriptor of the open file
+ :param times: if times is not None, it must be a tuple (atime, mtime)
+ """
+
+ self.require_state("mounted")
+ if not isinstance(fd, int):
+ raise TypeError('fd must be an int')
+ if times:
+ if not isinstance(times, tuple):
+ raise TypeError('times must be a tuple')
+ if not isinstance(times[0], (int, float)):
+ raise TypeError('atime must be an int or a float')
+ if not isinstance(times[1], (int, float)):
+ raise TypeError('mtime must be an int or a float')
+ actime = modtime = time.time()
+ if times:
+ actime = float(times[0])
+ modtime = float(times[1])
+
+ cdef:
+ int _fd = fd
+ timespec *buf = [to_timespec(actime), to_timespec(modtime)]
+ with nogil:
+ ret = ceph_futimens(self.cluster, _fd, buf)
+ if ret < 0:
+ raise make_ex(ret, "error in futimens")
diff --git a/src/pybind/cephfs/setup.py b/src/pybind/cephfs/setup.py
new file mode 100755
index 00000000..1f950055
--- /dev/null
+++ b/src/pybind/cephfs/setup.py
@@ -0,0 +1,224 @@
+from __future__ import print_function
+
+import os
+import pkgutil
+import shutil
+import subprocess
+import sys
+import tempfile
+import textwrap
+from distutils.ccompiler import new_compiler
+from distutils.errors import CompileError, LinkError
+import distutils.sysconfig
+
+unwrapped_customize = distutils.sysconfig.customize_compiler
+
+clang = False
+
+def filter_unsupported_flags(flags):
+ if clang:
+ return [f for f in flags if not (f == '-mcet' or
+ f.startswith('-fcf-protection'))]
+ else:
+ return flags
+
+def monkey_with_compiler(compiler):
+ unwrapped_customize(compiler)
+ if compiler.compiler_type == 'unix':
+ if compiler.compiler[0].find('clang') != -1:
+ global clang
+ clang = True
+ compiler.compiler = filter_unsupported_flags(compiler.compiler)
+ compiler.compiler_so = filter_unsupported_flags(
+ compiler.compiler_so)
+
+distutils.sysconfig.customize_compiler = monkey_with_compiler
+
+if not pkgutil.find_loader('setuptools'):
+ from distutils.core import setup
+ from distutils.extension import Extension
+else:
+ from setuptools import setup
+ from setuptools.extension import Extension
+
+# PEP 440 versioning of the Ceph FS package on PyPI
+# Bump this version, after every changeset
+
+__version__ = '2.0.0'
+
+
+def get_python_flags():
+ cflags = {'I': [], 'extras': []}
+ ldflags = {'l': [], 'L': [], 'extras': []}
+
+ if os.environ.get('VIRTUAL_ENV', None):
+ python = "python"
+ else:
+ python = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
+
+ python_config = python + '-config'
+
+ for cflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--cflags"]).strip().decode('utf-8').split()):
+ if cflag.startswith('-I'):
+ cflags['I'].append(cflag.replace('-I', ''))
+ else:
+ cflags['extras'].append(cflag)
+
+ for ldflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--ldflags"]).strip().decode('utf-8').split()):
+ if ldflag.startswith('-l'):
+ ldflags['l'].append(ldflag.replace('-l', ''))
+ if ldflag.startswith('-L'):
+ ldflags['L'].append(ldflag.replace('-L', ''))
+ else:
+ ldflags['extras'].append(ldflag)
+
+ return {
+ 'cflags': cflags,
+ 'ldflags': ldflags
+ }
+
+
+def check_sanity():
+ """
+ Test if development headers and library for cephfs is available by compiling a dummy C program.
+ """
+ CEPH_SRC_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..',
+ '..'
+ )
+
+ tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__)))
+ tmp_file = os.path.join(tmp_dir, 'cephfs_dummy.c')
+
+ with open(tmp_file, 'w') as fp:
+ dummy_prog = textwrap.dedent("""
+ #include <stddef.h>
+ #include "cephfs/libcephfs.h"
+
+ int main(void) {
+ struct ceph_mount_info *cmount = NULL;
+ ceph_init(cmount);
+ return 0;
+ }
+ """)
+ fp.write(dummy_prog)
+
+ compiler = new_compiler()
+ distutils.sysconfig.customize_compiler(compiler)
+
+ if {'MAKEFLAGS', 'MFLAGS', 'MAKELEVEL'}.issubset(set(os.environ.keys())):
+ # The setup.py has been invoked by a top-level Ceph make.
+ # Set the appropriate CFLAGS and LDFLAGS
+
+ compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')])
+
+ try:
+ compiler.define_macro('_FILE_OFFSET_BITS', '64')
+
+ link_objects = compiler.compile(
+ sources=[tmp_file],
+ output_dir=tmp_dir,
+ extra_preargs=['-iquote{path}'.format(path=os.path.join(CEPH_SRC_DIR, 'include'))]
+ )
+
+ compiler.link_executable(
+ objects=link_objects,
+ output_progname=os.path.join(tmp_dir, 'cephfs_dummy'),
+ libraries=['cephfs'],
+ output_dir=tmp_dir,
+ )
+
+ except CompileError:
+ print('\nCompile Error: Ceph FS development headers not found', file=sys.stderr)
+ return False
+ except LinkError:
+ print('\nLink Error: Ceph FS library not found', file=sys.stderr)
+ return False
+ else:
+ return True
+ finally:
+ shutil.rmtree(tmp_dir)
+
+
+if 'BUILD_DOC' in os.environ.keys():
+ pass
+elif check_sanity():
+ pass
+else:
+ sys.exit(1)
+
+cmdclass = {}
+try:
+ from Cython.Build import cythonize
+ from Cython.Distutils import build_ext
+
+ cmdclass = {'build_ext': build_ext}
+except ImportError:
+ print("WARNING: Cython is not installed.")
+
+ if not os.path.isfile('cephfs.c'):
+ print('ERROR: Cannot find Cythonized file cephfs.c', file=sys.stderr)
+ sys.exit(1)
+ else:
+ def cythonize(x, **kwargs):
+ return x
+
+ source = "cephfs.c"
+else:
+ source = "cephfs.pyx"
+
+# Disable cythonification if we're not really building anything
+if (len(sys.argv) >= 2 and
+ any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version')
+ )):
+ def cythonize(x, **kwargs):
+ return x
+
+flags = get_python_flags()
+
+setup(
+ name='cephfs',
+ version=__version__,
+ description="Python bindings for the Ceph FS library",
+ long_description=(
+ "This package contains Python bindings for interacting with the "
+ "Ceph Filesystem (Ceph FS) library. Ceph FS is a POSIX-compliant "
+ "filesystem that uses a Ceph Storage Cluster to store its data. The "
+ "Ceph filesystem uses the same Ceph Storage Cluster system as "
+ "Ceph Block Devices, Ceph Object Storage with its S3 and Swift APIs, "
+ "or native bindings (librados)."
+ ),
+ url='https://github.com/ceph/ceph/tree/master/src/pybind/cephfs',
+ license='LGPLv2+',
+ platforms='Linux',
+ ext_modules=cythonize(
+ [
+ Extension(
+ "cephfs",
+ [source],
+ include_dirs=flags['cflags']['I'],
+ library_dirs=flags['ldflags']['L'],
+ libraries=['cephfs'] + flags['ldflags']['l'],
+ extra_compile_args=flags['cflags']['extras'] + flags['ldflags']['extras'],
+ )
+ ],
+ build_dir=os.environ.get("CYTHON_BUILD_DIR", None),
+ include_path=[
+ os.path.join(os.path.dirname(__file__), "..", "rados")
+ ]
+ ),
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Cython',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5'
+ ],
+ cmdclass=cmdclass,
+)
diff --git a/src/pybind/mgr/.gitignore b/src/pybind/mgr/.gitignore
new file mode 100644
index 00000000..fcdcddd5
--- /dev/null
+++ b/src/pybind/mgr/.gitignore
@@ -0,0 +1 @@
+proxy.conf.json
diff --git a/src/pybind/mgr/CMakeLists.txt b/src/pybind/mgr/CMakeLists.txt
new file mode 100644
index 00000000..2b5f4a7d
--- /dev/null
+++ b/src/pybind/mgr/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_subdirectory(dashboard)
+add_subdirectory(insights)
+add_subdirectory(ansible)
+add_subdirectory(orchestrator_cli)
+
+# Location needs to match default setting for mgr_module_path, currently:
+# OPTION(mgr_module_path, OPT_STR, CEPH_PKGLIBDIR "/mgr")
+install(DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ DESTINATION ${CEPH_INSTALL_DATADIR}
+ REGEX "CMakeLists.txt" EXCLUDE
+ REGEX "\\.gitignore" EXCLUDE
+ REGEX "hello/.*" EXCLUDE
+ REGEX "osd_perf_query/.*" EXCLUDE)
diff --git a/src/pybind/mgr/alerts/__init__.py b/src/pybind/mgr/alerts/__init__.py
new file mode 100644
index 00000000..e4c185ca
--- /dev/null
+++ b/src/pybind/mgr/alerts/__init__.py
@@ -0,0 +1 @@
+from .module import Alerts
diff --git a/src/pybind/mgr/alerts/module.py b/src/pybind/mgr/alerts/module.py
new file mode 100644
index 00000000..d6cec4b6
--- /dev/null
+++ b/src/pybind/mgr/alerts/module.py
@@ -0,0 +1,259 @@
+
+"""
+A simple cluster health alerting module.
+"""
+
+from mgr_module import MgrModule, HandleCommandResult
+from threading import Event
+import errno
+import json
+import smtplib
+
+class Alerts(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "alerts send",
+ "desc": "(re)send alerts immediately",
+ "perm": "r"
+ },
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'interval',
+ 'type': 'secs',
+ 'default': 60,
+ 'desc': 'How frequently to reexamine health status',
+ 'runtime': True,
+ },
+ # smtp
+ {
+ 'name': 'smtp_host',
+ 'default': '',
+ 'desc': 'SMTP server',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_destination',
+ 'default': '',
+ 'desc': 'Email address to send alerts to',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_port',
+ 'type': 'int',
+ 'default': 465,
+ 'desc': 'SMTP port',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_ssl',
+ 'type': 'bool',
+ 'default': True,
+ 'desc': 'Use SSL to connect to SMTP server',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_user',
+ 'default': '',
+ 'desc': 'User to authenticate as',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_password',
+ 'default': '',
+ 'desc': 'Password to authenticate with',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_sender',
+ 'default': '',
+ 'desc': 'SMTP envelope sender',
+ 'runtime': True,
+ },
+ {
+ 'name': 'smtp_from_name',
+ 'default': 'Ceph',
+ 'desc': 'Email From: name',
+ 'runtime': True,
+ },
+ ]
+
+ # These are "native" Ceph options that this module cares about.
+ NATIVE_OPTIONS = [
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Alerts, self).__init__(*args, **kwargs)
+
+ # set up some members to enable the serve() method and shutdown()
+ self.run = True
+ self.event = Event()
+
+ # ensure config options members are initialized; see config_notify()
+ self.config_notify()
+
+ self.log.info("Init")
+
+
+ def config_notify(self):
+ """
+ This method is called whenever one of our config options is changed.
+ """
+ # This is some boilerplate that stores MODULE_OPTIONS in a class
+ # member, so that, for instance, the 'emphatic' option is always
+ # available as 'self.emphatic'.
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' mgr option %s = %s',
+ opt['name'], getattr(self, opt['name']))
+ # Do the same for the native options.
+ for opt in self.NATIVE_OPTIONS:
+ setattr(self,
+ opt,
+ self.get_ceph_option(opt))
+ self.log.debug(' native option %s = %s', opt, getattr(self, opt))
+
+ def handle_command(self, inbuf, cmd):
+ ret = 0
+ out = ''
+ err = ''
+ if cmd['prefix'] == 'alerts send':
+ status = json.loads(self.get('health')['json'])
+ self._send_alert(status, {})
+ return HandleCommandResult(
+ retval=ret, # exit code
+ stdout=out, # stdout
+ stderr=err)
+
+ def _diff(self, last, new):
+ d = {}
+ for code, alert in new.get('checks', {}).items():
+ self.log.debug('new code %s alert %s' % (code, alert))
+ if code not in last.get('checks', {}):
+ if 'new' not in d:
+ d['new'] = {}
+ d['new'][code] = alert
+ elif alert['summary'].get('count', 0) > \
+ last['checks'][code]['summary'].get('count', 0):
+ if 'updated' not in d:
+ d['updated'] = {}
+ d['updated'][code] = alert
+ for code, alert in last.get('checks', {}).items():
+ self.log.debug('old code %s alert %s' % (code, alert))
+ if code not in new.get('checks', {}):
+ if 'cleared' not in d:
+ d['cleared'] = {}
+ d['cleared'][code] = alert
+ return d
+
+ def _send_alert(self, status, diff):
+ checks = {}
+ if self.smtp_host:
+ r = self._send_alert_smtp(status, diff)
+ if r:
+ for code, alert in r.items():
+ checks[code] = alert
+ else:
+ self.log.warn('Alert is not sent because smtp_host is not configured')
+ self.set_health_checks(checks)
+
+ def serve(self):
+ """
+ This method is called by the mgr when the module starts and can be
+ used for any background activity.
+ """
+ self.log.info("Starting")
+ last_status = {}
+ while self.run:
+ # Do some useful background work here.
+ new_status = json.loads(self.get('health')['json'])
+ if new_status != last_status:
+ self.log.debug('last_status %s' % last_status)
+ self.log.debug('new_status %s' % new_status)
+ diff = self._diff(last_status,
+ new_status)
+ self.log.debug('diff %s' % diff)
+ if diff:
+ self._send_alert(new_status, diff)
+ last_status = new_status
+
+ self.log.debug('Sleeping for %d seconds', self.interval)
+ ret = self.event.wait(self.interval)
+ self.event.clear()
+
+ def shutdown(self):
+ """
+ This method is called by the mgr when the module needs to shut
+ down (i.e., when the serve() function needs to exit).
+ """
+ self.log.info('Stopping')
+ self.run = False
+ self.event.set()
+
+ # SMTP
+ def _smtp_format_alert(self, code, alert):
+ r = '[{sev}] {code}: {summary}\n'.format(
+ code=code,
+ sev=alert['severity'].split('_')[1],
+ summary=alert['summary']['message'])
+ for detail in alert['detail']:
+ r += ' {message}\n'.format(
+ message=detail['message'])
+ return r
+
+ def _send_alert_smtp(self, status, diff):
+ # message
+ self.log.debug('_send_alert_smtp')
+ message = ('From: {from_name} <{sender}>\n'
+ 'Subject: {status}\n'
+ 'To: {target}\n'
+ '\n'
+ '{status}\n'.format(
+ sender=self.smtp_sender,
+ from_name=self.smtp_from_name,
+ status=status['status'],
+ target=self.smtp_destination))
+
+ if 'new' in diff:
+ message += ('\n--- New ---\n')
+ for code, alert in diff['new'].items():
+ message += self._smtp_format_alert(code, alert)
+ if 'updated' in diff:
+ message += ('\n--- Updated ---\n')
+ for code, alert in diff['updated'].items():
+ message += self._smtp_format_alert(code, alert)
+ if 'cleared' in diff:
+ message += ('\n--- Cleared ---\n')
+ for code, alert in diff['cleared'].items():
+ message += self._smtp_format_alert(code, alert)
+
+ message += ('\n\n=== Full health status ===\n')
+ for code, alert in status['checks'].items():
+ message += self._smtp_format_alert(code, alert)
+
+ self.log.debug('message: %s' % message)
+
+ # send
+ try:
+ if self.smtp_ssl:
+ server = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port)
+ else:
+ server = smtplib.SMTP(self.smtp_host, self.smtp_port)
+ if self.smtp_password:
+ server.login(self.smtp_user, self.smtp_password)
+ server.sendmail(self.smtp_sender, self.smtp_destination, message)
+ server.quit()
+ except Exception as e:
+ return {
+ 'ALERTS_SMTP_ERROR': {
+ 'severity': 'warning',
+ 'summary': 'unable to send alert email',
+ 'count': 1,
+ 'detail': [ str(e) ]
+ }
+ }
+ self.log.debug('Sent email to %s' % self.smtp_destination)
+ return None
diff --git a/src/pybind/mgr/ansible/.gitignore b/src/pybind/mgr/ansible/.gitignore
new file mode 100644
index 00000000..43a2d269
--- /dev/null
+++ b/src/pybind/mgr/ansible/.gitignore
@@ -0,0 +1 @@
+wheelhouse*
diff --git a/src/pybind/mgr/ansible/CMakeLists.txt b/src/pybind/mgr/ansible/CMakeLists.txt
new file mode 100644
index 00000000..c706aa8c
--- /dev/null
+++ b/src/pybind/mgr/ansible/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(MGR_ANSIBLE_VIRTUALENV ${CEPH_BUILD_VIRTUALENV}/mgr-ansible-virtualenv)
+
+add_custom_target(mgr-ansible-test-venv
+ COMMAND ${CMAKE_SOURCE_DIR}/src/tools/setup-virtualenv.sh --python=${MGR_PYTHON_EXECUTABLE} ${MGR_ANSIBLE_VIRTUALENV}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/ansible
+ COMMENT "ansible tests virtualenv is being created")
+add_dependencies(tests mgr-ansible-test-venv)
diff --git a/src/pybind/mgr/ansible/__init__.py b/src/pybind/mgr/ansible/__init__.py
new file mode 100644
index 00000000..ea61a12f
--- /dev/null
+++ b/src/pybind/mgr/ansible/__init__.py
@@ -0,0 +1,9 @@
+from __future__ import absolute_import
+import os
+
+if 'UNITTEST' not in os.environ:
+ from .module import Module
+else:
+ import sys
+ import mock
+ sys.modules['ceph_module'] = mock.Mock()
diff --git a/src/pybind/mgr/ansible/ansible_runner_svc.py b/src/pybind/mgr/ansible/ansible_runner_svc.py
new file mode 100644
index 00000000..636e20b0
--- /dev/null
+++ b/src/pybind/mgr/ansible/ansible_runner_svc.py
@@ -0,0 +1,326 @@
+"""
+Client module to interact with the Ansible Runner Service
+"""
+import requests
+import json
+import re
+from functools import wraps
+
+# Ansible Runner service API endpoints
+API_URL = "api"
+LOGIN_URL = "api/v1/login"
+PLAYBOOK_EXEC_URL = "api/v1/playbooks"
+PLAYBOOK_EVENTS = "api/v1/jobs/%s/events"
+EVENT_DATA_URL = "api/v1/jobs/%s/events/%s"
+
+class AnsibleRunnerServiceError(Exception):
+ pass
+
+def handle_requests_exceptions(func):
+ """Decorator to manage errors raised by requests library
+ """
+ @wraps(func)
+ def inner(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except requests.exceptions.RequestException as ex:
+ raise AnsibleRunnerServiceError(str(ex))
+ return inner
+
+class ExecutionStatusCode(object):
+ """Execution status of playbooks ( 'msg' field in playbook status request)
+ """
+
+ SUCCESS = 0 # Playbook has been executed succesfully" msg = successful
+ ERROR = 1 # Playbook has finished with error msg = failed
+ ON_GOING = 2 # Playbook is being executed msg = running
+ NOT_LAUNCHED = 3 # Not initialized
+
+class PlayBookExecution(object):
+ """Object to provide all the results of a Playbook execution
+ """
+
+ def __init__(self, rest_client, playbook, logger, result_pattern="",
+ the_params=None,
+ querystr_dict=None):
+
+ self.rest_client = rest_client
+
+ # Identifier of the playbook execution
+ self.play_uuid = "-"
+
+ # Pattern used to extract the result from the events
+ self.result_task_pattern = result_pattern
+
+ # Playbook name
+ self.playbook = playbook
+
+ # Parameters used in the playbook
+ self.params = the_params
+
+ # Query string used in the "launch" request
+ self.querystr_dict = querystr_dict
+
+ # Logger
+ self.log = logger
+
+ def launch(self):
+ """ Launch the playbook execution
+ """
+
+ response = None
+ endpoint = "%s/%s" % (PLAYBOOK_EXEC_URL, self.playbook)
+
+ try:
+ response = self.rest_client.http_post(endpoint,
+ self.params,
+ self.querystr_dict)
+ except AnsibleRunnerServiceError:
+ self.log.exception("Error launching playbook <%s>", self.playbook)
+ raise
+
+ # Here we have a server response, but an error trying
+ # to launch the playbook is also posible (ex. 404, playbook not found)
+ # Error already logged by rest_client, but an error should be raised
+ # to the orchestrator (via completion object)
+ if response.ok:
+ self.play_uuid = json.loads(response.text)["data"]["play_uuid"]
+ self.log.info("Playbook execution launched succesfuly")
+ else:
+ raise AnsibleRunnerServiceError(response.reason)
+
+ def get_status(self):
+ """ Return the status of the execution
+
+ In the msg field of the respons we can find:
+ "msg": "successful"
+ "msg": "running"
+ "msg": "failed"
+ """
+
+ status_value = ExecutionStatusCode.NOT_LAUNCHED
+ response = None
+
+ if self.play_uuid == '-': # Initialized
+ status_value = ExecutionStatusCode.NOT_LAUNCHED
+ elif self.play_uuid == '': # Error launching playbook
+ status_value = ExecutionStatusCode.ERROR
+ else:
+ endpoint = "%s/%s" % (PLAYBOOK_EXEC_URL, self.play_uuid)
+
+ try:
+ response = self.rest_client.http_get(endpoint)
+ except AnsibleRunnerServiceError:
+ self.log.exception("Error getting playbook <%s> status",
+ self.playbook)
+
+ if response:
+ the_status = json.loads(response.text)["msg"]
+ if the_status == 'successful':
+ status_value = ExecutionStatusCode.SUCCESS
+ elif the_status == 'failed':
+ status_value = ExecutionStatusCode.ERROR
+ else:
+ status_value = ExecutionStatusCode.ON_GOING
+ else:
+ status_value = ExecutionStatusCode.ERROR
+
+ self.log.info("Requested playbook execution status is: %s", status_value)
+ return status_value
+
+ def get_result(self, event_filter=""):
+ """Get the data of the events filtered by a task pattern and
+ a event filter
+
+ @returns: the events that matches with the patterns provided
+ """
+ response = None
+ if not self.play_uuid:
+ return {}
+
+ try:
+ response = self.rest_client.http_get(PLAYBOOK_EVENTS % self.play_uuid)
+ except AnsibleRunnerServiceError:
+ self.log.exception("Error getting playbook <%s> result", self.playbook)
+
+ if not response:
+ result_events = {}
+ else:
+ events = json.loads(response.text)["data"]["events"]
+
+ if self.result_task_pattern:
+ result_events = {event:data for event,data in events.items()
+ if "task" in data and
+ re.match(self.result_task_pattern, data["task"])}
+ else:
+ result_events = events
+
+ if event_filter:
+ result_events = {event:data for event,data in result_events.items()
+ if re.match(event_filter, data['event'])}
+
+ self.log.info("Requested playbook result is: %s", json.dumps(result_events))
+ return result_events
+
+class Client(object):
+ """An utility object that allows to connect with the Ansible runner service
+ and execute easily playbooks
+ """
+
+ def __init__(self, server_url, user, password, verify_server, logger):
+ """Provide an https client to make easy interact with the Ansible
+ Runner Service"
+
+ :param servers_url: The base URL >server>:<port> of the Ansible Runner Service
+ :param user: Username of the authorized user
+ :param password: Password of the authorized user
+ :param verify_server: Either a boolean, in which case it controls whether we verify
+ the server's TLS certificate, or a string, in which case it must be a path
+ to a CA bundle to use. Defaults to ``True``.
+ :param logger: Log file
+ """
+ self.server_url = server_url
+ self.user = user
+ self.password = password
+ self.log = logger
+ self.auth = (self.user, self.password)
+ if not verify_server:
+ self.verify_server = True
+ elif verify_server.lower().strip() == 'false':
+ self.verify_server = False
+ else:
+ self.verify_server = verify_server
+
+ # Once authenticated this token will be used in all the requests
+ self.token = ""
+
+ self.server_url = "https://{0}".format(self.server_url)
+
+ # Log in the server and get a token
+ self.login()
+
+ @handle_requests_exceptions
+ def login(self):
+ """ Login with user credentials to obtain a valid token
+ """
+
+ the_url = "%s/%s" % (self.server_url, LOGIN_URL)
+ response = requests.get(the_url,
+ auth = self.auth,
+ verify = self.verify_server)
+
+ if response.status_code != requests.codes.ok:
+ self.log.error("login error <<%s>> (%s):%s",
+ the_url, response.status_code, response.text)
+ else:
+ self.log.info("login succesful <<%s>> (%s):%s",
+ the_url, response.status_code, response.text)
+
+ if response:
+ self.token = json.loads(response.text)["data"]["token"]
+ self.log.info("Connection with Ansible Runner Service is operative")
+
+ @handle_requests_exceptions
+ def is_operative(self):
+ """Indicates if the connection with the Ansible runner Server is ok
+ """
+
+ # No Token... this means we haven't used yet the service.
+ if not self.token:
+ return False
+
+ # Check the service
+ response = self.http_get(API_URL)
+
+ if response:
+ return response.status_code == requests.codes.ok
+ else:
+ return False
+
+ @handle_requests_exceptions
+ def http_get(self, endpoint):
+ """Execute an http get request
+
+ :param endpoint: Ansible Runner service RESTful API endpoint
+
+ :returns: A requests object
+ """
+
+ the_url = "%s/%s" % (self.server_url, endpoint)
+ response = requests.get(the_url,
+ verify = self.verify_server,
+ headers = {"Authorization": self.token})
+
+ if response.status_code != requests.codes.ok:
+ self.log.error("http GET %s <--> (%s - %s)\n%s",
+ the_url, response.status_code, response.reason,
+ response.text)
+ else:
+ self.log.info("http GET %s <--> (%s - %s)",
+ the_url, response.status_code, response.text)
+
+ return response
+
+ @handle_requests_exceptions
+ def http_post(self, endpoint, payload, params_dict):
+ """Execute an http post request
+
+ :param endpoint: Ansible Runner service RESTful API endpoint
+ :param payload: Dictionary with the data used in the post request
+ :param params_dict: A dict used to build a query string
+
+ :returns: A requests object
+ """
+
+ the_url = "%s/%s" % (self.server_url, endpoint)
+ response = requests.post(the_url,
+ verify = self.verify_server,
+ headers = {"Authorization": self.token,
+ "Content-type": "application/json"},
+ json = payload,
+ params = params_dict)
+
+ if response.status_code != requests.codes.ok:
+ self.log.error("http POST %s [%s] <--> (%s - %s:%s)\n",
+ the_url, payload, response.status_code,
+ response.reason, response.text)
+ else:
+ self.log.info("http POST %s <--> (%s - %s)",
+ the_url, response.status_code, response.text)
+
+ return response
+
+ @handle_requests_exceptions
+ def http_delete(self, endpoint):
+ """Execute an http delete request
+
+ :param endpoint: Ansible Runner service RESTful API endpoint
+
+ :returns: A requests object
+ """
+
+ the_url = "%s/%s" % (self.server_url, endpoint)
+ response = requests.delete(the_url,
+ verify = self.verify_server,
+ headers = {"Authorization": self.token})
+
+ if response.status_code != requests.codes.ok:
+ self.log.error("http DELETE %s <--> (%s - %s)\n%s",
+ the_url, response.status_code, response.reason,
+ response.text)
+ else:
+ self.log.info("http DELETE %s <--> (%s - %s)",
+ the_url, response.status_code, response.text)
+
+ return response
+
+ def http_put(self, endpoint, payload):
+ """Execute an http put request
+
+ :param endpoint: Ansible Runner service RESTful API endpoint
+ :param payload: Dictionary with the data used in the put request
+
+ :returns: A requests object
+ """
+ # TODO
+ raise NotImplementedError("TODO")
diff --git a/src/pybind/mgr/ansible/module.py b/src/pybind/mgr/ansible/module.py
new file mode 100644
index 00000000..81e1c40a
--- /dev/null
+++ b/src/pybind/mgr/ansible/module.py
@@ -0,0 +1,729 @@
+"""
+ceph-mgr Ansible orchestrator module
+
+The external Orchestrator is the Ansible runner service (RESTful https service)
+"""
+
+# pylint: disable=abstract-method, no-member, bad-continuation
+
+import json
+import requests
+
+from mgr_module import MgrModule
+import orchestrator
+
+from .ansible_runner_svc import Client, PlayBookExecution, ExecutionStatusCode,\
+ AnsibleRunnerServiceError
+
+from .output_wizards import ProcessInventory, ProcessPlaybookResult, \
+ ProcessHostsList
+
+# Time to clean the completions list
+WAIT_PERIOD = 10
+
+# List of playbooks names used
+
+# Name of the playbook used in the "get_inventory" method.
+# This playbook is expected to provide a list of storage devices in the host
+# where the playbook is executed.
+GET_STORAGE_DEVICES_CATALOG_PLAYBOOK = "storage-inventory.yml"
+
+# Used in the create_osd method
+ADD_OSD_PLAYBOOK = "add-osd.yml"
+
+# Used in the remove_osds method
+REMOVE_OSD_PLAYBOOK = "shrink-osd.yml"
+
+# Default name for the inventory group for hosts managed by the Orchestrator
+ORCHESTRATOR_GROUP = "orchestrator"
+
+# URLs for Ansible Runner Operations
+# Add or remove host in one group
+URL_ADD_RM_HOSTS = "api/v1/hosts/{host_name}/groups/{inventory_group}"
+
+# Retrieve the groups where the host is included in.
+URL_GET_HOST_GROUPS = "api/v1/hosts/{host_name}"
+# Manage groups
+URL_MANAGE_GROUP = "api/v1/groups/{group_name}"
+# URLs for Ansible Runner Operations
+URL_GET_HOSTS = "api/v1/hosts"
+
+
+class AnsibleReadOperation(orchestrator.ReadCompletion):
+ """ A read operation means to obtain information from the cluster.
+ """
+ def __init__(self, client, logger):
+ """
+ :param client : Ansible Runner Service Client
+ :param logger : The object used to log messages
+ """
+ super(AnsibleReadOperation, self).__init__()
+
+ # Private attributes
+ self._is_complete = False
+ self._is_errored = False
+ self._result = []
+ self._status = ExecutionStatusCode.NOT_LAUNCHED
+
+ # Object used to process operation result in different ways
+ self.output_wizard = None
+
+ # Error description in operation
+ self.error = ""
+
+ # Ansible Runner Service client
+ self.ar_client = client
+
+ # Logger
+ self.log = logger
+
+ # OutputWizard object used to process the result
+ self.output_wizard = None
+
+ @property
+ def is_complete(self):
+ return self._is_complete
+
+ @property
+ def is_errored(self):
+ return self._is_errored
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def status(self):
+ """Retrieve the current status of the operation and update state
+ attributes
+ """
+ raise NotImplementedError()
+
+class ARSOperation(AnsibleReadOperation):
+ """Execute an Ansible Runner Service Operation
+ """
+
+ def __init__(self, client, logger, url, get_operation=True, payload=None):
+ """
+ :param client : Ansible Runner Service Client
+ :param logger : The object used to log messages
+ :param url : The Ansible Runner Service URL that provides
+ the operation
+ :param get_operation : True if operation is provided using an http GET
+ :param payload : http request payload
+ """
+ super(ARSOperation, self).__init__(client, logger)
+
+ self.url = url
+ self.get_operation = get_operation
+ self.payload = payload
+
+ def __str__(self):
+ return "Ansible Runner Service: {operation} {url}".format(
+ operation="GET" if self.get_operation else "POST",
+ url=self.url)
+
+ @property
+ def status(self):
+ """ Execute the Ansible Runner Service operation and update the status
+ and result of the underlying Completion object.
+ """
+
+ # Execute the right kind of http request
+ if self.get_operation:
+ response = self.ar_client.http_get(self.url)
+ else:
+ response = self.ar_client.http_post(self.url, self.payload)
+
+ # If no connection errors, the operation is complete
+ self._is_complete = True
+
+ # Depending of the response, status and result is updated
+ if not response:
+ self._is_errored = True
+ self._status = ExecutionStatusCode.ERROR
+ self._result = "Ansible Runner Service not Available"
+ else:
+ self._is_errored = (response.status_code != requests.codes.ok)
+
+ if not self._is_errored:
+ self._status = ExecutionStatusCode.SUCCESS
+ if self.output_wizard:
+ self._result = self.output_wizard.process(self.url,
+ response.text)
+ else:
+ self._result = response.text
+ else:
+ self._status = ExecutionStatusCode.ERROR
+ self._result = response.reason
+
+ return self._status
+
+
+class PlaybookOperation(AnsibleReadOperation):
+ """Execute a playbook using the Ansible Runner Service
+ """
+
+ def __init__(self, client, playbook, logger, result_pattern,
+ params,
+ querystr_dict={}):
+ """
+ :param client : Ansible Runner Service Client
+ :param playbook : The playbook to execute
+ :param logger : The object used to log messages
+ :param result_pattern: The "pattern" to discover what execution events
+ have the information deemed as result
+ :param params : http request payload for the playbook execution
+ :param querystr_dict : http request querystring for the playbook
+ execution (DO NOT MODIFY HERE)
+
+ """
+ super(PlaybookOperation, self).__init__(client, logger)
+
+ # Private attributes
+ self.playbook = playbook
+
+ # An aditional filter of result events based in the event
+ self.event_filter = ""
+
+ # Playbook execution object
+ self.pb_execution = PlayBookExecution(client,
+ playbook,
+ logger,
+ result_pattern,
+ params,
+ querystr_dict)
+
+ def __str__(self):
+ return "Playbook {playbook_name}".format(playbook_name=self.playbook)
+
+ @property
+ def status(self):
+ """Check the status of the playbook execution and update the status
+ and result of the underlying Completion object.
+ """
+
+ if self._status in [ExecutionStatusCode.ON_GOING,
+ ExecutionStatusCode.NOT_LAUNCHED]:
+ self._status = self.pb_execution.get_status()
+
+ self._is_complete = (self._status == ExecutionStatusCode.SUCCESS) or \
+ (self._status == ExecutionStatusCode.ERROR)
+
+ self._is_errored = (self._status == ExecutionStatusCode.ERROR)
+
+ if self._is_complete:
+ self.update_result()
+
+ return self._status
+
+ def execute_playbook(self):
+ """Launch the execution of the playbook with the parameters configured
+ """
+ try:
+ self.pb_execution.launch()
+ except AnsibleRunnerServiceError:
+ self._status = ExecutionStatusCode.ERROR
+ raise
+
+ def update_result(self):
+ """Output of the read operation
+
+ The result of the playbook execution can be customized through the
+ function provided as 'process_output' attribute
+
+ :return string: Result of the operation formatted if it is possible
+ """
+
+ processed_result = []
+
+ if self._is_complete:
+ raw_result = self.pb_execution.get_result(self.event_filter)
+
+ if self.output_wizard:
+ processed_result = self.output_wizard.process(self.pb_execution.play_uuid,
+ raw_result)
+ else:
+ processed_result = raw_result
+
+ self._result = processed_result
+
+
+class AnsibleChangeOperation(orchestrator.WriteCompletion):
+ """Operations that changes the "cluster" state
+
+ Modifications/Changes (writes) are a two-phase thing, firstly execute
+ the playbook that is going to change elements in the Ceph Cluster.
+ When the playbook finishes execution (independently of the result),
+ the modification/change operation has finished.
+ """
+ def __init__(self):
+ super(AnsibleChangeOperation, self).__init__()
+
+ self._status = ExecutionStatusCode.NOT_LAUNCHED
+ self._result = None
+
+ # Object used to process operation result in different ways
+ self.output_wizard = None
+
+ @property
+ def status(self):
+ """Return the status code of the operation
+ """
+ raise NotImplementedError()
+
+ @property
+ def is_persistent(self):
+ """
+ Has the operation updated the orchestrator's configuration
+ persistently? Typically this would indicate that an update
+ had been written to a manifest, but that the update
+ had not necessarily been pushed out to the cluster.
+
+ :return Boolean: True if the execution of the Ansible Playbook or the
+ operation over the Ansible Runner Service has finished
+ """
+
+ return self._status in [ExecutionStatusCode.SUCCESS,
+ ExecutionStatusCode.ERROR]
+
+ @property
+ def is_effective(self):
+ """Has the operation taken effect on the cluster?
+ For example, if we were adding a service, has it come up and appeared
+ in Ceph's cluster maps?
+
+ In the case of Ansible, this will be True if the playbooks has been
+ executed succesfully.
+
+ :return Boolean: if the playbook/ARS operation has been executed
+ succesfully
+ """
+
+ return self._status == ExecutionStatusCode.SUCCESS
+
+ @property
+ def is_errored(self):
+ return self._status == ExecutionStatusCode.ERROR
+
+ @property
+ def result(self):
+ return self._result
+
+class HttpOperation(object):
+ """A class to ease the management of http operations
+ """
+
+ def __init__(self, url, http_operation, payload="", query_string="{}"):
+ self.url = url
+ self.http_operation = http_operation
+ self.payload = payload
+ self.query_string = query_string
+ self.response = None
+
+class ARSChangeOperation(AnsibleChangeOperation):
+ """Execute one or more Ansible Runner Service Operations that implies
+ a change in the cluster
+ """
+ def __init__(self, client, logger, operations):
+ """
+ :param client : Ansible Runner Service Client
+ :param logger : The object used to log messages
+ :param operations : A list of http_operation objects
+ :param payload : dict with http request payload
+ """
+ super(ARSChangeOperation, self).__init__()
+
+ assert operations, "At least one operation is needed"
+ self.ar_client = client
+ self.log = logger
+ self.operations = operations
+
+ def __str__(self):
+ # Use the last operation as the main
+ return "Ansible Runner Service: {operation} {url}".format(
+ operation=self.operations[-1].http_operation,
+ url=self.operations[-1].url)
+
+ @property
+ def status(self):
+ """Execute the Ansible Runner Service operations and update the status
+ and result of the underlying Completion object.
+ """
+
+ for my_request in self.operations:
+ # Execute the right kind of http request
+ try:
+ if my_request.http_operation == "post":
+ response = self.ar_client.http_post(my_request.url,
+ my_request.payload,
+ my_request.query_string)
+ elif my_request.http_operation == "delete":
+ response = self.ar_client.http_delete(my_request.url)
+ elif my_request.http_operation == "get":
+ response = self.ar_client.http_get(my_request.url)
+
+ # Any problem executing the secuence of operations will
+ # produce an errored completion object.
+ if response.status_code != requests.codes.ok:
+ self._status = ExecutionStatusCode.ERROR
+ self._result = response.text
+ return self._status
+
+ # Any kind of error communicating with ARS or preventing
+ # to have a right http response
+ except AnsibleRunnerServiceError as ex:
+ self._status = ExecutionStatusCode.ERROR
+ self._result = str(ex)
+ return self._status
+
+ # If this point is reached, all the operations has been succesfuly
+ # executed, and the final result is updated
+ self._status = ExecutionStatusCode.SUCCESS
+ if self.output_wizard:
+ self._result = self.output_wizard.process("", response.text)
+ else:
+ self._result = response.text
+
+ return self._status
+
+class Module(MgrModule, orchestrator.Orchestrator):
+ """An Orchestrator that uses <Ansible Runner Service> to perform operations
+ """
+
+ MODULE_OPTIONS = [
+ {'name': 'server_url'},
+ {'name': 'username'},
+ {'name': 'password'},
+ {'name': 'verify_server'} # Check server identity (Boolean/path to CA bundle)
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+
+ self.run = False
+
+ self.all_completions = []
+
+ self.ar_client = None
+
+ def available(self):
+ """ Check if Ansible Runner service is working
+ """
+ # TODO
+ return (True, "Everything ready")
+
+ def wait(self, completions):
+ """Given a list of Completion instances, progress any which are
+ incomplete.
+
+ :param completions: list of Completion instances
+ :Returns : True if everything is done.
+ """
+
+ # Check progress and update status in each operation
+ # Access completion.status property do the trick
+ for operation in completions:
+ self.log.info("<%s> status:%s", operation, operation.status)
+
+ completions = filter(lambda x: not x.is_complete, completions)
+
+ ops_pending = len(completions)
+ self.log.info("Operations pending: %s", ops_pending)
+
+ return ops_pending == 0
+
+ def serve(self):
+ """ Mandatory for standby modules
+ """
+ self.log.info("Starting Ansible Orchestrator module ...")
+
+ # Verify config options (Just that settings are available)
+ self.verify_config()
+
+ # Ansible runner service client
+ try:
+ self.ar_client = Client(server_url=self.get_module_option('server_url', ''),
+ user=self.get_module_option('username', ''),
+ password=self.get_module_option('password', ''),
+ verify_server=self.get_module_option('verify_server', True),
+ logger=self.log)
+ except AnsibleRunnerServiceError:
+ self.log.exception("Ansible Runner Service not available. "
+ "Check external server status/TLS identity or "
+ "connection options. If configuration options changed"
+ " try to disable/enable the module.")
+ self.shutdown()
+ return
+
+ self.run = True
+
+ def shutdown(self):
+
+ self.log.info('Stopping Ansible orchestrator module')
+ self.run = False
+
+ def get_inventory(self, node_filter=None, refresh=False):
+ """
+
+ :param : node_filter instance
+ :param : refresh any cached state
+ :Return : A AnsibleReadOperation instance (Completion Object)
+ """
+
+ # Create a new read completion object for execute the playbook
+ playbook_operation = PlaybookOperation(client=self.ar_client,
+ playbook=GET_STORAGE_DEVICES_CATALOG_PLAYBOOK,
+ logger=self.log,
+ result_pattern="list storage inventory",
+ params={})
+
+
+ # Assign the process_output function
+ playbook_operation.output_wizard = ProcessInventory(self.ar_client,
+ self.log)
+ playbook_operation.event_filter = "runner_on_ok"
+
+ # Execute the playbook to obtain data
+ self._launch_operation(playbook_operation)
+
+ return playbook_operation
+
+ def create_osds(self, drive_group, all_hosts):
+ """Create one or more OSDs within a single Drive Group.
+ If no host provided the operation affects all the host in the OSDS role
+
+
+ :param drive_group: (orchestrator.DriveGroupSpec),
+ Drive group with the specification of drives to use
+ :param all_hosts : (List[str]),
+ List of hosts where the OSD's must be created
+ """
+
+ # Transform drive group specification to Ansible playbook parameters
+ host, osd_spec = dg_2_ansible(drive_group)
+
+ # Create a new read completion object for execute the playbook
+ playbook_operation = PlaybookOperation(client=self.ar_client,
+ playbook=ADD_OSD_PLAYBOOK,
+ logger=self.log,
+ result_pattern="",
+ params=osd_spec,
+ querystr_dict={"limit": host})
+
+ # Filter to get the result
+ playbook_operation.output_wizard = ProcessPlaybookResult(self.ar_client,
+ self.log)
+ playbook_operation.event_filter = "playbook_on_stats"
+
+ # Execute the playbook
+ self._launch_operation(playbook_operation)
+
+ return playbook_operation
+
+ def remove_osds(self, osd_ids):
+ """Remove osd's.
+
+ :param osd_ids: List of osd's to be removed (List[int])
+ """
+
+ extravars = {'osd_to_kill': ",".join([str(osd_id) for osd_id in osd_ids]),
+ 'ireallymeanit':'yes'}
+
+ # Create a new read completion object for execute the playbook
+ playbook_operation = PlaybookOperation(client=self.ar_client,
+ playbook=REMOVE_OSD_PLAYBOOK,
+ logger=self.log,
+ result_pattern="",
+ params=extravars)
+
+ # Filter to get the result
+ playbook_operation.output_wizard = ProcessPlaybookResult(self.ar_client,
+ self.log)
+ playbook_operation.event_filter = "playbook_on_stats"
+
+ # Execute the playbook
+ self._launch_operation(playbook_operation)
+
+ return playbook_operation
+
+ def get_hosts(self):
+ """Provides a list Inventory nodes
+ """
+
+ host_ls_op = ARSOperation(self.ar_client, self.log, URL_GET_HOSTS)
+
+ host_ls_op.output_wizard = ProcessHostsList(self.ar_client,
+ self.log)
+
+ return host_ls_op
+
+ def add_host(self, host):
+ """
+ Add a host to the Ansible Runner Service inventory in the "orchestrator"
+ group
+
+ :param host: hostname
+ :returns : orchestrator.WriteCompletion
+ """
+
+ url_group = URL_MANAGE_GROUP.format(group_name=ORCHESTRATOR_GROUP)
+
+ try:
+ # Create the orchestrator default group if not exist.
+ # If exists we ignore the error response
+ dummy_response = self.ar_client.http_post(url_group, "", {})
+
+ # Here, the default group exists so...
+ # Prepare the operation for adding the new host
+ add_url = URL_ADD_RM_HOSTS.format(host_name=host,
+ inventory_group=ORCHESTRATOR_GROUP)
+
+ operations = [HttpOperation(add_url, "post")]
+
+ except AnsibleRunnerServiceError as ex:
+ # Problems with the external orchestrator.
+ # Prepare the operation to return the error in a Completion object.
+ self.log.exception("Error checking <orchestrator> group: %s", ex)
+ operations = [HttpOperation(url_group, "post")]
+
+ return ARSChangeOperation(self.ar_client, self.log, operations)
+
+ def remove_host(self, host):
+ """
+ Remove a host from all the groups in the Ansible Runner Service
+ inventory.
+
+ :param host: hostname
+ :returns : orchestrator.WriteCompletion
+ """
+
+ operations = []
+ host_groups = []
+
+ try:
+ # Get the list of groups where the host is included
+ groups_url = URL_GET_HOST_GROUPS.format(host_name=host)
+ response = self.ar_client.http_get(groups_url)
+
+ if response.status_code == requests.codes.ok:
+ host_groups = json.loads(response.text)["data"]["groups"]
+
+ except AnsibleRunnerServiceError:
+ self.log.exception("Error retrieving host groups")
+
+ if not host_groups:
+ # Error retrieving the groups, prepare the completion object to
+ # execute the problematic operation just to provide the error
+ # to the caller
+ operations = [HttpOperation(groups_url, "get")]
+ else:
+ # Build the operations list
+ operations = list(map(lambda x:
+ HttpOperation(URL_ADD_RM_HOSTS.format(
+ host_name=host,
+ inventory_group=x),
+ "delete"),
+ host_groups))
+
+ return ARSChangeOperation(self.ar_client, self.log, operations)
+
+ def _launch_operation(self, ansible_operation):
+ """Launch the operation and add the operation to the completion objects
+ ongoing
+
+ :ansible_operation: A read/write ansible operation (completion object)
+ """
+
+ # Execute the playbook
+ ansible_operation.execute_playbook()
+
+ # Add the operation to the list of things ongoing
+ self.all_completions.append(ansible_operation)
+
+ def verify_config(self):
+ """ Verify configuration options for the Ansible orchestrator module
+ """
+ client_msg = ""
+
+ if not self.get_module_option('server_url', ''):
+ msg = "No Ansible Runner Service base URL <server_name>:<port>." \
+ "Try 'ceph config set mgr mgr/{0}/server_url " \
+ "<server name/ip>:<port>'".format(self.module_name)
+ self.log.error(msg)
+ client_msg += msg
+
+ if not self.get_module_option('username', ''):
+ msg = "No Ansible Runner Service user. " \
+ "Try 'ceph config set mgr mgr/{0}/username " \
+ "<string value>'".format(self.module_name)
+ self.log.error(msg)
+ client_msg += msg
+
+ if not self.get_module_option('password', ''):
+ msg = "No Ansible Runner Service User password. " \
+ "Try 'ceph config set mgr mgr/{0}/password " \
+ "<string value>'".format(self.module_name)
+ self.log.error(msg)
+ client_msg += msg
+
+ if not self.get_module_option('verify_server', ''):
+ msg = "TLS server identity verification is enabled by default." \
+ "Use 'ceph config set mgr mgr/{0}/verify_server False' " \
+ "to disable it. Use 'ceph config set mgr mgr/{0}/verify_server " \
+ "<path>' to point the CA bundle path used for " \
+ "verification".format(self.module_name)
+ self.log.error(msg)
+ client_msg += msg
+
+ if client_msg:
+ # Raise error
+ # TODO: Use OrchestratorValidationError
+ raise Exception(client_msg)
+
+
+
+# Auxiliary functions
+#==============================================================================
+def dg_2_ansible(drive_group):
+ """ Transform a drive group especification into:
+
+ a host : limit the playbook execution to this host
+ a osd_spec : dict of parameters to pass to the Ansible playbook used
+ to create the osds
+
+ :param drive_group: (type: DriveGroupSpec)
+
+ TODO: Possible this function will be removed/or modified heavily when
+ the ansible playbook to create osd's use ceph volume batch with
+ drive group parameter
+ """
+
+ # Limit the execution of the playbook to certain hosts
+ # TODO: Now only accepted "*" (all the hosts) or a host_name in the
+ # drive_group.host_pattern
+ # This attribute is intended to be used with "fnmatch" patterns, so when
+ # this become effective it will be needed to use the "get_inventory" method
+ # in order to have a list of hosts to be filtered with the "host_pattern"
+ if drive_group.host_pattern in ["*"]:
+ host = None # No limit in the playbook
+ else:
+ # For the moment, we assume that we only have 1 host
+ host = drive_group.host_pattern
+
+ # Compose the OSD configuration
+
+
+ osd = {}
+ osd["data"] = drive_group.data_devices.paths[0]
+ # Other parameters will be extracted in the same way
+ #osd["dmcrypt"] = drive_group.encryption
+
+ # lvm_volumes parameters
+ # (by the moment is what is accepted in the current playbook)
+ osd_spec = {"lvm_volumes":[osd]}
+
+ #Global scope variables also can be included in the osd_spec
+ #osd_spec["osd_objectstore"] = drive_group.objectstore
+
+ return host, osd_spec
diff --git a/src/pybind/mgr/ansible/output_wizards.py b/src/pybind/mgr/ansible/output_wizards.py
new file mode 100644
index 00000000..d924bf04
--- /dev/null
+++ b/src/pybind/mgr/ansible/output_wizards.py
@@ -0,0 +1,158 @@
+"""
+ceph-mgr Output Wizards module
+
+Output wizards are used to process results in different ways in
+completion objects
+"""
+
+# pylint: disable=bad-continuation
+
+import json
+
+
+from orchestrator import InventoryDevice, InventoryNode
+
+from .ansible_runner_svc import EVENT_DATA_URL
+
+class OutputWizard(object):
+ """Base class for help to process output in completion objects
+ """
+ def __init__(self, ar_client, logger):
+ """Make easy to work in output wizards using this attributes:
+
+ :param ars_client: Ansible Runner Service client
+ :param logger: log object
+ """
+ self.ar_client = ar_client
+ self.log = logger
+
+ def process(self, operation_id, raw_result):
+ """Make the magic here
+
+ :param operation_id: Allows to identify the Ansible Runner Service
+ operation whose result we wnat to process
+ :param raw_result: input for processing
+ """
+ raise NotImplementedError
+
+class ProcessInventory(OutputWizard):
+ """ Adapt the output of the playbook used in 'get_inventory'
+ to the Orchestrator expected output (list of InventoryNode)
+ """
+
+ def process(self, operation_id, raw_result):
+ """
+ :param operation_id: Playbook uuid
+ :param raw_result: events dict with the results
+
+ Example:
+ inventory_events =
+ {'37-100564f1-9fed-48c2-bd62-4ae8636dfcdb': {'host': '192.168.121.254',
+ 'task': 'list storage inventory',
+ 'event': 'runner_on_ok'},
+ '36-2016b900-e38f-7dcd-a2e7-00000000000e': {'host': '192.168.121.252'
+ 'task': 'list storage inventory',
+ 'event': 'runner_on_ok'}}
+
+ :return : list of InventoryNode
+ """
+ # Just making more readable the method
+ inventory_events = raw_result
+
+ #Obtain the needed data for each result event
+ inventory_nodes = []
+
+ # Loop over the result events and request the event data
+ for event_key, dummy_data in inventory_events.items():
+
+ event_response = self.ar_client.http_get(EVENT_DATA_URL %
+ (operation_id, event_key))
+
+ # self.pb_execution.play_uuid
+
+ # Process the data for each event
+ if event_response:
+ event_data = json.loads(event_response.text)["data"]["event_data"]
+
+ host = event_data["host"]
+
+ devices = json.loads(event_data["res"]["stdout"])
+ devs = []
+ for storage_device in devices:
+ dev = InventoryDevice.from_ceph_volume_inventory(storage_device)
+ devs.append(dev)
+
+ inventory_nodes.append(InventoryNode(host, devs))
+
+
+ return inventory_nodes
+
+class ProcessPlaybookResult(OutputWizard):
+ """ Provides the result of a playbook execution as plain text
+ """
+ def process(self, operation_id, raw_result):
+ """
+ :param operation_id: Playbook uuid
+ :param raw_result: events dict with the results
+
+ :return : String with the playbook execution event list
+ """
+ # Just making more readable the method
+ inventory_events = raw_result
+
+ result = ""
+
+ # Loop over the result events and request the data
+ for event_key, dummy_data in inventory_events.items():
+ event_response = self.ar_client.http_get(EVENT_DATA_URL %
+ (operation_id, event_key))
+
+ result += event_response.text
+
+ return result
+
+
+class ProcessHostsList(OutputWizard):
+ """ Format the output of host ls call
+ """
+ def process(self, operation_id, raw_result):
+ """ Format the output of host ls call
+
+ :param operation_id: Not used in this output wizard
+ :param raw_result: In this case is like the following json:
+ {
+ "status": "OK",
+ "msg": "",
+ "data": {
+ "hosts": [
+ "host_a",
+ "host_b",
+ ...
+ "host_x",
+ ]
+ }
+ }
+
+ :return: list of InventoryNodes
+ """
+ # Just making more readable the method
+ host_ls_json = raw_result
+
+ inventory_nodes = []
+
+ try:
+ json_resp = json.loads(host_ls_json)
+
+ for host in json_resp["data"]["hosts"]:
+ inventory_nodes.append(InventoryNode(host, []))
+
+ except ValueError:
+ self.log.exception("Malformed json response")
+ except KeyError:
+ self.log.exception("Unexpected content in Ansible Runner Service"
+ " response")
+ except TypeError:
+ self.log.exception("Hosts data must be iterable in Ansible Runner "
+ "Service response")
+
+ return inventory_nodes
diff --git a/src/pybind/mgr/ansible/requirements.txt b/src/pybind/mgr/ansible/requirements.txt
new file mode 100644
index 00000000..e75b578d
--- /dev/null
+++ b/src/pybind/mgr/ansible/requirements.txt
@@ -0,0 +1,2 @@
+tox==2.9.1
+importlib_metadata==2.1.0
diff --git a/src/pybind/mgr/ansible/run-tox.sh b/src/pybind/mgr/ansible/run-tox.sh
new file mode 100644
index 00000000..fd6da244
--- /dev/null
+++ b/src/pybind/mgr/ansible/run-tox.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+function dump_envvars {
+ echo "WITH_PYTHON2: ->$WITH_PYTHON2<-"
+ echo "WITH_PYTHON3: ->$WITH_PYTHON3<-"
+ echo "TOX_PATH: ->$TOX_PATH<-"
+ echo "ENV_LIST: ->$ENV_LIST<-"
+}
+
+# run from ./ or from ../
+: ${MGR_ANSIBLE_VIRTUALENV:=$CEPH_BUILD_DIR/mgr-ansible-virtualenv}
+: ${WITH_PYTHON2:=ON}
+: ${WITH_PYTHON3:=3}
+: ${CEPH_BUILD_DIR:=$PWD/.tox}
+test -d ansible && cd ansible
+
+if [ -e tox.ini ]; then
+ TOX_PATH=$(readlink -f tox.ini)
+else
+ TOX_PATH=$(readlink -f $(dirname $0)/tox.ini)
+fi
+
+# tox.ini will take care of this.
+unset PYTHONPATH
+export CEPH_BUILD_DIR=$CEPH_BUILD_DIR
+
+source ${MGR_ANSIBLE_VIRTUALENV}/bin/activate
+
+if [ "$WITH_PYTHON2" = "ON" ]; then
+ ENV_LIST+="py27,"
+fi
+# WITH_PYTHON3 might be set to "ON" or to the python3 RPM version number
+# prevailing on the system - e.g. "3", "36"
+if [[ "$WITH_PYTHON3" =~ (^3|^ON) ]]; then
+ ENV_LIST+="py3,"
+fi
+# use bash string manipulation to strip off any trailing comma
+ENV_LIST=${ENV_LIST%,}
+
+tox -c "${TOX_PATH}" -e "${ENV_LIST}" "$@"
+TOX_STATUS="$?"
+test "$TOX_STATUS" -ne "0" && dump_envvars
+exit $TOX_STATUS
diff --git a/src/pybind/mgr/ansible/tests/__init__.py b/src/pybind/mgr/ansible/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/ansible/tests/__init__.py
diff --git a/src/pybind/mgr/ansible/tests/pb_execution_events.data b/src/pybind/mgr/ansible/tests/pb_execution_events.data
new file mode 100644
index 00000000..248134a3
--- /dev/null
+++ b/src/pybind/mgr/ansible/tests/pb_execution_events.data
@@ -0,0 +1,183 @@
+{
+ "status": "OK",
+ "msg": "",
+ "data": {
+ "events": {
+ "2-6edf768f-2923-44e1-b884-f0227b811cfc": {
+ "event": "playbook_on_start"
+ },
+ "3-2016b900-e38f-7dcd-a2e7-000000000008": {
+ "event": "playbook_on_play_start"
+ },
+ "4-2016b900-e38f-7dcd-a2e7-000000000012": {
+ "event": "playbook_on_task_start",
+ "task": "Gathering Facts"
+ },
+ "5-19ae1e5e-aa2d-479e-845a-ef0253cc1f99": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.245",
+ "task": "Gathering Facts"
+ },
+ "6-aad3acc4-06a3-4c97-82ff-31e9e484b1f5": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.61",
+ "task": "Gathering Facts"
+ },
+ "7-55298017-3e7d-4734-b316-bbe13ce1da5e": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.254",
+ "task": "Gathering Facts"
+ },
+ "8-2016b900-e38f-7dcd-a2e7-00000000000a": {
+ "event": "playbook_on_task_start",
+ "task": "setup"
+ },
+ "9-2085ccb6-e337-4b9f-bc38-1d8bbf9b973f": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.254",
+ "task": "setup"
+ },
+ "10-e14cdbbc-4883-436c-a41c-a8194ec69075": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.245",
+ "task": "setup"
+ },
+ "11-6d815a26-df53-4240-b8b6-2484e88e4f48": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.61",
+ "task": "setup"
+ },
+ "12-2016b900-e38f-7dcd-a2e7-00000000000b": {
+ "event": "playbook_on_task_start",
+ "task": "Get a list of block devices (excludes loop and child devices)"
+ },
+ "13-799b0119-ccab-4eca-b30b-a37b0bafa02c": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.245",
+ "task": "Get a list of block devices (excludes loop and child devices)"
+ },
+ "14-6beb6958-4bfd-4a9c-bd2c-d20d00248605": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.61",
+ "task": "Get a list of block devices (excludes loop and child devices)"
+ },
+ "15-3ca99cc8-98ea-4967-8f2d-115426d00b6a": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.254",
+ "task": "Get a list of block devices (excludes loop and child devices)"
+ },
+ "16-2016b900-e38f-7dcd-a2e7-00000000000c": {
+ "event": "playbook_on_task_start",
+ "task": "check if disk {{ item }} is free"
+ },
+ "17-8c88141a-08d1-411f-a855-9f7702a49c4e": {
+ "event": "runner_item_on_failed",
+ "host": "192.168.121.245",
+ "task": "check if disk vda is free"
+ },
+ "18-4457db98-6f18-4f63-bfaa-584db5eea05b": {
+ "event": "runner_on_failed",
+ "host": "192.168.121.245",
+ "task": "check if disk {{ item }} is free"
+ },
+ "19-ac3c72cd-1fbb-495a-be69-53fa6029f356": {
+ "event": "runner_item_on_failed",
+ "host": "192.168.121.61",
+ "task": "check if disk vda is free"
+ },
+ "20-d161cb70-ba2e-4571-b029-c6428a566fef": {
+ "event": "runner_on_failed",
+ "host": "192.168.121.61",
+ "task": "check if disk {{ item }} is free"
+ },
+ "21-65f1ce5c-2d86-4cc3-8e10-cff6bf6cbd82": {
+ "event": "runner_item_on_failed",
+ "host": "192.168.121.254",
+ "task": "check if disk sda is free"
+ },
+ "22-7f86dcd4-4ef7-4f5a-9db3-c3780b67cc4b": {
+ "event": "runner_item_on_failed",
+ "host": "192.168.121.254",
+ "task": "check if disk sdb is free"
+ },
+ "23-837bf4f6-a912-46a8-b94b-55aa66a935c4": {
+ "event": "runner_item_on_ok",
+ "host": "192.168.121.254",
+ "task": "check if disk sdc is free"
+ },
+ "24-adf6238d-723f-4783-9226-8475419d466e": {
+ "event": "runner_item_on_failed",
+ "host": "192.168.121.254",
+ "task": "check if disk vda is free"
+ },
+ "25-554661d8-bc34-4885-a589-4960d6b8a487": {
+ "event": "runner_on_failed",
+ "host": "192.168.121.254",
+ "task": "check if disk {{ item }} is free"
+ },
+ "26-2016b900-e38f-7dcd-a2e7-00000000000d": {
+ "event": "playbook_on_task_start",
+ "task": "Update hosts freedisk list"
+ },
+ "27-52df484c-30a0-4e3b-9057-02ca345c5790": {
+ "event": "runner_item_on_skipped",
+ "host": "192.168.121.254",
+ "task": "Update hosts freedisk list"
+ },
+ "28-083616ad-3c1f-4fb8-a06c-5d64e670e362": {
+ "event": "runner_item_on_skipped",
+ "host": "192.168.121.254",
+ "task": "Update hosts freedisk list"
+ },
+ "29-bffc68d3-5448-491f-8780-07858285f5cd": {
+ "event": "runner_item_on_skipped",
+ "host": "192.168.121.245",
+ "task": "Update hosts freedisk list"
+ },
+ "30-cca2dfd9-16e9-4fcb-8bf7-c4da7dab5668": {
+ "event": "runner_on_skipped",
+ "host": "192.168.121.245",
+ "task": "Update hosts freedisk list"
+ },
+ "31-158a98ac-7e8d-4ebb-8c53-4467351a2d3a": {
+ "event": "runner_item_on_ok",
+ "host": "192.168.121.254",
+ "task": "Update hosts freedisk list"
+ },
+ "32-06a7e809-8d82-41df-b01d-45d94e519cb7": {
+ "event": "runner_item_on_skipped",
+ "host": "192.168.121.254",
+ "task": "Update hosts freedisk list"
+ },
+ "33-d5cdbb58-728a-4be5-abf1-4a051146e727": {
+ "event": "runner_item_on_skipped",
+ "host": "192.168.121.61",
+ "task": "Update hosts freedisk list"
+ },
+ "34-9b3c570b-22d8-4539-8c94-d0c1cbed8633": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.254",
+ "task": "Update hosts freedisk list"
+ },
+ "35-93336830-03cd-43ff-be87-a7e063ca7547": {
+ "event": "runner_on_skipped",
+ "host": "192.168.121.61",
+ "task": "Update hosts freedisk list"
+ },
+ "36-2016b900-e38f-7dcd-a2e7-00000000000e": {
+ "event": "playbook_on_task_start",
+ "task": "RESULTS"
+ },
+ "37-100564f1-9fed-48c2-bd62-4ae8636dfcdb": {
+ "event": "runner_on_ok",
+ "host": "192.168.121.254",
+ "task": "RESULTS"
+ },
+ "38-20a64160-30a1-481f-a3ee-36e491bc7869": {
+ "event": "playbook_on_stats"
+ }
+ },
+ "total_events": 37
+ }
+}
+
diff --git a/src/pybind/mgr/ansible/tests/test_client_playbooks.py b/src/pybind/mgr/ansible/tests/test_client_playbooks.py
new file mode 100644
index 00000000..98dfd3dd
--- /dev/null
+++ b/src/pybind/mgr/ansible/tests/test_client_playbooks.py
@@ -0,0 +1,287 @@
+import logging
+import unittest
+import mock
+import json
+
+import requests_mock
+
+from requests.exceptions import ConnectionError
+
+from ..ansible_runner_svc import Client, PlayBookExecution, ExecutionStatusCode, \
+ LOGIN_URL, API_URL, PLAYBOOK_EXEC_URL, \
+ PLAYBOOK_EVENTS, AnsibleRunnerServiceError
+
+
+SERVER_URL = "ars:5001"
+USER = "admin"
+PASSWORD = "admin"
+CERTIFICATE = ""
+
+# Playbook attributes
+PB_NAME = "test_playbook"
+PB_UUID = "1733c3ac"
+
+# Playbook execution data file
+PB_EVENTS_FILE = "./tests/pb_execution_events.data"
+
+# create console handler and set level to info
+logger = logging.getLogger()
+handler = logging.StreamHandler()
+handler.setLevel(logging.INFO)
+formatter = logging.Formatter("%(levelname)s - %(message)s")
+handler.setFormatter(formatter)
+logger.addHandler(handler)
+
+
+def mock_login(mock_server):
+
+ the_login_url = "https://%s/%s" % (SERVER_URL,LOGIN_URL)
+
+ mock_server.register_uri("GET",
+ the_login_url,
+ json={"status": "OK",
+ "msg": "Token returned",
+ "data": {"token": "dummy_token"}},
+ status_code=200)
+
+ the_api_url = "https://%s/%s" % (SERVER_URL,API_URL)
+ mock_server.register_uri("GET",
+ the_api_url,
+ text="<!DOCTYPE html>api</html>",
+ status_code=200)
+
+def mock_get_pb(mock_server, playbook_name, return_code):
+
+ mock_login(mock_server)
+
+ ars_client = Client(SERVER_URL, USER, PASSWORD,
+ CERTIFICATE, logger)
+
+ the_pb_url = "https://%s/%s/%s" % (SERVER_URL, PLAYBOOK_EXEC_URL, playbook_name)
+
+ if return_code == 404:
+ mock_server.register_uri("POST",
+ the_pb_url,
+ json={ "status": "NOTFOUND",
+ "msg": "playbook file not found",
+ "data": {}},
+ status_code=return_code)
+ elif return_code == 202:
+ mock_server.register_uri("POST",
+ the_pb_url,
+ json={ "status": "STARTED",
+ "msg": "starting",
+ "data": { "play_uuid": "1733c3ac" }},
+ status_code=return_code)
+
+ return PlayBookExecution(ars_client, playbook_name, logger,
+ result_pattern = "RESULTS")
+
+class ARSclientTest(unittest.TestCase):
+
+ def test_server_not_reachable(self):
+
+ with self.assertRaises(AnsibleRunnerServiceError):
+ ars_client = Client(SERVER_URL, USER, PASSWORD,
+ CERTIFICATE, logger)
+
+ def test_server_wrong_USER(self):
+
+ with requests_mock.Mocker() as mock_server:
+ the_login_url = "https://%s/%s" % (SERVER_URL,LOGIN_URL)
+ mock_server.get(the_login_url,
+ json={"status": "NOAUTH",
+ "msg": "Access denied invalid login: unknown USER",
+ "data": {}},
+ status_code=401)
+
+
+ ars_client = Client(SERVER_URL, USER, PASSWORD,
+ CERTIFICATE, logger)
+
+ self.assertFalse(ars_client.is_operative(),
+ "Operative attribute expected to be False")
+
+ def test_server_connection_ok(self):
+
+ with requests_mock.Mocker() as mock_server:
+
+ mock_login(mock_server)
+
+ ars_client = Client(SERVER_URL, USER, PASSWORD,
+ CERTIFICATE, logger)
+
+ self.assertTrue(ars_client.is_operative(),
+ "Operative attribute expected to be True")
+
+ def test_server_http_delete(self):
+
+ with requests_mock.Mocker() as mock_server:
+
+ mock_login(mock_server)
+
+ ars_client = Client(SERVER_URL, USER, PASSWORD,
+ CERTIFICATE, logger)
+
+ url = "https://%s/test" % (SERVER_URL)
+ mock_server.register_uri("DELETE",
+ url,
+ json={ "status": "OK",
+ "msg": "",
+ "data": {}},
+ status_code=201)
+
+ response = ars_client.http_delete("test")
+ self.assertTrue(response.status_code == 201)
+
+class PlayBookExecutionTests(unittest.TestCase):
+
+
+ def test_playbook_execution_ok(self):
+ """Check playbook id is set when the playbook is launched
+ """
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ test_pb.launch()
+
+ self.assertEqual(test_pb.play_uuid, PB_UUID,
+ "Found Unexpected playbook uuid")
+
+
+
+ def test_playbook_execution_error(self):
+ """Check playbook id is not set when the playbook is not present
+ """
+
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, "unknown_playbook", 404)
+
+ with self.assertRaises(AnsibleRunnerServiceError):
+ test_pb.launch()
+
+ #self.assertEqual(test_pb.play_uuid, "",
+ # "Playbook uuid not empty")
+
+ def test_playbook_not_launched(self):
+ """Check right status code when Playbook execution has not been launched
+ """
+
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ # Check playbook not launched
+ self.assertEqual(test_pb.get_status(),
+ ExecutionStatusCode.NOT_LAUNCHED,
+ "Wrong status code for playbook not launched")
+
+ def test_playbook_launched(self):
+ """Check right status code when Playbook execution has been launched
+ """
+
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ test_pb.launch()
+
+ the_status_url = "https://%s/%s/%s" % (SERVER_URL,
+ PLAYBOOK_EXEC_URL,
+ PB_UUID)
+ mock_server.register_uri("GET",
+ the_status_url,
+ json={"status": "OK",
+ "msg": "running",
+ "data": {"task": "Step 2",
+ "last_task_num": 6}
+ },
+ status_code=200)
+
+ self.assertEqual(test_pb.get_status(),
+ ExecutionStatusCode.ON_GOING,
+ "Wrong status code for a running playbook")
+
+ self.assertEqual(test_pb.play_uuid, PB_UUID,
+ "Unexpected playbook uuid")
+
+ def test_playbook_finish_ok(self):
+ """Check right status code when Playbook execution is succesful
+ """
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ test_pb.launch()
+
+ the_status_url = "https://%s/%s/%s" % (SERVER_URL,
+ PLAYBOOK_EXEC_URL,
+ PB_UUID)
+ mock_server.register_uri("GET",
+ the_status_url,
+ json={"status": "OK",
+ "msg": "successful",
+ "data": {}
+ },
+ status_code=200)
+
+ self.assertEqual(test_pb.get_status(),
+ ExecutionStatusCode.SUCCESS,
+ "Wrong status code for a playbook executed succesfully")
+
+ def test_playbook_finish_error(self):
+ """Check right status code when Playbook execution has failed
+ """
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ test_pb.launch()
+
+ the_status_url = "https://%s/%s/%s" % (SERVER_URL,
+ PLAYBOOK_EXEC_URL,
+ PB_UUID)
+ mock_server.register_uri("GET",
+ the_status_url,
+ json={"status": "OK",
+ "msg": "failed",
+ "data": {}
+ },
+ status_code=200)
+
+ self.assertEqual(test_pb.get_status(),
+ ExecutionStatusCode.ERROR,
+ "Wrong status code for a playbook with error")
+
+ def test_playbook_get_result(self):
+ """ Find the right result event in a set of different events
+ """
+ with requests_mock.Mocker() as mock_server:
+
+ test_pb = mock_get_pb(mock_server, PB_NAME, 202)
+
+ test_pb.launch()
+
+ the_events_url = "https://%s/%s" % (SERVER_URL,
+ PLAYBOOK_EVENTS % PB_UUID)
+
+ # Get the events stored in a file
+ pb_events = {}
+ with open(PB_EVENTS_FILE) as events_file:
+ pb_events = json.loads(events_file.read())
+
+ mock_server.register_uri("GET",
+ the_events_url,
+ json=pb_events,
+ status_code=200)
+
+ result = test_pb.get_result("runner_on_ok")
+
+ self.assertEqual(len(result.keys()), 1,
+ "Unique result event not found")
+
+ self.assertIn("37-100564f1-9fed-48c2-bd62-4ae8636dfcdb",
+ result.keys(),
+ "Predefined result event not found")
diff --git a/src/pybind/mgr/ansible/tests/test_output_wizards.py b/src/pybind/mgr/ansible/tests/test_output_wizards.py
new file mode 100644
index 00000000..2a3a9017
--- /dev/null
+++ b/src/pybind/mgr/ansible/tests/test_output_wizards.py
@@ -0,0 +1,207 @@
+""" Test output wizards
+"""
+import unittest
+import mock
+
+from ..ansible_runner_svc import EVENT_DATA_URL
+from ..output_wizards import ProcessHostsList, ProcessPlaybookResult, \
+ ProcessInventory
+
+class OutputWizardProcessHostsList(unittest.TestCase):
+ """Test ProcessHostsList Output Wizard
+ """
+ RESULT_OK = """
+ {
+ "status": "OK",
+ "msg": "",
+ "data": {
+ "hosts": [
+ "host_a",
+ "host_b",
+ "host_c"
+ ]
+ }
+ }
+ """
+ ar_client = mock.Mock()
+ logger = mock.Mock()
+ test_wizard = ProcessHostsList(ar_client, logger)
+
+ def test_process(self):
+ """Test a normal call"""
+
+ nodes_list = self.test_wizard.process("", self.RESULT_OK)
+ self.assertEqual([node.name for node in nodes_list],
+ ["host_a", "host_b", "host_c"])
+
+ def test_errors(self):
+ """Test different kind of errors processing result"""
+
+ # Malformed json
+ host_list = self.test_wizard.process("", """{"msg": """"")
+ self.assertEqual(host_list, [])
+
+ # key error
+ host_list = self.test_wizard.process("", """{"msg": ""}""")
+ self.assertEqual(host_list, [])
+
+ # Hosts not in iterable
+ host_list = self.test_wizard.process("", """{"data":{"hosts": 123} }""")
+ self.assertEqual(host_list, [])
+
+class OutputWizardProcessPlaybookResult(unittest.TestCase):
+ """Test ProcessPlaybookResult Output Wizard
+ """
+ # Input to process
+ INVENTORY_EVENTS = {1:"first event", 2:"second event"}
+ EVENT_INFORMATION = "event information\n"
+
+ # Mocked response
+ mocked_response = mock.Mock()
+ mocked_response.text = EVENT_INFORMATION
+
+ # The Ansible Runner Service client
+ ar_client = mock.Mock()
+ ar_client.http_get = mock.MagicMock(return_value=mocked_response)
+
+ logger = mock.Mock()
+
+ test_wizard = ProcessPlaybookResult(ar_client, logger)
+
+ def test_process(self):
+ """Test a normal call
+ """
+
+ operation_id = 24
+ result = self.test_wizard.process(operation_id, self.INVENTORY_EVENTS)
+
+ # Check http request are correct and compose expected result
+ expected_result = ""
+ for key, dummy_data in self.INVENTORY_EVENTS.items():
+ http_request = EVENT_DATA_URL % (operation_id, key)
+ self.ar_client.http_get.assert_any_call(http_request)
+ expected_result += self.EVENT_INFORMATION
+
+ #Check result
+ self.assertEqual(result, expected_result)
+
+class OutputWizardProcessInventory(unittest.TestCase):
+ """Test ProcessInventory Output Wizard
+ """
+ # Input to process
+ INVENTORY_EVENTS = {'event_uuid_1': {'host': '192.168.121.144',
+ 'task': 'list storage inventory',
+ 'event': 'runner_on_ok'}}
+ EVENT_DATA = r"""
+ {
+ "status": "OK",
+ "msg": "",
+ "data": {
+ "uuid": "5e96d509-174d-4f5f-bd94-e278c3a5b85b",
+ "counter": 11,
+ "stdout": "changed: [192.168.121.144]",
+ "start_line": 17,
+ "end_line": 18,
+ "runner_ident": "6e98b2ba-3ce1-11e9-be81-2016b900e38f",
+ "created": "2019-03-02T11:50:56.582112",
+ "pid": 482,
+ "event_data": {
+ "play_pattern": "osds",
+ "play": "query each host for storage device inventory",
+ "task": "list storage inventory",
+ "task_args": "_ansible_version=2.6.5, _ansible_selinux_special_fs=['fuse', 'nfs', 'vboxsf', 'ramfs', '9p'], _ansible_no_log=False, _ansible_module_name=ceph_volume, _ansible_debug=False, _ansible_verbosity=0, _ansible_keep_remote_files=False, _ansible_syslog_facility=LOG_USER, _ansible_socket=None, action=inventory, _ansible_diff=False, _ansible_remote_tmp=~/.ansible/tmp, _ansible_shell_executable=/bin/sh, _ansible_check_mode=False, _ansible_tmpdir=None",
+ "remote_addr": "192.168.121.144",
+ "res": {
+ "_ansible_parsed": true,
+ "stderr_lines": [],
+ "changed": true,
+ "end": "2019-03-02 11:50:56.554937",
+ "_ansible_no_log": false,
+ "stdout": "[{\"available\": true, \"rejected_reasons\": [], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 0, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sdc\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [], \"path\": \"/dev/sdc\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sda\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [{\"cluster_name\": \"ceph\", \"name\": \"osd-data-dcf8a88c-5546-42d2-afa4-b36f7fb23b66\", \"osd_id\": \"3\", \"cluster_fsid\": \"30d61f3e-7ee4-4bdc-8fe7-2ad5bb3f5317\", \"type\": \"block\", \"block_uuid\": \"fVqujC-9dgh-cN9W-1XD4-zVx1-1UdA-fUS3ha\", \"osd_fsid\": \"8b7cbeba-5e86-44ff-a5f3-2e7df77753fe\"}], \"path\": \"/dev/sda\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sdb\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [{\"cluster_name\": \"ceph\", \"name\": \"osd-data-8c92e986-bd97-4b3d-ba77-2cb88e15d80f\", \"osd_id\": \"1\", \"cluster_fsid\": \"30d61f3e-7ee4-4bdc-8fe7-2ad5bb3f5317\", \"type\": \"block\", \"block_uuid\": \"mgzO7O-vUfu-H3mf-4R3K-2f97-ZMRH-SngBFP\", \"osd_fsid\": \"6d067688-3e1b-45f9-ad03-8abd19e9f117\"}], \"path\": \"/dev/sdb\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"mq-deadline\", \"rotational\": \"1\", \"vendor\": \"0x1af4\", \"human_readable_size\": \"41.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {\"vda1\": {\"start\": \"2048\", \"holders\": [], \"sectorsize\": 512, \"sectors\": \"2048\", \"size\": \"1024.00 KB\"}, \"vda3\": {\"start\": \"2101248\", \"holders\": [\"dm-0\", \"dm-1\"], \"sectorsize\": 512, \"sectors\": \"81784832\", \"size\": \"39.00 GB\"}, \"vda2\": {\"start\": \"4096\", \"holders\": [], \"sectorsize\": 512, \"sectors\": \"2097152\", \"size\": \"1024.00 MB\"}}, \"rev\": \"\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/vda\", \"support_discard\": \"\", \"model\": \"\", \"ro\": \"0\", \"nr_requests\": \"256\", \"size\": 44023414784.0}, \"lvs\": [{\"comment\": \"not used by ceph\", \"name\": \"LogVol00\"}, {\"comment\": \"not used by ceph\", \"name\": \"LogVol01\"}], \"path\": \"/dev/vda\"}]",
+ "cmd": [
+ "ceph-volume",
+ "inventory",
+ "--format=json"
+ ],
+ "rc": 0,
+ "start": "2019-03-02 11:50:55.150121",
+ "stderr": "",
+ "delta": "0:00:01.404816",
+ "invocation": {
+ "module_args": {
+ "wal_vg": null,
+ "wal": null,
+ "dmcrypt": false,
+ "block_db_size": "-1",
+ "journal": null,
+ "objectstore": "bluestore",
+ "db": null,
+ "batch_devices": [],
+ "db_vg": null,
+ "journal_vg": null,
+ "cluster": "ceph",
+ "osds_per_device": 1,
+ "containerized": "False",
+ "crush_device_class": null,
+ "report": false,
+ "data_vg": null,
+ "data": null,
+ "action": "inventory",
+ "journal_size": "5120"
+ }
+ },
+ "stdout_lines": [
+ "[{\"available\": true, \"rejected_reasons\": [], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 0, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sdc\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [], \"path\": \"/dev/sdc\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sda\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [{\"cluster_name\": \"ceph\", \"name\": \"osd-data-dcf8a88c-5546-42d2-afa4-b36f7fb23b66\", \"osd_id\": \"3\", \"cluster_fsid\": \"30d61f3e-7ee4-4bdc-8fe7-2ad5bb3f5317\", \"type\": \"block\", \"block_uuid\": \"fVqujC-9dgh-cN9W-1XD4-zVx1-1UdA-fUS3ha\", \"osd_fsid\": \"8b7cbeba-5e86-44ff-a5f3-2e7df77753fe\"}], \"path\": \"/dev/sda\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"noop\", \"rotational\": \"1\", \"vendor\": \"ATA\", \"human_readable_size\": \"50.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {}, \"rev\": \"2.5+\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/sdb\", \"support_discard\": \"\", \"model\": \"QEMU HARDDISK\", \"ro\": \"0\", \"nr_requests\": \"128\", \"size\": 53687091200.0}, \"lvs\": [{\"cluster_name\": \"ceph\", \"name\": \"osd-data-8c92e986-bd97-4b3d-ba77-2cb88e15d80f\", \"osd_id\": \"1\", \"cluster_fsid\": \"30d61f3e-7ee4-4bdc-8fe7-2ad5bb3f5317\", \"type\": \"block\", \"block_uuid\": \"mgzO7O-vUfu-H3mf-4R3K-2f97-ZMRH-SngBFP\", \"osd_fsid\": \"6d067688-3e1b-45f9-ad03-8abd19e9f117\"}], \"path\": \"/dev/sdb\"}, {\"available\": false, \"rejected_reasons\": [\"locked\"], \"sys_api\": {\"scheduler_mode\": \"mq-deadline\", \"rotational\": \"1\", \"vendor\": \"0x1af4\", \"human_readable_size\": \"41.00 GB\", \"sectors\": 0, \"sas_device_handle\": \"\", \"partitions\": {\"vda1\": {\"start\": \"2048\", \"holders\": [], \"sectorsize\": 512, \"sectors\": \"2048\", \"size\": \"1024.00 KB\"}, \"vda3\": {\"start\": \"2101248\", \"holders\": [\"dm-0\", \"dm-1\"], \"sectorsize\": 512, \"sectors\": \"81784832\", \"size\": \"39.00 GB\"}, \"vda2\": {\"start\": \"4096\", \"holders\": [], \"sectorsize\": 512, \"sectors\": \"2097152\", \"size\": \"1024.00 MB\"}}, \"rev\": \"\", \"sas_address\": \"\", \"locked\": 1, \"sectorsize\": \"512\", \"removable\": \"0\", \"path\": \"/dev/vda\", \"support_discard\": \"\", \"model\": \"\", \"ro\": \"0\", \"nr_requests\": \"256\", \"size\": 44023414784.0}, \"lvs\": [{\"comment\": \"not used by ceph\", \"name\": \"LogVol00\"}, {\"comment\": \"not used by ceph\", \"name\": \"LogVol01\"}], \"path\": \"/dev/vda\"}]"
+ ]
+ },
+ "pid": 482,
+ "play_uuid": "2016b900-e38f-0e09-19be-00000000000c",
+ "task_uuid": "2016b900-e38f-0e09-19be-000000000012",
+ "event_loop": null,
+ "playbook_uuid": "e80e66f2-4a78-4a96-aaf6-fbe473f11312",
+ "playbook": "storage-inventory.yml",
+ "task_action": "ceph_volume",
+ "host": "192.168.121.144",
+ "task_path": "/usr/share/ansible-runner-service/project/storage-inventory.yml:29"
+ },
+ "event": "runner_on_ok"
+ }
+ }
+ """
+
+ # Mocked response
+ mocked_response = mock.Mock()
+ mocked_response.text = EVENT_DATA
+
+ # The Ansible Runner Service client
+ ar_client = mock.Mock()
+ ar_client.http_get = mock.MagicMock(return_value=mocked_response)
+
+ logger = mock.Mock()
+
+ test_wizard = ProcessInventory(ar_client, logger)
+
+ def test_process(self):
+ """Test a normal call
+ """
+ operation_id = 12
+ nodes_list = self.test_wizard.process(operation_id, self.INVENTORY_EVENTS)
+
+ for key, dummy_data in self.INVENTORY_EVENTS.items():
+ http_request = EVENT_DATA_URL % (operation_id, key)
+ self.ar_client.http_get.assert_any_call(http_request)
+
+
+ # Only one host
+ self.assertTrue(len(nodes_list), 1)
+
+ # Host retrieved OK
+ self.assertEqual(nodes_list[0].name, "192.168.121.144")
+
+ # Devices
+ self.assertTrue(len(nodes_list[0].devices), 4)
+
+ expected_device_ids = ["/dev/sdc", "/dev/sda", "/dev/sdb", "/dev/vda"]
+ device_ids = [dev.id for dev in nodes_list[0].devices]
+
+ self.assertEqual(expected_device_ids, device_ids)
diff --git a/src/pybind/mgr/ansible/tox.ini b/src/pybind/mgr/ansible/tox.ini
new file mode 100644
index 00000000..ae9888a6
--- /dev/null
+++ b/src/pybind/mgr/ansible/tox.ini
@@ -0,0 +1,18 @@
+[tox]
+envlist = py27,py3
+skipsdist = true
+toxworkdir = {env:CEPH_BUILD_DIR}/ansible
+minversion = 2.8.1
+
+[testenv]
+deps =
+ pytest
+ mock
+ requests-mock
+setenv=
+ UNITTEST = true
+ py27: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.2
+ py3: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.3
+
+commands=
+ {envbindir}/py.test tests/
diff --git a/src/pybind/mgr/balancer/__init__.py b/src/pybind/mgr/balancer/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/balancer/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/balancer/module.py b/src/pybind/mgr/balancer/module.py
new file mode 100644
index 00000000..acca915d
--- /dev/null
+++ b/src/pybind/mgr/balancer/module.py
@@ -0,0 +1,1324 @@
+"""
+Balance PG distribution across OSDs.
+"""
+
+import copy
+import errno
+import json
+import math
+import random
+import six
+import time
+from mgr_module import MgrModule, CommandResult
+from threading import Event
+from mgr_module import CRUSHMap
+import datetime
+
+TIME_FORMAT = '%Y-%m-%d_%H:%M:%S'
+
+class MappingState:
+ def __init__(self, osdmap, raw_pg_stats, raw_pool_stats, desc=''):
+ self.desc = desc
+ self.osdmap = osdmap
+ self.osdmap_dump = self.osdmap.dump()
+ self.crush = osdmap.get_crush()
+ self.crush_dump = self.crush.dump()
+ self.raw_pg_stats = raw_pg_stats
+ self.raw_pool_stats = raw_pool_stats
+ self.pg_stat = {
+ i['pgid']: i['stat_sum'] for i in raw_pg_stats.get('pg_stats', [])
+ }
+ osd_poolids = [p['pool'] for p in self.osdmap_dump.get('pools', [])]
+ pg_poolids = [p['poolid'] for p in raw_pool_stats.get('pool_stats', [])]
+ self.poolids = set(osd_poolids) & set(pg_poolids)
+ self.pg_up = {}
+ self.pg_up_by_poolid = {}
+ for poolid in self.poolids:
+ self.pg_up_by_poolid[poolid] = osdmap.map_pool_pgs_up(poolid)
+ for a,b in six.iteritems(self.pg_up_by_poolid[poolid]):
+ self.pg_up[a] = b
+
+ def calc_misplaced_from(self, other_ms):
+ num = len(other_ms.pg_up)
+ misplaced = 0
+ for pgid, before in six.iteritems(other_ms.pg_up):
+ if before != self.pg_up.get(pgid, []):
+ misplaced += 1
+ if num > 0:
+ return float(misplaced) / float(num)
+ return 0.0
+
+class Plan:
+ def __init__(self, name, ms, pools):
+ self.mode = 'unknown'
+ self.name = name
+ self.initial = ms
+ self.pools = pools
+
+ self.osd_weights = {}
+ self.compat_ws = {}
+ self.inc = ms.osdmap.new_incremental()
+
+ def final_state(self):
+ self.inc.set_osd_reweights(self.osd_weights)
+ self.inc.set_crush_compat_weight_set_weights(self.compat_ws)
+ return MappingState(self.initial.osdmap.apply_incremental(self.inc),
+ self.initial.raw_pg_stats,
+ self.initial.raw_pool_stats,
+ 'plan %s final' % self.name)
+
+ def dump(self):
+ return json.dumps(self.inc.dump(), indent=4)
+
+ def show(self):
+ ls = []
+ ls.append('# starting osdmap epoch %d' % self.initial.osdmap.get_epoch())
+ ls.append('# starting crush version %d' %
+ self.initial.osdmap.get_crush_version())
+ ls.append('# mode %s' % self.mode)
+ if len(self.compat_ws) and \
+ not CRUSHMap.have_default_choose_args(self.initial.crush_dump):
+ ls.append('ceph osd crush weight-set create-compat')
+ for osd, weight in six.iteritems(self.compat_ws):
+ ls.append('ceph osd crush weight-set reweight-compat %s %f' %
+ (osd, weight))
+ for osd, weight in six.iteritems(self.osd_weights):
+ ls.append('ceph osd reweight osd.%d %f' % (osd, weight))
+ incdump = self.inc.dump()
+ for pgid in incdump.get('old_pg_upmap_items', []):
+ ls.append('ceph osd rm-pg-upmap-items %s' % pgid)
+ for item in incdump.get('new_pg_upmap_items', []):
+ osdlist = []
+ for m in item['mappings']:
+ osdlist += [m['from'], m['to']]
+ ls.append('ceph osd pg-upmap-items %s %s' %
+ (item['pgid'], ' '.join([str(a) for a in osdlist])))
+ return '\n'.join(ls)
+
+
+class Eval:
+ def __init__(self, ms):
+ self.ms = ms
+ self.root_ids = {} # root name -> id
+ self.pool_name = {} # pool id -> pool name
+ self.pool_id = {} # pool name -> id
+ self.pool_roots = {} # pool name -> root name
+ self.root_pools = {} # root name -> pools
+ self.target_by_root = {} # root name -> target weight map
+ self.count_by_pool = {}
+ self.count_by_root = {}
+ self.actual_by_pool = {} # pool -> by_* -> actual weight map
+ self.actual_by_root = {} # pool -> by_* -> actual weight map
+ self.total_by_pool = {} # pool -> by_* -> total
+ self.total_by_root = {} # root -> by_* -> total
+ self.stats_by_pool = {} # pool -> by_* -> stddev or avg -> value
+ self.stats_by_root = {} # root -> by_* -> stddev or avg -> value
+
+ self.score_by_pool = {}
+ self.score_by_root = {}
+
+ self.score = 0.0
+
+ def show(self, verbose=False):
+ if verbose:
+ r = self.ms.desc + '\n'
+ r += 'target_by_root %s\n' % self.target_by_root
+ r += 'actual_by_pool %s\n' % self.actual_by_pool
+ r += 'actual_by_root %s\n' % self.actual_by_root
+ r += 'count_by_pool %s\n' % self.count_by_pool
+ r += 'count_by_root %s\n' % self.count_by_root
+ r += 'total_by_pool %s\n' % self.total_by_pool
+ r += 'total_by_root %s\n' % self.total_by_root
+ r += 'stats_by_root %s\n' % self.stats_by_root
+ r += 'score_by_pool %s\n' % self.score_by_pool
+ r += 'score_by_root %s\n' % self.score_by_root
+ else:
+ r = self.ms.desc + ' '
+ r += 'score %f (lower is better)\n' % self.score
+ return r
+
+ def calc_stats(self, count, target, total):
+ num = max(len(target), 1)
+ r = {}
+ for t in ('pgs', 'objects', 'bytes'):
+ if total[t] == 0:
+ r[t] = {
+ 'avg': 0,
+ 'stddev': 0,
+ 'sum_weight': 0,
+ 'score': 0,
+ }
+ continue
+
+ avg = float(total[t]) / float(num)
+ dev = 0.0
+
+ # score is a measure of how uneven the data distribution is.
+ # score lies between [0, 1), 0 means perfect distribution.
+ score = 0.0
+ sum_weight = 0.0
+
+ for k, v in six.iteritems(count[t]):
+ # adjust/normalize by weight
+ if target[k]:
+ adjusted = float(v) / target[k] / float(num)
+ else:
+ adjusted = 0.0
+
+ # Overweighted devices and their weights are factors to calculate reweight_urgency.
+ # One 10% underfilled device with 5 2% overfilled devices, is arguably a better
+ # situation than one 10% overfilled with 5 2% underfilled devices
+ if adjusted > avg:
+ '''
+ F(x) = 2*phi(x) - 1, where phi(x) = cdf of standard normal distribution
+ x = (adjusted - avg)/avg.
+ Since, we're considering only over-weighted devices, x >= 0, and so phi(x) lies in [0.5, 1).
+ To bring range of F(x) in range [0, 1), we need to make the above modification.
+
+ In general, we need to use a function F(x), where x = (adjusted - avg)/avg
+ 1. which is bounded between 0 and 1, so that ultimately reweight_urgency will also be bounded.
+ 2. A larger value of x, should imply more urgency to reweight.
+ 3. Also, the difference between F(x) when x is large, should be minimal.
+ 4. The value of F(x) should get close to 1 (highest urgency to reweight) with steeply.
+
+ Could have used F(x) = (1 - e^(-x)). But that had slower convergence to 1, compared to the one currently in use.
+
+ cdf of standard normal distribution: https://stackoverflow.com/a/29273201
+ '''
+ score += target[k] * (math.erf(((adjusted - avg)/avg) / math.sqrt(2.0)))
+ sum_weight += target[k]
+ dev += (avg - adjusted) * (avg - adjusted)
+ stddev = math.sqrt(dev / float(max(num - 1, 1)))
+ score = score / max(sum_weight, 1)
+ r[t] = {
+ 'avg': avg,
+ 'stddev': stddev,
+ 'sum_weight': sum_weight,
+ 'score': score,
+ }
+ return r
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'active',
+ 'type': 'bool',
+ 'default': False,
+ 'desc': 'automatically balance PGs across cluster',
+ 'runtime': True,
+ },
+ {
+ 'name': 'begin_time',
+ 'type': 'str',
+ 'default': '0000',
+ 'desc': 'beginning time of day to automatically balance',
+ 'long_desc': 'This is a time of day in the format HHMM.',
+ 'runtime': True,
+ },
+ {
+ 'name': 'end_time',
+ 'type': 'str',
+ 'default': '2400',
+ 'desc': 'ending time of day to automatically balance',
+ 'long_desc': 'This is a time of day in the format HHMM.',
+ 'runtime': True,
+ },
+ {
+ 'name': 'begin_weekday',
+ 'type': 'uint',
+ 'default': 0,
+ 'min': 0,
+ 'max': 7,
+ 'desc': 'Restrict automatic balancing to this day of the week or later',
+ 'long_desc': '0 or 7 = Sunday, 1 = Monday, etc.',
+ 'runtime': True,
+ },
+ {
+ 'name': 'end_weekday',
+ 'type': 'uint',
+ 'default': 7,
+ 'min': 0,
+ 'max': 7,
+ 'desc': 'Restrict automatic balancing to days of the week earlier than this',
+ 'long_desc': '0 or 7 = Sunday, 1 = Monday, etc.',
+ 'runtime': True,
+ },
+ {
+ 'name': 'crush_compat_max_iterations',
+ 'type': 'uint',
+ 'default': 25,
+ 'min': 1,
+ 'max': 250,
+ 'desc': 'maximum number of iterations to attempt optimization',
+ 'runtime': True,
+ },
+ {
+ 'name': 'crush_compat_metrics',
+ 'type': 'str',
+ 'default': 'pgs,objects,bytes',
+ 'desc': 'metrics with which to calculate OSD utilization',
+ 'long_desc': 'Value is a list of one or more of "pgs", "objects", or "bytes", and indicates which metrics to use to balance utilization.',
+ 'runtime': True,
+ },
+ {
+ 'name': 'crush_compat_step',
+ 'type': 'float',
+ 'default': .5,
+ 'min': .001,
+ 'max': .999,
+ 'desc': 'aggressiveness of optimization',
+ 'long_desc': '.99 is very aggressive, .01 is less aggressive',
+ 'runtime': True,
+ },
+ {
+ 'name': 'min_score',
+ 'type': 'float',
+ 'default': 0,
+ 'desc': 'minimum score, below which no optimization is attempted',
+ 'runtime': True,
+ },
+ {
+ 'name': 'mode',
+ 'desc': 'Balancer mode',
+ 'default': 'none',
+ 'enum_allowed': ['none', 'crush-compat', 'upmap'],
+ 'runtime': True,
+ },
+ {
+ 'name': 'sleep_interval',
+ 'type': 'secs',
+ 'default': 60,
+ 'desc': 'how frequently to wake up and attempt optimization',
+ 'runtime': True,
+ },
+ {
+ 'name': 'upmap_max_iterations',
+ 'type': 'uint',
+ 'default': 10,
+ 'desc': 'maximum upmap optimization iterations',
+ 'runtime': True,
+ },
+ {
+ 'name': 'upmap_max_deviation',
+ 'type': 'int',
+ 'default': 5,
+ 'min': 1,
+ 'desc': 'deviation below which no optimization is attempted',
+ 'long_desc': 'If the number of PGs are within this count then no optimization is attempted',
+ 'runtime': True,
+ },
+ {
+ 'name': 'pool_ids',
+ 'type': 'str',
+ 'default': '',
+ 'desc': 'pools which the automatic balancing will be limited to',
+ 'runtime': True,
+ },
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "balancer status",
+ "desc": "Show balancer status",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer mode name=mode,type=CephChoices,strings=none|crush-compat|upmap",
+ "desc": "Set balancer mode",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer on",
+ "desc": "Enable automatic balancing",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer off",
+ "desc": "Disable automatic balancing",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer pool ls",
+ "desc": "List automatic balancing pools. "
+ "Note that empty list means all existing pools will be automatic balancing targets, "
+ "which is the default behaviour of balancer.",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer pool add name=pools,type=CephString,n=N",
+ "desc": "Enable automatic balancing for specific pools",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer pool rm name=pools,type=CephString,n=N",
+ "desc": "Disable automatic balancing for specific pools",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer eval name=option,type=CephString,req=false",
+ "desc": "Evaluate data distribution for the current cluster or specific pool or specific plan",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer eval-verbose name=option,type=CephString,req=false",
+ "desc": "Evaluate data distribution for the current cluster or specific pool or specific plan (verbosely)",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer optimize name=plan,type=CephString name=pools,type=CephString,n=N,req=false",
+ "desc": "Run optimizer to create a new plan",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer show name=plan,type=CephString",
+ "desc": "Show details of an optimization plan",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer rm name=plan,type=CephString",
+ "desc": "Discard an optimization plan",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer reset",
+ "desc": "Discard all optimization plans",
+ "perm": "rw",
+ },
+ {
+ "cmd": "balancer dump name=plan,type=CephString",
+ "desc": "Show an optimization plan",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer ls",
+ "desc": "List all plans",
+ "perm": "r",
+ },
+ {
+ "cmd": "balancer execute name=plan,type=CephString",
+ "desc": "Execute an optimization plan",
+ "perm": "rw",
+ },
+ ]
+ active = False
+ run = True
+ plans = {}
+ mode = ''
+ optimizing = False
+ last_optimize_started = ''
+ last_optimize_duration = ''
+ optimize_result = ''
+ success_string = 'Optimization plan created successfully'
+ in_progress_string = 'in progress'
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.event = Event()
+
+ def handle_command(self, inbuf, command):
+ self.log.warn("Handling command: '%s'" % str(command))
+ if command['prefix'] == 'balancer status':
+ s = {
+ 'plans': list(self.plans.keys()),
+ 'active': self.active,
+ 'last_optimize_started': self.last_optimize_started,
+ 'last_optimize_duration': self.last_optimize_duration,
+ 'optimize_result': self.optimize_result,
+ 'mode': self.get_module_option('mode'),
+ }
+ return (0, json.dumps(s, indent=4), '')
+ elif command['prefix'] == 'balancer mode':
+ if command['mode'] == 'upmap':
+ min_compat_client = self.get_osdmap().dump().get('require_min_compat_client', '')
+ if min_compat_client < 'luminous': # works well because version is alphabetized..
+ warn = 'min_compat_client "%s" ' \
+ '< "luminous", which is required for pg-upmap. ' \
+ 'Try "ceph osd set-require-min-compat-client luminous" ' \
+ 'before enabling this mode' % min_compat_client
+ return (-errno.EPERM, '', warn)
+ elif command['mode'] == 'crush-compat':
+ ms = MappingState(self.get_osdmap(),
+ self.get("pg_stats"),
+ self.get("pool_stats"),
+ 'initialize compat weight-set')
+ self.get_compat_weight_set_weights(ms) # ignore error
+ self.set_module_option('mode', command['mode'])
+ return (0, '', '')
+ elif command['prefix'] == 'balancer on':
+ if not self.active:
+ self.set_module_option('active', 'true')
+ self.active = True
+ self.event.set()
+ return (0, '', '')
+ elif command['prefix'] == 'balancer off':
+ if self.active:
+ self.set_module_option('active', 'false')
+ self.active = False
+ self.event.set()
+ return (0, '', '')
+ elif command['prefix'] == 'balancer pool ls':
+ pool_ids = self.get_module_option('pool_ids')
+ if pool_ids == '':
+ return (0, '', '')
+ pool_ids = pool_ids.split(',')
+ pool_ids = [int(p) for p in pool_ids]
+ pool_name_by_id = dict((p['pool'], p['pool_name']) for p in self.get_osdmap().dump().get('pools', []))
+ should_prune = False
+ final_ids = []
+ final_names = []
+ for p in pool_ids:
+ if p in pool_name_by_id:
+ final_ids.append(p)
+ final_names.append(pool_name_by_id[p])
+ else:
+ should_prune = True
+ if should_prune: # some pools were gone, prune
+ self.set_module_option('pool_ids', ','.join(final_ids))
+ return (0, json.dumps(final_names, indent=4), '')
+ elif command['prefix'] == 'balancer pool add':
+ raw_names = command['pools']
+ pool_id_by_name = dict((p['pool_name'], p['pool']) for p in self.get_osdmap().dump().get('pools', []))
+ invalid_names = [p for p in raw_names if p not in pool_id_by_name]
+ if invalid_names:
+ return (-errno.EINVAL, '', 'pool(s) %s not found' % invalid_names)
+ to_add = [str(pool_id_by_name[p]) for p in raw_names if p in pool_id_by_name]
+ existing = self.get_module_option('pool_ids')
+ final = to_add
+ if existing != '':
+ existing = existing.split(',')
+ final = set(to_add) | set(existing)
+ self.set_module_option('pool_ids', ','.join(final))
+ return (0, '', '')
+ elif command['prefix'] == 'balancer pool rm':
+ raw_names = command['pools']
+ existing = self.get_module_option('pool_ids')
+ if existing == '': # for idempotence
+ return (0, '', '')
+ existing = existing.split(',')
+ osdmap = self.get_osdmap()
+ pool_ids = [str(p['pool']) for p in osdmap.dump().get('pools', [])]
+ pool_id_by_name = dict((p['pool_name'], p['pool']) for p in osdmap.dump().get('pools', []))
+ final = [p for p in existing if p in pool_ids]
+ to_delete = [str(pool_id_by_name[p]) for p in raw_names if p in pool_id_by_name]
+ final = set(final) - set(to_delete)
+ self.set_module_option('pool_ids', ','.join(final))
+ return (0, '', '')
+ elif command['prefix'] == 'balancer eval' or command['prefix'] == 'balancer eval-verbose':
+ verbose = command['prefix'] == 'balancer eval-verbose'
+ pools = []
+ if 'option' in command:
+ plan = self.plans.get(command['option'])
+ if not plan:
+ # not a plan, does it look like a pool?
+ osdmap = self.get_osdmap()
+ valid_pool_names = [p['pool_name'] for p in osdmap.dump().get('pools', [])]
+ option = command['option']
+ if option not in valid_pool_names:
+ return (-errno.EINVAL, '', 'option "%s" not a plan or a pool' % option)
+ pools.append(option)
+ ms = MappingState(osdmap, self.get("pg_stats"), self.get("pool_stats"), 'pool "%s"' % option)
+ else:
+ pools = plan.pools
+ ms = plan.final_state()
+ else:
+ ms = MappingState(self.get_osdmap(),
+ self.get("pg_stats"),
+ self.get("pool_stats"),
+ 'current cluster')
+ return (0, self.evaluate(ms, pools, verbose=verbose), '')
+ elif command['prefix'] == 'balancer optimize':
+ # The GIL can be release by the active balancer, so disallow when active
+ if self.active:
+ return (-errno.EINVAL, '', 'Balancer enabled, disable to optimize manually')
+ if self.optimizing:
+ return (-errno.EINVAL, '', 'Balancer finishing up....try again')
+ pools = []
+ if 'pools' in command:
+ pools = command['pools']
+ osdmap = self.get_osdmap()
+ valid_pool_names = [p['pool_name'] for p in osdmap.dump().get('pools', [])]
+ invalid_pool_names = []
+ for p in pools:
+ if p not in valid_pool_names:
+ invalid_pool_names.append(p)
+ if len(invalid_pool_names):
+ return (-errno.EINVAL, '', 'pools %s not found' % invalid_pool_names)
+ plan = self.plan_create(command['plan'], osdmap, pools)
+ self.last_optimize_started = time.asctime(time.localtime())
+ self.optimize_result = self.in_progress_string
+ start = time.time()
+ r, detail = self.optimize(plan)
+ end = time.time()
+ self.last_optimize_duration = str(datetime.timedelta(seconds=(end - start)))
+ if r == 0:
+ # Add plan if an optimization was created
+ self.optimize_result = self.success_string
+ self.plans[command['plan']] = plan
+ else:
+ self.optimize_result = detail
+ return (r, '', detail)
+ elif command['prefix'] == 'balancer rm':
+ self.plan_rm(command['plan'])
+ return (0, '', '')
+ elif command['prefix'] == 'balancer reset':
+ self.plans = {}
+ return (0, '', '')
+ elif command['prefix'] == 'balancer ls':
+ return (0, json.dumps([p for p in self.plans], indent=4), '')
+ elif command['prefix'] == 'balancer dump':
+ plan = self.plans.get(command['plan'])
+ if not plan:
+ return (-errno.ENOENT, '', 'plan %s not found' % command['plan'])
+ return (0, plan.dump(), '')
+ elif command['prefix'] == 'balancer show':
+ plan = self.plans.get(command['plan'])
+ if not plan:
+ return (-errno.ENOENT, '', 'plan %s not found' % command['plan'])
+ return (0, plan.show(), '')
+ elif command['prefix'] == 'balancer execute':
+ # The GIL can be release by the active balancer, so disallow when active
+ if self.active:
+ return (-errno.EINVAL, '', 'Balancer enabled, disable to execute a plan')
+ if self.optimizing:
+ return (-errno.EINVAL, '', 'Balancer finishing up....try again')
+ plan = self.plans.get(command['plan'])
+ if not plan:
+ return (-errno.ENOENT, '', 'plan %s not found' % command['plan'])
+ r, detail = self.execute(plan)
+ self.plan_rm(command['plan'])
+ return (r, '', detail)
+ else:
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(command['prefix']))
+
+ def shutdown(self):
+ self.log.info('Stopping')
+ self.run = False
+ self.event.set()
+
+ def time_permit(self):
+ local_time = time.localtime()
+ time_of_day = time.strftime('%H%M', local_time)
+ weekday = (local_time.tm_wday + 1) % 7 # be compatible with C
+ permit = False
+
+ begin_time = self.get_module_option('begin_time')
+ end_time = self.get_module_option('end_time')
+ if begin_time <= end_time:
+ permit = begin_time <= time_of_day < end_time
+ else:
+ permit = time_of_day >= begin_time or time_of_day < end_time
+ if not permit:
+ self.log.debug("should run between %s - %s, now %s, skipping",
+ begin_time, end_time, time_of_day)
+ return False
+
+ begin_weekday = self.get_module_option('begin_weekday')
+ end_weekday = self.get_module_option('end_weekday')
+ if begin_weekday <= end_weekday:
+ permit = begin_weekday <= weekday < end_weekday
+ else:
+ permit = weekday >= begin_weekday or weekday < end_weekday
+ if not permit:
+ self.log.debug("should run between weekday %d - %d, now %d, skipping",
+ begin_weekday, end_weekday, weekday)
+ return False
+
+ return True
+
+ def serve(self):
+ self.log.info('Starting')
+ while self.run:
+ self.active = self.get_module_option('active')
+ sleep_interval = self.get_module_option('sleep_interval')
+ self.log.debug('Waking up [%s, now %s]',
+ "active" if self.active else "inactive",
+ time.strftime(TIME_FORMAT, time.localtime()))
+ if self.active and self.time_permit():
+ self.log.debug('Running')
+ name = 'auto_%s' % time.strftime(TIME_FORMAT, time.gmtime())
+ osdmap = self.get_osdmap()
+ allow = self.get_module_option('pool_ids')
+ final = []
+ if allow != '':
+ allow = allow.split(',')
+ valid = [str(p['pool']) for p in osdmap.dump().get('pools', [])]
+ final = set(allow) & set(valid)
+ if set(allow) - set(valid): # some pools were gone, prune
+ self.set_module_option('pool_ids', ','.join(final))
+ pool_name_by_id = dict((p['pool'], p['pool_name']) for p in osdmap.dump().get('pools', []))
+ final = [int(p) for p in final]
+ final = [pool_name_by_id[p] for p in final if p in pool_name_by_id]
+ plan = self.plan_create(name, osdmap, final)
+ self.optimizing = True
+ self.last_optimize_started = time.asctime(time.localtime())
+ self.optimize_result = self.in_progress_string
+ start = time.time()
+ r, detail = self.optimize(plan)
+ end = time.time()
+ self.last_optimize_duration = str(datetime.timedelta(seconds=(end - start)))
+ if r == 0:
+ self.optimize_result = self.success_string
+ self.execute(plan)
+ else:
+ self.optimize_result = detail
+ self.optimizing = False
+ self.log.debug('Sleeping for %d', sleep_interval)
+ self.event.wait(sleep_interval)
+ self.event.clear()
+
+ def plan_create(self, name, osdmap, pools):
+ plan = Plan(name,
+ MappingState(osdmap,
+ self.get("pg_stats"),
+ self.get("pool_stats"),
+ 'plan %s initial' % name),
+ pools)
+ return plan
+
+ def plan_rm(self, name):
+ if name in self.plans:
+ del self.plans[name]
+
+ def calc_eval(self, ms, pools):
+ pe = Eval(ms)
+ pool_rule = {}
+ pool_info = {}
+ for p in ms.osdmap_dump.get('pools',[]):
+ if len(pools) and p['pool_name'] not in pools:
+ continue
+ # skip dead or not-yet-ready pools too
+ if p['pool'] not in ms.poolids:
+ continue
+ pe.pool_name[p['pool']] = p['pool_name']
+ pe.pool_id[p['pool_name']] = p['pool']
+ pool_rule[p['pool_name']] = p['crush_rule']
+ pe.pool_roots[p['pool_name']] = []
+ pool_info[p['pool_name']] = p
+ if len(pool_info) == 0:
+ return pe
+ self.log.debug('pool_name %s' % pe.pool_name)
+ self.log.debug('pool_id %s' % pe.pool_id)
+ self.log.debug('pools %s' % pools)
+ self.log.debug('pool_rule %s' % pool_rule)
+
+ osd_weight = { a['osd']: a['weight']
+ for a in ms.osdmap_dump.get('osds',[]) if a['weight'] > 0 }
+
+ # get expected distributions by root
+ actual_by_root = {}
+ rootids = ms.crush.find_takes()
+ roots = []
+ for rootid in rootids:
+ ls = ms.osdmap.get_pools_by_take(rootid)
+ want = []
+ # find out roots associating with pools we are passed in
+ for candidate in ls:
+ if candidate in pe.pool_name:
+ want.append(candidate)
+ if len(want) == 0:
+ continue
+ root = ms.crush.get_item_name(rootid)
+ pe.root_pools[root] = []
+ for poolid in want:
+ pe.pool_roots[pe.pool_name[poolid]].append(root)
+ pe.root_pools[root].append(pe.pool_name[poolid])
+ pe.root_ids[root] = rootid
+ roots.append(root)
+ weight_map = ms.crush.get_take_weight_osd_map(rootid)
+ adjusted_map = {
+ osd: cw * osd_weight[osd]
+ for osd,cw in six.iteritems(weight_map) if osd in osd_weight and cw > 0
+ }
+ sum_w = sum(adjusted_map.values())
+ assert len(adjusted_map) == 0 or sum_w > 0
+ pe.target_by_root[root] = { osd: w / sum_w
+ for osd,w in six.iteritems(adjusted_map) }
+ actual_by_root[root] = {
+ 'pgs': {},
+ 'objects': {},
+ 'bytes': {},
+ }
+ for osd in pe.target_by_root[root]:
+ actual_by_root[root]['pgs'][osd] = 0
+ actual_by_root[root]['objects'][osd] = 0
+ actual_by_root[root]['bytes'][osd] = 0
+ pe.total_by_root[root] = {
+ 'pgs': 0,
+ 'objects': 0,
+ 'bytes': 0,
+ }
+ self.log.debug('pool_roots %s' % pe.pool_roots)
+ self.log.debug('root_pools %s' % pe.root_pools)
+ self.log.debug('target_by_root %s' % pe.target_by_root)
+
+ # pool and root actual
+ for pool, pi in six.iteritems(pool_info):
+ poolid = pi['pool']
+ pm = ms.pg_up_by_poolid[poolid]
+ pgs = 0
+ objects = 0
+ bytes = 0
+ pgs_by_osd = {}
+ objects_by_osd = {}
+ bytes_by_osd = {}
+ for pgid, up in six.iteritems(pm):
+ for osd in [int(osd) for osd in up]:
+ if osd == CRUSHMap.ITEM_NONE:
+ continue
+ if osd not in pgs_by_osd:
+ pgs_by_osd[osd] = 0
+ objects_by_osd[osd] = 0
+ bytes_by_osd[osd] = 0
+ pgs_by_osd[osd] += 1
+ objects_by_osd[osd] += ms.pg_stat[pgid]['num_objects']
+ bytes_by_osd[osd] += ms.pg_stat[pgid]['num_bytes']
+ # pick a root to associate this pg instance with.
+ # note that this is imprecise if the roots have
+ # overlapping children.
+ # FIXME: divide bytes by k for EC pools.
+ for root in pe.pool_roots[pool]:
+ if osd in pe.target_by_root[root]:
+ actual_by_root[root]['pgs'][osd] += 1
+ actual_by_root[root]['objects'][osd] += ms.pg_stat[pgid]['num_objects']
+ actual_by_root[root]['bytes'][osd] += ms.pg_stat[pgid]['num_bytes']
+ pgs += 1
+ objects += ms.pg_stat[pgid]['num_objects']
+ bytes += ms.pg_stat[pgid]['num_bytes']
+ pe.total_by_root[root]['pgs'] += 1
+ pe.total_by_root[root]['objects'] += ms.pg_stat[pgid]['num_objects']
+ pe.total_by_root[root]['bytes'] += ms.pg_stat[pgid]['num_bytes']
+ break
+ pe.count_by_pool[pool] = {
+ 'pgs': {
+ k: v
+ for k, v in six.iteritems(pgs_by_osd)
+ },
+ 'objects': {
+ k: v
+ for k, v in six.iteritems(objects_by_osd)
+ },
+ 'bytes': {
+ k: v
+ for k, v in six.iteritems(bytes_by_osd)
+ },
+ }
+ pe.actual_by_pool[pool] = {
+ 'pgs': {
+ k: float(v) / float(max(pgs, 1))
+ for k, v in six.iteritems(pgs_by_osd)
+ },
+ 'objects': {
+ k: float(v) / float(max(objects, 1))
+ for k, v in six.iteritems(objects_by_osd)
+ },
+ 'bytes': {
+ k: float(v) / float(max(bytes, 1))
+ for k, v in six.iteritems(bytes_by_osd)
+ },
+ }
+ pe.total_by_pool[pool] = {
+ 'pgs': pgs,
+ 'objects': objects,
+ 'bytes': bytes,
+ }
+ for root in pe.total_by_root:
+ pe.count_by_root[root] = {
+ 'pgs': {
+ k: float(v)
+ for k, v in six.iteritems(actual_by_root[root]['pgs'])
+ },
+ 'objects': {
+ k: float(v)
+ for k, v in six.iteritems(actual_by_root[root]['objects'])
+ },
+ 'bytes': {
+ k: float(v)
+ for k, v in six.iteritems(actual_by_root[root]['bytes'])
+ },
+ }
+ pe.actual_by_root[root] = {
+ 'pgs': {
+ k: float(v) / float(max(pe.total_by_root[root]['pgs'], 1))
+ for k, v in six.iteritems(actual_by_root[root]['pgs'])
+ },
+ 'objects': {
+ k: float(v) / float(max(pe.total_by_root[root]['objects'], 1))
+ for k, v in six.iteritems(actual_by_root[root]['objects'])
+ },
+ 'bytes': {
+ k: float(v) / float(max(pe.total_by_root[root]['bytes'], 1))
+ for k, v in six.iteritems(actual_by_root[root]['bytes'])
+ },
+ }
+ self.log.debug('actual_by_pool %s' % pe.actual_by_pool)
+ self.log.debug('actual_by_root %s' % pe.actual_by_root)
+
+ # average and stddev and score
+ pe.stats_by_root = {
+ a: pe.calc_stats(
+ b,
+ pe.target_by_root[a],
+ pe.total_by_root[a]
+ ) for a, b in six.iteritems(pe.count_by_root)
+ }
+ self.log.debug('stats_by_root %s' % pe.stats_by_root)
+
+ # the scores are already normalized
+ pe.score_by_root = {
+ r: {
+ 'pgs': pe.stats_by_root[r]['pgs']['score'],
+ 'objects': pe.stats_by_root[r]['objects']['score'],
+ 'bytes': pe.stats_by_root[r]['bytes']['score'],
+ } for r in pe.total_by_root.keys()
+ }
+ self.log.debug('score_by_root %s' % pe.score_by_root)
+
+ # get the list of score metrics, comma separated
+ metrics = self.get_module_option('crush_compat_metrics').split(',')
+
+ # total score is just average of normalized stddevs
+ pe.score = 0.0
+ for r, vs in six.iteritems(pe.score_by_root):
+ for k, v in six.iteritems(vs):
+ if k in metrics:
+ pe.score += v
+ pe.score /= len(metrics) * len(roots)
+ return pe
+
+ def evaluate(self, ms, pools, verbose=False):
+ pe = self.calc_eval(ms, pools)
+ return pe.show(verbose=verbose)
+
+ def optimize(self, plan):
+ self.log.info('Optimize plan %s' % plan.name)
+ plan.mode = self.get_module_option('mode')
+ max_misplaced = float(self.get_ceph_option('target_max_misplaced_ratio'))
+ self.log.info('Mode %s, max misplaced %f' %
+ (plan.mode, max_misplaced))
+
+ info = self.get('pg_status')
+ unknown = info.get('unknown_pgs_ratio', 0.0)
+ degraded = info.get('degraded_ratio', 0.0)
+ inactive = info.get('inactive_pgs_ratio', 0.0)
+ misplaced = info.get('misplaced_ratio', 0.0)
+ self.log.debug('unknown %f degraded %f inactive %f misplaced %g',
+ unknown, degraded, inactive, misplaced)
+ if unknown > 0.0:
+ detail = 'Some PGs (%f) are unknown; try again later' % unknown
+ self.log.info(detail)
+ return -errno.EAGAIN, detail
+ elif degraded > 0.0:
+ detail = 'Some objects (%f) are degraded; try again later' % degraded
+ self.log.info(detail)
+ return -errno.EAGAIN, detail
+ elif inactive > 0.0:
+ detail = 'Some PGs (%f) are inactive; try again later' % inactive
+ self.log.info(detail)
+ return -errno.EAGAIN, detail
+ elif misplaced >= max_misplaced:
+ detail = 'Too many objects (%f > %f) are misplaced; ' \
+ 'try again later' % (misplaced, max_misplaced)
+ self.log.info(detail)
+ return -errno.EAGAIN, detail
+ else:
+ if plan.mode == 'upmap':
+ return self.do_upmap(plan)
+ elif plan.mode == 'crush-compat':
+ return self.do_crush_compat(plan)
+ elif plan.mode == 'none':
+ detail = 'Please do "ceph balancer mode" to choose a valid mode first'
+ self.log.info('Idle')
+ return -errno.ENOEXEC, detail
+ else:
+ detail = 'Unrecognized mode %s' % plan.mode
+ self.log.info(detail)
+ return -errno.EINVAL, detail
+ ##
+
+ def do_upmap(self, plan):
+ self.log.info('do_upmap')
+ max_iterations = self.get_module_option('upmap_max_iterations')
+ max_deviation = self.get_module_option('upmap_max_deviation')
+
+ ms = plan.initial
+ if len(plan.pools):
+ pools = plan.pools
+ else: # all
+ pools = [str(i['pool_name']) for i in ms.osdmap_dump.get('pools',[])]
+ if len(pools) == 0:
+ detail = 'No pools available'
+ self.log.info(detail)
+ return -errno.ENOENT, detail
+ # shuffle pool list so they all get equal (in)attention
+ random.shuffle(pools)
+ self.log.info('pools %s' % pools)
+
+ adjusted_pools = []
+ inc = plan.inc
+ total_did = 0
+ left = max_iterations
+ osdmap_dump = self.get_osdmap().dump()
+ pools_with_pg_merge = [p['pool_name'] for p in osdmap_dump.get('pools', [])
+ if p['pg_num'] > p['pg_num_target']]
+ crush_rule_by_pool_name = dict((p['pool_name'], p['crush_rule']) for p in osdmap_dump.get('pools', []))
+ for pool in pools:
+ if pool not in crush_rule_by_pool_name:
+ self.log.info('pool %s does not exist' % pool)
+ continue
+ if pool in pools_with_pg_merge:
+ self.log.info('pool %s has pending PG(s) for merging, skipping for now' % pool)
+ continue
+ adjusted_pools.append(pool)
+ # shuffle so all pools get equal (in)attention
+ random.shuffle(adjusted_pools)
+ for pool in adjusted_pools:
+ did = ms.osdmap.calc_pg_upmaps(inc, max_deviation, left, [pool])
+ total_did += did
+ left -= did
+ if left <= 0:
+ break
+ self.log.info('prepared %d/%d changes' % (total_did, max_iterations))
+ if total_did == 0:
+ return -errno.EALREADY, 'Unable to find further optimization, ' \
+ 'or pool(s) pg_num is decreasing, ' \
+ 'or distribution is already perfect'
+ return 0, ''
+
+ def do_crush_compat(self, plan):
+ self.log.info('do_crush_compat')
+ max_iterations = self.get_module_option('crush_compat_max_iterations')
+ if max_iterations < 1:
+ return -errno.EINVAL, '"crush_compat_max_iterations" must be >= 1'
+ step = self.get_module_option('crush_compat_step')
+ if step <= 0 or step >= 1.0:
+ return -errno.EINVAL, '"crush_compat_step" must be in (0, 1)'
+ max_misplaced = float(self.get_ceph_option('target_max_misplaced_ratio'))
+ min_pg_per_osd = 2
+
+ ms = plan.initial
+ osdmap = ms.osdmap
+ crush = osdmap.get_crush()
+ pe = self.calc_eval(ms, plan.pools)
+ min_score_to_optimize = self.get_module_option('min_score')
+ if pe.score <= min_score_to_optimize:
+ if pe.score == 0:
+ detail = 'Distribution is already perfect'
+ else:
+ detail = 'score %f <= min_score %f, will not optimize' \
+ % (pe.score, min_score_to_optimize)
+ self.log.info(detail)
+ return -errno.EALREADY, detail
+
+ # get current osd reweights
+ orig_osd_weight = { a['osd']: a['weight']
+ for a in ms.osdmap_dump.get('osds',[]) }
+ reweighted_osds = [ a for a,b in six.iteritems(orig_osd_weight)
+ if b < 1.0 and b > 0.0 ]
+
+ # get current compat weight-set weights
+ orig_ws = self.get_compat_weight_set_weights(ms)
+ if not orig_ws:
+ return -errno.EAGAIN, 'compat weight-set not available'
+ orig_ws = { a: b for a, b in six.iteritems(orig_ws) if a >= 0 }
+
+ # Make sure roots don't overlap their devices. If so, we
+ # can't proceed.
+ roots = list(pe.target_by_root.keys())
+ self.log.debug('roots %s', roots)
+ visited = {}
+ overlap = {}
+ root_ids = {}
+ for root, wm in six.iteritems(pe.target_by_root):
+ for osd in wm:
+ if osd in visited:
+ if osd not in overlap:
+ overlap[osd] = [ visited[osd] ]
+ overlap[osd].append(root)
+ visited[osd] = root
+ if len(overlap) > 0:
+ detail = 'Some osds belong to multiple subtrees: %s' % \
+ overlap
+ self.log.error(detail)
+ return -errno.EOPNOTSUPP, detail
+
+ # rebalance by pgs, objects, or bytes
+ metrics = self.get_module_option('crush_compat_metrics').split(',')
+ key = metrics[0] # balancing using the first score metric
+ if key not in ['pgs', 'bytes', 'objects']:
+ self.log.warn("Invalid crush_compat balancing key %s. Using 'pgs'." % key)
+ key = 'pgs'
+
+ # go
+ best_ws = copy.deepcopy(orig_ws)
+ best_ow = copy.deepcopy(orig_osd_weight)
+ best_pe = pe
+ left = max_iterations
+ bad_steps = 0
+ next_ws = copy.deepcopy(best_ws)
+ next_ow = copy.deepcopy(best_ow)
+ while left > 0:
+ # adjust
+ self.log.debug('best_ws %s' % best_ws)
+ random.shuffle(roots)
+ for root in roots:
+ pools = best_pe.root_pools[root]
+ osds = len(best_pe.target_by_root[root])
+ min_pgs = osds * min_pg_per_osd
+ if best_pe.total_by_root[root][key] < min_pgs:
+ self.log.info('Skipping root %s (pools %s), total pgs %d '
+ '< minimum %d (%d per osd)',
+ root, pools,
+ best_pe.total_by_root[root][key],
+ min_pgs, min_pg_per_osd)
+ continue
+ self.log.info('Balancing root %s (pools %s) by %s' %
+ (root, pools, key))
+ target = best_pe.target_by_root[root]
+ actual = best_pe.actual_by_root[root][key]
+ queue = sorted(actual.keys(),
+ key=lambda osd: -abs(target[osd] - actual[osd]))
+ for osd in queue:
+ if orig_osd_weight[osd] == 0:
+ self.log.debug('skipping out osd.%d', osd)
+ else:
+ deviation = target[osd] - actual[osd]
+ if deviation == 0:
+ break
+ self.log.debug('osd.%d deviation %f', osd, deviation)
+ weight = best_ws[osd]
+ ow = orig_osd_weight[osd]
+ if actual[osd] > 0:
+ calc_weight = target[osd] / actual[osd] * weight * ow
+ else:
+ # for newly created osds, reset calc_weight at target value
+ # this way weight-set will end up absorbing *step* of its
+ # target (final) value at the very beginning and slowly catch up later.
+ # note that if this turns out causing too many misplaced
+ # pgs, then we'll reduce step and retry
+ calc_weight = target[osd]
+ new_weight = weight * (1.0 - step) + calc_weight * step
+ self.log.debug('Reweight osd.%d %f -> %f', osd, weight,
+ new_weight)
+ next_ws[osd] = new_weight
+ if ow < 1.0:
+ new_ow = min(1.0, max(step + (1.0 - step) * ow,
+ ow + .005))
+ self.log.debug('Reweight osd.%d reweight %f -> %f',
+ osd, ow, new_ow)
+ next_ow[osd] = new_ow
+
+ # normalize weights under this root
+ root_weight = crush.get_item_weight(pe.root_ids[root])
+ root_sum = sum(b for a,b in six.iteritems(next_ws)
+ if a in target.keys())
+ if root_sum > 0 and root_weight > 0:
+ factor = root_sum / root_weight
+ self.log.debug('normalizing root %s %d, weight %f, '
+ 'ws sum %f, factor %f',
+ root, pe.root_ids[root], root_weight,
+ root_sum, factor)
+ for osd in actual.keys():
+ next_ws[osd] = next_ws[osd] / factor
+
+ # recalc
+ plan.compat_ws = copy.deepcopy(next_ws)
+ next_ms = plan.final_state()
+ next_pe = self.calc_eval(next_ms, plan.pools)
+ next_misplaced = next_ms.calc_misplaced_from(ms)
+ self.log.debug('Step result score %f -> %f, misplacing %f',
+ best_pe.score, next_pe.score, next_misplaced)
+
+ if next_misplaced > max_misplaced:
+ if best_pe.score < pe.score:
+ self.log.debug('Step misplaced %f > max %f, stopping',
+ next_misplaced, max_misplaced)
+ break
+ step /= 2.0
+ next_ws = copy.deepcopy(best_ws)
+ next_ow = copy.deepcopy(best_ow)
+ self.log.debug('Step misplaced %f > max %f, reducing step to %f',
+ next_misplaced, max_misplaced, step)
+ else:
+ if next_pe.score > best_pe.score * 1.0001:
+ bad_steps += 1
+ if bad_steps < 5 and random.randint(0, 100) < 70:
+ self.log.debug('Score got worse, taking another step')
+ else:
+ step /= 2.0
+ next_ws = copy.deepcopy(best_ws)
+ next_ow = copy.deepcopy(best_ow)
+ self.log.debug('Score got worse, trying smaller step %f',
+ step)
+ else:
+ bad_steps = 0
+ best_pe = next_pe
+ best_ws = copy.deepcopy(next_ws)
+ best_ow = copy.deepcopy(next_ow)
+ if best_pe.score == 0:
+ break
+ left -= 1
+
+ # allow a small regression if we are phasing out osd weights
+ fudge = 0
+ if best_ow != orig_osd_weight:
+ fudge = .001
+
+ if best_pe.score < pe.score + fudge:
+ self.log.info('Success, score %f -> %f', pe.score, best_pe.score)
+ plan.compat_ws = best_ws
+ for osd, w in six.iteritems(best_ow):
+ if w != orig_osd_weight[osd]:
+ self.log.debug('osd.%d reweight %f', osd, w)
+ plan.osd_weights[osd] = w
+ return 0, ''
+ else:
+ self.log.info('Failed to find further optimization, score %f',
+ pe.score)
+ plan.compat_ws = {}
+ return -errno.EDOM, 'Unable to find further optimization, ' \
+ 'change balancer mode and retry might help'
+
+ def get_compat_weight_set_weights(self, ms):
+ if not CRUSHMap.have_default_choose_args(ms.crush_dump):
+ # enable compat weight-set first
+ self.log.debug('ceph osd crush weight-set create-compat')
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd crush weight-set create-compat',
+ 'format': 'json',
+ }), '')
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.error('Error creating compat weight-set')
+ return
+
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd crush dump',
+ 'format': 'json',
+ }), '')
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.error('Error dumping crush map')
+ return
+ try:
+ crushmap = json.loads(outb)
+ except:
+ raise RuntimeError('unable to parse crush map')
+ else:
+ crushmap = ms.crush_dump
+
+ raw = CRUSHMap.get_default_choose_args(crushmap)
+ weight_set = {}
+ for b in raw:
+ bucket = None
+ for t in crushmap['buckets']:
+ if t['id'] == b['bucket_id']:
+ bucket = t
+ break
+ if not bucket:
+ raise RuntimeError('could not find bucket %s' % b['bucket_id'])
+ self.log.debug('bucket items %s' % bucket['items'])
+ self.log.debug('weight set %s' % b['weight_set'][0])
+ if len(bucket['items']) != len(b['weight_set'][0]):
+ raise RuntimeError('weight-set size does not match bucket items')
+ for pos in range(len(bucket['items'])):
+ weight_set[bucket['items'][pos]['id']] = b['weight_set'][0][pos]
+
+ self.log.debug('weight_set weights %s' % weight_set)
+ return weight_set
+
+ def do_crush(self):
+ self.log.info('do_crush (not yet implemented)')
+
+ def do_osd_weight(self):
+ self.log.info('do_osd_weight (not yet implemented)')
+
+ def execute(self, plan):
+ self.log.info('Executing plan %s' % plan.name)
+
+ commands = []
+
+ # compat weight-set
+ if len(plan.compat_ws) and \
+ not CRUSHMap.have_default_choose_args(plan.initial.crush_dump):
+ self.log.debug('ceph osd crush weight-set create-compat')
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd crush weight-set create-compat',
+ 'format': 'json',
+ }), '')
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.error('Error creating compat weight-set')
+ return r, outs
+
+ for osd, weight in six.iteritems(plan.compat_ws):
+ self.log.info('ceph osd crush weight-set reweight-compat osd.%d %f',
+ osd, weight)
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd crush weight-set reweight-compat',
+ 'format': 'json',
+ 'item': 'osd.%d' % osd,
+ 'weight': [weight],
+ }), '')
+ commands.append(result)
+
+ # new_weight
+ reweightn = {}
+ for osd, weight in six.iteritems(plan.osd_weights):
+ reweightn[str(osd)] = str(int(weight * float(0x10000)))
+ if len(reweightn):
+ self.log.info('ceph osd reweightn %s', reweightn)
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd reweightn',
+ 'format': 'json',
+ 'weights': json.dumps(reweightn),
+ }), '')
+ commands.append(result)
+
+ # upmap
+ incdump = plan.inc.dump()
+ for pgid in incdump.get('old_pg_upmap_items', []):
+ self.log.info('ceph osd rm-pg-upmap-items %s', pgid)
+ result = CommandResult('foo')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd rm-pg-upmap-items',
+ 'format': 'json',
+ 'pgid': pgid,
+ }), 'foo')
+ commands.append(result)
+
+ for item in incdump.get('new_pg_upmap_items', []):
+ self.log.info('ceph osd pg-upmap-items %s mappings %s', item['pgid'],
+ item['mappings'])
+ osdlist = []
+ for m in item['mappings']:
+ osdlist += [m['from'], m['to']]
+ result = CommandResult('foo')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd pg-upmap-items',
+ 'format': 'json',
+ 'pgid': item['pgid'],
+ 'id': osdlist,
+ }), 'foo')
+ commands.append(result)
+
+ # wait for commands
+ self.log.debug('commands %s' % commands)
+ for result in commands:
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.error('execute error: r = %d, detail = %s' % (r, outs))
+ return r, outs
+ self.log.debug('done')
+ return 0, ''
+
+ def gather_telemetry(self):
+ return {
+ 'active': self.active,
+ 'mode': self.mode,
+ }
diff --git a/src/pybind/mgr/crash/__init__.py b/src/pybind/mgr/crash/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/crash/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/crash/module.py b/src/pybind/mgr/crash/module.py
new file mode 100644
index 00000000..b9cf4929
--- /dev/null
+++ b/src/pybind/mgr/crash/module.py
@@ -0,0 +1,369 @@
+from mgr_module import MgrModule
+import datetime
+import errno
+import json
+from collections import defaultdict
+from prettytable import PrettyTable
+from threading import Event, Lock
+
+
+DATEFMT = '%Y-%m-%d %H:%M:%S.%f'
+
+MAX_WAIT = 600
+MIN_WAIT = 60
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'warn_recent_interval',
+ 'type': 'secs',
+ 'default': 60*60*24*14,
+ 'desc': 'time interval in which to warn about recent crashes',
+ 'runtime': True,
+ },
+ {
+ 'name': 'retain_interval',
+ 'type': 'secs',
+ 'default': 60*60*24 * 365,
+ 'desc': 'how long to retain crashes before pruning them',
+ 'runtime': True,
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.crashes = None
+ self.crashes_lock = Lock()
+ self.run = True
+ self.event = Event()
+
+ def shutdown(self):
+ self.run = False
+ self.event.set()
+
+ def serve(self):
+ self.config_notify()
+ while self.run:
+ with self.crashes_lock:
+ self._refresh_health_checks()
+ self._prune(self.retain_interval)
+ wait = min(MAX_WAIT, max(self.warn_recent_interval / 100, MIN_WAIT))
+ self.event.wait(wait)
+ self.event.clear()
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' mgr option %s = %s',
+ opt['name'], getattr(self, opt['name']))
+
+ def _load_crashes(self):
+ raw = self.get_store_prefix('crash/')
+ self.crashes = {k[6:]: json.loads(m) for (k, m) in raw.items()}
+
+ def _refresh_health_checks(self):
+ if not self.crashes:
+ self._load_crashes()
+ cutoff = datetime.datetime.utcnow() - datetime.timedelta(
+ seconds=self.warn_recent_interval)
+ recent = {
+ crashid: crash for crashid, crash in self.crashes.items()
+ if self.time_from_string(crash['timestamp']) > cutoff and 'archived' not in crash
+ }
+ num = len(recent)
+ health_checks = {}
+ if recent:
+ detail = [
+ '%s crashed on host %s at %s' % (
+ crash.get('entity_name', 'unidentified daemon'),
+ crash.get('utsname_hostname', '(unknown)'),
+ crash.get('timestamp', 'unknown time'))
+ for (_, crash) in recent.items()]
+ if num > 30:
+ detail = detail[0:30]
+ detail.append('and %d more' % (num - 30))
+ self.log.debug('detail %s' % detail)
+ health_checks['RECENT_CRASH'] = {
+ 'severity': 'warning',
+ 'summary': '%d daemons have recently crashed' % (num),
+ 'detail': detail,
+ }
+ self.set_health_checks(health_checks)
+
+ def handle_command(self, inbuf, command):
+ with self.crashes_lock:
+ if not self.crashes:
+ self._load_crashes()
+ for cmd in self.COMMANDS:
+ if cmd['cmd'].startswith(command['prefix']):
+ handler = cmd['handler']
+ break
+ if handler is None:
+ return errno.EINVAL, '', 'unknown command %s' % command['prefix']
+
+ return handler(self, command, inbuf)
+
+ def time_from_string(self, timestr):
+ # drop the 'Z' timezone indication, it's always UTC
+ timestr = timestr.rstrip('Z')
+ return datetime.datetime.strptime(timestr, DATEFMT)
+
+ def validate_crash_metadata(self, inbuf):
+ # raise any exceptions to caller
+ metadata = json.loads(inbuf)
+ for f in ['crash_id', 'timestamp']:
+ if f not in metadata:
+ raise AttributeError("missing '%s' field" % f)
+ time = self.time_from_string(metadata['timestamp'])
+ return metadata
+
+ def timestamp_filter(self, f):
+ """
+ Filter crash reports by timestamp.
+
+ :param f: f(time) return true to keep crash report
+ :returns: crash reports for which f(time) returns true
+ """
+ def inner(pair):
+ _, crash = pair
+ time = self.time_from_string(crash["timestamp"])
+ return f(time)
+ return filter(inner, self.crashes.items())
+
+ # command handlers
+
+ def do_info(self, cmd, inbuf):
+ crashid = cmd['id']
+ crash = self.crashes.get(crashid)
+ if not crash:
+ return errno.EINVAL, '', 'crash info: %s not found' % crashid
+ val = json.dumps(crash, indent=4)
+ return 0, val, ''
+
+ def do_post(self, cmd, inbuf):
+ try:
+ metadata = self.validate_crash_metadata(inbuf)
+ except Exception as e:
+ return errno.EINVAL, '', 'malformed crash metadata: %s' % e
+ crashid = metadata['crash_id']
+
+ if crashid not in self.crashes:
+ self.crashes[crashid] = metadata
+ key = 'crash/%s' % crashid
+ self.set_store(key, json.dumps(metadata))
+ self._refresh_health_checks()
+ return 0, '', ''
+
+ def ls(self):
+ if not self.crashes:
+ self._load_crashes()
+ return self.do_ls({'prefix': 'crash ls'}, '')
+
+ def do_ls(self, cmd, inbuf):
+ if cmd['prefix'] == 'crash ls':
+ t = self.crashes.values()
+ else:
+ t = [crash for crashid, crash in self.crashes.items()
+ if 'archived' not in crash]
+ r = sorted(t, key=lambda i: i.get('crash_id'))
+ if cmd.get('format') == 'json' or cmd.get('format') == 'json-pretty':
+ return 0, json.dumps(r, indent=4), ''
+ else:
+ table = PrettyTable(['ID', 'ENTITY', 'NEW'],
+ border=False)
+ table.left_padding_width = 0
+ table.right_padding_width = 1
+ table.align['ID'] = 'l'
+ table.align['ENTITY'] = 'l'
+ for c in r:
+ table.add_row([c.get('crash_id'),
+ c.get('entity_name','unknown'),
+ '' if 'archived' in c else '*'])
+ return 0, table.get_string(), ''
+
+ def do_rm(self, cmd, inbuf):
+ crashid = cmd['id']
+ if crashid in self.crashes:
+ del self.crashes[crashid]
+ key = 'crash/%s' % crashid
+ self.set_store(key, None) # removes key
+ self._refresh_health_checks()
+ return 0, '', ''
+
+ def do_prune(self, cmd, inbuf):
+ keep = cmd['keep']
+ try:
+ keep = int(keep)
+ except ValueError:
+ return errno.EINVAL, '', 'keep argument must be integer'
+
+ self._prune(keep * 60*60*24)
+ return 0, '', ''
+
+ def _prune(self, seconds):
+ now = datetime.datetime.utcnow()
+ cutoff = now - datetime.timedelta(seconds=seconds)
+ removed_any = False
+ # make a copy of the list, since we'll modify self.crashes below
+ to_prune = list(self.timestamp_filter(lambda ts: ts <= cutoff))
+ for crashid, crash in to_prune:
+ del self.crashes[crashid]
+ key = 'crash/%s' % crashid
+ self.set_store(key, None)
+ removed_any = True
+ if removed_any:
+ self._refresh_health_checks()
+
+ def do_archive(self, cmd, inbuf):
+ crashid = cmd['id']
+ crash = self.crashes.get(crashid)
+ if not crash:
+ return errno.EINVAL, '', 'crash info: %s not found' % crashid
+ if not crash.get('archived'):
+ crash['archived'] = str(datetime.datetime.utcnow())
+ self.crashes[crashid] = crash
+ key = 'crash/%s' % crashid
+ self.set_store(key, json.dumps(crash))
+ self._refresh_health_checks()
+ return 0, '', ''
+
+ def do_archive_all(self, cmd, inbuf):
+ for crashid, crash in self.crashes.items():
+ if not crash.get('archived'):
+ crash['archived'] = str(datetime.datetime.utcnow())
+ self.crashes[crashid] = crash
+ key = 'crash/%s' % crashid
+ self.set_store(key, json.dumps(crash))
+ self._refresh_health_checks()
+ return 0, '', ''
+
+ def do_stat(self, cmd, inbuf):
+ # age in days for reporting, ordered smallest first
+ bins = [1, 3, 7]
+ retlines = list()
+
+ def binstr(bindict):
+ binlines = list()
+ count = len(bindict['idlist'])
+ if count:
+ binlines.append(
+ '%d older than %s days old:' % (count, bindict['age'])
+ )
+ for crashid in bindict['idlist']:
+ binlines.append(crashid)
+ return '\n'.join(binlines)
+
+ total = 0
+ now = datetime.datetime.utcnow()
+ for i, age in enumerate(bins):
+ agelimit = now - datetime.timedelta(days=age)
+ bins[i] = {
+ 'age': age,
+ 'agelimit': agelimit,
+ 'idlist': list()
+ }
+
+ for crashid, crash in self.crashes.items():
+ total += 1
+ stamp = self.time_from_string(crash['timestamp'])
+ for i, bindict in enumerate(bins):
+ if stamp <= bindict['agelimit']:
+ bindict['idlist'].append(crashid)
+ # don't count this one again
+ continue
+
+ retlines.append('%d crashes recorded' % total)
+
+ for bindict in bins:
+ retlines.append(binstr(bindict))
+ return 0, '\n'.join(retlines), ''
+
+ def do_json_report(self, cmd, inbuf):
+ """
+ Return a machine readable summary of recent crashes.
+ """
+ try:
+ hours = int(cmd['hours'])
+ except ValueError:
+ return errno.EINVAL, '', '<hours> argument must be integer'
+
+ report = defaultdict(lambda: 0)
+ for crashid, crash in self.crashes.items():
+ pname = crash.get("process_name", "unknown")
+ if not pname:
+ pname = "unknown"
+ report[pname] += 1
+
+ return 0, '', json.dumps(report)
+
+ def self_test(self):
+ # test time conversion
+ timestr = '2018-06-22 20:35:38.058818Z'
+ dt = self.time_from_string(timestr)
+ if dt != datetime.datetime(2018, 6, 22, 20, 35, 38, 58818):
+ raise RuntimeError('time_from_string() failed')
+
+ COMMANDS = [
+ {
+ 'cmd': 'crash info name=id,type=CephString',
+ 'desc': 'show crash dump metadata',
+ 'perm': 'r',
+ 'handler': do_info,
+ },
+ {
+ 'cmd': 'crash ls',
+ 'desc': 'Show new and archived crash dumps',
+ 'perm': 'r',
+ 'handler': do_ls,
+ },
+ {
+ 'cmd': 'crash ls-new',
+ 'desc': 'Show new crash dumps',
+ 'perm': 'r',
+ 'handler': do_ls,
+ },
+ {
+ 'cmd': 'crash post',
+ 'desc': 'Add a crash dump (use -i <jsonfile>)',
+ 'perm': 'rw',
+ 'handler': do_post,
+ },
+ {
+ 'cmd': 'crash prune name=keep,type=CephString',
+ 'desc': 'Remove crashes older than <keep> days',
+ 'perm': 'rw',
+ 'handler': do_prune,
+ },
+ {
+ 'cmd': 'crash rm name=id,type=CephString',
+ 'desc': 'Remove a saved crash <id>',
+ 'perm': 'rw',
+ 'handler': do_rm,
+ },
+ {
+ 'cmd': 'crash stat',
+ 'desc': 'Summarize recorded crashes',
+ 'perm': 'r',
+ 'handler': do_stat,
+ },
+ {
+ 'cmd': 'crash json_report name=hours,type=CephString',
+ 'desc': 'Crashes in the last <hours> hours',
+ 'perm': 'r',
+ 'handler': do_json_report,
+ },
+ {
+ 'cmd': 'crash archive name=id,type=CephString',
+ 'desc': 'Acknowledge a crash and silence health warning(s)',
+ 'perm': 'w',
+ 'handler': do_archive,
+ },
+ {
+ 'cmd': 'crash archive-all',
+ 'desc': 'Acknowledge all new crashes and silence health warning(s)',
+ 'perm': 'w',
+ 'handler': do_archive_all,
+ },
+ ]
diff --git a/src/pybind/mgr/dashboard/.coveragerc b/src/pybind/mgr/dashboard/.coveragerc
new file mode 100644
index 00000000..29a63192
--- /dev/null
+++ b/src/pybind/mgr/dashboard/.coveragerc
@@ -0,0 +1,7 @@
+[run]
+omit = tests/*
+ */python*/*
+ ceph_module_mock.py
+ __init__.py
+ */mgr_module.py
+
diff --git a/src/pybind/mgr/dashboard/.editorconfig b/src/pybind/mgr/dashboard/.editorconfig
new file mode 100644
index 00000000..a831e3da
--- /dev/null
+++ b/src/pybind/mgr/dashboard/.editorconfig
@@ -0,0 +1,29 @@
+# EditorConfig helps developers define and maintain consistent coding styles
+# between different editors and IDEs.: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+# Set default charset
+[*.{js,py}]
+charset = utf-8
+
+# 4 space indentation for Python files
+[*.py]
+indent_style = space
+indent_size = 4
+
+# Indentation override for all JS under frontend directory
+[frontend/**.js]
+indent_style = space
+indent_size = 2
+
+# Indentation override for all HTML under frontend directory
+[frontend/**.html]
+indent_style = space
+indent_size = 2
diff --git a/src/pybind/mgr/dashboard/.gitignore b/src/pybind/mgr/dashboard/.gitignore
new file mode 100644
index 00000000..0e6f6149
--- /dev/null
+++ b/src/pybind/mgr/dashboard/.gitignore
@@ -0,0 +1,16 @@
+.coverage*
+htmlcov
+.tox
+coverage.xml
+junit*xml
+.cache
+ceph.conf
+wheelhouse*
+
+# IDE
+.vscode
+*.egg
+.env
+
+# virtualenv
+venv
diff --git a/src/pybind/mgr/dashboard/.pylintrc b/src/pybind/mgr/dashboard/.pylintrc
new file mode 100644
index 00000000..d5a9d1f7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/.pylintrc
@@ -0,0 +1,535 @@
+[MASTER]
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=rados,rbd,math,cephfs
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Add files or directories matching the regex patterns to the blacklist. The
+# regex matches against base names, not paths.
+ignore-patterns=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Specify a configuration file.
+#rcfile=
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages
+suggestion-mode=yes
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=import-star-module-level,
+ raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ locally-enabled,
+ suppressed-message,
+ useless-suppression,
+ apply-builtin,
+ basestring-builtin,
+ buffer-builtin,
+ cmp-builtin,
+ coerce-builtin,
+ execfile-builtin,
+ file-builtin,
+ long-builtin,
+ raw_input-builtin,
+ reduce-builtin,
+ standarderror-builtin,
+ unicode-builtin,
+ coerce-method,
+ delslice-method,
+ getslice-method,
+ setslice-method,
+ no-absolute-import,
+ old-division,
+ dict-iter-method,
+ dict-view-method,
+ next-method-called,
+ metaclass-assignment,
+ indexing-exception,
+ reload-builtin,
+ oct-method,
+ hex-method,
+ nonzero-method,
+ cmp-method,
+ input-builtin,
+ round-builtin,
+ intern-builtin,
+ unichr-builtin,
+ map-builtin-not-iterating,
+ zip-builtin-not-iterating,
+ range-builtin-not-iterating,
+ filter-builtin-not-iterating,
+ using-cmp-argument,
+ eq-without-hash,
+ div-method,
+ idiv-method,
+ rdiv-method,
+ exception-message-attribute,
+ invalid-str-codec,
+ sys-max-int,
+ bad-python3-import,
+ next-method-defined,
+ dict-items-not-iterating,
+ dict-keys-not-iterating,
+ dict-values-not-iterating,
+ missing-docstring,
+ invalid-name,
+ no-self-use,
+ too-few-public-methods,
+ no-member,
+ too-many-arguments,
+ too-many-locals,
+ too-many-statements,
+ useless-object-inheritance
+
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=c-extension-no-member
+
+
+[REPORTS]
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio).You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=optparse.Values,sys.exit
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins
+
+
+[BASIC]
+
+# Naming style matching correct argument names
+argument-naming-style=snake_case
+
+# Regular expression matching correct argument names. Overrides argument-
+# naming-style
+#argument-rgx=
+
+# Naming style matching correct attribute names
+attr-naming-style=snake_case
+
+# Regular expression matching correct attribute names. Overrides attr-naming-
+# style
+#attr-rgx=
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,
+ bar,
+ baz,
+ toto,
+ tutu,
+ tata
+
+# Naming style matching correct class attribute names
+class-attribute-naming-style=any
+
+# Regular expression matching correct class attribute names. Overrides class-
+# attribute-naming-style
+#class-attribute-rgx=
+
+# Naming style matching correct class names
+class-naming-style=PascalCase
+
+# Regular expression matching correct class names. Overrides class-naming-style
+#class-rgx=
+
+# Naming style matching correct constant names
+const-naming-style=UPPER_CASE
+
+# Regular expression matching correct constant names. Overrides const-naming-
+# style
+#const-rgx=
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming style matching correct function names
+function-naming-style=snake_case
+
+# Regular expression matching correct function names. Overrides function-
+# naming-style
+#function-rgx=
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,
+ j,
+ k,
+ ex,
+ Run,
+ _
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Naming style matching correct inline iteration names
+inlinevar-naming-style=any
+
+# Regular expression matching correct inline iteration names. Overrides
+# inlinevar-naming-style
+#inlinevar-rgx=
+
+# Naming style matching correct method names
+method-naming-style=snake_case
+
+# Regular expression matching correct method names. Overrides method-naming-
+# style
+#method-rgx=
+
+# Naming style matching correct module names
+module-naming-style=snake_case
+
+# Regular expression matching correct module names. Overrides module-naming-
+# style
+#module-rgx=
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+property-classes=abc.abstractproperty
+
+# Naming style matching correct variable names
+variable-naming-style=snake_case
+
+# Regular expression matching correct variable names. Overrides variable-
+# naming-style
+#variable-rgx=
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# List of optional constructs for which whitespace checking is disabled. `dict-
+# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
+# `empty-line` allows space-only lines.
+no-space-check=trailing-comma,
+ dict-separator
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes
+max-spelling-suggestions=4
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=cherrypy,distutils
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+ XXX,
+ TODO
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[SIMILARITIES]
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[IMPORTS]
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,
+ TERMIOS,
+ Bastion,
+ rexec
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,
+ _fields,
+ _replace,
+ _source,
+ _make
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/src/pybind/mgr/dashboard/CMakeLists.txt b/src/pybind/mgr/dashboard/CMakeLists.txt
new file mode 100644
index 00000000..b6c78618
--- /dev/null
+++ b/src/pybind/mgr/dashboard/CMakeLists.txt
@@ -0,0 +1,133 @@
+set(MGR_DASHBOARD_VIRTUALENV ${CEPH_BUILD_VIRTUALENV}/mgr-dashboard-virtualenv)
+
+add_custom_target(mgr-dashboard-test-venv
+ COMMAND
+ ${CMAKE_SOURCE_DIR}/src/tools/setup-virtualenv.sh --python=${MGR_PYTHON_EXECUTABLE} ${MGR_DASHBOARD_VIRTUALENV}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard
+ COMMENT "dashboard tests virtualenv is being created")
+add_dependencies(tests mgr-dashboard-test-venv)
+
+include(CMakeParseArguments)
+function(add_npm_command)
+ set(options NODEENV)
+ set(single_kw OUTPUT COMMENT WORKING_DIRECTORY)
+ set(multi_kw COMMAND DEPENDS)
+ cmake_parse_arguments(NC "${options}" "${single_kw}" "${multi_kw}" ${ARGN})
+ string(REPLACE ";" " " command "${NC_COMMAND}")
+ if(NC_NODEENV)
+ string(REGEX REPLACE "^(.*(npm|npx) .*)$" ". ${mgr-dashboard-nodeenv-dir}/bin/activate && \\1 && deactivate" command ${command})
+ endif()
+ string(REPLACE " " ";" command "${command}")
+ add_custom_command(
+ OUTPUT "${NC_OUTPUT}"
+ COMMAND ${command}
+ DEPENDS ${NC_DEPENDS}
+ WORKING_DIRECTORY "${NC_WORKING_DIRECTORY}"
+ COMMENT ${NC_COMMENT})
+endfunction(add_npm_command)
+
+if(WITH_MGR_DASHBOARD_FRONTEND AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm|ARM")
+
+if(WITH_SYSTEM_NPM)
+ set(mgr-dashboard-nodeenv-dir )
+ set(nodeenv "")
+ add_custom_target(mgr-dashboard-frontend-deps
+ DEPENDS frontend/node_modules
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend
+ )
+else()
+ set(mgr-dashboard-nodeenv-dir ${CMAKE_CURRENT_BINARY_DIR}/node-env)
+ set(nodeenv NODEENV)
+
+ add_custom_command(
+ OUTPUT "${mgr-dashboard-nodeenv-dir}/bin/npm"
+ COMMAND ${CMAKE_SOURCE_DIR}/src/tools/setup-virtualenv.sh --python=${MGR_PYTHON_EXECUTABLE} ${mgr-dashboard-nodeenv-dir}
+ COMMAND ${mgr-dashboard-nodeenv-dir}/bin/pip install nodeenv
+ COMMAND ${mgr-dashboard-nodeenv-dir}/bin/nodeenv -p --node=10.13.0
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "dashboard nodeenv is being installed"
+ )
+ add_custom_target(mgr-dashboard-nodeenv
+ DEPENDS ${mgr-dashboard-nodeenv-dir}/bin/npm
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ add_custom_target(mgr-dashboard-frontend-deps
+ DEPENDS frontend/node_modules mgr-dashboard-nodeenv
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend
+ )
+endif()
+
+add_npm_command(
+ OUTPUT "${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/node_modules"
+ COMMAND npm ci
+ DEPENDS frontend/package.json
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend
+ COMMENT "dashboard frontend dependencies are being installed"
+ ${nodeenv}
+)
+
+# Glob some frontend files. With CMake 3.6, this can be simplified
+# to *.ts *.html. Just add:
+# list(FILTER frontend_src INCLUDE REGEX "frontend/src")
+file(
+ GLOB_RECURSE frontend_src
+ frontend/src/*.ts
+ frontend/src/*.html
+ frontend/src/*/*.ts
+ frontend/src/*/*.html
+ frontend/src/*/*/*.ts
+ frontend/src/*/*/*.html
+ frontend/src/*/*/*/*.ts
+ frontend/src/*/*/*/*.html
+ frontend/src/*/*/*/*/*.ts
+ frontend/src/*/*/*/*/*.html
+ frontend/src/*/*/*/*/*/*.ts
+ frontend/src/*/*/*/*/*/*.html)
+
+# these files are generated during build
+list(REMOVE_ITEM frontend_src
+ ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/src/environments/environment.prod.ts
+ ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/src/environments/environment.ts)
+
+execute_process(
+ COMMAND bash -c "jq -r .config.locale ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/package.json"
+ OUTPUT_VARIABLE default_lang
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if(DASHBOARD_FRONTEND_LANGS)
+ string(STRIP "${DASHBOARD_FRONTEND_LANGS}" DASHBOARD_FRONTEND_LANGS)
+ if(DASHBOARD_FRONTEND_LANGS STREQUAL "ALL")
+ set(build_target ":*")
+ else()
+ string(FIND "${DASHBOARD_FRONTEND_LANGS}" "${default_lang}" default_idx)
+ if (default_idx EQUAL -1)
+ # default language must be always built
+ string(CONCAT DASHBOARD_FRONTEND_LANGS "${DASHBOARD_FRONTEND_LANGS}" ",${default_lang}")
+ endif()
+ set(build_target ":\{${DASHBOARD_FRONTEND_LANGS}\}")
+ endif()
+else(DASHBOARD_FRONTEND_LANGS)
+ set(build_target ":${default_lang}")
+endif(DASHBOARD_FRONTEND_LANGS)
+
+if(NOT CMAKE_BUILD_TYPE STREQUAL Debug)
+ set(npm_args "-- --prod --progress=false")
+else()
+ set(npm_args "-- --progress=false")
+endif()
+
+add_npm_command(
+ OUTPUT "${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/dist"
+ COMMAND npx npm-run-all --print-label --parallel --max-parallel 2 "\"build${build_target} -- ${npm_args}\""
+ DEPENDS ${frontend_src} frontend/node_modules
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend
+ COMMENT "dashboard frontend is being created"
+ ${nodeenv}
+)
+add_custom_target(mgr-dashboard-frontend-build
+ ALL
+ DEPENDS frontend/dist mgr-dashboard-frontend-deps
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend)
+
+add_dependencies(tests mgr-dashboard-frontend-build)
+endif(WITH_MGR_DASHBOARD_FRONTEND AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm|ARM")
diff --git a/src/pybind/mgr/dashboard/HACKING.rst b/src/pybind/mgr/dashboard/HACKING.rst
new file mode 100644
index 00000000..5a790aaa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/HACKING.rst
@@ -0,0 +1,1784 @@
+Ceph Dashboard Developer Documentation
+======================================
+
+.. contents:: Table of Contents
+
+Frontend Development
+--------------------
+
+Before you can start the dashboard from within a development environment, you
+will need to generate the frontend code and either use a compiled and running
+Ceph cluster (e.g. started by ``vstart.sh``) or the standalone development web
+server.
+
+The build process is based on `Node.js <https://nodejs.org/>`_ and requires the
+`Node Package Manager <https://www.npmjs.com/>`_ ``npm`` to be installed.
+
+Prerequisites
+~~~~~~~~~~~~~
+
+ * Node 8.9.0 or higher
+ * NPM 5.7.0 or higher
+
+nodeenv:
+ During Ceph's build we create a virtualenv with ``node`` and ``npm``
+ installed, which can be used as an alternative to installing node/npm in your
+ system.
+
+ If you want to use the node installed in the virtualenv you just need to
+ activate the virtualenv before you run any npm commands. To activate it run
+ ``. build/src/pybind/mgr/dashboard/node-env/bin/activate``.
+
+ Once you finish, you can simply run ``deactivate`` and exit the virtualenv.
+
+Angular CLI:
+ If you do not have the `Angular CLI <https://github.com/angular/angular-cli>`_
+ installed globally, then you need to execute ``ng`` commands with an
+ additional ``npm run`` before it.
+
+Package installation
+~~~~~~~~~~~~~~~~~~~~
+
+Run ``npm install`` in directory ``src/pybind/mgr/dashboard/frontend`` to
+install the required packages locally.
+
+Setting up a Development Server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Create the ``proxy.conf.json`` file based on ``proxy.conf.json.sample``.
+
+Run ``npm start`` for a dev server.
+Navigate to ``http://localhost:4200/``. The app will automatically
+reload if you change any of the source files.
+
+Code Scaffolding
+~~~~~~~~~~~~~~~~
+
+Run ``ng generate component component-name`` to generate a new
+component. You can also use
+``ng generate directive|pipe|service|class|guard|interface|enum|module``.
+
+Build the Project
+~~~~~~~~~~~~~~~~~
+
+Run ``npm run build`` to build the project. The build artifacts will be
+stored in the ``dist/`` directory. Use the ``-prod`` flag for a
+production build. Navigate to ``https://localhost:8443``.
+
+Build the Code Documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Run ``npm run doc-build`` to generate code docs in the ``documentation/``
+directory. To make them accesible locally for a web browser, run
+``npm run doc-serve`` and they will become available at ``http://localhost:8444``.
+With ``npm run compodoc -- <opts>`` you may
+`fully configure it https://compodoc.app/guides/usage.html`_.
+
+Code linting and formatting
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We use the following tools to lint and format the code in all our TS, SCSS and
+HTML files:
+
+- `codelyzer <http://codelyzer.com/>`_
+- `html-linter <https://github.com/chinchiheather/html-linter>`_
+- `Prettier <https://prettier.io/>`_
+- `TSLint <https://palantir.github.io/tslint/>`_
+
+We added 2 npm scripts to help run these tools:
+
+- ``npm run lint``, will check frontend files against all linters
+- ``npm run fix``, will try to fix all the detected linting errors
+
+Writing Unit Tests
+~~~~~~~~~~~~~~~~~~
+
+To write unit tests most efficient we have a small collection of tools,
+we use within test suites.
+
+Those tools can be found under
+``src/pybind/mgr/dashboard/frontend/src/testing/``, especially take
+a look at ``unit-test-helper.ts``.
+
+There you will be able to find:
+
+``configureTestBed`` that replaces the initial ``TestBed``
+methods. It takes the same arguments as ``TestBed.configureTestingModule``.
+Using it will run your tests a lot faster in development, as it doesn't
+recreate everything from scratch on every test. To use the default behaviour
+pass ``true`` as the second argument.
+
+``PermissionHelper`` to help determine if
+the correct actions are shown based on the current permissions and selection
+in a list.
+
+``FormHelper`` which makes testing a form a lot easier
+with a few simple methods. It allows you to set a control or multiple
+controls, expect if a control is valid or has an error or just do both with
+one method. Additional you can expect a template element or multiple elements
+to be visible in the rendered template.
+
+Running Unit Tests
+~~~~~~~~~~~~~~~~~~
+
+Create ``unit-test-configuration.ts`` file based on
+``unit-test-configuration.ts.sample`` in directory
+``src/pybind/mgr/dashboard/frontend/src``.
+
+Run ``npm run test`` to execute the unit tests via `Jest
+<https://facebook.github.io/jest/>`_.
+
+If you get errors on all tests, it could be because `Jest
+<https://facebook.github.io/jest/>`_ or something else was updated.
+There are a few ways how you can try to resolve this:
+
+- Remove all modules with ``rm -rf dist node_modules`` and run ``npm install``
+ again in order to reinstall them
+- Clear the cache of jest by running ``npx jest --clearCache``
+
+Running End-to-End Tests
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+We use `Protractor <http://www.protractortest.org/>`__ to run our frontend e2e
+tests.
+
+Our ``run-frontend-e2e-tests.sh`` script will check if Chrome or Docker is
+installed and run the tests if either is found.
+
+Start all frontend e2e tests by running::
+
+ $ ./run-frontend-e2e-tests.sh
+
+Device:
+ You can force the script to use a specific device with the ``-d`` flag::
+
+ $ ./run-frontend-e2e-tests.sh -d <chrome|docker>
+
+Remote:
+ If you want to run the tests outside the ceph environment, you will need to
+ manually define the dashboard url using ``-r``::
+
+ $ ./run-frontend-e2e-tests.sh -r <DASHBOARD_URL>
+
+Note:
+ When using docker, as your device, you might need to run the script with sudo
+ permissions.
+
+Writing End-to-End Tests
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When writing e2e tests you don't want to recompile every time from scratch to
+try out if your test has succeeded. As usual you have your development server
+open (``npm start``) which already has compiled all files. To attach
+`Protractor <http://www.protractortest.org/>`__ to this process, instead of
+spinning up it's own server, you can use ``npm run e2e -- --dev-server-target``
+or just ``npm run e2e:dev`` which is equivalent.
+
+Further Help
+~~~~~~~~~~~~
+
+To get more help on the Angular CLI use ``ng help`` or go check out the
+`Angular CLI
+README <https://github.com/angular/angular-cli/blob/master/README.md>`__.
+
+Example of a Generator
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ # Create module 'Core'
+ src/app> ng generate module core -m=app --routing
+
+ # Create module 'Auth' under module 'Core'
+ src/app/core> ng generate module auth -m=core --routing
+ or, alternatively:
+ src/app> ng generate module core/auth -m=core --routing
+
+ # Create component 'Login' under module 'Auth'
+ src/app/core/auth> ng generate component login -m=core/auth
+ or, alternatively:
+ src/app> ng generate component core/auth/login -m=core/auth
+
+Frontend Typescript Code Style Guide Recommendations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Group the imports based on its source and separate them with a blank
+line.
+
+The source groups can be either from Angular, external or internal.
+
+Example:
+
+.. code:: javascript
+
+ import { Component } from '@angular/core';
+ import { Router } from '@angular/router';
+
+ import { ToastrManager } from 'ngx-toastr';
+
+ import { Credentials } from '../../../shared/models/credentials.model';
+ import { HostService } from './services/host.service';
+
+Frontend components
+~~~~~~~~~~~~~~~~~~~
+
+There are several components that can be reused on different pages.
+This components are declared on the components module:
+`src/pybind/mgr/dashboard/frontend/src/app/shared/components`.
+
+Helper
+......
+
+This component should be used to provide additional information to the user.
+
+Example:
+
+.. code:: html
+
+ <cd-helper>
+ Some <strong>helper</strong> html text
+ </cd-helper>
+
+Terminology and wording
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Instead of using the Ceph component names, the approach
+suggested is to use the logical/generic names (Block over RBD, Filesystem over
+CephFS, Object over RGW). Nevertheless, as Ceph-Dashboard cannot completely hide
+the Ceph internals, some Ceph-specific names might remain visible.
+
+Regarding the wording for action labels and other textual elements (form titles,
+buttons, etc.), the chosen approach is to follow `these guidelines
+<https://www.patternfly.org/styles/terminology-and-wording/#terminology-and-wording-for-action-labels>`_.
+As a rule of thumb, 'Create' and 'Delete' are the proper wording for most forms,
+instead of 'Add' and 'Remove', unless some already created item is either added
+or removed to/from a set of items (e.g.: 'Add permission' to a user vs. 'Create
+(new) permission').
+
+In order to enforce the use of this wording, a service ``ActionLabelsI18n`` has
+been created, which provides translated labels for use in UI elements.
+
+Frontend branding
+~~~~~~~~~~~~~~~~~
+
+Every vendor can customize the 'Ceph dashboard' to his needs. No matter if
+logo, HTML-Template or TypeScript, every file inside the frontend folder can be
+replaced.
+
+To replace files, open ``./frontend/angular.json`` and scroll to the section
+``fileReplacements`` inside the production configuration. Here you can add the
+files you wish to brand. We recommend to place the branded version of a file in
+the same directory as the original one and to add a ``.brand`` to the file
+name, right in front of the file extension. A ``fileReplacement`` could for
+example look like this:
+
+.. code:: javascript
+
+ {
+ "replace": "src/app/core/auth/login/login.component.html",
+ "with": "src/app/core/auth/login/login.component.brand.html"
+ }
+
+To serve or build the branded user interface run:
+
+ $ npm run start -- --prod
+
+or
+
+ $ npm run build -- --prod
+
+Unfortunately it's currently not possible to use multiple configurations when
+serving or building the UI at the same time. That means a configuration just
+for the branding ``fileReplacements`` is not an option, because you want to use
+the production configuration anyway
+(https://github.com/angular/angular-cli/issues/10612).
+Furthermore it's also not possible to use glob expressions for
+``fileReplacements``. As long as the feature hasn't been implemented, you have
+to add the file replacements manually to the angular.json file
+(https://github.com/angular/angular-cli/issues/12354).
+
+Nevertheless you should stick to the suggested naming scheme because it makes
+it easier for you to use glob expressions once it's supported in the future.
+
+To change the variable defaults you can overwrite them in the file
+``./frontend/src/vendor.variables.scss``. Just reassign the variable you want
+to change, for example ``$color-primary: teal;``
+To overwrite or extend the default CSS, you can add your own styles in
+``./frontend/src/vendor.overrides.scss``.
+
+I18N
+----
+
+How to extract messages from source code?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To extract the I18N messages from the templates and the TypeScript files just
+run the following command in ``src/pybind/mgr/dashboard/frontend``::
+
+ $ npm run i18n:extract
+
+This will extract all marked messages from the HTML templates first and then
+add all marked strings from the TypeScript files to the translation template.
+Since the extraction from TypeScript files is still not supported by Angular
+itself, we are using the
+`ngx-translator <https://github.com/ngx-translate/i18n-polyfill>`_ extractor to
+parse the TypeScript files.
+
+When the command ran successfully, it should have created or updated the file
+``src/locale/messages.xlf``.
+
+The file isn't tracked by git, you can just use it to start with the
+translation offline or add/update the resource files on transifex.
+
+Supported languages
+~~~~~~~~~~~~~~~~~~~
+
+All our supported languages should be registered in both exports in
+``supported-languages.enum.ts`` and have a corresponding test in
+``language-selector.component.spec.ts``.
+
+The ``SupportedLanguages`` enum will provide the list for the default language selection.
+
+The ``languageBootstrapMapping`` variable will provide the
+`language support <https://github.com/valor-software/ngx-bootstrap/tree/development/src/chronos/i18n>`_
+for ngx-bootstrap components like the
+`date picker <https://valor-software.com/ngx-bootstrap/#/datepicker#locales>`_.
+
+Translating process
+~~~~~~~~~~~~~~~~~~~
+
+To facilitate the translation process of the dashboard we are using a web tool
+called `transifex <https://www.transifex.com/>`_.
+
+If you wish to help translating to any language just go to our `transifex
+project page <https://www.transifex.com/ceph/ceph-dashboard/>`_, join the
+project and you can start translating immediately.
+
+All translations will then be reviewed and later pushed upstream.
+
+Updating translated messages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Any time there are new messages translated and reviewed in a specific language
+we should update the translation file upstream.
+
+To do that, check the settings in the i18n config file
+``src/pybind/mgr/dashboard/frontend/i18n.config.json``:: and make sure that the
+organization is *ceph*, the project is *ceph-dashboard* and the resource is
+the one you want to pull from and push to e.g. *Master:master*. To find a list
+of avaiable resources visit ``https://www.transifex.com/ceph/ceph-dashboard/content/``::
+
+After you checked the config go to the directory ``src/pybind/mgr/dashboard/frontend``:: and run
+
+ $ npm run i18n
+
+This command will extract all marked messages from the HTML templates and
+TypeScript files. Once the source file has been created it will push it to
+transifex and pull the latest translations. It will also fill all the
+untranslated strings with the source string.
+The tool will ask you for an api token, unless you added it by running:
+
+ $ npm run i18n:token
+
+To create a transifex api token visit ``https://www.transifex.com/user/settings/api/``::
+
+After the command ran successfully, build the UI and check if everything is
+working as expected. You also might want to run the frontend tests.
+
+Suggestions
+~~~~~~~~~~~
+
+Strings need to start and end in the same line as the element:
+
+.. code-block:: xml
+
+ <!-- avoid -->
+ <span i18n>
+ Foo
+ </span>
+
+ <!-- recommended -->
+ <span i18n>Foo</span>
+
+
+ <!-- avoid -->
+ <span i18n>
+ Foo bar baz.
+ Foo bar baz.
+ </span>
+
+ <!-- recommended -->
+ <span i18n>Foo bar baz.
+ Foo bar baz.</span>
+
+Isolated interpolations should not be translated:
+
+.. code-block:: xml
+
+ <!-- avoid -->
+ <span i18n>{{ foo }}</span>
+
+ <!-- recommended -->
+ <span>{{ foo }}</span>
+
+Interpolations used in a sentence should be kept in the translation:
+
+.. code-block:: xml
+
+ <!-- recommended -->
+ <span i18n>There are {{ x }} OSDs.</span>
+
+Remove elements that are outside the context of the translation:
+
+.. code-block:: xml
+
+ <!-- avoid -->
+ <label i18n>
+ Profile
+ <span class="required"></span>
+ </label>
+
+ <!-- recommended -->
+ <label>
+ <ng-container i18n>Profile<ng-container>
+ <span class="required"></span>
+ </label>
+
+Keep elements that affect the sentence:
+
+.. code-block:: xml
+
+ <!-- recommended -->
+ <span i18n>Profile <b>foo</b> will be removed.</span>
+
+Backend Development
+-------------------
+
+The Python backend code of this module requires a number of Python modules to be
+installed. They are listed in file ``requirements.txt``. Using `pip
+<https://pypi.python.org/pypi/pip>`_ you may install all required dependencies
+by issuing ``pip install -r requirements.txt`` in directory
+``src/pybind/mgr/dashboard``.
+
+If you're using the `ceph-dev-docker development environment
+<https://github.com/ricardoasmarques/ceph-dev-docker/>`_, simply run
+``./install_deps.sh`` from the toplevel directory to install them.
+
+Unit Testing
+~~~~~~~~~~~~
+
+In dashboard we have two different kinds of backend tests:
+
+1. Unit tests based on ``tox``
+2. API tests based on Teuthology.
+
+Unit tests based on tox
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+We included a ``tox`` configuration file that will run the unit tests under
+Python 2 or 3, as well as linting tools to guarantee the uniformity of code.
+
+You need to install ``tox`` and ``coverage`` before running it. To install the
+packages in your system, either install it via your operating system's package
+management tools, e.g. by running ``dnf install python-tox python-coverage`` on
+Fedora Linux.
+
+Alternatively, you can use Python's native package installation method::
+
+ $ pip install tox
+ $ pip install coverage
+
+To run the tests, run ``run-tox.sh`` in the dashboard directory (where
+``tox.ini`` is located)::
+
+ ## Run Python 2+3 tests+lint commands:
+ $ ./run-tox.sh
+
+ ## Run Python 3 tests+lint commands:
+ $ WITH_PYTHON2=OFF ./run-tox.sh
+
+ ## Run Python 3 arbitrary command (e.g. 1 single test):
+ $ WITH_PYTHON2=OFF ./run-tox.sh pytest tests/test_rgw_client.py::RgwClientTest::test_ssl_verify
+
+You can also run tox instead of ``run-tox.sh``::
+
+ ## Run Python 3 tests command:
+ $ CEPH_BUILD_DIR=.tox tox -e py3-cov
+
+ ## Run Python 3 arbitrary command (e.g. 1 single test):
+ $ CEPH_BUILD_DIR=.tox tox -e py3-run pytest tests/test_rgw_client.py::RgwClientTest::test_ssl_verify
+
+We also collect coverage information from the backend code when you run tests. You can check the
+coverage information provided by the tox output, or by running the following
+command after tox has finished successfully::
+
+ $ coverage html
+
+This command will create a directory ``htmlcov`` with an HTML representation of
+the code coverage of the backend.
+
+API tests based on Teuthology
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+How to run existing API tests:
+ To run the API tests against a real Ceph cluster, we leverage the Teuthology
+ framework. This has the advantage of catching bugs originated from changes in
+ the internal Ceph code.
+
+ Our ``run-backend-api-tests.sh`` script will start a ``vstart`` Ceph cluster
+ before running the Teuthology tests, and then it stops the cluster after the
+ tests are run. Of course this implies that you have built/compiled Ceph
+ previously.
+
+ Start all dashboard tests by running::
+
+ $ ./run-backend-api-tests.sh
+
+ Or, start one or multiple specific tests by specifying the test name::
+
+ $ ./run-backend-api-tests.sh tasks.mgr.dashboard.test_pool.PoolTest
+
+ Or, ``source`` the script and run the tests manually::
+
+ $ source run-backend-api-tests.sh
+ $ run_teuthology_tests [tests]...
+ $ cleanup_teuthology
+
+How to write your own tests:
+ There are two possible ways to write your own API tests:
+
+ The first is by extending one of the existing test classes in the
+ ``qa/tasks/mgr/dashboard`` directory.
+
+ The second way is by adding your own API test module if you're creating a new
+ controller for example. To do so you'll just need to add the file containing
+ your new test class to the ``qa/tasks/mgr/dashboard`` directory and implement
+ all your tests here.
+
+ .. note:: Don't forget to add the path of the newly created module to
+ ``modules`` section in ``qa/suites/rados/mgr/tasks/dashboard.yaml``.
+
+ Short example: Let's assume you created a new controller called
+ ``my_new_controller.py`` and the related test module
+ ``test_my_new_controller.py``. You'll need to add
+ ``tasks.mgr.dashboard.test_my_new_controller`` to the ``modules`` section in
+ the ``dashboard.yaml`` file.
+
+ Also, if you're removing test modules please keep in mind to remove the
+ related section. Otherwise the Teuthology test run will fail.
+
+ Please run your API tests on your dev environment (as explained above)
+ before submitting a pull request. Also make sure that a full QA run in
+ Teuthology/sepia lab (based on your changes) has completed successfully
+ before it gets merged. You don't need to schedule the QA run yourself, just
+ add the 'needs-qa' label to your pull request as soon as you think it's ready
+ for merging (e.g. make check was successful, the pull request is approved and
+ all comments have been addressed). One of the developers who has access to
+ Teuthology/the sepia lab will take care of it and report the result back to
+ you.
+
+
+How to add a new controller?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A controller is a Python class that extends from the ``BaseController`` class
+and is decorated with either the ``@Controller``, ``@ApiController`` or
+``@UiApiController`` decorators. The Python class must be stored inside a Python
+file located under the ``controllers`` directory. The Dashboard module will
+automatically load your new controller upon start.
+
+``@ApiController`` and ``@UiApiController`` are both specializations of the
+``@Controller`` decorator.
+
+The ``@ApiController`` should be used for controllers that provide an API-like
+REST interface and the ``@UiApiController`` should be used for endpoints consumed
+by the UI but that are not part of the 'public' API. For any other kinds of
+controllers the ``@Controller`` decorator should be used.
+
+A controller has a URL prefix path associated that is specified in the
+controller decorator, and all endpoints exposed by the controller will share
+the same URL prefix path.
+
+A controller's endpoint is exposed by implementing a method on the controller
+class decorated with the ``@Endpoint`` decorator.
+
+For example create a file ``ping.py`` under ``controllers`` directory with the
+following code:
+
+.. code-block:: python
+
+ from ..tools import Controller, ApiController, UiApiController, BaseController, Endpoint
+
+ @Controller('/ping')
+ class Ping(BaseController):
+ @Endpoint()
+ def hello(self):
+ return {'msg': "Hello"}
+
+ @ApiController('/ping')
+ class ApiPing(BaseController):
+ @Endpoint()
+ def hello(self):
+ return {'msg': "Hello"}
+
+ @UiApiController('/ping')
+ class UiApiPing(BaseController):
+ @Endpoint()
+ def hello(self):
+ return {'msg': "Hello"}
+
+The ``hello`` endpoint of the ``Ping`` controller can be reached by the
+following URL: https://mgr_hostname:8443/ping/hello using HTTP GET requests.
+As you can see the controller URL path ``/ping`` is concatenated to the
+method name ``hello`` to generate the endpoint's URL.
+
+In the case of the ``ApiPing`` controller, the ``hello`` endpoint can be
+reached by the following URL: https://mgr_hostname:8443/api/ping/hello using a
+HTTP GET request.
+The API controller URL path ``/ping`` is prefixed by the ``/api`` path and then
+concatenated to the method name ``hello`` to generate the endpoint's URL.
+Internally, the ``@ApiController`` is actually calling the ``@Controller``
+decorator by passing an additional decorator parameter called ``base_url``::
+
+ @ApiController('/ping') <=> @Controller('/ping', base_url="/api")
+
+``UiApiPing`` works in a similar way than the ``ApiPing``, but the URL will be
+prefixed by ``/ui-api``: https://mgr_hostname:8443/ui-api/ping/hello. ``UiApiPing`` is
+also a ``@Controller`` extension::
+
+ @UiApiController('/ping') <=> @Controller('/ping', base_url="/ui-api")
+
+The ``@Endpoint`` decorator also supports many parameters to customize the
+endpoint:
+
+* ``method="GET"``: the HTTP method allowed to access this endpoint.
+* ``path="/<method_name>"``: the URL path of the endpoint, excluding the
+ controller URL path prefix.
+* ``path_params=[]``: list of method parameter names that correspond to URL
+ path parameters. Can only be used when ``method in ['POST', 'PUT']``.
+* ``query_params=[]``: list of method parameter names that correspond to URL
+ query parameters.
+* ``json_response=True``: indicates if the endpoint response should be
+ serialized in JSON format.
+* ``proxy=False``: indicates if the endpoint should be used as a proxy.
+
+An endpoint method may have parameters declared. Depending on the HTTP method
+defined for the endpoint the method parameters might be considered either
+path parameters, query parameters, or body parameters.
+
+For ``GET`` and ``DELETE`` methods, the method's non-optional parameters are
+considered path parameters by default. Optional parameters are considered
+query parameters. By specifying the ``query_parameters`` in the endpoint
+decorator it is possible to make a non-optional parameter to be a query
+parameter.
+
+For ``POST`` and ``PUT`` methods, all method parameters are considered
+body parameters by default. To override this default, one can use the
+``path_params`` and ``query_params`` to specify which method parameters are
+path and query parameters respectivelly.
+Body parameters are decoded from the request body, either from a form format, or
+from a dictionary in JSON format.
+
+Let's use an example to better understand the possible ways to customize an
+endpoint:
+
+.. code-block:: python
+
+ from ..tools import Controller, BaseController, Endpoint
+
+ @Controller('/ping')
+ class Ping(BaseController):
+
+ # URL: /ping/{key}?opt1=...&opt2=...
+ @Endpoint(path="/", query_params=['opt1'])
+ def index(self, key, opt1, opt2=None):
+ # ...
+
+ # URL: /ping/{key}?opt1=...&opt2=...
+ @Endpoint(query_params=['opt1'])
+ def __call__(self, key, opt1, opt2=None):
+ # ...
+
+ # URL: /ping/post/{key1}/{key2}
+ @Endpoint('POST', path_params=['key1', 'key2'])
+ def post(self, key1, key2, data1, data2=None):
+ # ...
+
+
+In the above example we see how the ``path`` option can be used to override the
+generated endpoint URL in order to not use the method's name in the URL. In the
+``index`` method we set the ``path`` to ``"/"`` to generate an endpoint that is
+accessible by the root URL of the controller.
+
+An alternative approach to generate an endpoint that is accessible through just
+the controller's path URL is by using the ``__call__`` method, as we show in
+the above example.
+
+From the third method you can see that the path parameters are collected from
+the URL by parsing the list of values separated by slashes ``/`` that come
+after the URL path ``/ping`` for ``index`` method case, and ``/ping/post`` for
+the ``post`` method case.
+
+Defining path parameters in endpoints's URLs using python methods's parameters
+is very easy but it is still a bit strict with respect to the position of these
+parameters in the URL structure.
+Sometimes we may want to explicitly define a URL scheme that
+contains path parameters mixed with static parts of the URL.
+Our controller infrastructure also supports the declaration of URL paths with
+explicit path parameters at both the controller level and method level.
+
+Consider the following example:
+
+.. code-block:: python
+
+ from ..tools import Controller, BaseController, Endpoint
+
+ @Controller('/ping/{node}/stats')
+ class Ping(BaseController):
+
+ # URL: /ping/{node}/stats/{date}/latency?unit=...
+ @Endpoint(path="/{date}/latency")
+ def latency(self, node, date, unit="ms"):
+ # ...
+
+In this example we explicitly declare a path parameter ``{node}`` in the
+controller URL path, and a path parameter ``{date}`` in the ``latency``
+method. The endpoint for the ``latency`` method is then accessible through
+the URL: https://mgr_hostname:8443/ping/{node}/stats/{date}/latency .
+
+For a full set of examples on how to use the ``@Endpoint``
+decorator please check the unit test file: ``tests/test_controllers.py``.
+There you will find many examples of how to customize endpoint methods.
+
+
+Implementing Proxy Controller
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes you might need to relay some requests from the Dashboard frontend
+directly to an external service.
+For that purpose we provide a decorator called ``@Proxy``.
+(As a concrete example, check the ``controllers/rgw.py`` file where we
+implemented an RGW Admin Ops proxy.)
+
+
+The ``@Proxy`` decorator is a wrapper of the ``@Endpoint`` decorator that
+already customizes the endpoint for working as a proxy.
+A proxy endpoint works by capturing the URL path that follows the controller
+URL prefix path, and does not do any decoding of the request body.
+
+Example:
+
+.. code-block:: python
+
+ from ..tools import Controller, BaseController, Proxy
+
+ @Controller('/foo/proxy')
+ class FooServiceProxy(BaseController):
+
+ @Proxy()
+ def proxy(self, path, **params):
+ # if requested URL is "/foo/proxy/access/service?opt=1"
+ # then path is "access/service" and params is {'opt': '1'}
+ # ...
+
+
+How does the RESTController work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We also provide a simple mechanism to create REST based controllers using the
+``RESTController`` class. Any class which inherits from ``RESTController`` will,
+by default, return JSON.
+
+The ``RESTController`` is basically an additional abstraction layer which eases
+and unifies the work with collections. A collection is just an array of objects
+with a specific type. ``RESTController`` enables some default mappings of
+request types and given parameters to specific method names. This may sound
+complicated at first, but it's fairly easy. Lets have look at the following
+example:
+
+.. code-block:: python
+
+ import cherrypy
+ from ..tools import ApiController, RESTController
+
+ @ApiController('ping')
+ class Ping(RESTController):
+ def list(self):
+ return {"msg": "Hello"}
+
+ def get(self, id):
+ return self.objects[id]
+
+In this case, the ``list`` method is automatically used for all requests to
+``api/ping`` where no additional argument is given and where the request type
+is ``GET``. If the request is given an additional argument, the ID in our
+case, it won't map to ``list`` anymore but to ``get`` and return the element
+with the given ID (assuming that ``self.objects`` has been filled before). The
+same applies to other request types:
+
++--------------+------------+----------------+-------------+
+| Request type | Arguments | Method | Status Code |
++==============+============+================+=============+
+| GET | No | list | 200 |
++--------------+------------+----------------+-------------+
+| PUT | No | bulk_set | 200 |
++--------------+------------+----------------+-------------+
+| POST | No | create | 201 |
++--------------+------------+----------------+-------------+
+| DELETE | No | bulk_delete | 204 |
++--------------+------------+----------------+-------------+
+| GET | Yes | get | 200 |
++--------------+------------+----------------+-------------+
+| PUT | Yes | set | 200 |
++--------------+------------+----------------+-------------+
+| DELETE | Yes | delete | 204 |
++--------------+------------+----------------+-------------+
+
+How to use a custom API endpoint in a RESTController?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you don't have any access restriction you can use ``@Endpoint``. If you
+have set a permission scope to restrict access to your endpoints,
+``@Endpoint`` will fail, as it doesn't know which permission property should be
+used. To use a custom endpoint inside a restricted ``RESTController`` use
+``@RESTController.Collection`` instead. You can also choose
+``@RESTController.Resource`` if you have set a ``RESOURCE_ID`` in your
+``RESTController`` class.
+
+.. code-block:: python
+
+ import cherrypy
+ from ..tools import ApiController, RESTController
+
+ @ApiController('ping', Scope.Ping)
+ class Ping(RESTController):
+ RESOURCE_ID = 'ping'
+
+ @RESTController.Resource('GET')
+ def some_get_endpoint(self):
+ return {"msg": "Hello"}
+
+ @RESTController.Collection('POST')
+ def some_post_endpoint(self, **data):
+ return {"msg": data}
+
+Both decorators also support four parameters to customize the
+endpoint:
+
+* ``method="GET"``: the HTTP method allowed to access this endpoint.
+* ``path="/<method_name>"``: the URL path of the endpoint, excluding the
+ controller URL path prefix.
+* ``status=200``: set the HTTP status response code
+* ``query_params=[]``: list of method parameter names that correspond to URL
+ query parameters.
+
+How to restrict access to a controller?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All controllers require authentication by default.
+If you require that the controller can be accessed without authentication,
+then you can add the parameter ``secure=False`` to the controller decorator.
+
+Example:
+
+.. code-block:: python
+
+ import cherrypy
+ from . import ApiController, RESTController
+
+
+ @ApiController('ping', secure=False)
+ class Ping(RESTController):
+ def list(self):
+ return {"msg": "Hello"}
+
+
+How to access the manager module instance from a controller?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We provide the manager module instance as a global variable that can be
+imported in any module. We also provide a logger instance in the same way.
+
+Example:
+
+.. code-block:: python
+
+ import cherrypy
+ from .. import logger, mgr
+ from ..tools import ApiController, RESTController
+
+
+ @ApiController('servers')
+ class Servers(RESTController):
+ def list(self):
+ logger.debug('Listing available servers')
+ return {'servers': mgr.list_servers()}
+
+
+How to write a unit test for a controller?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We provide a test helper class called ``ControllerTestCase`` to easily create
+unit tests for your controller.
+
+If we want to write a unit test for the above ``Ping`` controller, create a
+``test_ping.py`` file under the ``tests`` directory with the following code:
+
+.. code-block:: python
+
+ from .helper import ControllerTestCase
+ from .controllers.ping import Ping
+
+
+ class PingTest(ControllerTestCase):
+ @classmethod
+ def setup_test(cls):
+ Ping._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([Ping])
+
+ def test_ping(self):
+ self._get("/api/ping")
+ self.assertStatus(200)
+ self.assertJsonBody({'msg': 'Hello'})
+
+The ``ControllerTestCase`` class starts by initializing a CherryPy webserver.
+Then it will call the ``setup_test()`` class method where we can explicitly
+load the controllers that we want to test. In the above example we are only
+loading the ``Ping`` controller. We can also disable authentication of a
+controller at this stage, as depicted in the example.
+
+
+How to listen for manager notifications in a controller?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The manager notifies the modules of several types of cluster events, such
+as cluster logging event, etc...
+
+Each module has a "global" handler function called ``notify`` that the manager
+calls to notify the module. But this handler function must not block or spend
+too much time processing the event notification.
+For this reason we provide a notification queue that controllers can register
+themselves with to receive cluster notifications.
+
+The example below represents a controller that implements a very simple live
+log viewer page:
+
+.. code-block:: python
+
+ from __future__ import absolute_import
+
+ import collections
+
+ import cherrypy
+
+ from ..tools import ApiController, BaseController, NotificationQueue
+
+
+ @ApiController('livelog')
+ class LiveLog(BaseController):
+ log_buffer = collections.deque(maxlen=1000)
+
+ def __init__(self):
+ super(LiveLog, self).__init__()
+ NotificationQueue.register(self.log, 'clog')
+
+ def log(self, log_struct):
+ self.log_buffer.appendleft(log_struct)
+
+ @cherrypy.expose
+ def default(self):
+ ret = '<html><meta http-equiv="refresh" content="2" /><body>'
+ for l in self.log_buffer:
+ ret += "{}<br>".format(l)
+ ret += "</body></html>"
+ return ret
+
+As you can see above, the ``NotificationQueue`` class provides a register
+method that receives the function as its first argument, and receives the
+"notification type" as the second argument.
+You can omit the second argument of the ``register`` method, and in that case
+you are registering to listen all notifications of any type.
+
+Here is an list of notification types (these might change in the future) that
+can be used:
+
+* ``clog``: cluster log notifications
+* ``command``: notification when a command issued by ``MgrModule.send_command``
+ completes
+* ``perf_schema_update``: perf counters schema update
+* ``mon_map``: monitor map update
+* ``fs_map``: cephfs map update
+* ``osd_map``: OSD map update
+* ``service_map``: services (RGW, RBD-Mirror, etc.) map update
+* ``mon_status``: monitor status regular update
+* ``health``: health status regular update
+* ``pg_summary``: regular update of PG status information
+
+
+How to write a unit test when a controller accesses a Ceph module?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Consider the following example that implements a controller that retrieves the
+list of RBD images of the ``rbd`` pool:
+
+.. code-block:: python
+
+ import rbd
+ from .. import mgr
+ from ..tools import ApiController, RESTController
+
+
+ @ApiController('rbdimages')
+ class RbdImages(RESTController):
+ def __init__(self):
+ self.ioctx = mgr.rados.open_ioctx('rbd')
+ self.rbd = rbd.RBD()
+
+ def list(self):
+ return [{'name': n} for n in self.rbd.list(self.ioctx)]
+
+In the example above, we want to mock the return value of the ``rbd.list``
+function, so that we can test the JSON response of the controller.
+
+The unit test code will look like the following:
+
+.. code-block:: python
+
+ import mock
+ from .helper import ControllerTestCase
+
+
+ class RbdImagesTest(ControllerTestCase):
+ @mock.patch('rbd.RBD.list')
+ def test_list(self, rbd_list_mock):
+ rbd_list_mock.return_value = ['img1', 'img2']
+ self._get('/api/rbdimages')
+ self.assertJsonBody([{'name': 'img1'}, {'name': 'img2'}])
+
+
+
+How to add a new configuration setting?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you need to store some configuration setting for a new feature, we already
+provide an easy mechanism for you to specify/use the new config setting.
+
+For instance, if you want to add a new configuration setting to hold the
+email address of the dashboard admin, just add a setting name as a class
+attribute to the ``Options`` class in the ``settings.py`` file::
+
+ # ...
+ class Options(object):
+ # ...
+
+ ADMIN_EMAIL_ADDRESS = ('admin@admin.com', str)
+
+The value of the class attribute is a pair composed by the default value for that
+setting, and the python type of the value.
+
+By declaring the ``ADMIN_EMAIL_ADDRESS`` class attribute, when you restart the
+dashboard module, you will automatically gain two additional CLI commands to
+get and set that setting::
+
+ $ ceph dashboard get-admin-email-address
+ $ ceph dashboard set-admin-email-address <value>
+
+To access, or modify the config setting value from your Python code, either
+inside a controller or anywhere else, you just need to import the ``Settings``
+class and access it like this:
+
+.. code-block:: python
+
+ from settings import Settings
+
+ # ...
+ tmp_var = Settings.ADMIN_EMAIL_ADDRESS
+
+ # ....
+ Settings.ADMIN_EMAIL_ADDRESS = 'myemail@admin.com'
+
+The settings management implementation will make sure that if you change a
+setting value from the Python code you will see that change when accessing
+that setting from the CLI and vice-versa.
+
+
+How to run a controller read-write operation asynchronously?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some controllers might need to execute operations that alter the state of the
+Ceph cluster. These operations might take some time to execute and to maintain
+a good user experience in the Web UI, we need to run those operations
+asynchronously and return immediately to frontend some information that the
+operations are running in the background.
+
+To help in the development of the above scenario we added the support for
+asynchronous tasks. To trigger the execution of an asynchronous task we must
+use the following class method of the ``TaskManager`` class::
+
+ from ..tools import TaskManager
+ # ...
+ TaskManager.run(name, metadata, func, args, kwargs)
+
+* ``name`` is a string that can be used to group tasks. For instance
+ for RBD image creation tasks we could specify ``"rbd/create"`` as the
+ name, or similarly ``"rbd/remove"`` for RBD image removal tasks.
+
+* ``metadata`` is a dictionary where we can store key-value pairs that
+ characterize the task. For instance, when creating a task for creating
+ RBD images we can specify the metadata argument as
+ ``{'pool_name': "rbd", image_name': "test-img"}``.
+
+* ``func`` is the python function that implements the operation code, which
+ will be executed asynchronously.
+
+* ``args`` and ``kwargs`` are the positional and named arguments that will be
+ passed to ``func`` when the task manager starts its execution.
+
+The ``TaskManager.run`` method triggers the asynchronous execution of function
+``func`` and returns a ``Task`` object.
+The ``Task`` provides the public method ``Task.wait(timeout)``, which can be
+used to wait for the task to complete up to a timeout defined in seconds and
+provided as an argument. If no argument is provided the ``wait`` method
+blocks until the task is finished.
+
+The ``Task.wait`` is very useful for tasks that usually are fast to execute but
+that sometimes may take a long time to run.
+The return value of the ``Task.wait`` method is a pair ``(state, value)``
+where ``state`` is a string with following possible values:
+
+* ``VALUE_DONE = "done"``
+* ``VALUE_EXECUTING = "executing"``
+
+The ``value`` will store the result of the execution of function ``func`` if
+``state == VALUE_DONE``. If ``state == VALUE_EXECUTING`` then
+``value == None``.
+
+The pair ``(name, metadata)`` should unequivocally identify the task being
+run, which means that if you try to trigger a new task that matches the same
+``(name, metadata)`` pair of the currently running task, then the new task
+is not created and you get the task object of the current running task.
+
+For instance, consider the following example:
+
+.. code-block:: python
+
+ task1 = TaskManager.run("dummy/task", {'attr': 2}, func)
+ task2 = TaskManager.run("dummy/task", {'attr': 2}, func)
+
+If the second call to ``TaskManager.run`` executes while the first task is
+still executing then it will return the same task object:
+``assert task1 == task2``.
+
+
+How to get the list of executing and finished asynchronous tasks?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The list of executing and finished tasks is included in the ``Summary``
+controller, which is already polled every 5 seconds by the dashboard frontend.
+But we also provide a dedicated controller to get the same list of executing
+and finished tasks.
+
+The ``Task`` controller exposes the ``/api/task`` endpoint that returns the
+list of executing and finished tasks. This endpoint accepts the ``name``
+parameter that accepts a glob expression as its value.
+For instance, an HTTP GET request of the URL ``/api/task?name=rbd/*``
+will return all executing and finished tasks which name starts with ``rbd/``.
+
+To prevent the finished tasks list from growing unbounded, we will always
+maintain the 10 most recent finished tasks, and the remaining older finished
+tasks will be removed when reaching a TTL of 1 minute. The TTL is calculated
+using the timestamp when the task finished its execution. After a minute, when
+the finished task information is retrieved, either by the summary controller or
+by the task controller, it is automatically deleted from the list and it will
+not be included in further task queries.
+
+Each executing task is represented by the following dictionary::
+
+ {
+ 'name': "name", # str
+ 'metadata': { }, # dict
+ 'begin_time': "2018-03-14T15:31:38.423605Z", # str (ISO 8601 format)
+ 'progress': 0 # int (percentage)
+ }
+
+Each finished task is represented by the following dictionary::
+
+ {
+ 'name': "name", # str
+ 'metadata': { }, # dict
+ 'begin_time': "2018-03-14T15:31:38.423605Z", # str (ISO 8601 format)
+ 'end_time': "2018-03-14T15:31:39.423605Z", # str (ISO 8601 format)
+ 'duration': 0.0, # float
+ 'progress': 0 # int (percentage)
+ 'success': True, # bool
+ 'ret_value': None, # object, populated only if 'success' == True
+ 'exception': None, # str, populated only if 'success' == False
+ }
+
+
+How to use asynchronous APIs with asynchronous tasks?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``TaskManager.run`` method as described in a previous section, is well
+suited for calling blocking functions, as it runs the function inside a newly
+created thread. But sometimes we want to call some function of an API that is
+already asynchronous by nature.
+
+For these cases we want to avoid creating a new thread for just running a
+non-blocking function, and want to leverage the asynchronous nature of the
+function. The ``TaskManager.run`` is already prepared to be used with
+non-blocking functions by passing an object of the type ``TaskExecutor`` as an
+additional parameter called ``executor``. The full method signature of
+``TaskManager.run``::
+
+ TaskManager.run(name, metadata, func, args=None, kwargs=None, executor=None)
+
+
+The ``TaskExecutor`` class is responsible for code that executes a given task
+function, and defines three methods that can be overridden by
+subclasses::
+
+ def init(self, task)
+ def start(self)
+ def finish(self, ret_value, exception)
+
+The ``init`` method is called before the running the task function, and
+receives the task object (of class ``Task``).
+
+The ``start`` method runs the task function. The default implementation is to
+run the task function in the current thread context.
+
+The ``finish`` method should be called when the task function finishes with
+either the ``ret_value`` populated with the result of the execution, or with
+an exception object in the case that execution raised an exception.
+
+To leverage the asynchronous nature of a non-blocking function, the developer
+should implement a custom executor by creating a subclass of the
+``TaskExecutor`` class, and provide an instance of the custom executor class
+as the ``executor`` parameter of the ``TaskManager.run``.
+
+To better understand the expressive power of executors, we write a full example
+of use a custom executor to execute the ``MgrModule.send_command`` asynchronous
+function:
+
+.. code-block:: python
+
+ import json
+ from mgr_module import CommandResult
+ from .. import mgr
+ from ..tools import ApiController, RESTController, NotificationQueue, \
+ TaskManager, TaskExecutor
+
+
+ class SendCommandExecutor(TaskExecutor):
+ def __init__(self):
+ super(SendCommandExecutor, self).__init__()
+ self.tag = None
+ self.result = None
+
+ def init(self, task):
+ super(SendCommandExecutor, self).init(task)
+
+ # we need to listen for 'command' events to know when the command
+ # finishes
+ NotificationQueue.register(self._handler, 'command')
+
+ # store the CommandResult object to retrieve the results
+ self.result = self.task.fn_args[0]
+ if len(self.task.fn_args) > 4:
+ # the user specified a tag for the command, so let's use it
+ self.tag = self.task.fn_args[4]
+ else:
+ # let's generate a unique tag for the command
+ self.tag = 'send_command_{}'.format(id(self))
+ self.task.fn_args.append(self.tag)
+
+ def _handler(self, data):
+ if data == self.tag:
+ # the command has finished, notifying the task with the result
+ self.finish(self.result.wait(), None)
+ # deregister listener to avoid memory leaks
+ NotificationQueue.deregister(self._handler, 'command')
+
+
+ @ApiController('test')
+ class Test(RESTController):
+
+ def _run_task(self, osd_id):
+ task = TaskManager.run("test/task", {}, mgr.send_command,
+ [CommandResult(''), 'osd', osd_id,
+ json.dumps({'prefix': 'perf histogram dump'})],
+ executor=SendCommandExecutor())
+ return task.wait(1.0)
+
+ def get(self, osd_id):
+ status, value = self._run_task(osd_id)
+ return {'status': status, 'value': value}
+
+
+The above ``SendCommandExecutor`` executor class can be used for any call to
+``MgrModule.send_command``. This means that we should need just one custom
+executor class implementation for each non-blocking API that we use in our
+controllers.
+
+The default executor, used when no executor object is passed to
+``TaskManager.run``, is the ``ThreadedExecutor``. You can check its
+implementation in the ``tools.py`` file.
+
+
+How to update the execution progress of an asynchronous task?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The asynchronous tasks infrastructure provides support for updating the
+execution progress of an executing task.
+The progress can be updated from within the code the task is executing, which
+usually is the place where we have the progress information available.
+
+To update the progress from within the task code, the ``TaskManager`` class
+provides a method to retrieve the current task object::
+
+ TaskManager.current_task()
+
+The above method is only available when using the default executor
+``ThreadedExecutor`` for executing the task.
+The ``current_task()`` method returns the current ``Task`` object. The
+``Task`` object provides two public methods to update the execution progress
+value: the ``set_progress(percentage)``, and the ``inc_progress(delta)``
+methods.
+
+The ``set_progress`` method receives as argument an integer value representing
+the absolute percentage that we want to set to the task.
+
+The ``inc_progress`` method receives as argument an integer value representing
+the delta we want to increment to the current execution progress percentage.
+
+Take the following example of a controller that triggers a new task and
+updates its progress:
+
+.. code-block:: python
+
+ from __future__ import absolute_import
+ import random
+ import time
+ import cherrypy
+ from ..tools import TaskManager, ApiController, BaseController
+
+
+ @ApiController('dummy_task')
+ class DummyTask(BaseController):
+ def _dummy(self):
+ top = random.randrange(100)
+ for i in range(top):
+ TaskManager.current_task().set_progress(i*100/top)
+ # or TaskManager.current_task().inc_progress(100/top)
+ time.sleep(1)
+ return "finished"
+
+ @cherrypy.expose
+ @cherrypy.tools.json_out()
+ def default(self):
+ task = TaskManager.run("dummy/task", {}, self._dummy)
+ return task.wait(5) # wait for five seconds
+
+
+How to deal with asynchronous tasks in the front-end?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All executing and most recently finished asynchronous tasks are displayed on
+"Background-Tasks" and if finished on "Recent-Notifications" in the menu bar.
+For each task a operation name for three states (running, success and failure),
+a function that tells who is involved and error descriptions, if any, have to
+be provided. This can be achieved by appending
+``TaskManagerMessageService.messages``. This has to be done to achieve
+consistency among all tasks and states.
+
+Operation Object
+ Ensures consistency among all tasks. It consists of three verbs for each
+ different state f.e.
+ ``{running: 'Creating', failure: 'create', success: 'Created'}``.
+
+#. Put running operations in present participle f.e. ``'Updating'``.
+#. Failed messages always start with ``'Failed to '`` and should be continued
+ with the operation in present tense f.e. ``'update'``.
+#. Put successful operations in past tense f.e. ``'Updated'``.
+
+Involves Function
+ Ensures consistency among all messages of a task, it resembles who's
+ involved by the operation. It's a function that returns a string which
+ takes the metadata from the task to return f.e.
+ ``"RBD 'somePool/someImage'"``.
+
+Both combined create the following messages:
+
+* Failure => ``"Failed to create RBD 'somePool/someImage'"``
+* Running => ``"Creating RBD 'somePool/someImage'"``
+* Success => ``"Created RBD 'somePool/someImage'"``
+
+For automatic task handling use ``TaskWrapperService.wrapTaskAroundCall``.
+
+If for some reason ``wrapTaskAroundCall`` is not working for you,
+you have to subscribe to your asynchronous task manually through
+``TaskManagerService.subscribe``, and provide it with a callback,
+in case of a success to notify the user. A notification can
+be triggered with ``NotificationService.notifyTask``. It will use
+``TaskManagerMessageService.messages`` to display a message based on the state
+of a task.
+
+Notifications of API errors are handled by ``ApiInterceptorService``.
+
+Usage example:
+
+.. code-block:: javascript
+
+ export class TaskManagerMessageService {
+ // ...
+ messages = {
+ // Messages for task 'rbd/create'
+ 'rbd/create': new TaskManagerMessage(
+ // Message prefixes
+ ['create', 'Creating', 'Created'],
+ // Message suffix
+ (metadata) => `RBD '${metadata.pool_name}/${metadata.image_name}'`,
+ (metadata) => ({
+ // Error code and description
+ '17': `Name is already used by RBD '${metadata.pool_name}/${
+ metadata.image_name}'.`
+ })
+ ),
+ // ...
+ };
+ // ...
+ }
+
+ export class RBDFormComponent {
+ // ...
+ createAction() {
+ const request = this.createRequest();
+ // Subscribes to 'call' with submitted 'task' and handles notifications
+ return this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/create', {
+ pool_name: request.pool_name,
+ image_name: request.name
+ }),
+ call: this.rbdService.create(request)
+ });
+ }
+ // ...
+ }
+
+
+REST API documentation
+~~~~~~~~~~~~~~~~~~~~~~
+There is an automatically generated Swagger UI page for documentation of the REST
+API endpoints.However, by default it is not very detailed. There are two
+decorators that can be used to add more information:
+
+* ``@EndpointDoc()`` for documentation of endpoints. It has four optional arguments
+ (explained below): ``description``, ``group``, ``parameters`` and``responses``.
+* ``@ControllerDoc()`` for documentation of controller or group associated with
+ the endpoints. It only takes the two first arguments: ``description`` and``group``.
+
+
+``description``: A a string with a short (1-2 sentences) description of the object.
+
+
+``group``: By default, an endpoint is grouped together with other endpoints
+within the same controller class. ``group`` is a string that can be used to
+assign an endpoint or all endpoints in a class to another controller or a
+conceived group name.
+
+
+``parameters``: A dict used to describe path, query or request body parameters.
+By default, all parameters for an endpoint are listed on the Swagger UI page,
+including information of whether the parameter is optional/required and default
+values. However, there will be no description of the parameter and the parameter
+type will only be displayed in some cases.
+When adding information, each parameters should be described as in the example
+below. Note that the parameter type should be expressed as a built-in python
+type and not as a string. Allowed values are ``str``, ``int``, ``bool``, ``float``.
+
+.. code-block:: python
+
+ @EndpointDoc(parameters={'my_string': (str, 'Description of my_string')})
+
+For body parameters, more complex cases are possible. If the parameter is a
+dictionary, the type should be replaced with a ``dict`` containing its nested
+parameters. When describing nested parameters, the same format as other
+parameters is used. However, all nested parameters are set as required by default.
+If the nested parameter is optional this must be specified as for ``item2`` in
+the example below. If a nested parameters is set to optional, it is also
+possible to specify the default value (this will not be provided automatically
+for nested parameters).
+
+.. code-block:: python
+
+ @EndpointDoc(parameters={
+ 'my_dictionary': ({
+ 'item1': (str, 'Description of item1'),
+ 'item2': (str, 'Description of item2', True), # item2 is optional
+ 'item3': (str, 'Description of item3', True, 'foo'), # item3 is optional with 'foo' as default value
+ }, 'Description of my_dictionary')})
+
+If the parameter is a ``list`` of primitive types, the type should be
+surrounded with square brackets.
+
+.. code-block:: python
+
+ @EndpointDoc(parameters={'my_list': ([int], 'Description of my_list')})
+
+If the parameter is a ``list`` with nested parameters, the nested parameters
+should be placed in a dictionary and surrounded with square brackets.
+
+.. code-block:: python
+
+ @EndpointDoc(parameters={
+ 'my_list': ([{
+ 'list_item': (str, 'Description of list_item'),
+ 'list_item2': (str, 'Description of list_item2')
+ }], 'Description of my_list')})
+
+
+``responses``: A dict used for describing responses. Rules for describing
+responses are the same as for request body parameters, with one difference:
+responses also needs to be assigned to the related response code as in the
+example below:
+
+.. code-block:: python
+
+ @EndpointDoc(responses={
+ '400':{'my_response': (str, 'Description of my_response')}
+
+
+Error Handling in Python
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Good error handling is a key requirement in creating a good user experience
+and providing a good API.
+
+Dashboard code should not duplicate C++ code. Thus, if error handling in C++
+is sufficient to provide good feedback, a new wrapper to catch these errors
+is not necessary. On the other hand, input validation is the best place to
+catch errors and generate the best error messages. If required, generate
+errors as soon as possible.
+
+The backend provides few standard ways of returning errors.
+
+First, there is a generic Internal Server Error::
+
+ Status Code: 500
+ {
+ "version": <cherrypy version, e.g. 13.1.0>,
+ "detail": "The server encountered an unexpected condition which prevented it from fulfilling the request.",
+ }
+
+
+For errors generated by the backend, we provide a standard error
+format::
+
+ Status Code: 400
+ {
+ "detail": str(e), # E.g. "[errno -42] <some error message>"
+ "component": "rbd", # this can be null to represent a global error code
+ "code": "3", # Or a error name, e.g. "code": "some_error_key"
+ }
+
+
+In case, the API Endpoints uses @ViewCache to temporarily cache results,
+the error looks like so::
+
+ Status Code 400
+ {
+ "detail": str(e), # E.g. "[errno -42] <some error message>"
+ "component": "rbd", # this can be null to represent a global error code
+ "code": "3", # Or a error name, e.g. "code": "some_error_key"
+ 'status': 3, # Indicating the @ViewCache error status
+ }
+
+In case, the API Endpoints uses a task the error looks like so::
+
+ Status Code 400
+ {
+ "detail": str(e), # E.g. "[errno -42] <some error message>"
+ "component": "rbd", # this can be null to represent a global error code
+ "code": "3", # Or a error name, e.g. "code": "some_error_key"
+ "task": { # Information about the task itself
+ "name": "taskname",
+ "metadata": {...}
+ }
+ }
+
+
+Our WebUI should show errors generated by the API to the user. Especially
+field-related errors in wizards and dialogs or show non-intrusive notifications.
+
+Handling exceptions in Python should be an exception. In general, we
+should have few exception handlers in our project. Per default, propagate
+errors to the API, as it will take care of all exceptions anyway. In general,
+log the exception by adding ``logger.exception()`` with a description to the
+handler.
+
+We need to distinguish between user errors from internal errors and
+programming errors. Using different exception types will ease the
+task for the API layer and for the user interface:
+
+Standard Python errors, like ``SystemError``, ``ValueError`` or ``KeyError``
+will end up as internal server errors in the API.
+
+In general, do not ``return`` error responses in the REST API. They will be
+returned by the error handler. Instead, raise the appropriate exception.
+
+Plug-ins
+~~~~~~~~
+
+New functionality can be provided by means of a plug-in architecture. Among the
+benefits this approach brings in, loosely coupled development is one of the most
+notable. As the Ceph Dashboard grows in feature richness, its code-base becomes
+more and more complex. The hook-based nature of a plug-in architecture allows to
+extend functionality in a controlled manner, and isolate the scope of the
+changes.
+
+Ceph Dashboard relies on `Pluggy <https://pluggy.readthedocs.io>`_ to provide
+for plug-ing support. On top of pluggy, an interface-based approach has been
+implemented, with some safety checks (method override and abstract method
+checks).
+
+In order to create a new plugin, the following steps are required:
+
+#. Add a new file under ``src/pybind/mgr/dashboard/plugins``.
+#. Import the ``PLUGIN_MANAGER`` instance and the ``Interfaces``.
+#. Create a class extending the desired interfaces. The plug-in library will
+ check if all the methods of the interfaces have been properly overridden.
+#. Register the plugin in the ``PLUGIN_MANAGER`` instance.
+#. Import the plug-in from within the Ceph Dashboard ``module.py`` (currently no
+ dynamic loading is implemented).
+
+The available Mixins (helpers) are:
+
+- ``CanMgr``: provides the plug-in with access to the ``mgr`` instance under ``self.mgr``.
+- ``CanLog``: provides the plug-in with access to the Ceph Dashboard logger under ``self.log``.
+
+The available Interfaces are:
+
+- ``Initializable``: requires overriding ``init()`` hook. This method is run at
+ the very beginning of the dashboard module, right after all imports have been
+ performed.
+- ``Setupable``: requires overriding ``setup()`` hook. This method is run in the
+ Ceph Dashboard ``serve()`` method, right after CherryPy has been configured,
+ but before it is started. It's a placeholder for the plug-in initialization
+ logic.
+- ``HasOptions``: requires overriding ``get_options()`` hook by returning a list
+ of ``Options()``. The options returned here are added to the
+ ``MODULE_OPTIONS``.
+- ``HasCommands``: requires overriding ``register_commands()`` hook by defining
+ the commands the plug-in can handle and decorating them with ``@CLICommand``.
+ The commands can be optionally returned, so that they can be invoked
+ externally (which makes unit testing easier).
+- ``HasControllers``: requires overriding ``get_controllers()`` hook by defining
+ and returning the controllers as usual.
+- ``FilterRequest.BeforeHandler``: requires overriding
+ ``filter_request_before_handler()`` hook. This method receives a
+ ``cherrypy.request`` object for processing. A usual implementation of this
+ method will allow some requests to pass or will raise a ``cherrypy.HTTPError`
+ based on the ``request`` metadata and other conditions.
+
+New interfaces and hooks should be added as soon as they are required to
+implement new functionality. The above list only comprises the hooks needed for
+the existing plugins.
+
+A sample plugin implementation would look like this:
+
+.. code-block:: python
+
+ # src/pybind/mgr/dashboard/plugins/mute.py
+
+ from . import PLUGIN_MANAGER as PM
+ from . import interfaces as I
+
+ from mgr_module import CLICommand, Option
+ import cherrypy
+
+ @PM.add_plugin
+ class Mute(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions,
+ I.HasCommands, I.FilterRequest.BeforeHandler,
+ I.HasControllers):
+ @PM.add_hook
+ def get_options(self):
+ return [Option('mute', default=False, type='bool')]
+
+ @PM.add_hook
+ def setup(self):
+ self.mute = self.mgr.get_module_option('mute')
+
+ @PM.add_hook
+ def register_commands(self):
+ @CLICommand("dashboard mute")
+ def _(mgr):
+ self.mute = True
+ self.mgr.set_module_option('mute', True)
+ return 0
+
+ @PM.add_hook
+ def filter_request_before_handler(self, request):
+ if self.mute:
+ raise cherrypy.HTTPError(500, "I'm muted :-x")
+
+ @PM.add_hook
+ def get_controllers(self):
+ from ..controllers import ApiController, RESTController
+
+ @ApiController('/mute')
+ class MuteController(RESTController):
+ def get(_):
+ return self.mute
+
+ return [MuteController]
+
+
+Additionally, a helper for creating plugins ``SimplePlugin`` is provided. It
+facilitates the basic tasks (Options, Commands, and common Mixins). The previous
+plugin could be rewritten like this:
+
+.. code-block:: python
+
+ from . import PLUGIN_MANAGER as PM
+ from . import interfaces as I
+ from .plugin import SimplePlugin as SP
+
+ import cherrypy
+
+ @PM.add_plugin
+ class Mute(SP, I.Setupable, I.FilterRequest.BeforeHandler, I.HasControllers):
+ OPTIONS = [
+ SP.Option('mute', default=False, type='bool')
+ ]
+
+ def shut_up(self):
+ self.set_option('mute', True)
+ self.mute = True
+ return 0
+
+ COMMANDS = [
+ SP.Command("dashboard mute", handler=shut_up)
+ ]
+
+ @PM.add_hook
+ def setup(self):
+ self.mute = self.get_option('mute')
+
+ @PM.add_hook
+ def filter_request_before_handler(self, request):
+ if self.mute:
+ raise cherrypy.HTTPError(500, "I'm muted :-x")
+
+ @PM.add_hook
+ def get_controllers(self):
+ from ..controllers import ApiController, RESTController
+
+ @ApiController('/mute')
+ class MuteController(RESTController):
+ def get(_):
+ return self.mute
+
+ return [MuteController]
+
+
diff --git a/src/pybind/mgr/dashboard/README.rst b/src/pybind/mgr/dashboard/README.rst
new file mode 100644
index 00000000..0756845e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/README.rst
@@ -0,0 +1,37 @@
+Ceph Dashboard
+==============
+
+Overview
+--------
+
+The Ceph Dashboard is a built-in web-based Ceph management and monitoring
+application to administer various aspects and objects of the cluster. It is
+implemented as a Ceph Manager module.
+
+Enabling and Starting the Dashboard
+-----------------------------------
+
+If you want to start the dashboard from within a development environment, you
+need to have built Ceph (see the toplevel ``README.md`` file and the `developer
+documentation <http://docs.ceph.com/docs/master/dev/>`_ for details on how to
+accomplish this.
+
+Finally, you need to build the dashboard frontend code. See the file
+``HACKING.rst`` in this directory for instructions on setting up the necessary
+development environment.
+
+If you use the ``vstart.sh`` script to start up your development cluster, it
+will configure and enable the dashboard automatically. The URL and login
+credentials are displayed when the script finishes.
+
+Please see the `Ceph Dashboard documentation
+<http://docs.ceph.com/docs/master/mgr/dashboard/>`_ for details on how to enable
+and configure the dashboard manually and how to configure other settings, e.g.
+access to the Ceph object gateway.
+
+Working on the Dashboard Code
+-----------------------------
+
+If you're interested in helping with the development of the dashboard, please
+see the file ``HACKING.rst`` for details on how to set up a development
+environment and other development-related topics.
diff --git a/src/pybind/mgr/dashboard/__init__.py b/src/pybind/mgr/dashboard/__init__.py
new file mode 100644
index 00000000..798ed37e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/__init__.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=wrong-import-position,global-statement,protected-access
+"""
+ceph dashboard module
+"""
+from __future__ import absolute_import
+
+import os
+
+
+if 'UNITTEST' not in os.environ:
+ class _LoggerProxy(object):
+ def __init__(self):
+ self._logger = None
+
+ def __getattr__(self, item):
+ if self._logger is None:
+ raise AttributeError("logger not initialized")
+ return getattr(self._logger, item)
+
+ class _ModuleProxy(object):
+ def __init__(self):
+ self._mgr = None
+
+ def init(self, module_inst):
+ global logger
+ self._mgr = module_inst
+ logger._logger = self._mgr._logger
+
+ def __getattr__(self, item):
+ if self._mgr is None:
+ raise AttributeError("global manager module instance not initialized")
+ return getattr(self._mgr, item)
+
+ mgr = _ModuleProxy()
+ logger = _LoggerProxy()
+
+ from .module import Module, StandbyModule
+else:
+ import logging
+ logging.basicConfig(level=logging.DEBUG)
+ logger = logging.getLogger(__name__)
+ logging.root.handlers[0].setLevel(logging.DEBUG)
+ os.environ['PATH'] = '{}:{}'.format(os.path.abspath('../../../../build/bin'),
+ os.environ['PATH'])
+
+ # Mock ceph module otherwise every module that is involved in a testcase and imports it will
+ # raise an ImportError
+ import sys
+ import mock
+ sys.modules['ceph_module'] = mock.Mock()
+
+ mgr = mock.Mock()
+ mgr.get_frontend_path.side_effect = lambda: os.path.abspath("./frontend/dist")
diff --git a/src/pybind/mgr/dashboard/awsauth.py b/src/pybind/mgr/dashboard/awsauth.py
new file mode 100644
index 00000000..fdf87de6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/awsauth.py
@@ -0,0 +1,183 @@
+# -*- coding: utf-8 -*-
+# pylint: disable-all
+#
+# Copyright (c) 2012-2013 Paul Tax <paultax@gmail.com> All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# 3. Neither the name of Infrae nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INFRAE OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import hmac
+
+from hashlib import sha1 as sha
+
+py3k = False
+try:
+ from urlparse import urlparse, unquote
+ from base64 import encodestring
+except ImportError:
+ py3k = True
+ from urllib.parse import urlparse, unquote
+ from base64 import encodebytes as encodestring
+
+from email.utils import formatdate
+
+from requests.auth import AuthBase
+
+
+class S3Auth(AuthBase):
+
+ """Attaches AWS Authentication to the given Request object."""
+
+ service_base_url = 's3.amazonaws.com'
+ # List of Query String Arguments of Interest
+ special_params = [
+ 'acl', 'location', 'logging', 'partNumber', 'policy', 'requestPayment',
+ 'torrent', 'versioning', 'versionId', 'versions', 'website', 'uploads',
+ 'uploadId', 'response-content-type', 'response-content-language',
+ 'response-expires', 'response-cache-control', 'delete', 'lifecycle',
+ 'response-content-disposition', 'response-content-encoding', 'tagging',
+ 'notification', 'cors'
+ ]
+
+ def __init__(self, access_key, secret_key, service_url=None):
+ if service_url:
+ self.service_base_url = service_url
+ self.access_key = str(access_key)
+ self.secret_key = str(secret_key)
+
+ def __call__(self, r):
+ # Create date header if it is not created yet.
+ if 'date' not in r.headers and 'x-amz-date' not in r.headers:
+ r.headers['date'] = formatdate(
+ timeval=None,
+ localtime=False,
+ usegmt=True)
+ signature = self.get_signature(r)
+ if py3k:
+ signature = signature.decode('utf-8')
+ r.headers['Authorization'] = 'AWS %s:%s' % (self.access_key, signature)
+ return r
+
+ def get_signature(self, r):
+ canonical_string = self.get_canonical_string(
+ r.url, r.headers, r.method)
+ if py3k:
+ key = self.secret_key.encode('utf-8')
+ msg = canonical_string.encode('utf-8')
+ else:
+ key = self.secret_key
+ msg = canonical_string
+ h = hmac.new(key, msg, digestmod=sha)
+ return encodestring(h.digest()).strip()
+
+ def get_canonical_string(self, url, headers, method):
+ parsedurl = urlparse(url)
+ objectkey = parsedurl.path[1:]
+ query_args = sorted(parsedurl.query.split('&'))
+
+ bucket = parsedurl.netloc[:-len(self.service_base_url)]
+ if len(bucket) > 1:
+ # remove last dot
+ bucket = bucket[:-1]
+
+ interesting_headers = {
+ 'content-md5': '',
+ 'content-type': '',
+ 'date': ''}
+ for key in headers:
+ lk = key.lower()
+ try:
+ if isinstance(lk, bytes):
+ lk = lk.decode('utf-8')
+ except UnicodeDecodeError:
+ pass
+ if headers[key] and (lk in interesting_headers.keys()
+ or lk.startswith('x-amz-')):
+ interesting_headers[lk] = headers[key].strip()
+
+ # If x-amz-date is used it supersedes the date header.
+ if not py3k:
+ if 'x-amz-date' in interesting_headers:
+ interesting_headers['date'] = ''
+ else:
+ if 'x-amz-date' in interesting_headers:
+ interesting_headers['date'] = ''
+
+ buf = '%s\n' % method
+ for key in sorted(interesting_headers.keys()):
+ val = interesting_headers[key]
+ if key.startswith('x-amz-'):
+ buf += '%s:%s\n' % (key, val)
+ else:
+ buf += '%s\n' % val
+
+ # append the bucket if it exists
+ if bucket != '':
+ buf += '/%s' % bucket
+
+ # add the objectkey. even if it doesn't exist, add the slash
+ buf += '/%s' % objectkey
+
+ params_found = False
+
+ # handle special query string arguments
+ for q in query_args:
+ k = q.split('=')[0]
+ if k in self.special_params:
+ buf += '&' if params_found else '?'
+ params_found = True
+
+ try:
+ k, v = q.split('=', 1)
+
+ except ValueError:
+ buf += q
+
+ else:
+ # Riak CS multipart upload ids look like this, `TFDSheOgTxC2Tsh1qVK73A==`,
+ # is should be escaped to be included as part of a query string.
+ #
+ # A requests mp upload part request may look like
+ # resp = requests.put(
+ # 'https://url_here',
+ # params={
+ # 'partNumber': 1,
+ # 'uploadId': 'TFDSheOgTxC2Tsh1qVK73A=='
+ # },
+ # data='some data',
+ # auth=S3Auth('access_key', 'secret_key')
+ # )
+ #
+ # Requests automatically escapes the values in the `params` dict, so now
+ # our uploadId is `TFDSheOgTxC2Tsh1qVK73A%3D%3D`,
+ # if we sign the request with the encoded value the signature will
+ # not be valid, we'll get 403 Access Denied.
+ # So we unquote, this is no-op if the value isn't encoded.
+ buf += '{key}={value}'.format(key=k, value=unquote(v))
+
+ return buf
diff --git a/src/pybind/mgr/dashboard/cherrypy_backports.py b/src/pybind/mgr/dashboard/cherrypy_backports.py
new file mode 100644
index 00000000..524e3d58
--- /dev/null
+++ b/src/pybind/mgr/dashboard/cherrypy_backports.py
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+"""
+Copyright © 2004-2019, CherryPy Team (team@cherrypy.org)
+
+All rights reserved.
+
+* * *
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of CherryPy nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+from distutils.version import StrictVersion
+
+# The SSL code in CherryPy 3.5.0 is buggy. It was fixed long ago,
+# but 3.5.0 is still shipping in major linux distributions
+# (Fedora 27, Ubuntu Xenial), so we must monkey patch it to get SSL working.
+
+
+def patch_http_connection_init(v):
+ # It was fixed in 3.7.0. Exact lower bound version is probably earlier,
+ # but 3.5.0 is what this monkey patch is tested on.
+ if StrictVersion("3.5.0") <= v < StrictVersion("3.7.0"):
+ from cherrypy.wsgiserver.wsgiserver2 import \
+ HTTPConnection, CP_fileobject
+
+ def fixed_init(hc_self, server, sock, makefile=CP_fileobject):
+ hc_self.server = server
+ hc_self.socket = sock
+ hc_self.rfile = makefile(sock, "rb", hc_self.rbufsize)
+ hc_self.wfile = makefile(sock, "wb", hc_self.wbufsize)
+ hc_self.requests_seen = 0
+
+ HTTPConnection.__init__ = fixed_init
+
+
+# When the CherryPy server in 3.2.2 (and later) starts it attempts to verify
+# that the ports its listening on are in fact bound. When using the any address
+# "::" it tries both ipv4 and ipv6, and in some environments (e.g. kubernetes)
+# ipv6 isn't yet configured / supported and CherryPy throws an uncaught
+# exception.
+def skip_wait_for_occupied_port(v):
+ # the issue was fixed in 3.2.3. it's present in 3.2.2 (current version on
+ # centos:7) and back to at least 3.0.0.
+ if StrictVersion("3.1.2") <= v < StrictVersion("3.2.3"):
+ # https://github.com/cherrypy/cherrypy/issues/1100
+ from cherrypy.process import servers
+ servers.wait_for_occupied_port = lambda host, port: None
+
+
+# cherrypy.wsgiserver was extracted wsgiserver into cheroot in cherrypy v9.0.0
+def patch_builtin_ssl_wrap(v, new_wrap):
+ if v < StrictVersion("9.0.0"):
+ from cherrypy.wsgiserver.ssl_builtin import BuiltinSSLAdapter as builtin_ssl
+ else:
+ from cheroot.ssl.builtin import BuiltinSSLAdapter as builtin_ssl
+ builtin_ssl.wrap = new_wrap(builtin_ssl.wrap)
+
+
+def accept_exceptions_from_builtin_ssl(v):
+ # the fix was included by cheroot v5.2.0, which was included by cherrypy
+ # 10.2.0.
+ if v < StrictVersion("10.2.0"):
+ # see https://github.com/cherrypy/cheroot/pull/4
+ import ssl
+
+ def accept_ssl_errors(func):
+ def wrapper(self, sock):
+ try:
+ return func(self, sock)
+ except ssl.SSLError as e:
+ if e.errno == ssl.SSL_ERROR_SSL:
+ # Check if it's one of the known errors
+ # Errors that are caught by PyOpenSSL, but thrown by
+ # built-in ssl
+ _block_errors = ('unknown protocol', 'unknown ca', 'unknown_ca',
+ 'unknown error',
+ 'https proxy request', 'inappropriate fallback',
+ 'wrong version number',
+ 'no shared cipher', 'certificate unknown',
+ 'ccs received early',
+ 'certificate verify failed', # client cert w/o trusted CA
+ 'version too low', # caused by SSL3 connections
+ 'unsupported protocol', # caused by TLS1 connections
+ 'sslv3 alert bad certificate')
+ for error_text in _block_errors:
+ if error_text in e.args[1].lower():
+ # Accepted error, let's pass
+ return None, {}
+ raise
+ return wrapper
+ patch_builtin_ssl_wrap(v, accept_ssl_errors)
+
+
+def accept_socket_error_0(v):
+ # see https://github.com/cherrypy/cherrypy/issues/1618
+ try:
+ import cheroot
+ cheroot_version = cheroot.__version__
+ except ImportError:
+ pass
+
+ if v < StrictVersion("9.0.0") or cheroot_version < StrictVersion("6.5.5"):
+ import six
+ if six.PY3:
+ generic_socket_error = OSError
+ else:
+ import socket
+ generic_socket_error = socket.error
+
+ def accept_socket_error_0(func):
+ def wrapper(self, sock):
+ try:
+ return func(self, sock)
+ except generic_socket_error as e:
+ """It is unclear why exactly this happens.
+
+ It's reproducible only with openssl>1.0 and stdlib ``ssl`` wrapper.
+ In CherryPy it's triggered by Checker plugin, which connects
+ to the app listening to the socket port in TLS mode via plain
+ HTTP during startup (from the same process).
+
+ Ref: https://github.com/cherrypy/cherrypy/issues/1618
+ """
+ import ssl
+ is_error0 = e.args == (0, 'Error')
+ IS_ABOVE_OPENSSL10 = ssl.OPENSSL_VERSION_INFO >= (1, 1)
+ del ssl
+ if is_error0 and IS_ABOVE_OPENSSL10:
+ return None, {}
+ raise
+ return wrapper
+ patch_builtin_ssl_wrap(v, accept_socket_error_0)
+
+
+def patch_request_unique_id(v):
+ """
+ Older versions of cherrypy don't include request.unique_id field (a lazily
+ calculated UUID4).
+
+ Monkey-patching is preferred over alternatives as inheritance, as it'd break
+ type checks (cherrypy/lib/cgtools.py: `isinstance(obj, _cprequest.Request)`)
+ """
+ if v < StrictVersion('11.1.0'):
+ import uuid
+ from functools import update_wrapper
+ from cherrypy._cprequest import Request
+
+ class LazyUUID4(object):
+ def __str__(self):
+ """Return UUID4 and keep it for future calls."""
+ return str(self.uuid4)
+
+ @property
+ def uuid4(self):
+ """Provide unique id on per-request basis using UUID4.
+ It's evaluated lazily on render.
+ """
+ try:
+ self._uuid4
+ except AttributeError:
+ # evaluate on first access
+ self._uuid4 = uuid.uuid4()
+
+ return self._uuid4
+
+ old_init = Request.__init__
+
+ def init_with_unique_id(self, *args, **kwargs):
+ old_init(self, *args, **kwargs)
+ self.unique_id = LazyUUID4()
+
+ Request.__init__ = update_wrapper(init_with_unique_id, old_init)
+
+
+def patch_cherrypy(v):
+ patch_http_connection_init(v)
+ skip_wait_for_occupied_port(v)
+ accept_exceptions_from_builtin_ssl(v)
+ accept_socket_error_0(v)
+ patch_request_unique_id(v)
diff --git a/src/pybind/mgr/dashboard/ci/check_grafana_uids.py b/src/pybind/mgr/dashboard/ci/check_grafana_uids.py
new file mode 100644
index 00000000..134bb6e7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/ci/check_grafana_uids.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=F0401
+"""
+This script does:
+* Scan through Angular html templates and extract <cd-grafana> tags
+* Check if every tag has a corresponding Grafana dashboard by `uid`
+
+Usage:
+ python <script> <angular_app_dir> <grafana_dashboard_dir>
+
+e.g.
+ cd /ceph/src/pybind/mgr/dashboard
+ python ci/<script> frontend/src/app /ceph/monitoring/grafana/dashboards
+"""
+import argparse
+import codecs
+import copy
+import json
+import os
+
+import six
+from six.moves.html_parser import HTMLParser
+
+
+class TemplateParser(HTMLParser):
+
+ def __init__(self, _file, search_tag):
+ if six.PY3:
+ super(TemplateParser, self).__init__()
+ else:
+ # HTMLParser is not a new-style class in py2
+ HTMLParser.__init__(self)
+ self.search_tag = search_tag
+ self.file = _file
+ self.parsed_data = []
+
+ def parse(self):
+ with codecs.open(self.file, encoding='UTF-8') as f:
+ self.feed(f.read())
+
+ def handle_starttag(self, tag, attrs):
+ if tag != self.search_tag:
+ return
+ tag_data = {
+ 'file': self.file,
+ 'attrs': dict(attrs),
+ 'line': self.getpos()[0]
+ }
+ self.parsed_data.append(tag_data)
+
+ def error(self, message):
+ error_msg = 'fail to parse file {} (@{}): {}'.\
+ format(self.file, self.getpos(), message)
+ exit(error_msg)
+
+
+def stdout(msg):
+ six.print_(msg)
+
+
+def get_files(base_dir, file_ext):
+ result = []
+ for root, _, files in os.walk(base_dir):
+ for _file in files:
+ if _file.endswith('.{}'.format(file_ext)):
+ result.append(os.path.join(root, _file))
+ return result
+
+
+def get_tags(base_dir, tag='cd-grafana'):
+ templates = get_files(base_dir, 'html')
+ tags = []
+ for templ in templates:
+ parser = TemplateParser(templ, tag)
+ parser.parse()
+ if parser.parsed_data:
+ tags.extend(parser.parsed_data)
+ return tags
+
+
+def get_grafana_dashboards(base_dir):
+ json_files = get_files(base_dir, 'json')
+ dashboards = {}
+ for json_file in json_files:
+ with open(json_file) as f:
+ dashboard_config = json.load(f)
+ uid = dashboard_config.get('uid')
+ if not uid:
+ continue
+ if uid in dashboards:
+ # duplicated uids
+ error_msg = 'Duplicated UID {} found, already defined in {}'.\
+ format(uid, dashboards[uid]['file'])
+ exit(error_msg)
+ dashboards[uid] = {
+ 'file': json_file,
+ 'title': dashboard_config['title']
+ }
+ return dashboards
+
+
+def parse_args():
+ long_desc = ('Check every <cd-grafana> component in Angular template has a'
+ ' mapped Grafana dashboard.')
+ parser = argparse.ArgumentParser(description=long_desc)
+ parser.add_argument('angular_app_dir', type=str,
+ help='Angular app base directory')
+ parser.add_argument('grafana_dash_dir', type=str,
+ help='Directory contains Grafana dashboard JSON files')
+ parser.add_argument('--verbose', action='store_true',
+ help='Display verbose mapping information.')
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+ tags = get_tags(args.angular_app_dir)
+ grafana_dashboards = get_grafana_dashboards(args.grafana_dash_dir)
+ verbose = args.verbose
+
+ if not tags:
+ error_msg = 'Can not find any cd-grafana component under {}'.\
+ format(args.angular_app_dir)
+ exit(error_msg)
+
+ if verbose:
+ stdout('Found mappings:')
+ no_dashboard_tags = []
+ for tag in tags:
+ uid = tag['attrs']['uid']
+ if uid not in grafana_dashboards:
+ no_dashboard_tags.append(copy.copy(tag))
+ continue
+ if verbose:
+ msg = '{} ({}:{}) \n\t-> {} ({})'.\
+ format(uid, tag['file'], tag['line'],
+ grafana_dashboards[uid]['title'],
+ grafana_dashboards[uid]['file'])
+ stdout(msg)
+
+ if no_dashboard_tags:
+ title = ('Checking Grafana dashboards UIDs: ERROR\n'
+ 'Components that have no mapped Grafana dashboards:\n')
+ lines = ('{} ({}:{})'.format(tag['attrs']['uid'],
+ tag['file'],
+ tag['line'])
+ for tag in no_dashboard_tags)
+ error_msg = title + '\n'.join(lines)
+ exit(error_msg)
+ else:
+ stdout('Checking Grafana dashboards UIDs: OK')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/pybind/mgr/dashboard/constraints.txt b/src/pybind/mgr/dashboard/constraints.txt
new file mode 100644
index 00000000..f7a1f59d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/constraints.txt
@@ -0,0 +1,9 @@
+CherryPy==13.1.0
+enum34==1.1.6
+more-itertools==4.1.0
+PyJWT==2.0.1
+bcrypt==3.1.4
+python3-saml==1.4.1
+requests==2.20.0
+Routes==2.4.1
+six==1.14.0
diff --git a/src/pybind/mgr/dashboard/controllers/__init__.py b/src/pybind/mgr/dashboard/controllers/__init__.py
new file mode 100644
index 00000000..17e293e7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/__init__.py
@@ -0,0 +1,957 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=protected-access,too-many-branches
+from __future__ import absolute_import
+
+import collections
+import importlib
+import inspect
+import json
+import os
+import pkgutil
+import re
+import sys
+
+if sys.version_info >= (3, 0):
+ from urllib.parse import unquote # pylint: disable=no-name-in-module,import-error
+else:
+ from urllib import unquote # pylint: disable=no-name-in-module
+
+# pylint: disable=wrong-import-position
+import cherrypy
+
+from .. import logger
+from ..security import Scope, Permission
+from ..tools import wraps, getargspec, TaskManager, get_request_body_params
+from ..exceptions import ScopeNotValid, PermissionNotValid
+from ..services.auth import AuthManager, JwtManager
+from ..plugins import PLUGIN_MANAGER
+
+
+def EndpointDoc(description="", group="", parameters=None, responses=None):
+ if not isinstance(description, str):
+ raise Exception("%s has been called with a description that is not a string: %s"
+ % (EndpointDoc.__name__, description))
+ elif not isinstance(group, str):
+ raise Exception("%s has been called with a groupname that is not a string: %s"
+ % (EndpointDoc.__name__, group))
+ elif parameters and not isinstance(parameters, dict):
+ raise Exception("%s has been called with parameters that is not a dict: %s"
+ % (EndpointDoc.__name__, parameters))
+ elif responses and not isinstance(responses, dict):
+ raise Exception("%s has been called with responses that is not a dict: %s"
+ % (EndpointDoc.__name__, responses))
+
+ if not parameters:
+ parameters = {}
+
+ def _split_param(name, p_type, description, optional=False, default_value=None, nested=False):
+ param = {
+ 'name': name,
+ 'description': description,
+ 'required': not optional,
+ 'nested': nested,
+ }
+ if default_value:
+ param['default'] = default_value
+ if isinstance(p_type, type):
+ param['type'] = p_type
+ else:
+ nested_params = _split_parameters(p_type, nested=True)
+ if nested_params:
+ param['type'] = type(p_type)
+ param['nested_params'] = nested_params
+ else:
+ param['type'] = p_type
+ return param
+
+ # Optional must be set to True in order to set default value and parameters format must be:
+ # 'name: (type or nested parameters, description, [optional], [default value])'
+ def _split_dict(data, nested):
+ splitted = []
+ for name, props in data.items():
+ if isinstance(name, str) and isinstance(props, tuple):
+ if len(props) == 2:
+ param = _split_param(name, props[0], props[1], nested=nested)
+ elif len(props) == 3:
+ param = _split_param(name, props[0], props[1], optional=props[2], nested=nested)
+ if len(props) == 4:
+ param = _split_param(name, props[0], props[1], props[2], props[3], nested)
+ splitted.append(param)
+ else:
+ raise Exception(
+ """Parameter %s in %s has not correct format. Valid formats are:
+ <name>: (<type>, <description>, [optional], [default value])
+ <name>: (<[type]>, <description>, [optional], [default value])
+ <name>: (<[nested parameters]>, <description>, [optional], [default value])
+ <name>: (<{nested parameters}>, <description>, [optional], [default value])"""
+ % (name, EndpointDoc.__name__))
+ return splitted
+
+ def _split_list(data, nested):
+ splitted = []
+ for item in data:
+ splitted.extend(_split_parameters(item, nested))
+ return splitted
+
+ # nested = True means parameters are inside a dict or array
+ def _split_parameters(data, nested=False):
+ param_list = []
+ if isinstance(data, dict):
+ param_list.extend(_split_dict(data, nested))
+ elif isinstance(data, (list, tuple)):
+ param_list.extend(_split_list(data, True))
+ return param_list
+
+ resp = {}
+ if responses:
+ for status_code, response_body in responses.items():
+ resp[str(status_code)] = _split_parameters(response_body)
+
+ def _wrapper(func):
+ func.doc_info = {
+ 'summary': description,
+ 'tag': group,
+ 'parameters': _split_parameters(parameters),
+ 'response': resp
+ }
+ return func
+
+ return _wrapper
+
+
+class ControllerDoc(object):
+ def __init__(self, description="", group=""):
+ self.tag = group
+ self.tag_descr = description
+
+ def __call__(self, cls):
+ cls.doc_info = {
+ 'tag': self.tag,
+ 'tag_descr': self.tag_descr
+ }
+ return cls
+
+
+class Controller(object):
+ def __init__(self, path, base_url=None, security_scope=None, secure=True):
+ if security_scope and not Scope.valid_scope(security_scope):
+ logger.debug("Invalid security scope name: %s\n Possible values: "
+ "%s", security_scope, Scope.all_scopes())
+ raise ScopeNotValid(security_scope)
+ self.path = path
+ self.base_url = base_url
+ self.security_scope = security_scope
+ self.secure = secure
+
+ if self.path and self.path[0] != "/":
+ self.path = "/" + self.path
+
+ if self.base_url is None:
+ self.base_url = ""
+ elif self.base_url == "/":
+ self.base_url = ""
+
+ if self.base_url == "" and self.path == "":
+ self.base_url = "/"
+
+ def __call__(self, cls):
+ cls._cp_controller_ = True
+ cls._cp_path_ = "{}{}".format(self.base_url, self.path)
+ cls._security_scope = self.security_scope
+
+ config = {
+ 'tools.dashboard_exception_handler.on': True,
+ 'tools.authenticate.on': self.secure,
+ }
+ if not hasattr(cls, '_cp_config'):
+ cls._cp_config = {}
+ cls._cp_config.update(config)
+ return cls
+
+
+class ApiController(Controller):
+ def __init__(self, path, security_scope=None, secure=True):
+ super(ApiController, self).__init__(path, base_url="/api",
+ security_scope=security_scope,
+ secure=secure)
+
+ def __call__(self, cls):
+ cls = super(ApiController, self).__call__(cls)
+ cls._api_endpoint = True
+ return cls
+
+
+class UiApiController(Controller):
+ def __init__(self, path, security_scope=None, secure=True):
+ super(UiApiController, self).__init__(path, base_url="/ui-api",
+ security_scope=security_scope,
+ secure=secure)
+
+
+def Endpoint(method=None, path=None, path_params=None, query_params=None,
+ json_response=True, proxy=False, xml=False):
+
+ if method is None:
+ method = 'GET'
+ elif not isinstance(method, str) or \
+ method.upper() not in ['GET', 'POST', 'DELETE', 'PUT']:
+ raise TypeError("Possible values for method are: 'GET', 'POST', "
+ "'DELETE', or 'PUT'")
+
+ method = method.upper()
+
+ if method in ['GET', 'DELETE']:
+ if path_params is not None:
+ raise TypeError("path_params should not be used for {} "
+ "endpoints. All function params are considered"
+ " path parameters by default".format(method))
+
+ if path_params is None:
+ if method in ['POST', 'PUT']:
+ path_params = []
+
+ if query_params is None:
+ query_params = []
+
+ def _wrapper(func):
+ if method in ['POST', 'PUT']:
+ func_params = _get_function_params(func)
+ for param in func_params:
+ if param['name'] in path_params and not param['required']:
+ raise TypeError("path_params can only reference "
+ "non-optional function parameters")
+
+ if func.__name__ == '__call__' and path is None:
+ e_path = ""
+ else:
+ e_path = path
+
+ if e_path is not None:
+ e_path = e_path.strip()
+ if e_path and e_path[0] != "/":
+ e_path = "/" + e_path
+ elif e_path == "/":
+ e_path = ""
+
+ func._endpoint = {
+ 'method': method,
+ 'path': e_path,
+ 'path_params': path_params,
+ 'query_params': query_params,
+ 'json_response': json_response,
+ 'proxy': proxy,
+ 'xml': xml
+ }
+ return func
+ return _wrapper
+
+
+def Proxy(path=None):
+ if path is None:
+ path = ""
+ elif path == "/":
+ path = ""
+ path += "/{path:.*}"
+ return Endpoint(path=path, proxy=True)
+
+
+def load_controllers():
+ # setting sys.path properly when not running under the mgr
+ controllers_dir = os.path.dirname(os.path.realpath(__file__))
+ dashboard_dir = os.path.dirname(controllers_dir)
+ mgr_dir = os.path.dirname(dashboard_dir)
+ logger.debug("LC: controllers_dir=%s", controllers_dir)
+ logger.debug("LC: dashboard_dir=%s", dashboard_dir)
+ logger.debug("LC: mgr_dir=%s", mgr_dir)
+ if mgr_dir not in sys.path:
+ sys.path.append(mgr_dir)
+
+ controllers = []
+ mods = [mod for _, mod, _ in pkgutil.iter_modules([controllers_dir])]
+ logger.debug("LC: mods=%s", mods)
+ for mod_name in mods:
+ mod = importlib.import_module('.controllers.{}'.format(mod_name),
+ package='dashboard')
+ for _, cls in mod.__dict__.items():
+ # Controllers MUST be derived from the class BaseController.
+ if inspect.isclass(cls) and issubclass(cls, BaseController) and \
+ hasattr(cls, '_cp_controller_'):
+ if cls._cp_path_.startswith(':'):
+ # invalid _cp_path_ value
+ logger.error("Invalid url prefix '%s' for controller '%s'",
+ cls._cp_path_, cls.__name__)
+ continue
+ controllers.append(cls)
+
+ for clist in PLUGIN_MANAGER.hook.get_controllers() or []:
+ controllers.extend(clist)
+
+ return controllers
+
+
+ENDPOINT_MAP = collections.defaultdict(list)
+
+
+def generate_controller_routes(endpoint, mapper, base_url):
+ inst = endpoint.inst
+ ctrl_class = endpoint.ctrl
+
+ if endpoint.proxy:
+ conditions = None
+ else:
+ conditions = dict(method=[endpoint.method])
+
+ # base_url can be empty or a URL path that starts with "/"
+ # we will remove the trailing "/" if exists to help with the
+ # concatenation with the endpoint url below
+ if base_url.endswith("/"):
+ base_url = base_url[:-1]
+
+ endp_url = endpoint.url
+
+ if endp_url.find("/", 1) == -1:
+ parent_url = "{}{}".format(base_url, endp_url)
+ else:
+ parent_url = "{}{}".format(base_url, endp_url[:endp_url.find("/", 1)])
+
+ # parent_url might be of the form "/.../{...}" where "{...}" is a path parameter
+ # we need to remove the path parameter definition
+ parent_url = re.sub(r'(?:/\{[^}]+\})$', '', parent_url)
+ if not parent_url: # root path case
+ parent_url = "/"
+
+ url = "{}{}".format(base_url, endp_url)
+
+ logger.debug("Mapped [%s] to %s:%s restricted to %s",
+ url, ctrl_class.__name__, endpoint.action,
+ endpoint.method)
+
+ ENDPOINT_MAP[endpoint.url].append(endpoint)
+
+ name = ctrl_class.__name__ + ":" + endpoint.action
+ mapper.connect(name, url, controller=inst, action=endpoint.action,
+ conditions=conditions)
+
+ # adding route with trailing slash
+ name += "/"
+ url += "/"
+ mapper.connect(name, url, controller=inst, action=endpoint.action,
+ conditions=conditions)
+
+ return parent_url
+
+
+def generate_routes(url_prefix):
+ mapper = cherrypy.dispatch.RoutesDispatcher()
+ ctrls = load_controllers()
+
+ parent_urls = set()
+
+ endpoint_list = []
+ for ctrl in ctrls:
+ inst = ctrl()
+ for endpoint in ctrl.endpoints():
+ endpoint.inst = inst
+ endpoint_list.append(endpoint)
+
+ endpoint_list = sorted(endpoint_list, key=lambda e: e.url)
+ for endpoint in endpoint_list:
+ parent_urls.add(generate_controller_routes(endpoint, mapper,
+ "{}".format(url_prefix)))
+
+ logger.debug("list of parent paths: %s", parent_urls)
+ return mapper, parent_urls
+
+
+def json_error_page(status, message, traceback, version):
+ cherrypy.response.headers['Content-Type'] = 'application/json'
+ return json.dumps(dict(status=status, detail=message, traceback=traceback,
+ version=version))
+
+
+def _get_function_params(func):
+ """
+ Retrieves the list of parameters declared in function.
+ Each parameter is represented as dict with keys:
+ * name (str): the name of the parameter
+ * required (bool): whether the parameter is required or not
+ * default (obj): the parameter's default value
+ """
+ fspec = getargspec(func)
+
+ func_params = []
+ nd = len(fspec.args) if not fspec.defaults else -len(fspec.defaults)
+ for param in fspec.args[1:nd]:
+ func_params.append({'name': param, 'required': True})
+
+ if fspec.defaults:
+ for param, val in zip(fspec.args[nd:], fspec.defaults):
+ func_params.append({
+ 'name': param,
+ 'required': False,
+ 'default': val
+ })
+
+ return func_params
+
+
+class Task(object):
+ def __init__(self, name, metadata, wait_for=5.0, exception_handler=None):
+ self.name = name
+ if isinstance(metadata, list):
+ self.metadata = {e[1:-1]: e for e in metadata}
+ else:
+ self.metadata = metadata
+ self.wait_for = wait_for
+ self.exception_handler = exception_handler
+
+ def _gen_arg_map(self, func, args, kwargs):
+ arg_map = {}
+ params = _get_function_params(func)
+
+ args = args[1:] # exclude self
+ for idx, param in enumerate(params):
+ if idx < len(args):
+ arg_map[param['name']] = args[idx]
+ else:
+ if param['name'] in kwargs:
+ arg_map[param['name']] = kwargs[param['name']]
+ else:
+ assert not param['required'], "{0} is required".format(param['name'])
+ arg_map[param['name']] = param['default']
+
+ if param['name'] in arg_map:
+ # This is not a type error. We are using the index here.
+ arg_map[idx+1] = arg_map[param['name']]
+
+ return arg_map
+
+ def __call__(self, func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ arg_map = self._gen_arg_map(func, args, kwargs)
+ metadata = {}
+ for k, v in self.metadata.items():
+ if isinstance(v, str) and v and v[0] == '{' and v[-1] == '}':
+ param = v[1:-1]
+ try:
+ pos = int(param)
+ metadata[k] = arg_map[pos]
+ except ValueError:
+ if param.find('.') == -1:
+ metadata[k] = arg_map[param]
+ else:
+ path = param.split('.')
+ metadata[k] = arg_map[path[0]]
+ for i in range(1, len(path)):
+ metadata[k] = metadata[k][path[i]]
+ else:
+ metadata[k] = v
+ task = TaskManager.run(self.name, metadata, func, args, kwargs,
+ exception_handler=self.exception_handler)
+ try:
+ status, value = task.wait(self.wait_for)
+ except Exception as ex:
+ if task.ret_value:
+ # exception was handled by task.exception_handler
+ if 'status' in task.ret_value:
+ status = task.ret_value['status']
+ else:
+ status = getattr(ex, 'status', 500)
+ cherrypy.response.status = status
+ return task.ret_value
+ raise ex
+ if status == TaskManager.VALUE_EXECUTING:
+ cherrypy.response.status = 202
+ return {'name': self.name, 'metadata': metadata}
+ return value
+ return wrapper
+
+
+class BaseController(object):
+ """
+ Base class for all controllers providing API endpoints.
+ """
+
+ class Endpoint(object):
+ """
+ An instance of this class represents an endpoint.
+ """
+
+ def __init__(self, ctrl, func):
+ self.ctrl = ctrl
+ self.inst = None
+ self.func = func
+
+ if not self.config['proxy']:
+ setattr(self.ctrl, func.__name__, self.function)
+
+ @property
+ def config(self):
+ func = self.func
+ while not hasattr(func, '_endpoint'):
+ if hasattr(func, "__wrapped__"):
+ func = func.__wrapped__
+ else:
+ return None
+ return func._endpoint
+
+ @property
+ def function(self):
+ return self.ctrl._request_wrapper(self.func, self.method,
+ self.config['json_response'],
+ self.config['xml'])
+
+ @property
+ def method(self):
+ return self.config['method']
+
+ @property
+ def proxy(self):
+ return self.config['proxy']
+
+ @property
+ def url(self):
+ ctrl_path = self.ctrl.get_path()
+ if ctrl_path == "/":
+ ctrl_path = ""
+ if self.config['path'] is not None:
+ url = "{}{}".format(ctrl_path, self.config['path'])
+ else:
+ url = "{}/{}".format(ctrl_path, self.func.__name__)
+
+ ctrl_path_params = self.ctrl.get_path_param_names(
+ self.config['path'])
+ path_params = [p['name'] for p in self.path_params
+ if p['name'] not in ctrl_path_params]
+ path_params = ["{{{}}}".format(p) for p in path_params]
+ if path_params:
+ url += "/{}".format("/".join(path_params))
+
+ return url
+
+ @property
+ def action(self):
+ return self.func.__name__
+
+ @property
+ def path_params(self):
+ ctrl_path_params = self.ctrl.get_path_param_names(
+ self.config['path'])
+ func_params = _get_function_params(self.func)
+
+ if self.method in ['GET', 'DELETE']:
+ assert self.config['path_params'] is None
+
+ return [p for p in func_params if p['name'] in ctrl_path_params
+ or (p['name'] not in self.config['query_params']
+ and p['required'])]
+
+ # elif self.method in ['POST', 'PUT']:
+ return [p for p in func_params if p['name'] in ctrl_path_params
+ or p['name'] in self.config['path_params']]
+
+ @property
+ def query_params(self):
+ if self.method in ['GET', 'DELETE']:
+ func_params = _get_function_params(self.func)
+ path_params = [p['name'] for p in self.path_params]
+ return [p for p in func_params if p['name'] not in path_params]
+
+ # elif self.method in ['POST', 'PUT']:
+ func_params = _get_function_params(self.func)
+ return [p for p in func_params
+ if p['name'] in self.config['query_params']]
+
+ @property
+ def body_params(self):
+ func_params = _get_function_params(self.func)
+ path_params = [p['name'] for p in self.path_params]
+ query_params = [p['name'] for p in self.query_params]
+ return [p for p in func_params
+ if p['name'] not in path_params
+ and p['name'] not in query_params]
+
+ @property
+ def group(self):
+ return self.ctrl.__name__
+
+ @property
+ def is_api(self):
+ return hasattr(self.ctrl, '_api_endpoint')
+
+ @property
+ def is_secure(self):
+ return self.ctrl._cp_config['tools.authenticate.on']
+
+ def __repr__(self):
+ return "Endpoint({}, {}, {})".format(self.url, self.method,
+ self.action)
+
+ def __init__(self):
+ logger.info('Initializing controller: %s -> %s',
+ self.__class__.__name__, self._cp_path_)
+ super(BaseController, self).__init__()
+
+ def _has_permissions(self, permissions, scope=None):
+ if not self._cp_config['tools.authenticate.on']:
+ raise Exception("Cannot verify permission in non secured "
+ "controllers")
+
+ if not isinstance(permissions, list):
+ permissions = [permissions]
+
+ if scope is None:
+ scope = getattr(self, '_security_scope', None)
+ if scope is None:
+ raise Exception("Cannot verify permissions without scope security"
+ " defined")
+ username = JwtManager.LOCAL_USER.username
+ return AuthManager.authorize(username, scope, permissions)
+
+ @classmethod
+ def get_path_param_names(cls, path_extension=None):
+ if path_extension is None:
+ path_extension = ""
+ full_path = cls._cp_path_[1:] + path_extension
+ path_params = []
+ for step in full_path.split('/'):
+ param = None
+ if not step:
+ continue
+ if step[0] == ':':
+ param = step[1:]
+ elif step[0] == '{' and step[-1] == '}':
+ param, _, _ = step[1:-1].partition(':')
+ if param:
+ path_params.append(param)
+ return path_params
+
+ @classmethod
+ def get_path(cls):
+ return cls._cp_path_
+
+ @classmethod
+ def endpoints(cls):
+ """
+ This method iterates over all the methods decorated with ``@endpoint``
+ and creates an Endpoint object for each one of the methods.
+
+ :return: A list of endpoint objects
+ :rtype: list[BaseController.Endpoint]
+ """
+ result = []
+ for _, func in inspect.getmembers(cls, predicate=callable):
+ if hasattr(func, '_endpoint'):
+ result.append(cls.Endpoint(cls, func))
+ return result
+
+ @staticmethod
+ def _request_wrapper(func, method, json_response, xml): # pylint: disable=unused-argument
+ @wraps(func)
+ def inner(*args, **kwargs):
+ for key, value in kwargs.items():
+ # pylint: disable=undefined-variable
+ if (sys.version_info < (3, 0) and isinstance(value, unicode)) \
+ or isinstance(value, str):
+ kwargs[key] = unquote(value)
+
+ # Process method arguments.
+ params = get_request_body_params(cherrypy.request)
+ kwargs.update(params)
+
+ ret = func(*args, **kwargs)
+ if isinstance(ret, bytes):
+ ret = ret.decode('utf-8')
+ if xml:
+ cherrypy.response.headers['Content-Type'] = 'application/xml'
+ return ret.encode('utf8')
+ if json_response:
+ cherrypy.response.headers['Content-Type'] = 'application/json'
+ ret = json.dumps(ret).encode('utf8')
+ return ret
+ return inner
+
+ @property
+ def _request(self):
+ return self.Request(cherrypy.request)
+
+ class Request(object):
+ def __init__(self, cherrypy_req):
+ self._creq = cherrypy_req
+
+ @property
+ def scheme(self):
+ return self._creq.scheme
+
+ @property
+ def host(self):
+ base = self._creq.base
+ base = base[len(self.scheme)+3:]
+ return base[:base.find(":")] if ":" in base else base
+
+ @property
+ def port(self):
+ base = self._creq.base
+ base = base[len(self.scheme)+3:]
+ default_port = 443 if self.scheme == 'https' else 80
+ return int(base[base.find(":")+1:]) if ":" in base else default_port
+
+ @property
+ def path_info(self):
+ return self._creq.path_info
+
+
+class RESTController(BaseController):
+ """
+ Base class for providing a RESTful interface to a resource.
+
+ To use this class, simply derive a class from it and implement the methods
+ you want to support. The list of possible methods are:
+
+ * list()
+ * bulk_set(data)
+ * create(data)
+ * bulk_delete()
+ * get(key)
+ * set(data, key)
+ * delete(key)
+
+ Test with curl:
+
+ curl -H "Content-Type: application/json" -X POST \
+ -d '{"username":"xyz","password":"xyz"}' https://127.0.0.1:8443/foo
+ curl https://127.0.0.1:8443/foo
+ curl https://127.0.0.1:8443/foo/0
+
+ """
+
+ # resource id parameter for using in get, set, and delete methods
+ # should be overridden by subclasses.
+ # to specify a composite id (two parameters) use '/'. e.g., "param1/param2".
+ # If subclasses don't override this property we try to infer the structure
+ # of the resource ID.
+ RESOURCE_ID = None
+
+ _permission_map = {
+ 'GET': Permission.READ,
+ 'POST': Permission.CREATE,
+ 'PUT': Permission.UPDATE,
+ 'DELETE': Permission.DELETE
+ }
+
+ _method_mapping = collections.OrderedDict([
+ ('list', {'method': 'GET', 'resource': False, 'status': 200}),
+ ('create', {'method': 'POST', 'resource': False, 'status': 201}),
+ ('bulk_set', {'method': 'PUT', 'resource': False, 'status': 200}),
+ ('bulk_delete', {'method': 'DELETE', 'resource': False, 'status': 204}),
+ ('get', {'method': 'GET', 'resource': True, 'status': 200}),
+ ('delete', {'method': 'DELETE', 'resource': True, 'status': 204}),
+ ('set', {'method': 'PUT', 'resource': True, 'status': 200})
+ ])
+
+ @classmethod
+ def infer_resource_id(cls):
+ if cls.RESOURCE_ID is not None:
+ return cls.RESOURCE_ID.split('/')
+ for k, v in cls._method_mapping.items():
+ func = getattr(cls, k, None)
+ while hasattr(func, "__wrapped__"):
+ func = func.__wrapped__
+ if v['resource'] and func:
+ path_params = cls.get_path_param_names()
+ params = _get_function_params(func)
+ return [p['name'] for p in params
+ if p['required'] and p['name'] not in path_params]
+ return None
+
+ @classmethod
+ def endpoints(cls):
+ result = super(RESTController, cls).endpoints()
+ res_id_params = cls.infer_resource_id()
+
+ for _, func in inspect.getmembers(cls, predicate=callable):
+ no_resource_id_params = False
+ status = 200
+ method = None
+ query_params = None
+ path = ""
+ sec_permissions = hasattr(func, '_security_permissions')
+ permission = None
+
+ if func.__name__ in cls._method_mapping:
+ meth = cls._method_mapping[func.__name__]
+
+ if meth['resource']:
+ if not res_id_params:
+ no_resource_id_params = True
+ else:
+ path_params = ["{{{}}}".format(p) for p in res_id_params]
+ path += "/{}".format("/".join(path_params))
+
+ status = meth['status']
+ method = meth['method']
+ if not sec_permissions:
+ permission = cls._permission_map[method]
+
+ elif hasattr(func, "_collection_method_"):
+ if func._collection_method_['path']:
+ path = func._collection_method_['path']
+ else:
+ path = "/{}".format(func.__name__)
+ status = func._collection_method_['status']
+ method = func._collection_method_['method']
+ query_params = func._collection_method_['query_params']
+ if not sec_permissions:
+ permission = cls._permission_map[method]
+
+ elif hasattr(func, "_resource_method_"):
+ if not res_id_params:
+ no_resource_id_params = True
+ else:
+ path_params = ["{{{}}}".format(p) for p in res_id_params]
+ path += "/{}".format("/".join(path_params))
+ if func._resource_method_['path']:
+ path += func._resource_method_['path']
+ else:
+ path += "/{}".format(func.__name__)
+ status = func._resource_method_['status']
+ method = func._resource_method_['method']
+ query_params = func._resource_method_['query_params']
+ if not sec_permissions:
+ permission = cls._permission_map[method]
+
+ else:
+ continue
+
+ if no_resource_id_params:
+ raise TypeError("Could not infer the resource ID parameters for"
+ " method {} of controller {}. "
+ "Please specify the resource ID parameters "
+ "using the RESOURCE_ID class property"
+ .format(func.__name__, cls.__name__))
+
+ if method in ['GET', 'DELETE']:
+ params = _get_function_params(func)
+ if res_id_params is None:
+ res_id_params = []
+ if query_params is None:
+ query_params = [p['name'] for p in params
+ if p['name'] not in res_id_params]
+
+ func = cls._status_code_wrapper(func, status)
+ endp_func = Endpoint(method, path=path,
+ query_params=query_params)(func)
+ if permission:
+ _set_func_permissions(endp_func, [permission])
+ result.append(cls.Endpoint(cls, endp_func))
+
+ return result
+
+ @classmethod
+ def _status_code_wrapper(cls, func, status_code):
+ @wraps(func)
+ def wrapper(*vpath, **params):
+ cherrypy.response.status = status_code
+ return func(*vpath, **params)
+
+ return wrapper
+
+ @staticmethod
+ def Resource(method=None, path=None, status=None, query_params=None):
+ if not method:
+ method = 'GET'
+
+ if status is None:
+ status = 200
+
+ def _wrapper(func):
+ func._resource_method_ = {
+ 'method': method,
+ 'path': path,
+ 'status': status,
+ 'query_params': query_params
+ }
+ return func
+ return _wrapper
+
+ @staticmethod
+ def Collection(method=None, path=None, status=None, query_params=None):
+ if not method:
+ method = 'GET'
+
+ if status is None:
+ status = 200
+
+ def _wrapper(func):
+ func._collection_method_ = {
+ 'method': method,
+ 'path': path,
+ 'status': status,
+ 'query_params': query_params
+ }
+ return func
+ return _wrapper
+
+
+# Role-based access permissions decorators
+
+def _set_func_permissions(func, permissions):
+ if not isinstance(permissions, list):
+ permissions = [permissions]
+
+ for perm in permissions:
+ if not Permission.valid_permission(perm):
+ logger.debug("Invalid security permission: %s\n "
+ "Possible values: %s", perm,
+ Permission.all_permissions())
+ raise PermissionNotValid(perm)
+
+ if not hasattr(func, '_security_permissions'):
+ func._security_permissions = permissions
+ else:
+ permissions.extend(func._security_permissions)
+ func._security_permissions = list(set(permissions))
+
+
+def ReadPermission(func):
+ _set_func_permissions(func, Permission.READ)
+ return func
+
+
+def CreatePermission(func):
+ _set_func_permissions(func, Permission.CREATE)
+ return func
+
+
+def DeletePermission(func):
+ _set_func_permissions(func, Permission.DELETE)
+ return func
+
+
+def UpdatePermission(func):
+ _set_func_permissions(func, Permission.UPDATE)
+ return func
+
+
+# Empty request body decorator
+
+def allow_empty_body(func): # noqa: N802
+ """
+ The POST/PUT request methods decorated with ``@allow_empty_body``
+ are allowed to send empty request body.
+ """
+ try:
+ func._cp_config['tools.json_in.force'] = False
+ except (AttributeError, KeyError):
+ func._cp_config = {'tools.json_in.force': False}
+ return func
+
+
+def set_cookies(url_prefix, token):
+ cherrypy.response.cookie['token'] = token
+ if url_prefix == 'https':
+ cherrypy.response.cookie['token']['secure'] = True
+ cherrypy.response.cookie['token']['HttpOnly'] = True
+ cherrypy.response.cookie['token']['path'] = '/'
+ cherrypy.response.cookie['token']['SameSite'] = 'Strict'
diff --git a/src/pybind/mgr/dashboard/controllers/auth.py b/src/pybind/mgr/dashboard/controllers/auth.py
new file mode 100644
index 00000000..51139bef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/auth.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+try:
+ import Cookie
+except ImportError:
+ import http.cookies as Cookie
+import sys
+import jwt
+
+from . import ApiController, RESTController, \
+ allow_empty_body, set_cookies
+from .. import logger, mgr
+from ..exceptions import DashboardException
+from ..services.auth import AuthManager, JwtManager
+from ..services.access_control import UserDoesNotExist
+# Python 3.8 introduced `samesite` attribute:
+# https://docs.python.org/3/library/http.cookies.html#morsel-objects
+if sys.version_info < (3, 8):
+ Cookie.Morsel._reserved["samesite"] = "SameSite" # type: ignore # pylint: disable=W0212
+
+
+@ApiController('/auth', secure=False)
+class Auth(RESTController):
+ """
+ Provide authenticates and returns JWT token.
+ """
+
+ def create(self, username, password):
+ user_perms = AuthManager.authenticate(username, password)
+ if user_perms is not None:
+ url_prefix = 'https' if mgr.get_localized_module_option('ssl') else 'http'
+ logger.debug('Login successful')
+ token = JwtManager.gen_token(username)
+
+ # For backward-compatibility: PyJWT versions < 2.0.0 return bytes.
+ token = token.decode('utf-8') if isinstance(token, bytes) else token
+
+ set_cookies(url_prefix, token)
+ return {
+ 'token': token,
+ 'username': username,
+ 'permissions': user_perms
+ }
+
+ logger.debug('Login failed')
+ raise DashboardException(msg='Invalid credentials',
+ code='invalid_credentials',
+ component='auth')
+
+ @RESTController.Collection('POST')
+ @allow_empty_body
+ def logout(self):
+ logger.debug('Logout successful')
+ token = JwtManager.get_token_from_header()
+ JwtManager.blacklist_token(token)
+ redirect_url = '#/login'
+ if mgr.SSO_DB.protocol == 'saml2':
+ redirect_url = 'auth/saml2/slo'
+ return {
+ 'redirect_url': redirect_url
+ }
+
+ def _get_login_url(self):
+ if mgr.SSO_DB.protocol == 'saml2':
+ return 'auth/saml2/login'
+ return '#/login'
+
+ @RESTController.Collection('POST')
+ def check(self, token):
+ if token:
+ try:
+ token = JwtManager.decode_token(token)
+ if not JwtManager.is_blacklisted(token['jti']):
+ user = AuthManager.get_user(token['username'])
+ if user.lastUpdate <= token['iat']:
+ return {
+ 'username': user.username,
+ 'permissions': user.permissions_dict(),
+ }
+
+ logger.debug("AMT: user info changed after token was"
+ " issued, iat=%s lastUpdate=%s",
+ token['iat'], user.lastUpdate)
+ else:
+ logger.debug('AMT: Token is black-listed')
+ except jwt.exceptions.ExpiredSignatureError:
+ logger.debug("AMT: Token has expired")
+ except jwt.exceptions.InvalidTokenError:
+ logger.debug("AMT: Failed to decode token")
+ except UserDoesNotExist:
+ logger.debug("AMT: Invalid token: user %s does not exist",
+ token['username'])
+ return {
+ 'login_url': self._get_login_url()
+ }
diff --git a/src/pybind/mgr/dashboard/controllers/cephfs.py b/src/pybind/mgr/dashboard/controllers/cephfs.py
new file mode 100644
index 00000000..788a865a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/cephfs.py
@@ -0,0 +1,294 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from collections import defaultdict
+
+import cherrypy
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..exceptions import DashboardException
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..tools import ViewCache
+
+
+@ApiController('/cephfs', Scope.CEPHFS)
+class CephFS(RESTController):
+ def __init__(self):
+ super(CephFS, self).__init__()
+
+ # Stateful instances of CephFSClients, hold cached results. Key to
+ # dict is FSCID
+ self.cephfs_clients = {}
+
+ def list(self):
+ fsmap = mgr.get("fs_map")
+ return fsmap['filesystems']
+
+ def get(self, fs_id):
+ fs_id = self.fs_id_to_int(fs_id)
+
+ return self.fs_status(fs_id)
+
+ @RESTController.Resource('GET')
+ def clients(self, fs_id):
+ fs_id = self.fs_id_to_int(fs_id)
+
+ return self._clients(fs_id)
+
+ @RESTController.Resource('GET')
+ def mds_counters(self, fs_id):
+ """
+ Result format: map of daemon name to map of counter to list of datapoints
+ rtype: dict[str, dict[str, list]]
+ """
+
+ # Opinionated list of interesting performance counters for the GUI --
+ # if you need something else just add it. See how simple life is
+ # when you don't have to write general purpose APIs?
+ counters = [
+ "mds_server.handle_client_request",
+ "mds_log.ev",
+ "mds_cache.num_strays",
+ "mds.exported",
+ "mds.exported_inodes",
+ "mds.imported",
+ "mds.imported_inodes",
+ "mds.inodes",
+ "mds.caps",
+ "mds.subtrees",
+ "mds_mem.ino"
+ ]
+
+ fs_id = self.fs_id_to_int(fs_id)
+
+ result = {}
+ mds_names = self._get_mds_names(fs_id)
+
+ for mds_name in mds_names:
+ result[mds_name] = {}
+ for counter in counters:
+ data = mgr.get_counter("mds", mds_name, counter)
+ if data is not None:
+ result[mds_name][counter] = data[counter]
+ else:
+ result[mds_name][counter] = []
+
+ return dict(result)
+
+ @staticmethod
+ def fs_id_to_int(fs_id):
+ try:
+ return int(fs_id)
+ except ValueError:
+ raise DashboardException(code='invalid_cephfs_id',
+ msg="Invalid cephfs ID {}".format(fs_id),
+ component='cephfs')
+
+ def _get_mds_names(self, filesystem_id=None):
+ names = []
+
+ fsmap = mgr.get("fs_map")
+ for fs in fsmap['filesystems']:
+ if filesystem_id is not None and fs['id'] != filesystem_id:
+ continue
+ names.extend([info['name']
+ for _, info in fs['mdsmap']['info'].items()])
+
+ if filesystem_id is None:
+ names.extend(info['name'] for info in fsmap['standbys'])
+
+ return names
+
+ def _append_mds_metadata(self, mds_versions, metadata_key):
+ metadata = mgr.get_metadata('mds', metadata_key)
+ if metadata is None:
+ return
+ mds_versions[metadata.get('ceph_version', 'unknown')].append(metadata_key)
+
+ # pylint: disable=too-many-statements,too-many-branches
+ def fs_status(self, fs_id):
+ mds_versions = defaultdict(list)
+
+ fsmap = mgr.get("fs_map")
+ filesystem = None
+ for fs in fsmap['filesystems']:
+ if fs['id'] == fs_id:
+ filesystem = fs
+ break
+
+ if filesystem is None:
+ raise cherrypy.HTTPError(404,
+ "CephFS id {0} not found".format(fs_id))
+
+ rank_table = []
+
+ mdsmap = filesystem['mdsmap']
+
+ client_count = 0
+
+ for rank in mdsmap["in"]:
+ up = "mds_{0}".format(rank) in mdsmap["up"]
+ if up:
+ gid = mdsmap['up']["mds_{0}".format(rank)]
+ info = mdsmap['info']['gid_{0}'.format(gid)]
+ dns = mgr.get_latest("mds", info['name'], "mds_mem.dn")
+ inos = mgr.get_latest("mds", info['name'], "mds_mem.ino")
+
+ if rank == 0:
+ client_count = mgr.get_latest("mds", info['name'],
+ "mds_sessions.session_count")
+ elif client_count == 0:
+ # In case rank 0 was down, look at another rank's
+ # sessionmap to get an indication of clients.
+ client_count = mgr.get_latest("mds", info['name'],
+ "mds_sessions.session_count")
+
+ laggy = "laggy_since" in info
+
+ state = info['state'].split(":")[1]
+ if laggy:
+ state += "(laggy)"
+
+ # Populate based on context of state, e.g. client
+ # ops for an active daemon, replay progress, reconnect
+ # progress
+ if state == "active":
+ activity = CephService.get_rate("mds",
+ info['name'],
+ "mds_server.handle_client_request")
+ else:
+ activity = 0.0
+
+ self._append_mds_metadata(mds_versions, info['name'])
+ rank_table.append(
+ {
+ "rank": rank,
+ "state": state,
+ "mds": info['name'],
+ "activity": activity,
+ "dns": dns,
+ "inos": inos
+ }
+ )
+
+ else:
+ rank_table.append(
+ {
+ "rank": rank,
+ "state": "failed",
+ "mds": "",
+ "activity": 0.0,
+ "dns": 0,
+ "inos": 0
+ }
+ )
+
+ # Find the standby replays
+ # pylint: disable=unused-variable
+ for gid_str, daemon_info in mdsmap['info'].items():
+ if daemon_info['state'] != "up:standby-replay":
+ continue
+
+ inos = mgr.get_latest("mds", daemon_info['name'], "mds_mem.ino")
+ dns = mgr.get_latest("mds", daemon_info['name'], "mds_mem.dn")
+
+ activity = CephService.get_rate(
+ "mds", daemon_info['name'], "mds_log.replay")
+
+ rank_table.append(
+ {
+ "rank": "{0}-s".format(daemon_info['rank']),
+ "state": "standby-replay",
+ "mds": daemon_info['name'],
+ "activity": activity,
+ "dns": dns,
+ "inos": inos
+ }
+ )
+
+ df = mgr.get("df")
+ pool_stats = {p['id']: p['stats'] for p in df['pools']}
+ osdmap = mgr.get("osd_map")
+ pools = {p['pool']: p for p in osdmap['pools']}
+ metadata_pool_id = mdsmap['metadata_pool']
+ data_pool_ids = mdsmap['data_pools']
+
+ pools_table = []
+ for pool_id in [metadata_pool_id] + data_pool_ids:
+ pool_type = "metadata" if pool_id == metadata_pool_id else "data"
+ stats = pool_stats[pool_id]
+ pools_table.append({
+ "pool": pools[pool_id]['pool_name'],
+ "type": pool_type,
+ "used": stats['bytes_used'],
+ "avail": stats['max_avail']
+ })
+
+ standby_table = []
+ for standby in fsmap['standbys']:
+ self._append_mds_metadata(mds_versions, standby['name'])
+ standby_table.append({
+ 'name': standby['name']
+ })
+
+ return {
+ "cephfs": {
+ "id": fs_id,
+ "name": mdsmap['fs_name'],
+ "client_count": client_count,
+ "ranks": rank_table,
+ "pools": pools_table
+ },
+ "standbys": standby_table,
+ "versions": mds_versions
+ }
+
+ def _clients(self, fs_id):
+ cephfs_clients = self.cephfs_clients.get(fs_id, None)
+ if cephfs_clients is None:
+ cephfs_clients = CephFSClients(mgr, fs_id)
+ self.cephfs_clients[fs_id] = cephfs_clients
+
+ try:
+ status, clients = cephfs_clients.get()
+ except AttributeError:
+ raise cherrypy.HTTPError(404,
+ "No cephfs with id {0}".format(fs_id))
+
+ if clients is None:
+ raise cherrypy.HTTPError(404,
+ "No cephfs with id {0}".format(fs_id))
+
+ # Decorate the metadata with some fields that will be
+ # indepdendent of whether it's a kernel or userspace
+ # client, so that the javascript doesn't have to grok that.
+ for client in clients:
+ if "ceph_version" in client['client_metadata']:
+ client['type'] = "userspace"
+ client['version'] = client['client_metadata']['ceph_version']
+ client['hostname'] = client['client_metadata']['hostname']
+ elif "kernel_version" in client['client_metadata']:
+ client['type'] = "kernel"
+ client['version'] = client['client_metadata']['kernel_version']
+ client['hostname'] = client['client_metadata']['hostname']
+ else:
+ client['type'] = "unknown"
+ client['version'] = ""
+ client['hostname'] = ""
+
+ return {
+ 'status': status,
+ 'data': clients
+ }
+
+
+class CephFSClients(object):
+ def __init__(self, module_inst, fscid):
+ self._module = module_inst
+ self.fscid = fscid
+
+ @ViewCache()
+ def get(self):
+ return CephService.send_command('mds', 'session ls', srv_spec='{0}:0'.format(self.fscid))
diff --git a/src/pybind/mgr/dashboard/controllers/cluster_configuration.py b/src/pybind/mgr/dashboard/controllers/cluster_configuration.py
new file mode 100644
index 00000000..8401b09e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/cluster_configuration.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cherrypy
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..exceptions import DashboardException
+
+
+@ApiController('/cluster_conf', Scope.CONFIG_OPT)
+class ClusterConfiguration(RESTController):
+
+ def _append_config_option_values(self, options):
+ """
+ Appends values from the config database (if available) to the given options
+ :param options: list of config options
+ :return: list of config options extended by their current values
+ """
+ config_dump = CephService.send_command('mon', 'config dump')
+ for config_dump_entry in config_dump:
+ for i, elem in enumerate(options):
+ if config_dump_entry['name'] == elem['name']:
+ if 'value' not in elem:
+ options[i]['value'] = []
+ options[i]['source'] = 'mon'
+
+ options[i]['value'].append({'section': config_dump_entry['section'],
+ 'value': config_dump_entry['value']})
+ return options
+
+ def list(self):
+ options = mgr.get('config_options')['options']
+ return self._append_config_option_values(options)
+
+ def get(self, name):
+ return self._get_config_option(name)
+
+ @RESTController.Collection('GET', query_params=['name'])
+ def filter(self, names=None):
+ config_options = []
+
+ if names:
+ for name in names.split(','):
+ try:
+ config_options.append(self._get_config_option(name))
+ except cherrypy.HTTPError:
+ pass
+
+ if not config_options:
+ raise cherrypy.HTTPError(404, 'Config options `{}` not found'.format(names))
+
+ return config_options
+
+ def create(self, name, value):
+ # Check if config option is updateable at runtime
+ self._updateable_at_runtime([name])
+
+ # Update config option
+ availSections = ['global', 'mon', 'mgr', 'osd', 'mds', 'client']
+
+ for section in availSections:
+ for entry in value:
+ if entry['value'] is None:
+ break
+
+ if entry['section'] == section:
+ CephService.send_command('mon', 'config set', who=section, name=name,
+ value=str(entry['value']))
+ break
+ else:
+ CephService.send_command('mon', 'config rm', who=section, name=name)
+
+ def delete(self, name, section):
+ return CephService.send_command('mon', 'config rm', who=section, name=name)
+
+ def bulk_set(self, options):
+ self._updateable_at_runtime(options.keys())
+
+ for name, value in options.items():
+ CephService.send_command('mon', 'config set', who=value['section'],
+ name=name, value=str(value['value']))
+
+ def _get_config_option(self, name):
+ for option in mgr.get('config_options')['options']:
+ if option['name'] == name:
+ return self._append_config_option_values([option])[0]
+
+ raise cherrypy.HTTPError(404)
+
+ def _updateable_at_runtime(self, config_option_names):
+ not_updateable = []
+
+ for name in config_option_names:
+ config_option = self._get_config_option(name)
+ if not config_option['can_update_at_runtime']:
+ not_updateable.append(name)
+
+ if not_updateable:
+ raise DashboardException(
+ msg='Config option {} is/are not updatable at runtime'.format(
+ ', '.join(not_updateable)),
+ code='config_option_not_updatable_at_runtime',
+ component='cluster_configuration')
diff --git a/src/pybind/mgr/dashboard/controllers/docs.py b/src/pybind/mgr/dashboard/controllers/docs.py
new file mode 100644
index 00000000..70bea7c4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/docs.py
@@ -0,0 +1,427 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cherrypy
+
+from . import Controller, BaseController, Endpoint, ENDPOINT_MAP
+from .. import logger, mgr
+
+from ..tools import str_to_bool
+
+
+@Controller('/docs', secure=False)
+class Docs(BaseController):
+
+ @classmethod
+ def _gen_tags(cls, all_endpoints):
+ """ Generates a list of all tags and corresponding descriptions. """
+ # Scenarios to consider:
+ # * Intentionally make up a new tag name at controller => New tag name displayed.
+ # * Misspell or make up a new tag name at endpoint => Neither tag or endpoint displayed.
+ # * Misspell tag name at controller (when referring to another controller) =>
+ # Tag displayed but no endpoints assigned
+ # * Description for a tag added at multiple locations => Only one description displayed.
+ list_of_ctrl = set()
+ for endpoints in ENDPOINT_MAP.values():
+ for endpoint in endpoints:
+ if endpoint.is_api or all_endpoints:
+ list_of_ctrl.add(endpoint.ctrl)
+
+ TAG_MAP = {}
+ for ctrl in list_of_ctrl:
+ tag_name = ctrl.__name__
+ tag_descr = ""
+ if hasattr(ctrl, 'doc_info'):
+ if ctrl.doc_info['tag']:
+ tag_name = ctrl.doc_info['tag']
+ tag_descr = ctrl.doc_info['tag_descr']
+ if tag_name not in TAG_MAP or not TAG_MAP[tag_name]:
+ TAG_MAP[tag_name] = tag_descr
+
+ tags = [{'name': k, 'description': v if v else "*No description available*"}
+ for k, v in TAG_MAP.items()]
+ tags.sort(key=lambda e: e['name'])
+ return tags
+
+ @classmethod
+ def _get_tag(cls, endpoint):
+ """ Returns the name of a tag to assign to a path. """
+ ctrl = endpoint.ctrl
+ func = endpoint.func
+ tag = ctrl.__name__
+ if hasattr(func, 'doc_info') and func.doc_info['tag']:
+ tag = func.doc_info['tag']
+ elif hasattr(ctrl, 'doc_info') and ctrl.doc_info['tag']:
+ tag = ctrl.doc_info['tag']
+ return tag
+
+ @classmethod
+ def _gen_type(cls, param):
+ # pylint: disable=too-many-return-statements
+ """
+ Generates the type of parameter based on its name and default value,
+ using very simple heuristics.
+ Used if type is not explicitly defined.
+ """
+ param_name = param['name']
+ def_value = param['default'] if 'default' in param else None
+ if param_name.startswith("is_"):
+ return "boolean"
+ if "size" in param_name:
+ return "integer"
+ if "count" in param_name:
+ return "integer"
+ if "num" in param_name:
+ return "integer"
+ if isinstance(def_value, bool):
+ return "boolean"
+ if isinstance(def_value, int):
+ return "integer"
+ return "string"
+
+ @classmethod
+ # isinstance doesn't work: input is always <type 'type'>.
+ def _type_to_str(cls, type_as_type):
+ """ Used if type is explicitly defined. """
+ if type_as_type is str:
+ type_as_str = 'string'
+ elif type_as_type is int:
+ type_as_str = 'integer'
+ elif type_as_type is bool:
+ type_as_str = 'boolean'
+ elif type_as_type is list or type_as_type is tuple:
+ type_as_str = 'array'
+ elif type_as_type is float:
+ type_as_str = 'number'
+ else:
+ type_as_str = 'object'
+ return type_as_str
+
+ @classmethod
+ def _add_param_info(cls, parameters, p_info):
+ # Cases to consider:
+ # * Parameter name (if not nested) misspelt in decorator => parameter not displayed
+ # * Sometimes a parameter is used for several endpoints (e.g. fs_id in CephFS).
+ # Currently, there is no possibility of reuse. Should there be?
+ # But what if there are two parameters with same name but different functionality?
+ """
+ Adds explicitly described information for parameters of an endpoint.
+
+ There are two cases:
+ * Either the parameter in p_info corresponds to an endpoint parameter. Implicit information
+ has higher priority, so only information that doesn't already exist is added.
+ * Or the parameter in p_info describes a nested parameter inside an endpoint parameter.
+ In that case there is no implicit information at all so all explicitly described info needs
+ to be added.
+ """
+ for p in p_info:
+ if not p['nested']:
+ for parameter in parameters:
+ if p['name'] == parameter['name']:
+ parameter['type'] = p['type']
+ parameter['description'] = p['description']
+ if 'nested_params' in p:
+ parameter['nested_params'] = cls._add_param_info([], p['nested_params'])
+ else:
+ nested_p = {
+ 'name': p['name'],
+ 'type': p['type'],
+ 'description': p['description'],
+ 'required': p['required'],
+ }
+ if 'default' in p:
+ nested_p['default'] = p['default']
+ if 'nested_params' in p:
+ nested_p['nested_params'] = cls._add_param_info([], p['nested_params'])
+ parameters.append(nested_p)
+
+ return parameters
+
+ @classmethod
+ def _gen_schema_for_content(cls, params):
+ """
+ Generates information to the content-object in OpenAPI Spec.
+ Used to for request body and responses.
+ """
+ required_params = []
+ properties = {}
+
+ for param in params:
+ if param['required']:
+ required_params.append(param['name'])
+
+ props = {}
+ if 'type' in param:
+ props['type'] = cls._type_to_str(param['type'])
+ if 'nested_params' in param:
+ if props['type'] == 'array': # dict in array
+ props['items'] = cls._gen_schema_for_content(param['nested_params'])
+ else: # dict in dict
+ props = cls._gen_schema_for_content(param['nested_params'])
+ elif props['type'] == 'object': # e.g. [int]
+ props['type'] = 'array'
+ props['items'] = {'type': cls._type_to_str(param['type'][0])}
+ else:
+ props['type'] = cls._gen_type(param)
+ if 'description' in param:
+ props['description'] = param['description']
+ if 'default' in param:
+ props['default'] = param['default']
+ properties[param['name']] = props
+
+ schema = {
+ 'type': 'object',
+ 'properties': properties,
+ }
+ if required_params:
+ schema['required'] = required_params
+ return schema
+
+ @classmethod
+ def _gen_responses(cls, method, resp_object=None):
+ resp = {
+ '400': {
+ "description": "Operation exception. Please check the "
+ "response body for details."
+ },
+ '401': {
+ "description": "Unauthenticated access. Please login first."
+ },
+ '403': {
+ "description": "Unauthorized access. Please check your "
+ "permissions."
+ },
+ '500': {
+ "description": "Unexpected error. Please check the "
+ "response body for the stack trace."
+ }
+ }
+ if method.lower() == 'get':
+ resp['200'] = {'description': "OK"}
+ if method.lower() == 'post':
+ resp['201'] = {'description': "Resource created."}
+ if method.lower() == 'put':
+ resp['200'] = {'description': "Resource updated."}
+ if method.lower() == 'delete':
+ resp['204'] = {'description': "Resource deleted."}
+ if method.lower() in ['post', 'put', 'delete']:
+ resp['202'] = {'description': "Operation is still executing."
+ " Please check the task queue."}
+
+ if resp_object:
+ for status_code, response_body in resp_object.items():
+ resp[status_code].update({
+ 'content': {
+ 'application/json': {
+ 'schema': cls._gen_schema_for_content(response_body)}}})
+
+ return resp
+
+ @classmethod
+ def _gen_params(cls, params, location):
+ parameters = []
+ for param in params:
+ if 'type' in param:
+ _type = cls._type_to_str(param['type'])
+ else:
+ _type = cls._gen_type(param)
+ if 'description' in param:
+ descr = param['description']
+ else:
+ descr = "*No description available*"
+ res = {
+ 'name': param['name'],
+ 'in': location,
+ 'schema': {
+ 'type': _type
+ },
+ 'description': descr
+ }
+ if param['required']:
+ res['required'] = True
+ elif param['default'] is None:
+ res['allowEmptyValue'] = True
+ else:
+ res['default'] = param['default']
+ parameters.append(res)
+
+ return parameters
+
+ @classmethod
+ def _gen_paths(cls, all_endpoints, baseUrl):
+ METHOD_ORDER = ['get', 'post', 'put', 'delete']
+ paths = {}
+ for path, endpoints in sorted(list(ENDPOINT_MAP.items()),
+ key=lambda p: p[0]):
+ methods = {}
+ skip = False
+
+ endpoint_list = sorted(endpoints, key=lambda e:
+ METHOD_ORDER.index(e.method.lower()))
+ for endpoint in endpoint_list:
+ if not endpoint.is_api and not all_endpoints:
+ skip = True
+ break
+
+ method = endpoint.method
+ func = endpoint.func
+
+ summary = "No description available"
+ resp = {}
+ p_info = []
+ if hasattr(func, 'doc_info'):
+ if func.doc_info['summary']:
+ summary = func.doc_info['summary']
+ resp = func.doc_info['response']
+ p_info = func.doc_info['parameters']
+ params = []
+ if endpoint.path_params:
+ params.extend(
+ cls._gen_params(
+ cls._add_param_info(endpoint.path_params, p_info), 'path'))
+ if endpoint.query_params:
+ params.extend(
+ cls._gen_params(
+ cls._add_param_info(endpoint.query_params, p_info), 'query'))
+
+ methods[method.lower()] = {
+ 'tags': [cls._get_tag(endpoint)],
+ 'summary': summary,
+ 'description': func.__doc__,
+ 'parameters': params,
+ 'responses': cls._gen_responses(method, resp)
+ }
+
+ if method.lower() in ['post', 'put']:
+ if endpoint.body_params:
+ body_params = cls._add_param_info(endpoint.body_params, p_info)
+ methods[method.lower()]['requestBody'] = {
+ 'content': {
+ 'application/json': {
+ 'schema': cls._gen_schema_for_content(body_params)}}}
+
+ if endpoint.is_secure:
+ methods[method.lower()]['security'] = [{'jwt': []}]
+
+ if not skip:
+ paths[path[len(baseUrl):]] = methods
+
+ return paths
+
+ def _gen_spec(self, all_endpoints=False, base_url=""):
+ if all_endpoints:
+ base_url = ""
+
+ host = cherrypy.request.base
+ host = host[host.index(':')+3:]
+ logger.debug("DOCS: Host: %s", host)
+
+ paths = self._gen_paths(all_endpoints, base_url)
+
+ if not base_url:
+ base_url = "/"
+
+ scheme = 'https'
+ ssl = str_to_bool(mgr.get_localized_module_option('ssl', True))
+ if not ssl:
+ scheme = 'http'
+
+ spec = {
+ 'openapi': "3.0.0",
+ 'info': {
+ 'description': "Please note that this API is not an official "
+ "Ceph REST API to be used by third-party "
+ "applications. It's primary purpose is to serve"
+ " the requirements of the Ceph Dashboard and is"
+ " subject to change at any time. Use at your "
+ "own risk.",
+ 'version': "v1",
+ 'title': "Ceph-Dashboard REST API"
+ },
+ 'host': host,
+ 'basePath': base_url,
+ 'servers': [{'url': "{}{}".format(cherrypy.request.base, base_url)}],
+ 'tags': self._gen_tags(all_endpoints),
+ 'schemes': [scheme],
+ 'paths': paths,
+ 'components': {
+ 'securitySchemes': {
+ 'jwt': {
+ 'type': 'http',
+ 'scheme': 'bearer',
+ 'bearerFormat': 'JWT'
+ }
+ }
+ }
+ }
+
+ return spec
+
+ @Endpoint(path="api.json")
+ def api_json(self):
+ return self._gen_spec(False, "/api")
+
+ @Endpoint(path="api-all.json")
+ def api_all_json(self):
+ return self._gen_spec(True, "/api")
+
+ def _swagger_ui_page(self, all_endpoints=False):
+ base = cherrypy.request.base
+ if all_endpoints:
+ spec_url = "{}/docs/api-all.json".format(base)
+ else:
+ spec_url = "{}/docs/api.json".format(base)
+
+ page = """
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="referrer" content="no-referrer" />
+ <link rel="stylesheet" type="text/css"
+ href="/swagger-ui.css" >
+ <style>
+ html
+ {{
+ box-sizing: border-box;
+ overflow: -moz-scrollbars-vertical;
+ overflow-y: scroll;
+ }}
+ *,
+ *:before,
+ *:after
+ {{
+ box-sizing: inherit;
+ }}
+ body {{
+ margin:0;
+ background: #fafafa;
+ }}
+ </style>
+ </head>
+ <body>
+ <div id="swagger-ui"></div>
+ <script src="/swagger-ui-bundle.js">
+ </script>
+ <script>
+ window.onload = function() {{
+ const ui = SwaggerUIBundle({{
+ url: '{}',
+ dom_id: '#swagger-ui',
+ presets: [
+ SwaggerUIBundle.presets.apis
+ ],
+ layout: "BaseLayout"
+ }})
+ window.ui = ui
+ }}
+ </script>
+ </body>
+ </html>
+ """.format(spec_url)
+
+ return page
+
+ @Endpoint(json_response=False)
+ def __call__(self, all_endpoints=False):
+ return self._swagger_ui_page(all_endpoints)
diff --git a/src/pybind/mgr/dashboard/controllers/erasure_code_profile.py b/src/pybind/mgr/dashboard/controllers/erasure_code_profile.py
new file mode 100644
index 00000000..34c9f651
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/erasure_code_profile.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from cherrypy import NotFound
+
+from . import ApiController, RESTController, Endpoint, ReadPermission
+from ..security import Scope
+from ..services.ceph_service import CephService
+from .. import mgr
+
+
+def _serialize_ecp(name, ecp):
+ def serialize_numbers(key):
+ value = ecp.get(key)
+ if value is not None:
+ ecp[key] = int(value)
+
+ ecp['name'] = name
+ serialize_numbers('k')
+ serialize_numbers('m')
+ return ecp
+
+
+@ApiController('/erasure_code_profile', Scope.POOL)
+class ErasureCodeProfile(RESTController):
+ '''
+ create() supports additional key-value arguments that are passed to the
+ ECP plugin.
+ '''
+
+ def list(self):
+ ret = []
+ for name, ecp in mgr.get('osd_map').get('erasure_code_profiles', {}).items():
+ ret.append(_serialize_ecp(name, ecp))
+ return ret
+
+ def get(self, name):
+ try:
+ ecp = mgr.get('osd_map')['erasure_code_profiles'][name]
+ return _serialize_ecp(name, ecp)
+ except KeyError:
+ raise NotFound('No such erasure code profile')
+
+ def create(self, name, **kwargs):
+ profile = ['{}={}'.format(key, value) for key, value in kwargs.items()]
+ CephService.send_command('mon', 'osd erasure-code-profile set', name=name,
+ profile=profile)
+
+ def delete(self, name):
+ CephService.send_command('mon', 'osd erasure-code-profile rm', name=name)
+
+ @Endpoint()
+ @ReadPermission
+ def _info(self):
+ '''Used for profile creation and editing'''
+ config = mgr.get('config')
+ osd_map_crush = mgr.get('osd_map_crush')
+ return {
+ # Because 'shec' is experimental it's not included
+ 'plugins': config['osd_erasure_code_plugins'].split() + ['shec'],
+ 'directory': config['erasure_code_dir'],
+ 'devices': list({device['class'] for device in osd_map_crush['devices']}),
+ 'failure_domains': [domain['name'] for domain in osd_map_crush['types']],
+ 'names': [name for name, _ in
+ mgr.get('osd_map').get('erasure_code_profiles', {}).items()]
+ }
diff --git a/src/pybind/mgr/dashboard/controllers/grafana.py b/src/pybind/mgr/dashboard/controllers/grafana.py
new file mode 100644
index 00000000..001367c7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/grafana.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import (ApiController, BaseController, Endpoint, ReadPermission,
+ UpdatePermission)
+from .. import mgr
+from ..exceptions import DashboardException
+from ..grafana import GrafanaRestClient, push_local_dashboards
+from ..security import Scope
+from ..settings import Settings
+
+
+@ApiController('/grafana', Scope.GRAFANA)
+class Grafana(BaseController):
+ @Endpoint()
+ @ReadPermission
+ def url(self):
+ grafana_url = mgr.get_module_option('GRAFANA_API_URL')
+ grafana_frontend_url = mgr.get_module_option('GRAFANA_FRONTEND_API_URL')
+ if grafana_frontend_url != '' and grafana_url == '':
+ url = ''
+ else:
+ url = (mgr.get_module_option('GRAFANA_FRONTEND_API_URL')
+ or mgr.get_module_option('GRAFANA_API_URL')).rstrip('/')
+ response = {'instance': url}
+ return response
+
+ @Endpoint()
+ @ReadPermission
+ def validation(self, params):
+ grafana = GrafanaRestClient()
+ method = 'GET'
+ url = str(Settings.GRAFANA_API_URL).rstrip('/') + \
+ '/api/dashboards/uid/' + params
+ response = grafana.url_validation(method, url)
+ return response
+
+ @Endpoint(method='POST')
+ @UpdatePermission
+ def dashboards(self):
+ response = dict()
+ try:
+ response['success'] = push_local_dashboards()
+ except Exception as e: # pylint: disable=broad-except
+ raise DashboardException(
+ msg=str(e),
+ component='grafana',
+ http_status_code=500,
+ )
+ return response
diff --git a/src/pybind/mgr/dashboard/controllers/health.py b/src/pybind/mgr/dashboard/controllers/health.py
new file mode 100644
index 00000000..fab19bcb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/health.py
@@ -0,0 +1,189 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+from . import ApiController, Endpoint, BaseController
+
+from .. import mgr
+from ..security import Permission, Scope
+from ..services.ceph_service import CephService
+from ..services.iscsi_cli import IscsiGatewaysConfig
+
+
+class HealthData(object):
+ """
+ A class to be used in combination with BaseController to allow either
+ "full" or "minimal" sets of health data to be collected.
+
+ To function properly, it needs BaseCollector._has_permissions to be passed
+ in as ``auth_callback``.
+ """
+
+ def __init__(self, auth_callback, minimal=True):
+ self._has_permissions = auth_callback
+ self._minimal = minimal
+
+ @staticmethod
+ def _partial_dict(orig, keys):
+ return {k: orig[k] for k in keys}
+
+ def all_health(self):
+ result = {
+ "health": self.basic_health(),
+ }
+
+ if self._has_permissions(Permission.READ, Scope.MONITOR):
+ result['mon_status'] = self.mon_status()
+
+ if self._has_permissions(Permission.READ, Scope.CEPHFS):
+ result['fs_map'] = self.fs_map()
+
+ if self._has_permissions(Permission.READ, Scope.OSD):
+ result['osd_map'] = self.osd_map()
+ result['scrub_status'] = self.scrub_status()
+ result['pg_info'] = self.pg_info()
+
+ if self._has_permissions(Permission.READ, Scope.MANAGER):
+ result['mgr_map'] = self.mgr_map()
+
+ if self._has_permissions(Permission.READ, Scope.POOL):
+ result['pools'] = self.pools()
+ result['df'] = self.df()
+ result['client_perf'] = self.client_perf()
+
+ if self._has_permissions(Permission.READ, Scope.HOSTS):
+ result['hosts'] = self.host_count()
+
+ if self._has_permissions(Permission.READ, Scope.RGW):
+ result['rgw'] = self.rgw_count()
+
+ if self._has_permissions(Permission.READ, Scope.ISCSI):
+ result['iscsi_daemons'] = self.iscsi_daemons()
+
+ return result
+
+ def basic_health(self):
+ health_data = mgr.get("health")
+ health = json.loads(health_data['json'])
+
+ # Transform the `checks` dict into a list for the convenience
+ # of rendering from javascript.
+ checks = []
+ for k, v in health['checks'].items():
+ v['type'] = k
+ checks.append(v)
+
+ checks = sorted(checks, key=lambda c: c['severity'])
+ health['checks'] = checks
+ return health
+
+ def client_perf(self):
+ result = CephService.get_client_perf()
+ if self._minimal:
+ result = self._partial_dict(
+ result,
+ ['read_bytes_sec', 'read_op_per_sec',
+ 'recovering_bytes_per_sec', 'write_bytes_sec',
+ 'write_op_per_sec']
+ )
+ return result
+
+ def df(self):
+ df = mgr.get('df')
+
+ del df['stats_by_class']
+
+ if self._minimal:
+ df = dict(stats=self._partial_dict(
+ df['stats'],
+ ['total_avail_bytes', 'total_bytes',
+ 'total_used_raw_bytes']
+ ))
+ return df
+
+ def fs_map(self):
+ fs_map = mgr.get('fs_map')
+ if self._minimal:
+ fs_map = self._partial_dict(fs_map, ['filesystems', 'standbys'])
+ fs_map['filesystems'] = [self._partial_dict(item, ['mdsmap']) for
+ item in fs_map['filesystems']]
+ for fs in fs_map['filesystems']:
+ mdsmap_info = fs['mdsmap']['info']
+ min_mdsmap_info = dict()
+ for k, v in mdsmap_info.items():
+ min_mdsmap_info[k] = self._partial_dict(v, ['state'])
+ return fs_map
+
+ def host_count(self):
+ return len(mgr.list_servers())
+
+ def iscsi_daemons(self):
+ gateways = IscsiGatewaysConfig.get_gateways_config()['gateways']
+ return len(gateways) if gateways else 0
+
+ def mgr_map(self):
+ mgr_map = mgr.get('mgr_map')
+ if self._minimal:
+ mgr_map = self._partial_dict(mgr_map, ['active_name', 'standbys'])
+ return mgr_map
+
+ def mon_status(self):
+ mon_status = json.loads(mgr.get('mon_status')['json'])
+ if self._minimal:
+ mon_status = self._partial_dict(mon_status, ['monmap', 'quorum'])
+ mon_status['monmap'] = self._partial_dict(
+ mon_status['monmap'], ['mons']
+ )
+ mon_status['monmap']['mons'] = [{}] * \
+ len(mon_status['monmap']['mons'])
+ return mon_status
+
+ def osd_map(self):
+ osd_map = mgr.get('osd_map')
+ assert osd_map is not None
+ # Not needed, skip the effort of transmitting this to UI
+ del osd_map['pg_temp']
+ if self._minimal:
+ osd_map = self._partial_dict(osd_map, ['osds'])
+ osd_map['osds'] = [
+ self._partial_dict(item, ['in', 'up'])
+ for item in osd_map['osds']
+ ]
+ else:
+ osd_map['tree'] = mgr.get('osd_map_tree')
+ osd_map['crush'] = mgr.get('osd_map_crush')
+ osd_map['crush_map_text'] = mgr.get('osd_map_crush_map_text')
+ osd_map['osd_metadata'] = mgr.get('osd_metadata')
+ return osd_map
+
+ def pg_info(self):
+ return CephService.get_pg_info()
+
+ def pools(self):
+ pools = CephService.get_pool_list_with_stats()
+ if self._minimal:
+ pools = [{}] * len(pools)
+ return pools
+
+ def rgw_count(self):
+ return len(CephService.get_service_list('rgw'))
+
+ def scrub_status(self):
+ return CephService.get_scrub_status()
+
+
+@ApiController('/health')
+class Health(BaseController):
+ def __init__(self):
+ super(Health, self).__init__()
+ self.health_full = HealthData(self._has_permissions, minimal=False)
+ self.health_minimal = HealthData(self._has_permissions, minimal=True)
+
+ @Endpoint()
+ def full(self):
+ return self.health_full.all_health()
+
+ @Endpoint()
+ def minimal(self):
+ return self.health_minimal.all_health()
diff --git a/src/pybind/mgr/dashboard/controllers/home.py b/src/pybind/mgr/dashboard/controllers/home.py
new file mode 100644
index 00000000..0fbe79f7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/home.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import os
+import re
+import json
+try:
+ from functools import lru_cache
+except ImportError:
+ from ..plugins.lru_cache import lru_cache
+
+import cherrypy
+from cherrypy.lib.static import serve_file
+
+from . import Controller, UiApiController, BaseController, Proxy, Endpoint
+from .. import mgr, logger
+
+
+class LanguageMixin(object):
+ def __init__(self):
+ self.LANGUAGES = {
+ f
+ for f in os.listdir(mgr.get_frontend_path())
+ if os.path.isdir(os.path.join(mgr.get_frontend_path(), f))
+ }
+ self.LANGUAGES_PATH_MAP = {
+ f.lower(): {
+ 'lang': f,
+ 'path': os.path.join(mgr.get_frontend_path(), f)
+ }
+ for f in self.LANGUAGES
+ }
+ # pre-populating with the primary language subtag.
+ for lang in list(self.LANGUAGES_PATH_MAP.keys()):
+ if '-' in lang:
+ self.LANGUAGES_PATH_MAP[lang.split('-')[0]] = {
+ 'lang': self.LANGUAGES_PATH_MAP[lang]['lang'],
+ 'path': self.LANGUAGES_PATH_MAP[lang]['path']
+ }
+ with open("{}/../package.json".format(mgr.get_frontend_path()),
+ "r") as f:
+ config = json.load(f)
+ self.DEFAULT_LANGUAGE = config['config']['locale']
+ self.DEFAULT_LANGUAGE_PATH = os.path.join(mgr.get_frontend_path(),
+ self.DEFAULT_LANGUAGE)
+ super(LanguageMixin, self).__init__()
+
+
+@Controller("/", secure=False)
+class HomeController(BaseController, LanguageMixin):
+ LANG_TAG_SEQ_RE = re.compile(r'\s*([^,]+)\s*,?\s*')
+ LANG_TAG_RE = re.compile(
+ r'^(?P<locale>[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})?)(;q=(?P<weight>[01]\.\d{0,3}))?$')
+ MAX_ACCEPTED_LANGS = 10
+
+ @lru_cache()
+ def _parse_accept_language(self, accept_lang_header):
+ result = []
+ for i, m in enumerate(self.LANG_TAG_SEQ_RE.finditer(accept_lang_header)):
+ if i >= self.MAX_ACCEPTED_LANGS:
+ logger.debug("reached max accepted languages, skipping remaining")
+ break
+
+ tag_match = self.LANG_TAG_RE.match(m.group(1))
+ if tag_match is None:
+ raise cherrypy.HTTPError(400, "Malformed 'Accept-Language' header")
+ locale = tag_match.group('locale').lower()
+ weight = tag_match.group('weight')
+ if weight:
+ try:
+ ratio = float(weight)
+ except ValueError:
+ raise cherrypy.HTTPError(400, "Malformed 'Accept-Language' header")
+ else:
+ ratio = 1.0
+ result.append((locale, ratio))
+
+ result.sort(key=lambda l: l[0])
+ result.sort(key=lambda l: l[1], reverse=True)
+ logger.debug("language preference: %s", result)
+ return [l[0] for l in result]
+
+ def _language_dir(self, langs):
+ for lang in langs:
+ if lang in self.LANGUAGES_PATH_MAP:
+ logger.debug("found directory for language '%s'", lang)
+ cherrypy.response.headers[
+ 'Content-Language'] = self.LANGUAGES_PATH_MAP[lang]['lang']
+ return self.LANGUAGES_PATH_MAP[lang]['path']
+
+ logger.debug("Languages '%s' not available, falling back to %s",
+ langs, self.DEFAULT_LANGUAGE)
+ cherrypy.response.headers['Content-Language'] = self.DEFAULT_LANGUAGE
+ return self.DEFAULT_LANGUAGE_PATH
+
+ @Proxy()
+ def __call__(self, path, **params):
+ if not path:
+ path = "index.html"
+
+ if 'cd-lang' in cherrypy.request.cookie:
+ langs = [cherrypy.request.cookie['cd-lang'].value.lower()]
+ logger.debug("frontend language from cookie: %s", langs)
+ else:
+ if 'Accept-Language' in cherrypy.request.headers:
+ accept_lang_header = cherrypy.request.headers['Accept-Language']
+ langs = self._parse_accept_language(accept_lang_header)
+ else:
+ langs = [self.DEFAULT_LANGUAGE.lower()]
+ logger.debug("frontend language from headers: %s", langs)
+
+ base_dir = self._language_dir(langs)
+ full_path = os.path.join(base_dir, path)
+
+ # Block uplevel attacks
+ if not os.path.normpath(full_path).startswith(os.path.normpath(base_dir)):
+ raise cherrypy.HTTPError(403) # Forbidden
+
+ logger.debug("serving static content: %s", full_path)
+ if 'Vary' in cherrypy.response.headers:
+ cherrypy.response.headers['Vary'] = "{}, Accept-Language"
+ else:
+ cherrypy.response.headers['Vary'] = "Accept-Language"
+
+ cherrypy.response.headers['Cache-control'] = "no-cache"
+ return serve_file(full_path)
+
+
+@UiApiController("/langs", secure=False)
+class LangsController(BaseController, LanguageMixin):
+ @Endpoint('GET')
+ def __call__(self):
+ return list(self.LANGUAGES)
diff --git a/src/pybind/mgr/dashboard/controllers/host.py b/src/pybind/mgr/dashboard/controllers/host.py
new file mode 100644
index 00000000..e8518a14
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/host.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..security import Scope
+
+
+@ApiController('/host', Scope.HOSTS)
+class Host(RESTController):
+ def list(self):
+ return mgr.list_servers()
diff --git a/src/pybind/mgr/dashboard/controllers/iscsi.py b/src/pybind/mgr/dashboard/controllers/iscsi.py
new file mode 100644
index 00000000..af753205
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/iscsi.py
@@ -0,0 +1,1049 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-branches
+# pylint: disable=too-many-lines
+from __future__ import absolute_import
+
+from copy import deepcopy
+import re
+import json
+import cherrypy
+
+import rados
+import rbd
+
+from . import ApiController, UiApiController, RESTController, BaseController, Endpoint,\
+ ReadPermission, UpdatePermission, Task
+from .. import mgr
+from ..rest_client import RequestException
+from ..security import Scope
+from ..services.iscsi_client import IscsiClient
+from ..services.iscsi_cli import IscsiGatewaysConfig
+from ..services.iscsi_config import IscsiGatewayDoesNotExist
+from ..services.rbd import format_bitmask
+from ..services.tcmu_service import TcmuService
+from ..exceptions import DashboardException
+from ..tools import str_to_bool, TaskManager
+
+
+@UiApiController('/iscsi', Scope.ISCSI)
+class IscsiUi(BaseController):
+
+ REQUIRED_CEPH_ISCSI_CONFIG_MIN_VERSION = 10
+ REQUIRED_CEPH_ISCSI_CONFIG_MAX_VERSION = 11
+
+ @Endpoint()
+ @ReadPermission
+ def status(self):
+ status = {'available': False}
+ try:
+ gateway = get_available_gateway()
+ except DashboardException as e:
+ status['message'] = str(e)
+ return status
+ try:
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ if config['version'] < IscsiUi.REQUIRED_CEPH_ISCSI_CONFIG_MIN_VERSION or \
+ config['version'] > IscsiUi.REQUIRED_CEPH_ISCSI_CONFIG_MAX_VERSION:
+ status['message'] = 'Unsupported `ceph-iscsi` config version. ' \
+ 'Expected >= {} and <= {} but found' \
+ ' {}.'.format(IscsiUi.REQUIRED_CEPH_ISCSI_CONFIG_MIN_VERSION,
+ IscsiUi.REQUIRED_CEPH_ISCSI_CONFIG_MAX_VERSION,
+ config['version'])
+ return status
+ status['available'] = True
+ except RequestException as e:
+ if e.content:
+ try:
+ content = json.loads(e.content)
+ content_message = content.get('message')
+ except ValueError:
+ content_message = e.content
+ if content_message:
+ status['message'] = content_message
+
+ return status
+
+ @Endpoint()
+ @ReadPermission
+ def version(self):
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ return {
+ 'ceph_iscsi_config_version': config['version']
+ }
+
+ @Endpoint()
+ @ReadPermission
+ def settings(self):
+ gateway = get_available_gateway()
+ settings = IscsiClient.instance(gateway_name=gateway).get_settings()
+ if 'target_controls_limits' in settings:
+ target_default_controls = settings['target_default_controls']
+ for ctrl_k, ctrl_v in target_default_controls.items():
+ limits = settings['target_controls_limits'].get(ctrl_k, {})
+ if 'type' not in limits:
+ # default
+ limits['type'] = 'int'
+ # backward compatibility
+ if target_default_controls[ctrl_k] in ['Yes', 'No']:
+ limits['type'] = 'bool'
+ target_default_controls[ctrl_k] = str_to_bool(ctrl_v)
+ settings['target_controls_limits'][ctrl_k] = limits
+ if 'disk_controls_limits' in settings:
+ for backstore, disk_controls_limits in settings['disk_controls_limits'].items():
+ disk_default_controls = settings['disk_default_controls'][backstore]
+ for ctrl_k, ctrl_v in disk_default_controls.items():
+ limits = disk_controls_limits.get(ctrl_k, {})
+ if 'type' not in limits:
+ # default
+ limits['type'] = 'int'
+ settings['disk_controls_limits'][backstore][ctrl_k] = limits
+ return settings
+
+ @Endpoint()
+ @ReadPermission
+ def portals(self):
+ portals = []
+ gateways_config = IscsiGatewaysConfig.get_gateways_config()
+ for name in gateways_config['gateways']:
+ try:
+ ip_addresses = IscsiClient.instance(gateway_name=name).get_ip_addresses()
+ portals.append({'name': name, 'ip_addresses': ip_addresses['data']})
+ except RequestException:
+ pass
+ return sorted(portals, key=lambda p: '{}.{}'.format(p['name'], p['ip_addresses']))
+
+ @Endpoint()
+ @ReadPermission
+ def overview(self):
+ result_gateways = []
+ result_images = []
+ gateways_names = IscsiGatewaysConfig.get_gateways_config()['gateways'].keys()
+ config = None
+ for gateway_name in gateways_names:
+ try:
+ config = IscsiClient.instance(gateway_name=gateway_name).get_config()
+ break
+ except RequestException:
+ pass
+
+ # Gateways info
+ for gateway_name in gateways_names:
+ gateway = {
+ 'name': gateway_name,
+ 'state': '',
+ 'num_targets': 'n/a',
+ 'num_sessions': 'n/a'
+ }
+ try:
+ IscsiClient.instance(gateway_name=gateway_name).ping()
+ gateway['state'] = 'up'
+ if config:
+ gateway['num_sessions'] = 0
+ if gateway_name in config['gateways']:
+ gatewayinfo = IscsiClient.instance(
+ gateway_name=gateway_name).get_gatewayinfo()
+ gateway['num_sessions'] = gatewayinfo['num_sessions']
+ except RequestException:
+ gateway['state'] = 'down'
+ if config:
+ gateway['num_targets'] = len([target for _, target in config['targets'].items()
+ if gateway_name in target['portals']])
+ result_gateways.append(gateway)
+
+ # Images info
+ if config:
+ tcmu_info = TcmuService.get_iscsi_info()
+ for _, disk_config in config['disks'].items():
+ image = {
+ 'pool': disk_config['pool'],
+ 'image': disk_config['image'],
+ 'backstore': disk_config['backstore'],
+ 'optimized_since': None,
+ 'stats': None,
+ 'stats_history': None
+ }
+ tcmu_image_info = TcmuService.get_image_info(image['pool'],
+ image['image'],
+ tcmu_info)
+ if tcmu_image_info:
+ if 'optimized_since' in tcmu_image_info:
+ image['optimized_since'] = tcmu_image_info['optimized_since']
+ if 'stats' in tcmu_image_info:
+ image['stats'] = tcmu_image_info['stats']
+ if 'stats_history' in tcmu_image_info:
+ image['stats_history'] = tcmu_image_info['stats_history']
+ result_images.append(image)
+
+ return {
+ 'gateways': sorted(result_gateways, key=lambda g: g['name']),
+ 'images': sorted(result_images, key=lambda i: '{}/{}'.format(i['pool'], i['image']))
+ }
+
+
+@ApiController('/iscsi', Scope.ISCSI)
+class Iscsi(BaseController):
+
+ @Endpoint('GET', 'discoveryauth')
+ @ReadPermission
+ def get_discoveryauth(self):
+ gateway = get_available_gateway()
+ return self._get_discoveryauth(gateway)
+
+ @Endpoint('PUT', 'discoveryauth')
+ @UpdatePermission
+ def set_discoveryauth(self, user, password, mutual_user, mutual_password):
+ validate_auth({
+ 'user': user,
+ 'password': password,
+ 'mutual_user': mutual_user,
+ 'mutual_password': mutual_password
+ })
+
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ gateway_names = list(config['gateways'].keys())
+ validate_rest_api(gateway_names)
+ IscsiClient.instance(gateway_name=gateway).update_discoveryauth(user,
+ password,
+ mutual_user,
+ mutual_password)
+ return self._get_discoveryauth(gateway)
+
+ def _get_discoveryauth(self, gateway):
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ user = config['discovery_auth']['username']
+ password = config['discovery_auth']['password']
+ mutual_user = config['discovery_auth']['mutual_username']
+ mutual_password = config['discovery_auth']['mutual_password']
+ return {
+ 'user': user,
+ 'password': password,
+ 'mutual_user': mutual_user,
+ 'mutual_password': mutual_password
+ }
+
+
+def iscsi_target_task(name, metadata, wait_for=2.0):
+ return Task("iscsi/target/{}".format(name), metadata, wait_for)
+
+
+@ApiController('/iscsi/target', Scope.ISCSI)
+class IscsiTarget(RESTController):
+
+ def list(self):
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ targets = []
+ for target_iqn in config['targets'].keys():
+ target = IscsiTarget._config_to_target(target_iqn, config)
+ IscsiTarget._set_info(target)
+ targets.append(target)
+ return targets
+
+ def get(self, target_iqn):
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ if target_iqn not in config['targets']:
+ raise cherrypy.HTTPError(404)
+ target = IscsiTarget._config_to_target(target_iqn, config)
+ IscsiTarget._set_info(target)
+ return target
+
+ @iscsi_target_task('delete', {'target_iqn': '{target_iqn}'})
+ def delete(self, target_iqn):
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ if target_iqn not in config['targets']:
+ raise DashboardException(msg='Target does not exist',
+ code='target_does_not_exist',
+ component='iscsi')
+ portal_names = list(config['targets'][target_iqn]['portals'].keys())
+ validate_rest_api(portal_names)
+ if portal_names:
+ portal_name = portal_names[0]
+ target_info = IscsiClient.instance(gateway_name=portal_name).get_targetinfo(target_iqn)
+ if target_info['num_sessions'] > 0:
+ raise DashboardException(msg='Target has active sessions',
+ code='target_has_active_sessions',
+ component='iscsi')
+ IscsiTarget._delete(target_iqn, config, 0, 100)
+
+ @iscsi_target_task('create', {'target_iqn': '{target_iqn}'})
+ def create(self, target_iqn=None, target_controls=None, acl_enabled=None,
+ auth=None, portals=None, disks=None, clients=None, groups=None):
+ target_controls = target_controls or {}
+ portals = portals or []
+ disks = disks or []
+ clients = clients or []
+ groups = groups or []
+
+ validate_auth(auth)
+ for client in clients:
+ validate_auth(client['auth'])
+
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ if target_iqn in config['targets']:
+ raise DashboardException(msg='Target already exists',
+ code='target_already_exists',
+ component='iscsi')
+ settings = IscsiClient.instance(gateway_name=gateway).get_settings()
+ IscsiTarget._validate(target_iqn, target_controls, portals, disks, groups, settings)
+
+ IscsiTarget._create(target_iqn, target_controls, acl_enabled, auth, portals, disks,
+ clients, groups, 0, 100, config, settings)
+
+ @iscsi_target_task('edit', {'target_iqn': '{target_iqn}'})
+ def set(self, target_iqn, new_target_iqn=None, target_controls=None, acl_enabled=None,
+ auth=None, portals=None, disks=None, clients=None, groups=None):
+ target_controls = target_controls or {}
+ portals = IscsiTarget._sorted_portals(portals)
+ disks = IscsiTarget._sorted_disks(disks)
+ clients = IscsiTarget._sorted_clients(clients)
+ groups = IscsiTarget._sorted_groups(groups)
+
+ validate_auth(auth)
+ for client in clients:
+ validate_auth(client['auth'])
+
+ gateway = get_available_gateway()
+ config = IscsiClient.instance(gateway_name=gateway).get_config()
+ if target_iqn not in config['targets']:
+ raise DashboardException(msg='Target does not exist',
+ code='target_does_not_exist',
+ component='iscsi')
+ if target_iqn != new_target_iqn and new_target_iqn in config['targets']:
+ raise DashboardException(msg='Target IQN already in use',
+ code='target_iqn_already_in_use',
+ component='iscsi')
+
+ settings = IscsiClient.instance(gateway_name=gateway).get_settings()
+ new_portal_names = {p['host'] for p in portals}
+ old_portal_names = set(config['targets'][target_iqn]['portals'].keys())
+ deleted_portal_names = list(old_portal_names - new_portal_names)
+ validate_rest_api(deleted_portal_names)
+ IscsiTarget._validate(new_target_iqn, target_controls, portals, disks, groups, settings)
+ IscsiTarget._validate_delete(gateway, target_iqn, config, new_target_iqn, target_controls,
+ disks, clients, groups)
+ config = IscsiTarget._delete(target_iqn, config, 0, 50, new_target_iqn, target_controls,
+ portals, disks, clients, groups)
+ IscsiTarget._create(new_target_iqn, target_controls, acl_enabled, auth, portals, disks,
+ clients, groups, 50, 100, config, settings)
+
+ @staticmethod
+ def _delete(target_iqn, config, task_progress_begin, task_progress_end, new_target_iqn=None,
+ new_target_controls=None, new_portals=None, new_disks=None, new_clients=None,
+ new_groups=None):
+ new_target_controls = new_target_controls or {}
+ new_portals = new_portals or []
+ new_disks = new_disks or []
+ new_clients = new_clients or []
+ new_groups = new_groups or []
+
+ TaskManager.current_task().set_progress(task_progress_begin)
+ target_config = config['targets'][target_iqn]
+ if not target_config['portals'].keys():
+ raise DashboardException(msg="Cannot delete a target that doesn't contain any portal",
+ code='cannot_delete_target_without_portals',
+ component='iscsi')
+ target = IscsiTarget._config_to_target(target_iqn, config)
+ n_groups = len(target_config['groups'])
+ n_clients = len(target_config['clients'])
+ n_target_disks = len(target_config['disks'])
+ task_progress_steps = n_groups + n_clients + n_target_disks
+ task_progress_inc = 0
+ if task_progress_steps != 0:
+ task_progress_inc = int((task_progress_end - task_progress_begin) / task_progress_steps)
+ gateway_name = list(target_config['portals'].keys())[0]
+ deleted_groups = []
+ for group_id in list(target_config['groups'].keys()):
+ if IscsiTarget._group_deletion_required(target, new_target_iqn, new_target_controls,
+ new_groups, group_id):
+ deleted_groups.append(group_id)
+ IscsiClient.instance(gateway_name=gateway_name).delete_group(target_iqn,
+ group_id)
+ else:
+ group = IscsiTarget._get_group(new_groups, group_id)
+
+ old_group_disks = set(target_config['groups'][group_id]['disks'].keys())
+ new_group_disks = {'{}/{}'.format(x['pool'], x['image']) for x in group['disks']}
+ local_deleted_disks = list(old_group_disks - new_group_disks)
+
+ old_group_members = set(target_config['groups'][group_id]['members'])
+ new_group_members = set(group['members'])
+ local_deleted_members = list(old_group_members - new_group_members)
+
+ if local_deleted_disks or local_deleted_members:
+ IscsiClient.instance(gateway_name=gateway_name).update_group(
+ target_iqn, group_id, local_deleted_members, local_deleted_disks)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ deleted_clients = []
+ deleted_client_luns = []
+ for client_iqn, client_config in target_config['clients'].items():
+ if IscsiTarget._client_deletion_required(target, new_target_iqn, new_target_controls,
+ new_clients, client_iqn):
+ deleted_clients.append(client_iqn)
+ IscsiClient.instance(gateway_name=gateway_name).delete_client(target_iqn,
+ client_iqn)
+ else:
+ for image_id in list(client_config.get('luns', {}).keys()):
+ if IscsiTarget._client_lun_deletion_required(target, client_iqn, image_id,
+ new_clients, new_groups):
+ deleted_client_luns.append((client_iqn, image_id))
+ IscsiClient.instance(gateway_name=gateway_name).delete_client_lun(
+ target_iqn, client_iqn, image_id)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ for image_id in target_config['disks']:
+ if IscsiTarget._target_lun_deletion_required(target, new_target_iqn,
+ new_target_controls, new_disks, image_id):
+ all_clients = target_config['clients'].keys()
+ not_deleted_clients = [c for c in all_clients if c not in deleted_clients
+ and not IscsiTarget._client_in_group(target['groups'], c)
+ and not IscsiTarget._client_in_group(new_groups, c)]
+ for client_iqn in not_deleted_clients:
+ client_image_ids = target_config['clients'][client_iqn]['luns'].keys()
+ for client_image_id in client_image_ids:
+ if image_id == client_image_id and \
+ (client_iqn, client_image_id) not in deleted_client_luns:
+ IscsiClient.instance(gateway_name=gateway_name).delete_client_lun(
+ target_iqn, client_iqn, client_image_id)
+ IscsiClient.instance(gateway_name=gateway_name).delete_target_lun(target_iqn,
+ image_id)
+ pool, image = image_id.split('/', 1)
+ IscsiClient.instance(gateway_name=gateway_name).delete_disk(pool, image)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ old_portals_by_host = IscsiTarget._get_portals_by_host(target['portals'])
+ new_portals_by_host = IscsiTarget._get_portals_by_host(new_portals)
+ for old_portal_host, old_portal_ip_list in old_portals_by_host.items():
+ if IscsiTarget._target_portal_deletion_required(old_portal_host,
+ old_portal_ip_list,
+ new_portals_by_host):
+ IscsiClient.instance(gateway_name=gateway_name).delete_gateway(target_iqn,
+ old_portal_host)
+ if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls):
+ IscsiClient.instance(gateway_name=gateway_name).delete_target(target_iqn)
+ TaskManager.current_task().set_progress(task_progress_end)
+ return IscsiClient.instance(gateway_name=gateway_name).get_config()
+
+ @staticmethod
+ def _get_group(groups, group_id):
+ for group in groups:
+ if group['group_id'] == group_id:
+ return group
+ return None
+
+ @staticmethod
+ def _group_deletion_required(target, new_target_iqn, new_target_controls,
+ new_groups, group_id):
+ if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls):
+ return True
+ new_group = IscsiTarget._get_group(new_groups, group_id)
+ if not new_group:
+ return True
+ return False
+
+ @staticmethod
+ def _get_client(clients, client_iqn):
+ for client in clients:
+ if client['client_iqn'] == client_iqn:
+ return client
+ return None
+
+ @staticmethod
+ def _client_deletion_required(target, new_target_iqn, new_target_controls,
+ new_clients, client_iqn):
+ if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls):
+ return True
+ new_client = IscsiTarget._get_client(new_clients, client_iqn)
+ if not new_client:
+ return True
+ return False
+
+ @staticmethod
+ def _client_in_group(groups, client_iqn):
+ for group in groups:
+ if client_iqn in group['members']:
+ return True
+ return False
+
+ @staticmethod
+ def _client_lun_deletion_required(target, client_iqn, image_id, new_clients, new_groups):
+ new_client = IscsiTarget._get_client(new_clients, client_iqn)
+ if not new_client:
+ return True
+
+ # Disks inherited from groups must be considered
+ was_in_group = IscsiTarget._client_in_group(target['groups'], client_iqn)
+ is_in_group = IscsiTarget._client_in_group(new_groups, client_iqn)
+
+ if not was_in_group and is_in_group:
+ return True
+
+ if is_in_group:
+ return False
+
+ new_lun = IscsiTarget._get_disk(new_client.get('luns', []), image_id)
+ if not new_lun:
+ return True
+
+ old_client = IscsiTarget._get_client(target['clients'], client_iqn)
+ if not old_client:
+ return False
+
+ old_lun = IscsiTarget._get_disk(old_client.get('luns', []), image_id)
+ return new_lun != old_lun
+
+ @staticmethod
+ def _get_disk(disks, image_id):
+ for disk in disks:
+ if '{}/{}'.format(disk['pool'], disk['image']) == image_id:
+ return disk
+ return None
+
+ @staticmethod
+ def _target_lun_deletion_required(target, new_target_iqn, new_target_controls,
+ new_disks, image_id):
+ if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls):
+ return True
+ new_disk = IscsiTarget._get_disk(new_disks, image_id)
+ if not new_disk:
+ return True
+ old_disk = IscsiTarget._get_disk(target['disks'], image_id)
+ new_disk_without_controls = deepcopy(new_disk)
+ new_disk_without_controls.pop('controls')
+ old_disk_without_controls = deepcopy(old_disk)
+ old_disk_without_controls.pop('controls')
+ if new_disk_without_controls != old_disk_without_controls:
+ return True
+ return False
+
+ @staticmethod
+ def _target_portal_deletion_required(old_portal_host, old_portal_ip_list, new_portals_by_host):
+ if old_portal_host not in new_portals_by_host:
+ return True
+ if sorted(old_portal_ip_list) != sorted(new_portals_by_host[old_portal_host]):
+ return True
+ return False
+
+ @staticmethod
+ def _target_deletion_required(target, new_target_iqn, new_target_controls):
+ gateway = get_available_gateway()
+ settings = IscsiClient.instance(gateway_name=gateway).get_settings()
+
+ if target['target_iqn'] != new_target_iqn:
+ return True
+ if settings['api_version'] < 2 and target['target_controls'] != new_target_controls:
+ return True
+ return False
+
+ @staticmethod
+ def _validate(target_iqn, target_controls, portals, disks, groups, settings):
+ if not target_iqn:
+ raise DashboardException(msg='Target IQN is required',
+ code='target_iqn_required',
+ component='iscsi')
+
+ minimum_gateways = max(1, settings['config']['minimum_gateways'])
+ portals_by_host = IscsiTarget._get_portals_by_host(portals)
+ if len(portals_by_host.keys()) < minimum_gateways:
+ if minimum_gateways == 1:
+ msg = 'At least one portal is required'
+ else:
+ msg = 'At least {} portals are required'.format(minimum_gateways)
+ raise DashboardException(msg=msg,
+ code='portals_required',
+ component='iscsi')
+
+ # 'target_controls_limits' was introduced in ceph-iscsi > 3.2
+ # When using an older `ceph-iscsi` version these validations will
+ # NOT be executed beforehand
+ if 'target_controls_limits' in settings:
+ for target_control_name, target_control_value in target_controls.items():
+ limits = settings['target_controls_limits'].get(target_control_name)
+ if limits is not None:
+ min_value = limits.get('min')
+ if min_value is not None and target_control_value < min_value:
+ raise DashboardException(msg='Target control {} must be >= '
+ '{}'.format(target_control_name, min_value),
+ code='target_control_invalid_min',
+ component='iscsi')
+ max_value = limits.get('max')
+ if max_value is not None and target_control_value > max_value:
+ raise DashboardException(msg='Target control {} must be <= '
+ '{}'.format(target_control_name, max_value),
+ code='target_control_invalid_max',
+ component='iscsi')
+
+ portal_names = [p['host'] for p in portals]
+ validate_rest_api(portal_names)
+
+ for disk in disks:
+ pool = disk['pool']
+ image = disk['image']
+ backstore = disk['backstore']
+ required_rbd_features = settings['required_rbd_features'][backstore]
+ unsupported_rbd_features = settings['unsupported_rbd_features'][backstore]
+ IscsiTarget._validate_image(pool, image, backstore, required_rbd_features,
+ unsupported_rbd_features)
+
+ # 'disk_controls_limits' was introduced in ceph-iscsi > 3.2
+ # When using an older `ceph-iscsi` version these validations will
+ # NOT be executed beforehand
+ if 'disk_controls_limits' in settings:
+ for disk_control_name, disk_control_value in disk['controls'].items():
+ limits = settings['disk_controls_limits'][backstore].get(disk_control_name)
+ if limits is not None:
+ min_value = limits.get('min')
+ if min_value is not None and disk_control_value < min_value:
+ raise DashboardException(msg='Disk control {} must be >= '
+ '{}'.format(disk_control_name, min_value),
+ code='disk_control_invalid_min',
+ component='iscsi')
+ max_value = limits.get('max')
+ if max_value is not None and disk_control_value > max_value:
+ raise DashboardException(msg='Disk control {} must be <= '
+ '{}'.format(disk_control_name, max_value),
+ code='disk_control_invalid_max',
+ component='iscsi')
+
+ initiators = []
+ for group in groups:
+ initiators = initiators + group['members']
+ if len(initiators) != len(set(initiators)):
+ raise DashboardException(msg='Each initiator can only be part of 1 group at a time',
+ code='initiator_in_multiple_groups',
+ component='iscsi')
+
+ @staticmethod
+ def _validate_image(pool, image, backstore, required_rbd_features, unsupported_rbd_features):
+ try:
+ ioctx = mgr.rados.open_ioctx(pool)
+ try:
+ with rbd.Image(ioctx, image) as img:
+ if img.features() & required_rbd_features != required_rbd_features:
+ raise DashboardException(msg='Image {} cannot be exported using {} '
+ 'backstore because required features are '
+ 'missing (required features are '
+ '{})'.format(image,
+ backstore,
+ format_bitmask(
+ required_rbd_features)),
+ code='image_missing_required_features',
+ component='iscsi')
+ if img.features() & unsupported_rbd_features != 0:
+ raise DashboardException(msg='Image {} cannot be exported using {} '
+ 'backstore because it contains unsupported '
+ 'features ('
+ '{})'.format(image,
+ backstore,
+ format_bitmask(
+ unsupported_rbd_features)),
+ code='image_contains_unsupported_features',
+ component='iscsi')
+
+ except rbd.ImageNotFound:
+ raise DashboardException(msg='Image {} does not exist'.format(image),
+ code='image_does_not_exist',
+ component='iscsi')
+ except rados.ObjectNotFound:
+ raise DashboardException(msg='Pool {} does not exist'.format(pool),
+ code='pool_does_not_exist',
+ component='iscsi')
+
+ @staticmethod
+ def _validate_delete(gateway, target_iqn, config, new_target_iqn=None, new_target_controls=None,
+ new_disks=None, new_clients=None, new_groups=None):
+ new_target_controls = new_target_controls or {}
+ new_disks = new_disks or []
+ new_clients = new_clients or []
+ new_groups = new_groups or []
+
+ target_config = config['targets'][target_iqn]
+ target = IscsiTarget._config_to_target(target_iqn, config)
+ for client_iqn in list(target_config['clients'].keys()):
+ if IscsiTarget._client_deletion_required(target, new_target_iqn, new_target_controls,
+ new_clients, client_iqn):
+ client_info = IscsiClient.instance(gateway_name=gateway).get_clientinfo(target_iqn,
+ client_iqn)
+ if client_info.get('state', {}).get('LOGGED_IN', []):
+ raise DashboardException(msg="Client '{}' cannot be deleted until it's logged "
+ "out".format(client_iqn),
+ code='client_logged_in',
+ component='iscsi')
+
+ @staticmethod
+ def _update_targetauth(config, target_iqn, auth, gateway_name):
+ # Target level authentication was introduced in ceph-iscsi config v11
+ if config['version'] > 10:
+ user = auth['user']
+ password = auth['password']
+ mutual_user = auth['mutual_user']
+ mutual_password = auth['mutual_password']
+ IscsiClient.instance(gateway_name=gateway_name).update_targetauth(target_iqn,
+ user,
+ password,
+ mutual_user,
+ mutual_password)
+
+ @staticmethod
+ def _update_targetacl(target_config, target_iqn, acl_enabled, gateway_name):
+ if not target_config or target_config['acl_enabled'] != acl_enabled:
+ targetauth_action = ('enable_acl' if acl_enabled else 'disable_acl')
+ IscsiClient.instance(gateway_name=gateway_name).update_targetacl(target_iqn,
+ targetauth_action)
+
+ @staticmethod
+ def _is_auth_equal(auth_config, auth):
+ return auth['user'] == auth_config['username'] and \
+ auth['password'] == auth_config['password'] and \
+ auth['mutual_user'] == auth_config['mutual_username'] and \
+ auth['mutual_password'] == auth_config['mutual_password']
+
+ @staticmethod
+ def _create(target_iqn, target_controls, acl_enabled,
+ auth, portals, disks, clients, groups,
+ task_progress_begin, task_progress_end, config, settings):
+ target_config = config['targets'].get(target_iqn, None)
+ TaskManager.current_task().set_progress(task_progress_begin)
+ portals_by_host = IscsiTarget._get_portals_by_host(portals)
+ n_hosts = len(portals_by_host)
+ n_disks = len(disks)
+ n_clients = len(clients)
+ n_groups = len(groups)
+ task_progress_steps = n_hosts + n_disks + n_clients + n_groups
+ task_progress_inc = 0
+ if task_progress_steps != 0:
+ task_progress_inc = int((task_progress_end - task_progress_begin) / task_progress_steps)
+ try:
+ gateway_name = portals[0]['host']
+ if not target_config:
+ IscsiClient.instance(gateway_name=gateway_name).create_target(target_iqn,
+ target_controls)
+ for host, ip_list in portals_by_host.items():
+ if not target_config or host not in target_config['portals']:
+ IscsiClient.instance(gateway_name=gateway_name).create_gateway(target_iqn,
+ host,
+ ip_list)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+
+ if not target_config or \
+ acl_enabled != target_config['acl_enabled'] or \
+ not IscsiTarget._is_auth_equal(target_config['auth'], auth):
+ if acl_enabled:
+ IscsiTarget._update_targetauth(config, target_iqn, auth, gateway_name)
+ IscsiTarget._update_targetacl(target_config, target_iqn, acl_enabled,
+ gateway_name)
+ else:
+ IscsiTarget._update_targetacl(target_config, target_iqn, acl_enabled,
+ gateway_name)
+ IscsiTarget._update_targetauth(config, target_iqn, auth, gateway_name)
+
+ for disk in disks:
+ pool = disk['pool']
+ image = disk['image']
+ image_id = '{}/{}'.format(pool, image)
+ backstore = disk['backstore']
+ wwn = disk.get('wwn')
+ lun = disk.get('lun')
+ if image_id not in config['disks']:
+ IscsiClient.instance(gateway_name=gateway_name).create_disk(pool,
+ image,
+ backstore,
+ wwn)
+ if not target_config or image_id not in target_config['disks']:
+ IscsiClient.instance(gateway_name=gateway_name).create_target_lun(target_iqn,
+ image_id,
+ lun)
+
+ controls = disk['controls']
+ d_conf_controls = {}
+ if image_id in config['disks']:
+ d_conf_controls = config['disks'][image_id]['controls']
+ disk_default_controls = settings['disk_default_controls'][backstore]
+ for old_control in d_conf_controls.keys():
+ # If control was removed, restore the default value
+ if old_control not in controls:
+ controls[old_control] = disk_default_controls[old_control]
+
+ if (image_id not in config['disks'] or d_conf_controls != controls) and controls:
+ IscsiClient.instance(gateway_name=gateway_name).reconfigure_disk(pool,
+ image,
+ controls)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ for client in clients:
+ client_iqn = client['client_iqn']
+ if not target_config or client_iqn not in target_config['clients']:
+ IscsiClient.instance(gateway_name=gateway_name).create_client(target_iqn,
+ client_iqn)
+ if not target_config or client_iqn not in target_config['clients'] or \
+ not IscsiTarget._is_auth_equal(target_config['clients'][client_iqn]['auth'],
+ client['auth']):
+ user = client['auth']['user']
+ password = client['auth']['password']
+ m_user = client['auth']['mutual_user']
+ m_password = client['auth']['mutual_password']
+ IscsiClient.instance(gateway_name=gateway_name).create_client_auth(
+ target_iqn, client_iqn, user, password, m_user, m_password)
+ for lun in client['luns']:
+ pool = lun['pool']
+ image = lun['image']
+ image_id = '{}/{}'.format(pool, image)
+ # Disks inherited from groups must be considered
+ group_disks = []
+ for group in groups:
+ if client_iqn in group['members']:
+ group_disks = ['{}/{}'.format(x['pool'], x['image'])
+ for x in group['disks']]
+ if not target_config or client_iqn not in target_config['clients'] or \
+ (image_id not in target_config['clients'][client_iqn]['luns']
+ and image_id not in group_disks):
+ IscsiClient.instance(gateway_name=gateway_name).create_client_lun(
+ target_iqn, client_iqn, image_id)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ for group in groups:
+ group_id = group['group_id']
+ members = group['members']
+ image_ids = []
+ for disk in group['disks']:
+ image_ids.append('{}/{}'.format(disk['pool'], disk['image']))
+
+ if target_config and group_id in target_config['groups']:
+ old_members = target_config['groups'][group_id]['members']
+ old_disks = target_config['groups'][group_id]['disks'].keys()
+
+ if not target_config or group_id not in target_config['groups'] or \
+ list(set(group['members']) - set(old_members)) or \
+ list(set(image_ids) - set(old_disks)):
+ IscsiClient.instance(gateway_name=gateway_name).create_group(
+ target_iqn, group_id, members, image_ids)
+ TaskManager.current_task().inc_progress(task_progress_inc)
+ if target_controls:
+ if not target_config or target_controls != target_config['controls']:
+ IscsiClient.instance(gateway_name=gateway_name).reconfigure_target(
+ target_iqn, target_controls)
+ TaskManager.current_task().set_progress(task_progress_end)
+ except RequestException as e:
+ if e.content:
+ content = json.loads(e.content)
+ content_message = content.get('message')
+ if content_message:
+ raise DashboardException(msg=content_message, component='iscsi')
+ raise DashboardException(e=e, component='iscsi')
+
+ @staticmethod
+ def _config_to_target(target_iqn, config):
+ target_config = config['targets'][target_iqn]
+ portals = []
+ for host, portal_config in target_config['portals'].items():
+ for portal_ip in portal_config['portal_ip_addresses']:
+ portal = {
+ 'host': host,
+ 'ip': portal_ip
+ }
+ portals.append(portal)
+ portals = IscsiTarget._sorted_portals(portals)
+ disks = []
+ for target_disk in target_config['disks']:
+ disk_config = config['disks'][target_disk]
+ disk = {
+ 'pool': disk_config['pool'],
+ 'image': disk_config['image'],
+ 'controls': disk_config['controls'],
+ 'backstore': disk_config['backstore'],
+ 'wwn': disk_config['wwn']
+ }
+ # lun_id was introduced in ceph-iscsi config v11
+ if config['version'] > 10:
+ disk['lun'] = target_config['disks'][target_disk]['lun_id']
+ disks.append(disk)
+ disks = IscsiTarget._sorted_disks(disks)
+ clients = []
+ for client_iqn, client_config in target_config['clients'].items():
+ luns = []
+ for client_lun in client_config['luns'].keys():
+ pool, image = client_lun.split('/', 1)
+ lun = {
+ 'pool': pool,
+ 'image': image
+ }
+ luns.append(lun)
+ user = client_config['auth']['username']
+ password = client_config['auth']['password']
+ mutual_user = client_config['auth']['mutual_username']
+ mutual_password = client_config['auth']['mutual_password']
+ client = {
+ 'client_iqn': client_iqn,
+ 'luns': luns,
+ 'auth': {
+ 'user': user,
+ 'password': password,
+ 'mutual_user': mutual_user,
+ 'mutual_password': mutual_password
+ }
+ }
+ clients.append(client)
+ clients = IscsiTarget._sorted_clients(clients)
+ groups = []
+ for group_id, group_config in target_config['groups'].items():
+ group_disks = []
+ for group_disk_key, _ in group_config['disks'].items():
+ pool, image = group_disk_key.split('/', 1)
+ group_disk = {
+ 'pool': pool,
+ 'image': image
+ }
+ group_disks.append(group_disk)
+ group = {
+ 'group_id': group_id,
+ 'disks': group_disks,
+ 'members': group_config['members'],
+ }
+ groups.append(group)
+ groups = IscsiTarget._sorted_groups(groups)
+ target_controls = target_config['controls']
+ acl_enabled = target_config['acl_enabled']
+ target = {
+ 'target_iqn': target_iqn,
+ 'portals': portals,
+ 'disks': disks,
+ 'clients': clients,
+ 'groups': groups,
+ 'target_controls': target_controls,
+ 'acl_enabled': acl_enabled
+ }
+ # Target level authentication was introduced in ceph-iscsi config v11
+ if config['version'] > 10:
+ target_user = target_config['auth']['username']
+ target_password = target_config['auth']['password']
+ target_mutual_user = target_config['auth']['mutual_username']
+ target_mutual_password = target_config['auth']['mutual_password']
+ target['auth'] = {
+ 'user': target_user,
+ 'password': target_password,
+ 'mutual_user': target_mutual_user,
+ 'mutual_password': target_mutual_password
+ }
+ return target
+
+ @staticmethod
+ def _is_executing(target_iqn):
+ executing_tasks, _ = TaskManager.list()
+ for t in executing_tasks:
+ if t.name.startswith('iscsi/target') and t.metadata.get('target_iqn') == target_iqn:
+ return True
+ return False
+
+ @staticmethod
+ def _set_info(target):
+ if not target['portals']:
+ return
+ target_iqn = target['target_iqn']
+ # During task execution, additional info is not available
+ if IscsiTarget._is_executing(target_iqn):
+ return
+ # If any portal is down, additional info is not available
+ for portal in target['portals']:
+ try:
+ IscsiClient.instance(gateway_name=portal['host']).ping()
+ except (IscsiGatewayDoesNotExist, RequestException):
+ return
+ gateway_name = target['portals'][0]['host']
+ try:
+ target_info = IscsiClient.instance(gateway_name=gateway_name).get_targetinfo(
+ target_iqn)
+ target['info'] = target_info
+ for client in target['clients']:
+ client_iqn = client['client_iqn']
+ client_info = IscsiClient.instance(gateway_name=gateway_name).get_clientinfo(
+ target_iqn, client_iqn)
+ client['info'] = client_info
+ except RequestException as e:
+ # Target/Client has been removed in the meanwhile (e.g. using gwcli)
+ if e.status_code != 404:
+ raise e
+
+ @staticmethod
+ def _sorted_portals(portals):
+ portals = portals or []
+ return sorted(portals, key=lambda p: '{}.{}'.format(p['host'], p['ip']))
+
+ @staticmethod
+ def _sorted_disks(disks):
+ disks = disks or []
+ return sorted(disks, key=lambda d: '{}.{}'.format(d['pool'], d['image']))
+
+ @staticmethod
+ def _sorted_clients(clients):
+ clients = clients or []
+ for client in clients:
+ client['luns'] = sorted(client['luns'],
+ key=lambda d: '{}.{}'.format(d['pool'], d['image']))
+ return sorted(clients, key=lambda c: c['client_iqn'])
+
+ @staticmethod
+ def _sorted_groups(groups):
+ groups = groups or []
+ for group in groups:
+ group['disks'] = sorted(group['disks'],
+ key=lambda d: '{}.{}'.format(d['pool'], d['image']))
+ group['members'] = sorted(group['members'])
+ return sorted(groups, key=lambda g: g['group_id'])
+
+ @staticmethod
+ def _get_portals_by_host(portals):
+ portals_by_host = {}
+ for portal in portals:
+ host = portal['host']
+ ip = portal['ip']
+ if host not in portals_by_host:
+ portals_by_host[host] = []
+ portals_by_host[host].append(ip)
+ return portals_by_host
+
+
+def get_available_gateway():
+ gateways = IscsiGatewaysConfig.get_gateways_config()['gateways']
+ if not gateways:
+ raise DashboardException(msg='There are no gateways defined',
+ code='no_gateways_defined',
+ component='iscsi')
+ for gateway in gateways:
+ try:
+ IscsiClient.instance(gateway_name=gateway).ping()
+ return gateway
+ except RequestException:
+ pass
+ raise DashboardException(msg='There are no gateways available',
+ code='no_gateways_available',
+ component='iscsi')
+
+
+def validate_rest_api(gateways):
+ for gateway in gateways:
+ try:
+ IscsiClient.instance(gateway_name=gateway).ping()
+ except RequestException:
+ raise DashboardException(msg='iSCSI REST Api not available for gateway '
+ '{}'.format(gateway),
+ code='ceph_iscsi_rest_api_not_available_for_gateway',
+ component='iscsi')
+
+
+def validate_auth(auth):
+ username_regex = re.compile(r'^[\w\.:@_-]{8,64}$')
+ password_regex = re.compile(r'^[\w@\-_\/]{12,16}$')
+ result = True
+
+ if auth['user'] or auth['password']:
+ result = bool(username_regex.match(auth['user'])) and \
+ bool(password_regex.match(auth['password']))
+
+ if auth['mutual_user'] or auth['mutual_password']:
+ result = result and bool(username_regex.match(auth['mutual_user'])) and \
+ bool(password_regex.match(auth['mutual_password'])) and auth['user']
+
+ if not result:
+ raise DashboardException(msg='Bad authentication',
+ code='target_bad_auth',
+ component='iscsi')
diff --git a/src/pybind/mgr/dashboard/controllers/logging.py b/src/pybind/mgr/dashboard/controllers/logging.py
new file mode 100644
index 00000000..9c7d6de7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/logging.py
@@ -0,0 +1,10 @@
+from . import UiApiController, BaseController, Endpoint
+from .. import logger
+
+
+@UiApiController('/logging', secure=False)
+class Logging(BaseController):
+
+ @Endpoint('POST', path='js-error')
+ def jsError(self, url, message, stack=None):
+ logger.error('frontend error (%s): %s\n %s\n', url, message, stack)
diff --git a/src/pybind/mgr/dashboard/controllers/logs.py b/src/pybind/mgr/dashboard/controllers/logs.py
new file mode 100644
index 00000000..9dc5286f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/logs.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import collections
+
+from . import ApiController, Endpoint, BaseController, ReadPermission
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..tools import NotificationQueue
+
+
+LOG_BUFFER_SIZE = 30
+
+
+@ApiController('/logs', Scope.LOG)
+class Logs(BaseController):
+ def __init__(self):
+ super(Logs, self).__init__()
+ self._log_initialized = False
+ self.log_buffer = collections.deque(maxlen=LOG_BUFFER_SIZE)
+ self.audit_buffer = collections.deque(maxlen=LOG_BUFFER_SIZE)
+
+ def append_log(self, log_struct):
+ if log_struct['channel'] == 'audit':
+ self.audit_buffer.appendleft(log_struct)
+ else:
+ self.log_buffer.appendleft(log_struct)
+
+ def load_buffer(self, buf, channel_name):
+ lines = CephService.send_command(
+ 'mon', 'log last', channel=channel_name, num=LOG_BUFFER_SIZE)
+ for l in lines:
+ buf.appendleft(l)
+
+ def initialize_buffers(self):
+ if not self._log_initialized:
+ self._log_initialized = True
+
+ self.load_buffer(self.log_buffer, 'cluster')
+ self.load_buffer(self.audit_buffer, 'audit')
+
+ NotificationQueue.register(self.append_log, 'clog')
+
+ @Endpoint()
+ @ReadPermission
+ def all(self):
+ self.initialize_buffers()
+ return dict(
+ clog=list(self.log_buffer),
+ audit_log=list(self.audit_buffer),
+ )
diff --git a/src/pybind/mgr/dashboard/controllers/mgr_modules.py b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
new file mode 100644
index 00000000..c37225c9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ApiController, RESTController, \
+ allow_empty_body
+from .. import mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..services.exception import handle_send_command_error
+from ..tools import find_object_in_list, str_to_bool
+
+
+@ApiController('/mgr/module', Scope.CONFIG_OPT)
+class MgrModules(RESTController):
+ ignore_modules = ['selftest']
+
+ def list(self):
+ """
+ Get the list of managed modules.
+ :return: A list of objects with the fields 'enabled', 'name' and 'options'.
+ :rtype: list
+ """
+ result = []
+ mgr_map = mgr.get('mgr_map')
+ always_on_modules = mgr_map['always_on_modules'][mgr.release_name]
+ for module_config in mgr_map['available_modules']:
+ module_name = module_config['name']
+ if module_name not in self.ignore_modules:
+ always_on = module_name in always_on_modules
+ enabled = module_name in mgr_map['modules'] or always_on
+ result.append({
+ 'name': module_name,
+ 'enabled': enabled,
+ 'always_on': always_on,
+ 'options': self._convert_module_options(
+ module_config['module_options'])
+ })
+ return result
+
+ def get(self, module_name):
+ """
+ Retrieve the values of the persistent configuration settings.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The values of the module options.
+ :rtype: dict
+ """
+ assert self._is_module_managed(module_name)
+ options = self._get_module_options(module_name)
+ result = {}
+ for name, option in options.items():
+ result[name] = mgr.get_module_option_ex(module_name, name,
+ option['default_value'])
+ return result
+
+ @RESTController.Resource('PUT')
+ def set(self, module_name, config):
+ """
+ Set the values of the persistent configuration settings.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :param config: The values of the module options to be stored.
+ :type config: dict
+ """
+ assert self._is_module_managed(module_name)
+ options = self._get_module_options(module_name)
+ for name in options.keys():
+ if name in config:
+ mgr.set_module_option_ex(module_name, name, config[name])
+
+ @RESTController.Resource('POST')
+ @handle_send_command_error('mgr_modules')
+ @allow_empty_body
+ def enable(self, module_name):
+ """
+ Enable the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ """
+ assert self._is_module_managed(module_name)
+ CephService.send_command(
+ 'mon', 'mgr module enable', module=module_name)
+
+ @RESTController.Resource('POST')
+ @handle_send_command_error('mgr_modules')
+ @allow_empty_body
+ def disable(self, module_name):
+ """
+ Disable the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ """
+ assert self._is_module_managed(module_name)
+ CephService.send_command(
+ 'mon', 'mgr module disable', module=module_name)
+
+ @RESTController.Resource('GET')
+ def options(self, module_name):
+ """
+ Get the module options of the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module options as list of dicts.
+ :rtype: list
+ """
+ assert self._is_module_managed(module_name)
+ return self._get_module_options(module_name)
+
+ def _is_module_managed(self, module_name):
+ """
+ Check if the specified Ceph Mgr module is managed by this service.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: Returns ``true`` if the Ceph Mgr module is managed by
+ this service, otherwise ``false``.
+ :rtype: bool
+ """
+ if module_name in self.ignore_modules:
+ return False
+ mgr_map = mgr.get('mgr_map')
+ for module_config in mgr_map['available_modules']:
+ if module_name == module_config['name']:
+ return True
+ return False
+
+ def _get_module_config(self, module_name):
+ """
+ Helper function to get detailed module configuration.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module information, e.g. module name, can run,
+ error string and available module options.
+ :rtype: dict or None
+ """
+ mgr_map = mgr.get('mgr_map')
+ return find_object_in_list('name', module_name,
+ mgr_map['available_modules'])
+
+ def _get_module_options(self, module_name):
+ """
+ Helper function to get the module options.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module options.
+ :rtype: dict
+ """
+ options = self._get_module_config(module_name)['module_options']
+ return self._convert_module_options(options)
+
+ def _convert_module_options(self, options):
+ # Workaround a possible bug in the Ceph Mgr implementation.
+ # Various fields (e.g. default_value, min, max) are always
+ # returned as a string.
+ for option in options.values():
+ if option['type'] == 'str':
+ if option['default_value'] == 'None': # This is Python None
+ option['default_value'] = ''
+ elif option['type'] == 'bool':
+ if option['default_value'] == '':
+ option['default_value'] = False
+ else:
+ option['default_value'] = str_to_bool(
+ option['default_value'])
+ elif option['type'] == 'float':
+ for name in ['default_value', 'min', 'max']:
+ if option[name]: # Skip empty entries
+ option[name] = float(option[name])
+ elif option['type'] in ['uint', 'int', 'size', 'secs']:
+ for name in ['default_value', 'min', 'max']:
+ if option[name]: # Skip empty entries
+ option[name] = int(option[name])
+ return options
diff --git a/src/pybind/mgr/dashboard/controllers/monitor.py b/src/pybind/mgr/dashboard/controllers/monitor.py
new file mode 100644
index 00000000..d4512fcf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/monitor.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+from . import ApiController, Endpoint, BaseController, ReadPermission
+from .. import mgr
+from ..security import Scope
+
+
+@ApiController('/monitor', Scope.MONITOR)
+class Monitor(BaseController):
+ @Endpoint()
+ @ReadPermission
+ def __call__(self):
+ in_quorum, out_quorum = [], []
+
+ counters = ['mon.num_sessions']
+
+ mon_status_json = mgr.get("mon_status")
+ mon_status = json.loads(mon_status_json['json'])
+
+ for mon in mon_status["monmap"]["mons"]:
+ mon["stats"] = {}
+ for counter in counters:
+ data = mgr.get_counter("mon", mon["name"], counter)
+ if data is not None:
+ mon["stats"][counter.split(".")[1]] = data[counter]
+ else:
+ mon["stats"][counter.split(".")[1]] = []
+ if mon["rank"] in mon_status["quorum"]:
+ in_quorum.append(mon)
+ else:
+ out_quorum.append(mon)
+
+ return {
+ 'mon_status': mon_status,
+ 'in_quorum': in_quorum,
+ 'out_quorum': out_quorum
+ }
diff --git a/src/pybind/mgr/dashboard/controllers/nfsganesha.py b/src/pybind/mgr/dashboard/controllers/nfsganesha.py
new file mode 100644
index 00000000..b9599d72
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/nfsganesha.py
@@ -0,0 +1,315 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from functools import partial
+
+import cherrypy
+import cephfs
+
+from . import ApiController, RESTController, UiApiController, BaseController, \
+ Endpoint, Task, ReadPermission, ControllerDoc, EndpointDoc
+from .. import logger
+from ..security import Scope
+from ..services.cephfs import CephFS
+from ..services.cephx import CephX
+from ..services.exception import serialize_dashboard_exception
+from ..services.ganesha import Ganesha, GaneshaConf, NFSException
+from ..services.rgw_client import RgwClient
+
+
+# documentation helpers
+EXPORT_SCHEMA = {
+ 'export_id': (int, 'Export ID'),
+ 'path': (str, 'Export path'),
+ 'cluster_id': (str, 'Cluster identifier'),
+ 'daemons': ([str], 'List of NFS Ganesha daemons identifiers'),
+ 'pseudo': (str, 'Pseudo FS path'),
+ 'tag': (str, 'NFSv3 export tag'),
+ 'access_type': (str, 'Export access type'),
+ 'squash': (str, 'Export squash policy'),
+ 'security_label': (str, 'Security label'),
+ 'protocols': ([int], 'List of protocol types'),
+ 'transports': ([str], 'List of transport types'),
+ 'fsal': ({
+ 'name': (str, 'name of FSAL'),
+ 'user_id': (str, 'CephX user id', True),
+ 'filesystem': (str, 'CephFS filesystem ID', True),
+ 'sec_label_xattr': (str, 'Name of xattr for security label', True),
+ 'rgw_user_id': (str, 'RGW user id', True)
+ }, 'FSAL configuration'),
+ 'clients': ([{
+ 'addresses': ([str], 'list of IP addresses'),
+ 'access_type': (str, 'Client access type'),
+ 'squash': (str, 'Client squash policy')
+ }], 'List of client configurations'),
+}
+
+
+CREATE_EXPORT_SCHEMA = {
+ 'path': (str, 'Export path'),
+ 'cluster_id': (str, 'Cluster identifier'),
+ 'daemons': ([str], 'List of NFS Ganesha daemons identifiers'),
+ 'pseudo': (str, 'Pseudo FS path'),
+ 'tag': (str, 'NFSv3 export tag'),
+ 'access_type': (str, 'Export access type'),
+ 'squash': (str, 'Export squash policy'),
+ 'security_label': (str, 'Security label'),
+ 'protocols': ([int], 'List of protocol types'),
+ 'transports': ([str], 'List of transport types'),
+ 'fsal': ({
+ 'name': (str, 'name of FSAL'),
+ 'user_id': (str, 'CephX user id', True),
+ 'filesystem': (str, 'CephFS filesystem ID', True),
+ 'sec_label_xattr': (str, 'Name of xattr for security label', True),
+ 'rgw_user_id': (str, 'RGW user id', True)
+ }, 'FSAL configuration'),
+ 'clients': ([{
+ 'addresses': ([str], 'list of IP addresses'),
+ 'access_type': (str, 'Client access type'),
+ 'squash': (str, 'Client squash policy')
+ }], 'List of client configurations'),
+ 'reload_daemons': (bool,
+ 'Trigger reload of NFS-Ganesha daemons configuration',
+ True)
+}
+
+
+# pylint: disable=not-callable
+def NfsTask(name, metadata, wait_for):
+ def composed_decorator(func):
+ return Task("nfs/{}".format(name), metadata, wait_for,
+ partial(serialize_dashboard_exception,
+ include_http_status=True))(func)
+ return composed_decorator
+
+
+@ApiController('/nfs-ganesha', Scope.NFS_GANESHA)
+@ControllerDoc("NFS-Ganesha Management API", "NFS-Ganesha")
+class NFSGanesha(RESTController):
+
+ @EndpointDoc("Status of NFS-Ganesha management feature",
+ responses={200: {
+ 'available': (bool, "Is API available?"),
+ 'message': (str, "Error message")
+ }})
+ @Endpoint()
+ @ReadPermission
+ def status(self):
+ status = {'available': True, 'message': None}
+ try:
+ Ganesha.get_ganesha_clusters()
+ except NFSException as e:
+ status['message'] = str(e)
+ status['available'] = False
+
+ return status
+
+
+@ApiController('/nfs-ganesha/export', Scope.NFS_GANESHA)
+@ControllerDoc(group="NFS-Ganesha")
+class NFSGaneshaExports(RESTController):
+ RESOURCE_ID = "cluster_id/export_id"
+
+ @EndpointDoc("List all NFS-Ganesha exports",
+ responses={200: [EXPORT_SCHEMA]})
+ def list(self):
+ result = []
+ for cluster_id in Ganesha.get_ganesha_clusters():
+ result.extend(
+ [export.to_dict()
+ for export in GaneshaConf.instance(cluster_id).list_exports()])
+ return result
+
+ @NfsTask('create', {'path': '{path}', 'fsal': '{fsal.name}',
+ 'cluster_id': '{cluster_id}'}, 2.0)
+ @EndpointDoc("Creates a new NFS-Ganesha export",
+ parameters=CREATE_EXPORT_SCHEMA,
+ responses={201: EXPORT_SCHEMA})
+ def create(self, path, cluster_id, daemons, pseudo, tag, access_type,
+ squash, security_label, protocols, transports, fsal, clients,
+ reload_daemons=True):
+ if fsal['name'] not in Ganesha.fsals_available():
+ raise NFSException("Cannot create this export. "
+ "FSAL '{}' cannot be managed by the dashboard."
+ .format(fsal['name']))
+
+ ganesha_conf = GaneshaConf.instance(cluster_id)
+ ex_id = ganesha_conf.create_export({
+ 'path': path,
+ 'pseudo': pseudo,
+ 'cluster_id': cluster_id,
+ 'daemons': daemons,
+ 'tag': tag,
+ 'access_type': access_type,
+ 'squash': squash,
+ 'security_label': security_label,
+ 'protocols': protocols,
+ 'transports': transports,
+ 'fsal': fsal,
+ 'clients': clients
+ })
+ if reload_daemons:
+ ganesha_conf.reload_daemons(daemons)
+ return ganesha_conf.get_export(ex_id).to_dict()
+
+ @EndpointDoc("Get an NFS-Ganesha export",
+ parameters={
+ 'cluster_id': (str, 'Cluster identifier'),
+ 'export_id': (int, "Export ID")
+ },
+ responses={200: EXPORT_SCHEMA})
+ def get(self, cluster_id, export_id):
+ export_id = int(export_id)
+ ganesha_conf = GaneshaConf.instance(cluster_id)
+ if not ganesha_conf.has_export(export_id):
+ raise cherrypy.HTTPError(404)
+ return ganesha_conf.get_export(export_id).to_dict()
+
+ @NfsTask('edit', {'cluster_id': '{cluster_id}', 'export_id': '{export_id}'},
+ 2.0)
+ @EndpointDoc("Updates an NFS-Ganesha export",
+ parameters=dict(export_id=(int, "Export ID"),
+ **CREATE_EXPORT_SCHEMA),
+ responses={200: EXPORT_SCHEMA})
+ def set(self, cluster_id, export_id, path, daemons, pseudo, tag, access_type,
+ squash, security_label, protocols, transports, fsal, clients,
+ reload_daemons=True):
+ export_id = int(export_id)
+ ganesha_conf = GaneshaConf.instance(cluster_id)
+
+ if not ganesha_conf.has_export(export_id):
+ raise cherrypy.HTTPError(404)
+
+ if fsal['name'] not in Ganesha.fsals_available():
+ raise NFSException("Cannot make modifications to this export. "
+ "FSAL '{}' cannot be managed by the dashboard."
+ .format(fsal['name']))
+
+ old_export = ganesha_conf.update_export({
+ 'export_id': export_id,
+ 'path': path,
+ 'cluster_id': cluster_id,
+ 'daemons': daemons,
+ 'pseudo': pseudo,
+ 'tag': tag,
+ 'access_type': access_type,
+ 'squash': squash,
+ 'security_label': security_label,
+ 'protocols': protocols,
+ 'transports': transports,
+ 'fsal': fsal,
+ 'clients': clients
+ })
+ daemons = list(daemons)
+ for d_id in old_export.daemons:
+ if d_id not in daemons:
+ daemons.append(d_id)
+ if reload_daemons:
+ ganesha_conf.reload_daemons(daemons)
+ return ganesha_conf.get_export(export_id).to_dict()
+
+ @NfsTask('delete', {'cluster_id': '{cluster_id}',
+ 'export_id': '{export_id}'}, 2.0)
+ @EndpointDoc("Deletes an NFS-Ganesha export",
+ parameters={
+ 'cluster_id': (str, 'Cluster identifier'),
+ 'export_id': (int, "Export ID"),
+ 'reload_daemons': (bool,
+ 'Trigger reload of NFS-Ganesha daemons'
+ ' configuration',
+ True)
+ })
+ def delete(self, cluster_id, export_id, reload_daemons=True):
+ export_id = int(export_id)
+ ganesha_conf = GaneshaConf.instance(cluster_id)
+
+ if not ganesha_conf.has_export(export_id):
+ raise cherrypy.HTTPError(404)
+
+ export = ganesha_conf.remove_export(export_id)
+ if reload_daemons:
+ ganesha_conf.reload_daemons(export.daemons)
+
+
+@ApiController('/nfs-ganesha/daemon', Scope.NFS_GANESHA)
+@ControllerDoc(group="NFS-Ganesha")
+class NFSGaneshaService(RESTController):
+
+ @EndpointDoc("List NFS-Ganesha daemons information",
+ responses={200: [{
+ 'daemon_id': (str, 'Daemon identifier'),
+ 'cluster_id': (str, 'Cluster identifier'),
+ 'status': (int,
+ 'Status of daemon (1=RUNNING, 0=STOPPED, -1=ERROR',
+ True),
+ 'desc': (str, 'Error description (if status==-1)', True)
+ }]})
+ def list(self):
+ status_dict = Ganesha.get_daemons_status()
+ if status_dict:
+ return [
+ {
+ 'daemon_id': daemon_id,
+ 'cluster_id': cluster_id,
+ 'status': status_dict[cluster_id][daemon_id]['status'],
+ 'desc': status_dict[cluster_id][daemon_id]['desc']
+ }
+ for cluster_id in status_dict
+ for daemon_id in status_dict[cluster_id]
+ ]
+
+ result = []
+ for cluster_id in Ganesha.get_ganesha_clusters():
+ result.extend(
+ [{'daemon_id': daemon_id, 'cluster_id': cluster_id}
+ for daemon_id in GaneshaConf.instance(cluster_id).list_daemons()])
+ return result
+
+
+@UiApiController('/nfs-ganesha', Scope.NFS_GANESHA)
+class NFSGaneshaUi(BaseController):
+ @Endpoint('GET', '/cephx/clients')
+ @ReadPermission
+ def cephx_clients(self):
+ return [client for client in CephX.list_clients()]
+
+ @Endpoint('GET', '/fsals')
+ @ReadPermission
+ def fsals(self):
+ return Ganesha.fsals_available()
+
+ @Endpoint('GET', '/lsdir')
+ @ReadPermission
+ def lsdir(self, root_dir=None, depth=1): # pragma: no cover
+ if root_dir is None:
+ root_dir = "/"
+ depth = int(depth)
+ if depth > 5:
+ logger.warning("[NFS] Limiting depth to maximum value of 5: "
+ "input depth=%s", depth)
+ depth = 5
+ root_dir = '{}/'.format(root_dir) \
+ if not root_dir.endswith('/') else root_dir
+
+ try:
+ cfs = CephFS()
+ paths = cfs.get_dir_list(root_dir, depth)
+ paths = [p[:-1] for p in paths if p != root_dir]
+ return {'paths': paths}
+ except (cephfs.ObjectNotFound, cephfs.PermissionError):
+ return {'paths': []}
+
+ @Endpoint('GET', '/cephfs/filesystems')
+ @ReadPermission
+ def filesystems(self):
+ return CephFS.list_filesystems()
+
+ @Endpoint('GET', '/rgw/buckets')
+ @ReadPermission
+ def buckets(self, user_id=None):
+ return RgwClient.instance(user_id).get_buckets()
+
+ @Endpoint('GET', '/clusters')
+ @ReadPermission
+ def clusters(self):
+ return Ganesha.get_ganesha_clusters()
diff --git a/src/pybind/mgr/dashboard/controllers/osd.py b/src/pybind/mgr/dashboard/controllers/osd.py
new file mode 100644
index 00000000..a971a512
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/osd.py
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from mgr_util import get_most_recent_rate
+
+from . import ApiController, RESTController, UpdatePermission, \
+ allow_empty_body
+from .. import mgr, logger
+from ..security import Scope
+from ..services.ceph_service import CephService, SendCommandError
+from ..services.exception import handle_send_command_error
+from ..tools import str_to_bool
+try:
+ from typing import Dict, List, Any, Union # pylint: disable=unused-import
+except ImportError:
+ pass # For typing only
+
+
+@ApiController('/osd', Scope.OSD)
+class Osd(RESTController):
+ def list(self):
+ osds = self.get_osd_map()
+
+ # Extending by osd stats information
+ for stat in mgr.get('osd_stats')['osd_stats']:
+ if stat['osd'] in osds:
+ osds[stat['osd']]['osd_stats'] = stat
+
+ # Extending by osd node information
+ nodes = mgr.get('osd_map_tree')['nodes']
+ for node in nodes:
+ if node['type'] == 'osd' and node['id'] in osds:
+ osds[node['id']]['tree'] = node
+
+ # Extending by osd parent node information
+ for host in [n for n in nodes if n['type'] == 'host']:
+ for osd_id in host['children']:
+ if osd_id >= 0 and osd_id in osds:
+ osds[osd_id]['host'] = host
+
+ # Extending by osd histogram data
+ for osd_id, osd in osds.items():
+ osd['stats'] = {}
+ osd['stats_history'] = {}
+ osd_spec = str(osd_id)
+ if 'osd' not in osd:
+ continue
+ for stat in ['osd.op_w', 'osd.op_in_bytes', 'osd.op_r', 'osd.op_out_bytes']:
+ prop = stat.split('.')[1]
+ rates = CephService.get_rates('osd', osd_spec, stat)
+ osd['stats'][prop] = get_most_recent_rate(rates)
+ osd['stats_history'][prop] = rates
+ # Gauge stats
+ for stat in ['osd.numpg', 'osd.stat_bytes', 'osd.stat_bytes_used']:
+ osd['stats'][stat.split('.')[1]] = mgr.get_latest('osd', osd_spec, stat)
+
+ return list(osds.values())
+
+ @staticmethod
+ def get_osd_map(svc_id=None):
+ # type: (Union[int, None]) -> Dict[int, Union[Dict[str, Any], Any]]
+ def add_id(osd):
+ osd['id'] = osd['osd']
+ return osd
+ resp = {
+ osd['osd']: add_id(osd)
+ for osd in mgr.get('osd_map')['osds'] if svc_id is None or osd['osd'] == int(svc_id)
+ }
+ return resp if svc_id is None else resp[int(svc_id)]
+
+ @handle_send_command_error('osd')
+ def get(self, svc_id):
+ """
+ Returns collected data about an OSD.
+
+ :return: Returns the requested data. The `histogram` key man contain a
+ string with an error that occurred when the OSD is down.
+ """
+ try:
+ histogram = CephService.send_command('osd', srv_spec=svc_id,
+ prefix='perf histogram dump')
+ except SendCommandError as e:
+ if 'osd down' in str(e):
+ histogram = str(e)
+ else:
+ raise
+
+ return {
+ 'osd_map': self.get_osd_map(svc_id),
+ 'osd_metadata': mgr.get_metadata('osd', svc_id),
+ 'histogram': histogram,
+ }
+
+ @RESTController.Resource('POST', query_params=['deep'])
+ @UpdatePermission
+ @allow_empty_body
+ def scrub(self, svc_id, deep=False):
+ api_scrub = "osd deep-scrub" if str_to_bool(deep) else "osd scrub"
+ CephService.send_command("mon", api_scrub, who=svc_id)
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def mark_out(self, svc_id):
+ CephService.send_command('mon', 'osd out', ids=[svc_id])
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def mark_in(self, svc_id):
+ CephService.send_command('mon', 'osd in', ids=[svc_id])
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def mark_down(self, svc_id):
+ CephService.send_command('mon', 'osd down', ids=[svc_id])
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def reweight(self, svc_id, weight):
+ """
+ Reweights the OSD temporarily.
+
+ Note that ‘ceph osd reweight’ is not a persistent setting. When an OSD
+ gets marked out, the osd weight will be set to 0. When it gets marked
+ in again, the weight will be changed to 1.
+
+ Because of this ‘ceph osd reweight’ is a temporary solution. You should
+ only use it to keep your cluster running while you’re ordering more
+ hardware.
+
+ - Craig Lewis (http://lists.ceph.com/pipermail/ceph-users-ceph.com/2014-June/040967.html)
+ """
+ CephService.send_command(
+ 'mon',
+ 'osd reweight',
+ id=int(svc_id),
+ weight=float(weight))
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def mark_lost(self, svc_id):
+ """
+ Note: osd must be marked `down` before marking lost.
+ """
+ CephService.send_command(
+ 'mon',
+ 'osd lost',
+ id=int(svc_id),
+ yes_i_really_mean_it=True)
+
+ def create(self, uuid=None, svc_id=None):
+ """
+ :param uuid: Will be set automatically if the OSD starts up.
+ :param id: The ID is only used if a valid uuid is given.
+ :return:
+ """
+ result = CephService.send_command(
+ 'mon', 'osd create', id=int(svc_id), uuid=uuid)
+ return {
+ 'result': result,
+ 'svc_id': int(svc_id),
+ 'uuid': uuid,
+ }
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def purge(self, svc_id):
+ """
+ Note: osd must be marked `down` before removal.
+ """
+ CephService.send_command('mon', 'osd purge-actual', id=int(svc_id),
+ yes_i_really_mean_it=True)
+
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def destroy(self, svc_id):
+ """
+ Mark osd as being destroyed. Keeps the ID intact (allowing reuse), but
+ removes cephx keys, config-key data and lockbox keys, rendering data
+ permanently unreadable.
+
+ The osd must be marked down before being destroyed.
+ """
+ CephService.send_command(
+ 'mon', 'osd destroy-actual', id=int(svc_id), yes_i_really_mean_it=True)
+
+ @RESTController.Resource('GET')
+ def safe_to_destroy(self, svc_id):
+ """
+ :type svc_id: int|[int]
+ """
+ if not isinstance(svc_id, list):
+ svc_id = [svc_id]
+ svc_id = list(map(str, svc_id))
+ try:
+ result = CephService.send_command(
+ 'mon', 'osd safe-to-destroy', ids=svc_id, target=('mgr', ''))
+ result['is_safe_to_destroy'] = set(result['safe_to_destroy']) == set(map(int, svc_id))
+ return result
+
+ except SendCommandError as e:
+ return {
+ 'message': str(e),
+ 'is_safe_to_destroy': False,
+ }
+
+
+@ApiController('/osd/flags', Scope.OSD)
+class OsdFlagsController(RESTController):
+ @staticmethod
+ def _osd_flags():
+ enabled_flags = mgr.get('osd_map')['flags_set']
+ if 'pauserd' in enabled_flags and 'pausewr' in enabled_flags:
+ # 'pause' is set by calling `ceph osd set pause` and unset by
+ # calling `set osd unset pause`, but `ceph osd dump | jq '.flags'`
+ # will contain 'pauserd,pausewr' if pause is set.
+ # Let's pretend to the API that 'pause' is in fact a proper flag.
+ enabled_flags = list(
+ set(enabled_flags) - {'pauserd', 'pausewr'} | {'pause'})
+ return sorted(enabled_flags)
+
+ def list(self):
+ return self._osd_flags()
+
+ def bulk_set(self, flags):
+ """
+ The `recovery_deletes`, `sortbitwise` and `pglog_hardlimit` flags cannot be unset.
+ `purged_snapshots` cannot even be set. It is therefore required to at
+ least include those four flags for a successful operation.
+ """
+ assert isinstance(flags, list)
+
+ enabled_flags = set(self._osd_flags())
+ data = set(flags)
+ added = data - enabled_flags
+ removed = enabled_flags - data
+ for flag in added:
+ CephService.send_command('mon', 'osd set', '', key=flag)
+ for flag in removed:
+ CephService.send_command('mon', 'osd unset', '', key=flag)
+ logger.info('Changed OSD flags: added=%s removed=%s', added, removed)
+
+ return sorted(enabled_flags - removed | added)
diff --git a/src/pybind/mgr/dashboard/controllers/perf_counters.py b/src/pybind/mgr/dashboard/controllers/perf_counters.py
new file mode 100644
index 00000000..158641ca
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/perf_counters.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cherrypy
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+
+
+class PerfCounter(RESTController):
+ service_type = None # type: str
+
+ def get(self, service_id):
+ schema_dict = mgr.get_perf_schema(self.service_type, str(service_id))
+ try:
+ schema = schema_dict["{}.{}".format(self.service_type, service_id)]
+ except KeyError as e:
+ raise cherrypy.HTTPError(404, "{0} not found".format(e))
+ counters = []
+
+ for key, value in sorted(schema.items()):
+ counter = dict()
+ counter['name'] = str(key)
+ counter['description'] = value['description']
+ # pylint: disable=W0212
+ if mgr._stattype_to_str(value['type']) == 'counter':
+ counter['value'] = CephService.get_rate(
+ self.service_type, service_id, key)
+ counter['unit'] = mgr._unit_to_str(value['units'])
+ else:
+ counter['value'] = mgr.get_latest(
+ self.service_type, service_id, key)
+ counter['unit'] = ''
+ counters.append(counter)
+
+ return {
+ 'service': {
+ 'type': self.service_type,
+ 'id': str(service_id)
+ },
+ 'counters': counters
+ }
+
+
+@ApiController('perf_counters/mds', Scope.CEPHFS)
+class MdsPerfCounter(PerfCounter):
+ service_type = 'mds'
+
+
+@ApiController('perf_counters/mon', Scope.MONITOR)
+class MonPerfCounter(PerfCounter):
+ service_type = 'mon'
+
+
+@ApiController('perf_counters/osd', Scope.OSD)
+class OsdPerfCounter(PerfCounter):
+ service_type = 'osd'
+
+
+@ApiController('perf_counters/rgw', Scope.RGW)
+class RgwPerfCounter(PerfCounter):
+ service_type = 'rgw'
+
+
+@ApiController('perf_counters/rbd-mirror', Scope.RBD_MIRRORING)
+class RbdMirrorPerfCounter(PerfCounter):
+ service_type = 'rbd-mirror'
+
+
+@ApiController('perf_counters/mgr', Scope.MANAGER)
+class MgrPerfCounter(PerfCounter):
+ service_type = 'mgr'
+
+
+@ApiController('perf_counters/tcmu-runner', Scope.ISCSI)
+class TcmuRunnerPerfCounter(PerfCounter):
+ service_type = 'tcmu-runner'
+
+
+@ApiController('perf_counters')
+class PerfCounters(RESTController):
+ def list(self):
+ return mgr.get_all_perf_counters()
diff --git a/src/pybind/mgr/dashboard/controllers/pool.py b/src/pybind/mgr/dashboard/controllers/pool.py
new file mode 100644
index 00000000..c6919fc2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/pool.py
@@ -0,0 +1,234 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import time
+import cherrypy
+
+from . import ApiController, RESTController, Endpoint, ReadPermission, Task
+from .. import mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..services.rbd import RbdConfiguration
+from ..services.exception import handle_send_command_error
+from ..tools import str_to_bool, TaskManager
+
+
+def pool_task(name, metadata, wait_for=2.0):
+ return Task("pool/{}".format(name), metadata, wait_for)
+
+
+@ApiController('/pool', Scope.POOL)
+class Pool(RESTController):
+
+ @staticmethod
+ def _serialize_pool(pool, attrs):
+ if not attrs or not isinstance(attrs, list):
+ attrs = pool.keys()
+
+ crush_rules = {r['rule_id']: r["rule_name"] for r in mgr.get('osd_map_crush')['rules']}
+
+ res = {}
+ for attr in attrs:
+ if attr not in pool:
+ continue
+ if attr == 'type':
+ res[attr] = {1: 'replicated', 3: 'erasure'}[pool[attr]]
+ elif attr == 'crush_rule':
+ res[attr] = crush_rules[pool[attr]]
+ elif attr == 'application_metadata':
+ res[attr] = list(pool[attr].keys())
+ else:
+ res[attr] = pool[attr]
+
+ # pool_name is mandatory
+ res['pool_name'] = pool['pool_name']
+ return res
+
+ @classmethod
+ def _pool_list(cls, attrs=None, stats=False):
+ if attrs:
+ attrs = attrs.split(',')
+
+ if str_to_bool(stats):
+ pools = CephService.get_pool_list_with_stats()
+ else:
+ pools = CephService.get_pool_list()
+
+ return [cls._serialize_pool(pool, attrs) for pool in pools]
+
+ def list(self, attrs=None, stats=False):
+ return self._pool_list(attrs, stats)
+
+ @classmethod
+ def _get(cls, pool_name, attrs=None, stats=False):
+ # type: (str, str, bool) -> dict
+ pools = cls._pool_list(attrs, stats)
+ pool = [pool for pool in pools if pool['pool_name'] == pool_name]
+ if not pool:
+ raise cherrypy.NotFound('No such pool')
+ return pool[0]
+
+ def get(self, pool_name, attrs=None, stats=False):
+ # type: (str, str, bool) -> dict
+ pool = self._get(pool_name, attrs, stats)
+ pool['configuration'] = RbdConfiguration(pool_name).list()
+ return pool
+
+ @pool_task('delete', ['{pool_name}'])
+ @handle_send_command_error('pool')
+ def delete(self, pool_name):
+ return CephService.send_command('mon', 'osd pool delete', pool=pool_name, pool2=pool_name,
+ yes_i_really_really_mean_it=True)
+
+ @pool_task('edit', ['{pool_name}'])
+ def set(self, pool_name, flags=None, application_metadata=None, configuration=None, **kwargs):
+ self._set_pool_values(pool_name, application_metadata, flags, True, kwargs)
+ if kwargs.get('pool'):
+ pool_name = kwargs['pool']
+ RbdConfiguration(pool_name).set_configuration(configuration)
+ self._wait_for_pgs(pool_name)
+
+ @pool_task('create', {'pool_name': '{pool}'})
+ @handle_send_command_error('pool')
+ def create(self, pool, pg_num, pool_type, erasure_code_profile=None, flags=None,
+ application_metadata=None, rule_name=None, configuration=None, **kwargs):
+ ecp = erasure_code_profile if erasure_code_profile else None
+ CephService.send_command('mon', 'osd pool create', pool=pool, pg_num=int(pg_num),
+ pgp_num=int(pg_num), pool_type=pool_type, erasure_code_profile=ecp,
+ rule=rule_name)
+ self._set_pool_values(pool, application_metadata, flags, False, kwargs)
+ RbdConfiguration(pool).set_configuration(configuration)
+ self._wait_for_pgs(pool)
+
+ def _set_pool_values(self, pool, application_metadata, flags, update_existing, kwargs):
+ update_name = False
+ current_pool = self._get(pool)
+ if update_existing and kwargs.get('compression_mode') == 'unset':
+ self._prepare_compression_removal(current_pool.get('options'), kwargs)
+ if flags and 'ec_overwrites' in flags:
+ CephService.send_command('mon', 'osd pool set', pool=pool, var='allow_ec_overwrites',
+ val='true')
+ if application_metadata is not None:
+ def set_app(what, app):
+ CephService.send_command('mon', 'osd pool application ' + what, pool=pool, app=app,
+ yes_i_really_mean_it=True)
+ if update_existing:
+ original_app_metadata = set(
+ current_pool.get('application_metadata'))
+ else:
+ original_app_metadata = set()
+
+ for app in original_app_metadata - set(application_metadata):
+ set_app('disable', app)
+ for app in set(application_metadata) - original_app_metadata:
+ set_app('enable', app)
+
+ def set_key(key, value):
+ CephService.send_command('mon', 'osd pool set', pool=pool, var=key, val=str(value))
+
+ for key, value in kwargs.items():
+ if key == 'pool':
+ update_name = True
+ destpool = value
+ else:
+ set_key(key, value)
+ if key == 'pg_num':
+ set_key('pgp_num', value)
+ if update_name:
+ CephService.send_command('mon', 'osd pool rename', srcpool=pool, destpool=destpool)
+
+ def _prepare_compression_removal(self, options, kwargs):
+ """
+ Presets payload with values to remove compression attributes in case they are not
+ needed anymore.
+
+ In case compression is not needed the dashboard will send 'compression_mode' with the
+ value 'unset'.
+
+ :param options: All set options for the current pool.
+ :param kwargs: Payload of the PUT / POST call
+ """
+ if options is not None:
+ def reset_arg(arg, value):
+ if options.get(arg):
+ kwargs[arg] = value
+ for arg in ['compression_min_blob_size', 'compression_max_blob_size',
+ 'compression_required_ratio']:
+ reset_arg(arg, '0')
+ reset_arg('compression_algorithm', 'unset')
+
+ @classmethod
+ def _wait_for_pgs(cls, pool_name):
+ """
+ Keep the task waiting for until all pg changes are complete
+ :param pool_name: The name of the pool.
+ :type pool_name: string
+ """
+ current_pool = cls._get(pool_name)
+ initial_pgs = int(current_pool['pg_placement_num']) + int(current_pool['pg_num'])
+ cls._pg_wait_loop(current_pool, initial_pgs)
+
+ @classmethod
+ def _pg_wait_loop(cls, pool, initial_pgs):
+ """
+ Compares if all pg changes are completed, if not it will call itself
+ until all changes are completed.
+ :param pool: The dict that represents a pool.
+ :type pool: dict
+ :param initial_pgs: The pg and pg_num count before any change happened.
+ :type initial_pgs: int
+ """
+ if 'pg_num_target' in pool:
+ target = int(pool['pg_num_target']) + int(pool['pg_placement_num_target'])
+ current = int(pool['pg_placement_num']) + int(pool['pg_num'])
+ if current != target:
+ max_diff = abs(target - initial_pgs)
+ diff = max_diff - abs(target - current)
+ percentage = int(round(diff / float(max_diff) * 100))
+ TaskManager.current_task().set_progress(percentage)
+ time.sleep(4)
+ cls._pg_wait_loop(cls._get(pool['pool_name']), initial_pgs)
+
+ @RESTController.Resource()
+ @ReadPermission
+ def configuration(self, pool_name):
+ return RbdConfiguration(pool_name).list()
+
+ @Endpoint()
+ @ReadPermission
+ def _info(self, pool_name=''):
+ # type: (str) -> dict
+ """Used by the create-pool dialog"""
+
+ def rules(pool_type):
+ return [r
+ for r in mgr.get('osd_map_crush')['rules']
+ if r['type'] == pool_type]
+
+ def all_bluestore():
+ return all(o['osd_objectstore'] == 'bluestore'
+ for o in mgr.get('osd_metadata').values())
+
+ def get_config_option_enum(conf_name):
+ return [[v for v in o['enum_values'] if len(v) > 0]
+ for o in mgr.get('config_options')['options']
+ if o['name'] == conf_name][0]
+
+ mgr_config = mgr.get('config')
+ result = {
+ "pool_names": [p['pool_name'] for p in self._pool_list()],
+ "crush_rules_replicated": rules(1),
+ "crush_rules_erasure": rules(3),
+ "is_all_bluestore": all_bluestore(),
+ "osd_count": len(mgr.get('osd_map')['osds']),
+ "bluestore_compression_algorithm": mgr_config['bluestore_compression_algorithm'],
+ "compression_algorithms": get_config_option_enum('bluestore_compression_algorithm'),
+ "compression_modes": get_config_option_enum('bluestore_compression_mode'),
+ "pg_autoscale_default_mode": mgr_config['osd_pool_default_pg_autoscale_mode'],
+ "pg_autoscale_modes": get_config_option_enum('osd_pool_default_pg_autoscale_mode'),
+ }
+
+ if pool_name:
+ result['pool_options'] = RbdConfiguration(pool_name).list()
+
+ return result
diff --git a/src/pybind/mgr/dashboard/controllers/prometheus.py b/src/pybind/mgr/dashboard/controllers/prometheus.py
new file mode 100644
index 00000000..40333541
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/prometheus.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from datetime import datetime
+import json
+import requests
+
+from . import Controller, ApiController, BaseController, RESTController, Endpoint
+from ..security import Scope
+from ..settings import Settings
+from ..exceptions import DashboardException
+
+
+@Controller('/api/prometheus_receiver', secure=False)
+class PrometheusReceiver(BaseController):
+ ''' The receiver is needed in order to receive alert notifications (reports) '''
+ notifications = []
+
+ @Endpoint('POST', path='/')
+ def fetch_alert(self, **notification):
+ notification['notified'] = datetime.now().isoformat()
+ notification['id'] = str(len(self.notifications))
+ self.notifications.append(notification)
+
+
+class PrometheusRESTController(RESTController):
+ def prometheus_proxy(self, method, path, params=None, payload=None):
+ return self._proxy(self._get_api_url(Settings.PROMETHEUS_API_HOST),
+ method, path, params, payload)
+
+ def alert_proxy(self, method, path, params=None, payload=None):
+ return self._proxy(self._get_api_url(Settings.ALERTMANAGER_API_HOST),
+ method, path, params, payload)
+
+ def _get_api_url(self, host):
+ return host.rstrip('/') + '/api/v1'
+
+ def _proxy(self, base_url, method, path, params=None, payload=None):
+ try:
+ response = requests.request(method, base_url + path, params=params, json=payload)
+ except Exception:
+ raise DashboardException('Could not reach external API', http_status_code=404,
+ component='prometheus')
+ content = json.loads(response.content)
+ if content['status'] == 'success':
+ if 'data' in content:
+ return content['data']
+ return content
+ raise DashboardException(content, http_status_code=400, component='prometheus')
+
+
+@ApiController('/prometheus', Scope.PROMETHEUS)
+class Prometheus(PrometheusRESTController):
+ def list(self, **params):
+ return self.alert_proxy('GET', '/alerts', params)
+
+ @RESTController.Collection(method='GET')
+ def rules(self, **params):
+ return self.prometheus_proxy('GET', '/rules', params)
+
+ @RESTController.Collection(method='GET', path='/silences')
+ def get_silences(self, **params):
+ return self.alert_proxy('GET', '/silences', params)
+
+ @RESTController.Collection(method='POST', path='/silence', status=201)
+ def create_silence(self, **params):
+ return self.alert_proxy('POST', '/silences', payload=params)
+
+ @RESTController.Collection(method='DELETE', path='/silence/{s_id}', status=204)
+ def delete_silence(self, s_id):
+ return self.alert_proxy('DELETE', '/silence/' + s_id) if s_id else None
+
+
+@ApiController('/prometheus/notifications', Scope.PROMETHEUS)
+class PrometheusNotifications(RESTController):
+
+ def list(self, **params):
+ if 'from' in params:
+ f = params['from']
+ if f == 'last':
+ return PrometheusReceiver.notifications[-1:]
+ return PrometheusReceiver.notifications[int(f) + 1:]
+ return PrometheusReceiver.notifications
diff --git a/src/pybind/mgr/dashboard/controllers/rbd.py b/src/pybind/mgr/dashboard/controllers/rbd.py
new file mode 100644
index 00000000..52dca087
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/rbd.py
@@ -0,0 +1,526 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=unused-argument
+# pylint: disable=too-many-statements,too-many-branches
+from __future__ import absolute_import
+
+import math
+from functools import partial
+from datetime import datetime
+
+import cherrypy
+
+import rbd
+
+from . import ApiController, RESTController, Task, UpdatePermission, \
+ DeletePermission, CreatePermission, ReadPermission, allow_empty_body
+from .. import mgr, logger
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..services.rbd import RbdConfiguration, format_bitmask, format_features
+from ..tools import ViewCache, str_to_bool
+from ..services.exception import handle_rados_error, handle_rbd_error, \
+ serialize_dashboard_exception
+
+
+# pylint: disable=not-callable
+def RbdTask(name, metadata, wait_for):
+ def composed_decorator(func):
+ func = handle_rados_error('pool')(func)
+ func = handle_rbd_error()(func)
+ return Task("rbd/{}".format(name), metadata, wait_for,
+ partial(serialize_dashboard_exception, include_http_status=True))(func)
+ return composed_decorator
+
+
+def _rbd_call(pool_name, func, *args, **kwargs):
+ with mgr.rados.open_ioctx(pool_name) as ioctx:
+ func(ioctx, *args, **kwargs)
+
+
+def _rbd_image_call(pool_name, image_name, func, *args, **kwargs):
+ def _ioctx_func(ioctx, image_name, func, *args, **kwargs):
+ with rbd.Image(ioctx, image_name) as img:
+ func(ioctx, img, *args, **kwargs)
+
+ return _rbd_call(pool_name, _ioctx_func, image_name, func, *args, **kwargs)
+
+
+def _sort_features(features, enable=True):
+ """
+ Sorts image features according to feature dependencies:
+
+ object-map depends on exclusive-lock
+ journaling depends on exclusive-lock
+ fast-diff depends on object-map
+ """
+ ORDER = ['exclusive-lock', 'journaling', 'object-map', 'fast-diff']
+
+ def key_func(feat):
+ try:
+ return ORDER.index(feat)
+ except ValueError:
+ return id(feat)
+
+ features.sort(key=key_func, reverse=not enable)
+
+
+@ApiController('/block/image', Scope.RBD_IMAGE)
+class Rbd(RESTController):
+
+ RESOURCE_ID = "pool_name/image_name"
+
+ # set of image features that can be enable on existing images
+ ALLOW_ENABLE_FEATURES = {"exclusive-lock", "object-map", "fast-diff", "journaling"}
+
+ # set of image features that can be disabled on existing images
+ ALLOW_DISABLE_FEATURES = {"exclusive-lock", "object-map", "fast-diff", "deep-flatten",
+ "journaling"}
+
+ @classmethod
+ def _rbd_disk_usage(cls, image, snaps, whole_object=True):
+ class DUCallback(object):
+ def __init__(self):
+ self.used_size = 0
+
+ def __call__(self, offset, length, exists):
+ if exists:
+ self.used_size += length
+
+ snap_map = {}
+ prev_snap = None
+ total_used_size = 0
+ for _, size, name in snaps:
+ image.set_snap(name)
+ du_callb = DUCallback()
+ image.diff_iterate(0, size, prev_snap, du_callb,
+ whole_object=whole_object)
+ snap_map[name] = du_callb.used_size
+ total_used_size += du_callb.used_size
+ prev_snap = name
+
+ return total_used_size, snap_map
+
+ @classmethod
+ def _rbd_image(cls, ioctx, pool_name, image_name):
+ with rbd.Image(ioctx, image_name) as img:
+ stat = img.stat()
+ stat['name'] = image_name
+ if img.old_format():
+ stat['unique_id'] = '{}/{}'.format(pool_name, stat['block_name_prefix'])
+ stat['id'] = stat['unique_id']
+ stat['image_format'] = 1
+ else:
+ stat['unique_id'] = '{}/{}'.format(pool_name, img.id())
+ stat['id'] = img.id()
+ stat['image_format'] = 2
+
+ stat['pool_name'] = pool_name
+ features = img.features()
+ stat['features'] = features
+ stat['features_name'] = format_bitmask(features)
+
+ # the following keys are deprecated
+ del stat['parent_pool']
+ del stat['parent_name']
+
+ stat['timestamp'] = "{}Z".format(img.create_timestamp()
+ .isoformat())
+
+ stat['stripe_count'] = img.stripe_count()
+ stat['stripe_unit'] = img.stripe_unit()
+
+ data_pool_name = CephService.get_pool_name_from_id(
+ img.data_pool_id())
+ if data_pool_name == pool_name:
+ data_pool_name = None
+ stat['data_pool'] = data_pool_name
+
+ try:
+ parent_info = img.parent_info()
+ stat['parent'] = {
+ 'pool_name': parent_info[0],
+ 'image_name': parent_info[1],
+ 'snap_name': parent_info[2]
+ }
+ except rbd.ImageNotFound:
+ # no parent image
+ stat['parent'] = None
+
+ # snapshots
+ stat['snapshots'] = []
+ for snap in img.list_snaps():
+ snap['timestamp'] = "{}Z".format(
+ img.get_snap_timestamp(snap['id']).isoformat())
+ snap['is_protected'] = img.is_protected_snap(snap['name'])
+ snap['used_bytes'] = None
+ snap['children'] = []
+ img.set_snap(snap['name'])
+ for child_pool_name, child_image_name in img.list_children():
+ snap['children'].append({
+ 'pool_name': child_pool_name,
+ 'image_name': child_image_name
+ })
+ stat['snapshots'].append(snap)
+
+ # disk usage
+ img_flags = img.flags()
+ if 'fast-diff' in stat['features_name'] and \
+ not rbd.RBD_FLAG_FAST_DIFF_INVALID & img_flags:
+ snaps = [(s['id'], s['size'], s['name'])
+ for s in stat['snapshots']]
+ snaps.sort(key=lambda s: s[0])
+ snaps += [(snaps[-1][0]+1 if snaps else 0, stat['size'], None)]
+ total_prov_bytes, snaps_prov_bytes = cls._rbd_disk_usage(
+ img, snaps, True)
+ stat['total_disk_usage'] = total_prov_bytes
+ for snap, prov_bytes in snaps_prov_bytes.items():
+ if snap is None:
+ stat['disk_usage'] = prov_bytes
+ continue
+ for ss in stat['snapshots']:
+ if ss['name'] == snap:
+ ss['disk_usage'] = prov_bytes
+ break
+ else:
+ stat['total_disk_usage'] = None
+ stat['disk_usage'] = None
+
+ stat['configuration'] = RbdConfiguration(pool_ioctx=ioctx, image_name=image_name).list()
+
+ return stat
+
+ @classmethod
+ @ViewCache()
+ def _rbd_pool_list(cls, pool_name):
+ rbd_inst = rbd.RBD()
+ with mgr.rados.open_ioctx(pool_name) as ioctx:
+ names = rbd_inst.list(ioctx)
+ result = []
+ for name in names:
+ try:
+ stat = cls._rbd_image(ioctx, pool_name, name)
+ except rbd.ImageNotFound:
+ # may have been removed in the meanwhile
+ continue
+ result.append(stat)
+ return result
+
+ def _rbd_list(self, pool_name=None):
+ if pool_name:
+ pools = [pool_name]
+ else:
+ pools = [p['pool_name'] for p in CephService.get_pool_list('rbd')]
+
+ result = []
+ for pool in pools:
+ # pylint: disable=unbalanced-tuple-unpacking
+ status, value = self._rbd_pool_list(pool)
+ for i, image in enumerate(value):
+ value[i]['configuration'] = RbdConfiguration(pool, image['name']).list()
+ result.append({'status': status, 'value': value, 'pool_name': pool})
+ return result
+
+ @handle_rbd_error()
+ @handle_rados_error('pool')
+ def list(self, pool_name=None):
+ return self._rbd_list(pool_name)
+
+ @handle_rbd_error()
+ @handle_rados_error('pool')
+ def get(self, pool_name, image_name):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ try:
+ return self._rbd_image(ioctx, pool_name, image_name)
+ except rbd.ImageNotFound:
+ raise cherrypy.HTTPError(404)
+
+ @RbdTask('create',
+ {'pool_name': '{pool_name}', 'image_name': '{name}'}, 2.0)
+ def create(self, name, pool_name, size, obj_size=None, features=None,
+ stripe_unit=None, stripe_count=None, data_pool=None, configuration=None):
+
+ size = int(size)
+
+ def _create(ioctx):
+ rbd_inst = rbd.RBD()
+
+ # Set order
+ l_order = None
+ if obj_size and obj_size > 0:
+ l_order = int(round(math.log(float(obj_size), 2)))
+
+ # Set features
+ feature_bitmask = format_features(features)
+
+ rbd_inst.create(ioctx, name, size, order=l_order, old_format=False,
+ features=feature_bitmask, stripe_unit=stripe_unit,
+ stripe_count=stripe_count, data_pool=data_pool)
+ RbdConfiguration(pool_ioctx=ioctx, image_name=name).set_configuration(configuration)
+
+ _rbd_call(pool_name, _create)
+
+ @RbdTask('delete', ['{pool_name}', '{image_name}'], 2.0)
+ def delete(self, pool_name, image_name):
+ rbd_inst = rbd.RBD()
+ return _rbd_call(pool_name, rbd_inst.remove, image_name)
+
+ @RbdTask('edit', ['{pool_name}', '{image_name}', '{name}'], 4.0)
+ def set(self, pool_name, image_name, name=None, size=None, features=None, configuration=None):
+ def _edit(ioctx, image):
+ rbd_inst = rbd.RBD()
+ # check rename image
+ if name and name != image_name:
+ rbd_inst.rename(ioctx, image_name, name)
+
+ # check resize
+ if size and size != image.size():
+ image.resize(size)
+
+ # check enable/disable features
+ if features is not None:
+ curr_features = format_bitmask(image.features())
+ # check disabled features
+ _sort_features(curr_features, enable=False)
+ for feature in curr_features:
+ if feature not in features and feature in self.ALLOW_DISABLE_FEATURES:
+ if feature not in format_bitmask(image.features()):
+ continue
+ f_bitmask = format_features([feature])
+ image.update_features(f_bitmask, False)
+ # check enabled features
+ _sort_features(features)
+ for feature in features:
+ if feature not in curr_features and feature in self.ALLOW_ENABLE_FEATURES:
+ if feature in format_bitmask(image.features()):
+ continue
+ f_bitmask = format_features([feature])
+ image.update_features(f_bitmask, True)
+
+ RbdConfiguration(pool_ioctx=ioctx, image_name=image_name).set_configuration(
+ configuration)
+
+ return _rbd_image_call(pool_name, image_name, _edit)
+
+ @RbdTask('copy',
+ {'src_pool_name': '{pool_name}',
+ 'src_image_name': '{image_name}',
+ 'dest_pool_name': '{dest_pool_name}',
+ 'dest_image_name': '{dest_image_name}'}, 2.0)
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def copy(self, pool_name, image_name, dest_pool_name, dest_image_name,
+ snapshot_name=None, obj_size=None, features=None, stripe_unit=None,
+ stripe_count=None, data_pool=None, configuration=None):
+
+ def _src_copy(s_ioctx, s_img):
+ def _copy(d_ioctx):
+ # Set order
+ l_order = None
+ if obj_size and obj_size > 0:
+ l_order = int(round(math.log(float(obj_size), 2)))
+
+ # Set features
+ feature_bitmask = format_features(features)
+
+ if snapshot_name:
+ s_img.set_snap(snapshot_name)
+
+ s_img.copy(d_ioctx, dest_image_name, feature_bitmask, l_order,
+ stripe_unit, stripe_count, data_pool)
+ RbdConfiguration(pool_ioctx=d_ioctx, image_name=dest_image_name).set_configuration(
+ configuration)
+
+ return _rbd_call(dest_pool_name, _copy)
+
+ return _rbd_image_call(pool_name, image_name, _src_copy)
+
+ @RbdTask('flatten', ['{pool_name}', '{image_name}'], 2.0)
+ @RESTController.Resource('POST')
+ @UpdatePermission
+ @allow_empty_body
+ def flatten(self, pool_name, image_name):
+
+ def _flatten(ioctx, image):
+ image.flatten()
+
+ return _rbd_image_call(pool_name, image_name, _flatten)
+
+ @RESTController.Collection('GET')
+ def default_features(self):
+ rbd_default_features = mgr.get('config')['rbd_default_features']
+ return format_bitmask(int(rbd_default_features))
+
+ @RbdTask('trash/move', ['{pool_name}', '{image_name}'], 2.0)
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def move_trash(self, pool_name, image_name, delay=0):
+ """Move an image to the trash.
+ Images, even ones actively in-use by clones,
+ can be moved to the trash and deleted at a later time.
+ """
+ rbd_inst = rbd.RBD()
+ return _rbd_call(pool_name, rbd_inst.trash_move, image_name, delay)
+
+ @RESTController.Resource()
+ @ReadPermission
+ def configuration(self, pool_name, image_name):
+ return RbdConfiguration(pool_name, image_name).list()
+
+
+@ApiController('/block/image/{pool_name}/{image_name}/snap', Scope.RBD_IMAGE)
+class RbdSnapshot(RESTController):
+
+ RESOURCE_ID = "snapshot_name"
+
+ @RbdTask('snap/create',
+ ['{pool_name}', '{image_name}', '{snapshot_name}'], 2.0)
+ def create(self, pool_name, image_name, snapshot_name):
+ def _create_snapshot(ioctx, img, snapshot_name):
+ img.create_snap(snapshot_name)
+
+ return _rbd_image_call(pool_name, image_name, _create_snapshot,
+ snapshot_name)
+
+ @RbdTask('snap/delete',
+ ['{pool_name}', '{image_name}', '{snapshot_name}'], 2.0)
+ def delete(self, pool_name, image_name, snapshot_name):
+ def _remove_snapshot(ioctx, img, snapshot_name):
+ img.remove_snap(snapshot_name)
+
+ return _rbd_image_call(pool_name, image_name, _remove_snapshot,
+ snapshot_name)
+
+ @RbdTask('snap/edit',
+ ['{pool_name}', '{image_name}', '{snapshot_name}'], 4.0)
+ def set(self, pool_name, image_name, snapshot_name, new_snap_name=None,
+ is_protected=None):
+ def _edit(ioctx, img, snapshot_name):
+ if new_snap_name and new_snap_name != snapshot_name:
+ img.rename_snap(snapshot_name, new_snap_name)
+ snapshot_name = new_snap_name
+ if is_protected is not None and \
+ is_protected != img.is_protected_snap(snapshot_name):
+ if is_protected:
+ img.protect_snap(snapshot_name)
+ else:
+ img.unprotect_snap(snapshot_name)
+
+ return _rbd_image_call(pool_name, image_name, _edit, snapshot_name)
+
+ @RbdTask('snap/rollback',
+ ['{pool_name}', '{image_name}', '{snapshot_name}'], 5.0)
+ @RESTController.Resource('POST')
+ @UpdatePermission
+ @allow_empty_body
+ def rollback(self, pool_name, image_name, snapshot_name):
+ def _rollback(ioctx, img, snapshot_name):
+ img.rollback_to_snap(snapshot_name)
+ return _rbd_image_call(pool_name, image_name, _rollback, snapshot_name)
+
+ @RbdTask('clone',
+ {'parent_pool_name': '{pool_name}',
+ 'parent_image_name': '{image_name}',
+ 'parent_snap_name': '{snapshot_name}',
+ 'child_pool_name': '{child_pool_name}',
+ 'child_image_name': '{child_image_name}'}, 2.0)
+ @RESTController.Resource('POST')
+ @allow_empty_body
+ def clone(self, pool_name, image_name, snapshot_name, child_pool_name,
+ child_image_name, obj_size=None, features=None, stripe_unit=None, stripe_count=None,
+ data_pool=None, configuration=None):
+ """
+ Clones a snapshot to an image
+ """
+
+ def _parent_clone(p_ioctx):
+ def _clone(ioctx):
+ # Set order
+ l_order = None
+ if obj_size and obj_size > 0:
+ l_order = int(round(math.log(float(obj_size), 2)))
+
+ # Set features
+ feature_bitmask = format_features(features)
+
+ rbd_inst = rbd.RBD()
+ rbd_inst.clone(p_ioctx, image_name, snapshot_name, ioctx,
+ child_image_name, feature_bitmask, l_order,
+ stripe_unit, stripe_count, data_pool)
+
+ RbdConfiguration(pool_ioctx=ioctx, image_name=child_image_name).set_configuration(
+ configuration)
+
+ return _rbd_call(child_pool_name, _clone)
+
+ _rbd_call(pool_name, _parent_clone)
+
+
+@ApiController('/block/image/trash', Scope.RBD_IMAGE)
+class RbdTrash(RESTController):
+ RESOURCE_ID = "pool_name/image_id"
+ rbd_inst = rbd.RBD()
+
+ @ViewCache()
+ def _trash_pool_list(self, pool_name):
+ with mgr.rados.open_ioctx(pool_name) as ioctx:
+ images = self.rbd_inst.trash_list(ioctx)
+ result = []
+ for trash in images:
+ trash['pool_name'] = pool_name
+ trash['deletion_time'] = "{}Z".format(trash['deletion_time'].isoformat())
+ trash['deferment_end_time'] = "{}Z".format(trash['deferment_end_time'].isoformat())
+ result.append(trash)
+ return result
+
+ def _trash_list(self, pool_name=None):
+ if pool_name:
+ pools = [pool_name]
+ else:
+ pools = [p['pool_name'] for p in CephService.get_pool_list('rbd')]
+
+ result = []
+ for pool in pools:
+ # pylint: disable=unbalanced-tuple-unpacking
+ status, value = self._trash_pool_list(pool)
+ result.append({'status': status, 'value': value, 'pool_name': pool})
+ return result
+
+ @handle_rbd_error()
+ @handle_rados_error('pool')
+ def list(self, pool_name=None):
+ """List all entries from trash."""
+ return self._trash_list(pool_name)
+
+ @handle_rbd_error()
+ @handle_rados_error('pool')
+ @RbdTask('trash/purge', ['{pool_name}'], 2.0)
+ @RESTController.Collection('POST', query_params=['pool_name'])
+ @DeletePermission
+ @allow_empty_body
+ def purge(self, pool_name=None):
+ """Remove all expired images from trash."""
+ now = "{}Z".format(datetime.utcnow().isoformat())
+ pools = self._trash_list(pool_name)
+
+ for pool in pools:
+ for image in pool['value']:
+ if image['deferment_end_time'] < now:
+ logger.info('Removing trash image %s (pool=%s, name=%s)',
+ image['id'], pool['pool_name'], image['name'])
+ _rbd_call(pool['pool_name'], self.rbd_inst.trash_remove, image['id'], 0)
+
+ @RbdTask('trash/restore', ['{pool_name}', '{image_id}', '{new_image_name}'], 2.0)
+ @RESTController.Resource('POST')
+ @CreatePermission
+ @allow_empty_body
+ def restore(self, pool_name, image_id, new_image_name):
+ """Restore an image from trash."""
+ return _rbd_call(pool_name, self.rbd_inst.trash_restore, image_id, new_image_name)
+
+ @RbdTask('trash/remove', ['{pool_name}', '{image_id}', '{image_name}'], 2.0)
+ def delete(self, pool_name, image_id, image_name, force=False):
+ """Delete an image from trash.
+ If image deferment time has not expired you can not removed it unless use force.
+ But an actively in-use by clones or has snapshots can not be removed.
+ """
+ return _rbd_call(pool_name, self.rbd_inst.trash_remove, image_id, int(str_to_bool(force)))
diff --git a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py
new file mode 100644
index 00000000..0f6574a4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py
@@ -0,0 +1,460 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+import re
+
+from functools import partial
+
+import cherrypy
+
+import rbd
+
+from . import ApiController, Endpoint, Task, BaseController, ReadPermission, \
+ RESTController
+from .. import logger, mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..tools import ViewCache
+from ..services.exception import handle_rados_error, handle_rbd_error, \
+ serialize_dashboard_exception
+
+
+# pylint: disable=not-callable
+def handle_rbd_mirror_error():
+ def composed_decorator(func):
+ func = handle_rados_error('rbd-mirroring')(func)
+ return handle_rbd_error()(func)
+ return composed_decorator
+
+
+# pylint: disable=not-callable
+def RbdMirroringTask(name, metadata, wait_for):
+ def composed_decorator(func):
+ func = handle_rbd_mirror_error()(func)
+ return Task("rbd/mirroring/{}".format(name), metadata, wait_for,
+ partial(serialize_dashboard_exception, include_http_status=True))(func)
+ return composed_decorator
+
+
+def _rbd_call(pool_name, func, *args, **kwargs):
+ with mgr.rados.open_ioctx(pool_name) as ioctx:
+ func(ioctx, *args, **kwargs)
+
+
+@ViewCache()
+def get_daemons_and_pools(): # pylint: disable=R0915
+ def get_daemons():
+ daemons = []
+ for hostname, server in CephService.get_service_map('rbd-mirror').items():
+ for service in server['services']:
+ id = service['id'] # pylint: disable=W0622
+ metadata = service['metadata']
+ status = service['status'] or {}
+
+ try:
+ status = json.loads(status['json'])
+ except (ValueError, KeyError) as _:
+ status = {}
+
+ instance_id = metadata['instance_id']
+ if id == instance_id:
+ # new version that supports per-cluster leader elections
+ id = metadata['id']
+
+ # extract per-daemon service data and health
+ daemon = {
+ 'id': id,
+ 'instance_id': instance_id,
+ 'version': metadata['ceph_version'],
+ 'server_hostname': hostname,
+ 'service': service,
+ 'server': server,
+ 'metadata': metadata,
+ 'status': status
+ }
+ daemon = dict(daemon, **get_daemon_health(daemon))
+ daemons.append(daemon)
+
+ return sorted(daemons, key=lambda k: k['instance_id'])
+
+ def get_daemon_health(daemon):
+ health = {
+ 'health_color': 'info',
+ 'health': 'Unknown'
+ }
+ for _, pool_data in daemon['status'].items():
+ if (health['health'] != 'error'
+ and [k for k, v in pool_data.get('callouts', {}).items()
+ if v['level'] == 'error']):
+ health = {
+ 'health_color': 'error',
+ 'health': 'Error'
+ }
+ elif (health['health'] != 'error'
+ and [k for k, v in pool_data.get('callouts', {}).items()
+ if v['level'] == 'warning']):
+ health = {
+ 'health_color': 'warning',
+ 'health': 'Warning'
+ }
+ elif health['health_color'] == 'info':
+ health = {
+ 'health_color': 'success',
+ 'health': 'OK'
+ }
+ return health
+
+ def get_pools(daemons): # pylint: disable=R0912, R0915
+ pool_names = [pool['pool_name'] for pool in CephService.get_pool_list('rbd')
+ if pool.get('type', 1) == 1]
+ pool_stats = {}
+ rbdctx = rbd.RBD()
+ for pool_name in pool_names:
+ logger.debug("Constructing IOCtx %s", pool_name)
+ try:
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ except TypeError:
+ logger.exception("Failed to open pool %s", pool_name)
+ continue
+
+ try:
+ mirror_mode = rbdctx.mirror_mode_get(ioctx)
+ peer_uuids = [x['uuid'] for x in rbdctx.mirror_peer_list(ioctx)]
+ except: # noqa pylint: disable=W0702
+ logger.exception("Failed to query mirror settings %s", pool_name)
+ mirror_mode = None
+ peer_uuids = []
+
+ stats = {}
+ if mirror_mode == rbd.RBD_MIRROR_MODE_DISABLED:
+ mirror_mode = "disabled"
+ stats['health_color'] = "info"
+ stats['health'] = "Disabled"
+ elif mirror_mode == rbd.RBD_MIRROR_MODE_IMAGE:
+ mirror_mode = "image"
+ elif mirror_mode == rbd.RBD_MIRROR_MODE_POOL:
+ mirror_mode = "pool"
+ else:
+ mirror_mode = "unknown"
+ stats['health_color'] = "warning"
+ stats['health'] = "Warning"
+
+ pool_stats[pool_name] = dict(stats, **{
+ 'mirror_mode': mirror_mode,
+ 'peer_uuids': peer_uuids
+ })
+
+ for daemon in daemons:
+ for _, pool_data in daemon['status'].items():
+ stats = pool_stats.get(pool_data['name'], None)
+ if stats is None:
+ continue
+
+ if pool_data.get('leader', False):
+ # leader instance stores image counts
+ stats['leader_id'] = daemon['metadata']['instance_id']
+ stats['image_local_count'] = pool_data.get('image_local_count', 0)
+ stats['image_remote_count'] = pool_data.get('image_remote_count', 0)
+
+ if (stats.get('health_color', '') != 'error'
+ and pool_data.get('image_error_count', 0) > 0):
+ stats['health_color'] = 'error'
+ stats['health'] = 'Error'
+ elif (stats.get('health_color', '') != 'error'
+ and pool_data.get('image_warning_count', 0) > 0):
+ stats['health_color'] = 'warning'
+ stats['health'] = 'Warning'
+ elif stats.get('health', None) is None:
+ stats['health_color'] = 'success'
+ stats['health'] = 'OK'
+
+ for _, stats in pool_stats.items():
+ if stats['mirror_mode'] == 'disabled':
+ continue
+ if stats.get('health', None) is None:
+ # daemon doesn't know about pool
+ stats['health_color'] = 'error'
+ stats['health'] = 'Error'
+ elif stats.get('leader_id', None) is None:
+ # no daemons are managing the pool as leader instance
+ stats['health_color'] = 'warning'
+ stats['health'] = 'Warning'
+ return pool_stats
+
+ daemons = get_daemons()
+ return {
+ 'daemons': daemons,
+ 'pools': get_pools(daemons)
+ }
+
+
+@ViewCache()
+def _get_pool_datum(pool_name):
+ data = {}
+ logger.debug("Constructing IOCtx %s", pool_name)
+ try:
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ except TypeError:
+ logger.exception("Failed to open pool %s", pool_name)
+ return None
+
+ mirror_state = {
+ 'down': {
+ 'health': 'issue',
+ 'state_color': 'warning',
+ 'state': 'Unknown',
+ 'description': None
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_UNKNOWN: {
+ 'health': 'issue',
+ 'state_color': 'warning',
+ 'state': 'Unknown'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_ERROR: {
+ 'health': 'issue',
+ 'state_color': 'error',
+ 'state': 'Error'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_SYNCING: {
+ 'health': 'syncing'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY: {
+ 'health': 'ok',
+ 'state_color': 'success',
+ 'state': 'Starting'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_REPLAYING: {
+ 'health': 'ok',
+ 'state_color': 'success',
+ 'state': 'Replaying'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY: {
+ 'health': 'ok',
+ 'state_color': 'success',
+ 'state': 'Stopping'
+ },
+ rbd.MIRROR_IMAGE_STATUS_STATE_STOPPED: {
+ 'health': 'ok',
+ 'state_color': 'info',
+ 'state': 'Primary'
+ }
+ }
+
+ rbdctx = rbd.RBD()
+ try:
+ mirror_image_status = rbdctx.mirror_image_status_list(ioctx)
+ data['mirror_images'] = sorted([
+ dict({
+ 'name': image['name'],
+ 'description': image['description']
+ }, **mirror_state['down' if not image['up'] else image['state']])
+ for image in mirror_image_status
+ ], key=lambda k: k['name'])
+ except rbd.ImageNotFound:
+ pass
+ except: # noqa pylint: disable=W0702
+ logger.exception("Failed to list mirror image status %s", pool_name)
+ raise
+
+ return data
+
+
+@ViewCache()
+def _get_content_data(): # pylint: disable=R0914
+ pool_names = [pool['pool_name'] for pool in CephService.get_pool_list('rbd')
+ if pool.get('type', 1) == 1]
+ _, data = get_daemons_and_pools()
+ daemons = data.get('daemons', [])
+ pool_stats = data.get('pools', {})
+
+ pools = []
+ image_error = []
+ image_syncing = []
+ image_ready = []
+ for pool_name in pool_names:
+ _, pool = _get_pool_datum(pool_name)
+ if not pool:
+ pool = {}
+
+ stats = pool_stats.get(pool_name, {})
+ if stats.get('mirror_mode', None) is None:
+ continue
+
+ mirror_images = pool.get('mirror_images', [])
+ for mirror_image in mirror_images:
+ image = {
+ 'pool_name': pool_name,
+ 'name': mirror_image['name']
+ }
+
+ if mirror_image['health'] == 'ok':
+ image.update({
+ 'state_color': mirror_image['state_color'],
+ 'state': mirror_image['state'],
+ 'description': mirror_image['description']
+ })
+ image_ready.append(image)
+ elif mirror_image['health'] == 'syncing':
+ p = re.compile("bootstrapping, IMAGE_COPY/COPY_OBJECT (.*)%")
+ image.update({
+ 'progress': (p.findall(mirror_image['description']) or [0])[0]
+ })
+ image_syncing.append(image)
+ else:
+ image.update({
+ 'state_color': mirror_image['state_color'],
+ 'state': mirror_image['state'],
+ 'description': mirror_image['description']
+ })
+ image_error.append(image)
+
+ pools.append(dict({
+ 'name': pool_name
+ }, **stats))
+
+ return {
+ 'daemons': daemons,
+ 'pools': pools,
+ 'image_error': image_error,
+ 'image_syncing': image_syncing,
+ 'image_ready': image_ready
+ }
+
+
+def _reset_view_cache():
+ get_daemons_and_pools.reset()
+ _get_pool_datum.reset()
+ _get_content_data.reset()
+
+
+@ApiController('/block/mirroring/summary', Scope.RBD_MIRRORING)
+class RbdMirroringSummary(BaseController):
+
+ @Endpoint()
+ @handle_rbd_mirror_error()
+ @ReadPermission
+ def __call__(self):
+ status, content_data = _get_content_data()
+ return {'status': status, 'content_data': content_data}
+
+
+@ApiController('/block/mirroring/pool', Scope.RBD_MIRRORING)
+class RbdMirroringPoolMode(RESTController):
+
+ RESOURCE_ID = "pool_name"
+ MIRROR_MODES = {
+ rbd.RBD_MIRROR_MODE_DISABLED: 'disabled',
+ rbd.RBD_MIRROR_MODE_IMAGE: 'image',
+ rbd.RBD_MIRROR_MODE_POOL: 'pool'
+ }
+
+ @handle_rbd_mirror_error()
+ def get(self, pool_name):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ mode = rbd.RBD().mirror_mode_get(ioctx)
+ data = {
+ 'mirror_mode': self.MIRROR_MODES.get(mode, 'unknown')
+ }
+ return data
+
+ @RbdMirroringTask('pool/edit', {'pool_name': '{pool_name}'}, 5.0)
+ def set(self, pool_name, mirror_mode=None):
+ def _edit(ioctx, mirror_mode=None):
+ if mirror_mode:
+ mode_enum = {x[1]: x[0] for x in
+ self.MIRROR_MODES.items()}.get(mirror_mode, None)
+ if mode_enum is None:
+ raise rbd.Error('invalid mirror mode "{}"'.format(mirror_mode))
+
+ current_mode_enum = rbd.RBD().mirror_mode_get(ioctx)
+ if mode_enum != current_mode_enum:
+ rbd.RBD().mirror_mode_set(ioctx, mode_enum)
+ _reset_view_cache()
+
+ return _rbd_call(pool_name, _edit, mirror_mode)
+
+
+@ApiController('/block/mirroring/pool/{pool_name}/peer', Scope.RBD_MIRRORING)
+class RbdMirroringPoolPeer(RESTController):
+
+ RESOURCE_ID = "peer_uuid"
+
+ @handle_rbd_mirror_error()
+ def list(self, pool_name):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ peer_list = rbd.RBD().mirror_peer_list(ioctx)
+ return [x['uuid'] for x in peer_list]
+
+ @handle_rbd_mirror_error()
+ def create(self, pool_name, cluster_name, client_id, mon_host=None,
+ key=None):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ mode = rbd.RBD().mirror_mode_get(ioctx)
+ if mode == rbd.RBD_MIRROR_MODE_DISABLED:
+ raise rbd.Error('mirroring must be enabled')
+
+ uuid = rbd.RBD().mirror_peer_add(ioctx, cluster_name,
+ 'client.{}'.format(client_id))
+
+ attributes = {}
+ if mon_host is not None:
+ attributes[rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST] = mon_host
+ if key is not None:
+ attributes[rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY] = key
+ if attributes:
+ rbd.RBD().mirror_peer_set_attributes(ioctx, uuid, attributes)
+
+ _reset_view_cache()
+ return {'uuid': uuid}
+
+ @handle_rbd_mirror_error()
+ def get(self, pool_name, peer_uuid):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ peer_list = rbd.RBD().mirror_peer_list(ioctx)
+ peer = next((x for x in peer_list if x['uuid'] == peer_uuid), None)
+ if not peer:
+ raise cherrypy.HTTPError(404)
+
+ # convert full client name to just the client id
+ peer['client_id'] = peer['client_name'].split('.', 1)[-1]
+ del peer['client_name']
+
+ try:
+ attributes = rbd.RBD().mirror_peer_get_attributes(ioctx, peer_uuid)
+ except rbd.ImageNotFound:
+ attributes = {}
+
+ peer['mon_host'] = attributes.get(rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST, '')
+ peer['key'] = attributes.get(rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY, '')
+ return peer
+
+ @handle_rbd_mirror_error()
+ def delete(self, pool_name, peer_uuid):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ rbd.RBD().mirror_peer_remove(ioctx, peer_uuid)
+ _reset_view_cache()
+
+ @handle_rbd_mirror_error()
+ def set(self, pool_name, peer_uuid, cluster_name=None, client_id=None,
+ mon_host=None, key=None):
+ ioctx = mgr.rados.open_ioctx(pool_name)
+ if cluster_name:
+ rbd.RBD().mirror_peer_set_cluster(ioctx, peer_uuid, cluster_name)
+ if client_id:
+ rbd.RBD().mirror_peer_set_client(ioctx, peer_uuid,
+ 'client.{}'.format(client_id))
+
+ if mon_host is not None or key is not None:
+ try:
+ attributes = rbd.RBD().mirror_peer_get_attributes(ioctx, peer_uuid)
+ except rbd.ImageNotFound:
+ attributes = {}
+
+ if mon_host is not None:
+ attributes[rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST] = mon_host
+ if key is not None:
+ attributes[rbd.RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY] = key
+ rbd.RBD().mirror_peer_set_attributes(ioctx, peer_uuid, attributes)
+
+ _reset_view_cache()
diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py
new file mode 100644
index 00000000..085155aa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/rgw.py
@@ -0,0 +1,385 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+import cherrypy
+
+from . import ApiController, BaseController, RESTController, Endpoint, \
+ ReadPermission, allow_empty_body
+from .. import logger
+from ..exceptions import DashboardException
+from ..rest_client import RequestException
+from ..security import Scope, Permission
+from ..services.auth import AuthManager, JwtManager
+from ..services.ceph_service import CephService
+from ..services.rgw_client import RgwClient
+
+
+@ApiController('/rgw', Scope.RGW)
+class Rgw(BaseController):
+
+ @Endpoint()
+ @ReadPermission
+ def status(self):
+ status = {'available': False, 'message': None}
+ try:
+ if not CephService.get_service_list('rgw'):
+ raise LookupError('No RGW service is running.')
+ instance = RgwClient.admin_instance()
+ # Check if the service is online.
+ try:
+ is_online = instance.is_service_online()
+ except RequestException as e:
+ # Drop this instance because the RGW client seems not to
+ # exist anymore (maybe removed via orchestrator). Removing
+ # the instance from the cache will result in the correct
+ # error message next time when the backend tries to
+ # establish a new connection (-> 'No RGW found' instead
+ # of 'RGW REST API failed request ...').
+ # Note, this only applies to auto-detected RGW clients.
+ RgwClient.drop_instance(instance.userid)
+ raise e
+ if not is_online:
+ msg = 'Failed to connect to the Object Gateway\'s Admin Ops API.'
+ raise RequestException(msg)
+ # Ensure the API user ID is known by the RGW.
+ if not instance.user_exists():
+ msg = 'The user "{}" is unknown to the Object Gateway.'.format(
+ instance.userid)
+ raise RequestException(msg)
+ # Ensure the system flag is set for the API user ID.
+ if not instance.is_system_user():
+ msg = 'The system flag is not set for user "{}".'.format(
+ instance.userid)
+ raise RequestException(msg)
+ status['available'] = True
+ except (RequestException, LookupError) as ex:
+ status['message'] = str(ex)
+ return status
+
+
+@ApiController('/rgw/daemon', Scope.RGW)
+class RgwDaemon(RESTController):
+
+ def list(self):
+ daemons = []
+ for hostname, server in CephService.get_service_map('rgw').items():
+ for service in server['services']:
+ metadata = service['metadata']
+
+ # extract per-daemon service data and health
+ daemon = {
+ 'id': service['id'],
+ 'version': metadata['ceph_version'],
+ 'server_hostname': hostname
+ }
+
+ daemons.append(daemon)
+
+ return sorted(daemons, key=lambda k: k['id'])
+
+ def get(self, svc_id):
+ daemon = {
+ 'rgw_metadata': [],
+ 'rgw_id': svc_id,
+ 'rgw_status': []
+ }
+ service = CephService.get_service('rgw', svc_id)
+ if not service:
+ raise cherrypy.NotFound('Service rgw {} is not available'.format(svc_id))
+
+ metadata = service['metadata']
+ status = service['status']
+ if 'json' in status:
+ try:
+ status = json.loads(status['json'])
+ except ValueError:
+ logger.warning('%s had invalid status json', service['id'])
+ status = {}
+ else:
+ logger.warning('%s has no key "json" in status', service['id'])
+
+ daemon['rgw_metadata'] = metadata
+ daemon['rgw_status'] = status
+ return daemon
+
+
+class RgwRESTController(RESTController):
+
+ def proxy(self, method, path, params=None, json_response=True):
+ try:
+ instance = RgwClient.admin_instance()
+ result = instance.proxy(method, path, params, None)
+ if json_response and result != '':
+ result = json.loads(result.decode('utf-8'))
+ return result
+ except (DashboardException, RequestException) as e:
+ raise DashboardException(e, http_status_code=500, component='rgw')
+
+
+@ApiController('/rgw/bucket', Scope.RGW)
+class RgwBucket(RgwRESTController):
+
+ def _append_bid(self, bucket):
+ """
+ Append the bucket identifier that looks like [<tenant>/]<bucket>.
+ See http://docs.ceph.com/docs/nautilus/radosgw/multitenancy/ for
+ more information.
+ :param bucket: The bucket parameters.
+ :type bucket: dict
+ :return: The modified bucket parameters including the 'bid' parameter.
+ :rtype: dict
+ """
+ if isinstance(bucket, dict):
+ bucket['bid'] = '{}/{}'.format(bucket['tenant'], bucket['bucket']) \
+ if bucket['tenant'] else bucket['bucket']
+ return bucket
+
+ @staticmethod
+ def strip_tenant_from_bucket_name(bucket_name, uid):
+ # type (str, str) => str
+ """
+ When linking a bucket to a new user belonging to same tenant
+ as the previous owner, tenant must be removed from the bucket name.
+ >>> RgwBucket.strip_tenant_from_bucket_name('tenant/bucket-name', 'tenant$user1')
+ 'bucket-name'
+ >>> RgwBucket.strip_tenant_from_bucket_name('tenant/bucket-name', 'tenant2$user2')
+ 'tenant/bucket-name'
+ >>> RgwBucket.strip_tenant_from_bucket_name('bucket-name', 'user1')
+ 'bucket-name'
+ """
+ bucket_tenant = bucket_name[:bucket_name.find('/')] if bucket_name.find('/') >= 0 else None
+ uid_tenant = uid[:uid.find('$')] if uid.find('$') >= 0 else None
+ if bucket_tenant and uid_tenant and bucket_tenant == uid_tenant:
+ return bucket_name[bucket_name.find('/') + 1:]
+
+ return bucket_name
+
+ def list(self, stats=False):
+ query_params = '?stats' if stats else ''
+ result = self.proxy('GET', 'bucket{}'.format(query_params))
+
+ if stats:
+ result = [self._append_bid(bucket) for bucket in result]
+
+ return result
+
+ def get(self, bucket):
+ result = self.proxy('GET', 'bucket', {'bucket': bucket})
+ return self._append_bid(result)
+
+ @allow_empty_body
+ def create(self, bucket, uid):
+ try:
+ rgw_client = RgwClient.instance(uid)
+ return rgw_client.create_bucket(bucket)
+ except RequestException as e:
+ raise DashboardException(e, http_status_code=500, component='rgw')
+
+ @allow_empty_body
+ def set(self, bucket, bucket_id, uid):
+ result = self.proxy('PUT', 'bucket', {
+ 'bucket': RgwBucket.strip_tenant_from_bucket_name(bucket, uid),
+ 'bucket-id': bucket_id,
+ 'uid': uid
+ }, json_response=False)
+ return self._append_bid(result)
+
+ def delete(self, bucket, purge_objects='true'):
+ return self.proxy('DELETE', 'bucket', {
+ 'bucket': bucket,
+ 'purge-objects': purge_objects
+ }, json_response=False)
+
+
+@ApiController('/rgw/user', Scope.RGW)
+class RgwUser(RgwRESTController):
+
+ def _append_uid(self, user):
+ """
+ Append the user identifier that looks like [<tenant>$]<user>.
+ See http://docs.ceph.com/docs/jewel/radosgw/multitenancy/ for
+ more information.
+ :param user: The user parameters.
+ :type user: dict
+ :return: The modified user parameters including the 'uid' parameter.
+ :rtype: dict
+ """
+ if isinstance(user, dict):
+ user['uid'] = '{}${}'.format(user['tenant'], user['user_id']) \
+ if user['tenant'] else user['user_id']
+ return user
+
+ @staticmethod
+ def _keys_allowed():
+ permissions = AuthManager.get_user(JwtManager.get_username()).permissions_dict()
+ edit_permissions = [Permission.CREATE, Permission.UPDATE, Permission.DELETE]
+ return Scope.RGW in permissions and Permission.READ in permissions[Scope.RGW] \
+ and len(set(edit_permissions).intersection(set(permissions[Scope.RGW]))) > 0
+
+ def list(self):
+ users = []
+ marker = None
+ while True:
+ params = {}
+ if marker:
+ params['marker'] = marker
+ result = self.proxy('GET', 'user?list', params)
+ users.extend(result['keys'])
+ if not result['truncated']:
+ break
+ # Make sure there is a marker.
+ assert result['marker']
+ # Make sure the marker has changed.
+ assert marker != result['marker']
+ marker = result['marker']
+ return users
+
+ def get(self, uid):
+ result = self.proxy('GET', 'user', {'uid': uid})
+ if not self._keys_allowed():
+ del result['keys']
+ del result['swift_keys']
+ return self._append_uid(result)
+
+ @Endpoint()
+ @ReadPermission
+ def get_emails(self):
+ emails = []
+ for uid in json.loads(self.list()):
+ user = json.loads(self.get(uid))
+ if user["email"]:
+ emails.append(user["email"])
+ return emails
+
+ @allow_empty_body
+ def create(self, uid, display_name, email=None, max_buckets=None,
+ suspended=None, generate_key=None, access_key=None,
+ secret_key=None):
+ params = {'uid': uid}
+ if display_name is not None:
+ params['display-name'] = display_name
+ if email is not None:
+ params['email'] = email
+ if max_buckets is not None:
+ params['max-buckets'] = max_buckets
+ if suspended is not None:
+ params['suspended'] = suspended
+ if generate_key is not None:
+ params['generate-key'] = generate_key
+ if access_key is not None:
+ params['access-key'] = access_key
+ if secret_key is not None:
+ params['secret-key'] = secret_key
+ result = self.proxy('PUT', 'user', params)
+ return self._append_uid(result)
+
+ @allow_empty_body
+ def set(self, uid, display_name=None, email=None, max_buckets=None,
+ suspended=None):
+ params = {'uid': uid}
+ if display_name is not None:
+ params['display-name'] = display_name
+ if email is not None:
+ params['email'] = email
+ if max_buckets is not None:
+ params['max-buckets'] = max_buckets
+ if suspended is not None:
+ params['suspended'] = suspended
+ result = self.proxy('POST', 'user', params)
+ return self._append_uid(result)
+
+ def delete(self, uid):
+ try:
+ instance = RgwClient.admin_instance()
+ # Ensure the user is not configured to access the RGW Object Gateway.
+ if instance.userid == uid:
+ raise DashboardException(msg='Unable to delete "{}" - this user '
+ 'account is required for managing the '
+ 'Object Gateway'.format(uid))
+ # Finally redirect request to the RGW proxy.
+ return self.proxy('DELETE', 'user', {'uid': uid}, json_response=False)
+ except (DashboardException, RequestException) as e:
+ raise DashboardException(e, component='rgw')
+
+ # pylint: disable=redefined-builtin
+ @RESTController.Resource(method='POST', path='/capability', status=201)
+ @allow_empty_body
+ def create_cap(self, uid, type, perm):
+ return self.proxy('PUT', 'user?caps', {
+ 'uid': uid,
+ 'user-caps': '{}={}'.format(type, perm)
+ })
+
+ # pylint: disable=redefined-builtin
+ @RESTController.Resource(method='DELETE', path='/capability', status=204)
+ def delete_cap(self, uid, type, perm):
+ return self.proxy('DELETE', 'user?caps', {
+ 'uid': uid,
+ 'user-caps': '{}={}'.format(type, perm)
+ })
+
+ @RESTController.Resource(method='POST', path='/key', status=201)
+ @allow_empty_body
+ def create_key(self, uid, key_type='s3', subuser=None, generate_key='true',
+ access_key=None, secret_key=None):
+ params = {'uid': uid, 'key-type': key_type, 'generate-key': generate_key}
+ if subuser is not None:
+ params['subuser'] = subuser
+ if access_key is not None:
+ params['access-key'] = access_key
+ if secret_key is not None:
+ params['secret-key'] = secret_key
+ return self.proxy('PUT', 'user?key', params)
+
+ @RESTController.Resource(method='DELETE', path='/key', status=204)
+ def delete_key(self, uid, key_type='s3', subuser=None, access_key=None):
+ params = {'uid': uid, 'key-type': key_type}
+ if subuser is not None:
+ params['subuser'] = subuser
+ if access_key is not None:
+ params['access-key'] = access_key
+ return self.proxy('DELETE', 'user?key', params, json_response=False)
+
+ @RESTController.Resource(method='GET', path='/quota')
+ def get_quota(self, uid):
+ return self.proxy('GET', 'user?quota', {'uid': uid})
+
+ @RESTController.Resource(method='PUT', path='/quota')
+ @allow_empty_body
+ def set_quota(self, uid, quota_type, enabled, max_size_kb, max_objects):
+ return self.proxy('PUT', 'user?quota', {
+ 'uid': uid,
+ 'quota-type': quota_type,
+ 'enabled': enabled,
+ 'max-size-kb': max_size_kb,
+ 'max-objects': max_objects
+ }, json_response=False)
+
+ @RESTController.Resource(method='POST', path='/subuser', status=201)
+ @allow_empty_body
+ def create_subuser(self, uid, subuser, access, key_type='s3',
+ generate_secret='true', access_key=None,
+ secret_key=None):
+ return self.proxy('PUT', 'user', {
+ 'uid': uid,
+ 'subuser': subuser,
+ 'key-type': key_type,
+ 'access': access,
+ 'generate-secret': generate_secret,
+ 'access-key': access_key,
+ 'secret-key': secret_key
+ })
+
+ @RESTController.Resource(method='DELETE', path='/subuser/{subuser}', status=204)
+ def delete_subuser(self, uid, subuser, purge_keys='true'):
+ """
+ :param purge_keys: Set to False to do not purge the keys.
+ Note, this only works for s3 subusers.
+ """
+ return self.proxy('DELETE', 'user', {
+ 'uid': uid,
+ 'subuser': subuser,
+ 'purge-keys': purge_keys
+ }, json_response=False)
diff --git a/src/pybind/mgr/dashboard/controllers/role.py b/src/pybind/mgr/dashboard/controllers/role.py
new file mode 100644
index 00000000..f87eff7b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/role.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cherrypy
+
+from . import ApiController, RESTController, UiApiController
+from .. import mgr
+from ..exceptions import RoleDoesNotExist, DashboardException,\
+ RoleIsAssociatedWithUser, RoleAlreadyExists
+from ..security import Scope as SecurityScope, Permission
+from ..services.access_control import SYSTEM_ROLES
+
+
+@ApiController('/role', SecurityScope.USER)
+class Role(RESTController):
+ @staticmethod
+ def _role_to_dict(role):
+ role_dict = role.to_dict()
+ role_dict['system'] = role_dict['name'] in SYSTEM_ROLES
+ return role_dict
+
+ @staticmethod
+ def _validate_permissions(scopes_permissions):
+ if scopes_permissions:
+ for scope, permissions in scopes_permissions.items():
+ if scope not in SecurityScope.all_scopes():
+ raise DashboardException(msg='Invalid scope',
+ code='invalid_scope',
+ component='role')
+ if any(permission not in Permission.all_permissions()
+ for permission in permissions):
+ raise DashboardException(msg='Invalid permission',
+ code='invalid_permission',
+ component='role')
+
+ @staticmethod
+ def _set_permissions(role, scopes_permissions):
+ role.reset_scope_permissions()
+ if scopes_permissions:
+ for scope, permissions in scopes_permissions.items():
+ if permissions:
+ role.set_scope_permissions(scope, permissions)
+
+ def list(self):
+ roles = dict(mgr.ACCESS_CTRL_DB.roles)
+ roles.update(SYSTEM_ROLES)
+ roles = sorted(roles.values(), key=lambda role: role.name)
+ return [Role._role_to_dict(r) for r in roles]
+
+ def get(self, name):
+ role = SYSTEM_ROLES.get(name)
+ if not role:
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(name)
+ except RoleDoesNotExist:
+ raise cherrypy.HTTPError(404)
+ return Role._role_to_dict(role)
+
+ def create(self, name=None, description=None, scopes_permissions=None):
+ if not name:
+ raise DashboardException(msg='Name is required',
+ code='name_required',
+ component='role')
+ Role._validate_permissions(scopes_permissions)
+ try:
+ role = mgr.ACCESS_CTRL_DB.create_role(name, description)
+ except RoleAlreadyExists:
+ raise DashboardException(msg='Role already exists',
+ code='role_already_exists',
+ component='role')
+ Role._set_permissions(role, scopes_permissions)
+ mgr.ACCESS_CTRL_DB.save()
+ return Role._role_to_dict(role)
+
+ def set(self, name, description=None, scopes_permissions=None):
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(name)
+ except RoleDoesNotExist:
+ if name in SYSTEM_ROLES:
+ raise DashboardException(msg='Cannot update system role',
+ code='cannot_update_system_role',
+ component='role')
+ raise cherrypy.HTTPError(404)
+ Role._validate_permissions(scopes_permissions)
+ Role._set_permissions(role, scopes_permissions)
+ role.description = description
+ mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
+ mgr.ACCESS_CTRL_DB.save()
+ return Role._role_to_dict(role)
+
+ def delete(self, name):
+ try:
+ mgr.ACCESS_CTRL_DB.delete_role(name)
+ except RoleDoesNotExist:
+ if name in SYSTEM_ROLES:
+ raise DashboardException(msg='Cannot delete system role',
+ code='cannot_delete_system_role',
+ component='role')
+ raise cherrypy.HTTPError(404)
+ except RoleIsAssociatedWithUser:
+ raise DashboardException(msg='Role is associated with user',
+ code='role_is_associated_with_user',
+ component='role')
+ mgr.ACCESS_CTRL_DB.save()
+
+
+@UiApiController('/scope', SecurityScope.USER)
+class Scope(RESTController):
+ def list(self):
+ return SecurityScope.all_scopes()
diff --git a/src/pybind/mgr/dashboard/controllers/saml2.py b/src/pybind/mgr/dashboard/controllers/saml2.py
new file mode 100644
index 00000000..f02f81fe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/saml2.py
@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import sys
+import cherrypy
+
+try:
+ from onelogin.saml2.auth import OneLogin_Saml2_Auth
+ from onelogin.saml2.errors import OneLogin_Saml2_Error
+ from onelogin.saml2.settings import OneLogin_Saml2_Settings
+
+ python_saml_imported = True
+except ImportError:
+ python_saml_imported = False
+
+from .. import mgr
+from ..exceptions import UserDoesNotExist
+from ..services.auth import JwtManager
+from ..tools import prepare_url_prefix
+from . import BaseController, Controller, Endpoint, allow_empty_body, set_cookies
+
+
+@Controller('/auth/saml2', secure=False)
+class Saml2(BaseController):
+
+ @staticmethod
+ def _build_req(request, post_data):
+ return {
+ 'https': 'on' if request.scheme == 'https' else 'off',
+ 'http_host': request.host,
+ 'script_name': request.path_info,
+ 'server_port': str(request.port),
+ 'get_data': {},
+ 'post_data': post_data
+ }
+
+ @staticmethod
+ def _check_python_saml():
+ if not python_saml_imported:
+ python_saml_name = 'python3-saml' if sys.version_info >= (3, 0) else 'python-saml'
+ raise cherrypy.HTTPError(400,
+ 'Required library not found: `{}`'.format(python_saml_name))
+ try:
+ OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings)
+ except OneLogin_Saml2_Error:
+ raise cherrypy.HTTPError(400, 'Single Sign-On is not configured.')
+
+ @Endpoint('POST', path="")
+ @allow_empty_body
+ def auth_response(self, **kwargs):
+ Saml2._check_python_saml()
+ req = Saml2._build_req(self._request, kwargs)
+ auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings)
+ auth.process_response()
+ errors = auth.get_errors()
+
+ if auth.is_authenticated():
+ JwtManager.reset_user()
+ username_attribute = auth.get_attribute(mgr.SSO_DB.saml2.get_username_attribute())
+ if username_attribute is None:
+ raise cherrypy.HTTPError(400,
+ 'SSO error - `{}` not found in auth attributes. '
+ 'Received attributes: {}'
+ .format(
+ mgr.SSO_DB.saml2.get_username_attribute(),
+ auth.get_attributes()))
+ username = username_attribute[0]
+ url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default=''))
+ try:
+ mgr.ACCESS_CTRL_DB.get_user(username)
+ except UserDoesNotExist:
+ raise cherrypy.HTTPRedirect("{}/#/sso/404".format(url_prefix))
+
+ token = JwtManager.gen_token(username)
+ JwtManager.set_user(JwtManager.decode_token(token))
+ token = token.decode('utf-8')
+ set_cookies(url_prefix, token)
+ raise cherrypy.HTTPRedirect("{}/#/login?access_token={}".format(url_prefix, token))
+ else:
+ return {
+ 'is_authenticated': auth.is_authenticated(),
+ 'errors': errors,
+ 'reason': auth.get_last_error_reason()
+ }
+
+ @Endpoint(xml=True)
+ def metadata(self):
+ Saml2._check_python_saml()
+ saml_settings = OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings)
+ return saml_settings.get_sp_metadata()
+
+ @Endpoint(json_response=False)
+ def login(self):
+ Saml2._check_python_saml()
+ req = Saml2._build_req(self._request, {})
+ auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings)
+ raise cherrypy.HTTPRedirect(auth.login())
+
+ @Endpoint(json_response=False)
+ def slo(self):
+ Saml2._check_python_saml()
+ req = Saml2._build_req(self._request, {})
+ auth = OneLogin_Saml2_Auth(req, mgr.SSO_DB.saml2.onelogin_settings)
+ raise cherrypy.HTTPRedirect(auth.logout())
+
+ @Endpoint(json_response=False)
+ def logout(self, **kwargs):
+ # pylint: disable=unused-argument
+ Saml2._check_python_saml()
+ JwtManager.reset_user()
+ cherrypy.response.cookie['token'] = {'expires': 0, 'max-age': 0}
+ url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default=''))
+ raise cherrypy.HTTPRedirect("{}/#/login".format(url_prefix))
diff --git a/src/pybind/mgr/dashboard/controllers/settings.py b/src/pybind/mgr/dashboard/controllers/settings.py
new file mode 100644
index 00000000..a484580e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/settings.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+from contextlib import contextmanager
+
+import cherrypy
+
+from . import ApiController, RESTController
+from ..settings import Settings as SettingsModule, Options
+from ..security import Scope
+
+
+@ApiController('/settings', Scope.CONFIG_OPT)
+class Settings(RESTController):
+ """
+ Enables to manage the settings of the dashboard (not the Ceph cluster).
+ """
+ @contextmanager
+ def _attribute_handler(self, name):
+ """
+ :type name: str|dict[str, str]
+ :rtype: str|dict[str, str]
+ """
+ if isinstance(name, dict):
+ result = {self._to_native(key): value
+ for key, value in name.items()}
+ else:
+ result = self._to_native(name)
+
+ try:
+ yield result
+ except AttributeError:
+ raise cherrypy.NotFound(result)
+
+ @staticmethod
+ def _to_native(setting):
+ return setting.upper().replace('-', '_')
+
+ def list(self):
+ return [
+ self._get(name) for name in Options.__dict__
+ if name.isupper() and not name.startswith('_')
+ ]
+
+ def _get(self, name):
+ with self._attribute_handler(name) as sname:
+ default, data_type = getattr(Options, sname)
+ return {
+ 'name': sname,
+ 'default': default,
+ 'type': data_type.__name__,
+ 'value': getattr(SettingsModule, sname)
+ }
+
+ def get(self, name):
+ return self._get(name)
+
+ def set(self, name, value):
+ with self._attribute_handler(name) as sname:
+ setattr(SettingsModule, self._to_native(sname), value)
+
+ def delete(self, name):
+ with self._attribute_handler(name) as sname:
+ delattr(SettingsModule, self._to_native(sname))
+
+ def bulk_set(self, **kwargs):
+ with self._attribute_handler(kwargs) as data:
+ for name, value in data.items():
+ setattr(SettingsModule, self._to_native(name), value)
diff --git a/src/pybind/mgr/dashboard/controllers/summary.py b/src/pybind/mgr/dashboard/controllers/summary.py
new file mode 100644
index 00000000..09d69ecf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/summary.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+from . import ApiController, Endpoint, BaseController
+from .. import mgr
+from ..security import Permission, Scope
+from ..controllers.rbd_mirroring import get_daemons_and_pools
+from ..exceptions import ViewCacheNoDataException
+from ..tools import TaskManager
+
+
+@ApiController('/summary')
+class Summary(BaseController):
+ def _health_status(self):
+ health_data = mgr.get("health")
+ return json.loads(health_data["json"])['status']
+
+ def _rbd_mirroring(self):
+ try:
+ _, data = get_daemons_and_pools()
+ except ViewCacheNoDataException:
+ return {}
+
+ daemons = data.get('daemons', [])
+ pools = data.get('pools', {})
+
+ warnings = 0
+ errors = 0
+ for daemon in daemons:
+ if daemon['health_color'] == 'error':
+ errors += 1
+ elif daemon['health_color'] == 'warning':
+ warnings += 1
+ for _, pool in pools.items():
+ if pool['health_color'] == 'error':
+ errors += 1
+ elif pool['health_color'] == 'warning':
+ warnings += 1
+ return {'warnings': warnings, 'errors': errors}
+
+ def _task_permissions(self, name):
+ result = True
+ if name == 'pool/create':
+ result = self._has_permissions(Permission.CREATE, Scope.POOL)
+ elif name == 'pool/edit':
+ result = self._has_permissions(Permission.UPDATE, Scope.POOL)
+ elif name == 'pool/delete':
+ result = self._has_permissions(Permission.DELETE, Scope.POOL)
+ elif name in [
+ 'rbd/create', 'rbd/copy', 'rbd/snap/create',
+ 'rbd/clone', 'rbd/trash/restore']:
+ result = self._has_permissions(Permission.CREATE, Scope.RBD_IMAGE)
+ elif name in [
+ 'rbd/edit', 'rbd/snap/edit', 'rbd/flatten',
+ 'rbd/snap/rollback']:
+ result = self._has_permissions(Permission.UPDATE, Scope.RBD_IMAGE)
+ elif name in [
+ 'rbd/delete', 'rbd/snap/delete', 'rbd/trash/move',
+ 'rbd/trash/remove', 'rbd/trash/purge']:
+ result = self._has_permissions(Permission.DELETE, Scope.RBD_IMAGE)
+ return result
+
+ def _get_host(self):
+ # type: () -> str
+ services = mgr.get('mgr_map')['services']
+ return services['dashboard'] if 'dashboard' in services else ''
+
+ @Endpoint()
+ def __call__(self):
+ exe_t, fin_t = TaskManager.list_serializable()
+ executing_tasks = [task for task in exe_t if self._task_permissions(task['name'])]
+ finished_tasks = [task for task in fin_t if self._task_permissions(task['name'])]
+
+ result = {
+ 'health_status': self._health_status(),
+ 'mgr_id': mgr.get_mgr_id(),
+ 'mgr_host': self._get_host(),
+ 'have_mon_connection': mgr.have_mon_connection(),
+ 'executing_tasks': executing_tasks,
+ 'finished_tasks': finished_tasks,
+ 'version': mgr.version
+ }
+ if self._has_permissions(Permission.READ, Scope.RBD_MIRRORING):
+ result['rbd_mirroring'] = self._rbd_mirroring()
+ return result
diff --git a/src/pybind/mgr/dashboard/controllers/task.py b/src/pybind/mgr/dashboard/controllers/task.py
new file mode 100644
index 00000000..9380f070
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/task.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ApiController, RESTController
+from ..tools import TaskManager
+
+
+@ApiController('/task')
+class Task(RESTController):
+ def list(self, name=None):
+ executing_t, finished_t = TaskManager.list_serializable(name)
+ return {
+ 'executing_tasks': executing_t,
+ 'finished_tasks': finished_t
+ }
diff --git a/src/pybind/mgr/dashboard/controllers/user.py b/src/pybind/mgr/dashboard/controllers/user.py
new file mode 100644
index 00000000..d99dead3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/user.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import cherrypy
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..exceptions import DashboardException, UserAlreadyExists, \
+ UserDoesNotExist
+from ..security import Scope
+from ..services.access_control import SYSTEM_ROLES
+from ..services.auth import JwtManager
+
+
+@ApiController('/user', Scope.USER)
+class User(RESTController):
+ @staticmethod
+ def _user_to_dict(user):
+ result = user.to_dict()
+ del result['password']
+ return result
+
+ @staticmethod
+ def _get_user_roles(roles):
+ all_roles = dict(mgr.ACCESS_CTRL_DB.roles)
+ all_roles.update(SYSTEM_ROLES)
+ try:
+ return [all_roles[rolename] for rolename in roles]
+ except KeyError:
+ raise DashboardException(msg='Role does not exist',
+ code='role_does_not_exist',
+ component='user')
+
+ def list(self):
+ users = mgr.ACCESS_CTRL_DB.users
+ result = [User._user_to_dict(u) for _, u in users.items()]
+ return result
+
+ def get(self, username):
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ except UserDoesNotExist:
+ raise cherrypy.HTTPError(404)
+ return User._user_to_dict(user)
+
+ def create(self, username=None, password=None, name=None, email=None, roles=None):
+ if not username:
+ raise DashboardException(msg='Username is required',
+ code='username_required',
+ component='user')
+ user_roles = None
+ if roles:
+ user_roles = User._get_user_roles(roles)
+ try:
+ user = mgr.ACCESS_CTRL_DB.create_user(username, password, name, email)
+ except UserAlreadyExists:
+ raise DashboardException(msg='Username already exists',
+ code='username_already_exists',
+ component='user')
+ if user_roles:
+ user.set_roles(user_roles)
+ mgr.ACCESS_CTRL_DB.save()
+ return User._user_to_dict(user)
+
+ def delete(self, username):
+ session_username = JwtManager.get_username()
+ if session_username == username:
+ raise DashboardException(msg='Cannot delete current user',
+ code='cannot_delete_current_user',
+ component='user')
+ try:
+ mgr.ACCESS_CTRL_DB.delete_user(username)
+ except UserDoesNotExist:
+ raise cherrypy.HTTPError(404)
+ mgr.ACCESS_CTRL_DB.save()
+
+ def set(self, username, password=None, name=None, email=None, roles=None):
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ except UserDoesNotExist:
+ raise cherrypy.HTTPError(404)
+ user_roles = []
+ if roles:
+ user_roles = User._get_user_roles(roles)
+ if password:
+ user.set_password(password)
+ user.name = name
+ user.email = email
+ user.set_roles(user_roles)
+ mgr.ACCESS_CTRL_DB.save()
+ return User._user_to_dict(user)
diff --git a/src/pybind/mgr/dashboard/exceptions.py b/src/pybind/mgr/dashboard/exceptions.py
new file mode 100644
index 00000000..b44a3f15
--- /dev/null
+++ b/src/pybind/mgr/dashboard/exceptions.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+
+class ViewCacheNoDataException(Exception):
+ def __init__(self):
+ self.status = 200
+ super(ViewCacheNoDataException, self).__init__('ViewCache: unable to retrieve data')
+
+
+class DashboardException(Exception):
+ """
+ Used for exceptions that are already handled and should end up as a user error.
+ Or, as a replacement for cherrypy.HTTPError(...)
+
+ Typically, you don't inherent from DashboardException
+ """
+
+ # pylint: disable=too-many-arguments
+ def __init__(self, e=None, code=None, component=None, http_status_code=None, msg=None):
+ super(DashboardException, self).__init__(msg)
+ self._code = code
+ self.component = component
+ if e:
+ self.e = e
+ if http_status_code:
+ self.status = http_status_code
+ else:
+ self.status = 400
+
+ def __str__(self):
+ try:
+ return str(self.e)
+ except AttributeError:
+ return super(DashboardException, self).__str__()
+
+ @property
+ def errno(self):
+ return self.e.errno
+
+ @property
+ def code(self):
+ if self._code:
+ return str(self._code)
+ return str(abs(self.errno))
+
+
+# access control module exceptions
+class RoleAlreadyExists(Exception):
+ def __init__(self, name):
+ super(RoleAlreadyExists, self).__init__(
+ "Role '{}' already exists".format(name))
+
+
+class RoleDoesNotExist(Exception):
+ def __init__(self, name):
+ super(RoleDoesNotExist, self).__init__(
+ "Role '{}' does not exist".format(name))
+
+
+class ScopeNotValid(Exception):
+ def __init__(self, name):
+ super(ScopeNotValid, self).__init__(
+ "Scope '{}' is not valid".format(name))
+
+
+class PermissionNotValid(Exception):
+ def __init__(self, name):
+ super(PermissionNotValid, self).__init__(
+ "Permission '{}' is not valid".format(name))
+
+
+class RoleIsAssociatedWithUser(Exception):
+ def __init__(self, rolename, username):
+ super(RoleIsAssociatedWithUser, self).__init__(
+ "Role '{}' is still associated with user '{}'"
+ .format(rolename, username))
+
+
+class UserAlreadyExists(Exception):
+ def __init__(self, name):
+ super(UserAlreadyExists, self).__init__(
+ "User '{}' already exists".format(name))
+
+
+class UserDoesNotExist(Exception):
+ def __init__(self, name):
+ super(UserDoesNotExist, self).__init__(
+ "User '{}' does not exist".format(name))
+
+
+class ScopeNotInRole(Exception):
+ def __init__(self, scopename, rolename):
+ super(ScopeNotInRole, self).__init__(
+ "There are no permissions for scope '{}' in role '{}'"
+ .format(scopename, rolename))
+
+
+class RoleNotInUser(Exception):
+ def __init__(self, rolename, username):
+ super(RoleNotInUser, self).__init__(
+ "Role '{}' is not associated with user '{}'"
+ .format(rolename, username))
+
+
+class GrafanaError(Exception):
+ pass
diff --git a/src/pybind/mgr/dashboard/frontend/.babelrc b/src/pybind/mgr/dashboard/frontend/.babelrc
new file mode 100644
index 00000000..002b4aa0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["env"]
+}
diff --git a/src/pybind/mgr/dashboard/frontend/.editorconfig b/src/pybind/mgr/dashboard/frontend/.editorconfig
new file mode 100644
index 00000000..6e87a003
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/src/pybind/mgr/dashboard/frontend/.gitignore b/src/pybind/mgr/dashboard/frontend/.gitignore
new file mode 100644
index 00000000..abe42200
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/.gitignore
@@ -0,0 +1,49 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+
+# dependencies
+/node_modules
+
+# IDEs and editors
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+testem.log
+/typings
+/src/unit-test-configuration.ts
+
+# e2e
+/e2e/*.js
+/e2e/*.map
+
+# System Files
+.DS_Store
+Thumbs.db
+
+# Package lock files
+yarn.lock
+
+# Ceph
+!core
+!*.core
diff --git a/src/pybind/mgr/dashboard/frontend/.prettierignore b/src/pybind/mgr/dashboard/frontend/.prettierignore
new file mode 100644
index 00000000..2d19fc76
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/.prettierignore
@@ -0,0 +1 @@
+*.html
diff --git a/src/pybind/mgr/dashboard/frontend/.prettierrc b/src/pybind/mgr/dashboard/frontend/.prettierrc
new file mode 100644
index 00000000..7d65e364
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "arrowParens": "always",
+ "printWidth": 100,
+ "singleQuote": true
+}
diff --git a/src/pybind/mgr/dashboard/frontend/angular.json b/src/pybind/mgr/dashboard/frontend/angular.json
new file mode 100644
index 00000000..fc8a78ab
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/angular.json
@@ -0,0 +1,233 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "ceph-dashboard": {
+ "root": "",
+ "sourceRoot": "src",
+ "projectType": "application",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:browser",
+ "options": {
+ "aot": true,
+ "i18nFormat": "xlf",
+ "i18nMissingTranslation": "ignore",
+ "outputPath": "dist",
+ "index": "src/index.html",
+ "main": "src/main.ts",
+ "tsConfig": "src/tsconfig.app.json",
+ "polyfills": "src/polyfills.ts",
+ "assets": [
+ "src/assets",
+ "src/favicon.ico",
+ {
+ "glob": "**/swagger-ui.css",
+ "input": "node_modules/swagger-ui-dist",
+ "output": "."
+ },
+ {
+ "glob": "**/swagger-ui-bundle.js",
+ "input": "node_modules/swagger-ui-dist",
+ "output": "."
+ }
+ ],
+ "styles": [
+ "node_modules/ngx-toastr/toastr.css",
+ "node_modules/bootstrap/dist/css/bootstrap.css",
+ "node_modules/fork-awesome/css/fork-awesome.css",
+ "node_modules/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css",
+ "node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
+ "src/styles.scss",
+ "src/vendor.overrides.scss",
+ "node_modules/ng2-tree/styles.css"
+ ],
+ "scripts": [
+ "node_modules/chart.js/dist/Chart.bundle.js"
+ ]
+ },
+ "configurations": {
+ "production": {
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ]
+ },
+ "cs": {
+ "outputPath": "dist/cs/",
+ "i18nFile": "src/locale/messages.cs.xlf",
+ "i18nLocale": "cs"
+ },
+ "de-DE": {
+ "outputPath": "dist/de-DE/",
+ "i18nFile": "src/locale/messages.de-DE.xlf",
+ "i18nLocale": "de-DE"
+ },
+ "en-US": {
+ "outputPath": "dist/en-US/",
+ "i18nFile": "src/locale/messages.en-US.xlf",
+ "i18nLocale": "en-US"
+ },
+ "es-ES": {
+ "outputPath": "dist/es-ES/",
+ "i18nFile": "src/locale/messages.es-ES.xlf",
+ "i18nLocale": "es-ES"
+ },
+ "fr-FR": {
+ "outputPath": "dist/fr-FR/",
+ "i18nFile": "src/locale/messages.fr-FR.xlf",
+ "i18nLocale": "fr-FR"
+ },
+ "id-ID": {
+ "outputPath": "dist/id-ID/",
+ "i18nFile": "src/locale/messages.id-ID.xlf",
+ "i18nLocale": "id-ID"
+ },
+ "it-IT": {
+ "outputPath": "dist/it-IT/",
+ "i18nFile": "src/locale/messages.it-IT.xlf",
+ "i18nLocale": "it-IT"
+ },
+ "ja-JP": {
+ "outputPath": "dist/ja-JP/",
+ "i18nFile": "src/locale/messages.ja-JP.xlf",
+ "i18nLocale": "ja-JP"
+ },
+ "pl-PL": {
+ "outputPath": "dist/pl-PL/",
+ "i18nFile": "src/locale/messages.pl-PL.xlf",
+ "i18nLocale": "pl-PL"
+ },
+ "pt-BR": {
+ "outputPath": "dist/pt-BR/",
+ "i18nFile": "src/locale/messages.pt-BR.xlf",
+ "i18nLocale": "pt-BR"
+ },
+ "zh-CN": {
+ "outputPath": "dist/zh-CN/",
+ "i18nFile": "src/locale/messages.zh-CN.xlf",
+ "i18nLocale": "zh-CN"
+ },
+ "zh-TW": {
+ "outputPath": "dist/zh-TW/",
+ "i18nFile": "src/locale/messages.zh-TW.xlf",
+ "i18nLocale": "zh-TW"
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "options": {
+ "browserTarget": "ceph-dashboard:build",
+ "proxyConfig": "proxy.conf.json"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "ceph-dashboard:build:production"
+ },
+ "cs": {
+ "browserTarget": "ceph-dashboard:build:cs"
+ },
+ "de-DE": {
+ "browserTarget": "ceph-dashboard:build:de-DE"
+ },
+ "en-US": {
+ "browserTarget": "ceph-dashboard:build:en-US"
+ },
+ "es-ES": {
+ "browserTarget": "ceph-dashboard:build:es-ES"
+ },
+ "fr-FR": {
+ "browserTarget": "ceph-dashboard:build:fr-FR"
+ },
+ "id-ID": {
+ "browserTarget": "ceph-dashboard:build:id-ID"
+ },
+ "it-IT": {
+ "browserTarget": "ceph-dashboard:build:it-IT"
+ },
+ "ja-JP": {
+ "browserTarget": "ceph-dashboard:build:ja-JP"
+ },
+ "pl-PL": {
+ "browserTarget": "ceph-dashboard:build:pl-PL"
+ },
+ "pt-BR": {
+ "browserTarget": "ceph-dashboard:build:pt-BR"
+ },
+ "zh-CN": {
+ "browserTarget": "ceph-dashboard:build:zh-CN"
+ },
+ "zh-TW": {
+ "browserTarget": "ceph-dashboard:build:zh-TW"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "ceph-dashboard:build"
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "src/tsconfig.app.json",
+ "src/tsconfig.spec.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ },
+ "ceph-dashboard-e2e": {
+ "root": "",
+ "sourceRoot": "",
+ "projectType": "application",
+ "architect": {
+ "e2e": {
+ "builder": "@angular-devkit/build-angular:protractor",
+ "options": {
+ "protractorConfig": "./protractor.conf.js",
+ "devServerTarget": "ceph-dashboard:serve"
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "e2e/tsconfig.e2e.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "defaultProject": "ceph-dashboard",
+ "schematics": {
+ "@schematics/angular:component": {
+ "prefix": "cd",
+ "styleext": "scss"
+ },
+ "@schematics/angular:directive": {
+ "prefix": "cd"
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/2.22b12bf9358f95829e55.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/2.22b12bf9358f95829e55.js
new file mode 100644
index 00000000..911e456b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/2.22b12bf9358f95829e55.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"+lcs":function(l,n,e){"use strict";e.d(n,"a",function(){return a});var t=e("gIcY"),u=e("K9Ia"),i=(e("F83c"),e("sne2"),e("QFaf")),o=e("kvvV"),a=(e("9nlD"),e("VXsX"),function(){function l(l,n,e,t,u,i){this.modalRef=l,this.rbdService=n,this.taskManagerService=e,this.notificationService=t,this.i18n=u,this.actionLabels=i,this.editing=!1,this.action=this.actionLabels.CREATE,this.resource=this.i18n("RBD Snapshot"),this.createForm()}return l.prototype.createForm=function(){this.snapshotForm=new i.a({snapshotName:new t.i("",{validators:[t.A.required]})})},l.prototype.ngOnInit=function(){this.onSubmit=new u.a},l.prototype.setSnapName=function(l){this.snapName=l,this.snapshotForm.get("snapshotName").setValue(l)},l.prototype.setEditing=function(l){void 0===l&&(l=!0),this.editing=l,this.action=this.editing?this.actionLabels.RENAME:this.actionLabels.CREATE},l.prototype.editAction=function(){var l=this,n=this.snapshotForm.getValue("snapshotName"),e=new o.a;e.name="rbd/snap/edit",e.metadata={pool_name:this.poolName,image_name:this.imageName,snapshot_name:n},this.rbdService.renameSnapshot(this.poolName,this.imageName,this.snapName,n).toPromise().then(function(){l.taskManagerService.subscribe(e.name,e.metadata,function(n){l.notificationService.notifyTask(n)}),l.modalRef.hide(),l.onSubmit.next(l.snapName)}).catch(function(){l.snapshotForm.setErrors({cdSubmitButton:!0})})},l.prototype.createAction=function(){var l=this,n=this.snapshotForm.getValue("snapshotName"),e=new o.a;e.name="rbd/snap/create",e.metadata={pool_name:this.poolName,image_name:this.imageName,snapshot_name:n},this.rbdService.createSnapshot(this.poolName,this.imageName,n).toPromise().then(function(){l.taskManagerService.subscribe(e.name,e.metadata,function(n){l.notificationService.notifyTask(n)}),l.modalRef.hide(),l.onSubmit.next(n)}).catch(function(){l.snapshotForm.setErrors({cdSubmitButton:!0})})},l.prototype.submit=function(){this.editing?this.editAction():this.createAction()},l}())},"0rTx":function(l,n,e){"use strict";var t=e("CcnG"),u=e("EEJc"),i=e("ajRT"),o=e("gIcY"),a=e("Ip0R"),r=e("IZUe"),s=e("ANnk"),d=e("f/UV"),c=e("aexS"),p=e("gp3X"),m=e("sb0X"),f=e("KVJa"),g=e("Z21x"),h=e("sne2"),v=e("2GqK"),b=e("F83c"),y=e("DQlY"),C=e("2EZI"),_=e("kn/O");e.d(n,"a",function(){return k});var w=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,45,"cd-modal",[],null,null,null,u.c,u.b)),t["\u0275did"](1,49152,null,0,i.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Restore Image"])),(l()(),t["\u0275eld"](4,0,null,1,41,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,40,"form",[["class","form"],["name","restoreForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,o.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,o.d,null,[o.l]),t["\u0275did"](9,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,28,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,12,"p",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["To restore"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](15,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](16,null,["","/","@",""])),(l()(),t["\u0275ted"](-1,null,[",\xa0 "])),(l()(),t["\u0275eld"](18,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["type the image's new name and click"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](21,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Restore Image"])),(l()(),t["\u0275ted"](-1,null,[". "])),(l()(),t["\u0275eld"](24,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](25,278528,null,0,a.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](26,{"has-error":0}),(l()(),t["\u0275eld"](27,0,null,null,1,"label",[["for","name"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["New Name"])),(l()(),t["\u0275eld"](29,0,null,null,7,"input",[["autocomplete","off"],["autofocus",""],["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,30)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,30).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,30)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,30)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](30,16384,null,0,o.e,[t.Renderer2,t.ElementRef,[2,o.b]],null,null),t["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),t["\u0275did"](32,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,o.q,null,[o.j]),t["\u0275did"](34,16384,null,0,o.r,[[4,o.q]],null,null),t["\u0275did"](35,4210688,null,0,r.a,[t.ElementRef],null,null),t["\u0275did"](36,4210688,null,0,s.a,[[2,d.a],c.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](38,16384,null,0,a.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](39,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](40,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](41,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.restore()&&t),t},p.b,p.a)),t["\u0275did"](42,114688,null,0,m.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Restore Image"])),(l()(),t["\u0275eld"](44,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,f.b,f.a)),t["\u0275did"](45,49152,null,0,g.a,[a.Location,h.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,7,0,e.restoreForm);var u=l(n,26,0,e.restoreForm.showError("name",t["\u0275nov"](n,7)));l(n,25,0,"form-group",u),l(n,32,0,"name"),l(n,38,0,e.restoreForm.showError("name",t["\u0275nov"](n,7),"required")),l(n,42,0,e.restoreForm),l(n,45,0,"Cancel",e.modalRef.hide)},function(l,n){var e=n.component;l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending),l(n,16,0,e.poolName,e.imageName,e.imageId),l(n,29,0,t["\u0275nov"](n,34).ngClassUntouched,t["\u0275nov"](n,34).ngClassTouched,t["\u0275nov"](n,34).ngClassPristine,t["\u0275nov"](n,34).ngClassDirty,t["\u0275nov"](n,34).ngClassValid,t["\u0275nov"](n,34).ngClassInvalid,t["\u0275nov"](n,34).ngClassPending)})}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rbd-trash-restore-modal",[],null,null,null,I,w)),t["\u0275did"](1,114688,null,0,v.a,[b.a,y.a,C.a,_.a],null,null)],function(l,n){l(n,1,0)},null)}var k=t["\u0275ccf"]("cd-rbd-trash-restore-modal",v.a,S,{},{},[])},"2GqK":function(l,n,e){"use strict";e.d(n,"a",function(){return u}),e("F83c"),e("2EZI");var t=e("kvvV"),u=(e("kn/O"),function(){function l(l,n,e,t){this.rbdService=l,this.modalRef=n,this.fb=e,this.taskWrapper=t}return l.prototype.ngOnInit=function(){this.restoreForm=this.fb.group({name:this.imageName})},l.prototype.restore=function(){var l=this,n=this.restoreForm.getValue("name");this.taskWrapper.wrapTaskAroundCall({task:new t.a("rbd/trash/restore",{pool_name:this.poolName,image_id:this.imageId,new_image_name:n}),call:this.rbdService.restoreTrash(this.poolName,this.imageId,n)}).subscribe(void 0,function(){l.restoreForm.setErrors({cdSubmitButton:!0})},function(){l.modalRef.hide()})},l}())},"2JDI":function(l,n,e){"use strict";e.d(n,"a",function(){return o});var t=e("wd/R"),u=(e("F83c"),e("2EZI"),e("1Ni5")),i=e("kvvV"),o=(e("kn/O"),function(){function l(l,n,e,t){this.rbdService=l,this.modalRef=n,this.fb=e,this.taskWrapper=t,this.minDate=new Date,this.bsConfig={dateInputFormat:"YYYY-MM-DD HH:mm:ss",containerClass:"theme-default"},this.createForm()}return l.prototype.createForm=function(){this.moveForm=this.fb.group({expiresAt:["",[u.a.custom("format",function(l){return!(""===l||t(l,"YYYY-MM-DD HH:mm:ss").isValid())}),u.a.custom("expired",function(l){return t().isAfter(l)})]]})},l.prototype.ngOnInit=function(){this.pattern=this.poolName+"/"+this.imageName},l.prototype.moveImage=function(){var l=this,n=0,e=this.moveForm.getValue("expiresAt");e&&(n=t(e).diff(t(),"seconds",!0)),n<0&&(n=0),this.taskWrapper.wrapTaskAroundCall({task:new i.a("rbd/trash/move",{pool_name:this.poolName,image_name:this.imageName}),call:this.rbdService.moveTrash(this.poolName,this.imageName,n)}).subscribe(void 0,void 0,function(){l.modalRef.hide()})},l}())},"3ris":function(l,n,e){"use strict";e.d(n,"a",function(){return u});var t=e("LvDl"),u=(e("uIqm"),e("vCyI"),e("iExv"),e("uYzU"),function(){function l(l,n,e){this.i18n=l,this.iscsiBackstorePipe=n,this.booleanTextPipe=e,this.metadata={}}return Object.defineProperty(l.prototype,"content",{set:function(l){this.detailTable=l,l&&l.updateColumns()},enumerable:!0,configurable:!0}),l.prototype.ngOnInit=function(){this.columns=[{prop:"displayName",name:this.i18n("Name"),flexGrow:1,cellTemplate:this.highlightTpl},{prop:"current",name:this.i18n("Current"),flexGrow:1,cellTemplate:this.highlightTpl},{prop:"default",name:this.i18n("Default"),flexGrow:1,cellTemplate:this.highlightTpl}]},l.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.selectedItem=this.selection.first(),this.generateTree()),this.data=void 0},l.prototype.generateTree=function(){var l=this,n=t.cloneDeep(this.selectedItem.target_controls);this.cephIscsiConfigVersion>10&&t.extend(n,t.cloneDeep(this.selectedItem.auth)),this.metadata={root:n};var e={target:{expanded:this.selectedItem.cdExecuting?"fa fa-fw fa-spinner fa-spin fa-lg":"fa fa-fw fa-bullseye fa-lg"},initiators:{expanded:"fa fa-fw fa-user fa-lg",leaf:"fa fa-fw fa-user"},groups:{expanded:"fa fa-fw fa-users fa-lg",leaf:"fa fa-fw fa-users"},disks:{expanded:"fa fa-fw fa-hdd-o fa-lg",leaf:"fa fa-fw fa-hdd-o"},portals:{expanded:"fa fa-fw fa-server fa-lg",leaf:"fa fa-fw fa-server fa-lg"}},u=[];t.forEach(this.selectedItem.disks,function(n){var e="disk_"+n.pool+"_"+n.image;l.metadata[e]={controls:n.controls,backstore:n.backstore},["wwn","lun"].forEach(function(t){t in n&&(l.metadata[e][t]=n[t])}),u.push({value:n.pool+"/"+n.image,id:e})});var i=[];t.forEach(this.selectedItem.portals,function(l){i.push({value:l.host+":"+l.ip})});var o=[];t.forEach(this.selectedItem.clients,function(n){var u=t.cloneDeep(n.auth);n.info&&(t.extend(u,n.info),delete u.state,t.forEach(Object.keys(n.info.state),function(l){u[l.toLowerCase()]=n.info.state[l]})),l.metadata["client_"+n.client_iqn]=u;var i=[];n.luns.forEach(function(l){i.push({value:l.pool+"/"+l.image,id:"disk_"+l.pool+"_"+l.image,settings:{cssClasses:e.disks}})});var a="";n.info&&(a=Object.keys(n.info.state).includes("LOGGED_IN")?"logged_in":"logged_out"),o.push({value:n.client_iqn,status:a,id:"client_"+n.client_iqn,children:i})});var a=[];t.forEach(this.selectedItem.groups,function(l){var n=[];l.disks.forEach(function(l){n.push({value:l.pool+"/"+l.image,id:"disk_"+l.pool+"_"+l.image})});var t=[];l.members.forEach(function(l){t.push({value:l,id:"client_"+l})}),a.push({value:l.group_id,children:[{value:"Disks",children:n,settings:{selectionAllowed:!1,cssClasses:e.disks}},{value:"Initiators",children:t,settings:{selectionAllowed:!1,cssClasses:e.initiators}}]})}),this.tree={value:this.selectedItem.target_iqn,id:"root",settings:{static:!0,cssClasses:e.target},children:[{value:"Disks",children:u,settings:{selectionAllowed:!1,cssClasses:e.disks}},{value:"Portals",children:i,settings:{selectionAllowed:!1,cssClasses:e.portals}},{value:"Initiators",children:o,settings:{selectionAllowed:!1,cssClasses:e.initiators}},{value:"Groups",children:a,settings:{selectionAllowed:!1,cssClasses:e.groups}}]}},l.prototype.format=function(l){return"boolean"==typeof l?this.booleanTextPipe.transform(l):l},l.prototype.onNodeSelected=function(l){var n=this;if(l.node.id){this.title=l.node.value;var e=this.metadata[l.node.id]||{};"root"===l.node.id?(this.columns[2].isHidden=!1,this.data=t.map(this.settings.target_default_controls,function(l,u){return{displayName:u,default:l=n.format(l),current:t.isUndefined(e[u])?l:n.format(e[u])}}),this.cephIscsiConfigVersion>10&&["user","password","mutual_user","mutual_password"].forEach(function(l){n.data.push({displayName:l,default:null,current:e[l]})})):l.node.id.toString().startsWith("disk_")?(this.columns[2].isHidden=!1,this.data=t.map(this.settings.disk_default_controls[e.backstore],function(l,u){return{displayName:u,default:l=n.format(l),current:t.isUndefined(e.controls[u])?l:n.format(e.controls[u])}}),this.data.push({displayName:"backstore",default:this.iscsiBackstorePipe.transform(this.settings.default_backstore),current:this.iscsiBackstorePipe.transform(e.backstore)}),["wwn","lun"].forEach(function(l){l in e&&n.data.push({displayName:l,default:void 0,current:e[l]})})):(this.columns[2].isHidden=!0,this.data=t.map(e,function(l,e){return{displayName:e,default:void 0,current:n.format(l)}}))}else this.data=void 0;this.detailTable&&this.detailTable.updateColumns()},l}())},BH9v:function(l,n,e){"use strict";var t=e("CcnG"),u=e("gIcY"),i=e("aXbf"),o=function(){function l(l,n){this.control=l,this.formatter=n}return l.prototype.setValue=function(l){var n=this.formatter.toMilliseconds(l);this.control.control.setValue(n+" ms")},l.prototype.ngOnInit=function(){var l=this;this.setValue(this.control.value),this.ngDataReady&&this.ngDataReady.subscribe(function(){return l.setValue(l.control.value)})},l.prototype.onUpdate=function(l){this.setValue(l)},l}(),a=e("ANnk"),r=e("f/UV"),s=e("aexS"),d=e("LvDl"),c=e("IzCI"),p=function(){function l(l,n,e,u){this.elementRef=l,this.control=n,this.dimlessBinaryPerSecondPipe=e,this.formatter=u,this.ngModelChange=new t.EventEmitter,this.el=this.elementRef.nativeElement}return l.prototype.ngOnInit=function(){var l=this;this.setValue(this.el.value),this.ngDataReady&&this.ngDataReady.subscribe(function(){return l.setValue(l.el.value)})},l.prototype.setValue=function(l){/^[\d.]+$/.test(l)&&(l+=this.defaultUnit||"m");var n=this.formatter.toBytes(l,0),e=this.round(n);this.el.value=this.dimlessBinaryPerSecondPipe.transform(e),null!==n?(this.ngModelChange.emit(this.el.value),this.control.control.setValue(this.el.value)):(this.ngModelChange.emit(null),this.control.control.setValue(null))},l.prototype.round=function(l){if(null!==l&&0!==l){if(!d.isUndefined(this.minBytes)&&l<this.minBytes)return this.minBytes;if(!d.isUndefined(this.maxBytes)&&l>this.maxBytes)return this.maxBytes;if(!d.isUndefined(this.roundPower)){var n=Math.round(Math.log(l)/Math.log(this.roundPower));return Math.pow(this.roundPower,n)}}return l},l.prototype.onBlur=function(l){this.setValue(l)},l}(),m=function(){function l(l,n){this.formatter=l,this.ngControl=n}return l.prototype.setValue=function(l){var n=this.formatter.toIops(l);this.ngControl.control.setValue(n+" IOPS")},l.prototype.ngOnInit=function(){var l=this;this.setValue(this.ngControl.value),this.ngDataReady&&this.ngDataReady.subscribe(function(){return l.setValue(l.ngControl.value)})},l.prototype.onUpdate=function(l){this.setValue(l)},l}(),f=e("Ip0R"),g=e("4HWh"),h=e("p4Cf");e("rFfW"),e("o8EM"),e.d(n,"a",function(){return v}),e.d(n,"b",function(){return I});var v=t["\u0275crt"]({encapsulation:0,styles:[[".collapsible[_ngcontent-%COMP%]{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}"]],data:{}});function b(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,8,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,7,"input",[["cdMilliseconds",""],["class","form-control"],["type","text"]],[[8,"id",0],[8,"name",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,2)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,2).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionEnd(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,7).onUpdate(e.target.value)&&u),u},null,null)),t["\u0275did"](2,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](4,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](6,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](7,81920,null,0,o,[u.q,i.a],{ngDataReady:[0,"ngDataReady"]},null),t["\u0275did"](8,4210688,null,0,a.a,[[2,r.a],s.a,t.ElementRef],null,null)],function(l,n){var e=n.component;l(n,4,0,n.parent.context.$implicit.name),l(n,7,0,e.ngDataReady)},function(l,n){l(n,1,0,n.parent.context.$implicit.name,n.parent.context.$implicit.name,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function y(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,8,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,7,"input",[["cdDimlessBinaryPerSecond",""],["class","form-control"],["defaultUnit","b"],["type","text"]],[[8,"id",0],[8,"name",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,2)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,2).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionEnd(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,7).onBlur(e.target.value)&&u),u},null,null)),t["\u0275did"](2,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](4,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](6,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](7,81920,null,0,p,[t.ElementRef,u.q,c.a,i.a],{ngDataReady:[0,"ngDataReady"],defaultUnit:[1,"defaultUnit"]},null),t["\u0275did"](8,4210688,null,0,a.a,[[2,r.a],s.a,t.ElementRef],null,null)],function(l,n){var e=n.component;l(n,4,0,n.parent.context.$implicit.name),l(n,7,0,e.ngDataReady,"b")},function(l,n){l(n,1,0,n.parent.context.$implicit.name,n.parent.context.$implicit.name,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function C(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,8,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,7,"input",[["cdIops",""],["class","form-control"],["type","text"]],[[8,"id",0],[8,"name",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,2)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,2).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,2)._compositionEnd(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,7).onUpdate(e.target.value)&&u),u},null,null)),t["\u0275did"](2,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](4,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](6,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](7,81920,null,0,m,[i.a,u.q],{ngDataReady:[0,"ngDataReady"]},null),t["\u0275did"](8,4210688,null,0,a.a,[[2,r.a],s.a,t.ElementRef],null,null)],function(l,n){var e=n.component;l(n,4,0,n.parent.context.$implicit.name),l(n,7,0,e.ngDataReady)},function(l,n){l(n,1,0,n.parent.context.$implicit.name,n.parent.context.$implicit.name,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function _(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The mininum value is 0"]))],null,null)}function w(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,f.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,4,"label",[["class","control-label col-sm-3"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),t["\u0275ted"](4,null,["",""])),(l()(),t["\u0275eld"](5,0,null,null,2,"cd-helper",[],null,null,null,g.b,g.a)),t["\u0275did"](6,49152,null,0,h.a,[],null,null),(l()(),t["\u0275ted"](7,0,["",""])),(l()(),t["\u0275eld"](8,0,null,null,16,"div",[],[[8,"className",0]],null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,13,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,7,null,null,null,null,null,null,null)),t["\u0275did"](11,16384,null,0,f.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,b)),t["\u0275did"](13,278528,null,0,f.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,f.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,y)),t["\u0275did"](15,278528,null,0,f.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,f.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,C)),t["\u0275did"](17,278528,null,0,f.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,f.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275eld"](18,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,3,"button",[["class","btn btn-default"],["data-toggle","button"],["title","Remove the local configuration value. The parent configuration value will be inherited and used instead."],["type","button"]],null,[[null,"click"]],function(l,n,e){var t=!0;return"click"===n&&(t=!1!==l.component.reset(l.context.$implicit.name)&&t),t},null,null)),t["\u0275did"](20,278528,null,0,f.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](21,{active:0}),(l()(),t["\u0275eld"](22,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-eraser"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,_)),t["\u0275did"](24,16384,null,0,f.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,u=l(n,2,0,e.form.showError("configuration."+n.context.$implicit.name,t["\u0275nov"](n.parent.parent,0)));l(n,1,0,"form-group",u),l(n,11,0,n.context.$implicit.type),l(n,13,0,e.configurationType.milliseconds),l(n,15,0,e.configurationType.bps),l(n,17,0,e.configurationType.iops);var i=l(n,21,0,e.isDisabled(n.context.$implicit.name));l(n,20,0,"btn btn-default",i),l(n,24,0,e.form.showError("configuration."+n.context.$implicit.name,t["\u0275nov"](n.parent.parent,0),"min"))},function(l,n){l(n,3,0,n.context.$implicit.name),l(n,4,0,n.context.$implicit.displayName),l(n,7,0,n.context.$implicit.description),l(n,8,0,t["\u0275inlineInterpolate"](1,"col-sm-9 ",n.parent.context.$implicit.heading,""))})}function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,9,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,5,"h3",[["class","page-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,4,"span",[["class","collapsible"]],null,[[null,"click"]],function(l,n,e){var t=!0;return"click"===n&&(t=!1!==l.component.toggleSectionVisibility(l.context.$implicit.class)&&t),t},null,null)),(l()(),t["\u0275ted"](3,null,[""," "])),(l()(),t["\u0275eld"](4,0,null,null,2,"i",[["aria-hidden","true"],["class","fa"]],null,null,null,null,null)),t["\u0275did"](5,278528,null,0,f.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](6,{"fa-plus-circle":0,"fa-minus-circle":1}),(l()(),t["\u0275eld"](7,0,null,null,2,"div",[],[[8,"className",0],[8,"hidden",0]],null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,w)),t["\u0275did"](9,278528,null,0,f.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component,t=l(n,6,0,!e.sectionVisibility[n.context.$implicit.class],e.sectionVisibility[n.context.$implicit.class]);l(n,5,0,"fa",t),l(n,9,0,n.context.$implicit.options)},function(l,n){var e=n.component;l(n,3,0,n.context.$implicit.heading),l(n,7,0,t["\u0275inlineInterpolate"](1,"",n.context.$implicit.class,""),!e.sectionVisibility[n.context.$implicit.class])})}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,[["cfgFormGroup",1]],null,7,"fieldset",[],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,1).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,1).onReset()&&u),u},null,null)),t["\u0275did"](1,540672,null,0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,u.d,null,[u.l]),t["\u0275did"](3,16384,null,0,u.s,[[4,u.d]],null,null),(l()(),t["\u0275eld"](4,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["RBD Configuration"])),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](7,278528,null,0,f.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,1,0,e.form.get("configuration")),l(n,7,0,e.rbdConfigurationService.sections)},function(l,n){l(n,0,0,t["\u0275nov"](n,3).ngClassUntouched,t["\u0275nov"](n,3).ngClassTouched,t["\u0275nov"](n,3).ngClassPristine,t["\u0275nov"](n,3).ngClassDirty,t["\u0275nov"](n,3).ngClassValid,t["\u0275nov"](n,3).ngClassInvalid,t["\u0275nov"](n,3).ngClassPending)})}},EFGL:function(l,n,e){"use strict";var t=e("CcnG"),u=e("Ip0R"),i=e("IzCI"),o=e("aXbf"),a=e("dEH0"),r=e("BQkM"),s=e("25BL"),d=e("uIqm");e("aAWM"),e("o8EM"),e("Jm/i"),e.d(n,"a",function(){return c}),e.d(n,"b",function(){return _});var c=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function p(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Global"]))],null,null)}function m(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Image"]))],null,null)}function f(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Pool"]))],null,null)}function g(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,7,"div",[],null,null,null,null,null)),t["\u0275did"](1,16384,null,0,u.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,p)),t["\u0275did"](3,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,m)),t["\u0275did"](5,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,f)),t["\u0275did"](7,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null)],function(l,n){l(n,1,0,n.context.value),l(n,3,0,"global"),l(n,5,0,"image"),l(n,7,0,"pool")},null)}function h(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""])),t["\u0275ppd"](2,1)],null,function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent,0),n.parent.context.value));l(n,1,0,e)})}function v(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""])),t["\u0275ppd"](2,1)],null,function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent,1),n.parent.context.value));l(n,1,0,e)})}function b(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""])),t["\u0275ppd"](2,1)],null,function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent,2),n.parent.context.value));l(n,1,0,e)})}function y(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""]))],null,function(l,n){l(n,1,0,n.parent.context.value)})}function C(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,9,"div",[],null,null,null,null,null)),t["\u0275did"](1,16384,null,0,u.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,h)),t["\u0275did"](3,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,v)),t["\u0275did"](5,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,b)),t["\u0275did"](7,278528,null,0,u.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,y)),t["\u0275did"](9,16384,null,0,u.NgSwitchDefault,[t.ViewContainerRef,t.TemplateRef,u.NgSwitch],null,null)],function(l,n){var e=n.component;l(n,1,0,n.context.row.type),l(n,3,0,e.typeField.bps),l(n,5,0,e.typeField.milliseconds),l(n,7,0,e.typeField.iops)},null)}function _(l){return t["\u0275vid"](0,[t["\u0275pid"](0,i.a,[o.a]),t["\u0275pid"](0,a.a,[]),t["\u0275pid"](0,r.a,[]),t["\u0275qud"](402653184,1,{configurationSourceTpl:0}),t["\u0275qud"](402653184,2,{configurationValueTpl:0}),t["\u0275qud"](402653184,3,{poolConfTable:0}),(l()(),t["\u0275eld"](6,0,null,null,1,"cd-table",[["identifier","name"]],null,null,null,s.b,s.a)),t["\u0275did"](7,2867200,[[3,4],["poolConfTable",4]],0,d.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],identifier:[2,"identifier"]},null),(l()(),t["\u0275and"](0,[[1,2],["configurationSourceTpl",2]],null,0,null,g)),(l()(),t["\u0275and"](0,[[2,2],["configurationValueTpl",2]],null,0,null,C))],function(l,n){var e=n.component;l(n,7,0,e.data,e.poolConfigurationColumns,"name")},null)}},Ekvf:function(l,n,e){"use strict";e.d(n,"a",function(){return d});var t=e("mrSG"),u=e("t/Na"),i=e("67Y/"),o=e("xTzq"),a=e("o8EM"),r=e("CcnG"),s=e("pL04"),d=function(){function l(l,n){this.http=l,this.rbdConfigurationService=n,this.apiPath="api/pool"}return l.prototype.create=function(l){return this.http.post(this.apiPath,l,{observe:"response"})},l.prototype.update=function(l){var n;return l.hasOwnProperty("srcpool")?(n=l.srcpool,delete l.srcpool):(n=l.pool,delete l.pool),this.http.put(this.apiPath+"/"+encodeURIComponent(n),l,{observe:"response"})},l.prototype.delete=function(l){return this.http.delete(this.apiPath+"/"+l,{observe:"response"})},l.prototype.get=function(l){return this.http.get(this.apiPath+"/"+l)},l.prototype.getList=function(){return this.http.get(this.apiPath+"?stats=true")},l.prototype.getConfiguration=function(l){var n=this;return this.http.get(this.apiPath+"/"+l+"/configuration").pipe(Object(i.a)(function(l){return l.map(function(l){return Object.assign(l,n.rbdConfigurationService.getOptionByName(l.name))})}))},l.prototype.getInfo=function(l){return this.http.get(this.apiPath+"/_info"+(l?"?pool_name="+l:""))},l.prototype.list=function(l){void 0===l&&(l=[]);var n=l.join(",");return this.http.get(this.apiPath+"?attrs="+n).toPromise().then(function(l){return l})},l.ngInjectableDef=r.defineInjectable({factory:function(){return new l(r.inject(u.c),r.inject(a.a))},token:l,providedIn:s.a}),l=t.__decorate([o.a,t.__metadata("design:paramtypes",[u.c,a.a])],l)}()},EmSq:function(l,n,e){"use strict";e.d(n,"a",function(){return i});var t=e("CcnG"),u=e("LvDl"),i=(e("Fgil"),e("aXbf"),function(){function l(l,n,e,u){this.elementRef=l,this.control=n,this.dimlessBinaryPipe=e,this.formatter=u,this.ngModelChange=new t.EventEmitter,this.el=this.elementRef.nativeElement}return l.prototype.ngOnInit=function(){this.setValue(this.el.value)},l.prototype.setValue=function(l){/^[\d.]+$/.test(l)&&(l+=this.defaultUnit||"m");var n=this.formatter.toBytes(l),e=this.round(n);this.el.value=this.dimlessBinaryPipe.transform(e),null!==n?(this.ngModelChange.emit(this.el.value),this.control.control.setValue(this.el.value)):(this.ngModelChange.emit(null),this.control.control.setValue(null))},l.prototype.round=function(l){if(null!==l&&0!==l){if(!u.isUndefined(this.minBytes)&&l<this.minBytes)return this.minBytes;if(!u.isUndefined(this.maxBytes)&&l>this.maxBytes)return this.maxBytes;if(!u.isUndefined(this.roundPower)){var n=Math.round(Math.log(l)/Math.log(this.roundPower));return Math.pow(this.roundPower,n)}}return l},l.prototype.onBlur=function(l){this.setValue(l)},l}())},F83c:function(l,n,e){"use strict";e.d(n,"a",function(){return d});var t=e("mrSG"),u=e("t/Na"),i=e("67Y/"),o=e("xTzq"),a=e("o8EM"),r=e("CcnG"),s=e("pL04"),d=function(){function l(l,n){this.http=l,this.rbdConfigurationService=n}return l.prototype.create=function(l){return this.http.post("api/block/image",l,{observe:"response"})},l.prototype.delete=function(l,n){return this.http.delete("api/block/image/"+l+"/"+n,{observe:"response"})},l.prototype.update=function(l,n,e){return this.http.put("api/block/image/"+l+"/"+n,e,{observe:"response"})},l.prototype.get=function(l,n){return this.http.get("api/block/image/"+l+"/"+n)},l.prototype.list=function(){var l=this;return this.http.get("api/block/image").pipe(Object(i.a)(function(n){return n.map(function(n){return n.value.map(function(n){return n.configuration?(n.configuration.map(function(n){return Object.assign(n,l.rbdConfigurationService.getOptionByName(n.name))}),n):n}),n})}))},l.prototype.copy=function(l,n,e){return this.http.post("api/block/image/"+l+"/"+n+"/copy",e,{observe:"response"})},l.prototype.flatten=function(l,n){return this.http.post("api/block/image/"+l+"/"+n+"/flatten",null,{observe:"response"})},l.prototype.defaultFeatures=function(){return this.http.get("api/block/image/default_features")},l.prototype.createSnapshot=function(l,n,e){return this.http.post("api/block/image/"+l+"/"+n+"/snap",{snapshot_name:e},{observe:"response"})},l.prototype.renameSnapshot=function(l,n,e,t){return this.http.put("api/block/image/"+l+"/"+n+"/snap/"+e,{new_snap_name:t},{observe:"response"})},l.prototype.protectSnapshot=function(l,n,e,t){return this.http.put("api/block/image/"+l+"/"+n+"/snap/"+e,{is_protected:t},{observe:"response"})},l.prototype.rollbackSnapshot=function(l,n,e){return this.http.post("api/block/image/"+l+"/"+n+"/snap/"+e+"/rollback",null,{observe:"response"})},l.prototype.cloneSnapshot=function(l,n,e,t){return this.http.post("api/block/image/"+l+"/"+n+"/snap/"+e+"/clone",t,{observe:"response"})},l.prototype.deleteSnapshot=function(l,n,e){return this.http.delete("api/block/image/"+l+"/"+n+"/snap/"+e,{observe:"response"})},l.prototype.listTrash=function(){return this.http.get("api/block/image/trash/")},l.prototype.moveTrash=function(l,n,e){return this.http.post("api/block/image/"+l+"/"+n+"/move_trash",{delay:e},{observe:"response"})},l.prototype.purgeTrash=function(l){return this.http.post("api/block/image/trash/purge/?pool_name="+l,null,{observe:"response"})},l.prototype.restoreTrash=function(l,n,e){return this.http.post("api/block/image/trash/"+l+"/"+n+"/restore",{new_image_name:e},{observe:"response"})},l.prototype.removeTrash=function(l,n,e,t){return void 0===t&&(t=!1),this.http.delete("api/block/image/trash/"+l+"/"+n+"/?image_name="+e+"&force="+t,{observe:"response"})},l.ngInjectableDef=r.defineInjectable({factory:function(){return new l(r.inject(u.c),r.inject(a.a))},token:l,providedIn:s.a}),t.__decorate([t.__param(2,o.b),t.__metadata("design:type",Function),t.__metadata("design:paramtypes",[Object,Object,Object]),t.__metadata("design:returntype",void 0)],l.prototype,"createSnapshot",null),t.__decorate([t.__param(3,o.b),t.__metadata("design:type",Function),t.__metadata("design:paramtypes",[Object,Object,Object,Object]),t.__metadata("design:returntype",void 0)],l.prototype,"renameSnapshot",null),t.__decorate([t.__param(3,o.b),t.__metadata("design:type",Function),t.__metadata("design:paramtypes",[Object,Object,Object,Object]),t.__metadata("design:returntype",void 0)],l.prototype,"protectSnapshot",null),t.__decorate([t.__param(2,o.b),t.__metadata("design:type",Function),t.__metadata("design:paramtypes",[Object,Object,Object]),t.__metadata("design:returntype",void 0)],l.prototype,"restoreTrash",null),l=t.__decorate([o.a,t.__metadata("design:paramtypes",[u.c,a.a])],l)}()},I4Qz:function(l,n,e){"use strict";var t=e("CcnG"),u=e("EEJc"),i=e("ajRT"),o=e("gIcY"),a=e("Ip0R"),r=e("ARl4"),s=e("lqqz"),d=e("ANnk"),c=e("f/UV"),p=e("aexS"),m=e("gp3X"),f=e("sb0X"),g=e("KVJa"),h=e("Z21x"),v=e("sne2"),b=e("2JDI"),y=e("F83c"),C=e("DQlY"),_=e("2EZI"),w=e("kn/O");e.d(n,"a",function(){return F});var R=t["\u0275crt"]({encapsulation:0,styles:[[".bs-datepicker-head bs-datepicker-navigation-view{display:-webkit-box;display:flex;-webkit-box-pack:justify;justify-content:space-between}"]],data:{}});function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,['Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".']))],null,null)}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Protection has already expired. Please pick a future date or leave it empty."]))],null,null)}function k(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,44,"cd-modal",[],null,null,null,u.c,u.b)),t["\u0275did"](1,49152,null,0,i.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Move an image to trash"])),(l()(),t["\u0275eld"](4,0,null,1,40,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,39,"form",[["class","form"],["name","moveForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,o.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,o.d,null,[o.l]),t["\u0275did"](9,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,27,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,7,"p",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["To move "])),(l()(),t["\u0275eld"](13,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](14,null,["","/",""])),(l()(),t["\u0275ted"](-1,null,[" to trash, click "])),(l()(),t["\u0275eld"](16,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Move Image"])),(l()(),t["\u0275ted"](-1,null,[". Optionally, you can pick an expiration date."])),(l()(),t["\u0275eld"](19,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](20,278528,null,0,a.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](21,{"has-error":0}),(l()(),t["\u0275eld"](22,0,null,null,1,"label",[["for","expires"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Protection expires at"])),(l()(),t["\u0275eld"](24,16777216,null,null,9,"input",[["bsDatepicker",""],["class","form-control"],["formControlName","expiresAt"],["placeholder","NOT PROTECTED"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"],[null,"keyup.esc"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,25)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,25).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,25)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,25)._compositionEnd(e.target.value)&&u),"change"===n&&(u=!1!==t["\u0275nov"](l,27).onChange(e)&&u),"keyup.esc"===n&&(u=!1!==t["\u0275nov"](l,27).hide()&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,27).onBlur()&&u),u},null,null)),t["\u0275did"](25,16384,null,0,o.e,[t.Renderer2,t.ElementRef,[2,o.b]],null,null),t["\u0275did"](26,737280,null,0,r.c,[r.a,t.ElementRef,t.Renderer2,t.ViewContainerRef,s.a],{bsConfig:[0,"bsConfig"],minDate:[1,"minDate"]},null),t["\u0275did"](27,16384,null,0,r.f,[r.c,r.j,t.Renderer2,t.ElementRef,t.ChangeDetectorRef],null,null),t["\u0275prd"](1024,null,o.o,function(l){return[l]},[r.f]),t["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,r.f]),t["\u0275did"](30,671744,null,0,o.j,[[3,o.d],[6,o.o],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,o.q,null,[o.j]),t["\u0275did"](32,16384,null,0,o.r,[[4,o.q]],null,null),t["\u0275did"](33,4210688,null,0,d.a,[[2,c.a],p.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,I)),t["\u0275did"](35,16384,null,0,a.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,S)),t["\u0275did"](37,16384,null,0,a.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](38,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](40,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.moveImage()&&t),t},m.b,m.a)),t["\u0275did"](41,114688,null,0,f.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Move Image"])),(l()(),t["\u0275eld"](43,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,g.b,g.a)),t["\u0275did"](44,49152,null,0,h.a,[a.Location,v.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,7,0,e.moveForm);var u=l(n,21,0,e.moveForm.showError("expiresAt",t["\u0275nov"](n,7)));l(n,20,0,"form-group",u),l(n,26,0,e.bsConfig,e.minDate),l(n,30,0,"expiresAt"),l(n,35,0,e.moveForm.showError("expiresAt",t["\u0275nov"](n,7),"format")),l(n,37,0,e.moveForm.showError("expiresAt",t["\u0275nov"](n,7),"expired")),l(n,41,0,e.moveForm),l(n,44,0,"Cancel",e.modalRef.hide)},function(l,n){var e=n.component;l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending),l(n,14,0,e.poolName,e.imageName),l(n,24,0,t["\u0275nov"](n,32).ngClassUntouched,t["\u0275nov"](n,32).ngClassTouched,t["\u0275nov"](n,32).ngClassPristine,t["\u0275nov"](n,32).ngClassDirty,t["\u0275nov"](n,32).ngClassValid,t["\u0275nov"](n,32).ngClassInvalid,t["\u0275nov"](n,32).ngClassPending)})}function E(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rbd-trash-move-modal",[],null,null,null,k,R)),t["\u0275did"](1,114688,null,0,b.a,[y.a,C.a,_.a,w.a],null,null)],function(l,n){l(n,1,0)},null)}var F=t["\u0275ccf"]("cd-rbd-trash-move-modal",b.a,E,{},{},[])},JBea:function(l,n,e){"use strict";e.d(n,"a",function(){return t}),e("vCyI");var t=function(){function l(){}return l.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.selectedItem=this.selection.first())},l}()},"JIi+":function(l,n,e){"use strict";var t=e("CcnG"),u=e("eajB"),i=e("lqqz"),o=e("NJnL"),a=e("pKUh"),r=e("YAQW"),s=e("Ip0R"),d=e("25BL"),c=e("uIqm"),p=e("NUGo"),m=e("S7zO"),f=e("VTlA"),g=e("ufoC"),h=e("mSOc"),v=e("wd/R"),b=e("F/XL"),y=e("F83c"),C=e("OLbh"),_=e("0+/T"),w=e("sne2"),R=e("x38r"),I=e("vCyI"),S=e("QTAa"),k=e("kvvV"),E=e("a0VL"),F=e("Fgil"),D=e("aexS"),V=e("9nlD"),T=e("VXsX"),N=e("+lcs"),P=function(){return function(l,n){this.i18n=l,this.create={permission:"create",icon:"fa-plus",name:n.CREATE},this.rename={permission:"update",icon:"fa-pencil",name:n.RENAME},this.protect={permission:"update",icon:"fa-lock",visible:function(l){return l.hasSingleSelection&&!l.first().is_protected},name:n.PROTECT},this.unprotect={permission:"update",icon:"fa-unlock",visible:function(l){return l.hasSingleSelection&&l.first().is_protected},name:n.UNPROTECT},this.clone={permission:"create",canBePrimary:function(l){return l.hasSingleSelection},disable:function(l){return!l.hasSingleSelection||l.first().cdExecuting},icon:"fa-clone",name:n.CLONE},this.copy={permission:"create",canBePrimary:function(l){return l.hasSingleSelection},disable:function(l){return!l.hasSingleSelection||l.first().cdExecuting},icon:"fa-copy",name:n.COPY},this.rollback={permission:"update",icon:"fa-undo",name:n.ROLLBACK},this.deleteSnap={permission:"delete",icon:"fa-times",disable:function(l){var n=l.first();return!l.hasSingleSelection||n.cdExecuting||n.is_protected},name:n.DELETE},this.ordering=[this.create,this.rename,this.protect,this.unprotect,this.clone,this.copy,this.rollback,this.deleteSnap]}}(),x=function(){return function(){}}(),O=function(){function l(l,n,e,t,u,i,o,a,r,s,d){var c=this;this.authStorageService=l,this.modalService=n,this.dimlessBinaryPipe=e,this.cdDatePipe=t,this.rbdService=u,this.taskManagerService=i,this.notificationService=o,this.summaryService=a,this.taskListService=r,this.i18n=s,this.actionLabels=d,this.snapshots=[],this.selection=new I.a,this.builders={"rbd/snap/create":function(l){var n=new x;return n.name=l.snapshot_name,n}},this.permission=this.authStorageService.getPermissions().rbdImage;var p=new P(this.i18n,this.actionLabels);p.create.click=function(){return c.openCreateSnapshotModal()},p.rename.click=function(){return c.openEditSnapshotModal()},p.protect.click=function(){return c.toggleProtection()},p.unprotect.click=function(){return c.toggleProtection()};var m=function(){return c.selection.first()&&encodeURIComponent(c.poolName)+"/"+encodeURIComponent(c.rbdName)+"/"+encodeURIComponent(c.selection.first().name)};p.clone.routerLink=function(){return"/block/rbd/clone/"+m()},p.copy.routerLink=function(){return"/block/rbd/copy/"+m()},p.rollback.click=function(){return c.rollbackModal()},p.deleteSnap.click=function(){return c.deleteSnapshotModal()},this.tableActions=p.ordering}return l.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"name",cellTransformation:R.a.executing,flexGrow:2},{name:this.i18n("Size"),prop:"size",flexGrow:1,cellClass:"text-right",pipe:this.dimlessBinaryPipe},{name:this.i18n("Provisioned"),prop:"disk_usage",flexGrow:1,cellClass:"text-right",pipe:this.dimlessBinaryPipe},{name:this.i18n("State"),prop:"is_protected",flexGrow:1,cellClass:"text-center",cellTemplate:this.protectTpl},{name:this.i18n("Created"),prop:"timestamp",flexGrow:1,pipe:this.cdDatePipe}]},l.prototype.ngOnChanges=function(){var l=this;this.taskListService.init(function(){return Object(b.a)(l.snapshots)},null,function(n){return l.data=n},function(){return l.data=l.snapshots},function(n){return["rbd/snap/create","rbd/snap/delete","rbd/snap/edit","rbd/snap/rollback"].includes(n.name)&&l.poolName===n.metadata.pool_name&&l.rbdName===n.metadata.image_name},function(l,n){return l.name===n.metadata.snapshot_name},this.builders)},l.prototype.openSnapshotModal=function(l,n){var e=this;void 0===n&&(n=null),this.modalRef=this.modalService.show(N.a),this.modalRef.content.poolName=this.poolName,this.modalRef.content.imageName=this.rbdName,n?this.modalRef.content.setEditing():n=this.rbdName+"_"+v().toISOString(!0),this.modalRef.content.setSnapName(n),this.modalRef.content.onSubmit.subscribe(function(n){var t=new S.a;t.name=l,t.metadata={image_name:e.rbdName,pool_name:e.poolName,snapshot_name:n},e.summaryService.addRunningTask(t),e.ngOnChanges()})},l.prototype.openCreateSnapshotModal=function(){this.openSnapshotModal("rbd/snap/create")},l.prototype.openEditSnapshotModal=function(){this.openSnapshotModal("rbd/snap/edit",this.selection.first().name)},l.prototype.toggleProtection=function(){var l=this,n=this.selection.first().name,e=this.selection.first().is_protected,t=new k.a;t.name="rbd/snap/edit",t.metadata={pool_name:this.poolName,image_name:this.rbdName,snapshot_name:n},this.rbdService.protectSnapshot(this.poolName,this.rbdName,n,!e).toPromise().then(function(){var n=new S.a;n.name=t.name,n.metadata=t.metadata,l.summaryService.addRunningTask(n),l.ngOnChanges(),l.taskManagerService.subscribe(t.name,t.metadata,function(n){l.notificationService.notifyTask(n)})})},l.prototype._asyncTask=function(l,n,e){var t=this,u=new k.a;u.name=n,u.metadata={pool_name:this.poolName,image_name:this.rbdName,snapshot_name:e},this.rbdService[l](this.poolName,this.rbdName,e).toPromise().then(function(){var l=new S.a;l.name=u.name,l.metadata=u.metadata,t.summaryService.addRunningTask(l),t.modalRef.hide(),t.ngOnChanges(),t.taskManagerService.subscribe(l.name,l.metadata,function(l){t.notificationService.notifyTask(l)})}).catch(function(){t.modalRef.content.stopLoadingSpinner()})},l.prototype.rollbackModal=function(){var l=this,n=this.selection.selected[0].name,e={titleText:this.i18n("RBD snapshot rollback"),buttonText:this.i18n("Rollback"),bodyTpl:this.rollbackTpl,bodyData:{snapName:this.poolName+"/"+this.rbdName+"@"+n},onSubmit:function(){l._asyncTask("rollbackSnapshot","rbd/snap/rollback",n)}};this.modalRef=this.modalService.show(C.a,{initialState:e})},l.prototype.deleteSnapshotModal=function(){var l=this,n=this.selection.selected[0].name;this.modalRef=this.modalService.show(_.a,{initialState:{itemDescription:this.i18n("RBD snapshot"),itemNames:[n],submitAction:function(){return l._asyncTask("deleteSnapshot","rbd/snap/delete",n)}}})},l.prototype.updateSelection=function(l){this.selection=l},l}(),q=e("DQlY"),M=e("Jm/i"),A=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function B(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","label label-success"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["PROTECTED"]))],null,null)}function j(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","label label-info"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["UNPROTECTED"]))],null,null)}function U(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,B)),t["\u0275did"](1,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,j)),t["\u0275did"](3,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,n.context.value),l(n,3,0,!n.context.value)},null)}function G(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["You are about to rollback"])),(l()(),t["\u0275eld"](2,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),t["\u0275ted"](3,null,["",""])),(l()(),t["\u0275ted"](-1,null,[".\n"]))],null,function(l,n){l(n,3,0,n.context.$implicit.snapName)})}function L(l){return t["\u0275vid"](0,[t["\u0275qud"](402653184,1,{nameTpl:0}),t["\u0275qud"](402653184,2,{protectTpl:0}),t["\u0275qud"](402653184,3,{rollbackTpl:0}),(l()(),t["\u0275eld"](3,0,null,null,3,"cd-table",[["columnMode","flex"],["selectionType","single"]],null,[[null,"updateSelection"]],function(l,n,e){var t=!0;return"updateSelection"===n&&(t=!1!==l.component.updateSelection(e)&&t),t},d.b,d.a)),t["\u0275did"](4,2867200,null,0,c.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],selectionType:[3,"selectionType"]},{updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](5,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,p.b,p.a)),t["\u0275did"](6,114688,null,0,m.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),t["\u0275and"](0,[[2,2],["protectTpl",2]],null,0,null,U)),(l()(),t["\u0275and"](0,[[3,2],["rollbackTpl",2]],null,0,null,G))],function(l,n){var e=n.component;l(n,4,0,e.data,e.columns,"flex","single"),l(n,6,0,e.permission,e.selection,e.tableActions)},null)}var z=e("EFGL"),W=e("aAWM"),$=e("aXbf"),X=e("o8EM"),Y=e("nSDx"),K=e("o4+5"),J=e("JBea");e.d(n,"b",function(){return Z}),e.d(n,"c",function(){return dl}),e.d(n,"a",function(){return pl});var Z=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Q(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,4,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Only available for RBD images with "])),(l()(),t["\u0275eld"](2,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["fast-diff"])),(l()(),t["\u0275ted"](-1,null,[" enabled"]))],null,null)}function H(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[["class","badge badge-pill badge-primary margin-right-sm"]],null,null,null,null,null)),(l()(),t["\u0275ted"](2,null,["",""]))],null,function(l,n){l(n,2,0,n.context.$implicit)})}function ll(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,16777216,null,null,2,"span",[["class","text-muted"],["placement","top"]],[[1,"aria-describedby",0]],null,null,null,null)),t["\u0275did"](2,212992,null,0,u.c,[t.ViewContainerRef,i.a,u.a,t.ElementRef,t.Renderer2,o.a],{tooltip:[0,"tooltip"],placement:[1,"placement"]},null),(l()(),t["\u0275ted"](-1,null,["N/A"]))],function(l,n){l(n,2,0,t["\u0275nov"](n.parent.parent,5),"top")},function(l,n){l(n,1,0,t["\u0275nov"](n,2).ariaDescribedby)})}function nl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "])),t["\u0275ppd"](2,1)],null,function(l,n){var e=n.component,u=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent,2),e.selectedItem.disk_usage));l(n,1,0,u)})}function el(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,16777216,null,null,2,"span",[["class","text-muted"],["placement","top"]],[[1,"aria-describedby",0]],null,null,null,null)),t["\u0275did"](2,212992,null,0,u.c,[t.ViewContainerRef,i.a,u.a,t.ElementRef,t.Renderer2,o.a],{tooltip:[0,"tooltip"],placement:[1,"placement"]},null),(l()(),t["\u0275ted"](-1,null,["N/A"]))],function(l,n){l(n,2,0,t["\u0275nov"](n.parent.parent,5),"top")},function(l,n){l(n,1,0,t["\u0275nov"](n,2).ariaDescribedby)})}function tl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "])),t["\u0275ppd"](2,1)],null,function(l,n){var e=n.component,u=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent,2),e.selectedItem.total_disk_usage));l(n,1,0,u)})}function ul(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[""," /"," @",""]))],null,function(l,n){var e=n.component;l(n,1,0,e.selectedItem.parent.pool_name,e.selectedItem.parent.image_name,e.selectedItem.parent.snap_name)})}function il(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["-"]))],null,null)}function ol(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,110,"tabset",[],[[2,"tab-container",null]],null,null,a.b,a.a)),t["\u0275did"](1,180224,null,0,r.d,[r.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](2,0,null,0,99,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](3,212992,null,0,r.b,[r.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](4,0,null,null,97,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,96,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Name"])),(l()(),t["\u0275eld"](9,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](10,null,["",""])),(l()(),t["\u0275eld"](11,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Pool"])),(l()(),t["\u0275eld"](14,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](15,null,["",""])),(l()(),t["\u0275eld"](16,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Data Pool"])),(l()(),t["\u0275eld"](19,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](20,null,["",""])),t["\u0275ppd"](21,1),(l()(),t["\u0275eld"](22,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](23,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Created"])),(l()(),t["\u0275eld"](25,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](26,null,["",""])),t["\u0275ppd"](27,1),(l()(),t["\u0275eld"](28,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](29,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Size"])),(l()(),t["\u0275eld"](31,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](32,null,["",""])),t["\u0275ppd"](33,1),(l()(),t["\u0275eld"](34,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](35,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Objects"])),(l()(),t["\u0275eld"](37,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](38,null,["",""])),t["\u0275ppd"](39,1),(l()(),t["\u0275eld"](40,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](41,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Object size"])),(l()(),t["\u0275eld"](43,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](44,null,["",""])),t["\u0275ppd"](45,1),(l()(),t["\u0275eld"](46,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](47,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Features"])),(l()(),t["\u0275eld"](49,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,H)),t["\u0275did"](51,278528,null,0,s.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275eld"](52,0,null,null,7,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](53,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Provisioned"])),(l()(),t["\u0275eld"](55,0,null,null,4,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,ll)),t["\u0275did"](57,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,nl)),t["\u0275did"](59,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](60,0,null,null,7,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](61,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Total provisioned"])),(l()(),t["\u0275eld"](63,0,null,null,4,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,el)),t["\u0275did"](65,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,tl)),t["\u0275did"](67,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](68,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](69,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Striping unit"])),(l()(),t["\u0275eld"](71,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](72,null,["",""])),t["\u0275ppd"](73,1),(l()(),t["\u0275eld"](74,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](75,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Striping count"])),(l()(),t["\u0275eld"](77,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](78,null,["",""])),(l()(),t["\u0275eld"](79,0,null,null,7,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](80,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Parent"])),(l()(),t["\u0275eld"](82,0,null,null,4,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,ul)),t["\u0275did"](84,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,il)),t["\u0275did"](86,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](87,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](88,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Block name prefix"])),(l()(),t["\u0275eld"](90,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](91,null,["",""])),(l()(),t["\u0275eld"](92,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](93,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Order"])),(l()(),t["\u0275eld"](95,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](96,null,["",""])),(l()(),t["\u0275eld"](97,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](98,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Format Version"])),(l()(),t["\u0275eld"](100,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](101,null,["",""])),(l()(),t["\u0275eld"](102,0,null,0,4,"tab",[["heading","Snapshots"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](103,212992,null,0,r.b,[r.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](104,0,null,null,2,"cd-rbd-snapshot-list",[],null,null,null,L,A)),t["\u0275prd"](131584,null,f.a,f.a,[g.a,h.a]),t["\u0275did"](106,638976,null,0,O,[D.a,q.b,F.a,E.a,y.a,T.a,V.a,h.a,f.a,M.a,w.b],{snapshots:[0,"snapshots"],poolName:[1,"poolName"],rbdName:[2,"rbdName"]},null),(l()(),t["\u0275eld"](107,0,null,0,3,"tab",[["heading","Configuration"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](108,212992,null,0,r.b,[r.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](109,0,null,null,1,"cd-rbd-configuration-table",[],null,null,null,z.b,z.a)),t["\u0275did"](110,638976,null,0,W.a,[$.a,X.a,M.a],{data:[0,"data"]},null)],function(l,n){var e=n.component;l(n,3,0,"Details"),l(n,51,0,e.selectedItem.features_name),l(n,57,0,-1===(null==e.selectedItem.features_name?null:e.selectedItem.features_name.indexOf("fast-diff"))),l(n,59,0,-1!==(null==e.selectedItem.features_name?null:e.selectedItem.features_name.indexOf("fast-diff"))),l(n,65,0,-1===(null==e.selectedItem.features_name?null:e.selectedItem.features_name.indexOf("fast-diff"))),l(n,67,0,-1!==(null==e.selectedItem.features_name?null:e.selectedItem.features_name.indexOf("fast-diff"))),l(n,84,0,e.selectedItem.parent),l(n,86,0,!e.selectedItem.parent),l(n,103,0,"Snapshots"),l(n,106,0,e.selectedItem.snapshots,e.selectedItem.pool_name,e.selectedItem.name),l(n,108,0,"Configuration"),l(n,110,0,e.selectedItem.configuration)},function(l,n){var e=n.component;l(n,0,0,t["\u0275nov"](n,1).clazz),l(n,2,0,t["\u0275nov"](n,3).id,t["\u0275nov"](n,3).active,t["\u0275nov"](n,3).addClass),l(n,10,0,e.selectedItem.name),l(n,15,0,e.selectedItem.pool_name);var u=t["\u0275unv"](n,20,0,l(n,21,0,t["\u0275nov"](n.parent,0),e.selectedItem.data_pool));l(n,20,0,u);var i=t["\u0275unv"](n,26,0,l(n,27,0,t["\u0275nov"](n.parent,1),e.selectedItem.timestamp));l(n,26,0,i);var o=t["\u0275unv"](n,32,0,l(n,33,0,t["\u0275nov"](n.parent,2),e.selectedItem.size));l(n,32,0,o);var a=t["\u0275unv"](n,38,0,l(n,39,0,t["\u0275nov"](n.parent,3),e.selectedItem.num_objs));l(n,38,0,a);var r=t["\u0275unv"](n,44,0,l(n,45,0,t["\u0275nov"](n.parent,2),e.selectedItem.obj_size));l(n,44,0,r);var s=t["\u0275unv"](n,72,0,l(n,73,0,t["\u0275nov"](n.parent,2),e.selectedItem.stripe_unit));l(n,72,0,s),l(n,78,0,e.selectedItem.stripe_count),l(n,91,0,e.selectedItem.block_name_prefix),l(n,96,0,e.selectedItem.order),l(n,101,0,e.selection.image_format),l(n,102,0,t["\u0275nov"](n,103).id,t["\u0275nov"](n,103).active,t["\u0275nov"](n,103).addClass),l(n,107,0,t["\u0275nov"](n,108).id,t["\u0275nov"](n,108).active,t["\u0275nov"](n,108).addClass)})}function al(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](1,16777216,null,null,2,"strong",[["tooltip","This setting overrides the global value"]],[[1,"aria-describedby",0]],null,null,null,null)),t["\u0275did"](2,212992,null,0,u.c,[t.ViewContainerRef,i.a,u.a,t.ElementRef,t.Renderer2,o.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275ted"](-1,null,["Image"])),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,2,0,"This setting overrides the global value")},function(l,n){l(n,1,0,t["\u0275nov"](n,2).ariaDescribedby)})}function rl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,16777216,null,null,2,"span",[["tooltip","This is the global value. No value for this option has been set for this image."]],[[1,"aria-describedby",0]],null,null,null,null)),t["\u0275did"](1,212992,null,0,u.c,[t.ViewContainerRef,i.a,u.a,t.ElementRef,t.Renderer2,o.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275ted"](-1,null,["Global"])),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,"This is the global value. No value for this option has been set for this image.")},function(l,n){l(n,0,0,t["\u0275nov"](n,1).ariaDescribedby)})}function sl(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,al)),t["\u0275did"](1,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(l()(),t["\u0275and"](0,[["global",2]],null,0,null,rl))],function(l,n){l(n,1,0,n.context.value-0,t["\u0275nov"](n,2))},null)}function dl(l){return t["\u0275vid"](0,[t["\u0275pid"](0,Y.a,[]),t["\u0275pid"](0,E.a,[s.DatePipe]),t["\u0275pid"](0,F.a,[$.a]),t["\u0275pid"](0,K.a,[$.a]),t["\u0275qud"](402653184,1,{poolConfigurationSourceTpl:0}),(l()(),t["\u0275and"](0,[["usageNotAvailableTooltipTpl",2]],null,0,null,Q)),(l()(),t["\u0275and"](16777216,null,null,1,null,ol)),t["\u0275did"](7,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](0,[[1,2],["poolConfigurationSourceTpl",2]],null,0,null,sl))],function(l,n){var e=n.component;l(n,7,0,null==e.selection?null:e.selection.hasSingleSelection)},null)}function cl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rbd-details",[],null,null,null,dl,Z)),t["\u0275did"](1,573440,null,0,J.a,[],null,null)],null,null)}var pl=t["\u0275ccf"]("cd-rbd-details",J.a,cl,{selection:"selection",images:"images"},{},[])},L4us:function(l,n,e){"use strict";var t=e("gIcY"),u=(e("XED3"),e("QFaf")),i=e("kvvV"),o=(e("kn/O"),function(){return function(){}}());e.d(n,"a",function(){return a});var a=function(){function l(l,n,e){this.modalRef=l,this.rbdMirroringService=n,this.taskWrapper=e,this.bsConfig={containerClass:"theme-default"},this.createForm()}return l.prototype.createForm=function(){this.editPeerForm=new u.a({clusterName:new t.i("",{validators:[t.A.required,this.validateClusterName]}),clientID:new t.i("",{validators:[t.A.required,this.validateClientID]}),monAddr:new t.i("",{validators:[this.validateMonAddr]}),key:new t.i("",{validators:[this.validateKey]})})},l.prototype.ngOnInit=function(){var l=this;this.pattern=this.poolName+"/"+this.peerUUID,"edit"===this.mode&&this.rbdMirroringService.getPeer(this.poolName,this.peerUUID).subscribe(function(n){l.setResponse(n)})},l.prototype.validateClusterName=function(l){if(!l.value.match(/^[\w\-_]*$/))return{invalidClusterName:{value:l.value}}},l.prototype.validateClientID=function(l){if(!l.value.match(/^(?!client\.)[\w\-_.]*$/))return{invalidClientID:{value:l.value}}},l.prototype.validateMonAddr=function(l){if(!l.value.match(/^[,; ]*([\w.\-_\[\]]+(:[\d]+)?[,; ]*)*$/))return{invalidMonAddr:{value:l.value}}},l.prototype.validateKey=function(l){try{if(""===l.value||atob(l.value))return null}catch(n){}return{invalidKey:{value:l.value}}},l.prototype.setResponse=function(l){this.response=l,this.editPeerForm.get("clusterName").setValue(l.cluster_name),this.editPeerForm.get("clientID").setValue(l.client_id),this.editPeerForm.get("monAddr").setValue(l.mon_host),this.editPeerForm.get("key").setValue(l.key)},l.prototype.update=function(){var l=this,n=new o;n.cluster_name=this.editPeerForm.getValue("clusterName"),n.client_id=this.editPeerForm.getValue("clientID"),n.mon_host=this.editPeerForm.getValue("monAddr"),n.key=this.editPeerForm.getValue("key"),this.taskWrapper.wrapTaskAroundCall("edit"===this.mode?{task:new i.a("rbd/mirroring/peer/edit",{pool_name:this.poolName}),call:this.rbdMirroringService.updatePeer(this.poolName,this.peerUUID,n)}:{task:new i.a("rbd/mirroring/peer/add",{pool_name:this.poolName}),call:this.rbdMirroringService.addPeer(this.poolName,n)}).subscribe(void 0,function(){return l.editPeerForm.setErrors({cdSubmitButton:!0})},function(){l.rbdMirroringService.refresh(),l.modalRef.hide()})},l}()},MyVl:function(l,n,e){"use strict";var t,u=e("CcnG"),i=e("gIcY"),o=e("LvDl"),a=e("svcd"),r=e("15JJ"),s=(e("Ekvf"),e("F83c"),e("sne2"),e("QFaf")),d=e("PhyI"),c=e("kvvV"),p=(e("Fgil"),e("aexS"),e("aXbf"),e("kn/O"),e("u0yg")),m=function(){return function(){this.features=[]}}(),f=function(){return function(){this.features=[]}}(),g=e("mrSG"),h=function(l){function n(){var n=null!==l&&l.apply(this,arguments)||this;return n.features=[],n}return g.__extends(n,l),n}(function(){return function(){}}()),v=function(){return function(){this.features=[]}}();!function(l){l.editing="editing",l.cloning="cloning",l.copying="copying"}(t||(t={})),e.d(n,"a",function(){return b});var b=function(){function l(l,n,e,i,o,r,s,d,c,p){this.authStorageService=l,this.route=n,this.poolService=e,this.rbdService=i,this.formatter=o,this.taskWrapper=r,this.dimlessBinaryPipe=s,this.i18n=d,this.actionLabels=c,this.router=p,this.pools=null,this.allPools=null,this.dataPools=null,this.allDataPools=null,this.featuresList=[],this.initializeConfigData=new u.EventEmitter,this.advancedEnabled=!1,this.rbdFormMode=t,this.defaultObjectSize="4 MiB",this.objectSizes=["4 KiB","8 KiB","16 KiB","32 KiB","64 KiB","128 KiB","256 KiB","512 KiB","1 MiB","2 MiB","4 MiB","8 MiB","16 MiB","32 MiB"],this.rbdImage=new a.a,this.poolPermission=this.authStorageService.getPermissions().pool,this.resource=this.i18n("RBD"),this.features={"deep-flatten":{desc:this.i18n("Deep flatten"),requires:null,allowEnable:!1,allowDisable:!0},layering:{desc:this.i18n("Layering"),requires:null,allowEnable:!1,allowDisable:!1},"exclusive-lock":{desc:this.i18n("Exclusive lock"),requires:null,allowEnable:!0,allowDisable:!0},"object-map":{desc:this.i18n("Object map (requires exclusive-lock)"),requires:"exclusive-lock",allowEnable:!0,allowDisable:!0,initDisabled:!0},journaling:{desc:this.i18n("Journaling (requires exclusive-lock)"),requires:"exclusive-lock",allowEnable:!0,allowDisable:!0,initDisabled:!0},"fast-diff":{desc:this.i18n("Fast diff (interlocked with object-map)"),requires:"object-map",allowEnable:!0,allowDisable:!0,interlockedWith:"object-map",initDisabled:!0}},this.featuresList=this.objToArray(this.features),this.createForm()}return l.prototype.objToArray=function(l){return o.map(l,function(l,n){return Object.assign(l,{key:n})})},l.prototype.createForm=function(){this.rbdForm=new s.a({parent:new i.i(""),name:new i.i("",{validators:[i.A.required,i.A.pattern(/^[^@\/]+?$/)]}),pool:new i.i(null,{validators:[i.A.required]}),useDataPool:new i.i(!1),dataPool:new i.i(null),size:new i.i(null,{updateOn:"blur"}),obj_size:new i.i(this.defaultObjectSize),features:new s.a(this.featuresList.reduce(function(l,n){return l[n.key]=new i.i({value:!1,disabled:!!n.initDisabled}),l},{})),stripingUnit:new i.i(null),stripingCount:new i.i(null,{updateOn:"blur"})},this.validateRbdForm(this.formatter))},l.prototype.disableForEdit=function(){var l=this;this.rbdForm.get("parent").disable(),this.rbdForm.get("pool").disable(),this.rbdForm.get("useDataPool").disable(),this.rbdForm.get("dataPool").disable(),this.rbdForm.get("obj_size").disable(),this.rbdForm.get("stripingUnit").disable(),this.rbdForm.get("stripingCount").disable(),this.rbdImage.subscribe(function(n){n.image_format===p.a.V1&&(l.rbdForm.get("deep-flatten").disable(),l.rbdForm.get("layering").disable(),l.rbdForm.get("exclusive-lock").disable())})},l.prototype.disableForClone=function(){this.rbdForm.get("parent").disable(),this.rbdForm.get("size").disable()},l.prototype.disableForCopy=function(){this.rbdForm.get("parent").disable(),this.rbdForm.get("size").disable()},l.prototype.ngOnInit=function(){var l=this;this.router.url.startsWith("/block/rbd/edit")?(this.mode=this.rbdFormMode.editing,this.action=this.actionLabels.EDIT,this.disableForEdit()):this.router.url.startsWith("/block/rbd/clone")?(this.mode=this.rbdFormMode.cloning,this.disableForClone(),this.action=this.actionLabels.CLONE):this.router.url.startsWith("/block/rbd/copy")?(this.mode=this.rbdFormMode.copying,this.action=this.actionLabels.COPY,this.disableForCopy()):this.action=this.actionLabels.CREATE,this.mode===this.rbdFormMode.editing||this.mode===this.rbdFormMode.cloning||this.mode===this.rbdFormMode.copying?this.route.params.subscribe(function(n){var e=decodeURIComponent(n.pool),t=decodeURIComponent(n.name);n.snap&&(l.snapName=decodeURIComponent(n.snap)),l.rbdService.get(e,t).subscribe(function(n){l.setResponse(n,l.snapName),l.rbdImage.next(n)})}):this.rbdService.defaultFeatures().subscribe(function(n){l.setFeatures(n)}),this.mode!==this.rbdFormMode.editing&&this.poolPermission.read&&this.poolService.list(["pool_name","type","flags_names","application_metadata"]).then(function(n){for(var e=[],t=[],u=0,i=n;u<i.length;u++){var a=i[u];-1!==o.indexOf(a.application_metadata,"rbd")&&(a.pool_name.includes("/")||("replicated"===a.type?(e.push(a),t.push(a)):"erasure"===a.type&&-1!==a.flags_names.indexOf("ec_overwrites")&&t.push(a)))}if(l.pools=e,l.allPools=e,l.dataPools=t,l.allDataPools=t,1===l.pools.length){var r=l.pools[0].pool_name;l.rbdForm.get("pool").setValue(r),l.onPoolChange(r)}}),o.each(this.features,function(n){l.rbdForm.get("features").get(n.key).valueChanges.subscribe(function(e){return l.featureFormUpdate(n.key,e)})})},l.prototype.onPoolChange=function(l){var n=this.allDataPools.filter(function(n){return n.pool_name!==l});this.rbdForm.getValue("dataPool")===l&&this.rbdForm.get("dataPool").setValue(null),this.dataPools=n},l.prototype.onUseDataPoolChange=function(){this.rbdForm.getValue("useDataPool")||(this.rbdForm.get("dataPool").setValue(null),this.onDataPoolChange(null))},l.prototype.onDataPoolChange=function(l){var n=this.allPools.filter(function(n){return n.pool_name!==l});this.rbdForm.getValue("pool")===l&&this.rbdForm.get("pool").setValue(null),this.pools=n},l.prototype.validateRbdForm=function(l){var n=this;return function(e){var t=e.get("useDataPool"),u=e.get("dataPool"),i=null;t.value&&null==u.value&&(i={required:!0}),u.setErrors(i);var o=e.get("size"),a=e.get("obj_size"),r=l.toBytes(null!=a.value?a.value:n.defaultObjectSize),s=e.get("stripingCount"),d=null!=s.value?s.value:1,c=null;null===o.value?c={required:!0}:d*r>l.toBytes(o.value)&&(c={invalidSizeObject:!0}),o.setErrors(c);var p=e.get("stripingUnit"),m=null;null===p.value&&null!==s.value?m={required:!0}:null!==p.value&&l.toBytes(p.value)>r&&(m={invalidStripingUnit:!0}),p.setErrors(m);var f=null;return null===s.value&&null!==p.value?f={required:!0}:d<1&&(f={min:!0}),s.setErrors(f),null}},l.prototype.getDependendChildFeatures=function(l){return o.filter(this.features,function(n){return n.requires===l})||[]},l.prototype.deepBoxCheck=function(l,n){var e=this;this.getDependendChildFeatures(l).forEach(function(l){var t=e.rbdForm.get(l.key);n?t.enable({emitEvent:!1}):(t.disable({emitEvent:!1}),t.setValue(!1,{emitEvent:!1}),e.deepBoxCheck(l.key,n));var u=e.rbdForm.get("features");e.mode===e.rbdFormMode.editing&&u.get(l.key).enabled&&((-1===e.response.features_name.indexOf(l.key)||l.allowDisable)&&(-1!==e.response.features_name.indexOf(l.key)||l.allowEnable)||u.get(l.key).disable())})},l.prototype.interlockCheck=function(l,n){var e=this,t=this.featuresList.find(function(n){return n.key===l});if(this.response){var u=null!=t.interlockedWith,i=this.featuresList.find(function(l){return l.interlockedWith===t.key}),a=!!this.response.features_name.find(function(l){return l===t.key});if(u){if(a!==!!this.response.features_name.find(function(l){return l===t.interlockedWith}))return}else if(i&&!!this.response.features_name.find(function(l){return l===i.key})!==a)return}n?o.filter(this.features,function(n){return n.interlockedWith===l}).forEach(function(l){return e.rbdForm.get(l.key).setValue(!0,{emitEvent:!1})}):t.interlockedWith&&this.rbdForm.get("features").get(t.interlockedWith).setValue(!1)},l.prototype.featureFormUpdate=function(l,n){if(n){var e=this.features[l].requires;if(e&&!this.rbdForm.getValue(e))return void this.rbdForm.get("features."+l).setValue(!1)}this.deepBoxCheck(l,n),this.interlockCheck(l,n)},l.prototype.setFeatures=function(l){var n=this,e=this.rbdForm.get("features");o.forIn(this.features,function(t){-1!==l.indexOf(t.key)&&e.get(t.key).setValue(!0),n.featureFormUpdate(t.key,e.get(t.key).value)})},l.prototype.setResponse=function(l,n){if(this.response=l,this.mode===this.rbdFormMode.cloning)this.rbdForm.get("parent").setValue(l.pool_name+"/"+l.name+"@"+n);else if(this.mode===this.rbdFormMode.copying)n?this.rbdForm.get("parent").setValue(l.pool_name+"/"+l.name+"@"+n):this.rbdForm.get("parent").setValue(l.pool_name+"/"+l.name);else if(l.parent){var e=l.parent;this.rbdForm.get("parent").setValue(e.pool_name+"/"+e.image_name+"@"+e.snap_name)}this.mode===this.rbdFormMode.editing&&this.rbdForm.get("name").setValue(l.name),this.rbdForm.get("pool").setValue(l.pool_name),l.data_pool&&(this.rbdForm.get("useDataPool").setValue(!0),this.rbdForm.get("dataPool").setValue(l.data_pool)),this.rbdForm.get("size").setValue(this.dimlessBinaryPipe.transform(l.size)),this.rbdForm.get("obj_size").setValue(this.dimlessBinaryPipe.transform(l.obj_size)),this.setFeatures(l.features_name),this.rbdForm.get("stripingUnit").setValue(this.dimlessBinaryPipe.transform(l.stripe_unit)),this.rbdForm.get("stripingCount").setValue(l.stripe_count),this.initializeConfigData.emit({initialData:this.response.configuration,sourceType:d.a.image})},l.prototype.createRequest=function(){var l=this,n=new h;return n.pool_name=this.rbdForm.getValue("pool"),n.name=this.rbdForm.getValue("name"),n.size=this.formatter.toBytes(this.rbdForm.getValue("size")),n.obj_size=this.formatter.toBytes(this.rbdForm.getValue("obj_size")),o.forIn(this.features,function(e){l.rbdForm.getValue(e.key)&&n.features.push(e.key)}),n.stripe_unit=this.formatter.toBytes(this.rbdForm.getValue("stripingUnit")),n.stripe_count=this.rbdForm.getValue("stripingCount"),n.data_pool=this.rbdForm.getValue("dataPool"),n.configuration=this.getDirtyConfigurationValues(),n},l.prototype.createAction=function(){var l=this.createRequest();return this.taskWrapper.wrapTaskAroundCall({task:new c.a("rbd/create",{pool_name:l.pool_name,image_name:l.name}),call:this.rbdService.create(l)})},l.prototype.editRequest=function(){var l=this,n=new v;return n.name=this.rbdForm.getValue("name"),n.size=this.formatter.toBytes(this.rbdForm.getValue("size")),o.forIn(this.features,function(e){l.rbdForm.getValue(e.key)&&n.features.push(e.key)}),n.configuration=this.getDirtyConfigurationValues(),n},l.prototype.cloneRequest=function(){var l=this,n=new m;return n.child_pool_name=this.rbdForm.getValue("pool"),n.child_image_name=this.rbdForm.getValue("name"),n.obj_size=this.formatter.toBytes(this.rbdForm.getValue("obj_size")),o.forIn(this.features,function(e){l.rbdForm.getValue(e.key)&&n.features.push(e.key)}),n.stripe_unit=this.formatter.toBytes(this.rbdForm.getValue("stripingUnit")),n.stripe_count=this.rbdForm.getValue("stripingCount"),n.data_pool=this.rbdForm.getValue("dataPool"),n.configuration=this.getDirtyConfigurationValues(!0,d.a.image),n},l.prototype.editAction=function(){return this.taskWrapper.wrapTaskAroundCall({task:new c.a("rbd/edit",{pool_name:this.response.pool_name,image_name:this.response.name}),call:this.rbdService.update(this.response.pool_name,this.response.name,this.editRequest())})},l.prototype.cloneAction=function(){var l=this.cloneRequest();return this.taskWrapper.wrapTaskAroundCall({task:new c.a("rbd/clone",{parent_pool_name:this.response.pool_name,parent_image_name:this.response.name,parent_snap_name:this.snapName,child_pool_name:l.child_pool_name,child_image_name:l.child_image_name}),call:this.rbdService.cloneSnapshot(this.response.pool_name,this.response.name,this.snapName,l)})},l.prototype.copyRequest=function(){var l=this,n=new f;return this.snapName&&(n.snapshot_name=this.snapName),n.dest_pool_name=this.rbdForm.getValue("pool"),n.dest_image_name=this.rbdForm.getValue("name"),n.obj_size=this.formatter.toBytes(this.rbdForm.getValue("obj_size")),o.forIn(this.features,function(e){l.rbdForm.getValue(e.key)&&n.features.push(e.key)}),n.stripe_unit=this.formatter.toBytes(this.rbdForm.getValue("stripingUnit")),n.stripe_count=this.rbdForm.getValue("stripingCount"),n.data_pool=this.rbdForm.getValue("dataPool"),n.configuration=this.getDirtyConfigurationValues(!0,d.a.image),n},l.prototype.copyAction=function(){var l=this.copyRequest();return this.taskWrapper.wrapTaskAroundCall({task:new c.a("rbd/copy",{src_pool_name:this.response.pool_name,src_image_name:this.response.name,dest_pool_name:l.dest_pool_name,dest_image_name:l.dest_image_name}),call:this.rbdService.copy(this.response.pool_name,this.response.name,l)})},l.prototype.submit=function(){var l=this;this.mode||this.rbdImage.next("create"),this.rbdImage.complete(),this.rbdImage.pipe(Object(r.a)(function(){return l.mode===l.rbdFormMode.editing?l.editAction():l.mode===l.rbdFormMode.cloning?l.cloneAction():l.mode===l.rbdFormMode.copying?l.copyAction():l.createAction()})).subscribe(function(){},function(){return l.rbdForm.setErrors({cdSubmitButton:!0})},function(){return l.router.navigate(["/block/rbd"])})},l}()},OcYo:function(l,n,e){"use strict";e.d(n,"a",function(){return t});var t=function(){function l(l,n,e){this.elementRef=l,this.renderer=n,this.toastr=e}return l.prototype.ngOnInit=function(){var l=this.renderer.createElement("i");this.renderer.addClass(l,"icon-prepend"),this.renderer.addClass(l,"fa"),this.renderer.addClass(l,"fa-clipboard"),this.renderer.appendChild(this.elementRef.nativeElement,l)},l.prototype.getInputElement=function(){return document.getElementById(this.cdCopy2ClipboardButton)},l.prototype.onClick=function(){try{var l=document.createElement("input");l.value=this.getInputElement().value,document.body.appendChild(l),l.select(),document.execCommand("copy"),document.body.removeChild(l),this.toastr.success("Copied text to the clipboard successfully.")}catch(n){this.toastr.error("Failed to copy text to the clipboard.")}},l}()},PhyI:function(l,n,e){"use strict";e.d(n,"a",function(){return t}),e.d(n,"b",function(){return u});var t=function(l){return l[l.global=0]="global",l[l.pool=1]="pool",l[l.image=2]="image",l}({}),u=function(l){return l[l.bps=0]="bps",l[l.iops=1]="iops",l[l.milliseconds=2]="milliseconds",l}({})},RIVN:function(l,n,e){"use strict";var t=e("CcnG"),u=e("C6Ij"),i=e("AWcq"),o=e("Ip0R"),a=function(){function l(){}return l.prototype.transform=function(l){return"warning"===l?"label label-warning":"error"===l?"label label-danger":"success"===l?"label label-success":"label label-info"},l}(),r=e("25BL"),s=e("uIqm"),d=e("XED3"),c=e("85J/"),p=function(){function l(l,n,e){this.rbdMirroringService=l,this.cephShortVersionPipe=n,this.i18n=e}return l.prototype.ngOnInit=function(){var l=this;this.columns=[{prop:"instance_id",name:this.i18n("Instance"),flexGrow:2},{prop:"id",name:this.i18n("ID"),flexGrow:2},{prop:"server_hostname",name:this.i18n("Hostname"),flexGrow:2},{prop:"version",name:this.i18n("Version"),pipe:this.cephShortVersionPipe,flexGrow:2},{prop:"health",name:this.i18n("Health"),cellTemplate:this.healthTmpl,flexGrow:1}],this.subs=this.rbdMirroringService.subscribeSummary(function(n){n&&(l.data=n.content_data.daemons)})},l.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},l.prototype.refresh=function(){this.rbdMirroringService.refresh()},l}(),m=e("Jm/i"),f=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function g(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{ngClass:[0,"ngClass"]},null),t["\u0275ppd"](2,1),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent,0),n.context.row.health_color));l(n,1,0,e)},function(l,n){l(n,3,0,n.context.value)})}function h(l){return t["\u0275vid"](0,[t["\u0275pid"](0,a,[]),t["\u0275qud"](402653184,1,{healthTmpl:0}),(l()(),t["\u0275eld"](2,0,null,null,1,"cd-table",[["columnMode","flex"]],null,[[null,"fetchData"]],function(l,n,e){var t=!0;return"fetchData"===n&&(t=!1!==l.component.refresh()&&t),t},r.b,r.a)),t["\u0275did"](3,2867200,null,0,s.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"]},{fetchData:"fetchData"}),(l()(),t["\u0275and"](0,[[1,2],["healthTmpl",2]],null,0,null,g))],function(l,n){var e=n.component;l(n,3,0,e.data,e.columns,"flex",0)},null)}var v=e("NUGo"),b=e("S7zO"),y=e("6blF"),C=e("0+/T"),_=e("vCyI"),w=e("kvvV"),R=e("aexS"),I=e("kn/O"),S=e("aa9H"),k=e("L4us"),E=function(){function l(l,n,e,t,u){var i=this;this.authStorageService=l,this.rbdMirroringService=n,this.modalService=e,this.taskWrapper=t,this.i18n=u,this.selection=new _.a,this.data=[],this.permission=this.authStorageService.getPermissions().rbdMirroring;var o={permission:"update",icon:"fa-edit",click:function(){return i.editModeModal()},name:this.i18n("Edit Mode"),canBePrimary:function(){return!0}},a={permission:"create",icon:"fa-plus",name:this.i18n("Add Peer"),click:function(){return i.editPeersModal("add")},disable:function(){return!i.selection.first()||"disabled"===i.selection.first().mirror_mode},visible:function(){return!i.getPeerUUID()},canBePrimary:function(){return!1}},r={permission:"update",icon:"fa-exchange",name:this.i18n("Edit Peer"),click:function(){return i.editPeersModal("edit")},visible:function(){return!!i.getPeerUUID()}},s={permission:"delete",icon:"fa-times",name:this.i18n("Delete Peer"),click:function(){return i.deletePeersModal()},visible:function(){return!!i.getPeerUUID()}};this.tableActions=[o,a,r,s]}return l.prototype.ngOnInit=function(){var l=this;this.columns=[{prop:"name",name:this.i18n("Name"),flexGrow:2},{prop:"mirror_mode",name:this.i18n("Mode"),flexGrow:2},{prop:"leader_id",name:this.i18n("Leader"),flexGrow:2},{prop:"image_local_count",name:this.i18n("# Local"),flexGrow:2},{prop:"image_remote_count",name:this.i18n("# Remote"),flexGrow:2},{prop:"health",name:this.i18n("Health"),cellTemplate:this.healthTmpl,flexGrow:1}],this.subs=this.rbdMirroringService.subscribeSummary(function(n){n&&(l.data=n.content_data.pools)})},l.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},l.prototype.refresh=function(){this.rbdMirroringService.refresh()},l.prototype.editModeModal=function(){var l={poolName:this.selection.first().name};this.modalRef=this.modalService.show(S.a,{initialState:l})},l.prototype.editPeersModal=function(l){var n={poolName:this.selection.first().name,mode:l};"edit"===l&&(n.peerUUID=this.getPeerUUID()),this.modalRef=this.modalService.show(k.a,{initialState:n})},l.prototype.deletePeersModal=function(){var l=this,n=this.selection.first().name,e=this.getPeerUUID();this.modalRef=this.modalService.show(C.a,{initialState:{itemDescription:this.i18n("mirror peer"),itemNames:[n+" ("+e+")"],submitActionObservable:function(){return new y.a(function(t){l.taskWrapper.wrapTaskAroundCall({task:new w.a("rbd/mirroring/peer/delete",{pool_name:n}),call:l.rbdMirroringService.deletePeer(n,e)}).subscribe(void 0,function(l){return t.error(l)},function(){l.rbdMirroringService.refresh(),t.complete()})})}}})},l.prototype.getPeerUUID=function(){var l=this.selection.first(),n=this.data.find(function(n){return l&&l.name===n.name});if(n&&n.peer_uuids)return n.peer_uuids[0]},l.prototype.updateSelection=function(l){this.selection=l},l}(),F=e("DQlY"),D=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function V(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{ngClass:[0,"ngClass"]},null),t["\u0275ppd"](2,1),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent,0),n.context.row.health_color));l(n,1,0,e)},function(l,n){l(n,3,0,n.context.value)})}function T(l){return t["\u0275vid"](0,[t["\u0275pid"](0,a,[]),t["\u0275qud"](402653184,1,{healthTmpl:0}),(l()(),t["\u0275eld"](2,0,null,null,3,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","name"],["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(l,n,e){var t=!0,u=l.component;return"fetchData"===n&&(t=!1!==u.refresh()&&t),"updateSelection"===n&&(t=!1!==u.updateSelection(e)&&t),t},r.b,r.a)),t["\u0275did"](3,2867200,null,0,s.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"],identifier:[4,"identifier"],forceIdentifier:[5,"forceIdentifier"],selectionType:[6,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](4,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,v.b,v.a)),t["\u0275did"](5,114688,null,0,b.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),t["\u0275and"](0,[[1,2],["healthTmpl",2]],null,0,null,V))],function(l,n){var e=n.component;l(n,3,0,e.data,e.columns,"flex",0,"name","true","single"),l(n,5,0,e.permission,e.selection,e.tableActions)},null)}var N=e("Da1D"),P=t["\u0275crt"]({encapsulation:2,styles:[],data:{}});function x(l){return t["\u0275vid"](0,[t["\u0275ncd"](null,0)],null,null)}var O=t["\u0275crt"]({encapsulation:0,styles:["[_nghost-%COMP%] {\n width: 100%;\n display: flex;\n }"],data:{}});function q(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"bar",[["aria-valuemin","0"],["role","progressbar"]],[[8,"className",0],[2,"progress-bar-animated",null],[2,"progress-bar-striped",null],[2,"active",null],[1,"aria-valuenow",0],[1,"aria-valuetext",0],[1,"aria-valuemax",0],[4,"height","%"],[4,"width","%"]],null,null,x,P)),t["\u0275did"](1,245760,null,0,N.a,[N.b],{type:[0,"type"],value:[1,"value"]},null),t["\u0275ncd"](0,0)],function(l,n){var e=n.component;l(n,1,0,e.type,e._value)},function(l,n){l(n,0,0,"progress-bar "+(t["\u0275nov"](n,1).type?"progress-bar-"+t["\u0275nov"](n,1).type+" bg-"+t["\u0275nov"](n,1).type:""),!t["\u0275nov"](n,1).isBs3&&t["\u0275nov"](n,1).animate,t["\u0275nov"](n,1).striped,t["\u0275nov"](n,1).isBs3&&t["\u0275nov"](n,1).animate,t["\u0275nov"](n,1).value,t["\u0275nov"](n,1).percent?t["\u0275nov"](n,1).percent.toFixed(0)+"%":"",t["\u0275nov"](n,1).max,"100",t["\u0275nov"](n,1).setBarWidth)})}function M(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"bar",[["aria-valuemin","0"],["role","progressbar"]],[[8,"className",0],[2,"progress-bar-animated",null],[2,"progress-bar-striped",null],[2,"active",null],[1,"aria-valuenow",0],[1,"aria-valuetext",0],[1,"aria-valuemax",0],[4,"height","%"],[4,"width","%"]],null,null,x,P)),t["\u0275did"](1,245760,null,0,N.a,[N.b],{type:[0,"type"],value:[1,"value"]},null),(l()(),t["\u0275ted"](2,0,["",""]))],function(l,n){l(n,1,0,n.context.$implicit.type,n.context.$implicit.value)},function(l,n){l(n,0,0,"progress-bar "+(t["\u0275nov"](n,1).type?"progress-bar-"+t["\u0275nov"](n,1).type+" bg-"+t["\u0275nov"](n,1).type:""),!t["\u0275nov"](n,1).isBs3&&t["\u0275nov"](n,1).animate,t["\u0275nov"](n,1).striped,t["\u0275nov"](n,1).isBs3&&t["\u0275nov"](n,1).animate,t["\u0275nov"](n,1).value,t["\u0275nov"](n,1).percent?t["\u0275nov"](n,1).percent.toFixed(0)+"%":"",t["\u0275nov"](n,1).max,"100",t["\u0275nov"](n,1).setBarWidth),l(n,2,0,n.context.$implicit.label)})}function A(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,M)),t["\u0275did"](1,278528,null,0,o.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,n.component._value)},null)}function B(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,q)),t["\u0275did"](1,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,A)),t["\u0275did"](3,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,1,0,!e.isStacked),l(n,3,0,e.isStacked)},null)}var j=e("pKUh"),U=e("YAQW"),G=function(){function l(l,n){this.rbdMirroringService=l,this.i18n=n,this.image_error={data:[],columns:{}},this.image_syncing={data:[],columns:{}},this.image_ready={data:[],columns:{}}}return l.prototype.ngOnInit=function(){var l=this;this.image_error.columns=[{prop:"pool_name",name:this.i18n("Pool"),flexGrow:2},{prop:"name",name:this.i18n("Image"),flexGrow:2},{prop:"description",name:this.i18n("Issue"),flexGrow:4},{prop:"state",name:this.i18n("State"),cellTemplate:this.stateTmpl,flexGrow:1}],this.image_syncing.columns=[{prop:"pool_name",name:this.i18n("Pool"),flexGrow:2},{prop:"name",name:this.i18n("Image"),flexGrow:2},{prop:"progress",name:this.i18n("Progress"),cellTemplate:this.progressTmpl,flexGrow:2},{prop:"state",name:this.i18n("State"),cellTemplate:this.syncTmpl,flexGrow:1}],this.image_ready.columns=[{prop:"pool_name",name:this.i18n("Pool"),flexGrow:2},{prop:"name",name:this.i18n("Image"),flexGrow:2},{prop:"description",name:this.i18n("Description"),flexGrow:4},{prop:"state",name:this.i18n("State"),cellTemplate:this.stateTmpl,flexGrow:1}],this.subs=this.rbdMirroringService.subscribeSummary(function(n){n&&(l.image_error.data=n.content_data.image_error,l.image_syncing.data=n.content_data.image_syncing,l.image_ready.data=n.content_data.image_ready)})},l.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},l.prototype.refresh=function(){this.rbdMirroringService.refresh()},l}(),L=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function z(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{ngClass:[0,"ngClass"]},null),t["\u0275ppd"](2,1),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){var e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent,0),n.context.row.state_color));l(n,1,0,e)},function(l,n){l(n,3,0,n.context.value)})}function W(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","label label-info"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Syncing"]))],null,null)}function $(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"progressbar",[["type","info"]],[[1,"max",0],[2,"progress",null]],null,null,B,O)),t["\u0275did"](1,49152,null,0,N.b,[N.c],{type:[0,"type"],value:[1,"value"]},null)],function(l,n){l(n,1,0,"info",n.context.value)},function(l,n){l(n,0,0,t["\u0275nov"](n,1).max,t["\u0275nov"](n,1).addClass)})}function X(l){return t["\u0275vid"](0,[t["\u0275pid"](0,a,[]),t["\u0275qud"](402653184,1,{stateTmpl:0}),t["\u0275qud"](402653184,2,{syncTmpl:0}),t["\u0275qud"](402653184,3,{progressTmpl:0}),(l()(),t["\u0275eld"](4,0,null,null,13,"tabset",[],[[2,"tab-container",null]],null,null,j.b,j.a)),t["\u0275did"](5,180224,null,0,U.d,[U.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](6,0,null,0,3,"tab",[["heading","Issues"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](7,212992,null,0,U.b,[U.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](8,0,null,null,1,"cd-table",[["columnMode","flex"]],null,[[null,"fetchData"]],function(l,n,e){var t=!0;return"fetchData"===n&&(t=!1!==l.component.refresh()&&t),t},r.b,r.a)),t["\u0275did"](9,2867200,null,0,s.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"]},{fetchData:"fetchData"}),(l()(),t["\u0275eld"](10,0,null,0,3,"tab",[["heading","Syncing"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](11,212992,null,0,U.b,[U.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](12,0,null,null,1,"cd-table",[["columnMode","flex"]],null,[[null,"fetchData"]],function(l,n,e){var t=!0;return"fetchData"===n&&(t=!1!==l.component.refresh()&&t),t},r.b,r.a)),t["\u0275did"](13,2867200,null,0,s.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"]},{fetchData:"fetchData"}),(l()(),t["\u0275eld"](14,0,null,0,3,"tab",[["heading","Ready"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](15,212992,null,0,U.b,[U.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](16,0,null,null,1,"cd-table",[["columnMode","flex"]],null,[[null,"fetchData"]],function(l,n,e){var t=!0;return"fetchData"===n&&(t=!1!==l.component.refresh()&&t),t},r.b,r.a)),t["\u0275did"](17,2867200,null,0,s.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"]},{fetchData:"fetchData"}),(l()(),t["\u0275and"](0,[[1,2],["stateTmpl",2]],null,0,null,z)),(l()(),t["\u0275and"](0,[[2,2],["syncTmpl",2]],null,0,null,W)),(l()(),t["\u0275and"](0,[[3,2],["progressTmpl",2]],null,0,null,$))],function(l,n){var e=n.component;l(n,7,0,"Issues"),l(n,9,0,e.image_error.data,e.image_error.columns,"flex",0),l(n,11,0,"Syncing"),l(n,13,0,e.image_syncing.data,e.image_syncing.columns,"flex",0),l(n,15,0,"Ready"),l(n,17,0,e.image_ready.data,e.image_ready.columns,"flex",0)},function(l,n){l(n,4,0,t["\u0275nov"](n,5).clazz),l(n,6,0,t["\u0275nov"](n,7).id,t["\u0275nov"](n,7).active,t["\u0275nov"](n,7).addClass),l(n,10,0,t["\u0275nov"](n,11).id,t["\u0275nov"](n,11).active,t["\u0275nov"](n,11).addClass),l(n,14,0,t["\u0275nov"](n,15).id,t["\u0275nov"](n,15).active,t["\u0275nov"](n,15).addClass)})}var Y=e("cxJu");e.d(n,"a",function(){return Q});var K=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function J(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-view-cache",[],null,null,null,u.b,u.a)),t["\u0275did"](1,114688,null,0,i.a,[],{status:[0,"status"]},null),(l()(),t["\u0275eld"](2,0,null,null,10,"div",[["class","row"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,4,"div",[["class","col-sm-6"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Daemons"])),(l()(),t["\u0275eld"](6,0,null,null,1,"cd-mirroring-daemons",[],null,null,null,h,f)),t["\u0275did"](7,245760,null,0,p,[d.a,c.a,m.a],null,null),(l()(),t["\u0275eld"](8,0,null,null,4,"div",[["class","col-sm-6"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Pools"])),(l()(),t["\u0275eld"](11,0,null,null,1,"cd-mirroring-pools",[],null,null,null,T,D)),t["\u0275did"](12,245760,null,0,E,[R.a,d.a,F.b,I.a,m.a],null,null),(l()(),t["\u0275eld"](13,0,null,null,5,"div",[["class","row"]],null,null,null,null,null)),(l()(),t["\u0275eld"](14,0,null,null,4,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](15,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Images"])),(l()(),t["\u0275eld"](17,0,null,null,1,"cd-mirroring-images",[],null,null,null,X,L)),t["\u0275did"](18,245760,null,0,G,[d.a,m.a],null,null)],function(l,n){l(n,1,0,n.component.status),l(n,7,0),l(n,12,0),l(n,18,0)},null)}function Z(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-mirroring",[],null,null,null,J,K)),t["\u0275did"](1,245760,null,0,Y.a,[d.a],null,null)],function(l,n){l(n,1,0)},null)}var Q=t["\u0275ccf"]("cd-mirroring",Y.a,Z,{},{},[])},Sofw:function(l,n,e){"use strict";e.d(n,"a",function(){return a});var t=e("gIcY"),u=(e("my5R"),e("mtw6")),i=e("QFaf"),o=e("1Ni5"),a=(e("aexS"),e("9nlD"),function(){function l(l,n,e,t,u){this.authStorageService=l,this.bsModalRef=n,this.iscsiService=e,this.notificationService=t,this.i18n=u,this.USER_REGEX=/^[\w\.:@_-]{8,64}$/,this.PASSWORD_REGEX=/^[\w@\-_\/]{12,16}$/,this.permission=this.authStorageService.getPermissions().iscsi}return l.prototype.ngOnInit=function(){var l=this;this.hasPermission=this.permission.update,this.createForm(),this.iscsiService.getDiscovery().subscribe(function(n){l.discoveryForm.patchValue(n)})},l.prototype.createForm=function(){var l=this;this.discoveryForm=new i.a({user:new t.i({value:"",disabled:!this.hasPermission}),password:new t.i({value:"",disabled:!this.hasPermission}),mutual_user:new t.i({value:"",disabled:!this.hasPermission}),mutual_password:new t.i({value:"",disabled:!this.hasPermission})}),o.a.validateIf(this.discoveryForm.get("user"),function(){return l.discoveryForm.getValue("password")||l.discoveryForm.getValue("mutual_user")||l.discoveryForm.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.USER_REGEX)],[this.discoveryForm.get("password"),this.discoveryForm.get("mutual_user"),this.discoveryForm.get("mutual_password")]),o.a.validateIf(this.discoveryForm.get("password"),function(){return l.discoveryForm.getValue("user")||l.discoveryForm.getValue("mutual_user")||l.discoveryForm.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.PASSWORD_REGEX)],[this.discoveryForm.get("user"),this.discoveryForm.get("mutual_user"),this.discoveryForm.get("mutual_password")]),o.a.validateIf(this.discoveryForm.get("mutual_user"),function(){return l.discoveryForm.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.USER_REGEX)],[this.discoveryForm.get("user"),this.discoveryForm.get("password"),this.discoveryForm.get("mutual_password")]),o.a.validateIf(this.discoveryForm.get("mutual_password"),function(){return l.discoveryForm.getValue("mutual_user")},[t.A.required],[t.A.pattern(this.PASSWORD_REGEX)],[this.discoveryForm.get("user"),this.discoveryForm.get("password"),this.discoveryForm.get("mutual_user")])},l.prototype.submitAction=function(){var l=this;this.iscsiService.updateDiscovery(this.discoveryForm.value).subscribe(function(){l.notificationService.show(u.a.success,l.i18n("Updated discovery authentication")),l.bsModalRef.hide()},function(){l.discoveryForm.setErrors({cdSubmitButton:!0})})},l}())},Ur3J:function(l,n,e){"use strict";var t=e("CcnG"),u=e("Ip0R"),i=e("8xTl"),o=e("gIcY"),a=e("IZUe"),r=e("ANnk"),s=e("f/UV"),d=e("aexS"),c=e("gp3X"),p=e("sb0X"),m=e("KVJa"),f=e("Z21x"),g=e("sne2"),h=e("+lcs"),v=e("DQlY"),b=e("F83c"),y=e("VXsX"),C=e("9nlD"),_=e("Jm/i");e.d(n,"a",function(){return k});var w=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function I(l){return t["\u0275vid"](0,[t["\u0275pid"](0,u.TitleCasePipe,[]),t["\u0275pid"](0,i.a,[]),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,[""," ",""])),t["\u0275ppd"](5,1),t["\u0275ppd"](6,1),(l()(),t["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,e){var t=!0;return"click"===n&&(t=!1!==l.component.modalRef.hide()&&t),t},null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xd7"])),(l()(),t["\u0275eld"](10,0,null,null,32,"form",[["class","form-horizontal"],["name","snapshotForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,12).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,12).onReset()&&u),u},null,null)),t["\u0275did"](11,16384,null,0,o.D,[],null,null),t["\u0275did"](12,540672,[["formDir",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,o.d,null,[o.l]),t["\u0275did"](14,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),t["\u0275eld"](15,0,null,null,18,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](17,278528,null,0,u.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](18,{"has-error":0}),(l()(),t["\u0275eld"](19,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","snapshotName"]],null,null,null,null,null)),(l()(),t["\u0275eld"](20,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Name"])),(l()(),t["\u0275eld"](22,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](23,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](24,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","snapshotName"],["id","snapshotName"],["name","snapshotName"],["placeholder","Snapshot name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,25)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,25).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,25)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,25)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](25,16384,null,0,o.e,[t.Renderer2,t.ElementRef,[2,o.b]],null,null),t["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),t["\u0275did"](27,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,o.q,null,[o.j]),t["\u0275did"](29,16384,null,0,o.r,[[4,o.q]],null,null),t["\u0275did"](30,4210688,null,0,a.a,[t.ElementRef],null,null),t["\u0275did"](31,4210688,null,0,r.a,[[2,s.a],d.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](33,16384,null,0,u.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](34,0,null,null,8,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](35,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](36,0,null,null,4,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.submit()&&t),t},c.b,c.a)),t["\u0275did"](37,114688,null,0,p.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](38,0,[""," ",""])),t["\u0275ppd"](39,1),t["\u0275ppd"](40,1),(l()(),t["\u0275eld"](41,0,null,null,1,"cd-back-button",[["name","Close"]],null,null,null,m.b,m.a)),t["\u0275did"](42,49152,null,0,f.a,[u.Location,g.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,12,0,e.snapshotForm);var u=l(n,18,0,e.snapshotForm.showError("snapshotName",t["\u0275nov"](n,12)));l(n,17,0,"form-group",u),l(n,27,0,"snapshotName"),l(n,33,0,e.snapshotForm.showError("snapshotName",t["\u0275nov"](n,12),"required")),l(n,37,0,e.snapshotForm),l(n,42,0,"Close",e.modalRef.hide)},function(l,n){var e=n.component,u=t["\u0275unv"](n,4,0,l(n,5,0,t["\u0275nov"](n,0),e.action)),i=t["\u0275unv"](n,4,1,l(n,6,0,t["\u0275nov"](n,1),e.resource));l(n,4,0,u,i),l(n,10,0,t["\u0275nov"](n,14).ngClassUntouched,t["\u0275nov"](n,14).ngClassTouched,t["\u0275nov"](n,14).ngClassPristine,t["\u0275nov"](n,14).ngClassDirty,t["\u0275nov"](n,14).ngClassValid,t["\u0275nov"](n,14).ngClassInvalid,t["\u0275nov"](n,14).ngClassPending),l(n,24,0,t["\u0275nov"](n,29).ngClassUntouched,t["\u0275nov"](n,29).ngClassTouched,t["\u0275nov"](n,29).ngClassPristine,t["\u0275nov"](n,29).ngClassDirty,t["\u0275nov"](n,29).ngClassValid,t["\u0275nov"](n,29).ngClassInvalid,t["\u0275nov"](n,29).ngClassPending);var o=t["\u0275unv"](n,38,0,l(n,39,0,t["\u0275nov"](n,0),e.action)),a=t["\u0275unv"](n,38,1,l(n,40,0,t["\u0275nov"](n,1),e.resource));l(n,38,0,o,a)})}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rbd-snapshot-form",[],null,null,null,I,w)),t["\u0275did"](1,114688,null,0,h.a,[v.a,b.a,y.a,C.a,_.a,g.b],null,null)],function(l,n){l(n,1,0)},null)}var k=t["\u0275ccf"]("cd-rbd-snapshot-form",h.a,S,{},{},[])},VBM6:function(l,n,e){"use strict";var t=e("CcnG"),u=e("EEJc"),i=e("ajRT"),o=e("Ip0R"),a=e("gIcY"),r=e("IZUe"),s=e("ANnk"),d=e("f/UV"),c=e("aexS"),p=e("gp3X"),m=e("sb0X"),f=e("KVJa"),g=e("Z21x"),h=e("sne2"),v=e("L4us"),b=e("DQlY"),y=e("XED3"),C=e("kn/O");e.d(n,"a",function(){return x});var _=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function w(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["Edit"]))],null,null)}function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["Add"]))],null,null)}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["Edit"]))],null,null)}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["Add"]))],null,null)}function k(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function E(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The cluster name is not valid."]))],null,null)}function F(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function D(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The CephX ID is not valid."]))],null,null)}function V(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The monitory address is not valid."]))],null,null)}function T(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["CephX key must be base64 encoded."]))],null,null)}function N(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,105,"cd-modal",[],null,null,null,u.c,u.b)),t["\u0275did"](1,49152,null,0,i.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,7,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,5,null,null,null,null,null,null,null)),t["\u0275did"](4,16384,null,0,o.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,w)),t["\u0275did"](6,278528,null,0,o.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,o.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](8,16384,null,0,o.NgSwitchDefault,[t.ViewContainerRef,t.TemplateRef,o.NgSwitch],null,null),(l()(),t["\u0275ted"](-1,null,[" pool mirror peer"])),(l()(),t["\u0275eld"](10,0,null,1,95,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,94,"form",[["class","form"],["name","editPeerForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,13).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,13).onReset()&&u),u},null,null)),t["\u0275did"](12,16384,null,0,a.D,[],null,null),t["\u0275did"](13,540672,[["formDir",4]],0,a.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,a.d,null,[a.l]),t["\u0275did"](15,16384,null,0,a.s,[[4,a.d]],null,null),(l()(),t["\u0275eld"](16,0,null,null,82,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,14,"p",[],null,null,null,null,null)),(l()(),t["\u0275eld"](18,0,null,null,13,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,5,null,null,null,null,null,null,null)),t["\u0275did"](20,16384,null,0,o.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,I)),t["\u0275did"](22,278528,null,0,o.NgSwitchCase,[t.ViewContainerRef,t.TemplateRef,o.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,S)),t["\u0275did"](24,16384,null,0,o.NgSwitchDefault,[t.ViewContainerRef,t.TemplateRef,o.NgSwitch],null,null),(l()(),t["\u0275ted"](-1,null,[" the pool mirror peer attributes for pool "])),(l()(),t["\u0275eld"](26,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](27,null,["",""])),(l()(),t["\u0275ted"](-1,null,[" and click "])),(l()(),t["\u0275eld"](29,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Submit"])),(l()(),t["\u0275ted"](-1,null,["."])),(l()(),t["\u0275eld"](32,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](33,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](34,{"has-error":0}),(l()(),t["\u0275eld"](35,0,null,null,3,"label",[["class","control-label"],["for","clusterName"]],null,null,null,null,null)),(l()(),t["\u0275eld"](36,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Cluster Name"])),(l()(),t["\u0275eld"](38,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","clusterName"],["id","clusterName"],["name","clusterName"],["placeholder","Name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,42)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,42).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,42)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,42)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](40,4210688,null,0,r.a,[t.ElementRef],null,null),t["\u0275did"](41,4210688,null,0,s.a,[[2,d.a],c.a,t.ElementRef],null,null),t["\u0275did"](42,16384,null,0,a.e,[t.Renderer2,t.ElementRef,[2,a.b]],null,null),t["\u0275prd"](1024,null,a.p,function(l){return[l]},[a.e]),t["\u0275did"](44,671744,null,0,a.j,[[3,a.d],[8,null],[8,null],[6,a.p],[2,a.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,a.q,null,[a.j]),t["\u0275did"](46,16384,null,0,a.r,[[4,a.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,k)),t["\u0275did"](48,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,E)),t["\u0275did"](50,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](51,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](52,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](53,{"has-error":0}),(l()(),t["\u0275eld"](54,0,null,null,3,"label",[["class","control-label"],["for","clientID"]],null,null,null,null,null)),(l()(),t["\u0275eld"](55,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["CephX ID"])),(l()(),t["\u0275eld"](57,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](58,0,null,null,6,"input",[["class","form-control"],["formControlName","clientID"],["id","clientID"],["name","clientID"],["placeholder","CephX ID..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,60)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,60).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,60)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,60)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](59,4210688,null,0,s.a,[[2,d.a],c.a,t.ElementRef],null,null),t["\u0275did"](60,16384,null,0,a.e,[t.Renderer2,t.ElementRef,[2,a.b]],null,null),t["\u0275prd"](1024,null,a.p,function(l){return[l]},[a.e]),t["\u0275did"](62,671744,null,0,a.j,[[3,a.d],[8,null],[8,null],[6,a.p],[2,a.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,a.q,null,[a.j]),t["\u0275did"](64,16384,null,0,a.r,[[4,a.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,F)),t["\u0275did"](66,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,D)),t["\u0275did"](68,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](69,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](70,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](71,{"has-error":0}),(l()(),t["\u0275eld"](72,0,null,null,2,"label",[["class","control-label"],["for","monAddr"]],null,null,null,null,null)),(l()(),t["\u0275eld"](73,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Monitor Addresses"])),(l()(),t["\u0275eld"](75,0,null,null,6,"input",[["class","form-control"],["formControlName","monAddr"],["id","monAddr"],["name","monAddr"],["placeholder","Comma-delimited addresses..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,77)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,77).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,77)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,77)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](76,4210688,null,0,s.a,[[2,d.a],c.a,t.ElementRef],null,null),t["\u0275did"](77,16384,null,0,a.e,[t.Renderer2,t.ElementRef,[2,a.b]],null,null),t["\u0275prd"](1024,null,a.p,function(l){return[l]},[a.e]),t["\u0275did"](79,671744,null,0,a.j,[[3,a.d],[8,null],[8,null],[6,a.p],[2,a.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,a.q,null,[a.j]),t["\u0275did"](81,16384,null,0,a.r,[[4,a.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,V)),t["\u0275did"](83,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](84,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](85,278528,null,0,o.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](86,{"has-error":0}),(l()(),t["\u0275eld"](87,0,null,null,2,"label",[["class","control-label"],["for","key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](88,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["CephX Key"])),(l()(),t["\u0275eld"](90,0,null,null,6,"input",[["class","form-control"],["formControlName","key"],["id","key"],["name","key"],["placeholder","Base64-encoded key..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,92)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,92).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,92)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,92)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](91,4210688,null,0,s.a,[[2,d.a],c.a,t.ElementRef],null,null),t["\u0275did"](92,16384,null,0,a.e,[t.Renderer2,t.ElementRef,[2,a.b]],null,null),t["\u0275prd"](1024,null,a.p,function(l){return[l]},[a.e]),t["\u0275did"](94,671744,null,0,a.j,[[3,a.d],[8,null],[8,null],[6,a.p],[2,a.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,a.q,null,[a.j]),t["\u0275did"](96,16384,null,0,a.r,[[4,a.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,T)),t["\u0275did"](98,16384,null,0,o.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](99,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](100,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](101,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.update()&&t),t},p.b,p.a)),t["\u0275did"](102,114688,null,0,m.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Submit"])),(l()(),t["\u0275eld"](104,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,f.b,f.a)),t["\u0275did"](105,49152,null,0,g.a,[o.Location,h.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,4,0,e.mode),l(n,6,0,"edit"),l(n,13,0,e.editPeerForm),l(n,20,0,e.mode),l(n,22,0,"edit");var u=l(n,34,0,e.editPeerForm.showError("clusterName",t["\u0275nov"](n,13)));l(n,33,0,"form-group",u),l(n,44,0,"clusterName"),l(n,48,0,e.editPeerForm.showError("clusterName",t["\u0275nov"](n,13),"required")),l(n,50,0,e.editPeerForm.showError("clusterName",t["\u0275nov"](n,13),"invalidClusterName"));var i=l(n,53,0,e.editPeerForm.showError("clientID",t["\u0275nov"](n,13)));l(n,52,0,"form-group",i),l(n,62,0,"clientID"),l(n,66,0,e.editPeerForm.showError("clientID",t["\u0275nov"](n,13),"required")),l(n,68,0,e.editPeerForm.showError("clientID",t["\u0275nov"](n,13),"invalidClientID"));var o=l(n,71,0,e.editPeerForm.showError("monAddr",t["\u0275nov"](n,13)));l(n,70,0,"form-group",o),l(n,79,0,"monAddr"),l(n,83,0,e.editPeerForm.showError("monAddr",t["\u0275nov"](n,13),"invalidMonAddr"));var a=l(n,86,0,e.editPeerForm.showError("key",t["\u0275nov"](n,13)));l(n,85,0,"form-group",a),l(n,94,0,"key"),l(n,98,0,e.editPeerForm.showError("key",t["\u0275nov"](n,13),"invalidKey")),l(n,102,0,e.editPeerForm),l(n,105,0,"Cancel",e.modalRef.hide)},function(l,n){var e=n.component;l(n,11,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending),l(n,27,0,e.poolName),l(n,39,0,t["\u0275nov"](n,46).ngClassUntouched,t["\u0275nov"](n,46).ngClassTouched,t["\u0275nov"](n,46).ngClassPristine,t["\u0275nov"](n,46).ngClassDirty,t["\u0275nov"](n,46).ngClassValid,t["\u0275nov"](n,46).ngClassInvalid,t["\u0275nov"](n,46).ngClassPending),l(n,58,0,t["\u0275nov"](n,64).ngClassUntouched,t["\u0275nov"](n,64).ngClassTouched,t["\u0275nov"](n,64).ngClassPristine,t["\u0275nov"](n,64).ngClassDirty,t["\u0275nov"](n,64).ngClassValid,t["\u0275nov"](n,64).ngClassInvalid,t["\u0275nov"](n,64).ngClassPending),l(n,75,0,t["\u0275nov"](n,81).ngClassUntouched,t["\u0275nov"](n,81).ngClassTouched,t["\u0275nov"](n,81).ngClassPristine,t["\u0275nov"](n,81).ngClassDirty,t["\u0275nov"](n,81).ngClassValid,t["\u0275nov"](n,81).ngClassInvalid,t["\u0275nov"](n,81).ngClassPending),l(n,90,0,t["\u0275nov"](n,96).ngClassUntouched,t["\u0275nov"](n,96).ngClassTouched,t["\u0275nov"](n,96).ngClassPristine,t["\u0275nov"](n,96).ngClassDirty,t["\u0275nov"](n,96).ngClassValid,t["\u0275nov"](n,96).ngClassInvalid,t["\u0275nov"](n,96).ngClassPending)})}function P(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-pool-edit-peer-modal",[],null,null,null,N,_)),t["\u0275did"](1,114688,null,0,v.a,[b.a,y.a,C.a],null,null)],function(l,n){l(n,1,0)},null)}var x=t["\u0275ccf"]("cd-pool-edit-peer-modal",v.a,P,{},{},[])},WxU5:function(l,n,e){"use strict";e.d(n,"a",function(){return u}),e("Ekvf"),e("F83c"),e("2EZI");var t=e("kvvV"),u=(e("aexS"),e("kn/O"),function(){function l(l,n,e,t,u,i){this.authStorageService=l,this.rbdService=n,this.modalRef=e,this.fb=t,this.poolService=u,this.taskWrapper=i,this.poolPermission=this.authStorageService.getPermissions().pool}return l.prototype.createForm=function(){this.purgeForm=this.fb.group({poolName:""})},l.prototype.ngOnInit=function(){var l=this;this.poolPermission.read&&this.poolService.list(["pool_name","application_metadata"]).then(function(n){l.pools=n.filter(function(l){return l.application_metadata.includes("rbd")}).map(function(l){return l.pool_name})}),this.createForm()},l.prototype.purge=function(){var l=this,n=this.purgeForm.getValue("poolName")||"";this.taskWrapper.wrapTaskAroundCall({task:new t.a("rbd/trash/purge",{pool_name:n}),call:this.rbdService.purgeTrash(n)}).subscribe(void 0,function(){l.purgeForm.setErrors({cdSubmitButton:!0})},function(){l.modalRef.hide()})},l}())},XED3:function(l,n,e){"use strict";e.d(n,"a",function(){return a});var t=e("26FU"),u=e("CcnG"),i=e("t/Na"),o=e("pL04"),a=function(){function l(l,n){this.http=l,this.ngZone=n,this.summaryDataSource=new t.a(null),this.summaryData$=this.summaryDataSource.asObservable(),this.refreshAndSchedule()}return l.prototype.refresh=function(){var l=this;this.http.get("api/block/mirroring/summary").subscribe(function(n){l.summaryDataSource.next(n)})},l.prototype.refreshAndSchedule=function(){var l=this;this.refresh(),this.ngZone.runOutsideAngular(function(){setTimeout(function(){l.ngZone.run(function(){l.refreshAndSchedule()})},3e4)})},l.prototype.getCurrentSummary=function(){return this.summaryDataSource.getValue()},l.prototype.subscribeSummary=function(l,n){return this.summaryData$.subscribe(l,n)},l.prototype.getPool=function(l){return this.http.get("api/block/mirroring/pool/"+l)},l.prototype.updatePool=function(l,n){return this.http.put("api/block/mirroring/pool/"+l,n,{observe:"response"})},l.prototype.getPeer=function(l,n){return this.http.get("api/block/mirroring/pool/"+l+"/peer/"+n)},l.prototype.addPeer=function(l,n){return this.http.post("api/block/mirroring/pool/"+l+"/peer",n,{observe:"response"})},l.prototype.updatePeer=function(l,n,e){return this.http.put("api/block/mirroring/pool/"+l+"/peer/"+n,e,{observe:"response"})},l.prototype.deletePeer=function(l,n){return this.http.delete("api/block/mirroring/pool/"+l+"/peer/"+n,{observe:"response"})},l.ngInjectableDef=u.defineInjectable({factory:function(){return new l(u.inject(i.c),u.inject(u.NgZone))},token:l,providedIn:o.a}),l}()},Z4cD:function(l,n,e){"use strict";e.d(n,"a",function(){return a});var t=e("mrSG"),u=e("gIcY"),i=e("LvDl"),o=(e("my5R"),e("QFaf")),a=function(){function l(l,n){this.modalRef=l,this.iscsiService=n}return l.prototype.ngOnInit=function(){var l=this,n={backstore:new u.i(this.imagesSettings[this.image].backstore),lun:new u.i(this.imagesSettings[this.image].lun),wwn:new u.i(this.imagesSettings[this.image].wwn)};i.forEach(this.backstores,function(e){var t=l.imagesSettings[l.image][e]||{};i.forIn(l.disk_default_controls[e],function(l,e){n[e]=new u.i(t[e])})}),this.settingsForm=new o.a(n)},l.prototype.getDiskControlLimits=function(l,n){return this.disk_controls_limits?this.disk_controls_limits[l][n]:{type:"int"}},l.prototype.save=function(){var l=this,n=this.settingsForm.controls.backstore.value,e=this.settingsForm.controls.lun.value,u=this.settingsForm.controls.wwn.value,o={};i.forIn(this.settingsForm.controls,function(e,t){""!==e.value&&null!==e.value&&t in l.disk_default_controls[l.settingsForm.value.backstore]&&(o[t]=e.value,i.forEach(l.backstores,function(u){u!==n&&t in(l.imagesSettings[l.image][u]||{})&&(l.imagesSettings[l.image][u][t]=e.value)}))}),this.imagesSettings[this.image].backstore=n,this.imagesSettings[this.image].lun=e,this.imagesSettings[this.image].wwn=u,this.imagesSettings[this.image][n]=o,this.imagesSettings=t.__assign({},this.imagesSettings),this.control.updateValueAndValidity({emitEvent:!1}),this.modalRef.hide()},l}()},a6qe:function(l,n,e){"use strict";e.d(n,"a",function(){return o});var t=e("gIcY"),u=e("LvDl"),i=(e("my5R"),e("QFaf")),o=function(){function l(l,n){this.modalRef=l,this.iscsiService=n}return l.prototype.ngOnInit=function(){var l=this,n={};u.forIn(this.target_default_controls,function(e,u){n[u]=new t.i(l.target_controls.value[u])}),this.settingsForm=new i.a(n)},l.prototype.save=function(){var l={};u.forIn(this.settingsForm.controls,function(n,e){""!==n.value&&null!==n.value&&(l[e]=n.value)}),this.target_controls.setValue(l),this.modalRef.hide()},l.prototype.getTargetControlLimits=function(l){return this.target_controls_limits?this.target_controls_limits[l]:["Yes","No"].includes(this.target_default_controls[l])?{type:"bool"}:{type:"int"}},l}()},aAWM:function(l,n,e){"use strict";e("uIqm");var t=e("PhyI"),u=function(){function l(){}return l.prototype.transform=function(l){return{0:"global",1:"pool",2:"image"}[l]},l}();e("aXbf"),e("o8EM"),e.d(n,"a",function(){return i});var i=function(){function l(l,n,e){this.formatterService=l,this.rbdConfigurationService=n,this.i18n=e,this.sourceField=t.a,this.typeField=t.b}return l.prototype.ngOnInit=function(){this.poolConfigurationColumns=[{prop:"displayName",name:this.i18n("Name")},{prop:"description",name:this.i18n("Description")},{prop:"name",name:this.i18n("Key")},{prop:"source",name:this.i18n("Source"),cellTemplate:this.configurationSourceTpl,pipe:new u},{prop:"value",name:this.i18n("Value"),cellTemplate:this.configurationValueTpl}]},l.prototype.ngOnChanges=function(){var l=this;this.data&&(this.data=this.data.filter(function(n){return l.rbdConfigurationService.getOptionFields().map(function(l){return l.name}).includes(n.name)}))},l}()},aa9H:function(l,n,e){"use strict";var t=e("gIcY"),u=(e("XED3"),e("QFaf")),i=e("kvvV"),o=(e("kn/O"),function(){return function(){}}());e.d(n,"a",function(){return a});var a=function(){function l(l,n,e,t){this.modalRef=l,this.i18n=n,this.rbdMirroringService=e,this.taskWrapper=t,this.bsConfig={containerClass:"theme-default"},this.peerExists=!1,this.mirrorModes=[{id:"disabled",name:this.i18n("Disabled")},{id:"pool",name:this.i18n("Pool")},{id:"image",name:this.i18n("Image")}],this.createForm()}return l.prototype.createForm=function(){this.editModeForm=new u.a({mirrorMode:new t.i("",{validators:[t.A.required,this.validateMode.bind(this)]})})},l.prototype.ngOnInit=function(){var l=this;this.pattern=""+this.poolName,this.rbdMirroringService.getPool(this.poolName).subscribe(function(n){l.setResponse(n)}),this.subs=this.rbdMirroringService.subscribeSummary(function(n){if(l.peerExists=!1,n){var e=n.content_data.pools.find(function(n){return l.poolName===n.name});l.peerExists=e&&e.peer_uuids.length}})},l.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},l.prototype.validateMode=function(l){return"disabled"===l.value&&this.peerExists?{cannotDisable:{value:l.value}}:null},l.prototype.setResponse=function(l){this.editModeForm.get("mirrorMode").setValue(l.mirror_mode)},l.prototype.update=function(){var l=this,n=new o;n.mirror_mode=this.editModeForm.getValue("mirrorMode"),this.taskWrapper.wrapTaskAroundCall({task:new i.a("rbd/mirroring/pool/edit",{pool_name:this.poolName}),call:this.rbdMirroringService.updatePool(this.poolName,n)}).subscribe(void 0,function(){return l.editModeForm.setErrors({cdSubmitButton:!0})},function(){l.rbdMirroringService.refresh(),l.modalRef.hide()})},l}()},bUo2:function(l,n,e){"use strict";var t=e("CcnG"),u=e("gp3X"),i=e("sb0X"),o=e("EEJc"),a=e("ajRT"),r=e("gIcY"),s=e("Ip0R"),d=e("ANnk"),c=e("f/UV"),p=e("aexS"),m=e("D4zM"),f=e("OcYo"),g=e("SZbH"),h=e("KVJa"),v=e("Z21x"),b=e("sne2"),y=e("Sofw"),C=e("DQlY"),_=e("my5R"),w=e("9nlD"),R=e("Jm/i");e.d(n,"a",function(){return q});var I=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function k(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function E(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function F(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function D(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function V(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function T(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function N(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function P(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.submitAction()&&t),t},u.b,u.a)),t["\u0275did"](1,114688,null,0,i.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Submit"]))],function(l,n){l(n,1,0,n.component.discoveryForm)},null)}function x(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,97,"cd-modal",[],null,null,null,o.c,o.b)),t["\u0275did"](1,49152,null,0,a.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Discovery Authentication"])),(l()(),t["\u0275eld"](4,0,null,1,93,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,92,"form",[["class","form-horizontal"],["name","discoveryForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,r.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,r.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,r.d,null,[r.l]),t["\u0275did"](9,16384,null,0,r.s,[[4,r.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,81,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](12,278528,null,0,s.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](13,{"has-error":0}),(l()(),t["\u0275eld"](14,0,null,null,1,"label",[["class","control-label col-sm-4"],["for","user"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["User"])),(l()(),t["\u0275eld"](16,0,null,null,11,"div",[["class","col-sm-8"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","user"],["id","user"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,18)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,18).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,18)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,18)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](18,16384,null,0,r.e,[t.Renderer2,t.ElementRef,[2,r.b]],null,null),t["\u0275prd"](1024,null,r.p,function(l){return[l]},[r.e]),t["\u0275did"](20,671744,null,0,r.j,[[3,r.d],[8,null],[8,null],[6,r.p],[2,r.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,r.q,null,[r.j]),t["\u0275did"](22,16384,null,0,r.r,[[4,r.q]],null,null),t["\u0275did"](23,4210688,null,0,d.a,[[2,c.a],p.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,S)),t["\u0275did"](25,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,k)),t["\u0275did"](27,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](28,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](29,278528,null,0,s.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](30,{"has-error":0}),(l()(),t["\u0275eld"](31,0,null,null,1,"label",[["class","control-label col-sm-4"],["for","password"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Password"])),(l()(),t["\u0275eld"](33,0,null,null,17,"div",[["class","col-sm-8"]],null,null,null,null,null)),(l()(),t["\u0275eld"](34,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](35,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","password"],["id","password"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,36)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,36).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,36)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,36)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](36,16384,null,0,r.e,[t.Renderer2,t.ElementRef,[2,r.b]],null,null),t["\u0275prd"](1024,null,r.p,function(l){return[l]},[r.e]),t["\u0275did"](38,671744,null,0,r.j,[[3,r.d],[8,null],[8,null],[6,r.p],[2,r.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,r.q,null,[r.j]),t["\u0275did"](40,16384,null,0,r.r,[[4,r.q]],null,null),t["\u0275did"](41,4210688,null,0,d.a,[[2,c.a],p.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](42,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](43,0,null,null,1,"button",[["cdPasswordButton","password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==t["\u0275nov"](l,44).onClick()&&u),u},null,null)),t["\u0275did"](44,81920,null,0,m.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](45,0,null,null,1,"button",[["cdCopy2ClipboardButton","password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==t["\u0275nov"](l,46).onClick()&&u),u},null,null)),t["\u0275did"](46,81920,null,0,f.a,[t.ElementRef,t.Renderer2,g.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,E)),t["\u0275did"](48,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,F)),t["\u0275did"](50,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](51,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](52,278528,null,0,s.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](53,{"has-error":0}),(l()(),t["\u0275eld"](54,0,null,null,2,"label",[["class","control-label col-sm-4"],["for","mutual_user"]],null,null,null,null,null)),(l()(),t["\u0275eld"](55,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Mutual User"])),(l()(),t["\u0275eld"](57,0,null,null,11,"div",[["class","col-sm-8"]],null,null,null,null,null)),(l()(),t["\u0275eld"](58,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","mutual_user"],["id","mutual_user"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,59)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,59).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,59)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,59)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](59,16384,null,0,r.e,[t.Renderer2,t.ElementRef,[2,r.b]],null,null),t["\u0275prd"](1024,null,r.p,function(l){return[l]},[r.e]),t["\u0275did"](61,671744,null,0,r.j,[[3,r.d],[8,null],[8,null],[6,r.p],[2,r.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,r.q,null,[r.j]),t["\u0275did"](63,16384,null,0,r.r,[[4,r.q]],null,null),t["\u0275did"](64,4210688,null,0,d.a,[[2,c.a],p.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,D)),t["\u0275did"](66,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,V)),t["\u0275did"](68,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](69,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](70,278528,null,0,s.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](71,{"has-error":0}),(l()(),t["\u0275eld"](72,0,null,null,1,"label",[["class","control-label col-sm-4"],["for","mutual_password"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Mutual Password"])),(l()(),t["\u0275eld"](74,0,null,null,17,"div",[["class","col-sm-8"]],null,null,null,null,null)),(l()(),t["\u0275eld"](75,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](76,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","mutual_password"],["id","mutual_password"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,77)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,77).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,77)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,77)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](77,16384,null,0,r.e,[t.Renderer2,t.ElementRef,[2,r.b]],null,null),t["\u0275prd"](1024,null,r.p,function(l){return[l]},[r.e]),t["\u0275did"](79,671744,null,0,r.j,[[3,r.d],[8,null],[8,null],[6,r.p],[2,r.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,r.q,null,[r.j]),t["\u0275did"](81,16384,null,0,r.r,[[4,r.q]],null,null),t["\u0275did"](82,4210688,null,0,d.a,[[2,c.a],p.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](83,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](84,0,null,null,1,"button",[["cdPasswordButton","mutual_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==t["\u0275nov"](l,85).onClick()&&u),u},null,null)),t["\u0275did"](85,81920,null,0,m.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](86,0,null,null,1,"button",[["cdCopy2ClipboardButton","mutual_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==t["\u0275nov"](l,87).onClick()&&u),u},null,null)),t["\u0275did"](87,81920,null,0,f.a,[t.ElementRef,t.Renderer2,g.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,T)),t["\u0275did"](89,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,N)),t["\u0275did"](91,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](92,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](93,0,null,null,4,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,P)),t["\u0275did"](95,16384,null,0,s.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](96,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,h.b,h.a)),t["\u0275did"](97,49152,null,0,v.a,[s.Location,b.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.bsModalRef),l(n,7,0,e.discoveryForm);var u=l(n,13,0,e.discoveryForm.showError("user",t["\u0275nov"](n,7)));l(n,12,0,"form-group",u),l(n,20,0,"user"),l(n,25,0,e.discoveryForm.showError("user",t["\u0275nov"](n,7),"required")),l(n,27,0,e.discoveryForm.showError("user",t["\u0275nov"](n,7),"pattern"));var i=l(n,30,0,e.discoveryForm.showError("password",t["\u0275nov"](n,7)));l(n,29,0,"form-group",i),l(n,38,0,"password"),l(n,44,0,"password"),l(n,46,0,"password"),l(n,48,0,e.discoveryForm.showError("password",t["\u0275nov"](n,7),"required")),l(n,50,0,e.discoveryForm.showError("password",t["\u0275nov"](n,7),"pattern"));var o=l(n,53,0,e.discoveryForm.showError("mutual_user",t["\u0275nov"](n,7)));l(n,52,0,"form-group",o),l(n,61,0,"mutual_user"),l(n,66,0,e.discoveryForm.showError("mutual_user",t["\u0275nov"](n,7),"required")),l(n,68,0,e.discoveryForm.showError("mutual_user",t["\u0275nov"](n,7),"pattern"));var a=l(n,71,0,e.discoveryForm.showError("mutual_password",t["\u0275nov"](n,7)));l(n,70,0,"form-group",a),l(n,79,0,"mutual_password"),l(n,85,0,"mutual_password"),l(n,87,0,"mutual_password"),l(n,89,0,e.discoveryForm.showError("mutual_password",t["\u0275nov"](n,7),"required")),l(n,91,0,e.discoveryForm.showError("mutual_password",t["\u0275nov"](n,7),"pattern")),l(n,95,0,e.hasPermission),l(n,97,0,"Cancel",e.bsModalRef.hide)},function(l,n){l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending),l(n,17,0,t["\u0275nov"](n,22).ngClassUntouched,t["\u0275nov"](n,22).ngClassTouched,t["\u0275nov"](n,22).ngClassPristine,t["\u0275nov"](n,22).ngClassDirty,t["\u0275nov"](n,22).ngClassValid,t["\u0275nov"](n,22).ngClassInvalid,t["\u0275nov"](n,22).ngClassPending),l(n,35,0,t["\u0275nov"](n,40).ngClassUntouched,t["\u0275nov"](n,40).ngClassTouched,t["\u0275nov"](n,40).ngClassPristine,t["\u0275nov"](n,40).ngClassDirty,t["\u0275nov"](n,40).ngClassValid,t["\u0275nov"](n,40).ngClassInvalid,t["\u0275nov"](n,40).ngClassPending),l(n,58,0,t["\u0275nov"](n,63).ngClassUntouched,t["\u0275nov"](n,63).ngClassTouched,t["\u0275nov"](n,63).ngClassPristine,t["\u0275nov"](n,63).ngClassDirty,t["\u0275nov"](n,63).ngClassValid,t["\u0275nov"](n,63).ngClassInvalid,t["\u0275nov"](n,63).ngClassPending),l(n,76,0,t["\u0275nov"](n,81).ngClassUntouched,t["\u0275nov"](n,81).ngClassTouched,t["\u0275nov"](n,81).ngClassPristine,t["\u0275nov"](n,81).ngClassDirty,t["\u0275nov"](n,81).ngClassValid,t["\u0275nov"](n,81).ngClassInvalid,t["\u0275nov"](n,81).ngClassPending)})}function O(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-discovery-modal",[],null,null,null,x,I)),t["\u0275did"](1,114688,null,0,y.a,[p.a,C.a,_.a,w.a,R.a],null,null)],function(l,n){l(n,1,0)},null)}var q=t["\u0275ccf"]("cd-iscsi-target-discovery-modal",y.a,O,{},{},[])},cxJu:function(l,n,e){"use strict";e.d(n,"a",function(){return t}),e("XED3");var t=function(){function l(l){this.rbdMirroringService=l}return l.prototype.ngOnInit=function(){var l=this;this.subs=this.rbdMirroringService.subscribeSummary(function(n){n&&(l.status=n.content_data.status)})},l.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},l}()},"e/kN":function(l,n,e){"use strict";e.d(n,"a",function(){return s});var t=e("LvDl"),u=(e("my5R"),e("0+/T")),i=(e("sne2"),e("uIqm"),e("x38r")),o=e("vCyI"),a=e("kvvV"),r=(e("+0ag"),e("uhwM"),e("G1/K"),e("aexS"),e("mSOc"),e("VTlA"),e("kn/O"),e("Sofw")),s=function(){function l(l,n,e,u,i,a,r,s,d,c,p){var m=this;this.authStorageService=l,this.i18n=n,this.iscsiService=e,this.listPipe=u,this.taskListService=i,this.cephReleaseNamePipe=a,this.notAvailablePipe=r,this.summaryservice=s,this.modalService=d,this.taskWrapper=c,this.actionLabels=p,this.available=void 0,this.selection=new o.a,this.targets=[],this.builders={"iscsi/target/create":function(l){return{target_iqn:l.target_iqn}}},this.permissions=this.authStorageService.getPermissions(),this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return"/block/iscsi/targets/create"},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return"/block/iscsi/targets/edit/"+m.selection.first().target_iqn},name:this.actionLabels.EDIT,disable:function(){return!m.selection.first()||!t.isUndefined(m.getEditDisableDesc())},disableDesc:function(){return m.getEditDisableDesc()}},{permission:"delete",icon:"fa-times",click:function(){return m.deleteIscsiTargetModal()},name:this.actionLabels.DELETE,disable:function(){return!m.selection.first()||!t.isUndefined(m.getDeleteDisableDesc())},disableDesc:function(){return m.getDeleteDisableDesc()}}]}return l.prototype.ngOnInit=function(){var l=this;this.columns=[{name:this.i18n("Target"),prop:"target_iqn",flexGrow:2,cellTransformation:i.a.executing},{name:this.i18n("Portals"),prop:"cdPortals",pipe:this.listPipe,flexGrow:2},{name:this.i18n("Images"),prop:"cdImages",pipe:this.listPipe,flexGrow:2},{name:this.i18n("# Sessions"),prop:"info.num_sessions",pipe:this.notAvailablePipe,flexGrow:1}],this.iscsiService.status().subscribe(function(n){if(l.available=n.available,n.available)l.iscsiService.version().subscribe(function(n){l.cephIscsiConfigVersion=n.ceph_iscsi_config_version,l.taskListService.init(function(){return l.iscsiService.listTargets()},function(n){return l.prepareResponse(n)},function(n){return l.targets=n},function(){return l.onFetchError()},l.taskFilter,l.itemFilter,l.builders)}),l.iscsiService.settings().subscribe(function(n){l.settings=n});else{var e=l.summaryservice.getCurrentSummary(),t=l.cephReleaseNamePipe.transform(e.version);l.docsUrl="http://docs.ceph.com/docs/"+t+"/mgr/dashboard/#enabling-iscsi-management",l.status=n.message}})},l.prototype.ngOnDestroy=function(){this.summaryDataSubscription&&this.summaryDataSubscription.unsubscribe()},l.prototype.getEditDisableDesc=function(){var l=this.selection.first();return l&&l.cdExecuting?l.cdExecuting:l&&t.isUndefined(l.info)?this.i18n("Unavailable gateway(s)"):void 0},l.prototype.getDeleteDisableDesc=function(){var l=this.selection.first();return l&&l.cdExecuting?l.cdExecuting:l&&t.isUndefined(l.info)?this.i18n("Unavailable gateway(s)"):l&&l.info&&l.info.num_sessions?this.i18n("Target has active sessions"):void 0},l.prototype.prepareResponse=function(l){return l.forEach(function(l){l.cdPortals=l.portals.map(function(l){return l.host+":"+l.ip}),l.cdImages=l.disks.map(function(l){return l.pool+"/"+l.image})}),l},l.prototype.onFetchError=function(){this.table.reset()},l.prototype.itemFilter=function(l,n){return l.target_iqn===n.metadata.target_iqn},l.prototype.taskFilter=function(l){return["iscsi/target/create","iscsi/target/edit","iscsi/target/delete"].includes(l.name)},l.prototype.updateSelection=function(l){this.selection=l},l.prototype.deleteIscsiTargetModal=function(){var l=this,n=this.selection.first().target_iqn;this.modalRef=this.modalService.show(u.a,{initialState:{itemDescription:this.i18n("iSCSI target"),itemNames:[n],submitActionObservable:function(){return l.taskWrapper.wrapTaskAroundCall({task:new a.a("iscsi/target/delete",{target_iqn:n}),call:l.iscsiService.deleteTarget(n)})}}})},l.prototype.configureDiscoveryAuth=function(){this.modalService.show(r.a,{})},l}()},eF8U:function(l,n,e){"use strict";var t=e("CcnG"),u=e("gIcY"),i=e("ANnk"),o=e("f/UV"),a=e("aexS"),r=e("Ip0R");e("jMP8"),e.d(n,"a",function(){return s}),e.d(n,"b",function(){return b});var s=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function d(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](2,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function c(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"select",[["class","form-control custom-select"]],[[8,"id",0],[8,"name",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==t["\u0275nov"](l,1).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,1).onTouched()&&u),u},null,null)),t["\u0275did"](1,16384,null,0,u.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.z]),t["\u0275did"](3,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](5,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](6,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](7,0,null,null,2,"option",[],null,null,null,null,null)),t["\u0275did"](8,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](9,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,d)),t["\u0275did"](11,278528,null,0,r.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,3,0,e.setting),l(n,8,0,null),l(n,9,0,null),l(n,11,0,e.limits.values)},function(l,n){var e=n.component;l(n,0,0,t["\u0275inlineInterpolate"](1,"",e.setting,""),t["\u0275inlineInterpolate"](1,"",e.setting,""),t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending)})}function p(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,7,"input",[["class","form-control"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,1)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,1).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionEnd(e.target.value)&&u),"change"===n&&(u=!1!==t["\u0275nov"](l,2).onChange(e.target.value)&&u),"input"===n&&(u=!1!==t["\u0275nov"](l,2).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,2).onTouched()&&u),u},null,null)),t["\u0275did"](1,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275did"](2,16384,null,0,u.C,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l,n){return[l,n]},[u.e,u.C]),t["\u0275did"](4,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](6,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](7,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null)],function(l,n){l(n,4,0,n.component.setting)},function(l,n){l(n,0,0,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function m(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,1)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,1).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](1,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](3,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](5,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](6,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null)],function(l,n){l(n,3,0,n.component.setting)},function(l,n){l(n,0,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending)})}function f(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,23,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,10,"div",[["class","radio radio-inline"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,7,"input",[["class","custom-control-input"],["type","radio"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,4)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,4).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,4)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,4)._compositionEnd(e.target.value)&&u),"change"===n&&(u=!1!==t["\u0275nov"](l,5).onChange()&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,5).onTouched()&&u),u},null,null)),t["\u0275did"](4,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275did"](5,212992,null,0,u.w,[t.Renderer2,t.ElementRef,u.E,t.Injector],{formControlName:[0,"formControlName"],value:[1,"value"]},null),t["\u0275prd"](1024,null,u.p,function(l,n){return[l,n]},[u.e,u.w]),t["\u0275did"](7,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](9,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](10,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](11,0,null,null,1,"label",[["class","custom-control-label"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Yes"])),(l()(),t["\u0275eld"](13,0,null,null,10,"div",[["class","radio radio-inline"]],null,null,null,null,null)),(l()(),t["\u0275eld"](14,0,null,null,7,"input",[["class","custom-control-input"],["type","radio"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,15)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,15).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,15)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,15)._compositionEnd(e.target.value)&&u),"change"===n&&(u=!1!==t["\u0275nov"](l,16).onChange()&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,16).onTouched()&&u),u},null,null)),t["\u0275did"](15,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275did"](16,212992,null,0,u.w,[t.Renderer2,t.ElementRef,u.E,t.Injector],{formControlName:[0,"formControlName"],value:[1,"value"]},null),t["\u0275prd"](1024,null,u.p,function(l,n){return[l,n]},[u.e,u.w]),t["\u0275did"](18,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](20,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](21,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](22,0,null,null,1,"label",[["class","custom-control-label"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["No"]))],function(l,n){var e=n.component;l(n,5,0,e.setting,!0),l(n,7,0,e.setting),l(n,16,0,e.setting,!1),l(n,18,0,e.setting)},function(l,n){var e=n.component;l(n,3,0,e.setting+"True",t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending),l(n,11,0,e.setting+"True"),l(n,14,0,e.setting+"False",t["\u0275nov"](n,20).ngClassUntouched,t["\u0275nov"](n,20).ngClassTouched,t["\u0275nov"](n,20).ngClassPristine,t["\u0275nov"](n,20).ngClassDirty,t["\u0275nov"](n,20).ngClassValid,t["\u0275nov"](n,20).ngClassInvalid,t["\u0275nov"](n,20).ngClassPending),l(n,22,0,e.setting+"False")})}function g(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,6,"span",[],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,p)),t["\u0275did"](2,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,m)),t["\u0275did"](4,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,f)),t["\u0275did"](6,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,2,0,"int"===e.limits.type),l(n,4,0,"str"===e.limits.type),l(n,6,0,"bool"===e.limits.type)},null)}function h(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](2,null,["Must be greater than or equal to ","."]))],null,function(l,n){l(n,2,0,n.component.limits.min)})}function v(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](2,null,["Must be less than or equal to ","."]))],null,function(l,n){l(n,2,0,n.component.limits.max)})}function b(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,15,"div",[["class","form-group"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,3).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,3).onReset()&&u),u},null,null)),t["\u0275did"](1,278528,null,0,r.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),t["\u0275did"](3,540672,null,0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,u.d,null,[u.l]),t["\u0275did"](5,16384,null,0,u.s,[[4,u.d]],null,null),(l()(),t["\u0275eld"](6,0,null,null,1,"label",[["class","col-form-label"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),t["\u0275ted"](7,null,["",""])),(l()(),t["\u0275and"](16777216,null,null,1,null,c)),t["\u0275did"](9,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,g)),t["\u0275did"](11,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,h)),t["\u0275did"](13,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,v)),t["\u0275did"](15,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.settingsForm.showError(e.setting,e.formDir));l(n,1,0,"form-group",t),l(n,3,0,e.settingsForm),l(n,9,0,"enum"===e.limits.type),l(n,11,0,"enum"!==e.limits.type),l(n,13,0,e.settingsForm.showError(e.setting,e.formDir,"min")),l(n,15,0,e.settingsForm.showError(e.setting,e.formDir,"max"))},function(l,n){var e=n.component;l(n,0,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending),l(n,6,0,t["\u0275inlineInterpolate"](1,"",e.setting,"")),l(n,7,0,e.setting)})}},gr3l:function(l,n,e){"use strict";e.d(n,"a",function(){return m});var t=e("gIcY"),u=e("LvDl"),i=e("VNr4"),o=(e("my5R"),e("F83c"),e("DNAf")),a=e("a96k"),r=(e("sne2"),e("QFaf")),s=e("1Ni5"),d=e("kvvV"),c=(e("kn/O"),e("Z4cD")),p=e("a6qe"),m=function(){function l(l,n,e,t,u,i,a,r){this.iscsiService=l,this.modalService=n,this.rbdService=e,this.router=t,this.route=u,this.i18n=i,this.taskWrapper=a,this.actionLabels=r,this.api_version=0,this.minimum_gateways=1,this.isEdit=!1,this.portalsSelections=[],this.imagesInitiatorSelections=[],this.groupDiskSelections=[],this.groupMembersSelections=[],this.imagesSettings={},this.messages={portals:new o.a({noOptions:this.i18n("There are no portals available.")},this.i18n),images:new o.a({noOptions:this.i18n("There are no images available.")},this.i18n),initiatorImage:new o.a({noOptions:this.i18n("There are no images available. Please make sure you add an image to the target.")},this.i18n),groupInitiator:new o.a({noOptions:this.i18n("There are no initiators available. Please make sure you add an initiator to the target.")},this.i18n)},this.IQN_REGEX=/^iqn\.(19|20)\d\d-(0[1-9]|1[0-2])\.\D{2,3}(\.[A-Za-z0-9-]+)+(:[A-Za-z0-9-\.]+)*$/,this.USER_REGEX=/^[\w\.:@_-]{8,64}$/,this.PASSWORD_REGEX=/^[\w@\-_\/]{12,16}$/,this.resource=this.i18n("target")}return l.prototype.ngOnInit=function(){var l=this,n=[this.iscsiService.listTargets(),this.rbdService.list(),this.iscsiService.portals(),this.iscsiService.settings(),this.iscsiService.version()];this.router.url.startsWith("/block/iscsi/targets/edit")&&(this.isEdit=!0,this.route.params.subscribe(function(e){l.target_iqn=decodeURIComponent(e.target_iqn),n.push(l.iscsiService.getTarget(l.target_iqn))})),this.action=this.isEdit?this.actionLabels.EDIT:this.actionLabels.CREATE,Object(i.a)(n).subscribe(function(n){var e=u(n[0]).filter(function(n){return n.target_iqn!==l.target_iqn}).flatMap(function(l){return l.disks}).map(function(l){return l.pool+"/"+l.image}).value();"api_version"in n[3]&&(l.api_version=n[3].api_version),l.minimum_gateways=n[3].config.minimum_gateways,l.target_default_controls=n[3].target_default_controls,l.target_controls_limits=n[3].target_controls_limits,l.disk_default_controls=n[3].disk_default_controls,l.disk_controls_limits=n[3].disk_controls_limits,l.backstores=n[3].backstores,l.default_backstore=n[3].default_backstore,l.unsupported_rbd_features=n[3].unsupported_rbd_features,l.required_rbd_features=n[3].required_rbd_features,l.imagesAll=u(n[1]).flatMap(function(l){return l.value}).filter(function(n){return-1===e.indexOf(n.pool_name+"/"+n.name)&&0!==l.getValidBackstores(n).length}).value(),l.imagesSelections=l.imagesAll.map(function(l){return new a.a(!1,l.pool_name+"/"+l.name,"")});var t=[];n[2].forEach(function(l){l.ip_addresses.forEach(function(n){t.push(new a.a(!1,l.name+":"+n,""))})}),l.portalsSelections=t.slice(),l.cephIscsiConfigVersion=n[4].ceph_iscsi_config_version,l.createForm(),n[5]&&l.resolveModel(n[5])})},l.prototype.createForm=function(){var l=this;if(this.targetForm=new r.a({target_iqn:new t.i("iqn.2001-07.com.ceph:"+Date.now(),{validators:[t.A.required,t.A.pattern(this.IQN_REGEX)]}),target_controls:new t.i({}),portals:new t.i([],{validators:[s.a.custom("minGateways",function(n){return u.uniq(n.map(function(l){return l.split(":")[0]})).length<Math.max(1,l.minimum_gateways)})]}),disks:new t.i([],{validators:[s.a.custom("dupLunId",function(n){var e=l.getLunIds(n);return e.length!==u.uniq(e).length}),s.a.custom("dupWwn",function(n){var e=l.getWwns(n);return e.length!==u.uniq(e).length})]}),initiators:new t.f([]),groups:new t.f([]),acl_enabled:new t.i(!1)}),this.cephIscsiConfigVersion>10){var n=new r.a({user:new t.i(""),password:new t.i(""),mutual_user:new t.i(""),mutual_password:new t.i("")});this.setAuthValidator(n),this.targetForm.addControl("auth",n)}},l.prototype.resolveModel=function(l){var n=this;this.targetForm.patchValue({target_iqn:l.target_iqn,target_controls:l.target_controls,acl_enabled:l.acl_enabled}),this.cephIscsiConfigVersion>10&&this.targetForm.patchValue({auth:l.auth});var e=[];u.forEach(l.portals,function(l){e.push(l.host+":"+l.ip)}),this.targetForm.patchValue({portals:e});var t=[];u.forEach(l.disks,function(l){var e=l.pool+"/"+l.image;t.push(e),n.imagesSettings[e]={backstore:l.backstore},n.imagesSettings[e][l.backstore]=l.controls,"lun"in l&&(n.imagesSettings[e].lun=l.lun),"wwn"in l&&(n.imagesSettings[e].wwn=l.wwn),n.onImageSelection({option:{name:e,selected:!0}})}),this.targetForm.patchValue({disks:t}),u.forEach(l.clients,function(l){var e=n.addInitiator();l.luns=u.map(l.luns,function(l){return l.pool+"/"+l.image}),e.patchValue(l)}),u.forEach(l.groups,function(l){var e=n.addGroup();l.disks=u.map(l.disks,function(l){return l.pool+"/"+l.image}),e.patchValue(l),u.forEach(l.members,function(l){n.onGroupMemberSelection({option:new a.a(!0,l,"")})})})},l.prototype.hasAdvancedSettings=function(l){return Object.values(l).length>0},Object.defineProperty(l.prototype,"portals",{get:function(){return this.targetForm.get("portals")},enumerable:!0,configurable:!0}),l.prototype.onPortalSelection=function(){this.portals.setValue(this.portals.value)},l.prototype.removePortal=function(l,n){return this.portalsSelections.forEach(function(l){l.name===n&&(l.selected=!1)}),this.portals.value.splice(l,1),this.portals.setValue(this.portals.value),!1},Object.defineProperty(l.prototype,"disks",{get:function(){return this.targetForm.get("disks")},enumerable:!0,configurable:!0}),l.prototype.removeImage=function(l,n){return this.imagesSelections.forEach(function(l){l.name===n&&(l.selected=!1)}),this.disks.value.splice(l,1),this.removeImageRefs(n),this.targetForm.get("disks").updateValueAndValidity({emitEvent:!1}),!1},l.prototype.removeImageRefs=function(l){var n=this;this.initiators.controls.forEach(function(n){var e=n.value.luns.filter(function(n){return n!==l});n.get("luns").setValue(e)}),this.groups.controls.forEach(function(n){var e=n.value.disks.filter(function(n){return n!==l});n.get("disks").setValue(e)}),u.forEach(this.imagesInitiatorSelections,function(e,t){n.imagesInitiatorSelections[t]=e.filter(function(n){return n.name!==l})}),u.forEach(this.groupDiskSelections,function(e,t){n.groupDiskSelections[t]=e.filter(function(n){return n.name!==l})})},l.prototype.getDefaultBackstore=function(l){var n=this,e=this.default_backstore,t=this.getImageById(l);return this.validFeatures(t,this.default_backstore)||this.backstores.forEach(function(l){l!==n.default_backstore&&n.validFeatures(t,l)&&(e=l)}),e},l.prototype.isLunIdInUse=function(l,n){var e=this.disks.value.filter(function(l){return l!==n});return this.getLunIds(e).includes(l)},l.prototype.getLunIds=function(l){var n=this;return u.map(l,function(l){return n.imagesSettings[l].lun})},l.prototype.nextLunId=function(l){for(var n=this.disks.value.filter(function(n){return n!==l}),e=this.getLunIds(n),t=0;e.includes(t);)t++;return t},l.prototype.getWwns=function(l){var n=this;return u.map(l,function(l){return n.imagesSettings[l].wwn}).filter(function(l){return u.isString(l)&&""!==l})},l.prototype.onImageSelection=function(l){var n=this,e=l.option;if(e.selected){if(this.imagesSettings[e.name])this.isLunIdInUse(this.imagesSettings[e.name].lun,e.name)&&(this.imagesSettings[e.name].lun=this.nextLunId(e.name));else{var t=this.getDefaultBackstore(e.name);this.imagesSettings[e.name]={backstore:t,lun:this.nextLunId(e.name)},this.imagesSettings[e.name][t]={}}u.forEach(this.imagesInitiatorSelections,function(l,t){l.push(new a.a(!1,e.name,"")),n.imagesInitiatorSelections[t]=l.slice()}),u.forEach(this.groupDiskSelections,function(l,t){l.push(new a.a(!1,e.name,"")),n.groupDiskSelections[t]=l.slice()})}else this.removeImageRefs(e.name);this.targetForm.get("disks").updateValueAndValidity({emitEvent:!1})},Object.defineProperty(l.prototype,"initiators",{get:function(){return this.targetForm.get("initiators")},enumerable:!0,configurable:!0}),l.prototype.addInitiator=function(){var l=this,n=new r.a({client_iqn:new t.i("",{validators:[t.A.required,s.a.custom("notUnique",function(n){var e=l.initiators.controls.reduce(function(l,n){return l.concat(n.value.client_iqn)},[]);return e.indexOf(n)!==e.lastIndexOf(n)}),t.A.pattern(this.IQN_REGEX)]}),auth:new r.a({user:new t.i(""),password:new t.i(""),mutual_user:new t.i(""),mutual_password:new t.i("")}),luns:new t.i([]),cdIsInGroup:new t.i(!1)});this.setAuthValidator(n),this.initiators.push(n),u.forEach(this.groupMembersSelections,function(n,e){n.push(new a.a(!1,"","")),l.groupMembersSelections[e]=n.slice()});var e=u.map(this.targetForm.getValue("disks"),function(l){return new a.a(!1,l,"")});return this.imagesInitiatorSelections.push(e),n},l.prototype.setAuthValidator=function(l){s.a.validateIf(l.get("user"),function(){return l.getValue("password")||l.getValue("mutual_user")||l.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.USER_REGEX)],[l.get("password"),l.get("mutual_user"),l.get("mutual_password")]),s.a.validateIf(l.get("password"),function(){return l.getValue("user")||l.getValue("mutual_user")||l.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.PASSWORD_REGEX)],[l.get("user"),l.get("mutual_user"),l.get("mutual_password")]),s.a.validateIf(l.get("mutual_user"),function(){return l.getValue("mutual_password")},[t.A.required],[t.A.pattern(this.USER_REGEX)],[l.get("user"),l.get("password"),l.get("mutual_password")]),s.a.validateIf(l.get("mutual_password"),function(){return l.getValue("mutual_user")},[t.A.required],[t.A.pattern(this.PASSWORD_REGEX)],[l.get("user"),l.get("password"),l.get("mutual_user")])},l.prototype.removeInitiator=function(l){var n=this,e=this.initiators.value[l];this.initiators.removeAt(l),u.forEach(this.groupMembersSelections,function(e,t){e.splice(l,1),n.groupMembersSelections[t]=e.slice()}),this.groups.controls.forEach(function(l){var n=l.value.members.filter(function(l){return l!==e.client_iqn});l.get("members").setValue(n)}),this.imagesInitiatorSelections.splice(l,1)},l.prototype.updatedInitiatorSelector=function(){var l=this;this.initiators.controls.forEach(function(l){l.get("client_iqn").updateValueAndValidity({emitEvent:!1})}),u.forEach(this.groupMembersSelections,function(n,e){u.forEach(n,function(n,e){var t=n.name;n.name=l.initiators.controls[e].value.client_iqn,l.groups.controls.forEach(function(l){var e=l.value.members,u=e.indexOf(t);-1!==u&&(e[u]=n.name),l.get("members").setValue(e)})}),l.groupMembersSelections[e]=l.groupMembersSelections[e].slice()})},l.prototype.removeInitiatorImage=function(l,n,e,t){var u=l.getValue("luns");return u.splice(n,1),l.patchValue({luns:u}),this.imagesInitiatorSelections[e].forEach(function(l){l.name===t&&(l.selected=!1)}),!1},Object.defineProperty(l.prototype,"groups",{get:function(){return this.targetForm.get("groups")},enumerable:!0,configurable:!0}),l.prototype.addGroup=function(){var l=new r.a({group_id:new t.i("",{validators:[t.A.required]}),members:new t.i([]),disks:new t.i([])});this.groups.push(l);var n=u.map(this.targetForm.getValue("disks"),function(l){return new a.a(!1,l,"")});this.groupDiskSelections.push(n);var e=u.map(this.initiators.value,function(l){return new a.a(!1,l.client_iqn,"",!l.cdIsInGroup)});return this.groupMembersSelections.push(e),l},l.prototype.removeGroup=function(l){this.groups.removeAt(l),this.groupDiskSelections.splice(l,1)},l.prototype.onGroupMemberSelection=function(l){var n,e=l.option;this.initiators.controls.forEach(function(l,t){l.value.client_iqn===e.name&&(l.patchValue({luns:[]}),l.get("cdIsInGroup").setValue(e.selected),n=t)}),u.forEach(this.groupMembersSelections,function(l){l[n].enabled=!e.selected})},l.prototype.removeGroupInitiator=function(l,n,e){var t=l.getValue("members")[n];l.getValue("members").splice(n,1),this.groupMembersSelections[e].forEach(function(l){l.name===t&&(l.selected=!1)}),this.groupMembersSelections[e]=this.groupMembersSelections[e].slice(),this.onGroupMemberSelection({option:new a.a(!1,t,"")})},l.prototype.removeGroupDisk=function(l,n,e){var t=l.getValue("disks")[n];l.getValue("disks").splice(n,1),this.groupDiskSelections[e].forEach(function(l){l.name===t&&(l.selected=!1)}),this.groupDiskSelections[e]=this.groupDiskSelections[e].slice()},l.prototype.submit=function(){var l,n=this,e=u.cloneDeep(this.targetForm.value),t={target_iqn:this.targetForm.getValue("target_iqn"),target_controls:this.targetForm.getValue("target_controls"),acl_enabled:this.targetForm.getValue("acl_enabled"),portals:[],disks:[],clients:[],groups:[]};if(this.cephIscsiConfigVersion>10){var i=this.targetForm.get("auth");i.getValue("user")||i.get("user").setValue(""),i.getValue("password")||i.get("password").setValue(""),i.getValue("mutual_user")||i.get("mutual_user").setValue(""),i.getValue("mutual_password")||i.get("mutual_password").setValue("");var o=this.targetForm.getValue("acl_enabled");t.auth={user:o?"":i.getValue("user"),password:o?"":i.getValue("password"),mutual_user:o?"":i.getValue("mutual_user"),mutual_password:o?"":i.getValue("mutual_password")}}e.disks.forEach(function(l){var e=l.split("/"),u=n.imagesSettings[l].backstore;t.disks.push({pool:e[0],image:e[1],backstore:u,controls:n.imagesSettings[l][u],lun:n.imagesSettings[l].lun,wwn:n.imagesSettings[l].wwn})}),e.portals.forEach(function(l){var n=l.indexOf(":");t.portals.push({host:l.substring(0,n),ip:l.substring(n+1)})}),t.acl_enabled&&(e.initiators.forEach(function(l){l.auth.user||(l.auth.user=""),l.auth.password||(l.auth.password=""),l.auth.mutual_user||(l.auth.mutual_user=""),l.auth.mutual_password||(l.auth.mutual_password=""),delete l.cdIsInGroup;var n=[];l.luns.forEach(function(l){var e=l.split("/");n.push({pool:e[0],image:e[1]})}),l.luns=n}),t.clients=e.initiators),t.acl_enabled&&(e.groups.forEach(function(l){var n=[];l.disks.forEach(function(l){var e=l.split("/");n.push({pool:e[0],image:e[1]})}),l.disks=n}),t.groups=e.groups),this.isEdit?(t.new_target_iqn=t.target_iqn,t.target_iqn=this.target_iqn,l=this.taskWrapper.wrapTaskAroundCall({task:new d.a("iscsi/target/edit",{target_iqn:t.target_iqn}),call:this.iscsiService.updateTarget(this.target_iqn,t)})):l=this.taskWrapper.wrapTaskAroundCall({task:new d.a("iscsi/target/create",{target_iqn:t.target_iqn}),call:this.iscsiService.createTarget(t)}),l.subscribe(void 0,function(){n.targetForm.setErrors({cdSubmitButton:!0})},function(){return n.router.navigate(["/block/iscsi/targets"])})},l.prototype.targetSettingsModal=function(){var l={target_controls:this.targetForm.get("target_controls"),target_default_controls:this.target_default_controls,target_controls_limits:this.target_controls_limits};this.modalRef=this.modalService.show(p.a,{initialState:l})},l.prototype.imageSettingsModal=function(l){var n={imagesSettings:this.imagesSettings,image:l,api_version:this.api_version,disk_default_controls:this.disk_default_controls,disk_controls_limits:this.disk_controls_limits,backstores:this.getValidBackstores(this.getImageById(l)),control:this.targetForm.get("disks")};this.modalRef=this.modalService.show(c.a,{initialState:n})},l.prototype.validFeatures=function(l,n){var e=l.features,t=this.required_rbd_features[n];return(e&t)===t&&0==(e&this.unsupported_rbd_features[n])},l.prototype.getImageById=function(l){return this.imagesAll.find(function(n){return l===n.pool_name+"/"+n.name})},l.prototype.getValidBackstores=function(l){var n=this;return this.backstores.filter(function(e){return n.validFeatures(l,e)})},l}()},jMP8:function(l,n,e){"use strict";e.d(n,"a",function(){return u});var t=e("gIcY"),u=(e("QFaf"),function(){function l(){}return l.prototype.ngOnInit=function(){var l=[];"min"in this.limits&&l.push(t.A.min(this.limits.min)),"max"in this.limits&&l.push(t.A.max(this.limits.max)),this.settingsForm.get(this.setting).setValidators(l)},l}())},"k/xb":function(l,n,e){"use strict";e.d(n,"a",function(){return u}),e.d(n,"b",function(){return v}),e.d(n,"c",function(){return i}),e.d(n,"d",function(){return o}),e.d(n,"g",function(){return a}),e.d(n,"h",function(){return r}),e.d(n,"i",function(){return s}),e.d(n,"j",function(){return d}),e.d(n,"k",function(){return c}),e.d(n,"l",function(){return p}),e.d(n,"m",function(){return m}),e.d(n,"n",function(){return f}),e.d(n,"e",function(){return g}),e.d(n,"f",function(){return h});var t=e("sne2"),u=(e("Vhfg"),e("gr3l"),e("e/kN"),e("roDX"),e("cxJu"),e("MyVl"),e("wG1H"),function(){return function(){}}()),i={breadcrumbs:"Images"},o={breadcrumbs:t.a.CREATE},a={breadcrumbs:t.a.EDIT},r={breadcrumbs:t.a.CLONE},s={breadcrumbs:t.a.COPY},d={breadcrumbs:t.a.COPY},c={breadcrumbs:"Mirroring"},p={breadcrumbs:"iSCSI"},m={breadcrumbs:"Overview"},f={breadcrumbs:"Targets"},g={breadcrumbs:t.a.CREATE},h={breadcrumbs:t.a.EDIT},v=function(){return function(){}}()},kccj:function(l,n,e){"use strict";e.d(n,"a",function(){return t});var t=function(){return function(){}}()},l7Jr:function(l,n,e){"use strict";var t=e("CcnG"),u=e("Ip0R"),i=e("eF8U"),o=e("jMP8"),a=e("EEJc"),r=e("ajRT"),s=e("gIcY"),d=e("gp3X"),c=e("sb0X"),p=e("KVJa"),m=e("Z21x"),f=e("sne2"),g=e("a6qe"),h=e("DQlY"),v=e("my5R");e.d(n,"a",function(){return w});var b=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function y(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"div",[["class","form-group row"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,u.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,2,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"cd-iscsi-setting",[],null,null,null,i.b,i.a)),t["\u0275did"](5,114688,null,0,o.a,[],{settingsForm:[0,"settingsForm"],formDir:[1,"formDir"],setting:[2,"setting"],limits:[3,"limits"]},null)],function(l,n){var e=n.component,u=l(n,2,0,e.settingsForm.showError(n.context.$implicit.key,t["\u0275nov"](n.parent,7)));l(n,1,0,"form-group row",u),l(n,5,0,e.settingsForm,t["\u0275nov"](n.parent,7),n.context.$implicit.key,e.getTargetControlLimits(n.context.$implicit.key))},null)}function C(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,22,"cd-modal",[],null,null,null,a.c,a.b)),t["\u0275did"](1,49152,null,0,r.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Advanced Settings"])),(l()(),t["\u0275eld"](4,0,null,1,18,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,17,"form",[["class","form"],["name","settingsForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,s.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,s.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,s.d,null,[s.l]),t["\u0275did"](9,16384,null,0,s.s,[[4,s.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,5,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,1,"p",[["class","alert-warning"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Changing these parameters from their default values is usually not necessary."])),(l()(),t["\u0275and"](16777216,null,null,2,null,y)),t["\u0275did"](14,278528,null,0,u.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),t["\u0275pid"](0,u.KeyValuePipe,[t.KeyValueDiffers]),(l()(),t["\u0275eld"](16,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](18,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.save()&&t),t},d.b,d.a)),t["\u0275did"](19,114688,null,0,c.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Confirm"])),(l()(),t["\u0275eld"](21,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,p.b,p.a)),t["\u0275did"](22,49152,null,0,m.a,[u.Location,f.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,7,0,e.settingsForm),l(n,14,0,t["\u0275unv"](n,14,0,t["\u0275nov"](n,15).transform(e.settingsForm.controls))),l(n,19,0,e.settingsForm),l(n,22,0,"Cancel",e.modalRef.hide)},function(l,n){l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function _(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-iqn-settings-modal",[],null,null,null,C,b)),t["\u0275did"](1,114688,null,0,g.a,[h.a,v.a],null,null)],function(l,n){l(n,1,0)},null)}var w=t["\u0275ccf"]("cd-iscsi-target-iqn-settings-modal",g.a,_,{},{},[])},"lz+O":function(l,n,e){"use strict";var t=e("CcnG"),u=e("gIcY"),i=e("ANnk"),o=e("f/UV"),a=e("aexS"),r=e("Ip0R"),s=e("EEJc"),d=e("ajRT"),c=e("gp3X"),p=e("sb0X"),m=e("KVJa"),f=e("Z21x"),g=e("sne2"),h=e("WxU5"),v=e("F83c"),b=e("DQlY"),y=e("2EZI"),C=e("Ekvf"),_=e("kn/O");e.d(n,"a",function(){return F});var w=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","poolName"],["placeholder","Pool name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,1)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,1).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,1)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](1,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](3,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](5,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](6,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null)],function(l,n){l(n,3,0,"poolName")},function(l,n){l(n,0,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending)})}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,12,"select",[["class","form-control"],["formControlName","poolName"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==t["\u0275nov"](l,1).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,1).onTouched()&&u),u},null,null)),t["\u0275did"](1,16384,null,0,u.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.z]),t["\u0275did"](3,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](5,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](6,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](7,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),t["\u0275did"](8,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{value:[0,"value"]},null),t["\u0275did"](9,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["All"])),(l()(),t["\u0275and"](16777216,null,null,1,null,I)),t["\u0275did"](12,278528,null,0,r.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,3,0,"poolName"),l(n,8,0,""),l(n,9,0,""),l(n,12,0,e.pools)},function(l,n){l(n,0,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending)})}function k(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,37,"cd-modal",[],null,null,null,s.c,s.b)),t["\u0275did"](1,49152,null,0,d.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Purge Trash"])),(l()(),t["\u0275eld"](4,0,null,1,33,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,32,"form",[["class","form"],["name","purgeForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,u.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,u.d,null,[u.l]),t["\u0275did"](9,16384,null,0,u.s,[[4,u.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,20,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,12,"p",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["To purge, select one or"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](15,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["All"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](18,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["pools and click"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](21,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Purge Trash"])),(l()(),t["\u0275ted"](-1,null,[".\xa0 "])),(l()(),t["\u0275eld"](24,0,null,null,6,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](25,0,null,null,1,"label",[["class","center-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Pool:"])),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](28,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,S)),t["\u0275did"](30,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](31,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](32,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](33,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.purge()&&t),t},c.b,c.a)),t["\u0275did"](34,114688,null,0,p.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Purge Trash"])),(l()(),t["\u0275eld"](36,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,m.b,m.a)),t["\u0275did"](37,49152,null,0,f.a,[r.Location,g.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,7,0,e.purgeForm),l(n,28,0,!e.poolPermission.read),l(n,30,0,e.poolPermission.read),l(n,34,0,e.purgeForm),l(n,37,0,"Cancel",e.modalRef.hide)},function(l,n){l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function E(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rbd-trash-purge-modal",[],null,null,null,k,w)),t["\u0275did"](1,114688,null,0,h.a,[a.a,v.a,b.a,y.a,C.a,_.a],null,null)],function(l,n){l(n,1,0)},null)}var F=t["\u0275ccf"]("cd-rbd-trash-purge-modal",h.a,E,{},{},[])},my5R:function(l,n,e){"use strict";e.d(n,"a",function(){return r});var t=e("mrSG"),u=e("t/Na"),i=e("xTzq"),o=e("CcnG"),a=e("pL04"),r=function(){function l(l){this.http=l}return l.prototype.listTargets=function(){return this.http.get("api/iscsi/target")},l.prototype.getTarget=function(l){return this.http.get("api/iscsi/target/"+l)},l.prototype.updateTarget=function(l,n){return this.http.put("api/iscsi/target/"+l,n,{observe:"response"})},l.prototype.status=function(){return this.http.get("ui-api/iscsi/status")},l.prototype.settings=function(){return this.http.get("ui-api/iscsi/settings")},l.prototype.version=function(){return this.http.get("ui-api/iscsi/version")},l.prototype.portals=function(){return this.http.get("ui-api/iscsi/portals")},l.prototype.createTarget=function(l){return this.http.post("api/iscsi/target",l,{observe:"response"})},l.prototype.deleteTarget=function(l){return this.http.delete("api/iscsi/target/"+l,{observe:"response"})},l.prototype.getDiscovery=function(){return this.http.get("api/iscsi/discoveryauth")},l.prototype.updateDiscovery=function(l){return this.http.put("api/iscsi/discoveryauth",l)},l.prototype.overview=function(){return this.http.get("ui-api/iscsi/overview")},l.ngInjectableDef=o.defineInjectable({factory:function(){return new l(o.inject(u.c))},token:l,providedIn:a.a}),l=t.__decorate([i.a,t.__metadata("design:paramtypes",[u.c])],l)}()},nP0W:function(l,n,e){"use strict";var t=e("CcnG"),u=e("gIcY"),i=e("EEJc"),o=e("ajRT"),a=e("Ip0R"),r=e("ANnk"),s=e("f/UV"),d=e("aexS"),c=e("gp3X"),p=e("sb0X"),m=e("KVJa"),f=e("Z21x"),g=e("sne2"),h=e("aa9H"),v=e("DQlY"),b=e("Jm/i"),y=e("XED3"),C=e("kn/O");e.d(n,"a",function(){return k});var _=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function w(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit.id),l(n,2,0,n.context.$implicit.id)},function(l,n){l(n,3,0,n.context.$implicit.name)})}function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Peer clusters must be removed prior to disabling mirror."]))],null,null)}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,43,"cd-modal",[],null,null,null,i.c,i.b)),t["\u0275did"](1,49152,null,0,o.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Edit pool mirror mode"])),(l()(),t["\u0275eld"](4,0,null,1,39,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,38,"form",[["class","form"],["name","editModeForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,7).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,7).onReset()&&u),u},null,null)),t["\u0275did"](6,16384,null,0,u.D,[],null,null),t["\u0275did"](7,540672,[["formDir",4]],0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,u.d,null,[u.l]),t["\u0275did"](9,16384,null,0,u.s,[[4,u.d]],null,null),(l()(),t["\u0275eld"](10,0,null,null,26,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,8,"p",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,7,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["To edit the mirror mode for pool\xa0 "])),(l()(),t["\u0275eld"](14,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](15,null,["",""])),(l()(),t["\u0275ted"](-1,null,[", select a new mode from the list and click\xa0 "])),(l()(),t["\u0275eld"](17,0,null,null,1,"kbd",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Update"])),(l()(),t["\u0275ted"](-1,null,["."])),(l()(),t["\u0275eld"](20,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](21,278528,null,0,a.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](22,{"has-error":0}),(l()(),t["\u0275eld"](23,0,null,null,2,"label",[["class","control-label"],["for","mirrorMode"]],null,null,null,null,null)),(l()(),t["\u0275eld"](24,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Mode"])),(l()(),t["\u0275eld"](26,0,null,null,8,"select",[["class","form-control"],["formControlName","mirrorMode"],["id","mirrorMode"],["name","mirrorMode"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==t["\u0275nov"](l,28).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,28).onTouched()&&u),u},null,null)),t["\u0275did"](27,4210688,null,0,r.a,[[2,s.a],d.a,t.ElementRef],null,null),t["\u0275did"](28,16384,null,0,u.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.z]),t["\u0275did"](30,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](32,16384,null,0,u.r,[[4,u.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,w)),t["\u0275did"](34,278528,null,0,a.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](36,16384,null,0,a.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](37,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](38,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.update()&&t),t},c.b,c.a)),t["\u0275did"](40,114688,null,0,p.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Update"])),(l()(),t["\u0275eld"](42,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,m.b,m.a)),t["\u0275did"](43,49152,null,0,f.a,[a.Location,g.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,1,0,e.modalRef),l(n,7,0,e.editModeForm);var u=l(n,22,0,e.editModeForm.showError("mirrorMode",t["\u0275nov"](n,7)));l(n,21,0,"form-group",u),l(n,30,0,"mirrorMode"),l(n,34,0,e.mirrorModes),l(n,36,0,e.editModeForm.showError("mirrorMode",t["\u0275nov"](n,7),"cannotDisable")),l(n,40,0,e.editModeForm),l(n,43,0,"Cancel",e.modalRef.hide)},function(l,n){var e=n.component;l(n,5,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending),l(n,15,0,e.poolName),l(n,26,0,t["\u0275nov"](n,32).ngClassUntouched,t["\u0275nov"](n,32).ngClassTouched,t["\u0275nov"](n,32).ngClassPristine,t["\u0275nov"](n,32).ngClassDirty,t["\u0275nov"](n,32).ngClassValid,t["\u0275nov"](n,32).ngClassInvalid,t["\u0275nov"](n,32).ngClassPending)})}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-pool-edit-mode-modal",[],null,null,null,I,_)),t["\u0275did"](1,245760,null,0,h.a,[v.a,b.a,y.a,C.a],null,null)],function(l,n){l(n,1,0)},null)}var k=t["\u0275ccf"]("cd-pool-edit-mode-modal",h.a,S,{},{},[])},nhAp:function(l,n,e){"use strict";var t=e("CcnG"),u=e("gIcY"),i=e("ANnk"),o=e("f/UV"),a=e("aexS"),r=e("Ip0R"),s=e("eF8U"),d=e("jMP8"),c=e("uYzU"),p=e("EEJc"),m=e("ajRT"),f=e("gp3X"),g=e("sb0X"),h=e("KVJa"),v=e("Z21x"),b=e("sne2"),y=e("Z4cD"),C=e("DQlY"),_=e("my5R");e.d(n,"a",function(){return T});var w=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function R(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","invalid-feedback"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function I(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,29,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[["class","cd-header"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Identifier"])),(l()(),t["\u0275eld"](3,0,null,null,15,"div",[["class","form-group row"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,14,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,3,"label",[["class","col-form-label"],["for","lun"]],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["lun"])),(l()(),t["\u0275eld"](8,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,7,"input",[["class","form-control"],["formControlName","lun"],["id","lun"],["name","lun"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,10)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,10).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,10)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,10)._compositionEnd(e.target.value)&&u),"change"===n&&(u=!1!==t["\u0275nov"](l,11).onChange(e.target.value)&&u),"input"===n&&(u=!1!==t["\u0275nov"](l,11).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,11).onTouched()&&u),u},null,null)),t["\u0275did"](10,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275did"](11,16384,null,0,u.C,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l,n){return[l,n]},[u.e,u.C]),t["\u0275did"](13,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](15,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](16,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,R)),t["\u0275did"](18,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](19,0,null,null,10,"div",[["class","form-group row"]],null,null,null,null,null)),(l()(),t["\u0275eld"](20,0,null,null,9,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](21,0,null,null,1,"label",[["class","col-form-label"],["for","wwn"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["wwn"])),(l()(),t["\u0275eld"](23,0,null,null,6,"input",[["class","form-control"],["formControlName","wwn"],["id","wwn"],["name","wwn"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var u=!0;return"input"===n&&(u=!1!==t["\u0275nov"](l,24)._handleInput(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,24).onTouched()&&u),"compositionstart"===n&&(u=!1!==t["\u0275nov"](l,24)._compositionStart()&&u),"compositionend"===n&&(u=!1!==t["\u0275nov"](l,24)._compositionEnd(e.target.value)&&u),u},null,null)),t["\u0275did"](24,16384,null,0,u.e,[t.Renderer2,t.ElementRef,[2,u.b]],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.e]),t["\u0275did"](26,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](28,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](29,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null)],function(l,n){var e=n.component;l(n,13,0,"lun"),l(n,18,0,e.settingsForm.showError("lun",t["\u0275nov"](n.parent,12),"required")),l(n,26,0,"wwn")},function(l,n){l(n,9,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending),l(n,23,0,t["\u0275nov"](n,28).ngClassUntouched,t["\u0275nov"](n,28).ngClassTouched,t["\u0275nov"](n,28).ngClassPristine,t["\u0275nov"](n,28).ngClassDirty,t["\u0275nov"](n,28).ngClassValid,t["\u0275nov"](n,28).ngClassInvalid,t["\u0275nov"](n,28).ngClassPending)})}function S(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,4,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,u.v,[t.ElementRef,t.Renderer2,[2,u.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,u.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""])),t["\u0275ppd"](4,1)],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){var e=t["\u0275unv"](n,3,0,l(n,4,0,t["\u0275nov"](n.parent,0),n.context.$implicit));l(n,3,0,e)})}function k(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"div",[["class","form-group row"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,r.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,2,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"cd-iscsi-setting",[],null,null,null,s.b,s.a)),t["\u0275did"](5,114688,null,0,d.a,[],{settingsForm:[0,"settingsForm"],formDir:[1,"formDir"],setting:[2,"setting"],limits:[3,"limits"]},null)],function(l,n){var e=n.component,u=l(n,2,0,e.settingsForm.showError(n.context.$implicit.key,t["\u0275nov"](n.parent.parent.parent,12)));l(n,1,0,"form-group row",u),l(n,5,0,e.settingsForm,t["\u0275nov"](n.parent.parent.parent,12),n.context.$implicit.key,e.getDiskControlLimits(n.parent.parent.context.$implicit,n.context.$implicit.key))},null)}function E(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,null,null,null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,2,null,k)),t["\u0275did"](2,278528,null,0,r.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),t["\u0275pid"](0,r.KeyValuePipe,[t.KeyValueDiffers]),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){var e=n.component;l(n,2,0,t["\u0275unv"](n,2,0,t["\u0275nov"](n,3).transform(e.disk_default_controls[n.parent.context.$implicit])))},null)}function F(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,null,null,null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,E)),t["\u0275did"](2,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,2,0,n.component.settingsForm.value.backstore===n.context.$implicit)},null)}function D(l){return t["\u0275vid"](0,[t["\u0275pid"](0,c.a,[]),(l()(),t["\u0275eld"](1,0,null,null,42,"cd-modal",[],null,null,null,p.c,p.b)),t["\u0275did"](2,49152,null,0,m.a,[],{modalRef:[0,"modalRef"]},null),(l()(),t["\u0275eld"](3,0,null,0,5,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Configure"])),(l()(),t["\u0275ted"](-1,null,["\xa0 "])),(l()(),t["\u0275eld"](7,0,null,null,1,"small",[],null,null,null,null,null)),(l()(),t["\u0275ted"](8,null,["",""])),(l()(),t["\u0275eld"](9,0,null,1,34,null,null,null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,33,"form",[["class","form"],["name","settingsForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var u=!0;return"submit"===n&&(u=!1!==t["\u0275nov"](l,12).onSubmit(e)&&u),"reset"===n&&(u=!1!==t["\u0275nov"](l,12).onReset()&&u),u},null,null)),t["\u0275did"](11,16384,null,0,u.D,[],null,null),t["\u0275did"](12,540672,[["formDir",4]],0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,u.d,null,[u.l]),t["\u0275did"](14,16384,null,0,u.s,[[4,u.d]],null,null),(l()(),t["\u0275eld"](15,0,null,null,21,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,1,"p",[["class","alert-warning"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Changing these parameters from their default values is usually not necessary."])),(l()(),t["\u0275and"](16777216,null,null,1,null,I)),t["\u0275did"](19,16384,null,0,r.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](20,0,null,null,1,"legend",[["class","cd-header"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Settings"])),(l()(),t["\u0275eld"](22,0,null,null,12,"div",[["class","form-group row"]],null,null,null,null,null)),(l()(),t["\u0275eld"](23,0,null,null,11,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),t["\u0275eld"](24,0,null,null,1,"label",[["class","control-label"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Backstore"])),(l()(),t["\u0275eld"](26,0,null,null,8,"select",[["class","form-control"],["formControlName","backstore"],["id","backstore"],["name","backstore"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==t["\u0275nov"](l,27).onChange(e.target.value)&&u),"blur"===n&&(u=!1!==t["\u0275nov"](l,27).onTouched()&&u),u},null,null)),t["\u0275did"](27,16384,null,0,u.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,u.p,function(l){return[l]},[u.z]),t["\u0275did"](29,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,u.q,null,[u.j]),t["\u0275did"](31,16384,null,0,u.r,[[4,u.q]],null,null),t["\u0275did"](32,4210688,null,0,i.a,[[2,o.a],a.a,t.ElementRef],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,S)),t["\u0275did"](34,278528,null,0,r.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,F)),t["\u0275did"](36,278528,null,0,r.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275eld"](37,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](38,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var t=!0;return"submitAction"===n&&(t=!1!==l.component.save()&&t),t},f.b,f.a)),t["\u0275did"](40,114688,null,0,g.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](-1,0,["Confirm"])),(l()(),t["\u0275eld"](42,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,h.b,h.a)),t["\u0275did"](43,49152,null,0,v.a,[r.Location,b.b],{name:[0,"name"],back:[1,"back"]},null)],function(l,n){var e=n.component;l(n,2,0,e.modalRef),l(n,12,0,e.settingsForm),l(n,19,0,e.api_version>=1),l(n,29,0,"backstore"),l(n,34,0,e.backstores),l(n,36,0,e.backstores),l(n,40,0,e.settingsForm),l(n,43,0,"Cancel",e.modalRef.hide)},function(l,n){l(n,8,0,n.component.image),l(n,10,0,t["\u0275nov"](n,14).ngClassUntouched,t["\u0275nov"](n,14).ngClassTouched,t["\u0275nov"](n,14).ngClassPristine,t["\u0275nov"](n,14).ngClassDirty,t["\u0275nov"](n,14).ngClassValid,t["\u0275nov"](n,14).ngClassInvalid,t["\u0275nov"](n,14).ngClassPending),l(n,26,0,t["\u0275nov"](n,31).ngClassUntouched,t["\u0275nov"](n,31).ngClassTouched,t["\u0275nov"](n,31).ngClassPristine,t["\u0275nov"](n,31).ngClassDirty,t["\u0275nov"](n,31).ngClassValid,t["\u0275nov"](n,31).ngClassInvalid,t["\u0275nov"](n,31).ngClassPending)})}function V(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-image-settings-modal",[],null,null,null,D,w)),t["\u0275did"](1,114688,null,0,y.a,[C.a,_.a],null,null)],function(l,n){l(n,1,0)},null)}var T=t["\u0275ccf"]("cd-iscsi-target-image-settings-modal",y.a,V,{},{},[])},o8EM:function(l,n,e){"use strict";e.d(n,"a",function(){return o});var t=e("PhyI"),u=e("CcnG"),i=e("Jm/i"),o=function(){function l(l){this.i18n=l,this.sections=[{heading:this.i18n("Quality of Service"),class:"quality-of-service",options:[{name:"rbd_qos_bps_limit",displayName:this.i18n("BPS Limit"),description:this.i18n("The desired limit of IO bytes per second."),type:t.b.bps},{name:"rbd_qos_iops_limit",displayName:this.i18n("IOPS Limit"),description:this.i18n("The desired limit of IO operations per second."),type:t.b.iops},{name:"rbd_qos_read_bps_limit",displayName:this.i18n("Read BPS Limit"),description:this.i18n("The desired limit of read bytes per second."),type:t.b.bps},{name:"rbd_qos_read_iops_limit",displayName:this.i18n("Read IOPS Limit"),description:this.i18n("The desired limit of read operations per second."),type:t.b.iops},{name:"rbd_qos_write_bps_limit",displayName:this.i18n("Write BPS Limit"),description:this.i18n("The desired limit of write bytes per second."),type:t.b.bps},{name:"rbd_qos_write_iops_limit",displayName:this.i18n("Write IOPS Limit"),description:this.i18n("The desired limit of write operations per second."),type:t.b.iops},{name:"rbd_qos_bps_burst",displayName:this.i18n("BPS Burst"),description:this.i18n("The desired burst limit of IO bytes."),type:t.b.bps},{name:"rbd_qos_iops_burst",displayName:this.i18n("IOPS Burst"),description:this.i18n("The desired burst limit of IO operations."),type:t.b.iops},{name:"rbd_qos_read_bps_burst",displayName:this.i18n("Read BPS Burst"),description:this.i18n("The desired burst limit of read bytes."),type:t.b.bps},{name:"rbd_qos_read_iops_burst",displayName:this.i18n("Read IOPS Burst"),description:this.i18n("The desired burst limit of read operations."),type:t.b.iops},{name:"rbd_qos_write_bps_burst",displayName:this.i18n("Write BPS Burst"),description:this.i18n("The desired burst limit of write bytes."),type:t.b.bps},{name:"rbd_qos_write_iops_burst",displayName:this.i18n("Write IOPS Burst"),description:this.i18n("The desired burst limit of write operations."),type:t.b.iops}]}]}return l.getOptionsFromSections=function(l){return l.map(function(l){return l.options}).reduce(function(l,n){return l.concat(n)})},l.prototype.filterConfigOptionsByName=function(n){return l.getOptionsFromSections(this.sections).filter(function(l){return l.name===n})},l.prototype.getOptionValueByName=function(l,n,e){void 0===e&&(e="");var t=this.filterConfigOptionsByName(l);return 1===t.length?t.pop()[n]:e},l.prototype.getWritableSections=function(){return this.sections.map(function(l){return l.options=l.options.filter(function(l){return!l.readOnly}),l})},l.prototype.getOptionFields=function(){return l.getOptionsFromSections(this.sections)},l.prototype.getWritableOptionFields=function(){return l.getOptionsFromSections(this.getWritableSections())},l.prototype.getOptionByName=function(l){return this.filterConfigOptionsByName(l).pop()},l.prototype.getDisplayName=function(l){return this.getOptionValueByName(l,"displayName")},l.prototype.getDescription=function(l){return this.getOptionValueByName(l,"description")},l.ngInjectableDef=u.defineInjectable({factory:function(){return new l(u.inject(i.a))},token:l,providedIn:"root"}),l}()},rFfW:function(l,n,e){"use strict";e.d(n,"a",function(){return a});var t=e("CcnG"),u=e("gIcY"),i=e("QFaf"),o=e("PhyI"),a=(e("aXbf"),e("o8EM"),function(){function l(l,n){this.formatterService=l,this.rbdConfigurationService=n,this.changes=new t.EventEmitter,this.ngDataReady=new t.EventEmitter,this.configurationType=o.b,this.sectionVisibility={}}return l.prototype.ngOnInit=function(){var l=this,n=this.createConfigurationFormGroup();this.form.addControl("configuration",n),n.valueChanges.subscribe(function(){l.changes.emit(l.getDirtyValues.bind(l))}),this.initializeData&&this.initializeData.subscribe(function(n){l.initialData=n.initialData;var e=n.sourceType;l.rbdConfigurationService.getWritableOptionFields().forEach(function(t){var u=n.initialData.filter(function(l){return l.name===t.name}).pop();u&&u.source===e&&l.form.get("configuration."+t.name).setValue(u.value)}),l.ngDataReady.emit()}),this.rbdConfigurationService.getWritableSections().forEach(function(n){return l.sectionVisibility[n.class]=!1})},l.prototype.getDirtyValues=function(l,n){var e=this;if(void 0===l&&(l=!1),l&&!n)throw new Error("ProgrammingError: If local values shall be included, a proper localFieldType argument has to be provided, too");var t={};return this.rbdConfigurationService.getWritableOptionFields().forEach(function(u){var i=e.form.get("configuration").get(u.name);e.initialData&&e.initialData[u.name]===i.value||(i.dirty||l&&i.source===n)&&(t[u.name]=null===i.value?i.value:u.type===o.b.bps?e.formatterService.toBytes(i.value):u.type===o.b.milliseconds?e.formatterService.toMilliseconds(i.value):u.type===o.b.iops?e.formatterService.toIops(i.value):i.value)}),t},l.prototype.createConfigurationFormGroup=function(){var l=new i.a({});return this.rbdConfigurationService.getWritableOptionFields().forEach(function(n){var e;if(n.type!==o.b.milliseconds&&n.type!==o.b.iops&&n.type!==o.b.bps)throw new Error("Type "+n.type+" is unknown, you may need to add it to RbdConfiguration class");e=new u.i(0,u.A.min(0)),l.addControl(n.name,e)}),l},l.prototype.reset=function(l){var n=this.form.get("configuration").get(l);n.disabled?(n.setValue(n.previousValue||0),n.enable(),n.previousValue||n.markAsPristine()):(n.previousValue=n.value,n.setValue(null),n.markAsDirty(),n.disable())},l.prototype.isDisabled=function(l){return this.form.get("configuration").get(l).disabled},l.prototype.toggleSectionVisibility=function(l){this.sectionVisibility[l]=!this.sectionVisibility[l]},l}())},roDX:function(l,n,e){"use strict";e.d(n,"a",function(){return t}),e("my5R"),e("o4+5"),e("uYzU");var t=function(){function l(l,n,e,t){this.iscsiService=l,this.dimlessPipe=n,this.iscsiBackstorePipe=e,this.i18n=t,this.gateways=[],this.images=[]}return l.prototype.ngOnInit=function(){this.gatewaysColumns=[{name:this.i18n("Name"),prop:"name"},{name:this.i18n("State"),prop:"state",cellTemplate:this.statusColorTpl},{name:this.i18n("# Targets"),prop:"num_targets"},{name:this.i18n("# Sessions"),prop:"num_sessions"}],this.imagesColumns=[{name:this.i18n("Pool"),prop:"pool"},{name:this.i18n("Image"),prop:"image"},{name:this.i18n("Backstore"),prop:"backstore",pipe:this.iscsiBackstorePipe},{name:this.i18n("Read Bytes"),prop:"stats_history.rd_bytes",cellTemplate:this.iscsiSparklineTpl},{name:this.i18n("Write Bytes"),prop:"stats_history.wr_bytes",cellTemplate:this.iscsiSparklineTpl},{name:this.i18n("Read Ops"),prop:"stats.rd",pipe:this.dimlessPipe,cellTemplate:this.iscsiPerSecondTpl},{name:this.i18n("Write Ops"),prop:"stats.wr",pipe:this.dimlessPipe,cellTemplate:this.iscsiPerSecondTpl},{name:this.i18n("A/O Since"),prop:"optimized_since",cellTemplate:this.iscsiRelativeDateTpl}]},l.prototype.refresh=function(){var l=this;this.iscsiService.overview().subscribe(function(n){l.gateways=n.gateways,l.images=n.images,l.images.map(function(l){return l.stats_history&&(l.stats_history.rd_bytes=l.stats_history.rd_bytes.map(function(l){return l[1]}),l.stats_history.wr_bytes=l.stats_history.wr_bytes.map(function(l){return l[1]})),l.cdIsBinary=!0,l})})},l}()},u0yg:function(l,n,e){"use strict";e.d(n,"b",function(){return t}),e.d(n,"a",function(){return u});var t=function(){return function(){}}(),u=function(l){return l[l.V1=1]="V1",l[l.V2=2]="V2",l}({})},u2XS:function(l,n,e){"use strict";var t=e("CcnG"),u=e("Ip0R"),i=e("25BL"),o=e("uIqm"),a=e("nuQ0"),r=e("Tff5"),s=e("urB8"),d=e("xtUU"),c=e("3ris"),p=e("Jm/i"),m=e("uYzU"),f=e("iExv");e.d(n,"b",function(){return g}),e.d(n,"c",function(){return _}),e.d(n,"a",function(){return R});var g=t["\u0275crt"]({encapsulation:0,styles:[["tree .fa{font-weight:unset!important}"]],data:{}});function h(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","node-name"]],[[8,"innerHTML",1]],null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xa0"])),(l()(),t["\u0275eld"](3,0,null,null,5,"span",[["class","label"]],null,null,null,null,null)),t["\u0275did"](4,278528,null,0,u.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pad"](5,1),t["\u0275pad"](6,1),t["\u0275pod"](7,{"label-success":0,"label-danger":1}),(l()(),t["\u0275ted"](8,null,[" "," "]))],function(l,n){var e=l(n,7,0,l(n,5,0,"logged_in").includes(n.context.$implicit.status),l(n,6,0,"logged_out").includes(n.context.$implicit.status));l(n,4,0,"label",e)},function(l,n){l(n,0,0,n.context.$implicit.value),l(n,8,0,n.context.$implicit.status)})}function v(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,4,"div",[["class","col-sm-6 col-lg-6 metadata"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](2,null,["",""])),(l()(),t["\u0275eld"](3,0,null,null,1,"cd-table",[["columnMode","flex"]],null,null,null,i.b,i.a)),t["\u0275did"](4,2867200,[[2,4],["detailTable",4]],0,o.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],limit:[3,"limit"]},null)],function(l,n){var e=n.component;l(n,4,0,e.data,e.columns,"flex",0)},function(l,n){l(n,2,0,n.component.title)})}function b(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""]))],null,function(l,n){l(n,1,0,n.parent.context.value)})}function y(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,["",""]))],null,function(l,n){l(n,1,0,n.parent.context.value)})}function C(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,b)),t["\u0275did"](1,16384,null,0,u.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,y)),t["\u0275did"](3,16384,null,0,u.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,void 0===n.context.row.default||n.context.row.default===n.context.row.current),l(n,3,0,void 0!==n.context.row.default&&n.context.row.default!==n.context.row.current)},null)}function _(l){return t["\u0275vid"](0,[t["\u0275qud"](402653184,1,{highlightTpl:0}),t["\u0275qud"](671088640,2,{content:0}),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","col-sm-6 col-lg-6"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["iSCSI Topology"])),(l()(),t["\u0275eld"](5,0,null,null,4,"tree",[],null,[[null,"nodeSelected"]],function(l,n,e){var t=!0;return"nodeSelected"===n&&(t=!1!==l.component.onNodeSelected(e)&&t),t},a.b,a.a)),t["\u0275prd"](512,null,r.TreeService,r.TreeService,[s.NodeDraggableService]),t["\u0275did"](7,770048,null,1,d.TreeComponent,[r.TreeService],{treeModel:[0,"treeModel"]},{nodeSelected:"nodeSelected"}),t["\u0275qud"](335544320,3,{template:0}),(l()(),t["\u0275and"](0,[[3,2]],null,0,null,h)),(l()(),t["\u0275and"](16777216,null,null,1,null,v)),t["\u0275did"](11,16384,null,0,u.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](0,[[1,2],["highlightTpl",2]],null,0,null,C))],function(l,n){var e=n.component;l(n,7,0,e.tree),l(n,11,0,e.data)},null)}function w(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-details",[],null,null,null,_,g)),t["\u0275did"](1,638976,null,0,c.a,[p.a,m.a,f.a],null,null)],function(l,n){l(n,1,0)},null)}var R=t["\u0275ccf"]("cd-iscsi-target-details",c.a,w,{selection:"selection",settings:"settings",cephIscsiConfigVersion:"cephIscsiConfigVersion"},{},[])},wG1H:function(l,n,e){"use strict";e.d(n,"a",function(){return t}),e("aexS");var t=function(){function l(l){this.authStorageService=l,this.grafanaPermission=this.authStorageService.getPermissions().grafana}return l.prototype.ngOnInit=function(){},l}()}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/3rdpartylicenses.txt b/src/pybind/mgr/dashboard/frontend/dist/en-US/3rdpartylicenses.txt
new file mode 100644
index 00000000..ebb3801d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/3rdpartylicenses.txt
@@ -0,0 +1,1462 @@
+@angular/animations
+MIT
+
+@angular/common
+MIT
+
+@angular/core
+MIT
+
+@angular/forms
+MIT
+
+@angular/platform-browser
+MIT
+
+@angular/router
+MIT
+
+@ngx-translate/i18n-polyfill
+MIT
+
+@swimlane/ngx-datatable
+MIT
+(The MIT License)
+
+Copyright (c) 2016 Swimlane <info@swimlane.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+awesome-bootstrap-checkbox
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2014 flatlogic.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+bootstrap
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2011-2019 Twitter, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+chart.js
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2018 Chart.js Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+chartjs-color
+MIT
+Copyright (c) 2012 Heather Arthur
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+chartjs-color-string
+MIT
+Copyright (c) 2011 Heather Arthur <fayearthur@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+color-convert
+Copyright (c) 2011 Heather Arthur <fayearthur@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+color-name
+MIT
+The MIT License (MIT)
+Copyright (c) 2015 Dmitry Ivanov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+core-js
+MIT
+Copyright (c) 2014-2019 Denis Pushkarev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+detect-browser
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2019 Damon Oehlman <damon.oehlman@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+fork-awesome
+(OFL-1.1 AND MIT)
+/!\ The MIT License only applies to all CSS and LESS files in the following
+directories: fork-awesome/css/, fork-awesome/less/, and fork-awesome/scss/.
+
+MIT License
+
+Copyright (c) 2018 Dave Gandy & Fork Awesome
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*******************************************************************************
+
+/!\ The Creative Commons Attribution 3.0 Unported License applies to all Fork
+Awesome project files that are not a part of the Font or Code licenses.
+
+Creative Commons Legal Code
+
+Attribution 3.0 Unported
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+ DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+ other pre-existing works, such as a translation, adaptation,
+ derivative work, arrangement of music or other alterations of a
+ literary or artistic work, or phonogram or performance and includes
+ cinematographic adaptations or any other form in which the Work may be
+ recast, transformed, or adapted including in any form recognizably
+ derived from the original, except that a work that constitutes a
+ Collection will not be considered an Adaptation for the purpose of
+ this License. For the avoidance of doubt, where the Work is a musical
+ work, performance or phonogram, the synchronization of the Work in
+ timed-relation with a moving image ("synching") will be considered an
+ Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+ encyclopedias and anthologies, or performances, phonograms or
+ broadcasts, or other works or subject matter other than works listed
+ in Section 1(f) below, which, by reason of the selection and
+ arrangement of their contents, constitute intellectual creations, in
+ which the Work is included in its entirety in unmodified form along
+ with one or more other contributions, each constituting separate and
+ independent works in themselves, which together are assembled into a
+ collective whole. A work that constitutes a Collection will not be
+ considered an Adaptation (as defined above) for the purposes of this
+ License.
+ c. "Distribute" means to make available to the public the original and
+ copies of the Work or Adaptation, as appropriate, through sale or
+ other transfer of ownership.
+ d. "Licensor" means the individual, individuals, entity or entities that
+ offer(s) the Work under the terms of this License.
+ e. "Original Author" means, in the case of a literary or artistic work,
+ the individual, individuals, entity or entities who created the Work
+ or if no individual or entity can be identified, the publisher; and in
+ addition (i) in the case of a performance the actors, singers,
+ musicians, dancers, and other persons who act, sing, deliver, declaim,
+ play in, interpret or otherwise perform literary or artistic works or
+ expressions of folklore; (ii) in the case of a phonogram the producer
+ being the person or legal entity who first fixes the sounds of a
+ performance or other sounds; and, (iii) in the case of broadcasts, the
+ organization that transmits the broadcast.
+ f. "Work" means the literary and/or artistic work offered under the terms
+ of this License including without limitation any production in the
+ literary, scientific and artistic domain, whatever may be the mode or
+ form of its expression including digital form, such as a book,
+ pamphlet and other writing; a lecture, address, sermon or other work
+ of the same nature; a dramatic or dramatico-musical work; a
+ choreographic work or entertainment in dumb show; a musical
+ composition with or without words; a cinematographic work to which are
+ assimilated works expressed by a process analogous to cinematography;
+ a work of drawing, painting, architecture, sculpture, engraving or
+ lithography; a photographic work to which are assimilated works
+ expressed by a process analogous to photography; a work of applied
+ art; an illustration, map, plan, sketch or three-dimensional work
+ relative to geography, topography, architecture or science; a
+ performance; a broadcast; a phonogram; a compilation of data to the
+ extent it is protected as a copyrightable work; or a work performed by
+ a variety or circus performer to the extent it is not otherwise
+ considered a literary or artistic work.
+ g. "You" means an individual or entity exercising rights under this
+ License who has not previously violated the terms of this License with
+ respect to the Work, or who has received express permission from the
+ Licensor to exercise rights under this License despite a previous
+ violation.
+ h. "Publicly Perform" means to perform public recitations of the Work and
+ to communicate to the public those public recitations, by any means or
+ process, including by wire or wireless means or public digital
+ performances; to make available to the public Works in such a way that
+ members of the public may access these Works from a place and at a
+ place individually chosen by them; to perform the Work to the public
+ by any means or process and the communication to the public of the
+ performances of the Work, including by public digital performance; to
+ broadcast and rebroadcast the Work by any means including signs,
+ sounds or images.
+ i. "Reproduce" means to make copies of the Work by any means including
+ without limitation by sound or visual recordings and the right of
+ fixation and reproducing fixations of the Work, including storage of a
+ protected performance or phonogram in digital form or other electronic
+ medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+ Collections, and to Reproduce the Work as incorporated in the
+ Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+ including any translation in any medium, takes reasonable steps to
+ clearly label, demarcate or otherwise identify that changes were made
+ to the original Work. For example, a translation could be marked "The
+ original work was translated from English to Spanish," or a
+ modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+ in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+ i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme cannot be waived, the Licensor
+ reserves the exclusive right to collect such royalties for any
+ exercise by You of the rights granted under this License;
+ ii. Waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme can be waived, the Licensor waives the
+ exclusive right to collect such royalties for any exercise by You
+ of the rights granted under this License; and,
+ iii. Voluntary License Schemes. The Licensor waives the right to
+ collect royalties, whether individually or, in the event that the
+ Licensor is a member of a collecting society that administers
+ voluntary licensing schemes, via that society, from any exercise
+ by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+ of this License. You must include a copy of, or the Uniform Resource
+ Identifier (URI) for, this License with every copy of the Work You
+ Distribute or Publicly Perform. You may not offer or impose any terms
+ on the Work that restrict the terms of this License or the ability of
+ the recipient of the Work to exercise the rights granted to that
+ recipient under the terms of the License. You may not sublicense the
+ Work. You must keep intact all notices that refer to this License and
+ to the disclaimer of warranties with every copy of the Work You
+ Distribute or Publicly Perform. When You Distribute or Publicly
+ Perform the Work, You may not impose any effective technological
+ measures on the Work that restrict the ability of a recipient of the
+ Work from You to exercise the rights granted to that recipient under
+ the terms of the License. This Section 4(a) applies to the Work as
+ incorporated in a Collection, but this does not require the Collection
+ apart from the Work itself to be made subject to the terms of this
+ License. If You create a Collection, upon notice from any Licensor You
+ must, to the extent practicable, remove from the Collection any credit
+ as required by Section 4(b), as requested. If You create an
+ Adaptation, upon notice from any Licensor You must, to the extent
+ practicable, remove from the Adaptation any credit as required by
+ Section 4(b), as requested.
+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
+ Collections, You must, unless a request has been made pursuant to
+ Section 4(a), keep intact all copyright notices for the Work and
+ provide, reasonable to the medium or means You are utilizing: (i) the
+ name of the Original Author (or pseudonym, if applicable) if supplied,
+ and/or if the Original Author and/or Licensor designate another party
+ or parties (e.g., a sponsor institute, publishing entity, journal) for
+ attribution ("Attribution Parties") in Licensor's copyright notice,
+ terms of service or by other reasonable means, the name of such party
+ or parties; (ii) the title of the Work if supplied; (iii) to the
+ extent reasonably practicable, the URI, if any, that Licensor
+ specifies to be associated with the Work, unless such URI does not
+ refer to the copyright notice or licensing information for the Work;
+ and (iv) , consistent with Section 3(b), in the case of an Adaptation,
+ a credit identifying the use of the Work in the Adaptation (e.g.,
+ "French translation of the Work by Original Author," or "Screenplay
+ based on original Work by Original Author"). The credit required by
+ this Section 4 (b) may be implemented in any reasonable manner;
+ provided, however, that in the case of a Adaptation or Collection, at
+ a minimum such credit will appear, if a credit for all contributing
+ authors of the Adaptation or Collection appears, then as part of these
+ credits and in a manner at least as prominent as the credits for the
+ other contributing authors. For the avoidance of doubt, You may only
+ use the credit required by this Section for the purpose of attribution
+ in the manner set out above and, by exercising Your rights under this
+ License, You may not implicitly or explicitly assert or imply any
+ connection with, sponsorship or endorsement by the Original Author,
+ Licensor and/or Attribution Parties, as appropriate, of You or Your
+ use of the Work, without the separate, express prior written
+ permission of the Original Author, Licensor and/or Attribution
+ Parties.
+ c. Except as otherwise agreed in writing by the Licensor or as may be
+ otherwise permitted by applicable law, if You Reproduce, Distribute or
+ Publicly Perform the Work either by itself or as part of any
+ Adaptations or Collections, You must not distort, mutilate, modify or
+ take other derogatory action in relation to the Work which would be
+ prejudicial to the Original Author's honor or reputation. Licensor
+ agrees that in those jurisdictions (e.g. Japan), in which any exercise
+ of the right granted in Section 3(b) of this License (the right to
+ make Adaptations) would be deemed to be a distortion, mutilation,
+ modification or other derogatory action prejudicial to the Original
+ Author's honor and reputation, the Licensor will waive or not assert,
+ as appropriate, this Section, to the fullest extent permitted by the
+ applicable national law, to enable You to reasonably exercise Your
+ right under Section 3(b) of this License (right to make Adaptations)
+ but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+ automatically upon any breach by You of the terms of this License.
+ Individuals or entities who have received Adaptations or Collections
+ from You under this License, however, will not have their licenses
+ terminated provided such individuals or entities remain in full
+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+ survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+ perpetual (for the duration of the applicable copyright in the Work).
+ Notwithstanding the above, Licensor reserves the right to release the
+ Work under different license terms or to stop distributing the Work at
+ any time; provided, however that any such election will not serve to
+ withdraw this License (or any other license that has been, or is
+ required to be, granted under the terms of this License), and this
+ License will continue in full force and effect unless terminated as
+ stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+ the Licensor offers to the recipient a license to the Work on the same
+ terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+ offers to the recipient a license to the original Work on the same
+ terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this License, and without further action
+ by the parties to this agreement, such provision shall be reformed to
+ the minimum extent necessary to make such provision valid and
+ enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+ breach consented to unless such waiver or consent shall be in writing
+ and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+ respect to the Work licensed here. There are no understandings,
+ agreements or representations with respect to the Work not specified
+ here. Licensor shall not be bound by any additional provisions that
+ may appear in any communication from You. This License may not be
+ modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+ License were drafted utilizing the terminology of the Berne Convention
+ for the Protection of Literary and Artistic Works (as amended on
+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+ and the Universal Copyright Convention (as revised on July 24, 1971).
+ These rights and subject matter take effect in the relevant
+ jurisdiction in which the License terms are sought to be enforced
+ according to the corresponding provisions of the implementation of
+ those treaty provisions in the applicable national law. If the
+ standard suite of rights granted under applicable copyright law
+ includes additional rights not granted under this License, such
+ additional rights are deemed to be included in the License; this
+ License is not intended to restrict the license of any rights under
+ applicable law.
+
+
+Creative Commons Notice
+
+ Creative Commons is not a party to this License, and makes no warranty
+ whatsoever in connection with the Work. Creative Commons will not be
+ liable to You or any party on any legal theory for any damages
+ whatsoever, including without limitation any general, special,
+ incidental or consequential damages arising in connection to this
+ license. Notwithstanding the foregoing two (2) sentences, if Creative
+ Commons has expressly identified itself as the Licensor hereunder, it
+ shall have all rights and obligations of Licensor.
+
+ Except for the limited purpose of indicating to the public that the
+ Work is licensed under the CCPL, Creative Commons does not authorize
+ the use by either party of the trademark "Creative Commons" or any
+ related trademark or logo of Creative Commons without the prior
+ written consent of Creative Commons. Any permitted use will be in
+ compliance with Creative Commons' then-current trademark usage
+ guidelines, as may be published on its website or otherwise made
+ available upon request from time to time. For the avoidance of doubt,
+ this trademark restriction does not form part of this License.
+
+ Creative Commons may be contacted at https://creativecommons.org/.
+
+*******************************************************************************
+
+/!\ The SIL OPEN FONT LICENSE applies to all desktop and webfont files in the
+following directory: fonts/ and to all glyphs and SVG files in the following
+directory: src/icons/svg/.
+
+
+Copyright (c) 2018, Fork Awesome (https://forkawesome.github.io),
+with Reserved Font Name Fork Awesome.
+
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+
+lodash
+MIT
+Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
+
+
+moment
+MIT
+Copyright (c) JS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+ng-block-ui
+MIT
+MIT License
+
+Copyright (c) 2017
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+ng2-charts
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2015-2017 Dmitriy Shekhovtsov <valorkin@gmail.com>
+Copyright (c) 2015-2017 Valor Software
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
+ng2-tree
+MIT
+
+ngx-bootstrap/accordion
+
+ngx-bootstrap/alert
+
+ngx-bootstrap/chronos
+The MIT License (MIT)
+
+Copyright (c) Valor Software
+Copyright (c) Dmitriy Shekhovtsov<valorkin@gmail.com>
+Copyright (c) moment/moment
+Copyright (c) JS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+ngx-bootstrap/collapse
+
+ngx-bootstrap/component-loader
+
+ngx-bootstrap/datepicker
+
+ngx-bootstrap/dropdown
+
+ngx-bootstrap/mini-ngrx
+
+ngx-bootstrap/modal
+
+ngx-bootstrap/popover
+
+ngx-bootstrap/positioning
+
+ngx-bootstrap/progressbar
+
+ngx-bootstrap/tabs
+
+ngx-bootstrap/timepicker
+
+ngx-bootstrap/tooltip
+
+ngx-bootstrap/typeahead
+
+ngx-bootstrap/utils
+
+ngx-toastr
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2018 Scott Cooper
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+undefined
+
+rxjs
+Apache-2.0
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+rxjs-compat
+Apache-2.0
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+tslib
+Apache-2.0
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+
+uuid
+MIT
+The MIT License (MIT)
+
+Copyright (c) 2010-2016 Robert Kieffer and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+webpack
+MIT
+Copyright JS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+zone.js
+MIT
+The MIT License
+
+Copyright (c) 2016-2018 Google, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/6.f054f1f260c137d64363.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/6.f054f1f260c137d64363.js
new file mode 100644
index 00000000..361e2741
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/6.f054f1f260c137d64363.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{EmSq:function(l,n,u){"use strict";u.d(n,"a",function(){return i});var e=u("CcnG"),t=u("LvDl"),i=(u("Fgil"),u("aXbf"),function(){function l(l,n,u,t){this.elementRef=l,this.control=n,this.dimlessBinaryPipe=u,this.formatter=t,this.ngModelChange=new e.EventEmitter,this.el=this.elementRef.nativeElement}return l.prototype.ngOnInit=function(){this.setValue(this.el.value)},l.prototype.setValue=function(l){/^[\d.]+$/.test(l)&&(l+=this.defaultUnit||"m");var n=this.formatter.toBytes(l),u=this.round(n);this.el.value=this.dimlessBinaryPipe.transform(u),null!==n?(this.ngModelChange.emit(this.el.value),this.control.control.setValue(this.el.value)):(this.ngModelChange.emit(null),this.control.control.setValue(null))},l.prototype.round=function(l){if(null!==l&&0!==l){if(!t.isUndefined(this.minBytes)&&l<this.minBytes)return this.minBytes;if(!t.isUndefined(this.maxBytes)&&l>this.maxBytes)return this.maxBytes;if(!t.isUndefined(this.roundPower)){var n=Math.round(Math.log(l)/Math.log(this.roundPower));return Math.pow(this.roundPower,n)}}return l},l.prototype.onBlur=function(l){this.setValue(l)},l}())},OcYo:function(l,n,u){"use strict";u.d(n,"a",function(){return e});var e=function(){function l(l,n,u){this.elementRef=l,this.renderer=n,this.toastr=u}return l.prototype.ngOnInit=function(){var l=this.renderer.createElement("i");this.renderer.addClass(l,"icon-prepend"),this.renderer.addClass(l,"fa"),this.renderer.addClass(l,"fa-clipboard"),this.renderer.appendChild(this.elementRef.nativeElement,l)},l.prototype.getInputElement=function(){return document.getElementById(this.cdCopy2ClipboardButton)},l.prototype.onClick=function(){try{var l=document.createElement("input");l.value=this.getInputElement().value,document.body.appendChild(l),l.select(),document.execCommand("copy"),document.body.removeChild(l),this.toastr.success("Copied text to the clipboard successfully.")}catch(n){this.toastr.error("Failed to copy text to the clipboard.")}},l}()},Znkk:function(l,n,u){"use strict";u.r(n);var e,t=u("CcnG"),i=u("sne2"),o=u("Avrn"),a=u("+0ag"),r=u("mSOc"),s=function(){function l(l,n,u){this.route=l,this.summaryService=n,this.cephReleaseNamePipe=u,this.message="The Object Gateway service is not configured."}return l.prototype.ngOnInit=function(){var l=this,n=this.summaryService.subscribe(function(u){if(u){var e=l.cephReleaseNamePipe.transform(u.version);l.docsUrl="http://docs.ceph.com/docs/"+e+"/mgr/dashboard/#enabling-the-object-gateway-management-frontend",setTimeout(function(){n.unsubscribe()},0)}});this.routeParamsSubscribe=this.route.params.subscribe(function(n){l.message=n.message})},l.prototype.ngOnDestroy=function(){this.routeParamsSubscribe.unsubscribe()},l}(),d=u("gIcY"),c=u("LvDl"),p=u("mrSG"),f=u("t/Na"),m=u("F/XL"),g=u("psW0"),v=u("xTzq"),b=u("pL04"),h=function(){function l(l){this.http=l,this.url="api/rgw/bucket"}return l.prototype.list=function(){var l=new f.h;return l=l.append("stats","true"),this.http.get(this.url,{params:l})},l.prototype.enumerate=function(){return this.http.get(this.url)},l.prototype.get=function(l){return this.http.get(this.url+"/"+l)},l.prototype.create=function(l,n){var u=new f.h;return u=(u=u.append("bucket",l)).append("uid",n),this.http.post(this.url,null,{params:u})},l.prototype.update=function(l,n,u){var e=new f.h;return e=(e=e.append("bucket_id",n)).append("uid",u),this.http.put(this.url+"/"+l,null,{params:e})},l.prototype.delete=function(l,n){void 0===n&&(n=!0);var u=new f.h;return u=u.append("purge_objects",n?"true":"false"),this.http.delete(this.url+"/"+l,{params:u})},l.prototype.exists=function(l){return this.enumerate().pipe(Object(g.a)(function(n){var u=c.indexOf(n,l);return Object(m.a)(-1!==u)}))},l.ngInjectableDef=t.defineInjectable({factory:function(){return new l(t.inject(f.c))},token:l,providedIn:b.a}),l=p.__decorate([v.a,p.__metadata("design:paramtypes",[f.c])],l)}(),y=u("P8lu"),C=u("mtw6"),_=u("2EZI"),k=u("9nlD"),R=function(){function l(l,n,u,e,t,o,a,r){this.route=l,this.router=n,this.formBuilder=u,this.rgwBucketService=e,this.rgwUserService=t,this.notificationService=o,this.i18n=a,this.actionLabels=r,this.editing=!1,this.error=!1,this.loading=!1,this.owners=null,this.editing=this.router.url.startsWith("/rgw/bucket/"+i.e.EDIT),this.action=this.editing?this.actionLabels.EDIT:this.actionLabels.CREATE,this.resource=this.i18n("bucket"),this.createForm()}return l.prototype.createForm=function(){this.bucketForm=this.formBuilder.group({id:[null],bid:[null,[d.A.required],[this.bucketNameValidator()]],owner:[null,[d.A.required]]})},l.prototype.ngOnInit=function(){var l=this;this.rgwUserService.enumerate().subscribe(function(n){l.owners=n.sort()}),this.route.params.subscribe(function(n){if(n.hasOwnProperty("bid")){var u=decodeURIComponent(n.bid);l.loading=!0,l.rgwBucketService.get(u).subscribe(function(n){l.loading=!1;var u=c.clone(l.bucketForm.value),e=c.pick(n,c.keys(l.bucketForm.value));e=c.merge(u,e),l.bucketForm.setValue(e)})}},function(n){l.error=n})},l.prototype.goToListView=function(){this.router.navigate(["/rgw/bucket"])},l.prototype.submit=function(){var l=this;if(this.bucketForm.pristine)this.goToListView();else{var n=this.bucketForm.get("bid"),u=this.bucketForm.get("owner");if(this.editing){var e=this.bucketForm.get("id");this.rgwBucketService.update(n.value,e.value,u.value).subscribe(function(){l.notificationService.show(C.a.success,l.i18n('Updated Object Gateway bucket "{{bid}}"',{bid:n.value})),l.goToListView()},function(){l.bucketForm.setErrors({cdSubmitButton:!0})})}else this.rgwBucketService.create(n.value,u.value).subscribe(function(){l.notificationService.show(C.a.success,l.i18n('Created Object Gateway bucket "{{bid}}"',{bid:n.value})),l.goToListView()},function(){l.bucketForm.setErrors({cdSubmitButton:!0})})}},l.prototype.bucketNameValidator=function(){var l=this.rgwBucketService;return function(n){return new Promise(function(u){n.pristine||""===n.value?u(null):/^[0-9A-Za-z][\w-\.]{2,254}$/.test(n.value)?l.exists(n.value).subscribe(function(l){u(l?{bucketNameExists:!0}:null)}):u({bucketNameInvalid:!0})})}},l}(),I=u("6blF"),w=u("VNr4"),E=u("0+/T"),x=u("uIqm"),T=u("vCyI"),q=u("Fgil"),V=u("o4+5"),S=u("aexS"),D=u("EgGo"),N=new D.a("rgw/bucket"),F=function(){function l(l,n,u,e,t,i,o,a,r){var s=this;this.authStorageService=l,this.dimlessBinaryPipe=n,this.dimlessPipe=u,this.rgwBucketService=e,this.bsModalService=t,this.i18n=i,this.urlBuilder=o,this.actionLabels=a,this.changeDetectorRef=r,this.columns=[],this.buckets=[],this.selection=new T.a,this.permission=this.authStorageService.getPermissions().rgw,this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return s.urlBuilder.getCreate()},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return s.urlBuilder.getEdit(s.selection.first()&&""+encodeURIComponent(s.selection.first().bid))},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-times",click:function(){return s.deleteAction()},name:this.actionLabels.DELETE}]}return l.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"bid",flexGrow:2},{name:this.i18n("Owner"),prop:"owner",flexGrow:3},{name:this.i18n("Used Capacity"),prop:"bucket_size",flexGrow:.5,pipe:this.dimlessBinaryPipe},{name:this.i18n("Capacity Limit %"),prop:"size_usage",cellTemplate:this.bucketSizeTpl,flexGrow:1},{name:this.i18n("Objects"),prop:"num_objects",flexGrow:.5,pipe:this.dimlessPipe},{name:this.i18n("Object Limit %"),prop:"object_usage",cellTemplate:this.bucketObjectTpl,flexGrow:1}]},l.prototype.transformBucketData=function(){c.forEach(this.buckets,function(l){var n=l.bucket_quota.max_size,u=l.bucket_quota.max_objects,e=0,t=0;c.forEach(l.usage,function(l){e+=l.size_actual,t+=l.num_objects}),l.bucket_size=e,l.num_objects=t,l.size_usage=n>0?e/n:void 0,l.object_usage=u>0?t/u:void 0})},l.prototype.getBucketList=function(l){var n=this;this.rgwBucketService.list().subscribe(function(l){n.buckets=l,n.transformBucketData(),n.changeDetectorRef.detectChanges()},function(){l.error()})},l.prototype.updateSelection=function(l){this.selection=l},l.prototype.deleteAction=function(){var l=this;this.bsModalService.show(E.a,{initialState:{itemDescription:this.i18n(this.selection.hasSingleSelection?"bucket":"buckets"),itemNames:this.selection.selected.map(function(l){return l.bid}),submitActionObservable:function(){return new I.a(function(n){Object(w.a)(l.selection.selected.map(function(n){return l.rgwBucketService.delete(n.bid)})).subscribe(null,function(u){n.error(u),l.table.refreshBtn()},function(){n.complete(),l.table.refreshBtn()})})}}})},l}(),j=function(){function l(l){this.http=l,this.url="api/rgw/daemon"}return l.prototype.list=function(){return this.http.get(this.url)},l.prototype.get=function(l){return this.http.get(this.url+"/"+l)},l.ngInjectableDef=t.defineInjectable({factory:function(){return new l(t.inject(f.c))},token:l,providedIn:b.a}),l=p.__decorate([v.a,p.__metadata("design:paramtypes",[f.c])],l)}(),P=u("85J/"),z=function(){function l(l,n,u,e){this.rgwDaemonService=l,this.authStorageService=n,this.i18n=e,this.columns=[],this.daemons=[],this.selection=new T.a,this.grafanaPermission=this.authStorageService.getPermissions().grafana,this.columns=[{name:this.i18n("ID"),prop:"id",flexGrow:2},{name:this.i18n("Hostname"),prop:"server_hostname",flexGrow:2},{name:this.i18n("Version"),prop:"version",flexGrow:1,pipe:u}]}return l.prototype.getDaemonList=function(l){var n=this;this.rgwDaemonService.list().subscribe(function(l){n.daemons=l},function(){l.error()})},l.prototype.updateSelection=function(l){this.selection=l},l}(),A=u("dEwP"),B=u("1Ni5"),U=u("aXbf");!function(l){l.USERS="users",l.BUCKETS="buckets",l.METADATA="metadata",l.USAGE="usage",l.ZONE="zone"}(e||(e={}));var M=function(){function l(){}return l.getAll=function(){return Object.values(l.capabilities)},l.capabilities=e,l}(),O=function(){function l(l,n,u,e){this.formBuilder=l,this.bsModalRef=n,this.i18n=u,this.actionLabels=e,this.submitAction=new t.EventEmitter,this.editing=!0,this.types=[],this.resource=this.i18n("capability"),this.createForm()}return l.prototype.createForm=function(){this.formGroup=this.formBuilder.group({type:[null,[d.A.required]],perm:[null,[d.A.required]]})},l.prototype.setEditing=function(l){void 0===l&&(l=!0),this.editing=l,this.action=this.editing?this.actionLabels.EDIT:this.actionLabels.ADD},l.prototype.setValues=function(l,n){this.formGroup.setValue({type:l,perm:n})},l.prototype.setCapabilities=function(l){var n=this,u=[];l.forEach(function(l){u.push(l.type)}),this.types=[],M.getAll().forEach(function(l){-1===c.indexOf(u,l)&&n.types.push(l)})},l.prototype.onSubmit=function(){this.submitAction.emit(this.formGroup.value),this.bsModalRef.hide()},l}(),L=function(){function l(l,n,u,e){this.formBuilder=l,this.bsModalRef=n,this.i18n=u,this.actionLabels=e,this.submitAction=new t.EventEmitter,this.viewing=!0,this.userCandidates=[],this.resource=this.i18n("S3 Key"),this.createForm()}return l.prototype.createForm=function(){this.formGroup=this.formBuilder.group({user:[null,[d.A.required]],generate_key:[!0],access_key:[null,[B.a.requiredIf({generate_key:!1})]],secret_key:[null,[B.a.requiredIf({generate_key:!1})]]})},l.prototype.setViewing=function(l){void 0===l&&(l=!0),this.viewing=l,this.action=this.viewing?this.actionLabels.SHOW:this.actionLabels.CREATE},l.prototype.setValues=function(l,n,u){this.formGroup.setValue({user:l,generate_key:c.isEmpty(n),access_key:n,secret_key:u})},l.prototype.setUserCandidates=function(l){this.userCandidates=l},l.prototype.onSubmit=function(){this.submitAction.emit(this.formGroup.value),this.bsModalRef.hide()},l}(),G=function(){return function(){}}(),K=function(){function l(l,n,u,e){this.formBuilder=l,this.bsModalRef=n,this.i18n=u,this.actionLabels=e,this.submitAction=new t.EventEmitter,this.editing=!0,this.subusers=[],this.resource=this.i18n("Subuser"),this.createForm()}return l.prototype.createForm=function(){this.formGroup=this.formBuilder.group({uid:[null],subuid:[null,[d.A.required,this.subuserValidator()]],perm:[null,[d.A.required]],generate_secret:[!0],secret_key:[null,[B.a.requiredIf({generate_secret:!1})]]})},l.prototype.subuserValidator=function(){var l=this;return function(n){return l.editing?null:Object(B.b)(n.value)?null:l.subusers.some(function(u){return c.isEqual(l.getSubuserName(u.id),n.value)})?{subuserIdExists:!0}:null}},l.prototype.getSubuserName=function(l){if(c.isEmpty(l))return l;var n=l.match(/([^:]+)(:(.+))?/);return c.isUndefined(n[3])?n[1]:n[3]},l.prototype.setEditing=function(l){void 0===l&&(l=!0),this.editing=l,this.action=this.editing?this.actionLabels.EDIT:this.actionLabels.CREATE},l.prototype.setValues=function(l,n,u){void 0===n&&(n=""),void 0===u&&(u=""),this.formGroup.setValue({uid:l,subuid:this.getSubuserName(n),perm:u,generate_secret:!0,secret_key:null})},l.prototype.setSubusers=function(l){this.subusers=l},l.prototype.onSubmit=function(){var l=this.formGroup.value,n=new G;n.id=l.uid+":"+l.subuid,n.permissions=l.perm,n.generate_secret=l.generate_secret,n.secret_key=l.secret_key,this.submitAction.emit(n),this.bsModalRef.hide()},l}(),$=function(){function l(l,n,u){this.bsModalRef=l,this.i18n=n,this.actionLabels=u,this.resource=this.i18n("Swift Key"),this.action=this.actionLabels.SHOW}return l.prototype.setValues=function(l,n){this.user=l,this.secret_key=n},l}(),Z=function(){function l(l,n,u,e,t,o,a,r){this.formBuilder=l,this.route=n,this.router=u,this.rgwUserService=e,this.bsModalService=t,this.notificationService=o,this.i18n=a,this.actionLabels=r,this.editing=!1,this.error=!1,this.loading=!1,this.submitObservables=[],this.subusers=[],this.s3Keys=[],this.swiftKeys=[],this.capabilities=[],this.resource=this.i18n("user"),this.subuserLabel=this.i18n("subuser"),this.s3keyLabel=this.i18n("S3 Key"),this.capabilityLabel=this.i18n("capability"),this.editing=this.router.url.startsWith("/rgw/user/"+i.e.EDIT),this.action=this.editing?this.actionLabels.EDIT:this.actionLabels.CREATE,this.createForm()}return l.prototype.createForm=function(){this.userForm=this.formBuilder.group({uid:[null,[d.A.required],this.editing?[]:[B.a.unique(this.rgwUserService.exists,this.rgwUserService)]],display_name:[null,[d.A.required]],email:[null,[B.a.email],[B.a.unique(this.rgwUserService.emailExists,this.rgwUserService)]],max_buckets_mode:["1"],max_buckets:[1e3,[B.a.requiredIf({max_buckets_mode:"1"}),B.a.number(!1),d.A.min(1)]],suspended:[!1],generate_key:[!0],access_key:[null,[B.a.requiredIf({generate_key:!1})]],secret_key:[null,[B.a.requiredIf({generate_key:!1})]],user_quota_enabled:[!1],user_quota_max_size_unlimited:[!0],user_quota_max_size:[null,[B.a.requiredIf({user_quota_enabled:!0,user_quota_max_size_unlimited:!1}),this.quotaMaxSizeValidator]],user_quota_max_objects_unlimited:[!0],user_quota_max_objects:[null,[d.A.min(0),B.a.requiredIf({user_quota_enabled:!0,user_quota_max_objects_unlimited:!1})]],bucket_quota_enabled:[!1],bucket_quota_max_size_unlimited:[!0],bucket_quota_max_size:[null,[B.a.requiredIf({bucket_quota_enabled:!0,bucket_quota_max_size_unlimited:!1}),this.quotaMaxSizeValidator]],bucket_quota_max_objects_unlimited:[!0],bucket_quota_max_objects:[null,[d.A.min(0),B.a.requiredIf({bucket_quota_enabled:!0,bucket_quota_max_objects_unlimited:!1})]]})},l.prototype.ngOnInit=function(){var l=this;this.route.params.subscribe(function(n){if(n.hasOwnProperty("uid")){var u=decodeURIComponent(n.uid);l.loading=!0;var e=[];e.push(l.rgwUserService.get(u)),e.push(l.rgwUserService.getQuota(u)),Object(w.a)(e).subscribe(function(n){l.loading=!1;var u=c.clone(l.userForm.value),e=c.pick(n[0],c.keys(l.userForm.value));switch(e.max_buckets){case-1:e.max_buckets_mode="-1",e.max_buckets="";break;case 0:e.max_buckets_mode="0",e.max_buckets="";break;default:e.max_buckets_mode="1"}["user","bucket"].forEach(function(l){var u=n[1][l+"_quota"];e[l+"_quota_enabled"]=u.enabled,u.max_size<0?(e[l+"_quota_max_size_unlimited"]=!0,e[l+"_quota_max_size"]=null):(e[l+"_quota_max_size_unlimited"]=!1,e[l+"_quota_max_size"]=u.max_size+" B"),u.max_objects<0?(e[l+"_quota_max_objects_unlimited"]=!0,e[l+"_quota_max_objects"]=null):(e[l+"_quota_max_objects_unlimited"]=!1,e[l+"_quota_max_objects"]=u.max_objects)}),e=c.merge(u,e),l.userForm.setValue(e),l.subusers=n[0].subusers,l.s3Keys=n[0].keys,l.swiftKeys=n[0].swift_keys;var t={"read, write":"*"};n[0].caps.forEach(function(l){l.perm in t&&(l.perm=t[l.perm])}),l.capabilities=n[0].caps},function(n){l.error=n})}})},l.prototype.goToListView=function(){this.router.navigate(["/rgw/user"])},l.prototype.onSubmit=function(){var l,n=this;if(this.userForm.pristine)this.goToListView();else{var u=this.userForm.getValue("uid");if(this.editing){if(this._isGeneralDirty()){var e=this._getUpdateArgs();this.submitObservables.push(this.rgwUserService.update(u,e))}l=this.i18n('Updated Object Gateway user "{{uid}}"',{uid:u})}else e=this._getCreateArgs(),this.submitObservables.push(this.rgwUserService.create(e)),l=this.i18n('Created Object Gateway user "{{uid}}"',{uid:u});if(this._isUserQuotaDirty()){var t=this._getUserQuotaArgs();this.submitObservables.push(this.rgwUserService.updateQuota(u,t))}if(this._isBucketQuotaDirty()){var i=this._getBucketQuotaArgs();this.submitObservables.push(this.rgwUserService.updateQuota(u,i))}A.a.apply(void 0,this.submitObservables).subscribe({error:function(){n.userForm.setErrors({cdSubmitButton:!0})},complete:function(){n.notificationService.show(C.a.success,l),n.goToListView()}})}},l.prototype.quotaMaxSizeValidator=function(l){return Object(B.b)(l.value)?null:null===RegExp("^(\\d+(\\.\\d+)?)\\s*(B|K(B|iB)?|M(B|iB)?|G(B|iB)?|T(B|iB)?)?$","i").exec(l.value)?{quotaMaxSize:!0}:(new U.a).toBytes(l.value)<1024?{quotaMaxSize:!0}:null},l.prototype.setSubuser=function(l,n){var u={"full-control":"full","read-write":"readwrite"},e=this.userForm.getValue("uid");this.submitObservables.push(this.rgwUserService.createSubuser(e,{subuser:l.id,access:l.permissions in u?u[l.permissions]:l.permissions,key_type:"swift",secret_key:l.secret_key,generate_secret:l.generate_secret?"true":"false"})),c.isNumber(n)?this.subusers[n]=l:(this.subusers.push(l),this.swiftKeys.push({user:l.id,secret_key:l.generate_secret?"Apply your changes first...":l.secret_key})),this.userForm.markAsDirty()},l.prototype.deleteSubuser=function(l){var n=this.subusers[l];this.submitObservables.push(this.rgwUserService.deleteSubuser(this.userForm.getValue("uid"),n.id)),this.s3Keys=this.s3Keys.filter(function(l){return l.user!==n.id}),this.swiftKeys=this.swiftKeys.filter(function(l){return l.user!==n.id}),this.subusers.splice(l,1),this.userForm.markAsDirty()},l.prototype.setCapability=function(l,n){var u=this.userForm.getValue("uid");if(c.isNumber(n)){var e=this.capabilities[n];this.submitObservables.push(this.rgwUserService.deleteCapability(u,e.type,e.perm)),this.submitObservables.push(this.rgwUserService.addCapability(u,l.type,l.perm)),this.capabilities[n]=l}else this.submitObservables.push(this.rgwUserService.addCapability(u,l.type,l.perm)),this.capabilities.push(l);this.userForm.markAsDirty()},l.prototype.deleteCapability=function(l){var n=this.capabilities[l];this.submitObservables.push(this.rgwUserService.deleteCapability(this.userForm.getValue("uid"),n.type,n.perm)),this.capabilities.splice(l,1),this.userForm.markAsDirty()},l.prototype.hasAllCapabilities=function(){return!c.difference(M.getAll(),c.map(this.capabilities,"type")).length},l.prototype.setS3Key=function(l,n){if(c.isNumber(n));else{var u=l.user.match(/([^:]+)(:(.+))?/),e=u[1],t={subuser:u[2]?u[3]:"",generate_key:l.generate_key?"true":"false"};"false"===t.generate_key&&(c.isNil(l.access_key)||(t.access_key=l.access_key),c.isNil(l.secret_key)||(t.secret_key=l.secret_key)),this.submitObservables.push(this.rgwUserService.addS3Key(e,t)),this.s3Keys.push({user:l.user,access_key:l.generate_key?"Apply your changes first...":l.access_key,secret_key:l.generate_key?"Apply your changes first...":l.secret_key})}this.userForm.markAsDirty()},l.prototype.deleteS3Key=function(l){var n=this.s3Keys[l];this.submitObservables.push(this.rgwUserService.deleteS3Key(this.userForm.getValue("uid"),n.access_key)),this.s3Keys.splice(l,1),this.userForm.markAsDirty()},l.prototype.showSubuserModal=function(l){var n=this,u=this.userForm.getValue("uid"),e=this.bsModalService.show(K);if(c.isNumber(l)){var t=this.subusers[l];e.content.setEditing(),e.content.setValues(u,t.id,t.permissions)}else e.content.setEditing(!1),e.content.setValues(u),e.content.setSubusers(this.subusers);e.content.submitAction.subscribe(function(u){n.setSubuser(u,l)})},l.prototype.showS3KeyModal=function(l){var n=this,u=this.bsModalService.show(L);if(c.isNumber(l)){var e=this.s3Keys[l];u.content.setViewing(),u.content.setValues(e.user,e.access_key,e.secret_key)}else{var t=this._getS3KeyUserCandidates();u.content.setViewing(!1),u.content.setUserCandidates(t),u.content.submitAction.subscribe(function(l){n.setS3Key(l)})}},l.prototype.showSwiftKeyModal=function(l){var n=this.bsModalService.show($),u=this.swiftKeys[l];n.content.setValues(u.user,u.secret_key)},l.prototype.showCapabilityModal=function(l){var n=this,u=this.bsModalService.show(O);if(c.isNumber(l)){var e=this.capabilities[l];u.content.setEditing(),u.content.setValues(e.type,e.perm)}else u.content.setEditing(!1),u.content.setCapabilities(this.capabilities);u.content.submitAction.subscribe(function(u){n.setCapability(u,l)})},l.prototype._isGeneralDirty=function(){var l=this;return["display_name","email","max_buckets_mode","max_buckets","suspended"].some(function(n){return l.userForm.get(n).dirty})},l.prototype._isUserQuotaDirty=function(){var l=this;return["user_quota_enabled","user_quota_max_size_unlimited","user_quota_max_size","user_quota_max_objects_unlimited","user_quota_max_objects"].some(function(n){return l.userForm.get(n).dirty})},l.prototype._isBucketQuotaDirty=function(){var l=this;return["bucket_quota_enabled","bucket_quota_max_size_unlimited","bucket_quota_max_size","bucket_quota_max_objects_unlimited","bucket_quota_max_objects"].some(function(n){return l.userForm.get(n).dirty})},l.prototype._getCreateArgs=function(){var l={uid:this.userForm.getValue("uid"),display_name:this.userForm.getValue("display_name"),suspended:this.userForm.getValue("suspended"),email:"",max_buckets:this.userForm.getValue("max_buckets"),generate_key:this.userForm.getValue("generate_key"),access_key:"",secret_key:""},n=this.userForm.getValue("email");c.isString(n)&&n.length>0&&c.merge(l,{email:n}),this.userForm.getValue("generate_key")||c.merge(l,{generate_key:!1,access_key:this.userForm.getValue("access_key"),secret_key:this.userForm.getValue("secret_key")});var u=parseInt(this.userForm.getValue("max_buckets_mode"),10);return c.includes([-1,0],u)&&c.merge(l,{max_buckets:u}),l},l.prototype._getUpdateArgs=function(){for(var l={},n=0,u=["display_name","email","max_buckets","suspended"];n<u.length;n++){var e=u[n];l[e]=this.userForm.getValue(e)}var t=parseInt(this.userForm.getValue("max_buckets_mode"),10);return c.includes([-1,0],t)&&(l.max_buckets=t),l},l.prototype._getUserQuotaArgs=function(){var l={quota_type:"user",enabled:this.userForm.getValue("user_quota_enabled"),max_size_kb:-1,max_objects:-1};if(!this.userForm.getValue("user_quota_max_size_unlimited")){var n=(new U.a).toBytes(this.userForm.getValue("user_quota_max_size"));l.max_size_kb=(n/1024).toFixed(0)}return this.userForm.getValue("user_quota_max_objects_unlimited")||(l.max_objects=this.userForm.getValue("user_quota_max_objects")),l},l.prototype._getBucketQuotaArgs=function(){var l={quota_type:"bucket",enabled:this.userForm.getValue("bucket_quota_enabled"),max_size_kb:-1,max_objects:-1};if(!this.userForm.getValue("bucket_quota_max_size_unlimited")){var n=(new U.a).toBytes(this.userForm.getValue("bucket_quota_max_size"));l.max_size_kb=(n/1024).toFixed(0)}return this.userForm.getValue("bucket_quota_max_objects_unlimited")||(l.max_objects=this.userForm.getValue("bucket_quota_max_objects")),l},l.prototype._getS3KeyUserCandidates=function(){var l=[],n=this.userForm.getValue("uid");return c.isString(n)&&!c.isEmpty(n)&&l.push(n),this.subusers.forEach(function(n){l.push(n.id)}),this.s3Keys.forEach(function(n){l.push(n.user)}),l=c.uniq(l)},l.prototype.onMaxBucketsModeChange=function(l){if("1"===l){var n=this.userForm.getValue("max_buckets");this.userForm.patchValue({max_buckets:c.isEmpty(n)?1e3:n})}},l}(),Q=u("x38r"),H=new D.a("rgw/user"),Y=function(){function l(l,n,u,e,t,i){var o=this;this.authStorageService=l,this.rgwUserService=n,this.bsModalService=u,this.i18n=e,this.urlBuilder=t,this.actionLabels=i,this.columns=[],this.users=[],this.selection=new T.a,this.permission=this.authStorageService.getPermissions().rgw,this.columns=[{name:this.i18n("Username"),prop:"uid",flexGrow:1},{name:this.i18n("Full name"),prop:"display_name",flexGrow:1},{name:this.i18n("Email address"),prop:"email",flexGrow:1},{name:this.i18n("Suspended"),prop:"suspended",flexGrow:1,cellClass:"text-center",cellTransformation:Q.a.checkIcon},{name:this.i18n("Max. buckets"),prop:"max_buckets",flexGrow:1,cellTransformation:Q.a.map,customTemplateConfig:{"-1":this.i18n("Disabled"),0:this.i18n("Unlimited")}}],this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return o.urlBuilder.getCreate()},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return o.urlBuilder.getEdit(o.selection.first()&&""+encodeURIComponent(o.selection.first().uid))},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-times",click:function(){return o.deleteAction()},name:this.actionLabels.DELETE}]}return l.prototype.getUserList=function(l){var n=this;this.rgwUserService.list().subscribe(function(l){n.users=l},function(){l.error()})},l.prototype.updateSelection=function(l){this.selection=l},l.prototype.deleteAction=function(){var l=this;this.bsModalService.show(E.a,{initialState:{itemDescription:this.i18n(this.selection.hasSingleSelection?"user":"users"),itemNames:this.selection.selected.map(function(l){return l.uid}),submitActionObservable:function(){return new I.a(function(n){Object(w.a)(l.selection.selected.map(function(n){return l.rgwUserService.delete(n.uid)})).subscribe(null,function(u){n.error(u),l.table.refreshBtn()},function(){n.complete(),l.table.refreshBtn()})})}}})},l}(),X=function(){return function(){}}(),J={breadcrumbs:"Daemons"},W={breadcrumbs:"Users"},ll={breadcrumbs:i.a.CREATE},nl={breadcrumbs:i.a.EDIT},ul={breadcrumbs:"Buckets"},el={breadcrumbs:i.a.CREATE},tl={breadcrumbs:i.a.EDIT},il={breadcrumbs:"Object Gateway"},ol=function(){return function(){}}(),al=u("MdoF"),rl=u("ES0t"),sl=u("Xg1U"),dl=u("z5nN"),cl=u("iutN"),pl=u("EEJc"),fl=u("PEr+"),ml=u("a40w"),gl=u("pMnS"),vl=u("YAQW"),bl=u("a278"),hl=u("insk"),yl=u("ZYjt"),Cl=u("20UP"),_l=u("Jm/i"),kl=u("pKUh"),Rl=u("sLuX"),Il=u("FSuO"),wl=u("a0VL"),El=u("j8L6"),xl=u("b5OY"),Tl=u("pxLl"),ql=u("Ip0R"),Vl=function(){function l(l,n){this.rgwDaemonService=l,this.authStorageService=n,this.serviceId="",this.grafanaPermission=this.authStorageService.getPermissions().grafana}return l.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.serviceId=this.selection.first().id)},l.prototype.getMetaData=function(){var l=this;c.isEmpty(this.serviceId)||this.rgwDaemonService.get(this.serviceId).subscribe(function(n){l.metadata=n.rgw_metadata})},l}(),Sl=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Dl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"tab",[["heading","Performance Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](1,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","one"],["uid","x5ARzZtmk"]],null,null,null,bl.b,bl.a)),t["\u0275did"](3,638976,null,0,hl.a,[r.a,yl.DomSanitizer,Cl.a,a.a,_l.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(l,n){var u=n.component;l(n,1,0,"Performance Details"),l(n,3,0,"rgw-instance-detail?var-rgw_servers=rgw."+u.selection.first().id,"one","x5ARzZtmk")},function(l,n){l(n,0,0,t["\u0275nov"](n,1).id,t["\u0275nov"](n,1).active,t["\u0275nov"](n,1).addClass)})}function Nl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"tabset",[],[[2,"tab-container",null]],null,null,kl.b,kl.a)),t["\u0275did"](1,180224,null,0,vl.d,[vl.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](3,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,[[null,"fetchData"]],function(l,n,u){var e=!0;return"fetchData"===n&&(e=!1!==l.component.getMetaData()&&e),e},Rl.b,Rl.a)),t["\u0275did"](5,638976,null,0,Il.a,[wl.a],{data:[0,"data"]},{fetchData:"fetchData"}),(l()(),t["\u0275eld"](6,0,null,0,3,"tab",[["heading","Performance Counters"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](7,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](8,0,null,null,1,"cd-table-performance-counter",[["serviceType","rgw"]],null,null,null,El.b,El.a)),t["\u0275did"](9,114688,null,0,xl.a,[Tl.a,_l.a],{serviceType:[0,"serviceType"],serviceId:[1,"serviceId"]},null),(l()(),t["\u0275and"](16777216,null,0,1,null,Dl)),t["\u0275did"](11,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,"Details"),l(n,5,0,u.metadata),l(n,7,0,"Performance Counters"),l(n,9,0,"rgw",u.serviceId),l(n,11,0,u.grafanaPermission.read)},function(l,n){l(n,0,0,t["\u0275nov"](n,1).clazz),l(n,2,0,t["\u0275nov"](n,3).id,t["\u0275nov"](n,3).active,t["\u0275nov"](n,3).addClass),l(n,6,0,t["\u0275nov"](n,7).id,t["\u0275nov"](n,7).active,t["\u0275nov"](n,7).addClass)})}function Fl(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,Nl)),t["\u0275did"](1,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,1,0,n.component.selection.hasSingleSelection)},null)}function jl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-daemon-details",[],null,null,null,Fl,Sl)),t["\u0275did"](1,573440,null,0,Vl,[j,S.a],null,null)],null,null)}var Pl=t["\u0275ccf"]("cd-rgw-daemon-details",Vl,jl,{selection:"selection"},{},[]),zl=u("iExv"),Al=function(){function l(){}return l.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.bucket=this.selection.first())},l}(),Bl=t["\u0275crt"]({encapsulation:0,styles:[["table[_ngcontent-%COMP%]{table-layout:fixed}table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{word-wrap:break-word}"]],data:{}});function Ul(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function Ml(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "])),t["\u0275ppd"](2,1)],null,function(l,n){var u=n.component,e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent.parent.parent,2),u.bucket.bucket_quota.max_size));l(n,1,0,e)})}function Ol(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function Ll(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "]))],null,function(l,n){l(n,1,0,n.component.bucket.bucket_quota.max_objects)})}function Gl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,24,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Bucket quota"])),(l()(),t["\u0275eld"](3,0,null,null,21,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,20,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Enabled"])),(l()(),t["\u0275eld"](8,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](9,null,["",""])),t["\u0275ppd"](10,1),(l()(),t["\u0275eld"](11,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum size"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Ul)),t["\u0275did"](15,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ml)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](18,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum objects"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Ol)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ll)),t["\u0275did"](24,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,15,0,u.bucket.bucket_quota.max_size<=-1),l(n,17,0,u.bucket.bucket_quota.max_size>-1),l(n,22,0,u.bucket.bucket_quota.max_objects<=-1),l(n,24,0,u.bucket.bucket_quota.max_objects>-1)},function(l,n){var u=n.component,e=t["\u0275unv"](n,9,0,l(n,10,0,t["\u0275nov"](n.parent.parent.parent,1),u.bucket.bucket_quota.enabled));l(n,9,0,e)})}function Kl(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,60,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,57,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,56,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Name"])),(l()(),t["\u0275eld"](6,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](7,null,["",""])),(l()(),t["\u0275eld"](8,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["ID"])),(l()(),t["\u0275eld"](11,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](12,null,["",""])),(l()(),t["\u0275eld"](13,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](14,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Owner"])),(l()(),t["\u0275eld"](16,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](17,null,["",""])),(l()(),t["\u0275eld"](18,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Index type"])),(l()(),t["\u0275eld"](21,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](22,null,["",""])),(l()(),t["\u0275eld"](23,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](24,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Placement rule"])),(l()(),t["\u0275eld"](26,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](27,null,["",""])),(l()(),t["\u0275eld"](28,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](29,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Marker"])),(l()(),t["\u0275eld"](31,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](32,null,["",""])),(l()(),t["\u0275eld"](33,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](34,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum marker"])),(l()(),t["\u0275eld"](36,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](37,null,["",""])),(l()(),t["\u0275eld"](38,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Version"])),(l()(),t["\u0275eld"](41,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](42,null,["",""])),(l()(),t["\u0275eld"](43,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](44,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Master version"])),(l()(),t["\u0275eld"](46,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](47,null,["",""])),(l()(),t["\u0275eld"](48,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](49,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Modification time"])),(l()(),t["\u0275eld"](51,0,null,null,2,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](52,null,["",""])),t["\u0275ppd"](53,1),(l()(),t["\u0275eld"](54,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](55,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Zonegroup"])),(l()(),t["\u0275eld"](57,0,null,null,1,"td",[],null,null,null,null,null)),(l()(),t["\u0275ted"](58,null,["",""])),(l()(),t["\u0275and"](16777216,null,null,1,null,Gl)),t["\u0275did"](60,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,60,0,n.component.bucket.bucket_quota)},function(l,n){var u=n.component;l(n,7,0,u.bucket.bid),l(n,12,0,u.bucket.id),l(n,17,0,u.bucket.owner),l(n,22,0,u.bucket.index_type),l(n,27,0,u.bucket.placement_rule),l(n,32,0,u.bucket.marker),l(n,37,0,u.bucket.max_marker),l(n,42,0,u.bucket.ver),l(n,47,0,u.bucket.master_ver);var e=t["\u0275unv"](n,52,0,l(n,53,0,t["\u0275nov"](n.parent.parent,0),u.bucket.mtime));l(n,52,0,e),l(n,58,0,u.bucket.zonegroup)})}function $l(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,kl.b,kl.a)),t["\u0275did"](1,180224,null,0,vl.d,[vl.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](3,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Kl)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,"Details"),l(n,5,0,u.bucket)},function(l,n){l(n,0,0,t["\u0275nov"](n,1).clazz),l(n,2,0,t["\u0275nov"](n,3).id,t["\u0275nov"](n,3).active,t["\u0275nov"](n,3).addClass)})}function Zl(l){return t["\u0275vid"](0,[t["\u0275pid"](0,wl.a,[ql.DatePipe]),t["\u0275pid"](0,zl.a,[_l.a]),t["\u0275pid"](0,V.a,[U.a]),(l()(),t["\u0275and"](16777216,null,null,1,null,$l)),t["\u0275did"](4,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,4,0,n.component.selection.hasSingleSelection)},null)}function Ql(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-bucket-details",[],null,null,null,Zl,Bl)),t["\u0275did"](1,573440,null,0,Al,[],null,null)],null,null)}var Hl=t["\u0275ccf"]("cd-rgw-bucket-details",Al,Ql,{selection:"selection"},{},[]),Yl=u("25BL"),Xl=u("xtZt"),Jl=u("lqqz"),Wl=u("TJUb"),ln=function(){function l(l,n,u){this.rgwUserService=l,this.bsModalService=n,this.i18n=u,this.keys=[],this.keysColumns=[],this.keysSelection=new T.a}return l.prototype.ngOnInit=function(){this.keysColumns=[{name:this.i18n("Username"),prop:"username",flexGrow:1},{name:this.i18n("Type"),prop:"type",flexGrow:1}],this.maxBucketsMap={"-1":this.i18n("Disabled"),0:this.i18n("Unlimited")}},l.prototype.ngOnChanges=function(){var l=this;this.selection.hasSelection&&(this.user=this.selection.first(),this.user.subusers=c.sortBy(this.user.subusers,"id"),this.user.caps=c.sortBy(this.user.caps,"type"),this.rgwUserService.getQuota(this.user.uid).subscribe(function(n){c.extend(l.user,n)}),this.keys=[],this.user.keys&&this.user.keys.forEach(function(n){l.keys.push({id:l.keys.length+1,type:"S3",username:n.user,ref:n})}),this.user.swift_keys&&this.user.swift_keys.forEach(function(n){l.keys.push({id:l.keys.length+1,type:"Swift",username:n.user,ref:n})}),this.keys=c.sortBy(this.keys,"user"))},l.prototype.updateKeysSelection=function(l){this.keysSelection=l},l.prototype.showKeyModal=function(){var l=this.keysSelection.first(),n=this.bsModalService.show("S3"===l.type?L:$);switch(l.type){case"S3":n.content.setViewing(),n.content.setValues(l.ref.user,l.ref.access_key,l.ref.secret_key);break;case"Swift":n.content.setValues(l.ref.user,l.ref.secret_key)}},l}(),nn=u("DQlY"),un=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function en(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Email address"])),(l()(),t["\u0275eld"](3,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,["",""]))],null,function(l,n){l(n,4,0,n.component.user.email)})}function tn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"div",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," (",") "]))],null,function(l,n){l(n,1,0,n.context.$implicit.id,n.context.$implicit.permissions)})}function on(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Subusers"])),(l()(),t["\u0275eld"](3,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,tn)),t["\u0275did"](5,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){l(n,5,0,n.component.user.subusers)},null)}function an(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"div",[],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," (",") "]))],null,function(l,n){l(n,1,0,n.context.$implicit.type,n.context.$implicit.perm)})}function rn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Capabilities"])),(l()(),t["\u0275eld"](3,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,an)),t["\u0275did"](5,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){l(n,5,0,n.component.user.caps)},null)}function sn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function dn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "])),t["\u0275ppd"](2,1)],null,function(l,n){var u=n.component,e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent.parent.parent,2),u.user.user_quota.max_size));l(n,1,0,e)})}function cn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function pn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "]))],null,function(l,n){l(n,1,0,n.component.user.user_quota.max_objects)})}function fn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,24,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["User quota"])),(l()(),t["\u0275eld"](3,0,null,null,21,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,20,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Enabled"])),(l()(),t["\u0275eld"](8,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](9,null,["",""])),t["\u0275ppd"](10,1),(l()(),t["\u0275eld"](11,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum size"])),(l()(),t["\u0275and"](16777216,null,null,1,null,sn)),t["\u0275did"](15,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,dn)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](18,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum objects"])),(l()(),t["\u0275and"](16777216,null,null,1,null,cn)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,pn)),t["\u0275did"](24,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,15,0,u.user.user_quota.max_size<=-1),l(n,17,0,u.user.user_quota.max_size>-1),l(n,22,0,u.user.user_quota.max_objects<=-1),l(n,24,0,u.user.user_quota.max_objects>-1)},function(l,n){var u=n.component,e=t["\u0275unv"](n,9,0,l(n,10,0,t["\u0275nov"](n.parent.parent.parent,0),u.user.user_quota.enabled));l(n,9,0,e)})}function mn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function gn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "])),t["\u0275ppd"](2,1)],null,function(l,n){var u=n.component,e=t["\u0275unv"](n,1,0,l(n,2,0,t["\u0275nov"](n.parent.parent.parent.parent,2),u.user.bucket_quota.max_size));l(n,1,0,e)})}function vn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited"]))],null,null)}function bn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](1,null,[" "," "]))],null,function(l,n){l(n,1,0,n.component.user.bucket_quota.max_objects)})}function hn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,24,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Bucket quota"])),(l()(),t["\u0275eld"](3,0,null,null,21,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,20,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Enabled"])),(l()(),t["\u0275eld"](8,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](9,null,["",""])),t["\u0275ppd"](10,1),(l()(),t["\u0275eld"](11,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum size"])),(l()(),t["\u0275and"](16777216,null,null,1,null,mn)),t["\u0275did"](15,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,gn)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](18,0,null,null,6,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum objects"])),(l()(),t["\u0275and"](16777216,null,null,1,null,vn)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,bn)),t["\u0275did"](24,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,15,0,u.user.bucket_quota.max_size<=-1),l(n,17,0,u.user.bucket_quota.max_size>-1),l(n,22,0,u.user.bucket_quota.max_objects<=-1),l(n,24,0,u.user.bucket_quota.max_objects>-1)},function(l,n){var u=n.component,e=t["\u0275unv"](n,9,0,l(n,10,0,t["\u0275nov"](n.parent.parent.parent,0),u.user.bucket_quota.enabled));l(n,9,0,e)})}function yn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,40,"div",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,35,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,34,"tbody",[],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Username"])),(l()(),t["\u0275eld"](6,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](7,null,["",""])),(l()(),t["\u0275eld"](8,0,null,null,4,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Full name"])),(l()(),t["\u0275eld"](11,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](12,null,["",""])),(l()(),t["\u0275and"](16777216,null,null,1,null,en)),t["\u0275did"](14,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](15,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Suspended"])),(l()(),t["\u0275eld"](18,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](19,null,["",""])),t["\u0275ppd"](20,1),(l()(),t["\u0275eld"](21,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](22,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["System"])),(l()(),t["\u0275eld"](24,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](25,null,["",""])),t["\u0275ppd"](26,1),(l()(),t["\u0275eld"](27,0,null,null,5,"tr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](28,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Maximum buckets"])),(l()(),t["\u0275eld"](30,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275ted"](31,null,["",""])),t["\u0275ppd"](32,2),(l()(),t["\u0275and"](16777216,null,null,1,null,on)),t["\u0275did"](34,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,rn)),t["\u0275did"](36,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,fn)),t["\u0275did"](38,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,hn)),t["\u0275did"](40,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,14,0,null==u.user.email?null:u.user.email.length),l(n,34,0,u.user.subusers&&u.user.subusers.length),l(n,36,0,u.user.caps&&u.user.caps.length),l(n,38,0,u.user.user_quota),l(n,40,0,u.user.bucket_quota)},function(l,n){var u=n.component;l(n,7,0,u.user.uid),l(n,12,0,u.user.display_name);var e=t["\u0275unv"](n,19,0,l(n,20,0,t["\u0275nov"](n.parent.parent,0),u.user.suspended));l(n,19,0,e);var i=t["\u0275unv"](n,25,0,l(n,26,0,t["\u0275nov"](n.parent.parent,0),"true"===u.user.system));l(n,25,0,i);var o=t["\u0275unv"](n,31,0,l(n,32,0,t["\u0275nov"](n.parent.parent,1),u.user.max_buckets,u.maxBucketsMap));l(n,31,0,o)})}function Cn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"tab",[["heading","Keys"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](1,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](2,0,null,null,9,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["selectionType","multi"]],null,[[null,"updateSelection"]],function(l,n,u){var e=!0;return"updateSelection"===n&&(e=!1!==l.component.updateKeysSelection(u)&&e),e},Yl.b,Yl.a)),t["\u0275did"](3,2867200,null,0,x.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],forceIdentifier:[3,"forceIdentifier"],selectionType:[4,"selectionType"]},{updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](4,0,null,0,7,"div",[["class","table-actions"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,16777216,null,null,6,"div",[["class","btn-group"],["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),t["\u0275prd"](512,null,Xl.f,Xl.f,[]),t["\u0275did"](7,212992,null,0,Xl.c,[t.ElementRef,t.Renderer2,t.ViewContainerRef,Jl.a,Xl.a,Xl.f],null,null),(l()(),t["\u0275eld"](8,0,null,null,3,"button",[["class","btn btn-sm btn-primary"],["type","button"]],[[8,"disabled",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showKeyModal()&&e),e},null,null)),(l()(),t["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-eye"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Show"]))],function(l,n){var u=n.component;l(n,1,0,"Keys"),l(n,3,0,u.keys,u.keysColumns,"flex","true","multi"),l(n,7,0)},function(l,n){var u=n.component;l(n,0,0,t["\u0275nov"](n,1).id,t["\u0275nov"](n,1).active,t["\u0275nov"](n,1).addClass),l(n,5,0,t["\u0275nov"](n,7).dropup,t["\u0275nov"](n,7).isOpen,t["\u0275nov"](n,7).isOpen&&t["\u0275nov"](n,7).isBs4),l(n,8,0,!u.keysSelection.hasSingleSelection)})}function _n(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,7,"tabset",[],[[2,"tab-container",null]],null,null,kl.b,kl.a)),t["\u0275did"](1,180224,null,0,vl.d,[vl.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](3,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,yn)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,0,1,null,Cn)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,"Details"),l(n,5,0,u.user),l(n,7,0,u.keys.length)},function(l,n){l(n,0,0,t["\u0275nov"](n,1).clazz),l(n,2,0,t["\u0275nov"](n,3).id,t["\u0275nov"](n,3).active,t["\u0275nov"](n,3).addClass)})}function kn(l){return t["\u0275vid"](0,[t["\u0275pid"](0,zl.a,[_l.a]),t["\u0275pid"](0,Wl.a,[]),t["\u0275pid"](0,q.a,[U.a]),t["\u0275qud"](402653184,1,{accessKeyTpl:0}),t["\u0275qud"](402653184,2,{secretKeyTpl:0}),(l()(),t["\u0275and"](16777216,null,null,1,null,_n)),t["\u0275did"](6,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,6,0,n.component.selection.hasSingleSelection)},null)}function Rn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-details",[],null,null,null,kn,un)),t["\u0275did"](1,638976,null,0,ln,[y.a,nn.b,_l.a],null,null)],function(l,n){l(n,1,0)},null)}var In=t["\u0275ccf"]("cd-rgw-user-details",ln,Rn,{selection:"selection"},{},[]),wn=u("8xTl"),En=u("ANnk"),xn=u("f/UV"),Tn=u("D4zM"),qn=u("OcYo"),Vn=u("SZbH"),Sn=u("KVJa"),Dn=u("Z21x"),Nn=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Fn(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,[""," ",""])),t["\u0275ppd"](5,1),t["\u0275ppd"](6,1),(l()(),t["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.bsModalRef.hide()&&e),e},null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xd7"])),(l()(),t["\u0275eld"](10,0,null,null,33,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,32,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,13).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,13).onReset()&&e),e},null,null)),t["\u0275did"](12,16384,null,0,d.D,[],null,null),t["\u0275did"](13,4210688,null,0,d.t,[[8,null],[8,null]],null,null),t["\u0275prd"](2048,null,d.d,null,[d.t]),t["\u0275did"](15,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](16,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","user"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Username"])),(l()(),t["\u0275eld"](19,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](20,0,null,null,6,"input",[["class","form-control"],["id","user"],["name","user"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0,i=l.component;return"input"===n&&(e=!1!==t["\u0275nov"](l,22)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,22).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,22)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,22)._compositionEnd(u.target.value)&&e),"ngModelChange"===n&&(e=!1!==(i.user=u)&&e),e},null,null)),t["\u0275did"](21,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](22,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](24,671744,null,0,d.u,[[2,d.d],[8,null],[8,null],[6,d.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),t["\u0275prd"](2048,null,d.q,null,[d.u]),t["\u0275did"](26,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](27,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](28,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","secret_key"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Secret key"])),(l()(),t["\u0275eld"](30,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](31,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](32,0,null,null,6,"input",[["class","form-control"],["id","secret_key"],["name","secret_key"],["type","password"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0,i=l.component;return"input"===n&&(e=!1!==t["\u0275nov"](l,34)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,34).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,34)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,34)._compositionEnd(u.target.value)&&e),"ngModelChange"===n&&(e=!1!==(i.secret_key=u)&&e),e},null,null)),t["\u0275did"](33,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](34,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](36,671744,null,0,d.u,[[2,d.d],[8,null],[8,null],[6,d.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),t["\u0275prd"](2048,null,d.q,null,[d.u]),t["\u0275did"](38,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](39,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](40,0,null,null,1,"button",[["cdPasswordButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,41).onClick()&&e),e},null,null)),t["\u0275did"](41,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](42,0,null,null,1,"button",[["cdCopy2ClipboardButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,43).onClick()&&e),e},null,null)),t["\u0275did"](43,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275eld"](44,0,null,null,2,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](45,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](46,49152,null,0,Dn.a,[ql.Location,i.b],{back:[0,"back"]},null)],function(l,n){var u=n.component;l(n,24,0,"user",u.user),l(n,36,0,"secret_key",u.secret_key),l(n,41,0,"secret_key"),l(n,43,0,"secret_key"),l(n,46,0,u.bsModalRef.hide)},function(l,n){var u=n.component,e=t["\u0275unv"](n,4,0,l(n,5,0,t["\u0275nov"](n,0),u.action)),i=t["\u0275unv"](n,4,1,l(n,6,0,t["\u0275nov"](n,1),u.resource));l(n,4,0,e,i),l(n,11,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending),l(n,20,0,!0,t["\u0275nov"](n,26).ngClassUntouched,t["\u0275nov"](n,26).ngClassTouched,t["\u0275nov"](n,26).ngClassPristine,t["\u0275nov"](n,26).ngClassDirty,t["\u0275nov"](n,26).ngClassValid,t["\u0275nov"](n,26).ngClassInvalid,t["\u0275nov"](n,26).ngClassPending),l(n,32,0,!0,t["\u0275nov"](n,38).ngClassUntouched,t["\u0275nov"](n,38).ngClassTouched,t["\u0275nov"](n,38).ngClassPristine,t["\u0275nov"](n,38).ngClassDirty,t["\u0275nov"](n,38).ngClassValid,t["\u0275nov"](n,38).ngClassInvalid,t["\u0275nov"](n,38).ngClassPending)})}function jn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-swift-key-modal",[],null,null,null,Fn,Nn)),t["\u0275did"](1,49152,null,0,$,[nn.a,_l.a,i.b],null,null)],null,null)}var Pn=t["\u0275ccf"]("cd-rgw-user-swift-key-modal",$,jn,{},{},[]),zn=u("IZUe"),An=u("gp3X"),Bn=u("sb0X"),Un=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Mn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function On(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","user"],["id","user"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,2)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,2).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,2)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,2)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](1,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](2,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](4,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](6,16384,null,0,d.r,[[4,d.q]],null,null)],function(l,n){l(n,4,0,"user")},function(l,n){l(n,0,0,!0,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function Ln(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["-- Select a username --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Gn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Kn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"select",[["autofocus",""],["class","form-control"],["formControlName","user"],["id","user"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,3).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,3).onTouched()&&e),e},null,null)),t["\u0275did"](1,4210688,null,0,zn.a,[t.ElementRef],null,null),t["\u0275did"](2,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](3,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](5,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](7,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ln)),t["\u0275did"](9,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Gn)),t["\u0275did"](11,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var u=n.component;l(n,5,0,"user"),l(n,9,0,null!==u.userCandidates),l(n,11,0,u.userCandidates)},function(l,n){l(n,0,0,t["\u0275nov"](n,7).ngClassUntouched,t["\u0275nov"](n,7).ngClassTouched,t["\u0275nov"](n,7).ngClassPristine,t["\u0275nov"](n,7).ngClassDirty,t["\u0275nov"](n,7).ngClassValid,t["\u0275nov"](n,7).ngClassInvalid,t["\u0275nov"](n,7).ngClassPending)})}function $n(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Zn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,6,"input",[["formControlName","generate_key"],["id","generate_key"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,5).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,5).onTouched()&&e),e},null,null)),t["\u0275did"](4,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](5,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](7,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](9,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](10,0,null,null,1,"label",[["for","generate_key"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Auto-generate key"]))],function(l,n){l(n,7,0,"generate_key")},function(l,n){l(n,3,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function Qn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Hn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Yn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","access_key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Access key"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Qn)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](8,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,6,"input",[["class","form-control"],["formControlName","access_key"],["id","access_key"],["type","password"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,12)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,12).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,12)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,12)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](11,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](12,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](14,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](16,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](17,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](18,0,null,null,1,"button",[["cdPasswordButton","access_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,19).onClick()&&e),e},null,null)),t["\u0275did"](19,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](20,0,null,null,1,"button",[["cdCopy2ClipboardButton","access_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,21).onClick()&&e),e},null,null)),t["\u0275did"](21,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Hn)),t["\u0275did"](23,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.formGroup.showError("access_key",t["\u0275nov"](n.parent,12)));l(n,1,0,"form-group",e),l(n,7,0,!u.viewing),l(n,14,0,"access_key"),l(n,19,0,"access_key"),l(n,21,0,"access_key"),l(n,23,0,u.formGroup.showError("access_key",t["\u0275nov"](n.parent,12),"required"))},function(l,n){l(n,10,0,n.component.viewing,t["\u0275nov"](n,16).ngClassUntouched,t["\u0275nov"](n,16).ngClassTouched,t["\u0275nov"](n,16).ngClassPristine,t["\u0275nov"](n,16).ngClassDirty,t["\u0275nov"](n,16).ngClassValid,t["\u0275nov"](n,16).ngClassInvalid,t["\u0275nov"](n,16).ngClassPending)})}function Xn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Jn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Wn(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","secret_key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Secret key"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Xn)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](8,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,6,"input",[["class","form-control"],["formControlName","secret_key"],["id","secret_key"],["type","password"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,12)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,12).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,12)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,12)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](11,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](12,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](14,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](16,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](17,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](18,0,null,null,1,"button",[["cdPasswordButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,19).onClick()&&e),e},null,null)),t["\u0275did"](19,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](20,0,null,null,1,"button",[["cdCopy2ClipboardButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,21).onClick()&&e),e},null,null)),t["\u0275did"](21,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Jn)),t["\u0275did"](23,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.formGroup.showError("secret_key",t["\u0275nov"](n.parent,12)));l(n,1,0,"form-group",e),l(n,7,0,!u.viewing),l(n,14,0,"secret_key"),l(n,19,0,"secret_key"),l(n,21,0,"secret_key"),l(n,23,0,u.formGroup.showError("secret_key",t["\u0275nov"](n.parent,12),"required"))},function(l,n){l(n,10,0,n.component.viewing,t["\u0275nov"](n,16).ngClassUntouched,t["\u0275nov"](n,16).ngClassTouched,t["\u0275nov"](n,16).ngClassPristine,t["\u0275nov"](n,16).ngClassDirty,t["\u0275nov"](n,16).ngClassValid,t["\u0275nov"](n,16).ngClassInvalid,t["\u0275nov"](n,16).ngClassPending)})}function lu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,4,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.onSubmit()&&e),e},An.b,An.a)),t["\u0275did"](1,114688,null,0,Bn.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](2,0,[""," ",""])),t["\u0275ppd"](3,1),t["\u0275ppd"](4,1)],function(l,n){l(n,1,0,n.component.formGroup)},function(l,n){var u=n.component,e=t["\u0275unv"](n,2,0,l(n,3,0,t["\u0275nov"](n.parent,0),u.action)),i=t["\u0275unv"](n,2,1,l(n,4,0,t["\u0275nov"](n.parent,1),u.resource));l(n,2,0,e,i)})}function nu(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,[""," ",""])),t["\u0275ppd"](5,1),t["\u0275ppd"](6,1),(l()(),t["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.bsModalRef.hide()&&e),e},null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xd7"])),(l()(),t["\u0275eld"](10,0,null,null,31,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,12).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,12).onReset()&&e),e},null,null)),t["\u0275did"](11,16384,null,0,d.D,[],null,null),t["\u0275did"](12,540672,[["frm",4]],0,d.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,d.d,null,[d.l]),t["\u0275did"](14,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](15,0,null,null,21,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](17,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](18,{"has-error":0}),(l()(),t["\u0275eld"](19,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","user"]],null,null,null,null,null)),(l()(),t["\u0275eld"](20,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Username"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Mn)),t["\u0275did"](23,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](24,0,null,null,6,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,On)),t["\u0275did"](26,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Kn)),t["\u0275did"](28,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,$n)),t["\u0275did"](30,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Zn)),t["\u0275did"](32,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Yn)),t["\u0275did"](34,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Wn)),t["\u0275did"](36,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](37,0,null,null,4,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,lu)),t["\u0275did"](39,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](40,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](41,49152,null,0,Dn.a,[ql.Location,i.b],{back:[0,"back"]},null)],function(l,n){var u=n.component;l(n,12,0,u.formGroup);var e=l(n,18,0,u.formGroup.showError("user",t["\u0275nov"](n,12)));l(n,17,0,"form-group",e),l(n,23,0,!u.viewing),l(n,26,0,u.viewing),l(n,28,0,!u.viewing),l(n,30,0,u.formGroup.showError("user",t["\u0275nov"](n,12),"required")),l(n,32,0,!u.viewing),l(n,34,0,!u.formGroup.getValue("generate_key")),l(n,36,0,!u.formGroup.getValue("generate_key")),l(n,39,0,!u.viewing),l(n,41,0,u.bsModalRef.hide)},function(l,n){var u=n.component,e=t["\u0275unv"](n,4,0,l(n,5,0,t["\u0275nov"](n,0),u.action)),i=t["\u0275unv"](n,4,1,l(n,6,0,t["\u0275nov"](n,1),u.resource));l(n,4,0,e,i),l(n,10,0,t["\u0275nov"](n,14).ngClassUntouched,t["\u0275nov"](n,14).ngClassTouched,t["\u0275nov"](n,14).ngClassPristine,t["\u0275nov"](n,14).ngClassDirty,t["\u0275nov"](n,14).ngClassValid,t["\u0275nov"](n,14).ngClassInvalid,t["\u0275nov"](n,14).ngClassPending)})}function uu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-s3-key-modal",[],null,null,null,nu,Un)),t["\u0275did"](1,49152,null,0,L,[_.a,nn.a,_l.a,i.b],null,null)],null,null)}var eu=t["\u0275ccf"]("cd-rgw-user-s3-key-modal",L,uu,{},{submitAction:"submitAction"},[]),tu=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function iu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function ou(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","type"],["id","type"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,2)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,2).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,2)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,2)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](1,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](2,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](4,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](6,16384,null,0,d.r,[[4,d.q]],null,null)],function(l,n){l(n,4,0,"type")},function(l,n){l(n,0,0,!0,t["\u0275nov"](n,6).ngClassUntouched,t["\u0275nov"](n,6).ngClassTouched,t["\u0275nov"](n,6).ngClassPristine,t["\u0275nov"](n,6).ngClassDirty,t["\u0275nov"](n,6).ngClassValid,t["\u0275nov"](n,6).ngClassInvalid,t["\u0275nov"](n,6).ngClassPending)})}function au(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["-- Select a type --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function ru(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function su(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"select",[["autofocus",""],["class","form-control"],["formControlName","type"],["id","type"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,3).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,3).onTouched()&&e),e},null,null)),t["\u0275did"](1,4210688,null,0,zn.a,[t.ElementRef],null,null),t["\u0275did"](2,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](3,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](5,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](7,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,au)),t["\u0275did"](9,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ru)),t["\u0275did"](11,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var u=n.component;l(n,5,0,"type"),l(n,9,0,null!==u.types),l(n,11,0,u.types)},function(l,n){l(n,0,0,t["\u0275nov"](n,7).ngClassUntouched,t["\u0275nov"](n,7).ngClassTouched,t["\u0275nov"](n,7).ngClassPristine,t["\u0275nov"](n,7).ngClassDirty,t["\u0275nov"](n,7).ngClassValid,t["\u0275nov"](n,7).ngClassInvalid,t["\u0275nov"](n,7).ngClassPending)})}function du(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function cu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function pu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function fu(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,[""," ",""])),t["\u0275ppd"](5,1),t["\u0275ppd"](6,1),(l()(),t["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.bsModalRef.hide()&&e),e},null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xd7"])),(l()(),t["\u0275eld"](10,0,null,null,52,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,12).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,12).onReset()&&e),e},null,null)),t["\u0275did"](11,16384,null,0,d.D,[],null,null),t["\u0275did"](12,540672,[["frm",4]],0,d.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,d.d,null,[d.l]),t["\u0275did"](14,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](15,0,null,null,39,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](17,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](18,{"has-error":0}),(l()(),t["\u0275eld"](19,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","type"]],null,null,null,null,null)),(l()(),t["\u0275eld"](20,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Type"])),(l()(),t["\u0275and"](16777216,null,null,1,null,iu)),t["\u0275did"](23,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](24,0,null,null,6,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,ou)),t["\u0275did"](26,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,su)),t["\u0275did"](28,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,du)),t["\u0275did"](30,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](31,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](32,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](33,{"has-error":0}),(l()(),t["\u0275eld"](34,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","perm"]],null,null,null,null,null)),(l()(),t["\u0275eld"](35,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Permission"])),(l()(),t["\u0275eld"](37,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](38,0,null,null,16,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](39,0,null,null,13,"select",[["class","form-control"],["formControlName","perm"],["id","perm"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,41).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,41).onTouched()&&e),e},null,null)),t["\u0275did"](40,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](41,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](43,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](45,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](46,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](47,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](48,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["-- Select a permission --"])),(l()(),t["\u0275and"](16777216,null,null,2,null,cu)),t["\u0275did"](51,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),t["\u0275pad"](52,3),(l()(),t["\u0275and"](16777216,null,null,1,null,pu)),t["\u0275did"](54,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](55,0,null,null,7,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](56,0,null,null,4,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.onSubmit()&&e),e},An.b,An.a)),t["\u0275did"](57,114688,null,0,Bn.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](58,0,[""," ",""])),t["\u0275ppd"](59,1),t["\u0275ppd"](60,1),(l()(),t["\u0275eld"](61,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](62,49152,null,0,Dn.a,[ql.Location,i.b],{back:[0,"back"]},null)],function(l,n){var u=n.component;l(n,12,0,u.formGroup);var e=l(n,18,0,u.formGroup.showError("type",t["\u0275nov"](n,12)));l(n,17,0,"form-group",e),l(n,23,0,!u.editing),l(n,26,0,u.editing),l(n,28,0,!u.editing),l(n,30,0,u.formGroup.showError("type",t["\u0275nov"](n,12),"required"));var i=l(n,33,0,u.formGroup.showError("perm",t["\u0275nov"](n,12)));l(n,32,0,"form-group",i),l(n,43,0,"perm"),l(n,47,0,null),l(n,48,0,null);var o=l(n,52,0,"read","write","*");l(n,51,0,o),l(n,54,0,u.formGroup.showError("perm",t["\u0275nov"](n,12),"required")),l(n,57,0,u.formGroup),l(n,62,0,u.bsModalRef.hide)},function(l,n){var u=n.component,e=t["\u0275unv"](n,4,0,l(n,5,0,t["\u0275nov"](n,0),u.action)),i=t["\u0275unv"](n,4,1,l(n,6,0,t["\u0275nov"](n,1),u.resource));l(n,4,0,e,i),l(n,10,0,t["\u0275nov"](n,14).ngClassUntouched,t["\u0275nov"](n,14).ngClassTouched,t["\u0275nov"](n,14).ngClassPristine,t["\u0275nov"](n,14).ngClassDirty,t["\u0275nov"](n,14).ngClassValid,t["\u0275nov"](n,14).ngClassInvalid,t["\u0275nov"](n,14).ngClassPending),l(n,39,0,t["\u0275nov"](n,45).ngClassUntouched,t["\u0275nov"](n,45).ngClassTouched,t["\u0275nov"](n,45).ngClassPristine,t["\u0275nov"](n,45).ngClassDirty,t["\u0275nov"](n,45).ngClassValid,t["\u0275nov"](n,45).ngClassInvalid,t["\u0275nov"](n,45).ngClassPending);var o=t["\u0275unv"](n,58,0,l(n,59,0,t["\u0275nov"](n,0),u.action)),a=t["\u0275unv"](n,58,1,l(n,60,0,t["\u0275nov"](n,1),u.resource));l(n,58,0,o,a)})}function mu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-capability-modal",[],null,null,null,fu,tu)),t["\u0275did"](1,49152,null,0,O,[_.a,nn.a,_l.a,i.b],null,null)],null,null)}var gu=t["\u0275ccf"]("cd-rgw-user-capability-modal",O,mu,{},{submitAction:"submitAction"},[]),vu=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function bu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function hu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function yu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The chosen subuser ID is already in use."]))],null,null)}function Cu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function _u(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function ku(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Ru(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","secret_key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Secret key"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,6,"input",[["class","form-control"],["formControlName","secret_key"],["id","secret_key"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,11)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,11).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](10,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](11,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](13,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](16,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,"button",[["cdPasswordButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,18).onClick()&&e),e},null,null)),t["\u0275did"](18,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](19,0,null,null,1,"button",[["cdCopy2ClipboardButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,20).onClick()&&e),e},null,null)),t["\u0275did"](20,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ku)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.formGroup.showError("secret_key",t["\u0275nov"](n.parent.parent,12)));l(n,1,0,"form-group",e),l(n,13,0,"secret_key"),l(n,18,0,"secret_key"),l(n,20,0,"secret_key"),l(n,22,0,u.formGroup.showError("secret_key",t["\u0275nov"](n.parent.parent,12),"required"))},function(l,n){l(n,9,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function Iu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,16,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Swift key"])),(l()(),t["\u0275eld"](3,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,6,"input",[["formControlName","generate_secret"],["id","generate_secret"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,8).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,8).onTouched()&&e),e},null,null)),t["\u0275did"](7,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](8,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](10,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](12,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](13,0,null,null,1,"label",[["for","generate_secret"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Auto-generate secret"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Ru)),t["\u0275did"](16,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,10,0,"generate_secret"),l(n,16,0,!u.editing&&!u.formGroup.getValue("generate_secret"))},function(l,n){l(n,6,0,t["\u0275nov"](n,12).ngClassUntouched,t["\u0275nov"](n,12).ngClassTouched,t["\u0275nov"](n,12).ngClassPristine,t["\u0275nov"](n,12).ngClassDirty,t["\u0275nov"](n,12).ngClassValid,t["\u0275nov"](n,12).ngClassInvalid,t["\u0275nov"](n,12).ngClassPending)})}function wu(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),t["\u0275ted"](4,null,[""," ",""])),t["\u0275ppd"](5,1),t["\u0275ppd"](6,1),(l()(),t["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.bsModalRef.hide()&&e),e},null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["\xd7"])),(l()(),t["\u0275eld"](10,0,null,null,81,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,12).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,12).onReset()&&e),e},null,null)),t["\u0275did"](11,16384,null,0,d.D,[],null,null),t["\u0275did"](12,540672,[["frm",4]],0,d.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,d.d,null,[d.l]),t["\u0275did"](14,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](15,0,null,null,68,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](16,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](17,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](18,{"has-error":0}),(l()(),t["\u0275eld"](19,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","uid"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Username"])),(l()(),t["\u0275eld"](21,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](22,0,null,null,6,"input",[["class","form-control"],["formControlName","uid"],["id","uid"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,24)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,24).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,24)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,24)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](23,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](24,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](26,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](28,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](29,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](30,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](31,{"has-error":0}),(l()(),t["\u0275eld"](32,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","subuid"]],null,null,null,null,null)),(l()(),t["\u0275eld"](33,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Subuser"])),(l()(),t["\u0275and"](16777216,null,null,1,null,bu)),t["\u0275did"](36,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](37,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](38,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","subuid"],["id","subuid"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,41)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,41).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,41)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,41)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](39,4210688,null,0,zn.a,[t.ElementRef],null,null),t["\u0275did"](40,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](41,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](43,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](45,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,hu)),t["\u0275did"](47,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,yu)),t["\u0275did"](49,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](50,0,null,null,31,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](51,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](52,{"has-error":0}),(l()(),t["\u0275eld"](53,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","perm"]],null,null,null,null,null)),(l()(),t["\u0275eld"](54,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Permission"])),(l()(),t["\u0275eld"](56,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](57,0,null,null,24,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](58,0,null,null,21,"select",[["class","form-control"],["formControlName","perm"],["id","perm"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,60).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,60).onTouched()&&e),e},null,null)),t["\u0275did"](59,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](60,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](62,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](64,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](65,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](66,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](67,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["-- Select a permission --"])),(l()(),t["\u0275and"](16777216,null,null,2,null,Cu)),t["\u0275did"](70,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),t["\u0275pad"](71,2),(l()(),t["\u0275eld"](72,0,null,null,3,"option",[["value","read-write"]],null,null,null,null,null)),t["\u0275did"](73,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](74,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["read, write"])),(l()(),t["\u0275eld"](76,0,null,null,3,"option",[["value","full-control"]],null,null,null,null,null)),t["\u0275did"](77,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](78,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["full"])),(l()(),t["\u0275and"](16777216,null,null,1,null,_u)),t["\u0275did"](81,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Iu)),t["\u0275did"](83,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](84,0,null,null,7,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](85,0,null,null,4,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.onSubmit()&&e),e},An.b,An.a)),t["\u0275did"](86,114688,null,0,Bn.a,[t.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](87,0,[""," ",""])),t["\u0275ppd"](88,1),t["\u0275ppd"](89,1),(l()(),t["\u0275eld"](90,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](91,49152,null,0,Dn.a,[ql.Location,i.b],{back:[0,"back"]},null)],function(l,n){var u=n.component;l(n,12,0,u.formGroup);var e=l(n,18,0,u.formGroup.showError("uid",t["\u0275nov"](n,12)));l(n,17,0,"form-group",e),l(n,26,0,"uid");var i=l(n,31,0,u.formGroup.showError("subuid",t["\u0275nov"](n,12)));l(n,30,0,"form-group",i),l(n,36,0,!u.editing),l(n,43,0,"subuid"),l(n,47,0,u.formGroup.showError("subuid",t["\u0275nov"](n,12),"required")),l(n,49,0,u.formGroup.showError("subuid",t["\u0275nov"](n,12),"subuserIdExists"));var o=l(n,52,0,u.formGroup.showError("perm",t["\u0275nov"](n,12)));l(n,51,0,"form-group",o),l(n,62,0,"perm"),l(n,66,0,null),l(n,67,0,null);var a=l(n,71,0,"read","write");l(n,70,0,a),l(n,73,0,"read-write"),l(n,74,0,"read-write"),l(n,77,0,"full-control"),l(n,78,0,"full-control"),l(n,81,0,u.formGroup.showError("perm",t["\u0275nov"](n,12),"required")),l(n,83,0,!u.editing),l(n,86,0,u.formGroup),l(n,91,0,u.bsModalRef.hide)},function(l,n){var u=n.component,e=t["\u0275unv"](n,4,0,l(n,5,0,t["\u0275nov"](n,0),u.action)),i=t["\u0275unv"](n,4,1,l(n,6,0,t["\u0275nov"](n,1),u.resource));l(n,4,0,e,i),l(n,10,0,t["\u0275nov"](n,14).ngClassUntouched,t["\u0275nov"](n,14).ngClassTouched,t["\u0275nov"](n,14).ngClassPristine,t["\u0275nov"](n,14).ngClassDirty,t["\u0275nov"](n,14).ngClassValid,t["\u0275nov"](n,14).ngClassInvalid,t["\u0275nov"](n,14).ngClassPending),l(n,22,0,!0,t["\u0275nov"](n,28).ngClassUntouched,t["\u0275nov"](n,28).ngClassTouched,t["\u0275nov"](n,28).ngClassPristine,t["\u0275nov"](n,28).ngClassDirty,t["\u0275nov"](n,28).ngClassValid,t["\u0275nov"](n,28).ngClassInvalid,t["\u0275nov"](n,28).ngClassPending),l(n,38,0,u.editing,t["\u0275nov"](n,45).ngClassUntouched,t["\u0275nov"](n,45).ngClassTouched,t["\u0275nov"](n,45).ngClassPristine,t["\u0275nov"](n,45).ngClassDirty,t["\u0275nov"](n,45).ngClassValid,t["\u0275nov"](n,45).ngClassInvalid,t["\u0275nov"](n,45).ngClassPending),l(n,58,0,t["\u0275nov"](n,64).ngClassUntouched,t["\u0275nov"](n,64).ngClassTouched,t["\u0275nov"](n,64).ngClassPristine,t["\u0275nov"](n,64).ngClassDirty,t["\u0275nov"](n,64).ngClassValid,t["\u0275nov"](n,64).ngClassInvalid,t["\u0275nov"](n,64).ngClassPending);var o=t["\u0275unv"](n,87,0,l(n,88,0,t["\u0275nov"](n,0),u.action)),a=t["\u0275unv"](n,87,1,l(n,89,0,t["\u0275nov"](n,1),u.resource));l(n,87,0,o,a)})}function Eu(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-subuser-modal",[],null,null,null,wu,vu)),t["\u0275did"](1,49152,null,0,K,[_.a,nn.a,_l.a,i.b],null,null)],null,null)}var xu=t["\u0275ccf"]("cd-rgw-user-subuser-modal",K,Eu,{},{submitAction:"submitAction"},[]),Tu=u("IzCI"),qu=u("Dwqy"),Vu=u("uYzU"),Su=u("uhwM"),Du=u("E2fk"),Nu=u("nSDx"),Fu=u("SB+Q"),ju=u("TYzs"),Pu=u("BQkM"),zu=u("dEH0"),Au=u("G1/K"),Bu=u("lTVp"),Uu=u("OZfm"),Mu=u("NJnL"),Ou=u("eajB"),Lu=u("FO+L"),Gu=u("nhM1"),Ku=u("BARL"),$u=u("ZYCi"),Zu=u("9Xeq"),Qu=u("xdbM"),Hu=u("yGOH"),Yu=u("V/fk"),Xu=u("F8xH"),Ju=u("ChqD"),Wu=u("PCNd"),le=u("G6Q+"),ne=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function ue(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"tab",[["heading","Overall Performance"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](1,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","two"],["uid","WAkugZpiz"]],null,null,null,bl.b,bl.a)),t["\u0275did"](3,638976,null,0,hl.a,[r.a,yl.DomSanitizer,Cl.a,a.a,_l.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(l,n){l(n,1,0,"Overall Performance"),l(n,3,0,"rgw-overview?","two","WAkugZpiz")},function(l,n){l(n,0,0,t["\u0275nov"](n,1).id,t["\u0275nov"](n,1).active,t["\u0275nov"](n,1).addClass)})}function ee(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,9,"tabset",[],[[2,"tab-container",null]],null,null,kl.b,kl.a)),t["\u0275did"](1,180224,null,0,vl.d,[vl.e,t.Renderer2,t.ElementRef],null,null),(l()(),t["\u0275eld"](2,0,null,0,5,"tab",[["heading","Daemons List"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),t["\u0275did"](3,212992,null,0,vl.b,[vl.d,t.ElementRef,t.Renderer2],{heading:[0,"heading"]},null),(l()(),t["\u0275eld"](4,0,null,null,3,"cd-table",[["columnMode","flex"],["selectionType","single"]],null,[[null,"updateSelection"],[null,"fetchData"]],function(l,n,u){var e=!0,t=l.component;return"updateSelection"===n&&(e=!1!==t.updateSelection(u)&&e),"fetchData"===n&&(e=!1!==t.getDaemonList(u)&&e),e},Yl.b,Yl.a)),t["\u0275did"](5,2867200,null,0,x.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],selectionType:[3,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](6,0,null,2,1,"cd-rgw-daemon-details",[["cdTableDetail",""]],null,null,null,Fl,Sl)),t["\u0275did"](7,573440,null,0,Vl,[j,S.a],{selection:[0,"selection"]},null),(l()(),t["\u0275and"](16777216,null,0,1,null,ue)),t["\u0275did"](9,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,"Daemons List"),l(n,5,0,u.daemons,u.columns,"flex","single"),l(n,7,0,u.selection),l(n,9,0,u.grafanaPermission.read)},function(l,n){l(n,0,0,t["\u0275nov"](n,1).clazz),l(n,2,0,t["\u0275nov"](n,3).id,t["\u0275nov"](n,3).active,t["\u0275nov"](n,3).addClass)})}function te(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-daemon-list",[],null,null,null,ee,ne)),t["\u0275did"](1,49152,null,0,z,[j,S.a,P.a,_l.a],null,null)],null,null)}var ie=t["\u0275ccf"]("cd-rgw-daemon-list",z,te,{},{},[]),oe=u("NUGo"),ae=u("S7zO"),re=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function se(l){return t["\u0275vid"](0,[t["\u0275qud"](402653184,1,{table:0}),(l()(),t["\u0275eld"](1,0,null,null,5,"cd-table",[["columnMode","flex"],["identifier","uid"],["selectionType","multi"]],null,[[null,"updateSelection"],[null,"fetchData"]],function(l,n,u){var e=!0,t=l.component;return"updateSelection"===n&&(e=!1!==t.updateSelection(u)&&e),"fetchData"===n&&(e=!1!==t.getUserList(u)&&e),e},Yl.b,Yl.a)),t["\u0275did"](2,2867200,[[1,4],["table",4]],0,x.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"],identifier:[4,"identifier"],selectionType:[5,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](3,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,oe.b,oe.a)),t["\u0275did"](4,114688,null,0,ae.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),t["\u0275eld"](5,0,null,2,1,"cd-rgw-user-details",[["cdTableDetail",""]],null,null,null,kn,un)),t["\u0275did"](6,638976,null,0,ln,[y.a,nn.b,_l.a],{selection:[0,"selection"]},null)],function(l,n){var u=n.component;l(n,2,0,u.users,u.columns,"flex",!1,"uid","multi"),l(n,4,0,u.permission,u.selection,u.tableActions),l(n,6,0,u.selection)},null)}function de(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-rgw-user-list",[],null,null,null,se,re)),t["\u0275prd"](256,null,D.a,H,[]),t["\u0275did"](2,49152,null,0,Y,[S.a,y.a,nn.b,_l.a,D.a,i.b],null,null)],null,null)}var ce=t["\u0275ccf"]("cd-rgw-user-list",Y,de,{},{},[]),pe=u("QC43"),fe=u("XFyV"),me=u("M/6F"),ge=u("NDi4"),ve=u("EmSq"),be=t["\u0275crt"]({encapsulation:0,styles:[["form[_ngcontent-%COMP%] .input-group-addon[_ngcontent-%COMP%]{color:#90949c!important;background-color:transparent}"]],data:{}});function he(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-loading-panel",[],null,null,null,pe.b,pe.a)),t["\u0275did"](1,49152,null,0,fe.a,[],null,null),(l()(),t["\u0275ted"](-1,0,["Loading user data..."]))],null,null)}function ye(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-error-panel",[],null,[[null,"backAction"]],function(l,n,u){var e=!0;return"backAction"===n&&(e=!1!==l.component.goToListView()&&e),e},me.b,me.a)),t["\u0275did"](1,49152,null,0,ge.a,[],null,{backAction:"backAction"}),(l()(),t["\u0275ted"](-1,0,["The user data could not be loaded."]))],null,null)}function Ce(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function _e(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function ke(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The chosen user ID is already in use."]))],null,null)}function Re(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Ie(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function we(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This is not a valid email address."]))],null,null)}function Ee(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The chosen email address is already in use."]))],null,null)}function xe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Te(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The entered value must be >= 1."]))],null,null)}function qe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,0,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,7,"input",[["class","form-control"],["formControlName","max_buckets"],["id","max_buckets"],["min","1"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,7)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,7).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,7)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,7)._compositionEnd(u.target.value)&&e),"change"===n&&(e=!1!==t["\u0275nov"](l,8).onChange(u.target.value)&&e),"input"===n&&(e=!1!==t["\u0275nov"](l,8).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,8).onTouched()&&e),e},null,null)),t["\u0275did"](6,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](7,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275did"](8,16384,null,0,d.C,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l,n){return[l,n]},[d.e,d.C]),t["\u0275did"](10,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](12,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,xe)),t["\u0275did"](14,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Te)),t["\u0275did"](16,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("max_buckets",t["\u0275nov"](n.parent,3)));l(n,1,0,"form-group",e),l(n,10,0,"max_buckets"),l(n,14,0,u.userForm.showError("max_buckets",t["\u0275nov"](n.parent,3),"required")),l(n,16,0,u.userForm.showError("max_buckets",t["\u0275nov"](n.parent,3),"min"))},function(l,n){l(n,5,0,t["\u0275nov"](n,12).ngClassUntouched,t["\u0275nov"](n,12).ngClassTouched,t["\u0275nov"](n,12).ngClassPristine,t["\u0275nov"](n,12).ngClassDirty,t["\u0275nov"](n,12).ngClassValid,t["\u0275nov"](n,12).ngClassInvalid,t["\u0275nov"](n,12).ngClassPending)})}function Ve(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Se(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","access_key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Access key"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,6,"input",[["class","form-control"],["formControlName","access_key"],["id","access_key"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,11)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,11).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](10,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](11,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](13,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](16,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,"button",[["cdPasswordButton","access_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,18).onClick()&&e),e},null,null)),t["\u0275did"](18,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](19,0,null,null,1,"button",[["cdCopy2ClipboardButton","access_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,20).onClick()&&e),e},null,null)),t["\u0275did"](20,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ve)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("access_key",t["\u0275nov"](n.parent.parent,3)));l(n,1,0,"form-group",e),l(n,13,0,"access_key"),l(n,18,0,"access_key"),l(n,20,0,"access_key"),l(n,22,0,u.userForm.showError("access_key",t["\u0275nov"](n.parent.parent,3),"required"))},function(l,n){l(n,9,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function De(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Ne(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","secret_key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Secret key"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,6,"input",[["class","form-control"],["formControlName","secret_key"],["id","secret_key"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,11)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,11).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,11)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](10,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](11,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](13,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](16,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,"button",[["cdPasswordButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,18).onClick()&&e),e},null,null)),t["\u0275did"](18,81920,null,0,Tn.a,[t.ElementRef,t.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),t["\u0275eld"](19,0,null,null,1,"button",[["cdCopy2ClipboardButton","secret_key"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==t["\u0275nov"](l,20).onClick()&&e),e},null,null)),t["\u0275did"](20,81920,null,0,qn.a,[t.ElementRef,t.Renderer2,Vn.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,De)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("secret_key",t["\u0275nov"](n.parent.parent,3)));l(n,1,0,"form-group",e),l(n,13,0,"secret_key"),l(n,18,0,"secret_key"),l(n,20,0,"secret_key"),l(n,22,0,u.userForm.showError("secret_key",t["\u0275nov"](n.parent.parent,3),"required"))},function(l,n){l(n,9,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function Fe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,18,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["S3 key"])),(l()(),t["\u0275eld"](3,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](5,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](6,0,null,null,6,"input",[["formControlName","generate_key"],["id","generate_key"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,8).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,8).onTouched()&&e),e},null,null)),t["\u0275did"](7,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](8,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](10,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](12,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](13,0,null,null,1,"label",[["for","generate_key"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Auto-generate key"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Se)),t["\u0275did"](16,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ne)),t["\u0275did"](18,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,10,0,"generate_key"),l(n,16,0,!u.editing&&!u.userForm.getValue("generate_key")),l(n,18,0,!u.editing&&!u.userForm.getValue("generate_key"))},function(l,n){l(n,6,0,t["\u0275nov"](n,12).ngClassUntouched,t["\u0275nov"](n,12).ngClassTouched,t["\u0275nov"](n,12).ngClassPristine,t["\u0275nov"](n,12).ngClassDirty,t["\u0275nov"](n,12).ngClassValid,t["\u0275nov"](n,12).ngClassInvalid,t["\u0275nov"](n,12).ngClassPending)})}function je(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["There are no subusers."]))],null,null)}function Pe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,17,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,15,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,0,"i",[["class","icon-prepend fa fa-user"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"input",[["class","form-control"],["readonly",""],["type","text"]],[[8,"value",0]],null,null,null,null)),t["\u0275did"](5,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](6,0,null,null,1,"span",[["class","input-group-addon"],["style","border-left: 0; border-right: 0;"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,0,"i",[["class","icon-prepend fa fa-share-alt"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,1,"input",[["class","form-control"],["readonly",""],["type","text"]],[[8,"value",0]],null,null,null,null)),t["\u0275did"](9,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](10,0,null,null,6,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,16777216,null,null,2,"button",[["class","btn btn-default tc_showSubuserButton"],["tooltip","Edit"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showSubuserModal(l.context.index)&&e),e},null,null)),t["\u0275did"](12,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](13,0,null,null,0,"i",[["class","fa fa-cogs"]],null,null,null,null,null)),(l()(),t["\u0275eld"](14,16777216,null,null,2,"button",[["class","btn btn-default tc_deleteSubuserButton"],["tooltip","Delete"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.deleteSubuser(l.context.index)&&e),e},null,null)),t["\u0275did"](15,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](16,0,null,null,0,"i",[["class","fa fa-times"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,0,"span",[["class","help-block"]],null,null,null,null,null))],function(l,n){l(n,12,0,"Edit"),l(n,15,0,"Delete")},function(l,n){l(n,4,0,t["\u0275inlineInterpolate"](1,"",n.context.$implicit.id,"")),l(n,8,0,t["\u0275inlineInterpolate"](1,"","full-control"===n.context.$implicit.permissions?"full":n.context.$implicit.permissions,"")),l(n,11,0,t["\u0275nov"](n,12).ariaDescribedby),l(n,14,0,t["\u0275nov"](n,15).ariaDescribedby)})}function ze(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,14,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Subusers"])),(l()(),t["\u0275eld"](3,0,null,null,11,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,je)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Pe)),t["\u0275did"](7,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275eld"](8,0,null,null,6,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,0,null,null,5,"button",[["class","btn btn-sm btn-default btn-label pull-right tc_addSubuserButton"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showSubuserModal()&&e),e},null,null)),(l()(),t["\u0275eld"](10,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,3,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](12,null,[""," ",""])),t["\u0275ppd"](13,1),t["\u0275ppd"](14,1)],function(l,n){var u=n.component;l(n,5,0,0===u.subusers.length),l(n,7,0,u.subusers)},function(l,n){var u=n.component,e=t["\u0275unv"](n,12,0,l(n,13,0,t["\u0275nov"](n.parent.parent,0),u.actionLabels.CREATE)),i=t["\u0275unv"](n,12,1,l(n,14,0,t["\u0275nov"](n.parent.parent,1),u.subuserLabel));l(n,12,0,e,i)})}function Ae(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["There are no keys."]))],null,null)}function Be(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,13,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,11,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,0,"i",[["class","icon-prepend fa fa-key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"input",[["class","form-control"],["readonly",""],["type","text"]],[[8,"value",0]],null,null,null,null)),t["\u0275did"](5,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](6,0,null,null,6,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,16777216,null,null,2,"button",[["class","btn btn-default tc_showS3KeyButton"],["tooltip","Show"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showS3KeyModal(l.context.index)&&e),e},null,null)),t["\u0275did"](8,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-eye"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,16777216,null,null,2,"button",[["class","btn btn-default tc_deleteS3KeyButton"],["tooltip","Delete"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.deleteS3Key(l.context.index)&&e),e},null,null)),t["\u0275did"](11,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](12,0,null,null,0,"i",[["class","fa fa-times"]],null,null,null,null,null)),(l()(),t["\u0275eld"](13,0,null,null,0,"span",[["class","help-block"]],null,null,null,null,null))],function(l,n){l(n,8,0,"Show"),l(n,11,0,"Delete")},function(l,n){l(n,4,0,t["\u0275inlineInterpolate"](1,"",n.context.$implicit.user,"")),l(n,7,0,t["\u0275nov"](n,8).ariaDescribedby),l(n,10,0,t["\u0275nov"](n,11).ariaDescribedby)})}function Ue(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["There are no keys."]))],null,null)}function Me(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,10,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,8,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,0,"i",[["class","icon-prepend fa fa-key"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"input",[["class","form-control"],["readonly",""],["type","text"]],[[8,"value",0]],null,null,null,null)),t["\u0275did"](5,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](6,0,null,null,3,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,16777216,null,null,2,"button",[["class","btn btn-default tc_showSwiftKeyButton"],["tooltip","Show"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showSwiftKeyModal(l.context.index)&&e),e},null,null)),t["\u0275did"](8,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-eye"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,0,null,null,0,"span",[["class","help-block"]],null,null,null,null,null))],function(l,n){l(n,8,0,"Show")},function(l,n){l(n,4,0,t["\u0275inlineInterpolate"](1,"",n.context.$implicit.user,"")),l(n,7,0,t["\u0275nov"](n,8).ariaDescribedby)})}function Oe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,24,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Keys"])),(l()(),t["\u0275eld"](3,0,null,null,1,"label",[["class","col-sm-3 control-label"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["S3"])),(l()(),t["\u0275eld"](5,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,Ae)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Be)),t["\u0275did"](9,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275eld"](10,0,null,null,6,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](11,0,null,null,5,"button",[["class","btn btn-sm btn-default btn-label pull-right tc_addS3KeyButton"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showS3KeyModal()&&e),e},null,null)),(l()(),t["\u0275eld"](12,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),t["\u0275eld"](13,0,null,null,3,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](14,null,[""," ",""])),t["\u0275ppd"](15,1),t["\u0275ppd"](16,1),(l()(),t["\u0275eld"](17,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),t["\u0275eld"](18,0,null,null,1,"label",[["class","col-sm-3 control-label"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Swift"])),(l()(),t["\u0275eld"](20,0,null,null,4,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,Ue)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Me)),t["\u0275did"](24,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var u=n.component;l(n,7,0,0===u.s3Keys.length),l(n,9,0,u.s3Keys),l(n,22,0,0===u.swiftKeys.length),l(n,24,0,u.swiftKeys)},function(l,n){var u=n.component,e=t["\u0275unv"](n,14,0,l(n,15,0,t["\u0275nov"](n.parent.parent,0),u.actionLabels.CREATE)),i=t["\u0275unv"](n,14,1,l(n,16,0,t["\u0275nov"](n.parent.parent,1),u.s3keyLabel));l(n,14,0,e,i)})}function Le(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["There are no capabilities."]))],null,null)}function Ge(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,13,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,11,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,0,"i",[["class","icon-prepend fa fa-share-alt"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,"input",[["class","form-control"],["readonly",""],["type","text"]],[[8,"value",0]],null,null,null,null)),t["\u0275did"](5,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),(l()(),t["\u0275eld"](6,0,null,null,6,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,16777216,null,null,2,"button",[["class","btn btn-default tc_editCapButton"],["tooltip","Edit"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showCapabilityModal(l.context.index)&&e),e},null,null)),t["\u0275did"](8,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-cogs"]],null,null,null,null,null)),(l()(),t["\u0275eld"](10,16777216,null,null,2,"button",[["class","btn btn-default tc_deleteCapButton"],["tooltip","Delete"],["type","button"]],[[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.deleteCapability(l.context.index)&&e),e},null,null)),t["\u0275did"](11,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"]},null),(l()(),t["\u0275eld"](12,0,null,null,0,"i",[["class","fa fa-times"]],null,null,null,null,null)),(l()(),t["\u0275eld"](13,0,null,null,0,"span",[["class","help-block"]],null,null,null,null,null))],function(l,n){l(n,8,0,"Edit"),l(n,11,0,"Delete")},function(l,n){l(n,4,0,t["\u0275inlineInterpolate"](2,"",n.context.$implicit.type,":",n.context.$implicit.perm,"")),l(n,7,0,t["\u0275nov"](n,8).ariaDescribedby),l(n,10,0,t["\u0275nov"](n,11).ariaDescribedby)})}function Ke(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,15,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Capabilities"])),(l()(),t["\u0275eld"](3,0,null,null,12,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,Le)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ge)),t["\u0275did"](7,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275eld"](8,0,null,null,7,"span",[["class","form-control no-border"]],null,null,null,null,null)),(l()(),t["\u0275eld"](9,16777216,null,null,6,"button",[["class","btn btn-sm btn-default btn-label pull-right tc_addCapButton"],["tooltip","All capabilities are already added."],["triggers","pointerenter pointerleave"],["type","button"]],[[8,"disabled",0],[1,"aria-describedby",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.showCapabilityModal()&&e),e},null,null)),t["\u0275did"](10,212992,null,0,Ou.c,[t.ViewContainerRef,Jl.a,Ou.a,t.ElementRef,t.Renderer2,Mu.a],{tooltip:[0,"tooltip"],triggers:[1,"triggers"],isDisabled:[2,"isDisabled"]},null),(l()(),t["\u0275eld"](11,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),t["\u0275eld"](12,0,null,null,3,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](13,null,[""," ",""])),t["\u0275ppd"](14,1),t["\u0275ppd"](15,1)],function(l,n){var u=n.component;l(n,5,0,0===u.capabilities.length),l(n,7,0,u.capabilities),l(n,10,0,"All capabilities are already added.","pointerenter pointerleave",!u.hasAllCapabilities())},function(l,n){var u=n.component;l(n,9,0,u.hasAllCapabilities(),t["\u0275nov"](n,10).ariaDescribedby);var e=t["\u0275unv"](n,13,0,l(n,14,0,t["\u0275nov"](n.parent.parent,0),u.actionLabels.ADD)),i=t["\u0275unv"](n,13,1,l(n,15,0,t["\u0275nov"](n.parent.parent,1),u.capabilityLabel));l(n,13,0,e,i)})}function $e(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,6,"input",[["formControlName","user_quota_max_size_unlimited"],["id","user_quota_max_size_unlimited"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,5).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,5).onTouched()&&e),e},null,null)),t["\u0275did"](4,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](5,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](7,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](9,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](10,0,null,null,1,"label",[["for","user_quota_max_size_unlimited"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited size"]))],function(l,n){l(n,7,0,"user_quota_max_size_unlimited")},function(l,n){l(n,3,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function Ze(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Qe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The value is not valid."]))],null,null)}function He(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","user_quota_max_size"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Max. size"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,7,"input",[["cdDimlessBinary",""],["class","form-control"],["formControlName","user_quota_max_size"],["id","user_quota_max_size"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,9)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,9).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,9)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,9)._compositionEnd(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,13).onBlur(u.target.value)&&e),e},null,null)),t["\u0275did"](9,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](11,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](13,81920,null,0,ve.a,[t.ElementRef,d.q,q.a,U.a],null,null),t["\u0275did"](14,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ze)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Qe)),t["\u0275did"](19,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("user_quota_max_size",t["\u0275nov"](n.parent,3)));l(n,1,0,"form-group",e),l(n,11,0,"user_quota_max_size"),l(n,13,0),l(n,17,0,u.userForm.showError("user_quota_max_size",t["\u0275nov"](n.parent,3),"required")),l(n,19,0,u.userForm.showError("user_quota_max_size",t["\u0275nov"](n.parent,3),"quotaMaxSize"))},function(l,n){l(n,8,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function Ye(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,6,"input",[["formControlName","user_quota_max_objects_unlimited"],["id","user_quota_max_objects_unlimited"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,5).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,5).onTouched()&&e),e},null,null)),t["\u0275did"](4,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](5,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](7,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](9,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](10,0,null,null,1,"label",[["for","user_quota_max_objects_unlimited"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited objects"]))],function(l,n){l(n,7,0,"user_quota_max_objects_unlimited")},function(l,n){l(n,3,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function Xe(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Je(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The entered value must be >= 0."]))],null,null)}function We(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","user_quota_max_objects"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Max. objects"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,7,"input",[["class","form-control"],["formControlName","user_quota_max_objects"],["id","user_quota_max_objects"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,10)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,10).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,10)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,10)._compositionEnd(u.target.value)&&e),"change"===n&&(e=!1!==t["\u0275nov"](l,11).onChange(u.target.value)&&e),"input"===n&&(e=!1!==t["\u0275nov"](l,11).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,11).onTouched()&&e),e},null,null)),t["\u0275did"](9,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](10,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275did"](11,16384,null,0,d.C,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l,n){return[l,n]},[d.e,d.C]),t["\u0275did"](13,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,Xe)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Je)),t["\u0275did"](19,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("user_quota_max_objects",t["\u0275nov"](n.parent,3)));l(n,1,0,"form-group",e),l(n,13,0,"user_quota_max_objects"),l(n,17,0,u.userForm.showError("user_quota_max_objects",t["\u0275nov"](n.parent,3),"required")),l(n,19,0,u.userForm.showError("user_quota_max_objects",t["\u0275nov"](n.parent,3),"min"))},function(l,n){l(n,8,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function lt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,6,"input",[["formControlName","bucket_quota_max_size_unlimited"],["id","bucket_quota_max_size_unlimited"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,5).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,5).onTouched()&&e),e},null,null)),t["\u0275did"](4,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](5,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](7,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](9,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](10,0,null,null,1,"label",[["for","bucket_quota_max_size_unlimited"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited size"]))],function(l,n){l(n,7,0,"bucket_quota_max_size_unlimited")},function(l,n){l(n,3,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function nt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function ut(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The value is not valid."]))],null,null)}function et(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","bucket_quota_max_size"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Max. size"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,7,"input",[["cdDimlessBinary",""],["class","form-control"],["formControlName","bucket_quota_max_size"],["id","bucket_quota_max_size"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,9)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,9).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,9)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,9)._compositionEnd(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,13).onBlur(u.target.value)&&e),e},null,null)),t["\u0275did"](9,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](11,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](13,81920,null,0,ve.a,[t.ElementRef,d.q,q.a,U.a],null,null),t["\u0275did"](14,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,nt)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ut)),t["\u0275did"](19,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("bucket_quota_max_size",t["\u0275nov"](n.parent,3)));l(n,1,0,"form-group",e),l(n,11,0,"bucket_quota_max_size"),l(n,13,0),l(n,17,0,u.userForm.showError("bucket_quota_max_size",t["\u0275nov"](n.parent,3),"required")),l(n,19,0,u.userForm.showError("bucket_quota_max_size",t["\u0275nov"](n.parent,3),"quotaMaxSize"))},function(l,n){l(n,8,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function tt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](3,0,null,null,6,"input",[["formControlName","bucket_quota_max_objects_unlimited"],["id","bucket_quota_max_objects_unlimited"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,5).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,5).onTouched()&&e),e},null,null)),t["\u0275did"](4,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](5,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](7,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](9,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](10,0,null,null,1,"label",[["for","bucket_quota_max_objects_unlimited"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Unlimited objects"]))],function(l,n){l(n,7,0,"bucket_quota_max_objects_unlimited")},function(l,n){l(n,3,0,t["\u0275nov"](n,9).ngClassUntouched,t["\u0275nov"](n,9).ngClassTouched,t["\u0275nov"](n,9).ngClassPristine,t["\u0275nov"](n,9).ngClassDirty,t["\u0275nov"](n,9).ngClassValid,t["\u0275nov"](n,9).ngClassInvalid,t["\u0275nov"](n,9).ngClassPending)})}function it(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function ot(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The entered value must be >= 0."]))],null,null)}function at(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](1,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](2,{"has-error":0}),(l()(),t["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","bucket_quota_max_objects"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Max. objects"])),(l()(),t["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,7,"input",[["class","form-control"],["formControlName","bucket_quota_max_objects"],["id","bucket_quota_max_objects"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,10)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,10).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,10)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,10)._compositionEnd(u.target.value)&&e),"change"===n&&(e=!1!==t["\u0275nov"](l,11).onChange(u.target.value)&&e),"input"===n&&(e=!1!==t["\u0275nov"](l,11).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,11).onTouched()&&e),e},null,null)),t["\u0275did"](9,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](10,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275did"](11,16384,null,0,d.C,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l,n){return[l,n]},[d.e,d.C]),t["\u0275did"](13,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](15,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,it)),t["\u0275did"](17,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ot)),t["\u0275did"](19,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,e=l(n,2,0,u.userForm.showError("bucket_quota_max_objects",t["\u0275nov"](n.parent,3)));l(n,1,0,"form-group",e),l(n,13,0,"bucket_quota_max_objects"),l(n,17,0,u.userForm.showError("bucket_quota_max_objects",t["\u0275nov"](n.parent,3),"required")),l(n,19,0,u.userForm.showError("bucket_quota_max_objects",t["\u0275nov"](n.parent,3),"min"))},function(l,n){l(n,8,0,t["\u0275nov"](n,15).ngClassUntouched,t["\u0275nov"](n,15).ngClassTouched,t["\u0275nov"](n,15).ngClassPristine,t["\u0275nov"](n,15).ngClassDirty,t["\u0275nov"](n,15).ngClassValid,t["\u0275nov"](n,15).ngClassInvalid,t["\u0275nov"](n,15).ngClassPending)})}function rt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,168,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,167,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,3).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,3).onReset()&&e),e},null,null)),t["\u0275did"](2,16384,null,0,d.D,[],null,null),t["\u0275did"](3,540672,[["frm",4]],0,d.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,d.d,null,[d.l]),t["\u0275did"](5,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](6,0,null,null,162,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),t["\u0275ted"](9,null,[""," ",""])),t["\u0275ppd"](10,1),t["\u0275ppd"](11,1),(l()(),t["\u0275eld"](12,0,null,null,147,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),t["\u0275eld"](13,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](14,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](15,{"has-error":0}),(l()(),t["\u0275eld"](16,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","uid"]],null,null,null,null,null)),(l()(),t["\u0275eld"](17,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Username"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Ce)),t["\u0275did"](20,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](21,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](22,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","uid"],["id","uid"],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,25)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,25).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,25)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,25)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](23,4210688,null,0,zn.a,[t.ElementRef],null,null),t["\u0275did"](24,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](25,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](27,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](29,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,_e)),t["\u0275did"](31,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ke)),t["\u0275did"](33,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](34,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](35,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](36,{"has-error":0}),(l()(),t["\u0275eld"](37,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","display_name"]],null,null,null,null,null)),(l()(),t["\u0275eld"](38,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Full name"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Re)),t["\u0275did"](41,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](42,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](43,0,null,null,6,"input",[["class","form-control"],["formControlName","display_name"],["id","display_name"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,45)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,45).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,45)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,45)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](44,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](45,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](47,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](49,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ie)),t["\u0275did"](51,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](52,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](53,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](54,{"has-error":0}),(l()(),t["\u0275eld"](55,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","email"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Email address"])),(l()(),t["\u0275eld"](57,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](58,0,null,null,6,"input",[["class","form-control"],["formControlName","email"],["id","email"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,60)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,60).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,60)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,60)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](59,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](60,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](62,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](64,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,we)),t["\u0275did"](66,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ee)),t["\u0275did"](68,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](69,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](70,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","max_buckets_mode"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Max. buckets"])),(l()(),t["\u0275eld"](72,0,null,null,19,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](73,0,null,null,18,"select",[["class","form-control"],["formControlName","max_buckets_mode"],["id","max_buckets_mode"],["name","max_buckets_mode"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0,i=l.component;return"change"===n&&(e=!1!==t["\u0275nov"](l,75).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,75).onTouched()&&e),"change"===n&&(e=!1!==i.onMaxBucketsModeChange(u.target.value)&&e),e},null,null)),t["\u0275did"](74,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](75,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](77,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](79,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](80,0,null,null,3,"option",[["value","-1"]],null,null,null,null,null)),t["\u0275did"](81,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](82,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["Disabled"])),(l()(),t["\u0275eld"](84,0,null,null,3,"option",[["value","0"]],null,null,null,null,null)),t["\u0275did"](85,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](86,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["Unlimited"])),(l()(),t["\u0275eld"](88,0,null,null,3,"option",[["value","1"]],null,null,null,null,null)),t["\u0275did"](89,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](90,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](-1,null,["Custom"])),(l()(),t["\u0275and"](16777216,null,null,1,null,qe)),t["\u0275did"](93,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](94,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](95,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](96,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](97,0,null,null,6,"input",[["formControlName","suspended"],["id","suspended"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,99).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,99).onTouched()&&e),e},null,null)),t["\u0275did"](98,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](99,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](101,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](103,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](104,0,null,null,1,"label",[["for","suspended"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Suspended"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Fe)),t["\u0275did"](107,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ze)),t["\u0275did"](109,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Oe)),t["\u0275did"](111,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ke)),t["\u0275did"](113,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](114,0,null,null,22,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](115,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["User quota"])),(l()(),t["\u0275eld"](117,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](118,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](119,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](120,0,null,null,6,"input",[["formControlName","user_quota_enabled"],["id","user_quota_enabled"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,122).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,122).onTouched()&&e),e},null,null)),t["\u0275did"](121,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](122,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](124,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](126,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](127,0,null,null,1,"label",[["for","user_quota_enabled"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Enabled"])),(l()(),t["\u0275and"](16777216,null,null,1,null,$e)),t["\u0275did"](130,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,He)),t["\u0275did"](132,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ye)),t["\u0275did"](134,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,We)),t["\u0275did"](136,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](137,0,null,null,22,"fieldset",[],null,null,null,null,null)),(l()(),t["\u0275eld"](138,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Bucket quota"])),(l()(),t["\u0275eld"](140,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](141,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](142,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),t["\u0275eld"](143,0,null,null,6,"input",[["formControlName","bucket_quota_enabled"],["id","bucket_quota_enabled"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,145).onChange(u.target.checked)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,145).onTouched()&&e),e},null,null)),t["\u0275did"](144,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](145,16384,null,0,d.c,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.c]),t["\u0275did"](147,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](149,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275eld"](150,0,null,null,1,"label",[["for","bucket_quota_enabled"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Enabled"])),(l()(),t["\u0275and"](16777216,null,null,1,null,lt)),t["\u0275did"](153,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,et)),t["\u0275did"](155,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,tt)),t["\u0275did"](157,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,at)),t["\u0275did"](159,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](160,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](161,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](162,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.onSubmit()&&e),e},An.b,An.a)),t["\u0275did"](163,114688,null,0,Bn.a,[t.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](164,0,[""," ",""])),t["\u0275ppd"](165,1),t["\u0275ppd"](166,1),(l()(),t["\u0275eld"](167,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](168,49152,null,0,Dn.a,[ql.Location,i.b],null,null)],function(l,n){var u=n.component;l(n,3,0,u.userForm);var e=l(n,15,0,u.userForm.showError("uid",t["\u0275nov"](n,3)));l(n,14,0,"form-group",e),l(n,20,0,!u.editing),l(n,27,0,"uid"),l(n,31,0,u.userForm.showError("uid",t["\u0275nov"](n,3),"required")),l(n,33,0,u.userForm.showError("uid",t["\u0275nov"](n,3),"notUnique"));var i=l(n,36,0,u.userForm.showError("display_name",t["\u0275nov"](n,3)));l(n,35,0,"form-group",i),l(n,41,0,!u.editing),l(n,47,0,"display_name"),l(n,51,0,u.userForm.showError("display_name",t["\u0275nov"](n,3),"required"));var o=l(n,54,0,u.userForm.showError("email",t["\u0275nov"](n,3)));l(n,53,0,"form-group",o),l(n,62,0,"email"),l(n,66,0,u.userForm.showError("email",t["\u0275nov"](n,3),"email")),l(n,68,0,u.userForm.showError("email",t["\u0275nov"](n,3),"notUnique")),l(n,77,0,"max_buckets_mode"),l(n,81,0,"-1"),l(n,82,0,"-1"),l(n,85,0,"0"),l(n,86,0,"0"),l(n,89,0,"1"),l(n,90,0,"1"),l(n,93,0,1==u.userForm.get("max_buckets_mode").value),l(n,101,0,"suspended"),l(n,107,0,!u.editing),l(n,109,0,u.editing),l(n,111,0,u.editing),l(n,113,0,u.editing),l(n,124,0,"user_quota_enabled"),l(n,130,0,u.userForm.controls.user_quota_enabled.value),l(n,132,0,!u.userForm.getValue("user_quota_max_size_unlimited")),l(n,134,0,u.userForm.controls.user_quota_enabled.value),l(n,136,0,!u.userForm.getValue("user_quota_max_objects_unlimited")),l(n,147,0,"bucket_quota_enabled"),l(n,153,0,u.userForm.controls.bucket_quota_enabled.value),l(n,155,0,!u.userForm.getValue("bucket_quota_max_size_unlimited")),l(n,157,0,u.userForm.controls.bucket_quota_enabled.value),l(n,159,0,!u.userForm.getValue("bucket_quota_max_objects_unlimited")),l(n,163,0,u.userForm,"button")},function(l,n){var u=n.component;l(n,1,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending);var e=t["\u0275unv"](n,9,0,l(n,10,0,t["\u0275nov"](n.parent,0),u.action)),i=t["\u0275unv"](n,9,1,l(n,11,0,t["\u0275nov"](n.parent,1),u.resource));l(n,9,0,e,i),l(n,22,0,u.editing,t["\u0275nov"](n,29).ngClassUntouched,t["\u0275nov"](n,29).ngClassTouched,t["\u0275nov"](n,29).ngClassPristine,t["\u0275nov"](n,29).ngClassDirty,t["\u0275nov"](n,29).ngClassValid,t["\u0275nov"](n,29).ngClassInvalid,t["\u0275nov"](n,29).ngClassPending),l(n,43,0,t["\u0275nov"](n,49).ngClassUntouched,t["\u0275nov"](n,49).ngClassTouched,t["\u0275nov"](n,49).ngClassPristine,t["\u0275nov"](n,49).ngClassDirty,t["\u0275nov"](n,49).ngClassValid,t["\u0275nov"](n,49).ngClassInvalid,t["\u0275nov"](n,49).ngClassPending),l(n,58,0,t["\u0275nov"](n,64).ngClassUntouched,t["\u0275nov"](n,64).ngClassTouched,t["\u0275nov"](n,64).ngClassPristine,t["\u0275nov"](n,64).ngClassDirty,t["\u0275nov"](n,64).ngClassValid,t["\u0275nov"](n,64).ngClassInvalid,t["\u0275nov"](n,64).ngClassPending),l(n,73,0,t["\u0275nov"](n,79).ngClassUntouched,t["\u0275nov"](n,79).ngClassTouched,t["\u0275nov"](n,79).ngClassPristine,t["\u0275nov"](n,79).ngClassDirty,t["\u0275nov"](n,79).ngClassValid,t["\u0275nov"](n,79).ngClassInvalid,t["\u0275nov"](n,79).ngClassPending),l(n,97,0,t["\u0275nov"](n,103).ngClassUntouched,t["\u0275nov"](n,103).ngClassTouched,t["\u0275nov"](n,103).ngClassPristine,t["\u0275nov"](n,103).ngClassDirty,t["\u0275nov"](n,103).ngClassValid,t["\u0275nov"](n,103).ngClassInvalid,t["\u0275nov"](n,103).ngClassPending),l(n,120,0,t["\u0275nov"](n,126).ngClassUntouched,t["\u0275nov"](n,126).ngClassTouched,t["\u0275nov"](n,126).ngClassPristine,t["\u0275nov"](n,126).ngClassDirty,t["\u0275nov"](n,126).ngClassValid,t["\u0275nov"](n,126).ngClassInvalid,t["\u0275nov"](n,126).ngClassPending),l(n,143,0,t["\u0275nov"](n,149).ngClassUntouched,t["\u0275nov"](n,149).ngClassTouched,t["\u0275nov"](n,149).ngClassPristine,t["\u0275nov"](n,149).ngClassDirty,t["\u0275nov"](n,149).ngClassValid,t["\u0275nov"](n,149).ngClassInvalid,t["\u0275nov"](n,149).ngClassPending);var o=t["\u0275unv"](n,164,0,l(n,165,0,t["\u0275nov"](n.parent,0),u.action)),a=t["\u0275unv"](n,164,1,l(n,166,0,t["\u0275nov"](n.parent,1),u.resource));l(n,164,0,o,a)})}function st(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275and"](16777216,null,null,1,null,he)),t["\u0275did"](3,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,ye)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,rt)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,u.editing&&u.loading&&!u.error),l(n,5,0,u.editing&&u.error),l(n,7,0,!u.loading&&!u.error)},null)}function dt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-user-form",[],null,null,null,st,be)),t["\u0275did"](1,114688,null,0,Z,[_.a,$u.a,$u.l,y.a,nn.b,k.a,_l.a,i.b],null,null)],function(l,n){l(n,1,0)},null)}var ct=t["\u0275ccf"]("cd-rgw-user-form",Z,dt,{},{},[]),pt=u("xSw7"),ft=u("GgAd"),mt=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function gt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-usage-bar",[],null,null,null,pt.b,pt.a)),t["\u0275did"](1,573440,null,0,ft.a,[],{total:[0,"total"],used:[1,"used"]},null)],function(l,n){l(n,1,0,n.parent.context.row.bucket_quota.max_size,n.parent.context.row.bucket_size)},null)}function vt(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["No Limit"]))],null,null)}function bt(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,gt)),t["\u0275did"](1,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(l()(),t["\u0275and"](0,[["noSizeQuota",2]],null,0,null,vt))],function(l,n){l(n,1,0,n.context.row.bucket_quota.max_size>0&&n.context.row.bucket_quota.enabled,t["\u0275nov"](n,2))},null)}function ht(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-usage-bar",[],null,null,null,pt.b,pt.a)),t["\u0275did"](1,573440,null,0,ft.a,[],{total:[0,"total"],used:[1,"used"],isBinary:[2,"isBinary"]},null)],function(l,n){l(n,1,0,n.parent.context.row.bucket_quota.max_objects,n.parent.context.row.num_objects,!1)},null)}function yt(l){return t["\u0275vid"](0,[(l()(),t["\u0275ted"](-1,null,["No Limit"]))],null,null)}function Ct(l){return t["\u0275vid"](0,[(l()(),t["\u0275and"](16777216,null,null,1,null,ht)),t["\u0275did"](1,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(l()(),t["\u0275and"](0,[["noObjectQuota",2]],null,0,null,yt))],function(l,n){l(n,1,0,n.context.row.bucket_quota.max_objects>0&&n.context.row.bucket_quota.enabled,t["\u0275nov"](n,2))},null)}function _t(l){return t["\u0275vid"](0,[t["\u0275qud"](402653184,1,{table:0}),t["\u0275qud"](402653184,2,{bucketSizeTpl:0}),t["\u0275qud"](402653184,3,{bucketObjectTpl:0}),(l()(),t["\u0275eld"](3,0,null,null,5,"cd-table",[["columnMode","flex"],["identifier","bid"],["selectionType","multi"]],null,[[null,"updateSelection"],[null,"fetchData"]],function(l,n,u){var e=!0,t=l.component;return"updateSelection"===n&&(e=!1!==t.updateSelection(u)&&e),"fetchData"===n&&(e=!1!==t.getBucketList(u)&&e),e},Yl.b,Yl.a)),t["\u0275did"](4,2867200,[[1,4],["table",4]],0,x.a,[t.NgZone,t.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"],identifier:[4,"identifier"],selectionType:[5,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),t["\u0275eld"](5,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,oe.b,oe.a)),t["\u0275did"](6,114688,null,0,ae.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),t["\u0275eld"](7,0,null,2,1,"cd-rgw-bucket-details",[["cdTableDetail",""]],null,null,null,Zl,Bl)),t["\u0275did"](8,573440,null,0,Al,[],{selection:[0,"selection"]},null),(l()(),t["\u0275and"](0,[[2,2],["bucketSizeTpl",2]],null,0,null,bt)),(l()(),t["\u0275and"](0,[[3,2],["bucketObjectTpl",2]],null,0,null,Ct))],function(l,n){var u=n.component;l(n,4,0,u.buckets,u.columns,"flex",!1,"bid","multi"),l(n,6,0,u.permission,u.selection,u.tableActions),l(n,8,0,u.selection)},null)}function kt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-rgw-bucket-list",[],null,null,null,_t,mt)),t["\u0275prd"](256,null,D.a,N,[]),t["\u0275did"](2,114688,null,0,F,[S.a,q.a,V.a,h,nn.b,_l.a,D.a,i.b,t.ChangeDetectorRef],null,null)],function(l,n){l(n,2,0)},null)}var Rt=t["\u0275ccf"]("cd-rgw-bucket-list",F,kt,{},{},[]),It=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function wt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-loading-panel",[],null,null,null,pe.b,pe.a)),t["\u0275did"](1,49152,null,0,fe.a,[],null,null),(l()(),t["\u0275ted"](-1,0,["Loading bucket data..."]))],null,null)}function Et(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,2,"cd-error-panel",[],null,[[null,"backAction"]],function(l,n,u){var e=!0;return"backAction"===n&&(e=!1!==l.component.goToListView()&&e),e},me.b,me.a)),t["\u0275did"](1,49152,null,0,ge.a,[],null,{backAction:"backAction"}),(l()(),t["\u0275ted"](-1,0,["The bucket data could not be loaded."]))],null,null)}function xt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","id"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Id"])),(l()(),t["\u0275eld"](3,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,null,6,"input",[["class","form-control"],["formControlName","id"],["id","id"],["name","id"],["readonly",""],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,6)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,6).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,6)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,6)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](5,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](6,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](8,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](10,16384,null,0,d.r,[[4,d.q]],null,null)],function(l,n){l(n,8,0,"id")},function(l,n){l(n,4,0,t["\u0275nov"](n,10).ngClassUntouched,t["\u0275nov"](n,10).ngClassTouched,t["\u0275nov"](n,10).ngClassPristine,t["\u0275nov"](n,10).ngClassDirty,t["\u0275nov"](n,10).ngClassValid,t["\u0275nov"](n,10).ngClassInvalid,t["\u0275nov"](n,10).ngClassPending)})}function Tt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function qt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Vt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The value is not valid."]))],null,null)}function St(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["The chosen name is already in use."]))],null,null)}function Dt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Nt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{ngValue:[0,"ngValue"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),t["\u0275ted"](-1,null,["-- Select a user --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Ft(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),t["\u0275did"](1,147456,null,0,d.v,[t.ElementRef,t.Renderer2,[2,d.z]],{value:[0,"value"]},null),t["\u0275did"](2,147456,null,0,d.G,[t.ElementRef,t.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),t["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function jt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Pt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,69,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,68,"form",[["class","form-horizontal"],["name","bucketForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var e=!0;return"submit"===n&&(e=!1!==t["\u0275nov"](l,3).onSubmit(u)&&e),"reset"===n&&(e=!1!==t["\u0275nov"](l,3).onReset()&&e),e},null,null)),t["\u0275did"](2,16384,null,0,d.D,[],null,null),t["\u0275did"](3,540672,[["frm",4]],0,d.l,[[8,null],[8,null]],{form:[0,"form"]},null),t["\u0275prd"](2048,null,d.d,null,[d.l]),t["\u0275did"](5,16384,null,0,d.s,[[4,d.d]],null,null),(l()(),t["\u0275eld"](6,0,null,null,63,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),t["\u0275eld"](7,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),t["\u0275eld"](8,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),t["\u0275ted"](9,null,[""," ",""])),t["\u0275ppd"](10,1),t["\u0275ppd"](11,1),(l()(),t["\u0275eld"](12,0,null,null,48,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,xt)),t["\u0275did"](14,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](15,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](16,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](17,{"has-error":0}),(l()(),t["\u0275eld"](18,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","bid"]],null,null,null,null,null)),(l()(),t["\u0275eld"](19,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Name"])),(l()(),t["\u0275and"](16777216,null,null,1,null,Tt)),t["\u0275did"](22,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](23,0,null,null,14,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](24,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","bid"],["id","bid"],["name","bid"],["placeholder","Name..."],["type","text"]],[[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var e=!0;return"input"===n&&(e=!1!==t["\u0275nov"](l,27)._handleInput(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,27).onTouched()&&e),"compositionstart"===n&&(e=!1!==t["\u0275nov"](l,27)._compositionStart()&&e),"compositionend"===n&&(e=!1!==t["\u0275nov"](l,27)._compositionEnd(u.target.value)&&e),e},null,null)),t["\u0275did"](25,4210688,null,0,zn.a,[t.ElementRef],null,null),t["\u0275did"](26,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](27,16384,null,0,d.e,[t.Renderer2,t.ElementRef,[2,d.b]],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.e]),t["\u0275did"](29,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](31,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,qt)),t["\u0275did"](33,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Vt)),t["\u0275did"](35,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,St)),t["\u0275did"](37,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](38,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),t["\u0275did"](39,278528,null,0,ql.NgClass,[t.IterableDiffers,t.KeyValueDiffers,t.ElementRef,t.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),t["\u0275pod"](40,{"has-error":0}),(l()(),t["\u0275eld"](41,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","owner"]],null,null,null,null,null)),(l()(),t["\u0275eld"](42,0,null,null,1,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Owner"])),(l()(),t["\u0275eld"](44,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),t["\u0275eld"](45,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),t["\u0275eld"](46,0,null,null,12,"select",[["class","form-control"],["formControlName","owner"],["id","owner"],["name","owner"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==t["\u0275nov"](l,48).onChange(u.target.value)&&e),"blur"===n&&(e=!1!==t["\u0275nov"](l,48).onTouched()&&e),e},null,null)),t["\u0275did"](47,4210688,null,0,En.a,[[2,xn.a],S.a,t.ElementRef],null,null),t["\u0275did"](48,16384,null,0,d.z,[t.Renderer2,t.ElementRef],null,null),t["\u0275prd"](1024,null,d.p,function(l){return[l]},[d.z]),t["\u0275did"](50,671744,null,0,d.j,[[3,d.d],[8,null],[8,null],[6,d.p],[2,d.F]],{name:[0,"name"]},null),t["\u0275prd"](2048,null,d.q,null,[d.j]),t["\u0275did"](52,16384,null,0,d.r,[[4,d.q]],null,null),(l()(),t["\u0275and"](16777216,null,null,1,null,Dt)),t["\u0275did"](54,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Nt)),t["\u0275did"](56,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Ft)),t["\u0275did"](58,278528,null,0,ql.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,jt)),t["\u0275did"](60,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275eld"](61,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),t["\u0275eld"](62,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),t["\u0275eld"](63,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.submit()&&e),e},An.b,An.a)),t["\u0275did"](64,114688,null,0,Bn.a,[t.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),t["\u0275ted"](65,0,[""," ",""])),t["\u0275ppd"](66,1),t["\u0275ppd"](67,1),(l()(),t["\u0275eld"](68,0,null,null,1,"cd-back-button",[],null,null,null,Sn.b,Sn.a)),t["\u0275did"](69,49152,null,0,Dn.a,[ql.Location,i.b],null,null)],function(l,n){var u=n.component;l(n,3,0,u.bucketForm),l(n,14,0,u.editing);var e=l(n,17,0,u.bucketForm.showError("bid",t["\u0275nov"](n,3)));l(n,16,0,"form-group",e),l(n,22,0,!u.editing),l(n,29,0,"bid"),l(n,33,0,u.bucketForm.showError("bid",t["\u0275nov"](n,3),"required")),l(n,35,0,u.bucketForm.showError("bid",t["\u0275nov"](n,3),"bucketNameInvalid")),l(n,37,0,u.bucketForm.showError("bid",t["\u0275nov"](n,3),"bucketNameExists"));var i=l(n,40,0,u.bucketForm.showError("owner",t["\u0275nov"](n,3)));l(n,39,0,"form-group",i),l(n,50,0,"owner"),l(n,54,0,null===u.owners),l(n,56,0,null!==u.owners),l(n,58,0,u.owners),l(n,60,0,u.bucketForm.showError("owner",t["\u0275nov"](n,3),"required")),l(n,64,0,u.bucketForm,"button")},function(l,n){var u=n.component;l(n,1,0,t["\u0275nov"](n,5).ngClassUntouched,t["\u0275nov"](n,5).ngClassTouched,t["\u0275nov"](n,5).ngClassPristine,t["\u0275nov"](n,5).ngClassDirty,t["\u0275nov"](n,5).ngClassValid,t["\u0275nov"](n,5).ngClassInvalid,t["\u0275nov"](n,5).ngClassPending);var e=t["\u0275unv"](n,9,0,l(n,10,0,t["\u0275nov"](n.parent,0),u.action)),i=t["\u0275unv"](n,9,1,l(n,11,0,t["\u0275nov"](n.parent,1),u.resource));l(n,9,0,e,i),l(n,24,0,u.editing,t["\u0275nov"](n,31).ngClassUntouched,t["\u0275nov"](n,31).ngClassTouched,t["\u0275nov"](n,31).ngClassPristine,t["\u0275nov"](n,31).ngClassDirty,t["\u0275nov"](n,31).ngClassValid,t["\u0275nov"](n,31).ngClassInvalid,t["\u0275nov"](n,31).ngClassPending),l(n,46,0,t["\u0275nov"](n,52).ngClassUntouched,t["\u0275nov"](n,52).ngClassTouched,t["\u0275nov"](n,52).ngClassPristine,t["\u0275nov"](n,52).ngClassDirty,t["\u0275nov"](n,52).ngClassValid,t["\u0275nov"](n,52).ngClassInvalid,t["\u0275nov"](n,52).ngClassPending);var o=t["\u0275unv"](n,65,0,l(n,66,0,t["\u0275nov"](n.parent,0),u.action)),a=t["\u0275unv"](n,65,1,l(n,67,0,t["\u0275nov"](n.parent,1),u.resource));l(n,65,0,o,a)})}function zt(l){return t["\u0275vid"](0,[t["\u0275pid"](0,ql.TitleCasePipe,[]),t["\u0275pid"](0,wn.a,[]),(l()(),t["\u0275and"](16777216,null,null,1,null,wt)),t["\u0275did"](3,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Et)),t["\u0275did"](5,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),t["\u0275and"](16777216,null,null,1,null,Pt)),t["\u0275did"](7,16384,null,0,ql.NgIf,[t.ViewContainerRef,t.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,3,0,u.editing&&u.loading&&!u.error),l(n,5,0,u.editing&&u.error),l(n,7,0,!u.loading&&!u.error)},null)}function At(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-bucket-form",[],null,null,null,zt,It)),t["\u0275did"](1,114688,null,0,R,[$u.a,$u.l,_.a,h,y.a,k.a,_l.a,i.b],null,null)],function(l,n){l(n,1,0)},null)}var Bt=t["\u0275ccf"]("cd-rgw-bucket-form",R,At,{},{},[]),Ut=u("TZo1"),Mt=u("9Kw/"),Ot=t["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Lt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,8,"cd-info-panel",[],null,null,null,Ut.b,Ut.a)),t["\u0275did"](1,49152,null,0,Mt.a,[_l.a],null,null),(l()(),t["\u0275ted"](2,0,[" ",""])),(l()(),t["\u0275eld"](3,0,null,0,0,"br",[],null,null,null,null,null)),(l()(),t["\u0275eld"](4,0,null,0,4,null,null,null,null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["Please consult the "])),(l()(),t["\u0275eld"](6,0,null,null,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(l()(),t["\u0275ted"](-1,null,["documentation"])),(l()(),t["\u0275ted"](-1,null,[" on how to configure and enable the Object Gateway management functionality."]))],null,function(l,n){var u=n.component;l(n,2,0,u.message),l(n,6,0,t["\u0275inlineInterpolate"](1,"",u.docsUrl,""))})}function Gt(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,1,"cd-rgw-501",[],null,null,null,Lt,Ot)),t["\u0275did"](1,245760,null,0,s,[$u.a,r.a,a.a],null,null)],function(l,n){l(n,1,0)},null)}var Kt=t["\u0275ccf"]("cd-rgw-501",s,Gt,{},{},[]);u.d(n,"RgwModuleNgFactory",function(){return $t}),u.d(n,"RoutedRgwModuleNgFactory",function(){return Zt});var $t=t["\u0275cmf"](X,[],function(l){return t["\u0275mod"]([t["\u0275mpd"](512,t.ComponentFactoryResolver,t["\u0275CodegenComponentFactoryResolver"],[[8,[al.a,rl.a,sl.a,dl.a,dl.b,cl.a,pl.a,fl.a,ml.a,gl.a,Pl,Hl,In,Pn,eu,gu,xu]],[3,t.ComponentFactoryResolver],t.NgModuleRef]),t["\u0275mpd"](4608,ql.NgLocalization,ql.NgLocaleLocalization,[t.LOCALE_ID,[2,ql["\u0275angular_packages_common_common_a"]]]),t["\u0275mpd"](4608,zl.a,zl.a,[_l.a]),t["\u0275mpd"](4608,ql.DatePipe,ql.DatePipe,[t.LOCALE_ID]),t["\u0275mpd"](4608,P.a,P.a,[]),t["\u0275mpd"](4608,a.a,a.a,[]),t["\u0275mpd"](4608,U.a,U.a,[]),t["\u0275mpd"](4608,q.a,q.a,[U.a]),t["\u0275mpd"](4608,Tu.a,Tu.a,[U.a]),t["\u0275mpd"](4608,V.a,V.a,[U.a]),t["\u0275mpd"](4608,qu.a,qu.a,[]),t["\u0275mpd"](4608,Vu.a,Vu.a,[]),t["\u0275mpd"](4608,Su.a,Su.a,[]),t["\u0275mpd"](4608,Du.a,Du.a,[]),t["\u0275mpd"](4608,wl.a,wl.a,[ql.DatePipe]),t["\u0275mpd"](4608,Nu.a,Nu.a,[]),t["\u0275mpd"](4608,Fu.a,Fu.a,[]),t["\u0275mpd"](4608,ju.a,ju.a,[]),t["\u0275mpd"](4608,Pu.a,Pu.a,[]),t["\u0275mpd"](4608,zu.a,zu.a,[]),t["\u0275mpd"](4608,Au.a,Au.a,[_l.a]),t["\u0275mpd"](4608,wn.a,wn.a,[]),t["\u0275mpd"](4608,Wl.a,Wl.a,[]),t["\u0275mpd"](4608,d.E,d.E,[]),t["\u0275mpd"](4608,d.h,d.h,[]),t["\u0275mpd"](4608,Bu.b,Bu.b,[]),t["\u0275mpd"](4608,Uu.a,Uu.a,[]),t["\u0275mpd"](4608,Mu.a,Mu.a,[t.RendererFactory2,t.PLATFORM_ID]),t["\u0275mpd"](4608,Jl.a,Jl.a,[t.ComponentFactoryResolver,t.NgZone,t.Injector,Mu.a,t.ApplicationRef]),t["\u0275mpd"](4608,Ou.a,Ou.a,[]),t["\u0275mpd"](4608,nn.b,nn.b,[t.RendererFactory2,Jl.a]),t["\u0275mpd"](4608,Lu.ScrollbarHelper,Lu.ScrollbarHelper,[yl.DOCUMENT]),t["\u0275mpd"](4608,Gu.DimensionsHelper,Gu.DimensionsHelper,[]),t["\u0275mpd"](4608,Ku.ColumnChangesService,Ku.ColumnChangesService,[]),t["\u0275mpd"](4608,Xl.f,Xl.f,[]),t["\u0275mpd"](4608,S.a,S.a,[]),t["\u0275mpd"](4608,o.a,o.a,[$u.l,S.a]),t["\u0275mpd"](4608,vl.e,vl.e,[]),t["\u0275mpd"](1073742336,ql.CommonModule,ql.CommonModule,[]),t["\u0275mpd"](1073742336,Zu.a,Zu.a,[]),t["\u0275mpd"](1073742336,d.B,d.B,[]),t["\u0275mpd"](1073742336,d.n,d.n,[]),t["\u0275mpd"](1073742336,d.x,d.x,[]),t["\u0275mpd"](1073742336,Bu.c,Bu.c,[]),t["\u0275mpd"](1073742336,Uu.d,Uu.d,[]),t["\u0275mpd"](1073742336,Ou.d,Ou.d,[]),t["\u0275mpd"](1073742336,Qu.ChartsModule,Qu.ChartsModule,[]),t["\u0275mpd"](1073742336,nn.e,nn.e,[]),t["\u0275mpd"](1073742336,Hu.a,Hu.a,[]),t["\u0275mpd"](1073742336,Xl.e,Xl.e,[]),t["\u0275mpd"](1073742336,Yu.a,Yu.a,[]),t["\u0275mpd"](1073742336,Xu.NgxDatatableModule,Xu.NgxDatatableModule,[]),t["\u0275mpd"](1073742336,$u.p,$u.p,[[2,$u.v],[2,$u.l]]),t["\u0275mpd"](1073742336,Ju.a,Ju.a,[]),t["\u0275mpd"](1073742336,b.a,b.a,[]),t["\u0275mpd"](1073742336,Wu.a,Wu.a,[]),t["\u0275mpd"](1073742336,le.a,le.a,[]),t["\u0275mpd"](1073742336,vl.c,vl.c,[]),t["\u0275mpd"](1073742336,X,X,[]),t["\u0275mpd"](256,t.LOCALE_ID,"en-US",[]),t["\u0275mpd"](256,Xl.a,{autoClose:!0,insideClick:!1},[]),t["\u0275mpd"](256,t.TRANSLATIONS_FORMAT,"xlf",[])])}),Zt=t["\u0275cmf"](ol,[],function(l){return t["\u0275mod"]([t["\u0275mpd"](512,t.ComponentFactoryResolver,t["\u0275CodegenComponentFactoryResolver"],[[8,[al.a,rl.a,sl.a,dl.a,dl.b,cl.a,pl.a,fl.a,ml.a,gl.a,Pl,Hl,In,Pn,eu,gu,xu,ie,ce,ct,Rt,Bt,Kt]],[3,t.ComponentFactoryResolver],t.NgModuleRef]),t["\u0275mpd"](4608,ql.NgLocalization,ql.NgLocaleLocalization,[t.LOCALE_ID,[2,ql["\u0275angular_packages_common_common_a"]]]),t["\u0275mpd"](4608,zl.a,zl.a,[_l.a]),t["\u0275mpd"](4608,ql.DatePipe,ql.DatePipe,[t.LOCALE_ID]),t["\u0275mpd"](4608,P.a,P.a,[]),t["\u0275mpd"](4608,a.a,a.a,[]),t["\u0275mpd"](4608,U.a,U.a,[]),t["\u0275mpd"](4608,q.a,q.a,[U.a]),t["\u0275mpd"](4608,Tu.a,Tu.a,[U.a]),t["\u0275mpd"](4608,V.a,V.a,[U.a]),t["\u0275mpd"](4608,qu.a,qu.a,[]),t["\u0275mpd"](4608,Vu.a,Vu.a,[]),t["\u0275mpd"](4608,Su.a,Su.a,[]),t["\u0275mpd"](4608,Du.a,Du.a,[]),t["\u0275mpd"](4608,wl.a,wl.a,[ql.DatePipe]),t["\u0275mpd"](4608,Nu.a,Nu.a,[]),t["\u0275mpd"](4608,Fu.a,Fu.a,[]),t["\u0275mpd"](4608,ju.a,ju.a,[]),t["\u0275mpd"](4608,Pu.a,Pu.a,[]),t["\u0275mpd"](4608,zu.a,zu.a,[]),t["\u0275mpd"](4608,Au.a,Au.a,[_l.a]),t["\u0275mpd"](4608,wn.a,wn.a,[]),t["\u0275mpd"](4608,Wl.a,Wl.a,[]),t["\u0275mpd"](4608,d.E,d.E,[]),t["\u0275mpd"](4608,d.h,d.h,[]),t["\u0275mpd"](4608,Bu.b,Bu.b,[]),t["\u0275mpd"](4608,Uu.a,Uu.a,[]),t["\u0275mpd"](4608,Mu.a,Mu.a,[t.RendererFactory2,t.PLATFORM_ID]),t["\u0275mpd"](4608,Jl.a,Jl.a,[t.ComponentFactoryResolver,t.NgZone,t.Injector,Mu.a,t.ApplicationRef]),t["\u0275mpd"](4608,Ou.a,Ou.a,[]),t["\u0275mpd"](4608,nn.b,nn.b,[t.RendererFactory2,Jl.a]),t["\u0275mpd"](4608,Lu.ScrollbarHelper,Lu.ScrollbarHelper,[yl.DOCUMENT]),t["\u0275mpd"](4608,Gu.DimensionsHelper,Gu.DimensionsHelper,[]),t["\u0275mpd"](4608,Ku.ColumnChangesService,Ku.ColumnChangesService,[]),t["\u0275mpd"](4608,Xl.f,Xl.f,[]),t["\u0275mpd"](4608,S.a,S.a,[]),t["\u0275mpd"](4608,o.a,o.a,[$u.l,S.a]),t["\u0275mpd"](4608,vl.e,vl.e,[]),t["\u0275mpd"](1073742336,ql.CommonModule,ql.CommonModule,[]),t["\u0275mpd"](1073742336,Zu.a,Zu.a,[]),t["\u0275mpd"](1073742336,d.B,d.B,[]),t["\u0275mpd"](1073742336,d.n,d.n,[]),t["\u0275mpd"](1073742336,d.x,d.x,[]),t["\u0275mpd"](1073742336,Bu.c,Bu.c,[]),t["\u0275mpd"](1073742336,Uu.d,Uu.d,[]),t["\u0275mpd"](1073742336,Ou.d,Ou.d,[]),t["\u0275mpd"](1073742336,Qu.ChartsModule,Qu.ChartsModule,[]),t["\u0275mpd"](1073742336,nn.e,nn.e,[]),t["\u0275mpd"](1073742336,Hu.a,Hu.a,[]),t["\u0275mpd"](1073742336,Xl.e,Xl.e,[]),t["\u0275mpd"](1073742336,Yu.a,Yu.a,[]),t["\u0275mpd"](1073742336,Xu.NgxDatatableModule,Xu.NgxDatatableModule,[]),t["\u0275mpd"](1073742336,$u.p,$u.p,[[2,$u.v],[2,$u.l]]),t["\u0275mpd"](1073742336,Ju.a,Ju.a,[]),t["\u0275mpd"](1073742336,b.a,b.a,[]),t["\u0275mpd"](1073742336,Wu.a,Wu.a,[]),t["\u0275mpd"](1073742336,le.a,le.a,[]),t["\u0275mpd"](1073742336,vl.c,vl.c,[]),t["\u0275mpd"](1073742336,X,X,[]),t["\u0275mpd"](1073742336,ol,ol,[]),t["\u0275mpd"](256,t.LOCALE_ID,"en-US",[]),t["\u0275mpd"](256,Xl.a,{autoClose:!0,insideClick:!1},[]),t["\u0275mpd"](1024,$u.j,function(){return[[{path:"",redirectTo:"daemon",pathMatch:"full"},{path:"daemon",component:z,data:J},{path:"user",data:W,children:[{path:"",component:Y},{path:"create",component:Z,data:ll},{path:"edit/:uid",component:Z,data:nl}]},{path:"bucket",data:ul,children:[{path:"",component:F},{path:"create",component:R,data:el},{path:"edit/:bid",component:R,data:tl}]},{path:"501/:message",component:s,canActivate:[o.a],data:il}]]},[]),t["\u0275mpd"](256,t.TRANSLATIONS_FORMAT,"xlf",[])])})}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/7.76846491986b0ea6c0bd.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/7.76846491986b0ea6c0bd.js
new file mode 100644
index 00000000..61b2e446
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/7.76846491986b0ea6c0bd.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{J6Oi:function(l,n,u){"use strict";u.r(n);var e=u("CcnG"),t=u("k/xb"),a=u("MdoF"),o=u("ES0t"),i=u("Xg1U"),r=u("z5nN"),d=u("iutN"),s=u("EEJc"),c=u("PEr+"),p=u("a40w"),f=u("pMnS"),g=u("RIVN"),m=u("nP0W"),v=u("VBM6"),h=u("atuK"),b=u("JIi+"),C=u("Ur3J"),R=u("I4Qz"),I=u("0rTx"),w=u("lz+O"),T=u("u2XS"),y=u("nhAp"),k=u("l7Jr"),E=u("bUo2"),_=u("Ip0R"),x=u("iExv"),V=u("Jm/i"),N=u("85J/"),D=u("+0ag"),S=u("aXbf"),F=u("Fgil"),P=u("IzCI"),q=u("o4+5"),j=u("Dwqy"),O=u("uYzU"),A=u("uhwM"),U=u("E2fk"),$=u("a0VL"),M=u("nSDx"),z=u("SB+Q"),B=u("TYzs"),L=u("BQkM"),G=u("dEH0"),K=u("G1/K"),H=u("8xTl"),J=u("TJUb"),Z=u("gIcY"),W=u("lTVp"),Q=u("OZfm"),Y=u("NJnL"),X=u("lqqz"),ll=u("eajB"),nl=u("DQlY"),ul=u("FO+L"),el=u("ZYjt"),tl=u("nhM1"),al=u("BARL"),ol=u("xtZt"),il=u("aexS"),rl=u("Avrn"),dl=u("ZYCi"),sl=u("urB8"),cl=u("JZ5S"),pl=u("Tff5"),fl=u("YAQW"),gl=u("Da1D"),ml=u("ARl4"),vl=u("9Xeq"),hl=u("xdbM"),bl=u("yGOH"),Cl=u("V/fk"),Rl=u("F8xH"),Il=u("ChqD"),wl=u("pL04"),Tl=u("PCNd"),yl=u("STEd"),kl=u("kccj"),El=u("a278"),_l=u("insk"),xl=u("mSOc"),Vl=u("20UP"),Nl=u("pKUh"),Dl=u("C6Ij"),Sl=u("AWcq"),Fl=u("25BL"),Pl=u("uIqm"),ql=u("NUGo"),jl=u("S7zO"),Ol=u("JBea"),Al=u("VTlA"),Ul=u("ufoC"),$l=u("EgGo"),Ml=u("LvDl"),zl=u("F83c"),Bl=u("OLbh"),Ll=u("0+/T"),Gl=u("sne2"),Kl=u("x38r"),Hl=u("yJti"),Jl=u("vCyI"),Zl=u("kvvV"),Wl=u("kn/O"),Ql=u("2JDI"),Yl=u("u0yg"),Xl=new $l.a("block/rbd"),ln=function(){function l(l,n,u,e,t,a,o,i,r,d){var s=this;this.authStorageService=l,this.rbdService=n,this.dimlessBinaryPipe=u,this.dimlessPipe=e,this.modalService=t,this.taskWrapper=a,this.taskListService=o,this.i18n=i,this.urlBuilder=r,this.actionLabels=d,this.selection=new Jl.a,this.builders={"rbd/create":function(l){return s.createRbdFromTask(l.pool_name,l.image_name)},"rbd/clone":function(l){return s.createRbdFromTask(l.child_pool_name,l.child_image_name)},"rbd/copy":function(l){return s.createRbdFromTask(l.dest_pool_name,l.dest_image_name)}},this.permission=this.authStorageService.getPermissions().rbdImage;var c=function(){return s.selection.first()&&encodeURIComponent(s.selection.first().pool_name)+"/"+encodeURIComponent(s.selection.first().name)};this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return s.urlBuilder.getCreate()},canBePrimary:function(l){return!l.hasSingleSelection},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return s.urlBuilder.getEdit(c())},name:this.actionLabels.EDIT},{permission:"create",canBePrimary:function(l){return l.hasSingleSelection},disable:function(l){return!l.hasSingleSelection||l.first().cdExecuting},icon:"fa-copy",routerLink:function(){return"/block/rbd/copy/"+c()},name:this.actionLabels.COPY},{permission:"update",disable:function(l){return!l.hasSingleSelection||l.first().cdExecuting||!l.first().parent},icon:"fa-chain-broken",click:function(){return s.flattenRbdModal()},name:this.actionLabels.FLATTEN},{permission:"delete",icon:"fa-times",click:function(){return s.deleteRbdModal()},name:this.actionLabels.DELETE},{permission:"delete",icon:"fa-trash-o",click:function(){return s.trashRbdModal()},name:this.actionLabels.TRASH,disable:function(l){return!l.first()||!l.hasSingleSelection||l.first().image_format===Yl.a.V1}}]}return l.prototype.createRbdFromTask=function(l,n){var u=new Yl.b;return u.id="-1",u.unique_id="-1",u.name=n,u.pool_name=l,u.image_format=Yl.a.V2,u},l.prototype.ngOnInit=function(){var l=this;this.columns=[{name:this.i18n("Name"),prop:"name",flexGrow:2,cellTransformation:Kl.a.executing},{name:this.i18n("Pool"),prop:"pool_name",flexGrow:2},{name:this.i18n("Size"),prop:"size",flexGrow:1,cellClass:"text-right",pipe:this.dimlessBinaryPipe},{name:this.i18n("Objects"),prop:"num_objs",flexGrow:1,cellClass:"text-right",pipe:this.dimlessPipe},{name:this.i18n("Object size"),prop:"obj_size",flexGrow:1,cellClass:"text-right",pipe:this.dimlessBinaryPipe},{name:this.i18n("Provisioned"),prop:"disk_usage",cellClass:"text-center",flexGrow:1,pipe:this.dimlessBinaryPipe},{name:this.i18n("Total provisioned"),prop:"total_disk_usage",cellClass:"text-center",flexGrow:1,pipe:this.dimlessBinaryPipe},{name:this.i18n("Parent"),prop:"parent",flexGrow:2,cellTemplate:this.parentTpl}],this.taskListService.init(function(){return l.rbdService.list()},function(n){return l.prepareResponse(n)},function(n){return l.images=n},function(){return l.onFetchError()},this.taskFilter,this.itemFilter,this.builders)},l.prototype.onFetchError=function(){this.table.reset(),this.viewCacheStatusList=[{status:Hl.a.ValueException}]},l.prototype.prepareResponse=function(l){var n=[],u={};l.forEach(function(l){Ml.isUndefined(u[l.status])&&(u[l.status]=[]),u[l.status].push(l.pool_name),n=n.concat(l.value)});var e=[];return Ml.forEach(u,function(l,n){e.push({status:parseInt(n,10),statusFor:(l.length>1?"pools ":"pool ")+"<strong>"+l.join("</strong>, <strong>")+"</strong>"})}),this.viewCacheStatusList=e,n},l.prototype.itemFilter=function(l,n){var u,e;switch(n.name){case"rbd/copy":u="dest_pool_name",e="dest_image_name";break;case"rbd/clone":u="child_pool_name",e="child_image_name";break;default:u="pool_name",e="image_name"}return l.pool_name===n.metadata[u]&&l.name===n.metadata[e]},l.prototype.taskFilter=function(l){return["rbd/clone","rbd/copy","rbd/create","rbd/delete","rbd/edit","rbd/flatten","rbd/trash/move"].includes(l.name)},l.prototype.updateSelection=function(l){this.selection=l},l.prototype.deleteRbdModal=function(){var l=this,n=this.selection.first().pool_name,u=this.selection.first().name;this.modalRef=this.modalService.show(Ll.a,{initialState:{itemDescription:"RBD",itemNames:[n+"/"+u],submitActionObservable:function(){return l.taskWrapper.wrapTaskAroundCall({task:new Zl.a("rbd/delete",{pool_name:n,image_name:u}),call:l.rbdService.delete(n,u)})}}})},l.prototype.trashRbdModal=function(){var l={metaType:"RBD",poolName:this.selection.first().pool_name,imageName:this.selection.first().name};this.modalRef=this.modalService.show(Ql.a,{initialState:l})},l.prototype.flattenRbd=function(l,n){var u=this;this.taskWrapper.wrapTaskAroundCall({task:new Zl.a("rbd/flatten",{pool_name:l,image_name:n}),call:this.rbdService.flatten(l,n)}).subscribe(void 0,void 0,function(){u.modalRef.hide()})},l.prototype.flattenRbdModal=function(){var l=this,n=this.selection.first().pool_name,u=this.selection.first().name,e=this.selection.first().parent;this.modalRef=this.modalService.show(Bl.a,{initialState:{titleText:"RBD flatten",buttonText:"Flatten",bodyTpl:this.flattenTpl,bodyData:{parent:e.pool_name+"/"+e.image_name+"@"+e.snap_name,child:n+"/"+u},onSubmit:function(){l.flattenRbd(n,u)}}})},l}(),nn=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function un(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-view-cache",[],null,null,null,Dl.b,Dl.a)),e["\u0275did"](1,114688,null,0,Sl.a,[],{status:[0,"status"],statusFor:[1,"statusFor"]},null)],function(l,n){l(n,1,0,n.context.$implicit.status,n.context.$implicit.statusFor)},null)}function en(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,0,"div",[],[[8,"innerHTML",1]],null,null,null,null))],null,function(l,n){l(n,0,0,"Only available for RBD images with <strong>fast-diff</strong> enabled")})}function tn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,["","/","@",""]))],null,function(l,n){l(n,1,0,n.parent.context.value.pool_name,n.parent.context.value.image_name,n.parent.context.value.snap_name)})}function an(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["-"]))],null,null)}function on(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,tn)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,an)),e["\u0275did"](3,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,n.context.value),l(n,3,0,!n.context.value)},null)}function rn(l){return e["\u0275vid"](0,[(l()(),e["\u0275ted"](-1,null,[" You are about to flatten "])),(l()(),e["\u0275eld"](1,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),e["\u0275ted"](2,null,["",""])),(l()(),e["\u0275ted"](-1,null,[". "])),(l()(),e["\u0275eld"](4,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,[" All blocks will be copied from parent "])),(l()(),e["\u0275eld"](7,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),e["\u0275ted"](8,null,["",""])),(l()(),e["\u0275ted"](-1,null,[" to child "])),(l()(),e["\u0275eld"](10,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),e["\u0275ted"](11,null,["",""])),(l()(),e["\u0275ted"](-1,null,[".\n"]))],null,function(l,n){l(n,2,0,n.context.$implicit.child),l(n,8,0,n.context.$implicit.parent),l(n,11,0,n.context.$implicit.child)})}function dn(l){return e["\u0275vid"](0,[e["\u0275qud"](402653184,1,{table:0}),e["\u0275qud"](402653184,2,{usageTpl:0}),e["\u0275qud"](402653184,3,{parentTpl:0}),e["\u0275qud"](402653184,4,{nameTpl:0}),e["\u0275qud"](402653184,5,{flattenTpl:0}),(l()(),e["\u0275and"](16777216,null,null,1,null,un)),e["\u0275did"](6,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](7,0,null,null,5,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","unique_id"],["selectionType","single"]],null,[[null,"updateSelection"]],function(l,n,u){var e=!0;return"updateSelection"===n&&(e=!1!==l.component.updateSelection(u)&&e),e},Fl.b,Fl.a)),e["\u0275did"](8,2867200,[[1,4],["table",4]],0,Pl.a,[e.NgZone,e.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"],searchableObjects:[6,"searchableObjects"]},{updateSelection:"updateSelection"}),(l()(),e["\u0275eld"](9,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,ql.b,ql.a)),e["\u0275did"](10,114688,null,0,jl.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),e["\u0275eld"](11,0,null,2,1,"cd-rbd-details",[["cdTableDetail",""]],null,null,null,b.c,b.b)),e["\u0275did"](12,573440,null,0,Ol.a,[],{selection:[0,"selection"]},null),(l()(),e["\u0275and"](0,[["usageNotAvailableTooltipTpl",2]],null,0,null,en)),(l()(),e["\u0275and"](0,[[3,2],["parentTpl",2]],null,0,null,on)),(l()(),e["\u0275and"](0,[[5,2],["flattenTpl",2]],null,0,null,rn))],function(l,n){var u=n.component;l(n,6,0,u.viewCacheStatusList),l(n,8,0,u.images,u.columns,"flex","unique_id","true","single",!0),l(n,10,0,u.permission,u.selection,u.tableActions),l(n,12,0,u.selection)},null)}var sn=u("wd/R"),cn=u("WxU5"),pn=u("2GqK"),fn=function(){function l(l,n,u,e,t,a,o,i){var r=this;this.authStorageService=l,this.rbdService=n,this.modalService=u,this.cdDatePipe=e,this.taskListService=t,this.taskWrapper=a,this.i18n=o,this.actionLabels=i,this.executingTasks=[],this.selection=new Jl.a,this.disablePurgeBtn=!0,this.permission=this.authStorageService.getPermissions().rbdImage,this.tableActions=[{permission:"update",icon:"fa-undo",click:function(){return r.restoreModal()},name:this.actionLabels.RESTORE},{permission:"delete",icon:"fa-times",click:function(){return r.deleteModal()},name:this.actionLabels.DELETE}]}return l.prototype.ngOnInit=function(){var l=this;this.columns=[{name:this.i18n("ID"),prop:"id",flexGrow:1,cellTransformation:Kl.a.executing},{name:this.i18n("Name"),prop:"name",flexGrow:1},{name:this.i18n("Pool"),prop:"pool_name",flexGrow:1},{name:this.i18n("Status"),prop:"deferment_end_time",flexGrow:1,cellTemplate:this.expiresTpl},{name:this.i18n("Deleted At"),prop:"deletion_time",flexGrow:1,pipe:this.cdDatePipe}],this.taskListService.init(function(){return l.rbdService.listTrash()},function(n){return l.prepareResponse(n)},function(n){return l.images=n},function(){return l.onFetchError()},this.taskFilter,this.itemFilter,void 0)},l.prototype.prepareResponse=function(l){var n=this,u=[],e={};l.forEach(function(l){Ml.isUndefined(e[l.status])&&(e[l.status]=[]),e[l.status].push(l.pool_name),u=u.concat(l.value),n.disablePurgeBtn=!u.length});var t=[];return Ml.forEach(e,function(l,n){t.push({status:parseInt(n,10),statusFor:(l.length>1?"pools ":"pool ")+"<strong>"+l.join("</strong>, <strong>")+"</strong>"})}),this.viewCacheStatusList=t,u.forEach(function(l){l.cdIsExpired=sn().isAfter(l.deferment_end_time)}),u},l.prototype.onFetchError=function(){this.table.reset(),this.viewCacheStatusList=[{status:Hl.a.ValueException}]},l.prototype.itemFilter=function(l,n){return l.id===n.metadata.image_id},l.prototype.taskFilter=function(l){return["rbd/trash/remove","rbd/trash/restore"].includes(l.name)},l.prototype.updateSelection=function(l){this.selection=l},l.prototype.restoreModal=function(){var l={metaType:"RBD",poolName:this.selection.first().pool_name,imageName:this.selection.first().name,imageId:this.selection.first().id};this.modalRef=this.modalService.show(pn.a,{initialState:l})},l.prototype.deleteModal=function(){var l=this,n=this.selection.first().pool_name,u=this.selection.first().name,e=this.selection.first().id,t=this.selection.first().deferment_end_time;this.modalRef=this.modalService.show(Ll.a,{initialState:{itemDescription:"RBD",itemNames:[n+"/"+u],bodyTemplate:this.deleteTpl,bodyContext:{$implicit:t},submitActionObservable:function(){return l.taskWrapper.wrapTaskAroundCall({task:new Zl.a("rbd/trash/remove",{pool_name:n,image_id:e,image_name:u}),call:l.rbdService.removeTrash(n,e,u,!0)})}}})},l.prototype.isExpired=function(l){return sn().isAfter(l)},l.prototype.purgeModal=function(){this.modalService.show(cn.a)},l}(),gn=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function mn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-view-cache",[],null,null,null,Dl.b,Dl.a)),e["\u0275did"](1,114688,null,0,Sl.a,[],{status:[0,"status"],statusFor:[1,"statusFor"]},null)],function(l,n){l(n,1,0,n.context.$implicit.status,n.context.$implicit.statusFor)},null)}function vn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"button",[["class","btn btn-sm btn-default btn-label"],["type","button"]],[[8,"disabled",0]],[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.purgeModal()&&e),e},null,null)),(l()(),e["\u0275eld"](1,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-fw fa-times"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Purge Trash"]))],null,function(l,n){l(n,0,0,n.component.disablePurgeBtn)})}function hn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Expired at"]))],null,null)}function bn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Protected until"]))],null,null)}function Cn(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,hn)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,bn)),e["\u0275did"](3,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275ted"](4,null,[" ","\n"])),e["\u0275ppd"](5,1)],function(l,n){l(n,1,0,n.context.row.cdIsExpired),l(n,3,0,!n.context.row.cdIsExpired)},function(l,n){var u=e["\u0275unv"](n,4,0,l(n,5,0,e["\u0275nov"](n.parent,0),n.context.value));l(n,4,0,u)})}function Rn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,4,"p",[["class","text-danger"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,3,"strong",[],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,2,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](3,null,["This image is protected until ","."])),e["\u0275ppd"](4,1)],null,function(l,n){var u=e["\u0275unv"](n,3,0,l(n,4,0,e["\u0275nov"](n.parent.parent,0),n.parent.context.$implicit));l(n,3,0,u)})}function In(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,Rn)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,!n.component.isExpired(n.context.$implicit))},null)}function wn(l){return e["\u0275vid"](0,[e["\u0275pid"](0,$.a,[_.DatePipe]),e["\u0275qud"](402653184,1,{table:0}),e["\u0275qud"](402653184,2,{expiresTpl:0}),e["\u0275qud"](402653184,3,{deleteTpl:0}),(l()(),e["\u0275and"](16777216,null,null,1,null,mn)),e["\u0275did"](5,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](6,0,null,null,6,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","id"],["selectionType","single"]],null,[[null,"updateSelection"]],function(l,n,u){var e=!0;return"updateSelection"===n&&(e=!1!==l.component.updateSelection(u)&&e),e},Fl.b,Fl.a)),e["\u0275did"](7,2867200,[[1,4]],0,Pl.a,[e.NgZone,e.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"]},{updateSelection:"updateSelection"}),(l()(),e["\u0275eld"](8,0,null,0,4,"div",[["class","table-actions btn-toolbar"]],null,null,null,null,null)),(l()(),e["\u0275eld"](9,0,null,null,1,"cd-table-actions",[["class","btn-group"]],null,null,null,ql.b,ql.a)),e["\u0275did"](10,114688,null,0,jl.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,vn)),e["\u0275did"](12,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,[[2,2],["expiresTpl",2]],null,0,null,Cn)),(l()(),e["\u0275and"](0,[[3,2],["deleteTpl",2]],null,0,null,In))],function(l,n){var u=n.component;l(n,5,0,u.viewCacheStatusList),l(n,7,0,u.images,u.columns,"flex","id","true","single"),l(n,10,0,u.permission,u.selection,u.tableActions),l(n,12,0,u.permission.delete)},null)}var Tn=u("wG1H"),yn=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function kn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"tab",[["heading","Overall Performance"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),e["\u0275did"](1,212992,null,0,fl.b,[fl.d,e.ElementRef,e.Renderer2],{heading:[0,"heading"]},null),(l()(),e["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","two"],["uid","41FrpeUiz"]],null,null,null,El.b,El.a)),e["\u0275did"](3,638976,null,0,_l.a,[xl.a,el.DomSanitizer,Vl.a,D.a,V.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(l,n){l(n,1,0,"Overall Performance"),l(n,3,0,"rbd-overview?","two","41FrpeUiz")},function(l,n){l(n,0,0,e["\u0275nov"](n,1).id,e["\u0275nov"](n,1).active,e["\u0275nov"](n,1).addClass)})}function En(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,15,"div",[],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,14,"tabset",[],[[2,"tab-container",null]],null,null,Nl.b,Nl.a)),e["\u0275did"](2,180224,null,0,fl.d,[fl.e,e.Renderer2,e.ElementRef],null,null),(l()(),e["\u0275eld"](3,0,null,0,5,"tab",[["heading","Images"],["id","tab1"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),e["\u0275did"](4,212992,null,0,fl.b,[fl.d,e.ElementRef,e.Renderer2],{heading:[0,"heading"],id:[1,"id"]},null),(l()(),e["\u0275eld"](5,0,null,null,3,"cd-rbd-list",[],null,null,null,dn,nn)),e["\u0275prd"](131584,null,Al.a,Al.a,[Ul.a,xl.a]),e["\u0275prd"](256,null,$l.a,Xl,[]),e["\u0275did"](8,114688,null,0,ln,[il.a,zl.a,F.a,q.a,nl.b,Wl.a,Al.a,V.a,$l.a,Gl.b],null,null),(l()(),e["\u0275eld"](9,0,null,0,4,"tab",[["heading","Trash"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),e["\u0275did"](10,212992,null,0,fl.b,[fl.d,e.ElementRef,e.Renderer2],{heading:[0,"heading"]},null),(l()(),e["\u0275eld"](11,0,null,null,2,"cd-rbd-trash-list",[],null,null,null,wn,gn)),e["\u0275prd"](131584,null,Al.a,Al.a,[Ul.a,xl.a]),e["\u0275did"](13,114688,null,0,fn,[il.a,zl.a,nl.b,$.a,Al.a,Wl.a,V.a,Gl.b],null,null),(l()(),e["\u0275and"](16777216,null,0,1,null,kn)),e["\u0275did"](15,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,4,0,"Images","tab1"),l(n,8,0),l(n,10,0,"Trash"),l(n,13,0),l(n,15,0,u.grafanaPermission.read)},function(l,n){l(n,1,0,e["\u0275nov"](n,2).clazz),l(n,3,0,e["\u0275nov"](n,4).id,e["\u0275nov"](n,4).active,e["\u0275nov"](n,4).addClass),l(n,9,0,e["\u0275nov"](n,10).id,e["\u0275nov"](n,10).active,e["\u0275nov"](n,10).addClass)})}function _n(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-rbd-images",[],null,null,null,En,yn)),e["\u0275did"](1,114688,null,0,Tn.a,[il.a],null,null)],function(l,n){l(n,1,0)},null)}var xn=e["\u0275ccf"]("cd-rbd-images",Tn.a,_n,{},{},[]),Vn=u("ANnk"),Nn=u("f/UV"),Dn=u("4HWh"),Sn=u("p4Cf"),Fn=u("IZUe"),Pn=u("EmSq"),qn=u("BH9v"),jn=u("rFfW"),On=u("o8EM"),An=u("gp3X"),Un=u("sb0X"),$n=u("KVJa"),Mn=u("Z21x"),zn=u("MyVl"),Bn=u("Ekvf"),Ln=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Gn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),e["\u0275ted"](2,null,[""," from"])),e["\u0275ppd"](3,1),(l()(),e["\u0275eld"](4,0,null,null,8,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,6,"input",[["class","form-control"],["formControlName","parent"],["id","parent"],["name","parent"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,6)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,6).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,6)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,6)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](6,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](8,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](10,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](11,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](12,0,null,null,0,"hr",[],null,null,null,null,null))],function(l,n){l(n,8,0,"parent")},function(l,n){var u=n.component,t=e["\u0275unv"](n,2,0,l(n,3,0,e["\u0275nov"](n.parent,0),u.action));l(n,2,0,t),l(n,5,0,e["\u0275nov"](n,10).ngClassUntouched,e["\u0275nov"](n,10).ngClassTouched,e["\u0275nov"](n,10).ngClassPristine,e["\u0275nov"](n,10).ngClassDirty,e["\u0275nov"](n,10).ngClassValid,e["\u0275nov"](n,10).ngClassInvalid,e["\u0275nov"](n,10).ngClassPending)})}function Kn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Hn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["'/' and '@' are not allowed."]))],null,null)}function Jn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Zn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","pool"],["id","pool"],["name","pool"],["placeholder","Pool name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,1)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,1).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,1)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,1)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](1,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](3,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](5,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](6,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null)],function(l,n){l(n,3,0,"pool")},function(l,n){l(n,0,0,e["\u0275nov"](n,5).ngClassUntouched,e["\u0275nov"](n,5).ngClassTouched,e["\u0275nov"](n,5).ngClassPristine,e["\u0275nov"](n,5).ngClassDirty,e["\u0275nov"](n,5).ngClassValid,e["\u0275nov"](n,5).ngClassInvalid,e["\u0275nov"](n,5).ngClassPending)})}function Wn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Qn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["-- No rbd pools available --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Yn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["-- Select a pool --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Xn(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{value:[0,"value"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),e["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit.pool_name),l(n,2,0,n.context.$implicit.pool_name)},function(l,n){l(n,3,0,n.context.$implicit.pool_name)})}function lu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,14,"select",[["class","form-control"],["formControlName","pool"],["id","pool"],["name","pool"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0;return"change"===n&&(t=!1!==e["\u0275nov"](l,1).onChange(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,1).onTouched()&&t),t},null,null)),e["\u0275did"](1,16384,null,0,Z.z,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.z]),e["\u0275did"](3,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](5,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](6,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Wn)),e["\u0275did"](8,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Qn)),e["\u0275did"](10,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Yn)),e["\u0275did"](12,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Xn)),e["\u0275did"](14,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var u=n.component;l(n,3,0,"pool"),l(n,8,0,null===u.pools),l(n,10,0,null!==u.pools&&0===u.pools.length),l(n,12,0,null!==u.pools&&u.pools.length>0),l(n,14,0,u.pools)},function(l,n){l(n,0,0,e["\u0275nov"](n,5).ngClassUntouched,e["\u0275nov"](n,5).ngClassTouched,e["\u0275nov"](n,5).ngClassPristine,e["\u0275nov"](n,5).ngClassDirty,e["\u0275nov"](n,5).ngClassValid,e["\u0275nov"](n,5).ngClassInvalid,e["\u0275nov"](n,5).ngClassPending)})}function nu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function uu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function eu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","dataPool"],["id","dataPool"],["name","dataPool"],["placeholder","Data pool name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,1)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,1).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,1)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,1)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](1,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](3,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](5,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](6,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null)],function(l,n){l(n,3,0,"dataPool")},function(l,n){l(n,0,0,e["\u0275nov"](n,5).ngClassUntouched,e["\u0275nov"](n,5).ngClassTouched,e["\u0275nov"](n,5).ngClassPristine,e["\u0275nov"](n,5).ngClassDirty,e["\u0275nov"](n,5).ngClassValid,e["\u0275nov"](n,5).ngClassInvalid,e["\u0275nov"](n,5).ngClassPending)})}function tu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function au(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["-- No data pools available --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function ou(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["-- Select a data pool -- "]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function iu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{value:[0,"value"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),e["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit.pool_name),l(n,2,0,n.context.$implicit.pool_name)},function(l,n){l(n,3,0,n.context.$implicit.pool_name)})}function ru(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,14,"select",[["class","form-control"],["formControlName","dataPool"],["id","dataPool"],["name","dataPool"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0,a=l.component;return"change"===n&&(t=!1!==e["\u0275nov"](l,1).onChange(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,1).onTouched()&&t),"change"===n&&(t=!1!==a.onDataPoolChange(u.target.value)&&t),t},null,null)),e["\u0275did"](1,16384,null,0,Z.z,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.z]),e["\u0275did"](3,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](5,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](6,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,tu)),e["\u0275did"](8,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,au)),e["\u0275did"](10,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ou)),e["\u0275did"](12,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,iu)),e["\u0275did"](14,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var u=n.component;l(n,3,0,"dataPool"),l(n,8,0,null===u.dataPools),l(n,10,0,null!==u.dataPools&&0===u.dataPools.length),l(n,12,0,null!==u.dataPools&&u.dataPools.length>0),l(n,14,0,u.dataPools)},function(l,n){l(n,0,0,e["\u0275nov"](n,5).ngClassUntouched,e["\u0275nov"](n,5).ngClassTouched,e["\u0275nov"](n,5).ngClassPristine,e["\u0275nov"](n,5).ngClassDirty,e["\u0275nov"](n,5).ngClassValid,e["\u0275nov"](n,5).ngClassInvalid,e["\u0275nov"](n,5).ngClassPending)})}function du(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function su(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](1,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](2,{"has-error":0}),(l()(),e["\u0275eld"](3,0,null,null,6,"label",[["class","control-label col-sm-3"],["for","dataPool"]],null,null,null,null,null)),(l()(),e["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Data pool"])),(l()(),e["\u0275and"](16777216,null,null,1,null,uu)),e["\u0275did"](7,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](8,0,null,null,1,"cd-helper",[["html","Dedicated pool that stores the object-data of the RBD."]],null,null,null,Dn.b,Dn.a)),e["\u0275did"](9,49152,null,0,Sn.a,[],{html:[0,"html"]},null),(l()(),e["\u0275eld"](10,0,null,null,6,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,eu)),e["\u0275did"](12,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ru)),e["\u0275did"](14,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,du)),e["\u0275did"](16,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component,t=l(n,2,0,u.rbdForm.showError("dataPool",e["\u0275nov"](n.parent,5)));l(n,1,0,"form-group",t),l(n,7,0,"editing"!==u.mode),l(n,9,0,"Dedicated pool that stores the object-data of the RBD."),l(n,12,0,"editing"===u.mode||!u.poolPermission.read),l(n,14,0,"editing"!==u.mode&&u.poolPermission.read),l(n,16,0,u.rbdForm.showError("dataPool",e["\u0275nov"](n.parent,5),"required"))},null)}function cu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function pu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["You have to increase the size."]))],null,null)}function fu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-helper",[],null,null,null,Dn.b,Dn.a)),e["\u0275did"](1,49152,null,0,Sn.a,[],{html:[0,"html"]},null)],function(l,n){l(n,1,0,e["\u0275inlineInterpolate"](1,"",n.parent.context.$implicit.helperHtml,""))},null)}function gu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,11,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,6,"input",[["type","checkbox"]],[[8,"id",0],[8,"name",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0;return"change"===n&&(t=!1!==e["\u0275nov"](l,2).onChange(u.target.checked)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,2).onTouched()&&t),t},null,null)),e["\u0275did"](2,16384,null,0,Z.c,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.c]),e["\u0275did"](4,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](6,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](7,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](8,0,null,null,1,"label",[],[[8,"htmlFor",0]],null,null,null,null)),(l()(),e["\u0275ted"](9,null,["",""])),(l()(),e["\u0275and"](16777216,null,null,1,null,fu)),e["\u0275did"](11,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,4,0,e["\u0275inlineInterpolate"](1,"",n.context.$implicit.key,"")),l(n,11,0,n.context.$implicit.helperHtml)},function(l,n){l(n,1,0,e["\u0275inlineInterpolate"](1,"",n.context.$implicit.key,""),e["\u0275inlineInterpolate"](1,"",n.context.$implicit.key,""),e["\u0275nov"](n,6).ngClassUntouched,e["\u0275nov"](n,6).ngClassTouched,e["\u0275nov"](n,6).ngClassPristine,e["\u0275nov"](n,6).ngClassDirty,e["\u0275nov"](n,6).ngClassValid,e["\u0275nov"](n,6).ngClassInvalid,e["\u0275nov"](n,6).ngClassPending),l(n,8,0,e["\u0275inlineInterpolate"](1,"",n.context.$implicit.key,"")),l(n,9,0,n.context.$implicit.desc)})}function mu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"a",[["class","pull-right margin-right-md"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=0!=(l.component.advancedEnabled=!0)&&e),e},null,null)),(l()(),e["\u0275ted"](-1,null,["Advanced..."]))],null,null)}function vu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{value:[0,"value"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),e["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function hu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function bu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](1,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{value:[0,"value"]},null),e["\u0275did"](2,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),e["\u0275ted"](3,null,["",""]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Cu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required because stripe count is defined!"]))],null,null)}function Ru(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Stripe unit is greater than object size."]))],null,null)}function Iu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function wu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required because stripe unit is defined!"]))],null,null)}function Tu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Stripe count must be greater than 0."]))],null,null)}function yu(l){return e["\u0275vid"](0,[e["\u0275pid"](0,_.TitleCasePipe,[]),e["\u0275pid"](0,H.a,[]),(l()(),e["\u0275eld"](2,0,null,null,177,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),e["\u0275eld"](3,0,null,null,176,"form",[["class","form-horizontal"],["name","rbdForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var t=!0;return"submit"===n&&(t=!1!==e["\u0275nov"](l,5).onSubmit(u)&&t),"reset"===n&&(t=!1!==e["\u0275nov"](l,5).onReset()&&t),t},null,null)),e["\u0275did"](4,16384,null,0,Z.D,[],null,null),e["\u0275did"](5,540672,[["formDir",4]],0,Z.l,[[8,null],[8,null]],{form:[0,"form"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.l]),e["\u0275did"](7,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](8,0,null,null,171,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),e["\u0275eld"](9,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),e["\u0275eld"](10,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),e["\u0275ted"](11,null,[""," ",""])),e["\u0275ppd"](12,1),e["\u0275ppd"](13,1),(l()(),e["\u0275eld"](14,0,null,null,156,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Gn)),e["\u0275did"](16,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](17,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](18,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](19,{"has-error":0}),(l()(),e["\u0275eld"](20,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),e["\u0275eld"](21,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Name"])),(l()(),e["\u0275eld"](23,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](24,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](25,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["placeholder","Name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,26)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,26).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,26)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,26)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](26,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](28,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](30,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](31,4210688,null,0,Fn.a,[e.ElementRef],null,null),e["\u0275did"](32,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Kn)),e["\u0275did"](34,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Hn)),e["\u0275did"](36,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](37,0,null,null,13,"div",[["class","form-group"]],null,[[null,"change"]],function(l,n,u){var e=!0;return"change"===n&&(e=!1!==l.component.onPoolChange(u.target.value)&&e),e},null,null)),e["\u0275did"](38,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](39,{"has-error":0}),(l()(),e["\u0275eld"](40,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","pool"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,[" Pool "])),(l()(),e["\u0275and"](16777216,null,null,1,null,Jn)),e["\u0275did"](43,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](44,0,null,null,6,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Zn)),e["\u0275did"](46,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,lu)),e["\u0275did"](48,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,nu)),e["\u0275did"](50,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](51,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](52,0,null,null,10,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](53,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),e["\u0275eld"](54,0,null,null,6,"input",[["formControlName","useDataPool"],["id","useDataPool"],["name","useDataPool"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0,a=l.component;return"change"===n&&(t=!1!==e["\u0275nov"](l,55).onChange(u.target.checked)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,55).onTouched()&&t),"change"===n&&(t=!1!==a.onUseDataPoolChange()&&t),t},null,null)),e["\u0275did"](55,16384,null,0,Z.c,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.c]),e["\u0275did"](57,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](59,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](60,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](61,0,null,null,1,"label",[["for","useDataPool"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Use a dedicated data pool"])),(l()(),e["\u0275and"](16777216,null,null,1,null,su)),e["\u0275did"](64,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](65,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](66,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](67,{"has-error":0}),(l()(),e["\u0275eld"](68,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","size"]],null,null,null,null,null)),(l()(),e["\u0275eld"](69,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Size"])),(l()(),e["\u0275eld"](71,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](72,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](73,0,null,null,7,"input",[["cdDimlessBinary",""],["class","form-control"],["defaultUnit","GiB"],["formControlName","size"],["id","size"],["name","size"],["placeholder","e.g., 10GiB"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,74)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,74).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,74)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,74)._compositionEnd(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,79).onBlur(u.target.value)&&t),t},null,null)),e["\u0275did"](74,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](76,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](78,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](79,81920,null,0,Pn.a,[e.ElementRef,Z.q,F.a,S.a],{defaultUnit:[0,"defaultUnit"]},null),e["\u0275did"](80,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,cu)),e["\u0275did"](82,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,pu)),e["\u0275did"](84,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](85,0,null,null,10,"div",[["class","form-group"],["formGroupName","features"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](86,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](87,{"has-error":0}),e["\u0275did"](88,212992,null,0,Z.m,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.m]),e["\u0275did"](90,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](91,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","features"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Features"])),(l()(),e["\u0275eld"](93,0,null,null,2,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,gu)),e["\u0275did"](95,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](96,0,null,null,3,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](97,0,null,null,2,"div",[["class","col-sm-12"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,mu)),e["\u0275did"](99,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](100,0,null,null,70,"div",[],[[8,"hidden",0]],null,null,null,null)),(l()(),e["\u0275eld"](101,0,null,null,1,"h2",[["class","page-header"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Advanced"])),(l()(),e["\u0275eld"](103,0,null,null,64,"div",[["class","section"]],null,null,null,null,null)),(l()(),e["\u0275eld"](104,0,null,null,1,"h3",[["class","page-header"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Striping"])),(l()(),e["\u0275eld"](106,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](107,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](108,{"has-error":0}),(l()(),e["\u0275eld"](109,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","size"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Object size"])),(l()(),e["\u0275eld"](111,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](112,0,null,null,8,"select",[["class","form-control"],["formControlName","obj_size"],["id","obj_size"],["name","obj_size"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0;return"change"===n&&(t=!1!==e["\u0275nov"](l,113).onChange(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,113).onTouched()&&t),t},null,null)),e["\u0275did"](113,16384,null,0,Z.z,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.z]),e["\u0275did"](115,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](117,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](118,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,vu)),e["\u0275did"](120,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](121,0,null,null,25,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](122,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](123,{"has-error":0}),(l()(),e["\u0275eld"](124,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","stripingUnit"]],null,null,null,null,null)),(l()(),e["\u0275eld"](125,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Stripe unit"])),(l()(),e["\u0275and"](16777216,null,null,1,null,hu)),e["\u0275did"](128,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](129,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](130,0,null,null,12,"select",[["class","form-control"],["formControlName","stripingUnit"],["id","stripingUnit"],["name","stripingUnit"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0;return"change"===n&&(t=!1!==e["\u0275nov"](l,131).onChange(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,131).onTouched()&&t),t},null,null)),e["\u0275did"](131,16384,null,0,Z.z,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.z]),e["\u0275did"](133,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](135,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](136,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](137,0,null,null,3,"option",[],null,null,null,null,null)),e["\u0275did"](138,147456,null,0,Z.v,[e.ElementRef,e.Renderer2,[2,Z.z]],{ngValue:[0,"ngValue"]},null),e["\u0275did"](139,147456,null,0,Z.G,[e.ElementRef,e.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),e["\u0275ted"](-1,null,["-- Select stripe unit --"])),(l()(),e["\u0275and"](16777216,null,null,1,null,bu)),e["\u0275did"](142,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Cu)),e["\u0275did"](144,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ru)),e["\u0275did"](146,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](147,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](148,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](149,{"has-error":0}),(l()(),e["\u0275eld"](150,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","stripingCount"]],null,null,null,null,null)),(l()(),e["\u0275eld"](151,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Stripe count"])),(l()(),e["\u0275and"](16777216,null,null,1,null,Iu)),e["\u0275did"](154,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](155,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](156,0,null,null,7,"input",[["class","form-control"],["formControlName","stripingCount"],["id","stripingCount"],["name","stripingCount"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,157)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,157).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,157)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,157)._compositionEnd(u.target.value)&&t),"change"===n&&(t=!1!==e["\u0275nov"](l,158).onChange(u.target.value)&&t),"input"===n&&(t=!1!==e["\u0275nov"](l,158).onChange(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,158).onTouched()&&t),t},null,null)),e["\u0275did"](157,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275did"](158,16384,null,0,Z.C,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l,n){return[l,n]},[Z.e,Z.C]),e["\u0275did"](160,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](162,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](163,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,wu)),e["\u0275did"](165,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Tu)),e["\u0275did"](167,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](168,0,null,null,2,"div",[["class","section"]],null,null,null,null,null)),(l()(),e["\u0275eld"](169,0,null,null,1,"cd-rbd-configuration-form",[],null,[[null,"changes"]],function(l,n,u){var e=!0;return"changes"===n&&(e=!1!==(l.component.getDirtyConfigurationValues=u)&&e),e},qn.b,qn.a)),e["\u0275did"](170,114688,null,0,jn.a,[S.a,On.a],{form:[0,"form"],initializeData:[1,"initializeData"]},{changes:"changes"}),(l()(),e["\u0275eld"](171,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),e["\u0275eld"](172,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),e["\u0275eld"](173,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.submit()&&e),e},An.b,An.a)),e["\u0275did"](174,114688,null,0,Un.a,[e.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),e["\u0275ted"](175,0,[""," ",""])),e["\u0275ppd"](176,1),e["\u0275ppd"](177,1),(l()(),e["\u0275eld"](178,0,null,null,1,"cd-back-button",[],null,null,null,$n.b,$n.a)),e["\u0275did"](179,49152,null,0,Mn.a,[_.Location,Gl.b],null,null)],function(l,n){var u=n.component;l(n,5,0,u.rbdForm),l(n,16,0,u.rbdForm.getValue("parent"));var t=l(n,19,0,u.rbdForm.showError("name",e["\u0275nov"](n,5)));l(n,18,0,"form-group",t),l(n,28,0,"name"),l(n,34,0,u.rbdForm.showError("name",e["\u0275nov"](n,5),"required")),l(n,36,0,u.rbdForm.showError("name",e["\u0275nov"](n,5),"pattern"));var a=l(n,39,0,u.rbdForm.showError("pool",e["\u0275nov"](n,5)));l(n,38,0,"form-group",a),l(n,43,0,"editing"!==u.mode),l(n,46,0,"editing"===u.mode||!u.poolPermission.read),l(n,48,0,"editing"!==u.mode&&u.poolPermission.read),l(n,50,0,u.rbdForm.showError("pool",e["\u0275nov"](n,5),"required")),l(n,57,0,"useDataPool"),l(n,64,0,u.rbdForm.getValue("useDataPool"));var o=l(n,67,0,u.rbdForm.showError("size",e["\u0275nov"](n,5)));l(n,66,0,"form-group",o),l(n,76,0,"size"),l(n,79,0,"GiB"),l(n,82,0,u.rbdForm.showError("size",e["\u0275nov"](n,5),"required")),l(n,84,0,u.rbdForm.showError("size",e["\u0275nov"](n,5),"invalidSizeObject"));var i=l(n,87,0,(e["\u0275nov"](n,5).submitted||u.rbdForm.get("features").dirty)&&u.rbdForm.get("features").invalid);l(n,86,0,"form-group",i),l(n,88,0,"features"),l(n,95,0,u.featuresList),l(n,99,0,!u.advancedEnabled);var r=l(n,108,0,u.rbdForm.showError("obj_size",e["\u0275nov"](n,5)));l(n,107,0,"form-group",r),l(n,115,0,"obj_size"),l(n,120,0,u.objectSizes);var d=l(n,123,0,u.rbdForm.showError("stripingUnit",e["\u0275nov"](n,5)));l(n,122,0,"form-group",d),l(n,128,0,u.rbdForm.getValue("stripingCount")),l(n,133,0,"stripingUnit"),l(n,138,0,null),l(n,139,0,null),l(n,142,0,u.objectSizes),l(n,144,0,u.rbdForm.showError("stripingUnit",e["\u0275nov"](n,5),"required")),l(n,146,0,u.rbdForm.showError("stripingUnit",e["\u0275nov"](n,5),"invalidStripingUnit"));var s=l(n,149,0,u.rbdForm.showError("stripingCount",e["\u0275nov"](n,5)));l(n,148,0,"form-group",s),l(n,154,0,u.rbdForm.getValue("stripingUnit")),l(n,160,0,"stripingCount"),l(n,165,0,u.rbdForm.showError("stripingCount",e["\u0275nov"](n,5),"required")),l(n,167,0,u.rbdForm.showError("stripingCount",e["\u0275nov"](n,5),"min")),l(n,170,0,u.rbdForm,u.initializeConfigData),l(n,174,0,e["\u0275nov"](n,5),"button")},function(l,n){var u=n.component;l(n,3,0,e["\u0275nov"](n,7).ngClassUntouched,e["\u0275nov"](n,7).ngClassTouched,e["\u0275nov"](n,7).ngClassPristine,e["\u0275nov"](n,7).ngClassDirty,e["\u0275nov"](n,7).ngClassValid,e["\u0275nov"](n,7).ngClassInvalid,e["\u0275nov"](n,7).ngClassPending);var t=e["\u0275unv"](n,11,0,l(n,12,0,e["\u0275nov"](n,0),u.action)),a=e["\u0275unv"](n,11,1,l(n,13,0,e["\u0275nov"](n,1),u.resource));l(n,11,0,t,a),l(n,25,0,e["\u0275nov"](n,30).ngClassUntouched,e["\u0275nov"](n,30).ngClassTouched,e["\u0275nov"](n,30).ngClassPristine,e["\u0275nov"](n,30).ngClassDirty,e["\u0275nov"](n,30).ngClassValid,e["\u0275nov"](n,30).ngClassInvalid,e["\u0275nov"](n,30).ngClassPending),l(n,54,0,e["\u0275nov"](n,59).ngClassUntouched,e["\u0275nov"](n,59).ngClassTouched,e["\u0275nov"](n,59).ngClassPristine,e["\u0275nov"](n,59).ngClassDirty,e["\u0275nov"](n,59).ngClassValid,e["\u0275nov"](n,59).ngClassInvalid,e["\u0275nov"](n,59).ngClassPending),l(n,73,0,e["\u0275nov"](n,78).ngClassUntouched,e["\u0275nov"](n,78).ngClassTouched,e["\u0275nov"](n,78).ngClassPristine,e["\u0275nov"](n,78).ngClassDirty,e["\u0275nov"](n,78).ngClassValid,e["\u0275nov"](n,78).ngClassInvalid,e["\u0275nov"](n,78).ngClassPending),l(n,85,0,e["\u0275nov"](n,90).ngClassUntouched,e["\u0275nov"](n,90).ngClassTouched,e["\u0275nov"](n,90).ngClassPristine,e["\u0275nov"](n,90).ngClassDirty,e["\u0275nov"](n,90).ngClassValid,e["\u0275nov"](n,90).ngClassInvalid,e["\u0275nov"](n,90).ngClassPending),l(n,100,0,!u.advancedEnabled),l(n,112,0,e["\u0275nov"](n,117).ngClassUntouched,e["\u0275nov"](n,117).ngClassTouched,e["\u0275nov"](n,117).ngClassPristine,e["\u0275nov"](n,117).ngClassDirty,e["\u0275nov"](n,117).ngClassValid,e["\u0275nov"](n,117).ngClassInvalid,e["\u0275nov"](n,117).ngClassPending),l(n,130,0,e["\u0275nov"](n,135).ngClassUntouched,e["\u0275nov"](n,135).ngClassTouched,e["\u0275nov"](n,135).ngClassPristine,e["\u0275nov"](n,135).ngClassDirty,e["\u0275nov"](n,135).ngClassValid,e["\u0275nov"](n,135).ngClassInvalid,e["\u0275nov"](n,135).ngClassPending),l(n,156,0,e["\u0275nov"](n,162).ngClassUntouched,e["\u0275nov"](n,162).ngClassTouched,e["\u0275nov"](n,162).ngClassPristine,e["\u0275nov"](n,162).ngClassDirty,e["\u0275nov"](n,162).ngClassValid,e["\u0275nov"](n,162).ngClassInvalid,e["\u0275nov"](n,162).ngClassPending);var o=e["\u0275unv"](n,175,0,l(n,176,0,e["\u0275nov"](n,0),u.action)),i=e["\u0275unv"](n,175,1,l(n,177,0,e["\u0275nov"](n,1),u.resource));l(n,175,0,o,i)})}function ku(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-rbd-form",[],null,null,null,yu,Ln)),e["\u0275did"](1,114688,null,0,zn.a,[il.a,dl.a,Bn.a,zl.a,S.a,Wl.a,F.a,V.a,Gl.b,dl.l],null,null)],function(l,n){l(n,1,0)},null)}var Eu=e["\u0275ccf"]("cd-rbd-form",zn.a,ku,{},{},[]),_u=u("JxMD"),xu=u("dgut"),Vu=function(){function l(l){this.router=l}return l.prototype.ngOnInit=function(){this.url=this.router.url},l.prototype.navigateTo=function(l){this.router.navigate([l])},l}(),Nu=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Du(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,Nl.b,Nl.a)),e["\u0275did"](1,180224,null,0,fl.d,[fl.e,e.Renderer2,e.ElementRef],null,null),(l()(),e["\u0275eld"](2,0,null,0,1,"tab",[["heading","Overview"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(l,n,u){var e=!0;return"selectTab"===n&&(e=!1!==l.component.navigateTo("/block/iscsi/overview")&&e),e},null,null)),e["\u0275did"](3,212992,null,0,fl.b,[fl.d,e.ElementRef,e.Renderer2],{heading:[0,"heading"],active:[1,"active"]},{selectTab:"selectTab"}),(l()(),e["\u0275eld"](4,0,null,0,1,"tab",[["heading","Targets"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(l,n,u){var e=!0;return"selectTab"===n&&(e=!1!==l.component.navigateTo("/block/iscsi/targets")&&e),e},null,null)),e["\u0275did"](5,212992,null,0,fl.b,[fl.d,e.ElementRef,e.Renderer2],{heading:[0,"heading"],active:[1,"active"]},{selectTab:"selectTab"})],function(l,n){var u=n.component;l(n,3,0,"Overview","/block/iscsi/overview"===u.url),l(n,5,0,"Targets","/block/iscsi/targets"===u.url)},function(l,n){l(n,0,0,e["\u0275nov"](n,1).clazz),l(n,2,0,e["\u0275nov"](n,3).id,e["\u0275nov"](n,3).active,e["\u0275nov"](n,3).addClass),l(n,4,0,e["\u0275nov"](n,5).id,e["\u0275nov"](n,5).active,e["\u0275nov"](n,5).addClass)})}var Su=u("roDX"),Fu=u("my5R"),Pu=e["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function qu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,3,"span",[["class","label"]],null,null,null,null,null)),e["\u0275did"](1,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](2,{"label-success":0,"label-danger":1}),(l()(),e["\u0275ted"](3,null,["",""]))],function(l,n){var u=l(n,2,0,"up"==n.context.value,"down"==n.context.value);l(n,1,0,"label",u)},function(l,n){l(n,3,0,n.context.value)})}function ju(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,1,"cd-sparkline",[],null,null,null,_u.b,_u.a)),e["\u0275did"](2,638976,null,0,xu.a,[F.a],{data:[0,"data"],isBinary:[1,"isBinary"]},null)],function(l,n){l(n,2,0,n.parent.context.value,n.parent.context.row.cdIsBinary)},null)}function Ou(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,[" n/a "]))],null,null)}function Au(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,ju)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ou)),e["\u0275did"](3,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,"user:rbd"===n.context.row.backstore),l(n,3,0,"user:rbd"!==n.context.row.backstore)},null)}function Uu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,[" "," /s "]))],null,function(l,n){l(n,1,0,n.parent.context.value)})}function $u(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,[" n/a "]))],null,null)}function Mu(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,Uu)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,$u)),e["\u0275did"](3,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,"user:rbd"===n.context.row.backstore),l(n,3,0,"user:rbd"!==n.context.row.backstore)},null)}function zu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,[" "," "])),e["\u0275ppd"](2,1)],null,function(l,n){var u=e["\u0275unv"](n,1,0,l(n,2,0,e["\u0275nov"](n.parent.parent,0),n.parent.context.value));l(n,1,0,u)})}function Bu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,[" n/a "]))],null,null)}function Lu(l){return e["\u0275vid"](0,[(l()(),e["\u0275and"](16777216,null,null,1,null,zu)),e["\u0275did"](1,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Bu)),e["\u0275did"](3,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,"user:rbd"===n.context.row.backstore),l(n,3,0,"user:rbd"!==n.context.row.backstore)},null)}function Gu(l){return e["\u0275vid"](0,[e["\u0275pid"](0,j.a,[]),e["\u0275qud"](402653184,1,{statusColorTpl:0}),e["\u0275qud"](402653184,2,{iscsiSparklineTpl:0}),e["\u0275qud"](402653184,3,{iscsiPerSecondTpl:0}),e["\u0275qud"](402653184,4,{iscsiRelativeDateTpl:0}),(l()(),e["\u0275eld"](5,0,null,null,1,"cd-iscsi-tabs",[],null,null,null,Du,Nu)),e["\u0275did"](6,114688,null,0,Vu,[dl.l],null,null),(l()(),e["\u0275eld"](7,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Gateways"])),(l()(),e["\u0275eld"](9,0,null,null,1,"cd-table",[],null,[[null,"fetchData"]],function(l,n,u){var e=!0;return"fetchData"===n&&(e=!1!==l.component.refresh()&&e),e},Fl.b,Fl.a)),e["\u0275did"](10,2867200,null,0,Pl.a,[e.NgZone,e.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"]},{fetchData:"fetchData"}),(l()(),e["\u0275eld"](11,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Images"])),(l()(),e["\u0275eld"](13,0,null,null,1,"cd-table",[],null,null,null,Fl.b,Fl.a)),e["\u0275did"](14,2867200,null,0,Pl.a,[e.NgZone,e.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"]},null),(l()(),e["\u0275and"](0,[[1,2],["statusColorTpl",2]],null,0,null,qu)),(l()(),e["\u0275and"](0,[[2,2],["iscsiSparklineTpl",2]],null,0,null,Au)),(l()(),e["\u0275and"](0,[[3,2],["iscsiPerSecondTpl",2]],null,0,null,Mu)),(l()(),e["\u0275and"](0,[[4,2],["iscsiRelativeDateTpl",2]],null,0,null,Lu))],function(l,n){var u=n.component;l(n,6,0),l(n,10,0,u.gateways,u.gatewaysColumns),l(n,14,0,u.images,u.imagesColumns)},null)}function Ku(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-iscsi",[],null,null,null,Gu,Pu)),e["\u0275did"](1,114688,null,0,Su.a,[Fu.a,q.a,O.a,V.a],null,null)],function(l,n){l(n,1,0)},null)}var Hu=e["\u0275ccf"]("cd-iscsi",Su.a,Ku,{},{},[]),Ju=u("TZo1"),Zu=u("9Kw/"),Wu=u("3ris"),Qu=u("e/kN"),Yu=e["\u0275crt"]({encapsulation:0,styles:[["tabset.tabset>ul{border-bottom:0;float:left;display:block;margin-right:20px;border-right:1px solid #ddd;padding-right:15px}"]],data:{}});function Xu(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,5,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Available information:"])),(l()(),e["\u0275eld"](4,0,null,null,1,"pre",[],null,null,null,null,null)),(l()(),e["\u0275ted"](5,null,["",""]))],null,function(l,n){l(n,5,0,n.component.status)})}function le(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,8,"cd-info-panel",[["title","iSCSI Targets not available"]],null,null,null,Ju.b,Ju.a)),e["\u0275did"](1,49152,null,0,Zu.a,[V.a],{title:[0,"title"]},null),(l()(),e["\u0275eld"](2,0,null,0,4,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Please consult the "])),(l()(),e["\u0275eld"](4,0,null,null,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["documentation"])),(l()(),e["\u0275ted"](-1,null,[" on how to configure and enable the iSCSI Targets management functionality."])),(l()(),e["\u0275and"](16777216,null,0,1,null,Xu)),e["\u0275did"](8,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,1,0,"iSCSI Targets not available"),l(n,8,0,u.status)},function(l,n){l(n,4,0,e["\u0275inlineInterpolate"](1,"",n.component.docsUrl,""))})}function ne(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-details",[["cdTableDetail",""]],null,null,null,T.c,T.b)),e["\u0275did"](1,638976,null,0,Wu.a,[V.a,O.a,x.a],{selection:[0,"selection"],settings:[1,"settings"],cephIscsiConfigVersion:[2,"cephIscsiConfigVersion"]},null)],function(l,n){var u=n.component;l(n,1,0,u.selection,u.settings,u.cephIscsiConfigVersion)},null)}function ue(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,10,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","target_iqn"],["selectionType","single"]],null,[[null,"updateSelection"]],function(l,n,u){var e=!0;return"updateSelection"===n&&(e=!1!==l.component.updateSelection(u)&&e),e},Fl.b,Fl.a)),e["\u0275did"](1,2867200,[[1,4],["table",4]],0,Pl.a,[e.NgZone,e.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"]},{updateSelection:"updateSelection"}),(l()(),e["\u0275eld"](2,0,null,0,6,"div",[["class","table-actions btn-toolbar"]],null,null,null,null,null)),(l()(),e["\u0275eld"](3,0,null,null,1,"cd-table-actions",[["class","btn-group"]],null,null,null,ql.b,ql.a)),e["\u0275did"](4,114688,null,0,jl.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),e["\u0275eld"](5,0,null,null,3,"button",[["class","btn btn-sm btn-default btn-label"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.configureDiscoveryAuth()&&e),e},null,null)),(l()(),e["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-fw fa-key-modern"]],null,null,null,null,null)),(l()(),e["\u0275eld"](7,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Discovery authentication"])),(l()(),e["\u0275and"](16777216,null,2,1,null,ne)),e["\u0275did"](10,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,1,0,u.targets,u.columns,"flex","target_iqn","true","single"),l(n,4,0,u.permissions.iscsi,u.selection,u.tableActions),l(n,10,0,u.selection.hasSingleSelection)},null)}function ee(l){return e["\u0275vid"](0,[e["\u0275qud"](671088640,1,{table:0}),(l()(),e["\u0275eld"](1,0,null,null,1,"cd-iscsi-tabs",[],null,null,null,Du,Nu)),e["\u0275did"](2,114688,null,0,Vu,[dl.l],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,le)),e["\u0275did"](4,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ue)),e["\u0275did"](6,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,2,0),l(n,4,0,!1===u.available),l(n,6,0,!0===u.available)},null)}function te(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,"cd-iscsi-target-list",[],null,null,null,ee,Yu)),e["\u0275prd"](131584,null,Al.a,Al.a,[Ul.a,xl.a]),e["\u0275did"](2,245760,null,0,Qu.a,[il.a,V.a,Fu.a,A.a,Al.a,D.a,K.a,xl.a,nl.b,Wl.a,Gl.b],null,null)],function(l,n){l(n,2,0)},null)}var ae=e["\u0275ccf"]("cd-iscsi-target-list",Qu.a,te,{},{},[]),oe=u("D4zM"),ie=u("OcYo"),re=u("SZbH"),de=u("WiuZ"),se=u("wnGv"),ce=function(){function l(l){this.ngControl=l}return l.prototype.onInput=function(l){this.setValue(l)},l.prototype.setValue=function(l){l=Ml.isString(l)?l.trim():l,this.ngControl.control.setValue(l)},l}(),pe=u("gr3l"),fe=e["\u0275crt"]({encapsulation:0,styles:[[".cd-mb[_ngcontent-%COMP%]{margin-bottom:10px}"]],data:{}});function ge(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function me(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["IQN has wrong pattern."]))],null,null)}function ve(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,8,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'"])),(l()(),e["\u0275eld"](3,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),e["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309"])),(l()(),e["\u0275eld"](6,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),e["\u0275eld"](7,0,null,null,1,"a",[["href","https://en.wikipedia.org/wiki/ISCSI#Addressing"],["target","_blank"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["More information"]))],null,null)}function he(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This target has modified advanced settings."]))],null,null)}function be(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,5,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),e["\u0275did"](3,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](4,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removePortal(l.context.index,l.context.$implicit)&&e),e},null,null)),(l()(),e["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null))],null,function(l,n){l(n,2,0,n.context.$implicit)})}function Ce(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,["At least "," gateways are required."]))],null,function(l,n){l(n,1,0,n.component.minimum_gateways)})}function Re(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"div",[["class","input-group-addon"]],null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,["lun: ",""]))],null,function(l,n){l(n,1,0,n.component.imagesSettings[n.parent.context.$implicit].lun)})}function Ie(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,2,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](1,null,["Backstore: ",".\xa0"])),e["\u0275ppd"](2,1)],null,function(l,n){var u=n.component,t=e["\u0275unv"](n,1,0,l(n,2,0,e["\u0275nov"](n.parent.parent.parent,2),u.imagesSettings[n.parent.context.$implicit].backstore));l(n,1,0,t)})}function we(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This image has modified settings."]))],null,null)}function Te(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,15,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,9,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),e["\u0275did"](3,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Re)),e["\u0275did"](5,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](6,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](7,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.imageSettingsModal(l.context.$implicit)&&e),e},null,null)),(l()(),e["\u0275eld"](8,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-cogs fa-fw"]],null,null,null,null,null)),(l()(),e["\u0275eld"](9,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removeImage(l.context.index,l.context.$implicit)&&e),e},null,null)),(l()(),e["\u0275eld"](10,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null)),(l()(),e["\u0275eld"](11,0,null,null,4,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Ie)),e["\u0275did"](13,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,we)),e["\u0275did"](15,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,5,0,u.api_version>=1),l(n,13,0,u.backstores.length>1),l(n,15,0,u.hasAdvancedSettings(u.imagesSettings[n.context.$implicit][u.imagesSettings[n.context.$implicit].backstore]))},function(l,n){l(n,2,0,n.context.$implicit)})}function ye(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Duplicated LUN numbers."]))],null,null)}function ke(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Duplicated WWN."]))],null,null)}function Ee(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function _e(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function xe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Ve(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function Ne(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function De(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function Se(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Fe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function Pe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,87,"div",[["formGroupName","auth"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](1,212992,null,0,Z.m,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.m]),e["\u0275did"](3,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](4,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](5,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](6,{"has-error":0}),(l()(),e["\u0275eld"](7,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","target_user"]],null,null,null,null,null)),(l()(),e["\u0275eld"](8,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["User"])),(l()(),e["\u0275eld"](10,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](11,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","user"],["id","target_user"],["name","target_user"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,12)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,12).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,12)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,12)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](12,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](14,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](16,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](17,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ee)),e["\u0275did"](19,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,_e)),e["\u0275did"](21,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](22,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](23,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](24,{"has-error":0}),(l()(),e["\u0275eld"](25,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","target_password"]],null,null,null,null,null)),(l()(),e["\u0275eld"](26,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Password"])),(l()(),e["\u0275eld"](28,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](29,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](30,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","password"],["id","target_password"],["name","target_password"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,31)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,31).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,31)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,31)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](31,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](33,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](35,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](36,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](37,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](38,0,null,null,1,"button",[["cdPasswordButton","target_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,39).onClick()&&t),t},null,null)),e["\u0275did"](39,81920,null,0,oe.a,[e.ElementRef,e.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),e["\u0275eld"](40,0,null,null,1,"button",[["cdCopy2ClipboardButton","target_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,41).onClick()&&t),t},null,null)),e["\u0275did"](41,81920,null,0,ie.a,[e.ElementRef,e.Renderer2,re.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,xe)),e["\u0275did"](43,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ve)),e["\u0275did"](45,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](46,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](47,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](48,{"has-error":0}),(l()(),e["\u0275eld"](49,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","target_mutual_user"]],null,null,null,null,null)),(l()(),e["\u0275eld"](50,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Mutual User"])),(l()(),e["\u0275eld"](52,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](53,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","mutual_user"],["id","target_mutual_user"],["name","target_mutual_user"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,54)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,54).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,54)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,54)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](54,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](56,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](58,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](59,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ne)),e["\u0275did"](61,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,De)),e["\u0275did"](63,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](64,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](65,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](66,{"has-error":0}),(l()(),e["\u0275eld"](67,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","target_mutual_password"]],null,null,null,null,null)),(l()(),e["\u0275eld"](68,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Mutual Password"])),(l()(),e["\u0275eld"](70,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](71,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](72,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","mutual_password"],["id","target_mutual_password"],["name","target_mutual_password"],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,73)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,73).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,73)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,73)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](73,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](75,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](77,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](78,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](79,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](80,0,null,null,1,"button",[["cdPasswordButton","target_mutual_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,81).onClick()&&t),t},null,null)),e["\u0275did"](81,81920,null,0,oe.a,[e.ElementRef,e.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),e["\u0275eld"](82,0,null,null,1,"button",[["cdCopy2ClipboardButton","target_mutual_password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,83).onClick()&&t),t},null,null)),e["\u0275did"](83,81920,null,0,ie.a,[e.ElementRef,e.Renderer2,re.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Se)),e["\u0275did"](85,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Fe)),e["\u0275did"](87,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var u=n.component;l(n,1,0,"auth");var t=l(n,6,0,u.targetForm.showError("user",e["\u0275nov"](n.parent,2)));l(n,5,0,"form-group",t),l(n,14,0,"user"),l(n,19,0,u.targetForm.showError("user",e["\u0275nov"](n.parent,2),"required")),l(n,21,0,u.targetForm.showError("user",e["\u0275nov"](n.parent,2),"pattern"));var a=l(n,24,0,u.targetForm.showError("password",e["\u0275nov"](n.parent,2)));l(n,23,0,"form-group",a),l(n,33,0,"password"),l(n,39,0,"target_password"),l(n,41,0,"target_password"),l(n,43,0,u.targetForm.showError("password",e["\u0275nov"](n.parent,2),"required")),l(n,45,0,u.targetForm.showError("password",e["\u0275nov"](n.parent,2),"pattern"));var o=l(n,48,0,u.targetForm.showError("mutual_user",e["\u0275nov"](n.parent,2)));l(n,47,0,"form-group",o),l(n,56,0,"mutual_user"),l(n,61,0,u.targetForm.showError("mutual_user",e["\u0275nov"](n.parent,2),"required")),l(n,63,0,u.targetForm.showError("mutual_user",e["\u0275nov"](n.parent,2),"pattern"));var i=l(n,66,0,u.targetForm.showError("mutual_password",e["\u0275nov"](n.parent,2)));l(n,65,0,"form-group",i),l(n,75,0,"mutual_password"),l(n,81,0,"target_mutual_password"),l(n,83,0,"target_mutual_password"),l(n,85,0,u.targetForm.showError("mutual_password",e["\u0275nov"](n.parent,2),"required")),l(n,87,0,u.targetForm.showError("mutual_password",e["\u0275nov"](n.parent,2),"pattern"))},function(l,n){l(n,0,0,e["\u0275nov"](n,3).ngClassUntouched,e["\u0275nov"](n,3).ngClassTouched,e["\u0275nov"](n,3).ngClassPristine,e["\u0275nov"](n,3).ngClassDirty,e["\u0275nov"](n,3).ngClassValid,e["\u0275nov"](n,3).ngClassInvalid,e["\u0275nov"](n,3).ngClassPending),l(n,11,0,e["\u0275nov"](n,16).ngClassUntouched,e["\u0275nov"](n,16).ngClassTouched,e["\u0275nov"](n,16).ngClassPristine,e["\u0275nov"](n,16).ngClassDirty,e["\u0275nov"](n,16).ngClassValid,e["\u0275nov"](n,16).ngClassInvalid,e["\u0275nov"](n,16).ngClassPending),l(n,30,0,e["\u0275nov"](n,35).ngClassUntouched,e["\u0275nov"](n,35).ngClassTouched,e["\u0275nov"](n,35).ngClassPristine,e["\u0275nov"](n,35).ngClassDirty,e["\u0275nov"](n,35).ngClassValid,e["\u0275nov"](n,35).ngClassInvalid,e["\u0275nov"](n,35).ngClassPending),l(n,53,0,e["\u0275nov"](n,58).ngClassUntouched,e["\u0275nov"](n,58).ngClassTouched,e["\u0275nov"](n,58).ngClassPristine,e["\u0275nov"](n,58).ngClassDirty,e["\u0275nov"](n,58).ngClassValid,e["\u0275nov"](n,58).ngClassInvalid,e["\u0275nov"](n,58).ngClassPending),l(n,72,0,e["\u0275nov"](n,77).ngClassUntouched,e["\u0275nov"](n,77).ngClassTouched,e["\u0275nov"](n,77).ngClassPristine,e["\u0275nov"](n,77).ngClassDirty,e["\u0275nov"](n,77).ngClassValid,e["\u0275nov"](n,77).ngClassInvalid,e["\u0275nov"](n,77).ngClassPending)})}function qe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Initiator IQN needs to be unique."]))],null,null)}function je(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Oe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["IQN has wrong pattern."]))],null,null)}function Ae(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Ue(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function $e(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Me(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function ze(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Be(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Usernames must have a length of 8 to 64 characters and can only contain letters, '.', '@', '-', '_' or ':'."]))],null,null)}function Le(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Ge(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Passwords must have a length of 12 to 16 characters and can only contain letters, '@', '-', '_' or '/'."]))],null,null)}function Ke(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,5,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),e["\u0275did"](3,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](4,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removeInitiatorImage(l.parent.context.$implicit,l.context.index,l.parent.context.index,l.context.$implicit)&&e),e},null,null)),(l()(),e["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null))],null,function(l,n){l(n,2,0,n.context.$implicit)})}function He(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Initiator belongs to a group. Images will be configure in the group."]))],null,null)}function Je(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,null,null,de.b,de.a)),e["\u0275did"](3,638976,null,0,se.a,[V.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},null),(l()(),e["\u0275eld"](4,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,0,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add image"]))],function(l,n){var u=n.component,e=n.parent.context.$implicit.getValue("luns");l(n,3,0,"btn btn-default pull-right",e,u.imagesInitiatorSelections[n.parent.context.index],u.messages.initiatorImage)},null)}function Ze(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,129,"div",[["class","panel panel-default"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](1,212992,null,0,Z.m,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.m]),e["\u0275did"](3,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](4,0,null,null,5,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Initiator"])),(l()(),e["\u0275ted"](7,null,[": "," "])),(l()(),e["\u0275eld"](8,0,null,null,1,"button",[["class","close"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removeInitiator(l.context.index)&&e),e},null,null)),(l()(),e["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-remove fa-fw"]],null,null,null,null,null)),(l()(),e["\u0275eld"](10,0,null,null,119,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),e["\u0275eld"](11,0,null,null,21,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](12,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](13,{"has-error":0}),(l()(),e["\u0275eld"](14,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","client_iqn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](15,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Client IQN"])),(l()(),e["\u0275eld"](17,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](18,0,null,null,14,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](19,0,null,null,7,"input",[["cdTrim",""],["class","form-control"],["formControlName","client_iqn"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"blur"],[null,"input"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0,a=l.component;return"input"===n&&(t=!1!==e["\u0275nov"](l,20)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,20).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,20)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,20)._compositionEnd(u.target.value)&&t),"input"===n&&(t=!1!==e["\u0275nov"](l,25).onInput(u.target.value)&&t),"blur"===n&&(t=!1!==a.updatedInitiatorSelector()&&t),t},null,null)),e["\u0275did"](20,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](22,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](24,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](25,16384,null,0,ce,[Z.q],null,null),e["\u0275did"](26,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,qe)),e["\u0275did"](28,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,je)),e["\u0275did"](30,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Oe)),e["\u0275did"](32,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](33,0,null,null,84,null,null,null,null,null,null,null)),e["\u0275did"](34,212992,null,0,Z.m,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.m]),e["\u0275did"](36,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](37,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](38,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](39,{"has-error":0}),(l()(),e["\u0275eld"](40,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","user"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["User"])),(l()(),e["\u0275eld"](42,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](43,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","user"],["type","text"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,44)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,44).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,44)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,44)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](44,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](46,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](48,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](49,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ae)),e["\u0275did"](51,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ue)),e["\u0275did"](53,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](54,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](55,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](56,{"has-error":0}),(l()(),e["\u0275eld"](57,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","password"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Password"])),(l()(),e["\u0275eld"](59,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](60,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](61,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","password"],["type","password"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,62)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,62).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,62)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,62)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](62,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](64,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](66,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](67,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](68,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](69,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,70).onClick()&&t),t},null,null)),e["\u0275did"](70,81920,null,0,oe.a,[e.ElementRef,e.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),e["\u0275eld"](71,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,72).onClick()&&t),t},null,null)),e["\u0275did"](72,81920,null,0,ie.a,[e.ElementRef,e.Renderer2,re.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,$e)),e["\u0275did"](74,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Me)),e["\u0275did"](76,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](77,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](78,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](79,{"has-error":0}),(l()(),e["\u0275eld"](80,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","mutual_user"]],null,null,null,null,null)),(l()(),e["\u0275eld"](81,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Mutual User"])),(l()(),e["\u0275eld"](83,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](84,0,null,null,6,"input",[["autocomplete","off"],["class","form-control"],["formControlName","mutual_user"],["type","text"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,85)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,85).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,85)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,85)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](85,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](87,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](89,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](90,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,ze)),e["\u0275did"](92,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Be)),e["\u0275did"](94,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](95,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](96,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](97,{"has-error":0}),(l()(),e["\u0275eld"](98,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","mutual_password"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Mutual Password"])),(l()(),e["\u0275eld"](100,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](101,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](102,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","mutual_password"],["type","password"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,103)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,103).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,103)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,103)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](103,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](105,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](107,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](108,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](109,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](110,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,111).onClick()&&t),t},null,null)),e["\u0275did"](111,81920,null,0,oe.a,[e.ElementRef,e.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),e["\u0275eld"](112,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var t=!0;return"click"===n&&(t=!1!==e["\u0275nov"](l,113).onClick()&&t),t},null,null)),e["\u0275did"](113,81920,null,0,ie.a,[e.ElementRef,e.Renderer2,re.j],{cdCopy2ClipboardButton:[0,"cdCopy2ClipboardButton"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Le)),e["\u0275did"](115,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ge)),e["\u0275did"](117,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](118,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](119,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](120,{"has-error":0}),(l()(),e["\u0275eld"](121,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","luns"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Images"])),(l()(),e["\u0275eld"](123,0,null,null,6,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Ke)),e["\u0275did"](125,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,He)),e["\u0275did"](127,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Je)),e["\u0275did"](129,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,1,0,n.context.index);var u=l(n,13,0,n.context.$implicit.showError("client_iqn",e["\u0275nov"](n.parent.parent,2)));l(n,12,0,"form-group",u),l(n,22,0,"client_iqn");var t=n.context.$implicit.showError("client_iqn",e["\u0275nov"](n.parent.parent,2),"notUnique");l(n,28,0,t);var a=n.context.$implicit.showError("client_iqn",e["\u0275nov"](n.parent.parent,2),"required");l(n,30,0,a);var o=n.context.$implicit.showError("client_iqn",e["\u0275nov"](n.parent.parent,2),"pattern");l(n,32,0,o),l(n,34,0,"auth");var i=l(n,39,0,n.context.$implicit.showError("user",e["\u0275nov"](n.parent.parent,2)));l(n,38,0,"form-group",i),l(n,46,0,"user");var r=n.context.$implicit.showError("user",e["\u0275nov"](n.parent.parent,2),"required");l(n,51,0,r);var d=n.context.$implicit.showError("user",e["\u0275nov"](n.parent.parent,2),"pattern");l(n,53,0,d);var s=l(n,56,0,n.context.$implicit.showError("password",e["\u0275nov"](n.parent.parent,2)));l(n,55,0,"form-group",s),l(n,64,0,"password"),l(n,70,0,"password"+n.context.index),l(n,72,0,"password"+n.context.index);var c=n.context.$implicit.showError("password",e["\u0275nov"](n.parent.parent,2),"required");l(n,74,0,c);var p=n.context.$implicit.showError("password",e["\u0275nov"](n.parent.parent,2),"pattern");l(n,76,0,p);var f=l(n,79,0,n.context.$implicit.showError("mutual_user",e["\u0275nov"](n.parent.parent,2)));l(n,78,0,"form-group",f),l(n,87,0,"mutual_user");var g=n.context.$implicit.showError("mutual_user",e["\u0275nov"](n.parent.parent,2),"required");l(n,92,0,g);var m=n.context.$implicit.showError("mutual_user",e["\u0275nov"](n.parent.parent,2),"pattern");l(n,94,0,m);var v=l(n,97,0,n.context.$implicit.showError("mutual_password",e["\u0275nov"](n.parent.parent,2)));l(n,96,0,"form-group",v),l(n,105,0,"mutual_password"),l(n,111,0,"mutual_password"+n.context.index),l(n,113,0,"mutual_password"+n.context.index);var h=n.context.$implicit.showError("mutual_password",e["\u0275nov"](n.parent.parent,2),"required");l(n,115,0,h);var b=n.context.$implicit.showError("mutual_password",e["\u0275nov"](n.parent.parent,2),"pattern");l(n,117,0,b);var C=l(n,120,0,n.context.$implicit.showError("luns",e["\u0275nov"](n.parent.parent,2)));l(n,119,0,"form-group",C);var R=n.context.$implicit.getValue("luns");l(n,125,0,R);var I=n.context.$implicit.getValue("cdIsInGroup");l(n,127,0,I);var w=!n.context.$implicit.getValue("cdIsInGroup");l(n,129,0,w)},function(l,n){l(n,0,0,e["\u0275nov"](n,3).ngClassUntouched,e["\u0275nov"](n,3).ngClassTouched,e["\u0275nov"](n,3).ngClassPristine,e["\u0275nov"](n,3).ngClassDirty,e["\u0275nov"](n,3).ngClassValid,e["\u0275nov"](n,3).ngClassInvalid,e["\u0275nov"](n,3).ngClassPending);var u=n.context.$implicit.getValue("client_iqn");l(n,7,0,u),l(n,19,0,e["\u0275nov"](n,24).ngClassUntouched,e["\u0275nov"](n,24).ngClassTouched,e["\u0275nov"](n,24).ngClassPristine,e["\u0275nov"](n,24).ngClassDirty,e["\u0275nov"](n,24).ngClassValid,e["\u0275nov"](n,24).ngClassInvalid,e["\u0275nov"](n,24).ngClassPending),l(n,43,0,"user"+n.context.index,e["\u0275nov"](n,48).ngClassUntouched,e["\u0275nov"](n,48).ngClassTouched,e["\u0275nov"](n,48).ngClassPristine,e["\u0275nov"](n,48).ngClassDirty,e["\u0275nov"](n,48).ngClassValid,e["\u0275nov"](n,48).ngClassInvalid,e["\u0275nov"](n,48).ngClassPending),l(n,61,0,"password"+n.context.index,e["\u0275nov"](n,66).ngClassUntouched,e["\u0275nov"](n,66).ngClassTouched,e["\u0275nov"](n,66).ngClassPristine,e["\u0275nov"](n,66).ngClassDirty,e["\u0275nov"](n,66).ngClassValid,e["\u0275nov"](n,66).ngClassInvalid,e["\u0275nov"](n,66).ngClassPending),l(n,84,0,"mutual_user"+n.context.index,e["\u0275nov"](n,89).ngClassUntouched,e["\u0275nov"](n,89).ngClassTouched,e["\u0275nov"](n,89).ngClassPristine,e["\u0275nov"](n,89).ngClassDirty,e["\u0275nov"](n,89).ngClassValid,e["\u0275nov"](n,89).ngClassInvalid,e["\u0275nov"](n,89).ngClassPending),l(n,102,0,"mutual_password"+n.context.index,e["\u0275nov"](n,107).ngClassUntouched,e["\u0275nov"](n,107).ngClassTouched,e["\u0275nov"](n,107).ngClassPristine,e["\u0275nov"](n,107).ngClassDirty,e["\u0275nov"](n,107).ngClassValid,e["\u0275nov"](n,107).ngClassInvalid,e["\u0275nov"](n,107).ngClassPending)})}function We(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["No items added."]))],null,null)}function Qe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","initiators"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Initiators"])),(l()(),e["\u0275eld"](3,0,null,null,14,"div",[["class","col-sm-9"],["formArrayName","initiators"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](4,212992,null,0,Z.g,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.g]),e["\u0275did"](6,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ze)),e["\u0275did"](8,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](9,0,null,null,7,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](10,0,null,null,6,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,We)),e["\u0275did"](12,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](13,0,null,null,3,"button",[["class","btn btn-default pull-right"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(l.component.addInitiator(),e=!1),e},null,null)),(l()(),e["\u0275eld"](14,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](15,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add initiator"])),(l()(),e["\u0275eld"](17,0,null,null,0,"hr",[],null,null,null,null,null))],function(l,n){var u=n.component;l(n,4,0,"initiators"),l(n,8,0,u.initiators.controls),l(n,12,0,0===u.initiators.controls.length)},function(l,n){l(n,3,0,e["\u0275nov"](n,6).ngClassUntouched,e["\u0275nov"](n,6).ngClassTouched,e["\u0275nov"](n,6).ngClassPristine,e["\u0275nov"](n,6).ngClassDirty,e["\u0275nov"](n,6).ngClassValid,e["\u0275nov"](n,6).ngClassInvalid,e["\u0275nov"](n,6).ngClassPending)})}function Ye(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,5,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),e["\u0275did"](3,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](4,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removeGroupInitiator(l.parent.context.$implicit,l.context.index,l.parent.context.index)&&e),e},null,null)),(l()(),e["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null))],null,function(l,n){l(n,2,0,n.context.$implicit)})}function Xe(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(l()(),e["\u0275eld"](1,0,null,null,5,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(l()(),e["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),e["\u0275did"](3,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](4,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.removeGroupDisk(l.parent.context.$implicit,l.context.index,l.parent.context.index)&&e),e},null,null)),(l()(),e["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null))],null,function(l,n){l(n,2,0,n.context.$implicit)})}function lt(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,57,"div",[["class","panel panel-default"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](1,212992,null,0,Z.m,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.m]),e["\u0275did"](3,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](4,0,null,null,5,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),e["\u0275eld"](5,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Group"])),(l()(),e["\u0275ted"](7,null,[": "," "])),(l()(),e["\u0275eld"](8,0,null,null,1,"button",[["class","close"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.groups.removeAt(l.context.index)&&e),e},null,null)),(l()(),e["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-remove fa-fw"]],null,null,null,null,null)),(l()(),e["\u0275eld"](10,0,null,null,47,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),e["\u0275eld"](11,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](12,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","group_id"]],null,null,null,null,null)),(l()(),e["\u0275eld"](13,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Name"])),(l()(),e["\u0275eld"](15,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](16,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](17,0,null,null,6,"input",[["class","form-control"],["formControlName","group_id"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,18)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,18).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,18)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,18)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](18,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](20,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](22,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](23,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](24,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](25,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](26,{"has-error":0}),(l()(),e["\u0275eld"](27,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","members"]],null,null,null,null,null)),(l()(),e["\u0275eld"](28,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Initiators"])),(l()(),e["\u0275eld"](30,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Ye)),e["\u0275did"](32,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](33,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](34,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275eld"](35,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,[[null,"selection"]],function(l,n,u){var e=!0;return"selection"===n&&(e=!1!==l.component.onGroupMemberSelection(u)&&e),e},de.b,de.a)),e["\u0275did"](36,638976,null,0,se.a,[V.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},{selection:"selection"}),(l()(),e["\u0275eld"](37,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](38,0,null,0,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add initiator"])),(l()(),e["\u0275eld"](40,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),e["\u0275eld"](41,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](42,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](43,{"has-error":0}),(l()(),e["\u0275eld"](44,0,null,null,2,"label",[["class","control-label col-sm-3"],["for","disks"]],null,null,null,null,null)),(l()(),e["\u0275eld"](45,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Images"])),(l()(),e["\u0275eld"](47,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Xe)),e["\u0275did"](49,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](50,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](51,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275eld"](52,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,null,null,de.b,de.a)),e["\u0275did"](53,638976,null,0,se.a,[V.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},null),(l()(),e["\u0275eld"](54,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](55,0,null,0,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add image"])),(l()(),e["\u0275eld"](57,0,null,null,0,"hr",[],null,null,null,null,null))],function(l,n){var u=n.component;l(n,1,0,n.context.index),l(n,20,0,"group_id");var t=l(n,26,0,n.context.$implicit.showError("members",e["\u0275nov"](n.parent.parent,2)));l(n,25,0,"form-group",t);var a=n.context.$implicit.getValue("members");l(n,32,0,a);var o=n.context.$implicit.getValue("members");l(n,36,0,"btn btn-default pull-right",o,u.groupMembersSelections[n.context.index],u.messages.groupInitiator);var i=l(n,43,0,n.context.$implicit.showError("disks",e["\u0275nov"](n.parent.parent,2)));l(n,42,0,"form-group",i);var r=n.context.$implicit.getValue("disks");l(n,49,0,r);var d=n.context.$implicit.getValue("disks");l(n,53,0,"btn btn-default pull-right",d,u.groupDiskSelections[n.context.index],u.messages.initiatorImage)},function(l,n){l(n,0,0,e["\u0275nov"](n,3).ngClassUntouched,e["\u0275nov"](n,3).ngClassTouched,e["\u0275nov"](n,3).ngClassPristine,e["\u0275nov"](n,3).ngClassDirty,e["\u0275nov"](n,3).ngClassValid,e["\u0275nov"](n,3).ngClassInvalid,e["\u0275nov"](n,3).ngClassPending);var u=n.context.$implicit.getValue("group_id");l(n,7,0,u),l(n,17,0,e["\u0275nov"](n,22).ngClassUntouched,e["\u0275nov"](n,22).ngClassTouched,e["\u0275nov"](n,22).ngClassPristine,e["\u0275nov"](n,22).ngClassDirty,e["\u0275nov"](n,22).ngClassValid,e["\u0275nov"](n,22).ngClassInvalid,e["\u0275nov"](n,22).ngClassPending)})}function nt(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["No items added."]))],null,null)}function ut(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](1,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](2,{"has-error":0}),(l()(),e["\u0275eld"](3,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","initiators"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Groups"])),(l()(),e["\u0275eld"](5,0,null,null,13,"div",[["class","col-sm-9"],["formArrayName","groups"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),e["\u0275did"](6,212992,null,0,Z.g,[[3,Z.d],[8,null],[8,null]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.g]),e["\u0275did"](8,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,lt)),e["\u0275did"](10,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](11,0,null,null,7,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](12,0,null,null,6,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,nt)),e["\u0275did"](14,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](15,0,null,null,3,"button",[["class","btn btn-default pull-right"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(l.component.addGroup(),e=!1),e},null,null)),(l()(),e["\u0275eld"](16,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](17,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add group"]))],function(l,n){var u=n.component,t=l(n,2,0,u.targetForm.showError("groups",e["\u0275nov"](n.parent,2)));l(n,1,0,"form-group",t),l(n,6,0,"groups"),l(n,10,0,u.groups.controls),l(n,14,0,0===u.groups.controls.length)},function(l,n){l(n,5,0,e["\u0275nov"](n,8).ngClassUntouched,e["\u0275nov"](n,8).ngClassTouched,e["\u0275nov"](n,8).ngClassPristine,e["\u0275nov"](n,8).ngClassDirty,e["\u0275nov"](n,8).ngClassValid,e["\u0275nov"](n,8).ngClassInvalid,e["\u0275nov"](n,8).ngClassPending)})}function et(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,115,"form",[["class","form-horizontal"],["name","targetForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,u){var t=!0;return"submit"===n&&(t=!1!==e["\u0275nov"](l,2).onSubmit(u)&&t),"reset"===n&&(t=!1!==e["\u0275nov"](l,2).onReset()&&t),t},null,null)),e["\u0275did"](1,16384,null,0,Z.D,[],null,null),e["\u0275did"](2,540672,[["formDir",4]],0,Z.l,[[8,null],[8,null]],{form:[0,"form"]},null),e["\u0275prd"](2048,null,Z.d,null,[Z.l]),e["\u0275did"](4,16384,null,0,Z.s,[[4,Z.d]],null,null),(l()(),e["\u0275eld"](5,0,null,null,110,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),e["\u0275eld"](6,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),e["\u0275eld"](7,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),e["\u0275ted"](8,null,[""," ",""])),e["\u0275ppd"](9,1),e["\u0275ppd"](10,1),(l()(),e["\u0275eld"](11,0,null,null,95,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),e["\u0275eld"](12,0,null,null,28,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](13,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](14,{"has-error":0}),(l()(),e["\u0275eld"](15,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","target_iqn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](16,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Target IQN"])),(l()(),e["\u0275eld"](18,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](19,0,null,null,21,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](20,0,null,null,11,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](21,0,null,null,7,"input",[["cdTrim",""],["class","form-control"],["formControlName","target_iqn"],["id","target_iqn"],["name","target_iqn"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,22)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,22).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,22)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,22)._compositionEnd(u.target.value)&&t),"input"===n&&(t=!1!==e["\u0275nov"](l,27).onInput(u.target.value)&&t),t},null,null)),e["\u0275did"](22,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](24,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](26,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](27,16384,null,0,ce,[Z.q],null,null),e["\u0275did"](28,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](29,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),e["\u0275eld"](30,0,null,null,1,"button",[["class","btn btn-default"],["id","ecp-info-button"],["type","button"]],null,[[null,"click"]],function(l,n,u){var e=!0;return"click"===n&&(e=!1!==l.component.targetSettingsModal()&&e),e},null,null)),(l()(),e["\u0275eld"](31,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-cogs fa-fw"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,ge)),e["\u0275did"](33,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,me)),e["\u0275did"](35,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ve)),e["\u0275did"](37,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,he)),e["\u0275did"](39,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](40,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),e["\u0275eld"](41,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](42,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](43,{"has-error":0}),(l()(),e["\u0275eld"](44,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","portals"]],null,null,null,null,null)),(l()(),e["\u0275eld"](45,0,null,null,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Portals"])),(l()(),e["\u0275eld"](47,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),e["\u0275eld"](48,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,be)),e["\u0275did"](50,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Ce)),e["\u0275did"](52,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](53,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](54,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275eld"](55,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,[[null,"selection"]],function(l,n,u){var e=!0;return"selection"===n&&(e=!1!==l.component.onPortalSelection(u)&&e),e},de.b,de.a)),e["\u0275did"](56,638976,null,0,se.a,[V.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},{selection:"selection"}),(l()(),e["\u0275eld"](57,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](58,0,null,0,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add portal"])),(l()(),e["\u0275eld"](60,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),e["\u0275eld"](61,0,null,null,26,"div",[["class","form-group"]],null,null,null,null,null)),e["\u0275did"](62,278528,null,0,_.NgClass,[e.IterableDiffers,e.KeyValueDiffers,e.ElementRef,e.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),e["\u0275pod"](63,{"has-error":0}),(l()(),e["\u0275eld"](64,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","disks"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Images"])),(l()(),e["\u0275eld"](66,0,null,null,21,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Te)),e["\u0275did"](68,278528,null,0,_.NgForOf,[e.ViewContainerRef,e.TemplateRef,e.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),e["\u0275eld"](69,0,null,null,6,"input",[["class","form-control"],["formControlName","disks"],["id","disks"],["name","disks"],["type","hidden"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,u){var t=!0;return"input"===n&&(t=!1!==e["\u0275nov"](l,70)._handleInput(u.target.value)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,70).onTouched()&&t),"compositionstart"===n&&(t=!1!==e["\u0275nov"](l,70)._compositionStart()&&t),"compositionend"===n&&(t=!1!==e["\u0275nov"](l,70)._compositionEnd(u.target.value)&&t),t},null,null)),e["\u0275did"](70,16384,null,0,Z.e,[e.Renderer2,e.ElementRef,[2,Z.b]],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.e]),e["\u0275did"](72,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](74,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](75,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275and"](16777216,null,null,1,null,ye)),e["\u0275did"](77,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ke)),e["\u0275did"](79,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](80,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(l()(),e["\u0275eld"](81,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(l()(),e["\u0275eld"](82,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,[[null,"selection"]],function(l,n,u){var e=!0;return"selection"===n&&(e=!1!==l.component.onImageSelection(u)&&e),e},de.b,de.a)),e["\u0275did"](83,638976,null,0,se.a,[V.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},{selection:"selection"}),(l()(),e["\u0275eld"](84,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(l()(),e["\u0275eld"](85,0,null,0,1,null,null,null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["Add image"])),(l()(),e["\u0275eld"](87,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),e["\u0275eld"](88,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),e["\u0275eld"](89,0,null,null,11,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),e["\u0275eld"](90,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),e["\u0275eld"](91,0,null,null,6,"input",[["formControlName","acl_enabled"],["id","acl_enabled"],["name","acl_enabled"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,u){var t=!0;return"change"===n&&(t=!1!==e["\u0275nov"](l,92).onChange(u.target.checked)&&t),"blur"===n&&(t=!1!==e["\u0275nov"](l,92).onTouched()&&t),t},null,null)),e["\u0275did"](92,16384,null,0,Z.c,[e.Renderer2,e.ElementRef],null,null),e["\u0275prd"](1024,null,Z.p,function(l){return[l]},[Z.c]),e["\u0275did"](94,671744,null,0,Z.j,[[3,Z.d],[8,null],[8,null],[6,Z.p],[2,Z.F]],{name:[0,"name"]},null),e["\u0275prd"](2048,null,Z.q,null,[Z.j]),e["\u0275did"](96,16384,null,0,Z.r,[[4,Z.q]],null,null),e["\u0275did"](97,4210688,null,0,Vn.a,[[2,Nn.a],il.a,e.ElementRef],null,null),(l()(),e["\u0275eld"](98,0,null,null,1,"label",[["for","acl_enabled"]],null,null,null,null,null)),(l()(),e["\u0275ted"](-1,null,["ACL authentication"])),(l()(),e["\u0275eld"](100,0,null,null,0,"hr",[],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,Pe)),e["\u0275did"](102,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,Qe)),e["\u0275did"](104,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275and"](16777216,null,null,1,null,ut)),e["\u0275did"](106,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),e["\u0275eld"](107,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),e["\u0275eld"](108,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),e["\u0275eld"](109,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,u){var e=!0;return"submitAction"===n&&(e=!1!==l.component.submit()&&e),e},An.b,An.a)),e["\u0275did"](110,114688,null,0,Un.a,[e.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),e["\u0275ted"](111,0,[""," ",""])),e["\u0275ppd"](112,1),e["\u0275ppd"](113,1),(l()(),e["\u0275eld"](114,0,null,null,1,"cd-back-button",[],null,null,null,$n.b,$n.a)),e["\u0275did"](115,49152,null,0,Mn.a,[_.Location,Gl.b],null,null)],function(l,n){var u=n.component;l(n,2,0,u.targetForm);var t=l(n,14,0,u.targetForm.showError("target_iqn",e["\u0275nov"](n,2)));l(n,13,0,"form-group",t),l(n,24,0,"target_iqn"),l(n,33,0,u.targetForm.showError("target_iqn",e["\u0275nov"](n,2),"required")),l(n,35,0,u.targetForm.showError("target_iqn",e["\u0275nov"](n,2),"pattern")),l(n,37,0,u.targetForm.showError("target_iqn",e["\u0275nov"](n,2),"iqn")),l(n,39,0,u.hasAdvancedSettings(u.targetForm.getValue("target_controls")));var a=l(n,43,0,u.targetForm.showError("portals",e["\u0275nov"](n,2)));l(n,42,0,"form-group",a),l(n,50,0,u.portals.value),l(n,52,0,u.targetForm.showError("portals",e["\u0275nov"](n,2),"minGateways")),l(n,56,0,"btn btn-default pull-right",u.portals.value,u.portalsSelections,u.messages.portals);var o=l(n,63,0,u.targetForm.showError("disks",e["\u0275nov"](n,2)));l(n,62,0,"form-group",o),l(n,68,0,u.targetForm.getValue("disks")),l(n,72,0,"disks"),l(n,77,0,u.targetForm.showError("disks",e["\u0275nov"](n,2),"dupLunId")),l(n,79,0,u.targetForm.showError("disks",e["\u0275nov"](n,2),"dupWwn")),l(n,83,0,"btn btn-default pull-right",u.disks.value,u.imagesSelections,u.messages.images),l(n,94,0,"acl_enabled"),l(n,102,0,u.cephIscsiConfigVersion>10&&!u.targetForm.getValue("acl_enabled")),l(n,104,0,u.targetForm.getValue("acl_enabled")),l(n,106,0,u.targetForm.getValue("acl_enabled")),l(n,110,0,e["\u0275nov"](n,2),"button")},function(l,n){var u=n.component;l(n,0,0,e["\u0275nov"](n,4).ngClassUntouched,e["\u0275nov"](n,4).ngClassTouched,e["\u0275nov"](n,4).ngClassPristine,e["\u0275nov"](n,4).ngClassDirty,e["\u0275nov"](n,4).ngClassValid,e["\u0275nov"](n,4).ngClassInvalid,e["\u0275nov"](n,4).ngClassPending);var t=e["\u0275unv"](n,8,0,l(n,9,0,e["\u0275nov"](n.parent,0),u.action)),a=e["\u0275unv"](n,8,1,l(n,10,0,e["\u0275nov"](n.parent,1),u.resource));l(n,8,0,t,a),l(n,21,0,e["\u0275nov"](n,26).ngClassUntouched,e["\u0275nov"](n,26).ngClassTouched,e["\u0275nov"](n,26).ngClassPristine,e["\u0275nov"](n,26).ngClassDirty,e["\u0275nov"](n,26).ngClassValid,e["\u0275nov"](n,26).ngClassInvalid,e["\u0275nov"](n,26).ngClassPending),l(n,69,0,e["\u0275nov"](n,74).ngClassUntouched,e["\u0275nov"](n,74).ngClassTouched,e["\u0275nov"](n,74).ngClassPristine,e["\u0275nov"](n,74).ngClassDirty,e["\u0275nov"](n,74).ngClassValid,e["\u0275nov"](n,74).ngClassInvalid,e["\u0275nov"](n,74).ngClassPending),l(n,91,0,e["\u0275nov"](n,96).ngClassUntouched,e["\u0275nov"](n,96).ngClassTouched,e["\u0275nov"](n,96).ngClassPristine,e["\u0275nov"](n,96).ngClassDirty,e["\u0275nov"](n,96).ngClassValid,e["\u0275nov"](n,96).ngClassInvalid,e["\u0275nov"](n,96).ngClassPending);var o=e["\u0275unv"](n,111,0,l(n,112,0,e["\u0275nov"](n.parent,0),u.action)),i=e["\u0275unv"](n,111,1,l(n,113,0,e["\u0275nov"](n.parent,1),u.resource));l(n,111,0,o,i)})}function tt(l){return e["\u0275vid"](0,[e["\u0275pid"](0,_.TitleCasePipe,[]),e["\u0275pid"](0,H.a,[]),e["\u0275pid"](0,O.a,[]),(l()(),e["\u0275eld"](3,0,null,null,2,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),e["\u0275and"](16777216,null,null,1,null,et)),e["\u0275did"](5,16384,null,0,_.NgIf,[e.ViewContainerRef,e.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,5,0,n.component.targetForm)},null)}function at(l){return e["\u0275vid"](0,[(l()(),e["\u0275eld"](0,0,null,null,1,"cd-iscsi-target-form",[],null,null,null,tt,fe)),e["\u0275did"](1,114688,null,0,pe.a,[Fu.a,nl.b,zl.a,dl.l,dl.a,V.a,Wl.a,Gl.b],null,null)],function(l,n){l(n,1,0)},null)}var ot=e["\u0275ccf"]("cd-iscsi-target-form",pe.a,at,{},{},[]),it=u("Vhfg"),rt=u("cxJu");u.d(n,"BlockModuleNgFactory",function(){return dt}),u.d(n,"RoutedBlockModuleNgFactory",function(){return st});var dt=e["\u0275cmf"](t.a,[],function(l){return e["\u0275mod"]([e["\u0275mpd"](512,e.ComponentFactoryResolver,e["\u0275CodegenComponentFactoryResolver"],[[8,[a.a,o.a,i.a,r.a,r.b,d.a,s.a,c.a,p.a,f.a,g.a,m.a,v.a,h.a,h.c,h.b,b.a,C.a,R.a,I.a,w.a,T.a,y.a,k.a,E.a]],[3,e.ComponentFactoryResolver],e.NgModuleRef]),e["\u0275mpd"](4608,_.NgLocalization,_.NgLocaleLocalization,[e.LOCALE_ID,[2,_["\u0275angular_packages_common_common_a"]]]),e["\u0275mpd"](4608,x.a,x.a,[V.a]),e["\u0275mpd"](4608,_.DatePipe,_.DatePipe,[e.LOCALE_ID]),e["\u0275mpd"](4608,N.a,N.a,[]),e["\u0275mpd"](4608,D.a,D.a,[]),e["\u0275mpd"](4608,S.a,S.a,[]),e["\u0275mpd"](4608,F.a,F.a,[S.a]),e["\u0275mpd"](4608,P.a,P.a,[S.a]),e["\u0275mpd"](4608,q.a,q.a,[S.a]),e["\u0275mpd"](4608,j.a,j.a,[]),e["\u0275mpd"](4608,O.a,O.a,[]),e["\u0275mpd"](4608,A.a,A.a,[]),e["\u0275mpd"](4608,U.a,U.a,[]),e["\u0275mpd"](4608,$.a,$.a,[_.DatePipe]),e["\u0275mpd"](4608,M.a,M.a,[]),e["\u0275mpd"](4608,z.a,z.a,[]),e["\u0275mpd"](4608,B.a,B.a,[]),e["\u0275mpd"](4608,L.a,L.a,[]),e["\u0275mpd"](4608,G.a,G.a,[]),e["\u0275mpd"](4608,K.a,K.a,[V.a]),e["\u0275mpd"](4608,H.a,H.a,[]),e["\u0275mpd"](4608,J.a,J.a,[]),e["\u0275mpd"](4608,Z.E,Z.E,[]),e["\u0275mpd"](4608,Z.h,Z.h,[]),e["\u0275mpd"](4608,W.b,W.b,[]),e["\u0275mpd"](4608,Q.a,Q.a,[]),e["\u0275mpd"](4608,Y.a,Y.a,[e.RendererFactory2,e.PLATFORM_ID]),e["\u0275mpd"](4608,X.a,X.a,[e.ComponentFactoryResolver,e.NgZone,e.Injector,Y.a,e.ApplicationRef]),e["\u0275mpd"](4608,ll.a,ll.a,[]),e["\u0275mpd"](4608,nl.b,nl.b,[e.RendererFactory2,X.a]),e["\u0275mpd"](4608,ul.ScrollbarHelper,ul.ScrollbarHelper,[el.DOCUMENT]),e["\u0275mpd"](4608,tl.DimensionsHelper,tl.DimensionsHelper,[]),e["\u0275mpd"](4608,al.ColumnChangesService,al.ColumnChangesService,[]),e["\u0275mpd"](4608,ol.f,ol.f,[]),e["\u0275mpd"](4608,il.a,il.a,[]),e["\u0275mpd"](4608,rl.a,rl.a,[dl.l,il.a]),e["\u0275mpd"](4608,sl.NodeDraggableService,sl.NodeDraggableService,[]),e["\u0275mpd"](4608,cl.NodeMenuService,cl.NodeMenuService,[]),e["\u0275mpd"](4608,pl.TreeService,pl.TreeService,[sl.NodeDraggableService]),e["\u0275mpd"](4608,fl.e,fl.e,[]),e["\u0275mpd"](4608,gl.c,gl.c,[]),e["\u0275mpd"](4608,ml.r,ml.r,[]),e["\u0275mpd"](4608,ml.t,ml.t,[]),e["\u0275mpd"](4608,ml.a,ml.a,[]),e["\u0275mpd"](4608,ml.h,ml.h,[]),e["\u0275mpd"](4608,ml.d,ml.d,[]),e["\u0275mpd"](4608,ml.j,ml.j,[]),e["\u0275mpd"](4608,ml.s,ml.s,[ml.t,ml.j]),e["\u0275mpd"](1073742336,_.CommonModule,_.CommonModule,[]),e["\u0275mpd"](1073742336,fl.c,fl.c,[]),e["\u0275mpd"](1073742336,vl.a,vl.a,[]),e["\u0275mpd"](1073742336,Z.B,Z.B,[]),e["\u0275mpd"](1073742336,Z.n,Z.n,[]),e["\u0275mpd"](1073742336,Z.x,Z.x,[]),e["\u0275mpd"](1073742336,W.c,W.c,[]),e["\u0275mpd"](1073742336,Q.d,Q.d,[]),e["\u0275mpd"](1073742336,ll.d,ll.d,[]),e["\u0275mpd"](1073742336,hl.ChartsModule,hl.ChartsModule,[]),e["\u0275mpd"](1073742336,nl.e,nl.e,[]),e["\u0275mpd"](1073742336,bl.a,bl.a,[]),e["\u0275mpd"](1073742336,ol.e,ol.e,[]),e["\u0275mpd"](1073742336,Cl.a,Cl.a,[]),e["\u0275mpd"](1073742336,Rl.NgxDatatableModule,Rl.NgxDatatableModule,[]),e["\u0275mpd"](1073742336,dl.p,dl.p,[[2,dl.v],[2,dl.l]]),e["\u0275mpd"](1073742336,Il.a,Il.a,[]),e["\u0275mpd"](1073742336,wl.a,wl.a,[]),e["\u0275mpd"](1073742336,Tl.a,Tl.a,[]),e["\u0275mpd"](1073742336,gl.d,gl.d,[]),e["\u0275mpd"](1073742336,yl.TreeModule,yl.TreeModule,[]),e["\u0275mpd"](1073742336,kl.a,kl.a,[]),e["\u0275mpd"](1073742336,ml.g,ml.g,[]),e["\u0275mpd"](1073742336,t.a,t.a,[]),e["\u0275mpd"](256,e.LOCALE_ID,"en-US",[]),e["\u0275mpd"](256,ol.a,{autoClose:!0,insideClick:!1},[]),e["\u0275mpd"](256,e.TRANSLATIONS_FORMAT,"xlf",[])])}),st=e["\u0275cmf"](t.b,[],function(l){return e["\u0275mod"]([e["\u0275mpd"](512,e.ComponentFactoryResolver,e["\u0275CodegenComponentFactoryResolver"],[[8,[a.a,o.a,i.a,r.a,r.b,d.a,s.a,c.a,p.a,f.a,g.a,m.a,v.a,h.a,h.c,h.b,b.a,C.a,R.a,I.a,w.a,T.a,y.a,k.a,E.a,xn,Eu,Hu,ae,ot]],[3,e.ComponentFactoryResolver],e.NgModuleRef]),e["\u0275mpd"](4608,_.NgLocalization,_.NgLocaleLocalization,[e.LOCALE_ID,[2,_["\u0275angular_packages_common_common_a"]]]),e["\u0275mpd"](4608,x.a,x.a,[V.a]),e["\u0275mpd"](4608,_.DatePipe,_.DatePipe,[e.LOCALE_ID]),e["\u0275mpd"](4608,N.a,N.a,[]),e["\u0275mpd"](4608,D.a,D.a,[]),e["\u0275mpd"](4608,S.a,S.a,[]),e["\u0275mpd"](4608,F.a,F.a,[S.a]),e["\u0275mpd"](4608,P.a,P.a,[S.a]),e["\u0275mpd"](4608,q.a,q.a,[S.a]),e["\u0275mpd"](4608,j.a,j.a,[]),e["\u0275mpd"](4608,O.a,O.a,[]),e["\u0275mpd"](4608,A.a,A.a,[]),e["\u0275mpd"](4608,U.a,U.a,[]),e["\u0275mpd"](4608,$.a,$.a,[_.DatePipe]),e["\u0275mpd"](4608,M.a,M.a,[]),e["\u0275mpd"](4608,z.a,z.a,[]),e["\u0275mpd"](4608,B.a,B.a,[]),e["\u0275mpd"](4608,L.a,L.a,[]),e["\u0275mpd"](4608,G.a,G.a,[]),e["\u0275mpd"](4608,K.a,K.a,[V.a]),e["\u0275mpd"](4608,H.a,H.a,[]),e["\u0275mpd"](4608,J.a,J.a,[]),e["\u0275mpd"](4608,Z.E,Z.E,[]),e["\u0275mpd"](4608,Z.h,Z.h,[]),e["\u0275mpd"](4608,W.b,W.b,[]),e["\u0275mpd"](4608,Q.a,Q.a,[]),e["\u0275mpd"](4608,Y.a,Y.a,[e.RendererFactory2,e.PLATFORM_ID]),e["\u0275mpd"](4608,X.a,X.a,[e.ComponentFactoryResolver,e.NgZone,e.Injector,Y.a,e.ApplicationRef]),e["\u0275mpd"](4608,ll.a,ll.a,[]),e["\u0275mpd"](4608,nl.b,nl.b,[e.RendererFactory2,X.a]),e["\u0275mpd"](4608,ul.ScrollbarHelper,ul.ScrollbarHelper,[el.DOCUMENT]),e["\u0275mpd"](4608,tl.DimensionsHelper,tl.DimensionsHelper,[]),e["\u0275mpd"](4608,al.ColumnChangesService,al.ColumnChangesService,[]),e["\u0275mpd"](4608,ol.f,ol.f,[]),e["\u0275mpd"](4608,il.a,il.a,[]),e["\u0275mpd"](4608,rl.a,rl.a,[dl.l,il.a]),e["\u0275mpd"](4608,sl.NodeDraggableService,sl.NodeDraggableService,[]),e["\u0275mpd"](4608,cl.NodeMenuService,cl.NodeMenuService,[]),e["\u0275mpd"](4608,pl.TreeService,pl.TreeService,[sl.NodeDraggableService]),e["\u0275mpd"](4608,fl.e,fl.e,[]),e["\u0275mpd"](4608,gl.c,gl.c,[]),e["\u0275mpd"](4608,ml.r,ml.r,[]),e["\u0275mpd"](4608,ml.t,ml.t,[]),e["\u0275mpd"](4608,ml.a,ml.a,[]),e["\u0275mpd"](4608,ml.h,ml.h,[]),e["\u0275mpd"](4608,ml.d,ml.d,[]),e["\u0275mpd"](4608,ml.j,ml.j,[]),e["\u0275mpd"](4608,ml.s,ml.s,[ml.t,ml.j]),e["\u0275mpd"](1073742336,_.CommonModule,_.CommonModule,[]),e["\u0275mpd"](1073742336,fl.c,fl.c,[]),e["\u0275mpd"](1073742336,vl.a,vl.a,[]),e["\u0275mpd"](1073742336,Z.B,Z.B,[]),e["\u0275mpd"](1073742336,Z.n,Z.n,[]),e["\u0275mpd"](1073742336,Z.x,Z.x,[]),e["\u0275mpd"](1073742336,W.c,W.c,[]),e["\u0275mpd"](1073742336,Q.d,Q.d,[]),e["\u0275mpd"](1073742336,ll.d,ll.d,[]),e["\u0275mpd"](1073742336,hl.ChartsModule,hl.ChartsModule,[]),e["\u0275mpd"](1073742336,nl.e,nl.e,[]),e["\u0275mpd"](1073742336,bl.a,bl.a,[]),e["\u0275mpd"](1073742336,ol.e,ol.e,[]),e["\u0275mpd"](1073742336,Cl.a,Cl.a,[]),e["\u0275mpd"](1073742336,Rl.NgxDatatableModule,Rl.NgxDatatableModule,[]),e["\u0275mpd"](1073742336,dl.p,dl.p,[[2,dl.v],[2,dl.l]]),e["\u0275mpd"](1073742336,Il.a,Il.a,[]),e["\u0275mpd"](1073742336,wl.a,wl.a,[]),e["\u0275mpd"](1073742336,Tl.a,Tl.a,[]),e["\u0275mpd"](1073742336,gl.d,gl.d,[]),e["\u0275mpd"](1073742336,yl.TreeModule,yl.TreeModule,[]),e["\u0275mpd"](1073742336,kl.a,kl.a,[]),e["\u0275mpd"](1073742336,ml.g,ml.g,[]),e["\u0275mpd"](1073742336,t.a,t.a,[]),e["\u0275mpd"](1073742336,t.b,t.b,[]),e["\u0275mpd"](256,e.LOCALE_ID,"en-US",[]),e["\u0275mpd"](256,ol.a,{autoClose:!0,insideClick:!1},[]),e["\u0275mpd"](1024,dl.j,function(){return[[{path:"",redirectTo:"rbd",pathMatch:"full"},{path:"rbd",canActivate:[it.a],data:t.c,children:[{path:"",component:Tn.a},{path:"create",component:zn.a,data:t.d},{path:"edit/:pool/:name",component:zn.a,data:t.g},{path:"clone/:pool/:name/:snap",component:zn.a,data:t.h},{path:"copy/:pool/:name",component:zn.a,data:t.i},{path:"copy/:pool/:name/:snap",component:zn.a,data:t.j}]},{path:"mirroring",component:rt.a,canActivate:[it.a],data:t.k},{path:"iscsi",canActivate:[it.a],data:t.l,children:[{path:"",redirectTo:"overview",pathMatch:"full"},{path:"overview",component:Su.a,data:t.m},{path:"targets",data:t.n,children:[{path:"",component:Qu.a},{path:"create",component:pe.a,data:t.e},{path:"edit/:target_iqn",component:pe.a,data:t.f}]}]}]]},[]),e["\u0275mpd"](256,e.TRANSLATIONS_FORMAT,"xlf",[])])})}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/8.7550b99d388b9ca165da.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/8.7550b99d388b9ca165da.js
new file mode 100644
index 00000000..e0842db4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/8.7550b99d388b9ca165da.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{nOaW:function(l,n,e){"use strict";e.r(n);var u=e("CcnG"),t=e("sne2"),o=e("gIcY"),i=e("LvDl"),a=e("VNr4"),r=e("t/Na"),s=e("Jm/i"),d=e("pL04"),c=function(){function l(l,n){this.http=l,this.i18n=n,this.apiPath="api/erasure_code_profile",this.formTooltips={k:this.i18n("Each object is split in data-chunks parts, each stored on a different OSD."),m:this.i18n("Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data."),plugins:{jerasure:{description:this.i18n("The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools."),technique:this.i18n("The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2."),packetSize:this.i18n("The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.")},lrc:{description:this.i18n("With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven."),l:this.i18n("Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set."),crushLocality:this.i18n("The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.")},isa:{description:this.i18n("The isa plugin encapsulates the ISA library. It only runs on Intel processors."),technique:this.i18n("The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.")},shec:{description:this.i18n("The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes."),c:this.i18n("The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.")}},crushRoot:this.i18n("The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default."),crushFailureDomain:this.i18n("Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host."),crushDeviceClass:this.i18n("Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map."),directory:this.i18n("Set the directory name from which the erasure code plugin is loaded.")}}return l.prototype.list=function(){return this.http.get(this.apiPath)},l.prototype.create=function(l){return this.http.post(this.apiPath,l,{observe:"response"})},l.prototype.update=function(l){return this.http.put(this.apiPath+"/"+l.name,l,{observe:"response"})},l.prototype.delete=function(l){return this.http.delete(this.apiPath+"/"+l,{observe:"response"})},l.prototype.get=function(l){return this.http.get(this.apiPath+"/"+l)},l.prototype.getInfo=function(){return this.http.get(this.apiPath+"/_info")},l.ngInjectableDef=u.defineInjectable({factory:function(){return new l(u.inject(r.c),u.inject(s.a))},token:l,providedIn:d.a}),l}(),p=e("Ekvf"),f=e("0+/T"),m=e("QFaf"),g=e("1Ni5"),h=e("PhyI"),v=e("kvvV"),b=e("Fgil"),C=e("aexS"),R=e("aXbf"),y=e("kn/O"),I=e("2EZI"),E=function(){return function(){}}(),V=function(){function l(l,n,e,t,o,i){this.formBuilder=l,this.bsModalRef=n,this.taskWrapper=e,this.ecpService=t,this.i18n=o,this.actionLabels=i,this.submitAction=new u.EventEmitter,this.requiredControls=[],this.devices=[],this.tooltips=this.ecpService.formTooltips,this.PLUGIN={LRC:"lrc",SHEC:"shec",JERASURE:"jerasure",ISA:"isa"},this.plugin=this.PLUGIN.JERASURE,this.action=this.actionLabels.CREATE,this.resource=this.i18n("EC Profile"),this.createForm(),this.setJerasureDefaults()}return l.prototype.createForm=function(){var l=this;this.form=this.formBuilder.group({name:[null,[o.A.required,o.A.pattern("[A-Za-z0-9_-]+"),g.a.custom("uniqueName",function(n){return l.names&&-1!==l.names.indexOf(n)})]],plugin:[this.PLUGIN.JERASURE,[o.A.required]],k:[1],m:[1],crushFailureDomain:["host"],crushRoot:["default"],crushDeviceClass:[""],directory:[""],technique:["reed_sol_van"],packetSize:[2048,[o.A.min(1)]],l:[1,[o.A.required,o.A.min(1)]],crushLocality:[""],c:[1,[o.A.required,o.A.min(1)]]}),this.form.get("plugin").valueChanges.subscribe(function(n){return l.onPluginChange(n)})},l.prototype.onPluginChange=function(l){this.plugin=l,l===this.PLUGIN.JERASURE?this.setJerasureDefaults():l===this.PLUGIN.LRC?this.setLrcDefaults():l===this.PLUGIN.ISA?this.setIsaDefaults():l===this.PLUGIN.SHEC&&this.setShecDefaults()},l.prototype.setNumberValidators=function(l,n){var e=[o.A.min(1)];n&&e.push(o.A.required),this.form.get(l).setValidators(e)},l.prototype.setKMValidators=function(l){var n=this;["k","m"].forEach(function(e){return n.setNumberValidators(e,l)})},l.prototype.setJerasureDefaults=function(){this.requiredControls=["k","m"],this.setDefaults({k:4,m:2}),this.setKMValidators(!0),this.techniques=["reed_sol_van","reed_sol_r6_op","cauchy_orig","cauchy_good","liberation","blaum_roth","liber8tion"]},l.prototype.setLrcDefaults=function(){this.requiredControls=["k","m","l"],this.setKMValidators(!0),this.setNumberValidators("l",!0),this.setDefaults({k:4,m:2,l:3})},l.prototype.setIsaDefaults=function(){this.requiredControls=[],this.setKMValidators(!1),this.setDefaults({k:7,m:3}),this.techniques=["reed_sol_van","cauchy"]},l.prototype.setShecDefaults=function(){this.requiredControls=[],this.setKMValidators(!1),this.setDefaults({k:4,m:3,c:2})},l.prototype.setDefaults=function(l){var n=this;Object.keys(l).forEach(function(e){n.form.get(e).pristine&&n.form.silentSet(e,l[e])})},l.prototype.ngOnInit=function(){var l=this;this.ecpService.getInfo().subscribe(function(n){var e=n.plugins,u=n.names,t=n.directory,o=n.devices;l.failureDomains=n.failure_domains,l.plugins=e,l.names=u,l.devices=o,l.form.silentSet("directory",t)})},l.prototype.createJson=function(){var l=this,n={technique:[this.PLUGIN.ISA,this.PLUGIN.JERASURE],packetSize:[this.PLUGIN.JERASURE],l:[this.PLUGIN.LRC],crushLocality:[this.PLUGIN.LRC],c:[this.PLUGIN.SHEC]},e=new E,u=this.form.getValue("plugin");return Object.keys(this.form.controls).filter(function(e){var t=n[e],o=l.form.get(e);return(t&&t.includes(u)||!t)&&(o.dirty||l.requiredControls.includes(e))&&l.form.getValue(e)}).forEach(function(n){l.extendJson(n,e)}),e},l.prototype.extendJson=function(l,n){n[{crushFailureDomain:"crush-failure-domain",crushRoot:"crush-root",crushDeviceClass:"crush-device-class",packetSize:"packetsize",crushLocality:"crush-locality"}[l]||l]=this.form.getValue(l)},l.prototype.onSubmit=function(){var l=this;if(this.form.invalid)this.form.setErrors({cdSubmitButton:!0});else{var n=this.createJson();this.taskWrapper.wrapTaskAroundCall({task:new v.a("ecp/create",{name:n.name}),call:this.ecpService.create(n)}).subscribe(void 0,function(){l.form.setErrors({cdSubmitButton:!0})},function(){l.bsModalRef.hide(),l.submitAction.emit(n)})}},l}(),T=e("DNAf"),w=e("a96k"),S=function(){return function(l){this.erasureInfo=!1,this.crushInfo=!1,this.pgs=1,this.poolTypes=["erasure","replicated"],this.applications={selected:[],available:[new w.a(!1,"cephfs",""),new w.a(!1,"rbd",""),new w.a(!1,"rgw","")],validators:[o.A.pattern("[A-Za-z0-9_]+"),o.A.maxLength(128)],messages:new T.a({empty:l("No applications added"),selectionLimit:{text:l("Applications limit reached"),tooltip:l("A pool can only have up to four applications definitions.")},customValidations:{pattern:l("Allowed characters '_a-zA-Z0-9'"),maxlength:l("Maximum length is 128 characters")},filter:l("Filter or add applications"),add:l("Add application")},l)}}}(),N=function(){function l(l,n,e,o,i,a,r,s,d,c,p,f){this.dimlessBinaryPipe=l,this.route=n,this.router=e,this.modalService=o,this.poolService=i,this.authStorageService=a,this.formatter=r,this.bsModalService=s,this.taskWrapper=d,this.ecpService=c,this.i18n=p,this.actionLabels=f,this.editing=!1,this.data=new S(this.i18n),this.externalPgChange=!1,this.current={rules:[]},this.initializeConfigData=new u.EventEmitter,this.currentConfigurationValues={},this.editing=this.router.url.startsWith("/pool/"+t.e.EDIT),this.action=this.editing?this.actionLabels.EDIT:this.actionLabels.CREATE,this.resource=this.i18n("pool"),this.authenticate(),this.createForm()}return l.prototype.authenticate=function(){this.permission=this.authStorageService.getPermissions().pool,(!this.permission.read||!this.permission.update&&this.editing||!this.permission.create&&!this.editing)&&this.router.navigate(["/404"])},l.prototype.createForm=function(){var l=this,n=new m.a({mode:new o.i("none"),algorithm:new o.i(""),minBlobSize:new o.i("",{updateOn:"blur"}),maxBlobSize:new o.i("",{updateOn:"blur"}),ratio:new o.i("",{updateOn:"blur"})});this.form=new m.a({name:new o.i("",{validators:[o.A.pattern(/^[.A-Za-z0-9_\/-]+$/),o.A.required]}),poolType:new o.i("",{validators:[o.A.required]}),crushRule:new o.i(null,{validators:[g.a.custom("tooFewOsds",function(n){return l.info&&n&&l.info.osd_count<n.min_size})]}),size:new o.i("",{updateOn:"blur"}),erasureProfile:new o.i(null),pgNum:new o.i("",{validators:[o.A.required,o.A.min(1)]}),ecOverwrites:new o.i(!1),compression:n},[g.a.custom("form",function(){return null}),g.a.custom("rbdPool",function(){return l.form&&l.form.getValue("name").includes("/")&&l.data&&-1!==l.data.applications.selected.indexOf("rbd")})])},l.prototype.ngOnInit=function(){var l=this;Object(a.a)(this.poolService.getInfo(),this.ecpService.list()).subscribe(function(n){l.initInfo(n[0]),l.initEcp(n[1]),l.editing&&l.initEditMode(),l.listenToChanges(),l.setComplexValidators()})},l.prototype.initInfo=function(l){this.form.silentSet("algorithm",l.bluestore_compression_algorithm),this.info=l},l.prototype.initEcp=function(l){var n=this.form.get("erasureProfile");l.length<=1&&n.disable(),1===l.length?n.setValue(l[0]):l.length>1&&n.disabled&&n.enable(),this.ecProfiles=l},l.prototype.initEditMode=function(){var l=this;this.disableForEdit(),this.routeParamsSubscribe=this.route.params.subscribe(function(n){return l.poolService.get(n.name).subscribe(function(n){l.data.pool=n,l.initEditFormData(n)})})},l.prototype.disableForEdit=function(){var l=this;["poolType","crushRule","size","erasureProfile","ecOverwrites"].forEach(function(n){return l.form.get(n).disable()})},l.prototype.initEditFormData=function(l){var n=this;this.initializeConfigData.emit({initialData:l.configuration,sourceType:h.a.pool});var e={name:l.pool_name,poolType:l.type,crushRule:this.info["crush_rules_"+l.type].find(function(n){return n.rule_name===l.crush_rule}),size:l.size,erasureProfile:this.ecProfiles.find(function(n){return n.name===l.erasure_code_profile}),pgNum:l.pg_num,ecOverwrites:l.flags_names.includes("ec_overwrites"),mode:l.options.compression_mode,algorithm:l.options.compression_algorithm,minBlobSize:this.dimlessBinaryPipe.transform(l.options.compression_min_blob_size),maxBlobSize:this.dimlessBinaryPipe.transform(l.options.compression_max_blob_size),ratio:l.options.compression_required_ratio};Object.keys(e).forEach(function(l){var u=e[l];i.isUndefined(u)||""===u||n.form.silentSet(l,u)}),this.data.pgs=this.form.getValue("pgNum"),this.data.applications.selected=l.application_metadata},l.prototype.listenToChanges=function(){this.listenToChangesDuringAddEdit(),this.editing||this.listenToChangesDuringAdd()},l.prototype.listenToChangesDuringAddEdit=function(){var l=this;this.form.get("pgNum").valueChanges.subscribe(function(n){var e=n-l.data.pgs;1===Math.abs(e)&&2!==n?l.doPgPowerJump(e):l.data.pgs=n})},l.prototype.doPgPowerJump=function(l){var n=this.calculatePgPower()+l;this.setPgs(-1===l?Math.round(n):Math.floor(n))},l.prototype.calculatePgPower=function(l){return void 0===l&&(l=this.form.getValue("pgNum")),Math.log(l)/Math.log(2)},l.prototype.setPgs=function(l){var n=Math.pow(2,l<0?0:l);this.data.pgs=n,this.form.silentSet("pgNum",n)},l.prototype.listenToChangesDuringAdd=function(){var l=this;this.form.get("poolType").valueChanges.subscribe(function(n){l.form.get("size").updateValueAndValidity(),l.rulesChange(),"replicated"===n&&l.replicatedRuleChange(),l.pgCalc()}),this.form.get("crushRule").valueChanges.subscribe(function(){"replicated"===l.form.getValue("poolType")&&l.replicatedRuleChange(),l.pgCalc()}),this.form.get("size").valueChanges.subscribe(function(){l.pgCalc()}),this.form.get("erasureProfile").valueChanges.subscribe(function(){l.pgCalc()}),this.form.get("mode").valueChanges.subscribe(function(){["minBlobSize","maxBlobSize","ratio"].forEach(function(n){l.form.get(n).updateValueAndValidity({emitEvent:!1})})}),this.form.get("minBlobSize").valueChanges.subscribe(function(){l.form.get("maxBlobSize").updateValueAndValidity({emitEvent:!1})}),this.form.get("maxBlobSize").valueChanges.subscribe(function(){l.form.get("minBlobSize").updateValueAndValidity({emitEvent:!1})})},l.prototype.rulesChange=function(){var l=this.form.getValue("poolType");if(l&&this.info){var n=this.info["crush_rules_"+l]||[],e=this.form.get("crushRule");1===n.length?(e.setValue(n[0]),e.disable()):(e.setValue(null),e.enable()),this.current.rules=n}else this.current.rules=[]},l.prototype.replicatedRuleChange=function(){if("replicated"===this.form.getValue("poolType")){var l=this.form.get("size"),n=this.form.getValue("size")||3,e=this.getMinSize(),u=this.getMaxSize();n<e?n=e:n>u&&(n=u),n!==l.value&&this.form.silentSet("size",n)}},l.prototype.getMinSize=function(){if(this.info&&!(this.info.osd_count<1)){var l=this.form.getValue("crushRule");return l?l.min_size:1}},l.prototype.getMaxSize=function(){if(this.info&&!(this.info.osd_count<1)){var l=this.info.osd_count;if(this.form.getValue("crushRule")){var n=this.form.get("crushRule").value.max_size;if(n<l)return n}return l}},l.prototype.pgCalc=function(){var l=this.form.getValue("poolType");if(this.info&&!this.form.get("pgNum").dirty&&l){var n=100*this.info.osd_count,e="replicated"===l?this.replicatedPgCalc(n):this.erasurePgCalc(n);if(e){var u=this.data.pgs;this.alignPgs(e),this.externalPgChange||(this.externalPgChange=u!==this.data.pgs)}}},l.prototype.replicatedPgCalc=function(l){var n=this.form.get("size"),e=n.value;if(n.valid&&e>0)return l/e},l.prototype.erasurePgCalc=function(l){var n=this.form.get("erasureProfile"),e=n.value;if((n.valid||n.disabled)&&e)return l/(e.k+e.m)},l.prototype.alignPgs=function(l){void 0===l&&(l=this.form.getValue("pgNum")),this.setPgs(Math.round(this.calculatePgPower(l<1?1:l)))},l.prototype.setComplexValidators=function(){var l=this;this.editing?this.form.get("name").setValidators([this.form.get("name").validator,g.a.custom("uniqueName",function(n){return l.data.pool&&l.info&&-1!==l.info.pool_names.indexOf(n)&&l.info.pool_names.indexOf(n)!==l.info.pool_names.indexOf(l.data.pool.pool_name)})]):(g.a.validateIf(this.form.get("size"),function(){return"replicated"===l.form.get("poolType").value},[g.a.custom("min",function(n){return l.form.getValue("size")&&n<l.getMinSize()}),g.a.custom("max",function(n){return l.form.getValue("size")&&l.getMaxSize()<n})]),this.form.get("name").setValidators([this.form.get("name").validator,g.a.custom("uniqueName",function(n){return l.info&&-1!==l.info.pool_names.indexOf(n)})])),this.setCompressionValidators()},l.prototype.setCompressionValidators=function(){var l=this;g.a.validateIf(this.form.get("minBlobSize"),function(){return l.hasCompressionEnabled()},[o.A.min(0),g.a.custom("maximum",function(n){return l.oddBlobSize(n,l.form.getValue("maxBlobSize"))})]),g.a.validateIf(this.form.get("maxBlobSize"),function(){return l.hasCompressionEnabled()},[o.A.min(0),g.a.custom("minimum",function(n){return l.oddBlobSize(l.form.getValue("minBlobSize"),n)})]),g.a.validateIf(this.form.get("ratio"),function(){return l.hasCompressionEnabled()},[o.A.min(0),o.A.max(1)])},l.prototype.oddBlobSize=function(l,n){return l=this.formatter.toBytes(l),n=this.formatter.toBytes(n),Boolean(l&&n&&l>=n)},l.prototype.hasCompressionEnabled=function(){return this.form.getValue("mode")&&"none"!==this.form.get("mode").value.toLowerCase()},l.prototype.describeCrushStep=function(l){return[l.op.replace("_"," "),l.item_name||"",l.type?l.num+" type "+l.type:""].join(" ")},l.prototype.addErasureCodeProfile=function(){var l=this;this.modalSubscription=this.modalService.onHide.subscribe(function(){return l.reloadECPs()}),this.bsModalService.show(V)},l.prototype.reloadECPs=function(){var l=this;this.ecpService.list().subscribe(function(n){return l.initEcp(n)}),this.modalSubscription.unsubscribe()},l.prototype.deleteErasureCodeProfile=function(){var l=this,n=this.form.getValue("erasureProfile");if(n){var e=n.name;this.modalSubscription=this.modalService.onHide.subscribe(function(){return l.reloadECPs()}),this.modalService.show(f.a,{initialState:{itemDescription:this.i18n("erasure code profile"),itemNames:[e],submitActionObservable:function(){return l.taskWrapper.wrapTaskAroundCall({task:new v.a("ecp/delete",{name:e}),call:l.ecpService.delete(e)})}}})}},l.prototype.submit=function(){var l=this;if(this.form.invalid)this.form.setErrors({cdSubmitButton:!0});else{var n={pool:this.form.getValue("name")};this.assignFormFields(n,[{externalFieldName:"pool_type",formControlName:"poolType"},{externalFieldName:"pg_num",formControlName:"pgNum",editable:!0},"replicated"===this.form.getValue("poolType")?{externalFieldName:"size",formControlName:"size"}:{externalFieldName:"erasure_code_profile",formControlName:"erasureProfile",attr:"name"},{externalFieldName:"rule_name",formControlName:"crushRule",attr:"rule_name"}]),this.info.is_all_bluestore&&(this.assignFormField(n,{externalFieldName:"flags",formControlName:"ecOverwrites",replaceFn:function(){return["ec_overwrites"]}}),"none"!==this.form.getValue("mode")?this.assignFormFields(n,[{externalFieldName:"compression_mode",formControlName:"mode",editable:!0,replaceFn:function(n){return l.hasCompressionEnabled()&&n}},{externalFieldName:"compression_algorithm",formControlName:"algorithm",editable:!0},{externalFieldName:"compression_min_blob_size",formControlName:"minBlobSize",replaceFn:this.formatter.toBytes,editable:!0,resetValue:0},{externalFieldName:"compression_max_blob_size",formControlName:"maxBlobSize",replaceFn:this.formatter.toBytes,editable:!0,resetValue:0},{externalFieldName:"compression_required_ratio",formControlName:"ratio",editable:!0,resetValue:0}]):this.editing&&this.assignFormFields(n,[{externalFieldName:"compression_mode",formControlName:"mode",editable:!0,replaceFn:function(){return"unset"}},{externalFieldName:"srcpool",formControlName:"name",editable:!0,replaceFn:function(){return l.data.pool.pool_name}}]));var e=this.data.applications.selected;(e.length>0||this.editing)&&(n.application_metadata=e),"replicated"!==this.form.get("poolType").value||i.isEmpty(this.currentConfigurationValues)||(n.configuration=this.currentConfigurationValues),this.triggerApiTask(n)}},l.prototype.assignFormFields=function(l,n){var e=this;n.forEach(function(n){return e.assignFormField(l,n)})},l.prototype.assignFormField=function(l,n){var e=n.externalFieldName,u=n.formControlName,t=n.attr,o=n.replaceFn,a=n.editable,r=n.resetValue;if(!this.editing||a&&!this.form.get(u).pristine){var s=this.form.getValue(u),d=o?o(s):t?i.get(s,t):s;if(!s||!d){if(!a||i.isUndefined(r))return;d=r}l[e]=d}},l.prototype.triggerApiTask=function(l){var n=this;this.taskWrapper.wrapTaskAroundCall({task:new v.a("pool/"+(this.editing?t.e.EDIT:t.e.CREATE),{pool_name:l.hasOwnProperty("srcpool")?l.srcpool:l.pool}),call:this.poolService[this.editing?t.e.UPDATE:t.e.CREATE](l)}).subscribe(void 0,function(l){i.isObject(l.error)&&"34"===l.error.code&&n.form.get("pgNum").setErrors({34:!0}),n.form.setErrors({cdSubmitButton:!0})},function(){return n.router.navigate(["/pool"])})},l.prototype.appSelection=function(){this.form.updateValueAndValidity({emitEvent:!1,onlySelf:!0})},l}(),_=e("MuvH"),D=e("uIqm"),P=e("x38r"),k=e("yJti"),z=e("vCyI"),x=e("o4+5"),F=e("VTlA"),q=e("EgGo"),A=e("d+Og"),O=function(){return function(l){this.pool_name=l}}(),L=new q.a("pool"),j=function(){function l(l,n,e,u,t,o,a,r,s,d,c){var p=this;this.poolService=l,this.taskWrapper=n,this.authStorageService=e,this.taskListService=u,this.modalService=t,this.i18n=o,this.pgCategoryService=a,this.dimlessPipe=r,this.urlBuilder=s,this.configurationService=d,this.actionLabels=c,this.pools=[],this.selection=new z.a,this.executingTasks=[],this.selectionCacheTiers=[],this.monAllowPoolDelete=!1,this.permissions=this.authStorageService.getPermissions(),this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return p.urlBuilder.getCreate()},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return p.urlBuilder.getEdit(encodeURIComponent(p.selection.first().pool_name))},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-trash-o",click:function(){return p.deletePoolModal()},name:this.actionLabels.DELETE,disable:function(){return!p.selection.first()||!p.monAllowPoolDelete},disableDesc:function(){return p.getDisableDesc()}}],this.permissions.configOpt.read&&this.configurationService.get("mon_allow_pool_delete").subscribe(function(l){if(i.has(l,"value")){var n=i.find(l.value,function(l){return"mon"===l.section})||{value:!1};p.monAllowPoolDelete="true"===n.value}})}return l.prototype.ngOnInit=function(){var l=this,n=function(l,n,e){return i.get(n,l)>i.get(e,l)?1:-1};this.columns=[{prop:"pool_name",name:this.i18n("Name"),flexGrow:4,cellTransformation:P.a.executing},{prop:"type",name:this.i18n("Type"),flexGrow:2},{prop:"application_metadata",name:this.i18n("Applications"),flexGrow:3},{prop:"pg_status",name:this.i18n("PG Status"),flexGrow:3,cellClass:function(n){return l.getPgStatusCellClass(n.row,n.column,n.value)}},{prop:"size",name:this.i18n("Replica Size"),flexGrow:2,cellClass:"text-right"},{prop:"last_change",name:this.i18n("Last Change"),flexGrow:2,cellClass:"text-right"},{prop:"erasure_code_profile",name:this.i18n("Erasure Coded Profile"),flexGrow:2},{prop:"crush_rule",name:this.i18n("Crush Ruleset"),flexGrow:3},{name:this.i18n("Usage"),prop:"usage",cellTemplate:this.poolUsageTpl,flexGrow:3},{prop:"stats.rd_bytes.rates",name:this.i18n("Read bytes"),comparator:function(l,e,u,t){return n("stats.rd_bytes.latest",u,t)},cellTransformation:P.a.sparkline,flexGrow:3},{prop:"stats.wr_bytes.rates",name:this.i18n("Write bytes"),comparator:function(l,e,u,t){return n("stats.wr_bytes.latest",u,t)},cellTransformation:P.a.sparkline,flexGrow:3},{prop:"stats.rd.rate",name:this.i18n("Read ops"),flexGrow:1,pipe:this.dimlessPipe,cellTransformation:P.a.perSecond},{prop:"stats.wr.rate",name:this.i18n("Write ops"),flexGrow:1,pipe:this.dimlessPipe,cellTransformation:P.a.perSecond}],this.taskListService.init(function(){return l.poolService.getList()},void 0,function(n){return l.pools=l.transformPoolsData(n)},function(){l.table.reset(),l.viewCacheStatusList=[{status:k.a.ValueException}]},function(l){return l.name.startsWith("pool/")},function(l,n){return n.metadata.pool_name===l.pool_name},{default:function(l){return new O(l.metadata.pool_name)}})},l.prototype.updateSelection=function(l){this.selection=l,this.getSelectionTiers()},l.prototype.deletePoolModal=function(){var l=this,n=this.selection.first().pool_name;this.modalRef=this.modalService.show(f.a,{initialState:{itemDescription:"Pool",itemNames:[n],submitActionObservable:function(){return l.taskWrapper.wrapTaskAroundCall({task:new v.a("pool/"+t.e.DELETE,{pool_name:n}),call:l.poolService.delete(n)})}}})},l.prototype.getPgStatusCellClass=function(l,n,e){var u;return(u={"text-right":!0})["pg-"+this.pgCategoryService.getTypeByStates(e)]=!0,u},l.prototype.transformPoolsData=function(l){var n=this,e=["bytes_used","max_avail","avail_raw","percent_used","rd_bytes","wr_bytes","rd","wr"],u={latest:0,rate:0,rates:[]};return i.forEach(l,function(l){l.pg_status=n.transformPgStatus(l.pg_status);var t={};i.forEach(e,function(n){t[n]=l.stats&&l.stats[n]?l.stats[n]:u}),l.stats=t,l.usage=t.percent_used.latest,l.cdExecuting||l.pg_num+l.pg_placement_num===l.pg_num_target+l.pg_placement_num_target||(l.cdExecuting="Updating"),["rd_bytes","wr_bytes"].forEach(function(n){l.stats[n].rates=l.stats[n].rates.map(function(l){return l[1]})}),l.cdIsBinary=!0}),l},l.prototype.transformPgStatus=function(l){var n=[];return i.forEach(l,function(l,e){n.push(l+" "+e)}),n.join(", ")},l.prototype.getSelectionTiers=function(){var l=this.selection.hasSingleSelection?this.selection.first().tiers:[];this.selectionCacheTiers=this.pools.filter(function(n){return l.includes(n.pool)})},l.prototype.getDisableDesc=function(){if(!this.monAllowPoolDelete)return this.i18n("Pool deletion is disabled by the mon_allow_pool_delete configuration setting.")},l}(),M=function(){return function(){}}(),U={breadcrumbs:t.a.CREATE},B={breadcrumbs:t.a.EDIT},G=function(){return function(){}}(),K=e("ES0t"),$=e("MdoF"),J=e("Xg1U"),H=e("z5nN"),W=e("iutN"),Z=e("EEJc"),Y=e("PEr+"),X=e("a40w"),Q=e("pMnS"),ll=e("RIVN"),nl=e("nP0W"),el=e("VBM6"),ul=e("atuK"),tl=e("JIi+"),ol=e("Ur3J"),il=e("I4Qz"),al=e("0rTx"),rl=e("lz+O"),sl=e("u2XS"),dl=e("nhAp"),cl=e("l7Jr"),pl=e("bUo2"),fl=e("Ip0R"),ml=e("4HWh"),gl=e("p4Cf"),hl=e("ANnk"),vl=e("f/UV"),bl=e("8xTl"),Cl=e("IZUe"),Rl=e("gp3X"),yl=e("sb0X"),Il=e("KVJa"),El=e("Z21x"),Vl=e("DQlY"),Tl=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function wl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Sl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The name can only consist of alphanumeric characters, dashes and underscores."]))],null,null)}function Nl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The chosen erasure code profile name is already in use."]))],null,null)}function _l(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function Dl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Pl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function kl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function zl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function xl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Must be equal to or greater than 2."]))],null,null)}function Fl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function ql(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Al(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Must be equal to or greater than 1."]))],null,null)}function Ol(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Must be equal to or greater than 1."]))],null,null)}function Ll(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](1,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](2,{"has-error":0}),(l()(),u["\u0275eld"](3,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","c"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Durability estimator (c)"])),(l()(),u["\u0275eld"](6,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](7,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](8,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](9,0,null,null,7,"input",[["class","form-control"],["formControlName","c"],["id","c"],["name","c"],["placeholder","Coding chunks..."],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,11)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,11).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,12).onTouched()&&t),t},null,null)),u["\u0275did"](10,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](11,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](12,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](14,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](16,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ol)),u["\u0275did"](18,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.form.showError("c",u["\u0275nov"](n.parent,12)));l(n,1,0,"form-group",t),l(n,7,0,e.tooltips.plugins.shec.c),l(n,14,0,"c"),l(n,18,0,e.form.showError("c",u["\u0275nov"](n.parent,12),"min"))},function(l,n){l(n,9,0,u["\u0275nov"](n,16).ngClassUntouched,u["\u0275nov"](n,16).ngClassTouched,u["\u0275nov"](n,16).ngClassPristine,u["\u0275nov"](n,16).ngClassDirty,u["\u0275nov"](n,16).ngClassValid,u["\u0275nov"](n,16).ngClassInvalid,u["\u0275nov"](n,16).ngClassPending)})}function jl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Ml(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Must be equal to or greater than 1."]))],null,null)}function Ul(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,21,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](1,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](2,{"has-error":0}),(l()(),u["\u0275eld"](3,0,null,null,5,"label",[["class","control-label col-sm-3"],["for","l"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Locality (l)"])),(l()(),u["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](8,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](9,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](10,0,null,null,7,"input",[["class","form-control"],["formControlName","l"],["id","l"],["name","l"],["placeholder","Coding chunks..."],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,12)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,12).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,12)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,12)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,13).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,13).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,13).onTouched()&&t),t},null,null)),u["\u0275did"](11,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](12,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](13,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](15,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](17,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,jl)),u["\u0275did"](19,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ml)),u["\u0275did"](21,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.form.showError("l",u["\u0275nov"](n.parent,12)));l(n,1,0,"form-group",t),l(n,8,0,e.tooltips.plugins.lrc.l),l(n,15,0,"l"),l(n,19,0,e.form.showError("l",u["\u0275nov"](n.parent,12),"required")),l(n,21,0,e.form.showError("l",u["\u0275nov"](n.parent,12),"min"))},function(l,n){l(n,10,0,u["\u0275nov"](n,17).ngClassUntouched,u["\u0275nov"](n,17).ngClassTouched,u["\u0275nov"](n,17).ngClassPristine,u["\u0275nov"](n,17).ngClassDirty,u["\u0275nov"](n,17).ngClassValid,u["\u0275nov"](n,17).ngClassInvalid,u["\u0275nov"](n,17).ngClassPending)})}function Bl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function Gl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Kl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function $l(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["None"]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function Jl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Hl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","crushLocality"]],null,null,null,null,null)),(l()(),u["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Crush Locality"])),(l()(),u["\u0275eld"](4,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](5,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](6,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,12,"select",[["class","form-control"],["formControlName","crushLocality"],["id","crushLocality"],["name","crushLocality"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,9).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,9).onTouched()&&t),t},null,null)),u["\u0275did"](8,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](9,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](11,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](13,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Kl)),u["\u0275did"](15,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,$l)),u["\u0275did"](17,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Jl)),u["\u0275did"](19,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,5,0,e.tooltips.plugins.lrc.crushLocality),l(n,11,0,"crushLocality"),l(n,15,0,!e.failureDomains),l(n,17,0,e.failureDomains&&e.failureDomains.length>0),l(n,19,0,e.failureDomains)},function(l,n){l(n,7,0,u["\u0275nov"](n,13).ngClassUntouched,u["\u0275nov"](n,13).ngClassTouched,u["\u0275nov"](n,13).ngClassPristine,u["\u0275nov"](n,13).ngClassDirty,u["\u0275nov"](n,13).ngClassValid,u["\u0275nov"](n,13).ngClassInvalid,u["\u0275nov"](n,13).ngClassPending)})}function Wl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Zl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,15,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","technique"]],null,null,null,null,null)),(l()(),u["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Technique"])),(l()(),u["\u0275eld"](4,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](5,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](6,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,8,"select",[["class","form-control"],["formControlName","technique"],["id","technique"],["name","technique"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,9).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,9).onTouched()&&t),t},null,null)),u["\u0275did"](8,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](9,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](11,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](13,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Wl)),u["\u0275did"](15,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,5,0,e.tooltips.plugins[e.plugin].technique),l(n,11,0,"technique"),l(n,15,0,e.techniques)},function(l,n){l(n,7,0,u["\u0275nov"](n,13).ngClassUntouched,u["\u0275nov"](n,13).ngClassTouched,u["\u0275nov"](n,13).ngClassPristine,u["\u0275nov"](n,13).ngClassDirty,u["\u0275nov"](n,13).ngClassValid,u["\u0275nov"](n,13).ngClassInvalid,u["\u0275nov"](n,13).ngClassPending)})}function Yl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Must be equal to or greater than 1."]))],null,null)}function Xl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](1,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](2,{"has-error":0}),(l()(),u["\u0275eld"](3,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","packetSize"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Packetsize"])),(l()(),u["\u0275eld"](6,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](7,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](8,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](9,0,null,null,7,"input",[["class","form-control"],["formControlName","packetSize"],["id","packetSize"],["name","packetSize"],["placeholder","Packetsize..."],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,11)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,11).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,12).onTouched()&&t),t},null,null)),u["\u0275did"](10,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](11,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](12,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](14,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](16,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Yl)),u["\u0275did"](18,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.form.showError("packetSize",u["\u0275nov"](n.parent,12)));l(n,1,0,"form-group",t),l(n,7,0,e.tooltips.plugins.jerasure.packetSize),l(n,14,0,"packetSize"),l(n,18,0,e.form.showError("packetSize",u["\u0275nov"](n.parent,12),"min"))},function(l,n){l(n,9,0,u["\u0275nov"](n,16).ngClassUntouched,u["\u0275nov"](n,16).ngClassTouched,u["\u0275nov"](n,16).ngClassPristine,u["\u0275nov"](n,16).ngClassDirty,u["\u0275nov"](n,16).ngClassValid,u["\u0275nov"](n,16).ngClassInvalid,u["\u0275nov"](n,16).ngClassPending)})}function Ql(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function ln(l){return u["\u0275vid"](0,[u["\u0275pid"](0,fl.TitleCasePipe,[]),u["\u0275pid"](0,bl.a,[]),(l()(),u["\u0275eld"](2,0,null,null,7,"div",[["class","modal-header"]],null,null,null,null,null)),(l()(),u["\u0275eld"](3,0,null,null,3,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(l()(),u["\u0275ted"](4,null,[""," ",""])),u["\u0275ppd"](5,1),u["\u0275ppd"](6,1),(l()(),u["\u0275eld"](7,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==l.component.bsModalRef.hide()&&u),u},null,null)),(l()(),u["\u0275eld"](8,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["\xd7"])),(l()(),u["\u0275eld"](10,0,null,null,181,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var t=!0;return"submit"===n&&(t=!1!==u["\u0275nov"](l,12).onSubmit(e)&&t),"reset"===n&&(t=!1!==u["\u0275nov"](l,12).onReset()&&t),t},null,null)),u["\u0275did"](11,16384,null,0,o.D,[],null,null),u["\u0275did"](12,540672,[["frm",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),u["\u0275prd"](2048,null,o.d,null,[o.l]),u["\u0275did"](14,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),u["\u0275eld"](15,0,null,null,168,"div",[["class","modal-body"]],null,null,null,null,null)),(l()(),u["\u0275eld"](16,0,null,null,21,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](17,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](18,{"has-error":0}),(l()(),u["\u0275eld"](19,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275eld"](20,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Name"])),(l()(),u["\u0275eld"](22,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](23,0,null,null,14,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](24,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["placeholder","Name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,27)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,27).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,27)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,27)._compositionEnd(e.target.value)&&t),t},null,null)),u["\u0275did"](25,4210688,null,0,Cl.a,[u.ElementRef],null,null),u["\u0275did"](26,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](27,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](29,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](31,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,wl)),u["\u0275did"](33,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Sl)),u["\u0275did"](35,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Nl)),u["\u0275did"](37,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](38,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](39,0,null,null,5,"label",[["class","control-label col-sm-3"],["for","plugin"]],null,null,null,null,null)),(l()(),u["\u0275eld"](40,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Plugin"])),(l()(),u["\u0275eld"](42,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](43,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](44,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](45,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](46,0,null,null,10,"select",[["class","form-control"],["formControlName","plugin"],["id","plugin"],["name","plugin"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,48).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,48).onTouched()&&t),t},null,null)),u["\u0275did"](47,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](48,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](50,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](52,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,_l)),u["\u0275did"](54,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Dl)),u["\u0275did"](56,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Pl)),u["\u0275did"](58,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](59,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](60,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](61,{"has-error":0}),(l()(),u["\u0275eld"](62,0,null,null,6,"label",[["class","control-label col-sm-3"],["for","k"]],null,null,null,null,null)),(l()(),u["\u0275eld"](63,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Data chunks (k)"])),(l()(),u["\u0275and"](16777216,null,null,1,null,kl)),u["\u0275did"](66,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](67,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](68,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](69,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](70,0,null,null,7,"input",[["class","form-control"],["formControlName","k"],["id","k"],["name","k"],["ng-model","$ctrl.erasureCodeProfile.k"],["placeholder","Data chunks..."],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,72)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,72).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,72)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,72)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,73).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,73).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,73).onTouched()&&t),t},null,null)),u["\u0275did"](71,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](72,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](73,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](75,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](77,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,zl)),u["\u0275did"](79,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,xl)),u["\u0275did"](81,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](82,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](83,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](84,{"has-error":0}),(l()(),u["\u0275eld"](85,0,null,null,6,"label",[["class","control-label col-sm-3"],["for","m"]],null,null,null,null,null)),(l()(),u["\u0275eld"](86,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Coding chunks (m)"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Fl)),u["\u0275did"](89,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](90,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](91,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](92,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](93,0,null,null,7,"input",[["class","form-control"],["formControlName","m"],["id","m"],["name","m"],["placeholder","Coding chunks..."],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,95)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,95).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,95)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,95)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,96).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,96).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,96).onTouched()&&t),t},null,null)),u["\u0275did"](94,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](95,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](96,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](98,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](100,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,ql)),u["\u0275did"](102,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Al)),u["\u0275did"](104,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ll)),u["\u0275did"](106,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ul)),u["\u0275did"](108,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](109,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](110,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","crushFailureDomain"]],null,null,null,null,null)),(l()(),u["\u0275eld"](111,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Crush failure domain"])),(l()(),u["\u0275eld"](113,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](114,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](115,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](116,0,null,null,10,"select",[["class","form-control"],["formControlName","crushFailureDomain"],["id","crushFailureDomain"],["name","crushFailureDomain"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,118).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,118).onTouched()&&t),t},null,null)),u["\u0275did"](117,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](118,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](120,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](122,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Bl)),u["\u0275did"](124,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Gl)),u["\u0275did"](126,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Hl)),u["\u0275did"](128,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,2,null,Zl)),u["\u0275did"](130,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),u["\u0275pad"](131,2),(l()(),u["\u0275and"](16777216,null,null,1,null,Xl)),u["\u0275did"](133,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](134,0,null,null,15,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](135,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](136,{"has-error":0}),(l()(),u["\u0275eld"](137,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","crushRoot"]],null,null,null,null,null)),(l()(),u["\u0275eld"](138,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Crush root"])),(l()(),u["\u0275eld"](140,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](141,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](142,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](143,0,null,null,6,"input",[["class","form-control"],["formControlName","crushRoot"],["id","crushRoot"],["name","crushRoot"],["placeholder","root..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,145)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,145).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,145)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,145)._compositionEnd(e.target.value)&&t),t},null,null)),u["\u0275did"](144,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](145,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](147,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](149,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](150,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](151,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","crushDeviceClass"]],null,null,null,null,null)),(l()(),u["\u0275eld"](152,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Crush device class"])),(l()(),u["\u0275eld"](154,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](155,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](156,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](157,0,null,null,12,"select",[["class","form-control"],["formControlName","crushDeviceClass"],["id","crushDeviceClass"],["name","crushDeviceClass"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,159).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,159).onTouched()&&t),t},null,null)),u["\u0275did"](158,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](159,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](161,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](163,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](164,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](165,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](166,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["any"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Ql)),u["\u0275did"](169,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275eld"](170,0,null,null,13,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](171,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","directory"]],null,null,null,null,null)),(l()(),u["\u0275eld"](172,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Directory"])),(l()(),u["\u0275eld"](174,0,null,null,1,"cd-helper",[],null,null,null,ml.b,ml.a)),u["\u0275did"](175,49152,null,0,gl.a,[],{html:[0,"html"]},null),(l()(),u["\u0275eld"](176,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](177,0,null,null,6,"input",[["class","form-control"],["formControlName","directory"],["id","directory"],["name","directory"],["placeholder","Path..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,179)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,179).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,179)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,179)._compositionEnd(e.target.value)&&t),t},null,null)),u["\u0275did"](178,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](179,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](181,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](183,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](184,0,null,null,7,"div",[["class","modal-footer"]],null,null,null,null,null)),(l()(),u["\u0275eld"](185,0,null,null,4,"cd-submit-button",[],null,[[null,"submitAction"]],function(l,n,e){var u=!0;return"submitAction"===n&&(u=!1!==l.component.onSubmit()&&u),u},Rl.b,Rl.a)),u["\u0275did"](186,114688,null,0,yl.a,[u.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(l()(),u["\u0275ted"](187,0,[""," ",""])),u["\u0275ppd"](188,1),u["\u0275ppd"](189,1),(l()(),u["\u0275eld"](190,0,null,null,1,"cd-back-button",[],null,null,null,Il.b,Il.a)),u["\u0275did"](191,49152,null,0,El.a,[fl.Location,t.b],{back:[0,"back"]},null)],function(l,n){var e=n.component;l(n,12,0,e.form);var t=l(n,18,0,e.form.showError("name",u["\u0275nov"](n,12)));l(n,17,0,"form-group",t),l(n,29,0,"name"),l(n,33,0,e.form.showError("name",u["\u0275nov"](n,12),"required")),l(n,35,0,e.form.showError("name",u["\u0275nov"](n,12),"pattern")),l(n,37,0,e.form.showError("name",u["\u0275nov"](n,12),"uniqueName")),l(n,44,0,e.tooltips.plugins[e.plugin].description),l(n,50,0,"plugin"),l(n,54,0,!e.plugins),l(n,56,0,e.plugins),l(n,58,0,e.form.showError("name",u["\u0275nov"](n,12),"required"));var o=l(n,61,0,e.form.showError("k",u["\u0275nov"](n,12)));l(n,60,0,"form-group",o),l(n,66,0,e.requiredControls.includes("k")),l(n,68,0,e.tooltips.k),l(n,75,0,"k"),l(n,79,0,e.form.showError("k",u["\u0275nov"](n,12),"required")),l(n,81,0,e.form.showError("k",u["\u0275nov"](n,12),"min"));var i=l(n,84,0,e.form.showError("m",u["\u0275nov"](n,12)));l(n,83,0,"form-group",i),l(n,89,0,e.requiredControls.includes("m")),l(n,91,0,e.tooltips.m),l(n,98,0,"m"),l(n,102,0,e.form.showError("m",u["\u0275nov"](n,12),"required")),l(n,104,0,e.form.showError("m",u["\u0275nov"](n,12),"min")),l(n,106,0,"shec"===e.plugin),l(n,108,0,e.plugin===e.PLUGIN.LRC),l(n,114,0,e.tooltips.crushFailureDomain),l(n,120,0,"crushFailureDomain"),l(n,124,0,!e.failureDomains),l(n,126,0,e.failureDomains),l(n,128,0,e.plugin===e.PLUGIN.LRC);var a=l(n,131,0,e.PLUGIN.JERASURE,e.PLUGIN.ISA).includes(e.plugin);l(n,130,0,a),l(n,133,0,e.plugin===e.PLUGIN.JERASURE);var r=l(n,136,0,e.form.showError("crushRoot",u["\u0275nov"](n,12)));l(n,135,0,"form-group",r),l(n,141,0,e.tooltips.crushRoot),l(n,147,0,"crushRoot"),l(n,155,0,e.tooltips.crushDeviceClass),l(n,161,0,"crushDeviceClass"),l(n,165,0,""),l(n,166,0,""),l(n,169,0,e.devices),l(n,175,0,e.tooltips.directory),l(n,181,0,"directory"),l(n,186,0,u["\u0275nov"](n,12)),l(n,191,0,e.bsModalRef.hide)},function(l,n){var e=n.component,t=u["\u0275unv"](n,4,0,l(n,5,0,u["\u0275nov"](n,0),e.action)),o=u["\u0275unv"](n,4,1,l(n,6,0,u["\u0275nov"](n,1),e.resource));l(n,4,0,t,o),l(n,10,0,u["\u0275nov"](n,14).ngClassUntouched,u["\u0275nov"](n,14).ngClassTouched,u["\u0275nov"](n,14).ngClassPristine,u["\u0275nov"](n,14).ngClassDirty,u["\u0275nov"](n,14).ngClassValid,u["\u0275nov"](n,14).ngClassInvalid,u["\u0275nov"](n,14).ngClassPending),l(n,24,0,u["\u0275nov"](n,31).ngClassUntouched,u["\u0275nov"](n,31).ngClassTouched,u["\u0275nov"](n,31).ngClassPristine,u["\u0275nov"](n,31).ngClassDirty,u["\u0275nov"](n,31).ngClassValid,u["\u0275nov"](n,31).ngClassInvalid,u["\u0275nov"](n,31).ngClassPending),l(n,46,0,u["\u0275nov"](n,52).ngClassUntouched,u["\u0275nov"](n,52).ngClassTouched,u["\u0275nov"](n,52).ngClassPristine,u["\u0275nov"](n,52).ngClassDirty,u["\u0275nov"](n,52).ngClassValid,u["\u0275nov"](n,52).ngClassInvalid,u["\u0275nov"](n,52).ngClassPending),l(n,70,0,u["\u0275nov"](n,77).ngClassUntouched,u["\u0275nov"](n,77).ngClassTouched,u["\u0275nov"](n,77).ngClassPristine,u["\u0275nov"](n,77).ngClassDirty,u["\u0275nov"](n,77).ngClassValid,u["\u0275nov"](n,77).ngClassInvalid,u["\u0275nov"](n,77).ngClassPending),l(n,93,0,u["\u0275nov"](n,100).ngClassUntouched,u["\u0275nov"](n,100).ngClassTouched,u["\u0275nov"](n,100).ngClassPristine,u["\u0275nov"](n,100).ngClassDirty,u["\u0275nov"](n,100).ngClassValid,u["\u0275nov"](n,100).ngClassInvalid,u["\u0275nov"](n,100).ngClassPending),l(n,116,0,u["\u0275nov"](n,122).ngClassUntouched,u["\u0275nov"](n,122).ngClassTouched,u["\u0275nov"](n,122).ngClassPristine,u["\u0275nov"](n,122).ngClassDirty,u["\u0275nov"](n,122).ngClassValid,u["\u0275nov"](n,122).ngClassInvalid,u["\u0275nov"](n,122).ngClassPending),l(n,143,0,u["\u0275nov"](n,149).ngClassUntouched,u["\u0275nov"](n,149).ngClassTouched,u["\u0275nov"](n,149).ngClassPristine,u["\u0275nov"](n,149).ngClassDirty,u["\u0275nov"](n,149).ngClassValid,u["\u0275nov"](n,149).ngClassInvalid,u["\u0275nov"](n,149).ngClassPending),l(n,157,0,u["\u0275nov"](n,163).ngClassUntouched,u["\u0275nov"](n,163).ngClassTouched,u["\u0275nov"](n,163).ngClassPristine,u["\u0275nov"](n,163).ngClassDirty,u["\u0275nov"](n,163).ngClassValid,u["\u0275nov"](n,163).ngClassInvalid,u["\u0275nov"](n,163).ngClassPending),l(n,177,0,u["\u0275nov"](n,183).ngClassUntouched,u["\u0275nov"](n,183).ngClassTouched,u["\u0275nov"](n,183).ngClassPristine,u["\u0275nov"](n,183).ngClassDirty,u["\u0275nov"](n,183).ngClassValid,u["\u0275nov"](n,183).ngClassInvalid,u["\u0275nov"](n,183).ngClassPending);var i=u["\u0275unv"](n,187,0,l(n,188,0,u["\u0275nov"](n,0),e.action)),a=u["\u0275unv"](n,187,1,l(n,189,0,u["\u0275nov"](n,1),e.resource));l(n,187,0,i,a)})}function nn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-erasure-code-profile-form",[],null,null,null,ln,Tl)),u["\u0275did"](1,114688,null,0,V,[I.a,Vl.a,y.a,c,s.a,t.b],null,null)],function(l,n){l(n,1,0)},null)}var en=u["\u0275ccf"]("cd-erasure-code-profile-form",V,nn,{},{submitAction:"submitAction"},[]),un=e("iExv"),tn=e("85J/"),on=e("+0ag"),an=e("IzCI"),rn=e("Dwqy"),sn=e("uYzU"),dn=e("uhwM"),cn=e("E2fk"),pn=e("a0VL"),fn=e("nSDx"),mn=e("SB+Q"),gn=e("TYzs"),hn=e("BQkM"),vn=e("dEH0"),bn=e("G1/K"),Cn=e("TJUb"),Rn=e("lTVp"),yn=e("OZfm"),In=e("NJnL"),En=e("lqqz"),Vn=e("eajB"),Tn=e("FO+L"),wn=e("ZYjt"),Sn=e("nhM1"),Nn=e("BARL"),_n=e("xtZt"),Dn=e("Avrn"),Pn=e("ZYCi"),kn=e("urB8"),zn=e("JZ5S"),xn=e("Tff5"),Fn=e("YAQW"),qn=e("Da1D"),An=e("ARl4"),On=e("kJI8"),Ln=e("9Xeq"),jn=e("xdbM"),Mn=e("yGOH"),Un=e("V/fk"),Bn=e("F8xH"),Gn=e("ChqD"),Kn=e("PCNd"),$n=e("STEd"),Jn=e("kccj"),Hn=e("k/xb"),Wn=e("C6Ij"),Zn=e("AWcq"),Yn=e("xSw7"),Xn=e("GgAd"),Qn=e("a278"),le=e("insk"),ne=e("mSOc"),ee=e("20UP"),ue=e("pKUh"),te=e("25BL"),oe=e("NUGo"),ie=e("S7zO"),ae=e("EFGL"),re=e("aAWM"),se=e("o8EM"),de=e("sLuX"),ce=e("FSuO"),pe=(e("jKX/"),function(){function l(l,n){this.i18n=l,this.poolService=n,this.cacheTierColumns=[],this.cacheTierColumns=[{prop:"pool_name",name:this.i18n("Name"),flexGrow:3},{prop:"cache_mode",name:this.i18n("Cache Mode"),flexGrow:2},{prop:"cache_min_evict_age",name:this.i18n("Min Evict Age"),flexGrow:2},{prop:"cache_min_flush_age",name:this.i18n("Min Flush Age"),flexGrow:2},{prop:"target_max_bytes",name:this.i18n("Target Max Bytes"),flexGrow:2},{prop:"target_max_objects",name:this.i18n("Target Max Objects"),flexGrow:2}]}return l.prototype.ngOnChanges=function(){var l=this;this.selection.hasSingleSelection&&this.poolService.getConfiguration(this.selection.first().pool_name).subscribe(function(n){l.selectedPoolConfiguration=n})},l.prototype.filterNonPoolData=function(l){return i.omit(l,["cdExecuting","cdIsBinary"])},l}()),fe=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function me(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"tab",[["heading","Performance Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](1,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","one"],["uid","-xyV8KCiz"]],null,null,null,Qn.b,Qn.a)),u["\u0275did"](3,638976,null,0,le.a,[ne.a,wn.DomSanitizer,ee.a,on.a,s.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(l,n){var e=n.component;l(n,1,0,"Performance Details"),l(n,3,0,"ceph-pool-detail?var-pool_name="+e.selection.first().pool_name,"one","-xyV8KCiz")},function(l,n){l(n,0,0,u["\u0275nov"](n,1).id,u["\u0275nov"](n,1).active,u["\u0275nov"](n,1).addClass)})}function ge(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"tab",[["heading","Configuration"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](1,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](2,0,null,null,1,"cd-rbd-configuration-table",[],null,null,null,ae.b,ae.a)),u["\u0275did"](3,638976,null,0,re.a,[R.a,se.a,s.a],{data:[0,"data"]},null)],function(l,n){var e=n.component;l(n,1,0,"Configuration"),l(n,3,0,e.selectedPoolConfiguration)},function(l,n){l(n,0,0,u["\u0275nov"](n,1).id,u["\u0275nov"](n,1).active,u["\u0275nov"](n,1).addClass)})}function he(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"tab",[["heading","Cache Tiers Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](1,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](2,0,null,null,1,"cd-table",[["columnMode","flex"]],null,null,null,te.b,te.a)),u["\u0275did"](3,2867200,null,0,D.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoSave:[3,"autoSave"]},null)],function(l,n){var e=n.component;l(n,1,0,"Cache Tiers Details"),l(n,3,0,e.cacheTiers,e.cacheTierColumns,"flex",!1)},function(l,n){l(n,0,0,u["\u0275nov"](n,1).id,u["\u0275nov"](n,1).active,u["\u0275nov"](n,1).addClass)})}function ve(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,11,"tabset",[["cdTableDetail",""]],[[2,"tab-container",null]],null,null,ue.b,ue.a)),u["\u0275did"](1,180224,[[1,4],["tabsetChild",4]],0,Fn.d,[Fn.e,u.Renderer2,u.ElementRef],null,null),(l()(),u["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](3,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,null,null,de.b,de.a)),u["\u0275did"](5,638976,null,0,ce.a,[pn.a],{data:[0,"data"],autoReload:[1,"autoReload"],renderObjects:[2,"renderObjects"]},null),(l()(),u["\u0275and"](16777216,null,0,1,null,me)),u["\u0275did"](7,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,0,1,null,ge)),u["\u0275did"](9,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,0,1,null,he)),u["\u0275did"](11,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,3,0,"Details"),l(n,5,0,e.filterNonPoolData(e.selection.first()),!1,!0),l(n,7,0,e.permissions.grafana.read),l(n,9,0,"replicated"===e.selection.first().type),l(n,11,0,e.selection.first().tiers.length>0)},function(l,n){l(n,0,0,u["\u0275nov"](n,1).clazz),l(n,2,0,u["\u0275nov"](n,3).id,u["\u0275nov"](n,3).active,u["\u0275nov"](n,3).addClass)})}function be(l){return u["\u0275vid"](0,[u["\u0275qud"](671088640,1,{tabsetChild:0}),(l()(),u["\u0275and"](16777216,null,null,1,null,ve)),u["\u0275did"](2,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){l(n,2,0,n.component.selection.hasSingleSelection)},null)}var Ce=e("ufoC"),Re=u["\u0275crt"]({encapsulation:0,styles:[[".pg-clean{color:#0b0} .pg-working{color:#2b99a8} .pg-warning{color:#ffc200} .pg-unknown{color:red}"]],data:{}});function ye(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-view-cache",[],null,null,null,Wn.b,Wn.a)),u["\u0275did"](1,114688,null,0,Zn.a,[],{status:[0,"status"],statusFor:[1,"statusFor"]},null)],function(l,n){l(n,1,0,n.context.$implicit.status,n.context.$implicit.statusFor)},null)}function Ie(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-usage-bar",[["decimals","2"]],null,null,null,Yn.b,Yn.a)),u["\u0275did"](1,573440,null,0,Xn.a,[],{total:[0,"total"],used:[1,"used"],decimals:[2,"decimals"]},null)],function(l,n){l(n,1,0,n.parent.context.row.stats.bytes_used.latest+n.parent.context.row.stats.avail_raw.latest,n.parent.context.row.stats.bytes_used.latest,"2")},null)}function Ee(l){return u["\u0275vid"](0,[(l()(),u["\u0275and"](16777216,null,null,1,null,Ie)),u["\u0275did"](1,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,null==n.context.row.stats?null:null==n.context.row.stats.avail_raw?null:n.context.row.stats.avail_raw.latest)},null)}function Ve(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"tab",[["heading","Overall Performance"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](1,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","two"],["uid","z99hzWtmk"]],null,null,null,Qn.b,Qn.a)),u["\u0275did"](3,638976,null,0,le.a,[ne.a,wn.DomSanitizer,ee.a,on.a,s.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(l,n){l(n,1,0,"Overall Performance"),l(n,3,0,"ceph-pools-overview?","two","z99hzWtmk")},function(l,n){l(n,0,0,u["\u0275nov"](n,1).id,u["\u0275nov"](n,1).active,u["\u0275nov"](n,1).addClass)})}function Te(l){return u["\u0275vid"](0,[u["\u0275qud"](402653184,1,{table:0}),u["\u0275qud"](402653184,2,{poolUsageTpl:0}),u["\u0275qud"](402653184,3,{poolConfigurationSourceTpl:0}),(l()(),u["\u0275eld"](3,0,null,null,14,"tabset",[],[[2,"tab-container",null]],null,null,ue.b,ue.a)),u["\u0275did"](4,180224,null,0,Fn.d,[Fn.e,u.Renderer2,u.ElementRef],null,null),(l()(),u["\u0275eld"](5,0,null,0,10,"tab",[["heading","Pools List"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](6,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,ye)),u["\u0275did"](8,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275eld"](9,0,null,null,5,"cd-table",[["selectionType","single"]],null,[[null,"updateSelection"]],function(l,n,e){var u=!0;return"updateSelection"===n&&(u=!1!==l.component.updateSelection(e)&&u),u},te.b,te.a)),u["\u0275did"](10,2867200,[[1,4],["table",4]],0,D.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],selectionType:[2,"selectionType"]},{updateSelection:"updateSelection"}),(l()(),u["\u0275eld"](11,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,oe.b,oe.a)),u["\u0275did"](12,114688,null,0,ie.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),u["\u0275eld"](13,0,null,2,1,"cd-pool-details",[["cdTableDetail",""]],null,null,null,be,fe)),u["\u0275did"](14,573440,null,0,pe,[s.a,p.a],{selection:[0,"selection"],permissions:[1,"permissions"],cacheTiers:[2,"cacheTiers"]},null),(l()(),u["\u0275and"](0,[[2,2],["poolUsageTpl",2]],null,0,null,Ee)),(l()(),u["\u0275and"](16777216,null,0,1,null,Ve)),u["\u0275did"](17,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,6,0,"Pools List"),l(n,8,0,e.viewCacheStatusList),l(n,10,0,e.pools,e.columns,"single"),l(n,12,0,e.permissions.pool,e.selection,e.tableActions),l(n,14,0,e.selection,e.permissions,e.selectionCacheTiers),l(n,17,0,e.permissions.grafana.read)},function(l,n){l(n,3,0,u["\u0275nov"](n,4).clazz),l(n,5,0,u["\u0275nov"](n,6).id,u["\u0275nov"](n,6).active,u["\u0275nov"](n,6).addClass)})}function we(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"cd-pool-list",[],null,null,null,Te,Re)),u["\u0275prd"](131584,null,F.a,F.a,[Ce.a,ne.a]),u["\u0275prd"](256,null,q.a,L,[]),u["\u0275did"](3,114688,null,0,j,[p.a,y.a,C.a,F.a,Vl.b,s.a,A.a,x.a,q.a,_.a,t.b],null,null)],function(l,n){l(n,3,0)},null)}var Se=u["\u0275ccf"]("cd-pool-list",j,we,{},{},[]),Ne=e("EmSq"),_e=e("pYKc"),De=e("ppaS"),Pe=e("BH9v"),ke=e("rFfW"),ze=u["\u0275crt"]({encapsulation:0,styles:[[".crush-rule-steps[_ngcontent-%COMP%]{margin-top:10px}"]],data:{}});function xe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"h1",[["class","jumbotron"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,0,"i",[["class","fa fa-lg fa-pulse fa-spinner text-primary"]],null,null,null,null,null)),(l()(),u["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],null,null)}function Fe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function qe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The chosen Ceph pool name is already in use."]))],null,null)}function Ae(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{value:[0,"value"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function Oe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Le(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function je(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["At least one placement group is needed!"]))],null,null)}function Me(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Your cluster can't handle this many PGs. Please recalculate the PG amount needed."]))],null,null)}function Ue(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The current PGs settings were calculated for you, you should make sure the values suit your needs before submit."]))],null,null)}function Be(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit.rule_name)})}function Ge(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"li",[],null,null,null,null,null)),(l()(),u["\u0275ted"](1,null,[" "," "]))],null,function(l,n){l(n,1,0,n.component.describeCrushStep(n.context.$implicit))})}function Ke(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,11,"span",[["class","help-block"],["id","crush-info-block"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,10,"tabset",[],[[2,"tab-container",null]],null,null,ue.b,ue.a)),u["\u0275did"](2,180224,null,0,Fn.d,[Fn.e,u.Renderer2,u.ElementRef],null,null),(l()(),u["\u0275eld"](3,0,null,0,3,"tab",[["class","crush-rule-info"],["heading","Crush rule"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](4,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](5,0,null,null,1,"cd-table-key-value",[],null,null,null,de.b,de.a)),u["\u0275did"](6,638976,null,0,ce.a,[pn.a],{data:[0,"data"],autoReload:[1,"autoReload"],renderObjects:[2,"renderObjects"]},null),(l()(),u["\u0275eld"](7,0,null,0,4,"tab",[["class","crush-rule-steps"],["heading","Crush steps"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](8,212992,null,0,Fn.b,[Fn.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](9,0,null,null,2,"ol",[],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,Ge)),u["\u0275did"](11,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,4,0,"Crush rule"),l(n,6,0,e.form.getValue("crushRule"),!1,!0),l(n,8,0,"Crush steps"),l(n,11,0,e.form.get("crushRule").value.steps)},function(l,n){l(n,1,0,u["\u0275nov"](n,2).clazz),l(n,3,0,u["\u0275nov"](n,4).id,u["\u0275nov"](n,4).active,u["\u0275nov"](n,4).addClass),l(n,7,0,u["\u0275nov"](n,8).id,u["\u0275nov"](n,8).active,u["\u0275nov"](n,8).addClass)})}function $e(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The rule can't be used in the current cluster as it has to few OSDs to meet the minimum required OSD by this rule."]))],null,null)}function Je(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,28,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](1,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](2,{"has-error":0}),(l()(),u["\u0275eld"](3,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","crushRule"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Crush ruleset"])),(l()(),u["\u0275eld"](5,0,null,null,23,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](6,0,null,null,18,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,12,"select",[["class","form-control"],["formControlName","crushRule"],["id","crushRule"],["name","crushSet"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,9).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,9).onTouched()&&t),t},null,null)),u["\u0275did"](8,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](9,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](11,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](13,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](14,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](15,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](16,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["-- Select a crush rule --"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Be)),u["\u0275did"](19,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275eld"](20,0,null,null,4,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),u["\u0275eld"](21,0,null,null,3,"button",[["class","btn btn-default"],["id","crush-info-button"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0,t=l.component;return"click"===n&&(u=0!=(t.data.crushInfo=!t.data.crushInfo)&&u),u},null,null)),u["\u0275did"](22,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](23,{active:0}),(l()(),u["\u0275eld"](24,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-question-circle"]],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,Ke)),u["\u0275did"](26,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,$e)),u["\u0275did"](28,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.form.showError("crushRule",u["\u0275nov"](n.parent.parent,2)));l(n,1,0,"form-group",t),l(n,11,0,"crushRule"),l(n,15,0,null),l(n,16,0,null),l(n,19,0,e.current.rules);var o=l(n,23,0,e.data.crushInfo);l(n,22,0,"btn btn-default",o),l(n,26,0,e.data.crushInfo&&e.form.getValue("crushRule")),l(n,28,0,e.form.showError("crushRule",u["\u0275nov"](n.parent.parent,2),"tooFewOsds"))},function(l,n){l(n,7,0,u["\u0275nov"](n,13).ngClassUntouched,u["\u0275nov"](n,13).ngClassTouched,u["\u0275nov"](n,13).ngClassPristine,u["\u0275nov"](n,13).ngClassDirty,u["\u0275nov"](n,13).ngClassValid,u["\u0275nov"](n,13).ngClassInvalid,u["\u0275nov"](n,13).ngClassPending)})}function He(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,5,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,4,"ul",[["class","list-inline"]],null,null,null,null,null)),(l()(),u["\u0275eld"](2,0,null,null,1,"li",[],null,null,null,null,null)),(l()(),u["\u0275ted"](3,null,["Minimum: ",""])),(l()(),u["\u0275eld"](4,0,null,null,1,"li",[],null,null,null,null,null)),(l()(),u["\u0275ted"](5,null,["Maximum: ",""]))],null,function(l,n){var e=n.component;l(n,3,0,e.getMinSize()),l(n,5,0,e.getMaxSize())})}function We(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](1,null,["The size specified is out of range. A value from "," to "," is valid."]))],null,function(l,n){var e=n.component;l(n,1,0,e.getMinSize(),e.getMaxSize())})}function Ze(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](1,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](2,{"has-error":0}),(l()(),u["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","size"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Replicated size"])),(l()(),u["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](8,0,null,null,7,"input",[["class","form-control"],["formControlName","size"],["id","size"],["name","size"],["type","number"]],[[8,"max",0],[8,"min",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,10)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,10).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,10)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,10)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,11).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,11).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,11).onTouched()&&t),t},null,null)),u["\u0275did"](9,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](10,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](11,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](13,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](15,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,He)),u["\u0275did"](17,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,We)),u["\u0275did"](19,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,2,0,e.form.showError("size",u["\u0275nov"](n.parent.parent,2)));l(n,1,0,"form-group",t),l(n,13,0,"size"),l(n,17,0,e.form.showError("size",u["\u0275nov"](n.parent.parent,2))),l(n,19,0,e.form.showError("size",u["\u0275nov"](n.parent.parent,2)))},function(l,n){var e=n.component;l(n,8,0,e.getMaxSize(),e.getMinSize(),u["\u0275nov"](n,15).ngClassUntouched,u["\u0275nov"](n,15).ngClassTouched,u["\u0275nov"](n,15).ngClassPristine,u["\u0275nov"](n,15).ngClassDirty,u["\u0275nov"](n,15).ngClassValid,u["\u0275nov"](n,15).ngClassInvalid,u["\u0275nov"](n,15).ngClassPending)})}function Ye(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function Xe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["-- No erasure code profile available --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function Qe(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["-- Select an erasure code profile --"]))],function(l,n){l(n,1,0,null),l(n,2,0,null)},null)}function lu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit.name)})}function nu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,2,"span",[["class","help-block"],["id","ecp-info-block"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"cd-table-key-value",[],null,null,null,de.b,de.a)),u["\u0275did"](2,638976,null,0,ce.a,[pn.a],{data:[0,"data"],autoReload:[1,"autoReload"],renderObjects:[2,"renderObjects"]},null)],function(l,n){l(n,2,0,n.component.form.getValue("erasureProfile"),!1,!0)},null)}function eu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,30,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","erasureProfile"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Erasure code profile"])),(l()(),u["\u0275eld"](3,0,null,null,27,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,24,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](5,0,null,null,14,"select",[["class","form-control"],["formControlName","erasureProfile"],["id","erasureProfile"],["name","erasureProfile"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,7).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,7).onTouched()&&t),t},null,null)),u["\u0275did"](6,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](7,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](9,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](11,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ye)),u["\u0275did"](13,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Xe)),u["\u0275did"](15,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Qe)),u["\u0275did"](17,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,lu)),u["\u0275did"](19,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275eld"](20,0,null,null,8,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),u["\u0275eld"](21,0,null,null,3,"button",[["class","btn btn-default"],["id","ecp-info-button"],["type","button"]],null,[[null,"click"]],function(l,n,e){var u=!0,t=l.component;return"click"===n&&(u=0!=(t.data.erasureInfo=!t.data.erasureInfo)&&u),u},null,null)),u["\u0275did"](22,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](23,{active:0}),(l()(),u["\u0275eld"](24,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-question-circle"]],null,null,null,null,null)),(l()(),u["\u0275eld"](25,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],[[8,"disabled",0]],[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==l.component.addErasureCodeProfile()&&u),u},null,null)),(l()(),u["\u0275eld"](26,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-plus"]],null,null,null,null,null)),(l()(),u["\u0275eld"](27,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],[[8,"disabled",0]],[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==l.component.deleteErasureCodeProfile()&&u),u},null,null)),(l()(),u["\u0275eld"](28,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-trash-o"]],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,nu)),u["\u0275did"](30,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,9,0,"erasureProfile"),l(n,13,0,!e.ecProfiles),l(n,15,0,e.ecProfiles&&0===e.ecProfiles.length),l(n,17,0,e.ecProfiles&&e.ecProfiles.length>0),l(n,19,0,e.ecProfiles);var u=l(n,23,0,e.data.erasureInfo);l(n,22,0,"btn btn-default",u),l(n,30,0,e.data.erasureInfo&&e.form.getValue("erasureProfile"))},function(l,n){var e=n.component;l(n,5,0,u["\u0275nov"](n,11).ngClassUntouched,u["\u0275nov"](n,11).ngClassTouched,u["\u0275nov"](n,11).ngClassPristine,u["\u0275nov"](n,11).ngClassDirty,u["\u0275nov"](n,11).ngClassValid,u["\u0275nov"](n,11).ngClassInvalid,u["\u0275nov"](n,11).ngClassPending),l(n,25,0,e.editing),l(n,27,0,e.editing||e.ecProfiles.length<1)})}function uu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Flags"])),(l()(),u["\u0275eld"](3,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,10,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](5,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),u["\u0275eld"](6,0,null,null,6,"input",[["formControlName","ecOverwrites"],["id","ec-overwrites"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,8).onChange(e.target.checked)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,8).onTouched()&&t),t},null,null)),u["\u0275did"](7,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](8,16384,null,0,o.c,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.c]),u["\u0275did"](10,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](12,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](13,0,null,null,1,"label",[["for","ec-overwrites"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["EC Overwrites"]))],function(l,n){l(n,10,0,"ecOverwrites")},function(l,n){l(n,6,0,u["\u0275nov"](n,12).ngClassUntouched,u["\u0275nov"](n,12).ngClassTouched,u["\u0275nov"](n,12).ngClassPristine,u["\u0275nov"](n,12).ngClassDirty,u["\u0275nov"](n,12).ngClassValid,u["\u0275nov"](n,12).ngClassInvalid,u["\u0275nov"](n,12).ngClassPending)})}function tu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,37,"div",[],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,28,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](2,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](3,{"has-error":0}),(l()(),u["\u0275eld"](4,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","pgNum"]],null,null,null,null,null)),(l()(),u["\u0275eld"](5,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Placement groups"])),(l()(),u["\u0275eld"](7,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](8,0,null,null,21,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](9,0,null,null,9,"input",[["class","form-control"],["formControlName","pgNum"],["id","pgNum"],["min","1"],["name","pgNum"],["required",""],["type","number"]],[[1,"required",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"focus"],[null,"blur"],[null,"input"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0,o=l.component;return"input"===n&&(t=!1!==u["\u0275nov"](l,11)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,11).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,11)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,12).onTouched()&&t),"focus"===n&&(t=0!=(o.externalPgChange=!1)&&t),"blur"===n&&(t=!1!==o.alignPgs()&&t),t},null,null)),u["\u0275did"](10,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](11,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](12,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275did"](13,16384,null,0,o.y,[],{required:[0,"required"]},null),u["\u0275prd"](1024,null,o.o,function(l){return[l]},[o.y]),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](16,671744,null,0,o.j,[[3,o.d],[6,o.o],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](18,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Le)),u["\u0275did"](20,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,je)),u["\u0275did"](22,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Me)),u["\u0275did"](24,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](25,0,null,null,2,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275eld"](26,0,null,null,1,"a",[["href","http://ceph.com/pgcalc"],["target","_blank"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Calculation help"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Ue)),u["\u0275did"](29,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Je)),u["\u0275did"](31,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ze)),u["\u0275did"](33,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,eu)),u["\u0275did"](35,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,uu)),u["\u0275did"](37,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,3,0,e.form.showError("pgNum",u["\u0275nov"](n.parent,2)));l(n,2,0,"form-group",t),l(n,13,0,""),l(n,16,0,"pgNum"),l(n,20,0,e.form.showError("pgNum",u["\u0275nov"](n.parent,2),"required")),l(n,22,0,e.form.showError("pgNum",u["\u0275nov"](n.parent,2),"min")),l(n,24,0,e.form.showError("pgNum",u["\u0275nov"](n.parent,2),"34")),l(n,29,0,e.externalPgChange),l(n,31,0,e.form.getValue("poolType")&&e.current.rules.length>0),l(n,33,0,"replicated"===e.form.getValue("poolType")),l(n,35,0,"erasure"===e.form.getValue("poolType")),l(n,37,0,e.info.is_all_bluestore&&"erasure"===e.form.getValue("poolType"))},function(l,n){l(n,9,0,u["\u0275nov"](n,13).required?"":null,u["\u0275nov"](n,18).ngClassUntouched,u["\u0275nov"](n,18).ngClassTouched,u["\u0275nov"](n,18).ngClassPristine,u["\u0275nov"](n,18).ngClassDirty,u["\u0275nov"](n,18).ngClassValid,u["\u0275nov"](n,18).ngClassInvalid,u["\u0275nov"](n,18).ngClassPending)})}function ou(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{value:[0,"value"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function iu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["Loading..."]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function au(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["-- No erasure compression algorithm available --"]))],function(l,n){l(n,1,0,""),l(n,2,0,"")},null)}function ru(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),u["\u0275did"](1,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{value:[0,"value"]},null),u["\u0275did"](2,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{value:[0,"value"]},null),(l()(),u["\u0275ted"](3,null,[" "," "]))],function(l,n){l(n,1,0,n.context.$implicit),l(n,2,0,n.context.$implicit)},function(l,n){l(n,3,0,n.context.$implicit)})}function su(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Value should be greater than 0"]))],null,null)}function du(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Value should be less than the maximum blob size"]))],null,null)}function cu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Value should be greater than 0"]))],null,null)}function pu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Value should be greater than the minimum blob size"]))],null,null)}function fu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Value should be between 0.0 and 1.0"]))],null,null)}function mu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,71,"div",[],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](2,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](3,{"has-error":0}),(l()(),u["\u0275eld"](4,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","algorithm"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Algorithm"])),(l()(),u["\u0275eld"](6,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,12,"select",[["class","form-control"],["formControlName","algorithm"],["id","algorithm"],["name","algorithm"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,9).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,9).onTouched()&&t),t},null,null)),u["\u0275did"](8,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](9,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](11,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](13,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,iu)),u["\u0275did"](15,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,au)),u["\u0275did"](17,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,ru)),u["\u0275did"](19,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275eld"](20,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](21,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](22,{"has-error":0}),(l()(),u["\u0275eld"](23,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","minBlobSize"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Minimum blob size"])),(l()(),u["\u0275eld"](25,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](26,0,null,null,7,"input",[["cdDimlessBinary",""],["class","form-control"],["defaultUnit","KiB"],["formControlName","minBlobSize"],["id","minBlobSize"],["min","0"],["name","minBlobSize"],["placeholder","e.g., 128KiB"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,27)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,27).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,27)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,27)._compositionEnd(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,31).onBlur(e.target.value)&&t),t},null,null)),u["\u0275did"](27,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](29,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](31,81920,null,0,Ne.a,[u.ElementRef,o.q,b.a,R.a],{defaultUnit:[0,"defaultUnit"]},null),u["\u0275did"](32,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](33,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,su)),u["\u0275did"](35,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,du)),u["\u0275did"](37,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](38,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](39,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](40,{"has-error":0}),(l()(),u["\u0275eld"](41,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","maxBlobSize"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Maximum blob size"])),(l()(),u["\u0275eld"](43,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](44,0,null,null,7,"input",[["cdDimlessBinary",""],["class","form-control"],["defaultUnit","KiB"],["formControlName","maxBlobSize"],["id","maxBlobSize"],["min","0"],["placeholder","e.g., 512KiB"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,45)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,45).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,45)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,45)._compositionEnd(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,49).onBlur(e.target.value)&&t),t},null,null)),u["\u0275did"](45,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](47,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](49,81920,null,0,Ne.a,[u.ElementRef,o.q,b.a,R.a],{defaultUnit:[0,"defaultUnit"]},null),u["\u0275did"](50,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](51,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,cu)),u["\u0275did"](53,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,pu)),u["\u0275did"](55,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](56,0,null,null,15,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](57,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](58,{"has-error":0}),(l()(),u["\u0275eld"](59,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","ratio"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Ratio"])),(l()(),u["\u0275eld"](61,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](62,0,null,null,7,"input",[["class","form-control"],["formControlName","ratio"],["id","ratio"],["max","1"],["min","0"],["name","ratio"],["placeholder","Compression ratio"],["step","0.1"],["type","number"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,64)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,64).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,64)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,64)._compositionEnd(e.target.value)&&t),"change"===n&&(t=!1!==u["\u0275nov"](l,65).onChange(e.target.value)&&t),"input"===n&&(t=!1!==u["\u0275nov"](l,65).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,65).onTouched()&&t),t},null,null)),u["\u0275did"](63,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](64,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275did"](65,16384,null,0,o.C,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l,n){return[l,n]},[o.e,o.C]),u["\u0275did"](67,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](69,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,fu)),u["\u0275did"](71,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component,t=l(n,3,0,e.form.showError("algorithm",u["\u0275nov"](n.parent.parent,2)));l(n,2,0,"form-group",t),l(n,11,0,"algorithm"),l(n,15,0,!e.info.compression_algorithms),l(n,17,0,e.info.compression_algorithms&&0===e.info.compression_algorithms.length),l(n,19,0,e.info.compression_algorithms);var o=l(n,22,0,e.form.showError("minBlobSize",u["\u0275nov"](n.parent.parent,2)));l(n,21,0,"form-group",o),l(n,29,0,"minBlobSize"),l(n,31,0,"KiB"),l(n,35,0,e.form.showError("minBlobSize",u["\u0275nov"](n.parent.parent,2),"min")),l(n,37,0,e.form.showError("minBlobSize",u["\u0275nov"](n.parent.parent,2),"maximum"));var i=l(n,40,0,e.form.showError("maxBlobSize",u["\u0275nov"](n.parent.parent,2)));l(n,39,0,"form-group",i),l(n,47,0,"maxBlobSize"),l(n,49,0,"KiB"),l(n,53,0,e.form.showError("maxBlobSize",u["\u0275nov"](n.parent.parent,2),"min")),l(n,55,0,e.form.showError("maxBlobSize",u["\u0275nov"](n.parent.parent,2),"minimum"));var a=l(n,58,0,e.form.showError("ratio",u["\u0275nov"](n.parent.parent,2)));l(n,57,0,"form-group",a),l(n,67,0,"ratio"),l(n,71,0,e.form.showError("ratio",u["\u0275nov"](n.parent.parent,2),"min")||e.form.showError("ratio",u["\u0275nov"](n.parent.parent,2),"max"))},function(l,n){l(n,7,0,u["\u0275nov"](n,13).ngClassUntouched,u["\u0275nov"](n,13).ngClassTouched,u["\u0275nov"](n,13).ngClassPristine,u["\u0275nov"](n,13).ngClassDirty,u["\u0275nov"](n,13).ngClassValid,u["\u0275nov"](n,13).ngClassInvalid,u["\u0275nov"](n,13).ngClassPending),l(n,26,0,u["\u0275nov"](n,33).ngClassUntouched,u["\u0275nov"](n,33).ngClassTouched,u["\u0275nov"](n,33).ngClassPristine,u["\u0275nov"](n,33).ngClassDirty,u["\u0275nov"](n,33).ngClassValid,u["\u0275nov"](n,33).ngClassInvalid,u["\u0275nov"](n,33).ngClassPending),l(n,44,0,u["\u0275nov"](n,51).ngClassUntouched,u["\u0275nov"](n,51).ngClassTouched,u["\u0275nov"](n,51).ngClassPristine,u["\u0275nov"](n,51).ngClassDirty,u["\u0275nov"](n,51).ngClassValid,u["\u0275nov"](n,51).ngClassInvalid,u["\u0275nov"](n,51).ngClassPending),l(n,62,0,u["\u0275nov"](n,69).ngClassUntouched,u["\u0275nov"](n,69).ngClassTouched,u["\u0275nov"](n,69).ngClassPristine,u["\u0275nov"](n,69).ngClassDirty,u["\u0275nov"](n,69).ngClassValid,u["\u0275nov"](n,69).ngClassInvalid,u["\u0275nov"](n,69).ngClassPending)})}function gu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,20,"div",[["formGroupName","compression"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),u["\u0275did"](1,212992,null,0,o.m,[[3,o.d],[8,null],[8,null]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.d,null,[o.m]),u["\u0275did"](3,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),u["\u0275eld"](4,0,null,null,1,"legend",[],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Compression"])),(l()(),u["\u0275eld"](6,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","mode"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Mode"])),(l()(),u["\u0275eld"](9,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](10,0,null,null,8,"select",[["class","form-control"],["formControlName","mode"],["id","mode"],["name","mode"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,12).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,12).onTouched()&&t),t},null,null)),u["\u0275did"](11,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](12,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](14,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](16,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,ou)),u["\u0275did"](18,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,mu)),u["\u0275did"](20,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,1,0,"compression"),l(n,14,0,"mode"),l(n,18,0,e.info.compression_modes),l(n,20,0,e.hasCompressionEnabled())},function(l,n){l(n,0,0,u["\u0275nov"](n,3).ngClassUntouched,u["\u0275nov"](n,3).ngClassTouched,u["\u0275nov"](n,3).ngClassPristine,u["\u0275nov"](n,3).ngClassDirty,u["\u0275nov"](n,3).ngClassValid,u["\u0275nov"](n,3).ngClassInvalid,u["\u0275nov"](n,3).ngClassPending),l(n,10,0,u["\u0275nov"](n,16).ngClassUntouched,u["\u0275nov"](n,16).ngClassTouched,u["\u0275nov"](n,16).ngClassPristine,u["\u0275nov"](n,16).ngClassDirty,u["\u0275nov"](n,16).ngClassValid,u["\u0275nov"](n,16).ngClassInvalid,u["\u0275nov"](n,16).ngClassPending)})}function hu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,5,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),u["\u0275eld"](2,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["It's not possible to create an RBD pool with '/' in the name."])),(l()(),u["\u0275eld"](4,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Please change the name or remove 'rbd' from the applications list."]))],null,null)}function vu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,80,"form",[["class","form-horizontal"],["name","form"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var t=!0;return"submit"===n&&(t=!1!==u["\u0275nov"](l,2).onSubmit(e)&&t),"reset"===n&&(t=!1!==u["\u0275nov"](l,2).onReset()&&t),t},null,null)),u["\u0275did"](1,16384,null,0,o.D,[],null,null),u["\u0275did"](2,540672,[["formDir",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),u["\u0275prd"](2048,null,o.d,null,[o.l]),u["\u0275did"](4,16384,null,0,o.s,[[4,o.d]],null,null),(l()(),u["\u0275eld"](5,0,null,null,75,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),u["\u0275eld"](6,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),u["\u0275eld"](7,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),u["\u0275ted"](8,null,[""," ",""])),u["\u0275ppd"](9,1),u["\u0275ppd"](10,1),(l()(),u["\u0275eld"](11,0,null,null,60,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),u["\u0275eld"](12,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](13,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](14,{"has-error":0}),(l()(),u["\u0275eld"](15,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275eld"](16,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Name"])),(l()(),u["\u0275eld"](18,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](19,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](20,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["placeholder","Name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var t=!0;return"input"===n&&(t=!1!==u["\u0275nov"](l,23)._handleInput(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,23).onTouched()&&t),"compositionstart"===n&&(t=!1!==u["\u0275nov"](l,23)._compositionStart()&&t),"compositionend"===n&&(t=!1!==u["\u0275nov"](l,23)._compositionEnd(e.target.value)&&t),t},null,null)),u["\u0275did"](21,4210688,null,0,Cl.a,[u.ElementRef],null,null),u["\u0275did"](22,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](23,16384,null,0,o.e,[u.Renderer2,u.ElementRef,[2,o.b]],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.e]),u["\u0275did"](25,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](27,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Fe)),u["\u0275did"](29,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,qe)),u["\u0275did"](31,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](32,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](33,278528,null,0,fl.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](34,{"has-error":0}),(l()(),u["\u0275eld"](35,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","poolType"]],null,null,null,null,null)),(l()(),u["\u0275eld"](36,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Pool type"])),(l()(),u["\u0275eld"](38,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(l()(),u["\u0275eld"](39,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](40,0,null,null,12,"select",[["class","form-control"],["formControlName","poolType"],["id","poolType"],["name","poolType"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(l,n,e){var t=!0;return"change"===n&&(t=!1!==u["\u0275nov"](l,42).onChange(e.target.value)&&t),"blur"===n&&(t=!1!==u["\u0275nov"](l,42).onTouched()&&t),t},null,null)),u["\u0275did"](41,4210688,null,0,hl.a,[[2,vl.a],C.a,u.ElementRef],null,null),u["\u0275did"](42,16384,null,0,o.z,[u.Renderer2,u.ElementRef],null,null),u["\u0275prd"](1024,null,o.p,function(l){return[l]},[o.z]),u["\u0275did"](44,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,o.q,null,[o.j]),u["\u0275did"](46,16384,null,0,o.r,[[4,o.q]],null,null),(l()(),u["\u0275eld"](47,0,null,null,3,"option",[["ngValue",""]],null,null,null,null,null)),u["\u0275did"](48,147456,null,0,o.v,[u.ElementRef,u.Renderer2,[2,o.z]],{ngValue:[0,"ngValue"]},null),u["\u0275did"](49,147456,null,0,o.G,[u.ElementRef,u.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(l()(),u["\u0275ted"](-1,null,["-- Select a pool type --"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Ae)),u["\u0275did"](52,278528,null,0,fl.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Oe)),u["\u0275did"](54,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,tu)),u["\u0275did"](56,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](57,0,null,null,6,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](58,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","applications"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Applications"])),(l()(),u["\u0275eld"](60,0,null,null,3,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](61,0,null,null,2,"span",[["class","form-control no-border full-height"]],null,null,null,null,null)),(l()(),u["\u0275eld"](62,0,null,null,1,"cd-select-badges",[["id","applications"]],null,[[null,"selection"]],function(l,n,e){var u=!0;return"selection"===n&&(u=!1!==l.component.appSelection()&&u),u},_e.b,_e.a)),u["\u0275did"](63,49152,null,0,De.a,[s.a],{data:[0,"data"],options:[1,"options"],messages:[2,"messages"],selectionLimit:[3,"selectionLimit"],customBadges:[4,"customBadges"],customBadgeValidators:[5,"customBadgeValidators"]},{selection:"selection"}),(l()(),u["\u0275and"](16777216,null,null,1,null,gu)),u["\u0275did"](65,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](66,0,null,null,2,"div",[],[[8,"hidden",0]],null,null,null,null)),(l()(),u["\u0275eld"](67,0,null,null,1,"cd-rbd-configuration-form",[],null,[[null,"changes"]],function(l,n,e){var u=!0;return"changes"===n&&(u=!1!==(l.component.currentConfigurationValues=e())&&u),u},Pe.b,Pe.a)),u["\u0275did"](68,114688,null,0,ke.a,[R.a,se.a],{form:[0,"form"],initializeData:[1,"initializeData"]},{changes:"changes"}),(l()(),u["\u0275eld"](69,0,null,null,2,"div",[["class","form-group has-error"]],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,hu)),u["\u0275did"](71,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](72,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),u["\u0275eld"](73,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),u["\u0275eld"](74,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,e){var u=!0;return"submitAction"===n&&(u=!1!==l.component.submit()&&u),u},Rl.b,Rl.a)),u["\u0275did"](75,114688,null,0,yl.a,[u.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),u["\u0275ted"](76,0,[""," ",""])),u["\u0275ppd"](77,1),u["\u0275ppd"](78,1),(l()(),u["\u0275eld"](79,0,null,null,1,"cd-back-button",[],null,null,null,Il.b,Il.a)),u["\u0275did"](80,49152,null,0,El.a,[fl.Location,t.b],null,null)],function(l,n){var e=n.component;l(n,2,0,e.form);var t=l(n,14,0,e.form.showError("name",u["\u0275nov"](n,2)));l(n,13,0,"form-group",t),l(n,25,0,"name"),l(n,29,0,e.form.showError("name",u["\u0275nov"](n,2),"required")),l(n,31,0,e.form.showError("name",u["\u0275nov"](n,2),"uniqueName"));var o=l(n,34,0,e.form.showError("poolType",u["\u0275nov"](n,2)));l(n,33,0,"form-group",o),l(n,44,0,"poolType"),l(n,48,0,""),l(n,49,0,""),l(n,52,0,e.data.poolTypes),l(n,54,0,e.form.showError("poolType",u["\u0275nov"](n,2),"required")),l(n,56,0,e.form.getValue("poolType")),l(n,63,0,e.data.applications.selected,e.data.applications.available,e.data.applications.messages,4,!0,e.data.applications.validators),l(n,65,0,e.info.is_all_bluestore),l(n,68,0,e.form,e.initializeConfigData),l(n,71,0,e.form.hasError("rbdPool")),l(n,75,0,u["\u0275nov"](n,2),"button")},function(l,n){var e=n.component;l(n,0,0,u["\u0275nov"](n,4).ngClassUntouched,u["\u0275nov"](n,4).ngClassTouched,u["\u0275nov"](n,4).ngClassPristine,u["\u0275nov"](n,4).ngClassDirty,u["\u0275nov"](n,4).ngClassValid,u["\u0275nov"](n,4).ngClassInvalid,u["\u0275nov"](n,4).ngClassPending);var t=u["\u0275unv"](n,8,0,l(n,9,0,u["\u0275nov"](n.parent,0),e.action)),o=u["\u0275unv"](n,8,1,l(n,10,0,u["\u0275nov"](n.parent,1),e.resource));l(n,8,0,t,o),l(n,20,0,u["\u0275nov"](n,27).ngClassUntouched,u["\u0275nov"](n,27).ngClassTouched,u["\u0275nov"](n,27).ngClassPristine,u["\u0275nov"](n,27).ngClassDirty,u["\u0275nov"](n,27).ngClassValid,u["\u0275nov"](n,27).ngClassInvalid,u["\u0275nov"](n,27).ngClassPending),l(n,40,0,u["\u0275nov"](n,46).ngClassUntouched,u["\u0275nov"](n,46).ngClassTouched,u["\u0275nov"](n,46).ngClassPristine,u["\u0275nov"](n,46).ngClassDirty,u["\u0275nov"](n,46).ngClassValid,u["\u0275nov"](n,46).ngClassInvalid,u["\u0275nov"](n,46).ngClassPending),l(n,66,0,"replicated"!==e.form.get("poolType").value||-1===e.data.applications.selected.indexOf("rbd"));var i=u["\u0275unv"](n,76,0,l(n,77,0,u["\u0275nov"](n.parent,0),e.action)),a=u["\u0275unv"](n,76,1,l(n,78,0,u["\u0275nov"](n.parent,1),e.resource));l(n,76,0,i,a)})}function bu(l){return u["\u0275vid"](0,[u["\u0275pid"](0,fl.TitleCasePipe,[]),u["\u0275pid"](0,bl.a,[]),(l()(),u["\u0275eld"](2,0,null,null,4,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,xe)),u["\u0275did"](4,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,vu)),u["\u0275did"](6,16384,null,0,fl.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,4,0,!(e.info&&e.ecProfiles)),l(n,6,0,e.info&&e.ecProfiles)},null)}function Cu(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-pool-form",[],null,null,null,bu,ze)),u["\u0275did"](1,114688,null,0,N,[b.a,Pn.a,Pn.l,Vl.b,p.a,C.a,R.a,Vl.b,y.a,c,s.a,t.b],null,null)],function(l,n){l(n,1,0)},null)}var Ru=u["\u0275ccf"]("cd-pool-form",N,Cu,{},{},[]);e.d(n,"PoolModuleNgFactory",function(){return yu}),e.d(n,"RoutedPoolModuleNgFactory",function(){return Iu});var yu=u["\u0275cmf"](M,[],function(l){return u["\u0275mod"]([u["\u0275mpd"](512,u.ComponentFactoryResolver,u["\u0275CodegenComponentFactoryResolver"],[[8,[K.a,$.a,J.a,H.a,H.b,W.a,Z.a,Y.a,X.a,Q.a,ll.a,nl.a,el.a,ul.a,ul.c,ul.b,tl.a,ol.a,il.a,al.a,rl.a,sl.a,dl.a,cl.a,pl.a,en]],[3,u.ComponentFactoryResolver],u.NgModuleRef]),u["\u0275mpd"](4608,fl.NgLocalization,fl.NgLocaleLocalization,[u.LOCALE_ID,[2,fl["\u0275angular_packages_common_common_a"]]]),u["\u0275mpd"](4608,un.a,un.a,[s.a]),u["\u0275mpd"](4608,fl.DatePipe,fl.DatePipe,[u.LOCALE_ID]),u["\u0275mpd"](4608,tn.a,tn.a,[]),u["\u0275mpd"](4608,on.a,on.a,[]),u["\u0275mpd"](4608,R.a,R.a,[]),u["\u0275mpd"](4608,b.a,b.a,[R.a]),u["\u0275mpd"](4608,an.a,an.a,[R.a]),u["\u0275mpd"](4608,x.a,x.a,[R.a]),u["\u0275mpd"](4608,rn.a,rn.a,[]),u["\u0275mpd"](4608,sn.a,sn.a,[]),u["\u0275mpd"](4608,dn.a,dn.a,[]),u["\u0275mpd"](4608,cn.a,cn.a,[]),u["\u0275mpd"](4608,pn.a,pn.a,[fl.DatePipe]),u["\u0275mpd"](4608,fn.a,fn.a,[]),u["\u0275mpd"](4608,mn.a,mn.a,[]),u["\u0275mpd"](4608,gn.a,gn.a,[]),u["\u0275mpd"](4608,hn.a,hn.a,[]),u["\u0275mpd"](4608,vn.a,vn.a,[]),u["\u0275mpd"](4608,bn.a,bn.a,[s.a]),u["\u0275mpd"](4608,bl.a,bl.a,[]),u["\u0275mpd"](4608,Cn.a,Cn.a,[]),u["\u0275mpd"](4608,o.E,o.E,[]),u["\u0275mpd"](4608,o.h,o.h,[]),u["\u0275mpd"](4608,Rn.b,Rn.b,[]),u["\u0275mpd"](4608,yn.a,yn.a,[]),u["\u0275mpd"](4608,In.a,In.a,[u.RendererFactory2,u.PLATFORM_ID]),u["\u0275mpd"](4608,En.a,En.a,[u.ComponentFactoryResolver,u.NgZone,u.Injector,In.a,u.ApplicationRef]),u["\u0275mpd"](4608,Vn.a,Vn.a,[]),u["\u0275mpd"](4608,Vl.b,Vl.b,[u.RendererFactory2,En.a]),u["\u0275mpd"](4608,Tn.ScrollbarHelper,Tn.ScrollbarHelper,[wn.DOCUMENT]),u["\u0275mpd"](4608,Sn.DimensionsHelper,Sn.DimensionsHelper,[]),u["\u0275mpd"](4608,Nn.ColumnChangesService,Nn.ColumnChangesService,[]),u["\u0275mpd"](4608,_n.f,_n.f,[]),u["\u0275mpd"](4608,C.a,C.a,[]),u["\u0275mpd"](4608,Dn.a,Dn.a,[Pn.l,C.a]),u["\u0275mpd"](4608,kn.NodeDraggableService,kn.NodeDraggableService,[]),u["\u0275mpd"](4608,zn.NodeMenuService,zn.NodeMenuService,[]),u["\u0275mpd"](4608,xn.TreeService,xn.TreeService,[kn.NodeDraggableService]),u["\u0275mpd"](4608,Fn.e,Fn.e,[]),u["\u0275mpd"](4608,qn.c,qn.c,[]),u["\u0275mpd"](4608,An.r,An.r,[]),u["\u0275mpd"](4608,An.t,An.t,[]),u["\u0275mpd"](4608,An.a,An.a,[]),u["\u0275mpd"](4608,An.h,An.h,[]),u["\u0275mpd"](4608,An.d,An.d,[]),u["\u0275mpd"](4608,An.j,An.j,[]),u["\u0275mpd"](4608,An.s,An.s,[An.t,An.j]),u["\u0275mpd"](1073742336,fl.CommonModule,fl.CommonModule,[]),u["\u0275mpd"](1073742336,On.a,On.a,[]),u["\u0275mpd"](1073742336,Fn.c,Fn.c,[]),u["\u0275mpd"](1073742336,yn.d,yn.d,[]),u["\u0275mpd"](1073742336,Ln.a,Ln.a,[]),u["\u0275mpd"](1073742336,o.B,o.B,[]),u["\u0275mpd"](1073742336,o.n,o.n,[]),u["\u0275mpd"](1073742336,o.x,o.x,[]),u["\u0275mpd"](1073742336,Rn.c,Rn.c,[]),u["\u0275mpd"](1073742336,Vn.d,Vn.d,[]),u["\u0275mpd"](1073742336,jn.ChartsModule,jn.ChartsModule,[]),u["\u0275mpd"](1073742336,Vl.e,Vl.e,[]),u["\u0275mpd"](1073742336,Mn.a,Mn.a,[]),u["\u0275mpd"](1073742336,_n.e,_n.e,[]),u["\u0275mpd"](1073742336,Un.a,Un.a,[]),u["\u0275mpd"](1073742336,Bn.NgxDatatableModule,Bn.NgxDatatableModule,[]),u["\u0275mpd"](1073742336,Pn.p,Pn.p,[[2,Pn.v],[2,Pn.l]]),u["\u0275mpd"](1073742336,Gn.a,Gn.a,[]),u["\u0275mpd"](1073742336,d.a,d.a,[]),u["\u0275mpd"](1073742336,Kn.a,Kn.a,[]),u["\u0275mpd"](1073742336,qn.d,qn.d,[]),u["\u0275mpd"](1073742336,$n.TreeModule,$n.TreeModule,[]),u["\u0275mpd"](1073742336,Jn.a,Jn.a,[]),u["\u0275mpd"](1073742336,An.g,An.g,[]),u["\u0275mpd"](1073742336,Hn.a,Hn.a,[]),u["\u0275mpd"](1073742336,M,M,[]),u["\u0275mpd"](256,u.LOCALE_ID,"en-US",[]),u["\u0275mpd"](256,_n.a,{autoClose:!0,insideClick:!1},[]),u["\u0275mpd"](256,u.TRANSLATIONS_FORMAT,"xlf",[])])}),Iu=u["\u0275cmf"](G,[],function(l){return u["\u0275mod"]([u["\u0275mpd"](512,u.ComponentFactoryResolver,u["\u0275CodegenComponentFactoryResolver"],[[8,[K.a,$.a,J.a,H.a,H.b,W.a,Z.a,Y.a,X.a,Q.a,ll.a,nl.a,el.a,ul.a,ul.c,ul.b,tl.a,ol.a,il.a,al.a,rl.a,sl.a,dl.a,cl.a,pl.a,en,Se,Ru]],[3,u.ComponentFactoryResolver],u.NgModuleRef]),u["\u0275mpd"](4608,fl.NgLocalization,fl.NgLocaleLocalization,[u.LOCALE_ID,[2,fl["\u0275angular_packages_common_common_a"]]]),u["\u0275mpd"](4608,un.a,un.a,[s.a]),u["\u0275mpd"](4608,fl.DatePipe,fl.DatePipe,[u.LOCALE_ID]),u["\u0275mpd"](4608,tn.a,tn.a,[]),u["\u0275mpd"](4608,on.a,on.a,[]),u["\u0275mpd"](4608,R.a,R.a,[]),u["\u0275mpd"](4608,b.a,b.a,[R.a]),u["\u0275mpd"](4608,an.a,an.a,[R.a]),u["\u0275mpd"](4608,x.a,x.a,[R.a]),u["\u0275mpd"](4608,rn.a,rn.a,[]),u["\u0275mpd"](4608,sn.a,sn.a,[]),u["\u0275mpd"](4608,dn.a,dn.a,[]),u["\u0275mpd"](4608,cn.a,cn.a,[]),u["\u0275mpd"](4608,pn.a,pn.a,[fl.DatePipe]),u["\u0275mpd"](4608,fn.a,fn.a,[]),u["\u0275mpd"](4608,mn.a,mn.a,[]),u["\u0275mpd"](4608,gn.a,gn.a,[]),u["\u0275mpd"](4608,hn.a,hn.a,[]),u["\u0275mpd"](4608,vn.a,vn.a,[]),u["\u0275mpd"](4608,bn.a,bn.a,[s.a]),u["\u0275mpd"](4608,bl.a,bl.a,[]),u["\u0275mpd"](4608,Cn.a,Cn.a,[]),u["\u0275mpd"](4608,o.E,o.E,[]),u["\u0275mpd"](4608,o.h,o.h,[]),u["\u0275mpd"](4608,Rn.b,Rn.b,[]),u["\u0275mpd"](4608,yn.a,yn.a,[]),u["\u0275mpd"](4608,In.a,In.a,[u.RendererFactory2,u.PLATFORM_ID]),u["\u0275mpd"](4608,En.a,En.a,[u.ComponentFactoryResolver,u.NgZone,u.Injector,In.a,u.ApplicationRef]),u["\u0275mpd"](4608,Vn.a,Vn.a,[]),u["\u0275mpd"](4608,Vl.b,Vl.b,[u.RendererFactory2,En.a]),u["\u0275mpd"](4608,Tn.ScrollbarHelper,Tn.ScrollbarHelper,[wn.DOCUMENT]),u["\u0275mpd"](4608,Sn.DimensionsHelper,Sn.DimensionsHelper,[]),u["\u0275mpd"](4608,Nn.ColumnChangesService,Nn.ColumnChangesService,[]),u["\u0275mpd"](4608,_n.f,_n.f,[]),u["\u0275mpd"](4608,C.a,C.a,[]),u["\u0275mpd"](4608,Dn.a,Dn.a,[Pn.l,C.a]),u["\u0275mpd"](4608,kn.NodeDraggableService,kn.NodeDraggableService,[]),u["\u0275mpd"](4608,zn.NodeMenuService,zn.NodeMenuService,[]),u["\u0275mpd"](4608,xn.TreeService,xn.TreeService,[kn.NodeDraggableService]),u["\u0275mpd"](4608,Fn.e,Fn.e,[]),u["\u0275mpd"](4608,qn.c,qn.c,[]),u["\u0275mpd"](4608,An.r,An.r,[]),u["\u0275mpd"](4608,An.t,An.t,[]),u["\u0275mpd"](4608,An.a,An.a,[]),u["\u0275mpd"](4608,An.h,An.h,[]),u["\u0275mpd"](4608,An.d,An.d,[]),u["\u0275mpd"](4608,An.j,An.j,[]),u["\u0275mpd"](4608,An.s,An.s,[An.t,An.j]),u["\u0275mpd"](1073742336,fl.CommonModule,fl.CommonModule,[]),u["\u0275mpd"](1073742336,On.a,On.a,[]),u["\u0275mpd"](1073742336,Fn.c,Fn.c,[]),u["\u0275mpd"](1073742336,yn.d,yn.d,[]),u["\u0275mpd"](1073742336,Ln.a,Ln.a,[]),u["\u0275mpd"](1073742336,o.B,o.B,[]),u["\u0275mpd"](1073742336,o.n,o.n,[]),u["\u0275mpd"](1073742336,o.x,o.x,[]),u["\u0275mpd"](1073742336,Rn.c,Rn.c,[]),u["\u0275mpd"](1073742336,Vn.d,Vn.d,[]),u["\u0275mpd"](1073742336,jn.ChartsModule,jn.ChartsModule,[]),u["\u0275mpd"](1073742336,Vl.e,Vl.e,[]),u["\u0275mpd"](1073742336,Mn.a,Mn.a,[]),u["\u0275mpd"](1073742336,_n.e,_n.e,[]),u["\u0275mpd"](1073742336,Un.a,Un.a,[]),u["\u0275mpd"](1073742336,Bn.NgxDatatableModule,Bn.NgxDatatableModule,[]),u["\u0275mpd"](1073742336,Pn.p,Pn.p,[[2,Pn.v],[2,Pn.l]]),u["\u0275mpd"](1073742336,Gn.a,Gn.a,[]),u["\u0275mpd"](1073742336,d.a,d.a,[]),u["\u0275mpd"](1073742336,Kn.a,Kn.a,[]),u["\u0275mpd"](1073742336,qn.d,qn.d,[]),u["\u0275mpd"](1073742336,$n.TreeModule,$n.TreeModule,[]),u["\u0275mpd"](1073742336,Jn.a,Jn.a,[]),u["\u0275mpd"](1073742336,An.g,An.g,[]),u["\u0275mpd"](1073742336,Hn.a,Hn.a,[]),u["\u0275mpd"](1073742336,M,M,[]),u["\u0275mpd"](1073742336,G,G,[]),u["\u0275mpd"](256,u.LOCALE_ID,"en-US",[]),u["\u0275mpd"](256,_n.a,{autoClose:!0,insideClick:!1},[]),u["\u0275mpd"](1024,Pn.j,function(){return[[{path:"",component:j},{path:"create",component:N,data:U},{path:"edit/:name",component:N,data:B}]]},[]),u["\u0275mpd"](256,u.TRANSLATIONS_FORMAT,"xlf",[])])})}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/9.b19f6391d5c667b85d12.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/9.b19f6391d5c667b85d12.js
new file mode 100644
index 00000000..b4cb12f4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/9.b19f6391d5c667b85d12.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{DY6s:function(l,n,e){"use strict";e.r(n);var u=e("CcnG"),o=e("LceX"),a=e("iutN"),t=e("ES0t"),d=e("MdoF"),s=e("Xg1U"),r=e("z5nN"),i=e("EEJc"),c=e("PEr+"),p=e("a40w"),m=e("pMnS"),f=e("Ip0R"),v=e("gIcY"),g=e("iExv"),h=e("Jm/i"),b=e("85J/"),C=e("+0ag"),R=e("aXbf"),I=e("Fgil"),y=e("IzCI"),T=e("o4+5"),w=e("Dwqy"),D=e("uYzU"),x=e("uhwM"),E=e("E2fk"),k=e("a0VL"),N=e("nSDx"),F=e("SB+Q"),S=e("TYzs"),_=e("BQkM"),P=e("dEH0"),M=e("G1/K"),A=e("8xTl"),q=e("TJUb"),V=e("lTVp"),L=e("OZfm"),U=e("NJnL"),O=e("lqqz"),j=e("eajB"),z=e("DQlY"),H=e("FO+L"),B=e("ZYjt"),Z=e("nhM1"),G=e("BARL"),K=e("xtZt"),Y=e("aexS"),J=e("Avrn"),X=e("ZYCi"),Q=e("YAQW"),W=e("9Xeq"),$=e("xdbM"),ll=e("yGOH"),nl=e("V/fk"),el=e("F8xH"),ul=e("ChqD"),ol=e("pL04"),al=e("PCNd"),tl=e("pKUh"),dl=function(){function l(l){this.router=l}return l.prototype.ngOnInit=function(){this.url=this.router.url},l.prototype.navigateTo=function(l){this.router.navigate([l])},l}(),sl=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function rl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,tl.b,tl.a)),u["\u0275did"](1,180224,null,0,Q.d,[Q.e,u.Renderer2,u.ElementRef],null,null),(l()(),u["\u0275eld"](2,0,null,0,1,"tab",[["heading","Users"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(l,n,e){var u=!0;return"selectTab"===n&&(u=!1!==l.component.navigateTo("/user-management/users")&&u),u},null,null)),u["\u0275did"](3,212992,null,0,Q.b,[Q.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"],active:[1,"active"]},{selectTab:"selectTab"}),(l()(),u["\u0275eld"](4,0,null,0,1,"tab",[["heading","Roles"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(l,n,e){var u=!0;return"selectTab"===n&&(u=!1!==l.component.navigateTo("/user-management/roles")&&u),u},null,null)),u["\u0275did"](5,212992,null,0,Q.b,[Q.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"],active:[1,"active"]},{selectTab:"selectTab"})],function(l,n){var e=n.component;l(n,3,0,"Users","/user-management/users"===e.url),l(n,5,0,"Roles","/user-management/roles"===e.url)},function(l,n){l(n,0,0,u["\u0275nov"](n,1).clazz),l(n,2,0,u["\u0275nov"](n,3).id,u["\u0275nov"](n,3).active,u["\u0275nov"](n,3).addClass),l(n,4,0,u["\u0275nov"](n,5).id,u["\u0275nov"](n,5).active,u["\u0275nov"](n,5).addClass)})}var il=e("25BL"),cl=e("uIqm"),pl=e("NUGo"),ml=e("S7zO"),fl=e("EgGo"),vl=e("ZEkX"),gl=e("Mxhz"),hl=e("9nlD"),bl=e("sne2"),Cl=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Rl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(l()(),u["\u0275ted"](1,null,[" ",""," "]))],null,function(l,n){l(n,1,0,n.context.$implicit,n.context.last?"":", ")})}function Il(l){return u["\u0275vid"](0,[(l()(),u["\u0275and"](16777216,null,null,1,null,Rl)),u["\u0275did"](1,278528,null,0,f.NgForOf,[u.ViewContainerRef,u.TemplateRef,u.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(l()(),u["\u0275and"](0,null,null,0))],function(l,n){l(n,1,0,n.context.value)},null)}function yl(l){return u["\u0275vid"](0,[u["\u0275qud"](402653184,1,{userRolesTpl:0}),(l()(),u["\u0275eld"](1,0,null,null,1,"cd-user-tabs",[],null,null,null,rl,sl)),u["\u0275did"](2,114688,null,0,dl,[X.l],null,null),(l()(),u["\u0275eld"](3,0,null,null,3,"cd-table",[["columnMode","flex"],["identifier","username"],["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(l,n,e){var u=!0,o=l.component;return"fetchData"===n&&(u=!1!==o.getUsers()&&u),"updateSelection"===n&&(u=!1!==o.updateSelection(e)&&u),u},il.b,il.a)),u["\u0275did"](4,2867200,null,0,cl.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],selectionType:[4,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),u["\u0275eld"](5,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,pl.b,pl.a)),u["\u0275did"](6,114688,null,0,ml.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),u["\u0275and"](0,[[1,2],["userRolesTpl",2]],null,0,null,Il))],function(l,n){var e=n.component;l(n,2,0),l(n,4,0,e.users,e.columns,"flex","username","single"),l(n,6,0,e.permission,e.selection,e.tableActions)},null)}function Tl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,2,"cd-user-list",[],null,null,null,yl,Cl)),u["\u0275prd"](256,null,fl.a,vl.b,[]),u["\u0275did"](2,114688,null,0,vl.a,[gl.a,N.a,z.b,hl.a,Y.a,h.a,fl.a,bl.b],null,null)],function(l,n){l(n,2,0)},null)}var wl=u["\u0275ccf"]("cd-user-list",vl.a,Tl,{},{},[]),Dl=e("pYKc"),xl=e("ppaS"),El=e("IZUe"),kl=e("ANnk"),Nl=e("f/UV"),Fl=e("D4zM"),Sl=e("gp3X"),_l=e("sb0X"),Pl=e("KVJa"),Ml=e("Z21x"),Al=e("V3my"),ql=e("DSvg"),Vl=e("SgmB"),Ll=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Ul(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Ol(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required."]))],null,null)}function jl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required."]))],null,null)}function zl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Hl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Password confirmation doesn't match the password."]))],null,null)}function Bl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Invalid email."]))],null,null)}function Zl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border full-height"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"cd-select-badges",[],null,null,null,Dl.b,Dl.a)),u["\u0275did"](2,49152,null,0,xl.a,[h.a],{data:[0,"data"],options:[1,"options"],messages:[2,"messages"]},null)],function(l,n){var e=n.component;l(n,2,0,e.userForm.controls.roles.value,e.allRoles,e.messages)},null)}function Gl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,2,"p",[],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"strong",[],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,['You are about to remove "user read / update" permissions from your own user.'])),(l()(),u["\u0275eld"](3,0,null,null,0,"br",[],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,1,"p",[],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["If you continue, you will no longer be able to add or remove roles from any user."])),(l()(),u["\u0275eld"](6,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Are you sure you want to continue?"]))],null,null)}function Kl(l){return u["\u0275vid"](0,[u["\u0275pid"](0,f.TitleCasePipe,[]),u["\u0275pid"](0,A.a,[]),u["\u0275qud"](402653184,1,{removeSelfUserReadUpdatePermissionTpl:0}),(l()(),u["\u0275eld"](3,0,null,null,111,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),u["\u0275eld"](4,0,null,null,110,"form",[["class","form-horizontal"],["name","userForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var o=!0;return"submit"===n&&(o=!1!==u["\u0275nov"](l,6).onSubmit(e)&&o),"reset"===n&&(o=!1!==u["\u0275nov"](l,6).onReset()&&o),o},null,null)),u["\u0275did"](5,16384,null,0,v.D,[],null,null),u["\u0275did"](6,540672,[["formDir",4]],0,v.l,[[8,null],[8,null]],{form:[0,"form"]},null),u["\u0275prd"](2048,null,v.d,null,[v.l]),u["\u0275did"](8,16384,null,0,v.s,[[4,v.d]],null,null),(l()(),u["\u0275eld"](9,0,null,null,105,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),u["\u0275eld"](10,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),u["\u0275eld"](11,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),u["\u0275ted"](12,null,[""," ",""])),u["\u0275ppd"](13,1),u["\u0275ppd"](14,1),(l()(),u["\u0275eld"](15,0,null,null,90,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),u["\u0275eld"](16,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](17,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](18,{"has-error":0}),(l()(),u["\u0275eld"](19,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275eld"](20,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Username"])),(l()(),u["\u0275and"](16777216,null,null,1,null,Ul)),u["\u0275did"](23,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](24,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](25,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","username"],["id","username"],["name","username"],["placeholder","Username..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,26)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,26).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,26)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,26)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](26,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](28,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](30,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](31,4210688,null,0,El.a,[u.ElementRef],null,null),u["\u0275did"](32,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Ol)),u["\u0275did"](34,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](35,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](36,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](37,{"has-error":0}),(l()(),u["\u0275eld"](38,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Password"])),(l()(),u["\u0275eld"](40,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](41,0,null,null,10,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](42,0,null,null,6,"input",[["autocomplete","new-password"],["class","form-control"],["formControlName","password"],["id","password"],["name","password"],["placeholder","Password..."],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,43)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,43).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,43)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,43)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](43,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](45,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](47,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](48,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](49,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),u["\u0275eld"](50,0,null,null,1,"button",[["cdPasswordButton","password"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var o=!0;return"click"===n&&(o=!1!==u["\u0275nov"](l,51).onClick()&&o),o},null,null)),u["\u0275did"](51,81920,null,0,Fl.a,[u.ElementRef,u.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,jl)),u["\u0275did"](53,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](54,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](55,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](56,{"has-error":0}),(l()(),u["\u0275eld"](57,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Confirm password"])),(l()(),u["\u0275eld"](59,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](60,0,null,null,10,"div",[["class","input-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](61,0,null,null,6,"input",[["class","form-control"],["formControlName","confirmpassword"],["id","confirmpassword"],["name","confirmpassword"],["placeholder","Confirm password..."],["type","password"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,62)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,62).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,62)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,62)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](62,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](64,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](66,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](67,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](68,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(l()(),u["\u0275eld"](69,0,null,null,1,"button",[["cdPasswordButton","confirmpassword"],["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(l,n,e){var o=!0;return"click"===n&&(o=!1!==u["\u0275nov"](l,70).onClick()&&o),o},null,null)),u["\u0275did"](70,81920,null,0,Fl.a,[u.ElementRef,u.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,zl)),u["\u0275did"](72,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,Hl)),u["\u0275did"](74,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](75,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](76,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Full name"])),(l()(),u["\u0275eld"](78,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](79,0,null,null,6,"input",[["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["placeholder","Full name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,80)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,80).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,80)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,80)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](80,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](82,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](84,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](85,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](86,0,null,null,14,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](87,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](88,{"has-error":0}),(l()(),u["\u0275eld"](89,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","email"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Email"])),(l()(),u["\u0275eld"](91,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](92,0,null,null,6,"input",[["class","form-control"],["formControlName","email"],["id","email"],["name","email"],["placeholder","Email..."],["type","email"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,93)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,93).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,93)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,93)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](93,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](95,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](97,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](98,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,Bl)),u["\u0275did"](100,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](101,0,null,null,1,"label",[["class","col-sm-3 control-label"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Roles"])),(l()(),u["\u0275eld"](103,0,null,null,2,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275and"](16777216,null,null,1,null,Zl)),u["\u0275did"](105,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](106,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),u["\u0275eld"](107,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),u["\u0275eld"](108,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,e){var u=!0;return"submitAction"===n&&(u=!1!==l.component.submit()&&u),u},Sl.b,Sl.a)),u["\u0275did"](109,114688,null,0,_l.a,[u.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),u["\u0275ted"](110,0,[""," ",""])),u["\u0275ppd"](111,1),u["\u0275ppd"](112,1),(l()(),u["\u0275eld"](113,0,null,null,1,"cd-back-button",[],null,null,null,Pl.b,Pl.a)),u["\u0275did"](114,49152,null,0,Ml.a,[f.Location,bl.b],null,null),(l()(),u["\u0275and"](0,[[1,2],["removeSelfUserReadUpdatePermissionTpl",2]],null,0,null,Gl))],function(l,n){var e=n.component;l(n,6,0,e.userForm);var o=l(n,18,0,e.userForm.showError("username",u["\u0275nov"](n,6)));l(n,17,0,"form-group",o),l(n,23,0,e.mode!==e.userFormMode.editing),l(n,28,0,"username"),l(n,34,0,e.userForm.showError("username",u["\u0275nov"](n,6),"required"));var a=l(n,37,0,e.userForm.showError("password",u["\u0275nov"](n,6)));l(n,36,0,"form-group",a),l(n,45,0,"password"),l(n,51,0,"password"),l(n,53,0,e.userForm.showError("password",u["\u0275nov"](n,6),"required"));var t=l(n,56,0,e.userForm.showError("confirmpassword",u["\u0275nov"](n,6)));l(n,55,0,"form-group",t),l(n,64,0,"confirmpassword"),l(n,70,0,"confirmpassword"),l(n,72,0,e.userForm.showError("confirmpassword",u["\u0275nov"](n,6),"required")),l(n,74,0,e.userForm.showError("confirmpassword",u["\u0275nov"](n,6),"match")),l(n,82,0,"name");var d=l(n,88,0,e.userForm.showError("email",u["\u0275nov"](n,6)));l(n,87,0,"form-group",d),l(n,95,0,"email"),l(n,100,0,e.userForm.showError("email",u["\u0275nov"](n,6),"email")),l(n,105,0,e.allRoles),l(n,109,0,u["\u0275nov"](n,6),"button")},function(l,n){var e=n.component;l(n,4,0,u["\u0275nov"](n,8).ngClassUntouched,u["\u0275nov"](n,8).ngClassTouched,u["\u0275nov"](n,8).ngClassPristine,u["\u0275nov"](n,8).ngClassDirty,u["\u0275nov"](n,8).ngClassValid,u["\u0275nov"](n,8).ngClassInvalid,u["\u0275nov"](n,8).ngClassPending);var o=u["\u0275unv"](n,12,0,l(n,13,0,u["\u0275nov"](n,0),e.action)),a=u["\u0275unv"](n,12,1,l(n,14,0,u["\u0275nov"](n,1),e.resource));l(n,12,0,o,a),l(n,25,0,u["\u0275nov"](n,30).ngClassUntouched,u["\u0275nov"](n,30).ngClassTouched,u["\u0275nov"](n,30).ngClassPristine,u["\u0275nov"](n,30).ngClassDirty,u["\u0275nov"](n,30).ngClassValid,u["\u0275nov"](n,30).ngClassInvalid,u["\u0275nov"](n,30).ngClassPending),l(n,42,0,u["\u0275nov"](n,47).ngClassUntouched,u["\u0275nov"](n,47).ngClassTouched,u["\u0275nov"](n,47).ngClassPristine,u["\u0275nov"](n,47).ngClassDirty,u["\u0275nov"](n,47).ngClassValid,u["\u0275nov"](n,47).ngClassInvalid,u["\u0275nov"](n,47).ngClassPending),l(n,61,0,u["\u0275nov"](n,66).ngClassUntouched,u["\u0275nov"](n,66).ngClassTouched,u["\u0275nov"](n,66).ngClassPristine,u["\u0275nov"](n,66).ngClassDirty,u["\u0275nov"](n,66).ngClassValid,u["\u0275nov"](n,66).ngClassInvalid,u["\u0275nov"](n,66).ngClassPending),l(n,79,0,u["\u0275nov"](n,84).ngClassUntouched,u["\u0275nov"](n,84).ngClassTouched,u["\u0275nov"](n,84).ngClassPristine,u["\u0275nov"](n,84).ngClassDirty,u["\u0275nov"](n,84).ngClassValid,u["\u0275nov"](n,84).ngClassInvalid,u["\u0275nov"](n,84).ngClassPending),l(n,92,0,u["\u0275nov"](n,97).ngClassUntouched,u["\u0275nov"](n,97).ngClassTouched,u["\u0275nov"](n,97).ngClassPristine,u["\u0275nov"](n,97).ngClassDirty,u["\u0275nov"](n,97).ngClassValid,u["\u0275nov"](n,97).ngClassInvalid,u["\u0275nov"](n,97).ngClassPending);var t=u["\u0275unv"](n,110,0,l(n,111,0,u["\u0275nov"](n,0),e.action)),d=u["\u0275unv"](n,110,1,l(n,112,0,u["\u0275nov"](n,1),e.resource));l(n,110,0,t,d)})}function Yl(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-user-form",[],null,null,null,Kl,Ll)),u["\u0275did"](1,114688,null,0,Al.a,[ql.a,Y.a,X.a,X.l,z.b,Vl.a,gl.a,hl.a,h.a,bl.b],null,null)],function(l,n){l(n,1,0)},null)}var Jl=u["\u0275ccf"]("cd-user-form",Al.a,Yl,{},{},[]),Xl=e("LvDl"),Ql=e("x38r"),Wl=(e("vCyI"),function(){function l(l){this.i18n=l,this.scopes_permissions=[]}return l.prototype.ngOnInit=function(){this.columns=[{prop:"scope",name:this.i18n("Scope"),flexGrow:2},{prop:"read",name:this.i18n("Read"),flexGrow:1,cellClass:"text-center",cellTransformation:Ql.a.checkIcon},{prop:"create",name:this.i18n("Create"),flexGrow:1,cellClass:"text-center",cellTransformation:Ql.a.checkIcon},{prop:"update",name:this.i18n("Update"),flexGrow:1,cellClass:"text-center",cellTransformation:Ql.a.checkIcon},{prop:"delete",name:this.i18n("Delete"),flexGrow:1,cellClass:"text-center",cellTransformation:Ql.a.checkIcon}]},l.prototype.ngOnChanges=function(){var l=this;if(this.selection.hasSelection){this.selectedItem=this.selection.first();var n=[];Xl.each(this.scopes,function(e){var u={read:!1,create:!1,update:!1,delete:!1};u.scope=e,e in l.selectedItem.scopes_permissions&&Xl.each(l.selectedItem.scopes_permissions[e],function(l){u[l]=!0}),n.push(u)}),this.scopes_permissions=n}},l}()),$l=u["\u0275crt"]({encapsulation:0,styles:[["thead[_ngcontent-%COMP%]{background-color:#f5f5f5}.fa[_ngcontent-%COMP%]{font-size:large}.fa.fa-square-o[_ngcontent-%COMP%]{color:#d1d1d1}"]],data:{}});function ln(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,tl.b,tl.a)),u["\u0275did"](1,180224,null,0,Q.d,[Q.e,u.Renderer2,u.ElementRef],null,null),(l()(),u["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),u["\u0275did"](3,212992,null,0,Q.b,[Q.d,u.ElementRef,u.Renderer2],{heading:[0,"heading"]},null),(l()(),u["\u0275eld"](4,0,null,null,1,"cd-table",[["columnMode","flex"]],null,null,null,il.b,il.a)),u["\u0275did"](5,2867200,null,0,cl.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],toolHeader:[3,"toolHeader"],footer:[4,"footer"],limit:[5,"limit"],autoReload:[6,"autoReload"],autoSave:[7,"autoSave"]},null)],function(l,n){var e=n.component;l(n,3,0,"Details"),l(n,5,0,e.scopes_permissions,e.columns,"flex",!1,!1,0,!1,!1)},function(l,n){l(n,0,0,u["\u0275nov"](n,1).clazz),l(n,2,0,u["\u0275nov"](n,3).id,u["\u0275nov"](n,3).active,u["\u0275nov"](n,3).addClass)})}function nn(l){return u["\u0275vid"](0,[(l()(),u["\u0275and"](16777216,null,null,1,null,ln)),u["\u0275did"](1,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(l,n){var e=n.component;l(n,1,0,null==e.selection?null:e.selection.hasSingleSelection)},null)}var en=e("n/D3"),un=e("ZDA6"),on=u["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function an(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-user-tabs",[],null,null,null,rl,sl)),u["\u0275did"](1,114688,null,0,dl,[X.l],null,null),(l()(),u["\u0275eld"](2,0,null,null,5,"cd-table",[["columnMode","flex"],["identifier","name"],["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(l,n,e){var u=!0,o=l.component;return"fetchData"===n&&(u=!1!==o.getRoles()&&u),"updateSelection"===n&&(u=!1!==o.updateSelection(e)&&u),u},il.b,il.a)),u["\u0275did"](3,2867200,null,0,cl.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],selectionType:[4,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(l()(),u["\u0275eld"](4,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,pl.b,pl.a)),u["\u0275did"](5,114688,null,0,ml.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(l()(),u["\u0275eld"](6,0,null,2,1,"cd-role-details",[["cdTableDetail",""]],null,null,null,nn,$l)),u["\u0275did"](7,638976,null,0,Wl,[h.a],{selection:[0,"selection"],scopes:[1,"scopes"]},null)],function(l,n){var e=n.component;l(n,1,0),l(n,3,0,e.roles,e.columns,"flex","name","single"),l(n,5,0,e.permission,e.selection,e.tableActions),l(n,7,0,e.selection,e.scopes)},null)}function tn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,2,"cd-role-list",[],null,null,null,an,on)),u["\u0275prd"](256,null,fl.a,en.b,[]),u["\u0275did"](2,114688,null,0,en.a,[Vl.a,un.a,N.a,Y.a,z.b,hl.a,h.a,fl.a,bl.b],null,null)],function(l,n){l(n,2,0)},null)}var dn=u["\u0275ccf"]("cd-role-list",en.a,tn,{},{},[]),sn=e("eTJe"),rn=u["\u0275crt"]({encapsulation:0,styles:[[".datatable-permissions-header-cell-label[_ngcontent-%COMP%], .datatable-permissions-scope-cell-label[_ngcontent-%COMP%]{font-weight:700}"]],data:{}});function cn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function pn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["This field is required."]))],null,null)}function mn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["The chosen name is already in use."]))],null,null)}function fn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,4,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"input",[["type","checkbox"]],[[8,"id",0],[8,"checked",0]],[[null,"change"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==l.component.onClickCellCheckbox(l.context.row.scope,l.context.column.prop,e)&&u),u},null,null)),u["\u0275did"](2,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](3,0,null,null,1,"label",[["class","datatable-permissions-scope-cell-label"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),u["\u0275ted"](4,null,["",""]))],null,function(l,n){var e=n.component;l(n,1,0,u["\u0275inlineInterpolate"](1,"scope_",n.context.row.scope,""),e.isRowChecked(n.context.row.scope)),l(n,3,0,u["\u0275inlineInterpolate"](1,"scope_",n.context.row.scope,"")),l(n,4,0,n.context.value)})}function vn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,3,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"input",[["type","checkbox"]],[[8,"checked",0]],[[null,"change"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==l.component.onClickCellCheckbox(l.context.row.scope,l.context.column.prop,e)&&u),u},null,null)),u["\u0275did"](2,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](3,0,null,null,0,"label",[],null,null,null,null,null))],null,function(l,n){l(n,1,0,n.context.value)})}function gn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,4,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(l()(),u["\u0275eld"](1,0,null,null,1,"input",[["type","checkbox"]],[[8,"id",0],[8,"checked",0]],[[null,"change"]],function(l,n,e){var u=!0;return"change"===n&&(u=!1!==l.component.onClickHeaderCheckbox(l.context.column.prop,e)&&u),u},null,null)),u["\u0275did"](2,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](3,0,null,null,1,"label",[["class","datatable-permissions-header-cell-label"]],[[8,"htmlFor",0]],null,null,null,null)),(l()(),u["\u0275ted"](4,null,["",""]))],null,function(l,n){var e=n.component;l(n,1,0,u["\u0275inlineInterpolate"](1,"header_",n.context.column.prop,""),e.isHeaderChecked(n.context.column.prop)),l(n,3,0,u["\u0275inlineInterpolate"](1,"header_",n.context.column.prop,"")),l(n,4,0,n.context.column.name)})}function hn(l){return u["\u0275vid"](0,[u["\u0275pid"](0,f.TitleCasePipe,[]),u["\u0275pid"](0,A.a,[]),u["\u0275qud"](402653184,1,{headerPermissionCheckboxTpl:0}),u["\u0275qud"](402653184,2,{cellScopeCheckboxTpl:0}),u["\u0275qud"](402653184,3,{cellPermissionCheckboxTpl:0}),(l()(),u["\u0275eld"](5,0,null,null,61,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(l()(),u["\u0275eld"](6,0,null,null,60,"form",[["class","form-horizontal"],["name","roleForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(l,n,e){var o=!0;return"submit"===n&&(o=!1!==u["\u0275nov"](l,8).onSubmit(e)&&o),"reset"===n&&(o=!1!==u["\u0275nov"](l,8).onReset()&&o),o},null,null)),u["\u0275did"](7,16384,null,0,v.D,[],null,null),u["\u0275did"](8,540672,[["formDir",4]],0,v.l,[[8,null],[8,null]],{form:[0,"form"]},null),u["\u0275prd"](2048,null,v.d,null,[v.l]),u["\u0275did"](10,16384,null,0,v.s,[[4,v.d]],null,null),(l()(),u["\u0275eld"](11,0,null,null,55,"div",[["class","panel panel-default"]],null,null,null,null,null)),(l()(),u["\u0275eld"](12,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(l()(),u["\u0275eld"](13,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(l()(),u["\u0275ted"](14,null,[""," ",""])),u["\u0275ppd"](15,1),u["\u0275ppd"](16,1),(l()(),u["\u0275eld"](17,0,null,null,40,"div",[["class","panel-body"]],null,null,null,null,null)),(l()(),u["\u0275eld"](18,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](19,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](20,{"has-error":0}),(l()(),u["\u0275eld"](21,0,null,null,4,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(l()(),u["\u0275eld"](22,0,null,null,1,null,null,null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Name"])),(l()(),u["\u0275and"](16777216,null,null,1,null,cn)),u["\u0275did"](25,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](26,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](27,0,null,null,7,"input",[["autofocus",""],["class","form-control"],["formControlName","name"],["id","name"],["name","name"],["placeholder","Name..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,28)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,28).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,28)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,28)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](28,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](30,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](32,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](33,4210688,null,0,El.a,[u.ElementRef],null,null),u["\u0275did"](34,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275and"](16777216,null,null,1,null,pn)),u["\u0275did"](36,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275and"](16777216,null,null,1,null,mn)),u["\u0275did"](38,16384,null,0,f.NgIf,[u.ViewContainerRef,u.TemplateRef],{ngIf:[0,"ngIf"]},null),(l()(),u["\u0275eld"](39,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),u["\u0275did"](40,278528,null,0,f.NgClass,[u.IterableDiffers,u.KeyValueDiffers,u.ElementRef,u.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),u["\u0275pod"](41,{"has-error":0}),(l()(),u["\u0275eld"](42,0,null,null,1,"label",[["class","control-label col-sm-3"],["for","description"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Description"])),(l()(),u["\u0275eld"](44,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](45,0,null,null,6,"input",[["class","form-control"],["formControlName","description"],["id","description"],["name","description"],["placeholder","Description..."],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(l,n,e){var o=!0;return"input"===n&&(o=!1!==u["\u0275nov"](l,46)._handleInput(e.target.value)&&o),"blur"===n&&(o=!1!==u["\u0275nov"](l,46).onTouched()&&o),"compositionstart"===n&&(o=!1!==u["\u0275nov"](l,46)._compositionStart()&&o),"compositionend"===n&&(o=!1!==u["\u0275nov"](l,46)._compositionEnd(e.target.value)&&o),o},null,null)),u["\u0275did"](46,16384,null,0,v.e,[u.Renderer2,u.ElementRef,[2,v.b]],null,null),u["\u0275prd"](1024,null,v.p,function(l){return[l]},[v.e]),u["\u0275did"](48,671744,null,0,v.j,[[3,v.d],[8,null],[8,null],[6,v.p],[2,v.F]],{name:[0,"name"]},null),u["\u0275prd"](2048,null,v.q,null,[v.j]),u["\u0275did"](50,16384,null,0,v.r,[[4,v.q]],null,null),u["\u0275did"](51,4210688,null,0,kl.a,[[2,Nl.a],Y.a,u.ElementRef],null,null),(l()(),u["\u0275eld"](52,0,null,null,5,"div",[["class","form-group"]],null,null,null,null,null)),(l()(),u["\u0275eld"](53,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(l()(),u["\u0275ted"](-1,null,["Permissions"])),(l()(),u["\u0275eld"](55,0,null,null,2,"div",[["class","col-sm-9"]],null,null,null,null,null)),(l()(),u["\u0275eld"](56,0,null,null,1,"cd-table",[["columnMode","flex"]],null,null,null,il.b,il.a)),u["\u0275did"](57,2867200,null,0,cl.a,[u.NgZone,u.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],toolHeader:[3,"toolHeader"],footer:[4,"footer"],limit:[5,"limit"],autoReload:[6,"autoReload"],autoSave:[7,"autoSave"]},null),(l()(),u["\u0275eld"](58,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(l()(),u["\u0275eld"](59,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(l()(),u["\u0275eld"](60,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(l,n,e){var u=!0;return"submitAction"===n&&(u=!1!==l.component.submit()&&u),u},Sl.b,Sl.a)),u["\u0275did"](61,114688,null,0,_l.a,[u.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(l()(),u["\u0275ted"](62,0,[""," ",""])),u["\u0275ppd"](63,1),u["\u0275ppd"](64,1),(l()(),u["\u0275eld"](65,0,null,null,1,"cd-back-button",[],null,null,null,Pl.b,Pl.a)),u["\u0275did"](66,49152,null,0,Ml.a,[f.Location,bl.b],null,null),(l()(),u["\u0275and"](0,[[2,2],["cellScopeCheckboxTpl",2]],null,0,null,fn)),(l()(),u["\u0275and"](0,[[3,2],["cellPermissionCheckboxTpl",2]],null,0,null,vn)),(l()(),u["\u0275and"](0,[[1,2],["headerPermissionCheckboxTpl",2]],null,0,null,gn))],function(l,n){var e=n.component;l(n,8,0,e.roleForm);var o=l(n,20,0,e.roleForm.showError("name",u["\u0275nov"](n,8)));l(n,19,0,"form-group",o),l(n,25,0,e.mode!==e.roleFormMode.editing),l(n,30,0,"name"),l(n,36,0,e.roleForm.showError("name",u["\u0275nov"](n,8),"required")),l(n,38,0,e.roleForm.showError("name",u["\u0275nov"](n,8),"notUnique"));var a=l(n,41,0,e.roleForm.showError("description",u["\u0275nov"](n,8)));l(n,40,0,"form-group",a),l(n,48,0,"description"),l(n,57,0,e.scopes_permissions,e.columns,"flex",!1,!1,0,!1,!1),l(n,61,0,u["\u0275nov"](n,8),"button")},function(l,n){var e=n.component;l(n,6,0,u["\u0275nov"](n,10).ngClassUntouched,u["\u0275nov"](n,10).ngClassTouched,u["\u0275nov"](n,10).ngClassPristine,u["\u0275nov"](n,10).ngClassDirty,u["\u0275nov"](n,10).ngClassValid,u["\u0275nov"](n,10).ngClassInvalid,u["\u0275nov"](n,10).ngClassPending);var o=u["\u0275unv"](n,14,0,l(n,15,0,u["\u0275nov"](n,0),e.action)),a=u["\u0275unv"](n,14,1,l(n,16,0,u["\u0275nov"](n,1),e.resource));l(n,14,0,o,a),l(n,27,0,u["\u0275nov"](n,32).ngClassUntouched,u["\u0275nov"](n,32).ngClassTouched,u["\u0275nov"](n,32).ngClassPristine,u["\u0275nov"](n,32).ngClassDirty,u["\u0275nov"](n,32).ngClassValid,u["\u0275nov"](n,32).ngClassInvalid,u["\u0275nov"](n,32).ngClassPending),l(n,45,0,u["\u0275nov"](n,50).ngClassUntouched,u["\u0275nov"](n,50).ngClassTouched,u["\u0275nov"](n,50).ngClassPristine,u["\u0275nov"](n,50).ngClassDirty,u["\u0275nov"](n,50).ngClassValid,u["\u0275nov"](n,50).ngClassInvalid,u["\u0275nov"](n,50).ngClassPending);var t=u["\u0275unv"](n,62,0,l(n,63,0,u["\u0275nov"](n,0),e.action)),d=u["\u0275unv"](n,62,1,l(n,64,0,u["\u0275nov"](n,1),e.resource));l(n,62,0,t,d)})}function bn(l){return u["\u0275vid"](0,[(l()(),u["\u0275eld"](0,0,null,null,1,"cd-role-form",[],null,null,null,hn,rn)),u["\u0275did"](1,114688,null,0,sn.a,[X.a,X.l,Vl.a,un.a,hl.a,h.a,bl.b],null,null)],function(l,n){l(n,1,0)},null)}var Cn=u["\u0275ccf"]("cd-role-form",sn.a,bn,{},{},[]);e.d(n,"AuthModuleNgFactory",function(){return Rn}),e.d(n,"RoutedAuthModuleNgFactory",function(){return In});var Rn=u["\u0275cmf"](o.a,[],function(l){return u["\u0275mod"]([u["\u0275mpd"](512,u.ComponentFactoryResolver,u["\u0275CodegenComponentFactoryResolver"],[[8,[a.a,t.a,d.a,s.a,r.a,r.b,i.a,c.a,p.a,m.a]],[3,u.ComponentFactoryResolver],u.NgModuleRef]),u["\u0275mpd"](4608,f.NgLocalization,f.NgLocaleLocalization,[u.LOCALE_ID,[2,f["\u0275angular_packages_common_common_a"]]]),u["\u0275mpd"](4608,v.E,v.E,[]),u["\u0275mpd"](4608,v.h,v.h,[]),u["\u0275mpd"](4608,g.a,g.a,[h.a]),u["\u0275mpd"](4608,f.DatePipe,f.DatePipe,[u.LOCALE_ID]),u["\u0275mpd"](4608,b.a,b.a,[]),u["\u0275mpd"](4608,C.a,C.a,[]),u["\u0275mpd"](4608,R.a,R.a,[]),u["\u0275mpd"](4608,I.a,I.a,[R.a]),u["\u0275mpd"](4608,y.a,y.a,[R.a]),u["\u0275mpd"](4608,T.a,T.a,[R.a]),u["\u0275mpd"](4608,w.a,w.a,[]),u["\u0275mpd"](4608,D.a,D.a,[]),u["\u0275mpd"](4608,x.a,x.a,[]),u["\u0275mpd"](4608,E.a,E.a,[]),u["\u0275mpd"](4608,k.a,k.a,[f.DatePipe]),u["\u0275mpd"](4608,N.a,N.a,[]),u["\u0275mpd"](4608,F.a,F.a,[]),u["\u0275mpd"](4608,S.a,S.a,[]),u["\u0275mpd"](4608,_.a,_.a,[]),u["\u0275mpd"](4608,P.a,P.a,[]),u["\u0275mpd"](4608,M.a,M.a,[h.a]),u["\u0275mpd"](4608,A.a,A.a,[]),u["\u0275mpd"](4608,q.a,q.a,[]),u["\u0275mpd"](4608,V.b,V.b,[]),u["\u0275mpd"](4608,L.a,L.a,[]),u["\u0275mpd"](4608,U.a,U.a,[u.RendererFactory2,u.PLATFORM_ID]),u["\u0275mpd"](4608,O.a,O.a,[u.ComponentFactoryResolver,u.NgZone,u.Injector,U.a,u.ApplicationRef]),u["\u0275mpd"](4608,j.a,j.a,[]),u["\u0275mpd"](4608,z.b,z.b,[u.RendererFactory2,O.a]),u["\u0275mpd"](4608,H.ScrollbarHelper,H.ScrollbarHelper,[B.DOCUMENT]),u["\u0275mpd"](4608,Z.DimensionsHelper,Z.DimensionsHelper,[]),u["\u0275mpd"](4608,G.ColumnChangesService,G.ColumnChangesService,[]),u["\u0275mpd"](4608,K.f,K.f,[]),u["\u0275mpd"](4608,Y.a,Y.a,[]),u["\u0275mpd"](4608,J.a,J.a,[X.l,Y.a]),u["\u0275mpd"](4608,Q.e,Q.e,[]),u["\u0275mpd"](1073742336,K.e,K.e,[]),u["\u0275mpd"](1073742336,f.CommonModule,f.CommonModule,[]),u["\u0275mpd"](1073742336,v.B,v.B,[]),u["\u0275mpd"](1073742336,v.n,v.n,[]),u["\u0275mpd"](1073742336,L.d,L.d,[]),u["\u0275mpd"](1073742336,v.x,v.x,[]),u["\u0275mpd"](1073742336,W.a,W.a,[]),u["\u0275mpd"](1073742336,V.c,V.c,[]),u["\u0275mpd"](1073742336,j.d,j.d,[]),u["\u0275mpd"](1073742336,$.ChartsModule,$.ChartsModule,[]),u["\u0275mpd"](1073742336,z.e,z.e,[]),u["\u0275mpd"](1073742336,ll.a,ll.a,[]),u["\u0275mpd"](1073742336,nl.a,nl.a,[]),u["\u0275mpd"](1073742336,el.NgxDatatableModule,el.NgxDatatableModule,[]),u["\u0275mpd"](1073742336,X.p,X.p,[[2,X.v],[2,X.l]]),u["\u0275mpd"](1073742336,ul.a,ul.a,[]),u["\u0275mpd"](1073742336,ol.a,ol.a,[]),u["\u0275mpd"](1073742336,al.a,al.a,[]),u["\u0275mpd"](1073742336,Q.c,Q.c,[]),u["\u0275mpd"](1073742336,o.a,o.a,[]),u["\u0275mpd"](256,u.LOCALE_ID,"en-US",[]),u["\u0275mpd"](256,K.a,{autoClose:!0,insideClick:!1},[]),u["\u0275mpd"](256,u.TRANSLATIONS_FORMAT,"xlf",[])])}),In=u["\u0275cmf"](o.b,[],function(l){return u["\u0275mod"]([u["\u0275mpd"](512,u.ComponentFactoryResolver,u["\u0275CodegenComponentFactoryResolver"],[[8,[a.a,t.a,d.a,s.a,r.a,r.b,i.a,c.a,p.a,m.a,wl,Jl,dn,Cn]],[3,u.ComponentFactoryResolver],u.NgModuleRef]),u["\u0275mpd"](4608,f.NgLocalization,f.NgLocaleLocalization,[u.LOCALE_ID,[2,f["\u0275angular_packages_common_common_a"]]]),u["\u0275mpd"](4608,v.E,v.E,[]),u["\u0275mpd"](4608,v.h,v.h,[]),u["\u0275mpd"](4608,g.a,g.a,[h.a]),u["\u0275mpd"](4608,f.DatePipe,f.DatePipe,[u.LOCALE_ID]),u["\u0275mpd"](4608,b.a,b.a,[]),u["\u0275mpd"](4608,C.a,C.a,[]),u["\u0275mpd"](4608,R.a,R.a,[]),u["\u0275mpd"](4608,I.a,I.a,[R.a]),u["\u0275mpd"](4608,y.a,y.a,[R.a]),u["\u0275mpd"](4608,T.a,T.a,[R.a]),u["\u0275mpd"](4608,w.a,w.a,[]),u["\u0275mpd"](4608,D.a,D.a,[]),u["\u0275mpd"](4608,x.a,x.a,[]),u["\u0275mpd"](4608,E.a,E.a,[]),u["\u0275mpd"](4608,k.a,k.a,[f.DatePipe]),u["\u0275mpd"](4608,N.a,N.a,[]),u["\u0275mpd"](4608,F.a,F.a,[]),u["\u0275mpd"](4608,S.a,S.a,[]),u["\u0275mpd"](4608,_.a,_.a,[]),u["\u0275mpd"](4608,P.a,P.a,[]),u["\u0275mpd"](4608,M.a,M.a,[h.a]),u["\u0275mpd"](4608,A.a,A.a,[]),u["\u0275mpd"](4608,q.a,q.a,[]),u["\u0275mpd"](4608,V.b,V.b,[]),u["\u0275mpd"](4608,L.a,L.a,[]),u["\u0275mpd"](4608,U.a,U.a,[u.RendererFactory2,u.PLATFORM_ID]),u["\u0275mpd"](4608,O.a,O.a,[u.ComponentFactoryResolver,u.NgZone,u.Injector,U.a,u.ApplicationRef]),u["\u0275mpd"](4608,j.a,j.a,[]),u["\u0275mpd"](4608,z.b,z.b,[u.RendererFactory2,O.a]),u["\u0275mpd"](4608,H.ScrollbarHelper,H.ScrollbarHelper,[B.DOCUMENT]),u["\u0275mpd"](4608,Z.DimensionsHelper,Z.DimensionsHelper,[]),u["\u0275mpd"](4608,G.ColumnChangesService,G.ColumnChangesService,[]),u["\u0275mpd"](4608,K.f,K.f,[]),u["\u0275mpd"](4608,Y.a,Y.a,[]),u["\u0275mpd"](4608,J.a,J.a,[X.l,Y.a]),u["\u0275mpd"](4608,Q.e,Q.e,[]),u["\u0275mpd"](1073742336,K.e,K.e,[]),u["\u0275mpd"](1073742336,f.CommonModule,f.CommonModule,[]),u["\u0275mpd"](1073742336,v.B,v.B,[]),u["\u0275mpd"](1073742336,v.n,v.n,[]),u["\u0275mpd"](1073742336,L.d,L.d,[]),u["\u0275mpd"](1073742336,v.x,v.x,[]),u["\u0275mpd"](1073742336,W.a,W.a,[]),u["\u0275mpd"](1073742336,V.c,V.c,[]),u["\u0275mpd"](1073742336,j.d,j.d,[]),u["\u0275mpd"](1073742336,$.ChartsModule,$.ChartsModule,[]),u["\u0275mpd"](1073742336,z.e,z.e,[]),u["\u0275mpd"](1073742336,ll.a,ll.a,[]),u["\u0275mpd"](1073742336,nl.a,nl.a,[]),u["\u0275mpd"](1073742336,el.NgxDatatableModule,el.NgxDatatableModule,[]),u["\u0275mpd"](1073742336,X.p,X.p,[[2,X.v],[2,X.l]]),u["\u0275mpd"](1073742336,ul.a,ul.a,[]),u["\u0275mpd"](1073742336,ol.a,ol.a,[]),u["\u0275mpd"](1073742336,al.a,al.a,[]),u["\u0275mpd"](1073742336,Q.c,Q.c,[]),u["\u0275mpd"](1073742336,o.a,o.a,[]),u["\u0275mpd"](1073742336,o.b,o.b,[]),u["\u0275mpd"](256,u.LOCALE_ID,"en-US",[]),u["\u0275mpd"](256,K.a,{autoClose:!0,insideClick:!1},[]),u["\u0275mpd"](1024,X.j,function(){return[[{path:"",redirectTo:"users",pathMatch:"full"},{path:"users",data:o.c,children:[{path:"",component:vl.a},{path:"create",component:Al.a,data:o.d},{path:"edit/:username",component:Al.a,data:o.e}]},{path:"roles",data:o.f,children:[{path:"",component:en.a},{path:"create",component:sn.a,data:o.g},{path:"edit/:name",component:sn.a,data:o.h}]}]]},[]),u["\u0275mpd"](256,u.TRANSLATIONS_FORMAT,"xlf",[])])})}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/Ceph_Logo_Stacked_RGB_120411_fa_228x228.1ed169ccc35367a2dab2.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/Ceph_Logo_Stacked_RGB_120411_fa_228x228.1ed169ccc35367a2dab2.png
new file mode 100644
index 00000000..79064dc0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/Ceph_Logo_Stacked_RGB_120411_fa_228x228.1ed169ccc35367a2dab2.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Mimic_Octopus2.jpg b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Mimic_Octopus2.jpg
new file mode 100644
index 00000000..f8cf2a8d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Mimic_Octopus2.jpg
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Nautilus_Octopus.jpg b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Nautilus_Octopus.jpg
new file mode 100644
index 00000000..1f0776fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/1280px-Nautilus_Octopus.jpg
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png
new file mode 100644
index 00000000..79064dc0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png
new file mode 100644
index 00000000..d46bd73f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png
new file mode 100644
index 00000000..26d602be
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png
new file mode 100644
index 00000000..0f07b83e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/loading.gif b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/loading.gif
new file mode 100644
index 00000000..8fb88dea
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/loading.gif
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/logo-mini.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/logo-mini.png
new file mode 100644
index 00000000..b3446a89
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/logo-mini.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/notification-icons.png b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/notification-icons.png
new file mode 100644
index 00000000..d609a7c8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/notification-icons.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/prometheus_logo.svg b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/prometheus_logo.svg
new file mode 100644
index 00000000..5c51f66d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/assets/prometheus_logo.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="115.333px"
+ height="114px"
+ viewBox="0 0 115.333 114"
+ enable-background="new 0 0 115.333 114"
+ xml:space="preserve"
+ sodipodi:docname="prometheus_logo_orange.svg"
+ inkscape:version="0.92.1 r15371"><metadata
+ id="metadata4495"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs4493" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1484"
+ inkscape:window-height="886"
+ id="namedview4491"
+ showgrid="false"
+ inkscape:zoom="5.2784901"
+ inkscape:cx="60.603667"
+ inkscape:cy="60.329656"
+ inkscape:window-x="54"
+ inkscape:window-y="7"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" /><g
+ id="Layer_2" /><path
+ style="fill:#e6522c;fill-opacity:1"
+ inkscape:connector-curvature="0"
+ id="path4486"
+ d="M 56.667,0.667 C 25.372,0.667 0,26.036 0,57.332 c 0,31.295 25.372,56.666 56.667,56.666 31.295,0 56.666,-25.371 56.666,-56.666 0,-31.296 -25.372,-56.665 -56.666,-56.665 z m 0,106.055 c -8.904,0 -16.123,-5.948 -16.123,-13.283 H 72.79 c 0,7.334 -7.219,13.283 -16.123,13.283 z M 83.297,89.04 H 30.034 V 79.382 H 83.298 V 89.04 Z M 83.106,74.411 H 30.186 C 30.01,74.208 29.83,74.008 29.66,73.802 24.208,67.182 22.924,63.726 21.677,60.204 c -0.021,-0.116 6.611,1.355 11.314,2.413 0,0 2.42,0.56 5.958,1.205 -3.397,-3.982 -5.414,-9.044 -5.414,-14.218 0,-11.359 8.712,-21.285 5.569,-29.308 3.059,0.249 6.331,6.456 6.552,16.161 3.252,-4.494 4.613,-12.701 4.613,-17.733 0,-5.21 3.433,-11.262 6.867,-11.469 -3.061,5.045 0.793,9.37 4.219,20.099 1.285,4.03 1.121,10.812 2.113,15.113 C 63.797,33.534 65.333,20.5 71,16 c -2.5,5.667 0.37,12.758 2.333,16.167 3.167,5.5 5.087,9.667 5.087,17.548 0,5.284 -1.951,10.259 -5.242,14.148 3.742,-0.702 6.326,-1.335 6.326,-1.335 l 12.152,-2.371 c 10e-4,-10e-4 -1.765,7.261 -8.55,14.254 z" /></svg> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/common.8a53d98b04768bd15706.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/common.8a53d98b04768bd15706.js
new file mode 100644
index 00000000..85fd813e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/common.8a53d98b04768bd15706.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[0],{pYKc:function(l,n,e){"use strict";var t=e("CcnG"),u=e("WiuZ"),i=e("wnGv"),s=e("Jm/i"),a=e("Ip0R");e("ppaS"),e.d(n,"a",function(){return c}),e.d(n,"b",function(){return r});var c=t["\u0275crt"]({encapsulation:0,styles:[[".select-menu-edit{margin-left:-20px}.badge-remove[_ngcontent-%COMP%]{color:#fff}"]],data:{}});function o(l){return t["\u0275vid"](0,[(l()(),t["\u0275eld"](0,0,null,null,5,"span",[],null,null,null,null,null)),(l()(),t["\u0275eld"](1,0,null,null,4,"span",[["class","badge badge-pill badge-primary margin-right-sm"]],null,null,null,null,null)),(l()(),t["\u0275eld"](2,0,null,null,1,"span",[["class","margin-right-sm"]],null,null,null,null,null)),(l()(),t["\u0275ted"](3,null,["",""])),(l()(),t["\u0275eld"](4,0,null,null,1,"a",[["class","badge-remove"]],null,[[null,"click"]],function(l,n,e){var u=!0;return"click"===n&&(u=!1!==t["\u0275nov"](l.parent,2).removeItem(l.context.$implicit)&&u),u},null,null)),(l()(),t["\u0275eld"](5,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-times"]],null,null,null,null,null))],null,function(l,n){l(n,3,0,n.context.$implicit)})}function r(l){return t["\u0275vid"](0,[t["\u0275qud"](402653184,1,{cdSelect:0}),(l()(),t["\u0275eld"](1,0,null,null,2,"cd-select",[["elemClass","margin-right-sm select-menu-edit"]],null,[[null,"selection"]],function(l,n,e){var t=!0;return"selection"===n&&(t=!1!==l.component.selection.emit(e)&&t),t},u.b,u.a)),t["\u0275did"](2,638976,[[1,4],["cdSelect",4]],0,i.a,[s.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"],selectionLimit:[4,"selectionLimit"],customBadges:[5,"customBadges"],customBadgeValidators:[6,"customBadgeValidators"]},{selection:"selection"}),(l()(),t["\u0275eld"](3,0,null,0,0,"i",[["class","fa fa-fw fa-pencil"]],null,null,null,null,null)),(l()(),t["\u0275and"](16777216,null,null,1,null,o)),t["\u0275did"](5,278528,null,0,a.NgForOf,[t.ViewContainerRef,t.TemplateRef,t.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(l,n){var e=n.component;l(n,2,0,"margin-right-sm select-menu-edit",e.data,e.options,e.messages,e.selectionLimit,e.customBadges,e.customBadgeValidators),l(n,5,0,e.data)},null)}},ppaS:function(l,n,e){"use strict";e.d(n,"a",function(){return i});var t=e("CcnG"),u=e("DNAf"),i=function(){return function(l){this.i18n=l,this.data=[],this.options=[],this.messages=new u.a({},this.i18n),this.customBadges=!1,this.customBadgeValidators=[],this.selection=new t.EventEmitter}}()}}]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/favicon.ico b/src/pybind/mgr/dashboard/frontend/dist/en-US/favicon.ico
new file mode 100644
index 00000000..90e538ba
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/favicon.ico
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.35e77a38ca9d85c4e897.eot b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.35e77a38ca9d85c4e897.eot
new file mode 100644
index 00000000..b96d208f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.35e77a38ca9d85c4e897.eot
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.3a9e014c2469ffa65a0e.woff2 b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.3a9e014c2469ffa65a0e.woff2
new file mode 100644
index 00000000..f3520b53
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.3a9e014c2469ffa65a0e.woff2
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woff b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woff
new file mode 100644
index 00000000..477da445
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woff
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.78dcc9c4999659b8026a.svg b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.78dcc9c4999659b8026a.svg
new file mode 100644
index 00000000..e9972045
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.78dcc9c4999659b8026a.svg
@@ -0,0 +1,2849 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<!--
+2019-2-18: Created with FontForge (http://fontforge.org)
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
+<metadata>
+Created by FontForge 20180321 at Mon Feb 18 18:29:30 2019
+ By Julien Deswaef
+The Fork Awesome font is licensed under the SIL OFL 1.1 (http://scripts.sil.org/OFL). Fork Awesome is a fork based of off Font Awesome 4.7.0 by Dave Gandy. More info on licenses at https://forkawesome.github.io
+</metadata>
+<defs>
+<font id="forkawesome" horiz-adv-x="1536" >
+ <font-face
+ font-family="forkawesome"
+ font-weight="400"
+ font-stretch="normal"
+ units-per-em="1792"
+ panose-1="2 0 5 3 0 0 0 0 0 0"
+ ascent="1536"
+ descent="-256"
+ bbox="-0.653061 -264 2304.01 1538"
+ underline-thickness="89.6"
+ underline-position="-179.2"
+ unicode-range="U+0020-F32B"
+ />
+ <missing-glyph />
+ <glyph glyph-name="space" unicode=" " horiz-adv-x="200"
+ />
+ <glyph glyph-name="code" unicode="&#xf121;" horiz-adv-x="1830"
+d="M572 137l-50 -50c-13 -13 -33 -13 -46 0l-466 466c-13 13 -13 33 0 46l466 466c13 13 33 13 46 0l50 -50c13 -13 13 -33 0 -46l-393 -393l393 -393c13 -13 13 -33 0 -46zM1163 1204l-373 -1291c-5 -17 -23 -27 -39 -22l-62 17c-17 5 -27 23 -22 40l373 1291
+c5 17 23 27 39 22l62 -17c17 -5 27 -23 22 -40zM1820 553l-466 -466c-13 -13 -33 -13 -46 0l-50 50c-13 13 -13 33 0 46l393 393l-393 393c-13 13 -13 33 0 46l50 50c13 13 33 13 46 0l466 -466c13 -13 13 -33 0 -46z" />
+ <glyph glyph-name="chevron-circle-right" unicode="&#xf138;"
+d="M717 141l454 454c25 25 25 65 0 90l-454 454c-25 25 -65 25 -90 0l-102 -102c-25 -25 -25 -65 0 -90l307 -307l-307 -307c-25 -25 -25 -65 0 -90l102 -102c25 -25 65 -25 90 0zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768
+s768 -344 768 -768z" />
+ <glyph glyph-name="crosshairs" unicode="&#xf05b;"
+d="M1197 512h-109c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h109c-43 144 -157 258 -301 301v-109c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v109c-144 -43 -258 -157 -301 -301h109c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-109c43 -144 157 -258 301 -301
+v109c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-109c144 43 258 157 301 301zM1536 704v-128c0 -35 -29 -64 -64 -64h-143c-49 -215 -218 -384 -433 -433v-143c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v143c-215 49 -384 218 -433 433h-143c-35 0 -64 29 -64 64v128
+c0 35 29 64 64 64h143c49 215 218 384 433 433v143c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-143c215 -49 384 -218 433 -433h143c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="gg" unicode="&#xf260;" horiz-adv-x="1920"
+d="M672 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1248 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+ <glyph glyph-name="wpforms" unicode="&#xf298;"
+d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240c0 11 -9 20 -20 20h-32l-378 -256l-210 171l-210 -171l-378 256h-32c-11 0 -20 -9 -20 -20v-1240
+c0 -11 9 -20 20 -20h1240c11 0 20 9 20 20zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240c0 -82 -66 -148 -148 -148h-1240c-82 0 -148 66 -148 148v1240c0 82 66 148 148 148h1240c82 0 148 -66 148 -148z" />
+ <glyph glyph-name="angle-double-left" unicode="&#xf100;" horiz-adv-x="966"
+d="M582 160c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -15 10 -23s-4 -17 -10 -23l-393 -393l393 -393c6 -6 10 -15 10 -23zM966 160
+c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -15 10 -23s-4 -17 -10 -23l-393 -393l393 -393c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="list" unicode="&#xf03a;" horiz-adv-x="1792"
+d="M256 224v-192c0 -17 -15 -32 -32 -32h-192c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h192c17 0 32 -15 32 -32zM256 608v-192c0 -17 -15 -32 -32 -32h-192c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h192c17 0 32 -15 32 -32zM256 992v-192c0 -17 -15 -32 -32 -32h-192
+c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h192c17 0 32 -15 32 -32zM1792 224v-192c0 -17 -15 -32 -32 -32h-1344c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1344c17 0 32 -15 32 -32zM256 1376v-192c0 -17 -15 -32 -32 -32h-192c-17 0 -32 15 -32 32v192
+c0 17 15 32 32 32h192c17 0 32 -15 32 -32zM1792 608v-192c0 -17 -15 -32 -32 -32h-1344c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1344c17 0 32 -15 32 -32zM1792 992v-192c0 -17 -15 -32 -32 -32h-1344c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1344
+c17 0 32 -15 32 -32zM1792 1376v-192c0 -17 -15 -32 -32 -32h-1344c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1344c17 0 32 -15 32 -32z" />
+ <glyph glyph-name="archlinux" unicode="&#xf323;" horiz-adv-x="1794"
+d="M897 1538c164 -386 203 -504 682 -1397c-61 36 -138 70 -247 98c158 -81 236 -156 310 -214c47 -87 97 -179 152 -281c-281 162 -499 263 -702 303c7 31 11 64 12 98c5 182 -83 337 -195 347s-207 -131 -212 -313v-9c0 -43 4 -84 13 -122c-205 -39 -426 -140 -710 -304
+c362 650 540 989 654 1226c60 -50 139 -99 256 -147c-109 76 -175 143 -230 201c89 190 137 318 217 514z" />
+ <glyph glyph-name="th" unicode="&#xf00a;" horiz-adv-x="1792"
+d="M512 288v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM512 800v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1152 288v-192c0 -53 -43 -96 -96 -96h-320
+c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM512 1312v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1152 800v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96
+h320c53 0 96 -43 96 -96zM1792 288v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1152 1312v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1792 800v-192
+c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1792 1312v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="angle-left" unicode="&#xf104;" horiz-adv-x="582"
+d="M582 992c0 -8 -4 -17 -10 -23l-393 -393l393 -393c6 -6 10 -15 10 -23s-4 -17 -10 -23l-50 -50c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -14 10 -23z" />
+ <glyph glyph-name="recycle" unicode="&#xf1b8;" horiz-adv-x="1760"
+d="M820 367l-15 -368l-2 -22l-420 29c-52 4 -95 53 -114 97c-40 93 12 203 42 292c0 0 77 -12 509 -28zM433 953l180 -379l-147 92c-225 -257 -246 -448 -246 -448l-190 357c-39 58 -4 121 -4 121s35 63 114 188l-140 86zM1664 436l-188 -359c-26 -65 -98 -71 -98 -71
+s-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173c339 -41 509 50 509 50zM879 1360c0 0 -47 -62 -265 -435l-317 187l-19 12l225 356c28 44 91 60 140 55c100 -9 172 -106 236 -175zM1534 1053l212 -363c27 -45 11 -108 -15 -150c-54 -84 -174 -104 -264 -129
+c0 0 -34 71 -265 436l313 195zM1391 1279l142 83l-220 -373l-419 20l151 86c-120 319 -279 429 -279 429l405 -1c70 6 108 -54 108 -54s39 -61 112 -190z" />
+ <glyph glyph-name="file-code-o" unicode="&#xf1c9;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM480 768c11 14 31 17 45 6l51 -38c14 -11 17 -31 6 -45l-182 -243l182 -243c11 -14 8 -34 -6 -45l-51 -38c-14 -11 -34 -8 -45 6l-226 301c-8 11 -8 27 0 38zM1282 467c8 -11 8 -27 0 -38l-226 -301c-11 -14 -31 -17 -45 -6l-51 38c-14 11 -17 31 -6 45
+l182 243l-182 243c-11 14 -8 34 6 45l51 38c14 11 34 8 45 -6zM662 6c-18 3 -29 20 -26 37l138 831c3 18 20 29 37 26l63 -10c18 -3 29 -20 26 -37l-138 -831c-3 -18 -20 -29 -37 -26z" />
+ <glyph glyph-name="thumb-tack" unicode="&#xf08d;" horiz-adv-x="1152"
+d="M480 672v448c0 18 -14 32 -32 32s-32 -14 -32 -32v-448c0 -18 14 -32 32 -32s32 14 32 32zM1152 320c0 -35 -29 -64 -64 -64h-429l-51 -483c-2 -16 -15 -29 -31 -29h-1c-16 0 -29 11 -32 27l-76 485h-404c-35 0 -64 29 -64 64c0 164 124 320 256 320v512
+c-70 0 -128 58 -128 128s58 128 128 128h640c70 0 128 -58 128 -128s-58 -128 -128 -128v-512c132 0 256 -156 256 -320z" />
+ <glyph glyph-name="fax" unicode="&#xf1ac;" horiz-adv-x="1792"
+d="M288 1152c88 0 160 -72 160 -160v-1088c0 -88 -72 -160 -160 -160h-128c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h128zM1664 989c76 -44 128 -127 128 -221v-768c0 -141 -115 -256 -256 -256h-864c-88 0 -160 72 -160 160v1536c0 53 43 96 96 96h672
+c53 0 127 -31 164 -68l152 -152c37 -37 68 -111 68 -164v-163zM928 0v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM928 256v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128
+c18 0 32 14 32 32zM928 512v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1184 0v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1184 256v128
+c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1184 512v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1440 0v128c0 18 -14 32 -32 32h-128
+c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1440 256v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1440 512v128c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-128
+c0 -18 14 -32 32 -32h128c18 0 32 14 32 32zM1536 896v256h-160c-53 0 -96 43 -96 96v160h-640v-512h896z" />
+ <glyph glyph-name="xing-square" unicode="&#xf169;"
+d="M685 771c0 0 0 1 -126 222c-10 16 -24 34 -52 34h-184c-12 0 -21 -4 -26 -11c-5 -8 -4 -19 1 -29l125 -216v-1l-196 -346c-6 -10 -5 -20 0 -28s13 -13 24 -13h185c27 0 41 19 50 36c192 339 199 352 199 352zM1309 1268c-5 8 -13 12 -24 12h-187c-27 0 -39 -17 -49 -35
+c-398 -706 -411 -729 -411 -729s0 -1 262 -481c9 -16 23 -35 52 -35h184c11 0 20 4 25 12s5 18 -1 28l-260 476v1l409 723c5 10 5 20 0 28zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960
+c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="google-plus-official" unicode="&#xf2b3;"
+d="M917 631c0 22 -2 43 -6 64h-362v-132h217c-16 -106 -116 -165 -217 -165c-133 0 -239 110 -239 242s106 242 239 242c56 0 112 -19 153 -59l104 101c-71 66 -160 100 -257 100c-213 0 -384 -172 -384 -384s171 -384 384 -384c221 0 368 156 368 375zM1262 585h109v110
+h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="quora" unicode="&#xf2c4;" horiz-adv-x="1734"
+d="M1226 749c0 417 -130 631 -435 631c-300 0 -430 -214 -430 -631c0 -415 130 -627 430 -627c48 0 91 5 131 17c-62 122 -135 245 -277 245c-27 0 -54 -4 -79 -16l-49 97c59 51 154 91 276 91c191 0 288 -92 366 -209c45 100 67 235 67 402zM1616 117h117
+c7 -72 -29 -373 -356 -373c-198 0 -302 115 -381 249c-65 -18 -135 -27 -205 -27c-400 0 -791 319 -791 783c0 468 392 787 791 787c407 0 794 -317 794 -787c0 -262 -122 -475 -299 -612c57 -86 116 -143 198 -143c90 0 126 69 132 123z" />
+ <glyph glyph-name="archive-org" unicode="&#xf2fc;" horiz-adv-x="1506"
+d="M1459 1344l-27 -53h-1385l-24 53l717 189zM1430 1237v-140h-1380v140h1380zM1257 442c-3 65 -4 124 -3 178c0 25 1 61 3 108s3 77 3 91c1 22 3 57 5 104s4 82 5 107c0 1 1 3 1 7v10c47 10 93 10 138 0c21 -325 21 -630 0 -916c-41 -11 -82 -12 -123 -1c-6 1 -10 2 -11 2
+s-3 2 -3 3s-1 4 -1 9c-3 34 -6 90 -10 165zM80 369v0c-1 9 -1 22 -1 38c0 5 -1 11 -1 21s-1 17 -1 22c0 26 0 45 -1 57v219c2 38 3 68 3 88c2 32 3 56 3 71c1 7 1 15 1 26c0 3 1 9 1 17s1 14 1 18c0 7 0 10 1 12c0 12 0 22 1 28c0 11 1 20 2 27c0 11 0 19 1 24c0 4 2 6 7 7
+c29 10 61 13 96 8c11 -2 22 -5 32 -9c2 0 3 -2 3 -6c2 -42 4 -74 6 -97c1 -20 2 -50 3 -90s2 -69 2 -88s1 -47 1 -85s1 -66 2 -84c-3 -131 -4 -199 -4 -206c-1 -47 -3 -112 -7 -194c-2 -27 -3 -47 -3 -60c0 -3 -2 -5 -6 -6c-28 -9 -59 -11 -94 -8c-4 1 -10 3 -18 5
+s-12 4 -14 5c-4 0 -6 1 -6 4c0 12 0 21 -1 26c0 4 -1 8 -1 14s-1 10 -1 13c0 9 0 15 -1 20c0 6 -1 13 -1 24v25c-1 6 -2 14 -2 25s0 19 -1 25c0 17 -1 30 -2 40v24zM464 255v0v25s-1 19 -1 25c-1 10 -1 23 -1 40c-1 5 -2 13 -2 24c0 16 0 29 -1 38v43c-1 13 -2 32 -2 57v29
+s-1 21 -1 27v102c0 27 0 47 1 61c0 18 1 48 3 88c0 17 1 40 3 71c0 11 0 20 1 26c0 15 1 27 2 35v12c0 4 1 9 1 15v13s1 7 2 13s1 10 1 14l2 24c0 4 1 6 5 7c30 10 62 13 96 8c11 -2 22 -5 32 -9c4 0 6 -2 6 -6l4 -97l4 -178c2 -78 3 -135 3 -169c0 -24 -1 -59 -1 -104
+s-1 -79 -2 -102c-1 -47 -3 -112 -7 -194c0 -13 -1 -33 -3 -60c0 -3 -2 -5 -7 -6c-26 -10 -57 -12 -92 -8c-4 0 -7 1 -11 2s-8 3 -13 4s-8 3 -10 4c-2 0 -3 1 -3 4c-1 7 -1 15 -1 26c-1 7 -2 16 -2 27c-2 4 -3 10 -3 20zM1046 961v0c1 -26 3 -63 4 -114s2 -89 2 -114
+c2 -67 3 -113 3 -140c0 -22 -1 -53 -1 -95s-1 -73 -2 -94c-1 -45 -3 -111 -7 -199c-1 -8 -2 -20 -2 -36s0 -28 -1 -36c0 -3 -2 -5 -7 -6c-27 -9 -58 -11 -93 -8c-5 1 -12 2 -20 5s-12 5 -13 5c-3 0 -5 1 -5 5c0 12 0 31 -2 56s-4 45 -5 58c0 15 -1 40 -2 73s-2 59 -3 77
+c0 13 -1 33 -2 60s-1 47 -1 60v68c-1 46 -1 69 0 70c1 55 3 136 7 242c2 48 4 94 8 139c0 4 2 6 6 7c29 10 61 13 95 8c12 -2 23 -5 33 -9c3 0 4 -2 4 -6zM60 -18v98h1390v-98h-1390zM0 -128v73h1506v-73h-1506z" />
+ <glyph glyph-name="volume-up" unicode="&#xf028;" horiz-adv-x="1664"
+d="M768 1184v-1088c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-333 333h-262c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h262l333 333c12 12 28 19 45 19c35 0 64 -29 64 -64zM1152 640c0 -100 -61 -197 -155 -235c-8 -4 -17 -5 -25 -5c-35 0 -64 28 -64 64
+c0 76 116 55 116 176s-116 100 -116 176c0 36 29 64 64 64c8 0 17 -1 25 -5c94 -37 155 -135 155 -235zM1408 640c0 -203 -122 -392 -310 -471c-8 -3 -17 -5 -25 -5c-36 0 -65 29 -65 64c0 28 16 47 39 59c27 14 52 26 76 44c99 72 157 187 157 309s-58 237 -157 309
+c-24 18 -49 30 -76 44c-23 12 -39 31 -39 59c0 35 29 64 64 64c9 0 18 -2 26 -5c188 -79 310 -268 310 -471zM1664 640c0 -307 -183 -585 -465 -706c-8 -3 -17 -5 -26 -5c-35 0 -64 29 -64 64c0 29 15 45 39 59c14 8 30 13 45 21c28 15 56 32 82 51c164 121 261 312 261 516
+s-97 395 -261 516c-26 19 -54 36 -82 51c-15 8 -31 13 -45 21c-24 14 -39 30 -39 59c0 35 29 64 64 64c9 0 18 -2 26 -5c282 -121 465 -399 465 -706z" />
+ <glyph glyph-name="spoon" unicode="&#xf1b1;" horiz-adv-x="640"
+d="M640 1008c0 -200 -87 -331 -209 -379l45 -821c2 -35 -25 -64 -60 -64h-192c-35 0 -62 29 -60 64l45 821c-122 48 -209 179 -209 379c0 256 143 528 320 528s320 -272 320 -528z" />
+ <glyph glyph-name="facebook" unicode="&#xf09a;" horiz-adv-x="864"
+d="M864 1524v-264h-157c-123 0 -146 -59 -146 -144v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218c0 253 155 391 381 391c108 0 201 -8 228 -12z" />
+ <glyph glyph-name="universal-access" unicode="&#xf29a;" horiz-adv-x="1792"
+d="M1374 879c-8 34 -42 55 -77 47c-143 -34 -273 -62 -401 -62s-258 28 -401 62c-35 8 -69 -13 -77 -47c-8 -35 13 -69 47 -77c106 -25 205 -47 303 -58c-4 -338 -41 -432 -83 -540l-9 -21c-13 -33 4 -70 37 -83c7 -3 15 -4 23 -4c26 0 50 15 60 41l8 20
+c28 72 54 139 71 259h42c17 -120 43 -187 71 -259l8 -20c10 -26 34 -41 60 -41c8 0 16 1 23 4c33 13 50 50 37 83l-9 21c-42 108 -79 202 -83 540c98 11 197 33 303 58c34 8 55 42 47 77zM1024 1024c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128
+s128 57 128 128zM1600 640c0 -389 -315 -704 -704 -704s-704 315 -704 704s315 704 704 704s704 -315 704 -704zM896 1408c-423 0 -768 -345 -768 -768s345 -768 768 -768s768 345 768 768s-345 768 -768 768zM1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896
+s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="cloud-download" unicode="&#xf0ed;" horiz-adv-x="1920"
+d="M1280 608c0 18 -14 32 -32 32h-224v352c0 17 -15 32 -32 32h-192c-17 0 -32 -15 -32 -32v-352h-224c-18 0 -32 -15 -32 -32c0 -8 3 -17 9 -23l352 -352c6 -6 14 -9 23 -9c8 0 17 3 23 9l351 351c6 7 10 15 10 24zM1920 384c0 -212 -172 -384 -384 -384h-1088
+c-247 0 -448 201 -448 448c0 174 101 332 258 405c-1 15 -2 29 -2 43c0 283 229 512 512 512c208 0 395 -126 474 -318c46 40 105 62 166 62c141 0 256 -115 256 -256c0 -49 -14 -97 -41 -138c174 -41 297 -196 297 -374z" />
+ <glyph glyph-name="trophy" unicode="&#xf091;" horiz-adv-x="1664"
+d="M458 653c-42 92 -74 214 -74 371h-256v-96c0 -98 133 -234 330 -275zM1536 928v96h-256c0 -157 -32 -279 -74 -371c197 41 330 177 330 275zM1664 1056v-128c0 -190 -230 -400 -542 -415c-40 -51 -77 -81 -95 -95c-53 -48 -67 -98 -67 -162s32 -128 128 -128
+s192 -64 192 -160v-64c0 -18 -14 -32 -32 -32h-832c-18 0 -32 14 -32 32v64c0 96 96 160 192 160s128 64 128 128s-14 114 -67 162c-18 14 -55 44 -95 95c-312 15 -542 225 -542 415v128c0 53 43 96 96 96h288v96c0 88 72 160 160 160h576c88 0 160 -72 160 -160v-96h288
+c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="caret-up" unicode="&#xf0d8;" horiz-adv-x="1024"
+d="M1024 320c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64c0 17 7 33 19 45l448 448c12 12 28 19 45 19s33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="magic" unicode="&#xf0d0;" horiz-adv-x="1637"
+d="M1163 955l293 293l-107 107l-293 -293zM1610 1248c0 -17 -6 -33 -18 -45l-1286 -1286c-12 -12 -28 -18 -45 -18s-33 6 -45 18l-198 198c-12 12 -18 28 -18 45s6 33 18 45l1286 1286c12 12 28 18 45 18s33 -6 45 -18l198 -198c12 -12 18 -28 18 -45zM259 1438l98 -30
+l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM609 1276l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1539 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM899 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+ <glyph glyph-name="hourglass-o" unicode="&#xf250;"
+d="M1408 1408c0 -370 -177 -638 -373 -768c196 -130 373 -398 373 -768h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96c0 370 177 638 373 768c-196 130 -373 398 -373 768h-96c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h1472c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96zM874 700c202 76 406 343 406 708h-1024c0 -365 204 -632 406 -708c25 -9 42 -33 42 -60s-17 -51 -42 -60c-202 -76 -406 -343 -406 -708h1024c0 365 -204 632 -406 708c-25 9 -42 33 -42 60
+s17 51 42 60z" />
+ <glyph glyph-name="balance-scale" unicode="&#xf24e;" horiz-adv-x="2176"
+d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280c-19 -54 -63 -98 -117 -117v-1291h608c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1344c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h608v1291c-54 19 -98 63 -117 117h-491c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h491c27 75 97 128 181 128s154 -53 181 -128h491c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-491zM1088 1264c44 0 80 36 80 80s-36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80zM2176 384c0 -206 -285 -288 -448 -288s-448 82 -448 288
+c0 39 349 657 392 735c11 20 33 33 56 33s45 -13 56 -33c43 -78 392 -696 392 -735zM896 384c0 -206 -285 -288 -448 -288s-448 82 -448 288c0 39 349 657 392 735c11 20 33 33 56 33s45 -13 56 -33c43 -78 392 -696 392 -735z" />
+ <glyph glyph-name="upload" unicode="&#xf093;" horiz-adv-x="1664"
+d="M1280 64c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1536 64c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1664 288v-320c0 -53 -43 -96 -96 -96h-1472c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h427c27 -74 98 -128 181 -128
+h256c83 0 154 54 181 128h427c53 0 96 -43 96 -96zM1339 936c-10 -24 -33 -40 -59 -40h-256v-448c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v448h-256c-26 0 -49 16 -59 40c-10 23 -5 51 14 69l448 448c12 13 29 19 45 19s33 -6 45 -19l448 -448
+c19 -18 24 -46 14 -69z" />
+ <glyph glyph-name="magnet" unicode="&#xf076;"
+d="M1536 704v-128c0 -408 -323 -704 -768 -704s-768 296 -768 704v128c0 35 29 64 64 64h384c35 0 64 -29 64 -64v-128c0 -183 213 -192 256 -192s256 9 256 192v128c0 35 29 64 64 64h384c35 0 64 -29 64 -64zM512 1344v-384c0 -35 -29 -64 -64 -64h-384
+c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h384c35 0 64 -29 64 -64zM1536 1344v-384c0 -35 -29 -64 -64 -64h-384c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h384c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="adjust" unicode="&#xf042;"
+d="M768 96v1088c-300 0 -544 -244 -544 -544s244 -544 544 -544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="subway" unicode="&#xf239;"
+d="M1088 1536c247 0 448 -143 448 -320v-896c0 -173 -191 -313 -431 -319l213 -202c21 -20 7 -55 -22 -55h-1056c-29 0 -43 35 -22 55l213 202c-240 6 -431 146 -431 319v896c0 177 201 320 448 320h640zM288 224c88 0 160 72 160 160s-72 160 -160 160s-160 -72 -160 -160
+s72 -160 160 -160zM704 768v512h-544v-512h544zM1248 224c88 0 160 72 160 160s-72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160zM1408 768v512h-576v-512h576z" />
+ <glyph glyph-name="unslpash" unicode="&#xf325;"
+d="M1052 728h484v-856h-1536v856h484v-428h568v428zM484 1408h568v-428h-568v428z" />
+ <glyph glyph-name="chevron-down" unicode="&#xf078;" horiz-adv-x="1612"
+d="M1593 728l-742 -741c-25 -25 -65 -25 -90 0l-742 741c-25 25 -25 66 0 91l166 165c25 25 65 25 90 0l531 -531l531 531c25 25 65 25 90 0l166 -165c25 -25 25 -66 0 -91z" />
+ <glyph glyph-name="location-arrow" unicode="&#xf124;" horiz-adv-x="1408"
+d="M1401 1187l-640 -1280c-11 -22 -33 -35 -57 -35c-5 0 -10 1 -15 2c-29 7 -49 32 -49 62v576h-576c-30 0 -55 20 -62 49s7 59 33 72l1280 640c9 5 19 7 29 7c17 0 33 -6 45 -19c20 -19 25 -49 12 -74z" />
+ <glyph glyph-name="check-circle" unicode="&#xf058;"
+d="M1284 802c0 17 -6 34 -18 46l-91 90c-12 12 -28 19 -45 19s-33 -7 -45 -19l-408 -407l-226 226c-12 12 -28 19 -45 19s-33 -7 -45 -19l-91 -90c-12 -12 -18 -29 -18 -46s6 -33 18 -45l362 -362c12 -12 29 -19 45 -19c17 0 34 7 46 19l543 543c12 12 18 28 18 45z
+M1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="arrow-down" unicode="&#xf063;" horiz-adv-x="1558"
+d="M1558 704c0 -34 -14 -67 -37 -90l-651 -652c-24 -23 -57 -37 -91 -37s-67 14 -90 37l-651 652c-24 23 -38 56 -38 90s14 67 38 91l74 75c24 23 57 37 91 37s67 -14 90 -37l294 -294v704c0 70 58 128 128 128h128c70 0 128 -58 128 -128v-704l294 294c23 23 56 37 90 37
+s67 -14 91 -37l75 -75c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="bicycle" unicode="&#xf206;" horiz-adv-x="2304"
+d="M762 384h-314c-53 0 -83 60 -51 102l188 251c-42 20 -88 31 -137 31c-176 0 -320 -144 -320 -320s144 -320 320 -320c155 0 284 110 314 256zM576 512h186c-12 56 -38 107 -75 148zM1056 512l288 384h-480l-99 -132c67 -66 112 -154 126 -252h165zM2176 448
+c0 176 -144 320 -320 320c-43 0 -83 -9 -121 -24l174 -260c20 -30 12 -70 -17 -89c-11 -8 -24 -11 -36 -11c-21 0 -41 10 -53 29l-174 260c-57 -58 -93 -137 -93 -225c0 -176 144 -320 320 -320s320 144 320 320zM2304 448c0 -247 -201 -448 -448 -448s-448 201 -448 448
+c0 132 58 251 149 333l-65 98l-353 -469c-12 -17 -31 -26 -51 -26h-197c-31 -217 -217 -384 -443 -384c-247 0 -448 201 -448 448s201 448 448 448c78 0 151 -20 215 -55l137 183h-224c-35 0 -64 29 -64 64s29 64 64 64h384v-128h435l-85 128h-222c-35 0 -64 29 -64 64
+s29 64 64 64h256c21 0 41 -11 53 -28l267 -400c58 28 123 44 192 44c247 0 448 -201 448 -448z" />
+ <glyph glyph-name="instagram" unicode="&#xf16d;"
+d="M1024 640c0 141 -115 256 -256 256s-256 -115 -256 -256s115 -256 256 -256s256 115 256 256zM1162 640c0 -218 -176 -394 -394 -394s-394 176 -394 394s176 394 394 394s394 -176 394 -394zM1270 1050c0 -51 -41 -92 -92 -92s-92 41 -92 92s41 92 92 92s92 -41 92 -92z
+M768 1270c-112 0 -352 9 -453 -31c-35 -14 -61 -31 -88 -58s-44 -53 -58 -88c-40 -101 -31 -341 -31 -453s-9 -352 31 -453c14 -35 31 -61 58 -88s53 -44 88 -58c101 -40 341 -31 453 -31s352 -9 453 31c35 14 61 31 88 58s44 53 58 88c40 101 31 341 31 453s9 352 -31 453
+c-14 35 -31 61 -58 88s-53 44 -88 58c-101 40 -341 31 -453 31zM1536 640c0 -106 1 -211 -5 -317c-6 -123 -34 -232 -124 -322s-199 -118 -322 -124c-106 -6 -211 -5 -317 -5s-211 -1 -317 5c-123 6 -232 34 -322 124s-118 199 -124 322c-6 106 -5 211 -5 317s-1 211 5 317
+c6 123 34 232 124 322s199 118 322 124c106 6 211 5 317 5s211 1 317 -5c123 -6 232 -34 322 -124s118 -199 124 -322c6 -106 5 -211 5 -317z" />
+ <glyph glyph-name="caret-square-o-up" unicode="&#xf151;"
+d="M1145 419c-11 -22 -33 -35 -57 -35h-640c-24 0 -46 13 -57 35c-11 21 -9 47 5 66l320 448c12 17 31 27 52 27s40 -10 52 -27l320 -448c14 -19 16 -45 5 -66zM1280 160v960c0 17 -15 32 -32 32h-960c-17 0 -32 -15 -32 -32v-960c0 -17 15 -32 32 -32h960c17 0 32 15 32 32
+zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="crop" unicode="&#xf125;" horiz-adv-x="1664"
+d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192c0 -18 -14 -32 -32 -32h-224v-224c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v224h-864c-18 0 -32 14 -32 32v864h-224c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h224v224c0 18 14 32 32 32h192
+c18 0 32 -14 32 -32v-224h851l246 247c13 12 33 12 46 0c12 -13 12 -33 0 -46l-247 -246v-851h224c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="external-link" unicode="&#xf08e;" horiz-adv-x="1792"
+d="M1408 608v-320c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h704c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-704c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160v320c0 18 14 32 32 32
+h64c18 0 32 -14 32 -32zM1792 1472v-512c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-176 176l-652 -652c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-114 114c-6 6 -10 15 -10 23s4 17 10 23l652 652l-176 176c-12 12 -19 28 -19 45c0 35 29 64 64 64h512c35 0 64 -29 64 -64z
+" />
+ <glyph glyph-name="arrow-circle-down" unicode="&#xf0ab;"
+d="M1284 639c0 17 -6 33 -18 45l-91 91c-12 12 -28 18 -45 18s-33 -6 -45 -18l-189 -189v502c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-502l-189 189c-12 12 -28 19 -45 19s-33 -7 -45 -19l-91 -91c-12 -12 -18 -28 -18 -45s6 -33 18 -45l362 -362l91 -91
+c12 -12 28 -18 45 -18s33 6 45 18l91 91l362 362c12 12 18 28 18 45zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="font-awesome" unicode="&#xf2b4;" horiz-adv-x="1499"
+d="M1499 1024v-839c0 -31 -20 -54 -49 -62c-107 -32 -227 -52 -338 -52c-150 0 -277 59 -443 59c-123 0 -250 -20 -370 -48v-338h-160v1368c-84 33 -139 115 -139 205c0 121 98 219 219 219s219 -98 219 -219c0 -90 -55 -172 -139 -205v-68c112 26 228 44 343 44
+c66 0 132 -5 198 -15c86 -13 173 -43 261 -43c55 0 111 7 165 18c41 8 135 40 169 40c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="paper-plane" unicode="&#xf1d8;" horiz-adv-x="1792"
+d="M1764 1525c21 -15 31 -39 27 -64l-256 -1536c-3 -19 -15 -35 -32 -45c-9 -5 -20 -8 -31 -8c-8 0 -16 2 -24 5l-453 185l-242 -295c-12 -15 -30 -23 -49 -23c-7 0 -15 1 -22 4c-25 9 -42 33 -42 60v349l864 1059l-1069 -925l-395 162c-23 9 -38 30 -40 55
+c-1 24 11 47 32 59l1664 960c10 6 21 9 32 9c13 0 26 -4 36 -11z" />
+ <glyph glyph-name="meanpath" unicode="&#xf20c;"
+d="M1311 694v-114c0 -32 -19 -52 -51 -52h-202c-32 0 -52 20 -52 52v114c0 32 20 52 52 52h202c32 0 51 -20 51 -52zM821 464v250c0 71 -47 118 -118 118h-133c-45 0 -78 -19 -96 -52c-18 33 -51 52 -96 52h-130c-70 0 -118 -47 -118 -118v-250c0 -15 7 -22 21 -22h55
+c15 0 22 7 22 22v230c0 32 19 52 52 52h94c32 0 52 -20 52 -52v-230c0 -15 6 -22 21 -22h54c15 0 22 7 22 22v230c0 32 20 52 52 52h97c32 0 51 -20 51 -52v-230c0 -15 7 -22 22 -22h55c14 0 21 7 21 22zM1410 560v154c0 71 -48 118 -119 118h-264c-71 0 -119 -47 -119 -118
+v-410c0 -15 8 -21 22 -21h55c15 0 21 6 21 21v180c19 -26 49 -42 94 -42h191c71 0 119 48 119 118zM1536 1176v-1072c0 -128 -104 -232 -232 -232h-1072c-128 0 -232 104 -232 232v1072c0 128 104 232 232 232h1072c128 0 232 -104 232 -232z" />
+ <glyph glyph-name="long-arrow-left" unicode="&#xf177;" horiz-adv-x="1728"
+d="M1728 736v-192c0 -18 -14 -32 -32 -32h-1248v-224c0 -13 -7 -24 -19 -29s-25 -3 -35 5l-384 350c-6 6 -10 14 -10 23s4 18 10 24l384 354c10 9 23 11 35 6c11 -5 19 -16 19 -29v-224h1248c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="download" unicode="&#xf019;" horiz-adv-x="1664"
+d="M1280 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1536 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1664 416v-320c0 -53 -43 -96 -96 -96h-1472c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h465l135 -136
+c37 -36 85 -56 136 -56s99 20 136 56l136 136h464c53 0 96 -43 96 -96zM1339 985c10 -24 5 -52 -14 -70l-448 -448c-12 -13 -29 -19 -45 -19s-33 6 -45 19l-448 448c-19 18 -24 46 -14 70c10 23 33 39 59 39h256v448c0 35 29 64 64 64h256c35 0 64 -29 64 -64v-448h256
+c26 0 49 -16 59 -39z" />
+ <glyph glyph-name="bold" unicode="&#xf032;" horiz-adv-x="1408"
+d="M555 15c44 -19 92 -32 140 -32c228 0 376 91 376 335c0 62 -8 127 -41 180c-93 150 -227 158 -388 158c-30 0 -73 0 -101 -10c0 -106 -1 -212 -1 -317c0 -69 -9 -256 15 -314zM541 761c36 -6 73 -7 109 -7c206 0 353 58 353 289c0 195 -173 262 -340 262
+c-44 0 -87 -6 -130 -13c0 -101 8 -202 8 -303c0 -53 -1 -106 -1 -159c0 -23 0 -46 1 -69zM0 -128l2 94c64 16 129 17 191 43c35 59 30 163 30 230c0 22 2 978 -22 1025c-15 29 -162 36 -195 40l-4 83c238 4 476 21 713 21c45 0 91 -1 136 -1c226 0 475 -108 475 -368
+c0 -179 -136 -246 -277 -310c190 -43 359 -172 359 -382c0 -344 -313 -458 -606 -458c-88 0 -176 6 -264 6c-179 0 -360 -16 -538 -23z" />
+ <glyph glyph-name="caret-down" unicode="&#xf0d7;" horiz-adv-x="1024"
+d="M1024 832c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-448 448c-12 12 -19 28 -19 45c0 35 29 64 64 64h896c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="chevron-left" unicode="&#xf053;" horiz-adv-x="1036"
+d="M1017 1235l-531 -531l531 -531c25 -25 25 -65 0 -90l-166 -166c-25 -25 -65 -25 -90 0l-742 742c-25 25 -25 65 0 90l742 742c25 25 65 25 90 0l166 -166c25 -25 25 -65 0 -90z" />
+ <glyph glyph-name="venus" unicode="&#xf221;" horiz-adv-x="1152"
+d="M1152 960c0 -296 -224 -540 -512 -572v-260h224c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-224v-224c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v224h-224c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v260c-303 33 -535 302 -510 619
+c22 272 238 495 508 525c348 39 642 -232 642 -572zM128 960c0 -247 201 -448 448 -448s448 201 448 448s-201 448 -448 448s-448 -201 -448 -448z" />
+ <glyph glyph-name="font" unicode="&#xf031;" horiz-adv-x="1664"
+d="M725 977l-170 -450c99 -1 198 -4 297 -4c19 0 38 1 57 2c-52 152 -113 307 -184 452zM0 -128l2 79c94 29 196 9 238 117l237 616l280 724h128c4 -7 8 -14 11 -21l205 -480c75 -177 144 -356 220 -532c45 -104 80 -211 130 -313c7 -16 21 -46 35 -57
+c33 -26 125 -32 172 -50c3 -19 6 -38 6 -57c0 -9 -1 -17 -1 -26c-127 0 -254 16 -381 16c-131 0 -262 -11 -393 -15c0 26 1 52 4 78l131 28c27 6 80 13 80 50c0 36 -129 333 -145 374l-450 2c-26 -58 -127 -320 -127 -358c0 -77 147 -80 204 -88c1 -19 1 -38 1 -58
+c0 -9 -1 -18 -2 -27c-116 0 -233 20 -349 20c-14 0 -34 -6 -48 -8c-63 -11 -125 -14 -188 -14z" />
+ <glyph glyph-name="pinterest" unicode="&#xf0d2;"
+d="M1536 640c0 -424 -344 -768 -768 -768c-76 0 -148 11 -218 32c29 46 62 105 78 164c0 0 9 34 54 211c26 -51 104 -96 187 -96c247 0 415 225 415 527c0 227 -193 440 -487 440c-364 0 -548 -262 -548 -480c0 -132 50 -250 157 -294c17 -7 33 0 38 20c4 13 12 47 16 61
+c5 20 3 26 -11 43c-31 37 -51 84 -51 151c0 194 145 368 378 368c206 0 320 -126 320 -295c0 -221 -98 -408 -244 -408c-80 0 -140 66 -121 148c23 97 68 202 68 272c0 63 -34 116 -104 116c-82 0 -148 -85 -148 -199c0 0 0 -73 25 -122c-84 -356 -99 -418 -99 -418
+c-14 -58 -15 -123 -13 -177c-271 119 -460 389 -460 704c0 424 344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="sun" unicode="&#xf329;" horiz-adv-x="1707"
+d="M1706 363c-3 -10 -11 -17 -20 -20l-292 -96v-306c0 -10 -5 -20 -13 -26c-9 -6 -19 -8 -29 -4l-292 94l-180 -248c-6 -8 -16 -13 -26 -13s-20 5 -26 13l-180 248l-292 -94c-10 -4 -20 -2 -29 4c-8 6 -13 16 -13 26v306l-292 96c-9 3 -17 10 -20 20s-2 21 4 29l180 248
+l-180 248c-6 9 -7 19 -4 29s11 17 20 20l292 96v306c0 10 5 20 13 26c9 6 19 8 29 4l292 -94l180 248c12 16 40 16 52 0l180 -248l292 94c10 4 20 2 29 -4c8 -6 13 -16 13 -26v-306l292 -96c9 -3 17 -10 20 -20s2 -20 -4 -29l-180 -248l180 -248c6 -8 7 -19 4 -29z" />
+ <glyph glyph-name="cart-plus" unicode="&#xf217;" horiz-adv-x="1664"
+d="M1216 832c0 35 -29 64 -64 64h-128v128c0 35 -29 64 -64 64s-64 -29 -64 -64v-128h-128c-35 0 -64 -29 -64 -64s29 -64 64 -64h128v-128c0 -35 29 -64 64 -64s64 29 64 64v128h128c35 0 64 29 64 64zM640 0c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128
+s128 -57 128 -128zM1536 0c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1664 1088v-512c0 -32 -24 -60 -57 -64l-1044 -122c4 -22 13 -47 13 -70s-14 -44 -24 -64h920c35 0 64 -29 64 -64s-29 -64 -64 -64h-1024c-35 0 -64 29 -64 64
+c0 31 47 108 61 137l-177 823h-204c-35 0 -64 29 -64 64s29 64 64 64h256c68 0 69 -80 79 -128h1201c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="folder-open-o" unicode="&#xf115;" horiz-adv-x="1909"
+d="M1781 605c0 28 -31 35 -53 35h-1088c-53 0 -123 -33 -157 -74l-294 -363c-9 -12 -18 -25 -18 -40c0 -28 31 -35 53 -35h1088c53 0 123 33 157 75l294 363c9 11 18 24 18 39zM640 768h768v160c0 53 -43 96 -96 96h-576c-53 0 -96 43 -96 96v64c0 53 -43 96 -96 96h-320
+c-53 0 -96 -43 -96 -96v-853l256 315c58 71 165 122 256 122zM1909 605c0 -44 -19 -86 -46 -120l-295 -363c-57 -70 -166 -122 -256 -122h-1088c-123 0 -224 101 -224 224v960c0 123 101 224 224 224h320c123 0 224 -101 224 -224v-32h544c123 0 224 -101 224 -224v-160h192
+c68 0 136 -31 166 -95c10 -21 15 -44 15 -68z" />
+ <glyph glyph-name="tachometer" unicode="&#xf0e4;" horiz-adv-x="1792"
+d="M384 384c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM576 832c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1004 351l101 382c8 34 -12 69 -46 78s-69 -12 -78 -46l-101 -382
+c-79 -6 -148 -61 -170 -142c-27 -103 35 -208 137 -235c103 -27 208 35 235 137c21 81 -13 163 -78 208zM1664 384c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1024 1024c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128
+s128 57 128 128zM1472 832c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1792 384c0 -172 -49 -338 -141 -483c-12 -18 -32 -29 -54 -29h-1402c-22 0 -42 11 -54 29c-92 144 -141 311 -141 483c0 494 402 896 896 896s896 -402 896 -896z
+" />
+ <glyph glyph-name="creative-commons" unicode="&#xf25e;" horiz-adv-x="1792"
+d="M605 303c-200 0 -344 142 -344 337c0 192 147 337 344 337c159 0 240 -92 243 -96c9 -11 10 -27 2 -39l-53 -78c-5 -8 -14 -13 -24 -14s-19 3 -26 10c0 0 -55 56 -138 56c-99 0 -170 -73 -170 -175c0 -103 73 -177 174 -177c92 0 155 67 156 67c7 8 17 12 27 11
+c10 -2 20 -8 24 -17l45 -82c7 -11 5 -26 -3 -36c-4 -4 -93 -104 -257 -104zM1235 303c-200 0 -344 142 -344 337c0 192 148 337 344 337c159 0 240 -92 243 -96c9 -11 10 -27 2 -39l-53 -78c-5 -8 -14 -13 -24 -14s-19 3 -26 10c0 0 -54 56 -138 56
+c-99 0 -170 -73 -170 -175c0 -103 73 -177 174 -177c92 0 155 67 156 67c7 8 17 12 27 11c11 -2 20 -8 25 -17l45 -82c6 -11 4 -26 -4 -36c-4 -4 -92 -104 -257 -104zM896 1376c-406 0 -736 -330 -736 -736s330 -736 736 -736s736 330 736 736s-330 736 -736 736zM896 1536
+c495 0 896 -401 896 -896s-401 -896 -896 -896s-896 401 -896 896s401 896 896 896z" />
+ <glyph glyph-name="clipboard" unicode="&#xf0ea;" horiz-adv-x="1792"
+d="M768 -128h896v640h-416c-53 0 -96 43 -96 96v416h-384v-1152zM1024 1312v64c0 17 -15 32 -32 32h-704c-17 0 -32 -15 -32 -32v-64c0 -17 15 -32 32 -32h704c17 0 32 15 32 32zM1280 640h299l-299 299v-299zM1792 512v-672c0 -53 -43 -96 -96 -96h-960
+c-53 0 -96 43 -96 96v160h-544c-53 0 -96 43 -96 96v1344c0 53 43 96 96 96h1088c53 0 96 -43 96 -96v-328c13 -8 25 -17 36 -28l408 -408c38 -38 68 -111 68 -164z" />
+ <glyph glyph-name="eercast" unicode="&#xf2da;" horiz-adv-x="1719"
+d="M1304 752c35 54 -6 191 -128 272c-121 81 -276 75 -312 21c-35 -53 40 -19 177 -70c226 -84 228 -277 263 -223zM1667 178c-283 -696 -1558 -520 -1531 383c3 115 35 192 68 302c-211 -864 966 -1367 1449 -685c18 25 23 23 14 0zM1428 627c0 -283 -228 -513 -509 -513
+s-509 230 -509 513s228 513 509 513s509 -230 509 -513zM1715 915c-356 808 -1826 510 -1663 -589c-338 1101 1055 1606 1570 822c42 -64 90 -176 93 -233zM1653 573c17 338 -217 569 -533 656c-5 0 -27 9 14 13c772 -26 800 -1260 -41 -1274c274 76 543 266 560 605z" />
+ <glyph glyph-name="bar-chart" unicode="&#xf080;" horiz-adv-x="2048"
+d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+ <glyph glyph-name="reply" unicode="&#xf112;" horiz-adv-x="1792"
+d="M1792 416c0 -140 -70 -323 -127 -451c-11 -23 -22 -55 -37 -76c-7 -10 -14 -17 -28 -17c-20 0 -32 16 -32 35c0 16 4 34 5 50c3 41 5 82 5 123c0 477 -283 560 -714 560h-224v-256c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-512 512c-12 12 -19 28 -19 45s7 33 19 45
+l512 512c12 12 28 19 45 19c35 0 64 -29 64 -64v-256h224c328 0 736 -58 875 -403c42 -106 53 -221 53 -333z" />
+ <glyph glyph-name="hourglass-half" unicode="&#xf252;"
+d="M1408 1408c0 -370 -177 -638 -373 -768c196 -130 373 -398 373 -768h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96c0 370 177 638 373 768c-196 130 -373 398 -373 768h-96c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h1472c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96zM1280 1408h-1024c0 -146 33 -275 85 -384h854c52 109 85 238 85 384zM1223 192c-74 193 -207 330 -340 384h-230c-133 -54 -266 -191 -340 -384h910z" />
+ <glyph glyph-name="microchip" unicode="&#xf2db;"
+d="M192 256v-128h-112c-9 0 -16 7 -16 16v16h-48c-9 0 -16 7 -16 16v32c0 9 7 16 16 16h48v16c0 9 7 16 16 16h112zM192 512v-128h-112c-9 0 -16 7 -16 16v16h-48c-9 0 -16 7 -16 16v32c0 9 7 16 16 16h48v16c0 9 7 16 16 16h112zM192 768v-128h-112c-9 0 -16 7 -16 16v16
+h-48c-9 0 -16 7 -16 16v32c0 9 7 16 16 16h48v16c0 9 7 16 16 16h112zM192 1024v-128h-112c-9 0 -16 7 -16 16v16h-48c-9 0 -16 7 -16 16v32c0 9 7 16 16 16h48v16c0 9 7 16 16 16h112zM192 1280v-128h-112c-9 0 -16 7 -16 16v16h-48c-9 0 -16 7 -16 16v32c0 9 7 16 16 16
+h48v16c0 9 7 16 16 16h112zM1280 1440v-1472c0 -53 -43 -96 -96 -96h-832c-53 0 -96 43 -96 96v1472c0 53 43 96 96 96h832c53 0 96 -43 96 -96zM1536 208v-32c0 -9 -7 -16 -16 -16h-48v-16c0 -9 -7 -16 -16 -16h-112v128h112c9 0 16 -7 16 -16v-16h48c9 0 16 -7 16 -16z
+M1536 464v-32c0 -9 -7 -16 -16 -16h-48v-16c0 -9 -7 -16 -16 -16h-112v128h112c9 0 16 -7 16 -16v-16h48c9 0 16 -7 16 -16zM1536 720v-32c0 -9 -7 -16 -16 -16h-48v-16c0 -9 -7 -16 -16 -16h-112v128h112c9 0 16 -7 16 -16v-16h48c9 0 16 -7 16 -16zM1536 976v-32
+c0 -9 -7 -16 -16 -16h-48v-16c0 -9 -7 -16 -16 -16h-112v128h112c9 0 16 -7 16 -16v-16h48c9 0 16 -7 16 -16zM1536 1232v-32c0 -9 -7 -16 -16 -16h-48v-16c0 -9 -7 -16 -16 -16h-112v128h112c9 0 16 -7 16 -16v-16h48c9 0 16 -7 16 -16z" />
+ <glyph glyph-name="graduation-cap" unicode="&#xf19d;" horiz-adv-x="2304"
+d="M1774 700l18 -316c8 -141 -287 -256 -640 -256s-648 115 -640 256l18 316l574 -181c16 -5 32 -7 48 -7s32 2 48 7zM2304 1024c0 -14 -9 -26 -22 -31l-1120 -352c-4 -1 -7 -1 -10 -1s-6 0 -10 1l-652 206c-57 -45 -97 -155 -105 -290c38 -22 63 -62 63 -109
+c0 -45 -23 -84 -58 -107l58 -433c1 -9 -2 -18 -8 -25s-15 -11 -24 -11h-192c-9 0 -18 4 -24 11s-9 16 -8 25l58 433c-35 23 -58 62 -58 107c0 48 27 89 65 111c6 117 36 243 98 330l-333 104c-13 5 -22 17 -22 31s9 26 22 31l1120 352c4 1 7 1 10 1s6 0 10 -1l1120 -352
+c13 -5 22 -17 22 -31z" />
+ <glyph glyph-name="info-circle" unicode="&#xf05a;"
+d="M1024 160v160c0 18 -14 32 -32 32h-96v512c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-160c0 -18 14 -32 32 -32h96v-320h-96c-18 0 -32 -14 -32 -32v-160c0 -18 14 -32 32 -32h448c18 0 32 14 32 32zM896 1056v160c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32
+v-160c0 -18 14 -32 32 -32h192c18 0 32 14 32 32zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="barcode" unicode="&#xf02a;" horiz-adv-x="2176"
+d="M0 1404h128v-1532h-128v1532zM2048 1408h128v-1536h-128v1536zM256 1408h128v-1280h-128v1280zM512 1408h256v-1280h-256v1280zM1280 1408h256v-1280h-256v1280zM1792 1408h128v-1280h-128v1280zM1024 1408h128v-1280h-128v1280zM256 0h128v-128h-128v128zM512 0h128
+v-128h-128v128zM768 0h128v-128h-128v128zM1024 0h128v-128h-128v128zM1280 0h128v-128h-128v128zM1536 0h128v-128h-128v128zM1792 0h128v-128h-128v128z" />
+ <glyph glyph-name="exchange" unicode="&#xf0ec;" horiz-adv-x="1792"
+d="M1792 352v-192c0 -17 -15 -32 -32 -32h-1376v-192c0 -17 -14 -32 -32 -32c-9 0 -17 4 -24 10l-319 320c-6 6 -9 14 -9 22c0 9 3 17 9 23l320 320c6 6 15 9 23 9c17 0 32 -14 32 -32v-192h1376c17 0 32 -14 32 -32zM1792 896c0 -8 -3 -17 -9 -23l-320 -320
+c-6 -6 -15 -9 -23 -9c-17 0 -32 15 -32 32v192h-1376c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1376v192c0 18 14 32 32 32c9 0 17 -4 24 -10l319 -319c6 -6 9 -15 9 -23z" />
+ <glyph glyph-name="hand-o-up" unicode="&#xf0a6;"
+d="M1280 -64c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1408 700c0 113 -46 189 -167 189c-19 0 -38 -2 -56 -5c-23 42 -80 65 -126 65c-24 0 -48 -6 -69 -18c-32 34 -72 53 -119 53c-32 0 -79 -14 -103 -35v331c0 69 -59 128 -128 128
+c-68 0 -128 -61 -128 -128v-576c-63 0 -128 96 -256 96c-96 0 -128 -75 -128 -160c0 -28 116 -79 139 -90c22 -12 44 -24 65 -37c53 -33 99 -71 145 -112c73 -64 163 -135 163 -241v-32h640v32c0 175 128 346 128 540zM1536 705c0 -112 -31 -218 -69 -322
+c-22 -61 -59 -160 -59 -223v-288c0 -71 -57 -128 -128 -128h-640c-71 0 -128 57 -128 128v288c0 48 -86 116 -119 145c-41 36 -82 70 -129 100c-93 58 -264 101 -264 235c0 159 87 288 256 288c44 0 87 -7 128 -22v374c0 138 117 256 255 256c140 0 257 -116 257 -256v-169
+c42 -3 82 -16 119 -37c14 2 29 3 43 3c64 0 128 -21 178 -60c189 2 300 -127 300 -312z" />
+ <glyph glyph-name="pause" unicode="&#xf04c;"
+d="M1536 1344v-1408c0 -35 -29 -64 -64 -64h-512c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h512c35 0 64 -29 64 -64zM640 1344v-1408c0 -35 -29 -64 -64 -64h-512c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h512c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="github-square" unicode="&#xf092;"
+d="M519 336c2 3 1 9 -3 13c-5 4 -11 5 -14 2c-2 -3 -1 -9 3 -13c5 -4 11 -5 14 -2zM491 377c-3 4 -8 6 -12 4c-3 -2 -3 -8 0 -12c4 -5 9 -7 12 -5s3 8 0 13zM450 417c1 2 -1 6 -5 8c-3 1 -7 1 -8 -2c-2 -3 0 -6 4 -8c4 -1 8 -1 9 2zM471 394c2 2 2 7 -2 10c-3 4 -8 5 -10 3
+c-3 -3 -2 -7 1 -11c3 -3 8 -5 11 -2zM557 319c1 4 -3 9 -9 11s-11 0 -13 -4c-1 -4 3 -9 9 -11s11 0 13 4zM599 316c0 4 -5 8 -12 8c-6 0 -10 -4 -10 -8s5 -8 11 -8s11 4 11 8zM638 323c-1 4 -7 6 -13 5s-10 -5 -9 -9s6 -7 12 -6s10 6 10 10zM1280 640
+c0 283 -229 512 -512 512s-512 -229 -512 -512c0 -226 147 -418 350 -486c26 -5 35 11 35 25c0 12 0 52 -1 95c0 0 -142 -31 -172 61c0 0 -23 59 -57 74c0 0 -46 32 4 32c0 0 50 -4 78 -53c45 -79 120 -56 149 -43c5 33 18 56 33 69c-114 13 -234 57 -234 253
+c0 56 20 101 53 137c-5 13 -23 65 5 136c43 13 141 -53 141 -53c41 12 84 17 128 17s87 -5 128 -17c0 0 98 66 141 53c28 -71 10 -123 5 -136c33 -36 53 -81 53 -137c0 -197 -120 -240 -234 -253c18 -16 35 -47 35 -95c0 -68 -1 -123 -1 -140c0 -14 9 -30 35 -25
+c203 68 350 260 350 486zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="search" unicode="&#xf002;" horiz-adv-x="1664"
+d="M1152 704c0 247 -201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448s448 201 448 448zM1664 -128c0 -70 -58 -128 -128 -128c-34 0 -67 14 -90 38l-343 342c-117 -81 -257 -124 -399 -124c-389 0 -704 315 -704 704s315 704 704 704s704 -315 704 -704
+c0 -142 -43 -282 -124 -399l343 -343c23 -23 37 -56 37 -90z" />
+ <glyph glyph-name="mixcloud" unicode="&#xf289;" horiz-adv-x="2304"
+d="M1645 438c0 80 -51 148 -121 175c-5 -31 -13 -62 -23 -92c-10 -32 -40 -52 -72 -52c-8 0 -16 1 -24 3c-41 14 -62 57 -49 97c15 46 23 94 23 143c0 250 -204 454 -455 454c-180 0 -342 -107 -414 -267c70 -18 135 -54 188 -106c30 -30 30 -79 0 -109s-79 -30 -109 0
+c-48 48 -112 75 -180 75c-141 0 -256 -114 -256 -255s115 -255 256 -255h1046c105 0 190 85 190 189zM1798 438c0 -189 -154 -342 -343 -342h-1046c-226 0 -409 183 -409 408c0 205 152 374 349 403c83 244 314 412 575 412c315 0 575 -241 605 -548
+c153 -33 269 -170 269 -333zM2048 438c0 -114 -33 -224 -97 -319c-15 -22 -39 -33 -64 -33c-15 0 -30 4 -43 13c-35 23 -44 71 -20 106c47 69 71 149 71 233c0 83 -24 164 -71 233c-24 35 -15 82 20 106s83 14 107 -21c64 -94 97 -204 97 -318zM2304 438
+c0 -159 -46 -312 -134 -443c-15 -22 -39 -34 -64 -34c-14 0 -29 4 -42 13c-35 24 -45 71 -21 106c70 106 108 230 108 358s-38 252 -108 357c-24 35 -14 83 21 106c35 24 82 15 106 -21c88 -130 134 -283 134 -442z" />
+ <glyph glyph-name="snowflake-o" unicode="&#xf2dc;" horiz-adv-x="1570"
+d="M1519 419l-167 -33l186 -107c30 -17 41 -57 23 -87s-57 -41 -87 -23l-186 106l55 -160c28 -80 -94 -121 -121 -42l-102 300l-271 156v-313l208 -238c56 -63 -41 -148 -96 -84l-112 128v-214c0 -35 -29 -64 -64 -64s-64 29 -64 64v214l-112 -128c-55 -64 -152 21 -96 84
+l208 238v313l-271 -156l-102 -300c-27 -79 -149 -38 -121 42l55 160l-186 -106c-30 -18 -69 -7 -87 23s-7 70 23 87l186 107l-167 33c-83 17 -58 142 25 126l310 -62l271 157l-271 157l-310 -62c-4 -1 -9 -1 -13 -1c-76 0 -87 112 -12 127l167 33l-186 107
+c-30 17 -41 57 -23 87c18 31 57 41 87 23l186 -106l-55 160c-28 80 94 121 121 42l102 -300l271 -156v313l-208 238c-56 63 41 148 96 84l112 -128v214c0 35 29 64 64 64s64 -29 64 -64v-214l112 128c55 64 152 -21 96 -84l-208 -238v-313l271 156l102 300
+c27 79 149 38 121 -42l-55 -160l186 106c30 18 69 7 87 -23s7 -70 -23 -87l-186 -107l167 -33c75 -15 64 -127 -12 -127c-4 0 -9 0 -13 1l-310 62l-271 -157l271 -157l310 62c83 16 108 -109 25 -126z" />
+ <glyph glyph-name="flask" unicode="&#xf0c3;" horiz-adv-x="1458"
+d="M1424 88c75 -119 22 -216 -119 -216h-1152c-141 0 -194 97 -119 216l503 793v399h-64c-35 0 -64 29 -64 64s29 64 64 64h512c35 0 64 -29 64 -64s-29 -64 -64 -64h-64v-399zM645 813l-272 -429h712l-272 429l-20 31v436h-128v-436z" />
+ <glyph glyph-name="pinterest-square" unicode="&#xf0d3;"
+d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-725c33 47 87 128 108 210c0 0 9 34 53 209c27 -51 104 -95 186 -95c244 0 410 223 410 521c0 225 -191 435 -481 435c-361 0 -543 -259 -543 -475c0 -130 50 -246 156 -290c17 -7 33 0 38 19
+c3 13 11 47 15 61c5 19 3 26 -11 42c-30 37 -50 83 -50 150c0 192 144 363 374 363c204 0 316 -124 316 -291c0 -219 -97 -404 -241 -404c-79 0 -139 66 -120 147c23 96 67 200 67 269c0 62 -33 114 -102 114c-81 0 -146 -84 -146 -196c0 0 0 -72 24 -121
+c-83 -352 -98 -414 -98 -414c-22 -92 -13 -199 -7 -254h-183c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960z" />
+ <glyph glyph-name="fast-backward" unicode="&#xf049;" horiz-adv-x="1792"
+d="M1747 1395c25 25 45 16 45 -19v-1472c0 -35 -20 -44 -45 -19l-710 710c-6 6 -10 12 -13 19v-710c0 -35 -20 -44 -45 -19l-710 710c-6 6 -10 12 -13 19v-678c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-678
+c3 7 7 13 13 19l710 710c25 25 45 16 45 -19v-710c3 7 7 13 13 19z" />
+ <glyph glyph-name="volume-control-phone" unicode="&#xf2a0;" horiz-adv-x="1408"
+d="M617 -153c0 -34 -90 -84 -119 -95c-15 -6 -30 -8 -45 -8c-33 0 -66 9 -98 18c-164 49 -203 149 -268 290c-70 151 -87 295 -87 460s17 309 87 460c65 141 104 241 268 290c32 9 65 18 98 18c15 0 30 -2 45 -8c29 -11 119 -61 119 -95c0 -24 -53 -194 -64 -234
+c-6 -25 -8 -66 -27 -84c-13 -12 -34 -14 -51 -14c-47 0 -94 11 -141 11c-14 0 -35 -1 -47 -11c-16 -13 -24 -58 -30 -78c-24 -83 -37 -168 -37 -255s13 -172 37 -255c6 -20 14 -65 30 -78c12 -10 33 -11 47 -11c47 0 94 11 141 11c17 0 38 -2 51 -14c19 -18 21 -59 27 -84
+c11 -40 64 -210 64 -234zM776 760c-17 0 -33 7 -45 19c-25 25 -26 66 0 91c24 24 37 56 37 90s-13 66 -37 91c-26 25 -25 65 0 90s65 25 90 0c48 -48 75 -113 75 -181s-27 -133 -75 -181c-13 -12 -29 -19 -45 -19zM957 579c-17 0 -33 6 -45 19c-25 25 -25 65 0 90
+c72 73 112 169 112 272s-40 199 -112 272c-25 25 -25 65 0 90s65 25 90 0c97 -97 150 -225 150 -362s-53 -265 -150 -362c-12 -13 -29 -19 -45 -19zM1138 398c-17 0 -33 6 -45 19c-25 25 -25 65 0 90c120 121 187 282 187 453s-67 332 -187 453c-25 25 -25 65 0 90
+s65 25 90 0c145 -145 225 -338 225 -543s-80 -398 -225 -543c-12 -13 -29 -19 -45 -19z" />
+ <glyph glyph-name="biometric" unicode="&#xf32b;" horiz-adv-x="2304"
+d="M1419 640c0 -147 -120 -267 -267 -267s-267 120 -267 267s120 267 267 267s267 -120 267 -267zM0 1222h2304v-521h-769c-29 185 -190 327 -383 327s-354 -142 -383 -327h-769v521zM0 579h769c29 -185 190 -327 383 -327s354 142 383 327h769v-521h-2304v521z" />
+ <glyph glyph-name="tasks" unicode="&#xf0ae;" horiz-adv-x="1792"
+d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 832v-256c0 -35 -29 -64 -64 -64h-1664
+c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 1344v-256c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h1664c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="firefox" unicode="&#xf269;" horiz-adv-x="1792"
+d="M903 -256c-386 0 -693 226 -834 549c-158 359 -32 934 249 1188l-11 -281c14 18 121 23 138 0c58 111 245 194 395 197c-57 -48 -189 -223 -178 -312c73 -23 185 -24 244 -28c18 -10 15 -71 -21 -121c0 0 -47 -65 -174 -88l15 -189l-139 67c-45 -114 63 -215 175 -196
+c124 21 168 102 255 97c86 -5 120 -53 109 -98c0 0 -14 -54 -107 -45c-79 -125 -184 -180 -354 -165c258 -214 606 -20 694 155c88 174 11 433 -77 506c104 -45 176 -91 214 -192c20 224 -83 478 -267 627c346 -101 557 -369 563 -797s-379 -874 -889 -874z" />
+ <glyph glyph-name="apple" unicode="&#xf179;" horiz-adv-x="1393"
+d="M1393 321c-25 -79 -65 -163 -123 -250c-86 -131 -172 -196 -257 -196c-34 0 -80 11 -140 32c-59 22 -110 32 -151 32c-40 0 -88 -11 -142 -33c-55 -23 -99 -34 -132 -34c-103 0 -202 87 -301 259c-97 172 -147 339 -147 503c0 153 38 277 113 374c75 96 169 144 284 144
+c49 0 107 -10 177 -30c69 -20 115 -30 138 -30c29 0 77 11 143 34c66 22 124 34 173 34c80 0 151 -22 213 -65c35 -24 70 -58 104 -100c-52 -44 -90 -83 -114 -118c-43 -62 -65 -131 -65 -207c0 -82 23 -157 69 -223s99 -108 158 -126zM1017 1494c0 -41 -10 -87 -29 -136
+c-20 -50 -51 -96 -93 -138c-36 -36 -72 -60 -108 -72c-23 -7 -57 -13 -104 -17c2 99 28 185 78 257s134 121 250 148c2 -9 4 -16 5 -22c0 -7 1 -13 1 -20z" />
+ <glyph glyph-name="gamepad" unicode="&#xf11b;" horiz-adv-x="1920"
+d="M832 448v128c0 18 -14 32 -32 32h-192v192c0 18 -14 32 -32 32h-128c-18 0 -32 -14 -32 -32v-192h-192c-18 0 -32 -14 -32 -32v-128c0 -18 14 -32 32 -32h192v-192c0 -18 14 -32 32 -32h128c18 0 32 14 32 32v192h192c18 0 32 14 32 32zM1408 384c0 71 -57 128 -128 128
+s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1664 640c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1920 512c0 -283 -229 -512 -512 -512c-130 0 -248 49 -338 128h-220c-90 -79 -208 -128 -338 -128c-283 0 -512 229 -512 512
+s229 512 512 512h896c283 0 512 -229 512 -512z" />
+ <glyph glyph-name="cc-stripe" unicode="&#xf1f5;" horiz-adv-x="2304"
+d="M1597 633c0 -46 -7 -81 -21 -106c-12 -22 -31 -35 -52 -35c-15 0 -29 3 -41 9v224c26 27 49 30 57 30c38 0 57 -42 57 -122zM2035 669h-110c4 67 22 98 56 98s52 -32 54 -98zM476 534c0 84 -51 119 -134 149c-44 16 -68 29 -68 49c0 17 14 26 38 26c46 0 92 -17 124 -33
+l18 112c-25 12 -77 32 -149 32c-51 0 -93 -13 -123 -38c-32 -26 -48 -64 -48 -109c0 -82 50 -118 132 -147c52 -19 70 -32 70 -53c0 -20 -17 -31 -48 -31c-38 0 -101 19 -142 43l-18 -113c35 -20 100 -41 168 -41c54 0 98 13 129 37c34 27 51 66 51 117zM771 749l19 111h-96
+v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219c0 -57 15 -96 44 -120c25 -20 61 -30 111 -30c39 0 62 7 79 11v118c-9 -2 -30 -7 -44 -7c-29 0 -42 16 -42 50v197h77zM1087 724v139c-10 2 -19 3 -28 3c-42 0 -76 -22 -89 -62l-10 56h-131v-471h150v306c19 23 46 31 82 31
+c8 0 16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638c0 80 -15 141 -45 179c-27 35 -64 52 -111 52c-43 0 -81 -18 -117 -56l-8 47h-132v-645l150 25v151c23 -7 47 -11 68 -11c37 0 92 10 134 56c41 44 61 112 61 202zM1278 986c0 44 -35 79 -79 79s-79 -35 -79 -79
+s35 -80 79 -80s79 36 79 80zM2176 629c0 75 -16 134 -48 176c-33 42 -82 64 -144 64c-128 0 -207 -94 -207 -246c0 -84 21 -148 63 -188c37 -37 91 -55 161 -55c64 0 123 15 160 40l-16 103c-37 -20 -80 -31 -128 -31c-29 0 -49 6 -63 19c-16 13 -25 35 -28 66h248
+c1 7 2 41 2 52zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h2048c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="quote-left" unicode="&#xf10d;" horiz-adv-x="1664"
+d="M768 576v-384c0 -106 -86 -192 -192 -192h-384c-106 0 -192 86 -192 192v704c0 282 230 512 512 512h64c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-64c-141 0 -256 -115 -256 -256v-32c0 -53 43 -96 96 -96h224c106 0 192 -86 192 -192zM1664 576v-384
+c0 -106 -86 -192 -192 -192h-384c-106 0 -192 86 -192 192v704c0 282 230 512 512 512h64c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-64c-141 0 -256 -115 -256 -256v-32c0 -53 43 -96 96 -96h224c106 0 192 -86 192 -192z" />
+ <glyph glyph-name="user-times" unicode="&#xf235;" horiz-adv-x="2039"
+d="M704 640c-212 0 -384 172 -384 384s172 384 384 384s384 -172 384 -384s-172 -384 -384 -384zM1781 320l249 -249c6 -6 9 -14 9 -23c0 -8 -3 -16 -9 -22l-136 -136c-6 -6 -14 -9 -22 -9c-9 0 -17 3 -23 9l-249 249l-249 -249c-6 -6 -14 -9 -23 -9c-8 0 -16 3 -22 9
+l-136 136c-6 6 -9 14 -9 22c0 9 3 17 9 23l249 249l-249 249c-6 6 -9 14 -9 23c0 8 3 16 9 22l136 136c6 6 14 9 22 9c9 0 17 -3 23 -9l249 -249l249 249c6 6 14 9 23 9c8 0 16 -3 22 -9l136 -136c6 -6 9 -14 9 -22c0 -9 -3 -17 -9 -23zM1283 320l-181 -181
+c-24 -24 -37 -57 -37 -91c0 -33 13 -66 37 -90l83 -83c-14 -2 -29 -3 -44 -3h-874c-160 0 -267 96 -267 259c0 226 53 573 346 573c16 0 27 -7 39 -17c96 -76 194 -122 319 -122s223 46 319 122c12 10 23 17 39 17c19 0 38 -2 57 -6c-33 -32 -54 -58 -54 -106
+c0 -34 13 -67 37 -91z" />
+ <glyph glyph-name="plus-square-o" unicode="&#xf196;" horiz-adv-x="1408"
+d="M1152 736v-64c0 -18 -14 -32 -32 -32h-352v-352c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v352h-352c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h352v352c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-352h352c18 0 32 -14 32 -32zM1280 288v832c0 88 -72 160 -160 160
+h-832c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160zM1408 1120v-832c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="eye-slash" unicode="&#xf070;" horiz-adv-x="1792"
+d="M555 201l78 141c-116 84 -185 219 -185 362c0 79 21 157 61 225c-156 -80 -286 -206 -381 -353c104 -161 251 -296 427 -375zM944 960c0 26 -22 48 -48 48c-167 0 -304 -137 -304 -304c0 -26 22 -48 48 -48s48 22 48 48c0 115 94 208 208 208c26 0 48 22 48 48z
+M1307 1151c0 -2 0 -7 -1 -9c-211 -377 -420 -756 -631 -1133l-49 -89c-6 -10 -17 -16 -28 -16c-18 0 -113 58 -134 70c-10 6 -16 16 -16 28c0 16 34 70 44 87c-194 88 -357 238 -472 418c-13 20 -20 44 -20 69c0 24 7 49 20 69c198 304 507 507 876 507c60 0 121 -6 180 -17
+l54 97c6 10 16 16 28 16c18 0 112 -58 133 -70c10 -6 16 -16 16 -27zM1344 704c0 -186 -115 -352 -288 -418l280 502c5 -28 8 -56 8 -84zM1792 576c0 -26 -7 -47 -20 -69c-31 -51 -70 -100 -109 -145c-196 -225 -466 -362 -767 -362l74 132c291 25 538 202 694 444
+c-74 115 -169 216 -282 294l63 112c124 -83 249 -208 327 -337c13 -22 20 -43 20 -69z" />
+ <glyph glyph-name="trello" unicode="&#xf181;"
+d="M704 192v1024c0 18 -14 32 -32 32h-480c-18 0 -32 -14 -32 -32v-1024c0 -18 14 -32 32 -32h480c18 0 32 14 32 32zM1376 576v640c0 18 -14 32 -32 32h-480c-18 0 -32 -14 -32 -32v-640c0 -18 14 -32 32 -32h480c18 0 32 14 32 32zM1536 1344v-1408c0 -35 -29 -64 -64 -64
+h-1408c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h1408c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="dribbble" unicode="&#xf17d;"
+d="M1024 36c-10 58 -48 258 -140 498c-1 0 -3 -1 -4 -1c0 0 -389 -136 -515 -410c-6 5 -15 11 -15 11c114 -93 259 -150 418 -150c91 0 177 19 256 52zM839 643c-16 37 -34 74 -53 111c-338 -101 -662 -93 -673 -93c-1 -7 -1 -14 -1 -21c0 -168 64 -322 168 -438
+c179 319 533 433 533 433c9 3 18 5 26 8zM732 855c-114 202 -235 366 -244 378c-183 -86 -319 -255 -362 -458c17 0 291 -3 606 80zM1416 536c-14 4 -197 62 -409 29c86 -237 121 -430 128 -469c147 99 251 257 281 440zM611 1277c-1 0 -1 0 -2 -1c0 0 1 1 2 1zM1201 1132
+c-115 102 -267 164 -433 164c-53 0 -105 -7 -155 -19c10 -13 134 -176 246 -382c247 92 340 234 342 237zM1424 647c-2 155 -57 298 -149 410c-2 -2 -107 -154 -366 -260c15 -31 30 -63 44 -95c5 -11 9 -23 14 -34c226 29 449 -20 457 -21zM1536 640
+c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="user-secret" unicode="&#xf21b;" horiz-adv-x="1408"
+d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010c-1 2 -2 4 -4 6c-9 7 -81 8 -96 8c-57 0 -111 -8 -167 -19c-7 -2 -14 -2 -21 -2s-14 0 -21 2c-56 11 -110 19 -167 19c-15 0 -87 -1 -96 -8c-2 -2 -3 -4 -4 -6c1 -9 2 -18 4 -27
+c6 -8 11 -5 15 -17c26 -71 38 -126 128 -126c129 0 93 119 135 119h12c42 0 6 -119 135 -119c90 0 102 55 128 126c4 12 9 9 15 17c2 9 3 18 4 27zM1408 131c0 -163 -107 -259 -267 -259h-874c-160 0 -267 96 -267 259c0 181 32 455 218 545l-90 220h214
+c-14 41 -22 84 -22 128c0 11 1 22 2 32c-39 8 -194 40 -194 96c0 59 170 91 210 99c21 75 71 189 122 248c20 23 45 37 76 37c60 0 108 -62 168 -62s108 62 168 62c31 0 56 -14 76 -37c51 -59 101 -173 122 -248c40 -8 210 -40 210 -99c0 -56 -155 -88 -194 -96
+c5 -54 -2 -108 -20 -160h214l-82 -225c179 -93 210 -362 210 -540z" />
+ <glyph glyph-name="cloud" unicode="&#xf0c2;" horiz-adv-x="1920"
+d="M1920 384c0 -212 -172 -384 -384 -384h-1088c-247 0 -448 201 -448 448c0 179 106 334 258 405c-1 14 -2 29 -2 43c0 283 229 512 512 512c214 0 397 -131 474 -318c44 39 102 62 166 62c141 0 256 -115 256 -256c0 -51 -15 -98 -41 -138c170 -40 297 -192 297 -374z" />
+ <glyph glyph-name="usd" unicode="&#xf155;" horiz-adv-x="932"
+d="M932 351c0 -204 -146 -365 -358 -400v-175c0 -18 -14 -32 -32 -32h-135c-17 0 -32 14 -32 32v175c-234 33 -362 173 -367 179c-10 12 -11 29 -2 41l103 135c5 7 14 11 23 12s18 -2 24 -9c2 -1 142 -135 319 -135c98 0 204 52 204 165c0 96 -118 143 -253 197
+c-180 71 -404 161 -404 412c0 184 144 336 353 376v180c0 18 15 32 32 32h135c18 0 32 -14 32 -32v-176c203 -23 311 -133 315 -137c10 -11 12 -26 5 -38l-81 -146c-5 -9 -13 -15 -23 -16c-10 -2 -19 1 -27 7c-1 1 -122 108 -272 108c-127 0 -215 -63 -215 -154
+c0 -106 122 -153 264 -208c184 -71 392 -152 392 -393z" />
+ <glyph glyph-name="eye" unicode="&#xf06e;" horiz-adv-x="1792"
+d="M1664 576c-95 147 -225 273 -381 353c40 -68 61 -146 61 -225c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 79 21 157 61 225c-156 -80 -286 -206 -381 -353c171 -264 447 -448 768 -448s597 184 768 448zM944 960c0 26 -22 48 -48 48c-167 0 -304 -137 -304 -304
+c0 -26 22 -48 48 -48s48 22 48 48c0 114 94 208 208 208c26 0 48 22 48 48zM1792 576c0 -25 -8 -48 -20 -69c-184 -303 -521 -507 -876 -507s-692 205 -876 507c-12 21 -20 44 -20 69s8 48 20 69c184 302 521 507 876 507s692 -205 876 -507c12 -21 20 -44 20 -69z" />
+ <glyph glyph-name="usb" unicode="&#xf287;" horiz-adv-x="2304"
+d="M2288 731c10 -5 16 -16 16 -27s-6 -22 -16 -27l-320 -192c-5 -3 -10 -5 -16 -5c-5 0 -11 1 -16 4c-10 6 -16 16 -16 28v128h-858c32 -50 59 -109 83 -165c48 -108 97 -219 167 -219h96v96c0 18 14 32 32 32h320c18 0 32 -14 32 -32v-320c0 -18 -14 -32 -32 -32h-320
+c-18 0 -32 14 -32 32v96h-96c-153 0 -222 157 -284 295c-47 107 -96 217 -164 217h-360c-29 -110 -129 -192 -248 -192c-141 0 -256 115 -256 256s115 256 256 256c119 0 219 -82 248 -192h104c68 0 117 110 164 217c62 138 131 295 284 295h107c27 75 97 128 181 128
+c106 0 192 -86 192 -192s-86 -192 -192 -192c-84 0 -154 53 -181 128h-107c-70 0 -119 -111 -167 -219c-24 -56 -51 -115 -83 -165h1114v128c0 12 6 22 16 28s23 5 32 -1z" />
+ <glyph glyph-name="certificate" unicode="&#xf0a3;"
+d="M1376 640l138 -135c19 -18 26 -45 20 -70c-7 -25 -27 -45 -52 -51l-188 -48l53 -186c7 -25 0 -52 -19 -70c-18 -19 -45 -26 -70 -19l-186 53l-48 -188c-6 -25 -26 -45 -51 -52c-6 -1 -13 -2 -19 -2c-19 0 -38 8 -51 22l-135 138l-135 -138c-18 -19 -45 -26 -70 -20
+c-26 7 -45 27 -51 52l-48 188l-186 -53c-25 -7 -52 0 -70 19c-19 18 -26 45 -19 70l53 186l-188 48c-25 6 -45 26 -52 51c-6 25 1 52 20 70l138 135l-138 135c-19 18 -26 45 -20 70c7 25 27 45 52 51l188 48l-53 186c-7 25 0 52 19 70c18 19 45 26 70 19l186 -53l48 188
+c6 25 26 45 51 51c25 7 52 0 70 -19l135 -139l135 139c18 19 44 26 70 19c25 -6 45 -26 51 -51l48 -188l186 53c25 7 52 0 70 -19c19 -18 26 -45 19 -70l-53 -186l188 -48c25 -6 45 -26 52 -51c6 -25 -1 -52 -20 -70z" />
+ <glyph glyph-name="500px" unicode="&#xf26e;" horiz-adv-x="1394"
+d="M1387 -11l-6 -6c-75 -75 -162 -134 -259 -175c-101 -42 -207 -64 -317 -64s-217 22 -317 64c-97 41 -185 100 -259 175c-75 74 -134 161 -175 258c-25 61 -45 124 -54 189c-4 28 35 34 48 36c31 5 52 3 56 -20c1 -1 1 -2 1 -4c4 -20 14 -80 46 -159
+c33 -82 84 -158 152 -226c65 -65 141 -116 226 -152c87 -37 180 -56 276 -56c95 0 188 19 276 56c84 36 160 87 225 152l6 6c7 7 15 9 25 6c9 -2 20 -10 33 -22c32 -33 25 -49 17 -58zM915 604l-66 -66l63 -63c7 -7 20 -22 -7 -49c-11 -11 -22 -17 -32 -17
+c-7 0 -13 3 -19 10l-62 61l-66 -66c-2 -2 -7 -5 -15 -5c-9 0 -20 5 -31 16l-2 2c-7 6 -18 17 -18 29c0 6 3 11 8 17l66 65l-66 66c-11 11 -6 25 14 45c12 12 22 18 31 18c5 0 9 -2 13 -5l65 -66l65 65c11 11 29 6 48 -13c12 -12 25 -29 11 -44zM1386 547
+c0 -79 -16 -156 -46 -228c-30 -70 -72 -132 -126 -186s-117 -96 -187 -126c-72 -31 -149 -46 -228 -46s-156 15 -228 46c-70 30 -133 72 -187 126s-96 116 -125 186c-6 13 -15 38 -15 40h-1c-9 28 31 40 43 44c29 9 51 13 60 -12c24 -64 61 -126 97 -167h1v341
+c2 84 37 169 102 232c67 66 157 103 253 103c196 0 355 -158 355 -352c0 -196 -160 -355 -355 -355c-39 0 -68 3 -112 16c-5 2 -28 12 -13 61c4 13 16 51 44 43c2 0 51 -12 77 -12c139 0 248 108 248 246c0 65 -26 126 -72 171c-46 46 -108 71 -175 71
+c-69 0 -132 -28 -178 -80c-40 -45 -64 -105 -64 -160v-413c72 -44 155 -67 242 -67c128 0 252 51 341 140c90 90 140 211 140 338c0 128 -50 248 -141 339c-90 90 -210 140 -339 140s-250 -50 -340 -140c-1 -1 -58 -60 -77 -87l-2 -2c-12 -17 -23 -33 -73 -22
+c-25 6 -52 21 -52 43v680c0 18 14 38 38 38h877c30 0 30 -42 30 -55c0 -14 0 -55 -30 -55h-811v-483h1c56 59 153 121 210 145c71 30 151 46 231 46c79 0 156 -15 228 -46c70 -30 133 -72 187 -126s96 -116 126 -186c30 -73 46 -149 46 -229zM1355 1128
+c19 -17 6 -35 -13 -57c-12 -12 -25 -26 -39 -26c-6 0 -11 2 -16 7c-72 62 -137 104 -207 133c-87 38 -180 56 -276 56c-85 0 -178 -17 -262 -49c-26 -10 -40 24 -45 37c-6 16 -9 29 -8 38c2 10 7 17 16 20c82 36 194 57 299 57c109 0 216 -22 316 -64
+c92 -39 167 -87 235 -152z" />
+ <glyph glyph-name="liberapay-square" unicode="&#xf2e8;" horiz-adv-x="1533"
+d="M148 1404h1236c82 0 149 -66 149 -148v-1236c0 -82 -67 -148 -149 -148h-1236c-82 0 -148 66 -148 148v1236c0 82 66 148 148 148zM736 1150v0l-161 -25l-133 -553c-8 -33 -12 -64 -12 -93s6 -54 18 -76s32 -40 60 -53s68 -19 117 -19l31 128c-18 1 -32 4 -42 9
+s-18 12 -22 20s-5 17 -5 27s1 23 4 35zM985 902v0c-42 0 -80 -3 -116 -10s-67 -14 -95 -22l-174 -722h155l47 189c24 -4 47 -6 71 -6c49 0 94 8 135 25s76 41 106 72s52 67 69 109s25 88 25 139c0 31 -4 61 -13 88s-22 51 -40 72c-18 20 -41 36 -69 48s-62 18 -101 18z
+M965 772v0c33 0 56 -11 69 -32s20 -46 20 -76c0 -31 -4 -59 -13 -84s-21 -47 -37 -65s-34 -32 -56 -42s-47 -15 -74 -15c-17 0 -32 1 -44 4l73 303c19 4 40 7 62 7z" />
+ <glyph glyph-name="foursquare" unicode="&#xf180;" horiz-adv-x="1192"
+d="M956 1102l37 194c7 32 -17 57 -44 57h-712c-32 0 -54 -29 -54 -54v-1101c0 -3 3 -4 6 -1c262 315 291 352 291 352c30 35 42 41 86 41h239c33 0 52 28 55 44s31 162 37 191s-21 59 -48 59h-294c-39 0 -67 28 -67 67v42c0 39 28 66 67 66h346c24 0 51 22 55 43zM1183 1324
+c-37 -180 -148 -749 -158 -790c-12 -47 -30 -129 -144 -129h-271c-11 0 -12 1 -22 -10c0 0 -7 -8 -426 -494c-33 -38 -87 -31 -107 -23s-55 32 -55 98v1410c0 58 36 150 158 150h888c130 0 165 -74 137 -212zM1183 1324l-158 -790c10 41 121 610 158 790z" />
+ <glyph glyph-name="music" unicode="&#xf001;"
+d="M1536 1312v-1120c0 -141 -211 -192 -320 -192s-320 51 -320 192s211 192 320 192c66 0 132 -12 192 -39v537l-768 -237v-709c0 -141 -211 -192 -320 -192s-320 51 -320 192s211 192 320 192c66 0 132 -12 192 -39v967c0 42 28 79 68 92l832 256c9 3 18 4 28 4
+c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="wpexplorer" unicode="&#xf2de;" horiz-adv-x="1792"
+d="M948 508l163 -329h-51l-175 350l-171 -350h-49l179 374l-78 33l21 49l240 -102l-21 -50zM563 1100l304 -130l-130 -304l-304 130zM907 915l240 -103l-103 -239l-239 102zM1188 765l191 -81l-82 -190l-190 81zM1680 640c0 432 -352 784 -784 784s-784 -352 -784 -784
+s352 -784 784 -784s784 352 784 784zM1792 640c0 -494 -402 -896 -896 -896s-896 402 -896 896s402 896 896 896s896 -402 896 -896z" />
+ <glyph glyph-name="gg-circle" unicode="&#xf261;" horiz-adv-x="1792"
+d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640c0 -495 -401 -896 -896 -896
+s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="sort" unicode="&#xf0dc;" horiz-adv-x="1024"
+d="M1024 448c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-448 448c-12 12 -19 28 -19 45c0 35 29 64 64 64h896c35 0 64 -29 64 -64zM1024 832c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64c0 17 7 33 19 45l448 448c12 12 28 19 45 19
+s33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="pencil" unicode="&#xf040;" horiz-adv-x="1515"
+d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928c0 13 -9 22 -22 22c-6 0 -12 -2 -17 -7l-542 -542c-5 -5 -7 -11 -7 -17c0 -13 9 -22 22 -22c6 0 12 2 17 7l542 542c5 5 7 11 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024c0 -34 -14 -67 -37 -90
+l-166 -166l-416 416l166 165c23 24 56 38 90 38s67 -14 91 -38l235 -234c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="bookmark-o" unicode="&#xf097;" horiz-adv-x="1280"
+d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408c15 0 30 -3 44 -9c44 -17 72 -58 72 -103v-1289c0 -45 -28 -86 -72 -103c-14 -6 -29 -8 -44 -8c-31 0 -60 11 -83 32l-441 424l-441 -424c-23 -21 -52 -33 -83 -33c-15 0 -30 3 -44 9
+c-44 17 -72 58 -72 103v1289c0 45 28 86 72 103c14 6 29 9 44 9h1048z" />
+ <glyph glyph-name="diamond" unicode="&#xf219;" horiz-adv-x="2048"
+d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512c19 -24 17 -59 -4 -82l-960 -1024c-12 -13 -29 -20 -47 -20
+s-35 7 -47 20l-960 1024c-21 23 -23 58 -4 82l384 512c12 17 31 26 51 26h1152c20 0 39 -9 51 -26z" />
+ <glyph glyph-name="share" unicode="&#xf064;" horiz-adv-x="1792"
+d="M1792 896c0 -17 -7 -33 -19 -45l-512 -512c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v256h-224c-431 0 -714 -83 -714 -560c0 -41 2 -82 5 -123c1 -16 5 -34 5 -50c0 -19 -12 -35 -32 -35c-14 0 -21 7 -28 17c-15 21 -26 53 -37 76c-57 128 -127 311 -127 451
+c0 112 11 227 53 333c139 345 547 403 875 403h224v256c0 35 29 64 64 64c17 0 33 -7 45 -19l512 -512c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="envelope" unicode="&#xf0e0;" horiz-adv-x="1792"
+d="M1792 826v-794c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v794c30 -33 64 -62 101 -87c166 -113 334 -226 497 -345c84 -62 188 -138 297 -138h2c109 0 213 76 297 138c163 118 331 232 498 345c36 25 70 54 100 87zM1792 1120c0 -112 -83 -213 -171 -274
+c-156 -108 -313 -216 -468 -325c-65 -45 -175 -137 -256 -137h-2c-81 0 -191 92 -256 137c-155 109 -312 217 -467 325c-71 48 -172 161 -172 252c0 98 53 182 160 182h1472c87 0 160 -72 160 -160z" />
+ <glyph glyph-name="yahoo" unicode="&#xf19e;" horiz-adv-x="1318"
+d="M750 579l13 -707c-34 6 -69 11 -105 11c-35 0 -70 -5 -105 -11l13 707c-186 321 -361 648 -566 957c35 -9 71 -15 108 -15s75 7 111 15c140 -248 292 -489 439 -733c148 242 305 483 439 733c35 -9 71 -14 107 -14c38 0 77 5 114 14c-80 -110 -146 -230 -215 -347
+c-119 -203 -236 -406 -353 -610z" />
+ <glyph glyph-name="window-restore" unicode="&#xf2d2;" horiz-adv-x="2048"
+d="M256 0h768v512h-768v-512zM1280 512h512v768h-768v-256h96c88 0 160 -72 160 -160v-352zM2048 1376v-960c0 -88 -72 -160 -160 -160h-608v-352c0 -88 -72 -160 -160 -160h-960c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h608v352c0 88 72 160 160 160h960
+c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="glass" unicode="&#xf000;" horiz-adv-x="1606"
+d="M1606 1350c0 -29 -23 -58 -43 -78l-632 -632v-768h320c35 0 64 -29 64 -64s-29 -64 -64 -64h-896c-35 0 -64 29 -64 64s29 64 64 64h320v768l-632 632c-20 20 -43 49 -43 78c0 49 62 58 99 58h1408c37 0 99 -9 99 -58z" />
+ <glyph glyph-name="flag" unicode="&#xf024;" horiz-adv-x="1728"
+d="M256 1280c0 -46 -25 -87 -64 -110v-1266c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v1266c-39 23 -64 64 -64 110c0 71 57 128 128 128s128 -57 128 -128zM1728 1216v-763c0 -37 -23 -51 -52 -66c-113 -61 -238 -116 -369 -116c-184 0 -272 140 -490 140
+c-159 0 -326 -72 -464 -146c-11 -6 -21 -9 -33 -9c-35 0 -64 29 -64 64v742c0 24 12 41 31 55c24 16 53 30 79 43c126 64 279 120 421 120c157 0 280 -52 419 -117c28 -14 57 -19 88 -19c157 0 326 136 370 136c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="train" unicode="&#xf238;"
+d="M1088 1536c247 0 448 -143 448 -320v-896c0 -173 -191 -313 -431 -319l213 -202c21 -20 7 -55 -22 -55h-1056c-29 0 -43 35 -22 55l213 202c-240 6 -431 146 -431 319v896c0 177 201 320 448 320h640zM768 192c106 0 192 86 192 192s-86 192 -192 192s-192 -86 -192 -192
+s86 -192 192 -192zM1344 768v512h-1152v-512h1152z" />
+ <glyph glyph-name="bullhorn" unicode="&#xf0a1;" horiz-adv-x="1792"
+d="M1664 896c71 0 128 -57 128 -128s-57 -128 -128 -128v-384c0 -70 -58 -128 -128 -128c-178 148 -465 351 -812 380c-119 -40 -160 -179 -82 -259c-70 -115 20 -196 126 -279c-62 -122 -320 -124 -412 -39c-58 178 -144 356 -74 581h-122c-88 0 -160 72 -160 160v192
+c0 88 72 160 160 160h480c384 0 704 224 896 384c70 0 128 -58 128 -128v-384zM1536 292v954c-261 -200 -514 -315 -768 -343v-270c254 -28 507 -141 768 -341z" />
+ <glyph glyph-name="pause-circle-o" unicode="&#xf28c;"
+d="M768 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM768 96c300 0 544 244 544 544s-244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544zM864 320c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-576
+c0 -18 -14 -32 -32 -32h-192zM480 320c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-576c0 -18 -14 -32 -32 -32h-192z" />
+ <glyph glyph-name="snapchat-ghost" unicode="&#xf2ac;" horiz-adv-x="1634"
+d="M833 1408c180 2 329 -99 404 -261c23 -49 27 -125 27 -179c0 -64 -5 -127 -9 -191c8 -4 19 -7 28 -7c36 0 66 27 102 27c34 0 83 -24 83 -64c0 -96 -201 -78 -201 -162c0 -15 6 -29 12 -43c48 -105 139 -206 247 -251c26 -11 52 -17 80 -23c18 -4 28 -17 28 -35
+c0 -68 -173 -96 -219 -103c-20 -31 -5 -104 -58 -104c-41 0 -82 13 -126 13c-21 0 -42 -1 -62 -5c-119 -20 -159 -148 -354 -148c-188 0 -233 128 -349 148c-21 4 -42 5 -63 5c-45 0 -88 -15 -124 -15c-56 0 -39 74 -60 106c-46 7 -219 35 -219 103c0 18 10 31 28 35
+c28 6 54 12 80 23c107 44 200 146 247 251c6 14 12 28 12 43c0 84 -202 68 -202 161c0 39 46 64 81 64c31 0 62 -26 101 -26c11 0 22 2 32 7c-4 63 -9 126 -9 190c0 54 4 131 27 180c88 190 237 259 436 261z" />
+ <glyph glyph-name="folder" unicode="&#xf07b;" horiz-adv-x="1664"
+d="M1664 928v-704c0 -123 -101 -224 -224 -224h-1216c-123 0 -224 101 -224 224v960c0 123 101 224 224 224h320c123 0 224 -101 224 -224v-32h672c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="outdent" unicode="&#xf03b;" horiz-adv-x="1792"
+d="M384 992v-576c0 -17 -15 -32 -32 -32c-8 0 -17 3 -23 9l-288 288c-6 6 -9 15 -9 23s3 17 9 23l288 288c6 6 15 9 23 9c17 0 32 -15 32 -32zM1792 224v-192c0 -17 -15 -32 -32 -32h-1728c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1728c17 0 32 -15 32 -32zM1792 608
+v-192c0 -17 -15 -32 -32 -32h-1088c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1088c17 0 32 -15 32 -32zM1792 992v-192c0 -17 -15 -32 -32 -32h-1088c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1088c17 0 32 -15 32 -32zM1792 1376v-192c0 -17 -15 -32 -32 -32h-1728
+c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1728c17 0 32 -15 32 -32z" />
+ <glyph glyph-name="stumbleupon" unicode="&#xf1a4;" horiz-adv-x="1920"
+d="M1062 824v118c0 56 -46 102 -102 102s-102 -46 -102 -102v-612c0 -234 -194 -423 -429 -423c-237 0 -429 192 -429 429v266h328v-262c0 -57 46 -102 102 -102s102 45 102 102v620c0 229 196 413 428 413c233 0 428 -185 428 -416v-136l-195 -58zM1592 602h328v-266
+c0 -237 -192 -429 -429 -429c-236 0 -429 190 -429 425v268l131 -61l195 58v-270c0 -56 46 -101 102 -101s102 45 102 101v275z" />
+ <glyph glyph-name="address-card" unicode="&#xf2bb;" horiz-adv-x="2048"
+d="M1024 405c0 155 -38 327 -196 327c-49 -28 -115 -76 -188 -76s-139 48 -188 76c-158 0 -196 -172 -196 -327c0 -87 57 -149 128 -149h512c71 0 128 62 128 149zM867 925c0 125 -102 227 -227 227s-227 -102 -227 -227c0 -126 102 -227 227 -227s227 101 227 227z
+M1792 416v64c0 18 -14 32 -32 32h-576c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h576c18 0 32 14 32 32zM1792 676v56c0 20 -16 36 -36 36h-568c-20 0 -36 -16 -36 -36v-56c0 -20 16 -36 36 -36h568c20 0 36 16 36 36zM1792 928v64c0 18 -14 32 -32 32h-576
+c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h576c18 0 32 14 32 32zM2048 1248v-1216c0 -88 -72 -160 -160 -160h-352v96c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-96h-768v96c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-96h-352c-88 0 -160 72 -160 160
+v1216c0 88 72 160 160 160h1728c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="i-cursor" unicode="&#xf246;" horiz-adv-x="896"
+d="M832 1408c-212 0 -320 -75 -320 -224v-416h128v-128h-128v-544c0 -149 108 -224 320 -224h64v-128h-64c-180 0 -312 52 -384 146c-72 -94 -204 -146 -384 -146h-64v128h64c212 0 320 75 320 224v544h-128v128h128v416c0 149 -108 224 -320 224h-64v128h64
+c180 0 312 -52 384 -146c72 94 204 146 384 146h64v-128h-64z" />
+ <glyph glyph-name="car" unicode="&#xf1b9;" horiz-adv-x="2048"
+d="M480 448c0 88 -72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160s160 72 160 160zM516 768h1016l-89 357c-3 11 -23 27 -35 27h-768c-12 0 -32 -16 -35 -27zM1888 448c0 88 -72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160s160 72 160 160zM2048 544v-384
+c0 -18 -14 -32 -32 -32h-96v-128c0 -106 -86 -192 -192 -192s-192 86 -192 192v128h-1024v-128c0 -106 -86 -192 -192 -192s-192 86 -192 192v128h-96c-18 0 -32 14 -32 32v384c0 124 100 224 224 224h28l105 419c31 126 153 221 283 221h768c130 0 252 -95 283 -221
+l105 -419h28c124 0 224 -100 224 -224z" />
+ <glyph glyph-name="file-excel-o" unicode="&#xf1c3;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM429 106h68l194 283l-189 272h-68v107h290v-107h-76l106 -159c8 -9 13 -16 17 -23c2 -3 4 -6 5 -10h2c0 -1 9 14 21 33l103 159h-74v107h279v-107h-67l-195 -282l192 -273h68v-106h-291v106h76l-107 161c-7 10 -13 16 -17 24c-2 3 -4 6 -5 10h-2
+c-3 0 -9 -15 -21 -34l-103 -161h75v-106h-281v106z" />
+ <glyph glyph-name="arrow-circle-o-left" unicode="&#xf190;"
+d="M1152 736v-192c0 -17 -15 -32 -32 -32h-352v-192c0 -18 -14 -32 -32 -32c-9 0 -17 4 -24 10l-319 319c-6 6 -9 15 -9 23s3 17 9 23l320 320c6 6 15 9 23 9c17 0 32 -15 32 -32v-192h352c17 0 32 -15 32 -32zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544
+s244 -544 544 -544s544 244 544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="paragraph" unicode="&#xf1dd;" horiz-adv-x="1254"
+d="M1254 1347v-73c0 -34 -27 -93 -61 -93c-17 0 -37 3 -54 -1c-16 -4 -28 -15 -32 -31c-5 -19 -3 -43 -3 -64v-1152c0 -34 -27 -61 -61 -61h-108c-34 0 -61 27 -61 61v1218h-143v-1218c0 -34 -27 -61 -61 -61h-108c-34 0 -61 27 -61 61v496c-97 8 -180 28 -245 59
+c-84 39 -148 99 -192 179c-42 77 -64 164 -64 259c0 111 30 207 88 286c59 79 129 132 209 159c75 25 233 37 417 37h479c34 0 61 -27 61 -61z" />
+ <glyph glyph-name="y-combinator" unicode="&#xf23b;"
+d="M809 532l266 499h-112l-157 -312s-24 -48 -44 -92c-19 46 -42 92 -42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+ <glyph glyph-name="male" unicode="&#xf183;" horiz-adv-x="1024"
+d="M1024 832v-416c0 -53 -43 -96 -96 -96s-96 43 -96 96v352h-64v-912c0 -62 -50 -112 -112 -112s-112 50 -112 112v464h-64v-464c0 -62 -50 -112 -112 -112s-112 50 -112 112v912h-64v-352c0 -53 -43 -96 -96 -96s-96 43 -96 96v416c0 106 86 192 192 192h640
+c106 0 192 -86 192 -192zM736 1280c0 -124 -100 -224 -224 -224s-224 100 -224 224s100 224 224 224s224 -100 224 -224z" />
+ <glyph glyph-name="history" unicode="&#xf1da;"
+d="M1536 640c0 -423 -345 -768 -768 -768c-229 0 -445 101 -591 277c-10 13 -9 32 2 43l137 138c7 6 16 9 25 9c9 -1 18 -5 23 -12c98 -127 245 -199 404 -199c282 0 512 230 512 512s-230 512 -512 512c-131 0 -255 -50 -348 -137l137 -138c19 -18 24 -46 14 -69
+c-10 -24 -33 -40 -59 -40h-448c-35 0 -64 29 -64 64v448c0 26 16 49 40 59c23 10 51 5 69 -14l130 -129c141 133 332 212 529 212c423 0 768 -345 768 -768zM896 928v-448c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v352c0 18 14 32 32 32h64
+c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="h-square" unicode="&#xf0fd;"
+d="M1280 192v896c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-320h-512v320c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-896c0 -35 29 -64 64 -64h128c35 0 64 29 64 64v320h512v-320c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="heart" unicode="&#xf004;" horiz-adv-x="1792"
+d="M896 -128c-16 0 -32 6 -44 18l-624 602c-8 7 -228 208 -228 448c0 293 179 468 478 468c175 0 339 -138 418 -216c79 78 243 216 418 216c299 0 478 -175 478 -468c0 -240 -220 -441 -229 -450l-623 -600c-12 -12 -28 -18 -44 -18z" />
+ <glyph glyph-name="sort-amount-desc" unicode="&#xf161;" horiz-adv-x="1760"
+d="M1184 -32v-192c0 -18 -14 -32 -32 -32h-256c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h256c18 0 32 -14 32 -32zM704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192
+c18 0 32 -14 32 -32v-1376h192c18 0 32 -14 32 -32zM1376 480v-192c0 -18 -14 -32 -32 -32h-448c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h448c18 0 32 -14 32 -32zM1568 992v-192c0 -18 -14 -32 -32 -32h-640c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h640
+c18 0 32 -14 32 -32zM1760 1504v-192c0 -18 -14 -32 -32 -32h-832c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h832c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="search-plus" unicode="&#xf00e;" horiz-adv-x="1664"
+d="M1024 736v-64c0 -17 -15 -32 -32 -32h-224v-224c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v224h-224c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h224v224c0 17 15 32 32 32h64c17 0 32 -15 32 -32v-224h224c17 0 32 -15 32 -32zM1152 704c0 247 -201 448 -448 448
+s-448 -201 -448 -448s201 -448 448 -448s448 201 448 448zM1664 -128c0 -71 -57 -128 -128 -128c-34 0 -67 14 -90 38l-343 342c-117 -81 -257 -124 -399 -124c-389 0 -704 315 -704 704s315 704 704 704s704 -315 704 -704c0 -142 -43 -282 -124 -399l343 -343
+c23 -23 37 -56 37 -90z" />
+ <glyph glyph-name="life-ring" unicode="&#xf1cd;" horiz-adv-x="1792"
+d="M896 1536c495 0 896 -401 896 -896s-401 -896 -896 -896s-896 401 -896 896s401 896 896 896zM896 1408c-130 0 -253 -33 -361 -90l194 -194c53 18 109 28 167 28c59 0 114 -10 167 -28l194 194c-108 57 -231 90 -361 90zM218 279l194 194c-18 53 -28 109 -28 167
+c0 59 10 114 28 167l-194 194c-57 -108 -90 -231 -90 -361s33 -253 90 -361zM896 -128c130 0 253 33 361 90l-194 194c-53 -18 -108 -28 -167 -28c-58 0 -114 10 -167 28l-194 -194c108 -57 231 -90 361 -90zM896 256c212 0 384 172 384 384s-172 384 -384 384
+s-384 -172 -384 -384s172 -384 384 -384zM1380 473l194 -194c57 108 90 231 90 361s-33 253 -90 361l-194 -194c18 -53 28 -109 28 -167s-10 -114 -28 -167z" />
+ <glyph glyph-name="lock" unicode="&#xf023;" horiz-adv-x="1152"
+d="M320 768h512v192c0 141 -115 256 -256 256s-256 -115 -256 -256v-192zM1152 672v-576c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v576c0 53 43 96 96 96h32v192c0 246 202 448 448 448s448 -202 448 -448v-192h32c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="git-square" unicode="&#xf1d2;"
+d="M582 228c0 -54 -49 -66 -93 -66c-43 0 -107 7 -107 63c0 55 54 64 98 64c42 0 102 -7 102 -61zM546 694c0 -50 -20 -85 -74 -85c-55 0 -77 32 -77 84s20 90 77 90c51 0 74 -42 74 -89zM712 769v125c-43 -16 -89 -29 -135 -29c-33 19 -71 29 -110 29
+c-114 0 -204 -84 -204 -200c0 -62 41 -148 103 -169v-3c-32 -14 -38 -53 -38 -85c0 -33 12 -60 41 -77v-3c-68 -22 -113 -65 -113 -139c0 -127 121 -163 227 -163c128 0 224 47 224 188c0 100 -91 130 -174 145c-28 5 -76 25 -76 60c0 33 18 47 49 52c102 20 167 99 167 204
+c0 18 -4 35 -10 52c16 4 33 8 49 13zM771 350h137c-2 27 -2 55 -2 82v387c0 23 0 46 2 69h-137c3 -23 3 -48 3 -71v-392c0 -25 0 -50 -3 -75zM1280 366v121c-20 -14 -44 -21 -68 -21c-45 0 -53 45 -53 82v225h52c18 0 35 -2 53 -2v117h-105c0 34 -2 68 3 102h-140
+c3 -18 4 -36 4 -55v-47h-60v-117c12 1 24 3 37 3c7 0 15 -1 23 -1v-2h-2v-217c0 -108 16 -212 148 -212c37 0 75 6 108 24zM924 1072c0 47 -35 91 -84 91s-85 -43 -85 -91c0 -47 37 -89 85 -89s84 43 84 89zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960
+c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="mouse-pointer" unicode="&#xf245;" horiz-adv-x="1152"
+d="M1133 493c19 -18 24 -46 14 -69c-10 -24 -33 -40 -59 -40h-382l201 -476c14 -33 -2 -70 -34 -84l-177 -75c-33 -14 -70 2 -84 34l-191 452l-312 -312c-12 -12 -28 -19 -45 -19c-8 0 -17 2 -24 5c-24 10 -40 33 -40 59v1504c0 26 16 49 40 59c7 3 16 5 24 5
+c17 0 33 -6 45 -19z" />
+ <glyph glyph-name="sign-in" unicode="&#xf090;"
+d="M1184 640c0 -17 -7 -33 -19 -45l-544 -544c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v288h-448c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h448v288c0 35 29 64 64 64c17 0 33 -7 45 -19l544 -544c12 -12 19 -28 19 -45zM1536 992v-704c0 -159 -129 -288 -288 -288
+h-320c-17 0 -32 15 -32 32c0 28 -13 96 32 96h320c88 0 160 72 160 160v704c0 88 -72 160 -160 160h-288c-25 0 -64 -5 -64 32c0 28 -13 96 32 96h320c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="odnoklassniki-square" unicode="&#xf264;"
+d="M927 956c0 -88 -71 -159 -159 -159s-159 71 -159 159s71 159 159 159s159 -71 159 -159zM1141 593c-18 36 -69 67 -136 14c0 0 -91 -72 -237 -72s-237 72 -237 72c-67 53 -118 22 -136 -14c-32 -64 4 -95 85 -148c69 -44 165 -61 226 -67l-51 -52
+c-72 -72 -142 -142 -191 -190c-29 -29 -29 -76 0 -105l9 -9c29 -29 76 -29 105 0l191 191c72 -73 142 -143 191 -191c29 -29 76 -29 105 0l9 9c29 29 29 76 0 105l-191 190l-52 52c62 6 156 23 225 67c81 53 117 84 85 148zM1092 956c0 179 -145 324 -324 324
+s-324 -145 -324 -324s145 -324 324 -324s324 145 324 324zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="tag" unicode="&#xf02b;" horiz-adv-x="1515"
+d="M448 1088c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1515 512c0 -34 -14 -67 -37 -90l-491 -492c-24 -23 -57 -37 -91 -37s-67 14 -90 37l-715 716c-51 50 -91 147 -91 218v416c0 70 58 128 128 128h416c71 0 168 -40 219 -91
+l715 -714c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="align-justify" unicode="&#xf039;" horiz-adv-x="1792"
+d="M1792 192v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 576v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 960v-128
+c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 1344v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="hospital-o" unicode="&#xf0f8;" horiz-adv-x="1408"
+d="M384 224v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 480v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 480v-64c0 -17 -15 -32 -32 -32h-64
+c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 224v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64
+c17 0 32 -15 32 -32zM896 480v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 480v-64
+c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64
+c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 -128h384v1152h-256v-32c0 -53 -43 -96 -96 -96h-448c-53 0 -96 43 -96 96v32h-256v-1152h384v224c0 17 15 32 32 32h320c17 0 32 -15 32 -32v-224zM896 1056v320c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-96h-128v96
+c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-320c0 -17 15 -32 32 -32h64c17 0 32 15 32 32v96h128v-96c0 -17 15 -32 32 -32h64c17 0 32 15 32 32zM1408 1088v-1280c0 -35 -29 -64 -64 -64h-1280c-35 0 -64 29 -64 64v1280c0 35 29 64 64 64h320v288c0 53 43 96 96 96
+h448c53 0 96 -43 96 -96v-288h320c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="chevron-circle-down" unicode="&#xf13a;"
+d="M813 237l454 454c25 25 25 65 0 90l-102 102c-25 25 -65 25 -90 0l-307 -307l-307 307c-25 25 -65 25 -90 0l-102 -102c-25 -25 -25 -65 0 -90l454 -454c25 -25 65 -25 90 0zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z
+" />
+ <glyph glyph-name="filter" unicode="&#xf0b0;" horiz-adv-x="1408"
+d="M1403 1241c10 -24 5 -52 -14 -70l-493 -493v-742c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 6 -45 19l-256 256c-12 12 -19 28 -19 45v486l-493 493c-19 18 -24 46 -14 70c10 23 33 39 59 39h1280c26 0 49 -16 59 -39z" />
+ <glyph glyph-name="google-plus" unicode="&#xf0d5;" horiz-adv-x="2304"
+d="M1437 623c0 -419 -281 -716 -704 -716c-405 0 -733 328 -733 733s328 733 733 733c198 0 363 -72 491 -192l-199 -191c-54 52 -149 113 -292 113c-250 0 -454 -207 -454 -463s204 -463 454 -463c290 0 399 209 416 316h-416v252h692c7 -37 12 -74 12 -122zM2304 745v-210
+h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
+ <glyph glyph-name="sticky-note-o" unicode="&#xf24a;"
+d="M1400 256h-248v-248c17 6 34 15 41 22l185 185c7 7 16 24 22 41zM1120 384h288v896h-1280v-1280h896v288c0 53 43 96 96 96zM1536 1312v-1024c0 -53 -31 -127 -68 -164l-184 -184c-37 -37 -111 -68 -164 -68h-1024c-53 0 -96 43 -96 96v1344c0 53 43 96 96 96h1344
+c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="fonticons" unicode="&#xf280;"
+d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925c41 0 57 -15 56 -79l174 21c0 153 -105 181 -222 181c-174 0 -265 -70 -265 -240v-72h-96v-128h76
+c10 0 20 0 20 -8v-382c0 -19 -5 -25 -23 -27l-73 -7v-88h448v86l-149 14c-18 2 -11 5 -11 25v387h191l38 128h-231c-10 0 2 7 2 15v80c0 60 2 94 65 94zM1248 96v86l-54 9c-19 3 -10 5 -10 25v520h-275l-23 -101l83 -22c13 -4 23 -13 23 -27v-370c0 -19 -8 -23 -26 -25
+l-70 -9v-86h352z" />
+ <glyph glyph-name="comments-o" unicode="&#xf0e6;" horiz-adv-x="1792"
+d="M704 1152c-312 0 -576 -176 -576 -384c0 -110 74 -216 202 -290l97 -56l-35 -84c21 12 42 25 62 39l44 31l53 -10c50 -9 101 -14 153 -14c312 0 576 176 576 384s-264 384 -576 384zM704 1280c389 0 704 -229 704 -512s-315 -512 -704 -512c-61 0 -120 6 -176 16
+c-83 -59 -177 -102 -278 -128c-27 -7 -56 -12 -86 -16h-3c-15 0 -29 12 -32 29c-4 19 9 31 20 44c39 44 83 83 117 166c-162 94 -266 239 -266 401c0 283 315 512 704 512zM1526 111c34 -83 78 -122 117 -166c11 -13 24 -25 20 -44c-4 -18 -19 -31 -35 -29
+c-30 4 -59 9 -86 16c-101 26 -195 69 -278 128c-56 -10 -115 -16 -176 -16c-181 0 -347 50 -472 132c29 -2 59 -4 88 -4c215 0 418 62 573 174c167 122 259 287 259 466c0 52 -8 103 -23 152c169 -93 279 -241 279 -408c0 -163 -104 -307 -266 -401z" />
+ <glyph glyph-name="lastfm" unicode="&#xf202;" horiz-adv-x="1792"
+d="M1292 832c0 -6 8 -34 10 -41c27 -82 90 -99 165 -120c167 -47 325 -136 325 -332c0 -199 -166 -339 -360 -339c-322 0 -422 394 -515 634c-77 198 -158 314 -381 314c-198 0 -372 -190 -372 -385c0 -207 155 -399 370 -399c95 0 194 20 258 95c31 35 61 73 83 116
+l84 -152c-11 -25 -27 -49 -44 -70l1 -1c-101 -117 -239 -152 -388 -152c-302 0 -528 267 -528 561c0 285 248 550 536 550c478 0 502 -414 664 -747c44 -92 119 -200 233 -200c104 0 196 67 196 177c0 238 -437 76 -499 467c-2 11 -3 22 -3 33c0 148 139 275 286 270
+c88 -3 141 -6 211 -68h-1c27 -25 47 -59 68 -88l-129 -99c-15 28 -29 51 -54 70v1c-24 22 -67 21 -97 21c-65 0 -119 -49 -119 -116z" />
+ <glyph glyph-name="peertube" unicode="&#xf2e4;" horiz-adv-x="1350"
+d="M0 1536l675 -450l-675 -450v900zM675 1086l675 -450l-675 -450v900zM0 636l675 -450l-675 -450v900z" />
+ <glyph glyph-name="pagelines" unicode="&#xf18c;" horiz-adv-x="1402"
+d="M1402 433c-201 -499 -683 -197 -683 -197c-148 -299 -392 -491 -674 -492c-25 0 -45 20 -45 45s20 44 45 44c235 1 440 156 574 402c-150 -58 -433 -102 -590 300c398 164 581 -41 651 -166c36 89 62 186 79 291c0 0 -510 -80 -546 358c435 175 557 -280 557 -280
+c6 61 12 192 12 195c0 0 -388 269 -139 603c455 -157 224 -593 224 -593c2 -6 2 -87 0 -122c0 0 165 325 498 210c-15 -489 -518 -388 -518 -388c-16 -100 -41 -195 -73 -283c0 0 303 335 628 73z" />
+ <glyph glyph-name="credit-card-alt" unicode="&#xf283;" horiz-adv-x="2304"
+d="M0 32v608h2304v-608c0 -88 -72 -160 -160 -160h-1984c-88 0 -160 72 -160 160zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408c88 0 160 -72 160 -160v-224h-2304v224c0 88 72 160 160 160h1984z" />
+ <glyph glyph-name="file-word-o" unicode="&#xf1c2;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM233 768h300v-107h-90l99 -438c4 -16 6 -33 7 -46l2 -21h4l4 21c3 13 4 30 8 46l144 545h114l144 -545c4 -16 6 -33 9 -46c1 -7 3 -15 3 -21h4l2 21c1 13 3 30 7 46l99 438h-90v107h300v-107h-70l-164 -661h-159l-128 485c-5 16 -6 32 -9 46l-3 24h-4
+c0 -8 -1 -16 -2 -24c-2 -16 -5 -31 -10 -46l-128 -485h-159l-164 661h-70v107z" />
+ <glyph glyph-name="map" unicode="&#xf279;" horiz-adv-x="1792"
+d="M512 1536c17 0 32 -15 32 -32v-1472c0 -12 -7 -23 -17 -28l-480 -256c-5 -3 -10 -4 -15 -4c-17 0 -32 15 -32 32v1472c0 12 7 23 17 28l480 256c5 3 10 4 15 4zM1760 1536c17 0 32 -15 32 -32v-1472c0 -12 -7 -23 -17 -28l-480 -256c-5 -3 -10 -4 -15 -4
+c-17 0 -32 15 -32 32v1472c0 12 7 23 17 28l480 256c5 3 10 4 15 4zM640 1536c5 0 10 -1 14 -3l512 -256c11 -6 18 -17 18 -29v-1472c0 -17 -15 -32 -32 -32c-5 0 -10 1 -14 3l-512 256c-11 6 -18 17 -18 29v1472c0 17 15 32 32 32z" />
+ <glyph glyph-name="object-ungroup" unicode="&#xf248;" horiz-adv-x="2304"
+d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256
+v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+ <glyph glyph-name="briefcase" unicode="&#xf0b1;" horiz-adv-x="1792"
+d="M640 1280h512v128h-512v-128zM1792 640v-480c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v480h672v-160c0 -35 29 -64 64 -64h320c35 0 64 29 64 64v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384c0 88 72 160 160 160h352v160
+c0 53 43 96 96 96h576c53 0 96 -43 96 -96v-160h352c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="weixin" unicode="&#xf1d7;" horiz-adv-x="2048"
+d="M580 1075c0 55 -36 91 -91 91c-54 0 -109 -36 -109 -91c0 -54 55 -90 109 -90c55 0 91 36 91 90zM1323 568c0 36 -36 72 -91 72c-36 0 -72 -36 -72 -72c0 -37 36 -73 72 -73c55 0 91 36 91 73zM1087 1075c0 55 -36 91 -90 91c-55 0 -109 -36 -109 -91
+c0 -54 54 -90 109 -90c54 0 90 36 90 90zM1722 568c0 36 -37 72 -91 72c-36 0 -72 -36 -72 -72c0 -37 36 -73 72 -73c54 0 91 36 91 73zM1456 965c-23 3 -46 4 -70 4c-344 0 -616 -257 -616 -573c0 -53 8 -104 23 -152c-23 -2 -45 -3 -68 -3c-91 0 -163 18 -254 36
+l-253 -127l72 218c-181 127 -290 291 -290 490c0 345 326 616 725 616c356 0 669 -217 731 -509zM2048 404c0 -163 -108 -308 -254 -417l55 -181l-199 109c-73 -18 -146 -37 -218 -37c-345 0 -616 236 -616 526s271 526 616 526c326 0 616 -236 616 -526z" />
+ <glyph glyph-name="stop" unicode="&#xf04d;"
+d="M1536 1344v-1408c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h1408c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="clone" unicode="&#xf24d;" horiz-adv-x="1792"
+d="M1664 -96v1088c0 17 -15 32 -32 32h-1088c-17 0 -32 -15 -32 -32v-1088c0 -17 15 -32 32 -32h1088c17 0 32 15 32 32zM1792 992v-1088c0 -88 -72 -160 -160 -160h-1088c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1088c88 0 160 -72 160 -160zM1408 1376v-160
+h-128v160c0 17 -15 32 -32 32h-1088c-17 0 -32 -15 -32 -32v-1088c0 -17 15 -32 32 -32h160v-128h-160c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1088c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="thermometer-full" unicode="&#xf2c7;" horiz-adv-x="1024"
+d="M640 192c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 80 50 153 128 181v907h128v-907c78 -28 128 -101 128 -181zM768 192c0 105 -50 197 -128 256v768c0 106 -86 192 -192 192s-192 -86 -192 -192v-768c-78 -59 -128 -151 -128 -256c0 -177 143 -320 320 -320
+s320 143 320 320zM896 192c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 122 49 232 128 313v711c0 177 143 320 320 320s320 -143 320 -320v-711c79 -81 128 -191 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z
+" />
+ <glyph glyph-name="plane" unicode="&#xf072;" horiz-adv-x="1402"
+d="M1376 1376c64 -64 0 -224 -96 -320l-161 -161l160 -696c3 -12 -2 -25 -12 -33l-128 -96c-5 -4 -12 -6 -19 -6c-2 0 -4 0 -7 1c-9 2 -17 7 -21 16l-279 508l-259 -259l53 -194c3 -11 0 -22 -8 -31l-96 -96c-6 -6 -15 -9 -23 -9h-2c-10 1 -18 5 -24 13l-189 252l-252 189
+c-8 5 -12 14 -13 23s3 18 9 25l96 97c6 6 15 9 23 9c3 0 6 0 8 -1l194 -53l259 259l-508 279c-9 5 -15 14 -17 24c-1 9 2 20 9 27l128 128c8 7 20 11 30 8l665 -159l160 160c96 96 256 160 320 96z" />
+ <glyph glyph-name="check-square" unicode="&#xf14a;"
+d="M685 237l614 614c25 25 25 65 0 90l-102 102c-25 25 -65 25 -90 0l-467 -467l-211 211c-25 25 -65 25 -90 0l-102 -102c-25 -25 -25 -65 0 -90l358 -358c25 -25 65 -25 90 0zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960
+c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="window-maximize" unicode="&#xf2d0;" horiz-adv-x="1792"
+d="M256 128h1280v768h-1280v-768zM1792 1248v-1216c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="github" unicode="&#xf09b;"
+d="M768 1408c424 0 768 -344 768 -768c0 -339 -220 -627 -525 -729c-39 -7 -53 17 -53 37c0 25 1 108 1 211c0 72 -24 118 -52 142c171 19 351 84 351 379c0 84 -30 152 -79 206c8 20 34 98 -8 204c-64 20 -211 -79 -211 -79c-61 17 -127 26 -192 26s-131 -9 -192 -26
+c0 0 -147 99 -211 79c-42 -106 -16 -184 -8 -204c-49 -54 -79 -122 -79 -206c0 -294 179 -360 350 -379c-22 -20 -42 -54 -49 -103c-44 -20 -156 -54 -223 64c-42 73 -118 79 -118 79c-75 1 -5 -47 -5 -47c50 -23 85 -112 85 -112c45 -137 259 -91 259 -91
+c0 -64 1 -124 1 -143c0 -20 -14 -44 -53 -37c-305 102 -525 390 -525 729c0 424 344 768 768 768zM291 305c-2 -4 -8 -5 -13 -2c-6 3 -9 8 -7 12c2 3 7 4 13 2c6 -3 9 -8 7 -12zM322 271c-4 -4 -11 -2 -16 3c-5 6 -6 13 -2 16c4 4 11 2 16 -3c5 -6 6 -13 2 -16zM352 226
+c-4 -3 -12 0 -17 7s-5 15 0 18c5 4 13 1 17 -6c5 -7 5 -15 0 -19zM394 184c-4 -5 -13 -4 -20 3c-7 6 -9 15 -4 19c4 5 13 4 20 -3c6 -6 8 -15 4 -19zM451 159c-2 -6 -11 -9 -19 -6c-9 2 -15 9 -13 15s11 9 19 7c9 -3 15 -10 13 -16zM514 154c0 -6 -7 -11 -16 -11
+c-10 -1 -17 4 -17 11c0 6 7 11 16 11c9 1 17 -4 17 -11zM572 164c1 -6 -5 -12 -14 -14s-17 2 -18 8c-1 7 5 13 14 15c9 1 17 -3 18 -9z" />
+ <glyph glyph-name="mastodon" unicode="&#xf2e1;"
+d="M1503 425c-23 -116 -202 -243 -408 -268c-108 -13 -214 -25 -327 -20c-185 8 -330 44 -330 44c0 -18 1 -35 3 -51c24 -182 181 -193 329 -198c150 -5 284 37 284 37l6 -136s-105 -56 -292 -66c-103 -6 -230 3 -379 42c-323 85 -379 430 -388 779c-3 104 -1 201 -1 283
+c0 357 235 462 235 462c118 54 320 77 531 79h5c211 -2 413 -25 531 -79c0 0 234 -105 234 -462c0 0 3 -263 -33 -446zM1260 843c0 88 -22 160 -68 211c-47 52 -107 79 -183 79c-88 0 -154 -34 -198 -101l-43 -72l-43 72c-44 67 -110 101 -198 101c-76 0 -136 -27 -183 -79
+c-45 -52 -68 -123 -68 -211v-432h171v420c0 88 38 133 112 133c82 0 124 -54 124 -159v-229h170v229c0 105 42 159 124 159c74 0 112 -45 112 -133v-420h171v432v0z" />
+ <glyph glyph-name="envelope-open" unicode="&#xf2b6;" horiz-adv-x="1792"
+d="M1792 882v-978c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v978c0 9 4 18 11 24c105 92 106 103 628 484c63 46 174 146 257 146s195 -101 257 -146c522 -381 523 -392 628 -484c7 -6 11 -15 11 -24zM1228 297c156 113 265 192 345 252c14 10 17 30 6 44
+l-38 52c-11 14 -31 17 -45 6c-79 -58 -187 -138 -343 -250c-62 -45 -174 -145 -257 -145s-195 100 -257 145c-156 113 -264 192 -343 250c-14 11 -34 8 -45 -6l-38 -52c-11 -14 -8 -34 6 -44c80 -60 189 -139 345 -252c78 -56 201 -169 332 -169c132 0 258 115 332 169z" />
+ <glyph glyph-name="step-backward" unicode="&#xf048;" horiz-adv-x="1024"
+d="M979 1395c25 25 45 16 45 -19v-1472c0 -35 -20 -44 -45 -19l-710 710c-6 6 -10 12 -13 19v-678c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v1408c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-678c3 7 7 13 13 19z" />
+ <glyph glyph-name="wheelchair" unicode="&#xf193;" horiz-adv-x="1629"
+d="M1023 349l102 -204c-77 -238 -299 -401 -549 -401c-317 0 -576 259 -576 576c0 242 152 458 379 541l17 -131c-163 -72 -268 -232 -268 -410c0 -247 201 -448 448 -448c257 0 465 220 447 477zM1571 249l58 -114l-256 -128c-9 -5 -19 -7 -29 -7c-24 0 -47 14 -57 35
+l-239 477h-472c-32 0 -60 25 -64 57l-96 779c-1 10 3 32 6 42c19 69 83 114 154 114c88 0 160 -72 160 -160c0 -91 -80 -169 -172 -159l37 -289h423v-128h-407l16 -128h455c24 0 47 -14 57 -35l228 -455z" />
+ <glyph glyph-name="bootstrap" unicode="&#xf315;"
+d="M256 1408h1024c141 0 256 -115 256 -256v-1024c0 -141 -115 -256 -256 -256h-1024c-141 0 -256 115 -256 256v1024c0 141 115 256 256 256zM494 1020v-795h310c169 0 270 83 270 223c0 106 -69 182 -177 196v4c77 14 137 91 137 174c0 119 -93 198 -229 198h-311z
+M593 933h190c97 0 150 -44 150 -123c0 -86 -64 -133 -181 -133h-159v256zM593 592v0h187c127 0 192 -47 192 -139s-63 -141 -183 -141h-196v280z" />
+ <glyph glyph-name="cutlery" unicode="&#xf0f5;" horiz-adv-x="1408"
+d="M640 1472v-640c0 -81 -52 -154 -128 -181v-779c0 -70 -58 -128 -128 -128h-128c-70 0 -128 58 -128 128v779c-76 27 -128 100 -128 181v640c0 35 29 64 64 64s64 -29 64 -64v-416c0 -35 29 -64 64 -64s64 29 64 64v416c0 35 29 64 64 64s64 -29 64 -64v-416
+c0 -35 29 -64 64 -64s64 29 64 64v416c0 35 29 64 64 64s64 -29 64 -64zM1408 1472v-1600c0 -70 -58 -128 -128 -128h-128c-70 0 -128 58 -128 128v512h-224c-17 0 -32 15 -32 32v800c0 176 144 320 320 320h256c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="microphone-slash" unicode="&#xf131;" horiz-adv-x="1382"
+d="M258 591l-101 -101c-27 66 -42 138 -42 214v128c0 35 29 64 64 64s64 -29 64 -64v-128c0 -39 6 -77 15 -113zM1372 1193l-361 -361v-128c0 -176 -144 -320 -320 -320c-38 0 -75 7 -109 19l-96 -96c61 -32 131 -51 205 -51c247 0 448 201 448 448v128c0 35 29 64 64 64
+s64 -29 64 -64v-128c0 -296 -224 -540 -512 -572v-132h256c35 0 64 -29 64 -64s-29 -64 -64 -64h-640c-35 0 -64 29 -64 64s29 64 64 64h256v132c-85 9 -165 38 -235 81l-254 -254c-13 -13 -33 -13 -46 0l-82 82c-13 13 -13 33 0 46l1234 1234c13 13 33 13 46 0l82 -82
+c13 -13 13 -33 0 -46zM992 1325l-621 -621v512c0 176 144 320 320 320c138 0 256 -89 301 -211z" />
+ <glyph glyph-name="user-plus" unicode="&#xf234;" horiz-adv-x="2048"
+d="M704 640c-212 0 -384 172 -384 384s172 384 384 384s384 -172 384 -384s-172 -384 -384 -384zM1664 512h352c17 0 32 -15 32 -32v-192c0 -17 -15 -32 -32 -32h-352v-352c0 -17 -15 -32 -32 -32h-192c-17 0 -32 15 -32 32v352h-352c-17 0 -32 15 -32 32v192
+c0 17 15 32 32 32h352v352c0 17 15 32 32 32h192c17 0 32 -15 32 -32v-352zM928 288c0 -70 58 -128 128 -128h256v-238c-49 -36 -111 -50 -171 -50h-874c-160 0 -267 96 -267 259c0 226 53 573 346 573c16 0 27 -7 39 -17c98 -75 193 -122 319 -122s221 47 319 122
+c12 10 23 17 39 17c85 0 160 -32 217 -96h-223c-70 0 -128 -58 -128 -128v-192z" />
+ <glyph glyph-name="truck" unicode="&#xf0d1;" horiz-adv-x="1728"
+d="M576 128c0 70 -58 128 -128 128s-128 -58 -128 -128s58 -128 128 -128s128 58 128 128zM192 640h384v256h-158c-4 0 -19 -6 -22 -9l-195 -195c-3 -3 -9 -18 -9 -22v-30zM1472 128c0 70 -58 128 -128 128s-128 -58 -128 -128s58 -128 128 -128s128 58 128 128zM1728 1216
+v-1024c0 -74 -78 -64 -128 -64c0 -141 -115 -256 -256 -256s-256 115 -256 256h-384c0 -141 -115 -256 -256 -256s-256 115 -256 256h-64c-50 0 -128 -10 -128 64c0 35 29 64 64 64v320c0 71 -10 150 45 205l198 198c25 25 73 45 109 45h160v192c0 35 29 64 64 64h1024
+c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="wrench" unicode="&#xf0ad;" horiz-adv-x="1641"
+d="M363 64c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1007 484l-682 -682c-23 -23 -56 -37 -90 -37s-67 14 -91 37l-106 108c-24 23 -38 56 -38 90s14 67 38 91l681 681c52 -131 157 -236 288 -288zM1641 919c0 -33 -12 -74 -23 -106
+c-63 -178 -234 -301 -423 -301c-247 0 -448 201 -448 448s201 448 448 448c73 0 168 -22 229 -63c10 -7 16 -16 16 -28c0 -11 -7 -22 -16 -28l-293 -169v-224l193 -107c33 19 265 165 285 165s32 -15 32 -35z" />
+ <glyph glyph-name="ambulance" unicode="&#xf0f9;" horiz-adv-x="1856"
+d="M576 128c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM192 640h384v256h-158c-6 -1 -17 -5 -22 -9l-195 -195c-3 -5 -8 -16 -9 -22v-30zM1472 128c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1600 800
+v192c0 18 -14 32 -32 32h-224v224c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32v-224h-224c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h224v-224c0 -18 14 -32 32 -32h192c18 0 32 14 32 32v224h224c18 0 32 14 32 32zM1856 1344v-1152c0 -35 -29 -64 -64 -64h-192
+c0 -141 -114 -256 -256 -256c-141 0 -256 115 -256 256h-384c0 -141 -114 -256 -256 -256s-256 115 -256 256h-128c-35 0 -64 29 -64 64s29 64 64 64v416c0 35 20 84 45 109l198 198c25 25 74 45 109 45h160v320c0 35 29 64 64 64h1152c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="cc-visa" unicode="&#xf1f0;" horiz-adv-x="2304"
+d="M1975 546h-138s14 37 66 179c-1 -1 14 37 22 61l12 -55c31 -153 38 -185 38 -185zM531 611l-58 295c-8 41 -39 54 -75 54h-268l-2 -13c184 -47 335 -147 403 -336zM710 960l-162 -438l-17 89c-35 93 -120 179 -216 218l135 -510h175l261 641h-176zM849 318h166l104 642
+h-166zM1617 944c-33 13 -85 27 -149 27c-164 0 -279 -87 -280 -212c-1 -92 82 -143 145 -174c65 -31 86 -52 86 -80c0 -43 -52 -62 -99 -62c-67 0 -103 8 -156 33l-22 11l-23 -144c39 -18 110 -34 185 -34c174 -1 287 86 289 219c0 73 -45 128 -140 174
+c-58 29 -93 50 -93 80c0 27 30 55 95 55c54 1 94 -10 124 -24l15 -8zM2042 960h-128c-40 0 -70 -12 -87 -54l-246 -588h174c28 79 35 96 35 96h212s5 -22 20 -96h154zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128
+h2048c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="superscript" unicode="&#xf12b;" horiz-adv-x="1529"
+d="M892 167v-167h-248l-159 252l-24 42c-6 7 -9 14 -11 21h-3c-2 -7 -6 -14 -9 -21c-6 -12 -15 -28 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228c9 -14 16 -29 23 -42c6 -7 9 -14 11 -21h3c2 7 6 14 11 21l25 42l140 228h257v-168h-125
+l-184 -267l204 -296h109zM1529 846v-206h-514l-3 27c-2 14 -4 33 -4 46c0 273 350 296 350 441c0 52 -47 87 -100 87c-38 0 -72 -18 -97 -39c-13 -11 -25 -25 -36 -38l-105 92c18 25 38 46 63 66c42 33 103 65 188 65c145 0 246 -85 246 -218c0 -240 -332 -260 -346 -403
+h232v80h126z" />
+ <glyph glyph-name="pixelfed" unicode="&#xf314;"
+d="M768 -128c-424 0 -768 344 -768 768s344 768 768 768s768 -344 768 -768s-344 -768 -768 -768zM707 472h141c133 0 240 105 240 234s-107 234 -240 234h-203c-77 0 -139 -60 -139 -135v-525z" />
+ <glyph glyph-name="tty" unicode="&#xf1e4;" horiz-adv-x="1792"
+d="M448 224v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM256 608v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM832 224v-192c0 -18 -14 -32 -32 -32h-192
+c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM640 608v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM66 768c-37 0 -66 29 -66 65v129h514v-129c0 -36 -29 -65 -65 -65h-383zM1216 224v-192
+c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1024 608v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1600 224v-192c0 -18 -14 -32 -32 -32h-192
+c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1408 608v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1792 1016v-13h-514v10c0 37 -32 104 -382 102c-350 -1 -382 -65 -382 -102v-10h-514v13
+c0 67 120 392 896 392c775 0 896 -325 896 -392zM1792 608v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1792 962v-129c0 -36 -29 -65 -65 -65h-384c-36 0 -65 29 -65 65v129h514z" />
+ <glyph glyph-name="linode" unicode="&#xf2b8;" horiz-adv-x="1494"
+d="M309 1l202 -214l-34 236l-216 213zM535 -225l274 218l-11 245l-300 -215zM224 413l227 -213l-48 327l-245 204zM474 189l317 214l-14 324l-352 -200zM822 178l95 -80l-2 239l-103 79c0 -8 4 -22 -4 -28l-78 -52l85 -70c10 -8 7 -76 7 -88zM117 930l256 -200l-68 465
+l-279 173zM1152 267l15 234l-230 -164l2 -240zM396 722l373 194l-19 441l-423 -163zM1249 357l20 233l-226 142l-2 -105l144 -95c3 -2 5 -6 4 -9l-7 -119zM1440 496l30 222l-179 -128l-20 -228zM1252 329l-71 49l-8 -117c0 -3 -1 -6 -4 -8l-234 -187c-4 -3 -10 -3 -14 0
+l-98 83l7 -161c0 -3 -1 -6 -4 -8l-293 -234c-2 -1 -4 -2 -6 -2c-3 1 -6 1 -8 3l-228 242c-5 5 -54 252 -59 277c-1 4 2 9 5 11l61 37c-12 11 -93 82 -95 92l-72 351c-1 4 1 9 6 12l94 45c-16 12 -132 96 -135 108l-96 466c-1 6 2 11 7 13l433 135c2 0 5 0 8 -1l317 -153
+c3 -2 6 -6 6 -9l20 -463c0 -4 -2 -8 -6 -10l-118 -61l126 -85c3 -1 5 -5 5 -8l5 -123l121 74c3 2 8 2 11 0l84 -56l3 110c0 3 2 7 5 9l206 126c4 2 8 2 11 0l245 -135c2 -2 4 -4 5 -7c2 -7 -31 -232 -34 -255c0 -3 -2 -6 -4 -7l-191 -153c-4 -3 -9 -3 -13 0z" />
+ <glyph glyph-name="shield" unicode="&#xf132;" horiz-adv-x="1280"
+d="M1088 576v640h-448v-1137c51 27 133 74 213 137c107 84 235 215 235 360zM1280 1344v-768c0 -421 -589 -687 -614 -698c-8 -4 -17 -6 -26 -6s-18 2 -26 6c-25 11 -614 277 -614 698v768c0 35 29 64 64 64h1152c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="user-md" unicode="&#xf0f0;" horiz-adv-x="1408"
+d="M384 192c0 -35 -29 -64 -64 -64s-64 29 -64 64s29 64 64 64s64 -29 64 -64zM1408 131c0 -163 -107 -259 -267 -259h-874c-160 0 -267 96 -267 259c0 199 40 513 278 565c-16 -38 -22 -79 -22 -120v-203c-77 -27 -128 -100 -128 -181c0 -106 86 -192 192 -192
+s192 86 192 192c0 81 -52 154 -128 181v203c0 33 3 66 25 93c84 -66 188 -104 295 -104s211 38 295 104c22 -27 25 -60 25 -93v-64c-141 0 -256 -115 -256 -256v-89c-20 -18 -32 -44 -32 -71c0 -53 43 -96 96 -96s96 43 96 96c0 27 -12 53 -32 71v89c0 70 58 128 128 128
+s128 -58 128 -128v-89c-20 -18 -32 -44 -32 -71c0 -53 43 -96 96 -96s96 43 96 96c0 27 -12 53 -32 71v89c0 91 -49 176 -128 221c0 73 7 151 -22 219c238 -52 278 -366 278 -565zM1088 1024c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384
+s384 -172 384 -384z" />
+ <glyph glyph-name="xmpp" unicode="&#xf2f9;" horiz-adv-x="1542"
+d="M1536 1314c47 -398 -206 -904 -657 -1199c122 -101 261 -177 414 -216v-27c-165 14 -320 59 -461 128l-30 15l-1 1l-6 3c-11 6 -30 16 -41 22c-94 -51 -193 -90 -297 -116c-68 -19 -139 -33 -211 -42v28c145 37 279 107 396 201c-426 296 -682 805 -637 1192l93 -33v0
+l273 -81c-1 -16 -1 -32 -1 -49c0 -296 147 -656 394 -917c254 262 406 628 406 929c0 17 0 33 -1 49l274 81z" />
+ <glyph glyph-name="moon-o" unicode="&#xf186;" horiz-adv-x="1471"
+d="M1262 233c-36 -6 -73 -9 -110 -9c-371 0 -672 301 -672 672c0 127 37 251 104 357c-266 -79 -456 -323 -456 -613c0 -353 287 -640 640 -640c193 0 374 88 494 233zM1465 318c-125 -271 -399 -446 -697 -446c-423 0 -768 345 -768 768c0 415 325 752 739 767
+c28 1 51 -15 61 -39c11 -25 4 -54 -15 -72c-114 -104 -177 -246 -177 -400c0 -300 244 -544 544 -544c79 0 155 17 228 51c25 11 53 6 72 -13s24 -48 13 -72z" />
+ <glyph glyph-name="pie-chart" unicode="&#xf200;" horiz-adv-x="1728"
+d="M768 646l546 -546c-139 -141 -333 -228 -546 -228c-424 0 -768 344 -768 768s344 768 768 768v-762zM955 640h773c0 -213 -87 -407 -228 -546zM1664 768h-768v768c424 0 768 -344 768 -768z" />
+ <glyph glyph-name="align-left" unicode="&#xf036;" horiz-adv-x="1792"
+d="M1792 192v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1408 576v-128c0 -35 -29 -64 -64 -64h-1280c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1280c35 0 64 -29 64 -64zM1664 960v-128
+c0 -35 -29 -64 -64 -64h-1536c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1536c35 0 64 -29 64 -64zM1280 1344v-128c0 -35 -29 -64 -64 -64h-1152c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1152c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="motorcycle" unicode="&#xf21c;" horiz-adv-x="2304"
+d="M2301 500c32 -281 -197 -517 -476 -499c-214 14 -392 185 -414 399c-16 152 44 289 146 381l-71 107c-126 -105 -206 -262 -206 -438c0 -36 -28 -66 -64 -66h-325c-31 -217 -217 -384 -443 -384c-247 0 -448 201 -448 448s201 448 448 448c53 0 104 -10 152 -27l24 45
+c-77 69 -178 110 -304 110h-64c-35 0 -64 29 -64 64s29 64 64 64h128c224 0 338 -92 384 -128h627l-85 128h-222c-39 0 -70 35 -63 75c5 31 35 53 66 53h253c21 0 41 -11 53 -28l70 -105l114 114c12 12 29 19 46 19h101c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-179
+l115 -172c81 39 175 55 275 36c191 -35 340 -195 362 -388zM448 128c155 0 284 110 314 256h-314c-22 0 -43 12 -55 31c-11 19 -12 43 -1 63l147 277c-29 8 -59 13 -91 13c-176 0 -320 -144 -320 -320s144 -320 320 -320zM1856 128c176 0 320 144 320 320s-144 320 -320 320
+c-43 0 -83 -9 -121 -24l174 -260c20 -30 12 -70 -17 -89c-11 -8 -24 -11 -36 -11c-21 0 -41 10 -53 29l-174 260c-57 -58 -93 -137 -93 -225c0 -176 144 -320 320 -320z" />
+ <glyph glyph-name="nextcloud-square" unicode="&#xf307;"
+d="M257 1408h1022c142 0 257 -115 257 -257v-1022c0 -142 -115 -257 -257 -257h-1022c-142 0 -257 115 -257 257v1022c0 142 115 257 257 257zM772 969v0c-145 0 -268 -98 -307 -230c-34 69 -105 118 -187 118c-114 0 -208 -94 -208 -208s94 -207 208 -207
+c82 0 153 48 187 117c39 -132 162 -230 307 -230s267 98 306 230c34 -69 105 -117 187 -117c114 0 208 93 208 207s-94 208 -208 208c-82 0 -153 -49 -187 -118c-39 132 -161 230 -306 230zM772 846v0c106 0 196 -88 196 -197s-87 -196 -196 -196s-197 87 -197 196
+s88 197 197 197zM278 733c47 0 84 -37 84 -84s-37 -84 -84 -84s-84 37 -84 84s37 84 84 84zM1265 733c47 0 84 -37 84 -84s-37 -84 -84 -84s-84 37 -84 84s37 84 84 84z" />
+ <glyph glyph-name="ticket" unicode="&#xf145;" horiz-adv-x="1685"
+d="M970 1084l316 -316l-572 -572l-316 316zM760 105l618 618c25 25 25 65 0 90l-362 362c-24 24 -66 24 -90 0l-618 -618c-25 -25 -25 -65 0 -90l362 -362c12 -12 27 -18 44 -18s34 6 46 18zM1648 742l-906 -908c-50 -49 -133 -49 -182 0l-126 126c75 75 75 197 0 272
+s-197 75 -272 0l-124 126c-50 49 -50 131 0 181l906 906c49 50 132 50 182 0l124 -125c-75 -75 -75 -197 0 -272s197 -75 272 0l126 -125c49 -50 49 -132 0 -181z" />
+ <glyph glyph-name="battery-half" unicode="&#xf242;" horiz-adv-x="2304"
+d="M256 256v768h896v-768h-896zM2176 960c71 0 128 -57 128 -128v-384c0 -71 -57 -128 -128 -128v-160c0 -88 -72 -160 -160 -160h-1856c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1856c88 0 160 -72 160 -160v-160zM2176 448v384h-128v288c0 18 -14 32 -32 32h-1856
+c-18 0 -32 -14 -32 -32v-960c0 -18 14 -32 32 -32h1856c18 0 32 14 32 32v288h128z" />
+ <glyph glyph-name="spotify" unicode="&#xf1bc;"
+d="M1127 326c0 28 -11 39 -30 51c-129 77 -279 115 -447 115c-98 0 -192 -13 -287 -34c-23 -5 -42 -20 -42 -52c0 -25 19 -49 49 -49c9 0 25 5 37 8c78 16 160 27 243 27c147 0 286 -36 397 -103c12 -7 20 -11 33 -11c25 0 47 20 47 48zM1223 541c0 27 -10 46 -35 61
+c-153 91 -347 141 -548 141c-129 0 -217 -18 -303 -42c-32 -9 -48 -31 -48 -64s27 -60 60 -60c14 0 22 4 37 8c70 19 154 33 251 33c190 0 363 -50 488 -124c11 -6 22 -13 38 -13c34 0 60 27 60 60zM1331 789c0 37 -16 56 -40 70c-173 101 -410 148 -636 148
+c-133 0 -255 -15 -364 -47c-28 -8 -54 -32 -54 -74c0 -41 31 -73 72 -73c15 0 29 5 40 8c97 27 202 37 307 37c208 0 424 -46 563 -129c14 -8 24 -12 40 -12c38 0 72 30 72 72zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z
+" />
+ <glyph glyph-name="dot-circle-o" unicode="&#xf192;"
+d="M1024 640c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256zM768 1184c-300 0 -544 -244 -544 -544s244 -544 544 -544s544 244 544 544s-244 544 -544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768
+s768 -344 768 -768z" />
+ <glyph glyph-name="facebook-square" unicode="&#xf082;"
+d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-188v595h199l30 232h-229v148c0 67 18 112 115 112l122 1v207c-21 3 -94 9 -178 9c-177 0 -299 -108 -299 -306v-171h-200v-232h200v-595h-532c-159 0 -288 129 -288 288v960c0 159 129 288 288 288
+h960z" />
+ <glyph glyph-name="facebook-messenger" unicode="&#xf2fe;" horiz-adv-x="1520"
+d="M760 1408c420 0 760 -318 760 -711c0 -476 -490 -817 -978 -681l-260 -144v272c-556 420 -235 1264 478 1264zM841 455l415 440l-379 -209l-197 204l-415 -441l379 210z" />
+ <glyph glyph-name="angle-up" unicode="&#xf106;" horiz-adv-x="998"
+d="M998 352c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -14 -10 -23 -10c-8 0 -17 4 -23 10l-393 393l-393 -393c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="glide" unicode="&#xf2a5;"
+d="M866 1021c0 -32 -7 -63 -13 -94c-21 -100 -41 -200 -62 -300c-3 -14 -3 -14 -18 -15c-10 -1 -21 -2 -31 -2c-86 0 -110 93 -110 163c0 104 41 243 138 298c16 8 33 14 51 14c41 0 45 -30 45 -64zM1352 597c0 18 -74 135 -91 142c-8 3 -25 8 -34 8
+c-82 0 -156 -37 -226 -77l-2 2c16 107 52 202 52 313c0 159 -85 233 -242 233c-23 0 -46 -3 -68 -6c-197 -35 -317 -260 -317 -445c0 -196 113 -304 308 -304c4 0 25 2 25 -3c0 -2 0 -3 -1 -5c-4 -38 -16 -80 -26 -117c-15 -55 -67 -150 -134 -150c-29 0 -42 20 -42 47
+c0 87 100 139 102 144c0 4 -5 8 -7 10c-31 28 -82 51 -124 51c-76 0 -117 -122 -117 -184c0 -116 73 -196 190 -196c173 0 299 182 338 332c11 44 19 89 30 133c2 9 5 13 14 18c71 36 146 60 227 60c44 0 83 -8 127 -18c1 -1 3 -1 4 -1c6 0 14 7 14 13zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="gitea" unicode="&#xf31f;" horiz-adv-x="2066"
+d="M366 1280v0c62 0 120 -8 160 -8v0v0c329 -18 502 -29 699 -29l1 -363l53 -27v390c171 2 371 11 709 29v0h1c15 0 28 -7 38 -17s18 -25 24 -43c12 -36 16 -85 15 -143c-3 -117 -30 -272 -75 -427s-107 -311 -182 -431s-163 -204 -259 -211h-615c-75 8 -156 85 -224 169
+c-34 42 -64 87 -87 126c-21 36 -35 66 -41 88c-82 2 -219 15 -341 80c-125 67 -233 191 -242 414c-6 143 45 245 118 310s167 93 248 93zM388 1107v0c-90 -1 -147 -29 -180 -71c-36 -44 -46 -104 -38 -164c14 -113 61 -183 126 -229c62 -44 143 -65 231 -78
+c-70 193 -106 325 -128 542h-11zM1118 893c-34 0 -66 -19 -82 -51l-172 -353c-22 -45 -3 -99 42 -121l354 -172c45 -22 99 -3 121 42l171 354c22 45 3 99 -42 121l-249 121l-45 -93c5 -5 10 -14 12 -20c2 -5 3 -13 3 -19v-4c30 -14 54 -25 74 -36c30 -17 52 -34 59 -62
+s-1 -57 -17 -95c-12 -29 -29 -65 -51 -111c4 -5 9 -13 11 -19c2 -5 4 -13 4 -19c0 -22 -17 -46 -38 -54c-5 -2 -14 -4 -20 -4c-22 0 -46 17 -54 38c-2 5 -3 14 -3 20c0 22 17 46 38 54c5 2 14 3 19 3h2c22 46 41 82 52 109c15 36 18 55 15 66s-13 20 -39 35
+c-18 10 -41 22 -71 36c-4 -4 -13 -9 -19 -11c-5 -2 -14 -3 -19 -3h-6l-77 -158c5 -5 12 -14 14 -21c2 -5 3 -13 3 -19c0 -22 -17 -46 -38 -54c-5 -2 -13 -4 -19 -4c-22 0 -46 17 -54 38c-2 5 -3 14 -3 20c0 22 16 46 37 54c5 2 15 3 20 3l79 162c-3 4 -8 11 -10 16
+s-3 14 -3 20c0 22 17 46 38 54c5 2 14 3 19 3h1l46 94l-64 31c-13 6 -26 9 -39 9z" />
+ <glyph glyph-name="f-droid" unicode="&#xf32a;" horiz-adv-x="1676"
+d="M47 1526v0c12 0 29 -8 36 -18l127 -164c10 3 27 6 37 6v0h1182v0c10 0 27 -3 37 -6l127 164c7 9 22 17 34 18h2h3c24 -1 44 -22 44 -46c0 -9 -4 -22 -10 -29l-133 -172c4 -11 7 -29 7 -40v0v-258c0 -61 -50 -111 -111 -111h-1182c-61 0 -111 50 -111 111v258v0
+c0 11 3 29 7 40l-133 172c-6 7 -10 20 -10 29c0 26 20 46 46 46h1zM482 1212v0c-69 0 -125 -56 -125 -125v0c0 -69 56 -125 125 -125v0c69 0 125 56 125 125v0c0 69 -56 125 -125 125v0zM1203 1212c-69 0 -125 -56 -125 -125v0c0 -69 56 -125 125 -125s125 56 125 125v0
+c0 69 -56 125 -125 125zM247 833h1182c61 0 111 -50 111 -111v-739c0 -61 -50 -111 -111 -111h-1182c-61 0 -111 50 -111 111v739c0 61 50 111 111 111zM838 740v0c-214 0 -388 -174 -388 -388s174 -388 388 -388s388 174 388 388s-174 388 -388 388zM838 670v0
+c176 0 318 -142 318 -318s-142 -317 -318 -317s-318 141 -318 317s142 318 318 318zM838 583v0c-106 0 -197 -72 -223 -171h119c20 36 59 61 104 61c67 0 120 -54 120 -121s-53 -120 -120 -120c-48 0 -89 28 -108 69h-117c24 -102 116 -180 225 -180c127 0 231 104 231 231
+s-104 231 -231 231z" />
+ <glyph glyph-name="shopping-basket" unicode="&#xf291;" horiz-adv-x="2048"
+d="M1920 768c71 0 128 -57 128 -128s-57 -128 -128 -128h-15l-115 -662c-11 -61 -64 -106 -126 -106h-1280c-62 0 -115 45 -126 106l-115 662h-15c-71 0 -128 57 -128 128s57 128 128 128h1792zM485 -32c35 3 62 34 59 69l-32 416c-3 35 -34 62 -69 59s-62 -34 -59 -69
+l32 -416c3 -33 31 -59 64 -59h5zM896 32v416c0 35 -29 64 -64 64s-64 -29 -64 -64v-416c0 -35 29 -64 64 -64s64 29 64 64zM1280 32v416c0 35 -29 64 -64 64s-64 -29 -64 -64v-416c0 -35 29 -64 64 -64s64 29 64 64zM1632 27l32 416c3 35 -24 66 -59 69s-66 -24 -69 -59
+l-32 -416c-3 -35 24 -66 59 -69h5c33 0 61 26 64 59zM476 1244l-93 -412h-132l101 441c26 117 129 199 249 199h167c0 35 29 64 64 64h384c35 0 64 -29 64 -64h167c120 0 223 -82 249 -199l101 -441h-132l-93 412c-14 59 -65 100 -125 100h-167c0 -35 -29 -64 -64 -64h-384
+c-35 0 -64 29 -64 64h-167c-60 0 -111 -41 -125 -100z" />
+ <glyph glyph-name="user-o" unicode="&#xf2c0;"
+d="M1201 752c141 -41 335 -180 335 -635c0 -206 -153 -373 -341 -373h-854c-188 0 -341 167 -341 373c0 455 194 594 335 635c-50 79 -79 172 -79 272c0 282 230 512 512 512s512 -230 512 -512c0 -100 -29 -193 -79 -272zM768 1408c-212 0 -384 -172 -384 -384
+s172 -384 384 -384s384 172 384 384s-172 384 -384 384zM1195 -128c117 0 213 109 213 245c0 315 -106 512 -304 522c-90 -79 -207 -127 -336 -127s-246 48 -336 127c-198 -10 -304 -207 -304 -522c0 -136 96 -245 213 -245h854z" />
+ <glyph glyph-name="paperclip" unicode="&#xf0c6;" horiz-adv-x="1400"
+d="M1400 151c0 -156 -119 -275 -275 -275c-88 0 -173 38 -235 100l-777 776c-71 72 -113 170 -113 271c0 212 167 381 379 381c102 0 200 -41 273 -113l605 -606c6 -6 10 -14 10 -22c0 -21 -56 -77 -77 -77c-9 0 -17 4 -23 10l-606 607c-48 47 -113 77 -181 77
+c-142 0 -252 -115 -252 -256c0 -68 28 -133 76 -181l776 -777c38 -38 91 -63 145 -63c85 0 148 63 148 148c0 55 -25 107 -63 145l-581 581c-16 15 -38 24 -60 24c-38 0 -67 -28 -67 -67c0 -22 10 -43 25 -59l410 -410c6 -6 10 -14 10 -22c0 -21 -57 -78 -78 -78
+c-8 0 -16 4 -22 10l-410 410c-40 39 -63 94 -63 149c0 110 86 196 196 196c56 0 110 -23 149 -63l581 -581c63 -62 100 -147 100 -235z" />
+ <glyph glyph-name="deviantart" unicode="&#xf1bd;" horiz-adv-x="1024"
+d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273c-1 0 -28 -28 -30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273c1 0 28 28 30 30h301v-303z" />
+ <glyph glyph-name="file-audio-o" unicode="&#xf1c7;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM620 686c12 -5 20 -17 20 -30v-544c0 -13 -8 -25 -20 -30c-4 -1 -8 -2 -12 -2c-8 0 -16 3 -23 9l-166 167h-131c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h131l166 167c10 9 23 12 35 7zM1037 -3c-14 0 -28 5 -40 15c-28 22 -32 62 -9 90
+c65 80 100 178 100 282s-35 202 -100 282c-23 28 -19 68 9 91c27 22 68 18 90 -10c83 -102 129 -231 129 -363s-46 -261 -129 -363c-13 -16 -31 -24 -50 -24zM826 145c-15 0 -31 6 -44 17c-25 24 -27 65 -2 91c33 36 52 82 52 131s-19 95 -52 131c-25 26 -23 67 2 91
+c26 24 67 23 91 -3c56 -60 87 -137 87 -219s-31 -159 -87 -219c-13 -13 -30 -20 -47 -20z" />
+ <glyph glyph-name="eur" unicode="&#xf153;" horiz-adv-x="1012"
+d="M976 229l35 -159c4 -16 -5 -32 -20 -37c-4 -1 -97 -33 -217 -33c-312 0 -563 188 -647 482h-95c-18 0 -32 15 -32 32v113c0 17 14 32 32 32h66c-1 32 -1 70 1 105h-67c-18 0 -32 14 -32 32v114c0 18 14 32 32 32h98c89 280 345 466 644 466c104 0 190 -22 194 -23
+c8 -2 15 -8 20 -15c4 -7 5 -16 3 -24l-43 -159c-4 -17 -21 -27 -38 -22c-1 0 -69 17 -140 17c-168 0 -309 -91 -376 -240h468c10 0 19 -4 25 -12c6 -7 9 -17 7 -26l-24 -114c-3 -15 -16 -26 -32 -26h-488c-3 -32 -2 -66 0 -105h459c10 0 19 -5 25 -12c6 -8 8 -18 6 -27
+l-24 -112c-3 -15 -16 -26 -31 -26h-387c64 -156 208 -254 378 -254c87 0 158 24 159 24c8 3 18 2 26 -2c8 -5 13 -13 15 -21z" />
+ <glyph glyph-name="coffee" unicode="&#xf0f4;" horiz-adv-x="1856"
+d="M1664 896c0 106 -86 192 -192 192h-64v-384h64c106 0 192 86 192 192zM0 128h1792c0 -141 -115 -256 -256 -256h-1280c-141 0 -256 115 -256 256zM1856 896c0 -212 -172 -384 -384 -384h-64v-32c0 -123 -101 -224 -224 -224h-704c-123 0 -224 101 -224 224v736
+c0 35 29 64 64 64h1152c212 0 384 -172 384 -384z" />
+ <glyph glyph-name="university" unicode="&#xf19c;" horiz-adv-x="1920"
+d="M960 1536l960 -384v-128h-128c0 -35 -31 -64 -69 -64h-1526c-38 0 -69 29 -69 64h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59c38 0 69 -29 69 -64v-64h-1664v64c0 35 31 64 69 64h59v768zM1851 -64c38 0 69 -29 69 -64v-128
+h-1920v128c0 35 31 64 69 64h1782z" />
+ <glyph glyph-name="times-circle-o" unicode="&#xf05c;"
+d="M1097 457l-146 -146c-13 -13 -33 -13 -46 0l-137 137l-137 -137c-13 -13 -33 -13 -46 0l-146 146c-13 13 -13 33 0 46l137 137l-137 137c-13 13 -13 33 0 46l146 146c13 13 33 13 46 0l137 -137l137 137c13 13 33 13 46 0l146 -146c13 -13 13 -33 0 -46l-137 -137
+l137 -137c13 -13 13 -33 0 -46zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544s544 244 544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="python" unicode="&#xf322;"
+d="M759 1416v0c63 0 129 -4 193 -15c101 -17 185 -92 185 -192v-353c0 -103 -82 -188 -185 -188h-370c-126 0 -232 -108 -232 -230v-170h-127c-108 0 -171 78 -197 188c-36 147 -34 236 0 377c29 123 124 188 232 188h509v47h-370v141c0 107 28 164 185 192
+c53 9 114 15 177 15zM558 1303c-38 0 -69 -32 -69 -71s31 -70 69 -70s70 31 70 70s-32 71 -70 71zM1183 1021h139c108 0 159 -81 186 -188c37 -149 39 -261 0 -377c-37 -113 -78 -188 -186 -188h-555v-47h370v-141c0 -107 -92 -161 -185 -188c-140 -41 -253 -34 -370 0
+c-98 29 -185 88 -185 188v353c0 102 84 188 185 188h370c123 0 231 107 231 235v165zM975 127v0c-38 0 -69 -31 -69 -70s31 -71 69 -71s70 32 70 71s-32 70 -70 70zM1389 366c0 -17 -70 -30 -156 -30s-156 13 -156 30s70 30 156 30s156 -13 156 -30z" />
+ <glyph glyph-name="internet-explorer" unicode="&#xf26b;" horiz-adv-x="1792"
+d="M1792 599c0 -35 -2 -70 -7 -104h-1151c0 -199 175 -343 367 -343c130 0 255 64 322 177h423c-114 -321 -419 -536 -759 -536c-123 0 -246 29 -356 83c-112 -57 -269 -116 -394 -116c-168 0 -237 103 -237 263c0 93 20 186 45 275c16 58 80 176 109 229
+c123 223 285 437 475 606c-153 -66 -319 -232 -427 -354c84 366 410 625 785 625c15 0 30 0 45 -1c124 57 297 117 433 117c162 0 301 -62 301 -245c0 -96 -37 -200 -75 -286c66 -119 101 -254 101 -390zM1722 1239c0 112 -80 181 -190 181c-84 0 -179 -34 -254 -70
+c162 -63 301 -179 393 -327c25 66 51 146 51 216zM128 2c0 -116 69 -179 183 -179c89 0 188 40 266 83c-163 96 -289 249 -351 428c-46 -96 -98 -224 -98 -332zM632 715h728c-7 193 -177 332 -364 332c-188 0 -357 -139 -364 -332z" />
+ <glyph glyph-name="file-video-o" unicode="&#xf1c8;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM768 768c70 0 128 -58 128 -128v-384c0 -70 -58 -128 -128 -128h-384c-70 0 -128 58 -128 128v384c0 70 58 128 128 128h384zM1260 766c12 -5 20 -17 20 -30v-576c0 -13 -8 -25 -20 -30c-4 -1 -8 -2 -12 -2c-8 0 -17 3 -23 9l-265 266v90l265 266
+c6 6 15 9 23 9c4 0 8 -1 12 -2z" />
+ <glyph glyph-name="angle-double-right" unicode="&#xf101;" horiz-adv-x="966"
+d="M582 576c0 -8 -4 -17 -10 -23l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l393 393l-393 393c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23zM966 576c0 -8 -4 -17 -10 -23
+l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l393 393l-393 393c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="safari" unicode="&#xf267;" horiz-adv-x="1792"
+d="M949 643c0 -33 -23 -64 -58 -64c-33 0 -64 24 -64 58c0 33 24 64 59 64c32 0 63 -23 63 -58zM964 585l350 581c-47 -44 -485 -447 -497 -468l-349 -580c46 43 485 448 496 467zM1611 640c0 -131 -36 -260 -104 -371c-10 5 -52 35 -60 35c-7 0 -13 -6 -13 -13
+c0 -13 47 -37 59 -44c-99 -150 -252 -258 -426 -301l-16 67c-1 9 -7 10 -15 10c-7 0 -11 -10 -10 -15l16 -68c-48 -10 -97 -15 -146 -15c-131 0 -260 37 -372 105c6 10 44 65 44 73c0 7 -6 13 -13 13c-14 0 -44 -60 -53 -72c-151 100 -260 255 -302 432l69 15
+c8 2 10 8 10 15s-10 11 -16 10l-68 -15c-9 46 -14 92 -14 139c0 134 38 266 109 379c10 -6 58 -39 66 -39c7 0 13 5 13 12c0 14 -53 41 -65 49c102 149 257 256 433 296l15 -67c2 -8 8 -10 15 -10s11 10 10 16l-15 66c44 8 89 13 134 13c134 0 265 -38 379 -109
+c-7 -10 -39 -57 -39 -65c0 -7 5 -13 12 -13c14 0 41 52 48 64c148 -100 254 -253 295 -427l-56 -12c-9 -2 -10 -8 -10 -16c0 -7 10 -11 15 -10l57 13c9 -46 14 -93 14 -140zM1696 640c0 442 -358 800 -800 800s-800 -358 -800 -800s358 -800 800 -800s800 358 800 800z
+M1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="commenting-o" unicode="&#xf27b;" horiz-adv-x="1792"
+d="M640 640c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1024 640c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1408 640c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128z
+M896 1152c-416 0 -768 -234 -768 -512c0 -149 100 -291 273 -389l87 -50l-27 -96c-19 -71 -44 -126 -70 -172c101 42 193 99 275 171l43 38l57 -6c43 -5 87 -8 130 -8c416 0 768 234 768 512s-352 512 -768 512zM1792 640c0 -354 -401 -640 -896 -640c-49 0 -98 3 -145 8
+c-131 -116 -287 -198 -460 -242c-36 -10 -75 -17 -114 -22h-5c-20 0 -38 16 -43 38v1c-5 25 12 40 27 58c63 71 135 131 182 298c-206 117 -338 298 -338 501c0 353 401 640 896 640s896 -287 896 -640z" />
+ <glyph glyph-name="snowdrift" unicode="&#xf2f1;" horiz-adv-x="1448"
+d="M1007 384c104 116 30 287 -165 383c7 -6 44 24 83 67s65 84 58 90c-195 96 -438 80 -542 -36s-30 -287 165 -383c-7 6 -44 -24 -83 -67s-65 -84 -58 -90c195 -96 438 -80 542 36zM103 1188v0c228 253 760 288 1188 78c15 -14 -42 -101 -127 -196s-167 -161 -182 -147
+c428 -210 591 -585 363 -839c-228 -253 -760 -288 -1188 -78c-15 14 42 101 127 196s167 161 182 147c-428 210 -591 585 -363 839z" />
+ <glyph glyph-name="black-tie" unicode="&#xf27e;"
+d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+ <glyph glyph-name="youtube-play" unicode="&#xf16a;" horiz-adv-x="1792"
+d="M711 408l484 250l-484 253v-503zM896 1270c377 0 627 -18 627 -18c35 -4 112 -4 180 -76c0 0 55 -54 71 -178c19 -145 18 -290 18 -290v-136s1 -145 -18 -290c-16 -123 -71 -178 -71 -178c-68 -71 -145 -71 -180 -75c0 0 -250 -19 -627 -19c-466 4 -609 18 -609 18
+c-40 7 -130 5 -198 76c0 0 -55 55 -71 178c-19 145 -18 290 -18 290v136s-1 145 18 290c16 124 71 178 71 178c68 72 145 72 180 76c0 0 250 18 627 18z" />
+ <glyph glyph-name="modx" unicode="&#xf285;" horiz-adv-x="1728"
+d="M1395 827l-614 386l92 151h855zM373 562l-184 116v858l1183 -743zM1392 697l147 -95v-858l-532 335zM1355 718l-500 -802h-855l356 571z" />
+ <glyph glyph-name="caret-square-o-right" unicode="&#xf152;"
+d="M1088 640c0 -21 -10 -40 -27 -52l-448 -320c-19 -14 -45 -16 -66 -5c-22 11 -35 33 -35 57v640c0 24 13 46 35 57c21 11 47 9 66 -5l448 -320c17 -12 27 -31 27 -52zM1280 160v960c0 18 -14 32 -32 32h-960c-18 0 -32 -14 -32 -32v-960c0 -18 14 -32 32 -32h960
+c18 0 32 14 32 32zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="gitlab" unicode="&#xf296;" horiz-adv-x="1793"
+d="M104 830l792 -1015l-868 630c-24 18 -34 49 -25 77zM566 830h660l-330 -1015zM368 1442l198 -612h-462l198 612c11 31 55 31 66 0zM1688 830l101 -308c9 -28 -1 -59 -25 -77l-868 -630zM1688 830h-462l198 612c11 31 55 31 66 0z" />
+ <glyph glyph-name="arrows" unicode="&#xf047;" horiz-adv-x="1792"
+d="M1792 640c0 -17 -7 -33 -19 -45l-256 -256c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v128h-384v-384h128c35 0 64 -29 64 -64c0 -17 -7 -33 -19 -45l-256 -256c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-256 256c-12 12 -19 28 -19 45c0 35 29 64 64 64h128v384h-384
+v-128c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-256 256c-12 12 -19 28 -19 45s7 33 19 45l256 256c12 12 28 19 45 19c35 0 64 -29 64 -64v-128h384v384h-128c-35 0 -64 29 -64 64c0 17 7 33 19 45l256 256c12 12 28 19 45 19s33 -7 45 -19l256 -256
+c12 -12 19 -28 19 -45c0 -35 -29 -64 -64 -64h-128v-384h384v128c0 35 29 64 64 64c17 0 33 -7 45 -19l256 -256c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="refresh" unicode="&#xf021;"
+d="M1511 480c0 -2 0 -5 -1 -7c-85 -354 -377 -601 -746 -601c-195 0 -384 77 -526 212l-129 -129c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v448c0 35 29 64 64 64h448c35 0 64 -29 64 -64c0 -17 -7 -33 -19 -45l-137 -137c94 -88 219 -138 348 -138
+c178 0 343 92 436 244c24 39 36 77 53 117c5 14 15 23 30 23h192c18 0 32 -15 32 -32zM1536 1280v-448c0 -35 -29 -64 -64 -64h-448c-35 0 -64 29 -64 64c0 17 7 33 19 45l138 138c-95 88 -220 137 -349 137c-178 0 -343 -92 -436 -244c-24 -39 -36 -77 -53 -117
+c-5 -14 -15 -23 -30 -23h-199c-18 0 -32 15 -32 32v7c86 355 381 601 750 601c196 0 387 -78 529 -212l130 129c12 12 28 19 45 19c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="file-o" unicode="&#xf016;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280z" />
+ <glyph glyph-name="battery-three-quarters" unicode="&#xf241;" horiz-adv-x="2304"
+d="M256 256v768h1280v-768h-1280zM2176 960c71 0 128 -57 128 -128v-384c0 -71 -57 -128 -128 -128v-160c0 -88 -72 -160 -160 -160h-1856c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1856c88 0 160 -72 160 -160v-160zM2176 448v384h-128v288c0 18 -14 32 -32 32
+h-1856c-18 0 -32 -14 -32 -32v-960c0 -18 14 -32 32 -32h1856c18 0 32 14 32 32v288h128z" />
+ <glyph glyph-name="reddit-alien" unicode="&#xf281;" horiz-adv-x="1792"
+d="M1792 690c0 -78 -44 -145 -109 -178c8 -31 12 -63 12 -96c0 -316 -357 -572 -797 -572c-439 0 -796 256 -796 572c0 32 4 64 11 94c-67 33 -113 101 -113 180c0 110 89 199 199 199c57 0 108 -24 145 -63c135 94 315 155 515 162l116 521c4 18 23 30 41 26l369 -81
+c24 48 75 82 133 82c83 0 150 -67 150 -149c0 -83 -67 -150 -150 -150c-82 0 -149 67 -149 149l-334 74l-104 -472c201 -6 383 -66 519 -160c36 38 87 61 143 61c110 0 199 -89 199 -199zM418 491c0 -83 67 -150 149 -150c83 0 150 67 150 150c0 82 -67 149 -150 149
+c-82 0 -149 -67 -149 -149zM1228 136c15 15 15 37 0 52c-14 14 -37 14 -51 0c-60 -61 -189 -82 -281 -82s-221 21 -281 82c-14 14 -37 14 -51 0c-15 -14 -15 -37 0 -52c95 -95 278 -102 332 -102s237 7 332 102zM1225 341c82 0 149 67 149 150c0 82 -67 149 -149 149
+c-83 0 -150 -67 -150 -149c0 -83 67 -150 150 -150z" />
+ <glyph glyph-name="square" unicode="&#xf0c8;"
+d="M1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="ellipsis-v" unicode="&#xf142;" horiz-adv-x="384"
+d="M384 288v-192c0 -53 -43 -96 -96 -96h-192c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96zM384 800v-192c0 -53 -43 -96 -96 -96h-192c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96zM384 1312v-192c0 -53 -43 -96 -96 -96h-192
+c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="glide-g" unicode="&#xf2a6;" horiz-adv-x="1461"
+d="M707 1231c0 53 -5 99 -69 99c-27 0 -54 -9 -78 -23c-151 -83 -213 -298 -213 -460c0 -108 37 -252 169 -252c30 0 68 -8 76 27c32 154 64 309 96 463c10 48 19 97 19 146zM1461 575c0 -10 -13 -20 -23 -20l-6 1c-68 10 -128 28 -197 28c-125 0 -240 -37 -351 -93
+c-14 -7 -17 -13 -21 -27c-18 -68 -30 -138 -47 -206c-60 -233 -255 -514 -522 -514c-182 0 -294 124 -294 303c0 97 63 286 180 286c41 0 202 -53 203 -95c-2 -8 -157 -88 -157 -223c0 -41 20 -73 65 -73c159 0 232 290 248 412v9c0 8 -32 4 -38 4c-301 0 -477 168 -477 471
+c0 286 186 635 491 688c35 6 70 9 106 9c242 0 374 -113 374 -360c0 -167 -57 -321 -81 -484l3 -3c108 61 222 119 350 119c13 0 41 -8 53 -13c26 -10 141 -191 141 -219z" />
+ <glyph glyph-name="globe" unicode="&#xf0ac;"
+d="M768 1404c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM737 1186v0c-18 0 -40 -7 -58 -7c-27 0 -61 12 -81 0s-18 -37 -27 -55s-28 -34 -28 -54s19 -36 28 -54s2 -47 27 -54s54 36 81 54s69 32 81 54s0 36 0 54s16 39 0 55
+c-5 5 -14 7 -23 7zM491 1178h-6s-44 -8 -76 -13c-136 -92 -261 -300 -278 -464c23 -12 46 -22 60 -36c27 -27 83 -27 88 -56s-24 -62 -33 -80s-31 -31 -27 -54s36 -36 54 -54s37 -22 54 -54s20 -98 27 -135c9 -47 23 -85 44 -118c27 -19 72 -44 102 -58c10 28 10 93 16 122
+c7 37 13 109 27 135s19 19 28 28s18 15 28 28s17 34 26 52s30 31 26 53s-36 37 -54 55s-29 39 -55 54s-73 18 -101 25s-127 12 -129 13c-2 0 -1 -6 -7 2s-2 39 -2 57s11 34 24 66c13 18 5 10 25 24c10 9 43 -44 57 -44s-3 91 6 100c36 36 128 98 128 136s-37 36 -55 54
+s-46 -30 -111 -30s76 103 85 112s23 17 27 27s0 18 0 27s12 22 8 25c-2 1 -4 1 -6 1zM1212 1096c-62 -8 -139 -10 -182 -26c-45 -17 -54 -36 -81 -54s-67 -28 -81 -54s0 -54 0 -81s-26 -68 0 -82s55 37 82 55s63 64 81 54s6 -7 0 -27s-51 -41 -52 -81s102 -73 68 -126
+s-188 46 -232 17s-19 -54 -28 -81s-37 -52 -27 -81s52 -34 81 -54s81 -56 82 -58s20 -99 27 -135c14 -73 -27 -199 76 -231c31 14 78 41 106 60c13 34 24 72 35 94c22 44 71 123 80 161s0 37 0 55s7 30 0 54s-36 54 -54 81s-34 64 -54 81s-46 18 -54 27s-4 8 -4 13
+s-4 7 5 14s34 8 54 0s36 -36 54 -54s25 -51 54 -54s54 36 81 54c25 17 52 56 76 55c-12 131 -98 312 -193 404z" />
+ <glyph glyph-name="hashnode" unicode="&#xf317;"
+d="M246 1408h1044c136 0 246 -110 246 -246v-1044c0 -136 -110 -246 -246 -246h-1044c-136 0 -246 110 -246 246v1044c0 136 110 246 246 246zM1153 23v0c87 1 158 71 162 158s-62 162 -149 171l-315 556c-46 83 -135 78 -167 -39c-28 -111 -20 -216 -28 -342
+c0 -1 -1 -2 -2 -2s-2 1 -2 1l-281 560c20 16 37 50 37 75c0 52 -41 93 -93 93s-94 -41 -94 -93s42 -93 94 -93c4 0 7 1 11 1c118 -304 250 -659 297 -741c32 -78 141 -53 144 31l12 444c0 3 3 3 4 1l226 -537c-11 -20 -21 -55 -21 -78v-1c0 -91 74 -165 165 -165z" />
+ <glyph glyph-name="comment-o" unicode="&#xf0e5;" horiz-adv-x="1792"
+d="M896 1152c-416 0 -768 -234 -768 -512c0 -149 100 -291 273 -389l87 -50l-27 -96c-19 -71 -44 -126 -70 -172c101 42 193 99 275 171l43 38l57 -6c43 -5 87 -8 130 -8c416 0 768 234 768 512s-352 512 -768 512zM1792 640c0 -354 -401 -640 -896 -640c-49 0 -98 3 -145 8
+c-131 -116 -287 -198 -460 -242c-36 -10 -75 -17 -114 -22h-5c-20 0 -38 16 -43 38v1c-5 25 12 40 27 58c63 71 135 131 182 298c-206 117 -338 298 -338 501c0 354 401 640 896 640s896 -286 896 -640z" />
+ <glyph glyph-name="bluetooth" unicode="&#xf293;" horiz-adv-x="1322"
+d="M734 483l148 -148l-149 -149zM733 1094l149 -149l-148 -148zM603 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1322 640c0 -710 -270 -896 -661 -896s-661 186 -661 896s270 896 661 896s661 -186 661 -896z
+" />
+ <glyph glyph-name="hand-pointer-o" unicode="&#xf25a;" horiz-adv-x="1664"
+d="M640 1408c-71 0 -128 -57 -128 -128v-896l-151 202c-25 33 -65 54 -107 54c-70 0 -126 -59 -126 -128c0 -28 9 -55 26 -77l384 -512c24 -32 62 -51 102 -51h718c29 0 55 20 62 48l92 368c16 64 24 129 24 194v217c0 53 -41 101 -96 101c-53 0 -96 -43 -96 -96h-32v61
+c0 63 -48 115 -112 115c-62 0 -112 -50 -112 -112v-64h-32v90c0 72 -55 134 -128 134c-71 0 -128 -57 -128 -128v-96h-32v570c0 72 -55 134 -128 134zM640 1536c143 0 256 -120 256 -262v-220c11 1 21 2 32 2c65 0 126 -25 173 -69c31 14 65 21 99 21c72 0 139 -32 184 -87
+c19 5 37 7 56 7c126 0 224 -105 224 -229v-217c0 -75 -9 -151 -28 -225l-92 -368c-21 -85 -98 -145 -186 -145h-718c-80 0 -157 39 -205 102l-384 512c-33 44 -51 99 -51 154c0 140 114 256 254 256c46 0 91 -12 130 -35v547c0 141 115 256 256 256zM768 128h-32v384h32
+v-384zM1024 128h-32v384h32v-384zM1280 128h-32v384h32v-384z" />
+ <glyph glyph-name="unlock" unicode="&#xf09c;" horiz-adv-x="1664"
+d="M1664 960v-256c0 -35 -29 -64 -64 -64h-64c-35 0 -64 29 -64 64v256c0 141 -115 256 -256 256s-256 -115 -256 -256v-192h96c53 0 96 -43 96 -96v-576c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v576c0 53 43 96 96 96h672v192c0 247 201 448 448 448
+s448 -201 448 -448z" />
+ <glyph glyph-name="quote-right" unicode="&#xf10e;" horiz-adv-x="1664"
+d="M768 1216v-704c0 -282 -230 -512 -512 -512h-64c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h64c141 0 256 115 256 256v32c0 53 -43 96 -96 96h-224c-106 0 -192 86 -192 192v384c0 106 86 192 192 192h384c106 0 192 -86 192 -192zM1664 1216v-704
+c0 -282 -230 -512 -512 -512h-64c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h64c141 0 256 115 256 256v32c0 53 -43 96 -96 96h-224c-106 0 -192 86 -192 192v384c0 106 86 192 192 192h384c106 0 192 -86 192 -192z" />
+ <glyph glyph-name="arrow-left" unicode="&#xf060;" horiz-adv-x="1472"
+d="M1472 640v-128c0 -68 -45 -128 -117 -128h-704l293 -294c24 -23 38 -56 38 -90s-14 -67 -38 -90l-75 -76c-23 -23 -56 -37 -90 -37s-67 14 -91 37l-651 652c-23 23 -37 56 -37 90s14 67 37 91l651 650c24 24 57 38 91 38s66 -14 90 -38l75 -74c24 -24 38 -57 38 -91
+s-14 -67 -38 -91l-293 -293h704c72 0 117 -60 117 -128z" />
+ <glyph glyph-name="scissors" unicode="&#xf0c4;" horiz-adv-x="1792"
+d="M960 640c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1260 576l507 -398c18 -13 27 -35 25 -56c-3 -22 -16 -41 -35 -51l-128 -64c-9 -5 -19 -7 -29 -7c-11 0 -22 3 -31 8l-690 387l-110 -66c-4 -2 -8 -4 -12 -5c9 -31 13 -64 10 -97
+c-9 -103 -78 -201 -188 -271c-85 -54 -183 -84 -277 -84c-90 0 -166 27 -222 78c-57 53 -86 129 -79 207c9 102 78 201 187 271c85 54 184 84 278 84c56 0 107 -11 151 -31c6 9 13 16 22 22l122 73l-122 73c-9 6 -16 13 -22 22c-44 -20 -95 -31 -151 -31
+c-94 0 -193 30 -278 84c-109 70 -178 169 -187 271c-7 78 22 154 79 206c56 52 132 79 222 79c94 0 192 -30 277 -84c110 -69 179 -168 188 -271c3 -33 -1 -66 -10 -97c4 -1 8 -3 12 -5l110 -66l690 387c9 5 20 8 31 8c10 0 20 -2 29 -7l128 -64c19 -10 32 -29 35 -51
+c2 -21 -7 -43 -25 -56zM579 836c61 56 23 157 -85 225c-61 39 -132 59 -192 59c-46 0 -87 -12 -113 -36c-61 -56 -23 -157 85 -225c61 -39 131 -59 192 -59c46 0 87 12 113 36zM494 91c108 68 146 169 85 225c-26 24 -67 36 -113 36c-61 0 -131 -20 -192 -59
+c-108 -68 -146 -169 -85 -225c26 -24 67 -36 113 -36c60 0 131 20 192 59zM672 704l96 -58v11c0 23 13 44 33 56l14 8l-79 47l-26 -26c-8 -8 -14 -16 -22 -23c-3 -3 -5 -4 -7 -6zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8c2 -3 4 -4 7 -6
+c8 -8 14 -16 22 -24l26 -26zM1600 64l128 64l-520 408l-177 -138c-3 -4 -8 -5 -13 -7z" />
+ <glyph glyph-name="ellipsis-h" unicode="&#xf141;" horiz-adv-x="1408"
+d="M384 800v-192c0 -53 -43 -96 -96 -96h-192c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96zM896 800v-192c0 -53 -43 -96 -96 -96h-192c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96zM1408 800v-192c0 -53 -43 -96 -96 -96h-192
+c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h192c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="scribd" unicode="&#xf28a;" horiz-adv-x="1464"
+d="M1464 -13c0 -119 -96 -216 -216 -216s-217 97 -217 216c0 120 97 217 217 217s216 -97 216 -217zM1231 268c-152 -20 -270 -150 -270 -308c0 -49 12 -97 33 -138c-90 -48 -212 -78 -379 -78c-532 0 -615 376 -615 426c0 51 30 218 218 218s214 -161 214 -194
+c0 0 0 -34 -23 -81c64 -60 215 -60 215 -60c151 0 265 74 265 184c0 111 -128 165 -420 302c-292 138 -402 239 -402 490c0 252 168 507 587 507s577 -235 577 -396s-137 -201 -188 -201c-50 0 -235 -17 -235 261c-33 37 -177 37 -177 37c-145 0 -209 -110 -209 -177
+c0 -68 27 -152 329 -252c463 -154 480 -355 480 -540z" />
+ <glyph glyph-name="exclamation" unicode="&#xf12a;" horiz-adv-x="444"
+d="M414 288v-224c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v224c0 35 29 64 64 64h256c35 0 64 -29 64 -64zM444 1344l-28 -768c-1 -35 -31 -64 -66 -64h-256c-35 0 -65 29 -66 64l-28 768c-1 35 27 64 62 64h320c35 0 63 -29 62 -64z" />
+ <glyph glyph-name="try" unicode="&#xf195;" horiz-adv-x="1152"
+d="M1152 704c0 -388 -316 -704 -704 -704h-160c-18 0 -32 14 -32 32v611l-215 -66c-3 -1 -6 -1 -9 -1c-7 0 -13 2 -19 6c-8 6 -13 16 -13 26v128c0 14 9 26 23 31l233 71v93l-215 -66c-3 -1 -6 -1 -9 -1c-7 0 -13 2 -19 6c-8 6 -13 16 -13 26v128c0 14 9 26 23 31l233 71
+v250c0 18 14 32 32 32h160c18 0 32 -14 32 -32v-181l375 116c9 3 20 1 28 -5s13 -16 13 -26v-128c0 -14 -9 -26 -23 -31l-393 -121v-93l375 116c9 3 20 1 28 -5s13 -16 13 -26v-128c0 -14 -9 -26 -23 -31l-393 -121v-487c250 17 448 225 448 479c0 18 14 32 32 32h160
+c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="assistive-listening-systems" unicode="&#xf2a2;" horiz-adv-x="1792"
+d="M128 -192c0 -35 -29 -64 -64 -64s-64 29 -64 64s29 64 64 64s64 -29 64 -64zM320 0c0 -35 -29 -64 -64 -64s-64 29 -64 64s29 64 64 64s64 -29 64 -64zM365 365l256 -256l-90 -90l-256 256zM704 384c0 -35 -29 -64 -64 -64s-64 29 -64 64s29 64 64 64s64 -29 64 -64z
+M1411 704c0 -166 -78 -255 -146 -334c-63 -72 -113 -129 -113 -242c0 -212 -172 -384 -384 -384c-35 0 -64 29 -64 64s29 64 64 64c141 0 256 115 256 256c0 161 77 249 144 326c62 71 115 132 115 250c0 247 -201 448 -448 448s-448 -201 -448 -448c0 -35 -29 -64 -64 -64
+s-64 29 -64 64c0 318 258 576 576 576s576 -258 576 -576zM896 576c0 -35 -29 -64 -64 -64s-64 29 -64 64s29 64 64 64s64 -29 64 -64zM1184 704c0 -35 -29 -64 -64 -64s-64 29 -64 64c0 124 -100 224 -224 224c-123 0 -224 -100 -224 -224c0 -35 -29 -64 -64 -64
+s-64 29 -64 64c0 194 158 352 352 352s352 -158 352 -352zM1578 993c13 -33 -4 -70 -37 -83c-7 -3 -15 -4 -23 -4c-25 0 -50 15 -59 41c-45 117 -123 219 -224 295c-28 21 -34 61 -13 89c22 28 62 34 90 13c120 -90 212 -212 266 -351zM1788 1074c12 -33 -4 -70 -37 -83
+c-8 -3 -15 -4 -23 -4c-26 0 -50 15 -60 41c-60 156 -163 292 -297 393c-29 21 -34 61 -13 89c21 29 61 34 89 13c154 -115 272 -271 341 -449z" />
+ <glyph glyph-name="flag-o" unicode="&#xf11d;" horiz-adv-x="1728"
+d="M1600 491v616c-80 -43 -192 -91 -306 -91c-53 0 -102 10 -145 32c-107 53 -223 104 -362 104c-129 0 -287 -63 -403 -127v-599c132 61 300 113 433 113c154 0 254 -51 361 -104l28 -14c28 -14 62 -22 101 -22c111 0 231 59 293 92zM256 1280c0 -47 -26 -88 -64 -110
+v-1266c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v1266c-38 22 -64 63 -64 110c0 71 57 128 128 128s128 -57 128 -128zM1728 1216v-763c0 -24 -14 -46 -35 -57c-4 -2 -10 -5 -17 -9c-64 -34 -215 -116 -369 -116c-59 0 -112 12 -158 35l-28 14
+c-101 51 -181 91 -304 91c-144 0 -347 -75 -464 -146c-10 -6 -22 -9 -33 -9s-22 3 -32 8c-20 12 -32 33 -32 56v742c0 22 12 43 31 55c64 38 290 163 500 163c167 0 303 -61 418 -117c26 -13 56 -19 89 -19c118 0 248 75 310 112c13 7 24 13 31 17c20 10 43 9 62 -2
+c19 -12 31 -33 31 -55z" />
+ <glyph glyph-name="wikipedia-w" unicode="&#xf266;" horiz-adv-x="2304"
+d="M1494 -103l-295 695c-117 -229 -246 -468 -357 -695c-1 -1 -54 0 -54 1c-169 395 -346 787 -515 1183c-41 96 -178 252 -272 251c0 11 -1 36 -1 51h583v-50c-69 -4 -190 -48 -156 -123c79 -179 373 -865 452 -1039c54 107 208 393 271 514c-50 102 -211 482 -262 576
+c-35 64 -130 70 -201 71v50l513 -1v-47c-70 -2 -137 -28 -106 -94c68 -144 110 -245 173 -377c20 39 125 250 173 363c32 74 -14 103 -139 106c1 13 0 37 1 49c160 1 400 1 443 2v-49c-81 -3 -165 -46 -209 -114l-213 -442c23 -58 228 -514 249 -564l441 1017
+c-31 83 -131 101 -170 102v50l460 -4l1 -2l-1 -44c-101 -3 -162 -57 -201 -145c-90 -208 -372 -864 -559 -1291h-49z" />
+ <glyph glyph-name="battery-quarter" unicode="&#xf243;" horiz-adv-x="2304"
+d="M256 256v768h512v-768h-512zM2176 960c71 0 128 -57 128 -128v-384c0 -71 -57 -128 -128 -128v-160c0 -88 -72 -160 -160 -160h-1856c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1856c88 0 160 -72 160 -160v-160zM2176 448v384h-128v288c0 18 -14 32 -32 32h-1856
+c-18 0 -32 -14 -32 -32v-960c0 -18 14 -32 32 -32h1856c18 0 32 14 32 32v288h128z" />
+ <glyph glyph-name="print" unicode="&#xf02f;" horiz-adv-x="1664"
+d="M384 0h896v256h-896v-256zM384 640h896v384h-160c-53 0 -96 43 -96 96v160h-640v-640zM1536 576c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1664 576v-416c0 -17 -15 -32 -32 -32h-224v-160c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v160
+h-224c-17 0 -32 15 -32 32v416c0 105 87 192 192 192h64v544c0 53 43 96 96 96h672c53 0 126 -30 164 -68l152 -152c38 -38 68 -111 68 -164v-256h64c105 0 192 -87 192 -192z" />
+ <glyph glyph-name="tipeee" unicode="&#xf301;" horiz-adv-x="2304"
+d="M116 1259h2072c64 0 116 -52 116 -116v-1006c0 -64 -52 -116 -116 -116h-2072c-64 0 -116 52 -116 116v1006c0 64 52 116 116 116zM756 1006v0c-59 0 -90 -47 -90 -85c0 -40 37 -84 90 -84c59 0 92 38 92 84c0 38 -34 85 -92 85zM1672 966v-159l45 -211h110l45 211v159
+h-200zM534 925l-154 -49v-77h-45v-109h45v-148c3 -107 7 -176 132 -176c19 0 77 6 102 16v107c-16 -7 -42 -14 -53 -14c-33 0 -27 39 -27 67v148h80v109h-80v126zM1212 806v0c-50 0 -85 -24 -101 -36l-14 29h-192v-111h35v-368h-35v-109h250v109h-45v85c6 -5 40 -33 109 -33
+c108 0 190 82 190 215c0 119 -67 219 -197 219zM643 799v-109h35v-199h-35v-110h234v110h-40v308h-194zM1169 688v0c37 0 61 -53 61 -103c0 -64 -25 -104 -60 -104c-32 0 -60 43 -60 100c-3 66 26 107 59 107zM1764 555c-60 0 -95 -47 -95 -89c0 -43 41 -86 95 -86
+c61 0 99 39 99 86c0 48 -40 89 -99 89z" />
+ <glyph glyph-name="check-circle-o" unicode="&#xf05d;"
+d="M1171 723l-422 -422c-25 -25 -65 -25 -90 0l-294 294c-25 25 -25 65 0 90l102 102c25 25 65 25 90 0l147 -147l275 275c25 25 65 25 90 0l102 -102c25 -25 25 -65 0 -90zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544s544 244 544 544z
+M1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="level-up" unicode="&#xf148;" horiz-adv-x="1024"
+d="M1018 933c-11 -23 -33 -37 -58 -37h-192v-864c0 -18 -14 -32 -32 -32h-704c-12 0 -24 7 -29 18c-5 12 -4 25 4 35l160 192c6 7 16 11 25 11h320v640h-192c-25 0 -47 14 -58 37c-10 22 -7 49 9 68l320 384c24 29 74 29 98 0l320 -384c16 -19 20 -46 9 -68z" />
+ <glyph glyph-name="houzz" unicode="&#xf27c;" horiz-adv-x="1024"
+d="M512 345l512 295v-591l-512 -296v592zM0 640l512 -295l-512 -296v591zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+ <glyph glyph-name="lemon-o" unicode="&#xf094;" horiz-adv-x="1535"
+d="M1407 710c0 47 -9 170 -25 210c-19 48 -30 75 -30 129c0 46 10 91 10 136c0 19 -1 39 -10 55c-4 1 -9 1 -13 1c-39 0 -78 -9 -117 -9c-119 0 -232 48 -351 48c-93 0 -183 -35 -269 -69c-68 -27 -143 -59 -202 -103c-202 -153 -272 -433 -272 -674c0 -81 25 -160 25 -241
+c0 -46 -22 -88 -22 -132c0 -28 16 -51 46 -51c49 0 96 22 146 22c114 0 225 -31 339 -31c89 0 201 7 284 36c263 93 461 397 461 673zM1535 712c0 -333 -231 -684 -547 -796c-99 -35 -222 -44 -326 -44c-114 0 -226 29 -339 29c-48 0 -96 -29 -146 -29
+c-99 0 -174 89 -174 184c0 47 22 89 22 135c0 81 -25 160 -25 242c0 284 87 598 323 777c68 52 153 89 232 120c102 41 205 78 316 78c119 0 232 -48 349 -48c38 0 76 10 115 10c114 0 155 -81 155 -185c0 -45 -10 -91 -10 -136c0 -36 9 -50 21 -82c23 -58 34 -191 34 -255z
+" />
+ <glyph glyph-name="umbrella" unicode="&#xf0e9;" horiz-adv-x="1664"
+d="M896 708v-580c0 -139 -117 -256 -256 -256s-256 117 -256 256c0 35 29 64 64 64s64 -29 64 -64c0 -67 61 -128 128 -128s128 61 128 128v580c21 7 42 11 64 11s43 -4 64 -11zM1664 681c0 -17 -15 -32 -32 -32c-9 0 -16 4 -23 10c-58 54 -112 92 -195 92
+c-95 0 -177 -59 -231 -134c-12 -17 -21 -35 -32 -52c-7 -11 -15 -17 -28 -17c-14 0 -22 6 -29 17c-11 17 -20 35 -32 52c-54 75 -135 134 -230 134s-176 -59 -230 -134c-12 -17 -21 -35 -32 -52c-7 -11 -15 -17 -29 -17c-13 0 -21 6 -28 17c-11 17 -20 35 -32 52
+c-54 75 -136 134 -231 134c-83 0 -137 -38 -195 -92c-7 -6 -14 -10 -23 -10c-17 0 -32 15 -32 32c0 3 0 5 1 7c92 378 457 592 831 592c372 0 741 -214 831 -592c1 -2 1 -4 1 -7zM896 1408v-98c-21 1 -43 2 -64 2s-43 -1 -64 -2v98c0 35 29 64 64 64s64 -29 64 -64z" />
+ <glyph glyph-name="bell-o" unicode="&#xf0a2;" horiz-adv-x="1664"
+d="M848 -160c0 9 -7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176c9 0 16 7 16 16zM1664 128c0 -70 -58 -128 -128 -128h-448c0 -141 -115 -256 -256 -256s-256 115 -256 256h-448c-70 0 -128 58 -128 128
+c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c265 -39 424 -249 424 -441c0 -483 172 -707 320 -832z" />
+ <glyph glyph-name="shaarli" unicode="&#xf2f5;" horiz-adv-x="1651"
+d="M878 1408c161 0 254 -160 278 -479h66c287 -44 429 -135 426 -273c24 -163 -80 -238 -312 -226c178 -156 241 -302 191 -437c-39 -108 -133 -143 -282 -107c-164 82 -281 176 -349 282h-43c-64 -188 -188 -282 -372 -282h-64c-153 47 -209 140 -166 278l80 221h-23
+c-225 32 -326 131 -305 298c6 153 160 231 462 233c84 9 119 36 105 80c0 275 103 412 308 412zM830 1182c-56 4 -83 -72 -82 -227l-5 -128c-5 -64 -25 -96 -61 -96l-360 -20c-56 -2 -85 -25 -85 -69c0 -43 31 -65 92 -68c211 11 310 -4 296 -43l-64 -137
+c-108 -163 -135 -258 -80 -287c73 -44 176 70 310 342c32 29 59 29 80 0c94 -100 171 -182 232 -246c62 -64 113 -83 151 -57c46 49 33 101 -37 157c-68 58 -146 137 -234 237c-9 33 -8 50 6 50c298 -20 441 -1 429 57c9 64 -121 96 -388 96c-41 -8 -74 2 -100 29v224
+c0 125 -30 186 -89 184c-3 1 -8 2 -11 2v0z" />
+ <glyph glyph-name="cc-diners-club" unicode="&#xf24c;" horiz-adv-x="2304"
+d="M858 295v693c-139 -54 -238 -189 -238 -347s99 -293 238 -346zM1362 641c0 158 -99 293 -238 347v-694c139 54 238 189 238 347zM1577 641c0 -323 -262 -586 -586 -586c-323 0 -586 263 -586 586c0 324 263 586 586 586c324 0 586 -262 586 -586zM1960 634
+c0 382 -319 646 -669 646h-301c-354 0 -646 -264 -646 -646c0 -349 292 -634 646 -634h301c350 0 669 285 669 634zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h2048c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="undo" unicode="&#xf0e2;"
+d="M1536 640c0 -423 -345 -768 -768 -768c-229 0 -445 101 -591 277c-10 13 -9 32 2 43l137 138c7 6 16 9 25 9c9 -1 18 -5 23 -12c98 -127 245 -199 404 -199c282 0 512 230 512 512s-230 512 -512 512c-131 0 -255 -50 -348 -137l137 -138c19 -18 24 -46 14 -69
+c-10 -24 -33 -40 -59 -40h-448c-35 0 -64 29 -64 64v448c0 26 16 49 40 59c23 10 51 5 69 -14l130 -129c141 133 332 212 529 212c423 0 768 -345 768 -768z" />
+ <glyph glyph-name="rebel" unicode="&#xf1d0;" horiz-adv-x="1756"
+d="M0 662c10 286 156 550 421 724c1 0 7 2 4 -3c-21 -20 -402 -469 -51 -818c180 -179 325 -9 325 -9c139 181 -2 455 -2 455c-36 90 -165 145 -165 145l104 115c88 -38 156 -140 156 -140c3 107 -79 222 -79 222l161 183l160 -181c-74 -104 -79 -226 -79 -226
+c50 83 157 142 157 142l103 -115c-99 -32 -164 -144 -164 -144c-57 -103 -98 -323 2 -460c117 -161 317 10 317 10c371 332 -38 813 -38 813c-22 20 3 10 3 10c181 -132 414 -305 420 -740c7 -526 -361 -901 -876 -901c-503 0 -894 420 -879 918z" />
+ <glyph glyph-name="codiepie" unicode="&#xf284;" horiz-adv-x="1723"
+d="M1584 246l-218 111c-98 -160 -272 -258 -460 -258c-298 0 -539 241 -539 538c0 298 241 539 539 539c175 0 339 -85 440 -229l215 125c-147 226 -396 361 -665 361c-438 0 -793 -355 -793 -793s355 -793 793 -793c284 0 547 152 688 399zM1030 643l693 -352
+c-152 -332 -457 -547 -827 -547c-495 0 -896 401 -896 896s401 896 896 896c352 0 642 -194 806 -500zM1543 640h-39v-160h-96v352h136c111 0 121 -192 -1 -192z" />
+ <glyph glyph-name="soundcloud" unicode="&#xf1be;" horiz-adv-x="2304"
+d="M784 164c-1 -13 -11 -23 -24 -23c-12 0 -22 10 -23 23l-14 241l14 523c0 13 11 24 23 24c13 0 23 -11 24 -24l16 -523zM1080 193l-1 -24c0 -8 -3 -15 -9 -20c-5 -5 -12 -9 -20 -9c-9 0 -17 4 -23 11c-4 5 -6 11 -6 17v1c-11 235 -11 236 -11 236l10 579l1 6
+c0 10 5 19 13 24c5 3 10 5 16 5s11 -2 16 -5c8 -5 13 -14 13 -24l12 -586zM35 533l20 -128l-20 -126c-1 -5 -4 -9 -9 -9s-8 4 -9 9l-17 126l17 128c1 5 4 9 9 9s8 -4 9 -9zM121 612l26 -207l-26 -203c-1 -5 -5 -9 -10 -9s-9 4 -9 10l-23 202l23 207c0 5 4 9 9 9s9 -4 10 -9z
+M401 159zM213 650l25 -245l-25 -237c0 -6 -5 -11 -11 -11s-11 5 -12 11l-21 237l21 245c1 7 6 12 12 12s11 -5 11 -12zM307 657l23 -252l-23 -244c-1 -8 -7 -13 -14 -13s-13 5 -13 13l-21 244l21 252c0 8 6 13 13 13s13 -5 14 -13zM401 639l21 -234l-21 -246
+c-1 -9 -8 -16 -16 -16s-15 7 -15 16l-20 246l20 234c0 8 7 15 15 15s15 -7 16 -15zM784 164zM495 785l21 -380l-21 -246c0 -10 -8 -18 -17 -18c-10 0 -17 8 -18 18l-18 246l18 380c1 10 8 18 18 18c9 0 17 -8 17 -18zM589 871l19 -468l-19 -244c0 -11 -9 -19 -19 -19
+c-11 0 -19 8 -20 19l-16 244l16 468c1 11 9 19 20 19c10 0 19 -8 19 -19zM687 911l18 -506l-18 -242c-1 -12 -10 -21 -22 -21c-11 0 -20 9 -21 21l-16 242l16 506c0 12 10 22 21 22c12 0 21 -10 22 -22zM1079 169zM881 915l15 -510l-15 -239c0 -14 -11 -25 -25 -25
+s-24 11 -25 25l-14 239l14 510c0 14 11 25 25 25s25 -11 25 -25zM980 896l14 -492l-14 -236c0 -15 -12 -27 -27 -27s-27 12 -28 27l-12 236l12 492c1 16 13 28 28 28s26 -12 27 -28zM1192 404l-14 -231c0 -17 -14 -31 -31 -31s-31 14 -32 31l-6 114l-6 117l12 636v3
+c1 9 5 18 12 24c5 4 12 7 20 7c5 0 11 -2 15 -5c9 -5 15 -15 16 -26zM2304 423c0 -156 -127 -282 -283 -282h-786c-17 2 -31 15 -31 33v899c0 17 6 25 28 33c55 22 117 34 181 34c261 0 475 -200 498 -455c34 14 71 22 110 22c156 0 283 -127 283 -284z" />
+ <glyph glyph-name="microphone" unicode="&#xf130;" horiz-adv-x="1152"
+d="M1152 832v-128c0 -296 -224 -540 -512 -572v-132h256c35 0 64 -29 64 -64s-29 -64 -64 -64h-640c-35 0 -64 29 -64 64s29 64 64 64h256v132c-288 32 -512 276 -512 572v128c0 35 29 64 64 64s64 -29 64 -64v-128c0 -247 201 -448 448 -448s448 201 448 448v128
+c0 35 29 64 64 64s64 -29 64 -64zM896 1216v-512c0 -176 -144 -320 -320 -320s-320 144 -320 320v512c0 176 144 320 320 320s320 -144 320 -320z" />
+ <glyph glyph-name="laravel" unicode="&#xf30b;" horiz-adv-x="1870"
+d="M1863 682v0c13 -14 10 -25 -13 -31c-20 -6 -203 -54 -255 -68c76 -101 219 -294 231 -312c17 -25 2 -32 -23 -42s-571 -207 -608 -218c-48 -14 -69 -21 -100 22c-23 33 -149 259 -211 371c-117 -30 -330 -86 -392 -101c-60 -14 -86 22 -96 44s-365 786 -387 839
+c-23 53 2 62 24 64s335 28 376 30s44 -8 62 -34l450 -753l566 136c-31 44 -173 246 -187 265c-15 22 0 32 25 36s242 41 261 44s33 9 63 -27s201 -251 214 -265zM834 472c7 1 10 5 3 18s-422 729 -422 729c-4 7 -3 9 -13 9s-305 -27 -310 -27s-5 -8 0 -18s380 -783 382 -789
+s2 -8 19 -4s334 81 341 82zM1728 304c-5 8 -178 244 -187 258s-13 10 -27 6l-552 -143s169 -293 182 -312s21 -17 31 -13s531 179 547 185s11 11 6 19zM1763 696c13 3 22 7 16 14s-149 189 -159 203s-18 12 -27 10c-8 -2 -196 -36 -208 -38s-8 -8 -3 -15l166 -227
+s202 50 215 53z" />
+ <glyph glyph-name="indent" unicode="&#xf03c;" horiz-adv-x="1792"
+d="M352 704c0 -8 -3 -17 -9 -23l-288 -288c-6 -6 -15 -9 -23 -9c-17 0 -32 15 -32 32v576c0 17 15 32 32 32c8 0 17 -3 23 -9l288 -288c6 -6 9 -15 9 -23zM1792 224v-192c0 -17 -15 -32 -32 -32h-1728c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1728c17 0 32 -15 32 -32z
+M1792 608v-192c0 -17 -15 -32 -32 -32h-1088c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1088c17 0 32 -15 32 -32zM1792 992v-192c0 -17 -15 -32 -32 -32h-1088c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1088c17 0 32 -15 32 -32zM1792 1376v-192c0 -17 -15 -32 -32 -32
+h-1728c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1728c17 0 32 -15 32 -32z" />
+ <glyph glyph-name="address-card-o" unicode="&#xf2bc;" horiz-adv-x="2048"
+d="M1024 405c0 -87 -57 -149 -128 -149h-512c-71 0 -128 62 -128 149c0 155 38 327 196 327c49 -28 115 -76 188 -76s139 48 188 76c158 0 196 -172 196 -327zM867 925c0 -126 -102 -227 -227 -227s-227 101 -227 227c0 125 102 227 227 227s227 -102 227 -227zM1792 480
+v-64c0 -18 -14 -32 -32 -32h-576c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h576c18 0 32 -14 32 -32zM1792 732v-56c0 -20 -16 -36 -36 -36h-568c-20 0 -36 16 -36 36v56c0 20 16 36 36 36h568c20 0 36 -16 36 -36zM1792 992v-64c0 -18 -14 -32 -32 -32h-576
+c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h576c18 0 32 -14 32 -32zM1920 32v1216c0 17 -15 32 -32 32h-1728c-17 0 -32 -15 -32 -32v-1216c0 -17 15 -32 32 -32h352v96c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-96h768v96c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-96h352
+c17 0 32 15 32 32zM2048 1248v-1216c0 -88 -72 -160 -160 -160h-1728c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1728c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="language" unicode="&#xf1ab;"
+d="M654 458c-2 -7 -51 16 -64 21c-13 6 -72 39 -87 49s-72 57 -79 60c-36 -55 -82 -120 -134 -181c-18 -21 -72 -89 -105 -110c-5 -3 -34 -6 -38 -4c16 12 62 69 82 92c25 29 144 195 164 233c21 38 84 164 87 176c-10 1 -89 -26 -110 -33c-20 -6 -75 -19 -79 -22
+c-4 -4 -1 -16 -3 -20s-20 -13 -31 -15c-10 -3 -33 -4 -47 0c-13 3 -25 16 -28 21c0 0 -4 6 -5 23c12 4 32 5 54 11s76 22 105 32s85 31 102 35c18 3 63 33 87 41s41 18 42 13s0 -27 -1 -33c-1 -5 -49 -99 -56 -114c-4 -8 -32 -61 -77 -131c16 -7 50 -21 64 -28
+c17 -8 136 -58 142 -60s17 -48 15 -56zM449 944c3 -17 -2 -24 -4 -28c-10 -19 -35 -32 -50 -38s-40 -12 -60 -12c-9 1 -27 4 -49 26c-12 13 -21 48 -17 44s33 -8 46 -5s44 12 58 16c15 5 45 13 55 14c10 0 18 -4 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032
+l-694 -233v-1031zM1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66c-81 -52 -181 -92 -276 -108c-29 -6 -62 -12 -91 -12h-84c-106 0 -299 63 -383 124c-6 5 -8 9 -8 16c0 11 8 19 18 19
+c9 0 56 -29 69 -35c90 -45 216 -86 317 -86c125 0 210 16 324 65c33 15 62 34 93 51zM1536 1050v-1079c-773 246 -774 246 -774 246c-16 -7 -733 -249 -743 -249c-8 0 -15 5 -18 13c0 1 -1 2 -1 3v1078c1 3 2 8 4 10c6 7 14 9 20 11c3 1 64 21 149 50v384l558 -198
+c7 2 629 217 638 217c11 0 20 -8 20 -21v-418z" />
+ <glyph glyph-name="circle-thin" unicode="&#xf1db;"
+d="M768 1280c-353 0 -640 -287 -640 -640s287 -640 640 -640s640 287 640 640s-287 640 -640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="drupal" unicode="&#xf1a9;"
+d="M1167 -50c-2 7 -8 17 -24 5c-34 -25 -110 -56 -218 -56s-159 23 -193 49c-5 4 -3 4 -13 4c-11 0 -17 -5 -26 -12c-8 -7 -12 -24 0 -36c74 -68 198 -62 289 -54c92 9 170 63 178 71c12 12 9 22 7 29zM1128 65c-7 17 -19 47 -39 61c-20 13 -49 15 -76 15s-42 2 -71 -10
+s-59 -39 -78 -56s-22 -30 -12 -44c10 -13 21 -5 49 19c29 23 48 44 107 44s69 -22 81 -44s13 -25 25 -19c14 7 21 17 14 34zM1483 346c0 52 -23 140 -108 140c-80 0 -242 -166 -327 -167c-99 -2 -236 196 -434 194c-156 -1 -279 -125 -281 -257c-1 -74 23 -129 74 -164
+c34 -23 65 -37 166 -37c168 0 381 208 479 205c78 -3 199 -194 260 -198c48 -4 73 18 114 77c40 60 57 154 57 207zM1536 506c0 -448 -354 -744 -761 -744c-408 0 -775 321 -775 758c0 436 340 638 403 671c75 40 129 61 214 129c42 33 77 81 88 198
+c61 -73 134 -158 186 -193c85 -56 170 -78 259 -134c54 -33 386 -236 386 -685z" />
+ <glyph glyph-name="headphones" unicode="&#xf025;" horiz-adv-x="1664"
+d="M1664 650c0 -109 -20 -215 -60 -314l-20 -49l-185 -33c-29 -109 -128 -190 -247 -190v-32c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-32c96 0 179 -53 223 -131l68 12c19 62 29 126 29 193c0 302 -299 566 -640 566
+s-640 -264 -640 -566c0 -67 10 -131 29 -193l68 -12c44 78 127 131 223 131v32c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-576c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v32c-119 0 -218 81 -247 190l-185 33l-20 49c-40 99 -60 205 -60 314c0 411 381 758 832 758
+s832 -347 832 -758z" />
+ <glyph glyph-name="cc-mastercard" unicode="&#xf1f1;" horiz-adv-x="2304"
+d="M1119 1195c-83 55 -181 85 -281 85c-281 0 -509 -228 -509 -508c0 -281 228 -509 509 -509c100 0 198 30 281 85c-268 218 -266 629 0 847zM1152 1171c-258 -203 -259 -597 0 -799c259 202 258 596 0 799zM1185 1195c265 -218 269 -630 0 -847c83 -55 182 -85 281 -85
+c281 0 509 228 509 509c0 280 -228 508 -509 508c-100 0 -198 -30 -281 -85zM1926 473h7v3h-17v-3h7v-17h3v17zM1955 456h4v20h-5l-6 -13l-6 13h-5v-20h3v15l6 -13h4l5 13v-15zM1947 16v-2h-5v3h5v-1zM1947 7h3l-4 5c2 0 2 1 3 1c1 1 1 2 1 3s0 2 -1 3c-1 0 -2 1 -4 1h-6
+v-13h3v5h1zM685 75c0 24 15 43 41 43c24 0 40 -19 40 -43c0 -25 -16 -43 -40 -43c-26 0 -41 19 -41 43zM1158 119c19 0 32 -11 35 -32h-70c3 19 15 32 35 32zM1514 75c0 24 15 43 40 43s41 -19 41 -43c0 -25 -16 -43 -41 -43s-40 19 -40 43zM1786 75c0 24 16 43 41 43
+c24 0 41 -19 41 -43c0 -25 -17 -43 -41 -43c-25 0 -41 19 -41 43zM1944 3c-1 0 -2 0 -4 1c-1 0 -2 1 -3 2s-2 2 -2 3c-1 2 -1 3 -1 4c0 2 0 3 1 4c0 2 1 3 2 4s2 1 3 2c2 1 3 1 4 1c2 0 3 0 4 -1c2 -1 3 -1 4 -2s1 -2 2 -4c0 -1 1 -2 1 -4c0 -1 -1 -2 -1 -4
+c-1 -1 -1 -2 -2 -3s-2 -2 -4 -2c-1 -1 -2 -1 -4 -1zM599 7h30v85c0 32 -21 53 -54 54c-17 0 -35 -5 -47 -24c-9 15 -24 24 -45 24c-14 0 -28 -5 -39 -20v16h-30v-135h30v75c0 24 13 36 33 36s30 -13 30 -36v-75h29v75c0 24 14 36 33 36c20 0 30 -13 30 -36v-75zM765 7h29
+v135h-29v-16c-10 12 -24 20 -43 20c-38 0 -67 -30 -67 -71s29 -71 67 -71c19 0 33 7 43 20v-17zM943 48c0 24 -18 36 -47 40l-14 2c-13 2 -23 5 -23 14s9 15 25 15c18 0 34 -6 43 -11l12 24c-14 9 -33 14 -55 14c-34 0 -56 -17 -56 -44c0 -22 16 -35 47 -39l13 -2
+c17 -3 24 -7 24 -14c0 -11 -11 -17 -31 -17s-35 7 -45 14l-13 -23c16 -11 36 -17 58 -17c39 0 62 18 62 44zM1073 14l-8 25c-9 -5 -18 -7 -26 -7c-15 0 -19 9 -19 22v61h48v27h-48v41h-30v-41h-28v-27h28v-61c0 -31 12 -50 47 -50c12 0 27 4 36 10zM1159 146
+c-39 0 -67 -29 -67 -71c0 -43 29 -71 69 -71c20 0 39 5 55 19l-14 22c-11 -9 -26 -15 -39 -15c-19 0 -36 9 -41 33h101v12c0 42 -26 71 -64 71zM1318 146c-17 0 -28 -8 -35 -20v16h-30v-135h30v76c0 22 9 35 29 35c6 0 12 -1 18 -4l9 28c-7 3 -15 4 -21 4zM1348 75
+c0 -41 28 -71 72 -71c20 0 34 4 48 16l-14 24c-11 -8 -22 -13 -35 -12c-24 0 -41 17 -41 43s17 43 41 43c13 0 24 -4 35 -12l14 24c-14 11 -28 16 -48 16c-44 0 -72 -30 -72 -71zM1593 7h30v135h-30v-16c-9 12 -23 20 -42 20c-38 0 -68 -30 -68 -71s30 -71 68 -71
+c19 0 33 7 42 20v-17zM1726 146c-17 0 -28 -8 -35 -20v16h-29v-135h29v76c0 22 10 35 29 35c6 0 12 -1 18 -4l9 28c-6 3 -15 4 -21 4zM1866 7h29v190h-29v-71c-9 12 -23 20 -43 20c-37 0 -67 -30 -67 -71s30 -71 67 -71c20 0 34 7 43 20v-17zM1944 27c-1 0 -3 -1 -5 -1
+c-2 -1 -3 -2 -4 -3c-2 -1 -3 -3 -3 -4c-1 -2 -1 -4 -1 -6c0 -1 0 -3 1 -5c0 -1 1 -3 3 -4c1 -1 2 -2 4 -3s4 -1 5 -1c2 0 4 0 6 1c1 1 3 2 4 3s2 3 3 4c1 2 1 4 1 5c0 2 0 4 -1 6c-1 1 -2 3 -3 4s-3 2 -4 3c-2 0 -4 1 -6 1zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048
+c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h2048c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="times" unicode="&#xf00d;" horiz-adv-x="1188"
+d="M1188 214c0 -25 -10 -50 -28 -68l-136 -136c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-294 294l-294 -294c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-136 136c-18 18 -28 43 -28 68s10 50 28 68l294 294l-294 294c-18 18 -28 43 -28 68s10 50 28 68l136 136
+c18 18 43 28 68 28s50 -10 68 -28l294 -294l294 294c18 18 43 28 68 28s50 -10 68 -28l136 -136c18 -18 28 -43 28 -68s-10 -50 -28 -68l-294 -294l294 -294c18 -18 28 -43 28 -68z" />
+ <glyph glyph-name="buysellads" unicode="&#xf20d;"
+d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960c0 -158 -130 -288 -288 -288h-960c-158 0 -288 130 -288 288v960c0 158 130 288 288 288h960c158 0 288 -130 288 -288z" />
+ <glyph glyph-name="diaspora" unicode="&#xf2e5;" horiz-adv-x="1581"
+d="M1005 -16c-42 59 -111 155 -153 214c-41 57 -75 102 -77 102s-66 -87 -152 -205c-82 -113 -150 -205 -151 -205c-2 0 -296 207 -297 209c0 1 65 99 147 217s149 217 149 219c0 4 -27 14 -234 83c-129 43 -235 78 -237 79s10 41 52 174c30 95 56 174 57 175
+s112 -35 248 -80s249 -81 250 -81s2 2 3 5s2 118 3 257s2 254 3 255c1 2 40 2 180 2c98 0 179 0 180 -1c2 -1 4 -78 8 -249c7 -281 9 -285 13 -285c2 0 109 36 239 80s236 79 237 78c3 -3 109 -350 108 -351s-109 -37 -241 -82c-181 -61 -240 -82 -240 -85
+c0 -2 62 -95 141 -211c78 -114 141 -208 141 -209c-1 -2 -293 -217 -295 -217c-1 0 -38 50 -82 112z" />
+ <glyph glyph-name="att" unicode="&#xf31e;"
+d="M768 1407v0c144 0 278 -39 393 -108c31 -19 46 -30 46 -48c0 -73 -206 -150 -472 -150c-268 0 -419 70 -419 135c0 22 19 39 54 60c116 71 253 111 398 111zM273 1226v0c1 0 0 -1 -1 -2c-22 -27 -31 -53 -31 -79c0 -72 57 -185 362 -185c416 0 677 151 677 236
+c0 7 -2 13 -5 18c-1 1 0 2 1 1c25 -23 48 -46 73 -74c38 -43 53 -66 53 -104c0 -107 -166 -228 -539 -228c-350 0 -725 108 -725 257c0 10 10 28 25 47c32 41 68 78 108 112c1 0 2 1 2 1zM1456 979v0s1 0 1 -1c18 -36 40 -89 51 -133c10 -40 10 -69 2 -97
+c-43 -152 -307 -235 -646 -235c-556 0 -794 160 -841 260c-6 12 -7 20 -4 37c7 39 32 114 55 159c1 1 1 1 1 0c-4 -15 -6 -30 -6 -45c0 -153 253 -274 557 -274c281 0 837 129 830 328v1zM1534 683v0s1 -1 1 -2c1 -13 1 -25 1 -41c0 -67 -9 -146 -28 -190
+c-26 -61 -154 -248 -714 -248c-411 0 -649 139 -744 238c-21 22 -36 49 -39 67c-7 36 -11 91 -11 133c0 2 2 2 2 0c34 -125 219 -308 612 -308c413 0 891 200 919 350c0 1 1 1 1 1zM1482 360v0c1 0 1 -1 1 -2c-13 -33 -30 -67 -47 -96c-29 -50 -61 -86 -95 -114
+c-124 -102 -332 -154 -521 -154c-359 0 -649 111 -745 315c-1 2 0 2 1 1c103 -149 366 -227 610 -227c345 0 679 106 795 276c0 1 1 1 1 1zM1274 64v0c1 0 1 -1 0 -2c-135 -118 -312 -190 -506 -190c-177 0 -341 60 -471 161c-1 1 -1 3 1 2c84 -47 234 -100 470 -100
+c272 0 444 89 505 129h1z" />
+ <glyph glyph-name="sort-asc" unicode="&#xf0de;" horiz-adv-x="1024"
+d="M1024 832c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64c0 17 7 33 19 45l448 448c12 12 28 19 45 19s33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="folder-open" unicode="&#xf07c;" horiz-adv-x="1879"
+d="M1879 584c0 -24 -15 -48 -31 -66l-336 -396c-58 -68 -176 -122 -264 -122h-1088c-36 0 -87 11 -87 56c0 24 15 48 31 66l336 396c58 68 176 122 264 122h1088c36 0 87 -11 87 -56zM1536 928v-160h-832c-125 0 -280 -71 -361 -167l-337 -396l-5 -6c0 8 -1 17 -1 25v960
+c0 123 101 224 224 224h320c123 0 224 -101 224 -224v-32h544c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="heartbeat" unicode="&#xf21e;" horiz-adv-x="1792"
+d="M1280 512h305c-12 -13 -20 -20 -22 -22l-623 -600c-12 -12 -28 -18 -44 -18s-32 6 -44 18l-624 602c-2 1 -10 8 -21 20h369c29 0 55 20 62 48l70 281l190 -667c8 -27 33 -46 62 -46c28 0 53 19 61 46l146 485l56 -112c11 -21 33 -35 57 -35zM1792 940
+c0 -115 -50 -220 -103 -300h-369l-111 221c-11 23 -37 37 -62 35c-27 -3 -49 -20 -56 -46l-129 -430l-196 686c-8 27 -33 46 -63 46c-29 0 -54 -20 -61 -48l-116 -464h-423c-53 80 -103 185 -103 300c0 293 179 468 478 468c175 0 339 -138 418 -216c79 78 243 216 418 216
+c299 0 478 -175 478 -468z" />
+ <glyph glyph-name="blind" unicode="&#xf29d;" horiz-adv-x="1330"
+d="M327 1225c-86 0 -156 70 -156 156c0 85 70 155 156 155s155 -70 155 -155c0 -86 -69 -156 -155 -156zM878 583c0 -108 -115 -84 -141 -40l-367 438c-16 26 -28 14 -28 14s-7 -8 4 -21l122 -139l1 -354c-86 -250 -161 -457 -161 -457c-47 -134 -86 -250 -120 -266
+c-41 -21 -71 -16 -103 -1c-42 19 -54 70 -51 100c0 0 2 16 197 618l5 416l-85 -164l35 -222c13 -84 -58 -95 -58 -95c-68 -11 -82 68 -82 70l-46 299c210 379 211 381 211 381c16 24 52 34 113 34c54 0 88 -16 107 -40l424 -521c6 -4 10 -10 14 -17l3 -3l-1 -1
+c5 -9 7 -19 7 -29zM475 433c96 -255 182 -448 182 -448c29 -74 79 -180 6 -222c-72 -42 -130 7 -146 41h-1c-3 8 -6 16 -8 25l-124 351zM1299 -159c21 -33 39 -57 28 -64c-19 -12 -25 23 -46 57c0 0 -113 171 -423 661c6 -2 17 7 17 7s11 9 11 17
+c308 -503 413 -678 413 -678z" />
+ <glyph glyph-name="arrows-v" unicode="&#xf07d;" horiz-adv-x="640"
+d="M640 1216c0 -35 -29 -64 -64 -64h-128v-1024h128c35 0 64 -29 64 -64c0 -17 -7 -33 -19 -45l-256 -256c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-256 256c-12 12 -19 28 -19 45c0 35 29 64 64 64h128v1024h-128c-35 0 -64 29 -64 64c0 17 7 33 19 45l256 256
+c12 12 28 19 45 19s33 -7 45 -19l256 -256c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="phone-square" unicode="&#xf098;"
+d="M1280 343c0 5 0 11 -2 16c-6 18 -152 92 -180 108c-19 11 -42 33 -65 33c-44 0 -109 -131 -148 -131c-20 0 -45 18 -63 28c-132 74 -223 165 -297 297c-10 18 -28 43 -28 63c0 39 131 104 131 148c0 23 -22 46 -33 65c-16 28 -90 174 -108 180c-5 2 -11 2 -16 2
+c-26 0 -77 -12 -101 -22c-66 -30 -114 -156 -114 -225c0 -67 27 -128 50 -190c80 -219 318 -457 537 -537c62 -23 123 -50 190 -50c69 0 195 48 225 114c10 24 22 75 22 101zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960
+c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="text-height" unicode="&#xf034;" horiz-adv-x="1789"
+d="M1744 128c44 0 58 -28 31 -63l-126 -162c-27 -35 -71 -35 -98 0l-126 162c-27 35 -13 63 31 63h80v1024h-80c-44 0 -58 28 -31 63l126 162c27 35 71 35 98 0l126 -162c27 -35 13 -63 -31 -63h-80v-1024h80zM81 1407l54 -27c7 -3 190 -5 211 -5c88 0 176 4 264 4
+c72 0 143 -1 215 -1h293c40 0 63 -9 90 29l42 1c9 0 19 -1 28 -1c2 -112 2 -224 2 -336c0 -35 1 -74 -5 -109c-22 -8 -45 -15 -68 -18c-23 40 -39 84 -54 128c-7 20 -31 155 -33 157c-21 26 -44 21 -75 21c-91 0 -186 4 -276 -7c-5 -44 -9 -91 -8 -136c1 -281 4 -562 4 -843
+c0 -77 -12 -158 10 -232c76 -39 166 -45 244 -80c2 -16 5 -33 5 -50c0 -9 -1 -19 -3 -29l-34 -1c-142 -4 -282 18 -425 18c-101 0 -202 -18 -303 -18c-1 17 -3 35 -3 52v9c38 61 175 62 238 99c22 49 19 320 19 383c0 202 -6 404 -6 606v117c0 18 4 90 -8 104
+c-14 15 -145 12 -162 12c-37 0 -144 -17 -173 -38c-48 -33 -48 -233 -108 -237c-18 11 -43 27 -56 44v383z" />
+ <glyph glyph-name="linkedin-square" unicode="&#xf08c;"
+d="M237 122h231v694h-231v-694zM483 1030c-1 68 -50 120 -129 120s-131 -52 -131 -120c0 -66 50 -120 128 -120h1c81 0 131 54 131 120zM1068 122h231v398c0 213 -114 312 -266 312c-124 0 -179 -69 -209 -117h2v101h-231s3 -65 0 -694h231v388c0 20 1 41 7 56
+c17 41 55 84 119 84c83 0 116 -63 116 -157v-371zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="delicious" unicode="&#xf1a5;"
+d="M1472 160v480h-704v704h-480c-124 0 -224 -100 -224 -224v-480h704v-704h480c124 0 224 100 224 224zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="qrcode" unicode="&#xf029;"
+d="M0 1408h768v-704h-128v576h-512v-512h640v-128h-768v768zM0 -128v640h640v-640h-576v128h448v384h-384v-512h-128zM896 768v640h640v-640h-576v128h448v384h-384v-512h-128zM256 1152h256v-256h-256v256zM1152 1152h128v-128h-128v128zM256 256h128v-128h-128v128z
+M768 512h128v-128h-128v128zM1152 384h128v-128h-128v128zM1152 128h128v-128h-128v128zM1024 640h384v-256h-128v128h-256v128zM1536 256v-384h-256v128h128v256h128zM1024 384v-256h-256v128h128v128h128zM768 0h384v-128h-384v128z" />
+ <glyph glyph-name="arrows-h" unicode="&#xf07e;" horiz-adv-x="1792"
+d="M1792 640c0 -17 -7 -33 -19 -45l-256 -256c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v128h-1024v-128c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-256 256c-12 12 -19 28 -19 45s7 33 19 45l256 256c12 12 28 19 45 19c35 0 64 -29 64 -64v-128h1024v128
+c0 35 29 64 64 64c17 0 33 -7 45 -19l256 -256c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="mercury" unicode="&#xf223;" horiz-adv-x="1152"
+d="M830 1220c190 -94 322 -290 322 -516c0 -296 -224 -540 -512 -572v-132h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96v-96c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v96h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96v132c-288 32 -512 276 -512 572
+c0 226 132 422 322 516c-105 61 -187 157 -228 273c-8 21 8 43 30 43h69c13 0 24 -8 29 -20c58 -139 195 -236 354 -236s296 97 354 236c5 12 16 20 37 20h61c22 0 38 -22 30 -43c-41 -116 -123 -212 -228 -273zM576 256c247 0 448 201 448 448s-201 448 -448 448
+s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="text-width" unicode="&#xf035;"
+d="M81 1407l54 -27c7 -3 190 -5 211 -5c88 0 176 4 264 4c265 0 533 6 798 -3c22 -1 43 13 56 31l42 1c9 0 19 -1 28 -1c2 -112 2 -224 2 -336c0 -36 1 -74 -5 -109c-22 -8 -45 -15 -68 -18c-23 40 -39 84 -54 128c-7 20 -32 155 -33 157c-7 9 -16 15 -27 19
+c-8 3 -56 2 -66 2c-123 0 -265 7 -386 -7c-5 -44 -9 -91 -8 -136l1 -152v52c1 -163 3 -325 3 -487c0 -77 -12 -158 10 -232c76 -39 166 -45 244 -80c2 -16 5 -33 5 -50c0 -9 -1 -19 -3 -29l-34 -1c-142 -4 -282 18 -425 18c-101 0 -202 -18 -303 -18c-1 17 -3 35 -3 52v9
+c38 61 175 62 238 99c25 56 18 529 18 617c0 14 -5 29 -5 44c0 41 7 276 -8 293c-14 15 -145 12 -162 12c-42 0 -277 -22 -301 -38c-47 -31 -48 -232 -108 -237c-18 11 -43 27 -56 44v383zM1310 125c35 0 168 -119 195 -140c15 -12 26 -29 26 -49s-11 -37 -26 -49
+c-27 -21 -160 -140 -195 -140c-46 0 -30 107 -30 125h-1024c0 -18 16 -125 -30 -125c-35 0 -168 119 -195 140c-15 12 -26 29 -26 49s11 37 26 49c27 21 160 140 195 140c46 0 30 -107 30 -125h1024c0 18 -16 125 30 125z" />
+ <glyph glyph-name="envelope-o" unicode="&#xf003;" horiz-adv-x="1792"
+d="M1664 32v768c-21 -24 -44 -46 -69 -66c-143 -110 -287 -222 -426 -338c-75 -63 -168 -140 -272 -140h-2c-104 0 -197 77 -272 140c-139 116 -283 228 -426 338c-25 20 -48 42 -69 66v-768c0 -17 15 -32 32 -32h1472c17 0 32 15 32 32zM1664 1083c0 25 6 69 -32 69h-1472
+c-17 0 -32 -15 -32 -32c0 -114 57 -213 147 -284c134 -105 268 -211 401 -317c53 -43 149 -135 219 -135h2c70 0 166 92 219 135c133 106 267 212 401 317c65 51 147 162 147 247zM1792 1120v-1088c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v1088
+c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="rss-square" unicode="&#xf143;"
+d="M512 256c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM863 162c-17 310 -263 556 -573 573c-9 1 -18 -3 -24 -9s-10 -14 -10 -23v-128c0 -17 13 -31 30 -32c205 -15 370 -180 385 -385c1 -17 15 -30 32 -30h128c9 0 17 4 23 10
+s10 15 9 24zM1247 161c-17 520 -438 941 -958 958c-10 1 -17 -2 -23 -9c-6 -6 -10 -14 -10 -23v-128c0 -17 14 -31 31 -32c415 -15 753 -353 768 -768c1 -17 15 -31 32 -31h128c9 0 17 4 23 10c7 6 10 14 9 23zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960
+c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="bookmark" unicode="&#xf02e;" horiz-adv-x="1280"
+d="M1164 1408c15 0 30 -3 44 -9c44 -17 72 -58 72 -103v-1289c0 -45 -28 -86 -72 -103c-14 -6 -29 -8 -44 -8c-31 0 -60 11 -83 32l-441 424l-441 -424c-23 -21 -52 -33 -83 -33c-15 0 -30 3 -44 9c-44 17 -72 58 -72 103v1289c0 45 28 86 72 103c14 6 29 9 44 9h1048z" />
+ <glyph glyph-name="behance" unicode="&#xf1b4;" horiz-adv-x="2048"
+d="M1848 1197v-124h-511v124h511zM1596 771c-120 0 -200 -75 -208 -195h408c-11 121 -74 195 -200 195zM1612 186c76 0 174 41 198 119h221c-68 -209 -209 -307 -427 -307c-288 0 -467 195 -467 479c0 274 189 483 467 483c286 0 444 -225 444 -495c0 -16 -1 -32 -2 -47
+h-658c0 -146 77 -232 224 -232zM277 236h296c113 0 205 40 205 167c0 129 -77 180 -199 180h-302v-347zM277 773h281c99 0 169 43 169 150c0 116 -90 144 -190 144h-260v-294zM0 1282h594c216 0 403 -61 403 -312c0 -127 -59 -209 -172 -263c155 -44 230 -161 230 -319
+c0 -256 -215 -366 -444 -366h-611v1260z" />
+ <glyph glyph-name="wpbeginner" unicode="&#xf297;" horiz-adv-x="1792"
+d="M384 704h160v224h-160v-224zM1221 372v92c-86 -30 -157 -37 -243 -38c-193 -1 -364 79 -480 169l1 -96c109 -99 276 -177 484 -176c87 0 169 18 238 49zM640 704h640v224h-640v-224zM1792 736c0 -127 -36 -247 -99 -352c56 -64 89 -143 89 -229
+c0 -209 -198 -379 -443 -379c-166 0 -310 78 -386 193c-19 -1 -38 -1 -57 -1s-38 0 -57 1c-76 -115 -220 -193 -386 -193c-245 0 -443 170 -443 379c0 86 33 165 89 229c-63 105 -99 225 -99 352c0 424 401 768 896 768s896 -344 896 -768z" />
+ <glyph glyph-name="star-half-o" unicode="&#xf123;" horiz-adv-x="1664"
+d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500c7 -44 -9 -70 -40 -70c-11 0 -25 4 -40 12l-449 236l-449 -236c-15 -8 -29 -12 -40 -12c-31 0 -47 26 -40 70l86 500l-364 354c-43 43 -29 85 31 94
+l502 73l225 455c13 27 31 41 49 41s35 -14 49 -41l225 -455l502 -73c60 -9 74 -51 30 -94z" />
+ <glyph glyph-name="keyboard-o" unicode="&#xf11c;" horiz-adv-x="1920"
+d="M384 368v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM512 624v-96c0 -9 -7 -16 -16 -16h-224c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h224c9 0 16 -7 16 -16zM384 880v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96
+c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1408 368v-96c0 -9 -7 -16 -16 -16h-864c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h864c9 0 16 -7 16 -16zM768 624v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM640 880v-96
+c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1024 624v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM896 880v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96
+c9 0 16 -7 16 -16zM1280 624v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1664 368v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1152 880v-96c0 -9 -7 -16 -16 -16h-96
+c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1408 880v-96c0 -9 -7 -16 -16 -16h-96c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h96c9 0 16 -7 16 -16zM1664 880v-352c0 -9 -7 -16 -16 -16h-224c-9 0 -16 7 -16 16v96c0 9 7 16 16 16h112v240c0 9 7 16 16 16h96
+c9 0 16 -7 16 -16zM1792 128v896h-1664v-896h1664zM1920 1024v-896c0 -71 -57 -128 -128 -128h-1664c-71 0 -128 57 -128 128v896c0 71 57 128 128 128h1664c71 0 128 -57 128 -128z" />
+ <glyph glyph-name="minus-circle" unicode="&#xf056;"
+d="M1216 576v128c0 35 -29 64 -64 64h-768c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h768c35 0 64 29 64 64zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="hand-o-down" unicode="&#xf0a7;"
+d="M1408 576c0 199 -128 369 -128 544v32h-640v-32c0 -106 -90 -177 -163 -241c-46 -41 -92 -79 -145 -112c-22 -14 -45 -26 -68 -38s-136 -62 -136 -89c0 -85 32 -160 128 -160c128 0 193 96 256 96v-576c0 -67 60 -128 128 -128c69 0 128 59 128 128v331
+c26 -20 70 -35 103 -35c47 0 87 19 119 53c21 -12 45 -18 69 -18c46 0 103 23 126 65c18 -3 37 -4 56 -4c118 0 167 73 167 184zM1280 1344c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1536 580c0 -184 -104 -318 -295 -317l-5 1
+c-50 -40 -114 -61 -178 -61c-14 0 -29 1 -43 3c-34 -19 -80 -33 -119 -37v-169c0 -140 -117 -256 -257 -256c-138 0 -255 118 -255 256v374c-39 -16 -86 -22 -128 -22c-168 0 -256 129 -256 288c0 134 171 177 264 235c47 30 88 64 129 100c33 29 119 97 119 145v288
+c0 71 57 128 128 128h640c71 0 128 -57 128 -128v-288c0 -63 37 -162 59 -223c37 -102 69 -207 69 -317z" />
+ <glyph glyph-name="sort-numeric-asc" unicode="&#xf162;" horiz-adv-x="1454"
+d="M1314 223c0 82 -67 169 -147 169c-70 0 -114 -57 -114 -131c0 -72 46 -133 141 -133c65 0 120 39 120 95zM704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192
+c18 0 32 -14 32 -32v-1376h192c18 0 32 -14 32 -32zM1454 165c0 -202 -110 -421 -348 -421c-45 0 -82 7 -108 16c-16 5 -30 10 -42 15l39 113c9 -4 20 -8 31 -11c20 -7 46 -13 75 -13c120 0 182 100 201 204h-2c-28 -30 -87 -51 -146 -51c-145 0 -240 114 -240 244
+c0 138 106 251 253 251c159 0 287 -130 287 -347zM1424 882v-114h-469v114h167v432c0 13 1 26 1 36v16h-2l-7 -12c-5 -8 -13 -18 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
+ <glyph glyph-name="share-alt" unicode="&#xf1e0;"
+d="M1216 512c177 0 320 -143 320 -320s-143 -320 -320 -320s-320 143 -320 320c0 11 1 23 2 34l-360 180c-57 -53 -134 -86 -218 -86c-177 0 -320 143 -320 320s143 320 320 320c84 0 161 -33 218 -86l360 180c-1 11 -2 23 -2 34c0 177 143 320 320 320s320 -143 320 -320
+s-143 -320 -320 -320c-84 0 -161 33 -218 86l-360 -180c1 -11 2 -23 2 -34s-1 -23 -2 -34l360 -180c57 53 134 86 218 86z" />
+ <glyph glyph-name="shirtsinbulk" unicode="&#xf214;"
+d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34
+l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114
+v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z
+M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378
+v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265c-172 0 -313 140 -313 313c0 172 141 313 313 313c173 0 313 -141 313 -313c0 -173 -140 -313 -313 -313zM595 646c0 -152 266 -41 266 -130c0 -45 -82 -49 -112 -49c-42 0 -102 9 -123 51h-3l-31 -63
+c51 -32 100 -42 162 -42c67 0 175 20 175 107c0 165 -269 56 -269 130c0 45 71 51 102 51c37 0 100 -11 122 -45h3l30 58c-52 21 -94 41 -152 41c-69 0 -170 -22 -170 -109z" />
+ <glyph glyph-name="viacoin" unicode="&#xf237;"
+d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+ <glyph glyph-name="dogmazic" unicode="&#xf303;"
+d="M768 1404c423 0 768 -343 768 -766s-345 -766 -768 -766s-768 343 -768 766s345 766 768 766zM768 1302c-368 0 -666 -297 -666 -664s298 -664 666 -664s666 297 666 664s-298 664 -666 664zM768 1223c668 3 845 -918 212 -1148c-52 -19 -148 -29 -165 -17
+c-9 6 6 111 30 214c20 88 28 84 -78 37c-49 -22 -92 -40 -96 -41c-5 -1 -23 23 -60 78c-32 48 -54 78 -55 74s-21 -73 -44 -154c-50 -177 -38 -165 -111 -110c-452 340 -218 1052 351 1067h16zM803 1137c-251 0 -505 -261 -415 -458c14 -31 19 -30 9 1
+c-66 214 206 464 458 420c281 -49 436 -423 255 -613c-49 -51 -21 -53 31 -2c184 181 17 586 -267 645c-23 5 -47 7 -71 7zM435 998c-2 0 -6 0 -10 -1c-132 -18 -189 -193 -96 -296c27 -30 30 -29 22 5c-18 75 7 167 69 258c19 28 24 34 15 34zM805 958
+c-12 0 -35 -27 -35 -44c0 -20 -7 -22 -25 -6c-42 37 -123 53 -167 34c-14 -6 -14 -5 6 -8c61 -8 101 -75 69 -117c-27 -36 -40 -72 -44 -123c-4 -61 -30 -81 -51 -39c-27 54 10 135 62 135c11 0 0 8 -15 11c-89 17 -142 -140 -56 -167c14 -4 6 -11 -14 -11
+c-24 0 -48 11 -69 31c-23 22 -10 -6 24 -53c12 -16 57 -84 101 -150c94 -139 89 -132 95 -129c3 1 61 28 131 60s144 64 166 72c40 15 83 37 79 41c-1 1 -6 0 -11 -3c-24 -13 -80 -2 -98 18c-9 10 -9 9 15 9c97 0 121 145 28 173c-16 5 -18 7 -20 26c-1 11 -4 26 -5 33
+c-5 33 78 59 121 37c19 -10 15 0 -9 21c-37 33 -64 43 -119 43c-70 0 -77 6 -56 49c9 19 10 23 4 24c-10 2 -23 -11 -30 -29c-5 -15 -13 -20 -19 -11c-2 3 1 12 6 20c11 17 12 30 3 30c-8 0 -17 -11 -27 -30c-4 -8 -10 -15 -12 -15c-6 0 -4 18 3 31c4 6 6 16 6 20
+c0 16 -22 -2 -32 -25c-5 -12 -13 -22 -16 -22c-9 0 -7 12 6 37c6 13 10 24 9 25s-2 2 -4 2zM1242 756c-5 0 -5 -16 -5 -59c0 -100 -23 -174 -72 -226c-26 -27 -19 -29 32 -6c106 48 136 192 58 280c-6 7 -10 11 -13 11zM982 689c3 0 6 -3 10 -8c39 -45 25 -117 -28 -144
+c-24 -12 -28 -11 -37 8c-8 16 -8 16 3 28c16 17 34 55 40 86c4 21 8 30 12 30zM680 537c10 0 20 -8 21 -22c2 -25 -16 -39 -36 -27v0c-11 6 -11 32 1 43c4 4 9 6 14 6zM778 509c10 0 19 -11 19 -28c0 -22 -23 -33 -38 -18c-10 10 -9 27 2 38c6 6 12 8 17 8z" />
+ <glyph glyph-name="digg" unicode="&#xf1a6;" horiz-adv-x="2048"
+d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968h205v-697h-205v697zM614 1254h205v-204h-205v204zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123
+v-369h123z" />
+ <glyph glyph-name="rss" unicode="&#xf09e;" horiz-adv-x="1408"
+d="M384 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM896 69c1 -18 -5 -35 -17 -48c-12 -14 -29 -21 -47 -21h-135c-33 0 -60 25 -63 58c-29 305 -271 547 -576 576c-33 3 -58 30 -58 63v135c0 18 7 35 21 47c11 11 27 17 43 17h5
+c213 -17 414 -110 565 -262c152 -151 245 -352 262 -565zM1408 67c1 -17 -5 -34 -18 -47c-12 -13 -28 -20 -46 -20h-143c-34 0 -62 26 -64 60c-33 581 -496 1044 -1077 1078c-34 2 -60 30 -60 63v143c0 18 7 34 20 46c12 12 28 18 44 18h3c350 -18 679 -165 927 -414
+c249 -248 396 -577 414 -927z" />
+ <glyph glyph-name="television" unicode="&#xf26c;" horiz-adv-x="1920"
+d="M1792 288v960c0 17 -15 32 -32 32h-1600c-17 0 -32 -15 -32 -32v-960c0 -17 15 -32 32 -32h1600c17 0 32 15 32 32zM1920 1248v-960c0 -88 -72 -160 -160 -160h-736v-128h352c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-832c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h352v128h-736c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1600c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="ffmpeg" unicode="&#xf30f;"
+d="M1158 323v179l-530 -527l-628 53l1010 1100l-167 -10l-730 -810v688l69 83l-169 -10v185l591 50l-325 -379v-161l483 553l774 66l-1134 -1194l149 -8l824 849v-806l-92 -87l234 -14v-223l-731 62z" />
+ <glyph glyph-name="folder-o" unicode="&#xf114;" horiz-adv-x="1664"
+d="M1536 224v704c0 53 -43 96 -96 96h-704c-53 0 -96 43 -96 96v64c0 53 -43 96 -96 96h-320c-53 0 -96 -43 -96 -96v-960c0 -53 43 -96 96 -96h1216c53 0 96 43 96 96zM1664 928v-704c0 -123 -101 -224 -224 -224h-1216c-123 0 -224 101 -224 224v960
+c0 123 101 224 224 224h320c123 0 224 -101 224 -224v-32h672c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="bed" unicode="&#xf236;" horiz-adv-x="2048"
+d="M256 512h1728c35 0 64 -29 64 -64v-448h-256v256h-1536v-256h-256v1216c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-704zM832 832c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256zM2048 576h-1152v384c0 35 29 64 64 64h704
+c212 0 384 -172 384 -384v-64z" />
+ <glyph glyph-name="caret-square-o-down" unicode="&#xf150;"
+d="M1145 861c11 -21 9 -47 -5 -66l-320 -448c-12 -17 -31 -27 -52 -27s-40 10 -52 27l-320 448c-14 19 -16 45 -5 66c11 22 33 35 57 35h640c24 0 46 -13 57 -35zM1280 160v960c0 17 -15 32 -32 32h-960c-17 0 -32 -15 -32 -32v-960c0 -17 15 -32 32 -32h960
+c17 0 32 15 32 32zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="shower" unicode="&#xf2cc;" horiz-adv-x="1920"
+d="M1433 1287c13 -13 13 -33 0 -46l-626 -626c-13 -13 -33 -13 -46 0l-82 82c-13 13 -13 33 0 46l44 44c-97 122 -109 289 -35 422c-46 44 -108 71 -176 71c-141 0 -256 -115 -256 -256v-1280h-256v1280c0 282 230 512 512 512c144 0 274 -60 367 -156
+c126 51 272 32 382 -55l44 44c13 13 33 13 46 0zM1344 1024c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1600 896c-35 0 -64 29 -64 64s29 64 64 64s64 -29 64 -64s-29 -64 -64 -64zM1856 1024c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64
+s29 64 64 64zM1216 896c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1408 832c0 35 29 64 64 64s64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64zM1728 896c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1088 768c35 0 64 -29 64 -64
+s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1344 640c-35 0 -64 29 -64 64s29 64 64 64s64 -29 64 -64s-29 -64 -64 -64zM1600 768c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1216 512c-35 0 -64 29 -64 64s29 64 64 64s64 -29 64 -64
+s-29 -64 -64 -64zM1472 640c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1088 512c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1344 512c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1216 384
+c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64zM1088 256c35 0 64 -29 64 -64s-29 -64 -64 -64s-64 29 -64 64s29 64 64 64z" />
+ <glyph glyph-name="paper-plane-o" unicode="&#xf1d9;" horiz-adv-x="1792"
+d="M1764 1525c21 -15 31 -39 27 -64l-256 -1536c-3 -19 -15 -35 -32 -45c-9 -5 -20 -8 -31 -8c-8 0 -16 2 -24 5l-527 215l-298 -327c-12 -14 -29 -21 -47 -21c-8 0 -16 1 -23 4c-25 10 -41 34 -41 60v452l-472 193c-23 9 -38 30 -40 55c-2 24 11 47 32 59l1664 960
+c21 13 48 12 68 -2zM1422 26l221 1323l-1434 -827l336 -137l863 639l-478 -797z" />
+ <glyph glyph-name="circle-o-notch" unicode="&#xf1ce;" horiz-adv-x="1728"
+d="M1728 640c0 -477 -387 -864 -864 -864s-864 387 -864 864c0 434 320 793 736 855v-228c-292 -59 -512 -318 -512 -627c0 -353 287 -640 640 -640s640 287 640 640c0 309 -220 568 -512 627v228c416 -62 736 -421 736 -855z" />
+ <glyph glyph-name="gnupg" unicode="&#xf30d;" horiz-adv-x="1156"
+d="M0 667h81v244c0 274 223 497 497 497s497 -223 497 -497v-242c-1 -1 -3 -1 -4 -2v0l-1 -1v0v0v0h-1v-1v0v0v0h-1v0v0v-1v0h-1v0v0v0l-1 -1v0v0h-1v0l-1 -1v0v0v0v0l-1 -1v0v0v0h-1v0v0v0l-1 -1v0v0v0v0v0h-1v0v-1v0v0v0v0h-1v0v0v0l-2 -1v0v0l-1 -1v0h-1v0v-1v0v0v0h-1v0
+v0v0v0h-1v-1h-1l-1 -1h-1v-1l-2 -1h-1l-1 -1v0l-3 -1l-1 -1l-1 -1h-1l-1 -1l-1 -1h-1l-4 -2v0l-1 -1h-1v-1h-2l-3 -2l-1 -1c-1 -1 -3 -1 -4 -2h-1v0l-2 -2h-1h-1l-1 -1v0l-2 -1v0l-2 -1h-1l-1 -1c-1 -1 -3 -1 -4 -2l-1 -1c-2 -1 -3 -1 -5 -2v0l-4 -2l-2 -1
+c-2 -1 -3 -2 -5 -3v0c-99 -47 -257 -97 -557 -119c-215 -15 -346 -110 -431 -224v390v0zM310 667h536v244c0 148 -120 268 -268 268s-268 -120 -268 -268v-244zM1004 628c-1 -1 -4 -1 -5 -2zM803 1288c-64 38 -138 60 -218 60c-218 0 -398 -164 -422 -376
+c64 200 251 345 472 345c59 0 116 -10 168 -29v0zM1156 573v-701h-989c109 61 190 54 325 50c183 -6 385 71 485 173s-9 24 -122 -5s-330 -31 -476 7c459 -6 637 142 739 275s-44 24 -138 -22s-258 -79 -439 -55c273 1 482 137 615 278v0z" />
+ <glyph glyph-name="medkit" unicode="&#xf0fa;" horiz-adv-x="1792"
+d="M1280 416v192c0 18 -14 32 -32 32h-224v224c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32v-224h-224c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h224v-224c0 -18 14 -32 32 -32h192c18 0 32 14 32 32v224h224c18 0 32 14 32 32zM640 1152h512v128h-512v-128z
+M256 1152v-1280h-32c-123 0 -224 101 -224 224v832c0 123 101 224 224 224h32zM1440 1152v-1280h-1088v1280h160v160c0 53 43 96 96 96h576c53 0 96 -43 96 -96v-160h160zM1792 928v-832c0 -123 -101 -224 -224 -224h-32v1280h32c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="toggle-off" unicode="&#xf204;" horiz-adv-x="2048"
+d="M1152 640c0 282 -230 512 -512 512s-512 -230 -512 -512s230 -512 512 -512s512 230 512 512zM1920 640c0 282 -230 512 -512 512h-386c156 -117 258 -303 258 -512s-102 -395 -258 -512h386c282 0 512 230 512 512zM2048 640c0 -353 -287 -640 -640 -640h-768
+c-353 0 -640 287 -640 640s287 640 640 640h768c353 0 640 -287 640 -640z" />
+ <glyph glyph-name="calendar-minus-o" unicode="&#xf272;" horiz-adv-x="1664"
+d="M1152 416v-64c0 -18 -14 -32 -32 -32h-576c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h576c18 0 32 -14 32 -32zM128 -128h1408v1024h-1408v-1024zM512 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1280 1088
+v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1664 1152v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96
+c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="id-badge" unicode="&#xf2c1;" horiz-adv-x="1280"
+d="M1024 278c0 -86 -57 -150 -128 -150h-512c-71 0 -128 64 -128 150c0 156 39 329 196 329c49 -46 115 -75 188 -75s139 29 188 75c157 0 196 -173 196 -329zM870 797c0 -126 -103 -227 -230 -227s-230 101 -230 227c0 125 103 227 230 227s230 -102 230 -227zM1152 -96
+v1376h-1024v-1376c0 -17 15 -32 32 -32h960c17 0 32 15 32 32zM1280 1376v-1472c0 -88 -72 -160 -160 -160h-960c-88 0 -160 72 -160 160v1472c0 88 72 160 160 160h352v-96c0 -18 14 -32 32 -32h192c18 0 32 14 32 32v96h352c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="tencent-weibo" unicode="&#xf1d5;" horiz-adv-x="1166"
+d="M785 964c0 -106 -87 -193 -193 -193c-41 0 -79 13 -111 35c-36 -39 -76 -88 -115 -146c-163 -245 -232 -534 -202 -859c2 -29 -19 -54 -47 -57h-5c-26 0 -49 20 -52 47c-39 438 100 748 223 931c45 67 90 121 132 165c-11 24 -16 50 -16 77c0 107 86 193 193 193
+c106 0 193 -86 193 -193zM1166 953c0 -321 -261 -582 -583 -582c-44 0 -88 5 -131 14c-28 7 -45 35 -39 63c7 27 34 45 62 39c35 -9 72 -13 108 -13c264 0 479 215 479 479s-215 479 -479 479s-479 -215 -479 -479c0 -77 18 -150 52 -218c13 -26 3 -57 -22 -70
+c-26 -13 -57 -3 -70 23c-42 81 -64 173 -64 265c0 322 262 583 583 583c322 0 583 -261 583 -583z" />
+ <glyph glyph-name="file-archive-o" unicode="&#xf1c6;"
+d="M640 1152h-128v128h128v-128zM768 1024h-128v128h128v-128zM640 896h-128v128h128v-128zM768 768h-128v128h128v-128zM1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68z
+M1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416h-128v-128h-128v128h-512v-1536h1280zM781 593c85 -287 107 -349 107 -349c5 -17 8 -34 8 -52c0 -111 -108 -192 -256 -192s-256 81 -256 192
+c0 18 3 35 8 52c0 0 21 62 120 396v128h128v-128h79c29 0 54 -19 62 -47zM640 128c71 0 128 29 128 64s-57 64 -128 64s-128 -29 -128 -64s57 -64 128 -64z" />
+ <glyph glyph-name="yoast" unicode="&#xf2b1;" horiz-adv-x="1664"
+d="M339 1318h691l-26 -72h-665c-147 0 -267 -121 -267 -268v-771c0 -126 90 -237 214 -263c32 -7 65 -5 98 -5v-72h-45c-187 0 -339 153 -339 340v771c0 187 152 340 339 340zM1190 1536h247l-482 -1294c-90 -240 -199 -490 -495 -498v195c111 18 182 79 220 182
+c13 34 20 69 20 105s-7 72 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795c16 24 33 47 45 73h678v1038c0 114 -72 216 -179 254l25 67c136 -46 226 -178 226 -321z" />
+ <glyph glyph-name="share-alt-square" unicode="&#xf1e1;"
+d="M1280 341c0 118 -96 214 -213 214c-56 0 -107 -22 -145 -58l-241 120c1 8 2 15 2 23s-1 15 -2 23l241 120c38 -36 89 -58 145 -58c117 0 213 96 213 214c0 117 -96 213 -213 213c-118 0 -214 -96 -214 -213c0 -8 1 -15 2 -23l-241 -120c-38 35 -89 57 -145 57
+c-117 0 -213 -95 -213 -213s96 -213 213 -213c56 0 107 22 145 57l241 -120c-1 -8 -2 -15 -2 -23c0 -117 96 -213 214 -213c117 0 213 96 213 213zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960
+c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="imdb" unicode="&#xf2d8;"
+d="M922 739v-182c0 -36 7 -69 -38 -68v309c44 0 38 -23 38 -59zM1238 643v-121c0 -20 6 -53 -23 -53c-6 0 -11 3 -14 9c-8 19 -4 163 -4 165c0 14 -4 47 18 47c27 0 23 -27 23 -47zM180 407h122v472h-122v-472zM614 407h106v472h-159l-28 -221c-10 74 -20 148 -32 221h-158
+v-472h107v312l45 -312h76l43 319v-319zM1039 712c0 30 1 62 -5 90c-16 83 -116 77 -181 77h-91v-472c318 0 277 -22 277 305zM1356 515v133c0 64 -3 111 -82 111c-33 0 -55 -10 -77 -34v154h-117v-472h110l7 30c21 -25 44 -36 77 -36c73 0 82 56 82 114zM1536 1248v-1216
+c0 -88 -72 -160 -160 -160h-1216c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1216c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="snapchat-square" unicode="&#xf2ad;"
+d="M1280 388c0 14 -8 24 -22 27c-91 19 -160 83 -198 167c-4 8 -7 16 -7 25c0 45 124 36 124 100c0 27 -33 44 -57 44c-22 0 -40 -16 -63 -16c-4 0 -8 1 -12 2c3 38 5 77 5 115c0 34 -2 82 -17 114c-48 104 -140 165 -255 165c-125 0 -220 -47 -275 -165
+c-15 -32 -18 -80 -18 -115c0 -38 3 -76 6 -114c-5 -1 -10 -2 -15 -2c-22 0 -41 16 -62 16c-25 0 -55 -17 -55 -45c0 -62 124 -54 124 -99c0 -9 -3 -17 -7 -25c-39 -84 -106 -147 -198 -167c-14 -3 -22 -13 -22 -27c0 -47 106 -64 138 -69c9 -24 5 -66 40 -66
+c26 0 51 10 77 10c106 0 134 -95 256 -95c127 0 151 95 258 95c26 0 52 -9 78 -9c34 0 31 42 39 65c32 5 138 22 138 69zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="spell-check" unicode="&#xf327;" horiz-adv-x="2049"
+d="M2049 700c0 -25 -10 -50 -28 -68l-724 -724l-136 -136c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-136 136l-362 362c-18 18 -28 43 -28 68s10 50 28 68l136 136c18 18 43 28 68 28s50 -10 68 -28l294 -295l656 657c18 18 43 28 68 28s50 -10 68 -28l136 -136
+c18 -18 28 -43 28 -68zM0 880v73h48l158 454h111l158 -454h49v-73h-199v73h52l-32 98h-167l-32 -98h52v-73h-198zM200 1127h122l-49 149c-2 8 -5 16 -6 23c-1 8 -3 15 -3 18l-1 5h-2c-1 -13 -5 -29 -10 -46zM569 880v73h63v381h-63v73h242c40 0 72 -5 95 -14
+c24 -9 44 -25 58 -47c15 -21 22 -46 22 -75c0 -25 -6 -47 -17 -67s-28 -35 -48 -46v-1c28 -8 50 -24 64 -47s22 -49 22 -78c0 -35 -10 -65 -30 -91s-45 -43 -75 -52c-21 -6 -47 -9 -79 -9h-254zM730 1192h92c20 0 37 6 48 18c11 13 17 30 17 51c0 29 -10 49 -30 60
+c-11 5 -27 8 -46 8h-81v-137zM730 958h98c15 0 27 2 37 6c13 5 25 15 32 28c7 14 11 29 11 46c0 23 -7 41 -21 55c-13 14 -32 22 -56 22h-101v-157zM1131 950c-52 53 -78 118 -78 196s26 142 78 193s116 77 193 77c18 0 39 -2 60 -5c22 -3 44 -9 67 -16s41 -18 56 -33
+s23 -32 23 -51v-72h-88v41c0 12 -7 23 -20 31s-29 14 -45 17s-32 5 -48 5c-51 0 -94 -17 -127 -51c-33 -33 -49 -77 -49 -132c0 -59 17 -106 51 -142s78 -54 130 -54c14 0 29 2 45 4s31 8 46 16s23 19 23 32v41h89v-72c0 -18 -7 -35 -22 -49c-14 -14 -33 -26 -56 -33
+c-22 -7 -45 -13 -67 -16c-22 -4 -44 -6 -64 -6c-79 0 -145 27 -197 79v0z" />
+ <glyph glyph-name="building-o" unicode="&#xf0f7;" horiz-adv-x="1408"
+d="M384 224v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 480v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 480v-64c0 -17 -15 -32 -32 -32h-64
+c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 224v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64
+c17 0 32 -15 32 -32zM896 480v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 992v-64
+c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 480v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 736v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64
+c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 992v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 1248v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 736
+v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 992v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM640 1248v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32
+v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1152 992v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 1248v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32z
+M1152 1248v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM896 -128h384v1536h-1152v-1536h384v224c0 17 15 32 32 32h320c17 0 32 -15 32 -32v-224zM1408 1472v-1664c0 -35 -29 -64 -64 -64h-1280c-35 0 -64 29 -64 64
+v1664c0 35 29 64 64 64h1280c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="sort-alpha-desc" unicode="&#xf15e;" horiz-adv-x="1629"
+d="M1159 104h177l-72 218l-12 47c-1 8 -2 14 -2 20h-4l-3 -20c-3 -12 -4 -27 -11 -47zM704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-1376h192
+c18 0 32 -14 32 -32zM1629 -150v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1540 1001v-233h-584v90l369 529c8 12 16 22 21 27l11 9v3c-4 0 -8 -1 -14 -1c-8 -2 -18 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530
+c-6 -9 -14 -18 -21 -26l-11 -10v-3l14 3c9 1 18 1 30 1h248v119h121z" />
+ <glyph glyph-name="map-signs" unicode="&#xf277;" horiz-adv-x="1718"
+d="M1708 1239c13 -13 13 -33 0 -46l-141 -141c-18 -18 -43 -28 -68 -28h-1344c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h576v64c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-64h512c25 0 50 -10 68 -28zM731 320h256v-512c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64
+v512zM1563 768c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64h-1344c-25 0 -50 10 -68 28l-141 141c-13 13 -13 33 0 46l141 141c18 18 43 28 68 28h512v192h256v-192h576z" />
+ <glyph glyph-name="long-arrow-right" unicode="&#xf178;" horiz-adv-x="1728"
+d="M1728 643c0 -9 -4 -18 -10 -24l-384 -354c-10 -9 -23 -11 -35 -6c-11 5 -19 16 -19 29v224h-1248c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h1248v224c0 13 7 24 19 29s25 3 35 -5l384 -350c6 -6 10 -14 10 -23z" />
+ <glyph glyph-name="first-order" unicode="&#xf2b0;"
+d="M1322 640c0 -26 -1 -51 -5 -76l-236 14l224 -78c-13 -51 -33 -98 -58 -141l-214 103l177 -158c-30 -41 -66 -77 -107 -108l-157 178l103 -215c-43 -26 -90 -45 -140 -59l-79 228l14 -240c-25 -4 -50 -6 -76 -6c-25 0 -51 2 -76 6l14 238l-78 -226c-50 13 -97 33 -140 59
+l103 215l-157 -178c-41 30 -77 67 -108 108l178 158l-214 -104c-25 44 -45 91 -58 141l224 79l-237 -14c-3 25 -5 50 -5 76s2 52 5 77l238 -14l-225 79c13 50 33 97 58 140l214 -104l-177 159c31 41 67 77 107 108l158 -178l-103 215c43 25 90 45 140 58l77 -224l-13 236
+c24 4 50 6 75 6c26 0 51 -2 76 -6l-14 -237l78 225c50 -13 97 -33 140 -59l-103 -214l158 178c40 -31 76 -67 107 -108l-177 -159l213 104c26 -43 45 -91 58 -141l-224 -78l237 14c4 -25 5 -51 5 -77zM1352 640c0 325 -262 588 -584 588c-323 0 -584 -263 -584 -588
+c0 -324 261 -587 584 -587c322 0 584 263 584 587zM1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
+ <glyph glyph-name="calendar-check-o" unicode="&#xf274;" horiz-adv-x="1664"
+d="M1303 572l-512 -512c-13 -12 -33 -12 -46 0l-288 288c-12 13 -12 33 0 45l46 46c12 12 32 12 45 0l220 -220l444 444c13 12 33 12 45 0l46 -46c12 -12 12 -32 0 -45zM128 -128h1408v1024h-1408v-1024zM512 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288
+c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1280 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1664 1152v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96
+c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="id-card" unicode="&#xf2c2;" horiz-adv-x="2048"
+d="M896 324c0 132 -32 284 -164 284c-40 -40 -95 -64 -156 -64s-116 24 -156 64c-132 0 -164 -152 -164 -284c0 -73 48 -132 107 -132h426c59 0 107 59 107 132zM768 768c0 106 -86 192 -192 192s-192 -86 -192 -192s86 -192 192 -192s192 86 192 192zM1792 288v64
+c0 18 -14 32 -32 32h-704c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h704c18 0 32 14 32 32zM1408 544v64c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1792 544v64c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32
+v-64c0 -18 14 -32 32 -32h192c18 0 32 14 32 32zM1792 800v64c0 18 -14 32 -32 32h-704c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h704c18 0 32 14 32 32zM128 1152h1792v96c0 18 -14 32 -32 32h-1728c-18 0 -32 -14 -32 -32v-96zM2048 1248v-1216
+c0 -88 -72 -160 -160 -160h-1728c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1728c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="globe-w" unicode="&#xf305;"
+d="M768 1404c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM924 1238v0c-3 0 -6 -1 -7 -1c-2 0 -153 -25 -208 -34s-156 -30 -201 -34s-46 0 -69 0c-7 0 -14 1 -21 2c-65 -43 -152 -132 -193 -198c0 -4 2 -7 6 -11c12 -12 46 0 69 0
+s59 8 69 0s1 -7 2 -9s-16 -108 -7 -144s10 -88 33 -129s110 -63 145 -98s106 -34 112 -71s-30 -79 -42 -102s-40 -40 -35 -69s46 -47 69 -70s47 -29 69 -69s25 -125 35 -173c2 -9 5 -22 7 -31c3 0 8 -1 11 -1c57 0 146 15 200 33c6 41 13 83 24 103c18 33 24 24 36 36
+s23 18 35 35s23 46 34 68s38 38 33 67s-47 47 -70 70s-35 50 -69 69s-94 24 -130 33s-163 15 -165 16s0 -8 -8 2s-3 50 -3 73s13 44 30 85c17 23 7 12 33 31c13 12 55 -57 73 -57s-4 117 7 128c46 46 163 125 163 174s-46 46 -69 69s-60 -39 -143 -39s97 131 109 143
+s30 22 35 35s0 23 0 34s14 28 9 32c-2 2 -5 2 -8 2zM1041 1214v0c-6 -14 -7 -31 -14 -45c-12 -23 -35 -43 -35 -69s23 -46 35 -69s1 -60 34 -69s69 46 104 69c21 14 50 26 72 40c-46 50 -134 114 -196 143z" />
+ <glyph glyph-name="github-alt" unicode="&#xf113;" horiz-adv-x="1664"
+d="M640 320c0 -73 -38 -192 -128 -192s-128 119 -128 192s38 192 128 192s128 -119 128 -192zM1280 320c0 -73 -38 -192 -128 -192s-128 119 -128 192s38 192 128 192s128 -119 128 -192zM1440 320c0 153 -93 288 -256 288c-66 0 -129 -12 -195 -21
+c-52 -8 -104 -11 -157 -11s-105 3 -157 11c-65 9 -129 21 -195 21c-163 0 -256 -135 -256 -288c0 -306 280 -353 524 -353h168c244 0 524 47 524 353zM1664 496c0 -111 -11 -229 -61 -331c-132 -267 -495 -293 -755 -293c-264 0 -649 23 -786 293c-51 101 -62 220 -62 331
+c0 146 40 284 136 396c-18 55 -27 113 -27 170c0 75 17 150 51 218c158 0 259 -69 379 -163c101 24 205 35 309 35c94 0 189 -10 280 -32c119 93 220 160 376 160c34 -68 51 -143 51 -218c0 -57 -9 -114 -27 -168c96 -113 136 -252 136 -398z" />
+ <glyph glyph-name="sign-language" unicode="&#xf2a7;" horiz-adv-x="1664"
+d="M831 863c21 0 41 -6 59 -18l222 -148c41 -27 78 -60 110 -97l146 -170c25 -29 36 -68 29 -106l-72 -413c-8 -42 -42 -74 -85 -79l-527 -56l-352 -32h-9c-52 0 -96 42 -96 96c0 50 42 90 92 96l260 32h-448c-55 0 -99 46 -96 101c3 52 49 91 101 91l442 1l-521 64
+c-54 6 -93 55 -85 110c8 48 52 80 100 80h10l481 -60l-351 94c-50 13 -88 59 -80 110c8 48 49 81 95 81c7 0 13 -1 20 -2l448 -96l217 -37c2 0 4 -1 6 -1c30 0 45 41 18 59l-186 125c-46 31 -57 93 -24 137c18 25 47 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38
+l-238 262c-2 2 -3 5 -5 7c-31 41 -24 101 19 134c40 31 97 21 132 -16l142 -147c-3 -3 -6 -5 -9 -8c-21 -29 -29 -64 -23 -99c6 -34 26 -65 55 -85zM1648 1115l15 -266c3 -49 -1 -99 -11 -147l-48 -219c-8 -38 -32 -69 -67 -87l-106 -54c1 40 -12 78 -39 109l-146 170
+c-34 39 -73 74 -117 103l-222 148c-22 15 -48 23 -76 23c-34 0 -65 -14 -88 -37l-235 312c-33 44 -23 106 23 137c43 30 102 16 134 -26l266 -352l-262 455c-28 47 -12 108 37 134c46 24 104 5 130 -40l241 -420l-136 337c-19 48 -6 106 40 130c49 26 109 5 132 -45
+l193 -415l101 -196c16 -31 63 -18 61 16l-12 224c-3 55 40 101 95 102c52 0 94 -44 97 -96z" />
+ <glyph glyph-name="play" unicode="&#xf04b;" horiz-adv-x="1407"
+d="M1384 609l-1328 -738c-31 -17 -56 -2 -56 33v1472c0 35 25 50 56 33l1328 -738c31 -17 31 -45 0 -62z" />
+ <glyph glyph-name="heart-o" unicode="&#xf08a;" horiz-adv-x="1792"
+d="M1664 940c0 281 -190 340 -350 340c-149 0 -317 -161 -369 -223c-24 -29 -74 -29 -98 0c-52 62 -220 223 -369 223c-160 0 -350 -59 -350 -340c0 -183 185 -353 187 -355l581 -560l580 559c3 3 188 173 188 356zM1792 940c0 -240 -220 -441 -229 -450l-623 -600
+c-12 -12 -28 -18 -44 -18s-32 6 -44 18l-624 602c-8 7 -228 208 -228 448c0 293 179 468 478 468c175 0 339 -138 418 -216c79 78 243 216 418 216c299 0 478 -175 478 -468z" />
+ <glyph glyph-name="weibo" unicode="&#xf18a;" horiz-adv-x="1792"
+d="M675 252c28 46 13 99 -34 119c-45 19 -105 -1 -133 -45c-29 -45 -15 -98 30 -119c46 -21 108 -1 137 45zM769 373c10 18 4 38 -14 45c-18 6 -40 -2 -50 -19c-10 -18 -5 -37 13 -45c18 -7 41 1 51 19zM943 266c-60 -136 -234 -210 -382 -162c-143 46 -203 187 -141 314
+c62 124 221 194 362 158c147 -38 221 -176 161 -310zM1255 426c-19 195 -275 329 -572 300c-297 -30 -521 -211 -502 -406s275 -329 572 -300c297 30 521 211 502 406zM1563 422c0 -225 -324 -508 -811 -508c-372 0 -752 180 -752 477c0 155 98 334 267 503
+c226 226 489 328 588 229c44 -43 48 -119 20 -209c-14 -46 43 -20 43 -21c182 77 341 81 399 -2c31 -44 28 -106 0 -178c-13 -33 4 -38 29 -46c103 -32 217 -109 217 -245zM1489 1046c57 -63 73 -150 48 -226c-10 -31 -43 -48 -74 -38s-48 43 -38 74c12 38 4 80 -24 111
+s-69 43 -107 35c-32 -7 -64 13 -70 45c-7 32 13 63 45 70c78 17 163 -7 220 -71zM1670 1209c118 -130 149 -308 99 -464c-12 -36 -50 -56 -86 -44s-56 50 -45 86c36 111 14 238 -70 330c-84 93 -207 128 -321 104c-37 -8 -74 16 -82 53s16 73 53 81c161 34 334 -15 452 -146
+z" />
+ <glyph glyph-name="angle-down" unicode="&#xf107;" horiz-adv-x="998"
+d="M998 800c0 -8 -4 -17 -10 -23l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 14 10 23 10c8 0 17 -4 23 -10l393 -393l393 393c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="cc-jcb" unicode="&#xf24b;" horiz-adv-x="2304"
+d="M1951 538c0 -36 -24 -62 -54 -68c-4 -1 -13 -2 -18 -2h-153v140h153c5 0 14 -1 18 -2c30 -6 54 -33 54 -68zM1933 751c0 -35 -24 -58 -53 -63c-3 -1 -10 -1 -15 -1h-139v129h139c5 0 12 -1 15 -1c29 -5 53 -29 53 -64zM728 587v308h-228v-308c0 -75 -51 -131 -143 -131
+c-78 0 -155 23 -229 59v-112c120 -33 272 -33 272 -33c254 0 328 97 328 217zM1442 403v113c-52 -27 -118 -53 -200 -59c-144 -11 -230 59 -230 183s86 194 230 183c82 -6 147 -31 200 -58v112c-107 27 -208 31 -208 31c-352 16 -452 -123 -452 -268s100 -284 452 -268
+c0 0 101 4 208 31zM2176 518c0 74 -66 122 -152 128v3c78 11 121 62 121 121c0 76 -63 120 -148 124c-6 0 -17 1 -26 1h-455v-510h491c97 0 169 52 169 133zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h2048
+c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="compress" unicode="&#xf066;" horiz-adv-x="1510"
+d="M755 576v-448c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-144 144l-332 -332c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-114 114c-6 6 -10 15 -10 23s4 17 10 23l332 332l-144 144c-12 12 -19 28 -19 45c0 35 29 64 64 64h448c35 0 64 -29 64 -64zM1510 1248
+c0 -8 -4 -17 -10 -23l-332 -332l144 -144c12 -12 19 -28 19 -45c0 -35 -29 -64 -64 -64h-448c-35 0 -64 29 -64 64v448c0 35 29 64 64 64c17 0 33 -7 45 -19l144 -144l332 332c6 6 15 10 23 10s17 -4 23 -10l114 -114c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="pencil-square-o" unicode="&#xf044;" horiz-adv-x="1784"
+d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072c-9 9 -24 8 -33 -1l-350 -350c-9 -9 -10 -24 -1 -33s24 -8 33 1l350 350c9 9 10 24 1 33zM1408 478v-190c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832
+c40 0 80 -8 117 -25c9 -4 16 -13 18 -23c2 -11 -1 -21 -9 -29l-49 -49c-9 -9 -21 -12 -32 -8c-15 4 -30 6 -45 6h-832c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160v126c0 8 3 16 9 22l64 64c10 10 23 12 35 7s20 -16 20 -29zM1312 1216
+l288 -288l-672 -672h-288v288zM1756 1084l-92 -92l-288 288l92 92c37 37 99 37 136 0l152 -152c37 -37 37 -99 0 -136z" />
+ <glyph glyph-name="google-plus-square" unicode="&#xf0d4;"
+d="M917 631c0 25 -3 45 -6 64h-362v-132h217c-8 -56 -65 -165 -217 -165c-132 0 -239 108 -239 242s107 242 239 242c74 0 124 -31 153 -59l104 101c-67 62 -154 100 -257 100c-213 0 -384 -172 -384 -384s171 -384 384 -384c221 0 368 156 368 375zM1262 585h109v110h-109
+v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="keybase" unicode="&#xf2f4;" horiz-adv-x="1547"
+d="M146 -80c-13 28 -30 67 -39 87l-13 38l-44 -49l-44 -48l-4 92c-7 131 4 267 26 363c50 214 208 408 411 511l45 21l-10 33c-7 17 -14 55 -16 79l-4 46l-46 4c-70 7 -107 26 -131 76c-13 26 -13 31 -9 101c4 92 12 111 40 142c35 39 59 45 146 41c63 -4 77 -6 105 -19
+c17 -9 33 -18 35 -18s22 24 46 57l41 59l26 -15c15 -9 33 -20 42 -24l15 -9l-13 -33c-7 -17 -16 -48 -18 -63l-4 -31l37 -4c133 -13 234 -94 271 -216c11 -39 11 -116 0 -153c-11 -35 -11 -37 -2 -37c15 0 118 -51 159 -77c81 -52 175 -143 227 -222
+c98 -146 140 -306 123 -481c-9 -105 -29 -187 -64 -268l-13 -31h-109l26 52c28 57 50 136 61 206c7 48 10 179 3 203l-5 15l-28 -31c-70 -76 -172 -98 -310 -61c-118 31 -167 37 -278 37c-85 0 -113 -2 -159 -13c-127 -28 -217 -69 -341 -159c-46 -33 -83 -59 -85 -59
+s4 22 13 50s24 74 33 105l17 55l-19 -20c-11 -11 -42 -42 -68 -70l-46 -50l11 -42c13 -55 44 -122 77 -172c13 -22 24 -40 24 -42s-26 -2 -57 -2h-57zM338 449c105 111 190 200 192 200c2 -2 -8 -35 -19 -72c-72 -227 -87 -271 -85 -273c0 0 26 9 54 20
+c186 81 402 92 631 31c103 -26 142 -26 192 0c28 15 40 23 53 45c24 37 26 90 11 138c-37 105 -182 240 -317 299c-70 31 -74 30 -89 15l-14 -13l57 -69c31 -37 64 -79 68 -90c13 -26 15 -68 2 -94c-17 -37 -70 -64 -111 -55c-17 4 -25 3 -42 -10c-48 -35 -100 -26 -144 26
+c-35 39 -44 59 -46 98c0 20 -7 43 -11 52c-7 13 -8 28 -8 48l2 31l-29 7c-39 11 -85 32 -111 52c-13 9 -24 17 -28 17s-33 -13 -64 -28c-212 -109 -349 -312 -371 -541c-2 -22 -4 -51 -6 -62l-3 -19l24 24c11 11 107 112 212 223zM904 610c20 15 37 28 41 28
+c2 0 9 -6 16 -15c11 -17 30 -17 39 -2c7 11 7 13 -122 170c-76 94 -92 110 -103 110c-26 -2 -19 -23 22 -73l39 -48l-22 -17c-24 -22 -26 -26 -11 -39c11 -11 13 -9 35 6l24 15l16 -13c9 -7 13 -17 13 -19c0 -4 -17 -20 -37 -37c-20 -15 -35 -34 -35 -38c0 -7 10 -24 30 -48
+c7 -13 18 -8 55 20zM679 920c13 39 56 70 100 70c24 0 59 -20 83 -46l22 -26l20 24c55 61 61 147 17 221c-33 55 -94 87 -179 96c-46 4 -57 8 -81 32l-17 18l-9 -13c-17 -26 -54 -111 -65 -144c-15 -50 -9 -129 11 -168c20 -37 72 -88 87 -81c2 -2 7 6 11 17zM484 1217
+c4 11 16 39 27 61s19 44 19 51c0 20 -21 28 -80 32c-52 4 -57 3 -68 -8c-9 -9 -13 -20 -13 -35c0 -13 -3 -37 -5 -57c-4 -46 2 -54 48 -61c68 -4 65 -5 72 17zM417 1270c0 37 4 41 35 41h28v-61h-61v20h-2zM554 -4c-13 13 -17 22 -17 44c0 41 24 66 63 66
+c37 0 64 -27 64 -64c0 -39 -25 -61 -66 -63c-22 0 -31 4 -44 17zM976 -10c-50 39 -24 116 39 116c39 0 61 -25 63 -66c0 -24 -2 -31 -17 -44s-22 -17 -44 -17c-20 0 -32 4 -41 11z" />
+ <glyph glyph-name="angle-right" unicode="&#xf105;" horiz-adv-x="582"
+d="M582 576c0 -8 -4 -17 -10 -23l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 14 -10 23c0 8 4 17 10 23l393 393l-393 393c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="forumbee" unicode="&#xf211;"
+d="M934 1386c-423 -161 -756 -499 -914 -923c-13 58 -20 117 -20 176c0 423 342 766 765 766c57 0 114 -7 169 -19zM1203 1267c62 -43 117 -95 164 -155c-518 -151 -923 -558 -1071 -1077c-59 46 -112 100 -155 162c149 514 549 918 1062 1070zM470 -67
+c154 475 526 849 999 1006c27 -62 45 -128 54 -195c-390 -160 -700 -472 -859 -863c-67 9 -132 26 -194 52zM1536 -125c-124 32 -247 70 -367 115c-88 -55 -187 -92 -290 -107c146 273 371 499 643 646c-14 -100 -49 -198 -101 -284c45 -121 83 -245 115 -370z" />
+ <glyph glyph-name="eject" unicode="&#xf052;" horiz-adv-x="1538"
+d="M14 557l710 710c25 25 65 25 90 0l710 -710c25 -25 16 -45 -19 -45h-1472c-35 0 -44 20 -19 45zM1473 0h-1408c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h1408c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64z" />
+ <glyph glyph-name="mobile" unicode="&#xf10b;" horiz-adv-x="768"
+d="M464 128c0 44 -36 80 -80 80s-80 -36 -80 -80s36 -80 80 -80s80 36 80 80zM672 288v704c0 17 -15 32 -32 32h-512c-17 0 -32 -15 -32 -32v-704c0 -17 15 -32 32 -32h512c17 0 32 15 32 32zM480 1136c0 9 -7 16 -16 16h-160c-9 0 -16 -7 -16 -16s7 -16 16 -16h160
+c9 0 16 7 16 16zM768 1152v-1024c0 -70 -58 -128 -128 -128h-512c-70 0 -128 58 -128 128v1024c0 70 58 128 128 128h512c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="hourglass-end" unicode="&#xf253;"
+d="M1408 1408c0 -370 -177 -638 -373 -768c196 -130 373 -398 373 -768h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96c0 370 177 638 373 768c-196 130 -373 398 -373 768h-96c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h1472c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96zM874 700c202 76 406 343 406 708h-1024c0 -365 204 -632 406 -708c25 -9 42 -33 42 -60s-17 -51 -42 -60c-86 -32 -173 -100 -244 -196h700c-71 96 -158 164 -244 196c-25 9 -42 33 -42 60
+s17 51 42 60z" />
+ <glyph glyph-name="trash-o" unicode="&#xf014;" horiz-adv-x="1408"
+d="M512 800v-576c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM768 800v-576c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1024 800v-576c0 -18 -14 -32 -32 -32h-64
+c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1152 76v948h-896v-948c0 -48 27 -76 32 -76h832c5 0 32 28 32 76zM480 1152h448l-48 117c-3 4 -12 10 -17 11h-317c-6 -1 -14 -7 -17 -11zM1408 1120v-64c0 -18 -14 -32 -32 -32h-96v-948
+c0 -110 -72 -204 -160 -204h-832c-88 0 -160 90 -160 200v952h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h309l70 167c20 49 80 89 133 89h320c53 0 113 -40 133 -89l70 -167h309c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="star-o" unicode="&#xf006;" horiz-adv-x="1664"
+d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889c0 -18 -13 -35 -26 -48l-363 -354l86 -500c1 -7 1 -13 1 -20c0 -27 -12 -50 -41 -50c-14 0 -28 5 -40 12l-449 236l-449 -236c-13 -7 -26 -12 -40 -12
+c-29 0 -42 24 -42 50c0 7 1 13 2 20l86 500l-364 354c-12 13 -25 30 -25 48c0 30 31 42 56 46l502 73l225 455c9 19 26 41 49 41s40 -22 49 -41l225 -455l502 -73c24 -4 56 -16 56 -46z" />
+ <glyph glyph-name="floppy-o" unicode="&#xf0c7;"
+d="M384 0h768v384h-768v-384zM1280 0h128v896c0 19 -17 60 -30 73l-281 281c-14 14 -53 30 -73 30v-416c0 -53 -43 -96 -96 -96h-576c-53 0 -96 43 -96 96v416h-128v-1280h128v416c0 53 43 96 96 96h832c53 0 96 -43 96 -96v-416zM896 928v320c0 17 -15 32 -32 32h-192
+c-17 0 -32 -15 -32 -32v-320c0 -17 15 -32 32 -32h192c17 0 32 15 32 32zM1536 896v-928c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1344c0 53 43 96 96 96h928c53 0 126 -30 164 -68l280 -280c38 -38 68 -111 68 -164z" />
+ <glyph glyph-name="file-powerpoint-o" unicode="&#xf1c4;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM416 106h92v555h-92v107h368c46 0 92 -4 130 -19c83 -35 137 -119 137 -228s-56 -202 -146 -233c-36 -13 -75 -15 -118 -15h-137v-167h93v-106h-327v106zM769 386c31 0 57 5 78 15c42 21 62 64 62 120c0 53 -20 94 -56 115c-21 12 -48 18 -83 18h-120v-268
+h119z" />
+ <glyph glyph-name="cc-discover" unicode="&#xf1f2;" horiz-adv-x="2304"
+d="M313 759c0 -32 -13 -63 -36 -84c-20 -18 -47 -26 -89 -26h-17v220h17c42 0 68 -7 89 -27c23 -20 36 -51 36 -83zM2089 824c0 -34 -22 -52 -64 -52h-19v101h20c41 0 63 -17 63 -49zM380 759c0 98 -73 167 -179 167h-95v-333h95c50 0 87 11 119 38c38 32 60 79 60 128z
+M410 593h65v333h-65v-333zM730 694c0 53 -22 77 -96 104c-39 14 -50 24 -50 42c0 21 20 37 48 37c20 0 36 -8 53 -27l34 44c-28 25 -62 37 -98 37c-59 0 -104 -41 -104 -95c0 -46 21 -70 82 -92c25 -9 38 -14 45 -19c13 -8 19 -20 19 -34c0 -27 -21 -47 -50 -47
+c-31 0 -56 15 -71 44l-42 -40c30 -44 66 -64 115 -64c68 0 115 45 115 110zM1008 604v77c-26 -26 -49 -37 -78 -37c-66 0 -112 48 -112 115c0 64 48 115 109 115c31 0 54 -11 81 -38v77c-28 14 -52 20 -80 20c-98 0 -177 -77 -177 -174c0 -98 77 -174 176 -174
+c28 0 52 5 81 19zM2240 0v527c-160 -100 -723 -420 -1633 -591h1569c35 0 64 29 64 64zM1389 757c0 100 -81 181 -181 181s-181 -81 -181 -181s81 -181 181 -181s181 81 181 181zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56
+h-115v74h119v57h-184v-333zM2105 593h80l-105 140c49 10 76 43 76 94c0 63 -43 99 -118 99h-97v-333h65v133h9zM2304 1274v-1268c0 -74 -59 -134 -132 -134h-2040c-73 0 -132 60 -132 134v1268c0 74 59 134 132 134h2040c73 0 132 -60 132 -134z" />
+ <glyph glyph-name="bomb" unicode="&#xf1e2;" horiz-adv-x="1792"
+d="M571 947c-13 33 -50 48 -83 35c-144 -58 -260 -174 -318 -318c-13 -33 2 -70 35 -83c8 -3 16 -5 24 -5c26 0 49 15 60 40c45 112 135 202 247 247c33 14 49 51 35 84zM1513 1303l46 -46l-244 -243l68 -68c25 -25 25 -66 0 -91l-64 -64c56 -101 89 -218 89 -343
+c0 -389 -315 -704 -704 -704s-704 315 -704 704s315 704 704 704c125 0 242 -33 343 -89l64 64c25 25 66 25 91 0l68 -68zM1521 1359c-6 -6 -14 -10 -22 -10c-9 0 -17 4 -23 10l-91 90c-12 13 -12 33 0 46c13 12 33 12 46 0l90 -91c13 -12 13 -33 0 -45zM1751 1129
+c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-90 91c-13 12 -13 33 0 45c12 13 33 13 45 0l91 -90c12 -13 12 -33 0 -46zM1792 1312c0 -18 -14 -32 -32 -32h-96c-18 0 -32 14 -32 32s14 32 32 32h96c18 0 32 -14 32 -32zM1600 1504v-96c0 -18 -14 -32 -32 -32s-32 14 -32 32v96
+c0 18 14 32 32 32s32 -14 32 -32zM1751 1449l-91 -90c-6 -6 -14 -10 -22 -10c-9 0 -17 4 -23 10c-13 12 -13 33 0 45l90 91c13 12 33 12 46 0c12 -13 12 -33 0 -46z" />
+ <glyph glyph-name="random" unicode="&#xf074;" horiz-adv-x="1792"
+d="M666 1055c-56 -86 -97 -179 -137 -273c-58 121 -122 242 -273 242h-224c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h224c178 0 309 -83 410 -225zM1792 256c0 -8 -3 -17 -9 -23l-320 -320c-6 -6 -15 -9 -23 -9c-17 0 -32 15 -32 32v192c-297 0 -480 -35 -665 225
+c55 86 96 179 136 273c58 -121 122 -242 273 -242h256v192c0 18 14 32 32 32c9 0 17 -4 24 -10l319 -319c6 -6 9 -15 9 -23zM1792 1152c0 -8 -3 -17 -9 -23l-320 -320c-6 -6 -15 -9 -23 -9c-17 0 -32 14 -32 32v192h-256c-133 0 -196 -91 -252 -199
+c-29 -56 -54 -114 -78 -171c-111 -258 -241 -526 -566 -526h-224c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h224c133 0 196 91 252 199c29 56 54 114 78 171c111 258 241 526 566 526h256v192c0 18 14 32 32 32c9 0 17 -4 24 -10l319 -319c6 -6 9 -15 9 -23z" />
+ <glyph glyph-name="fire-extinguisher" unicode="&#xf134;" horiz-adv-x="1408"
+d="M512 1344c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1408 1376v-320c0 -10 -4 -19 -12 -25c-6 -5 -13 -7 -20 -7c-2 0 -4 0 -7 1l-448 96c-14 3 -25 16 -25 31h-256v-102c146 -30 256 -159 256 -314v-800c0 -35 -29 -64 -64 -64h-512
+c-35 0 -64 29 -64 64v800c0 143 94 265 224 305v111h-32c-212 0 -326 -219 -327 -221c-11 -22 -34 -35 -57 -35c-10 0 -20 2 -29 7c-31 16 -44 54 -28 86c5 10 105 204 306 269c-15 25 -25 54 -25 86c0 88 72 160 160 160s160 -72 160 -160c0 -23 -5 -44 -14 -64h302
+c0 15 11 28 25 31l448 96c3 1 5 1 7 1c7 0 14 -2 20 -7c8 -6 12 -15 12 -25z" />
+ <glyph glyph-name="gnu-social" unicode="&#xf2e7;" horiz-adv-x="1513"
+d="M218 1404v0h1077c121 0 218 -97 218 -218v-873c0 -121 -97 -218 -218 -218h-118c-80 -349 -645 -351 -645 -351s334 104 335 351h-649c-121 0 -218 97 -218 218v873c0 121 97 218 218 218zM532 1229c-35 -5 -114 -89 -114 -150c0 -49 -3 -127 70 -167
+c-69 -67 -82 -163 -81 -247c2 -154 67 -382 357 -397s352 214 352 360h-305l50 -134l89 5s17 -107 -174 -100c-122 5 -200 68 -200 249s22 211 193 218s203 -139 203 -139l142 -3s-11 107 -93 188c73 40 72 118 69 167c-2 47 -102 169 -125 148s39 -41 34 -143
+c-2 -45 11 -79 -75 -79c-57 0 -33 51 -105 51c-43 0 -59 -28 -65 -50c-6 22 -21 50 -64 50c-72 0 -49 -51 -106 -51c-86 0 -72 34 -74 79c-5 102 56 122 33 143c-1 1 -3 2 -5 2h-6z" />
+ <glyph glyph-name="pencil-square" unicode="&#xf14b;"
+d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818c8 -7 6 -21 -3 -30l-291 -291c-9 -9 -23 -11 -30 -3c-8 7 -6 21 3 30l291 291c9 9 23 11 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92c37 37 37 99 0 136l-152 152c-37 37 -99 37 -136 0
+l-92 -92zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="reddit-square" unicode="&#xf1a2;"
+d="M939 407c7 -7 7 -19 0 -26c-49 -49 -143 -53 -171 -53s-122 4 -171 53c-7 7 -7 19 0 26c7 8 19 8 26 0c31 -31 98 -42 145 -42s114 11 145 42c7 8 19 8 26 0zM676 563c0 -42 -35 -77 -77 -77s-77 35 -77 77c0 43 35 77 77 77s77 -34 77 -77zM1014 563
+c0 -42 -35 -77 -77 -77s-77 35 -77 77c0 43 35 77 77 77s77 -34 77 -77zM1229 666c0 56 -46 102 -103 102c-28 0 -54 -12 -73 -31c-70 48 -164 79 -267 82l54 243l171 -39c1 -42 35 -76 77 -76s77 35 77 77s-35 77 -77 77c-30 0 -56 -17 -69 -43l-189 42
+c-10 3 -19 -4 -21 -13l-60 -268c-103 -4 -196 -35 -265 -83c-19 20 -45 32 -74 32c-57 0 -103 -46 -103 -102c0 -41 24 -76 58 -93c-3 -15 -5 -32 -5 -48c0 -163 183 -295 409 -295s410 132 410 295c0 17 -2 33 -6 49c33 17 56 52 56 92zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="arrow-circle-o-down" unicode="&#xf01a;"
+d="M1120 608c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v352c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-352h192c18 0 32 -14 32 -32zM768 1184c-300 0 -544 -244 -544 -544s244 -544 544 -544
+s544 244 544 544s-244 544 -544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="caret-left" unicode="&#xf0d9;" horiz-adv-x="576"
+d="M576 1088v-896c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-448 448c-12 12 -19 28 -19 45s7 33 19 45l448 448c12 12 28 19 45 19c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="camera-retro" unicode="&#xf083;" horiz-adv-x="1792"
+d="M928 704c0 18 -14 32 -32 32c-88 0 -160 -72 -160 -160c0 -18 14 -32 32 -32s32 14 32 32c0 53 43 96 96 96c18 0 32 14 32 32zM1152 574c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256zM128 0h1536v128h-1536v-128zM1280 574
+c0 212 -172 384 -384 384s-384 -172 -384 -384s172 -384 384 -384s384 172 384 384zM256 1216h384v128h-384v-128zM128 1024h1536v256h-828l-64 -128h-644v-128zM1792 1280v-1280c0 -71 -57 -128 -128 -128h-1536c-71 0 -128 57 -128 128v1280c0 71 57 128 128 128h1536
+c71 0 128 -57 128 -128z" />
+ <glyph glyph-name="thumbs-o-up" unicode="&#xf087;"
+d="M256 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1408 768c0 68 -61 128 -128 128h-352c0 117 96 202 96 320c0 117 -23 192 -160 192c-64 -65 -31 -218 -128 -320c-28 -29 -52 -60 -77 -91c-45 -58 -164 -229 -243 -229h-32v-640h32
+c56 0 148 -36 202 -55c110 -38 224 -73 342 -73h121c113 0 192 45 192 167c0 19 -2 38 -5 56c42 23 65 80 65 126c0 24 -6 48 -18 69c34 32 53 72 53 119c0 32 -14 79 -35 103c47 1 75 91 75 128zM1536 769c0 -58 -17 -115 -49 -163c6 -22 9 -46 9 -69
+c0 -50 -13 -100 -38 -144c2 -14 3 -29 3 -43c0 -64 -21 -128 -60 -178c2 -189 -127 -300 -312 -300h-129c-142 0 -274 42 -406 88c-29 10 -110 40 -138 40h-288c-71 0 -128 57 -128 128v640c0 71 57 128 128 128h274c39 26 107 116 137 155c34 44 69 87 107 128
+c60 64 28 222 128 320c24 23 56 37 90 37c104 0 204 -37 253 -134c31 -61 35 -119 35 -186c0 -70 -18 -130 -48 -192h176c138 0 256 -117 256 -255z" />
+ <glyph glyph-name="product-hunt" unicode="&#xf288;" horiz-adv-x="1792"
+d="M1150 774c0 -74 -60 -134 -135 -134h-253v269h253c75 0 135 -60 135 -135zM1329 774c0 174 -140 314 -314 314h-433v-896h180v269h253c174 0 314 140 314 313zM1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="etsy" unicode="&#xf2d7;"
+d="M518 1353v-655c232 -2 354 10 354 10c94 3 108 27 130 119l33 142h103l-14 -322l7 -319h-103l-29 127c-21 95 -62 118 -129 119c0 0 -86 8 -352 8v-556c0 -104 57 -153 177 -153h357c120 0 228 12 302 183l93 216h89c-7 -43 -55 -440 -62 -528c-329 12 -470 12 -470 12
+h-628l-376 -12v102l127 25c89 17 116 43 117 116c6 242 8 643 8 643s3 402 -8 645c-3 83 -28 103 -117 120l-127 24v102l376 -12h702s139 0 374 27c-14 -153 -31 -506 -31 -506h-93l-32 124c-39 155 -91 238 -187 238h-548c-41 0 -43 -14 -43 -39z" />
+ <glyph glyph-name="copyright" unicode="&#xf1f9;"
+d="M1150 462v-109c0 -141 -225 -193 -366 -193c-274 0 -480 209 -480 485c0 271 204 475 475 475c99 0 358 -35 358 -194v-109c0 -9 -7 -16 -16 -16h-118c-9 0 -16 7 -16 16v70c0 63 -121 92 -203 92c-187 0 -317 -135 -317 -329c0 -201 136 -348 325 -348
+c72 0 208 27 208 90v70c0 9 7 16 15 16h119c8 0 16 -7 16 -16zM768 1280c-353 0 -640 -287 -640 -640s287 -640 640 -640s640 287 640 640s-287 640 -640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="pleroma" unicode="&#xf324;" horiz-adv-x="961"
+d="M120 1408h262v-1536h-382v1416c0 66 54 120 120 120zM575 1408h386v-648c0 -66 -53 -120 -119 -120v0h-267v768zM575 254h386v-262c0 -66 -53 -120 -119 -120v0h-267v382z" />
+ <glyph glyph-name="terminal" unicode="&#xf120;" horiz-adv-x="1651"
+d="M572 553l-466 -466c-13 -13 -33 -13 -46 0l-50 50c-13 13 -13 33 0 46l393 393l-393 393c-13 13 -13 33 0 46l50 50c13 13 33 13 46 0l466 -466c13 -13 13 -33 0 -46zM1651 96v-64c0 -18 -14 -32 -32 -32h-960c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h960
+c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="twitter-square" unicode="&#xf081;"
+d="M1280 926c-38 -17 -78 -28 -121 -34c44 26 77 68 93 117c-41 -24 -86 -42 -134 -51c-38 41 -93 66 -153 66c-116 0 -210 -94 -210 -210c0 -16 1 -33 5 -48c-175 9 -330 92 -434 220c-18 -31 -29 -68 -29 -106c0 -73 34 -137 91 -175c-35 1 -68 11 -100 26v-2
+c0 -102 77 -187 173 -206c-18 -5 -32 -8 -51 -8c-13 0 -26 2 -39 4c27 -83 104 -144 196 -146c-72 -56 -162 -90 -261 -90c-17 0 -34 1 -50 3c93 -59 203 -94 322 -94c386 0 598 320 598 598c0 9 0 18 -1 27c41 29 77 66 105 109zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="shopping-bag" unicode="&#xf290;" horiz-adv-x="1793"
+d="M1757 128l35 -313c2 -18 -4 -36 -16 -50c-12 -13 -30 -21 -48 -21h-1664c-18 0 -36 8 -48 21c-12 14 -18 32 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775c4 32 31 57 64 57h256v-128c0 -71 57 -128 128 -128s128 57 128 128v128h384v-128c0 -71 57 -128 128 -128
+s128 57 128 128v128h256c33 0 60 -25 64 -57zM1280 1152v-256c0 -35 -29 -64 -64 -64s-64 29 -64 64v256c0 141 -115 256 -256 256s-256 -115 -256 -256v-256c0 -35 -29 -64 -64 -64s-64 29 -64 64v256c0 212 172 384 384 384s384 -172 384 -384z" />
+ <glyph glyph-name="stop-circle" unicode="&#xf28d;"
+d="M1088 352v576c0 18 -14 32 -32 32h-576c-18 0 -32 -14 -32 -32v-576c0 -18 14 -32 32 -32h576c18 0 32 14 32 32zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="telegram" unicode="&#xf2c6;" horiz-adv-x="1792"
+d="M1189 229l147 693c13 61 -22 85 -62 70l-864 -333c-59 -23 -58 -56 -10 -71l221 -69l513 323c24 16 46 7 28 -9l-415 -375l-16 -228c23 0 33 10 45 22l108 104l224 -165c41 -23 70 -11 81 38zM1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896
+s896 -401 896 -896z" />
+ <glyph glyph-name="circle" unicode="&#xf111;"
+d="M1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="columns" unicode="&#xf0db;" horiz-adv-x="1664"
+d="M160 0h608v1152h-640v-1120c0 -17 15 -32 32 -32zM1536 32v1120h-640v-1152h608c17 0 32 15 32 32zM1664 1248v-1216c0 -88 -72 -160 -160 -160h-1344c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1344c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="zotero" unicode="&#xf309;" horiz-adv-x="1330"
+d="M662 -127l-662 310v924l662 301l668 -301v-924zM314 152h723v221l-63 78h-275l338 379v218l-63 78h-601l-59 -82v-214h377l-352 -379l-25 -97v-202z" />
+ <glyph glyph-name="sign-out" unicode="&#xf08b;" horiz-adv-x="1568"
+d="M640 96c0 -28 13 -96 -32 -96h-320c-159 0 -288 129 -288 288v704c0 159 129 288 288 288h320c17 0 32 -15 32 -32c0 -28 13 -96 -32 -96h-320c-88 0 -160 -72 -160 -160v-704c0 -88 72 -160 160 -160h288c25 0 64 5 64 -32zM1568 640c0 -17 -7 -33 -19 -45l-544 -544
+c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v288h-448c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h448v288c0 35 29 64 64 64c17 0 33 -7 45 -19l544 -544c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="cube" unicode="&#xf1b2;" horiz-adv-x="1664"
+d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768c0 -47 -26 -90 -67 -112l-704 -384c-19 -11 -40 -16 -61 -16s-42 5 -61 16l-704 384c-41 22 -67 65 -67 112v768c0 54 34 102 84 120l704 256c14 5 29 8 44 8s30 -3 44 -8
+l704 -256c50 -18 84 -66 84 -120z" />
+ <glyph glyph-name="mars-stroke-v" unicode="&#xf22a;" horiz-adv-x="1152"
+d="M640 892c288 -32 512 -276 512 -572c0 -340 -294 -611 -642 -572c-270 30 -486 253 -508 525c-25 317 207 586 510 619v132h-160c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h160v165l-92 -92c-13 -12 -33 -12 -45 0l-46 46c-12 12 -12 32 0 45l202 201c25 25 65 25 90 0
+l202 -201c12 -13 12 -33 0 -45l-46 -46c-12 -12 -32 -12 -45 0l-92 92v-165h160c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-160v-132zM576 -128c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="file-text" unicode="&#xf15c;"
+d="M1468 1060c10 -10 19 -22 28 -36h-472v472c14 -9 26 -18 36 -28zM992 896h544v-1056c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h800v-544c0 -53 43 -96 96 -96zM1152 160v64c0 18 -14 32 -32 32h-704c-18 0 -32 -14 -32 -32v-64
+c0 -18 14 -32 32 -32h704c18 0 32 14 32 32zM1152 416v64c0 18 -14 32 -32 32h-704c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h704c18 0 32 14 32 32zM1152 672v64c0 18 -14 32 -32 32h-704c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h704c18 0 32 14 32 32z" />
+ <glyph glyph-name="amazon" unicode="&#xf270;" horiz-adv-x="1736"
+d="M1523 60c30 15 53 -8 22 -48s-280 -268 -698 -268s-738 286 -836 404c-27 31 4 45 22 33c293 -178 751 -471 1490 -121zM1730 175c15 -20 0 -108 -26 -172c-26 -63 -64 -107 -85 -124c-22 -18 -38 -11 -26 15s77 186 51 220c-26 33 -148 17 -192 13c-43 -4 -52 -8 -56 1
+c-9 23 87 62 150 70c63 7 164 3 184 -23zM1336 618c0 -110 129 -211 129 -211l-227 -224c-89 84 -156 154 -156 154c-10 10 -18 22 -25 33c-181 -283 -734 -265 -734 173c0 408 483 463 678 470v127c0 27 10 150 -142 150c0 0 -152 0 -217 -198l-294 27
+c0 197 187 417 539 417c351 0 449 -228 449 -329v-589zM664 597c0 -203 337 -251 337 69v162c-135 -4 -337 -42 -337 -231z" />
+ <glyph glyph-name="smile-o" unicode="&#xf118;"
+d="M1134 461c-50 -161 -197 -269 -366 -269s-316 108 -366 269c-11 34 8 69 42 80c33 11 69 -8 80 -42c33 -107 132 -179 244 -179s211 72 244 179c11 34 47 53 81 42c33 -11 52 -46 41 -80zM640 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128
+s128 -57 128 -128zM1152 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1408 640c0 353 -287 640 -640 640s-640 -287 -640 -640s287 -640 640 -640s640 287 640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768
+s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="compass" unicode="&#xf14e;"
+d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544s544 244 544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="address-book" unicode="&#xf2b9;" horiz-adv-x="1664"
+d="M1201 298c0 177 -43 374 -221 374c-55 -32 -130 -87 -212 -87s-157 55 -212 87c-178 0 -221 -197 -221 -374c0 -99 65 -170 145 -170h576c80 0 145 71 145 170zM1028 892c0 144 -117 260 -260 260s-260 -116 -260 -260c0 -143 117 -259 260 -259s260 116 260 259z
+M1664 352v-192c0 -18 -14 -32 -32 -32h-96v-224c0 -88 -72 -160 -160 -160h-1216c-88 0 -160 72 -160 160v1472c0 88 72 160 160 160h1216c88 0 160 -72 160 -160v-224h96c18 0 32 -14 32 -32v-192c0 -18 -14 -32 -32 -32h-96v-128h96c18 0 32 -14 32 -32v-192
+c0 -18 -14 -32 -32 -32h-96v-128h96c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="list-ol" unicode="&#xf0cb;" horiz-adv-x="1777"
+d="M366 -84c0 -110 -86 -172 -190 -172c-63 0 -127 21 -172 66l57 88c27 -25 68 -45 106 -45c35 0 72 17 72 57c0 56 -64 59 -105 56l-26 56c36 46 69 97 112 136v1c-32 0 -65 -2 -97 -2v-53h-106v152h333v-88l-95 -115c67 -16 111 -68 111 -137zM368 543v-159h-362
+c-3 18 -6 36 -6 54c0 185 226 213 226 297c0 34 -21 52 -54 52c-35 0 -64 -30 -81 -58l-85 59c33 69 101 108 177 108c93 0 173 -55 173 -154c0 -148 -217 -181 -220 -259h127v60h105zM1777 224v-192c0 -17 -15 -32 -32 -32h-1216c-18 0 -32 15 -32 32v192c0 18 14 32 32 32
+h1216c17 0 32 -14 32 -32zM369 1123v-99h-335v99h107c0 81 1 162 1 243v12h-2c-11 -22 -31 -37 -50 -54l-71 76l136 127h106v-404h108zM1777 736v-192c0 -17 -15 -32 -32 -32h-1216c-18 0 -32 15 -32 32v192c0 18 14 32 32 32h1216c17 0 32 -14 32 -32zM1777 1248v-192
+c0 -17 -15 -32 -32 -32h-1216c-18 0 -32 15 -32 32v192c0 17 14 32 32 32h1216c17 0 32 -15 32 -32z" />
+ <glyph glyph-name="stumbleupon-circle" unicode="&#xf1a3;"
+d="M866 697l90 27v62c0 106 -90 191 -196 191s-196 -84 -196 -190v-283c0 -26 -21 -47 -47 -47s-46 21 -46 47v120h-151v-122c0 -109 88 -196 197 -196c107 0 196 86 196 193v280c0 26 21 47 47 47c25 0 46 -21 46 -47v-54zM1199 502v122h-150v-126c0 -26 -21 -47 -47 -47
+c-25 0 -46 21 -46 47v123l-90 -26l-60 28v-123c0 -107 89 -194 197 -194s196 87 196 196zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="slack" unicode="&#xf198;"
+d="M837 508l-205 69l66 197l205 -68zM979 1344c528 -158 651 -387 493 -915s-387 -651 -915 -493s-651 387 -493 915s387 651 915 493zM1256 671v0c13 41 -9 87 -51 101l-99 34l34 103c13 42 -8 88 -50 101c-47 13 -88 -14 -101 -51l-34 -103l-206 69l35 103
+c13 42 -9 88 -51 101c-47 13 -87 -13 -100 -50l-35 -104c-100 33 -111 39 -126 37c-32 -1 -63 -22 -74 -54c-13 -42 8 -88 50 -101l100 -33l-66 -198c-100 33 -112 39 -127 37c-32 -1 -63 -23 -74 -55c-13 -42 9 -87 51 -100l99 -34l-34 -103c-13 -42 8 -88 50 -101
+s88 9 101 51l34 103l206 -69l-35 -103c-13 -42 9 -88 51 -101s87 8 100 50l35 104l99 -34c42 -13 88 9 101 51s-8 88 -50 101l-100 33l66 198l100 -34c42 -13 88 9 101 51z" />
+ <glyph glyph-name="qq" unicode="&#xf1d6;" horiz-adv-x="1756"
+d="M252 730c-7 17 -8 34 -8 52c0 28 18 73 35 94c-1 26 10 79 30 96c0 185 143 418 310 498c103 49 211 66 324 66c88 0 184 -21 266 -55c235 -99 288 -283 338 -518l1 -5c29 -44 55 -96 55 -150c0 -27 -18 -54 -18 -78c0 -2 6 -10 7 -12c86 -127 164 -265 164 -423
+c0 -35 -19 -157 -75 -157c-39 0 -82 95 -96 121c-1 1 -2 1 -3 1l-5 -4c-32 -83 -67 -161 -132 -223c57 -55 149 -50 166 -145c-5 -11 -3 -23 -11 -34c-57 -86 -210 -97 -302 -97c-122 0 -221 32 -336 66c-24 7 -60 3 -86 6c-61 -67 -210 -85 -296 -85c-76 0 -370 5 -370 135
+c0 56 12 72 51 108c31 6 54 23 90 25c5 0 9 1 14 2c1 1 2 1 2 4l-2 3c-69 16 -166 190 -181 262l-5 3c-7 0 -10 -15 -12 -20c-22 -51 -74 -106 -132 -112h-1c-8 0 -5 8 -11 10c-14 33 -23 63 -23 100c0 200 96 348 252 466z" />
+ <glyph glyph-name="audio-description" unicode="&#xf29e;" horiz-adv-x="2304"
+d="M504 542h171l-1 265zM1530 641c0 111 -64 193 -197 193h-54v-388h52c125 0 199 91 199 195zM956 1018l1 -756c0 -19 -15 -34 -33 -34h-216c-18 0 -33 15 -33 34v62h-291l-55 -81c-6 -9 -17 -15 -28 -15h-267c-28 0 -44 31 -27 53l556 757c6 9 16 14 27 14h332
+c19 0 34 -15 34 -34zM1783 641c0 -263 -192 -413 -450 -413h-270c-19 0 -34 15 -34 34v756c0 19 15 34 34 34h268c260 0 452 -148 452 -411zM1939 640c0 0 4 -260 -148 -413h-51c136 162 139 414 139 414s2 198 -135 410h43c148 -169 152 -411 152 -411zM2123 640
+c0 0 4 -260 -149 -413h-51c136 162 139 414 139 414s2 198 -134 410h43c148 -169 152 -411 152 -411zM2304 640c0 0 4 -260 -148 -413h-51c135 162 138 414 138 414s2 198 -134 410h43c148 -169 152 -411 152 -411z" />
+ <glyph glyph-name="stop-circle-o" unicode="&#xf28e;"
+d="M768 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM768 96c300 0 544 244 544 544s-244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544zM480 320c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h576c18 0 32 -14 32 -32v-576
+c0 -18 -14 -32 -32 -32h-576z" />
+ <glyph glyph-name="grav" unicode="&#xf2d6;" horiz-adv-x="1794"
+d="M1291 1060c-32 36 -84 -25 -56 -58c27 -33 116 -9 56 58zM895 814c-11 -11 -28 -11 -38 0c-11 10 -11 27 0 37c10 11 27 11 38 0c10 -10 10 -27 0 -37zM1060 740l-35 -35c-16 -17 -43 -17 -60 0l-38 38c-16 17 -16 43 0 60l35 35c16 16 43 16 60 0l38 -39
+c16 -16 16 -43 0 -59zM951 870c-10 -10 -27 -10 -38 0c-10 11 -10 28 0 38c11 11 28 11 38 0c11 -10 11 -27 0 -38zM1354 968c-45 -85 -163 -120 -235 -69c-72 52 -122 156 -43 246c78 90 147 62 216 -3c43 -41 106 -90 62 -174zM1555 486c9 58 -74 60 -92 93
+c-49 87 -100 133 -197 110c42 29 85 22 85 22c1 23 0 47 -34 90c14 45 1 81 1 81c56 31 97 88 105 156c13 112 -68 214 -180 227c-80 9 -158 -28 -196 -93c-84 -145 5 -256 81 -294c-52 5 -124 43 -145 124c-24 93 10 180 32 222c0 0 -16 21 -29 32c0 0 -50 0 -89 -19
+c43 55 91 52 91 52c0 23 -2 54 -13 78c-20 41 -90 47 -117 -15c1 3 2 5 4 7c-18 -43 -4 -202 61 -315c-9 -5 -33 -22 -47 -36c-78 -35 -203 -218 -203 -218c-102 -39 -280 -184 -256 -288c1 -11 5 -20 11 -27c-10 -8 -20 -18 -30 -30c-43 -50 -19 -127 64 -88
+c57 26 108 73 132 110c0 0 -21 18 -60 16c100 24 125 34 168 33c29 -14 29 124 29 124c0 53 -8 112 -40 150c45 -44 105 -118 101 -219c-3 -66 -55 -83 -55 -83c-33 -60 -156 -238 -110 -383c0 0 -35 54 -37 80c-63 -70 -169 -189 -90 -233c96 -53 394 320 457 514
+c125 75 200 171 231 235c80 -159 346 -343 367 -215zM1794 640c0 -495 -402 -896 -897 -896s-897 401 -897 896s402 896 897 896s897 -401 897 -896z" />
+ <glyph glyph-name="mars-stroke-h" unicode="&#xf22b;" horiz-adv-x="1919"
+d="M1901 621c25 -25 25 -65 0 -90l-294 -294c-12 -13 -33 -13 -45 0l-45 45c-13 12 -13 33 0 45l185 185h-294v-224c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v224h-132c-32 -288 -276 -512 -572 -512c-340 0 -611 294 -572 642c30 270 253 486 525 508
+c317 25 586 -207 619 -510h132v224c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-224h294l-185 185c-13 12 -13 33 0 45l45 45c12 13 33 13 45 0zM576 128c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="gbp" unicode="&#xf154;" horiz-adv-x="1020"
+d="M1020 399v-367c0 -18 -14 -32 -32 -32h-956c-18 0 -32 14 -32 32v150c0 17 14 32 32 32h97v383h-95c-18 0 -32 14 -32 32v131c0 18 14 32 32 32h95v223c0 228 184 393 438 393c200 0 329 -120 335 -125c12 -11 13 -30 3 -43l-103 -127c-6 -7 -13 -11 -22 -12
+c-8 -1 -17 2 -23 7c-1 1 -87 69 -188 69c-113 0 -189 -68 -189 -170v-215h305c18 0 32 -14 32 -32v-131c0 -18 -14 -32 -32 -32h-305v-379h414v181c0 18 14 32 32 32h162c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="shaarli-o" unicode="&#xf2f6;" horiz-adv-x="1630"
+d="M859 1408v0c107 0 210 -67 264 -160c40 -69 61 -156 75 -252c115 -20 212 -47 288 -96c78 -50 134 -137 140 -229l3 -20c7 -91 -25 -191 -100 -245c-18 -13 -36 -22 -55 -30c11 -19 25 -36 34 -56c37 -84 43 -181 12 -267v-1h-1c-26 -70 -82 -133 -154 -160
+s-147 -24 -224 -5c-9 3 -17 5 -25 10c-94 47 -174 101 -239 162c-25 -34 -53 -66 -86 -91c-75 -57 -168 -84 -266 -84c-31 0 -62 -4 -90 5c-82 25 -155 68 -199 141s-44 164 -20 243l1 3l1 3l21 58c-57 19 -109 45 -151 86c-67 66 -95 165 -86 259h-1c0 1 1 2 1 3v7h1
+c8 100 75 193 165 238c87 43 192 57 317 60c6 109 27 206 84 283c66 89 177 135 290 135zM859 1288c-173 0 -260 -116 -260 -348c12 -37 -17 -59 -88 -67c-255 -1 -386 -66 -391 -196c-18 -141 68 -226 258 -253h19l-67 -186c-36 -117 11 -195 141 -235h53
+c155 0 260 80 314 239h37c58 -90 155 -170 294 -239c126 -31 206 -1 239 90c42 114 -12 238 -162 370c196 -10 285 53 264 190c3 117 -118 194 -360 231h-56c-21 269 -99 404 -235 404zM819 1097v0c3 0 6 0 9 -1c50 1 76 -51 76 -156v-188c22 -23 49 -31 84 -25
+c226 0 335 -27 327 -81c10 -49 -110 -65 -361 -48c-12 0 -14 -15 -6 -43c74 -85 140 -151 198 -200c59 -47 69 -92 31 -133c-32 -22 -74 -5 -127 49c-51 54 -117 122 -197 207c-18 24 -40 24 -67 0c-113 -230 -200 -325 -262 -288c-46 24 -23 105 68 242l54 116
+c12 33 -72 45 -250 36c-51 3 -77 22 -77 58c0 37 24 57 71 58l304 17c31 0 48 27 52 81l4 107c-1 131 22 195 69 192z" />
+ <glyph glyph-name="ban" unicode="&#xf05e;"
+d="M1312 643c0 109 -32 210 -87 295l-754 -753c86 -56 188 -89 297 -89c300 0 544 245 544 547zM313 344l755 754c-86 58 -189 91 -300 91c-300 0 -544 -245 -544 -546c0 -111 33 -213 89 -299zM1536 643c0 -426 -344 -771 -768 -771s-768 345 -768 771
+c0 425 344 770 768 770s768 -345 768 -770z" />
+ <glyph glyph-name="fighter-jet" unicode="&#xf0fb;" horiz-adv-x="1920"
+d="M1920 576c0 0 0 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69c35 0 64 -7 64 -16s-29 -16 -64 -16h-320v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h320c35 0 64 -7 64 -16
+s-29 -16 -64 -16h-69l293 -352h64l224 -64l352 -32c288 -64 288 -96 288 -96z" />
+ <glyph glyph-name="space-shuttle" unicode="&#xf197;" horiz-adv-x="2176"
+d="M620 416c-69 -40 -163 -64 -268 -64h-128v64h-64c-18 0 -32 36 -32 80c0 18 3 35 7 49c-77 2 -135 15 -135 31s58 29 135 31c-4 14 -7 31 -7 49c0 44 14 80 32 80h64v64h128c105 0 199 -24 268 -64h1113c74 -13 141 -24 187 -32c192 -32 256 -96 256 -128
+s-64 -96 -256 -128c-46 -8 -113 -19 -187 -32h-1113zM1739 668c32 -22 53 -55 53 -92s-21 -70 -53 -92l81 -30c41 29 68 73 68 122s-27 93 -68 122zM625 400h1015s-217 -38 -456 -80c-128 0 -224 -96 -224 -96l-288 -288s-97 -64 -160 -64h-96l-93 464h29
+c102 0 199 23 273 64zM352 816h-29l93 464h96c65 0 128 -32 160 -64l288 -288s96 -96 224 -96c239 -42 456 -80 456 -80h-1015c-74 41 -171 64 -273 64z" />
+ <glyph glyph-name="matrix-org" unicode="&#xf313;"
+d="M40 1373v-1466h106v-35h-146v1536h146v-35h-106zM491 908v-74h2c20 28 44 51 72 66c28 16 60 23 96 23c35 0 66 -7 95 -20s50 -37 65 -71c16 24 38 46 66 64s61 27 99 27c29 0 56 -4 81 -11s45 -18 63 -34s31 -35 41 -60s15 -56 15 -91v-367h-150v311c0 18 -1 36 -2 52
+s-6 30 -12 42s-16 22 -28 29s-29 10 -50 10s-38 -4 -51 -12s-24 -19 -31 -32s-13 -27 -15 -44s-4 -34 -4 -51v-305h-150v307c0 16 0 33 -1 49s-4 30 -9 44c-5 13 -15 24 -27 32s-31 12 -55 12c-7 0 -16 -2 -28 -5s-23 -9 -34 -18s-20 -21 -28 -38s-11 -38 -11 -65v-318h-151
+v548h142zM1496 -93v1466h-106v35h146v-1536h-146v35h106z" />
+ <glyph glyph-name="steam" unicode="&#xf1b6;" horiz-adv-x="1792"
+d="M1582 954c0 -135 -110 -244 -244 -244c-135 0 -244 109 -244 244s109 244 244 244c134 0 244 -109 244 -244zM812 212c0 139 -111 250 -250 250c-18 0 -36 -2 -54 -6l104 -42c102 -41 152 -156 111 -258s-157 -152 -259 -110c-41 16 -82 33 -123 49
+c42 -79 125 -133 221 -133c139 0 250 111 250 250zM1642 953c0 168 -137 305 -305 305c-169 0 -306 -137 -306 -305c0 -169 137 -305 306 -305c168 0 305 136 305 305zM1792 953c0 -252 -204 -455 -455 -455l-437 -319c-16 -172 -162 -307 -338 -307
+c-162 0 -299 115 -332 268l-230 92v429l389 -157c51 31 110 48 173 48c12 0 24 -1 35 -2l284 407c2 249 206 451 456 451c251 0 455 -204 455 -455z" />
+ <glyph glyph-name="bars" unicode="&#xf0c9;"
+d="M1536 192v-128c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1408c35 0 64 -29 64 -64zM1536 704v-128c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1408c35 0 64 -29 64 -64zM1536 1216v-128
+c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1408c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="lightbulb-o" unicode="&#xf0eb;" horiz-adv-x="1024"
+d="M736 960c0 -17 -15 -32 -32 -32s-32 15 -32 32c0 69 -107 96 -160 96c-17 0 -32 15 -32 32s15 32 32 32c93 0 224 -49 224 -160zM896 960c0 200 -203 320 -384 320s-384 -120 -384 -320c0 -64 26 -131 68 -180c19 -22 41 -43 61 -66c71 -85 131 -185 141 -298h228
+c10 113 70 213 141 298c20 23 42 44 61 66c42 49 68 116 68 180zM1024 960c0 -103 -34 -192 -103 -268s-160 -183 -168 -290c29 -17 47 -49 47 -82c0 -24 -9 -47 -25 -64c16 -17 25 -40 25 -64c0 -33 -17 -63 -45 -81c8 -14 13 -31 13 -47c0 -65 -51 -96 -109 -96
+c-26 -58 -84 -96 -147 -96s-121 38 -147 96c-58 0 -109 31 -109 96c0 16 5 33 13 47c-28 18 -45 48 -45 81c0 24 9 47 25 64c-16 17 -25 40 -25 64c0 33 18 65 47 82c-8 107 -99 214 -168 290s-103 165 -103 268c0 272 259 448 512 448s512 -176 512 -448z" />
+ <glyph glyph-name="map-pin" unicode="&#xf276;" horiz-adv-x="1024"
+d="M512 448c44 0 87 5 128 15v-655c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v655c41 -10 84 -15 128 -15zM512 1536c283 0 512 -229 512 -512s-229 -512 -512 -512s-512 229 -512 512s229 512 512 512zM512 1312c18 0 32 14 32 32s-14 32 -32 32
+c-194 0 -352 -158 -352 -352c0 -18 14 -32 32 -32s32 14 32 32c0 159 129 288 288 288z" />
+ <glyph glyph-name="circle-o" unicode="&#xf10c;"
+d="M768 1184c-300 0 -544 -244 -544 -544s244 -544 544 -544s544 244 544 544s-244 544 -544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="contao" unicode="&#xf26d;" horiz-adv-x="1748"
+d="M116 1408h197c-47 -43 -89 -93 -126 -149c-155 -239 -92 -501 -32 -783c49 -229 90 -447 233 -604h-272c-64 0 -116 52 -116 116v1304c0 64 52 116 116 116zM1324 1408h308c64 0 116 -52 116 -116v-1304c0 -64 -52 -116 -116 -116h-178c132 131 207 321 196 565
+l-469 -101c-6 -111 -44 -218 -196 -250c-85 -18 -155 2 -199 40c-54 46 -97 106 -169 448c-73 343 -58 415 -28 479c25 52 81 100 165 118c153 32 231 -51 282 -150l468 100c-46 118 -107 214 -180 287z" />
+ <glyph glyph-name="vine" unicode="&#xf1ca;" horiz-adv-x="1458"
+d="M1458 709v-198c-70 -16 -140 -23 -198 -23c-140 -294 -391 -546 -475 -593c-53 -30 -103 -32 -162 3c-103 62 -493 382 -623 1388h283c71 -604 245 -914 436 -1146c106 106 208 247 287 406c-189 96 -304 307 -304 553c0 249 143 437 388 437c238 0 368 -148 368 -403
+c0 -95 -20 -203 -58 -286c0 0 -176 -35 -241 78c13 43 31 117 31 184c0 119 -43 177 -108 177c-69 0 -117 -65 -117 -190c0 -255 162 -401 372 -401c37 0 79 4 121 14z" />
+ <glyph glyph-name="align-center" unicode="&#xf037;" horiz-adv-x="1792"
+d="M1792 192v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1408 576v-128c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h896c35 0 64 -29 64 -64zM1664 960v-128c0 -35 -29 -64 -64 -64
+h-1408c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1408c35 0 64 -29 64 -64zM1280 1344v-128c0 -35 -29 -64 -64 -64h-640c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h640c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="btc" unicode="&#xf15a;" horiz-adv-x="1202"
+d="M1111 896c13 -133 -43 -213 -131 -258c146 -35 238 -122 220 -317c-23 -243 -203 -308 -461 -322v-255h-154v251c-39 0 -80 0 -122 1v-252h-154v255c-36 0 -72 1 -109 1h-200l31 183c113 -2 111 0 111 0c43 0 55 31 58 51v402h16c-6 1 -12 1 -16 1v287
+c-6 32 -26 68 -89 68c0 0 2 2 -111 0v164l212 -1c31 0 64 0 97 1v252h154v-247c41 1 82 2 122 2v245h154v-252c198 -17 355 -78 372 -260zM896 351c0 198 -326 169 -430 169v-338c104 0 430 -22 430 169zM825 827c0 181 -272 154 -359 154v-307c87 0 359 -20 359 153z" />
+ <glyph glyph-name="calendar" unicode="&#xf073;" horiz-adv-x="1664"
+d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
+M512 1088v288c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-288c0 -17 15 -32 32 -32h64c17 0 32 15 32 32zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-288
+c0 -17 15 -32 32 -32h64c17 0 32 15 32 32zM1664 1152v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128
+c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="retweet" unicode="&#xf079;" horiz-adv-x="1920"
+d="M1280 32c0 -17 -15 -32 -32 -32h-960c-37 0 -32 39 -32 64v576h-192c-35 0 -64 29 -64 64c0 15 5 30 15 41l320 384c12 14 30 22 49 22s37 -8 49 -22l320 -384c10 -11 15 -26 15 -41c0 -35 -29 -64 -64 -64h-192v-384h576c9 0 19 -4 25 -11l160 -192c4 -6 7 -14 7 -21z
+M1920 448c0 -15 -5 -30 -15 -41l-320 -384c-12 -14 -30 -23 -49 -23s-37 9 -49 23l-320 384c-10 11 -15 26 -15 41c0 35 29 64 64 64h192v384h-576c-9 0 -19 4 -25 12l-160 192c-4 5 -7 13 -7 20c0 17 15 32 32 32h960c37 0 32 -39 32 -64v-576h192c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="hourglass" unicode="&#xf254;"
+d="M1504 -64c18 0 32 -14 32 -32v-128c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v128c0 18 14 32 32 32h1472zM130 0c19 337 294 518 478 640c-184 122 -459 303 -478 640h1276c-19 -337 -294 -518 -478 -640c184 -122 459 -303 478 -640h-1276zM1504 1536
+c18 0 32 -14 32 -32v-128c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v128c0 18 14 32 32 32h1472z" />
+ <glyph glyph-name="paint-brush" unicode="&#xf1fc;" horiz-adv-x="1790"
+d="M1615 1536c91 0 175 -68 175 -163c0 -53 -21 -104 -45 -151c-78 -148 -340 -637 -465 -752c-61 -57 -133 -91 -218 -91c-169 0 -307 144 -307 312c0 80 33 158 92 212l638 579c35 32 81 54 130 54zM706 502c52 -101 147 -177 257 -206l1 -71c6 -285 -192 -481 -478 -481
+c-339 0 -486 270 -486 577c37 -25 166 -128 208 -128c25 0 46 14 55 37c85 222 218 262 443 272z" />
+ <glyph glyph-name="viadeo-square" unicode="&#xf2aa;"
+d="M1050 495c0 50 -9 100 -28 147c-26 -16 -55 -28 -85 -34c16 -36 22 -75 22 -114c0 -154 -114 -280 -270 -280c-157 0 -271 126 -271 280c0 151 115 284 271 284c34 0 67 -6 98 -19c3 30 13 60 27 87c-40 14 -82 21 -125 21c-207 0 -361 -167 -361 -372s155 -367 361 -367
+s361 163 361 367zM872 850c25 -72 38 -148 38 -225c0 -173 -71 -317 -219 -411h-10c-14 0 -28 1 -42 3c199 76 235 377 235 562c0 23 0 47 -2 71zM872 850c-5 97 -60 247 -142 302c56 -95 106 -197 142 -302zM1207 955c0 61 -15 123 -51 174c-24 -51 -69 -94 -124 -109
+c-79 -22 -149 -59 -149 -153c0 -27 9 -54 24 -77c95 22 196 92 236 182c-6 -80 -155 -177 -213 -209c29 -29 67 -52 110 -52c73 0 125 65 150 127c12 30 17 86 17 117zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288
+h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="tags" unicode="&#xf02c;" horiz-adv-x="1899"
+d="M448 1088c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1515 512c0 -34 -14 -67 -37 -90l-491 -492c-24 -23 -57 -37 -91 -37s-67 14 -90 37l-715 716c-51 50 -91 147 -91 218v416c0 70 58 128 128 128h416c71 0 168 -40 219 -91
+l715 -714c23 -24 37 -57 37 -91zM1899 512c0 -34 -14 -67 -37 -90l-491 -492c-24 -23 -57 -37 -91 -37c-52 0 -78 24 -112 59l470 470c23 23 37 56 37 90s-14 67 -37 91l-715 714c-51 51 -148 91 -219 91h224c71 0 168 -40 219 -91l715 -714c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="minus-square-o" unicode="&#xf147;" horiz-adv-x="1408"
+d="M1152 736v-64c0 -18 -14 -32 -32 -32h-832c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h832c18 0 32 -14 32 -32zM1280 288v832c0 88 -72 160 -160 160h-832c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160zM1408 1120v-832
+c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="user-circle" unicode="&#xf2bd;" horiz-adv-x="1792"
+d="M1523 197c-26 187 -102 353 -272 376c-88 -96 -215 -157 -355 -157s-267 61 -355 157c-170 -23 -246 -189 -272 -376c139 -196 368 -325 627 -325s488 129 627 325zM1280 896c0 212 -172 384 -384 384s-384 -172 -384 -384s172 -384 384 -384s384 172 384 384zM1792 640
+c0 -493 -400 -896 -896 -896c-495 0 -896 402 -896 896c0 495 401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="thumbs-o-down" unicode="&#xf088;"
+d="M256 1088c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1408 512c0 37 -28 127 -75 128c21 24 35 71 35 103c0 47 -19 87 -53 119c12 21 18 45 18 69c0 46 -23 103 -65 126c3 18 5 37 5 56c0 117 -74 167 -185 167h-128c-118 0 -232 -35 -342 -73
+c-54 -19 -146 -55 -202 -55h-32v-640h32c79 0 198 -171 243 -229c25 -31 49 -62 77 -91c97 -102 64 -255 128 -320c137 0 160 75 160 192c0 118 -96 203 -96 320h352c67 0 128 60 128 128zM1536 511c0 -138 -118 -255 -256 -255h-176c30 -62 48 -122 48 -192
+c0 -66 -4 -126 -35 -186c-49 -97 -149 -134 -253 -134c-34 0 -66 14 -90 37c-100 98 -69 256 -128 321c-38 40 -73 83 -107 127c-30 39 -98 129 -137 155h-274c-71 0 -128 57 -128 128v640c0 71 57 128 128 128h288c28 0 109 30 138 40c144 50 269 88 423 88h112
+c182 0 313 -108 312 -295v-5c39 -50 60 -114 60 -178c0 -14 -1 -29 -3 -43c25 -44 38 -94 38 -144c0 -23 -3 -47 -9 -69c32 -48 49 -105 49 -163z" />
+ <glyph glyph-name="subscript" unicode="&#xf12c;" horiz-adv-x="1531"
+d="M892 167v-167h-248l-159 252l-24 42c-6 7 -9 14 -11 21h-3c-2 -7 -6 -14 -9 -21c-6 -12 -15 -28 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228c9 -14 16 -29 23 -42c6 -7 9 -14 11 -21h3c2 7 6 14 11 21l25 42l140 228h257v-168h-125
+l-184 -267l204 -296h109zM1531 -50v-206h-514l-4 27c-1 15 -3 33 -3 46c0 273 350 296 350 441c0 52 -47 87 -100 87c-39 0 -72 -18 -97 -39c-13 -11 -25 -25 -36 -38l-105 92c18 25 38 46 63 66c42 34 103 65 188 65c145 0 246 -85 246 -218c0 -239 -332 -259 -346 -403
+h232v80h126z" />
+ <glyph glyph-name="flickr" unicode="&#xf16e;"
+d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960zM698 640c0 117 -95 212 -212 212s-212 -95 -212 -212s95 -212 212 -212s212 95 212 212zM1262 640c0 117 -95 212 -212 212
+s-212 -95 -212 -212s95 -212 212 -212s212 95 212 212z" />
+ <glyph glyph-name="cc-amex" unicode="&#xf1f3;" horiz-adv-x="2304"
+d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453c0 24 -18 33 -40 33h-84v-69h83c23 0 41 11 41 36zM1475 457c0 25 -22 29 -42 29h-82v-61h81c22 0 43 5 43 32zM1197 923c0 25 -22 29 -42 29h-82v-60h81
+c22 0 43 5 43 31zM1656 854h89l-44 108zM699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453c0 -109 -119 -91 -193 -91v-91h-126l-80 90l-83 -90h-256v271h260l80 -89l82 89h207
+c61 0 109 -21 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229c0 -73 -59 -134 -132 -134h-2040c-73 0 -132 61 -132 134v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1c9 0 10 -7 10 -14v-86h279v23
+c65 -34 154 -23 222 -23l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249c-37 0 -76 -4 -109 -22v22h-172v-22c-20 18 -47 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391c0 73 59 134 132 134h2040c73 0 132 -61 132 -134
+v-678h-120c-28 0 -58 -5 -81 -22v22h-177c-25 0 -59 -4 -78 -22v22h-316v-22c-24 17 -59 22 -87 22h-209v-22c-21 20 -64 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21c30 0 61 1 90 13v-102h174v99h8c10 0 12 -1 12 -12v-87h529c29 0 65 6 88 24
+v-24h168c32 0 66 3 95 17zM1546 469c0 -30 -16 -60 -46 -72c36 -13 43 -37 43 -72v-54h-65v45c0 46 -15 54 -58 54h-69v-99h-65v271h154c51 0 106 -9 106 -73zM1269 936c0 -31 -17 -61 -46 -73c37 -13 43 -36 43 -72v-53h-65c-1 58 14 98 -58 98h-70v-98h-64v271l153 -1
+c52 0 107 -8 107 -72zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357c0 -64 -44 -86 -102 -86h-126v58h126c16 0 34 4 34 25c0 58 -167 -22 -167 107c0 55 42 81 92 81h130v-57h-119c-17 0 -36 -3 -36 -25
+c0 -59 168 27 168 -103zM2304 407v-101c-19 -28 -56 -35 -88 -35h-125v58h125c16 0 33 5 33 25c0 57 -167 -22 -167 107c0 55 43 81 93 81h129v-57h-118c-18 0 -36 -3 -36 -25c0 -48 113 1 154 -53zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75
+c-89 0 -129 46 -129 133c0 91 41 138 133 138h63v-59c-68 1 -130 16 -130 -77c0 -46 11 -78 63 -78h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
+ <glyph glyph-name="reddit" unicode="&#xf1a1;" horiz-adv-x="1792"
+d="M1095 369c9 -9 9 -23 0 -31c-57 -57 -167 -62 -199 -62s-142 5 -199 62c-9 8 -9 22 0 31c8 8 22 8 30 0c36 -37 114 -49 169 -49s132 12 169 49c8 8 22 8 30 0zM788 550c0 -49 -40 -89 -89 -89c-50 0 -90 40 -90 89c0 50 40 90 90 90c49 0 89 -40 89 -90zM1183 550
+c0 -49 -40 -89 -90 -89c-49 0 -89 40 -89 89c0 50 40 90 89 90c50 0 90 -40 90 -90zM1434 670c0 66 -54 119 -120 119c-34 0 -64 -14 -86 -36c-81 56 -190 92 -311 96l63 283l200 -45c0 -49 40 -89 89 -89c50 0 90 41 90 90s-40 90 -90 90c-35 0 -65 -21 -80 -50l-221 49
+c-11 3 -22 -5 -25 -16l-69 -312c-120 -5 -228 -41 -309 -97c-22 23 -53 37 -87 37c-66 0 -120 -53 -120 -119c0 -48 28 -88 68 -108c-4 -18 -6 -37 -6 -56c0 -190 214 -344 477 -344c264 0 478 154 478 344c0 19 -2 39 -7 57c39 20 66 60 66 107zM1792 640
+c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="times-circle" unicode="&#xf057;"
+d="M1149 414c0 17 -7 33 -19 45l-181 181l181 181c12 12 19 28 19 45s-7 34 -19 46l-90 90c-12 12 -29 19 -46 19s-33 -7 -45 -19l-181 -181l-181 181c-12 12 -28 19 -45 19s-34 -7 -46 -19l-90 -90c-12 -12 -19 -29 -19 -46s7 -33 19 -45l181 -181l-181 -181
+c-12 -12 -19 -28 -19 -45s7 -34 19 -46l90 -90c12 -12 29 -19 46 -19s33 7 45 19l181 181l181 -181c12 -12 28 -19 45 -19s34 7 46 19l90 90c12 12 19 29 19 46zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="tripadvisor" unicode="&#xf262;" horiz-adv-x="2304"
+d="M651 539c0 -52 -42 -94 -93 -94c-52 0 -94 42 -94 94c0 51 42 93 94 93c51 0 93 -42 93 -93zM1805 540c0 -52 -42 -94 -94 -94s-94 42 -94 94s42 93 94 93s94 -41 94 -93zM765 539c0 106 -87 193 -193 193c-107 0 -193 -87 -193 -193c0 -107 86 -193 193 -193
+c106 0 193 86 193 193zM1918 540c0 106 -86 193 -193 193c-106 0 -193 -87 -193 -193c0 -107 87 -193 193 -193c107 0 193 86 193 193zM850 539c0 -154 -124 -279 -278 -279s-279 125 -279 279c0 153 125 278 279 278s278 -125 278 -278zM2004 540
+c0 -154 -125 -278 -279 -278c-153 0 -278 124 -278 278s125 278 278 278c154 0 279 -124 279 -278zM1040 537c0 255 -207 462 -462 462c-254 0 -461 -207 -461 -462s207 -462 461 -462c255 0 462 207 462 462zM1708 1110c-165 72 -351 111 -556 111s-409 -39 -573 -110
+c317 -1 573 -257 573 -574c0 311 247 564 556 573zM2187 537c0 255 -206 462 -461 462s-462 -207 -462 -462s207 -462 462 -462s461 207 461 462zM1921 1103h383c-60 -70 -104 -164 -115 -229c69 -95 110 -211 110 -337c0 -317 -257 -573 -573 -573c-180 0 -340 82 -445 211
+c0 0 -47 -56 -129 -179c-14 29 -85 130 -128 180c-105 -130 -266 -212 -446 -212c-316 0 -573 256 -573 573c0 126 41 242 110 337c-11 65 -55 159 -115 229h365c196 131 481 213 787 213s573 -82 769 -213z" />
+ <glyph glyph-name="sort-amount-asc" unicode="&#xf160;" horiz-adv-x="1760"
+d="M704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-1376h192c18 0 32 -14 32 -32zM1760 -32v-192c0 -18 -14 -32 -32 -32h-832c-18 0 -32 14 -32 32
+v192c0 18 14 32 32 32h832c18 0 32 -14 32 -32zM1568 480v-192c0 -18 -14 -32 -32 -32h-640c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h640c18 0 32 -14 32 -32zM1376 992v-192c0 -18 -14 -32 -32 -32h-448c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h448
+c18 0 32 -14 32 -32zM1184 1504v-192c0 -18 -14 -32 -32 -32h-256c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h256c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="renren" unicode="&#xf18b;"
+d="M1133 -34c-109 -60 -234 -94 -368 -94c-133 0 -258 34 -367 94c177 112 320 281 367 479c48 -198 191 -367 368 -479zM638 1394v-485c0 -342 -189 -636 -457 -766c-113 134 -181 306 -181 495c0 380 276 695 638 756zM1536 638c0 -189 -68 -361 -181 -495
+c-268 130 -457 424 -457 766v485c362 -61 638 -376 638 -756z" />
+ <glyph glyph-name="key-modern" unicode="&#xf2f7;" horiz-adv-x="1792"
+d="M546 1536v0c139 1 278 -52 383 -158c142 -141 187 -343 137 -525l726 -726v-319c0 -35 -29 -64 -64 -64h-300l-45 45l135 226l-46 45l-225 -135l-45 46l134 225l-45 45l-225 -134l-46 45l135 225l-45 46l-243 -139l-186 186c-182 -50 -382 -5 -524 136
+c-211 212 -209 556 4 770c107 106 246 159 385 160zM405 1290v0c-41 0 -82 -16 -113 -47c-63 -63 -63 -163 0 -226s164 -63 227 0s63 163 0 226c-31 31 -73 47 -114 47z" />
+ <glyph glyph-name="arrow-circle-o-right" unicode="&#xf18e;"
+d="M1152 640c0 -8 -3 -17 -9 -23l-320 -320c-6 -6 -15 -9 -23 -9c-17 0 -32 15 -32 32v192h-352c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h352v192c0 18 14 32 32 32c9 0 17 -4 24 -10l319 -319c6 -6 9 -15 9 -23zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544
+s244 -544 544 -544s544 244 544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="pinterest-p" unicode="&#xf231;" horiz-adv-x="1280"
+d="M0 939c0 369 338 597 680 597c314 0 600 -216 600 -547c0 -311 -159 -656 -513 -656c-84 0 -190 42 -231 120c-76 -301 -70 -346 -238 -576l-14 -5l-9 10c-6 63 -15 125 -15 188c0 204 94 499 140 697c-25 51 -32 113 -32 169c0 101 70 229 184 229
+c84 0 129 -64 129 -143c0 -130 -88 -252 -88 -378c0 -86 71 -146 154 -146c230 0 301 332 301 509c0 237 -168 366 -395 366c-264 0 -468 -190 -468 -458c0 -129 79 -195 79 -226c0 -26 -19 -118 -52 -118c-5 0 -12 2 -17 3c-143 43 -195 234 -195 365z" />
+ <glyph glyph-name="html5" unicode="&#xf13b;" horiz-adv-x="1408"
+d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+ <glyph glyph-name="key" unicode="&#xf084;" horiz-adv-x="1683"
+d="M832 1024c0 106 -86 192 -192 192s-192 -86 -192 -192c0 -29 7 -57 19 -83c-26 12 -54 19 -83 19c-106 0 -192 -86 -192 -192s86 -192 192 -192s192 86 192 192c0 29 -7 57 -19 83c26 -12 54 -19 83 -19c106 0 192 86 192 192zM1683 320c0 -23 -92 -115 -115 -115
+c-26 0 -107 94 -128 115l-96 -96l220 -220c18 -18 28 -43 28 -68c0 -56 -64 -120 -120 -120c-25 0 -50 10 -68 28l-671 671c-105 -78 -233 -131 -365 -131c-218 0 -368 151 -368 368c0 328 328 656 656 656c217 0 368 -150 368 -368c0 -132 -53 -260 -131 -365l355 -355
+l96 96c-21 21 -115 102 -115 128c0 23 92 115 115 115c8 0 17 -4 23 -10c37 -37 316 -300 316 -329z" />
+ <glyph glyph-name="syncthing" unicode="&#xf311;"
+d="M768 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM774 1254c-337 0 -611 -274 -611 -611c0 -10 0 -28 1 -38c-17 -10 -32 -23 -42 -41c-33 -56 -14 -128 41 -161c18 -10 37 -15 56 -16c97 -210 309 -355 555 -355
+c108 0 210 28 298 78c16 -11 35 -19 56 -21c65 -5 122 42 129 107v10c0 14 -5 36 -11 49c87 105 139 241 139 388c0 57 -8 112 -23 164c14 13 25 30 32 49c21 61 -12 128 -73 149c-12 4 -26 6 -38 6v0c-6 0 -15 0 -21 -1c-112 148 -289 244 -488 244zM774 1175v0
+c171 0 323 -79 420 -204c-10 -11 -17 -24 -22 -39c-9 -27 -8 -55 1 -80l-224 -186c-18 11 -39 16 -60 16c-22 0 -44 -5 -63 -18c-26 -16 -43 -42 -50 -70l-447 -41c-10 21 -25 39 -46 52c-13 8 -27 12 -41 14c0 8 -1 16 -1 24c0 295 238 532 533 532zM1224 792
+c6 -3 15 -7 21 -9c15 -5 29 -8 44 -7c11 -43 17 -87 17 -133c0 -125 -42 -240 -114 -331c-13 7 -28 11 -43 13c-15 1 -28 0 -42 -4l-122 175c23 32 29 73 15 110zM783 516c2 -4 5 -11 8 -15c29 -44 81 -63 129 -50l122 -175c-12 -16 -19 -37 -21 -59v-9c0 -10 2 -26 5 -35
+c-75 -40 -161 -63 -252 -63c-211 0 -394 123 -480 301c10 8 24 22 30 33c5 8 11 22 13 31z" />
+ <glyph glyph-name="picture-o" unicode="&#xf03e;" horiz-adv-x="1920"
+d="M640 960c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600c-17 0 -32 -15 -32 -32v-1216c0 -17 15 -32 32 -32h1600c17 0 32 15 32 32v1216c0 17 -15 32 -32 32z
+M1920 1248v-1216c0 -88 -72 -160 -160 -160h-1600c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1600c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="list-alt" unicode="&#xf022;" horiz-adv-x="1792"
+d="M384 352v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 608v-64c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM384 864v-64c0 -17 -15 -32 -32 -32h-64
+c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h64c17 0 32 -15 32 -32zM1536 352v-64c0 -17 -15 -32 -32 -32h-960c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h960c17 0 32 -15 32 -32zM1536 608v-64c0 -17 -15 -32 -32 -32h-960c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h960
+c17 0 32 -15 32 -32zM1536 864v-64c0 -17 -15 -32 -32 -32h-960c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h960c17 0 32 -15 32 -32zM1664 160v832c0 17 -15 32 -32 32h-1472c-17 0 -32 -15 -32 -32v-832c0 -17 15 -32 32 -32h1472c17 0 32 15 32 32zM1792 1248v-1088
+c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="fort-awesome" unicode="&#xf286;" horiz-adv-x="1664"
+d="M640 528v224c0 9 -7 16 -16 16h-96c-9 0 -16 -7 -16 -16v-224c0 -9 7 -16 16 -16h96c9 0 16 7 16 16zM1152 528v224c0 9 -7 16 -16 16h-96c-9 0 -16 -7 -16 -16v-224c0 -9 7 -16 16 -16h96c9 0 16 7 16 16zM1664 496v-752h-640v320c0 106 -86 192 -192 192
+s-192 -86 -192 -192v-320h-640v752c0 9 7 16 16 16h96c9 0 16 -7 16 -16v-112h128v624c0 9 7 16 16 16h96c9 0 16 -7 16 -16v-112h128v112c0 9 7 16 16 16h96c9 0 16 -7 16 -16v-112h128v112c0 21 28 16 41 16v391c-19 9 -32 29 -32 50c0 30 25 55 55 55s55 -25 55 -55
+c0 -21 -13 -41 -32 -50v-17c27 6 55 10 83 10c41 0 80 -15 114 -15c31 0 66 15 84 15c9 0 16 -7 16 -16v-210c0 -24 -81 -28 -97 -28c-37 0 -72 15 -110 15c-30 0 -61 -5 -90 -12v-133c13 0 41 5 41 -16v-112h128v112c0 9 7 16 16 16h96c9 0 16 -7 16 -16v-112h128v112
+c0 9 7 16 16 16h96c9 0 16 -7 16 -16v-624h128v112c0 9 7 16 16 16h96c9 0 16 -7 16 -16z" />
+ <glyph glyph-name="c" unicode="&#xf31c;" horiz-adv-x="1404"
+d="M996 819c0 0 -23 211 -232 217s-317 -157 -317 -392s119 -423 323 -423s226 235 226 235l391 -24s22 -211 -141 -373s-364 -188 -504 -187s-334 -2 -522 190s-220 379 -220 563s36 427 259 611c152 125 306 172 460 172c643 0 685 -593 685 -593l-408 4v0z" />
+ <glyph glyph-name="commenting" unicode="&#xf27a;" horiz-adv-x="1792"
+d="M640 640c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1024 640c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1408 640c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128z
+M1792 640c0 -354 -401 -640 -896 -640c-73 0 -144 6 -211 18c-114 -114 -263 -192 -435 -229c-27 -5 -56 -10 -86 -13c-16 -2 -31 9 -35 24c-4 16 8 26 20 37c63 59 138 106 164 317c-191 117 -313 291 -313 486c0 354 401 640 896 640s896 -286 896 -640z" />
+ <glyph glyph-name="tablet" unicode="&#xf10a;" horiz-adv-x="1152"
+d="M640 128c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1024 288v960c0 17 -15 32 -32 32h-832c-17 0 -32 -15 -32 -32v-960c0 -17 15 -32 32 -32h832c17 0 32 15 32 32zM1152 1248v-1088c0 -88 -72 -160 -160 -160h-832c-88 0 -160 72 -160 160v1088
+c0 88 72 160 160 160h832c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="credit-card" unicode="&#xf09d;" horiz-adv-x="1920"
+d="M1760 1408c88 0 160 -72 160 -160v-1216c0 -88 -72 -160 -160 -160h-1600c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1600zM160 1280c-17 0 -32 -15 -32 -32v-224h1664v224c0 17 -15 32 -32 32h-1600zM1760 0c17 0 32 15 32 32v608h-1664v-608
+c0 -17 15 -32 32 -32h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+ <glyph glyph-name="minus" unicode="&#xf068;" horiz-adv-x="1408"
+d="M1408 800v-192c0 -53 -43 -96 -96 -96h-1216c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h1216c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="unlock-alt" unicode="&#xf13e;" horiz-adv-x="1152"
+d="M1056 768c53 0 96 -43 96 -96v-576c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v576c0 53 43 96 96 96h32v320c0 247 201 448 448 448s448 -201 448 -448c0 -35 -29 -64 -64 -64h-64c-35 0 -64 29 -64 64c0 141 -115 256 -256 256s-256 -115 -256 -256v-320h736z
+" />
+ <glyph glyph-name="ils" unicode="&#xf20b;" horiz-adv-x="1376"
+d="M992 912v-496c0 -18 -14 -32 -32 -32h-160c-18 0 -32 14 -32 32v496c0 150 -122 272 -272 272h-272v-1152c0 -18 -14 -32 -32 -32h-160c-18 0 -32 14 -32 32v1344c0 18 14 32 32 32h464c274 0 496 -222 496 -496zM1376 1376v-880c0 -274 -222 -496 -496 -496h-464
+c-18 0 -32 14 -32 32v960c0 18 14 32 32 32h160c18 0 32 -14 32 -32v-768h272c150 0 272 122 272 272v880c0 18 14 32 32 32h160c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="cog" unicode="&#xf013;"
+d="M1024 640c0 141 -115 256 -256 256s-256 -115 -256 -256s115 -256 256 -256s256 115 256 256zM1536 749v-222c0 -15 -12 -33 -28 -36l-185 -28c-11 -32 -23 -62 -39 -91c34 -49 70 -93 107 -138c6 -7 10 -16 10 -25s-3 -16 -9 -23c-24 -32 -159 -179 -193 -179
+c-9 0 -18 4 -26 9l-138 108c-29 -15 -60 -28 -91 -38c-7 -61 -13 -126 -29 -186c-4 -16 -18 -28 -36 -28h-222c-18 0 -34 13 -36 30l-28 184c-31 10 -61 22 -90 37l-141 -107c-7 -6 -16 -9 -25 -9s-18 4 -25 11c-53 48 -123 110 -165 168c-5 7 -7 15 -7 23c0 9 3 16 8 23
+c34 46 71 90 105 137c-17 32 -31 65 -41 99l-183 27c-17 3 -29 19 -29 36v222c0 15 12 33 27 36l186 28c10 32 23 62 39 92c-34 48 -70 93 -107 138c-6 7 -10 15 -10 24s4 16 9 23c24 33 159 179 193 179c9 0 18 -4 26 -10l138 -107c29 15 60 28 91 38c7 61 13 126 29 186
+c4 16 18 28 36 28h222c18 0 34 -13 36 -30l28 -184c31 -10 61 -22 90 -37l142 107c6 6 15 9 24 9s18 -4 25 -10c53 -49 123 -111 165 -170c5 -6 7 -14 7 -22c0 -9 -3 -16 -8 -23c-34 -46 -71 -90 -105 -137c17 -32 31 -65 41 -98l183 -28c17 -3 29 -19 29 -36z" />
+ <glyph glyph-name="arrow-right" unicode="&#xf061;" horiz-adv-x="1472"
+d="M1472 576c0 -34 -13 -67 -37 -91l-651 -651c-24 -23 -57 -37 -91 -37s-66 14 -90 37l-75 75c-24 24 -38 57 -38 91s14 67 38 91l293 293h-704c-72 0 -117 60 -117 128v128c0 68 45 128 117 128h704l-293 294c-24 23 -38 56 -38 90s14 67 38 90l75 75c24 24 56 38 90 38
+s67 -14 91 -38l651 -651c24 -23 37 -56 37 -90z" />
+ <glyph glyph-name="cc-paypal" unicode="&#xf1f4;" horiz-adv-x="2304"
+d="M745 630c0 -49 -39 -86 -88 -86c-37 0 -64 21 -64 60c0 49 38 88 87 88c37 0 65 -23 65 -62zM1530 779c0 -60 -36 -72 -88 -72l-32 -1l17 107c1 7 6 11 13 11h18c34 0 72 -2 72 -45zM1881 630c0 -49 -39 -86 -87 -86c-37 0 -65 21 -65 60c0 49 38 88 87 88
+c37 0 65 -23 65 -62zM513 801c0 84 -65 112 -139 112h-160c-10 0 -20 -8 -21 -19l-65 -408c-1 -8 5 -16 13 -16h76c11 0 21 8 22 19l18 110c4 29 53 19 72 19c114 0 184 68 184 183zM822 489l41 261c1 8 -5 16 -13 16h-76c-15 0 -16 -22 -17 -33c-23 34 -57 40 -95 40
+c-98 0 -173 -86 -173 -181c0 -78 49 -129 127 -129c36 0 81 16 106 44c-2 -6 -4 -15 -4 -21c0 -9 4 -16 13 -16h69c11 0 20 8 22 19zM1269 752c0 7 -6 14 -13 14h-77c-7 0 -14 -4 -18 -10l-106 -156l-44 150c-3 9 -12 16 -22 16h-75c-7 0 -13 -7 -13 -14
+c0 -5 78 -231 85 -252c-11 -15 -82 -108 -82 -120c0 -7 6 -13 13 -13h77c7 0 14 4 18 10l255 368c2 2 2 4 2 7zM1649 801c0 84 -65 112 -139 112h-159c-11 0 -21 -8 -22 -19l-65 -408c-1 -8 5 -16 13 -16h82c8 0 14 6 16 13l18 116c4 29 53 19 72 19c114 0 184 68 184 183z
+M1958 489l41 261c1 8 -5 16 -13 16h-76c-15 0 -16 -22 -17 -33c-22 34 -56 40 -95 40c-98 0 -173 -86 -173 -181c0 -78 49 -129 127 -129c37 0 82 16 106 44c-1 -6 -4 -15 -4 -21c0 -9 4 -16 13 -16h69c11 0 20 8 22 19zM2176 898v1c0 8 -6 14 -13 14h-74
+c-6 0 -12 -5 -13 -11l-65 -416l-1 -2c0 -7 6 -14 14 -14h66c10 0 20 8 21 19zM392 764c-8 -51 -42 -57 -86 -57l-33 -1l17 107c1 7 7 11 13 11h19c45 0 79 -6 70 -60zM2304 1280v-1280c0 -70 -58 -128 -128 -128h-2048c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128
+h2048c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="birthday-cake" unicode="&#xf1fd;" horiz-adv-x="1792"
+d="M1792 128v-384h-1792v384c98 0 150 44 191 79c34 30 57 49 108 49s73 -19 108 -49c41 -35 92 -79 191 -79c98 0 149 44 191 79c34 30 56 49 107 49s74 -19 108 -49c41 -35 93 -79 191 -79s150 44 191 79c34 30 57 49 108 49c50 0 73 -19 107 -49c41 -35 93 -79 191 -79z
+M1792 448v-192c-51 0 -73 19 -108 49c-41 35 -92 79 -190 79c-99 0 -150 -44 -191 -79c-35 -30 -57 -49 -108 -49s-74 19 -108 49c-41 35 -92 79 -191 79c-98 0 -149 -44 -191 -79c-34 -30 -56 -49 -107 -49s-74 19 -108 49c-41 35 -93 79 -191 79c-99 0 -150 -44 -191 -79
+c-34 -30 -57 -49 -108 -49v192c0 106 86 192 192 192h64v448h256v-448h256v448h256v-448h256v448h256v-448h64c106 0 192 -86 192 -192zM512 1312c0 -106 -57 -160 -128 -160s-128 57 -128 128c0 124 128 92 128 256c48 0 128 -118 128 -224zM1024 1312
+c0 -106 -57 -160 -128 -160s-128 57 -128 128c0 124 128 92 128 256c48 0 128 -118 128 -224zM1536 1312c0 -106 -57 -160 -128 -160s-128 57 -128 128c0 124 128 92 128 256c48 0 128 -118 128 -224z" />
+ <glyph glyph-name="comment" unicode="&#xf075;" horiz-adv-x="1792"
+d="M1792 640c0 -354 -401 -640 -896 -640c-49 0 -98 3 -145 8c-131 -116 -287 -198 -460 -242c-36 -10 -75 -17 -114 -22c-22 -2 -43 14 -48 38v1c-5 25 12 40 27 58c63 71 135 131 182 298c-206 117 -338 298 -338 501c0 353 401 640 896 640s896 -286 896 -640z" />
+ <glyph glyph-name="bell" unicode="&#xf0f3;" horiz-adv-x="1664"
+d="M848 -160c0 9 -7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176c9 0 16 7 16 16zM182 128h1300c-179 202 -266 476 -266 832c0 129 -122 320 -384 320s-384 -191 -384 -320c0 -356 -87 -630 -266 -832zM1664 128
+c0 -70 -58 -128 -128 -128h-448c0 -141 -115 -256 -256 -256s-256 115 -256 256h-448c-70 0 -128 58 -128 128c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c265 -39 424 -249 424 -441
+c0 -483 172 -707 320 -832z" />
+ <glyph glyph-name="cc" unicode="&#xf20a;" horiz-adv-x="2048"
+d="M785 528h207c-19 -211 -140 -339 -313 -339c-216 0 -347 166 -347 432c0 264 144 429 326 429c200 0 312 -124 329 -334h-203c-7 85 -49 134 -117 134c-75 0 -120 -80 -120 -238c0 -115 20 -223 129 -223c69 0 101 60 109 139zM1497 528h206
+c-19 -211 -139 -339 -312 -339c-216 0 -347 166 -347 432c0 264 144 429 326 429c200 0 312 -124 329 -334h-204c-6 85 -49 134 -116 134c-75 0 -120 -80 -120 -238c0 -115 19 -223 128 -223c69 0 102 60 110 139zM1856 647c0 268 -14 384 -76 468c-13 17 -34 28 -51 40
+c-63 46 -356 63 -697 63s-648 -17 -710 -63c-18 -13 -40 -23 -53 -40c-62 -83 -75 -200 -75 -468c0 -269 14 -385 75 -468c14 -19 35 -27 53 -41c62 -46 369 -65 710 -65s634 18 697 65c17 13 39 21 51 41c63 82 76 199 76 468zM2048 1408v-1536h-2048v1536h2048z" />
+ <glyph glyph-name="get-pocket" unicode="&#xf265;" horiz-adv-x="1720"
+d="M1565 1408c87 0 155 -70 155 -156v-519c0 -479 -383 -861 -859 -861c-478 0 -861 382 -861 861v519c0 85 71 156 156 156h1409zM861 344c30 0 60 12 82 33l404 388c23 22 37 53 37 85c0 65 -53 118 -118 118c-31 0 -60 -12 -82 -33l-323 -310l-323 310
+c-22 21 -51 33 -81 33c-65 0 -118 -53 -118 -118c0 -32 13 -63 36 -85l405 -388c21 -21 51 -33 81 -33z" />
+ <glyph glyph-name="bell-slash-o" unicode="&#xf1f7;" horiz-adv-x="2019"
+d="M1026 -160c0 9 -7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176c9 0 16 7 16 16zM489 315l877 760c-50 105 -166 205 -356 205c-262 0 -384 -191 -384 -320c0 -256 -45 -470 -137 -645zM1842 128c0 -70 -58 -128 -128 -128
+h-448c0 -141 -115 -256 -256 -256s-255 114 -256 255l149 129h757c-111 125 -186 277 -227 459l111 97c51 -298 182 -458 298 -556zM1928 1520l84 -96c11 -14 10 -34 -3 -46l-1872 -1622c-13 -11 -34 -10 -45 4l-84 96c-11 14 -10 34 3 45l186 161c-12 20 -19 42 -19 66
+c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c172 -25 299 -122 367 -240l418 363c13 11 34 10 45 -4z" />
+ <glyph glyph-name="header" unicode="&#xf1dc;" horiz-adv-x="1668"
+d="M1620 -128c-88 0 -177 7 -266 7c-88 0 -176 -7 -264 -7c-34 0 -50 37 -50 66c0 89 100 51 152 85c33 21 33 105 33 140l-1 391c0 11 0 21 -1 31c-16 5 -34 4 -50 4h-675c-17 0 -35 1 -51 -4c-1 -10 -1 -20 -1 -31l-1 -371c0 -38 0 -142 37 -164c52 -32 170 13 170 -77
+c0 -30 -14 -70 -49 -70c-93 0 -186 7 -278 7c-85 0 -170 -7 -255 -7c-33 0 -48 38 -48 66c0 87 92 51 141 85c32 22 33 108 33 143l-1 57v813c0 48 7 202 -38 229c-50 31 -157 -17 -157 73c0 29 13 70 48 70c92 0 185 -7 277 -7c84 0 169 7 253 7c36 0 50 -40 50 -70
+c0 -86 -99 -44 -148 -75c-35 -21 -35 -124 -35 -160l1 -320c0 -11 0 -21 1 -32c13 -3 26 -3 39 -3h699c12 0 25 0 38 3c1 11 1 21 1 32l1 320c0 37 0 139 -35 160c-50 30 -150 -10 -150 75c0 30 14 70 50 70c88 0 176 -7 264 -7c86 0 172 7 258 7c36 0 50 -40 50 -70
+c0 -87 -103 -43 -153 -74c-34 -22 -35 -125 -35 -161l1 -943c0 -33 2 -120 34 -140c51 -32 159 9 159 -78c0 -29 -13 -70 -48 -70z" />
+ <glyph glyph-name="bluetooth-b" unicode="&#xf294;" horiz-adv-x="944"
+d="M556 113l173 172l-173 172v-344zM556 823l173 172l-173 172v-344zM588 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+ <glyph glyph-name="linux" unicode="&#xf17c;" horiz-adv-x="1523"
+d="M657 1125c-20 -2 -13 -20 -24 -20c-10 -1 -8 22 24 20zM744 1111c-10 -3 -11 16 -29 11c29 13 39 -7 29 -11zM393 684c-9 3 -7 -15 -16 -29c-7 -13 -25 -23 -11 -25c5 -1 19 11 25 25c5 17 10 26 2 29zM1248 325c0 18 -39 35 -55 42c27 90 15 126 -3 211
+c-14 64 -73 151 -119 178c12 -10 34 -39 57 -83c40 -75 80 -186 54 -278c-10 -36 -34 -41 -50 -42c-70 -8 -29 84 -58 209c-33 140 -67 150 -75 161c-41 182 -86 164 -99 232c-11 61 53 111 -34 128c-27 5 -65 32 -80 34s-23 101 33 104c55 4 65 -62 55 -88
+c-16 -26 1 -36 28 -27c22 7 8 65 13 73c-14 84 -49 96 -85 103c-138 -11 -76 -163 -90 -149c-20 21 -78 2 -78 15c1 78 -25 123 -61 124c-40 1 -56 -55 -58 -87c-3 -30 17 -93 32 -88c10 3 27 23 9 22c-9 0 -23 22 -25 48c-1 26 9 52 43 51c39 -1 39 -79 35 -82
+c-13 -9 -29 -26 -31 -29c-13 -21 -38 -27 -48 -36c-17 -18 -21 -38 -8 -45c46 -26 31 -56 95 -58c42 -2 73 6 102 15c22 7 93 22 108 48c7 11 15 11 20 8c10 -5 12 -24 -13 -30c-35 -10 -70 -29 -102 -41c-31 -13 -41 -18 -70 -23c-66 -12 -115 24 -71 -19
+c15 -14 29 -23 67 -22c84 3 177 104 186 59c2 -10 -26 -22 -48 -33c-78 -38 -133 -114 -183 -88c-45 24 -90 135 -89 85c1 -77 -101 -145 -54 -233c-31 -8 -100 -155 -110 -231c-6 -44 4 -98 -7 -128c-15 -44 -83 42 -61 147c4 18 0 22 -5 13c-27 -49 -12 -118 10 -166
+c9 -21 32 -30 49 -48c35 -40 173 -142 197 -167c31 -29 22 -97 -42 -104c33 -62 65 -68 64 -169c38 20 23 64 7 92c-11 20 -25 29 -22 34c2 3 22 20 33 7c34 -38 98 -45 166 -36c69 8 143 32 177 87c16 26 27 35 34 30c8 -4 11 -22 10 -52c-1 -32 -14 -65 -23 -92
+c-9 -31 -12 -52 18 -53c8 56 24 111 28 167c5 64 -41 182 9 241c13 16 29 18 51 18c3 80 126 74 167 41zM620 1152c4 25 -8 43 -14 45c-12 3 -10 -15 -4 -13c4 0 9 -6 7 -15c-2 -12 -1 -20 8 -20c1 0 3 0 3 3zM1039 955c-4 19 -18 12 -34 22c-19 12 -23 32 -30 25
+c-21 -23 26 -71 46 -75c12 -2 21 14 18 28zM861 1168c1 24 -20 36 -25 35c-13 -1 -9 -7 -3 -9c8 -2 16 -16 18 -31c0 -2 10 2 10 5zM915 1401c1 5 -12 11 -21 18c-8 8 -16 15 -24 15c-20 -2 -10 -23 -13 -33c-4 -11 -19 -20 -9 -28c9 -7 15 11 34 18c5 2 28 -1 33 10z
+M1480 60c123 -76 -46 -139 -119 -176c-57 -29 -133 -93 -161 -120c-21 -20 -108 -30 -157 -5c-57 29 -27 75 -115 78c-44 1 -87 1 -130 1c-38 -1 -76 -3 -115 -4c-132 -3 -145 -88 -230 -85c-58 2 -131 48 -257 74c-88 18 -173 23 -191 62s22 83 25 121c3 51 -38 120 -8 146
+c26 23 81 6 117 26c38 22 54 39 54 86c14 -48 -1 -87 -32 -106c-19 -12 -54 -18 -83 -15c-23 2 -37 -1 -43 -10c-9 -11 -6 -31 5 -57s24 -43 22 -75c-1 -32 -37 -70 -31 -97c2 -10 12 -19 37 -26c40 -11 113 -22 184 -39c79 -20 161 -56 212 -49c152 21 65 184 41 223
+c-129 202 -214 334 -282 282c-17 -14 -18 34 -17 53c3 66 36 90 56 141c38 97 67 208 125 265c43 56 111 147 124 195c-11 104 -14 214 -16 310c-2 103 14 193 130 256c28 15 65 21 104 21c69 1 146 -19 195 -55c78 -58 127 -181 121 -269c-4 -69 8 -140 30 -214
+c26 -87 67 -148 133 -218c79 -84 141 -249 159 -354c16 -98 -6 -159 -27 -162c-32 -5 -52 -106 -152 -102c-64 3 -70 41 -88 74c-29 51 -58 35 -69 -19c-6 -27 -2 -67 7 -97c18 -63 12 -122 1 -195c-21 -138 97 -164 176 -98c78 65 95 75 193 109c149 51 99 96 19 123
+c-72 24 -75 145 -49 168c6 -130 74 -149 102 -167z" />
+ <glyph glyph-name="table" unicode="&#xf0ce;" horiz-adv-x="1664"
+d="M512 160v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM512 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 160v192c0 18 -14 32 -32 32h-320
+c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM512 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192
+c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1536 160v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32z
+M1536 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1536 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1664 1248v-1088c0 -88 -72 -160 -160 -160
+h-1344c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1344c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="handshake-o" unicode="&#xf2b5;" horiz-adv-x="2304"
+d="M192 384c84 0 84 128 0 128s-84 -128 0 -128zM1665 442c-79 103 -156 208 -246 302l-125 -140c-110 -125 -307 -122 -414 6c-76 92 -76 224 2 315l177 206c-62 32 -137 21 -204 21c-59 0 -116 -24 -158 -66l-158 -158h-155v-544c44 0 84 6 119 -28l297 -292
+c61 -59 140 -111 227 -111c45 0 93 15 125 47c75 -26 162 16 185 93c48 -4 92 11 127 44c23 21 53 63 50 96c9 -9 31 -10 43 -10c119 0 181 125 108 219zM1824 384h96v512h-93l-157 180c-42 48 -105 76 -169 76h-167c-56 0 -110 -25 -146 -67l-209 -243
+c-37 -44 -37 -106 -1 -150c57 -68 162 -69 221 -3l193 218c46 51 130 3 109 -62c38 -44 79 -87 116 -131c50 -62 98 -127 147 -190c31 -40 54 -88 60 -140zM2112 384c84 0 84 128 0 128s-84 -128 0 -128zM2304 960v-640c0 -35 -29 -64 -64 -64h-434
+c-36 -87 -115 -145 -207 -158c-43 -63 -109 -111 -183 -127c-55 -70 -144 -112 -233 -106c-165 -93 -351 -12 -474 109l-287 282h-358c-35 0 -64 29 -64 64v672c0 35 29 64 64 64h421c116 116 196 224 370 224h117c65 0 128 -20 181 -56c53 36 116 56 181 56h167
+c190 0 269 -124 384 -256h355c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="spinner" unicode="&#xf110;" horiz-adv-x="1664"
+d="M462 142c0 -70 -57 -128 -128 -128c-70 0 -128 58 -128 128c0 71 58 128 128 128c71 0 128 -57 128 -128zM960 -64c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM256 640c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128
+s128 -57 128 -128zM1458 142c0 -70 -58 -128 -128 -128c-71 0 -128 58 -128 128c0 71 57 128 128 128c70 0 128 -57 128 -128zM494 1138c0 -88 -72 -160 -160 -160s-160 72 -160 160s72 160 160 160s160 -72 160 -160zM1664 640c0 -71 -57 -128 -128 -128s-128 57 -128 128
+s57 128 128 128s128 -57 128 -128zM1024 1344c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1554 1138c0 -124 -101 -224 -224 -224c-124 0 -224 100 -224 224c0 123 100 224 224 224c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="snapchat" unicode="&#xf2ab;"
+d="M1279 388c0 14 -8 24 -22 27c-91 20 -160 83 -198 167c-3 8 -7 16 -7 25c0 45 125 36 125 100c0 27 -33 44 -57 44c-23 0 -41 -16 -63 -16c-4 0 -8 1 -12 2c2 38 5 76 5 114c0 35 -2 83 -17 114c-48 104 -141 165 -255 165c-125 0 -220 -46 -275 -165
+c-15 -31 -17 -79 -17 -114c0 -38 3 -76 5 -114c-4 -2 -9 -2 -14 -2c-23 0 -41 15 -62 15c-25 0 -56 -16 -56 -44c0 -62 125 -54 125 -99c0 -9 -4 -17 -7 -25c-39 -84 -106 -147 -198 -167c-14 -3 -22 -13 -22 -27c0 -46 106 -63 137 -68c9 -24 5 -66 41 -66c25 0 50 9 77 9
+c105 0 133 -95 255 -95c127 0 151 95 257 95c27 0 52 -8 78 -8c35 0 31 42 40 65c31 5 137 22 137 68zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="tint" unicode="&#xf043;" horiz-adv-x="1024"
+d="M512 384c0 25 -8 49 -20 69c-13 20 -66 88 -87 155c-3 11 -13 16 -21 16s-18 -5 -21 -16c-21 -67 -74 -135 -87 -155c-12 -20 -20 -44 -20 -69c0 -71 57 -128 128 -128s128 57 128 128zM1024 512c0 -283 -229 -512 -512 -512s-512 229 -512 512c0 101 31 195 81 275
+c51 80 265 351 346 621c13 43 53 64 85 64s73 -21 85 -64c81 -270 295 -541 346 -621s81 -174 81 -275z" />
+ <glyph glyph-name="connectdevelop" unicode="&#xf20e;" horiz-adv-x="2048"
+d="M2048 641c0 -28 -20 -51 -46 -56l-205 -356c2 -6 3 -12 3 -18c0 -27 -19 -50 -45 -55l-193 -337c2 -5 3 -10 3 -16c0 -31 -25 -57 -57 -57c-16 0 -31 7 -41 18h-400c-10 -12 -26 -20 -43 -20s-33 8 -43 20h-399c-10 -12 -25 -20 -43 -20c-31 0 -57 25 -57 57
+c0 7 2 14 4 20l-193 335c-26 5 -45 28 -45 55c0 7 1 12 3 18l-206 356c-26 6 -45 29 -45 56c0 28 20 51 47 56l199 344c0 2 -1 4 -1 6c0 23 14 42 34 51l209 363c-2 5 -4 12 -4 18c0 32 26 57 57 57c18 0 33 -8 44 -21h396c10 13 25 21 43 21s33 -8 43 -21h398
+c11 13 26 21 44 21c31 0 57 -25 57 -57c0 -6 -2 -12 -4 -18l207 -358c30 -1 55 -26 55 -56c0 -10 -3 -19 -7 -27l187 -324c25 -5 44 -28 44 -55zM1063 -158h389l-342 354h-143l-342 -354h360c10 9 24 16 39 16s29 -7 39 -16zM112 654c1 -4 1 -8 1 -13s0 -10 -2 -15l208 -360
+c5 -1 10 -4 15 -6l188 199v347l-187 194c-9 -6 -19 -9 -29 -10zM986 1438h-388l190 -200l554 200h-280c-10 -10 -23 -16 -38 -16s-28 6 -38 16zM1689 226c1 4 3 8 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427
+l333 -343c4 2 8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6c9 -3 16 -7 22 -13zM552 226h402l64 66l-309 321l-157 -166v-221zM359 226h163v189l-168 -177c2 -4 4 -8 5 -12zM358 1051c0 -1 1 -3 1 -4c0 -11 -3 -21 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314
+l-223 236zM556 1425l-4 -8v-264l205 74l-191 201c-3 -1 -6 -2 -10 -3zM1447 1438h-16l-621 -224l213 -225zM1023 946l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018c-5 8 -8 18 -8 29v2
+l-216 376c-5 1 -9 3 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196l-48 -227l130 227h-82zM1729 266l207 361c-1 5 -2 9 -2 14c0 6 2 11 3 16l-171 296l-129 -612l77 -82c5 3 10 5 15 7z" />
+ <glyph glyph-name="chrome" unicode="&#xf268;" horiz-adv-x="1792"
+d="M893 1536c153 1 309 -38 451 -120c157 -91 276 -222 352 -372l-742 39c-210 12 -410 -106 -479 -304l-276 424c172 214 430 332 694 333zM146 1131l337 -663c95 -187 296 -301 504 -262l-230 -451c-429 66 -757 437 -757 885c0 181 54 350 146 491zM1732 962
+c157 -404 0 -874 -388 -1098c-157 -91 -330 -128 -498 -119l405 623c115 177 113 408 -24 568zM896 942c167 0 302 -135 302 -302s-135 -302 -302 -302s-302 135 -302 302s135 302 302 302z" />
+ <glyph glyph-name="trademark" unicode="&#xf25c;" horiz-adv-x="1972"
+d="M857 992v-117c0 -17 -15 -31 -32 -31h-298v-812c0 -18 -14 -32 -31 -32h-135c-18 0 -32 14 -32 32v812h-297c-18 0 -32 14 -32 31v117c0 18 14 32 32 32h793c17 0 32 -14 32 -32zM1895 995l77 -961c1 -9 -2 -17 -8 -24c-6 -6 -14 -10 -23 -10h-134c-16 0 -30 13 -31 29
+l-46 588l-189 -425c-5 -12 -16 -19 -29 -19h-120c-12 0 -23 7 -29 19l-188 427l-45 -590c-1 -16 -15 -29 -31 -29h-135c-9 0 -17 4 -23 10c-6 7 -9 15 -9 24l78 961c1 16 15 29 31 29h142c13 0 24 -8 29 -19l220 -520c7 -16 14 -34 20 -51c7 17 13 35 20 51l221 520
+c5 11 16 19 29 19h141c17 0 31 -13 32 -29z" />
+ <glyph glyph-name="align-right" unicode="&#xf038;" horiz-adv-x="1792"
+d="M1792 192v-128c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1664c35 0 64 -29 64 -64zM1792 576v-128c0 -35 -29 -64 -64 -64h-1280c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1280c35 0 64 -29 64 -64zM1792 960v-128
+c0 -35 -29 -64 -64 -64h-1536c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1536c35 0 64 -29 64 -64zM1792 1344v-128c0 -35 -29 -64 -64 -64h-1152c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h1152c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="bandcamp" unicode="&#xf2d5;" horiz-adv-x="1792"
+d="M1070 358l306 564h-654l-306 -564h654zM1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="long-arrow-down" unicode="&#xf175;" horiz-adv-x="767"
+d="M765 237c5 -12 3 -25 -5 -35l-350 -384c-6 -6 -14 -10 -23 -10s-18 4 -24 10l-355 384c-8 10 -10 23 -5 35c5 11 16 19 29 19h224v1248c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-1248h224c13 0 24 -7 29 -19z" />
+ <glyph glyph-name="beer" unicode="&#xf0fc;" horiz-adv-x="1600"
+d="M576 640v384h-256v-256c0 -71 57 -128 128 -128h128zM1600 192v-192h-1152v192l128 192h-128c-212 0 -384 172 -384 384v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+ <glyph glyph-name="th-list" unicode="&#xf00b;" horiz-adv-x="1792"
+d="M512 288v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM512 800v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1792 288v-192c0 -53 -43 -96 -96 -96h-960
+c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h960c53 0 96 -43 96 -96zM512 1312v-192c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h320c53 0 96 -43 96 -96zM1792 800v-192c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v192c0 53 43 96 96 96
+h960c53 0 96 -43 96 -96zM1792 1312v-192c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h960c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="eraser" unicode="&#xf12d;" horiz-adv-x="1920"
+d="M896 128l336 384h-768l-336 -384h768zM1909 1205c20 -46 12 -99 -21 -137l-896 -1024c-24 -28 -59 -44 -96 -44h-768c-50 0 -96 29 -117 75c-20 46 -12 99 21 137l896 1024c24 28 59 44 96 44h768c50 0 96 -29 117 -75z" />
+ <glyph glyph-name="codepen" unicode="&#xf1cb;" horiz-adv-x="1792"
+d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546
+c0 -25 -13 -50 -34 -64l-819 -546c-13 -8 -28 -13 -43 -13s-30 5 -43 13l-819 546c-21 14 -34 39 -34 64v546c0 25 13 50 34 64l819 546c13 8 28 13 43 13s30 -5 43 -13l819 -546c21 -14 34 -39 34 -64z" />
+ <glyph glyph-name="slideshare" unicode="&#xf1e7;" horiz-adv-x="1758"
+d="M856 796c0 -111 -97 -202 -216 -202s-216 91 -216 202c0 112 97 202 216 202s216 -90 216 -202zM1358 796c0 -111 -96 -202 -216 -202c-119 0 -216 91 -216 202c0 112 97 202 216 202c120 0 216 -90 216 -202zM1583 616v667c0 115 -37 160 -143 160h-1112
+c-111 0 -142 -38 -142 -160v-673c237 -124 440 -102 551 -98c47 1 77 -8 95 -27c3 -3 6 -6 10 -9c21 -20 41 -36 61 -51c4 55 35 90 118 87c113 -5 321 -27 562 104zM1746 621c-64 -79 -186 -176 -372 -252c197 -671 -481 -778 -470 -434c0 -6 -1 185 -1 327
+c-15 3 -30 7 -48 11c0 -143 -1 -344 -1 -338c11 -344 -667 -237 -470 434c-186 76 -308 173 -372 252c-32 48 3 99 56 62c7 -5 15 -10 22 -15v694c0 96 72 174 161 174h1257c89 0 161 -78 161 -174v-694l21 15c53 37 88 -14 56 -62z" />
+ <glyph glyph-name="square-o" unicode="&#xf096;" horiz-adv-x="1408"
+d="M1120 1280h-832c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160v832c0 88 -72 160 -160 160zM1408 1120v-832c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="hourglass-start" unicode="&#xf251;"
+d="M1408 1408c0 -370 -177 -638 -373 -768c196 -130 373 -398 373 -768h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96c0 370 177 638 373 768c-196 130 -373 398 -373 768h-96c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h1472c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96zM1280 1408h-1024c0 -44 3 -87 9 -128h1006c6 41 9 84 9 128zM1280 -128c0 359 -198 624 -397 704h-230c-199 -80 -397 -345 -397 -704h1024z" />
+ <glyph glyph-name="superpowers" unicode="&#xf2dd;" horiz-adv-x="1792"
+d="M1473 607c18 320 -227 585 -544 604c-315 19 -594 -221 -612 -538c-18 -320 227 -585 545 -604c315 -19 594 220 611 538zM1792 1536l-349 -348c159 -155 245 -371 231 -593c-22 -372 -308 -669 -675 -719l-999 -132l347 347c-159 155 -244 371 -231 593
+c23 373 308 670 676 720c333 44 667 88 1000 132z" />
+ <glyph glyph-name="fire" unicode="&#xf06d;" horiz-adv-x="1408"
+d="M1408 -160v-64c0 -17 -15 -32 -32 -32h-1344c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h1344c17 0 32 -15 32 -32zM1152 896c0 -383 -448 -417 -448 -672c0 -70 35 -163 67 -224l-4 1l1 -1c-276 127 -512 302 -512 640c0 383 448 417 448 672c0 70 -35 163 -66 224l3 -1
+l-1 1c276 -127 512 -302 512 -640z" />
+ <glyph glyph-name="sellsy" unicode="&#xf213;" horiz-adv-x="2048"
+d="M1500 165v733c0 28 -23 51 -50 51h-93c-27 0 -50 -23 -50 -51v-733c0 -27 23 -50 50 -50h93c27 0 50 23 50 50zM1216 165v531c0 27 -23 50 -50 50h-101c-27 0 -50 -23 -50 -50v-531c0 -27 23 -50 50 -50h101c27 0 50 23 50 50zM924 165v429c0 27 -23 50 -50 50h-101
+c-27 0 -50 -23 -50 -50v-429c0 -27 23 -50 50 -50h101c27 0 50 23 50 50zM632 165v362c0 27 -23 50 -50 50h-101c-27 0 -50 -23 -50 -50v-362c0 -27 23 -50 50 -50h101c27 0 50 23 50 50zM2048 311c0 -222 -181 -402 -402 -402h-1244c-221 0 -402 180 -402 402
+c0 155 91 297 231 363c-7 24 -10 49 -10 73c0 151 123 274 274 274c66 0 130 -24 180 -67c60 244 280 417 532 417c302 0 548 -246 548 -548c0 -41 -4 -82 -14 -122c180 -44 307 -206 307 -390z" />
+ <glyph glyph-name="fast-forward" unicode="&#xf050;" horiz-adv-x="1792"
+d="M45 -115c-25 -25 -45 -16 -45 19v1472c0 35 20 44 45 19l710 -710c6 -6 10 -12 13 -19v710c0 35 20 44 45 19l710 -710c6 -6 10 -12 13 -19v678c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-1408c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v678
+c-3 -7 -7 -13 -13 -19l-710 -710c-25 -25 -45 -16 -45 19v710c-3 -7 -7 -13 -13 -19z" />
+ <glyph glyph-name="bell-slash" unicode="&#xf1f6;" horiz-adv-x="2019"
+d="M1544 684c51 -298 182 -458 298 -556c0 -70 -58 -128 -128 -128h-448c0 -141 -115 -256 -256 -256s-255 114 -256 255zM1010 -176c9 0 16 7 16 16s-7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176zM2012 1424
+c11 -14 10 -34 -3 -46l-1872 -1622c-13 -11 -34 -10 -45 4l-84 96c-11 14 -10 34 3 45l186 161c-12 20 -19 42 -19 66c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c172 -25 299 -122 367 -240
+l418 363c13 11 34 10 45 -4z" />
+ <glyph glyph-name="cubes" unicode="&#xf1b3;" horiz-adv-x="2176"
+d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416
+c0 -48 -27 -93 -71 -114l-448 -224c-18 -10 -37 -14 -57 -14s-39 4 -57 14l-448 224c-3 1 -5 2 -7 4c-2 -2 -4 -3 -7 -4l-448 -224c-18 -10 -37 -14 -57 -14s-39 4 -57 14l-448 224c-44 21 -71 66 -71 114v416c0 51 31 97 78 118l434 186v400c0 51 31 97 78 118l448 192
+c16 7 33 10 50 10s34 -3 50 -10l448 -192c47 -21 78 -67 78 -118v-400l434 -186c48 -21 78 -67 78 -118z" />
+ <glyph glyph-name="inr" unicode="&#xf156;" horiz-adv-x="898"
+d="M898 1066v-102c0 -18 -14 -32 -32 -32h-168c-31 -192 -178 -317 -405 -344c149 -159 308 -351 459 -536c8 -9 10 -23 4 -34c-5 -11 -16 -18 -29 -18h-195c-10 0 -19 4 -25 12c-161 193 -309 370 -498 571c-6 6 -9 14 -9 22v127c0 17 14 32 32 32h112
+c176 0 286 59 315 168h-427c-18 0 -32 14 -32 32v102c0 18 14 32 32 32h413c-38 75 -128 113 -268 113h-145c-18 0 -32 15 -32 32v133c0 18 14 32 32 32h832c18 0 32 -14 32 -32v-102c0 -18 -14 -32 -32 -32h-233c32 -41 53 -89 64 -144h171c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="hashtag" unicode="&#xf292;" horiz-adv-x="1728"
+d="M959 512l64 256h-254l-64 -256h254zM1727 1016l-56 -224c-4 -14 -16 -24 -31 -24h-327l-64 -256h311c10 0 19 -5 25 -12c6 -8 9 -18 6 -28l-56 -224c-3 -14 -16 -24 -31 -24h-327l-81 -328c-4 -14 -17 -24 -31 -24h-224c-10 0 -20 5 -26 12c-6 8 -8 18 -6 28l78 312h-254
+l-81 -328c-4 -14 -17 -24 -31 -24h-225c-9 0 -19 5 -25 12c-6 8 -8 18 -6 28l78 312h-311c-10 0 -19 5 -25 12c-6 8 -8 18 -6 28l56 224c4 14 16 24 31 24h327l64 256h-311c-10 0 -19 5 -25 12c-6 8 -9 18 -6 28l56 224c3 14 16 24 31 24h327l81 328c4 14 17 24 32 24h224
+c9 0 19 -5 25 -12c6 -8 8 -18 6 -28l-78 -312h254l81 328c4 14 17 24 32 24h224c9 0 19 -5 25 -12c6 -8 8 -18 6 -28l-78 -312h311c10 0 19 -5 25 -12c6 -8 8 -18 6 -28z" />
+ <glyph glyph-name="file-text-o" unicode="&#xf0f6;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM384 736c0 18 14 32 32 32h704c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-704c-18 0 -32 14 -32 32v64zM1120 512c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-704c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h704zM1120 256c18 0 32 -14 32 -32
+v-64c0 -18 -14 -32 -32 -32h-704c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h704z" />
+ <glyph glyph-name="nextcloud" unicode="&#xf306;" horiz-adv-x="1792"
+d="M896 1049c225 0 409 -184 409 -409s-184 -409 -409 -409s-409 184 -409 409s184 409 409 409zM896 891c-139 0 -251 -112 -251 -251s112 -251 251 -251s251 112 251 251s-112 251 -251 251zM265 905c146 0 265 -119 265 -265s-119 -265 -265 -265s-265 119 -265 265
+s119 265 265 265zM265 748c-60 0 -107 -48 -107 -108s47 -108 107 -108s108 48 108 108s-48 108 -108 108zM1527 905c146 0 265 -119 265 -265s-119 -265 -265 -265s-265 119 -265 265s119 265 265 265zM1527 748c-60 0 -108 -48 -108 -108s48 -108 108 -108s107 48 107 108
+s-47 108 -107 108z" />
+ <glyph glyph-name="hand-o-left" unicode="&#xf0a5;" horiz-adv-x="1792"
+d="M1376 128h32v640h-32c-106 0 -177 90 -241 163c-41 46 -79 92 -112 145c-14 22 -26 45 -38 68s-62 136 -89 136c-85 0 -160 -32 -160 -128c0 -128 96 -193 96 -256h-576c-67 0 -128 -60 -128 -128c0 -69 59 -128 128 -128h331c-21 -24 -35 -71 -35 -103
+c0 -47 19 -87 53 -119c-12 -21 -18 -45 -18 -69c0 -46 23 -103 65 -126c-3 -18 -4 -37 -4 -56c0 -118 73 -167 184 -167c199 0 369 128 544 128zM1664 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1792 768v-640c0 -71 -57 -128 -128 -128h-288
+c-63 0 -162 -37 -223 -59c-102 -37 -207 -69 -317 -69c-184 0 -318 104 -317 295l1 5c-40 50 -61 114 -61 178c0 14 1 29 3 43c-21 37 -34 77 -37 119h-169c-140 0 -256 117 -256 257c0 138 118 255 256 255h374c-15 41 -22 84 -22 128c0 169 129 256 288 256
+c134 0 177 -171 235 -264c30 -47 64 -88 100 -129c29 -33 97 -119 145 -119h288c71 0 128 -57 128 -128z" />
+ <glyph glyph-name="vimeo" unicode="&#xf27d;" horiz-adv-x="1628"
+d="M1627 1018c-7 -158 -118 -375 -332 -651c-222 -287 -408 -431 -562 -431c-95 0 -175 88 -240 263c-44 160 -88 321 -132 482c-48 175 -101 262 -157 262c-12 0 -54 -25 -127 -76l-77 98c80 71 159 143 238 212c106 94 187 141 241 146c127 12 204 -74 234 -259
+c31 -200 54 -325 66 -373c37 -166 76 -249 120 -249c34 0 85 53 154 161c68 108 104 190 109 246c9 93 -27 139 -109 139c-39 0 -79 -9 -121 -26c80 262 233 389 459 382c167 -5 246 -114 236 -326z" />
+ <glyph glyph-name="mastodon-alt" unicode="&#xf2e2;"
+d="M766 1408h5c211 -2 413 -25 531 -79c0 0 234 -105 234 -462c0 0 3 -263 -33 -446c-23 -116 -202 -243 -408 -268c-108 -13 -214 -25 -327 -20c-185 8 -330 45 -330 45c0 -18 1 -36 3 -52c24 -182 181 -193 329 -198c150 -5 284 37 284 37l6 -135s-105 -57 -292 -67
+c-103 -6 -230 3 -379 42c-323 85 -380 430 -388 779c-3 104 -1 201 -1 283c0 357 235 462 235 462c118 54 320 77 531 79v0zM350 839c-64 0 -115 -52 -115 -116s51 -115 115 -115s116 51 116 115s-52 116 -116 116v0zM768 839c-64 0 -116 -52 -116 -116s52 -115 116 -115
+s116 51 116 115s-52 116 -116 116v0zM1186 839c-64 0 -116 -52 -116 -116s52 -115 116 -115s115 51 115 115s-51 116 -115 116v0z" />
+ <glyph glyph-name="strikethrough" unicode="&#xf0cc;" horiz-adv-x="1792"
+d="M1760 640c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-1728c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h1728zM483 704c-19 24 -36 51 -51 80c-32 65 -48 128 -48 188c0 122 45 224 134 309s220 127 393 127c38 0 93 -7 167 -19c44 -8 103 -24 177 -48
+c7 -26 14 -66 21 -118c9 -79 14 -140 14 -183c0 -14 -2 -29 -5 -45l-12 -3l-84 6l-14 2c-34 101 -69 169 -103 205c-59 61 -130 91 -210 91c-76 0 -137 -20 -182 -59s-67 -88 -67 -146c0 -49 22 -95 66 -140s137 -88 279 -129c48 -14 105 -36 173 -66c36 -17 68 -34 95 -52
+h-743zM990 448h411c5 -28 7 -59 7 -92c0 -72 -13 -143 -41 -212c-15 -37 -38 -71 -71 -104c-24 -23 -60 -50 -109 -81c-50 -30 -100 -53 -153 -66c-53 -14 -120 -21 -203 -21c-55 0 -121 2 -195 23l-140 40c-39 11 -62 20 -72 28c-4 4 -8 11 -8 22v13c0 8 2 60 -2 156
+c-2 50 2 85 2 105v44l102 2c37 -85 54 -136 65 -154c24 -39 51 -70 80 -94s64 -43 105 -57c40 -15 85 -22 132 -22c42 0 89 9 139 27c51 17 92 46 122 86c31 40 47 83 47 129c0 56 -27 108 -81 157c-22 19 -68 43 -137 71z" />
+ <glyph glyph-name="ravelry" unicode="&#xf2d9;" horiz-adv-x="2080"
+d="M1095 -197c-4 1 -7 2 -11 4c0 0 -329 193 -440 505c-37 6 -115 24 -175 37c87 -283 329 -499 626 -546zM454 409l168 -28c-57 171 -64 366 -64 366c-67 -65 -103 -154 -121 -224c3 -39 8 -77 17 -114zM564 1018c-31 -46 -56 -96 -77 -148c33 35 60 58 74 68
+c-2 30 3 80 3 80zM2001 584c0 436 -352 790 -784 790c-200 0 -382 -76 -521 -201c-21 -41 -35 -93 -45 -160c213 181 593 136 593 136c95 -4 84 -88 83 -114c-346 29 -516 -70 -684 -213c0 0 33 -320 109 -450c438 -20 771 218 771 218c42 30 79 33 87 -19
+c6 -42 9 -99 -39 -121c-146 -68 -307 -111 -467 -134c-104 -15 -162 -19 -317 -16c148 -344 518 -438 518 -438c116 -19 204 -4 263 15c256 130 433 398 433 707zM2075 621c-7 -68 -18 -147 -40 -212c-90 -267 -215 -441 -500 -600c-26 -18 -54 -35 -82 -44
+c-51 -18 -106 -22 -163 -16c-24 -2 -48 -3 -73 -3c-381 0 -703 260 -800 615c-3 0 -6 1 -9 1c-23 -180 110 -423 110 -423s8 -12 54 -82c-255 135 -262 533 -262 533c-61 23 -273 95 -310 154c0 0 166 -91 309 -109c-1 1 2 32 2 32c9 122 51 217 94 290
+c28 137 90 261 176 365c15 62 39 136 81 214c18 34 35 56 81 77c304 142 604 178 912 18c295 -154 455 -476 420 -810z" />
+ <glyph glyph-name="code-fork" unicode="&#xf126;" horiz-adv-x="1024"
+d="M288 64c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM288 1216c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM928 1088c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM1024 1088c0 -71 -39 -133 -96 -166
+c-3 -361 -259 -441 -429 -495c-159 -50 -211 -74 -211 -171v-26c57 -33 96 -95 96 -166c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 71 39 133 96 166v820c-57 33 -96 95 -96 166c0 106 86 192 192 192s192 -86 192 -192c0 -71 -39 -133 -96 -166v-497
+c51 25 105 42 154 57c186 59 292 103 294 312c-57 33 -96 95 -96 166c0 106 86 192 192 192s192 -86 192 -192z" />
+ <glyph glyph-name="hand-o-right" unicode="&#xf0a4;" horiz-adv-x="1792"
+d="M256 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1664 768c0 68 -61 128 -128 128h-576c0 63 96 128 96 256c0 96 -75 128 -160 128c-28 0 -79 -116 -90 -139c-12 -22 -24 -44 -37 -65c-33 -53 -71 -99 -112 -145c-64 -73 -135 -163 -241 -163
+h-32v-640h32c175 0 346 -128 540 -128c112 0 189 47 189 167c0 19 -2 38 -5 56c42 23 65 80 65 126c0 24 -6 48 -18 69c34 32 53 72 53 119c0 32 -14 79 -35 103h331c69 0 128 59 128 128zM1792 769c0 -140 -116 -257 -256 -257h-169c-3 -42 -16 -82 -37 -119
+c2 -14 3 -29 3 -43c0 -64 -21 -128 -60 -178c2 -189 -127 -300 -312 -300c-112 0 -218 31 -322 69c-61 22 -160 59 -223 59h-288c-71 0 -128 57 -128 128v640c0 71 57 128 128 128h288c48 0 116 86 145 119c36 41 70 82 100 129c58 93 101 264 235 264
+c159 0 288 -87 288 -256c0 -44 -7 -87 -22 -128h374c138 0 256 -117 256 -255z" />
+ <glyph glyph-name="object-group" unicode="&#xf247;" horiz-adv-x="2048"
+d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128
+h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+ <glyph glyph-name="wikidata" unicode="&#xf31a;" horiz-adv-x="2048"
+d="M0 1264h76v-1264h-76v1264zM152 1264h227v-1264h-227v1264zM455 1264h228v-1264h-228v1264zM759 1264h75v-1264h-75v1264zM910 1264h76v-1264h-76v1264zM1820 1264h76v-1264h-76v1264zM1972 1264h76v-1264h-76v1264zM1062 1264h227v-1264h-227v1264zM1365 1264h76v-1264
+h-76v1264zM1517 1264h228v-1264h-228v1264z" />
+ <glyph glyph-name="anchor" unicode="&#xf13d;" horiz-adv-x="1792"
+d="M960 1280c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1792 352v-352c0 -13 -8 -25 -20 -30c-4 -1 -8 -2 -12 -2c-8 0 -16 3 -23 9l-93 93c-157 -189 -439 -310 -748 -310s-591 121 -748 310l-93 -93c-6 -6 -15 -9 -23 -9c-4 0 -8 1 -12 2
+c-12 5 -20 17 -20 30v352c0 18 14 32 32 32h352c13 0 25 -8 30 -20s2 -25 -7 -35l-100 -100c90 -121 263 -209 461 -236v647h-192c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h192v163c-76 44 -128 126 -128 221c0 141 115 256 256 256s256 -115 256 -256
+c0 -95 -52 -177 -128 -221v-163h192c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-192v-647c198 27 371 115 461 236l-100 100c-9 10 -12 23 -7 35s17 20 30 20h352c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="meh-o" unicode="&#xf11a;"
+d="M1152 448c0 -35 -29 -64 -64 -64h-640c-35 0 -64 29 -64 64s29 64 64 64h640c35 0 64 -29 64 -64zM640 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1152 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128
+s128 -57 128 -128zM1408 640c0 353 -287 640 -640 640s-640 -287 -640 -640s287 -640 640 -640s640 287 640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="file-image-o" unicode="&#xf1c5;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512c-106 0 -192 86 -192 192s86 192 192 192s192 -86 192 -192s-86 -192 -192 -192z" />
+ <glyph glyph-name="liberapay" unicode="&#xf2e9;" horiz-adv-x="1191"
+d="M468 1404v0l-222 -918c-4 -19 -6 -37 -7 -53s3 -30 9 -42s18 -23 33 -30s36 -12 64 -14l-48 -196c-75 0 -134 9 -177 29s-74 47 -93 81s-28 73 -27 117s6 91 18 141l203 847zM849 1025v0c60 0 111 -9 154 -27s78 -44 106 -75s49 -68 62 -110s20 -86 20 -134h-1
+c0 -78 -12 -149 -38 -213s-61 -120 -106 -167s-99 -83 -162 -109s-133 -39 -207 -39c-36 0 -72 3 -108 9l-72 -288h-236l265 1103c42 13 91 24 146 34s113 16 177 16zM819 825v0c-34 0 -66 -3 -96 -9l-111 -464c18 -4 40 -7 67 -7c41 0 79 8 113 23s63 37 87 65
+s43 61 56 100s20 81 20 128c0 46 -11 84 -31 116s-55 48 -105 48z" />
+ <glyph glyph-name="nodejs" unicode="&#xf308;"
+d="M768 -225c-24 0 -46 6 -67 17l-211 126c-32 17 -17 24 -7 27c43 14 51 18 96 43c5 3 11 1 16 -2l162 -97c6 -3 14 -3 19 0l634 367c6 3 10 10 10 18v733c0 8 -4 14 -10 17l-634 366c-6 3 -14 3 -19 0l-635 -366c-6 -3 -9 -11 -9 -17v-733c0 -6 3 -15 9 -18l174 -100
+c94 -48 152 8 152 64v723c0 10 8 19 19 19h82c10 0 19 -8 19 -19v-723c0 -126 -69 -199 -188 -199c-37 0 -65 0 -146 40l-167 95c-41 24 -67 68 -67 116v733c0 48 26 92 67 116l634 368c40 22 94 22 134 0l634 -368c41 -24 67 -68 67 -116v-733c0 -48 -26 -92 -67 -116
+l-634 -367c-21 -10 -45 -14 -67 -14zM964 279c-278 0 -336 127 -336 235c0 10 8 19 19 19h83c10 0 17 -6 17 -16c13 -84 49 -125 218 -125c134 0 191 29 191 101c0 41 -16 72 -224 93c-173 17 -282 56 -282 194c0 129 109 205 290 205c204 0 303 -70 316 -223
+c0 -5 -2 -9 -5 -14c-3 -3 -7 -7 -12 -7h-83c-8 0 -16 7 -18 15c-19 87 -68 116 -198 116c-146 0 -164 -51 -164 -89c0 -46 21 -61 218 -86c196 -25 288 -62 288 -199c-2 -140 -116 -219 -318 -219z" />
+ <glyph glyph-name="calculator" unicode="&#xf1ec;" horiz-adv-x="1664"
+d="M384 0c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM768 0c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM384 384c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1152 0
+c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM768 384c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM384 768c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1152 384
+c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM768 768c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1536 0v384c0 70 -58 128 -128 128s-128 -58 -128 -128v-384c0 -70 58 -128 128 -128s128 58 128 128z
+M1152 768c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1536 1088v256c0 35 -29 64 -64 64h-1280c-35 0 -64 -29 -64 -64v-256c0 -35 29 -64 64 -64h1280c35 0 64 29 64 64zM1536 768c0 71 -57 128 -128 128s-128 -57 -128 -128
+s57 -128 128 -128s128 57 128 128zM1664 1408v-1536c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1536c0 70 58 128 128 128h1408c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="vk" unicode="&#xf189;" horiz-adv-x="1921"
+d="M1918 1016c15 -41 -32 -137 -150 -294c-194 -258 -215 -234 -55 -383c154 -143 186 -212 191 -221c0 0 64 -112 -71 -113l-256 -4c-55 -11 -128 39 -128 39c-96 66 -186 237 -256 215c0 0 -72 -23 -70 -177c1 -33 -15 -51 -15 -51s-18 -19 -53 -22h-115
+c-253 -16 -476 217 -476 217s-244 252 -458 755c-14 33 1 49 1 49s15 19 57 19l274 2c26 -4 44 -18 44 -18s16 -11 24 -32c45 -112 103 -214 103 -214c100 -206 168 -241 207 -220c0 0 51 31 40 280c-4 90 -29 131 -29 131c-23 31 -66 40 -85 43c-15 2 10 38 43 54
+c49 24 136 25 239 24c81 -1 104 -6 135 -13c95 -23 63 -111 63 -323c0 -68 -13 -163 36 -194c21 -14 73 -2 201 216c0 0 60 104 107 225c8 22 25 31 25 31s16 9 38 6l288 2c87 11 101 -29 101 -29z" />
+ <glyph glyph-name="odnoklassniki" unicode="&#xf263;" horiz-adv-x="1078"
+d="M539 629c-250 0 -454 203 -454 453c0 251 204 454 454 454s454 -203 454 -454c0 -250 -204 -453 -454 -453zM539 1306c-123 0 -223 -100 -223 -224c0 -123 100 -223 223 -223s223 100 223 223c0 124 -100 224 -223 224zM1062 574c44 -90 -6 -133 -120 -207
+c-96 -61 -228 -85 -315 -94l73 -72l267 -267c40 -41 40 -107 0 -147l-12 -13c-41 -40 -107 -40 -148 0c-67 68 -165 166 -267 268l-267 -268c-41 -40 -107 -40 -147 0l-12 13c-41 40 -41 106 0 147c68 68 165 166 267 267l72 72c-86 9 -220 32 -317 94
+c-114 74 -164 117 -120 207c26 51 97 94 191 20c0 0 127 -101 332 -101s332 101 332 101c94 74 165 31 191 -20z" />
+ <glyph glyph-name="linkedin" unicode="&#xf0e1;"
+d="M349 911v-991h-330v991h330zM370 1217c1 -95 -71 -171 -186 -171h-2c-111 0 -182 76 -182 171c0 97 74 171 186 171c113 0 183 -74 184 -171zM1536 488v-568h-329v530c0 133 -48 224 -167 224c-91 0 -145 -61 -169 -120c-8 -22 -11 -51 -11 -81v-553h-329
+c4 898 0 991 0 991h329v-144h-2c43 68 121 167 299 167c217 0 379 -142 379 -446z" />
+ <glyph glyph-name="jpy" unicode="&#xf157;" horiz-adv-x="1026"
+d="M603 0h-172c-18 0 -32 14 -32 32v330h-288c-18 0 -32 14 -32 32v103c0 18 14 32 32 32h288v85h-288c-18 0 -32 14 -32 32v104c0 17 14 32 32 32h214l-321 578c-5 10 -5 22 0 32c6 10 17 16 28 16h194c12 0 23 -7 29 -18l215 -425c24 -47 40 -87 56 -125
+c17 43 39 85 58 129l191 420c5 12 17 19 29 19h191c11 0 21 -6 27 -16c6 -9 6 -21 1 -31l-313 -579h215c18 0 32 -15 32 -32v-104c0 -18 -14 -32 -32 -32h-290v-85h290c18 0 32 -14 32 -32v-103c0 -18 -14 -32 -32 -32h-290v-330c0 -18 -15 -32 -32 -32z" />
+ <glyph glyph-name="skype" unicode="&#xf17e;"
+d="M1173 473c0 174 -169 234 -311 266l-104 24c-76 18 -133 31 -133 89c0 53 56 77 144 77c157 0 160 -115 257 -115c65 0 104 51 104 109c0 115 -191 190 -380 190c-173 0 -374 -75 -374 -278c0 -168 112 -228 258 -263l146 -36c89 -22 144 -32 144 -96
+c0 -51 -57 -90 -145 -90c-185 0 -195 154 -302 154c-70 0 -101 -50 -101 -105c0 -123 188 -223 413 -223c188 0 384 94 384 297zM1536 256c0 -212 -172 -384 -384 -384c-88 0 -169 30 -234 80c-48 -10 -99 -16 -150 -16c-389 0 -704 315 -704 704c0 51 6 102 16 150
+c-50 65 -80 146 -80 234c0 212 172 384 384 384c88 0 169 -30 234 -80c48 10 99 16 150 16c389 0 704 -315 704 -704c0 -51 -6 -102 -16 -150c50 -65 80 -146 80 -234z" />
+ <glyph glyph-name="envelope-square" unicode="&#xf199;"
+d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960zM1280 352v436c-19 -21 -40 -40 -64 -55c-94 -62 -191 -120 -284 -184c-47 -33 -105 -69 -164 -69s-117 36 -164 69
+c-93 64 -191 121 -284 185c-23 15 -41 37 -64 54v-436c0 -53 43 -96 96 -96h832c53 0 96 43 96 96zM1280 925c0 54 -40 99 -96 99h-832c-53 0 -96 -43 -96 -96c0 -54 56 -113 98 -141c88 -59 179 -114 267 -172c38 -25 101 -71 147 -71s109 46 147 71c89 58 178 115 267 174
+c39 26 98 86 98 136z" />
+ <glyph glyph-name="question-circle-o" unicode="&#xf29c;"
+d="M880 336v-160c0 -18 -14 -32 -32 -32h-160c-18 0 -32 14 -32 32v160c0 18 14 32 32 32h160c18 0 32 -14 32 -32zM1136 832c0 -142 -99 -198 -172 -239c-52 -30 -84 -49 -84 -81v-32c0 -18 -14 -32 -32 -32h-160c-18 0 -32 14 -32 32v68c0 123 88 162 159 194
+c60 28 97 47 97 92c0 58 -73 101 -139 101c-35 0 -72 -11 -95 -27c-22 -15 -43 -37 -80 -83c-6 -8 -15 -12 -25 -12c-7 0 -14 2 -19 6l-108 82c-13 10 -16 29 -7 43c82 129 197 192 349 192c164 0 348 -130 348 -304zM768 1280c-353 0 -640 -287 -640 -640
+s287 -640 640 -640s640 287 640 640s-287 640 -640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="ship" unicode="&#xf21a;" horiz-adv-x="2010"
+d="M1792 -19c25 25 65 25 90 0l128 -128l-90 -90l-83 83l-83 -83c-12 -13 -29 -19 -45 -19s-33 6 -45 19l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83
+l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-128 128l90 90l83 -83l83 83c25 25 65 25 90 0l83 -83l83 83c25 25 65 25 90 0l83 -83l83 83c25 25 65 25 90 0l83 -83l83 83c25 25 65 25 90 0l83 -83l83 83c25 25 65 25 90 0l83 -83l83 83
+c25 25 65 25 90 0l83 -83zM218 19c-25 -25 -65 -25 -90 0l-128 128l90 90l83 -82l83 82c25 25 65 25 90 0l83 -82l64 64v293l-210 314c-23 35 -7 83 33 97l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58c40 -14 56 -62 33 -97l-210 -314v-293l19 18
+c25 25 65 25 90 0l83 -82l83 82c25 25 65 25 90 0l128 -128l-90 -90l-83 83l-83 -83c-12 -13 -29 -19 -45 -19s-33 6 -45 19l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83l-83 -83
+c-25 -25 -65 -25 -90 0l-83 83l-83 -83c-25 -25 -65 -25 -90 0l-83 83zM621 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+ <glyph glyph-name="gimp" unicode="&#xf31b;" horiz-adv-x="1792"
+d="M1760 1453c243 -1827 -975 -1550 -1432 -1186c28 4 55 13 78 30c50 38 74 102 73 173s-25 150 -73 220c-6 9 -13 17 -20 25l26 588s159 -366 481 -358c674 18 794 417 867 508zM612 937c-97 0 -177 -85 -177 -193s80 -194 177 -194c16 0 31 4 46 8
+c-67 3 -122 62 -122 133v0c0 73 57 133 127 133v0c56 0 112 -47 124 -104c1 8 2 16 2 24c0 108 -80 193 -177 193zM1031 928v0c-119 0 -216 -102 -216 -228s97 -227 216 -227c45 0 87 14 122 39c-17 -8 -47 -15 -66 -15c-90 0 -162 77 -162 171v0c0 94 72 170 162 170
+c75 0 147 -63 160 -141v3c0 126 -97 228 -216 228zM158 822v0c79 -2 166 -58 227 -146c46 -67 70 -141 70 -206s-21 -121 -64 -153s-100 -37 -158 -16s-118 67 -164 134s-69 141 -69 206s21 121 64 153c26 20 58 29 94 28zM1042 804c-42 0 -76 -36 -76 -80v0
+c0 -44 34 -80 76 -80s76 36 76 80v0c0 44 -34 80 -76 80zM615 787c-28 0 -50 -23 -50 -52v0v0c0 -29 22 -53 50 -53s50 24 50 53v0v0c0 29 -22 52 -50 52zM130 770c-47 0 -85 -47 -85 -106v0c0 -59 38 -107 85 -107s84 48 84 107v0c0 59 -37 106 -84 106zM1202 468
+c0 0 44 -38 69 -72c-96 -78 -261 -141 -583 -73c163 -60 300 -88 406 -81c-64 -22 -146 -39 -250 -44c233 -23 407 22 468 117c16 -18 32 -49 47 -89c10 69 36 101 -4 155s-153 87 -153 87z" />
+ <glyph glyph-name="dashcube" unicode="&#xf210;" horiz-adv-x="1408"
+d="M0 856c0 173 138 322 314 322h742l352 358v-1470c0 -174 -138 -322 -314 -322h-780c-176 0 -314 148 -314 322v790zM1232 102l-176 180v425c0 61 -49 112 -110 112h-484c-61 0 -110 -51 -110 -112v-492c0 -61 49 -113 110 -113h770z" />
+ <glyph glyph-name="optin-monster" unicode="&#xf23c;" horiz-adv-x="2132"
+d="M396 -139c-10 -21 -39 -50 -64 -60c-35 -12 -78 11 -80 35c-2 31 75 87 108 93c32 6 47 -42 36 -68zM1737 -139c-11 26 4 74 35 68c33 -6 111 -62 108 -93c-1 -24 -45 -47 -79 -35c-26 10 -55 39 -64 60zM1785 -30c-21 43 15 121 70 114c58 -6 183 -94 183 -160
+c0 -43 -58 -72 -119 -55c-45 12 -116 65 -134 101zM346 -30c-18 -36 -88 -89 -133 -101c-61 -17 -119 12 -119 55c0 66 125 154 183 160c55 7 91 -71 69 -114zM1076 1094c106 0 192 -80 192 -179s-86 -179 -192 -179s-191 80 -191 179c0 15 2 28 5 42c16 -25 46 -43 80 -43
+c51 0 92 38 92 85c0 37 -26 69 -61 80c23 10 49 15 76 15h-1zM1380 1312c-132 145 -301 177 -466 87c93 208 452 180 466 -87zM2130 73c5 -7 -1 -25 -11 -42c4 -13 7 -26 7 -40c3 -117 -164 -237 -272 -241c-64 -3 -128 31 -158 87c-420 -15 -840 -18 -1259 0
+c-31 -56 -95 -89 -159 -87c-107 4 -274 124 -272 241c1 14 3 27 7 40c-10 17 -16 35 -11 42c4 6 17 6 31 1c12 19 26 35 41 51c-4 17 -4 32 2 38c7 6 23 4 39 -4c17 12 37 24 59 34c0 18 5 32 13 37c12 6 33 2 51 -16c21 3 42 3 61 -2c13 -3 26 -10 38 -19v73
+c-6 0 -11 0 -18 2c-65 12 -136 57 -152 132c-6 25 -6 52 0 81c12 50 55 79 93 95c3 22 30 52 55 59c28 7 46 -17 52 -38h13c18 -2 47 -6 60 -23c2 -2 4 -5 5 -7c20 2 41 5 61 7c-9 7 -19 13 -30 17c-19 33 -51 41 -91 43c0 3 0 6 1 10c-73 2 -163 21 -203 66
+c-46 51 -54 138 -45 204c8 65 35 140 90 179c31 21 80 3 84 -36c2 -17 5 -75 21 -84c18 -9 47 -13 76 -12c30 29 62 54 98 74c-55 5 -107 -6 -162 -14l47 46c46 44 107 82 163 111c87 44 185 77 282 86c-69 29 -148 44 -221 61c283 60 646 82 904 -139
+c67 -57 120 -134 158 -222c41 -5 93 -6 121 9h1c16 9 19 66 21 84c4 38 53 57 84 35c55 -39 82 -114 91 -178c8 -66 1 -153 -46 -204c-40 -45 -127 -65 -199 -67v-10c-41 -1 -75 -9 -95 -43c-11 -4 -21 -10 -31 -17c21 -2 42 -5 62 -7c1 3 3 6 5 8c14 16 43 21 60 23h13
+c6 20 25 44 52 38s52 -37 55 -59c40 -16 82 -45 93 -95c7 -30 6 -56 1 -81c-17 -75 -88 -121 -153 -132c-5 -1 -12 -2 -17 -2c0 -25 0 -49 -1 -73c12 9 24 16 38 19c19 5 40 5 61 2c18 18 40 22 51 16c8 -5 14 -19 14 -37c21 -10 42 -22 59 -34c16 8 31 10 38 4
+c6 -6 7 -21 2 -38c15 -16 30 -33 41 -51c14 5 26 5 31 -1zM1855 1025c0 -23 -5 -43 -9 -54c64 -25 97 -82 112 -132c4 39 -10 146 -51 189c-27 27 -52 19 -52 -3zM1777 925c48 -58 63 -154 47 -233c40 8 76 23 97 45c7 8 14 18 18 28c-4 79 -38 158 -110 181
+c-12 -12 -34 -18 -52 -21zM1740 921c-14 0 -30 0 -44 1c28 -76 46 -158 53 -239c13 0 28 1 43 3c22 90 -1 191 -52 235zM176 839c15 50 48 107 112 132c-4 11 -9 31 -9 54c0 22 -26 30 -52 3c-42 -43 -55 -150 -51 -189zM212 737c21 -23 57 -37 97 -45c-16 79 -1 175 47 233
+c-18 3 -40 9 -52 21c-72 -23 -105 -102 -110 -181c5 -10 11 -20 18 -28zM389 683c9 82 34 162 73 235c-19 -4 -37 -11 -55 -18l-45 -19v1c-27 -52 -37 -127 -20 -196c17 -2 32 -3 47 -3zM1352 644c13 -66 18 -132 28 -198c4 -23 11 -28 33 -17c59 30 84 145 85 211
+c-48 3 -97 3 -146 4zM1070 1285c-155 0 -282 -126 -282 -281c0 -156 127 -282 282 -282s282 126 282 282c0 155 -127 281 -282 281zM1298 646c-70 1 -141 1 -211 0v1c-1 -19 1 -141 16 -152c41 -20 146 -17 189 -4c20 6 9 137 6 155zM1030 447c17 9 9 168 5 199v1
+c-72 -1 -143 -1 -214 -3c-7 -34 -17 -181 7 -191c48 -21 154 -19 202 -6zM636 636c-20 -73 1 -167 82 -203c20 -9 32 -9 36 16c7 32 9 136 18 193c-45 -1 -91 -3 -136 -6zM509 510c2 -18 -14 -29 -34 -36c162 -174 343 -317 577 -394c250 71 428 222 604 396
+c-18 7 -32 19 -30 34c1 4 2 6 3 9v1v-1c-33 3 -66 7 -98 10c-35 -122 -133 -196 -173 -117c-10 19 -13 43 -17 62c-14 -31 -49 -30 -91 -33c-49 -4 -117 -5 -163 11c-11 -48 -41 -48 -99 -53c-52 -5 -180 -15 -203 40c-4 -106 -130 -37 -167 26c-12 21 -20 42 -26 65
+c-29 -3 -58 -6 -87 -10c2 -3 3 -7 4 -10zM425 -118c2 9 3 19 3 30c-21 86 -69 184 -124 200c-83 25 -255 -87 -245 -202c47 -72 148 -132 219 -135c66 -3 133 41 147 107zM428 53c12 -33 24 -77 27 -119c124 72 256 132 392 174c-143 76 -252 177 -360 285
+c-8 -5 -19 -9 -29 -13c-1 -3 -1 -6 -2 -9c17 -10 29 -22 22 -37c-8 -15 -32 -28 -56 -34c-8 -10 -19 -18 -29 -24h-1c-1 -50 -1 -100 1 -150c14 -25 26 -51 35 -73zM497 -113c382 -15 764 -13 1145 0c-136 79 -274 153 -428 196c-51 -23 -103 -42 -156 -57
+c-8 -3 -8 -3 -16 0c-44 14 -86 30 -129 49c-149 -43 -286 -108 -416 -188h-1v-1c1 0 1 0 1 1zM1681 -67c3 42 16 87 28 120c8 22 19 47 33 71l-1 -1c2 51 3 102 3 153c-11 6 -21 15 -30 25c-24 5 -48 19 -56 33c-7 15 5 28 22 38c-1 2 -2 6 -2 9c-11 3 -20 7 -28 12
+c-117 -109 -242 -210 -383 -284c144 -43 281 -104 414 -176zM2073 -90c11 115 -161 227 -245 202c-54 -16 -103 -114 -124 -200c0 -11 1 -21 3 -30c14 -66 81 -110 147 -107c71 3 172 63 219 135z" />
+ <glyph glyph-name="paw" unicode="&#xf1b0;" horiz-adv-x="1664"
+d="M780 1064c0 -112 -58 -245 -187 -245c-162 0 -260 204 -260 344c0 112 58 245 187 245c163 0 260 -204 260 -344zM438 581c0 -97 -51 -198 -161 -198c-160 0 -277 196 -277 341c0 97 52 199 161 199c160 0 277 -197 277 -342zM832 608c245 0 576 -353 576 -589
+c0 -127 -104 -147 -206 -147c-134 0 -242 90 -370 90c-134 0 -248 -89 -393 -89c-97 0 -183 33 -183 146c0 237 331 589 576 589zM1071 819c-129 0 -187 133 -187 245c0 140 97 344 260 344c129 0 187 -133 187 -245c0 -140 -98 -344 -260 -344zM1503 923
+c109 0 161 -102 161 -199c0 -145 -117 -341 -277 -341c-110 0 -161 101 -161 198c0 145 117 342 277 342z" />
+ <glyph glyph-name="venus-double" unicode="&#xf226;" horiz-adv-x="1792"
+d="M1790 1007c25 -317 -207 -586 -510 -619v-260h224c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-224v-224c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v224h-512v-224c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v224h-224c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h224v260c-303 33 -535 302 -510 619c22 275 243 500 517 526c140 14 271 -23 377 -94c106 71 237 108 377 94c274 -26 495 -251 517 -526zM896 647c79 81 128 191 128 313s-49 232 -128 313c-79 -81 -128 -191 -128 -313s49 -232 128 -313zM576 512
+c79 0 153 21 218 57c-96 103 -154 240 -154 391s59 288 154 391c-65 36 -139 57 -218 57c-247 0 -448 -201 -448 -448s201 -448 448 -448zM1152 128v260c-94 10 -181 44 -256 94c-75 -50 -162 -84 -256 -94v-260h512zM1216 512c247 0 448 201 448 448s-201 448 -448 448
+c-79 0 -153 -21 -218 -57c95 -103 154 -240 154 -391s-58 -288 -154 -391c65 -36 139 -57 218 -57z" />
+ <glyph glyph-name="calendar-times-o" unicode="&#xf273;" horiz-adv-x="1664"
+d="M1111 151l-46 -46c-12 -12 -32 -12 -45 0l-188 189l-188 -189c-13 -12 -33 -12 -45 0l-46 46c-12 12 -12 32 0 45l189 188l-189 188c-12 13 -12 33 0 45l46 46c12 12 32 12 45 0l188 -188l188 188c13 12 33 12 45 0l46 -46c12 -12 12 -32 0 -45l-188 -188l188 -188
+c12 -13 12 -33 0 -45zM128 -128h1408v1024h-1408v-1024zM512 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1280 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64
+c18 0 32 14 32 32zM1664 1152v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128c70 0 128 -58 128 -128z
+" />
+ <glyph glyph-name="address-book-o" unicode="&#xf2ba;" horiz-adv-x="1664"
+d="M1028 892c0 -143 -117 -259 -260 -259s-260 116 -260 259c0 144 117 260 260 260s260 -116 260 -260zM980 672c191 0 221 -227 221 -374c0 -84 -53 -170 -145 -170h-576c-92 0 -145 86 -145 170c0 141 30 374 216 374h5c66 -39 133 -87 212 -87s146 48 212 87zM1664 928
+c0 -17 -15 -32 -32 -32h-96v-128h96c17 0 32 -15 32 -32v-192c0 -17 -15 -32 -32 -32h-96v-128h96c17 0 32 -15 32 -32v-192c0 -17 -15 -32 -32 -32h-96v-224c0 -88 -72 -160 -160 -160h-1216c-88 0 -160 72 -160 160v1472c0 88 72 160 160 160h1216c88 0 160 -72 160 -160
+v-224h96c17 0 32 -15 32 -32v-192zM1408 -96v1472c0 17 -15 32 -32 32h-1216c-17 0 -32 -15 -32 -32v-1472c0 -17 15 -32 32 -32h1216c17 0 32 15 32 32z" />
+ <glyph glyph-name="check" unicode="&#xf00c;" horiz-adv-x="1550"
+d="M1550 970c0 -25 -10 -50 -28 -68l-724 -724l-136 -136c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-136 136l-362 362c-18 18 -28 43 -28 68s10 50 28 68l136 136c18 18 43 28 68 28s50 -10 68 -28l294 -295l656 657c18 18 43 28 68 28s50 -10 68 -28l136 -136
+c18 -18 28 -43 28 -68z" />
+ <glyph glyph-name="meetup" unicode="&#xf2e0;" horiz-adv-x="1847"
+d="M1297 302c-11 72 -143 16 -151 95c-11 112 153 354 140 448c-12 84 -68 102 -117 103c-47 1 -59 -7 -75 -16c-10 -6 -23 -17 -41 1c-22 21 -39 41 -68 45c-43 7 -62 -7 -93 -34c-12 -10 -42 -45 -70 -32c-12 6 -54 27 -84 40c-57 25 -140 -16 -170 -70
+c-45 -80 -133 -396 -146 -438c-30 -93 38 -170 129 -165c39 2 64 16 89 61c14 26 146 377 156 394c7 12 31 28 51 18c20 -11 24 -33 21 -53c-4 -34 -98 -248 -101 -272c-12 -80 94 -93 135 -14c13 25 160 324 173 344c15 22 26 29 41 28c11 0 29 -3 25 -38
+c-5 -33 -123 -253 -136 -307c-16 -72 23 -145 87 -177c40 -20 219 -55 205 39zM346 86c4 -20 -8 -39 -28 -43c-19 -4 -38 8 -42 28c-4 19 8 39 27 43s39 -8 43 -28zM916 -177c16 -23 10 -54 -12 -70c-23 -16 -54 -10 -70 13c-15 23 -9 54 13 70c23 16 54 10 69 -13zM140 635
+c-24 -36 -72 -45 -107 -20c-35 24 -44 73 -20 108c24 36 72 45 107 21c35 -25 44 -73 20 -109zM1430 -42c25 -37 16 -88 -21 -114c-37 -25 -87 -16 -112 21s-16 88 20 114c37 26 87 16 113 -21zM1542 562c92 -151 53 -350 -92 -452c-61 -43 -130 -62 -199 -60
+c-42 -165 -243 -226 -368 -114c-4 -3 -9 -6 -13 -10c-137 -95 -323 -61 -418 78c-34 50 -51 107 -53 164c-229 38 -315 329 -144 489c-99 164 2 376 187 402c88 232 377 342 573 190c236 78 477 -103 458 -354c144 -44 185 -234 69 -333zM418 1222c18 -27 12 -64 -15 -83
+c-26 -18 -63 -12 -81 15s-12 64 15 83c26 18 63 12 81 -15zM577 1503c5 -22 -9 -44 -31 -49s-44 9 -49 32c-4 22 10 44 32 49s44 -9 48 -32zM1763 555c6 -27 -11 -53 -37 -58c-26 -6 -52 11 -57 37c-6 27 11 53 37 59c26 5 52 -12 57 -38zM1099 1448c21 -36 10 -84 -27 -106
+c-36 -22 -83 -10 -104 26c-22 37 -10 85 26 107s83 10 105 -27zM1845 792c5 -20 -8 -39 -27 -44c-20 -4 -39 9 -43 28c-4 20 8 40 28 44c19 4 38 -8 42 -28zM1654 1033c20 -30 13 -71 -16 -92c-30 -20 -71 -13 -91 17s-13 71 17 92c29 21 70 13 90 -17z" />
+ <glyph glyph-name="sliders" unicode="&#xf1de;"
+d="M352 128v-128h-352v128h352zM704 256c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280c35 0 64 -29 64 -64v-256
+c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM1216 768c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
+ <glyph glyph-name="file-pdf-o" unicode="&#xf1c1;"
+d="M1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416
+h-768v-1536h1280zM894 465c25 -20 53 -38 84 -56c42 5 81 7 117 7c67 0 152 -8 177 -49c7 -10 13 -28 2 -52c-1 -1 -2 -3 -3 -4v-1c-3 -18 -18 -38 -71 -38c-64 0 -161 29 -245 73c-139 -15 -285 -46 -392 -83c-103 -176 -182 -262 -242 -262c-10 0 -19 2 -28 7l-24 12
+c-3 1 -4 3 -6 5c-5 5 -9 16 -6 36c10 46 64 123 188 188c8 5 18 2 23 -6c1 -1 2 -3 2 -4c31 51 67 116 107 197c45 90 80 178 104 262c-32 109 -42 221 -24 287c7 25 22 40 42 40h22c15 0 27 -5 35 -15c12 -14 15 -36 9 -68c-1 -3 -2 -6 -4 -8c1 -3 1 -5 1 -8v-30
+c-1 -63 -2 -123 -14 -192c35 -105 87 -190 146 -238zM318 54c30 14 73 57 137 158c-75 -58 -122 -124 -137 -158zM716 974c-10 -28 -10 -76 -2 -132c3 16 5 31 7 44c2 17 5 31 7 43c1 3 2 5 4 8c-1 1 -1 3 -2 5c-1 18 -7 29 -13 36c0 -2 -1 -3 -1 -4zM592 313
+c88 35 186 63 284 81c-10 8 -20 15 -29 23c-49 43 -93 103 -127 176c-19 -61 -47 -126 -83 -197c-15 -28 -30 -56 -45 -83zM1238 329c-5 5 -31 24 -140 24c49 -18 94 -28 124 -28c9 0 14 0 18 1c0 1 -1 2 -2 3z" />
+ <glyph glyph-name="android" unicode="&#xf17b;" horiz-adv-x="1408"
+d="M493 1053c22 0 39 18 39 39s-17 39 -39 39c-21 0 -38 -18 -38 -39s17 -39 38 -39zM915 1053c21 0 38 18 38 39s-17 39 -38 39c-22 0 -39 -18 -39 -39s17 -39 39 -39zM103 869c56 0 102 -46 102 -102v-430c0 -57 -45 -103 -102 -103s-103 46 -103 103v430
+c0 56 46 102 103 102zM1163 850v-666c0 -61 -49 -110 -109 -110h-75v-227c0 -57 -46 -103 -103 -103s-103 46 -103 103v227h-138v-227c0 -57 -46 -103 -103 -103c-56 0 -102 46 -102 103l-1 227h-74c-61 0 -110 49 -110 110v666h918zM931 1255c140 -72 235 -210 235 -369
+h-925c0 159 95 297 236 369l-71 131c-4 7 -2 16 5 20c7 3 16 1 20 -6l72 -132c61 27 129 42 201 42s140 -15 201 -42l72 132c4 7 13 9 20 6c7 -4 9 -13 5 -20zM1408 767v-430c0 -57 -46 -103 -103 -103c-56 0 -102 46 -102 103v430c0 57 46 102 102 102
+c57 0 103 -45 103 -102z" />
+ <glyph glyph-name="hubzilla" unicode="&#xf2eb;" horiz-adv-x="1587"
+d="M1349 1363c86 -43 165 -125 207 -213c16 -40 34 -78 30 -170c-3 -83 -8 -115 -34 -170c-68 -146 -203 -243 -356 -253l-83 -6l-29 -115c-24 -96 -27 -129 -27 -129c28 -29 91 -47 117 -115c36 -69 32 -168 -14 -225c-75 -93 -187 -121 -286 -70c-90 47 -136 164 -108 266
+c7 26 -2 34 -109 104l-116 77l-43 -35c-203 -162 -499 -19 -498 242c0 168 133 299 304 298c86 0 138 -20 202 -78l47 -42l104 53l105 51l-11 37c-16 55 -12 176 7 238c21 74 87 166 150 212c128 94 302 111 441 43v0zM580 413l233 -160s71 60 167 68l60 254
+s-185 59 -237 189l-217 -102s52 -128 -6 -248v-1z" />
+ <glyph glyph-name="stack-exchange" unicode="&#xf18d;" horiz-adv-x="1238"
+d="M1238 283v-66c0 -113 -88 -204 -196 -204h-57l-260 -269v269h-529c-108 0 -196 91 -196 204v66h1238zM1238 609v-255h-1238v255h1238zM1238 937v-255h-1238v255h1238zM1238 1077v-67h-1238v67c0 112 88 203 196 203h846c108 0 196 -91 196 -203z" />
+ <glyph glyph-name="twitch" unicode="&#xf1e8;" horiz-adv-x="1592"
+d="M796 1102v-434h-145v434h145zM1194 1102v-434h-145v434h145zM1194 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1592 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+ <glyph glyph-name="caret-right" unicode="&#xf0da;" horiz-adv-x="576"
+d="M576 640c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v896c0 35 29 64 64 64c17 0 33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="tree" unicode="&#xf1bb;" horiz-adv-x="1472"
+d="M1472 64c0 -35 -29 -64 -64 -64h-462c3 -64 11 -131 11 -196c0 -33 -27 -60 -61 -60h-320c-34 0 -61 27 -61 60c0 65 8 132 11 196h-462c-35 0 -64 29 -64 64c0 17 7 33 19 45l402 403h-229c-35 0 -64 29 -64 64c0 17 7 33 19 45l402 403h-197c-35 0 -64 29 -64 64
+c0 17 7 33 19 45l384 384c12 12 28 19 45 19s33 -7 45 -19l384 -384c12 -12 19 -28 19 -45c0 -35 -29 -64 -64 -64h-197l402 -403c12 -12 19 -28 19 -45c0 -35 -29 -64 -64 -64h-229l402 -403c12 -12 19 -28 19 -45z" />
+ <glyph glyph-name="friendica" unicode="&#xf2e6;" horiz-adv-x="1520"
+d="M0 1128c0 152 123 276 274 276h973c151 0 273 -124 273 -276v-980c0 -152 -122 -276 -273 -276h-973c-151 0 -274 124 -274 276v980zM1247 1343h-244v-368h-486v-310l485 3l1 -367h-486v-368h730c118 0 212 95 212 215v980c0 120 -94 215 -212 215z" />
+ <glyph glyph-name="gratipay" unicode="&#xf184;"
+d="M773 234l350 473c27 37 59 156 -43 223c-86 56 -168 13 -211 -37c-16 -18 -44 -40 -96 -40s-79 22 -95 40c-43 50 -125 93 -212 37c-101 -67 -69 -186 -42 -223zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="map-marker" unicode="&#xf041;" horiz-adv-x="1024"
+d="M768 896c0 141 -115 256 -256 256s-256 -115 -256 -256s115 -256 256 -256s256 115 256 256zM1024 896c0 -61 -7 -124 -33 -179l-364 -774c-21 -44 -67 -71 -115 -71s-94 27 -114 71l-365 774c-26 55 -33 118 -33 179c0 283 229 512 512 512s512 -229 512 -512z" />
+ <glyph glyph-name="globe-e" unicode="&#xf304;"
+d="M768 1404c204 0 399 -81 543 -225s225 -339 225 -543s-81 -399 -225 -543s-339 -225 -543 -225s-399 81 -543 225s-225 339 -225 543s81 399 225 543s339 225 543 225zM863 1165h-1h-6c-78 -1 -136 -19 -204 -29s-157 -10 -205 -29s-58 -39 -87 -58s-72 -30 -87 -58
+s0 -58 0 -87s-28 -73 0 -88s58 39 87 58s68 70 88 59s6 -8 0 -29s-54 -44 -56 -87s110 -78 73 -135c-37 -56 -202 50 -250 18s-19 -58 -29 -87s-40 -57 -29 -88s55 -37 87 -58s87 -59 88 -62s21 -106 29 -145c6 -34 3 -78 4 -120c44 -36 123 -82 176 -102
+c21 41 37 107 53 139c24 48 77 133 87 174s0 39 0 58s8 32 0 58s-40 58 -59 87s-37 69 -58 88s-49 19 -58 29s-4 9 -4 14s-5 8 5 15s36 9 58 0s39 -39 58 -58s27 -55 58 -58s58 39 87 58c29 20 74 35 107 -22c8 -16 43 -35 68 -35s22 42 30 58s24 37 48 41s28 -14 44 -30
+s30 -69 53 -69s22 43 30 59c15 34 6 65 57 116c19 19 50 29 57 57s-21 62 -29 86s-28 63 -28 88c0 21 27 25 63 44c-24 30 -67 73 -97 97c-22 1 -41 2 -55 4c-69 8 -176 29 -253 29zM1251 411c-32 1 -70 -43 -105 -60c-39 -19 -100 -32 -116 -59s0 -39 0 -58s-14 -44 0 -58
+s38 0 58 0s37 9 59 0c12 -5 23 -17 33 -29c40 34 96 98 125 142c-5 11 -10 21 -14 32c-10 29 5 74 -29 88c-4 2 -7 2 -11 2z" />
+ <glyph glyph-name="american-sign-language-interpreting" unicode="&#xf2a3;" horiz-adv-x="2303"
+d="M1032 576c-35 1 -68 21 -84 55c-22 45 -66 73 -116 73c-71 0 -128 -57 -128 -128c0 -34 12 -67 36 -89l10 -8c22 -20 51 -31 82 -31c50 0 94 28 116 73c16 34 49 54 84 55zM1600 704c0 34 -12 67 -36 89l-10 8c-22 20 -51 31 -82 31c-50 0 -94 -28 -116 -73
+c-16 -34 -49 -54 -84 -55c35 -1 68 -21 84 -55c22 -45 66 -73 116 -73c71 0 128 57 128 128zM1174 925c-23 -47 -81 -67 -128 -44c-42 21 -87 31 -134 31c-35 0 -68 -6 -99 -17c6 0 13 1 19 1c123 0 236 -72 289 -183c23 -48 2 -105 -46 -128c-12 -6 -25 -9 -39 -9
+c14 0 27 -3 39 -9c48 -23 69 -80 46 -128c-53 -111 -166 -183 -289 -183h-6c-15 2 -29 3 -44 4l-290 27l-239 -120c-10 -5 -19 -7 -29 -7c-23 0 -46 13 -57 35l-160 320c-15 31 -4 68 25 85l209 119l148 267c23 206 125 395 287 528c41 34 102 28 135 -13
+c34 -41 28 -101 -13 -135c-45 -38 -85 -81 -117 -128c78 53 168 89 267 101c53 7 101 -30 107 -83c7 -53 -30 -101 -83 -107c-58 -7 -112 -27 -159 -55c32 7 65 10 99 10c76 0 150 -17 218 -50c48 -24 68 -81 44 -129zM2137 1085l160 -320c15 -31 4 -68 -25 -85l-209 -119
+l-148 -267c-23 -206 -125 -395 -287 -528c-18 -15 -40 -22 -61 -22c-28 0 -55 12 -74 35c-34 41 -28 101 13 135c45 38 85 81 117 128c-78 -53 -168 -89 -267 -101c-4 -1 -8 -1 -12 -1c-48 0 -89 36 -95 84c-7 53 30 101 83 107c58 7 112 27 159 55c-32 -7 -65 -10 -99 -10
+c-76 0 -150 17 -218 50c-48 24 -68 81 -44 129c23 47 81 67 128 44c42 -21 87 -31 134 -31c35 0 68 6 99 17c-6 0 -13 -1 -19 -1c-123 0 -236 72 -289 183c-23 48 -2 105 46 128c12 6 25 9 39 9c-14 0 -27 3 -39 9c-48 23 -69 80 -46 128c53 111 166 183 289 183h7
+c14 -2 28 -3 42 -4l291 -27l239 120c10 5 19 7 29 7c23 0 46 -13 57 -35z" />
+ <glyph glyph-name="binoculars" unicode="&#xf1e5;" horiz-adv-x="1792"
+d="M704 1216v-768c0 -35 -29 -64 -64 -64v-576c0 -35 -29 -64 -64 -64h-512c-35 0 -64 29 -64 64v512l249 873c4 14 17 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512c0 -35 -29 -64 -64 -64h-512c-35 0 -64 29 -64 64v576c-35 0 -64 29 -64 64v768h424
+c14 0 27 -9 31 -23zM736 1504v-224h-352v224c0 18 14 32 32 32h288c18 0 32 -14 32 -32zM1408 1504v-224h-352v224c0 18 14 32 32 32h288c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="sticky-note" unicode="&#xf249;"
+d="M1024 288v-416h-928c-53 0 -96 43 -96 96v1344c0 53 43 96 96 96h1344c53 0 96 -43 96 -96v-928h-416c-53 0 -96 -43 -96 -96zM1152 256h381c-9 -48 -35 -102 -65 -132l-184 -184c-30 -30 -84 -56 -132 -65v381z" />
+ <glyph glyph-name="user" unicode="&#xf007;" horiz-adv-x="1280"
+d="M1280 137c0 -146 -96 -265 -213 -265h-854c-117 0 -213 119 -213 265c0 263 65 567 327 567c81 -79 191 -128 313 -128s232 49 313 128c262 0 327 -304 327 -567zM1024 1024c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384s384 -172 384 -384z" />
+ <glyph glyph-name="php" unicode="&#xf30e;" horiz-adv-x="2299"
+d="M1149 1245c635 0 1150 -271 1150 -605s-515 -605 -1150 -605s-1149 271 -1149 605s514 605 1149 605zM1049 1081l-130 -627h125l74 359l100 -1c32 0 52 -6 62 -18s12 -33 6 -62l-58 -278h126l61 291c13 65 4 109 -27 132c-30 23 -77 36 -138 37h-111l35 167h-125z
+M478 914v0l-129 -625h126l34 165h108c37 0 73 5 107 13s66 27 96 57c25 24 44 50 58 80s24 60 28 91c11 67 1 121 -31 160s-84 58 -155 59h-242zM1549 914l-130 -625h126l34 165h109c37 0 72 5 106 13s67 27 97 57c25 24 43 50 57 80s24 60 28 91c11 67 1 121 -31 160
+s-84 58 -155 59h-241zM623 815v0c48 1 88 -4 120 -13s43 -45 32 -106c-13 -73 -38 -115 -77 -127s-87 -18 -145 -17h-12c-3 0 -8 1 -11 1l54 261h18c7 0 14 0 21 1zM1693 815v0c48 1 88 -4 120 -13s44 -45 33 -106c-13 -73 -39 -115 -78 -127s-87 -18 -145 -17h-12
+c-3 0 -8 1 -11 1l54 261h18c7 0 14 0 21 1z" />
+ <glyph glyph-name="ioxhost" unicode="&#xf208;" horiz-adv-x="2048"
+d="M1463 704c0 -47 -38 -86 -86 -86h-702c-48 0 -86 39 -86 86s38 86 86 86h702c48 0 86 -39 86 -86zM1677 704c0 59 -8 115 -23 170h-982c-48 0 -86 38 -86 85c0 48 38 86 86 86h908c-115 187 -321 311 -555 311c-360 0 -653 -292 -653 -652c0 -59 8 -115 23 -170h982
+c48 0 86 -38 86 -85c0 -48 -38 -86 -86 -86h-908c115 -187 321 -311 556 -311c359 0 652 292 652 652zM2048 959c0 -47 -38 -85 -86 -85h-131c11 -55 17 -112 17 -170c0 -454 -369 -824 -823 -824c-333 0 -620 198 -750 483h-189c-48 0 -86 38 -86 86c0 47 38 85 86 85h132
+c-11 55 -17 112 -17 170c0 454 369 824 824 824c332 0 619 -198 749 -483h188c48 0 86 -38 86 -86z" />
+ <glyph glyph-name="expand" unicode="&#xf065;"
+d="M755 480c0 -8 -4 -17 -10 -23l-332 -332l144 -144c12 -12 19 -28 19 -45c0 -35 -29 -64 -64 -64h-448c-35 0 -64 29 -64 64v448c0 35 29 64 64 64c17 0 33 -7 45 -19l144 -144l332 332c6 6 15 10 23 10s17 -4 23 -10l114 -114c6 -6 10 -15 10 -23zM1536 1344v-448
+c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-144 144l-332 -332c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-114 114c-6 6 -10 15 -10 23s4 17 10 23l332 332l-144 144c-12 12 -19 28 -19 45c0 35 29 64 64 64h448c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="discord-alt" unicode="&#xf2ef;"
+d="M559 1212v0l13 -16c-237 -68 -346 -172 -346 -172s29 16 78 38c141 62 252 79 298 83c8 1 15 3 23 3c80 11 170 13 265 2c125 -14 259 -51 396 -126c0 0 -103 99 -327 167l18 21s181 4 370 -138c0 0 189 -343 189 -766c0 0 -111 -191 -402 -200c0 0 -48 56 -87 106
+c172 49 238 157 238 157c-54 -35 -105 -61 -151 -78c-66 -28 -129 -45 -191 -56c-126 -24 -242 -17 -341 1c-75 14 -139 36 -193 57c-30 12 -63 26 -96 44c-4 3 -8 4 -12 7c-3 1 -4 3 -5 4c-24 13 -37 22 -37 22s63 -105 230 -155c-39 -50 -88 -109 -88 -109
+c-291 9 -401 200 -401 200c0 423 189 766 189 766c189 142 370 138 370 138zM522 722v0c-75 0 -134 -66 -134 -146s60 -146 134 -146c75 0 134 66 134 146c1 80 -59 146 -134 146zM1002 722v0c-75 0 -134 -66 -134 -146s60 -146 134 -146c75 0 134 66 134 146
+s-59 146 -134 146z" />
+ <glyph glyph-name="bitbucket-square" unicode="&#xf172;"
+d="M848 666c0 57 -70 96 -118 67c-57 -27 -57 -119 1 -143c52 -31 125 16 117 76zM928 682c11 -88 -58 -174 -146 -182s-171 64 -175 153c-3 66 38 130 98 157c94 42 210 -26 223 -128zM1100 1073c-44 -45 -111 -51 -170 -58c-107 -14 -216 -13 -324 0
+c-59 8 -124 15 -170 58c28 40 78 48 123 55c135 24 273 23 408 1c48 -7 102 -15 133 -56zM1142 327c0 24 25 65 -9 75c-215 -142 -515 -142 -731 0l-12 -6l-5 -12c12 -70 23 -141 41 -210c41 -71 129 -95 204 -108c142 -26 299 -18 428 53c75 42 63 137 84 208zM1272 1020
+c4 24 9 53 -8 75c-38 48 -98 71 -155 88c-158 46 -325 52 -487 36c-77 -7 -154 -20 -226 -46c-54 -21 -127 -49 -136 -113c18 -150 47 -297 72 -446c8 -42 8 -92 46 -122c81 -62 184 -89 284 -100c148 -16 305 -5 440 63c38 20 82 46 90 92c28 157 55 314 80 473zM1536 1120
+v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="hand-paper-o" unicode="&#xf256;" horiz-adv-x="1632"
+d="M880 1408c-62 0 -112 -50 -112 -112v-656h-32v528c0 62 -50 112 -112 112s-112 -50 -112 -112v-784l-154 205c-24 32 -62 51 -102 51c-71 0 -128 -58 -128 -128c0 -28 9 -55 26 -77l384 -512c24 -32 62 -51 102 -51h688c46 0 86 33 95 78l76 405c3 19 5 39 5 59v498
+c0 62 -50 112 -112 112s-112 -50 -112 -112v-272h-32v528c0 62 -50 112 -112 112s-112 -50 -112 -112v-528h-32v656c0 62 -50 112 -112 112zM880 1536c90 0 173 -51 214 -132c14 3 28 4 42 4c132 0 240 -108 240 -240v-17c139 8 256 -99 256 -239v-498c0 -28 -3 -56 -8 -83
+l-76 -404c-19 -106 -112 -183 -220 -183h-688c-80 0 -157 39 -205 102l-384 512c-33 44 -51 99 -51 154c0 141 114 256 256 256c42 0 93 -10 128 -34v434c0 132 108 240 240 240c14 0 28 -1 42 -4c41 81 124 132 214 132z" />
+ <glyph glyph-name="database" unicode="&#xf1c0;"
+d="M768 768c301 0 603 54 768 170v-170c0 -141 -344 -256 -768 -256s-768 115 -768 256v170c165 -116 467 -170 768 -170zM768 0c301 0 603 54 768 170v-170c0 -141 -344 -256 -768 -256s-768 115 -768 256v170c165 -116 467 -170 768 -170zM768 384c301 0 603 54 768 170
+v-170c0 -141 -344 -256 -768 -256s-768 115 -768 256v170c165 -116 467 -170 768 -170zM768 1536c424 0 768 -115 768 -256v-128c0 -141 -344 -256 -768 -256s-768 115 -768 256v128c0 141 344 256 768 256z" />
+ <glyph glyph-name="jirafeau" unicode="&#xf318;"
+d="M1459 1408c43 0 77 -34 77 -77v-1382c0 -43 -34 -77 -77 -77h-923c18 109 27 134 50 210c31 103 92 108 92 108c49 11 74 31 224 -36s270 -72 270 -72v0c15 -19 71 -80 137 -85c90 -7 128 19 128 19s31 91 -38 176s-336 376 -343 403c0 0 -40 47 -69 58s-119 63 -135 130
+s-42 168 -33 215s22 152 -32 130s-31 -74 -40 -137s-52 -190 -112 -190c0 0 -87 150 -145 132s-108 -181 -63 -275c0 0 -210 -295 -393 -772c-20 14 -34 37 -34 63v1382c0 43 34 77 77 77h1382z" />
+ <glyph glyph-name="user-circle-o" unicode="&#xf2be;" horiz-adv-x="1792"
+d="M896 1536c495 0 896 -401 896 -896c0 -492 -399 -896 -896 -896c-496 0 -896 403 -896 896c0 495 401 896 896 896zM1515 185c93 128 149 285 149 455c0 423 -345 768 -768 768s-768 -345 -768 -768c0 -170 56 -327 149 -455c36 179 123 327 306 327
+c81 -79 191 -128 313 -128s232 49 313 128c183 0 270 -148 306 -327zM1280 832c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384s384 -172 384 -384z" />
+ <glyph glyph-name="hacker-news" unicode="&#xf1d4;"
+d="M809 532l266 499h-112l-157 -312s-24 -48 -44 -92c-19 46 -42 92 -42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="edge" unicode="&#xf282;" horiz-adv-x="1654"
+d="M0 741h1c52 414 335 796 841 795c307 0 560 -144 708 -409c76 -137 104 -283 104 -442v-188h-1125c5 -464 682 -448 974 -244v-377c-171 -103 -557 -192 -858 -77c-255 98 -433 363 -436 621c-4 333 165 554 436 680c-57 -72 -101 -150 -124 -285h635
+c37 379 -359 379 -359 379c-374 -13 -644 -231 -797 -453z" />
+ <glyph glyph-name="calendar-plus-o" unicode="&#xf271;" horiz-adv-x="1664"
+d="M1536 1280c70 0 128 -58 128 -128v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128zM1152 1376v-288
+c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32zM384 1376v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32zM1536 -128v1024h-1408v-1024h1408zM896 448h224
+c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-224v-224c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v224h-224c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v224c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-224z" />
+ <glyph glyph-name="hand-lizard-o" unicode="&#xf258;" horiz-adv-x="2048"
+d="M1151 1536c81 0 159 -39 207 -105l572 -781c77 -104 118 -229 118 -359v-355c0 -106 -86 -192 -192 -192h-384c-106 0 -192 86 -192 192v177l-286 143h-546c-106 0 -192 86 -192 192v32c0 159 129 288 288 288h420l42 128h-686c-133 0 -244 102 -255 234
+c-42 51 -65 116 -65 182v32c0 106 86 192 192 192h959zM1920 -64v355c0 101 -33 202 -93 284l-573 781c-24 32 -62 52 -103 52h-959c-35 0 -64 -29 -64 -64c0 -53 1 -90 36 -133c13 41 50 69 92 69h832v-32h-832c-35 0 -64 -29 -64 -64c0 -19 -1 -39 3 -58
+c11 -59 65 -102 125 -102h731c53 0 96 -43 96 -96c0 -10 -2 -21 -5 -30l-64 -192c-13 -39 -50 -66 -91 -66h-443c-88 0 -160 -72 -160 -160v-32c0 -35 29 -64 64 -64h561c10 0 20 -2 29 -7l317 -158c32 -17 53 -50 53 -86v-197c0 -35 29 -64 64 -64h384c35 0 64 29 64 64z
+" />
+ <glyph glyph-name="digitalocean" unicode="&#xf31d;" horiz-adv-x="1535"
+d="M245 169h-191v190h191v-190zM473 -59h-228v228h228v-228zM769 465v-296h-296v296h296zM768 -128v298c315 0 559 312 438 644c-44 123 -142 221 -265 265c-332 120 -644 -123 -644 -438h-297c0 502 485 894 1012 729c230 -72 414 -255 485 -485
+c165 -527 -226 -1013 -729 -1013z" />
+ <glyph glyph-name="xing" unicode="&#xf168;" horiz-adv-x="1408"
+d="M597 869c0 0 -10 -17 -257 -456c-13 -22 -30 -46 -65 -46h-239c-14 0 -25 7 -31 17s-7 23 0 36l253 448c1 0 1 0 0 1l-161 279c-7 13 -8 27 -1 37c6 10 18 15 32 15h239c36 0 54 -24 66 -45c163 -285 164 -286 164 -286zM1403 1511c7 -10 7 -24 0 -37l-528 -934
+c-1 0 -1 -1 0 -1l336 -615c7 -13 7 -27 1 -37c-7 -10 -18 -15 -32 -15h-239c-36 0 -55 24 -66 45c-339 621 -339 622 -339 622s17 30 531 942c13 23 28 45 64 45h241c14 0 25 -5 31 -15z" />
+ <glyph glyph-name="youtube-square" unicode="&#xf166;"
+d="M919 233v157c0 33 -10 50 -29 50c-11 0 -22 -5 -33 -16v-224c11 -11 22 -16 33 -16c19 0 29 16 29 49zM1103 355h66v34c0 34 -11 51 -33 51s-33 -17 -33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40c-26 -30 -51 -45 -76 -45
+c-21 0 -36 9 -42 28c-4 11 -6 28 -6 54v290h66v-270c0 -15 0 -24 1 -26c1 -10 6 -15 15 -15c14 0 27 10 42 31v280h67zM985 384v-146c0 -33 -2 -58 -7 -73c-8 -28 -26 -42 -53 -42c-23 0 -46 14 -68 41v-36h-67v493h67v-161c21 26 44 40 68 40c27 0 45 -14 53 -42
+c5 -15 7 -39 7 -74zM1236 255v-9c0 -22 -1 -36 -2 -43c-2 -15 -7 -28 -15 -40c-18 -27 -46 -40 -80 -40c-35 0 -62 13 -81 38c-14 18 -21 47 -21 86v129c0 39 6 67 20 86c19 25 46 38 80 38c33 0 60 -13 78 -38c14 -19 21 -47 21 -86v-76h-133v-65c0 -34 11 -51 34 -51
+c16 0 26 9 30 26c0 4 1 19 1 45h68zM785 1079v-156c0 -34 -11 -51 -32 -51c-22 0 -32 17 -32 51v156c0 34 10 52 32 52c21 0 32 -18 32 -52zM1318 366c0 86 0 177 -19 260c-14 59 -62 102 -119 108c-136 15 -274 15 -412 15c-137 0 -275 0 -411 -15
+c-58 -6 -106 -49 -119 -108c-19 -83 -20 -174 -20 -260c0 -85 0 -176 20 -260c13 -58 61 -101 118 -108c137 -15 275 -15 412 -15s275 0 412 15c57 7 105 50 118 108c20 84 20 175 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78c15 -46 32 -92 47 -138
+c24 -70 39 -122 46 -158v-201h74v201zM852 936v130c0 39 -7 68 -21 87c-19 25 -45 38 -78 38c-34 0 -60 -13 -78 -38c-14 -19 -21 -48 -21 -87v-130c0 -39 7 -68 21 -87c18 -25 44 -38 78 -38c33 0 59 13 78 38c14 18 21 48 21 87zM1033 816h67v370h-67v-283
+c-15 -21 -29 -31 -42 -31c-9 0 -15 5 -16 16c-1 2 -1 10 -1 26v272h-67v-293c0 -26 2 -43 6 -55c7 -18 22 -27 43 -27c25 0 50 15 77 45v-40zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960
+c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="taxi" unicode="&#xf1ba;" horiz-adv-x="2048"
+d="M1824 640c124 0 224 -100 224 -224v-384c0 -18 -14 -32 -32 -32h-96v-64c0 -106 -86 -192 -192 -192s-192 86 -192 192v64h-1024v-64c0 -106 -86 -192 -192 -192s-192 86 -192 192v64h-96c-18 0 -32 14 -32 32v384c0 124 100 224 224 224h28l105 419
+c31 126 153 221 283 221h128v224c0 18 14 32 32 32h448c18 0 32 -14 32 -32v-224h128c130 0 252 -95 283 -221l105 -419h28zM320 160c88 0 160 72 160 160s-72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160zM516 640h1016l-89 357c-3 11 -23 27 -35 27h-768
+c-12 0 -32 -16 -35 -27zM1728 160c88 0 160 72 160 160s-72 160 -160 160s-160 -72 -160 -160s72 -160 160 -160z" />
+ <glyph glyph-name="sort-desc" unicode="&#xf0dd;" horiz-adv-x="1024"
+d="M1024 448c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-448 448c-12 12 -19 28 -19 45c0 35 29 64 64 64h896c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="rocket" unicode="&#xf135;" horiz-adv-x="1632"
+d="M1408 1088c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM1632 1376c0 -332 -92 -553 -329 -791c-58 -57 -124 -116 -195 -176l-20 -379c-1 -10 -7 -20 -16 -26l-384 -224c-5 -3 -10 -4 -16 -4c-8 0 -16 3 -23 9l-64 64c-8 9 -11 21 -8 32l85 276
+l-281 281l-276 -85c-3 -1 -6 -1 -9 -1c-8 0 -17 3 -23 9l-64 64c-10 11 -12 27 -5 39l224 384c6 9 16 15 26 16l379 20c60 71 119 137 176 195c250 249 441 329 789 329c18 0 34 -14 34 -32z" />
+ <glyph glyph-name="discord" unicode="&#xf2ee;"
+d="M180 1516v0h1176c99 0 180 -81 180 -181v-1575l-189 167l-106 98l-112 105l46 -163h-995c-99 0 -180 81 -180 181v1187c0 100 81 181 180 181zM634 1107c0 0 -121 3 -247 -92c0 0 -126 -229 -126 -512c0 0 73 -128 267 -134c0 0 33 40 59 73c-111 33 -153 104 -153 104
+s8 -6 24 -15c1 -1 2 -2 4 -3c3 -2 5 -2 8 -4c22 -12 44 -22 64 -30c36 -14 79 -28 129 -38c66 -12 143 -17 227 -1c41 7 83 20 127 38c31 11 65 28 101 52c0 0 -44 -73 -159 -105c26 -33 58 -71 58 -71c194 6 269 134 269 134c0 283 -127 512 -127 512
+c-126 95 -246 92 -246 92l-12 -14c149 -46 218 -112 218 -112c-91 50 -181 75 -264 85c-63 7 -123 5 -177 -2c-5 0 -10 -1 -15 -2c-31 -3 -106 -14 -200 -55c-32 -15 -51 -26 -51 -26s72 69 230 115zM609 779c50 0 91 -43 90 -97c0 -54 -40 -98 -90 -98c-49 0 -89 44 -89 98
+s39 97 89 97zM930 779c50 0 89 -43 89 -97s-39 -98 -89 -98c-49 0 -90 44 -90 98s40 97 90 97z" />
+ <glyph glyph-name="money" unicode="&#xf0d6;" horiz-adv-x="1920"
+d="M768 384h384v96h-128v448h-114l-148 -137l77 -80c24 21 39 32 55 57h2v-288h-128v-96zM1280 640c0 -182 -110 -416 -320 -416s-320 234 -320 416s110 416 320 416s320 -234 320 -416zM1792 384v512c-141 0 -256 115 -256 256h-1152c0 -141 -115 -256 -256 -256v-512
+c141 0 256 -115 256 -256h1152c0 141 115 256 256 256zM1920 1216v-1152c0 -35 -29 -64 -64 -64h-1792c-35 0 -64 29 -64 64v1152c0 35 29 64 64 64h1792c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="laptop" unicode="&#xf109;" horiz-adv-x="1920"
+d="M416 256c-88 0 -160 72 -160 160v704c0 88 72 160 160 160h1088c88 0 160 -72 160 -160v-704c0 -88 -72 -160 -160 -160h-1088zM384 1120v-704c0 -17 15 -32 32 -32h1088c17 0 32 15 32 32v704c0 17 -15 32 -32 32h-1088c-17 0 -32 -15 -32 -32zM1760 192h160v-96
+c0 -53 -72 -96 -160 -96h-1600c-88 0 -160 43 -160 96v96h1760zM1040 96c9 0 16 7 16 16s-7 16 -16 16h-160c-9 0 -16 -7 -16 -16s7 -16 16 -16h160z" />
+ <glyph glyph-name="arrows-alt" unicode="&#xf0b2;"
+d="M1283 995l-355 -355l355 -355l144 144c18 19 46 24 70 14c23 -10 39 -33 39 -59v-448c0 -35 -29 -64 -64 -64h-448c-26 0 -49 16 -59 40c-10 23 -5 51 14 69l144 144l-355 355l-355 -355l144 -144c19 -18 24 -46 14 -69c-10 -24 -33 -40 -59 -40h-448
+c-35 0 -64 29 -64 64v448c0 26 16 49 40 59c23 10 51 5 69 -14l144 -144l355 355l-355 355l-144 -144c-12 -12 -28 -19 -45 -19c-8 0 -17 2 -24 5c-24 10 -40 33 -40 59v448c0 35 29 64 64 64h448c26 0 49 -16 59 -40c10 -23 5 -51 -14 -69l-144 -144l355 -355l355 355
+l-144 144c-19 18 -24 46 -14 69c10 24 33 40 59 40h448c35 0 64 -29 64 -64v-448c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 7 -45 19z" />
+ <glyph glyph-name="thermometer-empty" unicode="&#xf2cb;" horiz-adv-x="1024"
+d="M640 192c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 105 85 192 192 192s192 -88 192 -192zM768 192c0 105 -50 197 -128 256v768c0 106 -86 192 -192 192s-192 -86 -192 -192v-768c-78 -59 -128 -151 -128 -256c0 -177 143 -320 320 -320s320 143 320 320zM896 192
+c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 122 49 232 128 313v711c0 177 143 320 320 320s320 -143 320 -320v-711c79 -81 128 -191 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z" />
+ <glyph glyph-name="underline" unicode="&#xf0cd;"
+d="M48 1313c-18 1 -33 1 -45 4l-3 88c13 1 26 1 40 1c35 0 73 -1 112 -4c94 -5 150 -7 166 -7c57 0 113 1 168 3c54 2 103 4 146 5c42 0 71 1 86 2l-1 -14l2 -64v-9c-40 -6 -81 -9 -124 -9c-40 0 -66 -8 -79 -25c-9 -10 -13 -54 -13 -132c0 -24 1 -43 1 -58l1 -229l14 -280
+c4 -81 20 -148 51 -202c23 -39 55 -70 96 -92c60 -32 119 -47 177 -47c68 0 132 9 191 28c35 11 68 27 99 51c31 23 53 44 65 64c26 40 43 79 53 114c14 49 21 125 21 229c0 179 -13 184 -28 410l-4 59c-3 43 -10 73 -24 88c-22 23 -48 35 -77 34l-100 -2l-14 3l2 86h84
+l205 -10c68 -3 133 3 196 10l18 -2c4 -25 6 -42 6 -51s-2 -19 -4 -31c-27 -7 -55 -12 -84 -13c-47 -7 -74 -12 -79 -17c-9 -9 -15 -22 -15 -41c0 -13 2 -33 3 -58c0 0 8 -18 22 -396c5 -151 -5 -253 -15 -304s-24 -92 -41 -122c-26 -44 -64 -85 -112 -123
+c-49 -37 -109 -67 -182 -89s-158 -33 -255 -33c-110 0 -205 15 -284 46s-139 72 -179 122s-68 115 -83 195c-11 55 -16 134 -16 237v333c0 126 -6 197 -17 213c-16 23 -65 37 -147 39zM1536 -96c0 -18 -14 -32 -32 -32h-1472c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h1472
+c18 0 32 -14 32 -32v-64z" />
+ <glyph glyph-name="sun-o" unicode="&#xf185;" horiz-adv-x="1707"
+d="M1430 640c0 318 -258 576 -576 576s-576 -258 -576 -576s258 -576 576 -576s576 258 576 576zM1706 363c-3 -10 -11 -17 -20 -20l-292 -96v-306c0 -10 -5 -20 -13 -26c-9 -6 -19 -8 -29 -4l-292 94l-180 -248c-6 -8 -16 -13 -26 -13s-20 5 -26 13l-180 248l-292 -94
+c-10 -4 -20 -2 -29 4c-8 6 -13 16 -13 26v306l-292 96c-9 3 -17 10 -20 20s-2 21 4 29l180 248l-180 248c-6 9 -7 19 -4 29s11 17 20 20l292 96v306c0 10 5 20 13 26c9 6 19 8 29 4l292 -94l180 248c12 16 40 16 52 0l180 -248l292 94c10 4 20 2 29 -4c8 -6 13 -16 13 -26
+v-306l292 -96c9 -3 17 -10 20 -20s2 -20 -4 -29l-180 -248l180 -248c6 -8 7 -19 4 -29z" />
+ <glyph glyph-name="activitypub" unicode="&#xf2f2;" horiz-adv-x="2032"
+d="M924 1280v-1280l-185 107v853l-739 -427v214zM1109 1280l923 -533v-214l-923 -533v213l739 427l-739 427v213zM1109 853l369 -213l-369 -213v426zM554 640v-427l-369 214z" />
+ <glyph glyph-name="play-circle" unicode="&#xf144;"
+d="M768 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM1152 585c20 11 32 32 32 55s-12 44 -32 55l-544 320c-19 12 -44 12 -64 1c-20 -12 -32 -33 -32 -56v-640c0 -23 12 -44 32 -56c10 -5 21 -8 32 -8s22 3 32 9z" />
+ <glyph glyph-name="share-square-o" unicode="&#xf045;" horiz-adv-x="1664"
+d="M1408 547v-259c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h255c17 0 32 -14 32 -32c0 -16 -11 -29 -26 -32c-50 -17 -95 -37 -133 -60c-5 -2 -10 -4 -16 -4h-112c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832
+c88 0 160 72 160 160v214c0 12 7 23 18 29c20 9 38 22 54 37c9 9 23 13 35 8s21 -16 21 -29zM1645 1043l-384 -384c-12 -13 -28 -19 -45 -19c-8 0 -17 2 -25 5c-23 10 -39 33 -39 59v192h-160c-220 0 -360 -42 -438 -131c-81 -93 -105 -243 -74 -473c2 -14 -7 -28 -20 -34
+c-4 -1 -8 -2 -12 -2c-10 0 -20 5 -26 13c-7 10 -166 235 -166 435c0 268 84 576 736 576h160v192c0 26 16 49 39 59c8 3 17 5 25 5c17 0 33 -7 45 -19l384 -384c25 -25 25 -65 0 -90z" />
+ <glyph glyph-name="street-view" unicode="&#xf21d;" horiz-adv-x="1408"
+d="M1408 0c0 -176 -365 -256 -704 -256s-704 80 -704 256c0 136 203 200 373 229c35 6 68 -17 74 -52s-17 -68 -52 -74c-206 -36 -264 -92 -267 -104c10 -34 202 -127 576 -127s566 93 576 129c-3 10 -61 66 -267 102c-35 6 -58 39 -52 74s39 58 74 52
+c170 -29 373 -93 373 -229zM1024 896v-384c0 -35 -29 -64 -64 -64h-64v-384c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v384h-64c-35 0 -64 29 -64 64v384c0 71 57 128 128 128h384c71 0 128 -57 128 -128zM928 1280c0 -124 -100 -224 -224 -224s-224 100 -224 224
+s100 224 224 224s224 -100 224 -224z" />
+ <glyph glyph-name="arrow-circle-up" unicode="&#xf0aa;"
+d="M1284 641c0 17 -6 33 -18 45l-362 362l-91 91c-12 12 -28 18 -45 18s-33 -6 -45 -18l-91 -91l-362 -362c-12 -12 -18 -28 -18 -45s6 -33 18 -45l91 -91c12 -12 28 -18 45 -18s33 6 45 18l189 189v-502c0 -35 29 -64 64 -64h128c35 0 64 29 64 64v502l189 -189
+c12 -12 28 -19 45 -19s33 7 45 19l91 91c12 12 18 28 18 45zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="podcast" unicode="&#xf2ce;"
+d="M994 344c0 -66 -7 -132 -17 -197c-15 -104 -30 -211 -55 -313c-18 -73 -86 -90 -152 -90s-134 17 -152 90c-25 102 -40 209 -55 313c-10 65 -17 131 -17 197c0 135 109 168 224 168s224 -33 224 -168zM1536 768c0 -324 -200 -601 -484 -714c-11 -4 -23 6 -21 18
+c3 21 6 43 10 66c2 16 4 32 6 47c1 6 4 10 9 12c208 106 352 322 352 571c0 365 -306 659 -675 639c-338 -18 -607 -306 -605 -644c2 -249 147 -464 356 -568c5 -2 8 -7 9 -12c2 -14 4 -29 6 -45c4 -24 7 -46 11 -68c2 -12 -11 -22 -22 -17c-297 116 -504 412 -487 753
+c19 387 331 704 718 728c446 28 817 -326 817 -766zM994 800c0 -124 -100 -224 -224 -224s-224 100 -224 224s100 224 224 224s224 -100 224 -224zM1282 768c0 -165 -79 -313 -200 -406c-10 -8 -24 -1 -26 12c-3 28 -11 61 -29 92c-4 6 -3 14 3 20c76 70 124 170 124 282
+c0 226 -197 407 -428 382c-177 -20 -321 -166 -338 -344c-13 -126 37 -242 122 -320c6 -6 7 -14 3 -20c-18 -31 -26 -64 -29 -93c-2 -12 -16 -19 -26 -11c-124 96 -203 247 -200 417c6 266 222 488 487 500c294 14 537 -220 537 -511z" />
+ <glyph glyph-name="hackster" unicode="&#xf326;"
+d="M768 -128c-424 0 -768 344 -768 768s344 768 768 768s768 -344 768 -768s-344 -768 -768 -768zM517 887c-10 -3 -17 -13 -17 -23s8 -18 18 -18h113c17 0 31 14 31 31v9c0 3 0 5 -1 8c-4 16 -22 26 -38 22zM661 739v59v5c-2 9 -12 13 -21 11l-325 -88c-5 -1 -9 -7 -9 -12
+s4 -9 9 -9h151c17 0 31 -14 31 -31v-86c0 -9 8 -17 17 -17h324c17 0 31 -13 31 -30v-59v-5c2 -9 12 -13 21 -11l325 88c5 1 9 7 9 12s-4 9 -9 9h-152c-17 0 -30 14 -30 31v85c0 9 -8 17 -17 17h-324c-17 0 -31 14 -31 31v0zM891 989c-13 -4 -23 -16 -23 -30v-176
+c0 -17 14 -31 31 -31h101c17 0 30 14 30 31v203v0c0 2 0 6 -1 8c-4 16 -21 26 -37 22zM1013 386c10 3 17 13 17 23s-8 19 -18 19h-113c-17 0 -31 -14 -31 -31v-9c0 -3 0 -5 1 -8c4 -16 22 -26 38 -22zM639 285c13 4 23 16 23 30v176c0 17 -14 30 -31 30h-101
+c-17 0 -30 -13 -30 -30v-204c0 -3 0 -5 1 -8c4 -16 21 -25 37 -21z" />
+ <glyph glyph-name="plus-square" unicode="&#xf0fe;"
+d="M1280 576v128c0 35 -29 64 -64 64h-320v320c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-320h-320c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h320v-320c0 -35 29 -64 64 -64h128c35 0 64 29 64 64v320h320c35 0 64 29 64 64zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="desktop" unicode="&#xf108;" horiz-adv-x="1920"
+d="M1792 544v832c0 17 -15 32 -32 32h-1600c-17 0 -32 -15 -32 -32v-832c0 -17 15 -32 32 -32h1600c17 0 32 15 32 32zM1920 1376v-1088c0 -88 -72 -160 -160 -160h-544c0 -85 64 -157 64 -192s-29 -64 -64 -64h-512c-35 0 -64 29 -64 64c0 37 64 105 64 192h-544
+c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1600c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="expeditedssl" unicode="&#xf23e;" horiz-adv-x="1792"
+d="M896 1472c-459 0 -832 -373 -832 -832s373 -832 832 -832s832 373 832 832s-373 832 -832 832zM896 1536c495 0 896 -401 896 -896s-401 -896 -896 -896s-896 401 -896 896s401 896 896 896zM496 704c9 0 16 -7 16 -16v-480c0 -9 -7 -16 -16 -16h-32c-9 0 -16 7 -16 16
+v480c0 9 7 16 16 16h32zM896 640c71 0 128 -57 128 -128c0 -47 -26 -88 -64 -110v-114c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v114c-38 22 -64 63 -64 110c0 71 57 128 128 128zM896 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768
+s344 768 768 768zM544 928v-96c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v96c0 124 100 224 224 224s224 -100 224 -224v-96c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v96c0 194 -158 352 -352 352s-352 -158 -352 -352zM1408 192v512c0 35 -29 64 -64 64h-896
+c-35 0 -64 -29 -64 -64v-512c0 -35 29 -64 64 -64h896c35 0 64 29 64 64z" />
+ <glyph glyph-name="toggle-on" unicode="&#xf205;" horiz-adv-x="2048"
+d="M0 640c0 353 287 640 640 640h768c353 0 640 -287 640 -640s-287 -640 -640 -640h-768c-353 0 -640 287 -640 640zM1408 128c282 0 512 230 512 512s-230 512 -512 512s-512 -230 -512 -512s230 -512 512 -512z" />
+ <glyph glyph-name="minus-square" unicode="&#xf146;"
+d="M1280 576v128c0 35 -29 64 -64 64h-896c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h896c35 0 64 29 64 64zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="adn" unicode="&#xf170;"
+d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="whatsapp" unicode="&#xf232;"
+d="M985 562c17 0 180 -85 187 -97c2 -5 2 -11 2 -15c0 -25 -8 -53 -17 -76c-23 -56 -116 -92 -173 -92c-48 0 -147 42 -190 62c-143 65 -232 176 -318 303c-38 56 -72 125 -71 194v8c2 66 26 113 74 158c15 14 31 22 52 22c12 0 24 -3 37 -3c27 0 32 -8 42 -34
+c7 -17 58 -153 58 -163c0 -38 -69 -81 -69 -104c0 -5 2 -10 5 -15c22 -47 64 -101 102 -137c46 -44 95 -73 151 -101c7 -4 14 -7 22 -7c30 0 80 97 106 97zM782 32c346 0 628 282 628 628s-282 628 -628 628s-628 -282 -628 -628c0 -132 42 -261 120 -368l-79 -233l242 77
+c102 -67 223 -104 345 -104zM782 1414c416 0 754 -338 754 -754s-338 -754 -754 -754c-127 0 -253 32 -365 94l-417 -134l136 405c-71 117 -108 252 -108 389c0 416 338 754 754 754z" />
+ <glyph glyph-name="puzzle-piece" unicode="&#xf12e;" horiz-adv-x="1664"
+d="M1664 438c0 -103 -59 -189 -168 -189c-122 0 -154 111 -264 111c-80 0 -110 -50 -110 -124c0 -78 32 -153 31 -230v-5c-11 0 -22 0 -33 -1c-103 -10 -207 -30 -311 -30c-71 0 -145 28 -145 110c0 110 111 142 111 264c0 109 -86 168 -189 168c-105 0 -202 -58 -202 -173
+c0 -127 97 -182 97 -251c0 -35 -22 -66 -46 -89c-31 -29 -75 -35 -117 -35c-82 0 -164 11 -245 24c-18 3 -37 5 -55 8l-13 2c-2 1 -5 1 -5 2v1024c4 -3 63 -10 73 -12c81 -13 163 -24 245 -24c42 0 86 6 117 35c24 23 46 54 46 89c0 69 -97 124 -97 251
+c0 115 97 173 203 173c102 0 188 -59 188 -168c0 -122 -111 -154 -111 -264c0 -82 74 -110 145 -110c115 0 229 26 343 32v-2c-3 -4 -10 -63 -12 -73c-13 -81 -24 -163 -24 -245c0 -42 6 -86 35 -117c23 -24 54 -46 89 -46c69 0 124 97 251 97c115 0 173 -97 173 -202z" />
+ <glyph glyph-name="css3" unicode="&#xf13c;" horiz-adv-x="1768"
+d="M263 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+ <glyph glyph-name="skyatlas" unicode="&#xf216;" horiz-adv-x="2048"
+d="M1430 953c0 0 -1 1 0 0zM1690 749c194 0 358 -145 358 -343c0 -211 -168 -366 -376 -366c-531 0 -629 799 -1151 799c-202 0 -349 -129 -349 -336c0 -214 160 -343 367 -343c136 0 291 57 401 136c18 13 54 52 73 52s35 -16 35 -35c0 -25 -42 -61 -60 -77
+c-131 -114 -321 -196 -495 -196c-267 0 -493 189 -493 464s216 477 489 477c593 0 712 -787 1158 -787c134 0 235 87 235 224c0 127 -98 223 -224 223c-56 0 -112 -37 -150 -37c-27 0 -51 23 -51 50c0 37 17 76 17 116c0 213 -163 367 -374 367c-170 0 -256 -118 -284 -118
+c-20 0 -36 16 -36 36c0 18 13 33 25 46c81 92 207 140 329 140c254 0 445 -187 445 -441c0 -22 -1 -44 -4 -66c38 10 77 15 115 15z" />
+ <glyph glyph-name="level-down" unicode="&#xf149;" horiz-adv-x="1024"
+d="M32 1280h704c18 0 32 -15 32 -33v-863h192c25 0 47 -15 58 -37c11 -23 7 -50 -9 -69l-320 -384c-24 -29 -74 -29 -98 0l-320 384c-16 19 -19 46 -9 69c11 22 33 37 58 37h192v640h-320c-9 0 -18 4 -25 11l-160 192c-8 9 -9 23 -4 34s17 19 29 19z" />
+ <glyph glyph-name="stack-overflow" unicode="&#xf16c;" horiz-adv-x="1514"
+d="M1278 -96v480h160v-640h-1438v640h160v-480h1118zM336 428l33 157l783 -165l-33 -156zM439 802l67 146l725 -339l-67 -145zM640 1158l102 123l614 -513l-102 -123zM1037 1536l477 -641l-128 -96l-477 641zM319 65v159h800v-159h-800z" />
+ <glyph glyph-name="check-square-o" unicode="&#xf046;" horiz-adv-x="1663"
+d="M1408 606v-318c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832c40 0 80 -8 117 -25c9 -4 16 -13 18 -23c2 -11 -1 -21 -9 -29l-49 -49c-6 -6 -15 -10 -23 -10c-3 0 -6 1 -9 2c-15 4 -30 6 -45 6h-832
+c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160v254c0 8 3 16 9 22l64 64c7 7 15 10 23 10c4 0 8 -1 12 -3c12 -5 20 -16 20 -29zM1639 1095l-814 -814c-32 -32 -82 -32 -114 0l-430 430c-32 32 -32 82 0 114l110 110c32 32 82 32 114 0
+l263 -263l647 647c32 32 82 32 114 0l110 -110c32 -32 32 -82 0 -114z" />
+ <glyph glyph-name="emby" unicode="&#xf319;" horiz-adv-x="1534"
+d="M474 224l-62 -62l-412 415l356 356l-60 61l414 414l355 -355l58 57l411 -414l-352 -352l58 -58l-414 -414zM1091 633l-496 291v-578z" />
+ <glyph glyph-name="hand-spock-o" unicode="&#xf259;" horiz-adv-x="1920"
+d="M459 -256c-103 0 -192 70 -217 170l-101 401c-8 35 -13 72 -13 108c0 23 0 45 -5 67l-116 477c-5 19 -7 38 -7 57c0 124 94 226 217 239c22 113 119 193 235 193c111 0 207 -76 233 -184l83 -348l103 428c26 108 122 184 233 184c119 0 217 -86 236 -202
+c123 -14 212 -118 212 -241c0 -19 -3 -39 -7 -59l-123 -512c80 60 138 118 243 118c139 0 255 -113 255 -253c0 -84 -41 -162 -107 -212l-507 -380c-44 -33 -98 -51 -153 -51h-694zM1104 1408c-51 0 -96 -36 -108 -86l-164 -682h-127l-145 602c-12 50 -57 86 -108 86
+c-64 0 -112 -51 -112 -113c0 -10 1 -19 3 -28l132 -547h-26l-99 408c-12 49 -57 88 -109 88c-62 0 -113 -50 -113 -112c0 -9 1 -18 3 -26l116 -478c14 -58 4 -116 19 -174l100 -401c11 -43 49 -73 93 -73h694c27 0 54 9 76 26l507 379c34 26 56 67 56 110
+c0 70 -58 125 -127 125c-28 0 -55 -9 -77 -26l-307 -230v227c0 8 129 538 139 581c2 9 4 19 4 29c0 62 -47 115 -111 115c-52 0 -97 -36 -109 -86l-116 -482h-26l150 624c2 9 3 19 3 28c0 63 -46 116 -111 116z" />
+ <glyph glyph-name="scuttlebutt" unicode="&#xf2ea;" horiz-adv-x="1709"
+d="M760 -126c-31 4 -114 28 -131 38c-5 3 -12 10 -16 16l-8 10l-7 -5c-14 -9 -14 -9 -151 60c-70 36 -134 68 -141 71c-21 10 -30 25 -45 74c-5 17 -6 19 -12 21c-18 7 -84 50 -121 78c-27 21 -66 60 -70 70c-10 25 -31 91 -37 112c-18 60 -21 88 -21 178c0 60 0 68 4 76
+c5 11 24 29 46 43c29 19 128 68 192 96l8 4l-4 8c-3 5 -16 24 -29 42l-24 33h-10c-21 1 -28 3 -48 16s-21 13 -39 41c-56 87 -91 163 -95 205c-4 46 23 129 52 160c9 9 17 16 28 22c16 8 17 8 40 8c19 0 25 -1 35 -5c27 -11 44 -29 49 -50c2 -11 2 -17 -1 -43
+c-9 -68 -1 -127 21 -163c4 -6 16 -19 28 -29c19 -17 38 -37 38 -43c0 -7 4 -1 11 15c9 23 70 138 78 148l5 8l-2 25c-8 86 -8 113 0 139c5 18 16 33 31 39c26 12 96 16 121 8c15 -5 28 -14 35 -26c5 -7 6 -12 7 -27l1 -18l52 8c71 11 95 16 116 24c26 10 38 13 57 13
+c29 0 45 -6 104 -37c137 -72 176 -97 219 -139c24 -23 28 -31 49 -73c17 -34 19 -37 38 -57l20 -21l23 6c28 8 37 8 49 2c10 -5 22 -21 22 -29c0 -2 4 -9 9 -16c7 -10 24 -34 39 -58c0 0 6 1 12 3c13 5 27 6 38 1c4 -2 17 -10 28 -19c11 -8 20 -15 21 -15s12 -7 25 -15
+c13 -9 27 -17 32 -18s14 -6 20 -9c13 -8 27 -10 64 -13c15 -1 31 -4 35 -5c18 -5 46 -31 55 -51c8 -18 5 -43 -9 -65c-4 -6 -18 -21 -30 -33s-23 -23 -24 -26s1 -24 4 -47c8 -67 4 -101 -13 -127c-8 -12 -29 -26 -59 -40c-13 -6 -24 -13 -27 -15s-8 -14 -12 -26
+c-9 -26 -17 -44 -26 -54c-8 -10 -10 -18 -13 -57c-4 -53 -10 -71 -37 -99c-20 -21 -37 -29 -70 -39c-11 -3 -49 -16 -85 -28c-35 -12 -66 -22 -68 -22s-6 -5 -9 -11c-14 -25 -33 -48 -63 -75c-48 -43 -116 -83 -163 -97c-9 -3 -16 -7 -24 -14c-43 -38 -88 -56 -154 -62
+c-28 -2 -42 -3 -63 0zM820 -67c13 1 31 5 41 7c18 4 49 17 49 20c0 1 -9 6 -20 12s-37 22 -56 36c-70 48 -117 94 -124 121c-9 35 -9 157 1 321c2 29 3 52 2 53c-3 3 -131 99 -131 99c-2 -2 -20 -148 -25 -210c-5 -54 -7 -145 -4 -170c3 -21 10 -46 32 -105
+c24 -66 44 -109 63 -139l9 -14l26 -8c44 -15 83 -25 104 -25c5 0 20 1 33 2zM559 26c-15 35 -29 69 -47 122c-14 40 -15 45 -17 70c-6 75 4 212 26 365c4 29 7 55 7 57c0 3 -11 12 -33 28c-30 22 -50 32 -58 32c-5 0 -83 -100 -120 -153c-34 -49 -63 -103 -68 -122
+c-2 -10 42 -188 64 -258c16 -52 -1 -38 137 -108l120 -60s-5 12 -11 27zM988 8c27 8 80 38 113 63c21 16 45 38 44 39c-1 0 -24 -2 -51 -6c-28 -4 -58 -7 -68 -7c-45 0 -82 18 -99 48c-8 14 -22 51 -31 82c-7 24 -8 30 -9 64c-1 30 -3 43 -7 59c-6 22 -18 48 -26 55
+c-9 8 -48 36 -57 40c-5 2 -13 7 -18 10l-9 6l-1 -10c-4 -31 -7 -124 -7 -206c0 -107 -2 -99 22 -123c49 -49 155 -116 185 -117c4 0 13 1 19 3zM1086 191c27 4 59 9 71 11c31 6 92 24 138 41c22 8 49 17 61 20c39 11 51 21 55 44c1 8 2 8 -3 7c-48 -15 -87 -22 -143 -24
+c-94 -4 -148 8 -226 46c-23 12 -57 33 -74 47c-5 4 -9 7 -9 7s3 -13 6 -27c5 -20 7 -33 8 -62c2 -39 6 -57 22 -97c6 -14 7 -16 13 -18c12 -4 31 -2 81 5zM232 241c-1 2 -10 37 -20 78s-19 77 -20 79c-4 8 -3 30 3 48c18 54 75 143 164 253c11 13 19 25 19 26
+c0 3 -40 24 -53 27c-7 2 -20 6 -27 9c-13 5 -14 5 -22 1c-4 -2 -28 -13 -53 -24c-76 -34 -138 -68 -159 -84l-7 -5l1 -71c1 -78 3 -88 17 -138c6 -20 26 -79 36 -106c3 -8 33 -36 58 -55c20 -15 62 -42 64 -42c0 0 0 2 -1 4v0zM1306 380c32 4 65 11 87 20c16 7 40 20 47 27
+c5 5 12 18 11 20l-24 -2c-44 -4 -92 -5 -118 -2c-32 3 -55 10 -86 26c-59 29 -105 72 -127 117c-11 23 -13 31 -13 52c0 63 43 117 183 229c22 17 40 32 41 33c0 1 -7 14 -17 29l-18 28l-11 2c-11 2 -13 2 -44 -8c-41 -14 -52 -16 -104 -22c-23 -2 -48 -7 -55 -9
+c-17 -5 -40 -21 -57 -39c-19 -20 -75 -92 -90 -116c-19 -29 -19 -33 -11 -52c4 -9 13 -27 20 -41s16 -33 20 -43c6 -16 9 -25 23 -88c7 -34 14 -49 32 -69c31 -33 75 -60 131 -80c49 -17 105 -20 180 -12zM889 488c0 0 -1 6 -3 12s-6 26 -10 44c-8 41 -14 58 -29 86
+c-16 31 -34 71 -37 83c-3 14 1 37 9 58c10 24 35 62 74 111c54 68 87 98 126 115c19 8 40 13 80 17c18 2 35 4 38 5c5 1 5 1 -2 9c-11 13 -23 33 -36 62c-10 22 -16 31 -26 42c-29 31 -63 54 -150 100c-35 18 -68 36 -73 39c-14 9 -36 17 -46 17c-5 0 -19 -4 -31 -9
+c-25 -10 -61 -17 -144 -30c-29 -5 -53 -9 -54 -9c-3 -3 -2 -38 1 -62c7 -50 24 -108 42 -142c9 -18 10 -29 4 -39c-5 -8 -27 -28 -34 -31c-9 -4 -12 -25 -11 -72c0 -33 0 -38 6 -57c9 -29 14 -67 13 -106l-1 -32l86 -65c112 -84 134 -100 153 -111c9 -5 24 -15 34 -22
+c16 -12 21 -15 21 -13zM1392 530c61 4 104 12 148 30l26 11v13c1 12 -2 47 -4 49c0 1 -6 -1 -10 -3c-22 -12 -53 -16 -74 -9c-34 12 -72 52 -86 90c-5 13 -5 18 -4 34s1 21 7 34c8 18 25 39 39 51c6 5 11 9 11 10s-3 3 -7 4c-4 2 -14 8 -22 14l-14 11l-19 -16
+c-10 -9 -37 -32 -61 -51c-70 -55 -85 -67 -114 -98c-24 -24 -29 -32 -36 -46c-7 -13 -6 -18 -4 -28c10 -26 42 -57 80 -77c44 -24 66 -28 144 -23zM1533 717c27 16 74 54 62 49c-2 -1 -9 -2 -16 -3c-15 -1 -28 5 -38 17c-6 8 -8 8 -15 6c-18 -5 -43 -23 -51 -36
+c-4 -7 -5 -9 -2 -15c1 -4 8 -12 14 -19c11 -11 12 -12 20 -11c5 1 17 6 26 12zM525 805c-4 36 -5 39 -38 113c-9 21 -11 22 -17 22c-8 0 -16 4 -23 11c-3 3 -13 28 -23 55c-13 36 -18 48 -19 46c-4 -5 -29 -57 -35 -72c-10 -27 -13 -43 -19 -90c-4 -25 -7 -48 -7 -50
+c0 -3 5 -4 15 -7c8 -2 18 -7 23 -10s14 -7 20 -11s16 -10 21 -13s24 -10 41 -16c23 -8 35 -14 47 -22l16 -11v11c0 6 0 26 -2 44zM210 969c12 6 27 21 27 26c0 1 -11 11 -24 23c-40 34 -56 64 -67 125c-5 27 -5 80 0 114c4 24 4 25 0 27c-14 9 -30 11 -43 4
+c-9 -4 -10 -7 -21 -30c-22 -47 -28 -86 -19 -114c10 -32 40 -90 75 -146c26 -41 40 -47 72 -29zM519 1007c20 5 27 8 36 14c2 2 2 6 -4 22c-12 30 -23 69 -29 103c-7 36 -7 79 -3 124c3 27 2 70 -1 73c-5 5 -72 -1 -79 -7c-4 -4 -6 -29 -3 -62c-2 -41 16 -99 14 -134
+c-2 -25 0 -32 22 -93c14 -39 16 -45 20 -45c2 0 15 2 27 5z" />
+ <glyph glyph-name="social-home" unicode="&#xf2ec;" horiz-adv-x="1486"
+d="M491 894h482v-621h-482v621v0zM1050 538h341v-666h-341v666zM91 273v0v620h318v-620h-318zM975 -128h-882v326h882v-326v0zM1053 894h340v-279h-340v279zM1452 1109v0c20 -5 34 -22 34 -44c0 -26 -93 -93 -93 -93h-1300s-87 62 -92 83s5 42 25 51l624 292
+c16 9 99 9 112 0z" />
+ <glyph glyph-name="leanpub" unicode="&#xf212;" horiz-adv-x="2048"
+d="M1893 1144l155 -1272c-93 0 -173 19 -257 57c-125 57 -255 91 -393 91c-142 0 -273 -47 -374 -148c-101 101 -232 148 -374 148c-138 0 -268 -34 -393 -91c-81 -36 -163 -57 -252 -57h-5l155 1272c143 81 317 127 482 127c135 0 274 -28 387 -106c113 78 252 106 387 106
+c165 0 339 -46 482 -127zM1398 157c190 0 320 -51 492 -122l-124 1021c-112 51 -245 78 -368 78c-140 0 -271 -44 -374 -141c-103 97 -234 141 -374 141c-123 0 -256 -27 -368 -78l-124 -1021c172 71 302 122 492 122c137 0 258 -35 374 -108c116 73 237 108 374 108z
+M1438 191l-40 1c-132 3 -261 -32 -374 -102c-113 70 -242 102 -374 102c-166 0 -299 -39 -450 -101l114 941c104 43 224 66 336 66c150 0 269 -48 374 -155c101 103 215 152 359 155z" />
+ <glyph glyph-name="arrow-circle-left" unicode="&#xf0a8;"
+d="M1280 576v128c0 35 -29 64 -64 64h-502l189 189c12 12 19 28 19 45s-7 33 -19 45l-91 91c-12 12 -28 18 -45 18s-33 -6 -45 -18l-362 -362l-91 -91c-12 -12 -18 -28 -18 -45s6 -33 18 -45l91 -91l362 -362c12 -12 28 -18 45 -18s33 6 45 18l91 91c12 12 18 28 18 45
+s-6 33 -18 45l-189 189h502c35 0 64 29 64 64zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="exclamation-triangle" unicode="&#xf071;" horiz-adv-x="1792"
+d="M1024 161v190c0 18 -14 33 -32 33h-192c-18 0 -32 -15 -32 -33v-190c0 -18 14 -33 32 -33h192c18 0 32 15 32 33zM1022 535l18 459c0 6 -3 14 -10 19c-6 5 -15 11 -24 11h-220c-9 0 -18 -6 -24 -11c-7 -5 -10 -15 -10 -21l17 -457c0 -13 15 -23 34 -23h185
+c18 0 33 10 34 23zM1008 1469l768 -1408c22 -39 21 -87 -2 -126s-65 -63 -110 -63h-1536c-45 0 -87 24 -110 63s-24 87 -2 126l768 1408c22 41 65 67 112 67s90 -26 112 -67z" />
+ <glyph glyph-name="gift" unicode="&#xf06b;"
+d="M928 180v716h-320v-716c0 -35 29 -52 64 -52h192c35 0 64 17 64 52zM472 1024h195l-126 161c-11 13 -35 31 -69 31c-53 0 -96 -43 -96 -96s43 -96 96 -96zM1160 1120c0 53 -43 96 -96 96c-34 0 -58 -18 -69 -31l-125 -161h194c53 0 96 43 96 96zM1536 864v-320
+c0 -18 -14 -32 -32 -32h-96v-416c0 -53 -43 -96 -96 -96h-1088c-53 0 -96 43 -96 96v416h-96c-18 0 -32 14 -32 32v320c0 18 14 32 32 32h440c-124 0 -224 100 -224 224s100 224 224 224c67 0 129 -28 168 -77l128 -165l128 165c39 49 101 77 168 77
+c124 0 224 -100 224 -224s-100 -224 -224 -224h440c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="cogs" unicode="&#xf085;" horiz-adv-x="1920"
+d="M896 640c0 141 -115 256 -256 256s-256 -115 -256 -256s115 -256 256 -256s256 115 256 256zM1664 128c0 70 -58 128 -128 128s-128 -58 -128 -128c0 -71 58 -128 128 -128c71 0 128 58 128 128zM1664 1152c0 70 -58 128 -128 128s-128 -58 -128 -128
+c0 -71 58 -128 128 -128c71 0 128 58 128 128zM1280 731v-185c0 -13 -10 -28 -23 -30l-155 -24c-8 -26 -19 -51 -32 -76c28 -40 58 -77 90 -115c4 -6 7 -12 7 -20c0 -7 -2 -14 -7 -19c-20 -27 -132 -149 -161 -149c-8 0 -15 3 -21 7l-115 90c-25 -13 -50 -23 -77 -31
+c-5 -51 -10 -106 -23 -155c-4 -14 -16 -24 -30 -24h-186c-14 0 -28 11 -30 25l-23 153c-26 8 -51 19 -75 31l-118 -89c-5 -5 -13 -7 -20 -7c-8 0 -15 3 -21 8c-26 24 -144 131 -144 160c0 7 3 13 7 19c29 38 59 75 88 114c-14 27 -26 54 -35 82l-152 24c-14 2 -24 15 -24 29
+v185c0 13 10 28 23 30l155 24c8 26 19 51 32 76c-28 40 -58 77 -90 115c-4 6 -7 13 -7 20s2 14 7 20c20 27 132 148 161 148c8 0 15 -3 21 -7l115 -90c25 13 50 23 77 32c5 50 10 105 23 154c4 14 16 24 30 24h186c14 0 28 -11 30 -25l23 -153c26 -8 51 -19 75 -31l118 89
+c6 5 13 7 20 7c8 0 15 -3 21 -8c26 -24 144 -132 144 -160c0 -7 -3 -13 -7 -19c-29 -39 -59 -75 -87 -114c13 -27 25 -54 34 -82l152 -23c14 -3 24 -16 24 -30zM1920 198v-140c0 -15 -129 -29 -149 -31c-8 -19 -18 -36 -30 -52c9 -20 51 -120 51 -138c0 -3 -1 -5 -4 -7
+c-12 -7 -119 -71 -124 -71c-13 0 -88 100 -98 115c-10 -1 -20 -2 -30 -2s-20 1 -30 2c-10 -15 -85 -115 -98 -115c-5 0 -112 64 -124 71c-3 2 -4 5 -4 7c0 17 42 118 51 138c-12 16 -22 33 -30 52c-20 2 -149 16 -149 31v140c0 15 129 29 149 31c8 18 18 36 30 52
+c-9 20 -51 121 -51 138c0 2 1 5 4 7c12 6 119 70 124 70c13 0 88 -99 98 -114c10 1 20 2 30 2s20 -1 30 -2c28 39 58 78 92 112l6 2c5 0 112 -63 124 -70c3 -2 4 -5 4 -7c0 -18 -42 -118 -51 -138c12 -16 22 -34 30 -52c20 -2 149 -16 149 -31zM1920 1222v-140
+c0 -15 -129 -29 -149 -31c-8 -19 -18 -36 -30 -52c9 -20 51 -120 51 -138c0 -3 -1 -5 -4 -7c-12 -7 -119 -71 -124 -71c-13 0 -88 100 -98 115c-10 -1 -20 -2 -30 -2s-20 1 -30 2c-10 -15 -85 -115 -98 -115c-5 0 -112 64 -124 71c-3 2 -4 5 -4 7c0 17 42 118 51 138
+c-12 16 -22 33 -30 52c-20 2 -149 16 -149 31v140c0 15 129 29 149 31c8 18 18 36 30 52c-9 20 -51 121 -51 138c0 2 1 5 4 7c12 6 119 70 124 70c13 0 88 -99 98 -114c10 1 20 2 30 2s20 -1 30 -2c28 39 58 78 92 112l6 2c5 0 112 -63 124 -70c3 -2 4 -5 4 -7
+c0 -18 -42 -118 -51 -138c12 -16 22 -34 30 -52c20 -2 149 -16 149 -31z" />
+ <glyph glyph-name="hackaday" unicode="&#xf30a;" horiz-adv-x="1686"
+d="M215 1408c118 0 214 -95 215 -213v-2c0 -11 -1 -21 -3 -31l168 -149c-60 -45 -109 -106 -142 -178l-173 154c-21 -7 -42 -11 -65 -11c-119 0 -215 96 -215 215c0 14 1 28 4 42l138 -122l150 167l-134 120c18 5 37 8 57 8zM1247 436l162 -143c17 5 45 9 62 9v0
+c118 0 214 -95 215 -213v-2c0 -13 -2 -26 -4 -39l-139 123l-150 -166l140 -124c-20 -6 -41 -9 -62 -9c-119 0 -215 96 -215 215c0 12 1 24 3 35l-140 124c56 50 100 115 128 190zM1471 1408c20 0 39 -3 57 -8l-134 -120l150 -167l138 122c3 -14 4 -28 4 -42
+c0 -119 -96 -215 -215 -215c-23 0 -44 4 -65 11l-174 -154c-33 72 -81 133 -141 178l167 149c-2 10 -2 20 -2 31v2c1 118 97 213 215 213zM439 436v0c28 -75 71 -140 127 -190l-139 -124c2 -11 3 -23 3 -35c0 -119 -96 -215 -215 -215c-21 0 -42 3 -62 9l140 124l-150 166
+l-139 -123c-2 13 -4 26 -4 39v2c1 118 97 213 215 213v0c17 0 45 -4 62 -9zM843 1062c222 0 401 -199 401 -445c0 -153 -69 -288 -175 -368c8 -12 12 -26 12 -41c0 -42 -33 -76 -75 -76s-76 34 -76 76c0 4 0 8 1 12h-13c1 -3 0 -9 0 -12v0c0 -42 -33 -76 -75 -76
+s-76 34 -76 76c0 4 0 8 1 12h-10v-9c0 -43 -35 -79 -77 -79s-77 36 -77 79c0 15 4 28 11 40c-105 80 -173 214 -173 366c0 246 179 445 401 445zM670 730c-8 0 -15 -1 -22 -3c-28 -4 -52 -23 -69 -45c-15 -18 -26 -40 -26 -64c-2 -20 1 -39 5 -58c5 -23 21 -41 39 -54
+c8 -7 20 -16 31 -8c7 9 1 23 7 33c2 10 9 18 18 23c18 9 37 18 57 25c16 5 29 15 43 24c18 14 30 40 21 62c-10 18 -22 34 -39 46c-19 12 -42 19 -65 19zM1015 730c-23 0 -45 -7 -64 -19c-17 -12 -29 -28 -39 -46c-9 -22 3 -48 21 -62c14 -9 27 -19 43 -24
+c20 -7 38 -16 56 -25c9 -5 17 -13 19 -23c6 -10 0 -24 7 -33c11 -8 23 1 31 8c18 13 34 31 39 54c4 19 7 38 5 58c0 24 -11 46 -26 64c-17 22 -41 41 -69 45c-7 2 -15 3 -23 3zM844 502c-20 1 -44 -88 -40 -126c12 -51 16 36 40 36c23 -1 19 -88 37 -35
+c5 35 -16 124 -37 125z" />
+ <glyph glyph-name="frown-o" unicode="&#xf119;"
+d="M1134 307c11 -34 -8 -69 -41 -80c-34 -11 -70 8 -81 42c-33 107 -132 179 -244 179s-211 -72 -244 -179c-11 -34 -47 -53 -80 -42c-34 11 -53 46 -42 80c50 161 197 269 366 269s316 -108 366 -269zM640 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128
+s128 -57 128 -128zM1152 896c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1408 640c0 353 -287 640 -640 640s-640 -287 -640 -640s287 -640 640 -640s640 287 640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768
+s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="opera" unicode="&#xf26a;" horiz-adv-x="1792"
+d="M1493 1308c-105 70 -228 110 -359 110c-213 0 -401 -109 -533 -273c-96 -120 -163 -290 -168 -484v-42c5 -194 72 -364 168 -484c132 -164 320 -273 533 -273c131 0 254 40 359 110c-158 -142 -368 -228 -597 -228c-14 0 -29 0 -43 1c-475 22 -853 414 -853 895
+c0 495 401 896 896 896h3c228 -1 436 -87 594 -228zM1792 640c0 -261 -112 -495 -290 -659c-68 -41 -143 -63 -222 -63c-92 0 -179 30 -255 84c203 74 353 331 353 638c0 306 -149 563 -352 638c76 53 162 83 254 83c81 0 157 -23 226 -65c176 -164 286 -397 286 -656z" />
+ <glyph glyph-name="viadeo" unicode="&#xf2a9;" horiz-adv-x="1278"
+d="M1050 430c0 -143 -50 -269 -147 -374c-101 -110 -229 -161 -378 -161c-148 0 -277 50 -378 161c-97 105 -147 231 -147 374c0 297 224 540 525 540c62 0 124 -10 182 -31c-20 -39 -34 -82 -39 -126c-45 19 -94 28 -143 28c-227 0 -394 -194 -394 -414
+c0 -224 166 -407 394 -407s393 183 393 407c0 57 -10 113 -32 166c44 9 86 26 123 49c28 -67 41 -140 41 -212zM846 619c0 111 -19 221 -55 326c3 -34 3 -69 3 -103c0 -268 -53 -707 -342 -817c20 -3 41 -5 62 -5l14 1c216 136 318 346 318 598zM791 947v-2
+c-52 153 -124 301 -206 440c126 -85 195 -291 206 -438zM1035 744c-62 0 -117 33 -160 75c102 56 231 143 290 247c7 14 19 40 21 56c-58 -130 -206 -232 -344 -264c-22 34 -35 72 -35 113c0 48 24 112 60 147c41 39 102 59 157 74c80 22 145 84 180 159
+c52 -74 74 -164 74 -253c0 -45 -7 -127 -24 -170c-37 -90 -112 -184 -219 -184z" />
+ <glyph glyph-name="battery-empty" unicode="&#xf244;" horiz-adv-x="2304"
+d="M2176 960c71 0 128 -57 128 -128v-384c0 -71 -57 -128 -128 -128v-160c0 -88 -72 -160 -160 -160h-1856c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1856c88 0 160 -72 160 -160v-160zM2176 448v384h-128v288c0 18 -14 32 -32 32h-1856c-18 0 -32 -14 -32 -32v-960
+c0 -18 14 -32 32 -32h1856c18 0 32 14 32 32v288h128z" />
+ <glyph glyph-name="freedombox" unicode="&#xf2fd;" horiz-adv-x="1816"
+d="M152 1274v0h10c90 -2 180 -36 272 -79c4 -2 11 -5 15 -7c7 -3 13 -7 20 -10c116 -58 199 -126 267 -210l3 -3c2 -2 4 -7 6 -9l-255 -148l9 -492l37 465l50 -29l10 -491l37 464l49 -29l10 -490l37 463l50 -29l9 -488l37 461l50 -29l10 -487l37 466l422 245l-267 155
+c2 3 5 5 7 8s5 6 7 9c70 83 157 151 278 208c101 48 200 86 296 86h9c45 -1 84 -15 110 -44c80 -92 -8 -177 -39 -293c-41 -155 6 -321 -118 -429c-43 -37 -93 -47 -143 -52c65 -77 103 -183 82 -292c-4 -21 -10 -42 -18 -61c-6 -17 -13 -32 -22 -47l-9 -15
+c-2 -2 -3 -5 -5 -7c-63 -94 -168 -154 -281 -161c-6 0 -11 -1 -17 -1h-9c-15 0 -39 3 -53 5c-19 3 -49 12 -67 19c-3 1 -7 2 -9 3c-69 29 -124 80 -159 143c-2 3 -4 5 -5 8c-2 3 -5 3 -7 0c-1 -3 -3 -5 -5 -8s-2 -5 -4 -8c-48 -81 -131 -140 -231 -157c-12 -2 -23 -3 -35 -4
+c-6 0 -12 -1 -18 -1c-169 -3 -327 118 -361 292c-21 109 18 215 83 292c-50 5 -101 15 -144 52c-124 108 -78 274 -119 429c-31 116 -118 201 -38 293c26 29 65 43 110 44h9z" />
+ <glyph glyph-name="file-epub" unicode="&#xf321;"
+d="M723 132l458 458l70 -71c24 -24 24 -64 0 -88l-483 -483c-24 -24 -65 -24 -89 0l-483 483c-24 24 -24 64 0 88l483 484c24 24 65 24 89 0l298 -299l-343 -343l-114 114l229 229l-115 114l-343 -343zM1468 1156c37 -37 68 -111 68 -164v-1152c0 -53 -43 -96 -96 -96h-1344
+c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h896c53 0 127 -31 164 -68zM1024 1400v-376h376c-6 17 -15 34 -22 41l-313 313c-7 7 -24 16 -41 22zM1408 -128v1024h-416c-53 0 -96 43 -96 96v416h-768v-1536h1280z" />
+ <glyph glyph-name="chevron-circle-left" unicode="&#xf137;"
+d="M909 141l102 102c25 25 25 65 0 90l-307 307l307 307c25 25 25 65 0 90l-102 102c-25 25 -65 25 -90 0l-454 -454c-25 -25 -25 -65 0 -90l454 -454c25 -25 65 -25 90 0zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="signal" unicode="&#xf012;" horiz-adv-x="1792"
+d="M256 96v-192c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v192c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM640 224v-320c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v320c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1024 480v-576c0 -18 -14 -32 -32 -32h-192
+c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1408 864v-960c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v960c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1792 1376v-1472c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v1472
+c0 18 14 32 32 32h192c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="sitemap" unicode="&#xf0e8;" horiz-adv-x="1792"
+d="M1792 288v-320c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h96v192h-512v-192h96c53 0 96 -43 96 -96v-320c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h96v192h-512v-192h96c53 0 96 -43 96 -96v-320
+c0 -53 -43 -96 -96 -96h-320c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h96v192c0 70 58 128 128 128h512v192h-96c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h320c53 0 96 -43 96 -96v-320c0 -53 -43 -96 -96 -96h-96v-192h512c70 0 128 -58 128 -128v-192h96
+c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="wheelchair-alt" unicode="&#xf29b;" horiz-adv-x="1399"
+d="M1370 723c21 -22 32 -52 29 -82l-44 -551c-5 -56 -51 -98 -106 -98c-3 0 -6 0 -9 1c-59 4 -102 56 -98 114l35 429l-143 -8c35 -72 55 -154 55 -240c0 -144 -56 -275 -148 -372l-137 137c56 62 91 145 91 235c0 194 -157 351 -350 351c-91 0 -173 -35 -236 -92l-137 138
+c77 73 175 123 284 141l264 300l-149 87l-181 -161c-44 -40 -111 -36 -150 8s-35 111 8 150l239 213c34 31 84 36 124 12c487 -283 488 -283 488 -283c26 -15 41 -41 48 -68c10 -39 3 -83 -26 -117l-205 -232l371 20c31 2 61 -9 83 -32zM1172 1180c-98 0 -178 79 -178 178
+c0 98 80 178 178 178c99 0 179 -80 179 -178c0 -99 -80 -178 -179 -178zM545 -62c72 0 140 23 196 61l139 -139c-92 -73 -209 -116 -335 -116c-301 0 -545 244 -545 544c0 127 43 243 116 336l139 -139c-38 -56 -60 -124 -60 -197c0 -193 157 -350 350 -350z" />
+ <glyph glyph-name="external-link-square" unicode="&#xf14c;"
+d="M1280 608v480c0 35 -29 64 -64 64h-480c-26 0 -49 -16 -59 -39c-10 -24 -5 -52 14 -70l144 -144l-534 -534c-25 -25 -25 -65 0 -90l102 -102c25 -25 65 -25 90 0l534 534l144 -144c12 -13 28 -19 45 -19c8 0 17 2 25 5c23 10 39 33 39 59zM1536 1120v-960
+c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="google" unicode="&#xf1a0;" horiz-adv-x="1505"
+d="M768 750h725c7 -39 12 -77 12 -128c0 -438 -294 -750 -737 -750c-425 0 -768 343 -768 768s343 768 768 768c207 0 381 -76 515 -201l-209 -201c-57 55 -157 119 -306 119c-262 0 -476 -217 -476 -485s214 -485 476 -485c304 0 418 218 436 331h-436v264z" />
+ <glyph glyph-name="volume-off" unicode="&#xf026;" horiz-adv-x="768"
+d="M768 1184v-1088c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-333 333h-262c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h262l333 333c12 12 28 19 45 19c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="twitter" unicode="&#xf099;" horiz-adv-x="1576"
+d="M1576 1128c-44 -64 -99 -121 -162 -167c1 -14 1 -28 1 -42c0 -427 -325 -919 -919 -919c-183 0 -353 53 -496 145c26 -3 51 -4 78 -4c151 0 290 51 401 138c-142 3 -261 96 -302 224c20 -3 40 -5 61 -5c29 0 58 4 85 11c-148 30 -259 160 -259 317v4
+c43 -24 93 -39 146 -41c-87 58 -144 157 -144 269c0 60 16 115 44 163c159 -196 398 -324 666 -338c-5 24 -8 49 -8 74c0 178 144 323 323 323c93 0 177 -39 236 -102c73 14 143 41 205 78c-24 -75 -75 -138 -142 -178c65 7 128 25 186 50z" />
+ <glyph glyph-name="battery-full" unicode="&#xf240;" horiz-adv-x="2304"
+d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288c0 18 -14 32 -32 32h-1856c-18 0 -32 -14 -32 -32v-960c0 -18 14 -32 32 -32h1856c18 0 32 14 32 32v288zM2304 832v-384c0 -71 -57 -128 -128 -128v-160c0 -88 -72 -160 -160 -160h-1856
+c-88 0 -160 72 -160 160v960c0 88 72 160 160 160h1856c88 0 160 -72 160 -160v-160c71 0 128 -57 128 -128z" />
+ <glyph glyph-name="deaf" unicode="&#xf2a4;" horiz-adv-x="1792"
+d="M1056 704c0 124 -101 224 -224 224s-224 -100 -224 -224c0 -35 -29 -64 -64 -64s-64 29 -64 64c0 194 158 352 352 352s352 -158 352 -352c0 -35 -29 -64 -64 -64s-64 29 -64 64zM835 1280c318 0 576 -258 576 -576c0 -166 -78 -255 -146 -334
+c-63 -72 -113 -129 -113 -242c0 -212 -172 -384 -384 -384c-35 0 -64 29 -64 64s29 64 64 64c141 0 256 115 256 256c0 161 77 249 144 326c62 71 115 132 115 250c0 247 -201 448 -448 448s-448 -201 -448 -448c0 -35 -29 -64 -64 -64s-64 29 -64 64c0 318 258 576 576 576
+zM591 561l226 -226l-579 -579c-16 -16 -42 -16 -58 0l-168 168c-16 16 -16 42 0 58zM1612 1524l168 -168c16 -16 16 -42 0 -59l-233 -233l-26 -25l-71 -71c-43 100 -109 188 -195 258l91 91l207 207c17 16 43 16 59 0z" />
+ <glyph glyph-name="window-close-o" unicode="&#xf2d4;" horiz-adv-x="1792"
+d="M1257 425l-146 -146c-13 -13 -33 -13 -46 0l-169 169l-169 -169c-13 -13 -33 -13 -46 0l-146 146c-13 13 -13 33 0 46l169 169l-169 169c-13 13 -13 33 0 46l146 146c13 13 33 13 46 0l169 -169l169 169c13 13 33 13 46 0l146 -146c13 -13 13 -33 0 -46l-169 -169
+l169 -169c13 -13 13 -33 0 -46zM256 128h1280v1024h-1280v-1024zM1792 1248v-1216c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="phone" unicode="&#xf095;" horiz-adv-x="1408"
+d="M1408 296c0 -36 -16 -106 -31 -139c-21 -49 -77 -81 -122 -106c-59 -32 -119 -51 -186 -51c-93 0 -177 38 -262 69c-61 22 -120 49 -175 83c-170 105 -375 310 -480 480c-34 55 -61 114 -83 175c-31 85 -69 169 -69 262c0 67 19 127 51 186c25 45 57 101 106 122
+c33 15 103 31 139 31c7 0 14 0 21 -3c21 -7 43 -56 53 -76c32 -57 63 -115 96 -171c16 -26 46 -58 46 -89c0 -61 -181 -150 -181 -204c0 -27 25 -62 39 -86c101 -182 227 -308 409 -409c24 -14 59 -39 86 -39c54 0 143 181 204 181c31 0 63 -30 89 -46
+c56 -33 114 -64 171 -96c20 -10 69 -32 76 -53c3 -7 3 -14 3 -21z" />
+ <glyph glyph-name="mars-double" unicode="&#xf227;" horiz-adv-x="1920"
+d="M1536 1120c0 18 14 32 32 32h288c35 0 64 -29 64 -64v-288c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v134l-254 -255c98 -123 147 -286 117 -461c-42 -243 -240 -434 -484 -468c-286 -40 -539 131 -626 380c-316 16 -565 288 -544 613c18 274 235 502 508 533
+c161 19 311 -31 426 -122l255 254h-134c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h288c35 0 64 -29 64 -64v-288c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v134l-254 -255c40 -50 71 -107 93 -169c124 -6 237 -52 328 -124l255 254h-134c-18 0 -32 14 -32 32v64z
+M1024 704c0 20 -2 39 -4 58c-215 -33 -380 -218 -380 -442c0 -20 2 -39 4 -58c215 33 380 218 380 442zM128 704c0 -226 169 -413 387 -443c-2 19 -3 39 -3 59c0 282 204 517 473 566c-70 157 -227 266 -409 266c-247 0 -448 -201 -448 -448zM1088 -128
+c247 0 448 201 448 448c0 226 -169 413 -387 443c2 -19 3 -39 3 -59c0 -282 -204 -517 -473 -566c70 -157 227 -266 409 -266z" />
+ <glyph glyph-name="maxcdn" unicode="&#xf136;" horiz-adv-x="1755"
+d="M1745 763l-164 -763h-334l178 832c8 35 3 67 -15 88c-17 21 -47 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276c135 0 258 -56 337 -154c80 -98 109 -231 81 -363z" />
+ <glyph glyph-name="hand-peace-o" unicode="&#xf25b;"
+d="M1288 889c37 0 74 -7 107 -23c96 -43 141 -122 141 -226v-177c0 -63 -8 -126 -23 -186l-85 -339c-28 -114 -130 -194 -248 -194h-668c-141 0 -256 115 -256 256v401l-239 628c-11 29 -17 60 -17 91c0 141 115 256 256 256c106 0 202 -66 239 -165l17 -44v113
+c0 141 115 256 256 256s256 -115 256 -256v-261c16 3 32 5 48 5c92 0 176 -53 216 -135zM1072 896c-44 0 -84 -26 -102 -66l-74 -163l-71 -155h55c67 0 126 -47 140 -112l154 338c7 14 10 30 10 46c0 62 -50 112 -112 112zM1293 761c-76 0 -100 -61 -127 -121l-132 -290
+c-7 -14 -10 -30 -10 -46c0 -62 50 -112 112 -112c44 0 84 26 102 66l160 352c5 10 9 26 9 38c0 67 -48 113 -114 113zM128 1120c0 -16 3 -31 8 -46l248 -650v-69l102 111c27 29 66 46 106 46h198l106 233v535c0 71 -57 128 -128 128s-128 -57 -128 -128v-640h-64l-200 526
+c-19 49 -67 82 -120 82c-71 0 -128 -58 -128 -128zM1180 -128c59 0 110 40 124 97l85 339c13 50 19 103 19 155v91l-141 -310c-23 -51 -75 -84 -131 -84c-70 0 -131 51 -142 121c-27 -35 -69 -57 -114 -57h-208v32h208c61 0 116 50 116 112c0 61 -46 112 -108 112h-296
+c-31 0 -61 -13 -82 -36l-126 -136v-308c0 -71 57 -128 128 -128h668z" />
+ <glyph glyph-name="envira" unicode="&#xf299;" horiz-adv-x="1792"
+d="M896 720c-127 240 -244 474 -577 632c-199 94 -21 -37 -21 -37c181 -125 264 -294 361 -479c126 -241 316 -559 577 -671c260 -112 137 -50 24 34c-113 85 -273 348 -364 521zM549 177c-361 286 -341 628 -549 1359c1911 0 1467 -1269 1469 -1465l323 -327h-104l-281 285
+c-156 -17 -498 -138 -858 148z" />
+ <glyph glyph-name="lastfm-square" unicode="&#xf203;"
+d="M1432 484c0 141 -114 205 -234 239c-55 15 -100 28 -120 88c-1 5 -6 24 -6 28c0 48 38 83 85 83c22 0 53 1 71 -15h-1c19 -14 28 -30 39 -51l93 71c-15 21 -30 46 -49 64c-47 42 -91 49 -153 49c-105 0 -204 -86 -204 -195c0 -8 1 -15 2 -23c22 -136 91 -178 213 -213
+c60 -17 145 -44 146 -118v-5c1 -80 -66 -128 -141 -128c-82 0 -135 78 -167 144c-116 239 -134 538 -478 538c-207 0 -393 -191 -386 -396v-1c7 -214 154 -403 380 -403c107 0 207 25 279 110c12 16 23 33 31 51l-60 109c-56 -106 -125 -152 -245 -152
+c-158 0 -267 140 -267 291c0 139 128 273 268 273c160 0 218 -83 274 -226c67 -172 139 -456 371 -456c139 0 259 101 259 244zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="home" unicode="&#xf015;" horiz-adv-x="1612"
+d="M1382 544v-480c0 -35 -29 -64 -64 -64h-384v384h-256v-384h-384c-35 0 -64 29 -64 64v480c0 2 1 4 1 6l575 474l575 -474c1 -2 1 -4 1 -6zM1605 613l-62 -74c-5 -6 -13 -10 -21 -11h-3c-8 0 -15 2 -21 7l-692 577l-692 -577c-7 -5 -15 -8 -24 -7c-8 1 -16 5 -21 11
+l-62 74c-11 13 -9 34 4 45l719 599c42 35 110 35 152 0l244 -204v195c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-408l219 -182c13 -11 15 -32 4 -45z" />
+ <glyph glyph-name="empire" unicode="&#xf1d1;" horiz-adv-x="1792"
+d="M874 -102v-66c-282 8 -529 160 -668 385l58 34c21 -35 46 -68 73 -99l65 57c94 -107 222 -183 368 -212l-17 -86c39 -7 80 -12 121 -13zM276 428l-83 -28c14 -39 30 -76 49 -112l-57 -33c-62 114 -98 246 -98 385s36 271 98 385l57 -33c-19 -35 -36 -73 -49 -112l82 -28
+c-23 -66 -35 -138 -35 -212s13 -146 36 -212zM1528 251l58 -34c-139 -225 -386 -377 -668 -385v66c41 1 82 6 121 13l-17 86c146 29 274 105 368 212l65 -57c27 31 52 64 73 99zM1377 805l-233 -80c9 -27 14 -55 14 -85s-5 -58 -14 -85l232 -80c-21 -63 -55 -120 -98 -169
+l-185 162c-37 -43 -88 -73 -147 -85l48 -241c-31 -6 -64 -10 -98 -10s-67 4 -98 10l48 241c-59 12 -110 42 -147 85l-185 -162c-43 49 -77 106 -98 169l232 80c-9 27 -14 55 -14 85s5 58 14 85l-233 80c22 63 56 120 99 169l185 -162c37 43 88 74 147 86l-48 240
+c31 7 64 10 98 10s67 -3 98 -10l-48 -240c59 -12 110 -43 147 -86l185 162c43 -49 77 -106 99 -169zM874 1448v-66c-41 -1 -82 -5 -121 -13l17 -86c-146 -28 -274 -104 -368 -211l-65 56c-27 -30 -51 -63 -73 -98l-57 33c139 226 385 377 667 385zM1705 640
+c0 -139 -36 -271 -98 -385l-57 33c19 36 35 73 49 112l-83 28c23 66 36 138 36 212s-12 146 -35 212l82 28c-13 39 -30 77 -49 112l57 33c62 -114 98 -246 98 -385zM1585 1063l-57 -33c-22 35 -46 68 -73 98l-65 -56c-94 107 -222 183 -368 211l17 86c-39 8 -80 12 -121 13
+v66c282 -8 528 -159 667 -385zM1748 640c0 470 -382 852 -852 852s-852 -382 -852 -852s382 -852 852 -852s852 382 852 852zM1792 640c0 -495 -401 -896 -896 -896s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="server" unicode="&#xf233;" horiz-adv-x="1792"
+d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM128 1152h1024v128h-1024v-128zM1696 704c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM1696 1216
+c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+ <glyph glyph-name="inkscape" unicode="&#xf312;"
+d="M755 1398v0c47 0 95 -17 131 -52l588 -601c234 -234 -259 -288 -401 -371c-50 -51 153 -85 132 -147c-42 -126 -157 -45 -280 -171c-50 -51 95 -46 45 -97c-93 -68 -285 -115 -300 -32c-21 117 -135 68 -185 119s101 104 51 155s-299 97 -349 148s191 88 141 139
+c-138 68 -461 41 -269 278l567 580c34 35 82 52 129 52zM760 1343v0c-34 0 -68 -13 -93 -38c-49 -50 -140 -138 -219 -223c-45 -45 -40 -109 10 -109h123l80 139l49 -199l149 95l93 -49l22 131l111 -89c12 12 12 54 -9 76l-224 228c-24 25 -58 38 -92 38zM491 456
+c-74 0 219 -119 279 -103c27 14 40 34 21 38c-56 9 -285 56 -300 65zM1390 297c43 -1 86 -22 100 -63c0 -54 -212 -36 -212 -7c13 47 63 71 112 70zM409 172c26 0 50 -8 64 -26c-23 -61 -101 -115 -151 -72c-57 50 21 99 87 98zM1251 168c71 -14 85 -65 71 -79
+c-64 -38 -136 21 -71 79z" />
+ <glyph glyph-name="search-minus" unicode="&#xf010;" horiz-adv-x="1664"
+d="M1024 736v-64c0 -17 -15 -32 -32 -32h-576c-17 0 -32 15 -32 32v64c0 17 15 32 32 32h576c17 0 32 -15 32 -32zM1152 704c0 247 -201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448s448 201 448 448zM1664 -128c0 -71 -57 -128 -128 -128c-34 0 -67 14 -90 38
+l-343 342c-117 -81 -257 -124 -399 -124c-389 0 -704 315 -704 704s315 704 704 704s704 -315 704 -704c0 -142 -43 -282 -124 -399l343 -343c23 -23 37 -56 37 -90z" />
+ <glyph glyph-name="leaf" unicode="&#xf06c;" horiz-adv-x="1792"
+d="M1280 832c0 35 -29 64 -64 64c-354 0 -582 -148 -813 -403c-12 -13 -19 -27 -19 -45c0 -35 29 -64 64 -64c18 0 32 7 45 19c49 44 93 92 141 137c181 163 336 228 582 228c35 0 64 29 64 64zM1792 1030c0 -64 -7 -129 -20 -193c-64 -311 -264 -513 -542 -651
+c-135 -68 -286 -108 -438 -108c-96 0 -195 16 -286 47c-48 16 -144 79 -184 79c-50 0 -110 -204 -197 -204c-63 0 -82 31 -109 77c-9 17 -16 23 -16 44c0 104 198 185 198 243c0 9 -26 62 -30 82c-6 34 -9 69 -9 104c0 318 253 545 537 639c205 68 641 -11 780 121
+c55 51 82 98 166 98c113 0 150 -293 150 -378z" />
+ <glyph glyph-name="envelope-open-o" unicode="&#xf2b7;" horiz-adv-x="1792"
+d="M1474 623l39 -51c11 -14 8 -33 -5 -44c-100 -78 -330 -255 -340 -263c-71 -58 -167 -138 -271 -137h-2c-104 0 -200 79 -271 137c-11 9 -233 180 -331 256c-14 11 -17 30 -6 44l37 52c11 15 32 18 46 6c68 -53 164 -127 306 -236c50 -38 149 -131 219 -131h2
+c70 0 169 93 219 131c147 113 245 188 313 242c14 11 34 8 45 -6zM1664 -96v928c-100 93 -85 85 -548 443c-50 39 -149 133 -219 133h-2c-70 0 -169 -94 -219 -133c-463 -358 -448 -350 -548 -443v-928c0 -17 15 -32 32 -32h1472c17 0 32 15 32 32zM1792 832v-928
+c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v928c0 36 15 70 41 94c205 190 441 355 583 472c70 58 167 138 271 138h2c104 0 201 -80 271 -138c132 -109 383 -286 583 -472c26 -24 41 -58 41 -94z" />
+ <glyph glyph-name="exclamation-circle" unicode="&#xf06a;"
+d="M768 1408c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM896 161v190c0 18 -14 33 -31 33h-192c-18 0 -33 -15 -33 -33v-190c0 -18 15 -33 33 -33h192c17 0 31 15 31 33zM894 505l18 621c0 7 -3 14 -10 18c-6 5 -15 8 -24 8h-220
+c-9 0 -18 -3 -24 -8c-7 -4 -10 -11 -10 -18l17 -621c0 -14 15 -25 34 -25h185c18 0 33 11 34 25z" />
+ <glyph glyph-name="comments" unicode="&#xf086;" horiz-adv-x="1792"
+d="M1408 768c0 -283 -315 -512 -704 -512c-61 0 -120 6 -176 16c-83 -59 -177 -102 -278 -128c-27 -7 -56 -12 -86 -16h-3c-15 0 -29 12 -32 29c-4 19 9 31 20 44c39 44 83 83 117 166c-162 94 -266 239 -266 401c0 283 315 512 704 512s704 -229 704 -512zM1792 512
+c0 -163 -104 -307 -266 -401c34 -83 78 -122 117 -166c11 -13 24 -25 20 -44c-4 -18 -19 -31 -35 -29c-30 4 -59 9 -86 16c-101 26 -195 69 -278 128c-56 -10 -115 -16 -176 -16c-181 0 -347 50 -472 132c29 -2 59 -4 88 -4c215 0 418 62 573 174c167 122 259 287 259 466
+c0 52 -8 103 -23 152c169 -93 279 -241 279 -408z" />
+ <glyph glyph-name="moon" unicode="&#xf328;" horiz-adv-x="1471"
+d="M1465 318c-125 -271 -399 -446 -697 -446c-423 0 -768 345 -768 768c0 415 325 752 739 767c28 1 51 -15 61 -39c11 -25 4 -54 -15 -72c-114 -104 -177 -246 -177 -400c0 -300 244 -544 544 -544c79 0 155 17 228 51c25 11 53 6 72 -13s24 -48 13 -72z" />
+ <glyph glyph-name="facebook-official" unicode="&#xf230;"
+d="M1451 1408c47 0 85 -38 85 -85v-1366c0 -47 -38 -85 -85 -85h-391v595h199l30 232h-229v148c0 67 18 112 115 112l122 1v207c-21 3 -94 9 -178 9c-177 0 -299 -108 -299 -306v-171h-200v-232h200v-595h-735c-47 0 -85 38 -85 85v1366c0 47 38 85 85 85h1366z" />
+ <glyph glyph-name="clock-o" unicode="&#xf017;"
+d="M896 992v-448c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v352c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544s544 244 544 544zM1536 640
+c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="caret-square-o-left" unicode="&#xf191;"
+d="M1024 960v-640c0 -35 -29 -64 -64 -64c-13 0 -26 4 -37 12l-448 320c-17 12 -27 31 -27 52c0 20 10 40 27 52l448 320c11 8 24 12 37 12c35 0 64 -29 64 -64zM1280 160v960c0 17 -15 32 -32 32h-960c-17 0 -32 -15 -32 -32v-960c0 -17 15 -32 32 -32h960
+c17 0 32 15 32 32zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="hand-scissors-o" unicode="&#xf257;" horiz-adv-x="1792"
+d="M1073 -128h-177c-104 0 -183 45 -226 141c-15 32 -23 67 -23 102v5c-82 40 -135 124 -135 216c0 11 0 38 5 48h-261c-141 0 -256 115 -256 256s115 256 256 256h113l-44 17c-99 37 -165 133 -165 239c0 141 115 256 256 256c31 0 62 -6 91 -17l628 -239h401
+c141 0 256 -115 256 -256v-668c0 -118 -80 -220 -194 -248l-339 -85c-60 -15 -123 -23 -186 -23zM1024 583l-155 -71l-163 -74c-40 -18 -66 -58 -66 -102c0 -62 50 -112 112 -112c16 0 32 3 46 10l338 154c-65 14 -112 73 -112 140v55zM1344 272c0 62 -50 112 -112 112
+c-16 0 -32 -3 -46 -10l-290 -132c-60 -27 -121 -51 -121 -127c0 -66 46 -114 113 -114c12 0 28 4 38 9l352 160c40 18 66 58 66 102zM1112 1024l-650 248c-15 5 -30 8 -46 8c-70 0 -128 -57 -128 -128c0 -53 33 -101 82 -120l526 -200v-64h-640c-71 0 -128 -57 -128 -128
+s57 -128 128 -128h535l233 106v198c0 40 17 79 46 106l111 102h-69zM1073 0c52 0 105 6 155 19l339 85c57 14 97 65 97 124v668c0 71 -57 128 -128 128h-308l-136 -126c-23 -21 -36 -51 -36 -82v-296c0 -62 51 -108 112 -108c62 0 112 55 112 116v208h32v-208
+c0 -45 -22 -87 -57 -114c70 -11 121 -72 121 -142c0 -56 -33 -108 -84 -131l-310 -141h91z" />
+ <glyph glyph-name="tumblr-square" unicode="&#xf174;"
+d="M1136 75l-62 183c-24 -12 -69 -22 -103 -22c-102 -3 -123 71 -123 126v398h257v194h-256v326h-188c-3 0 -8 -3 -9 -10c-11 -99 -58 -275 -252 -345v-165h130v-418c0 -143 105 -347 384 -342c94 2 199 41 222 75zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960
+c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="rub" unicode="&#xf158;" horiz-adv-x="1280"
+d="M1043 971c0 134 -95 224 -236 224h-320v-448h320c141 0 236 90 236 224zM1280 971c0 -257 -186 -437 -453 -437h-340v-118h505c18 0 32 -14 32 -32v-128c0 -18 -14 -32 -32 -32h-505v-192c0 -18 -14 -32 -32 -32h-167c-18 0 -32 14 -32 32v192h-224c-18 0 -32 14 -32 32
+v128c0 18 14 32 32 32h224v118h-224c-18 0 -32 14 -32 32v149c0 18 14 32 32 32h224v629c0 18 14 32 32 32h539c267 0 453 -180 453 -437z" />
+ <glyph glyph-name="chevron-circle-up" unicode="&#xf139;"
+d="M1165 397l102 102c25 25 25 65 0 90l-454 454c-25 25 -65 25 -90 0l-454 -454c-25 -25 -25 -65 0 -90l102 -102c25 -25 65 -25 90 0l307 307l307 -307c25 -25 65 -25 90 0zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z
+" />
+ <glyph glyph-name="opencart" unicode="&#xf23d;" horiz-adv-x="2304"
+d="M1524 -25c0 -91 -73 -164 -164 -164s-165 73 -165 164s74 165 165 165s164 -74 164 -165zM775 -25c0 -91 -74 -164 -165 -164s-164 73 -164 164s73 165 164 165s165 -74 165 -165zM0 1469c295 -311 572 -357 1660 -357s610 -242 -62 -842c213 370 945 698 -255 680
+c-1151 -17 -1219 333 -1343 519z" />
+ <glyph glyph-name="artstation" unicode="&#xf2ed;" horiz-adv-x="1533"
+d="M601 1277v0h267c51 0 112 -37 136 -83l504 -878c16 -24 25 -53 25 -84c0 -35 -7 -53 -31 -94l-123 -213zM474 1058l348 -604h-695zM0 233v0h949l178 -309h-859c-53 0 -114 38 -138 85h-1z" />
+ <glyph glyph-name="thumbs-up" unicode="&#xf164;" horiz-adv-x="1600"
+d="M256 192c0 35 -29 64 -64 64c-36 0 -64 -29 -64 -64c0 -36 28 -64 64 -64c35 0 64 28 64 64zM416 704v-640c0 -35 -29 -64 -64 -64h-288c-35 0 -64 29 -64 64v640c0 35 29 64 64 64h288c35 0 64 -29 64 -64zM1600 704c0 -53 -21 -110 -55 -149c11 -32 15 -62 15 -76
+c2 -50 -13 -97 -43 -137c11 -37 11 -77 0 -117c-10 -37 -29 -70 -54 -94c6 -75 -11 -136 -49 -181c-43 -51 -109 -77 -197 -78h-129c-143 0 -278 47 -386 84c-63 22 -123 43 -158 44c-34 1 -64 29 -64 64v641c0 33 28 61 61 64c37 3 133 122 177 180c36 46 70 89 101 120
+c39 39 50 99 62 157c11 59 23 121 66 163c12 12 28 19 45 19c224 0 224 -179 224 -256c0 -82 -29 -140 -56 -192c-11 -22 -21 -32 -29 -64h277c104 0 192 -88 192 -192z" />
+ <glyph glyph-name="vimeo-square" unicode="&#xf194;"
+d="M1292 898c7 145 -47 218 -161 222c-154 5 -258 -82 -312 -261c28 12 55 19 82 19c56 0 81 -32 74 -96c-3 -38 -28 -94 -74 -167c-47 -74 -82 -110 -105 -110c-30 0 -56 56 -82 169c-8 34 -23 118 -45 255c-20 126 -73 185 -160 177c-36 -4 -92 -36 -164 -100
+c-54 -47 -107 -96 -162 -144l52 -67c50 34 79 52 87 52c38 0 74 -60 107 -179c30 -110 60 -219 90 -329c45 -119 99 -179 164 -179c104 0 232 98 383 294c146 188 222 336 226 444zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960
+c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="arrow-circle-right" unicode="&#xf0a9;"
+d="M1285 640c0 17 -6 33 -18 45l-91 91l-362 362c-12 12 -28 18 -45 18s-33 -6 -45 -18l-91 -91c-12 -12 -18 -28 -18 -45s6 -33 18 -45l189 -189h-502c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h502l-189 -189c-12 -12 -19 -28 -19 -45s7 -33 19 -45l91 -91
+c12 -12 28 -18 45 -18s33 6 45 18l362 362l91 91c12 12 18 28 18 45zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="bolt" unicode="&#xf0e7;" horiz-adv-x="896"
+d="M885 970c11 -12 14 -29 7 -44l-540 -1157c-8 -15 -24 -25 -42 -25c-4 0 -9 1 -14 2c-22 7 -35 28 -30 49l197 808l-406 -101c-4 -1 -8 -1 -12 -1c-11 0 -23 4 -31 11c-12 10 -16 25 -13 39l201 825c5 19 23 32 44 32h328c25 0 45 -19 45 -42c0 -6 -2 -12 -5 -18
+l-171 -463l396 98c4 1 8 2 12 2c13 0 25 -6 34 -15z" />
+ <glyph glyph-name="thermometer-quarter" unicode="&#xf2ca;" horiz-adv-x="1024"
+d="M640 192c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 80 50 153 128 181v139h128v-139c78 -28 128 -101 128 -181zM768 192c0 105 -50 197 -128 256v768c0 106 -86 192 -192 192s-192 -86 -192 -192v-768c-78 -59 -128 -151 -128 -256c0 -177 143 -320 320 -320
+s320 143 320 320zM896 192c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 122 49 232 128 313v711c0 177 143 320 320 320s320 -143 320 -320v-711c79 -81 128 -191 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z
+" />
+ <glyph glyph-name="hdd-o" unicode="&#xf0a0;"
+d="M1040 320c0 -44 -36 -80 -80 -80s-80 36 -80 80s36 80 80 80s80 -36 80 -80zM1296 320c0 -44 -36 -80 -80 -80s-80 36 -80 80s36 80 80 80s80 -36 80 -80zM1408 160v320c0 17 -15 32 -32 32h-1216c-17 0 -32 -15 -32 -32v-320c0 -17 15 -32 32 -32h1216c17 0 32 15 32 32
+zM178 640h1180l-157 482c-5 17 -24 30 -42 30h-782c-18 0 -37 -13 -42 -30zM1536 480v-320c0 -88 -72 -160 -160 -160h-1216c-88 0 -160 72 -160 160v320c0 27 8 50 16 75l197 606c23 70 90 119 164 119h782c74 0 141 -49 164 -119l197 -606c8 -25 16 -48 16 -75z" />
+ <glyph glyph-name="id-card-o" unicode="&#xf2c3;" horiz-adv-x="2048"
+d="M896 324c0 -73 -48 -132 -107 -132h-426c-59 0 -107 59 -107 132c0 132 32 284 164 284c40 -40 95 -64 156 -64s116 24 156 64c132 0 164 -152 164 -284zM768 768c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1792 352v-64
+c0 -18 -14 -32 -32 -32h-704c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h704c18 0 32 -14 32 -32zM1408 608v-64c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h320c18 0 32 -14 32 -32zM1792 608v-64c0 -18 -14 -32 -32 -32h-192
+c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h192c18 0 32 -14 32 -32zM1792 864v-64c0 -18 -14 -32 -32 -32h-704c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h704c18 0 32 -14 32 -32zM1920 32v1120h-1792v-1120c0 -17 15 -32 32 -32h1728c17 0 32 15 32 32zM2048 1248v-1216
+c0 -88 -72 -160 -160 -160h-1728c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1728c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="plug" unicode="&#xf1e6;" horiz-adv-x="1792"
+d="M1755 1083c49 -50 49 -131 0 -181l-401 -400l150 -150l-160 -160c-219 -219 -553 -250 -801 -86l-362 -362h-181v181l362 362c-164 248 -133 582 86 801l160 160l150 -150l400 401c50 49 131 49 181 0c50 -50 50 -132 0 -181l-400 -401l234 -234l401 400
+c50 50 131 50 181 0z" />
+ <glyph glyph-name="react" unicode="&#xf302;" horiz-adv-x="1755"
+d="M1434 910v0c187 -64 321 -165 321 -269c0 -109 -143 -215 -341 -280c-11 -3 -21 -7 -32 -10c3 -13 7 -33 10 -46c39 -197 10 -360 -83 -413c-89 -52 -235 -1 -382 125c-16 14 -31 28 -46 43c-12 -12 -24 -22 -36 -33c-152 -133 -307 -187 -400 -134
+c-90 52 -118 203 -82 393c4 21 9 40 14 61c-16 4 -32 10 -47 15c-190 65 -330 172 -330 279c0 104 131 205 314 268c20 7 42 14 64 20c-5 19 -9 38 -13 57c-38 193 -11 348 79 400c94 55 250 -3 406 -142c8 -7 21 -20 29 -27c14 13 28 27 43 40c149 130 296 184 386 132
+c94 -54 121 -219 79 -423c-3 -13 -6 -25 -9 -38c15 -5 41 -13 56 -18zM970 1201v0c-14 -12 -27 -23 -40 -36c53 -57 101 -118 146 -182c77 -7 155 -20 231 -37c3 11 5 23 7 35c36 177 15 311 -43 344c-54 31 -173 -13 -301 -124zM524 553c-22 -52 -41 -104 -56 -153
+c52 -11 106 -19 159 -25c-19 29 -37 59 -54 89c-17 29 -33 59 -49 89zM524 726c15 30 32 61 49 90s35 59 53 87c-55 -7 -108 -16 -157 -27c15 -48 33 -99 55 -150zM563 640v0c23 -47 48 -93 74 -139c22 -38 59 -98 84 -134c50 -3 103 -5 157 -5s107 2 158 6
+c29 44 57 87 83 133c22 38 55 101 74 140c-23 47 -49 94 -75 139c-22 37 -59 96 -83 132c-51 4 -104 6 -157 6s-107 -2 -158 -6c-29 -44 -57 -87 -83 -133s-51 -92 -74 -139zM1182 464c-17 -29 -34 -59 -53 -88c54 6 108 16 161 28c-17 52 -35 102 -57 152
+c-16 -31 -34 -62 -51 -92zM1232 726c21 49 39 98 55 149c-49 11 -102 21 -157 28c15 -24 38 -63 52 -87c17 -29 34 -60 50 -90zM878 1112v0c-34 -37 -68 -79 -102 -123c28 1 74 3 102 3s74 -2 102 -3c-32 43 -66 84 -102 123zM481 1322c-54 -31 -76 -156 -44 -322
+c4 -18 8 -36 12 -53c76 17 154 29 231 36c45 64 94 125 147 182c-9 8 -17 16 -26 24c-135 119 -262 167 -320 133zM397 419c24 75 52 149 85 221c-33 71 -61 144 -84 218c-20 -6 -40 -12 -60 -19c-156 -55 -264 -135 -264 -198c7 -41 29 -78 64 -102
+c60 -48 143 -84 216 -107c14 -5 29 -9 43 -13zM796 83c11 10 22 19 33 30c-53 58 -103 119 -148 183c-79 6 -156 18 -233 34c-5 -19 -8 -38 -12 -57c-31 -163 -9 -284 46 -316c39 -15 83 -13 121 5c71 28 136 69 193 121zM880 166c36 40 70 81 102 125
+c-34 -2 -69 -3 -104 -3c-34 0 -68 1 -101 2c34 -45 68 -86 103 -124zM1328 63c11 76 9 153 -8 227c-2 12 -6 31 -9 42c-64 -14 -169 -31 -234 -36c-44 -64 -93 -126 -145 -184c15 -14 30 -27 44 -39c125 -108 241 -149 296 -117c33 26 53 65 56 107zM1391 432
+c171 57 291 143 291 210c0 62 -112 144 -272 199c-16 5 -34 11 -52 16c-23 -74 -51 -146 -84 -216c34 -71 64 -143 88 -218c10 3 19 6 29 9zM878 797c87 0 157 -70 157 -157s-70 -157 -157 -157s-157 70 -157 157s70 157 157 157z" />
+ <glyph glyph-name="themeisle" unicode="&#xf2b2;" horiz-adv-x="1792"
+d="M852 1227c0 -36 -23 -76 -62 -76c-40 0 -62 40 -62 76c0 35 22 76 62 76c39 0 62 -41 62 -76zM688 -149v114c0 39 -31 73 -71 73s-70 -34 -70 -73v-114c0 -39 30 -74 70 -74s71 34 71 74zM860 -149v114c0 39 -30 73 -70 73s-71 -34 -71 -73v-114c0 -39 31 -74 71 -74
+s70 35 70 74zM1034 -149v114c0 39 -31 73 -71 73s-71 -34 -71 -73v-114c0 -39 31 -74 71 -74s71 34 71 74zM1208 -149v114c0 39 -31 73 -71 73s-71 -34 -71 -73v-114c0 -39 31 -74 71 -74s71 35 71 74zM1476 535c-108 -207 -316 -359 -555 -359c-338 0 -562 296 -562 618
+c0 59 7 117 21 174c-70 -118 -104 -254 -104 -390c0 -211 87 -426 250 -563c18 34 52 57 91 57c35 0 68 -20 86 -50c19 30 51 50 87 50c35 0 68 -20 86 -50c19 30 52 50 87 50s68 -20 87 -50c18 30 51 50 86 50c38 0 73 -23 90 -56c152 127 240 322 250 519zM1326 564
+c0 50 -22 75 -72 75c-16 0 -32 -3 -47 -6c-50 -10 -99 -19 -149 -19c-158 0 -226 92 -226 243c0 69 13 137 30 204c-53 -81 -83 -178 -83 -275c0 -189 120 -371 324 -371c75 0 149 27 210 70c7 26 13 52 13 79zM884 1223c0 63 -44 129 -113 129s-113 -66 -113 -129
+c0 -64 44 -130 113 -130s113 66 113 130zM1513 884c0 188 -121 370 -324 370c-106 0 -205 -53 -276 -129c-25 -83 -48 -180 -48 -268c0 -133 53 -210 193 -210c48 0 95 9 142 19c18 3 35 6 53 6c69 0 104 -40 104 -108c0 -15 -1 -31 -4 -46c101 91 160 230 160 366z
+M1792 667c0 -126 -40 -358 -127 -454c-80 -87 -306 -214 -423 -247l-4 -1v-114c0 -57 -44 -107 -102 -107c-35 0 -68 20 -86 50c-19 -30 -52 -50 -87 -50s-68 20 -87 50c-18 -30 -51 -50 -86 -50c-36 0 -68 20 -87 50c-18 -30 -51 -50 -86 -50c-66 0 -103 55 -103 115
+c-57 -43 -125 -68 -198 -68c-77 0 -152 29 -211 80c36 1 72 8 106 20c-73 20 -138 66 -182 127c23 -5 47 -7 71 -7c58 0 115 16 164 46c-77 77 -198 206 -240 306c-20 47 -24 110 -24 160c0 174 71 560 302 560c37 0 66 -17 81 -52c13 19 27 37 42 54c7 9 20 19 25 29
+c28 44 41 74 76 119c113 144 286 243 472 243c21 0 42 -1 62 -4c38 41 91 64 146 64c51 0 104 -21 140 -57c3 -3 5 -8 5 -12c0 -13 -36 -47 -45 -57c15 -5 55 -24 55 -42c0 -10 -10 -18 -16 -25c110 -97 173 -235 197 -378c15 18 36 30 60 30c37 0 73 -25 100 -49
+c73 -65 90 -186 90 -279z" />
+ <glyph glyph-name="braille" unicode="&#xf2a1;" horiz-adv-x="2176"
+d="M192 352c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM704 352c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM704 864c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160z
+M1472 352c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM1984 352c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM1472 864c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160z
+M1984 864c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM1984 1376c-88 0 -160 -72 -160 -160s72 -160 160 -160s160 72 160 160s-72 160 -160 160zM384 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192z
+M896 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM384 704c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM896 704c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192z
+M384 1216c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1664 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM896 1216c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192
+zM2176 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1664 704c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM2176 704c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192
+s192 -86 192 -192zM1664 1216c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM2176 1216c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192z" />
+ <glyph glyph-name="industry" unicode="&#xf275;" horiz-adv-x="1792"
+d="M448 1536c35 0 64 -29 64 -64v-891l536 429c11 9 26 14 40 14c35 0 64 -29 64 -64v-379l536 429c11 9 26 14 40 14c35 0 64 -29 64 -64v-1152c0 -35 -29 -64 -64 -64h-1664c-35 0 -64 29 -64 64v1664c0 35 29 64 64 64h384z" />
+ <glyph glyph-name="map-o" unicode="&#xf278;" horiz-adv-x="2048"
+d="M2020 1525c17 -12 28 -32 28 -53v-1408c0 -26 -16 -50 -40 -59l-640 -256c-16 -7 -32 -7 -48 0l-616 246l-616 -246c-8 -4 -16 -5 -24 -5c-13 0 -25 4 -36 11c-17 12 -28 32 -28 53v1408c0 26 16 50 40 59l640 256c16 7 32 7 48 0l616 -246l616 246c20 8 42 6 60 -6z
+M736 1390v-1270l576 -230v1270zM128 1173v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+ <glyph glyph-name="krw" unicode="&#xf159;" horiz-adv-x="1792"
+d="M514 341l81 299h-159l75 -300c1 -2 1 -4 2 -6c0 2 1 5 1 7zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299c1 -3 1 -5 2 -7c0 2 1 4 1 6zM1382 768l33 128h-297l34 -128h230zM1792 736v-64c0 -18 -14 -32 -32 -32h-213
+l-164 -616c-4 -14 -17 -24 -31 -24h-159c-14 0 -27 10 -31 24l-166 616h-209l-167 -616c-4 -14 -16 -24 -31 -24h-159c-14 0 -27 10 -30 24l-160 616h-208c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h175l-33 128h-142c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h109l-89 344
+c-3 10 -1 20 5 28c6 7 16 12 26 12h137c15 0 28 -10 31 -24l90 -360h359l97 360c4 14 17 24 31 24h126c15 0 27 -10 31 -24l98 -360h365l93 360c3 14 16 24 31 24h137c10 0 20 -5 26 -12c6 -8 8 -19 5 -28l-91 -344h111c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-145
+l-34 -128h179c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="joomla" unicode="&#xf1aa;"
+d="M1070 463l-160 -160l-151 -152l-30 -30c-88 -87 -211 -117 -323 -89c-21 -92 -103 -160 -201 -160c-113 0 -205 92 -205 206c0 97 67 179 158 200c-29 113 1 237 89 325l12 12l151 -152l-11 -11c-50 -49 -49 -129 0 -179c49 -49 129 -49 178 0l30 30l151 152l161 160z
+M729 1145l12 -12l-152 -152l-12 12c-49 49 -129 49 -178 0s-49 -130 0 -179l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30c-92 91 -120 222 -85 339c-92 20 -160 102 -160 200c0 114 92 206 205 206c103 0 187 -75 203 -172c111 26 232 -5 319 -91z
+M1536 78c0 -114 -92 -206 -205 -206c-100 0 -183 71 -202 165c-116 -36 -249 -8 -341 84l-11 12l151 152l12 -12c49 -49 129 -49 178 0s49 129 0 178l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30c87 -87 118 -210 90 -322c100 -14 177 -99 177 -203z
+M1534 1202c0 -104 -78 -190 -178 -204c33 -115 4 -244 -87 -335l-12 -12l-151 152l12 12c49 49 49 129 0 178s-129 49 -178 0l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30c91 91 221 120 337 86c14 100 100 177 204 177c113 0 205 -92 205 -206z" />
+ <glyph glyph-name="ethereum" unicode="&#xf2f3;" horiz-adv-x="1064"
+d="M1064 623l-532 -325l-532 325l532 913zM532 194l532 325l-532 -775l-532 775z" />
+ <glyph glyph-name="plus" unicode="&#xf067;" horiz-adv-x="1408"
+d="M1408 800v-192c0 -53 -43 -96 -96 -96h-416v-416c0 -53 -43 -96 -96 -96h-192c-53 0 -96 43 -96 96v416h-416c-53 0 -96 43 -96 96v192c0 53 43 96 96 96h416v416c0 53 43 96 96 96h192c53 0 96 -43 96 -96v-416h416c53 0 96 -43 96 -96z" />
+ <glyph glyph-name="list-ul" unicode="&#xf0ca;" horiz-adv-x="1792"
+d="M384 128c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM384 640c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1792 224v-192c0 -17 -15 -32 -32 -32h-1216c-17 0 -32 15 -32 32v192c0 17 15 32 32 32
+h1216c17 0 32 -15 32 -32zM384 1152c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM1792 736v-192c0 -17 -15 -32 -32 -32h-1216c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1216c17 0 32 -15 32 -32zM1792 1248v-192
+c0 -17 -15 -32 -32 -32h-1216c-17 0 -32 15 -32 32v192c0 17 15 32 32 32h1216c17 0 32 -15 32 -32z" />
+ <glyph glyph-name="play-circle-o" unicode="&#xf01d;"
+d="M1184 640c0 -23 -12 -44 -32 -55l-544 -320c-10 -6 -21 -9 -32 -9s-22 3 -32 8c-20 12 -32 33 -32 56v640c0 23 12 44 32 56c20 11 45 11 64 -1l544 -320c20 -11 32 -32 32 -55zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544
+s544 244 544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="joplin" unicode="&#xf310;"
+d="M288 1408h960c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288zM737 1171v-148l43 -1c59 -2 70 -6 81 -30c4 -10 5 -13 5 -296c0 -323 0 -323 -16 -362c-16 -38 -48 -69 -87 -83
+c-13 -5 -21 -5 -43 -6c-33 -1 -53 2 -80 15c-30 14 -50 37 -62 69c-9 24 -10 34 -12 88c-2 51 -1 56 -7 70c-9 23 -25 45 -40 56c-24 18 -49 24 -87 22c-40 -2 -68 -13 -95 -41c-23 -23 -35 -44 -44 -75c-4 -15 -5 -23 -5 -54c0 -38 1 -46 11 -79c26 -82 92 -156 178 -199
+c46 -23 85 -35 155 -44v0c20 -3 119 -3 142 0c87 10 150 32 208 71c73 49 127 125 142 199c8 40 9 47 10 343l1 291l6 13c6 15 15 24 29 28c5 2 28 3 52 4l43 1v74l-1 73l-263 1h-264z" />
+ <glyph glyph-name="mars-stroke" unicode="&#xf229;"
+d="M1472 1408c35 0 64 -29 64 -64v-416c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v262l-213 -214l140 -140c12 -13 12 -33 0 -45l-46 -46c-12 -12 -32 -12 -45 0l-140 141l-78 -79c79 -98 126 -223 126 -359c0 -318 -258 -576 -576 -576s-576 258 -576 576
+s258 576 576 576c136 0 261 -47 359 -126l78 78l-172 172c-12 13 -12 33 0 45l46 46c12 12 32 12 45 0l172 -172l213 213h-261c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h416zM576 0c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="road" unicode="&#xf018;" horiz-adv-x="1820"
+d="M1061 540v4l-24 320c-1 18 -17 32 -34 32h-186c-17 0 -33 -14 -34 -32l-24 -320v-4c-1 -16 14 -28 29 -28h244c15 0 30 12 29 28zM1820 73c0 -29 -8 -73 -46 -73h-704c17 0 31 14 30 32l-20 256c-1 18 -17 32 -34 32h-272c-17 0 -33 -14 -34 -32l-20 -256
+c-1 -18 13 -32 30 -32h-704c-38 0 -46 44 -46 73c0 40 11 80 26 116l417 1044c10 25 37 47 64 47h339c-17 0 -33 -14 -34 -32l-15 -192c-1 -18 12 -32 30 -32h166c18 0 31 14 30 32l-15 192c-1 18 -17 32 -34 32h339c27 0 54 -22 64 -47l417 -1044c15 -36 26 -76 26 -116z
+" />
+ <glyph glyph-name="volume-down" unicode="&#xf027;" horiz-adv-x="1152"
+d="M768 1184v-1088c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-333 333h-262c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h262l333 333c12 12 28 19 45 19c35 0 64 -29 64 -64zM1152 640c0 -100 -61 -197 -155 -235c-8 -4 -17 -5 -25 -5c-35 0 -64 28 -64 64
+c0 76 116 55 116 176s-116 100 -116 176c0 36 29 64 64 64c8 0 17 -1 25 -5c94 -37 155 -135 155 -235z" />
+ <glyph glyph-name="question-circle" unicode="&#xf059;"
+d="M896 160v192c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h192c18 0 32 14 32 32zM1152 832c0 183 -192 320 -364 320c-163 0 -285 -70 -371 -213c-9 -14 -5 -32 8 -42l132 -100c5 -4 12 -6 19 -6c9 0 19 4 25 12c47 60 67 78 86 92
+c17 12 50 24 86 24c64 0 123 -41 123 -85c0 -52 -27 -78 -88 -106c-71 -32 -168 -115 -168 -212v-36c0 -18 14 -32 32 -32h192c18 0 32 14 32 32c0 23 29 72 76 99c76 43 180 101 180 253zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768
+s768 -344 768 -768z" />
+ <glyph glyph-name="paypal" unicode="&#xf1ed;" horiz-adv-x="1519"
+d="M1510 890c13 -60 10 -129 -4 -204c-65 -330 -284 -444 -565 -444h-44c-34 0 -62 -25 -68 -59l-4 -19l-55 -346l-2 -15c-7 -34 -35 -59 -69 -59h-251c-28 0 -46 23 -42 51c18 112 35 224 53 336s36 223 54 335c3 24 19 37 43 37c40 0 80 1 131 0c72 -1 155 3 236 21
+c108 24 206 68 287 144c73 68 122 152 155 246c15 44 27 88 35 133c2 12 5 10 12 5c55 -41 86 -96 98 -162zM1338 1172c0 -82 -19 -160 -46 -236c-52 -151 -150 -259 -302 -315c-81 -29 -166 -41 -252 -42c-60 -1 -120 0 -180 0c-65 0 -106 -32 -118 -96
+c-14 -76 -69 -430 -85 -530c-1 -7 -4 -10 -12 -10h-295c-30 0 -52 26 -48 55l232 1471c6 38 40 67 79 67h598c43 0 142 -19 209 -45c142 -55 220 -167 220 -319z" />
+ <glyph glyph-name="child" unicode="&#xf1ae;" horiz-adv-x="1152"
+d="M1124 988l-292 -292v-824c0 -62 -50 -112 -112 -112s-112 50 -112 112v384h-64v-384c0 -62 -50 -112 -112 -112s-112 50 -112 112v824l-292 292c-37 38 -37 98 0 136c38 37 98 37 136 0l228 -228h368l228 228c38 37 98 37 136 0c37 -38 37 -98 0 -136zM800 1152
+c0 -124 -100 -224 -224 -224s-224 100 -224 224s100 224 224 224s224 -100 224 -224z" />
+ <glyph glyph-name="fork-awesome" unicode="&#xf2e3;" horiz-adv-x="1533"
+d="M766 1404v0c423 0 767 -343 767 -766v-1v-2c0 -8 -1 -17 -1 -25v-2c-14 -388 -318 -703 -701 -735v1c-18 -2 -47 -2 -65 -2s-47 1 -65 3v-2c-383 32 -685 347 -700 735v2c0 8 -1 17 -1 25v2v1c0 423 343 766 766 766zM594 1085h-66c-35 -251 -54 -525 -29 -712
+s145 -157 181 -351c5 -29 10 -59 14 -89c20 -2 52 -4 72 -4s52 2 72 4c4 30 9 60 14 89c36 194 156 164 181 351s6 456 -28 712h-65c3 -190 12 -430 -8 -640c-8 -89 -103 -87 -108 0c-13 208 -15 428 -26 639h-64c-11 -211 -18 -431 -26 -643c-3 -82 -100 -81 -108 0
+c-19 208 -10 453 -6 644z" />
+ <glyph glyph-name="angle-double-up" unicode="&#xf102;" horiz-adv-x="998"
+d="M998 224c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -14 -10 -23 -10c-8 0 -17 4 -23 10l-393 393l-393 -393c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23zM998 608
+c0 -8 -4 -17 -10 -23l-50 -50c-6 -6 -14 -10 -23 -10c-8 0 -17 4 -23 10l-393 393l-393 -393c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-50 50c-6 6 -10 15 -10 23s4 17 10 23l466 466c6 6 15 10 23 10s17 -4 23 -10l466 -466c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="bath" unicode="&#xf2cd;" horiz-adv-x="1792"
+d="M1664 448v-192c0 -114 -50 -215 -128 -286v-194c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v118c-40 -14 -83 -22 -128 -22h-768c-45 0 -88 8 -128 22v-110c0 -22 -14 -40 -32 -40h-64c-18 0 -32 18 -32 40v186c-78 71 -128 172 -128 286v192h1536zM704 864
+c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM768 928c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM704 992c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM832 992c0 -18 -14 -32 -32 -32s-32 14 -32 32
+s14 32 32 32s32 -14 32 -32zM768 1056c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM704 1120c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM1792 608v-64c0 -18 -14 -32 -32 -32h-1728c-18 0 -32 14 -32 32v64c0 18 14 32 32 32
+h96v640c0 141 115 256 256 256c72 0 137 -30 184 -78c62 25 136 16 191 -27l22 22c6 6 16 6 22 0l42 -42c6 -6 6 -16 0 -22l-314 -314c-6 -6 -16 -6 -22 0l-42 42c-6 6 -6 16 0 22l22 22c-48 61 -54 145 -17 212c-23 22 -54 35 -88 35c-71 0 -128 -57 -128 -128v-640h1504
+c18 0 32 -14 32 -32zM896 1056c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM832 1120c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM768 1184c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM960 1120
+c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM896 1184c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM832 1248c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM1024 1184c0 -18 -14 -32 -32 -32s-32 14 -32 32
+s14 32 32 32s32 -14 32 -32zM960 1248c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32zM1088 1248c0 -18 -14 -32 -32 -32s-32 14 -32 32s14 32 32 32s32 -14 32 -32z" />
+ <glyph glyph-name="reply-all" unicode="&#xf122;" horiz-adv-x="1792"
+d="M640 454v-70c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 6 -45 19l-512 512c-25 25 -25 65 0 90l512 512c18 19 46 24 70 14c23 -10 39 -33 39 -59v-69l-397 -398c-25 -25 -25 -65 0 -90zM1792 416c0 -208 -157 -514 -164 -527c-5 -11 -16 -17 -28 -17
+c-3 0 -6 0 -9 1c-15 5 -24 19 -23 34c29 273 -5 453 -106 565c-85 95 -223 146 -438 163v-251c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 6 -45 19l-512 512c-25 25 -25 65 0 90l512 512c18 19 46 24 70 14c23 -10 39 -33 39 -59v-262c276 -19 473 -92 599 -221
+c151 -155 169 -365 169 -509z" />
+ <glyph glyph-name="patreon" unicode="&#xf2f0;"
+d="M985 1341c-305 0 -553 -248 -553 -553c0 -304 248 -551 553 -551c304 0 551 247 551 551c0 305 -247 553 -551 553zM270 -132h-270v1473h270v-1473z" />
+ <glyph glyph-name="inbox" unicode="&#xf01c;"
+d="M1023 576h316c-2 5 -3 11 -5 16l-212 496h-708l-212 -496c-2 -5 -3 -11 -5 -16h316l95 -192h320zM1536 546v-482c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v482c0 36 11 89 25 123l238 552c14 33 54 59 89 59h832c35 0 75 -26 89 -59l238 -552
+c14 -34 25 -87 25 -123z" />
+ <glyph glyph-name="female" unicode="&#xf182;" horiz-adv-x="1280"
+d="M1280 480c0 -53 -43 -96 -96 -96c-32 0 -62 16 -80 43l-227 341h-45v-132l247 -411c6 -10 9 -21 9 -33c0 -35 -29 -64 -64 -64h-192v-272c0 -62 -50 -112 -112 -112h-160c-61 0 -112 50 -112 112v272h-192c-35 0 -64 29 -64 64c0 12 3 23 9 33l247 411v132h-45l-227 -341
+c-18 -27 -48 -43 -80 -43c-53 0 -96 43 -96 96c0 19 6 38 16 53l256 384c40 59 102 107 176 107h384c74 0 136 -48 176 -107l256 -384c10 -15 16 -34 16 -53zM864 1280c0 -124 -100 -224 -224 -224s-224 100 -224 224s100 224 224 224s224 -100 224 -224z" />
+ <glyph glyph-name="gavel" unicode="&#xf0e3;" horiz-adv-x="1731"
+d="M1731 0c0 -34 -14 -67 -37 -90l-107 -108c-24 -23 -57 -37 -91 -37s-67 14 -90 37l-363 364c-24 23 -38 56 -38 90c0 38 16 69 43 96l-256 256l-126 -126c-9 -9 -21 -14 -34 -14s-25 5 -34 14c30 -30 58 -52 58 -98c0 -26 -10 -49 -28 -68c-34 -36 -70 -84 -124 -84
+c-25 0 -50 10 -68 28l-408 408c-18 18 -28 43 -28 68c0 54 48 90 84 124c19 18 42 28 68 28c46 0 68 -28 98 -58c-9 9 -14 21 -14 34s5 25 14 34l348 348c9 9 21 14 34 14s25 -5 34 -14c-30 30 -58 52 -58 98c0 26 10 49 28 68c34 36 70 84 124 84c25 0 50 -10 68 -28
+l408 -408c18 -18 28 -43 28 -68c0 -54 -48 -90 -84 -124c-19 -18 -42 -28 -68 -28c-46 0 -68 28 -98 58c9 -9 14 -21 14 -34s-5 -25 -14 -34l-126 -126l256 -256c27 27 58 43 96 43c34 0 67 -14 91 -37l363 -363c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="jsfiddle" unicode="&#xf1cc;" horiz-adv-x="2048"
+d="M1800 764c145 -60 248 -202 248 -367c0 -219 -181 -397 -403 -397c-8 0 -15 1 -22 1h-1217c-224 13 -406 184 -406 406c0 149 81 279 202 350c-8 26 -12 53 -12 82c0 153 125 277 281 277c64 0 124 -22 172 -58c98 202 306 342 549 342c337 0 609 -269 609 -600
+c0 -12 -1 -24 -1 -36zM468 498c0 -169 133 -264 292 -264c98 0 169 31 240 99c-29 36 -61 71 -91 107c-41 -40 -86 -65 -144 -65c-71 0 -132 47 -132 121c0 73 61 121 130 121c220 0 267 -384 587 -384c156 0 288 98 288 262c0 166 -133 263 -291 263
+c-98 0 -171 -28 -241 -97c32 -35 62 -72 93 -108c40 39 85 64 142 64c66 0 132 -47 132 -117c0 -77 -56 -126 -131 -126c-213 0 -270 384 -582 384c-155 0 -292 -95 -292 -260z" />
+ <glyph glyph-name="git" unicode="&#xf1d3;" horiz-adv-x="1656"
+d="M527 22c0 88 -97 100 -165 100c-71 0 -158 -15 -158 -104c0 -90 103 -101 172 -101c73 0 151 18 151 105zM468 777c0 75 -36 143 -119 143c-92 0 -124 -61 -124 -145c0 -83 36 -135 124 -135c87 0 119 56 119 137zM737 1101v-202c-26 -9 -52 -16 -79 -22
+c10 -27 16 -55 16 -84c0 -169 -104 -298 -270 -329c-50 -10 -79 -31 -79 -85c0 -153 404 -49 404 -331c0 -229 -155 -304 -363 -304c-171 0 -366 57 -366 263c0 120 73 189 182 225v4c-46 28 -67 72 -67 126c0 51 11 114 63 137v4c-101 34 -167 173 -167 274
+c0 187 145 324 330 324c62 0 124 -16 178 -47c75 0 149 20 218 47zM1055 220h-222c4 45 4 89 4 134v609c0 43 1 86 -4 128h222c-5 -41 -4 -83 -4 -124v-613c0 -45 0 -89 4 -134zM1656 442v-196c-53 -29 -114 -39 -174 -39c-214 0 -239 169 -239 343v351h2v4
+c-13 0 -25 2 -37 2c-20 0 -40 -3 -59 -6v190h96v76c0 30 -1 60 -6 89h227c-8 -55 -6 -110 -6 -165h171v-190c-29 0 -58 4 -86 4h-85v-365c0 -59 13 -131 87 -131c39 0 77 11 109 33zM1080 1389c0 -75 -58 -145 -135 -145c-79 0 -138 69 -138 145c0 77 58 147 138 147
+c79 0 135 -72 135 -147z" />
+ <glyph glyph-name="signalapp" unicode="&#xf30c;" horiz-adv-x="1652"
+d="M710 1400c32 4 84 8 116 8v0c27 0 53 -2 80 -4l-3 -42c-21 2 -56 3 -77 3c-31 0 -81 -3 -111 -7zM977 1351l8 43c54 -10 138 -36 188 -58l-17 -39c-48 21 -128 45 -179 54zM446 1321c49 24 133 54 186 66l10 -42c-51 -11 -130 -39 -177 -62zM1223 1264l21 37
+c48 -27 120 -78 160 -115l-29 -32c-38 35 -106 85 -152 110zM222 1161c39 39 108 93 155 122l22 -36c-44 -27 -110 -79 -147 -116l-30 30v0zM1427 1101l32 28c37 -41 87 -114 112 -163l-38 -20c-24 46 -71 116 -106 155v0zM65 934c23 50 69 125 104 168l33 -27
+c-33 -40 -77 -112 -98 -159zM1564 878l39 15c20 -52 41 -138 46 -193l-43 -4c-5 52 -23 133 -42 182zM0 664c3 55 19 143 36 196l41 -14c-16 -49 -32 -132 -34 -184zM1582 436c14 50 26 133 27 185h43c-1 -55 -14 -144 -29 -197zM-0 585l43 2c2 -70 10 -131 23 -187l-42 -11
+c-14 59 -22 123 -24 196zM1464 203c32 41 73 114 93 162l40 -16c-21 -51 -66 -128 -99 -172zM47 313l40 15c22 -60 52 -113 92 -160l-33 -28c-43 51 -75 108 -99 173v0zM1273 26c44 28 107 82 143 120l31 -29c-37 -40 -105 -97 -151 -127zM202 82l28 32
+c12 -11 34 -28 47 -38c4 -3 6 -7 7 -11l40 -125l-41 -13l-37 118c-13 10 -32 26 -44 37v0zM1033 -80c50 13 129 44 175 68l20 -39c-48 -25 -131 -56 -184 -70zM644 -86c2 1 7 2 9 2s3 -1 5 -1c17 -5 31 -8 42 -11l-9 -42c-10 2 -27 7 -37 10l-128 -57l-18 40l136 59v0z
+M826 -106c45 0 90 4 134 11l7 -42c-39 -6 -102 -12 -141 -12c-22 0 -40 0 -55 1l2 43c15 -1 31 -1 53 -1v0zM357 -256v0v0c-9 0 -17 7 -20 15l-30 93l41 13l23 -70l67 29l17 -39l-89 -39c-2 -1 -7 -2 -9 -2zM442 -65c-11 0 -21 8 -22 19l-16 213c-70 53 -124 122 -161 204
+c-37 81 -56 171 -56 268c0 332 292 602 651 602s651 -270 651 -602s-292 -602 -651 -602c-60 0 -119 8 -176 23l-209 -123c-3 -2 -7 -2 -11 -2v0z" />
+ <glyph glyph-name="share-square" unicode="&#xf14d;"
+d="M1005 435l352 352c25 25 25 65 0 90l-352 352c-18 19 -46 24 -69 14c-24 -10 -40 -33 -40 -59v-160c-574 0 -640 -329 -640 -576c0 -201 161 -396 167 -404c7 -8 16 -12 25 -12c4 0 9 1 13 3c13 5 21 19 19 33c-30 241 -11 391 62 473c61 69 167 99 354 99v-160
+c0 -26 16 -49 40 -59c7 -3 16 -5 24 -5c17 0 33 7 45 19zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960c159 0 288 -129 288 -288z" />
+ <glyph glyph-name="thermometer-half" unicode="&#xf2c9;" horiz-adv-x="1024"
+d="M640 192c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 80 50 153 128 181v395h128v-395c78 -28 128 -101 128 -181zM768 192c0 105 -50 197 -128 256v768c0 106 -86 192 -192 192s-192 -86 -192 -192v-768c-78 -59 -128 -151 -128 -256c0 -177 143 -320 320 -320
+s320 143 320 320zM896 192c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 122 49 232 128 313v711c0 177 143 320 320 320s320 -143 320 -320v-711c79 -81 128 -191 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z
+" />
+ <glyph glyph-name="question" unicode="&#xf128;" horiz-adv-x="924"
+d="M608 280v-240c0 -22 -18 -40 -40 -40h-240c-22 0 -40 18 -40 40v240c0 22 18 40 40 40h240c22 0 40 -18 40 -40zM924 880c0 -190 -129 -263 -224 -316c-59 -34 -96 -103 -96 -132c0 -22 -17 -48 -40 -48h-240c-22 0 -36 34 -36 56v45c0 121 120 225 208 265
+c77 35 109 68 109 132c0 56 -73 106 -154 106c-45 0 -86 -14 -108 -29c-24 -17 -48 -41 -107 -115c-8 -10 -20 -16 -31 -16c-9 0 -17 3 -25 8l-164 125c-17 13 -21 35 -10 53c108 179 260 266 464 266c214 0 454 -171 454 -400z" />
+ <glyph glyph-name="low-vision" unicode="&#xf2a8;" horiz-adv-x="1792"
+d="M335 180c-2 0 -4 1 -6 2c-117 78 -234 206 -308 325c-14 20 -21 44 -21 69c0 52 36 94 65 133c116 158 271 288 452 365c-15 27 -110 193 -110 211c0 12 7 23 17 29c20 11 110 64 128 64c11 0 22 -6 28 -16l124 -229c63 13 128 19 192 19c362 0 684 -205 876 -507
+c13 -20 20 -44 20 -69s-7 -49 -20 -69c-119 -187 -293 -342 -497 -429c15 -27 110 -193 110 -211c0 -12 -6 -23 -17 -29c-20 -11 -110 -64 -127 -64c-12 0 -23 6 -29 16l-124 229l-64 119l-444 820l7 7c-34 -14 -67 -29 -99 -47c12 -23 489 -899 489 -906c0 -5 -4 -8 -9 -9
+c-22 -5 -50 -3 -72 -3c-11 0 -56 -2 -60 7l-456 841c-29 -21 -56 -44 -82 -68c22 -39 404 -742 404 -748c0 -8 -5 -10 -11 -10c-17 0 -150 41 -155 50l-106 197l-224 413c-28 -34 -54 -69 -78 -106c13 -19 30 -39 41 -59c14 -26 176 -321 176 -327c0 -5 -5 -10 -10 -10z
+M1165 282l49 -91c187 76 341 216 450 385c-111 171 -269 313 -459 389c89 -85 139 -202 139 -325c0 -141 -66 -274 -179 -358zM848 896c0 -26 22 -48 48 -48c55 0 108 -22 147 -61s61 -92 61 -147c0 -26 22 -48 48 -48s48 22 48 48c0 168 -136 304 -304 304
+c-26 0 -48 -22 -48 -48zM1214 961l-9 4l7 -7z" />
+ <glyph glyph-name="camera" unicode="&#xf030;" horiz-adv-x="1920"
+d="M960 864c159 0 288 -129 288 -288s-129 -288 -288 -288s-288 129 -288 288s129 288 288 288zM1664 1280c141 0 256 -115 256 -256v-896c0 -141 -115 -256 -256 -256h-1408c-141 0 -256 115 -256 256v896c0 141 115 256 256 256h224l51 136c25 66 103 120 173 120h512
+c70 0 148 -54 173 -120l51 -136h224zM960 128c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="wordpress" unicode="&#xf19a;" horiz-adv-x="1792"
+d="M127 640c0 111 24 217 67 313l367 -1005c-257 125 -434 388 -434 692zM1415 679c0 -66 -27 -142 -59 -249l-76 -256l-278 826s46 3 88 8c41 5 36 66 -5 63c-125 -9 -205 -10 -205 -10s-75 1 -202 10c-42 3 -47 -60 -5 -63c39 -4 80 -8 80 -8l120 -328l-168 -504l-280 832
+s46 3 88 8c41 5 36 66 -5 63c-124 -9 -205 -10 -205 -10c-14 0 -31 1 -49 1c137 209 373 347 642 347c200 0 382 -77 519 -202h-10c-75 0 -129 -65 -129 -136c0 -63 37 -116 76 -180c30 -51 63 -117 63 -212zM909 573l237 -647c1 -4 3 -8 5 -11c-80 -28 -165 -44 -255 -44
+c-75 0 -148 11 -217 32zM1570 1009c60 -110 95 -235 95 -369c0 -284 -154 -531 -383 -664l235 678c39 112 59 198 59 276c0 28 -2 54 -6 79zM896 1536c494 0 896 -402 896 -896s-402 -896 -896 -896s-896 402 -896 896s402 896 896 896zM896 -215c471 0 855 384 855 855
+s-384 855 -855 855s-855 -384 -855 -855s384 -855 855 -855z" />
+ <glyph glyph-name="italic" unicode="&#xf033;" horiz-adv-x="1024"
+d="M0 -126l17 85c64 20 133 28 193 59c23 29 34 66 41 101c13 68 231 1049 228 1129v25c-55 30 -122 22 -182 32l19 103c129 -6 260 -16 390 -16c106 0 212 10 318 16c-4 -30 -11 -60 -19 -89c-69 -24 -142 -35 -210 -62c-22 -54 -27 -113 -37 -170
+c-48 -259 -112 -518 -165 -775c-10 -48 -59 -247 -55 -289l1 -18c61 -14 123 -21 185 -31c-2 -33 -8 -66 -16 -99c-22 0 -43 -3 -65 -3c-57 0 -116 19 -173 20c-69 1 -138 2 -206 2c-89 0 -176 -15 -264 -20z" />
+ <glyph glyph-name="forward" unicode="&#xf04e;" horiz-adv-x="1542"
+d="M45 -115c-25 -25 -45 -16 -45 19v1472c0 35 20 44 45 19l710 -710c6 -6 10 -12 13 -19v710c0 35 20 44 45 19l710 -710c25 -25 25 -65 0 -90l-710 -710c-25 -25 -45 -16 -45 19v710c-3 -7 -7 -13 -13 -19z" />
+ <glyph glyph-name="steam-square" unicode="&#xf1b7;"
+d="M1242 889c0 106 -87 193 -194 193c-106 0 -193 -87 -193 -193c0 -107 87 -193 193 -193c107 0 194 86 194 193zM632 301c0 -110 -88 -198 -198 -198c-76 0 -142 43 -175 106c33 -13 65 -26 98 -40c80 -32 172 7 205 88c32 80 -7 172 -88 204l-82 33c13 3 28 5 42 5
+c110 0 198 -88 198 -198zM1536 1120v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v153l172 -69c26 -121 134 -212 262 -212c140 0 255 107 268 243l345 252c200 0 361 162 361 360c0 200 -161 361 -361 361c-197 0 -358 -160 -360 -357l-225 -322
+c-9 1 -18 1 -28 1c-50 0 -97 -13 -137 -37l-297 119v468c0 159 129 288 288 288h960c159 0 288 -129 288 -288zM1289 887c0 -133 -108 -241 -242 -241c-133 0 -241 108 -241 241c0 134 108 242 241 242c134 0 242 -108 242 -242z" />
+ <glyph glyph-name="medium-square" unicode="&#xf2f8;"
+d="M0 1404h1536v-1536h-1536v1536zM257 1057v-17l97 -116c7 -7 13 -20 13 -30v-4v-456v-9c0 -12 -6 -28 -14 -36l-109 -132v-17h308v17l-109 132c-9 9 -15 26 -15 38v7v395l270 -589h31l232 589v-469c0 -13 0 -16 -8 -24l-84 -80v-18h405v18l-80 79c-5 4 -10 12 -10 19
+c0 1 1 3 1 4v580c0 1 -1 3 -1 4c0 7 5 15 10 19l82 79v17h-285l-203 -507l-232 507h-299z" />
+ <glyph glyph-name="sort-numeric-desc" unicode="&#xf163;" horiz-adv-x="1454"
+d="M1314 1247c0 82 -67 169 -147 169c-70 0 -114 -57 -114 -131c0 -72 46 -133 141 -133c65 0 120 39 120 95zM704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192
+c18 0 32 -14 32 -32v-1376h192c18 0 32 -14 32 -32zM1424 -142v-114h-469v114h167v432c0 13 1 26 1 36v16h-2l-7 -12c-5 -8 -13 -18 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1454 1189c0 -202 -110 -421 -348 -421c-45 0 -82 7 -108 16c-16 5 -30 10 -42 15l39 113
+c9 -4 20 -8 31 -11c20 -7 46 -13 75 -13c120 0 182 100 201 204h-2c-28 -30 -87 -51 -146 -51c-145 0 -240 114 -240 244c0 138 106 251 253 251c159 0 287 -130 287 -347z" />
+ <glyph glyph-name="video-camera" unicode="&#xf03d;" horiz-adv-x="1792"
+d="M1792 1184v-1088c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 6 -45 19l-403 403v-166c0 -159 -129 -288 -288 -288h-704c-159 0 -288 129 -288 288v704c0 159 129 288 288 288h704c159 0 288 -129 288 -288v-165l403 402c12 13 28 19 45 19c8 0 17 -2 25 -5
+c23 -10 39 -33 39 -59z" />
+ <glyph glyph-name="thumbs-down" unicode="&#xf165;" horiz-adv-x="1600"
+d="M256 960c0 36 -29 64 -64 64c-36 0 -64 -28 -64 -64c0 -35 28 -64 64 -64c35 0 64 29 64 64zM416 448c0 -35 -29 -64 -64 -64h-288c-35 0 -64 29 -64 64v640c0 35 29 64 64 64h288c35 0 64 -29 64 -64v-640zM1545 597c34 -38 55 -96 55 -149c-1 -104 -88 -192 -192 -192
+h-277c8 -32 18 -42 29 -64c26 -52 56 -110 56 -192c0 -77 0 -256 -224 -256c-17 0 -33 7 -45 19c-43 42 -55 104 -66 163c-12 58 -23 118 -62 157c-31 31 -65 74 -101 120c-44 58 -140 177 -177 180c-33 3 -61 31 -61 64v641c0 35 30 63 64 64c35 1 95 22 158 44
+c108 37 243 84 386 84h129c88 -1 154 -27 197 -78c38 -45 55 -106 49 -181c25 -24 44 -57 54 -94c11 -40 11 -80 0 -117c30 -40 45 -87 43 -137c0 -14 -4 -44 -15 -76z" />
+ <glyph glyph-name="medium" unicode="&#xf23a;"
+d="M182 999v6c0 15 -8 34 -19 44l-144 173v26h446l344 -755l302 755h425v-26l-123 -117c-8 -6 -14 -19 -14 -29c0 -2 1 -4 1 -6v-864c0 -2 -1 -4 -1 -6c0 -10 6 -23 14 -29l120 -117v-26h-602v26l124 120c12 12 12 16 12 35v698l-345 -876h-47l-401 876v-587
+c0 -3 -1 -8 -1 -11c0 -18 10 -44 23 -57l162 -195v-26h-458v26l161 195c12 13 22 38 22 55c0 4 0 9 -1 13v679z" />
+ <glyph glyph-name="chevron-right" unicode="&#xf054;" horiz-adv-x="1036"
+d="M1017 659l-742 -742c-25 -25 -65 -25 -90 0l-166 166c-25 25 -25 65 0 90l531 531l-531 531c-25 25 -25 65 0 90l166 166c25 25 65 25 90 0l742 -742c25 -25 25 -65 0 -90z" />
+ <glyph glyph-name="bus" unicode="&#xf207;"
+d="M384 320c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1408 320c0 71 -57 128 -128 128s-128 -57 -128 -128s57 -128 128 -128s128 57 128 128zM1362 716l-72 384c-6 30 -32 52 -63 52h-918c-31 0 -57 -22 -63 -52l-72 -384
+c-7 -40 23 -76 63 -76h1062c40 0 70 36 63 76zM1136 1328c0 27 -21 48 -48 48h-640c-26 0 -48 -21 -48 -48s22 -48 48 -48h640c27 0 48 21 48 48zM1536 603v-603h-128v-128c0 -71 -57 -128 -128 -128s-128 57 -128 128v128h-768v-128c0 -71 -57 -128 -128 -128
+s-128 57 -128 128v128h-128v603c0 82 7 143 25 223l103 454c19 160 299 256 640 256s621 -96 640 -256l105 -454c18 -80 23 -141 23 -223z" />
+ <glyph glyph-name="registered" unicode="&#xf25d;" horiz-adv-x="1792"
+d="M1042 833c0 58 -20 99 -60 121c-20 11 -48 18 -117 18h-123v-281h162c88 0 138 52 138 142zM1094 548l205 -373c5 -10 5 -22 -1 -31c-5 -10 -16 -16 -27 -16h-152c-12 0 -23 6 -28 17l-194 365h-155v-350c0 -18 -14 -32 -32 -32h-134c-18 0 -32 14 -32 32v960
+c0 18 14 32 32 32h294c105 0 151 -9 190 -24c113 -42 183 -153 183 -289c0 -123 -61 -227 -158 -275c3 -5 6 -10 9 -16zM896 1376c-406 0 -736 -330 -736 -736s330 -736 736 -736s736 330 736 736s-330 736 -736 736zM1792 640c0 -495 -401 -896 -896 -896
+s-896 401 -896 896s401 896 896 896s896 -401 896 -896z" />
+ <glyph glyph-name="mars" unicode="&#xf222;"
+d="M1472 1408c35 0 64 -29 64 -64v-416c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v262l-382 -383c79 -98 126 -223 126 -359c0 -318 -258 -576 -576 -576s-576 258 -576 576s258 576 576 576c136 0 261 -47 359 -126l382 382h-261c-18 0 -32 14 -32 32v64
+c0 18 14 32 32 32h416zM576 0c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="hand-rock-o" unicode="&#xf255;"
+d="M768 1152c-71 0 -128 -57 -128 -128v-128h-32v93c0 63 -48 115 -112 115c-62 0 -112 -50 -112 -112v-429l-32 30v172c0 63 -48 115 -112 115c-62 0 -112 -50 -112 -112v-224c0 -31 13 -60 35 -82l310 -296c29 -29 39 -62 39 -102c0 -35 29 -64 64 -64h640
+c35 0 64 29 64 64v25c0 26 3 52 10 77l108 436c7 25 10 51 10 77v246c0 63 -48 115 -112 115c-62 0 -112 -50 -112 -112v-32h-32v125c0 53 -36 102 -89 113c-7 1 -15 2 -23 2c-62 0 -112 -50 -112 -112v-128h-32v122c0 67 -48 126 -115 133c-5 1 -9 1 -13 1zM768 1280
+c54 0 106 -17 149 -50c37 22 80 34 123 34c79 0 152 -38 197 -103c19 5 39 7 59 7c134 0 240 -110 240 -243v-246c0 -36 -5 -73 -13 -108l-109 -436c-6 -24 -6 -47 -6 -71c0 -106 -86 -192 -192 -192h-640c-114 0 -192 91 -192 201l-308 296c-47 45 -76 109 -76 175v224
+c0 132 108 240 240 240c6 0 11 0 16 -1c8 127 114 225 240 225c34 0 67 -7 98 -21c47 45 109 69 174 69z" />
+ <glyph glyph-name="window-close" unicode="&#xf2d3;" horiz-adv-x="1792"
+d="M1175 215l146 146c13 13 13 33 0 46l-233 233l233 233c13 13 13 33 0 46l-146 146c-13 13 -33 13 -46 0l-233 -233l-233 233c-13 13 -33 13 -46 0l-146 -146c-13 -13 -13 -33 0 -46l233 -233l-233 -233c-13 -13 -13 -33 0 -46l146 -146c13 -13 33 -13 46 0l233 233
+l233 -233c13 -13 33 -13 46 0zM1792 1248v-1216c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="link" unicode="&#xf0c1;" horiz-adv-x="1632"
+d="M1440 320c0 26 -10 50 -28 68l-208 208c-18 18 -43 28 -68 28c-29 0 -52 -11 -72 -32c33 -33 72 -61 72 -112c0 -53 -43 -96 -96 -96c-51 0 -79 39 -112 72c-21 -20 -33 -43 -33 -73c0 -25 10 -50 28 -68l206 -207c18 -18 43 -27 68 -27s50 9 68 26l147 146
+c18 18 28 42 28 67zM737 1025c0 25 -10 50 -28 68l-206 207c-18 18 -43 28 -68 28s-50 -10 -68 -27l-147 -146c-18 -18 -28 -42 -28 -67c0 -26 10 -50 28 -68l208 -208c18 -18 43 -27 68 -27c29 0 52 10 72 31c-33 33 -72 61 -72 112c0 53 43 96 96 96c51 0 79 -39 112 -72
+c21 20 33 43 33 73zM1632 320c0 -76 -31 -150 -85 -203l-147 -146c-54 -54 -127 -83 -203 -83c-77 0 -150 30 -204 85l-206 207c-54 54 -83 127 -83 203c0 79 32 154 88 209l-88 88c-55 -56 -129 -88 -208 -88c-76 0 -150 30 -204 84l-208 208c-55 55 -84 127 -84 204
+c0 76 31 150 85 203l147 146c54 54 127 83 203 83c77 0 150 -30 204 -85l206 -207c54 -54 83 -127 83 -203c0 -79 -32 -154 -88 -209l88 -88c55 56 129 88 208 88c76 0 150 -30 204 -84l208 -208c55 -55 84 -127 84 -204z" />
+ <glyph glyph-name="window-minimize" unicode="&#xf2d1;" horiz-adv-x="1792"
+d="M1792 224v-192c0 -88 -72 -160 -160 -160h-1472c-88 0 -160 72 -160 160v192c0 88 72 160 160 160h1472c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="eyedropper" unicode="&#xf1fb;" horiz-adv-x="1792"
+d="M1698 1442c125 -125 126 -328 0 -452l-225 -223l104 -104c13 -13 13 -33 0 -46l-210 -210c-13 -13 -33 -13 -46 0l-105 105l-603 -603c-24 -24 -56 -37 -90 -37h-203l-256 -128l-64 64l128 256v203c0 34 13 66 37 90l603 603l-105 105c-13 13 -13 33 0 46l210 210
+c13 13 33 13 46 0l104 -104l223 225c124 126 327 125 452 0zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+ <glyph glyph-name="bug" unicode="&#xf188;" horiz-adv-x="1600"
+d="M1600 576c0 -35 -29 -64 -64 -64h-224c0 -125 -27 -219 -67 -290l208 -209c25 -25 25 -65 0 -90c-12 -13 -29 -19 -45 -19s-33 6 -45 19l-198 197s-131 -120 -301 -120v896h-128v-896c-181 0 -313 132 -313 132l-183 -207c-13 -14 -30 -21 -48 -21c-15 0 -30 5 -43 16
+c-26 24 -28 64 -5 91l202 227c-35 69 -58 158 -58 274h-224c-35 0 -64 29 -64 64s29 64 64 64h224v294l-173 173c-25 25 -25 65 0 90s65 25 90 0l173 -173h844l173 173c25 25 65 25 90 0s25 -65 0 -90l-173 -173v-294h224c35 0 64 -29 64 -64zM1120 1152h-640
+c0 177 143 320 320 320s320 -143 320 -320z" />
+ <glyph glyph-name="angellist" unicode="&#xf209;" horiz-adv-x="1258"
+d="M942 1158l-114 -328l117 -21c30 82 165 451 165 518c0 25 -8 56 -38 56c-56 0 -116 -182 -130 -225zM643 471c11 -29 23 -58 33 -88c22 25 45 48 71 67c-35 7 -70 10 -104 21zM351 1367c0 -102 121 -420 159 -521c14 8 32 10 49 10c24 0 51 -3 75 -5l-121 351
+c-13 38 -71 220 -123 220c-27 0 -39 -32 -39 -55zM272 608c0 -73 196 -342 269 -342c20 0 37 22 37 40c0 23 -23 80 -32 102c-26 67 -121 274 -203 274c-27 0 -71 -47 -71 -74zM114 273c0 -36 12 -71 25 -104c79 -195 257 -309 465 -309c152 0 280 58 382 170
+c108 120 152 268 152 427c0 56 1 145 -43 185c-84 74 -369 102 -482 102c-14 0 -38 -1 -49 -11c-12 -5 -12 -24 -12 -35c0 -153 323 -139 420 -139c19 0 28 -5 40 -19c13 -16 17 -35 19 -55c-26 -26 -62 -41 -96 -54c-33 -12 -65 -25 -93 -46c-77 -56 -153 -152 -153 -251
+c0 -62 37 -115 37 -176c0 -1 -7 -23 -7 -26c-114 8 -142 121 -146 216c-12 -3 -28 -2 -41 -2c2 -7 2 -14 2 -21c0 -73 -65 -126 -135 -126c-108 0 -251 127 -251 237c0 30 13 47 33 67c20 -25 41 -50 60 -76c29 -39 79 -104 133 -104c14 0 41 12 41 29
+c0 45 -164 256 -204 256c-63 0 -97 -83 -97 -135zM0 264c0 130 50 216 179 251c-11 29 -28 73 -28 104c0 82 101 184 183 184c24 0 48 -7 70 -15c-42 119 -163 454 -163 567c0 101 51 181 160 181c140 0 299 -504 333 -604c44 110 182 571 338 571c98 0 153 -78 153 -171
+c0 -106 -118 -436 -159 -550c168 -41 192 -177 192 -328c0 -400 -255 -710 -668 -710c-76 0 -151 15 -223 42c-190 72 -367 267 -367 478z" />
+ <glyph glyph-name="chain-broken" unicode="&#xf127;" horiz-adv-x="1664"
+d="M439 265l-256 -256c-7 -6 -15 -9 -23 -9s-16 3 -23 9c-12 13 -12 33 0 46l256 256c13 12 33 12 46 0c12 -13 12 -33 0 -46zM608 224v-320c0 -18 -14 -32 -32 -32s-32 14 -32 32v320c0 18 14 32 32 32s32 -14 32 -32zM384 448c0 -18 -14 -32 -32 -32h-320
+c-18 0 -32 14 -32 32s14 32 32 32h320c18 0 32 -14 32 -32zM1648 320c0 -77 -30 -149 -85 -203l-147 -146c-54 -54 -126 -83 -203 -83s-150 30 -204 85l-334 335c-17 17 -30 36 -42 56l239 18l273 -274c36 -36 100 -37 136 -1l147 146c18 18 28 42 28 67c0 26 -10 50 -28 68
+l-274 275l18 239c20 -12 39 -25 56 -42l336 -336c54 -55 84 -127 84 -204zM1031 1044l-239 -18l-273 274c-18 18 -42 28 -68 28s-50 -10 -68 -27l-147 -146c-18 -18 -28 -42 -28 -67c0 -26 10 -50 28 -68l274 -274l-18 -240c-20 12 -39 25 -56 42l-336 336
+c-54 55 -84 127 -84 204s30 149 85 203l147 146c54 54 126 83 203 83s150 -30 204 -85l334 -335c17 -17 30 -36 42 -56zM1664 960c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32s14 32 32 32h320c18 0 32 -14 32 -32zM1120 1504v-320c0 -18 -14 -32 -32 -32
+s-32 14 -32 32v320c0 18 14 32 32 32s32 -14 32 -32zM1527 1353l-256 -256c-7 -6 -15 -9 -23 -9s-16 3 -23 9c-12 13 -12 33 0 46l256 256c13 12 33 12 46 0c12 -13 12 -33 0 -46z" />
+ <glyph glyph-name="info" unicode="&#xf129;" horiz-adv-x="640"
+d="M640 192v-128c0 -35 -29 -64 -64 -64h-512c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h64v384h-64c-35 0 -64 29 -64 64v128c0 35 29 64 64 64h384c35 0 64 -29 64 -64v-576h64c35 0 64 -29 64 -64zM512 1344v-192c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v192
+c0 35 29 64 64 64h256c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="tumblr" unicode="&#xf173;" horiz-adv-x="956"
+d="M876 207l80 -237c-30 -45 -166 -96 -288 -98c-363 -6 -500 258 -500 444v544h-168v215c252 91 313 319 327 449c1 8 8 12 12 12h244v-424h333v-252h-334v-518c0 -70 26 -167 160 -164c44 1 103 14 134 29z" />
+ <glyph glyph-name="line-chart" unicode="&#xf201;" horiz-adv-x="2048"
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435c0 -28 -34 -43 -55 -22l-121 121l-633 -633c-13 -13 -33 -13 -46 0l-233 233l-416 -416l-192 192l585 585c13 13 33 13 46 0l233 -233l464 464l-121 121c-21 21 -6 55 22 55h435c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="long-arrow-up" unicode="&#xf176;" horiz-adv-x="767"
+d="M765 1043c-5 -11 -16 -19 -29 -19h-224v-1248c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v1248h-224c-13 0 -24 7 -29 19s-3 25 5 35l350 384c6 6 14 10 23 10s18 -4 24 -10l355 -384c8 -10 10 -23 5 -35z" />
+ <glyph glyph-name="simplybuilt" unicode="&#xf215;" horiz-adv-x="2048"
+d="M863 504c0 150 -121 271 -271 271c-149 0 -270 -121 -270 -271c0 -149 121 -270 270 -270c150 0 271 121 271 270zM1726 505c0 149 -121 270 -270 270c-150 0 -271 -121 -271 -270c0 -150 121 -271 271 -271c149 0 270 121 270 271zM2048 1314v-1348
+c0 -59 -48 -107 -108 -107h-1832c-60 0 -108 48 -108 107v1348c0 59 48 107 108 107h431c59 0 108 -48 108 -107v-161h754v161c0 59 49 107 108 107h431c60 0 108 -48 108 -107z" />
+ <glyph glyph-name="trash" unicode="&#xf1f8;" horiz-adv-x="1408"
+d="M512 160v704c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM768 160v704c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1024 160v704c0 18 -14 32 -32 32h-64
+c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM480 1152h448l-48 117c-3 4 -12 10 -17 11h-317c-6 -1 -14 -7 -17 -11zM1408 1120v-64c0 -18 -14 -32 -32 -32h-96v-948c0 -110 -72 -204 -160 -204h-832c-88 0 -160 90 -160 200v952h-96
+c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h309l70 167c20 49 80 89 133 89h320c53 0 113 -40 133 -89l70 -167h309c18 0 32 -14 32 -32z" />
+ <glyph glyph-name="free-code-camp" unicode="&#xf2c5;" horiz-adv-x="2304"
+d="M453 -101c0 -28 -25 -54 -53 -54c-4 0 -9 2 -13 3c-56 13 -128 97 -162 140c-156 197 -225 427 -225 676c0 232 70 431 213 614c33 43 131 156 189 156c25 0 51 -20 51 -46c0 -30 -44 -71 -63 -90c-55 -57 -106 -115 -147 -184c-85 -142 -119 -284 -119 -449
+c0 -177 33 -337 123 -491c38 -65 83 -119 136 -173c21 -23 70 -68 70 -102zM1796 33c0 -37 -25 -68 -64 -68h-1081c-35 0 -64 29 -64 64c0 37 25 68 64 68h1081c35 0 64 -29 64 -64zM1581 644c0 -84 -19 -162 -67 -233c-33 -49 -100 -112 -153 -139c-8 -5 -18 -10 -27 -10
+c-8 0 -23 9 -23 18c0 29 122 98 122 232c0 44 -11 93 -35 130c-7 10 -32 42 -46 42c-3 0 -3 -2 -3 -5c0 -24 15 -47 15 -72c0 -32 -39 -48 -66 -48c-47 0 -66 33 -66 76c0 29 3 59 3 88c0 21 -1 27 -10 46c-14 27 -60 82 -93 82c-9 0 -12 0 -12 -9c0 -14 32 -29 32 -80
+c0 -133 -183 -157 -183 -290c0 -60 8 -110 42 -160c21 -31 44 -49 79 -63c9 -3 18 -4 18 -15s-9 -16 -18 -16c-5 0 -28 9 -33 11c-154 56 -271 190 -271 358c0 199 239 373 239 564c0 37 -6 63 -25 94c-11 18 -38 53 -56 64c-8 4 -19 11 -19 21c0 17 29 20 41 20
+c36 0 77 -13 110 -29c139 -66 168 -167 192 -307c6 -33 18 -138 66 -138c31 0 51 21 51 51c0 45 -40 94 -40 119c0 7 4 10 10 10c25 0 77 -53 93 -70c97 -103 133 -203 133 -342zM2304 615c0 -176 -47 -352 -138 -503c-42 -70 -180 -266 -271 -266c-21 0 -46 26 -46 47
+c0 34 117 143 146 180c124 156 183 332 183 531c0 164 -20 297 -93 446c-45 92 -92 154 -163 228c-23 24 -73 69 -73 105c0 25 26 52 51 52c66 0 161 -122 196 -169c134 -180 191 -365 206 -587c1 -21 2 -43 2 -64z" />
+ <glyph glyph-name="windows" unicode="&#xf17a;" horiz-adv-x="1664"
+d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+ <glyph glyph-name="calendar-o" unicode="&#xf133;" horiz-adv-x="1664"
+d="M128 -128h1408v1024h-1408v-1024zM512 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1280 1088v288c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-288c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1664 1152
+v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="suitcase" unicode="&#xf0f2;" horiz-adv-x="1792"
+d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64c-123 0 -224 101 -224 224v832c0 123 101 224 224 224h64zM1408 1152v-1280h-1024v1280h128v160c0 53 43 96 96 96h576c53 0 96 -43 96 -96v-160h128zM1792 928v-832c0 -123 -101 -224 -224 -224h-64v1280h64
+c123 0 224 -101 224 -224z" />
+ <glyph glyph-name="arrow-circle-o-up" unicode="&#xf01b;"
+d="M1118 660c-5 -12 -17 -20 -30 -20h-192v-352c0 -18 -14 -32 -32 -32h-192c-18 0 -32 14 -32 32v352h-192c-18 0 -32 14 -32 32c0 9 4 17 10 24l319 319c7 6 15 9 23 9s16 -3 23 -9l320 -320c9 -10 12 -23 7 -35zM768 1184c-300 0 -544 -244 -544 -544s244 -544 544 -544
+s544 244 544 544s-244 544 -544 544zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="arrow-up" unicode="&#xf062;" horiz-adv-x="1558"
+d="M1558 565c0 -34 -14 -66 -37 -90l-75 -75c-24 -24 -57 -38 -91 -38s-67 14 -90 38l-294 293v-704c0 -72 -60 -117 -128 -117h-128c-68 0 -128 45 -128 117v704l-294 -293c-23 -24 -56 -38 -90 -38s-67 14 -90 38l-75 75c-24 24 -38 56 -38 90s14 67 38 91l651 651
+c23 24 56 37 90 37s67 -13 91 -37l651 -651c23 -24 37 -57 37 -91z" />
+ <glyph glyph-name="venus-mars" unicode="&#xf228;" horiz-adv-x="2048"
+d="M1664 1504c0 18 14 32 32 32h288c35 0 64 -29 64 -64v-288c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v134l-254 -255c98 -123 147 -286 117 -461c-42 -240 -237 -431 -478 -467c-152 -23 -295 14 -409 90c-75 -50 -162 -83 -256 -93v-132h96c18 0 32 -14 32 -32
+v-64c0 -18 -14 -32 -32 -32h-96v-96c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v96h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96v132c-314 35 -553 323 -506 654c34 249 232 449 480 487c153 23 296 -14 410 -90c92 61 202 97 320 97c136 0 261 -48 359 -126
+l255 254h-134c-18 0 -32 14 -32 32v64zM896 391c79 81 128 191 128 313s-49 232 -128 313c-79 -81 -128 -191 -128 -313s49 -232 128 -313zM128 704c0 -247 201 -448 448 -448c79 0 154 21 218 57c-95 103 -154 240 -154 391s59 288 154 391c-64 36 -139 57 -218 57
+c-247 0 -448 -201 -448 -448zM1216 256c247 0 448 201 448 448s-201 448 -448 448c-79 0 -154 -21 -218 -57c95 -103 154 -240 154 -391s-59 -288 -154 -391c64 -36 139 -57 218 -57z" />
+ <glyph glyph-name="pause-circle" unicode="&#xf28b;"
+d="M704 352v576c0 18 -14 32 -32 32h-256c-18 0 -32 -14 -32 -32v-576c0 -18 14 -32 32 -32h256c18 0 32 14 32 32zM1152 352v576c0 18 -14 32 -32 32h-256c-18 0 -32 -14 -32 -32v-576c0 -18 14 -32 32 -32h256c18 0 32 14 32 32zM1536 640c0 -424 -344 -768 -768 -768
+s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="shopping-cart" unicode="&#xf07a;" horiz-adv-x="1664"
+d="M640 0c0 -70 -58 -128 -128 -128s-128 58 -128 128s58 128 128 128s128 -58 128 -128zM1536 0c0 -70 -58 -128 -128 -128s-128 58 -128 128s58 128 128 128s128 -58 128 -128zM1664 1088v-512c0 -32 -25 -60 -57 -64l-1044 -122c5 -23 13 -46 13 -70
+c0 -23 -14 -44 -24 -64h920c35 0 64 -29 64 -64s-29 -64 -64 -64h-1024c-35 0 -64 29 -64 64c0 31 45 106 61 137l-177 823h-204c-35 0 -64 29 -64 64s29 64 64 64h256c67 0 69 -80 79 -128h1201c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="files-o" unicode="&#xf0c5;" horiz-adv-x="1792"
+d="M1696 1152c53 0 96 -43 96 -96v-1216c0 -53 -43 -96 -96 -96h-960c-53 0 -96 43 -96 96v288h-544c-53 0 -96 43 -96 96v672c0 53 31 127 68 164l408 408c37 37 111 68 164 68h416c53 0 96 -43 96 -96v-328c39 23 89 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323
+l-299 -299h299v299zM708 676l316 316v416h-384v-416c0 -53 -43 -96 -96 -96h-416v-640h512v256c0 53 31 127 68 164zM1664 -128v1152h-384v-416c0 -53 -43 -96 -96 -96h-416v-640h896z" />
+ <glyph glyph-name="mastodon-square" unicode="&#xf300;"
+d="M288 1408h960c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288zM766 1189v0c-140 -1 -275 -17 -354 -53c0 0 -156 -70 -156 -308c0 -55 -1 -119 1 -188c6 -233 43 -463 258 -520
+c99 -26 184 -32 253 -28c124 7 195 45 195 45l-5 90s-88 -28 -188 -25c-99 3 -204 11 -220 133c-1 11 -2 22 -2 34c0 0 97 -24 220 -30c75 -3 146 4 218 13c138 16 257 102 272 179c24 122 22 297 22 297c0 238 -156 308 -156 308c-79 36 -214 52 -354 53h-4zM608 1003v0
+c58 0 103 -23 132 -68l28 -47l28 47c29 45 74 68 132 68c51 0 92 -18 123 -53c31 -34 45 -81 45 -140v-288h-114v280c0 59 -25 88 -75 88c-55 0 -82 -35 -82 -105v-153h-114v153c0 70 -27 105 -82 105c-50 0 -75 -29 -75 -88v-280h-114v288c0 59 15 105 45 140
+c31 35 72 53 123 53z" />
+ <glyph glyph-name="th-large" unicode="&#xf009;" horiz-adv-x="1664"
+d="M768 512v-384c0 -70 -58 -128 -128 -128h-512c-70 0 -128 58 -128 128v384c0 70 58 128 128 128h512c70 0 128 -58 128 -128zM768 1280v-384c0 -70 -58 -128 -128 -128h-512c-70 0 -128 58 -128 128v384c0 70 58 128 128 128h512c70 0 128 -58 128 -128zM1664 512v-384
+c0 -70 -58 -128 -128 -128h-512c-70 0 -128 58 -128 128v384c0 70 58 128 128 128h512c70 0 128 -58 128 -128zM1664 1280v-384c0 -70 -58 -128 -128 -128h-512c-70 0 -128 58 -128 128v384c0 70 58 128 128 128h512c70 0 128 -58 128 -128z" />
+ <glyph glyph-name="at" unicode="&#xf1fa;"
+d="M972 761c0 144 -75 230 -201 230c-166 0 -344 -165 -344 -432c0 -149 74 -234 204 -234c201 0 341 230 341 436zM1536 640c0 -311 -222 -428 -412 -434c-13 0 -18 -1 -32 -1c-62 0 -111 18 -142 53c-19 22 -30 50 -33 83c-62 -78 -170 -154 -305 -154
+c-215 0 -338 133 -338 365c0 319 221 578 491 578c117 0 211 -50 261 -135l2 19l11 56c1 8 8 18 15 18h118c5 0 10 -7 13 -11c3 -3 4 -11 3 -16l-120 -614c-4 -19 -5 -34 -5 -48c0 -54 16 -65 57 -65c68 2 288 30 288 306c0 389 -251 640 -640 640
+c-353 0 -640 -287 -640 -640s287 -640 640 -640c147 0 291 51 405 144c14 12 34 10 45 -4l41 -49c5 -7 8 -15 7 -24c-1 -8 -5 -16 -12 -22c-136 -111 -309 -173 -486 -173c-423 0 -768 345 -768 768s345 768 768 768c459 0 768 -309 768 -768z" />
+ <glyph glyph-name="file" unicode="&#xf15b;"
+d="M1024 1024v472c14 -9 26 -18 36 -28l408 -408c10 -10 19 -22 28 -36h-472zM896 992c0 -53 43 -96 96 -96h544v-1056c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1600c0 53 43 96 96 96h800v-544z" />
+ <glyph glyph-name="star-half" unicode="&#xf089;" horiz-adv-x="832"
+d="M832 1504v-1339l-449 -236c-13 -7 -26 -12 -40 -12c-29 0 -42 24 -42 50c0 7 1 13 2 20l86 500l-364 354c-12 13 -25 30 -25 48c0 30 31 42 56 46l502 73l225 455c9 19 26 41 49 41z" />
+ <glyph glyph-name="futbol-o" unicode="&#xf1e3;" horiz-adv-x="1792"
+d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536c495 0 896 -401 896 -896s-401 -896 -896 -896s-896 401 -896 896s401 896 896 896zM1515 186c94 128 149 284 149 454v3l-102 -89l-240 224l63 323l134 -12c-95 131 -231 232 -389 282l53 -124l-287 -159l-287 159
+l53 124c-158 -50 -294 -151 -389 -282l135 12l62 -323l-240 -224l-102 89v-3c0 -170 55 -326 149 -454l30 132l326 -40l139 -298l-116 -69c75 -25 156 -39 240 -39s165 14 240 39l-116 69l139 298l326 40z" />
+ <glyph glyph-name="flag-checkered" unicode="&#xf11e;" horiz-adv-x="1728"
+d="M768 536v192c-122 -11 -269 -60 -384 -117v-185c116 54 260 100 384 110zM768 954v197c-126 -6 -274 -65 -384 -126v-189c118 61 260 113 384 118zM1600 491v184c-91 -45 -250 -112 -384 -71v224c-13 4 -26 9 -39 15c-115 58 -209 112 -360 112c-16 0 -32 -1 -49 -3v-222
+h19c151 0 275 -54 390 -111c13 -6 26 -11 39 -15v-188c27 -11 57 -17 91 -17c111 0 231 59 293 92zM1600 918v189c-80 -43 -192 -91 -306 -91c-27 0 -53 2 -78 8v-196c134 -38 293 39 384 90zM256 1280c0 -47 -26 -88 -64 -110v-1266c0 -18 -14 -32 -32 -32h-64
+c-18 0 -32 14 -32 32v1266c-38 22 -64 63 -64 110c0 71 57 128 128 128s128 -57 128 -128zM1728 1216v-763c0 -24 -14 -46 -35 -57c-4 -2 -10 -5 -17 -9c-64 -34 -215 -116 -369 -116c-59 0 -112 12 -158 35l-28 14c-101 51 -181 91 -304 91c-144 0 -347 -75 -464 -146
+c-10 -6 -22 -9 -33 -9s-22 3 -32 8c-20 12 -32 33 -32 56v742c0 22 12 43 31 55c64 38 290 163 500 163c167 0 303 -61 418 -117c26 -13 56 -19 89 -19c118 0 248 75 310 112c13 7 24 13 31 17c20 10 43 9 62 -2c19 -12 31 -33 31 -55z" />
+ <glyph glyph-name="genderless" unicode="&#xf22d;" horiz-adv-x="1152"
+d="M1024 576c0 247 -201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448s448 201 448 448zM1152 576c0 -318 -258 -576 -576 -576s-576 258 -576 576s258 576 576 576s576 -258 576 -576z" />
+ <glyph glyph-name="archive" unicode="&#xf187;" horiz-adv-x="1664"
+d="M1024 704c0 35 -29 64 -64 64h-256c-35 0 -64 -29 -64 -64s29 -64 64 -64h256c35 0 64 29 64 64zM1600 896v-960c0 -35 -29 -64 -64 -64h-1408c-35 0 -64 29 -64 64v960c0 35 29 64 64 64h1408c35 0 64 -29 64 -64zM1664 1344v-256c0 -35 -29 -64 -64 -64h-1536
+c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h1536c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="film" unicode="&#xf008;" horiz-adv-x="1920"
+d="M384 -64v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM384 320v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM384 704v128c0 35 -29 64 -64 64h-128
+c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1408 -64v512c0 35 -29 64 -64 64h-768c-35 0 -64 -29 -64 -64v-512c0 -35 29 -64 64 -64h768c35 0 64 29 64 64zM384 1088v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128
+c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1792 -64v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1408 704v512c0 35 -29 64 -64 64h-768c-35 0 -64 -29 -64 -64v-512c0 -35 29 -64 64 -64h768c35 0 64 29 64 64z
+M1792 320v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1792 704v128c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1792 1088v128c0 35 -29 64 -64 64h-128
+c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h128c35 0 64 29 64 64zM1920 1248v-1344c0 -88 -72 -160 -160 -160h-1600c-88 0 -160 72 -160 160v1344c0 88 72 160 160 160h1600c88 0 160 -72 160 -160z" />
+ <glyph glyph-name="power-off" unicode="&#xf011;"
+d="M1536 640c0 -423 -345 -768 -768 -768s-768 345 -768 768c0 243 112 467 307 613c57 43 137 32 179 -25c43 -56 31 -137 -25 -179c-130 -98 -205 -247 -205 -409c0 -282 230 -512 512 -512s512 230 512 512c0 162 -75 311 -205 409c-56 42 -68 123 -25 179
+c42 57 123 68 179 25c195 -146 307 -370 307 -613zM896 1408v-640c0 -70 -58 -128 -128 -128s-128 58 -128 128v640c0 70 58 128 128 128s128 -58 128 -128z" />
+ <glyph glyph-name="percent" unicode="&#xf295;"
+d="M1280 256c0 70 -58 128 -128 128s-128 -58 -128 -128s58 -128 128 -128s128 58 128 128zM512 1024c0 70 -58 128 -128 128s-128 -58 -128 -128s58 -128 128 -128s128 58 128 128zM1536 256c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384
+s384 -172 384 -384zM1440 1344c0 -14 -5 -27 -13 -38l-1056 -1408c-12 -16 -31 -26 -51 -26h-160c-35 0 -64 29 -64 64c0 14 5 27 13 38l1056 1408c12 16 31 26 51 26h160c35 0 64 -29 64 -64zM768 1024c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384
+s384 -172 384 -384z" />
+ <glyph glyph-name="google-wallet" unicode="&#xf1ee;" horiz-adv-x="1756"
+d="M405 864c20 0 40 -10 52 -26c175 -239 297 -495 362 -774h-446c-80 278 -198 532 -367 749c-16 21 0 51 26 51h373zM964 507c-33 -135 -75 -266 -125 -393c-53 209 -138 405 -256 594c26 145 41 294 44 449c141 -227 253 -443 337 -650zM1063 1216
+c299 -412 521 -920 569 -1472h-451c-33 534 -279 1040 -553 1472h435zM1756 640c0 -278 -38 -570 -101 -812c-44 370 -166 738 -359 1083c-17 202 -53 398 -106 584c-5 21 10 41 31 41h359c28 0 54 -19 61 -46c76 -270 115 -556 115 -850z" />
+ <glyph glyph-name="book" unicode="&#xf02d;" horiz-adv-x="1664"
+d="M1639 1058c25 -36 32 -83 18 -129l-275 -906c-25 -85 -113 -151 -199 -151h-923c-102 0 -211 81 -248 185c-16 45 -16 89 -2 127c2 20 6 40 7 64c1 16 -8 29 -6 41c4 24 25 41 41 68c30 50 64 131 75 183c5 19 -5 41 0 58c5 19 24 33 34 51c27 46 62 135 67 182
+c2 21 -8 44 -2 60c7 23 29 33 44 53c24 33 64 128 70 181c2 17 -8 34 -5 52c4 19 28 39 44 62c42 62 50 199 177 163l-1 -3c17 4 34 9 51 9h761c47 0 89 -21 114 -56c26 -36 32 -83 18 -130l-274 -906c-47 -154 -73 -188 -200 -188h-869c-13 0 -29 -3 -38 -15
+c-8 -12 -9 -21 -1 -43c20 -58 89 -70 144 -70h923c37 0 80 21 91 57l300 987c6 19 6 39 5 57c23 -9 44 -23 59 -43zM575 1056c-6 -18 4 -32 22 -32h608c17 0 36 14 42 32l21 64c6 18 -4 32 -22 32h-608c-17 0 -36 -14 -42 -32zM492 800c-6 -18 4 -32 22 -32h608
+c17 0 36 14 42 32l21 64c6 18 -4 32 -22 32h-608c-17 0 -36 -14 -42 -32z" />
+ <glyph glyph-name="thermometer-three-quarters" unicode="&#xf2c8;" horiz-adv-x="1024"
+d="M640 192c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 80 50 153 128 181v651h128v-651c78 -28 128 -101 128 -181zM768 192c0 105 -50 197 -128 256v768c0 106 -86 192 -192 192s-192 -86 -192 -192v-768c-78 -59 -128 -151 -128 -256c0 -177 143 -320 320 -320
+s320 143 320 320zM896 192c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 122 49 232 128 313v711c0 177 143 320 320 320s320 -143 320 -320v-711c79 -81 128 -191 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z
+" />
+ <glyph glyph-name="transgender" unicode="&#xf224;" horiz-adv-x="1408"
+d="M1024 1504c0 18 14 32 32 32h288c35 0 64 -29 64 -64v-288c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v134l-254 -255c78 -98 126 -223 126 -359c0 -296 -224 -540 -512 -572v-132h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96v-96c0 -18 -14 -32 -32 -32
+h-64c-18 0 -32 14 -32 32v96h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96v132c-302 33 -535 302 -510 618c21 272 237 495 507 526c162 19 312 -31 426 -122l255 254h-134c-18 0 -32 14 -32 32v64zM576 256c247 0 448 201 448 448s-201 448 -448 448
+s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="cloud-upload" unicode="&#xf0ee;" horiz-adv-x="1920"
+d="M1280 672c0 8 -3 17 -9 23l-352 352c-6 6 -14 9 -23 9c-8 0 -17 -3 -23 -9l-351 -351c-6 -7 -10 -15 -10 -24c0 -18 14 -32 32 -32h224v-352c0 -17 15 -32 32 -32h192c17 0 32 15 32 32v352h224c18 0 32 15 32 32zM1920 384c0 -212 -172 -384 -384 -384h-1088
+c-247 0 -448 201 -448 448c0 174 101 332 258 405c-1 15 -2 29 -2 43c0 283 229 512 512 512c208 0 395 -126 474 -318c46 40 105 62 166 62c141 0 256 -115 256 -256c0 -49 -14 -97 -41 -138c174 -41 297 -196 297 -374z" />
+ <glyph glyph-name="bullseye" unicode="&#xf140;"
+d="M1024 640c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256zM1152 640c0 212 -172 384 -384 384s-384 -172 -384 -384s172 -384 384 -384s384 172 384 384zM1280 640c0 -283 -229 -512 -512 -512s-512 229 -512 512s229 512 512 512
+s512 -229 512 -512zM1408 640c0 353 -287 640 -640 640s-640 -287 -640 -640s287 -640 640 -640s640 287 640 640zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="openid" unicode="&#xf19b;" horiz-adv-x="1792"
+d="M1086 1536v-1536l-272 -128c-460 41 -814 286 -814 583c0 286 330 524 767 577v-172c-286 -50 -496 -212 -496 -405c0 -204 234 -373 543 -412v1360zM1755 954l37 -390l-525 114l147 83c-78 46 -174 80 -280 99v172c185 -22 351 -78 481 -157z" />
+ <glyph glyph-name="repeat" unicode="&#xf01e;"
+d="M1536 1280v-448c0 -35 -29 -64 -64 -64h-448c-26 0 -49 16 -59 40c-10 23 -5 51 14 69l138 138c-94 87 -218 137 -349 137c-282 0 -512 -230 -512 -512s230 -512 512 -512c159 0 306 72 404 199c5 7 14 11 23 12c9 0 18 -3 25 -9l137 -138c12 -11 12 -30 2 -43
+c-146 -176 -362 -277 -591 -277c-423 0 -768 345 -768 768s345 768 768 768c197 0 388 -79 529 -212l130 129c18 19 46 24 70 14c23 -10 39 -33 39 -59z" />
+ <glyph glyph-name="star" unicode="&#xf005;" horiz-adv-x="1664"
+d="M1664 889c0 -18 -13 -35 -26 -48l-363 -354l86 -500c1 -7 1 -13 1 -20c0 -26 -12 -50 -41 -50c-14 0 -28 5 -40 12l-449 236l-449 -236c-13 -7 -26 -12 -40 -12c-29 0 -42 24 -42 50c0 7 1 13 2 20l86 500l-364 354c-12 13 -25 30 -25 48c0 30 31 42 56 46l502 73
+l225 455c9 19 26 41 49 41s40 -22 49 -41l225 -455l502 -73c24 -4 56 -16 56 -46z" />
+ <glyph glyph-name="users" unicode="&#xf0c0;" horiz-adv-x="1920"
+d="M593 640c-104 -3 -198 -48 -265 -128h-134c-100 0 -194 48 -194 159c0 81 -3 353 124 353c21 0 125 -85 260 -85c46 0 90 8 133 23c-3 -22 -5 -44 -5 -66c0 -91 29 -181 81 -256zM1664 3c0 -162 -107 -259 -267 -259h-874c-160 0 -267 97 -267 259c0 226 53 573 346 573
+c34 0 158 -139 358 -139s324 139 358 139c293 0 346 -347 346 -573zM640 1280c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256zM1344 896c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384s384 -172 384 -384zM1920 671
+c0 -111 -94 -159 -194 -159h-134c-67 80 -161 125 -265 128c52 75 81 165 81 256c0 22 -2 44 -5 66c43 -15 87 -23 133 -23c135 0 239 85 260 85c127 0 124 -272 124 -353zM1792 1280c0 -141 -115 -256 -256 -256s-256 115 -256 256s115 256 256 256s256 -115 256 -256z" />
+ <glyph glyph-name="transgender-alt" unicode="&#xf225;" horiz-adv-x="1664"
+d="M1280 1504c0 18 14 32 32 32h288c35 0 64 -29 64 -64v-288c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v134l-254 -255c78 -98 126 -223 126 -359c0 -296 -224 -540 -512 -572v-132h96c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-96v-96c0 -18 -14 -32 -32 -32
+h-64c-18 0 -32 14 -32 32v96h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h96v132c-288 32 -512 276 -512 572c0 136 48 261 126 359l-52 53l-101 -111c-12 -13 -32 -14 -45 -3l-48 44c-13 11 -14 32 -2 45l105 115l-111 112v-134c0 -18 -14 -32 -32 -32h-64
+c-18 0 -32 14 -32 32v288c0 35 29 64 64 64h288c18 0 32 -14 32 -32v-64c0 -18 -14 -32 -32 -32h-133l106 -107l86 94c12 13 32 14 45 3l48 -44c13 -11 14 -32 2 -45l-90 -99l57 -56c98 78 223 126 359 126s261 -48 359 -126l255 254h-134c-18 0 -32 14 -32 32v64zM832 256
+c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="chevron-up" unicode="&#xf077;" horiz-adv-x="1612"
+d="M1593 205l-166 -165c-25 -25 -65 -25 -90 0l-531 531l-531 -531c-25 -25 -65 -25 -90 0l-166 165c-25 25 -25 66 0 91l742 741c25 25 65 25 90 0l742 -741c25 -25 25 -66 0 -91z" />
+ <glyph glyph-name="asterisk" unicode="&#xf069;" horiz-adv-x="1428"
+d="M1364 486c61 -35 82 -114 47 -175l-64 -110c-35 -61 -114 -82 -175 -47l-266 153v-307c0 -70 -58 -128 -128 -128h-128c-70 0 -128 58 -128 128v307l-266 -153c-61 -35 -140 -14 -175 47l-64 110c-35 61 -14 140 47 175l266 154l-266 154c-61 35 -82 114 -47 175l64 110
+c35 61 114 82 175 47l266 -153v307c0 70 58 128 128 128h128c70 0 128 -58 128 -128v-307l266 153c61 35 140 14 175 -47l64 -110c35 -61 14 -140 -47 -175l-266 -154z" />
+ <glyph glyph-name="plus-circle" unicode="&#xf055;"
+d="M1216 576v128c0 35 -29 64 -64 64h-256v256c0 35 -29 64 -64 64h-128c-35 0 -64 -29 -64 -64v-256h-256c-35 0 -64 -29 -64 -64v-128c0 -35 29 -64 64 -64h256v-256c0 -35 29 -64 64 -64h128c35 0 64 29 64 64v256h256c35 0 64 29 64 64zM1536 640
+c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
+ <glyph glyph-name="cart-arrow-down" unicode="&#xf218;" horiz-adv-x="1664"
+d="M1280 832c0 35 -29 64 -64 64c-17 0 -33 -7 -45 -19l-147 -146v293c0 35 -29 64 -64 64s-64 -29 -64 -64v-293l-147 146c-12 12 -28 19 -45 19c-35 0 -64 -29 -64 -64c0 -17 7 -33 19 -45l256 -256c12 -12 28 -19 45 -19s33 7 45 19l256 256c12 12 19 28 19 45zM640 0
+c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1536 0c0 -71 -57 -128 -128 -128s-128 57 -128 128s57 128 128 128s128 -57 128 -128zM1664 1088v-512c0 -32 -24 -60 -57 -64l-1044 -122c4 -22 13 -47 13 -70s-14 -44 -24 -64h920
+c35 0 64 -29 64 -64s-29 -64 -64 -64h-1024c-35 0 -64 29 -64 64c0 31 47 108 61 137l-177 823h-204c-35 0 -64 29 -64 64s29 64 64 64h256c68 0 69 -80 79 -128h1201c35 0 64 -29 64 -64z" />
+ <glyph glyph-name="dropbox" unicode="&#xf16b;" horiz-adv-x="1664"
+d="M338 829l494 -305l-342 -285l-490 319zM1324 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM490 1418l342 -285l-494 -304l-338 270zM1326 829l338 -271l-489 -319l-343 285zM1175 1418l489 -319l-338 -270l-494 304z" />
+ <glyph glyph-name="debian" unicode="&#xf2ff;" horiz-adv-x="1440"
+d="M1 954c3 22 -11 29 15 62c-4 -17 -6 -33 -15 -62zM61 1152c0 -18 30 18 8 -31c-40 -28 -3 -12 -8 31zM754 1527c20 7 49 4 70 9c-28 -2 -55 -3 -82 -7l12 -2zM1399 728c-8 -61 -27 -121 -56 -176c26 52 43 108 51 165zM582 550l10 -27c-12 21 -26 42 -33 66
+c7 -14 13 -28 23 -39zM536 548c25 -47 38 -61 56 -96c-25 21 -40 49 -60 76zM1274 762c2 -48 -15 -72 -29 -113l-25 -13c-21 -41 2 -26 -13 -58c-33 -29 -100 -91 -121 -97c-16 0 11 19 14 26c-44 -30 -36 -46 -103 -64l-2 4c-166 -78 -395 76 -392 287
+c-2 -13 -5 -10 -9 -15c-9 108 50 218 149 262c97 48 210 28 279 -37c-38 50 -113 103 -203 98c-88 -1 -171 -57 -198 -118c-45 -28 -49 -109 -69 -124c-26 -194 49 -277 178 -376c20 -14 5 -16 8 -26c-43 20 -82 50 -114 87c17 -25 35 -49 59 -68c-40 14 -93 98 -109 101
+c69 -124 282 -218 393 -172c-51 -2 -117 -1 -175 20c-24 12 -57 39 -51 44c152 -57 308 -43 439 62c33 26 70 70 81 71c-16 -24 2 -12 -10 -33c33 54 -14 22 35 93l18 -25c-7 45 55 99 49 169c14 22 16 -23 1 -73c21 55 5 65 10 110c6 -15 14 -32 18 -48
+c-14 53 14 89 21 120c-7 3 -22 -23 -25 40c0 27 8 14 11 21c-5 3 -19 24 -28 64c6 9 17 -25 25 -26c-5 32 -15 57 -15 81c-25 51 -9 -7 -29 22c-26 82 22 19 25 56c40 -58 63 -147 73 -184c-8 45 -21 89 -37 131c12 -5 -19 93 16 28c-38 138 -161 266 -274 327
+c14 -13 31 -29 25 -31c-56 34 -46 37 -54 51c-46 19 -49 -1 -79 0c-86 46 -103 40 -183 69l4 -17c-57 19 -67 -7 -129 0c-4 3 20 11 39 14c-55 -7 -53 11 -107 -2c13 9 28 15 42 23c-45 -3 -107 -26 -88 -5c-74 -33 -205 -78 -278 -147l-2 15c-34 -40 -147 -121 -156 -173
+l-9 -2c-17 -30 -29 -64 -43 -94c-23 -39 -33 -15 -30 -21c-45 -91 -68 -168 -87 -231c14 -21 1 -123 6 -206c-23 -408 286 -804 624 -896c50 -18 123 -17 186 -19c-74 21 -84 11 -156 36c-52 24 -63 53 -100 85l15 -26c-72 26 -42 31 -101 50l16 20c-23 2 -62 40 -73 61
+l-25 -1c-31 38 -47 65 -46 86l-8 -15c-9 16 -114 142 -60 113c-10 9 -23 15 -37 41l11 13c-26 33 -48 76 -46 90c14 -19 23 -22 32 -25c-65 162 -68 9 -118 165l10 1c-8 12 -13 25 -19 38l5 45c-47 54 -14 232 -7 329c5 39 40 81 66 147l-16 3c31 53 174 214 241 206
+c32 41 -6 1 -12 11c71 74 93 52 141 65c52 31 -45 -13 -20 11c89 23 63 52 180 64c12 -7 -28 -11 -38 -20c75 36 235 28 340 -20c122 -57 259 -225 264 -383l6 -2c-3 -63 10 -135 -12 -202l15 32zM779 1504l-11 -2l11 1v1zM748 1513c53 -2 48 -5 31 -9c3 4 -15 6 -31 9z
+M1079 782c-5 -22 -10 13 -16 16c5 20 20 37 16 -16zM1020 629c18 24 30 51 35 79c-4 -20 -15 -37 -25 -55c-56 -35 -5 21 0 42c-60 -75 -8 -45 -10 -66zM860 589c-30 0 6 -15 45 -21c8 7 21 18 29 25c-24 -6 -49 -6 -74 -4z" />
+ <glyph glyph-name="newspaper-o" unicode="&#xf1ea;" horiz-adv-x="2048"
+d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960c0 -35 29 -64 64 -64
+s64 29 64 64zM1920 192v1088h-1536v-1088c0 -22 -4 -44 -11 -64h1483c35 0 64 29 64 64zM2048 1408v-1216c0 -106 -86 -192 -192 -192h-1664c-106 0 -192 86 -192 192v1088h256v128h1792z" />
+ <glyph glyph-name="building" unicode="&#xf1ad;" horiz-adv-x="1408"
+d="M1344 1536c35 0 64 -29 64 -64v-1664c0 -35 -29 -64 -64 -64h-1280c-35 0 -64 29 -64 64v1664c0 35 29 64 64 64h1280zM512 1248v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32zM512 992v-64c0 -18 14 -32 32 -32h64
+c18 0 32 14 32 32v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32zM512 736v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32zM512 480v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32v64c0 18 -14 32 -32 32h-64
+c-18 0 -32 -14 -32 -32zM384 160v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM384 416v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM384 672v64
+c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM384 928v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM384 1184v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64
+c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM896 -96v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM896 416v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32z
+M896 672v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM896 928v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM896 1184v64c0 18 -14 32 -32 32h-64
+c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1152 160v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1152 416v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64
+c18 0 32 14 32 32zM1152 672v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1152 928v64c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1152 1184v64c0 18 -14 32 -32 32
+h-64c-18 0 -32 -14 -32 -32v-64c0 -18 14 -32 32 -32h64c18 0 32 14 32 32z" />
+ <glyph glyph-name="bitbucket" unicode="&#xf171;" horiz-adv-x="1408"
+d="M815 677c11 -84 -91 -150 -162 -107c-80 35 -80 162 -2 198c67 41 164 -13 164 -91zM926 698c-18 142 -179 236 -310 177c-83 -37 -139 -125 -135 -218c5 -122 121 -222 243 -211s217 130 202 252zM1165 1240c-44 58 -119 68 -185 79c-187 30 -379 31 -566 -2
+c-62 -10 -132 -21 -171 -77c64 -60 155 -69 237 -79c148 -19 300 -20 448 -1c83 10 175 18 237 80zM1222 205c-28 -98 -12 -230 -116 -287c-179 -99 -396 -110 -593 -75c-104 19 -226 52 -283 150c-25 96 -41 194 -57 292l6 16l18 9c298 -197 715 -197 1014 0
+c47 -14 12 -71 11 -105zM1403 1166c-34 -219 -73 -437 -111 -655c-11 -64 -73 -100 -125 -127c-187 -94 -405 -110 -610 -88c-139 15 -281 52 -394 139c-53 41 -53 111 -63 170c-35 205 -75 410 -100 617c12 90 113 129 188 157c100 37 207 54 313 64c226 22 457 14 676 -50
+c78 -23 162 -55 215 -122c24 -31 16 -70 11 -105z" />
+ <glyph glyph-name="yelp" unicode="&#xf1e9;" horiz-adv-x="1366"
+d="M688 217v-127c-1 -282 -1 -292 -6 -305c-8 -21 -26 -35 -51 -40c-72 -12 -297 71 -344 127c-10 11 -15 24 -17 36c-1 9 1 18 4 26c5 14 14 25 215 263c0 0 1 0 60 70c20 25 56 33 89 21c33 -13 51 -41 50 -71zM539 468c-2 -35 -22 -61 -52 -70l-120 -39
+c-269 -86 -278 -88 -292 -88c-22 1 -42 14 -54 36c-8 16 -14 43 -17 75c-11 98 2 245 31 291c14 22 34 33 56 32c15 0 27 -6 317 -124c0 0 -1 -1 84 -34c30 -12 49 -43 47 -79zM1365 171c-10 -72 -159 -261 -227 -288c-23 -9 -46 -7 -63 7c-12 9 -24 27 -184 287l-47 77
+c-18 28 -15 64 8 92c22 27 54 36 83 26c0 0 1 -1 119 -40c269 -88 278 -91 289 -100c18 -14 26 -35 22 -61zM693 803c5 -104 -39 -117 -54 -122c-14 -4 -58 -17 -114 71c-368 581 -378 598 -378 598c-5 21 1 44 19 62c55 57 354 141 432 121c25 -6 43 -22 49 -45
+c4 -25 40 -564 46 -685zM1355 695c2 -25 -7 -46 -26 -59c-12 -8 -24 -12 -329 -86c-49 -11 -76 -18 -91 -23l1 2c-30 -8 -64 6 -83 36s-18 63 0 87c0 0 1 1 75 102c164 224 172 235 184 243c19 13 42 13 65 2c65 -31 196 -226 204 -301v-3z" />
+ <glyph glyph-name="neuter" unicode="&#xf22c;" horiz-adv-x="1152"
+d="M1152 960c0 -296 -224 -540 -512 -572v-612c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v612c-288 32 -512 276 -512 572c0 318 258 576 576 576s576 -258 576 -576zM576 512c247 0 448 201 448 448s-201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448z" />
+ <glyph glyph-name="behance-square" unicode="&#xf1b5;"
+d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-960c-159 0 -288 129 -288 288v960c0 159 129 288 288 288h960zM499 1041h-371v-787h382c143 0 277 68 277 228c0 99 -47 172 -143 200c70 34 107 85 107 164c0 157 -117 195 -252 195zM477 723
+h-176v184h163c62 0 119 -17 119 -90c0 -67 -44 -94 -106 -94zM486 388h-185v217h189c76 0 124 -33 124 -113s-57 -104 -128 -104zM1136 356c-92 0 -140 54 -140 145h411c1 10 1 20 1 30c0 168 -99 309 -278 309c-173 0 -292 -131 -292 -302c0 -178 112 -299 292 -299
+c137 0 225 61 267 191h-138c-15 -48 -76 -74 -123 -74zM1126 722c78 0 117 -47 124 -122h-254c5 75 55 122 130 122zM964 988v-77h319v77h-319z" />
+ <glyph glyph-name="wifi" unicode="&#xf1eb;" horiz-adv-x="1964"
+d="M982 13c-26 0 -166 140 -166 167c0 49 128 76 166 76s166 -27 166 -76c0 -27 -140 -167 -166 -167zM1252 284c-14 0 -123 100 -270 100c-148 0 -255 -100 -270 -100c-24 0 -169 144 -169 168c0 9 4 17 10 23c107 106 281 165 429 165s322 -59 429 -165
+c6 -6 10 -14 10 -23c0 -24 -145 -168 -169 -168zM1525 556c-8 0 -17 4 -23 8c-165 128 -304 204 -520 204c-302 0 -532 -212 -543 -212c-23 0 -167 144 -167 168c0 8 4 16 10 22c179 179 449 278 700 278s521 -99 700 -278c6 -6 10 -14 10 -22c0 -24 -144 -168 -167 -168z
+M1796 827c-8 0 -16 4 -22 9c-231 203 -480 316 -792 316s-561 -113 -792 -316c-6 -5 -14 -9 -22 -9c-23 0 -168 144 -168 168c0 9 4 17 10 23c253 251 618 390 972 390s719 -139 972 -390c6 -6 10 -14 10 -23c0 -24 -145 -168 -168 -168z" />
+ <glyph glyph-name="youtube" unicode="&#xf167;" horiz-adv-x="1482"
+d="M944 292v-211c0 -45 -13 -67 -39 -67c-15 0 -30 7 -45 22v301c15 15 30 22 45 22c26 0 39 -23 39 -67zM1282 291v-46h-90v46c0 45 15 68 45 68s45 -23 45 -68zM316 509h107v94h-312v-94h105v-569h100v569zM604 -60h89v494h-89v-378c-20 -28 -39 -42 -57 -42
+c-12 0 -19 7 -21 21c-1 3 -1 14 -1 35v364h-89v-391c0 -35 3 -58 8 -73c8 -25 29 -37 58 -37c32 0 66 20 102 61v-54zM1033 88v197c0 46 -2 79 -9 99c-11 37 -36 56 -71 56c-33 0 -64 -18 -93 -54v217h-89v-663h89v48c30 -37 61 -55 93 -55c35 0 60 19 71 55
+c7 21 9 54 9 100zM1371 98v13h-91c0 -36 -1 -56 -2 -61c-5 -24 -18 -36 -40 -36c-31 0 -46 23 -46 69v87h179v103c0 53 -9 91 -27 116c-26 34 -61 51 -106 51c-46 0 -81 -17 -107 -51c-19 -25 -28 -63 -28 -116v-173c0 -53 10 -92 29 -116c26 -34 61 -51 108 -51
+s84 18 108 53c11 16 19 34 21 54c2 9 2 29 2 58zM763 1011v210c0 46 -13 69 -43 69c-29 0 -43 -23 -43 -69v-210c0 -46 14 -70 43 -70c30 0 43 24 43 70zM1482 260c0 -115 -1 -238 -26 -350c-19 -79 -83 -137 -160 -145c-184 -21 -370 -21 -555 -21s-371 0 -555 21
+c-77 8 -142 66 -160 145c-26 112 -26 235 -26 350c0 116 1 238 26 350c19 79 83 137 161 146c183 20 369 20 554 20s371 0 555 -20c77 -9 142 -67 160 -146c26 -112 26 -234 26 -350zM484 1536h102l-121 -399v-271h-100v271c-9 49 -29 119 -61 212c-22 62 -44 125 -65 187
+h106l71 -263zM854 1203v-175c0 -53 -9 -93 -28 -118c-25 -34 -60 -51 -106 -51c-45 0 -80 17 -105 51c-19 26 -28 65 -28 118v175c0 53 9 92 28 117c25 34 60 51 105 51c46 0 81 -17 106 -51c19 -25 28 -64 28 -117zM1189 1365v-499h-91v55c-36 -42 -70 -62 -103 -62
+c-29 0 -50 12 -59 37c-5 15 -8 39 -8 75v394h91v-367c0 -21 0 -33 1 -35c2 -14 9 -22 21 -22c18 0 37 14 57 43v381h91z" />
+ <glyph glyph-name="angle-double-down" unicode="&#xf103;" horiz-adv-x="998"
+d="M998 672c0 -8 -4 -17 -10 -23l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 14 10 23 10c8 0 17 -4 23 -10l393 -393l393 393c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -15 10 -23zM998 1056
+c0 -8 -4 -17 -10 -23l-466 -466c-6 -6 -15 -10 -23 -10s-17 4 -23 10l-466 466c-6 6 -10 15 -10 23s4 17 10 23l50 50c6 6 14 10 23 10c8 0 17 -4 23 -10l393 -393l393 393c6 6 15 10 23 10s17 -4 23 -10l50 -50c6 -6 10 -15 10 -23z" />
+ <glyph glyph-name="sort-alpha-asc" unicode="&#xf15d;" horiz-adv-x="1629"
+d="M1159 1128h177l-72 218l-12 47c-1 8 -2 14 -2 20h-4l-3 -20c-3 -12 -4 -27 -11 -47zM704 96c0 -9 -4 -17 -10 -24l-319 -319c-7 -6 -15 -9 -23 -9s-16 3 -23 9l-320 320c-9 10 -12 23 -7 35s17 20 30 20h192v1376c0 18 14 32 32 32h192c18 0 32 -14 32 -32v-1376h192
+c18 0 32 -14 32 -32zM1540 -23v-233h-584v90l369 529c8 12 16 22 21 27l11 9v3c-4 0 -8 -1 -14 -1c-8 -2 -18 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530c-6 -9 -14 -18 -21 -26l-11 -11v-2l14 2c9 2 18 2 30 2h248v119h121zM1629 874v-106h-288v106h75l-47 144h-243
+l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70z" />
+ <glyph glyph-name="area-chart" unicode="&#xf1fe;" horiz-adv-x="2048"
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+ <glyph glyph-name="dev-to" unicode="&#xf316;"
+d="M39 1403v0c13 5 121 6 735 5c717 -1 721 -1 734 -9c7 -5 15 -14 20 -21c8 -13 8 -16 8 -739s0 -726 -8 -739c-5 -7 -13 -15 -20 -20c-13 -8 -16 -8 -739 -8s-726 0 -739 8c-7 5 -16 13 -21 20c-8 13 -8 16 -9 731c0 490 0 723 3 733c5 19 18 33 36 39zM404 935
+c-18 4 -53 6 -119 6h-93v-603h84c46 0 96 1 111 3c72 9 131 63 144 132c5 26 5 306 0 332c-6 31 -20 59 -43 83c-25 26 -50 40 -84 47zM897 886v55h-118c-92 0 -121 -2 -133 -6c-20 -7 -42 -30 -47 -50c-3 -11 -4 -89 -3 -254c1 -265 -1 -250 27 -274c20 -17 39 -19 163 -19
+h111v109l-95 1l-96 1l-1 69v69h116v109h-116v136h192v54zM1081 933c-3 8 -4 8 -62 8h-59l3 -10c26 -106 136 -514 143 -528c11 -23 33 -49 49 -57c18 -9 47 -7 67 4c16 9 45 45 50 62c8 25 138 522 138 525s-16 4 -60 3l-58 -1l-52 -198c-28 -109 -52 -199 -53 -202
+s-24 83 -52 190s-52 199 -54 204zM301 639v193l41 -1c37 -2 42 -2 56 -11c28 -18 27 -18 27 -178c0 -164 0 -166 -29 -183c-15 -9 -22 -10 -56 -11l-39 -2v193z" />
+ <glyph glyph-name="stethoscope" unicode="&#xf0f1;" horiz-adv-x="1408"
+d="M1280 832c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1408 832c0 -84 -53 -154 -128 -181v-395c0 -212 -201 -384 -448 -384s-448 172 -448 384v132c-217 27 -384 187 -384 380v512c0 35 29 64 64 64c6 0 11 -1 16 -2c22 39 64 66 112 66
+c71 0 128 -57 128 -128s-57 -128 -128 -128c-23 0 -45 7 -64 18v-402c0 -141 144 -256 320 -256s320 115 320 256v402c-19 -11 -41 -18 -64 -18c-71 0 -128 57 -128 128s57 128 128 128c48 0 90 -27 112 -66c5 1 10 2 16 2c35 0 64 -29 64 -64v-512
+c0 -193 -167 -353 -384 -380v-132c0 -141 144 -256 320 -256s320 115 320 256v395c-75 27 -128 97 -128 181c0 106 86 192 192 192s192 -86 192 -192z" />
+ <glyph glyph-name="step-forward" unicode="&#xf051;" horiz-adv-x="1024"
+d="M45 -115c-25 -25 -45 -16 -45 19v1472c0 35 20 44 45 19l710 -710c6 -6 10 -12 13 -19v678c0 35 29 64 64 64h128c35 0 64 -29 64 -64v-1408c0 -35 -29 -64 -64 -64h-128c-35 0 -64 29 -64 64v678c-3 -7 -7 -13 -13 -19z" />
+ <glyph glyph-name="backward" unicode="&#xf04a;" horiz-adv-x="1542"
+d="M1497 1395c25 25 45 16 45 -19v-1472c0 -35 -20 -44 -45 -19l-710 710c-6 6 -10 12 -13 19v-710c0 -35 -20 -44 -45 -19l-710 710c-25 25 -25 65 0 90l710 710c25 25 45 16 45 -19v-710c3 7 7 13 13 19z" />
+ </font>
+</defs></svg>
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.fc46f3dae03b2b2e1cee.ttf b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.fc46f3dae03b2b2e1cee.ttf
new file mode 100644
index 00000000..6cf62efb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/forkawesome-webfont.fc46f3dae03b2b2e1cee.ttf
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.448c34a56d699c29117a.woff2 b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.448c34a56d699c29117a.woff2
new file mode 100644
index 00000000..64539b54
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.448c34a56d699c29117a.woff2
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.89889688147bd7575d63.svg b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.89889688147bd7575d63.svg
new file mode 100644
index 00000000..94fb5490
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.89889688147bd7575d63.svg
@@ -0,0 +1,288 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph horiz-adv-x="0" />
+<glyph horiz-adv-x="400" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
+<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
+<glyph unicode="&#x2000;" horiz-adv-x="650" />
+<glyph unicode="&#x2001;" horiz-adv-x="1300" />
+<glyph unicode="&#x2002;" horiz-adv-x="650" />
+<glyph unicode="&#x2003;" horiz-adv-x="1300" />
+<glyph unicode="&#x2004;" horiz-adv-x="433" />
+<glyph unicode="&#x2005;" horiz-adv-x="325" />
+<glyph unicode="&#x2006;" horiz-adv-x="216" />
+<glyph unicode="&#x2007;" horiz-adv-x="216" />
+<glyph unicode="&#x2008;" horiz-adv-x="162" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="325" />
+<glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
+<glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
+<glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
+<glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
+<glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
+<glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
+<glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
+<glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
+<glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
+<glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
+<glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
+<glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
+<glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
+<glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
+<glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
+<glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
+<glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
+<glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
+<glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
+<glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
+<glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
+<glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
+<glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
+<glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
+<glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
+<glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
+<glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
+<glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
+<glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
+<glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
+<glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
+<glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
+<glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
+<glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
+<glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
+<glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
+<glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
+<glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
+<glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
+<glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
+<glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
+<glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
+<glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
+<glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
+<glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
+<glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
+<glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
+<glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
+<glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
+<glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
+<glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
+<glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
+<glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
+<glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
+<glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
+<glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
+<glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
+<glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
+<glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
+<glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
+<glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
+<glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
+<glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
+<glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
+<glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
+<glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
+<glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
+<glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
+<glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
+<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
+<glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
+<glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
+<glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
+<glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
+<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
+<glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
+<glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
+<glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
+<glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
+<glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
+<glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
+<glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
+<glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
+<glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
+<glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
+<glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
+<glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
+<glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
+<glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
+<glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
+<glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
+<glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
+<glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
+<glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
+<glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
+<glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
+<glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
+<glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
+<glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
+<glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
+<glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
+<glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
+<glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
+<glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
+<glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
+<glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
+<glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
+<glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
+<glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
+<glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
+<glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
+<glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
+<glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
+<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
+<glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
+<glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
+<glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
+<glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
+<glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
+<glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
+<glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
+<glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
+<glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
+<glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
+<glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
+<glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
+<glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
+<glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
+<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
+<glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
+<glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
+<glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
+<glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
+<glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
+<glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
+<glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
+<glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
+<glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
+<glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
+<glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
+<glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
+<glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
+<glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
+<glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
+<glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
+<glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
+<glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
+<glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
+<glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
+<glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
+<glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
+<glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
+<glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
+<glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
+<glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
+<glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
+<glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
+<glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
+<glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
+<glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
+<glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
+<glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
+<glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
+<glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
+<glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
+<glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
+<glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
+<glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
+<glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
+<glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
+<glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf
new file mode 100644
index 00000000..1413fc60
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.f4769f9bdb7466be6508.eot b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.f4769f9bdb7466be6508.eot
new file mode 100644
index 00000000..b93a4953
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.f4769f9bdb7466be6508.eot
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.fa2772327f55d8198301.woff b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.fa2772327f55d8198301.woff
new file mode 100644
index 00000000..9e612858
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/glyphicons-halflings-regular.fa2772327f55d8198301.woff
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/index.html b/src/pybind/mgr/dashboard/frontend/dist/en-US/index.html
new file mode 100644
index 00000000..c8c823f7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/index.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Ceph</title>
+
+ <script>
+ document.write('<base href="' + document.location+ '" />');
+ </script>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
+<link rel="stylesheet" href="styles.f5317b15474518dffebc.css"></head>
+<body>
+ <noscript>
+ <div class="noscript container"
+ ng-if="false">
+ <div class="jumbotron alert alert-danger">
+ <h2 i18n>JavaScript required!</h2>
+ <p i18n>A browser with JavaScript enabled is required in order to use this service.</p>
+ <p i18n>When using Internet Explorer, please check your security settings and add this address to your trusted sites.</p>
+ </div>
+ </div>
+ </noscript>
+
+ <cd-root></cd-root>
+<script type="text/javascript" src="runtime.ff444394af058f159c51.js"></script><script type="text/javascript" src="polyfills.f31db31652a3fd9f4bca.js"></script><script type="text/javascript" src="scripts.fc88ef4a23399c760d0b.js"></script><script type="text/javascript" src="main.a8acf27ca1415ab0d94b.js"></script></body>
+</html>
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/main.a8acf27ca1415ab0d94b.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/main.a8acf27ca1415ab0d94b.js
new file mode 100644
index 00000000..8cf068e1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/main.a8acf27ca1415ab0d94b.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"+0ag":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){var e=/ceph version\s+[^ ]+\s+\(.+\)\s+(.+)\s+\((.+)\)/.exec(t);return e?"dev"===e[2]?"master":e[1]:t},t}()},"+s0g":function(t,e,n){!function(t){"use strict";var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),n="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),a=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;t.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"\xe9\xe9n minuut",mm:"%d minuten",h:"\xe9\xe9n uur",hh:"%d uur",d:"\xe9\xe9n dag",dd:"%d dagen",M:"\xe9\xe9n maand",MM:"%d maanden",y:"\xe9\xe9n jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}})}(n("wd/R"))},"+tJ4":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(t){return function(e){for(var n=0,a=t.length;n<a&&!e.closed;n++)e.next(t[n]);e.complete()}}},"+umK":function(t,e,n){"use strict";function a(){}n.d(e,"a",function(){return a})},"//9w":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("se",{months:"o\u0111\u0111ajagem\xe1nnu_guovvam\xe1nnu_njuk\u010dam\xe1nnu_cuo\u014bom\xe1nnu_miessem\xe1nnu_geassem\xe1nnu_suoidnem\xe1nnu_borgem\xe1nnu_\u010dak\u010dam\xe1nnu_golggotm\xe1nnu_sk\xe1bmam\xe1nnu_juovlam\xe1nnu".split("_"),monthsShort:"o\u0111\u0111j_guov_njuk_cuo_mies_geas_suoi_borg_\u010dak\u010d_golg_sk\xe1b_juov".split("_"),weekdays:"sotnabeaivi_vuoss\xe1rga_ma\u014b\u014beb\xe1rga_gaskavahkku_duorastat_bearjadat_l\xe1vvardat".split("_"),weekdaysShort:"sotn_vuos_ma\u014b_gask_duor_bear_l\xe1v".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s gea\u017ees",past:"ma\u014bit %s",s:"moadde sekunddat",ss:"%d sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta m\xe1nnu",MM:"%d m\xe1nut",y:"okta jahki",yy:"%d jagit"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},"/21U":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("isby");function r(t){return!Object(a.a)(t)&&t-parseFloat(t)+1>=0}},"/6aS":function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="pl-PL">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Rozwi\u0144</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Pulpit</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Klaster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Hosty</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitory</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD-ki</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Konfiguracja</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH mapa</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Zarz\u0105dca modu\u0142\xf3w</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Logi</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Powiadomienia</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Pule</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Dost\u0119p blokowy</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Obrazy</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Kopia lustrzana</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>Sieciowy system plik\xf3w NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Systemy plik\xf3w</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Dost\u0119p obiektowy</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Demony</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>U\u017cytkownicy</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Wiadra</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Trwa pobieranie danych \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> dla \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Czekaj...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Wy\u015bwietlanie wcze\u015bniej buforowanych danych \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> \ndla \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Nie mo\u017cna za\u0142adowa\u0107 danych \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> dla\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Sprawd\u017a prosz\u0119 zdrowie klastra. \n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Wstecz</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Wybierz j\u0119zyk</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Trwa \u0142adowanie danych...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Sprawd\u017a prosz\u0119 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentacj\u0119\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>jak\nskonfigurowa\u0107 i uruchomi\u0107 funkcje monitoringu.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Pulpit Grafany nie istnieje. Sprawd\u017a prosz\u0119 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentacj\u0119 \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> jak\ndodaj pulpity do Grafany.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Wyb\xf3r czasu Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Zresetuj ustawienia</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>B\u0142\u0105d wczytywania danych.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>Wybrane</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>Znaleziono</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>Razem</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Edytuj</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nazwa</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Opis</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>D\u0142ugi opis</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Domy\u015blna</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Domy\u015blny demon</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Us\u0142ugi</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Warto\u015bci</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za wysoka. Nie mo\u017ce by\u0107 wi\u0119ksza ni\u017c \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za ma\u0142a. Nie mo\u017ce by\u0107 mniejsza od \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Zapisz</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>widok CRUSH mapy</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Lista host\xf3w</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Ca\u0142kowita wydajno\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Nie znaleziono wej\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Logi z klastra </target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Audyt log\xf3w</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>\u0141adowanie konfiguracji.</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>Nie mo\u017cna za\u0142adowa\u0107 konfiguracji</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Edytuj modu\u0142 zarz\u0105dzania</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>Wpisana warto\u015b\u0107 nie jest poprawnym UUID, np. 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>Wpisana warto\u015b\u0107 musi by\u0107 poprawnym adresem IP</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Pole jest wymagane.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za wysoka! Musi by\u0107 mniejsza b\u0105d\u017a r\xf3wna \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za niska! Musi by\u0107 wi\u0119ksza b\u0105d\u017a r\xf3wna \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>Podana warto\u015b\u0107 musi by\u0107 liczb\u0105</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>Podana warto\u015b\u0107 musi by\u0107 liczb\u0105 albo dziesi\u0119tn\u0105.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Zaktualizuj</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Status</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>Klaster ID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>Zmodyfikowana monmapa</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>epoka monmap</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>kworum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>kworum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>wymagany con</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>Wymagane mon </target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>W kworum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Nie w kworum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Anuluj</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Jeste\u015b pewny, \u017ce chcesz \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\xa0 wybrany \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>? \n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Tak, jestem pewny.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Flagi OSD w ca\u0142ym klastrze</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Zatwierd\u017a</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Zaawansowane...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Priorytet odzyskiwania OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Priorytet</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Dostosuj warto\u015bci priorytetowe</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>To pole jest wymagane.</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za wysoka. Nie mo\u017ce by\u0107 wi\u0119ksza ni\u017c \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>Podana warto\u015b\u0107 jest za ma\u0142a! Nie mo\u017ce by\u0107 mniejsza od \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Ponowne wa\u017cenie OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>Warto\u015b\u0107 powinna by\u0107 pomi\u0119dzy 0 a 1. </target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Ponowne wa\u017cenie</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>Szoruj\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> OSD-ki\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, wybierz, 1 {G\u0142\u0119boko\u015b\u0107} }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Zamierzasz zaaplikowa\u0107 \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> szorowanie na OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, wybierz, 1 {g\u0142\u0119boko\u015b\u0107} }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Lista OSD-k\xf3w </target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Je\u015bli kontynuujesz \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> b\u0119dzie zaznaczony\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> .\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>Nie mo\u017cna bezpiecznie zniszczy\u0107 tego OSD.</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Je\u015bli kontyuujesz \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> b\u0119dzie \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Szczeg\xf3\u0142y</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Warto\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Zamknij</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Usu\u0144</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Zdrowie</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statystyki</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Sprawd\u017a prosz\u0119 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentacj\u0119 \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\xa0\njak nale\u017cy skonfigurowa\u0107 i uruchomi\u0107 zarz\u0105dzanie funkcjami NFS Ganeshy \n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Klienci</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Ka\u017cdy klient ma dost\u0119p</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Adresy</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Obowi\u0105zkowe pole</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Musi zawiera\u0107 jedn\u0105 albo wi\u0119cej ,rozdzielonych przecinkiem, warto\u015bci </target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Na przyk\u0142ad: </target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Typ dost\u0119pu</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Dodaj klient\xf3w </target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>\u0141adowanie...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- Brak dost\u0119pnego klastra -- </target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Wybierz klaster --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Dodaj demona</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Pami\u0119\u0107 Podr\u0119czna</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- Brak danych puli -- </target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Wybierz pami\u0119\u0107 podr\u0119czn\u0105 -- </target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>U\u017cytkownik dost\u0119pu obiektowego</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- Brak dost\u0119pnych u\u017cytkownik\xf3w -- </target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Wybierz u\u017cytkownika dost\u0119pu obiektowego -- </target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS U\u017cytkownik ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- Brak dost\u0119pnych klient\xf3w -- </target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Wybierz klienta cephx -- </target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nazwa CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Etykieta bezpiecze\u0144stwa</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Uruchom etykiet\u0119 bezpiecze\u0144stwa</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>\u015acie\u017cka CephFS </target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>\u015acie\u017cka powinna zaczyna\u0107 si\u0119 z \'/\' i nast\u0119pne mo\u017ce by\u0107 s\u0142owo</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Nowy katalog b\u0119dzie stworzony. </target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>\u015acie\u017cka</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>\u015acie\u017ck\u0105 mo\u017ce by\u0107 tylko \'/\' albo s\u0142owo</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Nowe wiadro b\u0119dzie stworzone </target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protok\xf3\u0142 NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Tag NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Alternatywny dost\u0119p do \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\xa0montuje ( nie musi mie\u0107 poprzedzaj\u0105cego \'/\' )\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Klient mo\u017ce nie montowa\u0107 podkatalog\xf3w ( np. je\u015bli Tag = foo, klient mo\u017ce nie montowa\u0107 foo/baz) </target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>U\u017cywaj\u0105c r\xf3\u017cnych opcji Tagu, ta sama \u015acie\u017cka mo\u017ce by\u0107 wyeksportowana kilka razy.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>Pozycja, kt\xf3r\u0105 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> eksport zajmuje \nw \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (musi by\u0107 unikatowa). \n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>U\u017cywaj\u0105c r\xf3\u017cnych opcji Pseudo, ta sama \u015acie\u017cka mo\u017ce by\u0107 wyeksportowana kilka razy.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- Brak dost\u0119pnych typ\xf3w dost\u0119pu --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Wybierz typ dost\u0119pu --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>- Brak squasha -</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- Wybierz, jakiego rodzaju identyfikacja u\u017cytkownika ma by\u0107 przeprowadzana --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protok\xf3\u0142 Transportu </target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Witamy w Cephie! </target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Nazwa u\u017cytkownika jest wymagana</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Has\u0142o jest wymagane.</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Zaloguj</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Przepraszam, u\u017cytkownik nie istnieje w Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Powr\xf3t do \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Strony Logowania\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Zostaniesz wylogowany z Dostastcy To\u017csamo\u015bci , kiedy spr\xf3bujesz si\u0119 zalgowa\u0107. \n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Zakazany</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Przepraszam, nie masz dost\u0119pu do tego czego szukasz. </target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Przepraszam, nie mo\u017cemy znale\u017a\u0107 tego czego szukasz.</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Usu\u0144 wszystko</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Ostatnie powiadomienia</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Brak zada\u0144 w tle.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Zagadnienia w tle </target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Pomoc</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Dokumentacja</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>Interfejs API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>O</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Ustawienia Pulpitu</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Zarz\u0105dzanie u\u017cytkownikami</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Zalogowany u\u017cytkownik</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Zalogowany jako \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Wyloguj</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nazwa...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Wybrana nazwa ju\u017c jest u\u017cyta.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Opis...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Pozwolenia</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Role</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nazwa u\u017cytkownika</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Has\u0142o</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Potwierd\u017a has\u0142o</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Potwierdzaj\u0105ce has\u0142o nie pokrywa si\u0119 z has\u0142em.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Pe\u0142ne imi\u0119 </target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>Email</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>Niepoprawny email.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Zamierzasz usun\u0105\u0107 uprawnienia \u201eodczytu / aktualizacji u\u017cytkownika\u201d od w\u0142asnego u\u017cytkownika.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Je\u015bli kontynuujesz, nie b\u0119dziesz m\xf3g\u0142 dodawa\u0107 albo usuwa\u0107 role od u\u017cytkownik\xf3w.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Jeste\u015b pewny, \u017ce chcesz kontynuowa\u0107? </target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Liczniki wydajno\u015bci nie s\u0105 dost\u0119pne</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Atrybuty (mapa OSD-k\xf3w)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Niedost\u0119pne metadane</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadane</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Licznik wydajno\u015bci</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histogram niedost\u0119pny: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Pisze</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Czyta</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histogram</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Szczeg\xf3\u0142y wydajno\u015bci</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Obecne warto\u015bci </target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Typ</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Min</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Max</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Flagi</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>\u0179r\xf3d\u0142o </target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Poziom</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Mo\u017ce by\u0107 aktualizowany w czasie wykonywania (edytowalny)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Tagi</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Warto\u015bci enumerowane </target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Zobacz tak\u017ce </target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Status klastra</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Zarz\u0105dzanie demonami</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Obiekty bram </target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Serwery metadanych</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>Bramy iSCSI</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>Klient IOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Przepustowo\u015b\u0107 klienta</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Odczyt/Zapis klienta</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Przepustowo\u015b\u0107 odzyskiwania</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Szoruj</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Wydajno\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Pojemno\u015b\u0107 rz\u0119du</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Obiekty</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>PG-y na OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Status PG</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Pojemno\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> zobacz\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>logi\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> , \u017ceby mie\u0107 wi\u0119cej szczeg\xf3\u0142\xf3w. \n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Szeregi</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Klienci: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Przenie\u015b obraz do kosza</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>\u017beby przenie\u015b\u0107 \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> do kosza, kliknij \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Przenie\u015b obraz\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Opcjonalnie, mo\u017cesz wybra\u0107 dat\u0119 wa\u017cno\u015bci.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>Zabezpieczenie wygasa w </target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>NIEZABEZPIECZONY </target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Z\u0142y format daty. Prosz\u0119 u\u017cywa\u0107 "RRRR-MM-DD GG:mm:ss".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>Ochrona ju\u017c wygas\u0142a. Prosz\u0119 wybra\u0107 przysz\u0142\u0105 dat\u0119 lub zostawi\u0107 pust\u0105.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Przenie\u015b obraz</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Przegl\u0105d</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Obiekty docelowe</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Uwierzytelnianie wykrywania</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>U\u017cytkownik</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Nazwy u\u017cytkownik\xf3w musz\u0105 mie\u0107 d\u0142ugo\u015b\u0107 od 8 do 64 znak\xf3w i \nmog\u0105 zawiera\u0107 jedynie litery, \'.\', \'@\', \'-\', \'_\' lub \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Wsp\xf3lny u\u017cytkownik </target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Wsp\xf3lne has\u0142o</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Sprawd\u017a prosz\u0119 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentacj\u0119 \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\xa0\njak skonfigurowa\u0107 i uruchomi\u0107 zarz\u0105dzanie funkcjonalno\u015bciami obiektami docelowymi iSCSI\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Dost\u0119pne informacje: </target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>obiekty docelowe iSCSI niedost\u0119pne </target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Dost\u0119pne tylko dla obraz\xf3w RBD z \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> szybk\u0105 r\xf3\u017cnic\u0105 \n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> w\u0142\u0105czone\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Pul</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Dane pula</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Utworzony</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Rozmiar</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Rozmiar obiektu</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Funkcje</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Zaopatrzony</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>Niedost\u0119pny</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Ca\u0142kowite rezerwy</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Jednostka maskowana</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Licznik maskowania</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Rodzic</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Prefiks nazwy bloku</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Zam\xf3wienie</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Migawki</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Obraz</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>To ustawienie zast\u0119puj\u0119 warto\u015b\u0107 globaln\u0105.</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Globalne</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>To jest globalna warto\u015b\u0107. Dla tego obrazu nie ustawiono \u017cadnej warto\u015bci dla tej opcji.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' and \'@\' nie s\u0105 dozwolone.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- Brak dost\u0119pnych rbd puli -- </target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Wybierz pul --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>U\u017cyj dedykowanych danych pul </target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Dane pul</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Dedykowany pul, kt\xf3ry przechowuje dane obiektowe z RBD</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>np. 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Musisz zwi\u0119kszy\u0107 rozmiar.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Zaawansowane</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Maskowanie</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Jednostka pask\xf3w</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Wybierz jednostk\u0119 pask\xf3w -- </target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Pole jest wymagane, poniewa\u017c licznik pask\xf3w jest zdefiniowany. </target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>Jednostka pask\xf3w jest wi\u0119ksza ni\u017c rozmiar obiektu.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Licznik pask\xf3w </target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Pole jest wymagane, poniewa\u017c jednostka pask\xf3w jest zdefiniowana! </target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Licznik pask\xf3w musi by\u0107 wi\u0119kszy od 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> migawka RBD\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, wybierz, prawda {Zmie\u0144 nazwe} inaczej{Utw\xf3rz} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Migawka\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>ZABEZPIECZONE</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>NIEZABEZPIECZONY </target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Zaraz si\u0119 wycofasz. </target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Usu\u0144 \u015amieci</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Aby usun\u0105\u0107, wybierz jeden albo wszystkie obrazy i kliknij </target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Pul:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nazwa pula</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Wszystkie</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Przywr\xf3\u0107 obraz</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Przywr\xf3\u0107</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>Wpisz nazwe nowego obrazu i kliknij. </target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nowa Nazwa</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Wygas\u0142y w</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Zabezpieczony do</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Ten obraz jest chroniony do \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Kosz</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologia iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Zmiana tych parametr\xf3w z domy\u015blnych warto\u015bci przewa\u017cnie nie jest potrzebna.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Ustawienia</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Tylny koniec przechowywania</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Potwierd\u017a</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Ustawienia zaawansowane</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>Nazwa IQN obiektu docelowego iSCSI</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>B\u0142\u0119dna sk\u0142adnia nazwy IQN.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN ma nast\u0119puj\u0105c\u0105 notacj\u0119 \u201eiqn. $ Rok-$ miesi\u0105c. $ odwr\xf3conyAdres: $ zdefiniowanaNazwa\u201d</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Na przyk\u0142ad: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Wi\u0119cej informacji</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Ten obiekt docelowy zmodyfikowa\u0142 zaawansowane ustawienia.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portale</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Wymagane s\u0105 przynajmniej \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> bramy.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Dodaj portal</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Ten obraz zmodyfikowa\u0142 ustawienia. </target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Dodaj obraz.</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Uwierzytelnianie ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Inicjatory iSCSI</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Inicjator iSCSI</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>Klient IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>Inicjator IQN powinien by\u0107 unikalny.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Nazwy u\u017cytkownik\xf3w musz\u0105 mie\u0107 d\u0142ugo\u015b\u0107 od 8 do 64 znak\xf3w i mog\u0105 zawiera\u0107 jedynie litery, \'.\', \'@\', \'-\', \'_\' lub \':\'.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>Inicjator iSCSI nale\u017c\u0105 do grupy. Obrazy b\u0119d\u0105 skonfigurowane w grupie. </target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Brak dodanych pozycji.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Dodaj inicjator iSCSI</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Grupy</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Grupa</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Dodaj grup\u0119</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Konfiguracja RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Usu\u0144 warto\u015b\u0107 konfiguracji lokalnej. Warto\u015b\u0107 konfiguracji rodzica b\u0119dzie odziedziczona i zostanie u\u017cyta zamiast tej.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>Minimalna warto\u015b\u0107 wynosi 0.</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Zagadnienia</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Synchronizacja</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Gotowy</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Tryb edycji lustrzanego pula</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Aby edytowa\u0107 tryb lustrzanydla pula\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, wybierz tryb z listy i kliknij\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Zaktualizuj\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Tryb</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Sparowany klaster musi by\u0107 usuni\u0119ty przed wy\u0142\u0105czeniem lustra. </target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> sparowany pul lustrzany\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, wybierz, edytuj{Edytuj} inaczej {Dodaj} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> pul \nlustra sparowanych atrybut\xf3w dla pula \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> i kliknij \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Zatwierd\u017a\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nazwa Klastra</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>Nazwa klastra jest niepoprawna </target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>ID CephX nie jest poprawne.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Adres monitora </target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Adresy rozdzielane przecinkami... </target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>Adres monitora nie jest poprawny.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>Klucz CephX</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Klucz zakodowany w Base64...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>Klucz CephX musi by\u0107 zakodowany w Base64/</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Lista puli</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>Nazwa mo\u017ce sk\u0142ada\u0107 si\u0119 z alfanumerycznych znak\xf3w, kresek i podkre\u015ble\u0144.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Wybrana nazwa profilu kodu kasowania jest ju\u017c u\u017cywana.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Wtyczka</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Ramka danych (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Musi by\u0107 wi\u0119ksza b\u0105d\u017a r\xf3wna 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Kodowanie kawa\u0142ka (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Musi by\u0107 wi\u0119ksza b\u0105d\u017a r\xf3wna 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Estymator trwa\u0142o\u015bci (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Lokalno\u015b\u0107 (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Domena niepowodzenia Crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Lokalno\u015b\u0107 Crusha</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Nic</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Technika</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Rozmiar pakietu</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>korze\u0144 Crusha</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>urz\u0105dzenie klasy Crush</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>kt\xf3rykolwiek</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Katalog</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Wybrana nazwa Ceph pula jest ju\u017c u\u017cyta.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Typ pula</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Wybierz typ pula --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Grupa umieszczenia</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Przynajmniej jedna grupa umieszczenia jest wymagana</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Tw\xf3j klaster nie obs\u0142uguje tylu PG. Skalkuluj prosz\u0119 potrzebn\u0105 ilo\u015b\u0107 PG.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Pomoc obliczeniowa</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>Obecne ustawienia PG zosta\u0142y policzone dla Ciebie, \npowiniene\u015b upewni\u0107 si\u0119 czy te warto\u015bci Ci odpowiadaj\u0105 przed zatwierdzeniem.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>zbi\xf3r zasad Crush</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Wybierz zasad\u0119 Crush --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>zasada Crush</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Kroki Crush</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Zasada nie mo\u017ce by\u0107 u\u017cyta w obecnym klastrze, gdy\u017c ma\nzbyt ma\u0142o OSD-k\xf3w, \u017ceby spe\u0142ni\u0107 minimum OSD-k\xf3w wymaganych przez t\u0119 zasad\u0119.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Replikowany rozmiar</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>Sprecyzowany rozmiar jest poza zakresem. Warto\u015b\u0107 od \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> do \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> jest poprawna.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Skasuj profil kodu.</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- Brak profilu kasowania --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Wybierz profil kodu wymazywania --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC Nadpisuje</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Zastosowania</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Kompresja</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algorytm</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- Brak algorytmu kompresji wymazywania --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Minimalny rozmiar blob</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>np. 128 KB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>Warto\u015b\u0107 powinna by\u0107 wi\u0119ksza ni\u017c 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Maksymalny rozmiar blob</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>np. 512 KB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>Warto\u015b\u0107 powinna by\u0107 wi\u0119ksza ni\u017c minimalny rozmiar blob</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Stosunek</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Skompresowany stosunek</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>Warto\u015b\u0107 powinna by\u0107 pomi\u0119dzy 0.0, a 1.0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Nie mo\u017cna stworzy\u0107 pula RBD z \'/\' w nazwie.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Prosz\u0119 zmieni\u0107 nazw\u0119 albo usun\u0105\u0107 \'rbd\' z listy zastosowa\u0144.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Szczeg\xf3\u0142y poziom\xf3w pami\u0119ci podr\u0119cznej</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Sprawd\u017a prosz\u0119 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentacj\u0119 \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\xa0\njak skonfigurowa\u0107 i i uruchomi\u0107 zarz\u0105dzanie funkcjami Dost\u0119pu obiektowego\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Lista demon\xf3w</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Liczniki wydajno\u015bci</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>\u0141adowanie wiadra danych</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Nie mo\u017cna za\u0142adowa\u0107 wiadra danych.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>Number ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>Warto\u015b\u0107 nie jest poprawna.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>W\u0142a\u015bciciel</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Wybierz u\u017cytkownika -- </target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Typ indeksu</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Zasada umieszczania</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Znacznik</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Maksymalny znacznik</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Wersja</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>G\u0142\xf3wna wersja</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Czas modyfikacji</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Strefa </target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>kontyngent wiadra</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Uaktywniony</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Maksymalny rozmiar</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Nielimitowany</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Maksimum obiekt\xf3w</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Wybierz nazw\u0119 u\u017cytkownika -- </target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Auto-generowany klucz</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Klucz dost\u0119pu</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Tajny klucz </target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Adres email</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Zawieszony</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>System</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, wybierz, 0 {Nie} 1{Tak} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Maksimum wiader</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>pod-u\u017cytkownicy</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Zdolno\u015bci</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Limit u\u017cytkownika</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Poka\u017c</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Klucze</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- wybierz typ --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Pozwolenie </target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Wybierz pozwolenie --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>pod-u\u017cytkownik</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>Wybrane ID pod-u\u017cytkownika jest ju\u017c u\u017cyte.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>odczyt, zapis</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>pe\u0142ny</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Szybki klucz</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Auto-generowany sekret</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>\u0141adowanie danych u\u017cytkownika...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>Nie mo\u017cna za\u0142adowa\u0107 danych u\u017cytkownika.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>Wybrane ID u\u017cytkownika jest ju\u017c u\u017cyte.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Ten adres email nie jest poprawny.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>Wybrany adres email jest ju\u017c u\u017cyty.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Max. wiader </target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>Podana warto\u015b\u0107 musi by\u0107 &gt;= 0</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>klucz S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Nie ma pod-u\u017cytkownik\xf3w.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3 (prosty serwis przechowywania) </target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Nie ma kluczy.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Szybki</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Nie ma zdolno\u015bci. </target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Nielimitowany rozmiar</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Max. rozmiar</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Nielimitowane obiekty</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Max. obiekt\xf3w</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Obecny</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Zaktualizowane uwierzytelnianie wykrywania</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Brak dost\u0119pnych portali.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Nie ma dost\u0119pnych obraz\xf3w. </target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Nie ma dost\u0119pnych obraz\xf3w. Prosz\u0119 si\u0119 upewni\u0107, \u017ce dodajesz obraz do obiektu docelowego. </target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Nie ma dost\u0119pnych inicjator\xf3w iSCSI. Prosz\u0119 upewni\u0107 si\u0119, \u017ce dodajesz inicjator iSCSI do obiektu docelowego.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>obiekt docelowy iSCSI</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Stan</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Odczyt bajt\xf3w </target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Zapis bajt\xf3w</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Odczyt Ops</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Zapis Ops</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O Od</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instancja</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nazwa hosta</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Zagadnienie </target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Progres</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Wy\u0142\u0105czony</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Tryb Edycji</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Dodaj parowanie </target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Edytuj parowanie</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Usu\u0144 parowanie</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Lider</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># Lokalny</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># Zdalny</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>lustrzane parowanie</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Klucz</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>G\u0142\u0119bokie sp\u0142aszczenie</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Warstwowanie </target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Wy\u0142\u0105czna blokada</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Mapa obiekt\xf3w (wymaga wy\u0142\u0105cznej blokady)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Kronikowanie (wymaga wy\u0142\u0105cznej blokady)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Wycofywanie migawek RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Wycofanie</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>migawka RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Usuni\u0119ty o </target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>id</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>typ</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>stan</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>wersja</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>administrator</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Ranga</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Demon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Aktywno\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>centrale</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>i-w\u0119z\u0142y</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>U\u017cycie</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Czuwanie demona </target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>Warto\u015b\u0107 mo\u017ce by\u0107 zaktualizowana w czasie wykonywania . </target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Demony/klienci nie pobieraj\u0105 tej warto\u015bci z\nbazy danych skonfigurowanego monitora. Nie zezwalamy na ustawienie tej opcji przez \'konfiguracje ceph\nustaw.. \'. Ta opcja powinna by\u0107 skonfigurowana przez ceph.conf albo przez\nterminal.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>Opcja dzia\u0142a tylko podczas startu demona.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>Opcja dotyczy tylko tworzenia klastra.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>Opcja tylko wp\u0142ywa na tworzenie demona.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Zaktualizowana opcja konfiguracji \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Us\u0142uga</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Obecna warto\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Edytowalny</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Zaktualizowane opcje dla modu\u0142u &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>W\u0142\u0105czy\u0107</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Wy\u0142\u0105czy\u0107</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Ponowne \u0142\u0105czenie, prosz\u0119 czeka\u0107</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Adres publiczny</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Otwarte sesje</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Nie w </target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>OSD-ki, kt\xf3re zosta\u0142y oznaczone jako poza, nie b\u0119d\u0105 oznaczone ponownie jako w gdy zostan\u0105 uruchomion</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Nie poza</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD-ki nie b\u0119d\u0105 automatycznie oznaczone jako poza po konfiguracji interwa\u0142u</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Nie powsta\u0142y </target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSD-ki nie mog\u0105 startowa\u0107</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Nie upad\u0142y</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Raport z niepowodzenia OSD jest ignorowany, tak\u017ce monitory nie oznacz\u0105 OSD jako upad\u0142ego. </target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pauza </target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Pauzuje czytanie i zapisywanie</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Nie szoruj</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Szorowanie jest wy\u0142\u0105czone</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Nie ma g\u0142\u0119bokiego szorowania</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>G\u0142\u0119bokie szorowanie jest wy\u0142\u0105czone</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Brak zasypywania</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Zasypywanie PG jest zawieszone</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Nie przywr\xf3cono</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Przywr\xf3cenie PGy jest zawieszone </target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Sortuj bitowo</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>U\u017cyj sortowania bitowego</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Usu\u0144 snap katalogi</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD-ki zmieni\u0142y snapsety</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Odzyskaj usuni\u0119te</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Podczas zdrowienia zastosowano usuni\u0119cie zamiast parowania</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Twardy limit log\xf3w PG</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Ustawia twardy limit na d\u0142ugo\u015b\u0107 log\xf3w PG</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Zaktualizowane flagi OSD-k\xf3w</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>poza</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>w</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>upad\u0142y</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Zaznacz</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>Stracony OSD</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>Zaznaczony jako stracony</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Czy\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD-ik</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>Oczyszczony</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>Zniszcz</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>Zniszczony</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>PG-y</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Czytanie bajt\xf3w</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Zapis bajt\xf3w</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Czytanie ops</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Zapis ops</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Zaznacz OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Zaznacz \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Max zasypywanie</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Max aktywno\u015b\u0107 wyzdrowienia</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Max pojedynczy start wyzdrowienia</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>U\u015bpienie wyzdrowienia</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Zwyczaj</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Zaktualizowano pr\u0119dko\u015b\u0107 wyzdrowienia OSD priorytet &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> zosta\u0142 zainicjalizowany w nast\u0119puj\u0105cym OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Praca</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>surowo\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Wystartowany</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Zaktualizowany</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>U\u017cyty</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Dost\u0119pny</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Czy\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>Dzia\u0142aj\u0105cy</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Ostrze\u017cenie </target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Nieznany</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>Podniesiony</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>brak system\xf3w plik\xf3w</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>aktywny</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>Rezerwa</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>niedost\u0119pny</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>aktywny demon</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>kworum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Us\u0142uga NFS Ganesha nie jest skonfigurowana</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transport</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>U\u017cytkownik CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>system plik\xf3w CephFS </target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(Odziedziczy\u0142o z globalnej konfiguracji)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>Odziedziczy\u0142o z globalnej konfiguracji</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Wybierz, jakiego rodzaju identyfikacja u\u017cytkownika ma by\u0107 przeprowadzana -- </target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Brak dost\u0119pnym demon\xf3w</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Tryb pami\u0119ci podr\u0119cznej</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Min wiek eksmisji</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Min wiek wyr\xf3wnania </target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Max bajt\xf3w obiektu docelowego </target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Max obiekt\xf3w docelowych</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Nie dodano \u017cadnego zastosowania</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Osi\u0105gni\u0119to limit zastosowa\u0144 </target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Pul mo\u017ce mie\u0107 maksymalnie 4 definicje aplikacji. </target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Dozwolone znaki \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>Maksymalna d\u0142ugo\u015b\u0107 wynosi 128 znak\xf3w</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtruj lub dodaj zastosowanie</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Dodaj zastosowanie</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>skasuj profil kodu</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Rozmiar repliki</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Ostatnia zmiana</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Skasuj profil zakodowany</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Zbi\xf3r zasad Crush</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Zapis bajt\xf3w </target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>wiadro</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Zaktualizowano wiadro dost\u0119pu obiektowego &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Stworzono wiadro dost\u0119pu obiektowego &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>Wiadra</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>u\u017cytkownik</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Zaktualizowano u\u017cytkownika dost\u0119pu obiektowego &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Stworzono u\u017cytkownika dost\u0119pu obiektowego&amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>u\u017cytkownicy</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Zakres</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Czytaj</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Stw\xf3rz</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Utw\xf3rz rol\u0119 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Zaktualizuj rol\u0119 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>System roli </target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Usu\u0144 rol\u0119 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Stw\xf3rz u\u017cytkownika &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Zaktualizuj u\u017cytkownika</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Kontynuuj </target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Zosta\u0142e\u015b automatycznie wylogowany, poniewa\u017c zosta\u0142y zmienione twoje role.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Zaktualizowano u\u017cytkownika &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Usuni\u0119to u\u017cytkownika &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Nie uda\u0142o si\u0119 usun\u0105\u0107 u\u017cytkownika &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Jeste\u015b obecnie zalogowany jako&amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Ka\u017cdy obiekt jest podzielony na cz\u0119\u015bci fragment\xf3w danych, ka\u017cdy jest przechowywany na innym OSD.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Oblicz porcje kodu dla ka\u017cdego obiektu i przechowuj je na r\xf3\u017cnych OSD.\n Liczba fragment\xf3w koduj\u0105cych to r\xf3wnie\u017c liczba OSD, kt\xf3re mog\u0105 zosta\u0107 wy\u0142\u0105czone bez utraty danych.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Wtyczka jerasure jest najbardziej uniwersaln\u0105 i elastyczn\u0105 wtyczk\u0105,\n jest to r\xf3wnie\u017c domy\u015blne ustawienie dla pui kodowanych przez Ceph.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>Bardziej elastyczn\u0105 technik\u0105 jest reed_sol_van: wystarczy ustawi\u0107 k\n oraz m. Technika cauchy_good mo\u017ce by\u0107 szybsza, ale musisz wybra\u0107 rozmiar pakietu\n ostro\u017cnie. Wszystkie reed_sol_r6_op, liberation, blaum_roth, liber8tion s\u0105 odpowiednikami RAID6\n w tym sensie, \u017ce mog\u0105 by\u0107 skonfigurowane tylko z m = 2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>Kodowanie b\u0119dzie wykonywane na pakietach o rozmiarze bajt\xf3w naraz.\n Wyb\xf3r odpowiedniego rozmiaru pakietu jest trudny.\n Dokumentacja jerasure zawiera obszerne informacje na ten temat.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Z wtyczk\u0105 jerasure, gdy obiekt zakodowany przy u\u017cyciu skasowania jest przechowywany na \n wielu OSD-kach, odzyskiwanie po utracie jednego OSD wymaga odczytu ze wszystkich pozosta\u0142ych.\n Na przyk\u0142ad, je\u015bli konfiguracja skryptu ma warto\u015b\u0107 k = 8 ,m = 4 i l=4, utrata jednego OSD wymaga odczytu\n od jedenastu innych do naprawy.\n\n Wtyczka kodu wymazywania lrc tworzy fragmenty o parzysto\u015bci lokalnej, aby m\xf3c je odzyska\u0107\n mniej OSD. Na przyk\u0142ad, je\u015bli lrc jest skonfigurowane z k = 8, m = 4 i l = 4, zostanie utworzony\n dodatkowy fragment parzysto\u015bci na ka\u017cde cztery OSD. Gdy jeden OSD zostanie utracone, mo\u017ce to by\u0107\n odzyskane tylko z czterema OSD zamiast jedenastu.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Grupuj fragmenty kodu i danych w zestawy lokalizacji wielko\u015bci. Na przyk\u0142ad,\n dla k = 4 i m = 2, gdy lokalno\u015b\u0107 = 3 tworzone s\u0105 dwie grupy po trzy. Ka\u017cdy zestaw mo\u017ce\n odzyska\u0107 bez czytania kawa\u0142k\xf3w z innego zestawu.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>Typ wiadra CRUSH, w kt\xf3rym zdefiniowano ka\u017cdy zestaw porcji\n przez l zostan\u0105 zapisane. Na przyk\u0142ad, je\u015bli jest ustawiony na rack, ka\u017cda grupa l porcji b\u0119dzie\n umieszczona w innym raku. S\u0142u\u017cy do utworzenia kroku regu\u0142y CRUSH, takiego jak krok wyboru\n racka. Je\u015bli nie jest ustawiony, nie ma takiego grupowania.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Wtyczka isa zawiera bibliotek\u0119 ISA. Dzia\u0142a tylko na procesorach Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>Wtyczka ISA jest dost\u0119pna w dw\xf3ch formach Reed Solomon.\n Je\u015bli ustawiono reed_sol_van, jest to Vandermonde, je\u015bli ustawiono cauchy, to jest to Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>Wtyczka shec zawiera wiele bibliotek SHEC.\n Pozwala ceph odzyska\u0107 dane bardziej efektywnie ni\u017c kody Reeda Solomona.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>Liczba kawa\u0142k\xf3w parzysto\u015bci, z kt\xf3rych ka\u017cdy zawiera ka\u017cd\u0105 porcj\u0119 danych w swoim zakresie oblicze\u0144. Liczba jest u\u017cywana jako estymator trwa\u0142o\u015bci. Na przyk\u0142ad, je\u015bli c = 2,\n 2 OSD mo\u017cna wy\u0142\u0105czy\u0107 bez utraty danych.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>Nazwa wiadra crush jest u\u017cyte do pierwszego kroku regu\u0142y CRUSH.\nNa przyk\u0142ad krok jest domy\u015blny.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Upewnij si\u0119, \u017ce \u017cadne dwie porcje nie znajduj\u0105 si\u0119 w wiadrze z t\u0105 sam\u0105 awari\u0105\n domeny. Na przyk\u0142ad, je\u015bli domena awarii jest hostem, nie zostan\u0105 na niej zapisane dwie porcje\n hosta. S\u0142u\u017cy do utworzenia kroku regu\u0142y CRUSH, takiego jak krok wyboru hosta.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Ogranicz umieszczanie do urz\u0105dze\u0144 okre\u015blonej klasy\n (np. ssd lub hdd), u\u017cywaj\u0105c nazw klas urz\u0105dze\u0144 zgniataj\u0105cych na mapie CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Ustaw nazw\u0119 katalogu, z kt\xf3rego \u0142adowana jest wtyczka kodu kasowania.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Dozwolone s\u0105 wszystkie operacje</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Dozwolone s\u0105 operacje, kt\xf3re nie modyfikuj\u0105 serweru</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>Operacje odczytu i zapisu s\u0105 zakazane, wszystkie inne dozwolone</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>Operacje odczytu i zapisu, oraz wszystkie operacje modyfikuj\u0105ce atrybuty albo katalogi s\u0105 zakazane\xa0</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>Brak dost\u0119pu w og\xf3le</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- wybierz priorytet -- </target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Niski</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Wysoki</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>Ostatnie 5 minut</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>Ostatnie 15 minut</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>Ostatnie 30 minut</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>Ostatnia 1 godzina (domy\u015blnie)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>Ostatnie 3 godziny</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>Ostatnie 6 godzin</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>Ostatnie 12 godzin</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>Ostatnie 24 godziny</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Wczoraj</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Dzisiaj</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Do tej pory dzisiaj</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Przedwczoraj</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Ostatnie 2 dni</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Tego dnia tydzie\u0144 temu</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>Poprzedni tydzie\u0144</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Ten tydzie\u0144 </target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Do tej pory w tym tygodniu</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Ostatnie 7 dni</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>Poprzedniego miesi\u0105ca</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>ten miesi\u0105c</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Do tej pory w tym miesi\u0105cu</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Ostatnie 30 dni</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Ostatnie 90 dni</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Ostatnie 6 miesi\u0119cy</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>Ostatni 1 rok</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>Poprzedniego roku</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Bie\u017c\u0105cego roku</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Do tej pory bie\u017c\u0105cego roku</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Ostatnie 2 lata</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Ostatnie 5 lat</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informacja</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Nie wybrano \u017cadnej pozycji</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Odznacz pozycj\u0119, \u017ceby wybra\u0107 ponownie</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Osi\u0105gni\u0119to limit wyboru. </target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Filtr tag\xf3w.</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Dodaj odznak\u0119</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Brak dost\u0119pnych pozycji.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Dodaj</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Sklonuj</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Kopia</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Szoruj g\u0142\u0119boko</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Zniszcz</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Sp\u0142aszcz</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>zaznacz jako upad\u0142y</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Zaznacz jako w </target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Zaznacz jako stracony</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Zaznacz jako poza</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Zabezpiecz</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Zmie\u0144 nazw\u0119</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Przywr\xf3\u0107</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>Przenie\u015b do kosza</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Odbezpiecz </target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Usuni\u0119ty</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Sklonowano</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Skopiowano </target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Tak</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>Nie</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Jako\u015b\u0107 serwisu</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>Limit BPS</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Po\u017c\u0105dany limit IO bajt\xf3w na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>Limit IOPS</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Po\u017c\u0105dany limit operacji IO na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>limit odczytu BPS</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Po\u017c\u0105dany limit odczytu bajt\xf3w na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>limit odczytu IOPS</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Po\u017c\u0105dany limit operacji odczytu na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Limit zapisu BPS</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Po\u017c\u0105dany limit zapisu bajt\xf3w na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Limit zapisu IOPS</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Po\u017c\u0105dany limit operacji zapisu na sekund\u0119.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>Wi\u0105zka BPS</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>\u017b\u0105dana granica serii IO bajt\xf3w.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>Wi\u0105zka IOPS</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>\u017b\u0105dana granica serii operacji IO.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Odczyt wi\u0105zki BPS</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>\u017b\u0105dana granica serii odczytanych bajt\xf3w.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Odczyt wi\u0105zki IOPS</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target> \u017b\u0105dana granica serii operacji odczytu.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Zapis wi\u0105zki BPS</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>\u017b\u0105dana granica serii bajt\xf3w zapisu.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Zapis wi\u0105zki IOPS</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>\u017b\u0105dana granica serii operacji zapisu.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Nie powiod\u0142o si\u0119 \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Wykonywanie </target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>Wykonaj</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Wykonany</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>Nieznane zadanie</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Tworzenie</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>Utw\xf3rz</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Aktualizowanie </target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>Zaktualizuj</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Usuwanie</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>Usu\u0144</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>urz\u0105dzenie blokowe Rados\xa0\'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\xa0\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>migawka RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\xa0\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>tryb lustrzany dla pula \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Lustrzane parowanie dla pula \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Nazwa jest ju\u017c u\u017cyta przez \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Nazwa jest ju\u017c u\u017cywana przez \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Nazwa jest ju\u017c u\u017cywana przez \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> zawiera migawk\u0119.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Klonowanie</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>Sklonuj </target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>Migawka \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\xa0 musi by\u0107 zabezpieczona.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Kopiowanie </target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>Kopiuj</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Sp\u0142aszczanie</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>Sp\u0142aszcz</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Sp\u0142aszczony</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Nazwa ju\u017c jest u\u017cywana przez \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Nie mo\u017cna zdj\u0105\u0107 zabezpieczenia \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> , poniewa\u017c zawiera pokrewne obrazy.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Nie mo\u017cna usun\u0105\u0107 \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, poniewa\u017c jest zabezpieczony.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Wycofywanie </target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>Wycofanie</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Wycofaj</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Przenoszenie</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>Przenie\u015b</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>Przeniesiono</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>Obraz \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' przenie\u015b do kosza\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Nie znaleziono obrazu.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Przywracanie</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>Przywr\xf3\u0107 </target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Przywr\xf3cony</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target> Obraz \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' w \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\' \n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Nazwa obrazu \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' jest ju\u017c u\u017cywana. \n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Obraz \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\xa0\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>oczyszcza\u0107</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>oczy\u015b\u0107</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Oczyszczony</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>Wszystkie pule</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>Obraz z \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Nie mo\u017cna wy\u0142\u0105czy\u0107 lustrzenia poniewa\u017c zawiera parowanie.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>pul \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>skasuj profil kodu \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>docelowy \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},"/TVo":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=(n("urB8"),n("0M9P"));n("xZld"),e.NodeDraggableDirective=function(){function t(t,e,n){this.element=t,this.nodeDraggableService=e,this.renderer=n,this.disposersForDragListeners=[],this.nodeNativeElement=t.nativeElement}return t.prototype.ngOnInit=function(){this.tree.isStatic()||(this.renderer.setAttribute(this.nodeNativeElement,"draggable","true"),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"dragenter",this.handleDragEnter.bind(this))),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"dragover",this.handleDragOver.bind(this))),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"dragstart",this.handleDragStart.bind(this))),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"dragleave",this.handleDragLeave.bind(this))),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"drop",this.handleDrop.bind(this))),this.disposersForDragListeners.push(this.renderer.listen(this.nodeNativeElement,"dragend",this.handleDragEnd.bind(this))))},t.prototype.ngOnDestroy=function(){this.disposersForDragListeners.forEach(function(t){return t()})},t.prototype.handleDragStart=function(e){e.stopPropagation&&e.stopPropagation(),this.nodeDraggableService.captureNode(new r.CapturedNode(this.nodeDraggable,this.tree)),e.dataTransfer.setData("text",t.DATA_TRANSFER_STUB_DATA),e.dataTransfer.effectAllowed="move"},t.prototype.handleDragOver=function(t){t.preventDefault(),t.dataTransfer.dropEffect="move"},t.prototype.handleDragEnter=function(t){t.preventDefault(),this.containsElementAt(t)&&this.addClass("over-drop-target")},t.prototype.handleDragLeave=function(t){this.containsElementAt(t)||this.removeClass("over-drop-target")},t.prototype.handleDrop=function(t){return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),this.removeClass("over-drop-target"),!!this.isDropPossible(t)&&(this.nodeDraggableService.getCapturedNode()?this.notifyThatNodeWasDropped():void 0)},t.prototype.isDropPossible=function(t){var e=this.nodeDraggableService.getCapturedNode();return e&&e.canBeDroppedAt(this.nodeDraggable)&&this.containsElementAt(t)},t.prototype.handleDragEnd=function(t){this.removeClass("over-drop-target"),this.nodeDraggableService.releaseCapturedNode()},t.prototype.containsElementAt=function(t){var e=t.x,n=t.y;return this.nodeNativeElement.contains(document.elementFromPoint(void 0===e?t.clientX:e,void 0===n?t.clientY:n))},t.prototype.addClass=function(t){this.nodeNativeElement.classList.add(t)},t.prototype.removeClass=function(t){this.nodeNativeElement.classList.remove(t)},t.prototype.notifyThatNodeWasDropped=function(){this.nodeDraggableService.fireNodeDragged(this.nodeDraggableService.getCapturedNode(),this.nodeDraggable)},t.DATA_TRANSFER_STUB_DATA="some browsers enable drag-n-drop only when dataTransfer has data",t.decorators=[{type:a.Directive,args:[{selector:"[nodeDraggable]"}]}],t.propDecorators={nodeDraggable:[{type:a.Input}],tree:[{type:a.Input}]},t}()},"/WYv":function(t,e,n){"use strict";function a(t){return!!t&&"function"!=typeof t.subscribe&&"function"==typeof t.then}n.d(e,"a",function(){return a})},"/X5v":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("x-pseudo",{months:"J~\xe1\xf1\xfa\xe1~r\xfd_F~\xe9br\xfa~\xe1r\xfd_~M\xe1rc~h_\xc1p~r\xedl_~M\xe1\xfd_~J\xfa\xf1\xe9~_J\xfal~\xfd_\xc1\xfa~g\xfast~_S\xe9p~t\xe9mb~\xe9r_\xd3~ct\xf3b~\xe9r_\xd1~\xf3v\xe9m~b\xe9r_~D\xe9c\xe9~mb\xe9r".split("_"),monthsShort:"J~\xe1\xf1_~F\xe9b_~M\xe1r_~\xc1pr_~M\xe1\xfd_~J\xfa\xf1_~J\xfal_~\xc1\xfag_~S\xe9p_~\xd3ct_~\xd1\xf3v_~D\xe9c".split("_"),monthsParseExact:!0,weekdays:"S~\xfa\xf1d\xe1~\xfd_M\xf3~\xf1d\xe1\xfd~_T\xfa\xe9~sd\xe1\xfd~_W\xe9d~\xf1\xe9sd~\xe1\xfd_T~h\xfars~d\xe1\xfd_~Fr\xedd~\xe1\xfd_S~\xe1t\xfar~d\xe1\xfd".split("_"),weekdaysShort:"S~\xfa\xf1_~M\xf3\xf1_~T\xfa\xe9_~W\xe9d_~Th\xfa_~Fr\xed_~S\xe1t".split("_"),weekdaysMin:"S~\xfa_M\xf3~_T\xfa_~W\xe9_T~h_Fr~_S\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~\xf3d\xe1~\xfd \xe1t] LT",nextDay:"[T~\xf3m\xf3~rr\xf3~w \xe1t] LT",nextWeek:"dddd [\xe1t] LT",lastDay:"[\xdd~\xe9st~\xe9rd\xe1~\xfd \xe1t] LT",lastWeek:"[L~\xe1st] dddd [\xe1t] LT",sameElse:"L"},relativeTime:{future:"\xed~\xf1 %s",past:"%s \xe1~g\xf3",s:"\xe1 ~f\xe9w ~s\xe9c\xf3~\xf1ds",ss:"%d s~\xe9c\xf3\xf1~ds",m:"\xe1 ~m\xed\xf1~\xfat\xe9",mm:"%d m~\xed\xf1\xfa~t\xe9s",h:"\xe1~\xf1 h\xf3~\xfar",hh:"%d h~\xf3\xfars",d:"\xe1 ~d\xe1\xfd",dd:"%d d~\xe1\xfds",M:"\xe1 ~m\xf3\xf1~th",MM:"%d m~\xf3\xf1t~hs",y:"\xe1 ~\xfd\xe9\xe1r",yy:"%d \xfd~\xe9\xe1rs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},0:function(t,e,n){t.exports=n("zUnb")},"0+/T":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("gIcY"),r=n("QFaf"),i=(n("sb0X"),function(){function t(t){this.modalRef=t,this.actionDescription="delete"}return t.prototype.ngOnInit=function(){if(this.deletionForm=new r.a({confirmation:new a.i(!1,[a.A.requiredTrue])}),!this.submitAction&&!this.submitActionObservable)throw new Error("No submit action defined")},t.prototype.callSubmitAction=function(){this.submitActionObservable?this.submitActionObservable().subscribe(null,this.stopLoadingSpinner.bind(this),this.hideModal.bind(this)):this.submitAction()},t.prototype.hideModal=function(){this.modalRef.hide()},t.prototype.stopLoadingSpinner=function(){this.deletionForm.setErrors({cdSubmitButton:!0})},t}())},"0/uQ":function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("6blF"),r=n("Fxb1"),i=n("i4X3");function s(t,e){return e?Object(i.a)(t,e):t instanceof a.a?t:new a.a(Object(r.a)(t))}},"0M9P":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CapturedNode=function(){function t(t,e){this.anElement=t,this.aTree=e}return t.prototype.canBeDroppedAt=function(t){return!this.sameAs(t)&&!this.contains(t)},t.prototype.contains=function(t){return this.element.nativeElement.contains(t.nativeElement)},t.prototype.sameAs=function(t){return this.element===t},Object.defineProperty(t.prototype,"element",{get:function(){return this.anElement},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"tree",{get:function(){return this.aTree},enumerable:!0,configurable:!0}),t}()},"0MID":function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("qwkt"),o=n("5tze");n("czA5"),e.DataTableHeaderCellComponent=function(){function t(t){this.cd=t,this.sort=new i.EventEmitter,this.select=new i.EventEmitter,this.columnContextmenu=new i.EventEmitter(!1),this.sortFn=this.onSort.bind(this),this.selectFn=this.select.emit.bind(this.select),this.cellContext={column:this.column,sortDir:this.sortDir,sortFn:this.sortFn,allRowsSelected:this.allRowsSelected,selectFn:this.selectFn}}return Object.defineProperty(t.prototype,"allRowsSelected",{get:function(){return this._allRowsSelected},set:function(t){this._allRowsSelected=t,this.cellContext.allRowsSelected=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"column",{get:function(){return this._column},set:function(t){this._column=t,this.cellContext.column=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"sorts",{get:function(){return this._sorts},set:function(t){this._sorts=t,this.sortDir=this.calcSortDir(t),this.cellContext.sortDir=this.sortDir,this.sortClass=this.calcSortClass(this.sortDir),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnCssClasses",{get:function(){var t="datatable-header-cell";if(this.column.sortable&&(t+=" sortable"),this.column.resizeable&&(t+=" resizeable"),this.column.headerClass)if("string"==typeof this.column.headerClass)t+=" "+this.column.headerClass;else if("function"==typeof this.column.headerClass){var e=this.column.headerClass({column:this.column});if("string"==typeof e)t+=e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}var i=this.sortDir;return i&&(t+=" sort-active sort-"+i),t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return void 0===this.column.headerTemplate?this.column.name:void 0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"minWidth",{get:function(){return this.column.minWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"maxWidth",{get:function(){return this.column.maxWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"width",{get:function(){return this.column.width},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCheckboxable",{get:function(){return this.column.checkboxable&&this.column.headerCheckboxable&&this.selectionType===s.SelectionType.checkbox},enumerable:!0,configurable:!0}),t.prototype.onContextmenu=function(t){this.columnContextmenu.emit({event:t,column:this.column})},t.prototype.calcSortDir=function(t){var e=this;if(t&&this.column){var n=t.find(function(t){return t.prop===e.column.prop});if(n)return n.dir}},t.prototype.onSort=function(){if(this.column.sortable){var t=o.nextSortDir(this.sortType,this.sortDir);this.sort.emit({column:this.column,prevValue:this.sortDir,newValue:t})}},t.prototype.calcSortClass=function(t){return t===s.SortDirection.asc?"sort-btn sort-asc "+this.sortAscendingIcon:t===s.SortDirection.desc?"sort-btn sort-desc "+this.sortDescendingIcon:"sort-btn"},a([i.Input(),r("design:type",String)],t.prototype,"sortType",void 0),a([i.Input(),r("design:type",String)],t.prototype,"sortAscendingIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"sortDescendingIcon",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"isTarget",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"targetMarkerContext",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"allRowsSelected",null),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"column",null),a([i.HostBinding("style.height.px"),i.Input(),r("design:type",Number)],t.prototype,"headerHeight",void 0),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"sorts",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"sort",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"columnContextmenu",void 0),a([i.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"columnCssClasses",null),a([i.HostBinding("attr.title"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"name",null),a([i.HostBinding("style.minWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"minWidth",null),a([i.HostBinding("style.maxWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"maxWidth",null),a([i.HostBinding("style.width.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"width",null),a([i.HostListener("contextmenu",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onContextmenu",null),a([i.Component({selector:"datatable-header-cell",template:'\n <div class="datatable-header-cell-template-wrap">\n <ng-template\n *ngIf="isTarget"\n [ngTemplateOutlet]="targetMarkerTemplate"\n [ngTemplateOutletContext]="targetMarkerContext">\n </ng-template>\n <label\n *ngIf="isCheckboxable"\n class="datatable-checkbox">\n <input\n type="checkbox"\n [checked]="allRowsSelected"\n (change)="select.emit(!allRowsSelected)"\n />\n </label>\n <span\n *ngIf="!column.headerTemplate"\n class="datatable-header-cell-wrapper">\n <span\n class="datatable-header-cell-label draggable"\n (click)="onSort()"\n [innerHTML]="name">\n </span>\n </span>\n <ng-template\n *ngIf="column.headerTemplate"\n [ngTemplateOutlet]="column.headerTemplate"\n [ngTemplateOutletContext]="cellContext">\n </ng-template>\n <span\n (click)="onSort()"\n [class]="sortClass">\n </span>\n </div>\n ',host:{class:"datatable-header-cell"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},"0mo+":function(t,e,n){!function(t){"use strict";var e={1:"\u0f21",2:"\u0f22",3:"\u0f23",4:"\u0f24",5:"\u0f25",6:"\u0f26",7:"\u0f27",8:"\u0f28",9:"\u0f29",0:"\u0f20"},n={"\u0f21":"1","\u0f22":"2","\u0f23":"3","\u0f24":"4","\u0f25":"5","\u0f26":"6","\u0f27":"7","\u0f28":"8","\u0f29":"9","\u0f20":"0"};t.defineLocale("bo",{months:"\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54".split("_"),monthsShort:"\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54".split("_"),weekdays:"\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b_\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b_\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b_\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b_\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74_\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b_\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b".split("_"),weekdaysShort:"\u0f49\u0f72\u0f0b\u0f58\u0f0b_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b_\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b_\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b_\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74_\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b_\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b".split("_"),weekdaysMin:"\u0f49\u0f72\u0f0b\u0f58\u0f0b_\u0f5f\u0fb3\u0f0b\u0f56\u0f0b_\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b_\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b_\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74_\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b_\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[\u0f51\u0f72\u0f0b\u0f62\u0f72\u0f44] LT",nextDay:"[\u0f66\u0f44\u0f0b\u0f49\u0f72\u0f53] LT",nextWeek:"[\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f55\u0fb2\u0f42\u0f0b\u0f62\u0f97\u0f7a\u0f66\u0f0b\u0f58], LT",lastDay:"[\u0f41\u0f0b\u0f66\u0f44] LT",lastWeek:"[\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f55\u0fb2\u0f42\u0f0b\u0f58\u0f50\u0f60\u0f0b\u0f58] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0f63\u0f0b",past:"%s \u0f66\u0f94\u0f53\u0f0b\u0f63",s:"\u0f63\u0f58\u0f0b\u0f66\u0f44",ss:"%d \u0f66\u0f90\u0f62\u0f0b\u0f46\u0f0d",m:"\u0f66\u0f90\u0f62\u0f0b\u0f58\u0f0b\u0f42\u0f45\u0f72\u0f42",mm:"%d \u0f66\u0f90\u0f62\u0f0b\u0f58",h:"\u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0b\u0f42\u0f45\u0f72\u0f42",hh:"%d \u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51",d:"\u0f49\u0f72\u0f53\u0f0b\u0f42\u0f45\u0f72\u0f42",dd:"%d \u0f49\u0f72\u0f53\u0f0b",M:"\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f45\u0f72\u0f42",MM:"%d \u0f5f\u0fb3\u0f0b\u0f56",y:"\u0f63\u0f7c\u0f0b\u0f42\u0f45\u0f72\u0f42",yy:"%d \u0f63\u0f7c"},preparse:function(t){return t.replace(/[\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\u0f29\u0f20]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0f58\u0f5a\u0f53\u0f0b\u0f58\u0f7c|\u0f5e\u0f7c\u0f42\u0f66\u0f0b\u0f40\u0f66|\u0f49\u0f72\u0f53\u0f0b\u0f42\u0f74\u0f44|\u0f51\u0f42\u0f7c\u0f44\u0f0b\u0f51\u0f42|\u0f58\u0f5a\u0f53\u0f0b\u0f58\u0f7c/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0f58\u0f5a\u0f53\u0f0b\u0f58\u0f7c"===e&&t>=4||"\u0f49\u0f72\u0f53\u0f0b\u0f42\u0f74\u0f44"===e&&t<5||"\u0f51\u0f42\u0f7c\u0f44\u0f0b\u0f51\u0f42"===e?t+12:t},meridiem:function(t,e,n){return t<4?"\u0f58\u0f5a\u0f53\u0f0b\u0f58\u0f7c":t<10?"\u0f5e\u0f7c\u0f42\u0f66\u0f0b\u0f40\u0f66":t<17?"\u0f49\u0f72\u0f53\u0f0b\u0f42\u0f74\u0f44":t<20?"\u0f51\u0f42\u0f7c\u0f44\u0f0b\u0f51\u0f42":"\u0f58\u0f5a\u0f53\u0f0b\u0f58\u0f7c"},week:{dow:0,doy:6}})}(n("wd/R"))},"0tRk":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("pt-br",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Do_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [\xe0s] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [\xe0s] HH:mm"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"h\xe1 %s",s:"poucos segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba"})}()},"15JJ":function(t,e,n){"use strict";n.d(e,"a",function(){return c});var a=n("mrSG"),r=n("MGBS"),i=n("rPjj"),s=n("zotm"),o=n("67Y/"),u=n("0/uQ");function c(t,e){return"function"==typeof e?function(n){return n.pipe(c(function(n,a){return Object(u.a)(t(n,a)).pipe(Object(o.a)(function(t,r){return e(n,t,a,r)}))}))}:function(e){return e.lift(new l(t))}}var l=function(){function t(t){this.project=t}return t.prototype.call=function(t,e){return e.subscribe(new d(t,this.project))},t}(),d=function(t){function e(e,n){var a=t.call(this,e)||this;return a.project=n,a.index=0,a}return a.__extends(e,t),e.prototype._next=function(t){var e,n=this.index++;try{e=this.project(t,n)}catch(a){return void this.destination.error(a)}this._innerSub(e,t,n)},e.prototype._innerSub=function(t,e,n){var a=this.innerSubscription;a&&a.unsubscribe();var r=new i.a(this,void 0,void 0);this.destination.add(r),this.innerSubscription=Object(s.a)(this,t,e,n,r)},e.prototype._complete=function(){var e=this.innerSubscription;e&&!e.closed||t.prototype._complete.call(this),this.unsubscribe()},e.prototype._unsubscribe=function(){this.innerSubscription=null},e.prototype.notifyComplete=function(e){this.destination.remove(e),this.innerSubscription=null,this.isStopped&&t.prototype._complete.call(this)},e.prototype.notifyNext=function(t,e,n,a,r){this.destination.next(e)},e}(r.a)},"1HVU":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("rdkg"),r=n("CVuo"),i="undefined"!=typeof window?a.getVendorPrefixedName("transform"):void 0,s="undefined"!=typeof window?a.getVendorPrefixedName("backfaceVisibility"):void 0,o="undefined"!=typeof window?!!a.getVendorPrefixedName("transform"):void 0,u="undefined"!=typeof window?!!a.getVendorPrefixedName("perspective"):void 0,c="undefined"!=typeof window?window.navigator.userAgent:"Chrome",l=/Safari\//.test(c)&&!/Chrome\//.test(c);e.translateXY=function(t,e,n){void 0!==i&&o?!l&&u?(t[i]="translate3d("+e+"px, "+n+"px, 0)",t[s]="hidden"):t[r.camelCase(i)]="translate("+e+"px, "+n+"px)":(t.top=n+"px",t.left=e+"px")}},"1Ni5":function(t,e,n){"use strict";n.d(e,"b",function(){return l}),n.d(e,"a",function(){return d});var a=n("gIcY"),r=n("LvDl"),i=n("F/XL"),s=n("gI3B"),o=n("zQHH"),u=n("67Y/"),c=n("t9fZ");function l(t){return null==t||0===t.length}var d=function(){function t(){}return t.email=function(t){return l(t.value)?null:a.A.email(t)},t.ip=function(t){void 0===t&&(t=0);var e=/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i,n=/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;return a.A.pattern(4===t?e:6===t?n:new RegExp(e.source+"|"+n.source))},t.number=function(t){return void 0===t&&(t=!0),a.A.pattern(t?/^-?[0-9]+$/i:/^[0-9]+$/i)},t.decimalNumber=function(t){return void 0===t&&(t=!0),a.A.pattern(t?/^-?[0-9]+(.[0-9]+)?$/i:/^[0-9]+(.[0-9]+)?$/i)},t.requiredIf=function(t,e){var n=!1;return function(a){return!n&&a.parent&&(Object.keys(t).forEach(function(t){a.parent.get(t).valueChanges.subscribe(function(){a.updateValueAndValidity({emitEvent:!1})})}),n=!0),Object.keys(t).every(function(e){return a.parent&&a.parent.get(e).value===t[e]})&&(r.isFunction(e)?e.call(e,a.value):l(a.value))?{required:!0}:null}},t.custom=function(t,e){var n=this;return function(a){var r,i=e.call(n,a.value);return i?((r={})[t]=i,r):null}},t.validateIf=function(t,e,n,r,i){var s=this;void 0===r&&(r=[]),void 0===i&&(i=[]),n=n.concat(r),t.setValidators(function(t){return e.call(s)?a.A.compose(n)(t):r.length>0?a.A.compose(r)(t):null}),i.forEach(function(e){e.valueChanges.subscribe(function(){t.updateValueAndValidity({emitEvent:!1})})})},t.match=function(t,e){return function(n){var a=n.get(t),i=n.get(e);if(a.value!==i.value)i.setErrors({match:!0});else if(i.hasError("match")){var s=i.errors;r.unset(s,"match"),i.setErrors(r.isEmpty(r.keys(s))?null:s)}return null}},t.unique=function(t,e,n){return void 0===e&&(e=null),void 0===n&&(n=500),function(a){return a.pristine||l(a.value)?Object(i.a)(null):Object(s.a)(n).pipe(Object(o.a)(t.call(e,a.value)),Object(u.a)(function(t){return t?{notUnique:!0}:null}),Object(c.a)(1))}},t.uuid=function(t){void 0===t&&(t=!1);var e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return function(n){return n.pristine&&n.untouched?null:t||n.value?e.test(n.value)?null:{invalidUuid:"This is not a valid UUID"}:null}},t}()},"1PfE":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NodeEditableEventAction=function(t){return t[t.Cancel=0]="Cancel",t}(e.NodeEditableEventAction||{})},"1fDf":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("FFOo");function r(t){for(;t;){var e=t.destination;if(t.closed||t.isStopped)return!1;t=e&&e instanceof a.a?e:null}return!0}},"1rYy":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("hy-am",{months:{format:"\u0570\u0578\u0582\u0576\u057e\u0561\u0580\u056b_\u0583\u0565\u057f\u0580\u057e\u0561\u0580\u056b_\u0574\u0561\u0580\u057f\u056b_\u0561\u057a\u0580\u056b\u056c\u056b_\u0574\u0561\u0575\u056b\u057d\u056b_\u0570\u0578\u0582\u0576\u056b\u057d\u056b_\u0570\u0578\u0582\u056c\u056b\u057d\u056b_\u0585\u0563\u0578\u057d\u057f\u0578\u057d\u056b_\u057d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580\u056b_\u0570\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b_\u0576\u0578\u0575\u0565\u0574\u0562\u0565\u0580\u056b_\u0564\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b".split("_"),standalone:"\u0570\u0578\u0582\u0576\u057e\u0561\u0580_\u0583\u0565\u057f\u0580\u057e\u0561\u0580_\u0574\u0561\u0580\u057f_\u0561\u057a\u0580\u056b\u056c_\u0574\u0561\u0575\u056b\u057d_\u0570\u0578\u0582\u0576\u056b\u057d_\u0570\u0578\u0582\u056c\u056b\u057d_\u0585\u0563\u0578\u057d\u057f\u0578\u057d_\u057d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580_\u0570\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580_\u0576\u0578\u0575\u0565\u0574\u0562\u0565\u0580_\u0564\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580".split("_")},monthsShort:"\u0570\u0576\u057e_\u0583\u057f\u0580_\u0574\u0580\u057f_\u0561\u057a\u0580_\u0574\u0575\u057d_\u0570\u0576\u057d_\u0570\u056c\u057d_\u0585\u0563\u057d_\u057d\u057a\u057f_\u0570\u056f\u057f_\u0576\u0574\u0562_\u0564\u056f\u057f".split("_"),weekdays:"\u056f\u056b\u0580\u0561\u056f\u056b_\u0565\u0580\u056f\u0578\u0582\u0577\u0561\u0562\u0569\u056b_\u0565\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b_\u0579\u0578\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b_\u0570\u056b\u0576\u0563\u0577\u0561\u0562\u0569\u056b_\u0578\u0582\u0580\u0562\u0561\u0569_\u0577\u0561\u0562\u0561\u0569".split("_"),weekdaysShort:"\u056f\u0580\u056f_\u0565\u0580\u056f_\u0565\u0580\u0584_\u0579\u0580\u0584_\u0570\u0576\u0563_\u0578\u0582\u0580\u0562_\u0577\u0562\u0569".split("_"),weekdaysMin:"\u056f\u0580\u056f_\u0565\u0580\u056f_\u0565\u0580\u0584_\u0579\u0580\u0584_\u0570\u0576\u0563_\u0578\u0582\u0580\u0562_\u0577\u0562\u0569".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0569.",LLL:"D MMMM YYYY \u0569., HH:mm",LLLL:"dddd, D MMMM YYYY \u0569., HH:mm"},calendar:{sameDay:"[\u0561\u0575\u057d\u0585\u0580] LT",nextDay:"[\u057e\u0561\u0572\u0568] LT",lastDay:"[\u0565\u0580\u0565\u056f] LT",nextWeek:function(){return"dddd [\u0585\u0580\u0568 \u056a\u0561\u0574\u0568] LT"},lastWeek:function(){return"[\u0561\u0576\u0581\u0561\u056e] dddd [\u0585\u0580\u0568 \u056a\u0561\u0574\u0568] LT"},sameElse:"L"},relativeTime:{future:"%s \u0570\u0565\u057f\u0578",past:"%s \u0561\u057c\u0561\u057b",s:"\u0574\u056b \u0584\u0561\u0576\u056b \u057e\u0561\u0575\u0580\u056f\u0575\u0561\u0576",ss:"%d \u057e\u0561\u0575\u0580\u056f\u0575\u0561\u0576",m:"\u0580\u0578\u057a\u0565",mm:"%d \u0580\u0578\u057a\u0565",h:"\u056a\u0561\u0574",hh:"%d \u056a\u0561\u0574",d:"\u0585\u0580",dd:"%d \u0585\u0580",M:"\u0561\u0574\u056b\u057d",MM:"%d \u0561\u0574\u056b\u057d",y:"\u057f\u0561\u0580\u056b",yy:"%d \u057f\u0561\u0580\u056b"},meridiemParse:/\u0563\u056b\u0577\u0565\u0580\u057e\u0561|\u0561\u057c\u0561\u057e\u0578\u057f\u057e\u0561|\u0581\u0565\u0580\u0565\u056f\u057e\u0561|\u0565\u0580\u0565\u056f\u0578\u0575\u0561\u0576/,isPM:function(t){return/^(\u0581\u0565\u0580\u0565\u056f\u057e\u0561|\u0565\u0580\u0565\u056f\u0578\u0575\u0561\u0576)$/.test(t)},meridiem:function(t){return t<4?"\u0563\u056b\u0577\u0565\u0580\u057e\u0561":t<12?"\u0561\u057c\u0561\u057e\u0578\u057f\u057e\u0561":t<17?"\u0581\u0565\u0580\u0565\u056f\u057e\u0561":"\u0565\u0580\u0565\u056f\u0578\u0575\u0561\u0576"},dayOfMonthOrdinalParse:/\d{1,2}|\d{1,2}-(\u056b\u0576|\u0580\u0564)/,ordinal:function(t,e){switch(e){case"DDD":case"w":case"W":case"DDDo":return 1===t?t+"-\u056b\u0576":t+"-\u0580\u0564";default:return t}},week:{dow:1,doy:7}})}()},"1xZ4":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ca",{months:{standalone:"gener_febrer_mar\xe7_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),format:"de gener_de febrer_de mar\xe7_d'abril_de maig_de juny_de juliol_d'agost_de setembre_d'octubre_de novembre_de desembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._mar\xe7_abr._maig_juny_jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dt_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a les] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a les] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[dem\xe0 a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"d'aqu\xed %s",past:"fa %s",s:"uns segons",ss:"%d segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|\xe8|a)/,ordinal:function(t,e){var n=1===t?"r":2===t?"n":3===t?"r":4===t?"t":"\xe8";return"w"!==e&&"W"!==e||(n="a"),t+n},week:{dow:1,doy:4}})}()},"20UP":function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("t/Na"),i=n("pL04"),s=function(){function t(t){this.http=t,this.settings={}}return t.prototype.ifSettingConfigured=function(t,e,n){var a=this,r=this.settings[t];void 0===r?this.http.get(t).subscribe(function(r){a.settings[t]=a.getSettingsValue(r),a.ifSettingConfigured(t,e,n)},function(e){401!==e.status&&(a.settings[t]="")}):""!==r?e(r):n&&n()},t.prototype.disableSetting=function(t){this.settings[t]=""},t.prototype.getSettingsValue=function(t){return t.value||t.instance||""},t.prototype.validateGrafanaDashboardUrl=function(t){return this.http.get("api/grafana/validation/"+t)},t.ngInjectableDef=a.defineInjectable({factory:function(){return new t(a.inject(r.c))},token:t,providedIn:i.a}),t}()},"25BL":function(t,e,n){"use strict";var a=n("CcnG"),r=n("M/6F"),i=n("NDi4"),s=n("Ip0R"),o=n("gIcY"),u=n("xtZt"),c=n("lqqz"),l=n("fhFe"),d=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function f(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"li",[["class","pages"],["role","button"]],[[1,"aria-label",0],[2,"active",null]],null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"a",[["href","javascript:void(0)"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.selectPage(t.context.$implicit.number)&&a),a},null,null)),(t()(),a["\u0275ted"](2,null,[" "," "]))],null,function(t,e){t(e,0,0,"page "+e.context.$implicit.number,e.context.$implicit.number===e.component.page),t(e,2,0,e.context.$implicit.text)})}function p(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,14,"ul",[["class","pager"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,2,"li",[],[[2,"disabled",null]],null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,1,"a",[["aria-label","go to first page"],["href","javascript:void(0)"],["role","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.selectPage(1)&&a),a},null,null)),(t()(),a["\u0275eld"](3,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](4,0,null,null,2,"li",[],[[2,"disabled",null]],null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"a",[["aria-label","go to previous page"],["href","javascript:void(0)"],["role","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.prevPage()&&a),a},null,null)),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,f)),a["\u0275did"](8,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275eld"](9,0,null,null,2,"li",[],[[2,"disabled",null]],null,null,null,null)),(t()(),a["\u0275eld"](10,0,null,null,1,"a",[["aria-label","go to next page"],["href","javascript:void(0)"],["role","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.nextPage()&&a),a},null,null)),(t()(),a["\u0275eld"](11,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](12,0,null,null,2,"li",[],[[2,"disabled",null]],null,null,null,null)),(t()(),a["\u0275eld"](13,0,null,null,1,"a",[["aria-label","go to last page"],["href","javascript:void(0)"],["role","button"]],null,[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.selectPage(r.totalPages)&&a),a},null,null)),(t()(),a["\u0275eld"](14,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null))],function(t,e){t(e,8,0,e.component.pages)},function(t,e){var n=e.component;t(e,1,0,!n.canPrevious()),t(e,3,0,a["\u0275inlineInterpolate"](1,"",n.pagerPreviousIcon,"")),t(e,4,0,!n.canPrevious()),t(e,6,0,a["\u0275inlineInterpolate"](1,"",n.pagerLeftArrowIcon,"")),t(e,9,0,!n.canNext()),t(e,11,0,a["\u0275inlineInterpolate"](1,"",n.pagerRightArrowIcon,"")),t(e,12,0,!n.canNext()),t(e,14,0,a["\u0275inlineInterpolate"](1,"",n.pagerNextIcon,""))})}var h=n("JxMD"),g=n("dgut"),b=n("Fgil"),m=n("ZYCi"),y=n("o4+5"),v=n("aXbf"),_=n("TJUb"),x=n("0MID"),T=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function w(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function S(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,w)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.targetMarkerContext,n.targetMarkerTemplate)},null)}function O(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"label",[["class","datatable-checkbox"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"input",[["type","checkbox"]],[[8,"checked",0]],[[null,"change"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==r.select.emit(!r.allRowsSelected)&&a),a},null,null))],null,function(t,e){t(e,1,0,e.component.allRowsSelected)})}function I(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","datatable-header-cell-wrapper"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"span",[["class","datatable-header-cell-label draggable"]],[[8,"innerHTML",1]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onSort()&&a),a},null,null))],null,function(t,e){t(e,1,0,e.component.name)})}function C(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function k(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,C)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.cellContext,n.column.headerTemplate)},null)}function N(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,9,"div",[["class","datatable-header-cell-template-wrap"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,S)),a["\u0275did"](2,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,O)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,I)),a["\u0275did"](6,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,k)),a["\u0275did"](8,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](9,0,null,null,0,"span",[],[[8,"className",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onSort()&&a),a},null,null))],function(t,e){var n=e.component;t(e,2,0,n.isTarget),t(e,4,0,n.isCheckboxable),t(e,6,0,!n.column.headerTemplate),t(e,8,0,n.column.headerTemplate)},function(t,e){t(e,9,0,e.component.sortClass)})}var R=n("3MdB"),A=n("M9eX"),D=n("Cc8h"),E=n("ylLw"),L=n("ZYjt"),P=n("tFKq"),M=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function q(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"datatable-header-cell",[["class","datatable-header-cell"],["draggable",""],["long-press",""],["resizeable",""]],[[2,"resizeable",null],[2,"press",null],[2,"longpress",null],[4,"height","px"],[8,"className",0],[1,"title",0],[4,"minWidth","px"],[4,"maxWidth","px"],[4,"width","px"]],[[null,"resize"],[null,"longPressStart"],[null,"longPressEnd"],[null,"sort"],[null,"select"],[null,"columnContextmenu"],[null,"mousedown"],[null,"contextmenu"]],function(t,e,n){var r=!0,i=t.component;return"mousedown"===e&&(r=!1!==a["\u0275nov"](t,2).onMousedown(n)&&r),"mousedown"===e&&(r=!1!==a["\u0275nov"](t,3).onMouseDown(n)&&r),"contextmenu"===e&&(r=!1!==a["\u0275nov"](t,4).onContextmenu(n)&&r),"resize"===e&&(r=!1!==i.onColumnResized(n,t.context.$implicit)&&r),"longPressStart"===e&&(r=!1!==i.onLongPressStart(n)&&r),"longPressEnd"===e&&(r=!1!==i.onLongPressEnd(n)&&r),"sort"===e&&(r=!1!==i.onSort(n)&&r),"select"===e&&(r=!1!==i.select.emit(n)&&r),"columnContextmenu"===e&&(r=!1!==i.columnContextmenu.emit(n)&&r),r},N,T)),a["\u0275did"](1,671744,[[1,4]],0,R.DraggableDirective,[a.ElementRef],{dragEventTarget:[0,"dragEventTarget"],dragModel:[1,"dragModel"],dragX:[2,"dragX"],dragY:[3,"dragY"]},null),a["\u0275did"](2,4341760,null,0,A.ResizeableDirective,[a.ElementRef,a.Renderer2],{resizeEnabled:[0,"resizeEnabled"]},{resize:"resize"}),a["\u0275did"](3,147456,null,0,D.LongPressDirective,[],{pressEnabled:[0,"pressEnabled"],pressModel:[1,"pressModel"]},{longPressStart:"longPressStart",longPressEnd:"longPressEnd"}),a["\u0275did"](4,49152,null,0,x.DataTableHeaderCellComponent,[a.ChangeDetectorRef],{sortType:[0,"sortType"],sortAscendingIcon:[1,"sortAscendingIcon"],sortDescendingIcon:[2,"sortDescendingIcon"],isTarget:[3,"isTarget"],targetMarkerTemplate:[4,"targetMarkerTemplate"],targetMarkerContext:[5,"targetMarkerContext"],allRowsSelected:[6,"allRowsSelected"],selectionType:[7,"selectionType"],column:[8,"column"],headerHeight:[9,"headerHeight"],sorts:[10,"sorts"]},{sort:"sort",select:"select",columnContextmenu:"columnContextmenu"})],function(t,e){var n=e.component;t(e,1,0,n.dragEventTarget,e.context.$implicit,n.reorderable&&e.context.$implicit.draggable&&e.context.$implicit.dragging,!1),t(e,2,0,e.context.$implicit.resizeable),t(e,3,0,n.reorderable&&e.context.$implicit.draggable,e.context.$implicit),t(e,4,1,[n.sortType,n.sortAscendingIcon,n.sortDescendingIcon,e.context.$implicit.isTarget,n.targetMarkerTemplate,e.context.$implicit.targetMarkerContext,n.allRowsSelected,n.selectionType,e.context.$implicit,n.headerHeight,n.sorts])},function(t,e){t(e,0,0,a["\u0275nov"](e,2).resizeEnabled,a["\u0275nov"](e,3).press,a["\u0275nov"](e,3).isLongPress,a["\u0275nov"](e,4).headerHeight,a["\u0275nov"](e,4).columnCssClasses,a["\u0275nov"](e,4).name,a["\u0275nov"](e,4).minWidth,a["\u0275nov"](e,4).maxWidth,a["\u0275nov"](e,4).width)})}function j(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[],[[8,"className",0]],null,null,null,null)),a["\u0275did"](1,278528,null,0,s.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,q)),a["\u0275did"](3,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null)],function(t,e){var n=e.component;t(e,1,0,n._styleByGroup[e.context.$implicit.type]),t(e,3,0,e.context.$implicit.columns,n.columnTrackingFn)},function(t,e){t(e,0,0,"datatable-row-"+e.context.$implicit.type)})}function F(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["class","datatable-header-inner"],["orderable",""]],[[4,"width","px"]],[[null,"reorder"],[null,"targetChanged"]],function(t,e,n){var a=!0,r=t.component;return"reorder"===e&&(a=!1!==r.onColumnReordered(n)&&a),"targetChanged"===e&&(a=!1!==r.onTargetChanged(n)&&a),a},null,null)),a["\u0275did"](1,1196032,null,1,E.OrderableDirective,[a.KeyValueDiffers,L.DOCUMENT],null,{reorder:"reorder",targetChanged:"targetChanged"}),a["\u0275qud"](603979776,1,{draggables:1}),(t()(),a["\u0275and"](16777216,null,null,1,null,j)),a["\u0275did"](4,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null)],function(t,e){var n=e.component;t(e,4,0,n._columnsByPin,n.trackByGroups)},function(t,e){t(e,0,0,e.component._columnGroupWidths.total)})}var z=n("Ahxa"),G=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function Y(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function V(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,Y)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),a["\u0275pod"](2,{rowCount:0,pageSize:1,selectedCount:2,curPage:3,offset:4}),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component,a=t(e,2,0,n.rowCount,n.pageSize,n.selectedCount,n.curPage,n.offset);t(e,1,0,a,n.footerTemplate.template)},null)}function H(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" "," "," / "]))],null,function(t,e){var n=e.component;t(e,1,0,null==n.selectedCount?null:n.selectedCount.toLocaleString(),n.selectedMessage)})}function B(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","page-count"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,H)),a["\u0275did"](2,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](3,null,[" "," "," "]))],function(t,e){t(e,2,0,e.component.selectedMessage)},function(t,e){var n=e.component;t(e,3,0,null==n.rowCount?null:n.rowCount.toLocaleString(),n.totalMessage)})}function U(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-pager",[["class","datatable-pager"]],[[8,"hidden",0]],[[null,"change"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==t.component.page.emit(n)&&a),a},p,d)),a["\u0275did"](1,49152,null,0,l.DataTablePagerComponent,[],{pagerLeftArrowIcon:[0,"pagerLeftArrowIcon"],pagerRightArrowIcon:[1,"pagerRightArrowIcon"],pagerPreviousIcon:[2,"pagerPreviousIcon"],pagerNextIcon:[3,"pagerNextIcon"],size:[4,"size"],count:[5,"count"],page:[6,"page"]},{change:"change"})],function(t,e){var n=e.component;t(e,1,0,n.pagerLeftArrowIcon,n.pagerRightArrowIcon,n.pagerPreviousIcon,n.pagerNextIcon,n.pageSize,n.rowCount,n.curPage)},function(t,e){t(e,0,0,!e.component.isVisible)})}function W(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,8,"div",[["class","datatable-footer-inner"]],[[4,"height","px"]],null,null,null,null)),a["\u0275did"](1,278528,null,0,s.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](2,{"selected-count":0}),(t()(),a["\u0275and"](16777216,null,null,1,null,V)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,B)),a["\u0275did"](6,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,U)),a["\u0275did"](8,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.selectedMessage);t(e,1,0,"datatable-footer-inner",a),t(e,4,0,n.footerTemplate),t(e,6,0,!n.footerTemplate),t(e,8,0,!n.footerTemplate)},function(t,e){t(e,0,0,e.component.footerHeight)})}var K=n("uKs4"),$=n("PNOi"),Z=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function X(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","progress-linear"],["role","progressbar"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"div",[["class","container"]],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,0,"div",[["class","bar"]],null,null,null,null,null))],null,null)}var J=n("YVFZ"),Q=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function tt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"label",[["class","datatable-checkbox"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"input",[["type","checkbox"]],[[8,"checked",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onCheckboxChange(n)&&a),a},null,null))],null,function(t,e){t(e,1,0,e.component.isSelected)})}function et(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["class","icon datatable-icon-collapse"]],null,null,null,null,null))],null,null)}function nt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["class","icon datatable-icon-up"]],null,null,null,null,null))],null,null)}function at(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["class","icon datatable-icon-down"]],null,null,null,null,null))],null,null)}function rt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,7,"button",[["class","datatable-tree-button"]],[[8,"disabled",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onTreeAction()&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,6,"span",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,et)),a["\u0275did"](3,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,nt)),a["\u0275did"](5,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,at)),a["\u0275did"](7,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,"loading"===n.treeStatus),t(e,5,0,"collapsed"===n.treeStatus),t(e,7,0,"expanded"===n.treeStatus||"disabled"===n.treeStatus)},function(t,e){t(e,0,0,"disabled"===e.component.treeStatus)})}function it(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function st(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,it)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),a["\u0275pod"](2,{cellContext:0}),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component,a=t(e,2,0,n.cellContext);t(e,1,0,a,n.column.treeToggleTemplate)},null)}function ot(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,null,null,null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,rt)),a["\u0275did"](2,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,st)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,2,0,!n.column.treeToggleTemplate),t(e,4,0,n.column.treeToggleTemplate)},null)}function ut(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"span",[],[[8,"title",0],[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){var n=e.component;t(e,0,0,n.sanitizedValue,n.value)})}function ct(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function lt(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,[[1,3],["cellTemplate",2]],null,1,null,ct)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.cellContext,n.column.cellTemplate)},null)}function dt(t){return a["\u0275vid"](2,[a["\u0275qud"](671088640,1,{cellTemplate:0}),(t()(),a["\u0275eld"](1,0,null,null,8,"div",[["class","datatable-body-cell-label"]],[[4,"margin-left","px"]],null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,tt)),a["\u0275did"](3,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,ot)),a["\u0275did"](5,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,ut)),a["\u0275did"](7,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,lt)),a["\u0275did"](9,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.column.checkboxable&&(!n.displayCheck||n.displayCheck(n.row,n.column,n.value))),t(e,5,0,n.column.isTreeColumn),t(e,7,0,!n.column.cellTemplate),t(e,9,0,n.column.cellTemplate)},function(t,e){var n=e.component;t(e,1,0,n.calcLeftMargin(n.column,n.row))})}var ft=n("syrc"),pt=n("FO+L"),ht=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function gt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-body-cell",[["tabindex","-1"]],[[8,"className",0],[4,"width","px"],[4,"minWidth","px"],[4,"maxWidth","px"],[4,"height",null]],[[null,"activate"],[null,"treeAction"],[null,"focus"],[null,"blur"],[null,"click"],[null,"dblclick"],[null,"keydown"]],function(t,e,n){var r=!0,i=t.component;return"focus"===e&&(r=!1!==a["\u0275nov"](t,1).onFocus()&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,1).onBlur()&&r),"click"===e&&(r=!1!==a["\u0275nov"](t,1).onClick(n)&&r),"dblclick"===e&&(r=!1!==a["\u0275nov"](t,1).onDblClick(n)&&r),"keydown"===e&&(r=!1!==a["\u0275nov"](t,1).onKeyDown(n)&&r),"activate"===e&&(r=!1!==i.onActivate(n,t.context.index)&&r),"treeAction"===e&&(r=!1!==i.onTreeAction()&&r),r},dt,Q)),a["\u0275did"](1,442368,null,0,J.DataTableBodyCellComponent,[a.ElementRef,a.ChangeDetectorRef],{displayCheck:[0,"displayCheck"],group:[1,"group"],rowHeight:[2,"rowHeight"],isSelected:[3,"isSelected"],expanded:[4,"expanded"],rowIndex:[5,"rowIndex"],column:[6,"column"],row:[7,"row"],treeStatus:[8,"treeStatus"]},{activate:"activate",treeAction:"treeAction"})],function(t,e){var n=e.component;t(e,1,0,n.displayCheck,n.group,n.rowHeight,n.isSelected,n.expanded,n.rowIndex,e.context.$implicit,n.row,n.treeStatus)},function(t,e){t(e,0,0,a["\u0275nov"](e,1).columnCssClasses,a["\u0275nov"](e,1).width,a["\u0275nov"](e,1).minWidth,a["\u0275nov"](e,1).maxWidth,a["\u0275nov"](e,1).height)})}function bt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[],[[8,"className",0]],null,null,null,null)),a["\u0275did"](1,278528,null,0,s.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,gt)),a["\u0275did"](3,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null)],function(t,e){var n=e.component;t(e,1,0,n._groupStyles[e.context.$implicit.type]),t(e,3,0,e.context.$implicit.columns,n.columnTrackingFn)},function(t,e){t(e,0,0,a["\u0275inlineInterpolate"](1,"datatable-row-",e.context.$implicit.type," datatable-row-group"))})}function mt(t){return a["\u0275vid"](2,[(t()(),a["\u0275and"](16777216,null,null,1,null,bt)),a["\u0275did"](1,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null)],function(t,e){var n=e.component;t(e,1,0,n._columnsByPin,n.trackByGroups)},null)}var yt=n("rLYq"),vt=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function _t(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-body-row",[["tabindex","-1"]],[[8,"className",0],[4,"height","px"],[4,"width","px"]],[[null,"keydown"],[null,"mouseenter"]],function(t,e,n){var r=!0;return"keydown"===e&&(r=!1!==a["\u0275nov"](t,1).onKeyDown(n)&&r),"mouseenter"===e&&(r=!1!==a["\u0275nov"](t,1).onMouseenter(n)&&r),r},mt,ht)),a["\u0275did"](1,311296,null,0,ft.DataTableBodyRowComponent,[a.KeyValueDiffers,[1,pt.ScrollbarHelper],a.ChangeDetectorRef,a.ElementRef],{columns:[0,"columns"],innerWidth:[1,"innerWidth"],row:[2,"row"],rowIndex:[3,"rowIndex"],offsetX:[4,"offsetX"],rowHeight:[5,"rowHeight"]},null)],function(t,e){var n=e.component;t(e,1,0,n._internalColumns,n.innerWidth,n.summaryRow,-1,n.offsetX,n.rowHeight)},function(t,e){t(e,0,0,a["\u0275nov"](e,1).cssClass,a["\u0275nov"](e,1).rowHeight,a["\u0275nov"](e,1).columnsTotalWidths)})}function xt(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,_t)),a["\u0275did"](1,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.summaryRow&&n._internalColumns)},null)}var Tt=n("Mfce"),wt=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function St(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function Ot(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,St)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.groupContext,n.groupHeader.template)},null)}function It(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","datatable-group-header"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,s.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,Ot)),a["\u0275did"](3,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.getGroupHeaderStyle()),t(e,3,0,n.groupHeader&&n.groupHeader.template)},null)}function Ct(t){return a["\u0275vid"](0,[a["\u0275ncd"](null,0),(t()(),a["\u0275and"](0,null,null,0))],null,null)}function kt(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function Nt(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,kt)),a["\u0275did"](1,540672,null,0,s.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.rowContext,n.rowDetail.template)},null)}function Rt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","datatable-row-detail"]],[[4,"height","px"]],null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,Nt)),a["\u0275did"](2,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.rowDetail&&n.rowDetail.template)},function(t,e){t(e,0,0,e.component.detailRowHeight)})}function At(t){return a["\u0275vid"](2,[(t()(),a["\u0275and"](16777216,null,null,1,null,It)),a["\u0275did"](1,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,Ct)),a["\u0275did"](3,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,Rt)),a["\u0275did"](5,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.groupHeader&&n.groupHeader.template),t(e,3,0,n.groupHeader&&n.groupHeader.template&&n.expanded||!n.groupHeader||!n.groupHeader.template),t(e,5,0,n.rowDetail&&n.rowDetail.template&&n.expanded)},null)}var Dt=n("SfHT"),Et=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function Lt(t){return a["\u0275vid"](2,[a["\u0275ncd"](null,0)],null,null)}var Pt=n("7F1K"),Mt=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function qt(t){return a["\u0275vid"](2,[a["\u0275ncd"](null,0)],null,null)}var jt=n("IPm6"),Ft=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function zt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-progress",[],null,null,null,X,Z)),a["\u0275did"](1,49152,null,0,$.ProgressBarComponent,[],null,null)],null,null)}function Gt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-summary-row",[["class","datatable-summary-row"]],null,null,null,xt,vt)),a["\u0275did"](1,573440,null,0,yt.DataTableSummaryRowComponent,[],{rows:[0,"rows"],columns:[1,"columns"],rowHeight:[2,"rowHeight"],offsetX:[3,"offsetX"],innerWidth:[4,"innerWidth"]},null)],function(t,e){var n=e.component;t(e,1,0,n.rows,n.columns,n.summaryHeight,n.offsetX,n.innerWidth)},null)}function Yt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-body-row",[["tabindex","-1"]],[[8,"className",0],[4,"height","px"],[4,"width","px"]],[[null,"treeAction"],[null,"activate"],[null,"keydown"],[null,"mouseenter"]],function(t,e,n){var r=!0,i=t.component;return"keydown"===e&&(r=!1!==a["\u0275nov"](t,1).onKeyDown(n)&&r),"mouseenter"===e&&(r=!1!==a["\u0275nov"](t,1).onMouseenter(n)&&r),"treeAction"===e&&(r=!1!==i.onTreeAction(t.parent.context.$implicit)&&r),"activate"===e&&(r=!1!==a["\u0275nov"](t.parent.parent.parent,2).onActivate(n,i.indexes.first+t.parent.context.index)&&r),r},mt,ht)),a["\u0275did"](1,311296,null,0,ft.DataTableBodyRowComponent,[a.KeyValueDiffers,[1,pt.ScrollbarHelper],a.ChangeDetectorRef,a.ElementRef],{columns:[0,"columns"],innerWidth:[1,"innerWidth"],expanded:[2,"expanded"],rowClass:[3,"rowClass"],row:[4,"row"],isSelected:[5,"isSelected"],rowIndex:[6,"rowIndex"],displayCheck:[7,"displayCheck"],treeStatus:[8,"treeStatus"],offsetX:[9,"offsetX"],rowHeight:[10,"rowHeight"]},{activate:"activate",treeAction:"treeAction"})],function(t,e){var n=e.component;t(e,1,1,[n.columns,n.innerWidth,n.getRowExpanded(e.parent.context.$implicit),n.rowClass,e.parent.context.$implicit,a["\u0275nov"](e.parent.parent.parent,2).getRowSelected(e.parent.context.$implicit),n.getRowIndex(e.parent.context.$implicit),n.displayCheck,e.parent.context.$implicit.treeStatus,n.offsetX,n.getRowHeight(e.parent.context.$implicit)])},function(t,e){t(e,0,0,a["\u0275nov"](e,1).cssClass,a["\u0275nov"](e,1).rowHeight,a["\u0275nov"](e,1).columnsTotalWidths)})}function Vt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-body-row",[["tabindex","-1"]],[[8,"className",0],[4,"height","px"],[4,"width","px"]],[[null,"activate"],[null,"keydown"],[null,"mouseenter"]],function(t,e,n){var r=!0;return"keydown"===e&&(r=!1!==a["\u0275nov"](t,1).onKeyDown(n)&&r),"mouseenter"===e&&(r=!1!==a["\u0275nov"](t,1).onMouseenter(n)&&r),"activate"===e&&(r=!1!==a["\u0275nov"](t.parent.parent.parent.parent,2).onActivate(n,t.context.index)&&r),r},mt,ht)),a["\u0275did"](1,311296,null,0,ft.DataTableBodyRowComponent,[a.KeyValueDiffers,[1,pt.ScrollbarHelper],a.ChangeDetectorRef,a.ElementRef],{columns:[0,"columns"],innerWidth:[1,"innerWidth"],expanded:[2,"expanded"],rowClass:[3,"rowClass"],row:[4,"row"],group:[5,"group"],isSelected:[6,"isSelected"],rowIndex:[7,"rowIndex"],offsetX:[8,"offsetX"],rowHeight:[9,"rowHeight"]},{activate:"activate"})],function(t,e){var n=e.component;t(e,1,0,n.columns,n.innerWidth,n.getRowExpanded(e.context.$implicit),n.rowClass,e.context.$implicit,e.parent.parent.context.$implicit.value,a["\u0275nov"](e.parent.parent.parent.parent,2).getRowSelected(e.context.$implicit),n.getRowIndex(e.context.$implicit),n.offsetX,n.getRowHeight(e.context.$implicit))},function(t,e){t(e,0,0,a["\u0275nov"](e,1).cssClass,a["\u0275nov"](e,1).rowHeight,a["\u0275nov"](e,1).columnsTotalWidths)})}function Ht(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,Vt)),a["\u0275did"](1,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.parent.context.$implicit.value,e.component.rowTrackingFn)},null)}function Bt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"datatable-row-wrapper",[["class","datatable-row-wrapper"]],null,[[null,"rowContextmenu"],[null,"contextmenu"]],function(t,e,n){var r=!0,i=t.component;return"contextmenu"===e&&(r=!1!==a["\u0275nov"](t,2).onContextmenu(n)&&r),"rowContextmenu"===e&&(r=!1!==i.rowContextmenu.emit(n)&&r),r},At,wt)),a["\u0275did"](1,278528,null,0,s.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),a["\u0275did"](2,311296,null,0,Tt.DataTableRowWrapperComponent,[a.ChangeDetectorRef,a.KeyValueDiffers],{innerWidth:[0,"innerWidth"],rowDetail:[1,"rowDetail"],groupHeader:[2,"groupHeader"],offsetX:[3,"offsetX"],detailRowHeight:[4,"detailRowHeight"],row:[5,"row"],groupedRows:[6,"groupedRows"],rowIndex:[7,"rowIndex"],expanded:[8,"expanded"]},{rowContextmenu:"rowContextmenu"}),(t()(),a["\u0275and"](16777216,null,0,1,null,Yt)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),a["\u0275and"](0,[["groupedRowsTemplate",2]],0,0,null,Ht))],function(t,e){var n=e.component;t(e,1,0,n.getRowsStyles(e.context.$implicit)),t(e,2,0,n.innerWidth,n.rowDetail,n.groupHeader,n.offsetX,n.getDetailRowHeight(e.context.$implicit[e.context.index],e.context.index),e.context.$implicit,n.groupedRows,n.getRowIndex(e.context.$implicit[e.context.index]),n.getRowExpanded(e.context.$implicit)),t(e,4,0,!n.groupedRows,a["\u0275nov"](e,5))},null)}function Ut(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"datatable-summary-row",[["class","datatable-summary-row"]],null,null,null,xt,vt)),a["\u0275did"](1,278528,null,0,s.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),a["\u0275did"](2,573440,null,0,yt.DataTableSummaryRowComponent,[],{rows:[0,"rows"],columns:[1,"columns"],rowHeight:[2,"rowHeight"],offsetX:[3,"offsetX"],innerWidth:[4,"innerWidth"]},null)],function(t,e){var n=e.component;t(e,1,0,n.getBottomSummaryRowStyles()),t(e,2,0,n.rows,n.columns,n.summaryHeight,n.offsetX,n.innerWidth)},null)}function Wt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,7,"datatable-scroller",[["class","datatable-scroll"]],[[4,"height","px"],[4,"width","px"]],[[null,"scroll"]],function(t,e,n){var a=!0;return"scroll"===e&&(a=!1!==t.component.onBodyScroll(n)&&a),a},Lt,Et)),a["\u0275did"](1,245760,[[1,4]],0,Dt.ScrollerComponent,[a.NgZone,a.ElementRef,a.Renderer2],{scrollbarV:[0,"scrollbarV"],scrollbarH:[1,"scrollbarH"],scrollHeight:[2,"scrollHeight"],scrollWidth:[3,"scrollWidth"]},{scroll:"scroll"}),(t()(),a["\u0275and"](16777216,null,0,1,null,Gt)),a["\u0275did"](3,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,0,1,null,Bt)),a["\u0275did"](5,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null),(t()(),a["\u0275and"](16777216,null,0,1,null,Ut)),a["\u0275did"](7,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.scrollbarV,n.scrollbarH,n.scrollHeight,null==n.columnGroupWidths?null:n.columnGroupWidths.total),t(e,3,0,n.summaryRow&&"top"===n.summaryPosition),t(e,5,0,n.temp,n.rowTrackingFn),t(e,7,0,n.summaryRow&&"bottom"===n.summaryPosition)},function(t,e){t(e,0,0,a["\u0275nov"](e,1).scrollHeight,a["\u0275nov"](e,1).scrollWidth)})}function Kt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"div",[["class","empty-row"]],[[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){t(e,0,0,e.component.emptyMessage)})}function $t(t){return a["\u0275vid"](2,[a["\u0275qud"](671088640,1,{scroller:0}),(t()(),a["\u0275eld"](1,0,null,null,7,"datatable-selection",[],null,[[null,"select"],[null,"activate"]],function(t,e,n){var a=!0,r=t.component;return"select"===e&&(a=!1!==r.select.emit(n)&&a),"activate"===e&&(a=!1!==r.activate.emit(n)&&a),a},qt,Mt)),a["\u0275did"](2,49152,[["selector",4]],0,Pt.DataTableSelectionComponent,[],{rows:[0,"rows"],selected:[1,"selected"],selectEnabled:[2,"selectEnabled"],selectionType:[3,"selectionType"],rowIdentity:[4,"rowIdentity"],selectCheck:[5,"selectCheck"]},{activate:"activate",select:"select"}),(t()(),a["\u0275and"](16777216,null,0,1,null,zt)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,0,1,null,Wt)),a["\u0275did"](6,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,0,1,null,Kt)),a["\u0275did"](8,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.rows,n.selected,n.selectEnabled,n.selectionType,n.rowIdentity,n.selectCheck),t(e,4,0,n.loadingIndicator),t(e,6,0,null==n.rows?null:n.rows.length),t(e,8,0,!(null!=n.rows&&n.rows.length||n.loadingIndicator))},null)}var Zt=n("3/HP"),Xt=n("nhM1"),Jt=n("BARL"),Qt=a["\u0275crt"]({encapsulation:2,styles:[[".ngx-datatable{display:block;overflow:hidden;-webkit-box-pack:center;justify-content:center;position:relative;-webkit-transform:translate3d(0,0,0)}.ngx-datatable [hidden]{display:none!important}.ngx-datatable *,.ngx-datatable :after,.ngx-datatable :before{box-sizing:border-box}.ngx-datatable.scroll-vertical .datatable-body{overflow-y:auto}.ngx-datatable.scroll-vertical.virtualized .datatable-body .datatable-row-wrapper{position:absolute}.ngx-datatable.scroll-horz .datatable-body{overflow-x:auto;-webkit-overflow-scrolling:touch}.ngx-datatable.fixed-header .datatable-header .datatable-header-inner{white-space:nowrap}.ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-datatable.fixed-row .datatable-scroll,.ngx-datatable.fixed-row .datatable-scroll .datatable-body-row{white-space:nowrap}.ngx-datatable.fixed-row .datatable-scroll .datatable-body-row .datatable-body-cell,.ngx-datatable.fixed-row .datatable-scroll .datatable-body-row .datatable-body-group-cell{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ngx-datatable .datatable-body-row,.ngx-datatable .datatable-header-inner,.ngx-datatable .datatable-row-center{display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-direction:row;-o-flex-flow:row;flex-flow:row}.ngx-datatable .datatable-body-cell,.ngx-datatable .datatable-header-cell{overflow-x:hidden;vertical-align:top;display:inline-block;line-height:1.625}.ngx-datatable .datatable-body-cell:focus,.ngx-datatable .datatable-header-cell:focus{outline:0}.ngx-datatable .datatable-row-left,.ngx-datatable .datatable-row-right{z-index:9}.ngx-datatable .datatable-row-center,.ngx-datatable .datatable-row-group,.ngx-datatable .datatable-row-left,.ngx-datatable .datatable-row-right{position:relative}.ngx-datatable .datatable-header{display:block;overflow:hidden}.ngx-datatable .datatable-header .datatable-header-inner{-webkit-box-align:stretch;align-items:stretch;-webkit-align-items:stretch}.ngx-datatable .datatable-header .datatable-header-cell{position:relative;display:inline-block}.ngx-datatable .datatable-header .datatable-header-cell.sortable .datatable-header-cell-wrapper{cursor:pointer}.ngx-datatable .datatable-header .datatable-header-cell.longpress .datatable-header-cell-wrapper{cursor:move}.ngx-datatable .datatable-header .datatable-header-cell .sort-btn{line-height:100%;vertical-align:middle;display:inline-block;cursor:pointer}.ngx-datatable .datatable-header .datatable-header-cell .resize-handle,.ngx-datatable .datatable-header .datatable-header-cell .resize-handle--not-resizable{display:inline-block;position:absolute;right:0;top:0;bottom:0;width:5px;padding:0 4px;visibility:hidden}.ngx-datatable .datatable-header .datatable-header-cell .resize-handle{cursor:ew-resize}.ngx-datatable .datatable-header .datatable-header-cell.resizeable:hover .resize-handle,.ngx-datatable .datatable-header .datatable-header-cell:hover .resize-handle--not-resizable{visibility:visible}.ngx-datatable .datatable-header .datatable-header-cell .targetMarker{position:absolute;top:0;bottom:0}.ngx-datatable .datatable-header .datatable-header-cell .targetMarker.dragFromLeft{right:0}.ngx-datatable .datatable-header .datatable-header-cell .targetMarker.dragFromRight{left:0}.ngx-datatable .datatable-header .datatable-header-cell .datatable-header-cell-template-wrap{height:inherit}.ngx-datatable .datatable-body{position:relative;z-index:10;display:block}.ngx-datatable .datatable-body .datatable-scroll{display:inline-block}.ngx-datatable .datatable-body .datatable-row-detail{overflow-y:hidden}.ngx-datatable .datatable-body .datatable-row-wrapper{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column}.ngx-datatable .datatable-body .datatable-body-row{outline:0}.ngx-datatable .datatable-body .datatable-body-row>div{display:-webkit-box;display:flex}.ngx-datatable .datatable-footer{display:block;width:100%}.ngx-datatable .datatable-footer .datatable-footer-inner{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;width:100%}.ngx-datatable .datatable-footer .selected-count .page-count{-webkit-box-flex:1;flex:1 1 40%}.ngx-datatable .datatable-footer .selected-count .datatable-pager{-webkit-box-flex:1;flex:1 1 60%}.ngx-datatable .datatable-footer .page-count{-webkit-box-flex:1;flex:1 1 20%}.ngx-datatable .datatable-footer .datatable-pager{-webkit-box-flex:1;flex:1 1 80%;text-align:right}.ngx-datatable .datatable-footer .datatable-pager .pager,.ngx-datatable .datatable-footer .datatable-pager .pager li{padding:0;margin:0;display:inline-block;list-style:none}.ngx-datatable .datatable-footer .datatable-pager .pager li,.ngx-datatable .datatable-footer .datatable-pager .pager li a{outline:0}.ngx-datatable .datatable-footer .datatable-pager .pager li a{cursor:pointer;display:inline-block}.ngx-datatable .datatable-footer .datatable-pager .pager li.disabled a{cursor:not-allowed}"]],data:{}});function te(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"datatable-header",[["class","datatable-header"]],[[4,"height",null],[4,"width",null]],[[null,"sort"],[null,"resize"],[null,"reorder"],[null,"select"],[null,"columnContextmenu"]],function(t,e,n){var a=!0,r=t.component;return"sort"===e&&(a=!1!==r.onColumnSort(n)&&a),"resize"===e&&(a=!1!==r.onColumnResize(n)&&a),"reorder"===e&&(a=!1!==r.onColumnReorder(n)&&a),"select"===e&&(a=!1!==r.onHeaderSelect(n)&&a),"columnContextmenu"===e&&(a=!1!==r.onColumnContextmenu(n)&&a),a},F,M)),a["\u0275did"](1,49152,[[2,4]],0,P.DataTableHeaderComponent,[a.ChangeDetectorRef],{sortAscendingIcon:[0,"sortAscendingIcon"],sortDescendingIcon:[1,"sortDescendingIcon"],scrollbarH:[2,"scrollbarH"],dealsWithGroup:[3,"dealsWithGroup"],targetMarkerTemplate:[4,"targetMarkerTemplate"],innerWidth:[5,"innerWidth"],sorts:[6,"sorts"],sortType:[7,"sortType"],allRowsSelected:[8,"allRowsSelected"],selectionType:[9,"selectionType"],reorderable:[10,"reorderable"],headerHeight:[11,"headerHeight"],columns:[12,"columns"],offsetX:[13,"offsetX"]},{sort:"sort",reorder:"reorder",resize:"resize",select:"select",columnContextmenu:"columnContextmenu"}),a["\u0275pid"](131072,s.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,1,[n.cssClasses.sortAscending,n.cssClasses.sortDescending,n.scrollbarH,n.groupedRows,n.targetMarkerTemplate,n._innerWidth,n.sorts,n.sortType,n.allRowsSelected,n.selectionType,n.reorderable,n.headerHeight,n._internalColumns,a["\u0275unv"](e,1,13,a["\u0275nov"](e,2).transform(n._offsetX))])},function(t,e){t(e,0,0,a["\u0275nov"](e,1).headerHeight,a["\u0275nov"](e,1).headerWidth)})}function ee(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"datatable-footer",[["class","datatable-footer"]],null,[[null,"page"]],function(t,e,n){var a=!0;return"page"===e&&(a=!1!==t.component.onFooterPage(n)&&a),a},W,G)),a["\u0275did"](1,49152,null,0,z.DataTableFooterComponent,[],{footerHeight:[0,"footerHeight"],rowCount:[1,"rowCount"],pageSize:[2,"pageSize"],offset:[3,"offset"],pagerLeftArrowIcon:[4,"pagerLeftArrowIcon"],pagerRightArrowIcon:[5,"pagerRightArrowIcon"],pagerPreviousIcon:[6,"pagerPreviousIcon"],pagerNextIcon:[7,"pagerNextIcon"],totalMessage:[8,"totalMessage"],footerTemplate:[9,"footerTemplate"],selectedCount:[10,"selectedCount"],selectedMessage:[11,"selectedMessage"]},{page:"page"})],function(t,e){var n=e.component;t(e,1,1,[n.footerHeight,n.rowCount,n.pageSize,n.offset,n.cssClasses.pagerLeftArrow,n.cssClasses.pagerRightArrow,n.cssClasses.pagerPrevious,n.cssClasses.pagerNext,n.messages.totalMessage,n.footer,n.selected.length,!!n.selectionType&&n.messages.selectedMessage])},null)}function ne(t){return a["\u0275vid"](2,[a["\u0275qud"](402653184,1,{bodyComponent:0}),a["\u0275qud"](671088640,2,{headerComponent:0}),(t()(),a["\u0275eld"](2,0,null,null,8,"div",[["visibilityObserver",""]],[[2,"visible",null]],[[null,"visible"]],function(t,e,n){var a=!0;return"visible"===e&&(a=!1!==t.component.recalculate()&&a),a},null,null)),a["\u0275did"](3,212992,null,0,K.VisibilityDirective,[a.ElementRef,a.NgZone],null,{visible:"visible"}),(t()(),a["\u0275and"](16777216,null,null,1,null,te)),a["\u0275did"](5,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](6,0,null,null,2,"datatable-body",[["class","datatable-body"]],[[4,"width",null],[4,"height",null]],[[null,"page"],[null,"activate"],[null,"rowContextmenu"],[null,"select"],[null,"scroll"],[null,"treeAction"]],function(t,e,n){var a=!0,r=t.component;return"page"===e&&(a=!1!==r.onBodyPage(n)&&a),"activate"===e&&(a=!1!==r.activate.emit(n)&&a),"rowContextmenu"===e&&(a=!1!==r.onRowContextmenu(n)&&a),"select"===e&&(a=!1!==r.onBodySelect(n)&&a),"scroll"===e&&(a=!1!==r.onBodyScroll(n)&&a),"treeAction"===e&&(a=!1!==r.onTreeAction(n)&&a),a},$t,Ft)),a["\u0275did"](7,245760,[[1,4]],0,jt.DataTableBodyComponent,[a.ChangeDetectorRef],{scrollbarV:[0,"scrollbarV"],scrollbarH:[1,"scrollbarH"],loadingIndicator:[2,"loadingIndicator"],externalPaging:[3,"externalPaging"],rowHeight:[4,"rowHeight"],offsetX:[5,"offsetX"],emptyMessage:[6,"emptyMessage"],selectionType:[7,"selectionType"],selected:[8,"selected"],rowIdentity:[9,"rowIdentity"],rowDetail:[10,"rowDetail"],groupHeader:[11,"groupHeader"],selectCheck:[12,"selectCheck"],displayCheck:[13,"displayCheck"],trackByProp:[14,"trackByProp"],rowClass:[15,"rowClass"],groupedRows:[16,"groupedRows"],groupExpansionDefault:[17,"groupExpansionDefault"],innerWidth:[18,"innerWidth"],groupRowsBy:[19,"groupRowsBy"],virtualization:[20,"virtualization"],summaryRow:[21,"summaryRow"],summaryPosition:[22,"summaryPosition"],summaryHeight:[23,"summaryHeight"],pageSize:[24,"pageSize"],rows:[25,"rows"],columns:[26,"columns"],offset:[27,"offset"],rowCount:[28,"rowCount"],bodyHeight:[29,"bodyHeight"]},{scroll:"scroll",page:"page",activate:"activate",select:"select",rowContextmenu:"rowContextmenu",treeAction:"treeAction"}),a["\u0275pid"](131072,s.AsyncPipe,[a.ChangeDetectorRef]),(t()(),a["\u0275and"](16777216,null,null,1,null,ee)),a["\u0275did"](10,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0),t(e,5,0,n.headerHeight),t(e,7,1,[n.scrollbarV,n.scrollbarH,n.loadingIndicator,n.externalPaging,n.rowHeight,a["\u0275unv"](e,7,5,a["\u0275nov"](e,8).transform(n._offsetX)),n.messages.emptyMessage,n.selectionType,n.selected,n.rowIdentity,n.rowDetail,n.groupHeader,n.selectCheck,n.displayCheck,n.trackByProp,n.rowClass,n.groupedRows,n.groupExpansionDefault,n._innerWidth,n.groupRowsBy,n.virtualization,n.summaryRow,n.summaryPosition,n.summaryHeight,n.pageSize,n._internalRows,n._internalColumns,n.offset,n.rowCount,n.bodyHeight]),t(e,10,0,n.footerHeight)},function(t,e){t(e,2,0,a["\u0275nov"](e,3).isVisible),t(e,6,0,a["\u0275nov"](e,7).bodyWidth,a["\u0275nov"](e,7).bodyHeight)})}var ae=n("lUjN"),re=n("vxfy");n("uIqm"),n.d(e,"a",function(){return ie}),n.d(e,"b",function(){return Oe});var ie=a["\u0275crt"]({encapsulation:0,styles:[[".dataTables_wrapper[_ngcontent-%COMP%]{margin-bottom:25px}.dataTables_wrapper[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%]{height:30px;border-left:1px solid rgba(0,0,0,.09);padding-left:5px;margin-left:5px;display:inline-block;vertical-align:middle}.dataTables_wrapper[_ngcontent-%COMP%] .widget-toolbar[_ngcontent-%COMP%]{display:inline-block;float:right;width:auto;height:30px;line-height:28px;position:relative;border-left:1px solid rgba(0,0,0,.09);cursor:pointer;padding:0 8px;text-align:center}.dataTables_wrapper[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%]{white-space:nowrap}.dataTables_wrapper[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] > li[_ngcontent-%COMP%]{cursor:pointer}.dataTables_wrapper[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] > li[_ngcontent-%COMP%] > label[_ngcontent-%COMP%]{width:100%;margin-bottom:0;padding-left:20px;padding-right:20px;cursor:pointer}.dataTables_wrapper[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] > li[_ngcontent-%COMP%] > label[_ngcontent-%COMP%]:hover{background-color:#f5f5f5}.dataTables_wrapper[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] > li[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] > input[_ngcontent-%COMP%]{cursor:pointer}.dataTables_wrapper[_ngcontent-%COMP%] th.oadatatablecheckbox[_ngcontent-%COMP%]{width:16px}.dataTables_wrapper[_ngcontent-%COMP%] .dataTables_length[_ngcontent-%COMP%] > input[_ngcontent-%COMP%]{line-height:25px;text-align:right}.dataTables_header[_ngcontent-%COMP%]{background-color:#f5f5f5;border:1px solid #d1d1d1;border-bottom:none;padding:5px;position:relative}.dataTables_header[_ngcontent-%COMP%] .oadatatableactions[_ngcontent-%COMP%]{float:left}.dataTables_header[_ngcontent-%COMP%] .table-filters{float:right;border-left:1px solid rgba(0,0,0,.09);padding-left:8px}.dataTables_header[_ngcontent-%COMP%] .table-filters label{margin-right:4px}.dataTables_header[_ngcontent-%COMP%] .form-group[_ngcontent-%COMP%]{padding-left:8px}.dataTables_header[_ngcontent-%COMP%] .input-group[_ngcontent-%COMP%]{float:right;border-left:1px solid rgba(0,0,0,.09);padding-left:8px;padding-right:8px;width:40%;max-width:250px}.dataTables_header[_ngcontent-%COMP%] .input-group[_ngcontent-%COMP%] .clear-input[_ngcontent-%COMP%], .dataTables_header[_ngcontent-%COMP%] .input-group[_ngcontent-%COMP%] .form-control[_ngcontent-%COMP%]{height:30px}.dataTables_header[_ngcontent-%COMP%] .input-group[_ngcontent-%COMP%] .clear-input[_ngcontent-%COMP%] i[_ngcontent-%COMP%]{vertical-align:text-top}.dataTables_header[_ngcontent-%COMP%] .input-group.dataTables_paginate[_ngcontent-%COMP%]{width:8%;min-width:85px;padding-right:8px} .oadatatable{border:1px solid #d1d1d1;margin-bottom:0;max-width:none!important} .oadatatable .progress-linear{display:block;position:relative;width:100%;height:5px;padding:0;margin:0} .oadatatable .progress-linear .container{background-color:#afd9ee} .oadatatable .progress-linear .container .bar{left:0;height:100%;width:100%;position:absolute;overflow:hidden;background-color:#afd9ee} .oadatatable .progress-linear .container .bar:before{display:block;position:absolute;content:'';left:-200px;width:200px;height:100%;background-color:#2b99a8;-webkit-animation:3s linear infinite progress-loading;animation:3s linear infinite progress-loading} .oadatatable .datatable-header{background-clip:padding-box;background-color:#f5f5f5;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#f5f5f5),to(#ededed));background-image:linear-gradient(to bottom,#f5f5f5 0,#ededed 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0)} .oadatatable .datatable-header .sort-asc, .oadatatable .datatable-header .sort-desc{color:#2b99a8} .oadatatable .datatable-header .datatable-header-cell{padding:5px;border:none;border-left:1px solid #d1d1d1;border-bottom:1px solid #d1d1d1;text-align:left;font-weight:700} .oadatatable .datatable-header .datatable-header-cell .datatable-header-cell-label:after{font-family:ForkAwesome;font-weight:400;height:9px;left:10px;line-height:12px;position:relative;vertical-align:baseline;width:12px} .oadatatable .datatable-header .datatable-header-cell.sortable .datatable-header-cell-label:after{content:' \\f0dc'} .oadatatable .datatable-header .datatable-header-cell.sortable.sort-active.sort-asc .datatable-header-cell-label:after{content:' \\f160'} .oadatatable .datatable-header .datatable-header-cell.sortable.sort-active.sort-desc .datatable-header-cell-label:after{content:' \\f161'} .oadatatable .datatable-header .datatable-header-cell:first-child{border-left:none} .oadatatable .datatable-body .empty-row{background-color:#fff3cd;text-align:center;font-weight:700;font-style:italic;padding-top:5px;padding-bottom:5px} .oadatatable .datatable-body .datatable-body-row .label{font-size:.9em} .oadatatable .datatable-body .datatable-body-row.clickable:hover .datatable-row-group{background-color:#eee;-webkit-transition-property:background;transition-property:background;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:linear;transition-timing-function:linear} .oadatatable .datatable-body .datatable-body-row.datatable-row-even{background-color:#fff} .oadatatable .datatable-body .datatable-body-row.datatable-row-odd{background-color:#f5f5f5} .oadatatable .datatable-body .datatable-body-row.active, .oadatatable .datatable-body .datatable-body-row.active:hover{background-color:#d9edf7} .oadatatable .datatable-body .datatable-body-row .datatable-body-cell{padding:5px;border:none;border-left:1px solid #d1d1d1;border-bottom:1px solid #d1d1d1} .oadatatable .datatable-body .datatable-body-row .datatable-body-cell:first-child{border-left:none} .oadatatable .datatable-body .datatable-body-row .datatable-body-cell .datatable-body-cell-label{display:block} .oadatatable .datatable-footer .page-count, .oadatatable .datatable-footer .selected-count{font-style:italic;padding-left:5px} .oadatatable .datatable-footer .datatable-pager .pager{margin-right:5px!important} .oadatatable .datatable-footer .datatable-pager .pager li:not(:first-child){margin-left:3px} .oadatatable .datatable-footer .datatable-pager .pager li>a, .oadatatable .datatable-footer .datatable-pager .pager li>span{border-radius:3px} .oadatatable .datatable-footer .datatable-pager .pager .pages>a, .oadatatable .datatable-footer .datatable-pager .pager .pages>span{display:inline-block;padding:5px 10px;margin-bottom:5px;border:none} .oadatatable .datatable-footer .datatable-pager .pager .pages a:hover{background-color:#afd9ee} .oadatatable .datatable-footer .datatable-pager .pager .pages.active>a{background-color:#d9edf7}@-webkit-keyframes progress-loading{from{left:-200px;width:15%}50%{width:30%}70%{width:70%}80%{left:50%}95%{left:120%}to{left:100%}}@keyframes progress-loading{from{left:-200px;width:15%}50%{width:30%}70%{width:70%}80%{left:50%}95%{left:120%}to{left:100%}}"]],data:{}});function se(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"cd-error-panel",[],null,null,null,r.b,r.a)),a["\u0275did"](1,49152,null,0,i.a,[],null,null),(t()(),a["\u0275ted"](-1,0,["Failed to load data."]))],null,null)}function oe(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"div",[["class","input-group dataTables_paginate"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"input",[["class","form-control"],["max","9999"],["min","1"],["type","number"]],[[8,"value",0]],[[null,"click"],[null,"keyup"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.setLimit(n)&&a),"keyup"===e&&(a=!1!==r.setLimit(n)&&a),"blur"===e&&(a=!1!==r.setLimit(n)&&a),a},null,null))],null,function(t,e){t(e,1,0,e.component.userConfig.limit)})}function ue(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"li",[],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,3,"label",[],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,0,"input",[["type","checkbox"]],[[8,"name",0],[8,"checked",0]],[[null,"change"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==t.component.toggleColumn(n)&&a),a},null,null)),(t()(),a["\u0275eld"](3,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](4,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit.prop,!e.context.$implicit.isHidden),t(e,4,0,e.context.$implicit.name)})}function ce(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"ul",[["class","dropdown-menu"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,ue)),a["\u0275did"](2,278528,null,0,s.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.columns)},null)}function le(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","widget-toolbar tc_refreshBtn"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"a",[],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.refreshBtn()&&a),a},null,null)),(t()(),a["\u0275eld"](2,0,null,null,0,"i",[["class","fa fa-lg fa-refresh"]],[[2,"fa-spin",null]],null,null,null,null))],null,function(t,e){var n=e.component;t(e,2,0,n.updating||n.loadingIndicator)})}function de(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,28,"div",[["class","dataTables_header clearfix form-inline"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"div",[["class","oadatatableactions"]],null,null,null,null,null)),a["\u0275ncd"](null,0),a["\u0275ncd"](null,1),(t()(),a["\u0275eld"](4,0,null,null,11,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[["class","glyphicon glyphicon-search"]],null,null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,5,"input",[["class","form-control"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"keyup"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var r=!0,i=t.component;return"input"===e&&(r=!1!==a["\u0275nov"](t,8)._handleInput(n.target.value)&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,8).onTouched()&&r),"compositionstart"===e&&(r=!1!==a["\u0275nov"](t,8)._compositionStart()&&r),"compositionend"===e&&(r=!1!==a["\u0275nov"](t,8)._compositionEnd(n.target.value)&&r),"ngModelChange"===e&&(r=!1!==(i.search=n)&&r),"keyup"===e&&(r=!1!==i.updateFilter()&&r),r},null,null)),a["\u0275did"](8,16384,null,0,o.e,[a.Renderer2,a.ElementRef,[2,o.b]],null,null),a["\u0275prd"](1024,null,o.p,function(t){return[t]},[o.e]),a["\u0275did"](10,671744,null,0,o.u,[[8,null],[8,null],[8,null],[6,o.p]],{model:[0,"model"]},{update:"ngModelChange"}),a["\u0275prd"](2048,null,o.q,null,[o.u]),a["\u0275did"](12,16384,null,0,o.r,[[4,o.q]],null,null),(t()(),a["\u0275eld"](13,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),a["\u0275eld"](14,0,null,null,1,"button",[["class","btn btn-default clear-input tc_clearInputBtn"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.updateFilter(!0)&&a),a},null,null)),(t()(),a["\u0275eld"](15,0,null,null,0,"i",[["class","icon-prepend fa fa-remove"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,oe)),a["\u0275did"](17,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](18,0,null,null,8,"div",[["class","widget-toolbar"]],null,null,null,null,null)),(t()(),a["\u0275eld"](19,16777216,null,null,7,"div",[["class","dropdown tc_menuitem tc_menuitem_cluster"],["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),a["\u0275prd"](512,null,u.f,u.f,[]),a["\u0275did"](21,212992,null,0,u.c,[a.ElementRef,a.Renderer2,a.ViewContainerRef,c.a,u.a,u.f],null,null),(t()(),a["\u0275eld"](22,0,null,null,2,"a",[["class","btn btn-sm btn-default dropdown-toggle tc_columnBtn"],["data-toggle","dropdown"],["dropdownToggle",""]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,23).onClick()&&r),r},null,null)),a["\u0275did"](23,147456,null,0,u.g,[a.ChangeDetectorRef,u.c,a.ElementRef,a.Renderer2,u.f],null,null),(t()(),a["\u0275eld"](24,0,null,null,0,"i",[["class","fa fa-lg fa-table"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,ce)),a["\u0275did"](26,16384,null,0,u.d,[u.f,a.ViewContainerRef,a.TemplateRef],null,null),(t()(),a["\u0275and"](16777216,null,null,1,null,le)),a["\u0275did"](28,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,10,0,n.search),t(e,17,0,n.limit),t(e,21,0),t(e,28,0,n.fetchData.observers.length>0)},function(t,e){t(e,7,0,a["\u0275nov"](e,12).ngClassUntouched,a["\u0275nov"](e,12).ngClassTouched,a["\u0275nov"](e,12).ngClassPristine,a["\u0275nov"](e,12).ngClassDirty,a["\u0275nov"](e,12).ngClassValid,a["\u0275nov"](e,12).ngClassInvalid,a["\u0275nov"](e,12).ngClassPending),t(e,19,0,a["\u0275nov"](e,21).dropup,a["\u0275nov"](e,21).isOpen,a["\u0275nov"](e,21).isOpen&&a["\u0275nov"](e,21).isBs4),t(e,22,0,!0,a["\u0275nov"](e,23).isDisabled,a["\u0275nov"](e,23).isOpen)})}function fe(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" "," "])),(t()(),a["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["selected"])),(t()(),a["\u0275ted"](-1,null,[" / "]))],null,function(t,e){t(e,1,0,e.parent.context.selectedCount)})}function pe(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" "," "])),(t()(),a["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["found"])),(t()(),a["\u0275ted"](-1,null,[" / "]))],null,function(t,e){t(e,1,0,e.parent.context.rowCount)})}function he(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,8,"div",[["class","page-count"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,fe)),a["\u0275did"](2,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,pe)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](5,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](6,null,[" "," "])),(t()(),a["\u0275eld"](7,0,null,null,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["total"])),(t()(),a["\u0275eld"](9,0,null,null,1,"datatable-pager",[["class","datatable-pager"]],[[8,"hidden",0]],[[null,"change"]],function(t,e,n){var r=!0;return"change"===e&&(r=!1!==a["\u0275nov"](t.parent,17).onFooterPage(n)&&r),r},p,d)),a["\u0275did"](10,49152,null,0,l.DataTablePagerComponent,[],{pagerLeftArrowIcon:[0,"pagerLeftArrowIcon"],pagerRightArrowIcon:[1,"pagerRightArrowIcon"],pagerPreviousIcon:[2,"pagerPreviousIcon"],pagerNextIcon:[3,"pagerNextIcon"],size:[4,"size"],count:[5,"count"],page:[6,"page"]},{change:"change"})],function(t,e){var n=e.component;t(e,2,0,n.selectionType),t(e,4,0,e.context.rowCount!=(null==n.data?null:n.data.length)),t(e,10,0,n.paginationClasses.pagerLeftArrow,n.paginationClasses.pagerRightArrow,n.paginationClasses.pagerPrevious,n.paginationClasses.pagerNext,e.context.pageSize,e.context.rowCount,e.context.curPage)},function(t,e){var n=e.component;t(e,6,0,(null==n.data?null:n.data.length)||0),t(e,9,0,!(e.context.rowCount/e.context.pageSize>1))})}function ge(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.context.value)})}function be(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"cd-sparkline",[],null,null,null,h.b,h.a)),a["\u0275did"](1,638976,null,0,g.a,[b.a],{data:[0,"data"],isBinary:[1,"isBinary"]},null)],function(t,e){t(e,1,0,e.context.value,e.context.row.cdIsBinary)},null)}function me(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"a",[],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,1).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&r),r},null,null)),a["\u0275did"](1,671744,null,0,m.o,[m.l,m.a,s.LocationStrategy],{queryParams:[0,"queryParams"],routerLink:[1,"routerLink"]},null),a["\u0275pad"](2,1),(t()(),a["\u0275ted"](3,null,["",""]))],function(t,e){var n=e.context.row.cdParams,a=t(e,2,0,e.context.row.cdLink);t(e,1,0,n,a)},function(t,e){t(e,0,0,a["\u0275nov"](e,1).target,a["\u0275nov"](e,1).href),t(e,3,0,e.context.value)})}function ye(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["class","fa fa-check fa-fw"]],[[8,"hidden",0]],null,null,null,null))],null,function(t,e){t(e,0,0,!e.context.value)})}function ve(t){return a["\u0275vid"](0,[(t()(),a["\u0275ted"](0,null,[" "," /s\n"])),a["\u0275ppd"](1,1)],null,function(t,e){var n=a["\u0275unv"](e,0,0,t(e,1,0,a["\u0275nov"](e.parent,0),e.context.value));t(e,0,0,n)})}function _e(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["class","fa fa-spinner fa-spin fa-fw"]],null,null,null,null,null))],null,null)}function xe(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted italic"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["(",")"]))],null,function(t,e){t(e,1,0,e.parent.context.row.cdExecuting)})}function Te(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,_e)),a["\u0275did"](1,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](2,null,[" "," "])),(t()(),a["\u0275and"](16777216,null,null,1,null,xe)),a["\u0275did"](4,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.context.row.cdExecuting),t(e,4,0,e.context.row.cdExecuting)},function(t,e){t(e,2,0,e.context.value)})}function we(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,0,0,a["\u0275inlineInterpolate"](1,"",e.component.useCustomClass(e.context.value),"")),t(e,1,0,e.context.value)})}function Se(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""])),a["\u0275ppd"](2,2)],null,function(t,e){var n=a["\u0275unv"](e,1,0,t(e,2,0,a["\u0275nov"](e.parent,1),e.context.value,null==e.context.column?null:e.context.column.customTemplateConfig));t(e,1,0,n)})}function Oe(t){return a["\u0275vid"](2,[a["\u0275pid"](0,y.a,[v.a]),a["\u0275pid"](0,_.a,[]),a["\u0275qud"](402653184,1,{table:0}),a["\u0275qud"](402653184,2,{tableCellBoldTpl:0}),a["\u0275qud"](402653184,3,{sparklineTpl:0}),a["\u0275qud"](402653184,4,{routerLinkTpl:0}),a["\u0275qud"](402653184,5,{checkIconTpl:0}),a["\u0275qud"](402653184,6,{perSecondTpl:0}),a["\u0275qud"](402653184,7,{executingTpl:0}),a["\u0275qud"](402653184,8,{classAddingTpl:0}),a["\u0275qud"](402653184,9,{mapTpl:0}),(t()(),a["\u0275and"](16777216,null,null,1,null,se)),a["\u0275did"](12,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](13,0,null,null,13,"div",[["class","dataTables_wrapper"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,de)),a["\u0275did"](15,16384,null,0,s.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](16,0,null,null,10,"ngx-datatable",[["class","bootstrap oadatatable ngx-datatable"]],[[2,"fixed-header",null],[2,"fixed-row",null],[2,"scroll-vertical",null],[2,"virtualized",null],[2,"scroll-horz",null],[2,"selectable",null],[2,"checkbox-selection",null],[2,"cell-selection",null],[2,"single-selection",null],[2,"multi-selection",null],[2,"multi-click-selection",null]],[[null,"select"],[null,"sort"],["window","resize"]],function(t,e,n){var r=!0,i=t.component;return"window:resize"===e&&(r=!1!==a["\u0275nov"](t,17).onWindowResize()&&r),"select"===e&&(r=!1!==i.onSelect(n)&&r),"sort"===e&&(r=!1!==i.changeSorting(n)&&r),r},ne,Qt)),a["\u0275did"](17,5750784,[[1,4],["table",4]],4,Zt.DatatableComponent,[[1,pt.ScrollbarHelper],[1,Xt.DimensionsHelper],a.ChangeDetectorRef,a.ElementRef,a.KeyValueDiffers,Jt.ColumnChangesService],{rows:[0,"rows"],columns:[1,"columns"],selected:[2,"selected"],rowHeight:[3,"rowHeight"],columnMode:[4,"columnMode"],headerHeight:[5,"headerHeight"],footerHeight:[6,"footerHeight"],limit:[7,"limit"],loadingIndicator:[8,"loadingIndicator"],selectionType:[9,"selectionType"],sorts:[10,"sorts"],cssClasses:[11,"cssClasses"],rowIdentity:[12,"rowIdentity"],rowClass:[13,"rowClass"]},{select:"select",sort:"sort"}),a["\u0275qud"](603979776,10,{columnTemplates:1}),a["\u0275qud"](335544320,11,{rowDetail:0}),a["\u0275qud"](335544320,12,{groupHeader:0}),a["\u0275qud"](335544320,13,{footer:0}),(t()(),a["\u0275eld"](22,0,null,null,4,"ngx-datatable-footer",[],null,null,null,null,null)),a["\u0275did"](23,16384,[[13,4]],1,ae.DatatableFooterDirective,[],null,null),a["\u0275qud"](335544320,14,{template:0}),(t()(),a["\u0275and"](0,[[14,2]],null,1,null,he)),a["\u0275did"](26,16384,null,0,re.DataTableFooterTemplateDirective,[a.TemplateRef],null,null),a["\u0275ncd"](null,2),(t()(),a["\u0275and"](0,[[2,2],["tableCellBoldTpl",2]],null,0,null,ge)),(t()(),a["\u0275and"](0,[[3,2],["sparklineTpl",2]],null,0,null,be)),(t()(),a["\u0275and"](0,[[4,2],["routerLinkTpl",2]],null,0,null,me)),(t()(),a["\u0275and"](0,[[5,2],["checkIconTpl",2]],null,0,null,ye)),(t()(),a["\u0275and"](0,[[6,2],["perSecondTpl",2]],null,0,null,ve)),(t()(),a["\u0275and"](0,[[7,2],["executingTpl",2]],null,0,null,Te)),(t()(),a["\u0275and"](0,[[8,2],["classAddingTpl",2]],null,0,null,we)),(t()(),a["\u0275and"](0,[[9,2],["mapTpl",2]],null,0,null,Se))],function(t,e){var n=e.component;t(e,12,0,n.loadingError),t(e,15,0,n.toolHeader),t(e,17,1,[n.rows,n.tableColumns,n.selection.selected,"auto",n.columnMode,n.header?"auto":0,n.footer?"auto":0,n.userConfig.limit>0?n.userConfig.limit:void 0,n.loadingIndicator,n.selectionType,n.userConfig.sorts,n.paginationClasses,n.rowIdentity(),n.getRowClass()])},function(t,e){t(e,16,1,[a["\u0275nov"](e,17).isFixedHeader,a["\u0275nov"](e,17).isFixedRow,a["\u0275nov"](e,17).isVertScroll,a["\u0275nov"](e,17).isVirtualized,a["\u0275nov"](e,17).isHorScroll,a["\u0275nov"](e,17).isSelectable,a["\u0275nov"](e,17).isCheckboxSelection,a["\u0275nov"](e,17).isCellSelection,a["\u0275nov"](e,17).isSingleSelection,a["\u0275nov"](e,17).isMultiSelection,a["\u0275nov"](e,17).isMultiClickSelection])})}},"26FU":function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("K9Ia"),i=n("8g8A"),s=function(t){function e(e){var n=t.call(this)||this;return n._value=e,n}return a.__extends(e,t),Object.defineProperty(e.prototype,"value",{get:function(){return this.getValue()},enumerable:!0,configurable:!0}),e.prototype._subscribe=function(e){var n=t.prototype._subscribe.call(this,e);return n&&!n.closed&&e.next(this._value),n},e.prototype.getValue=function(){if(this.hasError)throw this.thrownError;if(this.closed)throw new i.a;return this._value},e.prototype.next=function(e){t.prototype.next.call(this,this._value=e)},e}(r.a)},"2Bdj":function(t,e,n){"use strict";function a(t){return"function"==typeof t}n.d(e,"a",function(){return a})},"2EZI":function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("mrSG"),r=n("gIcY"),i=n("QFaf"),s=n("CcnG"),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e.prototype.group=function(e,n){void 0===n&&(n=null);var a=t.prototype.group.call(this,e,n);return new i.a(a.controls,a.validator,a.asyncValidator)},e.ngInjectableDef=s.defineInjectable({factory:function(){return new e},token:e,providedIn:"root"}),e}(r.h)},"2UWG":function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3");function i(t){return void 0!==t._view.width}function s(t){var e,n,a,r,s=t._view;if(i(t)){var o=s.width/2;e=s.x-o,n=s.x+o,a=Math.min(s.y,s.base),r=Math.max(s.y,s.base)}else{var u=s.height/2;e=Math.min(s.x,s.base),n=Math.max(s.x,s.base),a=s.y-u,r=s.y+u}return{left:e,top:a,right:n,bottom:r}}a._set("global",{elements:{rectangle:{backgroundColor:a.global.defaultColor,borderColor:a.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),t.exports=r.extend({draw:function(){var t,e,n,a,r,i,s,o=this._chart.ctx,u=this._view,c=u.borderWidth;if(u.horizontal?(n=u.y-u.height/2,a=u.y+u.height/2,r=(e=u.x)>(t=u.base)?1:-1,i=1,s=u.borderSkipped||"left"):(t=u.x-u.width/2,e=u.x+u.width/2,r=1,i=(a=u.base)>(n=u.y)?1:-1,s=u.borderSkipped||"bottom"),c){var l=Math.min(Math.abs(t-e),Math.abs(n-a)),d=(c=c>l?l:c)/2,f=t+("left"!==s?d*r:0),p=e+("right"!==s?-d*r:0),h=n+("top"!==s?d*i:0),g=a+("bottom"!==s?-d*i:0);f!==p&&(n=h,a=g),h!==g&&(t=f,e=p)}o.beginPath(),o.fillStyle=u.backgroundColor,o.strokeStyle=u.borderColor,o.lineWidth=c;var b=[[t,a],[t,n],[e,n],[e,a]],m=["bottom","left","top","right"].indexOf(s,0);function y(t){return b[(m+t)%4]}-1===m&&(m=0);var v=y(0);o.moveTo(v[0],v[1]);for(var _=1;_<4;_++)v=y(_),o.lineTo(v[0],v[1]);o.fill(),c&&o.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var a=s(this);n=t>=a.left&&t<=a.right&&e>=a.top&&e<=a.bottom}return n},inLabelRange:function(t,e){if(!this._view)return!1;var n=s(this);return i(this)?t>=n.left&&t<=n.right:e>=n.top&&e<=n.bottom},inXRange:function(t){var e=s(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=s(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},"2V7f":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("IPm6")),a(n("YVFZ")),a(n("syrc")),a(n("PNOi")),a(n("SfHT")),a(n("Mfce")),a(n("7F1K")),a(n("99TG")),a(n("Fjl2")),a(n("VHo1"))},"2WpN":function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("FFOo"),i=n("pugT");function s(t){return function(e){return e.lift(new o(t))}}var o=function(){function t(t){this.callback=t}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.callback))},t}(),u=function(t){function e(e,n){var a=t.call(this,e)||this;return a.add(new i.a(n)),a}return a.__extends(e,t),e}(r.a)},"2ePl":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(t){return t&&"number"==typeof t.length&&"function"!=typeof t}},"2fjn":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("fr-ca",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd\u2019hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(t,e){switch(e){default:case"M":case"Q":case"D":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}}})}()},"2ykv":function(t,e,n){!function(t){"use strict";var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),n="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),a=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;t.defineLocale("nl-be",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"\xe9\xe9n minuut",mm:"%d minuten",h:"\xe9\xe9n uur",hh:"%d uur",d:"\xe9\xe9n dag",dd:"%d dagen",M:"\xe9\xe9n maand",MM:"%d maanden",y:"\xe9\xe9n jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}})}(n("wd/R"))},"3/HP":function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata,i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var s=n("CcnG"),o=n("5tze"),u=(n("bpWZ"),n("qwkt")),c=n("2V7f"),l=n("99TG"),d=n("QHrR"),f=n("i3PA"),p=n("fktO"),h=n("FLvf"),g=n("DtyJ");e.DatatableComponent=function(){function t(t,e,n,a,r,i){this.scrollbarHelper=t,this.dimensionsHelper=e,this.cd=n,this.columnChangesService=i,this.selected=[],this.scrollbarV=!1,this.scrollbarH=!1,this.rowHeight=30,this.columnMode=u.ColumnMode.standard,this.headerHeight=30,this.footerHeight=0,this.externalPaging=!1,this.externalSorting=!1,this.loadingIndicator=!1,this.reorderable=!0,this.swapColumns=!0,this.sortType=u.SortType.single,this.sorts=[],this.cssClasses={sortAscending:"datatable-icon-up",sortDescending:"datatable-icon-down",pagerLeftArrow:"datatable-icon-left",pagerRightArrow:"datatable-icon-right",pagerPrevious:"datatable-icon-prev",pagerNext:"datatable-icon-skip"},this.messages={emptyMessage:"No data to display",totalMessage:"total",selectedMessage:"selected"},this.rowIdentity=function(t){return t},this.groupExpansionDefault=!1,this.selectAllRowsOnPage=!1,this.virtualization=!0,this.summaryRow=!1,this.summaryHeight=30,this.summaryPosition="top",this.scroll=new s.EventEmitter,this.activate=new s.EventEmitter,this.select=new s.EventEmitter,this.sort=new s.EventEmitter,this.page=new s.EventEmitter,this.reorder=new s.EventEmitter,this.resize=new s.EventEmitter,this.tableContextmenu=new s.EventEmitter(!1),this.treeAction=new s.EventEmitter,this.rowCount=0,this._offsetX=new g.BehaviorSubject(0),this._count=0,this._offset=0,this._subscriptions=[],this.element=a.nativeElement,this.rowDiffer=r.find({}).create()}return Object.defineProperty(t.prototype,"rows",{get:function(){return this._rows},set:function(t){this._rows=t,t&&(this._internalRows=t.slice()),this.externalSorting||this.sortInternalRows(),this._internalRows=o.groupRowsByParents(this._internalRows,o.optionalGetterForProp(this.treeFromRelation),o.optionalGetterForProp(this.treeToRelation)),this.recalculate(),this._rows&&this._groupRowsBy&&(this.groupedRows=this.groupArrayBy(this._rows,this._groupRowsBy)),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"groupRowsBy",{get:function(){return this._groupRowsBy},set:function(t){t&&(this._groupRowsBy=t,this._rows&&this._groupRowsBy&&(this.groupedRows=this.groupArrayBy(this._rows,this._groupRowsBy)))},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){t&&(this._internalColumns=t.slice(),o.setColumnDefaults(this._internalColumns),this.recalculateColumns()),this._columns=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"limit",{get:function(){return this._limit},set:function(t){this._limit=t,this.recalculate()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"count",{get:function(){return this._count},set:function(t){this._count=t,this.recalculate()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offset",{get:function(){return Math.max(Math.min(this._offset,Math.ceil(this.rowCount/this.pageSize)-1),0)},set:function(t){this._offset=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isFixedHeader",{get:function(){var t=this.headerHeight;return"string"!=typeof t||"auto"!==t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isFixedRow",{get:function(){var t=this.rowHeight;return"string"!=typeof t||"auto"!==t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isVertScroll",{get:function(){return this.scrollbarV},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isVirtualized",{get:function(){return this.virtualization},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isHorScroll",{get:function(){return this.scrollbarH},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSelectable",{get:function(){return void 0!==this.selectionType},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCheckboxSelection",{get:function(){return this.selectionType===u.SelectionType.checkbox},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCellSelection",{get:function(){return this.selectionType===u.SelectionType.cell},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSingleSelection",{get:function(){return this.selectionType===u.SelectionType.single},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isMultiSelection",{get:function(){return this.selectionType===u.SelectionType.multi},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isMultiClickSelection",{get:function(){return this.selectionType===u.SelectionType.multiClick},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnTemplates",{get:function(){return this._columnTemplates},set:function(t){this._columnTemplates=t,this.translateColumns(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"allRowsSelected",{get:function(){var t=this.rows&&this.selected&&this.selected.length===this.rows.length;if(this.selectAllRowsOnPage){var e=this.bodyComponent.indexes;t=this.selected.length===e.last-e.first}return this.selected&&this.rows&&0!==this.rows.length&&t},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.recalculate()},t.prototype.ngAfterViewInit=function(){var t=this;this.externalSorting||this.sortInternalRows(),"undefined"!=typeof requestAnimationFrame&&requestAnimationFrame(function(){t.recalculate(),t.externalPaging&&t.scrollbarV&&t.page.emit({count:t.count,pageSize:t.pageSize,limit:t.limit,offset:0})})},t.prototype.ngAfterContentInit=function(){var t=this;this.columnTemplates.changes.subscribe(function(e){return t.translateColumns(e)}),this.listenForColumnInputChanges()},t.prototype.translateColumns=function(t){if(t){var e=t.toArray();e.length&&(this._internalColumns=o.translateTemplates(e),o.setColumnDefaults(this._internalColumns),this.recalculateColumns(),this.sortInternalRows(),this.cd.markForCheck())}},t.prototype.groupArrayBy=function(t,e){var n=new Map;return t.forEach(function(t){var a=t[e];n.has(a)?n.get(a).push(t):n.set(a,[t])}),Array.from(n,function(t){return{key:t[0],value:t[1]}})},t.prototype.ngDoCheck=function(){this.rowDiffer.diff(this.rows)&&(this.externalSorting?this._internalRows=this.rows.slice():this.sortInternalRows(),this._internalRows=o.groupRowsByParents(this._internalRows,o.optionalGetterForProp(this.treeFromRelation),o.optionalGetterForProp(this.treeToRelation)),this.recalculatePages(),this.cd.markForCheck())},t.prototype.recalculate=function(){this.recalculateDims(),this.recalculateColumns()},t.prototype.onWindowResize=function(){this.recalculate()},t.prototype.recalculateColumns=function(t,e,n){if(void 0===t&&(t=this._internalColumns),void 0===e&&(e=-1),void 0===n&&(n=this.scrollbarH),t){var a=this._innerWidth;return this.scrollbarV&&(a-=this.scrollbarHelper.width),this.columnMode===u.ColumnMode.force?o.forceFillColumnWidths(t,a,e,n):this.columnMode===u.ColumnMode.flex&&o.adjustColumnWidths(t,a),t}},t.prototype.recalculateDims=function(){var t=this.dimensionsHelper.getDimensions(this.element);if(this._innerWidth=Math.floor(t.width),this.scrollbarV){var e=t.height;this.headerHeight&&(e-=this.headerHeight),this.footerHeight&&(e-=this.footerHeight),this.bodyHeight=e}this.recalculatePages()},t.prototype.recalculatePages=function(){this.pageSize=this.calcPageSize(),this.rowCount=this.calcRowCount()},t.prototype.onBodyPage=function(t){this.externalPaging&&!this.virtualization||(this.offset=t.offset,this.page.emit({count:this.count,pageSize:this.pageSize,limit:this.limit,offset:this.offset}))},t.prototype.onBodyScroll=function(t){this._offsetX.next(t.offsetX),this.scroll.emit(t),this.cd.detectChanges()},t.prototype.onFooterPage=function(t){this.offset=t.page-1,this.bodyComponent.updateOffsetY(this.offset),this.page.emit({count:this.count,pageSize:this.pageSize,limit:this.limit,offset:this.offset}),this.selectAllRowsOnPage&&(this.selected=[],this.select.emit({selected:this.selected}))},t.prototype.calcPageSize=function(t){if(void 0===t&&(t=this.rows),this.scrollbarV&&this.virtualization){var e=Math.ceil(this.bodyHeight/this.rowHeight);return Math.max(e,0)}return void 0!==this.limit?this.limit:t?t.length:0},t.prototype.calcRowCount=function(t){return void 0===t&&(t=this.rows),this.externalPaging?this.count:t?this.groupedRows?this.groupedRows.length:null!=this.treeFromRelation&&null!=this.treeToRelation?this._internalRows.length:t.length:0},t.prototype.onColumnContextmenu=function(t){this.tableContextmenu.emit({event:t.event,type:u.ContextmenuType.header,content:t.column})},t.prototype.onRowContextmenu=function(t){this.tableContextmenu.emit({event:t.event,type:u.ContextmenuType.body,content:t.row})},t.prototype.onColumnResize=function(t){var e=t.column,n=t.newValue;if(void 0!==e){var a,r=this._internalColumns.map(function(t,r){return(t=i({},t)).$$id===e.$$id&&(a=r,t.width=n,t.$$oldWidth=n),t});this.recalculateColumns(r,a),this._internalColumns=r,this.resize.emit({column:e,newValue:n})}},t.prototype.onColumnReorder=function(t){var e=t.column,n=t.newValue,a=t.prevValue,r=this._internalColumns.map(function(t){return i({},t)});if(this.swapColumns){var s=r[n];r[n]=e,r[a]=s}else if(n>a){for(var o=r[a],u=a;u<n;u++)r[u]=r[u+1];r[n]=o}else{for(o=r[a],u=a;u>n;u--)r[u]=r[u-1];r[n]=o}this._internalColumns=r,this.reorder.emit({column:e,newValue:n,prevValue:a})},t.prototype.onColumnSort=function(t){this.selectAllRowsOnPage&&(this.selected=[],this.select.emit({selected:this.selected})),this.sorts=t.sorts,!1===this.externalSorting&&this.sortInternalRows(),this._internalRows=o.groupRowsByParents(this._internalRows,o.optionalGetterForProp(this.treeFromRelation),o.optionalGetterForProp(this.treeToRelation)),this.offset=0,this.bodyComponent.updateOffsetY(this.offset),this.sort.emit(t)},t.prototype.onHeaderSelect=function(t){var e,n;if(this.selectAllRowsOnPage){var a=this.bodyComponent.indexes.first,r=this.bodyComponent.indexes.last,i=this.selected.length===r-a;this.selected=[],i||(e=this.selected).push.apply(e,this._internalRows.slice(a,r))}else i=this.selected.length===this.rows.length,this.selected=[],i||(n=this.selected).push.apply(n,this.rows);this.select.emit({selected:this.selected})},t.prototype.onBodySelect=function(t){this.select.emit(t)},t.prototype.onTreeAction=function(t){var e=this,n=t.row,a=this._rows.findIndex(function(n){return n[e.treeToRelation]===t.row[e.treeToRelation]});this.treeAction.emit({row:n,rowIndex:a})},t.prototype.ngOnDestroy=function(){this._subscriptions.forEach(function(t){return t.unsubscribe()})},t.prototype.listenForColumnInputChanges=function(){var t=this;this._subscriptions.push(this.columnChangesService.columnInputChanges$.subscribe(function(){t.columnTemplates&&t.columnTemplates.notifyOnChanges()}))},t.prototype.sortInternalRows=function(){this._internalRows=o.sortRows(this._internalRows,this._internalColumns,this.sorts)},a([s.Input(),r("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),a([s.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"rows",null),a([s.Input(),r("design:type",String),r("design:paramtypes",[String])],t.prototype,"groupRowsBy",null),a([s.Input(),r("design:type",Array)],t.prototype,"groupedRows",void 0),a([s.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([s.Input(),r("design:type",Array)],t.prototype,"selected",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"scrollbarV",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"rowHeight",void 0),a([s.Input(),r("design:type",String)],t.prototype,"columnMode",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"headerHeight",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"footerHeight",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"externalPaging",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"externalSorting",void 0),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"limit",null),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"count",null),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offset",null),a([s.Input(),r("design:type",Boolean)],t.prototype,"loadingIndicator",void 0),a([s.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"reorderable",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"swapColumns",void 0),a([s.Input(),r("design:type",String)],t.prototype,"sortType",void 0),a([s.Input(),r("design:type",Array)],t.prototype,"sorts",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"cssClasses",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"messages",void 0),a([s.Input(),r("design:type",Function)],t.prototype,"rowIdentity",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"rowClass",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"selectCheck",void 0),a([s.Input(),r("design:type",Function)],t.prototype,"displayCheck",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"groupExpansionDefault",void 0),a([s.Input(),r("design:type",String)],t.prototype,"trackByProp",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"selectAllRowsOnPage",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"virtualization",void 0),a([s.Input(),r("design:type",String)],t.prototype,"treeFromRelation",void 0),a([s.Input(),r("design:type",String)],t.prototype,"treeToRelation",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"summaryRow",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"summaryHeight",void 0),a([s.Input(),r("design:type",String)],t.prototype,"summaryPosition",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"scroll",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"activate",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"select",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"sort",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"page",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"reorder",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"resize",void 0),a([s.Output(),r("design:type",Object)],t.prototype,"tableContextmenu",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"treeAction",void 0),a([s.HostBinding("class.fixed-header"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isFixedHeader",null),a([s.HostBinding("class.fixed-row"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isFixedRow",null),a([s.HostBinding("class.scroll-vertical"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isVertScroll",null),a([s.HostBinding("class.virtualized"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isVirtualized",null),a([s.HostBinding("class.scroll-horz"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isHorScroll",null),a([s.HostBinding("class.selectable"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isSelectable",null),a([s.HostBinding("class.checkbox-selection"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isCheckboxSelection",null),a([s.HostBinding("class.cell-selection"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isCellSelection",null),a([s.HostBinding("class.single-selection"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isSingleSelection",null),a([s.HostBinding("class.multi-selection"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isMultiSelection",null),a([s.HostBinding("class.multi-click-selection"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isMultiClickSelection",null),a([s.ContentChildren(d.DataTableColumnDirective),r("design:type",s.QueryList),r("design:paramtypes",[s.QueryList])],t.prototype,"columnTemplates",null),a([s.ContentChild(f.DatatableRowDetailDirective),r("design:type",f.DatatableRowDetailDirective)],t.prototype,"rowDetail",void 0),a([s.ContentChild(l.DatatableGroupHeaderDirective),r("design:type",l.DatatableGroupHeaderDirective)],t.prototype,"groupHeader",void 0),a([s.ContentChild(p.DatatableFooterDirective),r("design:type",p.DatatableFooterDirective)],t.prototype,"footer",void 0),a([s.ViewChild(c.DataTableBodyComponent),r("design:type",c.DataTableBodyComponent)],t.prototype,"bodyComponent",void 0),a([s.ViewChild(h.DataTableHeaderComponent),r("design:type",h.DataTableHeaderComponent)],t.prototype,"headerComponent",void 0),a([s.HostListener("window:resize"),o.throttleable(5),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",void 0)],t.prototype,"onWindowResize",null),a([s.Component({selector:"ngx-datatable",template:'\n <div\n visibilityObserver\n (visible)="recalculate()">\n <datatable-header\n *ngIf="headerHeight"\n [sorts]="sorts"\n [sortType]="sortType"\n [scrollbarH]="scrollbarH"\n [innerWidth]="_innerWidth"\n [offsetX]="_offsetX | async"\n [dealsWithGroup]="groupedRows"\n [columns]="_internalColumns"\n [headerHeight]="headerHeight"\n [reorderable]="reorderable"\n [targetMarkerTemplate]="targetMarkerTemplate"\n [sortAscendingIcon]="cssClasses.sortAscending"\n [sortDescendingIcon]="cssClasses.sortDescending"\n [allRowsSelected]="allRowsSelected"\n [selectionType]="selectionType"\n (sort)="onColumnSort($event)"\n (resize)="onColumnResize($event)"\n (reorder)="onColumnReorder($event)"\n (select)="onHeaderSelect($event)"\n (columnContextmenu)="onColumnContextmenu($event)">\n </datatable-header>\n <datatable-body\n [groupRowsBy]="groupRowsBy"\n [groupedRows]="groupedRows"\n [rows]="_internalRows"\n [groupExpansionDefault]="groupExpansionDefault"\n [scrollbarV]="scrollbarV"\n [scrollbarH]="scrollbarH"\n [virtualization]="virtualization"\n [loadingIndicator]="loadingIndicator"\n [externalPaging]="externalPaging"\n [rowHeight]="rowHeight"\n [rowCount]="rowCount"\n [offset]="offset"\n [trackByProp]="trackByProp"\n [columns]="_internalColumns"\n [pageSize]="pageSize"\n [offsetX]="_offsetX | async"\n [rowDetail]="rowDetail"\n [groupHeader]="groupHeader"\n [selected]="selected"\n [innerWidth]="_innerWidth"\n [bodyHeight]="bodyHeight"\n [selectionType]="selectionType"\n [emptyMessage]="messages.emptyMessage"\n [rowIdentity]="rowIdentity"\n [rowClass]="rowClass"\n [selectCheck]="selectCheck"\n [displayCheck]="displayCheck"\n [summaryRow]="summaryRow"\n [summaryHeight]="summaryHeight"\n [summaryPosition]="summaryPosition"\n (page)="onBodyPage($event)"\n (activate)="activate.emit($event)"\n (rowContextmenu)="onRowContextmenu($event)"\n (select)="onBodySelect($event)"\n (scroll)="onBodyScroll($event)"\n (treeAction)="onTreeAction($event)">\n </datatable-body>\n <datatable-footer\n *ngIf="footerHeight"\n [rowCount]="rowCount"\n [pageSize]="pageSize"\n [offset]="offset"\n [footerHeight]="footerHeight"\n [footerTemplate]="footer"\n [totalMessage]="messages.totalMessage"\n [pagerLeftArrowIcon]="cssClasses.pagerLeftArrow"\n [pagerRightArrowIcon]="cssClasses.pagerRightArrow"\n [pagerPreviousIcon]="cssClasses.pagerPrevious"\n [selectedCount]="selected.length"\n [selectedMessage]="!!selectionType && messages.selectedMessage"\n [pagerNextIcon]="cssClasses.pagerNext"\n (page)="onFooterPage($event)">\n </datatable-footer>\n </div>\n ',changeDetection:s.ChangeDetectionStrategy.OnPush,encapsulation:s.ViewEncapsulation.None,styleUrls:["./datatable.component.css"],host:{class:"ngx-datatable"}})],t)}()},"35yf":function(t,e,n){"use strict";n("CDJp")._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),t.exports=function(t){t.controllers.scatter=t.controllers.line}},"3E1r":function(t,e,n){!function(t){"use strict";var e={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},n={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};t.defineLocale("hi",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u093c\u0930\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948\u0932_\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0938\u094d\u0924_\u0938\u093f\u0924\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u0942\u092c\u0930_\u0928\u0935\u092e\u094d\u092c\u0930_\u0926\u093f\u0938\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u093c\u0930._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948._\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932._\u0905\u0917._\u0938\u093f\u0924._\u0905\u0915\u094d\u091f\u0942._\u0928\u0935._\u0926\u093f\u0938.".split("_"),monthsParseExact:!0,weekdays:"\u0930\u0935\u093f\u0935\u093e\u0930_\u0938\u094b\u092e\u0935\u093e\u0930_\u092e\u0902\u0917\u0932\u0935\u093e\u0930_\u092c\u0941\u0927\u0935\u093e\u0930_\u0917\u0941\u0930\u0942\u0935\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930_\u0936\u0928\u093f\u0935\u093e\u0930".split("_"),weekdaysShort:"\u0930\u0935\u093f_\u0938\u094b\u092e_\u092e\u0902\u0917\u0932_\u092c\u0941\u0927_\u0917\u0941\u0930\u0942_\u0936\u0941\u0915\u094d\u0930_\u0936\u0928\u093f".split("_"),weekdaysMin:"\u0930_\u0938\u094b_\u092e\u0902_\u092c\u0941_\u0917\u0941_\u0936\u0941_\u0936".split("_"),longDateFormat:{LT:"A h:mm \u092c\u091c\u0947",LTS:"A h:mm:ss \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm \u092c\u091c\u0947",LLLL:"dddd, D MMMM YYYY, A h:mm \u092c\u091c\u0947"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u0915\u0932] LT",nextWeek:"dddd, LT",lastDay:"[\u0915\u0932] LT",lastWeek:"[\u092a\u093f\u091b\u0932\u0947] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u092e\u0947\u0902",past:"%s \u092a\u0939\u0932\u0947",s:"\u0915\u0941\u091b \u0939\u0940 \u0915\u094d\u0937\u0923",ss:"%d \u0938\u0947\u0915\u0902\u0921",m:"\u090f\u0915 \u092e\u093f\u0928\u091f",mm:"%d \u092e\u093f\u0928\u091f",h:"\u090f\u0915 \u0918\u0902\u091f\u093e",hh:"%d \u0918\u0902\u091f\u0947",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u0940\u0928\u0947",MM:"%d \u092e\u0939\u0940\u0928\u0947",y:"\u090f\u0915 \u0935\u0930\u094d\u0937",yy:"%d \u0935\u0930\u094d\u0937"},preparse:function(t){return t.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0930\u093e\u0924|\u0938\u0941\u092c\u0939|\u0926\u094b\u092a\u0939\u0930|\u0936\u093e\u092e/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0930\u093e\u0924"===e?t<4?t:t+12:"\u0938\u0941\u092c\u0939"===e?t:"\u0926\u094b\u092a\u0939\u0930"===e?t>=10?t:t+12:"\u0936\u093e\u092e"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0930\u093e\u0924":t<10?"\u0938\u0941\u092c\u0939":t<17?"\u0926\u094b\u092a\u0939\u0930":t<20?"\u0936\u093e\u092e":"\u0930\u093e\u0924"},week:{dow:0,doy:6}})}(n("wd/R"))},"3MdB":function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("DtyJ"),o=n("ahDk");e.DraggableDirective=function(){function t(t){this.dragX=!0,this.dragY=!0,this.dragStart=new i.EventEmitter,this.dragging=new i.EventEmitter,this.dragEnd=new i.EventEmitter,this.isDragging=!1,this.element=t.nativeElement}return t.prototype.ngOnChanges=function(t){t.dragEventTarget&&t.dragEventTarget.currentValue&&this.dragModel.dragging&&this.onMousedown(t.dragEventTarget.currentValue)},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype.onMouseup=function(t){this.isDragging&&(this.isDragging=!1,this.element.classList.remove("dragging"),this.subscription&&(this._destroySubscription(),this.dragEnd.emit({event:t,element:this.element,model:this.dragModel})))},t.prototype.onMousedown=function(t){var e=this;if(t.target.classList.contains("draggable")&&(this.dragX||this.dragY)){t.preventDefault(),this.isDragging=!0;var n={x:t.clientX,y:t.clientY},a=s.fromEvent(document,"mouseup");this.subscription=a.subscribe(function(t){return e.onMouseup(t)});var r=s.fromEvent(document,"mousemove").pipe(o.takeUntil(a)).subscribe(function(t){return e.move(t,n)});this.subscription.add(r),this.dragStart.emit({event:t,element:this.element,model:this.dragModel})}},t.prototype.move=function(t,e){if(this.isDragging){var n=t.clientY-e.y;this.dragX&&(this.element.style.left=t.clientX-e.x+"px"),this.dragY&&(this.element.style.top=n+"px"),this.element.classList.add("dragging"),this.dragging.emit({event:t,element:this.element,model:this.dragModel})}},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Object)],t.prototype,"dragEventTarget",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"dragModel",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"dragX",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"dragY",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragStart",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragging",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragEnd",void 0),a([i.Directive({selector:"[draggable]"})],t)}()},"3U0i":function(t,e,n){"use strict";function a(){return Error.call(this),this.message="Timeout has occurred",this.name="TimeoutError",this}n.d(e,"a",function(){return r}),a.prototype=Object.create(Error.prototype);var r=a},"3fWJ":function(t,e,n){"use strict";function a(){return Error.call(this),this.message="no elements in sequence",this.name="EmptyError",this}n.d(e,"a",function(){return r}),a.prototype=Object.create(Error.prototype);var r=a},"4HWh":function(t,e,n){"use strict";var a=n("CcnG"),r=n("OZfm"),i=n("lqqz"),s=n("NJnL");n("p4Cf"),n.d(e,"a",function(){return o}),n.d(e,"b",function(){return c});var o=a["\u0275crt"]({encapsulation:0,styles:[["i[_ngcontent-%COMP%]{color:#2b99a8;cursor:pointer;padding-left:4px}"]],data:{}});function u(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"div",[],[[8,"innerHTML",1]],null,null,null,null)),a["\u0275ncd"](null,0),(t()(),a["\u0275and"](0,null,null,0))],null,function(t,e){t(e,0,0,e.component.html)})}function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,[["popoverTpl",2]],null,0,null,u)),(t()(),a["\u0275eld"](1,16777216,null,null,1,"i",[["aria-hidden","true"],["class","fa fa-question-circle"],["container","body"],["placement","bottom"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==n.preventDefault()&&a),a},null,null)),a["\u0275did"](2,212992,null,0,r.c,[r.a,a.ElementRef,a.Renderer2,a.ViewContainerRef,i.a,s.a],{popover:[0,"popover"],placement:[1,"placement"],outsideClick:[2,"outsideClick"],container:[3,"container"]},null)],function(t,e){t(e,2,0,a["\u0275nov"](e,0),"bottom",!0,"body")},null)}},"4MV3":function(t,e,n){!function(t){"use strict";var e={1:"\u0ae7",2:"\u0ae8",3:"\u0ae9",4:"\u0aea",5:"\u0aeb",6:"\u0aec",7:"\u0aed",8:"\u0aee",9:"\u0aef",0:"\u0ae6"},n={"\u0ae7":"1","\u0ae8":"2","\u0ae9":"3","\u0aea":"4","\u0aeb":"5","\u0aec":"6","\u0aed":"7","\u0aee":"8","\u0aef":"9","\u0ae6":"0"};t.defineLocale("gu",{months:"\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1\u0a86\u0ab0\u0ac0_\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1\u0a86\u0ab0\u0ac0_\u0aae\u0abe\u0ab0\u0acd\u0a9a_\u0a8f\u0aaa\u0acd\u0ab0\u0abf\u0ab2_\u0aae\u0ac7_\u0a9c\u0ac2\u0aa8_\u0a9c\u0ac1\u0ab2\u0abe\u0a88_\u0a91\u0a97\u0ab8\u0acd\u0a9f_\u0ab8\u0aaa\u0acd\u0a9f\u0ac7\u0aae\u0acd\u0aac\u0ab0_\u0a91\u0a95\u0acd\u0a9f\u0acd\u0aac\u0ab0_\u0aa8\u0ab5\u0ac7\u0aae\u0acd\u0aac\u0ab0_\u0aa1\u0abf\u0ab8\u0ac7\u0aae\u0acd\u0aac\u0ab0".split("_"),monthsShort:"\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1._\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1._\u0aae\u0abe\u0ab0\u0acd\u0a9a_\u0a8f\u0aaa\u0acd\u0ab0\u0abf._\u0aae\u0ac7_\u0a9c\u0ac2\u0aa8_\u0a9c\u0ac1\u0ab2\u0abe._\u0a91\u0a97._\u0ab8\u0aaa\u0acd\u0a9f\u0ac7._\u0a91\u0a95\u0acd\u0a9f\u0acd._\u0aa8\u0ab5\u0ac7._\u0aa1\u0abf\u0ab8\u0ac7.".split("_"),monthsParseExact:!0,weekdays:"\u0ab0\u0ab5\u0abf\u0ab5\u0abe\u0ab0_\u0ab8\u0acb\u0aae\u0ab5\u0abe\u0ab0_\u0aae\u0a82\u0a97\u0ab3\u0ab5\u0abe\u0ab0_\u0aac\u0ac1\u0aa7\u0acd\u0ab5\u0abe\u0ab0_\u0a97\u0ac1\u0ab0\u0ac1\u0ab5\u0abe\u0ab0_\u0ab6\u0ac1\u0a95\u0acd\u0ab0\u0ab5\u0abe\u0ab0_\u0ab6\u0aa8\u0abf\u0ab5\u0abe\u0ab0".split("_"),weekdaysShort:"\u0ab0\u0ab5\u0abf_\u0ab8\u0acb\u0aae_\u0aae\u0a82\u0a97\u0ab3_\u0aac\u0ac1\u0aa7\u0acd_\u0a97\u0ac1\u0ab0\u0ac1_\u0ab6\u0ac1\u0a95\u0acd\u0ab0_\u0ab6\u0aa8\u0abf".split("_"),weekdaysMin:"\u0ab0_\u0ab8\u0acb_\u0aae\u0a82_\u0aac\u0ac1_\u0a97\u0ac1_\u0ab6\u0ac1_\u0ab6".split("_"),longDateFormat:{LT:"A h:mm \u0ab5\u0abe\u0a97\u0acd\u0aaf\u0ac7",LTS:"A h:mm:ss \u0ab5\u0abe\u0a97\u0acd\u0aaf\u0ac7",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm \u0ab5\u0abe\u0a97\u0acd\u0aaf\u0ac7",LLLL:"dddd, D MMMM YYYY, A h:mm \u0ab5\u0abe\u0a97\u0acd\u0aaf\u0ac7"},calendar:{sameDay:"[\u0a86\u0a9c] LT",nextDay:"[\u0a95\u0abe\u0ab2\u0ac7] LT",nextWeek:"dddd, LT",lastDay:"[\u0a97\u0a87\u0a95\u0abe\u0ab2\u0ac7] LT",lastWeek:"[\u0aaa\u0abe\u0a9b\u0ab2\u0abe] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0aae\u0abe",past:"%s \u0aaa\u0ac7\u0ab9\u0ab2\u0abe",s:"\u0a85\u0aae\u0ac1\u0a95 \u0aaa\u0ab3\u0acb",ss:"%d \u0ab8\u0ac7\u0a95\u0a82\u0aa1",m:"\u0a8f\u0a95 \u0aae\u0abf\u0aa8\u0abf\u0a9f",mm:"%d \u0aae\u0abf\u0aa8\u0abf\u0a9f",h:"\u0a8f\u0a95 \u0a95\u0ab2\u0abe\u0a95",hh:"%d \u0a95\u0ab2\u0abe\u0a95",d:"\u0a8f\u0a95 \u0aa6\u0abf\u0ab5\u0ab8",dd:"%d \u0aa6\u0abf\u0ab5\u0ab8",M:"\u0a8f\u0a95 \u0aae\u0ab9\u0abf\u0aa8\u0acb",MM:"%d \u0aae\u0ab9\u0abf\u0aa8\u0acb",y:"\u0a8f\u0a95 \u0ab5\u0ab0\u0acd\u0ab7",yy:"%d \u0ab5\u0ab0\u0acd\u0ab7"},preparse:function(t){return t.replace(/[\u0ae7\u0ae8\u0ae9\u0aea\u0aeb\u0aec\u0aed\u0aee\u0aef\u0ae6]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0ab0\u0abe\u0aa4|\u0aac\u0aaa\u0acb\u0ab0|\u0ab8\u0ab5\u0abe\u0ab0|\u0ab8\u0abe\u0a82\u0a9c/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0ab0\u0abe\u0aa4"===e?t<4?t:t+12:"\u0ab8\u0ab5\u0abe\u0ab0"===e?t:"\u0aac\u0aaa\u0acb\u0ab0"===e?t>=10?t:t+12:"\u0ab8\u0abe\u0a82\u0a9c"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0ab0\u0abe\u0aa4":t<10?"\u0ab8\u0ab5\u0abe\u0ab0":t<17?"\u0aac\u0aaa\u0acb\u0ab0":t<20?"\u0ab8\u0abe\u0a82\u0a9c":"\u0ab0\u0abe\u0aa4"},week:{dow:0,doy:6}})}(n("wd/R"))},"4dOw":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},"4fRq":function(t,e){var n="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(n){var a=new Uint8Array(16);t.exports=function(){return n(a),a}}else{var r=new Array(16);t.exports=function(){for(var t,e=0;e<16;e++)0==(3&e)&&(t=4294967296*Math.random()),r[e]=t>>>((3&e)<<3)&255;return r}}},"58b6":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("kQXf");e.FoldingType=function(){function t(t){this._cssClass=t}return Object.defineProperty(t.prototype,"cssClass",{get:function(){return this._cssClass},enumerable:!0,configurable:!0}),t.Expanded=new t("node-expanded"),t.Collapsed=new t("node-collapsed"),t.Empty=new t("node-empty"),t.Leaf=new t("node-leaf"),t}(),e.TreeModelSettings=function(){function t(){}return t.merge=function(e,n){var r=a.omit(a.get(n,"settings"),t.NOT_CASCADING_SETTINGS);return a.defaultsDeep({},a.get(e,"settings"),r,{static:!1,leftMenu:!1,rightMenu:!0,isCollapsedOnInit:!1,checked:!1,keepNodesInDOM:!1,selectionAllowed:!0})},t.NOT_CASCADING_SETTINGS=["selectionAllowed"],t}(),e.Ng2TreeSettings=function(){return function(){this.rootIsVisible=!0,this.showCheckboxes=!1,this.enableCheckboxes=!0}}(),e.TreeStatus=function(t){return t[t.New=0]="New",t[t.Modified=1]="Modified",t[t.IsBeingRenamed=2]="IsBeingRenamed",t}(e.TreeStatus||{})},"5ZZ7":function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,a=n.datasets,r=n.labels;if(a.length)for(var i=0;i<a[0].data.length;++i)e.push('<li><span style="background-color:'+a[0].backgroundColor[i]+'"></span>'),r[i]&&e.push(r[i]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,a){var r=t.getDatasetMeta(0),s=e.datasets[0],o=r.data[a].custom||{},u=i.valueAtIndexOrDefault,c=t.options.elements.arc;return{text:n,fillStyle:o.backgroundColor?o.backgroundColor:u(s.backgroundColor,a,c.backgroundColor),strokeStyle:o.borderColor?o.borderColor:u(s.borderColor,a,c.borderColor),lineWidth:o.borderWidth?o.borderWidth:u(s.borderWidth,a,c.borderWidth),hidden:isNaN(s.data[a])||r.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,a,r,i=e.index,s=this.chart;for(n=0,a=(s.data.datasets||[]).length;n<a;++n)(r=s.getDatasetMeta(n)).data[i].hidden=!r.data[i].hidden;s.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),t.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:r.Arc,linkScales:i.noop,update:function(t){var e,n,a,r=this,s=r.getDataset(),o=r.getMeta(),u=r.chart.options.startAngle||0,c=r._starts=[],l=r._angles=[];for(r._updateRadius(),o.count=r.countVisibleElements(),e=0,n=s.data.length;e<n;e++)c[e]=u,a=r._computeAngle(e),l[e]=a,u+=a;i.each(o.data,function(e,n){r.updateElement(e,n,t)})},_updateRadius:function(){var t=this,e=t.chart,n=e.chartArea,a=e.options,r=a.elements.arc,i=Math.min(n.right-n.left,n.bottom-n.top);e.outerRadius=Math.max((i-r.borderWidth/2)/2,0),e.innerRadius=Math.max(a.cutoutPercentage?e.outerRadius/100*a.cutoutPercentage:1,0),e.radiusLength=(e.outerRadius-e.innerRadius)/e.getVisibleDatasetCount(),t.outerRadius=e.outerRadius-e.radiusLength*t.index,t.innerRadius=t.outerRadius-e.radiusLength},updateElement:function(t,e,n){var a=this,r=a.chart,s=a.getDataset(),o=r.options,u=o.animation,c=r.scale,l=r.data.labels,d=c.xCenter,f=c.yCenter,p=o.startAngle,h=t.hidden?0:c.getDistanceFromCenterForValue(s.data[e]),g=a._starts[e],b=g+(t.hidden?0:a._angles[e]),m=u.animateScale?0:c.getDistanceFromCenterForValue(s.data[e]);i.extend(t,{_datasetIndex:a.index,_index:e,_scale:c,_model:{x:d,y:f,innerRadius:0,outerRadius:n?m:h,startAngle:n&&u.animateRotate?p:g,endAngle:n&&u.animateRotate?p:b,label:i.valueAtIndexOrDefault(l,e,l[e])}});var y=this.chart.options.elements.arc,v=t.custom||{},_=i.valueAtIndexOrDefault,x=t._model;x.backgroundColor=v.backgroundColor?v.backgroundColor:_(s.backgroundColor,e,y.backgroundColor),x.borderColor=v.borderColor?v.borderColor:_(s.borderColor,e,y.borderColor),x.borderWidth=v.borderWidth?v.borderWidth:_(s.borderWidth,e,y.borderWidth),t.pivot()},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return i.each(e.data,function(e,a){isNaN(t.data[a])||e.hidden||n++}),n},_computeAngle:function(t){var e=this,n=this.getMeta().count,a=e.getDataset(),r=e.getMeta();return isNaN(a.data[t])||r.data[t].hidden?0:i.options.resolve([e.chart.options.elements.arc.angle,2*Math.PI/n],{chart:e.chart,dataIndex:t,dataset:a,datasetIndex:e.index},t)}})}},"5tze":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("HV4d")),a(n("ae7Z")),a(n("h+PQ")),a(n("CVuo")),a(n("RnPR")),a(n("ohIB")),a(n("rdkg")),a(n("y9Z7")),a(n("1HVU")),a(n("MgB7")),a(n("h6KF")),a(n("GDJm")),a(n("VYA+")),a(n("AqeW")),a(n("FMPj"))},"6+QB":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(t,e){return 12===t&&(t=0),"pagi"===e?t:"tengahari"===e?t>=11?t:t+12:"petang"===e||"malam"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"pagi":t<15?"tengahari":t<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}()},"60iU":function(t,e,n){"use strict";n.d(e,"b",function(){return a}),n.d(e,"a",function(){return o});var a,r=n("G5J1"),i=n("F/XL"),s=n("XlPw");a||(a={});var o=function(){function t(t,e,n){this.kind=t,this.value=e,this.error=n,this.hasValue="N"===t}return t.prototype.observe=function(t){switch(this.kind){case"N":return t.next&&t.next(this.value);case"E":return t.error&&t.error(this.error);case"C":return t.complete&&t.complete()}},t.prototype.do=function(t,e,n){switch(this.kind){case"N":return t&&t(this.value);case"E":return e&&e(this.error);case"C":return n&&n()}},t.prototype.accept=function(t,e,n){return t&&"function"==typeof t.next?this.observe(t):this.do(t,e,n)},t.prototype.toObservable=function(){switch(this.kind){case"N":return Object(i.a)(this.value);case"E":return Object(s.a)(this.error);case"C":return Object(r.b)()}throw new Error("unexpected notification kind value")},t.createNext=function(e){return void 0!==e?new t("N",e):t.undefinedValueNotification},t.createError=function(e){return new t("E",void 0,e)},t.createComplete=function(){return t.completeNotification},t.completeNotification=new t("C"),t.undefinedValueNotification=new t("N",void 0),t}()},"67Y/":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t,e){return function(n){if("function"!=typeof t)throw new TypeError("argument is not a function. Are you looking for `mapTo()`?");return n.lift(new s(t,e))}}var s=function(){function t(t,e){this.project=t,this.thisArg=e}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.project,this.thisArg))},t}(),o=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.project=n,r.count=0,r.thisArg=a||r,r}return a.__extends(e,t),e.prototype._next=function(t){var e;try{e=this.project.call(this.thisArg,t,this.count++)}catch(n){return void this.destination.error(n)}this.destination.next(e)},e}(r.a)},"6B0Y":function(t,e,n){!function(t){"use strict";var e={1:"\u17e1",2:"\u17e2",3:"\u17e3",4:"\u17e4",5:"\u17e5",6:"\u17e6",7:"\u17e7",8:"\u17e8",9:"\u17e9",0:"\u17e0"},n={"\u17e1":"1","\u17e2":"2","\u17e3":"3","\u17e4":"4","\u17e5":"5","\u17e6":"6","\u17e7":"7","\u17e8":"8","\u17e9":"9","\u17e0":"0"};t.defineLocale("km",{months:"\u1798\u1780\u179a\u17b6_\u1780\u17bb\u1798\u17d2\u1797\u17c8_\u1798\u17b8\u1793\u17b6_\u1798\u17c1\u179f\u17b6_\u17a7\u179f\u1797\u17b6_\u1798\u17b7\u1790\u17bb\u1793\u17b6_\u1780\u1780\u17d2\u1780\u178a\u17b6_\u179f\u17b8\u17a0\u17b6_\u1780\u1789\u17d2\u1789\u17b6_\u178f\u17bb\u179b\u17b6_\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6_\u1792\u17d2\u1793\u17bc".split("_"),monthsShort:"\u1798\u1780\u179a\u17b6_\u1780\u17bb\u1798\u17d2\u1797\u17c8_\u1798\u17b8\u1793\u17b6_\u1798\u17c1\u179f\u17b6_\u17a7\u179f\u1797\u17b6_\u1798\u17b7\u1790\u17bb\u1793\u17b6_\u1780\u1780\u17d2\u1780\u178a\u17b6_\u179f\u17b8\u17a0\u17b6_\u1780\u1789\u17d2\u1789\u17b6_\u178f\u17bb\u179b\u17b6_\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6_\u1792\u17d2\u1793\u17bc".split("_"),weekdays:"\u17a2\u17b6\u1791\u17b7\u178f\u17d2\u1799_\u1785\u17d0\u1793\u17d2\u1791_\u17a2\u1784\u17d2\u1782\u17b6\u179a_\u1796\u17bb\u1792_\u1796\u17d2\u179a\u17a0\u179f\u17d2\u1794\u178f\u17b7\u17cd_\u179f\u17bb\u1780\u17d2\u179a_\u179f\u17c5\u179a\u17cd".split("_"),weekdaysShort:"\u17a2\u17b6_\u1785_\u17a2_\u1796_\u1796\u17d2\u179a_\u179f\u17bb_\u179f".split("_"),weekdaysMin:"\u17a2\u17b6_\u1785_\u17a2_\u1796_\u1796\u17d2\u179a_\u179f\u17bb_\u179f".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/\u1796\u17d2\u179a\u17b9\u1780|\u179b\u17d2\u1784\u17b6\u1785/,isPM:function(t){return"\u179b\u17d2\u1784\u17b6\u1785"===t},meridiem:function(t,e,n){return t<12?"\u1796\u17d2\u179a\u17b9\u1780":"\u179b\u17d2\u1784\u17b6\u1785"},calendar:{sameDay:"[\u1790\u17d2\u1784\u17c3\u1793\u17c1\u17c7 \u1798\u17c9\u17c4\u1784] LT",nextDay:"[\u179f\u17d2\u17a2\u17c2\u1780 \u1798\u17c9\u17c4\u1784] LT",nextWeek:"dddd [\u1798\u17c9\u17c4\u1784] LT",lastDay:"[\u1798\u17d2\u179f\u17b7\u179b\u1798\u17b7\u1789 \u1798\u17c9\u17c4\u1784] LT",lastWeek:"dddd [\u179f\u1794\u17d2\u178f\u17b6\u17a0\u17cd\u1798\u17bb\u1793] [\u1798\u17c9\u17c4\u1784] LT",sameElse:"L"},relativeTime:{future:"%s\u1791\u17c0\u178f",past:"%s\u1798\u17bb\u1793",s:"\u1794\u17c9\u17bb\u1793\u17d2\u1798\u17b6\u1793\u179c\u17b7\u1793\u17b6\u1791\u17b8",ss:"%d \u179c\u17b7\u1793\u17b6\u1791\u17b8",m:"\u1798\u17bd\u1799\u1793\u17b6\u1791\u17b8",mm:"%d \u1793\u17b6\u1791\u17b8",h:"\u1798\u17bd\u1799\u1798\u17c9\u17c4\u1784",hh:"%d \u1798\u17c9\u17c4\u1784",d:"\u1798\u17bd\u1799\u1790\u17d2\u1784\u17c3",dd:"%d \u1790\u17d2\u1784\u17c3",M:"\u1798\u17bd\u1799\u1781\u17c2",MM:"%d \u1781\u17c2",y:"\u1798\u17bd\u1799\u1786\u17d2\u1793\u17b6\u17c6",yy:"%d \u1786\u17d2\u1793\u17b6\u17c6"},dayOfMonthOrdinalParse:/\u1791\u17b8\d{1,2}/,ordinal:"\u1791\u17b8%d",preparse:function(t){return t.replace(/[\u17e1\u17e2\u17e3\u17e4\u17e5\u17e6\u17e7\u17e8\u17e9\u17e0]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},week:{dow:1,doy:4}})}(n("wd/R"))},"6ahw":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("iLxQ"),r=n("DKTb"),i={closed:!0,next:function(t){},error:function(t){if(a.a.useDeprecatedSynchronousErrorHandling)throw t;Object(r.a)(t)},complete:function(){}}},"6blF":function(t,e,n){"use strict";var a=n("1fDf"),r=n("FFOo"),i=n("L/V9"),s=n("6ahw"),o=n("xTla"),u=n("y3By"),c=n("iLxQ");n.d(e,"a",function(){return l});var l=function(){function t(t){this._isScalar=!1,t&&(this._subscribe=t)}return t.prototype.lift=function(e){var n=new t;return n.source=this,n.operator=e,n},t.prototype.subscribe=function(t,e,n){var a=this.operator,o=function(t,e,n){if(t){if(t instanceof r.a)return t;if(t[i.a])return t[i.a]()}return t||e||n?new r.a(t,e,n):new r.a(s.a)}(t,e,n);if(o.add(a?a.call(o,this.source):this.source||c.a.useDeprecatedSynchronousErrorHandling&&!o.syncErrorThrowable?this._subscribe(o):this._trySubscribe(o)),c.a.useDeprecatedSynchronousErrorHandling&&o.syncErrorThrowable&&(o.syncErrorThrowable=!1,o.syncErrorThrown))throw o.syncErrorValue;return o},t.prototype._trySubscribe=function(t){try{return this._subscribe(t)}catch(e){c.a.useDeprecatedSynchronousErrorHandling&&(t.syncErrorThrown=!0,t.syncErrorValue=e),Object(a.a)(t)?t.error(e):console.warn(e)}},t.prototype.forEach=function(t,e){var n=this;return new(e=d(e))(function(e,a){var r;r=n.subscribe(function(e){try{t(e)}catch(n){a(n),r&&r.unsubscribe()}},a,e)})},t.prototype._subscribe=function(t){var e=this.source;return e&&e.subscribe(t)},t.prototype[o.a]=function(){return this},t.prototype.pipe=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return 0===t.length?this:Object(u.b)(t)(this)},t.prototype.toPromise=function(t){var e=this;return new(t=d(t))(function(t,n){var a;e.subscribe(function(t){return a=t},function(t){return n(t)},function(){return t(a)})})},t.create=function(e){return new t(e)},t}();function d(t){if(t||(t=c.a.Promise||Promise),!t)throw new Error("no Promise impl found");return t}},"6rqY":function(t,e,n){"use strict";var a=n("A5uo"),r=n("dpnK"),i=n("CDJp"),s=n("RDha"),o=n("mlr9"),u=n("fELs"),c=n("iM7B"),l=n("VgNv"),d=n("tjFV"),f=n("x8uC");t.exports=function(t){function e(t){return"top"===t||"bottom"===t}t.types={},t.instances={},t.controllers={},s.extend(t.prototype,{construct:function(e,n){var a=this;n=function(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=s.configMerge(i.global,i[t.type],t.options||{}),t}(n);var r=c.acquireContext(e,n),o=r&&r.canvas,u=o&&o.height,l=o&&o.width;a.id=s.uid(),a.ctx=r,a.canvas=o,a.config=n,a.width=l,a.height=u,a.aspectRatio=u?l/u:null,a.options=n.options,a._bufferedRender=!1,a.chart=a,a.controller=a,t.instances[a.id]=a,Object.defineProperty(a,"data",{get:function(){return a.config.data},set:function(t){a.config.data=t}}),r&&o?(a.initialize(),a.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),s.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return s.canvas.clear(this),this},stop:function(){return r.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,a=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,i=Math.max(0,Math.floor(s.getMaximumWidth(a))),o=Math.max(0,Math.floor(r?i/r:s.getMaximumHeight(a)));if((e.width!==i||e.height!==o)&&(a.width=e.width=i,a.height=e.height=o,a.style.width=i+"px",a.style.height=o+"px",s.retinaScale(e,n.devicePixelRatio),!t)){var u={width:i,height:o};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update({duration:e.options.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;s.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),s.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var t=this,n=t.options,a=t.scales||{},r=[],i=Object.keys(a).reduce(function(t,e){return t[e]=!1,t},{});n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),s.each(r,function(n){var r=n.options,o=r.id,u=s.valueOrDefault(r.type,n.dtype);e(r.position)!==e(n.dposition)&&(r.position=n.dposition),i[o]=!0;var c=null;if(o in a&&a[o].type===u)(c=a[o]).options=r,c.ctx=t.ctx,c.chart=t;else{var l=d.getScaleConstructor(u);if(!l)return;c=new l({id:o,type:u,options:r,ctx:t.ctx,chart:t}),a[c.id]=c}c.mergeTicksOptions(),n.isDefault&&(t.scale=c)}),s.each(i,function(t,e){t||delete a[e]}),t.scales=a,d.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],a=[];return s.each(e.data.datasets,function(r,i){var s=e.getDatasetMeta(i),o=r.type||e.config.type;if(s.type&&s.type!==o&&(e.destroyDatasetMeta(i),s=e.getDatasetMeta(i)),s.type=o,n.push(s.type),s.controller)s.controller.updateIndex(i),s.controller.linkScales();else{var u=t.controllers[s.type];if(void 0===u)throw new Error('"'+s.type+'" is not a chart type.');s.controller=new u(e,i),a.push(s.controller)}},e),a},resetElements:function(){var t=this;s.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(e){var n,a,r=this;if(e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]}),a=(n=r).options,s.each(n.scales,function(t){u.removeBox(n,t)}),a=s.configMerge(t.defaults.global,t.defaults[n.config.type],a),n.options=n.config.options=a,n.ensureScalesHaveIDs(),n.buildOrUpdateScales(),n.tooltip._options=a.tooltips,n.tooltip.initialize(),l._invalidate(r),!1!==l.notify(r,"beforeUpdate")){r.tooltip._data=r.data;var i=r.buildOrUpdateControllers();s.each(r.data.datasets,function(t,e){r.getDatasetMeta(e).controller.buildOrUpdateElements()},r),r.updateLayout(),r.options.animation&&r.options.animation.duration&&s.each(i,function(t){t.reset()}),r.updateDatasets(),r.tooltip.initialize(),r.lastActive=[],l.notify(r,"afterUpdate"),r._bufferedRender?r._bufferedRequest={duration:e.duration,easing:e.easing,lazy:e.lazy}:r.render(e)}},updateLayout:function(){!1!==l.notify(this,"beforeLayout")&&(u.update(this,this.width,this.height),l.notify(this,"afterScaleUpdate"),l.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==l.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);l.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),n={meta:e,index:t};!1!==l.notify(this,"beforeDatasetUpdate",[n])&&(e.controller.update(),l.notify(this,"afterDatasetUpdate",[n]))},render:function(t){var e=this;t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]});var n=t.duration,i=t.lazy;if(!1!==l.notify(e,"beforeRender")){var o=e.options.animation,u=function(t){l.notify(e,"afterRender"),s.callback(o&&o.onComplete,[t],e)};if(o&&(void 0!==n&&0!==n||void 0===n&&0!==o.duration)){var c=new a({numSteps:(n||o.duration)/16.66,easing:t.easing||o.easing,render:function(t,e){var n=e.currentStep,a=n/e.numSteps;t.draw((0,s.easing.effects[e.easing])(a),a,n)},onAnimationProgress:o.onProgress,onAnimationComplete:u});r.addAnimation(e,c,n,i)}else e.draw(),u(new a({numSteps:0,chart:e}));return e}},draw:function(t){var e=this;e.clear(),s.isNullOrUndef(t)&&(t=1),e.transition(t),e.width<=0||e.height<=0||!1!==l.notify(e,"beforeDraw",[t])&&(s.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e._drawTooltip(t),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=0,n=(this.data.datasets||[]).length;e<n;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this.getDatasetMeta(t),a={meta:n,index:t,easingValue:e};!1!==l.notify(this,"beforeDatasetDraw",[a])&&(n.controller.draw(e),l.notify(this,"afterDatasetDraw",[a]))},_drawTooltip:function(t){var e=this.tooltip,n={tooltip:e,easingValue:t};!1!==l.notify(this,"beforeTooltipDraw",[n])&&(e.draw(),l.notify(this,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var a=o.modes[e];return"function"==typeof a?a(this,t,n):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var n=e._meta[this.id];return n||(n=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),n},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],a=n._meta&&n._meta[e];a&&(a.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,a=this,r=a.canvas;for(a.stop(),e=0,n=a.data.datasets.length;e<n;++e)a.destroyDatasetMeta(e);r&&(a.unbindEvents(),s.canvas.clear(a),c.releaseContext(a.ctx),a.canvas=null,a.ctx=null),l.notify(a,"destroy"),delete t.instances[a.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var t=this;t.tooltip=new f({_chart:t,_chartInstance:t,_data:t.data,_options:t.options.tooltips},t)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};s.each(t.options.events,function(a){c.addEventListener(t,a,n),e[a]=n}),t.options.responsive&&(n=function(){t.resize()},c.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,s.each(e,function(e,n){c.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var a,r,i,s=n?"setHoverStyle":"removeHoverStyle";for(r=0,i=t.length;r<i;++r)(a=t[r])&&this.getDatasetMeta(a._datasetIndex).controller[s](a)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var a=e.handleEvent(t);n&&(a=n._start?n.handleEvent(t):a|n.handleEvent(t)),l.notify(e,"afterEvent",[t]);var r=e._bufferedRequest;return r?e.render(r):a&&!e.animating&&(e.stop(),e.render({duration:e.options.hover.animationDuration,lazy:!0})),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,n=this,a=n.options||{},r=a.hover;return n.lastActive=n.lastActive||[],n.active="mouseout"===t.type?[]:n.getElementsAtEventForMode(t,r.mode,r),s.callback(a.onHover||a.hover.onHover,[t.native,n.active],n),"mouseup"!==t.type&&"click"!==t.type||a.onClick&&a.onClick.call(n,t.native,n.active),n.lastActive.length&&n.updateHoverStyle(n.lastActive,r.mode,!1),n.active.length&&r.mode&&n.updateHoverStyle(n.active,r.mode,!0),e=!s.arrayEquals(n.active,n.lastActive),n.lastActive=n.active,e}}),t.Controller=t}},"6ww4":function(t,e,n){var a=n("uxXc"),r=n("mgIt"),i=function(t){return t instanceof i?t:this instanceof i?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=r.getRgba(t))?this.setValues("rgb",e):(e=r.getHsla(t))?this.setValues("hsl",e):(e=r.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new i(t);var e};i.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return r.hexString(this.values.rgb)},rgbString:function(){return r.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return r.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return r.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return r.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return r.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return r.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return r.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var a=t[n]/255;e[n]=a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=t,a=void 0===e?.5:e,r=2*a-1,i=this.alpha()-n.alpha(),s=((r*i==-1?r:(r+i)/(1+r*i))+1)/2,o=1-s;return this.rgb(s*this.red()+o*n.red(),s*this.green()+o*n.green(),s*this.blue()+o*n.blue()).alpha(this.alpha()*a+n.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new i,a=this.values,r=n.values;for(var s in a)a.hasOwnProperty(s)&&("[object Array]"===(e={}.toString.call(t=a[s]))?r[s]=t.slice(0):"[object Number]"===e?r[s]=t:console.error("unexpected color value:",t));return n}},i.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},i.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},i.prototype.getValues=function(t){for(var e=this.values,n={},a=0;a<t.length;a++)n[t.charAt(a)]=e[t][a];return 1!==e.alpha&&(n.a=e.alpha),n},i.prototype.setValues=function(t,e){var n,r,i=this.values,s=this.spaces,o=this.maxes,u=1;if(this.valid=!0,"alpha"===t)u=e;else if(e.length)i[t]=e.slice(0,t.length),u=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)i[t][n]=e[t.charAt(n)];u=e.a}else if(void 0!==e[s[t][0]]){var c=s[t];for(n=0;n<t.length;n++)i[t][n]=e[c[n]];u=e.alpha}if(i.alpha=Math.max(0,Math.min(1,void 0===u?i.alpha:u)),"alpha"===t)return!1;for(n=0;n<t.length;n++)r=Math.max(0,Math.min(o[t][n],i[t][n])),i[t][n]=Math.round(r);for(var l in s)l!==t&&(i[l]=a[t][l](i[t]));return!0},i.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},i.prototype.setChannel=function(t,e,n){var a=this.values[t];return void 0===n?a[e]:n===a[e]?this:(a[e]=n,this.setValues(t,a),this)},"undefined"!=typeof window&&(window.Color=i),t.exports=i},"7BjC":function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={s:["m\xf5ne sekundi","m\xf5ni sekund","paar sekundit"],ss:[t+"sekundi",t+"sekundit"],m:["\xfche minuti","\xfcks minut"],mm:[t+" minuti",t+" minutit"],h:["\xfche tunni","tund aega","\xfcks tund"],hh:[t+" tunni",t+" tundi"],d:["\xfche p\xe4eva","\xfcks p\xe4ev"],M:["kuu aja","kuu aega","\xfcks kuu"],MM:[t+" kuu",t+" kuud"],y:["\xfche aasta","aasta","\xfcks aasta"],yy:[t+" aasta",t+" aastat"]};return e?r[n][2]?r[n][2]:r[n][1]:a?r[n][0]:r[n][1]}n("wd/R").defineLocale("et",{months:"jaanuar_veebruar_m\xe4rts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_m\xe4rts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"p\xfchap\xe4ev_esmasp\xe4ev_teisip\xe4ev_kolmap\xe4ev_neljap\xe4ev_reede_laup\xe4ev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[T\xe4na,] LT",nextDay:"[Homme,] LT",nextWeek:"[J\xe4rgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s p\xe4rast",past:"%s tagasi",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:"%d p\xe4eva",M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},"7F1K":function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("5tze"),o=n("qwkt");e.DataTableSelectionComponent=function(){function t(){this.activate=new i.EventEmitter,this.select=new i.EventEmitter}return t.prototype.selectRow=function(t,e,n){var a;if(this.selectEnabled){var r=this.selectionType===o.SelectionType.checkbox,i=this.selectionType===o.SelectionType.multiClick,u=[];u=this.selectionType===o.SelectionType.multi||r||i?t.shiftKey?s.selectRowsBetween([],this.rows,e,this.prevIndex,this.getRowSelectedIdx.bind(this)):s.selectRows(t.ctrlKey||t.metaKey||i||r?this.selected.slice():[],n,this.getRowSelectedIdx.bind(this)):s.selectRows([],n,this.getRowSelectedIdx.bind(this)),"function"==typeof this.selectCheck&&(u=u.filter(this.selectCheck.bind(this))),this.selected.splice(0,this.selected.length),(a=this.selected).push.apply(a,u),this.prevIndex=e,this.select.emit({selected:u})}},t.prototype.onActivate=function(t,e){var n=t.type,a=t.event,r=t.row,i=this.selectionType===o.SelectionType.checkbox;!i&&("click"===n||"dblclick"===n)||i&&"checkbox"===n?this.selectRow(a,e,r):"keydown"===n&&(a.keyCode===s.Keys.return?this.selectRow(a,e,r):this.onKeyboardFocus(t)),this.activate.emit(t)},t.prototype.onKeyboardFocus=function(t){var e=t.event.keyCode;if(e===s.Keys.up||e===s.Keys.down||e===s.Keys.right||e===s.Keys.left){var n=this.selectionType===o.SelectionType.cell;t.cellElement&&n?n&&this.focusCell(t.cellElement,t.rowElement,e,t.cellIndex):this.focusRow(t.rowElement,e)}},t.prototype.focusRow=function(t,e){var n=this.getPrevNextRow(t,e);n&&n.focus()},t.prototype.getPrevNextRow=function(t,e){var n=t.parentElement;if(n){var a=void 0;if(e===s.Keys.up?a=n.previousElementSibling:e===s.Keys.down&&(a=n.nextElementSibling),a&&a.children.length)return a.children[0]}},t.prototype.focusCell=function(t,e,n,a){var r;if(n===s.Keys.left)r=t.previousElementSibling;else if(n===s.Keys.right)r=t.nextElementSibling;else if(n===s.Keys.up||n===s.Keys.down){var i=this.getPrevNextRow(e,n);if(i){var o=i.getElementsByClassName("datatable-body-cell");o.length&&(r=o[a])}}r&&r.focus()},t.prototype.getRowSelected=function(t){return this.getRowSelectedIdx(t,this.selected)>-1},t.prototype.getRowSelectedIdx=function(t,e){var n=this;if(!e||!e.length)return-1;var a=this.rowIdentity(t);return e.findIndex(function(t){return n.rowIdentity(t)===a})},a([i.Input(),r("design:type",Array)],t.prototype,"rows",void 0),a([i.Input(),r("design:type",Array)],t.prototype,"selected",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"selectEnabled",void 0),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowIdentity",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectCheck",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Component({selector:"datatable-selection",template:"\n <ng-content></ng-content>\n ",changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},"7O6V":function(t,e,n){"use strict";t.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},"7aV9":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("si",{months:"\u0da2\u0db1\u0dc0\u0dcf\u0dbb\u0dd2_\u0db4\u0dd9\u0db6\u0dbb\u0dc0\u0dcf\u0dbb\u0dd2_\u0db8\u0dcf\u0dbb\u0dca\u0dad\u0dd4_\u0d85\u0db4\u0dca\u200d\u0dbb\u0dda\u0dbd\u0dca_\u0db8\u0dd0\u0dba\u0dd2_\u0da2\u0dd6\u0db1\u0dd2_\u0da2\u0dd6\u0dbd\u0dd2_\u0d85\u0d9c\u0ddd\u0dc3\u0dca\u0dad\u0dd4_\u0dc3\u0dd0\u0db4\u0dca\u0dad\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca_\u0d94\u0d9a\u0dca\u0dad\u0ddd\u0db6\u0dbb\u0dca_\u0db1\u0ddc\u0dc0\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca_\u0daf\u0dd9\u0dc3\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca".split("_"),monthsShort:"\u0da2\u0db1_\u0db4\u0dd9\u0db6_\u0db8\u0dcf\u0dbb\u0dca_\u0d85\u0db4\u0dca_\u0db8\u0dd0\u0dba\u0dd2_\u0da2\u0dd6\u0db1\u0dd2_\u0da2\u0dd6\u0dbd\u0dd2_\u0d85\u0d9c\u0ddd_\u0dc3\u0dd0\u0db4\u0dca_\u0d94\u0d9a\u0dca_\u0db1\u0ddc\u0dc0\u0dd0_\u0daf\u0dd9\u0dc3\u0dd0".split("_"),weekdays:"\u0d89\u0dbb\u0dd2\u0daf\u0dcf_\u0dc3\u0db3\u0dd4\u0daf\u0dcf_\u0d85\u0d9f\u0dc4\u0dbb\u0dd4\u0dc0\u0dcf\u0daf\u0dcf_\u0db6\u0daf\u0dcf\u0daf\u0dcf_\u0db6\u0dca\u200d\u0dbb\u0dc4\u0dc3\u0dca\u0db4\u0dad\u0dd2\u0db1\u0dca\u0daf\u0dcf_\u0dc3\u0dd2\u0d9a\u0dd4\u0dbb\u0dcf\u0daf\u0dcf_\u0dc3\u0dd9\u0db1\u0dc3\u0dd4\u0dbb\u0dcf\u0daf\u0dcf".split("_"),weekdaysShort:"\u0d89\u0dbb\u0dd2_\u0dc3\u0db3\u0dd4_\u0d85\u0d9f_\u0db6\u0daf\u0dcf_\u0db6\u0dca\u200d\u0dbb\u0dc4_\u0dc3\u0dd2\u0d9a\u0dd4_\u0dc3\u0dd9\u0db1".split("_"),weekdaysMin:"\u0d89_\u0dc3_\u0d85_\u0db6_\u0db6\u0dca\u200d\u0dbb_\u0dc3\u0dd2_\u0dc3\u0dd9".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"a h:mm",LTS:"a h:mm:ss",L:"YYYY/MM/DD",LL:"YYYY MMMM D",LLL:"YYYY MMMM D, a h:mm",LLLL:"YYYY MMMM D [\u0dc0\u0dd0\u0db1\u0dd2] dddd, a h:mm:ss"},calendar:{sameDay:"[\u0d85\u0daf] LT[\u0da7]",nextDay:"[\u0dc4\u0dd9\u0da7] LT[\u0da7]",nextWeek:"dddd LT[\u0da7]",lastDay:"[\u0d8a\u0dba\u0dda] LT[\u0da7]",lastWeek:"[\u0db4\u0dc3\u0dd4\u0d9c\u0dd2\u0dba] dddd LT[\u0da7]",sameElse:"L"},relativeTime:{future:"%s\u0d9a\u0dd2\u0db1\u0dca",past:"%s\u0d9a\u0da7 \u0db4\u0dd9\u0dbb",s:"\u0dad\u0dad\u0dca\u0db4\u0dbb \u0d9a\u0dd2\u0dc4\u0dd2\u0db4\u0dba",ss:"\u0dad\u0dad\u0dca\u0db4\u0dbb %d",m:"\u0db8\u0dd2\u0db1\u0dd2\u0dad\u0dca\u0dad\u0dd4\u0dc0",mm:"\u0db8\u0dd2\u0db1\u0dd2\u0dad\u0dca\u0dad\u0dd4 %d",h:"\u0db4\u0dd0\u0dba",hh:"\u0db4\u0dd0\u0dba %d",d:"\u0daf\u0dd2\u0db1\u0dba",dd:"\u0daf\u0dd2\u0db1 %d",M:"\u0db8\u0dcf\u0dc3\u0dba",MM:"\u0db8\u0dcf\u0dc3 %d",y:"\u0dc0\u0dc3\u0dbb",yy:"\u0dc0\u0dc3\u0dbb %d"},dayOfMonthOrdinalParse:/\d{1,2} \u0dc0\u0dd0\u0db1\u0dd2/,ordinal:function(t){return t+" \u0dc0\u0dd0\u0db1\u0dd2"},meridiemParse:/\u0db4\u0dd9\u0dbb \u0dc0\u0dbb\u0dd4|\u0db4\u0dc3\u0dca \u0dc0\u0dbb\u0dd4|\u0db4\u0dd9.\u0dc0|\u0db4.\u0dc0./,isPM:function(t){return"\u0db4.\u0dc0."===t||"\u0db4\u0dc3\u0dca \u0dc0\u0dbb\u0dd4"===t},meridiem:function(t,e,n){return t>11?n?"\u0db4.\u0dc0.":"\u0db4\u0dc3\u0dca \u0dc0\u0dbb\u0dd4":n?"\u0db4\u0dd9.\u0dc0.":"\u0db4\u0dd9\u0dbb \u0dc0\u0dbb\u0dd4"}})}()},"8/+R":function(t,e,n){!function(t){"use strict";var e={1:"\u0a67",2:"\u0a68",3:"\u0a69",4:"\u0a6a",5:"\u0a6b",6:"\u0a6c",7:"\u0a6d",8:"\u0a6e",9:"\u0a6f",0:"\u0a66"},n={"\u0a67":"1","\u0a68":"2","\u0a69":"3","\u0a6a":"4","\u0a6b":"5","\u0a6c":"6","\u0a6d":"7","\u0a6e":"8","\u0a6f":"9","\u0a66":"0"};t.defineLocale("pa-in",{months:"\u0a1c\u0a28\u0a35\u0a30\u0a40_\u0a2b\u0a3c\u0a30\u0a35\u0a30\u0a40_\u0a2e\u0a3e\u0a30\u0a1a_\u0a05\u0a2a\u0a4d\u0a30\u0a48\u0a32_\u0a2e\u0a08_\u0a1c\u0a42\u0a28_\u0a1c\u0a41\u0a32\u0a3e\u0a08_\u0a05\u0a17\u0a38\u0a24_\u0a38\u0a24\u0a70\u0a2c\u0a30_\u0a05\u0a15\u0a24\u0a42\u0a2c\u0a30_\u0a28\u0a35\u0a70\u0a2c\u0a30_\u0a26\u0a38\u0a70\u0a2c\u0a30".split("_"),monthsShort:"\u0a1c\u0a28\u0a35\u0a30\u0a40_\u0a2b\u0a3c\u0a30\u0a35\u0a30\u0a40_\u0a2e\u0a3e\u0a30\u0a1a_\u0a05\u0a2a\u0a4d\u0a30\u0a48\u0a32_\u0a2e\u0a08_\u0a1c\u0a42\u0a28_\u0a1c\u0a41\u0a32\u0a3e\u0a08_\u0a05\u0a17\u0a38\u0a24_\u0a38\u0a24\u0a70\u0a2c\u0a30_\u0a05\u0a15\u0a24\u0a42\u0a2c\u0a30_\u0a28\u0a35\u0a70\u0a2c\u0a30_\u0a26\u0a38\u0a70\u0a2c\u0a30".split("_"),weekdays:"\u0a10\u0a24\u0a35\u0a3e\u0a30_\u0a38\u0a4b\u0a2e\u0a35\u0a3e\u0a30_\u0a2e\u0a70\u0a17\u0a32\u0a35\u0a3e\u0a30_\u0a2c\u0a41\u0a27\u0a35\u0a3e\u0a30_\u0a35\u0a40\u0a30\u0a35\u0a3e\u0a30_\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30_\u0a38\u0a3c\u0a28\u0a40\u0a1a\u0a30\u0a35\u0a3e\u0a30".split("_"),weekdaysShort:"\u0a10\u0a24_\u0a38\u0a4b\u0a2e_\u0a2e\u0a70\u0a17\u0a32_\u0a2c\u0a41\u0a27_\u0a35\u0a40\u0a30_\u0a38\u0a3c\u0a41\u0a15\u0a30_\u0a38\u0a3c\u0a28\u0a40".split("_"),weekdaysMin:"\u0a10\u0a24_\u0a38\u0a4b\u0a2e_\u0a2e\u0a70\u0a17\u0a32_\u0a2c\u0a41\u0a27_\u0a35\u0a40\u0a30_\u0a38\u0a3c\u0a41\u0a15\u0a30_\u0a38\u0a3c\u0a28\u0a40".split("_"),longDateFormat:{LT:"A h:mm \u0a35\u0a1c\u0a47",LTS:"A h:mm:ss \u0a35\u0a1c\u0a47",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm \u0a35\u0a1c\u0a47",LLLL:"dddd, D MMMM YYYY, A h:mm \u0a35\u0a1c\u0a47"},calendar:{sameDay:"[\u0a05\u0a1c] LT",nextDay:"[\u0a15\u0a32] LT",nextWeek:"[\u0a05\u0a17\u0a32\u0a3e] dddd, LT",lastDay:"[\u0a15\u0a32] LT",lastWeek:"[\u0a2a\u0a3f\u0a1b\u0a32\u0a47] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0a35\u0a3f\u0a71\u0a1a",past:"%s \u0a2a\u0a3f\u0a1b\u0a32\u0a47",s:"\u0a15\u0a41\u0a1d \u0a38\u0a15\u0a3f\u0a70\u0a1f",ss:"%d \u0a38\u0a15\u0a3f\u0a70\u0a1f",m:"\u0a07\u0a15 \u0a2e\u0a3f\u0a70\u0a1f",mm:"%d \u0a2e\u0a3f\u0a70\u0a1f",h:"\u0a07\u0a71\u0a15 \u0a18\u0a70\u0a1f\u0a3e",hh:"%d \u0a18\u0a70\u0a1f\u0a47",d:"\u0a07\u0a71\u0a15 \u0a26\u0a3f\u0a28",dd:"%d \u0a26\u0a3f\u0a28",M:"\u0a07\u0a71\u0a15 \u0a2e\u0a39\u0a40\u0a28\u0a3e",MM:"%d \u0a2e\u0a39\u0a40\u0a28\u0a47",y:"\u0a07\u0a71\u0a15 \u0a38\u0a3e\u0a32",yy:"%d \u0a38\u0a3e\u0a32"},preparse:function(t){return t.replace(/[\u0a67\u0a68\u0a69\u0a6a\u0a6b\u0a6c\u0a6d\u0a6e\u0a6f\u0a66]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0a30\u0a3e\u0a24|\u0a38\u0a35\u0a47\u0a30|\u0a26\u0a41\u0a2a\u0a39\u0a3f\u0a30|\u0a38\u0a3c\u0a3e\u0a2e/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0a30\u0a3e\u0a24"===e?t<4?t:t+12:"\u0a38\u0a35\u0a47\u0a30"===e?t:"\u0a26\u0a41\u0a2a\u0a39\u0a3f\u0a30"===e?t>=10?t:t+12:"\u0a38\u0a3c\u0a3e\u0a2e"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0a30\u0a3e\u0a24":t<10?"\u0a38\u0a35\u0a47\u0a30":t<17?"\u0a26\u0a41\u0a2a\u0a39\u0a3f\u0a30":t<20?"\u0a38\u0a3c\u0a3e\u0a2e":"\u0a30\u0a3e\u0a24"},week:{dow:0,doy:6}})}(n("wd/R"))},"8//i":function(t,e,n){"use strict";var a=n("CDJp"),r=n("RDha"),i=n("tjFV"),s=n("g8vO");t.exports=function(t){var e=a.global,n={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:s.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function o(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function u(t){var n=t.options.pointLabels,a=r.valueOrDefault(n.fontSize,e.defaultFontSize),i=r.valueOrDefault(n.fontStyle,e.defaultFontStyle),s=r.valueOrDefault(n.fontFamily,e.defaultFontFamily);return{size:a,style:i,family:s,font:r.fontString(a,i,s)}}function c(t,e,n,a,r){return t===a||t===r?{start:e-n/2,end:e+n/2}:t<a||t>r?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){return 0===t||180===t?"center":t<180?"left":"right"}function d(t,e,n,a){if(r.isArray(e))for(var i=n.y,s=1.5*a,o=0;o<e.length;++o)t.fillText(e[o],n.x,i),i+=s;else t.fillText(e,n.x,n.y)}function f(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function p(t){return r.isNumber(t)?t:0}var h=t.LinearScaleBase.extend({setDimensions:function(){var t=this,n=t.options,a=n.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=r.min([t.height,t.width]),s=r.valueOrDefault(a.fontSize,e.defaultFontSize);t.drawingArea=n.display?i/2-(s/2+a.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY;r.each(e.data.datasets,function(i,s){if(e.isDatasetVisible(s)){var o=e.getDatasetMeta(s);r.each(i.data,function(e,r){var i=+t.getRightValue(e);isNaN(i)||o.data[r].hidden||(n=Math.min(i,n),a=Math.max(i,a))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=a===Number.NEGATIVE_INFINITY?0:a,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,n=r.valueOrDefault(t.fontSize,e.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*n)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t;this.options.pointLabels.display?function(t){var e,n,a,i=u(t),s=Math.min(t.height/2,t.width/2),l={r:t.width,l:0,t:t.height,b:0},d={};t.ctx.font=i.font,t._pointLabelSizes=[];var f,p,h,g=o(t);for(e=0;e<g;e++){a=t.getPointPosition(e,s),f=t.ctx,p=i.size,n=r.isArray(h=t.pointLabels[e]||"")?{w:r.longestText(f,f.font,h),h:h.length*p+1.5*(h.length-1)*p}:{w:f.measureText(h).width,h:p},t._pointLabelSizes[e]=n;var b=t.getIndexAngle(e),m=r.toDegrees(b)%360,y=c(m,a.x,n.w,0,180),v=c(m,a.y,n.h,90,270);y.start<l.l&&(l.l=y.start,d.l=b),y.end>l.r&&(l.r=y.end,d.r=b),v.start<l.t&&(l.t=v.start,d.t=b),v.end>l.b&&(l.b=v.end,d.b=b)}t.setReductions(s,l,d)}(this):(t=Math.min(this.height/2,this.width/2),this.drawingArea=Math.round(t),this.setCenterPoint(0,0,0,0))},setReductions:function(t,e,n){var a=e.l/Math.sin(n.l),r=Math.max(e.r-this.width,0)/Math.sin(n.r),i=-e.t/Math.cos(n.t),s=-Math.max(e.b-this.height,0)/Math.cos(n.b);a=p(a),r=p(r),i=p(i),s=p(s),this.drawingArea=Math.min(Math.round(t-(a+r)/2),Math.round(t-(i+s)/2)),this.setCenterPoint(a,r,i,s)},setCenterPoint:function(t,e,n,a){var r=this,i=n+r.drawingArea,s=r.height-a-r.drawingArea;r.xCenter=Math.round((t+r.drawingArea+(r.width-e-r.drawingArea))/2+r.left),r.yCenter=Math.round((i+s)/2+r.top)},getIndexAngle:function(t){return t*(2*Math.PI/o(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(n)*e)+this.xCenter,y:Math.round(Math.sin(n)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0)},draw:function(){var t=this,n=t.options,a=n.gridLines,i=n.ticks,s=r.valueOrDefault;if(n.display){var c=t.ctx,p=this.getIndexAngle(0),h=s(i.fontSize,e.defaultFontSize),g=s(i.fontStyle,e.defaultFontStyle),b=s(i.fontFamily,e.defaultFontFamily),m=r.fontString(h,g,b);r.each(t.ticks,function(n,u){if(u>0||i.reverse){var l=t.getDistanceFromCenterForValue(t.ticksAsNumbers[u]);if(a.display&&0!==u&&function(t,e,n,a){var i=t.ctx;if(i.strokeStyle=r.valueAtIndexOrDefault(e.color,a-1),i.lineWidth=r.valueAtIndexOrDefault(e.lineWidth,a-1),t.options.gridLines.circular)i.beginPath(),i.arc(t.xCenter,t.yCenter,n,0,2*Math.PI),i.closePath(),i.stroke();else{var s=o(t);if(0===s)return;i.beginPath();var u=t.getPointPosition(0,n);i.moveTo(u.x,u.y);for(var c=1;c<s;c++)u=t.getPointPosition(c,n),i.lineTo(u.x,u.y);i.closePath(),i.stroke()}}(t,a,l,u),i.display){var d=s(i.fontColor,e.defaultFontColor);if(c.font=m,c.save(),c.translate(t.xCenter,t.yCenter),c.rotate(p),i.showLabelBackdrop){var f=c.measureText(n).width;c.fillStyle=i.backdropColor,c.fillRect(-f/2-i.backdropPaddingX,-l-h/2-i.backdropPaddingY,f+2*i.backdropPaddingX,h+2*i.backdropPaddingY)}c.textAlign="center",c.textBaseline="middle",c.fillStyle=d,c.fillText(n,0,-l),c.restore()}}}),(n.angleLines.display||n.pointLabels.display)&&function(t){var n=t.ctx,a=t.options,i=a.angleLines,s=a.pointLabels;n.lineWidth=i.lineWidth,n.strokeStyle=i.color;var c=t.getDistanceFromCenterForValue(a.ticks.reverse?t.min:t.max),p=u(t);n.textBaseline="top";for(var h=o(t)-1;h>=0;h--){if(i.display){var g=t.getPointPosition(h,c);n.beginPath(),n.moveTo(t.xCenter,t.yCenter),n.lineTo(g.x,g.y),n.stroke(),n.closePath()}if(s.display){var b=t.getPointPosition(h,c+5),m=r.valueAtIndexOrDefault(s.fontColor,h,e.defaultFontColor);n.font=p.font,n.fillStyle=m;var y=t.getIndexAngle(h),v=r.toDegrees(y);n.textAlign=l(v),f(v,t._pointLabelSizes[h],b),d(n,t.pointLabels[h]||"",b,p.size)}}}(t)}}});i.registerScaleType("radialLinear",h,n)}},"85J/":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){var e=/ceph version\s+([^ ]+)\s+\(.+\)/.exec(t);return e?e[1]:t},t}()},"88/t":function(t,e,n){"use strict";n.r(e);var a=n("DtyJ");n.d(e,"Observable",function(){return a.Observable})},"8TtQ":function(t,e,n){"use strict";var a=n("cdu6"),r=n("tjFV");t.exports=function(){var t=a.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t,e=this,n=e.getLabels();e.minIndex=0,e.maxIndex=n.length-1,void 0!==e.options.ticks.min&&(t=n.indexOf(e.options.ticks.min),e.minIndex=-1!==t?t:e.minIndex),void 0!==e.options.ticks.max&&(t=n.indexOf(e.options.ticks.max),e.maxIndex=-1!==t?t:e.maxIndex),e.min=n[e.minIndex],e.max=n[e.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,a=n.chart.data,r=n.isHorizontal();return a.yLabels&&!r?n.getRightValue(a.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,a=this,r=a.options.offset,i=Math.max(a.maxIndex+1-a.minIndex-(r?0:1),1);if(null!=t&&(n=a.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var s=a.getLabels().indexOf(t=n||t);e=-1!==s?s:e}if(a.isHorizontal()){var o=a.width/i,u=o*(e-a.minIndex);return r&&(u+=o/2),a.left+Math.round(u)}var c=a.height/i,l=c*(e-a.minIndex);return r&&(l+=c/2),a.top+Math.round(l)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,a=Math.max(e._ticks.length-(n?0:1),1),r=e.isHorizontal(),i=(r?e.width:e.height)/a;return t-=r?e.left:e.top,n&&(t-=i/2),(t<=0?0:Math.round(t/i))+e.minIndex},getBasePixel:function(){return this.bottom}});r.registerScaleType("category",t,{position:"bottom"})}},"8g8A":function(t,e,n){"use strict";function a(){return Error.call(this),this.message="object unsubscribed",this.name="ObjectUnsubscribedError",this}n.d(e,"a",function(){return r}),a.prototype=Object.create(Error.prototype);var r=a},"8iEZ":function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DataTableColumnCellDirective=function(){return a([r.Directive({selector:"[ngx-datatable-cell-template]"})],function(t){this.template=t})}()},"8mBD":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("pt",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Do_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"h\xe1 %s",s:"segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},"8xTl":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=function(){function t(){}return t.prototype.transform=function(t){return a.upperFirst(t)},t}()},"909l":function(t,e,n){"use strict";n.d(e,"b",function(){return l}),n.d(e,"a",function(){return d});var a=n("mrSG"),r=n("IUTb"),i=n("isby"),s=n("FFOo"),o=n("MGBS"),u=n("zotm"),c=n("En8+");function l(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t[t.length-1];return"function"==typeof n&&t.pop(),Object(r.a)(t,void 0).lift(new d(n))}var d=function(){function t(t){this.resultSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new f(t,this.resultSelector))},t}(),f=function(t){function e(e,n,a){void 0===a&&(a=Object.create(null));var r=t.call(this,e)||this;return r.iterators=[],r.active=0,r.resultSelector="function"==typeof n?n:null,r.values=a,r}return a.__extends(e,t),e.prototype._next=function(t){var e=this.iterators;Object(i.a)(t)?e.push(new h(t)):e.push("function"==typeof t[c.a]?new p(t[c.a]()):new g(this.destination,this,t))},e.prototype._complete=function(){var t=this.iterators,e=t.length;if(this.unsubscribe(),0!==e){this.active=e;for(var n=0;n<e;n++){var a=t[n];a.stillUnsubscribed?this.destination.add(a.subscribe(a,n)):this.active--}}else this.destination.complete()},e.prototype.notifyInactive=function(){this.active--,0===this.active&&this.destination.complete()},e.prototype.checkIterators=function(){for(var t=this.iterators,e=t.length,n=this.destination,a=0;a<e;a++)if("function"==typeof(s=t[a]).hasValue&&!s.hasValue())return;var r=!1,i=[];for(a=0;a<e;a++){var s,o=(s=t[a]).next();if(s.hasCompleted()&&(r=!0),o.done)return void n.complete();i.push(o.value)}this.resultSelector?this._tryresultSelector(i):n.next(i),r&&n.complete()},e.prototype._tryresultSelector=function(t){var e;try{e=this.resultSelector.apply(this,t)}catch(n){return void this.destination.error(n)}this.destination.next(e)},e}(s.a),p=function(){function t(t){this.iterator=t,this.nextResult=t.next()}return t.prototype.hasValue=function(){return!0},t.prototype.next=function(){var t=this.nextResult;return this.nextResult=this.iterator.next(),t},t.prototype.hasCompleted=function(){var t=this.nextResult;return t&&t.done},t}(),h=function(){function t(t){this.array=t,this.index=0,this.length=0,this.length=t.length}return t.prototype[c.a]=function(){return this},t.prototype.next=function(t){var e=this.index++;return e<this.length?{value:this.array[e],done:!1}:{value:null,done:!0}},t.prototype.hasValue=function(){return this.array.length>this.index},t.prototype.hasCompleted=function(){return this.array.length===this.index},t}(),g=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.parent=n,r.observable=a,r.stillUnsubscribed=!0,r.buffer=[],r.isComplete=!1,r}return a.__extends(e,t),e.prototype[c.a]=function(){return this},e.prototype.next=function(){var t=this.buffer;return 0===t.length&&this.isComplete?{value:null,done:!0}:{value:t.shift(),done:!1}},e.prototype.hasValue=function(){return this.buffer.length>0},e.prototype.hasCompleted=function(){return 0===this.buffer.length&&this.isComplete},e.prototype.notifyComplete=function(){this.buffer.length>0?(this.isComplete=!0,this.parent.notifyInactive()):this.destination.complete()},e.prototype.notifyNext=function(t,e,n,a,r){this.buffer.push(e),this.parent.checkIterators()},e.prototype.subscribe=function(t,e){return Object(u.a)(this,this.observable,this,e)},e}(o.a)},"99TG":function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("Fjl2");e.DatatableGroupHeaderDirective=function(){function t(){this.rowHeight=0,this.toggle=new i.EventEmitter}return t.prototype.toggleExpandGroup=function(t){this.toggle.emit({type:"group",value:t})},t.prototype.expandAllGroups=function(){this.toggle.emit({type:"all",value:!0})},t.prototype.collapseAllGroups=function(){this.toggle.emit({type:"all",value:!1})},a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),i.ContentChild(s.DatatableGroupHeaderTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"toggle",void 0),a([i.Directive({selector:"ngx-datatable-group-header"})],t)}()},"9GXa":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){this.title="Warning"}}()},"9Kw/":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(t){this.i18n=t,this.title=this.i18n("Information")}}()},"9Xeq":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},"9Z1F":function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("mrSG"),r=n("MGBS"),i=n("rPjj"),s=n("zotm");function o(t){return function(e){var n=new u(t),a=e.lift(n);return n.caught=a}}var u=function(){function t(t){this.selector=t}return t.prototype.call=function(t,e){return e.subscribe(new c(t,this.selector,this.caught))},t}(),c=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.selector=n,r.caught=a,r}return a.__extends(e,t),e.prototype.error=function(e){if(!this.isStopped){var n=void 0;try{n=this.selector(e,this.caught)}catch(r){return void t.prototype.error.call(this,r)}this._unsubscribeAndRecycle();var a=new i.a(this,void 0,void 0);this.add(a),Object(s.a)(this,n,void 0,void 0,a)}},e}(r.a)},"9nlD":function(t,e,n){"use strict";n.d(e,"a",function(){return d});var a=n("LvDl"),r=n("26FU"),i=n("mtw6"),s=n("G1I9"),o=n("a0VL"),u=n("ufoC"),c=n("CcnG"),l=n("SZbH"),d=function(){function t(t,e,n){this.toastr=t,this.taskMessageService=e,this.cdDatePipe=n,this.hideToasties=!1,this.dataSource=new r.a([]),this.data$=this.dataSource.asObservable(),this.queued=[],this.KEY="cdNotifications";var i=localStorage.getItem(this.KEY),o=[];a.isString(i)&&(o=JSON.parse(i,function(t,e){return a.isPlainObject(e)?a.assign(new s.a,e):e})),this.dataSource.next(o)}return t.prototype.removeAll=function(){localStorage.removeItem(this.KEY),this.dataSource.next([])},t.prototype.save=function(t){var e=this.dataSource.getValue();for(e.push(t);e.length>10;)e.shift();this.dataSource.next(e),localStorage.setItem(this.KEY,JSON.stringify(e))},t.prototype.show=function(t,e,n,r,i){var o=this;return window.setTimeout(function(){var u;u=a.isFunction(t)?t():a.isObject(t)?t:new s.b(t,e,n,r,i),o.queueToShow(u)},10)},t.prototype.queueToShow=function(t){var e=this;this.cancel(this.queuedTimeoutId),this.queued.find(function(e){return a.isEqual(e,t)})||this.queued.push(t),this.queuedTimeoutId=window.setTimeout(function(){e.showQueued()},500)},t.prototype.showQueued=function(){var t=this;this.getUnifiedTitleQueue().forEach(function(e){var n=new s.a(e);t.save(n),t.showToasty(n)})},t.prototype.getUnifiedTitleQueue=function(){return Object.values(this.queueShiftByTitle()).map(function(t){var e=t[0];return t.length>1&&(e.message="<ul>"+t.map(function(t){return"<li>"+t.message+"</li>"}).join("")+"</ul>"),e})},t.prototype.queueShiftByTitle=function(){for(var t,e={};t=this.queued.shift();)e[t.title]||(e[t.title]=[]),e[t.title].push(t);return e},t.prototype.showToasty=function(t){this.hideToasties||this.toastr[["error","info","success"][t.type]]((t.message?t.message+"<br>":"")+this.renderTimeAndApplicationHtml(t),t.title,t.options)},t.prototype.renderTimeAndApplicationHtml=function(t){return'<small class="date">'+this.cdDatePipe.transform(t.timestamp)+'</small><i class="pull-right custom-icon '+t.applicationClass+'" title="'+t.application+'"></i>'},t.prototype.notifyTask=function(t,e){var n;return void 0===e&&(e=!0),n=t.success&&e?new s.b(i.a.success,this.taskMessageService.getSuccessTitle(t)):new s.b(i.a.error,this.taskMessageService.getErrorTitle(t),this.taskMessageService.getErrorMessage(t)),this.show(n)},t.prototype.cancel=function(t){window.clearTimeout(t)},t.prototype.suspendToasties=function(t){this.hideToasties=t},t.ngInjectableDef=c.defineInjectable({factory:function(){return new t(c.inject(l.j),c.inject(u.a),c.inject(o.a))},token:t,providedIn:"root"}),t}()},"9rRi":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("gd",{months:["Am Faoilleach","An Gearran","Am M\xe0rt","An Giblean","An C\xe8itean","An t-\xd2gmhios","An t-Iuchar","An L\xf9nastal","An t-Sultain","An D\xe0mhair","An t-Samhain","An D\xf9bhlachd"],monthsShort:["Faoi","Gear","M\xe0rt","Gibl","C\xe8it","\xd2gmh","Iuch","L\xf9n","Sult","D\xe0mh","Samh","D\xf9bh"],monthsParseExact:!0,weekdays:["Did\xf2mhnaich","Diluain","Dim\xe0irt","Diciadain","Diardaoin","Dihaoine","Disathairne"],weekdaysShort:["Did","Dil","Dim","Dic","Dia","Dih","Dis"],weekdaysMin:["D\xf2","Lu","M\xe0","Ci","Ar","Ha","Sa"],longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-m\xe0ireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-d\xe8 aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",ss:"%d diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"m\xecos",MM:"%d m\xecosan",y:"bliadhna",yy:"%d bliadhna"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(t){return t+(1===t?"d":t%10==2?"na":"mh")},week:{dow:1,doy:4}})}()},"A+xa":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("cv",{months:"\u043a\u04d1\u0440\u043b\u0430\u0447_\u043d\u0430\u0440\u04d1\u0441_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\u04ab\u04d7\u0440\u0442\u043c\u0435_\u0443\u0442\u04d1_\u04ab\u0443\u0440\u043b\u0430_\u0430\u0432\u04d1\u043d_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448\u0442\u0430\u0432".split("_"),monthsShort:"\u043a\u04d1\u0440_\u043d\u0430\u0440_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\u04ab\u04d7\u0440_\u0443\u0442\u04d1_\u04ab\u0443\u0440_\u0430\u0432\u043d_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448".split("_"),weekdays:"\u0432\u044b\u0440\u0441\u0430\u0440\u043d\u0438\u043a\u0443\u043d_\u0442\u0443\u043d\u0442\u0438\u043a\u0443\u043d_\u044b\u0442\u043b\u0430\u0440\u0438\u043a\u0443\u043d_\u044e\u043d\u043a\u0443\u043d_\u043a\u04d7\u04ab\u043d\u0435\u0440\u043d\u0438\u043a\u0443\u043d_\u044d\u0440\u043d\u0435\u043a\u0443\u043d_\u0448\u04d1\u043c\u0430\u0442\u043a\u0443\u043d".split("_"),weekdaysShort:"\u0432\u044b\u0440_\u0442\u0443\u043d_\u044b\u0442\u043b_\u044e\u043d_\u043a\u04d7\u04ab_\u044d\u0440\u043d_\u0448\u04d1\u043c".split("_"),weekdaysMin:"\u0432\u0440_\u0442\u043d_\u044b\u0442_\u044e\u043d_\u043a\u04ab_\u044d\u0440_\u0448\u043c".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [\u04ab\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u04d1\u0445\u04d7\u043d] D[-\u043c\u04d7\u0448\u04d7]",LLL:"YYYY [\u04ab\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u04d1\u0445\u04d7\u043d] D[-\u043c\u04d7\u0448\u04d7], HH:mm",LLLL:"dddd, YYYY [\u04ab\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u04d1\u0445\u04d7\u043d] D[-\u043c\u04d7\u0448\u04d7], HH:mm"},calendar:{sameDay:"[\u041f\u0430\u044f\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextDay:"[\u042b\u0440\u0430\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastDay:"[\u04d6\u043d\u0435\u0440] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextWeek:"[\u04aa\u0438\u0442\u0435\u0441] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastWeek:"[\u0418\u0440\u0442\u043d\u04d7] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",sameElse:"L"},relativeTime:{future:function(t){return t+(/\u0441\u0435\u0445\u0435\u0442$/i.exec(t)?"\u0440\u0435\u043d":/\u04ab\u0443\u043b$/i.exec(t)?"\u0442\u0430\u043d":"\u0440\u0430\u043d")},past:"%s \u043a\u0430\u044f\u043b\u043b\u0430",s:"\u043f\u04d7\u0440-\u0438\u043a \u04ab\u0435\u043a\u043a\u0443\u043d\u0442",ss:"%d \u04ab\u0435\u043a\u043a\u0443\u043d\u0442",m:"\u043f\u04d7\u0440 \u043c\u0438\u043d\u0443\u0442",mm:"%d \u043c\u0438\u043d\u0443\u0442",h:"\u043f\u04d7\u0440 \u0441\u0435\u0445\u0435\u0442",hh:"%d \u0441\u0435\u0445\u0435\u0442",d:"\u043f\u04d7\u0440 \u043a\u0443\u043d",dd:"%d \u043a\u0443\u043d",M:"\u043f\u04d7\u0440 \u0443\u0439\u04d1\u0445",MM:"%d \u0443\u0439\u04d1\u0445",y:"\u043f\u04d7\u0440 \u04ab\u0443\u043b",yy:"%d \u04ab\u0443\u043b"},dayOfMonthOrdinalParse:/\d{1,2}-\u043c\u04d7\u0448/,ordinal:"%d-\u043c\u04d7\u0448",week:{dow:1,doy:7}})}()},A5uo:function(t,e,n){"use strict";var a=n("K2E3");e=t.exports=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),Object.defineProperty(e.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(e.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})},ANnk:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("aexS"),n("f/UV");var a=function(){function t(t,e,n){this.formScope=t,this.authStorageService=e,this.elementRef=n}return t.prototype.ngAfterViewInit=function(){this.permissions=this.authStorageService.getPermissions(),null!==this.formScope&&(this.service_name=this.formScope.cdFormScope),this.service_name&&!this.permissions[this.service_name].update&&(this.elementRef.nativeElement.disabled=!0)},t}()},AQ68:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("uz-latn",{months:"Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr".split("_"),monthsShort:"Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek".split("_"),weekdays:"Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba".split("_"),weekdaysShort:"Yak_Dush_Sesh_Chor_Pay_Jum_Shan".split("_"),weekdaysMin:"Ya_Du_Se_Cho_Pa_Ju_Sha".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Bugun soat] LT [da]",nextDay:"[Ertaga] LT [da]",nextWeek:"dddd [kuni soat] LT [da]",lastDay:"[Kecha soat] LT [da]",lastWeek:"[O'tgan] dddd [kuni soat] LT [da]",sameElse:"L"},relativeTime:{future:"Yaqin %s ichida",past:"Bir necha %s oldin",s:"soniya",ss:"%d soniya",m:"bir daqiqa",mm:"%d daqiqa",h:"bir soat",hh:"%d soat",d:"bir kun",dd:"%d kun",M:"bir oy",MM:"%d oy",y:"bir yil",yy:"%d yil"},week:{dow:1,doy:7}})}()},ARl4:function(t,e,n){"use strict";n.d(e,"a",function(){return h}),n.d(e,"b",function(){return z}),n.d(e,"c",function(){return G}),n.d(e,"d",function(){return Y}),n.d(e,"e",function(){return V}),n.d(e,"f",function(){return H}),n.d(e,"g",function(){return at}),n.d(e,"h",function(){return B}),n.d(e,"i",function(){return U}),n.d(e,"j",function(){return m}),n.d(e,"k",function(){return ot}),n.d(e,"l",function(){return it}),n.d(e,"m",function(){return st}),n.d(e,"n",function(){return dt}),n.d(e,"o",function(){return ut}),n.d(e,"p",function(){return ct}),n.d(e,"q",function(){return lt}),n.d(e,"r",function(){return F}),n.d(e,"s",function(){return y}),n.d(e,"t",function(){return b}),n.d(e,"u",function(){return Z}),n.d(e,"v",function(){return K}),n.d(e,"w",function(){return J}),n.d(e,"x",function(){return et}),n.d(e,"y",function(){return W}),n.d(e,"z",function(){return Q}),n.d(e,"A",function(){return tt}),n.d(e,"B",function(){return nt}),n.d(e,"C",function(){return $});var a=n("CcnG"),r=n("mrSG"),i=n("VnD/"),s=n("67Y/"),o=n("t9fZ"),u=n("lHUG"),c=n("26FU"),l=n("MwfX"),d=n("NJnL"),f=(n("ihYY"),n("lqqz")),p=(n("gIcY"),n("rpEJ")),h=function(){return function(){this.adaptivePosition=!1,this.isAnimated=!1,this.containerClass="theme-green",this.displayMonths=1,this.showWeekNumbers=!0,this.dateInputFormat="L",this.rangeSeparator=" - ",this.rangeInputFormat="L",this.monthTitle="MMMM",this.yearTitle="YYYY",this.dayLabel="D",this.monthLabel="MMMM",this.yearLabel="YYYY",this.weekNumbers="w"}}(),g=function(){function t(){this._customRangesFish=[]}return Object.defineProperty(t.prototype,"minDate",{set:function(t){this._effects.setMinDate(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"maxDate",{set:function(t){this._effects.setMaxDate(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"daysDisabled",{set:function(t){this._effects.setDaysDisabled(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"datesDisabled",{set:function(t){this._effects.setDatesDisabled(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isDisabled",{set:function(t){this._effects.setDisabled(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"dateCustomClasses",{set:function(t){this._effects.setDateCustomClasses(t)},enumerable:!0,configurable:!0}),t.prototype.setViewMode=function(t){},t.prototype.navigateTo=function(t){},t.prototype.dayHoverHandler=function(t){},t.prototype.weekHoverHandler=function(t){},t.prototype.monthHoverHandler=function(t){},t.prototype.yearHoverHandler=function(t){},t.prototype.daySelectHandler=function(t){},t.prototype.monthSelectHandler=function(t){},t.prototype.yearSelectHandler=function(t){},t.prototype._stopPropagation=function(t){t.stopPropagation()},t}(),b=function(){function t(){}return t.prototype.calculate=function(){return{type:t.CALCULATE}},t.prototype.format=function(){return{type:t.FORMAT}},t.prototype.flag=function(){return{type:t.FLAG}},t.prototype.select=function(e){return{type:t.SELECT,payload:e}},t.prototype.changeViewMode=function(e){return{type:t.CHANGE_VIEWMODE,payload:e}},t.prototype.navigateTo=function(e){return{type:t.NAVIGATE_TO,payload:e}},t.prototype.navigateStep=function(e){return{type:t.NAVIGATE_OFFSET,payload:e}},t.prototype.setOptions=function(e){return{type:t.SET_OPTIONS,payload:e}},t.prototype.selectRange=function(e){return{type:t.SELECT_RANGE,payload:e}},t.prototype.hoverDay=function(e){return{type:t.HOVER,payload:e.isHovered?e.cell.date:null}},t.prototype.minDate=function(e){return{type:t.SET_MIN_DATE,payload:e}},t.prototype.maxDate=function(e){return{type:t.SET_MAX_DATE,payload:e}},t.prototype.daysDisabled=function(e){return{type:t.SET_DAYSDISABLED,payload:e}},t.prototype.datesDisabled=function(e){return{type:t.SET_DATESDISABLED,payload:e}},t.prototype.isDisabled=function(e){return{type:t.SET_IS_DISABLED,payload:e}},t.prototype.setDateCustomClasses=function(e){return{type:t.SET_DATE_CUSTOM_CLASSES,payload:e}},t.prototype.setLocale=function(e){return{type:t.SET_LOCALE,payload:e}},t.CALCULATE="[datepicker] calculate dates matrix",t.FORMAT="[datepicker] format datepicker values",t.FLAG="[datepicker] set flags",t.SELECT="[datepicker] select date",t.NAVIGATE_OFFSET="[datepicker] shift view date",t.NAVIGATE_TO="[datepicker] change view date",t.SET_OPTIONS="[datepicker] update render options",t.HOVER="[datepicker] hover date",t.CHANGE_VIEWMODE="[datepicker] switch view mode",t.SET_MIN_DATE="[datepicker] set min date",t.SET_MAX_DATE="[datepicker] set max date",t.SET_DAYSDISABLED="[datepicker] set days disabled",t.SET_DATESDISABLED="[datepicker] set dates disabled",t.SET_IS_DISABLED="[datepicker] set is disabled",t.SET_DATE_CUSTOM_CLASSES="[datepicker] set date custom classes",t.SET_LOCALE="[datepicker] set datepicker locale",t.SELECT_RANGE="[daterangepicker] select dates range",t}(),m=function(){function t(){this._defaultLocale="en",this._locale=new c.a(this._defaultLocale),this._localeChange=this._locale.asObservable()}return Object.defineProperty(t.prototype,"locale",{get:function(){return this._locale},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"localeChange",{get:function(){return this._localeChange},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"currentLocale",{get:function(){return this._locale.getValue()},enumerable:!0,configurable:!0}),t.prototype.use=function(t){t!==this.currentLocale&&this._locale.next(t)},t}(),y=function(){function t(t,e){this._actions=t,this._localeService=e,this._subs=[]}return t.prototype.init=function(t){return this._store=t,this},t.prototype.setValue=function(t){this._store.dispatch(this._actions.select(t))},t.prototype.setRangeValue=function(t){this._store.dispatch(this._actions.selectRange(t))},t.prototype.setMinDate=function(t){return this._store.dispatch(this._actions.minDate(t)),this},t.prototype.setMaxDate=function(t){return this._store.dispatch(this._actions.maxDate(t)),this},t.prototype.setDaysDisabled=function(t){return this._store.dispatch(this._actions.daysDisabled(t)),this},t.prototype.setDatesDisabled=function(t){return this._store.dispatch(this._actions.datesDisabled(t)),this},t.prototype.setDisabled=function(t){return this._store.dispatch(this._actions.isDisabled(t)),this},t.prototype.setDateCustomClasses=function(t){return this._store.dispatch(this._actions.setDateCustomClasses(t)),this},t.prototype.setOptions=function(t){var e=Object.assign({locale:this._localeService.currentLocale},t);return this._store.dispatch(this._actions.setOptions(e)),this},t.prototype.setBindings=function(t){return t.daysCalendar=this._store.select(function(t){return t.flaggedMonths}).pipe(Object(i.a)(function(t){return!!t})),t.monthsCalendar=this._store.select(function(t){return t.flaggedMonthsCalendar}).pipe(Object(i.a)(function(t){return!!t})),t.yearsCalendar=this._store.select(function(t){return t.yearsCalendarFlagged}).pipe(Object(i.a)(function(t){return!!t})),t.viewMode=this._store.select(function(t){return t.view.mode}),t.options=this._store.select(function(t){return t.showWeekNumbers}).pipe(Object(s.a)(function(t){return{showWeekNumbers:t}})),this},t.prototype.setEventHandlers=function(t){var e=this;return t.setViewMode=function(t){e._store.dispatch(e._actions.changeViewMode(t))},t.navigateTo=function(t){e._store.dispatch(e._actions.navigateStep(t.step))},t.dayHoverHandler=function(t){var n=t.cell;n.isOtherMonth||n.isDisabled||(e._store.dispatch(e._actions.hoverDay(t)),n.isHovered=t.isHovered)},t.monthHoverHandler=function(t){t.cell.isHovered=t.isHovered},t.yearHoverHandler=function(t){t.cell.isHovered=t.isHovered},t.monthSelectHandler=function(t){t.isDisabled||e._store.dispatch(e._actions.navigateTo({unit:{month:Object(u.l)(t.date),year:Object(u.j)(t.date)},viewMode:"day"}))},t.yearSelectHandler=function(t){t.isDisabled||e._store.dispatch(e._actions.navigateTo({unit:{year:Object(u.j)(t.date)},viewMode:"month"}))},this},t.prototype.registerDatepickerSideEffects=function(){var t=this;return this._subs.push(this._store.select(function(t){return t.view}).subscribe(function(e){t._store.dispatch(t._actions.calculate())})),this._subs.push(this._store.select(function(t){return t.monthsModel}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.format())})),this._subs.push(this._store.select(function(t){return t.formattedMonths}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.selectedDate}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.selectedRange}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.monthsCalendar}).subscribe(function(){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.yearsCalendarModel}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.hoveredDate}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._store.select(function(t){return t.dateCustomClasses}).pipe(Object(i.a)(function(t){return!!t})).subscribe(function(e){return t._store.dispatch(t._actions.flag())})),this._subs.push(this._localeService.localeChange.subscribe(function(e){return t._store.dispatch(t._actions.setLocale(e))})),this},t.prototype.destroy=function(){var t,e;try{for(var n=Object(r.__values)(this._subs),a=n.next();!a.done;a=n.next())a.value.unsubscribe()}catch(i){t={error:i}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}},t}(),v={date:new Date,mode:"day"},_=Object.assign(new h,{locale:"en",view:v,selectedRange:[],monthViewOptions:{width:7,height:6}});function x(t,e,n){var a=e&&Object(u.p)(Object(u.d)(t,"month"),e,"day"),r=n&&Object(u.n)(Object(u.G)(t,"month"),n,"day");return a||r}function T(t,e,n){var a=e&&Object(u.p)(Object(u.d)(t,"year"),e,"day"),r=n&&Object(u.n)(Object(u.G)(t,"year"),n,"day");return a||r}function w(t,e){for(var n=t.initialDate,a=new Array(t.height),r=0;r<t.height;r++){a[r]=new Array(t.width);for(var i=0;i<t.width;i++)a[r][i]=e(n),n=Object(u.F)(n,t.shift)}return a}function S(t){var e=Object(u.k)(t),n=e.weekdaysShort(),a=e.firstDayOfWeek();return Object(r.__spread)(n.slice(a),n.slice(0,a))}function O(t,e){return!e||t>=e}var I=4,C=3,k={month:1};function N(t,e){var n=Object(u.G)(t,"year");return{months:w({width:C,height:I,initialDate:n,shift:k},function(t){return{date:t,label:Object(u.f)(t,e.monthLabel,e.locale)}}),monthTitle:"",yearTitle:Object(u.f)(t,e.yearTitle,e.locale)}}var R=4,A=4,D=R*A,E=-1*(Math.floor(D/2)-1),L={year:1};function P(t,e){var n=Object(u.F)(t,{year:E}),a=w({width:A,height:R,initialDate:n,shift:L},function(t){return{date:t,label:Object(u.f)(t,e.yearLabel,e.locale)}});return{years:a,monthTitle:"",yearTitle:function(t,e){return Object(u.f)(t[0][0].date,e.yearTitle,e.locale)+" - "+Object(u.f)(t[R-1][A-1].date,e.yearTitle,e.locale)}(a,e)}}function M(t,e){switch(void 0===t&&(t=_),e.type){case b.CALCULATE:return function(t){var e,n,a,r,i=t.displayMonths,s=t.view.date;if("day"===t.view.mode){t.monthViewOptions.firstDayOfWeek=Object(u.k)(t.locale).firstDayOfWeek();for(var o=new Array(i),c=0;c<i;c++)o[c]=(e=s,n=t.monthViewOptions,void 0,void 0,r=function(t,e){if(Object(u.t)(t,e.firstDayOfWeek))return t;var n=function(t,e){if(0===e)return t;var n=t-e%7;return n<0?n+7:n}(Object(u.h)(t),e.firstDayOfWeek);return Object(u.F)(t,{day:-n})}(a=Object(u.i)(e),n),{daysMatrix:w({width:n.width,height:n.height,initialDate:r,shift:{day:1}},function(t){return t}),month:a}),s=Object(u.F)(s,{month:1});return Object.assign({},t,{monthsModel:o})}if("month"===t.view.mode){for(var l=new Array(i),d=0;d<i;d++)l[d]=N(s,q(t)),s=Object(u.F)(s,{year:1});return Object.assign({},t,{monthsCalendar:l})}if("year"===t.view.mode){var f=new Array(i);for(d=0;d<i;d++)f[d]=P(s,q(t)),s=Object(u.F)(s,{year:D});return Object.assign({},t,{yearsCalendarModel:f})}return t}(t);case b.FORMAT:return function(t,e){if("day"===t.view.mode){var n=t.monthsModel.map(function(e,n){return function(t,e,n){return{month:t.month,monthTitle:Object(u.f)(t.month,e.monthTitle,e.locale),yearTitle:Object(u.f)(t.month,e.yearTitle,e.locale),weekNumbers:(a=t.daysMatrix,r=e.weekNumbers,i=e.locale,a.map(function(t){return t[0]?Object(u.f)(t[0],r,i):""})),weekdays:S(e.locale),weeks:t.daysMatrix.map(function(t,a){return{days:t.map(function(t,r){return{date:t,label:Object(u.f)(t,e.dayLabel,e.locale),monthIndex:n,weekIndex:a,dayIndex:r}})}})};var a,r,i}(e,q(t),n)});return Object.assign({},t,{formattedMonths:n})}var a=t.displayMonths,r=t.view.date;if("month"===t.view.mode){for(var i=new Array(a),s=0;s<a;s++)i[s]=N(r,q(t)),r=Object(u.F)(r,{year:1});return Object.assign({},t,{monthsCalendar:i})}if("year"===t.view.mode){var o=new Array(a);for(s=0;s<a;s++)o[s]=P(r,q(t)),r=Object(u.F)(r,{year:16});return Object.assign({},t,{yearsCalendarModel:o})}return t}(t);case b.FLAG:return function(t,e){if("day"===t.view.mode){var n=t.formattedMonths.map(function(e,n){return function(t,e){return t.weeks.forEach(function(n){n.days.forEach(function(a,r){var i,s,o=!Object(u.w)(a.date,t.month),c=!o&&Object(u.v)(a.date,e.hoveredDate),l=!o&&e.selectedRange&&Object(u.v)(a.date,e.selectedRange[0]),d=!o&&e.selectedRange&&Object(u.v)(a.date,e.selectedRange[1]),f=!o&&Object(u.v)(a.date,e.selectedDate)||l||d,p=!o&&e.selectedRange&&function(t,e,n){return!(!t||!e[0])&&(e[1]?t>e[0]&&t<=e[1]:!!n&&t>e[0]&&t<=n)}(a.date,e.selectedRange,e.hoveredDate),h=e.isDisabled||Object(u.p)(a.date,e.minDate,"day")||Object(u.n)(a.date,e.maxDate,"day")||Object(u.s)(a.date,e.daysDisabled)||(i=a.date,!(void 0===(s=e.datesDisabled)||!s||!s.length)&&s.some(function(t){return Object(u.u)(i,t,"date")})),g=new Date,b=!o&&Object(u.v)(a.date,g),m=e.dateCustomClasses&&e.dateCustomClasses.map(function(t){return Object(u.v)(a.date,t.date)?t.classes:[]}).reduce(function(t,e){return t.concat(e)},[]).join(" ")||"",y=Object.assign({},a,{isOtherMonth:o,isHovered:c,isSelected:f,isSelectionStart:l,isSelectionEnd:d,isInRange:p,isDisabled:h,isToday:b,customClasses:m});a.isOtherMonth===y.isOtherMonth&&a.isHovered===y.isHovered&&a.isSelected===y.isSelected&&a.isSelectionStart===y.isSelectionStart&&a.isSelectionEnd===y.isSelectionEnd&&a.isDisabled===y.isDisabled&&a.isInRange===y.isInRange&&a.customClasses===y.customClasses||(n.days[r]=y)})}),t.hideLeftArrow=e.isDisabled||e.monthIndex>0&&e.monthIndex!==e.displayMonths,t.hideRightArrow=e.isDisabled||e.monthIndex<e.displayMonths&&e.monthIndex+1!==e.displayMonths,t.disableLeftArrow=x(Object(u.F)(t.month,{month:-1}),e.minDate,e.maxDate),t.disableRightArrow=x(Object(u.F)(t.month,{month:1}),e.minDate,e.maxDate),t}(e,{isDisabled:t.isDisabled,minDate:t.minDate,maxDate:t.maxDate,daysDisabled:t.daysDisabled,datesDisabled:t.datesDisabled,hoveredDate:t.hoveredDate,selectedDate:t.selectedDate,selectedRange:t.selectedRange,displayMonths:t.displayMonths,dateCustomClasses:t.dateCustomClasses,monthIndex:n})});return Object.assign({},t,{flaggedMonths:n})}if("month"===t.view.mode){var a=t.monthsCalendar.map(function(e,n){return r={isDisabled:t.isDisabled,minDate:t.minDate,maxDate:t.maxDate,hoveredMonth:t.hoveredMonth,displayMonths:t.displayMonths,monthIndex:n},(a=e).months.forEach(function(t,e){t.forEach(function(t,n){var i=Object(u.w)(t.date,r.hoveredMonth),s=r.isDisabled||x(t.date,r.minDate,r.maxDate),o=Object.assign(t,{isHovered:i,isDisabled:s});t.isHovered===o.isHovered&&t.isDisabled===o.isDisabled||(a.months[e][n]=o)})}),a.hideLeftArrow=r.monthIndex>0&&r.monthIndex!==r.displayMonths,a.hideRightArrow=r.monthIndex<r.displayMonths&&r.monthIndex+1!==r.displayMonths,a.disableLeftArrow=T(Object(u.F)(a.months[0][0].date,{year:-1}),r.minDate,r.maxDate),a.disableRightArrow=T(Object(u.F)(a.months[0][0].date,{year:1}),r.minDate,r.maxDate),a;var a,r});return Object.assign({},t,{flaggedMonthsCalendar:a})}if("year"===t.view.mode){var r=t.yearsCalendarModel.map(function(e,n){return function(t,e){t.years.forEach(function(n,a){n.forEach(function(n,r){var i=Object(u.x)(n.date,e.hoveredYear),s=e.isDisabled||T(n.date,e.minDate,e.maxDate),o=Object.assign(n,{isHovered:i,isDisabled:s});n.isHovered===o.isHovered&&n.isDisabled===o.isDisabled||(t.years[a][r]=o)})}),t.hideLeftArrow=e.yearIndex>0&&e.yearIndex!==e.displayMonths,t.hideRightArrow=e.yearIndex<e.displayMonths&&e.yearIndex+1!==e.displayMonths,t.disableLeftArrow=T(Object(u.F)(t.years[0][0].date,{year:-1}),e.minDate,e.maxDate);var n=t.years.length-1,a=t.years[n].length-1;return t.disableRightArrow=T(Object(u.F)(t.years[n][a].date,{year:1}),e.minDate,e.maxDate),t}(e,{isDisabled:t.isDisabled,minDate:t.minDate,maxDate:t.maxDate,hoveredYear:t.hoveredYear,displayMonths:t.displayMonths,yearIndex:n})});return Object.assign({},t,{yearsCalendarFlagged:r})}return t}(t);case b.NAVIGATE_OFFSET:var n=Object(u.F)(Object(u.G)(t.view.date,"month"),e.payload),a={view:{mode:t.view.mode,date:n}};return Object.assign({},t,a);case b.NAVIGATE_TO:var r=e.payload,i=(n=Object(u.E)(t.view.date,r.unit),void(a=void 0));return a=O(r.viewMode,t.minMode)?{view:{date:n,mode:i=r.viewMode}}:{selectedDate:n,view:{date:n,mode:i=t.view.mode}},Object.assign({},t,a);case b.CHANGE_VIEWMODE:return O(e.payload,t.minMode)?(a={view:{date:n=t.view.date,mode:i=e.payload}},Object.assign({},t,a)):t;case b.HOVER:return Object.assign({},t,{hoveredDate:e.payload});case b.SELECT:return a={selectedDate:e.payload,view:t.view},i=t.view.mode,n=j(e.payload||t.view.date,t.minDate,t.maxDate),a.view={mode:i,date:n},Object.assign({},t,a);case b.SET_OPTIONS:return i=(a=e.payload).minMode?a.minMode:t.view.mode,n=j(Object(u.r)(a.value)&&a.value||Object(u.o)(a.value)&&Object(u.r)(a.value[0])&&a.value[0]||t.view.date,a.minDate,a.maxDate),a.view={mode:i,date:n},a.value&&(Object(u.o)(a.value)&&(a.selectedRange=a.value),a.value instanceof Date&&(a.selectedDate=a.value)),Object.assign({},t,a);case b.SELECT_RANGE:return a={selectedRange:e.payload,view:t.view},i=t.view.mode,n=j(e.payload&&e.payload[0]||t.view.date,t.minDate,t.maxDate),a.view={mode:i,date:n},Object.assign({},t,a);case b.SET_MIN_DATE:return Object.assign({},t,{minDate:e.payload});case b.SET_MAX_DATE:return Object.assign({},t,{maxDate:e.payload});case b.SET_IS_DISABLED:return Object.assign({},t,{isDisabled:e.payload});case b.SET_DATE_CUSTOM_CLASSES:return Object.assign({},t,{dateCustomClasses:e.payload});default:return t}}function q(t){return{locale:t.locale,monthTitle:t.monthTitle,yearTitle:t.yearTitle,dayLabel:t.dayLabel,monthLabel:t.monthLabel,yearLabel:t.yearLabel,weekNumbers:t.weekNumbers}}function j(t,e,n){var a=Array.isArray(t)?t[0]:t;return e&&Object(u.n)(e,a,"day")?e:n&&Object(u.p)(n,a,"day")?n:a}var F=function(t){function e(){var e=new c.a({type:"[datepicker] dispatcher init"}),n=new l.a(_,e,M);return t.call(this,e,M,n)||this}return Object(r.__extends)(e,t),e}(l.b),z=function(t){function e(e,n,r,i,s,o){var u=t.call(this)||this;return u._config=e,u._store=n,u._element=r,u._actions=i,u._positionService=o,u.valueChange=new a.EventEmitter,u.animationState="void",u._subs=[],u._effects=s,u}return Object(r.__extends)(e,t),Object.defineProperty(e.prototype,"value",{set:function(t){this._effects.setValue(t)},enumerable:!0,configurable:!0}),e.prototype.ngOnInit=function(){var t=this;this._positionService.setOptions({modifiers:{flip:{enabled:this._config.adaptivePosition}},allowedPositions:["top","bottom"]}),this._positionService.event$.pipe(Object(o.a)(1)).subscribe(function(){t._positionService.disable(),t.animationState=t._config.isAnimated?t.isTopPosition?"animated-up":"animated-down":"unanimated"}),this.isOtherMonthsActive=this._config.selectFromOtherMonth,this.containerClass=this._config.containerClass,this._effects.init(this._store).setOptions(this._config).setBindings(this).setEventHandlers(this).registerDatepickerSideEffects(),this._subs.push(this._store.select(function(t){return t.selectedDate}).subscribe(function(e){return t.valueChange.emit(e)}))},Object.defineProperty(e.prototype,"isTopPosition",{get:function(){return this._element.nativeElement.classList.contains("top")},enumerable:!0,configurable:!0}),e.prototype.positionServiceEnable=function(){this._positionService.enable()},e.prototype.daySelectHandler=function(t){(this.isOtherMonthsActive?t.isDisabled:t.isOtherMonth||t.isDisabled)||this._store.dispatch(this._actions.select(t.date))},e.prototype.ngOnDestroy=function(){var t,e;try{for(var n=Object(r.__values)(this._subs),a=n.next();!a.done;a=n.next())a.value.unsubscribe()}catch(i){t={error:i}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}this._effects.destroy()},e}(g),G=function(){function t(t,e,n,r,i){this._config=t,this.placement="bottom",this.triggers="click",this.outsideClick=!0,this.container="body",this.outsideEsc=!0,this.bsValueChange=new a.EventEmitter,this._subs=[],Object.assign(this,this._config),this._datepicker=i.createLoader(e,r,n),this.onShown=this._datepicker.onShown,this.onHidden=this._datepicker.onHidden}return Object.defineProperty(t.prototype,"isOpen",{get:function(){return this._datepicker.isShown},set:function(t){t?this.show():this.hide()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bsValue",{set:function(t){this._bsValue!==t&&(this._bsValue=t,this.bsValueChange.emit(t))},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this._datepicker.listen({outsideClick:this.outsideClick,outsideEsc:this.outsideEsc,triggers:this.triggers,show:function(){return t.show()}}),this.setConfig()},t.prototype.ngOnChanges=function(t){this._datepickerRef&&this._datepickerRef.instance&&(t.minDate&&(this._datepickerRef.instance.minDate=this.minDate),t.maxDate&&(this._datepickerRef.instance.maxDate=this.maxDate),t.daysDisabled&&(this._datepickerRef.instance.daysDisabled=this.daysDisabled),t.datesDisabled&&(this._datepickerRef.instance.datesDisabled=this.datesDisabled),t.isDisabled&&(this._datepickerRef.instance.isDisabled=this.isDisabled),t.dateCustomClasses&&(this._datepickerRef.instance.dateCustomClasses=this.dateCustomClasses))},t.prototype.show=function(){var t=this;this._datepicker.isShown||(this.setConfig(),this._datepickerRef=this._datepicker.provide({provide:h,useValue:this._config}).attach(z).to(this.container).position({attachment:this.placement}).show({placement:this.placement}),this._subs.push(this.bsValueChange.subscribe(function(e){t._datepickerRef.instance.value=e})),this._subs.push(this._datepickerRef.instance.valueChange.subscribe(function(e){t.bsValue=e,t.hide()})))},t.prototype.hide=function(){var t,e;this.isOpen&&this._datepicker.hide();try{for(var n=Object(r.__values)(this._subs),a=n.next();!a.done;a=n.next())a.value.unsubscribe()}catch(i){t={error:i}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}},t.prototype.toggle=function(){if(this.isOpen)return this.hide();this.show()},t.prototype.setConfig=function(){this._config=Object.assign({},this._config,this.bsConfig,{value:this._bsValue,isDisabled:this.isDisabled,minDate:this.minDate||this.bsConfig&&this.bsConfig.minDate,maxDate:this.maxDate||this.bsConfig&&this.bsConfig.maxDate,daysDisabled:this.daysDisabled||this.bsConfig&&this.bsConfig.daysDisabled,dateCustomClasses:this.dateCustomClasses||this.bsConfig&&this.bsConfig.dateCustomClasses,datesDisabled:this.datesDisabled||this.bsConfig&&this.bsConfig.datesDisabled,minMode:this.minMode||this.bsConfig&&this.bsConfig.minMode})},t.prototype.ngOnDestroy=function(){this._datepicker.dispose()},t}(),Y=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(r.__extends)(e,t),e}(h),V=function(t){function e(e,n,a,r,i,s){return t.call(this,e,n,a,r,i,s)||this}return Object(r.__extends)(e,t),e}(z),H=function(){function t(t,e,n,a,r){var i=this;this._picker=t,this._localeService=e,this._renderer=n,this._elRef=a,this.changeDetection=r,this._onChange=Function.prototype,this._onTouched=Function.prototype,this._validatorChange=Function.prototype,this._picker.bsValueChange.subscribe(function(t){i._setInputValue(t),i._value!==t&&(i._value=t,i._onChange(t),i._onTouched()),i.changeDetection.markForCheck()}),this._localeService.localeChange.subscribe(function(){i._setInputValue(i._value)})}return t.prototype._setInputValue=function(t){var e=t?Object(u.f)(t,this._picker._config.dateInputFormat,this._localeService.currentLocale):"";this._renderer.setProperty(this._elRef.nativeElement,"value",e)},t.prototype.onChange=function(t){this.writeValue(t.target.value),this._onChange(this._value),this._onTouched()},t.prototype.validate=function(t){var e=t.value;if(null==e||""===e)return null;if(Object(u.q)(e)){if(!Object(u.r)(e))return{bsDate:{invalid:e}};if(this._picker&&this._picker.minDate&&Object(u.p)(e,this._picker.minDate,"date"))return{bsDate:{minDate:this._picker.minDate}};if(this._picker&&this._picker.maxDate&&Object(u.n)(e,this._picker.maxDate,"date"))return{bsDate:{maxDate:this._picker.maxDate}}}},t.prototype.registerOnValidatorChange=function(t){this._validatorChange=t},t.prototype.writeValue=function(t){if(t){var e=this._localeService.currentLocale;if(!Object(u.k)(e))throw new Error('Locale "'+e+'" is not defined, please add it with "defineLocale(...)"');this._value=Object(u.B)(t,this._picker._config.dateInputFormat,this._localeService.currentLocale)}else this._value=null;this._picker.bsValue=this._value},t.prototype.setDisabledState=function(t){this._picker.isDisabled=t,t?this._renderer.setAttribute(this._elRef.nativeElement,"disabled","disabled"):this._renderer.removeAttribute(this._elRef.nativeElement,"disabled")},t.prototype.registerOnChange=function(t){this._onChange=t},t.prototype.registerOnTouched=function(t){this._onTouched=t},t.prototype.onBlur=function(){this._onTouched()},t.prototype.hide=function(){this._picker.hide(),this._renderer.selectRootElement(this._elRef.nativeElement).blur()},t}(),B=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.displayMonths=2,e.isAnimated=!1,e}return Object(r.__extends)(e,t),e}(h),U=function(t){function e(e,n,r,i,s,o){var u=t.call(this)||this;return u._actions=n,u._config=r,u._store=i,u._element=s,u._positionService=o,u.valueChange=new a.EventEmitter,u.animationState="void",u._rangeStack=[],u._subs=[],u._effects=e,u}return Object(r.__extends)(e,t),Object.defineProperty(e.prototype,"value",{set:function(t){this._effects.setRangeValue(t)},enumerable:!0,configurable:!0}),e.prototype.ngOnInit=function(){var t=this;this._positionService.setOptions({modifiers:{flip:{enabled:this._config.adaptivePosition}},allowedPositions:["top","bottom"]}),this._positionService.event$.pipe(Object(o.a)(1)).subscribe(function(){t._positionService.disable(),t.animationState=t._config.isAnimated?t.isTopPosition?"animated-up":"animated-down":"unanimated"}),this.containerClass=this._config.containerClass,this.isOtherMonthsActive=this._config.selectFromOtherMonth,this._effects.init(this._store).setOptions(this._config).setBindings(this).setEventHandlers(this).registerDatepickerSideEffects(),this._subs.push(this._store.select(function(t){return t.selectedRange}).subscribe(function(e){return t.valueChange.emit(e)}))},Object.defineProperty(e.prototype,"isTopPosition",{get:function(){return this._element.nativeElement.classList.contains("top")},enumerable:!0,configurable:!0}),e.prototype.positionServiceEnable=function(){this._positionService.enable()},e.prototype.daySelectHandler=function(t){(this.isOtherMonthsActive?t.isDisabled:t.isOtherMonth||t.isDisabled)||(1===this._rangeStack.length&&(this._rangeStack=t.date>=this._rangeStack[0]?[this._rangeStack[0],t.date]:[t.date]),0===this._rangeStack.length&&(this._rangeStack=[t.date]),this._store.dispatch(this._actions.selectRange(this._rangeStack)),2===this._rangeStack.length&&(this._rangeStack=[]))},e.prototype.ngOnDestroy=function(){var t,e;try{for(var n=Object(r.__values)(this._subs),a=n.next();!a.done;a=n.next())a.value.unsubscribe()}catch(i){t={error:i}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}this._effects.destroy()},e}(g),W=function(){return function(){}}(),K=function(){return function(){}}(),$=function(){return function(){}}(),Z=function(){function t(t,e,n){this._config=t,this._elRef=e,this._renderer=n}return t.prototype.ngOnInit=function(){var t=this;this.day.isToday&&this._config&&this._config.customTodayClass&&this._renderer.addClass(this._elRef.nativeElement,this._config.customTodayClass),"string"==typeof this.day.customClasses&&this.day.customClasses.split(" ").filter(function(t){return t}).forEach(function(e){t._renderer.addClass(t._elRef.nativeElement,e)})},t}(),X=function(){var t={UP:0,DOWN:1};return t[t.UP]="UP",t[t.DOWN]="DOWN",t}(),J=function(){function t(){this.onNavigate=new a.EventEmitter,this.onViewMode=new a.EventEmitter}return t.prototype.navTo=function(t){this.onNavigate.emit(t?X.DOWN:X.UP)},t.prototype.view=function(t){this.onViewMode.emit(t)},t}(),Q=function(){function t(t){this._config=t,this.onNavigate=new a.EventEmitter,this.onViewMode=new a.EventEmitter,this.onSelect=new a.EventEmitter,this.onHover=new a.EventEmitter,this.onHoverWeek=new a.EventEmitter}return t.prototype.navigateTo=function(t){this.onNavigate.emit({step:{month:X.DOWN===t?-1:1}})},t.prototype.changeViewMode=function(t){this.onViewMode.emit(t)},t.prototype.selectDay=function(t){this.onSelect.emit(t)},t.prototype.selectWeek=function(t){var e=this;if(this._config.selectWeek)if(t.days&&t.days[0]&&!t.days[0].isDisabled&&this._config.selectFromOtherMonth)this.onSelect.emit(t.days[0]);else if(0!==t.days.length){var n=t.days.find(function(t){return e._config.selectFromOtherMonth?!t.isDisabled:!t.isOtherMonth&&!t.isDisabled});this.onSelect.emit(n)}},t.prototype.weekHoverHandler=function(t,e){var n=this;this._config.selectWeek&&t.days.find(function(t){return n._config.selectFromOtherMonth?!t.isDisabled:!t.isOtherMonth&&!t.isDisabled})&&(t.isHovered=e,this.isWeekHovered=e,this.onHoverWeek.emit(t))},t.prototype.hoverDay=function(t,e){this._config.selectFromOtherMonth&&t.isOtherMonth&&(t.isOtherMonthHovered=e),this.onHover.emit({cell:t,isHovered:e})},t}(),tt=function(){function t(){this.onNavigate=new a.EventEmitter,this.onViewMode=new a.EventEmitter,this.onSelect=new a.EventEmitter,this.onHover=new a.EventEmitter}return t.prototype.navigateTo=function(t){this.onNavigate.emit({step:{year:X.DOWN===t?-1:1}})},t.prototype.viewMonth=function(t){this.onSelect.emit(t)},t.prototype.hoverMonth=function(t,e){this.onHover.emit({cell:t,isHovered:e})},t.prototype.changeViewMode=function(t){this.onViewMode.emit(t)},t}(),et=function(){return function(){this.ampm="ok",this.hours=0,this.minutes=0}}(),nt=function(){function t(){this.onNavigate=new a.EventEmitter,this.onViewMode=new a.EventEmitter,this.onSelect=new a.EventEmitter,this.onHover=new a.EventEmitter}return t.prototype.navigateTo=function(t){this.onNavigate.emit({step:{year:(X.DOWN===t?-1:1)*D}})},t.prototype.viewYear=function(t){this.onSelect.emit(t)},t.prototype.hoverYear=function(t,e){this.onHover.emit({cell:t,isHovered:e})},t.prototype.changeViewMode=function(t){this.onViewMode.emit(t)},t}(),at=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[f.a,d.a,F,b,h,B,Y,y,m]}},t}(),rt=function(){function t(){}return t.prototype.format=function(t,e,n){return Object(u.f)(t,e,n)},t}(),it=function(){function t(){this.selectionDone=new a.EventEmitter(void 0),this.update=new a.EventEmitter(!1),this.activeDateChange=new a.EventEmitter(void 0),this.stepDay={},this.stepMonth={},this.stepYear={},this.modes=["day","month","year"],this.dateFormatter=new rt}return Object.defineProperty(t.prototype,"activeDate",{get:function(){return this._activeDate},set:function(t){this._activeDate=t},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.uniqueId="datepicker--"+Math.floor(1e4*Math.random()),this.initDate?(this.activeDate=this.initDate,this.selectedDate=new Date(this.activeDate.valueOf()),this.update.emit(this.activeDate)):void 0===this.activeDate&&(this.activeDate=new Date)},t.prototype.ngOnChanges=function(t){this.refreshView(),this.checkIfActiveDateGotUpdated(t.activeDate)},t.prototype.checkIfActiveDateGotUpdated=function(t){if(t&&!t.firstChange){var e=t.previousValue;e&&e instanceof Date&&e.getTime()!==t.currentValue.getTime()&&this.activeDateChange.emit(this.activeDate)}},t.prototype.setCompareHandler=function(t,e){"day"===e&&(this.compareHandlerDay=t),"month"===e&&(this.compareHandlerMonth=t),"year"===e&&(this.compareHandlerYear=t)},t.prototype.compare=function(t,e){if(void 0!==t&&void 0!==e)return"day"===this.datepickerMode&&this.compareHandlerDay?this.compareHandlerDay(t,e):"month"===this.datepickerMode&&this.compareHandlerMonth?this.compareHandlerMonth(t,e):"year"===this.datepickerMode&&this.compareHandlerYear?this.compareHandlerYear(t,e):void 0},t.prototype.setRefreshViewHandler=function(t,e){"day"===e&&(this.refreshViewHandlerDay=t),"month"===e&&(this.refreshViewHandlerMonth=t),"year"===e&&(this.refreshViewHandlerYear=t)},t.prototype.refreshView=function(){"day"===this.datepickerMode&&this.refreshViewHandlerDay&&this.refreshViewHandlerDay(),"month"===this.datepickerMode&&this.refreshViewHandlerMonth&&this.refreshViewHandlerMonth(),"year"===this.datepickerMode&&this.refreshViewHandlerYear&&this.refreshViewHandlerYear()},t.prototype.dateFilter=function(t,e){return this.dateFormatter.format(t,e,this.locale)},t.prototype.isActive=function(t){return 0===this.compare(t.date,this.activeDate)&&(this.activeDateId=t.uid,!0)},t.prototype.createDateObject=function(t,e){var n={};return n.date=new Date(t.getFullYear(),t.getMonth(),t.getDate()),n.date=this.fixTimeZone(n.date),n.label=this.dateFilter(t,e),n.selected=0===this.compare(t,this.selectedDate),n.disabled=this.isDisabled(t),n.current=0===this.compare(t,new Date),n.customClass=this.getCustomClassForDate(n.date),n},t.prototype.split=function(t,e){for(var n=[];t.length>0;)n.push(t.splice(0,e));return n},t.prototype.fixTimeZone=function(t){var e=t.getHours();return new Date(t.getFullYear(),t.getMonth(),t.getDate(),23===e?e+2:0)},t.prototype.select=function(t,e){void 0===e&&(e=!0),this.datepickerMode===this.minMode?(this.activeDate||(this.activeDate=new Date(0,0,0,0,0,0,0)),this.activeDate=new Date(t.getFullYear(),t.getMonth(),t.getDate()),this.activeDate=this.fixTimeZone(this.activeDate),e&&this.selectionDone.emit(this.activeDate)):(this.activeDate=new Date(t.getFullYear(),t.getMonth(),t.getDate()),this.activeDate=this.fixTimeZone(this.activeDate),e&&(this.datepickerMode=this.modes[this.modes.indexOf(this.datepickerMode)-1])),this.selectedDate=new Date(this.activeDate.valueOf()),this.update.emit(this.activeDate),this.refreshView()},t.prototype.move=function(t){var e;if("day"===this.datepickerMode&&(e=this.stepDay),"month"===this.datepickerMode&&(e=this.stepMonth),"year"===this.datepickerMode&&(e=this.stepYear),e){var n=this.activeDate.getFullYear()+t*(e.years||0),a=this.activeDate.getMonth()+t*(e.months||0);this.activeDate=new Date(n,a,1),this.refreshView(),this.activeDateChange.emit(this.activeDate)}},t.prototype.toggleMode=function(t){var e=t||1;this.datepickerMode===this.maxMode&&1===e||this.datepickerMode===this.minMode&&-1===e||(this.datepickerMode=this.modes[this.modes.indexOf(this.datepickerMode)+e],this.refreshView())},t.prototype.getCustomClassForDate=function(t){var e=this;if(!this.customClass)return"";var n=this.customClass.find(function(n){return n.date.valueOf()===t.valueOf()&&n.mode===e.datepickerMode},this);return void 0===n?"":n.clazz},t.prototype.compareDateDisabled=function(t,e){if(void 0!==t&&void 0!==e)return"day"===t.mode&&this.compareHandlerDay?this.compareHandlerDay(t.date,e):"month"===t.mode&&this.compareHandlerMonth?this.compareHandlerMonth(t.date,e):"year"===t.mode&&this.compareHandlerYear?this.compareHandlerYear(t.date,e):void 0},t.prototype.isDisabled=function(t){var e=this,n=!1;return this.dateDisabled&&this.dateDisabled.forEach(function(a){0===e.compareDateDisabled(a,t)&&(n=!0)}),this.dayDisabled&&(n=n||this.dayDisabled.indexOf(t.getDay())>-1),n||this.minDate&&this.compare(t,this.minDate)<0||this.maxDate&&this.compare(t,this.maxDate)>0},t}(),st=function(){return function(){this.locale="en",this.datepickerMode="day",this.startingDay=0,this.yearRange=20,this.minMode="day",this.maxMode="year",this.showWeeks=!0,this.formatDay="DD",this.formatMonth="MMMM",this.formatYear="YYYY",this.formatDayHeader="dd",this.formatDayTitle="MMMM YYYY",this.formatMonthTitle="YYYY",this.onlyCurrentMonth=!1,this.monthColLimit=3,this.yearColLimit=5,this.shortcutPropagation=!1}}(),ot=function(){function t(t){this.datepickerMode="day",this.showWeeks=!0,this.selectionDone=new a.EventEmitter(void 0),this.activeDateChange=new a.EventEmitter(void 0),this.onChange=Function.prototype,this.onTouched=Function.prototype,this._now=new Date,this.config=t,this.configureOptions()}return Object.defineProperty(t.prototype,"activeDate",{get:function(){return this._activeDate||this._now},set:function(t){this._activeDate=t},enumerable:!0,configurable:!0}),t.prototype.configureOptions=function(){Object.assign(this,this.config)},t.prototype.onUpdate=function(t){this.activeDate=t,this.onChange(t)},t.prototype.onSelectionDone=function(t){this.selectionDone.emit(t)},t.prototype.onActiveDateChange=function(t){this.activeDateChange.emit(t)},t.prototype.writeValue=function(t){if(0!==this._datePicker.compare(t,this._activeDate))return t&&t instanceof Date?(this.activeDate=t,void this._datePicker.select(t,!1)):void(this.activeDate=t?new Date(t):void 0)},t.prototype.registerOnChange=function(t){this.onChange=t},t.prototype.registerOnTouched=function(t){this.onTouched=t},t}(),ut=function(){function t(t){this.labels=[],this.rows=[],this.weekNumbers=[],this.datePicker=t}return Object.defineProperty(t.prototype,"isBs4",{get:function(){return!Object(p.d)()},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this.datePicker.stepDay={months:1},this.datePicker.setRefreshViewHandler(function(){var e=this.activeDate.getFullYear(),n=this.activeDate.getMonth(),a=new Date(e,n,1),r=this.startingDay-a.getDay(),i=r>0?7-r:-r,s=new Date(a.getTime());i>0&&s.setDate(1-i);for(var o=t.getDates(s,42),u=[],c=0;c<42;c++){var l=this.createDateObject(o[c],this.formatDay);l.secondary=o[c].getMonth()!==n,l.uid=this.uniqueId+"-"+c,u[c]=l}t.labels=[];for(var d=0;d<7;d++)t.labels[d]={},t.labels[d].abbr=this.dateFilter(u[d].date,this.formatDayHeader),t.labels[d].full=this.dateFilter(u[d].date,"EEEE");if(t.title=this.dateFilter(this.activeDate,this.formatDayTitle),t.rows=this.split(u,7),this.showWeeks){t.weekNumbers=[];for(var f=(11-this.startingDay)%7,p=t.rows.length,h=0;h<p;h++)t.weekNumbers.push(t.getISO8601WeekNumber(t.rows[h][f].date))}},"day"),this.datePicker.setCompareHandler(function(t,e){var n=new Date(t.getFullYear(),t.getMonth(),t.getDate()),a=new Date(e.getFullYear(),e.getMonth(),e.getDate());return n.getTime()-a.getTime()},"day"),this.datePicker.refreshView()},t.prototype.getDates=function(t,e){for(var n,a=new Array(e),r=new Date(t.getTime()),i=0;i<e;)n=new Date(r.getTime()),n=this.datePicker.fixTimeZone(n),a[i++]=n,r=new Date(n.getFullYear(),n.getMonth(),n.getDate()+1);return a},t.prototype.getISO8601WeekNumber=function(t){var e=new Date(t.getTime());e.setDate(e.getDate()+4-(e.getDay()||7));var n=e.getTime();return e.setMonth(0),e.setDate(1),Math.floor(Math.round((n-e.getTime())/864e5)/7)+1},t}(),ct=function(){function t(t){this.rows=[],this.datePicker=t}return Object.defineProperty(t.prototype,"isBs4",{get:function(){return!Object(p.d)()},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this.datePicker.stepMonth={years:1},this.datePicker.setRefreshViewHandler(function(){for(var e,n=new Array(12),a=this.activeDate.getFullYear(),r=0;r<12;r++)e=new Date(a,r,1),e=this.fixTimeZone(e),n[r]=this.createDateObject(e,this.formatMonth),n[r].uid=this.uniqueId+"-"+r;t.title=this.dateFilter(this.activeDate,this.formatMonthTitle),t.rows=this.split(n,t.datePicker.monthColLimit)},"month"),this.datePicker.setCompareHandler(function(t,e){var n=new Date(t.getFullYear(),t.getMonth()),a=new Date(e.getFullYear(),e.getMonth());return n.getTime()-a.getTime()},"month"),this.datePicker.refreshView()},t}(),lt=function(){function t(t){this.rows=[],this.datePicker=t}return Object.defineProperty(t.prototype,"isBs4",{get:function(){return!Object(p.d)()},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this.datePicker.stepYear={years:this.datePicker.yearRange},this.datePicker.setRefreshViewHandler(function(){for(var e,n=new Array(this.yearRange),a=t.getStartingYear(this.activeDate.getFullYear()),r=0;r<this.yearRange;r++)e=new Date(a+r,0,1),e=this.fixTimeZone(e),n[r]=this.createDateObject(e,this.formatYear),n[r].uid=this.uniqueId+"-"+r;t.title=[n[0].label,n[this.yearRange-1].label].join(" - "),t.rows=this.split(n,t.datePicker.yearColLimit)},"year"),this.datePicker.setCompareHandler(function(t,e){return t.getFullYear()-e.getFullYear()},"year"),this.datePicker.refreshView()},t.prototype.getStartingYear=function(t){return(t-1)/this.datePicker.yearRange*this.datePicker.yearRange+1},t}(),dt=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[st]}},t}()},AWcq:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("yJti"),r=function(){function t(){this.vcs=a.a}return t.prototype.ngOnInit=function(){},t}()},AX6q:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha"),s=n("fELs"),o=i.noop;function u(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}a._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,a=this.chart,r=a.getDatasetMeta(n);r.hidden=null===r.hidden?!a.data.datasets[n].hidden:null,a.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return i.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:i.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}});var c=r.extend({initialize:function(t){i.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:o,update:function(t,e,n){var a=this;return a.beforeUpdate(),a.maxWidth=t,a.maxHeight=e,a.margins=n,a.beforeSetDimensions(),a.setDimensions(),a.afterSetDimensions(),a.beforeBuildLabels(),a.buildLabels(),a.afterBuildLabels(),a.beforeFit(),a.fit(),a.afterFit(),a.afterUpdate(),a.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:function(){var t=this,e=t.options.labels||{},n=i.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=t.options,n=e.labels,r=e.display,s=t.ctx,o=a.global,c=i.valueOrDefault,l=c(n.fontSize,o.defaultFontSize),d=c(n.fontStyle,o.defaultFontStyle),f=c(n.fontFamily,o.defaultFontFamily),p=i.fontString(l,d,f),h=t.legendHitBoxes=[],g=t.minSize,b=t.isHorizontal();if(b?(g.width=t.maxWidth,g.height=r?10:0):(g.width=r?10:0,g.height=t.maxHeight),r)if(s.font=p,b){var m=t.lineWidths=[0],y=t.legendItems.length?l+n.padding:0;s.textAlign="left",s.textBaseline="top",i.each(t.legendItems,function(e,a){var r=u(n,l)+l/2+s.measureText(e.text).width;m[m.length-1]+r+n.padding>=t.width&&(y+=l+n.padding,m[m.length]=t.left),h[a]={left:0,top:0,width:r,height:l},m[m.length-1]+=r+n.padding}),g.height+=y}else{var v=n.padding,_=t.columnWidths=[],x=n.padding,T=0,w=0,S=l+v;i.each(t.legendItems,function(t,e){var a=u(n,l)+l/2+s.measureText(t.text).width;w+S>g.height&&(x+=T+n.padding,_.push(T),T=0,w=0),T=Math.max(T,a),w+=S,h[e]={left:0,top:0,width:a,height:l}}),x+=T,_.push(T),g.width+=x}t.width=g.width,t.height=g.height},afterFit:o,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,n=e.labels,r=a.global,s=r.elements.line,o=t.width,c=t.lineWidths;if(e.display){var l,d=t.ctx,f=i.valueOrDefault,p=f(n.fontColor,r.defaultFontColor),h=f(n.fontSize,r.defaultFontSize),g=f(n.fontStyle,r.defaultFontStyle),b=f(n.fontFamily,r.defaultFontFamily),m=i.fontString(h,g,b);d.textAlign="left",d.textBaseline="middle",d.lineWidth=.5,d.strokeStyle=p,d.fillStyle=p,d.font=m;var y=u(n,h),v=t.legendHitBoxes,_=t.isHorizontal();l=_?{x:t.left+(o-c[0])/2,y:t.top+n.padding,line:0}:{x:t.left+n.padding,y:t.top+n.padding,line:0};var x=h+n.padding;i.each(t.legendItems,function(a,u){var p=d.measureText(a.text).width,g=y+h/2+p,b=l.x,m=l.y;_?b+g>=o&&(m=l.y+=x,l.line++,b=l.x=t.left+(o-c[l.line])/2):m+x>t.bottom&&(b=l.x=b+t.columnWidths[l.line]+n.padding,m=l.y=t.top+n.padding,l.line++),function(t,n,a){if(!(isNaN(y)||y<=0)){d.save(),d.fillStyle=f(a.fillStyle,r.defaultColor),d.lineCap=f(a.lineCap,s.borderCapStyle),d.lineDashOffset=f(a.lineDashOffset,s.borderDashOffset),d.lineJoin=f(a.lineJoin,s.borderJoinStyle),d.lineWidth=f(a.lineWidth,s.borderWidth),d.strokeStyle=f(a.strokeStyle,r.defaultColor);var o=0===f(a.lineWidth,s.borderWidth);if(d.setLineDash&&d.setLineDash(f(a.lineDash,s.borderDash)),e.labels&&e.labels.usePointStyle){var u=h*Math.SQRT2/2,c=u/Math.SQRT2;i.canvas.drawPoint(d,a.pointStyle,u,t+c,n+c)}else o||d.strokeRect(t,n,y,h),d.fillRect(t,n,y,h);d.restore()}}(b,m,a),v[u].left=b,v[u].top=m,function(t,e,n,a){var r=h/2,i=y+r+t,s=e+r;d.fillText(n.text,i,s),n.hidden&&(d.beginPath(),d.lineWidth=2,d.moveTo(i,s),d.lineTo(i+a,s),d.stroke())}(b,m,a,p),_?l.x+=g+n.padding:l.y+=x})}},handleEvent:function(t){var e=this,n=e.options,a="mouseup"===t.type?"click":t.type,r=!1;if("mousemove"===a){if(!n.onHover)return}else{if("click"!==a)return;if(!n.onClick)return}var i=t.x,s=t.y;if(i>=e.left&&i<=e.right&&s>=e.top&&s<=e.bottom)for(var o=e.legendHitBoxes,u=0;u<o.length;++u){var c=o[u];if(i>=c.left&&i<=c.left+c.width&&s>=c.top&&s<=c.top+c.height){if("click"===a){n.onClick.call(e,t.native,e.legendItems[u]),r=!0;break}if("mousemove"===a){n.onHover.call(e,t.native,e.legendItems[u]),r=!0;break}}}return r}});function l(t,e){var n=new c({ctx:t.ctx,options:e,chart:t});s.configure(t,n,e),s.addBox(t,n),t.legend=n}t.exports={id:"legend",_element:c,beforeInit:function(t){var e=t.options.legend;e&&l(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(i.mergeIf(e,a.global.legend),n?(s.configure(t,n,e),n.options=e):l(t,e)):n&&(s.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}},Ahxa:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("lUjN");e.DataTableFooterComponent=function(){function t(){this.selectedCount=0,this.page=new i.EventEmitter}return Object.defineProperty(t.prototype,"isVisible",{get:function(){return this.rowCount/this.pageSize>1},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"curPage",{get:function(){return this.offset+1},enumerable:!0,configurable:!0}),a([i.Input(),r("design:type",Number)],t.prototype,"footerHeight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"rowCount",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"pageSize",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offset",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"totalMessage",void 0),a([i.Input(),r("design:type",s.DatatableFooterDirective)],t.prototype,"footerTemplate",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"selectedCount",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectedMessage",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"page",void 0),a([i.Component({selector:"datatable-footer",template:'\n <div\n class="datatable-footer-inner"\n [ngClass]="{\'selected-count\': selectedMessage}"\n [style.height.px]="footerHeight">\n <ng-template\n *ngIf="footerTemplate"\n [ngTemplateOutlet]="footerTemplate.template"\n [ngTemplateOutletContext]="{ \n rowCount: rowCount, \n pageSize: pageSize, \n selectedCount: selectedCount,\n curPage: curPage,\n offset: offset\n }">\n </ng-template>\n <div class="page-count" *ngIf="!footerTemplate">\n <span *ngIf="selectedMessage">\n {{selectedCount?.toLocaleString()}} {{selectedMessage}} / \n </span>\n {{rowCount?.toLocaleString()}} {{totalMessage}}\n </div>\n <datatable-pager *ngIf="!footerTemplate"\n [pagerLeftArrowIcon]="pagerLeftArrowIcon"\n [pagerRightArrowIcon]="pagerRightArrowIcon"\n [pagerPreviousIcon]="pagerPreviousIcon"\n [pagerNextIcon]="pagerNextIcon"\n [page]="curPage"\n [size]="pageSize"\n [count]="rowCount"\n [hidden]="!isVisible"\n (change)="page.emit($event)">\n </datatable-pager>\n </div>\n ',host:{class:"datatable-footer"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},AqeW:function(t,e,n){"use strict";function a(t,e){for(var n,a,r,i=[],s=[];(n=document.elementFromPoint(t,e))&&-1===i.indexOf(n)&&null!=n;)i.push(n),s.push({value:n.style.getPropertyValue("pointer-events"),priority:n.style.getPropertyPriority("pointer-events")}),n.style.setProperty("pointer-events","none","important");for(a=s.length;r=s[--a];)i[a].style.setProperty("pointer-events",r.value?r.value:"",r.priority);return i}Object.defineProperty(e,"__esModule",{value:!0}),"undefined"==typeof document||document.elementsFromPoint||(document.elementsFromPoint=a),e.elementsFromPoint=a},As3K:function(t,e,n){"use strict";var a=n("TC34");t.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,r,i;return a.isObject(t)?(e=+t.top||0,n=+t.right||0,r=+t.bottom||0,i=+t.left||0):e=n=r=i=+t||0,{top:e,right:n,bottom:r,left:i,height:e+r,width:i+n}},resolve:function(t,e,n){var r,i,s;for(r=0,i=t.length;r<i;++r)if(void 0!==(s=t[r])&&(void 0!==e&&"function"==typeof s&&(s=s(e)),void 0!==n&&a.isArray(s)&&(s=s[n]),void 0!==s))return s}}},Avrn:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("aexS"),r=n("CcnG"),i=n("ZYCi"),s=function(){function t(t,e){this.router=t,this.authStorageService=e}return t.prototype.canActivate=function(t,e){return!!this.authStorageService.isLoggedIn()||(this.router.navigate(["/login"],{queryParams:{returnUrl:e.url}}),!1)},t.prototype.canActivateChild=function(t,e){return this.canActivate(t,e)},t.ngInjectableDef=r.defineInjectable({factory:function(){return new t(r.inject(i.l),r.inject(a.a))},token:t,providedIn:"root"}),t}()},AvvY:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ml",{months:"\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f_\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41\u0d35\u0d30\u0d3f_\u0d2e\u0d3e\u0d7c\u0d1a\u0d4d\u0d1a\u0d4d_\u0d0f\u0d2a\u0d4d\u0d30\u0d3f\u0d7d_\u0d2e\u0d47\u0d2f\u0d4d_\u0d1c\u0d42\u0d7a_\u0d1c\u0d42\u0d32\u0d48_\u0d13\u0d17\u0d38\u0d4d\u0d31\u0d4d\u0d31\u0d4d_\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02\u0d2c\u0d7c_\u0d12\u0d15\u0d4d\u0d1f\u0d4b\u0d2c\u0d7c_\u0d28\u0d35\u0d02\u0d2c\u0d7c_\u0d21\u0d3f\u0d38\u0d02\u0d2c\u0d7c".split("_"),monthsShort:"\u0d1c\u0d28\u0d41._\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41._\u0d2e\u0d3e\u0d7c._\u0d0f\u0d2a\u0d4d\u0d30\u0d3f._\u0d2e\u0d47\u0d2f\u0d4d_\u0d1c\u0d42\u0d7a_\u0d1c\u0d42\u0d32\u0d48._\u0d13\u0d17._\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31._\u0d12\u0d15\u0d4d\u0d1f\u0d4b._\u0d28\u0d35\u0d02._\u0d21\u0d3f\u0d38\u0d02.".split("_"),monthsParseExact:!0,weekdays:"\u0d1e\u0d3e\u0d2f\u0d31\u0d3e\u0d34\u0d4d\u0d1a_\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d33\u0d3e\u0d34\u0d4d\u0d1a_\u0d1a\u0d4a\u0d35\u0d4d\u0d35\u0d3e\u0d34\u0d4d\u0d1a_\u0d2c\u0d41\u0d27\u0d28\u0d3e\u0d34\u0d4d\u0d1a_\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d3e\u0d34\u0d4d\u0d1a_\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u0d1a_\u0d36\u0d28\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u0d1a".split("_"),weekdaysShort:"\u0d1e\u0d3e\u0d2f\u0d7c_\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d7e_\u0d1a\u0d4a\u0d35\u0d4d\u0d35_\u0d2c\u0d41\u0d27\u0d7b_\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d02_\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f_\u0d36\u0d28\u0d3f".split("_"),weekdaysMin:"\u0d1e\u0d3e_\u0d24\u0d3f_\u0d1a\u0d4a_\u0d2c\u0d41_\u0d35\u0d4d\u0d2f\u0d3e_\u0d35\u0d46_\u0d36".split("_"),longDateFormat:{LT:"A h:mm -\u0d28\u0d41",LTS:"A h:mm:ss -\u0d28\u0d41",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm -\u0d28\u0d41",LLLL:"dddd, D MMMM YYYY, A h:mm -\u0d28\u0d41"},calendar:{sameDay:"[\u0d07\u0d28\u0d4d\u0d28\u0d4d] LT",nextDay:"[\u0d28\u0d3e\u0d33\u0d46] LT",nextWeek:"dddd, LT",lastDay:"[\u0d07\u0d28\u0d4d\u0d28\u0d32\u0d46] LT",lastWeek:"[\u0d15\u0d34\u0d3f\u0d1e\u0d4d\u0d1e] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0d15\u0d34\u0d3f\u0d1e\u0d4d\u0d1e\u0d4d",past:"%s \u0d2e\u0d41\u0d7b\u0d2a\u0d4d",s:"\u0d05\u0d7d\u0d2a \u0d28\u0d3f\u0d2e\u0d3f\u0d37\u0d19\u0d4d\u0d19\u0d7e",ss:"%d \u0d38\u0d46\u0d15\u0d4d\u0d15\u0d7b\u0d21\u0d4d",m:"\u0d12\u0d30\u0d41 \u0d2e\u0d3f\u0d28\u0d3f\u0d31\u0d4d\u0d31\u0d4d",mm:"%d \u0d2e\u0d3f\u0d28\u0d3f\u0d31\u0d4d\u0d31\u0d4d",h:"\u0d12\u0d30\u0d41 \u0d2e\u0d23\u0d3f\u0d15\u0d4d\u0d15\u0d42\u0d7c",hh:"%d \u0d2e\u0d23\u0d3f\u0d15\u0d4d\u0d15\u0d42\u0d7c",d:"\u0d12\u0d30\u0d41 \u0d26\u0d3f\u0d35\u0d38\u0d02",dd:"%d \u0d26\u0d3f\u0d35\u0d38\u0d02",M:"\u0d12\u0d30\u0d41 \u0d2e\u0d3e\u0d38\u0d02",MM:"%d \u0d2e\u0d3e\u0d38\u0d02",y:"\u0d12\u0d30\u0d41 \u0d35\u0d7c\u0d37\u0d02",yy:"%d \u0d35\u0d7c\u0d37\u0d02"},meridiemParse:/\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f|\u0d30\u0d3e\u0d35\u0d3f\u0d32\u0d46|\u0d09\u0d1a\u0d4d\u0d1a \u0d15\u0d34\u0d3f\u0d1e\u0d4d\u0d1e\u0d4d|\u0d35\u0d48\u0d15\u0d41\u0d28\u0d4d\u0d28\u0d47\u0d30\u0d02|\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f/i,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f"===e&&t>=4||"\u0d09\u0d1a\u0d4d\u0d1a \u0d15\u0d34\u0d3f\u0d1e\u0d4d\u0d1e\u0d4d"===e||"\u0d35\u0d48\u0d15\u0d41\u0d28\u0d4d\u0d28\u0d47\u0d30\u0d02"===e?t+12:t},meridiem:function(t,e,n){return t<4?"\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f":t<12?"\u0d30\u0d3e\u0d35\u0d3f\u0d32\u0d46":t<17?"\u0d09\u0d1a\u0d4d\u0d1a \u0d15\u0d34\u0d3f\u0d1e\u0d4d\u0d1e\u0d4d":t<20?"\u0d35\u0d48\u0d15\u0d41\u0d28\u0d4d\u0d28\u0d47\u0d30\u0d02":"\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f"}})}()},AxiF:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("mrSG"),r=n("FFOo"),i=n("b7mW"),s=n("G5J1");function o(t){return function(e){return 0===t?Object(s.b)():e.lift(new u(t))}}var u=function(){function t(t){if(this.total=t,this.total<0)throw new i.a}return t.prototype.call=function(t,e){return e.subscribe(new c(t,this.total))},t}(),c=function(t){function e(e,n){var a=t.call(this,e)||this;return a.total=n,a.ring=new Array,a.count=0,a}return a.__extends(e,t),e.prototype._next=function(t){var e=this.ring,n=this.total,a=this.count++;e.length<n?e.push(t):e[a%n]=t},e.prototype._complete=function(){var t=this.destination,e=this.count;if(e>0)for(var n=this.count>=this.total?this.total:this.count,a=this.ring,r=0;r<n;r++){var i=e++%n;t.next(a[i])}t.complete()},e}(r.a)},B55N:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ja",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u65e5\u66dc\u65e5_\u6708\u66dc\u65e5_\u706b\u66dc\u65e5_\u6c34\u66dc\u65e5_\u6728\u66dc\u65e5_\u91d1\u66dc\u65e5_\u571f\u66dc\u65e5".split("_"),weekdaysShort:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),weekdaysMin:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5 HH:mm",LLLL:"YYYY\u5e74M\u6708D\u65e5 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5(ddd) HH:mm"},meridiemParse:/\u5348\u524d|\u5348\u5f8c/i,isPM:function(t){return"\u5348\u5f8c"===t},meridiem:function(t,e,n){return t<12?"\u5348\u524d":"\u5348\u5f8c"},calendar:{sameDay:"[\u4eca\u65e5] LT",nextDay:"[\u660e\u65e5] LT",nextWeek:function(t){return t.week()<this.week()?"[\u6765\u9031]dddd LT":"dddd LT"},lastDay:"[\u6628\u65e5] LT",lastWeek:function(t){return this.week()<t.week()?"[\u5148\u9031]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}\u65e5/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\u65e5";default:return t}},relativeTime:{future:"%s\u5f8c",past:"%s\u524d",s:"\u6570\u79d2",ss:"%d\u79d2",m:"1\u5206",mm:"%d\u5206",h:"1\u6642\u9593",hh:"%d\u6642\u9593",d:"1\u65e5",dd:"%d\u65e5",M:"1\u30f6\u6708",MM:"%d\u30f6\u6708",y:"1\u5e74",yy:"%d\u5e74"}})}()},BARL:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG"),i=n("DtyJ");e.ColumnChangesService=function(){function t(){this.columnInputChanges=new i.Subject}return Object.defineProperty(t.prototype,"columnInputChanges$",{get:function(){return this.columnInputChanges.asObservable()},enumerable:!0,configurable:!0}),t.prototype.onInputChange=function(){this.columnInputChanges.next()},a([r.Injectable()],t)}()},BQkM:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){return t+" IOPS"},t}()},BVg3:function(t,e,n){!function(t){"use strict";function e(t){return t%100==11||t%10!=1}function a(t,n,a,r){var i=t+" ";switch(a){case"s":return n||r?"nokkrar sek\xfandur":"nokkrum sek\xfandum";case"ss":return e(t)?i+(n||r?"sek\xfandur":"sek\xfandum"):i+"sek\xfanda";case"m":return n?"m\xedn\xfata":"m\xedn\xfatu";case"mm":return e(t)?i+(n||r?"m\xedn\xfatur":"m\xedn\xfatum"):n?i+"m\xedn\xfata":i+"m\xedn\xfatu";case"hh":return e(t)?i+(n||r?"klukkustundir":"klukkustundum"):i+"klukkustund";case"d":return n?"dagur":r?"dag":"degi";case"dd":return e(t)?n?i+"dagar":i+(r?"daga":"d\xf6gum"):n?i+"dagur":i+(r?"dag":"degi");case"M":return n?"m\xe1nu\xf0ur":r?"m\xe1nu\xf0":"m\xe1nu\xf0i";case"MM":return e(t)?n?i+"m\xe1nu\xf0ir":i+(r?"m\xe1nu\xf0i":"m\xe1nu\xf0um"):n?i+"m\xe1nu\xf0ur":i+(r?"m\xe1nu\xf0":"m\xe1nu\xf0i");case"y":return n||r?"\xe1r":"\xe1ri";case"yy":return e(t)?i+(n||r?"\xe1r":"\xe1rum"):i+(n||r?"\xe1r":"\xe1ri")}}n("wd/R").defineLocale("is",{months:"jan\xfaar_febr\xfaar_mars_apr\xedl_ma\xed_j\xfan\xed_j\xfal\xed_\xe1g\xfast_september_okt\xf3ber_n\xf3vember_desember".split("_"),monthsShort:"jan_feb_mar_apr_ma\xed_j\xfan_j\xfal_\xe1g\xfa_sep_okt_n\xf3v_des".split("_"),weekdays:"sunnudagur_m\xe1nudagur_\xferi\xf0judagur_mi\xf0vikudagur_fimmtudagur_f\xf6studagur_laugardagur".split("_"),weekdaysShort:"sun_m\xe1n_\xferi_mi\xf0_fim_f\xf6s_lau".split("_"),weekdaysMin:"Su_M\xe1_\xder_Mi_Fi_F\xf6_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[\xed dag kl.] LT",nextDay:"[\xe1 morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[\xed g\xe6r kl.] LT",lastWeek:"[s\xed\xf0asta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s s\xed\xf0an",s:a,ss:a,m:a,mm:a,h:"klukkustund",hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},"BY/9":function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="de-DE">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Navigation umschalten</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Dashboard</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Cluster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Hosts</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitore</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSDs</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Konfiguration</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH-Zuordnung</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Manager-Module</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Protokolle</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Warnungen</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Pools</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Block</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Images</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Spiegelung</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Dateisysteme</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Objektgateway</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemons</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Benutzer</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Buckets</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Daten \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> f\xfcr\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> werden abgerufen. Bitte warten...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Zuvor zwischengespeicherte Daten\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n f\xfcr \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> werden angezeigt.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Daten\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> f\xfcr\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> konnten nicht geladen werden.\n Pr\xfcfen Sie die Clusterintegrit\xe4t.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Zur\xfcck</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Sprache ausw\xe4hlen</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Bereichsdaten werden geladen...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Lesen Sie die\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum\n Konfigurieren und Aktivieren der \xdcberwachungsfunktion.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Das Grafana-Dashboard ist nicht vorhanden. In der\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> wird beschrieben,\n wie Grafana Dashboards hinzugef\xfcgt werden.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Grafana-Zeitauswahl</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Einstellungen f\xfcr Zur\xfccksetzungen</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Daten konnten nicht geladen werden.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>ausgew\xe4hlt</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>gefunden</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>insgesamt</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Bearbeiten</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Name</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Beschreibung</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Lange Beschreibung</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Standard</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Daemon-Standard</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Services</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Werte</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu gro\xdf! Er darf nicht gr\xf6\xdfer als \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/> sein.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu klein! Er darf nicht kleiner als \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/> sein.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Speichern</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>CRUSH-Zuordnungsanzeige</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Liste mit Hosts</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Gesamtleistung</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Keine Eintr\xe4ge gefunden</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Clusterprotokolle</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Revisionsprotokoll</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Konfiguration wird geladen...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>Die Konfiguration konnte nicht geladen werden.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Manager-Modul bearbeiten</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>Der eingegebene Wert ist kein g\xfcltiger UUID, z. B.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>Der eingegebene Wert muss eine g\xfcltige IP-Adresse sein.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Dies ist ein Pflichtfeld.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu gro\xdf! Er muss kleiner als \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/> sein oder diesem Wert entsprechen.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu klein! Er muss gr\xf6\xdfer als \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/> sein oder diesem Wert entsprechen.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>Der eingegebene Wert muss eine Zahl sein.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>Der eingegebene Wert muss eine Zahl oder Dezimalzahl sein.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Aktualisieren</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Status</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>Cluster-ID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>Monmap ge\xe4ndert</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>Monmap-Epoche</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>erforderliche Verbindung</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>erforderliche \xdcberwachung</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>In Quorum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Nicht in Quorum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Abbrechen</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Sind Sie sicher dass Sie die ausgew\xe4hlten \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> m\xf6chten?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Ja, ich bin sicher.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Clusterweite OSD-Flags</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Absenden</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Erweitert...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>OSD-Wiederherstellungspriorit\xe4t</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Priorit\xe4t</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Priorit\xe4tswerte anpassen</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Dies ist ein Pflichtfeld!</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu gro\xdf! Er darf nicht gr\xf6\xdfer als \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/> sein.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>Der eingegebene Wert ist zu klein! Er darf nicht kleiner als \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/> sein.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>OSD neu gewichten</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>Der Wert muss zwischen 0 und 1 liegen.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Neu gewichten</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Tief } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Sie sind dabei, einen \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub auf\n das OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> anzuwenden.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {tief } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>OSD-Liste</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> wird markiert als\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>, wenn Sie den Vorgang fortsetzen.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>Es ist nicht sicher, das OSD zu vernichten!</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> wird\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> , wenn Sie den Vorgang fortsetzen.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Details</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Wert</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Schlie\xdfen</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>L\xf6schen</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Integrit\xe4t</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statistiken</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Lesen Sie die \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum\n Konfigurieren und Aktivieren der Verwaltungsfunktion f\xfcr NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Clients</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Jeder Client hat Zugriff</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Adressen</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Pflichtfeld</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Muss mindestens einen kommagetrennten Wert enthalten</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Beispielsweise:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Zugriffstyp</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Clients hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Laden...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- Kein Cluster verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Cluster ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Daemon hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Speicher-Back-End</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- Keine Datenpools verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Speicher-Back-End ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Objektgatewaybenutzer</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- Keine Benutzer verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Objektgatewaybenutzer ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS-Benutzer-ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- keine Clients verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- cephx-Client ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>CephFS-Name</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Sicherheitsbezeichnung</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Sicherheitsbezeichnung aktivieren</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS-Pfad</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>Pfad muss mit einem \'/\' beginnen und kann von einem Wort gefolgt werden</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Neues Verzeichnis wird erstellt</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Pfad</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>Pfad darf nur ein einzelner \'/\' oder ein Wort sein</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Neuer Bucket wird erstellt</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS-Protokoll</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS-Tag</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Alternativer Zugriff f\xfcr \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>-Mountpunkte (d\xfcrfen keinen f\xfchrenden / enthalten)\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Clients k\xf6nnen Unterverzeichnisse m\xf6glicherweise nicht mounten (d. h. wenn das Tag = foo, kann der Client foo/baz m\xf6glicherweise nicht mounten).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>Wenn unterschiedliche Tagoptionen verwendet werden, wird derselbe Pfad m\xf6glicherweise mehrfach exportiert.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>Die Position dieses \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>-Exports\n auf dem \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo-Dateisystem\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (muss eindeutig sein).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>Wenn unterschiedliche Pseudo-Optionen verwendet werden, wird derselbe Pfad m\xf6glicherweise mehrfach exportiert.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- Kein Zugriffstyp verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Zugriffstyp ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- Kein Squash verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- Durchzuf\xfchrende Benutzer-ID-Squashing-Art ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Transportprotokoll</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Willkommen bei Ceph!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Benutzername ist erforderlich</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Passwort ist erforderlich</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Anmeldung</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Der Benutzer ist in Ceph leider nicht enthalten.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Kehren Sie zur \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Anmeldeseite\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zur\xfcck. Sie werden vom Identit\xe4tsanbieter abgemeldet, wenn Sie versuchen, sich erneut anzumelden.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Verboten</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Leider sind Sie nicht berechtigt, den gew\xfcnschten Inhalt anzuzeigen.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Leider konnte der gew\xfcnschte Inhalt nicht gefunden werden.</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Alle l\xf6schen</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Neue Benachrichtigungen</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Keine Hintergrundaufgaben vorhanden.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Hintergrundaufgaben</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Hilfe</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Dokumentation</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\xdcber</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Dashboard-Einstellungen</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Benutzerverwaltung</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Angemeldeter Benutzer</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Angemeldet als\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Abmelden</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Name...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Der ausgew\xe4hlte Name wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Beschreibung...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Berechtigungen</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Rollen</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Benutzername</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Passwort</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Passwort best\xe4tigen</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Passwortbest\xe4tigung stimmt nicht mit dem Passwort \xfcberein.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Vollst\xe4ndiger Name</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>E-Mail-Adresse</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>Ung\xfcltige E-Mail-Adresse.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Sie sind dabei, die Lese-/Aktualisierungsberechtigungen f\xfcr Benutzer von Ihrem eigenen Benutzer zu entfernen.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Wenn Sie den Vorgang fortsetzen, k\xf6nnen Sie Benutzerrollen nicht mehr hinzuf\xfcgen oder entfernen.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>M\xf6chten Sie den Vorgang wirklich fortsetzen?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Leistungsindikatoren nicht verf\xfcgbar</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Attribute (OSD-Zuordnung)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Metadaten nicht verf\xfcgbar</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadaten</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Leistungsindikator</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histogramm nicht verf\xfcgbar: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histogramm</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Leistungsdetails</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Aktuelle Werte</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Typ</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Min.</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Max.</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Flags</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Quelle</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Ebene</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Kann zur Laufzeit aktualisiert werden (bearbeitbar)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Tags</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Auflistungswerte</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Siehe auch</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Clusterstatus</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Manager-Daemons</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Objektgateways</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Metadatenserver</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI-Gateways</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>Client-IOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Clientdurchsatz</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Client-Lese-/Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Wiederherstellungsdurchsatz</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Scrub</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Leistung</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Rohkapazit\xe4t</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objekte</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>Platzierungsgruppen pro OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Platzierungsgruppenstatus</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Kapazit\xe4t</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Weitere Details finden Sie in den \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Protokollen\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>R\xe4nge</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Image in Papierkorb verschieben</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Um \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> in den Papierkorb zu verschieben,\n klicken Sie auf \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Image verschieben\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optional k\xf6nnen Sie ein Ablaufdatum ausw\xe4hlen.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>Schutz l\xe4uft ab am</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>NICHT GESCH\xdcTZT</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Falsches Datumsformat. Verwenden Sie "TT.MM.JJJJ HH:mm:ss".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>Schutz ist bereits abgelaufen. W\xe4hlen Sie ein k\xfcnftiges Datum aus oder lassen Sie es leer.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Image verschieben</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>\xdcbersicht</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Ziele</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Ermittlungsauthentifizierung</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Benutzer</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Benutzernamen m\xfcssen zwischen 8 und 64 Zeichen lang sein und\n d\xfcrfen nur Buchstaben, \'.\', \'@\', \'-\', \'_\' oder \':\' enthalten.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Gemeinsamer Benutzer</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Gemeinsames Passwort</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Lesen Sie die\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum\n Konfigurieren und Aktivieren der Verwaltungsfunktion f\xfcr iSCSI-Ziele.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Verf\xfcgbare Informationen:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>iSCSI-Ziele nicht verf\xfcgbar</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Nur f\xfcr RBD-Images verf\xfcgbar, bei denen \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> aktiviert ist\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Datenpool</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Erstellt</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Gr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Objektgr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Funktionen</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Bereitgestellt</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>n. v.</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Bereitgestellt gesamt</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Striping-Einheit</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Striping-Anzahl</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>\xdcbergeordnet</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Pr\xe4fix f\xfcr Blockname</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Reihenfolge</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Snapshots</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Image</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Diese Einstellung \xfcberschreibt den globalen Wert</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Global</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Dies ist der globale Wert. Kein Wert f\xfcr diese Option wurde f\xfcr dieses Image festgelegt.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' und \'@\' sind nicht zul\xe4ssig.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- Keine rbd-Pools verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Pool ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Dedizierten Datenpool verwenden</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Datenpool</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Dedizierter Pool zur Speicherung von RBD-Objektdaten.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>z. B. 10GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Sie m\xfcssen die Gr\xf6\xdfe erh\xf6hen.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Erweitert</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Striping</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Stripe-Einheit</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Stripe-Einheit ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Dies ist ein Pflichtfeld, da eine Stripe-Anzahl definiert wurde!</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>Die Stripe-Einheit ist gr\xf6\xdfer als die Objektgr\xf6\xdfe.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Stripe-Anzahl</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Dies ist ein Pflichtfeld, da eine Stripe-Einheit definiert wurde!</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Die Stripe-Anzahl muss gr\xf6\xdfer als 0 sein.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD-Snapshot\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Umbenennen} other {Erstellen} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>GESCH\xdcTZT</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>NICHT GESCH\xdcTZT</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Sie sind dabei, ein Rollback durchzuf\xfchren</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Papierkorb bereinigen</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Zum Bereinigen ein oder alle Images ausw\xe4hlen und klicken</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Pool:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Poolname...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Alle</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Image wiederherstellen</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Zum Wiederherstellen</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>Neuen Namen des Images eingeben und klicken</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Neuer Name</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Abgelaufen am</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Gesch\xfctzt bis</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Dieses Image ist gesch\xfctzt bis \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Papierkorb</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>iSCSI-Topologie</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Eine \xc4nderung dieser Parameter von ihren Standardwerten ist in der Regel nicht erforderlich.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Einstellungen</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Best\xe4tigen</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Erweiterte Einstellungen</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>Ziel-IQN</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN hat ein fehlerhaftes Muster.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Eine IQN hat die folgende Notation \'iqn.$jahr-$monat.$umkehradresse:$definierterName\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Zum Beispiel: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Weitere Informationen</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Erweiterte Einstellungen bei diesem Ziel wurden ge\xe4ndert.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portale</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Es sind mindestens \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> Gateways erforderlich.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Portal hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Einstellungen bei diesem Image wurden ge\xe4ndert.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Image hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL-Authentifizierung</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Initiatoren</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Initiator</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>Client-IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>Initiator-IQN muss eindeutig sein.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Benutzernamen m\xfcssen zwischen 8 und 64 Zeichen lang sein und\n d\xfcrfen nur Buchstaben, \'.\', \'@\', \'-\', \'_\' oder \':\' enthalten.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>Der Initiator geh\xf6rt zu einer Gruppe. Images werden in der Gruppe konfiguriert.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Keine Elemente hinzugef\xfcgt.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Initiator hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Gruppen</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Gruppe</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Gruppe hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>RBD-Konfiguration</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Entfernen Sie den lokalen Konfigurationswert. Stattdessen wird der \xfcbergeordnete Konfigurationswert \xfcbernommen und verwendet.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>Der Mindestwert lautet 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Probleme</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Wird synchronisiert</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Fertig</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Spiegelungsmodus f\xfcr Pool bearbeiten</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>W\xe4hlen Sie zum Bearbeiten des Spiegelungsmodus f\xfcr den Pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> einen neuen Modus aus der Liste aus und klicken Sie auf\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aktualisieren\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Modus</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Vor dem Deaktivieren der Spiegelung m\xfcssen Peer-Cluster entfernt werden.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n Peer f\xfcr Poolspiegelung\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Bearbeiten} other {Hinzuf\xfcgen} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> Der Pool\n Spiegeln Sie Peer-Attribute f\xfcr Pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> und klicken Sie auf \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Absenden\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Clustername</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>Der Clustername ist ung\xfcltig.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX-ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX-ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>Die CephX ID ist ung\xfcltig.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Adressen der Monitore</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Kommagetrennte Adressen...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>Die Anrede ist ung\xfcltig.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX-Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64-codierter Schl\xfcssel...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>CephX-Schl\xfcssel muss base64-codiert sein.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Pool-Liste</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>Der Name darf nur alphanumerische Zeichen, Bindestriche und Unterstriche enthalten.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Der ausgew\xe4hlte L\xf6schcode-Profilname wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Plugin</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Datenbl\xf6cke (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Muss gr\xf6\xdfer oder gleich 2 sein.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Datenbl\xf6cke f\xfcr die Codierung (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Muss gr\xf6\xdfer oder gleich 1 sein.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Dauerhaftigkeitssch\xe4tzung (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Standort (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Crush-Ausfalldom\xe4ne</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Crush-Standort</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Keine</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Technik</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Paketgr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Crush-Stamm</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Crush-Ger\xe4teklasse</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>beliebig</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Verzeichnis</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Der ausgew\xe4hlte Poolname wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Pooltyp</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Pooltyp ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Platzierungsgruppen</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Es wird mindestens eine Platzierungsgruppe ben\xf6tigt.</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Ihr Cluster kann nicht so viele Platzierungsgruppen verarbeiten. Berechnen Sie die ben\xf6tigte Anzahl an Platzierungsgruppen.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Hilfe zur Berechnung</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>Die aktuellen Einstellungen f\xfcr die Platzierungsgruppen wurden f\xfcr Sie berechnet.\n Stellen Sie vor dem Senden sicher, dass die Werte Ihren Anforderungen entsprechen.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Crush-Regelsatz</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Crush-Regel ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Crush-Regel</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Crush-Schritte</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Die Regel kann im aktuellen Cluster nicht verwendet werden,\n da es zu wenige OSDs enth\xe4lt, um das von dieser Regel geforderte OSD-Minimum zu erf\xfcllen.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Reproduzierte Gr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>Die angegebene Gr\xf6\xdfe liegt au\xdferhalb des Bereichs. G\xfcltige Werte liegen zwischen\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> und \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>L\xf6schcode-Profil</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- Kein L\xf6schcode-Profil verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- L\xf6schcode-Profil ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC-\xdcberschreibungen</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Anwendungen</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Komprimierung</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algorithmus</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- Kein L\xf6schkomprimierungsalgorithmus verf\xfcgbar --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Minimale Blobgr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>z. B. 128KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>Wert sollte gr\xf6\xdfer als 0 sein</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Maximale Blobgr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>z. B. 512KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>Wert sollte gr\xf6\xdfer als die minimale Blobgr\xf6\xdfe sein</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Verh\xe4ltnis</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Komprimierungsverh\xe4ltnis</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>Wert sollte zwischen 0,0 und 1,0 liegen</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Es ist nicht m\xf6glich, einen RBD-Pool mit \'/\' im Namen zu erstellen.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>\xc4ndern Sie den Namen oder entfernen Sie \'rbd\' aus der Anwendungsliste.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Details zu den Cache-Ebenen</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Lesen Sie die \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum\n Konfigurieren und Aktivieren der Verwaltungsfunktion f\xfcr das Objektgateway.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Liste der Daemons</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Leistungsindikatoren</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Bucket-Daten werden geladen...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Die Bucket-Daten konnten nicht geladen werden.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>Der Wert ist ung\xfcltig.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Inhaber</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Benutzer ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Indextyp</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Platzierungsregel</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Marker</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Maximum f\xfcr Marker</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Version</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Masterversion</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>\xc4nderungszeit</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Zonengruppe</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Bucket-Quote</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Aktiviert</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Maximale Gr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Unbegrenzt</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Maximale Objekte</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Benutzername ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Schl\xfcssel automatisch generieren</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Zugriffsschl\xfcssel</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Geheimer Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>E-Mail-Adresse</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Angehalten</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>System</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {Nein} 1 {Ja} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Maximale Buckets</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Unterbenutzer</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Bef\xe4higungen</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Benutzerquote</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Anzeigen</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Typ ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Berechtigung</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Berechtigung ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Unterbenutzer</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>Die ausgew\xe4hlte Unterbenutzer-ID wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>lesen, schreiben</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>voll</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Swift-Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Geheimnis automatisch generieren</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Benutzerdaten werden geladen...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>Die Benutzerdaten konnten nicht geladen werden.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>Die ausgew\xe4hlte Benutzer-ID wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Dies ist keine g\xfcltige E-Mail-Adresse.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>Die ausgew\xe4hlte E-Mail-Adresse wird bereits verwendet.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Max. Buckets</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>Der eingegebene Wert muss &gt;=0 sein.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3-Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Keine Unterbenutzer vorhanden.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Keine Schl\xfcssel vorhanden.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Keine Bef\xe4higungen vorhanden.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Unbegrenzte Gr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Max. Gr\xf6\xdfe</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Unbegrenzte Objekte</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Max. Objekte</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Aktuell</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target> Ermittlungsauthentifizierung aktualisiert</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Keine Portale verf\xfcgbar.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Keine Images verf\xfcgbar.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Keine Images verf\xfcgbar. F\xfcgen Sie dem Ziel ein Image hinzu.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Keine Initiatoren verf\xfcgen. F\xfcgen Sie dem Ziel einen Initiator hinzu.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Ziel</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Zustand</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Bytes f\xfcr Lesevorgang</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Bytes f\xfcr Schreibvorgang</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O seit</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instanz</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Hostname</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Problem</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Fortschritt</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Deaktiviert</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Bearbeitungsmodus</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Peer hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Peer bearbeiten</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Peer l\xf6schen</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Leader</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># lokal</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># remote</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>Peer spiegeln</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Schl\xfcssel</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Umfassende Vereinfachung</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Schichtung</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Exklusive Sperre</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Objektzuordnung (erfordert exklusive Sperre)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Journaling (erfordert exklusive Sperre)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Rollback f\xfcr RBD-Snapshot</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Rollback</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>RBD-Snapshot</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Gel\xf6scht am</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>Typ</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>Zustand</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>Version</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>Stamm</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Rang</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Aktivit\xe4t</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inodes</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Nutzung</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Standby-Daemons</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>Der Wert kann zur Laufzeit aktualisiert werden.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Daemons/Clients rufen diesen Wert nicht aus der\n Datenbank \'monitor config\' ab. Es ist nicht zul\xe4ssig, diese Option \xfcber \'ceph config\n set ...\' festzulegen. Diese Option sollte \xfcber \'ceph.conf\' oder an der\n Befehlszeile konfiguriert werden.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>Die Option wird nur w\xe4hrend des Daemon-Starts wirksam.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>Die Option wirkt sich nur auf die Cluster-Erstellung aus.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>Die Option wirkt sich nur auf die Daemon-Erstellung aus.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Aktualisierte config-Option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Service</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Aktueller Wert</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Bearbeitbar</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Aktualisierte Optionen f\xfcr Modul &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Aktivieren</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Deaktivieren</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Verbindung wird erneut hergestellt, bitte warten...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>\xd6ffentliche Adresse</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Offene Sitzungen</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Kein In-Vorgang</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>OSDs, die zuvor als \'out\' markiert wurden, werden beim Start nicht wieder markiert</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Kein Out-Vorgang</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSDs werden nach dem konfigurierten Intervall nicht automatisch als \'out\' markiert</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Kein Up-Vorgang</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSDs d\xfcrfen nicht gestartet werden</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Kein Down-Vorgang</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>OSD-Fehlerberichte werden ignoriert, sodass die Monitore die OSDs nicht als ausgefallen markieren</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pause</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>H\xe4lt Lese- und Schreibvorg\xe4nge an</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Kein Scrub</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Scrubbing ist deaktiviert</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Kein umfassender Scrub</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Umfassendes Scrubbing ist deaktiviert</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Kein Abgleich</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Abgleich der Platzierungsgruppen ist ausgesetzt</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Keine Wiederherstellung</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Wiederherstellung der Platzierungsgruppen ist ausgesetzt</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Bitweise Sortierung</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Bitweise Sortierung verwenden</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Bereinigte Snapdirs</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSDs besitzen konvertierte Snapsets</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>L\xf6schvorg\xe4nge bei Wiederherstellungen</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Bei der Wiederherstellung anstelle des Peerings durchgef\xfchrte L\xf6schvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Hardlimit f\xfcr Platzierungsgruppen-Protokoll</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Legt ein Hardlimit f\xfcr die Platzierungsgruppen-Protokolll\xe4nge fest</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Aktualisierte OSD-Flags</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>aus</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>ein</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>ausgefallen</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Markieren</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD verloren</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>markierter Verlust</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Bereinigen</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>bereinigt</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>vernichten</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>vernichtet</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>Platzierungsgruppen</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Bytes f\xfcr Lesevorgang</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Bytes f\xfcr Schreibvorgang</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/> markieren\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{markAction}}"/> markieren\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Max. Abgleiche</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Wiederherstellung, max. aktiv</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Wiederherstellung, max. - einzelner Start</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Wiederherstellung - Inaktivit\xe4t</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Benutzerdefiniert</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Aktualisierte OSD-Wiederherstellungsgeschwindigkeits-Priorit\xe4t &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> wurde im folgenden OSD initialisiert: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Auftrag</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Schweregrad</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Gestartet</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Aktualisiert</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Verwendet</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Verf.</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Bereinigen</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>In Bearbeitung</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Warnung</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Unbekannt</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>aktiv</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>keine Dateisysteme</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>aktiv</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>Standby</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n. v.</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>aktiver Daemon</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>Quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Der NFS Ganesha-Dienst ist nicht konfiguriert.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transport</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS-Benutzer</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>CephFS-Dateisystem</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(aus globaler Konfiguration \xfcbernommen)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>aus globaler Konfiguration \xfcbernommen</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Durchzuf\xfchrende Benutzer-ID-Squashing-Art ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Keine Daemons verf\xfcgbar.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Cache-Modus</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Min. Alter f\xfcr Vertreibung</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Min. Alter f\xfcr Leerung</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Max. Bytes f\xfcr Ziel</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Max. Objekte f\xfcr Ziel</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Keine Anwendungen hinzugef\xfcgt</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Anwendungslimit erreicht</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Ein Pool kann nur bis zu vier Anwendungsdefinitionen aufweisen.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Zul\xe4ssige Zeichen \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>Maximale L\xe4nge betr\xe4gt 128 Zeichen</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Anwendungen filtern oder hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Anwendung hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>L\xf6schcode-Profil</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Gr\xf6\xdfe des Replikats</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Letzte \xc4nderung</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Profil mit L\xf6schcodierung</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Crush-Regelsatz</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Bytes f\xfcr Schreibvorgang</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>Bucket</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Aktualisierter Objektgateway-Bucket &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Erstellter Objektgateway-Bucket &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>Buckets</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>Benutzer</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Aktualisierter Objektgatewaybenutzer &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Erstellter Objektgatewaybenutzer &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>Benutzer</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Bereich</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Lesen</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Erstellen</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Erstellte Rolle \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Aktualisierte Rolle \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Systemrolle</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Gel\xf6schte Rolle \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Erstellter Benutzer &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Benutzer aktualisieren</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Fortfahren</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Sie wurden automatisch abgemeldet, da Ihre Rollen ge\xe4ndert wurden.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Aktualisierter Benutzer &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Gel\xf6schter Benutzer &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Fehler beim L\xf6schen des Benutzers &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Sie sind derzeit angemeldet als &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Jedes Objekt wird in Datenbl\xf6cke aufgeteilt und jeweils auf einem anderen OSD gespeichert.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Berechnen Sie Codierungsdatenbl\xf6cke f\xfcr jedes Objekt und speichern Sie sie auf unterschiedlichen OSDs.\n Die Anzahl der Codierungsdatenbl\xf6cke entspricht auch der Anzahl der OSDs, die ausfallen k\xf6nnen, ohne dass Daten verloren gehen.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Das jerasure-Modul ist das allgemeinste und flexibelste Modul\n und fungiert auch als der Standard f\xfcr Ceph-Pools mit L\xf6schcodierung.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>Die flexiblere Technik ist \'reed_sol_van :\', wobei es ausreicht, k\n und m festzulegen. Die Technik \'cauchy_good\' kann schneller sein. Sie m\xfcssen jedoch die Paketgr\xf6\xdfe sorgf\xe4ltig\n ausw\xe4hlen. S\xe4mtliche \'reed_sol_r6_op\'-, \'liberation\'-, \'blaum_roth\'- und \'liber8tion\'-Vorg\xe4nge sind dahingehend RAID6-Entsprechungen,\n dass sie nur mit \'m=2\' konfiguriert werden k\xf6nnen.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>Die Codierung wird jeweils f\xfcr Pakete auf Bytes-Gr\xf6\xdfe vorgenommen.\n Die Auswahl der richtigen Paketgr\xf6\xdfe ist schwierig.\n In der Jerasure-Dokumentation sind ausf\xfchrliche Informationen zu diesem Thema enthalten.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Bei Verwendung des Jerasure-Moduls, wenn ein Objekt mit L\xf6schcodierung auf mehreren OSDs gespeichert ist,\n m\xfcssen alle anderen OSDs gelesen werden, um die verloren gegangenen Daten eines OSDs wiederherzustellen.\n Wenn jerasure beispielsweise mit \'k=8\' und \'m=4\' konfiguriert ist,\n m\xfcssen bei Verlust eines OSDs zum Reparieren die elf anderen gelesen werden.\n\n Das lrc-L\xf6schcode-Modul erstellt lokale Parit\xe4tsdatenbl\xf6cke, um die Wiederherstellung mit weniger OSDs auszuf\xfchren.\n Wenn lrc beispielsweise mit \'k=8\', \'m=4\' und \'l=4\' konfiguriert ist, wird ein zus\xe4tzlicher Parit\xe4tsdatenblock f\xfcr jeweils vier OSDs erstellt.\n Geht ein einzelnes OSD verloren, kann es mit nur vier OSDs anstelle\n von elf wiederhergestellt werden.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Gruppieren Sie die Codierungs- und Datenbl\xf6cke in S\xe4tze entsprechend dem Speicherort.\n Beispielsweise werden f\xfcr \'k=4\' und \'m=2\', wenn der Speicherort \'3\' entspricht, zwei Dreiergruppen erstellt.\n Jeder Satz kann wiederhergestellt werden, ohne dass Datenbl\xf6cke aus einem anderen Satz gelesen werden.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>Der Typ des Crush-Buckets, in dem jeder durch l definierte Satz von Datenbl\xf6cken gespeichert wird.\n Wenn er beispielsweise auf \'rack\' festgelegt ist, wird jede Gruppe an l-Datenbl\xf6cken in einem anderen Rack platziert.\n Er wird zum Erstellen eines CRUSH-Regelschritts verwendet, beispielsweise f\xfcr einen Schritt zum Ausw\xe4hlen des Racks.\n Wenn er nicht festgelegt ist, wird keine solche Gruppierung vorgenommen.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Das isa-Modul kapselt die ISA-Bibliothek und wird nur auf Intel-Prozessoren ausgef\xfchrt.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>Das ISA-Modul wird in zwei Reed Solomon-Formularen bereitgestellt.\n Wenn \'reed_sol_van\' festgelegt ist, entspricht dies Vandermonde. Ist \'cauchy\' festgelegt, entspricht dies \'Cauchy\'.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>Das shec-Modul kapselt die SHEC-Mehrfachbibliothek.\n Dadurch kann ceph Daten effizienter wiederherstellen als Reed Solomon-Codes.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>Die Anzahl der Parit\xe4tsdatenbl\xf6cke, von denen jeder jeden Datenblock in seinem Berechnungsbereich enth\xe4lt.\n Die Anzahl wird als eine Dauerhaftigkeitssch\xe4tzung verwendet. Wenn beispielsweise \'c=2\' vorliegt,\n k\xf6nnen 2 OSDs ausfallen, ohne dass Daten verloren gehen.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>Der Name des f\xfcr den ersten Schritt der CRUSH-Regel verwendeten Crush-Buckets.\n Beispielsweise \'step take default\'.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Stellen Sie sicher, dass sich keine zwei Datenbl\xf6cke in einem Bucket mit derselben Ausfalldom\xe4ne befinden.\n Wenn die Ausfalldom\xe4ne beispielsweise als Host fungiert, werden keine zwei Datenbl\xf6cke auf demselben Host gespeichert.\n Er wird zum Erstellen eines CRUSH-Regelschritts verwendet, beispielsweise \'step chooseleaf host\'.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Schr\xe4nken Sie mithilfe der Klassennamen f\xfcr Crush-Ger\xe4te in der CRUSH-Zuordnung die Platzierung\n auf Ger\xe4te einer bestimmten Klasse (z. B. SSD oder HDD) ein.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Legen Sie den Verzeichnisnamen fest, \xfcber den das L\xf6schcode-Modul geladen wird.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>L\xe4sst alle Vorg\xe4nge zu</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>L\xe4sst nur Vorg\xe4nge zu, die den Server nicht \xe4ndern</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>L\xe4sst weder Lese- noch Schreibvorg\xe4nge zu, jedoch alle anderen Vorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>L\xe4sst Lese-/Schreibvorg\xe4nge und andere Vorg\xe4nge nicht zu, die Dateiattribute oder Verzeichnisinhalte \xe4ndern</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>L\xe4sst \xfcberhaupt keinen Zugriff zu</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Priorit\xe4t ausw\xe4hlen --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Niedrig</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Hoch</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>Letzte 5 Minuten</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>Letzte 15 Minuten</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>Letzte 30 Minuten</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>Letzte Stunde (Standard)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>Letzte 3 Stunden</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>Letzte 6 Stunden</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>Letzte 12 Stunden</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>Letzte 24 Stunden</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Gestern</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Heute</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Heute bisher</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Vorgestern</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Letzte 2 Tage</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Dieser Tag letzte Woche</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>Vorwoche</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Diese Woche</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Diese Woche bisher</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Letzte 7 Tage</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>Vormonat</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Dieser Monat</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Dieser Monat bisher</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Letzte 30 Tage</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Letzte 90 Tage</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Letzte 6 Monate</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>Letztes Jahr</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>Vorjahr</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Dieses Jahr</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Dieses Jahr bisher</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Letzte 2 Jahre</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Letzte 5 Jahre</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informationen</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Keine Elemente ausgew\xe4hlt.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Elementauswahl zum erneuten Ausw\xe4hlen aufheben</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Auswahllimit erreicht</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Tags filtern</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Badge hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Keine Elemente verf\xfcgbar.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Hinzuf\xfcgen</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Klonen</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Kopieren</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Umfassender Scrub</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Vernichten</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Vereinfachen</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Als ausgefallen markieren</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Mit Befehl \'In\' markieren</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Als verloren markieren</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Mit Befehl \'Out\' markieren</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Sch\xfctzen</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Umbenennen</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Wiederherstellen</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>In Papierkorb verschieben</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Schutz aufheben</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Gel\xf6scht</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Geklont</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Kopiert</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Ja</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>Nein</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Quality of Service</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS-Limit</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Das gew\xfcnschte Limit der E/A-Bytes pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS-Limit</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Das gew\xfcnschte Limit der E/A-Vorg\xe4nge pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>BPS-Limit f\xfcr Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Das gew\xfcnschte Limit der gelesenen Bytes pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>IOPS-Limit f\xfcr Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Das gew\xfcnschte Limit f\xfcr Lesevorg\xe4nge pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>BPS-Limit f\xfcr Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Das gew\xfcnschte Limit der geschriebenen Bytes pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>IOPS-Limit f\xfcr Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Das gew\xfcnschte Limit f\xfcr Schreibvorg\xe4nge pro Sekunde.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS-Block</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>Das gew\xfcnschte Blocklimit der E/A-Bytes.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS-Block</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>Das gew\xfcnschte Blocklimit der E/A-Vorg\xe4nge.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>BPS-Block f\xfcr Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>Das gew\xfcnschte Blocklimit der gelesenen Bytes.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>IOPS-Block f\xfcr Lesevorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>Das gew\xfcnschte Blocklimit der Lesevorg\xe4nge.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>BPS-Block f\xfcr Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>Das gew\xfcnschte Blocklimit der geschriebenen Bytes.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>IOPS-Block f\xfcr Schreibvorg\xe4nge</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>Das gew\xfcnschte Blocklimit der Schreibvorg\xe4nge.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Fehler bei \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Wird ausgef\xfchrt</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>ausf\xfchren</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Ausgef\xfchrt</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>Unbekannte Aufgabe</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Wird erstellt</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>erstellen</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Wird aktualisiert</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>aktualisieren</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Wird gel\xf6scht</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>l\xf6schen</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD-Snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Spiegelungsmodus f\xfcr Pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Peer f\xfcr Pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' spiegeln\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Name wird bereits von \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> verwendet.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Name wird bereits von \n <x id="INTERPOLATION" equiv-text="{{name}}"/> verwendet.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Name wird bereits von \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> verwendet.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> enth\xe4lt Snapshots.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Wird geklont</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>klonen</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>Snapshot von \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> muss gesch\xfctzt sein.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Wird kopiert</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>kopieren</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Wird vereinfacht</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>vereinfachen</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Vereinfacht</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Name wird bereits von \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> verwendet.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Der Schutz von \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> kann aufgrund enthaltener untergeordneter Images nicht aufgehoben werden.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Kann \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> nicht l\xf6schen, da es gesch\xfctzt ist.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Rollback wird ausgef\xfchrt</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>Rollback</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Rollback wurde ausgef\xfchrt</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Wird verschoben</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>verschieben</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>Verschoben</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>Image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' in Papierkorb verschieben\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Image konnte nicht gefunden werden.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Wird wiederhergestellt</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>wiederherstellen</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Wiederhergestellt</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>Image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' in \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\' verschieben\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Image-Name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' wird bereits verwendet.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>Wird bereinigt</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>bereinigen</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Bereinigt</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>alle Pools</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>Images von \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Spiegelung kann nicht deaktiviert werden, da sie einen Peer enth\xe4lt.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>Pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>L\xf6schcode-Profil \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>Ziel \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},ByF4:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("fo",{months:"januar_februar_mars_apr\xedl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_m\xe1nadagur_t\xfdsdagur_mikudagur_h\xf3sdagur_fr\xedggjadagur_leygardagur".split("_"),weekdaysShort:"sun_m\xe1n_t\xfds_mik_h\xf3s_fr\xed_ley".split("_"),weekdaysMin:"su_m\xe1_t\xfd_mi_h\xf3_fr_le".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D. MMMM, YYYY HH:mm"},calendar:{sameDay:"[\xcd dag kl.] LT",nextDay:"[\xcd morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[\xcd gj\xe1r kl.] LT",lastWeek:"[s\xed\xf0stu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s s\xed\xf0ani",s:"f\xe1 sekund",ss:"%d sekundir",m:"ein minuttur",mm:"%d minuttir",h:"ein t\xedmi",hh:"%d t\xedmar",d:"ein dagur",dd:"%d dagar",M:"ein m\xe1na\xf0ur",MM:"%d m\xe1na\xf0ir",y:"eitt \xe1r",yy:"%d \xe1r"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},C6Ij:function(t,e,n){"use strict";var a=n("CcnG"),r=n("TZo1"),i=n("9Kw/"),s=n("Jm/i"),o=n("Ip0R"),u=n("xbqr"),c=n("9GXa"),l=n("M/6F"),d=n("NDi4");n("AWcq"),n.d(e,"a",function(){return f}),n.d(e,"b",function(){return v});var f=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function p(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,[" for "])),(t()(),a["\u0275eld"](2,0,null,null,0,"span",[],[[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){t(e,2,0,e.component.statusFor)})}function h(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,6,"cd-info-panel",[],null,null,null,r.b,r.a)),a["\u0275did"](1,49152,null,0,i.a,[s.a],null,null),(t()(),a["\u0275eld"](2,0,null,0,4,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Retrieving data"])),(t()(),a["\u0275and"](16777216,null,null,1,null,p)),a["\u0275did"](5,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](-1,null,[". Please wait..."]))],function(t,e){t(e,5,0,e.component.statusFor)},null)}function g(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,[" for "])),(t()(),a["\u0275eld"](2,0,null,null,0,"span",[],[[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){t(e,2,0,e.component.statusFor)})}function b(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,6,"cd-warning-panel",[],null,null,null,u.b,u.a)),a["\u0275did"](1,49152,null,0,c.a,[],null,null),(t()(),a["\u0275eld"](2,0,null,0,4,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Displaying previously cached data"])),(t()(),a["\u0275and"](16777216,null,null,1,null,g)),a["\u0275did"](5,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](-1,null,["."]))],function(t,e){t(e,5,0,e.component.statusFor)},null)}function m(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,[" for "])),(t()(),a["\u0275eld"](2,0,null,null,0,"span",[],[[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){t(e,2,0,e.component.statusFor)})}function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,6,"cd-error-panel",[],null,null,null,l.b,l.a)),a["\u0275did"](1,49152,null,0,d.a,[],null,null),(t()(),a["\u0275eld"](2,0,null,0,4,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Could not load data"])),(t()(),a["\u0275and"](16777216,null,null,1,null,m)),a["\u0275did"](5,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](-1,null,[". Please check the cluster health."]))],function(t,e){t(e,5,0,e.component.statusFor)},null)}function v(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,h)),a["\u0275did"](1,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,b)),a["\u0275did"](3,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,y)),a["\u0275did"](5,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.status===n.vcs.ValueNone),t(e,3,0,n.status===n.vcs.ValueStale),t(e,5,0,n.status===n.vcs.ValueException)},null)}},CDJp:function(t,e,n){"use strict";var a=n("RDha");t.exports={_set:function(t,e){return a.merge(this[t]||(this[t]={}),e)}}},CS9Q:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("siIJ"),i=function(t){function e(n,a){void 0===a&&(a=r.a.now);var i=t.call(this,n,function(){return e.delegate&&e.delegate!==i?e.delegate.now():a()})||this;return i.actions=[],i.active=!1,i.scheduled=void 0,i}return a.__extends(e,t),e.prototype.schedule=function(n,a,r){return void 0===a&&(a=0),e.delegate&&e.delegate!==this?e.delegate.schedule(n,a,r):t.prototype.schedule.call(this,n,a,r)},e.prototype.flush=function(t){var e=this.actions;if(this.active)e.push(t);else{var n;this.active=!0;do{if(n=t.execute(t.state,t.delay))break}while(t=e.shift());if(this.active=!1,n){for(;t=e.shift();)t.unsubscribe();throw n}}},e}(r.a)},CVuo:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.camelCase=function(t){return(t=(t=(t=t.replace(/[^a-zA-Z0-9 ]/g," ")).replace(/([a-z](?=[A-Z]))/g,"$1 ")).replace(/([^a-zA-Z0-9 ])|^[0-9]+/g,"").trim().toLowerCase()).replace(/([ 0-9]+)([a-zA-Z])/g,function(t,e,n){return e.trim()+n.toUpperCase()})},e.deCamelCase=function(t){return t.replace(/([A-Z])/g,function(t){return" "+t}).replace(/^./,function(t){return t.toUpperCase()})}},Cc8h:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("DtyJ"),o=n("ahDk");n("czA5"),e.LongPressDirective=function(){function t(){this.pressEnabled=!0,this.duration=500,this.longPressStart=new i.EventEmitter,this.longPressing=new i.EventEmitter,this.longPressEnd=new i.EventEmitter,this.mouseX=0,this.mouseY=0}return Object.defineProperty(t.prototype,"press",{get:function(){return this.pressing},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isLongPress",{get:function(){return this.isLongPressing},enumerable:!0,configurable:!0}),t.prototype.onMouseDown=function(t){var e=this;if(1===t.which&&this.pressEnabled&&!t.target.classList.contains("resize-handle")){this.mouseX=t.clientX,this.mouseY=t.clientY,this.pressing=!0,this.isLongPressing=!1;var n=s.fromEvent(document,"mouseup");this.subscription=n.subscribe(function(t){return e.onMouseup()}),this.timeout=setTimeout(function(){e.isLongPressing=!0,e.longPressStart.emit({event:t,model:e.pressModel}),e.subscription.add(s.fromEvent(document,"mousemove").pipe(o.takeUntil(n)).subscribe(function(t){return e.onMouseMove(t)})),e.loop(t)},this.duration),this.loop(t)}},t.prototype.onMouseMove=function(t){if(this.pressing&&!this.isLongPressing){var e=Math.abs(t.clientX-this.mouseX)>10,n=Math.abs(t.clientY-this.mouseY)>10;(e||n)&&this.endPress()}},t.prototype.loop=function(t){var e=this;this.isLongPressing&&(this.timeout=setTimeout(function(){e.longPressing.emit({event:t,model:e.pressModel}),e.loop(t)},50))},t.prototype.endPress=function(){clearTimeout(this.timeout),this.isLongPressing=!1,this.pressing=!1,this._destroySubscription(),this.longPressEnd.emit({model:this.pressModel})},t.prototype.onMouseup=function(){this.endPress()},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Boolean)],t.prototype,"pressEnabled",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"pressModel",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"duration",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressStart",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressing",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressEnd",void 0),a([i.HostBinding("class.press"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"press",null),a([i.HostBinding("class.longpress"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isLongPress",null),a([i.HostListener("mousedown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMouseDown",null),a([i.Directive({selector:"[long-press]"})],t)}()},CcnG:function(t,e,n){"use strict";n.r(e),n.d(e,"\u0275angular_packages_core_core_t",function(){return Xh}),n.d(e,"\u0275angular_packages_core_core_q",function(){return Kh}),n.d(e,"\u0275angular_packages_core_core_r",function(){return $h}),n.d(e,"\u0275angular_packages_core_core_s",function(){return Zh}),n.d(e,"\u0275angular_packages_core_core_h",function(){return Zf}),n.d(e,"\u0275angular_packages_core_core_o",function(){return kh}),n.d(e,"\u0275angular_packages_core_core_p",function(){return Ph}),n.d(e,"\u0275angular_packages_core_core_n",function(){return gh}),n.d(e,"\u0275angular_packages_core_core_m",function(){return hh}),n.d(e,"\u0275angular_packages_core_core_c",function(){return po}),n.d(e,"\u0275angular_packages_core_core_d",function(){return Ae}),n.d(e,"\u0275angular_packages_core_core_e",function(){return Hf}),n.d(e,"\u0275angular_packages_core_core_f",function(){return Df}),n.d(e,"\u0275angular_packages_core_core_g",function(){return jf}),n.d(e,"\u0275angular_packages_core_core_l",function(){return rd}),n.d(e,"\u0275angular_packages_core_core_u",function(){return Sp}),n.d(e,"\u0275angular_packages_core_core_w",function(){return _p}),n.d(e,"\u0275angular_packages_core_core_v",function(){return vp}),n.d(e,"\u0275angular_packages_core_core_z",function(){return wp}),n.d(e,"\u0275angular_packages_core_core_x",function(){return xp}),n.d(e,"\u0275angular_packages_core_core_y",function(){return Tp}),n.d(e,"\u0275angular_packages_core_core_bc",function(){return kn}),n.d(e,"\u0275angular_packages_core_core_bj",function(){return p}),n.d(e,"\u0275angular_packages_core_core_bd",function(){return Xe}),n.d(e,"\u0275angular_packages_core_core_be",function(){return Qe}),n.d(e,"\u0275angular_packages_core_core_bf",function(){return mn}),n.d(e,"\u0275angular_packages_core_core_bi",function(){return rr}),n.d(e,"\u0275angular_packages_core_core_bm",function(){return Xt}),n.d(e,"\u0275angular_packages_core_core_i",function(){return du}),n.d(e,"\u0275angular_packages_core_core_j",function(){return fu}),n.d(e,"\u0275angular_packages_core_core_k",function(){return pu}),n.d(e,"\u0275angular_packages_core_core_a",function(){return N}),n.d(e,"\u0275angular_packages_core_core_b",function(){return R}),n.d(e,"\u0275angular_packages_core_core_bk",function(){return c}),n.d(e,"\u0275angular_packages_core_core_ba",function(){return Ub}),n.d(e,"\u0275angular_packages_core_core_bb",function(){return ug}),n.d(e,"createPlatform",function(){return Bp}),n.d(e,"assertPlatform",function(){return Wp}),n.d(e,"destroyPlatform",function(){return Kp}),n.d(e,"getPlatform",function(){return $p}),n.d(e,"PlatformRef",function(){return Zp}),n.d(e,"ApplicationRef",function(){return Jp}),n.d(e,"createPlatformFactory",function(){return Up}),n.d(e,"NgProbeToken",function(){return Hp}),n.d(e,"enableProdMode",function(){return zu}),n.d(e,"isDevMode",function(){return Fu}),n.d(e,"APP_ID",function(){return $f}),n.d(e,"PACKAGE_ROOT_URL",function(){return np}),n.d(e,"PLATFORM_INITIALIZER",function(){return Qf}),n.d(e,"PLATFORM_ID",function(){return tp}),n.d(e,"APP_BOOTSTRAP_LISTENER",function(){return ep}),n.d(e,"APP_INITIALIZER",function(){return Wf}),n.d(e,"ApplicationInitStatus",function(){return Kf}),n.d(e,"DebugElement",function(){return Ch}),n.d(e,"DebugNode",function(){return Ih}),n.d(e,"asNativeElements",function(){return bh}),n.d(e,"getDebugNode",function(){return Sh}),n.d(e,"Testability",function(){return qp}),n.d(e,"TestabilityRegistry",function(){return jp}),n.d(e,"setTestabilityGetter",function(){return Fp}),n.d(e,"TRANSLATIONS",function(){return Bh}),n.d(e,"TRANSLATIONS_FORMAT",function(){return Uh}),n.d(e,"LOCALE_ID",function(){return Hh}),n.d(e,"MissingTranslationStrategy",function(){return Wh}),n.d(e,"ApplicationModule",function(){return Jh}),n.d(e,"wtfCreateScope",function(){return Ip}),n.d(e,"wtfLeave",function(){return Cp}),n.d(e,"wtfStartTimeRange",function(){return kp}),n.d(e,"wtfEndTimeRange",function(){return Np}),n.d(e,"Type",function(){return ud}),n.d(e,"EventEmitter",function(){return hl}),n.d(e,"ErrorHandler",function(){return Sf}),n.d(e,"Sanitizer",function(){return Cu}),n.d(e,"SecurityContext",function(){return Iu}),n.d(e,"ANALYZE_FOR_ENTRY_COMPONENTS",function(){return A}),n.d(e,"Attribute",function(){return D}),n.d(e,"ContentChild",function(){return P}),n.d(e,"ContentChildren",function(){return L}),n.d(e,"Query",function(){return E}),n.d(e,"ViewChild",function(){return q}),n.d(e,"ViewChildren",function(){return M}),n.d(e,"Component",function(){return Yd}),n.d(e,"Directive",function(){return Gd}),n.d(e,"HostBinding",function(){return Wd}),n.d(e,"HostListener",function(){return Kd}),n.d(e,"Input",function(){return Bd}),n.d(e,"Output",function(){return Ud}),n.d(e,"Pipe",function(){return Vd}),n.d(e,"CUSTOM_ELEMENTS_SCHEMA",function(){return rf}),n.d(e,"NO_ERRORS_SCHEMA",function(){return sf}),n.d(e,"NgModule",function(){return of}),n.d(e,"ViewEncapsulation",function(){return at}),n.d(e,"Version",function(){return ku}),n.d(e,"VERSION",function(){return Nu}),n.d(e,"defineInjectable",function(){return v}),n.d(e,"defineInjector",function(){return _}),n.d(e,"forwardRef",function(){return X}),n.d(e,"resolveForwardRef",function(){return J}),n.d(e,"Injectable",function(){return gf}),n.d(e,"INJECTOR",function(){return fo}),n.d(e,"Injector",function(){return ho}),n.d(e,"inject",function(){return De}),n.d(e,"\u0275inject",function(){return De}),n.d(e,"InjectFlags",function(){return Ce}),n.d(e,"ReflectiveInjector",function(){return Vf}),n.d(e,"createInjector",function(){return Po}),n.d(e,"ResolvedReflectiveFactory",function(){return Pf}),n.d(e,"ReflectiveKey",function(){return Nf}),n.d(e,"InjectionToken",function(){return w}),n.d(e,"Inject",function(){return Te}),n.d(e,"Optional",function(){return we}),n.d(e,"Self",function(){return Se}),n.d(e,"SkipSelf",function(){return Oe}),n.d(e,"Host",function(){return Ie}),n.d(e,"NgZone",function(){return Rp}),n.d(e,"\u0275NoopNgZone",function(){return Mp}),n.d(e,"RenderComponentType",function(){return mu}),n.d(e,"Renderer",function(){return vu}),n.d(e,"Renderer2",function(){return wu}),n.d(e,"RendererFactory2",function(){return xu}),n.d(e,"RendererStyleFlags2",function(){return Tu}),n.d(e,"RootRenderer",function(){return _u}),n.d(e,"COMPILER_OPTIONS",function(){return mp}),n.d(e,"Compiler",function(){return bp}),n.d(e,"CompilerFactory",function(){return yp}),n.d(e,"ModuleWithComponentFactories",function(){return rp}),n.d(e,"ComponentFactory",function(){return Xo}),n.d(e,"\u0275ComponentFactory",function(){return Xo}),n.d(e,"ComponentRef",function(){return Zo}),n.d(e,"ComponentFactoryResolver",function(){return ru}),n.d(e,"ElementRef",function(){return hu}),n.d(e,"NgModuleFactory",function(){return uu}),n.d(e,"NgModuleRef",function(){return ou}),n.d(e,"NgModuleFactoryLoader",function(){return td}),n.d(e,"getModuleFactory",function(){return sd}),n.d(e,"QueryList",function(){return th}),n.d(e,"SystemJsNgModuleLoader",function(){return ah}),n.d(e,"SystemJsNgModuleLoaderConfig",function(){return eh}),n.d(e,"TemplateRef",function(){return gl}),n.d(e,"ViewContainerRef",function(){return ih}),n.d(e,"EmbeddedViewRef",function(){return fh}),n.d(e,"ViewRef",function(){return dh}),n.d(e,"ChangeDetectionStrategy",function(){return j}),n.d(e,"ChangeDetectorRef",function(){return uh}),n.d(e,"DefaultIterableDiffer",function(){return Rh}),n.d(e,"IterableDiffers",function(){return jh}),n.d(e,"KeyValueDiffers",function(){return Fh}),n.d(e,"SimpleChange",function(){return la}),n.d(e,"WrappedValue",function(){return ca}),n.d(e,"platformCore",function(){return Vh}),n.d(e,"\u0275ALLOW_MULTIPLE_PLATFORMS",function(){return Vp}),n.d(e,"\u0275APP_ID_RANDOM_PROVIDER",function(){return Xf}),n.d(e,"\u0275defaultIterableDiffers",function(){return Gh}),n.d(e,"\u0275defaultKeyValueDiffers",function(){return Yh}),n.d(e,"\u0275devModeEqual",function(){return ua}),n.d(e,"\u0275isListLikeIterable",function(){return da}),n.d(e,"\u0275ChangeDetectorStatus",function(){return F}),n.d(e,"\u0275isDefaultChangeDetectionStrategy",function(){return z}),n.d(e,"\u0275Console",function(){return ap}),n.d(e,"\u0275getInjectableDef",function(){return x}),n.d(e,"\u0275setCurrentInjector",function(){return Ne}),n.d(e,"\u0275APP_ROOT",function(){return No}),n.d(e,"\u0275ivyEnabled",function(){return tg}),n.d(e,"\u0275CodegenComponentFactoryResolver",function(){return iu}),n.d(e,"\u0275resolveComponentResources",function(){return Q}),n.d(e,"\u0275ReflectionCapabilities",function(){return pd}),n.d(e,"\u0275RenderDebugInfo",function(){return yu}),n.d(e,"\u0275_sanitizeHtml",function(){return oc}),n.d(e,"\u0275_sanitizeStyle",function(){return Bl}),n.d(e,"\u0275_sanitizeUrl",function(){return Hu}),n.d(e,"\u0275global",function(){return V}),n.d(e,"\u0275looseIdentical",function(){return K}),n.d(e,"\u0275stringify",function(){return $}),n.d(e,"\u0275makeDecorator",function(){return C}),n.d(e,"\u0275isObservable",function(){return Uf}),n.d(e,"\u0275isPromise",function(){return Bf}),n.d(e,"\u0275clearOverrides",function(){return ky}),n.d(e,"\u0275initServicesIfNeeded",function(){return Vm}),n.d(e,"\u0275overrideComponentView",function(){return Cy}),n.d(e,"\u0275overrideProvider",function(){return Iy}),n.d(e,"\u0275NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR",function(){return Qb}),n.d(e,"\u0275defineBase",function(){return ft}),n.d(e,"\u0275defineComponent",function(){return ot}),n.d(e,"\u0275defineDirective",function(){return pt}),n.d(e,"\u0275definePipe",function(){return ht}),n.d(e,"\u0275defineNgModule",function(){return lt}),n.d(e,"\u0275detectChanges",function(){return gs}),n.d(e,"\u0275renderComponent",function(){return $s}),n.d(e,"\u0275Render3ComponentFactory",function(){return Pu}),n.d(e,"\u0275Render3ComponentRef",function(){return Mu}),n.d(e,"\u0275directiveInject",function(){return Ps}),n.d(e,"\u0275injectAttribute",function(){return Ms}),n.d(e,"\u0275getFactoryOf",function(){return qn}),n.d(e,"\u0275getInheritedFactory",function(){return jn}),n.d(e,"\u0275templateRefExtractor",function(){return Ll}),n.d(e,"\u0275ProvidersFeature",function(){return $o}),n.d(e,"\u0275InheritDefinitionFeature",function(){return no}),n.d(e,"\u0275NgOnChangesFeature",function(){return io}),n.d(e,"\u0275LifecycleHooksFeature",function(){return Qs}),n.d(e,"\u0275Render3NgModuleRef",function(){return Wc}),n.d(e,"\u0275markDirty",function(){return vs}),n.d(e,"\u0275NgModuleFactory",function(){return Kc}),n.d(e,"\u0275NO_CHANGE",function(){return ha}),n.d(e,"\u0275container",function(){return ns}),n.d(e,"\u0275nextContext",function(){return di}),n.d(e,"\u0275elementStart",function(){return xi}),n.d(e,"\u0275namespaceHTML",function(){return mi}),n.d(e,"\u0275namespaceMathML",function(){return bi}),n.d(e,"\u0275namespaceSVG",function(){return gi}),n.d(e,"\u0275element",function(){return yi}),n.d(e,"\u0275listener",function(){return ki}),n.d(e,"\u0275text",function(){return Hi}),n.d(e,"\u0275embeddedViewStart",function(){return ss}),n.d(e,"\u0275query",function(){return Dl}),n.d(e,"\u0275registerContentQuery",function(){return qs}),n.d(e,"\u0275projection",function(){return ls}),n.d(e,"\u0275bind",function(){return _s}),n.d(e,"\u0275interpolation1",function(){return ws}),n.d(e,"\u0275interpolation2",function(){return Ss}),n.d(e,"\u0275interpolation3",function(){return Os}),n.d(e,"\u0275interpolation4",function(){return Is}),n.d(e,"\u0275interpolation5",function(){return Cs}),n.d(e,"\u0275interpolation6",function(){return ks}),n.d(e,"\u0275interpolation7",function(){return Ns}),n.d(e,"\u0275interpolation8",function(){return Rs}),n.d(e,"\u0275interpolationV",function(){return Ts}),n.d(e,"\u0275pipeBind1",function(){return ol}),n.d(e,"\u0275pipeBind2",function(){return ul}),n.d(e,"\u0275pipeBind3",function(){return cl}),n.d(e,"\u0275pipeBind4",function(){return ll}),n.d(e,"\u0275pipeBindV",function(){return dl}),n.d(e,"\u0275pureFunction0",function(){return Zc}),n.d(e,"\u0275pureFunction1",function(){return Xc}),n.d(e,"\u0275pureFunction2",function(){return Jc}),n.d(e,"\u0275pureFunction3",function(){return Qc}),n.d(e,"\u0275pureFunction4",function(){return tl}),n.d(e,"\u0275pureFunction5",function(){return el}),n.d(e,"\u0275pureFunction6",function(){return nl}),n.d(e,"\u0275pureFunction7",function(){return al}),n.d(e,"\u0275pureFunction8",function(){return rl}),n.d(e,"\u0275pureFunctionV",function(){return il}),n.d(e,"\u0275getCurrentView",function(){return zs}),n.d(e,"\u0275getHostElement",function(){return ea}),n.d(e,"\u0275restoreView",function(){return Je}),n.d(e,"\u0275containerRefreshStart",function(){return rs}),n.d(e,"\u0275containerRefreshEnd",function(){return is}),n.d(e,"\u0275queryRefresh",function(){return El}),n.d(e,"\u0275loadQueryList",function(){return Es}),n.d(e,"\u0275elementEnd",function(){return Ni}),n.d(e,"\u0275elementProperty",function(){return Ai}),n.d(e,"\u0275componentHostSyntheticProperty",function(){return Di}),n.d(e,"\u0275projectionDef",function(){return us}),n.d(e,"\u0275reference",function(){return Ds}),n.d(e,"\u0275enableBindings",function(){return $e}),n.d(e,"\u0275disableBindings",function(){return Ze}),n.d(e,"\u0275allocHostVars",function(){return xs}),n.d(e,"\u0275elementAttribute",function(){return Ri}),n.d(e,"\u0275elementContainerStart",function(){return vi}),n.d(e,"\u0275elementContainerEnd",function(){return _i}),n.d(e,"\u0275elementStyling",function(){return ji}),n.d(e,"\u0275elementHostAttrs",function(){return Fi}),n.d(e,"\u0275elementStylingMap",function(){return Vi}),n.d(e,"\u0275elementStyleProp",function(){return Gi}),n.d(e,"\u0275elementStylingApply",function(){return zi}),n.d(e,"\u0275elementClassProp",function(){return Yi}),n.d(e,"\u0275textBinding",function(){return Bi}),n.d(e,"\u0275template",function(){return es}),n.d(e,"\u0275embeddedViewEnd",function(){return os}),n.d(e,"\u0275store",function(){return As}),n.d(e,"\u0275load",function(){return Ls}),n.d(e,"\u0275pipe",function(){return sl}),n.d(e,"\u0275whenRendered",function(){return to}),n.d(e,"\u0275i18n",function(){return Pc}),n.d(e,"\u0275i18nAttributes",function(){return Mc}),n.d(e,"\u0275i18nExp",function(){return Fc}),n.d(e,"\u0275i18nStart",function(){return Nc}),n.d(e,"\u0275i18nEnd",function(){return Dc}),n.d(e,"\u0275i18nApply",function(){return zc}),n.d(e,"\u0275i18nPostprocess",function(){return Ac}),n.d(e,"\u0275setClassMetadata",function(){return $c}),n.d(e,"\u0275compileComponent",function(){return Ed}),n.d(e,"\u0275compileDirective",function(){return Ld}),n.d(e,"\u0275compileNgModule",function(){return Sd}),n.d(e,"\u0275compileNgModuleDefs",function(){return Od}),n.d(e,"\u0275patchComponentDefWithScope",function(){return kd}),n.d(e,"\u0275resetCompiledComponents",function(){return Id}),n.d(e,"\u0275compilePipe",function(){return zd}),n.d(e,"\u0275sanitizeHtml",function(){return Ul}),n.d(e,"\u0275sanitizeStyle",function(){return Wl}),n.d(e,"\u0275defaultStyleSanitizer",function(){return Xl}),n.d(e,"\u0275sanitizeScript",function(){return Zl}),n.d(e,"\u0275sanitizeUrl",function(){return Kl}),n.d(e,"\u0275sanitizeResourceUrl",function(){return $l}),n.d(e,"\u0275bypassSanitizationTrustHtml",function(){return ql}),n.d(e,"\u0275bypassSanitizationTrustStyle",function(){return jl}),n.d(e,"\u0275bypassSanitizationTrustScript",function(){return Fl}),n.d(e,"\u0275bypassSanitizationTrustUrl",function(){return zl}),n.d(e,"\u0275bypassSanitizationTrustResourceUrl",function(){return Gl}),n.d(e,"\u0275getLContext",function(){return Fn}),n.d(e,"\u0275bindPlayerFactory",function(){return ar}),n.d(e,"\u0275addPlayer",function(){return Vs}),n.d(e,"\u0275getPlayers",function(){return Hs}),n.d(e,"\u0275compileNgModuleFactory__POST_R3__",function(){return Yp}),n.d(e,"\u0275SWITCH_COMPILE_COMPONENT__POST_R3__",function(){return $d}),n.d(e,"\u0275SWITCH_COMPILE_DIRECTIVE__POST_R3__",function(){return Zd}),n.d(e,"\u0275SWITCH_COMPILE_PIPE__POST_R3__",function(){return Xd}),n.d(e,"\u0275SWITCH_COMPILE_NGMODULE__POST_R3__",function(){return uf}),n.d(e,"\u0275getDebugNode__POST_R3__",function(){return wh}),n.d(e,"\u0275SWITCH_COMPILE_INJECTABLE__POST_R3__",function(){return bf}),n.d(e,"\u0275SWITCH_IVY_ENABLED__POST_R3__",function(){return Qh}),n.d(e,"\u0275SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__",function(){return ch}),n.d(e,"\u0275Compiler_compileModuleSync__POST_R3__",function(){return up}),n.d(e,"\u0275Compiler_compileModuleAsync__POST_R3__",function(){return lp}),n.d(e,"\u0275Compiler_compileModuleAndAllComponentsSync__POST_R3__",function(){return fp}),n.d(e,"\u0275Compiler_compileModuleAndAllComponentsAsync__POST_R3__",function(){return hp}),n.d(e,"\u0275SWITCH_ELEMENT_REF_FACTORY__POST_R3__",function(){return gu}),n.d(e,"\u0275SWITCH_TEMPLATE_REF_FACTORY__POST_R3__",function(){return bl}),n.d(e,"\u0275SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__",function(){return sh}),n.d(e,"\u0275SWITCH_RENDERER2_FACTORY__POST_R3__",function(){return Su}),n.d(e,"\u0275getModuleFactory__POST_R3__",function(){return id}),n.d(e,"\u0275publishGlobalUtil",function(){return Ks}),n.d(e,"\u0275publishDefaultGlobalUtils",function(){return Ws}),n.d(e,"\u0275SWITCH_INJECTOR_FACTORY__POST_R3__",function(){return go}),n.d(e,"\u0275registerModuleFactory",function(){return nd}),n.d(e,"\u0275EMPTY_ARRAY",function(){return Zg}),n.d(e,"\u0275EMPTY_MAP",function(){return Xg}),n.d(e,"\u0275and",function(){return Jg}),n.d(e,"\u0275ccf",function(){return yb}),n.d(e,"\u0275cmf",function(){return Ny}),n.d(e,"\u0275crt",function(){return vg}),n.d(e,"\u0275did",function(){return Vb}),n.d(e,"\u0275eld",function(){return Qg}),n.d(e,"\u0275elementEventFullName",function(){return Rg}),n.d(e,"\u0275getComponentViewDefinitionFactory",function(){return vb}),n.d(e,"\u0275inlineInterpolate",function(){return Kg}),n.d(e,"\u0275interpolate",function(){return Wg}),n.d(e,"\u0275mod",function(){return cb}),n.d(e,"\u0275mpd",function(){return ub}),n.d(e,"\u0275ncd",function(){return dm}),n.d(e,"\u0275nov",function(){return Rb}),n.d(e,"\u0275pid",function(){return Hb}),n.d(e,"\u0275prd",function(){return Bb}),n.d(e,"\u0275pad",function(){return hm}),n.d(e,"\u0275pod",function(){return gm}),n.d(e,"\u0275ppd",function(){return pm}),n.d(e,"\u0275qud",function(){return sm}),n.d(e,"\u0275ted",function(){return mm}),n.d(e,"\u0275unv",function(){return bg}),n.d(e,"\u0275vid",function(){return _m});var a=n("mrSG"),r=n("pugT"),i=n("K9Ia"),s=n("6blF"),o=n("p0ib"),u=n("S1nX");function c(t){for(var e in t)if(t[e]===c)return e;throw Error("Could not find renamed property on target object.")}function l(t,e){for(var n in e)e.hasOwnProperty(n)&&!t.hasOwnProperty(n)&&(t[n]=e[n])}var d=c({ngComponentDef:c}),f=c({ngDirectiveDef:c}),p=c({ngInjectableDef:c}),h=c({ngInjectorDef:c}),g=c({ngPipeDef:c}),b=c({ngModuleDef:c}),m=c({ngBaseDef:c}),y=c({__NG_ELEMENT_ID__:c});function v(t){return{providedIn:t.providedIn||null,factory:t.factory,value:void 0}}function _(t){return{factory:t.factory,providers:t.providers||[],imports:t.imports||[]}}function x(t){return t&&t.hasOwnProperty(p)?t[p]:null}function T(t){return t&&t.hasOwnProperty(h)?t[h]:null}var w=function(){function t(t,e){this._desc=t,this.ngMetadataName="InjectionToken",this.ngInjectableDef=void 0!==e?v({providedIn:e.providedIn||"root",factory:e.factory}):void 0}return t.prototype.toString=function(){return"InjectionToken "+this._desc},t}(),S="__annotations__",O="__parameters__",I="__prop__metadata__";function C(t,e,n,r,i){var s=k(e);function o(){for(var t,e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];if(this instanceof o)return s.call.apply(s,Object(a.__spread)([this],e)),this;var u=new((t=o).bind.apply(t,Object(a.__spread)([void 0],e)));return function(t){return i&&i.apply(void 0,Object(a.__spread)([t],e)),(t.hasOwnProperty(S)?t[S]:Object.defineProperty(t,S,{value:[]})[S]).push(u),r&&r(t),t}}return n&&(o.prototype=Object.create(n.prototype)),o.prototype.ngMetadataName=t,o.annotationCls=o,o}function k(t){return function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];if(t){var r=t.apply(void 0,Object(a.__spread)(e));for(var i in r)this[i]=r[i]}}}function N(t,e,n){var r=k(e);function i(){for(var t,e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];if(this instanceof i)return r.apply(this,e),this;var s=new((t=i).bind.apply(t,Object(a.__spread)([void 0],e)));return o.annotation=s,o;function o(t,e,n){for(var a=t.hasOwnProperty(O)?t[O]:Object.defineProperty(t,O,{value:[]})[O];a.length<=n;)a.push(null);return(a[n]=a[n]||[]).push(s),t}}return n&&(i.prototype=Object.create(n.prototype)),i.prototype.ngMetadataName=t,i.annotationCls=i,i}function R(t,e,n,r){var i=k(e);function s(){for(var t,e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];if(this instanceof s)return i.apply(this,e),this;var o=new((t=s).bind.apply(t,Object(a.__spread)([void 0],e)));return function(t,n){var i=t.constructor,s=i.hasOwnProperty(I)?i[I]:Object.defineProperty(i,I,{value:{}})[I];s[n]=s.hasOwnProperty(n)&&s[n]||[],s[n].unshift(o),r&&r.apply(void 0,Object(a.__spread)([t,n],e))}}return n&&(s.prototype=Object.create(n.prototype)),s.prototype.ngMetadataName=t,s.annotationCls=s,s}var A=new w("AnalyzeForEntryComponents"),D=N("Attribute",function(t){return{attributeName:t}}),E=function(){return function(){}}(),L=R("ContentChildren",function(t,e){return void 0===e&&(e={}),Object(a.__assign)({selector:t,first:!1,isViewQuery:!1,descendants:!1},e)},E),P=R("ContentChild",function(t,e){return void 0===e&&(e={}),Object(a.__assign)({selector:t,first:!0,isViewQuery:!1,descendants:!0},e)},E),M=R("ViewChildren",function(t,e){return void 0===e&&(e={}),Object(a.__assign)({selector:t,first:!1,isViewQuery:!0,descendants:!0},e)},E),q=R("ViewChild",function(t,e){return Object(a.__assign)({selector:t,first:!0,isViewQuery:!0,descendants:!0},e)},E),j=function(t){return t[t.OnPush=0]="OnPush",t[t.Default=1]="Default",t}({}),F=function(t){return t[t.CheckOnce=0]="CheckOnce",t[t.Checked=1]="Checked",t[t.CheckAlways=2]="CheckAlways",t[t.Detached=3]="Detached",t[t.Errored=4]="Errored",t[t.Destroyed=5]="Destroyed",t}({});function z(t){return null==t||t===j.Default}var G="undefined"!=typeof window&&window,Y="undefined"!=typeof self&&"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&self,V="undefined"!=typeof global&&global||G||Y,H=Promise.resolve(0),B=null;function U(){if(!B){var t=V.Symbol;if(t&&t.iterator)B=t.iterator;else for(var e=Object.getOwnPropertyNames(Map.prototype),n=0;n<e.length;++n){var a=e[n];"entries"!==a&&"size"!==a&&Map.prototype[a]===Map.prototype.entries&&(B=a)}}return B}function W(t){"undefined"==typeof Zone?H.then(function(){t&&t.apply(null,null)}):Zone.current.scheduleMicroTask("scheduleMicrotask",t)}function K(t,e){return t===e||"number"==typeof t&&"number"==typeof e&&isNaN(t)&&isNaN(e)}function $(t){if("string"==typeof t)return t;if(t instanceof Array)return"["+t.map($).join(", ")+"]";if(null==t)return""+t;if(t.overriddenName)return""+t.overriddenName;if(t.name)return""+t.name;var e=t.toString();if(null==e)return""+e;var n=e.indexOf("\n");return-1===n?e:e.substring(0,n)}var Z=c({__forward_ref__:c});function X(t){return t.__forward_ref__=X,t.toString=function(){return $(this())},t}function J(t){var e=t;return"function"==typeof e&&e.hasOwnProperty(Z)&&e.__forward_ref__===X?e():t}function Q(t){var e=[],n=new Map;function a(a){var r=n.get(a);if(!r){var i=t(a);n.set(a,r=i.then(nt)),e.push(r)}return r}return tt.forEach(function(t){t.templateUrl&&a(t.templateUrl).then(function(e){t.template=e,t.templateUrl=void 0});var e=t.styleUrls,n=t.styles||(t.styles=[]),r=t.styles.length;e&&e.forEach(function(i,s){n.push(""),a(i).then(function(a){n[r+s]=a,e.splice(e.indexOf(i),1),0==e.length&&(t.styleUrls=void 0)})})}),tt.clear(),Promise.all(e).then(function(){return null})}var tt=new Set;function et(t){return t.templateUrl||t.styleUrls&&t.styleUrls.length}function nt(t){return"string"==typeof t?t:t.text()}var at=function(t){return t[t.Emulated=0]="Emulated",t[t.Native=1]="Native",t[t.None=2]="None",t[t.ShadowDom=3]="ShadowDom",t}({}),rt={},it=[],st=0;function ot(t){var e=t.type,n=e.prototype,a={},r={type:e,providersResolver:null,consts:t.consts,vars:t.vars,factory:t.factory,template:t.template||null,hostBindings:t.hostBindings||null,contentQueries:t.contentQueries||null,contentQueriesRefresh:t.contentQueriesRefresh||null,attributes:t.attributes||null,declaredInputs:a,inputs:null,outputs:null,exportAs:t.exportAs||null,onInit:n.ngOnInit||null,doCheck:n.ngDoCheck||null,afterContentInit:n.ngAfterContentInit||null,afterContentChecked:n.ngAfterContentChecked||null,afterViewInit:n.ngAfterViewInit||null,afterViewChecked:n.ngAfterViewChecked||null,onDestroy:n.ngOnDestroy||null,onPush:t.changeDetection===j.OnPush,directiveDefs:null,pipeDefs:null,selectors:t.selectors,viewQuery:t.viewQuery||null,features:t.features||null,data:t.data||{},encapsulation:t.encapsulation||at.Emulated,id:"c",styles:t.styles||it,_:null};return r._=""+{toString:function(){var e=t.directives,n=t.features,i=t.pipes;r.id+=st++,r.inputs=dt(t.inputs,a),r.outputs=dt(t.outputs),n&&n.forEach(function(t){return t(r)}),r.directiveDefs=e?function(){return("function"==typeof e?e():e).map(ut)}:null,r.pipeDefs=i?function(){return("function"==typeof i?i():i).map(ct)}:null}},r}function ut(t){return gt(t)||bt(t)}function ct(t){return mt(t)}function lt(t){return{type:t.type,bootstrap:t.bootstrap||it,declarations:t.declarations||it,imports:t.imports||it,exports:t.exports||it,transitiveCompileScopes:null}}function dt(t,e){if(null==t)return rt;var n={};for(var a in t)if(t.hasOwnProperty(a)){var r=t[a],i=r;Array.isArray(r)&&(i=r[1],r=r[0]),n[r]=a,e&&(e[r]=i)}return n}function ft(t){var e={};return{inputs:dt(t.inputs,e),declaredInputs:e,outputs:dt(t.outputs)}}var pt=ot;function ht(t){return{name:t.name,factory:t.factory,pure:!1!==t.pure,onDestroy:t.type.prototype.ngOnDestroy||null}}function gt(t){return t[d]||null}function bt(t){return t[f]||null}function mt(t){return t[g]||null}function yt(t,e){var n=t[b]||null;if(!n&&!0===e)throw new Error("Type "+$(t)+" does not have 'ngModuleDef' property.");return n}var vt=0,_t=1,xt=2,Tt=3,wt=4,St=5,Ot=6,It=7,Ct=8,kt=9,Nt=10,Rt=11,At=12,Dt=13,Et=14,Lt=15,Pt=16,Mt=17,qt=18,jt=0,Ft=1,zt=6,Gt=7,Yt=8,Vt="__ngContext__",Ht=8,Bt=8,Ut=9,Wt=-1,Kt=function(){return function(t,e,n){this.factory=t,this.resolving=!1,this.canSeeViewProviders=e,this.injectImpl=n}}(),$t=Kt.prototype;function Zt(t){return"function"==typeof t?t.name||t:"string"==typeof t?t:null==t?"":"object"==typeof t&&"function"==typeof t.type?t.type.name||t.type:""+t}function Xt(t,e){return t[e+qt]}function Jt(t){for(;Array.isArray(t);)t=t[St];return t}function Qt(t,e){return Jt(e[t+qt])}function te(t,e){return Jt(e[t.index])}function ee(t,e){return e[vt].data[t+qt]}function ne(t,e){var n=e[t];return n.length>=qt?n:n[St]}function ae(t){return 0!=(4&t.flags)}function re(t){return 1==(1&t.flags)}function ie(t){return null!==t.template}function se(t){return Array.isArray(t)&&t.length===Yt}function oe(t){return 0!=(128&t[_t])}function ue(t){for(var e=Array.isArray(t)?t:de(t);e&&!(128&e[_t]);)e=e[xt];return e}function ce(t){return ue(t)[kt]}function le(t){return t[Vt]}function de(t){var e=le(t);return e?Array.isArray(e)?e:e.lView:null}function fe(t){return t!==Wt}function pe(t){return 32767&t}function he(t){return t>>16}function ge(t,e){for(var n=he(t),a=e;n>0;)a=a[Mt],n--;return a}var be=("undefined"!=typeof requestAnimationFrame&&requestAnimationFrame||setTimeout).bind(V);function me(t,e){for(var n=0;n<t.length;n++)e.push(t[n])}function ye(t){for(var e=t[Ot];e&&2===e.type;)e=(t=t[Mt])[Ot];return t}function ve(){var t=V.ng;if(!t||!t.\u0275compilerFacade)throw new Error("Angular JIT compilation failed: '@angular/compiler' not loaded!\n - JIT compilation is discouraged for production use-cases! Consider AOT mode instead.\n - Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?\n - Alternatively provide the compiler with 'import \"@angular/compiler\";' before bootstrapping.");return t.\u0275compilerFacade}var _e,xe,Te=N("Inject",function(t){return{token:t}}),we=N("Optional"),Se=N("Self"),Oe=N("SkipSelf"),Ie=N("Host"),Ce=function(t){return t[t.Default=0]="Default",t[t.Host=1]="Host",t[t.Self=2]="Self",t[t.SkipSelf=4]="SkipSelf",t[t.Optional=8]="Optional",t}({}),ke=void 0;function Ne(t){var e=ke;return ke=t,e}function Re(t){var e=_e;return _e=t,e}function Ae(t,e){if(void 0===e&&(e=Ce.Default),void 0===ke)throw new Error("inject() must be called from an injection context");return null===ke?Ee(t,void 0,e):ke.get(t,e&Ce.Optional?null:void 0,e)}function De(t,e){return void 0===e&&(e=Ce.Default),(_e||Ae)(t,e)}function Ee(t,e,n){var a=x(t);if(a&&"root"==a.providedIn)return void 0===a.value?a.value=a.factory():a.value;if(n&Ce.Optional)return null;if(void 0!==e)return e;throw new Error("Injector: NOT_FOUND ["+$(t)+"]")}function Le(t){for(var e=[],n=0;n<t.length;n++){var a=t[n];if(Array.isArray(a)){if(0===a.length)throw new Error("Arguments array must have arguments.");for(var r=void 0,i=Ce.Default,s=0;s<a.length;s++){var o=a[s];o instanceof we||"Optional"===o.ngMetadataName?i|=Ce.Optional:o instanceof Oe||"SkipSelf"===o.ngMetadataName?i|=Ce.SkipSelf:o instanceof Se||"Self"===o.ngMetadataName?i|=Ce.Self:r=o instanceof Te?o.token:o}e.push(De(r,i))}else e.push(De(a))}return e}function Pe(t,e,n,a){e&&(a.initHooks||(a.initHooks=[])).push(t,e),n&&((a.initHooks||(a.initHooks=[])).push(t,n),(a.checkHooks||(a.checkHooks=[])).push(t,n))}function Me(t,e){if(t.firstTemplatePass)for(var n=e.directiveStart,a=e.directiveEnd;n<a;n++){var r=t.data[n];qe(r,t,n),je(r,t,n),Fe(r,t,n)}}function qe(t,e,n){t.afterContentInit&&(e.contentHooks||(e.contentHooks=[])).push(n,t.afterContentInit),t.afterContentChecked&&((e.contentHooks||(e.contentHooks=[])).push(n,t.afterContentChecked),(e.contentCheckHooks||(e.contentCheckHooks=[])).push(n,t.afterContentChecked))}function je(t,e,n){t.afterViewInit&&(e.viewHooks||(e.viewHooks=[])).push(n,t.afterViewInit),t.afterViewChecked&&((e.viewHooks||(e.viewHooks=[])).push(n,t.afterViewChecked),(e.viewCheckHooks||(e.viewCheckHooks=[])).push(n,t.afterViewChecked))}function Fe(t,e,n){null!=t.onDestroy&&(e.destroyHooks||(e.destroyHooks=[])).push(n,t.onDestroy)}function ze(t,e,n){!n&&32&t[_t]&&(Ge(t,e.initHooks,e.checkHooks,n),t[_t]&=-33)}function Ge(t,e,n,a){if(!a){var r=2&t[_t]?e:n;r&&Ye(t,r)}}function Ye(t,e){for(var n=0;n<e.length;n+=2)e[n+1].call(t[e[n]])}var Ve,He,Be,Ue,We=null;function Ke(t){We=t}function $e(){Ve=!0}function Ze(){Ve=!1}function Xe(){return Ue}function Je(t){sn=t}function Qe(){return He}function tn(t){He=t}function en(t,e){He=t,Ue=e}function nn(){return Be}function an(t){Be=t}function rn(t){return void 0===t&&(t=Ue),1==(1&t[_t])}var sn=null,on=!1;function un(){return on}function cn(t){on=t}var ln=!0;function dn(){return ln}function fn(t){ln=t}var pn=-1;function hn(){return pn}function gn(t){pn=t}function bn(t,e){var n=Ue;if(t){var a=t[vt];ln=a.firstTemplatePass,pn=a.bindingStartIndex}return He=e,Be=!0,Ue=sn=t,n}function mn(t){return void 0===t&&(t=1),(sn=function(t,e){for(;t>0;)e=e[Mt],t--;return e}(t,sn))[kt]}function yn(t){var e=Ue[vt];rn(Ue)?Ue[_t]&=-2:(Ge(Ue,e.viewHooks,e.viewCheckHooks,on),Ue[_t]&=-11,Ue[_t]|=32,Ue[It]=e.bindingStartIndex),bn(t,null)}var vn=!0;function _n(t){var e=vn;return vn=t,e}var xn=255,Tn=0;function wn(t,e){var n=On(t,e);if(-1!==n)return n;var a=e[vt];a.firstTemplatePass&&(t.injectorIndex=e.length,Sn(a.data,t),Sn(e,null),Sn(a.blueprint,null));var r=In(t,e),i=pe(r),s=ge(r,e),o=t.injectorIndex;if(fe(r))for(var u=s[vt].data,c=0;c<8;c++)e[o+c]=s[i+c]|u[i+c];return e[o+Bt]=r,o}function Sn(t,e){t.push(0,0,0,0,0,0,0,0,e)}function On(t,e){return-1===t.injectorIndex||t.parent&&t.parent.injectorIndex===t.injectorIndex||null==e[t.injectorIndex+Bt]?-1:t.injectorIndex}function In(t,e){if(t.parent&&-1!==t.parent.injectorIndex)return t.parent.injectorIndex;for(var n=e[Ot],a=1;n&&-1===n.injectorIndex;)n=(e=e[Mt])?e[Ot]:null,a++;return n?n.injectorIndex|a<<16:-1}function Cn(t,e,n){!function(t,e,n){var a="string"!=typeof n?n[y]:n.charCodeAt(0)||0;null==a&&(a=n[y]=Tn++);var r=a&xn,i=1<<r,s=64&r,o=32&r,u=e.data;128&r?s?o?u[t+7]|=i:u[t+6]|=i:o?u[t+5]|=i:u[t+4]|=i:s?o?u[t+3]|=i:u[t+2]|=i:o?u[t+1]|=i:u[t]|=i}(t,e[vt],n)}function kn(t,e){var n=t.attrs;if(n)for(var a=0;a<n.length;a+=2){var r=n[a];if(3===r)break;if(r==e)return n[a+1]}return null}function Nn(t,e,n,a,r){if(void 0===a&&(a=Ce.Default),t){var i=function(t){if("string"==typeof t)return t.charCodeAt(0)||0;var e=t[y];return"number"==typeof e?e&xn:e}(n);if("function"==typeof i){var s=Qe(),o=Xe();en(t,e);try{var u=i();if(null!=u||a&Ce.Optional)return u;throw new Error("No provider for "+Zt(n)+"!")}finally{en(s,o)}}else if("number"==typeof i){var c=null,l=On(t,e),d=Wt,f=a&Ce.Host?ye(e)[Ot]:null;for((-1===l||a&Ce.SkipSelf)&&(d=-1===l?In(t,e):e[l+Bt],Pn(a,!1)?(c=e[vt],l=pe(d),e=ge(d,e)):l=-1);-1!==l;){d=e[l+Bt];var p=e[vt];if(Ln(i,l,p.data)){var h=An(l,e,n,c,a,f);if(h!==Rn)return h}Pn(a,e[vt].data[l+Ht]===f)&&Ln(i,l,e)?(c=p,l=pe(d),e=ge(d,e)):l=-1}}}if(a&Ce.Optional&&void 0===r&&(r=null),0==(a&(Ce.Self|Ce.Host))){var g=e[Nt];return g?g.get(n,r,a&Ce.Optional):Ee(n,r,a&Ce.Optional)}if(a&Ce.Optional)return r;throw new Error("NodeInjector: NOT_FOUND ["+Zt(n)+"]")}var Rn={};function An(t,e,n,a,r,i){var s=e[vt],o=s.data[t+Ht],u=Dn(o,e,n,null==a?re(o)&&vn:a!=s&&3===o.type,r&Ce.Host&&i===o);return null!==u?En(s.data,e,u,o):Rn}function Dn(t,e,n,a,r){for(var i=t.providerIndexes,s=e[vt].data,o=65535&i,u=t.directiveStart,c=i>>16,l=r?o+c:t.directiveEnd,d=a?o:o+c;d<l;d++){var f=s[d];if(d<u&&n===f||d>=u&&f.type===n)return d}if(r){var p=s[u];if(p&&ie(p)&&p.type===n)return u}return null}function En(t,e,n,a){var r,i=e[n];if(null!=(r=i)&&"object"==typeof r&&Object.getPrototypeOf(r)==$t){var s=i;if(s.resolving)throw new Error("Circular dep for "+Zt(t[n]));var o=_n(s.canSeeViewProviders);s.resolving=!0;var u=void 0;s.injectImpl&&(u=Re(s.injectImpl));var c=Qe(),l=Xe();en(a,e);try{i=e[n]=s.factory(null,t,e,a)}finally{s.injectImpl&&Re(u),_n(o),s.resolving=!1,en(c,l)}}return i}function Ln(t,e,n){var a=64&t,r=32&t;return!!((128&t?a?r?n[e+7]:n[e+6]:r?n[e+5]:n[e+4]:a?r?n[e+3]:n[e+2]:r?n[e+1]:n[e])&1<<t)}function Pn(t,e){return!(t&Ce.Self||t&Ce.Host&&e)}var Mn=function(){function t(t,e){this._tNode=t,this._lView=e}return t.prototype.get=function(t,e){return Nn(this._tNode,this._lView,t,void 0,e)},t}();function qn(t){var e=t,n=gt(e)||bt(e)||mt(e)||x(e)||T(e);return n&&void 0!==n.factory?n.factory:null}function jn(t){var e=qn(Object.getPrototypeOf(t.prototype).constructor);return null!==e?e:function(t){return new t}}function Fn(t){var e,n=le(t);if(n){if(Array.isArray(n)){var a=n,r=void 0,i=void 0,s=void 0;if((e=t)&&e.constructor&&e.constructor.ngComponentDef){if(-1==(r=Bn(a,t)))throw new Error("The provided component was not found in the application");i=t}else if(t&&t.constructor&&t.constructor.ngDirectiveDef){if(-1==(r=function(t,e){for(var n=t[vt].firstChild;n;){for(var a=n.directiveEnd,r=n.directiveStart;r<a;r++)if(t[r]===e)return n.index;n=Hn(n)}return-1}(a,t)))throw new Error("The provided directive was not found in the application");s=Un(r,a,!1)}else if(-1==(r=Vn(a,t)))return null;var o=le(h=Jt(a[r])),u=o&&!Array.isArray(o)?o:zn(a,r,h);if(i&&void 0===u.component&&(u.component=i,Yn(u.component,u)),s&&void 0===u.directives){u.directives=s;for(var c=0;c<s.length;c++)Yn(s[c],u)}Yn(u.native,u),n=u}}else for(var l=t,d=l;d=d.parentNode;){var f=le(d);if(f){if(a=void 0,!(a=Array.isArray(f)?f:f.lView))return null;var p=Vn(a,l);if(p>=0){var h;Yn(h=Jt(a[p]),u=zn(a,p,h)),n=u;break}}}return n||null}function zn(t,e,n){return{lView:t,nodeIndex:e,native:n,component:void 0,directives:void 0,localRefs:void 0}}function Gn(t){var e,n=le(t);if(Array.isArray(n)){var a=Bn(n,t);(r=zn(n,a,(e=ne(a,n))[St])).component=t,Yn(t,r),Yn(r.native,r)}else{var r;e=ne((r=n).nodeIndex,r.lView)}return e}function Yn(t,e){t[Vt]=e}function Vn(t,e){for(var n=t[vt].firstChild;n;){if(te(n,t)===e)return n.index;n=Hn(n)}return-1}function Hn(t){if(t.child)return t.child;if(t.next)return t.next;for(;t.parent&&!t.parent.next;)t=t.parent;return t.parent&&t.parent.next}function Bn(t,e){var n=t[vt].components;if(n)for(var a=0;a<n.length;a++){var r=n[a];if(ne(r,t)[kt]===e)return r}else if(ne(qt,t)[kt]===e)return qt;return-1}function Un(t,e,n){var a=e[vt].data[t],r=a.directiveStart;return 0==r?it:(!n&&1&a.flags&&r++,e.slice(r,a.directiveEnd))}function Wn(t){var e,n,a=na(t);return void 0===a.component&&(a.component=1&(n=(e=a.lView)[vt].data[a.nodeIndex]).flags?e[n.directiveStart]:null),a.component}function Kn(t){return na(t).lView[kt]}function $n(t){for(var e=ta(t).lView;e[xt]&&null===e[St];)e=e[xt];return 128&e[_t]?null:e[kt]}function Zn(t){return function(t){var e;for(e=Array.isArray(t)?t:de(t);e&&!(128&e[_t]);)e=e[xt];return e}(Array.isArray(t)?t:ta(t).lView)[kt]}function Xn(t){return Object(a.__spread)(Zn(t).components)}function Jn(t){var e=ta(t);return new Mn(e.lView[vt].data[e.nodeIndex],e.lView)}function Qn(t){var e=ta(t);return void 0===e.directives&&(e.directives=Un(e.nodeIndex,e.lView,!1)),e.directives||[]}function ta(t,e){void 0===e&&(e=!0);var n=Fn(t);if(!n&&e)throw new Error("Invalid ng target");return n}function ea(t){return Fn(t).native}function na(t){if(!(t instanceof Node))throw new Error("Expecting instance of DOM Node");return ta(t)}function aa(t){return"boolean"==typeof t.useCapture}function ra(t){var e=na(t).lView,n=e[Ct],a=e[vt].cleanup,r=[];if(a&&n)for(var i=0;i<a.length;){var s=a[i++],o=a[i++];if("string"==typeof s){var u=s,c=Jt(e[o]),l=n[a[i++]],d=a[i++];t==c&&r.push({element:t,name:u,callback:l,useCapture:"boolean"==typeof d?d:!(d>=0)&&null})}}return r.sort(ia),r}function ia(t,e){return t.name==e.name?0:t.name<e.name?-1:1}var sa=/([A-Z])/g;function oa(t){try{return null!=t?t.toString().slice(0,30):t}catch(e){return"[ERROR] Exception while trying to serialize the value"}}function ua(t,e){var n=da(t),a=da(e);return n&&a?function(t,e,n){for(var a=t[U()](),r=e[U()]();;){var i=a.next(),s=r.next();if(i.done&&s.done)return!0;if(i.done||s.done)return!1;if(!n(i.value,s.value))return!1}}(t,e,ua):!(n||!t||"object"!=typeof t&&"function"!=typeof t||a||!e||"object"!=typeof e&&"function"!=typeof e)||K(t,e)}var ca=function(){function t(t){this.wrapped=t}return t.wrap=function(e){return new t(e)},t.unwrap=function(e){return t.isWrapped(e)?e.wrapped:e},t.isWrapped=function(e){return e instanceof t},t}(),la=function(){function t(t,e,n){this.previousValue=t,this.currentValue=e,this.firstChange=n}return t.prototype.isFirstChange=function(){return this.firstChange},t}();function da(t){return!!fa(t)&&(Array.isArray(t)||!(t instanceof Map)&&U()in t)}function fa(t){return null!==t&&("function"==typeof t||"object"==typeof t)}function pa(t){throw new Error("Multiple components match node with tagname "+t.tagName)}var ha={};function ga(t,e,n){return t[e]=n}function ba(t,e){return t[e]}function ma(t,e,n){if(t[e]===ha)t[e]=n;else{if(r=n,(a=t[e])!=a&&r!=r||a===r)return!1;t[e]=n}var a,r;return!0}function ya(t,e,n,a){var r=ma(t,e,n);return ma(t,e+1,a)||r}function va(t,e,n,a,r){var i=ya(t,e,n,a);return ma(t,e+2,r)||i}function _a(t,e,n,a,r,i){var s=ya(t,e,n,a);return ya(t,e+2,r,i)||s}var xa="ngProjectAs",Ta=function(t){return t[t.Important=1]="Important",t[t.DashCase=2]="DashCase",t}({});function wa(t){return!!t.listen}var Sa={createRenderer:function(t,e){return document}};function Oa(t,e){return null==t.parent?function(t){var e=t[Ot];return e&&2!==e.type?te(e,t[xt]):null}(e):te(Ia(t),e)}function Ia(t){for(var e=t.parent;e&&5===e.type;)e=e.parent;return e}function Ca(t,e){if(-1===t.index){var n=e[Lt];return n>-1?e[xt][n]:null}return e[xt][t.parent.index]}function ka(t,e){var n=Ca(t,e);return n?n[Gt]:null}var Na=[];function Ra(t,e,n,a,r){for(var i=t[vt].node,s=-1,o=t,u=i.child;u;){var c=null;if(3===u.type){Aa(e,n,a,te(u,o),r);var l=o[u.index];se(l)&&Aa(e,n,a,l[zt],r)}else if(0===u.type){var d=o[u.index];Aa(e,n,a,d[zt],r),a&&(d[Gt]=a),d[Ft].length&&(c=(o=d[Ft][0])[vt].node,r=d[zt])}else if(1===u.type){var f=ye(o),p=f[Ot].projection[u.projection];Na[++s]=u,Na[++s]=o,p&&(c=(o=f[xt])[vt].data[p.index])}else c=u.child;if(null===c)for(null===u.next&&2&u.flags&&(o=Na[s--],u=Na[s--]),c=u.next;!c;){if(null===(u=u.parent||o[vt].node)||u===i)return null;0===u.type&&(r=(o=o[xt])[u.index][zt]),c=2===u.type&&o[Tt]?(o=o[Tt])[vt].node:u.next}u=c}}function Aa(t,e,n,a,r){0===t?wa(e)?e.insertBefore(n,a,r):n.insertBefore(a,r,!0):1===t?wa(e)?e.removeChild(n,a):n.removeChild(a):2===t&&e.destroyNode(a)}function Da(t,e){return wa(e)?e.createText(Zt(t)):e.createTextNode(Zt(t))}function Ea(t,e,n){var a=ka(t[vt].node,t);a&&Ra(t,e?0:1,t[At],a,n)}function La(t,e,n,a,r){var i=e[Ft];a>0&&(i[a-1][Tt]=t),a<i.length?(t[Tt]=i[a],i.splice(a,0,t)):(i.push(t),t[Tt]=null),r>-1&&(t[Lt]=r,t[xt]=n),t[wt]&&t[wt].insertView(a),t[_t]|=16}function Pa(t,e,n){var a=t[Ft],r=a[e];return e>0&&(a[e-1][Tt]=r[Tt]),a.splice(e,1),n||Ea(r,!1),r[wt]&&r[wt].removeView(),r[Lt]=-1,r[xt]=null,r[_t]&=-17,r}function Ma(t,e,n){var a=t[Ft][n];Pa(t,n,!!e.detached),ja(a)}function qa(t){var e=t[vt].childIndex;return-1===e?null:t[e]}function ja(t){var e=t[At];wa(e)&&e.destroyNode&&Ra(t,2,e,null),function(t){if(-1===t[vt].childIndex)return za(t);for(var e=qa(t);e;){var n=null;if(e.length>=qt?e[vt].childIndex>-1&&(n=qa(e)):e[Ft].length&&(n=e[Ft][0]),null==n){for(;e&&!e[Tt]&&e!==t;)za(e),e=Fa(e,t);za(e||t),n=e&&e[Tt]}e=n}}(t),t[_t]|=64}function Fa(t,e){var n;return t.length>=qt&&(n=t[Ot])&&2===n.type?Ca(n,t):t[xt]===e?null:t[xt]}function za(t){if(t.length>=qt){var e=t;!function(t){var e,n=t[vt];null!=n&&null!=(e=n.destroyHooks)&&Ye(t,e)}(e),(r=(a=e)[vt]&&a[vt].pipeDestroyHooks)&&Ye(a,r),function(t){var e=t[vt].cleanup;if(null!=e){for(var n=t[Ct],a=0;a<e.length-1;a+=2)if("string"==typeof e[a]){var r=n[e[a+2]],i=Jt(t[e[a+1]]),s=e[a+3];"boolean"==typeof s?i.removeEventListener(e[a],r,s):s>=0?n[s]():n[-s].unsubscribe(),a+=2}else"number"==typeof e[a]?(0,n[e[a]])():e[a].call(n[e[a+1]]);t[Ct]=null}}(e);var n=e[Ot];n&&3===n.type&&wa(e[At])&&e[At].destroy()}var a,r}function Ga(t,e){if(Ya(t,e)){if(oe(e))return Ha(e[At],te(t,e));var n=e[Ot],a=t.parent;return null!=a&&4===a.type&&(t=Ua(a)),null==t.parent&&2===n.type?ka(n,e):Oa(t,e)}return null}function Ya(t,e){var n,a=t,r=t.parent;return t.parent&&(4===t.parent.type?r=(a=Ua(t)).parent:5===t.parent.type&&(r=(a=Ia(a)).parent)),null===r&&(r=e[Ot]),r&&2===r.type?null!=(n=Ca(r,e))&&null!=n[Gt]:null==a.parent||!(3!==a.parent.type||1&a.parent.flags)}function Va(t,e,n,a){wa(t)?t.insertBefore(e,n,a):e.insertBefore(n,a,!0)}function Ha(t,e){return wa(t)?t.parentNode(e):e.parentNode}function Ba(t,e,n){if(void 0===t&&(t=null),null!==t&&Ya(e,n)){var a=n[At],r=Oa(e,n),i=e.parent||n[Ot];if(2===i.type){var s=Ca(i,n),o=s[Ft],u=o.indexOf(n);Va(a,s[Gt],t,Wa(u,o,s[zt]))}else 4===i.type?Va(a,Ga(e,n),t,r):5===i.type?Va(a,r,t,te(e.parent,n)):wa(a)?a.appendChild(r,t):r.appendChild(t);return!0}return!1}function Ua(t){for(;null!=t.parent&&4===t.parent.type;)t=t.parent;return t}function Wa(t,e,n){if(t+1<e.length){var a=e[t+1],r=a[Ot];return r.child?te(r.child,a):n}return n}function Ka(t,e,n){if(null!==e&&Ya(t,n)){var a=Oa(t,n),r=n[At];return wa(r)?r.removeChild(a,e):a.removeChild(e),!0}return!1}function $a(t,e,n,a){var r=te(t,a);Ba(r,e,n),Yn(r,a);var i=Ga(e,n),s=a[t.index];if(0===t.type){s[Gt]=i;for(var o=s[Ft],u=0;u<o.length;u++)Ea(o[u],!0,s[zt])}else{if(4===t.type)for(var c=t.child;c;)$a(c,e,n,a),c=c.next;se(s)&&(s[Gt]=i,Ba(s[zt],e,n))}}var Za="ng-template";function Xa(t,e,n){return e===t.tagName&&(n||3===t.type||4===t.type||0===t.type&&e===Za)}function Ja(t,e,n){for(var a,r,i,s,o,u=4,c=t.attrs,l=c?c.indexOf(3):-1,d=!1,f=0;f<e.length;f++){var p=e[f];if("number"!=typeof p){if(!d)if(4&u){if(u=2|1&u,""!==p&&!Xa(t,p,n)||""===p&&1===e.length){if(Qa(u))return!1;d=!0}}else{var h=tr(8&u?"class":p,c);if(-1===h){if(Qa(u))return!1;d=!0;continue}var g,b=8&u?p:e[++f];if(""!==b)if(g=l>-1&&h>l?"":c[h+1],8&u&&(i=(a=g).length,o=(s=a.indexOf(r=b))+r.length,-1===s||s>0&&" "!==a[s-1]||o<i&&" "!==a[o])||2&u&&b!==g){if(Qa(u))return!1;d=!0}}}else{if(!d&&!Qa(u)&&!Qa(p))return!1;if(d&&Qa(p))continue;d=!1,u=p|1&u}}return Qa(u)||d}function Qa(t){return 0==(1&t)}function tr(t,e){if(null===e)return-1;for(var n=!1,a=0;a<e.length;){var r=e[a];if(r===t)return a;0===r?a+=4:(3===r&&(n=!0),a+=n?1:2)}return-1}function er(t,e,n){void 0===n&&(n=!1);for(var a=0;a<e.length;a++)if(Ja(t,e[a],n))return!0;return!1}function nr(t,e,n){for(var a=function(t){var e=t.attrs;if(null!=e){var n=e.indexOf(xa);if(0==(1&n))return e[n+1]}return null}(t),r=0;r<e.length;r++)if(a===n[r]||null===a&&er(t,e[r],!0))return r+1;return 0}function ar(t,e){return new rr(t,e)}var rr=function(){return function(t,e){this.fn=t,this.value=e}}(),ir=function(){function t(){this._players=[]}return t.prototype.flushPlayers=function(){for(var t=0;t<this._players.length;t++){var e=this._players[t];e.parent||0!==e.state||e.play()}this._players.length=0},t.prototype.queuePlayer=function(t){this._players.push(t)},t}(),sr="@";function or(t,e,n,a){return[0,[null,-1,!1,e||null],n||[null],a||[null],[0,0],t||null,null,null,null]}function ur(t,e){for(var n=t,a=e[n],r=e;Array.isArray(a);)r=a,a=a[St];if(o=r,Array.isArray(o)&&"number"==typeof o[0]&&Array.isArray(o[2]))return r;var i,s,o,u=ee(t-qt,e).stylingTemplate;return r!==e&&(n=St),r[n]=u?(i=a,(s=u.slice())[5]=i,s[0]|=32,s):or(a)}function cr(t){return t[0]===sr}function lr(t,e,n,a,r,i){return i=i||n,r?t[r]=a:t.push(a),!!a&&(a.addEventListener(200,function(){var e=t.indexOf(a);e&&(e<t[0]?t[e]=null:t.splice(e,1)),a.destroy()}),(e.playerHandler||(e.playerHandler=new ir)).queuePlayer(a,i),!0)}function dr(t){return t[8]}function fr(t){return t[8]=[5,null,null,null,null]}function pr(t){return!!(8&t.flags)}function hr(t){for(var e=or(),n=e[3]=[null],a=e[2]=[null],r=-1,i=0;i<t.length;i++){var s=t[i];if("number"==typeof s)r=s;else if(2===r)a.push(s,t[++i]);else if(1===r)n.push(s,!0);else if(3===r)break}return e}function gr(t,e,n){for(var a=1;a<t.length;){if(t[a]===e){var r=t[a+1];return void(null!=r&&0!=r||(t[a+1]=n))}a+=2}t.push(e,n)}function br(t,e,n,a){for(var r=1;r<n.length;r+=2){var i=n[r+1];i&&(a?_r(t,n[r+0],!0,e,null):vr(t,n[r+0],i,e,null))}}function mr(t,e,n,a){for(var r=n;r<a;r+=4)if(zr(t,r)===e)return r;return-1}function yr(t,e,n,a,r){var i=Jr(t,r||null),s=function(t,e,n,a){var r=t[1][4*e+1],i=t[4];return i[r+2+(a?i[r+0]:0)+n]}(t,i,e,a),o=Fr(t,s),u=jr(t,s),c=Xr(t,s),l=n instanceof rr?n.value:n;if($r(u,o,l)&&(!o||(l?i<=c:c===i))){var d=2==(2&u),f=n instanceof rr?new Zr(n,t[5],d?1:2):null,p=f?n.value:n,h=Pr(t,s),g=!1,b=f?h:0;if(Dr(t,f,h)){var m=Er(t,f,h);b=f?m:0,g=!0}if((g||c!==i)&&Lr(t,s,b,i),c!==i){var y=zr(t,s),v=ei(t,i);!function(t,e,n){v&&v(y)?t[e]|=4:t[e]&=-5}(t,s)}Ar(t,s,p);var _=kr(u),x=Fr(t,_);if(!x||$r(u,x,p)){var T=!1,w=!0;!Wr(p,d)&&Wr(x,d)&&(T=!0,w=!1),xr(t,_,T),xr(t,s,w),ni(t,i,!0),Yr(t,!0)}g&&Vr(t,!0)}}function vr(t,e,n,a,r,i,s){n=r&&n?r(e,n):n,i||s?(i&&i.setValue(e,n),s&&s.setValue(e,n)):n?(n=n.toString(),wa(a)?a.setStyle(t,e,n,Ta.DashCase):t.style.setProperty(e,n)):wa(a)?a.removeStyle(t,e,Ta.DashCase):t.style.removeProperty(e)}function _r(t,e,n,a,r,i){r||i?(r&&r.setValue(e,n),i&&i.setValue(e,n)):n?wa(a)?a.addClass(t,e):t.classList.add(e):wa(a)?a.removeClass(t,e):t.classList.remove(e)}function xr(t,e,n){var a=e>=9?e+0:e;n?t[a]|=1:t[a]&=-2}function Tr(t,e){return 1==(1&t[e>=9?e+0:e])}function wr(t,e){return 2==(2&t[e>=9?e+0:e])}function Sr(t,e){return 4==(4&t[e>=9?e+0:e])}function Or(t,e,n){return 63&t|e<<6|n<<20}function Ir(t,e){var n=Cr(e);return(2&e?t[3]:t[2])[n]}function Cr(t){return t>>6&16383}function kr(t){var e=t>>20&16383;return e>=9?e:-1}function Nr(t){return kr(t[0])}function Rr(t,e,n){t[e+1]=n}function Ar(t,e,n){t[e+2]=n}function Dr(t,e,n){var a=t[8];if(e){if(!a||0===n)return!0}else if(!a)return!1;return a[n]!==e}function Er(t,e,n){var a=t[8]||fr(t);return n>0?a[n]=e:(a.splice(n=a[0],0,e,null),a[0]+=2),n}function Lr(t,e,n,a){var r=function(t,e){return n<<16|t}(a);t[e+3]=r}function Pr(t,e){return t[e+3]>>16&65535}function Mr(t,e){var n=Pr(t,e);if(n){var a=t[8];if(a)return a[n]}return null}function qr(t,e,n){t[0===e?e:e+0]=n}function jr(t,e){return t[0===e?e:e+0]}function Fr(t,e){return t[e+2]}function zr(t,e){return t[e+1]}function Gr(t){return 16&t[0]}function Yr(t,e){xr(t,0,e)}function Vr(t,e){e?t[0]|=8:t[0]&=-9}function Hr(t,e,n){for(var a=(n||0)+1;a<t.length;a+=4)if(t[a]==e)return a-1;return-1}function Br(t,e,n){var a=Fr(t,e),r=zr(t,e),i=jr(t,e),s=Pr(t,e),o=i,u=jr(t,n),c=kr(o);c>=0&&qr(t,c,Or(l=jr(t,c),Cr(l),n));var l,d=kr(u);d>=0&&qr(t,d,Or(l=jr(t,d),Cr(l),e)),Ar(t,e,Fr(t,n)),Rr(t,e,zr(t,n)),qr(t,e,jr(t,n)),Lr(t,e,Pr(t,n),0),Ar(t,n,a),Rr(t,n,r),qr(t,n,i),Lr(t,n,s,0)}function Ur(t,e,n,a,r,i,s,o){var u=e<t.length;t.splice(e,0,1|r|(n?2:0),a,i,0),Lr(t,e,o,s),u&&function(t,n){for(var a=e+4;a<t.length;a+=4){var r=kr(jr(t,a));if(r>0){var i=Cr(jr(t,r));qr(t,r,Or((Tr(t,r)?1:0)|(wr(t,r)?2:0)|(Sr(t,r)?4:0),i,a))}}}(t)}function Wr(t,e){return e?!!t:null!==t}function Kr(t,e,n,a){var r,i=a&&a(e)?4:0;return n?(i|=2,r=ti(t[3],e)):r=ti(t[2],e),Or(i,r=r>0?r+1:0,0)}function $r(t,e,n){return!(2&t)&&e&&n&&4&t?e.toString()!==n.toString():e!==n}var Zr=function(){function t(t,e,n){this._element=e,this._type=n,this._values={},this._dirty=!1,this._factory=t}return t.prototype.setValue=function(t,e){this._values[t]!==e&&(this._values[t]=e,this._dirty=!0)},t.prototype.buildPlayer=function(t,e){if(this._dirty){var n=this._factory.fn(this._element,this._type,this._values,e,t||null);return this._values={},this._dirty=!1,n}},t}();function Xr(t,e){return 65535&t[e+3]}function Jr(t,e){var n=Qr(t[1],e);return n>0?n/4:0}function Qr(t,e){for(var n=0;n<t.length;n+=4)if(t[n]===e)return n;return-1}function ti(t,e){for(var n=1;n<t.length;n+=2)if(t[n]===e)return n;return-1}function ei(t,e){var n=t[1];return n[4*e+3]||n[3]||null}function ni(t,e,n){t[1][4*e+2]=n}function ai(t){var e=t[6];if(null==e){e="";for(var n=t[3],a=1;a<n.length;a+=2)n[a+1]&&(e+=(e.length?" ":"")+n[a]);t[6]=e}return e}var ri=Promise.resolve(null);function ii(t){var e=t[vt];if(e.firstTemplatePass=!1,fn(!1),!rn(t)){var n=un();ze(t,e,n),function(t){for(var e=qa(t);null!==e;e=e[Tt])if(e.length<qt&&-1===e[jt])for(var n=e,a=0;a<n[Ft].length;a++){var r=n[Ft][a];li(r,r[vt],r[kt])}}(t),function(t){if(null!=t.contentQueries)for(var e=0;e<t.contentQueries.length;e+=2){var n=t.contentQueries[e];t.data[n].contentQueriesRefresh(n-qt,t.contentQueries[e+1])}}(e),Ge(t,e.contentHooks,e.contentCheckHooks,n),function(t,e){if(t.expandoInstructions){var n=e[It]=t.expandoStartIndex;gn(n);for(var a=-1,r=-1,i=0;i<t.expandoInstructions.length;i++){var s=t.expandoInstructions[i];if("number"==typeof s){if(s<=0){r=-s;var o=t.expandoInstructions[++i];a=n+=Ut+o}else n+=s;gn(n)}else null!==s&&(e[It]=n,s(2,Jt(e[a]),r)),a++}}}(e,t)}!function(t){if(null!=t)for(var e=0;e<t.length;e++)void 0,void 0,16==(16&(n=ne(t[e],Xe()))[_t])&&12&n[_t]&&(function(t){for(var e=t[vt],n=t.length;n<e.blueprint.length;n++)t[n]=e.blueprint[n]}(n),ys(n,n[kt]));var n}(e.components)}function si(t,e,n,a,r,i,s,o){var u=e.blueprint.slice();return u[_t]=51|a,u[xt]=u[Mt]=t,u[kt]=n,u[Rt]=r||t&&t[Rt],u[At]=i||t&&t[At],u[Dt]=s||t&&t[Dt]||null,u[Nt]=o||t&&t[Nt]||null,u}function oi(t,e,n,a,r){var i=Xe(),s=i[vt],o=t+qt;i[o]=n;var u=s.data[o];null==u&&(u=s.data[o]=Pi(i,e,o,a,r,null));var c=Qe(),l=nn();return c&&(!l||null!=c.child||null===u.parent&&2!==c.type?l||(c.next=u):c.child=u),null==s.firstChild&&(s.firstChild=u),tn(u),an(!0),u}function ui(t,e){return null==e[vt].node&&(e[vt].node=Pi(e,2,t,null,null,null)),e[Ot]=e[vt].node}function ci(t){var e=t[vt];e.firstTemplatePass&&(e.expandoStartIndex++,e.blueprint.push(null),e.data.push(null),t.push(null))}function li(t,e,n){var a,r=nn(),i=Qe();if(an(!0),tn(null),128&t[_t])hs(ce(t));else try{an(!0),tn(null),a=bn(t,t[Ot]),mi(),e.template(pi(t),n),t[vt].firstTemplatePass=!1,fn(!1),ii(t)}finally{yn(a),an(r),tn(i)}}function di(t){return void 0===t&&(t=1),mn(t)}function fi(t,e,n){var a=t[Rt],r=bn(t,t[Ot]),i=!un();try{i&&a.begin&&a.begin(),rn(t)&&(n&&(mi(),n(1,e)),ii(t),t[_t]&=-2),n&&n(2,e),ii(t)}finally{i&&a.end&&a.end(),yn(r)}}function pi(t){return rn(t)?1:2}var hi=null;function gi(){hi="http://www.w3.org/2000/svg"}function bi(){hi="http://www.w3.org/1998/MathML/"}function mi(){hi=null}function yi(t,e,n,a){xi(t,e,n,a),Ni()}function vi(t,e,n){var a=Xe(),r=a[vt],i=a[At].createComment("");Ba(i,oi(t,4,i,"ng-container",e||null),a),wi(r,a,n),Yn(i,a)}function _i(){var t=Qe(),e=Xe(),n=e[vt];nn()?an(!1):tn(t=t.parent);var a=e[wt];a&&(e[wt]=a.addNode(t)),Me(n,t)}function xi(t,e,n,a){var r,i,s,o=Xe(),u=o[vt],c=Ti(e),l=oi(t,3,c,e,n||null);if(n&&(u.firstTemplatePass&&!l.stylingTemplate&&function(t){for(var e=0;e<t.length;e++){var n=t[e];if(1==n||2==n)return!0}return!1}(n)&&(l.stylingTemplate=hr(n)),Ii(c,n)),Ba(c,l,o),wi(u,o,a),0===xe&&Yn(c,o),xe++,u.firstTemplatePass){var d=Fs(l);d&&d.hasOwnProperty("class")&&(l.flags|=8)}l.stylingTemplate&&0==(8&l.flags)&&(br(r=c,s=o[At],(i=l.stylingTemplate)[3],!0),br(r,s,i[2],!1))}function Ti(t,e){var n=e||Xe()[At];return wa(n)?n.createElement(t,hi):null===hi?n.createElement(t):n.createElementNS(hi,t)}function wi(t,e,n,a){if(void 0===a&&(a=te),Ve){var r=Qe();dn()&&function(t,e,n,a,r){var i=r?{"":-1}:null;if(n){Xi(a,t.data.length,n.length);for(var s=0;s<n.length;s++)(o=n[s]).providersResolver&&o.providersResolver(o);for(Ui(t,a,n.length),s=0;s<n.length;s++){var o,u=t.data.length;Ji(t,e,o=n[s],o.factory),Zi(t.data.length-1,o,i),Pe(u,o.onInit,o.doCheck,t)}}i&&function(t,e,n){if(e)for(var a=t.localNames=[],r=0;r<e.length;r+=2){var i=n[e[r+1]];if(null==i)throw new Error("Export of name '"+e[r+1]+"' not found!");a.push(e[r],i)}}(a,r,i)}(t,e,function(t,e,n){var a=t.directiveRegistry,r=null;if(a)for(var i=0;i<a.length;i++){var s=a[i];er(n,s.selectors,!1)&&(r||(r=[]),Cn(wn(Qe(),e),e,s.type),ie(s)?(1&n.flags&&pa(n),n.flags=1,r.unshift(s)):r.push(s))}return r}(t,e,r),r,n||null),function(t,e,n){var a=n.directiveStart,r=n.directiveEnd;!dn()&&a<r&&wn(n,e);for(var i=a;i<r;i++){var s=t.data[i];ie(s)&&Qi(e,n,s),Wi(e,En(t.data,e,i,n),s,i)}}(t,e,r),function(t,e,n){for(var a=n.directiveStart,r=n.directiveEnd,i=t.expandoInstructions,s=dn(),o=a;o<r;o++){var u=t.data[o],c=e[o];if(u.hostBindings){var l=i.length;Ke(u),u.hostBindings(1,c,n.index-qt),Ke(null),l===i.length&&s&&i.push(u.hostBindings)}else s&&i.push(null)}}(t,e,r),function(t,e,n){var a=e.localNames;if(a)for(var r=e.index+1,i=0;i<a.length;i+=2){var s=a[i+1],o=-1===s?n(e,t):t[s];t[r++]=o}}(e,r,a)}}function Si(t,e,n,a,r,i){return t.ngPrivateData||(t.ngPrivateData=Oi(-1,t,e,n,a,r,i))}function Oi(t,e,n,a,r,i,s){var o=qt+n,u=o+a,c=function(t,e){var n=new Array(e).fill(null,0,t).fill(ha,t);return n[Lt]=-1,n[It]=t,n}(o,u);return c[vt]={id:t,blueprint:c,template:e,viewQuery:s,node:null,data:c.slice(),childIndex:-1,bindingStartIndex:o,expandoStartIndex:u,expandoInstructions:null,firstTemplatePass:!0,initHooks:null,checkHooks:null,contentHooks:null,contentCheckHooks:null,viewHooks:null,viewCheckHooks:null,destroyHooks:null,pipeDestroyHooks:null,cleanup:null,contentQueries:null,components:null,directiveRegistry:"function"==typeof r?r():r,pipeRegistry:"function"==typeof i?i():i,firstChild:null}}function Ii(t,e){for(var n=Xe()[At],a=wa(n),r=0;r<e.length;){var i=e[r++];if("number"==typeof i){if(0!==i)break;var s=e[r++],o=e[r++],u=e[r++];a?n.setAttribute(t,o,u,s):t.setAttributeNS(s,o,u)}else u=e[r++],i!==xa&&(cr(i)?a&&n.setProperty(t,i,u):a?n.setAttribute(t,i,u):t.setAttribute(i,u))}}function Ci(t,e){var n=t.createRenderer(null,null);return"string"==typeof e?wa(n)?n.selectRootElement(e):n.querySelector(e):e}function ki(t,e,n){void 0===n&&(n=!1);var a=Xe(),r=Qe(),i=a[vt],s=i.firstTemplatePass&&(i.cleanup||(i.cleanup=[]));if(3===r.type){var o=te(r,a),u=a[At],c=(b=Gs(a)).length,l=n;if(wa(u)){var d=u.listen(o,t,e);b.push(e,d),l=c+1}else{var f=function(t){return function(e){!1===t(e)&&(e.preventDefault(),e.returnValue=!1)}}(e);o.addEventListener(t,f,n),b.push(f)}s&&s.push(t,r.index,c,l)}void 0===r.outputs&&(r.outputs=qi(r,1));var p,h=r.outputs;if(h&&(p=h[t])){var g=p.length;if(g)for(var b=Gs(a),m=0;m<g;m+=2){var y=a[p[m]][p[m+1]].subscribe(e),v=b.length;b.push(e,y),s&&s.push(t,r.index,v,-(v+1))}}}function Ni(){var t=Qe();nn()?an(!1):tn(t=t.parent);var e=Xe(),n=e[wt];if(n&&(e[wt]=n.addNode(t)),Me(Xe()[vt],t),xe--,pr(t)){var a=ur(t.index,e);Mi(e,t.inputs.class,ai(a))}}function Ri(t,e,n,a){if(n!==ha){var r=Xe(),i=r[At],s=Qt(t,r);if(null==n)wa(i)?i.removeAttribute(s,e):s.removeAttribute(e);else{var o=null==a?Zt(n):a(n);wa(i)?i.setAttribute(s,e,o):s.setAttribute(e,o)}}}function Ai(t,e,n,a,r){Li(t,e,n,a,r)}function Di(t,e,n,a,r){Li(t,e,n,a,r,Ei)}function Ei(t,e){return e[t.index][At]}function Li(t,e,n,a,r,i){if(n!==ha){var s,o,u=Xe(),c=Qt(t,u),l=ee(t,u);if(!r&&(s=Fs(l))&&(o=s[e]))Mi(u,o,n),re(l)&&function(e,n){var a=ne(t+qt,e);4&a[_t]||(a[_t]|=8)}(u);else if(3===l.type){var d=i?i(l,u):u[At];n=null!=a?a(n):n,wa(d)?d.setProperty(c,e,n):cr(e)||(c.setProperty?c.setProperty(e,n):c[e]=n)}}}function Pi(t,e,n,a,r,i){var s=Qe(),o=nn()?s:s&&s.parent,u=o&&t&&o!==t[Ot]?o:null;return{type:e,index:n,injectorIndex:u?u.injectorIndex:-1,directiveStart:-1,directiveEnd:-1,flags:0,providerIndexes:0,tagName:a,attrs:r,localNames:null,initialInputs:void 0,inputs:void 0,outputs:void 0,tViews:i,next:null,child:null,parent:u,detached:null,stylingTemplate:null,projection:null}}function Mi(t,e,n){for(var a=0;a<e.length;a+=2)t[e[a]][e[a+1]]=n}function qi(t,e){var n=Xe()[vt],a=null,r=t.directiveStart,i=t.directiveEnd;if(i>r)for(var s=0===e,o=n.data,u=r;u<i;u++){var c=o[u],l=s?c.inputs:c.outputs;for(var d in l)if(l.hasOwnProperty(d)){var f=l[d];(a=a||{}).hasOwnProperty(d)?a[d].push(u,f):a[d]=[u,f]}}return a}function ji(t,e,n,a){var r=Qe();r.stylingTemplate||(r.stylingTemplate=or()),function(t,e,n,a,r,i){if(!(32&t[0])){var s=function(t,e,n){var a,r=t[1],i=t[4].length,s=Qr(r,e);if(-1===s)a=r.length/4,r.push(e,i,!1,n||null);else{if(r[s+1]>=0)return-1;a=s/4,r[s+1]=i,r[s+3]=n||null}return a}(t,e,r);if(-1!==s){var o=t[4],u=o[1],c=o[0],l=4*c,d=9+l,f=d+4*u,p=f+l,h=o.length;o.push(a?a.length:0,n?n.length:0);var g=0,b=[];if(a&&a.length)for(var m=0;m<a.length;m++){var y=a[m];-1==(x=mr(t,y,9,d))&&(x=d+g,g+=4,b.push(y)),o.push(x)}var v=[];if(n&&n.length)for(var _=0;_<n.length;_++){var x,T=n[_];-1==(x=mr(t,T,d,f))?(x=f+g,g+=4,v.push(T)):x+=4*b.length,o.push(x)}var w=2;if(b.length)for(;w<h;){var S=o[w+0],O=o[w+1];if(O)for(var I=w+2+S,C=I;C<I+O;C++)o[C]+=4*b.length;w+=2+(S+O)}for(var k=v.length+b.length,N=9;N<t.length;N+=4){var R=N>=f,A=N>=(R?p:d),D=jr(t,N),E=Cr(D),L=kr(D);qr(t,N,Or(D,E,L+=R?A?4*b.length:0:4*k+4*(A?b.length:0)))}for(var P=0;P<4*b.length;P++)t.splice(p,0,null),t.splice(d,0,null),d++,f++,p+=2;for(var M=0;M<4*v.length;M++)t.splice(f,0,null),t.push(null),f++,p++;for(var q=t[3],j=t[2],F=0;F<k;F++){var z=F>=b.length,G=z?F-b.length:F,Y=z?v[G]:b[G],V=void 0,H=void 0;z?(V=p+4*(u+G),H=d+4*(u+G)):(V=f+4*(c+G),H=9+4*(c+G));var B=z?q:j,U=ti(B,Y);-1===U?(U=B.length+1,B.push(Y,!z&&null)):U+=1;var W=Kr(t,Y,z,r||null);qr(t,H,Or(W,U,V)),Rr(t,H,Y),Ar(t,H,null),Lr(t,H,0,s),qr(t,V,Or(W,U,H)),Rr(t,V,Y),Ar(t,V,null),Lr(t,V,0,s)}o[1]=u+v.length,o[0]=c+b.length,qr(t,0,Or(0,0,f)|(i?16:0))}}}(r.stylingTemplate,a||null,t,e,n,pr(r))}function Fi(t,e){var n=Qe();n.stylingTemplate||(n.stylingTemplate=hr(e)),function(t,e,n){var a=t[1];if(-1==Qr(a,n)){a.push(n,-1,!1,null);for(var r=null,i=null,s=-1,o=0;o<e.length;o++){var u=e[o];"number"==typeof u?s=u:1==s?gr(r=r||t[3],u,!0):2==s&&gr(i=i||t[2],u,e[++o])}}}(n.stylingTemplate,e,t)}function zi(t,e){var n=Xe(),a=0!=(2&n[_t]);(function(t,n,a,r,i,s,o){var u=0,c=Jr(t,e||null);if(function(t){return Tr(t,0)}(t)&&function(t,e){return t[1][4*c+2]}(t)){for(var l=8&t[0],d=t[5],f=Nr(t),p=Gr(t),h=!1,g=9;g<t.length;g+=4)if(Tr(t,g)){var b=jr(t,g),m=Xr(t,g);if(c!==m){h=!0;continue}var y=zr(t,g),v=Fr(t,g),_=4&b?ei(t,m):null,x=Mr(t,g),T=!!(2&b),w=!T||!p,S=v;g<f&&!Wr(S,T)&&(S=Fr(t,kr(b))),T||Wr(S,T)||!w||(S=Ir(t,b)),(!r||S)&&(T?_r(d,y,!!S,n,null,x):vr(d,y,S,n,_,null,x)),xr(t,g,!1)}if(l){var O=Array.isArray(a)?ce(a):a,I=dr(t),C=I[0];for(g=1;g<C;g+=2){var k=I[g],N=g+1,R=I[N];if(k){var A=k.buildPlayer(R,r);void 0!==A&&(null!=A&&lr(I,O,d,A,N)&&u++,R&&R.destroy())}else R&&R.destroy()}Vr(t,!1)}ni(t,c,!1),Yr(t,h)}return u})(ur(t+qt,n),n[At],n,a)>0&&ps(ce(n),2)}function Gi(t,e,n,a,r){var i=null;null!==n&&(i=a?Zt(n)+a:n),yr(ur(t+qt,Xe()),e,i,!1,r)}function Yi(t,e,n,a){var r=n instanceof rr?n:!!n;yr(ur(t+qt,Xe()),e,r,!0,a)}function Vi(t,e,n,a){if(null!=a)return function(t,e,n,a){throw new Error("unimplemented. Should not be needed by ViewEngine compatibility")}();var r=Xe(),i=ee(t,r),s=ur(t+qt,r);if(pr(i)&&e!==ha){var o=ai(s);Mi(r,i.inputs.class,(o.length?o+" ":"")+e)}else!function(t,e,n,a){n=n||null;var r=Jr(t,null),i=t[5],s=e instanceof rr?new Zr(e,i,1):null,o=n instanceof rr?new Zr(n,i,2):null,u=s?e.value:e,c=o?n.value:n,l=Gr(t)||u===ha||u===t[6],d=c===ha||c===t[7];if(!l||!d){t[6]=u,t[7]=c;var f=it,p=!1,h=!1,g=s?1:0;Dr(t,s,1)&&(Er(t,s,1),h=!0);var b=o?3:0;Dr(t,o,3)&&(Er(t,o,3),h=!0),l||("string"==typeof u?(f=u.split(/\s+/),p=!0):f=u?Object.keys(u):it);for(var m=u||rt,y=c?Object.keys(c):it,v=c||rt,_=y.length,x=!1,T=Nr(t),w=0,S=y.length+f.length;T<t.length&&w<S;){if(!(M=w>=_)&&!d||M&&!l){var O=M?w-_:w,I=M?f[O]:y[O],C=M?!!p||m[I]:v[I],k=M?g:b;if((q=zr(t,T))===I){var N=Fr(t,T),R=jr(t,T);if(Lr(t,T,k,r),$r(R,N,C)){Ar(t,T,C),h=h||!!k;var A=Ir(t,R);(null!=N||$r(R,A,C))&&(xr(t,T,!0),x=!0)}}else{var D=Hr(t,I,T);if(D>0){var E=Fr(t,D),L=jr(t,D);Br(t,T,D),$r(L,E,C)&&(A=Ir(t,L),Ar(t,T,C),(null!=E||$r(L,A,C))&&(xr(t,T,!0),h=h||!!k,x=!0))}else h=h||!!k,Ur(t,T,M,I,Kr(t,I,M,ei(t,r)),C,r,k),x=!0}}T+=4,w++}for(;T<t.length;)(!(M=2==(2&(R=jr(t,T))))&&!d||M&&!l)&&Wr(N=Fr(t,T),M)&&(xr(t,T,!0),Ar(t,T,null),Lr(t,T,k=M?g:b,r),x=!0),T+=4;for(var P=ei(t,r);w<S;){var M;if(!(M=w>=_)&&!d||M&&!l){O=M?w-_:w;var q=M?f[O]:y[O],j=(N=M?!!p||m[q]:v[q],R=1|Kr(t,q,M,P),k=M?g:b,t.length);t.push(R,q,N,0),Lr(t,j,k,r),x=!0}w++}x&&(Yr(t,!0),ni(t,r,!0)),h&&Vr(t,!0)}}(s,e,n)}function Hi(t,e){var n=Xe(),a=Da(e,n[At]),r=oi(t,3,a,null,null);an(!1),Ba(a,r,n)}function Bi(t,e){if(e!==ha){var n=Xe(),a=Qt(t,n),r=n[At];wa(r)?r.setValue(a,Zt(e)):a.textContent=Zt(e)}}function Ui(t,e,n){var a=-(e.index-qt),r=t.data.length-(65535&e.providerIndexes);(t.expandoInstructions||(t.expandoInstructions=[])).push(a,r,n)}function Wi(t,e,n,a){var r=Qe();Ki(t,r,e,n),r&&r.attrs&&function(t,e,a,i){var s=r.initialInputs;(void 0===s||t>=s.length)&&(s=function(t,e,n){var a=n.initialInputs||(n.initialInputs=[]);a[t]=null;for(var r=n.attrs,i=0;i<r.length;){var s=r[i];if(3===s)break;if(0!==s){var o=e[s],u=r[i+1];void 0!==o&&(a[t]||(a[t]=[])).push(o,u),i+=2}else i+=4}return a}(t,n.inputs,r));var o=s[t];if(o)for(var u=0;u<o.length;u+=2)e[o[u]]=o[u+1]}(a,e),n.contentQueries&&n.contentQueries(a),ie(n)&&(ne(r.index,t)[kt]=e)}function Ki(t,e,n,a){var r=te(e,t);Yn(n,t),r&&Yn(r,t),null!=a.attributes&&3==e.type&&Ii(r,a.attributes)}function $i(t){var e=Xe()[vt];(e.components||(e.components=[])).push(t.index)}function Zi(t,e,n){n&&(e.exportAs&&(n[e.exportAs]=t),e.template&&(n[""]=t))}function Xi(t,e,n){t.flags=1&t.flags,t.directiveStart=e,t.directiveEnd=e+n,t.providerIndexes=e}function Ji(t,e,n,a){t.data.push(n);var r=new Kt(a,ie(n),null);t.blueprint.push(r),e.push(r)}function Qi(t,e,n){var a=te(e,t),r=Si(n.template,n.consts,n.vars,n.directiveDefs,n.pipeDefs,n.viewQuery),i=ds(t,e.index,si(t,r,null,n.onPush?8:4,t[Rt],t[Rt].createRenderer(a,n)));i[Ot]=e,i[St]=t[e.index],t[e.index]=i,dn()&&$i(e)}function ts(t,e,n,a,r){return[r?-1:0,[],n,null,null,t,a,Ga(e,n)]}function es(t,e,n,a,r,i,s,o){var u=Xe(),c=u[vt],l=as(t,r||null,i||null);dn()&&(l.tViews=Oi(-1,e,n,a,c.directiveRegistry,c.pipeRegistry,null)),wi(c,u,s,o);var d=u[wt],f=Qe();Yn(te(f,u),u),d&&(u[wt]=d.addNode(f)),Me(c,l),an(!1)}function ns(t){var e=as(t,null,null);dn()&&(e.tViews=[]),an(!1)}function as(t,e,n){var a=Xe(),r=t+qt,i=a[At].createComment(""),s=oi(t,0,i,e,n),o=a[r]=ts(a[r],s,a,i);Ba(i,s,a),ds(a,t+qt,o);var u=a[wt];return u&&(o[wt]=u.container()),s}function rs(t){var e=Xe(),n=e[vt];tn(Xt(n.data,t)),an(!0),e[t+qt][jt]=0,ze(e,n,un())}function is(){var t=Qe();nn()?an(!1):tn(t=t.parent);for(var e=Xe()[t.index],n=e[jt];n<e[Ft].length;)Ma(e,t,n)}function ss(t,e,n){var a=Xe(),r=Qe(),i=2===r.type?r.parent:r,s=a[i.index],o=function(t,e,n,a){for(var r=t[Ft],i=n;i<r.length;i++){var s=r[i][vt].id;if(s===a)return r[i];if(!(s<a))break;Ma(t,e,i)}return null}(s,i,s[jt],t);return o?(an(!0),bn(o,o[vt].node)):(o=si(a,function(t,e,n,a){var r=Xe()[vt],i=a.tViews;return(t>=i.length||null==i[t])&&(i[t]=Oi(t,null,e,n,r.directiveRegistry,r.pipeRegistry,null)),i[t]}(t,e,n,i),null,4),s[wt]&&(o[wt]=s[wt].createView()),ui(t,o),bn(o,o[vt].node)),s&&(rn(o)&&La(o,s,a,s[jt],-1),s[jt]++),rn(o)?3:2}function os(){var t=Xe(),e=t[Ot];rn(t)&&(ii(t),t[_t]&=-2),ii(t),yn(t[xt]),tn(e),an(!1)}function us(t,e){var n=ye(Xe())[Ot];if(!n.projection)for(var a=n.projection=new Array(t?t.length+1:1).fill(null),r=a.slice(),i=n.child;null!==i;){var s=t?nr(i,t,e):0,o=i.next;r[s]?r[s].next=i:(a[s]=i,i.next=null),r[s]=i,i=o}}var cs=[];function ls(t,e,n){void 0===e&&(e=0);var a=Xe(),r=oi(t,1,null,null,n||null);null===r.projection&&(r.projection=e),an(!1);for(var i=ye(a),s=i[Ot].projection[e],o=i[xt],u=-1;s;){if(1===s.type){var c=ye(o),l=c[Ot].projection[s.projection];if(l){cs[++u]=s,cs[++u]=o,s=l,o=c[xt];continue}}else s.flags|=2,$a(s,r,a,o);null===s.next&&o!==i[xt]&&(o=cs[u--],s=cs[u--]),s=s.next}}function ds(t,e,n){var a=t[vt],r=dn();return t[Et]?t[Et][Tt]=n:r&&(a.childIndex=e),t[Et]=n,n}function fs(t){for(;t&&!(128&t[_t]);)t[_t]|=8,t=t[xt];t[_t]|=8,ps(t[kt],1)}function ps(t,e){var n,a=0===t.flags;t.flags|=e,a&&t.clean==ri&&(t.clean=new Promise(function(t){return n=t}),t.scheduler(function(){if(1&t.flags&&(t.flags&=-2,hs(t)),2&t.flags){t.flags&=-3;var e=t.playerHandler;e&&e.flushPlayers()}t.clean=ri,n(null)}))}function hs(t){for(var e=0;e<t.components.length;e++){var n=t.components[e];fi(de(n),n)}}function gs(t){bs(Gn(t),t)}function bs(t,e){var n=t[Rt];n.begin&&n.begin(),rn(t)&&ys(t,e),ys(t,e),n.end&&n.end()}function ms(t){hs(t[kt])}function ys(t,e){var n=t[vt],a=bn(t,t[Ot]),r=n.template,i=n.viewQuery;try{mi(),function(e,n,a){e&&rn(t)&&e(1,a)}(i,0,e),r(pi(t),e),ii(t),function(e,n,a){e&&!rn(t)&&e(2,a)}(i,0,e)}finally{yn(a)}}function vs(t){fs(Gn(t))}function _s(t){var e=Xe();return ma(e,e[It]++,t)?t:ha}function xs(t){if(dn()){var e=Xe(),n=e[vt];!function(t,e,n){var a=t.expandoInstructions,r=a.length;r>=2&&a[r-2]===e.hostBindings?a[r-1]=a[r-1]+n:a.push(e.hostBindings,n)}(n,We,t),function(t,e,n){for(var a=0;a<n;a++)e.push(ha),t.blueprint.push(ha),t.data.push(null)}(n,e,t)}}function Ts(t){for(var e=!1,n=Xe(),a=n[It],r=1;r<t.length;r+=2)ma(n,a++,t[r])&&(e=!0);if(n[It]=a,!e)return ha;var i=t[0];for(r=1;r<t.length;r+=2)i+=Zt(t[r])+t[r+1];return i}function ws(t,e,n){var a=Xe(),r=ma(a,a[It],e);return a[It]+=1,r?t+Zt(e)+n:ha}function Ss(t,e,n,a,r){var i=Xe(),s=ya(i,i[It],e,a);return i[It]+=2,s?t+Zt(e)+n+Zt(a)+r:ha}function Os(t,e,n,a,r,i,s){var o=Xe(),u=va(o,o[It],e,a,i);return o[It]+=3,u?t+Zt(e)+n+Zt(a)+r+Zt(i)+s:ha}function Is(t,e,n,a,r,i,s,o,u){var c=Xe(),l=_a(c,c[It],e,a,i,o);return c[It]+=4,l?t+Zt(e)+n+Zt(a)+r+Zt(i)+s+Zt(o)+u:ha}function Cs(t,e,n,a,r,i,s,o,u,c,l){var d=Xe(),f=d[It],p=_a(d,f,e,a,i,o);return p=ma(d,f+4,c)||p,d[It]+=5,p?t+Zt(e)+n+Zt(a)+r+Zt(i)+s+Zt(o)+u+Zt(c)+l:ha}function ks(t,e,n,a,r,i,s,o,u,c,l,d,f){var p=Xe(),h=p[It],g=_a(p,h,e,a,i,o);return g=ya(p,h+4,c,d)||g,p[It]+=6,g?t+Zt(e)+n+Zt(a)+r+Zt(i)+s+Zt(o)+u+Zt(c)+l+Zt(d)+f:ha}function Ns(t,e,n,a,r,i,s,o,u,c,l,d,f,p,h){var g=Xe(),b=g[It],m=_a(g,b,e,a,i,o);return m=va(g,b+4,c,d,p)||m,g[It]+=7,m?t+Zt(e)+n+Zt(a)+r+Zt(i)+s+Zt(o)+u+Zt(c)+l+Zt(d)+f+Zt(p)+h:ha}function Rs(t,e,n,a,r,i,s,o,u,c,l,d,f,p,h,g,b){var m=Xe(),y=m[It],v=_a(m,y,e,a,i,o);return v=_a(m,y+4,c,d,p,g)||v,m[It]+=8,v?t+Zt(e)+n+Zt(a)+r+Zt(i)+s+Zt(o)+u+Zt(c)+l+Zt(d)+f+Zt(p)+h+Zt(g)+b:ha}function As(t,e){var n=Xe(),a=n[vt],r=t+qt;r>=a.data.length&&(a.data[r]=null),n[r]=e}function Ds(t){return Xt(sn,t)}function Es(t){return Xe()[Pt][t]}function Ls(t){return Xt(Xe(),t)}function Ps(t,e){return void 0===e&&(e=Ce.Default),t=J(t),Nn(Qe(),Xe(),t,e)}function Ms(t){return kn(Qe(),t)}function qs(t,e){var n=Xe(),a=n[vt],r=(n[Pt]||(n[Pt]=[])).push(t);if(dn()){var i=a.contentQueries||(a.contentQueries=[]);e!==(a.contentQueries.length?a.contentQueries[a.contentQueries.length-2]:-1)&&i.push(e,r-1)}}var js=ri;function Fs(t){return t?(void 0===t.inputs&&(t.inputs=qi(t,0)),t.inputs):null}function zs(){return Xe()}function Gs(t){return t[Ct]||(t[Ct]=[])}function Ys(t){return t[vt].cleanup||(t[vt].cleanup=[])}function Vs(t,e){var n=Fn(t);if(n){var a=n.native,r=n.lView,i=function(t,e){if(!(e=e||Fn(a)))return null;var n=ur(e.nodeIndex,e.lView);return dr(n)||fr(n)}(0,n),s=Zn(r);lr(i,s,a,e,0,t),ps(s,2)}}function Hs(t){var e=Fn(t);if(!e)return[];var n=ur(e.nodeIndex,e.lView),a=n?dr(n):null;return a?function(t){for(var e=[],n=t[0],a=2;a<n;a+=2){var r=t[a];r&&e.push(r)}for(a=n;a<t.length;a++)e.push(t[a]);return e}(a):[]}var Bs="ng",Us=!1;function Ws(){Us||(Us=!0,Ks("getComponent",Wn),Ks("getContext",Kn),Ks("getListeners",ra),Ks("getViewComponent",$n),Ks("getHostElement",ea),Ks("getInjector",Jn),Ks("getRootComponents",Xn),Ks("getDirectives",Qn),Ks("getPlayers",Hs),Ks("markDirty",vs))}function Ks(t,e){if(V){var n=V[Bs];n||(n=V[Bs]={}),n[t]=e}}function $s(t,e){void 0===e&&(e={});var n=e.rendererFactory||Sa,a=e.sanitizer||null,r=gt(t);r.type!=t&&(r.type=t);var i,s=Ci(n,e.host||r.selectors[0][0]),o=r.onPush?136:132,u=Js(e.scheduler,e.playerHandler),c=n.createRenderer(s,r),l=si(null,Oi(-1,null,1,0,null,null,null),u,o,n,c,void 0,e.injector||null),d=bn(l,null);try{n.begin&&n.begin(),i=Xs(Zs(s,r,l,n,c,a),r,l,u,e.hostFeatures||null),ii(l),l[_t]&=-2,ii(l)}finally{yn(d),n.end&&n.end()}return i}function Zs(t,e,n,a,r,i){Be=!1,He=null,xe=0,Ve=!0;var s=n[vt],o=si(n,Si(e.template,e.consts,e.vars,e.directiveDefs,e.pipeDefs,e.viewQuery),null,e.onPush?8:4,a,r,i),u=oi(0,3,t,null,null);return s.firstTemplatePass&&(Cn(wn(u,n),n,e.type),u.flags=1,Xi(u,n.length,1),$i(u)),o[St]=n[qt],o[Ot]=u,n[qt]=o}function Xs(t,e,n,a,r){var i=n[vt],s=function(t,e,n){var a=Qe();t.firstTemplatePass&&(n.providersResolver&&n.providersResolver(n),Ui(t,a,1),Ji(t,e,n,n.factory));var r=En(t.data,e,e.length-1,a);return Ki(e,a,r,n),r}(i,n,e);if(a.components.push(s),t[kt]=s,r&&r.forEach(function(t){return t(s,e)}),i.firstTemplatePass&&e.hostBindings){var o=Qe();Ke(e),e.hostBindings(1,s,o.index-qt),Ke(null)}return s}function Js(t,e){return{components:[],scheduler:t||be,clean:js,playerHandler:e||null,flags:0}}function Qs(t,e){var n=de(t)[vt],a=n.data.length-1;Pe(a,e.onInit,e.doCheck,n),Me(n,{directiveStart:a,directiveEnd:a+1})}function to(t){return function(t){return ue(t)[kt]}(t).clean}function eo(t){return"function"==typeof t.template}function no(t){for(var e=Object.getPrototypeOf(t.type.prototype).constructor,n=function(){var n,r,i=void 0;if(eo(t))i=e.ngComponentDef||e.ngDirectiveDef;else{if(e.ngComponentDef)throw new Error("Directives cannot inherit Components");i=e.ngDirectiveDef}var s=e.ngBaseDef;if(s||i){var o=t;o.inputs=ao(t.inputs),o.declaredInputs=ao(t.declaredInputs),o.outputs=ao(t.outputs)}if(s&&(l(t.inputs,s.inputs),l(t.declaredInputs,s.declaredInputs),l(t.outputs,s.outputs)),i){var u=t.hostBindings,c=i.hostBindings;if(c&&(t.hostBindings=u?function(t,e,n){c(t,e,n),u(t,e,n)}:c),eo(t)&&eo(i)){var d=t.viewQuery,f=i.viewQuery;f&&(t.viewQuery=d?function(t,e){f(t,e),d(t,e)}:f)}var p=t.contentQueries,h=i.contentQueries;h&&(t.contentQueries=p?function(t){h(t),p(t)}:h);var g=t.contentQueriesRefresh,b=i.contentQueriesRefresh;b&&(t.contentQueriesRefresh=g?function(t,e){b(t,e),g(t,e)}:b),l(t.inputs,i.inputs),l(t.declaredInputs,i.declaredInputs),l(t.outputs,i.outputs),t.afterContentChecked=t.afterContentChecked||i.afterContentChecked,t.afterContentInit=t.afterContentInit||i.afterContentInit,t.afterViewChecked=t.afterViewChecked||i.afterViewChecked,t.afterViewInit=t.afterViewInit||i.afterViewInit,t.doCheck=t.doCheck||i.doCheck,t.onDestroy=t.onDestroy||i.onDestroy,t.onInit=t.onInit||i.onInit;var m=i.features;if(m)try{for(var y=Object(a.__values)(m),v=y.next();!v.done;v=y.next()){var _=v.value;_&&_.ngInherit&&_(t)}}catch(T){n={error:T}}finally{try{v&&!v.done&&(r=y.return)&&r.call(y)}finally{if(n)throw n.error}}return"break"}var x=e.prototype;x&&(t.afterContentChecked=t.afterContentChecked||x.afterContentChecked,t.afterContentInit=t.afterContentInit||x.afterContentInit,t.afterViewChecked=t.afterViewChecked||x.afterViewChecked,t.afterViewInit=t.afterViewInit||x.afterViewInit,t.doCheck=t.doCheck||x.doCheck,t.onDestroy=t.onDestroy||x.onDestroy,t.onInit=t.onInit||x.onInit),e=Object.getPrototypeOf(e)};e&&"break"!==n(););}function ao(t){return t===rt?{}:t===it?[]:t}var ro="__ngOnChanges_";function io(t){var e=t.declaredInputs,n=t.inputs,a=t.type.prototype,r=function(t){if(e.hasOwnProperty(t)){for(var r=n[t],i=e[t],s=ro+r,o=void 0,u=a;!o&&u&&Object.getPrototypeOf(u)!==Object.getPrototypeOf(Object.prototype);)o=Object.getOwnPropertyDescriptor(u,r),u=Object.getPrototypeOf(u);var c=o&&o.set;Object.defineProperty(a,r,{get:o&&o.get||(c?void 0:function(){return this[s]}),set:function(t){var e=this[ro];e||(e={},Object.defineProperty(this,ro,{value:e,writable:!0}));var n=!this.hasOwnProperty(s),a=e[i];a?a.currentValue=t:e[i]=new la(this[s],t,n),n?Object.defineProperty(this,s,{value:t,writable:!0}):this[s]=t,c&&c.call(this,t)},configurable:!1})}};for(var i in e)r(i);null!=t.onInit&&(t.onInit=so(t.onInit)),t.doCheck=so(t.doCheck)}function so(t){return function(){var e=this[ro];null!=e&&(this.ngOnChanges(e),this[ro]=null),t&&t.apply(this)}}function oo(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e]}io.ngInherit=!0;var uo="__source",co=new Object,lo=co,fo=new w("INJECTOR"),po=function(){function t(){}return t.prototype.get=function(t,e){if(void 0===e&&(e=co),e===co)throw new Error("NullInjectorError: No provider for "+$(t)+"!");return e},t}(),ho=function(){function t(){}return t.create=function(t,e){return Array.isArray(t)?new Oo(t,e):new Oo(t.providers,t.parent,t.name||null)},t.THROW_IF_NOT_FOUND=co,t.NULL=new po,t.ngInjectableDef=v({providedIn:"any",factory:function(){return De(fo)}}),t.__NG_ELEMENT_ID__=function(){return bo()},t}(),go=function(){return t=Qe(),new Mn(t,Xe());var t},bo=oo,mo=function(t){return t},yo=[],vo=mo,_o=function(){return Array.prototype.slice.call(arguments)},xo=c({provide:String,useValue:c}),To=ho.NULL,wo=/\n/gm,So="\u0275",Oo=function(){function t(t,e,n){void 0===e&&(e=To),void 0===n&&(n=null),this.parent=e,this.source=n;var a=this._records=new Map;a.set(ho,{token:ho,fn:mo,deps:yo,value:this,useNew:!1}),a.set(fo,{token:fo,fn:mo,deps:yo,value:this,useNew:!1}),function t(e,n){if(n)if((n=J(n))instanceof Array)for(var a=0;a<n.length;a++)t(e,n[a]);else{if("function"==typeof n)throw ko("Function/Class not supported",n);if(!n||"object"!=typeof n||!n.provide)throw ko("Unexpected provider",n);var r=J(n.provide),i=function(t){var e=function(t){var e=yo,n=t.deps;if(n&&n.length){e=[];for(var a=0;a<n.length;a++){var r=6;if((u=J(n[a]))instanceof Array)for(var i=0,s=u;i<s.length;i++){var o=s[i];o instanceof we||o==we?r|=1:o instanceof Oe||o==Oe?r&=-3:o instanceof Se||o==Se?r&=-5:u=o instanceof Te?o.token:J(o)}e.push({token:u,options:r})}}else if(t.useExisting){var u;e=[{token:u=J(t.useExisting),options:6}]}else if(!(n||xo in t))throw ko("'deps' required",t);return e}(t),n=mo,a=yo,r=!1,i=J(t.provide);if(xo in t)a=t.useValue;else if(t.useFactory)n=t.useFactory;else if(t.useExisting);else if(t.useClass)r=!0,n=J(t.useClass);else{if("function"!=typeof i)throw ko("StaticProvider does not have [useValue|useFactory|useExisting|useClass] or [provide] is not newable",t);r=!0,n=i}return{deps:e,fn:n,useNew:r,value:a}}(n);if(!0===n.multi){var s=e.get(r);if(s){if(s.fn!==_o)throw Io(r)}else e.set(r,s={token:n.provide,deps:[],useNew:!1,fn:_o,value:yo});s.deps.push({token:r=n,options:6})}var o=e.get(r);if(o&&o.fn==_o)throw Io(r);e.set(r,i)}}(a,t)}return t.prototype.get=function(t,e,n){void 0===n&&(n=Ce.Default);var r=this._records.get(t);try{return function t(e,n,r,i,s,o){try{return function(e,n,r,i,s,o){var u,c;if(!n||o&Ce.SkipSelf)o&Ce.Self||(c=i.get(e,s,Ce.Default));else{if((c=n.value)==vo)throw Error(So+"Circular dependency");if(c===yo){n.value=vo;var l=n.useNew,d=n.fn,f=n.deps,p=yo;if(f.length){p=[];for(var h=0;h<f.length;h++){var g=f[h],b=g.options,m=2&b?r.get(g.token):void 0;p.push(t(g.token,m,r,m||4&b?i:To,1&b?null:ho.THROW_IF_NOT_FOUND,Ce.Default))}}n.value=c=l?new((u=d).bind.apply(u,Object(a.__spread)([void 0],p))):d.apply(void 0,p)}}return c}(e,n,r,i,s,o)}catch(u){throw u instanceof Error||(u=new Error(u)),(u.ngTempTokenPath=u.ngTempTokenPath||[]).unshift(e),n&&n.value==vo&&(n.value=yo),u}}(t,r,this._records,this.parent,e,n)}catch(s){var i=s.ngTempTokenPath;throw t[uo]&&i.unshift(t[uo]),s.message=Co("\n"+s.message,i,this.source),s.ngTokenPath=i,s.ngTempTokenPath=null,s}},t.prototype.toString=function(){var t=[];return this._records.forEach(function(e,n){return t.push($(n))}),"StaticInjector["+t.join(", ")+"]"},t}();function Io(t){return ko("Cannot mix multi providers and regular providers",t)}function Co(t,e,n){void 0===n&&(n=null),t=t&&"\n"===t.charAt(0)&&t.charAt(1)==So?t.substr(2):t;var a=$(e);if(e instanceof Array)a=e.map($).join(" -> ");else if("object"==typeof e){var r=[];for(var i in e)if(e.hasOwnProperty(i)){var s=e[i];r.push(i+":"+("string"==typeof s?JSON.stringify(s):$(s)))}a="{"+r.join(", ")+"}"}return"StaticInjectorError"+(n?"("+n+")":"")+"["+a+"]: "+t.replace(wo,"\n ")}function ko(t,e){return new Error(Co(t,e))}var No=new w("The presence of this token marks an injector as being the root injector."),Ro={},Ao={},Do=[],Eo=void 0;function Lo(){return void 0===Eo&&(Eo=new po),Eo}function Po(t,e,n){return void 0===e&&(e=null),void 0===n&&(n=null),e=e||Lo(),new Mo(t,n,e)}var Mo=function(){function t(t,e,n){var a=this;this.parent=n,this.records=new Map,this.injectorDefTypes=new Set,this.onDestroy=new Set,this.destroyed=!1;var r=[];zo([t],function(t){return a.processInjectorType(t,[],r)}),e&&zo(e,function(n){return a.processProvider(n,t,e)}),this.records.set(fo,Fo(void 0,this)),this.isRootInjector=this.records.has(No),this.injectorDefTypes.forEach(function(t){return a.get(t)})}return t.prototype.destroy=function(){this.assertNotDestroyed(),this.destroyed=!0;try{this.onDestroy.forEach(function(t){return t.ngOnDestroy()})}finally{this.records.clear(),this.onDestroy.clear(),this.injectorDefTypes.clear()}},t.prototype.get=function(t,e,n){void 0===e&&(e=lo),void 0===n&&(n=Ce.Default),this.assertNotDestroyed();var a,r=Ne(this);try{if(!(n&Ce.SkipSelf)){var i=this.records.get(t);if(void 0===i){var s=("function"==typeof(a=t)||"object"==typeof a&&a instanceof w)&&x(t);s&&this.injectableDefInScope(s)&&(i=Fo(qo(t),Ro),this.records.set(t,i))}if(void 0!==i)return this.hydrate(t,i)}return(n&Ce.Self?Lo():this.parent).get(t,e)}finally{Ne(r)}},t.prototype.assertNotDestroyed=function(){if(this.destroyed)throw new Error("Injector has already been destroyed.")},t.prototype.processInjectorType=function(t,e,n){var a=this;if(t=J(t)){var r=T(t),i=null==r&&t.ngModule||void 0,s=void 0===i?t:i,o=-1!==n.indexOf(s),u=void 0!==i&&t.providers||Do;if(void 0!==i&&(r=T(i)),null!=r){if(this.injectorDefTypes.add(s),this.records.set(s,Fo(r.factory,Ro)),null!=r.imports&&!o){n.push(s);try{zo(r.imports,function(t){return a.processInjectorType(t,e,n)})}finally{}}var c=r.providers;if(null!=c&&!o){var l=t;zo(c,function(t){return a.processProvider(t,l,c)})}var d=t.ngModule;zo(u,function(t){return a.processProvider(t,d,u)})}}},t.prototype.processProvider=function(t,e,n){var a=Yo(t=J(t))?t:J(t&&t.provide),r=function(t,e,n){var a=jo(t,e,n);return Go(t)?Fo(void 0,t.useValue):Fo(a,Ro)}(t,e,n);if(Yo(t)||!0!==t.multi){var i=this.records.get(a);if(i&&void 0!==i.multi)throw new Error("Mixed multi-provider for "+$(a))}else{var s=this.records.get(a);if(s){if(void 0===s.multi)throw new Error("Mixed multi-provider for "+a+".")}else(s=Fo(void 0,Ro,!0)).factory=function(){return Le(s.multi)},this.records.set(a,s);a=t,s.multi.push(t)}this.records.set(a,r)},t.prototype.hydrate=function(t,e){if(e.value===Ao)throw new Error("Cannot instantiate cyclic dependency! "+$(t));var n;return e.value===Ro&&(e.value=Ao,e.value=e.factory()),"object"==typeof e.value&&e.value&&"object"==typeof(n=e.value)&&null!=n&&n.ngOnDestroy&&"function"==typeof n.ngOnDestroy&&this.onDestroy.add(e.value),e.value},t.prototype.injectableDefInScope=function(t){return!!t.providedIn&&("string"==typeof t.providedIn?"any"===t.providedIn||"root"===t.providedIn&&this.isRootInjector:this.injectorDefTypes.has(t.providedIn))},t}();function qo(t){var e=x(t);if(null===e){var n=T(t);if(null!==n)return n.factory;if(t instanceof w)throw new Error("Token "+$(t)+" is missing an ngInjectableDef definition.");if(t instanceof Function){var a=t.length;if(a>0){var r=new Array(a).fill("?");throw new Error("Can't resolve all parameters for "+$(t)+": ("+r.join(", ")+").")}return function(){return new t}}throw new Error("unreachable")}return e.factory}function jo(t,e,n){var r,i=void 0;if(Yo(t))return qo(J(t));if(Go(t))i=function(){return J(t.useValue)};else if((r=t)&&r.useExisting)i=function(){return De(J(t.useExisting))};else if(t&&t.useFactory)i=function(){return t.useFactory.apply(t,Object(a.__spread)(Le(t.deps||[])))};else{var s=J(t&&(t.useClass||t.provide));if(!s){var o="";throw e&&n&&(o=" - only instances of Provider and Type are allowed, got: ["+n.map(function(e){return e==t?"?"+t+"?":"..."}).join(", ")+"]"),new Error("Invalid provider for the NgModule '"+$(e)+"'"+o)}if(!t.deps)return qo(s);i=function(){return new(s.bind.apply(s,Object(a.__spread)([void 0],Le(t.deps))))}}return i}function Fo(t,e,n){return void 0===n&&(n=!1),{factory:t,value:e,multi:n?[]:void 0}}function zo(t,e){t.forEach(function(t){return Array.isArray(t)?zo(t,e):e(t)})}function Go(t){return t&&"object"==typeof t&&xo in t}function Yo(t){return"function"==typeof t}function Vo(t,e,n,a,r){if(t=J(t),Array.isArray(t))for(var i=0;i<t.length;i++)Vo(t[i],e,n,a,r);else{var s=Xe(),o=Yo(t)?t:J(t.provide),u=jo(t),c=Qe(),l=65535&c.providerIndexes,d=c.directiveStart,f=c.providerIndexes>>16;if(Yo(t)||!t.multi){var p=new Kt(u,r,Ps),h=Bo(o,e,r?l:l+f,d);-1==h?(Cn(wn(c,s),s,o),e.push(o),c.directiveStart++,c.directiveEnd++,r&&(c.providerIndexes+=65536),n.push(p),s.push(p)):(n[h]=p,s[h]=p)}else{var g=Bo(o,e,l+f,d),b=Bo(o,e,l,l+f),m=b>=0&&n[b];r&&!m||!r&&!(g>=0&&n[g])?(Cn(wn(c,s),s,o),p=function(t,e,n,a,r){var i=new Kt(t,n,Ps);return i.multi=[],i.index=e,i.componentProviders=0,Ho(i,r,a&&!n),i}(r?Wo:Uo,n.length,r,a,u),!r&&m&&(n[b].providerFactory=p),e.push(o),c.directiveStart++,c.directiveEnd++,r&&(c.providerIndexes+=65536),n.push(p),s.push(p)):Ho(n[r?b:g],u,!r&&a),!r&&a&&m&&n[b].componentProviders++}}}function Ho(t,e,n){t.multi.push(e),n&&t.componentProviders++}function Bo(t,e,n,a){for(var r=n;r<a;r++)if(e[r]===t)return r;return-1}function Uo(t,e,n,a){return Ko(this.multi,[])}function Wo(t,e,n,a){var r,i=this.multi;if(this.providerFactory){var s=this.providerFactory.componentProviders,o=En(e,n,this.providerFactory.index,a);Ko(i,r=o.slice(0,s));for(var u=s;u<o.length;u++)r.push(o[u])}else Ko(i,r=[]);return r}function Ko(t,e){for(var n=0;n<t.length;n++)e.push((0,t[n])());return e}function $o(t,e){return void 0===e&&(e=[]),function(n){n.providersResolver=function(n){return function(t,e,n){var a=Xe()[vt];if(a.firstTemplatePass){var r=ie(t);Vo(n,a.data,a.blueprint,r,!0),Vo(e,a.data,a.blueprint,r,!1)}}(n,t,e)}}}var Zo=function(){return function(){}}(),Xo=function(){return function(){}}();function Jo(t){var e=Error("No component factory found for "+$(t)+". Did you add it to @NgModule.entryComponents?");return e[nu]=t,e}var Qo,tu,eu,nu="ngComponent",au=function(){function t(){}return t.prototype.resolveComponentFactory=function(t){throw Jo(t)},t}(),ru=function(){function t(){}return t.NULL=new au,t}(),iu=function(){function t(t,e,n){this._parent=e,this._ngModule=n,this._factories=new Map;for(var a=0;a<t.length;a++){var r=t[a];this._factories.set(r.componentType,r)}}return t.prototype.resolveComponentFactory=function(t){var e=this._factories.get(t);if(!e&&this._parent&&(e=this._parent.resolveComponentFactory(t)),!e)throw Jo(t);return new su(e,this._ngModule)},t}(),su=function(t){function e(e,n){var a=t.call(this)||this;return a.factory=e,a.ngModule=n,a.selector=e.selector,a.componentType=e.componentType,a.ngContentSelectors=e.ngContentSelectors,a.inputs=e.inputs,a.outputs=e.outputs,a}return Object(a.__extends)(e,t),e.prototype.create=function(t,e,n,a){return this.factory.create(t,e,n,a||this.ngModule)},e}(Xo),ou=function(){return function(){}}(),uu=function(){return function(){}}(),cu=function(){function t(t,e,n){this._context=e,this._componentIndex=n,this._appRef=null,this._viewContainerRef=null,this._tViewNode=null,this._lView=t}return Object.defineProperty(t.prototype,"rootNodes",{get:function(){return null==this._lView[St]?function t(e,n,a){for(var r=n.child;r;)a.push(te(r,e)),4===r.type&&t(e,r,a),r=r.next;return a}(this._lView,this._lView[Ot],[]):[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this._context?this._context:this._lookUpContext()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"destroyed",{get:function(){return 64==(64&this._lView[_t])},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){if(this._appRef)this._appRef.detachView(this);else if(this._viewContainerRef){var t=this._viewContainerRef.indexOf(this);t>-1&&this._viewContainerRef.detach(t),this._viewContainerRef=null}ja(this._lView)},t.prototype.onDestroy=function(t){var e,n;n=t,Gs(e=this._lView).push(n),e[vt].firstTemplatePass&&Ys(e).push(e[Ct].length-1,null)},t.prototype.markForCheck=function(){fs(this._lView)},t.prototype.detach=function(){this._lView[_t]&=-17},t.prototype.reattach=function(){this._lView[_t]|=16},t.prototype.detectChanges=function(){bs(this._lView,this.context)},t.prototype.checkNoChanges=function(){!function(t){cn(!0);try{gs(t)}finally{cn(!1)}}(this.context)},t.prototype.attachToViewContainerRef=function(t){if(this._appRef)throw new Error("This view is already attached directly to the ApplicationRef!");this._viewContainerRef=t},t.prototype.detachFromAppRef=function(){this._appRef=null},t.prototype.attachToAppRef=function(t){if(this._viewContainerRef)throw new Error("This view is already attached to a ViewContainer!");this._appRef=t},t.prototype._lookUpContext=function(){return this._context=this._lView[xt][this._componentIndex]},t}(),lu=function(t){function e(e){var n=t.call(this,e,null,-1)||this;return n._view=e,n}return Object(a.__extends)(e,t),e.prototype.detectChanges=function(){ms(this._view)},e.prototype.checkNoChanges=function(){!function(t){cn(!0);try{ms(t)}finally{cn(!1)}}(this._view)},Object.defineProperty(e.prototype,"context",{get:function(){return null},enumerable:!0,configurable:!0}),e}(cu);function du(t,e,n){return Qo||(Qo=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e}(t)),new Qo(te(e,n))}function fu(t,e,n,r){if(tu||(tu=function(t){function e(e,n,a,r,i,s){var o=t.call(this)||this;return o._declarationParentView=e,o.elementRef=n,o._tView=a,o._renderer=r,o._queries=i,o._injectorIndex=s,o}return Object(a.__extends)(e,t),e.prototype.createEmbeddedView=function(t,e,n,a,r){var i=function(t,e,n,a,r,i){var s=nn(),o=Qe();an(!0),tn(null);var u=si(n,t,e,4);return u[Mt]=n,r&&(u[wt]=r.createView()),ui(-1,u),t.firstTemplatePass&&(t.node.injectorIndex=i),an(s),tn(o),u}(this._tView,t,this._declarationParentView,0,this._queries,this._injectorIndex);e&&La(i,e,a,r,n.index),li(i,this._tView,t);var s=new cu(i,t,-1);return s._tViewNode=i[Ot],s},e}(t)),0===n.type){var i=r[n.index];return new tu(r,du(e,n,r),n.tViews,Xe()[At],i[wt],n.injectorIndex)}return null}function pu(t,e,n){if(re(t)){var a=t.directiveStart,r=ne(t.index,e);return new cu(r,n,a)}if(3===t.type){var i=ye(e);return new cu(i,i[kt],-1)}return null}var hu=function(){function t(t){this.nativeElement=t}return t.__NG_ELEMENT_ID__=function(){return bu(t)},t}(),gu=function(t){return du(t,Qe(),Xe())},bu=oo,mu=function(){return function(t,e,n,a,r,i){this.id=t,this.templateUrl=e,this.slotCount=n,this.encapsulation=a,this.styles=r,this.animations=i}}(),yu=function(){return function(){}}(),vu=function(){return function(){}}(),_u=function(){return function(){}}(),xu=function(){return function(){}}(),Tu=function(t){return t[t.Important=1]="Important",t[t.DashCase=2]="DashCase",t}({}),wu=function(){function t(){}return t.__NG_ELEMENT_ID__=function(){return Ou()},t}(),Su=function(){return function(t){var e=Xe()[At];if(wa(e))return e;throw new Error("Cannot inject Renderer2 when the application uses Renderer3!")}()},Ou=oo,Iu=function(t){return t[t.NONE=0]="NONE",t[t.HTML=1]="HTML",t[t.STYLE=2]="STYLE",t[t.SCRIPT=3]="SCRIPT",t[t.URL=4]="URL",t[t.RESOURCE_URL=5]="RESOURCE_URL",t}({}),Cu=function(){return function(){}}(),ku=function(){return function(t){this.full=t,this.major=t.split(".")[0],this.minor=t.split(".")[1],this.patch=t.split(".").slice(2).join(".")}}(),Nu=new ku("7.2.6"),Ru=function(t){function e(e){var n=t.call(this)||this;return n.ngModule=e,n}return Object(a.__extends)(e,t),e.prototype.resolveComponentFactory=function(t){var e=gt(t);return new Pu(e,this.ngModule)},e}(ru);function Au(t){var e=[];for(var n in t)t.hasOwnProperty(n)&&e.push({propName:t[n],templateName:n});return e}var Du=new w("ROOT_CONTEXT_TOKEN",{providedIn:"root",factory:function(){return Js(De(Eu))}}),Eu=new w("SCHEDULER_TOKEN",{providedIn:"root",factory:function(){return be}}),Lu={},Pu=function(t){function e(e,n){var a=t.call(this)||this;return a.componentDef=e,a.ngModule=n,a.componentType=e.type,a.selector=e.selectors[0][0],a.ngContentSelectors=[],a}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"inputs",{get:function(){return Au(this.componentDef.inputs)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"outputs",{get:function(){return Au(this.componentDef.outputs)},enumerable:!0,configurable:!0}),e.prototype.create=function(t,e,n,a){var r=void 0===n,i=(a=a||this.ngModule)?function(t,e){return{get:function(n,a){var r=t.get(n,Lu);return r!==Lu||a===Lu?r:e.get(n,a)}}}(t,a.injector):t,s=i.get(xu,Sa),o=i.get(Cu,null),u=r?Ti(this.selector,s.createRenderer(null,this.componentDef)):Ci(s,n),c=this.componentDef.onPush?136:132,l=r?Js():i.get(Du),d=s.createRenderer(u,this.componentDef);n&&u&&(wa(d)?d.setAttribute(u,"ng-version",Nu.full):u.setAttribute("ng-version",Nu.full));var f,p,h=si(null,Oi(-1,null,1,0,null,null,null),l,c,s,d,o,i),g=bn(h,null);try{s.begin&&s.begin();var b=Zs(u,this.componentDef,h,s,d);if(p=ee(0,h),e)for(var m=0,y=h[vt],v=p.projection=[],_=0;_<e.length;_++){for(var x=e[_],T=null,w=null,S=0;S<x.length;S++){y.firstTemplatePass&&(y.expandoStartIndex++,y.blueprint.splice(++m+qt,0,null),y.data.splice(m+qt,0,null),h.splice(m+qt,0,null));var O=oi(m,3,x[S],null,null);w?w.next=O:T=O,w=O}v.push(T)}f=Xs(b,this.componentDef,h,l,[Qs]),ds(h,qt,b),ii(h)}finally{yn(g),s.end&&s.end()}var I=new Mu(this.componentType,f,du(hu,p,h),h,p);return r&&(I.hostView._tViewNode.child=p),I},e}(Xo),Mu=function(t){function e(e,n,a,r,i){var s=t.call(this)||this;return s.location=a,s._rootLView=r,s._tNode=i,s.destroyCbs=[],s.instance=n,s.hostView=s.changeDetectorRef=new lu(r),s.hostView._tViewNode=ui(-1,r),s.componentType=e,s}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"injector",{get:function(){return new Mn(this._tNode,this._rootLView)},enumerable:!0,configurable:!0}),e.prototype.destroy=function(){this.destroyCbs.forEach(function(t){return t()}),this.destroyCbs=null,this.hostView.destroy()},e.prototype.onDestroy=function(t){this.destroyCbs.push(t)},e}(Zo),qu=!0,ju=!1;function Fu(){return ju=!0,qu}function zu(){if(ju)throw new Error("Cannot enable prod mode after platform setup.");qu=!1}var Gu=function(){function t(t){if(this.defaultDoc=t,this.inertDocument=this.defaultDoc.implementation.createHTMLDocument("sanitization-inert"),this.inertBodyElement=this.inertDocument.body,null==this.inertBodyElement){var e=this.inertDocument.createElement("html");this.inertDocument.appendChild(e),this.inertBodyElement=this.inertDocument.createElement("body"),e.appendChild(this.inertBodyElement)}this.inertBodyElement.innerHTML='<svg><g onload="this.parentNode.remove()"></g></svg>',!this.inertBodyElement.querySelector||this.inertBodyElement.querySelector("svg")?(this.inertBodyElement.innerHTML='<svg><p><style><img src="</style><img src=x onerror=alert(1)//">',this.getInertBodyElement=this.inertBodyElement.querySelector&&this.inertBodyElement.querySelector("svg img")&&function(){try{return!!window.DOMParser}catch(t){return!1}}()?this.getInertBodyElement_DOMParser:this.getInertBodyElement_InertDocument):this.getInertBodyElement=this.getInertBodyElement_XHR}return t.prototype.getInertBodyElement_XHR=function(t){t="<body><remove></remove>"+t+"</body>";try{t=encodeURI(t)}catch(a){return null}var e=new XMLHttpRequest;e.responseType="document",e.open("GET","data:text/html;charset=utf-8,"+t,!1),e.send(void 0);var n=e.response.body;return n.removeChild(n.firstChild),n},t.prototype.getInertBodyElement_DOMParser=function(t){t="<body><remove></remove>"+t+"</body>";try{var e=(new window.DOMParser).parseFromString(t,"text/html").body;return e.removeChild(e.firstChild),e}catch(n){return null}},t.prototype.getInertBodyElement_InertDocument=function(t){var e=this.inertDocument.createElement("template");return"content"in e?(e.innerHTML=t,e):(this.inertBodyElement.innerHTML=t,this.defaultDoc.documentMode&&this.stripCustomNsAttrs(this.inertBodyElement),this.inertBodyElement)},t.prototype.stripCustomNsAttrs=function(t){for(var e=t.attributes,n=e.length-1;0<n;n--){var a=e.item(n).name;"xmlns:ns1"!==a&&0!==a.indexOf("ns1:")||t.removeAttribute(a)}for(var r=t.firstChild;r;)r.nodeType===Node.ELEMENT_NODE&&this.stripCustomNsAttrs(r),r=r.nextSibling},t}(),Yu=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:\/?#]*(?:[\/?#]|$))/gi,Vu=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+\/]+=*$/i;function Hu(t){return(t=String(t)).match(Yu)||t.match(Vu)?t:(Fu()&&console.warn("WARNING: sanitizing unsafe URL value "+t+" (see http://g.co/ng/security#xss)"),"unsafe:"+t)}function Bu(t){return(t=String(t)).split(",").map(function(t){return Hu(t.trim())}).join(", ")}function Uu(t){var e,n,r={};try{for(var i=Object(a.__values)(t.split(",")),s=i.next();!s.done;s=i.next())r[s.value]=!0}catch(o){e={error:o}}finally{try{s&&!s.done&&(n=i.return)&&n.call(i)}finally{if(e)throw e.error}}return r}function Wu(){for(var t,e,n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];var i={};try{for(var s=Object(a.__values)(n),o=s.next();!o.done;o=s.next()){var u=o.value;for(var c in u)u.hasOwnProperty(c)&&(i[c]=!0)}}catch(l){t={error:l}}finally{try{o&&!o.done&&(e=s.return)&&e.call(s)}finally{if(t)throw t.error}}return i}var Ku,$u=Uu("area,br,col,hr,img,wbr"),Zu=Uu("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),Xu=Uu("rp,rt"),Ju=Wu(Xu,Zu),Qu=Wu($u,Wu(Zu,Uu("address,article,aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul")),Wu(Xu,Uu("a,abbr,acronym,audio,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video")),Ju),tc=Uu("background,cite,href,itemtype,longdesc,poster,src,xlink:href"),ec=Uu("srcset"),nc=Wu(tc,ec,Uu("abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,scope,scrolling,shape,size,sizes,span,srclang,start,summary,tabindex,target,title,translate,type,usemap,valign,value,vspace,width")),ac=function(){function t(){this.sanitizedSomething=!1,this.buf=[]}return t.prototype.sanitizeChildren=function(t){for(var e=t.firstChild,n=!0;e;)if(e.nodeType===Node.ELEMENT_NODE?n=this.startElement(e):e.nodeType===Node.TEXT_NODE?this.chars(e.nodeValue):this.sanitizedSomething=!0,n&&e.firstChild)e=e.firstChild;else for(;e;){e.nodeType===Node.ELEMENT_NODE&&this.endElement(e);var a=this.checkClobberedElement(e,e.nextSibling);if(a){e=a;break}e=this.checkClobberedElement(e,e.parentNode)}return this.buf.join("")},t.prototype.startElement=function(t){var e=t.nodeName.toLowerCase();if(!Qu.hasOwnProperty(e))return this.sanitizedSomething=!0,!1;this.buf.push("<"),this.buf.push(e);for(var n=t.attributes,a=0;a<n.length;a++){var r=n.item(a),i=r.name,s=i.toLowerCase();if(nc.hasOwnProperty(s)){var o=r.value;tc[s]&&(o=Hu(o)),ec[s]&&(o=Bu(o)),this.buf.push(" ",i,'="',sc(o),'"')}else this.sanitizedSomething=!0}return this.buf.push(">"),!0},t.prototype.endElement=function(t){var e=t.nodeName.toLowerCase();Qu.hasOwnProperty(e)&&!$u.hasOwnProperty(e)&&(this.buf.push("</"),this.buf.push(e),this.buf.push(">"))},t.prototype.chars=function(t){this.buf.push(sc(t))},t.prototype.checkClobberedElement=function(t,e){if(e&&(t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_CONTAINED_BY)===Node.DOCUMENT_POSITION_CONTAINED_BY)throw new Error("Failed to sanitize html because the element is clobbered: "+t.outerHTML);return e},t}(),rc=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,ic=/([^\#-~ |!])/g;function sc(t){return t.replace(/&/g,"&amp;").replace(rc,function(t){return"&#"+(1024*(t.charCodeAt(0)-55296)+(t.charCodeAt(1)-56320)+65536)+";"}).replace(ic,function(t){return"&#"+t.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function oc(t,e){var n=null;try{Ku=Ku||new Gu(t);var a=e?String(e):"";n=Ku.getInertBodyElement(a);var r=5,i=a;do{if(0===r)throw new Error("Failed to sanitize html because the input is unstable");r--,a=i,i=n.innerHTML,n=Ku.getInertBodyElement(a)}while(a!==i);var s=new ac,o=s.sanitizeChildren(uc(n)||n);return Fu()&&s.sanitizedSomething&&console.warn("WARNING: sanitizing HTML stripped some content, see http://g.co/ng/security#xss"),o}finally{if(n)for(var u=uc(n)||n;u.firstChild;)u.removeChild(u.firstChild)}}function uc(t){return"content"in t&&function(t){return t.nodeType===Node.ELEMENT_NODE&&"TEMPLATE"===t.nodeName}(t)?t.content:null}var cc={marker:"element"},lc={marker:"comment"},dc="\ufffd",fc=/^\s*(\ufffd\d+:?\d*\ufffd)\s*,\s*(select|plural)\s*,/,pc=/\ufffd\/?\*(\d+:\d+)\ufffd/gi,hc=/\ufffd(\/?[#*]\d+):?\d*\ufffd/gi,gc=/\ufffd(\d+):?\d*\ufffd/gi,bc=/({\s*\ufffd\d+:?\d*\ufffd\s*,\s*\S{6}\s*,[\s\S]*})/gi,mc=/\[(\ufffd.+?\ufffd?)\]/g,yc=/({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g,vc=/\ufffdI18N_EXP_(ICU(_\d+)?)\ufffd/g;function _c(t){if(!t)return[];var e,n=0,a=[],r=[],i=/[{}]/g;for(i.lastIndex=0;e=i.exec(t);){var s=e.index;if("}"==e[0]){if(a.pop(),0==a.length){var o=t.substring(n,s);fc.test(o)?r.push(xc(o)):o&&r.push(o),n=s+1}}else{if(0==a.length){var u=t.substring(n,s);r.push(u),n=s+1}a.push("{")}}var c=t.substring(n);return""!=c&&r.push(c),r}function xc(t){for(var e=[],n=[],a=1,r=0,i=_c(t=t.replace(fc,function(t,e,n){return a="select"===n?0:1,r=parseInt(e.substr(1),10),""})),s=0;s<i.length;){var o=i[s++].trim();1===a&&(o=o.replace(/\s*(?:=)?(\w+)\s*/,"$1")),o.length&&e.push(o);var u=_c(i[s++]);u.length&&n.push(u)}return c=e.indexOf("other"),l='Missing key "other" in ICU statement.',c<=-1&&function(t){throw new Error("ASSERTION ERROR: "+t)}(l),{type:a,mainBinding:r,cases:e,values:n};var c,l}function Tc(t){for(var e,n,a="",r=0,i=!1;null!==(e=pc.exec(t));)i?e[0]===dc+"/*"+n+dc&&(r=e.index,i=!1):(a+=t.substring(r,e.index+e[0].length),n=e[1],i=!0);return a+t.substr(r)}function wc(t,e,n,a){void 0===a&&(a=null);for(var r=[null,null],i=t.split(gc),s=0,o=0;o<i.length;o++){var u=i[o];if(1&o){var c=parseInt(u,10);r.push(-1-c),s|=Cc(c)}else""!==u&&r.push(u)}return r.push(e<<2|(n?1:0)),n&&r.push(n,a),r[0]=s,r[1]=r.length-2,r}function Sc(t,e){var n;void 0===e&&(e=0),e|=Cc(t.mainBinding);for(var a=0;a<t.values.length;a++)for(var r=t.values[a],i=0;i<r.length;i++){var s=r[i];if("string"==typeof s)for(;n=gc.exec(s);)e|=Cc(parseInt(n[1],10));else e=Sc(s,e)}return e}var Oc=[],Ic=-1;function Cc(t){return 1<<Math.min(t,31)}var kc=[];function Nc(t,e,n){var a=Xe()[vt];Oc[++Ic]=t,a.firstTemplatePass&&null===a.data[t+qt]&&function(t,e,n,a){var r=Xe(),i=t.blueprint.length-qt,s=Qe(),o=nn()?Qe():s&&s.parent,u=o&&o!==r[Ot]?o.index-qt:e,c=0;kc[c]=u;var l=[];e>0&&s!==o&&l.push(s.index<<3|0);for(var d=[],f=[],p=function(t,e){if("number"!=typeof e)return Tc(t);var n=t.indexOf(":"+e+dc)+2+e.toString().length,a=t.search(new RegExp(dc+"\\/\\*\\d+:"+e+dc));return Tc(t.substring(n,a))}(n,a).split(hc),h=0;h<p.length;h++){var g=p[h];if(1&h)if("/"===g.charAt(0)){if("#"===g.charAt(1)){var b=parseInt(g.substr(2),10);u=kc[--c],l.push(b<<3|5)}}else b=parseInt(g.substr(1),10),l.push(b<<3|0,u<<17|1),"#"===g.charAt(0)&&(kc[++c]=u=b);else for(var m=g.split(bc),y=0;y<m.length;y++)if(g=m[y],1&y){ci(r);var v=t.blueprint.length-1-qt;l.push(lc,"",u<<17|1);var _=xc(g.substr(1,g.length-2)),x=Sc(_);Vc(f,_,v,v);var T=f.length-1;d.push(Cc(_.mainBinding),3,-1-_.mainBinding,v<<2|2,T,x,2,v<<2|3,T)}else if(""!==g){var w=g.match(gc);ci(r),l.push(w?"":g,u<<17|1),w&&me(wc(g,t.blueprint.length-1-qt),d)}}t.data[e+qt]={vars:t.blueprint.length-qt-i,expandoStartIndex:i,create:l,update:d,icus:f.length?f:null}}(a,t,e,n)}function Rc(t,e,n){var a=Xe();n||(n=e),n===e&&t!==e.child?(t.next=e.child,e.child=t):n!==e&&t!==n.next?(t.next=n.next,n.next=t):t.next=null,e!==a[Ot]&&(t.parent=e),Ba(te(t,a),t,a);var r=a[t.index];return 0!==t.type&&se(r)&&Ba(r[zt],t,a),t}function Ac(t,e){var n={},a=t.replace(mc,function(t,e){if(n[e]||(n[e]=e.split("|")),!n[e].length)throw new Error("i18n postprocess: unmatched placeholder - "+e);return n[e].shift()});if(Object.keys(n).some(function(t){return!!n[t].length}))throw new Error("i18n postprocess: unmatched values - "+JSON.stringify(n));return Object.keys(e).length?a=(a=a.replace(yc,function(t,n,a,r,i,s){return e.hasOwnProperty(a)?""+n+e[a]+s:t})).replace(vc,function(t,n){if(e.hasOwnProperty(n)){var a=e[n];if(!a.length)throw new Error("i18n postprocess: unmatched ICU - "+t+" with key: "+n);return a.shift()}return t}):a}function Dc(){!function(t){for(var e=Xe(),n=Oc[Ic--],a=t.data[n+qt],r=Qe(),i=Ec(n,a.create,a.expandoStartIndex,e),s=n+1;s<=r.index-qt;s++)-1===i.indexOf(s)&&Lc(s,e)}(Xe()[vt])}function Ec(t,e,n,a){for(var r=Xe()[At],i=null,s=null,o=[],u=0;u<e.length;u++){var c=e[u];if("string"==typeof c)s=i,i=oi(n++,3,Da(c,r),null,null),an(!1);else if("number"==typeof c)switch(7&c){case 1:var l=c>>>17,d=void 0;s=Rc(i,d=l===t?a[Ot]:ee(l,a),s),d.next=null;break;case 0:var f=c>>>3;o.push(f),s=i,(i=ee(f,a))&&(tn(i),3===i.type&&an(!0));break;case 5:s=i=ee(c>>>3,a),tn(i),an(!1);break;case 4:Ri(c>>>3,e[++u],e[++u]);break;default:throw new Error('Unable to determine the type of mutate operation for "'+c+'"')}else switch(c){case lc:var p=e[++u],h=r.createComment(p);s=i,i=oi(n++,5,h,null,null),Yn(h,a),i.activeCaseIndex=null,an(!1);break;case cc:var g=e[++u];s=i,i=oi(n++,3,r.createElement(g),g,null);break;default:throw new Error('Unable to determine the type of mutate operation for "'+c+'"')}}return an(!1),o}function Lc(t,e){var n=ee(t,e);Ka(n,Qt(t,e)||null,e),n.detached=!0;var a=Ls(t);if(se(a)){var r=a;0!==n.type&&Ka(n,r[zt]||null,e),r[Gt]=null}}function Pc(t,e,n){Nc(t,e,n),Dc()}function Mc(t,e){var n=Xe()[vt];n.firstTemplatePass&&null===n.data[t+qt]&&function(t,e,n){for(var a=Qe().index-qt,r=[],i=0;i<n.length;i+=2)for(var s=n[i],o=n[i+1].split(bc),u=0;u<o.length;u++){var c=o[u];1&u||""!==c&&(c.match(gc)?me(wc(c,a,s),r):Ri(a,s,c))}t.data[e+qt]=r}(n,t,e)}var qc=0,jc=0;function Fc(t){t!==ha&&(qc|=1<<jc),jc++}function zc(t){if(jc){var e=Xe(),n=e[vt].data[t+qt],a=void 0,r=null;Array.isArray(n)?a=n:(a=n.update,r=n.icus),function t(e,n,a,r,i,s){void 0===s&&(s=!1);for(var o=!1,u=0;u<e.length;u++){var c=e[u],l=e[++u];if(s||c&r)for(var d="",f=u+1;f<=u+l;f++){var p=e[f];if("string"==typeof p)d+=p;else if("number"==typeof p)if(p<0)d+=Zt(i[a-p]);else{var h=p>>>2;switch(3&p){case 1:Ri(h,e[++f],d,e[++f]);break;case 0:Bi(h,d);break;case 2:var g=e[++f],b=n[g],m=ee(h,i);if(null!==m.activeCaseIndex)for(var y=b.remove[m.activeCaseIndex],v=0;v<y.length;v++){var _=y[v];switch(7&_){case 3:Lc(_>>>3,i);break;case 6:var x=ee(y[v+1]>>>3,i).activeCaseIndex;null!==x&&me(n[_>>>3].remove[x],y)}}var T=Yc(b,d);m.activeCaseIndex=-1!==T?T:null,Ec(-1,b.create[T],b.expandoStartIndex,i),o=!0;break;case 3:b=n[g=e[++f]],m=ee(h,i),t(b.update[m.activeCaseIndex],n,a,r,i,o)}}}u+=l}}(a,r,e[It]-jc-1,qc,e),qc=0,jc=0}}var Gc=function(t){return t[t.Zero=0]="Zero",t[t.One=1]="One",t[t.Two=2]="Two",t[t.Few=3]="Few",t[t.Many=4]="Many",t[t.Other=5]="Other",t}({});function Yc(t,e){var n=t.cases.indexOf(e);if(-1===n)switch(t.type){case 1:var a=function(t,n){switch(function(t,e){"string"==typeof e&&(e=parseInt(e,10));var n=e,a=n.toString().replace(/^[^.]*\.?/,""),r=Math.floor(Math.abs(n)),i=a.length,s=parseInt(a,10),o=parseInt(n.toString().replace(/^[^.]*\.?|0+$/g,""),10)||0;switch(t.split("-")[0].toLowerCase()){case"af":case"asa":case"az":case"bem":case"bez":case"bg":case"brx":case"ce":case"cgg":case"chr":case"ckb":case"ee":case"el":case"eo":case"es":case"eu":case"fo":case"fur":case"gsw":case"ha":case"haw":case"hu":case"jgo":case"jmc":case"ka":case"kk":case"kkj":case"kl":case"ks":case"ksb":case"ky":case"lb":case"lg":case"mas":case"mgo":case"ml":case"mn":case"nb":case"nd":case"ne":case"nn":case"nnh":case"nyn":case"om":case"or":case"os":case"ps":case"rm":case"rof":case"rwk":case"saq":case"seh":case"sn":case"so":case"sq":case"ta":case"te":case"teo":case"tk":case"tr":case"ug":case"uz":case"vo":case"vun":case"wae":case"xog":return 1===n?Gc.One:Gc.Other;case"ak":case"ln":case"mg":case"pa":case"ti":return n===Math.floor(n)&&n>=0&&n<=1?Gc.One:Gc.Other;case"am":case"as":case"bn":case"fa":case"gu":case"hi":case"kn":case"mr":case"zu":return 0===r||1===n?Gc.One:Gc.Other;case"ar":return 0===n?Gc.Zero:1===n?Gc.One:2===n?Gc.Two:n%100===Math.floor(n%100)&&n%100>=3&&n%100<=10?Gc.Few:n%100===Math.floor(n%100)&&n%100>=11&&n%100<=99?Gc.Many:Gc.Other;case"ast":case"ca":case"de":case"en":case"et":case"fi":case"fy":case"gl":case"it":case"nl":case"sv":case"sw":case"ur":case"yi":return 1===r&&0===i?Gc.One:Gc.Other;case"be":return n%10==1&&n%100!=11?Gc.One:n%10===Math.floor(n%10)&&n%10>=2&&n%10<=4&&!(n%100>=12&&n%100<=14)?Gc.Few:n%10==0||n%10===Math.floor(n%10)&&n%10>=5&&n%10<=9||n%100===Math.floor(n%100)&&n%100>=11&&n%100<=14?Gc.Many:Gc.Other;case"br":return n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?Gc.One:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?Gc.Two:n%10===Math.floor(n%10)&&(n%10>=3&&n%10<=4||n%10==9)&&!(n%100>=10&&n%100<=19||n%100>=70&&n%100<=79||n%100>=90&&n%100<=99)?Gc.Few:0!==n&&n%1e6==0?Gc.Many:Gc.Other;case"bs":case"hr":case"sr":return 0===i&&r%10==1&&r%100!=11||s%10==1&&s%100!=11?Gc.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)||s%10===Math.floor(s%10)&&s%10>=2&&s%10<=4&&!(s%100>=12&&s%100<=14)?Gc.Few:Gc.Other;case"cs":case"sk":return 1===r&&0===i?Gc.One:r===Math.floor(r)&&r>=2&&r<=4&&0===i?Gc.Few:0!==i?Gc.Many:Gc.Other;case"cy":return 0===n?Gc.Zero:1===n?Gc.One:2===n?Gc.Two:3===n?Gc.Few:6===n?Gc.Many:Gc.Other;case"da":return 1===n||0!==o&&(0===r||1===r)?Gc.One:Gc.Other;case"dsb":case"hsb":return 0===i&&r%100==1||s%100==1?Gc.One:0===i&&r%100==2||s%100==2?Gc.Two:0===i&&r%100===Math.floor(r%100)&&r%100>=3&&r%100<=4||s%100===Math.floor(s%100)&&s%100>=3&&s%100<=4?Gc.Few:Gc.Other;case"ff":case"fr":case"hy":case"kab":return 0===r||1===r?Gc.One:Gc.Other;case"fil":return 0===i&&(1===r||2===r||3===r)||0===i&&r%10!=4&&r%10!=6&&r%10!=9||0!==i&&s%10!=4&&s%10!=6&&s%10!=9?Gc.One:Gc.Other;case"ga":return 1===n?Gc.One:2===n?Gc.Two:n===Math.floor(n)&&n>=3&&n<=6?Gc.Few:n===Math.floor(n)&&n>=7&&n<=10?Gc.Many:Gc.Other;case"gd":return 1===n||11===n?Gc.One:2===n||12===n?Gc.Two:n===Math.floor(n)&&(n>=3&&n<=10||n>=13&&n<=19)?Gc.Few:Gc.Other;case"gv":return 0===i&&r%10==1?Gc.One:0===i&&r%10==2?Gc.Two:0!==i||r%100!=0&&r%100!=20&&r%100!=40&&r%100!=60&&r%100!=80?0!==i?Gc.Many:Gc.Other:Gc.Few;case"he":return 1===r&&0===i?Gc.One:2===r&&0===i?Gc.Two:0!==i||n>=0&&n<=10||n%10!=0?Gc.Other:Gc.Many;case"is":return 0===o&&r%10==1&&r%100!=11||0!==o?Gc.One:Gc.Other;case"ksh":return 0===n?Gc.Zero:1===n?Gc.One:Gc.Other;case"kw":case"naq":case"se":case"smn":return 1===n?Gc.One:2===n?Gc.Two:Gc.Other;case"lag":return 0===n?Gc.Zero:0!==r&&1!==r||0===n?Gc.Other:Gc.One;case"lt":return n%10!=1||n%100>=11&&n%100<=19?n%10===Math.floor(n%10)&&n%10>=2&&n%10<=9&&!(n%100>=11&&n%100<=19)?Gc.Few:0!==s?Gc.Many:Gc.Other:Gc.One;case"lv":case"prg":return n%10==0||n%100===Math.floor(n%100)&&n%100>=11&&n%100<=19||2===i&&s%100===Math.floor(s%100)&&s%100>=11&&s%100<=19?Gc.Zero:n%10==1&&n%100!=11||2===i&&s%10==1&&s%100!=11||2!==i&&s%10==1?Gc.One:Gc.Other;case"mk":return 0===i&&r%10==1||s%10==1?Gc.One:Gc.Other;case"mt":return 1===n?Gc.One:0===n||n%100===Math.floor(n%100)&&n%100>=2&&n%100<=10?Gc.Few:n%100===Math.floor(n%100)&&n%100>=11&&n%100<=19?Gc.Many:Gc.Other;case"pl":return 1===r&&0===i?Gc.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)?Gc.Few:0===i&&1!==r&&r%10===Math.floor(r%10)&&r%10>=0&&r%10<=1||0===i&&r%10===Math.floor(r%10)&&r%10>=5&&r%10<=9||0===i&&r%100===Math.floor(r%100)&&r%100>=12&&r%100<=14?Gc.Many:Gc.Other;case"pt":return n===Math.floor(n)&&n>=0&&n<=2&&2!==n?Gc.One:Gc.Other;case"ro":return 1===r&&0===i?Gc.One:0!==i||0===n||1!==n&&n%100===Math.floor(n%100)&&n%100>=1&&n%100<=19?Gc.Few:Gc.Other;case"ru":case"uk":return 0===i&&r%10==1&&r%100!=11?Gc.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)?Gc.Few:0===i&&r%10==0||0===i&&r%10===Math.floor(r%10)&&r%10>=5&&r%10<=9||0===i&&r%100===Math.floor(r%100)&&r%100>=11&&r%100<=14?Gc.Many:Gc.Other;case"shi":return 0===r||1===n?Gc.One:n===Math.floor(n)&&n>=2&&n<=10?Gc.Few:Gc.Other;case"si":return 0===n||1===n||0===r&&1===s?Gc.One:Gc.Other;case"sl":return 0===i&&r%100==1?Gc.One:0===i&&r%100==2?Gc.Two:0===i&&r%100===Math.floor(r%100)&&r%100>=3&&r%100<=4||0!==i?Gc.Few:Gc.Other;case"tzm":return n===Math.floor(n)&&n>=0&&n<=1||n===Math.floor(n)&&n>=11&&n<=99?Gc.One:Gc.Other;default:return Gc.Other}}("en-US",e)){case Gc.Zero:return"zero";case Gc.One:return"one";case Gc.Two:return"two";case Gc.Few:return"few";case Gc.Many:return"many";default:return"other"}}();-1===(n=t.cases.indexOf(a))&&"other"!==a&&(n=t.cases.indexOf("other"));break;case 0:n=t.cases.indexOf("other")}return n}function Vc(t,e,n,r){for(var i=[],s=[],o=[],u=[],c=[],l=0;l<e.values.length;l++){for(var d=e.values[l],f=[],p=0;p<d.length;p++){var h=d[p];if("string"!=typeof h){var g=f.push(h)-1;d[p]="\x3c!--\ufffd"+g+"\ufffd--\x3e"}}var b=Hc(d.join(""),n,f,t,r);i.push(b.create),s.push(b.remove),o.push(b.update),u.push(b.vars),c.push(b.childIcus)}t.push({type:e.type,vars:u,expandoStartIndex:r+1,childIcus:c,cases:e.cases,create:i,remove:s,update:o});var m=Xe(),y=Math.max.apply(Math,Object(a.__spread)(u));for(l=0;l<y;l++)ci(m)}function Hc(t,e,n,r,i){var s=new Gu(document).getInertBodyElement(t);if(!s)throw new Error("Unable to generate inert body element");var o={vars:0,childIcus:[],create:[],remove:[],update:[]};return function t(e,n,r,i,s,o){if(e){for(var u=[];e;){var c=e.nextSibling,l=o+ ++n.vars;switch(e.nodeType){case Node.ELEMENT_NODE:var d=e,f=d.tagName.toLowerCase();if(Qu.hasOwnProperty(f)){n.create.push(cc,f,r<<17|1);for(var p=d.attributes,h=0;h<p.length;h++){var g=p.item(h),b=g.name.toLowerCase();g.value.match(gc)?nc.hasOwnProperty(b)&&me(tc[b]?wc(g.value,l,g.name,Hu):ec[b]?wc(g.value,l,g.name,Bu):wc(g.value,l,g.name),n.update):n.create.push(l<<3|4,g.name,g.value)}t(e.firstChild,n,l,i,s,o),n.remove.push(l<<3|3)}else n.vars--;break;case Node.TEXT_NODE:var m=e.textContent||"",y=m.match(gc);n.create.push(y?"":m,r<<17|1),n.remove.push(l<<3|3),y&&me(wc(m,l),n.update);break;case Node.COMMENT_NODE:var v=Bc.exec(e.textContent||"");if(v){var _=parseInt(v[1],10);n.create.push(lc,"",r<<17|1),u.push([x=i[_],l])}else n.vars--;break;default:n.vars--}e=c}for(h=0;h<u.length;h++){var x,T=u[h][1];Vc(s,x=u[h][0],T,o+n.vars);var w=s.length-1;n.vars+=Math.max.apply(Math,Object(a.__spread)(s[w].vars)),n.childIcus.push(w);var S=Sc(x);n.update.push(Cc(x.mainBinding),3,-1-x.mainBinding,T<<2|2,w,S,2,T<<2|3,w),n.remove.push(w<<3|6,T<<3|3)}}}((uc(s)||s).firstChild,o,e,n,r,i),o}var Bc=/\ufffd(\d+)\ufffd/,Uc={provide:ru,useClass:Ru,deps:[ou]},Wc=function(t){function e(e,n){var a=t.call(this)||this;a._parent=n,a._bootstrapComponents=[],a.injector=a,a.destroyCbs=[];var r=yt(e);return a._bootstrapComponents=r.bootstrap,a._r3Injector=Po(e,n,[{provide:ou,useValue:a},Uc]),a.instance=a.get(e),a}return Object(a.__extends)(e,t),e.prototype.get=function(t,e,n){return void 0===e&&(e=ho.THROW_IF_NOT_FOUND),void 0===n&&(n=Ce.Default),t===ho||t===ou||t===fo?this:this._r3Injector.get(t,e,n)},Object.defineProperty(e.prototype,"componentFactoryResolver",{get:function(){return this.get(ru)},enumerable:!0,configurable:!0}),e.prototype.destroy=function(){this.destroyCbs.forEach(function(t){return t()}),this.destroyCbs=null},e.prototype.onDestroy=function(t){this.destroyCbs.push(t)},e}(ou),Kc=function(t){function e(e){var n=t.call(this)||this;return n.moduleType=e,n}return Object(a.__extends)(e,t),e.prototype.create=function(t){return new Wc(this.moduleType,t)},e}(uu);function $c(t,e,n,r){var i,s=t;null!==e&&(void 0!==s.decorators?(i=s.decorators).push.apply(i,Object(a.__spread)(e)):s.decorators=e),null!==n&&(s.ctorParameters=n),null!==r&&(s.propDecorators=void 0!==s.propDecorators?Object(a.__assign)({},s.propDecorators,r):r)}function Zc(t,e,n){var a=hn()+t,r=Xe();return rn()?ga(r,a,n?e.call(n):e()):ba(r,a)}function Xc(t,e,n,a){var r=Xe(),i=hn()+t;return ma(r,i,n)?ga(r,i+1,a?e.call(a,n):e(n)):ba(r,i+1)}function Jc(t,e,n,a,r){var i=hn()+t,s=Xe();return ya(s,i,n,a)?ga(s,i+2,r?e.call(r,n,a):e(n,a)):ba(s,i+2)}function Qc(t,e,n,a,r,i){var s=hn()+t,o=Xe();return va(o,s,n,a,r)?ga(o,s+3,i?e.call(i,n,a,r):e(n,a,r)):ba(o,s+3)}function tl(t,e,n,a,r,i,s){var o=hn()+t,u=Xe();return _a(u,o,n,a,r,i)?ga(u,o+4,s?e.call(s,n,a,r,i):e(n,a,r,i)):ba(u,o+4)}function el(t,e,n,a,r,i,s,o){var u=hn()+t,c=Xe(),l=_a(c,u,n,a,r,i);return ma(c,u+4,s)||l?ga(c,u+5,o?e.call(o,n,a,r,i,s):e(n,a,r,i,s)):ba(c,u+5)}function nl(t,e,n,a,r,i,s,o,u){var c=hn()+t,l=Xe(),d=_a(l,c,n,a,r,i);return ya(l,c+4,s,o)||d?ga(l,c+6,u?e.call(u,n,a,r,i,s,o):e(n,a,r,i,s,o)):ba(l,c+6)}function al(t,e,n,a,r,i,s,o,u,c){var l=hn()+t,d=Xe(),f=_a(d,l,n,a,r,i);return va(d,l+4,s,o,u)||f?ga(d,l+7,c?e.call(c,n,a,r,i,s,o,u):e(n,a,r,i,s,o,u)):ba(d,l+7)}function rl(t,e,n,a,r,i,s,o,u,c,l){var d=hn()+t,f=Xe(),p=_a(f,d,n,a,r,i);return _a(f,d+4,s,o,u,c)||p?ga(f,d+8,l?e.call(l,n,a,r,i,s,o,u,c):e(n,a,r,i,s,o,u,c)):ba(f,d+8)}function il(t,e,n,a){for(var r=hn()+t,i=!1,s=Xe(),o=0;o<n.length;o++)ma(s,r++,n[o])&&(i=!0);return i?ga(s,r,e.apply(a,n)):ba(s,r)}function sl(t,e){var n,a=Xe()[vt],r=t+qt;a.firstTemplatePass?(n=function(t,e){if(e)for(var n=e.length-1;n>=0;n--){var a=e[n];if(t===a.name)return a}throw new Error("The pipe '"+t+"' could not be found!")}(e,a.pipeRegistry),a.data[r]=n,n.onDestroy&&(a.pipeDestroyHooks||(a.pipeDestroyHooks=[])).push(r,n.onDestroy)):n=a.data[r];var i=n.factory(null);return As(t,i),i}function ol(t,e,n){var a=Ls(t);return pl(fl(t)?Xc(e,a.transform,n,a):a.transform(n))}function ul(t,e,n,a){var r=Ls(t);return pl(fl(t)?Jc(e,r.transform,n,a,r):r.transform(n,a))}function cl(t,e,n,a,r){var i=Ls(t);return pl(fl(t)?Qc(e,i.transform,n,a,r,i):i.transform(n,a,r))}function ll(t,e,n,a,r,i){var s=Ls(t);return pl(fl(t)?tl(e,s.transform,n,a,r,i,s):s.transform(n,a,r,i))}function dl(t,e,n){var a=Ls(t);return pl(fl(t)?il(e,a.transform,n,a):a.transform.apply(a,n))}function fl(t){return Xe()[vt].data[t+qt].pure}function pl(t){return ca.isWrapped(t)&&(t=ca.unwrap(t),Xe()[hn()]=ha),t}var hl=function(t){function e(e){void 0===e&&(e=!1);var n=t.call(this)||this;return n.__isAsync=e,n}return Object(a.__extends)(e,t),e.prototype.emit=function(e){t.prototype.next.call(this,e)},e.prototype.subscribe=function(e,n,a){var i,s=function(t){return null},o=function(){return null};e&&"object"==typeof e?(i=this.__isAsync?function(t){setTimeout(function(){return e.next(t)})}:function(t){e.next(t)},e.error&&(s=this.__isAsync?function(t){setTimeout(function(){return e.error(t)})}:function(t){e.error(t)}),e.complete&&(o=this.__isAsync?function(){setTimeout(function(){return e.complete()})}:function(){e.complete()})):(i=this.__isAsync?function(t){setTimeout(function(){return e(t)})}:function(t){e(t)},n&&(s=this.__isAsync?function(t){setTimeout(function(){return n(t)})}:function(t){n(t)}),a&&(o=this.__isAsync?function(){setTimeout(function(){return a()})}:function(){a()}));var u=t.prototype.subscribe.call(this,i,s,o);return e instanceof r.a&&e.add(u),u},e}(i.a),gl=function(){function t(){}return t.__NG_ELEMENT_ID__=function(){return ml(t,hu)},t}(),bl=function(t,e){return fu(t,e,Qe(),Xe())},ml=oo,yl=function(){function t(t,e,n){this.parent=t,this.shallow=e,this.deep=n}return t.prototype.track=function(t,e,n,a){n?this.deep=Rl(this.deep,t,e,null!=a?a:null):this.shallow=Rl(this.shallow,t,e,null!=a?a:null)},t.prototype.clone=function(){return new t(this,null,this.deep)},t.prototype.container=function(){var e=vl(this.shallow),n=vl(this.deep);return e||n?new t(this,e,n):null},t.prototype.createView=function(){var e=_l(this.shallow),n=_l(this.deep);return e||n?new t(this,e,n):null},t.prototype.insertView=function(t){xl(t,this.shallow),xl(t,this.deep)},t.prototype.addNode=function(t){return Cl(this.deep,t),ae(t)?(Cl(this.shallow,t),t.parent&&ae(t.parent)&&Cl(this.parent.shallow,t),this.parent):(function(t){return null===t.parent||ae(t.parent)}(t)&&Cl(this.shallow,t),this)},t.prototype.removeView=function(){Tl(this.shallow),Tl(this.deep)},t}();function vl(t){for(var e=null;t;){var n=[];t.values.push(n),e={next:e,list:t.list,predicate:t.predicate,values:n,containerValues:null},t=t.next}return e}function _l(t){for(var e=null;t;)e={next:e,list:t.list,predicate:t.predicate,values:[],containerValues:t.values},t=t.next;return e}function xl(t,e){for(;e;)e.containerValues.splice(t,0,e.values),e=e.next}function Tl(t){for(;t;){var e=t.containerValues,n=e.indexOf(t.values);e.splice(n,1)[0].length&&t.list.setDirty(),t=t.next}}function wl(t,e){var n=t.localNames;if(n)for(var a=0;a<n.length;a+=2)if(n[a]===e)return n[a+1];return null}function Sl(t,e,n){var a=t[y];if("function"==typeof a)return a();var r=Dn(e,n,t,!1,!1);return null!==r?En(n[vt].data,n,r,e):null}function Ol(t,e,n,a){var r=t[y]();return a?r?Sl(a,e,n):null:r}function Il(t,e,n,a){return n?Sl(n,t,e):a>-1?En(e[vt].data,e,a,t):function(t,e){return 3===t.type||4===t.type?du(hu,t,e):0===t.type?fu(gl,hu,t,e):null}(t,e)}function Cl(t,e){for(var n=Xe();t;){var a=t.predicate,r=a.type;if(r){var i=null;r===gl?i=Ol(r,e,n,a.read):null!==(u=Dn(e,n,r,!1,!1))&&(i=Il(e,n,a.read,u)),null!==i&&kl(t,i)}else for(var s=a.selector,o=0;o<s.length;o++){var u;null!==(u=wl(e,s[o]))&&null!==(i=Il(e,n,a.read,u))&&kl(t,i)}t=t.next}}function kl(t,e){t.values.push(e),t.list.setDirty()}function Nl(t,e){var n=Array.isArray(t);return{type:n?null:t,selector:n?t:null,read:e}}function Rl(t,e,n,a){return{next:t,list:e,predicate:Nl(n,a),values:e._valuesTree,containerValues:null}}var Al=function(){function t(){this.dirty=!0,this.changes=new hl,this._values=[],this._valuesTree=[]}return Object.defineProperty(t.prototype,"length",{get:function(){return this._values.length},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"first",{get:function(){var t=this._values;return t.length?t[0]:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"last",{get:function(){var t=this._values;return t.length?t[t.length-1]:null},enumerable:!0,configurable:!0}),t.prototype.map=function(t){return this._values.map(t)},t.prototype.filter=function(t){return this._values.filter(t)},t.prototype.find=function(t){return this._values.find(t)},t.prototype.reduce=function(t,e){return this._values.reduce(t,e)},t.prototype.forEach=function(t){this._values.forEach(t)},t.prototype.some=function(t){return this._values.some(t)},t.prototype.toArray=function(){return this._values.slice(0)},t.prototype[U()]=function(){return this._values[U()]()},t.prototype.toString=function(){return this._values.toString()},t.prototype.reset=function(t){this._values=function(t){for(var e=[],n=0;n<t.length;){var a=t[n];Array.isArray(a)?a.length>0?(t=a.concat(t.slice(n+1)),n=0):n++:(e.push(a),n++)}return e}(t),this.dirty=!1},t.prototype.notifyOnChanges=function(){this.changes.emit(this)},t.prototype.setDirty=function(){this.dirty=!0},t.prototype.destroy=function(){this.changes.complete(),this.changes.unsubscribe()},t}();function Dl(t,e,n,a){var r,i,s,o=new Al;return(r=yl,i=Xe(),s=i[wt],He&&He!==i[Ot]&&!ae(He)&&(s&&(s=i[wt]=s.clone()),He.flags|=4),s||(i[wt]=new r(null,null,null))).track(o,e,n,a),function(t,e,n){var a=Gs(t);a.push(e),t[vt].firstTemplatePass&&Ys(t).push(n,a.length-1)}(Xe(),o,o.destroy),null!=t&&As(t,o),o}function El(t){return!!t.dirty&&(t.reset(t._valuesTree),t.notifyOnChanges(),!0)}function Ll(t,e){return fu(gl,hu,t,e)}var Pl="__SANITIZER_TRUSTED_BRAND__";function Ml(t,e){return t instanceof String&&t[Pl]===e}function ql(t){return Yl(t,"Html")}function jl(t){return Yl(t,"Style")}function Fl(t){return Yl(t,"Script")}function zl(t){return Yl(t,"Url")}function Gl(t){return Yl(t,"ResourceUrl")}function Yl(t,e){var n=new String(t);return n[Pl]=e,n}var Vl=new RegExp("^([-,.\"'%_!# a-zA-Z0-9]+|(?:(?:matrix|translate|scale|rotate|skew|perspective)(?:X|Y|3d)?|(?:rgb|hsl)a?|(?:repeating-)?(?:linear|radial)-gradient|(?:calc|attr))\\([-0-9.%, #a-zA-Z]+\\))$","g"),Hl=/^url\(([^)]+)\)$/;function Bl(t){if(!(t=String(t).trim()))return"";var e=t.match(Hl);return e&&Hu(e[1])===e[1]||t.match(Vl)&&function(t){for(var e=!0,n=!0,a=0;a<t.length;a++){var r=t.charAt(a);"'"===r&&n?e=!e:'"'===r&&e&&(n=!n)}return e&&n}(t)?t:(Fu()&&console.warn("WARNING: sanitizing unsafe style value "+t+" (see http://g.co/ng/security#xss)."),"unsafe")}function Ul(t){var e=Jl();return e?e.sanitize(Iu.HTML,t)||"":Ml(t,"Html")?t.toString():oc(document,Zt(t))}function Wl(t){var e=Jl();return e?e.sanitize(Iu.STYLE,t)||"":Ml(t,"Style")?t.toString():Bl(Zt(t))}function Kl(t){var e=Jl();return e?e.sanitize(Iu.URL,t)||"":Ml(t,"Url")?t.toString():Hu(Zt(t))}function $l(t){var e=Jl();if(e)return e.sanitize(Iu.RESOURCE_URL,t)||"";if(Ml(t,"ResourceUrl"))return t.toString();throw new Error("unsafe value used in a resource URL context (see http://g.co/ng/security#xss)")}function Zl(t){var e=Jl();if(e)return e.sanitize(Iu.SCRIPT,t)||"";if(Ml(t,"Script"))return t.toString();throw new Error("unsafe value used in a script context")}var Xl=function(t,e){return void 0===e?"background-image"===t||"background"===t||"border-image"===t||"filter"===t||"list-style"===t||"list-style-image"===t:Wl(e)};function Jl(){var t=Xe();return t&&t[Dt]}var Ql={"\u0275defineBase":ft,"\u0275defineComponent":ot,"\u0275defineDirective":pt,defineInjectable:v,defineInjector:_,"\u0275defineNgModule":lt,"\u0275definePipe":ht,"\u0275directiveInject":Ps,"\u0275getFactoryOf":qn,"\u0275getInheritedFactory":jn,inject:De,"\u0275injectAttribute":Ms,"\u0275templateRefExtractor":Ll,"\u0275NgOnChangesFeature":io,"\u0275ProvidersFeature":$o,"\u0275InheritDefinitionFeature":no,"\u0275elementAttribute":Ri,"\u0275bind":_s,"\u0275container":ns,"\u0275nextContext":di,"\u0275containerRefreshStart":rs,"\u0275containerRefreshEnd":is,"\u0275loadQueryList":Es,"\u0275namespaceHTML":mi,"\u0275namespaceMathML":bi,"\u0275namespaceSVG":gi,"\u0275enableBindings":$e,"\u0275disableBindings":Ze,"\u0275allocHostVars":xs,"\u0275elementStart":xi,"\u0275elementEnd":Ni,"\u0275element":yi,"\u0275elementContainerStart":vi,"\u0275elementContainerEnd":_i,"\u0275pureFunction0":Zc,"\u0275pureFunction1":Xc,"\u0275pureFunction2":Jc,"\u0275pureFunction3":Qc,"\u0275pureFunction4":tl,"\u0275pureFunction5":el,"\u0275pureFunction6":nl,"\u0275pureFunction7":al,"\u0275pureFunction8":rl,"\u0275pureFunctionV":il,"\u0275getCurrentView":zs,"\u0275restoreView":Je,"\u0275interpolation1":ws,"\u0275interpolation2":Ss,"\u0275interpolation3":Os,"\u0275interpolation4":Is,"\u0275interpolation5":Cs,"\u0275interpolation6":ks,"\u0275interpolation7":Ns,"\u0275interpolation8":Rs,"\u0275interpolationV":Ts,"\u0275elementClassProp":Yi,"\u0275listener":ki,"\u0275load":Ls,"\u0275projection":ls,"\u0275elementProperty":Ai,"\u0275componentHostSyntheticProperty":Di,"\u0275pipeBind1":ol,"\u0275pipeBind2":ul,"\u0275pipeBind3":cl,"\u0275pipeBind4":ll,"\u0275pipeBindV":dl,"\u0275projectionDef":us,"\u0275pipe":sl,"\u0275query":Dl,"\u0275queryRefresh":El,"\u0275registerContentQuery":qs,"\u0275reference":Ds,"\u0275elementStyling":ji,"\u0275elementHostAttrs":Fi,"\u0275elementStylingMap":Vi,"\u0275elementStyleProp":Gi,"\u0275elementStylingApply":zi,"\u0275template":es,"\u0275text":Hi,"\u0275textBinding":Bi,"\u0275embeddedViewStart":ss,"\u0275embeddedViewEnd":os,"\u0275i18n":Pc,"\u0275i18nAttributes":Mc,"\u0275i18nExp":Fc,"\u0275i18nStart":Nc,"\u0275i18nEnd":Dc,"\u0275i18nApply":zc,"\u0275i18nPostprocess":Ac,"\u0275sanitizeHtml":Ul,"\u0275sanitizeStyle":Wl,"\u0275defaultStyleSanitizer":Xl,"\u0275sanitizeResourceUrl":$l,"\u0275sanitizeScript":Zl,"\u0275sanitizeUrl":Kl},td=function(){return function(){}}(),ed=new Map;function nd(t,e){var n=ed.get(t);ad(t,n&&n.moduleType),ed.set(t,e)}function ad(t,e){if(e)throw new Error("Duplicate module registered for "+t+" - "+$(e)+" vs "+$(e.name))}function rd(t){var e=ed.get(t);if(!e)throw od(t);return e}function id(t){var e=ed.get(t);if(!e)throw od(t);return new Kc(e)}var sd=rd;function od(t){return new Error("No module with ID "+t+" loaded")}var ud=Function;function cd(t){return"function"==typeof t}var ld=/^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/,dd=/^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/,fd=/^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/,pd=function(){function t(t){this._reflect=t||V.Reflect}return t.prototype.isReflectionEnabled=function(){return!0},t.prototype.factory=function(t){return function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return new(t.bind.apply(t,Object(a.__spread)([void 0],e)))}},t.prototype._zipTypesAndAnnotations=function(t,e){var n;n=void 0===t?new Array(e.length):new Array(t.length);for(var a=0;a<n.length;a++)n[a]=void 0===t?[]:t[a]!=Object?[t[a]]:[],e&&null!=e[a]&&(n[a]=n[a].concat(e[a]));return n},t.prototype._ownParameters=function(t,e){var n=t.toString();if(ld.exec(n)||dd.exec(n)&&!fd.exec(n))return null;if(t.parameters&&t.parameters!==e.parameters)return t.parameters;var a=t.ctorParameters;if(a&&a!==e.ctorParameters){var r="function"==typeof a?a():a,i=r.map(function(t){return t&&t.type}),s=r.map(function(t){return t&&hd(t.decorators)});return this._zipTypesAndAnnotations(i,s)}var o=t.hasOwnProperty(O)&&t[O],u=this._reflect&&this._reflect.getOwnMetadata&&this._reflect.getOwnMetadata("design:paramtypes",t);return u||o?this._zipTypesAndAnnotations(u,o):new Array(t.length).fill(void 0)},t.prototype.parameters=function(t){if(!cd(t))return[];var e=gd(t),n=this._ownParameters(t,e);return n||e===Object||(n=this.parameters(e)),n||[]},t.prototype._ownAnnotations=function(t,e){if(t.annotations&&t.annotations!==e.annotations){var n=t.annotations;return"function"==typeof n&&n.annotations&&(n=n.annotations),n}return t.decorators&&t.decorators!==e.decorators?hd(t.decorators):t.hasOwnProperty(S)?t[S]:null},t.prototype.annotations=function(t){if(!cd(t))return[];var e=gd(t),n=this._ownAnnotations(t,e)||[];return(e!==Object?this.annotations(e):[]).concat(n)},t.prototype._ownPropMetadata=function(t,e){if(t.propMetadata&&t.propMetadata!==e.propMetadata){var n=t.propMetadata;return"function"==typeof n&&n.propMetadata&&(n=n.propMetadata),n}if(t.propDecorators&&t.propDecorators!==e.propDecorators){var a=t.propDecorators,r={};return Object.keys(a).forEach(function(t){r[t]=hd(a[t])}),r}return t.hasOwnProperty(I)?t[I]:null},t.prototype.propMetadata=function(t){if(!cd(t))return{};var e=gd(t),n={};if(e!==Object){var r=this.propMetadata(e);Object.keys(r).forEach(function(t){n[t]=r[t]})}var i=this._ownPropMetadata(t,e);return i&&Object.keys(i).forEach(function(t){var e=[];n.hasOwnProperty(t)&&e.push.apply(e,Object(a.__spread)(n[t])),e.push.apply(e,Object(a.__spread)(i[t])),n[t]=e}),n},t.prototype.hasLifecycleHook=function(t,e){return t instanceof ud&&e in t.prototype},t.prototype.guards=function(t){return{}},t.prototype.getter=function(t){return new Function("o","return o."+t+";")},t.prototype.setter=function(t){return new Function("o","v","return o."+t+" = v;")},t.prototype.method=function(t){return new Function("o","args","if (!o."+t+") throw new Error('\""+t+"\" is undefined');\n return o."+t+".apply(o, args);")},t.prototype.importUri=function(t){return"object"==typeof t&&t.filePath?t.filePath:"./"+$(t)},t.prototype.resourceUri=function(t){return"./"+$(t)},t.prototype.resolveIdentifier=function(t,e,n,a){return a},t.prototype.resolveEnum=function(t,e){return t[e]},t}();function hd(t){return t?t.map(function(t){var e=t.type.annotationCls,n=t.args?t.args:[];return new(e.bind.apply(e,Object(a.__spread)([void 0],n)))}):[]}function gd(t){var e=t.prototype?Object.getPrototypeOf(t.prototype):null;return(e?e.constructor:null)||Object}var bd=null;function md(){return bd=bd||new pd}function yd(t){return vd(md().parameters(t))}function vd(t){var e=ve();return t.map(function(t){return function(t,e){var n={token:null,host:!1,optional:!1,resolved:t.R3ResolvedDependencyType.Token,self:!1,skipSelf:!1};function a(e){n.resolved=t.R3ResolvedDependencyType.Token,n.token=e}if(Array.isArray(e)){if(0===e.length)throw new Error("Dependency array must have arguments.");for(var r=0;r<e.length;r++){var i=e[r];if(void 0!==i)if(i instanceof we||"Optional"===i.__proto__.ngMetadataName)n.optional=!0;else if(i instanceof Oe||"SkipSelf"===i.__proto__.ngMetadataName)n.skipSelf=!0;else if(i instanceof Se||"Self"===i.__proto__.ngMetadataName)n.self=!0;else if(i instanceof Ie||"Host"===i.__proto__.ngMetadataName)n.host=!0;else if(i instanceof Te)n.token=i.token;else if(i instanceof D){if(void 0===i.attributeName)throw new Error("Attribute name must be defined.");n.token=i.attributeName,n.resolved=t.R3ResolvedDependencyType.Attribute}else a(i)}}else a(e);return n}(e,t)})}var _d=[],xd=[],Td=!1;function wd(t){return Array.isArray(t)?t.every(wd):!!J(t)}function Sd(t,e){void 0===e&&(e={}),Od(t,e),function(t,e){xd.push({moduleType:t,ngModule:e})}(t,e)}function Od(t,e){var n,a,r=Rd(e.declarations||_d),i=null;Object.defineProperty(t,b,{configurable:!0,get:function(){return null===i&&(i=ve().compileNgModule(Ql,"ng://"+t.name+"/ngModuleDef.js",{type:t,bootstrap:Rd(e.bootstrap||_d,J),declarations:r.map(J),imports:Rd(e.imports||_d,J).map(Ad),exports:Rd(e.exports||_d,J).map(Ad),emitInline:!0})),i}}),e.id&&(a=t,ad(n=e.id,ed.get(n)),ed.set(n,a));var s=null;Object.defineProperty(t,h,{get:function(){if(null===s){var n={name:t.name,type:t,deps:yd(t),providers:e.providers||_d,imports:[(e.imports||_d).map(J),(e.exports||_d).map(J)]};s=ve().compileInjector(Ql,"ng://"+t.name+"/ngInjectorDef.js",n)}return s},configurable:!1})}function Id(){new Map,new Map,xd.length=0}function Cd(t,e){var n=Rd(e.declarations||_d),a=Nd(t);n.forEach(function(e){e.hasOwnProperty(d)?kd(gt(e),a):e.hasOwnProperty(f)||e.hasOwnProperty(g)||(e.ngSelectorScope=t)})}function kd(t,e){t.directiveDefs=function(){return Array.from(e.compilation.directives).map(function(t){return bt(t)||gt(t)}).filter(function(t){return!!t})},t.pipeDefs=function(){return Array.from(e.compilation.pipes).map(function(t){return mt(t)})}}function Nd(t){if(!Dd(t))throw new Error(t.name+" does not have an ngModuleDef");var e=yt(t);if(null!==e.transitiveCompileScopes)return e.transitiveCompileScopes;var n={compilation:{directives:new Set,pipes:new Set},exported:{directives:new Set,pipes:new Set}};return e.declarations.forEach(function(t){mt(t)?n.compilation.pipes.add(t):n.compilation.directives.add(t)}),e.imports.forEach(function(t){var e=t;if(!Dd(e))throw new Error("Importing "+e.name+" which does not have an ngModuleDef");var a=Nd(e);a.exported.directives.forEach(function(t){return n.compilation.directives.add(t)}),a.exported.pipes.forEach(function(t){return n.compilation.pipes.add(t)})}),e.exports.forEach(function(t){var e=t;if(Dd(e)){var a=Nd(e);a.exported.directives.forEach(function(t){n.compilation.directives.add(t),n.exported.directives.add(t)}),a.exported.pipes.forEach(function(t){n.compilation.pipes.add(t),n.exported.pipes.add(t)})}else mt(e)?n.exported.pipes.add(e):n.exported.directives.add(e)}),e.transitiveCompileScopes=n,n}function Rd(t,e){var n=[];return t.forEach(function(t){Array.isArray(t)?n.push.apply(n,Object(a.__spread)(Rd(t,e))):n.push(e?e(t):t)}),n}function Ad(t){return function(t){return void 0!==t.ngModule}(t)?t.ngModule:t}function Dd(t){return!!yt(t)}function Ed(t,e){var n=null;!function(t){et(t)&&tt.add(t)}(e),Object.defineProperty(t,d,{get:function(){var r=ve();if(null===n){if(et(e)){var i=["Component '"+Zt(t)+"' is not resolved:"];throw e.templateUrl&&i.push(" - templateUrl: "+Zt(e.templateUrl)),e.styleUrls&&e.styleUrls.length&&i.push(" - styleUrls: "+JSON.stringify(e.styleUrls)),i.push("Did you run and wait for 'resolveComponentResources()'?"),new Error(i.join("\n"))}var s=Object(a.__assign)({},Md(t,e),{template:e.template||"",preserveWhitespaces:e.preserveWhitespaces||!1,styles:e.styles||it,animations:e.animations,viewQueries:qd(t,md().propMetadata(t),Fd),directives:[],changeDetection:e.changeDetection,pipes:new Map,encapsulation:e.encapsulation||at.Emulated,interpolation:e.interpolation,viewProviders:e.viewProviders||null});if(n=r.compileComponent(Ql,"ng://"+Zt(t)+"/template.html",s),function(){if(!Td){Td=!0;try{for(var t=xd.length-1;t>=0;t--){var e=xd[t],n=e.moduleType,a=e.ngModule;a.declarations&&a.declarations.every(wd)&&(xd.splice(t,1),Cd(n,a))}}finally{Td=!1}}}(),void 0!==t.ngSelectorScope){var o=Nd(t.ngSelectorScope);kd(n,o)}}return n},configurable:!1})}function Ld(t,e){var n=null;Object.defineProperty(t,f,{get:function(){if(null===n){var a=Md(t,e);n=ve().compileDirective(Ql,"ng://"+(t&&t.name)+"/ngDirectiveDef.js",a)}return n},configurable:!1})}function Pd(t){return Object.getPrototypeOf(t.prototype)===Object.prototype}function Md(t,e){var n=md().propMetadata(t);return{name:t.name,type:t,typeArgumentCount:0,selector:e.selector,deps:yd(t),host:e.host||rt,propMetadata:n,inputs:e.inputs||it,outputs:e.outputs||it,queries:qd(t,n,jd),lifecycle:{usesOnChanges:void 0!==t.prototype.ngOnChanges},typeSourceSpan:null,usesInheritance:!Pd(t),exportAs:e.exportAs||null,providers:e.providers||null}}function qd(t,e,n){var a=[],r=function(r){e.hasOwnProperty(r)&&e[r].forEach(function(e){if(n(e)){if(!e.selector)throw new Error("Can't construct a query for the property \""+r+'" of "'+Zt(t)+"\" since the query selector wasn't defined.");a.push(function(t,e){return{propertyName:r,predicate:(n=e.selector,"string"==typeof n?n.split(",").map(function(t){return t.trim()}):J(n)),descendants:e.descendants,first:e.first,read:e.read?e.read:null};var n}(0,e))}})};for(var i in e)r(i);return a}function jd(t){var e=t.ngMetadataName;return"ContentChild"===e||"ContentChildren"===e}function Fd(t){var e=t.ngMetadataName;return"ViewChild"===e||"ViewChildren"===e}function zd(t,e){var n=null;Object.defineProperty(t,g,{get:function(){return null===n&&(n=ve().compilePipe(Ql,"ng://"+Zt(t)+"/ngPipeDef.js",{type:t,name:t.name,deps:yd(t),pipeName:e.name,pure:void 0===e.pure||e.pure})),n},configurable:!1})}var Gd=C("Directive",function(t){return void 0===t&&(t={}),t},void 0,void 0,function(t,e){return Qd(t,e)}),Yd=C("Component",function(t){return void 0===t&&(t={}),Object(a.__assign)({changeDetection:j.Default},t)},Gd,void 0,function(t,e){return Jd(t,e)}),Vd=C("Pipe",function(t){return Object(a.__assign)({pure:!0},t)},void 0,void 0,function(t,e){return tf(t,e)}),Hd=function(t){return function(e,n){for(var a=[],r=2;r<arguments.length;r++)a[r-2]=arguments[r];var i=e.constructor;i.hasOwnProperty(m)||function(t){var e=t.constructor,n=e.ngBaseDef,a=e.ngBaseDef={inputs:{},outputs:{},declaredInputs:{}};n&&(l(a.inputs,n.inputs),l(a.outputs,n.outputs),l(a.declaredInputs,n.declaredInputs))}(e),t(i.ngBaseDef)[n]=a[0]}},Bd=R("Input",function(t){return{bindingPropertyName:t}},void 0,Hd(function(t){return t.inputs||{}})),Ud=R("Output",function(t){return{bindingPropertyName:t}},void 0,Hd(function(t){return t.outputs||{}})),Wd=R("HostBinding",function(t){return{hostPropertyName:t}}),Kd=R("HostListener",function(t,e){return{eventName:t,args:e}}),$d=Ed,Zd=Ld,Xd=zd,Jd=oo,Qd=oo,tf=oo,ef=c({provide:String,useValue:c}),nf=[];function af(t,e){if(!e){var n=(c=new pd).parameters(t);return function(){return new(t.bind.apply(t,Object(a.__spread)([void 0],Le(n))))}}if(ef in e){var r=e;return function(){return r.useValue}}if(e.useExisting){var i=e;return function(){return De(i.useExisting)}}if(e.useFactory){var s=e;return function(){return s.useFactory.apply(s,Object(a.__spread)(Le(s.deps||nf)))}}if(e.useClass){var o=e,u=e.deps;if(!u){var c=new pd;u=c.parameters(t)}return function(){var t;return new((t=o.useClass).bind.apply(t,Object(a.__spread)([void 0],Le(u))))}}var l=e.deps;return l||(c=new pd,l=c.parameters(t)),function(){return new(t.bind.apply(t,Object(a.__spread)([void 0],Le(l))))}}var rf={name:"custom-elements"},sf={name:"no-errors-schema"},of=C("NgModule",function(t){return t},void 0,void 0,function(t,e){return cf(t,e)}),uf=Sd,cf=function(t,e){var n=e&&e.imports||[];e&&e.exports&&(n=Object(a.__spread)(n,[e.exports])),t.ngInjectorDef=_({factory:af(t,{useClass:t}),providers:e&&e.providers,imports:n})},lf=c({provide:String,useValue:c});function df(t){return void 0!==t.useClass}function ff(t){return lf in t}function pf(t){return void 0!==t.useFactory}function hf(t){return void 0!==t.useExisting}var gf=C("Injectable",void 0,void 0,void 0,function(t,e){return mf(t,e)}),bf=function(t,e){var n=null;t.hasOwnProperty(p)||Object.defineProperty(t,p,{get:function(){if(null===n){var a=e||{providedIn:null},r=df(a)||pf(a)||ff(a)||hf(a),i={name:t.name,type:t,typeArgumentCount:0,providedIn:a.providedIn,ctorDeps:yd(t),userDeps:void 0};if((df(a)||pf(a))&&void 0!==a.deps&&(i.userDeps=vd(a.deps)),r)if(df(a))i.useClass=a.useClass;else if(ff(a))i.useValue=a.useValue;else if(pf(a))i.useFactory=a.useFactory;else{if(!hf(a))throw new Error("Unreachable state.");i.useExisting=a.useExisting}else i.useClass=t;n=ve().compileInjectable(Ql,"ng://"+t.name+"/ngInjectableDef.js",i)}return n}})},mf=function(t,e){e&&void 0!==e.providedIn&&!x(t)&&(t.ngInjectableDef=v({providedIn:e.providedIn,factory:af(t,e)}))},yf="ngDebugContext",vf="ngOriginalError",_f="ngErrorLogger";function xf(t){return t[yf]}function Tf(t){return t[vf]}function wf(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];t.error.apply(t,Object(a.__spread)(e))}var Sf=function(){function t(){this._console=console}return t.prototype.handleError=function(t){var e=this._findOriginalError(t),n=this._findContext(t),a=function(t){return t[_f]||wf}(t);a(this._console,"ERROR",t),e&&a(this._console,"ORIGINAL ERROR",e),n&&a(this._console,"ERROR CONTEXT",n)},t.prototype._findContext=function(t){return t?xf(t)?xf(t):this._findContext(Tf(t)):null},t.prototype._findOriginalError=function(t){for(var e=Tf(t);e&&Tf(e);)e=Tf(e);return e},t}();function Of(t){return t.length>1?" ("+function(t){for(var e=[],n=0;n<t.length;++n){if(e.indexOf(t[n])>-1)return e.push(t[n]),e;e.push(t[n])}return e}(t.slice().reverse()).map(function(t){return $(t.token)}).join(" -> ")+")":""}function If(t,e,n,a){var r=[e],i=n(r),s=a?function(t,e){var n=i+" caused by: "+(e instanceof Error?e.message:e),a=Error(n);return a[vf]=e,a}(0,a):Error(i);return s.addKey=Cf,s.keys=r,s.injectors=[t],s.constructResolvingMessage=n,s[vf]=a,s}function Cf(t,e){this.injectors.push(t),this.keys.push(e),this.message=this.constructResolvingMessage(this.keys)}function kf(t,e){for(var n=[],a=0,r=e.length;a<r;a++){var i=e[a];n.push(i&&0!=i.length?i.map($).join(" "):"?")}return Error("Cannot resolve all parameters for '"+$(t)+"'("+n.join(", ")+"). Make sure that all the parameters are decorated with Inject or have valid type annotations and that '"+$(t)+"' is decorated with Injectable.")}var Nf=function(){function t(t,e){if(this.token=t,this.id=e,!t)throw new Error("Token must be defined!");this.displayName=$(this.token)}return t.get=function(t){return Rf.get(J(t))},Object.defineProperty(t,"numberOfKeys",{get:function(){return Rf.numberOfKeys},enumerable:!0,configurable:!0}),t}(),Rf=new(function(){function t(){this._allKeys=new Map}return t.prototype.get=function(t){if(t instanceof Nf)return t;if(this._allKeys.has(t))return this._allKeys.get(t);var e=new Nf(t,Nf.numberOfKeys);return this._allKeys.set(t,e),e},Object.defineProperty(t.prototype,"numberOfKeys",{get:function(){return this._allKeys.size},enumerable:!0,configurable:!0}),t}()),Af=new(function(){function t(t){this.reflectionCapabilities=t}return t.prototype.updateCapabilities=function(t){this.reflectionCapabilities=t},t.prototype.factory=function(t){return this.reflectionCapabilities.factory(t)},t.prototype.parameters=function(t){return this.reflectionCapabilities.parameters(t)},t.prototype.annotations=function(t){return this.reflectionCapabilities.annotations(t)},t.prototype.propMetadata=function(t){return this.reflectionCapabilities.propMetadata(t)},t.prototype.hasLifecycleHook=function(t,e){return this.reflectionCapabilities.hasLifecycleHook(t,e)},t.prototype.getter=function(t){return this.reflectionCapabilities.getter(t)},t.prototype.setter=function(t){return this.reflectionCapabilities.setter(t)},t.prototype.method=function(t){return this.reflectionCapabilities.method(t)},t.prototype.importUri=function(t){return this.reflectionCapabilities.importUri(t)},t.prototype.resourceUri=function(t){return this.reflectionCapabilities.resourceUri(t)},t.prototype.resolveIdentifier=function(t,e,n,a){return this.reflectionCapabilities.resolveIdentifier(t,e,n,a)},t.prototype.resolveEnum=function(t,e){return this.reflectionCapabilities.resolveEnum(t,e)},t}())(new pd),Df=function(){function t(t,e,n){this.key=t,this.optional=e,this.visibility=n}return t.fromKey=function(e){return new t(e,!1,null)},t}(),Ef=[],Lf=function(){return function(t,e,n){this.key=t,this.resolvedFactories=e,this.multiProvider=n,this.resolvedFactory=this.resolvedFactories[0]}}(),Pf=function(){return function(t,e){this.factory=t,this.dependencies=e}}();function Mf(t){var e,n;if(t.useClass){var a=J(t.useClass);e=Af.factory(a),n=Ff(a)}else t.useExisting?(e=function(t){return t},n=[Df.fromKey(Nf.get(t.useExisting))]):t.useFactory?(e=t.useFactory,n=function(t,e){if(e){var n=e.map(function(t){return[t]});return e.map(function(e){return zf(t,e,n)})}return Ff(t)}(t.useFactory,t.deps)):(e=function(){return t.useValue},n=Ef);return new Pf(e,n)}function qf(t){return new Lf(Nf.get(t.provide),[Mf(t)],t.multi||!1)}function jf(t){var e=function(t,e){for(var n=0;n<t.length;n++){var a=t[n],r=e.get(a.key.id);if(r){if(a.multiProvider!==r.multiProvider)throw Error("Cannot mix multi providers and regular providers, got: "+r+" "+a);if(a.multiProvider)for(var i=0;i<a.resolvedFactories.length;i++)r.resolvedFactories.push(a.resolvedFactories[i]);else e.set(a.key.id,a)}else{var s;s=a.multiProvider?new Lf(a.key,a.resolvedFactories.slice(),a.multiProvider):a,e.set(a.key.id,s)}}return e}(function t(e,n){return e.forEach(function(e){if(e instanceof ud)n.push({provide:e,useClass:e});else if(e&&"object"==typeof e&&void 0!==e.provide)n.push(e);else{if(!(e instanceof Array))throw Error("Invalid provider - only instances of Provider and Type are allowed, got: "+e);t(e,n)}}),n}(t,[]).map(qf),new Map);return Array.from(e.values())}function Ff(t){var e=Af.parameters(t);if(!e)return[];if(e.some(function(t){return null==t}))throw kf(t,e);return e.map(function(n){return zf(t,n,e)})}function zf(t,e,n){var a=null,r=!1;if(!Array.isArray(e))return Gf(e instanceof Te?e.token:e,r,null);for(var i=null,s=0;s<e.length;++s){var o=e[s];o instanceof ud?a=o:o instanceof Te?a=o.token:o instanceof we?r=!0:o instanceof Se||o instanceof Oe?i=o:o instanceof w&&(a=o)}if(null!=(a=J(a)))return Gf(a,r,i);throw kf(t,n)}function Gf(t,e,n){return new Df(Nf.get(t),e,n)}var Yf=new Object,Vf=function(){function t(){}return t.resolve=function(t){return jf(t)},t.resolveAndCreate=function(e,n){var a=t.resolve(e);return t.fromResolvedProviders(a,n)},t.fromResolvedProviders=function(t,e){return new Hf(t,e)},t}(),Hf=function(){function t(t,e){this._constructionCounter=0,this._providers=t,this.parent=e||null;var n=t.length;this.keyIds=new Array(n),this.objs=new Array(n);for(var a=0;a<n;a++)this.keyIds[a]=t[a].key.id,this.objs[a]=Yf}return t.prototype.get=function(t,e){return void 0===e&&(e=lo),this._getByKey(Nf.get(t),null,e)},t.prototype.resolveAndCreateChild=function(t){var e=Vf.resolve(t);return this.createChildFromResolved(e)},t.prototype.createChildFromResolved=function(e){var n=new t(e);return n.parent=this,n},t.prototype.resolveAndInstantiate=function(t){return this.instantiateResolved(Vf.resolve([t])[0])},t.prototype.instantiateResolved=function(t){return this._instantiateProvider(t)},t.prototype.getProviderAtIndex=function(t){if(t<0||t>=this._providers.length)throw function(t){return Error("Index "+t+" is out-of-bounds.")}(t);return this._providers[t]},t.prototype._new=function(t){if(this._constructionCounter++>this._getMaxNumberOfObjects())throw If(this,t.key,function(t){return"Cannot instantiate cyclic dependency!"+Of(t)});return this._instantiateProvider(t)},t.prototype._getMaxNumberOfObjects=function(){return this.objs.length},t.prototype._instantiateProvider=function(t){if(t.multiProvider){for(var e=new Array(t.resolvedFactories.length),n=0;n<t.resolvedFactories.length;++n)e[n]=this._instantiate(t,t.resolvedFactories[n]);return e}return this._instantiate(t,t.resolvedFactories[0])},t.prototype._instantiate=function(t,e){var n,r,i,s=this,o=e.factory;try{n=e.dependencies.map(function(t){return s._getByReflectiveDependency(t)})}catch(u){throw u.addKey&&u.addKey(this,t.key),u}try{r=o.apply(void 0,Object(a.__spread)(n))}catch(u){throw If(this,t.key,function(t){var e=$(t[0].token);return i.message+": Error during instantiation of "+e+"!"+Of(t)+"."},i=u)}return r},t.prototype._getByReflectiveDependency=function(t){return this._getByKey(t.key,t.visibility,t.optional?null:lo)},t.prototype._getByKey=function(e,n,a){return e===t.INJECTOR_KEY?this:n instanceof Se?this._getByKeySelf(e,a):this._getByKeyDefault(e,a,n)},t.prototype._getObjByKeyId=function(t){for(var e=0;e<this.keyIds.length;e++)if(this.keyIds[e]===t)return this.objs[e]===Yf&&(this.objs[e]=this._new(this._providers[e])),this.objs[e];return Yf},t.prototype._throwOrNull=function(t,e){if(e!==lo)return e;throw function(t,e){return If(t,e,function(t){return"No provider for "+$(t[0].token)+"!"+Of(t)})}(this,t)},t.prototype._getByKeySelf=function(t,e){var n=this._getObjByKeyId(t.id);return n!==Yf?n:this._throwOrNull(t,e)},t.prototype._getByKeyDefault=function(e,n,a){var r;for(r=a instanceof Oe?this.parent:this;r instanceof t;){var i=r,s=i._getObjByKeyId(e.id);if(s!==Yf)return s;r=i.parent}return null!==r?r.get(e.token,n):this._throwOrNull(e,n)},Object.defineProperty(t.prototype,"displayName",{get:function(){return"ReflectiveInjector(providers: ["+function(t,e){for(var n=new Array(t._providers.length),a=0;a<t._providers.length;++a)n[a]=' "'+t.getProviderAtIndex(a).key.displayName+'" ';return n}(this).join(", ")+"])"},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return this.displayName},t.INJECTOR_KEY=Nf.get(ho),t}();function Bf(t){return!!t&&"function"==typeof t.then}function Uf(t){return!!t&&"function"==typeof t.subscribe}var Wf=new w("Application Initializer"),Kf=function(){function t(t){var e=this;this.appInits=t,this.initialized=!1,this.done=!1,this.donePromise=new Promise(function(t,n){e.resolve=t,e.reject=n})}return t.prototype.runInitializers=function(){var t=this;if(!this.initialized){var e=[],n=function(){t.done=!0,t.resolve()};if(this.appInits)for(var a=0;a<this.appInits.length;a++){var r=this.appInits[a]();Bf(r)&&e.push(r)}Promise.all(e).then(function(){n()}).catch(function(e){t.reject(e)}),0===e.length&&n(),this.initialized=!0}},t}(),$f=new w("AppId");function Zf(){return""+Jf()+Jf()+Jf()}var Xf={provide:$f,useFactory:Zf,deps:[]};function Jf(){return String.fromCharCode(97+Math.floor(25*Math.random()))}var Qf=new w("Platform Initializer"),tp=new w("Platform ID"),ep=new w("appBootstrapListener"),np=new w("Application Packages Root URL"),ap=function(){function t(){}return t.prototype.log=function(t){console.log(t)},t.prototype.warn=function(t){console.warn(t)},t}(),rp=function(){return function(t,e){this.ngModuleFactory=t,this.componentFactories=e}}();function ip(){throw new Error("Runtime compiler is not loaded")}var sp,op,up=function(t){return new Kc(t)},cp=ip,lp=function(t){return Promise.resolve(up(t))},dp=ip,fp=function(t){return new rp(up(t),[])},pp=ip,hp=function(t){return Promise.resolve(fp(t))},gp=ip,bp=function(){function t(){this.compileModuleSync=cp,this.compileModuleAsync=dp,this.compileModuleAndAllComponentsSync=pp,this.compileModuleAndAllComponentsAsync=gp}return t.prototype.clearCache=function(){},t.prototype.clearCacheFor=function(t){},t.prototype.getModuleId=function(t){},t}(),mp=new w("compilerOptions"),yp=function(){return function(){}}();function vp(){var t=V.wtf;return!(!t||!(sp=t.trace)||(op=sp.events,0))}function _p(t,e){return void 0===e&&(e=null),op.createScope(t,e)}function xp(t,e){return sp.leaveScope(t,e),e}function Tp(t,e){return sp.beginTimeRange(t,e)}function wp(t){sp.endTimeRange(t)}var Sp=vp();function Op(t,e){return null}var Ip=Sp?_p:function(t,e){return Op},Cp=Sp?xp:function(t,e){return e},kp=Sp?Tp:function(t,e){return null},Np=Sp?wp:function(t){return null},Rp=function(){function t(t){var e,n=t.enableLongStackTrace,a=void 0!==n&&n;if(this.hasPendingMicrotasks=!1,this.hasPendingMacrotasks=!1,this.isStable=!0,this.onUnstable=new hl(!1),this.onMicrotaskEmpty=new hl(!1),this.onStable=new hl(!1),this.onError=new hl(!1),"undefined"==typeof Zone)throw new Error("In this configuration Angular requires Zone.js");Zone.assertZonePatched(),this._nesting=0,this._outer=this._inner=Zone.current,Zone.wtfZoneSpec&&(this._inner=this._inner.fork(Zone.wtfZoneSpec)),Zone.TaskTrackingZoneSpec&&(this._inner=this._inner.fork(new Zone.TaskTrackingZoneSpec)),a&&Zone.longStackTraceZoneSpec&&(this._inner=this._inner.fork(Zone.longStackTraceZoneSpec)),(e=this)._inner=e._inner.fork({name:"angular",properties:{isAngularZone:!0},onInvokeTask:function(t,n,a,r,i,s){try{return Lp(e),t.invokeTask(a,r,i,s)}finally{Pp(e)}},onInvoke:function(t,n,a,r,i,s,o){try{return Lp(e),t.invoke(a,r,i,s,o)}finally{Pp(e)}},onHasTask:function(t,n,a,r){t.hasTask(a,r),n===a&&("microTask"==r.change?(e.hasPendingMicrotasks=r.microTask,Ep(e)):"macroTask"==r.change&&(e.hasPendingMacrotasks=r.macroTask))},onHandleError:function(t,n,a,r){return t.handleError(a,r),e.runOutsideAngular(function(){return e.onError.emit(r)}),!1}})}return t.isInAngularZone=function(){return!0===Zone.current.get("isAngularZone")},t.assertInAngularZone=function(){if(!t.isInAngularZone())throw new Error("Expected to be in Angular Zone, but it is not!")},t.assertNotInAngularZone=function(){if(t.isInAngularZone())throw new Error("Expected to not be in Angular Zone, but it is!")},t.prototype.run=function(t,e,n){return this._inner.run(t,e,n)},t.prototype.runTask=function(t,e,n,a){var r=this._inner,i=r.scheduleEventTask("NgZoneEvent: "+a,t,Dp,Ap,Ap);try{return r.runTask(i,e,n)}finally{r.cancelTask(i)}},t.prototype.runGuarded=function(t,e,n){return this._inner.runGuarded(t,e,n)},t.prototype.runOutsideAngular=function(t){return this._outer.run(t)},t}();function Ap(){}var Dp={};function Ep(t){if(0==t._nesting&&!t.hasPendingMicrotasks&&!t.isStable)try{t._nesting++,t.onMicrotaskEmpty.emit(null)}finally{if(t._nesting--,!t.hasPendingMicrotasks)try{t.runOutsideAngular(function(){return t.onStable.emit(null)})}finally{t.isStable=!0}}}function Lp(t){t._nesting++,t.isStable&&(t.isStable=!1,t.onUnstable.emit(null))}function Pp(t){t._nesting--,Ep(t)}var Mp=function(){function t(){this.hasPendingMicrotasks=!1,this.hasPendingMacrotasks=!1,this.isStable=!0,this.onUnstable=new hl,this.onMicrotaskEmpty=new hl,this.onStable=new hl,this.onError=new hl}return t.prototype.run=function(t){return t()},t.prototype.runGuarded=function(t){return t()},t.prototype.runOutsideAngular=function(t){return t()},t.prototype.runTask=function(t){return t()},t}(),qp=function(){function t(t){var e=this;this._ngZone=t,this._pendingCount=0,this._isZoneStable=!0,this._didWork=!1,this._callbacks=[],this.taskTrackingZone=null,this._watchAngularEvents(),t.run(function(){e.taskTrackingZone="undefined"==typeof Zone?null:Zone.current.get("TaskTrackingZone")})}return t.prototype._watchAngularEvents=function(){var t=this;this._ngZone.onUnstable.subscribe({next:function(){t._didWork=!0,t._isZoneStable=!1}}),this._ngZone.runOutsideAngular(function(){t._ngZone.onStable.subscribe({next:function(){Rp.assertNotInAngularZone(),W(function(){t._isZoneStable=!0,t._runCallbacksIfReady()})}})})},t.prototype.increasePendingRequestCount=function(){return this._pendingCount+=1,this._didWork=!0,this._pendingCount},t.prototype.decreasePendingRequestCount=function(){if(this._pendingCount-=1,this._pendingCount<0)throw new Error("pending async requests below zero");return this._runCallbacksIfReady(),this._pendingCount},t.prototype.isStable=function(){return this._isZoneStable&&0===this._pendingCount&&!this._ngZone.hasPendingMacrotasks},t.prototype._runCallbacksIfReady=function(){var t=this;if(this.isStable())W(function(){for(;0!==t._callbacks.length;){var e=t._callbacks.pop();clearTimeout(e.timeoutId),e.doneCb(t._didWork)}t._didWork=!1});else{var e=this.getPendingTasks();this._callbacks=this._callbacks.filter(function(t){return!t.updateCb||!t.updateCb(e)||(clearTimeout(t.timeoutId),!1)}),this._didWork=!0}},t.prototype.getPendingTasks=function(){return this.taskTrackingZone?this.taskTrackingZone.macroTasks.map(function(t){return{source:t.source,creationLocation:t.creationLocation,data:t.data}}):[]},t.prototype.addCallback=function(t,e,n){var a=this,r=-1;e&&e>0&&(r=setTimeout(function(){a._callbacks=a._callbacks.filter(function(t){return t.timeoutId!==r}),t(a._didWork,a.getPendingTasks())},e)),this._callbacks.push({doneCb:t,timeoutId:r,updateCb:n})},t.prototype.whenStable=function(t,e,n){if(n&&!this.taskTrackingZone)throw new Error('Task tracking zone is required when passing an update callback to whenStable(). Is "zone.js/dist/task-tracking.js" loaded?');this.addCallback(t,e,n),this._runCallbacksIfReady()},t.prototype.getPendingRequestCount=function(){return this._pendingCount},t.prototype.findProviders=function(t,e,n){return[]},t}(),jp=function(){function t(){this._applications=new Map,Gp.addToWindow(this)}return t.prototype.registerApplication=function(t,e){this._applications.set(t,e)},t.prototype.unregisterApplication=function(t){this._applications.delete(t)},t.prototype.unregisterAllApplications=function(){this._applications.clear()},t.prototype.getTestability=function(t){return this._applications.get(t)||null},t.prototype.getAllTestabilities=function(){return Array.from(this._applications.values())},t.prototype.getAllRootElements=function(){return Array.from(this._applications.keys())},t.prototype.findTestabilityInTree=function(t,e){return void 0===e&&(e=!0),Gp.findTestabilityInTree(this,t,e)},Object(a.__decorate)([Object(a.__metadata)("design:paramtypes",[])],t)}();function Fp(t){Gp=t}var zp,Gp=new(function(){function t(){}return t.prototype.addToWindow=function(t){},t.prototype.findTestabilityInTree=function(t,e,n){return null},t}());function Yp(t,e,n){return Promise.resolve(new Kc(n))}var Vp=new w("AllowMultipleToken"),Hp=function(){return function(t,e){this.name=t,this.token=e}}();function Bp(t){if(zp&&!zp.destroyed&&!zp.injector.get(Vp,!1))throw new Error("There can be only one platform. Destroy the previous one to create a new one.");zp=t.get(Zp);var e=t.get(Qf,null);return e&&e.forEach(function(t){return t()}),zp}function Up(t,e,n){void 0===n&&(n=[]);var a="Platform: "+e,r=new w(a);return function(e){void 0===e&&(e=[]);var i=$p();if(!i||i.injector.get(Vp,!1))if(t)t(n.concat(e).concat({provide:r,useValue:!0}));else{var s=n.concat(e).concat({provide:r,useValue:!0});Bp(ho.create({providers:s,name:a}))}return Wp(r)}}function Wp(t){var e=$p();if(!e)throw new Error("No platform exists!");if(!e.injector.get(t,null))throw new Error("A platform with a different configuration has been created. Please destroy it first.");return e}function Kp(){zp&&!zp.destroyed&&zp.destroy()}function $p(){return zp&&!zp.destroyed?zp:null}var Zp=function(){function t(t){this._injector=t,this._modules=[],this._destroyListeners=[],this._destroyed=!1}return t.prototype.bootstrapModuleFactory=function(t,e){var n,a=this,r="noop"===(n=e?e.ngZone:void 0)?new Mp:("zone.js"===n?void 0:n)||new Rp({enableLongStackTrace:Fu()}),i=[{provide:Rp,useValue:r}];return r.run(function(){var e=ho.create({providers:i,parent:a.injector,name:t.moduleType.name}),n=t.create(e),s=n.injector.get(Sf,null);if(!s)throw new Error("No ErrorHandler. Is platform module (BrowserModule) included?");return n.onDestroy(function(){return Qp(a._modules,n)}),r.runOutsideAngular(function(){return r.onError.subscribe({next:function(t){s.handleError(t)}})}),function(t,e,r){try{var i=((s=n.injector.get(Kf)).runInitializers(),s.donePromise.then(function(){return a._moduleDoBootstrap(n),n}));return Bf(i)?i.catch(function(n){throw e.runOutsideAngular(function(){return t.handleError(n)}),n}):i}catch(o){throw e.runOutsideAngular(function(){return t.handleError(o)}),o}var s}(s,r)})},t.prototype.bootstrapModule=function(t,e){var n=this;void 0===e&&(e=[]);var a=Xp({},e);return function(t,e,n){return t.get(yp).createCompiler([e]).compileModuleAsync(n)}(this.injector,a,t).then(function(t){return n.bootstrapModuleFactory(t,a)})},t.prototype._moduleDoBootstrap=function(t){var e=t.injector.get(Jp);if(t._bootstrapComponents.length>0)t._bootstrapComponents.forEach(function(t){return e.bootstrap(t)});else{if(!t.instance.ngDoBootstrap)throw new Error("The module "+$(t.instance.constructor)+' was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. Please define one of these.');t.instance.ngDoBootstrap(e)}this._modules.push(t)},t.prototype.onDestroy=function(t){this._destroyListeners.push(t)},Object.defineProperty(t.prototype,"injector",{get:function(){return this._injector},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){if(this._destroyed)throw new Error("The platform has already been destroyed!");this._modules.slice().forEach(function(t){return t.destroy()}),this._destroyListeners.forEach(function(t){return t()}),this._destroyed=!0},Object.defineProperty(t.prototype,"destroyed",{get:function(){return this._destroyed},enumerable:!0,configurable:!0}),t}();function Xp(t,e){return Array.isArray(e)?e.reduce(Xp,t):Object(a.__assign)({},t,e)}var Jp=function(){function t(t,e,n,a,r,i){var c=this;this._zone=t,this._console=e,this._injector=n,this._exceptionHandler=a,this._componentFactoryResolver=r,this._initStatus=i,this._bootstrapListeners=[],this._views=[],this._runningTick=!1,this._enforceNoNewChanges=!1,this._stable=!0,this.componentTypes=[],this.components=[],this._enforceNoNewChanges=Fu(),this._zone.onMicrotaskEmpty.subscribe({next:function(){c._zone.run(function(){c.tick()})}});var l=new s.a(function(t){c._stable=c._zone.isStable&&!c._zone.hasPendingMacrotasks&&!c._zone.hasPendingMicrotasks,c._zone.runOutsideAngular(function(){t.next(c._stable),t.complete()})}),d=new s.a(function(t){var e;c._zone.runOutsideAngular(function(){e=c._zone.onStable.subscribe(function(){Rp.assertNotInAngularZone(),W(function(){c._stable||c._zone.hasPendingMacrotasks||c._zone.hasPendingMicrotasks||(c._stable=!0,t.next(!0))})})});var n=c._zone.onUnstable.subscribe(function(){Rp.assertInAngularZone(),c._stable&&(c._stable=!1,c._zone.runOutsideAngular(function(){t.next(!1)}))});return function(){e.unsubscribe(),n.unsubscribe()}});this.isStable=Object(o.a)(l,d.pipe(Object(u.a)()))}var e;return e=t,t.prototype.bootstrap=function(t,e){var n,a=this;if(!this._initStatus.done)throw new Error("Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.");n=t instanceof Xo?t:this._componentFactoryResolver.resolveComponentFactory(t),this.componentTypes.push(n.componentType);var r=n instanceof su?null:this._injector.get(ou),i=n.create(ho.NULL,[],e||n.selector,r);i.onDestroy(function(){a._unloadComponent(i)});var s=i.injector.get(qp,null);return s&&i.injector.get(jp).registerApplication(i.location.nativeElement,s),this._loadComponent(i),Fu()&&this._console.log("Angular is running in the development mode. Call enableProdMode() to enable the production mode."),i},t.prototype.tick=function(){var t=this;if(this._runningTick)throw new Error("ApplicationRef.tick is called recursively");var n=e._tickScope();try{this._runningTick=!0,this._views.forEach(function(t){return t.detectChanges()}),this._enforceNoNewChanges&&this._views.forEach(function(t){return t.checkNoChanges()})}catch(a){this._zone.runOutsideAngular(function(){return t._exceptionHandler.handleError(a)})}finally{this._runningTick=!1,Cp(n)}},t.prototype.attachView=function(t){var e=t;this._views.push(e),e.attachToAppRef(this)},t.prototype.detachView=function(t){var e=t;Qp(this._views,e),e.detachFromAppRef()},t.prototype._loadComponent=function(t){this.attachView(t.hostView),this.tick(),this.components.push(t),this._injector.get(ep,[]).concat(this._bootstrapListeners).forEach(function(e){return e(t)})},t.prototype._unloadComponent=function(t){this.detachView(t.hostView),Qp(this.components,t)},t.prototype.ngOnDestroy=function(){this._views.slice().forEach(function(t){return t.destroy()})},Object.defineProperty(t.prototype,"viewCount",{get:function(){return this._views.length},enumerable:!0,configurable:!0}),t._tickScope=Ip("ApplicationRef#tick()"),t}();function Qp(t,e){var n=t.indexOf(e);n>-1&&t.splice(n,1)}var th=function(){function t(){this.dirty=!0,this._results=[],this.changes=new hl,this.length=0}return t.prototype.map=function(t){return this._results.map(t)},t.prototype.filter=function(t){return this._results.filter(t)},t.prototype.find=function(t){return this._results.find(t)},t.prototype.reduce=function(t,e){return this._results.reduce(t,e)},t.prototype.forEach=function(t){this._results.forEach(t)},t.prototype.some=function(t){return this._results.some(t)},t.prototype.toArray=function(){return this._results.slice()},t.prototype[U()]=function(){return this._results[U()]()},t.prototype.toString=function(){return this._results.toString()},t.prototype.reset=function(t){this._results=function t(e){return e.reduce(function(e,n){var a=Array.isArray(n)?t(n):n;return e.concat(a)},[])}(t),this.dirty=!1,this.length=this._results.length,this.last=this._results[this.length-1],this.first=this._results[0]},t.prototype.notifyOnChanges=function(){this.changes.emit(this)},t.prototype.setDirty=function(){this.dirty=!0},t.prototype.destroy=function(){this.changes.complete(),this.changes.unsubscribe()},t}(),eh=function(){return function(){}}(),nh={factoryPathPrefix:"",factoryPathSuffix:".ngfactory"},ah=function(){function t(t,e){this._compiler=t,this._config=e||nh}return t.prototype.load=function(t){return this._compiler instanceof bp?this.loadFactory(t):this.loadAndCompile(t)},t.prototype.loadAndCompile=function(t){var e=this,r=Object(a.__read)(t.split("#"),2),i=r[0],s=r[1];return void 0===s&&(s="default"),n("crnd")(i).then(function(t){return t[s]}).then(function(t){return rh(t,i,s)}).then(function(t){return e._compiler.compileModuleAsync(t)})},t.prototype.loadFactory=function(t){var e=Object(a.__read)(t.split("#"),2),r=e[0],i=e[1],s="NgFactory";return void 0===i&&(i="default",s=""),n("crnd")(this._config.factoryPathPrefix+r+this._config.factoryPathSuffix).then(function(t){return t[i+s]}).then(function(t){return rh(t,r,i)})},t}();function rh(t,e,n){if(!t)throw new Error("Cannot find '"+n+"' in '"+e+"'");return t}var ih=function(){function t(){}return t.__NG_ELEMENT_ID__=function(){return oh(t,hu)},t}(),sh=function(t,e){return function(t,e,n,r){var i;eu||(eu=function(t){function n(e,n,a){var r=t.call(this)||this;return r._lContainer=e,r._hostTNode=n,r._hostView=a,r._viewRefs=[],r}return Object(a.__extends)(n,t),Object.defineProperty(n.prototype,"element",{get:function(){return du(e,this._hostTNode,this._hostView)},enumerable:!0,configurable:!0}),Object.defineProperty(n.prototype,"injector",{get:function(){return new Mn(this._hostTNode,this._hostView)},enumerable:!0,configurable:!0}),Object.defineProperty(n.prototype,"parentInjector",{get:function(){var t=In(this._hostTNode,this._hostView),e=ge(t,this._hostView),n=function(t,e,n){if(n.parent&&-1!==n.parent.injectorIndex){for(var a=n.parent.injectorIndex,r=n.parent;null!=r.parent&&a==r.injectorIndex;)r=r.parent;return r}for(var i=he(t),s=e,o=e[Ot];i>1;)o=(s=s[Mt])[Ot],i--;return o}(t,this._hostView,this._hostTNode);return fe(t)&&null!=n?new Mn(n,e):new Mn(null,this._hostView)},enumerable:!0,configurable:!0}),n.prototype.clear=function(){for(;this._lContainer[Ft].length;)this.remove(0)},n.prototype.get=function(t){return this._viewRefs[t]||null},Object.defineProperty(n.prototype,"length",{get:function(){return this._lContainer[Ft].length},enumerable:!0,configurable:!0}),n.prototype.createEmbeddedView=function(t,e,n){var a=this._adjustIndex(n),r=t.createEmbeddedView(e||{},this._lContainer,this._hostTNode,this._hostView,a);return r.attachToViewContainerRef(this),this._viewRefs.splice(a,0,r),r},n.prototype.createComponent=function(t,e,n,a,r){var i=n||this.parentInjector;!r&&null==t.ngModule&&i&&(r=i.get(ou,null));var s=t.create(i,a,void 0,r);return this.insert(s.hostView,e),s},n.prototype.insert=function(t,e){if(t.destroyed)throw new Error("Cannot insert a destroyed View in a ViewContainer!");var n=t._lView,a=this._adjustIndex(e);return La(n,this._lContainer,this._hostView,a,this._hostTNode.index),Ea(n,!0,Wa(a,this._lContainer[Ft],this._lContainer[zt])),t.attachToViewContainerRef(this),this._viewRefs.splice(a,0,t),t},n.prototype.move=function(t,e){if(t.destroyed)throw new Error("Cannot move a destroyed View in a ViewContainer!");var n=this.indexOf(t);return this.detach(n),this.insert(t,this._adjustIndex(e)),t},n.prototype.indexOf=function(t){return this._viewRefs.indexOf(t)},n.prototype.remove=function(t){var e=this._adjustIndex(t,-1);Ma(this._lContainer,this._hostTNode,e),this._viewRefs.splice(e,1)},n.prototype.detach=function(t){var e=this._adjustIndex(t,-1),n=Pa(this._lContainer,e,!!this._hostTNode.detached);return null!=this._viewRefs.splice(e,1)[0]?new cu(n,n[kt],n[Lt]):null},n.prototype._adjustIndex=function(t,e){return void 0===e&&(e=0),null==t?this._lContainer[Ft].length+e:t},n}(t));var s=r[n.index];if(se(s))(i=s)[jt]=-1;else{var o=r[At].createComment("");if(oe(r)){var u=r[At],c=te(n,r);Va(u,Ha(u,c),o,function(t,e){return wa(t)?t.nextSibling(e):e.nextSibling}(u,c))}else Ba(o,n,r);r[n.index]=i=ts(s,n,r,o,!0),ds(r,n.index,i)}return new eu(i,n,r)}(t,e,Qe(),Xe())},oh=oo,uh=function(){function t(){}return t.__NG_ELEMENT_ID__=function(){return lh()},t}(),ch=function(){return pu(Qe(),Xe(),null)},lh=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e]},dh=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e}(uh),fh=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e}(dh),ph=function(){return function(t,e){this.name=t,this.callback=e}}(),hh=function(){function t(t,e,n){this.listeners=[],this.parent=null,this._debugContext=n,this.nativeNode=t,e&&e instanceof gh&&e.addChild(this)}return Object.defineProperty(t.prototype,"injector",{get:function(){return this._debugContext.injector},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"componentInstance",{get:function(){return this._debugContext.component},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this._debugContext.context},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"references",{get:function(){return this._debugContext.references},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"providerTokens",{get:function(){return this._debugContext.providerTokens},enumerable:!0,configurable:!0}),t}(),gh=function(t){function e(e,n,a){var r=t.call(this,e,n,a)||this;return r.properties={},r.attributes={},r.classes={},r.styles={},r.childNodes=[],r.nativeElement=e,r}return Object(a.__extends)(e,t),e.prototype.addChild=function(t){t&&(this.childNodes.push(t),t.parent=this)},e.prototype.removeChild=function(t){var e=this.childNodes.indexOf(t);-1!==e&&(t.parent=null,this.childNodes.splice(e,1))},e.prototype.insertChildrenAfter=function(t,e){var n,r=this,i=this.childNodes.indexOf(t);-1!==i&&((n=this.childNodes).splice.apply(n,Object(a.__spread)([i+1,0],e)),e.forEach(function(e){e.parent&&e.parent.removeChild(e),t.parent=r}))},e.prototype.insertBefore=function(t,e){var n=this.childNodes.indexOf(t);-1===n?this.addChild(e):(e.parent&&e.parent.removeChild(e),e.parent=this,this.childNodes.splice(n,0,e))},e.prototype.query=function(t){return this.queryAll(t)[0]||null},e.prototype.queryAll=function(t){var e=[];return mh(this,t,e),e},e.prototype.queryAllNodes=function(t){var e=[];return yh(this,t,e),e},Object.defineProperty(e.prototype,"children",{get:function(){return this.childNodes.filter(function(t){return t instanceof e})},enumerable:!0,configurable:!0}),e.prototype.triggerEventHandler=function(t,e){this.listeners.forEach(function(n){n.name==t&&n.callback(e)})},e}(hh);function bh(t){return t.map(function(t){return t.nativeElement})}function mh(t,e,n){t.childNodes.forEach(function(t){t instanceof gh&&(e(t)&&n.push(t),mh(t,e,n))})}function yh(t,e,n){t instanceof gh&&t.childNodes.forEach(function(t){e(t)&&n.push(t),t instanceof gh&&yh(t,e,n)})}var vh=function(){function t(t){this.nativeNode=t}return Object.defineProperty(t.prototype,"parent",{get:function(){var t=this.nativeNode.parentNode;return t?new _h(t):null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"injector",{get:function(){return Jn(this.nativeNode)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"componentInstance",{get:function(){var t=this.nativeNode;return t&&Wn(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return Kn(this.nativeNode)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"listeners",{get:function(){return ra(this.nativeNode).filter(aa)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"references",{get:function(){return void 0===(t=ta(this.nativeNode)).localRefs&&(t.localRefs=function(e,n){var a=e[vt].data[t.nodeIndex];if(a&&a.localNames){for(var r={},i=0;i<a.localNames.length;i+=2){var s=a.localNames[i+1];r[a.localNames[i]]=-1===s?te(a,e):e[s]}return r}return null}(t.lView)),t.localRefs||{};var t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"providerTokens",{get:function(){return function(t){var e=ta(t,!1);if(!e)return[];for(var n,a=e.lView[vt],r=a.data[e.nodeIndex],i=[],s=r.directiveEnd,o=65535&r.providerIndexes;o<s;o++){var u=a.data[o];void 0!==(n=u).type&&void 0!==n.template&&void 0!==n.declaredInputs&&(u=u.type),i.push(u)}return i}(this.nativeNode)},enumerable:!0,configurable:!0}),t}(),_h=function(t){function e(e){return t.call(this,e)||this}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"nativeElement",{get:function(){return this.nativeNode.nodeType==Node.ELEMENT_NODE?this.nativeNode:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"name",{get:function(){return this.nativeElement.nodeName},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"properties",{get:function(){return ta(this.nativeNode),{}},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"attributes",{get:function(){var t={},e=this.nativeElement;if(e)for(var n=e.attributes,a=0;a<n.length;a++){var r=n[a];t[r.name]=r.value}return t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"classes",{get:function(){var t={},e=this.nativeElement;if(e){var n=na(e),a=n.lView[n.nodeIndex];if(ur(n.nodeIndex,n.lView)){for(var r=9;r<a.length;r+=4)if(wr(a,r)){var i=zr(a,r),s=Fr(a,r);"boolean"==typeof s&&(t[i]=s)}}else{var o=e.classList;for(r=0;r<o.length;r++)t[o[r]]=!0}}return t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"styles",{get:function(){var t={},e=this.nativeElement;if(e){var n=na(e),a=n.lView[n.nodeIndex];if(ur(n.nodeIndex,n.lView)){for(var r=9;r<a.length;r+=4)if(!wr(a,r)){var i=zr(a,r),s=Fr(a,r);null!==s&&(t[i]=s)}}else{var o=e.style;for(r=0;r<o.length;r++){var u=o.item(r);t[u]=o.getPropertyValue(u)}}}return t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"childNodes",{get:function(){for(var t=this.nativeNode.childNodes,e=[],n=0;n<t.length;n++)e.push(wh(t[n]));return e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"children",{get:function(){var t=this.nativeElement;if(!t)return[];for(var e=t.children,n=[],a=0;a<e.length;a++)n.push(wh(e[a]));return n},enumerable:!0,configurable:!0}),e.prototype.query=function(t){return this.queryAll(t)[0]||null},e.prototype.queryAll=function(t){var e=[];return xh(this,t,e,!0),e},e.prototype.queryAllNodes=function(t){var e=[];return xh(this,t,e,!1),e},e.prototype.triggerEventHandler=function(t,e){this.listeners.forEach(function(n){n.name===t&&n.callback(e)})},e}(vh);function xh(t,e,n,a){t instanceof _h&&t.childNodes.forEach(function(t){e(t)&&n.push(t),t instanceof _h&&(a&&!t.nativeElement||xh(t,e,n,a))})}var Th=new Map;function wh(t){return t instanceof Node?t.nodeType==Node.ELEMENT_NODE?new _h(t):new vh(t):null}var Sh=function(t){return Th.get(t)||null};function Oh(t){Th.set(t.nativeNode,t)}var Ih=hh,Ch=gh,kh=function(){function t(){}return t.prototype.supports=function(t){return da(t)},t.prototype.create=function(t){return new Rh(t)},t}(),Nh=function(t,e){return e},Rh=function(){function t(t){this.length=0,this._linkedRecords=null,this._unlinkedRecords=null,this._previousItHead=null,this._itHead=null,this._itTail=null,this._additionsHead=null,this._additionsTail=null,this._movesHead=null,this._movesTail=null,this._removalsHead=null,this._removalsTail=null,this._identityChangesHead=null,this._identityChangesTail=null,this._trackByFn=t||Nh}return t.prototype.forEachItem=function(t){var e;for(e=this._itHead;null!==e;e=e._next)t(e)},t.prototype.forEachOperation=function(t){for(var e=this._itHead,n=this._removalsHead,a=0,r=null;e||n;){var i=!n||e&&e.currentIndex<Lh(n,a,r)?e:n,s=Lh(i,a,r),o=i.currentIndex;if(i===n)a--,n=n._nextRemoved;else if(e=e._next,null==i.previousIndex)a++;else{r||(r=[]);var u=s-a,c=o-a;if(u!=c){for(var l=0;l<u;l++){var d=l<r.length?r[l]:r[l]=0,f=d+l;c<=f&&f<u&&(r[l]=d+1)}r[i.previousIndex]=c-u}}s!==o&&t(i,s,o)}},t.prototype.forEachPreviousItem=function(t){var e;for(e=this._previousItHead;null!==e;e=e._nextPrevious)t(e)},t.prototype.forEachAddedItem=function(t){var e;for(e=this._additionsHead;null!==e;e=e._nextAdded)t(e)},t.prototype.forEachMovedItem=function(t){var e;for(e=this._movesHead;null!==e;e=e._nextMoved)t(e)},t.prototype.forEachRemovedItem=function(t){var e;for(e=this._removalsHead;null!==e;e=e._nextRemoved)t(e)},t.prototype.forEachIdentityChange=function(t){var e;for(e=this._identityChangesHead;null!==e;e=e._nextIdentityChange)t(e)},t.prototype.diff=function(t){if(null==t&&(t=[]),!da(t))throw new Error("Error trying to diff '"+$(t)+"'. Only arrays and iterables are allowed");return this.check(t)?this:null},t.prototype.onDestroy=function(){},t.prototype.check=function(t){var e=this;this._reset();var n,a,r,i=this._itHead,s=!1;if(Array.isArray(t)){this.length=t.length;for(var o=0;o<this.length;o++)r=this._trackByFn(o,a=t[o]),null!==i&&K(i.trackById,r)?(s&&(i=this._verifyReinsertion(i,a,r,o)),K(i.item,a)||this._addIdentityChange(i,a)):(i=this._mismatch(i,a,r,o),s=!0),i=i._next}else n=0,function(t,e){if(Array.isArray(t))for(var n=0;n<t.length;n++)e(t[n]);else for(var a=t[U()](),r=void 0;!(r=a.next()).done;)e(r.value)}(t,function(t){r=e._trackByFn(n,t),null!==i&&K(i.trackById,r)?(s&&(i=e._verifyReinsertion(i,t,r,n)),K(i.item,t)||e._addIdentityChange(i,t)):(i=e._mismatch(i,t,r,n),s=!0),i=i._next,n++}),this.length=n;return this._truncate(i),this.collection=t,this.isDirty},Object.defineProperty(t.prototype,"isDirty",{get:function(){return null!==this._additionsHead||null!==this._movesHead||null!==this._removalsHead||null!==this._identityChangesHead},enumerable:!0,configurable:!0}),t.prototype._reset=function(){if(this.isDirty){var t=void 0,e=void 0;for(t=this._previousItHead=this._itHead;null!==t;t=t._next)t._nextPrevious=t._next;for(t=this._additionsHead;null!==t;t=t._nextAdded)t.previousIndex=t.currentIndex;for(this._additionsHead=this._additionsTail=null,t=this._movesHead;null!==t;t=e)t.previousIndex=t.currentIndex,e=t._nextMoved;this._movesHead=this._movesTail=null,this._removalsHead=this._removalsTail=null,this._identityChangesHead=this._identityChangesTail=null}},t.prototype._mismatch=function(t,e,n,a){var r;return null===t?r=this._itTail:(r=t._prev,this._remove(t)),null!==(t=null===this._linkedRecords?null:this._linkedRecords.get(n,a))?(K(t.item,e)||this._addIdentityChange(t,e),this._moveAfter(t,r,a)):null!==(t=null===this._unlinkedRecords?null:this._unlinkedRecords.get(n,null))?(K(t.item,e)||this._addIdentityChange(t,e),this._reinsertAfter(t,r,a)):t=this._addAfter(new Ah(e,n),r,a),t},t.prototype._verifyReinsertion=function(t,e,n,a){var r=null===this._unlinkedRecords?null:this._unlinkedRecords.get(n,null);return null!==r?t=this._reinsertAfter(r,t._prev,a):t.currentIndex!=a&&(t.currentIndex=a,this._addToMoves(t,a)),t},t.prototype._truncate=function(t){for(;null!==t;){var e=t._next;this._addToRemovals(this._unlink(t)),t=e}null!==this._unlinkedRecords&&this._unlinkedRecords.clear(),null!==this._additionsTail&&(this._additionsTail._nextAdded=null),null!==this._movesTail&&(this._movesTail._nextMoved=null),null!==this._itTail&&(this._itTail._next=null),null!==this._removalsTail&&(this._removalsTail._nextRemoved=null),null!==this._identityChangesTail&&(this._identityChangesTail._nextIdentityChange=null)},t.prototype._reinsertAfter=function(t,e,n){null!==this._unlinkedRecords&&this._unlinkedRecords.remove(t);var a=t._prevRemoved,r=t._nextRemoved;return null===a?this._removalsHead=r:a._nextRemoved=r,null===r?this._removalsTail=a:r._prevRemoved=a,this._insertAfter(t,e,n),this._addToMoves(t,n),t},t.prototype._moveAfter=function(t,e,n){return this._unlink(t),this._insertAfter(t,e,n),this._addToMoves(t,n),t},t.prototype._addAfter=function(t,e,n){return this._insertAfter(t,e,n),this._additionsTail=null===this._additionsTail?this._additionsHead=t:this._additionsTail._nextAdded=t,t},t.prototype._insertAfter=function(t,e,n){var a=null===e?this._itHead:e._next;return t._next=a,t._prev=e,null===a?this._itTail=t:a._prev=t,null===e?this._itHead=t:e._next=t,null===this._linkedRecords&&(this._linkedRecords=new Eh),this._linkedRecords.put(t),t.currentIndex=n,t},t.prototype._remove=function(t){return this._addToRemovals(this._unlink(t))},t.prototype._unlink=function(t){null!==this._linkedRecords&&this._linkedRecords.remove(t);var e=t._prev,n=t._next;return null===e?this._itHead=n:e._next=n,null===n?this._itTail=e:n._prev=e,t},t.prototype._addToMoves=function(t,e){return t.previousIndex===e?t:(this._movesTail=null===this._movesTail?this._movesHead=t:this._movesTail._nextMoved=t,t)},t.prototype._addToRemovals=function(t){return null===this._unlinkedRecords&&(this._unlinkedRecords=new Eh),this._unlinkedRecords.put(t),t.currentIndex=null,t._nextRemoved=null,null===this._removalsTail?(this._removalsTail=this._removalsHead=t,t._prevRemoved=null):(t._prevRemoved=this._removalsTail,this._removalsTail=this._removalsTail._nextRemoved=t),t},t.prototype._addIdentityChange=function(t,e){return t.item=e,this._identityChangesTail=null===this._identityChangesTail?this._identityChangesHead=t:this._identityChangesTail._nextIdentityChange=t,t},t}(),Ah=function(){return function(t,e){this.item=t,this.trackById=e,this.currentIndex=null,this.previousIndex=null,this._nextPrevious=null,this._prev=null,this._next=null,this._prevDup=null,this._nextDup=null,this._prevRemoved=null,this._nextRemoved=null,this._nextAdded=null,this._nextMoved=null,this._nextIdentityChange=null}}(),Dh=function(){function t(){this._head=null,this._tail=null}return t.prototype.add=function(t){null===this._head?(this._head=this._tail=t,t._nextDup=null,t._prevDup=null):(this._tail._nextDup=t,t._prevDup=this._tail,t._nextDup=null,this._tail=t)},t.prototype.get=function(t,e){var n;for(n=this._head;null!==n;n=n._nextDup)if((null===e||e<=n.currentIndex)&&K(n.trackById,t))return n;return null},t.prototype.remove=function(t){var e=t._prevDup,n=t._nextDup;return null===e?this._head=n:e._nextDup=n,null===n?this._tail=e:n._prevDup=e,null===this._head},t}(),Eh=function(){function t(){this.map=new Map}return t.prototype.put=function(t){var e=t.trackById,n=this.map.get(e);n||(n=new Dh,this.map.set(e,n)),n.add(t)},t.prototype.get=function(t,e){var n=this.map.get(t);return n?n.get(t,e):null},t.prototype.remove=function(t){var e=t.trackById;return this.map.get(e).remove(t)&&this.map.delete(e),t},Object.defineProperty(t.prototype,"isEmpty",{get:function(){return 0===this.map.size},enumerable:!0,configurable:!0}),t.prototype.clear=function(){this.map.clear()},t}();function Lh(t,e,n){var a=t.previousIndex;if(null===a)return a;var r=0;return n&&a<n.length&&(r=n[a]),a+e+r}var Ph=function(){function t(){}return t.prototype.supports=function(t){return t instanceof Map||fa(t)},t.prototype.create=function(){return new Mh},t}(),Mh=function(){function t(){this._records=new Map,this._mapHead=null,this._appendAfter=null,this._previousMapHead=null,this._changesHead=null,this._changesTail=null,this._additionsHead=null,this._additionsTail=null,this._removalsHead=null,this._removalsTail=null}return Object.defineProperty(t.prototype,"isDirty",{get:function(){return null!==this._additionsHead||null!==this._changesHead||null!==this._removalsHead},enumerable:!0,configurable:!0}),t.prototype.forEachItem=function(t){var e;for(e=this._mapHead;null!==e;e=e._next)t(e)},t.prototype.forEachPreviousItem=function(t){var e;for(e=this._previousMapHead;null!==e;e=e._nextPrevious)t(e)},t.prototype.forEachChangedItem=function(t){var e;for(e=this._changesHead;null!==e;e=e._nextChanged)t(e)},t.prototype.forEachAddedItem=function(t){var e;for(e=this._additionsHead;null!==e;e=e._nextAdded)t(e)},t.prototype.forEachRemovedItem=function(t){var e;for(e=this._removalsHead;null!==e;e=e._nextRemoved)t(e)},t.prototype.diff=function(t){if(t){if(!(t instanceof Map||fa(t)))throw new Error("Error trying to diff '"+$(t)+"'. Only maps and objects are allowed")}else t=new Map;return this.check(t)?this:null},t.prototype.onDestroy=function(){},t.prototype.check=function(t){var e=this;this._reset();var n=this._mapHead;if(this._appendAfter=null,this._forEach(t,function(t,a){if(n&&n.key===a)e._maybeAddToChanges(n,t),e._appendAfter=n,n=n._next;else{var r=e._getOrCreateRecordForKey(a,t);n=e._insertBeforeOrAppend(n,r)}}),n){n._prev&&(n._prev._next=null),this._removalsHead=n;for(var a=n;null!==a;a=a._nextRemoved)a===this._mapHead&&(this._mapHead=null),this._records.delete(a.key),a._nextRemoved=a._next,a.previousValue=a.currentValue,a.currentValue=null,a._prev=null,a._next=null}return this._changesTail&&(this._changesTail._nextChanged=null),this._additionsTail&&(this._additionsTail._nextAdded=null),this.isDirty},t.prototype._insertBeforeOrAppend=function(t,e){if(t){var n=t._prev;return e._next=t,e._prev=n,t._prev=e,n&&(n._next=e),t===this._mapHead&&(this._mapHead=e),this._appendAfter=t,t}return this._appendAfter?(this._appendAfter._next=e,e._prev=this._appendAfter):this._mapHead=e,this._appendAfter=e,null},t.prototype._getOrCreateRecordForKey=function(t,e){if(this._records.has(t)){var n=this._records.get(t);this._maybeAddToChanges(n,e);var a=n._prev,r=n._next;return a&&(a._next=r),r&&(r._prev=a),n._next=null,n._prev=null,n}var i=new qh(t);return this._records.set(t,i),i.currentValue=e,this._addToAdditions(i),i},t.prototype._reset=function(){if(this.isDirty){var t=void 0;for(this._previousMapHead=this._mapHead,t=this._previousMapHead;null!==t;t=t._next)t._nextPrevious=t._next;for(t=this._changesHead;null!==t;t=t._nextChanged)t.previousValue=t.currentValue;for(t=this._additionsHead;null!=t;t=t._nextAdded)t.previousValue=t.currentValue;this._changesHead=this._changesTail=null,this._additionsHead=this._additionsTail=null,this._removalsHead=null}},t.prototype._maybeAddToChanges=function(t,e){K(e,t.currentValue)||(t.previousValue=t.currentValue,t.currentValue=e,this._addToChanges(t))},t.prototype._addToAdditions=function(t){null===this._additionsHead?this._additionsHead=this._additionsTail=t:(this._additionsTail._nextAdded=t,this._additionsTail=t)},t.prototype._addToChanges=function(t){null===this._changesHead?this._changesHead=this._changesTail=t:(this._changesTail._nextChanged=t,this._changesTail=t)},t.prototype._forEach=function(t,e){t instanceof Map?t.forEach(e):Object.keys(t).forEach(function(n){return e(t[n],n)})},t}(),qh=function(){return function(t){this.key=t,this.previousValue=null,this.currentValue=null,this._nextPrevious=null,this._next=null,this._prev=null,this._nextAdded=null,this._nextRemoved=null,this._nextChanged=null}}(),jh=function(){function t(t){this.factories=t}return t.create=function(e,n){if(null!=n){var a=n.factories.slice();e=e.concat(a)}return new t(e)},t.extend=function(e){return{provide:t,useFactory:function(n){if(!n)throw new Error("Cannot extend IterableDiffers without a parent injector");return t.create(e,n)},deps:[[t,new Oe,new we]]}},t.prototype.find=function(t){var e,n=this.factories.find(function(e){return e.supports(t)});if(null!=n)return n;throw new Error("Cannot find a differ supporting object '"+t+"' of type '"+((e=t).name||typeof e)+"'")},t.ngInjectableDef=v({providedIn:"root",factory:function(){return new t([new kh])}}),t}(),Fh=function(){function t(t){this.factories=t}return t.create=function(e,n){if(n){var a=n.factories.slice();e=e.concat(a)}return new t(e)},t.extend=function(e){return{provide:t,useFactory:function(n){if(!n)throw new Error("Cannot extend KeyValueDiffers without a parent injector");return t.create(e,n)},deps:[[t,new Oe,new we]]}},t.prototype.find=function(t){var e=this.factories.find(function(e){return e.supports(t)});if(e)return e;throw new Error("Cannot find a differ supporting object '"+t+"'")},t.ngInjectableDef=v({providedIn:"root",factory:function(){return new t([new Ph])}}),t}(),zh=[new Ph],Gh=new jh([new kh]),Yh=new Fh(zh),Vh=Up(null,"core",[{provide:tp,useValue:"unknown"},{provide:Zp,deps:[ho]},{provide:jp,deps:[]},{provide:ap,deps:[]}]),Hh=new w("LocaleId"),Bh=new w("Translations"),Uh=new w("TranslationsFormat"),Wh=function(t){return t[t.Error=0]="Error",t[t.Warning=1]="Warning",t[t.Ignore=2]="Ignore",t}({});function Kh(){return Gh}function $h(){return Yh}function Zh(t){return t||"en-US"}var Xh=[{provide:Jp,useClass:Jp,deps:[Rp,ap,ho,Sf,ru,Kf]},{provide:Kf,useClass:Kf,deps:[[new we,Wf]]},{provide:bp,useClass:bp,deps:[]},Xf,{provide:jh,useFactory:Kh,deps:[]},{provide:Fh,useFactory:$h,deps:[]},{provide:Hh,useFactory:Zh,deps:[[new Te(Hh),new we,new Oe]]}],Jh=function(){return function(t){}}(),Qh=!0,tg=!1;function eg(t,e,n){var a=t.state,r=1792&a;return r===e?(t.state=-1793&a|n,t.initIndex=-1,!0):r===n}function ng(t,e,n){return(1792&t.state)===e&&t.initIndex<=n&&(t.initIndex=n+1,!0)}function ag(t,e){return t.nodes[e]}function rg(t,e){return t.nodes[e]}function ig(t,e){return t.nodes[e]}function sg(t,e){return t.nodes[e]}function og(t,e){return t.nodes[e]}var ug=function(){return function(){}}(),cg={setCurrentNode:void 0,createRootView:void 0,createEmbeddedView:void 0,createComponentView:void 0,createNgModuleRef:void 0,overrideProvider:void 0,overrideComponentView:void 0,clearOverrides:void 0,checkAndUpdateView:void 0,checkNoChangesView:void 0,destroyView:void 0,resolveDep:void 0,createDebugContext:void 0,handleEvent:void 0,updateDirectives:void 0,updateRenderer:void 0,dirtyParentQueries:void 0};function lg(t,e,n,a){var r="ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '"+e+"'. Current value: '"+n+"'.";return a&&(r+=" It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?"),function(t,e){var n=new Error(t);return dg(n,e),n}(r,t)}function dg(t,e){t[yf]=e,t[_f]=e.logError.bind(e)}function fg(t){return new Error("ViewDestroyedError: Attempt to use a destroyed view: "+t)}var pg=function(){},hg=new Map;function gg(t){var e=hg.get(t);return e||(e=$(t)+"_"+hg.size,hg.set(t,e)),e}function bg(t,e,n,a){if(ca.isWrapped(a)){a=ca.unwrap(a);var r=t.def.nodes[e].bindingIndex+n,i=ca.unwrap(t.oldValues[r]);t.oldValues[r]=new ca(i)}return a}var mg="$$undefined",yg="$$empty";function vg(t){return{id:mg,styles:t.styles,encapsulation:t.encapsulation,data:t.data}}var _g=0;function xg(t,e,n,a){return!(!(2&t.state)&&K(t.oldValues[e.bindingIndex+n],a))}function Tg(t,e,n,a){return!!xg(t,e,n,a)&&(t.oldValues[e.bindingIndex+n]=a,!0)}function wg(t,e,n,a){var r=t.oldValues[e.bindingIndex+n];if(1&t.state||!ua(r,a)){var i=e.bindings[n].name;throw lg(cg.createDebugContext(t,e.nodeIndex),i+": "+r,i+": "+a,0!=(1&t.state))}}function Sg(t){for(var e=t;e;)2&e.def.flags&&(e.state|=8),e=e.viewContainerParent||e.parent}function Og(t,e){for(var n=t;n&&n!==e;)n.state|=64,n=n.viewContainerParent||n.parent}function Ig(t,e,n,a){try{return Sg(33554432&t.def.nodes[e].flags?rg(t,e).componentView:t),cg.handleEvent(t,e,n,a)}catch(r){t.root.errorHandler.handleError(r)}}function Cg(t){return t.parent?rg(t.parent,t.parentNodeDef.nodeIndex):null}function kg(t){return t.parent?t.parentNodeDef.parent:null}function Ng(t,e){switch(201347067&e.flags){case 1:return rg(t,e.nodeIndex).renderElement;case 2:return ag(t,e.nodeIndex).renderText}}function Rg(t,e){return t?t+":"+e:e}function Ag(t){return!!t.parent&&!!(32768&t.parentNodeDef.flags)}function Dg(t){return!(!t.parent||32768&t.parentNodeDef.flags)}function Eg(t){return 1<<t%32}function Lg(t){var e={},n=0,r={};return t&&t.forEach(function(t){var i=Object(a.__read)(t,2),s=i[0],o=i[1];"number"==typeof s?(e[s]=o,n|=Eg(s)):r[s]=o}),{matchedQueries:e,references:r,matchedQueryIds:n}}function Pg(t,e){return t.map(function(t){var n,r,i;return Array.isArray(t)?(i=(n=Object(a.__read)(t,2))[0],r=n[1]):(i=0,r=t),r&&("function"==typeof r||"object"==typeof r)&&e&&Object.defineProperty(r,uo,{value:e,configurable:!0}),{flags:i,token:r,tokenKey:gg(r)}})}function Mg(t,e,n){var a=n.renderParent;return a?0==(1&a.flags)||0==(33554432&a.flags)||a.element.componentRendererType&&a.element.componentRendererType.encapsulation===at.Native?rg(t,n.renderParent.nodeIndex).renderElement:void 0:e}var qg=new WeakMap;function jg(t){var e=qg.get(t);return e||((e=t(function(){return pg})).factory=t,qg.set(t,e)),e}function Fg(t,e,n,a,r){3===e&&(n=t.renderer.parentNode(Ng(t,t.def.lastRenderRootNode))),zg(t,e,0,t.def.nodes.length-1,n,a,r)}function zg(t,e,n,a,r,i,s){for(var o=n;o<=a;o++){var u=t.def.nodes[o];11&u.flags&&Yg(t,u,e,r,i,s),o+=u.childCount}}function Gg(t,e,n,a,r,i){for(var s=t;s&&!Ag(s);)s=s.parent;for(var o=s.parent,u=kg(s),c=u.nodeIndex+u.childCount,l=u.nodeIndex+1;l<=c;l++){var d=o.def.nodes[l];d.ngContentIndex===e&&Yg(o,d,n,a,r,i),l+=d.childCount}if(!o.parent){var f=t.root.projectableNodes[e];if(f)for(l=0;l<f.length;l++)Vg(t,f[l],n,a,r,i)}}function Yg(t,e,n,a,r,i){if(8&e.flags)Gg(t,e.ngContent.index,n,a,r,i);else{var s=Ng(t,e);if(3===n&&33554432&e.flags&&48&e.bindingFlags?(16&e.bindingFlags&&Vg(t,s,n,a,r,i),32&e.bindingFlags&&Vg(rg(t,e.nodeIndex).componentView,s,n,a,r,i)):Vg(t,s,n,a,r,i),16777216&e.flags)for(var o=rg(t,e.nodeIndex).viewContainer._embeddedViews,u=0;u<o.length;u++)Fg(o[u],n,a,r,i);1&e.flags&&!e.element.name&&zg(t,n,e.nodeIndex+1,e.nodeIndex+e.childCount,a,r,i)}}function Vg(t,e,n,a,r,i){var s=t.renderer;switch(n){case 1:s.appendChild(a,e);break;case 2:s.insertBefore(a,e,r);break;case 3:s.removeChild(a,e);break;case 0:i.push(e)}}var Hg=/^:([^:]+):(.+)$/;function Bg(t){if(":"===t[0]){var e=t.match(Hg);return[e[1],e[2]]}return["",t]}function Ug(t){for(var e=0,n=0;n<t.length;n++)e|=t[n].flags;return e}function Wg(t,e){for(var n="",a=0;a<2*t;a+=2)n=n+e[a]+$g(e[a+1]);return n+e[2*t]}function Kg(t,e,n,a,r,i,s,o,u,c,l,d,f,p,h,g,b,m,y,v){switch(t){case 1:return e+$g(n)+a;case 2:return e+$g(n)+a+$g(r)+i;case 3:return e+$g(n)+a+$g(r)+i+$g(s)+o;case 4:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c;case 5:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c+$g(l)+d;case 6:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c+$g(l)+d+$g(f)+p;case 7:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c+$g(l)+d+$g(f)+p+$g(h)+g;case 8:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c+$g(l)+d+$g(f)+p+$g(h)+g+$g(b)+m;case 9:return e+$g(n)+a+$g(r)+i+$g(s)+o+$g(u)+c+$g(l)+d+$g(f)+p+$g(h)+g+$g(b)+m+$g(y)+v;default:throw new Error("Does not support more than 9 expressions")}}function $g(t){return null!=t?t.toString():""}var Zg=[],Xg={};function Jg(t,e,n,a,r,i){t|=1;var s=Lg(e);return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,flags:t,checkIndex:-1,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:s.matchedQueries,matchedQueryIds:s.matchedQueryIds,references:s.references,ngContentIndex:n,childCount:a,bindings:[],bindingFlags:0,outputs:[],element:{ns:null,name:null,attrs:null,template:i?jg(i):null,componentProvider:null,componentView:null,componentRendererType:null,publicProviders:null,allProviders:null,handleEvent:r||pg},provider:null,text:null,query:null,ngContent:null}}function Qg(t,e,n,r,i,s,o,u,c,l,d,f){var p;void 0===o&&(o=[]),l||(l=pg);var h=Lg(n),g=h.matchedQueries,b=h.references,m=h.matchedQueryIds,y=null,v=null;s&&(y=(p=Object(a.__read)(Bg(s),2))[0],v=p[1]),u=u||[];for(var _=new Array(u.length),x=0;x<u.length;x++){var T=Object(a.__read)(u[x],3),w=T[0],S=T[1],O=T[2],I=Object(a.__read)(Bg(S),2),C=I[0],k=I[1],N=void 0,R=void 0;switch(15&w){case 4:R=O;break;case 1:case 8:N=O}_[x]={flags:w,ns:C,name:k,nonMinifiedName:k,securityContext:N,suffix:R}}c=c||[];var A=new Array(c.length);for(x=0;x<c.length;x++){var D=Object(a.__read)(c[x],2);A[x]={type:0,target:D[0],eventName:D[1],propName:null}}var E=(o=o||[]).map(function(t){var e=Object(a.__read)(t,2),n=e[0],r=e[1],i=Object(a.__read)(Bg(n),2);return[i[0],i[1],r]});return f=function(t){if(t&&t.id===mg){var e=null!=t.encapsulation&&t.encapsulation!==at.None||t.styles.length||Object.keys(t.data).length;t.id=e?"c"+_g++:yg}return t&&t.id===yg&&(t=null),t||null}(f),d&&(e|=33554432),{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:t,flags:e|=1,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:g,matchedQueryIds:m,references:b,ngContentIndex:r,childCount:i,bindings:_,bindingFlags:Ug(_),outputs:A,element:{ns:y,name:v,attrs:E,template:null,componentProvider:null,componentView:d||null,componentRendererType:f,publicProviders:null,allProviders:null,handleEvent:l||pg},provider:null,text:null,query:null,ngContent:null}}function tb(t,e,n){var r,i=n.element,s=t.root.selectorOrNode,o=t.renderer;if(t.parent||!s){r=i.name?o.createElement(i.name,i.ns):o.createComment("");var u=Mg(t,e,n);u&&o.appendChild(u,r)}else r=o.selectRootElement(s,!!i.componentRendererType&&i.componentRendererType.encapsulation===at.ShadowDom);if(i.attrs)for(var c=0;c<i.attrs.length;c++){var l=Object(a.__read)(i.attrs[c],3);o.setAttribute(r,l[1],l[2],l[0])}return r}function eb(t,e,n,a){for(var r=0;r<n.outputs.length;r++){var i=n.outputs[r],s=nb(t,n.nodeIndex,Rg(i.target,i.eventName)),o=i.target,u=t;"component"===i.target&&(o=null,u=e);var c=u.renderer.listen(o||a,i.eventName,s);t.disposables[n.outputIndex+r]=c}}function nb(t,e,n){return function(a){return Ig(t,e,n,a)}}function ab(t,e,n,a){if(!Tg(t,e,n,a))return!1;var r=e.bindings[n],i=rg(t,e.nodeIndex),s=i.renderElement,o=r.name;switch(15&r.flags){case 1:!function(t,e,n,a,r,i){var s=e.securityContext,o=s?t.root.sanitizer.sanitize(s,i):i;o=null!=o?o.toString():null;var u=t.renderer;null!=i?u.setAttribute(n,r,o,a):u.removeAttribute(n,r,a)}(t,r,s,r.ns,o,a);break;case 2:!function(t,e,n,a){var r=t.renderer;a?r.addClass(e,n):r.removeClass(e,n)}(t,s,o,a);break;case 4:!function(t,e,n,a,r){var i=t.root.sanitizer.sanitize(Iu.STYLE,r);if(null!=i){i=i.toString();var s=e.suffix;null!=s&&(i+=s)}else i=null;var o=t.renderer;null!=i?o.setStyle(n,a,i):o.removeStyle(n,a)}(t,r,s,o,a);break;case 8:!function(t,e,n,a,r){var i=e.securityContext,s=i?t.root.sanitizer.sanitize(i,r):r;t.renderer.setProperty(n,a,s)}(33554432&e.flags&&32&r.flags?i.componentView:t,r,s,o,a)}return!0}var rb=new Object,ib=gg(ho),sb=gg(fo),ob=gg(ou);function ub(t,e,n,a){return n=J(n),{index:-1,deps:Pg(a,$(e)),flags:t,token:e,value:n}}function cb(t){for(var e={},n=[],a=!1,r=0;r<t.length;r++){var i=t[r];i.token===No&&!0===i.value&&(a=!0),1073741824&i.flags&&n.push(i.token),i.index=r,e[gg(i.token)]=i}return{factory:null,providersByKey:e,providers:t,modules:n,isRoot:a}}function lb(t,e,n){void 0===n&&(n=ho.THROW_IF_NOT_FOUND);var a,r,i=Ne(t);try{if(8&e.flags)return e.token;if(2&e.flags&&(n=null),1&e.flags)return t._parent.get(e.token,n);var s=e.tokenKey;switch(s){case ib:case sb:case ob:return t}var o,u=t._def.providersByKey[s];if(u){var c=t._providers[u.index];return void 0===c&&(c=t._providers[u.index]=db(t,u)),c===rb?void 0:c}if((o=x(e.token))&&(a=t,null!=(r=o).providedIn&&(function(t,e){return t._def.modules.indexOf(r.providedIn)>-1}(a)||"root"===r.providedIn&&a._def.isRoot))){var l=t._providers.length;return t._def.providersByKey[e.tokenKey]={flags:5120,value:o.factory,deps:[],index:l,token:e.token},t._providers[l]=rb,t._providers[l]=db(t,t._def.providersByKey[e.tokenKey])}return 4&e.flags?n:t._parent.get(e.token,n)}finally{Ne(i)}}function db(t,e){var n;switch(201347067&e.flags){case 512:n=function(t,e,n){var r=n.length;switch(r){case 0:return new e;case 1:return new e(lb(t,n[0]));case 2:return new e(lb(t,n[0]),lb(t,n[1]));case 3:return new e(lb(t,n[0]),lb(t,n[1]),lb(t,n[2]));default:for(var i=new Array(r),s=0;s<r;s++)i[s]=lb(t,n[s]);return new(e.bind.apply(e,Object(a.__spread)([void 0],i)))}}(t,e.value,e.deps);break;case 1024:n=function(t,e,n){var r=n.length;switch(r){case 0:return e();case 1:return e(lb(t,n[0]));case 2:return e(lb(t,n[0]),lb(t,n[1]));case 3:return e(lb(t,n[0]),lb(t,n[1]),lb(t,n[2]));default:for(var i=Array(r),s=0;s<r;s++)i[s]=lb(t,n[s]);return e.apply(void 0,Object(a.__spread)(i))}}(t,e.value,e.deps);break;case 2048:n=lb(t,e.deps[0]);break;case 256:n=e.value}return n===rb||null==n||"object"!=typeof n||131072&e.flags||"function"!=typeof n.ngOnDestroy||(e.flags|=131072),void 0===n?rb:n}function fb(t,e){var n=t.viewContainer._embeddedViews;if((null==e||e>=n.length)&&(e=n.length-1),e<0)return null;var a=n[e];return a.viewContainerParent=null,bb(n,e),cg.dirtyParentQueries(a),hb(a),a}function pb(t,e,n){var a=e?Ng(e,e.def.lastRenderRootNode):t.renderElement,r=n.renderer.parentNode(a),i=n.renderer.nextSibling(a);Fg(n,2,r,i,void 0)}function hb(t){Fg(t,3,null,null,void 0)}function gb(t,e,n){e>=t.length?t.push(n):t.splice(e,0,n)}function bb(t,e){e>=t.length-1?t.pop():t.splice(e,1)}var mb=new Object;function yb(t,e,n,a,r,i){return new _b(t,e,n,a,r,i)}function vb(t){return t.viewDefFactory}var _b=function(t){function e(e,n,a,r,i,s){var o=t.call(this)||this;return o.selector=e,o.componentType=n,o._inputs=r,o._outputs=i,o.ngContentSelectors=s,o.viewDefFactory=a,o}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"inputs",{get:function(){var t=[],e=this._inputs;for(var n in e)t.push({propName:n,templateName:e[n]});return t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"outputs",{get:function(){var t=[];for(var e in this._outputs)t.push({propName:e,templateName:this._outputs[e]});return t},enumerable:!0,configurable:!0}),e.prototype.create=function(t,e,n,a){if(!a)throw new Error("ngModule should be provided");var r=jg(this.viewDefFactory),i=r.nodes[0].element.componentProvider.nodeIndex,s=cg.createRootView(t,e||[],n,r,a,mb),o=ig(s,i).instance;return n&&s.renderer.setAttribute(rg(s,0).renderElement,"ng-version",Nu.full),new xb(s,new Ob(s),o)},e}(Xo),xb=function(t){function e(e,n,a){var r=t.call(this)||this;return r._view=e,r._viewRef=n,r._component=a,r._elDef=r._view.def.nodes[0],r.hostView=n,r.changeDetectorRef=n,r.instance=a,r}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"location",{get:function(){return new hu(rg(this._view,this._elDef.nodeIndex).renderElement)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"injector",{get:function(){return new Nb(this._view,this._elDef)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"componentType",{get:function(){return this._component.constructor},enumerable:!0,configurable:!0}),e.prototype.destroy=function(){this._viewRef.destroy()},e.prototype.onDestroy=function(t){this._viewRef.onDestroy(t)},e}(Zo);function Tb(t,e,n){return new wb(t,e,n)}var wb=function(){function t(t,e,n){this._view=t,this._elDef=e,this._data=n,this._embeddedViews=[]}return Object.defineProperty(t.prototype,"element",{get:function(){return new hu(this._data.renderElement)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"injector",{get:function(){return new Nb(this._view,this._elDef)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"parentInjector",{get:function(){for(var t=this._view,e=this._elDef.parent;!e&&t;)e=kg(t),t=t.parent;return t?new Nb(t,e):new Nb(this._view,null)},enumerable:!0,configurable:!0}),t.prototype.clear=function(){for(var t=this._embeddedViews.length-1;t>=0;t--){var e=fb(this._data,t);cg.destroyView(e)}},t.prototype.get=function(t){var e=this._embeddedViews[t];if(e){var n=new Ob(e);return n.attachToViewContainerRef(this),n}return null},Object.defineProperty(t.prototype,"length",{get:function(){return this._embeddedViews.length},enumerable:!0,configurable:!0}),t.prototype.createEmbeddedView=function(t,e,n){var a=t.createEmbeddedView(e||{});return this.insert(a,n),a},t.prototype.createComponent=function(t,e,n,a,r){var i=n||this.parentInjector;r||t instanceof su||(r=i.get(ou));var s=t.create(i,a,void 0,r);return this.insert(s.hostView,e),s},t.prototype.insert=function(t,e){if(t.destroyed)throw new Error("Cannot insert a destroyed View in a ViewContainer!");var n,a,r,i,s=t;return i=(n=this._data).viewContainer._embeddedViews,null==(a=e)&&(a=i.length),(r=s._view).viewContainerParent=this._view,gb(i,a,r),function(t,e){var n=Cg(e);if(n&&n!==t&&!(16&e.state)){e.state|=16;var a=n.template._projectedViews;a||(a=n.template._projectedViews=[]),a.push(e),function(t,n){if(!(4&n.flags)){e.parent.def.nodeFlags|=4,n.flags|=4;for(var a=n.parent;a;)a.childFlags|=4,a=a.parent}}(0,e.parentNodeDef)}}(n,r),cg.dirtyParentQueries(r),pb(n,a>0?i[a-1]:null,r),s.attachToViewContainerRef(this),t},t.prototype.move=function(t,e){if(t.destroyed)throw new Error("Cannot move a destroyed View in a ViewContainer!");var n,a,r,i,s,o=this._embeddedViews.indexOf(t._view);return r=e,s=(i=(n=this._data).viewContainer._embeddedViews)[a=o],bb(i,a),null==r&&(r=i.length),gb(i,r,s),cg.dirtyParentQueries(s),hb(s),pb(n,r>0?i[r-1]:null,s),t},t.prototype.indexOf=function(t){return this._embeddedViews.indexOf(t._view)},t.prototype.remove=function(t){var e=fb(this._data,t);e&&cg.destroyView(e)},t.prototype.detach=function(t){var e=fb(this._data,t);return e?new Ob(e):null},t}();function Sb(t){return new Ob(t)}var Ob=function(){function t(t){this._view=t,this._viewContainerRef=null,this._appRef=null}return Object.defineProperty(t.prototype,"rootNodes",{get:function(){return Fg(this._view,0,void 0,void 0,t=[]),t;var t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this._view.context},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"destroyed",{get:function(){return 0!=(128&this._view.state)},enumerable:!0,configurable:!0}),t.prototype.markForCheck=function(){Sg(this._view)},t.prototype.detach=function(){this._view.state&=-5},t.prototype.detectChanges=function(){var t=this._view.root.rendererFactory;t.begin&&t.begin();try{cg.checkAndUpdateView(this._view)}finally{t.end&&t.end()}},t.prototype.checkNoChanges=function(){cg.checkNoChangesView(this._view)},t.prototype.reattach=function(){this._view.state|=4},t.prototype.onDestroy=function(t){this._view.disposables||(this._view.disposables=[]),this._view.disposables.push(t)},t.prototype.destroy=function(){this._appRef?this._appRef.detachView(this):this._viewContainerRef&&this._viewContainerRef.detach(this._viewContainerRef.indexOf(this)),cg.destroyView(this._view)},t.prototype.detachFromAppRef=function(){this._appRef=null,hb(this._view),cg.dirtyParentQueries(this._view)},t.prototype.attachToAppRef=function(t){if(this._viewContainerRef)throw new Error("This view is already attached to a ViewContainer!");this._appRef=t},t.prototype.attachToViewContainerRef=function(t){if(this._appRef)throw new Error("This view is already attached directly to the ApplicationRef!");this._viewContainerRef=t},t}();function Ib(t,e){return new Cb(t,e)}var Cb=function(t){function e(e,n){var a=t.call(this)||this;return a._parentView=e,a._def=n,a}return Object(a.__extends)(e,t),e.prototype.createEmbeddedView=function(t){return new Ob(cg.createEmbeddedView(this._parentView,this._def,this._def.element.template,t))},Object.defineProperty(e.prototype,"elementRef",{get:function(){return new hu(rg(this._parentView,this._def.nodeIndex).renderElement)},enumerable:!0,configurable:!0}),e}(gl);function kb(t,e){return new Nb(t,e)}var Nb=function(){function t(t,e){this.view=t,this.elDef=e}return t.prototype.get=function(t,e){return void 0===e&&(e=ho.THROW_IF_NOT_FOUND),cg.resolveDep(this.view,this.elDef,!!this.elDef&&0!=(33554432&this.elDef.flags),{flags:0,token:t,tokenKey:gg(t)},e)},t}();function Rb(t,e){var n=t.def.nodes[e];if(1&n.flags){var a=rg(t,n.nodeIndex);return n.element.template?a.template:a.renderElement}if(2&n.flags)return ag(t,n.nodeIndex).renderText;if(20240&n.flags)return ig(t,n.nodeIndex).instance;throw new Error("Illegal state: read nodeValue for node index "+e)}function Ab(t){return new Db(t.renderer)}var Db=function(){function t(t){this.delegate=t}return t.prototype.selectRootElement=function(t){return this.delegate.selectRootElement(t)},t.prototype.createElement=function(t,e){var n=Object(a.__read)(Bg(e),2),r=this.delegate.createElement(n[1],n[0]);return t&&this.delegate.appendChild(t,r),r},t.prototype.createViewRoot=function(t){return t},t.prototype.createTemplateAnchor=function(t){var e=this.delegate.createComment("");return t&&this.delegate.appendChild(t,e),e},t.prototype.createText=function(t,e){var n=this.delegate.createText(e);return t&&this.delegate.appendChild(t,n),n},t.prototype.projectNodes=function(t,e){for(var n=0;n<e.length;n++)this.delegate.appendChild(t,e[n])},t.prototype.attachViewAfter=function(t,e){for(var n=this.delegate.parentNode(t),a=this.delegate.nextSibling(t),r=0;r<e.length;r++)this.delegate.insertBefore(n,e[r],a)},t.prototype.detachView=function(t){for(var e=0;e<t.length;e++){var n=t[e],a=this.delegate.parentNode(n);this.delegate.removeChild(a,n)}},t.prototype.destroyView=function(t,e){for(var n=0;n<e.length;n++)this.delegate.destroyNode(e[n])},t.prototype.listen=function(t,e,n){return this.delegate.listen(t,e,n)},t.prototype.listenGlobal=function(t,e,n){return this.delegate.listen(t,e,n)},t.prototype.setElementProperty=function(t,e,n){this.delegate.setProperty(t,e,n)},t.prototype.setElementAttribute=function(t,e,n){var r=Object(a.__read)(Bg(e),2),i=r[0],s=r[1];null!=n?this.delegate.setAttribute(t,s,n,i):this.delegate.removeAttribute(t,s,i)},t.prototype.setBindingDebugInfo=function(t,e,n){},t.prototype.setElementClass=function(t,e,n){n?this.delegate.addClass(t,e):this.delegate.removeClass(t,e)},t.prototype.setElementStyle=function(t,e,n){null!=n?this.delegate.setStyle(t,e,n):this.delegate.removeStyle(t,e)},t.prototype.invokeElementMethod=function(t,e,n){t[e].apply(t,n)},t.prototype.setText=function(t,e){this.delegate.setValue(t,e)},t.prototype.animate=function(){throw new Error("Renderer.animate is no longer supported!")},t}();function Eb(t,e,n,a){return new Lb(t,e,n,a)}var Lb=function(){function t(t,e,n,a){this._moduleType=t,this._parent=e,this._bootstrapComponents=n,this._def=a,this._destroyListeners=[],this._destroyed=!1,this.injector=this,function(t){for(var e=t._def,n=t._providers=new Array(e.providers.length),a=0;a<e.providers.length;a++){var r=e.providers[a];4096&r.flags||void 0===n[a]&&(n[a]=db(t,r))}}(this)}return t.prototype.get=function(t,e,n){void 0===e&&(e=ho.THROW_IF_NOT_FOUND),void 0===n&&(n=Ce.Default);var a=0;return n&Ce.SkipSelf?a|=1:n&Ce.Self&&(a|=4),lb(this,{token:t,tokenKey:gg(t),flags:a},e)},Object.defineProperty(t.prototype,"instance",{get:function(){return this.get(this._moduleType)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"componentFactoryResolver",{get:function(){return this.get(ru)},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){if(this._destroyed)throw new Error("The ng module "+$(this.instance.constructor)+" has already been destroyed.");this._destroyed=!0,function(t,e){for(var n=t._def,a=new Set,r=0;r<n.providers.length;r++)if(131072&n.providers[r].flags){var i=t._providers[r];if(i&&i!==rb){var s=i.ngOnDestroy;"function"!=typeof s||a.has(i)||(s.apply(i),a.add(i))}}}(this),this._destroyListeners.forEach(function(t){return t()})},t.prototype.onDestroy=function(t){this._destroyListeners.push(t)},t}(),Pb=gg(vu),Mb=gg(wu),qb=gg(hu),jb=gg(ih),Fb=gg(gl),zb=gg(uh),Gb=gg(ho),Yb=gg(fo);function Vb(t,e,n,r,i,s,o,u){var c=[];if(o)for(var l in o){var d=Object(a.__read)(o[l],2);c[d[0]]={flags:8,name:l,nonMinifiedName:d[1],ns:null,securityContext:null,suffix:null}}var f=[];if(u)for(var p in u)f.push({type:1,propName:p,target:null,eventName:u[p]});return Ub(t,e|=16384,n,r,i,i,s,c,f)}function Hb(t,e,n){return Ub(-1,t|=16,null,0,e,e,n)}function Bb(t,e,n,a,r){return Ub(-1,t,e,0,n,a,r)}function Ub(t,e,n,a,r,i,s,o,u){var c=Lg(n),l=c.matchedQueries,d=c.references,f=c.matchedQueryIds;u||(u=[]),o||(o=[]),i=J(i);var p=Pg(s,$(r));return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:t,flags:e,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:l,matchedQueryIds:f,references:d,ngContentIndex:-1,childCount:a,bindings:o,bindingFlags:Ug(o),outputs:u,element:null,provider:{token:r,value:i,deps:p},text:null,query:null,ngContent:null}}function Wb(t,e){return Xb(t,e)}function Kb(t,e){for(var n=t;n.parent&&!Ag(n);)n=n.parent;return Jb(n.parent,kg(n),!0,e.provider.value,e.provider.deps)}function $b(t,e){var n=Jb(t,e.parent,(32768&e.flags)>0,e.provider.value,e.provider.deps);if(e.outputs.length)for(var a=0;a<e.outputs.length;a++){var r=e.outputs[a],i=n[r.propName];if(!Uf(i))throw new Error("@Output "+r.propName+" not initialized in '"+n.constructor.name+"'.");var s=i.subscribe(Zb(t,e.parent.nodeIndex,r.eventName));t.disposables[e.outputIndex+a]=s.unsubscribe.bind(s)}return n}function Zb(t,e,n){return function(a){return Ig(t,e,n,a)}}function Xb(t,e){var n=(8192&e.flags)>0,r=e.provider;switch(201347067&e.flags){case 512:return Jb(t,e.parent,n,r.value,r.deps);case 1024:return function(t,e,n,r,i){var s=i.length;switch(s){case 0:return r();case 1:return r(tm(t,e,n,i[0]));case 2:return r(tm(t,e,n,i[0]),tm(t,e,n,i[1]));case 3:return r(tm(t,e,n,i[0]),tm(t,e,n,i[1]),tm(t,e,n,i[2]));default:for(var o=Array(s),u=0;u<s;u++)o[u]=tm(t,e,n,i[u]);return r.apply(void 0,Object(a.__spread)(o))}}(t,e.parent,n,r.value,r.deps);case 2048:return tm(t,e.parent,n,r.deps[0]);case 256:return r.value}}function Jb(t,e,n,r,i){var s=i.length;switch(s){case 0:return new r;case 1:return new r(tm(t,e,n,i[0]));case 2:return new r(tm(t,e,n,i[0]),tm(t,e,n,i[1]));case 3:return new r(tm(t,e,n,i[0]),tm(t,e,n,i[1]),tm(t,e,n,i[2]));default:for(var o=new Array(s),u=0;u<s;u++)o[u]=tm(t,e,n,i[u]);return new(r.bind.apply(r,Object(a.__spread)([void 0],o)))}}var Qb={};function tm(t,e,n,a,r){if(void 0===r&&(r=ho.THROW_IF_NOT_FOUND),8&a.flags)return a.token;var i=t;2&a.flags&&(r=null);var s=a.tokenKey;s===zb&&(n=!(!e||!e.element.componentView)),e&&1&a.flags&&(n=!1,e=e.parent);for(var o=t;o;){if(e)switch(s){case Pb:return Ab(em(o,e,n));case Mb:return em(o,e,n).renderer;case qb:return new hu(rg(o,e.nodeIndex).renderElement);case jb:return rg(o,e.nodeIndex).viewContainer;case Fb:if(e.element.template)return rg(o,e.nodeIndex).template;break;case zb:return Sb(em(o,e,n));case Gb:case Yb:return kb(o,e);default:var u=(n?e.element.allProviders:e.element.publicProviders)[s];if(u){var c=ig(o,u.nodeIndex);return c||(c={instance:Xb(o,u)},o.nodes[u.nodeIndex]=c),c.instance}}n=Ag(o),e=kg(o),o=o.parent,4&a.flags&&(o=null)}var l=i.root.injector.get(a.token,Qb);return l!==Qb||r===Qb?l:i.root.ngModule.injector.get(a.token,r)}function em(t,e,n){var a;if(n)a=rg(t,e.nodeIndex).componentView;else for(a=t;a.parent&&!Ag(a);)a=a.parent;return a}function nm(t,e,n,a,r,i){if(32768&n.flags){var s=rg(t,n.parent.nodeIndex).componentView;2&s.def.flags&&(s.state|=8)}if(e.instance[n.bindings[a].name]=r,524288&n.flags){i=i||{};var o=ca.unwrap(t.oldValues[n.bindingIndex+a]);i[n.bindings[a].nonMinifiedName]=new la(o,r,0!=(2&t.state))}return t.oldValues[n.bindingIndex+a]=r,i}function am(t,e){if(t.def.nodeFlags&e)for(var n=t.def.nodes,a=0,r=0;r<n.length;r++){var i=n[r],s=i.parent;for(!s&&i.flags&e&&im(t,r,i.flags&e,a++),0==(i.childFlags&e)&&(r+=i.childCount);s&&1&s.flags&&r===s.nodeIndex+s.childCount;)s.directChildFlags&e&&(a=rm(t,s,e,a)),s=s.parent}}function rm(t,e,n,a){for(var r=e.nodeIndex+1;r<=e.nodeIndex+e.childCount;r++){var i=t.def.nodes[r];i.flags&n&&im(t,r,i.flags&n,a++),r+=i.childCount}return a}function im(t,e,n,a){var r=ig(t,e);if(r){var i=r.instance;i&&(cg.setCurrentNode(t,e),1048576&n&&ng(t,512,a)&&i.ngAfterContentInit(),2097152&n&&i.ngAfterContentChecked(),4194304&n&&ng(t,768,a)&&i.ngAfterViewInit(),8388608&n&&i.ngAfterViewChecked(),131072&n&&i.ngOnDestroy())}}function sm(t,e,n){var a=[];for(var r in n)a.push({propName:r,bindingType:n[r]});return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:-1,flags:t,childFlags:0,directChildFlags:0,childMatchedQueries:0,ngContentIndex:-1,matchedQueries:{},matchedQueryIds:0,references:{},childCount:0,bindings:[],bindingFlags:0,outputs:[],element:null,provider:null,text:null,query:{id:e,filterId:Eg(e),bindings:a},ngContent:null}}function om(t){for(var e=t.def.nodeMatchedQueries;t.parent&&Dg(t);){var n=t.parentNodeDef;t=t.parent;for(var a=n.nodeIndex+n.childCount,r=0;r<=a;r++)67108864&(i=t.def.nodes[r]).flags&&536870912&i.flags&&(i.query.filterId&e)===i.query.filterId&&og(t,r).setDirty(),!(1&i.flags&&r+i.childCount<n.nodeIndex)&&67108864&i.childFlags&&536870912&i.childFlags||(r+=i.childCount)}if(134217728&t.def.nodeFlags)for(r=0;r<t.def.nodes.length;r++){var i;134217728&(i=t.def.nodes[r]).flags&&536870912&i.flags&&og(t,r).setDirty(),r+=i.childCount}}function um(t,e){var n=og(t,e.nodeIndex);if(n.dirty){var a,r=void 0;if(67108864&e.flags){var i=e.parent.parent;r=cm(t,i.nodeIndex,i.nodeIndex+i.childCount,e.query,[]),a=ig(t,e.parent.nodeIndex).instance}else 134217728&e.flags&&(r=cm(t,0,t.def.nodes.length-1,e.query,[]),a=t.component);n.reset(r);for(var s=e.query.bindings,o=!1,u=0;u<s.length;u++){var c=s[u],l=void 0;switch(c.bindingType){case 0:l=n.first;break;case 1:l=n,o=!0}a[c.propName]=l}o&&n.notifyOnChanges()}}function cm(t,e,n,a,r){for(var i=e;i<=n;i++){var s=t.def.nodes[i],o=s.matchedQueries[a.id];if(null!=o&&r.push(lm(t,s,o)),1&s.flags&&s.element.template&&(s.element.template.nodeMatchedQueries&a.filterId)===a.filterId){var u=rg(t,i);if((s.childMatchedQueries&a.filterId)===a.filterId&&(cm(t,i+1,i+s.childCount,a,r),i+=s.childCount),16777216&s.flags)for(var c=u.viewContainer._embeddedViews,l=0;l<c.length;l++){var d=c[l],f=Cg(d);f&&f===u&&cm(d,0,d.def.nodes.length-1,a,r)}var p=u.template._projectedViews;if(p)for(l=0;l<p.length;l++){var h=p[l];cm(h,0,h.def.nodes.length-1,a,r)}}(s.childMatchedQueries&a.filterId)!==a.filterId&&(i+=s.childCount)}return r}function lm(t,e,n){if(null!=n)switch(n){case 1:return rg(t,e.nodeIndex).renderElement;case 0:return new hu(rg(t,e.nodeIndex).renderElement);case 2:return rg(t,e.nodeIndex).template;case 3:return rg(t,e.nodeIndex).viewContainer;case 4:return ig(t,e.nodeIndex).instance}}function dm(t,e){return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:-1,flags:8,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:{},matchedQueryIds:0,references:{},ngContentIndex:t,childCount:0,bindings:[],bindingFlags:0,outputs:[],element:null,provider:null,text:null,query:null,ngContent:{index:e}}}function fm(t,e,n){var a=Mg(t,e,n);a&&Gg(t,n.ngContent.index,1,a,null,void 0)}function pm(t,e){return bm(128,t,new Array(e+1))}function hm(t,e){return bm(32,t,new Array(e))}function gm(t,e){for(var n=Object.keys(e),a=n.length,r=new Array(a),i=0;i<a;i++){var s=n[i];r[e[s]]=s}return bm(64,t,r)}function bm(t,e,n){for(var a=new Array(n.length),r=0;r<n.length;r++){var i=n[r];a[r]={flags:8,name:i,ns:null,nonMinifiedName:i,securityContext:null,suffix:null}}return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:e,flags:t,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:{},matchedQueryIds:0,references:{},ngContentIndex:-1,childCount:0,bindings:a,bindingFlags:Ug(a),outputs:[],element:null,provider:null,text:null,query:null,ngContent:null}}function mm(t,e,n){for(var a=new Array(n.length-1),r=1;r<n.length;r++)a[r-1]={flags:8,name:null,ns:null,nonMinifiedName:null,securityContext:null,suffix:n[r]};return{nodeIndex:-1,parent:null,renderParent:null,bindingIndex:-1,outputIndex:-1,checkIndex:t,flags:2,childFlags:0,directChildFlags:0,childMatchedQueries:0,matchedQueries:{},matchedQueryIds:0,references:{},ngContentIndex:e,childCount:0,bindings:a,bindingFlags:8,outputs:[],element:null,provider:null,text:{prefix:n[0]},query:null,ngContent:null}}function ym(t,e,n){var a,r=t.renderer;a=r.createText(n.text.prefix);var i=Mg(t,e,n);return i&&r.appendChild(i,a),{renderText:a}}function vm(t,e){return(null!=t?t.toString():"")+e.suffix}function _m(t,e,n,a){for(var r=0,i=0,s=0,o=0,u=0,c=null,l=null,d=!1,f=!1,p=null,h=0;h<e.length;h++){var g=e[h];if(g.nodeIndex=h,g.parent=c,g.bindingIndex=r,g.outputIndex=i,g.renderParent=l,s|=g.flags,u|=g.matchedQueryIds,g.element){var b=g.element;b.publicProviders=c?c.element.publicProviders:Object.create(null),b.allProviders=b.publicProviders,d=!1,f=!1,g.element.template&&(u|=g.element.template.nodeMatchedQueries)}if(Tm(c,g,e.length),r+=g.bindings.length,i+=g.outputs.length,!l&&3&g.flags&&(p=g),20224&g.flags){d||(d=!0,c.element.publicProviders=Object.create(c.element.publicProviders),c.element.allProviders=c.element.publicProviders);var m=0!=(32768&g.flags);0==(8192&g.flags)||m?c.element.publicProviders[gg(g.provider.token)]=g:(f||(f=!0,c.element.allProviders=Object.create(c.element.publicProviders)),c.element.allProviders[gg(g.provider.token)]=g),m&&(c.element.componentProvider=g)}if(c?(c.childFlags|=g.flags,c.directChildFlags|=g.flags,c.childMatchedQueries|=g.matchedQueryIds,g.element&&g.element.template&&(c.childMatchedQueries|=g.element.template.nodeMatchedQueries)):o|=g.flags,g.childCount>0)c=g,xm(g)||(l=g);else for(;c&&h===c.nodeIndex+c.childCount;){var y=c.parent;y&&(y.childFlags|=c.childFlags,y.childMatchedQueries|=c.childMatchedQueries),l=(c=y)&&xm(c)?c.renderParent:c}}return{factory:null,nodeFlags:s,rootNodeFlags:o,nodeMatchedQueries:u,flags:t,nodes:e,updateDirectives:n||pg,updateRenderer:a||pg,handleEvent:function(t,n,a,r){return e[n].element.handleEvent(t,a,r)},bindingCount:r,outputCount:i,lastRenderRootNode:p}}function xm(t){return 0!=(1&t.flags)&&null===t.element.name}function Tm(t,e,n){var a=e.element&&e.element.template;if(a){if(!a.lastRenderRootNode)throw new Error("Illegal State: Embedded templates without nodes are not allowed!");if(a.lastRenderRootNode&&16777216&a.lastRenderRootNode.flags)throw new Error("Illegal State: Last root node of a template can't have embedded views, at index "+e.nodeIndex+"!")}if(20224&e.flags&&0==(1&(t?t.flags:0)))throw new Error("Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index "+e.nodeIndex+"!");if(e.query){if(67108864&e.flags&&(!t||0==(16384&t.flags)))throw new Error("Illegal State: Content Query nodes need to be children of directives, at index "+e.nodeIndex+"!");if(134217728&e.flags&&t)throw new Error("Illegal State: View Query nodes have to be top level nodes, at index "+e.nodeIndex+"!")}if(e.childCount){var r=t?t.nodeIndex+t.childCount:n-1;if(e.nodeIndex<=r&&e.nodeIndex+e.childCount>r)throw new Error("Illegal State: childCount of node leads outside of parent, at index "+e.nodeIndex+"!")}}function wm(t,e,n,a){var r=Im(t.root,t.renderer,t,e,n);return Cm(r,t.component,a),km(r),r}function Sm(t,e,n){var a=Im(t,t.renderer,null,null,e);return Cm(a,n,n),km(a),a}function Om(t,e,n,a){var r,i=e.element.componentRendererType;return r=i?t.root.rendererFactory.createRenderer(a,i):t.root.renderer,Im(t.root,r,t,e.element.componentProvider,n)}function Im(t,e,n,a,r){var i=new Array(r.nodes.length),s=r.outputCount?new Array(r.outputCount):null;return{def:r,parent:n,viewContainerParent:null,parentNodeDef:a,context:null,component:null,nodes:i,state:13,root:t,renderer:e,oldValues:new Array(r.bindingCount),disposables:s,initIndex:-1}}function Cm(t,e,n){t.component=e,t.context=n}function km(t){var e;Ag(t)&&(e=rg(t.parent,t.parentNodeDef.parent.nodeIndex).renderElement);for(var n=t.def,a=t.nodes,r=0;r<n.nodes.length;r++){var i=n.nodes[r];cg.setCurrentNode(t,r);var s=void 0;switch(201347067&i.flags){case 1:var o=tb(t,e,i),u=void 0;if(33554432&i.flags){var c=jg(i.element.componentView);u=cg.createComponentView(t,i,c,o)}eb(t,u,i,o),s={renderElement:o,componentView:u,viewContainer:null,template:i.element.template?Ib(t,i):void 0},16777216&i.flags&&(s.viewContainer=Tb(t,i,s));break;case 2:s=ym(t,e,i);break;case 512:case 1024:case 2048:case 256:(s=a[r])||4096&i.flags||(s={instance:Wb(t,i)});break;case 16:s={instance:Kb(t,i)};break;case 16384:(s=a[r])||(s={instance:$b(t,i)}),32768&i.flags&&Cm(rg(t,i.parent.nodeIndex).componentView,s.instance,s.instance);break;case 32:case 64:case 128:s={value:void 0};break;case 67108864:case 134217728:s=new th;break;case 8:fm(t,e,i),s=void 0}a[r]=s}qm(t,Mm.CreateViewNodes),Gm(t,201326592,268435456,0)}function Nm(t){Dm(t),cg.updateDirectives(t,1),jm(t,Mm.CheckNoChanges),cg.updateRenderer(t,1),qm(t,Mm.CheckNoChanges),t.state&=-97}function Rm(t){1&t.state?(t.state&=-2,t.state|=2):t.state&=-3,eg(t,0,256),Dm(t),cg.updateDirectives(t,0),jm(t,Mm.CheckAndUpdate),Gm(t,67108864,536870912,0);var e=eg(t,256,512);am(t,2097152|(e?1048576:0)),cg.updateRenderer(t,0),qm(t,Mm.CheckAndUpdate),Gm(t,134217728,536870912,0),am(t,8388608|((e=eg(t,512,768))?4194304:0)),2&t.def.flags&&(t.state&=-9),t.state&=-97,eg(t,768,1024)}function Am(t,e,n,r,i,s,o,u,c,l,d,f,p){return 0===n?function(t,e,n,a,r,i,s,o,u,c,l,d){switch(201347067&e.flags){case 1:return function(t,e,n,a,r,i,s,o,u,c,l,d){var f=e.bindings.length,p=!1;return f>0&&ab(t,e,0,n)&&(p=!0),f>1&&ab(t,e,1,a)&&(p=!0),f>2&&ab(t,e,2,r)&&(p=!0),f>3&&ab(t,e,3,i)&&(p=!0),f>4&&ab(t,e,4,s)&&(p=!0),f>5&&ab(t,e,5,o)&&(p=!0),f>6&&ab(t,e,6,u)&&(p=!0),f>7&&ab(t,e,7,c)&&(p=!0),f>8&&ab(t,e,8,l)&&(p=!0),f>9&&ab(t,e,9,d)&&(p=!0),p}(t,e,n,a,r,i,s,o,u,c,l,d);case 2:return function(t,e,n,a,r,i,s,o,u,c,l,d){var f=!1,p=e.bindings,h=p.length;if(h>0&&Tg(t,e,0,n)&&(f=!0),h>1&&Tg(t,e,1,a)&&(f=!0),h>2&&Tg(t,e,2,r)&&(f=!0),h>3&&Tg(t,e,3,i)&&(f=!0),h>4&&Tg(t,e,4,s)&&(f=!0),h>5&&Tg(t,e,5,o)&&(f=!0),h>6&&Tg(t,e,6,u)&&(f=!0),h>7&&Tg(t,e,7,c)&&(f=!0),h>8&&Tg(t,e,8,l)&&(f=!0),h>9&&Tg(t,e,9,d)&&(f=!0),f){var g=e.text.prefix;h>0&&(g+=vm(n,p[0])),h>1&&(g+=vm(a,p[1])),h>2&&(g+=vm(r,p[2])),h>3&&(g+=vm(i,p[3])),h>4&&(g+=vm(s,p[4])),h>5&&(g+=vm(o,p[5])),h>6&&(g+=vm(u,p[6])),h>7&&(g+=vm(c,p[7])),h>8&&(g+=vm(l,p[8])),h>9&&(g+=vm(d,p[9]));var b=ag(t,e.nodeIndex).renderText;t.renderer.setValue(b,g)}return f}(t,e,n,a,r,i,s,o,u,c,l,d);case 16384:return function(t,e,n,a,r,i,s,o,u,c,l,d){var f=ig(t,e.nodeIndex),p=f.instance,h=!1,g=void 0,b=e.bindings.length;return b>0&&xg(t,e,0,n)&&(h=!0,g=nm(t,f,e,0,n,g)),b>1&&xg(t,e,1,a)&&(h=!0,g=nm(t,f,e,1,a,g)),b>2&&xg(t,e,2,r)&&(h=!0,g=nm(t,f,e,2,r,g)),b>3&&xg(t,e,3,i)&&(h=!0,g=nm(t,f,e,3,i,g)),b>4&&xg(t,e,4,s)&&(h=!0,g=nm(t,f,e,4,s,g)),b>5&&xg(t,e,5,o)&&(h=!0,g=nm(t,f,e,5,o,g)),b>6&&xg(t,e,6,u)&&(h=!0,g=nm(t,f,e,6,u,g)),b>7&&xg(t,e,7,c)&&(h=!0,g=nm(t,f,e,7,c,g)),b>8&&xg(t,e,8,l)&&(h=!0,g=nm(t,f,e,8,l,g)),b>9&&xg(t,e,9,d)&&(h=!0,g=nm(t,f,e,9,d,g)),g&&p.ngOnChanges(g),65536&e.flags&&ng(t,256,e.nodeIndex)&&p.ngOnInit(),262144&e.flags&&p.ngDoCheck(),h}(t,e,n,a,r,i,s,o,u,c,l,d);case 32:case 64:case 128:return function(t,e,n,a,r,i,s,o,u,c,l,d){var f=e.bindings,p=!1,h=f.length;if(h>0&&Tg(t,e,0,n)&&(p=!0),h>1&&Tg(t,e,1,a)&&(p=!0),h>2&&Tg(t,e,2,r)&&(p=!0),h>3&&Tg(t,e,3,i)&&(p=!0),h>4&&Tg(t,e,4,s)&&(p=!0),h>5&&Tg(t,e,5,o)&&(p=!0),h>6&&Tg(t,e,6,u)&&(p=!0),h>7&&Tg(t,e,7,c)&&(p=!0),h>8&&Tg(t,e,8,l)&&(p=!0),h>9&&Tg(t,e,9,d)&&(p=!0),p){var g=sg(t,e.nodeIndex),b=void 0;switch(201347067&e.flags){case 32:b=new Array(f.length),h>0&&(b[0]=n),h>1&&(b[1]=a),h>2&&(b[2]=r),h>3&&(b[3]=i),h>4&&(b[4]=s),h>5&&(b[5]=o),h>6&&(b[6]=u),h>7&&(b[7]=c),h>8&&(b[8]=l),h>9&&(b[9]=d);break;case 64:b={},h>0&&(b[f[0].name]=n),h>1&&(b[f[1].name]=a),h>2&&(b[f[2].name]=r),h>3&&(b[f[3].name]=i),h>4&&(b[f[4].name]=s),h>5&&(b[f[5].name]=o),h>6&&(b[f[6].name]=u),h>7&&(b[f[7].name]=c),h>8&&(b[f[8].name]=l),h>9&&(b[f[9].name]=d);break;case 128:var m=n;switch(h){case 1:b=m.transform(n);break;case 2:b=m.transform(a);break;case 3:b=m.transform(a,r);break;case 4:b=m.transform(a,r,i);break;case 5:b=m.transform(a,r,i,s);break;case 6:b=m.transform(a,r,i,s,o);break;case 7:b=m.transform(a,r,i,s,o,u);break;case 8:b=m.transform(a,r,i,s,o,u,c);break;case 9:b=m.transform(a,r,i,s,o,u,c,l);break;case 10:b=m.transform(a,r,i,s,o,u,c,l,d)}}g.value=b}return p}(t,e,n,a,r,i,s,o,u,c,l,d);default:throw"unreachable"}}(t,e,r,i,s,o,u,c,l,d,f,p):function(t,e,n){switch(201347067&e.flags){case 1:return function(t,e,n){for(var a=!1,r=0;r<n.length;r++)ab(t,e,r,n[r])&&(a=!0);return a}(t,e,n);case 2:return function(t,e,n){for(var a=e.bindings,r=!1,i=0;i<n.length;i++)Tg(t,e,i,n[i])&&(r=!0);if(r){var s="";for(i=0;i<n.length;i++)s+=vm(n[i],a[i]);s=e.text.prefix+s;var o=ag(t,e.nodeIndex).renderText;t.renderer.setValue(o,s)}return r}(t,e,n);case 16384:return function(t,e,n){for(var a=ig(t,e.nodeIndex),r=a.instance,i=!1,s=void 0,o=0;o<n.length;o++)xg(t,e,o,n[o])&&(i=!0,s=nm(t,a,e,o,n[o],s));return s&&r.ngOnChanges(s),65536&e.flags&&ng(t,256,e.nodeIndex)&&r.ngOnInit(),262144&e.flags&&r.ngDoCheck(),i}(t,e,n);case 32:case 64:case 128:return function(t,e,n){for(var r=e.bindings,i=!1,s=0;s<n.length;s++)Tg(t,e,s,n[s])&&(i=!0);if(i){var o=sg(t,e.nodeIndex),u=void 0;switch(201347067&e.flags){case 32:u=n;break;case 64:for(u={},s=0;s<n.length;s++)u[r[s].name]=n[s];break;case 128:var c=n[0],l=n.slice(1);u=c.transform.apply(c,Object(a.__spread)(l))}o.value=u}return i}(t,e,n);default:throw"unreachable"}}(t,e,r)}function Dm(t){var e=t.def;if(4&e.nodeFlags)for(var n=0;n<e.nodes.length;n++){var a=e.nodes[n];if(4&a.flags){var r=rg(t,n).template._projectedViews;if(r)for(var i=0;i<r.length;i++){var s=r[i];s.state|=32,Og(s,t)}}else 0==(4&a.childFlags)&&(n+=a.childCount)}}function Em(t,e,n,a,r,i,s,o,u,c,l,d,f){return 0===n?function(t,e,n,a,r,i,s,o,u,c,l,d){var f=e.bindings.length;f>0&&wg(t,e,0,n),f>1&&wg(t,e,1,a),f>2&&wg(t,e,2,r),f>3&&wg(t,e,3,i),f>4&&wg(t,e,4,s),f>5&&wg(t,e,5,o),f>6&&wg(t,e,6,u),f>7&&wg(t,e,7,c),f>8&&wg(t,e,8,l),f>9&&wg(t,e,9,d)}(t,e,a,r,i,s,o,u,c,l,d,f):function(t,e,n){for(var a=0;a<n.length;a++)wg(t,e,a,n[a])}(t,e,a),!1}function Lm(t,e){if(og(t,e.nodeIndex).dirty)throw lg(cg.createDebugContext(t,e.nodeIndex),"Query "+e.query.id+" not dirty","Query "+e.query.id+" dirty",0!=(1&t.state))}function Pm(t){if(!(128&t.state)){if(jm(t,Mm.Destroy),qm(t,Mm.Destroy),am(t,131072),t.disposables)for(var e=0;e<t.disposables.length;e++)t.disposables[e]();!function(t){if(16&t.state){var e=Cg(t);if(e){var n=e.template._projectedViews;n&&(bb(n,n.indexOf(t)),cg.dirtyParentQueries(t))}}}(t),t.renderer.destroyNode&&function(t){for(var e=t.def.nodes.length,n=0;n<e;n++){var a=t.def.nodes[n];1&a.flags?t.renderer.destroyNode(rg(t,n).renderElement):2&a.flags?t.renderer.destroyNode(ag(t,n).renderText):(67108864&a.flags||134217728&a.flags)&&og(t,n).destroy()}}(t),Ag(t)&&t.renderer.destroy(),t.state|=128}}var Mm=function(t){return t[t.CreateViewNodes=0]="CreateViewNodes",t[t.CheckNoChanges=1]="CheckNoChanges",t[t.CheckNoChangesProjectedViews=2]="CheckNoChangesProjectedViews",t[t.CheckAndUpdate=3]="CheckAndUpdate",t[t.CheckAndUpdateProjectedViews=4]="CheckAndUpdateProjectedViews",t[t.Destroy=5]="Destroy",t}({});function qm(t,e){var n=t.def;if(33554432&n.nodeFlags)for(var a=0;a<n.nodes.length;a++){var r=n.nodes[a];33554432&r.flags?Fm(rg(t,a).componentView,e):0==(33554432&r.childFlags)&&(a+=r.childCount)}}function jm(t,e){var n=t.def;if(16777216&n.nodeFlags)for(var a=0;a<n.nodes.length;a++){var r=n.nodes[a];if(16777216&r.flags)for(var i=rg(t,a).viewContainer._embeddedViews,s=0;s<i.length;s++)Fm(i[s],e);else 0==(16777216&r.childFlags)&&(a+=r.childCount)}}function Fm(t,e){var n=t.state;switch(e){case Mm.CheckNoChanges:0==(128&n)&&(12==(12&n)?Nm(t):64&n&&zm(t,Mm.CheckNoChangesProjectedViews));break;case Mm.CheckNoChangesProjectedViews:0==(128&n)&&(32&n?Nm(t):64&n&&zm(t,e));break;case Mm.CheckAndUpdate:0==(128&n)&&(12==(12&n)?Rm(t):64&n&&zm(t,Mm.CheckAndUpdateProjectedViews));break;case Mm.CheckAndUpdateProjectedViews:0==(128&n)&&(32&n?Rm(t):64&n&&zm(t,e));break;case Mm.Destroy:Pm(t);break;case Mm.CreateViewNodes:km(t)}}function zm(t,e){jm(t,e),qm(t,e)}function Gm(t,e,n,a){if(t.def.nodeFlags&e&&t.def.nodeFlags&n)for(var r=t.def.nodes.length,i=0;i<r;i++){var s=t.def.nodes[i];if(s.flags&e&&s.flags&n)switch(cg.setCurrentNode(t,s.nodeIndex),a){case 0:um(t,s);break;case 1:Lm(t,s)}s.childFlags&e&&s.childFlags&n||(i+=s.childCount)}}var Ym=!1;function Vm(){if(!Ym){Ym=!0;var t=Fu()?{setCurrentNode:fy,createRootView:Bm,createEmbeddedView:Wm,createComponentView:Km,createNgModuleRef:$m,overrideProvider:Qm,overrideComponentView:ty,clearOverrides:ey,checkAndUpdateView:iy,checkNoChangesView:sy,destroyView:oy,createDebugContext:function(t,e){return new _y(t,e)},handleEvent:py,updateDirectives:hy,updateRenderer:gy}:{setCurrentNode:function(){},createRootView:Hm,createEmbeddedView:wm,createComponentView:Om,createNgModuleRef:Eb,overrideProvider:pg,overrideComponentView:pg,clearOverrides:pg,checkAndUpdateView:Rm,checkNoChangesView:Nm,destroyView:Pm,createDebugContext:function(t,e){return new _y(t,e)},handleEvent:function(t,e,n,a){return t.def.handleEvent(t,e,n,a)},updateDirectives:function(t,e){return t.def.updateDirectives(0===e?ay:ry,t)},updateRenderer:function(t,e){return t.def.updateRenderer(0===e?ay:ry,t)}};cg.setCurrentNode=t.setCurrentNode,cg.createRootView=t.createRootView,cg.createEmbeddedView=t.createEmbeddedView,cg.createComponentView=t.createComponentView,cg.createNgModuleRef=t.createNgModuleRef,cg.overrideProvider=t.overrideProvider,cg.overrideComponentView=t.overrideComponentView,cg.clearOverrides=t.clearOverrides,cg.checkAndUpdateView=t.checkAndUpdateView,cg.checkNoChangesView=t.checkNoChangesView,cg.destroyView=t.destroyView,cg.resolveDep=tm,cg.createDebugContext=t.createDebugContext,cg.handleEvent=t.handleEvent,cg.updateDirectives=t.updateDirectives,cg.updateRenderer=t.updateRenderer,cg.dirtyParentQueries=om}}function Hm(t,e,n,a,r,i){var s=r.injector.get(xu);return Sm(Um(t,r,s,e,n),a,i)}function Bm(t,e,n,a,r,i){var s=r.injector.get(xu),o=Um(t,r,new Sy(s),e,n),u=ny(a);return Ty(dy.create,Sm,null,[o,u,i])}function Um(t,e,n,a,r){var i=e.injector.get(Cu),s=e.injector.get(Sf),o=n.createRenderer(null,null);return{ngModule:e,injector:t,projectableNodes:a,selectorOrNode:r,sanitizer:i,rendererFactory:n,renderer:o,errorHandler:s}}function Wm(t,e,n,a){var r=ny(n);return Ty(dy.create,wm,null,[t,e,r,a])}function Km(t,e,n,a){return n=Jm.get(e.element.componentProvider.provider.token)||ny(n),Ty(dy.create,Om,null,[t,e,n,a])}function $m(t,e,n,a){return Eb(t,e,n,function(t){var e=function(t){var e=!1,n=!1;return 0===Zm.size?{hasOverrides:e,hasDeprecatedOverrides:n}:(t.providers.forEach(function(t){var a=Zm.get(t.token);3840&t.flags&&a&&(e=!0,n=n||a.deprecatedBehavior)}),t.modules.forEach(function(t){Xm.forEach(function(a,r){x(r).providedIn===t&&(e=!0,n=n||a.deprecatedBehavior)})}),{hasOverrides:e,hasDeprecatedOverrides:n})}(t),n=e.hasDeprecatedOverrides;return e.hasOverrides?(function(t){for(var e=0;e<t.providers.length;e++){var a=t.providers[e];n&&(a.flags|=4096);var r=Zm.get(a.token);r&&(a.flags=-3841&a.flags|r.flags,a.deps=Pg(r.deps),a.value=r.value)}if(Xm.size>0){var i=new Set(t.modules);Xm.forEach(function(e,a){if(i.has(x(a).providedIn)){var r={token:a,flags:e.flags|(n?4096:0),deps:Pg(e.deps),value:e.value,index:t.providers.length};t.providers.push(r),t.providersByKey[gg(a)]=r}})}}(t=t.factory(function(){return pg})),t):t}(a))}var Zm=new Map,Xm=new Map,Jm=new Map;function Qm(t){var e;Zm.set(t.token,t),"function"==typeof t.token&&(e=x(t.token))&&"function"==typeof e.providedIn&&Xm.set(t.token,t)}function ty(t,e){var n=jg(vb(e)),a=jg(n.nodes[0].element.componentView);Jm.set(t,a)}function ey(){Zm.clear(),Xm.clear(),Jm.clear()}function ny(t){if(0===Zm.size)return t;var e=function(t){for(var e=[],n=null,a=0;a<t.nodes.length;a++){var r=t.nodes[a];1&r.flags&&(n=r),n&&3840&r.flags&&Zm.has(r.provider.token)&&(e.push(n.nodeIndex),n=null)}return e}(t);if(0===e.length)return t;t=t.factory(function(){return pg});for(var n=0;n<e.length;n++)a(t,e[n]);return t;function a(t,e){for(var n=e+1;n<t.nodes.length;n++){var a=t.nodes[n];if(1&a.flags)return;if(3840&a.flags){var r=a.provider,i=Zm.get(r.token);i&&(a.flags=-3841&a.flags|i.flags,r.deps=Pg(i.deps),r.value=i.value)}}}}function ay(t,e,n,a,r,i,s,o,u,c,l,d,f){var p=t.def.nodes[e];return Am(t,p,n,a,r,i,s,o,u,c,l,d,f),224&p.flags?sg(t,e).value:void 0}function ry(t,e,n,a,r,i,s,o,u,c,l,d,f){var p=t.def.nodes[e];return Em(t,p,n,a,r,i,s,o,u,c,l,d,f),224&p.flags?sg(t,e).value:void 0}function iy(t){return Ty(dy.detectChanges,Rm,null,[t])}function sy(t){return Ty(dy.checkNoChanges,Nm,null,[t])}function oy(t){return Ty(dy.destroy,Pm,null,[t])}var uy,cy,ly,dy=function(t){return t[t.create=0]="create",t[t.detectChanges=1]="detectChanges",t[t.checkNoChanges=2]="checkNoChanges",t[t.destroy=3]="destroy",t[t.handleEvent=4]="handleEvent",t}({});function fy(t,e){cy=t,ly=e}function py(t,e,n,a){return fy(t,e),Ty(dy.handleEvent,t.def.handleEvent,null,[t,e,n,a])}function hy(t,e){if(128&t.state)throw fg(dy[uy]);return fy(t,yy(t,0)),t.def.updateDirectives(function(t,n,a){for(var r=[],i=3;i<arguments.length;i++)r[i-3]=arguments[i];var s=t.def.nodes[n];return 0===e?by(t,s,a,r):my(t,s,a,r),16384&s.flags&&fy(t,yy(t,n)),224&s.flags?sg(t,s.nodeIndex).value:void 0},t)}function gy(t,e){if(128&t.state)throw fg(dy[uy]);return fy(t,vy(t,0)),t.def.updateRenderer(function(t,n,a){for(var r=[],i=3;i<arguments.length;i++)r[i-3]=arguments[i];var s=t.def.nodes[n];return 0===e?by(t,s,a,r):my(t,s,a,r),3&s.flags&&fy(t,vy(t,n)),224&s.flags?sg(t,s.nodeIndex).value:void 0},t)}function by(t,e,n,r){if(Am.apply(void 0,Object(a.__spread)([t,e,n],r))){var i=1===n?r[0]:r;if(16384&e.flags){for(var s={},o=0;o<e.bindings.length;o++){var u=e.bindings[o],c=i[o];8&u.flags&&(s[(p=u.nonMinifiedName,"ng-reflect-"+p.replace(/[$@]/g,"_").replace(sa,function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return"-"+t[1].toLowerCase()}))]=oa(c))}var l=e.parent,d=rg(t,l.nodeIndex).renderElement;if(l.element.name)for(var f in s)null!=(c=s[f])?t.renderer.setAttribute(d,f,c):t.renderer.removeAttribute(d,f);else t.renderer.setValue(d,"bindings="+JSON.stringify(s,null,2))}}var p}function my(t,e,n,r){Em.apply(void 0,Object(a.__spread)([t,e,n],r))}function yy(t,e){for(var n=e;n<t.def.nodes.length;n++){var a=t.def.nodes[n];if(16384&a.flags&&a.bindings&&a.bindings.length)return n}return null}function vy(t,e){for(var n=e;n<t.def.nodes.length;n++){var a=t.def.nodes[n];if(3&a.flags&&a.bindings&&a.bindings.length)return n}return null}var _y=function(){function t(t,e){this.view=t,this.nodeIndex=e,null==e&&(this.nodeIndex=e=0),this.nodeDef=t.def.nodes[e];for(var n=this.nodeDef,a=t;n&&0==(1&n.flags);)n=n.parent;if(!n)for(;!n&&a;)n=kg(a),a=a.parent;this.elDef=n,this.elView=a}return Object.defineProperty(t.prototype,"elOrCompView",{get:function(){return rg(this.elView,this.elDef.nodeIndex).componentView||this.view},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"injector",{get:function(){return kb(this.elView,this.elDef)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"component",{get:function(){return this.elOrCompView.component},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this.elOrCompView.context},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"providerTokens",{get:function(){var t=[];if(this.elDef)for(var e=this.elDef.nodeIndex+1;e<=this.elDef.nodeIndex+this.elDef.childCount;e++){var n=this.elView.def.nodes[e];20224&n.flags&&t.push(n.provider.token),e+=n.childCount}return t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"references",{get:function(){var t={};if(this.elDef){xy(this.elView,this.elDef,t);for(var e=this.elDef.nodeIndex+1;e<=this.elDef.nodeIndex+this.elDef.childCount;e++){var n=this.elView.def.nodes[e];20224&n.flags&&xy(this.elView,n,t),e+=n.childCount}}return t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"componentRenderElement",{get:function(){var t=function(t){for(;t&&!Ag(t);)t=t.parent;return t.parent?rg(t.parent,kg(t).nodeIndex):null}(this.elOrCompView);return t?t.renderElement:void 0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"renderNode",{get:function(){return 2&this.nodeDef.flags?Ng(this.view,this.nodeDef):Ng(this.elView,this.elDef)},enumerable:!0,configurable:!0}),t.prototype.logError=function(t){for(var e,n,r=[],i=1;i<arguments.length;i++)r[i-1]=arguments[i];2&this.nodeDef.flags?(e=this.view.def,n=this.nodeDef.nodeIndex):(e=this.elView.def,n=this.elDef.nodeIndex);var s=function(t,e){for(var n=-1,a=0;a<=e;a++)3&t.nodes[a].flags&&n++;return n}(e,n),o=-1;e.factory(function(){var e;return++o===s?(e=t.error).bind.apply(e,Object(a.__spread)([t],r)):pg}),o<s&&(t.error("Illegal state: the ViewDefinitionFactory did not call the logger!"),t.error.apply(t,Object(a.__spread)(r)))},t}();function xy(t,e,n){for(var a in e.references)n[a]=lm(t,e,e.references[a])}function Ty(t,e,n,a){var r=uy,i=cy,s=ly;try{uy=t;var o=e.apply(n,a);return cy=i,ly=s,uy=r,o}catch(u){if(xf(u)||!cy)throw u;throw function(t,e){return t instanceof Error||(t=new Error(t.toString())),dg(t,e),t}(u,wy())}}function wy(){return cy?new _y(cy,ly):null}var Sy=function(){function t(t){this.delegate=t}return t.prototype.createRenderer=function(t,e){return new Oy(this.delegate.createRenderer(t,e))},t.prototype.begin=function(){this.delegate.begin&&this.delegate.begin()},t.prototype.end=function(){this.delegate.end&&this.delegate.end()},t.prototype.whenRenderingDone=function(){return this.delegate.whenRenderingDone?this.delegate.whenRenderingDone():Promise.resolve(null)},t}(),Oy=function(){function t(t){this.delegate=t,this.debugContextFactory=wy,this.data=this.delegate.data}return t.prototype.createDebugContext=function(t){return this.debugContextFactory(t)},t.prototype.destroyNode=function(t){!function(t){Th.delete(t.nativeNode)}(Sh(t)),this.delegate.destroyNode&&this.delegate.destroyNode(t)},t.prototype.destroy=function(){this.delegate.destroy()},t.prototype.createElement=function(t,e){var n=this.delegate.createElement(t,e),a=this.createDebugContext(n);if(a){var r=new gh(n,null,a);r.name=t,Oh(r)}return n},t.prototype.createComment=function(t){var e=this.delegate.createComment(t),n=this.createDebugContext(e);return n&&Oh(new hh(e,null,n)),e},t.prototype.createText=function(t){var e=this.delegate.createText(t),n=this.createDebugContext(e);return n&&Oh(new hh(e,null,n)),e},t.prototype.appendChild=function(t,e){var n=Sh(t),a=Sh(e);n&&a&&n instanceof gh&&n.addChild(a),this.delegate.appendChild(t,e)},t.prototype.insertBefore=function(t,e,n){var a=Sh(t),r=Sh(e),i=Sh(n);a&&r&&a instanceof gh&&a.insertBefore(i,r),this.delegate.insertBefore(t,e,n)},t.prototype.removeChild=function(t,e){var n=Sh(t),a=Sh(e);n&&a&&n instanceof gh&&n.removeChild(a),this.delegate.removeChild(t,e)},t.prototype.selectRootElement=function(t,e){var n=this.delegate.selectRootElement(t,e),a=wy();return a&&Oh(new gh(n,null,a)),n},t.prototype.setAttribute=function(t,e,n,a){var r=Sh(t);r&&r instanceof gh&&(r.attributes[a?a+":"+e:e]=n),this.delegate.setAttribute(t,e,n,a)},t.prototype.removeAttribute=function(t,e,n){var a=Sh(t);a&&a instanceof gh&&(a.attributes[n?n+":"+e:e]=null),this.delegate.removeAttribute(t,e,n)},t.prototype.addClass=function(t,e){var n=Sh(t);n&&n instanceof gh&&(n.classes[e]=!0),this.delegate.addClass(t,e)},t.prototype.removeClass=function(t,e){var n=Sh(t);n&&n instanceof gh&&(n.classes[e]=!1),this.delegate.removeClass(t,e)},t.prototype.setStyle=function(t,e,n,a){var r=Sh(t);r&&r instanceof gh&&(r.styles[e]=n),this.delegate.setStyle(t,e,n,a)},t.prototype.removeStyle=function(t,e,n){var a=Sh(t);a&&a instanceof gh&&(a.styles[e]=null),this.delegate.removeStyle(t,e,n)},t.prototype.setProperty=function(t,e,n){var a=Sh(t);a&&a instanceof gh&&(a.properties[e]=n),this.delegate.setProperty(t,e,n)},t.prototype.listen=function(t,e,n){if("string"!=typeof t){var a=Sh(t);a&&a.listeners.push(new ph(e,n))}return this.delegate.listen(t,e,n)},t.prototype.parentNode=function(t){return this.delegate.parentNode(t)},t.prototype.nextSibling=function(t){return this.delegate.nextSibling(t)},t.prototype.setValue=function(t,e){return this.delegate.setValue(t,e)},t}();function Iy(t){return Vm(),cg.overrideProvider(t)}function Cy(t,e){return Vm(),cg.overrideComponentView(t,e)}function ky(){return Vm(),cg.clearOverrides()}function Ny(t,e,n){return new Ry(t,e,n)}var Ry=function(t){function e(e,n,a){var r=t.call(this)||this;return r.moduleType=e,r._bootstrapComponents=n,r._ngModuleDefFactory=a,r}return Object(a.__extends)(e,t),e.prototype.create=function(t){Vm();var e=function(t){var e=Array.from(t.providers),n=Array.from(t.modules),a={};for(var r in t.providersByKey)a[r]=t.providersByKey[r];return{factory:t.factory,isRoot:t.isRoot,providers:e,modules:n,providersByKey:a}}(jg(this._ngModuleDefFactory));return cg.createNgModuleRef(this.moduleType,t||ho.NULL,this._bootstrapComponents,e)},e}(uu)},ChqD:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},CjzT:function(t,e,n){!function(t){"use strict";var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),a=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;t.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_s\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[ma\xf1ana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}(n("wd/R"))},CoRJ:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ar-ma",{months:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062a\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u062d\u062f_\u0627\u062a\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",ss:"%d \u062b\u0627\u0646\u064a\u0629",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:6,doy:12}})}()},"D/JM":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",ss:"%d segundo",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}()},D4zM:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(t,e){this.elementRef=t,this.renderer=e}return t.prototype.ngOnInit=function(){this.renderer.setAttribute(this.elementRef.nativeElement,"tabindex","-1"),this.iElement=this.renderer.createElement("i"),this.renderer.addClass(this.iElement,"icon-prepend"),this.renderer.addClass(this.iElement,"fa"),this.renderer.appendChild(this.elementRef.nativeElement,this.iElement),this.update()},t.prototype.getInputElement=function(){return document.getElementById(this.cdPasswordButton)},t.prototype.update=function(){var t=this.getInputElement();t&&"text"===t.type?(this.renderer.removeClass(this.iElement,"fa-eye"),this.renderer.addClass(this.iElement,"fa-eye-slash")):(this.renderer.removeClass(this.iElement,"fa-eye-slash"),this.renderer.addClass(this.iElement,"fa-eye"))},t.prototype.onClick=function(){var t=this.getInputElement();t.type="password"===t.type?"text":"password",this.update()},t}()},DKTb:function(t,e,n){"use strict";function a(t){setTimeout(function(){throw t},0)}n.d(e,"a",function(){return a})},"DKr+":function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={s:["thodde secondanim","thodde second"],ss:[t+" secondanim",t+" second"],m:["eka mintan","ek minute"],mm:[t+" mintanim",t+" mintam"],h:["eka voran","ek vor"],hh:[t+" voranim",t+" voram"],d:["eka disan","ek dis"],dd:[t+" disanim",t+" dis"],M:["eka mhoinean","ek mhoino"],MM:[t+" mhoineanim",t+" mhoine"],y:["eka vorsan","ek voros"],yy:[t+" vorsanim",t+" vorsam"]};return e?r[n][0]:r[n][1]}n("wd/R").defineLocale("gom-latn",{months:"Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr".split("_"),monthsShort:"Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Aitar_Somar_Mongllar_Budvar_Brestar_Sukrar_Son'var".split("_"),weekdaysShort:"Ait._Som._Mon._Bud._Bre._Suk._Son.".split("_"),weekdaysMin:"Ai_Sm_Mo_Bu_Br_Su_Sn".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [vazta]",LTS:"A h:mm:ss [vazta]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [vazta]",LLLL:"dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]",llll:"ddd, D MMM YYYY, A h:mm [vazta]"},calendar:{sameDay:"[Aiz] LT",nextDay:"[Faleam] LT",nextWeek:"[Ieta to] dddd[,] LT",lastDay:"[Kal] LT",lastWeek:"[Fatlo] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s adim",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}(er)/,ordinal:function(t,e){switch(e){case"D":return t+"er";default:case"M":case"Q":case"DDD":case"d":case"w":case"W":return t}},week:{dow:1,doy:4},meridiemParse:/rati|sokalli|donparam|sanje/,meridiemHour:function(t,e){return 12===t&&(t=0),"rati"===e?t<4?t:t+12:"sokalli"===e?t:"donparam"===e?t>12?t:t+12:"sanje"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"rati":t<12?"sokalli":t<16?"donparam":t<20?"sanje":"rati"}})}()},DNAf:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=function(){return function(t,e){this.customValidations={},this.i18n=e,this.empty=this.i18n("No items selected."),this.selectionLimit={tooltip:this.i18n("Deselect item to select again"),text:this.i18n("Selection limit reached")},this.filter=this.i18n("Filter tags"),this.add=this.i18n("Add badge"),this.noOptions=this.i18n("There are no items available."),a.merge(this,t)}}()},DQlY:function(t,e,n){"use strict";n.d(e,"a",function(){return o}),n.d(e,"b",function(){return f}),n.d(e,"c",function(){return d}),n.d(e,"d",function(){return l}),n.d(e,"e",function(){return p}),n.d(e,"f",function(){return u});var a=n("CcnG"),r=n("rpEJ"),i=n("lqqz"),s=n("NJnL"),o=function(){return function(){this.hide=Function,this.setClass=Function}}(),u=function(){return function(){}}(),c={backdrop:!0,keyboard:!0,focus:!0,show:!1,ignoreBackdropClick:!1,class:"",animated:!0,initialState:{}},l=function(){function t(t,e,n){this._element=e,this._renderer=n,this.isShown=!1,this.isModalHiding=!1,this.config=Object.assign({},t)}return t.prototype.ngOnInit=function(){var t=this;this.isAnimated&&this._renderer.addClass(this._element.nativeElement,"fade"),this._renderer.setStyle(this._element.nativeElement,"display","block"),setTimeout(function(){t.isShown=!0,t._renderer.addClass(t._element.nativeElement,Object(r.d)()?"in":"show")},this.isAnimated?150:0),document&&document.body&&(1===this.bsModalService.getModalsCount()&&(this.bsModalService.checkScrollbar(),this.bsModalService.setScrollbar()),this._renderer.addClass(document.body,"modal-open")),this._element.nativeElement&&this._element.nativeElement.focus()},t.prototype.onClick=function(t){this.config.ignoreBackdropClick||"static"===this.config.backdrop||t.target!==this._element.nativeElement||(this.bsModalService.setDismissReason("backdrop-click"),this.hide())},t.prototype.onEsc=function(t){this.isShown&&(27!==t.keyCode&&"Escape"!==t.key||t.preventDefault(),this.config.keyboard&&this.level===this.bsModalService.getModalsCount()&&(this.bsModalService.setDismissReason("esc"),this.hide()))},t.prototype.ngOnDestroy=function(){this.isShown&&this.hide()},t.prototype.hide=function(){var t=this;!this.isModalHiding&&this.isShown&&(this.isModalHiding=!0,this._renderer.removeClass(this._element.nativeElement,Object(r.d)()?"in":"show"),setTimeout(function(){t.isShown=!1,document&&document.body&&1===t.bsModalService.getModalsCount()&&t._renderer.removeClass(document.body,"modal-open"),t.bsModalService.hide(t.level),t.isModalHiding=!1},this.isAnimated?300:0))},t}(),d=function(){function t(t,e){this._isShown=!1,this.element=t,this.renderer=e}return Object.defineProperty(t.prototype,"isAnimated",{get:function(){return this._isAnimated},set:function(t){this._isAnimated=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isShown",{get:function(){return this._isShown},set:function(t){this._isShown=t,t?this.renderer.addClass(this.element.nativeElement,"in"):this.renderer.removeClass(this.element.nativeElement,"in"),Object(r.d)()||(t?this.renderer.addClass(this.element.nativeElement,"show"):this.renderer.removeClass(this.element.nativeElement,"show"))},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.isAnimated&&(this.renderer.addClass(this.element.nativeElement,"fade"),r.b.reflow(this.element.nativeElement)),this.isShown=!0},t}(),f=function(){function t(t,e){this.clf=e,this.config=c,this.onShow=new a.EventEmitter,this.onShown=new a.EventEmitter,this.onHide=new a.EventEmitter,this.onHidden=new a.EventEmitter,this.isBodyOverflowing=!1,this.originalBodyPadding=0,this.scrollbarWidth=0,this.modalsCount=0,this.lastDismissReason="",this.loaders=[],this._backdropLoader=this.clf.createLoader(null,null,null),this._renderer=t.createRenderer(null,null)}return t.prototype.show=function(t,e){return this.modalsCount++,this._createLoaders(),this.config=Object.assign({},c,e),this._showBackdrop(),this.lastDismissReason=null,this._showModal(t)},t.prototype.hide=function(t){var e=this;1===this.modalsCount&&(this._hideBackdrop(),this.resetScrollbar()),this.modalsCount=this.modalsCount>=1?this.modalsCount-1:0,setTimeout(function(){e._hideModal(t),e.removeLoaders(t)},this.config.animated?150:0)},t.prototype._showBackdrop=function(){var t=this.config.backdrop||"static"===this.config.backdrop,e=!this.backdropRef||!this.backdropRef.instance.isShown;1===this.modalsCount&&(this.removeBackdrop(),t&&e&&(this._backdropLoader.attach(d).to("body").show({isAnimated:this.config.animated}),this.backdropRef=this._backdropLoader._componentRef))},t.prototype._hideBackdrop=function(){var t=this;this.backdropRef&&(this.backdropRef.instance.isShown=!1,setTimeout(function(){return t.removeBackdrop()},this.config.animated?150:0))},t.prototype._showModal=function(t){var e=this.loaders[this.loaders.length-1],n=new o,a=e.provide({provide:u,useValue:this.config}).provide({provide:o,useValue:n}).attach(l).to("body").show({content:t,isAnimated:this.config.animated,initialState:this.config.initialState,bsModalService:this});return a.instance.level=this.getModalsCount(),n.hide=function(){a.instance.hide()},n.content=e.getInnerComponent()||null,n.setClass=function(t){a.instance.config.class=t},n},t.prototype._hideModal=function(t){var e=this.loaders[t-1];e&&e.hide()},t.prototype.getModalsCount=function(){return this.modalsCount},t.prototype.setDismissReason=function(t){this.lastDismissReason=t},t.prototype.removeBackdrop=function(){this._backdropLoader.hide(),this.backdropRef=null},t.prototype.checkScrollbar=function(){this.isBodyOverflowing=document.body.clientWidth<window.innerWidth,this.scrollbarWidth=this.getScrollbarWidth()},t.prototype.setScrollbar=function(){document&&(this.originalBodyPadding=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")||"0",10),this.isBodyOverflowing&&(document.body.style.paddingRight=this.originalBodyPadding+this.scrollbarWidth+"px"))},t.prototype.resetScrollbar=function(){document.body.style.paddingRight=this.originalBodyPadding+"px"},t.prototype.getScrollbarWidth=function(){var t=this._renderer.createElement("div");this._renderer.addClass(t,"modal-scrollbar-measure"),this._renderer.appendChild(document.body,t);var e=t.offsetWidth-t.clientWidth;return this._renderer.removeChild(document.body,t),e},t.prototype._createLoaders=function(){var t=this.clf.createLoader(null,null,null);this.copyEvent(t.onBeforeShow,this.onShow),this.copyEvent(t.onShown,this.onShown),this.copyEvent(t.onBeforeHide,this.onHide),this.copyEvent(t.onHidden,this.onHidden),this.loaders.push(t)},t.prototype.removeLoaders=function(t){this.loaders.splice(t-1,1),this.loaders.forEach(function(t,e){t.instance.level=e+1})},t.prototype.copyEvent=function(t,e){var n=this;t.subscribe(function(){e.emit(n.lastDismissReason)})},t}(),p=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[f,i.a,s.a]}},t}()},DSvg:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("aexS"),r=n("CcnG"),i=n("t/Na"),s=n("ZYCi"),o=n("pL04"),u=function(){function t(t,e,n){this.authStorageService=t,this.http=e,this.router=n}return t.prototype.check=function(t){return this.http.post("api/auth/check",{token:t})},t.prototype.login=function(t){var e=this;return this.http.post("api/auth",t).toPromise().then(function(t){e.authStorageService.set(t.username,t.permissions)})},t.prototype.logout=function(t){var e=this;return void 0===t&&(t=null),this.http.post("api/auth/logout",null).subscribe(function(n){e.authStorageService.remove(),e.router.navigate(["/logout"],{skipLocationChange:!0}),t&&t(),window.location.replace(n.redirect_url)})},t.ngInjectableDef=r.defineInjectable({factory:function(){return new t(r.inject(a.a),r.inject(i.c),r.inject(s.l))},token:t,providedIn:o.a}),t}()},Da1D:function(t,e,n){"use strict";n.d(e,"a",function(){return s}),n.d(e,"b",function(){return i}),n.d(e,"c",function(){return r}),n.d(e,"d",function(){return o});var a=n("rpEJ"),r=function(){return function(){this.animate=!1,this.max=100}}(),i=function(){function t(t){this.isStacked=!1,this.addClass=!0,this.bars=[],this._max=100,Object.assign(this,t)}return Object.defineProperty(t.prototype,"animate",{set:function(t){this._animate=t,this.bars.forEach(function(e){e.animate=t})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"striped",{set:function(t){this._striped=t,this.bars.forEach(function(e){e.striped=t})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"value",{set:function(t){this.isStacked=Array.isArray(t),this._value=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isBs3",{get:function(){return Object(a.d)()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"max",{get:function(){return this._max},set:function(t){this._max=t,this.bars.forEach(function(t){t.recalculatePercentage()})},enumerable:!0,configurable:!0}),t.prototype.addBar=function(t){t.animate=this._animate,t.striped=this._striped,this.bars.push(t)},t.prototype.removeBar=function(t){this.bars.splice(this.bars.indexOf(t),1)},t}(),s=function(){function t(t){this.percent=0,this.progress=t}return Object.defineProperty(t.prototype,"value",{get:function(){return this._value},set:function(t){(t||0===t)&&(this._value=t,this.recalculatePercentage())},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"setBarWidth",{get:function(){return this.recalculatePercentage(),this.percent},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isBs3",{get:function(){return Object(a.d)()},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.progress.addBar(this)},t.prototype.ngOnDestroy=function(){this.progress.removeBar(this)},t.prototype.recalculatePercentage=function(){this.percent=+(this.value/this.progress.max*100).toFixed(2);var t=this.progress.bars.reduce(function(t,e){return t+e.percent},0);t>100&&(this.percent-=t-100)},t}(),o=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[r]}},t}()},Dkky:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("fr-ch",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd\u2019hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(t,e){switch(e){default:case"M":case"Q":case"D":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}},week:{dow:1,doy:4}})}()},Dmvi:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},DoHr:function(t,e,n){!function(t){"use strict";var e={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'\xfcnc\xfc",4:"'\xfcnc\xfc",100:"'\xfcnc\xfc",6:"'nc\u0131",9:"'uncu",10:"'uncu",30:"'uncu",60:"'\u0131nc\u0131",90:"'\u0131nc\u0131"};t.defineLocale("tr",{months:"Ocak_\u015eubat_Mart_Nisan_May\u0131s_Haziran_Temmuz_A\u011fustos_Eyl\xfcl_Ekim_Kas\u0131m_Aral\u0131k".split("_"),monthsShort:"Oca_\u015eub_Mar_Nis_May_Haz_Tem_A\u011fu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Sal\u0131_\xc7ar\u015famba_Per\u015fembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_\xc7ar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_\xc7a_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bug\xfcn saat] LT",nextDay:"[yar\u0131n saat] LT",nextWeek:"[gelecek] dddd [saat] LT",lastDay:"[d\xfcn] LT",lastWeek:"[ge\xe7en] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s \xf6nce",s:"birka\xe7 saniye",ss:"%d saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir g\xfcn",dd:"%d g\xfcn",M:"bir ay",MM:"%d ay",y:"bir y\u0131l",yy:"%d y\u0131l"},ordinal:function(t,n){switch(n){case"d":case"D":case"Do":case"DD":return t;default:if(0===t)return t+"'\u0131nc\u0131";var a=t%10;return t+(e[a]||e[t%100-a]||e[t>=100?100:null])}},week:{dow:1,doy:7}})}(n("wd/R"))},DtyJ:function(t,e,n){"use strict";n.r(e);var a=n("6blF"),r=n("KhEm"),i=n("IxPp"),s=n("xTla"),o=n("K9Ia"),u=n("26FU"),c=n("S5bw"),l=n("svcd"),d=n("KQya"),f=n("T1DM"),p=n("zo3G"),h=n("tHPV"),g=n("mrSG"),b=n("h9Dq"),m=function(t){function e(e,n){void 0===e&&(e=y),void 0===n&&(n=Number.POSITIVE_INFINITY);var a=t.call(this,e,function(){return a.frame})||this;return a.maxFrames=n,a.frame=0,a.index=-1,a}return g.__extends(e,t),e.prototype.flush=function(){for(var t,e,n=this.actions,a=this.maxFrames;(e=n[0])&&e.delay<=a&&(n.shift(),this.frame=e.delay,!(t=e.execute(e.state,e.delay))););if(t){for(;e=n.shift();)e.unsubscribe();throw t}},e.frameTimeFactor=10,e}(n("CS9Q").a),y=function(t){function e(e,n,a){void 0===a&&(a=e.index+=1);var r=t.call(this,e,n)||this;return r.scheduler=e,r.work=n,r.index=a,r.active=!0,r.index=e.index=a,r}return g.__extends(e,t),e.prototype.schedule=function(n,a){if(void 0===a&&(a=0),!this.id)return t.prototype.schedule.call(this,n,a);this.active=!1;var r=new e(this.scheduler,this.work);return this.add(r),r.schedule(n,a)},e.prototype.requestAsyncId=function(t,n,a){void 0===a&&(a=0),this.delay=t.frame+a;var r=t.actions;return r.push(this),r.sort(e.sortActions),!0},e.prototype.recycleAsyncId=function(t,e,n){void 0===n&&(n=0)},e.prototype._execute=function(e,n){if(!0===this.active)return t.prototype._execute.call(this,e,n)},e.sortActions=function(t,e){return t.delay===e.delay?t.index===e.index?0:t.index>e.index?1:-1:t.delay>e.delay?1:-1},e}(b.a),v=n("siIJ"),_=n("pugT"),x=n("FFOo"),T=n("60iU"),w=n("y3By"),S=n("+umK"),O=n("mChF"),I=n("zrt+"),C=n("b7mW"),k=n("3fWJ"),N=n("8g8A"),R=n("awvh"),A=n("3U0i"),D=n("67Y/"),E=n("1fDf"),L=n("isby"),P=n("nkY7");function M(t,e,n){if(e){if(!Object(P.a)(e))return function(){for(var a=[],r=0;r<arguments.length;r++)a[r]=arguments[r];return M(t,n).apply(void 0,a).pipe(Object(D.a)(function(t){return Object(L.a)(t)?e.apply(void 0,t):e(t)}))};n=e}return function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];var i,s=this,o={context:s,subject:i,callbackFunc:t,scheduler:n};return new a.a(function(a){if(n)return n.schedule(q,0,{args:e,subscriber:a,params:o});if(!i){i=new l.a;try{t.apply(s,e.concat([function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];i.next(t.length<=1?t[0]:t),i.complete()}]))}catch(r){Object(E.a)(i)?i.error(r):console.warn(r)}}return i.subscribe(a)})}}function q(t){var e=this,n=t.args,a=t.subscriber,r=t.params,i=r.callbackFunc,s=r.context,o=r.scheduler,u=r.subject;if(!u){u=r.subject=new l.a;try{i.apply(s,n.concat([function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];e.add(o.schedule(j,0,{value:t.length<=1?t[0]:t,subject:u}))}]))}catch(c){u.error(c)}}this.add(u.subscribe(a))}function j(t){var e=t.subject;e.next(t.value),e.complete()}function F(t,e,n){if(e){if(!Object(P.a)(e))return function(){for(var a=[],r=0;r<arguments.length;r++)a[r]=arguments[r];return F(t,n).apply(void 0,a).pipe(Object(D.a)(function(t){return Object(L.a)(t)?e.apply(void 0,t):e(t)}))};n=e}return function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];var i={subject:void 0,args:e,callbackFunc:t,scheduler:n,context:this};return new a.a(function(a){var r=i.context,s=i.subject;if(n)return n.schedule(z,0,{params:i,subscriber:a,context:r});if(!s){s=i.subject=new l.a;try{t.apply(r,e.concat([function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t.shift();n?s.error(n):(s.next(t.length<=1?t[0]:t),s.complete())}]))}catch(o){Object(E.a)(s)?s.error(o):console.warn(o)}}return s.subscribe(a)})}}function z(t){var e=this,n=t.params,a=t.subscriber,r=t.context,i=n.callbackFunc,s=n.args,o=n.scheduler,u=n.subject;if(!u){u=n.subject=new l.a;try{i.apply(r,s.concat([function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];var a=t.shift();e.add(a?o.schedule(Y,0,{err:a,subject:u}):o.schedule(G,0,{value:t.length<=1?t[0]:t,subject:u}))}]))}catch(c){this.add(o.schedule(Y,0,{err:c,subject:u}))}}this.add(u.subscribe(a))}function G(t){var e=t.subject;e.next(t.value),e.complete()}function Y(t){t.subject.error(t.err)}var V=n("dzgT"),H=n("dEwP"),B=n("lYZG"),U=n("G5J1"),W=n("VNr4"),K=n("0/uQ"),$=n("bne5"),Z=n("2Bdj");function X(t,e,n){return n?X(t,e).pipe(Object(D.a)(function(t){return Object(L.a)(t)?n.apply(void 0,t):n(t)})):new a.a(function(n){var a,r=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return n.next(1===t.length?t[0]:t)};try{a=t(r)}catch(i){return void n.error(i)}if(Object(Z.a)(e))return function(){return e(r,a)}})}function J(t,e,n,r,i){var s,o;return 1==arguments.length?(o=t.initialState,e=t.condition,n=t.iterate,s=t.resultSelector||O.a,i=t.scheduler):void 0===r||Object(P.a)(r)?(o=t,s=O.a,i=r):(o=t,s=r),new a.a(function(t){var a=o;if(i)return i.schedule(Q,0,{subscriber:t,iterate:n,condition:e,resultSelector:s,state:a});for(;;){if(e){var r=void 0;try{r=e(a)}catch(c){return void t.error(c)}if(!r){t.complete();break}}var u=void 0;try{u=s(a)}catch(c){return void t.error(c)}if(t.next(u),t.closed)break;try{a=n(a)}catch(c){return void t.error(c)}}})}function Q(t){var e=t.subscriber,n=t.condition;if(!e.closed){if(t.needIterate)try{t.state=t.iterate(t.state)}catch(i){return void e.error(i)}else t.needIterate=!0;if(n){var a=void 0;try{a=n(t.state)}catch(i){return void e.error(i)}if(!a)return void e.complete();if(e.closed)return}var r;try{r=t.resultSelector(t.state)}catch(i){return void e.error(i)}if(!e.closed&&(e.next(r),!e.closed))return this.schedule(t)}}function tt(t,e,n){return void 0===e&&(e=U.a),void 0===n&&(n=U.a),Object(B.a)(function(){return t()?e:n})}var et=n("xXU7"),nt=n("p0ib"),at=new a.a(S.a);function rt(){return at}var it=n("F/XL");function st(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if(0===t.length)return U.a;var n=t[0],r=t.slice(1);return 1===t.length&&Object(L.a)(n)?st.apply(void 0,n):new a.a(function(t){var e=function(){return t.add(st.apply(void 0,r).subscribe(t))};return Object(K.a)(n).subscribe({next:function(e){t.next(e)},error:e,complete:e})})}function ot(t,e){return new a.a(e?function(n){var a=Object.keys(t),r=new _.a;return r.add(e.schedule(ut,0,{keys:a,index:0,subscriber:n,subscription:r,obj:t})),r}:function(e){for(var n=Object.keys(t),a=0;a<n.length&&!e.closed;a++){var r=n[a];t.hasOwnProperty(r)&&e.next([r,t[r]])}e.complete()})}function ut(t){var e=t.keys,n=t.index,a=t.subscriber,r=t.subscription,i=t.obj;if(!a.closed)if(n<e.length){var s=e[n];a.next([s,i[s]]),r.add(this.schedule({keys:e,index:n+1,subscriber:a,subscription:r,obj:i}))}else a.complete()}var ct=n("jFaF"),lt=n("Fxb1"),dt=n("VnD/");function ft(t,e,n){return[Object(dt.a)(e,n)(new a.a(Object(lt.a)(t))),Object(dt.a)(Object(ct.a)(e,n))(new a.a(Object(lt.a)(t)))]}var pt=n("W0Ae");function ht(t,e,n){return void 0===t&&(t=0),new a.a(function(a){void 0===e&&(e=t,t=0);var r=0,i=t;if(n)return n.schedule(gt,0,{index:r,count:e,start:t,subscriber:a});for(;;){if(r++>=e){a.complete();break}if(a.next(i++),a.closed)break}})}function gt(t){var e=t.start,n=t.index,a=t.subscriber;n>=t.count?a.complete():(a.next(e),a.closed||(t.index=n+1,t.start=e+1,this.schedule(t)))}var bt=n("XlPw"),mt=n("gI3B");function yt(t,e){return new a.a(function(n){var a,r;try{a=t()}catch(s){return void n.error(s)}try{r=e(a)}catch(s){return void n.error(s)}var i=(r?Object(K.a)(r):U.a).subscribe(n);return function(){i.unsubscribe(),a&&a.unsubscribe()}})}var vt=n("909l"),_t=n("i4X3"),xt=n("iLxQ");n.d(e,"Observable",function(){return a.a}),n.d(e,"ConnectableObservable",function(){return r.a}),n.d(e,"GroupedObservable",function(){return i.a}),n.d(e,"observable",function(){return s.a}),n.d(e,"Subject",function(){return o.a}),n.d(e,"BehaviorSubject",function(){return u.a}),n.d(e,"ReplaySubject",function(){return c.a}),n.d(e,"AsyncSubject",function(){return l.a}),n.d(e,"asapScheduler",function(){return d.a}),n.d(e,"asyncScheduler",function(){return f.a}),n.d(e,"queueScheduler",function(){return p.a}),n.d(e,"animationFrameScheduler",function(){return h.a}),n.d(e,"VirtualTimeScheduler",function(){return m}),n.d(e,"VirtualAction",function(){return y}),n.d(e,"Scheduler",function(){return v.a}),n.d(e,"Subscription",function(){return _.a}),n.d(e,"Subscriber",function(){return x.a}),n.d(e,"Notification",function(){return T.a}),n.d(e,"NotificationKind",function(){return T.b}),n.d(e,"pipe",function(){return w.a}),n.d(e,"noop",function(){return S.a}),n.d(e,"identity",function(){return O.a}),n.d(e,"isObservable",function(){return I.a}),n.d(e,"ArgumentOutOfRangeError",function(){return C.a}),n.d(e,"EmptyError",function(){return k.a}),n.d(e,"ObjectUnsubscribedError",function(){return N.a}),n.d(e,"UnsubscriptionError",function(){return R.a}),n.d(e,"TimeoutError",function(){return A.a}),n.d(e,"bindCallback",function(){return M}),n.d(e,"bindNodeCallback",function(){return F}),n.d(e,"combineLatest",function(){return V.b}),n.d(e,"concat",function(){return H.a}),n.d(e,"defer",function(){return B.a}),n.d(e,"empty",function(){return U.b}),n.d(e,"forkJoin",function(){return W.a}),n.d(e,"from",function(){return K.a}),n.d(e,"fromEvent",function(){return $.a}),n.d(e,"fromEventPattern",function(){return X}),n.d(e,"generate",function(){return J}),n.d(e,"iif",function(){return tt}),n.d(e,"interval",function(){return et.a}),n.d(e,"merge",function(){return nt.a}),n.d(e,"never",function(){return rt}),n.d(e,"of",function(){return it.a}),n.d(e,"onErrorResumeNext",function(){return st}),n.d(e,"pairs",function(){return ot}),n.d(e,"partition",function(){return ft}),n.d(e,"race",function(){return pt.a}),n.d(e,"range",function(){return ht}),n.d(e,"throwError",function(){return bt.a}),n.d(e,"timer",function(){return mt.a}),n.d(e,"using",function(){return yt}),n.d(e,"zip",function(){return vt.b}),n.d(e,"scheduled",function(){return _t.a}),n.d(e,"EMPTY",function(){return U.a}),n.d(e,"NEVER",function(){return at}),n.d(e,"config",function(){return xt.a})},Dwqy:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("wd/R"),r=function(){function t(){}return t.prototype.transform=function(t){return t?a(1e3*t).fromNow():"unknown"},t}()},DxQv:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"s\xf8ndag_mandag_tirsdag_onsdag_torsdag_fredag_l\xf8rdag".split("_"),weekdaysShort:"s\xf8n_man_tir_ons_tor_fre_l\xf8r".split("_"),weekdaysMin:"s\xf8_ma_ti_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"p\xe5 dddd [kl.] LT",lastDay:"[i g\xe5r kl.] LT",lastWeek:"[i] dddd[s kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"f\xe5 sekunder",ss:"%d sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"et \xe5r",yy:"%d \xe5r"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},Dysq:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="zh-TW">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>\u5207\u63db\u5c0e\u89bd</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>\u5100\u8868\u677f</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>\u53e2\u96c6</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>\u4e3b\u6a5f</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>\u76e3\u63a7\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>\u7d44\u614b</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH \u5730\u5716</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>\u7ba1\u7406\u54e1\u6a21\u7d44</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>\u8a18\u9304</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>\u8b66\u793a</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>\u6c60</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>\u5340\u584a</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>\u5f71\u50cf</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>\u93e1\u50cf</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>\u6a94\u6848\u7cfb\u7d71</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>\u7269\u4ef6\u9598\u9053</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>\u6876</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>\u8fd4\u56de</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>\u9078\u53d6\u8a9e\u8a00</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>\u6b63\u5728\u8f09\u5165\u9762\u677f\u8cc7\u6599...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>\u5982\u9700\u4e86\u89e3\u5982\u4f55\u8a2d\u5b9a\u548c\u555f\u7528\u76e3\u63a7\u529f\u80fd\uff0c\n \u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u4ef6\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Grafana \u5100\u8868\u677f\u4e0d\u5b58\u5728\u3002\u5982\u9700\u4e86\u89e3\n \u5982\u4f55\u5411 Grafana\xa0\u65b0\u589e\u5100\u8868\u677f\uff0c\n \u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u4ef6\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Grafana \u6642\u9593\u9078\u64c7\u5668</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>\u91cd\u8a2d\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>\u7121\u6cd5\u8f09\u5165\u8cc7\u6599\u3002</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>\u9078\u53d6\u7684\u6578\u76ee</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>\u627e\u5230\u7684\u6578\u76ee</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>\u7e3d\u8a08</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>\u7de8\u8f2f</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>\u63cf\u8ff0</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>\u8a73\u7d30\u63cf\u8ff0</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>\u9810\u8a2d\u503c</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>\u7cbe\u9748\u9810\u8a2d\u503c</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>\u670d\u52d9</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>\u503c</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u9ad8\uff01\u8a72\u503c\u4e0d\u5f97\u5927\u65bc \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u4f4e\uff01\u8a72\u503c\u4e0d\u5f97\u5c0f\u65bc \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>\u5132\u5b58</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>CRUSH \u5730\u5716\u6aa2\u8996\u5668</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>\u4e3b\u6a5f\u6e05\u55ae</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>\u6574\u9ad4\u6548\u80fd</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>\u627e\u4e0d\u5230\u9805\u76ee</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>\u53e2\u96c6\u8a18\u9304</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>\u7a3d\u6838\u8a18\u9304</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>\u6b63\u5728\u8f09\u5165\u7d44\u614b...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>\u7121\u6cd5\u8f09\u5165\u7d44\u614b\u3002</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>\u7de8\u8f2f\u7ba1\u7406\u54e1\u6a21\u7d44</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>\u8f38\u5165\u7684\u503c\u4e0d\u662f\u6709\u6548\u7684 UUID\uff0c\u4f8b\u5982 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>\u8f38\u5165\u7684\u503c\u5fc5\u9808\u662f\u6709\u6548\u7684 IP \u4f4d\u5740\u3002</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>\u6b64\u6b04\u4f4d\u70ba\u5fc5\u586b\u6b04\u4f4d\u3002</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u9ad8\uff01\u8a72\u503c\u5fc5\u9808\u5c0f\u65bc\u6216\u7b49\u65bc \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u4f4e\uff01\u8a72\u503c\u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>\u8f38\u5165\u7684\u503c\u5fc5\u9808\u70ba\u6578\u5b57\u3002</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>\u8f38\u5165\u7684\u503c\u5fc5\u9808\u70ba\u6578\u5b57\u6216\u5c0f\u6578\u3002</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>\u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>\u53e2\u96c6 ID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap \u4fee\u6539\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap \u7248\u672c\u7de8\u865f</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>required con</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>required mon</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>\u4ef2\u88c1\u6210\u54e1</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>\u975e\u4ef2\u88c1\u6210\u54e1</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>\u53d6\u6d88</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>\u78ba\u5b9a\u8981\n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\u9078\u53d6\u7684\n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\u55ce\uff1f\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>\u662f\u7684\uff0c\u6211\u78ba\u5b9a\u3002</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>\u53e2\u96c6\u7bc4\u570d\u7684 OSD \u65d7\u6a19</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>\u63d0\u4ea4</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>\u9032\u968e...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>OSD \u5fa9\u539f\u512a\u5148\u7a0b\u5ea6</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>\u512a\u5148\u7a0b\u5ea6</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>\u81ea\u8a02\u512a\u5148\u7a0b\u5ea6\u503c</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>\u6b64\u6b04\u4f4d\u70ba\u5fc5\u586b\u6b04\u4f4d\uff01</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u9ad8\uff01\u8a72\u503c\u4e0d\u5f97\u5927\u65bc \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>\u8f38\u5165\u7684\u503c\u592a\u4f4e\uff01\u8a72\u503c\u4e0d\u5f97\u5c0f\u65bc \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>\u91cd\u65b0\u8a2d\u5b9a OSD \u7684\u6b0a\u6578</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>\u8a72\u503c\u5fc5\u9808\u4ecb\u65bc 0 \u81f3 1 \u4e4b\u9593\u3002</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>\u91cd\u65b0\u8a2d\u5b9a\u6b0a\u6578</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\u6574\u7406\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {\u6df1\u5c64} }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>\u5373\u5c07\u5c0d OSD\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n \u5957\u7528\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\u6574\u7406\u3002 \n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {\u6df1\u5c64} }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>OSD \u6e05\u55ae</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u82e5\u7e7c\u7e8c\uff0c\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD\n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n \u5c07\u88ab\u6a19\u793a\u70ba\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>OSD \u4e0d\u5b89\u5168\uff0c\u7121\u6cd5\u640d\u6bc0\uff01</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u82e5\u7e7c\u7e8c\uff0c\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD\n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n \u5c07\u88ab\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>\u8a73\u7d30\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>\u503c</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>\u95dc\u9589</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>\u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>\u7d71\u8a08\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>\u5982\u9700\u4e86\u89e3\u5982\u4f55\u8a2d\u5b9a\u548c\u555f\u7528 NFS Ganesha \u7ba1\u7406\u529f\u80fd\uff0c\n \u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u4ef6\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>\u7528\u6236\u7aef</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>\u4efb\u4f55\u7528\u6236\u7aef\u5747\u53ef\u5b58\u53d6</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>\u4f4d\u5740</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>\u5fc5\u586b\u6b04\u4f4d</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>\u5fc5\u9808\u5305\u542b\u4e00\u6216\u591a\u500b\u9017\u865f\u5206\u9694\u503c</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>\u4f8b\u5982\ufe30</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>\u5b58\u53d6\u985e\u578b</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>\u65b0\u589e\u7528\u6236\u7aef</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>\u6b63\u5728\u8f09\u5165...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u53e2\u96c6 --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- \u9078\u53d6\u53e2\u96c6 --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>\u65b0\u589e\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>\u5132\u5b58\u5f8c\u7aef</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u8cc7\u6599\u6c60 --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- \u9078\u53d6\u5132\u5b58\u5f8c\u7aef --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>\u7269\u4ef6\u9598\u9053\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u4f7f\u7528\u8005 --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- \u9078\u53d6\u7269\u4ef6\u9598\u9053\u4f7f\u7528\u8005 --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS \u4f7f\u7528\u8005 ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u7528\u6236\u7aef --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- \u9078\u53d6 cephx \u7528\u6236\u7aef --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>CephFS \u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>\u5b89\u5168\u6a19\u7c64</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>\u555f\u7528\u5b89\u5168\u6a19\u7c64</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS \u8def\u5f91</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>\u8def\u5f91\u5fc5\u9808\u4ee5\u300c/\u300d\u958b\u982d\uff0c\u5f8c\u9762\u53ef\u63a5\u55ae\u8a5e</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>\u5c07\u5efa\u7acb\u65b0\u76ee\u9304</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>\u8def\u5f91</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>\u8def\u5f91\u53ea\u80fd\u4ee5\u55ae\u4e00\u300c/\u300d\u6216\u55ae\u8a5e\u958b\u982d</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>\u5c07\u5efa\u7acb\u65b0\u6876</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS \u901a\u8a0a\u5354\u5b9a</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS \u6a19\u8a18</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u639b\u63a5\u7684\u5099\u7528\u5b58\u53d6 (\u4e0d\u5f97\u5305\u542b\u524d\u7f6e /)\u3002\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>\u7528\u6236\u7aef\u4e0d\u80fd\u639b\u63a5\u5b50\u76ee\u9304 (\u5373\u5982\u679c\u6a19\u8a18\u70ba foo\uff0c\u5247\u7528\u6236\u7aef\u7121\u6cd5\u639b\u63a5 foo/baz)\u3002</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>\u900f\u904e\u4f7f\u7528\u4e0d\u540c\u6a19\u8a18\u9078\u9805\uff0c\u53ef\u5c07\u540c\u4e00\u8def\u5f91\u8f38\u51fa\u591a\u6b21\u3002</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>\u865b\u64ec</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>\u6b64 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u8f38\u51fa\u5728\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\u865b\u64ec\u6a94\u6848\u7cfb\u7d71\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u4e2d\n \u6240\u4f54\u7528\u7684\u4f4d\u7f6e (\u5fc5\u9808\u552f\u4e00)\u3002\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>\u900f\u904e\u4f7f\u7528\u4e0d\u540c\u865b\u64ec\u9078\u9805\uff0c\u53ef\u5c07\u540c\u4e00\u8def\u5f91\u8f38\u51fa\u591a\u6b21\u3002</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u5b58\u53d6\u985e\u578b --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- \u9078\u53d6\u5b58\u53d6\u985e\u578b --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684 squash --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- \u9078\u53d6\u57f7\u884c\u54ea\u7a2e\u985e\u578b\u7684\u4f7f\u7528\u8005 ID \u533f\u540d\u5b58\u53d6 --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>\u50b3\u8f38\u901a\u8a0a\u5354\u5b9a</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>\u6b61\u8fce\u4f7f\u7528 Ceph\uff01</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>\u9700\u8981\u6307\u5b9a\u4f7f\u7528\u8005\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>\u9700\u8981\u6307\u5b9a\u5bc6\u78bc</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>\u767b\u5165</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>\u62b1\u6b49\uff0c\u8a72\u4f7f\u7528\u8005\u4e0d\u5b58\u5728\u65bc Ceph \u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>\u8fd4\u56de\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u767b\u5165\u9801\u9762\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002 \u7576\u60a8\u91cd\u8a66\u767b\u5165\u6642\uff0c\u60a8\u5c07\u5f9e\u8eab\u5206\u63d0\u4f9b\u8005\u767b\u51fa\u3002\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>\u5df2\u7981\u6b62</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>\u62b1\u6b49\uff0c\u60a8\u7121\u6b0a\u67e5\u770b\u60a8\u8981\u5c0b\u627e\u7684\u5167\u5bb9\u3002</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>\u62b1\u6b49\uff0c\u6211\u5011\u627e\u4e0d\u5230\u60a8\u8981\u5c0b\u627e\u7684\u5167\u5bb9\u3002</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>\u5168\u90e8\u79fb\u9664</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>\u6700\u8fd1\u7684\u901a\u77e5</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>\u6c92\u6709\u80cc\u666f\u4efb\u52d9\u3002</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>\u80cc\u666f\u4efb\u52d9</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>\u8aaa\u660e</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>\u6587\u4ef6</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\u95dc\u65bc</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>\u5100\u8868\u677f\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>\u4f7f\u7528\u8005\u7ba1\u7406</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>\u767b\u5165\u7684\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>\u4ee5\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n \u8eab\u5206\u767b\u5165\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>\u767b\u51fa</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>\u540d\u7a31...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>\u6240\u9078\u7684\u540d\u7a31\u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>\u63cf\u8ff0...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>\u8a31\u53ef\u6b0a</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>\u89d2\u8272</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>\u4f7f\u7528\u8005\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>\u5bc6\u78bc</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>\u78ba\u8a8d\u5bc6\u78bc</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>\u78ba\u8a8d\u7684\u5bc6\u78bc\u8207\u4e4b\u524d\u8f38\u5165\u7684\u5bc6\u78bc\u4e0d\u7b26\u3002</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>\u5168\u540d</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>\u96fb\u5b50\u90f5\u4ef6</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>\u96fb\u5b50\u90f5\u4ef6\u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>\u60a8\u6b63\u8981\u70ba\u60a8\u81ea\u5df1\u7684\u4f7f\u7528\u8005\u79fb\u9664\u300c\u4f7f\u7528\u8005\u8b80\u53d6/\u5beb\u5165\u300d\u8a31\u53ef\u6b0a\u3002</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>\u82e5\u7e7c\u7e8c\uff0c\u60a8\u5c07\u518d\u4e5f\u7121\u6cd5\u70ba\u4efb\u4f55\u4f7f\u7528\u8005\u65b0\u589e\u6216\u79fb\u9664\u89d2\u8272\u3002</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>\u78ba\u5b9a\u8981\u7e7c\u7e8c\u55ce\uff1f</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u6548\u80fd\u8a08\u6578\u5668</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>\u5c6c\u6027 (OSD \u5730\u5716)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>\u7121\u6cd5\u4f7f\u7528\u4e2d\u7e7c\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>\u4e2d\u7e7c\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>\u6548\u80fd\u8a08\u6578\u5668</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>\u7121\u6cd5\u4f7f\u7528\u9577\u689d\u5716\ufe30\n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>\u5beb\u5165</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>\u8b80\u53d6</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>\u9577\u689d\u5716</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>\u6548\u80fd\u8a73\u7d30\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>\u76ee\u524d\u7684\u503c</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>\u985e\u578b</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>\u6700\u5c0f\u503c</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>\u6700\u5927\u503c</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>\u65d7\u6a19</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>\u4f86\u6e90</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>\u5c64\u7d1a</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>\u53ef\u5728\u57f7\u884c\u6642\u671f\u66f4\u65b0 (\u53ef\u7de8\u8f2f)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>\u6a19\u8a18</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>\u5217\u8209\u503c</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>\u53e6\u8acb\u53c3\u95b1</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>\u53e2\u96c6\u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>\u7ba1\u7406\u54e1\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>\u7269\u4ef6\u9598\u9053</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>\u4e2d\u7e7c\u8cc7\u6599\u4f3a\u670d\u5668</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI \u9598\u9053</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>\u7528\u6236\u7aef IOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>\u7528\u6236\u7aef\u8f38\u9001\u91cf</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>\u7528\u6236\u7aef\u8b80\u53d6/\u5beb\u5165</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>\u5fa9\u539f\u8f38\u9001\u91cf</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>\u6574\u7406</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>\u6548\u80fd</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>\u539f\u59cb\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>\u7269\u4ef6</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>\u6bcf\u500b OSD \u7684 PG \u6578</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>PG \u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>\u5982\u9700\u8a73\u7d30\u8cc7\u6599\uff0c\u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u8a18\u9304\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>\u968e\u5c64</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>\u7528\u6236\u7aef\ufe30\n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>\u5c07\u5f71\u50cf\u79fb\u81f3\u5783\u573e\u6876</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>\u82e5\u8981\u5c07 \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> \u79fb\u81f3\u5783\u573e\u6876\uff0c\n \u8acb\u6309\u4e00\u4e0b\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u79fb\u52d5\u5f71\u50cf\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\u6216\u8005\uff0c\u60a8\u53ef\u4ee5\u9078\u53d6\u4e00\u500b\u904e\u671f\u65e5\u3002\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>\u4fdd\u8b77\u7684\u904e\u671f\u65e5\u70ba</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>\u7121\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>\u65e5\u671f\u683c\u5f0f\u932f\u8aa4\u3002\u8acb\u4f7f\u7528\u300cYYYY-MM-DD HH:mm:ss\u300d\u3002</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>\u4fdd\u8b77\u5df2\u904e\u671f\u3002\u8acb\u9078\u53d6\u4e00\u500b\u672a\u4f86\u7684\u65e5\u671f\u6216\u4fdd\u7559\u7a7a\u767d\u3002</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>\u79fb\u52d5\u5f71\u50cf</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>\u7d9c\u89bd</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>\u76ee\u6a19</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>\u63a2\u67e5\u9a57\u8b49</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u4f7f\u7528\u8005\u540d\u7a31\u7684\u9577\u5ea6\u5fc5\u9808\u4ecb\u65bc 8 \u81f3 64 \u500b\u5b57\u5143\u4e4b\u9593\uff0c\u4e26\u4e14\u53ea\u80fd\u5305\u542b\u4ee5\u4e0b\n \u5b57\u5143\ufe30\u5b57\u6bcd\u3001\u300c.\u300d\u3001\u300c@\u300d\u3001\u300c-\u300d\u3001\u300c_\u300d\u6216\u300c:\u300d\u3002</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>\u96d9\u5411\u9a57\u8b49\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>\u96d9\u5411\u9a57\u8b49\u5bc6\u78bc</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>\u5982\u9700\u4e86\u89e3\u5982\u4f55\u8a2d\u5b9a\u548c\u555f\u7528 iSCSI \u76ee\u6a19\u7ba1\u7406\u529f\u80fd\uff0c\n \u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u4ef6\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>\u53ef\u7528\u8cc7\u8a0a\ufe30</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>\u7121\u6cd5\u4f7f\u7528 iSCSI \u76ee\u6a19</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>\u50c5\u9069\u7528\u65bc\u5df2\u555f\u7528 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u7684 RBD \u5f71\u50cf\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>\u6c60</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>\u8cc7\u6599\u6c60</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>\u5df2\u5efa\u7acb</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>\u7269\u4ef6\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>\u529f\u80fd</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>\u5df2\u4f48\u5efa</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>\u7121</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>\u7e3d\u4f48\u5efa\u6578</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>\u5206\u5272\u55ae\u4f4d</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>\u5206\u5272\u8a08\u6578</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>\u7236</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>\u5340\u584a\u540d\u7a31\u5b57\u9996</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>\u9806\u5e8f</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>\u5feb\u7167</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>\u5f71\u50cf</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>\u6b64\u8a2d\u5b9a\u6703\u8986\u5beb\u5168\u57df\u503c</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>\u5168\u57df</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>\u6b64\u503c\u70ba\u5168\u57df\u503c\u3002\u672a\u70ba\u6b64\u5f71\u50cf\u8a2d\u5b9a\u6b64\u9078\u9805\u7684\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\u4e0d\u5141\u8a31\u4f7f\u7528\u300c/\u300d\u548c\u300c@\u300d\u3002</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684 RBD \u6c60 --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- \u9078\u53d6\u6c60 --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>\u4f7f\u7528\u5c08\u5c6c\u7684\u8cc7\u6599\u6c60</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>\u8cc7\u6599\u6c60</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>\u5c08\u7528\u65bc\u5132\u5b58 RBD \u7684\u7269\u4ef6\u8cc7\u6599\u7684\u6c60</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>\u4f8b\u5982 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>\u60a8\u5fc5\u9808\u589e\u52a0\u5927\u5c0f\u3002</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>\u9032\u968e</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>\u5206\u5272</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>\u5206\u5272\u55ae\u4f4d</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- \u9078\u53d6\u5206\u5272\u55ae\u4f4d --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>\u7531\u65bc\u5df2\u5b9a\u7fa9\u5206\u5272\u8a08\u6578\uff0c\u56e0\u6b64\u5fc5\u9808\u586b\u5beb\u6b64\u6b04\u4f4d\uff01</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>\u5206\u5272\u55ae\u4f4d\u5927\u65bc\u7269\u4ef6\u5927\u5c0f\u3002</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>\u5206\u5272\u8a08\u6578</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>\u7531\u65bc\u5df2\u5b9a\u7fa9\u5206\u5272\u55ae\u4f4d\uff0c\u56e0\u6b64\u5fc5\u9808\u586b\u5beb\u6b64\u6b04\u4f4d\uff01</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>\u5206\u5272\u8a08\u6578\u5fc5\u9808\u5927\u65bc 0\u3002</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD \u5feb\u7167\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {\u91cd\u65b0\u547d\u540d} other {\u5efa\u7acb} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>\u5feb\u7167\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>\u53d7\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>\u672a\u53d7\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>\u60a8\u6b63\u8981\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>\u6e05\u9664\u5783\u573e\u6876</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>\u82e5\u8981\u6e05\u9664\uff0c\u8acb\u9078\u53d6\u4e00\u500b\u6216\u5168\u90e8\u5f71\u50cf\uff0c\u7136\u5f8c\u6309\u4e00\u4e0b</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>\u6c60\ufe30</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>\u6c60\u540d\u7a31...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>\u5168\u90e8</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>\u56de\u5b58\u5f71\u50cf</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>\u82e5\u8981\u56de\u5b58</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>\u9375\u5165\u5f71\u50cf\u7684\u65b0\u540d\u7a31\u5e76\u6309\u4e00\u4e0b</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>\u65b0\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>\u904e\u671f\u65e5\u70ba</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>\u4fdd\u8b77\u904e\u671f\u65e5\u70ba</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>\u6b64\u5f71\u50cf\u7684\u4fdd\u8b77\u904e\u671f\u65e5\u70ba \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>\u5783\u573e\u6876</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>iSCSI \u62d3\u64b2</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>\u901a\u5e38\u4e0d\u9700\u8981\u8b8a\u66f4\u9019\u4e9b\u53c3\u6578\u7684\u9810\u8a2d\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>\u652f\u63f4\u5132\u5b58</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>\u78ba\u8a8d</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>\u9032\u968e\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>\u76ee\u6a19 IQN</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN \u6a21\u5f0f\u932f\u8aa4\u3002</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN \u6a21\u5f0f\u61c9\u5982\u4e0b\u6240\u793a\ufe30\u300ciqn.$year-$month.$reversedAddress:$definedName\u300d</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>\u4f8b\u5982\uff1aiqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>\u66f4\u591a\u8cc7\u8a0a</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>\u6b64\u76ee\u6a19\u7684\u9032\u968e\u8a2d\u5b9a\u5b58\u5728\u4fee\u6539\u3002</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>\u5165\u53e3\u7db2\u7ad9</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>\u81f3\u5c11\u9700\u8981 \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> \u500b\u7269\u4ef6\u9598\u9053\u3002\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>\u65b0\u589e\u5165\u53e3\u7db2\u7ad9</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>\u6b64\u5f71\u50cf\u7684\u8a2d\u5b9a\u5b58\u5728\u4fee\u6539\u3002</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>\u65b0\u589e\u5f71\u50cf</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL \u9a57\u8b49</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>\u555f\u52d5\u5668</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>\u555f\u52d5\u5668</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>\u7528\u6236\u7aef IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>\u555f\u52d5\u5668 IQN \u5fc5\u9808\u552f\u4e00\u3002</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u4f7f\u7528\u8005\u540d\u7a31\u7684\u9577\u5ea6\u5fc5\u9808\u4ecb\u65bc 8 \u81f3 64 \u500b\u5b57\u5143\u4e4b\u9593\uff0c\u4e26\u4e14\u53ea\u80fd\u5305\u542b\u4ee5\u4e0b\n \u5b57\u5143\ufe30\u5b57\u6bcd\u3001\u300c.\u300d\u3001\u300c@\u300d\u3001\u300c-\u300d\u3001\u300c_\u300d\u6216\u300c:\u300d\u3002</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>\u555f\u52d5\u5668\u5c6c\u65bc\u7fa4\u7d44\u3002\u5f71\u50cf\u9808\u5728\u7fa4\u7d44\u4e2d\u9032\u884c\u8a2d\u5b9a\u3002 </target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>\u672a\u65b0\u589e\u9805\u76ee\u3002</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>\u65b0\u589e\u555f\u52d5\u5668</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>\u7fa4\u7d44</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>\u7fa4\u7d44</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>\u65b0\u589e\u7fa4\u7d44</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>RBD \u7d44\u614b</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>\u79fb\u9664\u672c\u5730\u7d44\u614b\u503c\u3002\u5c07\u7e7c\u627f\u4e26\u4f7f\u7528\u7236\u7d44\u614b\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>\u6700\u5c0f\u503c\u70ba 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>\u554f\u984c</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>\u6b63\u5728\u540c\u6b65</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>\u6e96\u5099\u5c31\u7dd2</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>\u7de8\u8f2f\u6c60\u93e1\u50cf\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\u82e5\u8981\u7de8\u8f2f\u6c60 \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\xa0\n \u7684\u93e1\u50cf\u6a21\u5f0f\uff0c\u8acb\u5f9e\u6e05\u55ae\u4e2d\u9078\u53d6\u4e00\u500b\u65b0\u6a21\u5f0f\uff0c\u7136\u5f8c\u6309\u4e00\u4e0b\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u66f4\u65b0\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>\u5728\u505c\u7528\u93e1\u50cf\u4e4b\u524d\uff0c\u5fc5\u9808\u5148\u79fb\u9664\u5c0d\u7b49\u53e2\u96c6\u3002</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n \u6c60\u93e1\u50cf\u5c0d\u7b49\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {\u7de8\u8f2f} other {\u65b0\u589e} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\u6c60\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u7684\n \u93e1\u50cf\u5c0d\u7b49\u5c6c\u6027\uff0c\u7136\u5f8c\u6309\u4e00\u4e0b\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u63d0\u4ea4\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>\u53e2\u96c6\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>\u53e2\u96c6\u540d\u7a31\u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>CephX ID \u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>\u76e3\u63a7\u7a0b\u5f0f\u4f4d\u5740</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>\u9017\u865f\u5206\u9694\u7684\u4f4d\u5740...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>\u76e3\u63a7\u7a0b\u5f0f\u4f4d\u5740\u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX \u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64 \u7de8\u78bc\u7684\u91d1\u9470...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>CephX \u91d1\u9470\u5fc5\u9808\u70ba Base64 \u7de8\u78bc\u7684\u91d1\u9470\u3002</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>\u6c60\u6e05\u55ae</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>\u540d\u7a31\u53ea\u80fd\u7531\u82f1\u6578\u5b57\u5143\u3001\u7834\u6298\u865f\u548c\u5e95\u7dda\u7d44\u6210\u3002</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>\u6240\u9078\u7684\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94\u540d\u7a31\u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>\u5916\u639b\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>\u8cc7\u6599\u5340\u584a (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>\u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc 2\u3002</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>\u7de8\u78bc\u5340\u584a (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>\u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc 1\u3002</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>\u6301\u4e45\u6027\u4f30\u503c (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>\u672c\u5730\u6027 (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>CRUSH \u6545\u969c\u7db2\u57df</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>CRUSH \u672c\u5730\u6027</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>\u7121</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>\u6280\u8853</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>\u5c01\u5305\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>CRUSH \u6839</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>CRUSH \u88dd\u7f6e\u985e\u5225</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>\u4efb\u4f55</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>\u76ee\u9304</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>\u6240\u9078\u7684 Ceph \u6c60\u540d\u7a31\u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>\u6c60\u985e\u578b</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- \u9078\u53d6\u6c60\u985e\u578b --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>\u653e\u7f6e\u7fa4\u7d44</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>\u81f3\u5c11\u9700\u8981\u4e00\u500b\u653e\u7f6e\u7fa4\u7d44\uff01</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>\u60a8\u7684\u53e2\u96c6\u7121\u6cd5\u8655\u7406\u9019\u9ebc\u591a\u7684 PG\u3002\u8acb\u91cd\u65b0\u8a08\u7b97\u6240\u9700\u7684 PG \u6578\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>\u8a08\u7b97\u8aaa\u660e</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>\u5df2\u70ba\u60a8\u8a08\u7b97\u76ee\u524d\u7684 PG \u8a2d\u5b9a\uff0c\u60a8\n \u61c9\u5728\u63d0\u4ea4\u524d\u78ba\u5b9a\u9019\u4e9b\u503c\u7b26\u5408\u60a8\u7684\u9700\u6c42\u3002</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>CRUSH \u898f\u5247\u96c6</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- \u9078\u53d6 CRUSH \u898f\u5247 --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>CRUSH \u898f\u5247</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>CRUSH \u6b65\u9a5f</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>\u7121\u6cd5\u5728\u76ee\u524d\u7684\u53e2\u96c6\u4e2d\u4f7f\u7528\u6b64\u898f\u5247\uff0c\u56e0\u70ba\u53e2\u96c6\u7684\n OSD \u6578\u91cf\u904e\u5c11\uff0c\u7121\u6cd5\u6eff\u8db3\u898f\u5247\u6240\u9700\u7684\u6700\u4f4e OSD \u6578\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>\u8907\u88fd\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>\u6700\u4f4e\ufe30\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>\u6700\u9ad8\ufe30\n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>\u6307\u5b9a\u7684\u5927\u5c0f\u8d85\u51fa\u4e86\u7bc4\u570d\u3002\u4ecb\u65bc\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> \u81f3 \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> \u4e4b\u9593\u7684\u503c\u624d\u6709\u6548\u3002\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94 --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- \u9078\u53d6\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94 --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC \u8986\u5beb</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>\u61c9\u7528\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>\u58d3\u7e2e</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>\u6f14\u7b97\u6cd5</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- \u6c92\u6709\u53ef\u7528\u7684\u7cfe\u522a\u58d3\u7e2e\u6f14\u7b97\u6cd5 --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Blob \u6700\u5c0f\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>\u4f8b\u5982 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>\u503c\u61c9\u5927\u65bc 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Blob \u6700\u5927\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>\u4f8b\u5982 512 KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>\u503c\u61c9\u5927\u65bc blob \u6700\u5c0f\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>\u6bd4\u7387</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>\u58d3\u7e2e\u7387</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>\u503c\u61c9\u4ecb\u65bc 0.0 \u81f3 1.0 \u4e4b\u9593</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>\u7121\u6cd5\u5efa\u7acb\u540d\u7a31\u4e2d\u5305\u542b\u300c/\u300d\u7684 RBD \u6c60\u3002</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>\u8acb\u8b8a\u66f4\u540d\u7a31\u6216\u5c07\u300crbd\u300d\u5f9e\u61c9\u7528\u7a0b\u5f0f\u6e05\u55ae\u4e2d\u79fb\u9664\u3002</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>\u5feb\u53d6\u5c64\u8a73\u7d30\u8cc7\u6599</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>\u5982\u9700\u4e86\u89e3\u5982\u4f55\u8a2d\u5b9a\u548c\u555f\u7528\u7269\u4ef6\u9598\u9053\u7ba1\u7406\u529f\u80fd\uff0c\n \u8acb\u53c3\u95b1\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u4ef6\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>\u7cbe\u9748\u6e05\u55ae</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>\u6548\u80fd\u8a08\u6578\u5668</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>\u6b63\u5728\u8f09\u5165\u6876\u8cc7\u6599...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>\u7121\u6cd5\u8f09\u5165\u6876\u8cc7\u6599\u3002</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>\u8a72\u503c\u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>\u64c1\u6709\u8005</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- \u9078\u53d6\u4f7f\u7528\u8005 --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>\u7d22\u5f15\u985e\u578b</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>\u653e\u7f6e\u898f\u5247</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>\u6a19\u8a18</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>\u6700\u5927\u6a19\u8a18\u6578</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>\u4e3b\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>\u4fee\u6539\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>\u5340\u57df\u7fa4\u7d44</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>\u6876\u5b9a\u984d</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>\u5df2\u555f\u7528</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>\u6700\u5927\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>\u7121\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>\u6700\u5927\u7269\u4ef6\u6578</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- \u9078\u53d6\u4f7f\u7528\u8005\u540d\u7a31 --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>\u81ea\u52d5\u7522\u751f\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>\u5b58\u53d6\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>\u6a5f\u5bc6\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>\u96fb\u5b50\u90f5\u4ef6\u5730\u5740</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>\u5df2\u66ab\u505c</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>\u7cfb\u7d71</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {\u5426} 1 {\u662f} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>\u6700\u5927\u6876\u6578</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>\u5b50\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>\u529f\u80fd</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>\u4f7f\u7528\u8005\u5b9a\u984d</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>\u986f\u793a</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- \u9078\u53d6\u985e\u578b --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>\u8a31\u53ef\u6b0a</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- \u9078\u53d6\u8a31\u53ef\u6b0a --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>\u5b50\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>\u6240\u9078\u7684\u5b50\u4f7f\u7528\u8005 ID \u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>\u8b80\u53d6\u3001\u5beb\u5165</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>\u5b8c\u6574</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Swift \u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>\u81ea\u52d5\u7522\u751f\u6a5f\u5bc6\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>\u6b63\u5728\u8f09\u5165\u4f7f\u7528\u8005\u8cc7\u6599...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>\u7121\u6cd5\u8f09\u5165\u4f7f\u7528\u8005\u8cc7\u6599\u3002</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>\u6240\u9078\u7684\u4f7f\u7528\u8005 ID \u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>\u96fb\u5b50\u90f5\u4ef6\u5730\u5740\u7121\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>\u6240\u9078\u7684\u96fb\u5b50\u90f5\u4ef6\u5730\u5740\u5df2\u5728\u4f7f\u7528\u4e2d\u3002</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>\u6700\u5927\u6876\u6578</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>\u8f38\u5165\u7684\u503c\u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc 0\u3002</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3 \u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>\u6c92\u6709\u5b50\u4f7f\u7528\u8005\u3002</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>\u6c92\u6709\u91d1\u9470\u3002</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>\u6c92\u6709\u529f\u80fd\u3002</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>\u5927\u5c0f\u4e0d\u9650</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>\u6700\u5927\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>\u7269\u4ef6\u6578\u4e0d\u9650</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>\u6700\u5927\u7269\u4ef6\u6578</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>\u76ee\u524d</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>\u5df2\u66f4\u65b0\u63a2\u67e5\u9a57\u8b49</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u5165\u53e3\u7db2\u7ad9\u3002</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u5f71\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u5f71\u50cf\u3002\u8acb\u78ba\u5b9a\u70ba\u76ee\u6a19\u65b0\u589e\u4e00\u500b\u5f71\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u555f\u52d5\u5668\u3002\u8acb\u78ba\u5b9a\u70ba\u76ee\u6a19\u65b0\u589e\u4e00\u500b\u555f\u52d5\u5668\u3002</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>\u76ee\u6a19</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>\u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>\u8b80\u53d6\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>\u5beb\u5165\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>\u8b80\u53d6\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>\u5beb\u5165\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>\u4f7f\u7528\u4e2d/\u6700\u4f73\u5316\u958b\u59cb\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>\u4f8b\u9805</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>\u4e3b\u6a5f\u540d\u7a31</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>\u554f\u984c</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>\u9032\u5ea6</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>\u5df2\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>\u7de8\u8f2f\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>\u65b0\u589e\u5c0d\u7b49</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>\u7de8\u8f2f\u5c0d\u7b49</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>\u522a\u9664\u5c0d\u7b49</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Leader</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>\u672c\u5730\u6578\u91cf</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>\u9060\u7aef\u6578\u91cf</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>\u93e1\u50cf\u5c0d\u7b49</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>\u91d1\u9470</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>\u6df1\u5c64\u58d3\u5e73</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>\u5206\u5c64</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>\u7368\u4f54\u9396\u5b9a</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>\u7269\u4ef6\u5c0d\u61c9 (\u9700\u8981\u7368\u4f54\u9396\u5b9a)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>\u8a18\u9304 (\u9700\u8981\u7368\u4f54\u9396\u5b9a)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>RBD \u5feb\u7167\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>RBD \u5feb\u7167</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>\u522a\u9664\u4f4d\u7f6e</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>\u985e\u578b</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>\u72c0\u614b</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>\u4e3b\u6a5f</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>\u6839</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>\u968e\u5c64</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>\u6d3b\u52d5</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentry</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inode</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>\u4f7f\u7528\u7387</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>\u5f85\u547d\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\u8a72\u503c\u53ef\u5728\u57f7\u884c\u6642\u671f\u66f4\u65b0\u3002</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>\u7cbe\u9748/\u7528\u6236\u7aef\u4e0d\u6703\u5f9e\u76e3\u63a7\u7a0b\u5f0f\u7d44\u614b\u8cc7\u6599\u5eab\n \u63d0\u53d6\u6b64\u503c\u3002\u6211\u5011\u4e0d\u5141\u8a31\u900f\u904e\u300cceph config set ...\u300d\n \u8a2d\u5b9a\u6b64\u9078\u9805\u3002\u61c9\u900f\u904e ceph.conf \u6216\u4f7f\u7528\u6307\u4ee4\u884c\n \u9032\u884c\u8a2d\u5b9a\u3002</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>\u8a72\u9078\u9805\u50c5\u5728\u7cbe\u9748\u555f\u52d5\u671f\u9593\u751f\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>\u8a72\u9078\u9805\u50c5\u5f71\u97ff\u53e2\u96c6\u5efa\u7acb\u3002</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>\u8a72\u9078\u9805\u50c5\u5f71\u97ff\u7cbe\u9748\u5efa\u7acb\u3002</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>\u5df2\u66f4\u65b0\u7d44\u614b\u9078\u9805\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>\u670d\u52d9</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>\u76ee\u524d\u7684\u503c</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>\u53ef\u7de8\u8f2f</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>\u5df2\u66f4\u65b0\u6a21\u7d44\u300c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u300d\u7684\u9078\u9805\u3002\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>\u555f\u7528</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>\u6b63\u5728\u91cd\u65b0\u9023\u63a5\uff0c\u8acb\u7a0d\u5019...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>\u516c\u7528\u4f4d\u5740</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>\u958b\u555f\u7684\u5de5\u4f5c\u968e\u6bb5</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>\u7981\u6b62\u6a19\u793a\u70ba In</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>\u4e4b\u524d\u6a19\u793a\u70ba out \u7684 OSD \u5728\u555f\u52d5\u6642\u5c07\u4e0d\u6703\u91cd\u65b0\u6a19\u793a\u70ba in</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>\u7981\u6b62\u6a19\u793a\u70ba Out</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD \u5728\u8a2d\u5b9a\u7684\u9593\u9694\u904e\u5f8c\u5c07\u4e0d\u6703\u81ea\u52d5\u6a19\u793a\u70ba out</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>\u7981\u6b62\u6a19\u793a\u70ba Up</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>\u4e0d\u5141\u8a31 OSD \u555f\u52d5</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>\u7981\u6b62\u6a19\u793a\u70ba Down</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>\u5c07\u6703\u5ffd\u7565 OSD \u6545\u969c\u5831\u544a\uff0c\u5982\u6b64\u76e3\u63a7\u7a0b\u5f0f\u4fbf\u4e0d\u6703\u5c07 OSD \u6a19\u793a\u70ba down</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>\u66ab\u505c</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>\u66ab\u505c\u8b80\u53d6\u548c\u5beb\u5165</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>\u7981\u6b62\u6574\u7406</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>\u6574\u7406\u5df2\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>\u7981\u6b62\u6df1\u5c64\u6574\u7406</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>\u6df1\u5c64\u6574\u7406\u5df2\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>\u7981\u6b62\u56de\u586b</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>PG \u56de\u586b\u5df2\u66ab\u505c</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>\u7981\u6b62\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>PG \u5fa9\u539f\u5df2\u66ab\u505c</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>\u6309\u4f4d\u5143\u6392\u5e8f</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>\u4f7f\u7528\u6309\u4f4d\u5143\u6392\u5e8f</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>\u5df2\u6e05\u9664 Snapdir</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD \u5df2\u8f49\u63db snapset</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>\u5fa9\u539f\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>\u5728\u5fa9\u539f\u671f\u9593\uff0c\u800c\u975e\u5728\u5efa\u7acb\u4e92\u806f\u6642\u57f7\u884c\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>PG \u8a18\u9304\u786c\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>\u70ba pg \u8a18\u9304\u9577\u5ea6\u8a2d\u5b9a\u786c\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>\u5df2\u66f4\u65b0 OSD \u65d7\u6a19</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>out</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>in</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>down</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>\u6a19\u793a</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD \u907a\u5931</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>\u5df2\u6a19\u793a\u70ba\u907a\u5931</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>\u5df2\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>\u640d\u6bc0</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>\u5df2\u640d\u6bc0</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>PG</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>\u8b80\u53d6\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>\u5beb\u5165\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>\u8b80\u53d6\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>\u5beb\u5165\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\u5c07 OSD \u6a19\u793a\u70ba \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\u6a19\u793a\u70ba \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>\u6700\u5927\u56de\u586b\u6578</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>\u8655\u65bc\u4f7f\u7528\u4e2d\u72c0\u614b\u7684\u6700\u5927\u5fa9\u539f\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>\u55ae\u6b21\u555f\u52d5\u7684\u6700\u5927\u5fa9\u539f\u64cd\u4f5c\u6578</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>\u5fa9\u539f\u64cd\u4f5c\u9593\u9694\u7761\u7720\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>\u81ea\u8a02</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0 OSD \u5fa9\u539f\u901f\u5ea6\u512a\u5148\u7a0b\u5ea6\u300c\n <x id="INTERPOLATION" equiv-text="{{value}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\u4ee5\u4e0b OSD \u5df2\u555f\u59cb\u5316\n <x id="INTERPOLATION" equiv-text="{{operation}}"/>\u64cd\u4f5c\ufe30\n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>\u5de5\u4f5c</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>\u56b4\u91cd\u6027</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>\u5df2\u555f\u52d5</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>\u5df2\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>\u5df2\u4f7f\u7528</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>\u53ef\u7528</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>\u4e7e\u6de8</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>\u5de5\u4f5c\u4e2d</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>\u8b66\u544a</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>\u672a\u77e5</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>\u555f\u7528\u4e2d</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>\u7121\u6a94\u6848\u7cfb\u7d71</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>\u4f7f\u7528\u4e2d</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>\u5f85\u547d</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>\u7121</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>\u4f7f\u7528\u4e2d\u7684\u7cbe\u9748</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>\u672a\u8a2d\u5b9a NFS Ganesha \u670d\u52d9\u3002</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>\u50b3\u8f38</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS \u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>CephFS \u6a94\u6848\u7cfb\u7d71</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(\u7e7c\u627f\u81ea\u5168\u57df\u7d44\u614b)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>\u7e7c\u627f\u81ea\u5168\u57df\u7d44\u614b</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- \u9078\u53d6\u57f7\u884c\u54ea\u7a2e\u985e\u578b\u7684\u4f7f\u7528\u8005 ID \u533f\u540d\u5b58\u53d6 --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u7cbe\u9748\u3002</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>\u5feb\u53d6\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>\u9010\u51fa\u524d\u81f3\u5c11\u53ef\u7559\u5b58\u7684\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>\u885d\u6d17\u524d\u81f3\u5c11\u53ef\u7559\u5b58\u7684\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>\u76ee\u6a19\u6700\u5927\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>\u76ee\u6a19\u6700\u5927\u7269\u4ef6\u6578</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>\u672a\u65b0\u589e\u61c9\u7528\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>\u5df2\u9054\u5230\u61c9\u7528\u7a0b\u5f0f\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>\u4e00\u500b\u6c60\u6700\u591a\u53ea\u80fd\u56db\u500b\u61c9\u7528\u7a0b\u5f0f\u5b9a\u7fa9\u3002</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>\u5141\u8a31\u7684\u5b57\u5143\u70ba\u300c_a-zA-Z0-9\u300d</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>\u6700\u5927\u9577\u5ea6\u70ba 128 \u500b\u5b57\u5143</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>\u904e\u6ffe\u6216\u65b0\u589e\u61c9\u7528\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>\u65b0\u589e\u61c9\u7528\u7a0b\u5f0f</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>\u8907\u672c\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\u4e0a\u6b21\u8b8a\u66f4\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>CRUSH \u898f\u5247\u96c6</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>\u5beb\u5165\u4f4d\u5143\u7d44\u6578</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>\u6876</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u7269\u4ef6\u9598\u9053\u6876\u300c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u5df2\u5efa\u7acb\u7269\u4ef6\u9598\u9053\u6876\u300c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>\u6876</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u7269\u4ef6\u9598\u9053\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u5df2\u5efa\u7acb\u7269\u4ef6\u9598\u9053\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>\u7bc4\u570d</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>\u8b80\u53d6</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>\u5efa\u7acb</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5df2\u5efa\u7acb\u89d2\u8272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5df2\u66f4\u65b0\u89d2\u8272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>\u7cfb\u7d71\u89d2\u8272</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5df2\u522a\u9664\u89d2\u8272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u5efa\u7acb\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>\u66f4\u65b0\u4f7f\u7528\u8005</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>\u7e7c\u7e8c</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>\u60a8\u5df2\u88ab\u81ea\u52d5\u767b\u51fa\uff0c\u56e0\u70ba\u60a8\u7684\u89d2\u8272\u767c\u751f\u4e86\u8b8a\u66f4\u3002</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u522a\u9664\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u7121\u6cd5\u522a\u9664\u4f7f\u7528\u8005\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>\u60a8\u76ee\u524d\u6b63\u4ee5\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u8eab\u5206\u767b\u5165\u3002\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>\u5404\u7269\u4ef6\u90fd\u88ab\u5206\u5272\u6210\u8cc7\u6599\u5340\u584a\u90e8\u5206\uff0c\u5206\u5225\u5132\u5b58\u65bc\u4e0d\u540c\u7684 OSD\u3002</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>\u904b\u7b97\u5404\u7269\u4ef6\u7684\u7de8\u78bc\u5340\u584a\u5e76\u5c07\u5b83\u5011\u5132\u5b58\u5230\u4e0d\u540c\u7684 OSD\u3002\n \u7de8\u78bc\u5340\u584a\u7684\u6578\u91cf\u7b49\u540c\u65bc\u5728\u4e0d\u907a\u5931\u8cc7\u6599\u7684\u524d\u63d0\u4e0b\uff0c\u53ef\u505c\u6a5f\u7684 OSD \u6578\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Jerasure \u5916\u639b\u7a0b\u5f0f\u662f\u6700\u4e00\u822c\u3001\u6700\u9748\u6d3b\u7684\u5916\u639b\u7a0b\u5f0f\uff0c\n \u4e5f\u662f Ceph \u7cfe\u522a\u78bc\u6c60\u7684\u9810\u8a2d\u5916\u639b\u7a0b\u5f0f\u3002</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>Reed_sol_van \u65b9\u6cd5\u66f4\u9748\u6d3b\ufe30\u5b83\u8db3\u4ee5\u8a2d\u5b9a k\n \u548c m\u3002Cauchy_good \u65b9\u6cd5\u66f4\u5feb\uff0c\u4f46\u60a8\u9700\u8981\u5c0f\u5fc3\u9078\u53d6\u5c01\u5305\u5927\u5c0f\u3002\n \u6240\u6709 reed_sol_r6_op\u3001liberation\u3001blaum_roth\u3001liber8tion \u90fd\n \u7b49\u540c\u65bc RAID6\uff0c\u5b83\u5011\u53ea\u80fd\u8a2d\u5b9a\u70ba m=2\u3002</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>\u5c07\u4ee5\u4f4d\u5143\u7d44\u5927\u5c0f\u7684\u5c01\u5305\u70ba\u55ae\u4f4d\u9032\u884c\u7de8\u78bc\u3002\n \u9078\u53d6\u5408\u9069\u7684\u5c01\u5305\u5927\u5c0f\u5f88\u96e3\u3002\n Jerasure \u6587\u4ef6\u5305\u542b\u6709\u95dc\u6b64\u4e3b\u984c\u7684\u8a73\u7d30\u8cc7\u8a0a\u3002</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>\u4f7f\u7528 jerasure \u5916\u639b\u7a0b\u5f0f\u6642\uff0c\u82e5\u7cfe\u522a\u78bc\u7269\u4ef6\u5132\u5b58\u65bc\n \u591a\u500b OSD \u4e0a\uff0c\u5247\u5fa9\u539f\u4e00\u500b\u907a\u5931\u7684 OSD \u6642\u9700\u8981\u8b80\u53d6\u6240\u6709\u5176\u4ed6 OSD\u3002\n \u4f8b\u5982\uff0c\u82e5 jerasure \u8a2d\u5b9a\u70ba k=8 \u4e14 m=4\uff0c\u5247\u907a\u5931\u4e00\u500b OSD \u5f8c\u9700\u8b80\u53d6\n \u5176\u4ed6\u5341\u4e00\u500b OSD \u624d\u80fd\u4fee\u5fa9\u3002\n\n lrc \u7cfe\u522a\u78bc\u5916\u639b\u7a0b\u5f0f\u6703\u5efa\u7acb\u672c\u5730\u540c\u4f4d\u5340\u584a\uff0c\u56e0\u6b64\u53ea\u9700\u8f03\u5c11\u7684 OSD \u5373\n \u53ef\u5fa9\u539f\u3002\u4f8b\u5982\uff0c\u82e5 lrc \u8a2d\u5b9a\u70ba k=8\u3001m=4 \u4e14 l=4\uff0c\u5b83\u5c07\u70ba\u6bcf\u56db\u500b OSD\n \u5efa\u7acb\u984d\u5916\u7684\u540c\u4f4d\u5340\u584a\u3002\u9019\u6a23\uff0c\u7576\u4e00\u500b OSD \u907a\u5931\u6642\uff0c\u5b83\u53ea\u9700\u56db\u500b OSD\n \u5373\u53ef\u5fa9\u539f\uff0c\u800c\u4e0d\u9700\u8981\u5341\u4e00\u500b\u3002</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>\u5c07\u7de8\u78bc\u5340\u584a\u548c\u8cc7\u6599\u5340\u584a\u5206\u7d44\u70ba\u5927\u5c0f\u70ba locality \u7684\u96c6\u5408\u3002\u4f8b\u5982\uff0c\n k=4 \u4e14 m=2 \u6642\uff0c\u82e5 locality=3\uff0c\u5247\u6703\u5efa\u7acb 2 \u500b\u5927\u5c0f\u70ba 3 \u7684\u7d44\u3002\u9019\u6a23\uff0c\u5404\u7d44\u90fd\u80fd\n \u81ea\u884c\u5fa9\u539f\uff0c\u800c\u7121\u9700\u5f9e\u53e6\u4e00\u7d44\u8b80\u53d6\u5340\u584a\u3002</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>\u7531 l \u5b9a\u7fa9\u7684\u5340\u584a\u96c6\u5c07\u6309\u54ea\u7a2e CRUSH \u6876\u985e\u578b\u5132\u5b58\u3002\n \u4f8b\u5982\uff0c\u82e5\u8a2d\u5b9a\u70ba\u6a5f\u67b6\uff0c\u5247\u5404\u7d44 l \u5340\u584a\u5c07\u6703\u88ab\u653e\u7f6e\u5230\u4e0d\u540c\u7684\n \u6a5f\u67b6\u4e2d\u3002\u8a72\u503c\u7528\u65bc\u5efa\u7acb\u985e\u4f3c step choose rack \u7684 CRUSH\n \u898f\u5247\u6b65\u9a5f\u3002\u82e5\u672a\u8a2d\u5b9a\uff0c\u5247\u4e0d\u6703\u9032\u884c\u6b64\u985e\u5206\u7d44\u3002</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>isa \u5916\u639b\u7a0b\u5f0f\u5c01\u5305\u4e86 ISA \u7a0b\u5f0f\u5eab\u3002\u5b83\u53ea\u80fd\u5728 Intel \u8655\u7406\u5668\u4e0a\u57f7\u884c\u3002</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>ISA \u5916\u639b\u7a0b\u5f0f\u5305\u542b\u5169\u7a2e Reed Solomon \u683c\u5f0f\u3002\n \u82e5\u8a2d\u5b9a\u70ba reed_sol_van\uff0c\u5247\u70ba Vandermonde\u3002\u82e5\u8a2d\u5b9a\u70ba cauchy\uff0c\u5247\u70ba Cauchy\u3002</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>shec \u5916\u639b\u7a0b\u5f0f\u5c01\u5305\u4e86\u591a\u500b SHEC \u7a0b\u5f0f\u5eab\u3002\n \u8207 Reed Solomon \u4ee3\u78bc\u76f8\u6bd4\uff0c\u5b83\u80fd\u66f4\u6709\u6548\u5730\u5fa9\u539f\u8cc7\u6599\u3002</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>\u540c\u4f4d\u5340\u584a\u7684\u6578\u91cf\uff0c\u5b83\u5011\u5728\u5404\u81ea\u7684\u8a08\u7b97\u7bc4\u570d\u5167\u5305\u542b\u4e86\n \u5404\u8cc7\u6599\u5340\u584a\u3002\u8a72\u6578\u503c\u88ab\u7528\u505a\u6301\u4e45\u6027\u4f30\u503c\u3002\u4f8b\u5982\uff0c\u82e5 c=2\uff0c\n \u5247\u5728\u4e0d\u907a\u5931\u8cc7\u6599\u7684\u524d\u63d0\u4e0b\uff0c\u53ef\u6709 2 \u500b OSD \u505c\u6a5f\u3002</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>CRUSH \u898f\u5247\u7684\u7b2c\u4e00\u6b65\u6240\u6307\u5411\u7684 CRUSH \u6876\u540d\u7a31\u3002\n \u4f8b\u5982 step take default\u3002</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>\u78ba\u5b9a\u5169\u500b\u5340\u584a\u4e0d\u6703\u5b58\u5728\u65bc\u540c\u4e00\u6545\u969c\u7db2\u57df\u7684\u6876\u4e2d\u3002\n \u4f8b\u5982\uff0c\u82e5\u6545\u969c\u7db2\u57df\u70ba\u4e3b\u6a5f\uff0c\u5247\u4e0d\u6703\u6709\u5169\u500b\u5340\u584a\u5132\u5b58\u65bc\u540c\u4e00\u4e3b\u6a5f\u4e2d\u3002\n \u8a72\u503c\u7528\u65bc\u5efa\u7acb\u985e\u4f3c step chooseleaf host \u7684 CRUSH \u898f\u5247\u6b65\u9a5f\u3002</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>\u4f7f\u7528 CRUSH \u5730\u5716\u4e2d\u7684 crush \u88dd\u7f6e\u985e\u5225\u540d\u7a31\uff0c\n \u5c07\u653e\u7f6e\u9650\u5236\u65bc\u7279\u5b9a\u985e\u5225\u7684\u88dd\u7f6e (\u4f8b\u5982 ssd \u6216 hdd)\u3002</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>\u8a2d\u5b9a\u7cfe\u522a\u78bc\u5916\u639b\u7a0b\u5f0f\u6240\u5728\u76ee\u9304\u3002</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>\u5141\u8a31\u6240\u6709\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>\u50c5\u5141\u8a31\u4e0d\u4fee\u6539\u4f3a\u670d\u5668\u7684\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>\u4e0d\u5141\u8a31\u8b80\u53d6\u6216\u5beb\u5165\u64cd\u4f5c\uff0c\u4f46\u662f\u5141\u8a31\u4efb\u4f55\u5176\u4ed6\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>\u4e0d\u5141\u8a31\u8b80\u53d6\u3001\u5beb\u5165\u6216\u4efb\u4f55\u53ef\u80fd\u4fee\u6539\u6a94\u6848\u5c6c\u6027\u6216\u76ee\u9304\u5167\u5bb9\u7684\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>\u5b8c\u5168\u7981\u6b62\u5b58\u53d6</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- \u9078\u53d6\u512a\u5148\u7a0b\u5ea6 --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>\u4f4e</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>\u9ad8</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\u904e\u53bb 5 \u5206\u9418</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\u904e\u53bb 15 \u5206\u9418</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\u904e\u53bb 30 \u5206\u9418</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\u904e\u53bb 1 \u5c0f\u6642 (\u9810\u8a2d\u503c)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\u904e\u53bb 3 \u5c0f\u6642</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\u904e\u53bb 6 \u5c0f\u6642</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\u904e\u53bb 12 \u5c0f\u6642</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\u904e\u53bb 24 \u5c0f\u6642</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>\u6628\u5929</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>\u4eca\u5929</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>\u4eca\u5929\u5230\u76ee\u524d\u70ba\u6b62</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>\u524d\u5929</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>\u904e\u53bb 2 \u5929</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>\u4e0a\u9031\u7684\u4eca\u5929</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>\u4e0a\u9031</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>\u672c\u9031</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>\u672c\u9031\u76ee\u524d\u70ba\u6b62</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>\u904e\u53bb 7 \u5929</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>\u4e0a\u500b\u6708</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>\u672c\u6708</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>\u672c\u6708\u76ee\u524d\u70ba\u6b62</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>\u904e\u53bb 30 \u5929</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>\u904e\u53bb 90 \u5929</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>\u904e\u53bb 6 \u500b\u6708</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>\u904e\u53bb 1 \u5e74</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>\u53bb\u5e74</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>\u4eca\u5e74</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>\u4eca\u5e74\u76ee\u524d\u70ba\u6b62</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>\u904e\u53bb 2 \u5e74</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>\u904e\u53bb 5 \u5e74</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>\u8cc7\u8a0a</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>\u672a\u9078\u53d6\u9805\u76ee\u3002</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>\u53d6\u6d88\u9078\u53d6\u9805\u76ee\u4ee5\u518d\u6b21\u9078\u53d6</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>\u5df2\u9054\u5230\u9078\u53d6\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>\u904e\u6ffe\u6a19\u8a18</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>\u65b0\u589e\u5fbd\u7ae0</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>\u6c92\u6709\u53ef\u7528\u7684\u9805\u76ee\u3002</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>\u65b0\u589e</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>\u6df1\u5c64\u6574\u7406</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>\u640d\u6bc0</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>\u58d3\u5e73</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>\u6a19\u793a\u70ba Down</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>\u6a19\u793a\u70ba In</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>\u6a19\u793a\u70ba\u907a\u5931</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>\u6a19\u793a\u70ba Out</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>\u91cd\u65b0\u547d\u540d</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>\u9084\u539f</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>\u79fb\u81f3\u5783\u573e\u6876</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>\u53d6\u6d88\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>\u5df2\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>\u5df2\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>\u5df2\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>\u662f</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>\u5426</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>\u670d\u52d9\u54c1\u8cea</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2 IO \u4f4d\u5143\u7d44\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2 IO \u64cd\u4f5c\u6b21\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>\u8b80\u53d6 BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5167\u8b80\u53d6\u7684\u4f4d\u5143\u7d44\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>\u8b80\u53d6 IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u8b80\u53d6\u64cd\u4f5c\u6b21\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>\u5beb\u5165 BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5167\u5beb\u5165\u7684\u4f4d\u5143\u7d44\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>\u5beb\u5165 IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5beb\u5165\u64cd\u4f5c\u6b21\u6578\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>\u6307\u5b9a\u7684 IO \u4f4d\u5143\u7d44\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>\u6307\u5b9a\u7684 IO \u64cd\u4f5c\u6b21\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>\u8b80\u53d6 BPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>\u6307\u5b9a\u7684\u8b80\u53d6\u7684\u4f4d\u5143\u7d44\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>\u8b80\u53d6 IOPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>\u6307\u5b9a\u7684\u8b80\u53d6\u64cd\u4f5c\u6b21\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>\u5beb\u5165 BPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>\u6307\u5b9a\u7684\u5beb\u5165\u7684\u4f4d\u5143\u7d44\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>\u5beb\u5165 IOPS \u9ad8\u8f09</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>\u6307\u5b9a\u7684\u5beb\u5165\u64cd\u4f5c\u6b21\u6578\u9ad8\u8f09\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>\u7121\u6cd5\n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>\u6b63\u5728\u57f7\u884c</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>\u57f7\u884c</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>\u5df2\u57f7\u884c</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>\u672a\u77e5\u4efb\u52d9</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>\u6b63\u5728\u5efa\u7acb</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>\u5efa\u7acb</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>\u6b63\u5728\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>\u6b63\u5728\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>\u522a\u9664</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \u5feb\u7167\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u6c60\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u7684\u93e1\u50cf\u6a21\u5f0f\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u6c60\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u7684\u93e1\u50cf\u5c0d\u7b49\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>\u540d\u7a31\u5df2\u88ab \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> \u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>\u540d\u7a31\u5df2\u88ab \n <x id="INTERPOLATION" equiv-text="{{name}}"/> \u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>\u540d\u7a31\u5df2\u88ab \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> \u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> \u5305\u542b\u5feb\u7167\u3002\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>\u6b63\u5728\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>\u5fc5\u9808\u4fdd\u8b77 \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> \u7684\u5feb\u7167\u3002\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>\u6b63\u5728\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>\u6b63\u5728\u58d3\u5e73</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>\u58d3\u5e73</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>\u5df2\u58d3\u5e73</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>\u540d\u7a31\u5df2\u88ab \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> \u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>\u7121\u6cd5\u4fdd\u8b77 \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\uff0c\u56e0\u70ba\u5176\u5305\u542b\u5b50\u5f71\u50cf\u3002\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>\u7121\u6cd5\u522a\u9664 \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\uff0c\u56e0\u70ba\u5176\u8655\u65bc\u4fdd\u8b77\u72c0\u614b\u3002\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>\u6b63\u5728\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>\u5df2\u5fa9\u539f</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>\u6b63\u5728\u79fb\u52d5</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>\u79fb\u52d5</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>\u5df2\u79fb\u52d5</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>\u5f71\u50cf\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u5230\u5783\u573e\u6876\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>\u627e\u4e0d\u5230\u5f71\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>\u6b63\u5728\u9084\u539f</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>\u9084\u539f</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>\u5df2\u9084\u539f</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>\u5f71\u50cf\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d(\u5230\u300c\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\u300d)\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>\u5f71\u50cf\u540d\u7a31\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u5df2\u5728\u4f7f\u7528\u4e2d\u3002\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u5f71\u50cf\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>\u6b63\u5728\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>\u5df2\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>\u6240\u6709\u6c60</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>\u5f71\u50cf (\u5f9e \n <x id="INTERPOLATION" equiv-text="{{message}}"/>)\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>\u7121\u6cd5\u505c\u7528\u93e1\u50cf\uff0c\u56e0\u70ba\u5176\u5305\u542b\u5c0d\u7b49\u3002</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>\u6c60\u300c\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>\u7cfe\u522a\u78bc\u8a2d\u5b9a\u6a94\u300c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>\u76ee\u6a19\u300c\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},Dzi0:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"LT [ngayong araw]",nextDay:"[Bukas ng] LT",nextWeek:"LT [sa susunod na] dddd",lastDay:"LT [kahapon]",lastWeek:"LT [noong nakaraang] dddd",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",ss:"%d segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(t){return t},week:{dow:1,doy:4}})}()},"E+lV":function(t,e,n){!function(t){"use strict";var e={words:{ss:["\u0441\u0435\u043a\u0443\u043d\u0434\u0430","\u0441\u0435\u043a\u0443\u043d\u0434\u0435","\u0441\u0435\u043a\u0443\u043d\u0434\u0438"],m:["\u0458\u0435\u0434\u0430\u043d \u043c\u0438\u043d\u0443\u0442","\u0458\u0435\u0434\u043d\u0435 \u043c\u0438\u043d\u0443\u0442\u0435"],mm:["\u043c\u0438\u043d\u0443\u0442","\u043c\u0438\u043d\u0443\u0442\u0435","\u043c\u0438\u043d\u0443\u0442\u0430"],h:["\u0458\u0435\u0434\u0430\u043d \u0441\u0430\u0442","\u0458\u0435\u0434\u043d\u043e\u0433 \u0441\u0430\u0442\u0430"],hh:["\u0441\u0430\u0442","\u0441\u0430\u0442\u0430","\u0441\u0430\u0442\u0438"],dd:["\u0434\u0430\u043d","\u0434\u0430\u043d\u0430","\u0434\u0430\u043d\u0430"],MM:["\u043c\u0435\u0441\u0435\u0446","\u043c\u0435\u0441\u0435\u0446\u0430","\u043c\u0435\u0441\u0435\u0446\u0438"],yy:["\u0433\u043e\u0434\u0438\u043d\u0430","\u0433\u043e\u0434\u0438\u043d\u0435","\u0433\u043e\u0434\u0438\u043d\u0430"]},correctGrammaticalCase:function(t,e){return 1===t?e[0]:t>=2&&t<=4?e[1]:e[2]},translate:function(t,n,a){var r=e.words[a];return 1===a.length?n?r[0]:r[1]:t+" "+e.correctGrammaticalCase(t,r)}};t.defineLocale("sr-cyrl",{months:"\u0458\u0430\u043d\u0443\u0430\u0440_\u0444\u0435\u0431\u0440\u0443\u0430\u0440_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0438\u043b_\u043c\u0430\u0458_\u0458\u0443\u043d_\u0458\u0443\u043b_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440_\u043e\u043a\u0442\u043e\u0431\u0430\u0440_\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440_\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440".split("_"),monthsShort:"\u0458\u0430\u043d._\u0444\u0435\u0431._\u043c\u0430\u0440._\u0430\u043f\u0440._\u043c\u0430\u0458_\u0458\u0443\u043d_\u0458\u0443\u043b_\u0430\u0432\u0433._\u0441\u0435\u043f._\u043e\u043a\u0442._\u043d\u043e\u0432._\u0434\u0435\u0446.".split("_"),monthsParseExact:!0,weekdays:"\u043d\u0435\u0434\u0435\u0459\u0430_\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a_\u0443\u0442\u043e\u0440\u0430\u043a_\u0441\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a_\u043f\u0435\u0442\u0430\u043a_\u0441\u0443\u0431\u043e\u0442\u0430".split("_"),weekdaysShort:"\u043d\u0435\u0434._\u043f\u043e\u043d._\u0443\u0442\u043e._\u0441\u0440\u0435._\u0447\u0435\u0442._\u043f\u0435\u0442._\u0441\u0443\u0431.".split("_"),weekdaysMin:"\u043d\u0435_\u043f\u043e_\u0443\u0442_\u0441\u0440_\u0447\u0435_\u043f\u0435_\u0441\u0443".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[\u0434\u0430\u043d\u0430\u0441 \u0443] LT",nextDay:"[\u0441\u0443\u0442\u0440\u0430 \u0443] LT",nextWeek:function(){switch(this.day()){case 0:return"[\u0443] [\u043d\u0435\u0434\u0435\u0459\u0443] [\u0443] LT";case 3:return"[\u0443] [\u0441\u0440\u0435\u0434\u0443] [\u0443] LT";case 6:return"[\u0443] [\u0441\u0443\u0431\u043e\u0442\u0443] [\u0443] LT";case 1:case 2:case 4:case 5:return"[\u0443] dddd [\u0443] LT"}},lastDay:"[\u0458\u0443\u0447\u0435 \u0443] LT",lastWeek:function(){return["[\u043f\u0440\u043e\u0448\u043b\u0435] [\u043d\u0435\u0434\u0435\u0459\u0435] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u043e\u0433] [\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u043a\u0430] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u043e\u0433] [\u0443\u0442\u043e\u0440\u043a\u0430] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u0435] [\u0441\u0440\u0435\u0434\u0435] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u043e\u0433] [\u0447\u0435\u0442\u0432\u0440\u0442\u043a\u0430] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u043e\u0433] [\u043f\u0435\u0442\u043a\u0430] [\u0443] LT","[\u043f\u0440\u043e\u0448\u043b\u0435] [\u0441\u0443\u0431\u043e\u0442\u0435] [\u0443] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"\u0437\u0430 %s",past:"\u043f\u0440\u0435 %s",s:"\u043d\u0435\u043a\u043e\u043b\u0438\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434\u0438",ss:e.translate,m:e.translate,mm:e.translate,h:e.translate,hh:e.translate,d:"\u0434\u0430\u043d",dd:e.translate,M:"\u043c\u0435\u0441\u0435\u0446",MM:e.translate,y:"\u0433\u043e\u0434\u0438\u043d\u0443",yy:e.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(n("wd/R"))},E2fk:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){return"[INF]"===t?"info":"[WRN]"===t?"warn":"[ERR]"===t?"err":""},t}()},EEJc:function(t,e,n){"use strict";var a=n("CcnG"),r=n("ajRT");n.d(e,"b",function(){return i}),n.d(e,"c",function(){return s}),n.d(e,"a",function(){return u});var i=a["\u0275crt"]({encapsulation:0,styles:[[".modal-header[_ngcontent-%COMP%]{border-bottom:1px solid #d1d1d1;background-color:#f5f5f5;border-radius:5px 5px 0 0} .modal-footer{border-bottom:1px solid #d1d1d1;background-color:#f5f5f5;border-radius:0 0 5px 5px} .modal-body{max-height:70vh;overflow-y:auto;overflow-x:hidden}"]],data:{}});function s(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"div",[["class","modal-header"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),a["\u0275ncd"](null,0),(t()(),a["\u0275eld"](3,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.close()&&a),a},null,null)),(t()(),a["\u0275eld"](4,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["\xd7"])),a["\u0275ncd"](null,1)],null,null)}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"cd-modal",[],null,null,null,s,i)),a["\u0275did"](1,49152,null,0,r.a,[],null,null)],null,null)}var u=a["\u0275ccf"]("cd-modal",r.a,o,{modalRef:"modalRef"},{hide:"hide"},[".modal-title",".modal-content"])},EOgW:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("th",{months:"\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21_\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c_\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21_\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19_\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21_\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19_\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21_\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21_\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19_\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21_\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19_\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21".split("_"),monthsShort:"\u0e21.\u0e04._\u0e01.\u0e1e._\u0e21\u0e35.\u0e04._\u0e40\u0e21.\u0e22._\u0e1e.\u0e04._\u0e21\u0e34.\u0e22._\u0e01.\u0e04._\u0e2a.\u0e04._\u0e01.\u0e22._\u0e15.\u0e04._\u0e1e.\u0e22._\u0e18.\u0e04.".split("_"),monthsParseExact:!0,weekdays:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysShort:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysMin:"\u0e2d\u0e32._\u0e08._\u0e2d._\u0e1e._\u0e1e\u0e24._\u0e28._\u0e2a.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 H:mm",LLLL:"\u0e27\u0e31\u0e19dddd\u0e17\u0e35\u0e48 D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 H:mm"},meridiemParse:/\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07|\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07/,isPM:function(t){return"\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"===t},meridiem:function(t,e,n){return t<12?"\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07":"\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"},calendar:{sameDay:"[\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextDay:"[\u0e1e\u0e23\u0e38\u0e48\u0e07\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextWeek:"dddd[\u0e2b\u0e19\u0e49\u0e32 \u0e40\u0e27\u0e25\u0e32] LT",lastDay:"[\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e27\u0e32\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",lastWeek:"[\u0e27\u0e31\u0e19]dddd[\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27 \u0e40\u0e27\u0e25\u0e32] LT",sameElse:"L"},relativeTime:{future:"\u0e2d\u0e35\u0e01 %s",past:"%s\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27",s:"\u0e44\u0e21\u0e48\u0e01\u0e35\u0e48\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35",ss:"%d \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35",m:"1 \u0e19\u0e32\u0e17\u0e35",mm:"%d \u0e19\u0e32\u0e17\u0e35",h:"1 \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",hh:"%d \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",d:"1 \u0e27\u0e31\u0e19",dd:"%d \u0e27\u0e31\u0e19",M:"1 \u0e40\u0e14\u0e37\u0e2d\u0e19",MM:"%d \u0e40\u0e14\u0e37\u0e2d\u0e19",y:"1 \u0e1b\u0e35",yy:"%d \u0e1b\u0e35"}})}()},ES0t:function(t,e,n){"use strict";n.d(e,"a",function(){return l});var a=n("CcnG"),r=n("OZfm"),i=n("Ip0R"),s=a["\u0275crt"]({encapsulation:0,styles:[".bs3.popover-top[_nghost-%COMP%] {\n margin-bottom: 10px;\n }\n .bs3.popover.top[_nghost-%COMP%] > .arrow[_ngcontent-%COMP%] {\n margin-left: -2px;\n }\n .bs3.popover.top[_nghost-%COMP%] {\n margin-bottom: 10px;\n }\n .popover.bottom[_nghost-%COMP%] > .arrow[_ngcontent-%COMP%] {\n margin-left: -4px;\n }\n .bs3.bs-popover-left[_nghost-%COMP%] {\n margin-right: .5rem;\n }\n .bs3.bs-popover-right[_nghost-%COMP%] .arrow[_ngcontent-%COMP%], .bs3.bs-popover-left[_nghost-%COMP%] .arrow[_ngcontent-%COMP%]{\n margin: .3rem 0;\n }"],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"h3",[["class","popover-title popover-header"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.component.title)})}function u(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,0,"div",[["class","popover-arrow arrow"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,o)),a["\u0275did"](2,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](3,0,null,null,1,"div",[["class","popover-content popover-body"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],function(t,e){t(e,2,0,e.component.title)},null)}function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"popover-container",[["role","tooltip"],["style","display:block;"]],[[8,"className",0],[2,"show",null],[2,"bs3",null]],null,null,u,s)),a["\u0275did"](1,49152,null,0,r.b,[r.a],null,null)],null,function(t,e){t(e,0,0,"popover in popover-"+a["\u0275nov"](e,1).placement+" bs-popover-"+a["\u0275nov"](e,1).placement+" "+a["\u0275nov"](e,1).placement+" "+a["\u0275nov"](e,1).containerClass,!a["\u0275nov"](e,1).isBs3,a["\u0275nov"](e,1).isBs3)})}var l=a["\u0275ccf"]("popover-container",r.b,c,{placement:"placement",title:"title"},{},["*"])},EgGo:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("Ip0R"),r=n("sne2"),i=function(){function t(t){this.base=t}return t.concatURLSegments=function(t){return t.reduce(a.Location.joinWithSlash)},t.buildURL=function(e){for(var n=[],a=1;a<arguments.length;a++)n[a-1]=arguments[a];return t.concatURLSegments((e?["/"]:[]).concat(n))},t.prototype.getURL=function(e,n){void 0===n&&(n=!0);for(var a=[],r=2;r<arguments.length;r++)a[r-2]=arguments[r];return t.buildURL.apply(t,[n,this.base,e].concat(a))},t.prototype.getCreate=function(t){return void 0===t&&(t=!0),this.getURL(r.e.CREATE,t)},t.prototype.getCreateFrom=function(t,e){return void 0===e&&(e=!0),this.getURL(r.e.CREATE,e,t)},t.prototype.getDelete=function(t){return void 0===t&&(t=!0),this.getURL(r.e.DELETE,t)},t.prototype.getEdit=function(t,e){return void 0===e&&(e=!0),this.getURL(r.e.EDIT,e,t)},t.prototype.getUpdate=function(t,e){return void 0===e&&(e=!0),this.getURL(r.e.UPDATE,e,t)},t.prototype.getAdd=function(t){return void 0===t&&(t=!0),this.getURL(r.e.ADD,t)},t.prototype.getRemove=function(t){return void 0===t&&(t=!0),this.getURL(r.e.REMOVE,t)},t.prototype.getRecreate=function(t,e){return void 0===e&&(e=!0),this.getURL(r.e.RECREATE,e,t)},t}()},"En8+":function(t,e,n){"use strict";function a(){return"function"==typeof Symbol&&Symbol.iterator?Symbol.iterator:"@@iterator"}n.d(e,"a",function(){return r});var r=a()},"F/XL":function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("nkY7"),r=n("IUTb"),i=n("JF+6");function s(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t[t.length-1];return Object(a.a)(n)?(t.pop(),Object(i.a)(t,n)):Object(r.a)(t)}},F8xH:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG"),i=n("Ip0R"),s=n("Nia1"),o=n("mn2k"),u=n("bpWZ");e.NgxDatatableModule=function(){return a([r.NgModule({imports:[i.CommonModule],providers:[u.ScrollbarHelper,u.DimensionsHelper,u.ColumnChangesService],declarations:[s.DataTableFooterTemplateDirective,o.VisibilityDirective,o.DraggableDirective,o.ResizeableDirective,o.OrderableDirective,o.LongPressDirective,s.ScrollerComponent,s.DatatableComponent,s.DataTableColumnDirective,s.DataTableHeaderComponent,s.DataTableHeaderCellComponent,s.DataTableBodyComponent,s.DataTableFooterComponent,s.DataTablePagerComponent,s.ProgressBarComponent,s.DataTableBodyRowComponent,s.DataTableRowWrapperComponent,s.DatatableRowDetailDirective,s.DatatableGroupHeaderDirective,s.DatatableRowDetailTemplateDirective,s.DataTableBodyCellComponent,s.DataTableSelectionComponent,s.DataTableColumnHeaderDirective,s.DataTableColumnCellDirective,s.DataTableColumnCellTreeToggle,s.DatatableFooterDirective,s.DatatableGroupHeaderTemplateDirective,s.DataTableSummaryRowComponent],exports:[s.DatatableComponent,s.DatatableRowDetailDirective,s.DatatableGroupHeaderDirective,s.DatatableRowDetailTemplateDirective,s.DataTableColumnDirective,s.DataTableColumnHeaderDirective,s.DataTableColumnCellDirective,s.DataTableColumnCellTreeToggle,s.DataTableFooterTemplateDirective,s.DatatableFooterDirective,s.DataTablePagerComponent,s.DatatableGroupHeaderTemplateDirective]})],function(){})}()},FBEI:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n("O5R2"),n("lZOh"),n("tKjC"),e.noop=function(){}},FFOo:function(t,e,n){"use strict";n.d(e,"a",function(){return l});var a=n("mrSG"),r=n("2Bdj"),i=n("6ahw"),s=n("pugT"),o=n("L/V9"),u=n("iLxQ"),c=n("DKTb"),l=function(t){function e(n,a,r){var s=t.call(this)||this;switch(s.syncErrorValue=null,s.syncErrorThrown=!1,s.syncErrorThrowable=!1,s.isStopped=!1,arguments.length){case 0:s.destination=i.a;break;case 1:if(!n){s.destination=i.a;break}if("object"==typeof n){n instanceof e?(s.syncErrorThrowable=n.syncErrorThrowable,s.destination=n,n.add(s)):(s.syncErrorThrowable=!0,s.destination=new d(s,n));break}default:s.syncErrorThrowable=!0,s.destination=new d(s,n,a,r)}return s}return a.__extends(e,t),e.prototype[o.a]=function(){return this},e.create=function(t,n,a){var r=new e(t,n,a);return r.syncErrorThrowable=!1,r},e.prototype.next=function(t){this.isStopped||this._next(t)},e.prototype.error=function(t){this.isStopped||(this.isStopped=!0,this._error(t))},e.prototype.complete=function(){this.isStopped||(this.isStopped=!0,this._complete())},e.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,t.prototype.unsubscribe.call(this))},e.prototype._next=function(t){this.destination.next(t)},e.prototype._error=function(t){this.destination.error(t),this.unsubscribe()},e.prototype._complete=function(){this.destination.complete(),this.unsubscribe()},e.prototype._unsubscribeAndRecycle=function(){var t=this._parentOrParents;return this._parentOrParents=null,this.unsubscribe(),this.closed=!1,this.isStopped=!1,this._parentOrParents=t,this},e}(s.a),d=function(t){function e(e,n,a,s){var o,u=t.call(this)||this;u._parentSubscriber=e;var c=u;return Object(r.a)(n)?o=n:n&&(o=n.next,a=n.error,s=n.complete,n!==i.a&&(c=Object.create(n),Object(r.a)(c.unsubscribe)&&u.add(c.unsubscribe.bind(c)),c.unsubscribe=u.unsubscribe.bind(u))),u._context=c,u._next=o,u._error=a,u._complete=s,u}return a.__extends(e,t),e.prototype.next=function(t){if(!this.isStopped&&this._next){var e=this._parentSubscriber;u.a.useDeprecatedSynchronousErrorHandling&&e.syncErrorThrowable?this.__tryOrSetError(e,this._next,t)&&this.unsubscribe():this.__tryOrUnsub(this._next,t)}},e.prototype.error=function(t){if(!this.isStopped){var e=this._parentSubscriber,n=u.a.useDeprecatedSynchronousErrorHandling;if(this._error)n&&e.syncErrorThrowable?(this.__tryOrSetError(e,this._error,t),this.unsubscribe()):(this.__tryOrUnsub(this._error,t),this.unsubscribe());else if(e.syncErrorThrowable)n?(e.syncErrorValue=t,e.syncErrorThrown=!0):Object(c.a)(t),this.unsubscribe();else{if(this.unsubscribe(),n)throw t;Object(c.a)(t)}}},e.prototype.complete=function(){var t=this;if(!this.isStopped){var e=this._parentSubscriber;if(this._complete){var n=function(){return t._complete.call(t._context)};u.a.useDeprecatedSynchronousErrorHandling&&e.syncErrorThrowable?(this.__tryOrSetError(e,n),this.unsubscribe()):(this.__tryOrUnsub(n),this.unsubscribe())}else this.unsubscribe()}},e.prototype.__tryOrUnsub=function(t,e){try{t.call(this._context,e)}catch(n){if(this.unsubscribe(),u.a.useDeprecatedSynchronousErrorHandling)throw n;Object(c.a)(n)}},e.prototype.__tryOrSetError=function(t,e,n){if(!u.a.useDeprecatedSynchronousErrorHandling)throw new Error("bad call");try{e.call(this._context,n)}catch(a){return u.a.useDeprecatedSynchronousErrorHandling?(t.syncErrorValue=a,t.syncErrorThrown=!0,!0):(Object(c.a)(a),!0)}return!1},e.prototype._unsubscribe=function(){var t=this._parentSubscriber;this._context=null,this._parentSubscriber=null,t.unsubscribe()},e}(l)},FLvf:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("tFKq")),a(n("0MID"))},FMPj:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("5tze");e.optionalGetterForProp=function(t){return t&&function(e){return a.getterForProp(t)(e,t)}},e.groupRowsByParents=function(t,e,n){if(e&&n){var a={},i=t.length,s=null;a[0]=new r;for(var o=t.reduce(function(t,e){var a=n(e);return-1===t.indexOf(a)&&t.push(a),t},[]),u=0;u<i;u++)a[n(t[u])]=new r(t[u]);for(u=0;u<i;u++){var c=0,l=e((s=a[n(t[u])]).row);l&&o.indexOf(l)>-1&&(c=l),s.parent=a[c],s.row.level=s.parent.row.level+1,s.parent.children.push(s)}var d=[];return a[0].flatten(function(){d=d.concat([this.row])},!0),d}return t};var r=function(){function t(t){void 0===t&&(t=null),t||(t={level:-1,treeStatus:"expanded"}),this.row=t,this.parent=null,this.children=[]}return t.prototype.flatten=function(t,e){if("expanded"===this.row.treeStatus)for(var n=0,a=this.children.length;n<a;n++){var r=this.children[n];t.apply(r,Array.prototype.slice.call(arguments,2)),e&&r.flatten.apply(r,arguments)}},t}()},"FO+L":function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");n("ZYjt"),e.ScrollbarHelper=function(){function t(t){this.document=t,this.width=this.getWidth()}return t.prototype.getWidth=function(){var t=this.document.createElement("div");t.style.visibility="hidden",t.style.width="100px",t.style.msOverflowStyle="scrollbar",this.document.body.appendChild(t);var e=t.offsetWidth;t.style.overflow="scroll";var n=this.document.createElement("div");n.style.width="100%",t.appendChild(n);var a=n.offsetWidth;return t.parentNode.removeChild(t),e-a},a([r.Injectable()],t)}()},FSuO:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("LvDl"),i=n("x38r"),s=(n("a0VL"),n("uIqm"),function(){function t(t){this.datePipe=t,this.autoReload=5e3,this.renderObjects=!1,this.appendParentKey=!0,this.hideEmpty=!1,this.hideKeys=[],this.columns=[],this.fetchData=new a.EventEmitter}return t.prototype.ngOnInit=function(){var t=this;this.columns=[{prop:"key",flexGrow:1,cellTransformation:i.a.bold},{prop:"value",flexGrow:3}],this.customCss&&(this.columns[1].cellTransformation=i.a.classAdding),this.fetchData.observers.length>0&&this.table.fetchData.subscribe(function(){t.fetchData.emit()}),this.useData()},t.prototype.ngOnChanges=function(){this.useData()},t.prototype.useData=function(){var t=this;if(this.data){var e=this.makePairs(this.data);this.hideKeys&&(e=e.filter(function(e){return!t.hideKeys.includes(e.key)})),this.tableData=e}},t.prototype.makePairs=function(t){var e=this,n=[];if(t){if(r.isArray(t))n=this.makePairsFromArray(t);else{if(!r.isObject(t))throw new Error("Wrong data format");n=this.makePairsFromObject(t)}return n=n.map(function(t){return t.value=e.convertValue(t.value),t}).filter(function(t){return null!==t.value}),r.sortBy(this.renderObjects?this.insertFlattenObjects(n):n,"key")}},t.prototype.makePairsFromArray=function(t){var e=this,n=[],a=t[0];if(r.isArray(a)){if(2!==a.length)throw new Error("Array contains too many elements ("+a.length+"). Needs to be of type [string, any][]");n=t.map(function(t){return{key:t[0],value:t[1]}})}else r.isObject(a)&&(n=r.has(a,"key")&&r.has(a,"value")?t.slice():t.reduce(function(t,n){return t.concat(e.makePairsFromObject(n))},n));return n},t.prototype.makePairsFromObject=function(t){return Object.keys(t).map(function(e){return{key:e,value:t[e]}})},t.prototype.insertFlattenObjects=function(t){var e=this;return r.flattenDeep(t.map(function(t){var n=t.value,a=r.isObject(n);return!a||r.isEmpty(n)?(a&&(t.value=""),t):e.splitItemIntoItems(t)}))},t.prototype.splitItemIntoItems=function(t){var e=this;return this.makePairs(t.value).map(function(n){return e.appendParentKey&&(n.key=t.key+" "+n.key),n})},t.prototype.convertValue=function(t){if(r.isArray(t)){if(r.isEmpty(t)&&this.hideEmpty)return null;t=t.map(function(t){return r.isObject(t)?JSON.stringify(t):t}).join(", ")}else if(r.isObject(t)){if(this.hideEmpty&&r.isEmpty(t)||!this.renderObjects)return null}else if(r.isString(t)){if(""===t&&this.hideEmpty)return null;this.isDate(t)&&(t=this.datePipe.transform(t)||t)}return t},t.prototype.isDate=function(t){var e="\\d{2}[ -:.TZ]";return t.match(new RegExp("^\\d{4}[ -:.TZ]"+e+e+e+e+e+"\\d*Z?$"))},t}())},FYBg:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=(n("JZ5S"),n("QG5k")),i=n("TCh0");e.NodeMenuComponent=function(){function t(t,e){this.renderer=t,this.nodeMenuService=e,this.menuItemSelected=new a.EventEmitter,this.availableMenuItems=[{name:"New tag",action:r.NodeMenuItemAction.NewTag,cssClass:"new-tag"},{name:"New folder",action:r.NodeMenuItemAction.NewFolder,cssClass:"new-folder"},{name:"Rename",action:r.NodeMenuItemAction.Rename,cssClass:"rename"},{name:"Remove",action:r.NodeMenuItemAction.Remove,cssClass:"remove"}],this.disposersForGlobalListeners=[]}return t.prototype.ngOnInit=function(){this.availableMenuItems=this.menuItems||this.availableMenuItems,this.disposersForGlobalListeners.push(this.renderer.listen("document","keyup",this.closeMenu.bind(this))),this.disposersForGlobalListeners.push(this.renderer.listen("document","mousedown",this.closeMenu.bind(this)))},t.prototype.ngOnDestroy=function(){this.disposersForGlobalListeners.forEach(function(t){return t()})},t.prototype.onMenuItemSelected=function(t,e){i.isLeftButtonClicked(t)&&(this.menuItemSelected.emit({nodeMenuItemAction:e.action,nodeMenuItemSelected:e.name}),this.nodeMenuService.fireMenuEvent(t.target,r.NodeMenuAction.Close))},t.prototype.closeMenu=function(t){var e=t instanceof MouseEvent,n=this.menuContainer.nativeElement!==t.target&&this.menuContainer.nativeElement.contains(t.target);(e&&!n||i.isEscapePressed(t))&&this.nodeMenuService.fireMenuEvent(t.target,r.NodeMenuAction.Close)},t.decorators=[{type:a.Component,args:[{selector:"node-menu",template:'\n <div class="node-menu">\n <ul class="node-menu-content" #menuContainer>\n <li class="node-menu-item" *ngFor="let menuItem of availableMenuItems"\n (click)="onMenuItemSelected($event, menuItem)">\n <div class="node-menu-item-icon {{menuItem.cssClass}}"></div>\n <span class="node-menu-item-value">{{menuItem.name}}</span>\n </li>\n </ul>\n </div>\n '}]}],t.propDecorators={menuItemSelected:[{type:a.Output}],menuItems:[{type:a.Input}],menuContainer:[{type:a.ViewChild,args:["menuContainer"]}]},t}()},Fgil:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("aXbf");var a=function(){function t(t){this.formatter=t}return t.prototype.transform=function(t){return this.formatter.format_number(t,1024,["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"])},t}()},Fjl2:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DatatableGroupHeaderTemplateDirective=function(){return a([r.Directive({selector:"[ngx-datatable-group-header-template]"})],function(t){this.template=t})}()},Fxb1:function(t,e,n){"use strict";var a=n("+tJ4"),r=n("DKTb"),i=n("En8+"),s=n("xTla"),o=n("2ePl"),u=n("/WYv"),c=n("McSo");n.d(e,"a",function(){return l});var l=function(t){if(t&&"function"==typeof t[s.a])return l=t,function(t){var e=l[s.a]();if("function"!=typeof e.subscribe)throw new TypeError("Provided object does not correctly implement Symbol.observable");return e.subscribe(t)};if(Object(o.a)(t))return Object(a.a)(t);if(Object(u.a)(t))return n=t,function(t){return n.then(function(e){t.closed||(t.next(e),t.complete())},function(e){return t.error(e)}).then(null,r.a),t};if(t&&"function"==typeof t[i.a])return e=t,function(t){for(var n=e[i.a]();;){var a=n.next();if(a.done){t.complete();break}if(t.next(a.value),t.closed)break}return"function"==typeof n.return&&t.add(function(){n.return&&n.return()}),t};var e,n,l,d=Object(c.a)(t)?"an invalid object":"'"+t+"'";throw new TypeError("You provided "+d+" where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.")}},G0Q6:function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),t.exports=function(t){function e(t,e){return i.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:r.Line,dataElementType:r.Point,update:function(t){var n,a,r,s=this,o=s.getMeta(),u=o.dataset,c=o.data||[],l=s.chart.options,d=l.elements.line,f=s.getScaleForId(o.yAxisID),p=s.getDataset(),h=e(p,l);for(h&&(r=u.custom||{},void 0!==p.tension&&void 0===p.lineTension&&(p.lineTension=p.tension),u._scale=f,u._datasetIndex=s.index,u._children=c,u._model={spanGaps:p.spanGaps?p.spanGaps:l.spanGaps,tension:r.tension?r.tension:i.valueOrDefault(p.lineTension,d.tension),backgroundColor:r.backgroundColor?r.backgroundColor:p.backgroundColor||d.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:p.borderWidth||d.borderWidth,borderColor:r.borderColor?r.borderColor:p.borderColor||d.borderColor,borderCapStyle:r.borderCapStyle?r.borderCapStyle:p.borderCapStyle||d.borderCapStyle,borderDash:r.borderDash?r.borderDash:p.borderDash||d.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:p.borderDashOffset||d.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:p.borderJoinStyle||d.borderJoinStyle,fill:r.fill?r.fill:void 0!==p.fill?p.fill:d.fill,steppedLine:r.steppedLine?r.steppedLine:i.valueOrDefault(p.steppedLine,d.stepped),cubicInterpolationMode:r.cubicInterpolationMode?r.cubicInterpolationMode:i.valueOrDefault(p.cubicInterpolationMode,d.cubicInterpolationMode)},u.pivot()),n=0,a=c.length;n<a;++n)s.updateElement(c[n],n,t);for(h&&0!==u._model.tension&&s.updateBezierControlPoints(),n=0,a=c.length;n<a;++n)c[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,a=this.getDataset(),r=t.custom||{};return r.backgroundColor?n=r.backgroundColor:a.pointBackgroundColor?n=i.valueAtIndexOrDefault(a.pointBackgroundColor,e,n):a.backgroundColor&&(n=a.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,a=this.getDataset(),r=t.custom||{};return r.borderColor?n=r.borderColor:a.pointBorderColor?n=i.valueAtIndexOrDefault(a.pointBorderColor,e,n):a.borderColor&&(n=a.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,a=this.getDataset(),r=t.custom||{};return isNaN(r.borderWidth)?!isNaN(a.pointBorderWidth)||i.isArray(a.pointBorderWidth)?n=i.valueAtIndexOrDefault(a.pointBorderWidth,e,n):isNaN(a.borderWidth)||(n=a.borderWidth):n=r.borderWidth,n},getPointRotation:function(t,e){var n=this.chart.options.elements.point.rotation,a=this.getDataset(),r=t.custom||{};return isNaN(r.rotation)?isNaN(a.pointRotation)&&!i.isArray(a.pointRotation)||(n=i.valueAtIndexOrDefault(a.pointRotation,e,n)):n=r.rotation,n},updateElement:function(t,e,n){var a,r,s=this,o=s.getMeta(),u=t.custom||{},c=s.getDataset(),l=s.index,d=c.data[e],f=s.getScaleForId(o.yAxisID),p=s.getScaleForId(o.xAxisID),h=s.chart.options.elements.point;void 0!==c.radius&&void 0===c.pointRadius&&(c.pointRadius=c.radius),void 0!==c.hitRadius&&void 0===c.pointHitRadius&&(c.pointHitRadius=c.hitRadius),a=p.getPixelForValue("object"==typeof d?d:NaN,e,l),r=n?f.getBasePixel():s.calculatePointY(d,e,l),t._xScale=p,t._yScale=f,t._datasetIndex=l,t._index=e,t._model={x:a,y:r,skip:u.skip||isNaN(a)||isNaN(r),radius:u.radius||i.valueAtIndexOrDefault(c.pointRadius,e,h.radius),pointStyle:u.pointStyle||i.valueAtIndexOrDefault(c.pointStyle,e,h.pointStyle),rotation:s.getPointRotation(t,e),backgroundColor:s.getPointBackgroundColor(t,e),borderColor:s.getPointBorderColor(t,e),borderWidth:s.getPointBorderWidth(t,e),tension:o.dataset._model?o.dataset._model.tension:0,steppedLine:!!o.dataset._model&&o.dataset._model.steppedLine,hitRadius:u.hitRadius||i.valueAtIndexOrDefault(c.pointHitRadius,e,h.hitRadius)}},calculatePointY:function(t,e,n){var a,r,i,s=this.chart,o=this.getMeta(),u=this.getScaleForId(o.yAxisID),c=0,l=0;if(u.options.stacked){for(a=0;a<n;a++)if(r=s.data.datasets[a],"line"===(i=s.getDatasetMeta(a)).type&&i.yAxisID===u.id&&s.isDatasetVisible(a)){var d=Number(u.getRightValue(r.data[e]));d<0?l+=d||0:c+=d||0}var f=Number(u.getRightValue(t));return u.getPixelForValue(f<0?l+f:c+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,n,a,r=this.getMeta(),s=this.chart.chartArea,o=r.data||[];function u(t,e,n){return Math.max(Math.min(t,n),e)}if(r.dataset._model.spanGaps&&(o=o.filter(function(t){return!t._model.skip})),"monotone"===r.dataset._model.cubicInterpolationMode)i.splineCurveMonotone(o);else for(t=0,e=o.length;t<e;++t)n=o[t]._model,a=i.splineCurve(i.previousItem(o,t)._model,n,i.nextItem(o,t)._model,r.dataset._model.tension),n.controlPointPreviousX=a.previous.x,n.controlPointPreviousY=a.previous.y,n.controlPointNextX=a.next.x,n.controlPointNextY=a.next.y;if(this.chart.options.elements.line.capBezierPoints)for(t=0,e=o.length;t<e;++t)(n=o[t]._model).controlPointPreviousX=u(n.controlPointPreviousX,s.left,s.right),n.controlPointPreviousY=u(n.controlPointPreviousY,s.top,s.bottom),n.controlPointNextX=u(n.controlPointNextX,s.left,s.right),n.controlPointNextY=u(n.controlPointNextY,s.top,s.bottom)},draw:function(){var t,n=this.chart,a=this.getMeta(),r=a.data||[],s=n.chartArea,o=r.length,u=0;for(e(this.getDataset(),n.options)&&(i.canvas.clipArea(n.ctx,{left:s.left,right:s.right,top:s.top-(t=(a.dataset._model.borderWidth||0)/2),bottom:s.bottom+t}),a.dataset.draw(),i.canvas.unclipArea(n.ctx));u<o;++u)r[u].draw(s)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=t._model;t.$previousStyle={backgroundColor:r.backgroundColor,borderColor:r.borderColor,borderWidth:r.borderWidth,radius:r.radius},r.backgroundColor=a.hoverBackgroundColor||i.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,i.getHoverColor(r.backgroundColor)),r.borderColor=a.hoverBorderColor||i.valueAtIndexOrDefault(e.pointHoverBorderColor,n,i.getHoverColor(r.borderColor)),r.borderWidth=a.hoverBorderWidth||i.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,r.borderWidth),r.radius=a.hoverRadius||i.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius)}})}},G0Uy:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("mt",{months:"Jannar_Frar_Marzu_April_Mejju_\u0120unju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Di\u010bembru".split("_"),monthsShort:"Jan_Fra_Mar_Apr_Mej_\u0120un_Lul_Aww_Set_Ott_Nov_Di\u010b".split("_"),weekdays:"Il-\u0126add_It-Tnejn_It-Tlieta_L-Erbg\u0127a_Il-\u0126amis_Il-\u0120img\u0127a_Is-Sibt".split("_"),weekdaysShort:"\u0126ad_Tne_Tli_Erb_\u0126am_\u0120im_Sib".split("_"),weekdaysMin:"\u0126a_Tn_Tl_Er_\u0126a_\u0120i_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Illum fil-]LT",nextDay:"[G\u0127ada fil-]LT",nextWeek:"dddd [fil-]LT",lastDay:"[Il-biera\u0127 fil-]LT",lastWeek:"dddd [li g\u0127adda] [fil-]LT",sameElse:"L"},relativeTime:{future:"f\u2019 %s",past:"%s ilu",s:"ftit sekondi",ss:"%d sekondi",m:"minuta",mm:"%d minuti",h:"sieg\u0127a",hh:"%d sieg\u0127at",d:"\u0121urnata",dd:"%d \u0121ranet",M:"xahar",MM:"%d xhur",y:"sena",yy:"%d sni"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},"G1/K":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t){return""===t?this.i18n("n/a"):t},t}()},G1I9:function(t,e,n){"use strict";n.d(e,"b",function(){return i}),n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("mtw6"),i=function(){return function(t,e,n,a,i){void 0===t&&(t=r.a.info),void 0===i&&(i="Ceph"),this.type=t,this.title=e,this.message=n,this.options=a,this.application=i,this.classes={Ceph:"ceph-icon",Prometheus:"prometheus-icon"},this.applicationClass=this.classes[this.application]}}(),s=function(t){function e(e){void 0===e&&(e=new i);var n=t.call(this,e.type,e.title,e.message,e.options,e.application)||this;return n.config=e,n.textClasses=["text-danger","text-info","text-success"],n.iconClasses=["fa-exclamation-triangle","fa-info","fa-check"],delete n.config,n.timestamp=(new Date).toJSON(),n.iconClass=n.iconClasses[n.type],n.textClass=n.textClasses[n.type],n}return a.__extends(e,t),e}(i)},G5J1:function(t,e,n){"use strict";n.d(e,"a",function(){return r}),n.d(e,"b",function(){return i});var a=n("6blF"),r=new a.a(function(t){return t.complete()});function i(t){return t?function(t){return new a.a(function(e){return t.schedule(function(){return e.complete()})})}(t):r}},"G6Q+":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},GDJm:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RowHeightCache=function(){function t(){this.treeArray=[]}return t.prototype.clearCache=function(){this.treeArray=[]},t.prototype.initCache=function(t){var e=t.rows,n=t.rowHeight,a=t.detailRowHeight,r=t.externalVirtual,i=t.rowCount,s=t.rowIndexes,o=t.rowExpansions,u="function"==typeof n,c="function"==typeof a;if(!u&&isNaN(n))throw new Error("Row Height cache initialization failed. Please ensure that 'rowHeight' is a\n valid number or function value: ("+n+") when 'scrollbarV' is enabled.");if(!c&&isNaN(a))throw new Error("Row Height cache initialization failed. Please ensure that 'detailRowHeight' is a\n valid number or function value: ("+a+") when 'scrollbarV' is enabled.");var l=r?i:e.length;this.treeArray=new Array(l);for(var d=0;d<l;++d)this.treeArray[d]=0;for(d=0;d<l;++d){var f=e[d],p=n;u&&(p=n(f));var h=o.get(f);f&&1===h&&(p+=c?a(f,s.get(f)):a),this.update(d,p)}},t.prototype.getRowIndex=function(t){return 0===t?0:this.calcRowIndex(t)},t.prototype.update=function(t,e){if(!this.treeArray.length)throw new Error("Update at index "+t+" with value "+e+" failed:\n Row Height cache not initialized.");var n=this.treeArray.length;for(t|=0;t<n;)this.treeArray[t]+=e,t|=t+1},t.prototype.query=function(t){if(!this.treeArray.length)throw new Error("query at index "+t+" failed: Fenwick tree array not initialized.");var e=0;for(t|=0;t>=0;)e+=this.treeArray[t],t=(t&t+1)-1;return e},t.prototype.queryBetween=function(t,e){return this.query(e)-this.query(t-1)},t.prototype.calcRowIndex=function(t){if(!this.treeArray.length)return 0;for(var e=-1,n=this.treeArray.length,a=Math.pow(2,n.toString(2).length-1);0!==a;a>>=1){var r=e+a;r<n&&t>=this.treeArray[r]&&(t-=this.treeArray[r],e=r)}return e+1},t}()},GgAd:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){this.decimals=0,this.isBinary=!0}return t.prototype.ngOnChanges=function(){this.usedPercentage=this.total>0?this.used/this.total*100:0,this.freePercentage=100-this.usedPercentage},t}()},Gi3i:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("FFOo"),i=n("T1DM");function s(t,e){return void 0===e&&(e=i.a),function(n){return n.lift(new o(t,e))}}var o=function(){function t(t,e){this.dueTime=t,this.scheduler=e}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.dueTime,this.scheduler))},t}(),u=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.dueTime=n,r.scheduler=a,r.debouncedSubscription=null,r.lastValue=null,r.hasValue=!1,r}return a.__extends(e,t),e.prototype._next=function(t){this.clearDebounce(),this.lastValue=t,this.hasValue=!0,this.add(this.debouncedSubscription=this.scheduler.schedule(c,this.dueTime,this))},e.prototype._complete=function(){this.debouncedNext(),this.destination.complete()},e.prototype.debouncedNext=function(){if(this.clearDebounce(),this.hasValue){var t=this.lastValue;this.lastValue=null,this.hasValue=!1,this.destination.next(t)}},e.prototype.clearDebounce=function(){var t=this.debouncedSubscription;null!==t&&(this.remove(t),t.unsubscribe(),this.debouncedSubscription=null)},e}(r.a);function c(t){t.debouncedNext()}},H8ED:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a,r;return"m"===n?e?"\u0445\u0432\u0456\u043b\u0456\u043d\u0430":"\u0445\u0432\u0456\u043b\u0456\u043d\u0443":"h"===n?e?"\u0433\u0430\u0434\u0437\u0456\u043d\u0430":"\u0433\u0430\u0434\u0437\u0456\u043d\u0443":t+" "+(a=+t,r={ss:e?"\u0441\u0435\u043a\u0443\u043d\u0434\u0430_\u0441\u0435\u043a\u0443\u043d\u0434\u044b_\u0441\u0435\u043a\u0443\u043d\u0434":"\u0441\u0435\u043a\u0443\u043d\u0434\u0443_\u0441\u0435\u043a\u0443\u043d\u0434\u044b_\u0441\u0435\u043a\u0443\u043d\u0434",mm:e?"\u0445\u0432\u0456\u043b\u0456\u043d\u0430_\u0445\u0432\u0456\u043b\u0456\u043d\u044b_\u0445\u0432\u0456\u043b\u0456\u043d":"\u0445\u0432\u0456\u043b\u0456\u043d\u0443_\u0445\u0432\u0456\u043b\u0456\u043d\u044b_\u0445\u0432\u0456\u043b\u0456\u043d",hh:e?"\u0433\u0430\u0434\u0437\u0456\u043d\u0430_\u0433\u0430\u0434\u0437\u0456\u043d\u044b_\u0433\u0430\u0434\u0437\u0456\u043d":"\u0433\u0430\u0434\u0437\u0456\u043d\u0443_\u0433\u0430\u0434\u0437\u0456\u043d\u044b_\u0433\u0430\u0434\u0437\u0456\u043d",dd:"\u0434\u0437\u0435\u043d\u044c_\u0434\u043d\u0456_\u0434\u0437\u0451\u043d",MM:"\u043c\u0435\u0441\u044f\u0446_\u043c\u0435\u0441\u044f\u0446\u044b_\u043c\u0435\u0441\u044f\u0446\u0430\u045e",yy:"\u0433\u043e\u0434_\u0433\u0430\u0434\u044b_\u0433\u0430\u0434\u043e\u045e"}[n].split("_"),a%10==1&&a%100!=11?r[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?r[1]:r[2])}n("wd/R").defineLocale("be",{months:{format:"\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f_\u043b\u044e\u0442\u0430\u0433\u0430_\u0441\u0430\u043a\u0430\u0432\u0456\u043a\u0430_\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a\u0430_\u0442\u0440\u0430\u045e\u043d\u044f_\u0447\u044d\u0440\u0432\u0435\u043d\u044f_\u043b\u0456\u043f\u0435\u043d\u044f_\u0436\u043d\u0456\u045e\u043d\u044f_\u0432\u0435\u0440\u0430\u0441\u043d\u044f_\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430_\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430_\u0441\u043d\u0435\u0436\u043d\u044f".split("_"),standalone:"\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044c_\u043b\u044e\u0442\u044b_\u0441\u0430\u043a\u0430\u0432\u0456\u043a_\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a_\u0442\u0440\u0430\u0432\u0435\u043d\u044c_\u0447\u044d\u0440\u0432\u0435\u043d\u044c_\u043b\u0456\u043f\u0435\u043d\u044c_\u0436\u043d\u0456\u0432\u0435\u043d\u044c_\u0432\u0435\u0440\u0430\u0441\u0435\u043d\u044c_\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a_\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434_\u0441\u043d\u0435\u0436\u0430\u043d\u044c".split("_")},monthsShort:"\u0441\u0442\u0443\u0434_\u043b\u044e\u0442_\u0441\u0430\u043a_\u043a\u0440\u0430\u0441_\u0442\u0440\u0430\u0432_\u0447\u044d\u0440\u0432_\u043b\u0456\u043f_\u0436\u043d\u0456\u0432_\u0432\u0435\u0440_\u043a\u0430\u0441\u0442_\u043b\u0456\u0441\u0442_\u0441\u043d\u0435\u0436".split("_"),weekdays:{format:"\u043d\u044f\u0434\u0437\u0435\u043b\u044e_\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a_\u0430\u045e\u0442\u043e\u0440\u0430\u043a_\u0441\u0435\u0440\u0430\u0434\u0443_\u0447\u0430\u0446\u0432\u0435\u0440_\u043f\u044f\u0442\u043d\u0456\u0446\u0443_\u0441\u0443\u0431\u043e\u0442\u0443".split("_"),standalone:"\u043d\u044f\u0434\u0437\u0435\u043b\u044f_\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a_\u0430\u045e\u0442\u043e\u0440\u0430\u043a_\u0441\u0435\u0440\u0430\u0434\u0430_\u0447\u0430\u0446\u0432\u0435\u0440_\u043f\u044f\u0442\u043d\u0456\u0446\u0430_\u0441\u0443\u0431\u043e\u0442\u0430".split("_"),isFormat:/\[ ?[\u0423\u0443\u045e] ?(?:\u043c\u0456\u043d\u0443\u043b\u0443\u044e|\u043d\u0430\u0441\u0442\u0443\u043f\u043d\u0443\u044e)? ?\] ?dddd/},weekdaysShort:"\u043d\u0434_\u043f\u043d_\u0430\u0442_\u0441\u0440_\u0447\u0446_\u043f\u0442_\u0441\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0430\u0442_\u0441\u0440_\u0447\u0446_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0433.",LLL:"D MMMM YYYY \u0433., HH:mm",LLLL:"dddd, D MMMM YYYY \u0433., HH:mm"},calendar:{sameDay:"[\u0421\u0451\u043d\u043d\u044f \u045e] LT",nextDay:"[\u0417\u0430\u045e\u0442\u0440\u0430 \u045e] LT",lastDay:"[\u0423\u0447\u043e\u0440\u0430 \u045e] LT",nextWeek:function(){return"[\u0423] dddd [\u045e] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[\u0423 \u043c\u0456\u043d\u0443\u043b\u0443\u044e] dddd [\u045e] LT";case 1:case 2:case 4:return"[\u0423 \u043c\u0456\u043d\u0443\u043b\u044b] dddd [\u045e] LT"}},sameElse:"L"},relativeTime:{future:"\u043f\u0440\u0430\u0437 %s",past:"%s \u0442\u0430\u043c\u0443",s:"\u043d\u0435\u043a\u0430\u043b\u044c\u043a\u0456 \u0441\u0435\u043a\u0443\u043d\u0434",m:e,mm:e,h:e,hh:e,d:"\u0434\u0437\u0435\u043d\u044c",dd:e,M:"\u043c\u0435\u0441\u044f\u0446",MM:e,y:"\u0433\u043e\u0434",yy:e},meridiemParse:/\u043d\u043e\u0447\u044b|\u0440\u0430\u043d\u0456\u0446\u044b|\u0434\u043d\u044f|\u0432\u0435\u0447\u0430\u0440\u0430/,isPM:function(t){return/^(\u0434\u043d\u044f|\u0432\u0435\u0447\u0430\u0440\u0430)$/.test(t)},meridiem:function(t,e,n){return t<4?"\u043d\u043e\u0447\u044b":t<12?"\u0440\u0430\u043d\u0456\u0446\u044b":t<17?"\u0434\u043d\u044f":"\u0432\u0435\u0447\u0430\u0440\u0430"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0456|\u044b|\u0433\u0430)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t%10!=2&&t%10!=3||t%100==12||t%100==13?t+"-\u044b":t+"-\u0456";case"D":return t+"-\u0433\u0430";default:return t}},week:{dow:1,doy:7}})}()},"HHO+":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=(n("58b6"),n("58b6")),i=n("xZld"),s=n("lJMN"),o=(n("JZ5S"),n("QG5k")),u=n("1PfE"),c=(n("Tff5"),n("TCh0")),l=n("kQXf");e.TreeInternalComponent=function(){function t(t,e,n){this.nodeMenuService=t,this.treeService=e,this.nodeElementRef=n,this.isSelected=!1,this.isRightMenuVisible=!1,this.isLeftMenuVisible=!1,this.isReadOnly=!1,this.subscriptions=[]}return t.prototype.ngAfterViewInit=function(){this.tree.checked&&!this.tree.firstCheckedFired&&(this.tree.firstCheckedFired=!0,this.treeService.fireNodeChecked(this.tree))},t.prototype.ngOnInit=function(){var t=this,e=l.get(this.tree,"node.id","");e&&(this.controller=new s.TreeController(this),this.treeService.setController(e,this.controller)),this.settings=this.settings||new r.Ng2TreeSettings,this.isReadOnly=!l.get(this.settings,"enableCheckboxes",!0),this.tree.isRoot()&&!1===this.settings.rootIsVisible&&this.tree.disableCollapseOnInit(),this.subscriptions.push(this.nodeMenuService.hideMenuStream(this.nodeElementRef).subscribe(function(){t.isRightMenuVisible=!1,t.isLeftMenuVisible=!1})),this.subscriptions.push(this.treeService.unselectStream(this.tree).subscribe(function(){return t.isSelected=!1})),this.subscriptions.push(this.treeService.draggedStream(this.tree,this.nodeElementRef).subscribe(function(e){t.tree.hasSibling(e.captured.tree)?t.swapWithSibling(e.captured.tree,t.tree):t.tree.isBranch()?t.moveNodeToThisTreeAndRemoveFromPreviousOne(e,t.tree):t.moveNodeToParentTreeAndRemoveFromPreviousOne(e,t.tree)})),this.subscriptions.push(this.treeService.nodeChecked$.merge(this.treeService.nodeUnchecked$).filter(function(e){return t.eventContainsId(e)&&t.tree.hasChild(e.node)}).subscribe(function(e){return t.updateCheckboxState()}))},t.prototype.ngOnChanges=function(t){this.controller=new s.TreeController(this)},t.prototype.ngOnDestroy=function(){l.get(this.tree,"node.id","")&&this.treeService.deleteController(this.tree.node.id),this.subscriptions.forEach(function(t){return t&&t.unsubscribe()})},t.prototype.swapWithSibling=function(t,e){e.swapWithSibling(t),this.treeService.fireNodeMoved(t,t.parent)},t.prototype.moveNodeToThisTreeAndRemoveFromPreviousOne=function(t,e){this.treeService.fireNodeRemoved(t.captured.tree);var n=e.addChild(t.captured.tree);this.treeService.fireNodeMoved(n,t.captured.tree.parent)},t.prototype.moveNodeToParentTreeAndRemoveFromPreviousOne=function(t,e){this.treeService.fireNodeRemoved(t.captured.tree);var n=e.addSibling(t.captured.tree,e.positionInParent);this.treeService.fireNodeMoved(n,t.captured.tree.parent)},t.prototype.onNodeSelected=function(t){this.tree.selectionAllowed&&c.isLeftButtonClicked(t)&&(this.isSelected=!0,this.treeService.fireNodeSelected(this.tree))},t.prototype.onNodeUnselected=function(t){this.tree.selectionAllowed&&c.isLeftButtonClicked(t)&&(this.isSelected=!1,this.treeService.fireNodeUnselected(this.tree))},t.prototype.showRightMenu=function(t){this.tree.hasRightMenu()&&(c.isRightButtonClicked(t)&&(this.isRightMenuVisible=!this.isRightMenuVisible,this.nodeMenuService.hideMenuForAllNodesExcept(this.nodeElementRef)),t.preventDefault())},t.prototype.showLeftMenu=function(t){this.tree.hasLeftMenu()&&c.isLeftButtonClicked(t)&&(this.isLeftMenuVisible=!this.isLeftMenuVisible,this.nodeMenuService.hideMenuForAllNodesExcept(this.nodeElementRef),this.isLeftMenuVisible&&t.preventDefault())},t.prototype.onMenuItemSelected=function(t){switch(t.nodeMenuItemAction){case o.NodeMenuItemAction.NewTag:case o.NodeMenuItemAction.NewFolder:this.onNewSelected(t);break;case o.NodeMenuItemAction.Rename:this.onRenameSelected();break;case o.NodeMenuItemAction.Remove:this.onRemoveSelected();break;case o.NodeMenuItemAction.Custom:this.onCustomSelected(),this.treeService.fireMenuItemSelected(this.tree,t.nodeMenuItemSelected);break;default:throw new Error("Chosen menu item doesn't exist")}},t.prototype.onNewSelected=function(t){this.tree.createNode(t.nodeMenuItemAction===o.NodeMenuItemAction.NewFolder),this.isRightMenuVisible=!1,this.isLeftMenuVisible=!1},t.prototype.onRenameSelected=function(){this.tree.markAsBeingRenamed(),this.isRightMenuVisible=!1,this.isLeftMenuVisible=!1},t.prototype.onRemoveSelected=function(){this.treeService.deleteController(l.get(this.tree,"node.id","")),this.treeService.fireNodeRemoved(this.tree)},t.prototype.onCustomSelected=function(){this.isRightMenuVisible=!1,this.isLeftMenuVisible=!1},t.prototype.onSwitchFoldingType=function(){this.tree.switchFoldingType(),this.treeService.fireNodeSwitchFoldingType(this.tree)},t.prototype.applyNewValue=function(t){if((t.action===u.NodeEditableEventAction.Cancel||this.tree.isNew())&&i.Tree.isValueEmpty(t.value))return this.treeService.fireNodeRemoved(this.tree);if(this.tree.isNew()&&(this.tree.value=t.value,this.treeService.fireNodeCreated(this.tree)),this.tree.isBeingRenamed()){var e=this.tree.value;this.tree.value=t.value,this.treeService.fireNodeRenamed(e,this.tree)}this.tree.markAsModified()},t.prototype.shouldShowInputForTreeValue=function(){return this.tree.isNew()||this.tree.isBeingRenamed()},t.prototype.isRootHidden=function(){return this.tree.isRoot()&&!this.settings.rootIsVisible},t.prototype.hasCustomMenu=function(){return this.tree.hasCustomMenu()},t.prototype.switchNodeCheckStatus=function(){this.tree.checked?this.onNodeUnchecked():this.onNodeChecked()},t.prototype.onNodeChecked=function(){this.checkboxElementRef&&(this.checkboxElementRef.nativeElement.indeterminate=!1,this.treeService.fireNodeChecked(this.tree),this.executeOnChildController(function(t){return t.check()}),this.tree.checked=!0)},t.prototype.onNodeUnchecked=function(){this.checkboxElementRef&&(this.checkboxElementRef.nativeElement.indeterminate=!1,this.treeService.fireNodeUnchecked(this.tree),this.executeOnChildController(function(t){return t.uncheck()}),this.tree.checked=!1)},t.prototype.executeOnChildController=function(t){var e=this;this.tree.hasLoadedChildern()&&this.tree.children.forEach(function(n){var a=e.treeService.getController(n.id);l.isNil(a)||t(a)})},t.prototype.updateCheckboxState=function(){var t=this;setTimeout(function(){var e=t.tree.checkedChildrenAmount();0===e?(t.checkboxElementRef.nativeElement.indeterminate=!1,t.tree.checked=!1,t.treeService.fireNodeUnchecked(t.tree)):e===t.tree.loadedChildrenAmount()?(t.checkboxElementRef.nativeElement.indeterminate=!1,t.tree.checked=!0,t.treeService.fireNodeChecked(t.tree)):(t.tree.checked=!1,t.checkboxElementRef.nativeElement.indeterminate=!0,t.treeService.fireNodeIndetermined(t.tree))})},t.prototype.eventContainsId=function(t){return!!t.node.id||(console.warn('"Node with checkbox" feature requires a unique id assigned to every node, please consider to add it.'),!1)},t.decorators=[{type:a.Component,args:[{selector:"tree-internal",template:'\n <ul class="tree" *ngIf="tree" [ngClass]="{rootless: isRootHidden()}">\n <li>\n <div class="value-container"\n [ngClass]="{rootless: isRootHidden()}"\n [class.selected]="isSelected"\n (contextmenu)="showRightMenu($event)"\n [nodeDraggable]="nodeElementRef"\n [tree]="tree">\n\n <div class="folding" (click)="onSwitchFoldingType()" [ngClass]="tree.foldingCssClass"></div>\n\n <div class="node-checkbox" *ngIf="settings.showCheckboxes">\n <input checkbox type="checkbox" [disabled]="isReadOnly" [checked]="this.tree.checked" (change)="switchNodeCheckStatus()" #checkbox />\n </div>\n\n <div class="node-value"\n *ngIf="!shouldShowInputForTreeValue()"\n [class.node-selected]="isSelected"\n (click)="onNodeSelected($event)">\n <div *ngIf="tree.nodeTemplate" class="node-template" [innerHTML]="tree.nodeTemplate | safeHtml"></div>\n <span *ngIf="!template" class="node-name" [innerHTML]="tree.value | safeHtml"></span>\n <span class="loading-children" *ngIf="tree.childrenAreBeingLoaded()"></span>\n <ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ $implicit: tree.node }"></ng-template>\n </div>\n\n <input type="text" class="node-value"\n *ngIf="shouldShowInputForTreeValue()"\n [nodeEditable]="tree.value"\n (valueChanged)="applyNewValue($event)"/>\n\n <div class="node-left-menu" *ngIf="tree.hasLeftMenu()" (click)="showLeftMenu($event)" [innerHTML]="tree.leftMenuTemplate">\n </div>\n <node-menu *ngIf="tree.hasLeftMenu() && isLeftMenuVisible && !hasCustomMenu()"\n (menuItemSelected)="onMenuItemSelected($event)">\n </node-menu>\n </div>\n\n <node-menu *ngIf="isRightMenuVisible && !hasCustomMenu()"\n (menuItemSelected)="onMenuItemSelected($event)">\n </node-menu>\n\n <node-menu *ngIf="hasCustomMenu() && (isRightMenuVisible || isLeftMenuVisible)"\n [menuItems]="tree.menuItems"\n (menuItemSelected)="onMenuItemSelected($event)">\n </node-menu>\n\n <div *ngIf="tree.keepNodesInDOM()" [ngStyle]="{\'display\': tree.isNodeExpanded() ? \'block\' : \'none\'}">\n <tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>\n </div>\n <ng-template [ngIf]="tree.isNodeExpanded() && !tree.keepNodesInDOM()">\n <tree-internal *ngFor="let child of tree.childrenAsync | async" [tree]="child" [template]="template" [settings]="settings"></tree-internal>\n </ng-template>\n </li>\n </ul>\n '}]}],t.propDecorators={tree:[{type:a.Input}],settings:[{type:a.Input}],template:[{type:a.Input}],checkboxElementRef:[{type:a.ViewChild,args:["checkbox"]}]},t}()},HJBe:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t){return void 0===t&&(t=null),function(e){return e.lift(new s(t))}}var s=function(){function t(t){this.defaultValue=t}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.defaultValue))},t}(),o=function(t){function e(e,n){var a=t.call(this,e)||this;return a.defaultValue=n,a.isEmpty=!0,a}return a.__extends(e,t),e.prototype._next=function(t){this.isEmpty=!1,this.destination.next(t)},e.prototype._complete=function(){this.isEmpty&&this.destination.next(this.defaultValue),this.destination.complete()},e}(r.a)},HP3h:function(t,e,n){!function(t){"use strict";var e={1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",0:"0"},n=function(t){return 0===t?0:1===t?1:2===t?2:t%100>=3&&t%100<=10?3:t%100>=11?4:5},a={s:["\u0623\u0642\u0644 \u0645\u0646 \u062b\u0627\u0646\u064a\u0629","\u062b\u0627\u0646\u064a\u0629 \u0648\u0627\u062d\u062f\u0629",["\u062b\u0627\u0646\u064a\u062a\u0627\u0646","\u062b\u0627\u0646\u064a\u062a\u064a\u0646"],"%d \u062b\u0648\u0627\u0646","%d \u062b\u0627\u0646\u064a\u0629","%d \u062b\u0627\u0646\u064a\u0629"],m:["\u0623\u0642\u0644 \u0645\u0646 \u062f\u0642\u064a\u0642\u0629","\u062f\u0642\u064a\u0642\u0629 \u0648\u0627\u062d\u062f\u0629",["\u062f\u0642\u064a\u0642\u062a\u0627\u0646","\u062f\u0642\u064a\u0642\u062a\u064a\u0646"],"%d \u062f\u0642\u0627\u0626\u0642","%d \u062f\u0642\u064a\u0642\u0629","%d \u062f\u0642\u064a\u0642\u0629"],h:["\u0623\u0642\u0644 \u0645\u0646 \u0633\u0627\u0639\u0629","\u0633\u0627\u0639\u0629 \u0648\u0627\u062d\u062f\u0629",["\u0633\u0627\u0639\u062a\u0627\u0646","\u0633\u0627\u0639\u062a\u064a\u0646"],"%d \u0633\u0627\u0639\u0627\u062a","%d \u0633\u0627\u0639\u0629","%d \u0633\u0627\u0639\u0629"],d:["\u0623\u0642\u0644 \u0645\u0646 \u064a\u0648\u0645","\u064a\u0648\u0645 \u0648\u0627\u062d\u062f",["\u064a\u0648\u0645\u0627\u0646","\u064a\u0648\u0645\u064a\u0646"],"%d \u0623\u064a\u0627\u0645","%d \u064a\u0648\u0645\u064b\u0627","%d \u064a\u0648\u0645"],M:["\u0623\u0642\u0644 \u0645\u0646 \u0634\u0647\u0631","\u0634\u0647\u0631 \u0648\u0627\u062d\u062f",["\u0634\u0647\u0631\u0627\u0646","\u0634\u0647\u0631\u064a\u0646"],"%d \u0623\u0634\u0647\u0631","%d \u0634\u0647\u0631\u0627","%d \u0634\u0647\u0631"],y:["\u0623\u0642\u0644 \u0645\u0646 \u0639\u0627\u0645","\u0639\u0627\u0645 \u0648\u0627\u062d\u062f",["\u0639\u0627\u0645\u0627\u0646","\u0639\u0627\u0645\u064a\u0646"],"%d \u0623\u0639\u0648\u0627\u0645","%d \u0639\u0627\u0645\u064b\u0627","%d \u0639\u0627\u0645"]},r=function(t){return function(e,r,i,s){var o=n(e),u=a[t][n(e)];return 2===o&&(u=u[r?0:1]),u.replace(/%d/i,e)}},i=["\u064a\u0646\u0627\u064a\u0631","\u0641\u0628\u0631\u0627\u064a\u0631","\u0645\u0627\u0631\u0633","\u0623\u0628\u0631\u064a\u0644","\u0645\u0627\u064a\u0648","\u064a\u0648\u0646\u064a\u0648","\u064a\u0648\u0644\u064a\u0648","\u0623\u063a\u0633\u0637\u0633","\u0633\u0628\u062a\u0645\u0628\u0631","\u0623\u0643\u062a\u0648\u0628\u0631","\u0646\u0648\u0641\u0645\u0628\u0631","\u062f\u064a\u0633\u0645\u0628\u0631"];t.defineLocale("ar-ly",{months:i,monthsShort:i,weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0623\u062d\u062f_\u0625\u062b\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0623\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/\u200fM/\u200fYYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/\u0635|\u0645/,isPM:function(t){return"\u0645"===t},meridiem:function(t,e,n){return t<12?"\u0635":"\u0645"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u064b\u0627 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0628\u0639\u062f %s",past:"\u0645\u0646\u0630 %s",s:r("s"),ss:r("s"),m:r("m"),mm:r("m"),h:r("h"),hh:r("h"),d:r("d"),dd:r("d"),M:r("M"),MM:r("M"),y:r("y"),yy:r("y")},preparse:function(t){return t.replace(/\u060c/g,",")},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]}).replace(/,/g,"\u060c")},week:{dow:6,doy:12}})}(n("wd/R"))},HV4d:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.id=function(){return("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)}},Hg4g:function(t,e){t.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},I2ZF:function(t,e){for(var n=[],a=0;a<256;++a)n[a]=(a+256).toString(16).substr(1);t.exports=function(t,e){var a=e||0;return[n[t[a++]],n[t[a++]],n[t[a++]],n[t[a++]],"-",n[t[a++]],n[t[a++]],"-",n[t[a++]],n[t[a++]],"-",n[t[a++]],n[t[a++]],"-",n[t[a++]],n[t[a++]],n[t[a++]],n[t[a++]],n[t[a++]],n[t[a++]]].join("")}},IBtZ:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ka",{months:{standalone:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10d8_\u10db\u10d0\u10e0\u10e2\u10d8_\u10d0\u10de\u10e0\u10d8\u10da\u10d8_\u10db\u10d0\u10d8\u10e1\u10d8_\u10d8\u10d5\u10dc\u10d8\u10e1\u10d8_\u10d8\u10d5\u10da\u10d8\u10e1\u10d8_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10dd_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10d8_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10d8".split("_"),format:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10e1_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10e1_\u10db\u10d0\u10e0\u10e2\u10e1_\u10d0\u10de\u10e0\u10d8\u10da\u10d8\u10e1_\u10db\u10d0\u10d8\u10e1\u10e1_\u10d8\u10d5\u10dc\u10d8\u10e1\u10e1_\u10d8\u10d5\u10da\u10d8\u10e1\u10e1_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10e1_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10e1_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10e1".split("_")},monthsShort:"\u10d8\u10d0\u10dc_\u10d7\u10d4\u10d1_\u10db\u10d0\u10e0_\u10d0\u10de\u10e0_\u10db\u10d0\u10d8_\u10d8\u10d5\u10dc_\u10d8\u10d5\u10da_\u10d0\u10d2\u10d5_\u10e1\u10d4\u10e5_\u10dd\u10e5\u10e2_\u10dc\u10dd\u10d4_\u10d3\u10d4\u10d9".split("_"),weekdays:{standalone:"\u10d9\u10d5\u10d8\u10e0\u10d0_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8_\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8".split("_"),format:"\u10d9\u10d5\u10d8\u10e0\u10d0\u10e1_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10e1_\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1".split("_"),isFormat:/(\u10ec\u10d8\u10dc\u10d0|\u10e8\u10d4\u10db\u10d3\u10d4\u10d2)/},weekdaysShort:"\u10d9\u10d5\u10d8_\u10dd\u10e0\u10e8_\u10e1\u10d0\u10db_\u10dd\u10d7\u10ee_\u10ee\u10e3\u10d7_\u10de\u10d0\u10e0_\u10e8\u10d0\u10d1".split("_"),weekdaysMin:"\u10d9\u10d5_\u10dd\u10e0_\u10e1\u10d0_\u10dd\u10d7_\u10ee\u10e3_\u10de\u10d0_\u10e8\u10d0".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[\u10d3\u10e6\u10d4\u10e1] LT[-\u10d6\u10d4]",nextDay:"[\u10ee\u10d5\u10d0\u10da] LT[-\u10d6\u10d4]",lastDay:"[\u10d2\u10e3\u10e8\u10d8\u10dc] LT[-\u10d6\u10d4]",nextWeek:"[\u10e8\u10d4\u10db\u10d3\u10d4\u10d2] dddd LT[-\u10d6\u10d4]",lastWeek:"[\u10ec\u10d8\u10dc\u10d0] dddd LT-\u10d6\u10d4",sameElse:"L"},relativeTime:{future:function(t){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10ec\u10d4\u10da\u10d8)/.test(t)?t.replace(/\u10d8$/,"\u10e8\u10d8"):t+"\u10e8\u10d8"},past:function(t){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10d3\u10e6\u10d4|\u10d7\u10d5\u10d4)/.test(t)?t.replace(/(\u10d8|\u10d4)$/,"\u10d8\u10e1 \u10ec\u10d8\u10dc"):/\u10ec\u10d4\u10da\u10d8/.test(t)?t.replace(/\u10ec\u10d4\u10da\u10d8$/,"\u10ec\u10da\u10d8\u10e1 \u10ec\u10d8\u10dc"):void 0},s:"\u10e0\u10d0\u10db\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 \u10ec\u10d0\u10db\u10d8",ss:"%d \u10ec\u10d0\u10db\u10d8",m:"\u10ec\u10e3\u10d7\u10d8",mm:"%d \u10ec\u10e3\u10d7\u10d8",h:"\u10e1\u10d0\u10d0\u10d7\u10d8",hh:"%d \u10e1\u10d0\u10d0\u10d7\u10d8",d:"\u10d3\u10e6\u10d4",dd:"%d \u10d3\u10e6\u10d4",M:"\u10d7\u10d5\u10d4",MM:"%d \u10d7\u10d5\u10d4",y:"\u10ec\u10d4\u10da\u10d8",yy:"%d \u10ec\u10d4\u10da\u10d8"},dayOfMonthOrdinalParse:/0|1-\u10da\u10d8|\u10db\u10d4-\d{1,2}|\d{1,2}-\u10d4/,ordinal:function(t){return 0===t?t:1===t?t+"-\u10da\u10d8":t<20||t<=100&&t%20==0||t%100==0?"\u10db\u10d4-"+t:t+"-\u10d4"},week:{dow:1,doy:7}})}()},ILDN:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.double="double"}(e.ClickType||(e.ClickType={}))},IPm6:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("5tze"),o=(n("qwkt"),n("SfHT"));e.DataTableBodyComponent=function(){function t(t){var e=this;this.cd=t,this.selected=[],this.scroll=new i.EventEmitter,this.page=new i.EventEmitter,this.activate=new i.EventEmitter,this.select=new i.EventEmitter,this.detailToggle=new i.EventEmitter,this.rowContextmenu=new i.EventEmitter(!1),this.treeAction=new i.EventEmitter,this.rowHeightsCache=new s.RowHeightCache,this.temp=[],this.offsetY=0,this.indexes={},this.rowIndexes=new Map,this.rowExpansions=new Map,this.getDetailRowHeight=function(t,n){if(!e.rowDetail)return 0;var a=e.rowDetail.rowHeight;return"function"==typeof a?a(t,n):a},this.rowTrackingFn=(function(t,e){var n=this.getRowIndex(e);return this.trackByProp?n+"-"+this.trackByProp:n}).bind(this)}return Object.defineProperty(t.prototype,"pageSize",{get:function(){return this._pageSize},set:function(t){this._pageSize=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rows",{get:function(){return this._rows},set:function(t){this._rows=t,this.rowExpansions.clear(),this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t;var e=s.columnsByPin(t);this.columnGroupWidths=s.columnGroupWidths(e,t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offset",{get:function(){return this._offset},set:function(t){this._offset=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowCount",{get:function(){return this._rowCount},set:function(t){this._rowCount=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bodyWidth",{get:function(){return this.scrollbarH?this.innerWidth+"px":"100%"},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bodyHeight",{get:function(){return this._bodyHeight},set:function(t){this._bodyHeight=this.scrollbarV?t+"px":"auto",this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"selectEnabled",{get:function(){return!!this.selectionType},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"scrollHeight",{get:function(){if(this.scrollbarV&&this.virtualization&&this.rowCount)return this.rowHeightsCache.query(this.rowCount-1)},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this.rowDetail&&(this.listener=this.rowDetail.toggle.subscribe(function(e){var n=e.type,a=e.value;"row"===n&&t.toggleRowExpansion(a),"all"===n&&t.toggleAllRows(a),t.updateIndexes(),t.updateRows(),t.cd.markForCheck()})),this.groupHeader&&(this.listener=this.groupHeader.toggle.subscribe(function(e){var n=e.type,a=e.value;"group"===n&&t.toggleRowExpansion(a),"all"===n&&t.toggleAllRows(a),t.updateIndexes(),t.updateRows(),t.cd.markForCheck()}))},t.prototype.ngOnDestroy=function(){this.rowDetail&&this.listener.unsubscribe(),this.groupHeader&&this.listener.unsubscribe()},t.prototype.updateOffsetY=function(t){this.scroller&&(this.scrollbarV&&this.virtualization&&t?t=this.rowHeightsCache.query(this.pageSize*t-1):this.scrollbarV&&!this.virtualization&&(t=0),this.scroller.setOffset(t||0))},t.prototype.onBodyScroll=function(t){var e=t.scrollYPos,n=t.scrollXPos;this.offsetY===e&&this.offsetX===n||this.scroll.emit({offsetY:e,offsetX:n}),this.offsetY=e,this.offsetX=n,this.updateIndexes(),this.updatePage(t.direction),this.updateRows()},t.prototype.updatePage=function(t){var e=this.indexes.first/this.pageSize;"up"===t?e=Math.ceil(e):"down"===t&&(e=Math.floor(e)),void 0===t||isNaN(e)||this.page.emit({offset:e})},t.prototype.updateRows=function(){var t=this.indexes,e=t.last,n=t.first,a=0,r=[];if(this.rowIndexes.clear(),this.groupedRows)for(;n<e&&n<this.groupedRows.length;)r[a]=this.groupedRows[n],a++,n++;else for(;n<e&&n<this.rowCount;){var i=this.rows[n];i&&(this.rowIndexes.set(i,n),r[a]=i),a++,n++}this.temp=r},t.prototype.getRowHeight=function(t){return"function"==typeof this.rowHeight?this.rowHeight(t):this.rowHeight},t.prototype.getGroupHeight=function(t){var e=0;if(t.value)for(var n=0;n<t.value.length;n++)e+=this.getRowAndDetailHeight(t.value[n]);return e},t.prototype.getRowAndDetailHeight=function(t){var e=this.getRowHeight(t);return 1===this.rowExpansions.get(t)&&(e+=this.getDetailRowHeight(t)),e},t.prototype.getRowsStyles=function(t){var e={};if(this.groupedRows&&(e.width=this.columnGroupWidths.total),this.scrollbarV&&this.virtualization){var n=0;if(this.groupedRows){var a=t[t.length-1];n=a?this.getRowIndex(a):0}else n=this.getRowIndex(t);var r=this.rowHeightsCache.query(n-1);s.translateXY(e,0,r)}return e},t.prototype.getBottomSummaryRowStyles=function(){if(!this.scrollbarV||!this.rows||!this.rows.length)return null;var t={position:"absolute"},e=this.rowHeightsCache.query(this.rows.length-1);return s.translateXY(t,0,e),t},t.prototype.hideIndicator=function(){var t=this;setTimeout(function(){return t.loadingIndicator=!1},500)},t.prototype.updateIndexes=function(){var t=0,e=0;if(this.scrollbarV)if(this.virtualization){var n=parseInt(this.bodyHeight,0);t=this.rowHeightsCache.getRowIndex(this.offsetY),e=this.rowHeightsCache.getRowIndex(n+this.offsetY)+1}else t=0,e=this.rowCount;else this.externalPaging||(t=Math.max(this.offset*this.pageSize,0)),e=Math.min(t+this.pageSize,this.rowCount);this.indexes={first:t,last:e}},t.prototype.refreshRowHeightCache=function(){!this.scrollbarV||this.scrollbarV&&!this.virtualization||(this.rowHeightsCache.clearCache(),this.rows&&this.rows.length&&this.rowHeightsCache.initCache({rows:this.rows,rowHeight:this.rowHeight,detailRowHeight:this.getDetailRowHeight,externalVirtual:this.scrollbarV&&this.externalPaging,rowCount:this.rowCount,rowIndexes:this.rowIndexes,rowExpansions:this.rowExpansions}))},t.prototype.getAdjustedViewPortIndex=function(){var t=this.indexes.first;return this.scrollbarV&&this.virtualization&&this.rowHeightsCache.query(t-1)<=this.offsetY?t-1:t},t.prototype.toggleRowExpansion=function(t){var e=this.getAdjustedViewPortIndex(),n=this.rowExpansions.get(t);if(this.scrollbarV&&this.virtualization){var a=this.getDetailRowHeight(t)*(n?-1:1),r=this.getRowIndex(t);this.rowHeightsCache.update(r,a)}n=n^=1,this.rowExpansions.set(t,n),this.detailToggle.emit({rows:[t],currentIndex:e})},t.prototype.toggleAllRows=function(t){this.rowExpansions.clear();for(var e=t?1:0,n=this.getAdjustedViewPortIndex(),a=0,r=this.rows;a<r.length;a++)this.rowExpansions.set(r[a],e);this.scrollbarV&&this.recalcLayout(),this.detailToggle.emit({rows:this.rows,currentIndex:n})},t.prototype.recalcLayout=function(){this.refreshRowHeightCache(),this.updateIndexes(),this.updateRows()},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.stylesByGroup=function(t){var e=this.columnGroupWidths,n=this.offsetX,a={width:e[t]+"px"};if("left"===t)s.translateXY(a,n,0);else if("right"===t){var r=parseInt(this.innerWidth+"",0);s.translateXY(a,-1*(e.total-r-n),0)}return a},t.prototype.getRowExpanded=function(t){if(0===this.rowExpansions.size&&this.groupExpansionDefault)for(var e=0,n=this.groupedRows;e<n.length;e++)this.rowExpansions.set(n[e],1);return 1===this.rowExpansions.get(t)},t.prototype.getRowIndex=function(t){return this.rowIndexes.get(t)||0},t.prototype.onTreeAction=function(t){this.treeAction.emit({row:t})},a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarV",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"loadingIndicator",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"externalPaging",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offsetX",void 0),a([i.Input(),r("design:type",String)],t.prototype,"emptyMessage",void 0),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Array)],t.prototype,"selected",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowIdentity",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowDetail",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupHeader",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectCheck",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"displayCheck",void 0),a([i.Input(),r("design:type",String)],t.prototype,"trackByProp",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowClass",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupedRows",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"groupExpansionDefault",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"innerWidth",void 0),a([i.Input(),r("design:type",String)],t.prototype,"groupRowsBy",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"virtualization",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"summaryRow",void 0),a([i.Input(),r("design:type",String)],t.prototype,"summaryPosition",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"summaryHeight",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"pageSize",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"rows",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offset",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowCount",null),a([i.HostBinding("style.width"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"bodyWidth",null),a([i.Input(),i.HostBinding("style.height"),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"bodyHeight",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"scroll",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"page",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"detailToggle",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"rowContextmenu",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"treeAction",void 0),a([i.ViewChild(o.ScrollerComponent),r("design:type",o.ScrollerComponent)],t.prototype,"scroller",void 0),a([i.Component({selector:"datatable-body",template:'\n <datatable-selection\n #selector\n [selected]="selected"\n [rows]="rows"\n [selectCheck]="selectCheck"\n [selectEnabled]="selectEnabled"\n [selectionType]="selectionType"\n [rowIdentity]="rowIdentity"\n (select)="select.emit($event)"\n (activate)="activate.emit($event)">\n <datatable-progress\n *ngIf="loadingIndicator">\n </datatable-progress>\n <datatable-scroller\n *ngIf="rows?.length"\n [scrollbarV]="scrollbarV"\n [scrollbarH]="scrollbarH"\n [scrollHeight]="scrollHeight"\n [scrollWidth]="columnGroupWidths?.total"\n (scroll)="onBodyScroll($event)">\n <datatable-summary-row\n *ngIf="summaryRow && summaryPosition === \'top\'"\n [rowHeight]="summaryHeight"\n [offsetX]="offsetX"\n [innerWidth]="innerWidth"\n [rows]="rows"\n [columns]="columns">\n </datatable-summary-row>\n <datatable-row-wrapper\n [groupedRows]="groupedRows"\n *ngFor="let group of temp; let i = index; trackBy: rowTrackingFn;"\n [innerWidth]="innerWidth"\n [ngStyle]="getRowsStyles(group)"\n [rowDetail]="rowDetail"\n [groupHeader]="groupHeader"\n [offsetX]="offsetX"\n [detailRowHeight]="getDetailRowHeight(group[i],i)"\n [row]="group"\n [expanded]="getRowExpanded(group)"\n [rowIndex]="getRowIndex(group[i])"\n (rowContextmenu)="rowContextmenu.emit($event)">\n <datatable-body-row\n *ngIf="!groupedRows; else groupedRowsTemplate"\n tabindex="-1"\n [isSelected]="selector.getRowSelected(group)"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="columns"\n [rowHeight]="getRowHeight(group)"\n [row]="group"\n [rowIndex]="getRowIndex(group)"\n [expanded]="getRowExpanded(group)"\n [rowClass]="rowClass"\n [displayCheck]="displayCheck"\n [treeStatus]="group.treeStatus"\n (treeAction)="onTreeAction(group)"\n (activate)="selector.onActivate($event, indexes.first + i)">\n </datatable-body-row>\n <ng-template #groupedRowsTemplate>\n <datatable-body-row\n *ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn;"\n tabindex="-1"\n [isSelected]="selector.getRowSelected(row)"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="columns"\n [rowHeight]="getRowHeight(row)"\n [row]="row"\n [group]="group.value"\n [rowIndex]="getRowIndex(row)"\n [expanded]="getRowExpanded(row)"\n [rowClass]="rowClass"\n (activate)="selector.onActivate($event, i)">\n </datatable-body-row>\n </ng-template>\n </datatable-row-wrapper>\n <datatable-summary-row\n *ngIf="summaryRow && summaryPosition === \'bottom\'"\n [ngStyle]="getBottomSummaryRowStyles()"\n [rowHeight]="summaryHeight"\n [offsetX]="offsetX"\n [innerWidth]="innerWidth"\n [rows]="rows"\n [columns]="columns">\n </datatable-summary-row>\n </datatable-scroller>\n <div\n class="empty-row"\n *ngIf="!rows?.length && !loadingIndicator"\n [innerHTML]="emptyMessage">\n </div>\n </datatable-selection>\n ',changeDetection:i.ChangeDetectionStrategy.OnPush,host:{class:"datatable-body"}})],t)}()},IUTb:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("6blF"),r=n("+tJ4"),i=n("JF+6");function s(t,e){return e?Object(i.a)(t,e):new a.a(Object(r.a)(t))}},IZUe:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=function(){function t(t){this.elementRef=t}return t.prototype.ngAfterViewInit=function(){var t=this.elementRef.nativeElement;a.isFunction(t.focus)&&t.focus()},t}()},Ip0R:function(t,e,n){"use strict";n.r(e),n.d(e,"\u0275angular_packages_common_common_e",function(){return Xt}),n.d(e,"\u0275angular_packages_common_common_d",function(){return B}),n.d(e,"\u0275angular_packages_common_common_a",function(){return Nt}),n.d(e,"\u0275angular_packages_common_common_b",function(){return Et}),n.d(e,"\u0275angular_packages_common_common_g",function(){return xe}),n.d(e,"\u0275angular_packages_common_common_f",function(){return Ve}),n.d(e,"\u0275registerLocaleData",function(){return b}),n.d(e,"registerLocaleData",function(){return b}),n.d(e,"formatDate",function(){return et}),n.d(e,"formatCurrency",function(){return St}),n.d(e,"formatNumber",function(){return It}),n.d(e,"formatPercent",function(){return Ot}),n.d(e,"NgLocaleLocalization",function(){return Dt}),n.d(e,"NgLocalization",function(){return Rt}),n.d(e,"Plural",function(){return v}),n.d(e,"NumberFormatStyle",function(){return y}),n.d(e,"FormStyle",function(){return _}),n.d(e,"TranslationWidth",function(){return x}),n.d(e,"FormatWidth",function(){return T}),n.d(e,"NumberSymbol",function(){return w}),n.d(e,"WeekDay",function(){return S}),n.d(e,"getNumberOfCurrencyDigits",function(){return K}),n.d(e,"getCurrencySymbol",function(){return U}),n.d(e,"getLocaleDayPeriods",function(){return I}),n.d(e,"getLocaleDayNames",function(){return C}),n.d(e,"getLocaleMonthNames",function(){return k}),n.d(e,"getLocaleId",function(){return O}),n.d(e,"getLocaleEraNames",function(){return N}),n.d(e,"getLocaleWeekEndRange",function(){return A}),n.d(e,"getLocaleFirstDayOfWeek",function(){return R}),n.d(e,"getLocaleDateFormat",function(){return D}),n.d(e,"getLocaleDateTimeFormat",function(){return L}),n.d(e,"getLocaleExtraDayPeriodRules",function(){return G}),n.d(e,"getLocaleExtraDayPeriods",function(){return Y}),n.d(e,"getLocalePluralCase",function(){return F}),n.d(e,"getLocaleTimeFormat",function(){return E}),n.d(e,"getLocaleNumberSymbol",function(){return P}),n.d(e,"getLocaleNumberFormat",function(){return M}),n.d(e,"getLocaleCurrencyName",function(){return j}),n.d(e,"getLocaleCurrencySymbol",function(){return q}),n.d(e,"\u0275parseCookieValue",function(){return Lt}),n.d(e,"CommonModule",function(){return He}),n.d(e,"DeprecatedI18NPipesModule",function(){return Be}),n.d(e,"NgClass",function(){return Pt}),n.d(e,"NgForOf",function(){return jt}),n.d(e,"NgForOfContext",function(){return qt}),n.d(e,"NgIf",function(){return zt}),n.d(e,"NgIfContext",function(){return Gt}),n.d(e,"NgPlural",function(){return Wt}),n.d(e,"NgPluralCase",function(){return Kt}),n.d(e,"NgStyle",function(){return $t}),n.d(e,"NgSwitch",function(){return Ht}),n.d(e,"NgSwitchCase",function(){return Bt}),n.d(e,"NgSwitchDefault",function(){return Ut}),n.d(e,"NgTemplateOutlet",function(){return Zt}),n.d(e,"NgComponentOutlet",function(){return Mt}),n.d(e,"DOCUMENT",function(){return Ue}),n.d(e,"AsyncPipe",function(){return Oe}),n.d(e,"DatePipe",function(){return Re}),n.d(e,"I18nPluralPipe",function(){return De}),n.d(e,"I18nSelectPipe",function(){return Ee}),n.d(e,"JsonPipe",function(){return Le}),n.d(e,"LowerCasePipe",function(){return Ie}),n.d(e,"CurrencyPipe",function(){return Fe}),n.d(e,"DecimalPipe",function(){return qe}),n.d(e,"PercentPipe",function(){return je}),n.d(e,"SlicePipe",function(){return Ye}),n.d(e,"UpperCasePipe",function(){return Ne}),n.d(e,"TitleCasePipe",function(){return ke}),n.d(e,"KeyValuePipe",function(){return Pe}),n.d(e,"DeprecatedDatePipe",function(){return ge}),n.d(e,"DeprecatedCurrencyPipe",function(){return _e}),n.d(e,"DeprecatedDecimalPipe",function(){return ye}),n.d(e,"DeprecatedPercentPipe",function(){return ve}),n.d(e,"\u0275PLATFORM_BROWSER_ID",function(){return We}),n.d(e,"\u0275PLATFORM_SERVER_ID",function(){return Ke}),n.d(e,"\u0275PLATFORM_WORKER_APP_ID",function(){return $e}),n.d(e,"\u0275PLATFORM_WORKER_UI_ID",function(){return Ze}),n.d(e,"isPlatformBrowser",function(){return Xe}),n.d(e,"isPlatformServer",function(){return Je}),n.d(e,"isPlatformWorkerApp",function(){return Qe}),n.d(e,"isPlatformWorkerUi",function(){return tn}),n.d(e,"VERSION",function(){return en}),n.d(e,"ViewportScroller",function(){return nn}),n.d(e,"\u0275NullViewportScroller",function(){return rn}),n.d(e,"PlatformLocation",function(){return i}),n.d(e,"LOCATION_INITIALIZED",function(){return s}),n.d(e,"LocationStrategy",function(){return o}),n.d(e,"APP_BASE_HREF",function(){return u}),n.d(e,"HashLocationStrategy",function(){return d}),n.d(e,"PathLocationStrategy",function(){return f}),n.d(e,"Location",function(){return c});var a=n("CcnG"),r=n("mrSG"),i=function(){return function(){}}(),s=new a.InjectionToken("Location Initialized"),o=function(){return function(){}}(),u=new a.InjectionToken("appBaseHref"),c=function(){function t(t){var n=this;this._subject=new a.EventEmitter,this._platformStrategy=t;var r=this._platformStrategy.getBaseHref();this._baseHref=e.stripTrailingSlash(l(r)),this._platformStrategy.onPopState(function(t){n._subject.emit({url:n.path(!0),pop:!0,state:t.state,type:t.type})})}var e;return e=t,t.prototype.path=function(t){return void 0===t&&(t=!1),this.normalize(this._platformStrategy.path(t))},t.prototype.isCurrentPathEqualTo=function(t,n){return void 0===n&&(n=""),this.path()==this.normalize(t+e.normalizeQueryParams(n))},t.prototype.normalize=function(t){return e.stripTrailingSlash(function(t,e){return t&&e.startsWith(t)?e.substring(t.length):e}(this._baseHref,l(t)))},t.prototype.prepareExternalUrl=function(t){return t&&"/"!==t[0]&&(t="/"+t),this._platformStrategy.prepareExternalUrl(t)},t.prototype.go=function(t,e,n){void 0===e&&(e=""),void 0===n&&(n=null),this._platformStrategy.pushState(n,"",t,e)},t.prototype.replaceState=function(t,e,n){void 0===e&&(e=""),void 0===n&&(n=null),this._platformStrategy.replaceState(n,"",t,e)},t.prototype.forward=function(){this._platformStrategy.forward()},t.prototype.back=function(){this._platformStrategy.back()},t.prototype.subscribe=function(t,e,n){return this._subject.subscribe({next:t,error:e,complete:n})},t.normalizeQueryParams=function(t){return t&&"?"!==t[0]?"?"+t:t},t.joinWithSlash=function(t,e){if(0==t.length)return e;if(0==e.length)return t;var n=0;return t.endsWith("/")&&n++,e.startsWith("/")&&n++,2==n?t+e.substring(1):1==n?t+e:t+"/"+e},t.stripTrailingSlash=function(t){var e=t.match(/#|\?|$/),n=e&&e.index||t.length;return t.slice(0,n-("/"===t[n-1]?1:0))+t.slice(n)},t}();function l(t){return t.replace(/\/index.html$/,"")}var d=function(t){function e(e,n){var a=t.call(this)||this;return a._platformLocation=e,a._baseHref="",null!=n&&(a._baseHref=n),a}return Object(r.__extends)(e,t),e.prototype.onPopState=function(t){this._platformLocation.onPopState(t),this._platformLocation.onHashChange(t)},e.prototype.getBaseHref=function(){return this._baseHref},e.prototype.path=function(t){void 0===t&&(t=!1);var e=this._platformLocation.hash;return null==e&&(e="#"),e.length>0?e.substring(1):e},e.prototype.prepareExternalUrl=function(t){var e=c.joinWithSlash(this._baseHref,t);return e.length>0?"#"+e:e},e.prototype.pushState=function(t,e,n,a){var r=this.prepareExternalUrl(n+c.normalizeQueryParams(a));0==r.length&&(r=this._platformLocation.pathname),this._platformLocation.pushState(t,e,r)},e.prototype.replaceState=function(t,e,n,a){var r=this.prepareExternalUrl(n+c.normalizeQueryParams(a));0==r.length&&(r=this._platformLocation.pathname),this._platformLocation.replaceState(t,e,r)},e.prototype.forward=function(){this._platformLocation.forward()},e.prototype.back=function(){this._platformLocation.back()},e}(o),f=function(t){function e(e,n){var a=t.call(this)||this;if(a._platformLocation=e,null==n&&(n=a._platformLocation.getBaseHrefFromDOM()),null==n)throw new Error("No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.");return a._baseHref=n,a}return Object(r.__extends)(e,t),e.prototype.onPopState=function(t){this._platformLocation.onPopState(t),this._platformLocation.onHashChange(t)},e.prototype.getBaseHref=function(){return this._baseHref},e.prototype.prepareExternalUrl=function(t){return c.joinWithSlash(this._baseHref,t)},e.prototype.path=function(t){void 0===t&&(t=!1);var e=this._platformLocation.pathname+c.normalizeQueryParams(this._platformLocation.search),n=this._platformLocation.hash;return n&&t?""+e+n:e},e.prototype.pushState=function(t,e,n,a){var r=this.prepareExternalUrl(n+c.normalizeQueryParams(a));this._platformLocation.pushState(t,e,r)},e.prototype.replaceState=function(t,e,n,a){var r=this.prepareExternalUrl(n+c.normalizeQueryParams(a));this._platformLocation.replaceState(t,e,r)},e.prototype.forward=function(){this._platformLocation.forward()},e.prototype.back=function(){this._platformLocation.back()},e}(o),p=void 0,h=["en",[["a","p"],["AM","PM"],p],[["AM","PM"],p,p],[["S","M","T","W","T","F","S"],["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],["Su","Mo","Tu","We","Th","Fr","Sa"]],p,[["J","F","M","A","M","J","J","A","S","O","N","D"],["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],["January","February","March","April","May","June","July","August","September","October","November","December"]],p,[["B","A"],["BC","AD"],["Before Christ","Anno Domini"]],0,[6,0],["M/d/yy","MMM d, y","MMMM d, y","EEEE, MMMM d, y"],["h:mm a","h:mm:ss a","h:mm:ss a z","h:mm:ss a zzzz"],["{1}, {0}",p,"{1} 'at' {0}",p],[".",",",";","%","+","-","E","\xd7","\u2030","\u221e","NaN",":"],["#,##0.###","#,##0%","\xa4#,##0.00","#E0"],"$","US Dollar",{},function(t){var e=Math.floor(Math.abs(t)),n=t.toString().replace(/^[^.]*\.?/,"").length;return 1===e&&0===n?1:5}],g={};function b(t,e,n){"string"!=typeof e&&(n=e,e=t[0]),e=e.toLowerCase().replace(/_/g,"-"),g[e]=t,n&&(g[e][19]=n)}var m={ADP:[void 0,void 0,0],AFN:[void 0,void 0,0],ALL:[void 0,void 0,0],AMD:[void 0,void 0,0],AOA:[void 0,"Kz"],ARS:[void 0,"$"],AUD:["A$","$"],BAM:[void 0,"KM"],BBD:[void 0,"$"],BDT:[void 0,"\u09f3"],BHD:[void 0,void 0,3],BIF:[void 0,void 0,0],BMD:[void 0,"$"],BND:[void 0,"$"],BOB:[void 0,"Bs"],BRL:["R$"],BSD:[void 0,"$"],BWP:[void 0,"P"],BYN:[void 0,"\u0440.",2],BYR:[void 0,void 0,0],BZD:[void 0,"$"],CAD:["CA$","$",2],CHF:[void 0,void 0,2],CLF:[void 0,void 0,4],CLP:[void 0,"$",0],CNY:["CN\xa5","\xa5"],COP:[void 0,"$",0],CRC:[void 0,"\u20a1",2],CUC:[void 0,"$"],CUP:[void 0,"$"],CZK:[void 0,"K\u010d",2],DJF:[void 0,void 0,0],DKK:[void 0,"kr",2],DOP:[void 0,"$"],EGP:[void 0,"E\xa3"],ESP:[void 0,"\u20a7",0],EUR:["\u20ac"],FJD:[void 0,"$"],FKP:[void 0,"\xa3"],GBP:["\xa3"],GEL:[void 0,"\u20be"],GIP:[void 0,"\xa3"],GNF:[void 0,"FG",0],GTQ:[void 0,"Q"],GYD:[void 0,"$",0],HKD:["HK$","$"],HNL:[void 0,"L"],HRK:[void 0,"kn"],HUF:[void 0,"Ft",2],IDR:[void 0,"Rp",0],ILS:["\u20aa"],INR:["\u20b9"],IQD:[void 0,void 0,0],IRR:[void 0,void 0,0],ISK:[void 0,"kr",0],ITL:[void 0,void 0,0],JMD:[void 0,"$"],JOD:[void 0,void 0,3],JPY:["\xa5",void 0,0],KHR:[void 0,"\u17db"],KMF:[void 0,"CF",0],KPW:[void 0,"\u20a9",0],KRW:["\u20a9",void 0,0],KWD:[void 0,void 0,3],KYD:[void 0,"$"],KZT:[void 0,"\u20b8"],LAK:[void 0,"\u20ad",0],LBP:[void 0,"L\xa3",0],LKR:[void 0,"Rs"],LRD:[void 0,"$"],LTL:[void 0,"Lt"],LUF:[void 0,void 0,0],LVL:[void 0,"Ls"],LYD:[void 0,void 0,3],MGA:[void 0,"Ar",0],MGF:[void 0,void 0,0],MMK:[void 0,"K",0],MNT:[void 0,"\u20ae",0],MRO:[void 0,void 0,0],MUR:[void 0,"Rs",0],MXN:["MX$","$"],MYR:[void 0,"RM"],NAD:[void 0,"$"],NGN:[void 0,"\u20a6"],NIO:[void 0,"C$"],NOK:[void 0,"kr",2],NPR:[void 0,"Rs"],NZD:["NZ$","$"],OMR:[void 0,void 0,3],PHP:[void 0,"\u20b1"],PKR:[void 0,"Rs",0],PLN:[void 0,"z\u0142"],PYG:[void 0,"\u20b2",0],RON:[void 0,"lei"],RSD:[void 0,void 0,0],RUB:[void 0,"\u20bd"],RUR:[void 0,"\u0440."],RWF:[void 0,"RF",0],SBD:[void 0,"$"],SEK:[void 0,"kr",2],SGD:[void 0,"$"],SHP:[void 0,"\xa3"],SLL:[void 0,void 0,0],SOS:[void 0,void 0,0],SRD:[void 0,"$"],SSP:[void 0,"\xa3"],STD:[void 0,void 0,0],STN:[void 0,"Db"],SYP:[void 0,"\xa3",0],THB:[void 0,"\u0e3f"],TMM:[void 0,void 0,0],TND:[void 0,void 0,3],TOP:[void 0,"T$"],TRL:[void 0,void 0,0],TRY:[void 0,"\u20ba"],TTD:[void 0,"$"],TWD:["NT$","$",2],TZS:[void 0,void 0,0],UAH:[void 0,"\u20b4"],UGX:[void 0,void 0,0],USD:["$"],UYI:[void 0,void 0,0],UYU:[void 0,"$"],UZS:[void 0,void 0,0],VEF:[void 0,"Bs"],VND:["\u20ab",void 0,0],VUV:[void 0,void 0,0],XAF:["FCFA",void 0,0],XCD:["EC$","$"],XOF:["CFA",void 0,0],XPF:["CFPF",void 0,0],YER:[void 0,void 0,0],ZAR:[void 0,"R"],ZMK:[void 0,void 0,0],ZMW:[void 0,"ZK"],ZWD:[void 0,void 0,0]},y=function(t){return t[t.Decimal=0]="Decimal",t[t.Percent=1]="Percent",t[t.Currency=2]="Currency",t[t.Scientific=3]="Scientific",t}({}),v=function(t){return t[t.Zero=0]="Zero",t[t.One=1]="One",t[t.Two=2]="Two",t[t.Few=3]="Few",t[t.Many=4]="Many",t[t.Other=5]="Other",t}({}),_=function(t){return t[t.Format=0]="Format",t[t.Standalone=1]="Standalone",t}({}),x=function(t){return t[t.Narrow=0]="Narrow",t[t.Abbreviated=1]="Abbreviated",t[t.Wide=2]="Wide",t[t.Short=3]="Short",t}({}),T=function(t){return t[t.Short=0]="Short",t[t.Medium=1]="Medium",t[t.Long=2]="Long",t[t.Full=3]="Full",t}({}),w=function(t){return t[t.Decimal=0]="Decimal",t[t.Group=1]="Group",t[t.List=2]="List",t[t.PercentSign=3]="PercentSign",t[t.PlusSign=4]="PlusSign",t[t.MinusSign=5]="MinusSign",t[t.Exponential=6]="Exponential",t[t.SuperscriptingExponent=7]="SuperscriptingExponent",t[t.PerMille=8]="PerMille",t[t[1/0]=9]="Infinity",t[t.NaN=10]="NaN",t[t.TimeSeparator=11]="TimeSeparator",t[t.CurrencyDecimal=12]="CurrencyDecimal",t[t.CurrencyGroup=13]="CurrencyGroup",t}({}),S=function(t){return t[t.Sunday=0]="Sunday",t[t.Monday=1]="Monday",t[t.Tuesday=2]="Tuesday",t[t.Wednesday=3]="Wednesday",t[t.Thursday=4]="Thursday",t[t.Friday=5]="Friday",t[t.Saturday=6]="Saturday",t}({});function O(t){return B(t)[0]}function I(t,e,n){var a=B(t),r=V([a[1],a[2]],e);return V(r,n)}function C(t,e,n){var a=B(t),r=V([a[3],a[4]],e);return V(r,n)}function k(t,e,n){var a=B(t),r=V([a[5],a[6]],e);return V(r,n)}function N(t,e){return V(B(t)[7],e)}function R(t){return B(t)[8]}function A(t){return B(t)[9]}function D(t,e){return V(B(t)[10],e)}function E(t,e){return V(B(t)[11],e)}function L(t,e){return V(B(t)[12],e)}function P(t,e){var n=B(t),a=n[13][e];if(void 0===a){if(e===w.CurrencyDecimal)return n[13][w.Decimal];if(e===w.CurrencyGroup)return n[13][w.Group]}return a}function M(t,e){return B(t)[14][e]}function q(t){return B(t)[15]||null}function j(t){return B(t)[16]||null}function F(t){return B(t)[18]}function z(t){if(!t[19])throw new Error('Missing extra locale data for the locale "'+t[0]+'". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.')}function G(t){var e=B(t);return z(e),(e[19][2]||[]).map(function(t){return"string"==typeof t?H(t):[H(t[0]),H(t[1])]})}function Y(t,e,n){var a=B(t);z(a);var r=V([a[19][0],a[19][1]],e)||[];return V(r,n)||[]}function V(t,e){for(var n=e;n>-1;n--)if(void 0!==t[n])return t[n];throw new Error("Locale data API: locale data undefined")}function H(t){var e=Object(r.__read)(t.split(":"),2);return{hours:+e[0],minutes:+e[1]}}function B(t){var e=t.toLowerCase().replace(/_/g,"-"),n=g[e];if(n)return n;var a=e.split("-")[0];if(n=g[a])return n;if("en"===a)return h;throw new Error('Missing locale data for the locale "'+t+'".')}function U(t,e,n){void 0===n&&(n="en");var a=function(t){return B(t)[17]}(n)[t]||m[t]||[],r=a[1];return"narrow"===e&&"string"==typeof r?r:a[0]||t}var W=2;function K(t){var e,n=m[t];return n&&(e=n[2]),"number"==typeof e?e:W}var $=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/,Z={},X=/((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/,J=function(t){return t[t.Short=0]="Short",t[t.ShortGMT=1]="ShortGMT",t[t.Long=2]="Long",t[t.Extended=3]="Extended",t}({}),Q=function(t){return t[t.FullYear=0]="FullYear",t[t.Month=1]="Month",t[t.Date=2]="Date",t[t.Hours=3]="Hours",t[t.Minutes=4]="Minutes",t[t.Seconds=5]="Seconds",t[t.FractionalSeconds=6]="FractionalSeconds",t[t.Day=7]="Day",t}({}),tt=function(t){return t[t.DayPeriods=0]="DayPeriods",t[t.Days=1]="Days",t[t.Months=2]="Months",t[t.Eras=3]="Eras",t}({});function et(t,e,n,a){var i=function(t){if(pt(t))return t;if("number"==typeof t&&!isNaN(t))return new Date(t);if("string"==typeof t){t=t.trim();var e,n=parseFloat(t);if(!isNaN(t-n))return new Date(n);if(/^(\d{4}-\d{1,2}-\d{1,2})$/.test(t)){var a=Object(r.__read)(t.split("-").map(function(t){return+t}),3);return new Date(a[0],a[1]-1,a[2])}if(e=t.match($))return ft(e)}var i=new Date(t);if(!pt(i))throw new Error('Unable to convert "'+t+'" into a date');return i}(t);e=function t(e,n){var a=O(e);if(Z[a]=Z[a]||{},Z[a][n])return Z[a][n];var r="";switch(n){case"shortDate":r=D(e,T.Short);break;case"mediumDate":r=D(e,T.Medium);break;case"longDate":r=D(e,T.Long);break;case"fullDate":r=D(e,T.Full);break;case"shortTime":r=E(e,T.Short);break;case"mediumTime":r=E(e,T.Medium);break;case"longTime":r=E(e,T.Long);break;case"fullTime":r=E(e,T.Full);break;case"short":var i=t(e,"shortTime"),s=t(e,"shortDate");r=nt(L(e,T.Short),[i,s]);break;case"medium":var o=t(e,"mediumTime"),u=t(e,"mediumDate");r=nt(L(e,T.Medium),[o,u]);break;case"long":var c=t(e,"longTime"),l=t(e,"longDate");r=nt(L(e,T.Long),[c,l]);break;case"full":var d=t(e,"fullTime"),f=t(e,"fullDate");r=nt(L(e,T.Full),[d,f])}return r&&(Z[a][n]=r),r}(n,e)||e;for(var s,o=[];e;){if(!(s=X.exec(e))){o.push(e);break}var u=(o=o.concat(s.slice(1))).pop();if(!u)break;e=u}var c=i.getTimezoneOffset();a&&(c=dt(a,c),i=function(t,e,n){var a=t.getTimezoneOffset();return function(t,e){return(t=new Date(t.getTime())).setMinutes(t.getMinutes()+e),t}(t,-1*(dt(e,a)-a))}(i,a));var l="";return o.forEach(function(t){var e=function(t){if(lt[t])return lt[t];var e;switch(t){case"G":case"GG":case"GGG":e=it(tt.Eras,x.Abbreviated);break;case"GGGG":e=it(tt.Eras,x.Wide);break;case"GGGGG":e=it(tt.Eras,x.Narrow);break;case"y":e=rt(Q.FullYear,1,0,!1,!0);break;case"yy":e=rt(Q.FullYear,2,0,!0,!0);break;case"yyy":e=rt(Q.FullYear,3,0,!1,!0);break;case"yyyy":e=rt(Q.FullYear,4,0,!1,!0);break;case"M":case"L":e=rt(Q.Month,1,1);break;case"MM":case"LL":e=rt(Q.Month,2,1);break;case"MMM":e=it(tt.Months,x.Abbreviated);break;case"MMMM":e=it(tt.Months,x.Wide);break;case"MMMMM":e=it(tt.Months,x.Narrow);break;case"LLL":e=it(tt.Months,x.Abbreviated,_.Standalone);break;case"LLLL":e=it(tt.Months,x.Wide,_.Standalone);break;case"LLLLL":e=it(tt.Months,x.Narrow,_.Standalone);break;case"w":e=ct(1);break;case"ww":e=ct(2);break;case"W":e=ct(1,!0);break;case"d":e=rt(Q.Date,1);break;case"dd":e=rt(Q.Date,2);break;case"E":case"EE":case"EEE":e=it(tt.Days,x.Abbreviated);break;case"EEEE":e=it(tt.Days,x.Wide);break;case"EEEEE":e=it(tt.Days,x.Narrow);break;case"EEEEEE":e=it(tt.Days,x.Short);break;case"a":case"aa":case"aaa":e=it(tt.DayPeriods,x.Abbreviated);break;case"aaaa":e=it(tt.DayPeriods,x.Wide);break;case"aaaaa":e=it(tt.DayPeriods,x.Narrow);break;case"b":case"bb":case"bbb":e=it(tt.DayPeriods,x.Abbreviated,_.Standalone,!0);break;case"bbbb":e=it(tt.DayPeriods,x.Wide,_.Standalone,!0);break;case"bbbbb":e=it(tt.DayPeriods,x.Narrow,_.Standalone,!0);break;case"B":case"BB":case"BBB":e=it(tt.DayPeriods,x.Abbreviated,_.Format,!0);break;case"BBBB":e=it(tt.DayPeriods,x.Wide,_.Format,!0);break;case"BBBBB":e=it(tt.DayPeriods,x.Narrow,_.Format,!0);break;case"h":e=rt(Q.Hours,1,-12);break;case"hh":e=rt(Q.Hours,2,-12);break;case"H":e=rt(Q.Hours,1);break;case"HH":e=rt(Q.Hours,2);break;case"m":e=rt(Q.Minutes,1);break;case"mm":e=rt(Q.Minutes,2);break;case"s":e=rt(Q.Seconds,1);break;case"ss":e=rt(Q.Seconds,2);break;case"S":e=rt(Q.FractionalSeconds,1);break;case"SS":e=rt(Q.FractionalSeconds,2);break;case"SSS":e=rt(Q.FractionalSeconds,3);break;case"Z":case"ZZ":case"ZZZ":e=st(J.Short);break;case"ZZZZZ":e=st(J.Extended);break;case"O":case"OO":case"OOO":case"z":case"zz":case"zzz":e=st(J.ShortGMT);break;case"OOOO":case"ZZZZ":case"zzzz":e=st(J.Long);break;default:return null}return lt[t]=e,e}(t);l+=e?e(i,n,c):"''"===t?"'":t.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),l}function nt(t,e){return e&&(t=t.replace(/\{([^}]+)}/g,function(t,n){return null!=e&&n in e?e[n]:t})),t}function at(t,e,n,a,r){void 0===n&&(n="-");var i="";(t<0||r&&t<=0)&&(r?t=1-t:(t=-t,i=n));for(var s=String(t);s.length<e;)s="0"+s;return a&&(s=s.substr(s.length-e)),i+s}function rt(t,e,n,a,r){return void 0===n&&(n=0),void 0===a&&(a=!1),void 0===r&&(r=!1),function(i,s){var o,u=function(t,e){switch(t){case Q.FullYear:return e.getFullYear();case Q.Month:return e.getMonth();case Q.Date:return e.getDate();case Q.Hours:return e.getHours();case Q.Minutes:return e.getMinutes();case Q.Seconds:return e.getSeconds();case Q.FractionalSeconds:return e.getMilliseconds();case Q.Day:return e.getDay();default:throw new Error('Unknown DateType value "'+t+'".')}}(t,i);if((n>0||u>-n)&&(u+=n),t===Q.Hours)0===u&&-12===n&&(u=12);else if(t===Q.FractionalSeconds)return o=e,at(u,3).substr(0,o);var c=P(s,w.MinusSign);return at(u,e,c,a,r)}}function it(t,e,n,a){return void 0===n&&(n=_.Format),void 0===a&&(a=!1),function(r,i){return function(t,e,n,a,r,i){switch(n){case tt.Months:return k(e,r,a)[t.getMonth()];case tt.Days:return C(e,r,a)[t.getDay()];case tt.DayPeriods:var s=t.getHours(),o=t.getMinutes();if(i){var u,c=G(e),l=Y(e,r,a);if(c.forEach(function(t,e){if(Array.isArray(t)){var n=t[0],a=t[1],r=a.hours;s>=n.hours&&o>=n.minutes&&(s<r||s===r&&o<a.minutes)&&(u=l[e])}else t.hours===s&&t.minutes===o&&(u=l[e])}),u)return u}return I(e,r,a)[s<12?0:1];case tt.Eras:return N(e,a)[t.getFullYear()<=0?0:1];default:throw new Error("unexpected translation type "+n)}}(r,i,t,e,n,a)}}function st(t){return function(e,n,a){var r=-1*a,i=P(n,w.MinusSign),s=r>0?Math.floor(r/60):Math.ceil(r/60);switch(t){case J.Short:return(r>=0?"+":"")+at(s,2,i)+at(Math.abs(r%60),2,i);case J.ShortGMT:return"GMT"+(r>=0?"+":"")+at(s,1,i);case J.Long:return"GMT"+(r>=0?"+":"")+at(s,2,i)+":"+at(Math.abs(r%60),2,i);case J.Extended:return 0===a?"Z":(r>=0?"+":"")+at(s,2,i)+":"+at(Math.abs(r%60),2,i);default:throw new Error('Unknown zone width "'+t+'"')}}}var ot=0,ut=4;function ct(t,e){return void 0===e&&(e=!1),function(n,a){var r,i,s,o;if(e){var u=new Date(n.getFullYear(),n.getMonth(),1).getDay()-1,c=n.getDate();r=1+Math.floor((c+u)/7)}else{var l=(s=n.getFullYear(),o=new Date(s,ot,1).getDay(),new Date(s,0,1+(o<=ut?ut:ut+7)-o)),d=(i=n,new Date(i.getFullYear(),i.getMonth(),i.getDate()+(ut-i.getDay()))).getTime()-l.getTime();r=1+Math.round(d/6048e5)}return at(r,t,P(a,w.MinusSign))}}var lt={};function dt(t,e){t=t.replace(/:/g,"");var n=Date.parse("Jan 01, 1970 00:00:00 "+t)/6e4;return isNaN(n)?e:n}function ft(t){var e=new Date(0),n=0,a=0,r=t[8]?e.setUTCFullYear:e.setFullYear,i=t[8]?e.setUTCHours:e.setHours;t[9]&&(n=Number(t[9]+t[10]),a=Number(t[9]+t[11])),r.call(e,Number(t[1]),Number(t[2])-1,Number(t[3]));var s=Number(t[4]||0)-n,o=Number(t[5]||0)-a,u=Number(t[6]||0),c=Math.round(1e3*parseFloat("0."+(t[7]||0)));return i.call(e,s,o,u,c),e}function pt(t){return t instanceof Date&&!isNaN(t.valueOf())}var ht=/^(\d+)?\.((\d+)(-(\d+))?)?$/,gt=22,bt=".",mt="0",yt=";",vt=",",_t="#",xt="\xa4",Tt="%";function wt(t,e,n,a,r,i,s){void 0===s&&(s=!1);var o="",u=!1;if(isFinite(t)){var c=function(e){var n,a,r,i,s,o=Math.abs(t)+"",u=0;for((a=o.indexOf(bt))>-1&&(o=o.replace(bt,"")),(r=o.search(/e/i))>0?(a<0&&(a=r),a+=+o.slice(r+1),o=o.substring(0,r)):a<0&&(a=o.length),r=0;o.charAt(r)===mt;r++);if(r===(s=o.length))n=[0],a=1;else{for(s--;o.charAt(s)===mt;)s--;for(a-=r,n=[],i=0;r<=s;r++,i++)n[i]=Number(o.charAt(r))}return a>gt&&(n=n.splice(0,gt-1),u=a-1,a=1),{digits:n,exponent:u,integerLen:a}}();s&&(c=function(t){if(0===t.digits[0])return t;var e=t.digits.length-t.integerLen;return t.exponent?t.exponent+=2:(0===e?t.digits.push(0,0):1===e&&t.digits.push(0),t.integerLen+=2),t}(c));var l=e.minInt,d=e.minFrac,f=e.maxFrac;if(i){var p=i.match(ht);if(null===p)throw new Error(i+" is not a valid digit info");var h=p[1],g=p[3],b=p[5];null!=h&&(l=kt(h)),null!=g&&(d=kt(g)),null!=b?f=kt(b):null!=g&&d>f&&(f=d)}!function(t,e,n){if(e>n)throw new Error("The minimum number of digits after fraction ("+e+") is higher than the maximum ("+n+").");var a=t.digits,r=a.length-t.integerLen,i=Math.min(Math.max(e,r),n),s=i+t.integerLen,o=a[s];if(s>0){a.splice(Math.max(t.integerLen,s));for(var u=s;u<a.length;u++)a[u]=0}else{r=Math.max(0,r),t.integerLen=1,a.length=Math.max(1,s=i+1),a[0]=0;for(var c=1;c<s;c++)a[c]=0}if(o>=5)if(s-1<0){for(var l=0;l>s;l--)a.unshift(0),t.integerLen++;a.unshift(1),t.integerLen++}else a[s-1]++;for(;r<Math.max(0,i);r++)a.push(0);var d=0!==i,f=e+t.integerLen,p=a.reduceRight(function(t,e,n,a){return a[n]=(e+=t)<10?e:e-10,d&&(0===a[n]&&n>=f?a.pop():d=!1),e>=10?1:0},0);p&&(a.unshift(p),t.integerLen++)}(c,d,f);var m=c.digits,y=c.integerLen,v=c.exponent,_=[];for(u=m.every(function(t){return!t});y<l;y++)m.unshift(0);for(;y<0;y++)m.unshift(0);y>0?_=m.splice(y,m.length):(_=m,m=[0]);var x=[];for(m.length>=e.lgSize&&x.unshift(m.splice(-e.lgSize,m.length).join(""));m.length>e.gSize;)x.unshift(m.splice(-e.gSize,m.length).join(""));m.length&&x.unshift(m.join("")),o=x.join(P(n,a)),_.length&&(o+=P(n,r)+_.join("")),v&&(o+=P(n,w.Exponential)+"+"+v)}else o=P(n,w.Infinity);return t<0&&!u?e.negPre+o+e.negSuf:e.posPre+o+e.posSuf}function St(t,e,n,a,r){var i=Ct(M(e,y.Currency),P(e,w.MinusSign));return i.minFrac=K(a),i.maxFrac=i.minFrac,wt(t,i,e,w.CurrencyGroup,w.CurrencyDecimal,r).replace(xt,n).replace(xt,"")}function Ot(t,e,n){return wt(t,Ct(M(e,y.Percent),P(e,w.MinusSign)),e,w.Group,w.Decimal,n,!0).replace(new RegExp(Tt,"g"),P(e,w.PercentSign))}function It(t,e,n){return wt(t,Ct(M(e,y.Decimal),P(e,w.MinusSign)),e,w.Group,w.Decimal,n)}function Ct(t,e){void 0===e&&(e="-");var n={minInt:1,minFrac:0,maxFrac:0,posPre:"",posSuf:"",negPre:"",negSuf:"",gSize:0,lgSize:0},a=t.split(yt),r=a[0],i=a[1],s=-1!==r.indexOf(bt)?r.split(bt):[r.substring(0,r.lastIndexOf(mt)+1),r.substring(r.lastIndexOf(mt)+1)],o=s[0],u=s[1]||"";n.posPre=o.substr(0,o.indexOf(_t));for(var c=0;c<u.length;c++){var l=u.charAt(c);l===mt?n.minFrac=n.maxFrac=c+1:l===_t?n.maxFrac=c+1:n.posSuf+=l}var d=o.split(vt);if(n.gSize=d[1]?d[1].length:0,n.lgSize=d[2]||d[1]?(d[2]||d[1]).length:0,i){var f=r.length-n.posPre.length-n.posSuf.length,p=i.indexOf(_t);n.negPre=i.substr(0,p).replace(/'/g,""),n.negSuf=i.substr(p+f).replace(/'/g,"")}else n.negPre=e+n.posPre,n.negSuf=n.posSuf;return n}function kt(t){var e=parseInt(t);if(isNaN(e))throw new Error("Invalid integer literal when parsing "+t);return e}var Nt=new a.InjectionToken("UseV4Plurals"),Rt=function(){return function(){}}();function At(t,e,n,a){var r="="+t;if(e.indexOf(r)>-1)return r;if(r=n.getPluralCategory(t,a),e.indexOf(r)>-1)return r;if(e.indexOf("other")>-1)return"other";throw new Error('No plural message found for value "'+t+'"')}var Dt=function(t){function e(e,n){var a=t.call(this)||this;return a.locale=e,a.deprecatedPluralFn=n,a}return Object(r.__extends)(e,t),e.prototype.getPluralCategory=function(t,e){switch(this.deprecatedPluralFn?this.deprecatedPluralFn(e||this.locale,t):F(e||this.locale)(t)){case v.Zero:return"zero";case v.One:return"one";case v.Two:return"two";case v.Few:return"few";case v.Many:return"many";default:return"other"}},e}(Rt);function Et(t,e){"string"==typeof e&&(e=parseInt(e,10));var n=e,a=n.toString().replace(/^[^.]*\.?/,""),r=Math.floor(Math.abs(n)),i=a.length,s=parseInt(a,10),o=parseInt(n.toString().replace(/^[^.]*\.?|0+$/g,""),10)||0;switch(t.split("-")[0].toLowerCase()){case"af":case"asa":case"az":case"bem":case"bez":case"bg":case"brx":case"ce":case"cgg":case"chr":case"ckb":case"ee":case"el":case"eo":case"es":case"eu":case"fo":case"fur":case"gsw":case"ha":case"haw":case"hu":case"jgo":case"jmc":case"ka":case"kk":case"kkj":case"kl":case"ks":case"ksb":case"ky":case"lb":case"lg":case"mas":case"mgo":case"ml":case"mn":case"nb":case"nd":case"ne":case"nn":case"nnh":case"nyn":case"om":case"or":case"os":case"ps":case"rm":case"rof":case"rwk":case"saq":case"seh":case"sn":case"so":case"sq":case"ta":case"te":case"teo":case"tk":case"tr":case"ug":case"uz":case"vo":case"vun":case"wae":case"xog":return 1===n?v.One:v.Other;case"ak":case"ln":case"mg":case"pa":case"ti":return n===Math.floor(n)&&n>=0&&n<=1?v.One:v.Other;case"am":case"as":case"bn":case"fa":case"gu":case"hi":case"kn":case"mr":case"zu":return 0===r||1===n?v.One:v.Other;case"ar":return 0===n?v.Zero:1===n?v.One:2===n?v.Two:n%100===Math.floor(n%100)&&n%100>=3&&n%100<=10?v.Few:n%100===Math.floor(n%100)&&n%100>=11&&n%100<=99?v.Many:v.Other;case"ast":case"ca":case"de":case"en":case"et":case"fi":case"fy":case"gl":case"it":case"nl":case"sv":case"sw":case"ur":case"yi":return 1===r&&0===i?v.One:v.Other;case"be":return n%10==1&&n%100!=11?v.One:n%10===Math.floor(n%10)&&n%10>=2&&n%10<=4&&!(n%100>=12&&n%100<=14)?v.Few:n%10==0||n%10===Math.floor(n%10)&&n%10>=5&&n%10<=9||n%100===Math.floor(n%100)&&n%100>=11&&n%100<=14?v.Many:v.Other;case"br":return n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?v.One:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?v.Two:n%10===Math.floor(n%10)&&(n%10>=3&&n%10<=4||n%10==9)&&!(n%100>=10&&n%100<=19||n%100>=70&&n%100<=79||n%100>=90&&n%100<=99)?v.Few:0!==n&&n%1e6==0?v.Many:v.Other;case"bs":case"hr":case"sr":return 0===i&&r%10==1&&r%100!=11||s%10==1&&s%100!=11?v.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)||s%10===Math.floor(s%10)&&s%10>=2&&s%10<=4&&!(s%100>=12&&s%100<=14)?v.Few:v.Other;case"cs":case"sk":return 1===r&&0===i?v.One:r===Math.floor(r)&&r>=2&&r<=4&&0===i?v.Few:0!==i?v.Many:v.Other;case"cy":return 0===n?v.Zero:1===n?v.One:2===n?v.Two:3===n?v.Few:6===n?v.Many:v.Other;case"da":return 1===n||0!==o&&(0===r||1===r)?v.One:v.Other;case"dsb":case"hsb":return 0===i&&r%100==1||s%100==1?v.One:0===i&&r%100==2||s%100==2?v.Two:0===i&&r%100===Math.floor(r%100)&&r%100>=3&&r%100<=4||s%100===Math.floor(s%100)&&s%100>=3&&s%100<=4?v.Few:v.Other;case"ff":case"fr":case"hy":case"kab":return 0===r||1===r?v.One:v.Other;case"fil":return 0===i&&(1===r||2===r||3===r)||0===i&&r%10!=4&&r%10!=6&&r%10!=9||0!==i&&s%10!=4&&s%10!=6&&s%10!=9?v.One:v.Other;case"ga":return 1===n?v.One:2===n?v.Two:n===Math.floor(n)&&n>=3&&n<=6?v.Few:n===Math.floor(n)&&n>=7&&n<=10?v.Many:v.Other;case"gd":return 1===n||11===n?v.One:2===n||12===n?v.Two:n===Math.floor(n)&&(n>=3&&n<=10||n>=13&&n<=19)?v.Few:v.Other;case"gv":return 0===i&&r%10==1?v.One:0===i&&r%10==2?v.Two:0!==i||r%100!=0&&r%100!=20&&r%100!=40&&r%100!=60&&r%100!=80?0!==i?v.Many:v.Other:v.Few;case"he":return 1===r&&0===i?v.One:2===r&&0===i?v.Two:0!==i||n>=0&&n<=10||n%10!=0?v.Other:v.Many;case"is":return 0===o&&r%10==1&&r%100!=11||0!==o?v.One:v.Other;case"ksh":return 0===n?v.Zero:1===n?v.One:v.Other;case"kw":case"naq":case"se":case"smn":return 1===n?v.One:2===n?v.Two:v.Other;case"lag":return 0===n?v.Zero:0!==r&&1!==r||0===n?v.Other:v.One;case"lt":return n%10!=1||n%100>=11&&n%100<=19?n%10===Math.floor(n%10)&&n%10>=2&&n%10<=9&&!(n%100>=11&&n%100<=19)?v.Few:0!==s?v.Many:v.Other:v.One;case"lv":case"prg":return n%10==0||n%100===Math.floor(n%100)&&n%100>=11&&n%100<=19||2===i&&s%100===Math.floor(s%100)&&s%100>=11&&s%100<=19?v.Zero:n%10==1&&n%100!=11||2===i&&s%10==1&&s%100!=11||2!==i&&s%10==1?v.One:v.Other;case"mk":return 0===i&&r%10==1||s%10==1?v.One:v.Other;case"mt":return 1===n?v.One:0===n||n%100===Math.floor(n%100)&&n%100>=2&&n%100<=10?v.Few:n%100===Math.floor(n%100)&&n%100>=11&&n%100<=19?v.Many:v.Other;case"pl":return 1===r&&0===i?v.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)?v.Few:0===i&&1!==r&&r%10===Math.floor(r%10)&&r%10>=0&&r%10<=1||0===i&&r%10===Math.floor(r%10)&&r%10>=5&&r%10<=9||0===i&&r%100===Math.floor(r%100)&&r%100>=12&&r%100<=14?v.Many:v.Other;case"pt":return n===Math.floor(n)&&n>=0&&n<=2&&2!==n?v.One:v.Other;case"ro":return 1===r&&0===i?v.One:0!==i||0===n||1!==n&&n%100===Math.floor(n%100)&&n%100>=1&&n%100<=19?v.Few:v.Other;case"ru":case"uk":return 0===i&&r%10==1&&r%100!=11?v.One:0===i&&r%10===Math.floor(r%10)&&r%10>=2&&r%10<=4&&!(r%100>=12&&r%100<=14)?v.Few:0===i&&r%10==0||0===i&&r%10===Math.floor(r%10)&&r%10>=5&&r%10<=9||0===i&&r%100===Math.floor(r%100)&&r%100>=11&&r%100<=14?v.Many:v.Other;case"shi":return 0===r||1===n?v.One:n===Math.floor(n)&&n>=2&&n<=10?v.Few:v.Other;case"si":return 0===n||1===n||0===r&&1===s?v.One:v.Other;case"sl":return 0===i&&r%100==1?v.One:0===i&&r%100==2?v.Two:0===i&&r%100===Math.floor(r%100)&&r%100>=3&&r%100<=4||0!==i?v.Few:v.Other;case"tzm":return n===Math.floor(n)&&n>=0&&n<=1||n===Math.floor(n)&&n>=11&&n<=99?v.One:v.Other;default:return v.Other}}function Lt(t,e){var n,a;e=encodeURIComponent(e);try{for(var i=Object(r.__values)(t.split(";")),s=i.next();!s.done;s=i.next()){var o=s.value,u=o.indexOf("="),c=Object(r.__read)(-1==u?[o,""]:[o.slice(0,u),o.slice(u+1)],2),l=c[1];if(c[0].trim()===e)return decodeURIComponent(l)}}catch(d){n={error:d}}finally{try{s&&!s.done&&(a=i.return)&&a.call(i)}finally{if(n)throw n.error}}return null}var Pt=function(){function t(t,e,n,a){this._iterableDiffers=t,this._keyValueDiffers=e,this._ngEl=n,this._renderer=a,this._initialClasses=[]}return Object.defineProperty(t.prototype,"klass",{set:function(t){this._removeClasses(this._initialClasses),this._initialClasses="string"==typeof t?t.split(/\s+/):[],this._applyClasses(this._initialClasses),this._applyClasses(this._rawClass)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClass",{set:function(t){this._removeClasses(this._rawClass),this._applyClasses(this._initialClasses),this._iterableDiffer=null,this._keyValueDiffer=null,this._rawClass="string"==typeof t?t.split(/\s+/):t,this._rawClass&&(Object(a["\u0275isListLikeIterable"])(this._rawClass)?this._iterableDiffer=this._iterableDiffers.find(this._rawClass).create():this._keyValueDiffer=this._keyValueDiffers.find(this._rawClass).create())},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){if(this._iterableDiffer){var t=this._iterableDiffer.diff(this._rawClass);t&&this._applyIterableChanges(t)}else if(this._keyValueDiffer){var e=this._keyValueDiffer.diff(this._rawClass);e&&this._applyKeyValueChanges(e)}},t.prototype._applyKeyValueChanges=function(t){var e=this;t.forEachAddedItem(function(t){return e._toggleClass(t.key,t.currentValue)}),t.forEachChangedItem(function(t){return e._toggleClass(t.key,t.currentValue)}),t.forEachRemovedItem(function(t){t.previousValue&&e._toggleClass(t.key,!1)})},t.prototype._applyIterableChanges=function(t){var e=this;t.forEachAddedItem(function(t){if("string"!=typeof t.item)throw new Error("NgClass can only toggle CSS classes expressed as strings, got "+Object(a["\u0275stringify"])(t.item));e._toggleClass(t.item,!0)}),t.forEachRemovedItem(function(t){return e._toggleClass(t.item,!1)})},t.prototype._applyClasses=function(t){var e=this;t&&(Array.isArray(t)||t instanceof Set?t.forEach(function(t){return e._toggleClass(t,!0)}):Object.keys(t).forEach(function(n){return e._toggleClass(n,!!t[n])}))},t.prototype._removeClasses=function(t){var e=this;t&&(Array.isArray(t)||t instanceof Set?t.forEach(function(t){return e._toggleClass(t,!1)}):Object.keys(t).forEach(function(t){return e._toggleClass(t,!1)}))},t.prototype._toggleClass=function(t,e){var n=this;(t=t.trim())&&t.split(/\s+/g).forEach(function(t){e?n._renderer.addClass(n._ngEl.nativeElement,t):n._renderer.removeClass(n._ngEl.nativeElement,t)})},t}(),Mt=function(){function t(t){this._viewContainerRef=t,this._componentRef=null,this._moduleRef=null}return t.prototype.ngOnChanges=function(t){if(this._viewContainerRef.clear(),this._componentRef=null,this.ngComponentOutlet){var e=this.ngComponentOutletInjector||this._viewContainerRef.parentInjector;if(t.ngComponentOutletNgModuleFactory)if(this._moduleRef&&this._moduleRef.destroy(),this.ngComponentOutletNgModuleFactory){var n=e.get(a.NgModuleRef);this._moduleRef=this.ngComponentOutletNgModuleFactory.create(n.injector)}else this._moduleRef=null;var r=(this._moduleRef?this._moduleRef.componentFactoryResolver:e.get(a.ComponentFactoryResolver)).resolveComponentFactory(this.ngComponentOutlet);this._componentRef=this._viewContainerRef.createComponent(r,this._viewContainerRef.length,e,this.ngComponentOutletContent)}},t.prototype.ngOnDestroy=function(){this._moduleRef&&this._moduleRef.destroy()},t}(),qt=function(){function t(t,e,n,a){this.$implicit=t,this.ngForOf=e,this.index=n,this.count=a}return Object.defineProperty(t.prototype,"first",{get:function(){return 0===this.index},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"last",{get:function(){return this.index===this.count-1},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"even",{get:function(){return this.index%2==0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"odd",{get:function(){return!this.even},enumerable:!0,configurable:!0}),t}(),jt=function(){function t(t,e,n){this._viewContainer=t,this._template=e,this._differs=n,this._ngForOfDirty=!0,this._differ=null}return Object.defineProperty(t.prototype,"ngForOf",{set:function(t){this._ngForOf=t,this._ngForOfDirty=!0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngForTrackBy",{get:function(){return this._trackByFn},set:function(t){Object(a.isDevMode)()&&null!=t&&"function"!=typeof t&&console&&console.warn&&console.warn("trackBy must be a function, but received "+JSON.stringify(t)+". See https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#change-propagation for more information."),this._trackByFn=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngForTemplate",{set:function(t){t&&(this._template=t)},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){if(this._ngForOfDirty){this._ngForOfDirty=!1;var t=this._ngForOf;if(!this._differ&&t)try{this._differ=this._differs.find(t).create(this.ngForTrackBy)}catch(a){throw new Error("Cannot find a differ supporting object '"+t+"' of type '"+((e=t).name||typeof e)+"'. NgFor only supports binding to Iterables such as Arrays.")}}var e;if(this._differ){var n=this._differ.diff(this._ngForOf);n&&this._applyChanges(n)}},t.prototype._applyChanges=function(t){var e=this,n=[];t.forEachOperation(function(t,a,r){if(null==t.previousIndex){var i=e._viewContainer.createEmbeddedView(e._template,new qt(null,e._ngForOf,-1,-1),r),s=new Ft(t,i);n.push(s)}else null==r?e._viewContainer.remove(a):(i=e._viewContainer.get(a),e._viewContainer.move(i,r),s=new Ft(t,i),n.push(s))});for(var a=0;a<n.length;a++)this._perViewChange(n[a].view,n[a].record);a=0;for(var r=this._viewContainer.length;a<r;a++){var i=this._viewContainer.get(a);i.context.index=a,i.context.count=r,i.context.ngForOf=this._ngForOf}t.forEachIdentityChange(function(t){e._viewContainer.get(t.currentIndex).context.$implicit=t.item})},t.prototype._perViewChange=function(t,e){t.context.$implicit=e.item},t.ngTemplateContextGuard=function(t,e){return!0},t}(),Ft=function(){return function(t,e){this.record=t,this.view=e}}(),zt=function(){function t(t,e){this._viewContainer=t,this._context=new Gt,this._thenTemplateRef=null,this._elseTemplateRef=null,this._thenViewRef=null,this._elseViewRef=null,this._thenTemplateRef=e}return Object.defineProperty(t.prototype,"ngIf",{set:function(t){this._context.$implicit=this._context.ngIf=t,this._updateView()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngIfThen",{set:function(t){Yt("ngIfThen",t),this._thenTemplateRef=t,this._thenViewRef=null,this._updateView()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngIfElse",{set:function(t){Yt("ngIfElse",t),this._elseTemplateRef=t,this._elseViewRef=null,this._updateView()},enumerable:!0,configurable:!0}),t.prototype._updateView=function(){this._context.$implicit?this._thenViewRef||(this._viewContainer.clear(),this._elseViewRef=null,this._thenTemplateRef&&(this._thenViewRef=this._viewContainer.createEmbeddedView(this._thenTemplateRef,this._context))):this._elseViewRef||(this._viewContainer.clear(),this._thenViewRef=null,this._elseTemplateRef&&(this._elseViewRef=this._viewContainer.createEmbeddedView(this._elseTemplateRef,this._context)))},t.ngTemplateGuard_ngIf=function(t,e){return!0},t}(),Gt=function(){return function(){this.$implicit=null,this.ngIf=null}}();function Yt(t,e){if(e&&!e.createEmbeddedView)throw new Error(t+" must be a TemplateRef, but received '"+Object(a["\u0275stringify"])(e)+"'.")}var Vt=function(){function t(t,e){this._viewContainerRef=t,this._templateRef=e,this._created=!1}return t.prototype.create=function(){this._created=!0,this._viewContainerRef.createEmbeddedView(this._templateRef)},t.prototype.destroy=function(){this._created=!1,this._viewContainerRef.clear()},t.prototype.enforceState=function(t){t&&!this._created?this.create():!t&&this._created&&this.destroy()},t}(),Ht=function(){function t(){this._defaultUsed=!1,this._caseCount=0,this._lastCaseCheckIndex=0,this._lastCasesMatched=!1}return Object.defineProperty(t.prototype,"ngSwitch",{set:function(t){this._ngSwitch=t,0===this._caseCount&&this._updateDefaultCases(!0)},enumerable:!0,configurable:!0}),t.prototype._addCase=function(){return this._caseCount++},t.prototype._addDefault=function(t){this._defaultViews||(this._defaultViews=[]),this._defaultViews.push(t)},t.prototype._matchCase=function(t){var e=t==this._ngSwitch;return this._lastCasesMatched=this._lastCasesMatched||e,this._lastCaseCheckIndex++,this._lastCaseCheckIndex===this._caseCount&&(this._updateDefaultCases(!this._lastCasesMatched),this._lastCaseCheckIndex=0,this._lastCasesMatched=!1),e},t.prototype._updateDefaultCases=function(t){if(this._defaultViews&&t!==this._defaultUsed){this._defaultUsed=t;for(var e=0;e<this._defaultViews.length;e++)this._defaultViews[e].enforceState(t)}},t}(),Bt=function(){function t(t,e,n){this.ngSwitch=n,n._addCase(),this._view=new Vt(t,e)}return t.prototype.ngDoCheck=function(){this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase))},t}(),Ut=function(){return function(t,e,n){n._addDefault(new Vt(t,e))}}(),Wt=function(){function t(t){this._localization=t,this._caseViews={}}return Object.defineProperty(t.prototype,"ngPlural",{set:function(t){this._switchValue=t,this._updateView()},enumerable:!0,configurable:!0}),t.prototype.addCase=function(t,e){this._caseViews[t]=e},t.prototype._updateView=function(){this._clearViews();var t=Object.keys(this._caseViews),e=At(this._switchValue,t,this._localization);this._activateView(this._caseViews[e])},t.prototype._clearViews=function(){this._activeView&&this._activeView.destroy()},t.prototype._activateView=function(t){t&&(this._activeView=t,this._activeView.create())},t}(),Kt=function(){return function(t,e,n,a){this.value=t;var r=!isNaN(Number(t));a.addCase(r?"="+t:t,new Vt(n,e))}}(),$t=function(){function t(t,e,n){this._differs=t,this._ngEl=e,this._renderer=n}return Object.defineProperty(t.prototype,"ngStyle",{set:function(t){this._ngStyle=t,!this._differ&&t&&(this._differ=this._differs.find(t).create())},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){if(this._differ){var t=this._differ.diff(this._ngStyle);t&&this._applyChanges(t)}},t.prototype._applyChanges=function(t){var e=this;t.forEachRemovedItem(function(t){return e._setStyle(t.key,null)}),t.forEachAddedItem(function(t){return e._setStyle(t.key,t.currentValue)}),t.forEachChangedItem(function(t){return e._setStyle(t.key,t.currentValue)})},t.prototype._setStyle=function(t,e){var n=Object(r.__read)(t.split("."),2),a=n[0],i=n[1];null!=(e=null!=e&&i?""+e+i:e)?this._renderer.setStyle(this._ngEl.nativeElement,a,e):this._renderer.removeStyle(this._ngEl.nativeElement,a)},t}(),Zt=function(){function t(t){this._viewContainerRef=t}return t.prototype.ngOnChanges=function(t){this._shouldRecreateView(t)?(this._viewRef&&this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef)),this.ngTemplateOutlet&&(this._viewRef=this._viewContainerRef.createEmbeddedView(this.ngTemplateOutlet,this.ngTemplateOutletContext))):this._viewRef&&this.ngTemplateOutletContext&&this._updateExistingContext(this.ngTemplateOutletContext)},t.prototype._shouldRecreateView=function(t){var e=t.ngTemplateOutletContext;return!!t.ngTemplateOutlet||e&&this._hasContextShapeChanged(e)},t.prototype._hasContextShapeChanged=function(t){var e,n,a=Object.keys(t.previousValue||{}),i=Object.keys(t.currentValue||{});if(a.length===i.length){try{for(var s=Object(r.__values)(i),o=s.next();!o.done;o=s.next())if(-1===a.indexOf(o.value))return!0}catch(u){e={error:u}}finally{try{o&&!o.done&&(n=s.return)&&n.call(s)}finally{if(e)throw e.error}}return!1}return!0},t.prototype._updateExistingContext=function(t){var e,n;try{for(var a=Object(r.__values)(Object.keys(t)),i=a.next();!i.done;i=a.next()){var s=i.value;this._viewRef.context[s]=this.ngTemplateOutletContext[s]}}catch(o){e={error:o}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(e)throw e.error}}},t}(),Xt=[Pt,Mt,jt,zt,Zt,$t,Ht,Bt,Ut,Wt,Kt];function Jt(t,e){return Error("InvalidPipeArgument: '"+e+"' for pipe '"+Object(a["\u0275stringify"])(t)+"'")}var Qt=function(){function t(){}return t.format=function(t,e,n,a){void 0===a&&(a={});var r=a.currency,i=a.currencyAsSymbol,s=void 0!==i&&i,o={minimumIntegerDigits:a.minimumIntegerDigits,minimumFractionDigits:a.minimumFractionDigits,maximumFractionDigits:a.maximumFractionDigits,style:y[n].toLowerCase()};return n==y.Currency&&(o.currency="string"==typeof r?r:void 0,o.currencyDisplay=s?"symbol":"code"),new Intl.NumberFormat(e,o).format(t)},t}(),te=/((?:[^yMLdHhmsazZEwGjJ']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|J+|j+|m+|s+|a|z|Z|G+|w+))(.*)/,ee={yMMMdjms:fe(de([ce("year",1),le("month",3),ce("day",1),ce("hour",1),ce("minute",1),ce("second",1)])),yMdjm:fe(de([ce("year",1),ce("month",1),ce("day",1),ce("hour",1),ce("minute",1)])),yMMMMEEEEd:fe(de([ce("year",1),le("month",4),le("weekday",4),ce("day",1)])),yMMMMd:fe(de([ce("year",1),le("month",4),ce("day",1)])),yMMMd:fe(de([ce("year",1),le("month",3),ce("day",1)])),yMd:fe(de([ce("year",1),ce("month",1),ce("day",1)])),jms:fe(de([ce("hour",1),ce("second",1),ce("minute",1)])),jm:fe(de([ce("hour",1),ce("minute",1)]))},ne={yyyy:fe(ce("year",4)),yy:fe(ce("year",2)),y:fe(ce("year",1)),MMMM:fe(le("month",4)),MMM:fe(le("month",3)),MM:fe(ce("month",2)),M:fe(ce("month",1)),LLLL:fe(le("month",4)),L:fe(le("month",1)),dd:fe(ce("day",2)),d:fe(ce("day",1)),HH:ae(ie(fe(ue(ce("hour",2),!1)))),H:ie(fe(ue(ce("hour",1),!1))),hh:ae(ie(fe(ue(ce("hour",2),!0)))),h:ie(fe(ue(ce("hour",1),!0))),jj:fe(ce("hour",2)),j:fe(ce("hour",1)),mm:ae(fe(ce("minute",2))),m:fe(ce("minute",1)),ss:ae(fe(ce("second",2))),s:fe(ce("second",1)),sss:fe(ce("second",3)),EEEE:fe(le("weekday",4)),EEE:fe(le("weekday",3)),EE:fe(le("weekday",2)),E:fe(le("weekday",1)),a:re(fe(ue(ce("hour",1),!0))),Z:oe("short"),z:oe("long"),ww:fe({}),w:fe({}),G:fe(le("era",1)),GG:fe(le("era",2)),GGG:fe(le("era",3)),GGGG:fe(le("era",4))};function ae(t){return function(e,n){var a=t(e,n);return 1==a.length?"0"+a:a}}function re(t){return function(e,n){return t(e,n).split(" ")[1]}}function ie(t){return function(e,n){return t(e,n).split(" ")[0]}}function se(t,e,n){return new Intl.DateTimeFormat(e,n).format(t).replace(/[\u200e\u200f]/g,"")}function oe(t){var e={hour:"2-digit",hour12:!1,timeZoneName:t};return function(t,n){var a=se(t,n,e);return a?a.substring(3):""}}function ue(t,e){return t.hour12=e,t}function ce(t,e){var n={};return n[t]=2===e?"2-digit":"numeric",n}function le(t,e){var n={};return n[t]=e<4?e>1?"short":"narrow":"long",n}function de(t){return t.reduce(function(t,e){return Object(r.__assign)({},t,e)},{})}function fe(t){return function(e,n){return se(e,n,t)}}var pe=new Map,he=function(){function t(){}return t.format=function(t,e,n){return function(t,e,n){var a=ee[t];if(a)return a(e,n);var r=t,i=pe.get(r);if(!i){i=[];var s=void 0;te.exec(t);for(var o=t;o;)(s=te.exec(o))?o=(i=i.concat(s.slice(1))).pop():(i.push(o),o=null);pe.set(r,i)}return i.reduce(function(t,a){var r=ne[a];return t+(r?r(e,n):function(t){return"''"===t?"'":t.replace(/(^'|'$)/g,"").replace(/''/g,"'")}(a))},"")}(n,t,e)},t}(),ge=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n){if(void 0===n&&(n="mediumDate"),null==t||""===t||t!=t)return null;var a;if("string"==typeof t&&(t=t.trim()),be(t))a=t;else if(isNaN(t-parseFloat(t)))if("string"==typeof t&&/^(\d{4}-\d{1,2}-\d{1,2})$/.test(t)){var i=Object(r.__read)(t.split("-").map(function(t){return parseInt(t,10)}),3);a=new Date(i[0],i[1]-1,i[2])}else a=new Date(t);else a=new Date(parseFloat(t));if(!be(a)){var s=void 0;if("string"!=typeof t||!(s=t.match($)))throw Jt(e,t);a=ft(s)}return he.format(a,this._locale,e._ALIASES[n]||n)},t._ALIASES={medium:"yMMMdjms",short:"yMdjm",fullDate:"yMMMMEEEEd",longDate:"yMMMMd",mediumDate:"yMMMd",shortDate:"yMd",mediumTime:"jms",shortTime:"jm"},t}();function be(t){return t instanceof Date&&!isNaN(t.valueOf())}function me(t,e,n,a,r,i,s){if(void 0===i&&(i=null),void 0===s&&(s=!1),null==n)return null;if("number"!=typeof(n="string"!=typeof n||isNaN(+n-parseFloat(n))?n:+n))throw Jt(t,n);var o,u,c;if(a!==y.Currency&&(o=1,u=0,c=3),r){var l=r.match(ht);if(null===l)throw new Error(r+" is not a valid digit info for number pipes");null!=l[1]&&(o=kt(l[1])),null!=l[3]&&(u=kt(l[3])),null!=l[5]&&(c=kt(l[5]))}return Qt.format(n,e,a,{minimumIntegerDigits:o,minimumFractionDigits:u,maximumFractionDigits:c,currency:i,currencyAsSymbol:s})}var ye=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n){return me(e,this._locale,t,y.Decimal,n)},t}(),ve=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n){return me(e,this._locale,t,y.Percent,n)},t}(),_e=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n,a,r){return void 0===n&&(n="USD"),void 0===a&&(a=!1),me(e,this._locale,t,y.Currency,r,n,a)},t}(),xe=[ye,ve,_e,ge],Te=function(){function t(){}return t.prototype.createSubscription=function(t,e){return t.subscribe({next:e,error:function(t){throw t}})},t.prototype.dispose=function(t){t.unsubscribe()},t.prototype.onDestroy=function(t){t.unsubscribe()},t}(),we=new(function(){function t(){}return t.prototype.createSubscription=function(t,e){return t.then(e,function(t){throw t})},t.prototype.dispose=function(t){},t.prototype.onDestroy=function(t){},t}()),Se=new Te,Oe=function(){function t(t){this._ref=t,this._latestValue=null,this._latestReturnedValue=null,this._subscription=null,this._obj=null,this._strategy=null}var e;return e=t,t.prototype.ngOnDestroy=function(){this._subscription&&this._dispose()},t.prototype.transform=function(t){return this._obj?t!==this._obj?(this._dispose(),this.transform(t)):this._latestValue===this._latestReturnedValue?this._latestReturnedValue:(this._latestReturnedValue=this._latestValue,a.WrappedValue.wrap(this._latestValue)):(t&&this._subscribe(t),this._latestReturnedValue=this._latestValue,this._latestValue)},t.prototype._subscribe=function(t){var e=this;this._obj=t,this._strategy=this._selectStrategy(t),this._subscription=this._strategy.createSubscription(t,function(n){return e._updateLatestValue(t,n)})},t.prototype._selectStrategy=function(t){if(Object(a["\u0275isPromise"])(t))return we;if(Object(a["\u0275isObservable"])(t))return Se;throw Jt(e,t)},t.prototype._dispose=function(){this._strategy.dispose(this._subscription),this._latestValue=null,this._latestReturnedValue=null,this._subscription=null,this._obj=null},t.prototype._updateLatestValue=function(t,e){t===this._obj&&(this._latestValue=e,this._ref.markForCheck())},t}(),Ie=function(){function t(){}var e;return e=t,t.prototype.transform=function(t){if(!t)return t;if("string"!=typeof t)throw Jt(e,t);return t.toLowerCase()},t}(),Ce=/(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])\S*/g,ke=function(){function t(){}var e;return e=t,t.prototype.transform=function(t){if(!t)return t;if("string"!=typeof t)throw Jt(e,t);return t.replace(Ce,function(t){return t[0].toUpperCase()+t.substr(1).toLowerCase()})},t}(),Ne=function(){function t(){}var e;return e=t,t.prototype.transform=function(t){if(!t)return t;if("string"!=typeof t)throw Jt(e,t);return t.toUpperCase()},t}(),Re=function(){function t(t){this.locale=t}var e;return e=t,t.prototype.transform=function(t,n,a,r){if(void 0===n&&(n="mediumDate"),null==t||""===t||t!=t)return null;try{return et(t,n,r||this.locale,a)}catch(i){throw Jt(e,i.message)}},t}(),Ae=/#/g,De=function(){function t(t){this._localization=t}var e;return e=t,t.prototype.transform=function(t,n,a){if(null==t)return"";if("object"!=typeof n||null===n)throw Jt(e,n);return n[At(t,Object.keys(n),this._localization,a)].replace(Ae,t.toString())},t}(),Ee=function(){function t(){}var e;return e=t,t.prototype.transform=function(t,n){if(null==t)return"";if("object"!=typeof n||"string"!=typeof t)throw Jt(e,n);return n.hasOwnProperty(t)?n[t]:n.hasOwnProperty("other")?n.other:""},t}(),Le=function(){function t(){}return t.prototype.transform=function(t){return JSON.stringify(t,null,2)},t}(),Pe=function(){function t(t){this.differs=t,this.keyValues=[]}return t.prototype.transform=function(t,e){var n=this;if(void 0===e&&(e=Me),!t||!(t instanceof Map)&&"object"!=typeof t)return null;this.differ||(this.differ=this.differs.find(t).create());var a=this.differ.diff(t);return a&&(this.keyValues=[],a.forEachItem(function(t){n.keyValues.push({key:t.key,value:t.currentValue})}),this.keyValues.sort(e)),this.keyValues},t}();function Me(t,e){var n=t.key,a=e.key;if(n===a)return 0;if(void 0===n)return 1;if(void 0===a)return-1;if(null===n)return 1;if(null===a)return-1;if("string"==typeof n&&"string"==typeof a)return n<a?-1:1;if("number"==typeof n&&"number"==typeof a)return n-a;if("boolean"==typeof n&&"boolean"==typeof a)return n<a?-1:1;var r=String(n),i=String(a);return r==i?0:r<i?-1:1}var qe=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n,a){if(ze(t))return null;a=a||this._locale;try{return It(Ge(t),a,n)}catch(r){throw Jt(e,r.message)}},t}(),je=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n,a){if(ze(t))return null;a=a||this._locale;try{return Ot(Ge(t),a,n)}catch(r){throw Jt(e,r.message)}},t}(),Fe=function(){function t(t){this._locale=t}var e;return e=t,t.prototype.transform=function(t,n,a,r,i){if(void 0===a&&(a="symbol"),ze(t))return null;i=i||this._locale,"boolean"==typeof a&&(console&&console.warn&&console.warn('Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".'),a=a?"symbol":"code");var s=n||"USD";"code"!==a&&(s="symbol"===a||"symbol-narrow"===a?U(s,"symbol"===a?"wide":"narrow",i):a);try{return St(Ge(t),i,s,n,r)}catch(o){throw Jt(e,o.message)}},t}();function ze(t){return null==t||""===t||t!=t}function Ge(t){if("string"==typeof t&&!isNaN(Number(t)-parseFloat(t)))return Number(t);if("number"!=typeof t)throw new Error(t+" is not a number");return t}var Ye=function(){function t(){}var e;return e=t,t.prototype.transform=function(t,n,a){if(null==t)return t;if(!this.supports(t))throw Jt(e,t);return t.slice(n,a)},t.prototype.supports=function(t){return"string"==typeof t||Array.isArray(t)},t}(),Ve=[Oe,Ne,Ie,Le,Ye,qe,je,ke,Fe,Re,De,Ee,Pe],He=function(){return function(){}}(),Be=function(){return function(){}}(),Ue=new a.InjectionToken("DocumentToken"),We="browser",Ke="server",$e="browserWorkerApp",Ze="browserWorkerUi";function Xe(t){return t===We}function Je(t){return t===Ke}function Qe(t){return t===$e}function tn(t){return t===Ze}var en=new a.Version("7.2.6"),nn=function(){function t(){}return t.ngInjectableDef=Object(a.defineInjectable)({providedIn:"root",factory:function(){return new an(Object(a.inject)(Ue),window)}}),t}(),an=function(){function t(t,e){this.document=t,this.window=e,this.offset=function(){return[0,0]}}return t.prototype.setOffset=function(t){this.offset=Array.isArray(t)?function(){return t}:t},t.prototype.getScrollPosition=function(){return this.supportScrollRestoration()?[this.window.scrollX,this.window.scrollY]:[0,0]},t.prototype.scrollToPosition=function(t){this.supportScrollRestoration()&&this.window.scrollTo(t[0],t[1])},t.prototype.scrollToAnchor=function(t){if(this.supportScrollRestoration()){var e=this.document.querySelector("#"+t);if(e)return void this.scrollToElement(e);var n=this.document.querySelector("[name='"+t+"']");if(n)return void this.scrollToElement(n)}},t.prototype.setHistoryScrollRestoration=function(t){if(this.supportScrollRestoration()){var e=this.window.history;e&&e.scrollRestoration&&(e.scrollRestoration=t)}},t.prototype.scrollToElement=function(t){var e=t.getBoundingClientRect(),n=e.left+this.window.pageXOffset,a=e.top+this.window.pageYOffset,r=this.offset();this.window.scrollTo(n-r[0],a-r[1])},t.prototype.supportScrollRestoration=function(){try{return!!this.window&&!!this.window.scrollTo}catch(t){return!1}},t}(),rn=function(){function t(){}return t.prototype.setOffset=function(t){},t.prototype.getScrollPosition=function(){return[0,0]},t.prototype.scrollToPosition=function(t){},t.prototype.scrollToAnchor=function(t){},t.prototype.setHistoryScrollRestoration=function(t){},t}()},"Ivi+":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ko",{months:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),monthsShort:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),weekdays:"\uc77c\uc694\uc77c_\uc6d4\uc694\uc77c_\ud654\uc694\uc77c_\uc218\uc694\uc77c_\ubaa9\uc694\uc77c_\uae08\uc694\uc77c_\ud1a0\uc694\uc77c".split("_"),weekdaysShort:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),weekdaysMin:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY\ub144 MMMM D\uc77c",LLL:"YYYY\ub144 MMMM D\uc77c A h:mm",LLLL:"YYYY\ub144 MMMM D\uc77c dddd A h:mm",l:"YYYY.MM.DD.",ll:"YYYY\ub144 MMMM D\uc77c",lll:"YYYY\ub144 MMMM D\uc77c A h:mm",llll:"YYYY\ub144 MMMM D\uc77c dddd A h:mm"},calendar:{sameDay:"\uc624\ub298 LT",nextDay:"\ub0b4\uc77c LT",nextWeek:"dddd LT",lastDay:"\uc5b4\uc81c LT",lastWeek:"\uc9c0\ub09c\uc8fc dddd LT",sameElse:"L"},relativeTime:{future:"%s \ud6c4",past:"%s \uc804",s:"\uba87 \ucd08",ss:"%d\ucd08",m:"1\ubd84",mm:"%d\ubd84",h:"\ud55c \uc2dc\uac04",hh:"%d\uc2dc\uac04",d:"\ud558\ub8e8",dd:"%d\uc77c",M:"\ud55c \ub2ec",MM:"%d\ub2ec",y:"\uc77c \ub144",yy:"%d\ub144"},dayOfMonthOrdinalParse:/\d{1,2}(\uc77c|\uc6d4|\uc8fc)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\uc77c";case"M":return t+"\uc6d4";case"w":case"W":return t+"\uc8fc";default:return t}},meridiemParse:/\uc624\uc804|\uc624\ud6c4/,isPM:function(t){return"\uc624\ud6c4"===t},meridiem:function(t,e,n){return t<12?"\uc624\uc804":"\uc624\ud6c4"}})}()},IxPp:function(t,e,n){"use strict";n.d(e,"b",function(){return u}),n.d(e,"a",function(){return f});var a=n("mrSG"),r=n("FFOo"),i=n("pugT"),s=n("6blF"),o=n("K9Ia");function u(t,e,n,a){return function(r){return r.lift(new c(t,e,n,a))}}var c=function(){function t(t,e,n,a){this.keySelector=t,this.elementSelector=e,this.durationSelector=n,this.subjectSelector=a}return t.prototype.call=function(t,e){return e.subscribe(new l(t,this.keySelector,this.elementSelector,this.durationSelector,this.subjectSelector))},t}(),l=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;return s.keySelector=n,s.elementSelector=a,s.durationSelector=r,s.subjectSelector=i,s.groups=null,s.attemptedToUnsubscribe=!1,s.count=0,s}return a.__extends(e,t),e.prototype._next=function(t){var e;try{e=this.keySelector(t)}catch(n){return void this.error(n)}this._group(t,e)},e.prototype._group=function(t,e){var n=this.groups;n||(n=this.groups=new Map);var a,r=n.get(e);if(this.elementSelector)try{a=this.elementSelector(t)}catch(u){this.error(u)}else a=t;if(!r){r=this.subjectSelector?this.subjectSelector():new o.a,n.set(e,r);var i=new f(e,r,this);if(this.destination.next(i),this.durationSelector){var s=void 0;try{s=this.durationSelector(new f(e,r))}catch(u){return void this.error(u)}this.add(s.subscribe(new d(e,r,this)))}}r.closed||r.next(a)},e.prototype._error=function(t){var e=this.groups;e&&(e.forEach(function(e,n){e.error(t)}),e.clear()),this.destination.error(t)},e.prototype._complete=function(){var t=this.groups;t&&(t.forEach(function(t,e){t.complete()}),t.clear()),this.destination.complete()},e.prototype.removeGroup=function(t){this.groups.delete(t)},e.prototype.unsubscribe=function(){this.closed||(this.attemptedToUnsubscribe=!0,0===this.count&&t.prototype.unsubscribe.call(this))},e}(r.a),d=function(t){function e(e,n,a){var r=t.call(this,n)||this;return r.key=e,r.group=n,r.parent=a,r}return a.__extends(e,t),e.prototype._next=function(t){this.complete()},e.prototype._unsubscribe=function(){var t=this.parent,e=this.key;this.key=this.parent=null,t&&t.removeGroup(e)},e}(r.a),f=function(t){function e(e,n,a){var r=t.call(this)||this;return r.key=e,r.groupSubject=n,r.refCountSubscription=a,r}return a.__extends(e,t),e.prototype._subscribe=function(t){var e=new i.a,n=this.refCountSubscription,a=this.groupSubject;return n&&!n.closed&&e.add(new p(n)),e.add(a.subscribe(t)),e},e}(s.a),p=function(t){function e(e){var n=t.call(this)||this;return n.parent=e,e.count++,n}return a.__extends(e,t),e.prototype.unsubscribe=function(){var e=this.parent;e.closed||this.closed||(t.prototype.unsubscribe.call(this),e.count-=1,0===e.count&&e.attemptedToUnsubscribe&&e.unsubscribe())},e}(i.a)},IzCI:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("aXbf");var a=function(){function t(t){this.formatter=t}return t.prototype.transform=function(t){return this.formatter.format_number(t,1024,["B/s","kB/s","MB/s","GB/s","TB/s","PB/s","EB/s","ZB/s","YB/s"])},t}()},"JCF/":function(t,e,n){!function(t){"use strict";var e={1:"\u0661",2:"\u0662",3:"\u0663",4:"\u0664",5:"\u0665",6:"\u0666",7:"\u0667",8:"\u0668",9:"\u0669",0:"\u0660"},n={"\u0661":"1","\u0662":"2","\u0663":"3","\u0664":"4","\u0665":"5","\u0666":"6","\u0667":"7","\u0668":"8","\u0669":"9","\u0660":"0"},a=["\u06a9\u0627\u0646\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645","\u0634\u0648\u0628\u0627\u062a","\u0626\u0627\u0632\u0627\u0631","\u0646\u06cc\u0633\u0627\u0646","\u0626\u0627\u06cc\u0627\u0631","\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646","\u062a\u06d5\u0645\u0645\u0648\u0632","\u0626\u0627\u0628","\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644","\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u0643\u06d5\u0645","\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645","\u0643\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"];t.defineLocale("ku",{months:a,monthsShort:a,weekdays:"\u06cc\u0647\u200c\u0643\u0634\u0647\u200c\u0645\u0645\u0647\u200c_\u062f\u0648\u0648\u0634\u0647\u200c\u0645\u0645\u0647\u200c_\u0633\u06ce\u0634\u0647\u200c\u0645\u0645\u0647\u200c_\u0686\u0648\u0627\u0631\u0634\u0647\u200c\u0645\u0645\u0647\u200c_\u067e\u06ce\u0646\u062c\u0634\u0647\u200c\u0645\u0645\u0647\u200c_\u0647\u0647\u200c\u06cc\u0646\u06cc_\u0634\u0647\u200c\u0645\u0645\u0647\u200c".split("_"),weekdaysShort:"\u06cc\u0647\u200c\u0643\u0634\u0647\u200c\u0645_\u062f\u0648\u0648\u0634\u0647\u200c\u0645_\u0633\u06ce\u0634\u0647\u200c\u0645_\u0686\u0648\u0627\u0631\u0634\u0647\u200c\u0645_\u067e\u06ce\u0646\u062c\u0634\u0647\u200c\u0645_\u0647\u0647\u200c\u06cc\u0646\u06cc_\u0634\u0647\u200c\u0645\u0645\u0647\u200c".split("_"),weekdaysMin:"\u06cc_\u062f_\u0633_\u0686_\u067e_\u0647_\u0634".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/\u0626\u06ce\u0648\u0627\u0631\u0647\u200c|\u0628\u0647\u200c\u06cc\u0627\u0646\u06cc/,isPM:function(t){return/\u0626\u06ce\u0648\u0627\u0631\u0647\u200c/.test(t)},meridiem:function(t,e,n){return t<12?"\u0628\u0647\u200c\u06cc\u0627\u0646\u06cc":"\u0626\u06ce\u0648\u0627\u0631\u0647\u200c"},calendar:{sameDay:"[\u0626\u0647\u200c\u0645\u0631\u06c6 \u0643\u0627\u062a\u0698\u0645\u06ce\u0631] LT",nextDay:"[\u0628\u0647\u200c\u06cc\u0627\u0646\u06cc \u0643\u0627\u062a\u0698\u0645\u06ce\u0631] LT",nextWeek:"dddd [\u0643\u0627\u062a\u0698\u0645\u06ce\u0631] LT",lastDay:"[\u062f\u0648\u06ce\u0646\u06ce \u0643\u0627\u062a\u0698\u0645\u06ce\u0631] LT",lastWeek:"dddd [\u0643\u0627\u062a\u0698\u0645\u06ce\u0631] LT",sameElse:"L"},relativeTime:{future:"\u0644\u0647\u200c %s",past:"%s",s:"\u0686\u0647\u200c\u0646\u062f \u0686\u0631\u0643\u0647\u200c\u06cc\u0647\u200c\u0643",ss:"\u0686\u0631\u0643\u0647\u200c %d",m:"\u06cc\u0647\u200c\u0643 \u062e\u0648\u0644\u0647\u200c\u0643",mm:"%d \u062e\u0648\u0644\u0647\u200c\u0643",h:"\u06cc\u0647\u200c\u0643 \u0643\u0627\u062a\u0698\u0645\u06ce\u0631",hh:"%d \u0643\u0627\u062a\u0698\u0645\u06ce\u0631",d:"\u06cc\u0647\u200c\u0643 \u0695\u06c6\u0698",dd:"%d \u0695\u06c6\u0698",M:"\u06cc\u0647\u200c\u0643 \u0645\u0627\u0646\u06af",MM:"%d \u0645\u0627\u0646\u06af",y:"\u06cc\u0647\u200c\u0643 \u0633\u0627\u06b5",yy:"%d \u0633\u0627\u06b5"},preparse:function(t){return t.replace(/[\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660]/g,function(t){return n[t]}).replace(/\u060c/g,",")},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]}).replace(/,/g,"\u060c")},week:{dow:6,doy:12}})}(n("wd/R"))},"JF+6":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("6blF"),r=n("pugT");function i(t,e){return new a.a(function(n){var a=new r.a,i=0;return a.add(e.schedule(function(){i!==t.length?(n.next(t[i++]),n.closed||a.add(this.schedule())):n.complete()})),a})}},JVSJ:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a=t+" ";switch(n){case"ss":return a+(1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi");case"m":return e?"jedna minuta":"jedne minute";case"mm":return a+(1===t?"minuta":2===t||3===t||4===t?"minute":"minuta");case"h":return e?"jedan sat":"jednog sata";case"hh":return a+(1===t?"sat":2===t||3===t||4===t?"sata":"sati");case"dd":return a+(1===t?"dan":"dana");case"MM":return a+(1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci");case"yy":return a+(1===t?"godina":2===t||3===t||4===t?"godine":"godina")}}n("wd/R").defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_\u010detvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._\u010det._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_\u010de_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[ju\u010der u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[pro\u0161lu] dddd [u] LT";case 6:return"[pro\u0161le] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[pro\u0161li] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}()},JZ5S:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=n("buEt"),i=n("QG5k");e.NodeMenuService=function(){function t(){this.nodeMenuEvents$=new r.Subject}return t.prototype.fireMenuEvent=function(t,e){this.nodeMenuEvents$.next({sender:t,action:e})},t.prototype.hideMenuStream=function(t){return this.nodeMenuEvents$.filter(function(e){return t.nativeElement!==e.sender}).filter(function(t){return t.action===i.NodeMenuAction.Close})},t.prototype.hideMenuForAllNodesExcept=function(t){this.nodeMenuEvents$.next({sender:t.nativeElement,action:i.NodeMenuAction.Close})},t.decorators=[{type:a.Injectable}],t}()},"Jm/i":function(t,e,n){"use strict";n.d(e,"a",function(){return On}),n.d(e,"b",function(){return Sn});var a=n("mrSG"),r=n("Ip0R"),i=n("CcnG"),s=function(){function t(t,e){this.value=t,this.sourceSpan=e}return t.prototype.visit=function(t,e){return t.visitText(this,e)},t}(),o=function(){function t(t,e,n,a,r){this.switchValue=t,this.type=e,this.cases=n,this.sourceSpan=a,this.switchValueSourceSpan=r}return t.prototype.visit=function(t,e){return t.visitExpansion(this,e)},t}(),u=function(){function t(t,e,n,a,r){this.value=t,this.expression=e,this.sourceSpan=n,this.valueSourceSpan=a,this.expSourceSpan=r}return t.prototype.visit=function(t,e){return t.visitExpansionCase(this,e)},t}(),c=function(){function t(t,e,n,a){this.name=t,this.value=e,this.sourceSpan=n,this.valueSpan=a}return t.prototype.visit=function(t,e){return t.visitAttribute(this,e)},t}(),l=function(){function t(t,e,n,a,r,i){void 0===r&&(r=null),void 0===i&&(i=null),this.name=t,this.attrs=e,this.children=n,this.sourceSpan=a,this.startSourceSpan=r,this.endSourceSpan=i}return t.prototype.visit=function(t,e){return t.visitElement(this,e)},t}(),d=function(){function t(t,e){this.value=t,this.sourceSpan=e}return t.prototype.visit=function(t,e){return t.visitComment(this,e)},t}();function f(t,e,n){void 0===n&&(n=null);var a=[],r=t.visit?function(e){return t.visit(e,n)||e.visit(t,n)}:function(e){return e.visit(t,n)};return e.forEach(function(t){var e=r(t);e&&a.push(e)}),a}var p=function(){return function(t,e,n,a,r,i){this.nodes=t,this.placeholders=e,this.placeholderToMessage=n,this.meaning=a,this.description=r,this.id=i,this.sources=t.length?[{filePath:t[0].sourceSpan.start.file.url,startLine:t[0].sourceSpan.start.line+1,startCol:t[0].sourceSpan.start.col+1,endLine:t[t.length-1].sourceSpan.end.line+1,endCol:t[0].sourceSpan.start.col+1}]:[]}}(),h=function(){function t(t,e){this.value=t,this.sourceSpan=e}return t.prototype.visit=function(t,e){return t.visitText(this,e)},t}(),g=function(){function t(t,e){this.children=t,this.sourceSpan=e}return t.prototype.visit=function(t,e){return t.visitContainer(this,e)},t}(),b=function(){function t(t,e,n,a){this.expression=t,this.type=e,this.cases=n,this.sourceSpan=a}return t.prototype.visit=function(t,e){return t.visitIcu(this,e)},t}(),m=function(){function t(t,e,n,a,r,i,s){this.tag=t,this.attrs=e,this.startName=n,this.closeName=a,this.children=r,this.isVoid=i,this.sourceSpan=s}return t.prototype.visit=function(t,e){return t.visitTagPlaceholder(this,e)},t}(),y=function(){function t(t,e,n){this.value=t,this.name=e,this.sourceSpan=n}return t.prototype.visit=function(t,e){return t.visitPlaceholder(this,e)},t}(),v=function(){function t(t,e,n){this.value=t,this.name=e,this.sourceSpan=n}return t.prototype.visit=function(t,e){return t.visitIcuPlaceholder(this,e)},t}(),_=function(){function t(){}return t.prototype.visitText=function(t,e){},t.prototype.visitContainer=function(t,e){var n=this;t.children.forEach(function(t){return t.visit(n)})},t.prototype.visitIcu=function(t,e){var n=this;Object.keys(t.cases).forEach(function(e){t.cases[e].visit(n)})},t.prototype.visitTagPlaceholder=function(t,e){var n=this;t.children.forEach(function(t){return t.visit(n)})},t.prototype.visitPlaceholder=function(t,e){},t.prototype.visitIcuPlaceholder=function(t,e){},t}(),x=function(){function t(t,e,n,a){this.file=t,this.offset=e,this.line=n,this.col=a}return t.prototype.toString=function(){return null!=this.offset?this.line+":"+this.col:""},t.prototype.getContext=function(t,e){var n=this.file.content,a=this.offset;if(null!=a){a>n.length-1&&(a=n.length-1);for(var r=a,i=0,s=0;i<t&&a>0&&(i++,"\n"!==n[--a]||++s!==e););for(i=0,s=0;i<t&&r<n.length-1&&(i++,"\n"!==n[++r]||++s!==e););return{before:n.substring(a,this.offset),after:n.substring(this.offset,r+1)}}return null},t}(),T=function(){return function(t,e){void 0===e&&(e=""),this.content=t,this.url=e}}(),w=function(){function t(t,e,n){void 0===n&&(n=null),this.start=t,this.end=e,this.details=n}return t.prototype.toString=function(){return this.start.file.content.substring(this.start.offset,this.end.offset)},t}(),S=function(){var t={WARNING:0,ERROR:1};return t[t.WARNING]="WARNING",t[t.ERROR]="ERROR",t}(),O=function(){function t(t,e,n){void 0===n&&(n=S.ERROR),this.span=t,this.msg=e,this.level=n}return t.prototype.contextualMessage=function(){var t=this.span.start.getContext(100,3);return t?' ("'+t.before+"["+S[this.level]+" ->]"+t.after+'")':""},t.prototype.toString=function(){var t=this.span.details?", "+this.span.details:"";return""+this.msg+this.contextualMessage()+": "+this.span.start+t},t}(),I=function(t){function e(e,n){return t.call(this,e,n)||this}return Object(a.__extends)(e,t),e}(O);function C(t){return t.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}var k=new(function(){return function(t,e){this.start=t,this.end=e}}())("{{","}}"),N=0,R=9,A=10,D=11,E=12,L=13,P=32,M=34,q=36,j=39,F=43,z=45,G=47,Y=59,V=61,H=62,B=48,U=57,W=65,K=70,$=90,Z=95,X=97,J=102,Q=110,tt=114,et=116,nt=118,at=122,rt=123,it=160;function st(t){return t>=R&&t<=P||t===it}function ot(t){return B<=t&&t<=U}function ut(t){return t>=X&&t<=at||t>=W&&t<=$}var ct=function(){var t={RAW_TEXT:0,ESCAPABLE_RAW_TEXT:1,PARSABLE_DATA:2};return t[t.RAW_TEXT]="RAW_TEXT",t[t.ESCAPABLE_RAW_TEXT]="ESCAPABLE_RAW_TEXT",t[t.PARSABLE_DATA]="PARSABLE_DATA",t}();function lt(t){if(":"!==t[0])return[null,t];var e=t.indexOf(":",1);if(-1===e)throw new Error('Unsupported format "'+t+'" expecting ":namespace:name"');return[t.slice(1,e),t.slice(e+1)]}function dt(t){return null===t?null:lt(t)[0]}function ft(t,e){return t?":"+t+":"+e:e}var pt={Aacute:"\xc1",aacute:"\xe1",Acirc:"\xc2",acirc:"\xe2",acute:"\xb4",AElig:"\xc6",aelig:"\xe6",Agrave:"\xc0",agrave:"\xe0",alefsym:"\u2135",Alpha:"\u0391",alpha:"\u03b1",amp:"&",and:"\u2227",ang:"\u2220",apos:"'",Aring:"\xc5",aring:"\xe5",asymp:"\u2248",Atilde:"\xc3",atilde:"\xe3",Auml:"\xc4",auml:"\xe4",bdquo:"\u201e",Beta:"\u0392",beta:"\u03b2",brvbar:"\xa6",bull:"\u2022",cap:"\u2229",Ccedil:"\xc7",ccedil:"\xe7",cedil:"\xb8",cent:"\xa2",Chi:"\u03a7",chi:"\u03c7",circ:"\u02c6",clubs:"\u2663",cong:"\u2245",copy:"\xa9",crarr:"\u21b5",cup:"\u222a",curren:"\xa4",dagger:"\u2020",Dagger:"\u2021",darr:"\u2193",dArr:"\u21d3",deg:"\xb0",Delta:"\u0394",delta:"\u03b4",diams:"\u2666",divide:"\xf7",Eacute:"\xc9",eacute:"\xe9",Ecirc:"\xca",ecirc:"\xea",Egrave:"\xc8",egrave:"\xe8",empty:"\u2205",emsp:"\u2003",ensp:"\u2002",Epsilon:"\u0395",epsilon:"\u03b5",equiv:"\u2261",Eta:"\u0397",eta:"\u03b7",ETH:"\xd0",eth:"\xf0",Euml:"\xcb",euml:"\xeb",euro:"\u20ac",exist:"\u2203",fnof:"\u0192",forall:"\u2200",frac12:"\xbd",frac14:"\xbc",frac34:"\xbe",frasl:"\u2044",Gamma:"\u0393",gamma:"\u03b3",ge:"\u2265",gt:">",harr:"\u2194",hArr:"\u21d4",hearts:"\u2665",hellip:"\u2026",Iacute:"\xcd",iacute:"\xed",Icirc:"\xce",icirc:"\xee",iexcl:"\xa1",Igrave:"\xcc",igrave:"\xec",image:"\u2111",infin:"\u221e",int:"\u222b",Iota:"\u0399",iota:"\u03b9",iquest:"\xbf",isin:"\u2208",Iuml:"\xcf",iuml:"\xef",Kappa:"\u039a",kappa:"\u03ba",Lambda:"\u039b",lambda:"\u03bb",lang:"\u27e8",laquo:"\xab",larr:"\u2190",lArr:"\u21d0",lceil:"\u2308",ldquo:"\u201c",le:"\u2264",lfloor:"\u230a",lowast:"\u2217",loz:"\u25ca",lrm:"\u200e",lsaquo:"\u2039",lsquo:"\u2018",lt:"<",macr:"\xaf",mdash:"\u2014",micro:"\xb5",middot:"\xb7",minus:"\u2212",Mu:"\u039c",mu:"\u03bc",nabla:"\u2207",nbsp:"\xa0",ndash:"\u2013",ne:"\u2260",ni:"\u220b",not:"\xac",notin:"\u2209",nsub:"\u2284",Ntilde:"\xd1",ntilde:"\xf1",Nu:"\u039d",nu:"\u03bd",Oacute:"\xd3",oacute:"\xf3",Ocirc:"\xd4",ocirc:"\xf4",OElig:"\u0152",oelig:"\u0153",Ograve:"\xd2",ograve:"\xf2",oline:"\u203e",Omega:"\u03a9",omega:"\u03c9",Omicron:"\u039f",omicron:"\u03bf",oplus:"\u2295",or:"\u2228",ordf:"\xaa",ordm:"\xba",Oslash:"\xd8",oslash:"\xf8",Otilde:"\xd5",otilde:"\xf5",otimes:"\u2297",Ouml:"\xd6",ouml:"\xf6",para:"\xb6",permil:"\u2030",perp:"\u22a5",Phi:"\u03a6",phi:"\u03c6",Pi:"\u03a0",pi:"\u03c0",piv:"\u03d6",plusmn:"\xb1",pound:"\xa3",prime:"\u2032",Prime:"\u2033",prod:"\u220f",prop:"\u221d",Psi:"\u03a8",psi:"\u03c8",quot:'"',radic:"\u221a",rang:"\u27e9",raquo:"\xbb",rarr:"\u2192",rArr:"\u21d2",rceil:"\u2309",rdquo:"\u201d",real:"\u211c",reg:"\xae",rfloor:"\u230b",Rho:"\u03a1",rho:"\u03c1",rlm:"\u200f",rsaquo:"\u203a",rsquo:"\u2019",sbquo:"\u201a",Scaron:"\u0160",scaron:"\u0161",sdot:"\u22c5",sect:"\xa7",shy:"\xad",Sigma:"\u03a3",sigma:"\u03c3",sigmaf:"\u03c2",sim:"\u223c",spades:"\u2660",sub:"\u2282",sube:"\u2286",sum:"\u2211",sup:"\u2283",sup1:"\xb9",sup2:"\xb2",sup3:"\xb3",supe:"\u2287",szlig:"\xdf",Tau:"\u03a4",tau:"\u03c4",there4:"\u2234",Theta:"\u0398",theta:"\u03b8",thetasym:"\u03d1",thinsp:"\u2009",THORN:"\xde",thorn:"\xfe",tilde:"\u02dc",times:"\xd7",trade:"\u2122",Uacute:"\xda",uacute:"\xfa",uarr:"\u2191",uArr:"\u21d1",Ucirc:"\xdb",ucirc:"\xfb",Ugrave:"\xd9",ugrave:"\xf9",uml:"\xa8",upsih:"\u03d2",Upsilon:"\u03a5",upsilon:"\u03c5",Uuml:"\xdc",uuml:"\xfc",weierp:"\u2118",Xi:"\u039e",xi:"\u03be",Yacute:"\xdd",yacute:"\xfd",yen:"\xa5",yuml:"\xff",Yuml:"\u0178",Zeta:"\u0396",zeta:"\u03b6",zwj:"\u200d",zwnj:"\u200c",ngsp:"\ue500"},ht=function(){var t={TAG_OPEN_START:0,TAG_OPEN_END:1,TAG_OPEN_END_VOID:2,TAG_CLOSE:3,TEXT:4,ESCAPABLE_RAW_TEXT:5,RAW_TEXT:6,COMMENT_START:7,COMMENT_END:8,CDATA_START:9,CDATA_END:10,ATTR_NAME:11,ATTR_VALUE:12,DOC_TYPE:13,EXPANSION_FORM_START:14,EXPANSION_CASE_VALUE:15,EXPANSION_CASE_EXP_START:16,EXPANSION_CASE_EXP_END:17,EXPANSION_FORM_END:18,EOF:19};return t[t.TAG_OPEN_START]="TAG_OPEN_START",t[t.TAG_OPEN_END]="TAG_OPEN_END",t[t.TAG_OPEN_END_VOID]="TAG_OPEN_END_VOID",t[t.TAG_CLOSE]="TAG_CLOSE",t[t.TEXT]="TEXT",t[t.ESCAPABLE_RAW_TEXT]="ESCAPABLE_RAW_TEXT",t[t.RAW_TEXT]="RAW_TEXT",t[t.COMMENT_START]="COMMENT_START",t[t.COMMENT_END]="COMMENT_END",t[t.CDATA_START]="CDATA_START",t[t.CDATA_END]="CDATA_END",t[t.ATTR_NAME]="ATTR_NAME",t[t.ATTR_VALUE]="ATTR_VALUE",t[t.DOC_TYPE]="DOC_TYPE",t[t.EXPANSION_FORM_START]="EXPANSION_FORM_START",t[t.EXPANSION_CASE_VALUE]="EXPANSION_CASE_VALUE",t[t.EXPANSION_CASE_EXP_START]="EXPANSION_CASE_EXP_START",t[t.EXPANSION_CASE_EXP_END]="EXPANSION_CASE_EXP_END",t[t.EXPANSION_FORM_END]="EXPANSION_FORM_END",t[t.EOF]="EOF",t}(),gt=function(){return function(t,e,n){this.type=t,this.parts=e,this.sourceSpan=n}}(),bt=function(t){function e(e,n,a){var r=t.call(this,a,e)||this;return r.tokenType=n,r}return Object(a.__extends)(e,t),e}(O),mt=function(){return function(t,e){this.tokens=t,this.errors=e}}(),yt=/\r\n?/g;function vt(t){return'Unexpected character "'+(t===N?"EOF":String.fromCharCode(t))+'"'}function _t(t){return'Unknown entity "'+t+'" - use the "&#<decimal>;" or "&#x<hex>;" syntax'}var xt=function(){return function(t){this.error=t}}(),Tt=function(){function t(t,e,n,a){void 0===a&&(a=k),this._file=t,this._getTagDefinition=e,this._tokenizeIcu=n,this._interpolationConfig=a,this._peek=-1,this._nextPeek=-1,this._index=-1,this._line=0,this._column=-1,this._expansionCaseStack=[],this._inInterpolation=!1,this.tokens=[],this.errors=[],this._input=t.content,this._length=t.content.length,this._advance()}return t.prototype._processCarriageReturns=function(t){return t.replace(yt,"\n")},t.prototype.tokenize=function(){for(;this._peek!==N;){var t=this._getLocation();try{this._attemptCharCode(60)?this._attemptCharCode(33)?this._attemptCharCode(91)?this._consumeCdata(t):this._attemptCharCode(z)?this._consumeComment(t):this._consumeDocType(t):this._attemptCharCode(G)?this._consumeTagClose(t):this._consumeTagOpen(t):this._tokenizeIcu&&this._tokenizeExpansionForm()||this._consumeText()}catch(e){if(!(e instanceof xt))throw e;this.errors.push(e.error)}}return this._beginToken(ht.EOF),this._endToken([]),new mt(function(t){for(var e=[],n=void 0,a=0;a<t.length;a++){var r=t[a];n&&n.type===ht.TEXT&&r.type===ht.TEXT?(n.parts[0]+=r.parts[0],n.sourceSpan.end=r.sourceSpan.end):e.push(n=r)}return e}(this.tokens),this.errors)},t.prototype._tokenizeExpansionForm=function(){if(Ct(this._input,this._index,this._interpolationConfig))return this._consumeExpansionFormStart(),!0;if(((t=this._peek)===V||ut(t)||ot(t))&&this._isInExpansionForm())return this._consumeExpansionCaseStart(),!0;var t;if(125===this._peek){if(this._isInExpansionCase())return this._consumeExpansionCaseEnd(),!0;if(this._isInExpansionForm())return this._consumeExpansionFormEnd(),!0}return!1},t.prototype._getLocation=function(){return new x(this._file,this._index,this._line,this._column)},t.prototype._getSpan=function(t,e){return void 0===t&&(t=this._getLocation()),void 0===e&&(e=this._getLocation()),new w(t,e)},t.prototype._beginToken=function(t,e){void 0===e&&(e=this._getLocation()),this._currentTokenStart=e,this._currentTokenType=t},t.prototype._endToken=function(t,e){void 0===e&&(e=this._getLocation());var n=new gt(this._currentTokenType,t,new w(this._currentTokenStart,e));return this.tokens.push(n),this._currentTokenStart=null,this._currentTokenType=null,n},t.prototype._createError=function(t,e){this._isInExpansionForm()&&(t+=' (Do you have an unescaped "{" in your template? Use "{{ \'{\' }}") to escape it.)');var n=new bt(t,this._currentTokenType,e);return this._currentTokenStart=null,this._currentTokenType=null,new xt(n)},t.prototype._advance=function(){if(this._index>=this._length)throw this._createError(vt(N),this._getSpan());this._peek===A?(this._line++,this._column=0):this._peek!==A&&this._peek!==L&&this._column++,this._index++,this._peek=this._index>=this._length?N:this._input.charCodeAt(this._index),this._nextPeek=this._index+1>=this._length?N:this._input.charCodeAt(this._index+1)},t.prototype._attemptCharCode=function(t){return this._peek===t&&(this._advance(),!0)},t.prototype._attemptCharCodeCaseInsensitive=function(t){return e=t,kt(this._peek)===kt(e)&&(this._advance(),!0);var e},t.prototype._requireCharCode=function(t){var e=this._getLocation();if(!this._attemptCharCode(t))throw this._createError(vt(this._peek),this._getSpan(e,e))},t.prototype._attemptStr=function(t){var e=t.length;if(this._index+e>this._length)return!1;for(var n=this._savePosition(),a=0;a<e;a++)if(!this._attemptCharCode(t.charCodeAt(a)))return this._restorePosition(n),!1;return!0},t.prototype._attemptStrCaseInsensitive=function(t){for(var e=0;e<t.length;e++)if(!this._attemptCharCodeCaseInsensitive(t.charCodeAt(e)))return!1;return!0},t.prototype._requireStr=function(t){var e=this._getLocation();if(!this._attemptStr(t))throw this._createError(vt(this._peek),this._getSpan(e))},t.prototype._attemptCharCodeUntilFn=function(t){for(;!t(this._peek);)this._advance()},t.prototype._requireCharCodeUntilFn=function(t,e){var n=this._getLocation();if(this._attemptCharCodeUntilFn(t),this._index-n.offset<e)throw this._createError(vt(this._peek),this._getSpan(n,n))},t.prototype._attemptUntilChar=function(t){for(;this._peek!==t;)this._advance()},t.prototype._readChar=function(t){if(t&&38===this._peek)return this._decodeEntity();var e=this._index;return this._advance(),this._input[e]},t.prototype._decodeEntity=function(){var t=this._getLocation();if(this._advance(),!this._attemptCharCode(35)){var e=this._savePosition();if(this._attemptCharCodeUntilFn(It),this._peek!==Y)return this._restorePosition(e),"&";this._advance();var n=this._input.substring(t.offset+1,this._index-1),a=pt[n];if(!a)throw this._createError(_t(n),this._getSpan(t));return a}var r=this._attemptCharCode(120)||this._attemptCharCode(88),i=this._getLocation().offset;if(this._attemptCharCodeUntilFn(Ot),this._peek!==Y)throw this._createError(vt(this._peek),this._getSpan());this._advance();var s=this._input.substring(i,this._index-1);try{var o=parseInt(s,r?16:10);return String.fromCharCode(o)}catch(c){var u=this._input.substring(t.offset+1,this._index-1);throw this._createError(_t(u),this._getSpan(t))}},t.prototype._consumeRawText=function(t,e,n){var a,r=this._getLocation();this._beginToken(t?ht.ESCAPABLE_RAW_TEXT:ht.RAW_TEXT,r);for(var i=[];a=this._getLocation(),!this._attemptCharCode(e)||!n();)for(this._index>a.offset&&i.push(this._input.substring(a.offset,this._index));this._peek!==e;)i.push(this._readChar(t));return this._endToken([this._processCarriageReturns(i.join(""))],a)},t.prototype._consumeComment=function(t){var e=this;this._beginToken(ht.COMMENT_START,t),this._requireCharCode(z),this._endToken([]);var n=this._consumeRawText(!1,z,function(){return e._attemptStr("->")});this._beginToken(ht.COMMENT_END,n.sourceSpan.end),this._endToken([])},t.prototype._consumeCdata=function(t){var e=this;this._beginToken(ht.CDATA_START,t),this._requireStr("CDATA["),this._endToken([]);var n=this._consumeRawText(!1,93,function(){return e._attemptStr("]>")});this._beginToken(ht.CDATA_END,n.sourceSpan.end),this._endToken([])},t.prototype._consumeDocType=function(t){this._beginToken(ht.DOC_TYPE,t),this._attemptUntilChar(H),this._advance(),this._endToken([this._input.substring(t.offset+2,this._index-1)])},t.prototype._consumePrefixAndName=function(){for(var t,e,n=this._index,a=null;58!==this._peek&&!(((t=this._peek)<X||at<t)&&(t<W||$<t)&&(t<B||t>U));)this._advance();return 58===this._peek?(this._advance(),a=this._input.substring(n,this._index-1),e=this._index):e=n,this._requireCharCodeUntilFn(St,this._index===e?1:0),[a,this._input.substring(e,this._index)]},t.prototype._consumeTagOpen=function(t){var e,n,a=this._savePosition();try{if(!ut(this._peek))throw this._createError(vt(this._peek),this._getSpan());var r=this._index;for(this._consumeTagOpenStart(t),n=(e=this._input.substring(r,this._index)).toLowerCase(),this._attemptCharCodeUntilFn(wt);this._peek!==G&&this._peek!==H;)this._consumeAttributeName(),this._attemptCharCodeUntilFn(wt),this._attemptCharCode(V)&&(this._attemptCharCodeUntilFn(wt),this._consumeAttributeValue()),this._attemptCharCodeUntilFn(wt);this._consumeTagOpenEnd()}catch(s){if(s instanceof xt)return this._restorePosition(a),this._beginToken(ht.TEXT,t),void this._endToken(["<"]);throw s}var i=this._getTagDefinition(e).contentType;i===ct.RAW_TEXT?this._consumeRawTextWithTagClose(n,!1):i===ct.ESCAPABLE_RAW_TEXT&&this._consumeRawTextWithTagClose(n,!0)},t.prototype._consumeRawTextWithTagClose=function(t,e){var n=this,a=this._consumeRawText(e,60,function(){return!!n._attemptCharCode(G)&&(n._attemptCharCodeUntilFn(wt),!!n._attemptStrCaseInsensitive(t)&&(n._attemptCharCodeUntilFn(wt),n._attemptCharCode(H)))});this._beginToken(ht.TAG_CLOSE,a.sourceSpan.end),this._endToken([null,t])},t.prototype._consumeTagOpenStart=function(t){this._beginToken(ht.TAG_OPEN_START,t);var e=this._consumePrefixAndName();this._endToken(e)},t.prototype._consumeAttributeName=function(){this._beginToken(ht.ATTR_NAME);var t=this._consumePrefixAndName();this._endToken(t)},t.prototype._consumeAttributeValue=function(){var t;if(this._beginToken(ht.ATTR_VALUE),this._peek===j||this._peek===M){var e=this._peek;this._advance();for(var n=[];this._peek!==e;)n.push(this._readChar(!0));t=n.join(""),this._advance()}else{var a=this._index;this._requireCharCodeUntilFn(St,1),t=this._input.substring(a,this._index)}this._endToken([this._processCarriageReturns(t)])},t.prototype._consumeTagOpenEnd=function(){var t=this._attemptCharCode(G)?ht.TAG_OPEN_END_VOID:ht.TAG_OPEN_END;this._beginToken(t),this._requireCharCode(H),this._endToken([])},t.prototype._consumeTagClose=function(t){this._beginToken(ht.TAG_CLOSE,t),this._attemptCharCodeUntilFn(wt);var e=this._consumePrefixAndName();this._attemptCharCodeUntilFn(wt),this._requireCharCode(H),this._endToken(e)},t.prototype._consumeExpansionFormStart=function(){this._beginToken(ht.EXPANSION_FORM_START,this._getLocation()),this._requireCharCode(rt),this._endToken([]),this._expansionCaseStack.push(ht.EXPANSION_FORM_START),this._beginToken(ht.RAW_TEXT,this._getLocation());var t=this._readUntil(44);this._endToken([t],this._getLocation()),this._requireCharCode(44),this._attemptCharCodeUntilFn(wt),this._beginToken(ht.RAW_TEXT,this._getLocation());var e=this._readUntil(44);this._endToken([e],this._getLocation()),this._requireCharCode(44),this._attemptCharCodeUntilFn(wt)},t.prototype._consumeExpansionCaseStart=function(){this._beginToken(ht.EXPANSION_CASE_VALUE,this._getLocation());var t=this._readUntil(rt).trim();this._endToken([t],this._getLocation()),this._attemptCharCodeUntilFn(wt),this._beginToken(ht.EXPANSION_CASE_EXP_START,this._getLocation()),this._requireCharCode(rt),this._endToken([],this._getLocation()),this._attemptCharCodeUntilFn(wt),this._expansionCaseStack.push(ht.EXPANSION_CASE_EXP_START)},t.prototype._consumeExpansionCaseEnd=function(){this._beginToken(ht.EXPANSION_CASE_EXP_END,this._getLocation()),this._requireCharCode(125),this._endToken([],this._getLocation()),this._attemptCharCodeUntilFn(wt),this._expansionCaseStack.pop()},t.prototype._consumeExpansionFormEnd=function(){this._beginToken(ht.EXPANSION_FORM_END,this._getLocation()),this._requireCharCode(125),this._endToken([]),this._expansionCaseStack.pop()},t.prototype._consumeText=function(){var t=this._getLocation();this._beginToken(ht.TEXT,t);var e=[];do{this._interpolationConfig&&this._attemptStr(this._interpolationConfig.start)?(e.push(this._interpolationConfig.start),this._inInterpolation=!0):this._interpolationConfig&&this._inInterpolation&&this._attemptStr(this._interpolationConfig.end)?(e.push(this._interpolationConfig.end),this._inInterpolation=!1):e.push(this._readChar(!0))}while(!this._isTextEnd());this._endToken([this._processCarriageReturns(e.join(""))])},t.prototype._isTextEnd=function(){if(60===this._peek||this._peek===N)return!0;if(this._tokenizeIcu&&!this._inInterpolation){if(Ct(this._input,this._index,this._interpolationConfig))return!0;if(125===this._peek&&this._isInExpansionCase())return!0}return!1},t.prototype._savePosition=function(){return[this._peek,this._index,this._column,this._line,this.tokens.length]},t.prototype._readUntil=function(t){var e=this._index;return this._attemptUntilChar(t),this._input.substring(e,this._index)},t.prototype._restorePosition=function(t){this._peek=t[0],this._index=t[1],this._column=t[2],this._line=t[3];var e=t[4];e<this.tokens.length&&(this.tokens=this.tokens.slice(0,e))},t.prototype._isInExpansionCase=function(){return this._expansionCaseStack.length>0&&this._expansionCaseStack[this._expansionCaseStack.length-1]===ht.EXPANSION_CASE_EXP_START},t.prototype._isInExpansionForm=function(){return this._expansionCaseStack.length>0&&this._expansionCaseStack[this._expansionCaseStack.length-1]===ht.EXPANSION_FORM_START},t}();function wt(t){return!st(t)||t===N}function St(t){return st(t)||t===H||t===G||t===j||t===M||t===V}function Ot(t){return t===Y||t===N||!function(t){return t>=X&&t<=J||t>=W&&t<=K||ot(t)}(t)}function It(t){return t===Y||t===N||!ut(t)}function Ct(t,e,n){var a=!!n&&t.indexOf(n.start,e)===e;return t.charCodeAt(e)===rt&&!a}function kt(t){return t>=X&&t<=at?t-X+W:t}var Nt=function(t){function e(e,n,a){var r=t.call(this,n,a)||this;return r.elementName=e,r}return Object(a.__extends)(e,t),e.create=function(t,n,a){return new e(t,n,a)},e}(O),Rt=function(){return function(t,e){this.rootNodes=t,this.errors=e}}(),At=function(){function t(t){this.getTagDefinition=t}return t.prototype.parse=function(t,e,n,a){void 0===n&&(n=!1),void 0===a&&(a=k);var r=function(t,e,n,a,r){return void 0===a&&(a=!1),void 0===r&&(r=k),new Tt(new T(t,e),n,a,r).tokenize()}(t,e,this.getTagDefinition,n,a),i=new Dt(r.tokens,this.getTagDefinition).build();return new Rt(i.rootNodes,r.errors.concat(i.errors))},t}(),Dt=function(){function t(t,e){this.tokens=t,this.getTagDefinition=e,this._index=-1,this._rootNodes=[],this._errors=[],this._elementStack=[],this._advance()}return t.prototype.build=function(){for(;this._peek.type!==ht.EOF;)this._peek.type===ht.TAG_OPEN_START?this._consumeStartTag(this._advance()):this._peek.type===ht.TAG_CLOSE?this._consumeEndTag(this._advance()):this._peek.type===ht.CDATA_START?(this._closeVoidElement(),this._consumeCdata(this._advance())):this._peek.type===ht.COMMENT_START?(this._closeVoidElement(),this._consumeComment(this._advance())):this._peek.type===ht.TEXT||this._peek.type===ht.RAW_TEXT||this._peek.type===ht.ESCAPABLE_RAW_TEXT?(this._closeVoidElement(),this._consumeText(this._advance())):this._peek.type===ht.EXPANSION_FORM_START?this._consumeExpansion(this._advance()):this._advance();return new Rt(this._rootNodes,this._errors)},t.prototype._advance=function(){var t=this._peek;return this._index<this.tokens.length-1&&this._index++,this._peek=this.tokens[this._index],t},t.prototype._advanceIf=function(t){return this._peek.type===t?this._advance():null},t.prototype._consumeCdata=function(t){this._consumeText(this._advance()),this._advanceIf(ht.CDATA_END)},t.prototype._consumeComment=function(t){var e=this._advanceIf(ht.RAW_TEXT);this._advanceIf(ht.COMMENT_END);var n=null!==e?e.parts[0].trim():null;this._addToParent(new d(n,t.sourceSpan))},t.prototype._consumeExpansion=function(t){for(var e=this._advance(),n=this._advance(),a=[];this._peek.type===ht.EXPANSION_CASE_VALUE;){var r=this._parseExpansionCase();if(!r)return;a.push(r)}if(this._peek.type===ht.EXPANSION_FORM_END){var i=new w(t.sourceSpan.start,this._peek.sourceSpan.end);this._addToParent(new o(e.parts[0],n.parts[0],a,i,e.sourceSpan)),this._advance()}else this._errors.push(Nt.create(null,this._peek.sourceSpan,"Invalid ICU message. Missing '}'."))},t.prototype._parseExpansionCase=function(){var e=this._advance();if(this._peek.type!==ht.EXPANSION_CASE_EXP_START)return this._errors.push(Nt.create(null,this._peek.sourceSpan,"Invalid ICU message. Missing '{'.")),null;var n=this._advance(),a=this._collectExpansionExpTokens(n);if(!a)return null;var r=this._advance();a.push(new gt(ht.EOF,[],r.sourceSpan));var i=new t(a,this.getTagDefinition).build();if(i.errors.length>0)return this._errors=this._errors.concat(i.errors),null;var s=new w(e.sourceSpan.start,r.sourceSpan.end),o=new w(n.sourceSpan.start,r.sourceSpan.end);return new u(e.parts[0],i.rootNodes,s,e.sourceSpan,o)},t.prototype._collectExpansionExpTokens=function(t){for(var e=[],n=[ht.EXPANSION_CASE_EXP_START];;){if(this._peek.type!==ht.EXPANSION_FORM_START&&this._peek.type!==ht.EXPANSION_CASE_EXP_START||n.push(this._peek.type),this._peek.type===ht.EXPANSION_CASE_EXP_END){if(!Et(n,ht.EXPANSION_CASE_EXP_START))return this._errors.push(Nt.create(null,t.sourceSpan,"Invalid ICU message. Missing '}'.")),null;if(n.pop(),0===n.length)return e}if(this._peek.type===ht.EXPANSION_FORM_END){if(!Et(n,ht.EXPANSION_FORM_START))return this._errors.push(Nt.create(null,t.sourceSpan,"Invalid ICU message. Missing '}'.")),null;n.pop()}if(this._peek.type===ht.EOF)return this._errors.push(Nt.create(null,t.sourceSpan,"Invalid ICU message. Missing '}'.")),null;e.push(this._advance())}},t.prototype._consumeText=function(t){var e=t.parts[0];if(e.length>0&&"\n"===e[0]){var n=this._getParentElement();null!==n&&0===n.children.length&&this.getTagDefinition(n.name).ignoreFirstLf&&(e=e.substring(1))}e.length>0&&this._addToParent(new s(e,t.sourceSpan))},t.prototype._closeVoidElement=function(){var t=this._getParentElement();t&&this.getTagDefinition(t.name).isVoid&&this._elementStack.pop()},t.prototype._consumeStartTag=function(t){for(var e=t.parts[0],n=t.parts[1],a=[];this._peek.type===ht.ATTR_NAME;)a.push(this._consumeAttr(this._advance()));var r=this._getElementFullName(e,n,this._getParentElement()),i=!1;if(this._peek.type===ht.TAG_OPEN_END_VOID){this._advance(),i=!0;var s=this.getTagDefinition(r);s.canSelfClose||null!==dt(r)||s.isVoid||this._errors.push(Nt.create(r,t.sourceSpan,'Only void and foreign elements can be self closed "'+t.parts[1]+'"'))}else this._peek.type===ht.TAG_OPEN_END&&(this._advance(),i=!1);var o=new w(t.sourceSpan.start,this._peek.sourceSpan.start),u=new l(r,a,[],o,o,void 0);this._pushElement(u),i&&(this._popElement(r),u.endSourceSpan=o)},t.prototype._pushElement=function(t){var e=this._getParentElement();e&&this.getTagDefinition(e.name).isClosedByChild(t.name)&&this._elementStack.pop();var n=this.getTagDefinition(t.name),a=this._getParentElementSkippingContainers(),r=a.parent,i=a.container;if(r&&n.requireExtraParent(r.name)){var s=new l(n.parentToAdd,[],[],t.sourceSpan,t.startSourceSpan,t.endSourceSpan);this._insertBeforeContainer(r,i,s)}this._addToParent(t),this._elementStack.push(t)},t.prototype._consumeEndTag=function(t){var e=this._getElementFullName(t.parts[0],t.parts[1],this._getParentElement());this._getParentElement()&&(this._getParentElement().endSourceSpan=t.sourceSpan),this.getTagDefinition(e).isVoid?this._errors.push(Nt.create(e,t.sourceSpan,'Void elements do not have end tags "'+t.parts[1]+'"')):this._popElement(e)||this._errors.push(Nt.create(e,t.sourceSpan,'Unexpected closing tag "'+e+'". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags'))},t.prototype._popElement=function(t){for(var e=this._elementStack.length-1;e>=0;e--){var n=this._elementStack[e];if(n.name===t)return this._elementStack.splice(e,this._elementStack.length-e),!0;if(!this.getTagDefinition(n.name).closedByParent)return!1}return!1},t.prototype._consumeAttr=function(t){var e=ft(t.parts[0],t.parts[1]),n=t.sourceSpan.end,a="",r=void 0;if(this._peek.type===ht.ATTR_VALUE){var i=this._advance();a=i.parts[0],n=i.sourceSpan.end,r=i.sourceSpan}return new c(e,a,new w(t.sourceSpan.start,n),r)},t.prototype._getParentElement=function(){return this._elementStack.length>0?this._elementStack[this._elementStack.length-1]:null},t.prototype._getParentElementSkippingContainers=function(){for(var t=null,e=this._elementStack.length-1;e>=0;e--){if("ng-container"!==lt(this._elementStack[e].name)[1])return{parent:this._elementStack[e],container:t};t=this._elementStack[e]}return{parent:null,container:t}},t.prototype._addToParent=function(t){var e=this._getParentElement();null!==e?e.children.push(t):this._rootNodes.push(t)},t.prototype._insertBeforeContainer=function(t,e,n){if(e){if(t){var a=t.children.indexOf(e);t.children[a]=n}else this._rootNodes.push(n);n.children.push(e),this._elementStack.splice(this._elementStack.indexOf(e),0,n)}else this._addToParent(n),this._elementStack.push(n)},t.prototype._getElementFullName=function(t,e,n){return null===t&&null===(t=this.getTagDefinition(e).implicitNamespacePrefix)&&null!==n&&(t=dt(n.name)),ft(t,e)},t}();function Et(t,e){return t.length>0&&t[t.length-1]===e}var Lt=new(function(){function t(){this.closedByParent=!1,this.contentType=ct.PARSABLE_DATA,this.isVoid=!1,this.ignoreFirstLf=!1,this.canSelfClose=!0}return t.prototype.requireExtraParent=function(t){return!1},t.prototype.isClosedByChild=function(t){return!1},t}());function Pt(t){return Lt}var Mt=function(){function t(t){var e=void 0===t?{}:t,n=e.closedByChildren,a=e.requiredParents,r=e.implicitNamespacePrefix,i=e.contentType,s=void 0===i?ct.PARSABLE_DATA:i,o=e.closedByParent,u=void 0!==o&&o,c=e.isVoid,l=void 0!==c&&c,d=e.ignoreFirstLf,f=void 0!==d&&d,p=this;this.closedByChildren={},this.closedByParent=!1,this.canSelfClose=!1,n&&n.length>0&&n.forEach(function(t){return p.closedByChildren[t]=!0}),this.isVoid=l,this.closedByParent=u||l,a&&a.length>0&&(this.requiredParents={},this.parentToAdd=a[0],a.forEach(function(t){return p.requiredParents[t]=!0})),this.implicitNamespacePrefix=r||null,this.contentType=s,this.ignoreFirstLf=f}return t.prototype.requireExtraParent=function(t){if(!this.requiredParents)return!1;if(!t)return!0;var e=t.toLowerCase();return!("template"===e||"ng-template"===t)&&!0!==this.requiredParents[e]},t.prototype.isClosedByChild=function(t){return this.isVoid||t.toLowerCase()in this.closedByChildren},t}(),qt={base:new Mt({isVoid:!0}),meta:new Mt({isVoid:!0}),area:new Mt({isVoid:!0}),embed:new Mt({isVoid:!0}),link:new Mt({isVoid:!0}),img:new Mt({isVoid:!0}),input:new Mt({isVoid:!0}),param:new Mt({isVoid:!0}),hr:new Mt({isVoid:!0}),br:new Mt({isVoid:!0}),source:new Mt({isVoid:!0}),track:new Mt({isVoid:!0}),wbr:new Mt({isVoid:!0}),p:new Mt({closedByChildren:["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","nav","ol","p","pre","section","table","ul"],closedByParent:!0}),thead:new Mt({closedByChildren:["tbody","tfoot"]}),tbody:new Mt({closedByChildren:["tbody","tfoot"],closedByParent:!0}),tfoot:new Mt({closedByChildren:["tbody"],closedByParent:!0}),tr:new Mt({closedByChildren:["tr"],requiredParents:["tbody","tfoot","thead"],closedByParent:!0}),td:new Mt({closedByChildren:["td","th"],closedByParent:!0}),th:new Mt({closedByChildren:["td","th"],closedByParent:!0}),col:new Mt({requiredParents:["colgroup"],isVoid:!0}),svg:new Mt({implicitNamespacePrefix:"svg"}),math:new Mt({implicitNamespacePrefix:"math"}),li:new Mt({closedByChildren:["li"],closedByParent:!0}),dt:new Mt({closedByChildren:["dt","dd"]}),dd:new Mt({closedByChildren:["dt","dd"],closedByParent:!0}),rb:new Mt({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),rt:new Mt({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),rtc:new Mt({closedByChildren:["rb","rtc","rp"],closedByParent:!0}),rp:new Mt({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),optgroup:new Mt({closedByChildren:["optgroup"],closedByParent:!0}),option:new Mt({closedByChildren:["option","optgroup"],closedByParent:!0}),pre:new Mt({ignoreFirstLf:!0}),listing:new Mt({ignoreFirstLf:!0}),style:new Mt({contentType:ct.RAW_TEXT}),script:new Mt({contentType:ct.RAW_TEXT}),title:new Mt({contentType:ct.ESCAPABLE_RAW_TEXT}),textarea:new Mt({contentType:ct.ESCAPABLE_RAW_TEXT,ignoreFirstLf:!0})},jt=new Mt;function Ft(t){return qt[t.toLowerCase()]||jt}var zt=function(t){function e(e,n){var a=t.call(this)||this;return a.mapName=n,a.internalToPublic={},a.publicToNextId={},a.publicToInternal={},e.nodes.forEach(function(t){return t.visit(a)}),a}return Object(a.__extends)(e,t),e.prototype.toPublicName=function(t){return this.internalToPublic.hasOwnProperty(t)?this.internalToPublic[t]:null},e.prototype.toInternalName=function(t){return this.publicToInternal.hasOwnProperty(t)?this.publicToInternal[t]:null},e.prototype.visitText=function(t,e){return null},e.prototype.visitTagPlaceholder=function(e,n){this.visitPlaceholderName(e.startName),t.prototype.visitTagPlaceholder.call(this,e,n),this.visitPlaceholderName(e.closeName)},e.prototype.visitPlaceholder=function(t,e){this.visitPlaceholderName(t.name)},e.prototype.visitIcuPlaceholder=function(t,e){this.visitPlaceholderName(t.name)},e.prototype.visitPlaceholderName=function(t){if(t&&!this.internalToPublic.hasOwnProperty(t)){var e=this.mapName(t);if(this.publicToInternal.hasOwnProperty(e)){var n=this.publicToNextId[e];this.publicToNextId[e]=n+1,e=e+"_"+n}else this.publicToNextId[e]=1;this.internalToPublic[t]=e,this.publicToInternal[e]=t}},e}(_),Gt=new r.I18nSelectPipe,Yt=function(){function t(t,e){this.params=e,this.i18nPluralPipe=new r.I18nPluralPipe(new r.NgLocaleLocalization(t))}return t.prototype.visitElement=function(t,e){return Ft(t.name).isVoid?"<"+t.name+this.serializeNodes(t.attrs," ")+"/>":"<"+t.name+this.serializeNodes(t.attrs," ")+">"+this.serializeNodes(t.children)+"</"+t.name+">"},t.prototype.visitAttribute=function(t,e){return t.name+'="'+t.value+'"'},t.prototype.visitText=function(t,e){return t.value},t.prototype.visitComment=function(t,e){return"\x3c!--"+t.value+"--\x3e"},t.prototype.visitExpansion=function(t,e){var n=this,a={};switch(t.cases.forEach(function(t){return a[t.value]=n.serializeNodes(t.expression)}),t.type){case"select":return Gt.transform(this.params[t.switchValue]||"",a);case"plural":return this.i18nPluralPipe.transform(this.params[t.switchValue],a)}throw new Error('Unknown expansion type "'+t.type+'"')},t.prototype.visitExpansionCase=function(t,e){return" "+t.value+" {"+this.serializeNodes(t.expression)+"}"},t.prototype.serializeNodes=function(t,e){var n=this;return void 0===e&&(e=""),0===t.length?"":e+t.map(function(t){return t.visit(n,null)}).join(e)},t}();function Vt(t){return t.id||function(t){var e,n,r=oe(t),i=function(t,e){for(var n=Array(t.length+3>>>2),a=0;a<n.length;a++)n[a]=ae(t,4*a,e);return n}(r,Xt.Big),s=8*r.length,o=new Array(80),u=Object(a.__read)([1732584193,4023233417,2562383102,271733878,3285377520],5),c=u[0],l=u[1],d=u[2],f=u[3],p=u[4];i[s>>5]|=128<<24-s%32,i[15+(s+64>>9<<4)]=s;for(var h=0;h<i.length;h+=16){for(var g=Object(a.__read)([c,l,d,f,p],5),b=g[0],m=g[1],y=g[2],v=g[3],_=g[4],x=0;x<80;x++){o[x]=x<16?i[h+x]:ee(o[x-3]^o[x-8]^o[x-14]^o[x-16],1);var T=Object(a.__read)(Wt(x,l,d,f),2),w=T[0],S=T[1],O=[ee(c,5),w,p,S,o[x]].reduce(Jt);p=(e=Object(a.__read)([f,d,ee(l,30),c,O],5))[0],f=e[1],d=e[2],l=e[3],c=e[4]}c=(n=Object(a.__read)([Jt(c,b),Jt(l,m),Jt(d,y),Jt(f,v),Jt(p,_)],5))[0],l=n[1],d=n[2],f=n[3],p=n[4]}return function(t){for(var e="",n=0;n<t.length;n++){var a=ne(t,n);e+=(a>>>4).toString(16)+(15&a).toString(16)}return e.toLowerCase()}(re([c,l,d,f,p]))}((e=t.nodes,e.map(function(t){return t.visit(Bt,null)})).join("")+"["+t.meaning+"]");var e}var Ht=function(){function t(){}return t.prototype.visitText=function(t,e){return t.value},t.prototype.visitContainer=function(t,e){var n=this;return"["+t.children.map(function(t){return t.visit(n)}).join(", ")+"]"},t.prototype.visitIcu=function(t,e){var n=this,a=Object.keys(t.cases).map(function(e){return e+" {"+t.cases[e].visit(n)+"}"});return"{"+t.expression+", "+t.type+", "+a.join(", ")+"}"},t.prototype.visitTagPlaceholder=function(t,e){var n=this;return t.isVoid?'<ph tag name="'+t.startName+'"/>':'<ph tag name="'+t.startName+'">'+t.children.map(function(t){return t.visit(n)}).join(", ")+'</ph name="'+t.closeName+'">'},t.prototype.visitPlaceholder=function(t,e){return t.value?'<ph name="'+t.name+'">'+t.value+"</ph>":'<ph name="'+t.name+'"/>'},t.prototype.visitIcuPlaceholder=function(t,e){return'<ph icu name="'+t.name+'">'+t.value.visit(this)+"</ph>"},t}(),Bt=new Ht,Ut=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.visitIcu=function(t,e){var n=this,a=Object.keys(t.cases).map(function(e){return e+" {"+t.cases[e].visit(n)+"}"});return"{"+t.type+", "+a.join(", ")+"}"},e}(Ht);function Wt(t,e,n,a){return t<20?[e&n|~e&a,1518500249]:t<40?[e^n^a,1859775393]:t<60?[e&n|e&a|n&a,2400959708]:[e^n^a,3395469782]}function Kt(t){var e=oe(t),n=Object(a.__read)([$t(e,0),$t(e,102072)],2),r=n[0],i=n[1];return 0!==r||0!==i&&1!==i||(r^=319790063,i^=-1801410264),[r,i]}function $t(t,e){var n,r,i=Object(a.__read)([2654435769,2654435769],2),s=i[0],o=i[1],u=t.length;for(n=0;n+12<=u;n+=12)s=Jt(s,ae(t,n,Xt.Little)),o=Jt(o,ae(t,n+4,Xt.Little)),e=Jt(e,ae(t,n+8,Xt.Little)),s=(r=Object(a.__read)(Zt([s,o,e]),3))[0],o=r[1],e=r[2];return s=Jt(s,ae(t,n,Xt.Little)),o=Jt(o,ae(t,n+4,Xt.Little)),e=Jt(e,u),Zt([s,o,e=Jt(e,ae(t,n+8,Xt.Little)<<8)])[2]}function Zt(t){var e=Object(a.__read)(t,3),n=e[0],r=e[1],i=e[2];return n=te(n,r),n=te(n,i),n^=i>>>13,r=te(r,i),r=te(r,n),r^=n<<8,i=te(i,n),i=te(i,r),i^=r>>>13,n=te(n,r),n=te(n,i),n^=i>>>12,r=te(r,i),r=te(r,n),r^=n<<16,i=te(i,n),i=te(i,r),i^=r>>>5,n=te(n,r),n=te(n,i),n^=i>>>3,r=te(r,i),r=te(r,n),r^=n<<10,i=te(i,n),i=te(i,r),[n,r,i^=r>>>15]}var Xt=function(){var t={Little:0,Big:1};return t[t.Little]="Little",t[t.Big]="Big",t}();function Jt(t,e){return Qt(t,e)[1]}function Qt(t,e){var n=(65535&t)+(65535&e),a=(t>>>16)+(e>>>16)+(n>>>16);return[a>>>16,a<<16|65535&n]}function te(t,e){var n=(65535&t)-(65535&e);return(t>>16)-(e>>16)+(n>>16)<<16|65535&n}function ee(t,e){return t<<e|t>>>32-e}function ne(t,e){return e>=t.length?0:255&t.charCodeAt(e)}function ae(t,e,n){var a=0;if(n===Xt.Big)for(var r=0;r<4;r++)a+=ne(t,e+r)<<24-8*r;else for(r=0;r<4;r++)a+=ne(t,e+r)<<8*r;return a}function re(t){return t.reduce(function(t,e){return t+function(t){for(var e="",n=0;n<4;n++)e+=String.fromCharCode(t>>>8*(3-n)&255);return e}(e)},"")}function ie(t,e){for(var n="",a=Math.max(t.length,e.length),r=0,i=0;r<a||i;r++){var s=i+ +(t[r]||0)+ +(e[r]||0);s>=10?(i=1,n+=s-10):(i=0,n+=s)}return n}function se(t,e){for(var n="",a=e;0!==t;t>>>=1)1&t&&(n=ie(n,a)),a=ie(a,a);return n}function oe(t){for(var e="",n=0;n<t.length;n++){var a=t.charCodeAt(n);if(a>=55296&&a<=56319&&t.length>n+1){var r=t.charCodeAt(n+1);r>=56320&&r<=57343&&(n++,a=(a-55296<<10)+r-56320+65536)}a<=127?e+=String.fromCharCode(a):a<=2047?e+=String.fromCharCode(a>>6&31|192,63&a|128):a<=65535?e+=String.fromCharCode(a>>12|224,a>>6&63|128,63&a|128):a<=2097151&&(e+=String.fromCharCode(a>>18&7|240,a>>12&63|128,a>>6&63|128,63&a|128))}return e}function ue(t){var e=(new le).parse(t),n=e.msgIdToHtml,r=e.errors,i={},s=new de;if(Object.keys(n).forEach(function(t){var e=s.convert(n[t]),o=e.i18nNodes,u=e.errors;r.push.apply(r,Object(a.__spread)(u)),i[t]=o}),r.length)throw new Error("xliff parse errors:\n"+r.join("\n"));return i}var ce=Vt,le=function(){function t(){}return t.prototype.parse=function(t){this._unitMlString=null,this._msgIdToHtml={};var e=new At(Pt).parse(t,"",!1);return this._errors=e.errors,f(this,e.rootNodes,null),{msgIdToHtml:this._msgIdToHtml,errors:this._errors}},t.prototype.visitElement=function(t,e){switch(t.name){case"trans-unit":this._unitMlString=null;var n=t.attrs.find(function(t){return"id"===t.name});if(n){var a=n.value;this._msgIdToHtml.hasOwnProperty(a)?this._addError(t,"Duplicated translations for msg "+a):(f(this,t.children,null),"string"==typeof this._unitMlString?this._msgIdToHtml[a]=this._unitMlString:this._addError(t,"Message "+a+" misses a translation"))}else this._addError(t,'<trans-unit> misses the "id" attribute');break;case"source":break;case"target":var r=t.startSourceSpan.start.file.content.slice(t.startSourceSpan.end.offset,t.endSourceSpan.start.offset);this._unitMlString=r;break;case"file":f(this,t.children,null);break;default:f(this,t.children,null)}},t.prototype.visitAttribute=function(t,e){},t.prototype.visitText=function(t,e){},t.prototype.visitComment=function(t,e){},t.prototype.visitExpansion=function(t,e){},t.prototype.visitExpansionCase=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}(),de=function(){function t(){}return t.prototype.convert=function(t){var e=new At(Pt).parse(t,"",!0);return this._errors=e.errors,{i18nNodes:this._errors.length>0||0===e.rootNodes.length?[]:f(this,e.rootNodes),errors:this._errors}},t.prototype.visitText=function(t,e){return new h(t.value,t.sourceSpan)},t.prototype.visitElement=function(t,e){if("x"===t.name){var n=t.attrs.find(function(t){return"id"===t.name});if(n)return new y("",n.value,t.sourceSpan);this._addError(t,'<x> misses the "id" attribute')}else this._addError(t,"Unexpected tag");return null},t.prototype.visitExpansion=function(t,e){var n={};return f(this,t.cases).forEach(function(e){n[e.value]=new g(e.nodes,t.sourceSpan)}),new b(t.switchValue,t.type,n,t.sourceSpan)},t.prototype.visitExpansionCase=function(t,e){return{value:t.value,nodes:f(this,t.expression)}},t.prototype.visitComment=function(t,e){},t.prototype.visitAttribute=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}();function fe(t){var e=(new he).parse(t),n=e.msgIdToHtml,r=e.errors,i={},s=new ge;if(Object.keys(n).forEach(function(t){var e=s.convert(n[t]),o=e.i18nNodes,u=e.errors;r.push.apply(r,Object(a.__spread)(u)),i[t]=o}),r.length)throw new Error("xliff2 parse errors:\n"+r.join("\n"));return i}var pe=function(t){if(t.id)return t.id;var e=new Ut;return function(t,e){var n,r=Object(a.__read)(Kt(t),2),i=r[0],s=r[1];if(e){var o=Object(a.__read)(Kt(e),2),u=o[0],c=o[1];i=(n=Object(a.__read)(function(t,e){var n=Object(a.__read)(t,2),r=n[0],i=n[1],s=Object(a.__read)(e,2),o=s[0],u=s[1],c=Object(a.__read)(Qt(i,u),2),l=c[0],d=c[1];return[Jt(Jt(r,o),l),d]}(function(t,e){var n=Object(a.__read)(t,2),r=n[0],i=n[1];return[r<<1|i>>>31,i<<1|r>>>31]}([i,s]),[u,c]),2))[0],s=n[1]}return function(t){for(var e="",n="1",a=t.length-1;a>=0;a--)e=ie(e,se(ne(t,a),n)),n=se(256,n);return e.split("").reverse().join("")}(re([2147483647&i,s]))}(t.nodes.map(function(t){return t.visit(e,null)}).join(""),t.meaning)},he=function(){function t(){}return t.prototype.parse=function(t){this._unitMlString=null,this._msgIdToHtml={};var e=new At(Pt).parse(t,"",!1);return this._errors=e.errors,f(this,e.rootNodes,null),{msgIdToHtml:this._msgIdToHtml,errors:this._errors}},t.prototype.visitElement=function(t,e){switch(t.name){case"unit":this._unitMlString=null;var n=t.attrs.find(function(t){return"id"===t.name});if(n){var a=n.value;this._msgIdToHtml.hasOwnProperty(a)?this._addError(t,"Duplicated translations for msg "+a):(f(this,t.children,null),"string"==typeof this._unitMlString?this._msgIdToHtml[a]=this._unitMlString:this._addError(t,"Message "+a+" misses a translation"))}else this._addError(t,'<unit> misses the "id" attribute');break;case"source":break;case"target":var r=t.startSourceSpan.start.file.content.slice(t.startSourceSpan.end.offset,t.endSourceSpan.start.offset);this._unitMlString=r;break;case"xliff":var i=t.attrs.find(function(t){return"version"===t.name});if(i){var s=i.value;"2.0"!==s?this._addError(t,"The XLIFF file version "+s+" is not compatible with XLIFF 2.0 serializer"):f(this,t.children,null)}break;default:f(this,t.children,null)}},t.prototype.visitAttribute=function(t,e){},t.prototype.visitText=function(t,e){},t.prototype.visitComment=function(t,e){},t.prototype.visitExpansion=function(t,e){},t.prototype.visitExpansionCase=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}(),ge=function(){function t(){}return t.prototype.convert=function(t){var e=new At(Pt).parse(t,"",!0);return this._errors=e.errors,{i18nNodes:this._errors.length>0||0===e.rootNodes.length?[]:[].concat.apply([],Object(a.__spread)(f(this,e.rootNodes))),errors:this._errors}},t.prototype.visitText=function(t,e){return new h(t.value,t.sourceSpan)},t.prototype.visitElement=function(t,e){var n=this;switch(t.name){case"ph":var r=t.attrs.find(function(t){return"equiv"===t.name});if(r)return[new y("",r.value,t.sourceSpan)];this._addError(t,'<ph> misses the "equiv" attribute');break;case"pc":var i=t.attrs.find(function(t){return"equivStart"===t.name}),s=t.attrs.find(function(t){return"equivEnd"===t.name});if(i){if(s){var o=i.value,u=s.value,c=[];return c.concat.apply(c,Object(a.__spread)([new y("",o,t.sourceSpan)],t.children.map(function(t){return t.visit(n,null)}),[new y("",u,t.sourceSpan)]))}this._addError(t,'<ph> misses the "equivEnd" attribute')}else this._addError(t,'<ph> misses the "equivStart" attribute');break;default:this._addError(t,"Unexpected tag")}return null},t.prototype.visitExpansion=function(t,e){var n={};return f(this,t.cases).forEach(function(e){n[e.value]=new g(e.nodes,t.sourceSpan)}),new b(t.switchValue,t.type,n,t.sourceSpan)},t.prototype.visitExpansionCase=function(t,e){return{value:t.value,nodes:[].concat.apply([],Object(a.__spread)(f(this,t.expression)))}},t.prototype.visitComment=function(t,e){},t.prototype.visitAttribute=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}();function be(t){return t.toUpperCase().replace(/[^A-Z0-9_]/g,"_")}function me(t){var e=(new _e).parse(t),n=e.msgIdToHtml,a=e.errors;if(a.length)throw new Error("xtb parse errors:\n"+a.join("\n"));var r={},i=new xe;return Object.keys(n).forEach(function(t){var e,a;e=r,a=t,Object.defineProperty(e,a,{configurable:!0,enumerable:!0,get:function(){var r=function(){var e=i.convert(n[t]),a=e.i18nNodes,r=e.errors;if(r.length)throw new Error("xtb parse errors:\n"+r.join("\n"));return a}();return Object.defineProperty(e,a,{enumerable:!0,value:r}),r},set:function(t){throw new Error("Could not overwrite an XTB translation")}})}),r}var ye=Vt,ve=function(t){return new zt(t,be)},_e=function(){function t(){}return t.prototype.parse=function(t){this._bundleDepth=0,this._msgIdToHtml={};var e=new At(Pt).parse(t,"",!1);return this._errors=e.errors,f(this,e.rootNodes),{msgIdToHtml:this._msgIdToHtml,errors:this._errors}},t.prototype.visitElement=function(t,e){switch(t.name){case"translationbundle":this._bundleDepth++,this._bundleDepth>1&&this._addError(t,"<translationbundle> elements can not be nested"),f(this,t.children,null),this._bundleDepth--;break;case"translation":var n=t.attrs.find(function(t){return"id"===t.name});if(n){var a=n.value;if(this._msgIdToHtml.hasOwnProperty(a))this._addError(t,"Duplicated translations for msg "+a);else{var r=t.startSourceSpan.start.file.content.slice(t.startSourceSpan.end.offset,t.endSourceSpan.start.offset);this._msgIdToHtml[a]=r}}else this._addError(t,'<translation> misses the "id" attribute');break;default:this._addError(t,"Unexpected tag")}},t.prototype.visitAttribute=function(t,e){},t.prototype.visitText=function(t,e){},t.prototype.visitComment=function(t,e){},t.prototype.visitExpansion=function(t,e){},t.prototype.visitExpansionCase=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}(),xe=function(){function t(){}return t.prototype.convert=function(t){var e=new At(Pt).parse(t,"",!0);return this._errors=e.errors,{i18nNodes:this._errors.length>0||0===e.rootNodes.length?[]:f(this,e.rootNodes),errors:this._errors}},t.prototype.visitText=function(t,e){return new h(t.value,t.sourceSpan)},t.prototype.visitExpansion=function(t,e){var n={};return f(this,t.cases).forEach(function(e){n[e.value]=new g(e.nodes,t.sourceSpan)}),new b(t.switchValue,t.type,n,t.sourceSpan)},t.prototype.visitExpansionCase=function(t,e){return{value:t.value,nodes:f(this,t.expression)}},t.prototype.visitElement=function(t,e){if("ph"===t.name){var n=t.attrs.find(function(t){return"name"===t.name});if(n)return new y("",n.value,t.sourceSpan);this._addError(t,'<ph> misses the "name" attribute')}else this._addError(t,"Unexpected tag");return null},t.prototype.visitComment=function(t,e){},t.prototype.visitAttribute=function(t,e){},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}(),Te=function(){return function(t,e,n,a){this.input=e,this.errLocation=n,this.ctxLocation=a,this.message="Parser Error: "+t+" "+n+" ["+e+"] in "+a}}(),we=function(){return function(t,e){this.start=t,this.end=e}}(),Se=function(){function t(t){this.span=t}return t.prototype.visit=function(t,e){return void 0===e&&(e=null),null},t.prototype.toString=function(){return"AST"},t}(),Oe=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.prefix=n,i.uninterpretedExpression=a,i.location=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitQuote(this,e)},e.prototype.toString=function(){return"Quote"},e}(Se),Ie=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){void 0===e&&(e=null)},e}(Se),Ce=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitImplicitReceiver(this,e)},e}(Se),ke=function(t){function e(e,n){var a=t.call(this,e)||this;return a.expressions=n,a}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitChain(this,e)},e}(Se),Ne=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.condition=n,i.trueExp=a,i.falseExp=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitConditional(this,e)},e}(Se),Re=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.receiver=n,r.name=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitPropertyRead(this,e)},e}(Se),Ae=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.receiver=n,i.name=a,i.value=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitPropertyWrite(this,e)},e}(Se),De=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.receiver=n,r.name=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitSafePropertyRead(this,e)},e}(Se),Ee=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.obj=n,r.key=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitKeyedRead(this,e)},e}(Se),Le=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.obj=n,i.key=a,i.value=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitKeyedWrite(this,e)},e}(Se),Pe=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.exp=n,i.name=a,i.args=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitPipe(this,e)},e}(Se),Me=function(t){function e(e,n){var a=t.call(this,e)||this;return a.value=n,a}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitLiteralPrimitive(this,e)},e}(Se),qe=function(t){function e(e,n){var a=t.call(this,e)||this;return a.expressions=n,a}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitLiteralArray(this,e)},e}(Se),je=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.keys=n,r.values=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitLiteralMap(this,e)},e}(Se),Fe=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.strings=n,r.expressions=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitInterpolation(this,e)},e}(Se),ze=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.operation=n,i.left=a,i.right=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitBinary(this,e)},e}(Se),Ge=function(t){function e(e,n){var a=t.call(this,e)||this;return a.expression=n,a}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitPrefixNot(this,e)},e}(Se),Ye=function(t){function e(e,n){var a=t.call(this,e)||this;return a.expression=n,a}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitNonNullAssert(this,e)},e}(Se),Ve=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.receiver=n,i.name=a,i.args=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitMethodCall(this,e)},e}(Se),He=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.receiver=n,i.name=a,i.args=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitSafeMethodCall(this,e)},e}(Se),Be=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.target=n,r.args=a,r}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),t.visitFunctionCall(this,e)},e}(Se),Ue=function(t){function e(e,n,a,r){var i=t.call(this,new we(0,null==n?0:n.length))||this;return i.ast=e,i.source=n,i.location=a,i.errors=r,i}return Object(a.__extends)(e,t),e.prototype.visit=function(t,e){return void 0===e&&(e=null),this.ast.visit(t,e)},e.prototype.toString=function(){return this.source+" in "+this.location},e}(Se),We=function(){return function(t,e,n,a,r){this.span=t,this.key=e,this.keyIsVar=n,this.name=a,this.expression=r}}(),Ke=function(){var t={Character:0,Identifier:1,Keyword:2,String:3,Operator:4,Number:5,Error:6};return t[t.Character]="Character",t[t.Identifier]="Identifier",t[t.Keyword]="Keyword",t[t.String]="String",t[t.Operator]="Operator",t[t.Number]="Number",t[t.Error]="Error",t}(),$e=["var","let","as","null","undefined","true","false","if","else","this"],Ze=function(){function t(){}return t.prototype.tokenize=function(t){for(var e=new en(t),n=[],a=e.scanToken();null!=a;)n.push(a),a=e.scanToken();return n},t}(),Xe=function(){function t(t,e,n,a){this.index=t,this.type=e,this.numValue=n,this.strValue=a}return t.prototype.isCharacter=function(t){return this.type===Ke.Character&&this.numValue===t},t.prototype.isNumber=function(){return this.type===Ke.Number},t.prototype.isString=function(){return this.type===Ke.String},t.prototype.isOperator=function(t){return this.type===Ke.Operator&&this.strValue===t},t.prototype.isIdentifier=function(){return this.type===Ke.Identifier},t.prototype.isKeyword=function(){return this.type===Ke.Keyword},t.prototype.isKeywordLet=function(){return this.type===Ke.Keyword&&"let"===this.strValue},t.prototype.isKeywordAs=function(){return this.type===Ke.Keyword&&"as"===this.strValue},t.prototype.isKeywordNull=function(){return this.type===Ke.Keyword&&"null"===this.strValue},t.prototype.isKeywordUndefined=function(){return this.type===Ke.Keyword&&"undefined"===this.strValue},t.prototype.isKeywordTrue=function(){return this.type===Ke.Keyword&&"true"===this.strValue},t.prototype.isKeywordFalse=function(){return this.type===Ke.Keyword&&"false"===this.strValue},t.prototype.isKeywordThis=function(){return this.type===Ke.Keyword&&"this"===this.strValue},t.prototype.isError=function(){return this.type===Ke.Error},t.prototype.toNumber=function(){return this.type===Ke.Number?this.numValue:-1},t.prototype.toString=function(){switch(this.type){case Ke.Character:case Ke.Identifier:case Ke.Keyword:case Ke.Operator:case Ke.String:case Ke.Error:return this.strValue;case Ke.Number:return this.numValue.toString();default:return null}},t}();function Je(t,e){return new Xe(t,Ke.Character,e,String.fromCharCode(e))}function Qe(t,e){return new Xe(t,Ke.Operator,0,e)}var tn=new Xe(-1,Ke.Character,0,""),en=function(){function t(t){this.input=t,this.peek=0,this.index=-1,this.length=t.length,this.advance()}return t.prototype.advance=function(){this.peek=++this.index>=this.length?N:this.input.charCodeAt(this.index)},t.prototype.scanToken=function(){for(var t=this.input,e=this.length,n=this.peek,a=this.index;n<=P;){if(++a>=e){n=N;break}n=t.charCodeAt(a)}if(this.peek=n,this.index=a,a>=e)return null;if(nn(n))return this.scanIdentifier();if(ot(n))return this.scanNumber(a);var r=a;switch(n){case 46:return this.advance(),ot(this.peek)?this.scanNumber(r):Je(r,46);case 40:case 41:case rt:case 125:case 91:case 93:case 44:case 58:case Y:return this.scanCharacter(r,n);case j:case M:return this.scanString();case 35:case F:case z:case 42:case G:case 37:case 94:return this.scanOperator(r,String.fromCharCode(n));case 63:return this.scanComplexOperator(r,"?",46,".");case 60:case H:return this.scanComplexOperator(r,String.fromCharCode(n),V,"=");case 33:case V:return this.scanComplexOperator(r,String.fromCharCode(n),V,"=",V,"=");case 38:return this.scanComplexOperator(r,"&",38,"&");case 124:return this.scanComplexOperator(r,"|",124,"|");case it:for(;st(this.peek);)this.advance();return this.scanToken()}return this.advance(),this.error("Unexpected character ["+String.fromCharCode(n)+"]",0)},t.prototype.scanCharacter=function(t,e){return this.advance(),Je(t,e)},t.prototype.scanOperator=function(t,e){return this.advance(),Qe(t,e)},t.prototype.scanComplexOperator=function(t,e,n,a,r,i){this.advance();var s=e;return this.peek===n&&(this.advance(),s+=a),null!=r&&this.peek===r&&(this.advance(),s+=i),Qe(t,s)},t.prototype.scanIdentifier=function(){var t=this.index;for(this.advance();an(this.peek);)this.advance();var e=this.input.substring(t,this.index);return $e.indexOf(e)>-1?new Xe(t,Ke.Keyword,0,e):new Xe(t,Ke.Identifier,0,e)},t.prototype.scanNumber=function(t){var e,n=this.index===t;for(this.advance();;){if(ot(this.peek));else if(46===this.peek)n=!1;else{if(101!==(e=this.peek)&&69!==e)break;if(this.advance(),rn(this.peek)&&this.advance(),!ot(this.peek))return this.error("Invalid exponent",-1);n=!1}this.advance()}var a=this.input.substring(t,this.index),r=n?function(t){var e=parseInt(t,10);if(isNaN(e))throw new Error("Invalid integer literal when parsing "+t);return e}(a):parseFloat(a);return new Xe(t,Ke.Number,r,"")},t.prototype.scanString=function(){var t=this.index,e=this.peek;this.advance();for(var n="",a=this.index,r=this.input;this.peek!==e;)if(92===this.peek){n+=r.substring(a,this.index),this.advance();var i=void 0;if(this.peek=this.peek,117===this.peek){var s=r.substring(this.index+1,this.index+5);if(!/^[0-9a-f]+$/i.test(s))return this.error("Invalid unicode escape [\\u"+s+"]",0);i=parseInt(s,16);for(var o=0;o<5;o++)this.advance()}else i=sn(this.peek),this.advance();n+=String.fromCharCode(i),a=this.index}else{if(this.peek===N)return this.error("Unterminated quote",0);this.advance()}var u=r.substring(a,this.index);return this.advance(),new Xe(t,Ke.String,0,n+u)},t.prototype.error=function(t,e){var n=this.index+e;return function(t,e){return new Xe(n,Ke.Error,0,e)}(0,"Lexer Error: "+t+" at column "+n+" in expression ["+this.input+"]")},t}();function nn(t){return X<=t&&t<=at||W<=t&&t<=$||t===Z||t===q}function an(t){return ut(t)||ot(t)||t===Z||t===q}function rn(t){return t===z||t===F}function sn(t){switch(t){case Q:return A;case J:return E;case tt:return L;case et:return R;case nt:return D;default:return t}}var on=function(){return function(t,e,n){this.strings=t,this.expressions=e,this.offsets=n}}(),un=function(){return function(t,e,n){this.templateBindings=t,this.warnings=e,this.errors=n}}();function cn(t){var e=C(t.start)+"([\\s\\S]*?)"+C(t.end);return new RegExp(e,"g")}var ln=function(){function t(t){this._lexer=t,this.errors=[]}return t.prototype.parseAction=function(t,e,n){void 0===n&&(n=k),this._checkNoInterpolation(t,e,n);var a=this._stripComments(t),r=this._lexer.tokenize(this._stripComments(t)),i=new dn(t,e,r,a.length,!0,this.errors,t.length-a.length).parseChain();return new Ue(i,t,e,this.errors)},t.prototype.parseBinding=function(t,e,n){void 0===n&&(n=k);var a=this._parseBindingAst(t,e,n);return new Ue(a,t,e,this.errors)},t.prototype.parseSimpleBinding=function(t,e,n){void 0===n&&(n=k);var a=this._parseBindingAst(t,e,n),r=fn.check(a);return r.length>0&&this._reportError("Host binding expression cannot contain "+r.join(" "),t,e),new Ue(a,t,e,this.errors)},t.prototype._reportError=function(t,e,n,a){this.errors.push(new Te(t,e,n,a))},t.prototype._parseBindingAst=function(t,e,n){var a=this._parseQuote(t,e);if(null!=a)return a;this._checkNoInterpolation(t,e,n);var r=this._stripComments(t),i=this._lexer.tokenize(r);return new dn(t,e,i,r.length,!1,this.errors,t.length-r.length).parseChain()},t.prototype._parseQuote=function(t,e){if(null===t)return null;var n=t.indexOf(":");if(-1===n)return null;var a=t.substring(0,n).trim();if(!function(t){if(0===a.length)return!1;var e=new en(a);if(!nn(e.peek))return!1;for(e.advance();e.peek!==N;){if(!an(e.peek))return!1;e.advance()}return!0}())return null;var r=t.substring(n+1);return new Oe(new we(0,t.length),a,r,e)},t.prototype.parseTemplateBindings=function(t,e,n){var r=this._lexer.tokenize(e);if(t){var i=this._lexer.tokenize(t).map(function(t){return t.index=0,t});r.unshift.apply(r,Object(a.__spread)(i))}return new dn(e,n,r,e.length,!1,this.errors,0).parseTemplateBindings()},t.prototype.parseInterpolation=function(t,e,n){void 0===n&&(n=k);var a=this.splitInterpolation(t,e,n);if(null===a)return null;for(var r=[],i=0;i<a.expressions.length;++i){var s=a.expressions[i],o=this._stripComments(s),u=this._lexer.tokenize(o),c=new dn(t,e,u,o.length,!1,this.errors,a.offsets[i]+(s.length-o.length)).parseChain();r.push(c)}return new Ue(new Fe(new we(0,null===t?0:t.length),a.strings,r),t,e,this.errors)},t.prototype.splitInterpolation=function(t,e,n){void 0===n&&(n=k);var a=cn(n),r=t.split(a);if(r.length<=1)return null;for(var i=[],s=[],o=[],u=0,c=0;c<r.length;c++){var l=r[c];c%2==0?(i.push(l),u+=l.length):l.trim().length>0?(u+=n.start.length,s.push(l),o.push(u),u+=l.length+n.end.length):(this._reportError("Blank expressions are not allowed in interpolated strings",t,"at column "+this._findInterpolationErrorColumn(r,c,n)+" in",e),s.push("$implict"),o.push(u))}return new on(i,s,o)},t.prototype.wrapLiteralPrimitive=function(t,e){return new Ue(new Me(new we(0,null===t?0:t.length),t),t,e,this.errors)},t.prototype._stripComments=function(t){var e=this._commentStart(t);return null!=e?t.substring(0,e).trim():t},t.prototype._commentStart=function(t){for(var e,n=null,a=0;a<t.length-1;a++){var r=t.charCodeAt(a),i=t.charCodeAt(a+1);if(r===G&&i===G&&null===n)return a;n===r?n=null:null===n&&((e=r)===j||e===M||96===e)&&(n=r)}return null},t.prototype._checkNoInterpolation=function(t,e,n){var a=cn(n),r=t.split(a);r.length>1&&this._reportError("Got interpolation ("+n.start+n.end+") where expression was expected",t,"at column "+this._findInterpolationErrorColumn(r,1,n)+" in",e)},t.prototype._findInterpolationErrorColumn=function(t,e,n){for(var a="",r=0;r<e;r++)a+=r%2==0?t[r]:""+n.start+t[r]+n.end;return a.length},t}(),dn=function(){function t(t,e,n,a,r,i,s){this.input=t,this.location=e,this.tokens=n,this.inputLength=a,this.parseAction=r,this.errors=i,this.offset=s,this.rparensExpected=0,this.rbracketsExpected=0,this.rbracesExpected=0,this.index=0}return t.prototype.peek=function(t){var e=this.index+t;return e<this.tokens.length?this.tokens[e]:tn},Object.defineProperty(t.prototype,"next",{get:function(){return this.peek(0)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"inputIndex",{get:function(){return this.index<this.tokens.length?this.next.index+this.offset:this.inputLength+this.offset},enumerable:!0,configurable:!0}),t.prototype.span=function(t){return new we(t,this.inputIndex)},t.prototype.advance=function(){this.index++},t.prototype.optionalCharacter=function(t){return!!this.next.isCharacter(t)&&(this.advance(),!0)},t.prototype.peekKeywordLet=function(){return this.next.isKeywordLet()},t.prototype.peekKeywordAs=function(){return this.next.isKeywordAs()},t.prototype.expectCharacter=function(t){this.optionalCharacter(t)||this.error("Missing expected "+String.fromCharCode(t))},t.prototype.optionalOperator=function(t){return!!this.next.isOperator(t)&&(this.advance(),!0)},t.prototype.expectOperator=function(t){this.optionalOperator(t)||this.error("Missing expected operator "+t)},t.prototype.expectIdentifierOrKeyword=function(){var t=this.next;return t.isIdentifier()||t.isKeyword()?(this.advance(),t.toString()):(this.error("Unexpected token "+t+", expected identifier or keyword"),"")},t.prototype.expectIdentifierOrKeywordOrString=function(){var t=this.next;return t.isIdentifier()||t.isKeyword()||t.isString()?(this.advance(),t.toString()):(this.error("Unexpected token "+t+", expected identifier, keyword, or string"),"")},t.prototype.parseChain=function(){for(var t=[],e=this.inputIndex;this.index<this.tokens.length;){var n=this.parsePipe();if(t.push(n),this.optionalCharacter(Y))for(this.parseAction||this.error("Binding expression cannot contain chained expression");this.optionalCharacter(Y););else this.index<this.tokens.length&&this.error("Unexpected token '"+this.next+"'")}return 0===t.length?new Ie(this.span(e)):1===t.length?t[0]:new ke(this.span(e),t)},t.prototype.parsePipe=function(){var t=this.parseExpression();if(this.optionalOperator("|")){this.parseAction&&this.error("Cannot have a pipe in an action expression");do{for(var e=this.expectIdentifierOrKeyword(),n=[];this.optionalCharacter(58);)n.push(this.parseExpression());t=new Pe(this.span(t.span.start),t,e,n)}while(this.optionalOperator("|"))}return t},t.prototype.parseExpression=function(){return this.parseConditional()},t.prototype.parseConditional=function(){var t=this.inputIndex,e=this.parseLogicalOr();if(this.optionalOperator("?")){var n=this.parsePipe(),a=void 0;if(this.optionalCharacter(58))a=this.parsePipe();else{var r=this.input.substring(t,this.inputIndex);this.error("Conditional expression "+r+" requires all 3 expressions"),a=new Ie(this.span(t))}return new Ne(this.span(t),e,n,a)}return e},t.prototype.parseLogicalOr=function(){for(var t=this.parseLogicalAnd();this.optionalOperator("||");){var e=this.parseLogicalAnd();t=new ze(this.span(t.span.start),"||",t,e)}return t},t.prototype.parseLogicalAnd=function(){for(var t=this.parseEquality();this.optionalOperator("&&");){var e=this.parseEquality();t=new ze(this.span(t.span.start),"&&",t,e)}return t},t.prototype.parseEquality=function(){for(var t=this.parseRelational();this.next.type===Ke.Operator;){var e=this.next.strValue;switch(e){case"==":case"===":case"!=":case"!==":this.advance();var n=this.parseRelational();t=new ze(this.span(t.span.start),e,t,n);continue}break}return t},t.prototype.parseRelational=function(){for(var t=this.parseAdditive();this.next.type===Ke.Operator;){var e=this.next.strValue;switch(e){case"<":case">":case"<=":case">=":this.advance();var n=this.parseAdditive();t=new ze(this.span(t.span.start),e,t,n);continue}break}return t},t.prototype.parseAdditive=function(){for(var t=this.parseMultiplicative();this.next.type===Ke.Operator;){var e=this.next.strValue;switch(e){case"+":case"-":this.advance();var n=this.parseMultiplicative();t=new ze(this.span(t.span.start),e,t,n);continue}break}return t},t.prototype.parseMultiplicative=function(){for(var t=this.parsePrefix();this.next.type===Ke.Operator;){var e=this.next.strValue;switch(e){case"*":case"%":case"/":this.advance();var n=this.parsePrefix();t=new ze(this.span(t.span.start),e,t,n);continue}break}return t},t.prototype.parsePrefix=function(){if(this.next.type===Ke.Operator){var t=this.inputIndex,e=this.next.strValue,n=void 0;switch(e){case"+":return this.advance(),this.parsePrefix();case"-":return this.advance(),n=this.parsePrefix(),new ze(this.span(t),e,new Me(new we(t,t),0),n);case"!":return this.advance(),n=this.parsePrefix(),new Ge(this.span(t),n)}}return this.parseCallChain()},t.prototype.parseCallChain=function(){for(var t=this.parsePrimary();;)if(this.optionalCharacter(46))t=this.parseAccessMemberOrMethodCall(t,!1);else if(this.optionalOperator("?."))t=this.parseAccessMemberOrMethodCall(t,!0);else if(this.optionalCharacter(91)){this.rbracketsExpected++;var e=this.parsePipe();if(this.rbracketsExpected--,this.expectCharacter(93),this.optionalOperator("=")){var n=this.parseConditional();t=new Le(this.span(t.span.start),t,e,n)}else t=new Ee(this.span(t.span.start),t,e)}else if(this.optionalCharacter(40)){this.rparensExpected++;var a=this.parseCallArguments();this.rparensExpected--,this.expectCharacter(41),t=new Be(this.span(t.span.start),t,a)}else{if(!this.optionalOperator("!"))return t;t=new Ye(this.span(t.span.start),t)}},t.prototype.parsePrimary=function(){var t=this.inputIndex;if(this.optionalCharacter(40)){this.rparensExpected++;var e=this.parsePipe();return this.rparensExpected--,this.expectCharacter(41),e}if(this.next.isKeywordNull())return this.advance(),new Me(this.span(t),null);if(this.next.isKeywordUndefined())return this.advance(),new Me(this.span(t),void 0);if(this.next.isKeywordTrue())return this.advance(),new Me(this.span(t),!0);if(this.next.isKeywordFalse())return this.advance(),new Me(this.span(t),!1);if(this.next.isKeywordThis())return this.advance(),new Ce(this.span(t));if(this.optionalCharacter(91)){this.rbracketsExpected++;var n=this.parseExpressionList(93);return this.rbracketsExpected--,this.expectCharacter(93),new qe(this.span(t),n)}if(this.next.isCharacter(rt))return this.parseLiteralMap();if(this.next.isIdentifier())return this.parseAccessMemberOrMethodCall(new Ce(this.span(t)),!1);if(this.next.isNumber()){var a=this.next.toNumber();return this.advance(),new Me(this.span(t),a)}if(this.next.isString()){var r=this.next.toString();return this.advance(),new Me(this.span(t),r)}return this.index>=this.tokens.length?(this.error("Unexpected end of expression: "+this.input),new Ie(this.span(t))):(this.error("Unexpected token "+this.next),new Ie(this.span(t)))},t.prototype.parseExpressionList=function(t){var e=[];if(!this.next.isCharacter(t))do{e.push(this.parsePipe())}while(this.optionalCharacter(44));return e},t.prototype.parseLiteralMap=function(){var t=[],e=[],n=this.inputIndex;if(this.expectCharacter(rt),!this.optionalCharacter(125)){this.rbracesExpected++;do{var a=this.next.isString(),r=this.expectIdentifierOrKeywordOrString();t.push({key:r,quoted:a}),this.expectCharacter(58),e.push(this.parsePipe())}while(this.optionalCharacter(44));this.rbracesExpected--,this.expectCharacter(125)}return new je(this.span(n),t,e)},t.prototype.parseAccessMemberOrMethodCall=function(t,e){void 0===e&&(e=!1);var n=t.span.start,a=this.expectIdentifierOrKeyword();if(this.optionalCharacter(40)){this.rparensExpected++;var r=this.parseCallArguments();this.expectCharacter(41),this.rparensExpected--;var i=this.span(n);return e?new He(i,t,a,r):new Ve(i,t,a,r)}if(e)return this.optionalOperator("=")?(this.error("The '?.' operator cannot be used in the assignment"),new Ie(this.span(n))):new De(this.span(n),t,a);if(this.optionalOperator("=")){if(!this.parseAction)return this.error("Bindings cannot contain assignments"),new Ie(this.span(n));var s=this.parseConditional();return new Ae(this.span(n),t,a,s)}return new Re(this.span(n),t,a)},t.prototype.parseCallArguments=function(){if(this.next.isCharacter(41))return[];var t=[];do{t.push(this.parsePipe())}while(this.optionalCharacter(44));return t},t.prototype.expectTemplateBindingKey=function(){var t="",e=!1;do{t+=this.expectIdentifierOrKeywordOrString(),(e=this.optionalOperator("-"))&&(t+="-")}while(e);return t.toString()},t.prototype.parseTemplateBindings=function(){for(var t=[],e=null;this.index<this.tokens.length;){var n=this.inputIndex,a=this.peekKeywordLet();a&&this.advance();var r=this.expectTemplateBindingKey(),i=r;a||(null===e?e=i:i=e+i[0].toUpperCase()+i.substring(1)),this.optionalCharacter(58);var s=null,o=null;if(a)s=this.optionalOperator("=")?this.expectTemplateBindingKey():"$implicit";else if(this.peekKeywordAs()){var u=this.inputIndex;this.advance(),s=r,i=this.expectTemplateBindingKey(),a=!0}else if(this.next!==tn&&!this.peekKeywordLet()){var c=this.inputIndex,l=this.parsePipe(),d=this.input.substring(c-this.offset,this.inputIndex-this.offset);o=new Ue(l,d,this.location,this.errors)}if(t.push(new We(this.span(n),i,a,s,o)),this.peekKeywordAs()&&!a){u=this.inputIndex,this.advance();var f=this.expectTemplateBindingKey();t.push(new We(this.span(u),f,!0,i,null))}this.optionalCharacter(Y)||this.optionalCharacter(44)}return new un(t,[],this.errors)},t.prototype.error=function(t,e){void 0===e&&(e=null),this.errors.push(new Te(t,this.input,this.locationText(e),this.location)),this.skip()},t.prototype.locationText=function(t){return void 0===t&&(t=null),null===t&&(t=this.index),t<this.tokens.length?"at column "+(this.tokens[t].index+1)+" in":"at the end of the expression"},t.prototype.skip=function(){for(var t=this.next;this.index<this.tokens.length&&!t.isCharacter(Y)&&(this.rparensExpected<=0||!t.isCharacter(41))&&(this.rbracesExpected<=0||!t.isCharacter(125))&&(this.rbracketsExpected<=0||!t.isCharacter(93));)this.next.isError()&&this.errors.push(new Te(this.next.toString(),this.input,this.locationText(),this.location)),this.advance(),t=this.next},t}(),fn=function(){function t(){this.errors=[]}return t.check=function(e){var n=new t;return e.visit(n),n.errors},t.prototype.visitImplicitReceiver=function(t,e){},t.prototype.visitInterpolation=function(t,e){},t.prototype.visitLiteralPrimitive=function(t,e){},t.prototype.visitPropertyRead=function(t,e){},t.prototype.visitPropertyWrite=function(t,e){},t.prototype.visitSafePropertyRead=function(t,e){},t.prototype.visitMethodCall=function(t,e){},t.prototype.visitSafeMethodCall=function(t,e){},t.prototype.visitFunctionCall=function(t,e){},t.prototype.visitLiteralArray=function(t,e){this.visitAll(t.expressions)},t.prototype.visitLiteralMap=function(t,e){this.visitAll(t.values)},t.prototype.visitBinary=function(t,e){},t.prototype.visitPrefixNot=function(t,e){},t.prototype.visitNonNullAssert=function(t,e){},t.prototype.visitConditional=function(t,e){},t.prototype.visitPipe=function(t,e){this.errors.push("pipes")},t.prototype.visitKeyedRead=function(t,e){},t.prototype.visitKeyedWrite=function(t,e){},t.prototype.visitAll=function(t){var e=this;return t.map(function(t){return t.visit(e)})},t.prototype.visitChain=function(t,e){},t.prototype.visitQuote=function(t,e){},t}(),pn={A:"LINK",B:"BOLD_TEXT",BR:"LINE_BREAK",EM:"EMPHASISED_TEXT",H1:"HEADING_LEVEL1",H2:"HEADING_LEVEL2",H3:"HEADING_LEVEL3",H4:"HEADING_LEVEL4",H5:"HEADING_LEVEL5",H6:"HEADING_LEVEL6",HR:"HORIZONTAL_RULE",I:"ITALIC_TEXT",LI:"LIST_ITEM",LINK:"MEDIA_LINK",OL:"ORDERED_LIST",P:"PARAGRAPH",Q:"QUOTATION",S:"STRIKETHROUGH_TEXT",SMALL:"SMALL_TEXT",SUB:"SUBSTRIPT",SUP:"SUPERSCRIPT",TBODY:"TABLE_BODY",TD:"TABLE_CELL",TFOOT:"TABLE_FOOTER",TH:"TABLE_HEADER_CELL",THEAD:"TABLE_HEADER",TR:"TABLE_ROW",TT:"MONOSPACED_TEXT",U:"UNDERLINED_TEXT",UL:"UNORDERED_LIST"},hn=function(){function t(){this._placeHolderNameCounts={},this._signatureToName={}}return t.prototype.getStartTagPlaceholderName=function(t,e,n){var a=this._hashTag(t,e,n);if(this._signatureToName[a])return this._signatureToName[a];var r=t.toUpperCase(),i=pn[r]||"TAG_"+r,s=this._generateUniqueName(n?i:"START_"+i);return this._signatureToName[a]=s,s},t.prototype.getCloseTagPlaceholderName=function(t){var e=this._hashClosingTag(t);if(this._signatureToName[e])return this._signatureToName[e];var n=t.toUpperCase(),a=this._generateUniqueName("CLOSE_"+(pn[n]||"TAG_"+n));return this._signatureToName[e]=a,a},t.prototype.getPlaceholderName=function(t,e){var n=t.toUpperCase(),a="PH: "+n+"="+e;if(this._signatureToName[a])return this._signatureToName[a];var r=this._generateUniqueName(n);return this._signatureToName[a]=r,r},t.prototype.getUniquePlaceholder=function(t){return this._generateUniqueName(t.toUpperCase())},t.prototype._hashTag=function(t,e,n){return"<"+t+Object.keys(e).sort().map(function(t){return" "+t+"="+e[t]}).join("")+(n?"/>":"></"+t+">")},t.prototype._hashClosingTag=function(t){return this._hashTag("/"+t,{},!1)},t.prototype._generateUniqueName=function(t){if(!this._placeHolderNameCounts.hasOwnProperty(t))return this._placeHolderNameCounts[t]=1,t;var e=this._placeHolderNameCounts[t];return this._placeHolderNameCounts[t]=e+1,t+"_"+e},t}(),gn=new ln(new Ze),bn=function(){function t(t,e){this._expressionParser=t,this._interpolationConfig=e}return t.prototype.toI18nMessage=function(t,e,n,a){this._isIcu=1===t.length&&t[0]instanceof o,this._icuDepth=0,this._placeholderRegistry=new hn,this._placeholderToContent={},this._placeholderToMessage={};var r=f(this,t,{});return new p(r,this._placeholderToContent,this._placeholderToMessage,e,n,a)},t.prototype.visitElement=function(t,e){var n=f(this,t.children),a={};t.attrs.forEach(function(t){a[t.name]=t.value});var r=Ft(t.name).isVoid,i=this._placeholderRegistry.getStartTagPlaceholderName(t.name,a,r);this._placeholderToContent[i]=t.sourceSpan?t.sourceSpan.toString():"";var s="";return r||(s=this._placeholderRegistry.getCloseTagPlaceholderName(t.name),this._placeholderToContent[s]="</"+t.name+">"),new m(t.name,a,i,s,n,r,t.sourceSpan)},t.prototype.visitAttribute=function(t,e){return this._visitTextWithInterpolation(t.value,t.sourceSpan)},t.prototype.visitText=function(t,e){return this._visitTextWithInterpolation(t.value,t.sourceSpan)},t.prototype.visitComment=function(t,e){return null},t.prototype.visitExpansion=function(e,n){var a=this;this._icuDepth++;var r={},i=new b(e.switchValue,e.type,r,e.sourceSpan);if(e.cases.forEach(function(t){r[t.value]=new g(t.expression.map(function(t){return t.visit(a,{})}),t.expSourceSpan)}),this._icuDepth--,this._isIcu||this._icuDepth>0){var s=this._placeholderRegistry.getUniquePlaceholder("VAR_"+e.type);return i.expressionPlaceholder=s,this._placeholderToContent[s]=e.switchValue,i}var o=this._placeholderRegistry.getPlaceholderName("ICU",e.sourceSpan.toString()),u=new t(this._expressionParser,this._interpolationConfig);return this._placeholderToMessage[o]=u.toI18nMessage([e],"","",""),new v(i,o,e.sourceSpan)},t.prototype.visitExpansionCase=function(t,e){throw new Error("Unreachable code")},t.prototype._visitTextWithInterpolation=function(t,e){var n=this._expressionParser.splitInterpolation(t,e.start.toString(),this._interpolationConfig);if(!n)return new h(t,e);for(var a=[],r=new g(a,e),i=this._interpolationConfig,s=i.start,o=i.end,u=0;u<n.strings.length-1;u++){var c=n.expressions[u],l=c.split(mn)[2]||"INTERPOLATION",d=this._placeholderRegistry.getPlaceholderName(l,c);n.strings[u].length&&a.push(new h(n.strings[u],e)),a.push(new y(c,d,e)),this._placeholderToContent[d]=s+c+o}var f=n.strings.length-1;return n.strings[f].length&&a.push(new h(n.strings[f],e)),r},t}(),mn=/\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g,yn=function(t){function e(e){void 0===e&&(e=k);var n=t.call(this,Ft)||this;return n.interpolationConfig=e,n}return Object(a.__extends)(e,t),e.prototype.parse=function(e,n,a){return void 0===a&&(a=!1),t.prototype.parse.call(this,e,n,a,this.interpolationConfig)},e.prototype.extractMessages=function(t){var e=new wn(["wrapper"]),n=new l("wrapper",[],t,void 0,void 0,void 0);return e.extract(n,this.interpolationConfig)},e.prototype.mergeTranslations=function(t,e,n,a,r){void 0===r&&(r=[]);var i=new wn(r),s=new l("wrapper",[],t,void 0,void 0,void 0);return i.merge(s,e,this.interpolationConfig,n,a)},e}(At),vn=function(){return function(t,e){this.messages=t,this.errors=e}}(),_n=function(){function t(t,e,n,a,r,i){void 0===t&&(t={}),this.i18nNodesByMsgId=t,this.digest=e,this.mapperFactory=r,this.i18nToHtml=new xn(t,e,r,a,n,i)}return t.load=function(e,n,a,r,i,s,o){return void 0===o&&(o=k),new t(i(e,n),function(t){return a(t)},o,s,function(t){return r(t)},console)},t.prototype.get=function(t,e){var n=this.i18nToHtml.convert(t,e);if(n.errors.length)throw new Error(n.errors.join("\n"));return n.nodes},t.prototype.has=function(t){return this.digest(t)in this.i18nNodesByMsgId},t}(),xn=function(){function t(t,e,n,a,r,i){void 0===t&&(t={}),this._i18nNodesByMsgId=t,this._digest=e,this._mapperFactory=n,this._missingTranslationStrategy=a,this._interpolationConfig=r,this._console=i,this._contextStack=[],this._errors=[]}return t.prototype.convert=function(t,e){this._contextStack.length=0,this._errors.length=0,this._params=e,this._paramKeys=Object.keys(e);var n=this.convertToText(t),r=t.nodes[0].sourceSpan.start.file.url,i=(new yn).parse(n,r,!0);return{nodes:i.rootNodes,errors:Object(a.__spread)(this._errors,i.errors)}},t.prototype.visitText=function(t,e){return t.value},t.prototype.visitContainer=function(t,e){var n=this;return t.children.map(function(t){return t.visit(n)}).join("")},t.prototype.visitIcu=function(t,e){var n=this,a=Object.keys(t.cases).map(function(e){return e+" {"+t.cases[e].visit(n)+"}"});return"{"+(this._srcMsg.placeholders.hasOwnProperty(t.expression)?this._srcMsg.placeholders[t.expression]:t.expression)+", "+t.type+", "+a.join(" ")+"}"},t.prototype.visitPlaceholder=function(t,e){var n=this._mapper(t.name);return this._srcMsg.placeholders.hasOwnProperty(n)?this.convertToValue(this._srcMsg.placeholders[n]):this._srcMsg.placeholderToMessage.hasOwnProperty(n)?this.convertToText(this._srcMsg.placeholderToMessage[n]):(this._addError(t,'Unknown placeholder "'+t.name+'"'),"")},t.prototype.visitTagPlaceholder=function(t,e){var n=this,a=""+t.tag,r=Object.keys(t.attrs).map(function(e){return e+'="'+t.attrs[e]+'"'}).join(" ");return t.isVoid?"<"+a+" "+r+"/>":"<"+a+" "+r+">"+t.children.map(function(t){return t.visit(n)}).join("")+"</"+a+">"},t.prototype.visitIcuPlaceholder=function(t,e){return this.convertToText(this._srcMsg.placeholderToMessage[t.name])},t.prototype.convertToText=function(t){var e,n=this,a=this._digest(t),r=this._mapperFactory?this._mapperFactory(t):null;this._contextStack.push({msg:this._srcMsg,mapper:this._mapper}),this._srcMsg=t,this._i18nNodesByMsgId.hasOwnProperty(a)?(e=this._i18nNodesByMsgId[a],this._mapper=function(t){return r?r.toInternalName(t):t}):(this._missingTranslationStrategy===i.MissingTranslationStrategy.Error?this._addError(t.nodes[0],'Missing translation for message "'+a+'"'):this._console&&this._missingTranslationStrategy===i.MissingTranslationStrategy.Warning&&this._console.warn('Missing translation for message "'+a+'"'),e=t.nodes,this._mapper=function(t){return t});var s=e.map(function(t){return t.visit(n)}).join(""),o=this._contextStack.pop();return this._srcMsg=o.msg,this._mapper=o.mapper,s},t.prototype.convertToValue=function(t){var e=t.replace(this._interpolationConfig.start,"").replace(this._interpolationConfig.end,"");return-1!==this._paramKeys.indexOf(e)?this._params[e]:t},t.prototype._addError=function(t,e){this._errors.push(new I(t.sourceSpan,e))},t}(),Tn=function(){var t={Extract:0,Merge:1};return t[t.Extract]="Extract",t[t.Merge]="Merge",t}(),wn=function(){function t(t){void 0===t&&(t=[]),this._implicitTags=t,this.blockChildren=[]}return t.prototype.extract=function(t,e){return this.init(Tn.Extract,e),t.visit(this,null),this.inI18nBlock&&this._reportError(t,"Unclosed block"),new vn(this.messages,this.errors)},t.prototype.merge=function(t,e,n,a,r){void 0===r&&(r={}),this.init(Tn.Merge,n,a),this.translations=e,this.metadata=r;var i=t.visit(this,null);return this.inI18nBlock&&this._reportError(t,"Unclosed block"),new Rt(i.children,this.errors)},t.prototype.visitExpansionCase=function(t,e){var n=f(this,t.expression,e);if(this.mode===Tn.Merge)return new u(t.value,n,t.sourceSpan,t.valueSourceSpan,t.expSourceSpan)},t.prototype.visitExpansion=function(t,e){this.mayBeAddBlockChildren(t);var n=this.inIcu;this.inIcu||(this.isInTranslatableSection&&this.addMessage([t]),this.inIcu=!0);var a=f(this,t.cases,e);return this.mode===Tn.Merge&&(t=new o(t.switchValue,t.type,a,t.sourceSpan,t.switchValueSourceSpan)),this.inIcu=n,t},t.prototype.visitComment=function(t,e){},t.prototype.visitText=function(t,e){return this.isInTranslatableSection&&this.mayBeAddBlockChildren(t),t},t.prototype.visitElement=function(t,e){var n=this;this.mayBeAddBlockChildren(t),this.depth++;var a=this.inI18nNode,r=this.inImplicitNode,i=[],s=void 0,o=t.attrs.find(function(t){return"i18n"===t.name})||null,u=this._implicitTags.some(function(e){return t.name===e})&&!this.inIcu&&!this.isInTranslatableSection,c=!r&&u;if(this.inImplicitNode=r||u,this.isInTranslatableSection||this.inIcu)(o||c)&&this._reportError(t,"Could not mark an element as translatable inside a translatable section"),this.mode===Tn.Extract&&f(this,t.children);else{if(o||c){this.inI18nNode=!0;var d=this.addMessage(t.children,this.metadata);s=this.translateMessage(t,d)}if(this.mode===Tn.Extract){var p=o||c;p&&this.openTranslatableSection(t),f(this,t.children),p&&this._closeTranslatableSection(t,t.children)}}return this.mode===Tn.Merge&&(s||t.children).forEach(function(t){var a=t.visit(n,e);a&&!n.isInTranslatableSection&&(i=i.concat(a))}),this.depth--,this.inI18nNode=a,this.inImplicitNode=r,this.mode===Tn.Merge?new l(t.name,[],i,t.sourceSpan,t.startSourceSpan,t.endSourceSpan):null},t.prototype.visitAttribute=function(t,e){throw new Error("unreachable code")},t.prototype.init=function(t,e,n){void 0===n&&(n={}),this.mode=t,this.inI18nBlock=!1,this.inI18nNode=!1,this.depth=0,this.inIcu=!1,this.msgCountAtSectionStart=void 0,this.errors=[],this.messages=[],this.inImplicitNode=!1,this.createI18nMessage=function(t){var e=new bn(gn,t);return function(t,n,a,r){return e.toI18nMessage(t,n,a,r)}}(e),this.params=n},t.prototype.addMessage=function(t,e){var n=void 0===e?{}:e,a=n.meaning,r=n.description,i=n.id;if(0===t.length||1===t.length&&t[0]instanceof c&&!t[0].value)return null;var s=this.createI18nMessage(t,void 0===a?"":a,void 0===r?"":r,void 0===i?"":i);return this.messages.push(s),s},t.prototype.translateMessage=function(t,e){if(e&&this.mode===Tn.Merge){var n=this.translations.get(e,this.params);if(n)return n;this._reportError(t,'Translation unavailable for message id="'+this.translations.digest(e)+'"')}return[]},t.prototype.mayBeAddBlockChildren=function(t){this.inI18nBlock&&!this.inIcu&&this.depth===this.blockStartDepth&&this.blockChildren.push(t)},t.prototype.openTranslatableSection=function(t){this.isInTranslatableSection?this._reportError(t,"Unexpected section start"):this.msgCountAtSectionStart=this.messages.length},Object.defineProperty(t.prototype,"isInTranslatableSection",{get:function(){return void 0!==this.msgCountAtSectionStart},enumerable:!0,configurable:!0}),t.prototype._closeTranslatableSection=function(t,e){if(this.isInTranslatableSection){var n=this.msgCountAtSectionStart;if(1===e.reduce(function(t,e){return t+(e instanceof d?0:1)},0))for(var a=this.messages.length-1;a>=n;a--){var r=this.messages[a].nodes;if(!(1===r.length&&r[0]instanceof h)){this.messages.splice(a,1);break}}this.msgCountAtSectionStart=void 0}else this._reportError(t,"Unexpected section end")},t.prototype._reportError=function(t,e){this.errors.push(new I(t.sourceSpan,e))},t}(),Sn=new i.InjectionToken("MissingTranslationStrategy"),On=function(){return function(t,e,n,a){var r,s;void 0===a&&(a=i.MissingTranslationStrategy.Warning);var o=function(t){return null};switch(t=(t||"xlf").toLowerCase()){case"xtb":r=me,s=ye,o=ve;break;case"xliff2":case"xlf2":r=fe,s=pe;break;case"xliff":case"xlf":r=ue,s=ce;break;default:throw new Error("Unknown translations format "+t)}var u=new yn,c=_n.load(e,"i18n",s,o,r,a);return function(t,e){void 0===e&&(e={});var a="string"==typeof t?t:t.value,r={};"object"==typeof t&&(r.id=t.id,r.meaning=t.meaning,r.description=t.description);var i=u.parse(a,"",!0);if(i.errors.length)throw i.errors;return function(t,e,n){return t.map(function(t){return t.visit(new Yt(e,n),null)})}(u.mergeTranslations(i.rootNodes,c,e,r,["wrapper"]).rootNodes,n,e).join("")}}}()},JvlW:function(t,e,n){!function(t){"use strict";var e={ss:"sekund\u0117_sekund\u017ei\u0173_sekundes",m:"minut\u0117_minut\u0117s_minut\u0119",mm:"minut\u0117s_minu\u010di\u0173_minutes",h:"valanda_valandos_valand\u0105",hh:"valandos_valand\u0173_valandas",d:"diena_dienos_dien\u0105",dd:"dienos_dien\u0173_dienas",M:"m\u0117nuo_m\u0117nesio_m\u0117nes\u012f",MM:"m\u0117nesiai_m\u0117nesi\u0173_m\u0117nesius",y:"metai_met\u0173_metus",yy:"metai_met\u0173_metus"};function n(t,e,n,a){return e?r(n)[0]:a?r(n)[1]:r(n)[2]}function a(t){return t%10==0||t>10&&t<20}function r(t){return e[t].split("_")}function i(t,e,i,s){var o=t+" ";return 1===t?o+n(0,e,i[0],s):e?o+(a(t)?r(i)[1]:r(i)[0]):s?o+r(i)[1]:o+(a(t)?r(i)[1]:r(i)[2])}t.defineLocale("lt",{months:{format:"sausio_vasario_kovo_baland\u017eio_gegu\u017e\u0117s_bir\u017eelio_liepos_rugpj\u016b\u010dio_rugs\u0117jo_spalio_lapkri\u010dio_gruod\u017eio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegu\u017e\u0117_bir\u017eelis_liepa_rugpj\u016btis_rugs\u0117jis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadien\u012f_pirmadien\u012f_antradien\u012f_tre\u010diadien\u012f_ketvirtadien\u012f_penktadien\u012f_\u0161e\u0161tadien\u012f".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_tre\u010diadienis_ketvirtadienis_penktadienis_\u0161e\u0161tadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_\u0160e\u0161".split("_"),weekdaysMin:"S_P_A_T_K_Pn_\u0160".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[\u0160iandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Pra\u0117jus\u012f] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prie\u0161 %s",s:function(t,e,n,a){return e?"kelios sekund\u0117s":a?"keli\u0173 sekund\u017ei\u0173":"kelias sekundes"},ss:i,m:n,mm:i,h:n,hh:i,d:n,dd:i,M:n,MM:i,y:n,yy:i},dayOfMonthOrdinalParse:/\d{1,2}-oji/,ordinal:function(t){return t+"-oji"},week:{dow:1,doy:4}})}(n("wd/R"))},JxMD:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R"),i=n("xdbM");n("dgut"),n("Fgil"),n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o});var s=a["\u0275crt"]({encapsulation:0,styles:[["canvas[_ngcontent-%COMP%]{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.chartjs-tooltip[_ngcontent-%COMP%]{opacity:0;position:absolute;background:rgba(0,0,0,.7);color:#fff;border-radius:3px;-webkit-transition:.1s;transition:all .1s ease;pointer-events:none;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif!important;-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]{-webkit-transform:translate(-10%,0);transform:translate(-10%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]::after{left:10%}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]{-webkit-transform:translate(-90%,0);transform:translate(-90%,0)}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]::after{left:90%}.chartjs-tooltip[_ngcontent-%COMP%]::after{content:' ';position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:#000 transparent transparent} .chartjs-tooltip-key{display:inline-block;width:10px;height:10px;margin-right:10px}.chart-container[_ngcontent-%COMP%]{margin:auto;cursor:pointer;overflow:visible;position:static!important}"]],data:{}});function o(t){return a["\u0275vid"](0,[a["\u0275qud"](402653184,1,{chartCanvasRef:0}),a["\u0275qud"](402653184,2,{chartTooltipRef:0}),(t()(),a["\u0275eld"](2,0,null,null,5,"div",[["class","chart-container"]],null,null,null,null,null)),a["\u0275did"](3,278528,null,0,r.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),(t()(),a["\u0275eld"](4,0,[[1,0],["sparkCanvas",1]],null,1,"canvas",[["baseChart",""]],null,null,null,null,null)),a["\u0275did"](5,737280,null,0,i.BaseChartDirective,[a.ElementRef],{datasets:[0,"datasets"],labels:[1,"labels"],options:[2,"options"],chartType:[3,"chartType"],colors:[4,"colors"]},null),(t()(),a["\u0275eld"](6,0,[[2,0],["sparkTooltip",1]],null,1,"div",[["class","chartjs-tooltip"]],null,null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,0,"table",[],null,null,null,null,null))],function(t,e){var n=e.component;t(e,3,0,n.style),t(e,5,0,n.datasets,n.labels,n.options,"line",n.colors)},null)}},"K/tc":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(t){return/^nm$/i.test(t)},meridiem:function(t,e,n){return t<12?n?"vm":"VM":n?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[M\xf4re om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",ss:"%d sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}})}()},K2E3:function(t,e,n){"use strict";var a=n("6ww4"),r=n("RDha"),i=function(t){r.extend(this,t),this.initialize.apply(this,arguments)};r.extend(i.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=r.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,r=e._start,i=e._view;return n&&1!==t?(i||(i=e._view={}),r||(r=e._start={}),function(t,e,n,r){var i,s,o,u,c,l,d,f,p,h=Object.keys(n);for(i=0,s=h.length;i<s;++i)if(l=n[o=h[i]],e.hasOwnProperty(o)||(e[o]=l),(u=e[o])!==l&&"_"!==o[0]){if(t.hasOwnProperty(o)||(t[o]=u),(d=typeof l)==typeof(c=t[o]))if("string"===d){if((f=a(c)).valid&&(p=a(l)).valid){e[o]=p.mix(f,r).rgbString();continue}}else if("number"===d&&isFinite(c)&&isFinite(l)){e[o]=c+(l-c)*r;continue}e[o]=l}}(r,i,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return r.isNumber(this._model.x)&&r.isNumber(this._model.y)}}),i.extend=r.inherits,t.exports=i},K9Ia:function(t,e,n){"use strict";n.d(e,"b",function(){return l}),n.d(e,"a",function(){return d});var a=n("mrSG"),r=n("6blF"),i=n("FFOo"),s=n("pugT"),o=n("8g8A"),u=n("uMaO"),c=n("L/V9"),l=function(t){function e(e){var n=t.call(this,e)||this;return n.destination=e,n}return a.__extends(e,t),e}(i.a),d=function(t){function e(){var e=t.call(this)||this;return e.observers=[],e.closed=!1,e.isStopped=!1,e.hasError=!1,e.thrownError=null,e}return a.__extends(e,t),e.prototype[c.a]=function(){return new l(this)},e.prototype.lift=function(t){var e=new f(this,this);return e.operator=t,e},e.prototype.next=function(t){if(this.closed)throw new o.a;if(!this.isStopped)for(var e=this.observers,n=e.length,a=e.slice(),r=0;r<n;r++)a[r].next(t)},e.prototype.error=function(t){if(this.closed)throw new o.a;this.hasError=!0,this.thrownError=t,this.isStopped=!0;for(var e=this.observers,n=e.length,a=e.slice(),r=0;r<n;r++)a[r].error(t);this.observers.length=0},e.prototype.complete=function(){if(this.closed)throw new o.a;this.isStopped=!0;for(var t=this.observers,e=t.length,n=t.slice(),a=0;a<e;a++)n[a].complete();this.observers.length=0},e.prototype.unsubscribe=function(){this.isStopped=!0,this.closed=!0,this.observers=null},e.prototype._trySubscribe=function(e){if(this.closed)throw new o.a;return t.prototype._trySubscribe.call(this,e)},e.prototype._subscribe=function(t){if(this.closed)throw new o.a;return this.hasError?(t.error(this.thrownError),s.a.EMPTY):this.isStopped?(t.complete(),s.a.EMPTY):(this.observers.push(t),new u.a(this,t))},e.prototype.asObservable=function(){var t=new r.a;return t.source=this,t},e.create=function(t,e){return new f(t,e)},e}(r.a),f=function(t){function e(e,n){var a=t.call(this)||this;return a.destination=e,a.source=n,a}return a.__extends(e,t),e.prototype.next=function(t){var e=this.destination;e&&e.next&&e.next(t)},e.prototype.error=function(t){var e=this.destination;e&&e.error&&this.destination.error(t)},e.prototype.complete=function(){var t=this.destination;t&&t.complete&&this.destination.complete()},e.prototype._subscribe=function(t){return this.source?this.source.subscribe(t):s.a.EMPTY},e}(d)},KAQS:function(t,e,n){"use strict";var a=n("RDha");t.exports=function(t){var e=["push","pop","shift","splice","unshift"];function n(t,n){var a=t._chartjs;if(a){var r=a.listeners,i=r.indexOf(n);-1!==i&&r.splice(i,1),r.length>0||(e.forEach(function(e){delete t[e]}),delete t._chartjs)}}t.DatasetController=function(t,e){this.initialize(t,e)},a.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null!==e.xAxisID&&e.xAxisID in t.chart.scales||(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null!==e.yAxisID&&e.yAxisID in t.chart.scales||(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,n=this.getMeta(),a=this.getDataset().data||[],r=n.data;for(t=0,e=a.length;t<e;++t)r[t]=r[t]||this.createMetaData(t);n.dataset=n.dataset||this.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t,r,i=this,s=i.getDataset(),o=s.data||(s.data=[]);i._data!==o&&(i._data&&n(i._data,i),r=i,(t=o)._chartjs?t._chartjs.listeners.push(r):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[r]}}),e.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),r=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),i=r.apply(this,e);return a.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),i}})})),i._data=o),i.resyncElements()},update:a.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],a=n.length,r=0;r<a;++r)n[r].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,a=0;for(t.dataset&&t.dataset.draw();a<n;++a)e[a].draw()},removeHoverStyle:function(t){a.merge(t._model,t.$previousStyle||{}),delete t.$previousStyle},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,r=t.custom||{},i=a.valueAtIndexOrDefault,s=a.getHoverColor,o=t._model;t.$previousStyle={backgroundColor:o.backgroundColor,borderColor:o.borderColor,borderWidth:o.borderWidth},o.backgroundColor=r.hoverBackgroundColor?r.hoverBackgroundColor:i(e.hoverBackgroundColor,n,s(o.backgroundColor)),o.borderColor=r.hoverBorderColor?r.hoverBorderColor:i(e.hoverBorderColor,n,s(o.borderColor)),o.borderWidth=r.hoverBorderWidth?r.hoverBorderWidth:i(e.hoverBorderWidth,n,o.borderWidth)},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,n=t.data.length,a=e.length;a<n?t.data.splice(a,n-a):a>n&&this.insertElements(n,a-n)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=a.inherits}},KQya:function(t,e,n){"use strict";var a=n("mrSG"),r=1,i={},s=function(t){function e(e,n){var a=t.call(this,e,n)||this;return a.scheduler=e,a.work=n,a}return a.__extends(e,t),e.prototype.requestAsyncId=function(e,n,a){return void 0===a&&(a=0),null!==a&&a>0?t.prototype.requestAsyncId.call(this,e,n,a):(e.actions.push(this),e.scheduled||(e.scheduled=(s=e.flush.bind(e,null),o=r++,i[o]=s,Promise.resolve().then(function(){return function(t){var e=i[t];e&&e()}(o)}),o)));var s,o},e.prototype.recycleAsyncId=function(e,n,a){if(void 0===a&&(a=0),null!==a&&a>0||null===a&&this.delay>0)return t.prototype.recycleAsyncId.call(this,e,n,a);0===e.actions.length&&(delete i[n],e.scheduled=void 0)},e}(n("h9Dq").a),o=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e.prototype.flush=function(t){this.active=!0,this.scheduled=void 0;var e,n=this.actions,a=-1,r=n.length;t=t||n.shift();do{if(e=t.execute(t.state,t.delay))break}while(++a<r&&(t=n.shift()));if(this.active=!1,e){for(;++a<r&&(t=n.shift());)t.unsubscribe();throw e}},e}(n("CS9Q").a);n.d(e,"a",function(){return u});var u=new o(s)},KSF8:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("vi",{months:"th\xe1ng 1_th\xe1ng 2_th\xe1ng 3_th\xe1ng 4_th\xe1ng 5_th\xe1ng 6_th\xe1ng 7_th\xe1ng 8_th\xe1ng 9_th\xe1ng 10_th\xe1ng 11_th\xe1ng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"ch\u1ee7 nh\u1eadt_th\u1ee9 hai_th\u1ee9 ba_th\u1ee9 t\u01b0_th\u1ee9 n\u0103m_th\u1ee9 s\xe1u_th\u1ee9 b\u1ea3y".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(t){return/^ch$/i.test(t)},meridiem:function(t,e,n){return t<12?n?"sa":"SA":n?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [n\u0103m] YYYY",LLL:"D MMMM [n\u0103m] YYYY HH:mm",LLLL:"dddd, D MMMM [n\u0103m] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[H\xf4m nay l\xfac] LT",nextDay:"[Ng\xe0y mai l\xfac] LT",nextWeek:"dddd [tu\u1ea7n t\u1edbi l\xfac] LT",lastDay:"[H\xf4m qua l\xfac] LT",lastWeek:"dddd [tu\u1ea7n r\u1ed3i l\xfac] LT",sameElse:"L"},relativeTime:{future:"%s t\u1edbi",past:"%s tr\u01b0\u1edbc",s:"v\xe0i gi\xe2y",ss:"%d gi\xe2y",m:"m\u1ed9t ph\xfat",mm:"%d ph\xfat",h:"m\u1ed9t gi\u1edd",hh:"%d gi\u1edd",d:"m\u1ed9t ng\xe0y",dd:"%d ng\xe0y",M:"m\u1ed9t th\xe1ng",MM:"%d th\xe1ng",y:"m\u1ed9t n\u0103m",yy:"%d n\u0103m"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(t){return t},week:{dow:1,doy:4}})}()},KTz0:function(t,e,n){!function(t){"use strict";var e={words:{ss:["sekund","sekunda","sekundi"],m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mjesec","mjeseca","mjeseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(t,e){return 1===t?e[0]:t>=2&&t<=4?e[1]:e[2]},translate:function(t,n,a){var r=e.words[a];return 1===a.length?n?r[0]:r[1]:t+" "+e.correctGrammaticalCase(t,r)}};t.defineLocale("me",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_\u010detvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._\u010det._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_\u010de_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sjutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[ju\u010de u] LT",lastWeek:function(){return["[pro\u0161le] [nedjelje] [u] LT","[pro\u0161log] [ponedjeljka] [u] LT","[pro\u0161log] [utorka] [u] LT","[pro\u0161le] [srijede] [u] LT","[pro\u0161log] [\u010detvrtka] [u] LT","[pro\u0161log] [petka] [u] LT","[pro\u0161le] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"nekoliko sekundi",ss:e.translate,m:e.translate,mm:e.translate,h:e.translate,hh:e.translate,d:"dan",dd:e.translate,M:"mjesec",MM:e.translate,y:"godinu",yy:e.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(n("wd/R"))},KVJa:function(t,e,n){"use strict";var a=n("CcnG");n("Z21x"),n("Ip0R"),n("sne2"),n.d(e,"a",function(){return r}),n.d(e,"b",function(){return i});var r=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function i(t){return a["\u0275vid"](0,[(t()(),a["\u0275ted"](-1,null,["\xa0\n"])),(t()(),a["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-sm btn-default tc_backButton"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.back()&&a),a},null,null)),(t()(),a["\u0275ted"](2,null,[" ","\n"]))],null,function(t,e){t(e,2,0,e.component.name)})}},KhEm:function(t,e,n){"use strict";n.d(e,"a",function(){return u}),n.d(e,"b",function(){return l});var a=n("mrSG"),r=n("K9Ia"),i=n("6blF"),s=(n("FFOo"),n("pugT")),o=n("yGWI"),u=function(t){function e(e,n){var a=t.call(this)||this;return a.source=e,a.subjectFactory=n,a._refCount=0,a._isComplete=!1,a}return a.__extends(e,t),e.prototype._subscribe=function(t){return this.getSubject().subscribe(t)},e.prototype.getSubject=function(){var t=this._subject;return t&&!t.isStopped||(this._subject=this.subjectFactory()),this._subject},e.prototype.connect=function(){var t=this._connection;return t||(this._isComplete=!1,(t=this._connection=new s.a).add(this.source.subscribe(new d(this.getSubject(),this))),t.closed&&(this._connection=null,t=s.a.EMPTY)),t},e.prototype.refCount=function(){return Object(o.a)()(this)},e}(i.a),c=u.prototype,l={operator:{value:null},_refCount:{value:0,writable:!0},_subject:{value:null,writable:!0},_connection:{value:null,writable:!0},_subscribe:{value:c._subscribe},_isComplete:{value:c._isComplete,writable:!0},getSubject:{value:c.getSubject},connect:{value:c.connect},refCount:{value:c.refCount}},d=function(t){function e(e,n){var a=t.call(this,e)||this;return a.connectable=n,a}return a.__extends(e,t),e.prototype._error=function(e){this._unsubscribe(),t.prototype._error.call(this,e)},e.prototype._complete=function(){this.connectable._isComplete=!0,this._unsubscribe(),t.prototype._complete.call(this)},e.prototype._unsubscribe=function(){var t=this.connectable;if(t){this.connectable=null;var e=t._connection;t._refCount=0,t._subject=null,t._connection=null,e&&e.unsubscribe()}},e}(r.b)},"L/V9":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a="function"==typeof Symbol?Symbol("rxSubscriber"):"@@rxSubscriber_"+Math.random()},L5sC:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DataTableColumnCellTreeToggle=function(){return a([r.Directive({selector:"[ngx-datatable-tree-toggle]"})],function(t){this.template=t})}()},LceX:function(t,e,n){"use strict";n.d(e,"a",function(){return r}),n.d(e,"b",function(){return d}),n.d(e,"c",function(){return i}),n.d(e,"d",function(){return s}),n.d(e,"e",function(){return o}),n.d(e,"f",function(){return u}),n.d(e,"g",function(){return c}),n.d(e,"h",function(){return l});var a=n("sne2"),r=(n("eTJe"),n("n/D3"),n("V3my"),n("ZEkX"),function(){return function(){}}()),i={breadcrumbs:"Users"},s={breadcrumbs:a.a.CREATE},o={breadcrumbs:a.a.EDIT},u={breadcrumbs:"Roles"},c={breadcrumbs:a.a.CREATE},l={breadcrumbs:a.a.EDIT},d=function(){return function(){}}()},Loxo:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("uz",{months:"\u044f\u043d\u0432\u0430\u0440_\u0444\u0435\u0432\u0440\u0430\u043b_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440_\u043e\u043a\u0442\u044f\u0431\u0440_\u043d\u043e\u044f\u0431\u0440_\u0434\u0435\u043a\u0430\u0431\u0440".split("_"),monthsShort:"\u044f\u043d\u0432_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433_\u0441\u0435\u043d_\u043e\u043a\u0442_\u043d\u043e\u044f_\u0434\u0435\u043a".split("_"),weekdays:"\u042f\u043a\u0448\u0430\u043d\u0431\u0430_\u0414\u0443\u0448\u0430\u043d\u0431\u0430_\u0421\u0435\u0448\u0430\u043d\u0431\u0430_\u0427\u043e\u0440\u0448\u0430\u043d\u0431\u0430_\u041f\u0430\u0439\u0448\u0430\u043d\u0431\u0430_\u0416\u0443\u043c\u0430_\u0428\u0430\u043d\u0431\u0430".split("_"),weekdaysShort:"\u042f\u043a\u0448_\u0414\u0443\u0448_\u0421\u0435\u0448_\u0427\u043e\u0440_\u041f\u0430\u0439_\u0416\u0443\u043c_\u0428\u0430\u043d".split("_"),weekdaysMin:"\u042f\u043a_\u0414\u0443_\u0421\u0435_\u0427\u043e_\u041f\u0430_\u0416\u0443_\u0428\u0430".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[\u0411\u0443\u0433\u0443\u043d \u0441\u043e\u0430\u0442] LT [\u0434\u0430]",nextDay:"[\u042d\u0440\u0442\u0430\u0433\u0430] LT [\u0434\u0430]",nextWeek:"dddd [\u043a\u0443\u043d\u0438 \u0441\u043e\u0430\u0442] LT [\u0434\u0430]",lastDay:"[\u041a\u0435\u0447\u0430 \u0441\u043e\u0430\u0442] LT [\u0434\u0430]",lastWeek:"[\u0423\u0442\u0433\u0430\u043d] dddd [\u043a\u0443\u043d\u0438 \u0441\u043e\u0430\u0442] LT [\u0434\u0430]",sameElse:"L"},relativeTime:{future:"\u042f\u043a\u0438\u043d %s \u0438\u0447\u0438\u0434\u0430",past:"\u0411\u0438\u0440 \u043d\u0435\u0447\u0430 %s \u043e\u043b\u0434\u0438\u043d",s:"\u0444\u0443\u0440\u0441\u0430\u0442",ss:"%d \u0444\u0443\u0440\u0441\u0430\u0442",m:"\u0431\u0438\u0440 \u0434\u0430\u043a\u0438\u043a\u0430",mm:"%d \u0434\u0430\u043a\u0438\u043a\u0430",h:"\u0431\u0438\u0440 \u0441\u043e\u0430\u0442",hh:"%d \u0441\u043e\u0430\u0442",d:"\u0431\u0438\u0440 \u043a\u0443\u043d",dd:"%d \u043a\u0443\u043d",M:"\u0431\u0438\u0440 \u043e\u0439",MM:"%d \u043e\u0439",y:"\u0431\u0438\u0440 \u0439\u0438\u043b",yy:"%d \u0439\u0438\u043b"},week:{dow:1,doy:7}})}()},LvDl:function(t,e,n){(function(t){var a;(function(){var r,i=200,s="Expected a function",o="__lodash_placeholder__",u=1,c=2,l=4,d=1,f=2,p=1,h=2,g=4,b=8,m=16,y=32,v=64,_=128,x=256,T=512,w=800,S=16,O=1/0,I=9007199254740991,C=1.7976931348623157e308,k=NaN,N=4294967295,R=N-1,A=N>>>1,D=[["ary",_],["bind",p],["bindKey",h],["curry",b],["curryRight",m],["flip",T],["partial",y],["partialRight",v],["rearg",x]],E="[object Arguments]",L="[object Array]",P="[object AsyncFunction]",M="[object Boolean]",q="[object Date]",j="[object DOMException]",F="[object Error]",z="[object Function]",G="[object GeneratorFunction]",Y="[object Map]",V="[object Number]",H="[object Null]",B="[object Object]",U="[object Proxy]",W="[object RegExp]",K="[object Set]",$="[object String]",Z="[object Symbol]",X="[object Undefined]",J="[object WeakMap]",Q="[object ArrayBuffer]",tt="[object DataView]",et="[object Float32Array]",nt="[object Float64Array]",at="[object Int8Array]",rt="[object Int16Array]",it="[object Int32Array]",st="[object Uint8Array]",ot="[object Uint8ClampedArray]",ut="[object Uint16Array]",ct="[object Uint32Array]",lt=/\b__p \+= '';/g,dt=/\b(__p \+=) '' \+/g,ft=/(__e\(.*?\)|\b__t\)) \+\n'';/g,pt=/&(?:amp|lt|gt|quot|#39);/g,ht=/[&<>"']/g,gt=RegExp(pt.source),bt=RegExp(ht.source),mt=/<%-([\s\S]+?)%>/g,yt=/<%([\s\S]+?)%>/g,vt=/<%=([\s\S]+?)%>/g,_t=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,xt=/^\w*$/,Tt=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,wt=/[\\^$.*+?()[\]{}|]/g,St=RegExp(wt.source),Ot=/^\s+|\s+$/g,It=/^\s+/,Ct=/\s+$/,kt=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Nt=/\{\n\/\* \[wrapped with (.+)\] \*/,Rt=/,? & /,At=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Dt=/\\(\\)?/g,Et=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Lt=/\w*$/,Pt=/^[-+]0x[0-9a-f]+$/i,Mt=/^0b[01]+$/i,qt=/^\[object .+?Constructor\]$/,jt=/^0o[0-7]+$/i,Ft=/^(?:0|[1-9]\d*)$/,zt=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Gt=/($^)/,Yt=/['\n\r\u2028\u2029\\]/g,Vt="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",Ht="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Bt="["+Ht+"]",Ut="["+Vt+"]",Wt="\\d+",Kt="[a-z\\xdf-\\xf6\\xf8-\\xff]",$t="[^\\ud800-\\udfff"+Ht+Wt+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",Zt="\\ud83c[\\udffb-\\udfff]",Xt="[^\\ud800-\\udfff]",Jt="(?:\\ud83c[\\udde6-\\uddff]){2}",Qt="[\\ud800-\\udbff][\\udc00-\\udfff]",te="[A-Z\\xc0-\\xd6\\xd8-\\xde]",ee="(?:"+Kt+"|"+$t+")",ne="(?:"+te+"|"+$t+")",ae="(?:"+Ut+"|"+Zt+")?",re="[\\ufe0e\\ufe0f]?"+ae+"(?:\\u200d(?:"+[Xt,Jt,Qt].join("|")+")[\\ufe0e\\ufe0f]?"+ae+")*",ie="(?:"+["[\\u2700-\\u27bf]",Jt,Qt].join("|")+")"+re,se="(?:"+[Xt+Ut+"?",Ut,Jt,Qt,"[\\ud800-\\udfff]"].join("|")+")",oe=RegExp("['\u2019]","g"),ue=RegExp(Ut,"g"),ce=RegExp(Zt+"(?="+Zt+")|"+se+re,"g"),le=RegExp([te+"?"+Kt+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?="+[Bt,te,"$"].join("|")+")",ne+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?="+[Bt,te+ee,"$"].join("|")+")",te+"?"+ee+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?",te+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Wt,ie].join("|"),"g"),de=RegExp("[\\u200d\\ud800-\\udfff"+Vt+"\\ufe0e\\ufe0f]"),fe=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,pe=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],he=-1,ge={};ge[et]=ge[nt]=ge[at]=ge[rt]=ge[it]=ge[st]=ge[ot]=ge[ut]=ge[ct]=!0,ge[E]=ge[L]=ge[Q]=ge[M]=ge[tt]=ge[q]=ge[F]=ge[z]=ge[Y]=ge[V]=ge[B]=ge[W]=ge[K]=ge[$]=ge[J]=!1;var be={};be[E]=be[L]=be[Q]=be[tt]=be[M]=be[q]=be[et]=be[nt]=be[at]=be[rt]=be[it]=be[Y]=be[V]=be[B]=be[W]=be[K]=be[$]=be[Z]=be[st]=be[ot]=be[ut]=be[ct]=!0,be[F]=be[z]=be[J]=!1;var me={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ye=parseFloat,ve=parseInt,_e="object"==typeof global&&global&&global.Object===Object&&global,xe="object"==typeof self&&self&&self.Object===Object&&self,Te=_e||xe||Function("return this")(),we=e&&!e.nodeType&&e,Se=we&&"object"==typeof t&&t&&!t.nodeType&&t,Oe=Se&&Se.exports===we,Ie=Oe&&_e.process,Ce=function(){try{return Se&&Se.require&&Se.require("util").types||Ie&&Ie.binding&&Ie.binding("util")}catch(t){}}(),ke=Ce&&Ce.isArrayBuffer,Ne=Ce&&Ce.isDate,Re=Ce&&Ce.isMap,Ae=Ce&&Ce.isRegExp,De=Ce&&Ce.isSet,Ee=Ce&&Ce.isTypedArray;function Le(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}function Pe(t,e,n,a){for(var r=-1,i=null==t?0:t.length;++r<i;){var s=t[r];e(a,s,n(s),t)}return a}function Me(t,e){for(var n=-1,a=null==t?0:t.length;++n<a&&!1!==e(t[n],n,t););return t}function qe(t,e){for(var n=-1,a=null==t?0:t.length;++n<a;)if(!e(t[n],n,t))return!1;return!0}function je(t,e){for(var n=-1,a=null==t?0:t.length,r=0,i=[];++n<a;){var s=t[n];e(s,n,t)&&(i[r++]=s)}return i}function Fe(t,e){return!(null==t||!t.length)&&$e(t,e,0)>-1}function ze(t,e,n){for(var a=-1,r=null==t?0:t.length;++a<r;)if(n(e,t[a]))return!0;return!1}function Ge(t,e){for(var n=-1,a=null==t?0:t.length,r=Array(a);++n<a;)r[n]=e(t[n],n,t);return r}function Ye(t,e){for(var n=-1,a=e.length,r=t.length;++n<a;)t[r+n]=e[n];return t}function Ve(t,e,n,a){var r=-1,i=null==t?0:t.length;for(a&&i&&(n=t[++r]);++r<i;)n=e(n,t[r],r,t);return n}function He(t,e,n,a){var r=null==t?0:t.length;for(a&&r&&(n=t[--r]);r--;)n=e(n,t[r],r,t);return n}function Be(t,e){for(var n=-1,a=null==t?0:t.length;++n<a;)if(e(t[n],n,t))return!0;return!1}var Ue=Qe("length");function We(t,e,n){var a;return n(t,function(t,n,r){if(e(t,n,r))return a=n,!1}),a}function Ke(t,e,n,a){for(var r=t.length,i=n+(a?1:-1);a?i--:++i<r;)if(e(t[i],i,t))return i;return-1}function $e(t,e,n){return e==e?function(t,e,n){for(var a=n-1,r=t.length;++a<r;)if(t[a]===e)return a;return-1}(t,e,n):Ke(t,Xe,n)}function Ze(t,e,n,a){for(var r=n-1,i=t.length;++r<i;)if(a(t[r],e))return r;return-1}function Xe(t){return t!=t}function Je(t,e){var n=null==t?0:t.length;return n?nn(t,e)/n:k}function Qe(t){return function(e){return null==e?r:e[t]}}function tn(t){return function(e){return null==t?r:t[e]}}function en(t,e,n,a,r){return r(t,function(t,r,i){n=a?(a=!1,t):e(n,t,r,i)}),n}function nn(t,e){for(var n,a=-1,i=t.length;++a<i;){var s=e(t[a]);s!==r&&(n=n===r?s:n+s)}return n}function an(t,e){for(var n=-1,a=Array(t);++n<t;)a[n]=e(n);return a}function rn(t){return function(e){return t(e)}}function sn(t,e){return Ge(e,function(e){return t[e]})}function on(t,e){return t.has(e)}function un(t,e){for(var n=-1,a=t.length;++n<a&&$e(e,t[n],0)>-1;);return n}function cn(t,e){for(var n=t.length;n--&&$e(e,t[n],0)>-1;);return n}var ln=tn({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),dn=tn({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"});function fn(t){return"\\"+me[t]}function pn(t){return de.test(t)}function hn(t){var e=-1,n=Array(t.size);return t.forEach(function(t,a){n[++e]=[a,t]}),n}function gn(t,e){return function(n){return t(e(n))}}function bn(t,e){for(var n=-1,a=t.length,r=0,i=[];++n<a;){var s=t[n];s!==e&&s!==o||(t[n]=o,i[r++]=n)}return i}function mn(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function yn(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=[t,t]}),n}function vn(t){return pn(t)?function(t){for(var e=ce.lastIndex=0;ce.test(t);)++e;return e}(t):Ue(t)}function _n(t){return pn(t)?function(t){return t.match(ce)||[]}(t):function(t){return t.split("")}(t)}var xn=tn({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),Tn=function t(e){var n,a=(e=null==e?Te:Tn.defaults(Te.Object(),e,Tn.pick(Te,pe))).Array,Vt=e.Date,Ht=e.Error,Bt=e.Function,Ut=e.Math,Wt=e.Object,Kt=e.RegExp,$t=e.String,Zt=e.TypeError,Xt=a.prototype,Jt=Wt.prototype,Qt=e["__core-js_shared__"],te=Bt.prototype.toString,ee=Jt.hasOwnProperty,ne=0,ae=(n=/[^.]+$/.exec(Qt&&Qt.keys&&Qt.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",re=Jt.toString,ie=te.call(Wt),se=Te._,ce=Kt("^"+te.call(ee).replace(wt,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),de=Oe?e.Buffer:r,me=e.Symbol,_e=e.Uint8Array,xe=de?de.allocUnsafe:r,we=gn(Wt.getPrototypeOf,Wt),Se=Wt.create,Ie=Jt.propertyIsEnumerable,Ce=Xt.splice,Ue=me?me.isConcatSpreadable:r,tn=me?me.iterator:r,wn=me?me.toStringTag:r,Sn=function(){try{var t=Ti(Wt,"defineProperty");return t({},"",{}),t}catch(e){}}(),On=e.clearTimeout!==Te.clearTimeout&&e.clearTimeout,In=Vt&&Vt.now!==Te.Date.now&&Vt.now,Cn=e.setTimeout!==Te.setTimeout&&e.setTimeout,kn=Ut.ceil,Nn=Ut.floor,Rn=Wt.getOwnPropertySymbols,An=de?de.isBuffer:r,Dn=e.isFinite,En=Xt.join,Ln=gn(Wt.keys,Wt),Pn=Ut.max,Mn=Ut.min,qn=Vt.now,jn=e.parseInt,Fn=Ut.random,zn=Xt.reverse,Gn=Ti(e,"DataView"),Yn=Ti(e,"Map"),Vn=Ti(e,"Promise"),Hn=Ti(e,"Set"),Bn=Ti(e,"WeakMap"),Un=Ti(Wt,"create"),Wn=Bn&&new Bn,Kn={},$n=Ki(Gn),Zn=Ki(Yn),Xn=Ki(Vn),Jn=Ki(Hn),Qn=Ki(Bn),ta=me?me.prototype:r,ea=ta?ta.valueOf:r,na=ta?ta.toString:r;function aa(t){if(fo(t)&&!to(t)&&!(t instanceof oa)){if(t instanceof sa)return t;if(ee.call(t,"__wrapped__"))return $i(t)}return new sa(t)}var ra=function(){function t(){}return function(e){if(!lo(e))return{};if(Se)return Se(e);t.prototype=e;var n=new t;return t.prototype=r,n}}();function ia(){}function sa(t,e){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!e,this.__index__=0,this.__values__=r}function oa(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=N,this.__views__=[]}function ua(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var a=t[e];this.set(a[0],a[1])}}function ca(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var a=t[e];this.set(a[0],a[1])}}function la(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var a=t[e];this.set(a[0],a[1])}}function da(t){var e=-1,n=null==t?0:t.length;for(this.__data__=new la;++e<n;)this.add(t[e])}function fa(t){var e=this.__data__=new ca(t);this.size=e.size}function pa(t,e){var n=to(t),a=!n&&Qs(t),r=!n&&!a&&ro(t),i=!n&&!a&&!r&&_o(t),s=n||a||r||i,o=s?an(t.length,$t):[],u=o.length;for(var c in t)!e&&!ee.call(t,c)||s&&("length"==c||r&&("offset"==c||"parent"==c)||i&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||Ni(c,u))||o.push(c);return o}function ha(t){var e=t.length;return e?t[ur(0,e-1)]:r}function ga(t,e,n){(n===r||Zs(t[e],n))&&(n!==r||e in t)||_a(t,e,n)}function ba(t,e,n){var a=t[e];ee.call(t,e)&&Zs(a,n)&&(n!==r||e in t)||_a(t,e,n)}function ma(t,e){for(var n=t.length;n--;)if(Zs(t[n][0],e))return n;return-1}function ya(t,e,n,a){return Ca(t,function(t,r,i){e(a,t,n(t),i)}),a}function va(t,e){return t&&Gr(e,Yo(e),t)}function _a(t,e,n){"__proto__"==e&&Sn?Sn(t,e,{configurable:!0,enumerable:!0,value:n,writable:!0}):t[e]=n}function xa(t,e){for(var n=-1,i=e.length,s=a(i),o=null==t;++n<i;)s[n]=o?r:qo(t,e[n]);return s}function Ta(t,e,n){return t==t&&(n!==r&&(t=t<=n?t:n),e!==r&&(t=t>=e?t:e)),t}function wa(t,e,n,a,i,s){var o,d=e&u,f=e&c,p=e&l;if(n&&(o=i?n(t,a,i,s):n(t)),o!==r)return o;if(!lo(t))return t;var h=to(t);if(h){if(o=function(t){var e=t.length,n=new t.constructor(e);return e&&"string"==typeof t[0]&&ee.call(t,"index")&&(n.index=t.index,n.input=t.input),n}(t),!d)return zr(t,o)}else{var g=Oi(t),b=g==z||g==G;if(ro(t))return Lr(t,d);if(g==B||g==E||b&&!i){if(o=f||b?{}:Ci(t),!d)return f?function(t,e){return Gr(t,Si(t),e)}(t,function(e,n){return e&&Gr(t,Vo(t),e)}(o)):function(t,e){return Gr(t,wi(t),e)}(t,va(o,t))}else{if(!be[g])return i?t:{};o=function(t,e,n){var a,r,i=t.constructor;switch(e){case Q:return Pr(t);case M:case q:return new i(+t);case tt:return function(t,e){var n=e?Pr(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}(t,n);case et:case nt:case at:case rt:case it:case st:case ot:case ut:case ct:return Mr(t,n);case Y:return new i;case V:case $:return new i(t);case W:return(r=new(a=t).constructor(a.source,Lt.exec(a))).lastIndex=a.lastIndex,r;case K:return new i;case Z:return ea?Wt(ea.call(t)):{}}}(t,g,d)}}s||(s=new fa);var m=s.get(t);if(m)return m;s.set(t,o),mo(t)?t.forEach(function(a){o.add(wa(a,e,n,a,t,s))}):po(t)&&t.forEach(function(a,r){o.set(r,wa(a,e,n,r,t,s))});var y=h?r:(p?f?gi:hi:f?Vo:Yo)(t);return Me(y||t,function(a,r){y&&(a=t[r=a]),ba(o,r,wa(a,e,n,r,t,s))}),o}function Sa(t,e,n){var a=n.length;if(null==t)return!a;for(t=Wt(t);a--;){var i=n[a],s=t[i];if(s===r&&!(i in t)||!(0,e[i])(s))return!1}return!0}function Oa(t,e,n){if("function"!=typeof t)throw new Zt(s);return Gi(function(){t.apply(r,n)},e)}function Ia(t,e,n,a){var r=-1,s=Fe,o=!0,u=t.length,c=[],l=e.length;if(!u)return c;n&&(e=Ge(e,rn(n))),a?(s=ze,o=!1):e.length>=i&&(s=on,o=!1,e=new da(e));t:for(;++r<u;){var d=t[r],f=null==n?d:n(d);if(d=a||0!==d?d:0,o&&f==f){for(var p=l;p--;)if(e[p]===f)continue t;c.push(d)}else s(e,f,a)||c.push(d)}return c}aa.templateSettings={escape:mt,evaluate:yt,interpolate:vt,variable:"",imports:{_:aa}},(aa.prototype=ia.prototype).constructor=aa,(sa.prototype=ra(ia.prototype)).constructor=sa,(oa.prototype=ra(ia.prototype)).constructor=oa,ua.prototype.clear=function(){this.__data__=Un?Un(null):{},this.size=0},ua.prototype.delete=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e},ua.prototype.get=function(t){var e=this.__data__;if(Un){var n=e[t];return"__lodash_hash_undefined__"===n?r:n}return ee.call(e,t)?e[t]:r},ua.prototype.has=function(t){var e=this.__data__;return Un?e[t]!==r:ee.call(e,t)},ua.prototype.set=function(t,e){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=Un&&e===r?"__lodash_hash_undefined__":e,this},ca.prototype.clear=function(){this.__data__=[],this.size=0},ca.prototype.delete=function(t){var e=this.__data__,n=ma(e,t);return!(n<0||(n==e.length-1?e.pop():Ce.call(e,n,1),--this.size,0))},ca.prototype.get=function(t){var e=this.__data__,n=ma(e,t);return n<0?r:e[n][1]},ca.prototype.has=function(t){return ma(this.__data__,t)>-1},ca.prototype.set=function(t,e){var n=this.__data__,a=ma(n,t);return a<0?(++this.size,n.push([t,e])):n[a][1]=e,this},la.prototype.clear=function(){this.size=0,this.__data__={hash:new ua,map:new(Yn||ca),string:new ua}},la.prototype.delete=function(t){var e=_i(this,t).delete(t);return this.size-=e?1:0,e},la.prototype.get=function(t){return _i(this,t).get(t)},la.prototype.has=function(t){return _i(this,t).has(t)},la.prototype.set=function(t,e){var n=_i(this,t),a=n.size;return n.set(t,e),this.size+=n.size==a?0:1,this},da.prototype.add=da.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},da.prototype.has=function(t){return this.__data__.has(t)},fa.prototype.clear=function(){this.__data__=new ca,this.size=0},fa.prototype.delete=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n},fa.prototype.get=function(t){return this.__data__.get(t)},fa.prototype.has=function(t){return this.__data__.has(t)},fa.prototype.set=function(t,e){var n=this.__data__;if(n instanceof ca){var a=n.__data__;if(!Yn||a.length<i-1)return a.push([t,e]),this.size=++n.size,this;n=this.__data__=new la(a)}return n.set(t,e),this.size=n.size,this};var Ca=Hr(Pa),ka=Hr(Ma,!0);function Na(t,e){var n=!0;return Ca(t,function(t,a,r){return n=!!e(t,a,r)}),n}function Ra(t,e,n){for(var a=-1,i=t.length;++a<i;){var s=t[a],o=e(s);if(null!=o&&(u===r?o==o&&!vo(o):n(o,u)))var u=o,c=s}return c}function Aa(t,e){var n=[];return Ca(t,function(t,a,r){e(t,a,r)&&n.push(t)}),n}function Da(t,e,n,a,r){var i=-1,s=t.length;for(n||(n=ki),r||(r=[]);++i<s;){var o=t[i];e>0&&n(o)?e>1?Da(o,e-1,n,a,r):Ye(r,o):a||(r[r.length]=o)}return r}var Ea=Br(),La=Br(!0);function Pa(t,e){return t&&Ea(t,e,Yo)}function Ma(t,e){return t&&La(t,e,Yo)}function qa(t,e){return je(e,function(e){return oo(t[e])})}function ja(t,e){for(var n=0,a=(e=Rr(e,t)).length;null!=t&&n<a;)t=t[Wi(e[n++])];return n&&n==a?t:r}function Fa(t,e,n){var a=e(t);return to(t)?a:Ye(a,n(t))}function za(t){return null==t?t===r?X:H:wn&&wn in Wt(t)?function(t){var e=ee.call(t,wn),n=t[wn];try{t[wn]=r;var a=!0}catch(s){}var i=re.call(t);return a&&(e?t[wn]=n:delete t[wn]),i}(t):function(t){return re.call(t)}(t)}function Ga(t,e){return t>e}function Ya(t,e){return null!=t&&ee.call(t,e)}function Va(t,e){return null!=t&&e in Wt(t)}function Ha(t,e,n){for(var i=n?ze:Fe,s=t[0].length,o=t.length,u=o,c=a(o),l=1/0,d=[];u--;){var f=t[u];u&&e&&(f=Ge(f,rn(e))),l=Mn(f.length,l),c[u]=!n&&(e||s>=120&&f.length>=120)?new da(u&&f):r}f=t[0];var p=-1,h=c[0];t:for(;++p<s&&d.length<l;){var g=f[p],b=e?e(g):g;if(g=n||0!==g?g:0,!(h?on(h,b):i(d,b,n))){for(u=o;--u;){var m=c[u];if(!(m?on(m,b):i(t[u],b,n)))continue t}h&&h.push(b),d.push(g)}}return d}function Ba(t,e,n){var a=null==(t=ji(t,e=Rr(e,t)))?t:t[Wi(ss(e))];return null==a?r:Le(a,t,n)}function Ua(t){return fo(t)&&za(t)==E}function Wa(t,e,n,a,i){return t===e||(null==t||null==e||!fo(t)&&!fo(e)?t!=t&&e!=e:function(t,e,n,a,i,s){var o=to(t),u=to(e),c=o?L:Oi(t),l=u?L:Oi(e),p=(c=c==E?B:c)==B,h=(l=l==E?B:l)==B,g=c==l;if(g&&ro(t)){if(!ro(e))return!1;o=!0,p=!1}if(g&&!p)return s||(s=new fa),o||_o(t)?fi(t,e,n,a,i,s):function(t,e,n,a,r,i,s){switch(c){case tt:if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case Q:return!(t.byteLength!=e.byteLength||!i(new _e(t),new _e(e)));case M:case q:case V:return Zs(+t,+e);case F:return t.name==e.name&&t.message==e.message;case W:case $:return t==e+"";case Y:var o=hn;case K:if(o||(o=mn),t.size!=e.size&&!(a&d))return!1;var u=s.get(t);if(u)return u==e;a|=f,s.set(t,e);var l=fi(o(t),o(e),a,r,i,s);return s.delete(t),l;case Z:if(ea)return ea.call(t)==ea.call(e)}return!1}(t,e,0,n,a,i,s);if(!(n&d)){var b=p&&ee.call(t,"__wrapped__"),m=h&&ee.call(e,"__wrapped__");if(b||m){var y=b?t.value():t,v=m?e.value():e;return s||(s=new fa),i(y,v,n,a,s)}}return!!g&&(s||(s=new fa),function(t,e,n,a,i,s){var o=n&d,u=hi(t),c=u.length;if(c!=hi(e).length&&!o)return!1;for(var l=c;l--;){var f=u[l];if(!(o?f in e:ee.call(e,f)))return!1}var p=s.get(t);if(p&&s.get(e))return p==e;var h=!0;s.set(t,e),s.set(e,t);for(var g=o;++l<c;){var b=t[f=u[l]],m=e[f];if(a)var y=o?a(m,b,f,e,t,s):a(b,m,f,t,e,s);if(!(y===r?b===m||i(b,m,n,a,s):y)){h=!1;break}g||(g="constructor"==f)}if(h&&!g){var v=t.constructor,_=e.constructor;v!=_&&"constructor"in t&&"constructor"in e&&!("function"==typeof v&&v instanceof v&&"function"==typeof _&&_ instanceof _)&&(h=!1)}return s.delete(t),s.delete(e),h}(t,e,n,a,i,s))}(t,e,n,a,Wa,i))}function Ka(t,e,n,a){var i=n.length,s=i,o=!a;if(null==t)return!s;for(t=Wt(t);i--;){var u=n[i];if(o&&u[2]?u[1]!==t[u[0]]:!(u[0]in t))return!1}for(;++i<s;){var c=(u=n[i])[0],l=t[c],p=u[1];if(o&&u[2]){if(l===r&&!(c in t))return!1}else{var h=new fa;if(a)var g=a(l,p,c,t,e,h);if(!(g===r?Wa(p,l,d|f,a,h):g))return!1}}return!0}function $a(t){return!(!lo(t)||(e=t,ae&&ae in e))&&(oo(t)?ce:qt).test(Ki(t));var e}function Za(t){return"function"==typeof t?t:null==t?hu:"object"==typeof t?to(t)?er(t[0],t[1]):tr(t):wu(t)}function Xa(t){if(!Li(t))return Ln(t);var e=[];for(var n in Wt(t))ee.call(t,n)&&"constructor"!=n&&e.push(n);return e}function Ja(t,e){return t<e}function Qa(t,e){var n=-1,r=no(t)?a(t.length):[];return Ca(t,function(t,a,i){r[++n]=e(t,a,i)}),r}function tr(t){var e=xi(t);return 1==e.length&&e[0][2]?Mi(e[0][0],e[0][1]):function(n){return n===t||Ka(n,t,e)}}function er(t,e){return Ai(t)&&Pi(e)?Mi(Wi(t),e):function(n){var a=qo(n,t);return a===r&&a===e?jo(n,t):Wa(e,a,d|f)}}function nr(t,e,n,a,i){t!==e&&Ea(e,function(s,o){if(i||(i=new fa),lo(s))!function(t,e,n,a,i,s,o){var u=Fi(t,n),c=Fi(e,n),l=o.get(c);if(l)ga(t,n,l);else{var d=s?s(u,c,n+"",t,e,o):r,f=d===r;if(f){var p=to(c),h=!p&&ro(c),g=!p&&!h&&_o(c);d=c,p||h||g?to(u)?d=u:ao(u)?d=zr(u):h?(f=!1,d=Lr(c,!0)):g?(f=!1,d=Mr(c,!0)):d=[]:go(c)||Qs(c)?(d=u,Qs(u)?d=ko(u):lo(u)&&!oo(u)||(d=Ci(c))):f=!1}f&&(o.set(c,d),i(d,c,a,s,o),o.delete(c)),ga(t,n,d)}}(t,e,o,n,nr,a,i);else{var u=a?a(Fi(t,o),s,o+"",t,e,i):r;u===r&&(u=s),ga(t,o,u)}},Vo)}function ar(t,e){var n=t.length;if(n)return Ni(e+=e<0?n:0,n)?t[e]:r}function rr(t,e,n){var a=-1;return e=Ge(e.length?e:[hu],rn(vi())),function(t,e){var a=t.length;for(t.sort(function(t,e){return function(t,e,n){for(var a=-1,r=t.criteria,i=e.criteria,s=r.length,o=n.length;++a<s;){var u=qr(r[a],i[a]);if(u)return a>=o?u:u*("desc"==n[a]?-1:1)}return t.index-e.index}(t,e,n)});a--;)t[a]=t[a].value;return t}(Qa(t,function(t,n,r){return{criteria:Ge(e,function(e){return e(t)}),index:++a,value:t}}))}function ir(t,e,n){for(var a=-1,r=e.length,i={};++a<r;){var s=e[a],o=ja(t,s);n(o,s)&&dr(i,Rr(s,t),o)}return i}function sr(t,e,n,a){var r=a?Ze:$e,i=-1,s=e.length,o=t;for(t===e&&(e=zr(e)),n&&(o=Ge(t,rn(n)));++i<s;)for(var u=0,c=e[i],l=n?n(c):c;(u=r(o,l,u,a))>-1;)o!==t&&Ce.call(o,u,1),Ce.call(t,u,1);return t}function or(t,e){for(var n=t?e.length:0,a=n-1;n--;){var r=e[n];if(n==a||r!==i){var i=r;Ni(r)?Ce.call(t,r,1):Tr(t,r)}}return t}function ur(t,e){return t+Nn(Fn()*(e-t+1))}function cr(t,e){var n="";if(!t||e<1||e>I)return n;do{e%2&&(n+=t),(e=Nn(e/2))&&(t+=t)}while(e);return n}function lr(t,e){return Yi(qi(t,e,hu),t+"")}function dr(t,e,n,a){if(!lo(t))return t;for(var i=-1,s=(e=Rr(e,t)).length,o=s-1,u=t;null!=u&&++i<s;){var c=Wi(e[i]),l=n;if(i!=o){var d=u[c];(l=a?a(d,c,u):r)===r&&(l=lo(d)?d:Ni(e[i+1])?[]:{})}ba(u,c,l),u=u[c]}return t}var fr=Wn?function(t,e){return Wn.set(t,e),t}:hu,pr=Sn?function(t,e){return Sn(t,"toString",{configurable:!0,enumerable:!1,value:du(e),writable:!0})}:hu;function hr(t,e,n){var r=-1,i=t.length;e<0&&(e=-e>i?0:i+e),(n=n>i?i:n)<0&&(n+=i),i=e>n?0:n-e>>>0,e>>>=0;for(var s=a(i);++r<i;)s[r]=t[r+e];return s}function gr(t,e){var n;return Ca(t,function(t,a,r){return!(n=e(t,a,r))}),!!n}function br(t,e,n){var a=0,r=null==t?a:t.length;if("number"==typeof e&&e==e&&r<=A){for(;a<r;){var i=a+r>>>1,s=t[i];null!==s&&!vo(s)&&(n?s<=e:s<e)?a=i+1:r=i}return r}return mr(t,e,hu,n)}function mr(t,e,n,a){e=n(e);for(var i=0,s=null==t?0:t.length,o=e!=e,u=null===e,c=vo(e),l=e===r;i<s;){var d=Nn((i+s)/2),f=n(t[d]),p=f!==r,h=null===f,g=f==f,b=vo(f);if(o)var m=a||g;else m=l?g&&(a||p):u?g&&p&&(a||!h):c?g&&p&&!h&&(a||!b):!h&&!b&&(a?f<=e:f<e);m?i=d+1:s=d}return Mn(s,R)}function yr(t,e){for(var n=-1,a=t.length,r=0,i=[];++n<a;){var s=t[n],o=e?e(s):s;if(!n||!Zs(o,u)){var u=o;i[r++]=0===s?0:s}}return i}function vr(t){return"number"==typeof t?t:vo(t)?k:+t}function _r(t){if("string"==typeof t)return t;if(to(t))return Ge(t,_r)+"";if(vo(t))return na?na.call(t):"";var e=t+"";return"0"==e&&1/t==-O?"-0":e}function xr(t,e,n){var a=-1,r=Fe,s=t.length,o=!0,u=[],c=u;if(n)o=!1,r=ze;else if(s>=i){var l=e?null:si(t);if(l)return mn(l);o=!1,r=on,c=new da}else c=e?[]:u;t:for(;++a<s;){var d=t[a],f=e?e(d):d;if(d=n||0!==d?d:0,o&&f==f){for(var p=c.length;p--;)if(c[p]===f)continue t;e&&c.push(f),u.push(d)}else r(c,f,n)||(c!==u&&c.push(f),u.push(d))}return u}function Tr(t,e){return null==(t=ji(t,e=Rr(e,t)))||delete t[Wi(ss(e))]}function wr(t,e,n,a){return dr(t,e,n(ja(t,e)),a)}function Sr(t,e,n,a){for(var r=t.length,i=a?r:-1;(a?i--:++i<r)&&e(t[i],i,t););return n?hr(t,a?0:i,a?i+1:r):hr(t,a?i+1:0,a?r:i)}function Or(t,e){var n=t;return n instanceof oa&&(n=n.value()),Ve(e,function(t,e){return e.func.apply(e.thisArg,Ye([t],e.args))},n)}function Ir(t,e,n){var r=t.length;if(r<2)return r?xr(t[0]):[];for(var i=-1,s=a(r);++i<r;)for(var o=t[i],u=-1;++u<r;)u!=i&&(s[i]=Ia(s[i]||o,t[u],e,n));return xr(Da(s,1),e,n)}function Cr(t,e,n){for(var a=-1,i=t.length,s=e.length,o={};++a<i;)n(o,t[a],a<s?e[a]:r);return o}function kr(t){return ao(t)?t:[]}function Nr(t){return"function"==typeof t?t:hu}function Rr(t,e){return to(t)?t:Ai(t,e)?[t]:Ui(No(t))}var Ar=lr;function Dr(t,e,n){var a=t.length;return n=n===r?a:n,!e&&n>=a?t:hr(t,e,n)}var Er=On||function(t){return Te.clearTimeout(t)};function Lr(t,e){if(e)return t.slice();var n=t.length,a=xe?xe(n):new t.constructor(n);return t.copy(a),a}function Pr(t){var e=new t.constructor(t.byteLength);return new _e(e).set(new _e(t)),e}function Mr(t,e){var n=e?Pr(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.length)}function qr(t,e){if(t!==e){var n=t!==r,a=null===t,i=t==t,s=vo(t),o=e!==r,u=null===e,c=e==e,l=vo(e);if(!u&&!l&&!s&&t>e||s&&o&&c&&!u&&!l||a&&o&&c||!n&&c||!i)return 1;if(!a&&!s&&!l&&t<e||l&&n&&i&&!a&&!s||u&&n&&i||!o&&i||!c)return-1}return 0}function jr(t,e,n,r){for(var i=-1,s=t.length,o=n.length,u=-1,c=e.length,l=Pn(s-o,0),d=a(c+l),f=!r;++u<c;)d[u]=e[u];for(;++i<o;)(f||i<s)&&(d[n[i]]=t[i]);for(;l--;)d[u++]=t[i++];return d}function Fr(t,e,n,r){for(var i=-1,s=t.length,o=-1,u=n.length,c=-1,l=e.length,d=Pn(s-u,0),f=a(d+l),p=!r;++i<d;)f[i]=t[i];for(var h=i;++c<l;)f[h+c]=e[c];for(;++o<u;)(p||i<s)&&(f[h+n[o]]=t[i++]);return f}function zr(t,e){var n=-1,r=t.length;for(e||(e=a(r));++n<r;)e[n]=t[n];return e}function Gr(t,e,n,a){var i=!n;n||(n={});for(var s=-1,o=e.length;++s<o;){var u=e[s],c=a?a(n[u],t[u],u,n,t):r;c===r&&(c=t[u]),i?_a(n,u,c):ba(n,u,c)}return n}function Yr(t,e){return function(n,a){var r=to(n)?Pe:ya,i=e?e():{};return r(n,t,vi(a,2),i)}}function Vr(t){return lr(function(e,n){var a=-1,i=n.length,s=i>1?n[i-1]:r,o=i>2?n[2]:r;for(s=t.length>3&&"function"==typeof s?(i--,s):r,o&&Ri(n[0],n[1],o)&&(s=i<3?r:s,i=1),e=Wt(e);++a<i;){var u=n[a];u&&t(e,u,a,s)}return e})}function Hr(t,e){return function(n,a){if(null==n)return n;if(!no(n))return t(n,a);for(var r=n.length,i=e?r:-1,s=Wt(n);(e?i--:++i<r)&&!1!==a(s[i],i,s););return n}}function Br(t){return function(e,n,a){for(var r=-1,i=Wt(e),s=a(e),o=s.length;o--;){var u=s[t?o:++r];if(!1===n(i[u],u,i))break}return e}}function Ur(t){return function(e){var n=pn(e=No(e))?_n(e):r,a=n?n[0]:e.charAt(0),i=n?Dr(n,1).join(""):e.slice(1);return a[t]()+i}}function Wr(t){return function(e){return Ve(uu(tu(e).replace(oe,"")),t,"")}}function Kr(t){return function(){var e=arguments;switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3]);case 5:return new t(e[0],e[1],e[2],e[3],e[4]);case 6:return new t(e[0],e[1],e[2],e[3],e[4],e[5]);case 7:return new t(e[0],e[1],e[2],e[3],e[4],e[5],e[6])}var n=ra(t.prototype),a=t.apply(n,e);return lo(a)?a:n}}function $r(t){return function(e,n,a){var i=Wt(e);if(!no(e)){var s=vi(n,3);e=Yo(e),n=function(t){return s(i[t],t,i)}}var o=t(e,n,a);return o>-1?i[s?e[o]:o]:r}}function Zr(t){return pi(function(e){var n=e.length,a=n,i=sa.prototype.thru;for(t&&e.reverse();a--;){var o=e[a];if("function"!=typeof o)throw new Zt(s);if(i&&!u&&"wrapper"==mi(o))var u=new sa([],!0)}for(a=u?a:n;++a<n;){var c=mi(o=e[a]),l="wrapper"==c?bi(o):r;u=l&&Di(l[0])&&l[1]==(_|b|y|x)&&!l[4].length&&1==l[9]?u[mi(l[0])].apply(u,l[3]):1==o.length&&Di(o)?u[c]():u.thru(o)}return function(){var t=arguments,a=t[0];if(u&&1==t.length&&to(a))return u.plant(a).value();for(var r=0,i=n?e[r].apply(this,t):a;++r<n;)i=e[r].call(this,i);return i}})}function Xr(t,e,n,i,s,o,u,c,l,d){var f=e&_,g=e&p,y=e&h,v=e&(b|m),x=e&T,w=y?r:Kr(t);return function p(){for(var h=arguments.length,b=a(h),m=h;m--;)b[m]=arguments[m];if(v)var _=yi(p),T=function(t,e){for(var n=t.length,a=0;n--;)t[n]===e&&++a;return a}(b,_);if(i&&(b=jr(b,i,s,v)),o&&(b=Fr(b,o,u,v)),h-=T,v&&h<d){var S=bn(b,_);return ri(t,e,Xr,p.placeholder,n,b,S,c,l,d-h)}var O=g?n:this,I=y?O[t]:t;return h=b.length,c?b=function(t,e){for(var n=t.length,a=Mn(e.length,n),i=zr(t);a--;){var s=e[a];t[a]=Ni(s,n)?i[s]:r}return t}(b,c):x&&h>1&&b.reverse(),f&&l<h&&(b.length=l),this&&this!==Te&&this instanceof p&&(I=w||Kr(I)),I.apply(O,b)}}function Jr(t,e){return function(n,a){return function(t,e,n,a){return Pa(t,function(t,r,i){e(a,n(t),r,i)}),a}(n,t,e(a),{})}}function Qr(t,e){return function(n,a){var i;if(n===r&&a===r)return e;if(n!==r&&(i=n),a!==r){if(i===r)return a;"string"==typeof n||"string"==typeof a?(n=_r(n),a=_r(a)):(n=vr(n),a=vr(a)),i=t(n,a)}return i}}function ti(t){return pi(function(e){return e=Ge(e,rn(vi())),lr(function(n){var a=this;return t(e,function(t){return Le(t,a,n)})})})}function ei(t,e){var n=(e=e===r?" ":_r(e)).length;if(n<2)return n?cr(e,t):e;var a=cr(e,kn(t/vn(e)));return pn(e)?Dr(_n(a),0,t).join(""):a.slice(0,t)}function ni(t){return function(e,n,i){return i&&"number"!=typeof i&&Ri(e,n,i)&&(n=i=r),e=So(e),n===r?(n=e,e=0):n=So(n),function(t,e,n,r){for(var i=-1,s=Pn(kn((e-t)/(n||1)),0),o=a(s);s--;)o[r?s:++i]=t,t+=n;return o}(e,n,i=i===r?e<n?1:-1:So(i),t)}}function ai(t){return function(e,n){return"string"==typeof e&&"string"==typeof n||(e=Co(e),n=Co(n)),t(e,n)}}function ri(t,e,n,a,i,s,o,u,c,l){var d=e&b;e|=d?y:v,(e&=~(d?v:y))&g||(e&=~(p|h));var f=[t,e,i,d?s:r,d?o:r,d?r:s,d?r:o,u,c,l],m=n.apply(r,f);return Di(t)&&zi(m,f),m.placeholder=a,Vi(m,t,e)}function ii(t){var e=Ut[t];return function(t,n){if(t=Co(t),(n=null==n?0:Mn(Oo(n),292))&&Dn(t)){var a=(No(t)+"e").split("e");return+((a=(No(e(a[0]+"e"+(+a[1]+n)))+"e").split("e"))[0]+"e"+(+a[1]-n))}return e(t)}}var si=Hn&&1/mn(new Hn([,-0]))[1]==O?function(t){return new Hn(t)}:vu;function oi(t){return function(e){var n=Oi(e);return n==Y?hn(e):n==K?yn(e):function(t,e){return Ge(e,function(e){return[e,t[e]]})}(e,t(e))}}function ui(t,e,n,i,u,c,l,d){var f=e&h;if(!f&&"function"!=typeof t)throw new Zt(s);var T=i?i.length:0;if(T||(e&=~(y|v),i=u=r),l=l===r?l:Pn(Oo(l),0),d=d===r?d:Oo(d),T-=u?u.length:0,e&v){var w=i,S=u;i=u=r}var O=f?r:bi(t),I=[t,e,n,i,u,w,S,c,l,d];if(O&&function(t,e){var n=t[1],a=e[1],r=n|a;if(!(r<(p|h|_)||a==_&&n==b||a==_&&n==x&&t[7].length<=e[8]||a==(_|x)&&e[7].length<=e[8]&&n==b))return t;a&p&&(t[2]=e[2],r|=n&p?0:g);var i=e[3];if(i){var s=t[3];t[3]=s?jr(s,i,e[4]):i,t[4]=s?bn(t[3],o):e[4]}(i=e[5])&&(t[5]=(s=t[5])?Fr(s,i,e[6]):i,t[6]=s?bn(t[5],o):e[6]),(i=e[7])&&(t[7]=i),a&_&&(t[8]=null==t[8]?e[8]:Mn(t[8],e[8])),null==t[9]&&(t[9]=e[9]),t[0]=e[0],t[1]=r}(I,O),t=I[0],e=I[1],n=I[2],i=I[3],u=I[4],!(d=I[9]=I[9]===r?f?0:t.length:Pn(I[9]-T,0))&&e&(b|m)&&(e&=~(b|m)),e&&e!=p)C=e==b||e==m?function(t,e,n){var i=Kr(t);return function s(){for(var o=arguments.length,u=a(o),c=o,l=yi(s);c--;)u[c]=arguments[c];var d=o<3&&u[0]!==l&&u[o-1]!==l?[]:bn(u,l);return(o-=d.length)<n?ri(t,e,Xr,s.placeholder,r,u,d,r,r,n-o):Le(this&&this!==Te&&this instanceof s?i:t,this,u)}}(t,e,d):e!=y&&e!=(p|y)||u.length?Xr.apply(r,I):function(t,e,n,r){var i=e&p,s=Kr(t);return function e(){for(var o=-1,u=arguments.length,c=-1,l=r.length,d=a(l+u),f=this&&this!==Te&&this instanceof e?s:t;++c<l;)d[c]=r[c];for(;u--;)d[c++]=arguments[++o];return Le(f,i?n:this,d)}}(t,e,n,i);else var C=function(t,e,n){var a=e&p,r=Kr(t);return function e(){return(this&&this!==Te&&this instanceof e?r:t).apply(a?n:this,arguments)}}(t,e,n);return Vi((O?fr:zi)(C,I),t,e)}function ci(t,e,n,a){return t===r||Zs(t,Jt[n])&&!ee.call(a,n)?e:t}function li(t,e,n,a,i,s){return lo(t)&&lo(e)&&(s.set(e,t),nr(t,e,r,li,s),s.delete(e)),t}function di(t){return go(t)?r:t}function fi(t,e,n,a,i,s){var o=n&d,u=t.length,c=e.length;if(u!=c&&!(o&&c>u))return!1;var l=s.get(t);if(l&&s.get(e))return l==e;var p=-1,h=!0,g=n&f?new da:r;for(s.set(t,e),s.set(e,t);++p<u;){var b=t[p],m=e[p];if(a)var y=o?a(m,b,p,e,t,s):a(b,m,p,t,e,s);if(y!==r){if(y)continue;h=!1;break}if(g){if(!Be(e,function(t,e){if(!on(g,e)&&(b===t||i(b,t,n,a,s)))return g.push(e)})){h=!1;break}}else if(b!==m&&!i(b,m,n,a,s)){h=!1;break}}return s.delete(t),s.delete(e),h}function pi(t){return Yi(qi(t,r,es),t+"")}function hi(t){return Fa(t,Yo,wi)}function gi(t){return Fa(t,Vo,Si)}var bi=Wn?function(t){return Wn.get(t)}:vu;function mi(t){for(var e=t.name+"",n=Kn[e],a=ee.call(Kn,e)?n.length:0;a--;){var r=n[a],i=r.func;if(null==i||i==t)return r.name}return e}function yi(t){return(ee.call(aa,"placeholder")?aa:t).placeholder}function vi(){var t=aa.iteratee||gu;return t=t===gu?Za:t,arguments.length?t(arguments[0],arguments[1]):t}function _i(t,e){var n,a,r=t.__data__;return("string"==(a=typeof(n=e))||"number"==a||"symbol"==a||"boolean"==a?"__proto__"!==n:null===n)?r["string"==typeof e?"string":"hash"]:r.map}function xi(t){for(var e=Yo(t),n=e.length;n--;){var a=e[n],r=t[a];e[n]=[a,r,Pi(r)]}return e}function Ti(t,e){var n=function(t,e){return null==t?r:t[e]}(t,e);return $a(n)?n:r}var wi=Rn?function(t){return null==t?[]:(t=Wt(t),je(Rn(t),function(e){return Ie.call(t,e)}))}:Iu,Si=Rn?function(t){for(var e=[];t;)Ye(e,wi(t)),t=we(t);return e}:Iu,Oi=za;function Ii(t,e,n){for(var a=-1,r=(e=Rr(e,t)).length,i=!1;++a<r;){var s=Wi(e[a]);if(!(i=null!=t&&n(t,s)))break;t=t[s]}return i||++a!=r?i:!!(r=null==t?0:t.length)&&co(r)&&Ni(s,r)&&(to(t)||Qs(t))}function Ci(t){return"function"!=typeof t.constructor||Li(t)?{}:ra(we(t))}function ki(t){return to(t)||Qs(t)||!!(Ue&&t&&t[Ue])}function Ni(t,e){var n=typeof t;return!!(e=null==e?I:e)&&("number"==n||"symbol"!=n&&Ft.test(t))&&t>-1&&t%1==0&&t<e}function Ri(t,e,n){if(!lo(n))return!1;var a=typeof e;return!!("number"==a?no(n)&&Ni(e,n.length):"string"==a&&e in n)&&Zs(n[e],t)}function Ai(t,e){if(to(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!vo(t))||xt.test(t)||!_t.test(t)||null!=e&&t in Wt(e)}function Di(t){var e=mi(t),n=aa[e];if("function"!=typeof n||!(e in oa.prototype))return!1;if(t===n)return!0;var a=bi(n);return!!a&&t===a[0]}(Gn&&Oi(new Gn(new ArrayBuffer(1)))!=tt||Yn&&Oi(new Yn)!=Y||Vn&&"[object Promise]"!=Oi(Vn.resolve())||Hn&&Oi(new Hn)!=K||Bn&&Oi(new Bn)!=J)&&(Oi=function(t){var e=za(t),n=e==B?t.constructor:r,a=n?Ki(n):"";if(a)switch(a){case $n:return tt;case Zn:return Y;case Xn:return"[object Promise]";case Jn:return K;case Qn:return J}return e});var Ei=Qt?oo:Cu;function Li(t){var e=t&&t.constructor;return t===("function"==typeof e&&e.prototype||Jt)}function Pi(t){return t==t&&!lo(t)}function Mi(t,e){return function(n){return null!=n&&n[t]===e&&(e!==r||t in Wt(n))}}function qi(t,e,n){return e=Pn(e===r?t.length-1:e,0),function(){for(var r=arguments,i=-1,s=Pn(r.length-e,0),o=a(s);++i<s;)o[i]=r[e+i];i=-1;for(var u=a(e+1);++i<e;)u[i]=r[i];return u[e]=n(o),Le(t,this,u)}}function ji(t,e){return e.length<2?t:ja(t,hr(e,0,-1))}function Fi(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}var zi=Hi(fr),Gi=Cn||function(t,e){return Te.setTimeout(t,e)},Yi=Hi(pr);function Vi(t,e,n){var a=e+"";return Yi(t,function(t,e){var n=e.length;if(!n)return t;var a=n-1;return e[a]=(n>1?"& ":"")+e[a],e=e.join(n>2?", ":" "),t.replace(kt,"{\n/* [wrapped with "+e+"] */\n")}(a,function(t,e){return Me(D,function(n){var a="_."+n[0];e&n[1]&&!Fe(t,a)&&t.push(a)}),t.sort()}(function(t){var e=t.match(Nt);return e?e[1].split(Rt):[]}(a),n)))}function Hi(t){var e=0,n=0;return function(){var a=qn(),i=S-(a-n);if(n=a,i>0){if(++e>=w)return arguments[0]}else e=0;return t.apply(r,arguments)}}function Bi(t,e){var n=-1,a=t.length,i=a-1;for(e=e===r?a:e;++n<e;){var s=ur(n,i),o=t[s];t[s]=t[n],t[n]=o}return t.length=e,t}var Ui=function(t){var e=Hs(function(t){var e=[];return 46===t.charCodeAt(0)&&e.push(""),t.replace(Tt,function(t,n,a,r){e.push(a?r.replace(Dt,"$1"):n||t)}),e},function(t){return 500===n.size&&n.clear(),t}),n=e.cache;return e}();function Wi(t){if("string"==typeof t||vo(t))return t;var e=t+"";return"0"==e&&1/t==-O?"-0":e}function Ki(t){if(null!=t){try{return te.call(t)}catch(e){}try{return t+""}catch(e){}}return""}function $i(t){if(t instanceof oa)return t.clone();var e=new sa(t.__wrapped__,t.__chain__);return e.__actions__=zr(t.__actions__),e.__index__=t.__index__,e.__values__=t.__values__,e}var Zi=lr(function(t,e){return ao(t)?Ia(t,Da(e,1,ao,!0)):[]}),Xi=lr(function(t,e){var n=ss(e);return ao(n)&&(n=r),ao(t)?Ia(t,Da(e,1,ao,!0),vi(n,2)):[]}),Ji=lr(function(t,e){var n=ss(e);return ao(n)&&(n=r),ao(t)?Ia(t,Da(e,1,ao,!0),r,n):[]});function Qi(t,e,n){var a=null==t?0:t.length;if(!a)return-1;var r=null==n?0:Oo(n);return r<0&&(r=Pn(a+r,0)),Ke(t,vi(e,3),r)}function ts(t,e,n){var a=null==t?0:t.length;if(!a)return-1;var i=a-1;return n!==r&&(i=Oo(n),i=n<0?Pn(a+i,0):Mn(i,a-1)),Ke(t,vi(e,3),i,!0)}function es(t){return null!=t&&t.length?Da(t,1):[]}function ns(t){return t&&t.length?t[0]:r}var as=lr(function(t){var e=Ge(t,kr);return e.length&&e[0]===t[0]?Ha(e):[]}),rs=lr(function(t){var e=ss(t),n=Ge(t,kr);return e===ss(n)?e=r:n.pop(),n.length&&n[0]===t[0]?Ha(n,vi(e,2)):[]}),is=lr(function(t){var e=ss(t),n=Ge(t,kr);return(e="function"==typeof e?e:r)&&n.pop(),n.length&&n[0]===t[0]?Ha(n,r,e):[]});function ss(t){var e=null==t?0:t.length;return e?t[e-1]:r}var os=lr(us);function us(t,e){return t&&t.length&&e&&e.length?sr(t,e):t}var cs=pi(function(t,e){var n=null==t?0:t.length,a=xa(t,e);return or(t,Ge(e,function(t){return Ni(t,n)?+t:t}).sort(qr)),a});function ls(t){return null==t?t:zn.call(t)}var ds=lr(function(t){return xr(Da(t,1,ao,!0))}),fs=lr(function(t){var e=ss(t);return ao(e)&&(e=r),xr(Da(t,1,ao,!0),vi(e,2))}),ps=lr(function(t){var e=ss(t);return e="function"==typeof e?e:r,xr(Da(t,1,ao,!0),r,e)});function hs(t){if(!t||!t.length)return[];var e=0;return t=je(t,function(t){if(ao(t))return e=Pn(t.length,e),!0}),an(e,function(e){return Ge(t,Qe(e))})}function gs(t,e){if(!t||!t.length)return[];var n=hs(t);return null==e?n:Ge(n,function(t){return Le(e,r,t)})}var bs=lr(function(t,e){return ao(t)?Ia(t,e):[]}),ms=lr(function(t){return Ir(je(t,ao))}),ys=lr(function(t){var e=ss(t);return ao(e)&&(e=r),Ir(je(t,ao),vi(e,2))}),vs=lr(function(t){var e=ss(t);return e="function"==typeof e?e:r,Ir(je(t,ao),r,e)}),_s=lr(hs),xs=lr(function(t){var e=t.length,n=e>1?t[e-1]:r;return n="function"==typeof n?(t.pop(),n):r,gs(t,n)});function Ts(t){var e=aa(t);return e.__chain__=!0,e}function ws(t,e){return e(t)}var Ss=pi(function(t){var e=t.length,n=e?t[0]:0,a=this.__wrapped__,i=function(e){return xa(e,t)};return!(e>1||this.__actions__.length)&&a instanceof oa&&Ni(n)?((a=a.slice(n,+n+(e?1:0))).__actions__.push({func:ws,args:[i],thisArg:r}),new sa(a,this.__chain__).thru(function(t){return e&&!t.length&&t.push(r),t})):this.thru(i)}),Os=Yr(function(t,e,n){ee.call(t,n)?++t[n]:_a(t,n,1)}),Is=$r(Qi),Cs=$r(ts);function ks(t,e){return(to(t)?Me:Ca)(t,vi(e,3))}function Ns(t,e){return(to(t)?function(t,e){for(var n=null==t?0:t.length;n--&&!1!==e(t[n],n,t););return t}:ka)(t,vi(e,3))}var Rs=Yr(function(t,e,n){ee.call(t,n)?t[n].push(e):_a(t,n,[e])}),As=lr(function(t,e,n){var r=-1,i="function"==typeof e,s=no(t)?a(t.length):[];return Ca(t,function(t){s[++r]=i?Le(e,t,n):Ba(t,e,n)}),s}),Ds=Yr(function(t,e,n){_a(t,n,e)});function Es(t,e){return(to(t)?Ge:Qa)(t,vi(e,3))}var Ls=Yr(function(t,e,n){t[n?0:1].push(e)},function(){return[[],[]]}),Ps=lr(function(t,e){if(null==t)return[];var n=e.length;return n>1&&Ri(t,e[0],e[1])?e=[]:n>2&&Ri(e[0],e[1],e[2])&&(e=[e[0]]),rr(t,Da(e,1),[])}),Ms=In||function(){return Te.Date.now()};function qs(t,e,n){return e=n?r:e,ui(t,_,r,r,r,r,e=t&&null==e?t.length:e)}function js(t,e){var n;if("function"!=typeof e)throw new Zt(s);return t=Oo(t),function(){return--t>0&&(n=e.apply(this,arguments)),t<=1&&(e=r),n}}var Fs=lr(function(t,e,n){var a=p;if(n.length){var r=bn(n,yi(Fs));a|=y}return ui(t,a,e,n,r)}),zs=lr(function(t,e,n){var a=p|h;if(n.length){var r=bn(n,yi(zs));a|=y}return ui(e,a,t,n,r)});function Gs(t,e,n){var a,i,o,u,c,l,d=0,f=!1,p=!1,h=!0;if("function"!=typeof t)throw new Zt(s);function g(e){var n=a,s=i;return a=i=r,d=e,u=t.apply(s,n)}function b(t){var n=t-l;return l===r||n>=e||n<0||p&&t-d>=o}function m(){var t=Ms();if(b(t))return y(t);c=Gi(m,function(t){var n=e-(t-l);return p?Mn(n,o-(t-d)):n}(t))}function y(t){return c=r,h&&a?g(t):(a=i=r,u)}function v(){var t=Ms(),n=b(t);if(a=arguments,i=this,l=t,n){if(c===r)return function(t){return d=t,c=Gi(m,e),f?g(t):u}(l);if(p)return Er(c),c=Gi(m,e),g(l)}return c===r&&(c=Gi(m,e)),u}return e=Co(e)||0,lo(n)&&(f=!!n.leading,o=(p="maxWait"in n)?Pn(Co(n.maxWait)||0,e):o,h="trailing"in n?!!n.trailing:h),v.cancel=function(){c!==r&&Er(c),d=0,a=l=i=c=r},v.flush=function(){return c===r?u:y(Ms())},v}var Ys=lr(function(t,e){return Oa(t,1,e)}),Vs=lr(function(t,e,n){return Oa(t,Co(e)||0,n)});function Hs(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new Zt(s);var n=function(){var a=arguments,r=e?e.apply(this,a):a[0],i=n.cache;if(i.has(r))return i.get(r);var s=t.apply(this,a);return n.cache=i.set(r,s)||i,s};return n.cache=new(Hs.Cache||la),n}function Bs(t){if("function"!=typeof t)throw new Zt(s);return function(){var e=arguments;switch(e.length){case 0:return!t.call(this);case 1:return!t.call(this,e[0]);case 2:return!t.call(this,e[0],e[1]);case 3:return!t.call(this,e[0],e[1],e[2])}return!t.apply(this,e)}}Hs.Cache=la;var Us=Ar(function(t,e){var n=(e=1==e.length&&to(e[0])?Ge(e[0],rn(vi())):Ge(Da(e,1),rn(vi()))).length;return lr(function(a){for(var r=-1,i=Mn(a.length,n);++r<i;)a[r]=e[r].call(this,a[r]);return Le(t,this,a)})}),Ws=lr(function(t,e){var n=bn(e,yi(Ws));return ui(t,y,r,e,n)}),Ks=lr(function(t,e){var n=bn(e,yi(Ks));return ui(t,v,r,e,n)}),$s=pi(function(t,e){return ui(t,x,r,r,r,e)});function Zs(t,e){return t===e||t!=t&&e!=e}var Xs=ai(Ga),Js=ai(function(t,e){return t>=e}),Qs=Ua(function(){return arguments}())?Ua:function(t){return fo(t)&&ee.call(t,"callee")&&!Ie.call(t,"callee")},to=a.isArray,eo=ke?rn(ke):function(t){return fo(t)&&za(t)==Q};function no(t){return null!=t&&co(t.length)&&!oo(t)}function ao(t){return fo(t)&&no(t)}var ro=An||Cu,io=Ne?rn(Ne):function(t){return fo(t)&&za(t)==q};function so(t){if(!fo(t))return!1;var e=za(t);return e==F||e==j||"string"==typeof t.message&&"string"==typeof t.name&&!go(t)}function oo(t){if(!lo(t))return!1;var e=za(t);return e==z||e==G||e==P||e==U}function uo(t){return"number"==typeof t&&t==Oo(t)}function co(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=I}function lo(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function fo(t){return null!=t&&"object"==typeof t}var po=Re?rn(Re):function(t){return fo(t)&&Oi(t)==Y};function ho(t){return"number"==typeof t||fo(t)&&za(t)==V}function go(t){if(!fo(t)||za(t)!=B)return!1;var e=we(t);if(null===e)return!0;var n=ee.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&te.call(n)==ie}var bo=Ae?rn(Ae):function(t){return fo(t)&&za(t)==W},mo=De?rn(De):function(t){return fo(t)&&Oi(t)==K};function yo(t){return"string"==typeof t||!to(t)&&fo(t)&&za(t)==$}function vo(t){return"symbol"==typeof t||fo(t)&&za(t)==Z}var _o=Ee?rn(Ee):function(t){return fo(t)&&co(t.length)&&!!ge[za(t)]},xo=ai(Ja),To=ai(function(t,e){return t<=e});function wo(t){if(!t)return[];if(no(t))return yo(t)?_n(t):zr(t);if(tn&&t[tn])return function(t){for(var e,n=[];!(e=t.next()).done;)n.push(e.value);return n}(t[tn]());var e=Oi(t);return(e==Y?hn:e==K?mn:Xo)(t)}function So(t){return t?(t=Co(t))===O||t===-O?(t<0?-1:1)*C:t==t?t:0:0===t?t:0}function Oo(t){var e=So(t),n=e%1;return e==e?n?e-n:e:0}function Io(t){return t?Ta(Oo(t),0,N):0}function Co(t){if("number"==typeof t)return t;if(vo(t))return k;if(lo(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=lo(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(Ot,"");var n=Mt.test(t);return n||jt.test(t)?ve(t.slice(2),n?2:8):Pt.test(t)?k:+t}function ko(t){return Gr(t,Vo(t))}function No(t){return null==t?"":_r(t)}var Ro=Vr(function(t,e){if(Li(e)||no(e))Gr(e,Yo(e),t);else for(var n in e)ee.call(e,n)&&ba(t,n,e[n])}),Ao=Vr(function(t,e){Gr(e,Vo(e),t)}),Do=Vr(function(t,e,n,a){Gr(e,Vo(e),t,a)}),Eo=Vr(function(t,e,n,a){Gr(e,Yo(e),t,a)}),Lo=pi(xa),Po=lr(function(t,e){t=Wt(t);var n=-1,a=e.length,i=a>2?e[2]:r;for(i&&Ri(e[0],e[1],i)&&(a=1);++n<a;)for(var s=e[n],o=Vo(s),u=-1,c=o.length;++u<c;){var l=o[u],d=t[l];(d===r||Zs(d,Jt[l])&&!ee.call(t,l))&&(t[l]=s[l])}return t}),Mo=lr(function(t){return t.push(r,li),Le(Bo,r,t)});function qo(t,e,n){var a=null==t?r:ja(t,e);return a===r?n:a}function jo(t,e){return null!=t&&Ii(t,e,Va)}var Fo=Jr(function(t,e,n){null!=e&&"function"!=typeof e.toString&&(e=re.call(e)),t[e]=n},du(hu)),zo=Jr(function(t,e,n){null!=e&&"function"!=typeof e.toString&&(e=re.call(e)),ee.call(t,e)?t[e].push(n):t[e]=[n]},vi),Go=lr(Ba);function Yo(t){return no(t)?pa(t):Xa(t)}function Vo(t){return no(t)?pa(t,!0):function(t){if(!lo(t))return function(t){var e=[];if(null!=t)for(var n in Wt(t))e.push(n);return e}(t);var e=Li(t),n=[];for(var a in t)("constructor"!=a||!e&&ee.call(t,a))&&n.push(a);return n}(t)}var Ho=Vr(function(t,e,n){nr(t,e,n)}),Bo=Vr(function(t,e,n,a){nr(t,e,n,a)}),Uo=pi(function(t,e){var n={};if(null==t)return n;var a=!1;e=Ge(e,function(e){return e=Rr(e,t),a||(a=e.length>1),e}),Gr(t,gi(t),n),a&&(n=wa(n,u|c|l,di));for(var r=e.length;r--;)Tr(n,e[r]);return n}),Wo=pi(function(t,e){return null==t?{}:function(t,e){return ir(t,e,function(e,n){return jo(t,n)})}(t,e)});function Ko(t,e){if(null==t)return{};var n=Ge(gi(t),function(t){return[t]});return e=vi(e),ir(t,n,function(t,n){return e(t,n[0])})}var $o=oi(Yo),Zo=oi(Vo);function Xo(t){return null==t?[]:sn(t,Yo(t))}var Jo=Wr(function(t,e,n){return e=e.toLowerCase(),t+(n?Qo(e):e)});function Qo(t){return ou(No(t).toLowerCase())}function tu(t){return(t=No(t))&&t.replace(zt,ln).replace(ue,"")}var eu=Wr(function(t,e,n){return t+(n?"-":"")+e.toLowerCase()}),nu=Wr(function(t,e,n){return t+(n?" ":"")+e.toLowerCase()}),au=Ur("toLowerCase"),ru=Wr(function(t,e,n){return t+(n?"_":"")+e.toLowerCase()}),iu=Wr(function(t,e,n){return t+(n?" ":"")+ou(e)}),su=Wr(function(t,e,n){return t+(n?" ":"")+e.toUpperCase()}),ou=Ur("toUpperCase");function uu(t,e,n){return t=No(t),(e=n?r:e)===r?function(t){return fe.test(t)}(t)?function(t){return t.match(le)||[]}(t):function(t){return t.match(At)||[]}(t):t.match(e)||[]}var cu=lr(function(t,e){try{return Le(t,r,e)}catch(n){return so(n)?n:new Ht(n)}}),lu=pi(function(t,e){return Me(e,function(e){e=Wi(e),_a(t,e,Fs(t[e],t))}),t});function du(t){return function(){return t}}var fu=Zr(),pu=Zr(!0);function hu(t){return t}function gu(t){return Za("function"==typeof t?t:wa(t,u))}var bu=lr(function(t,e){return function(n){return Ba(n,t,e)}}),mu=lr(function(t,e){return function(n){return Ba(t,n,e)}});function yu(t,e,n){var a=Yo(e),r=qa(e,a);null!=n||lo(e)&&(r.length||!a.length)||(n=e,e=t,t=this,r=qa(e,Yo(e)));var i=!(lo(n)&&"chain"in n&&!n.chain),s=oo(t);return Me(r,function(n){var a=e[n];t[n]=a,s&&(t.prototype[n]=function(){var e=this.__chain__;if(i||e){var n=t(this.__wrapped__);return(n.__actions__=zr(this.__actions__)).push({func:a,args:arguments,thisArg:t}),n.__chain__=e,n}return a.apply(t,Ye([this.value()],arguments))})}),t}function vu(){}var _u=ti(Ge),xu=ti(qe),Tu=ti(Be);function wu(t){return Ai(t)?Qe(Wi(t)):function(t){return function(e){return ja(e,t)}}(t)}var Su=ni(),Ou=ni(!0);function Iu(){return[]}function Cu(){return!1}var ku,Nu=Qr(function(t,e){return t+e},0),Ru=ii("ceil"),Au=Qr(function(t,e){return t/e},1),Du=ii("floor"),Eu=Qr(function(t,e){return t*e},1),Lu=ii("round"),Pu=Qr(function(t,e){return t-e},0);return aa.after=function(t,e){if("function"!=typeof e)throw new Zt(s);return t=Oo(t),function(){if(--t<1)return e.apply(this,arguments)}},aa.ary=qs,aa.assign=Ro,aa.assignIn=Ao,aa.assignInWith=Do,aa.assignWith=Eo,aa.at=Lo,aa.before=js,aa.bind=Fs,aa.bindAll=lu,aa.bindKey=zs,aa.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return to(t)?t:[t]},aa.chain=Ts,aa.chunk=function(t,e,n){e=(n?Ri(t,e,n):e===r)?1:Pn(Oo(e),0);var i=null==t?0:t.length;if(!i||e<1)return[];for(var s=0,o=0,u=a(kn(i/e));s<i;)u[o++]=hr(t,s,s+=e);return u},aa.compact=function(t){for(var e=-1,n=null==t?0:t.length,a=0,r=[];++e<n;){var i=t[e];i&&(r[a++]=i)}return r},aa.concat=function(){var t=arguments.length;if(!t)return[];for(var e=a(t-1),n=arguments[0],r=t;r--;)e[r-1]=arguments[r];return Ye(to(n)?zr(n):[n],Da(e,1))},aa.cond=function(t){var e=null==t?0:t.length,n=vi();return t=e?Ge(t,function(t){if("function"!=typeof t[1])throw new Zt(s);return[n(t[0]),t[1]]}):[],lr(function(n){for(var a=-1;++a<e;){var r=t[a];if(Le(r[0],this,n))return Le(r[1],this,n)}})},aa.conforms=function(t){return function(t){var e=Yo(t);return function(n){return Sa(n,t,e)}}(wa(t,u))},aa.constant=du,aa.countBy=Os,aa.create=function(t,e){var n=ra(t);return null==e?n:va(n,e)},aa.curry=function t(e,n,a){var i=ui(e,b,r,r,r,r,r,n=a?r:n);return i.placeholder=t.placeholder,i},aa.curryRight=function t(e,n,a){var i=ui(e,m,r,r,r,r,r,n=a?r:n);return i.placeholder=t.placeholder,i},aa.debounce=Gs,aa.defaults=Po,aa.defaultsDeep=Mo,aa.defer=Ys,aa.delay=Vs,aa.difference=Zi,aa.differenceBy=Xi,aa.differenceWith=Ji,aa.drop=function(t,e,n){var a=null==t?0:t.length;return a?hr(t,(e=n||e===r?1:Oo(e))<0?0:e,a):[]},aa.dropRight=function(t,e,n){var a=null==t?0:t.length;return a?hr(t,0,(e=a-(e=n||e===r?1:Oo(e)))<0?0:e):[]},aa.dropRightWhile=function(t,e){return t&&t.length?Sr(t,vi(e,3),!0,!0):[]},aa.dropWhile=function(t,e){return t&&t.length?Sr(t,vi(e,3),!0):[]},aa.fill=function(t,e,n,a){var i=null==t?0:t.length;return i?(n&&"number"!=typeof n&&Ri(t,e,n)&&(n=0,a=i),function(t,e,n,a){var i=t.length;for((n=Oo(n))<0&&(n=-n>i?0:i+n),(a=a===r||a>i?i:Oo(a))<0&&(a+=i),a=n>a?0:Io(a);n<a;)t[n++]=e;return t}(t,e,n,a)):[]},aa.filter=function(t,e){return(to(t)?je:Aa)(t,vi(e,3))},aa.flatMap=function(t,e){return Da(Es(t,e),1)},aa.flatMapDeep=function(t,e){return Da(Es(t,e),O)},aa.flatMapDepth=function(t,e,n){return n=n===r?1:Oo(n),Da(Es(t,e),n)},aa.flatten=es,aa.flattenDeep=function(t){return null!=t&&t.length?Da(t,O):[]},aa.flattenDepth=function(t,e){return null!=t&&t.length?Da(t,e=e===r?1:Oo(e)):[]},aa.flip=function(t){return ui(t,T)},aa.flow=fu,aa.flowRight=pu,aa.fromPairs=function(t){for(var e=-1,n=null==t?0:t.length,a={};++e<n;){var r=t[e];a[r[0]]=r[1]}return a},aa.functions=function(t){return null==t?[]:qa(t,Yo(t))},aa.functionsIn=function(t){return null==t?[]:qa(t,Vo(t))},aa.groupBy=Rs,aa.initial=function(t){return null!=t&&t.length?hr(t,0,-1):[]},aa.intersection=as,aa.intersectionBy=rs,aa.intersectionWith=is,aa.invert=Fo,aa.invertBy=zo,aa.invokeMap=As,aa.iteratee=gu,aa.keyBy=Ds,aa.keys=Yo,aa.keysIn=Vo,aa.map=Es,aa.mapKeys=function(t,e){var n={};return e=vi(e,3),Pa(t,function(t,a,r){_a(n,e(t,a,r),t)}),n},aa.mapValues=function(t,e){var n={};return e=vi(e,3),Pa(t,function(t,a,r){_a(n,a,e(t,a,r))}),n},aa.matches=function(t){return tr(wa(t,u))},aa.matchesProperty=function(t,e){return er(t,wa(e,u))},aa.memoize=Hs,aa.merge=Ho,aa.mergeWith=Bo,aa.method=bu,aa.methodOf=mu,aa.mixin=yu,aa.negate=Bs,aa.nthArg=function(t){return t=Oo(t),lr(function(e){return ar(e,t)})},aa.omit=Uo,aa.omitBy=function(t,e){return Ko(t,Bs(vi(e)))},aa.once=function(t){return js(2,t)},aa.orderBy=function(t,e,n,a){return null==t?[]:(to(e)||(e=null==e?[]:[e]),to(n=a?r:n)||(n=null==n?[]:[n]),rr(t,e,n))},aa.over=_u,aa.overArgs=Us,aa.overEvery=xu,aa.overSome=Tu,aa.partial=Ws,aa.partialRight=Ks,aa.partition=Ls,aa.pick=Wo,aa.pickBy=Ko,aa.property=wu,aa.propertyOf=function(t){return function(e){return null==t?r:ja(t,e)}},aa.pull=os,aa.pullAll=us,aa.pullAllBy=function(t,e,n){return t&&t.length&&e&&e.length?sr(t,e,vi(n,2)):t},aa.pullAllWith=function(t,e,n){return t&&t.length&&e&&e.length?sr(t,e,r,n):t},aa.pullAt=cs,aa.range=Su,aa.rangeRight=Ou,aa.rearg=$s,aa.reject=function(t,e){return(to(t)?je:Aa)(t,Bs(vi(e,3)))},aa.remove=function(t,e){var n=[];if(!t||!t.length)return n;var a=-1,r=[],i=t.length;for(e=vi(e,3);++a<i;){var s=t[a];e(s,a,t)&&(n.push(s),r.push(a))}return or(t,r),n},aa.rest=function(t,e){if("function"!=typeof t)throw new Zt(s);return lr(t,e=e===r?e:Oo(e))},aa.reverse=ls,aa.sampleSize=function(t,e,n){return e=(n?Ri(t,e,n):e===r)?1:Oo(e),(to(t)?function(t,e){return Bi(zr(t),Ta(e,0,t.length))}:function(t,e){var n=Xo(t);return Bi(n,Ta(e,0,n.length))})(t,e)},aa.set=function(t,e,n){return null==t?t:dr(t,e,n)},aa.setWith=function(t,e,n,a){return a="function"==typeof a?a:r,null==t?t:dr(t,e,n,a)},aa.shuffle=function(t){return(to(t)?function(t){return Bi(zr(t))}:function(t){return Bi(Xo(t))})(t)},aa.slice=function(t,e,n){var a=null==t?0:t.length;return a?(n&&"number"!=typeof n&&Ri(t,e,n)?(e=0,n=a):(e=null==e?0:Oo(e),n=n===r?a:Oo(n)),hr(t,e,n)):[]},aa.sortBy=Ps,aa.sortedUniq=function(t){return t&&t.length?yr(t):[]},aa.sortedUniqBy=function(t,e){return t&&t.length?yr(t,vi(e,2)):[]},aa.split=function(t,e,n){return n&&"number"!=typeof n&&Ri(t,e,n)&&(e=n=r),(n=n===r?N:n>>>0)?(t=No(t))&&("string"==typeof e||null!=e&&!bo(e))&&!(e=_r(e))&&pn(t)?Dr(_n(t),0,n):t.split(e,n):[]},aa.spread=function(t,e){if("function"!=typeof t)throw new Zt(s);return e=null==e?0:Pn(Oo(e),0),lr(function(n){var a=n[e],r=Dr(n,0,e);return a&&Ye(r,a),Le(t,this,r)})},aa.tail=function(t){var e=null==t?0:t.length;return e?hr(t,1,e):[]},aa.take=function(t,e,n){return t&&t.length?hr(t,0,(e=n||e===r?1:Oo(e))<0?0:e):[]},aa.takeRight=function(t,e,n){var a=null==t?0:t.length;return a?hr(t,(e=a-(e=n||e===r?1:Oo(e)))<0?0:e,a):[]},aa.takeRightWhile=function(t,e){return t&&t.length?Sr(t,vi(e,3),!1,!0):[]},aa.takeWhile=function(t,e){return t&&t.length?Sr(t,vi(e,3)):[]},aa.tap=function(t,e){return e(t),t},aa.throttle=function(t,e,n){var a=!0,r=!0;if("function"!=typeof t)throw new Zt(s);return lo(n)&&(a="leading"in n?!!n.leading:a,r="trailing"in n?!!n.trailing:r),Gs(t,e,{leading:a,maxWait:e,trailing:r})},aa.thru=ws,aa.toArray=wo,aa.toPairs=$o,aa.toPairsIn=Zo,aa.toPath=function(t){return to(t)?Ge(t,Wi):vo(t)?[t]:zr(Ui(No(t)))},aa.toPlainObject=ko,aa.transform=function(t,e,n){var a=to(t),r=a||ro(t)||_o(t);if(e=vi(e,4),null==n){var i=t&&t.constructor;n=r?a?new i:[]:lo(t)&&oo(i)?ra(we(t)):{}}return(r?Me:Pa)(t,function(t,a,r){return e(n,t,a,r)}),n},aa.unary=function(t){return qs(t,1)},aa.union=ds,aa.unionBy=fs,aa.unionWith=ps,aa.uniq=function(t){return t&&t.length?xr(t):[]},aa.uniqBy=function(t,e){return t&&t.length?xr(t,vi(e,2)):[]},aa.uniqWith=function(t,e){return e="function"==typeof e?e:r,t&&t.length?xr(t,r,e):[]},aa.unset=function(t,e){return null==t||Tr(t,e)},aa.unzip=hs,aa.unzipWith=gs,aa.update=function(t,e,n){return null==t?t:wr(t,e,Nr(n))},aa.updateWith=function(t,e,n,a){return a="function"==typeof a?a:r,null==t?t:wr(t,e,Nr(n),a)},aa.values=Xo,aa.valuesIn=function(t){return null==t?[]:sn(t,Vo(t))},aa.without=bs,aa.words=uu,aa.wrap=function(t,e){return Ws(Nr(e),t)},aa.xor=ms,aa.xorBy=ys,aa.xorWith=vs,aa.zip=_s,aa.zipObject=function(t,e){return Cr(t||[],e||[],ba)},aa.zipObjectDeep=function(t,e){return Cr(t||[],e||[],dr)},aa.zipWith=xs,aa.entries=$o,aa.entriesIn=Zo,aa.extend=Ao,aa.extendWith=Do,yu(aa,aa),aa.add=Nu,aa.attempt=cu,aa.camelCase=Jo,aa.capitalize=Qo,aa.ceil=Ru,aa.clamp=function(t,e,n){return n===r&&(n=e,e=r),n!==r&&(n=(n=Co(n))==n?n:0),e!==r&&(e=(e=Co(e))==e?e:0),Ta(Co(t),e,n)},aa.clone=function(t){return wa(t,l)},aa.cloneDeep=function(t){return wa(t,u|l)},aa.cloneDeepWith=function(t,e){return wa(t,u|l,e="function"==typeof e?e:r)},aa.cloneWith=function(t,e){return wa(t,l,e="function"==typeof e?e:r)},aa.conformsTo=function(t,e){return null==e||Sa(t,e,Yo(e))},aa.deburr=tu,aa.defaultTo=function(t,e){return null==t||t!=t?e:t},aa.divide=Au,aa.endsWith=function(t,e,n){t=No(t),e=_r(e);var a=t.length,i=n=n===r?a:Ta(Oo(n),0,a);return(n-=e.length)>=0&&t.slice(n,i)==e},aa.eq=Zs,aa.escape=function(t){return(t=No(t))&&bt.test(t)?t.replace(ht,dn):t},aa.escapeRegExp=function(t){return(t=No(t))&&St.test(t)?t.replace(wt,"\\$&"):t},aa.every=function(t,e,n){var a=to(t)?qe:Na;return n&&Ri(t,e,n)&&(e=r),a(t,vi(e,3))},aa.find=Is,aa.findIndex=Qi,aa.findKey=function(t,e){return We(t,vi(e,3),Pa)},aa.findLast=Cs,aa.findLastIndex=ts,aa.findLastKey=function(t,e){return We(t,vi(e,3),Ma)},aa.floor=Du,aa.forEach=ks,aa.forEachRight=Ns,aa.forIn=function(t,e){return null==t?t:Ea(t,vi(e,3),Vo)},aa.forInRight=function(t,e){return null==t?t:La(t,vi(e,3),Vo)},aa.forOwn=function(t,e){return t&&Pa(t,vi(e,3))},aa.forOwnRight=function(t,e){return t&&Ma(t,vi(e,3))},aa.get=qo,aa.gt=Xs,aa.gte=Js,aa.has=function(t,e){return null!=t&&Ii(t,e,Ya)},aa.hasIn=jo,aa.head=ns,aa.identity=hu,aa.includes=function(t,e,n,a){t=no(t)?t:Xo(t),n=n&&!a?Oo(n):0;var r=t.length;return n<0&&(n=Pn(r+n,0)),yo(t)?n<=r&&t.indexOf(e,n)>-1:!!r&&$e(t,e,n)>-1},aa.indexOf=function(t,e,n){var a=null==t?0:t.length;if(!a)return-1;var r=null==n?0:Oo(n);return r<0&&(r=Pn(a+r,0)),$e(t,e,r)},aa.inRange=function(t,e,n){return e=So(e),n===r?(n=e,e=0):n=So(n),function(t,e,n){return t>=Mn(e,n)&&t<Pn(e,n)}(t=Co(t),e,n)},aa.invoke=Go,aa.isArguments=Qs,aa.isArray=to,aa.isArrayBuffer=eo,aa.isArrayLike=no,aa.isArrayLikeObject=ao,aa.isBoolean=function(t){return!0===t||!1===t||fo(t)&&za(t)==M},aa.isBuffer=ro,aa.isDate=io,aa.isElement=function(t){return fo(t)&&1===t.nodeType&&!go(t)},aa.isEmpty=function(t){if(null==t)return!0;if(no(t)&&(to(t)||"string"==typeof t||"function"==typeof t.splice||ro(t)||_o(t)||Qs(t)))return!t.length;var e=Oi(t);if(e==Y||e==K)return!t.size;if(Li(t))return!Xa(t).length;for(var n in t)if(ee.call(t,n))return!1;return!0},aa.isEqual=function(t,e){return Wa(t,e)},aa.isEqualWith=function(t,e,n){var a=(n="function"==typeof n?n:r)?n(t,e):r;return a===r?Wa(t,e,r,n):!!a},aa.isError=so,aa.isFinite=function(t){return"number"==typeof t&&Dn(t)},aa.isFunction=oo,aa.isInteger=uo,aa.isLength=co,aa.isMap=po,aa.isMatch=function(t,e){return t===e||Ka(t,e,xi(e))},aa.isMatchWith=function(t,e,n){return n="function"==typeof n?n:r,Ka(t,e,xi(e),n)},aa.isNaN=function(t){return ho(t)&&t!=+t},aa.isNative=function(t){if(Ei(t))throw new Ht("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return $a(t)},aa.isNil=function(t){return null==t},aa.isNull=function(t){return null===t},aa.isNumber=ho,aa.isObject=lo,aa.isObjectLike=fo,aa.isPlainObject=go,aa.isRegExp=bo,aa.isSafeInteger=function(t){return uo(t)&&t>=-I&&t<=I},aa.isSet=mo,aa.isString=yo,aa.isSymbol=vo,aa.isTypedArray=_o,aa.isUndefined=function(t){return t===r},aa.isWeakMap=function(t){return fo(t)&&Oi(t)==J},aa.isWeakSet=function(t){return fo(t)&&"[object WeakSet]"==za(t)},aa.join=function(t,e){return null==t?"":En.call(t,e)},aa.kebabCase=eu,aa.last=ss,aa.lastIndexOf=function(t,e,n){var a=null==t?0:t.length;if(!a)return-1;var i=a;return n!==r&&(i=(i=Oo(n))<0?Pn(a+i,0):Mn(i,a-1)),e==e?function(t,e,n){for(var a=n+1;a--;)if(t[a]===e)return a;return a}(t,e,i):Ke(t,Xe,i,!0)},aa.lowerCase=nu,aa.lowerFirst=au,aa.lt=xo,aa.lte=To,aa.max=function(t){return t&&t.length?Ra(t,hu,Ga):r},aa.maxBy=function(t,e){return t&&t.length?Ra(t,vi(e,2),Ga):r},aa.mean=function(t){return Je(t,hu)},aa.meanBy=function(t,e){return Je(t,vi(e,2))},aa.min=function(t){return t&&t.length?Ra(t,hu,Ja):r},aa.minBy=function(t,e){return t&&t.length?Ra(t,vi(e,2),Ja):r},aa.stubArray=Iu,aa.stubFalse=Cu,aa.stubObject=function(){return{}},aa.stubString=function(){return""},aa.stubTrue=function(){return!0},aa.multiply=Eu,aa.nth=function(t,e){return t&&t.length?ar(t,Oo(e)):r},aa.noConflict=function(){return Te._===this&&(Te._=se),this},aa.noop=vu,aa.now=Ms,aa.pad=function(t,e,n){t=No(t);var a=(e=Oo(e))?vn(t):0;if(!e||a>=e)return t;var r=(e-a)/2;return ei(Nn(r),n)+t+ei(kn(r),n)},aa.padEnd=function(t,e,n){t=No(t);var a=(e=Oo(e))?vn(t):0;return e&&a<e?t+ei(e-a,n):t},aa.padStart=function(t,e,n){t=No(t);var a=(e=Oo(e))?vn(t):0;return e&&a<e?ei(e-a,n)+t:t},aa.parseInt=function(t,e,n){return n||null==e?e=0:e&&(e=+e),jn(No(t).replace(It,""),e||0)},aa.random=function(t,e,n){if(n&&"boolean"!=typeof n&&Ri(t,e,n)&&(e=n=r),n===r&&("boolean"==typeof e?(n=e,e=r):"boolean"==typeof t&&(n=t,t=r)),t===r&&e===r?(t=0,e=1):(t=So(t),e===r?(e=t,t=0):e=So(e)),t>e){var a=t;t=e,e=a}if(n||t%1||e%1){var i=Fn();return Mn(t+i*(e-t+ye("1e-"+((i+"").length-1))),e)}return ur(t,e)},aa.reduce=function(t,e,n){var a=to(t)?Ve:en,r=arguments.length<3;return a(t,vi(e,4),n,r,Ca)},aa.reduceRight=function(t,e,n){var a=to(t)?He:en,r=arguments.length<3;return a(t,vi(e,4),n,r,ka)},aa.repeat=function(t,e,n){return e=(n?Ri(t,e,n):e===r)?1:Oo(e),cr(No(t),e)},aa.replace=function(){var t=arguments,e=No(t[0]);return t.length<3?e:e.replace(t[1],t[2])},aa.result=function(t,e,n){var a=-1,i=(e=Rr(e,t)).length;for(i||(i=1,t=r);++a<i;){var s=null==t?r:t[Wi(e[a])];s===r&&(a=i,s=n),t=oo(s)?s.call(t):s}return t},aa.round=Lu,aa.runInContext=t,aa.sample=function(t){return(to(t)?ha:function(t){return ha(Xo(t))})(t)},aa.size=function(t){if(null==t)return 0;if(no(t))return yo(t)?vn(t):t.length;var e=Oi(t);return e==Y||e==K?t.size:Xa(t).length},aa.snakeCase=ru,aa.some=function(t,e,n){var a=to(t)?Be:gr;return n&&Ri(t,e,n)&&(e=r),a(t,vi(e,3))},aa.sortedIndex=function(t,e){return br(t,e)},aa.sortedIndexBy=function(t,e,n){return mr(t,e,vi(n,2))},aa.sortedIndexOf=function(t,e){var n=null==t?0:t.length;if(n){var a=br(t,e);if(a<n&&Zs(t[a],e))return a}return-1},aa.sortedLastIndex=function(t,e){return br(t,e,!0)},aa.sortedLastIndexBy=function(t,e,n){return mr(t,e,vi(n,2),!0)},aa.sortedLastIndexOf=function(t,e){if(null!=t&&t.length){var n=br(t,e,!0)-1;if(Zs(t[n],e))return n}return-1},aa.startCase=iu,aa.startsWith=function(t,e,n){return t=No(t),n=null==n?0:Ta(Oo(n),0,t.length),e=_r(e),t.slice(n,n+e.length)==e},aa.subtract=Pu,aa.sum=function(t){return t&&t.length?nn(t,hu):0},aa.sumBy=function(t,e){return t&&t.length?nn(t,vi(e,2)):0},aa.template=function(t,e,n){var a=aa.templateSettings;n&&Ri(t,e,n)&&(e=r),t=No(t),e=Do({},e,a,ci);var i,s,o=Do({},e.imports,a.imports,ci),u=Yo(o),c=sn(o,u),l=0,d=e.interpolate||Gt,f="__p += '",p=Kt((e.escape||Gt).source+"|"+d.source+"|"+(d===vt?Et:Gt).source+"|"+(e.evaluate||Gt).source+"|$","g"),h="//# sourceURL="+(ee.call(e,"sourceURL")?(e.sourceURL+"").replace(/[\r\n]/g," "):"lodash.templateSources["+ ++he+"]")+"\n";t.replace(p,function(e,n,a,r,o,u){return a||(a=r),f+=t.slice(l,u).replace(Yt,fn),n&&(i=!0,f+="' +\n__e("+n+") +\n'"),o&&(s=!0,f+="';\n"+o+";\n__p += '"),a&&(f+="' +\n((__t = ("+a+")) == null ? '' : __t) +\n'"),l=u+e.length,e}),f+="';\n";var g=ee.call(e,"variable")&&e.variable;g||(f="with (obj) {\n"+f+"\n}\n"),f=(s?f.replace(lt,""):f).replace(dt,"$1").replace(ft,"$1;"),f="function("+(g||"obj")+") {\n"+(g?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(i?", __e = _.escape":"")+(s?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+f+"return __p\n}";var b=cu(function(){return Bt(u,h+"return "+f).apply(r,c)});if(b.source=f,so(b))throw b;return b},aa.times=function(t,e){if((t=Oo(t))<1||t>I)return[];var n=N,a=Mn(t,N);e=vi(e),t-=N;for(var r=an(a,e);++n<t;)e(n);return r},aa.toFinite=So,aa.toInteger=Oo,aa.toLength=Io,aa.toLower=function(t){return No(t).toLowerCase()},aa.toNumber=Co,aa.toSafeInteger=function(t){return t?Ta(Oo(t),-I,I):0===t?t:0},aa.toString=No,aa.toUpper=function(t){return No(t).toUpperCase()},aa.trim=function(t,e,n){if((t=No(t))&&(n||e===r))return t.replace(Ot,"");if(!t||!(e=_r(e)))return t;var a=_n(t),i=_n(e);return Dr(a,un(a,i),cn(a,i)+1).join("")},aa.trimEnd=function(t,e,n){if((t=No(t))&&(n||e===r))return t.replace(Ct,"");if(!t||!(e=_r(e)))return t;var a=_n(t);return Dr(a,0,cn(a,_n(e))+1).join("")},aa.trimStart=function(t,e,n){if((t=No(t))&&(n||e===r))return t.replace(It,"");if(!t||!(e=_r(e)))return t;var a=_n(t);return Dr(a,un(a,_n(e))).join("")},aa.truncate=function(t,e){var n=30,a="...";if(lo(e)){var i="separator"in e?e.separator:i;n="length"in e?Oo(e.length):n,a="omission"in e?_r(e.omission):a}var s=(t=No(t)).length;if(pn(t)){var o=_n(t);s=o.length}if(n>=s)return t;var u=n-vn(a);if(u<1)return a;var c=o?Dr(o,0,u).join(""):t.slice(0,u);if(i===r)return c+a;if(o&&(u+=c.length-u),bo(i)){if(t.slice(u).search(i)){var l,d=c;for(i.global||(i=Kt(i.source,No(Lt.exec(i))+"g")),i.lastIndex=0;l=i.exec(d);)var f=l.index;c=c.slice(0,f===r?u:f)}}else if(t.indexOf(_r(i),u)!=u){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+a},aa.unescape=function(t){return(t=No(t))&&gt.test(t)?t.replace(pt,xn):t},aa.uniqueId=function(t){var e=++ne;return No(t)+e},aa.upperCase=su,aa.upperFirst=ou,aa.each=ks,aa.eachRight=Ns,aa.first=ns,yu(aa,(ku={},Pa(aa,function(t,e){ee.call(aa.prototype,e)||(ku[e]=t)}),ku),{chain:!1}),aa.VERSION="4.17.14",Me(["bind","bindKey","curry","curryRight","partial","partialRight"],function(t){aa[t].placeholder=aa}),Me(["drop","take"],function(t,e){oa.prototype[t]=function(n){n=n===r?1:Pn(Oo(n),0);var a=this.__filtered__&&!e?new oa(this):this.clone();return a.__filtered__?a.__takeCount__=Mn(n,a.__takeCount__):a.__views__.push({size:Mn(n,N),type:t+(a.__dir__<0?"Right":"")}),a},oa.prototype[t+"Right"]=function(e){return this.reverse()[t](e).reverse()}}),Me(["filter","map","takeWhile"],function(t,e){var n=e+1,a=1==n||3==n;oa.prototype[t]=function(t){var e=this.clone();return e.__iteratees__.push({iteratee:vi(t,3),type:n}),e.__filtered__=e.__filtered__||a,e}}),Me(["head","last"],function(t,e){var n="take"+(e?"Right":"");oa.prototype[t]=function(){return this[n](1).value()[0]}}),Me(["initial","tail"],function(t,e){var n="drop"+(e?"":"Right");oa.prototype[t]=function(){return this.__filtered__?new oa(this):this[n](1)}}),oa.prototype.compact=function(){return this.filter(hu)},oa.prototype.find=function(t){return this.filter(t).head()},oa.prototype.findLast=function(t){return this.reverse().find(t)},oa.prototype.invokeMap=lr(function(t,e){return"function"==typeof t?new oa(this):this.map(function(n){return Ba(n,t,e)})}),oa.prototype.reject=function(t){return this.filter(Bs(vi(t)))},oa.prototype.slice=function(t,e){t=Oo(t);var n=this;return n.__filtered__&&(t>0||e<0)?new oa(n):(t<0?n=n.takeRight(-t):t&&(n=n.drop(t)),e!==r&&(n=(e=Oo(e))<0?n.dropRight(-e):n.take(e-t)),n)},oa.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},oa.prototype.toArray=function(){return this.take(N)},Pa(oa.prototype,function(t,e){var n=/^(?:filter|find|map|reject)|While$/.test(e),a=/^(?:head|last)$/.test(e),i=aa[a?"take"+("last"==e?"Right":""):e],s=a||/^find/.test(e);i&&(aa.prototype[e]=function(){var e=this.__wrapped__,o=a?[1]:arguments,u=e instanceof oa,c=o[0],l=u||to(e),d=function(t){var e=i.apply(aa,Ye([t],o));return a&&f?e[0]:e};l&&n&&"function"==typeof c&&1!=c.length&&(u=l=!1);var f=this.__chain__,p=s&&!f,h=u&&!this.__actions__.length;if(!s&&l){e=h?e:new oa(this);var g=t.apply(e,o);return g.__actions__.push({func:ws,args:[d],thisArg:r}),new sa(g,f)}return p&&h?t.apply(this,o):(g=this.thru(d),p?a?g.value()[0]:g.value():g)})}),Me(["pop","push","shift","sort","splice","unshift"],function(t){var e=Xt[t],n=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",a=/^(?:pop|shift)$/.test(t);aa.prototype[t]=function(){var t=arguments;if(a&&!this.__chain__){var r=this.value();return e.apply(to(r)?r:[],t)}return this[n](function(n){return e.apply(to(n)?n:[],t)})}}),Pa(oa.prototype,function(t,e){var n=aa[e];if(n){var a=n.name+"";ee.call(Kn,a)||(Kn[a]=[]),Kn[a].push({name:e,func:n})}}),Kn[Xr(r,h).name]=[{name:"wrapper",func:r}],oa.prototype.clone=function(){var t=new oa(this.__wrapped__);return t.__actions__=zr(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=zr(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=zr(this.__views__),t},oa.prototype.reverse=function(){if(this.__filtered__){var t=new oa(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},oa.prototype.value=function(){var t=this.__wrapped__.value(),e=this.__dir__,n=to(t),a=e<0,r=n?t.length:0,i=function(t,e,n){for(var a=-1,r=n.length;++a<r;){var i=n[a],s=i.size;switch(i.type){case"drop":t+=s;break;case"dropRight":e-=s;break;case"take":e=Mn(e,t+s);break;case"takeRight":t=Pn(t,e-s)}}return{start:t,end:e}}(0,r,this.__views__),s=i.start,o=i.end,u=o-s,c=a?o:s-1,l=this.__iteratees__,d=l.length,f=0,p=Mn(u,this.__takeCount__);if(!n||!a&&r==u&&p==u)return Or(t,this.__actions__);var h=[];t:for(;u--&&f<p;){for(var g=-1,b=t[c+=e];++g<d;){var m=l[g],y=m.type,v=(0,m.iteratee)(b);if(2==y)b=v;else if(!v){if(1==y)continue t;break t}}h[f++]=b}return h},aa.prototype.at=Ss,aa.prototype.chain=function(){return Ts(this)},aa.prototype.commit=function(){return new sa(this.value(),this.__chain__)},aa.prototype.next=function(){this.__values__===r&&(this.__values__=wo(this.value()));var t=this.__index__>=this.__values__.length;return{done:t,value:t?r:this.__values__[this.__index__++]}},aa.prototype.plant=function(t){for(var e,n=this;n instanceof ia;){var a=$i(n);a.__index__=0,a.__values__=r,e?i.__wrapped__=a:e=a;var i=a;n=n.__wrapped__}return i.__wrapped__=t,e},aa.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof oa){var e=t;return this.__actions__.length&&(e=new oa(this)),(e=e.reverse()).__actions__.push({func:ws,args:[ls],thisArg:r}),new sa(e,this.__chain__)}return this.thru(ls)},aa.prototype.toJSON=aa.prototype.valueOf=aa.prototype.value=function(){return Or(this.__wrapped__,this.__actions__)},aa.prototype.first=aa.prototype.head,tn&&(aa.prototype[tn]=function(){return this}),aa}();Te._=Tn,(a=(function(){return Tn}).call(e,n,e,t))===r||(t.exports=a)}).call(this)}).call(this,n("YuTi")(t))},Lwhh:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DataTableColumnHeaderDirective=function(){return a([r.Directive({selector:"[ngx-datatable-header-template]"})],function(t){this.template=t})}()},"M/6F":function(t,e,n){"use strict";var a=n("CcnG"),r=n("IZUe"),i=n("MdoF"),s=n("lTVp"),o=n("Ip0R");n("NDi4"),n.d(e,"a",function(){return u}),n.d(e,"b",function(){return l});var u=a["\u0275crt"]({encapsulation:0,styles:[[".error-panel-alert-icon[_ngcontent-%COMP%]{vertical-align:top;padding-right:15px}.error-panel-alert-title[_ngcontent-%COMP%]{font-weight:700}"]],data:{}});function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,2,"button",[["autofocus",""],["class","btn btn-sm btn-default tc_backButton"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.backAction.emit()&&a),a},null,null)),a["\u0275did"](2,4210688,null,0,r.a,[a.ElementRef],null,null),(t()(),a["\u0275ted"](-1,null,["Back"]))],null,null)}function l(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,11,"alert",[["type","danger"]],null,null,null,i.c,i.b)),a["\u0275did"](1,114688,null,0,s.a,[s.b,a.ChangeDetectorRef],{type:[0,"type"]},null),(t()(),a["\u0275eld"](2,0,null,0,9,"table",[],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275eld"](4,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"td",[["class","error-panel-alert-icon"],["rowspan","2"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-3x fa-times-circle alert-danger"]],null,null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,1,"td",[["class","error-panel-alert-title"]],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,[" "," "])),(t()(),a["\u0275eld"](9,0,null,null,2,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](10,0,null,null,1,"td",[["class","error-panel-alert-text"]],null,null,null,null,null)),a["\u0275ncd"](null,0),(t()(),a["\u0275and"](16777216,null,null,1,null,c)),a["\u0275did"](13,16384,null,0,o.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"danger"),t(e,13,0,n.backAction.observers.length>0)},function(t,e){t(e,8,0,e.component.title)})}},M9eX:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("DtyJ"),o=(n("czA5"),n("ahDk"));e.ResizeableDirective=function(){function t(t,e){this.renderer=e,this.resizeEnabled=!0,this.resize=new i.EventEmitter,this.resizing=!1,this.element=t.nativeElement}return t.prototype.ngAfterViewInit=function(){var t=this.renderer,e=t.createElement("span");t.addClass(e,this.resizeEnabled?"resize-handle":"resize-handle--not-resizable"),t.appendChild(this.element,e)},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype.onMouseup=function(){this.resizing=!1,this.subscription&&!this.subscription.closed&&(this._destroySubscription(),this.resize.emit(this.element.clientWidth))},t.prototype.onMousedown=function(t){var e=this,n=t.target.classList.contains("resize-handle"),a=this.element.clientWidth,r=t.screenX;if(n){t.stopPropagation(),this.resizing=!0;var i=s.fromEvent(document,"mouseup");this.subscription=i.subscribe(function(t){return e.onMouseup()});var u=s.fromEvent(document,"mousemove").pipe(o.takeUntil(i)).subscribe(function(t){return e.move(t,a,r)});this.subscription.add(u)}},t.prototype.move=function(t,e,n){var a=e+(t.screenX-n);(!this.minWidth||a>=this.minWidth)&&(!this.maxWidth||a<=this.maxWidth)&&(this.element.style.width=a+"px")},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Boolean)],t.prototype,"resizeEnabled",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"minWidth",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"maxWidth",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"resize",void 0),a([i.HostListener("mousedown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMousedown",null),a([i.Directive({selector:"[resizeable]",host:{"[class.resizeable]":"resizeEnabled"}})],t)}()},MGBS:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.destination.next(e)},e.prototype.notifyError=function(t,e){this.destination.error(t)},e.prototype.notifyComplete=function(t){this.destination.complete()},e}(n("FFOo").a)},MaEZ:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="cs">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Zobraz./skr\xfdt navigaci</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>P\u0159ehled</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Klastr</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Stroje</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitory</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Nastaven\xed</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH mapa</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Moduly spr\xe1vy</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Z\xe1znamy ud\xe1lost\xed</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>V\xfdstrahy</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Fondy</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Blok</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Obrazy</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Zrcadlen\xed</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Souborov\xe9 syst\xe9my</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Objektov\xe1 br\xe1na</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Procesy slu\u017eeb</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>U\u017eivatel\xe9</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>N\xe1doby</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Z\xedsk\xe1vaj\xed se data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pro\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. \u010cekejte\u2026\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Zobrazuj\xed se data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>z mezipam\u011bti\n pro \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Neda\u0159\xed se na\u010d\xedst dat \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pro\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Zkontrolujte zdrav\xed klastru.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Zp\u011bt</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Vyberte jazyk</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Na\u010d\xedt\xe1n\xed \xfadaj\u016f panelu\u2026</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Nahl\xe9dn\u011bte do\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>, kde naleznete jak\n nastavit a zapnout funkci monitorov\xe1n\xed.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Grafana p\u0159ehled neexistuje. Pod\xedvejte se do\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> jak\n p\u0159idat p\u0159ehledy do Grafany.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Grafana Time Picker</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Resetovat nastaven\xed</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Data se nepoda\u0159ilo na\u010d\xedst</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>vybr\xe1no</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>nalezeno</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>celkem</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Upravit</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>N\xe1zev</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Popis</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Podrobn\u011bj\u0161\xed popis</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>V\xfdchoz\xed</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>V\xfdchoz\xed pro proces slu\u017eby</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Slu\u017eby</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Hodnoty</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>Zadan\xe1 hodnota je p\u0159\xedli\u0161 vysok\xe1! Nem\u016f\u017ee b\xfdt vy\u0161\u0161\xed ne\u017e \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>Zadan\xe1 hodnota je p\u0159\xedli\u0161 n\xedzk\xe1! Nem\u016f\u017ee b\xfdt ni\u017e\u0161\xed ne\u017e \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Ulo\u017eit</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>prohl\xed\u017ee\u010d CRUSH mapy</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Seznam stroj\u016f</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Celkov\xe1 v\xfdkonnost</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Nenalezeny \u017e\xe1dn\xe9 polo\u017eky</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Z\xe1znamy ud\xe1lost\xed v klastra</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Auditn\xed z\xe1znamy ud\xe1lost\xed</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Na\u010d\xedt\xe1n\xed nastaven\xed\u2026</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>Toto nastaven\xed se nepoda\u0159ilo na\u010d\xedst.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Upravit modul spr\xe1vy</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>Zadan\xe1 hodnota nen\xed platn\xe9 UUID, nap\u0159.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>Je t\u0159eba, aby zadan\xe1 hodnota byla platnou IP adresou.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Tuto kolonku je t\u0159eba vyplnit.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>Je t\u0159eba, aby zadan\xe1 hodnota byla \u010d\xedslo.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>Je t\u0159eba, aby zadan\xe1 hodnota byla \u010d\xedslo nebo des\xedtkov\xe9.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Aktualizovat</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Stav</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>Identif. kastru</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>mapa monitor\u016f zm\u011bn\u011bna</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap epocha</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>kv\xf3rum spojen\xed</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>kv\xf3rum monitor</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>vy\u017eadov\xe1no spojen\xed</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>vy\u017eadov\xe1no monitor\u016f</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>V kv\xf3ru</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Nen\xed v kv\xf3ru</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Storno</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Opravdu chcete ozna\u010den\xe9 \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Ano, opravdu to chci.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>P\u0159\xedznaky OSD pro cel\xfd klastr</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Odeslat</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Pokro\u010dil\xe9\u2026</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Priorita obnoven\xed OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Priorita</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>P\u0159izp\u016fsobit hodnoty priority</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Tuto kolonku je t\u0159eba vyplnit!</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>Zadan\xe1 hodnota je p\u0159\xedli\u0161 vysok\xe1, je t\u0159eba, aby nebyla vy\u0161\u0161\xed ne\u017e \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>Zadan\xe1 hodnota je p\u0159\xedli\u0161 n\xedzk\xe1! Je t\u0159eba, aby byla ni\u017e\u0161\xed ne\u017e \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Znovu vyv\xe1\u017eit OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>Je t\u0159eba, aby hodnota byla mezi 0 a 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Znovu vyv\xe1\u017eit</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>kontrola\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, vybrat, 1 {Deep } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Chyst\xe1te se pou\u017e\xedt kontrolu na\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, vybrat, 1 {deep } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Seznam OSD</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Pokud budete pokra\u010dovat, \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> bude ozna\u010deno\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>OSD nen\xed mo\u017en\xe9 bezpe\u010dn\u011b zlikvidovat!</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Pokud budete pokra\u010dovat,\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> bude \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Podrobnosti</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Hodnota</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Zav\u0159\xedt</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Smazat</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Zdrav\xed</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statistiky</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Ohledn\u011b nastaven\xed a zapnut\xed funkce spr\xe1vy NFS Ganesha nahl\xe9dn\u011bte do \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Klienti</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>P\u0159istupovat m\u016f\u017ee libovoln\xfd klient</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Adresy</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Vy\u017eadovan\xe1 kolonka</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Je t\u0159eba, aby obsahovalo jednu nebo v\xedce \u010d\xe1rkou odd\u011blovan\xfdch hodnot</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Nap\u0159\xedklad:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Typ p\u0159\xedstupu</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>P\u0159idat klienty</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Na\u010d\xedt\xe1n\xed\u2026</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- \u017d\xe1dn\xfd klastr k dispozici --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Vyberte klastr --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>P\u0159idat proces slu\u017eby</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Podp\u016frn\xe1 vrstva \xfalo\u017ei\u0161t\u011b</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- \u017d\xe1dn\xe9 fondy k dispozici --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Vyberte podp\u016frnou vrstvu \xfalo\u017ei\u0161t\u011b --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>U\u017eivatel objektov\xe9 br\xe1ny</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- \u017d\xe1dn\xed u\u017eivatel\xe9 k dispozici --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Vyberte u\u017eivatele br\xe1ny objekt\u016f --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>Identif. u\u017eivatele CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- \u017d\xe1dn\xed klienti k dispozici --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Vyberte cephx klienta --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>N\xe1zev CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Security Label</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Enable security label</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>Popis um\xedst\u011bn\xed CephFS</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>Je t\u0159eba, aby popis um\xedst\u011bn\xed za\u010d\xednal na \u201e/\u201c, za kter\xfdm n\xe1sleduje slovo</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Bude vytvo\u0159ena nov\xe1 slo\u017eka</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Popis um\xedst\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>Popis um\xedst\u011bn\xed m\u016f\u017ee b\xfdt pouze jedin\xe9 \u201e/\u201c nebo slovo</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Bude vytvo\u0159ena nov\xe1 n\xe1doba</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS protokol</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS \u0161t\xedtek</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Alternativn\xed p\u0159\xedstup pro \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> p\u0159ipojen\xed (nem\u016f\u017ee za\u010d\xednat na /).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>By using different Tag options, the same Path may be exported multiple times.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>By using different Pseudo options, the same Path may be exported multiple times.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- \u017d\xe1dn\xfd typ p\u0159\xedstupu k dispozici --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Vyberte typ p\u0159\xedstupu --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- No squash available --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>--Select what kind of user id squashing is performed --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Transportn\xed protokol</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>V\xedtejte v Ceph!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Je t\u0159eba vyplnit u\u017eivatelsk\xe9 jm\xe9no</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Je t\u0159eba vyplnit heslo</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>P\u0159ihl\xe1sit</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Je n\xe1m l\xedto, u\u017eivatel v Ceph neexistuje.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Vr\xe1tit se na \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>P\u0159ihla\u0161ovac\xed str\xe1nku\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Budete odhl\xe1\u0161eni od poskytovatele identity kdy\u017e se pokus\xedte znovu p\u0159ihl\xe1sit.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Odep\u0159eno</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Omlouv\xe1me se, ale nem\xe1te opr\xe1vn\u011bn\xed zobrazit to, po \u010dem se poohl\xed\u017e\xedte.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Omlouv\xe1me se, nepoda\u0159ilo se naj\xedt to, po \u010dem se poohl\xed\u017e\xedte</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Odebrat v\u0161e</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Ned\xe1vn\xe1 ozn\xe1men\xed</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Nejsou zde \u017e\xe1dn\xe9 \xfalohy na pozad\xed.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>\xdalohy na pozad\xed</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>N\xe1pov\u011bda</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Dokumentace</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>Aplika\u010dn\xed program. rozhran\xed</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>O aplikaci</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Nastaven\xed p\u0159ehledu</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Spr\xe1va u\u017eivatel\u016f</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>P\u0159ihl\xe1\u0161en\xfd u\u017eivatel</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>P\u0159ihl\xe1\u0161eni jako\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Odhl\xe1sit</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>N\xe1zev\u2026</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Zvolen\xfd n\xe1zev u\u017e je pou\u017e\xedv\xe1n.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Popis\u2026</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Opr\xe1vn\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Role</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>U\u017eivatelsk\xe9 jm\xe9no</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Heslo</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Potvrzen\xed zad\xe1n\xed hesla</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Zad\xe1n\xed hesla se neshoduj\xed.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Cel\xe9 jm\xe9no</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>E-mail</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>Neplatn\xfd e-mail.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Chyst\xe1te se odebrat opr\xe1vn\u011bn\xed \u201eu\u017eivatel \u010d\xedst/aktualizovat\u201c sv\xe9mu vlastn\xedmu \xfa\u010dtu.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Pokud budete pokra\u010dovat, nebudete nad\xe1le schopn\xed p\u0159id\xe1vat nebo nebo odeb\xedrat role \u017e\xe1dn\xe9mu z u\u017eivatel\u016f.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Opravdu chcete pokra\u010dovat?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>V\xfdkonnostn\xed \u010d\xedta\u010de nejsou k dispozici</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Atributy (OSD mapa)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Metadata nejsou k dispozici</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadata</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>V\xfdkonnostn\xed \u010d\xedta\u010d</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histogram nen\xed k dispozici: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Z\xe1pisy</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>\u010cten\xed</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histogram</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Podrobnosti o v\xfdkonnosti</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>St\xe1vaj\xedc\xed hodnoty</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Typ</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Min</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Max</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>P\u0159\xedznaky</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Zdroj</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>\xdarove\u0148</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Je mo\u017en\xe9 aktualizovat za provozu (upraviteln\xe9)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>\u0160t\xedtky</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Vy\u010d\xedslit hodnoty</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Viz tak\xe9</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Stav klastru</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Procesy slu\u017eby spr\xe1vy</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Objektov\xe9 br\xe1ny</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Metadata servery</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI br\xe1ny</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>vst/v\xfdst. klienta</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Propustnost klienta</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>\u010cten\xed/z\xe1pis klienta</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Propustnost zotaven\xed</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Kontrola</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>V\xfdkonnost</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Hol\xe1 kapacita</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objekty</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>Skupin um\xedst\u011bn\xed na OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Stav skupiny um\xedst\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Kapacita</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>Dal\u0161\xed podrobnosti \n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> naleznete v \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>z\xe1znamech ud\xe1lost\xed\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Hodnocen\xed</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Klienti: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>P\u0159esunout obraz do ko\u0161e</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Pro p\u0159esunut\xed \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> do ko\u0161e,\n klikn\u011bte na \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>P\u0159esunout obraz\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Voliteln\u011b je mo\u017en\xe9 zvolit datum skon\u010den\xed platnosti.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>Platnost ochrany skon\u010d\xed v</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>NECHR\xc1N\u011aNO</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Chybn\xfd form\xe1t data. Pou\u017eijte \u201eRRRR-MM-DD HH:mm:ss\u201c.</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>Platnost ochrany u\u017e skon\u010dila. Zvolte budouc\xed datum nebo nevypl\u0148ujte.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>P\u0159esunout obraz</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>P\u0159ehled</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>C\xedle</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Ov\u011b\u0159ov\xe1n\xed pro objevov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>U\u017eivatele</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>U\u017eivatel pro vz\xe1jemn\xe9 ov\u011b\u0159en\xed</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Heslo pro vz\xe1jemn\xe9 ov\u011b\u0159en\xed</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Pod\xedvejte se do \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n jak nastavit a zapnout funkci spr\xe1vy iSCSI c\xedl\u016f.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informace k dispozici:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>iSCSI c\xedl nen\xed k dispozici</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>K dispozici pouze pro RBD obrazy se zapnut\xfdm \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Fond</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Datov\xfd fond</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Vytvo\u0159eno</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Velikost</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Velikost objektu</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Funkce</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Poskytov\xe1no</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/A</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Celkem poskytov\xe1no</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Prou\u017ekovac\xed jednotka</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Po\u010det prou\u017ekov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Nad\u0159azen\xe9</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>P\u0159edpona n\xe1zvu bloku</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Po\u0159ad\xed</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Zachycen\xe9 stavy</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Obraz</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Toto nastaven\xed p\u0159ebije glob\xe1ln\xed hodnotu</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Glob\xe1ln\xed</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Toto je glob\xe1ln\xed hodnota. Pro tento obraz nebyla u t\xe9to volby nastavena \u017e\xe1dn\xe1 hodnota.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\u201e/\u201c a \u201e@\u201c nejsou dovoleny.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- \u017d\xe1dn\xe9 rbd fondy k dispozici --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Vybrat fond --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Pou\u017e\xedt vyhrazen\xfd datov\xfd fond</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Datov\xfd fond</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Vyhrazen\xfd fond kter\xfd uchov\xe1v\xe1 objektov\xe1 data RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>nap\u0159. 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Je t\u0159eba zv\u011bt\u0161it.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Pokro\u010dil\xe9</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Prou\u017ekov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Jednotka prou\u017eku</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Vybrat jednotku prou\u017eku --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Tuto kolonku je t\u0159eba vyplnit, proto\u017ee je definov\xe1n po\u010det prou\u017ek\u016f!</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>Jednotka prou\u017eku je vy\u0161\u0161\xed ne\u017e velikost objektu.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Po\u010det prou\u017ek\u016f</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Tuto kolonku je t\u0159eba vyplnit, proto\u017ee je definov\xe1na jednotka prou\u017eku!</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Je t\u0159eba, aby po\u010det prou\u017ek\u016f byl v\u011bt\u0161\xed ne\u017e nula.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD zachycen\xfd stav\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, vybrat, skute\u010dn\xe9 {Rename} ostatn\xed {Create} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> zachycen\xfd stav\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>CHR\xc1N\u011aNO</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>NECHR\xc1N\u011aNO</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Chyst\xe1te se vr\xe1tit zp\u011bt</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Vysypat ko\u0161</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Pro vy\u010di\u0161t\u011bn\xed, vyberte jeden nebo v\u0161echny obrazy a klikn\u011bte na</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Fond:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>N\xe1zev fondu\u2026</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>V\u0161e</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Obnovit obraz</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Pro obnoven\xed</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>zadejte nov\xfd n\xe1zev pro obraz a klikn\u011bte na</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nov\xfd n\xe1zev</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Platnost skon\u010dila v</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Chr\xe1n\u011bno do</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Tento obraz je chr\xe1n\u011bn do\n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Ko\u0161</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologie iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>M\u011bnit tyto parametry z jejich v\xfdchoz\xedch hodnot obvykle nen\xed pot\u0159eba.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Nastaven\xed</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Potvrdit</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Pokro\u010dil\xe1 nastaven\xed</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>IQN c\xedle</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN nem\xe1 spr\xe1vn\xfd form\xe1t.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN m\xe1 n\xe1sleduj\xedc\xed formu z\xe1pisu \u201eiqn.$rok-$m\u011bs\xedc.$adresaObr\xe1cen\u011b:$ur\u010den\xfdN\xe1zev\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Nap\u0159\xedklad: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Dal\u0161\xed informace</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Tento c\xedl m\xe1 zm\u011bn\u011bn\xe1 pokro\u010dil\xe1 nastaven\xed.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Port\xe1ly</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Je t\u0159eba alespo\u0148 \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> bran.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>P\u0159idat port\xe1l</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Tento obraz m\xe1 zm\u011bn\u011bn\xe1 nastaven\xed.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>P\u0159idat obraz</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL ov\u011b\u0159ov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Inici\xe1tory</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Inici\xe1tor</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>IQN klienta</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>Je t\u0159eba, aby se IQN inici\xe1toru neopakovalo.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Je t\u0159eba, aby u\u017eivatelsk\xe1 jm\xe9na m\u011bla d\xe9lku 8 a\u017e 64 znak\u016f a\n mohou obsahovat pouze p\xedsmena a znaky \u201e.\u201c, \u201e@\u201c, \u201e-\u201c, \u201e_\u201c nebo \u201e:\u201c.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>Inici\xe1tor spad\xe1 do skupiny. Obrazy budou nastaveny ve skupin\u011b.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Nep\u0159id\xe1ny \u017e\xe1dn\xe9 polo\u017eky.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>P\u0159idat inici\xe1tor</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Skupiny</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Skupina</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>P\u0159idat skupinu</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Nastaven\xed RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Odebrat hodnotu m\xedstn\xedmu nastaven\xed. Nam\xedsto n\xed bude pou\u017eita hodnota nad\u0159azen\xe9ho nastaven\xed.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>Minim\xe1ln\xed hodnota je 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>probl\xe9my</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Synchronizuje se</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>P\u0159ipraveno</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Upravit re\u017eim zrcadlen\xed fondu</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Pro \xfapravu re\u017eimu zrcadlen\xed pro fond\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, vyberte ze seznamu nov\xfd re\u017eim a klikn\u011bte na\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aktualizovat\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Re\u017eim</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>P\u0159ed vypnut\xedm zrcadlen\xed je t\u0159eba odebrat klastry-prot\u011bj\u0161ky.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n prot\u011bj\u0161ek zrcadlen\xed fondu\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> atributy\n prot\u011bj\u0161ku zrcadlen\xed pro fond \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> a klikn\u011bte na \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Odeslat\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>N\xe1zev klastru</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>N\xe1zev klastru nen\xed platn\xfd</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX identif.</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX identif. \u2026</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>CephX identif. nen\xed platn\xfd.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Adresy monitor\u016f</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>\u010c\xe1rkou odd\u011blovan\xe9 adresy\u2026</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>Adresa monitoru nen\xed platn\xe1.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Kl\xed\u010d v base64 k\xf3dov\xe1n\xed\u2026</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>Je t\u0159eba, aby CephX kl\xed\u010d byl v k\xf3dov\xe1n\xed base64.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Seznam fond\u016f</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>N\xe1zev m\u016f\u017ee b\xfdt tvo\u0159en pouze p\xedsmeny a \u010d\xedslicemi, d\xe1le je\u0161t\u011b spojovn\xedky a podtr\u017e\xedtky.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Zvolen\xfd n\xe1zev pro profil mazac\xedho k\xf3du je u\u017e pou\u017e\xedv\xe1n.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Z\xe1suvn\xfd modul</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Shluky dat (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Je t\u0159eba, aby bylo 2 a v\xedce.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Shluky k\xf3dov\xe1n\xed (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Je t\u0159eba, aby bylo 1 a v\xedce.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Odhadov\xe1n\xed odolnosti (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Um\xedst\u011bn\xed (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Dom\xe9na selh\xe1n\xed crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Lokalita crush</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>\u017d\xe1dn\xe9</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Technika</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Velikostpaketu</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Ko\u0159en crush</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>T\u0159\xedda crush za\u0159\xedzen\xed</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>libovoln\xe9</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Slo\u017eka</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Zvolen\xfd n\xe1zev pro Ceph fond je u\u017e pou\u017e\xedv\xe1n.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Typ fondul</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Vybrat typ fondu --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Skupiny um\xedst\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Je t\u0159eba alespo\u0148 jedn\xe9 skupiny um\xedst\u011bn\xed!</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>V\xe1\u0161 klastr nem\u016f\u017ee obslou\u017eit tolik skupin um\xedst\u011bn\xed. P\u0159epo\u010d\xedtejte pot\u0159ebn\xe9 mno\u017estv\xed skupin um\xedst\u011bn\xed.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>N\xe1pov\u011bda k v\xfdpo\u010dtu</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Sada pravidel crush</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Vybrat crush pravidlo --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Crush pravidlo</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Crush kroky</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Pravidlo nem\u016f\u017ee b\xfdt uplatn\u011bno na st\xe1vaj\xedc\xed klastr proto\u017ee m\xe1\n p\u0159\xedli\u0161 m\xe1lo OSD aby splnil minimum OSD vy\u017eadovan\xfdch t\xedmto pravidlem.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Replikovan\xe1 velikost</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Nejm\xe9n\u011b: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Nejv\xedce: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>Zadan\xe1 velikost je mimo rozsah. Platn\xe9 hodnoty jsou od \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> do \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Profil mazac\xedho k\xf3du</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- \u017d\xe1dn\xfd profil mazac\xedho k\xf3du --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Vyberte profil mazac\xedho k\xf3du --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC p\u0159ebit\xed</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Aplikace</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Komprese</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algoritmus</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- \u017d\xe1dn\xfd algoritmus komprese maz\xe1n\xed --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Minim\xe1ln\xed velikost blobu</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>nap\u0159. 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>Hodnota by m\u011bla b\xfdt vy\u0161\u0161\xed ne\u017e nula</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Nejvy\u0161\u0161\xed velikost blobu</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>nap\u0159. 512 KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>Hodnota by m\u011bla b\xfdt vy\u0161\u0161\xed ne\u017e nejni\u017e\u0161\xed velikost blobu</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Pom\u011br</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Kompresn\xed pom\u011br</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>Hodnota by m\u011bla b\xfdt z rozmez\xed 0.0 a\u017e 1.0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Nen\xed mo\u017en\xe9 vytvo\u0159it RBD fond, kter\xfd m\xe1 v n\xe1zvu \u201e/\u201c.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Zm\u011b\u0148te n\xe1zev nebo ze seznamu pou\u017eit\xed odeberte \u201erbd\u201c</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Podrobnosti o stupn\xedch mezipam\u011bti</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Pod\xedvejte se do \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n jak nastavit a zapnout funkci spr\xe1vy br\xe1ny objekt\u016f.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Seznam proces\u016f slu\u017eeb</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>V\xfdkonnostn\xed \u010d\xedta\u010de</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Na\u010d\xedt\xe1n\xed dat n\xe1doby\u2026</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Data n\xe1doby se nepoda\u0159ilo na\u010d\xedst.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>Identif.</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>Hodnota nen\xed platn\xe1.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Vlastn\xedk</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Vybrat u\u017eivatele --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>Identif.</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Typ rejst\u0159\xedku</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Pravidlo um\xedst\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Ozna\u010dova\u010d</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Nejvy\u0161\u0161\xed ozna\u010dova\u010d</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Verze</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Hlavn\xed verze</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Okam\u017eik \xfapravy</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Skupinaz\xf3ny</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Kv\xf3ta n\xe1doby</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Zapnuto</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Nejvy\u0161\u0161\xed velikost</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Neomezeno</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Nejv\xfd\u0161e objekt\u016f</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Vybrat u\u017eivatelsk\xe9 jm\xe9no --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Automaticky vytvo\u0159it kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>P\u0159\xedstupov\xfd kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Tajn\xfd kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>E-mailov\xe1 adresa</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Pozastaveno</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Syst\xe9m</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Nejv\xfd\u0161e n\xe1dob</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>D\xedl\u010d\xed u\u017eivatel\xe9</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Schopnosti</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Kv\xf3ta u\u017eivatele</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Zobrazit</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Kl\xed\u010de</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Vybrat typ --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Opr\xe1vn\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Vybrat opr\xe1vn\u011bn\xed --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>D\xedl\u010d\xed u\u017eivatel</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>Zvolen\xfd identifik\xe1tor d\xedl\u010d\xedho u\u017eivatele u\u017e je pou\u017e\xedv\xe1n.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>\u010d\xedst, zapisovat</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>pln\xe9</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Swift kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Automaticky vytvo\u0159it tajemstv\xed</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Na\u010d\xedt\xe1n\xed \xfadaj\u016f u\u017eivatele\u2026</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>\xdadaje u\u017eivatele se nepoda\u0159ilo na\u010d\xedst.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>Zvolen\xfd identif. u\u017eivatele u\u017e je pou\u017e\xedv\xe1n.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Toto nen\xed platn\xe1 e-mailov\xe1 adresa.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>Zvolen\xe1 e-mailov\xe1 adresa u\u017e je pou\u017e\xedv\xe1na.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Nejv\xfd\u0161e n\xe1dob</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>Je t\u0159eba, aby zadan\xe1 hodnota byla 0 a vy\u0161\u0161\xed.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3 kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Nejsou zde \u017e\xe1dn\xed d\xedl\u010d\xed u\u017eivatel\xe9.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Nejsou zde \u017e\xe1dn\xe9 kl\xed\u010de.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Nejsou zde \u017e\xe1dn\xe9 schopnosti.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Neomezen\xe1 velikost</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Nejvy\u0161\u0161\xed velikost</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Neomezen\xe9 objekty</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Nejv\xfd\u0161e objekt\u016f</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>St\xe1vaj\xedc\xed</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Aktualizov\xe1no ov\u011b\u0159ov\xe1n\xed pro objevov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 port\xe1ly.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 obrazy.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 obrazy. Ov\u011b\u0159te, \u017ee jste c\xedli p\u0159idali obraz.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 inici\xe1tory. Ov\u011b\u0159te, \u017ee jste c\xedli p\u0159idali inici\xe1tor.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>C\xedl</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Stav</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Bajt\u016f \u010dten\xed</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Bajt\u016f z\xe1pis</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Operac\xed/s \u010dten\xed</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Operac\xed/s z\xe1pis</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O od</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instance</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>N\xe1zev stroje</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Probl\xe9m</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Ukazatel postupu</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Vypnuto</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Upravit re\u017eim</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>P\u0159idat prot\u011bj\u0161ek</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Upravit prot\u011bj\u0161ek</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Smazat prot\u011bj\u0161ek</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Vedouc\xed</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>Po\u010det m\xedstn\xedch</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>Po\u010det vzd\xe1len\xfdch</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>zrcadlit prot\u011bj\u0161ek</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Kl\xed\u010d</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Hlubok\xe9 zplo\u0161t\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Vrstven\xed</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>V\xfdhradn\xed z\xe1mek</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Mapa objekt\u016f (vy\u017eaduje v\xfdhradn\xed z\xe1mek)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>\u017durn\xe1lov\xe1n\xed (vy\u017eaduje v\xfdhradn\xed z\xe1mek)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Vr\xe1cen\xed zachycen\xe9ho stavu RBD zp\u011bt</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Vr\xe1cen\xed zp\u011bt</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Zachycen\xfd stav RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Smaz\xe1no v</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>identif.</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>typ</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>stav</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>verze</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Stroj</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>ko\u0159en</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Hodnocen\xed</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Proces slu\u017eby</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Aktivita</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Struktury slo\u017eek</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>I-uzl\u016f</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Vyu\u017eit\xed</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Procesy slu\u017eeb v pohotovosti</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>Hodnotu je mo\u017en\xe9 aktualizovat za chodu.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Procesy slu\u017eeb / klienti nez\xedsk\xe1vaj\xed tuto hodnotu\n z datab\xe1ze nastaven\xed monitoru. Nen\xed umo\u017en\u011bno nastavit tuto volbu\n prost\u0159ednictv\xedm \u201eceph config set \u2026\'. Tato volba by m\u011bla b\xfdt nastavena\n z p\u0159\xedkazov\xe9ho \u0159\xe1dku.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>Volba se uplatn\xed pouze p\u0159i spou\u0161t\u011bn\xed procesu slu\u017eby.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>Volba ovlivn\xed pouze vytv\xe1\u0159en\xed klastru.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>Volba ovlivn\xed pouze vytvo\u0159en\xed procesu slu\u017eby.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Aktualizov\xe1na volba nastaven\xed \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Slu\u017eba</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>St\xe1vaj\xedc\xed hodnota</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Upraviteln\xe9</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Aktualizov\xe1na volba pro modul \u201e\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Zapnout</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Vypnout</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Op\u011btovn\xe9 p\u0159ipojov\xe1n\xed, \u010dekejte\u2026</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Ve\u0159ejn\xe1 adresa</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Otev\u0159en\xe9 relace</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Po\u010det do</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>OSD kter\xe9 byly d\u0159\xedve odzna\u010deny nebudou ozna\u010deny nazp\u011bt kdy\u017e spust\xed</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Po\u010det ven</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD nebudou automaticky odzna\u010deny po nastaven\xe9m intervalu</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Po\u010det aktivn\xedch</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSD nen\xed dovoleno spu\u0161t\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Po\u010det neaktivn\xedch</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Hl\xe1\u0161en\xed o selh\xe1n\xed OSD jsou ignorov\xe1ny, jako nap\u0159\xedklad \u017ee monitory OSD neozna\u010d\xed jako nedostupn\xe9</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pozastavit</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Pozastavit \u010dten\xed a z\xe1pisy</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>\u017d\xe1dn\xe1 kontrola</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Kontrola je vypnut\xe1</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>\u017d\xe1dn\xe1 hloubkov\xe1 kontrola</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Hloubkov\xe1 kontrola je vypnut\xe1</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>\u017d\xe1dn\xe9 zasyp\xe1v\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Zasyp\xe1v\xe1n\xed skupin um\xedst\u011bn\xed je pozastaveno</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>\u017d\xe1dn\xe9 obnoven\xed</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Obnovov\xe1n\xed skupin um\xedst\u011bn\xed je pozastaveno</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Bitov\xe9 t\u0159\xedd\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>T\u0159\xeddit podle bit\u016f</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Vy\u010di\u0161t\u011bn\xe9 slo\u017eky zachycen\xfdch stav\u016f</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD maj\xed p\u0159eveden\xe9 sady zachycen\xfdch stav\u016f</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Smaz\xe1no p\u0159i zotavov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Maz\xe1n\xed proveden\xe1 p\u0159i obnovov\xe1n\xed nam\xedsto peeringu</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Nep\u0159ekro\u010diteln\xfd limit z\xe1znamu ud\xe1lost\xed PG</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Zapne nep\u0159ekro\u010diteln\xfd limit na d\xe9lku z\xe1znamu ud\xe1lost\xed v pg</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Aktualizov\xe1ny OSD p\u0159\xedznaky</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>ven</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>dovnit\u0159</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>nedostupn\xe9</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Zna\u010dka</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD ztraceno</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>ozna\u010deno jako ztracen\xe9</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Vy\u010distit</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>vy\u010di\u0161t\u011bno</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>zlikvidovat</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>zlikvidov\xe1no</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>skupiny um\xedst\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>P\u0159e\u010dteno bajt\u016f</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Zaps\xe1no bajt\u016f</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Operac\xed/s \u010dten\xed</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Operac\xed/s z\xe1pis</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Ozna\u010dit OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Ozna\u010dit \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Max Backfills</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Recovery Max Active</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Recovery Max Single Start</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Recovery Sleep</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>U\u017eivatelsky ur\u010den\xe9</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Aktualizov\xe1na rychlost zotaven\xed OSD \u201e\n <x id="INTERPOLATION" equiv-text="{{value}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> bylo inicializov\xe1no v n\xe1sleduj\xedc\xedm OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>\xdaloha</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Z\xe1va\u017enost</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Zah\xe1jeno</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL adresa</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Aktualizov\xe1no</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Pou\u017eito</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>K dispozici</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>\u010cist\xe9</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>Pracuj\xedc\xed</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Varov\xe1n\xed</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Nezn\xe1m\xe9</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>aktivn\xed</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>\u017e\xe1dn\xe9 souborov\xe9 syst\xe9my</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>aktivn\xed</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>v pohotovosti</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/a</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>aktivn\xed proces slu\u017eby</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>kv\xf3rum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Slu\u017eba NFS Ganesha nen\xed nastavena.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transport</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS u\u017eivatel</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>Souborov\xfd syst\xe9m CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(p\u0159evzato z glob\xe1ln\xedho nastaven\xed)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>p\u0159evzato z glob\xe1ln\xedho nastaven\xed</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Select what kind of user id squashing is performed --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 procesy slu\u017eeb.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Re\u017eim mezipam\u011bti</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Min Evict Age</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Min Flush Age</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Nejv\xfd\u0161e bajt\u016f c\xedle</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Nejv\xfd\u0161e objekt\u016f c\xedle</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Nebyla p\u0159id\xe1na \u017e\xe1dn\xe1 aplikace</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Dosa\u017een limit aplikac\xed</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Fond m\u016f\u017ee m\xedt nejv\xfd\u0161e \u010dty\u0159i definice aplikac\xed.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Pou\u017eiteln\xe9 znaky \u201e_a-zA-Z0-9\u201c</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>Nejvy\u0161\u0161\xed d\xe9lka je 128 znak\u016f</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtrovat nebo p\u0159idat aplikace</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>P\u0159idat aplikaci</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>profil mazac\xedho k\xf3du</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Velikost repliky</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Nejnov\u011bj\u0161\xed zm\u011bna</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Maz\xe1n\xedm k\xf3dovan\xfd profil</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Sada crush pravidel</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Zaps\xe1no bajt\u016f</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>n\xe1doba</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Aktualizov\xe1na n\xe1doba objektov\xe9 br\xe1ny \u201e\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Vytvo\u0159ena n\xe1doba objektov\xe9 br\xe1ny \u201e\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>n\xe1doby</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>u\u017eivatel</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Aktualizov\xe1n u\u017eivatel objektov\xe9 br\xe1ny \u201e\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Vytvo\u0159en u\u017eivatel objektov\xe9 br\xe1ny \u201e\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>u\u017eivatel\xe9</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Rozsah</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>\u010cten\xed</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Vytvo\u0159it</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Vytvo\u0159ena role \u201e\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Aktualizov\xe1na role \u201e\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Syst\xe9mov\xe1 role</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Smaz\xe1na role \u201e\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Vytvo\u0159en u\u017eivatel \u201e\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Aktualizovat u\u017eivatele</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Pokra\u010dovat</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Byli jste automaticky odhl\xe1\u0161eni proto\u017ee va\u0161e role byly zm\u011bn\u011bny.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Aktualizov\xe1n u\u017eivatel \u201e\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Smaz\xe1n u\u017eivatel \u201e\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Nepoda\u0159ilo se smazat u\u017eivatele \u201e\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Nyn\xed jste p\u0159ihl\xe1\u0161en\xed jako \u201e\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201c.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Ka\u017ed\xfd objekt je rozd\u011blen v \u010d\xe1stech shluk\u016f dat, ka\u017ed\xe9 ulo\u017een\xe9 na jin\xe9m OSD.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Po\u010d\xedtat k\xf3dovac\xed shluky pro ka\u017ed\xfd objekt a ukl\xe1dat je na r\u016fzn\xfdch OSD.\n Po\u010det k\xf3dovac\xedch shluk\u016f je tak\xe9 po\u010det OSD, kter\xe9 mohou vypadnou, ani\u017e dojde ke ztr\xe1t\u011b dat.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Z\xe1suvn\xfd modul jerasure je nejobecn\u011bj\u0161\xed a nejp\u0159izp\u016fsobiv\u011bj\u0161\xed,\n je tak\xe9 v\xfdchoz\xed pro Ceph fondy k\xf3dovan\xe9 maz\xe1n\xedm.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Z\xe1suvn\xfd modul isa obaluje knihovnu ISA. Funguje pouze na procesorech Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>N\xe1zev crush n\xe1doby slou\u017e\xedc\xed jako prvn\xed krok CRUSH pravidla.\n Nap\u0159\xedklad krok vz\xedt v\xfdchoz\xed.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Omezit um\xedst\u011bn\xed na za\u0159\xedzen\xed ur\u010dit\xe9 t\u0159\xeddy\n (nap\u0159., ssd nebo hdd), pomoc\xed n\xe1zvu crush t\u0159\xeddy za\u0159\xedzen\xed v CRUSH map\u011b.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Nastavit slo\u017eku ze kter\xe9 na\u010d\xedtat z\xe1suvn\xfd modul mazac\xedho k\xf3du.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Umo\u017enit v\u0161echny operace</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Umo\u017enit pouze operace kter\xe9 neuprav\xed server</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>Neumo\u017e\u0148uje operace \u010dten\xed \u010di z\xe1pisu, ale umo\u017e\u0148uje ostatn\xed</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>Neumo\u017e\u0148uje \u010dten\xed, z\xe1pis nebo jinou operaci kter\xe1 upravuje atributy souboru nebo obsah slo\u017eky</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>Neumo\u017enit v\u016fbec \u017e\xe1dn\xfd p\u0159\xedstup</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Vyberte prioritu --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>N\xedzk\xe1</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Vysok\xe1</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>Uplynul\xfdch 5 minut</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>Uplynul\xfdch 15 minut</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>Uplynul\xfdch 30 minut</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>Uplynul\xe1 1 hodina (v\xfdchoz\xed)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>Uplynul\xe9 3 hodiny</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>Uplynul\xfdch 6 hodin</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>Uplynul\xfdch 12 hodin</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>Uplynul\xfdch 24 hodin</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>V\u010dera</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Dnes</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Dnes doposud</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>V\u010derej\u0161ek</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Uplynul\xe9 2 dny</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Tento den minul\xfd t\xfdden</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>P\u0159edchoz\xed t\xfdden</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Tento t\xfdden</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Tento t\xfdden doposud</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Uplynul\xfdch 7 dn\u016f</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>P\u0159edchoz\xed m\u011bs\xedc</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Tento m\u011bs\xedc</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Tento m\u011bs\xedc doposud</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Uplynul\xfdch 30 dn\u016f</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Uplynul\xfdch 90 dn\u016f</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Uplynul\xfdch 6 m\u011bs\xedc\u016f</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>Uplynul\xfd 1 rok</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>P\u0159edchoz\xed rok</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Tento rok</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Tento rok doposud</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Uplynul\xe9 2 roky</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Uplynul\xfdch 5 let</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informace</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Nevybr\xe1ny \u017e\xe1dn\xe9 polo\u017eky.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Aby polo\u017eku bylo mo\u017en\xe9 znovu vybrat, je t\u0159eba nejprve zru\u0161it jej\xed v\xfdb\u011br</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Dosa\u017een limit v\xfdb\u011bru</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Filtrovat \u0161t\xedtky</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>P\u0159idat odznak</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Nejsou k dispozici \u017e\xe1dn\xe9 polo\u017eky.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>P\u0159idat</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Klonovat</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Kop\xedrovat</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Hloubkov\xe1 kontrola</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Zlikvidovat</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Zplo\u0161tit</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Ozna\u010dit</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Ozna\u010dit</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Ozna\u010dit ztracen\xe9</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Odzna\u010dit</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Ochr\xe1nit</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>P\u0159ejmenovat</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Obnovit</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>P\u0159esunout do ko\u0161e</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Zru\u0161it ochranu</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Smaz\xe1no</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Naklonov\xe1no</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Zkop\xedrov\xe1no</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Ano</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>Ne</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Kvalita slu\u017eby</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS Limit</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Po\u017eadovan\xfd limit vst./v\xfdstup. bajt\u016f za sekundu.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS Limit</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Po\u017eadovan\xfd limit vst./v\xfdstup. operac\xed za sekundu.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>Read BPS Limit</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Po\u017eadovan\xfd limit \u010dten\xed bajt\u016f za sekundu.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>Read IOPS Limit</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Po\u017eadovan\xfd limit operac\xed \u010dten\xed za sekundu.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Write BPS Limit</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Po\u017eadovan\xfd limit z\xe1pisu bajt\u016f za sekundu.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Write IOPS Limit</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Po\u017eadovan\xfd limit operac\xed \u010dten\xed za sekundu.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS d\xe1vka</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>The desired burst limit of IO bytes.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS Burst</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>Po\u017eadovan\xfd limit d\xe1vky vst./v\xfdstup. operac\xed.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Read BPS Burst</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>Po\u017eadovan\xfd limit d\xe1vky bajt\u016f \u010dten\xed.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Read IOPS Burst</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>Po\u017eadovan\xfd limit d\xe1vky \u010dten\xed bajt\u016f.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Write BPS Burst</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>Po\u017eadovan\xfd limit bajt\u016f d\xe1vky z\xe1pisu.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Write IOPS Burst</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>Po\u017eadovan\xfd limit d\xe1vky operace z\xe1pisu.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Nepoda\u0159ilo se \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Vykon\xe1v\xe1 se</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>vykonat</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Vykon\xe1no</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>nezn\xe1m\xfd \xfakol</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Vytv\xe1\u0159\xed se</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>vytvo\u0159it</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Aktualizuje se</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>aktualizovat</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Ma\u017ee se</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>smazat</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD zachycen\xfd stav \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>re\u017eim zrcadlen\xed pro fond \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>prot\u011bj\u0161ek zrcadlen\xed pro fond \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>N\xe1zev u\u017e je pou\u017e\xedv\xe1n \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>N\xe1zev u\u017e je pou\u017e\xedv\xe1n \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>N\xe1zev u\u017e je pou\u017e\xedv\xe1n \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> obsahuje zachycen\xe9 stavy.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Klonuje se</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>klonovat</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>Je t\u0159eba, aby zachycen\xfd stav \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> byl chr\xe1n\u011bn\xfd.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Kop\xedruje se</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>zkop\xedrovat</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Zplo\u0161t\u011bn\xed</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>zplo\u0161tit</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Zplo\u0161t\u011bno</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>N\xe1zev u\u017e je pou\u017e\xedv\xe1n pro \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Nen\xed mo\u017en\xe9 zru\u0161it ochranu \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, proto\u017ee obsahuje pod\u0159\xedzen\xe9 obrazy.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> nen\xed mo\u017en\xe9 smazat, proto\u017ee je chr\xe1n\u011bn\xe9.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Bere se zp\u011bt</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>vz\xedt zp\u011bt</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Vzato zp\u011bt</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>P\u0159esouv\xe1 se</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>p\u0159esunout</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>P\u0159esunuto</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>obraz \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c do ko\u0161e\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Obraz se neda\u0159\xed naj\xedt.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Obnovuje se</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>obnovit</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Obnoveno</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>obraz \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c do \u201e\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>N\xe1zev \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c u\u017e je pou\u017e\xedv\xe1n pro jin\xfd obraz.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>obraz \u201e\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>\u010cist\xed se</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>vy\u010distit</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Vy\u010di\u0161t\u011bno</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>v\u0161echny fondy</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>obrazy z \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Zrcadlen\xed nelze vypnout proto\u017ee obsahuje prot\u011bj\u0161ek.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>fond \u201e\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>profil mazac\xedho k\xf3du \u201e\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>c\xedl \u201e\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\u201c\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},McSo:function(t,e,n){"use strict";function a(t){return null!==t&&"object"==typeof t}n.d(e,"a",function(){return a})},MdoF:function(t,e,n){"use strict";n.d(e,"b",function(){return s}),n.d(e,"c",function(){return c}),n.d(e,"a",function(){return d});var a=n("CcnG"),r=n("lTVp"),i=n("Ip0R"),s=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"button",[["aria-label","Close"],["class","close"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.close()&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["\xd7"])),(t()(),a["\u0275eld"](3,0,null,null,1,"span",[["class","sr-only"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Close"]))],null,null)}function u(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["role","alert"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,o)),a["\u0275did"](3,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),a["\u0275ncd"](null,0)],function(t,e){var n=e.component;t(e,1,0,"alert alert-"+n.type,n.classes),t(e,3,0,n.dismissible)},null)}function c(t){return a["\u0275vid"](2,[(t()(),a["\u0275and"](16777216,null,null,1,null,u)),a["\u0275did"](1,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.isOpen)},null)}function l(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"alert",[],null,null,null,c,s)),a["\u0275did"](1,114688,null,0,r.a,[r.b,a.ChangeDetectorRef],null,null)],function(t,e){t(e,1,0)},null)}var d=a["\u0275ccf"]("alert,bs-alert",r.a,l,{type:"type",dismissible:"dismissible",dismissOnTimeout:"dismissOnTimeout",isOpen:"isOpen"},{onClose:"onClose",onClosed:"onClosed"},["*"])},Mfce:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG");n("czA5"),e.DataTableRowWrapperComponent=function(){function t(t,e){this.cd=t,this.differs=e,this.rowContextmenu=new i.EventEmitter(!1),this.groupContext={group:this.row,expanded:this.expanded,rowIndex:this.rowIndex},this.rowContext={row:this.row,expanded:this.expanded,rowIndex:this.rowIndex},this._expanded=!1,this.rowDiffer=e.find({}).create()}return Object.defineProperty(t.prototype,"rowIndex",{get:function(){return this._rowIndex},set:function(t){this._rowIndex=t,this.rowContext.rowIndex=t,this.groupContext.rowIndex=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"expanded",{get:function(){return this._expanded},set:function(t){this._expanded=t,this.groupContext.expanded=t,this.rowContext.expanded=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this.rowDiffer.diff(this.row)&&(this.rowContext.row=this.row,this.groupContext.group=this.row,this.cd.markForCheck())},t.prototype.onContextmenu=function(t){this.rowContextmenu.emit({event:t,row:this.row})},t.prototype.getGroupHeaderStyle=function(){var t={};return t.transform="translate3d("+this.offsetX+"px, 0px, 0px)",t["backface-visibility"]="hidden",t.width=this.innerWidth,t},a([i.Input(),r("design:type",Number)],t.prototype,"innerWidth",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowDetail",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupHeader",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offsetX",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"detailRowHeight",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"row",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupedRows",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"rowContextmenu",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowIndex",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"expanded",null),a([i.HostListener("contextmenu",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onContextmenu",null),a([i.Component({selector:"datatable-row-wrapper",changeDetection:i.ChangeDetectionStrategy.OnPush,template:'\n <div \n *ngIf="groupHeader && groupHeader.template"\n class="datatable-group-header"\n [ngStyle]="getGroupHeaderStyle()">\n <ng-template\n *ngIf="groupHeader && groupHeader.template"\n [ngTemplateOutlet]="groupHeader.template"\n [ngTemplateOutletContext]="groupContext">\n </ng-template>\n </div>\n <ng-content \n *ngIf="(groupHeader && groupHeader.template && expanded) || \n (!groupHeader || !groupHeader.template)">\n </ng-content>\n <div\n *ngIf="rowDetail && rowDetail.template && expanded"\n [style.height.px]="detailRowHeight"\n class="datatable-row-detail">\n <ng-template\n *ngIf="rowDetail && rowDetail.template"\n [ngTemplateOutlet]="rowDetail.template"\n [ngTemplateOutletContext]="rowContext">\n </ng-template>\n </div>\n ',host:{class:"datatable-row-wrapper"}})],t)}()},MgB7:function(t,e,n){"use strict";function a(t,e,n){var a,r,i;n=n||{};var s=null,o=0;function u(){o=!1===n.leading?0:+new Date,s=null,i=t.apply(a,r)}return function(){var c=+new Date;o||!1!==n.leading||(o=c);var l=e-(c-o);return a=this,r=arguments,l<=0?(clearTimeout(s),s=null,o=c,i=t.apply(a,r)):s||!1===n.trailing||(s=setTimeout(u,l)),i}}Object.defineProperty(e,"__esModule",{value:!0}),e.throttle=a,e.throttleable=function(t,e){return function(n,r,i){return{configurable:!0,enumerable:i.enumerable,get:function(){return Object.defineProperty(this,r,{configurable:!0,enumerable:i.enumerable,value:a(i.value,t,e)}),this[r]}}}}},MuvH:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("t/Na"),i=n("pL04"),s=function(){function t(t){this.http=t}return t.prototype.getConfigData=function(){return this.http.get("api/cluster_conf/")},t.prototype.get=function(t){return this.http.get("api/cluster_conf/"+t)},t.prototype.filter=function(t){return this.http.get("api/cluster_conf/filter?names="+t.join(","))},t.prototype.create=function(t){return this.http.post("api/cluster_conf/",t)},t.prototype.delete=function(t,e){return this.http.delete("api/cluster_conf/"+t+"?section="+e)},t.prototype.bulkCreate=function(t){return this.http.put("api/cluster_conf/",t)},t.ngInjectableDef=a.defineInjectable({factory:function(){return new t(a.inject(r.c))},token:t,providedIn:i.a}),t}()},MwfX:function(t,e,n){"use strict";n.d(e,"a",function(){return d}),n.d(e,"b",function(){return f});var a=n("mrSG"),r=n("zo3G"),i=n("26FU"),s=n("6blF"),o=n("mZXl"),u=n("dC0D"),c=n("67Y/"),l=n("ad02"),d=function(t){function e(e,n,a){var i=t.call(this,e)||this;return n.pipe(Object(o.b)(r.a)).pipe(Object(u.a)(function(t,e){return e?a(t,e):t},e)).subscribe(function(t){return i.next(t)}),i}return Object(a.__extends)(e,t),e}(i.a),f=function(t){function e(e,n,a){var r=t.call(this)||this;return r._dispatcher=e,r._reducer=n,r.source=a,r}return Object(a.__extends)(e,t),e.prototype.select=function(t){return this.source.pipe(Object(c.a)(t)).pipe(Object(l.a)())},e.prototype.lift=function(t){var n=new e(this._dispatcher,this._reducer,this);return n.operator=t,n},e.prototype.dispatch=function(t){this._dispatcher.next(t)},e.prototype.next=function(t){this._dispatcher.next(t)},e.prototype.error=function(t){this._dispatcher.error(t)},e.prototype.complete=function(){},e}(s.a)},Mxhz:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("t/Na"),i=n("pL04"),s=function(){function t(t){this.http=t}return t.prototype.list=function(){return this.http.get("api/user")},t.prototype.delete=function(t){return this.http.delete("api/user/"+t)},t.prototype.get=function(t){return this.http.get("api/user/"+t)},t.prototype.create=function(t){return this.http.post("api/user",t)},t.prototype.update=function(t){return this.http.put("api/user/"+t.username,t)},t.ngInjectableDef=a.defineInjectable({factory:function(){return new t(a.inject(r.c))},token:t,providedIn:i.a}),t}()},NDi4:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("CcnG"),r=function(){return function(){this.title="Error",this.backAction=new a.EventEmitter}}()},NEZu:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(t,e,n,a){this.customColors={backgroundColor:void 0,borderColor:void 0},this.checkOffset=!1,this.chartEl=t.nativeElement,this.getStyleLeft=n,this.getStyleTop=a,this.tooltipEl=e.nativeElement}return t.prototype.customTooltips=function(t){var e=this;if(0!==t.opacity){if(this.tooltipEl.classList.remove("above","below","no-transform"),this.tooltipEl.classList.add(t.yAlign?t.yAlign:"no-transform"),t.body){var n=t.title||[],a=t.body.map(function(t){return t.lines}),r="<thead>";n.forEach(function(t){r+="<tr><th>"+e.getTitle(t)+"</th></tr>"}),r+="</thead><tbody>",a.forEach(function(n,a){var i=t.labelColors[a],s="background:"+(e.customColors.backgroundColor||i.backgroundColor);s+="; border-color:"+(e.customColors.borderColor||i.borderColor),r+='<tr><td nowrap><span class="chartjs-tooltip-key" style="'+(s+="; border-width: 2px")+'"></span>'+e.getBody(n)+"</td></tr>"}),r+="</tbody>",this.tooltipEl.querySelector("table").innerHTML=r}var i=this.chartEl.offsetTop,s=this.chartEl.offsetLeft;if(this.checkOffset){var o=t.width/2;this.tooltipEl.classList.remove("transform-left"),this.tooltipEl.classList.remove("transform-right"),t.caretX-o<0?this.tooltipEl.classList.add("transform-left"):t.caretX+o>this.chartEl.width&&this.tooltipEl.classList.add("transform-right")}this.tooltipEl.style.left=this.getStyleLeft(t,s),this.tooltipEl.style.top=this.getStyleTop(t,i),this.tooltipEl.style.opacity=1,this.tooltipEl.style.fontFamily=t._fontFamily,this.tooltipEl.style.fontSize=t.fontSize,this.tooltipEl.style.fontStyle=t._fontStyle,this.tooltipEl.style.padding=t.yPadding+"px "+t.xPadding+"px"}else this.tooltipEl.style.opacity=0},t.prototype.getBody=function(t){return t},t.prototype.getTitle=function(t){return t},t}()},NJnL:function(t,e,n){"use strict";n.d(e,"a",function(){return G});var a=n("mrSG"),r=n("CcnG"),i=n("Ip0R"),s=n("K9Ia"),o=n("p0ib"),u=n("bne5"),c=n("F/XL"),l=n("tHPV");function d(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function f(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function p(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=d(t),n=e.overflowX,a=e.overflowY;return/(auto|scroll|overlay)/.test(String(e.overflow)+String(a)+String(n))?t:p(f(t))}var h="undefined"!=typeof window&&"undefined"!=typeof document,g=h&&!(!window.MSInputMethodContext||!document.documentMode),b=h&&!(!window.MSInputMethodContext||!/MSIE 10/.test(navigator.userAgent));function m(t){return 11===t?g:10===t?b:g||b}function y(t){if(!t)return document.documentElement;for(var e,n=m(10)?document.body:null,a=t.offsetParent||null;a===n&&t.nextElementSibling&&e!==t.nextElementSibling;)a=(e=t.nextElementSibling).offsetParent;var r=a&&a.nodeName;return r&&"BODY"!==r&&"HTML"!==r?-1!==["TH","TD","TABLE"].indexOf(a.nodeName)&&"static"===d(a,"position")?y(a):a:e?e.ownerDocument.documentElement:document.documentElement}function v(t){return null!==t.parentNode?v(t.parentNode):t}function _(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,a=n?t:e,r=n?e:t,i=document.createRange();i.setStart(a,0),i.setEnd(r,0);var s,o,u=i.commonAncestorContainer;if(t!==u&&e!==u||a.contains(r))return"BODY"===(o=(s=u).nodeName)||"HTML"!==o&&y(s.firstElementChild)!==s?y(u):u;var c=v(t);return c.host?_(c.host,e):_(t,v(e).host)}function x(t,e){var n="x"===e?"Left":"Top",a="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+a+"Width"])}function T(t,e,n,a){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],m(10)?parseInt(n["offset"+t],10)+parseInt(a["margin"+("Height"===t?"Top":"Left")],10)+parseInt(a["margin"+("Height"===t?"Bottom":"Right")],10):0)}function w(t){var e=t.body,n=t.documentElement,a=m(10)&&getComputedStyle(n);return{height:T("Height",e,n,a),width:T("Width",e,n,a)}}function S(t,e){void 0===e&&(e="top");var n="top"===e?"scrollTop":"scrollLeft",a=t.nodeName;return"BODY"===a||"HTML"===a?(t.ownerDocument.scrollingElement||t.ownerDocument.documentElement)[n]:t[n]}function O(t){return Object(a.__assign)({},t,{right:t.left+t.width,bottom:t.top+t.height})}function I(t){var e={};try{if(m(10)){e=t.getBoundingClientRect();var n=S(t,"top"),a=S(t,"left");e.top+=n,e.left+=a,e.bottom+=n,e.right+=a}else e=t.getBoundingClientRect()}catch(c){return}var r={left:e.left,top:e.top,width:e.right-e.left,height:e.bottom-e.top},i="HTML"===t.nodeName?w(t.ownerDocument):{},s=t.offsetWidth-(i.width||t.clientWidth||r.right-r.left),o=t.offsetHeight-(i.height||t.clientHeight||r.bottom-r.top);if(s||o){var u=d(t);s-=x(u,"x"),o-=x(u,"y"),r.width-=s,r.height-=o}return O(r)}function C(t,e,n){void 0===n&&(n=!1);var a=m(10),r="HTML"===e.nodeName,i=I(t),s=I(e),o=p(t),u=d(e),c=parseFloat(u.borderTopWidth),l=parseFloat(u.borderLeftWidth);n&&r&&(s.top=Math.max(s.top,0),s.left=Math.max(s.left,0));var f=O({top:i.top-s.top-c,left:i.left-s.left-l,width:i.width,height:i.height});if(f.marginTop=0,f.marginLeft=0,!a&&r){var h=parseFloat(u.marginTop),g=parseFloat(u.marginLeft);f.top-=c-h,f.bottom-=c-h,f.left-=l-g,f.right-=l-g,f.marginTop=h,f.marginLeft=g}return(a&&!n?e.contains(o):e===o&&"BODY"!==o.nodeName)&&(f=function(t,e,n){void 0===n&&(n=!1);var a=S(e,"top"),r=S(e,"left"),i=n?-1:1;return t.top+=a*i,t.bottom+=a*i,t.left+=r*i,t.right+=r*i,t}(f,e)),f}function k(t){if(!t||!t.parentElement||m())return document.documentElement;for(var e=t.parentElement;e&&"none"===d(e,"transform");)e=e.parentElement;return e||document.documentElement}function N(t,e,n,a,r){void 0===n&&(n=0),void 0===r&&(r=!1);var i={top:0,left:0},s=r?k(t):_(t,e);if("viewport"===a)i=function(t,e){void 0===e&&(e=!1);var n=s.ownerDocument.documentElement,a=C(s,n),r=Math.max(n.clientWidth,window.innerWidth||0),i=Math.max(n.clientHeight,window.innerHeight||0),o=e?0:S(n),u=e?0:S(n,"left");return O({top:o-Number(a.top)+Number(a.marginTop),left:u-Number(a.left)+Number(a.marginLeft),width:r,height:i})}(0,r);else{var o=void 0;"scrollParent"===a?"BODY"===(o=p(f(e))).nodeName&&(o=t.ownerDocument.documentElement):o="window"===a?t.ownerDocument.documentElement:a;var u=C(o,s,r);if("HTML"!==o.nodeName||function t(e){var n=e.nodeName;return"BODY"!==n&&"HTML"!==n&&("fixed"===d(e,"position")||t(f(e)))}(s))i=u;else{var c=w(t.ownerDocument),l=c.height,h=c.width;i.top+=u.top-u.marginTop,i.bottom=Number(l)+Number(u.top),i.left+=u.left-u.marginLeft,i.right=Number(h)+Number(u.left)}}return i.left+=n,i.top+=n,i.right-=n,i.bottom-=n,i}function R(t,e,n,r,i,s,o){if(void 0===i&&(i=["top","bottom","right","left"]),void 0===s&&(s="viewport"),void 0===o&&(o=0),-1===t.indexOf("auto"))return t;var u=N(n,r,o,s),c={top:{width:u.width,height:e.top-u.top},right:{width:u.right-e.right,height:u.height},bottom:{width:u.width,height:u.bottom-e.bottom},left:{width:e.left-u.left,height:u.height}},l=Object.keys(c).map(function(t){return Object(a.__assign)({key:t},c[t],{area:(e=c[t],e.width*e.height)});var e}).sort(function(t,e){return e.area-t.area}),d=l.filter(function(t){return t.width>=n.clientWidth&&t.height>=n.clientHeight}),f=(d=d.filter(function(t){return i.some(function(e){return e===t.key})})).length>0?d[0].key:l[0].key,p=t.split(" ")[1];return n.className=n.className.replace(/bs-tooltip-auto/g,"bs-tooltip-"+f),f+(p?"-"+p:"")}function A(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),a=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:Number(t.offsetWidth)+a,height:Number(t.offsetHeight)+n}}function D(t,e,n){return void 0===n&&(n=null),C(e,n?k(t):_(t,e),n)}function E(t,e,n){var a,r=n.split(" ")[0],i=A(t),s={width:i.width,height:i.height},o=-1!==["right","left"].indexOf(r),u=o?"top":"left",c=o?"left":"top",l=o?"height":"width",d=o?"width":"height";return s[u]=e[u]+e[l]/2-i[l]/2,s[c]=r===c?e[c]-i[d]:e[(a={left:"right",right:"left",bottom:"top",top:"bottom"},c.replace(/left|right|bottom|top/g,function(t){return a[t]}))],s}function L(t,e){return t&&t.modifiers&&t.modifiers[e]&&t.modifiers[e].enabled}function P(t,e,n){Object.keys(e).forEach(function(a){var r,i="";-1!==["width","height","top","right","bottom","left"].indexOf(a)&&""!==(r=e[a])&&!isNaN(parseFloat(r))&&isFinite(r)&&(i="px"),n?n.setStyle(t,a,""+String(e[a])+i):t.style[a]=String(e[a])+i})}function M(t){var e,n=t.offsets.target,a=t.instance.target.querySelector(".arrow");if(!a)return t;var r=-1!==["left","right"].indexOf(t.placement),i=r?"height":"width",s=r?"Top":"Left",o=s.toLowerCase(),u=r?"left":"top",c=r?"bottom":"right",l=A(a)[i];t.offsets.host[c]-l<n[o]&&(n[o]-=n[o]-(t.offsets.host[c]-l)),Number(t.offsets.host[o])+Number(l)>n[c]&&(n[o]+=Number(t.offsets.host[o])+Number(l)-Number(n[c])),n=O(n);var f=Number(t.offsets.host[o])+Number(t.offsets.host[i]/2-l/2),p=d(t.instance.target),h=parseFloat(p["margin"+s]),g=parseFloat(p["border"+s+"Width"]),b=f-n[o]-h-g;return b=Math.max(Math.min(n[i]-l,b),0),t.offsets.arrow=((e={})[o]=Math.round(b),e[u]="",e),t.instance.arrow=a,t}function q(t){if(t.offsets.target=O(t.offsets.target),!L(t.options,"flip"))return t.offsets.target=Object(a.__assign)({},t.offsets.target,E(t.instance.target,t.offsets.host,t.placement)),t;var e=N(t.instance.target,t.instance.host,0,"viewport",!1),n=t.placement.split(" ")[0],r=t.placement.split(" ")[1]||"",i=R("auto",t.offsets.host,t.instance.target,t.instance.host,t.options.allowedPositions),s=[n,i];return s.forEach(function(i,o){if(n!==i||s.length===o+1)return t;var u="left"===(n=t.placement.split(" ")[0])&&Math.floor(t.offsets.target.right)>Math.floor(t.offsets.host.left)||"right"===n&&Math.floor(t.offsets.target.left)<Math.floor(t.offsets.host.right)||"top"===n&&Math.floor(t.offsets.target.bottom)>Math.floor(t.offsets.host.top)||"bottom"===n&&Math.floor(t.offsets.target.top)<Math.floor(t.offsets.host.bottom),c=Math.floor(t.offsets.target.left)<Math.floor(e.left),l=Math.floor(t.offsets.target.right)>Math.floor(e.right),d=Math.floor(t.offsets.target.top)<Math.floor(e.top),f=Math.floor(t.offsets.target.bottom)>Math.floor(e.bottom),p="left"===n&&c||"right"===n&&l||"top"===n&&d||"bottom"===n&&f,h=-1!==["top","bottom"].indexOf(n),g=h&&"left"===r&&c||h&&"right"===r&&l||!h&&"left"===r&&d||!h&&"right"===r&&f;(u||p||g)&&((u||p)&&(n=s[o+1]),g&&(r=function(t){return"right"===t?"left":"left"===t?"right":t}(r)),t.placement=n+(r?" "+r:""),t.offsets.target=Object(a.__assign)({},t.offsets.target,E(t.instance.target,t.offsets.host,t.placement)))}),t}function j(t){if(!L(t.options,"preventOverflow"))return t;var e=t.instance.target.style,n=e.top,r=e.left,i=e.transform;e.top="",e.left="",e.transform="";var s=N(t.instance.target,t.instance.host,0,"scrollParent",!1);e.top=n,e.left=r,e.transform=i;var o,u={primary:function(e){var n,a=t.offsets.target[e];return t.offsets.target[e]<s[e]&&(a=Math.max(t.offsets.target[e],s[e])),(n={})[e]=a,n},secondary:function(e){var n,a="right"===e?"left":"top",r=t.offsets.target[a];return t.offsets.target[e]>s[e]&&(r=Math.min(t.offsets.target[a],s[e]-("right"===e?t.offsets.target.width:t.offsets.target.height))),(n={})[a]=r,n}};return["left","right","top","bottom"].forEach(function(e){o=-1!==["left","top"].indexOf(e)?"primary":"secondary",t.offsets.target=Object(a.__assign)({},t.offsets.target,u[o](e))}),t}function F(t){var e,n,r=t.placement,i=r.split(" ")[0],s=r.split(" ")[1];if(s){var o=t.offsets,u=o.host,c=o.target,l=-1!==["bottom","top"].indexOf(i),d=l?"left":"top",f=l?"width":"height",p={start:(e={},e[d]=u[d],e),end:(n={},n[d]=u[d]+u[f]-c[f],n)};t.offsets.target=Object(a.__assign)({},c,p[s])}return t}var z=new(function(){function t(){}return t.prototype.position=function(t,e,n){return void 0===n&&(n=!0),this.offset(t,e,!1)},t.prototype.offset=function(t,e,n){return void 0===n&&(n=!0),D(e,t)},t.prototype.positionElements=function(t,e,n,a,r){return[q,F,j,M].reduce(function(t,e){return e(t)},function(t,e,n,a){var r=D(t,e);n.match(/^(auto)*\s*(left|right|top|bottom)*$/)||n.match(/^(left|right|top|bottom)*\s*(start|end)*$/)||(n="auto");var i=!!n.match(/auto/g),s=n.match(/auto\s(left|right|top|bottom)/)?n.split(" ")[1]||"auto":n;return{options:a,instance:{target:t,host:e,arrow:null},offsets:{target:E(t,r,s),host:r,arrow:null},positionFixed:!1,placement:s=R(s,r,t,e,a?a.allowedPositions:void 0),placementAuto:i}}(e,t,n,r))},t}()),G=function(){function t(t,e){var n=this;this.update$$=new s.a,this.positionElements=new Map,this.isDisabled=!1,Object(i.isPlatformBrowser)(e)&&(this.triggerEvent$=Object(o.a)(Object(u.a)(window,"scroll"),Object(u.a)(window,"resize"),Object(c.a)(0,l.a),this.update$$),this.triggerEvent$.subscribe(function(){n.isDisabled||n.positionElements.forEach(function(e){var a,r,i,s,o,u,c,l;a=Y(e.target),r=Y(e.element),i=e.attachment,s=e.appendToBody,o=n.options,u=t.createRenderer(null,null),P(r,{"will-change":"transform",top:"0px",left:"0px",transform:"translate3d("+(l=function(t){return{width:t.offsets.target.width,height:t.offsets.target.height,left:Math.floor(t.offsets.target.left),top:Math.round(t.offsets.target.top),bottom:Math.round(t.offsets.target.bottom),right:Math.floor(t.offsets.target.right)}}(c=z.positionElements(a,r,i,s,o))).left+"px, "+l.top+"px, 0px)"},u),c.instance.arrow&&P(c.instance.arrow,c.offsets.arrow,u),function(t,e){var n=t.instance.target,a=n.className;t.placementAuto&&(-1!==(a=(a=(a=a.replace(/bs-popover-auto/g,"bs-popover-"+t.placement)).replace(/bs-tooltip-auto/g,"bs-tooltip-"+t.placement)).replace(/\sauto/g," "+t.placement)).indexOf("popover")&&-1===a.indexOf("popover-auto")&&(a+=" popover-auto"),-1!==a.indexOf("tooltip")&&-1===a.indexOf("tooltip-auto")&&(a+=" tooltip-auto")),a=a.replace(/left|right|top|bottom/g,""+t.placement.split(" ")[0]),e?e.setAttribute(n,"class",a):n.className=a}(c,u)})}))}return t.prototype.position=function(t){this.addPositionElement(t)},Object.defineProperty(t.prototype,"event$",{get:function(){return this.triggerEvent$},enumerable:!0,configurable:!0}),t.prototype.disable=function(){this.isDisabled=!0},t.prototype.enable=function(){this.isDisabled=!1},t.prototype.addPositionElement=function(t){this.positionElements.set(Y(t.element),t)},t.prototype.calcPosition=function(){this.update$$.next()},t.prototype.deletePositionElement=function(t){this.positionElements.delete(Y(t))},t.prototype.setOptions=function(t){this.options=t},t}();function Y(t){return"string"==typeof t?document.querySelector(t):t instanceof r.ElementRef?t.nativeElement:t}},NUGo:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R"),i=n("ZYCi"),s=n("xtZt"),o=n("lqqz");n("S7zO"),n.d(e,"a",function(){return u}),n.d(e,"b",function(){return g});var u=a["\u0275crt"]({encapsulation:0,styles:[[".dropdown-menu[_ngcontent-%COMP%] > .disabled[_ngcontent-%COMP%] > a[_ngcontent-%COMP%]{pointer-events:auto;cursor:default!important}"]],data:{}});function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,7,null,null,null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,6,"button",[["class","btn btn-sm btn-primary"],["type","button"]],null,[[null,"click"]],function(t,e,n){var r=!0,i=t.component;return"click"===e&&(r=!1!==a["\u0275nov"](t,4).onClick()&&r),"click"===e&&(r=!1!==i.useClickAction(t.context.ngIf)&&r),r},null,null)),a["\u0275did"](2,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](3,{disabled:0}),a["\u0275did"](4,16384,null,0,i.m,[i.l,i.a,[8,null],a.Renderer2,a.ElementRef],{preserveFragment:[0,"preserveFragment"],routerLink:[1,"routerLink"]},null),(t()(),a["\u0275eld"](5,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](7,null,["",""]))],function(t,e){var n=e.component,a=t(e,3,0,n.disableSelectionAction(e.context.ngIf));t(e,2,0,"btn btn-sm btn-primary",a),t(e,4,0,e.context.ngIf.preserveFragment?"":null,n.useRouterLink(e.context.ngIf))},function(t,e){t(e,5,0,a["\u0275inlineInterpolate"](1,"fa fa-fw ",e.context.ngIf.icon,"")),t(e,7,0,e.context.ngIf.name)})}function l(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.component.onlyDropDown)})}function d(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"span",[["class","sr-only"]],null,null,null,null,null))],null,null)}function f(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,6,"button",[["class","btn btn-sm btn-primary dropdown-toggle dropdown-toggle-split"],["dropdownToggle",""],["type","button"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,1).onClick()&&r),r},null,null)),a["\u0275did"](1,147456,null,0,s.g,[a.ChangeDetectorRef,s.c,a.ElementRef,a.Renderer2,s.f],null,null),(t()(),a["\u0275and"](16777216,null,null,1,null,l)),a["\u0275did"](3,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](4,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,d)),a["\u0275did"](6,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.onlyDropDown),t(e,6,0,!n.onlyDropDown)},function(t,e){t(e,0,0,!0,a["\u0275nov"](e,1).isDisabled,a["\u0275nov"](e,1).isOpen)})}function p(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,8,null,null,null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,7,"li",[["data-toggle","tooltip"],["role","menuitem"]],[[8,"title",0]],null,null,null,null)),a["\u0275did"](2,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](3,{disabled:0}),(t()(),a["\u0275eld"](4,0,null,null,4,"a",[["class","dropdown-item"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var r=!0,i=t.component;return"click"===e&&(r=!1!==a["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&r),"click"===e&&(r=!1!==i.useClickAction(t.context.$implicit)&&r),r},null,null)),a["\u0275did"](5,671744,null,0,i.o,[i.l,i.a,r.LocationStrategy],{preserveFragment:[0,"preserveFragment"],routerLink:[1,"routerLink"]},null),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,["",""]))],function(t,e){var n=e.component,r=a["\u0275inlineInterpolate"](1,"",n.toClassName(e.context.$implicit.name),""),i=t(e,3,0,n.disableSelectionAction(e.context.$implicit));t(e,2,0,r,i),t(e,5,0,e.context.$implicit.preserveFragment?"":null,n.useRouterLink(e.context.$implicit))},function(t,e){t(e,1,0,a["\u0275inlineInterpolate"](1,"",e.component.useDisableDesc(e.context.$implicit),"")),t(e,4,0,a["\u0275nov"](e,5).target,a["\u0275nov"](e,5).href),t(e,6,0,a["\u0275inlineInterpolate"](1,"fa fa-fw ",e.context.$implicit.icon,"")),t(e,8,0,e.context.$implicit.name)})}function h(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"ul",[["class","dropdown-menu"],["role","menu"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,p)),a["\u0275did"](2,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.dropDownActions)},null)}function g(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,16777216,null,null,8,"div",[["class","btn-group"],["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),a["\u0275prd"](512,null,s.f,s.f,[]),a["\u0275did"](2,212992,null,0,s.c,[a.ElementRef,a.Renderer2,a.ViewContainerRef,o.a,s.a,s.f],null,null),(t()(),a["\u0275and"](16777216,null,null,1,null,c)),a["\u0275did"](4,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,f)),a["\u0275did"](6,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,h)),a["\u0275did"](8,16384,null,0,s.d,[s.f,a.ViewContainerRef,a.TemplateRef],null,null)],function(t,e){var n=e.component;t(e,2,0),t(e,4,0,n.getCurrentButton()),t(e,6,0,n.showDropDownActions())},function(t,e){t(e,0,0,a["\u0275nov"](e,2).dropup,a["\u0275nov"](e,2).isOpen,a["\u0275nov"](e,2).isOpen&&a["\u0275nov"](e,2).isBs4)})}},Nia1:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("3/HP")),a(n("FLvf")),a(n("2V7f")),a(n("fktO")),a(n("QHrR")),a(n("i3PA"))},O5R2:function(t,e,n){"use strict";n.r(e);var a=n("6blF"),r=n("VnD/");a.a.prototype.filter=function(t,e){return Object(r.a)(t,e)(this)}},ODdm:function(t,e,n){"use strict";t.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},OIYi:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}})}()},OLbh:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("gIcY"),r=function(){function t(t){this.modalRef=t,this.boundCancel=this.cancel.bind(this),this.confirmationForm=new a.k({})}return t.prototype.ngOnInit=function(){this.bodyContext=this.bodyContext||{},this.bodyContext.$implicit=this.bodyData},t.prototype.cancel=function(){this.modalRef.hide(),this.onCancel&&this.onCancel()},t.prototype.stopLoadingSpinner=function(){this.confirmationForm.setErrors({cdSubmitButton:!0})},t}()},"OWV/":function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="pt-BR">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Alternar navega\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Painel de controle</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Cluster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Hosts</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitores</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSDs</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Configura\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>Mapa CRUSH</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>M\xf3dulos do gerenciador</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Registros</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Alertas</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Pools</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Bloco</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Imagens</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Espelhamento</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Sistemas de arquivos</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Gateway de Objetos</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemons</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Usu\xe1rios</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Compartimentos</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Recuperando dados\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> de\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Aguarde...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Exibindo dados armazenados em cache anteriormente\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n para \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>N\xe3o foi poss\xedvel carregar os dados\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> de\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Verifique a sa\xfade do cluster.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Voltar</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Selecionar Idioma</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Carregando dados do painel...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Consulte a\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documenta\xe7\xe3o\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre como\n configurar e habilitar a funcionalidade de monitoramento.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>O Painel de Controle do Grafana n\xe3o existe. Consulte a\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documenta\xe7\xe3o\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre como\n adicionar pain\xe9is de controle ao Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Seletor de Hor\xe1rio do Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Redefinir Configura\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Falha ao carregar dados.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>selecionado(s)</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>encontrado(s)</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>total</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Editar</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nome</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Descri\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Descri\xe7\xe3o extensa</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Padr\xe3o</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Padr\xe3o do daemon</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Servi\xe7os</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Valores</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>O valor inserido \xe9 muito alto! Ele n\xe3o pode ser maior do que \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>O valor inserido \xe9 muito baixo! Ele n\xe3o deve ser menor do que \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Salvar</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>Visualizador de mapa CRUSH</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Lista de Hosts</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Desempenho Geral</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Nenhuma entrada encontrada</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Registros do Cluster</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Registros de Auditoria</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Carregando configura\xe7\xe3o...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>N\xe3o foi poss\xedvel carregar a configura\xe7\xe3o.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Editar m\xf3dulo do gerenciador</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>O valor inserido n\xe3o \xe9 um UUID v\xe1lido. Ex.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>O valor inserido precisa ser um endere\xe7o IP v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Este campo \xe9 obrigat\xf3rio.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>O valor inserido \xe9 muito alto! Ele deve ser menor ou igual a \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>O valor inserido \xe9 muito baixo! Ele deve ser maior ou igual a \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>O valor inserido precisa ser um n\xfamero.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>O valor inserido precisa ser um n\xfamero ou decimal.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Atualizar</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Status</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>ID do Cluster</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap modificado</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>\xe9poca de monmap</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>con obrigat\xf3rio</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>mon obrigat\xf3rio</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>No Quorum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>N\xe3o est\xe1 no Quorum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Cancelar</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Deseja realmente \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> o(a) \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> selecionado(a)?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Sim, desejo.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Flags OSD de todo o Cluster</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Enviar</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Avan\xe7ado...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Prioridade de Recupera\xe7\xe3o de OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Prioridade</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Personalizar valores de prioridade</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Este campo \xe9 obrigat\xf3rio!</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>O valor inserido \xe9 muito alto! Ele n\xe3o pode ser maior do que \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>O valor inserido \xe9 muito baixo! Ele n\xe3o deve ser menor do que \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Reponderar OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>O valor precisa ser entre 0 e 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Reponderar</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>Remo\xe7\xe3o de OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Profundo } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Voc\xea est\xe1 prestes a aplicar uma \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>remo\xe7\xe3o ao\n OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {profundo} }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Lista de OSDs</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> ser\xe1 marcado como\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se voc\xea continuar.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>N\xe3o \xe9 seguro destruir o OSD!</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> ser\xe1\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se voc\xea continuar.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Detalhes</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Valor</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Fechar</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Excluir</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Sa\xfade</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Estat\xedsticas</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Consulte a \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documenta\xe7\xe3o\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre como configurar e habilitar a funcionalidade de gerenciamento do NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Clientes</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Qualquer cliente pode acessar</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Endere\xe7os</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Campo obrigat\xf3rio</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Deve conter um ou mais valores separados por v\xedrgula</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Por exemplo:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Tipo de Acesso</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Executar Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Adicionar clientes</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Carregando...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- N\xe3o h\xe1 clusters dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Selecionar cluster --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Adicionar daemon</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Backend de Armazenamento</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- N\xe3o h\xe1 pools de dados dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Selecionar backend de armazenamento --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Usu\xe1rio do Gateway de Objetos</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- N\xe3o h\xe1 usu\xe1rios dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Selecionar usu\xe1rio do gateway de objetos --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>ID de Usu\xe1rio do CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- N\xe3o h\xe1 clientes dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Selecionar cliente do cephx --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nome do CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>R\xf3tulo de Seguran\xe7a</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Habilitar r\xf3tulo de seguran\xe7a</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>Caminho do CephFS</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>O caminho precisa come\xe7ar com \'/\' e pode ser seguido de uma palavra</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Novo diret\xf3rio ser\xe1 criado</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Caminho</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>O caminho pode ser apenas uma \'/\' ou uma palavra</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Novo compartimento ser\xe1 criado</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protocolo NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Tag NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Acesso alternativo \xe0s montagens do \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (n\xe3o deve ter / \xe0 esquerda).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Clientes n\xe3o podem montar subdiret\xf3rios (ou seja, se Tag = foo, o cliente n\xe3o poder\xe1 montar foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>Ao usar op\xe7\xf5es diferentes de Tag, o mesmo Caminho pode ser exportado v\xe1rias vezes.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>A posi\xe7\xe3o que esta exporta\xe7\xe3o de \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> ocupa\n no \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (deve ser exclusiva).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>Ao usar op\xe7\xf5es diferentes de Pseudo, o mesmo Caminho pode ser exportado v\xe1rias vezes.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- N\xe3o h\xe1 tipos de acesso dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Selecionar tipo de acesso --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- N\xe3o h\xe1 squashes dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>--Selecionar que tipo de squash de ID de usu\xe1rio ser\xe1 executado --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protocolo de Transporte</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Bem-vindo ao Ceph!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Nome de usu\xe1rio \xe9 obrigat\xf3rio</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Senha \xe9 obrigat\xf3ria</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Login</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>O usu\xe1rio n\xe3o existe no Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Retorne \xe0 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>P\xe1gina de Login\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Seu logout ser\xe1 efetuado do Provedor de Identidade quando voc\xea repetir o login.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Proibido</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Voc\xea n\xe3o tem permiss\xe3o para ver o que est\xe1 procurando.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>N\xe3o foi poss\xedvel localizar o que voc\xea est\xe1 procurando</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Remover tudo</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Notifica\xe7\xf5es Recentes</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>N\xe3o h\xe1 tarefas em segundo plano.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Tarefas em Segundo Plano</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Ajuda</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Documenta\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>Sobre</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Configura\xe7\xf5es do Painel de Controle</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Gerenciamento de usu\xe1rios</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Usu\xe1rio que efetuou login</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Efetuar login como\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Efetuar logout</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nome...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>O nome escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Descri\xe7\xe3o...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Permiss\xf5es</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Fun\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nome de usu\xe1rio</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Senha</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Confirmar senha</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>A confirma\xe7\xe3o de senha n\xe3o corresponde \xe0 senha.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Nome completo</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>E-mail</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>E-mail inv\xe1lido.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Voc\xea est\xe1 prestes a remover as permiss\xf5es de "leitura/atualiza\xe7\xe3o de usu\xe1rio" do seu pr\xf3prio usu\xe1rio.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Se voc\xea continuar, n\xe3o poder\xe1 mais adicionar ou remover fun\xe7\xf5es de nenhum usu\xe1rio.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Deseja realmente continuar?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Contadores de desempenho n\xe3o dispon\xedveis</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Atributos (mapa OSD)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Metadados n\xe3o dispon\xedveis</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadados</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Contador de desempenho</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histograma n\xe3o dispon\xedvel: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Grava\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Leituras</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histograma</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Detalhes de Desempenho</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Valores atuais</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Tipo</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>M\xedn.</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>M\xe1x.</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Flags</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Origem</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>N\xedvel</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Pode ser atualizado em tempo de execu\xe7\xe3o (edit\xe1vel)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Tags</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Valores de enum</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Consulte tamb\xe9m</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Status do Cluster</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Daemons do Gerenciador</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Gateways de Objetos</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Servidores de Metadados</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>Gateways iSCSI</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>IOPS do Cliente</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Throughput do Cliente</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Leitura/Grava\xe7\xe3o do Cliente</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Throughput de Recupera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Remo\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Desempenho</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Capacidade Bruta</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objetos</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>PGs por OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Status do PG</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Capacidade</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consulte os \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Registros\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> para obter mais detalhes.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Posi\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Clientes: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Mover imagem para o lixo</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Para mover \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> para o lixo,\n clique em \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mover Imagem\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Se preferir, escolha uma data de vencimento.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>Vencimento da prote\xe7\xe3o em</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>N\xc3O PROTEGIDO</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Formato de data incorreto. Use "AAAA-MM-DD HH:mm:ss".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>A prote\xe7\xe3o j\xe1 venceu. Escolha uma data no futuro ou deixe-a vazia.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Mover Imagem</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Vis\xe3o geral</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Destinos</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Autentica\xe7\xe3o de Descoberta</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Usu\xe1rio</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Os nomes de usu\xe1rio devem ter entre 8 e 64 caracteres e\n apenas podem conter letras, \'.\', \'@\', \'-\', \'_\' ou \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Usu\xe1rio M\xfatuo</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Senha M\xfatua</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Consulte a \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documenta\xe7\xe3o\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre como configurar e habilitar a funcionalidade de gerenciamento de Destinos iSCSI.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informa\xe7\xf5es dispon\xedveis:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>Destinos iSCSI n\xe3o dispon\xedveis</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Dispon\xedvel apenas para imagens RBD com \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>diff r\xe1pido\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> habilitado\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Pool de Dados</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Criado</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Tamanho</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Tamanho do objeto</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Recursos</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Aprovisionado</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/A</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Total aprovisionado</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Unidade de distribui\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Total de distribui\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Pai</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Prefixo do nome do bloco</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Ordem</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Instant\xe2neos</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Imagem</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Esta configura\xe7\xe3o substitui o valor global</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Global</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Este \xe9 o valor global. Nenhum valor para esta op\xe7\xe3o foi definido para esta imagem.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' e \'@\' n\xe3o s\xe3o permitidos.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- N\xe3o h\xe1 pools de RBD dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Selecionar pool --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Usar pool de dados dedicado</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Pool de dados</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Pool dedicado que armazena os dados de objetos do RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>ex. 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Voc\xea precisa aumentar o tamanho.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Avan\xe7ado</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Distribui\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Unidade de distribui\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Selecionar unidade de distribui\xe7\xe3o --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Este campo \xe9 obrigat\xf3rio porque o total de distribui\xe7\xf5es foi definido!</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>A unidade de distribui\xe7\xe3o \xe9 maior do que o tamanho do objeto.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Total de distribui\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Este campo \xe9 obrigat\xf3rio porque a unidade de distribui\xe7\xe3o foi definida!</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>O total de distribui\xe7\xf5es deve ser maior do que 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Instant\xe2neo do RBD\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Renomear} other {Criar} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Instant\xe2neo\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>PROTEGIDO</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>N\xc3O PROTEGIDO</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Voc\xea est\xe1 prestes a fazer rollback</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Purgar Lixo</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Para purgar, selecione uma ou Todas as imagens e clique em</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Pool:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nome do pool...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Tudo</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Restaurar Imagem</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Para restaurar</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>digite o novo nome da imagem e clique em</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Novo Nome</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Venceu em</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Protegido at\xe9</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Esta imagem est\xe1 protegida at\xe9 \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Lixo</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologia iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>N\xe3o costuma ser necess\xe1rio mudar o valor padr\xe3o destes par\xe2metros.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Configura\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Confirmar</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Configura\xe7\xf5es Avan\xe7adas</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>IQN de Destino</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN tem padr\xe3o incorreto.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Um IQN tem a seguinte nota\xe7\xe3o \'iqn.$year-$month.$reversedAddress:$definedName\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Por exemplo: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Mais informa\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Este destino tem configura\xe7\xf5es avan\xe7adas modificadas.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portais</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Pelo menos \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways s\xe3o necess\xe1rios.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Adicionar portal</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Esta imagem tem configura\xe7\xf5es modificadas.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Adicionar imagem</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Autentica\xe7\xe3o ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Iniciadores</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Iniciador</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>IQN do Cliente</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>O IQN do Iniciador precisa ser exclusivo.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Os nomes de usu\xe1rio devem ter entre 8 e 64 caracteres e\n apenas podem conter letras, \'.\', \'@\', \'-\', \'_\' ou \':\'.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>O iniciador pertence a um grupo. As imagens ser\xe3o configuradas no grupo.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Nenhum item adicionado.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Adicionar iniciador</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Grupos</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Grupo</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Adicionar grupo</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Configura\xe7\xe3o de RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Remova o valor de configura\xe7\xe3o local. No lugar dele, o valor de configura\xe7\xe3o pai ser\xe1 herdado e usado.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>O valor m\xednimo \xe9 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Problemas</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Sincronizando</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Pronto</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Editar modo de espelho do pool</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Para editar o modo de espelho do pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, selecione o novo modo na lista e clique em\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Atualizar\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Modo</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Clusters de peer devem ser removidos antes de desabilitar o espelho.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n peer de espelho do pool\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Editar} other {Adicionar} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> os atributos\n de peer de espelho do pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> e clique em \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Enviar\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nome do Cluster</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>O nome do cluster n\xe3o \xe9 v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>ID do CephX</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>ID do CephX...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>O ID do CephX n\xe3o \xe9 v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Endere\xe7os do Monitor</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Endere\xe7os delimitados por v\xedrgula...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>O endere\xe7o de monitoria n\xe3o \xe9 v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>Chave do CephX</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Chave codificada com base64...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>A chave do CephX deve ser codificada com base64.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Lista de Pools</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>O nome pode conter apenas caracteres alfanum\xe9ricos, tra\xe7os e sublinhados.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>O nome do perfil de c\xf3digo de elimina\xe7\xe3o escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Plug-in</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Pacotes de dados (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Deve ser igual ou maior do que 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Pacotes de codifica\xe7\xe3o (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Deve ser igual ou maior do que 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Estimador de durabilidade (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Localidade (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Dom\xednio de falha do Crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Localidade do Crush</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Nenhum</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>T\xe9cnica</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Tamanho do pacote</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Raiz do Crush</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Classe do dispositivo do Crush</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>qualquer</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Diret\xf3rio</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>O nome do pool do Ceph escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Tipo de pool</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Selecionar tipo de pool --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Grupos de posicionamento</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Pelo menos um grupo de posicionamento \xe9 necess\xe1rio!</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Seu cluster n\xe3o pode processar tantos PGs. Recalcule a quantidade de PG necess\xe1ria.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Ajuda no c\xe1lculo</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>As configura\xe7\xf5es de PGs atuais foram calculadas para voc\xea. Verifique\n se os valores atendem \xe0s suas necessidades antes de enviar.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Conjunto de regras do Crush</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Selecionar regra de crush --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Regra de Crush</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Etapas do Crush</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Imposs\xedvel usar a regra no cluster atual porque ela tem\n poucos OSDs para atender ao OSD m\xednimo necess\xe1rio para esta regra.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Tamanho replicado</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>M\xednimo: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>M\xe1ximo: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>O tamanho especificado est\xe1 fora da faixa. Um valor de\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> a \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> \xe9 v\xe1lido.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Perfil do c\xf3digo de elimina\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- N\xe3o h\xe1 perfis de c\xf3digo de elimina\xe7\xe3o dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Selecionar perfil do c\xf3digo de elimina\xe7\xe3o --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>Sobregrava\xe7\xf5es de EC</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Aplicativos</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Compacta\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algoritmo</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- N\xe3o h\xe1 algoritmos de compacta\xe7\xe3o de elimina\xe7\xe3o dispon\xedveis --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Tamanho m\xednimo do blob</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>ex. 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>O valor deve ser maior do que 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Tamanho m\xe1ximo do blob</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>ex. 512 KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>O valor deve ser maior do que o tamanho m\xednimo do blob</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Taxa</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Taxa de compacta\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>O valor deve ser entre 0.0 e 1.0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Imposs\xedvel criar um pool de RBD com \'/\' no nome.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Altere o nome ou remova o \'rbd\' da lista de aplicativos.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Detalhes das Camadas do Cache</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Consulte a \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documenta\xe7\xe3o\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre como configurar e habilitar a funcionalidade de gerenciamento do Gateway de Objetos.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Lista de Daemons</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Contadores de Desempenho</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Carregando dados do compartimento...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>N\xe3o foi poss\xedvel carregar os dados do compartimento.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>O valor n\xe3o \xe9 v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Propriet\xe1rio</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Selecionar usu\xe1rio --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Tipo de \xedndice</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Regra de posicionamento</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Marcador</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Marcador m\xe1ximo</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Vers\xe3o</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Vers\xe3o master</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Hor\xe1rio da modifica\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Grupo de zonas</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Cota do compartimento</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Habilitado</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Tamanho m\xe1ximo</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Ilimitado</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>M\xe1ximo de objetos</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Selecionar nome de usu\xe1rio --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Gerar chave automaticamente</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Chave de acesso</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Chave secreta</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Endere\xe7o de e-mail</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Suspenso</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Sistema</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {N\xe3o} 1 {Sim} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>M\xe1ximo de compartimentos</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Subusu\xe1rios</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Recursos</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Cota do usu\xe1rio</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Mostrar</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Chaves</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Selecionar tipo --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Permiss\xe3o</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Selecionar permiss\xe3o --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Subusu\xe1rio</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>O ID de subusu\xe1rio escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>leitura, grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>completo</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Chave Swift</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Gerar segredo automaticamente</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Carregando dados do usu\xe1rio...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>N\xe3o foi poss\xedvel carregar os dados do usu\xe1rio.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>O ID de usu\xe1rio escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Este n\xe3o \xe9 um endere\xe7o de e-mail v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>O endere\xe7o de e-mail escolhido j\xe1 est\xe1 em uso.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>M\xe1x. de compartimentos</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>O valor inserido deve ser &gt;= 0.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>Chave S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>N\xe3o h\xe1 subusu\xe1rios.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>N\xe3o h\xe1 chaves.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>N\xe3o h\xe1 recursos.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Tamanho ilimitado</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Tamanho m\xe1x.</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Objetos ilimitados</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>M\xe1x. de objetos</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Atual</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Autentica\xe7\xe3o de descoberta atualizada</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>N\xe3o h\xe1 portais dispon\xedveis.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>N\xe3o h\xe1 imagens dispon\xedveis.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>N\xe3o h\xe1 imagens dispon\xedveis. Adicione uma imagem ao destino.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>N\xe3o h\xe1 iniciadores dispon\xedveis. Adicione um iniciador ao destino.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Destino</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Estado</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Bytes de Leitura</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Bytes de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Op. de Leitura</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Op. de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O Desde</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Inst\xe2ncia</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nome de host</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Problema</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Andamento</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Desabilitado</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Modo de Edi\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Adicionar Peer</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Editar Peer</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Excluir Peer</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Leader</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>N\xba Local</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>N\xba Remoto</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>espelhar peer</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Chave</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Nivelamento profundo</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Disposi\xe7\xe3o em camadas</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Bloqueio exclusivo</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Mapa de objetos (requer bloqueio exclusivo)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Registro em di\xe1rio (requer bloqueio exclusivo)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Rollback de instant\xe2neo do RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Fazer Rollback</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Instant\xe2neo do RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Exclu\xeddo \xe0(s)</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>tipo</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>estado</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>vers\xe3o</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>raiz</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Posi\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Atividade</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inodes</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Uso</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Daemons de standby</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\xc9 poss\xedvel atualizar o valor em temo de execu\xe7\xe3o.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Daemons/clientes n\xe3o extraem este valor do\n banco de dados de configura\xe7\xe3o do monitor. A configura\xe7\xe3o desta op\xe7\xe3o n\xe3o \xe9 permitida por meio de \'ceph config\n set ...\'. Essa op\xe7\xe3o deve ser configurada por meio do ceph.conf ou da\n linha de comando.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>A op\xe7\xe3o entra em vigor apenas durante a inicializa\xe7\xe3o do daemon.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>A op\xe7\xe3o afeta apenas a cria\xe7\xe3o do cluster.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>A op\xe7\xe3o afeta apenas a cria\xe7\xe3o do daemon.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Op\xe7\xe3o de configura\xe7\xe3o \n <x id="INTERPOLATION" equiv-text="{{name}}"/> atualizada\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Servi\xe7o</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Valor atual</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Edit\xe1vel</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Op\xe7\xf5es atualizadas para o m\xf3dulo &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Habilitar</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Desabilitar</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Reconectando, aguarde...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Endere\xe7o P\xfablico</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Sess\xf5es Abertas</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>N\xe3o Entrada</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>Os OSDs que j\xe1 foram marcados como sa\xedda n\xe3o ser\xe3o remarcados como entrada ao serem iniciados</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>N\xe3o Sa\xedda</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>Os OSDs n\xe3o ser\xe3o automaticamente marcados como sa\xedda ap\xf3s o intervalo configurado</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>N\xe3o Ativo</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>Os OSDs n\xe3o podem ser iniciados</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>N\xe3o Inativo</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Os relat\xf3rios de falha de OSD est\xe3o sendo ignorados, portanto, os monitores n\xe3o marcar\xe3o os OSDs como inativos</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pausar</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Pausa leituras e grava\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Sem Remo\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Remo\xe7\xe3o desabilitada</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Sem Remo\xe7\xe3o Profunda</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Remo\xe7\xe3o Profunda desabilitada</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Sem Provisionamento</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Provisionamento de PGs suspenso</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Sem Recupera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Recupera\xe7\xe3o de PGs suspensa</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Classifica\xe7\xe3o Bit a Bit</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Usar classifica\xe7\xe3o bit a bit</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Snapdirs Purgados</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSDs converteram snapsets</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Exclus\xf5es de Recupera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Exclus\xf5es realizadas durante a recupera\xe7\xe3o, e n\xe3o o emparelhamento</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Limite F\xedsico do Registro de PG</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Atribui um limite f\xedsico ao tamanho do registro de PG</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Flags OSD Atualizadas</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>sa\xedda</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>entrada</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>inativo</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Marcar</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD perdido</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>marcado como perdido</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Purgar</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>purgado</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>destruir</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>destru\xeddo</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>PGs</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Bytes de leitura</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Bytes de grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Op. de leitura</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Op. de grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marcar OSD como \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marcar como \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>M\xe1x. de Provisionamentos</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>M\xe1x. Recupera\xe7\xe3o Ativo</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>M\xe1x. Recupera\xe7\xe3o Inicializa\xe7\xe3o \xdanica</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Suspens\xe3o de Recupera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Personalizado</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Prioridade de velocidade de recupera\xe7\xe3o de OSD &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot atualizada;\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> foi inicializado no seguinte OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Tarefa</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Gravidade</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Iniciado</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Atualizado</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Usado</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Disp.</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Limpar</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>Em funcionamento</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Aviso</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Desconhecido</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>ativo</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>sem sistemas de arquivos</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>ativo</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>standby</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/a</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>daemon ativo</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>O servi\xe7o NFS Ganesha n\xe3o est\xe1 configurado.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transporte</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>Usu\xe1rio do CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>Sistema de Arquivos do CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(herdado da configura\xe7\xe3o global)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>herdado da configura\xe7\xe3o global</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Selecionar que tipo de squash de ID de usu\xe1rio ser\xe1 executado --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>N\xe3o h\xe1 daemons dispon\xedveis.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Modo de Cache</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Tempo M\xedn. Expuls\xe3o</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Tempo M\xedn. Descarregamento</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>M\xe1x. de Bytes de Destino</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>M\xe1x. de Objetos de Destino</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Nenhum aplicativo adicionado</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Limite de aplicativos atingido</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Um pool apenas pode ter at\xe9 quatro defini\xe7\xf5es de aplicativos.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Caracteres permitidos: \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>Tamanho m\xe1ximo de 128 caracteres</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtrar ou adicionar aplicativos</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Adicionar aplicativo</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>perfil de c\xf3digo de elimina\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Tamanho da R\xe9plica</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\xdaltima Altera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Perfil Codificado para Elimina\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Conjunto de Regras do Crush</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Bytes de grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>compartimento</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Compartimento do Gateway de Objetos &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; atualizado\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Compartimento do Gateway de Objetos &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; criado\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>compartimentos</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>usu\xe1rio</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Usu\xe1rio do Gateway de Objetos &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot; atualizado\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Usu\xe1rio do Gateway de Objetos &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot; criado\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>usu\xe1rios</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Escopo</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Leitura</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Criar</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Fun\xe7\xe3o \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' criada\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Fun\xe7\xe3o \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' atualizada\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Fun\xe7\xe3o do Sistema</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Fun\xe7\xe3o \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' exclu\xedda\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Usu\xe1rio &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; criado\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Atualizar usu\xe1rio</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Continuar</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Voc\xea foi automaticamente desconectado porque suas fun\xe7\xf5es foram alteradas.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Usu\xe1rio &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; atualizado\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Usu\xe1rio &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; exclu\xeddo\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Falha ao excluir o usu\xe1rio &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>No momento, voc\xea est\xe1 conectado como &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Cada objeto \xe9 dividido em partes de pacotes de dados, cada uma armazenada em um OSD diferente.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Calcule os pacotes de codifica\xe7\xe3o de cada objeto e armazene-os em diferentes OSDs.\n O n\xfamero de pacotes de codifica\xe7\xe3o \xe9 tamb\xe9m o n\xfamero de OSDs que podem ficar inativos sem perda de dados.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>O plug-in jerasure \xe9 o mais gen\xe9rico e flex\xedvel,\n al\xe9m de ser o padr\xe3o para pools codificados para elimina\xe7\xe3o do Ceph.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>A t\xe9cnica mais flex\xedvel \xe9 reed_sol_van: ela \xe9 suficiente para definir k\n e m. A t\xe9cnica cauchy_good pode ser mais r\xe1pida, mas voc\xea precisa escolher o tamanho do pacote\n com cuidado. Todos os reed_sol_r6_op, liberation, blaum_roth e liber8tion s\xe3o equivalentes ao RAID6\n no sentido de que s\xf3 podem ser configurados com m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>A codifica\xe7\xe3o ser\xe1 feita em pacotes de tamanho de bytes um de cada vez.\n A escolha do tamanho do pacote certo \xe9 dif\xedcil.\n A documenta\xe7\xe3o do jerasure cont\xe9m informa\xe7\xf5es completas sobre este t\xf3pico.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Com o plug-in jerasure, quando um objeto codificado para elimina\xe7\xe3o \xe9 armazenado em\n v\xe1rios OSDs, a recupera\xe7\xe3o ap\xf3s a perda de um OSD requer a leitura de todos os outros.\n Por exemplo, se o jerasure for configurado com k=8 e m=4, a perda de um OSD exigir\xe1 a leitura\n dos outros onze para fazer o reparo.\n\n O plug-in de c\xf3digo de elimina\xe7\xe3o lrc cria pacotes locais de paridade para conseguir recuperar usando\n menos OSDs. Por exemplo, se o lrc for configurado com k=8, m=4 e l=4, ele criar\xe1\n um pacote de paridade adicional para cada quatro OSDs. Quando um \xfanico OSD \xe9 perdido, ele pode ser\n recuperado apenas com quatro OSDs, em vez de onze.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Agrupe os pacotes de codifica\xe7\xe3o e dados em conjuntos de localidades com tamanho. Por exemplo,\n no caso de k=4 e m=2, quando locality=3, dois grupos de tr\xeas s\xe3o criados. Cada conjunto pode\n ser recuperado sem a leitura dos pacotes do outro conjunto.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>O tipo do compartimento de crush em que cada conjunto de pacotes definido\n por l ser\xe1 armazenado. Por exemplo, se isso for definido como rack, cada grupo de pacotes l ser\xe1\n colocado em um rack diferente. Isso \xe9 usado para criar uma etapa da regra CRUSH, como a etapa de escolha do\n rack. Se isso n\xe3o for definido, esse tipo de agrupamento n\xe3o ser\xe1 feito.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>O plug-in isa encapsula a biblioteca ISA. Ele apenas \xe9 executado em processadores Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>O plug-in ISA vem em dois formatos de Reed Solomon.\n Se reed_sol_van for definido, ele ser\xe1 Vandermonde, se cauchy for definido, ele ser\xe1 Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>O plug-in shec encapsula a biblioteca m\xfaltipla SHEC.\n Ele permite ao ceph recuperar dados com mais efici\xeancia do que os c\xf3digos de Reed Solomon.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>O n\xfamero de pacotes de paridade, em que cada um inclui cada pacote de dados em sua\n faixa de c\xe1lculo. O n\xfamero \xe9 usado como estimador de durabilidade. Por exemplo, se c=2,\n 2 OSDs podem ficar inativos sem perda de dados.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>O nome do compartimento de crush usado para a primeira etapa da regra CRUSH.\n Por exemplo, a etapa assumir o padr\xe3o.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Verifique se n\xe3o h\xe1 dois pacotes em um compartimento com o mesmo dom\xednio de\n falha. Por exemplo, se o dom\xednio de falha for um host, n\xe3o armazene dois pacotes no mesmo\n host. Isso \xe9 usado para criar uma etapa da regra CRUSH, como a etapa de escolha do host folha.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Restrinja o posicionamento a dispositivos de uma classe espec\xedfica\n (ex. ssd ou hdd), usando nomes de classe de dispositivo crush no mapa CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Defina o nome do diret\xf3rio do qual o plug-in de c\xf3digo de elimina\xe7\xe3o \xe9 carregado.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Permite todas as opera\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Permite apenas as opera\xe7\xf5es que n\xe3o modificam o servidor</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>N\xe3o permite opera\xe7\xf5es de leitura ou grava\xe7\xe3o, mas permite qualquer outra opera\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>N\xe3o permite leitura, grava\xe7\xe3o ou qualquer opera\xe7\xe3o que modifica os atributos do arquivo ou o conte\xfado do diret\xf3rio</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>N\xe3o permite nenhum tipo de acesso</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Selecionar prioridade --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Baixa</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Alta</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\xdaltimos 5 minutos</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\xdaltimos 15 minutos</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\xdaltimos 30 minutos</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\xdaltima 1 hora (Padr\xe3o)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\xdaltimas 3 horas</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\xdaltimas 6 horas</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\xdaltimas 12 horas</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\xdaltimas 24 horas</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Ontem</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Hoje</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>At\xe9 agora hoje</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Antes de ontem</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>\xdaltimos 2 dias</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Este dia na semana passada</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>Semana anterior</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Esta semana</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>At\xe9 agora nesta semana</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>\xdaltimos 7 dias</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>M\xeas anterior</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Este m\xeas</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>At\xe9 agora neste m\xeas</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>\xdaltimos 30 dias</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>\xdaltimos 90 dias</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>\xdaltimos 6 meses</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>\xdaltimo ano</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>Ano anterior</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Este ano</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>At\xe9 agora neste ano</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>\xdaltimos 2 anos</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>\xdaltimos 5 anos</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informa\xe7\xf5es</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Nenhum item selecionado.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Desmarcar item para selecionar novamente</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Limite de sele\xe7\xe3o atingido</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Tags de filtro</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Adicionar selo</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>N\xe3o h\xe1 itens dispon\xedveis.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Adicionar</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Clonar</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Copiar</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Remo\xe7\xe3o Profunda</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Destruir</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Nivelar</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Marcar como Inativo</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Marcar como Entrada</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Marcar como Perdido</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Marcar como Sa\xedda</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Proteger</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Renomear</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Restaurar</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>Mover para Lixo</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Cancelar prote\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Exclu\xeddo</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Clonado</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Copiado</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Sim</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>N\xe3o</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Qualidade do Servi\xe7o</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>Limite de BPS</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>O limite de bytes por segundo de E/S desejado.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>Limite de IOPS</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>O limite de opera\xe7\xf5es por segundo de E/S desejado.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>Limite de BPS de Leitura</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>O limite de bytes por segundo de leitura desejado.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>Limite de IOPS de Leitura</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>O limite de opera\xe7\xf5es por segundo de leitura desejado.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Limite de BPS de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>O limite de bytes por segundo de grava\xe7\xe3o desejado.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Limite de IOPS de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>O limite de opera\xe7\xf5es por segundo de grava\xe7\xe3o desejado.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>Intermit\xeancia de BPS</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>O limite de bytes de E/S de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>Intermit\xeancia de IOPS</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>O limite de opera\xe7\xf5es de E/S de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Intermit\xeancia de BPS de Leitura</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>O limite de bytes de leitura de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Intermit\xeancia de IOPS de Leitura</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>O limite de opera\xe7\xf5es de leitura de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Intermit\xeancia de BPS de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>O limite de bytes de grava\xe7\xe3o de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Intermit\xeancia de IOPS de Grava\xe7\xe3o</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>O limite de opera\xe7\xf5es de grava\xe7\xe3o de intermit\xeancia desejado.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Falha ao \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Executando</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>executar</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Executado</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>tarefa desconhecida</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Criando</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>criar</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Atualizando</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>atualizar</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Excluindo</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>excluir</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Instant\xe2neo do RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>modo de espelho para o pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>espelhar peer para o pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Nome j\xe1 foi usado por \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Nome j\xe1 foi usado por \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Nome j\xe1 foi usado por \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> cont\xe9m instant\xe2neos.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Clonando</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>clonar</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>O instant\xe2neo de \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> deve ser protegido.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Copiando</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>copiar</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Nivelando</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>nivelar</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Nivelado</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Nome j\xe1 foi usado por \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Imposs\xedvel cancelar a prote\xe7\xe3o de \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque h\xe1 imagens filho.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Imposs\xedvel excluir \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque est\xe1 protegido.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Fazendo rollback</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>rollback</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Rollback feito</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Movendo</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>mover</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>Movido</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>imagem \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' para jogar no lixo\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Imagem n\xe3o encontrada.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Restaurando</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>restaurar</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Restaurado</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>imagem \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' para \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Nome da imagem \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' j\xe1 est\xe1 em uso.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>imagem \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>Purgando</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>purgar</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Purgado</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>todos os pools</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>imagens de \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Imposs\xedvel desabilitar espelhamento porque ele cont\xe9m um peer.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>perfil de c\xf3digo de elimina\xe7\xe3o \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>destino \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},OXbD:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha"),s=a.global.defaultColor;function o(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}a._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:s,borderColor:s,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),t.exports=r.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:o,inXRange:o,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,r=this._chart.ctx,o=e.pointStyle,u=e.rotation,c=e.radius,l=e.x,d=e.y;e.skip||(void 0===t||n.x>=t.left&&1.01*t.right>=n.x&&n.y>=t.top&&1.01*t.bottom>=n.y)&&(r.strokeStyle=e.borderColor||s,r.lineWidth=i.valueOrDefault(e.borderWidth,a.global.elements.point.borderWidth),r.fillStyle=e.backgroundColor||s,i.canvas.drawPoint(r,o,c,l,d,u))}})},OZfm:function(t,e,n){"use strict";n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o}),n.d(e,"c",function(){return u}),n.d(e,"d",function(){return c});var a=n("lqqz"),r=n("rpEJ"),i=n("NJnL"),s=function(){return function(){this.adaptivePosition=!0,this.placement="top",this.triggers="click",this.outsideClick=!1}}(),o=function(){function t(t){Object.assign(this,t)}return Object.defineProperty(t.prototype,"isBs3",{get:function(){return Object(r.d)()},enumerable:!0,configurable:!0}),t}(),u=function(){function t(t,e,n,a,r,i){this._positionService=i,this.outsideClick=!1,this.containerClass="",this._isInited=!1,this._popover=r.createLoader(e,a,n).provide({provide:s,useValue:t}),Object.assign(this,t),this.onShown=this._popover.onShown,this.onHidden=this._popover.onHidden,"undefined"!=typeof window&&e.nativeElement.addEventListener("click",function(){try{e.nativeElement.focus()}catch(t){return}})}return Object.defineProperty(t.prototype,"isOpen",{get:function(){return this._popover.isShown},set:function(t){t?this.show():this.hide()},enumerable:!0,configurable:!0}),t.prototype.show=function(){!this._popover.isShown&&this.popover&&(this._positionService.setOptions({modifiers:{flip:{enabled:this.adaptivePosition},preventOverflow:{enabled:this.adaptivePosition}}}),this._popover.attach(o).to(this.container).position({attachment:this.placement}).show({content:this.popover,context:this.popoverContext,placement:this.placement,title:this.popoverTitle,containerClass:this.containerClass}),this.adaptivePosition||(this._positionService.calcPosition(),this._positionService.deletePositionElement(this._popover._componentRef.location)),this.isOpen=!0)},t.prototype.hide=function(){this.isOpen&&(this._popover.hide(),this.isOpen=!1)},t.prototype.toggle=function(){if(this.isOpen)return this.hide();this.show()},t.prototype.ngOnInit=function(){var t=this;this._isInited||(this._isInited=!0,this._popover.listen({triggers:this.triggers,outsideClick:this.outsideClick,show:function(){return t.show()}}))},t.prototype.ngOnDestroy=function(){this._popover.dispose()},t}(),c=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[s,a.a,i.a]}},t}()},Oaa7:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},Ob0Z:function(t,e,n){!function(t){"use strict";var e={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},n={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};function a(t,e,n,a){var r="";if(e)switch(n){case"s":r="\u0915\u093e\u0939\u0940 \u0938\u0947\u0915\u0902\u0926";break;case"ss":r="%d \u0938\u0947\u0915\u0902\u0926";break;case"m":r="\u090f\u0915 \u092e\u093f\u0928\u093f\u091f";break;case"mm":r="%d \u092e\u093f\u0928\u093f\u091f\u0947";break;case"h":r="\u090f\u0915 \u0924\u093e\u0938";break;case"hh":r="%d \u0924\u093e\u0938";break;case"d":r="\u090f\u0915 \u0926\u093f\u0935\u0938";break;case"dd":r="%d \u0926\u093f\u0935\u0938";break;case"M":r="\u090f\u0915 \u092e\u0939\u093f\u0928\u093e";break;case"MM":r="%d \u092e\u0939\u093f\u0928\u0947";break;case"y":r="\u090f\u0915 \u0935\u0930\u094d\u0937";break;case"yy":r="%d \u0935\u0930\u094d\u0937\u0947"}else switch(n){case"s":r="\u0915\u093e\u0939\u0940 \u0938\u0947\u0915\u0902\u0926\u093e\u0902";break;case"ss":r="%d \u0938\u0947\u0915\u0902\u0926\u093e\u0902";break;case"m":r="\u090f\u0915\u093e \u092e\u093f\u0928\u093f\u091f\u093e";break;case"mm":r="%d \u092e\u093f\u0928\u093f\u091f\u093e\u0902";break;case"h":r="\u090f\u0915\u093e \u0924\u093e\u0938\u093e";break;case"hh":r="%d \u0924\u093e\u0938\u093e\u0902";break;case"d":r="\u090f\u0915\u093e \u0926\u093f\u0935\u0938\u093e";break;case"dd":r="%d \u0926\u093f\u0935\u0938\u093e\u0902";break;case"M":r="\u090f\u0915\u093e \u092e\u0939\u093f\u0928\u094d\u092f\u093e";break;case"MM":r="%d \u092e\u0939\u093f\u0928\u094d\u092f\u093e\u0902";break;case"y":r="\u090f\u0915\u093e \u0935\u0930\u094d\u0937\u093e";break;case"yy":r="%d \u0935\u0930\u094d\u0937\u093e\u0902"}return r.replace(/%d/i,t)}t.defineLocale("mr",{months:"\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940_\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u090f\u092a\u094d\u0930\u093f\u0932_\u092e\u0947_\u091c\u0942\u0928_\u091c\u0941\u0932\u0948_\u0911\u0917\u0938\u094d\u091f_\u0938\u092a\u094d\u091f\u0947\u0902\u092c\u0930_\u0911\u0915\u094d\u091f\u094b\u092c\u0930_\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930_\u0921\u093f\u0938\u0947\u0902\u092c\u0930".split("_"),monthsShort:"\u091c\u093e\u0928\u0947._\u092b\u0947\u092c\u094d\u0930\u0941._\u092e\u093e\u0930\u094d\u091a._\u090f\u092a\u094d\u0930\u093f._\u092e\u0947._\u091c\u0942\u0928._\u091c\u0941\u0932\u0948._\u0911\u0917._\u0938\u092a\u094d\u091f\u0947\u0902._\u0911\u0915\u094d\u091f\u094b._\u0928\u094b\u0935\u094d\u0939\u0947\u0902._\u0921\u093f\u0938\u0947\u0902.".split("_"),monthsParseExact:!0,weekdays:"\u0930\u0935\u093f\u0935\u093e\u0930_\u0938\u094b\u092e\u0935\u093e\u0930_\u092e\u0902\u0917\u0933\u0935\u093e\u0930_\u092c\u0941\u0927\u0935\u093e\u0930_\u0917\u0941\u0930\u0942\u0935\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930_\u0936\u0928\u093f\u0935\u093e\u0930".split("_"),weekdaysShort:"\u0930\u0935\u093f_\u0938\u094b\u092e_\u092e\u0902\u0917\u0933_\u092c\u0941\u0927_\u0917\u0941\u0930\u0942_\u0936\u0941\u0915\u094d\u0930_\u0936\u0928\u093f".split("_"),weekdaysMin:"\u0930_\u0938\u094b_\u092e\u0902_\u092c\u0941_\u0917\u0941_\u0936\u0941_\u0936".split("_"),longDateFormat:{LT:"A h:mm \u0935\u093e\u091c\u0924\u093e",LTS:"A h:mm:ss \u0935\u093e\u091c\u0924\u093e",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm \u0935\u093e\u091c\u0924\u093e",LLLL:"dddd, D MMMM YYYY, A h:mm \u0935\u093e\u091c\u0924\u093e"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u0909\u0926\u094d\u092f\u093e] LT",nextWeek:"dddd, LT",lastDay:"[\u0915\u093e\u0932] LT",lastWeek:"[\u092e\u093e\u0917\u0940\u0932] dddd, LT",sameElse:"L"},relativeTime:{future:"%s\u092e\u0927\u094d\u092f\u0947",past:"%s\u092a\u0942\u0930\u094d\u0935\u0940",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},preparse:function(t){return t.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0930\u093e\u0924\u094d\u0930\u0940|\u0938\u0915\u093e\u0933\u0940|\u0926\u0941\u092a\u093e\u0930\u0940|\u0938\u093e\u092f\u0902\u0915\u093e\u0933\u0940/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0930\u093e\u0924\u094d\u0930\u0940"===e?t<4?t:t+12:"\u0938\u0915\u093e\u0933\u0940"===e?t:"\u0926\u0941\u092a\u093e\u0930\u0940"===e?t>=10?t:t+12:"\u0938\u093e\u092f\u0902\u0915\u093e\u0933\u0940"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0930\u093e\u0924\u094d\u0930\u0940":t<10?"\u0938\u0915\u093e\u0933\u0940":t<17?"\u0926\u0941\u092a\u093e\u0930\u0940":t<20?"\u0938\u093e\u092f\u0902\u0915\u093e\u0933\u0940":"\u0930\u093e\u0924\u094d\u0930\u0940"},week:{dow:0,doy:6}})}(n("wd/R"))},OjkT:function(t,e,n){!function(t){"use strict";var e={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},n={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};t.defineLocale("ne",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f\u0932_\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0937\u094d\u091f_\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u094b\u092c\u0930_\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930_\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u0947\u092c\u094d\u0930\u0941._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f._\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908._\u0905\u0917._\u0938\u0947\u092a\u094d\u091f._\u0905\u0915\u094d\u091f\u094b._\u0928\u094b\u092d\u0947._\u0921\u093f\u0938\u0947.".split("_"),monthsParseExact:!0,weekdays:"\u0906\u0907\u0924\u092c\u093e\u0930_\u0938\u094b\u092e\u092c\u093e\u0930_\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930_\u092c\u0941\u0927\u092c\u093e\u0930_\u092c\u093f\u0939\u093f\u092c\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930_\u0936\u0928\u093f\u092c\u093e\u0930".split("_"),weekdaysShort:"\u0906\u0907\u0924._\u0938\u094b\u092e._\u092e\u0919\u094d\u0917\u0932._\u092c\u0941\u0927._\u092c\u093f\u0939\u093f._\u0936\u0941\u0915\u094d\u0930._\u0936\u0928\u093f.".split("_"),weekdaysMin:"\u0906._\u0938\u094b._\u092e\u0902._\u092c\u0941._\u092c\u093f._\u0936\u0941._\u0936.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A\u0915\u094b h:mm \u092c\u091c\u0947",LTS:"A\u0915\u094b h:mm:ss \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A\u0915\u094b h:mm \u092c\u091c\u0947",LLLL:"dddd, D MMMM YYYY, A\u0915\u094b h:mm \u092c\u091c\u0947"},preparse:function(t){return t.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0930\u093e\u0924\u093f|\u092c\u093f\u0939\u093e\u0928|\u0926\u093f\u0909\u0901\u0938\u094b|\u0938\u093e\u0901\u091d/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0930\u093e\u0924\u093f"===e?t<4?t:t+12:"\u092c\u093f\u0939\u093e\u0928"===e?t:"\u0926\u093f\u0909\u0901\u0938\u094b"===e?t>=10?t:t+12:"\u0938\u093e\u0901\u091d"===e?t+12:void 0},meridiem:function(t,e,n){return t<3?"\u0930\u093e\u0924\u093f":t<12?"\u092c\u093f\u0939\u093e\u0928":t<16?"\u0926\u093f\u0909\u0901\u0938\u094b":t<20?"\u0938\u093e\u0901\u091d":"\u0930\u093e\u0924\u093f"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u092d\u094b\u0932\u093f] LT",nextWeek:"[\u0906\u0909\u0901\u0926\u094b] dddd[,] LT",lastDay:"[\u0939\u093f\u091c\u094b] LT",lastWeek:"[\u0917\u090f\u0915\u094b] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s\u092e\u093e",past:"%s \u0905\u0917\u093e\u0921\u093f",s:"\u0915\u0947\u0939\u0940 \u0915\u094d\u0937\u0923",ss:"%d \u0938\u0947\u0915\u0947\u0923\u094d\u0921",m:"\u090f\u0915 \u092e\u093f\u0928\u0947\u091f",mm:"%d \u092e\u093f\u0928\u0947\u091f",h:"\u090f\u0915 \u0918\u0923\u094d\u091f\u093e",hh:"%d \u0918\u0923\u094d\u091f\u093e",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u093f\u0928\u093e",MM:"%d \u092e\u0939\u093f\u0928\u093e",y:"\u090f\u0915 \u092c\u0930\u094d\u0937",yy:"%d \u092c\u0930\u094d\u0937"},week:{dow:0,doy:6}})}(n("wd/R"))},Oxv6:function(t,e,n){!function(t){"use strict";var e={0:"-\u0443\u043c",1:"-\u0443\u043c",2:"-\u044e\u043c",3:"-\u044e\u043c",4:"-\u0443\u043c",5:"-\u0443\u043c",6:"-\u0443\u043c",7:"-\u0443\u043c",8:"-\u0443\u043c",9:"-\u0443\u043c",10:"-\u0443\u043c",12:"-\u0443\u043c",13:"-\u0443\u043c",20:"-\u0443\u043c",30:"-\u044e\u043c",40:"-\u0443\u043c",50:"-\u0443\u043c",60:"-\u0443\u043c",70:"-\u0443\u043c",80:"-\u0443\u043c",90:"-\u0443\u043c",100:"-\u0443\u043c"};t.defineLocale("tg",{months:"\u044f\u043d\u0432\u0430\u0440_\u0444\u0435\u0432\u0440\u0430\u043b_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440_\u043e\u043a\u0442\u044f\u0431\u0440_\u043d\u043e\u044f\u0431\u0440_\u0434\u0435\u043a\u0430\u0431\u0440".split("_"),monthsShort:"\u044f\u043d\u0432_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433_\u0441\u0435\u043d_\u043e\u043a\u0442_\u043d\u043e\u044f_\u0434\u0435\u043a".split("_"),weekdays:"\u044f\u043a\u0448\u0430\u043d\u0431\u0435_\u0434\u0443\u0448\u0430\u043d\u0431\u0435_\u0441\u0435\u0448\u0430\u043d\u0431\u0435_\u0447\u043e\u0440\u0448\u0430\u043d\u0431\u0435_\u043f\u0430\u043d\u04b7\u0448\u0430\u043d\u0431\u0435_\u04b7\u0443\u043c\u044a\u0430_\u0448\u0430\u043d\u0431\u0435".split("_"),weekdaysShort:"\u044f\u0448\u0431_\u0434\u0448\u0431_\u0441\u0448\u0431_\u0447\u0448\u0431_\u043f\u0448\u0431_\u04b7\u0443\u043c_\u0448\u043d\u0431".split("_"),weekdaysMin:"\u044f\u0448_\u0434\u0448_\u0441\u0448_\u0447\u0448_\u043f\u0448_\u04b7\u043c_\u0448\u0431".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0418\u043c\u0440\u04ef\u0437 \u0441\u043e\u0430\u0442\u0438] LT",nextDay:"[\u041f\u0430\u0433\u043e\u04b3 \u0441\u043e\u0430\u0442\u0438] LT",lastDay:"[\u0414\u0438\u0440\u04ef\u0437 \u0441\u043e\u0430\u0442\u0438] LT",nextWeek:"dddd[\u0438] [\u04b3\u0430\u0444\u0442\u0430\u0438 \u043e\u044f\u043d\u0434\u0430 \u0441\u043e\u0430\u0442\u0438] LT",lastWeek:"dddd[\u0438] [\u04b3\u0430\u0444\u0442\u0430\u0438 \u0433\u0443\u0437\u0430\u0448\u0442\u0430 \u0441\u043e\u0430\u0442\u0438] LT",sameElse:"L"},relativeTime:{future:"\u0431\u0430\u044a\u0434\u0438 %s",past:"%s \u043f\u0435\u0448",s:"\u044f\u043a\u0447\u0430\u043d\u0434 \u0441\u043e\u043d\u0438\u044f",m:"\u044f\u043a \u0434\u0430\u049b\u0438\u049b\u0430",mm:"%d \u0434\u0430\u049b\u0438\u049b\u0430",h:"\u044f\u043a \u0441\u043e\u0430\u0442",hh:"%d \u0441\u043e\u0430\u0442",d:"\u044f\u043a \u0440\u04ef\u0437",dd:"%d \u0440\u04ef\u0437",M:"\u044f\u043a \u043c\u043e\u04b3",MM:"%d \u043c\u043e\u04b3",y:"\u044f\u043a \u0441\u043e\u043b",yy:"%d \u0441\u043e\u043b"},meridiemParse:/\u0448\u0430\u0431|\u0441\u0443\u0431\u04b3|\u0440\u04ef\u0437|\u0431\u0435\u0433\u043e\u04b3/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0448\u0430\u0431"===e?t<4?t:t+12:"\u0441\u0443\u0431\u04b3"===e?t:"\u0440\u04ef\u0437"===e?t>=11?t:t+12:"\u0431\u0435\u0433\u043e\u04b3"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0448\u0430\u0431":t<11?"\u0441\u0443\u0431\u04b3":t<16?"\u0440\u04ef\u0437":t<19?"\u0431\u0435\u0433\u043e\u04b3":"\u0448\u0430\u0431"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0443\u043c|\u044e\u043c)/,ordinal:function(t){return t+(e[t]||e[t%10]||e[t>=100?100:null])},week:{dow:1,doy:7}})}(n("wd/R"))},P6uZ:function(t,e,n){"use strict";n.d(e,"a",function(){return c});var a=n("3fWJ"),r=n("VnD/"),i=n("t9fZ"),s=n("HJBe"),o=n("tNVB"),u=n("mChF");function c(t,e){var n=arguments.length>=2;return function(c){return c.pipe(t?Object(r.a)(function(e,n){return t(e,n,c)}):u.a,Object(i.a)(1),n?Object(s.a)(e):Object(o.a)(function(){return new a.a}))}}},P8lu:function(t,e,n){"use strict";n.d(e,"a",function(){return h});var a=n("mrSG"),r=n("t/Na"),i=n("LvDl"),s=n("VNr4"),o=n("F/XL"),u=n("psW0"),c=n("aGNc"),l=n("9Z1F"),d=n("xTzq"),f=n("CcnG"),p=n("pL04"),h=function(){function t(t){this.http=t,this.url="api/rgw/user"}return t.prototype.list=function(){var t=this;return this.enumerate().pipe(Object(u.a)(function(e){return e.length>0?Object(s.a)(e.map(function(e){return t.get(e)})):Object(o.a)([])}))},t.prototype.enumerate=function(){return this.http.get(this.url)},t.prototype.enumerateEmail=function(){return this.http.get(this.url+"/get_emails")},t.prototype.get=function(t){return this.http.get(this.url+"/"+t)},t.prototype.getQuota=function(t){return this.http.get(this.url+"/"+t+"/quota")},t.prototype.create=function(t){var e=new r.h;return i.keys(t).forEach(function(n){e=e.append(n,t[n])}),this.http.post(this.url,null,{params:e})},t.prototype.update=function(t,e){var n=new r.h;return i.keys(e).forEach(function(t){n=n.append(t,e[t])}),this.http.put(this.url+"/"+t,null,{params:n})},t.prototype.updateQuota=function(t,e){var n=new r.h;return i.keys(e).forEach(function(t){n=n.append(t,e[t])}),this.http.put(this.url+"/"+t+"/quota",null,{params:n})},t.prototype.delete=function(t){return this.http.delete(this.url+"/"+t)},t.prototype.createSubuser=function(t,e){var n=new r.h;return i.keys(e).forEach(function(t){n=n.append(t,e[t])}),this.http.post(this.url+"/"+t+"/subuser",null,{params:n})},t.prototype.deleteSubuser=function(t,e){return this.http.delete(this.url+"/"+t+"/subuser/"+e)},t.prototype.addCapability=function(t,e,n){var a=new r.h;return a=(a=a.append("type",e)).append("perm",n),this.http.post(this.url+"/"+t+"/capability",null,{params:a})},t.prototype.deleteCapability=function(t,e,n){var a=new r.h;return a=(a=a.append("type",e)).append("perm",n),this.http.delete(this.url+"/"+t+"/capability",{params:a})},t.prototype.addS3Key=function(t,e){var n=new r.h;return n=n.append("key_type","s3"),i.keys(e).forEach(function(t){n=n.append(t,e[t])}),this.http.post(this.url+"/"+t+"/key",null,{params:n})},t.prototype.deleteS3Key=function(t,e){var n=new r.h;return n=(n=n.append("key_type","s3")).append("access_key",e),this.http.delete(this.url+"/"+t+"/key",{params:n})},t.prototype.exists=function(t){return this.get(t).pipe(Object(c.a)(!0),Object(l.a)(function(t){return i.isFunction(t.preventDefault)&&t.preventDefault(),Object(o.a)(!1)}))},t.prototype.emailExists=function(t){return t=decodeURIComponent(t),this.enumerateEmail().pipe(Object(u.a)(function(e){var n=i.indexOf(e,t);return Object(o.a)(-1!==n)}))},t.ngInjectableDef=f.defineInjectable({factory:function(){return new t(f.inject(r.c))},token:t,providedIn:p.a}),t=a.__decorate([d.a,a.__metadata("design:paramtypes",[r.c])],t)}()},PA2r:function(t,e,n){!function(t){"use strict";var e="leden_\xfanor_b\u0159ezen_duben_kv\u011bten_\u010derven_\u010dervenec_srpen_z\xe1\u0159\xed_\u0159\xedjen_listopad_prosinec".split("_"),n="led_\xfano_b\u0159e_dub_kv\u011b_\u010dvn_\u010dvc_srp_z\xe1\u0159_\u0159\xedj_lis_pro".split("_"),a=[/^led/i,/^\xfano/i,/^b\u0159e/i,/^dub/i,/^kv\u011b/i,/^(\u010dvn|\u010derven$|\u010dervna)/i,/^(\u010dvc|\u010dervenec|\u010dervence)/i,/^srp/i,/^z\xe1\u0159/i,/^\u0159\xedj/i,/^lis/i,/^pro/i],r=/^(leden|\xfanor|b\u0159ezen|duben|kv\u011bten|\u010dervenec|\u010dervence|\u010derven|\u010dervna|srpen|z\xe1\u0159\xed|\u0159\xedjen|listopad|prosinec|led|\xfano|b\u0159e|dub|kv\u011b|\u010dvn|\u010dvc|srp|z\xe1\u0159|\u0159\xedj|lis|pro)/i;function i(t){return t>1&&t<5&&1!=~~(t/10)}function s(t,e,n,a){var r=t+" ";switch(n){case"s":return e||a?"p\xe1r sekund":"p\xe1r sekundami";case"ss":return e||a?r+(i(t)?"sekundy":"sekund"):r+"sekundami";case"m":return e?"minuta":a?"minutu":"minutou";case"mm":return e||a?r+(i(t)?"minuty":"minut"):r+"minutami";case"h":return e?"hodina":a?"hodinu":"hodinou";case"hh":return e||a?r+(i(t)?"hodiny":"hodin"):r+"hodinami";case"d":return e||a?"den":"dnem";case"dd":return e||a?r+(i(t)?"dny":"dn\xed"):r+"dny";case"M":return e||a?"m\u011bs\xedc":"m\u011bs\xedcem";case"MM":return e||a?r+(i(t)?"m\u011bs\xedce":"m\u011bs\xedc\u016f"):r+"m\u011bs\xedci";case"y":return e||a?"rok":"rokem";case"yy":return e||a?r+(i(t)?"roky":"let"):r+"lety"}}t.defineLocale("cs",{months:e,monthsShort:n,monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(leden|ledna|\xfanora|\xfanor|b\u0159ezen|b\u0159ezna|duben|dubna|kv\u011bten|kv\u011btna|\u010dervenec|\u010dervence|\u010derven|\u010dervna|srpen|srpna|z\xe1\u0159\xed|\u0159\xedjen|\u0159\xedjna|listopadu|listopad|prosinec|prosince)/i,monthsShortStrictRegex:/^(led|\xfano|b\u0159e|dub|kv\u011b|\u010dvn|\u010dvc|srp|z\xe1\u0159|\u0159\xedj|lis|pro)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"ned\u011ble_pond\u011bl\xed_\xfater\xfd_st\u0159eda_\u010dtvrtek_p\xe1tek_sobota".split("_"),weekdaysShort:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),weekdaysMin:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[z\xedtra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v ned\u011bli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve st\u0159edu v] LT";case 4:return"[ve \u010dtvrtek v] LT";case 5:return"[v p\xe1tek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[v\u010dera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou ned\u011bli v] LT";case 1:case 2:return"[minul\xe9] dddd [v] LT";case 3:return"[minulou st\u0159edu v] LT";case 4:case 5:return"[minul\xfd] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"p\u0159ed %s",s:s,ss:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},PCNd:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},"PEr+":function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R"),i=n("EEJc"),s=n("ajRT"),o=n("gIcY"),u=n("IZUe"),c=n("ANnk"),l=n("f/UV"),d=n("aexS"),f=n("gp3X"),p=n("sb0X"),h=n("KVJa"),g=n("Z21x"),b=n("sne2"),m=n("0+/T"),y=n("DQlY");n.d(e,"a",function(){return A});var v=a["\u0275crt"]({encapsulation:0,styles:[[".modal-body[_ngcontent-%COMP%] .question[_ngcontent-%COMP%]{margin-top:1em}.modal-body[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{font-weight:700}.modal-body[_ngcontent-%COMP%] .question[_ngcontent-%COMP%] .checkbox[_ngcontent-%COMP%]{padding-top:7px}"]],data:{}});function _(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function x(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function T(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"p",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["Are you sure that you want to "," "])),a["\u0275ppd"](2,1),(t()(),a["\u0275eld"](3,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),a["\u0275ted"](4,null,["",""])),(t()(),a["\u0275ted"](-1,null,["?"]))],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,1,0,t(e,2,0,a["\u0275nov"](e.parent.parent,0),n.actionDescription));t(e,1,0,r),t(e,4,0,n.itemNames[0])})}function w(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit)})}function S(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"p",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["Are you sure that you want to "," the selected items?"])),a["\u0275ppd"](2,1),(t()(),a["\u0275eld"](3,0,null,null,2,"ul",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,w)),a["\u0275did"](5,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,5,0,e.component.itemNames)},function(t,e){var n=e.component,r=a["\u0275unv"](e,1,0,t(e,2,0,a["\u0275nov"](e.parent.parent,0),n.actionDescription));t(e,1,0,r)})}function O(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,T)),a["\u0275did"](2,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),a["\u0275and"](0,[["manyNames",2]],null,0,null,S))],function(t,e){t(e,2,0,1===e.component.itemNames.length,a["\u0275nov"](e,3))},null)}function I(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"p",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["Are you sure that you want to "," the selected ","?"])),a["\u0275ppd"](2,1)],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,1,0,t(e,2,0,a["\u0275nov"](e.parent,0),n.actionDescription));t(e,1,0,r,n.itemDescription)})}function C(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function k(t){return a["\u0275vid"](0,[(t()(),a["\u0275ted"](0,null,[" "," ","\n"])),a["\u0275ppd"](1,1)],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,0,0,t(e,1,0,a["\u0275nov"](e.parent,1),n.actionDescription));t(e,0,0,r,n.itemDescription)})}function N(t){return a["\u0275vid"](0,[a["\u0275pid"](0,r.LowerCasePipe,[]),a["\u0275pid"](0,r.TitleCasePipe,[]),a["\u0275qud"](402653184,1,{submitButton:0}),(t()(),a["\u0275eld"](3,0,null,null,38,"cd-modal",[],null,null,null,i.c,i.b)),a["\u0275did"](4,49152,[["modal",4]],0,s.a,[],{modalRef:[0,"modalRef"]},null),(t()(),a["\u0275eld"](5,0,null,0,2,null,null,null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,_)),a["\u0275did"](7,540672,null,0,r.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),a["\u0275eld"](8,0,null,1,33,null,null,null,null,null,null,null)),(t()(),a["\u0275eld"](9,0,null,null,32,"form",[["name","deletionForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var r=!0;return"submit"===e&&(r=!1!==a["\u0275nov"](t,11).onSubmit(n)&&r),"reset"===e&&(r=!1!==a["\u0275nov"](t,11).onReset()&&r),r},null,null)),a["\u0275did"](10,16384,null,0,o.D,[],null,null),a["\u0275did"](11,540672,[["formDir",4]],0,o.l,[[8,null],[8,null]],{form:[0,"form"]},null),a["\u0275prd"](2048,null,o.d,null,[o.l]),a["\u0275did"](13,16384,null,0,o.s,[[4,o.d]],null,null),(t()(),a["\u0275eld"](14,0,null,null,20,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,x)),a["\u0275did"](16,540672,null,0,r.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275eld"](17,0,null,null,17,"div",[["class","question"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,O)),a["\u0275did"](19,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),a["\u0275and"](0,[["noNames",2]],null,0,null,I)),(t()(),a["\u0275eld"](21,0,null,null,13,"div",[["class","form-group"]],null,null,null,null,null)),a["\u0275did"](22,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](23,{"has-error":0}),(t()(),a["\u0275eld"](24,0,null,null,10,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),a["\u0275eld"](25,0,null,null,7,"input",[["autofocus",""],["formControlName","confirmation"],["id","confirmation"],["name","confirmation"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var r=!0;return"change"===e&&(r=!1!==a["\u0275nov"](t,26).onChange(n.target.checked)&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,26).onTouched()&&r),r},null,null)),a["\u0275did"](26,16384,null,0,o.c,[a.Renderer2,a.ElementRef],null,null),a["\u0275prd"](1024,null,o.p,function(t){return[t]},[o.c]),a["\u0275did"](28,671744,null,0,o.j,[[3,o.d],[8,null],[8,null],[6,o.p],[2,o.F]],{name:[0,"name"]},null),a["\u0275prd"](2048,null,o.q,null,[o.j]),a["\u0275did"](30,16384,null,0,o.r,[[4,o.q]],null,null),a["\u0275did"](31,4210688,null,0,u.a,[a.ElementRef],null,null),a["\u0275did"](32,4210688,null,0,c.a,[[2,l.a],d.a,a.ElementRef],null,null),(t()(),a["\u0275eld"](33,0,null,null,1,"label",[["for","confirmation"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Yes, I am sure."])),(t()(),a["\u0275eld"](35,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),a["\u0275eld"](36,0,null,null,3,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.callSubmitAction()&&a),a},f.b,f.a)),a["\u0275did"](37,114688,[[1,4],["submitButton",4]],0,p.a,[a.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),a["\u0275and"](16777216,null,0,1,null,C)),a["\u0275did"](39,540672,null,0,r.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),a["\u0275eld"](40,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,h.b,h.a)),a["\u0275did"](41,49152,null,0,g.a,[r.Location,b.b],{name:[0,"name"],back:[1,"back"]},null),(t()(),a["\u0275and"](0,[["deletionHeading",2]],null,0,null,k))],function(t,e){var n=e.component;t(e,4,0,n.modalRef),t(e,7,0,a["\u0275nov"](e,42)),t(e,11,0,n.deletionForm),t(e,16,0,n.bodyContext,n.bodyTemplate),t(e,19,0,n.itemNames,a["\u0275nov"](e,20));var r=t(e,23,0,n.deletionForm.showError("confirmation",a["\u0275nov"](e,11)));t(e,22,0,"form-group",r),t(e,28,0,"confirmation"),t(e,37,0,n.deletionForm),t(e,39,0,a["\u0275nov"](e,42)),t(e,41,0,"Cancel",n.modalRef.hide)},function(t,e){t(e,9,0,a["\u0275nov"](e,13).ngClassUntouched,a["\u0275nov"](e,13).ngClassTouched,a["\u0275nov"](e,13).ngClassPristine,a["\u0275nov"](e,13).ngClassDirty,a["\u0275nov"](e,13).ngClassValid,a["\u0275nov"](e,13).ngClassInvalid,a["\u0275nov"](e,13).ngClassPending),t(e,25,0,a["\u0275nov"](e,30).ngClassUntouched,a["\u0275nov"](e,30).ngClassTouched,a["\u0275nov"](e,30).ngClassPristine,a["\u0275nov"](e,30).ngClassDirty,a["\u0275nov"](e,30).ngClassValid,a["\u0275nov"](e,30).ngClassInvalid,a["\u0275nov"](e,30).ngClassPending)})}function R(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"cd-deletion-modal",[],null,null,null,N,v)),a["\u0275did"](1,114688,null,0,m.a,[y.a],null,null)],function(t,e){t(e,1,0)},null)}var A=a["\u0275ccf"]("cd-deletion-modal",m.a,R,{},{},[])},PNOi:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.ProgressBarComponent=function(){return a([r.Component({selector:"datatable-progress",template:'\n <div class="progress-linear" role="progressbar">\n <div class="container">\n <div class="bar"></div>\n </div>\n </div>\n ',changeDetection:r.ChangeDetectionStrategy.OnPush})],function(){})}()},PeUW:function(t,e,n){!function(t){"use strict";var e={1:"\u0be7",2:"\u0be8",3:"\u0be9",4:"\u0bea",5:"\u0beb",6:"\u0bec",7:"\u0bed",8:"\u0bee",9:"\u0bef",0:"\u0be6"},n={"\u0be7":"1","\u0be8":"2","\u0be9":"3","\u0bea":"4","\u0beb":"5","\u0bec":"6","\u0bed":"7","\u0bee":"8","\u0bef":"9","\u0be6":"0"};t.defineLocale("ta",{months:"\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf_\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf_\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd_\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd_\u0bae\u0bc7_\u0b9c\u0bc2\u0ba9\u0bcd_\u0b9c\u0bc2\u0bb2\u0bc8_\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd_\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bc6\u0bae\u0bcd\u0baa\u0bb0\u0bcd_\u0b85\u0b95\u0bcd\u0b9f\u0bc7\u0bbe\u0baa\u0bb0\u0bcd_\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd_\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd".split("_"),monthsShort:"\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf_\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf_\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd_\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd_\u0bae\u0bc7_\u0b9c\u0bc2\u0ba9\u0bcd_\u0b9c\u0bc2\u0bb2\u0bc8_\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd_\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bc6\u0bae\u0bcd\u0baa\u0bb0\u0bcd_\u0b85\u0b95\u0bcd\u0b9f\u0bc7\u0bbe\u0baa\u0bb0\u0bcd_\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd_\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd".split("_"),weekdays:"\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bcd\u0bb1\u0bc1\u0b95\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0b9f\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0baa\u0bc1\u0ba4\u0ba9\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0b95\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf\u0b95\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8_\u0b9a\u0ba9\u0bbf\u0b95\u0bcd\u0b95\u0bbf\u0bb4\u0bae\u0bc8".split("_"),weekdaysShort:"\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1_\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd_\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd_\u0baa\u0bc1\u0ba4\u0ba9\u0bcd_\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd_\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf_\u0b9a\u0ba9\u0bbf".split("_"),weekdaysMin:"\u0b9e\u0bbe_\u0ba4\u0bbf_\u0b9a\u0bc6_\u0baa\u0bc1_\u0bb5\u0bbf_\u0bb5\u0bc6_\u0b9a".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[\u0b87\u0ba9\u0bcd\u0bb1\u0bc1] LT",nextDay:"[\u0ba8\u0bbe\u0bb3\u0bc8] LT",nextWeek:"dddd, LT",lastDay:"[\u0ba8\u0bc7\u0bb1\u0bcd\u0bb1\u0bc1] LT",lastWeek:"[\u0b95\u0b9f\u0ba8\u0bcd\u0ba4 \u0bb5\u0bbe\u0bb0\u0bae\u0bcd] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0b87\u0bb2\u0bcd",past:"%s \u0bae\u0bc1\u0ba9\u0bcd",s:"\u0b92\u0bb0\u0bc1 \u0b9a\u0bbf\u0bb2 \u0bb5\u0bbf\u0ba8\u0bbe\u0b9f\u0bbf\u0b95\u0bb3\u0bcd",ss:"%d \u0bb5\u0bbf\u0ba8\u0bbe\u0b9f\u0bbf\u0b95\u0bb3\u0bcd",m:"\u0b92\u0bb0\u0bc1 \u0ba8\u0bbf\u0bae\u0bbf\u0b9f\u0bae\u0bcd",mm:"%d \u0ba8\u0bbf\u0bae\u0bbf\u0b9f\u0b99\u0bcd\u0b95\u0bb3\u0bcd",h:"\u0b92\u0bb0\u0bc1 \u0bae\u0ba3\u0bbf \u0ba8\u0bc7\u0bb0\u0bae\u0bcd",hh:"%d \u0bae\u0ba3\u0bbf \u0ba8\u0bc7\u0bb0\u0bae\u0bcd",d:"\u0b92\u0bb0\u0bc1 \u0ba8\u0bbe\u0bb3\u0bcd",dd:"%d \u0ba8\u0bbe\u0b9f\u0bcd\u0b95\u0bb3\u0bcd",M:"\u0b92\u0bb0\u0bc1 \u0bae\u0bbe\u0ba4\u0bae\u0bcd",MM:"%d \u0bae\u0bbe\u0ba4\u0b99\u0bcd\u0b95\u0bb3\u0bcd",y:"\u0b92\u0bb0\u0bc1 \u0bb5\u0bb0\u0bc1\u0b9f\u0bae\u0bcd",yy:"%d \u0b86\u0ba3\u0bcd\u0b9f\u0bc1\u0b95\u0bb3\u0bcd"},dayOfMonthOrdinalParse:/\d{1,2}\u0bb5\u0ba4\u0bc1/,ordinal:function(t){return t+"\u0bb5\u0ba4\u0bc1"},preparse:function(t){return t.replace(/[\u0be7\u0be8\u0be9\u0bea\u0beb\u0bec\u0bed\u0bee\u0bef\u0be6]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0baf\u0bbe\u0bae\u0bae\u0bcd|\u0bb5\u0bc8\u0b95\u0bb1\u0bc8|\u0b95\u0bbe\u0bb2\u0bc8|\u0ba8\u0ba3\u0bcd\u0baa\u0b95\u0bb2\u0bcd|\u0b8e\u0bb1\u0bcd\u0baa\u0bbe\u0b9f\u0bc1|\u0bae\u0bbe\u0bb2\u0bc8/,meridiem:function(t,e,n){return t<2?" \u0baf\u0bbe\u0bae\u0bae\u0bcd":t<6?" \u0bb5\u0bc8\u0b95\u0bb1\u0bc8":t<10?" \u0b95\u0bbe\u0bb2\u0bc8":t<14?" \u0ba8\u0ba3\u0bcd\u0baa\u0b95\u0bb2\u0bcd":t<18?" \u0b8e\u0bb1\u0bcd\u0baa\u0bbe\u0b9f\u0bc1":t<22?" \u0bae\u0bbe\u0bb2\u0bc8":" \u0baf\u0bbe\u0bae\u0bae\u0bcd"},meridiemHour:function(t,e){return 12===t&&(t=0),"\u0baf\u0bbe\u0bae\u0bae\u0bcd"===e?t<2?t:t+12:"\u0bb5\u0bc8\u0b95\u0bb1\u0bc8"===e||"\u0b95\u0bbe\u0bb2\u0bc8"===e?t:"\u0ba8\u0ba3\u0bcd\u0baa\u0b95\u0bb2\u0bcd"===e&&t>=10?t:t+12},week:{dow:0,doy:6}})}(n("wd/R"))},Phjn:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("psW0");function r(t,e){return Object(a.a)(t,e,1)}},PpIw:function(t,e,n){!function(t){"use strict";var e={1:"\u0ce7",2:"\u0ce8",3:"\u0ce9",4:"\u0cea",5:"\u0ceb",6:"\u0cec",7:"\u0ced",8:"\u0cee",9:"\u0cef",0:"\u0ce6"},n={"\u0ce7":"1","\u0ce8":"2","\u0ce9":"3","\u0cea":"4","\u0ceb":"5","\u0cec":"6","\u0ced":"7","\u0cee":"8","\u0cef":"9","\u0ce6":"0"};t.defineLocale("kn",{months:"\u0c9c\u0ca8\u0cb5\u0cb0\u0cbf_\u0cab\u0cc6\u0cac\u0ccd\u0cb0\u0cb5\u0cb0\u0cbf_\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd_\u0c8f\u0caa\u0ccd\u0cb0\u0cbf\u0cb2\u0ccd_\u0cae\u0cc6\u0cd5_\u0c9c\u0cc2\u0ca8\u0ccd_\u0c9c\u0cc1\u0cb2\u0cc6\u0cd6_\u0c86\u0c97\u0cb8\u0ccd\u0c9f\u0ccd_\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82\u0cac\u0cb0\u0ccd_\u0c85\u0c95\u0ccd\u0c9f\u0cc6\u0cc2\u0cd5\u0cac\u0cb0\u0ccd_\u0ca8\u0cb5\u0cc6\u0c82\u0cac\u0cb0\u0ccd_\u0ca1\u0cbf\u0cb8\u0cc6\u0c82\u0cac\u0cb0\u0ccd".split("_"),monthsShort:"\u0c9c\u0ca8_\u0cab\u0cc6\u0cac\u0ccd\u0cb0_\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd_\u0c8f\u0caa\u0ccd\u0cb0\u0cbf\u0cb2\u0ccd_\u0cae\u0cc6\u0cd5_\u0c9c\u0cc2\u0ca8\u0ccd_\u0c9c\u0cc1\u0cb2\u0cc6\u0cd6_\u0c86\u0c97\u0cb8\u0ccd\u0c9f\u0ccd_\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82_\u0c85\u0c95\u0ccd\u0c9f\u0cc6\u0cc2\u0cd5_\u0ca8\u0cb5\u0cc6\u0c82_\u0ca1\u0cbf\u0cb8\u0cc6\u0c82".split("_"),monthsParseExact:!0,weekdays:"\u0cad\u0cbe\u0ca8\u0cc1\u0cb5\u0cbe\u0cb0_\u0cb8\u0cc6\u0cc2\u0cd5\u0cae\u0cb5\u0cbe\u0cb0_\u0cae\u0c82\u0c97\u0cb3\u0cb5\u0cbe\u0cb0_\u0cac\u0cc1\u0ca7\u0cb5\u0cbe\u0cb0_\u0c97\u0cc1\u0cb0\u0cc1\u0cb5\u0cbe\u0cb0_\u0cb6\u0cc1\u0c95\u0ccd\u0cb0\u0cb5\u0cbe\u0cb0_\u0cb6\u0ca8\u0cbf\u0cb5\u0cbe\u0cb0".split("_"),weekdaysShort:"\u0cad\u0cbe\u0ca8\u0cc1_\u0cb8\u0cc6\u0cc2\u0cd5\u0cae_\u0cae\u0c82\u0c97\u0cb3_\u0cac\u0cc1\u0ca7_\u0c97\u0cc1\u0cb0\u0cc1_\u0cb6\u0cc1\u0c95\u0ccd\u0cb0_\u0cb6\u0ca8\u0cbf".split("_"),weekdaysMin:"\u0cad\u0cbe_\u0cb8\u0cc6\u0cc2\u0cd5_\u0cae\u0c82_\u0cac\u0cc1_\u0c97\u0cc1_\u0cb6\u0cc1_\u0cb6".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[\u0c87\u0c82\u0ca6\u0cc1] LT",nextDay:"[\u0ca8\u0cbe\u0cb3\u0cc6] LT",nextWeek:"dddd, LT",lastDay:"[\u0ca8\u0cbf\u0ca8\u0ccd\u0ca8\u0cc6] LT",lastWeek:"[\u0c95\u0cc6\u0cc2\u0ca8\u0cc6\u0caf] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0ca8\u0c82\u0ca4\u0cb0",past:"%s \u0cb9\u0cbf\u0c82\u0ca6\u0cc6",s:"\u0c95\u0cc6\u0cb2\u0cb5\u0cc1 \u0c95\u0ccd\u0cb7\u0ca3\u0c97\u0cb3\u0cc1",ss:"%d \u0cb8\u0cc6\u0c95\u0cc6\u0c82\u0ca1\u0cc1\u0c97\u0cb3\u0cc1",m:"\u0c92\u0c82\u0ca6\u0cc1 \u0ca8\u0cbf\u0cae\u0cbf\u0cb7",mm:"%d \u0ca8\u0cbf\u0cae\u0cbf\u0cb7",h:"\u0c92\u0c82\u0ca6\u0cc1 \u0c97\u0c82\u0c9f\u0cc6",hh:"%d \u0c97\u0c82\u0c9f\u0cc6",d:"\u0c92\u0c82\u0ca6\u0cc1 \u0ca6\u0cbf\u0ca8",dd:"%d \u0ca6\u0cbf\u0ca8",M:"\u0c92\u0c82\u0ca6\u0cc1 \u0ca4\u0cbf\u0c82\u0c97\u0cb3\u0cc1",MM:"%d \u0ca4\u0cbf\u0c82\u0c97\u0cb3\u0cc1",y:"\u0c92\u0c82\u0ca6\u0cc1 \u0cb5\u0cb0\u0ccd\u0cb7",yy:"%d \u0cb5\u0cb0\u0ccd\u0cb7"},preparse:function(t){return t.replace(/[\u0ce7\u0ce8\u0ce9\u0cea\u0ceb\u0cec\u0ced\u0cee\u0cef\u0ce6]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u0cb0\u0cbe\u0ca4\u0ccd\u0cb0\u0cbf|\u0cac\u0cc6\u0cb3\u0cbf\u0c97\u0ccd\u0c97\u0cc6|\u0cae\u0ca7\u0ccd\u0caf\u0cbe\u0cb9\u0ccd\u0ca8|\u0cb8\u0c82\u0c9c\u0cc6/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0cb0\u0cbe\u0ca4\u0ccd\u0cb0\u0cbf"===e?t<4?t:t+12:"\u0cac\u0cc6\u0cb3\u0cbf\u0c97\u0ccd\u0c97\u0cc6"===e?t:"\u0cae\u0ca7\u0ccd\u0caf\u0cbe\u0cb9\u0ccd\u0ca8"===e?t>=10?t:t+12:"\u0cb8\u0c82\u0c9c\u0cc6"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0cb0\u0cbe\u0ca4\u0ccd\u0cb0\u0cbf":t<10?"\u0cac\u0cc6\u0cb3\u0cbf\u0c97\u0ccd\u0c97\u0cc6":t<17?"\u0cae\u0ca7\u0ccd\u0caf\u0cbe\u0cb9\u0ccd\u0ca8":t<20?"\u0cb8\u0c82\u0c9c\u0cc6":"\u0cb0\u0cbe\u0ca4\u0ccd\u0cb0\u0cbf"},dayOfMonthOrdinalParse:/\d{1,2}(\u0ca8\u0cc6\u0cd5)/,ordinal:function(t){return t+"\u0ca8\u0cc6\u0cd5"},week:{dow:0,doy:6}})}(n("wd/R"))},Q3dv:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="ko-KR">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>\ub124\ube44\uac8c\uc774\uc158 \uc804\ud658</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>\ud604\ud669\ud310</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>\ud074\ub7ec\uc2a4\ud130</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>\ud638\uc2a4\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>\ubaa8\ub2c8\ud130\ub4e4</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD\ub4e4</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>\uc124\uc815</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>\ud06c\ub7ec\uc26c\ub9f5</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>\uba54\ub2c8\uc800 \ubaa8\ub4c8\ub4e4</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>\ub85c\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>\uacbd\uace0\ub4e4</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>\ud480\ub4e4</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>\ube14\ub7ed</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>\uc774\ubbf8\uc9c0\ub4e4</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>\ubbf8\ub7ec\ub9c1</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>\ud30c\uc77c\uc2dc\uc2a4\ud15c\ub4e4</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>\uc624\ube0c\uc81d\ud2b8\uac8c\uc774\ud2b8\uc6e8\uc774</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>\ub370\ubaac\ub4e4</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>\uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>\ubc84\ud0b7\ub4e4</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>\ub4a4\ub85c</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>\uc5b8\uc5b4\uc120\ud0dd</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>\ud328\ub110 \ub370\uc774\ud0c0 \ub85c\ub529 \uc911...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>\uadf8\ub77c\ud30c\ub098 \ud0c0\uc784 \ud53d\ucee4</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>\uc124\uc815 \ucd08\uae30\ud654</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>\ub370\uc774\ud0c0 \ub85c\ub529 \uc2e4\ud3d0</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>\uc120\ud0dd\ub41c</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>\ubc1c\uacac\ub41c</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>\uc804\uccb4</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>\ud3b8\uc9d1</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>\uc774\ub984</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>\uc124\uba85</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>\uc790\uc138\ud55c \uc124\uba85</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>\uae30\ubcf8\uac12</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>\ub370\ubaa8 \uae30\ubcf8\uac12</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>\uc11c\ube44\uc2a4\ub4e4</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>\uac12\ub4e4</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>\uc785\ub825\uac12\uc774 \ub108\ubb34 \ud07d\ub2c8\ub2e4! \uadf8\uac83\uc740 \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/> \ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>\uc785\ub825\ub41c \uac12\uc774 \ub108\ubb34 \uc791\uc2b5\ub2c8\ub2e4.! \uadf8\uac83\uc740 \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/> \uc791\uc544\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>\uc800\uc7a5\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>\ud06c\ub7ec\uc26c\ub9f5 \ubcf4\uae30</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>\ud638\uc2a4\ud2b8 \ubaa9\ub85d\ub4e4</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>\ud1b5\ud569 \uc131\ub2a5\uce58</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>\ud56d\ubaa9\ub4e4\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>\ud074\ub7ec\uc2a4\ud130 \ub85c\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>\uac10\uc0ac \ub85c\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>\uc124\uc815 \ub85c\ub529 \uc911</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>\uc124\uc815\uc744 \ub85c\ub4dc\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>\uad00\ub9ac\ubaa8\ub4c8 \ud3b8\uc9d1\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>\uc785\ub825\ub41c \uac12\uc774 \uc720\ud6a8\ud55c UUID\uac00 \uc544\ub2d9\ub2c8\ub2e4, \uc608.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>\uc785\ub825\ub41c \uac12\uc740 \uc720\ud6a8\ud55c IP\uc8fc\uc18c \uc5ec\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>\uc774 \ud544\ub4dc\ub294 \ud544\uc218\uc801\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>\uc785\ub825\uac12\uc774 \ub108\ubb34 \ud07d\ub2c8\ub2e4! \uadf8\uac83\uc740 \ubc18\ub4dc\uc2dc \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/> \uc791\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>\uc785\ub825\ub41c \uac12\uc774 \ub108\ubb34 \uc791\uc2b5\ub2c8\ub2e4! \uadf8\uac83\uc740 \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>\ubcf4\ub2e4 \ud06c\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>\uc785\ub825\ub41c \uac12\uc740 \uc801\uc5b4\ub3c4 \ud558\ub098\uc758 \uc22b\uc790\ub97c \ud544\uc694\ub85c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>\uc785\ub825 \ub41c \uac12\uc740 \uc22b\uc790 \ub610\ub294 \uc2ed\uc9c4\uc218\uc5ec\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>\uac31\uc2e0</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>\ud074\ub7ec\uc2a4\ud130 ID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>\ubaac\ub9f5 \ubcc0\uacbd\uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>\ubaac\ub9f5 \ubcc0\uacbd\ubc88\ud638</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>\uc815\uc871\uc218 \uc77c\uce58\ubc88\ud638</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>\uc815\uc871\uc218 \ubaa8\ub2c8\ud130\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>\uc694\uad6c\ub418\ub294 \uc77c\uce58\ubc88\ud638</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>\uc694\uad6c\ub418\ub294 \ubaa8\ub2c8\ud130\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>\uc815\uc871\uc218\uc5d0 \ud3ec\ud568</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>\uc815\uc871\uc218 \ubbf8\ud3ec\ud568</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>\ucde8\uc18c</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>\uc120\ud0dd\ub41c \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\ub85c \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> \uc744 \ud558\ub294 \uac83\uc774 \ud655\uc2e4\ud569\ub2c8\uae4c?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>\uc608, \ud655\uc2e4\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>\ud074\ub7ec\uc2a4\ud130-\uc218\uc900\uc758 OSD \ud50c\ub808\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>\uc81c\ucd9c</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>\uc790\uc138\ud55c \uc635\uc158...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>OSD \ubcf5\uad6c \uc6b0\uc120\uc21c\uc704</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>\uc6b0\uc120\uc21c\uc704</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>\uc6b0\uc120 \uc21c\uc704 \uac12 \ub9de\ucda4 \uc124\uc815</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>\uc774 \ud544\ub4dc\ub294 \uc694\uad6c\ub429\ub2c8\ub2e4!</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>\uc785\ub825\ub41c \uac12\uc774 \ub108\ubb34 \ud07d\ub2c8\ub2e4! \uadf8\uac83\uc740 \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>\ubcf4\ub2e4 \ud06c\uc9c0 \uc54a\uc544\uc57c \ud569\ub2c8\ub2e4..\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>\uc785\ub825\ub41c \uac12\uc774 \ub108\ubb34 \uc791\uc2b5\ub2c8\ub2e4! \uadf8\uac83\uc740 \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>\ubcf4\ub2e4 \uc791\uc544\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>OSD \uc7ac-\uc870\uc815</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>\uac12\uc740 0\uacfc 1\uc0ac\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>\uc7ac-\uc870\uc815</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD\ub4e4 \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> \uccad\uc18c\ud558\uae30\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, \uc120\ud0dd, 1 {\uae4a\uc774 } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\uc744 \uccad\uc18c\ud558\uae30 \uc704\ud574, \ub2f9\uc2e0\uc740 \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\uc744 \uc801\uc6a9\ud558\ub824\uace0 \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, \uc120\ud0dd, 1 {\uae4a\uc774 } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>OSD \ubaa9\ub85d\ub4e4</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\uacc4\uc18d\uc9c4\ud589\ud558\uba74 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \ub294 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \ub85c \ud45c\uc2dc\ub429\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>OSD\ub294 \ud30c\uad34\ud558\uae30\uc5d0 \uc548\uc804\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4!</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\uacc4\uc18d\uc9c4\ud589\ud558\uba74 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \ub294\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \uac00 \ub420 \uac83\uc785\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>\uc138\ubd80\uc124\uba85</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>\uac12</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>\ub2eb\uae30</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>\uc0ad\uc81c</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>\uac74\uac15\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>\ud1b5\uacc4\ub4e4</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>\ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc811\uadfc\uac00\ub2a5</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>\uc8fc\uc18c\ub4e4</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>\ud544\uc218 \uc785\ub825\ub780</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>\ubc18\ub4dc\uc2dc \ud558\ub098 \uc774\uc0c1\uc758 \uc27c\ud45c\ub85c \uad6c\ubd84 \ub41c \uac12\uc744 \ud3ec\ud568\ud574\uc57c \ud568</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>\uc608\ub97c\ub4e4\uba74:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>\uc811\uadfc\ud615\ud0dc</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8\ub4e4 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>\ub85c\ub529\uc911...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5 \ud074\ub7ec\uc2a4\ud130 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- \ud074\ub7ec\uc2a4\ud130 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>\ub370\ubaac \ucd94\uac00\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>\uc2a4\ud1a0\ub9ac\uc9c0 \ubc31\uc5d4\ub4dc</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- \uc774\uc6a9\uac00\ub2a5\ud55c \ub370\uc774\ud0c0\ud480 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- \uc2a4\ud1a0\ub9ac\uc9c0 \ubc31\uc5d4\ub4dc \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>\uac1d\uccb4 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5\ud55c \uc0ac\uc6a9\uc790\ub4e4 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- \uac1d\uccb4 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc0ac\uc6a9\uc790 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS \uc0ac\uc6a9\uc790 ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5\ud55c \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- cephx \ud074\ub77c\uc774\uc5b8\ud2b8 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>CephFS \uc774\ub984</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>\ubcf4\uc548 \ub808\uc774\ube14</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>\ubcf4\uc548 \ub808\uc774\ube14 \uc0ac\uc6a9</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS \uacbd\ub85c</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>\uacbd\ub85c\ub294 \'/\'\ub85c \uc2dc\uc791\ud574\uc57c\ud558\uba70 \uadf8 \ub4a4\uc5d0 \ub2e8\uc5b4\uac00 \uc62c \uc218 \uc788\uc2b5\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>\uc0c8\ub85c\uc6b4 \ub514\ub809\ud1a0\ub9ac\uac00 \ub9cc\ub4e4\uc5b4 \uc9c8 \uac83\uc785\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>\uacbd\ub85c</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>\uacbd\ub85c\ub294 \ud558\ub098\uc758 \'/\' \ub610\ub294 \ud558\ub098\uc758 \ub2e8\uc5b4 \uc77c \uc218 \uc788\uc2b5\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>\uc0c8\ub85c\uc6b4 \ubc84\ud0b7\uc774 \ub9cc\ub4e4\uc5b4 \uc9c8 \uac83\uc785\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS \ud504\ub85c\ud1a0\ucf5c</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS \ud0dc\ud06c</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \ub9c8\uc6b4\ud2b8\ub4e4\uc744 \uc704\ud55c \ub300\uccb4 \uc811\uadfc (/\uac00 \uc55e\uc5d0 \uc640\uc57c \ud568).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \ud558\uc704 \ub514\ub809\ud1a0\ub9ac\ub97c \ub9c8\uc6b4\ud2b8 \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 (\uc989, Tag = foo \uc778 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 foo / baz\ub97c \ub9c8\uc6b4\ud2b8\ud558\uc9c0 \ubabb\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>\ub2e4\ub978 \ud0dc\uadf8 \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \uac19\uc740 \uacbd\ub85c\ub97c \uc5ec\ub7ec \ubc88 \ub0b4\ubcf4\ub0bc \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>\ub2e4\ub978 Pseudo \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ub3d9\uc77c\ud55c \uacbd\ub85c\ub97c \uc5ec\ub7ec \ubc88 \ub0b4\ubcf4\ub0bc \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5\ud55c \uc811\uadfc\ud615\ud0dc \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- \uc811\uadfc\ud615\ud0dc \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5\ud55c squash \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- \uc5b4\ub5a4 \uc885\ub958\uc758 \uc0ac\uc6a9\uc790 ID \uc2a4\ucffc\uc2dc\uac00 \uc218\ud589\ub418\ub294\uc9c0 \uc120\ud0dd\ud558\uc138\uc694 --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>\uc804\uc1a1\ud504\ub85c\ud1a0\ucf5c</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Ceph \uc0ac\uc6a9\uc744 \ud658\uc601\ud569\ub2c8\ub2e4.</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>\uc0ac\uc6a9\uc790\uc774\ub984\uc774 \ud544\uc694\ud569\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>\uc554\ud638\uac00 \ud544\uc694\ud569\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>\ub85c\uadf8\uc778</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>\ubbf8\uc548\ud569\ub2c8\ub2e4. \uc0ac\uc6a9\uc790\uac00 Ceph\ub0b4\uc5d0 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>\uae08\uc9c0\ub428</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>\ubbf8\uc548\ud569\ub2c8\ub2e4. \ub2f9\uc2e0\uc774 \uc694\uccad\ud560 \uac83\uc744 \uc5f4\ub78c\ud558\ub294 \uac83\uc774 \ud5c8\ub77d\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>\ubbf8\uc548\ud569\ub2c8\ub2e4. \ub2f9\uc2e0\uc774 \uc694\uccad\ud560 \uac83\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>\ubaa8\ub4e0 \uac83 \uc81c\uac70</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>\ucd5c\uadfc \uc54c\ub9bc\ub4e4</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>\ubc31\uadf8\ub77c\uc6b4\ub4dc \uc791\uc5c5\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>\ubc31\uadf8\ub77c\uc6b4\ub4dc \uc791\uc5c5\ub4e4</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>\ub3c4\uc6c0\ub9d0</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>\ubb38\uc11c</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\ub300\ud558\uc5ec</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>\ub300\uc26c\ubcf4\ub4dc \uc124\uc815</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>\uc0ac\uc6a9\uc790 \uad00\ub9ac</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>\ub85c\uadf8\uc778\ub41c \uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \n\ub85c\uc368 \uc2b9\uc778\ub428\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>\ub85c\uadf8\uc544\uc6c3</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>\uc774\ub984...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>\uc120\ud0dd\ud55c \uc774\ub984\uc774 \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>\uc138\ubd80\uc124\uba85...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>\uad8c\ud55c\ub4e4</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>\uc5ed\ud560\ub4e4</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>\uc0ac\uc6a9\uc790\uba85</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>\uc554\ud638</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>\uc554\ud638 \ud655\uc778</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>\uc554\ud638 \ud655\uc778\uc774 \uc554\ud638\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>\uc804\uccb4 \uc774\ub984</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>\uc804\uc790\uc6b0\ud3b8</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>\uc720\ud6a8\ud558\uc9c0\uc54a\ub294 \uc804\uc790\uc6b0\ud3b8.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>\ub2f9\uc2e0\uc758 \uc0ac\uc6a9\uc790\ub85c\ubd80\ud130 "\uc0ac\uc6a9\uc790 \uc77d\uae30 / \uc5c5\ub370\uc774\ud2b8"\uad8c\ud55c\uc744 \uc81c\uac70\ud558\ub824\uace0\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>\uacc4\uc18d\ud558\uba74 \ubaa8\ub4e0 \uc0ac\uc6a9\uc790\uc5d0\uac8c \uc5ed\ud560\uc744 \ucd94\uac00\ud558\uac70\ub098 \uc81c\uac70 \ud560 \uc218 \uc5c6\uac8c\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>\uacc4\uc18d \uc9c4\ud589\ud558\uae30\ub97c \uc6d0\ud558\uc2ed\ub2c8\uae4c?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>\uc131\ub2a5 \uce74\uc6b4\ud130\ub4e4\uc744 \uc0ac\uc6a9 \ud560 \uc218 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>\uc18d\uc131\ub4e4 (OSD \ub9f5)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>\uba54\ud0c0\ub370\uc774\ud0c0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>\uba54\ud0c0\ub370\uc774\ud0c0</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>\uc131\ub2a5 \uce74\uc6b4\ud130</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>\ud788\uc2a4\ud1a0\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc74c: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>\uc4f0\uae30</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>\uc77d\uae30</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>\ud788\uc2a4\ud1a0\uadf8\ub7a8</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>\uc131\ub2a5 \uc138\ubd80\uc815\ubcf4\ub4e4</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>\ud604\uc7ac \uac12\ub4e4</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>\ud615\ud0dc</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>\ucd5c\uc18c</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>\ucd5c\ub300</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>\ud50c\ub808\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>\uc18c\uc2a4</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>\uc218\uc900</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>\uc218\ud589\uc2dc\uac04\uc5d0 \uac31\uc2e0\uac00\ub2a5\ud568(\ud3b8\uc9d1\uac00\ub2a5)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>\ud14c\ud06c\ub4e4</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>\uc5f4\uac70\ud615 \uac12\ub4e4</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>\ucd94\uac00\ub85c \ub354\ubcf4\uae30</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>\ud074\ub7ec\uc2a4\ud130 \uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>\uad00\ub9ac\uc790 \ub370\ubaac\ub4e4</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>\uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774\ub4e4</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>\uba54\ud0c0\ub370\uc774\ud0c0 \uc11c\ubc84\ub4e4</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI \uac8c\uc774\ud2b8\uc6e8\uc774\ub4e4</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8 IOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8 \ucc98\ub9ac\ub7c9</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8 \uc77d\uae30/\uc4f0\uae30</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>\ubcf5\uad6c \ucc98\ub9ac\ub7c9</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>\uc138\uc815\uc791\uc5c5</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>\uc131\ub2a5</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>\uc6d0\uc2dc\uc6a9\ub7c9</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>\uc624\ube0c\uc81d\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>OSD\ub2f9 PG\ub4e4</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>PG \uc0c1\ud0dc\ub4e4</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>\uc6a9\ub7c9</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> \ub354 \uc790\uc138\ud55c \ub0b4\uc6a9\uc744 \uc704\ud574 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\ub85c\uadf8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> \ubcf4\uc2ed\uc2dc\uc624.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>\uc21c\uc704</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8\ub4e4: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>\uc774\ubbf8\uc9c0\ub97c \ud734\uc9c0\ud1b5\uc5d0 \uc774\ub3d9</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>\ud734\uc9c0\ud1b5\uc73c\ub85c \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> \uc62e\uae30\uae30 \uc704\ud574, \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\uc120\ud0dd, \n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> \uc774\ubbf8\uc9c0 \uc62e\uae30\uc138\uc694. \uc120\ud0dd\uc801\uc73c\ub85c, \ud3d0\uae30\ub0a0\uc9dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>\ubcf4\ud638\uac00 \ub9cc\ub8cc\ub418\ub294 </target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>\ubcf4\ud638\ub418\uc9c0 \uc54a\uc74c</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>\ub0a0\uc9dc \ud615\uc2dd \uc624\ub958. "YYYY-MM-DD HH:mm:ss" \ud615\uc2dd\uc73c\ub85c \uc9c0\uc815\ud558\uc138\uc694.</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>\ubcf4\ud638\uae30\uac04\uc774 \uc774\ubbf8 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ub354 \ubbf8\ub798\uc758 \ub0a0\uc9dc\ub97c \uc120\ud0dd\ud558\uac70\ub098 \uacf5\ub780\uc73c\ub85c \ub0a8\uaca8\ub450\uc138\uc694.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>\uc774\ubbf8\uc9c0 \uc62e\uae30\uae30</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>\uac1c\uad00</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>\ud0c0\uac9f\ub4e4</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>\uc778\uc99d \ud0d0\uc0c9</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>\uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\uc0ac\uc6a9\uc790\uc774\ub984\uc740 8~64\uc790\uae4c\uc9c0 \uae38\uc774\uc758 \ubb38\uc790\ub4e4\uc744 \uac00\uc838\uc57c \ud558\uba70 \uadf8\ub9ac\uace0, \uc624\uc9c1 , \'.\', \'@\', \'-\', \'_\', \':\' \ub4f1\uc758 \ud2b9\uc218 \ubb38\uc790\ub4e4\ub9cc\uc744 \ud3ec\ud568\uac00\ub2a5\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>\uacf5\ub3d9 \uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>\uacf5\ud1b5 \uc554\ud638</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>iSCSI \ud0c0\uac9f\ub4e4 \uad00\ub9ac \uae30\ub2a5\ub4e4\uc744 \uc124\uc815\ud558\uace0 \ucf1c\uae30\uc704\ud574\uc11c \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\ubb38\uc11c\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> \ubd80\ubd84\uc744 \ucc38\uc870\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>\uc774\uc6a9\uac00\ub2a5\ud55c \uc815\ubcf4:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>iSCSI \ud0c0\uac9f\uc774 \uc774\uc6a9 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>\uc624\uc9c1 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \uc124\uc815\ub41c RBD \uc774\ubbf8\uc9c0\ub4e4\uacfc \ud568\uaed8 \uc0ac\uc6a9\uac00\ub2a5\ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>\ud480</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>\ub370\uc774\ud0c0 \ud480</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>\uc0dd\uc131\ub41c</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>\ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>\uac1d\uccb4\ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>\ud2b9\uc9d5\ub4e4</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>\uc900\ube44\ub41c</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>\uc774\uc6a9\ubd88\uac00</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>\uc900\ube44\ub41c \ucd1d\uacc4</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>\uc2a4\ud2b8\ub77c\uc774\ud551 \ub2e8\uc704</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>\uc2a4\ud2b8\ub77c\uc774\ud551 \ud69f\uc218</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>\uc0c1\uc704</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>\ube14\ub85d \uc774\ub984 \uc811\ub450\uc0ac</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>\uc21c\uc11c</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>\uc2a4\ub0c5\uc0bf</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>\uc774\ubbf8\uc9c0</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>\uc774 \uc124\uc815\uc740 \uc804\uc5ed \uac12\uc744 \ub36e\uc5b4\uc501\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>\uae00\ub85c\ubc8c</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>\uc774\uac83\uc740 \uc804\uc5ed \uac12\uc785\ub2c8\ub2e4. \uc774 \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud574 \uc774 \uc635\uc158\uc758 \uac12\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' \uc640 \'@\' \ubb38\uc790\ub294 \uc0ac\uc6a9\ubd88\uac00\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- \uc774\uc6a9\uac00\ub2a5\ud55c rbd\ud480 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- \ud480 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>\uc804\uc6a9 \ub370\uc774\ud0c0 \ud480\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc138\uc694</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>\ub370\uc774\ud0c0 \ud480</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>RBD\uc758 \uac1d\uccb4-\ub370\uc774\ud0c0\ub97c \uc800\uc7a5\ud558\uace0 \uc788\ub294 \uc804\uc6a9 \ud480</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>\uc608., 100 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>\uc0ac\uc774\uc988\ub97c \uc99d\uac00\uc2dc\ucf1c\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>\uc790\uc138\ud55c</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>\ubd84\uc0b0\uc800\uc7a5</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>\ubd84\uc0b0\uc800\uc7a5\ub2e8\uc704</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- \ubd84\uc0b0\uc800\uc7a5\ub2e8\uc704 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>\ubd84\uc0b0\uc800\uc7a5 \uac1c\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc73c\ubbc0\ub85c \uc774 \ud544\ub4dc\ub294 \ud544\uc218\uc785\ub2c8\ub2e4!</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>\ubd84\uc0b0\uc800\uc7a5\ub2e8\uc704\ub294 \uac1d\uccb4\ud06c\uae30\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>\ubd84\uc0b0\uc800\uc7a5 \uac2f\uc218</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>\ubd84\uc0b0\uc800\uc7a5 \ub2e8\uc704\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc73c\ubbc0\ub85c \uc774 \ud544\ub4dc\ub294 \ud544\uc218\uc785\ub2c8\ub2e4!</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>\ubd84\uc0b0\uc800\uc7a5 \uac2f\uc218\ub294 \ubc18\ub4dc\uc2dc 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD \uc2a4\ub0c5\uc0f7\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> \uc2a4\ub0c5\uc0f7\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>\ubcf4\ud638\ub428</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>\ubcf4\ud638\uc548\ub428</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>\ub864\ubc31\ud558\ub824\uace0 \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>\ud734\uc9c0\ud1b5 \ube44\uc6b0\uae30</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>\ube44\uc6b0\uae30 \uc704\ud574, \ud558\ub098 \ub610\ub294 \ubaa8\ub4e0 \uc774\ubbf8\uc9c0\ub4e4\uc744 \uc120\ud0dd\ud558\uace0 \ud074\ub9ad\ud558\uc138\uc694.</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>\ud480:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>\ud480 \uc774\ub984:</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>\ubaa8\ub4e0</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>\uc774\ubbf8\uc9c0 \ubcf5\uad6c\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>\ubcf5\uad6c\ub97c \uc704\ud574</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>\uc774\ubbf8\uc9c0\ub4e4\uc758 \uc0c8\ub85c\uc6b4 \uc774\ub984\uc744 \uc785\ub825\ud558\uace0 \ud074\ub9ad\ud558\uc138\uc694</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>\uc0c8\ub85c\uc6b4 \uc774\ub984</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>\ud3d0\uae30\ub420</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>\uae4c\uc9c0 \ubcf4\ud638\ub428</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>\uc774 \uc774\ubbf8\uc9c0\ub294 \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>\uae4c\uc9c0 \ubcf4\ud638\ub429\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>\ud734\uc9c0\ud1b5</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>iSCSI \ud1a0\ud3f4\ub85c\uc9c0</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>\uae30\ubcf8\uc124\uc815 \uac12\ub4e4\ub85c \ubd80\ud130 \uc778\uc790\ub97c \ubcc0\uacbd\ud558\ub294 \uac83\uc740 \uc77c\ubc18\uc801\uc73c\ub85c \ud544\uc694\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>\uc124\uc815\ub4e4</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>\ubc31\uc2a4\ud1a0\uc5b4</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>\ud655\uc778</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>\uace0\uae09\uc124\uc815\ub4e4</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>\ud0c0\uac9f IQN</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN\uc774 \uc798\ubabb\ub41c \ud328\ud134\uc744 \uac00\uc9c0\uace0 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uc9c0\uc815\uaddc\uce59\uc774 \uc788\uc2b5\ub2c8\ub2e4.\n\'iqn.$\ub144-$\ub2ec.$\ub4a4\uc9d1\uc5b4\uc9c4\uc8fc\uc18c:$\uc815\uc758\ub41c\uc774\ub984\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Key\n\uc608\ub97c\ub4e4\uba74: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>\ucd94\uac00 \uc815\ubcf4</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>\uc774 \ud0c0\uac9f\uc740 \uace0\uae09\uc124\uc815\ub4e4\uc744 \uc218\uc815\ud588\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>\ud3ec\ud138</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>\uc801\uc5b4\ub3c4 \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> \uac8c\uc774\ud2b8\uc6e8\uc774\ub4e4\uc744 \ud544\uc694\ub85c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>\ud3ec\ud138 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>\uc774 \uc774\ubbf8\uc9c0\ub294 \uc124\uc815\ub4e4\uc744 \uc218\uc815\ud588\uc2b5\ub2c8\ub2e4. </target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>\uc774\ubbf8\uc9c0 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL \uc778\uc99d</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>\uac1c\uc2dc\uc790\ub4e4</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>\uac1c\uc2dc\uc790\ub4e4</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>\ud074\ub77c\uc774\uc5b8\ud2b8 IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>\uac1c\uc2dc\uc790 IQN\uc740 \uc720\uc77c\ud574\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\uc0ac\uc6a9\uc790\uc774\ub984\uc740 8~64\uc790\uae4c\uc9c0 \uae38\uc774\uc758 \ubb38\uc790\ub4e4\uc744 \uac00\uc838\uc57c \ud558\uba70 \uadf8\ub9ac\uace0, \uc624\uc9c1 , \'.\', \'@\', \'-\', \'_\', \':\' \ub4f1\uc758 \ud2b9\uc218 \ubb38\uc790\ub4e4\ub9cc \ud3ec\ud568\uc774 \uac00\ub2a5\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>\uac1c\uc2dc\uc790\ub294 \ud558\ub098\uc758 \uadf8\ub8f9\uc5d0 \uc18d\ud574\uc57c \ud558\uace0, \uc774\ubbf8\uc9c0\ub294 \uadf8\ub8f9\uc548\uc5d0\uc11c \uc124\uc815\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>\ucd94\uac00\ub41c \uc544\uc774\ud15c\ub4e4\uc774 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>\uac8c\uc2dc\uc790 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>\uadf8\ub8f9\ub4e4</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>\uadf8\ub8f9</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>\uadf8\ub8f9\ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>RBD \uc124\uc815\ub4e4</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>\ub85c\uceec \uad6c\uc131 \uac12\uc744 \uc81c\uac70\ud558\uc2ed\uc2dc\uc624. \uc0c1\uc704 \uad6c\uc131 \uac12\uc740 \uacc4\uc2b9\ub418\uace0 \ub300\uc2e0 \uc0ac\uc6a9\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>\ucd5c\uc18c\uac12\uc740 0\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>\uc774\uc288\ub4e4</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>\ub3d9\uae30\ud654\uc911</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>\uc900\ube44\ub428</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>\ud480 \ubbf8\ub7ec\ubaa8\ub4dc\ub97c \ud3b8\uc9d1\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\ud480\uc744 \uc704\ud55c \ubbf8\ub7ec\ubaa8\ub4dc\ub97c \ud3b8\uc9d1\ud558\uae30 \uc704\ud574\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, \uadf8 \ubaa9\ub85d\uc73c\ub85c \ubd80\ud130 \uc0c8\ub85c\uc6b4 \ubaa8\ub4dc\ub97c \uc120\ud0dd\ud558\uace0, \ud074\ub9ad\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\uac31\uc2e0\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>\uc591\uc2dd</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>\uc0c1\ub300\ubc29 \ud074\ub7ec\uc2a4\ud130\ub4e4\uc740 \ubbf8\ub7ec\ub97c \ub2e8\uc808\ud558\uae30 \uc804\uc5d0 \ubc18\ub4dc\uc2dc \uc81c\uac70\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n \ud480 \ubbf8\ub7ec \uc0c1\ub300\ubc29\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> \ud480 \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> \ud480\uc744 \uc704\ud558\uc5ec \uc0c1\ub300\ubc29 \uc18d\uc131 \ubbf8\ub7ec\ud558\uace0,\n \uc120\ud0dd \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/> \uc81c\ucd9c \n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> .\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>\ud074\ub7ec\uc2a4\ud130 \uc774\ub984</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>\ud074\ub7ec\uc2a4\ud130 \uc774\ub984\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX \uc544\uc774\ub514</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX \uc544\uc774\ub514...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>CephX \uc544\uc774\ub514\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>\ubaa8\ub2c8\ud130 \uc8fc\uc18c\ub4e4</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>\ucf64\ub9c8\ub85c \ubd84\ub9ac\ub41c \uc8fc\uc18c\ub4e4...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>\ubaa8\ub2c8\ud130 \uc8fc\uc18c\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX \ud0a4</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64\ub85c \uc778\ucf54\ub529 \ub41c \ud0a4 ...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>CephX \ud0a4\ub294 \ubc18\ub4dc\uc2dc base64\ub85c \uc778\ucf54\ub4dc \ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>\ud480 \ubaa9\ub85d\ub4e4</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>\uc774\ub984\uc740 \uc601\uc22b\uc790, \ub300\uc2dc \ubc0f \ubc11\uc904\ub85c\ub9cc \uad6c\uc131 \ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>\uc120\ud0dd\ud55c Erasure Code \ud504\ub85c\ud30c\uc77c \uc774\ub984\uc774 \uc774\ubbf8 \uc0ac\uc6a9 \uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>\ud50c\ub7ec\uadf8\uc778</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>\ub370\uc774\ud130 \ub369\uc5b4\ub9ac\ub4e4 (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>\ubc18\ub4dc\uc2dc 2\ubcf4\ub2e4 \ud06c\uac70\ub098 \uac19\uc544\uc57c\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>\ucf54\ub529 \ub369\uc5b4\ub9ac\ub4e4 (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>\ubc18\ub4dc\uc2dc 1\ubcf4\ub2e4 \ud06c\uac70\ub098 \uac19\uc544\uc57c\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>\ub0b4\uad6c\uc131 \ud3c9\uac00(c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>\uc9c0\uc5ed (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>\ud06c\ub7ec\uc26c \uc2e4\ud328 \ub3c4\uba54\uc778</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>\ud06c\ub7ec\uc26c \uc9c0\uc5ed</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>\uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>\uae30\uc220</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>\ud328\ud0b7\ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>\ud06c\ub7ec\uc26c\ub8e8\ud2b8</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>\ud06c\ub7ec\uc26c \uc7a5\uce58 \ud074\ub798\uc2a4</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>\ubaa8\ub4e0</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>\ub514\ub809\ud1a0\ub9ac</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>\uc120\ud0dd\ud55c Ceph \ud480\uc774\ub984\uc774 \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>\ud480 \ud615\ud0dc</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- \ud480 \ud615\ud0dc \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>\uac8c\uc7ac\uc704\uce58 \uadf8\ub8f9</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>\uc801\uc5b4\ub3c4 \ud558\ub098\uc758 \uac8c\uc7ac\uc704\uce58 \uadf8\ub8f9\uc774 \ud544\uc694\ud568!</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>\ud074\ub7ec\uc2a4\ud130\ub294 \uc774 \ub9ce\uc740 PG\ub4e4\ub97c \ucc98\ub9ac \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \ud544\uc694\ud55c PG \uc591\uc744 \ub2e4\uc2dc \uacc4\uc0b0\ud558\uc2ed\uc2dc\uc624.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>\uacc4\uc0b0 \ub3c4\uc6c0\ub9d0</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>\ud604\uc7ac\uc758 PG\ub4e4 \uc124\uc815\ub4e4\uc774 \ub2f9\uc2e0\uc744 \uc704\ud574 \uacc4\uc0b0\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \n\ub2f9\uc2e0\uc740 \uc81c\ucd9c\ud558\uae30 \uc804\uc5d0 \ub2f9\uc2e0\uc758 \uc694\uad6c\uc5d0 \uc801\ud569\ud55c \uac12\uc778\uc9c0\ub97c \ud655\uc778\ud574\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>\ud06c\ub7ec\uc26c \ub8f0\uc14b</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- \ud06c\ub7ec\uc26c \ub8f0 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>\ud06c\ub7ec\uc26c \ub8f0</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>\ud06c\ub7ec\uc26c \ub2e8\uacc4\ub4e4</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>\uc774 \ub8f0\uc5d0 \uc758\ud558\uc5ec \ucd5c\uc18c\ub85c \ud544\uc694\ub85c \ud558\ub294 OSD\ubcf4\ub2e4 \uc801\uc740 OSD\ub97c \uac00\uc9c0\uace0 \uc788\uae30\ub54c\ubb38\uc5d0 \uc774 \ub8f0\uc740 \ud604\uc7ac\uc758 \ud074\ub7ec\uc2a4\ud130\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>\ubcf5\uc81c\ub418\ub294 \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>\ucd5c\uc18c: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>\ucd5c\ub300: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>\uc9c0\uc815\ub41c \ud06c\uae30\ub294 \ubc94\uc704\ub97c \ubc97\uc5b4\ub0ac\uc2b5\ub2c8\ub2e4.\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> \uc5d0\uc11c \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> \uc0ac\uc774\uc758 \uac12\uc774 \uc720\ud6a8\ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Erasure Code \ud504\ub85c\ud30c\uc77c</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- \uc0ac\uc6a9\uac00\ub2a5\ud55c Erasure Code \ud504\ub85c\ud30c\uc77c \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- \ud55c\uac1c\uc758 Erasure Code \ud504\ub85c\ud30c\uc77c \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC \ub36e\uc5b4\uc4f0\uae30</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>\uc751\uc6a9\ud504\ub85c\uadf8\ub7a8\ub4e4</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>\uc555\ucd95</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>\uc54c\uace0\ub9ac\uc998</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- \uc774\uc6a9\uac00\ub2a5\ud55c Erasure \uc555\ucd95\uc54c\uace0\ub9ac\uc998 \uc5c6\uc74c --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>\ucd5c\uc18c blob \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>\uc608) 128KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>\uac12\uc740 0\ubcf4\ub2e4 \ucee4\uc57c\ud569\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>\ucd5c\ub300 blob \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>\uc608) 512KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>\uac12\uc740 \ucd5c\uc18c blob \ud06c\uae30\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>\ube44\uc728</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>\uc555\ucd95\uc728</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>\uac12\uc740 0.0\uacfc 1.0 \uc0ac\uc774 \uc5ec\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>\uc774\ub984\uc5d0 \'/\'\uac00 \ud3ec\ud568 \ub41c RBD \ud480\uc744 \uc0dd\uc131 \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>\uc774\ub984\uc744 \ubcc0\uacbd\ud558\uac70\ub098 \uc751\uc6a9 \ud504\ub85c\uadf8\ub7a8 \ubaa9\ub85d\uc5d0\uc11c \'rbd\'\ub97c \uc81c\uac70\ud558\uc2ed\uc2dc\uc624.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>\ucf00\uc26c \uacc4\uce35\ub4e4 \uc0c1\uc138\uc124\uba85\ub4e4</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target> \uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774 \uad00\ub9ac\uae30\ub2a5\ub4e4\uc744 \uc5b4\ub5bb\uac8c \uc124\uc815\ud558\uace0 \ucf1c\ub294\uc9c0\uc5d0 \ub300\ud574 \n\ubb38\uc11c\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\uc0c1\uc758 \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> \ubd80\ubd84\uc744 \ucc38\uc870\ud558\uae30 \ubc14\ub78d\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>\ub370\ubaac \ubaa9\ub85d\ub4e4</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>\uc131\ub2a5 \uce74\uc6b4\ud130</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>\ubc84\ud0b7\ub370\uc774\ud0c0 \uc801\uc7ac \uc911</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>\ubc84\ud0b7 \ub370\uc774\ud0c0\ub97c \uc801\uc7ac\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>\uc544\uc774\ub514</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>\uac12\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>\uc18c\uc720\uc790</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- \uc0ac\uc6a9\uc790 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>\uc544\uc774\ub514</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>\uc0c9\uc778\ud615\uc2dd</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>\uc704\uce58\uaddc\uce59</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>\ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>\ucd5c\ub300 \ub9c8\ucee4</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>\ubc84\uc83c</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>\ub9c8\uc2a4\ud130 \ubc84\uc83c</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>\uc218\uc815\ub41c \uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>\uc81c\ub85c\uadf8\ub8f9</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>\ubc84\ud0b7 \ud560\ub2f9\ub7c9</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>\uc774\uc6a9\uac00\ub2a5</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>\ucd5c\ub300 \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>\ubb34\uc81c\ud55c</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>\ucd5c\ub300 \uac1d\uccb4\ub4e4</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- \uc0ac\uc6a9\uc790\uba85 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>\uc790\ub3d9\uc0dd\uc131\ub41c \ud0a4</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>\uc811\uadfc \ud0a4</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>\ube44\ubc00 \ud0a4</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>\uc804\uc790\uc6b0\ud3b8 \uc8fc\uc18c</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>\uc720\uc608\ub418\ub2e4.</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>\uc2dc\uc2a4\ud15c</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, \uc120\ud0dd, 0 {\uc544\ub2c8\uc624} 1 {\uc608} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>\ucd5c\ub300 \ubc84\ud0b7\ub4e4</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>\ubcf4\uc870\uc0ac\uc6a9\uc790\ub4e4</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>\ub2a5\ub825\uce58\ub4e4</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>\uc0ac\uc6a9\uc790 \ud560\ub2f9\ub7c9</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>\ubcf4\uae30</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>\ud0a4\ub4e4</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- \ud615\ud0dc \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>\uad8c\ud55c</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- \uad8c\ud55c \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>\ubcf4\uc870\uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>\uc120\ud0dd\ud55c \ubcf4\uc870\uc0ac\uc6a9\uc790 \uc544\uc774\ub514\uac00 \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>\uc77d\uae30, \uc4f0\uae30</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>\uac00\ub4dd\ucc2c</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>\uc2a4\uc704\ud504\ud2b8 \ud0a4</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>\uc790\ub3d9\uc0dd\uc120\ub41c \ube44\ubc00</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>\uc0ac\uc6a9\uc790 \ub370\uc774\ud0c0 \uc801\uc7ac \uc911...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>\uc0ac\uc6a9\uc790 \ub370\uc774\ud0c0\ub97c \uc801\uc7ac\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>\uc120\ud0dd\ub41c \uc0ac\uc6a9\uc790 \uc544\uc774\ub514\uac00 \uc774\ubbf8 \uc0ac\uc6a9 \uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>\uc774\uac83\uc740 \uc720\ud6a8\ud55c \uc804\uc790\uc6b0\ud3b8 \uc8fc\uc18c\uac00 \uc544\ub2d9\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>\uc120\ud0dd\ud55c \uc804\uc790\uc6b0\ud3b8 \uc8fc\uc18c\uac00 \uc774\ubbf8 \uc0ac\uc6a9 \uc911\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>\ucd5c\ub300 \ubc84\ud0b7\ub4e4</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>\uc785\ub825\ub41c \uac12\uc740 \ubc18\ub4dc\uc2dc 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3 \ud0a4</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>\ubcf4\uc870\uc0ac\uc6a9\uc790\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>\ud0a4\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>\uc2a4\uc704\ud504\ud2b8</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>\ub2a5\ub825\uce58\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>\ubb34\uc81c\ud55c \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>\ucd5c\ub300 \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>\ubb34\uc81c\ud55c \uac1d\uccb4\ub4e4</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>\ucd5c\ub300 \uac1d\uccb4\ub4e4</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>\ud604\uc7ac</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>\uc5c5\ub370\uc774\ud2b8\ub41c \uac80\uc0c9 \uc778\uc99d</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>\uc0ac\uc6a9\uac00\ub2a5\ud55c \ud3ec\ud0c8\ub4e4\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>\uc0ac\uc6a9\uac00\ub2a5\ud55c \uc774\ubbf8\uc9c0\ub4e4\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>\uc0ac\uc6a9\ud560 \uc218\uc788\ub294 \uc774\ubbf8\uc9c0\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub300\uc0c1\uc5d0 \uc774\ubbf8\uc9c0\ub97c \ucd94\uac00\ud588\ub294\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>\uc0ac\uc6a9\ud560 \uc218\uc788\ub294 \uac1c\uc2dc\uc790\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub300\uc0c1\uc5d0 \uac1c\uc2dc\uc790\ub97c \ucd94\uac00\ud588\ub294\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>\ud0c0\uac9f</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>\uc77d\uc740 \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>\uc4f0\uae30 \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>\uc77d\uae30 Ops</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>\uc4f0\uae30 Ops</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O \uc774\ub798\ub85c</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>\uc778\uc2a4\ud0c4\uc2a4</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>\ud638\uc2a4\ud2b8\uc774\ub984</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>\uc774\uc288</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>\uc9c4\ud589\uc911</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>\uc124\uc815\ud574\uc81c\ub428</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>\ud3b8\uc9d1\ubaa8\ub4dc</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>\uc0c1\ub300\ubc29 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>\uc0c1\ub300\ubc29 \ud3b8\uc9d1</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>\uc0c1\ub300\ubc29 \uc0ad\uc81c</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>\ub9ac\ub354</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># \ub85c\uceec</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># \uc6d0\uaca9</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>\uc0c1\ub300\ubc29 \ubbf8\ub7ec</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>\ud0a4</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>\ub525 \ud328\ud134</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>\uacc4\uce35\ud654</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>\ubc30\ud0c0\uc801\uc778 \ub77d</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>\uc624\ud504\uc81d\ud2b8-\ub9f5(\ubc30\ud0c0\uc801\uc778-\ub77d\uc744 \uc694\uad6c\ud55c\ub2e4)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>\uc800\ub110\ub9c1(\ubc30\ud0c1\uc801\uc778-\ub77d\uc744 \uc694\uad6c\ud569\ub2c8\ub2e4.)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>RBD \uc2a4\ub0c5\uc0f7 \ub864\ubc31</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>\ub864\ubc31</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>RBD \uc2a4\ub0c5\uc0f7</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>\uc0ad\uc81c\ub420 </target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>\uc544\uc774\ub514</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>\ud615\ud0dc</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>\uc0c1\ud0dc</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>\ubc84\uc83c</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>\ud638\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>\ub8e8\ud2b8</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>\uc21c\uc704</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>\ub370\ubaac</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>\ud65c\ub3d9</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>\ub374\ud2b8\ub9ac\ub4e4</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>\uc544\uc774\ub178\ub4dc\ub4e4</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>\uc0ac\uc6a9\ub7c9</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>\ub300\uae30 \ub370\ubaac\ub4e4</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\uc774 \uac12\uc740 \ub7f0\ud0c0\uc784\uc5d0 \uc5c5\ub370\uc774\ud2b8 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>\ub370\ubaac\ub4e4 / \ud074\ub77c\uc774\uc5b8\ud2b8\ub4e4\uc740 \ubaa8\ub2c8\ud130 \uad6c\uc131 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c\uc774 \uac12\uc744 \uac00\uc838 \uc624\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \'ceph config set ...\'\uc744 \ud1b5\ud574\uc774 \uc635\uc158\uc744 \uc124\uc815\ud558\ub294 \uac83\uc740 \ud5c8\ub77d\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc774 \uc635\uc158\uc740 ceph.conf \ub610\ub294 \uba85\ub839 \uc904\uc744 \ud1b5\ud574 \uad6c\uc131\ud574\uc57c\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>\uc635\uc158\uc740 \ub370\ubaac \uc2dc\uc791 \uc911\uc5d0 \ub9cc \uc801\uc6a9\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>\uc635\uc158\uc740 \ud074\ub7ec\uc2a4\ud130 \uc0dd\uc131\ud560 \ub54c \ub9cc \uc601\ud5a5\uc744 \uc90d\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>\uc635\uc158\uc740 \ub370\ubaac \uc0dd\uc131\ud560 \ub54c\ub9cc \uc601\ud5a5\uc744\uc90d\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>\uac31\uc2e0\ub41c \uc124\uc815 \uc635\uc158 \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>\uc11c\ube44\uc2a4</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>\ud604\uc7ac\uac12</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>\ud3b8\uc9d1\uac00\ub2a5</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>\ubaa8\ub4c8\uc744 \uc704\ud574 \uac31\uc2e0\ub41c \uc635\uc158\ub4e4 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>\uc0ac\uc6a9\uac00\ub2a5</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>\uc0ac\uc6a9\ubd88\uac00</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>\uc7ac-\uc811\uc18d \uc911, \uae30\ub2e4\ub824 \uc8fc\uc138\uc694...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>\uacf5\uac1c \uc8fc\uc18c</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>\uc5f4\ub9b0 \uc138\uc158\ub4e4</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>\ub4e4\uc5b4\uc62c \uc218 \uc5c6\ub294</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>\uc774\uc804\uc5d0 \ub9c8\ud06c \uc544\uc6c3 \ub41c OSD\ub294 \uc2dc\uc791\uc2dc \ub2e4\uc2dc \ud45c\uc2dc\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>\ub098\uac08 \uc218 \uc5c6\ub294</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD\ub4e4\uc740 \uad6c\uc131\ub41c \uac04\uaca9 \ud6c4\uc5d0\ub294 \uc790\ub3d9\uc73c\ub85c \ud45c\uc2dc\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>\uc0b4\uc544\ub098\uc9c0 \uc54a\ub294</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSD\ub294 \uc2dc\uc791\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>\uc8fd\uc77c \uc218 \uc5c6\ub294</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>\ubaa8\ub2c8\ud130\uac00 OSD\ub4e4\uc758 \ub2e4\uc6b4\uc744 \ud45c\uc2dc\ud558\uc9c0 \uc54a\ub3c4\ub85d OSD \uc7a5\uc560 \ubcf4\uace0\uc11c\uac00 \ubb34\uc2dc\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>\uba48\ucd9c</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>\uc77d\uae30\uc640 \uc4f0\uae30\ub97c \uba48\ucda4</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>\uc2a4\ud06c\ub7ec\ube59 \uc54a\ub428</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>\uc2a4\ud06c\ub7ec\ube59\uc774 \ube44\ud65c\uc131\ud654\ub418\uc5c8\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>\ub525 \uc2a4\ud06c\ub7fd \uc548\ub428</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>\ub525 \uc2a4\ud06c\ub7ec\ube59\uc774 \ube44\ud65c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>\ubc31\ud544 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>PG\ub4e4\uc758 \ubc31\ud544\uc774 \uc77c\uc2dc\uc911\uc9c0 \ub418\uc5c8\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>\ubcf5\uad6c \uc54a\ub428</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>PG\ub4e4\uc758 \ubcf5\uad6c\uac00 \uc77c\uc2dc\uc911\uc9c0 \ub418\uc5c8\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>\ube44\ud2b8\ub2e8\uc704 \uc815\ub82c</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>\ube44\ud2b8\ub2e8\uc704 \uc815\ub82c\uc744 \uc0ac\uc6a9\ud558\uc138\uc694</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>\uc644\uc804\uc0ad\uc81c\ub41c \uc2a4\ub0c5\ub514\ub809\ud1a0\ub9ac\ub4e4</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD\ub4e4\uc774 \ubcc0\ud654\ub41c \uc2a4\ub0c5\uc14b\uc744 \uac00\uc9c0\uace0 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>\uc0ad\uc81c\ub41c \ubcf5\uad6c\ub4e4</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>\ud53c\uc5b4\ub9c1 \ub300\uc2e0 \ubcf5\uad6c \uc911\uc5d0 \uc218\ud589\ub41c \uc0ad\uc81c\ubb3c\ub4e4</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>PG \ub85c\uadf8 \ud558\ub4dc \ud55c\uacc4</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>pg \ub85c\uadf8 \uae38\uc774\uc5d0 \ud558\ub4dc \ud55c\uacc4\ub97c \ub123\uc73c\uc138\uc694</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>\uac31\uc2e0\ub41c OSD \ud50c\ub798\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>\uc544\uc6c3</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>\uc778</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>\ub2e4\uc6b4</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>\ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD \uc190\uc2e4</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>\uc190\uc2e4 \ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>\uc644\uc804\uc81c\uac70</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>\uc644\uc804\uc81c\uac70\ub41c</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>\ud30c\uad34\ub428</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>\ud30c\uad34\ub41c</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>\ud30c\uad34\ub428</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>\uc77d\uc740 \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>\uc4f0\uae30\ub41c \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>\uc77d\uae30 ops</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>\uc4f0\uae30 ops</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\ud45c\uc2dc\ub41c OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\ud45c\uc2dc\ub41c \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>\ucd5c\ub300 \ubc31\ud544\ub4e4</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>\ucd5c\ub300 \ud65c\uc131\ud654\ub97c \ubcf5\uad6c\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>\ucd5c\ub300 \ub2e8\uc77c \uc2dc\uc791\uc744 \ubcf5\uad6c\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>\uc7a0\uc790\uae30\ub97c \ubcf5\uad6c\ud558\uae30</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>\ucee4\uc2a4\ud140</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>\uac31\uc2e0\ub41c OSD \ubcf5\uad6c \uc18d\ub3c4 \uc6b0\uc120\uc21c\uc704 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> \uc740 \ub2e4\uc74c\uc758 OSD\ub4e4 \uc548\uc5d0 \ucd08\uae30\ud654\ub428: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>\uc77c</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>\uc2ec\uac01\ub3c4</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>\uc2dc\uc791\ub41c</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>\uac31\uc2e0\ub41c</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>\uc0ac\uc6a9\ub41c</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>\uc774\uc6a9\uac00\ub2a5:</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>\uae68\ub057\ud55c</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>\uc815\uc0c1\ub3d9\uc791\uc911</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>\uacbd\uace0</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>\uc54c\ub824\uc9c0\uc9c0 \uc54a\uc740</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>\uc815\uc0c1</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>\ud30c\uc77c\uc2dc\uc2a4\ud15c\ub4e4 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>\ud65c\uc131\ud654\ub41c</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>\ub300\uae30\uc911\uc778</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>\uc774\uc6a9\ubd88\uac00</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>\ud65c\uc131\ud654\ub41c \ub370\ubaac\ub4e4</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>\uc815\uc871\uc218</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>NFS Ganesha \uc11c\ube44\uc2a4\uac00 \uc124\uc815\ub418\uc9c0 \uc54a\uc74c</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>\uc804\uc1a1</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS \uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>CephFS \ud30c\uc77c\uc2dc\uc2a4\ud15c</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(\uc804\uc5ed \uad6c\uc131\uc5d0\uc11c \uc0c1\uc18d)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>\uc804\uc5ed \uad6c\uc131\uc5d0\uc11c \uc0c1\uc18d</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>- \uc5b4\ub5a4 \uc885\ub958\uc758 \uc0ac\uc6a9\uc790 ID \uc2a4\ucffc\uc2dc\uac00 \uc218\ud589\ub418\ub294\uc9c0 \uc120\ud0dd -</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>\uc0ac\uc6a9\uac00\ub2a5\ud55c \ub370\ubaac\uc774 \uc5c6\uc74d\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>\uce90\uc26c\ubaa8\ub4dc</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>\ucd5c\uc18c \ud1f4\uac70 \uc5f0\ub839</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>\ucd5c\uc18c \ud50c\ub7ec\uc2dc \uc5f0\ub839</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>\ubaa9\ud45c \ucd5c\ub300 \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>\ubaa9\ud45c \ucd5c\ub300 \uc624\ube0c\uc81d\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>\ucd94\uac00\ub41c \uc751\uc6a9\ud504\ub85c\uadf8\ub7a8 \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>\uc751\uc6a9\ud504\ub85c\uadf8\ub7a8 \ud55c\uacc4\uc5d0 \ub3c4\ub2ec\ud568</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>\ud558\ub098\uc758 \ud480\uc740 \uc624\uc9c1 \ub124\uac1c\uc758 \uc751\uc6a9\ud504\ub85c\uadf8\ub7a8 \uc815\uc758\ub4e4\uc744 \uac00\uc9c8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target> \'_a-zA-Z0-9\' \ubb38\uc790\ub4e4\ub9cc \ud5c8\ub77d\ub428</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>\ucd5c\ub300 \uae38\uc774\ub294 128\uae00\uc790\uc774\ub2e4.</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>\ud544\ud130 \ub610\ub294 \ucd94\uac00\ub41c \uc751\uc6a9\ud504\ub85c\uadf8\ub7a8\ub4e4</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>\uc751\uc6a9\ud504\ub85c\uadf8\ub7a8 \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>Erasure \ucf54\ub4dc \ud504\ub85c\ud30c\uc77c</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>\ubcf5\uc81c \ud06c\uae30</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\ub9c8\uc9c0\ub9c9 \ubcc0\uacbd</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Erasure \ucf54\ub4dc\ud654\ub41c \ud504\ub85c\ud30c\uc77c</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>\ud06c\ub7ec\uc26c \ub8f0\uc14b</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>\uc4f0\uc5ec\uc9c4 \ubc14\uc774\ud2b8\ub4e4</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>\ubc84\ud0b7</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\uac31\uc2e0\ub41c \uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc5b4 \ubc84\ud0b7 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\uc0dd\uc131\ub41c \uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774 \ubc84\ud0b7 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>\ubc84\ud0b7\ub4e4</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>\uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\uac31\uc2e0\ub41c \uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc0ac\uc6a9\uc790 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\uc0dd\uc131\ub41c \uc624\ube0c\uc81d\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc0ac\uc6a9\uc790 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>\uc0ac\uc6a9\uc790\ub4e4</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>\ubc94\uc704</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>\uc77d\uae30</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>\ub9cc\ub4e4\uae30</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\uc0dd\uc131\ub41c \ub864 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\uac31\uc2e0\ub41c \ub864 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>\uc2dc\uc2a4\ud15c \ub864</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\uc0ad\uc81c\ub41c \ub864 \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\uc0dd\uc131\ub41c \uc0ac\uc6a9\uc790 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>\uac31\uc2e0\ub41c \uc0ac\uc6a9\uc790</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>\uacc4\uc18d</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>\ub2f9\uc2e0\uc758 \ub864\ub4e4\uc774 \ubcc0\uacbd\ub418\uc5b4 \ub2f9\uc2e0\uc740 \uc790\ub3d9\uc801\uc73c\ub85c \ub85c\uadf8\uc544\uc6c3\ub418\uc5c8\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\uac31\uc2e0\ub41c \uc0ac\uc6a9\uc790 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\uc0ad\uc81c\ub41c \uc0ac\uc6a9\uc790 &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\uc0ac\uc6a9\uc790 \uc0ad\uc81c\uac00 \uc2e4\ud3d0\ub41c &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>\ub2f9\uc2e0\uc740 \ud604\uc7ac &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; \ub85c \ub85c\uadf8\uc778\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>\uac01\uac01\uc758 \uc624\ube0c\uc81d\ud2b8\ub4e4\uc740 \ub370\uc774\ud0c0-\uccad\ud06c \ubd80\ubd84\ub4e4\ub85c \ubd84\ub9ac\ub418\uc5b4, \uac01\uae30 \ub2e4\ub978 OSD\uc5d0 \ubcf4\uad00\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>\uac01 \uc624\ube0c\uc81d\ud2b8\ub4e4\uc5d0 \ub300\ud55c \ucf54\ub529 \uccad\ud06c\ub97c \uacc4\uc0b0\ud558\uace0 \uc11c\ub85c \ub2e4\ub978 OSD\uc5d0 \uc800\uc7a5\ud569\ub2c8\ub2e4. \n\ucf54\ub529\ub41c \uccad\ud06c\uc758 \uc218\ub294 \ub370\uc774\ud130 \uc190\uc2e4\uc5c6\uc774 \uc791\ub3d9\uc911\uc9c0 \ub418\uc5b4 \uc9c8 \uc218\uc788\ub294 OSD\uc758 \uc22b\uc790\uc774\uae30\ub3c4\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Jerasure \ud50c\ub7ec\uadf8\uc778\uc740 \uac00\uc7a5 \uc77c\ubc18\uc801\uc774\uace0 \uc720\uc5f0\ud55c \ud50c\ub7ec\uadf8\uc778\uc73c\ub85c,\n\ub610\ud55c Ceph erasure \ucf54\ub4dc \ud480\uc758 \uae30\ubcf8\uac12\uc774\uae30\ub3c4\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>\ubcf4\ub2e4 \uc720\uc5f0\ud55c \uae30\uc220\uc740 reed_sol_van\uc785\ub2c8\ub2e4 : k\uc640 m\uc744 \uc124\uc815\ud558\uba74 \ucda9\ubd84\ud569\ub2c8\ub2e4. \ncauchy_good \uae30\uc220\uc740 \ube60\ub97c \uc218 \uc788\uc9c0\ub9cc \ud328\ud0b7\ud06c\uae30\ub97c \uc8fc\uc758\uae4a\uac8c \uc120\ud0dd\ud574\uc57c\ud569\ub2c8\ub2e4. \nreed_sol_r6_op, liberation, blaum_roth, liber8tion\uc740 \ubaa8\ub450 m = 2\ub85c\ub9cc \uad6c\uc131 \ud560 \uc218 \uc788\ub2e4\ub294 \uc810\uc5d0\uc11c RAID-6\uc5d0 \ud574\ub2f9\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>\uc778\ucf54\ub529\uc740 \ud55c\ubc88\uc5d0 \ubc14\uc774\ud2b8\ub4e4 \ud06c\uae30\uc758 \ud328\ud0b7\uc5d0 \ub300\ud574 \uc218\ud589\ub429\ub2c8\ub2e4. \uc62c\ubc14\ub978 \ud328\ud0b7 \ud06c\uae30\ub97c \uc120\ud0dd\ud558\ub294 \uac83\uc740 \uc5b4\ub835\uc2b5\ub2c8\ub2e4. jerasure \ubb38\uc11c\uc5d0\ub294\uc774 \uc8fc\uc81c\uc5d0 \ub300\ud55c \uad11\ubc94\uc704\ud55c \uc815\ubcf4\uac00 \ub4e4\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>jerasure \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uba74 \uc0ad\uc81c \ub41c \ucf54\ub529 \ub41c \uac1d\uccb4\uac00 \uc5ec\ub7ec OSD\uc5d0 \uc800\uc7a5 \ub420 \ub54c \ud558\ub098\uc758 OSD\uac00 \uc190\uc2e4\ub418\ub294 \uac83\uc744 \ubcf5\uad6c\ud558\ub824\uba74 \ub2e4\ub978 \ubaa8\ub4e0 OSD\ub97c \uc77d\uc5b4\uc57c\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 jerasure\uac00 k = 8 \ubc0f m = 4\ub85c \uad6c\uc131\ub418\uc5b4\uc788\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 OSD\ub97c \uc783\uc5b4 \ubc84\ub9ac\uba74 11 \uba85\uc758 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc218\ub9ac\ud574\uc57c\ud569\ub2c8\ub2e4.\nlrc erasure code plugin\uc740 \uc801\uc740 \uc591\uc758 OSD\ub97c \uc0ac\uc6a9\ud558\uc5ec \ubcf5\uad6c \ud560 \uc218 \uc788\ub3c4\ub85d \ub85c\uceec \ud328\ub9ac\ud2f0 \uccad\ud06c\ub97c \ub9cc\ub4ed\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, lrc\uac00 k = 8, m = 4 \ubc0f l = 4\ub85c \uad6c\uc131\ub41c \uacbd\uc6b0 4 \uac1c\uc758 OSD\ub9c8\ub2e4 \ucd94\uac00 \ud328\ub9ac\ud2f0 \ub369\uc5b4\ub9ac\uac00 \uc0dd\uc131\ub429\ub2c8\ub2e4. \ub2e8\uc77c OSD\uac00 \uc190\uc2e4\ub418\uba74 11 \uac1c \ub300\uc2e0 4 \uac1c\uc758 OSD\ub9cc\uc73c\ub85c \ubcf5\uad6c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>\ucf54\ub529 \ubc0f \ub370\uc774\ud130 \uccad\ud06c\ub97c \ud06c\uae30 \uc9c0\uc5ed \uc9d1\ud569\uc73c\ub85c \uadf8\ub8f9\ud654\ud569\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, k = 4 \ubc0f m = 2\uc5d0 \ub300\ud574, \uc9c0\uc5ed\uc131 = 3 \uc77c \ub54c \ub450 \uac1c\uc758 \uc138 \uadf8\ub8f9\uc774 \uc0dd\uc131\ub429\ub2c8\ub2e4. \uac01 \uc138\ud2b8\ub294 \ub2e4\ub978 \uc138\ud2b8\uc758 \uccad\ud06c\ub97c \uc77d\uc9c0 \uc54a\uace0\ub3c4 \ubcf5\uad6c \ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>l\ub85c \uc815\uc758 \ub41c \uac01 \uccad\ud06c \uc9d1\ud569\uc774 \uc800\uc7a5\ub418\ub294 \ud06c\ub7ec\uc2dc \ubc84\ud0b7\uc758 \uc720\ud615\uc785\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 \ub799\uc73c\ub85c \uc124\uc815\ud558\uba74 l \uac1c\uc758 \uccad\ud06c \uadf8\ub8f9\uc774 \uac01\uac01 \ub2e4\ub978 \ub799\uc5d0 \ubc30\uce58\ub429\ub2c8\ub2e4. \n\ub799 \uc120\ud0dd \ub2e8\uacc4\uc640 \uac19\uc740 CRUSH \uaddc\uce59 \ub2e8\uacc4\ub97c \ub9cc\ub4dc\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc124\uc815\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74, \uadf8\ub7ec\ud55c \uadf8\ub8f9\ud654\uac00 \uc218\ud589\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>isa \ud50c\ub7ec\uadf8\uc778\uc740 ISA \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \ucea1\uc290\ud654\ud569\ub2c8\ub2e4. \uc778\ud154 \ud504\ub85c\uc138\uc11c\uc5d0\uc11c\ub9cc \uc2e4\ud589\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>ISA \ud50c\ub7ec\uadf8\uc778\uc740 \ub450 \uac1c\uc758 \ub9ac\ub4dc \uc194\ub85c\ubaac \ud615\uc2dd\uc73c\ub85c \uc81c\uacf5\ub429\ub2c8\ub2e4.\nreed_sol_van\uc774 \uc124\uc815\ub418\uba74 Vandermonde, cauchy\uac00 \uc124\uc815\ub418\uba74 Cauchy\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>shec plugin\uc740 \ub2e4\uc911 SHEC \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \ucea1\uc290\ud654\ud569\ub2c8\ub2e4.\n\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0 ceph\uac00 \ub9ac\ub4dc \uc194\ub85c\ubaac \ucf54\ub4dc\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcf5\uad6c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>\uac01 \ub370\uc774\ud130 \uccad\ud06c\uac00 \uacc4\uc0b0 \ubc94\uc704\uc5d0 \ud3ec\ud568\ub418\ub294 \ud328\ub9ac\ud2f0 \uccad\ud06c\uc758 \uc218\uc785\ub2c8\ub2e4. \uc774 \uc218\uce58\ub294 \ub0b4\uad6c\uc131 \uce21\uc815\uae30\ub85c \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, c = 2 \uc778 \uacbd\uc6b0 2 \uac1c\uc758 OSD\uac00 \ub370\uc774\ud130 \uc190\uc2e4\uc5c6\uc774 \uc911\ub2e8 \ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>CRUSH \uaddc\uce59\uc758 \uccab \ubc88\uc9f8 \ub2e8\uacc4\uc5d0 \uc0ac\uc6a9 \ub41c \ud06c\ub7ec\uc2dc \ubc84\ud0b7\uc758 \uc774\ub984\uc785\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4 step\uc740 \uae30\ubcf8\uac12\uc744 \ucde8\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>\ub3d9\uc77c\ud55c \uc2e4\ud328 \ub3c4\uba54\uc778\uc744 \uac00\uc9c4 \uc591\ub3d9\uc774\uc5d0 \ub450 \uac1c\uc758 \uccad\ud06c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624. \uc608\ub97c \ub4e4\uc5b4 \uc2e4\ud328 \ub3c4\uba54\uc778\uc774 \ud638\uc2a4\ud2b8 \uc778 \uacbd\uc6b0 \ub450 \uac1c\uc758 \uccad\ud06c\uac00 \ub3d9\uc77c\ud55c \ud638\uc2a4\ud2b8\uc5d0 \uc800\uc7a5\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc774 \ub2e8\uacc4\ub294 \ub9ac\ud504 \ud638\uc2a4\ud2b8\ub97c \uc120\ud0dd\ud558\ub294 \ub2e8\uacc4\uc640 \uac19\uc740 CRUSH \uaddc\uce59 \ub2e8\uacc4\ub97c \ub9cc\ub4dc\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>CRUSH\uc9c0\ub3c4\uc5d0\uc11c \ud06c\ub798\uc2dc \uc7a5\uce58 \ud074\ub798\uc2a4 \uc774\ub984\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b9\uc815 \ud074\ub798\uc2a4 (\uc608 : ssd \ub610\ub294 hdd)\uc758 \uc7a5\uce58\ub85c \ubc30\uce58\ub97c \uc81c\ud55c\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>\uc0ad\uc81c \ucf54\ub4dc \ud50c\ub7ec\uadf8\uc778\uc774\ub85c\ub4dc\ub418\ub294 \ub514\ub809\ud1a0\ub9ac \uc774\ub984\uc744 \uc124\uc815\ud558\uc2ed\uc2dc\uc624.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>\ubaa8\ub4e0 \uc791\uc5c5\ub4e4 \ud5c8\uc6a9</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>\uc624\uc9c1 \uc11c\ubc84\ub97c \uc218\uc815\ud558\uc9c0 \uc54a\ub294 \uc791\uc5c5\ub4e4\ub9cc \uac00\ub2a5\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>\uc77d\uae30\uc640 \uc4f0\uae30 \uc791\uc5c5\uc740 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc9c0\ub9cc, \uadf8\uc678 \ubaa8\ub4e0 \uc791\uc5c5\uc774 \uac00\ub2a5\ud569\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>\ud30c\uc77c\uc758 \uc18d\uc131\uacfc \ub514\ub809\ud1a0\ub9ac \ub0b4\uc6a9\uc744 \ubcc0\uacbd\ud558\ub294 \uc77d\uae30, \uc4f0\uae30 \ub610\ub294 \uc5b4\ub5a0\ud55c \uc791\uc5c5\uc740 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>\uc804\ud600 \uc5b4\ub5a0\ud55c \uc811\uadfc\ub3c4 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- \uc6b0\uc120\uc21c\uc704 \uc120\ud0dd --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>\ub0ae\uc74c</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>\ub192\uc74c</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\ub9c8\uc9c0\ub9c9 5\ubd84</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\uc9c0\ub09c 15\ubd84</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\uc9c0\ub09c 30\ubd84</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\uc9c0\ub09c 1\uc2dc\uac04(\uae30\ubcf8)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\uc9c0\ub09c 3\uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\uc9c0\ub09c 6\uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\uc9c0\ub09c 12\uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\uc9c0\ub09c 24\uc2dc\uac04</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>\uc5b4\uc81c</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>\uc624\ub298</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>\uc624\ub298 \uc9c0\uae08\uae4c\uc9c0</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>\uadf8\uc800\uaed8</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>\uc9c0\ub09c 2\uc77c</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>\uc774\ubc88 \uc8fc \ub9c8\uc9c0\ub9c9\ub0a0</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>\uc804\uc8fc</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>\uc774\ubc88\uc8fc</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>\uc774\ubc88\uc8fc \uc9c0\uae08\uae4c\uc9c0</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>\uc9c0\ub09c 7\uc77c</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>\uc9c0\ub09c \ub2ec</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>\uc774\ubc88 \ub2ec</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>\uc774\ubc88 \ub2ec \uc9c0\uae08\uae4c\uc9c0</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>\uc9c0\ub09c 30\uc77c</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>\uc9c0\ub09c 90\uc77c</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>\uc9c0\ub09c 6\uac1c\uc6d4</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>\uc9c0\ub09c 1\ub144</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>\uc804\ub144\ub3c4</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>\uae08\ub144\ub3c4</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>\uae08\ub144 \uc9c0\uae08\uae4c\uc9c0</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>\uc9c0\ub09c 2\ub144</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>\uc9c0\ub09c 5\ub144</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>\uc815\ubcf4</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>\uc120\ud0dd\ub41c \uc544\uc774\ud15c \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>\ub2e4\uc2dc \uc120\ud0dd\ud558\uae30 \uc704\ud574 \uc544\uc774\ud15c \uc120\ud0dd\uc744 \ucde8\uc18c</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>\uc120\ud0dd \ud55c\uacc4\uc5d0 \ub3c4\ub2ec\ud568</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>\ud544\ud130 \ud14c\uadf8\ub4e4</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>\ubca0\ucc0c \ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>\uc0ac\uc6a9\uac00\ub2a5\ud55c \uc544\uc774\ud15c \uc5c6\uc74c</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>\ucd94\uac00</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>\ubcf5\uc81c</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>\ubcf5\uc0ac</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>\ub525 \uc2a4\ud06c\ub7fd</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>\ud30c\uad34\ub428</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>\ub2e8\uc870\ub85c\uc6c0</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>\ub2e4\uc6b4 \ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>\uc778 \ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>\uc190\uc2e4 \ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>\uc544\uc6c3 \ud45c\uc2dc</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>\ubcf4\ud638</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>\uc774\ub984\ubcc0\uacbd</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>\ubcf5\uad6c</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>\ud734\uc9c0\ud1b5\uc73c\ub85c \uc62e\uae30\uae30</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>\ubcf4\ud638\uc54a\ub428</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>\uc0ad\uc81c\ub3d4</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>\ubcf5\uc81c\ub41c</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>\ubcf5\uc0ac\ub41c</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>\uc608</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>\uc544\ub2c8\uc624</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>\uc11c\ube44\uc2a4 \ub7c9</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS \ud55c\uacc4</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 IO \ubc14\uc774\ud2b8 \uc218 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS \uc81c\ud55c</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 IO \uc791\uc5c5 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>\uc77d\uae30 BPS \uc81c\ud55c</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 \uc77d\uae30 \ubc14\uc774\uc2a4 \uc218 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>\uc77d\uae30 IOPS \ud55c\ub3c4</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 \uc77d\uae30 \uc791\uc5c5 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>\uc4f0\uae30 BPS \ud55c\ub3c4</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 \uc4f0\uae30 \ubc14\uc774\ud2b8 \uc218 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>\uc4f0\uae30 IOPS \uc81c\ud55c</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>\uc6d0\ud558\ub294 \ucd08\ub2f9 \uc4f0\uae30 \uc791\uc5c5 \uc81c\ud55c\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>\uc6d0\ud558\ub294 \ubc84\uc2a4\ud2b8 IO \ubc14\uc774\ud2b8 \ud55c\ub3c4 \uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>\uc6d0\ud558\ub294 IO \uc791\uc5c5\uc758 \ubc84\uc2a4\ud2b8 \ud55c\uacc4\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>\uc77d\uae30 BPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>\uc6d0\ud558\ub294 \uc77d\uae30 \ubc84\uc2a4\ud2b8 \ud55c\uacc4\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>\uc77d\uae30 IOPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>\uc6d0\ud558\ub294 \uc77d\uae30 \uc791\uc5c5\uc758 \ubc84\uc2a4\ud2b8 \ud55c\ub3c4\uc785\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>\uc4f0\uae30 BPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>\uc4f0\uae30 \ubc14\uc774\ud2b8\uc758 \uc6d0\ud558\ub294 \ubc84\uc2a4\ud2b8 \ud55c\ub3c4.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>\uc4f0\uae30 IOPS \ubc84\uc2a4\ud2b8</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>\uc4f0\uae30 \ubc14\uc774\ud2b8\uc758 \uc6d0\ud558\ub294 \ubc84\uc2a4\ud2b8 \ud55c\ub3c4.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/> \uc758 \uc2e4\ud3d0\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>\uc218\ud589\uc911</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>\uc218\ud589</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>\uc218\ud589\ub41c</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>\uc54c\ub824\uc9c0\uc9c0 \uc54a\ub294 \uc791\uc5c5</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>\uc0dd\uc131\ud558\ub294 \uc911</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>\uc0dd\uc131</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>\uac31\uc2e0 \uc911</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>\uac31\uc2e0</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>\uc0ad\uc81c \uc911</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>\uc0ad\uc81c</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \uc2a4\ub0c5\uc0bf \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\ud480 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \uc744 \uc704\ud55c \ubbf8\ub7ec\ubaa8\ub4dc\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\ud480 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \ubbf8\ub7ec \uc0c1\ub300\ubc29\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>\uc774\ub984\uc740 \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\uc5d0 \uc758\ud558\uc5ec \uc774\ubbf8 \uc0ac\uc6a9\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>\uc774\ub984\uc740 \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\uc5d0 \uc758\ud558\uc5ec \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>\uc774\ub984\uc774 \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\uc5d0 \uc758\ud558\uc5ec \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> \uc774 \ud3ec\ud568\ub41c \uc2a4\ub0c5\uc0bf\ub4e4.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>\ubcf5\uc81c\uc911</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>\ubcf5\uc81c</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>\ubc18\ub4dc\uc2dc\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\uc758 \uc2a4\ub0c5\uc0bf\uc740 \ubcf4\ud638\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>\ubcf5\uc0ac\uc911</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>\ubcf5\uc0ac</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>\ud3c9\ud3c9\ud558\uac8c \ud558\ub294 \uc911</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>\ud3c9\ud3c9\ud568</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>\ud3c9\ud3c9\ud558\uac8c \ub428</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>\uc774\ub984\uc774 \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\uc5d0 \uc758\ud558\uc5ec \uc774\ubbf8 \uc0ac\uc6a9 \uc911.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\uc744 \ubcf4\ud638\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc65c\ub0d0\ud558\uba74 \uadf8\uac83\uc740 \uc790\uc2dd \uc774\ubbf8\uc9c0\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4,\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> \uc744 \uc0ad\uc81c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \uc65c\ub0d0\ud558\uba74 \uadf8\uac83\uc740 \ubcf4\ud638\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>\ub864\ubc31 \uc911</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>\ub864\ubc31</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>\ub864\ubc31\ub428</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>\uc62e\uae30\ub294 \uc911</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>\uc62e\uae30\uae30</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>\uc62e\uaca8\uc9d0</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>\uc774\ubbf8\uc9c0 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \ubc84\ub9ac\uae30\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>\uc774\ubbf8\uc9c0\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>\ubcf5\uad6c\uc911</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>\ubcf5\uad6c</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>\ubcf5\uad6c\ub428</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>\uc774\ubbf8\uc9c0 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \uc744 \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\' \ub85c\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>\uc774\ubbf8\uc9c0 \uc774\ub984 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \uc774 \uc774\ubbf8 \uc0ac\uc6a9\uc911\uc785\ub2c8\ub2e4.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\uc774\ubbf8\uc9c0 \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>\uc644\uc804\uc0ad\uc81c \uc911</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>\uc644\uc804\uc0ad\uc81c</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>\uc644\uc804\uc0ad\uc81c\ub428</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>\ubaa8\ub4e0 \ud480\ub4e4</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{message}}"/>\ub85c \ubd80\ud130\uc758 \uc774\ubbf8\uc9c0\ub4e4\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>\ud53c\uc5b4\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uae30 \ub54c\ubb38\uc5d0 \ubbf8\ub7ec\ub9c1\uc744 \ube44\ud65c\uc131\ud654 \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>\ud480 \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>Erasure \ucf54\ub4dc \ud504\ub85c\ud30c\uc77c \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>\ud0c0\uae43 \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},QC43:function(t,e,n){"use strict";var a=n("CcnG"),r=n("MdoF"),i=n("lTVp");n("XFyV"),n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o});var s=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"alert",[["type","info"]],null,null,null,r.c,r.b)),a["\u0275did"](1,114688,null,0,i.a,[i.b,a.ChangeDetectorRef],{type:[0,"type"]},null),(t()(),a["\u0275eld"](2,0,null,0,1,"strong",[],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-spinner fa-spin fa-fw"]],null,null,null,null,null)),a["\u0275ncd"](0,0)],function(t,e){t(e,1,0,"info")},null)}},QFaf:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(e,n,a){var r=t.call(this,e,n,a)||this;return r.controls=e,r}return a.__extends(e,t),e.prototype.get=function(t){var e=this._get(t);if(!e)throw new Error("Control '"+t+"' could not be found!");return e},e.prototype._get=function(n){return t.prototype.get.call(this,n)||Object.values(this.controls).filter(function(t){return t.get}).map(function(t){return t instanceof e?t._get(n):t.get(n)}).find(function(t){return Boolean(t)})},e.prototype.getValue=function(t){return this.get(t).value},e.prototype.silentSet=function(t,e){this.get(t).setValue(e,{emitEvent:!1})},e.prototype.showError=function(t,e,n){var a=this.get(t);return(e.submitted||a.dirty)&&(n?a.hasError(n):a.invalid)},e}(n("gIcY").k)},QG5k:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NodeMenuItemAction=function(t){return t[t.NewFolder=0]="NewFolder",t[t.NewTag=1]="NewTag",t[t.Rename=2]="Rename",t[t.Remove=3]="Remove",t[t.Custom=4]="Custom",t}(e.NodeMenuItemAction||{}),e.NodeMenuAction=function(t){return t[t.Close=0]="Close",t}(e.NodeMenuAction||{})},QGcS:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NodeDraggableEvent=function(){return function(t,e){this.captured=t,this.target=e}}()},QHrR:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("Y0Co")),a(n("Lwhh")),a(n("8iEZ")),a(n("L5sC"))},QTAa:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e}(n("t/zF").a)},Qexa:function(t,e,n){"use strict";t.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},Qgas:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("dC0D"),r=n("AxiF"),i=n("HJBe"),s=n("y3By");function o(t,e){return arguments.length>=2?function(n){return Object(s.a)(Object(a.a)(t,e),Object(r.a)(1),Object(i.a)(e))(n)}:function(e){return Object(s.a)(Object(a.a)(function(e,n,a){return t(e,n,a+1)}),Object(r.a)(1))(e)}}},Qj4J:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ar-kw",{months:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062a\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u062d\u062f_\u0627\u062a\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",ss:"%d \u062b\u0627\u0646\u064a\u0629",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:0,doy:12}})}()},"R+r5":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("Qgas");function r(t,e,n){return 0===n?[e]:(t.push(e),t)}function i(){return Object(a.a)(r,[])}},RAwQ:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return e?r[n][0]:r[n][1]}function a(t){if(t=parseInt(t,10),isNaN(t))return!1;if(t<0)return!0;if(t<10)return 4<=t&&t<=7;if(t<100){var e=t%10;return a(0===e?t/10:e)}if(t<1e4){for(;t>=10;)t/=10;return a(t)}return a(t/=1e3)}n("wd/R").defineLocale("lb",{months:"Januar_Februar_M\xe4erz_Abr\xebll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_M\xe9indeg_D\xebnschdeg_M\xebttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._M\xe9._D\xeb._M\xeb._Do._Fr._Sa.".split("_"),weekdaysMin:"So_M\xe9_D\xeb_M\xeb_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[G\xebschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:function(t){return a(t.substr(0,t.indexOf(" ")))?"a "+t:"an "+t},past:function(t){return a(t.substr(0,t.indexOf(" ")))?"viru "+t:"virun "+t},s:"e puer Sekonnen",ss:"%d Sekonnen",m:e,mm:"%d Minutten",h:e,hh:"%d Stonnen",d:e,dd:"%d Deeg",M:e,MM:"%d M\xe9int",y:e,yy:"%d Joer"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},RCHg:function(t,e,n){"use strict";var a=n("wd/R");a="function"==typeof a?a:window.moment;var r=n("CDJp"),i=n("RDha"),s=n("cdu6"),o=n("tjFV"),u=Number.MIN_SAFE_INTEGER||-9007199254740991,c=Number.MAX_SAFE_INTEGER||9007199254740991,l={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,15,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,15,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},d=Object.keys(l);function f(t,e){return t-e}function p(t){var e,n,a,r={},i=[];for(e=0,n=t.length;e<n;++e)r[a=t[e]]||(r[a]=!0,i.push(a));return i}function h(t,e,n,a){var r=function(t,e,n){for(var a,r,i,s=0,o=t.length-1;s>=0&&s<=o;){if(i=t[a=s+o>>1],!(r=t[a-1]||null))return{lo:null,hi:i};if(i[e]<n)s=a+1;else{if(!(r[e]>n))return{lo:r,hi:i};o=a-1}}return{lo:i,hi:null}}(t,e,n),i=r.lo?r.hi?r.lo:t[t.length-2]:t[0],s=r.lo?r.hi?r.hi:t[t.length-1]:t[1],o=s[e]-i[e];return i[a]+(s[a]-i[a])*(o?(n-i[e])/o:0)}function g(t,e){var n=e.parser,r=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof r?a(t,r):(t instanceof a||(t=a(t)),t.isValid()?t:"function"==typeof r?r(t):t)}function b(t,e){if(i.isNullOrUndef(t))return null;var n=e.options.time,a=g(e.getRightValue(t),n);return a.isValid()?(n.round&&a.startOf(n.round),a.valueOf()):null}function m(t){for(var e=d.indexOf(t)+1,n=d.length;e<n;++e)if(l[d[e]].common)return d[e]}t.exports=function(){var t=s.extend({initialize:function(){if(!a)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),s.prototype.initialize.call(this)},update:function(){var t=this.options;return t.time&&t.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),s.prototype.update.apply(this,arguments)},getRightValue:function(t){return t&&void 0!==t.t&&(t=t.t),s.prototype.getRightValue.call(this,t)},determineDataLimits:function(){var t,e,n,r,s,o,l=this,d=l.chart,h=l.options.time,g=h.unit||"day",m=c,y=u,v=[],_=[],x=[];for(t=0,n=d.data.labels.length;t<n;++t)x.push(b(d.data.labels[t],l));for(t=0,n=(d.data.datasets||[]).length;t<n;++t)if(d.isDatasetVisible(t))if(i.isObject((s=d.data.datasets[t].data)[0]))for(_[t]=[],e=0,r=s.length;e<r;++e)o=b(s[e],l),v.push(o),_[t][e]=o;else v.push.apply(v,x),_[t]=x.slice(0);else _[t]=[];x.length&&(x=p(x).sort(f),m=Math.min(m,x[0]),y=Math.max(y,x[x.length-1])),v.length&&(v=p(v).sort(f),m=Math.min(m,v[0]),y=Math.max(y,v[v.length-1])),m=b(h.min,l)||m,y=b(h.max,l)||y,m=m===c?+a().startOf(g):m,y=y===u?+a().endOf(g)+1:y,l.min=Math.min(m,y),l.max=Math.max(m+1,y),l._horizontal=l.isHorizontal(),l._table=[],l._timestamps={data:v,datasets:_,labels:x}},buildTicks:function(){var t,e,n,r=this,s=r.min,o=r.max,u=r.options,f=u.time,p=[],y=[];switch(u.ticks.source){case"data":p=r._timestamps.data;break;case"labels":p=r._timestamps.labels;break;case"auto":default:p=function(t,e,n,r){var s,o=r.time,u=o.unit||function(t,e,n,a){var r,i,s=d.length;for(r=d.indexOf(o.minUnit);r<s-1;++r)if((i=l[d[r]]).common&&Math.ceil((n-e)/((i.steps?i.steps[i.steps.length-1]:c)*i.size))<=a)return d[r];return d[s-1]}(0,t,e,n),f=m(u),p=i.valueOrDefault(o.stepSize,o.unitStepSize),h="week"===u&&o.isoWeekday,g=r.ticks.major.enabled,b=l[u],y=a(t),v=a(e),_=[];for(p||(p=function(t,e,n,a){var r,i,s,o=e-t,c=l[u],d=c.size,f=c.steps;if(!f)return Math.ceil(o/(a*d));for(r=0,i=f.length;r<i&&(s=f[r],!(Math.ceil(o/(d*s))<=a));++r);return s}(t,e,0,n)),h&&(y=y.isoWeekday(h),v=v.isoWeekday(h)),y=y.startOf(h?"day":u),(v=v.startOf(h?"day":u))<e&&v.add(1,u),s=a(y),g&&f&&!h&&!o.round&&(s.startOf(f),s.add(~~((y-s)/(b.size*p))*p,u));s<v;s.add(p,u))_.push(+s);return _.push(+s),_}(s,o,r.getLabelCapacity(s),u)}for("ticks"===u.bounds&&p.length&&(s=p[0],o=p[p.length-1]),s=b(f.min,r)||s,o=b(f.max,r)||o,t=0,e=p.length;t<e;++t)(n=p[t])>=s&&n<=o&&y.push(n);return r.min=s,r.max=o,r._unit=f.unit||function(t,e,n,i){var s,o,u=a.duration(a(r.max).diff(a(n)));for(s=d.length-1;s>=d.indexOf(e);s--)if(l[o=d[s]].common&&u.as(o)>=t.length)return o;return d[e?d.indexOf(e):0]}(y,f.minUnit,r.min),r._majorUnit=m(r._unit),r._table=function(t,e,n,a){if("linear"===u.distribution||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var r,i,s,o,c,l=[],d=[e];for(r=0,i=t.length;r<i;++r)(o=t[r])>e&&o<n&&d.push(o);for(d.push(n),r=0,i=d.length;r<i;++r)c=d[r+1],o=d[r],void 0!==(s=d[r-1])&&void 0!==c&&Math.round((c+s)/2)===o||l.push({time:o,pos:r/(i-1)});return l}(r._timestamps.data,s,o),r._offsets=function(t,e,n,a,r){var i,s=0,o=0;return r.offset&&e.length&&(r.time.min||(i=e[0],s=(h(t,"time",e.length>1?e[1]:a,"pos")-h(t,"time",i,"pos"))/2),r.time.max||(i=e.length>1?e[e.length-2]:n,o=(h(t,"time",e[e.length-1],"pos")-h(t,"time",i,"pos"))/2)),{left:s,right:o}}(r._table,y,s,o,u),r._labelFormat=function(t,e){var n,a,r,i=t.length;for(n=0;n<i;n++){if(0!==(a=g(t[n],e)).millisecond())return"MMM D, YYYY h:mm:ss.SSS a";0===a.second()&&0===a.minute()&&0===a.hour()||(r=!0)}return r?"MMM D, YYYY h:mm:ss a":"MMM D, YYYY"}(r._timestamps.data,f),function(t,e){var n,r,i,s,o=[];for(n=0,r=t.length;n<r;++n)i=t[n],s=!!e&&i===+a(i).startOf(e),o.push({value:i,major:s});return o}(y,r._majorUnit)},getLabelForIndex:function(t,e){var n=this.chart.data,a=this.options.time,r=n.labels&&t<n.labels.length?n.labels[t]:"",s=n.datasets[e].data[t];return i.isObject(s)&&(r=this.getRightValue(s)),a.tooltipFormat?g(r,a).format(a.tooltipFormat):"string"==typeof r?r:g(r,a).format(this._labelFormat)},tickFormatFunction:function(t,e,n,a){var r=this.options,s=t.valueOf(),o=r.time.displayFormats,u=o[this._unit],c=this._majorUnit,l=o[c],d=t.clone().startOf(c).valueOf(),f=r.ticks.major,p=f.enabled&&c&&l&&s===d,h=t.format(a||(p?l:u)),g=p?f:r.ticks.minor,b=i.valueOrDefault(g.callback,g.userCallback);return b?b(h,e,n):h},convertTicksToLabels:function(t){var e,n,r=[];for(e=0,n=t.length;e<n;++e)r.push(this.tickFormatFunction(a(t[e].value),e,t));return r},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,a=e._horizontal?e.left:e.top,r=h(e._table,"time",t,"pos");return a+n*(e._offsets.left+r)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var a=null;if(void 0!==e&&void 0!==n&&(a=this._timestamps.datasets[n][e]),null===a&&(a=b(t,this)),null!==a)return this.getPixelForOffset(a)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,r=h(e._table,"pos",(n?(t-(e._horizontal?e.left:e.top))/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,"time");return a(r)},getLabelWidth:function(t){var e=this.options.ticks,n=this.ctx.measureText(t).width,a=i.toRadians(e.maxRotation),s=Math.cos(a),o=Math.sin(a);return n*s+i.valueOrDefault(e.fontSize,r.global.defaultFontSize)*o},getLabelCapacity:function(t){var e=this,n=e.options.time.displayFormats.millisecond,r=e.tickFormatFunction(a(t),0,[],n),i=e.getLabelWidth(r),s=e.isHorizontal()?e.width:e.height,o=Math.floor(s/i);return o>0?o:1}});o.registerScaleType("time",t,{position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}})}},RDha:function(t,e,n){"use strict";t.exports=n("TC34"),t.exports.easing=n("u0Op"),t.exports.canvas=n("Sfow"),t.exports.options=n("As3K")},RnPR:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Keys=function(t){return t[t.up=38]="up",t[t.down=40]="down",t[t.return=13]="return",t[t.escape=27]="escape",t[t.left=37]="left",t[t.right=39]="right",t}(e.Keys||{})},RnhZ:function(t,e,n){var a={"./af":"K/tc","./af.js":"K/tc","./ar":"jnO4","./ar-dz":"o1bE","./ar-dz.js":"o1bE","./ar-kw":"Qj4J","./ar-kw.js":"Qj4J","./ar-ly":"HP3h","./ar-ly.js":"HP3h","./ar-ma":"CoRJ","./ar-ma.js":"CoRJ","./ar-sa":"gjCT","./ar-sa.js":"gjCT","./ar-tn":"bYM6","./ar-tn.js":"bYM6","./ar.js":"jnO4","./az":"SFxW","./az.js":"SFxW","./be":"H8ED","./be.js":"H8ED","./bg":"hKrs","./bg.js":"hKrs","./bm":"p/rL","./bm.js":"p/rL","./bn":"kEOa","./bn.js":"kEOa","./bo":"0mo+","./bo.js":"0mo+","./br":"aIdf","./br.js":"aIdf","./bs":"JVSJ","./bs.js":"JVSJ","./ca":"1xZ4","./ca.js":"1xZ4","./cs":"PA2r","./cs.js":"PA2r","./cv":"A+xa","./cv.js":"A+xa","./cy":"l5ep","./cy.js":"l5ep","./da":"DxQv","./da.js":"DxQv","./de":"tGlX","./de-at":"s+uk","./de-at.js":"s+uk","./de-ch":"u3GI","./de-ch.js":"u3GI","./de.js":"tGlX","./dv":"WYrj","./dv.js":"WYrj","./el":"jUeY","./el.js":"jUeY","./en-SG":"zavE","./en-SG.js":"zavE","./en-au":"Dmvi","./en-au.js":"Dmvi","./en-ca":"OIYi","./en-ca.js":"OIYi","./en-gb":"Oaa7","./en-gb.js":"Oaa7","./en-ie":"4dOw","./en-ie.js":"4dOw","./en-il":"czMo","./en-il.js":"czMo","./en-nz":"b1Dy","./en-nz.js":"b1Dy","./eo":"Zduo","./eo.js":"Zduo","./es":"iYuL","./es-do":"CjzT","./es-do.js":"CjzT","./es-us":"Vclq","./es-us.js":"Vclq","./es.js":"iYuL","./et":"7BjC","./et.js":"7BjC","./eu":"D/JM","./eu.js":"D/JM","./fa":"jfSC","./fa.js":"jfSC","./fi":"gekB","./fi.js":"gekB","./fo":"ByF4","./fo.js":"ByF4","./fr":"nyYc","./fr-ca":"2fjn","./fr-ca.js":"2fjn","./fr-ch":"Dkky","./fr-ch.js":"Dkky","./fr.js":"nyYc","./fy":"cRix","./fy.js":"cRix","./ga":"USCx","./ga.js":"USCx","./gd":"9rRi","./gd.js":"9rRi","./gl":"iEDd","./gl.js":"iEDd","./gom-latn":"DKr+","./gom-latn.js":"DKr+","./gu":"4MV3","./gu.js":"4MV3","./he":"x6pH","./he.js":"x6pH","./hi":"3E1r","./hi.js":"3E1r","./hr":"S6ln","./hr.js":"S6ln","./hu":"WxRl","./hu.js":"WxRl","./hy-am":"1rYy","./hy-am.js":"1rYy","./id":"UDhR","./id.js":"UDhR","./is":"BVg3","./is.js":"BVg3","./it":"bpih","./it-ch":"bxKX","./it-ch.js":"bxKX","./it.js":"bpih","./ja":"B55N","./ja.js":"B55N","./jv":"tUCv","./jv.js":"tUCv","./ka":"IBtZ","./ka.js":"IBtZ","./kk":"bXm7","./kk.js":"bXm7","./km":"6B0Y","./km.js":"6B0Y","./kn":"PpIw","./kn.js":"PpIw","./ko":"Ivi+","./ko.js":"Ivi+","./ku":"JCF/","./ku.js":"JCF/","./ky":"lgnt","./ky.js":"lgnt","./lb":"RAwQ","./lb.js":"RAwQ","./lo":"sp3z","./lo.js":"sp3z","./lt":"JvlW","./lt.js":"JvlW","./lv":"uXwI","./lv.js":"uXwI","./me":"KTz0","./me.js":"KTz0","./mi":"aIsn","./mi.js":"aIsn","./mk":"aQkU","./mk.js":"aQkU","./ml":"AvvY","./ml.js":"AvvY","./mn":"lYtQ","./mn.js":"lYtQ","./mr":"Ob0Z","./mr.js":"Ob0Z","./ms":"6+QB","./ms-my":"ZAMP","./ms-my.js":"ZAMP","./ms.js":"6+QB","./mt":"G0Uy","./mt.js":"G0Uy","./my":"honF","./my.js":"honF","./nb":"bOMt","./nb.js":"bOMt","./ne":"OjkT","./ne.js":"OjkT","./nl":"+s0g","./nl-be":"2ykv","./nl-be.js":"2ykv","./nl.js":"+s0g","./nn":"uEye","./nn.js":"uEye","./pa-in":"8/+R","./pa-in.js":"8/+R","./pl":"jVdC","./pl.js":"jVdC","./pt":"8mBD","./pt-br":"0tRk","./pt-br.js":"0tRk","./pt.js":"8mBD","./ro":"lyxo","./ro.js":"lyxo","./ru":"lXzo","./ru.js":"lXzo","./sd":"Z4QM","./sd.js":"Z4QM","./se":"//9w","./se.js":"//9w","./si":"7aV9","./si.js":"7aV9","./sk":"e+ae","./sk.js":"e+ae","./sl":"gVVK","./sl.js":"gVVK","./sq":"yPMs","./sq.js":"yPMs","./sr":"zx6S","./sr-cyrl":"E+lV","./sr-cyrl.js":"E+lV","./sr.js":"zx6S","./ss":"Ur1D","./ss.js":"Ur1D","./sv":"X709","./sv.js":"X709","./sw":"dNwA","./sw.js":"dNwA","./ta":"PeUW","./ta.js":"PeUW","./te":"XLvN","./te.js":"XLvN","./tet":"V2x9","./tet.js":"V2x9","./tg":"Oxv6","./tg.js":"Oxv6","./th":"EOgW","./th.js":"EOgW","./tl-ph":"Dzi0","./tl-ph.js":"Dzi0","./tlh":"z3Vd","./tlh.js":"z3Vd","./tr":"DoHr","./tr.js":"DoHr","./tzl":"z1FC","./tzl.js":"z1FC","./tzm":"wQk9","./tzm-latn":"tT3J","./tzm-latn.js":"tT3J","./tzm.js":"wQk9","./ug-cn":"YRex","./ug-cn.js":"YRex","./uk":"raLr","./uk.js":"raLr","./ur":"UpQW","./ur.js":"UpQW","./uz":"Loxo","./uz-latn":"AQ68","./uz-latn.js":"AQ68","./uz.js":"Loxo","./vi":"KSF8","./vi.js":"KSF8","./x-pseudo":"/X5v","./x-pseudo.js":"/X5v","./yo":"fzPg","./yo.js":"fzPg","./zh-cn":"XDpg","./zh-cn.js":"XDpg","./zh-hk":"SatO","./zh-hk.js":"SatO","./zh-tw":"kOpN","./zh-tw.js":"kOpN"};function r(t){var e=i(t);return n(e)}function i(t){var e=a[t];if(!(e+1)){var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}return e}r.keys=function(){return Object.keys(a)},r.resolve=i,t.exports=r,r.id="RnhZ"},S1nX:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("xlPZ"),r=n("yGWI"),i=n("K9Ia");function s(){return new i.a}function o(){return function(t){return Object(r.a)()(Object(a.a)(s)(t))}}},"S3/U":function(t,e,n){"use strict";t.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},S5bw:function(t,e,n){"use strict";n.d(e,"a",function(){return l});var a=n("mrSG"),r=n("K9Ia"),i=n("zo3G"),s=n("pugT"),o=n("mZXl"),u=n("8g8A"),c=n("uMaO"),l=function(t){function e(e,n,a){void 0===e&&(e=Number.POSITIVE_INFINITY),void 0===n&&(n=Number.POSITIVE_INFINITY);var r=t.call(this)||this;return r.scheduler=a,r._events=[],r._infiniteTimeWindow=!1,r._bufferSize=e<1?1:e,r._windowTime=n<1?1:n,n===Number.POSITIVE_INFINITY?(r._infiniteTimeWindow=!0,r.next=r.nextInfiniteTimeWindow):r.next=r.nextTimeWindow,r}return a.__extends(e,t),e.prototype.nextInfiniteTimeWindow=function(e){var n=this._events;n.push(e),n.length>this._bufferSize&&n.shift(),t.prototype.next.call(this,e)},e.prototype.nextTimeWindow=function(e){this._events.push(new d(this._getNow(),e)),this._trimBufferThenGetEvents(),t.prototype.next.call(this,e)},e.prototype._subscribe=function(t){var e,n=this._infiniteTimeWindow,a=n?this._events:this._trimBufferThenGetEvents(),r=this.scheduler,i=a.length;if(this.closed)throw new u.a;if(this.isStopped||this.hasError?e=s.a.EMPTY:(this.observers.push(t),e=new c.a(this,t)),r&&t.add(t=new o.a(t,r)),n)for(var l=0;l<i&&!t.closed;l++)t.next(a[l]);else for(l=0;l<i&&!t.closed;l++)t.next(a[l].value);return this.hasError?t.error(this.thrownError):this.isStopped&&t.complete(),e},e.prototype._getNow=function(){return(this.scheduler||i.a).now()},e.prototype._trimBufferThenGetEvents=function(){for(var t=this._getNow(),e=this._bufferSize,n=this._windowTime,a=this._events,r=a.length,i=0;i<r&&!(t-a[i].time<n);)i++;return r>e&&(i=Math.max(i,r-e)),i>0&&a.splice(0,i),a},e}(r.a),d=function(){return function(t,e){this.time=t,this.value=e}}()},S6ln:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a=t+" ";switch(n){case"ss":return a+(1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi");case"m":return e?"jedna minuta":"jedne minute";case"mm":return a+(1===t?"minuta":2===t||3===t||4===t?"minute":"minuta");case"h":return e?"jedan sat":"jednog sata";case"hh":return a+(1===t?"sat":2===t||3===t||4===t?"sata":"sati");case"dd":return a+(1===t?"dan":"dana");case"MM":return a+(1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci");case"yy":return a+(1===t?"godina":2===t||3===t||4===t?"godine":"godina")}}n("wd/R").defineLocale("hr",{months:{format:"sije\u010dnja_velja\u010de_o\u017eujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"sije\u010danj_velja\u010da_o\u017eujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._o\u017eu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_\u010detvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._\u010det._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_\u010de_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[ju\u010der u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[pro\u0161lu] dddd [u] LT";case 6:return"[pro\u0161le] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[pro\u0161li] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}()},S7Ns:function(t,e,n){"use strict";t.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},S7zO:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=(n("vCyI"),n("jKX/"),function(){function t(){this.dropDownActions=[]}return t.prototype.ngOnInit=function(){this.removeActionsWithNoPermissions(),this.updateDropDownActions()},t.prototype.toClassName=function(t){return t.replace(/ /g,"-").replace(/[^a-z-]/gi,"").toLowerCase()},t.prototype.removeActionsWithNoPermissions=function(){var t=this;if(this.permission){var e=Object.keys(this.permission).filter(function(e){return t.permission[e]});this.tableActions=this.tableActions.filter(function(t){return e.includes(t.permission)})}else this.tableActions=[]},t.prototype.updateDropDownActions=function(){var t=this;this.dropDownActions=this.tableActions.filter(function(e){return e.visible?e.visible(t.selection):e})},t.prototype.getCurrentButton=function(){var t=this;if(!this.onlyDropDown){var e=this.dropDownActions.find(function(e){return t.showableAction(e)});return!e&&this.dropDownActions.length>0&&(e=this.dropDownActions[0]),e}},t.prototype.showableAction=function(t){var e=t.canBePrimary,n=this.selection.hasSingleSelection,a="create"===t.permission?!n:n;return e&&e(this.selection)||!e&&a},t.prototype.useRouterLink=function(t){if(t.routerLink&&!this.disableSelectionAction(t))return a.isString(t.routerLink)?t.routerLink:t.routerLink()},t.prototype.disableSelectionAction=function(t){var e=t.permission,n=t.disable;if(n)return Boolean(n(this.selection));var a=this.selection.hasSingleSelection&&this.selection.first();return Boolean(["update","delete"].includes(e)&&(!a||a.cdExecuting))},t.prototype.showDropDownActions=function(){return this.updateDropDownActions(),this.dropDownActions.length>1},t.prototype.useClickAction=function(t){return!this.disableSelectionAction(t)&&t.click&&t.click()},t.prototype.useDisableDesc=function(t){return t.disableDesc&&t.disableDesc()},t}())},"SB+Q":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){return encodeURIComponent(t)},t}()},SFxW:function(t,e,n){!function(t){"use strict";var e={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-\xfcnc\xfc",4:"-\xfcnc\xfc",100:"-\xfcnc\xfc",6:"-nc\u0131",9:"-uncu",10:"-uncu",30:"-uncu",60:"-\u0131nc\u0131",90:"-\u0131nc\u0131"};t.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ert\u0259si_\xc7\u0259r\u015f\u0259nb\u0259 ax\u015fam\u0131_\xc7\u0259r\u015f\u0259nb\u0259_C\xfcm\u0259 ax\u015fam\u0131_C\xfcm\u0259_\u015e\u0259nb\u0259".split("_"),weekdaysShort:"Baz_BzE_\xc7Ax_\xc7\u0259r_CAx_C\xfcm_\u015e\u0259n".split("_"),weekdaysMin:"Bz_BE_\xc7A_\xc7\u0259_CA_C\xfc_\u015e\u0259".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bug\xfcn saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[g\u0259l\u0259n h\u0259ft\u0259] dddd [saat] LT",lastDay:"[d\xfcn\u0259n] LT",lastWeek:"[ke\xe7\u0259n h\u0259ft\u0259] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s \u0259vv\u0259l",s:"birne\xe7\u0259 saniy\u0259",ss:"%d saniy\u0259",m:"bir d\u0259qiq\u0259",mm:"%d d\u0259qiq\u0259",h:"bir saat",hh:"%d saat",d:"bir g\xfcn",dd:"%d g\xfcn",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gec\u0259|s\u0259h\u0259r|g\xfcnd\xfcz|ax\u015fam/,isPM:function(t){return/^(g\xfcnd\xfcz|ax\u015fam)$/.test(t)},meridiem:function(t,e,n){return t<4?"gec\u0259":t<12?"s\u0259h\u0259r":t<17?"g\xfcnd\xfcz":"ax\u015fam"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0131nc\u0131|inci|nci|\xfcnc\xfc|nc\u0131|uncu)/,ordinal:function(t){if(0===t)return t+"-\u0131nc\u0131";var n=t%10;return t+(e[n]||e[t%100-n]||e[t>=100?100:null])},week:{dow:1,doy:7}})}(n("wd/R"))},STEd:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n("FBEI");var a=n("CcnG"),r=n("xtUU"),i=n("HHO+"),s=n("Ip0R"),o=n("/TVo"),u=n("urB8"),c=n("ty8c"),l=n("FYBg"),d=n("JZ5S"),f=n("Tff5"),p=n("VUo1");e.TreeModule=function(){function t(){}return t.decorators=[{type:a.NgModule,args:[{imports:[s.CommonModule],declarations:[o.NodeDraggableDirective,r.TreeComponent,c.NodeEditableDirective,l.NodeMenuComponent,i.TreeInternalComponent,p.SafeHtmlPipe],exports:[r.TreeComponent],providers:[u.NodeDraggableService,d.NodeMenuService,f.TreeService]}]}],t}()},SZbH:function(t,e,n){"use strict";n.d(e,"a",function(){return x}),n.d(e,"b",function(){return d}),n.d(e,"c",function(){return _}),n.d(e,"d",function(){return u}),n.d(e,"e",function(){return S}),n.d(e,"f",function(){return I}),n.d(e,"g",function(){return c}),n.d(e,"h",function(){return w}),n.d(e,"i",function(){return T}),n.d(e,"j",function(){return v});var a=n("mrSG"),r=n("CcnG"),i=n("K9Ia"),s=n("ZYjt"),o=n("Ip0R"),u=function(){return function(){}}(),c=function(){function t(t,e,n,a,r,s){var o=this;this.toastId=t,this.config=e,this.message=n,this.title=a,this.toastType=r,this.toastRef=s,this._onTap=new i.a,this._onAction=new i.a,this.toastRef.afterClosed().subscribe(function(){o._onAction.complete(),o._onTap.complete()})}return t.prototype.triggerTap=function(){this._onTap.next(),this.config.tapToDismiss&&this._onTap.complete()},t.prototype.onTap=function(){return this._onTap.asObservable()},t.prototype.triggerAction=function(t){this._onAction.next(t)},t.prototype.onAction=function(){return this._onAction.asObservable()},t}(),l={maxOpened:0,autoDismiss:!1,newestOnTop:!0,preventDuplicates:!1,countDuplicates:!1,resetTimeoutOnDuplicate:!1,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},closeButton:!1,disableTimeOut:!1,timeOut:5e3,extendedTimeOut:1e3,enableHtml:!1,progressBar:!1,toastClass:"ngx-toastr",positionClass:"toast-top-right",titleClass:"toast-title",messageClass:"toast-message",easing:"ease-in",easeTime:300,tapToDismiss:!0,onActivateTick:!1,progressAnimation:"decreasing"},d=new r.InjectionToken("ToastConfig"),f=function(){function t(t,e){this.component=t,this.injector=e}return t.prototype.attach=function(t,e){return this._attachedHost=t,t.attach(this,e)},t.prototype.detach=function(){var t=this._attachedHost;if(t)return this._attachedHost=void 0,t.detach()},Object.defineProperty(t.prototype,"isAttached",{get:function(){return null!=this._attachedHost},enumerable:!0,configurable:!0}),t.prototype.setAttachedHost=function(t){this._attachedHost=t},t}(),p=function(t){function e(e,n,a){var r=t.call(this)||this;return r._hostDomElement=e,r._componentFactoryResolver=n,r._appRef=a,r}return Object(a.__extends)(e,t),e.prototype.attachComponentPortal=function(t,e){var n,a=this,r=this._componentFactoryResolver.resolveComponentFactory(t.component);return n=r.create(t.injector),this._appRef.attachView(n.hostView),this.setDisposeFn(function(){a._appRef.detachView(n.hostView),n.destroy()}),e?this._hostDomElement.insertBefore(this._getComponentRootNode(n),this._hostDomElement.firstChild):this._hostDomElement.appendChild(this._getComponentRootNode(n)),n},e.prototype._getComponentRootNode=function(t){return t.hostView.rootNodes[0]},e}(function(){function t(){}return t.prototype.attach=function(t,e){return this._attachedPortal=t,this.attachComponentPortal(t,e)},t.prototype.detach=function(){this._attachedPortal&&this._attachedPortal.setAttachedHost(),this._attachedPortal=void 0,this._disposeFn&&(this._disposeFn(),this._disposeFn=void 0)},t.prototype.setDisposeFn=function(t){this._disposeFn=t},t}()),h=function(){function t(t){this._document=t}return t.prototype.ngOnDestroy=function(){this._containerElement&&this._containerElement.parentNode&&this._containerElement.parentNode.removeChild(this._containerElement)},t.prototype.getContainerElement=function(){return this._containerElement||this._createContainer(),this._containerElement},t.prototype._createContainer=function(){var t=this._document.createElement("div");t.classList.add("overlay-container"),this._document.body.appendChild(t),this._containerElement=t},t.ngInjectableDef=Object(r.defineInjectable)({factory:function(){return new t(Object(r.inject)(o.DOCUMENT))},token:t,providedIn:"root"}),t}(),g=function(){function t(t){this._portalHost=t}return t.prototype.attach=function(t,e){return void 0===e&&(e=!0),this._portalHost.attach(t,e)},t.prototype.detach=function(){return this._portalHost.detach()},t}(),b=function(){function t(t,e,n,a){this._overlayContainer=t,this._componentFactoryResolver=e,this._appRef=n,this._document=a,this._paneElements=new Map}return t.prototype.create=function(t,e){return this._createOverlayRef(this.getPaneElement(t,e))},t.prototype.getPaneElement=function(t,e){return void 0===t&&(t=""),this._paneElements.get(e)||this._paneElements.set(e,{}),this._paneElements.get(e)[t]||(this._paneElements.get(e)[t]=this._createPaneElement(t,e)),this._paneElements.get(e)[t]},t.prototype._createPaneElement=function(t,e){var n=this._document.createElement("div");return n.id="toast-container",n.classList.add(t),n.classList.add("toast-container"),e?e.getContainerElement().appendChild(n):this._overlayContainer.getContainerElement().appendChild(n),n},t.prototype._createPortalHost=function(t){return new p(t,this._componentFactoryResolver,this._appRef)},t.prototype._createOverlayRef=function(t){return new g(this._createPortalHost(t))},t.ngInjectableDef=Object(r.defineInjectable)({factory:function(){return new t(Object(r.inject)(h),Object(r.inject)(r.ComponentFactoryResolver),Object(r.inject)(r.ApplicationRef),Object(r.inject)(o.DOCUMENT))},token:t,providedIn:"root"}),t}(),m=function(){function t(t){this._overlayRef=t,this.duplicatesCount=0,this._afterClosed=new i.a,this._activate=new i.a,this._manualClose=new i.a,this._resetTimeout=new i.a,this._countDuplicate=new i.a}return t.prototype.manualClose=function(){this._manualClose.next(),this._manualClose.complete()},t.prototype.manualClosed=function(){return this._manualClose.asObservable()},t.prototype.timeoutReset=function(){return this._resetTimeout.asObservable()},t.prototype.countDuplicate=function(){return this._countDuplicate.asObservable()},t.prototype.close=function(){this._overlayRef.detach(),this._afterClosed.next(),this._manualClose.next(),this._afterClosed.complete(),this._manualClose.complete(),this._activate.complete(),this._resetTimeout.complete(),this._countDuplicate.complete()},t.prototype.afterClosed=function(){return this._afterClosed.asObservable()},t.prototype.isInactive=function(){return this._activate.isStopped},t.prototype.activate=function(){this._activate.next(),this._activate.complete()},t.prototype.afterActivate=function(){return this._activate.asObservable()},t.prototype.onDuplicate=function(t,e){t&&this._resetTimeout.next(),e&&this._countDuplicate.next(++this.duplicatesCount)},t}(),y=function(){function t(t,e){this._toastPackage=t,this._parentInjector=e}return t.prototype.get=function(t,e,n){return t===c?this._toastPackage:this._parentInjector.get(t,e,n)},t}(),v=function(){function t(t,e,n,r,i){this.overlay=e,this._injector=n,this.sanitizer=r,this.ngZone=i,this.currentlyActive=0,this.toasts=[],this.index=0,this.toastrConfig=Object(a.__assign)({},t.default,t.config),t.config.iconClasses&&(this.toastrConfig.iconClasses=Object(a.__assign)({},t.default.iconClasses,t.config.iconClasses))}return t.prototype.show=function(t,e,n,a){return void 0===n&&(n={}),void 0===a&&(a=""),this._preBuildNotification(a,t,e,this.applyConfig(n))},t.prototype.success=function(t,e,n){return void 0===n&&(n={}),this._preBuildNotification(this.toastrConfig.iconClasses.success||"",t,e,this.applyConfig(n))},t.prototype.error=function(t,e,n){return void 0===n&&(n={}),this._preBuildNotification(this.toastrConfig.iconClasses.error||"",t,e,this.applyConfig(n))},t.prototype.info=function(t,e,n){return void 0===n&&(n={}),this._preBuildNotification(this.toastrConfig.iconClasses.info||"",t,e,this.applyConfig(n))},t.prototype.warning=function(t,e,n){return void 0===n&&(n={}),this._preBuildNotification(this.toastrConfig.iconClasses.warning||"",t,e,this.applyConfig(n))},t.prototype.clear=function(t){var e,n;try{for(var r=Object(a.__values)(this.toasts),i=r.next();!i.done;i=r.next()){var s=i.value;if(void 0!==t){if(s.toastId===t)return void s.toastRef.manualClose()}else s.toastRef.manualClose()}}catch(o){e={error:o}}finally{try{i&&!i.done&&(n=r.return)&&n.call(r)}finally{if(e)throw e.error}}},t.prototype.remove=function(t){var e=this._findToast(t);if(!e)return!1;if(e.activeToast.toastRef.close(),this.toasts.splice(e.index,1),this.currentlyActive=this.currentlyActive-1,!this.toastrConfig.maxOpened||!this.toasts.length)return!1;if(this.currentlyActive<this.toastrConfig.maxOpened&&this.toasts[this.currentlyActive]){var n=this.toasts[this.currentlyActive].toastRef;n.isInactive()||(this.currentlyActive=this.currentlyActive+1,n.activate())}return!0},t.prototype.findDuplicate=function(t,e,n){for(var a=0;a<this.toasts.length;a++){var r=this.toasts[a];if(r.message===t)return r.toastRef.onDuplicate(e,n),r}return null},t.prototype.applyConfig=function(t){return void 0===t&&(t={}),Object(a.__assign)({},this.toastrConfig,t)},t.prototype._findToast=function(t){for(var e=0;e<this.toasts.length;e++)if(this.toasts[e].toastId===t)return{index:e,activeToast:this.toasts[e]};return null},t.prototype._preBuildNotification=function(t,e,n,a){var r=this;return a.onActivateTick?this.ngZone.run(function(){return r._buildNotification(t,e,n,a)}):this._buildNotification(t,e,n,a)},t.prototype._buildNotification=function(t,e,n,a){var i=this;if(!a.toastComponent)throw new Error("toastComponent required");var s=this.findDuplicate(e,this.toastrConfig.resetTimeoutOnDuplicate,this.toastrConfig.countDuplicates);if(e&&this.toastrConfig.preventDuplicates&&null!==s)return s;this.previousToastMessage=e;var o=!1;this.toastrConfig.maxOpened&&this.currentlyActive>=this.toastrConfig.maxOpened&&(o=!0,this.toastrConfig.autoDismiss&&this.clear(this.toasts[0].toastId));var u=this.overlay.create(a.positionClass,this.overlayContainer);this.index=this.index+1;var l=e;e&&a.enableHtml&&(l=this.sanitizer.sanitize(r.SecurityContext.HTML,e));var d=new m(u),p=new c(this.index,a,l,n,t,d),h=new y(p,this._injector),g=new f(a.toastComponent,h),b=u.attach(g,this.toastrConfig.newestOnTop);d.componentInstance=b._component;var v={toastId:this.index,message:e||"",toastRef:d,onShown:d.afterActivate(),onHidden:d.afterClosed(),onTap:p.onTap(),onAction:p.onAction(),portal:b};return o||setTimeout(function(){v.toastRef.activate(),i.currentlyActive=i.currentlyActive+1}),this.toasts.push(v),v},t.ngInjectableDef=Object(r.defineInjectable)({factory:function(){return new t(Object(r.inject)(d),Object(r.inject)(b),Object(r.inject)(r.INJECTOR),Object(r.inject)(s.DomSanitizer),Object(r.inject)(r.NgZone))},token:t,providedIn:"root"}),t}(),_=function(){function t(t,e,n){var a=this;this.toastrService=t,this.toastPackage=e,this.ngZone=n,this.width=-1,this.toastClasses="",this.state={value:"inactive",params:{easeTime:this.toastPackage.config.easeTime,easing:"ease-in"}},this.message=e.message,this.title=e.title,this.options=e.config,this.originalTimeout=e.config.timeOut,this.toastClasses=e.toastType+" "+e.config.toastClass,this.sub=e.toastRef.afterActivate().subscribe(function(){a.activateToast()}),this.sub1=e.toastRef.manualClosed().subscribe(function(){a.remove()}),this.sub2=e.toastRef.timeoutReset().subscribe(function(){a.resetTimeout()}),this.sub3=e.toastRef.countDuplicate().subscribe(function(t){a.duplicatesCount=t})}return Object.defineProperty(t.prototype,"displayStyle",{get:function(){return"inactive"===this.state.value?"none":"inherit"},enumerable:!0,configurable:!0}),t.prototype.ngOnDestroy=function(){this.sub.unsubscribe(),this.sub1.unsubscribe(),this.sub2.unsubscribe(),this.sub3.unsubscribe(),clearInterval(this.intervalId),clearTimeout(this.timeout)},t.prototype.activateToast=function(){var t=this;this.state=Object(a.__assign)({},this.state,{value:"active"}),!this.options.disableTimeOut&&this.options.timeOut&&(this.outsideTimeout(function(){return t.remove()},this.options.timeOut),this.hideTime=(new Date).getTime()+this.options.timeOut,this.options.progressBar&&this.outsideInterval(function(){return t.updateProgress()},10))},t.prototype.updateProgress=function(){if(0!==this.width&&100!==this.width&&this.options.timeOut){var t=(new Date).getTime();this.width=(this.hideTime-t)/this.options.timeOut*100,"increasing"===this.options.progressAnimation&&(this.width=100-this.width),this.width<=0&&(this.width=0),this.width>=100&&(this.width=100)}},t.prototype.resetTimeout=function(){var t=this;clearTimeout(this.timeout),clearInterval(this.intervalId),this.state=Object(a.__assign)({},this.state,{value:"active"}),this.outsideTimeout(function(){return t.remove()},this.originalTimeout),this.options.timeOut=this.originalTimeout,this.hideTime=(new Date).getTime()+(this.options.timeOut||0),this.width=-1,this.options.progressBar&&this.outsideInterval(function(){return t.updateProgress()},10)},t.prototype.remove=function(){var t=this;"removed"!==this.state.value&&(clearTimeout(this.timeout),this.state=Object(a.__assign)({},this.state,{value:"removed"}),this.outsideTimeout(function(){return t.toastrService.remove(t.toastPackage.toastId)},+this.toastPackage.config.easeTime))},t.prototype.tapToast=function(){"removed"!==this.state.value&&(this.toastPackage.triggerTap(),this.options.tapToDismiss&&this.remove())},t.prototype.stickAround=function(){"removed"!==this.state.value&&(clearTimeout(this.timeout),this.options.timeOut=0,this.hideTime=0,clearInterval(this.intervalId),this.width=0)},t.prototype.delayedHideToast=function(){var t=this;this.options.disableTimeOut||0===this.options.extendedTimeOut||"removed"===this.state.value||(this.outsideTimeout(function(){return t.remove()},this.options.extendedTimeOut),this.options.timeOut=this.options.extendedTimeOut,this.hideTime=(new Date).getTime()+(this.options.timeOut||0),this.width=-1,this.options.progressBar&&this.outsideInterval(function(){return t.updateProgress()},10))},t.prototype.outsideTimeout=function(t,e){var n=this;this.ngZone?this.ngZone.runOutsideAngular(function(){return n.timeout=setTimeout(function(){return n.runInsideAngular(t)},e)}):this.timeout=setTimeout(function(){return t()},e)},t.prototype.outsideInterval=function(t,e){var n=this;this.ngZone?this.ngZone.runOutsideAngular(function(){return n.intervalId=setInterval(function(){return n.runInsideAngular(t)},e)}):this.intervalId=setInterval(function(){return t()},e)},t.prototype.runInsideAngular=function(t){this.ngZone?this.ngZone.run(function(){return t()}):t()},t}(),x=Object(a.__assign)({},l,{toastComponent:_}),T=function(){function t(){}var e;return e=t,t.forRoot=function(t){return void 0===t&&(t={}),{ngModule:e,providers:[{provide:d,useValue:{default:x,config:t}}]}},t}(),w=function(){function t(){}return t.forRoot=function(t){return void 0===t&&(t={}),{ngModule:T,providers:[{provide:d,useValue:{default:l,config:t}}]}},t}(),S=function(){function t(t,e,n){var a=this;this.toastrService=t,this.toastPackage=e,this.appRef=n,this.width=-1,this.toastClasses="",this.state="inactive",this.message=e.message,this.title=e.title,this.options=e.config,this.originalTimeout=e.config.timeOut,this.toastClasses=e.toastType+" "+e.config.toastClass,this.sub=e.toastRef.afterActivate().subscribe(function(){a.activateToast()}),this.sub1=e.toastRef.manualClosed().subscribe(function(){a.remove()}),this.sub2=e.toastRef.timeoutReset().subscribe(function(){a.resetTimeout()}),this.sub3=e.toastRef.countDuplicate().subscribe(function(t){a.duplicatesCount=t})}return Object.defineProperty(t.prototype,"displayStyle",{get:function(){return"inactive"===this.state?"none":"inherit"},enumerable:!0,configurable:!0}),t.prototype.ngOnDestroy=function(){this.sub.unsubscribe(),this.sub1.unsubscribe(),this.sub2.unsubscribe(),this.sub3.unsubscribe(),clearInterval(this.intervalId),clearTimeout(this.timeout)},t.prototype.activateToast=function(){var t=this;this.state="active",!this.options.disableTimeOut&&this.options.timeOut&&(this.timeout=setTimeout(function(){t.remove()},this.options.timeOut),this.hideTime=(new Date).getTime()+this.options.timeOut,this.options.progressBar&&(this.intervalId=setInterval(function(){return t.updateProgress()},10))),this.options.onActivateTick&&this.appRef.tick()},t.prototype.updateProgress=function(){if(0!==this.width&&100!==this.width&&this.options.timeOut){var t=(new Date).getTime();this.width=(this.hideTime-t)/this.options.timeOut*100,"increasing"===this.options.progressAnimation&&(this.width=100-this.width),this.width<=0&&(this.width=0),this.width>=100&&(this.width=100)}},t.prototype.resetTimeout=function(){var t=this;clearTimeout(this.timeout),clearInterval(this.intervalId),this.state="active",this.options.timeOut=this.originalTimeout,this.timeout=setTimeout(function(){return t.remove()},this.originalTimeout),this.hideTime=(new Date).getTime()+(this.originalTimeout||0),this.width=-1,this.options.progressBar&&(this.intervalId=setInterval(function(){return t.updateProgress()},10))},t.prototype.remove=function(){var t=this;"removed"!==this.state&&(clearTimeout(this.timeout),this.state="removed",this.timeout=setTimeout(function(){return t.toastrService.remove(t.toastPackage.toastId)}))},t.prototype.tapToast=function(){"removed"!==this.state&&(this.toastPackage.triggerTap(),this.options.tapToDismiss&&this.remove())},t.prototype.stickAround=function(){"removed"!==this.state&&(clearTimeout(this.timeout),this.options.timeOut=0,this.hideTime=0,clearInterval(this.intervalId),this.width=0)},t.prototype.delayedHideToast=function(){var t=this;this.options.disableTimeOut||0===this.options.extendedTimeOut||"removed"===this.state||(this.timeout=setTimeout(function(){return t.remove()},this.options.extendedTimeOut),this.options.timeOut=this.options.extendedTimeOut,this.hideTime=(new Date).getTime()+(this.options.timeOut||0),this.width=-1,this.options.progressBar&&(this.intervalId=setInterval(function(){return t.updateProgress()},10)))},t}(),O=Object(a.__assign)({},l,{toastComponent:S}),I=function(){function t(){}var e;return e=t,t.forRoot=function(t){return void 0===t&&(t={}),{ngModule:e,providers:[{provide:d,useValue:{default:O,config:t}}]}},t}()},SatO:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("zh-hk",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u9031\u65e5_\u9031\u4e00_\u9031\u4e8c_\u9031\u4e09_\u9031\u56db_\u9031\u4e94_\u9031\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5 HH:mm",LLLL:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm",l:"YYYY/M/D",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm"},meridiemParse:/\u51cc\u6668|\u65e9\u4e0a|\u4e0a\u5348|\u4e2d\u5348|\u4e0b\u5348|\u665a\u4e0a/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u51cc\u6668"===e||"\u65e9\u4e0a"===e||"\u4e0a\u5348"===e?t:"\u4e2d\u5348"===e?t>=11?t:t+12:"\u4e0b\u5348"===e||"\u665a\u4e0a"===e?t+12:void 0},meridiem:function(t,e,n){var a=100*t+e;return a<600?"\u51cc\u6668":a<900?"\u65e9\u4e0a":a<1130?"\u4e0a\u5348":a<1230?"\u4e2d\u5348":a<1800?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(\u65e5|\u6708|\u9031)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\u65e5";case"M":return t+"\u6708";case"w":case"W":return t+"\u9031";default:return t}},relativeTime:{future:"%s\u5167",past:"%s\u524d",s:"\u5e7e\u79d2",ss:"%d \u79d2",m:"1 \u5206\u9418",mm:"%d \u5206\u9418",h:"1 \u5c0f\u6642",hh:"%d \u5c0f\u6642",d:"1 \u5929",dd:"%d \u5929",M:"1 \u500b\u6708",MM:"%d \u500b\u6708",y:"1 \u5e74",yy:"%d \u5e74"}})}()},SfHT:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG");e.ScrollerComponent=function(){function t(t,e,n){this.ngZone=t,this.renderer=n,this.scrollbarV=!1,this.scrollbarH=!1,this.scroll=new i.EventEmitter,this.scrollYPos=0,this.scrollXPos=0,this.prevScrollYPos=0,this.prevScrollXPos=0,this.element=e.nativeElement}return t.prototype.ngOnInit=function(){if(this.scrollbarV||this.scrollbarH){var t=this.renderer;this.parentElement=t.parentNode(t.parentNode(this.element)),this.parentElement.addEventListener("scroll",this.onScrolled.bind(this))}},t.prototype.ngOnDestroy=function(){(this.scrollbarV||this.scrollbarH)&&this.parentElement.removeEventListener("scroll",this.onScrolled.bind(this))},t.prototype.setOffset=function(t){this.parentElement&&(this.parentElement.scrollTop=t)},t.prototype.onScrolled=function(t){var e=this,n=t.currentTarget;requestAnimationFrame(function(){e.scrollYPos=n.scrollTop,e.scrollXPos=n.scrollLeft,e.updateOffset()})},t.prototype.updateOffset=function(){var t;this.scrollYPos<this.prevScrollYPos?t="down":this.scrollYPos>this.prevScrollYPos&&(t="up"),this.scroll.emit({direction:t,scrollYPos:this.scrollYPos,scrollXPos:this.scrollXPos}),this.prevScrollYPos=this.scrollYPos,this.prevScrollXPos=this.scrollXPos},a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarV",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([i.HostBinding("style.height.px"),i.Input(),r("design:type",Number)],t.prototype,"scrollHeight",void 0),a([i.HostBinding("style.width.px"),i.Input(),r("design:type",Number)],t.prototype,"scrollWidth",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"scroll",void 0),a([i.Component({selector:"datatable-scroller",template:"\n <ng-content></ng-content>\n ",host:{class:"datatable-scroll"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},Sfow:function(t,e,n){"use strict";var a=n("TC34");e=t.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,a,r,i){if(i){var s=Math.min(i,r/2-1e-7,a/2-1e-7);t.moveTo(e+s,n),t.lineTo(e+a-s,n),t.arcTo(e+a,n,e+a,n+s,s),t.lineTo(e+a,n+r-s),t.arcTo(e+a,n+r,e+a-s,n+r,s),t.lineTo(e+s,n+r),t.arcTo(e,n+r,e,n+r-s,s),t.lineTo(e,n+s),t.arcTo(e,n,e+s,n,s),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,a,r)},drawPoint:function(t,e,n,a,r,i){var s,o,u,c,l,d;if(i=i||0,!e||"object"!=typeof e||"[object HTMLImageElement]"!==(s=e.toString())&&"[object HTMLCanvasElement]"!==s){if(!(isNaN(n)||n<=0)){switch(t.save(),t.translate(a,r),t.rotate(i*Math.PI/180),t.beginPath(),e){default:t.arc(0,0,n,0,2*Math.PI),t.closePath();break;case"triangle":l=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(-o/2,l/3),t.lineTo(o/2,l/3),t.lineTo(0,-2*l/3),t.closePath();break;case"rect":d=1/Math.SQRT2*n,t.rect(-d,-d,2*d,2*d);break;case"rectRounded":var f=n/Math.SQRT2,p=Math.SQRT2*n;this.roundedRect(t,-f,-f,p,p,.425*n);break;case"rectRot":d=1/Math.SQRT2*n,t.moveTo(-d,0),t.lineTo(0,d),t.lineTo(d,0),t.lineTo(0,-d),t.closePath();break;case"cross":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0);break;case"crossRot":u=Math.cos(Math.PI/4)*n,c=Math.sin(Math.PI/4)*n,t.moveTo(-u,-c),t.lineTo(u,c),t.moveTo(-u,c),t.lineTo(u,-c);break;case"star":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0),u=Math.cos(Math.PI/4)*n,c=Math.sin(Math.PI/4)*n,t.moveTo(-u,-c),t.lineTo(u,c),t.moveTo(-u,c),t.lineTo(u,-c);break;case"line":t.moveTo(-n,0),t.lineTo(n,0);break;case"dash":t.moveTo(0,0),t.lineTo(n,0)}t.fill(),t.stroke(),t.restore()}}else t.drawImage(e,a-e.width/2,r-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,a){if(n.steppedLine)return"after"===n.steppedLine&&!a||"after"!==n.steppedLine&&a?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(a?e.controlPointPreviousX:e.controlPointNextX,a?e.controlPointPreviousY:e.controlPointNextY,a?n.controlPointNextX:n.controlPointPreviousX,a?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}},a.clear=e.clear,a.drawRoundedRectangle=function(t){t.beginPath(),e.roundedRect.apply(e,arguments)}},SgmB:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("F/XL"),r=n("psW0"),i=n("CcnG"),s=n("t/Na"),o=n("pL04"),u=function(){function t(t){this.http=t}return t.prototype.list=function(){return this.http.get("api/role")},t.prototype.delete=function(t){return this.http.delete("api/role/"+t)},t.prototype.get=function(t){return this.http.get("api/role/"+t)},t.prototype.create=function(t){return this.http.post("api/role",t)},t.prototype.update=function(t){return this.http.put("api/role/"+t.name,t)},t.prototype.exists=function(t){return this.list().pipe(Object(r.a)(function(e){var n=e.some(function(e){return e.name===t});return Object(a.a)(n)}))},t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(s.c))},token:t,providedIn:o.a}),t}()},SjWX:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=function(){return function(t,e,n){this.name=t,this.version=e,this.os=n}}();e.BrowserInfo=a;var r=function(){return function(t){this.version=t,this.name="node",this.os=process.platform}}();e.NodeInfo=r;var i=function(){return function(){this.bot=!0,this.name="bot",this.version=null,this.os=null}}();e.BotInfo=i;var s=3,o=[["aol",/AOLShield\/([0-9\._]+)/],["edge",/Edge\/([0-9\._]+)/],["yandexbrowser",/YaBrowser\/([0-9\._]+)/],["vivaldi",/Vivaldi\/([0-9\.]+)/],["kakaotalk",/KAKAOTALK\s([0-9\.]+)/],["samsung",/SamsungBrowser\/([0-9\.]+)/],["silk",/\bSilk\/([0-9._-]+)\b/],["chrome",/(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/],["phantomjs",/PhantomJS\/([0-9\.]+)(:?\s|$)/],["crios",/CriOS\/([0-9\.]+)(:?\s|$)/],["firefox",/Firefox\/([0-9\.]+)(?:\s|$)/],["fxios",/FxiOS\/([0-9\.]+)/],["opera-mini",/Opera Mini.*Version\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)(?:\s|$)/],["opera",/OPR\/([0-9\.]+)(:?\s|$)$/],["ie",/Trident\/7\.0.*rv\:([0-9\.]+).*\).*Gecko$/],["ie",/MSIE\s([0-9\.]+);.*Trident\/[4-7].0/],["ie",/MSIE\s(7\.0)/],["bb10",/BB10;\sTouch.*Version\/([0-9\.]+)/],["android",/Android\s([0-9\.]+)/],["ios",/Version\/([0-9\._]+).*Mobile.*Safari.*/],["safari",/Version\/([0-9\._]+).*Safari/],["facebook",/FBAV\/([0-9\.]+)/],["instagram",/Instagram\s([0-9\.]+)/],["ios-webview",/AppleWebKit\/([0-9\.]+).*Mobile/],["searchbot",/alexa|bot|crawl(er|ing)|facebookexternalhit|feedburner|google web preview|nagios|postrank|pingdom|slurp|spider|yahoo!|yandex/]],u=[["iOS",/iP(hone|od|ad)/],["Android OS",/Android/],["BlackBerry OS",/BlackBerry|BB10/],["Windows Mobile",/IEMobile/],["Amazon OS",/Kindle/],["Windows 3.11",/Win16/],["Windows 95",/(Windows 95)|(Win95)|(Windows_95)/],["Windows 98",/(Windows 98)|(Win98)/],["Windows 2000",/(Windows NT 5.0)|(Windows 2000)/],["Windows XP",/(Windows NT 5.1)|(Windows XP)/],["Windows Server 2003",/(Windows NT 5.2)/],["Windows Vista",/(Windows NT 6.0)/],["Windows 7",/(Windows NT 6.1)/],["Windows 8",/(Windows NT 6.2)/],["Windows 8.1",/(Windows NT 6.3)/],["Windows 10",/(Windows NT 10.0)/],["Windows ME",/Windows ME/],["Open BSD",/OpenBSD/],["Sun OS",/SunOS/],["Chrome OS",/CrOS/],["Linux",/(Linux)|(X11)/],["Mac OS",/(Mac_PowerPC)|(Macintosh)/],["QNX",/QNX/],["BeOS",/BeOS/],["OS/2",/OS\/2/],["Search Bot",/(nuhk)|(Googlebot)|(Yammybot)|(Openbot)|(Slurp)|(MSNBot)|(Ask Jeeves\/Teoma)|(ia_archiver)/]];function c(t){var e=""!==t&&o.reduce(function(e,n){var a=n[0];if(e)return e;var r=n[1].exec(t);return!!r&&[a,r]},!1);if(!e)return null;var n=e[0],r=e[1];if("searchbot"===n)return new i;var u=r[1]&&r[1].split(/[._]/).slice(0,3);return u?u.length<s&&(u=u.concat(function(t){for(var e=[],n=0;n<t;n++)e.push("0");return e}(s-u.length))):u=[],new a(n,u.join("."),l(t))}function l(t){for(var e=0,n=u.length;e<n;e++){var a=u[e],r=a[0];if(a[1].test(t))return r}return null}function d(){return"undefined"!=typeof process&&process.version?new r(process.version.slice(1)):null}e.detect=function(){return"undefined"!=typeof navigator?c(navigator.userAgent):d()},e.parseUserAgent=c,e.detectOS=l,e.getNodeVersion=d},T016:function(t,e,n){"use strict";t.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},T1DM:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("h9Dq"),r=new(n("CS9Q").a)(a.a)},TC34:function(t,e,n){"use strict";var a,r={noop:function(){},uid:(a=0,function(){return a++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return r.valueOrDefault(r.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var i,s,o;if(r.isArray(t))if(s=t.length,a)for(i=s-1;i>=0;i--)e.call(n,t[i],i);else for(i=0;i<s;i++)e.call(n,t[i],i);else if(r.isObject(t))for(s=(o=Object.keys(t)).length,i=0;i<s;i++)e.call(n,t[o[i]],o[i])},arrayEquals:function(t,e){var n,a,i,s;if(!t||!e||t.length!==e.length)return!1;for(n=0,a=t.length;n<a;++n)if(s=e[n],(i=t[n])instanceof Array&&s instanceof Array){if(!r.arrayEquals(i,s))return!1}else if(i!==s)return!1;return!0},clone:function(t){if(r.isArray(t))return t.map(r.clone);if(r.isObject(t)){for(var e={},n=Object.keys(t),a=n.length,i=0;i<a;++i)e[n[i]]=r.clone(t[n[i]]);return e}return t},_merger:function(t,e,n,a){var i=e[t],s=n[t];r.isObject(i)&&r.isObject(s)?r.merge(i,s,a):e[t]=r.clone(s)},_mergerIf:function(t,e,n){var a=e[t],i=n[t];r.isObject(a)&&r.isObject(i)?r.mergeIf(a,i):e.hasOwnProperty(t)||(e[t]=r.clone(i))},merge:function(t,e,n){var a,i,s,o,u,c=r.isArray(e)?e:[e],l=c.length;if(!r.isObject(t))return t;for(a=(n=n||{}).merger||r._merger,i=0;i<l;++i)if(r.isObject(e=c[i]))for(u=0,o=(s=Object.keys(e)).length;u<o;++u)a(s[u],t,e,n);return t},mergeIf:function(t,e){return r.merge(t,e,{merger:r._mergerIf})},extend:function(t){for(var e=function(e,n){t[n]=e},n=1,a=arguments.length;n<a;++n)r.each(arguments[n],e);return t},inherits:function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},a=function(){this.constructor=n};return a.prototype=e.prototype,n.prototype=new a,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n}};t.exports=r,r.callCallback=r.callback,r.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},r.getValueOrDefault=r.valueOrDefault,r.getValueAtIndexOrDefault=r.valueAtIndexOrDefault},TCh0:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=e.Keys=function(t){return t[t.Escape=27]="Escape",t}(e.Keys||{}),r=e.MouseButtons=function(t){return t[t.Left=0]="Left",t[t.Right=2]="Right",t}(e.MouseButtons||{});e.isLeftButtonClicked=function(t){return t.button===r.Left},e.isRightButtonClicked=function(t){return t.button===r.Right},e.isEscapePressed=function(t){return t.keyCode===a.Escape}},TJUb:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=function(){function t(){}return t.prototype.transform=function(t,e){return a.isPlainObject(e)?a.get(e,t,t):t},t}()},TYzs:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){var e=parseInt(t,10);return isNaN(e)?t:t+(1===Math.floor(e/10)?"th":e%10==1?"st":e%10==2?"nd":e%10==3?"rd":"th")},t}()},TZo1:function(t,e,n){"use strict";var a=n("CcnG"),r=n("MdoF"),i=n("lTVp");n("9Kw/"),n("Jm/i"),n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o});var s=a["\u0275crt"]({encapsulation:0,styles:[[".info-panel-alert-icon[_ngcontent-%COMP%]{vertical-align:top;padding-right:15px}.info-panel-alert-title[_ngcontent-%COMP%]{font-weight:700}"]],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,11,"alert",[["type","info"]],null,null,null,r.c,r.b)),a["\u0275did"](1,114688,null,0,i.a,[i.b,a.ChangeDetectorRef],{type:[0,"type"]},null),(t()(),a["\u0275eld"](2,0,null,0,9,"table",[],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275eld"](4,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"td",[["class","info-panel-alert-icon"],["rowspan","2"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-3x fa-info-circle alert-info"]],null,null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,1,"td",[["class","info-panel-alert-title"]],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,[" "," "])),(t()(),a["\u0275eld"](9,0,null,null,2,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](10,0,null,null,1,"td",[["class","info-panel-alert-text"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],function(t,e){t(e,1,0,"info")},function(t,e){t(e,8,0,e.component.title)})}},Tff5:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("VE89"),r=n("buEt"),i=n("CcnG"),s=(n("urB8"),n("kQXf"));e.TreeService=function(){function t(t){this.nodeDraggableService=t,this.nodeMoved$=new r.Subject,this.nodeRemoved$=new r.Subject,this.nodeRenamed$=new r.Subject,this.nodeCreated$=new r.Subject,this.nodeSelected$=new r.Subject,this.nodeUnselected$=new r.Subject,this.nodeExpanded$=new r.Subject,this.nodeCollapsed$=new r.Subject,this.menuItemSelected$=new r.Subject,this.loadNextLevel$=new r.Subject,this.nodeChecked$=new r.Subject,this.nodeUnchecked$=new r.Subject,this.nodeIndetermined$=new r.Subject,this.controllers=new Map,this.nodeRemoved$.subscribe(function(t){return t.node.removeItselfFromParent()})}return t.prototype.unselectStream=function(t){return this.nodeSelected$.filter(function(e){return t!==e.node})},t.prototype.fireNodeRemoved=function(t){this.nodeRemoved$.next(new a.NodeRemovedEvent(t,t.positionInParent))},t.prototype.fireNodeCreated=function(t){this.nodeCreated$.next(new a.NodeCreatedEvent(t))},t.prototype.fireNodeSelected=function(t){this.nodeSelected$.next(new a.NodeSelectedEvent(t))},t.prototype.fireNodeUnselected=function(t){this.nodeUnselected$.next(new a.NodeUnselectedEvent(t))},t.prototype.fireNodeRenamed=function(t,e){this.nodeRenamed$.next(new a.NodeRenamedEvent(e,t,e.value))},t.prototype.fireNodeMoved=function(t,e){this.nodeMoved$.next(new a.NodeMovedEvent(t,e))},t.prototype.fireMenuItemSelected=function(t,e){this.menuItemSelected$.next(new a.MenuItemSelectedEvent(t,e))},t.prototype.fireNodeSwitchFoldingType=function(t){t.isNodeExpanded()?(this.fireNodeExpanded(t),this.shouldFireLoadNextLevel(t)&&this.fireLoadNextLevel(t)):t.isNodeCollapsed()&&this.fireNodeCollapsed(t)},t.prototype.fireNodeExpanded=function(t){this.nodeExpanded$.next(new a.NodeExpandedEvent(t))},t.prototype.fireNodeCollapsed=function(t){this.nodeCollapsed$.next(new a.NodeCollapsedEvent(t))},t.prototype.fireLoadNextLevel=function(t){this.loadNextLevel$.next(new a.LoadNextLevelEvent(t))},t.prototype.fireNodeChecked=function(t){this.nodeChecked$.next(new a.NodeCheckedEvent(t))},t.prototype.fireNodeUnchecked=function(t){this.nodeUnchecked$.next(new a.NodeUncheckedEvent(t))},t.prototype.draggedStream=function(t,e){return this.nodeDraggableService.draggableNodeEvents$.filter(function(t){return t.target===e}).filter(function(e){return!e.captured.tree.hasChild(t)})},t.prototype.setController=function(t,e){this.controllers.set(t,e)},t.prototype.deleteController=function(t){this.controllers.has(t)&&this.controllers.delete(t)},t.prototype.getController=function(t){return this.controllers.has(t)?this.controllers.get(t):null},t.prototype.hasController=function(t){return this.controllers.has(t)},t.prototype.shouldFireLoadNextLevel=function(t){var e=t.node.emitLoadNextLevel&&!t.node.loadChildren&&!t.childrenAreBeingLoaded()&&s.isEmpty(t.children);return e&&t.loadingChildrenRequested(),e},t.prototype.fireNodeIndetermined=function(t){this.nodeIndetermined$.next(new a.NodeIndeterminedEvent(t))},t.decorators=[{type:i.Injectable}],t}()},Txjg:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("Zn8D");function r(){return Object(a.a)(1)}},UDhR:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(t,e){return 12===t&&(t=0),"pagi"===e?t:"siang"===e?t>=11?t:t+12:"sore"===e||"malam"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"pagi":t<15?"siang":t<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}()},UReH:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DatatableRowDetailTemplateDirective=function(){return a([r.Directive({selector:"[ngx-datatable-row-detail-template]"})],function(t){this.template=t})}()},USCx:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ga",{months:["Ean\xe1ir","Feabhra","M\xe1rta","Aibre\xe1n","Bealtaine","M\xe9itheamh","I\xfail","L\xfanasa","Me\xe1n F\xf3mhair","Deaireadh F\xf3mhair","Samhain","Nollaig"],monthsShort:["Ean\xe1","Feab","M\xe1rt","Aibr","Beal","M\xe9it","I\xfail","L\xfana","Me\xe1n","Deai","Samh","Noll"],monthsParseExact:!0,weekdays:["D\xe9 Domhnaigh","D\xe9 Luain","D\xe9 M\xe1irt","D\xe9 C\xe9adaoin","D\xe9ardaoin","D\xe9 hAoine","D\xe9 Satharn"],weekdaysShort:["Dom","Lua","M\xe1i","C\xe9a","D\xe9a","hAo","Sat"],weekdaysMin:["Do","Lu","M\xe1","Ce","D\xe9","hA","Sa"],longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Inniu ag] LT",nextDay:"[Am\xe1rach ag] LT",nextWeek:"dddd [ag] LT",lastDay:"[Inn\xe9 aig] LT",lastWeek:"dddd [seo caite] [ag] LT",sameElse:"L"},relativeTime:{future:"i %s",past:"%s \xf3 shin",s:"c\xfapla soicind",ss:"%d soicind",m:"n\xf3im\xe9ad",mm:"%d n\xf3im\xe9ad",h:"uair an chloig",hh:"%d uair an chloig",d:"l\xe1",dd:"%d l\xe1",M:"m\xed",MM:"%d m\xed",y:"bliain",yy:"%d bliain"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(t){return t+(1===t?"d":t%10==2?"na":"mh")},week:{dow:1,doy:4}})}()},UpQW:function(t,e,n){!function(t){"use strict";var e=["\u062c\u0646\u0648\u0631\u06cc","\u0641\u0631\u0648\u0631\u06cc","\u0645\u0627\u0631\u0686","\u0627\u067e\u0631\u06cc\u0644","\u0645\u0626\u06cc","\u062c\u0648\u0646","\u062c\u0648\u0644\u0627\u0626\u06cc","\u0627\u06af\u0633\u062a","\u0633\u062a\u0645\u0628\u0631","\u0627\u06a9\u062a\u0648\u0628\u0631","\u0646\u0648\u0645\u0628\u0631","\u062f\u0633\u0645\u0628\u0631"],a=["\u0627\u062a\u0648\u0627\u0631","\u067e\u06cc\u0631","\u0645\u0646\u06af\u0644","\u0628\u062f\u06be","\u062c\u0645\u0639\u0631\u0627\u062a","\u062c\u0645\u0639\u06c1","\u06c1\u0641\u062a\u06c1"];n("wd/R").defineLocale("ur",{months:e,monthsShort:e,weekdays:a,weekdaysShort:a,weekdaysMin:a,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd\u060c D MMMM YYYY HH:mm"},meridiemParse:/\u0635\u0628\u062d|\u0634\u0627\u0645/,isPM:function(t){return"\u0634\u0627\u0645"===t},meridiem:function(t,e,n){return t<12?"\u0635\u0628\u062d":"\u0634\u0627\u0645"},calendar:{sameDay:"[\u0622\u062c \u0628\u0648\u0642\u062a] LT",nextDay:"[\u06a9\u0644 \u0628\u0648\u0642\u062a] LT",nextWeek:"dddd [\u0628\u0648\u0642\u062a] LT",lastDay:"[\u06af\u0630\u0634\u062a\u06c1 \u0631\u0648\u0632 \u0628\u0648\u0642\u062a] LT",lastWeek:"[\u06af\u0630\u0634\u062a\u06c1] dddd [\u0628\u0648\u0642\u062a] LT",sameElse:"L"},relativeTime:{future:"%s \u0628\u0639\u062f",past:"%s \u0642\u0628\u0644",s:"\u0686\u0646\u062f \u0633\u06cc\u06a9\u0646\u0688",ss:"%d \u0633\u06cc\u06a9\u0646\u0688",m:"\u0627\u06cc\u06a9 \u0645\u0646\u0679",mm:"%d \u0645\u0646\u0679",h:"\u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06c1",hh:"%d \u06af\u06be\u0646\u0679\u06d2",d:"\u0627\u06cc\u06a9 \u062f\u0646",dd:"%d \u062f\u0646",M:"\u0627\u06cc\u06a9 \u0645\u0627\u06c1",MM:"%d \u0645\u0627\u06c1",y:"\u0627\u06cc\u06a9 \u0633\u0627\u0644",yy:"%d \u0633\u0627\u0644"},preparse:function(t){return t.replace(/\u060c/g,",")},postformat:function(t){return t.replace(/,/g,"\u060c")},week:{dow:1,doy:4}})}()},UqmZ:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha"),s=a.global;a._set("global",{elements:{line:{tension:.4,backgroundColor:s.defaultColor,borderWidth:3,borderColor:s.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),t.exports=r.extend({draw:function(){var t,e,n,a,r=this._view,o=this._chart.ctx,u=r.spanGaps,c=this._children.slice(),l=s.elements.line,d=-1;for(this._loop&&c.length&&c.push(c[0]),o.save(),o.lineCap=r.borderCapStyle||l.borderCapStyle,o.setLineDash&&o.setLineDash(r.borderDash||l.borderDash),o.lineDashOffset=r.borderDashOffset||l.borderDashOffset,o.lineJoin=r.borderJoinStyle||l.borderJoinStyle,o.lineWidth=r.borderWidth||l.borderWidth,o.strokeStyle=r.borderColor||s.defaultColor,o.beginPath(),d=-1,t=0;t<c.length;++t)e=c[t],n=i.previousItem(c,t),a=e._view,0===t?a.skip||(o.moveTo(a.x,a.y),d=t):(n=-1===d?n:c[d],a.skip||(d!==t-1&&!u||-1===d?o.moveTo(a.x,a.y):i.canvas.lineTo(o,n._view,e._view),d=t));o.stroke(),o.restore()}})},Ur1D:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",ss:"%d mzuzwana",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(t,e,n){return t<11?"ekuseni":t<15?"emini":t<19?"entsambama":"ebusuku"},meridiemHour:function(t,e){return 12===t&&(t=0),"ekuseni"===e?t:"emini"===e?t>=11?t:t+12:"entsambama"===e||"ebusuku"===e?0===t?0:t+12:void 0},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,doy:4}})}()},"V/fk":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},V2x9:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("tet",{months:"Janeiru_Fevereiru_Marsu_Abril_Maiu_Ju\xf1u_Jullu_Agustu_Setembru_Outubru_Novembru_Dezembru".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingu_Segunda_Tersa_Kuarta_Kinta_Sesta_Sabadu".split("_"),weekdaysShort:"Dom_Seg_Ters_Kua_Kint_Sest_Sab".split("_"),weekdaysMin:"Do_Seg_Te_Ku_Ki_Ses_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Ohin iha] LT",nextDay:"[Aban iha] LT",nextWeek:"dddd [iha] LT",lastDay:"[Horiseik iha] LT",lastWeek:"dddd [semana kotuk] [iha] LT",sameElse:"L"},relativeTime:{future:"iha %s",past:"%s liuba",s:"minutu balun",ss:"minutu %d",m:"minutu ida",mm:"minutu %d",h:"oras ida",hh:"oras %d",d:"loron ida",dd:"loron %d",M:"fulan ida",MM:"fulan %d",y:"tinan ida",yy:"tinan %d"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},V3my:function(t,e,n){"use strict";var a,r=n("gIcY"),i=n("LvDl"),s=(n("DSvg"),n("SgmB"),n("Mxhz"),n("OLbh")),o=n("DNAf"),u=(n("sne2"),n("mtw6")),c=n("QFaf"),l=n("1Ni5");n("aexS"),n("9nlD"),function(t){t.editing="editing"}(a||(a={}));var d=function(){return function(){}}();n.d(e,"a",function(){return f});var f=function(){function t(t,e,n,r,i,s,u,c,l,d){this.authService=t,this.authStorageService=e,this.route=n,this.router=r,this.modalService=i,this.roleService=s,this.userService=u,this.notificationService=c,this.i18n=l,this.actionLabels=d,this.userFormMode=a,this.messages=new o.a({empty:"There are no roles."},this.i18n),this.resource=this.i18n("user"),this.createForm(),this.messages=new o.a({empty:"There are no roles."},this.i18n)}return t.prototype.createForm=function(){this.userForm=new c.a({username:new r.i("",{validators:[r.A.required]}),name:new r.i(""),password:new r.i("",{validators:[]}),confirmpassword:new r.i("",{updateOn:"blur",validators:[]}),email:new r.i("",{validators:[r.A.email]}),roles:new r.i([])},{validators:[l.a.match("password","confirmpassword")]})},t.prototype.ngOnInit=function(){var t=this;this.router.url.startsWith("/user-management/users/edit")?(this.mode=this.userFormMode.editing,this.action=this.actionLabels.EDIT):this.action=this.actionLabels.CREATE,this.roleService.list().subscribe(function(e){t.allRoles=i.map(e,function(t){return t.enabled=!0,t})}),this.mode===this.userFormMode.editing&&this.initEdit()},t.prototype.initEdit=function(){var t=this;this.disableForEdit(),this.route.params.subscribe(function(e){t.userService.get(e.username).subscribe(function(e){t.response=i.cloneDeep(e),t.setResponse(e)})})},t.prototype.disableForEdit=function(){this.userForm.get("username").disable()},t.prototype.setResponse=function(t){var e=this;["username","name","email","roles"].forEach(function(n){return e.userForm.get(n).setValue(t[n])})},t.prototype.getRequest=function(){var t=this,e=new d;return["username","password","name","email","roles"].forEach(function(n){return e[n]=t.userForm.get(n).value}),e},t.prototype.createAction=function(){var t=this,e=this.getRequest();this.userService.create(e).subscribe(function(){t.notificationService.show(u.a.success,t.i18n('Created user "{{username}}"',{username:e.username})),t.router.navigate(["/user-management/users"])},function(){t.userForm.setErrors({cdSubmitButton:!0})})},t.prototype.editAction=function(){var t=this;if(this.isUserRemovingNeededRolePermissions()){var e={titleText:this.i18n("Update user"),buttonText:this.i18n("Continue"),bodyTpl:this.removeSelfUserReadUpdatePermissionTpl,onSubmit:function(){t.modalRef.hide(),t.doEditAction()},onCancel:function(){t.userForm.setErrors({cdSubmitButton:!0}),t.userForm.get("roles").reset(t.userForm.get("roles").value)}};this.modalRef=this.modalService.show(s.a,{initialState:e})}else this.doEditAction()},t.prototype.isCurrentUser=function(){return this.authStorageService.getUsername()===this.userForm.getValue("username")},t.prototype.isUserChangingRoles=function(){return this.isCurrentUser()&&this.response&&!i.isEqual(this.response.roles,this.userForm.getValue("roles"))},t.prototype.isUserRemovingNeededRolePermissions=function(){return this.isCurrentUser()&&!this.hasUserReadUpdatePermissions(this.userForm.getValue("roles"))},t.prototype.hasUserReadUpdatePermissions=function(t){void 0===t&&(t=[]);for(var e=function(e){if(-1!==t.indexOf(e.name)&&e.scopes_permissions.user){var n=e.scopes_permissions.user;return{value:["read","update"].every(function(t){return-1!==n.indexOf(t)})}}},n=0,a=this.allRoles;n<a.length;n++){var r=e(a[n]);if("object"==typeof r)return r.value}return!1},t.prototype.doEditAction=function(){var t=this,e=this.getRequest();this.userService.update(e).subscribe(function(){t.isUserChangingRoles()?t.authService.logout(function(){t.notificationService.show(u.a.info,t.i18n("You were automatically logged out because your roles have been changed."))}):(t.notificationService.show(u.a.success,t.i18n('Updated user "{{username}}"',{username:e.username})),t.router.navigate(["/user-management/users"]))},function(){t.userForm.setErrors({cdSubmitButton:!0})})},t.prototype.submit=function(){this.mode===this.userFormMode.editing?this.editAction():this.createAction()},t}()},VE89:function(t,e,n){var a=n("mrSG").__extends;Object.defineProperty(e,"__esModule",{value:!0});var r=function(){return function(t){this.node=t}}();e.NodeEvent=r,e.NodeSelectedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.NodeUnselectedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r);var i=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r);e.NodeDestructiveEvent=i,e.NodeMovedEvent=function(t){function e(e,n){var a=t.call(this,e)||this;return a.previousParent=n,a}return a(e,t),e}(i),e.NodeRemovedEvent=function(t){function e(e,n){var a=t.call(this,e)||this;return a.lastIndex=n,a}return a(e,t),e}(i),e.NodeCreatedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(i),e.NodeRenamedEvent=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.oldValue=n,r.newValue=a,r}return a(e,t),e}(i),e.NodeExpandedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.NodeCollapsedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.MenuItemSelectedEvent=function(t){function e(e,n){var a=t.call(this,e)||this;return a.selectedItem=n,a}return a(e,t),e}(r),e.LoadNextLevelEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.NodeCheckedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.NodeUncheckedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r),e.NodeIndeterminedEvent=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e}(r)},VHo1:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}(n("rLYq"))},VNr4:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("6blF"),r=n("isby"),i=n("67Y/"),s=n("McSo"),o=n("0/uQ");function u(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if(1===t.length){var n=t[0];if(Object(r.a)(n))return c(n,null);if(Object(s.a)(n)&&Object.getPrototypeOf(n)===Object.prototype){var a=Object.keys(n);return c(a.map(function(t){return n[t]}),a)}}if("function"==typeof t[t.length-1]){var o=t.pop();return c(t=1===t.length&&Object(r.a)(t[0])?t[0]:t,null).pipe(Object(i.a)(function(t){return o.apply(void 0,t)}))}return c(t,null)}function c(t,e){return new a.a(function(n){var a=t.length;if(0!==a)for(var r=new Array(a),i=0,s=0,u=function(u){var c=Object(o.a)(t[u]),l=!1;n.add(c.subscribe({next:function(t){l||(l=!0,s++),r[u]=t},error:function(t){return n.error(t)},complete:function(){++i!==a&&l||(s===a&&n.next(e?e.reduce(function(t,e,n){return t[e]=r[n],t},{}):r),n.complete())}}))},c=0;c<a;c++)u(c);else n.complete()})}},VTlA:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("mSOc"),n("ufoC");var a=function(){function t(t,e){this.taskMessageService=t,this.summaryService=e}return t.prototype.init=function(t,e,n,a,r,i,s){var o=this;this.getUpdate=t,this.preProcessing=e,this.setList=n,this.onFetchError=a,this.taskFilter=r,this.itemFilter=i,this.builders=s||{},this.summaryDataSubscription=this.summaryService.subscribe(function(t){t&&o.getUpdate().subscribe(function(e){o.updateData(e,t.executing_tasks.filter(o.taskFilter))},o.onFetchError)},this.onFetchError)},t.prototype.updateData=function(t,e){var n=this,a=this.preProcessing?this.preProcessing(t):t;this.addMissing(a,e),a.forEach(function(t){var a=e.filter(function(e){return n.itemFilter(t,e)});t.cdExecuting=n.getTaskAction(a)}),this.setList(a)},t.prototype.addMissing=function(t,e){var n=this,a=this.builders.default||{};e.forEach(function(e){var r=t.find(function(t){return n.itemFilter(t,e)}),i=n.builders[e.name];r||!i&&!a||t.push(i?i(e.metadata):a(e))})},t.prototype.getTaskAction=function(t){var e=this;if(0!==t.length)return t.map(function(t){var n=t.progress?" "+t.progress+"%":"";return e.taskMessageService.getRunningText(t)+"..."+n}).join(", ")},t.prototype.ngOnDestroy=function(){this.summaryDataSubscription&&this.summaryDataSubscription.unsubscribe()},t}()},VUo1:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG");n("ZYjt"),e.SafeHtmlPipe=function(){function t(t){this.sanitizer=t}return t.prototype.transform=function(t){return this.sanitizer.bypassSecurityTrustHtml(t)},t.decorators=[{type:a.Pipe,args:[{name:"safeHtml"}]}],t}()},VXsX:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("LvDl"),r=n("mSOc"),i=n("CcnG"),s=function(){return function(t,e,n){this.name=t,this.metadata=e,this.onTaskFinished=n}}(),o=function(){function t(t){var e=this;this.subscriptions=[],t.subscribe(function(t){if(t)for(var n=t.executing_tasks,a=t.finished_tasks,r=[],i=0,s=e.subscriptions;i<s.length;i++){var o=s[i],u=e._getTask(o,a),c=e._getTask(o,n);null!==u&&null===c&&o.onTaskFinished(u),null!==c&&r.push(o),e.subscriptions=r}})}return t.prototype.subscribe=function(t,e,n){this.subscriptions.push(new s(t,e,n))},t.prototype._getTask=function(t,e){for(var n=0,r=e;n<r.length;n++){var i=r[n];if(i.name===t.name&&a.isEqual(i.metadata,t.metadata))return i}return null},t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(r.a))},token:t,providedIn:"root"}),t}()},"VYA+":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CVuo"),r=n("HV4d"),i=n("h+PQ");function s(t){return null==t}e.setColumnDefaults=function(t){if(t)for(var e=!1,n=0,o=t;n<o.length;n++){var u=o[n];u.$$id||(u.$$id=r.id()),s(u.prop)&&u.name&&(u.prop=a.camelCase(u.name)),u.$$valueGetter||(u.$$valueGetter=i.getterForProp(u.prop)),!s(u.prop)&&s(u.name)&&(u.name=a.deCamelCase(String(u.prop))),s(u.prop)&&s(u.name)&&(u.name=""),u.hasOwnProperty("resizeable")||(u.resizeable=!0),u.hasOwnProperty("sortable")||(u.sortable=!0),u.hasOwnProperty("draggable")||(u.draggable=!0),u.hasOwnProperty("canAutoResize")||(u.canAutoResize=!0),u.hasOwnProperty("width")||(u.width=150),u.hasOwnProperty("isTreeColumn")&&u.isTreeColumn&&!e?e=!0:u.isTreeColumn=!1}},e.isNullOrUndefined=s,e.translateTemplates=function(t){for(var e=[],n=0,a=t;n<a.length;n++){for(var r=a[n],i={},s=0,o=Object.getOwnPropertyNames(r);s<o.length;s++){var u=o[s];i[u]=r[u]}r.headerTemplate&&(i.headerTemplate=r.headerTemplate),r.cellTemplate&&(i.cellTemplate=r.cellTemplate),r.summaryFunc&&(i.summaryFunc=r.summaryFunc),r.summaryTemplate&&(i.summaryTemplate=r.summaryTemplate),e.push(i)}return e}},Vclq:function(t,e,n){!function(t){"use strict";var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),a=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;t.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_s\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[ma\xf1ana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:0,doy:6}})}(n("wd/R"))},VgNv:function(t,e,n){"use strict";var a=n("CDJp"),r=n("RDha");a._set("global",{plugins:{}}),t.exports={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var a,r,i,s,o,u=this.descriptors(t),c=u.length;for(a=0;a<c;++a)if("function"==typeof(o=(i=(r=u[a]).plugin)[e])&&((s=[t].concat(n||[])).push(r.options),!1===o.apply(i,s)))return!1;return!0},descriptors:function(t){var e=t.$plugins||(t.$plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],i=[],s=t&&t.config||{},o=s.options&&s.options.plugins||{};return this._plugins.concat(s.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,s=o[e];!1!==s&&(!0===s&&(s=r.clone(a.global.plugins[e])),n.push(t),i.push({plugin:t,options:s||{}}))}}),e.descriptors=i,e.id=this._cacheId,i},_invalidate:function(t){delete t.$plugins}}},Vhfg:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("67Y/"),r=n("ej+x"),i=n("CcnG"),s=n("ZYCi"),o=function(){function t(t,e){this.router=t,this.featureToggles=e}return t.prototype.canActivate=function(t){var e=this;return this.featureToggles.get().pipe(Object(a.a)(function(n){return!1!==n[t.routeConfig.path]||(e.router.navigate(["404"]),!1)}))},t.prototype.canActivateChild=function(t){return this.canActivate(t.parent)},t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(s.l),i.inject(r.a))},token:t,providedIn:"root"}),t}()},"VnD/":function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t,e){return function(n){return n.lift(new s(t,e))}}var s=function(){function t(t,e){this.predicate=t,this.thisArg=e}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.predicate,this.thisArg))},t}(),o=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.predicate=n,r.thisArg=a,r.count=0,r}return a.__extends(e,t),e.prototype._next=function(t){var e;try{e=this.predicate.call(this.thisArg,t,this.count++)}catch(n){return void this.destination.error(n)}e&&this.destination.next(t)},e}(r.a)},W0Ae:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("mrSG"),r=n("isby"),i=n("IUTb"),s=n("MGBS"),o=n("zotm");function u(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if(1===t.length){if(!Object(r.a)(t[0]))return t[0];t=t[0]}return Object(i.a)(t,void 0).lift(new c)}var c=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new l(t))},t}(),l=function(t){function e(e){var n=t.call(this,e)||this;return n.hasFirst=!1,n.observables=[],n.subscriptions=[],n}return a.__extends(e,t),e.prototype._next=function(t){this.observables.push(t)},e.prototype._complete=function(){var t=this.observables,e=t.length;if(0===e)this.destination.complete();else{for(var n=0;n<e&&!this.hasFirst;n++){var a=t[n],r=Object(o.a)(this,a,a,n);this.subscriptions&&this.subscriptions.push(r),this.add(r)}this.observables=null}},e.prototype.notifyNext=function(t,e,n,a,r){if(!this.hasFirst){this.hasFirst=!0;for(var i=0;i<this.subscriptions.length;i++)if(i!==n){var s=this.subscriptions[i];s.unsubscribe(),this.remove(s)}this.subscriptions=null}this.destination.next(e)},e}(s.a)},WOoz:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.asc="asc",t.desc="desc"}(e.SortDirection||(e.SortDirection={}))},WYrj:function(t,e,n){!function(t){"use strict";var e=["\u0796\u07ac\u0782\u07aa\u0787\u07a6\u0783\u07a9","\u078a\u07ac\u0784\u07b0\u0783\u07aa\u0787\u07a6\u0783\u07a9","\u0789\u07a7\u0783\u07a8\u0797\u07aa","\u0787\u07ad\u0795\u07b0\u0783\u07a9\u078d\u07aa","\u0789\u07ad","\u0796\u07ab\u0782\u07b0","\u0796\u07aa\u078d\u07a6\u0787\u07a8","\u0787\u07af\u078e\u07a6\u0790\u07b0\u0793\u07aa","\u0790\u07ac\u0795\u07b0\u0793\u07ac\u0789\u07b0\u0784\u07a6\u0783\u07aa","\u0787\u07ae\u0786\u07b0\u0793\u07af\u0784\u07a6\u0783\u07aa","\u0782\u07ae\u0788\u07ac\u0789\u07b0\u0784\u07a6\u0783\u07aa","\u0791\u07a8\u0790\u07ac\u0789\u07b0\u0784\u07a6\u0783\u07aa"],a=["\u0787\u07a7\u078b\u07a8\u0787\u07b0\u078c\u07a6","\u0780\u07af\u0789\u07a6","\u0787\u07a6\u0782\u07b0\u078e\u07a7\u0783\u07a6","\u0784\u07aa\u078b\u07a6","\u0784\u07aa\u0783\u07a7\u0790\u07b0\u078a\u07a6\u078c\u07a8","\u0780\u07aa\u0786\u07aa\u0783\u07aa","\u0780\u07ae\u0782\u07a8\u0780\u07a8\u0783\u07aa"];n("wd/R").defineLocale("dv",{months:e,monthsShort:e,weekdays:a,weekdaysShort:a,weekdaysMin:"\u0787\u07a7\u078b\u07a8_\u0780\u07af\u0789\u07a6_\u0787\u07a6\u0782\u07b0_\u0784\u07aa\u078b\u07a6_\u0784\u07aa\u0783\u07a7_\u0780\u07aa\u0786\u07aa_\u0780\u07ae\u0782\u07a8".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/\u0789\u0786|\u0789\u078a/,isPM:function(t){return"\u0789\u078a"===t},meridiem:function(t,e,n){return t<12?"\u0789\u0786":"\u0789\u078a"},calendar:{sameDay:"[\u0789\u07a8\u0787\u07a6\u078b\u07aa] LT",nextDay:"[\u0789\u07a7\u078b\u07a6\u0789\u07a7] LT",nextWeek:"dddd LT",lastDay:"[\u0787\u07a8\u0787\u07b0\u0794\u07ac] LT",lastWeek:"[\u078a\u07a7\u0787\u07a8\u078c\u07aa\u0788\u07a8] dddd LT",sameElse:"L"},relativeTime:{future:"\u078c\u07ac\u0783\u07ad\u078e\u07a6\u0787\u07a8 %s",past:"\u0786\u07aa\u0783\u07a8\u0782\u07b0 %s",s:"\u0790\u07a8\u0786\u07aa\u0782\u07b0\u078c\u07aa\u0786\u07ae\u0785\u07ac\u0787\u07b0",ss:"d% \u0790\u07a8\u0786\u07aa\u0782\u07b0\u078c\u07aa",m:"\u0789\u07a8\u0782\u07a8\u0793\u07ac\u0787\u07b0",mm:"\u0789\u07a8\u0782\u07a8\u0793\u07aa %d",h:"\u078e\u07a6\u0791\u07a8\u0787\u07a8\u0783\u07ac\u0787\u07b0",hh:"\u078e\u07a6\u0791\u07a8\u0787\u07a8\u0783\u07aa %d",d:"\u078b\u07aa\u0788\u07a6\u0780\u07ac\u0787\u07b0",dd:"\u078b\u07aa\u0788\u07a6\u0790\u07b0 %d",M:"\u0789\u07a6\u0780\u07ac\u0787\u07b0",MM:"\u0789\u07a6\u0790\u07b0 %d",y:"\u0787\u07a6\u0780\u07a6\u0783\u07ac\u0787\u07b0",yy:"\u0787\u07a6\u0780\u07a6\u0783\u07aa %d"},preparse:function(t){return t.replace(/\u060c/g,",")},postformat:function(t){return t.replace(/,/g,"\u060c")},week:{dow:7,doy:12}})}()},WiuZ:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R"),i=n("eajB"),s=n("lqqz"),o=n("NJnL"),u=n("gIcY"),c=n("ANnk"),l=n("f/UV"),d=n("aexS"),f=n("OZfm");n("wnGv"),n("Jm/i"),n.d(e,"a",function(){return p}),n.d(e,"b",function(){return I});var p=a["\u0275crt"]({encapsulation:0,styles:[[".select-menu-item[_ngcontent-%COMP%]{display:block;cursor:pointer;border-bottom:1px solid rgba(0,0,0,.09);font-size:12px}.select-menu-item[_ngcontent-%COMP%]:hover{background-color:#f5f5f5}.select-menu-item-icon[_ngcontent-%COMP%]{float:left;padding:.5em;width:3em}.select-menu-item-content[_ngcontent-%COMP%]{padding:.5em}"]],data:{}});function h(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","help-block text-center"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" "," "]))],null,function(t,e){t(e,1,0,e.component.messages.customValidations[e.parent.context.$implicit])})}function g(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,null,null,null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,h)),a["\u0275did"](2,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,2,0,n.form.showError("filter",a["\u0275nov"](e.parent,2))&&n.filter.hasError(e.context.$implicit))},null)}function b(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-check"]],null,null,null,null,null))],null,null)}function m(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,null,null,null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,1,"small",[["class","text-muted"]],null,null,null,null,null)),(t()(),a["\u0275ted"](3,null,[" ","\xa0 "]))],null,function(t,e){t(e,3,0,e.parent.context.$implicit.description)})}function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,10,"div",[["class","select-menu-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.triggerSelection(t.context.$implicit)&&a),a},null,null)),a["\u0275did"](1,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](2,{"help-block disabled":0}),(t()(),a["\u0275eld"](3,0,null,null,3,"div",[["class","select-menu-item-icon"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,b)),a["\u0275did"](5,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](-1,null,[" \xa0 "])),(t()(),a["\u0275eld"](7,0,null,null,3,"div",[["class","select-menu-item-content"]],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,[" "," "])),(t()(),a["\u0275and"](16777216,null,null,1,null,m)),a["\u0275did"](10,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,!(n.data.length!==n.selectionLimit&&e.context.$implicit.enabled||e.context.$implicit.selected));t(e,1,0,"select-menu-item",a),t(e,5,0,e.context.$implicit.selected),t(e,10,0,e.context.$implicit.description)},function(t,e){t(e,8,0,e.context.$implicit.name)})}function v(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"div",[["class","select-menu-item"]],null,[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.addCustomOption(r.filter.value)&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,2,"div",[["class","select-menu-item-icon"]],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-tag"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,[" \xa0 "])),(t()(),a["\u0275eld"](4,0,null,null,1,"div",[["class","select-menu-item-content"]],null,null,null,null,null)),(t()(),a["\u0275ted"](5,null,[" "," '","' "]))],null,function(t,e){var n=e.component;t(e,5,0,n.messages.add,n.filter.value)})}function _(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,16777216,null,null,2,"span",[["class","help-block text-center text-warning"]],[[1,"aria-describedby",0]],null,null,null,null)),a["\u0275did"](1,212992,null,0,i.c,[a.ViewContainerRef,s.a,i.a,a.ElementRef,a.Renderer2,o.a],{tooltip:[0,"tooltip"]},null),(t()(),a["\u0275ted"](2,null,[" "," "])),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.component.messages.selectionLimit.tooltip)},function(t,e){var n=e.component;t(e,0,0,a["\u0275nov"](e,1).ariaDescribedby),t(e,2,0,n.messages.selectionLimit.text)})}function x(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","has-warning"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,_)),a["\u0275did"](2,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.data.length===n.selectionLimit)},null)}function T(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,16,"form",[["name","form"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var r=!0;return"submit"===e&&(r=!1!==a["\u0275nov"](t,2).onSubmit(n)&&r),"reset"===e&&(r=!1!==a["\u0275nov"](t,2).onReset()&&r),r},null,null)),a["\u0275did"](1,16384,null,0,u.D,[],null,null),a["\u0275did"](2,540672,[["formDir",4]],0,u.l,[[8,null],[8,null]],{form:[0,"form"]},null),a["\u0275prd"](2048,null,u.d,null,[u.l]),a["\u0275did"](4,16384,null,0,u.s,[[4,u.d]],null,null),(t()(),a["\u0275eld"](5,0,null,null,11,"div",[],null,null,null,null,null)),a["\u0275did"](6,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngClass:[0,"ngClass"]},null),a["\u0275pod"](7,{"has-error":0}),(t()(),a["\u0275eld"](8,0,null,null,6,"input",[["class","form-control text-center"],["formControlName","filter"],["type","text"]],[[8,"placeholder",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"keyup"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var r=!0,i=t.component;return"input"===e&&(r=!1!==a["\u0275nov"](t,9)._handleInput(n.target.value)&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,9).onTouched()&&r),"compositionstart"===e&&(r=!1!==a["\u0275nov"](t,9)._compositionStart()&&r),"compositionend"===e&&(r=!1!==a["\u0275nov"](t,9)._compositionEnd(n.target.value)&&r),"keyup"===e&&(r=!1!==(13==n.keyCode?i.selectOption():i.updateFilter())&&r),r},null,null)),a["\u0275did"](9,16384,null,0,u.e,[a.Renderer2,a.ElementRef,[2,u.b]],null,null),a["\u0275prd"](1024,null,u.p,function(t){return[t]},[u.e]),a["\u0275did"](11,671744,null,0,u.j,[[3,u.d],[8,null],[8,null],[6,u.p],[2,u.F]],{name:[0,"name"]},null),a["\u0275prd"](2048,null,u.q,null,[u.j]),a["\u0275did"](13,16384,null,0,u.r,[[4,u.q]],null,null),a["\u0275did"](14,4210688,null,0,c.a,[[2,l.a],d.a,a.ElementRef],null,null),(t()(),a["\u0275and"](16777216,null,null,1,null,g)),a["\u0275did"](16,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,y)),a["\u0275did"](18,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,v)),a["\u0275did"](20,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,x)),a["\u0275did"](22,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,2,0,n.form);var r=t(e,7,0,n.form.showError("filter",a["\u0275nov"](e,2)));t(e,6,0,r),t(e,11,0,"filter"),t(e,16,0,n.Object.keys(n.messages.customValidations)),t(e,18,0,n.filteredOptions),t(e,20,0,n.isCreatable()),t(e,22,0,n.data.length===n.selectionLimit)},function(t,e){var n=e.component;t(e,0,0,a["\u0275nov"](e,4).ngClassUntouched,a["\u0275nov"](e,4).ngClassTouched,a["\u0275nov"](e,4).ngClassPristine,a["\u0275nov"](e,4).ngClassDirty,a["\u0275nov"](e,4).ngClassValid,a["\u0275nov"](e,4).ngClassInvalid,a["\u0275nov"](e,4).ngClassPending),t(e,8,0,n.messages.filter,a["\u0275nov"](e,13).ngClassUntouched,a["\u0275nov"](e,13).ngClassTouched,a["\u0275nov"](e,13).ngClassPristine,a["\u0275nov"](e,13).ngClassDirty,a["\u0275nov"](e,13).ngClassValid,a["\u0275nov"](e,13).ngClassInvalid,a["\u0275nov"](e,13).ngClassPending)})}function w(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,16777216,null,null,3,"a",[["class","select-menu-edit"],["container","body"],["outsideClick","true"],["placement","bottom"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275did"](2,212992,null,0,f.c,[f.a,a.ElementRef,a.Renderer2,a.ViewContainerRef,s.a,o.a],{popover:[0,"popover"],placement:[1,"placement"],outsideClick:[2,"outsideClick"],container:[3,"container"]},null),a["\u0275ncd"](null,0),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,"select-menu-edit",e.component.elemClass),t(e,2,0,a["\u0275nov"](e.parent,0),"bottom","true","body")},null)}function S(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" ","\n"]))],null,function(t,e){t(e,1,0,e.component.messages.empty)})}function O(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[" ","\n"]))],null,function(t,e){t(e,1,0,e.component.messages.noOptions)})}function I(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,[["popTemplate",2]],null,0,null,T)),(t()(),a["\u0275and"](16777216,null,null,1,null,w)),a["\u0275did"](2,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,S)),a["\u0275did"](4,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,O)),a["\u0275did"](6,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.options.length>0),t(e,4,0,0===n.data.length&&n.options.length>0),t(e,6,0,0===n.options.length)},null)}},WxRl:function(t,e,n){!function(t){"use strict";var e="vas\xe1rnap h\xe9tf\u0151n kedden szerd\xe1n cs\xfct\xf6rt\xf6k\xf6n p\xe9nteken szombaton".split(" ");function n(t,e,n,a){var r=t;switch(n){case"s":return a||e?"n\xe9h\xe1ny m\xe1sodperc":"n\xe9h\xe1ny m\xe1sodperce";case"ss":return r+(a||e)?" m\xe1sodperc":" m\xe1sodperce";case"m":return"egy"+(a||e?" perc":" perce");case"mm":return r+(a||e?" perc":" perce");case"h":return"egy"+(a||e?" \xf3ra":" \xf3r\xe1ja");case"hh":return r+(a||e?" \xf3ra":" \xf3r\xe1ja");case"d":return"egy"+(a||e?" nap":" napja");case"dd":return r+(a||e?" nap":" napja");case"M":return"egy"+(a||e?" h\xf3nap":" h\xf3napja");case"MM":return r+(a||e?" h\xf3nap":" h\xf3napja");case"y":return"egy"+(a||e?" \xe9v":" \xe9ve");case"yy":return r+(a||e?" \xe9v":" \xe9ve")}return""}function a(t){return(t?"":"[m\xfalt] ")+"["+e[this.day()]+"] LT[-kor]"}t.defineLocale("hu",{months:"janu\xe1r_febru\xe1r_m\xe1rcius_\xe1prilis_m\xe1jus_j\xfanius_j\xfalius_augusztus_szeptember_okt\xf3ber_november_december".split("_"),monthsShort:"jan_feb_m\xe1rc_\xe1pr_m\xe1j_j\xfan_j\xfal_aug_szept_okt_nov_dec".split("_"),weekdays:"vas\xe1rnap_h\xe9tf\u0151_kedd_szerda_cs\xfct\xf6rt\xf6k_p\xe9ntek_szombat".split("_"),weekdaysShort:"vas_h\xe9t_kedd_sze_cs\xfct_p\xe9n_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(t){return"u"===t.charAt(1).toLowerCase()},meridiem:function(t,e,n){return t<12?!0===n?"de":"DE":!0===n?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return a.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return a.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s m\xfalva",past:"%s",s:n,ss:n,m:n,mm:n,h:n,hh:n,d:n,dd:n,M:n,MM:n,y:n,yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},WyAD:function(t,e,n){var a=n("yPMN")();a.helpers=n("RDha"),n("nDWh")(a),a.Animation=n("A5uo"),a.animationService=n("dpnK"),a.defaults=n("CDJp"),a.Element=n("K2E3"),a.elements=n("vvH+"),a.Interaction=n("mlr9"),a.layouts=n("fELs"),a.platform=n("iM7B"),a.plugins=n("VgNv"),a.Scale=n("cdu6"),a.scaleService=n("tjFV"),a.Ticks=n("g8vO"),a.Tooltip=n("x8uC"),n("6rqY")(a),n("KAQS")(a),n("paOr")(a),n("8TtQ")(a),n("YSsK")(a),n("Y4Rb")(a),n("8//i")(a),n("RCHg")(a),n("ZANz")(a),n("bidN")(a),n("XQh+")(a),n("G0Q6")(a),n("5ZZ7")(a),n("aB2c")(a),n("35yf")(a),n("ODdm")(a),n("Qexa")(a),n("S7Ns")(a),n("7O6V")(a),n("qzaf")(a),n("iYGd")(a),n("S3/U")(a);var r=n("jXIB");for(var i in r)r.hasOwnProperty(i)&&a.plugins.register(r[i]);a.platform.initialize(),t.exports=a,"undefined"!=typeof window&&(window.Chart=a),a.Legend=r.legend._element,a.Title=r.title._element,a.pluginService=a.plugins,a.PluginBase=a.Element.extend({}),a.canvasHelpers=a.helpers.canvas,a.layoutService=a.layouts},X709:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"s\xf6ndag_m\xe5ndag_tisdag_onsdag_torsdag_fredag_l\xf6rdag".split("_"),weekdaysShort:"s\xf6n_m\xe5n_tis_ons_tor_fre_l\xf6r".split("_"),weekdaysMin:"s\xf6_m\xe5_ti_on_to_fr_l\xf6".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Ig\xe5r] LT",nextWeek:"[P\xe5] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"f\xf6r %s sedan",s:"n\xe5gra sekunder",ss:"%d sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en m\xe5nad",MM:"%d m\xe5nader",y:"ett \xe5r",yy:"%d \xe5r"},dayOfMonthOrdinalParse:/\d{1,2}(e|a)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"e":1===e?"a":2===e?"a":"e")},week:{dow:1,doy:4}})}()},X8CM:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha");a._set("global",{elements:{arc:{backgroundColor:a.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),t.exports=r.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var a=i.getAngleFromPoint(n,{x:t,y:e}),r=a.angle,s=a.distance,o=n.startAngle,u=n.endAngle;u<o;)u+=2*Math.PI;for(;r>u;)r-=2*Math.PI;for(;r<o;)r+=2*Math.PI;return r>=o&&r<=u&&s>=n.innerRadius&&s<=n.outerRadius}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,a=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,a),t.arc(e.x,e.y,e.innerRadius,a,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},XDpg:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("zh-cn",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u5468\u65e5_\u5468\u4e00_\u5468\u4e8c_\u5468\u4e09_\u5468\u56db_\u5468\u4e94_\u5468\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5Ah\u70b9mm\u5206",LLLL:"YYYY\u5e74M\u6708D\u65e5ddddAh\u70b9mm\u5206",l:"YYYY/M/D",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm"},meridiemParse:/\u51cc\u6668|\u65e9\u4e0a|\u4e0a\u5348|\u4e2d\u5348|\u4e0b\u5348|\u665a\u4e0a/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u51cc\u6668"===e||"\u65e9\u4e0a"===e||"\u4e0a\u5348"===e?t:"\u4e0b\u5348"===e||"\u665a\u4e0a"===e?t+12:t>=11?t:t+12},meridiem:function(t,e,n){var a=100*t+e;return a<600?"\u51cc\u6668":a<900?"\u65e9\u4e0a":a<1130?"\u4e0a\u5348":a<1230?"\u4e2d\u5348":a<1800?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(\u65e5|\u6708|\u5468)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\u65e5";case"M":return t+"\u6708";case"w":case"W":return t+"\u5468";default:return t}},relativeTime:{future:"%s\u5185",past:"%s\u524d",s:"\u51e0\u79d2",ss:"%d \u79d2",m:"1 \u5206\u949f",mm:"%d \u5206\u949f",h:"1 \u5c0f\u65f6",hh:"%d \u5c0f\u65f6",d:"1 \u5929",dd:"%d \u5929",M:"1 \u4e2a\u6708",MM:"%d \u4e2a\u6708",y:"1 \u5e74",yy:"%d \u5e74"},week:{dow:1,doy:4}})}()},XFyV:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},XLvN:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("te",{months:"\u0c1c\u0c28\u0c35\u0c30\u0c3f_\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f_\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f_\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d_\u0c2e\u0c47_\u0c1c\u0c42\u0c28\u0c4d_\u0c1c\u0c41\u0c32\u0c48_\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41_\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d_\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d_\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d_\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d".split("_"),monthsShort:"\u0c1c\u0c28._\u0c2b\u0c3f\u0c2c\u0c4d\u0c30._\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f_\u0c0f\u0c2a\u0c4d\u0c30\u0c3f._\u0c2e\u0c47_\u0c1c\u0c42\u0c28\u0c4d_\u0c1c\u0c41\u0c32\u0c48_\u0c06\u0c17._\u0c38\u0c46\u0c2a\u0c4d._\u0c05\u0c15\u0c4d\u0c1f\u0c4b._\u0c28\u0c35._\u0c21\u0c3f\u0c38\u0c46.".split("_"),monthsParseExact:!0,weekdays:"\u0c06\u0c26\u0c3f\u0c35\u0c3e\u0c30\u0c02_\u0c38\u0c4b\u0c2e\u0c35\u0c3e\u0c30\u0c02_\u0c2e\u0c02\u0c17\u0c33\u0c35\u0c3e\u0c30\u0c02_\u0c2c\u0c41\u0c27\u0c35\u0c3e\u0c30\u0c02_\u0c17\u0c41\u0c30\u0c41\u0c35\u0c3e\u0c30\u0c02_\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02_\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02".split("_"),weekdaysShort:"\u0c06\u0c26\u0c3f_\u0c38\u0c4b\u0c2e_\u0c2e\u0c02\u0c17\u0c33_\u0c2c\u0c41\u0c27_\u0c17\u0c41\u0c30\u0c41_\u0c36\u0c41\u0c15\u0c4d\u0c30_\u0c36\u0c28\u0c3f".split("_"),weekdaysMin:"\u0c06_\u0c38\u0c4b_\u0c2e\u0c02_\u0c2c\u0c41_\u0c17\u0c41_\u0c36\u0c41_\u0c36".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[\u0c28\u0c47\u0c21\u0c41] LT",nextDay:"[\u0c30\u0c47\u0c2a\u0c41] LT",nextWeek:"dddd, LT",lastDay:"[\u0c28\u0c3f\u0c28\u0c4d\u0c28] LT",lastWeek:"[\u0c17\u0c24] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u0c32\u0c4b",past:"%s \u0c15\u0c4d\u0c30\u0c3f\u0c24\u0c02",s:"\u0c15\u0c4a\u0c28\u0c4d\u0c28\u0c3f \u0c15\u0c4d\u0c37\u0c23\u0c3e\u0c32\u0c41",ss:"%d \u0c38\u0c46\u0c15\u0c28\u0c4d\u0c32\u0c41",m:"\u0c12\u0c15 \u0c28\u0c3f\u0c2e\u0c3f\u0c37\u0c02",mm:"%d \u0c28\u0c3f\u0c2e\u0c3f\u0c37\u0c3e\u0c32\u0c41",h:"\u0c12\u0c15 \u0c17\u0c02\u0c1f",hh:"%d \u0c17\u0c02\u0c1f\u0c32\u0c41",d:"\u0c12\u0c15 \u0c30\u0c4b\u0c1c\u0c41",dd:"%d \u0c30\u0c4b\u0c1c\u0c41\u0c32\u0c41",M:"\u0c12\u0c15 \u0c28\u0c46\u0c32",MM:"%d \u0c28\u0c46\u0c32\u0c32\u0c41",y:"\u0c12\u0c15 \u0c38\u0c02\u0c35\u0c24\u0c4d\u0c38\u0c30\u0c02",yy:"%d \u0c38\u0c02\u0c35\u0c24\u0c4d\u0c38\u0c30\u0c3e\u0c32\u0c41"},dayOfMonthOrdinalParse:/\d{1,2}\u0c35/,ordinal:"%d\u0c35",meridiemParse:/\u0c30\u0c3e\u0c24\u0c4d\u0c30\u0c3f|\u0c09\u0c26\u0c2f\u0c02|\u0c2e\u0c27\u0c4d\u0c2f\u0c3e\u0c39\u0c4d\u0c28\u0c02|\u0c38\u0c3e\u0c2f\u0c02\u0c24\u0c4d\u0c30\u0c02/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u0c30\u0c3e\u0c24\u0c4d\u0c30\u0c3f"===e?t<4?t:t+12:"\u0c09\u0c26\u0c2f\u0c02"===e?t:"\u0c2e\u0c27\u0c4d\u0c2f\u0c3e\u0c39\u0c4d\u0c28\u0c02"===e?t>=10?t:t+12:"\u0c38\u0c3e\u0c2f\u0c02\u0c24\u0c4d\u0c30\u0c02"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"\u0c30\u0c3e\u0c24\u0c4d\u0c30\u0c3f":t<10?"\u0c09\u0c26\u0c2f\u0c02":t<17?"\u0c2e\u0c27\u0c4d\u0c2f\u0c3e\u0c39\u0c4d\u0c28\u0c02":t<20?"\u0c38\u0c3e\u0c2f\u0c02\u0c24\u0c4d\u0c30\u0c02":"\u0c30\u0c3e\u0c24\u0c4d\u0c30\u0c3f"},week:{dow:0,doy:6}})}()},"XQh+":function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,a=n.datasets,r=n.labels;if(a.length)for(var i=0;i<a[0].data.length;++i)e.push('<li><span style="background-color:'+a[0].backgroundColor[i]+'"></span>'),r[i]&&e.push(r[i]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,a){var r=t.getDatasetMeta(0),s=e.datasets[0],o=r.data[a],u=o&&o.custom||{},c=i.valueAtIndexOrDefault,l=t.options.elements.arc;return{text:n,fillStyle:u.backgroundColor?u.backgroundColor:c(s.backgroundColor,a,l.backgroundColor),strokeStyle:u.borderColor?u.borderColor:c(s.borderColor,a,l.borderColor),lineWidth:u.borderWidth?u.borderWidth:c(s.borderWidth,a,l.borderWidth),hidden:isNaN(s.data[a])||r.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,a,r,i=e.index,s=this.chart;for(n=0,a=(s.data.datasets||[]).length;n<a;++n)(r=s.getDatasetMeta(n)).data[i]&&(r.data[i].hidden=!r.data[i].hidden);s.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],a=": "+e.datasets[t.datasetIndex].data[t.index];return i.isArray(n)?(n=n.slice())[0]+=a:n+=a,n}}}}),a._set("pie",i.clone(a.doughnut)),a._set("pie",{cutoutPercentage:0}),t.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:r.Arc,linkScales:i.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,a=n.chartArea,r=n.options,s=r.elements.arc,o=a.right-a.left-s.borderWidth,u=a.bottom-a.top-s.borderWidth,c=Math.min(o,u),l={x:0,y:0},d=e.getMeta(),f=r.cutoutPercentage,p=r.circumference;if(p<2*Math.PI){var h=r.rotation%(2*Math.PI),g=(h+=2*Math.PI*(h>=Math.PI?-1:h<-Math.PI?1:0))+p,b={x:Math.cos(h),y:Math.sin(h)},m={x:Math.cos(g),y:Math.sin(g)},y=h<=0&&g>=0||h<=2*Math.PI&&2*Math.PI<=g,v=h<=.5*Math.PI&&.5*Math.PI<=g||h<=2.5*Math.PI&&2.5*Math.PI<=g,_=h<=-Math.PI&&-Math.PI<=g||h<=Math.PI&&Math.PI<=g,x=h<=.5*-Math.PI&&.5*-Math.PI<=g||h<=1.5*Math.PI&&1.5*Math.PI<=g,T=f/100,w={x:_?-1:Math.min(b.x*(b.x<0?1:T),m.x*(m.x<0?1:T)),y:x?-1:Math.min(b.y*(b.y<0?1:T),m.y*(m.y<0?1:T))},S={x:y?1:Math.max(b.x*(b.x>0?1:T),m.x*(m.x>0?1:T)),y:v?1:Math.max(b.y*(b.y>0?1:T),m.y*(m.y>0?1:T))},O={width:.5*(S.x-w.x),height:.5*(S.y-w.y)};c=Math.min(o/O.width,u/O.height),l={x:-.5*(S.x+w.x),y:-.5*(S.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(d.data),n.outerRadius=Math.max((c-n.borderWidth)/2,0),n.innerRadius=Math.max(f?n.outerRadius/100*f:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=l.x*n.outerRadius,n.offsetY=l.y*n.outerRadius,d.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),i.each(d.data,function(n,a){e.updateElement(n,a,t)})},updateElement:function(t,e,n){var a=this,r=a.chart,s=r.chartArea,o=r.options,u=o.animation,c=(s.left+s.right)/2,l=(s.top+s.bottom)/2,d=o.rotation,f=o.rotation,p=a.getDataset(),h=n&&u.animateRotate?0:t.hidden?0:a.calculateCircumference(p.data[e])*(o.circumference/(2*Math.PI));i.extend(t,{_datasetIndex:a.index,_index:e,_model:{x:c+r.offsetX,y:l+r.offsetY,startAngle:d,endAngle:f,circumference:h,outerRadius:n&&u.animateScale?0:a.outerRadius,innerRadius:n&&u.animateScale?0:a.innerRadius,label:(0,i.valueAtIndexOrDefault)(p.label,e,r.data.labels[e])}});var g=t._model,b=t.custom||{},m=i.valueAtIndexOrDefault,y=this.chart.options.elements.arc;g.backgroundColor=b.backgroundColor?b.backgroundColor:m(p.backgroundColor,e,y.backgroundColor),g.borderColor=b.borderColor?b.borderColor:m(p.borderColor,e,y.borderColor),g.borderWidth=b.borderWidth?b.borderWidth:m(p.borderWidth,e,y.borderWidth),n&&u.animateRotate||(g.startAngle=0===e?o.rotation:a.getMeta().data[e-1]._model.endAngle,g.endAngle=g.startAngle+g.circumference),t.pivot()},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),a=0;return i.each(n.data,function(n,r){t=e.data[r],isNaN(t)||n.hidden||(a+=Math.abs(t))}),a},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){for(var e,n,a=0,r=this.index,i=t.length,s=0;s<i;s++)a=(n=t[s]._chart?t[s]._chart.config.data.datasets[r].hoverBorderWidth:0)>(a=(e=t[s]._model?t[s]._model.borderWidth:0)>a?e:a)?n:a;return a}})}},Xg1U:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("CcnG"),r=n("eajB"),i=(n("Ip0R"),a["\u0275crt"]({encapsulation:0,styles:[".tooltip[_nghost-%COMP%] {\n display: block;\n pointer-events: none;\n }\n .bs3.tooltip.top[_nghost-%COMP%] > .arrow[_ngcontent-%COMP%] {\n margin-left: -2px;\n }\n .bs3.tooltip.bottom[_nghost-%COMP%] {\n margin-top: 0px;\n }\n .bs3.bs-tooltip-left[_nghost-%COMP%], .bs3.bs-tooltip-right[_nghost-%COMP%]{\n margin: 0px;\n }\n .bs3.bs-tooltip-right[_nghost-%COMP%] .arrow[_ngcontent-%COMP%], .bs3.bs-tooltip-left[_nghost-%COMP%] .arrow[_ngcontent-%COMP%] {\n margin: .3rem 0;\n }"],data:{}}));function s(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,0,"div",[["class","tooltip-arrow arrow"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"div",[["class","tooltip-inner"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],null,null)}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"bs-tooltip-container",[["role","tooltip"]],[[8,"className",0],[2,"show",null],[2,"bs3",null],[1,"id",0]],null,null,s,i)),a["\u0275did"](1,4243456,null,0,r.b,[r.a],null,null)],null,function(t,e){t(e,0,0,"tooltip in tooltip-"+a["\u0275nov"](e,1).placement+" bs-tooltip-"+a["\u0275nov"](e,1).placement+" "+a["\u0275nov"](e,1).placement+" "+a["\u0275nov"](e,1).containerClass,!a["\u0275nov"](e,1).isBs3,a["\u0275nov"](e,1).isBs3,a["\u0275nov"](e,1).id)})}var u=a["\u0275ccf"]("bs-tooltip-container",r.b,o,{},{},["*"])},XlPw:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("6blF");function r(t,e){return new a.a(e?function(n){return e.schedule(i,0,{error:t,subscriber:n})}:function(e){return e.error(t)})}function i(t){t.subscriber.error(t.error)}},Y0Co:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("Lwhh"),o=n("8iEZ"),u=n("L5sC");n("BARL"),e.DataTableColumnDirective=function(){function t(t){this.columnChangesService=t,this.isFirstChange=!0}return t.prototype.ngOnChanges=function(){this.isFirstChange?this.isFirstChange=!1:this.columnChangesService.onInputChange()},a([i.Input(),r("design:type",String)],t.prototype,"name",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"prop",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"frozenLeft",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"frozenRight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"flexGrow",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"resizeable",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"comparator",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"pipe",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"sortable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"draggable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"canAutoResize",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"minWidth",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"width",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"maxWidth",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"checkboxable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"headerCheckboxable",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"headerClass",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"cellClass",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"isTreeColumn",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"treeLevelIndent",void 0),a([i.Input(),r("design:type",Function)],t.prototype,"summaryFunc",void 0),a([i.Input(),r("design:type",i.TemplateRef)],t.prototype,"summaryTemplate",void 0),a([i.Input(),i.ContentChild(o.DataTableColumnCellDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"cellTemplate",void 0),a([i.Input(),i.ContentChild(s.DataTableColumnHeaderDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"headerTemplate",void 0),a([i.Input(),i.ContentChild(u.DataTableColumnCellTreeToggle,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"treeToggleTemplate",void 0),a([i.Directive({selector:"ngx-datatable-column"})],t)}()},Y4Rb:function(t,e,n){"use strict";var a=n("RDha"),r=n("cdu6"),i=n("tjFV"),s=n("g8vO");t.exports=function(t){var e={position:"left",ticks:{callback:s.formatters.logarithmic}},n=r.extend({determineDataLimits:function(){var t=this,e=t.options,n=t.chart,r=n.data.datasets,i=t.isHorizontal();function s(e){return i?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null,t.minNotZero=null;var o=e.stacked;if(void 0===o&&a.each(r,function(t,e){if(!o){var a=n.getDatasetMeta(e);n.isDatasetVisible(e)&&s(a)&&void 0!==a.stack&&(o=!0)}}),e.stacked||o){var u={};a.each(r,function(r,i){var o=n.getDatasetMeta(i),c=[o.type,void 0===e.stacked&&void 0===o.stack?i:"",o.stack].join(".");n.isDatasetVisible(i)&&s(o)&&(void 0===u[c]&&(u[c]=[]),a.each(r.data,function(e,n){var a=u[c],r=+t.getRightValue(e);isNaN(r)||o.data[n].hidden||r<0||(a[n]=a[n]||0,a[n]+=r)}))}),a.each(u,function(e){if(e.length>0){var n=a.min(e),r=a.max(e);t.min=null===t.min?n:Math.min(t.min,n),t.max=null===t.max?r:Math.max(t.max,r)}})}else a.each(r,function(e,r){var i=n.getDatasetMeta(r);n.isDatasetVisible(r)&&s(i)&&a.each(e.data,function(e,n){var a=+t.getRightValue(e);isNaN(a)||i.data[n].hidden||a<0||(null===t.min?t.min=a:a<t.min&&(t.min=a),null===t.max?t.max=a:a>t.max&&(t.max=a),0!==a&&(null===t.minNotZero||a<t.minNotZero)&&(t.minNotZero=a))})});this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks,n=a.valueOrDefault;t.min=n(e.min,t.min),t.max=n(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(a.log10(t.min))-1),t.max=Math.pow(10,Math.floor(a.log10(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(a.log10(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(a.log10(t.min))+1):10),null===t.minNotZero&&(t.minNotZero=t.min>0?t.min:t.max<1?Math.pow(10,Math.floor(a.log10(t.max))):1)},buildTicks:function(){var t=this,e=t.options.ticks,n=!t.isHorizontal(),r=t.ticks=function(t,e){var n,r,i=[],s=a.valueOrDefault,o=s(t.min,Math.pow(10,Math.floor(a.log10(e.min)))),u=Math.floor(a.log10(e.max)),c=Math.ceil(e.max/Math.pow(10,u));0===o?(n=Math.floor(a.log10(e.minNotZero)),r=Math.floor(e.minNotZero/Math.pow(10,n)),i.push(o),o=r*Math.pow(10,n)):(n=Math.floor(a.log10(o)),r=Math.floor(o/Math.pow(10,n)));var l=n<0?Math.pow(10,Math.abs(n)):1;do{i.push(o),10==++r&&(r=1,l=++n>=0?1:l),o=Math.round(r*Math.pow(10,n)*l)/l}while(n<u||n===u&&r<c);var d=s(t.max,o);return i.push(d),i}({min:e.min,max:e.max},t);t.max=a.max(r),t.min=a.min(r),e.reverse?(n=!n,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),n&&r.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),r.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},_getFirstTickValue:function(t){var e=Math.floor(a.log10(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},getPixelForValue:function(e){var n,r,i,s,o,u=this,c=u.options.ticks.reverse,l=a.log10,d=u._getFirstTickValue(u.minNotZero),f=0;return e=+u.getRightValue(e),c?(i=u.end,s=u.start,o=-1):(i=u.start,s=u.end,o=1),u.isHorizontal()?(n=u.width,r=c?u.right:u.left):(n=u.height,o*=-1,r=c?u.top:u.bottom),e!==i&&(0===i&&(n-=f=a.getValueOrDefault(u.options.ticks.fontSize,t.defaults.global.defaultFontSize),i=d),0!==e&&(f+=n/(l(s)-l(i))*(l(e)-l(i))),r+=o*f),r},getValueForPixel:function(e){var n,r,i,s,o=this,u=o.options.ticks.reverse,c=a.log10,l=o._getFirstTickValue(o.minNotZero);if(u?(r=o.end,i=o.start):(r=o.start,i=o.end),o.isHorizontal()?(n=o.width,s=u?o.right-e:e-o.left):(n=o.height,s=u?e-o.top:o.bottom-e),s!==r){if(0===r){var d=a.getValueOrDefault(o.options.ticks.fontSize,t.defaults.global.defaultFontSize);s-=d,n-=d,r=l}s*=c(i)-c(r),s/=n,s=Math.pow(10,c(r)+s)}return s}});i.registerScaleType("logarithmic",n,e)}},YAQW:function(t,e,n){"use strict";n.d(e,"a",function(){return r}),n.d(e,"b",function(){return o}),n.d(e,"c",function(){return u}),n.d(e,"d",function(){return s}),n.d(e,"e",function(){return i});var a=n("CcnG"),r=function(){function t(t){this.viewRef=t}return Object.defineProperty(t.prototype,"ngTransclude",{get:function(){return this._ngTransclude},set:function(t){this._ngTransclude=t,t&&this.viewRef.createEmbeddedView(t)},enumerable:!0,configurable:!0}),t}(),i=function(){return function(){this.type="tabs"}}(),s=function(){function t(t,e,n){this.renderer=e,this.elementRef=n,this.clazz=!0,this.tabs=[],this.classMap={},Object.assign(this,t)}return Object.defineProperty(t.prototype,"vertical",{get:function(){return this._vertical},set:function(t){this._vertical=t,this.setClassMap()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"justified",{get:function(){return this._justified},set:function(t){this._justified=t,this.setClassMap()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"type",{get:function(){return this._type},set:function(t){this._type=t,this.setClassMap()},enumerable:!0,configurable:!0}),t.prototype.ngOnDestroy=function(){this.isDestroyed=!0},t.prototype.addTab=function(t){this.tabs.push(t),t.active=1===this.tabs.length&&void 0===t.active},t.prototype.removeTab=function(t,e){void 0===e&&(e={reselect:!0,emit:!0});var n=this.tabs.indexOf(t);if(-1!==n&&!this.isDestroyed){if(e.reselect&&t.active&&this.hasAvailableTabs(n)){var a=this.getClosestTabIndex(n);this.tabs[a].active=!0}e.emit&&t.removed.emit(t),this.tabs.splice(n,1),t.elementRef.nativeElement.parentNode&&this.renderer.removeChild(t.elementRef.nativeElement.parentNode,t.elementRef.nativeElement)}},t.prototype.keyNavActions=function(t,e){var n=Array.from(this.elementRef.nativeElement.querySelectorAll(".nav-link"));if(13===t.keyCode||"Enter"===t.key||32===t.keyCode||"Space"===t.key)return t.preventDefault(),void n[e%n.length].click();if(39!==t.keyCode&&"RightArrow"!==t.key)if(37!==t.keyCode&&"LeftArrow"!==t.key)if(36!==t.keyCode&&"Home"!==t.key)if(35!==t.keyCode&&"End"!==t.key){if((46===t.keyCode||"Delete"===t.key)&&this.tabs[e].removable){if(this.removeTab(this.tabs[e]),n[e+1])return void n[(e+1)%n.length].focus();n[n.length-1]&&n[0].focus()}}else{t.preventDefault();var a=void 0;s=1,o=e;do{o-s<0?(a=n[o=n.length-1],s=0):a=n[o-s],s++}while(a.classList.contains("disabled"));a.focus()}else{t.preventDefault();var r=void 0;s=0;do{r=n[s%n.length],s++}while(r.classList.contains("disabled"));r.focus()}else{var i=void 0,s=1,o=e;do{o-s<0?(i=n[o=n.length-1],s=0):i=n[o-s],s++}while(i.classList.contains("disabled"));i.focus()}else{var u=void 0;s=1;do{u=n[(e+s)%n.length],s++}while(u.classList.contains("disabled"));u.focus()}},t.prototype.getClosestTabIndex=function(t){var e=this.tabs.length;if(!e)return-1;for(var n=1;n<=e;n+=1){var a=t-n,r=t+n;if(this.tabs[a]&&!this.tabs[a].disabled)return a;if(this.tabs[r]&&!this.tabs[r].disabled)return r}return-1},t.prototype.hasAvailableTabs=function(t){var e=this.tabs.length;if(!e)return!1;for(var n=0;n<e;n+=1)if(!this.tabs[n].disabled&&n!==t)return!0;return!1},t.prototype.setClassMap=function(){var t;this.classMap=((t={"nav-stacked":this.vertical,"flex-column":this.vertical,"nav-justified":this.justified})["nav-"+this.type]=!0,t)},t}(),o=function(){function t(t,e,n){this.elementRef=e,this.renderer=n,this.selectTab=new a.EventEmitter,this.deselect=new a.EventEmitter,this.removed=new a.EventEmitter,this.addClass=!0,this.tabset=t,this.tabset.addTab(this)}return Object.defineProperty(t.prototype,"customClass",{get:function(){return this._customClass},set:function(t){var e=this;this.customClass&&this.customClass.split(" ").forEach(function(t){e.renderer.removeClass(e.elementRef.nativeElement,t)}),this._customClass=t?t.trim():null,this.customClass&&this.customClass.split(" ").forEach(function(t){e.renderer.addClass(e.elementRef.nativeElement,t)})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"active",{get:function(){return this._active},set:function(t){var e=this;this._active!==t&&(this.disabled&&t||!t?this._active&&!t&&(this.deselect.emit(this),this._active=t):(this._active=t,this.selectTab.emit(this),this.tabset.tabs.forEach(function(t){t!==e&&(t.active=!1)})))},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.removable=this.removable},t.prototype.ngOnDestroy=function(){this.tabset.removeTab(this,{reselect:!1,emit:!1})},t}(),u=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[i]}},t}()},YRex:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ug-cn",{months:"\u064a\u0627\u0646\u06cb\u0627\u0631_\u0641\u06d0\u06cb\u0631\u0627\u0644_\u0645\u0627\u0631\u062a_\u0626\u0627\u067e\u0631\u06d0\u0644_\u0645\u0627\u064a_\u0626\u0649\u064a\u06c7\u0646_\u0626\u0649\u064a\u06c7\u0644_\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a_\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631_\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631_\u0646\u0648\u064a\u0627\u0628\u0649\u0631_\u062f\u06d0\u0643\u0627\u0628\u0649\u0631".split("_"),monthsShort:"\u064a\u0627\u0646\u06cb\u0627\u0631_\u0641\u06d0\u06cb\u0631\u0627\u0644_\u0645\u0627\u0631\u062a_\u0626\u0627\u067e\u0631\u06d0\u0644_\u0645\u0627\u064a_\u0626\u0649\u064a\u06c7\u0646_\u0626\u0649\u064a\u06c7\u0644_\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a_\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631_\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631_\u0646\u0648\u064a\u0627\u0628\u0649\u0631_\u062f\u06d0\u0643\u0627\u0628\u0649\u0631".split("_"),weekdays:"\u064a\u06d5\u0643\u0634\u06d5\u0646\u0628\u06d5_\u062f\u06c8\u0634\u06d5\u0646\u0628\u06d5_\u0633\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5_\u0686\u0627\u0631\u0634\u06d5\u0646\u0628\u06d5_\u067e\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5_\u062c\u06c8\u0645\u06d5_\u0634\u06d5\u0646\u0628\u06d5".split("_"),weekdaysShort:"\u064a\u06d5_\u062f\u06c8_\u0633\u06d5_\u0686\u0627_\u067e\u06d5_\u062c\u06c8_\u0634\u06d5".split("_"),weekdaysMin:"\u064a\u06d5_\u062f\u06c8_\u0633\u06d5_\u0686\u0627_\u067e\u06d5_\u062c\u06c8_\u0634\u06d5".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY-\u064a\u0649\u0644\u0649M-\u0626\u0627\u064a\u0646\u0649\u06adD-\u0643\u06c8\u0646\u0649",LLL:"YYYY-\u064a\u0649\u0644\u0649M-\u0626\u0627\u064a\u0646\u0649\u06adD-\u0643\u06c8\u0646\u0649\u060c HH:mm",LLLL:"dddd\u060c YYYY-\u064a\u0649\u0644\u0649M-\u0626\u0627\u064a\u0646\u0649\u06adD-\u0643\u06c8\u0646\u0649\u060c HH:mm"},meridiemParse:/\u064a\u06d0\u0631\u0649\u0645 \u0643\u06d0\u0686\u06d5|\u0633\u06d5\u06be\u06d5\u0631|\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646|\u0686\u06c8\u0634|\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646|\u0643\u06d5\u0686/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u064a\u06d0\u0631\u0649\u0645 \u0643\u06d0\u0686\u06d5"===e||"\u0633\u06d5\u06be\u06d5\u0631"===e||"\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646"===e?t:"\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646"===e||"\u0643\u06d5\u0686"===e?t+12:t>=11?t:t+12},meridiem:function(t,e,n){var a=100*t+e;return a<600?"\u064a\u06d0\u0631\u0649\u0645 \u0643\u06d0\u0686\u06d5":a<900?"\u0633\u06d5\u06be\u06d5\u0631":a<1130?"\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646":a<1230?"\u0686\u06c8\u0634":a<1800?"\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646":"\u0643\u06d5\u0686"},calendar:{sameDay:"[\u0628\u06c8\u06af\u06c8\u0646 \u0633\u0627\u0626\u06d5\u062a] LT",nextDay:"[\u0626\u06d5\u062a\u06d5 \u0633\u0627\u0626\u06d5\u062a] LT",nextWeek:"[\u0643\u06d0\u0644\u06d5\u0631\u0643\u0649] dddd [\u0633\u0627\u0626\u06d5\u062a] LT",lastDay:"[\u062a\u06c6\u0646\u06c8\u06af\u06c8\u0646] LT",lastWeek:"[\u0626\u0627\u0644\u062f\u0649\u0646\u0642\u0649] dddd [\u0633\u0627\u0626\u06d5\u062a] LT",sameElse:"L"},relativeTime:{future:"%s \u0643\u06d0\u064a\u0649\u0646",past:"%s \u0628\u06c7\u0631\u06c7\u0646",s:"\u0646\u06d5\u0686\u0686\u06d5 \u0633\u06d0\u0643\u0648\u0646\u062a",ss:"%d \u0633\u06d0\u0643\u0648\u0646\u062a",m:"\u0628\u0649\u0631 \u0645\u0649\u0646\u06c7\u062a",mm:"%d \u0645\u0649\u0646\u06c7\u062a",h:"\u0628\u0649\u0631 \u0633\u0627\u0626\u06d5\u062a",hh:"%d \u0633\u0627\u0626\u06d5\u062a",d:"\u0628\u0649\u0631 \u0643\u06c8\u0646",dd:"%d \u0643\u06c8\u0646",M:"\u0628\u0649\u0631 \u0626\u0627\u064a",MM:"%d \u0626\u0627\u064a",y:"\u0628\u0649\u0631 \u064a\u0649\u0644",yy:"%d \u064a\u0649\u0644"},dayOfMonthOrdinalParse:/\d{1,2}(-\u0643\u06c8\u0646\u0649|-\u0626\u0627\u064a|-\u06be\u06d5\u067e\u062a\u06d5)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"-\u0643\u06c8\u0646\u0649";case"w":case"W":return t+"-\u06be\u06d5\u067e\u062a\u06d5";default:return t}},preparse:function(t){return t.replace(/\u060c/g,",")},postformat:function(t){return t.replace(/,/g,"\u060c")},week:{dow:1,doy:7}})}()},YSsK:function(t,e,n){"use strict";var a=n("CDJp"),r=n("RDha"),i=n("tjFV"),s=n("g8vO");t.exports=function(t){var e={position:"left",ticks:{callback:s.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){var t=this,e=t.options,n=t.chart,a=n.data.datasets,i=t.isHorizontal();function s(e){return i?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null;var o=e.stacked;if(void 0===o&&r.each(a,function(t,e){if(!o){var a=n.getDatasetMeta(e);n.isDatasetVisible(e)&&s(a)&&void 0!==a.stack&&(o=!0)}}),e.stacked||o){var u={};r.each(a,function(a,i){var o=n.getDatasetMeta(i),c=[o.type,void 0===e.stacked&&void 0===o.stack?i:"",o.stack].join(".");void 0===u[c]&&(u[c]={positiveValues:[],negativeValues:[]});var l=u[c].positiveValues,d=u[c].negativeValues;n.isDatasetVisible(i)&&s(o)&&r.each(a.data,function(n,a){var r=+t.getRightValue(n);isNaN(r)||o.data[a].hidden||(l[a]=l[a]||0,d[a]=d[a]||0,e.relativePoints?l[a]=100:r<0?d[a]+=r:l[a]+=r)})}),r.each(u,function(e){var n=e.positiveValues.concat(e.negativeValues),a=r.min(n),i=r.max(n);t.min=null===t.min?a:Math.min(t.min,a),t.max=null===t.max?i:Math.max(t.max,i)})}else r.each(a,function(e,a){var i=n.getDatasetMeta(a);n.isDatasetVisible(a)&&s(i)&&r.each(e.data,function(e,n){var a=+t.getRightValue(e);isNaN(a)||i.data[n].hidden||(null===t.min?t.min=a:a<t.min&&(t.min=a),null===t.max?t.max=a:a>t.max&&(t.max=a))})});t.min=isFinite(t.min)&&!isNaN(t.min)?t.min:0,t.max=isFinite(t.max)&&!isNaN(t.max)?t.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var n=r.valueOrDefault(e.fontSize,a.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*n)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this,n=e.start,a=+e.getRightValue(t),r=e.end-n;return e.isHorizontal()?e.left+e.width/r*(a-n):e.bottom-e.height/r*(a-n)},getValueForPixel:function(t){var e=this,n=e.isHorizontal();return e.start+(n?t-e.left:e.bottom-t)/(n?e.width:e.height)*(e.end-e.start)},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});i.registerScaleType("linear",n,e)}},YVFZ:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("5tze"),o=n("qwkt");n("czA5"),e.DataTableBodyCellComponent=function(){function t(t,e){this.cd=e,this.activate=new i.EventEmitter,this.treeAction=new i.EventEmitter,this.isFocused=!1,this.onCheckboxChangeFn=this.onCheckboxChange.bind(this),this.activateFn=this.activate.emit.bind(this.activate),this.cellContext={onCheckboxChangeFn:this.onCheckboxChangeFn,activateFn:this.activateFn,row:this.row,group:this.group,value:this.value,column:this.column,rowHeight:this.rowHeight,isSelected:this.isSelected,rowIndex:this.rowIndex,treeStatus:this.treeStatus,onTreeAction:this.onTreeAction.bind(this)},this._element=t.nativeElement}return Object.defineProperty(t.prototype,"group",{get:function(){return this._group},set:function(t){this._group=t,this.cellContext.group=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowHeight",{get:function(){return this._rowHeight},set:function(t){this._rowHeight=t,this.cellContext.rowHeight=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSelected",{get:function(){return this._isSelected},set:function(t){this._isSelected=t,this.cellContext.isSelected=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"expanded",{get:function(){return this._expanded},set:function(t){this._expanded=t,this.cellContext.expanded=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowIndex",{get:function(){return this._rowIndex},set:function(t){this._rowIndex=t,this.cellContext.rowIndex=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"column",{get:function(){return this._column},set:function(t){this._column=t,this.cellContext.column=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"row",{get:function(){return this._row},set:function(t){this._row=t,this.cellContext.row=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"sorts",{get:function(){return this._sorts},set:function(t){this._sorts=t,this.calcSortDir=this.calcSortDir(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"treeStatus",{get:function(){return this._treeStatus},set:function(t){this._treeStatus="collapsed"!==t&&"expanded"!==t&&"loading"!==t&&"disabled"!==t?"collapsed":t,this.cellContext.treeStatus=this._treeStatus,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnCssClasses",{get:function(){var t="datatable-body-cell";if(this.column.cellClass)if("string"==typeof this.column.cellClass)t+=" "+this.column.cellClass;else if("function"==typeof this.column.cellClass){var e=this.column.cellClass({row:this.row,group:this.group,column:this.column,value:this.value,rowHeight:this.rowHeight});if("string"==typeof e)t+=e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}return this.sortDir||(t+=" sort-active"),this.isFocused&&(t+=" active"),this.sortDir===o.SortDirection.asc&&(t+=" sort-asc"),this.sortDir===o.SortDirection.desc&&(t+=" sort-desc"),t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"width",{get:function(){return this.column.width},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"minWidth",{get:function(){return this.column.minWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"maxWidth",{get:function(){return this.column.maxWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"height",{get:function(){var t=this.rowHeight;return isNaN(t)?t:t+"px"},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this.checkValueUpdates()},t.prototype.ngOnDestroy=function(){this.cellTemplate&&this.cellTemplate.clear()},t.prototype.checkValueUpdates=function(){var t="";if(this.row&&this.column){var e=this.column.$$valueGetter(this.row,this.column.prop),n=this.column.pipe;n?t=n.transform(e):void 0!==t&&(t=e)}else t="";this.value!==t&&(this.value=t,this.cellContext.value=t,this.sanitizedValue=null!=t?this.stripHtml(t):t,this.cd.markForCheck())},t.prototype.onFocus=function(){this.isFocused=!0},t.prototype.onBlur=function(){this.isFocused=!1},t.prototype.onClick=function(t){this.activate.emit({type:"click",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element})},t.prototype.onDblClick=function(t){this.activate.emit({type:"dblclick",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element})},t.prototype.onKeyDown=function(t){var e=t.keyCode;(e===s.Keys.return||e===s.Keys.down||e===s.Keys.up||e===s.Keys.left||e===s.Keys.right)&&t.target===this._element&&(t.preventDefault(),t.stopPropagation(),this.activate.emit({type:"keydown",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element}))},t.prototype.onCheckboxChange=function(t){this.activate.emit({type:"checkbox",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element,treeStatus:"collapsed"})},t.prototype.calcSortDir=function(t){var e=this;if(t){var n=t.find(function(t){return t.prop===e.column.prop});return n?n.dir:void 0}},t.prototype.stripHtml=function(t){return t.replace?t.replace(/<\/?[^>]+(>|$)/g,""):t},t.prototype.onTreeAction=function(){this.treeAction.emit(this.row)},t.prototype.calcLeftMargin=function(t,e){return t.isTreeColumn?e.level*(null!=t.treeLevelIndent?t.treeLevelIndent:50):0},a([i.Input(),r("design:type",Function)],t.prototype,"displayCheck",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"group",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowHeight",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"isSelected",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"expanded",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowIndex",null),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"column",null),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"row",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"sorts",null),a([i.Input(),r("design:type",String),r("design:paramtypes",[String])],t.prototype,"treeStatus",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"treeAction",void 0),a([i.ViewChild("cellTemplate",{read:i.ViewContainerRef}),r("design:type",i.ViewContainerRef)],t.prototype,"cellTemplate",void 0),a([i.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"columnCssClasses",null),a([i.HostBinding("style.width.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"width",null),a([i.HostBinding("style.minWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"minWidth",null),a([i.HostBinding("style.maxWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"maxWidth",null),a([i.HostBinding("style.height"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"height",null),a([i.HostListener("focus"),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",void 0)],t.prototype,"onFocus",null),a([i.HostListener("blur"),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",void 0)],t.prototype,"onBlur",null),a([i.HostListener("click",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onClick",null),a([i.HostListener("dblclick",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onDblClick",null),a([i.HostListener("keydown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onKeyDown",null),a([i.Component({selector:"datatable-body-cell",changeDetection:i.ChangeDetectionStrategy.OnPush,template:'\n <div class="datatable-body-cell-label"\n [style.margin-left.px]="calcLeftMargin(column, row)">\n <label\n *ngIf="column.checkboxable && (!displayCheck || displayCheck(row, column, value))"\n class="datatable-checkbox">\n <input\n type="checkbox"\n [checked]="isSelected"\n (click)="onCheckboxChange($event)"\n />\n </label>\n <ng-container *ngIf="column.isTreeColumn">\n <button *ngIf="!column.treeToggleTemplate"\n class="datatable-tree-button"\n [disabled]="treeStatus===\'disabled\'"\n (click)="onTreeAction()">\n <span>\n <i *ngIf="treeStatus===\'loading\'"\n class="icon datatable-icon-collapse"></i>\n <i *ngIf="treeStatus===\'collapsed\'"\n class="icon datatable-icon-up"></i>\n <i *ngIf="treeStatus===\'expanded\' ||\n treeStatus===\'disabled\'"\n class="icon datatable-icon-down"></i>\n </span>\n </button>\n <ng-template *ngIf="column.treeToggleTemplate"\n [ngTemplateOutlet]="column.treeToggleTemplate"\n [ngTemplateOutletContext]="{ cellContext: cellContext }">\n </ng-template>\n </ng-container>\n\n <span\n *ngIf="!column.cellTemplate"\n [title]="sanitizedValue"\n [innerHTML]="value">\n </span>\n <ng-template #cellTemplate\n *ngIf="column.cellTemplate"\n [ngTemplateOutlet]="column.cellTemplate"\n [ngTemplateOutletContext]="cellContext">\n </ng-template>\n </div>\n '})],t)}()},YuTi:function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},Z21x:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("sne2");var a=function(){return function(t,e){var n=this;this.location=t,this.actionLabels=e,this.name=this.actionLabels.CANCEL,this.back=function(){return n.location.back()}}}()},Z4QM:function(t,e,n){!function(t){"use strict";var e=["\u062c\u0646\u0648\u0631\u064a","\u0641\u064a\u0628\u0631\u0648\u0631\u064a","\u0645\u0627\u0631\u0686","\u0627\u067e\u0631\u064a\u0644","\u0645\u0626\u064a","\u062c\u0648\u0646","\u062c\u0648\u0644\u0627\u0621\u0650","\u0622\u06af\u0633\u067d","\u0633\u064a\u067e\u067d\u0645\u0628\u0631","\u0622\u06aa\u067d\u0648\u0628\u0631","\u0646\u0648\u0645\u0628\u0631","\u068a\u0633\u0645\u0628\u0631"],a=["\u0622\u0686\u0631","\u0633\u0648\u0645\u0631","\u0627\u06b1\u0627\u0631\u0648","\u0627\u0631\u0628\u0639","\u062e\u0645\u064a\u0633","\u062c\u0645\u0639","\u0687\u0646\u0687\u0631"];n("wd/R").defineLocale("sd",{months:e,monthsShort:e,weekdays:a,weekdaysShort:a,weekdaysMin:a,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd\u060c D MMMM YYYY HH:mm"},meridiemParse:/\u0635\u0628\u062d|\u0634\u0627\u0645/,isPM:function(t){return"\u0634\u0627\u0645"===t},meridiem:function(t,e,n){return t<12?"\u0635\u0628\u062d":"\u0634\u0627\u0645"},calendar:{sameDay:"[\u0627\u0684] LT",nextDay:"[\u0633\u0680\u0627\u06bb\u064a] LT",nextWeek:"dddd [\u0627\u06b3\u064a\u0646 \u0647\u0641\u062a\u064a \u062a\u064a] LT",lastDay:"[\u06aa\u0627\u0644\u0647\u0647] LT",lastWeek:"[\u06af\u0632\u0631\u064a\u0644 \u0647\u0641\u062a\u064a] dddd [\u062a\u064a] LT",sameElse:"L"},relativeTime:{future:"%s \u067e\u0648\u0621",past:"%s \u0627\u06b3",s:"\u0686\u0646\u062f \u0633\u064a\u06aa\u0646\u068a",ss:"%d \u0633\u064a\u06aa\u0646\u068a",m:"\u0647\u06aa \u0645\u0646\u067d",mm:"%d \u0645\u0646\u067d",h:"\u0647\u06aa \u06aa\u0644\u0627\u06aa",hh:"%d \u06aa\u0644\u0627\u06aa",d:"\u0647\u06aa \u068f\u064a\u0646\u0647\u0646",dd:"%d \u068f\u064a\u0646\u0647\u0646",M:"\u0647\u06aa \u0645\u0647\u064a\u0646\u0648",MM:"%d \u0645\u0647\u064a\u0646\u0627",y:"\u0647\u06aa \u0633\u0627\u0644",yy:"%d \u0633\u0627\u0644"},preparse:function(t){return t.replace(/\u060c/g,",")},postformat:function(t){return t.replace(/,/g,"\u060c")},week:{dow:1,doy:4}})}()},ZAMP:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(t,e){return 12===t&&(t=0),"pagi"===e?t:"tengahari"===e?t>=11?t:t+12:"petang"===e||"malam"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"pagi":t<15?"tengahari":t<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}()},ZANz:function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),a._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),t.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:r.Rectangle,initialize:function(){var e;t.DatasetController.prototype.initialize.apply(this,arguments),(e=this.getMeta()).stack=this.getDataset().stack,e.bar=!0},update:function(t){var e,n,a=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,n=a.length;e<n;++e)this.updateElement(a[e],e,t)},updateElement:function(t,e,n){var a=this,r=a.chart,s=a.getMeta(),o=a.getDataset(),u=t.custom||{},c=r.options.elements.rectangle;t._xScale=a.getScaleForId(s.xAxisID),t._yScale=a.getScaleForId(s.yAxisID),t._datasetIndex=a.index,t._index=e,t._model={datasetLabel:o.label,label:r.data.labels[e],borderSkipped:u.borderSkipped?u.borderSkipped:c.borderSkipped,backgroundColor:u.backgroundColor?u.backgroundColor:i.valueAtIndexOrDefault(o.backgroundColor,e,c.backgroundColor),borderColor:u.borderColor?u.borderColor:i.valueAtIndexOrDefault(o.borderColor,e,c.borderColor),borderWidth:u.borderWidth?u.borderWidth:i.valueAtIndexOrDefault(o.borderWidth,e,c.borderWidth)},a.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var a=this,r=t._model,i=a.getValueScale(),s=i.getBasePixel(),o=i.isHorizontal(),u=a._ruler||a.getRuler(),c=a.calculateBarValuePixels(a.index,e),l=a.calculateBarIndexPixels(a.index,e,u);r.horizontal=o,r.base=n?s:c.base,r.x=o?n?s:c.head:l.center,r.y=o?l.center:n?s:c.head,r.height=o?l.size:void 0,r.width=o?void 0:l.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},_getStacks:function(t){var e,n,a=this.chart,r=this.getIndexScale().options.stacked,i=void 0===t?a.data.datasets.length:t+1,s=[];for(e=0;e<i;++e)(n=a.getDatasetMeta(e)).bar&&a.isDatasetVisible(e)&&(!1===r||!0===r&&-1===s.indexOf(n.stack)||void 0===r&&(void 0===n.stack||-1===s.indexOf(n.stack)))&&s.push(n.stack);return s},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var n=this._getStacks(t),a=void 0!==e?n.indexOf(e):-1;return-1===a?n.length-1:a},getRuler:function(){var t,e,n=this.getIndexScale(),a=this.getStackCount(),r=this.index,s=n.isHorizontal(),o=s?n.left:n.top,u=o+(s?n.width:n.height),c=[];for(t=0,e=this.getMeta().data.length;t<e;++t)c.push(n.getPixelForValue(null,t,r));return{min:i.isNullOrUndef(n.options.barThickness)?function(t,e){var n,a,r,i,s=t.isHorizontal()?t.width:t.height,o=t.getTicks();for(r=1,i=e.length;r<i;++r)s=Math.min(s,e[r]-e[r-1]);for(r=0,i=o.length;r<i;++r)a=t.getPixelForTick(r),s=r>0?Math.min(s,a-n):s,n=a;return s}(n,c):-1,pixels:c,start:o,end:u,stackCount:a,scale:n}},calculateBarValuePixels:function(t,e){var n,a,r,i,s,o,u=this.chart,c=this.getMeta(),l=this.getValueScale(),d=u.data.datasets,f=l.getRightValue(d[t].data[e]),p=l.options.stacked,h=c.stack,g=0;if(p||void 0===p&&void 0!==h)for(n=0;n<t;++n)(a=u.getDatasetMeta(n)).bar&&a.stack===h&&a.controller.getValueScaleId()===l.id&&u.isDatasetVisible(n)&&(r=l.getRightValue(d[n].data[e]),(f<0&&r<0||f>=0&&r>0)&&(g+=r));return i=l.getPixelForValue(g),{size:o=((s=l.getPixelForValue(g+f))-i)/2,base:i,head:s,center:s+o/2}},calculateBarIndexPixels:function(t,e,n){var a=n.scale.options,r="flex"===a.barThickness?function(t,e,n){var a=e.pixels,r=a[t],i=t>0?a[t-1]:null,s=t<a.length-1?a[t+1]:null,o=n.categoryPercentage;return null===i&&(i=r-(null===s?e.end-r:s-r)),null===s&&(s=r+r-i),{chunk:(s-i)/2*o/e.stackCount,ratio:n.barPercentage,start:r-(r-i)/2*o}}(e,n,a):function(t,e,n){var a,r,s=n.barThickness,o=e.stackCount,u=e.pixels[t];return i.isNullOrUndef(s)?(a=e.min*n.categoryPercentage,r=n.barPercentage):(a=s*o,r=1),{chunk:a/o,ratio:r,start:u-a/2}}(e,n,a),s=this.getStackIndex(t,this.getMeta().stack),o=r.start+r.chunk*s+r.chunk/2,u=Math.min(i.valueOrDefault(a.maxBarThickness,1/0),r.chunk*r.ratio);return{base:o-u/2,head:o+u/2,center:o,size:u}},draw:function(){var t=this.chart,e=this.getValueScale(),n=this.getMeta().data,a=this.getDataset(),r=n.length,s=0;for(i.canvas.clipArea(t.ctx,t.chartArea);s<r;++s)isNaN(e.getRightValue(a.data[s]))||n[s].draw();i.canvas.unclipArea(t.ctx)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},ZDA6:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("t/Na"),i=n("pL04"),s=function(){function t(t){this.http=t}return t.prototype.list=function(){return this.http.get("ui-api/scope")},t.ngInjectableDef=a.defineInjectable({factory:function(){return new t(a.inject(r.c))},token:t,providedIn:i.a}),t}()},ZEkX:function(t,e,n){"use strict";n.d(e,"a",function(){return o}),n.d(e,"b",function(){return s}),n("Mxhz");var a=n("0+/T"),r=(n("sne2"),n("mtw6")),i=n("vCyI"),s=(n("nSDx"),n("aexS"),n("9nlD"),new(n("EgGo").a)("user-management/users")),o=function(){function t(t,e,n,a,r,s,o,u){var c=this;this.userService=t,this.emptyPipe=e,this.modalService=n,this.notificationService=a,this.authStorageService=r,this.i18n=s,this.urlBuilder=o,this.actionLabels=u,this.selection=new i.a,this.permission=this.authStorageService.getPermissions().user,this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return c.urlBuilder.getCreate()},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return c.selection.first()&&c.urlBuilder.getEdit(c.selection.first().username)},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-times",click:function(){return c.deleteUserModal()},name:this.actionLabels.DELETE}]}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Username"),prop:"username",flexGrow:1},{name:this.i18n("Name"),prop:"name",flexGrow:1,pipe:this.emptyPipe},{name:this.i18n("Email"),prop:"email",flexGrow:1,pipe:this.emptyPipe},{name:this.i18n("Roles"),prop:"roles",flexGrow:1,cellTemplate:this.userRolesTpl}]},t.prototype.getUsers=function(){var t=this;this.userService.list().subscribe(function(e){t.users=e})},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.deleteUser=function(t){var e=this;this.userService.delete(t).subscribe(function(){e.getUsers(),e.modalRef.hide(),e.notificationService.show(r.a.success,e.i18n('Deleted user "{{username}}"',{username:t}))},function(){e.modalRef.content.stopLoadingSpinner()})},t.prototype.deleteUserModal=function(){var t=this,e=this.authStorageService.getUsername(),n=this.selection.first().username;e!==n?this.modalRef=this.modalService.show(a.a,{initialState:{itemDescription:"User",itemNames:[n],submitAction:function(){return t.deleteUser(n)}}}):this.notificationService.show(r.a.error,this.i18n('Failed to delete user "{{username}}"',{username:n}),this.i18n('You are currently logged in as "{{username}}".',{username:n}))},t}()},ZYCi:function(t,e,n){"use strict";n.d(e,"v",function(){return pn}),n.d(e,"C",function(){return wn}),n.d(e,"x",function(){return mn}),n.d(e,"D",function(){return Sn}),n.d(e,"E",function(){return On}),n.d(e,"z",function(){return vn}),n.d(e,"y",function(){return yn}),n.d(e,"B",function(){return Tn}),n.d(e,"w",function(){return gn}),n.d(e,"A",function(){return xn}),n.d(e,"F",function(){return dn}),n.d(e,"m",function(){return Je}),n.d(e,"o",function(){return Qe}),n.d(e,"n",function(){return en}),n.d(e,"q",function(){return rn}),n.d(e,"d",function(){return P}),n.d(e,"k",function(){return Ye}),n.d(e,"l",function(){return Xe}),n.d(e,"j",function(){return He}),n.d(e,"h",function(){return fn}),n.d(e,"i",function(){return In}),n.d(e,"p",function(){return bn}),n.d(e,"b",function(){return an}),n.d(e,"e",function(){return cn}),n.d(e,"f",function(){return un}),n.d(e,"g",function(){return on}),n.d(e,"r",function(){return ln}),n.d(e,"a",function(){return Gt}),n.d(e,"s",function(){return Ue}),n.d(e,"c",function(){return _t}),n.d(e,"t",function(){return vt}),n.d(e,"u",function(){return Z});var a=n("mrSG"),r=n("Ip0R"),i=n("CcnG"),s=n("F/XL"),o=n("0/uQ"),u=n("26FU"),c=n("6blF"),l=n("3fWJ"),d=n("dzgT"),f=n("lYZG"),p=n("K9Ia"),h=n("G5J1"),g=n("67Y/"),b=n("Txjg"),m=n("w1EH"),y=n("9Z1F"),v=n("P6uZ"),_=n("psW0"),x=n("zAZS"),T=n("15JJ"),w=n("t9fZ"),S=n("p0Sj"),O=n("dC0D"),I=n("VnD/"),C=n("Phjn"),k=n("Qgas"),N=n("xMyE"),R=n("2WpN"),A=n("Zn8D"),D=n("ZYjt"),E=function(){return function(t,e){this.id=t,this.url=e}}(),L=function(t){function e(e,n,a,r){void 0===a&&(a="imperative"),void 0===r&&(r=null);var i=t.call(this,e,n)||this;return i.navigationTrigger=a,i.restoredState=r,i}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"NavigationStart(id: "+this.id+", url: '"+this.url+"')"},e}(E),P=function(t){function e(e,n,a){var r=t.call(this,e,n)||this;return r.urlAfterRedirects=a,r}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"NavigationEnd(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"')"},e}(E),M=function(t){function e(e,n,a){var r=t.call(this,e,n)||this;return r.reason=a,r}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"NavigationCancel(id: "+this.id+", url: '"+this.url+"')"},e}(E),q=function(t){function e(e,n,a){var r=t.call(this,e,n)||this;return r.error=a,r}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"NavigationError(id: "+this.id+", url: '"+this.url+"', error: "+this.error+")"},e}(E),j=function(t){function e(e,n,a,r){var i=t.call(this,e,n)||this;return i.urlAfterRedirects=a,i.state=r,i}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"RoutesRecognized(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"', state: "+this.state+")"},e}(E),F=function(t){function e(e,n,a,r){var i=t.call(this,e,n)||this;return i.urlAfterRedirects=a,i.state=r,i}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"GuardsCheckStart(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"', state: "+this.state+")"},e}(E),z=function(t){function e(e,n,a,r,i){var s=t.call(this,e,n)||this;return s.urlAfterRedirects=a,s.state=r,s.shouldActivate=i,s}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"GuardsCheckEnd(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"', state: "+this.state+", shouldActivate: "+this.shouldActivate+")"},e}(E),G=function(t){function e(e,n,a,r){var i=t.call(this,e,n)||this;return i.urlAfterRedirects=a,i.state=r,i}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"ResolveStart(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"', state: "+this.state+")"},e}(E),Y=function(t){function e(e,n,a,r){var i=t.call(this,e,n)||this;return i.urlAfterRedirects=a,i.state=r,i}return Object(a.__extends)(e,t),e.prototype.toString=function(){return"ResolveEnd(id: "+this.id+", url: '"+this.url+"', urlAfterRedirects: '"+this.urlAfterRedirects+"', state: "+this.state+")"},e}(E),V=function(){function t(t){this.route=t}return t.prototype.toString=function(){return"RouteConfigLoadStart(path: "+this.route.path+")"},t}(),H=function(){function t(t){this.route=t}return t.prototype.toString=function(){return"RouteConfigLoadEnd(path: "+this.route.path+")"},t}(),B=function(){function t(t){this.snapshot=t}return t.prototype.toString=function(){return"ChildActivationStart(path: '"+(this.snapshot.routeConfig&&this.snapshot.routeConfig.path||"")+"')"},t}(),U=function(){function t(t){this.snapshot=t}return t.prototype.toString=function(){return"ChildActivationEnd(path: '"+(this.snapshot.routeConfig&&this.snapshot.routeConfig.path||"")+"')"},t}(),W=function(){function t(t){this.snapshot=t}return t.prototype.toString=function(){return"ActivationStart(path: '"+(this.snapshot.routeConfig&&this.snapshot.routeConfig.path||"")+"')"},t}(),K=function(){function t(t){this.snapshot=t}return t.prototype.toString=function(){return"ActivationEnd(path: '"+(this.snapshot.routeConfig&&this.snapshot.routeConfig.path||"")+"')"},t}(),$=function(){function t(t,e,n){this.routerEvent=t,this.position=e,this.anchor=n}return t.prototype.toString=function(){return"Scroll(anchor: '"+this.anchor+"', position: '"+(this.position?this.position[0]+", "+this.position[1]:null)+"')"},t}(),Z=function(){return function(){}}(),X="primary",J=function(){function t(t){this.params=t||{}}return t.prototype.has=function(t){return this.params.hasOwnProperty(t)},t.prototype.get=function(t){if(this.has(t)){var e=this.params[t];return Array.isArray(e)?e[0]:e}return null},t.prototype.getAll=function(t){if(this.has(t)){var e=this.params[t];return Array.isArray(e)?e:[e]}return[]},Object.defineProperty(t.prototype,"keys",{get:function(){return Object.keys(this.params)},enumerable:!0,configurable:!0}),t}();function Q(t){return new J(t)}var tt="ngNavigationCancelingError";function et(t){var e=Error("NavigationCancelingError: "+t);return e[tt]=!0,e}function nt(t,e,n){var a=n.path.split("/");if(a.length>t.length)return null;if("full"===n.pathMatch&&(e.hasChildren()||a.length<t.length))return null;for(var r={},i=0;i<a.length;i++){var s=a[i],o=t[i];if(s.startsWith(":"))r[s.substring(1)]=o;else if(s!==o.path)return null}return{consumed:t.slice(0,a.length),posParams:r}}var at=function(){return function(t,e){this.routes=t,this.module=e}}();function rt(t,e){void 0===e&&(e="");for(var n=0;n<t.length;n++){var a=t[n];it(a,st(e,a))}}function it(t,e){if(!t)throw new Error("\n Invalid configuration of route '"+e+"': Encountered undefined route.\n The reason might be an extra comma.\n\n Example:\n const routes: Routes = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },, << two commas\n { path: 'detail/:id', component: HeroDetailComponent }\n ];\n ");if(Array.isArray(t))throw new Error("Invalid configuration of route '"+e+"': Array cannot be specified");if(!t.component&&!t.children&&!t.loadChildren&&t.outlet&&t.outlet!==X)throw new Error("Invalid configuration of route '"+e+"': a componentless route without children or loadChildren cannot have a named outlet set");if(t.redirectTo&&t.children)throw new Error("Invalid configuration of route '"+e+"': redirectTo and children cannot be used together");if(t.redirectTo&&t.loadChildren)throw new Error("Invalid configuration of route '"+e+"': redirectTo and loadChildren cannot be used together");if(t.children&&t.loadChildren)throw new Error("Invalid configuration of route '"+e+"': children and loadChildren cannot be used together");if(t.redirectTo&&t.component)throw new Error("Invalid configuration of route '"+e+"': redirectTo and component cannot be used together");if(t.path&&t.matcher)throw new Error("Invalid configuration of route '"+e+"': path and matcher cannot be used together");if(void 0===t.redirectTo&&!t.component&&!t.children&&!t.loadChildren)throw new Error("Invalid configuration of route '"+e+"'. One of the following must be provided: component, redirectTo, children or loadChildren");if(void 0===t.path&&void 0===t.matcher)throw new Error("Invalid configuration of route '"+e+"': routes must have either a path or a matcher specified");if("string"==typeof t.path&&"/"===t.path.charAt(0))throw new Error("Invalid configuration of route '"+e+"': path cannot start with a slash");if(""===t.path&&void 0!==t.redirectTo&&void 0===t.pathMatch)throw new Error("Invalid configuration of route '{path: \""+e+'", redirectTo: "'+t.redirectTo+"\"}': please provide 'pathMatch'. The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.");if(void 0!==t.pathMatch&&"full"!==t.pathMatch&&"prefix"!==t.pathMatch)throw new Error("Invalid configuration of route '"+e+"': pathMatch can only be set to 'prefix' or 'full'");t.children&&rt(t.children,e)}function st(t,e){return e?t||e.path?t&&!e.path?t+"/":!t&&e.path?e.path:t+"/"+e.path:"":t}function ot(t){var e=t.children&&t.children.map(ot),n=e?Object(a.__assign)({},t,{children:e}):Object(a.__assign)({},t);return!n.component&&(e||n.loadChildren)&&n.outlet&&n.outlet!==X&&(n.component=Z),n}function ut(t,e){var n,a=Object.keys(t),r=Object.keys(e);if(a.length!=r.length)return!1;for(var i=0;i<a.length;i++)if(t[n=a[i]]!==e[n])return!1;return!0}function ct(t){return Array.prototype.concat.apply([],t)}function lt(t){return t.length>0?t[t.length-1]:null}function dt(t,e){for(var n in t)t.hasOwnProperty(n)&&e(t[n],n)}function ft(t){return Object(i["\u0275isObservable"])(t)?t:Object(i["\u0275isPromise"])(t)?Object(o.a)(Promise.resolve(t)):Object(s.a)(t)}function pt(t,e,n){return n?function(t,e){return ut(t,e)}(t.queryParams,e.queryParams)&&function t(e,n){if(!mt(e.segments,n.segments))return!1;if(e.numberOfChildren!==n.numberOfChildren)return!1;for(var a in n.children){if(!e.children[a])return!1;if(!t(e.children[a],n.children[a]))return!1}return!0}(t.root,e.root):function(t,e){return Object.keys(e).length<=Object.keys(t).length&&Object.keys(e).every(function(n){return e[n]===t[n]})}(t.queryParams,e.queryParams)&&function t(e,n){return function e(n,a,r){if(n.segments.length>r.length)return!!mt(s=n.segments.slice(0,r.length),r)&&!a.hasChildren();if(n.segments.length===r.length){if(!mt(n.segments,r))return!1;for(var i in a.children){if(!n.children[i])return!1;if(!t(n.children[i],a.children[i]))return!1}return!0}var s=r.slice(0,n.segments.length),o=r.slice(n.segments.length);return!!mt(n.segments,s)&&!!n.children[X]&&e(n.children[X],a,o)}(e,n,n.segments)}(t.root,e.root)}var ht=function(){function t(t,e,n){this.root=t,this.queryParams=e,this.fragment=n}return Object.defineProperty(t.prototype,"queryParamMap",{get:function(){return this._queryParamMap||(this._queryParamMap=Q(this.queryParams)),this._queryParamMap},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return xt.serialize(this)},t}(),gt=function(){function t(t,e){var n=this;this.segments=t,this.children=e,this.parent=null,dt(e,function(t,e){return t.parent=n})}return t.prototype.hasChildren=function(){return this.numberOfChildren>0},Object.defineProperty(t.prototype,"numberOfChildren",{get:function(){return Object.keys(this.children).length},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return Tt(this)},t}(),bt=function(){function t(t,e){this.path=t,this.parameters=e}return Object.defineProperty(t.prototype,"parameterMap",{get:function(){return this._parameterMap||(this._parameterMap=Q(this.parameters)),this._parameterMap},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return kt(this)},t}();function mt(t,e){return t.length===e.length&&t.every(function(t,n){return t.path===e[n].path})}function yt(t,e){var n=[];return dt(t.children,function(t,a){a===X&&(n=n.concat(e(t,a)))}),dt(t.children,function(t,a){a!==X&&(n=n.concat(e(t,a)))}),n}var vt=function(){return function(){}}(),_t=function(){function t(){}return t.prototype.parse=function(t){var e=new Et(t);return new ht(e.parseRootSegment(),e.parseQueryParams(),e.parseFragment())},t.prototype.serialize=function(t){var e,n;return"/"+function t(e,n){if(!e.hasChildren())return Tt(e);if(n){var a=e.children[X]?t(e.children[X],!1):"",r=[];return dt(e.children,function(e,n){n!==X&&r.push(n+":"+t(e,!1))}),r.length>0?a+"("+r.join("//")+")":a}var i=yt(e,function(n,a){return a===X?[t(e.children[X],!1)]:[a+":"+t(n,!1)]});return Tt(e)+"/("+i.join("//")+")"}(t.root,!0)+(e=t.queryParams,(n=Object.keys(e).map(function(t){var n=e[t];return Array.isArray(n)?n.map(function(e){return St(t)+"="+St(e)}).join("&"):St(t)+"="+St(n)})).length?"?"+n.join("&"):"")+("string"==typeof t.fragment?"#"+encodeURI(t.fragment):"")},t}(),xt=new _t;function Tt(t){return t.segments.map(function(t){return kt(t)}).join("/")}function wt(t){return encodeURIComponent(t).replace(/%40/g,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",")}function St(t){return wt(t).replace(/%3B/gi,";")}function Ot(t){return wt(t).replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/%26/gi,"&")}function It(t){return decodeURIComponent(t)}function Ct(t){return It(t.replace(/\+/g,"%20"))}function kt(t){return""+Ot(t.path)+(e=t.parameters,Object.keys(e).map(function(t){return";"+Ot(t)+"="+Ot(e[t])}).join(""));var e}var Nt=/^[^\/()?;=#]+/;function Rt(t){var e=t.match(Nt);return e?e[0]:""}var At=/^[^=?&#]+/,Dt=/^[^?&#]+/,Et=function(){function t(t){this.url=t,this.remaining=t}return t.prototype.parseRootSegment=function(){return this.consumeOptional("/"),""===this.remaining||this.peekStartsWith("?")||this.peekStartsWith("#")?new gt([],{}):new gt([],this.parseChildren())},t.prototype.parseQueryParams=function(){var t={};if(this.consumeOptional("?"))do{this.parseQueryParam(t)}while(this.consumeOptional("&"));return t},t.prototype.parseFragment=function(){return this.consumeOptional("#")?decodeURIComponent(this.remaining):null},t.prototype.parseChildren=function(){if(""===this.remaining)return{};this.consumeOptional("/");var t=[];for(this.peekStartsWith("(")||t.push(this.parseSegment());this.peekStartsWith("/")&&!this.peekStartsWith("//")&&!this.peekStartsWith("/(");)this.capture("/"),t.push(this.parseSegment());var e={};this.peekStartsWith("/(")&&(this.capture("/"),e=this.parseParens(!0));var n={};return this.peekStartsWith("(")&&(n=this.parseParens(!1)),(t.length>0||Object.keys(e).length>0)&&(n[X]=new gt(t,e)),n},t.prototype.parseSegment=function(){var t=Rt(this.remaining);if(""===t&&this.peekStartsWith(";"))throw new Error("Empty path url segment cannot have parameters: '"+this.remaining+"'.");return this.capture(t),new bt(It(t),this.parseMatrixParams())},t.prototype.parseMatrixParams=function(){for(var t={};this.consumeOptional(";");)this.parseParam(t);return t},t.prototype.parseParam=function(t){var e=Rt(this.remaining);if(e){this.capture(e);var n="";if(this.consumeOptional("=")){var a=Rt(this.remaining);a&&this.capture(n=a)}t[It(e)]=It(n)}},t.prototype.parseQueryParam=function(t){var e,n=(e=this.remaining.match(At))?e[0]:"";if(n){this.capture(n);var a="";if(this.consumeOptional("=")){var r=function(t){var e=t.match(Dt);return e?e[0]:""}(this.remaining);r&&this.capture(a=r)}var i=Ct(n),s=Ct(a);if(t.hasOwnProperty(i)){var o=t[i];Array.isArray(o)||(t[i]=o=[o]),o.push(s)}else t[i]=s}},t.prototype.parseParens=function(t){var e={};for(this.capture("(");!this.consumeOptional(")")&&this.remaining.length>0;){var n=Rt(this.remaining),a=this.remaining[n.length];if("/"!==a&&")"!==a&&";"!==a)throw new Error("Cannot parse url '"+this.url+"'");var r=void 0;n.indexOf(":")>-1?(r=n.substr(0,n.indexOf(":")),this.capture(r),this.capture(":")):t&&(r=X);var i=this.parseChildren();e[r]=1===Object.keys(i).length?i[X]:new gt([],i),this.consumeOptional("//")}return e},t.prototype.peekStartsWith=function(t){return this.remaining.startsWith(t)},t.prototype.consumeOptional=function(t){return!!this.peekStartsWith(t)&&(this.remaining=this.remaining.substring(t.length),!0)},t.prototype.capture=function(t){if(!this.consumeOptional(t))throw new Error('Expected "'+t+'".')},t}(),Lt=function(){function t(t){this._root=t}return Object.defineProperty(t.prototype,"root",{get:function(){return this._root.value},enumerable:!0,configurable:!0}),t.prototype.parent=function(t){var e=this.pathFromRoot(t);return e.length>1?e[e.length-2]:null},t.prototype.children=function(t){var e=Pt(t,this._root);return e?e.children.map(function(t){return t.value}):[]},t.prototype.firstChild=function(t){var e=Pt(t,this._root);return e&&e.children.length>0?e.children[0].value:null},t.prototype.siblings=function(t){var e=Mt(t,this._root);return e.length<2?[]:e[e.length-2].children.map(function(t){return t.value}).filter(function(e){return e!==t})},t.prototype.pathFromRoot=function(t){return Mt(t,this._root).map(function(t){return t.value})},t}();function Pt(t,e){var n,r;if(t===e.value)return e;try{for(var i=Object(a.__values)(e.children),s=i.next();!s.done;s=i.next()){var o=Pt(t,s.value);if(o)return o}}catch(u){n={error:u}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(n)throw n.error}}return null}function Mt(t,e){var n,r;if(t===e.value)return[e];try{for(var i=Object(a.__values)(e.children),s=i.next();!s.done;s=i.next()){var o=Mt(t,s.value);if(o.length)return o.unshift(e),o}}catch(u){n={error:u}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(n)throw n.error}}return[]}var qt=function(){function t(t,e){this.value=t,this.children=e}return t.prototype.toString=function(){return"TreeNode("+this.value+")"},t}();function jt(t){var e={};return t&&t.children.forEach(function(t){return e[t.value.outlet]=t}),e}var Ft=function(t){function e(e,n){var a=t.call(this,e)||this;return a.snapshot=n,Bt(a,e),a}return Object(a.__extends)(e,t),e.prototype.toString=function(){return this.snapshot.toString()},e}(Lt);function zt(t,e){var n=function(t,e){var n=new Vt([],{},{},"",{},X,e,null,t.root,-1,{});return new Ht("",new qt(n,[]))}(t,e),a=new u.a([new bt("",{})]),r=new u.a({}),i=new u.a({}),s=new u.a({}),o=new u.a(""),c=new Gt(a,r,s,o,i,X,e,n.root);return c.snapshot=n.root,new Ft(new qt(c,[]),n)}var Gt=function(){function t(t,e,n,a,r,i,s,o){this.url=t,this.params=e,this.queryParams=n,this.fragment=a,this.data=r,this.outlet=i,this.component=s,this._futureSnapshot=o}return Object.defineProperty(t.prototype,"routeConfig",{get:function(){return this._futureSnapshot.routeConfig},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"root",{get:function(){return this._routerState.root},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"parent",{get:function(){return this._routerState.parent(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"firstChild",{get:function(){return this._routerState.firstChild(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"children",{get:function(){return this._routerState.children(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"pathFromRoot",{get:function(){return this._routerState.pathFromRoot(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"paramMap",{get:function(){return this._paramMap||(this._paramMap=this.params.pipe(Object(g.a)(function(t){return Q(t)}))),this._paramMap},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"queryParamMap",{get:function(){return this._queryParamMap||(this._queryParamMap=this.queryParams.pipe(Object(g.a)(function(t){return Q(t)}))),this._queryParamMap},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return this.snapshot?this.snapshot.toString():"Future("+this._futureSnapshot+")"},t}();function Yt(t,e){void 0===e&&(e="emptyOnly");var n=t.pathFromRoot,r=0;if("always"!==e)for(r=n.length-1;r>=1;){var i=n[r],s=n[r-1];if(i.routeConfig&&""===i.routeConfig.path)r--;else{if(s.component)break;r--}}return function(t){return t.reduce(function(t,e){return{params:Object(a.__assign)({},t.params,e.params),data:Object(a.__assign)({},t.data,e.data),resolve:Object(a.__assign)({},t.resolve,e._resolvedData)}},{params:{},data:{},resolve:{}})}(n.slice(r))}var Vt=function(){function t(t,e,n,a,r,i,s,o,u,c,l){this.url=t,this.params=e,this.queryParams=n,this.fragment=a,this.data=r,this.outlet=i,this.component=s,this.routeConfig=o,this._urlSegment=u,this._lastPathIndex=c,this._resolve=l}return Object.defineProperty(t.prototype,"root",{get:function(){return this._routerState.root},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"parent",{get:function(){return this._routerState.parent(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"firstChild",{get:function(){return this._routerState.firstChild(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"children",{get:function(){return this._routerState.children(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"pathFromRoot",{get:function(){return this._routerState.pathFromRoot(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"paramMap",{get:function(){return this._paramMap||(this._paramMap=Q(this.params)),this._paramMap},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"queryParamMap",{get:function(){return this._queryParamMap||(this._queryParamMap=Q(this.queryParams)),this._queryParamMap},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return"Route(url:'"+this.url.map(function(t){return t.toString()}).join("/")+"', path:'"+(this.routeConfig?this.routeConfig.path:"")+"')"},t}(),Ht=function(t){function e(e,n){var a=t.call(this,n)||this;return a.url=e,Bt(a,n),a}return Object(a.__extends)(e,t),e.prototype.toString=function(){return Ut(this._root)},e}(Lt);function Bt(t,e){e.value._routerState=t,e.children.forEach(function(e){return Bt(t,e)})}function Ut(t){var e=t.children.length>0?" { "+t.children.map(Ut).join(", ")+" } ":"";return""+t.value+e}function Wt(t){if(t.snapshot){var e=t.snapshot,n=t._futureSnapshot;t.snapshot=n,ut(e.queryParams,n.queryParams)||t.queryParams.next(n.queryParams),e.fragment!==n.fragment&&t.fragment.next(n.fragment),ut(e.params,n.params)||t.params.next(n.params),function(t,e){if(t.length!==e.length)return!1;for(var n=0;n<t.length;++n)if(!ut(t[n],e[n]))return!1;return!0}(e.url,n.url)||t.url.next(n.url),ut(e.data,n.data)||t.data.next(n.data)}else t.snapshot=t._futureSnapshot,t.data.next(t._futureSnapshot.data)}function Kt(t,e){var n,a;return ut(t.params,e.params)&&mt(n=t.url,a=e.url)&&n.every(function(t,e){return ut(t.parameters,a[e].parameters)})&&!(!t.parent!=!e.parent)&&(!t.parent||Kt(t.parent,e.parent))}function $t(t){return"object"==typeof t&&null!=t&&!t.outlets&&!t.segmentPath}function Zt(t,e,n,a,r){var i={};return a&&dt(a,function(t,e){i[e]=Array.isArray(t)?t.map(function(t){return""+t}):""+t}),new ht(n.root===t?e:function t(e,n,a){var r={};return dt(e.children,function(e,i){r[i]=e===n?a:t(e,n,a)}),new gt(e.segments,r)}(n.root,t,e),i,r)}var Xt=function(){function t(t,e,n){if(this.isAbsolute=t,this.numberOfDoubleDots=e,this.commands=n,t&&n.length>0&&$t(n[0]))throw new Error("Root segment cannot have matrix parameters");var a=n.find(function(t){return"object"==typeof t&&null!=t&&t.outlets});if(a&&a!==lt(n))throw new Error("{outlets:{}} has to be the last command")}return t.prototype.toRoot=function(){return this.isAbsolute&&1===this.commands.length&&"/"==this.commands[0]},t}(),Jt=function(){return function(t,e,n){this.segmentGroup=t,this.processChildren=e,this.index=n}}();function Qt(t){return"object"==typeof t&&null!=t&&t.outlets?t.outlets[X]:""+t}function te(t,e,n){if(t||(t=new gt([],{})),0===t.segments.length&&t.hasChildren())return ee(t,e,n);var a=function(t,e,n){for(var a=0,r=e,i={match:!1,pathIndex:0,commandIndex:0};r<t.segments.length;){if(a>=n.length)return i;var s=t.segments[r],o=Qt(n[a]),u=a<n.length-1?n[a+1]:null;if(r>0&&void 0===o)break;if(o&&u&&"object"==typeof u&&void 0===u.outlets){if(!ie(o,u,s))return i;a+=2}else{if(!ie(o,{},s))return i;a++}r++}return{match:!0,pathIndex:r,commandIndex:a}}(t,e,n),r=n.slice(a.commandIndex);if(a.match&&a.pathIndex<t.segments.length){var i=new gt(t.segments.slice(0,a.pathIndex),{});return i.children[X]=new gt(t.segments.slice(a.pathIndex),t.children),ee(i,0,r)}return a.match&&0===r.length?new gt(t.segments,{}):a.match&&!t.hasChildren()?ne(t,e,n):a.match?ee(t,0,r):ne(t,e,n)}function ee(t,e,n){if(0===n.length)return new gt(t.segments,{});var a=function(t){var e,n;return"object"!=typeof t[0]?((e={})[X]=t,e):void 0===t[0].outlets?((n={})[X]=t,n):t[0].outlets}(n),r={};return dt(a,function(n,a){null!==n&&(r[a]=te(t.children[a],e,n))}),dt(t.children,function(t,e){void 0===a[e]&&(r[e]=t)}),new gt(t.segments,r)}function ne(t,e,n){for(var a=t.segments.slice(0,e),r=0;r<n.length;){if("object"==typeof n[r]&&void 0!==n[r].outlets){var i=ae(n[r].outlets);return new gt(a,i)}if(0===r&&$t(n[0]))a.push(new bt(t.segments[e].path,n[0])),r++;else{var s=Qt(n[r]),o=r<n.length-1?n[r+1]:null;s&&o&&$t(o)?(a.push(new bt(s,re(o))),r+=2):(a.push(new bt(s,{})),r++)}}return new gt(a,{})}function ae(t){var e={};return dt(t,function(t,n){null!==t&&(e[n]=ne(new gt([],{}),0,t))}),e}function re(t){var e={};return dt(t,function(t,n){return e[n]=""+t}),e}function ie(t,e,n){return t==n.path&&ut(e,n.parameters)}var se=function(){function t(t,e,n,a){this.routeReuseStrategy=t,this.futureState=e,this.currState=n,this.forwardEvent=a}return t.prototype.activate=function(t){var e=this.futureState._root,n=this.currState?this.currState._root:null;this.deactivateChildRoutes(e,n,t),Wt(this.futureState.root),this.activateChildRoutes(e,n,t)},t.prototype.deactivateChildRoutes=function(t,e,n){var a=this,r=jt(e);t.children.forEach(function(t){var e=t.value.outlet;a.deactivateRoutes(t,r[e],n),delete r[e]}),dt(r,function(t,e){a.deactivateRouteAndItsChildren(t,n)})},t.prototype.deactivateRoutes=function(t,e,n){var a=t.value,r=e?e.value:null;if(a===r)if(a.component){var i=n.getContext(a.outlet);i&&this.deactivateChildRoutes(t,e,i.children)}else this.deactivateChildRoutes(t,e,n);else r&&this.deactivateRouteAndItsChildren(e,n)},t.prototype.deactivateRouteAndItsChildren=function(t,e){this.routeReuseStrategy.shouldDetach(t.value.snapshot)?this.detachAndStoreRouteSubtree(t,e):this.deactivateRouteAndOutlet(t,e)},t.prototype.detachAndStoreRouteSubtree=function(t,e){var n=e.getContext(t.value.outlet);if(n&&n.outlet){var a=n.outlet.detach(),r=n.children.onOutletDeactivated();this.routeReuseStrategy.store(t.value.snapshot,{componentRef:a,route:t,contexts:r})}},t.prototype.deactivateRouteAndOutlet=function(t,e){var n=this,a=e.getContext(t.value.outlet);if(a){var r=jt(t),i=t.value.component?a.children:e;dt(r,function(t,e){return n.deactivateRouteAndItsChildren(t,i)}),a.outlet&&(a.outlet.deactivate(),a.children.onOutletDeactivated())}},t.prototype.activateChildRoutes=function(t,e,n){var a=this,r=jt(e);t.children.forEach(function(t){a.activateRoutes(t,r[t.value.outlet],n),a.forwardEvent(new K(t.value.snapshot))}),t.children.length&&this.forwardEvent(new U(t.value.snapshot))},t.prototype.activateRoutes=function(t,e,n){var a=t.value,r=e?e.value:null;if(Wt(a),a===r)if(a.component){var i=n.getOrCreateContext(a.outlet);this.activateChildRoutes(t,e,i.children)}else this.activateChildRoutes(t,e,n);else if(a.component)if(i=n.getOrCreateContext(a.outlet),this.routeReuseStrategy.shouldAttach(a.snapshot)){var s=this.routeReuseStrategy.retrieve(a.snapshot);this.routeReuseStrategy.store(a.snapshot,null),i.children.onOutletReAttached(s.contexts),i.attachRef=s.componentRef,i.route=s.route.value,i.outlet&&i.outlet.attach(s.componentRef,s.route.value),oe(s.route)}else{var o=function(t){for(var e=a.snapshot.parent;e;e=e.parent){var n=e.routeConfig;if(n&&n._loadedConfig)return n._loadedConfig;if(n&&n.component)return null}return null}(),u=o?o.module.componentFactoryResolver:null;i.attachRef=null,i.route=a,i.resolver=u,i.outlet&&i.outlet.activateWith(a,u),this.activateChildRoutes(t,null,i.children)}else this.activateChildRoutes(t,null,n)},t}();function oe(t){Wt(t.value),t.children.forEach(oe)}function ue(t){return"function"==typeof t}function ce(t){return t instanceof ht}var le=function(){return function(t){this.segmentGroup=t||null}}(),de=function(){return function(t){this.urlTree=t}}();function fe(t){return new c.a(function(e){return e.error(new le(t))})}function pe(t){return new c.a(function(e){return e.error(new de(t))})}function he(t){return new c.a(function(e){return e.error(new Error("Only absolute redirects can have named outlets. redirectTo: '"+t+"'"))})}var ge=function(){function t(t,e,n,a,r){this.configLoader=e,this.urlSerializer=n,this.urlTree=a,this.config=r,this.allowRedirects=!0,this.ngModule=t.get(i.NgModuleRef)}return t.prototype.apply=function(){var t=this;return this.expandSegmentGroup(this.ngModule,this.config,this.urlTree.root,X).pipe(Object(g.a)(function(e){return t.createUrlTree(e,t.urlTree.queryParams,t.urlTree.fragment)})).pipe(Object(y.a)(function(e){if(e instanceof de)return t.allowRedirects=!1,t.match(e.urlTree);if(e instanceof le)throw t.noMatchError(e);throw e}))},t.prototype.match=function(t){var e=this;return this.expandSegmentGroup(this.ngModule,this.config,t.root,X).pipe(Object(g.a)(function(n){return e.createUrlTree(n,t.queryParams,t.fragment)})).pipe(Object(y.a)(function(t){if(t instanceof le)throw e.noMatchError(t);throw t}))},t.prototype.noMatchError=function(t){return new Error("Cannot match any routes. URL Segment: '"+t.segmentGroup+"'")},t.prototype.createUrlTree=function(t,e,n){var a,r=t.segments.length>0?new gt([],((a={})[X]=t,a)):t;return new ht(r,e,n)},t.prototype.expandSegmentGroup=function(t,e,n,a){return 0===n.segments.length&&n.hasChildren()?this.expandChildren(t,e,n).pipe(Object(g.a)(function(t){return new gt([],t)})):this.expandSegment(t,n,e,n.segments,a,!0)},t.prototype.expandChildren=function(t,e,n){var a=this;return function(n,r){if(0===Object.keys(n).length)return Object(s.a)({});var i=[],o=[],u={};return dt(n,function(n,r){var s,c,l=(s=r,c=n,a.expandSegmentGroup(t,e,c,s)).pipe(Object(g.a)(function(t){return u[r]=t}));r===X?i.push(l):o.push(l)}),s.a.apply(null,i.concat(o)).pipe(Object(b.a)(),Object(m.a)(),Object(g.a)(function(){return u}))}(n.children)},t.prototype.expandSegment=function(t,e,n,r,i,o){var u=this;return s.a.apply(void 0,Object(a.__spread)(n)).pipe(Object(g.a)(function(a){return u.expandSegmentAgainstRoute(t,e,n,a,r,i,o).pipe(Object(y.a)(function(t){if(t instanceof le)return Object(s.a)(null);throw t}))}),Object(b.a)(),Object(v.a)(function(t){return!!t}),Object(y.a)(function(t,n){if(t instanceof l.a||"EmptyError"===t.name){if(u.noLeftoversInUrl(e,r,i))return Object(s.a)(new gt([],{}));throw new le(e)}throw t}))},t.prototype.noLeftoversInUrl=function(t,e,n){return 0===e.length&&!t.children[n]},t.prototype.expandSegmentAgainstRoute=function(t,e,n,a,r,i,s){return ve(a)!==i?fe(e):void 0===a.redirectTo?this.matchSegmentAgainstRoute(t,e,a,r):s&&this.allowRedirects?this.expandSegmentAgainstRouteUsingRedirect(t,e,n,a,r,i):fe(e)},t.prototype.expandSegmentAgainstRouteUsingRedirect=function(t,e,n,a,r,i){return"**"===a.path?this.expandWildCardWithParamsAgainstRouteUsingRedirect(t,n,a,i):this.expandRegularSegmentAgainstRouteUsingRedirect(t,e,n,a,r,i)},t.prototype.expandWildCardWithParamsAgainstRouteUsingRedirect=function(t,e,n,a){var r=this,i=this.applyRedirectCommands([],n.redirectTo,{});return n.redirectTo.startsWith("/")?pe(i):this.lineralizeSegments(n,i).pipe(Object(_.a)(function(n){var i=new gt(n,{});return r.expandSegment(t,i,e,n,a,!1)}))},t.prototype.expandRegularSegmentAgainstRouteUsingRedirect=function(t,e,n,a,r,i){var s=this,o=be(e,a,r),u=o.consumedSegments,c=o.lastChild,l=o.positionalParamSegments;if(!o.matched)return fe(e);var d=this.applyRedirectCommands(u,a.redirectTo,l);return a.redirectTo.startsWith("/")?pe(d):this.lineralizeSegments(a,d).pipe(Object(_.a)(function(a){return s.expandSegment(t,e,n,a.concat(r.slice(c)),i,!1)}))},t.prototype.matchSegmentAgainstRoute=function(t,e,n,r){var i=this;if("**"===n.path)return n.loadChildren?this.configLoader.load(t.injector,n).pipe(Object(g.a)(function(t){return n._loadedConfig=t,new gt(r,{})})):Object(s.a)(new gt(r,{}));var o=be(e,n,r),u=o.consumedSegments,c=o.lastChild;if(!o.matched)return fe(e);var l=r.slice(c);return this.getChildConfig(t,n,r).pipe(Object(_.a)(function(t){var n=t.module,r=t.routes,o=function(t,e,n,r){return n.length>0&&function(t,e,n){return r.some(function(n){return ye(t,e,n)&&ve(n)!==X})}(t,n)?{segmentGroup:me(new gt(e,function(t,e){var n,r,i={};i[X]=e;try{for(var s=Object(a.__values)(t),o=s.next();!o.done;o=s.next()){var u=o.value;""===u.path&&ve(u)!==X&&(i[ve(u)]=new gt([],{}))}}catch(c){n={error:c}}finally{try{o&&!o.done&&(r=s.return)&&r.call(s)}finally{if(n)throw n.error}}return i}(r,new gt(n,t.children)))),slicedSegments:[]}:0===n.length&&function(t,e,n){return r.some(function(n){return ye(t,e,n)})}(t,n)?{segmentGroup:me(new gt(t.segments,function(t,e,n,r){var i,s,o={};try{for(var u=Object(a.__values)(n),c=u.next();!c.done;c=u.next()){var l=c.value;ye(t,e,l)&&!r[ve(l)]&&(o[ve(l)]=new gt([],{}))}}catch(d){i={error:d}}finally{try{c&&!c.done&&(s=u.return)&&s.call(u)}finally{if(i)throw i.error}}return Object(a.__assign)({},r,o)}(t,n,r,t.children))),slicedSegments:n}:{segmentGroup:t,slicedSegments:n}}(e,u,l,r),c=o.segmentGroup,d=o.slicedSegments;return 0===d.length&&c.hasChildren()?i.expandChildren(n,r,c).pipe(Object(g.a)(function(t){return new gt(u,t)})):0===r.length&&0===d.length?Object(s.a)(new gt(u,{})):i.expandSegment(n,c,r,d,X,!0).pipe(Object(g.a)(function(t){return new gt(u.concat(t.segments),t.children)}))}))},t.prototype.getChildConfig=function(t,e,n){var a=this;return e.children?Object(s.a)(new at(e.children,t)):e.loadChildren?void 0!==e._loadedConfig?Object(s.a)(e._loadedConfig):function(t,e,n){var a=e.canLoad;return a&&0!==a.length?Object(o.a)(a).pipe(Object(g.a)(function(a){var r,i=t.get(a);if(function(t){return t&&ue(t.canLoad)}(i))r=i.canLoad(e,n);else{if(!ue(i))throw new Error("Invalid CanLoad guard");r=i(e,n)}return ft(r)})).pipe(Object(b.a)(),Object(x.a)(function(t){return!0===t})):Object(s.a)(!0)}(t.injector,e,n).pipe(Object(_.a)(function(n){return n?a.configLoader.load(t.injector,e).pipe(Object(g.a)(function(t){return e._loadedConfig=t,t})):function(t){return new c.a(function(e){return e.error(et("Cannot load children because the guard of the route \"path: '"+t.path+"'\" returned false"))})}(e)})):Object(s.a)(new at([],t))},t.prototype.lineralizeSegments=function(t,e){for(var n=[],a=e.root;;){if(n=n.concat(a.segments),0===a.numberOfChildren)return Object(s.a)(n);if(a.numberOfChildren>1||!a.children[X])return he(t.redirectTo);a=a.children[X]}},t.prototype.applyRedirectCommands=function(t,e,n){return this.applyRedirectCreatreUrlTree(e,this.urlSerializer.parse(e),t,n)},t.prototype.applyRedirectCreatreUrlTree=function(t,e,n,a){var r=this.createSegmentGroup(t,e.root,n,a);return new ht(r,this.createQueryParams(e.queryParams,this.urlTree.queryParams),e.fragment)},t.prototype.createQueryParams=function(t,e){var n={};return dt(t,function(t,a){if("string"==typeof t&&t.startsWith(":")){var r=t.substring(1);n[a]=e[r]}else n[a]=t}),n},t.prototype.createSegmentGroup=function(t,e,n,a){var r=this,i=this.createSegments(t,e.segments,n,a),s={};return dt(e.children,function(e,i){s[i]=r.createSegmentGroup(t,e,n,a)}),new gt(i,s)},t.prototype.createSegments=function(t,e,n,a){var r=this;return e.map(function(e){return e.path.startsWith(":")?r.findPosParam(t,e,a):r.findOrReturn(e,n)})},t.prototype.findPosParam=function(t,e,n){var a=n[e.path.substring(1)];if(!a)throw new Error("Cannot redirect to '"+t+"'. Cannot find '"+e.path+"'.");return a},t.prototype.findOrReturn=function(t,e){var n,r,i=0;try{for(var s=Object(a.__values)(e),o=s.next();!o.done;o=s.next()){var u=o.value;if(u.path===t.path)return e.splice(i),u;i++}}catch(c){n={error:c}}finally{try{o&&!o.done&&(r=s.return)&&r.call(s)}finally{if(n)throw n.error}}return t},t}();function be(t,e,n){if(""===e.path)return"full"===e.pathMatch&&(t.hasChildren()||n.length>0)?{matched:!1,consumedSegments:[],lastChild:0,positionalParamSegments:{}}:{matched:!0,consumedSegments:[],lastChild:0,positionalParamSegments:{}};var a=(e.matcher||nt)(n,t,e);return a?{matched:!0,consumedSegments:a.consumed,lastChild:a.consumed.length,positionalParamSegments:a.posParams}:{matched:!1,consumedSegments:[],lastChild:0,positionalParamSegments:{}}}function me(t){if(1===t.numberOfChildren&&t.children[X]){var e=t.children[X];return new gt(t.segments.concat(e.segments),e.children)}return t}function ye(t,e,n){return(!(t.hasChildren()||e.length>0)||"full"!==n.pathMatch)&&""===n.path&&void 0!==n.redirectTo}function ve(t){return t.outlet||X}var _e=function(){return function(t){this.path=t,this.route=this.path[this.path.length-1]}}(),xe=function(){return function(t,e){this.component=t,this.route=e}}();function Te(t,e,n){var a=function(t){if(!t)return null;for(var e=t.parent;e;e=e.parent){var n=e.routeConfig;if(n&&n._loadedConfig)return n._loadedConfig}return null}(e);return(a?a.module.injector:n).get(t)}function we(t,e,n,a,r){void 0===r&&(r={canDeactivateChecks:[],canActivateChecks:[]});var i=jt(e);return t.children.forEach(function(t){!function(t,e,n,a,r){void 0===r&&(r={canDeactivateChecks:[],canActivateChecks:[]});var i=t.value,s=e?e.value:null,o=n?n.getContext(t.value.outlet):null;if(s&&i.routeConfig===s.routeConfig){var u=function(t,e,n){if("function"==typeof n)return n(t,e);switch(n){case"pathParamsChange":return!mt(t.url,e.url);case"pathParamsOrQueryParamsChange":return!mt(t.url,e.url)||!ut(t.queryParams,e.queryParams);case"always":return!0;case"paramsOrQueryParamsChange":return!Kt(t,e)||!ut(t.queryParams,e.queryParams);case"paramsChange":default:return!Kt(t,e)}}(s,i,i.routeConfig.runGuardsAndResolvers);u?r.canActivateChecks.push(new _e(a)):(i.data=s.data,i._resolvedData=s._resolvedData),we(t,e,i.component?o?o.children:null:n,a,r),u&&r.canDeactivateChecks.push(new xe(o&&o.outlet&&o.outlet.component||null,s))}else s&&Se(e,o,r),r.canActivateChecks.push(new _e(a)),we(t,null,i.component?o?o.children:null:n,a,r)}(t,i[t.value.outlet],n,a.concat([t.value]),r),delete i[t.value.outlet]}),dt(i,function(t,e){return Se(t,n.getContext(e),r)}),r}function Se(t,e,n){var a=jt(t),r=t.value;dt(a,function(t,a){Se(t,r.component?e?e.children.getContext(a):null:e,n)}),n.canDeactivateChecks.push(new xe(r.component&&e&&e.outlet&&e.outlet.isActivated?e.outlet.component:null,r))}var Oe=Symbol("INITIAL_VALUE");function Ie(){return Object(T.a)(function(t){return d.b.apply(void 0,Object(a.__spread)(t.map(function(t){return t.pipe(Object(w.a)(1),Object(S.a)(Oe))}))).pipe(Object(O.a)(function(t,e){var n=!1;return e.reduce(function(t,a,r){if(t!==Oe)return t;if(a===Oe&&(n=!0),!n){if(!1===a)return a;if(r===e.length-1||ce(a))return a}return t},t)},Oe),Object(I.a)(function(t){return t!==Oe}),Object(g.a)(function(t){return ce(t)?t:!0===t}),Object(w.a)(1))})}function Ce(t,e){return null!==t&&e&&e(new W(t)),Object(s.a)(!0)}function ke(t,e){return null!==t&&e&&e(new B(t)),Object(s.a)(!0)}function Ne(t,e,n){var a=e.routeConfig?e.routeConfig.canActivate:null;if(!a||0===a.length)return Object(s.a)(!0);var r=a.map(function(a){return Object(f.a)(function(){var r,i=Te(a,e,n);if(function(t){return t&&ue(t.canActivate)}(i))r=ft(i.canActivate(e,t));else{if(!ue(i))throw new Error("Invalid CanActivate guard");r=ft(i(e,t))}return r.pipe(Object(v.a)())})});return Object(s.a)(r).pipe(Ie())}function Re(t,e,n){var a=e[e.length-1],r=e.slice(0,e.length-1).reverse().map(function(t){return function(t){var e=t.routeConfig?t.routeConfig.canActivateChild:null;return e&&0!==e.length?{node:t,guards:e}:null}(t)}).filter(function(t){return null!==t}).map(function(e){return Object(f.a)(function(){var r=e.guards.map(function(r){var i,s=Te(r,e.node,n);if(function(t){return t&&ue(t.canActivateChild)}(s))i=ft(s.canActivateChild(a,t));else{if(!ue(s))throw new Error("Invalid CanActivateChild guard");i=ft(s(a,t))}return i.pipe(Object(v.a)())});return Object(s.a)(r).pipe(Ie())})});return Object(s.a)(r).pipe(Ie())}var Ae=function(){return function(){}}(),De=function(){function t(t,e,n,a,r,i){this.rootComponentType=t,this.config=e,this.urlTree=n,this.url=a,this.paramsInheritanceStrategy=r,this.relativeLinkResolution=i}return t.prototype.recognize=function(){try{var t=Pe(this.urlTree.root,[],[],this.config,this.relativeLinkResolution).segmentGroup,e=this.processSegmentGroup(this.config,t,X),n=new Vt([],Object.freeze({}),Object.freeze(Object(a.__assign)({},this.urlTree.queryParams)),this.urlTree.fragment,{},X,this.rootComponentType,null,this.urlTree.root,-1,{}),r=new qt(n,e),i=new Ht(this.url,r);return this.inheritParamsAndData(i._root),Object(s.a)(i)}catch(o){return new c.a(function(t){return t.error(o)})}},t.prototype.inheritParamsAndData=function(t){var e=this,n=t.value,a=Yt(n,this.paramsInheritanceStrategy);n.params=Object.freeze(a.params),n.data=Object.freeze(a.data),t.children.forEach(function(t){return e.inheritParamsAndData(t)})},t.prototype.processSegmentGroup=function(t,e,n){return 0===e.segments.length&&e.hasChildren()?this.processChildren(t,e):this.processSegment(t,e,e.segments,n)},t.prototype.processChildren=function(t,e){var n,a=this,r=yt(e,function(e,n){return a.processSegmentGroup(t,e,n)});return n={},r.forEach(function(t){var e=n[t.value.outlet];if(e){var a=e.url.map(function(t){return t.toString()}).join("/"),r=t.value.url.map(function(t){return t.toString()}).join("/");throw new Error("Two segments cannot have the same outlet name: '"+a+"' and '"+r+"'.")}n[t.value.outlet]=t.value}),r.sort(function(t,e){return t.value.outlet===X?-1:e.value.outlet===X?1:t.value.outlet.localeCompare(e.value.outlet)}),r},t.prototype.processSegment=function(t,e,n,r){var i,s;try{for(var o=Object(a.__values)(t),u=o.next();!u.done;u=o.next()){var c=u.value;try{return this.processSegmentAgainstRoute(c,e,n,r)}catch(l){if(!(l instanceof Ae))throw l}}}catch(d){i={error:d}}finally{try{u&&!u.done&&(s=o.return)&&s.call(o)}finally{if(i)throw i.error}}if(this.noLeftoversInUrl(e,n,r))return[];throw new Ae},t.prototype.noLeftoversInUrl=function(t,e,n){return 0===e.length&&!t.children[n]},t.prototype.processSegmentAgainstRoute=function(t,e,n,r){if(t.redirectTo)throw new Ae;if((t.outlet||X)!==r)throw new Ae;var i,s=[],o=[];if("**"===t.path){var u=n.length>0?lt(n).parameters:{};i=new Vt(n,u,Object.freeze(Object(a.__assign)({},this.urlTree.queryParams)),this.urlTree.fragment,je(t),r,t.component,t,Ee(e),Le(e)+n.length,Fe(t))}else{var c=function(t,e,n){if(""===e.path){if("full"===e.pathMatch&&(t.hasChildren()||n.length>0))throw new Ae;return{consumedSegments:[],lastChild:0,parameters:{}}}var r=(e.matcher||nt)(n,t,e);if(!r)throw new Ae;var i={};dt(r.posParams,function(t,e){i[e]=t.path});var s=r.consumed.length>0?Object(a.__assign)({},i,r.consumed[r.consumed.length-1].parameters):i;return{consumedSegments:r.consumed,lastChild:r.consumed.length,parameters:s}}(e,t,n);s=c.consumedSegments,o=n.slice(c.lastChild),i=new Vt(s,c.parameters,Object.freeze(Object(a.__assign)({},this.urlTree.queryParams)),this.urlTree.fragment,je(t),r,t.component,t,Ee(e),Le(e)+s.length,Fe(t))}var l=function(t){return t.children?t.children:t.loadChildren?t._loadedConfig.routes:[]}(t),d=Pe(e,s,o,l,this.relativeLinkResolution),f=d.segmentGroup,p=d.slicedSegments;if(0===p.length&&f.hasChildren()){var h=this.processChildren(l,f);return[new qt(i,h)]}if(0===l.length&&0===p.length)return[new qt(i,[])];var g=this.processSegment(l,f,p,X);return[new qt(i,g)]},t}();function Ee(t){for(var e=t;e._sourceSegment;)e=e._sourceSegment;return e}function Le(t){for(var e=t,n=e._segmentIndexShift?e._segmentIndexShift:0;e._sourceSegment;)n+=(e=e._sourceSegment)._segmentIndexShift?e._segmentIndexShift:0;return n-1}function Pe(t,e,n,r,i){if(n.length>0&&function(t,e,n){return r.some(function(n){return Me(t,e,n)&&qe(n)!==X})}(t,n)){var s=new gt(e,function(t,e,n,r){var i,s,o={};o[X]=r,r._sourceSegment=t,r._segmentIndexShift=e.length;try{for(var u=Object(a.__values)(n),c=u.next();!c.done;c=u.next()){var l=c.value;if(""===l.path&&qe(l)!==X){var d=new gt([],{});d._sourceSegment=t,d._segmentIndexShift=e.length,o[qe(l)]=d}}}catch(f){i={error:f}}finally{try{c&&!c.done&&(s=u.return)&&s.call(u)}finally{if(i)throw i.error}}return o}(t,e,r,new gt(n,t.children)));return s._sourceSegment=t,s._segmentIndexShift=e.length,{segmentGroup:s,slicedSegments:[]}}if(0===n.length&&function(t,e,n){return r.some(function(n){return Me(t,e,n)})}(t,n)){var o=new gt(t.segments,function(t,e,n,r,i,s){var o,u,c={};try{for(var l=Object(a.__values)(r),d=l.next();!d.done;d=l.next()){var f=d.value;if(Me(t,n,f)&&!i[qe(f)]){var p=new gt([],{});p._sourceSegment=t,p._segmentIndexShift="legacy"===s?t.segments.length:e.length,c[qe(f)]=p}}}catch(h){o={error:h}}finally{try{d&&!d.done&&(u=l.return)&&u.call(l)}finally{if(o)throw o.error}}return Object(a.__assign)({},i,c)}(t,e,n,r,t.children,i));return o._sourceSegment=t,o._segmentIndexShift=e.length,{segmentGroup:o,slicedSegments:n}}var u=new gt(t.segments,t.children);return u._sourceSegment=t,u._segmentIndexShift=e.length,{segmentGroup:u,slicedSegments:n}}function Me(t,e,n){return(!(t.hasChildren()||e.length>0)||"full"!==n.pathMatch)&&""===n.path&&void 0===n.redirectTo}function qe(t){return t.outlet||X}function je(t){return t.data||{}}function Fe(t){return t.resolve||{}}function ze(t,e,n,a){var r=Te(t,e,a);return ft(r.resolve?r.resolve(e,n):r(e,n))}function Ge(t){return function(e){return e.pipe(Object(T.a)(function(e){var n=t(e);return n?Object(o.a)(n).pipe(Object(g.a)(function(){return e})):Object(o.a)([e])}))}}var Ye=function(){return function(){}}(),Ve=function(){function t(){}return t.prototype.shouldDetach=function(t){return!1},t.prototype.store=function(t,e){},t.prototype.shouldAttach=function(t){return!1},t.prototype.retrieve=function(t){return null},t.prototype.shouldReuseRoute=function(t,e){return t.routeConfig===e.routeConfig},t}(),He=new i.InjectionToken("ROUTES"),Be=function(){function t(t,e,n,a){this.loader=t,this.compiler=e,this.onLoadStartListener=n,this.onLoadEndListener=a}return t.prototype.load=function(t,e){var n=this;return this.onLoadStartListener&&this.onLoadStartListener(e),this.loadModuleFactory(e.loadChildren).pipe(Object(g.a)(function(a){n.onLoadEndListener&&n.onLoadEndListener(e);var r=a.create(t);return new at(ct(r.injector.get(He)).map(ot),r)}))},t.prototype.loadModuleFactory=function(t){var e=this;return"string"==typeof t?Object(o.a)(this.loader.load(t)):ft(t()).pipe(Object(_.a)(function(t){return t instanceof i.NgModuleFactory?Object(s.a)(t):Object(o.a)(e.compiler.compileModuleAsync(t))}))},t}(),Ue=function(){return function(){}}(),We=function(){function t(){}return t.prototype.shouldProcessUrl=function(t){return!0},t.prototype.extract=function(t){return t},t.prototype.merge=function(t,e){return t},t}();function Ke(t){throw t}function $e(t,e,n){return e.parse("/")}function Ze(t,e){return Object(s.a)(null)}var Xe=function(){function t(t,e,n,a,r,s,o,c){var l=this;this.rootComponentType=t,this.urlSerializer=e,this.rootContexts=n,this.location=a,this.config=c,this.lastSuccessfulNavigation=null,this.currentNavigation=null,this.navigationId=0,this.isNgZoneEnabled=!1,this.events=new p.a,this.errorHandler=Ke,this.malformedUriErrorHandler=$e,this.navigated=!1,this.lastSuccessfulId=-1,this.hooks={beforePreactivation:Ze,afterPreactivation:Ze},this.urlHandlingStrategy=new We,this.routeReuseStrategy=new Ve,this.onSameUrlNavigation="ignore",this.paramsInheritanceStrategy="emptyOnly",this.urlUpdateStrategy="deferred",this.relativeLinkResolution="legacy",this.ngModule=r.get(i.NgModuleRef),this.console=r.get(i["\u0275Console"]);var d=r.get(i.NgZone);this.isNgZoneEnabled=d instanceof i.NgZone,this.resetConfig(c),this.currentUrlTree=new ht(new gt([],{}),{},null),this.rawUrlTree=this.currentUrlTree,this.browserUrlTree=this.currentUrlTree,this.configLoader=new Be(s,o,function(t){return l.triggerEvent(new V(t))},function(t){return l.triggerEvent(new H(t))}),this.routerState=zt(this.currentUrlTree,this.rootComponentType),this.transitions=new u.a({id:0,currentUrlTree:this.currentUrlTree,currentRawUrl:this.currentUrlTree,extractedUrl:this.urlHandlingStrategy.extract(this.currentUrlTree),urlAfterRedirects:this.urlHandlingStrategy.extract(this.currentUrlTree),rawUrl:this.currentUrlTree,extras:{},resolve:null,reject:null,promise:Promise.resolve(!0),source:"imperative",restoredState:null,currentSnapshot:this.routerState.snapshot,targetSnapshot:null,currentRouterState:this.routerState,targetRouterState:null,guards:{canActivateChecks:[],canDeactivateChecks:[]},guardsResult:null}),this.navigations=this.setupNavigations(this.transitions),this.processNavigations()}return t.prototype.setupNavigations=function(t){var e=this,n=this.events;return t.pipe(Object(I.a)(function(t){return 0!==t.id}),Object(g.a)(function(t){return Object(a.__assign)({},t,{extractedUrl:e.urlHandlingStrategy.extract(t.rawUrl)})}),Object(N.a)(function(t){e.currentNavigation={id:t.id,initialUrl:t.currentRawUrl,extractedUrl:t.extractedUrl,trigger:t.source,extras:t.extras,previousNavigation:e.lastSuccessfulNavigation?Object(a.__assign)({},e.lastSuccessfulNavigation,{previousNavigation:null}):null}}),Object(T.a)(function(t){var r,i,c,l=!1,d=!1;return Object(s.a)(t).pipe(Object(T.a)(function(t){var r,i,o,u,c=!e.navigated||t.extractedUrl.toString()!==e.browserUrlTree.toString();if(("reload"===e.onSameUrlNavigation||c)&&e.urlHandlingStrategy.shouldProcessUrl(t.rawUrl))return Object(s.a)(t).pipe(Object(T.a)(function(t){var a=e.transitions.getValue();return n.next(new L(t.id,e.serializeUrl(t.extractedUrl),t.source,t.restoredState)),a!==e.transitions.getValue()?h.a:[t]}),Object(T.a)(function(t){return Promise.resolve(t)}),(r=e.ngModule.injector,i=e.configLoader,o=e.urlSerializer,u=e.config,function(t){return t.pipe(Object(T.a)(function(t){return function(e,n,a,r,i){return new ge(e,n,a,t.extractedUrl,i).apply()}(r,i,o,0,u).pipe(Object(g.a)(function(e){return Object(a.__assign)({},t,{urlAfterRedirects:e})}))}))}),Object(N.a)(function(t){e.currentNavigation=Object(a.__assign)({},e.currentNavigation,{finalUrl:t.urlAfterRedirects})}),function(t,n,r,i,s){return function(r){return r.pipe(Object(_.a)(function(r){return function(t,e,n,a,r,i){return void 0===r&&(r="emptyOnly"),void 0===i&&(i="legacy"),new De(t,e,n,a,r,i).recognize()}(t,n,r.urlAfterRedirects,(o=r.urlAfterRedirects,e.serializeUrl(o)),i,s).pipe(Object(g.a)(function(t){return Object(a.__assign)({},r,{targetSnapshot:t})}));var o}))}}(e.rootComponentType,e.config,0,e.paramsInheritanceStrategy,e.relativeLinkResolution),Object(N.a)(function(t){"eager"===e.urlUpdateStrategy&&(t.extras.skipLocationChange||e.setBrowserUrl(t.urlAfterRedirects,!!t.extras.replaceUrl,t.id),e.browserUrlTree=t.urlAfterRedirects)}),Object(N.a)(function(t){var a=new j(t.id,e.serializeUrl(t.extractedUrl),e.serializeUrl(t.urlAfterRedirects),t.targetSnapshot);n.next(a)}));if(c&&e.rawUrlTree&&e.urlHandlingStrategy.shouldProcessUrl(e.rawUrlTree)){var l=t.extractedUrl,d=t.source,f=t.restoredState,p=t.extras,b=new L(t.id,e.serializeUrl(l),d,f);n.next(b);var m=zt(l,e.rootComponentType).snapshot;return Object(s.a)(Object(a.__assign)({},t,{targetSnapshot:m,urlAfterRedirects:l,extras:Object(a.__assign)({},p,{skipLocationChange:!1,replaceUrl:!1})}))}return e.rawUrlTree=t.rawUrl,t.resolve(null),h.a}),Ge(function(t){var n=t.extras;return e.hooks.beforePreactivation(t.targetSnapshot,{navigationId:t.id,appliedUrlTree:t.extractedUrl,rawUrlTree:t.rawUrl,skipLocationChange:!!n.skipLocationChange,replaceUrl:!!n.replaceUrl})}),Object(N.a)(function(t){var n=new F(t.id,e.serializeUrl(t.extractedUrl),e.serializeUrl(t.urlAfterRedirects),t.targetSnapshot);e.triggerEvent(n)}),Object(g.a)(function(t){return Object(a.__assign)({},t,{guards:(n=t.targetSnapshot,r=t.currentSnapshot,i=e.rootContexts,s=n._root,we(s,r?r._root:null,i,[s.value]))});var n,r,i,s}),function(t,e){return function(n){return n.pipe(Object(_.a)(function(n){var r=n.targetSnapshot,i=n.currentSnapshot,u=n.guards,c=u.canActivateChecks,l=u.canDeactivateChecks;return 0===l.length&&0===c.length?Object(s.a)(Object(a.__assign)({},n,{guardsResult:!0})):function(t,e,n,a){return Object(o.a)(t).pipe(Object(_.a)(function(t){return function(t,e,n,a,r){var i=e&&e.routeConfig?e.routeConfig.canDeactivate:null;if(!i||0===i.length)return Object(s.a)(!0);var o=i.map(function(i){var s,o=Te(i,e,r);if(function(t){return t&&ue(t.canDeactivate)}(o))s=ft(o.canDeactivate(t,e,n,a));else{if(!ue(o))throw new Error("Invalid CanDeactivate guard");s=ft(o(t,e,n,a))}return s.pipe(Object(v.a)())});return Object(s.a)(o).pipe(Ie())}(t.component,t.route,n,e,a)}),Object(v.a)(function(t){return!0!==t},!0))}(l,r,i,t).pipe(Object(_.a)(function(n){return n&&"boolean"==typeof n?function(t,e,n,a){return Object(o.a)(e).pipe(Object(C.a)(function(e){return Object(o.a)([ke(e.route.parent,a),Ce(e.route,a),Re(t,e.path,n),Ne(t,e.route,n)]).pipe(Object(b.a)(),Object(v.a)(function(t){return!0!==t},!0))}),Object(v.a)(function(t){return!0!==t},!0))}(r,c,t,e):Object(s.a)(n)}),Object(g.a)(function(t){return Object(a.__assign)({},n,{guardsResult:t})}))}))}}(e.ngModule.injector,function(t){return e.triggerEvent(t)}),Object(N.a)(function(t){if(ce(t.guardsResult)){var n=et('Redirecting to "'+e.serializeUrl(t.guardsResult)+'"');throw n.url=t.guardsResult,n}}),Object(N.a)(function(t){var n=new z(t.id,e.serializeUrl(t.extractedUrl),e.serializeUrl(t.urlAfterRedirects),t.targetSnapshot,!!t.guardsResult);e.triggerEvent(n)}),Object(I.a)(function(t){if(!t.guardsResult){e.resetUrlToCurrentUrlTree();var a=new M(t.id,e.serializeUrl(t.extractedUrl),"");return n.next(a),t.resolve(!1),!1}return!0}),Ge(function(t){if(t.guards.canActivateChecks.length)return Object(s.a)(t).pipe(Object(N.a)(function(t){var n=new G(t.id,e.serializeUrl(t.extractedUrl),e.serializeUrl(t.urlAfterRedirects),t.targetSnapshot);e.triggerEvent(n)}),(n=e.paramsInheritanceStrategy,r=e.ngModule.injector,function(t){return t.pipe(Object(_.a)(function(t){var e=t.targetSnapshot,i=t.guards.canActivateChecks;return i.length?Object(o.a)(i).pipe(Object(C.a)(function(t){return function(t,n,r,i){return function(t,e,n,a){var r=Object.keys(t);if(0===r.length)return Object(s.a)({});if(1===r.length){var i=r[0];return ze(t[i],e,n,a).pipe(Object(g.a)(function(t){var e;return(e={})[i]=t,e}))}var u={};return Object(o.a)(r).pipe(Object(_.a)(function(r){return ze(t[r],e,n,a).pipe(Object(g.a)(function(t){return u[r]=t,t}))})).pipe(Object(m.a)(),Object(g.a)(function(){return u}))}(t._resolve,t,e,i).pipe(Object(g.a)(function(e){return t._resolvedData=e,t.data=Object(a.__assign)({},t.data,Yt(t,r).resolve),null}))}(t.route,0,n,r)}),Object(k.a)(function(t,e){return t}),Object(g.a)(function(e){return t})):Object(s.a)(t)}))}),Object(N.a)(function(t){var n=new Y(t.id,e.serializeUrl(t.extractedUrl),e.serializeUrl(t.urlAfterRedirects),t.targetSnapshot);e.triggerEvent(n)}));var n,r}),Ge(function(t){var n=t.extras;return e.hooks.afterPreactivation(t.targetSnapshot,{navigationId:t.id,appliedUrlTree:t.extractedUrl,rawUrlTree:t.rawUrl,skipLocationChange:!!n.skipLocationChange,replaceUrl:!!n.replaceUrl})}),Object(g.a)(function(t){var n,r,i,s=(i=function t(e,n,r){if(r&&e.shouldReuseRoute(n.value,r.value.snapshot)){(l=r.value)._futureSnapshot=n.value;var i=function(e,n,r){return n.children.map(function(n){var i,s;try{for(var o=Object(a.__values)(r.children),u=o.next();!u.done;u=o.next()){var c=u.value;if(e.shouldReuseRoute(c.value.snapshot,n.value))return t(e,n,c)}}catch(l){i={error:l}}finally{try{u&&!u.done&&(s=o.return)&&s.call(o)}finally{if(i)throw i.error}}return t(e,n)})}(e,n,r);return new qt(l,i)}var s=e.retrieve(n.value);if(s){var o=s.route;return function t(e,n){if(e.value.routeConfig!==n.value.routeConfig)throw new Error("Cannot reattach ActivatedRouteSnapshot created from a different route");if(e.children.length!==n.children.length)throw new Error("Cannot reattach ActivatedRouteSnapshot with a different number of children");n.value._futureSnapshot=e.value;for(var a=0;a<e.children.length;++a)t(e.children[a],n.children[a])}(n,o),o}var c,l=new Gt(new u.a((c=n.value).url),new u.a(c.params),new u.a(c.queryParams),new u.a(c.fragment),new u.a(c.data),c.outlet,c.component,c);return i=n.children.map(function(n){return t(e,n)}),new qt(l,i)}(e.routeReuseStrategy,(n=t.targetSnapshot)._root,(r=t.currentRouterState)?r._root:void 0),new Ft(i,n));return Object(a.__assign)({},t,{targetRouterState:s})}),Object(N.a)(function(t){e.currentUrlTree=t.urlAfterRedirects,e.rawUrlTree=e.urlHandlingStrategy.merge(e.currentUrlTree,t.rawUrl),e.routerState=t.targetRouterState,"deferred"===e.urlUpdateStrategy&&(t.extras.skipLocationChange||e.setBrowserUrl(e.rawUrlTree,!!t.extras.replaceUrl,t.id,t.extras.state),e.browserUrlTree=t.urlAfterRedirects)}),(r=e.rootContexts,i=e.routeReuseStrategy,c=function(t){return e.triggerEvent(t)},Object(g.a)(function(t){return new se(i,t.targetRouterState,t.currentRouterState,c).activate(r),t})),Object(N.a)({next:function(){l=!0},complete:function(){l=!0}}),Object(R.a)(function(){if(!l&&!d){e.resetUrlToCurrentUrlTree();var a=new M(t.id,e.serializeUrl(t.extractedUrl),"Navigation ID "+t.id+" is not equal to the current navigation id "+e.navigationId);n.next(a),t.resolve(!1)}e.currentNavigation=null}),Object(y.a)(function(a){if(d=!0,(o=a)&&o[tt]){var r=ce(a.url);r||(e.navigated=!0,e.resetStateAndUrl(t.currentRouterState,t.currentUrlTree,t.rawUrl));var i=new M(t.id,e.serializeUrl(t.extractedUrl),a.message);n.next(i),t.resolve(!1),r&&e.navigateByUrl(a.url)}else{e.resetStateAndUrl(t.currentRouterState,t.currentUrlTree,t.rawUrl);var s=new q(t.id,e.serializeUrl(t.extractedUrl),a);n.next(s);try{t.resolve(e.errorHandler(a))}catch(u){t.reject(u)}}var o;return h.a}))}))},t.prototype.resetRootComponentType=function(t){this.rootComponentType=t,this.routerState.root.component=this.rootComponentType},t.prototype.getTransition=function(){return this.transitions.value},t.prototype.setTransition=function(t){this.transitions.next(Object(a.__assign)({},this.getTransition(),t))},t.prototype.initialNavigation=function(){this.setUpLocationChangeListener(),0===this.navigationId&&this.navigateByUrl(this.location.path(!0),{replaceUrl:!0})},t.prototype.setUpLocationChangeListener=function(){var t=this;this.locationSubscription||(this.locationSubscription=this.location.subscribe(function(e){var n=t.parseUrl(e.url),a="popstate"===e.type?"popstate":"hashchange",r=e.state&&e.state.navigationId?e.state:null;setTimeout(function(){t.scheduleNavigation(n,a,r,{replaceUrl:!0})},0)}))},Object.defineProperty(t.prototype,"url",{get:function(){return this.serializeUrl(this.currentUrlTree)},enumerable:!0,configurable:!0}),t.prototype.getCurrentNavigation=function(){return this.currentNavigation},t.prototype.triggerEvent=function(t){this.events.next(t)},t.prototype.resetConfig=function(t){rt(t),this.config=t.map(ot),this.navigated=!1,this.lastSuccessfulId=-1},t.prototype.ngOnDestroy=function(){this.dispose()},t.prototype.dispose=function(){this.locationSubscription&&(this.locationSubscription.unsubscribe(),this.locationSubscription=null)},t.prototype.createUrlTree=function(t,e){void 0===e&&(e={});var n=e.relativeTo,r=e.queryParams,s=e.fragment,o=e.preserveQueryParams,u=e.queryParamsHandling,c=e.preserveFragment;Object(i.isDevMode)()&&o&&console&&console.warn&&console.warn("preserveQueryParams is deprecated, use queryParamsHandling instead.");var l=n||this.routerState.root,d=c?this.currentUrlTree.fragment:s,f=null;if(u)switch(u){case"merge":f=Object(a.__assign)({},this.currentUrlTree.queryParams,r);break;case"preserve":f=this.currentUrlTree.queryParams;break;default:f=r||null}else f=o?this.currentUrlTree.queryParams:r||null;return null!==f&&(f=this.removeEmptyProps(f)),function(t,e,n,r,i){if(0===n.length)return Zt(e.root,e.root,e,r,i);var s=function(t){if("string"==typeof t[0]&&1===t.length&&"/"===t[0])return new Xt(!0,0,t);var e=0,n=!1,r=t.reduce(function(t,r,i){if("object"==typeof r&&null!=r){if(r.outlets){var s={};return dt(r.outlets,function(t,e){s[e]="string"==typeof t?t.split("/"):t}),Object(a.__spread)(t,[{outlets:s}])}if(r.segmentPath)return Object(a.__spread)(t,[r.segmentPath])}return"string"!=typeof r?Object(a.__spread)(t,[r]):0===i?(r.split("/").forEach(function(a,r){0==r&&"."===a||(0==r&&""===a?n=!0:".."===a?e++:""!=a&&t.push(a))}),t):Object(a.__spread)(t,[r])},[]);return new Xt(n,e,r)}(n);if(s.toRoot())return Zt(e.root,new gt([],{}),e,r,i);var o=function(t,n,a){if(t.isAbsolute)return new Jt(e.root,!0,0);if(-1===a.snapshot._lastPathIndex)return new Jt(a.snapshot._urlSegment,!0,0);var r=$t(t.commands[0])?0:1;return function(e,n,i){for(var s=a.snapshot._urlSegment,o=a.snapshot._lastPathIndex+r,u=t.numberOfDoubleDots;u>o;){if(u-=o,!(s=s.parent))throw new Error("Invalid number of '../'");o=s.segments.length}return new Jt(s,!1,o-u)}()}(s,0,t),u=o.processChildren?ee(o.segmentGroup,o.index,s.commands):te(o.segmentGroup,o.index,s.commands);return Zt(o.segmentGroup,u,e,r,i)}(l,this.currentUrlTree,t,f,d)},t.prototype.navigateByUrl=function(t,e){void 0===e&&(e={skipLocationChange:!1}),Object(i.isDevMode)()&&this.isNgZoneEnabled&&!i.NgZone.isInAngularZone()&&this.console.warn("Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?");var n=ce(t)?t:this.parseUrl(t),a=this.urlHandlingStrategy.merge(n,this.rawUrlTree);return this.scheduleNavigation(a,"imperative",null,e)},t.prototype.navigate=function(t,e){return void 0===e&&(e={skipLocationChange:!1}),function(t){for(var e=0;e<t.length;e++){var n=t[e];if(null==n)throw new Error("The requested path contains "+n+" segment at index "+e)}}(t),this.navigateByUrl(this.createUrlTree(t,e),e)},t.prototype.serializeUrl=function(t){return this.urlSerializer.serialize(t)},t.prototype.parseUrl=function(t){var e;try{e=this.urlSerializer.parse(t)}catch(n){e=this.malformedUriErrorHandler(n,this.urlSerializer,t)}return e},t.prototype.isActive=function(t,e){if(ce(t))return pt(this.currentUrlTree,t,e);var n=this.parseUrl(t);return pt(this.currentUrlTree,n,e)},t.prototype.removeEmptyProps=function(t){return Object.keys(t).reduce(function(e,n){var a=t[n];return null!=a&&(e[n]=a),e},{})},t.prototype.processNavigations=function(){var t=this;this.navigations.subscribe(function(e){t.navigated=!0,t.lastSuccessfulId=e.id,t.events.next(new P(e.id,t.serializeUrl(e.extractedUrl),t.serializeUrl(t.currentUrlTree))),t.lastSuccessfulNavigation=t.currentNavigation,t.currentNavigation=null,e.resolve(!0)},function(e){t.console.warn("Unhandled Navigation Error: ")})},t.prototype.scheduleNavigation=function(t,e,n,a){var r=this.getTransition();if(r&&"imperative"!==e&&"imperative"===r.source&&r.rawUrl.toString()===t.toString())return Promise.resolve(!0);if(r&&"hashchange"==e&&"popstate"===r.source&&r.rawUrl.toString()===t.toString())return Promise.resolve(!0);if(r&&"popstate"==e&&"hashchange"===r.source&&r.rawUrl.toString()===t.toString())return Promise.resolve(!0);var i=null,s=null,o=new Promise(function(t,e){i=t,s=e}),u=++this.navigationId;return this.setTransition({id:u,source:e,restoredState:n,currentUrlTree:this.currentUrlTree,currentRawUrl:this.rawUrlTree,rawUrl:t,extras:a,resolve:i,reject:s,promise:o,currentSnapshot:this.routerState.snapshot,currentRouterState:this.routerState}),o.catch(function(t){return Promise.reject(t)})},t.prototype.setBrowserUrl=function(t,e,n,r){var i=this.urlSerializer.serialize(t);r=r||{},this.location.isCurrentPathEqualTo(i)||e?this.location.replaceState(i,"",Object(a.__assign)({},r,{navigationId:n})):this.location.go(i,"",Object(a.__assign)({},r,{navigationId:n}))},t.prototype.resetStateAndUrl=function(t,e,n){this.routerState=t,this.currentUrlTree=e,this.rawUrlTree=this.urlHandlingStrategy.merge(this.currentUrlTree,n),this.resetUrlToCurrentUrlTree()},t.prototype.resetUrlToCurrentUrlTree=function(){this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree),"",{navigationId:this.lastSuccessfulId})},t}(),Je=function(){function t(t,e,n,a,r){this.router=t,this.route=e,this.commands=[],null==n&&a.setAttribute(r.nativeElement,"tabindex","0")}return Object.defineProperty(t.prototype,"routerLink",{set:function(t){this.commands=null!=t?Array.isArray(t)?t:[t]:[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"preserveQueryParams",{set:function(t){Object(i.isDevMode)()&&console&&console.warn&&console.warn("preserveQueryParams is deprecated!, use queryParamsHandling instead."),this.preserve=t},enumerable:!0,configurable:!0}),t.prototype.onClick=function(){var t={skipLocationChange:tn(this.skipLocationChange),replaceUrl:tn(this.replaceUrl)};return this.router.navigateByUrl(this.urlTree,t),!0},Object.defineProperty(t.prototype,"urlTree",{get:function(){return this.router.createUrlTree(this.commands,{relativeTo:this.route,queryParams:this.queryParams,fragment:this.fragment,preserveQueryParams:tn(this.preserve),queryParamsHandling:this.queryParamsHandling,preserveFragment:tn(this.preserveFragment)})},enumerable:!0,configurable:!0}),t}(),Qe=function(){function t(t,e,n){var a=this;this.router=t,this.route=e,this.locationStrategy=n,this.commands=[],this.subscription=t.events.subscribe(function(t){t instanceof P&&a.updateTargetUrlAndHref()})}return Object.defineProperty(t.prototype,"routerLink",{set:function(t){this.commands=null!=t?Array.isArray(t)?t:[t]:[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"preserveQueryParams",{set:function(t){Object(i.isDevMode)()&&console&&console.warn&&console.warn("preserveQueryParams is deprecated, use queryParamsHandling instead."),this.preserve=t},enumerable:!0,configurable:!0}),t.prototype.ngOnChanges=function(t){this.updateTargetUrlAndHref()},t.prototype.ngOnDestroy=function(){this.subscription.unsubscribe()},t.prototype.onClick=function(t,e,n,a){if(0!==t||e||n||a)return!0;if("string"==typeof this.target&&"_self"!=this.target)return!0;var r={skipLocationChange:tn(this.skipLocationChange),replaceUrl:tn(this.replaceUrl),state:this.state};return this.router.navigateByUrl(this.urlTree,r),!1},t.prototype.updateTargetUrlAndHref=function(){this.href=this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree))},Object.defineProperty(t.prototype,"urlTree",{get:function(){return this.router.createUrlTree(this.commands,{relativeTo:this.route,queryParams:this.queryParams,fragment:this.fragment,preserveQueryParams:tn(this.preserve),queryParamsHandling:this.queryParamsHandling,preserveFragment:tn(this.preserveFragment)})},enumerable:!0,configurable:!0}),Object(a.__decorate)([Object(i.HostBinding)("attr.target"),Object(i.Input)(),Object(a.__metadata)("design:type",String)],t.prototype,"target",void 0),t}();function tn(t){return""===t||!!t}var en=function(){function t(t,e,n,a){var r=this;this.router=t,this.element=e,this.renderer=n,this.cdr=a,this.classes=[],this.isActive=!1,this.routerLinkActiveOptions={exact:!1},this.subscription=t.events.subscribe(function(t){t instanceof P&&r.update()})}return t.prototype.ngAfterContentInit=function(){var t=this;this.links.changes.subscribe(function(e){return t.update()}),this.linksWithHrefs.changes.subscribe(function(e){return t.update()}),this.update()},Object.defineProperty(t.prototype,"routerLinkActive",{set:function(t){var e=Array.isArray(t)?t:t.split(" ");this.classes=e.filter(function(t){return!!t})},enumerable:!0,configurable:!0}),t.prototype.ngOnChanges=function(t){this.update()},t.prototype.ngOnDestroy=function(){this.subscription.unsubscribe()},t.prototype.update=function(){var t=this;this.links&&this.linksWithHrefs&&this.router.navigated&&Promise.resolve().then(function(){var e=t.hasActiveLinks();t.isActive!==e&&(t.isActive=e,t.classes.forEach(function(n){e?t.renderer.addClass(t.element.nativeElement,n):t.renderer.removeClass(t.element.nativeElement,n)}))})},t.prototype.isLinkActive=function(t){var e=this;return function(n){return t.isActive(n.urlTree,e.routerLinkActiveOptions.exact)}},t.prototype.hasActiveLinks=function(){return this.links.some(this.isLinkActive(this.router))||this.linksWithHrefs.some(this.isLinkActive(this.router))},t}(),nn=function(){return function(){this.outlet=null,this.route=null,this.resolver=null,this.children=new an,this.attachRef=null}}(),an=function(){function t(){this.contexts=new Map}return t.prototype.onChildOutletCreated=function(t,e){var n=this.getOrCreateContext(t);n.outlet=e,this.contexts.set(t,n)},t.prototype.onChildOutletDestroyed=function(t){var e=this.getContext(t);e&&(e.outlet=null)},t.prototype.onOutletDeactivated=function(){var t=this.contexts;return this.contexts=new Map,t},t.prototype.onOutletReAttached=function(t){this.contexts=t},t.prototype.getOrCreateContext=function(t){var e=this.getContext(t);return e||(e=new nn,this.contexts.set(t,e)),e},t.prototype.getContext=function(t){return this.contexts.get(t)||null},t}(),rn=function(){function t(t,e,n,a,r){this.parentContexts=t,this.location=e,this.resolver=n,this.changeDetector=r,this.activated=null,this._activatedRoute=null,this.activateEvents=new i.EventEmitter,this.deactivateEvents=new i.EventEmitter,this.name=a||X,t.onChildOutletCreated(this.name,this)}return t.prototype.ngOnDestroy=function(){this.parentContexts.onChildOutletDestroyed(this.name)},t.prototype.ngOnInit=function(){if(!this.activated){var t=this.parentContexts.getContext(this.name);t&&t.route&&(t.attachRef?this.attach(t.attachRef,t.route):this.activateWith(t.route,t.resolver||null))}},Object.defineProperty(t.prototype,"isActivated",{get:function(){return!!this.activated},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"component",{get:function(){if(!this.activated)throw new Error("Outlet is not activated");return this.activated.instance},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"activatedRoute",{get:function(){if(!this.activated)throw new Error("Outlet is not activated");return this._activatedRoute},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"activatedRouteData",{get:function(){return this._activatedRoute?this._activatedRoute.snapshot.data:{}},enumerable:!0,configurable:!0}),t.prototype.detach=function(){if(!this.activated)throw new Error("Outlet is not activated");this.location.detach();var t=this.activated;return this.activated=null,this._activatedRoute=null,t},t.prototype.attach=function(t,e){this.activated=t,this._activatedRoute=e,this.location.insert(t.hostView)},t.prototype.deactivate=function(){if(this.activated){var t=this.component;this.activated.destroy(),this.activated=null,this._activatedRoute=null,this.deactivateEvents.emit(t)}},t.prototype.activateWith=function(t,e){if(this.isActivated)throw new Error("Cannot activate an already activated outlet");this._activatedRoute=t;var n=(e=e||this.resolver).resolveComponentFactory(t._futureSnapshot.routeConfig.component),a=this.parentContexts.getOrCreateContext(this.name).children,r=new sn(t,a,this.location.injector);this.activated=this.location.createComponent(n,this.location.length,r),this.changeDetector.markForCheck(),this.activateEvents.emit(this.activated.instance)},t}(),sn=function(){function t(t,e,n){this.route=t,this.childContexts=e,this.parent=n}return t.prototype.get=function(t,e){return t===Gt?this.route:t===an?this.childContexts:this.parent.get(t,e)},t}(),on=function(){return function(){}}(),un=function(){function t(){}return t.prototype.preload=function(t,e){return e().pipe(Object(y.a)(function(){return Object(s.a)(null)}))},t}(),cn=function(){function t(){}return t.prototype.preload=function(t,e){return Object(s.a)(null)},t}(),ln=function(){function t(t,e,n,a,r){this.router=t,this.injector=a,this.preloadingStrategy=r,this.loader=new Be(e,n,function(e){return t.triggerEvent(new V(e))},function(e){return t.triggerEvent(new H(e))})}return t.prototype.setUpPreloading=function(){var t=this;this.subscription=this.router.events.pipe(Object(I.a)(function(t){return t instanceof P}),Object(C.a)(function(){return t.preload()})).subscribe(function(){})},t.prototype.preload=function(){var t=this.injector.get(i.NgModuleRef);return this.processRoutes(t,this.router.config)},t.prototype.ngOnDestroy=function(){this.subscription.unsubscribe()},t.prototype.processRoutes=function(t,e){var n,r,i=[];try{for(var s=Object(a.__values)(e),u=s.next();!u.done;u=s.next()){var c=u.value;if(c.loadChildren&&!c.canLoad&&c._loadedConfig){var l=c._loadedConfig;i.push(this.processRoutes(l.module,l.routes))}else c.loadChildren&&!c.canLoad?i.push(this.preloadConfig(t,c)):c.children&&i.push(this.processRoutes(t,c.children))}}catch(d){n={error:d}}finally{try{u&&!u.done&&(r=s.return)&&r.call(s)}finally{if(n)throw n.error}}return Object(o.a)(i).pipe(Object(A.a)(),Object(g.a)(function(t){}))},t.prototype.preloadConfig=function(t,e){var n=this;return this.preloadingStrategy.preload(e,function(){return n.loader.load(t.injector,e).pipe(Object(_.a)(function(t){return e._loadedConfig=t,n.processRoutes(t.module,t.routes)}))})},t}(),dn=function(){function t(t,e,n){void 0===n&&(n={}),this.router=t,this.viewportScroller=e,this.options=n,this.lastId=0,this.lastSource="imperative",this.restoredId=0,this.store={},n.scrollPositionRestoration=n.scrollPositionRestoration||"disabled",n.anchorScrolling=n.anchorScrolling||"disabled"}return t.prototype.init=function(){"disabled"!==this.options.scrollPositionRestoration&&this.viewportScroller.setHistoryScrollRestoration("manual"),this.routerEventsSubscription=this.createScrollEvents(),this.scrollEventsSubscription=this.consumeScrollEvents()},t.prototype.createScrollEvents=function(){var t=this;return this.router.events.subscribe(function(e){e instanceof L?(t.store[t.lastId]=t.viewportScroller.getScrollPosition(),t.lastSource=e.navigationTrigger,t.restoredId=e.restoredState?e.restoredState.navigationId:0):e instanceof P&&(t.lastId=e.id,t.scheduleScrollEvent(e,t.router.parseUrl(e.urlAfterRedirects).fragment))})},t.prototype.consumeScrollEvents=function(){var t=this;return this.router.events.subscribe(function(e){e instanceof $&&(e.position?"top"===t.options.scrollPositionRestoration?t.viewportScroller.scrollToPosition([0,0]):"enabled"===t.options.scrollPositionRestoration&&t.viewportScroller.scrollToPosition(e.position):e.anchor&&"enabled"===t.options.anchorScrolling?t.viewportScroller.scrollToAnchor(e.anchor):"disabled"!==t.options.scrollPositionRestoration&&t.viewportScroller.scrollToPosition([0,0]))})},t.prototype.scheduleScrollEvent=function(t,e){this.router.triggerEvent(new $(t,"popstate"===this.lastSource?this.store[this.restoredId]:null,e))},t.prototype.ngOnDestroy=function(){this.routerEventsSubscription&&this.routerEventsSubscription.unsubscribe(),this.scrollEventsSubscription&&this.scrollEventsSubscription.unsubscribe()},t}(),fn=new i.InjectionToken("ROUTER_CONFIGURATION"),pn=new i.InjectionToken("ROUTER_FORROOT_GUARD"),hn=[r.Location,{provide:vt,useClass:_t},{provide:Xe,useFactory:xn,deps:[i.ApplicationRef,vt,an,r.Location,i.Injector,i.NgModuleFactoryLoader,i.Compiler,He,fn,[Ue,new i.Optional],[Ye,new i.Optional]]},an,{provide:Gt,useFactory:Tn,deps:[Xe]},{provide:i.NgModuleFactoryLoader,useClass:i.SystemJsNgModuleLoader},ln,cn,un,{provide:fn,useValue:{enableTracing:!1}}];function gn(){return new i.NgProbeToken("Router",Xe)}var bn=function(){function t(t,e){}var e;return e=t,t.forRoot=function(t,n){return{ngModule:e,providers:[hn,_n(t),{provide:pn,useFactory:vn,deps:[[Xe,new i.Optional,new i.SkipSelf]]},{provide:fn,useValue:n||{}},{provide:r.LocationStrategy,useFactory:yn,deps:[r.PlatformLocation,[new i.Inject(r.APP_BASE_HREF),new i.Optional],fn]},{provide:dn,useFactory:mn,deps:[Xe,r.ViewportScroller,fn]},{provide:on,useExisting:n&&n.preloadingStrategy?n.preloadingStrategy:cn},{provide:i.NgProbeToken,multi:!0,useFactory:gn},[wn,{provide:i.APP_INITIALIZER,multi:!0,useFactory:Sn,deps:[wn]},{provide:In,useFactory:On,deps:[wn]},{provide:i.APP_BOOTSTRAP_LISTENER,multi:!0,useExisting:In}]]}},t.forChild=function(t){return{ngModule:e,providers:[_n(t)]}},t}();function mn(t,e,n){return n.scrollOffset&&e.setOffset(n.scrollOffset),new dn(t,e,n)}function yn(t,e,n){return void 0===n&&(n={}),n.useHash?new r.HashLocationStrategy(t,e):new r.PathLocationStrategy(t,e)}function vn(t){if(t)throw new Error("RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.");return"guarded"}function _n(t){return[{provide:i.ANALYZE_FOR_ENTRY_COMPONENTS,multi:!0,useValue:t},{provide:He,multi:!0,useValue:t}]}function xn(t,e,n,a,r,i,s,o,u,c,l){void 0===u&&(u={});var d=new Xe(null,e,n,a,r,i,s,ct(o));if(c&&(d.urlHandlingStrategy=c),l&&(d.routeReuseStrategy=l),u.errorHandler&&(d.errorHandler=u.errorHandler),u.malformedUriErrorHandler&&(d.malformedUriErrorHandler=u.malformedUriErrorHandler),u.enableTracing){var f=Object(D["\u0275getDOM"])();d.events.subscribe(function(t){f.logGroup("Router Event: "+t.constructor.name),f.log(t.toString()),f.log(t),f.logGroupEnd()})}return u.onSameUrlNavigation&&(d.onSameUrlNavigation=u.onSameUrlNavigation),u.paramsInheritanceStrategy&&(d.paramsInheritanceStrategy=u.paramsInheritanceStrategy),u.urlUpdateStrategy&&(d.urlUpdateStrategy=u.urlUpdateStrategy),u.relativeLinkResolution&&(d.relativeLinkResolution=u.relativeLinkResolution),d}function Tn(t){return t.routerState.root}var wn=function(){function t(t){this.injector=t,this.initNavigation=!1,this.resultOfPreactivationDone=new p.a}return t.prototype.appInitializer=function(){var t=this;return this.injector.get(r.LOCATION_INITIALIZED,Promise.resolve(null)).then(function(){var e=null,n=new Promise(function(t){return e=t}),a=t.injector.get(Xe),r=t.injector.get(fn);if(t.isLegacyDisabled(r)||t.isLegacyEnabled(r))e(!0);else if("disabled"===r.initialNavigation)a.setUpLocationChangeListener(),e(!0);else{if("enabled"!==r.initialNavigation)throw new Error("Invalid initialNavigation options: '"+r.initialNavigation+"'");a.hooks.afterPreactivation=function(){return t.initNavigation?Object(s.a)(null):(t.initNavigation=!0,e(!0),t.resultOfPreactivationDone)},a.initialNavigation()}return n})},t.prototype.bootstrapListener=function(t){var e=this.injector.get(fn),n=this.injector.get(ln),a=this.injector.get(dn),r=this.injector.get(Xe),s=this.injector.get(i.ApplicationRef);t===s.components[0]&&(this.isLegacyEnabled(e)?r.initialNavigation():this.isLegacyDisabled(e)&&r.setUpLocationChangeListener(),n.setUpPreloading(),a.init(),r.resetRootComponentType(s.componentTypes[0]),this.resultOfPreactivationDone.next(null),this.resultOfPreactivationDone.complete())},t.prototype.isLegacyEnabled=function(t){return"legacy_enabled"===t.initialNavigation||!0===t.initialNavigation||void 0===t.initialNavigation},t.prototype.isLegacyDisabled=function(t){return"legacy_disabled"===t.initialNavigation||!1===t.initialNavigation},t}();function Sn(t){return t.appInitializer.bind(t)}function On(t){return t.bootstrapListener.bind(t)}var In=new i.InjectionToken("Router Initializer")},ZYjt:function(t,e,n){"use strict";n.r(e),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_c",function(){return kt}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_b",function(){return Ct}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_a",function(){return It}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_k",function(){return d}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_d",function(){return Rt}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_i",function(){return w}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_h",function(){return T}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_e",function(){return Dt}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_f",function(){return Vt}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_j",function(){return R}),n.d(e,"\u0275angular_packages_platform_browser_platform_browser_g",function(){return L}),n.d(e,"BrowserModule",function(){return Nt}),n.d(e,"platformBrowser",function(){return St}),n.d(e,"Meta",function(){return At}),n.d(e,"Title",function(){return Et}),n.d(e,"disableDebugTools",function(){return Ft}),n.d(e,"enableDebugTools",function(){return jt}),n.d(e,"BrowserTransferStateModule",function(){return Ht}),n.d(e,"TransferState",function(){return Yt}),n.d(e,"makeStateKey",function(){return Gt}),n.d(e,"By",function(){return Bt}),n.d(e,"DOCUMENT",function(){return y}),n.d(e,"EVENT_MANAGER_PLUGINS",function(){return D}),n.d(e,"EventManager",function(){return E}),n.d(e,"HAMMER_GESTURE_CONFIG",function(){return ot}),n.d(e,"HAMMER_LOADER",function(){return ut}),n.d(e,"HammerGestureConfig",function(){return ct}),n.d(e,"DomSanitizer",function(){return ht}),n.d(e,"VERSION",function(){return Ut}),n.d(e,"\u0275BROWSER_SANITIZATION_PROVIDERS",function(){return wt}),n.d(e,"\u0275INTERNAL_BROWSER_PLATFORM_PROVIDERS",function(){return Tt}),n.d(e,"\u0275initDomAdapter",function(){return Ot}),n.d(e,"\u0275BrowserDomAdapter",function(){return b}),n.d(e,"\u0275BrowserPlatformLocation",function(){return _}),n.d(e,"\u0275TRANSITION_ID",function(){return x}),n.d(e,"\u0275BrowserGetTestability",function(){return S}),n.d(e,"\u0275escapeHtml",function(){return zt}),n.d(e,"\u0275ELEMENT_PROBE_PROVIDERS",function(){return A}),n.d(e,"\u0275DomAdapter",function(){return l}),n.d(e,"\u0275getDOM",function(){return o}),n.d(e,"\u0275setRootDomAdapter",function(){return u}),n.d(e,"\u0275DomRendererFactory2",function(){return B}),n.d(e,"\u0275NAMESPACE_URIS",function(){return q}),n.d(e,"\u0275flattenStyles",function(){return V}),n.d(e,"\u0275shimContentAttribute",function(){return G}),n.d(e,"\u0275shimHostAttribute",function(){return Y}),n.d(e,"\u0275DomEventsPlugin",function(){return it}),n.d(e,"\u0275HammerGesturesPlugin",function(){return lt}),n.d(e,"\u0275KeyEventsPlugin",function(){return pt}),n.d(e,"\u0275DomSharedStylesHost",function(){return M}),n.d(e,"\u0275SharedStylesHost",function(){return P}),n.d(e,"\u0275DomSanitizerImpl",function(){return gt});var a=n("mrSG"),r=n("Ip0R"),i=n("CcnG"),s=null;function o(){return s}function u(t){s||(s=t)}var c,l=function(){function t(){this.resourceLoaderType=null}return Object.defineProperty(t.prototype,"attrToPropMap",{get:function(){return this._attrToPropMap},set:function(t){this._attrToPropMap=t},enumerable:!0,configurable:!0}),t}(),d=function(t){function e(){var e=t.call(this)||this;e._animationPrefix=null,e._transitionEnd=null;try{var n=e.createElement("div",document);if(null!=e.getStyle(n,"animationName"))e._animationPrefix="";else for(var a=["Webkit","Moz","O","ms"],r=0;r<a.length;r++)if(null!=e.getStyle(n,a[r]+"AnimationName")){e._animationPrefix="-"+a[r].toLowerCase()+"-";break}var i={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};Object.keys(i).forEach(function(t){null!=e.getStyle(n,t)&&(e._transitionEnd=i[t])})}catch(s){e._animationPrefix=null,e._transitionEnd=null}return e}return Object(a.__extends)(e,t),e.prototype.getDistributedNodes=function(t){return t.getDistributedNodes()},e.prototype.resolveAndSetHref=function(t,e,n){t.href=null==n?e:e+"/../"+n},e.prototype.supportsDOMEvents=function(){return!0},e.prototype.supportsNativeShadowDOM=function(){return"function"==typeof document.body.createShadowRoot},e.prototype.getAnimationPrefix=function(){return this._animationPrefix?this._animationPrefix:""},e.prototype.getTransitionEnd=function(){return this._transitionEnd?this._transitionEnd:""},e.prototype.supportsAnimation=function(){return null!=this._animationPrefix&&null!=this._transitionEnd},e}(l),f={class:"className",innerHtml:"innerHTML",readonly:"readOnly",tabindex:"tabIndex"},p={"\b":"Backspace","\t":"Tab","\x7f":"Delete","\x1b":"Escape",Del:"Delete",Esc:"Escape",Left:"ArrowLeft",Right:"ArrowRight",Up:"ArrowUp",Down:"ArrowDown",Menu:"ContextMenu",Scroll:"ScrollLock",Win:"OS"},h={A:"1",B:"2",C:"3",D:"4",E:"5",F:"6",G:"7",H:"8",I:"9",J:"*",K:"+",M:"-",N:".",O:"/","`":"0","\x90":"NumLock"};i["\u0275global"].Node&&(c=i["\u0275global"].Node.prototype.contains||function(t){return!!(16&this.compareDocumentPosition(t))});var g,b=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.parse=function(t){throw new Error("parse not implemented")},e.makeCurrent=function(){u(new e)},e.prototype.hasProperty=function(t,e){return e in t},e.prototype.setProperty=function(t,e,n){t[e]=n},e.prototype.getProperty=function(t,e){return t[e]},e.prototype.invoke=function(t,e,n){var r;(r=t)[e].apply(r,Object(a.__spread)(n))},e.prototype.logError=function(t){window.console&&(console.error?console.error(t):console.log(t))},e.prototype.log=function(t){window.console&&window.console.log&&window.console.log(t)},e.prototype.logGroup=function(t){window.console&&window.console.group&&window.console.group(t)},e.prototype.logGroupEnd=function(){window.console&&window.console.groupEnd&&window.console.groupEnd()},Object.defineProperty(e.prototype,"attrToPropMap",{get:function(){return f},enumerable:!0,configurable:!0}),e.prototype.contains=function(t,e){return c.call(t,e)},e.prototype.querySelector=function(t,e){return t.querySelector(e)},e.prototype.querySelectorAll=function(t,e){return t.querySelectorAll(e)},e.prototype.on=function(t,e,n){t.addEventListener(e,n,!1)},e.prototype.onAndCancel=function(t,e,n){return t.addEventListener(e,n,!1),function(){t.removeEventListener(e,n,!1)}},e.prototype.dispatchEvent=function(t,e){t.dispatchEvent(e)},e.prototype.createMouseEvent=function(t){var e=this.getDefaultDocument().createEvent("MouseEvent");return e.initEvent(t,!0,!0),e},e.prototype.createEvent=function(t){var e=this.getDefaultDocument().createEvent("Event");return e.initEvent(t,!0,!0),e},e.prototype.preventDefault=function(t){t.preventDefault(),t.returnValue=!1},e.prototype.isPrevented=function(t){return t.defaultPrevented||null!=t.returnValue&&!t.returnValue},e.prototype.getInnerHTML=function(t){return t.innerHTML},e.prototype.getTemplateContent=function(t){return"content"in t&&this.isTemplateElement(t)?t.content:null},e.prototype.getOuterHTML=function(t){return t.outerHTML},e.prototype.nodeName=function(t){return t.nodeName},e.prototype.nodeValue=function(t){return t.nodeValue},e.prototype.type=function(t){return t.type},e.prototype.content=function(t){return this.hasProperty(t,"content")?t.content:t},e.prototype.firstChild=function(t){return t.firstChild},e.prototype.nextSibling=function(t){return t.nextSibling},e.prototype.parentElement=function(t){return t.parentNode},e.prototype.childNodes=function(t){return t.childNodes},e.prototype.childNodesAsList=function(t){for(var e=t.childNodes,n=new Array(e.length),a=0;a<e.length;a++)n[a]=e[a];return n},e.prototype.clearNodes=function(t){for(;t.firstChild;)t.removeChild(t.firstChild)},e.prototype.appendChild=function(t,e){t.appendChild(e)},e.prototype.removeChild=function(t,e){t.removeChild(e)},e.prototype.replaceChild=function(t,e,n){t.replaceChild(e,n)},e.prototype.remove=function(t){return t.parentNode&&t.parentNode.removeChild(t),t},e.prototype.insertBefore=function(t,e,n){t.insertBefore(n,e)},e.prototype.insertAllBefore=function(t,e,n){n.forEach(function(n){return t.insertBefore(n,e)})},e.prototype.insertAfter=function(t,e,n){t.insertBefore(n,e.nextSibling)},e.prototype.setInnerHTML=function(t,e){t.innerHTML=e},e.prototype.getText=function(t){return t.textContent},e.prototype.setText=function(t,e){t.textContent=e},e.prototype.getValue=function(t){return t.value},e.prototype.setValue=function(t,e){t.value=e},e.prototype.getChecked=function(t){return t.checked},e.prototype.setChecked=function(t,e){t.checked=e},e.prototype.createComment=function(t){return this.getDefaultDocument().createComment(t)},e.prototype.createTemplate=function(t){var e=this.getDefaultDocument().createElement("template");return e.innerHTML=t,e},e.prototype.createElement=function(t,e){return(e=e||this.getDefaultDocument()).createElement(t)},e.prototype.createElementNS=function(t,e,n){return(n=n||this.getDefaultDocument()).createElementNS(t,e)},e.prototype.createTextNode=function(t,e){return(e=e||this.getDefaultDocument()).createTextNode(t)},e.prototype.createScriptTag=function(t,e,n){var a=(n=n||this.getDefaultDocument()).createElement("SCRIPT");return a.setAttribute(t,e),a},e.prototype.createStyleElement=function(t,e){var n=(e=e||this.getDefaultDocument()).createElement("style");return this.appendChild(n,this.createTextNode(t,e)),n},e.prototype.createShadowRoot=function(t){return t.createShadowRoot()},e.prototype.getShadowRoot=function(t){return t.shadowRoot},e.prototype.getHost=function(t){return t.host},e.prototype.clone=function(t){return t.cloneNode(!0)},e.prototype.getElementsByClassName=function(t,e){return t.getElementsByClassName(e)},e.prototype.getElementsByTagName=function(t,e){return t.getElementsByTagName(e)},e.prototype.classList=function(t){return Array.prototype.slice.call(t.classList,0)},e.prototype.addClass=function(t,e){t.classList.add(e)},e.prototype.removeClass=function(t,e){t.classList.remove(e)},e.prototype.hasClass=function(t,e){return t.classList.contains(e)},e.prototype.setStyle=function(t,e,n){t.style[e]=n},e.prototype.removeStyle=function(t,e){t.style[e]=""},e.prototype.getStyle=function(t,e){return t.style[e]},e.prototype.hasStyle=function(t,e,n){var a=this.getStyle(t,e)||"";return n?a==n:a.length>0},e.prototype.tagName=function(t){return t.tagName},e.prototype.attributeMap=function(t){for(var e=new Map,n=t.attributes,a=0;a<n.length;a++){var r=n.item(a);e.set(r.name,r.value)}return e},e.prototype.hasAttribute=function(t,e){return t.hasAttribute(e)},e.prototype.hasAttributeNS=function(t,e,n){return t.hasAttributeNS(e,n)},e.prototype.getAttribute=function(t,e){return t.getAttribute(e)},e.prototype.getAttributeNS=function(t,e,n){return t.getAttributeNS(e,n)},e.prototype.setAttribute=function(t,e,n){t.setAttribute(e,n)},e.prototype.setAttributeNS=function(t,e,n,a){t.setAttributeNS(e,n,a)},e.prototype.removeAttribute=function(t,e){t.removeAttribute(e)},e.prototype.removeAttributeNS=function(t,e,n){t.removeAttributeNS(e,n)},e.prototype.templateAwareRoot=function(t){return this.isTemplateElement(t)?this.content(t):t},e.prototype.createHtmlDocument=function(){return document.implementation.createHTMLDocument("fakeTitle")},e.prototype.getDefaultDocument=function(){return document},e.prototype.getBoundingClientRect=function(t){try{return t.getBoundingClientRect()}catch(e){return{top:0,bottom:0,left:0,right:0,width:0,height:0}}},e.prototype.getTitle=function(t){return t.title},e.prototype.setTitle=function(t,e){t.title=e||""},e.prototype.elementMatches=function(t,e){return!!this.isElementNode(t)&&(t.matches&&t.matches(e)||t.msMatchesSelector&&t.msMatchesSelector(e)||t.webkitMatchesSelector&&t.webkitMatchesSelector(e))},e.prototype.isTemplateElement=function(t){return this.isElementNode(t)&&"TEMPLATE"===t.nodeName},e.prototype.isTextNode=function(t){return t.nodeType===Node.TEXT_NODE},e.prototype.isCommentNode=function(t){return t.nodeType===Node.COMMENT_NODE},e.prototype.isElementNode=function(t){return t.nodeType===Node.ELEMENT_NODE},e.prototype.hasShadowRoot=function(t){return null!=t.shadowRoot&&t instanceof HTMLElement},e.prototype.isShadowRoot=function(t){return t instanceof DocumentFragment},e.prototype.importIntoDoc=function(t){return document.importNode(this.templateAwareRoot(t),!0)},e.prototype.adoptNode=function(t){return document.adoptNode(t)},e.prototype.getHref=function(t){return t.getAttribute("href")},e.prototype.getEventKey=function(t){var e=t.key;if(null==e){if(null==(e=t.keyIdentifier))return"Unidentified";e.startsWith("U+")&&(e=String.fromCharCode(parseInt(e.substring(2),16)),3===t.location&&h.hasOwnProperty(e)&&(e=h[e]))}return p[e]||e},e.prototype.getGlobalEventTarget=function(t,e){return"window"===e?window:"document"===e?t:"body"===e?t.body:null},e.prototype.getHistory=function(){return window.history},e.prototype.getLocation=function(){return window.location},e.prototype.getBaseHref=function(t){var e,n=m||(m=document.querySelector("base"))?m.getAttribute("href"):null;return null==n?null:(e=n,g||(g=document.createElement("a")),g.setAttribute("href",e),"/"===g.pathname.charAt(0)?g.pathname:"/"+g.pathname)},e.prototype.resetBaseElement=function(){m=null},e.prototype.getUserAgent=function(){return window.navigator.userAgent},e.prototype.setData=function(t,e,n){this.setAttribute(t,"data-"+e,n)},e.prototype.getData=function(t,e){return this.getAttribute(t,"data-"+e)},e.prototype.getComputedStyle=function(t){return getComputedStyle(t)},e.prototype.supportsWebAnimation=function(){return"function"==typeof Element.prototype.animate},e.prototype.performanceNow=function(){return window.performance&&window.performance.now?window.performance.now():(new Date).getTime()},e.prototype.supportsCookies=function(){return!0},e.prototype.getCookie=function(t){return Object(r["\u0275parseCookieValue"])(document.cookie,t)},e.prototype.setCookie=function(t,e){document.cookie=encodeURIComponent(t)+"="+encodeURIComponent(e)},e}(d),m=null,y=r.DOCUMENT;function v(){return!!window.history.pushState}var _=function(t){function e(e){var n=t.call(this)||this;return n._doc=e,n._init(),n}return Object(a.__extends)(e,t),e.prototype._init=function(){this.location=o().getLocation(),this._history=o().getHistory()},e.prototype.getBaseHrefFromDOM=function(){return o().getBaseHref(this._doc)},e.prototype.onPopState=function(t){o().getGlobalEventTarget(this._doc,"window").addEventListener("popstate",t,!1)},e.prototype.onHashChange=function(t){o().getGlobalEventTarget(this._doc,"window").addEventListener("hashchange",t,!1)},Object.defineProperty(e.prototype,"pathname",{get:function(){return this.location.pathname},set:function(t){this.location.pathname=t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"search",{get:function(){return this.location.search},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hash",{get:function(){return this.location.hash},enumerable:!0,configurable:!0}),e.prototype.pushState=function(t,e,n){v()?this._history.pushState(t,e,n):this.location.hash=n},e.prototype.replaceState=function(t,e,n){v()?this._history.replaceState(t,e,n):this.location.hash=n},e.prototype.forward=function(){this._history.forward()},e.prototype.back=function(){this._history.back()},Object(a.__decorate)([Object(a.__param)(0,Object(i.Inject)(y)),Object(a.__metadata)("design:paramtypes",[Object])],e)}(r.PlatformLocation),x=new i.InjectionToken("TRANSITION_ID");function T(t,e,n){return function(){n.get(i.ApplicationInitStatus).donePromise.then(function(){var n=o();Array.prototype.slice.apply(n.querySelectorAll(e,"style[ng-transition]")).filter(function(e){return n.getAttribute(e,"ng-transition")===t}).forEach(function(t){return n.remove(t)})})}}var w=[{provide:i.APP_INITIALIZER,useFactory:T,deps:[x,y,i.Injector],multi:!0}],S=function(){function t(){}return t.init=function(){Object(i.setTestabilityGetter)(new t)},t.prototype.addToWindow=function(t){i["\u0275global"].getAngularTestability=function(e,n){void 0===n&&(n=!0);var a=t.findTestabilityInTree(e,n);if(null==a)throw new Error("Could not find testability for element.");return a},i["\u0275global"].getAllAngularTestabilities=function(){return t.getAllTestabilities()},i["\u0275global"].getAllAngularRootElements=function(){return t.getAllRootElements()},i["\u0275global"].frameworkStabilizers||(i["\u0275global"].frameworkStabilizers=[]),i["\u0275global"].frameworkStabilizers.push(function(t){var e=i["\u0275global"].getAllAngularTestabilities(),n=e.length,a=!1,r=function(e){a=a||e,0==--n&&t(a)};e.forEach(function(t){t.whenStable(r)})})},t.prototype.findTestabilityInTree=function(t,e,n){if(null==e)return null;var a=t.getTestability(e);return null!=a?a:n?o().isShadowRoot(e)?this.findTestabilityInTree(t,o().getHost(e),!0):this.findTestabilityInTree(t,o().parentElement(e),!0):null},t}();function O(t,e){"undefined"!=typeof COMPILED&&COMPILED||((i["\u0275global"].ng=i["\u0275global"].ng||{})[t]=e)}var I={ApplicationRef:i.ApplicationRef,NgZone:i.NgZone},C="probe",k="coreTokens";function N(t){return Object(i.getDebugNode)(t)}function R(t){return O(C,N),O(k,Object(a.__assign)({},I,(t||[]).reduce(function(t,e){return t[e.name]=e.token,t},{}))),function(){return N}}var A=[{provide:i.APP_INITIALIZER,useFactory:R,deps:[[i.NgProbeToken,new i.Optional]],multi:!0}],D=new i.InjectionToken("EventManagerPlugins"),E=function(){function t(t,e){var n=this;this._zone=e,this._eventNameToPlugin=new Map,t.forEach(function(t){return t.manager=n}),this._plugins=t.slice().reverse()}return t.prototype.addEventListener=function(t,e,n){return this._findPluginFor(e).addEventListener(t,e,n)},t.prototype.addGlobalEventListener=function(t,e,n){return this._findPluginFor(e).addGlobalEventListener(t,e,n)},t.prototype.getZone=function(){return this._zone},t.prototype._findPluginFor=function(t){var e=this._eventNameToPlugin.get(t);if(e)return e;for(var n=this._plugins,a=0;a<n.length;a++){var r=n[a];if(r.supports(t))return this._eventNameToPlugin.set(t,r),r}throw new Error("No event manager plugin found for event "+t)},t}(),L=function(){function t(t){this._doc=t}return t.prototype.addGlobalEventListener=function(t,e,n){var a=o().getGlobalEventTarget(this._doc,t);if(!a)throw new Error("Unsupported event target "+a+" for event "+e);return this.addEventListener(a,e,n)},t}(),P=function(){function t(){this._stylesSet=new Set}return t.prototype.addStyles=function(t){var e=this,n=new Set;t.forEach(function(t){e._stylesSet.has(t)||(e._stylesSet.add(t),n.add(t))}),this.onStylesAdded(n)},t.prototype.onStylesAdded=function(t){},t.prototype.getAllStyles=function(){return Array.from(this._stylesSet)},t}(),M=function(t){function e(e){var n=t.call(this)||this;return n._doc=e,n._hostNodes=new Set,n._styleNodes=new Set,n._hostNodes.add(e.head),n}return Object(a.__extends)(e,t),e.prototype._addStylesToHost=function(t,e){var n=this;t.forEach(function(t){var a=n._doc.createElement("style");a.textContent=t,n._styleNodes.add(e.appendChild(a))})},e.prototype.addHost=function(t){this._addStylesToHost(this._stylesSet,t),this._hostNodes.add(t)},e.prototype.removeHost=function(t){this._hostNodes.delete(t)},e.prototype.onStylesAdded=function(t){var e=this;this._hostNodes.forEach(function(n){return e._addStylesToHost(t,n)})},e.prototype.ngOnDestroy=function(){this._styleNodes.forEach(function(t){return o().remove(t)})},e}(P),q={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},j=/%COMP%/g,F="_nghost-%COMP%",z="_ngcontent-%COMP%";function G(t){return z.replace(j,t)}function Y(t){return F.replace(j,t)}function V(t,e,n){for(var a=0;a<e.length;a++){var r=e[a];Array.isArray(r)?V(t,r,n):(r=r.replace(j,t),n.push(r))}return n}function H(t){return function(e){!1===t(e)&&(e.preventDefault(),e.returnValue=!1)}}var B=function(){function t(t,e){this.eventManager=t,this.sharedStylesHost=e,this.rendererByCompId=new Map,this.defaultRenderer=new U(t)}return t.prototype.createRenderer=function(t,e){if(!t||!e)return this.defaultRenderer;switch(e.encapsulation){case i.ViewEncapsulation.Emulated:var n=this.rendererByCompId.get(e.id);return n||(n=new Z(this.eventManager,this.sharedStylesHost,e),this.rendererByCompId.set(e.id,n)),n.applyToHost(t),n;case i.ViewEncapsulation.Native:case i.ViewEncapsulation.ShadowDom:return new X(this.eventManager,this.sharedStylesHost,t,e);default:if(!this.rendererByCompId.has(e.id)){var a=V(e.id,e.styles,[]);this.sharedStylesHost.addStyles(a),this.rendererByCompId.set(e.id,this.defaultRenderer)}return this.defaultRenderer}},t.prototype.begin=function(){},t.prototype.end=function(){},t}(),U=function(){function t(t){this.eventManager=t,this.data=Object.create(null)}return t.prototype.destroy=function(){},t.prototype.createElement=function(t,e){return e?document.createElementNS(q[e],t):document.createElement(t)},t.prototype.createComment=function(t){return document.createComment(t)},t.prototype.createText=function(t){return document.createTextNode(t)},t.prototype.appendChild=function(t,e){t.appendChild(e)},t.prototype.insertBefore=function(t,e,n){t&&t.insertBefore(e,n)},t.prototype.removeChild=function(t,e){t&&t.removeChild(e)},t.prototype.selectRootElement=function(t,e){var n="string"==typeof t?document.querySelector(t):t;if(!n)throw new Error('The selector "'+t+'" did not match any elements');return e||(n.textContent=""),n},t.prototype.parentNode=function(t){return t.parentNode},t.prototype.nextSibling=function(t){return t.nextSibling},t.prototype.setAttribute=function(t,e,n,a){if(a){e=a+":"+e;var r=q[a];r?t.setAttributeNS(r,e,n):t.setAttribute(e,n)}else t.setAttribute(e,n)},t.prototype.removeAttribute=function(t,e,n){if(n){var a=q[n];a?t.removeAttributeNS(a,e):t.removeAttribute(n+":"+e)}else t.removeAttribute(e)},t.prototype.addClass=function(t,e){t.classList.add(e)},t.prototype.removeClass=function(t,e){t.classList.remove(e)},t.prototype.setStyle=function(t,e,n,a){a&i.RendererStyleFlags2.DashCase?t.style.setProperty(e,n,a&i.RendererStyleFlags2.Important?"important":""):t.style[e]=n},t.prototype.removeStyle=function(t,e,n){n&i.RendererStyleFlags2.DashCase?t.style.removeProperty(e):t.style[e]=""},t.prototype.setProperty=function(t,e,n){K(e,"property"),t[e]=n},t.prototype.setValue=function(t,e){t.nodeValue=e},t.prototype.listen=function(t,e,n){return K(e,"listener"),"string"==typeof t?this.eventManager.addGlobalEventListener(t,e,H(n)):this.eventManager.addEventListener(t,e,H(n))},t}(),W="@".charCodeAt(0);function K(t,e){if(t.charCodeAt(0)===W)throw new Error("Found the synthetic "+e+" "+t+'. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.')}var $,Z=function(t){function e(e,n,a){var r=t.call(this,e)||this;r.component=a;var i=V(a.id,a.styles,[]);return n.addStyles(i),r.contentAttr=G(a.id),r.hostAttr=Y(a.id),r}return Object(a.__extends)(e,t),e.prototype.applyToHost=function(e){t.prototype.setAttribute.call(this,e,this.hostAttr,"")},e.prototype.createElement=function(e,n){var a=t.prototype.createElement.call(this,e,n);return t.prototype.setAttribute.call(this,a,this.contentAttr,""),a},e}(U),X=function(t){function e(e,n,a,r){var s=t.call(this,e)||this;s.sharedStylesHost=n,s.hostEl=a,s.component=r,s.shadowRoot=r.encapsulation===i.ViewEncapsulation.ShadowDom?a.attachShadow({mode:"open"}):a.createShadowRoot(),s.sharedStylesHost.addHost(s.shadowRoot);for(var o=V(r.id,r.styles,[]),u=0;u<o.length;u++){var c=document.createElement("style");c.textContent=o[u],s.shadowRoot.appendChild(c)}return s}return Object(a.__extends)(e,t),e.prototype.nodeOrShadowRoot=function(t){return t===this.hostEl?this.shadowRoot:t},e.prototype.destroy=function(){this.sharedStylesHost.removeHost(this.shadowRoot)},e.prototype.appendChild=function(e,n){return t.prototype.appendChild.call(this,this.nodeOrShadowRoot(e),n)},e.prototype.insertBefore=function(e,n,a){return t.prototype.insertBefore.call(this,this.nodeOrShadowRoot(e),n,a)},e.prototype.removeChild=function(e,n){return t.prototype.removeChild.call(this,this.nodeOrShadowRoot(e),n)},e.prototype.parentNode=function(e){return this.nodeOrShadowRoot(t.prototype.parentNode.call(this,this.nodeOrShadowRoot(e)))},e}(U),J="undefined"!=typeof Zone&&Zone.__symbol__||function(t){return"__zone_symbol__"+t},Q=J("addEventListener"),tt=J("removeEventListener"),et={},nt="__zone_symbol__propagationStopped";"undefined"!=typeof Zone&&Zone[J("BLACK_LISTED_EVENTS")]&&($={});var at=function(t){return!!$&&$.hasOwnProperty(t)},rt=function(t){var e=et[t.type];if(e){var n=this[e];if(n){var a=[t];if(1===n.length)return(s=n[0]).zone!==Zone.current?s.zone.run(s.handler,this,a):s.handler.apply(this,a);for(var r=n.slice(),i=0;i<r.length&&!0!==t[nt];i++){var s;(s=r[i]).zone!==Zone.current?s.zone.run(s.handler,this,a):s.handler.apply(this,a)}}}},it=function(t){function e(e,n,a){var i=t.call(this,e)||this;return i.ngZone=n,a&&Object(r.isPlatformServer)(a)||i.patchEvent(),i}return Object(a.__extends)(e,t),e.prototype.patchEvent=function(){if("undefined"!=typeof Event&&Event&&Event.prototype&&!Event.prototype.__zone_symbol__stopImmediatePropagation){var t=Event.prototype.__zone_symbol__stopImmediatePropagation=Event.prototype.stopImmediatePropagation;Event.prototype.stopImmediatePropagation=function(){this&&(this[nt]=!0),t&&t.apply(this,arguments)}}},e.prototype.supports=function(t){return!0},e.prototype.addEventListener=function(t,e,n){var a=this,r=n;if(!t[Q]||i.NgZone.isInAngularZone()&&!at(e))t.addEventListener(e,r,!1);else{var s=et[e];s||(s=et[e]=J("ANGULAR"+e+"FALSE"));var o=t[s],u=o&&o.length>0;o||(o=t[s]=[]);var c=at(e)?Zone.root:Zone.current;if(0===o.length)o.push({zone:c,handler:r});else{for(var l=!1,d=0;d<o.length;d++)if(o[d].handler===r){l=!0;break}l||o.push({zone:c,handler:r})}u||t[Q](e,rt,!1)}return function(){return a.removeEventListener(t,e,r)}},e.prototype.removeEventListener=function(t,e,n){var a=t[tt];if(!a)return t.removeEventListener.apply(t,[e,n,!1]);var r=et[e],i=r&&t[r];if(!i)return t.removeEventListener.apply(t,[e,n,!1]);for(var s=!1,o=0;o<i.length;o++)if(i[o].handler===n){s=!0,i.splice(o,1);break}s?0===i.length&&a.apply(t,[e,rt,!1]):t.removeEventListener.apply(t,[e,n,!1])},e}(L),st={pan:!0,panstart:!0,panmove:!0,panend:!0,pancancel:!0,panleft:!0,panright:!0,panup:!0,pandown:!0,pinch:!0,pinchstart:!0,pinchmove:!0,pinchend:!0,pinchcancel:!0,pinchin:!0,pinchout:!0,press:!0,pressup:!0,rotate:!0,rotatestart:!0,rotatemove:!0,rotateend:!0,rotatecancel:!0,swipe:!0,swipeleft:!0,swiperight:!0,swipeup:!0,swipedown:!0,tap:!0},ot=new i.InjectionToken("HammerGestureConfig"),ut=new i.InjectionToken("HammerLoader"),ct=function(){function t(){this.events=[],this.overrides={}}return t.prototype.buildHammer=function(t){var e=new Hammer(t,this.options);for(var n in e.get("pinch").set({enable:!0}),e.get("rotate").set({enable:!0}),this.overrides)e.get(n).set(this.overrides[n]);return e},t}(),lt=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i._config=n,i.console=a,i.loader=r,i}return Object(a.__extends)(e,t),e.prototype.supports=function(t){return!(!st.hasOwnProperty(t.toLowerCase())&&!this.isCustomEvent(t)||!window.Hammer&&!this.loader&&(this.console.warn('The "'+t+'" event cannot be bound because Hammer.JS is not loaded and no custom loader has been specified.'),1))},e.prototype.addEventListener=function(t,e,n){var a=this,r=this.manager.getZone();if(e=e.toLowerCase(),!window.Hammer&&this.loader){var i=!1,s=function(){i=!0};return this.loader().then(function(){if(!window.Hammer)return a.console.warn("The custom HAMMER_LOADER completed, but Hammer.JS is not present."),void(s=function(){});i||(s=a.addEventListener(t,e,n))}).catch(function(){a.console.warn('The "'+e+'" event cannot be bound because the custom Hammer.JS loader failed.'),s=function(){}}),function(){s()}}return r.runOutsideAngular(function(){var i=a._config.buildHammer(t),s=function(t){r.runGuarded(function(){n(t)})};return i.on(e,s),function(){i.off(e,s),"function"==typeof i.destroy&&i.destroy()}})},e.prototype.isCustomEvent=function(t){return this._config.events.indexOf(t)>-1},e}(L),dt=["alt","control","meta","shift"],ft={alt:function(t){return t.altKey},control:function(t){return t.ctrlKey},meta:function(t){return t.metaKey},shift:function(t){return t.shiftKey}},pt=function(t){function e(e){return t.call(this,e)||this}var n;return Object(a.__extends)(e,t),n=e,e.prototype.supports=function(t){return null!=n.parseEventName(t)},e.prototype.addEventListener=function(t,e,a){var r=n.parseEventName(e),i=n.eventCallback(r.fullKey,a,this.manager.getZone());return this.manager.getZone().runOutsideAngular(function(){return o().onAndCancel(t,r.domEventName,i)})},e.parseEventName=function(t){var e=t.toLowerCase().split("."),a=e.shift();if(0===e.length||"keydown"!==a&&"keyup"!==a)return null;var r=n._normalizeKey(e.pop()),i="";if(dt.forEach(function(t){var n=e.indexOf(t);n>-1&&(e.splice(n,1),i+=t+".")}),i+=r,0!=e.length||0===r.length)return null;var s={};return s.domEventName=a,s.fullKey=i,s},e.getEventFullKey=function(t){var e="",n=o().getEventKey(t);return" "===(n=n.toLowerCase())?n="space":"."===n&&(n="dot"),dt.forEach(function(a){a!=n&&(0,ft[a])(t)&&(e+=a+".")}),e+=n},e.eventCallback=function(t,e,a){return function(r){n.getEventFullKey(r)===t&&a.runGuarded(function(){return e(r)})}},e._normalizeKey=function(t){switch(t){case"esc":return"escape";default:return t}},e}(L),ht=function(){return function(){}}(),gt=function(t){function e(e){var n=t.call(this)||this;return n._doc=e,n}return Object(a.__extends)(e,t),e.prototype.sanitize=function(t,e){if(null==e)return null;switch(t){case i.SecurityContext.NONE:return e;case i.SecurityContext.HTML:return e instanceof mt?e.changingThisBreaksApplicationSecurity:(this.checkNotSafeValue(e,"HTML"),Object(i["\u0275_sanitizeHtml"])(this._doc,String(e)));case i.SecurityContext.STYLE:return e instanceof yt?e.changingThisBreaksApplicationSecurity:(this.checkNotSafeValue(e,"Style"),Object(i["\u0275_sanitizeStyle"])(e));case i.SecurityContext.SCRIPT:if(e instanceof vt)return e.changingThisBreaksApplicationSecurity;throw this.checkNotSafeValue(e,"Script"),new Error("unsafe value used in a script context");case i.SecurityContext.URL:return e instanceof xt||e instanceof _t?e.changingThisBreaksApplicationSecurity:(this.checkNotSafeValue(e,"URL"),Object(i["\u0275_sanitizeUrl"])(String(e)));case i.SecurityContext.RESOURCE_URL:if(e instanceof xt)return e.changingThisBreaksApplicationSecurity;throw this.checkNotSafeValue(e,"ResourceURL"),new Error("unsafe value used in a resource URL context (see http://g.co/ng/security#xss)");default:throw new Error("Unexpected SecurityContext "+t+" (see http://g.co/ng/security#xss)")}},e.prototype.checkNotSafeValue=function(t,e){if(t instanceof bt)throw new Error("Required a safe "+e+", got a "+t.getTypeName()+" (see http://g.co/ng/security#xss)")},e.prototype.bypassSecurityTrustHtml=function(t){return new mt(t)},e.prototype.bypassSecurityTrustStyle=function(t){return new yt(t)},e.prototype.bypassSecurityTrustScript=function(t){return new vt(t)},e.prototype.bypassSecurityTrustUrl=function(t){return new _t(t)},e.prototype.bypassSecurityTrustResourceUrl=function(t){return new xt(t)},e}(ht),bt=function(){function t(t){this.changingThisBreaksApplicationSecurity=t}return t.prototype.toString=function(){return"SafeValue must use [property]=binding: "+this.changingThisBreaksApplicationSecurity+" (see http://g.co/ng/security#xss)"},t}(),mt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.getTypeName=function(){return"HTML"},e}(bt),yt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.getTypeName=function(){return"Style"},e}(bt),vt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.getTypeName=function(){return"Script"},e}(bt),_t=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.getTypeName=function(){return"URL"},e}(bt),xt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.getTypeName=function(){return"ResourceURL"},e}(bt),Tt=[{provide:i.PLATFORM_ID,useValue:r["\u0275PLATFORM_BROWSER_ID"]},{provide:i.PLATFORM_INITIALIZER,useValue:Ot,multi:!0},{provide:r.PlatformLocation,useClass:_,deps:[y]},{provide:y,useFactory:Ct,deps:[]}],wt=[{provide:i.Sanitizer,useExisting:ht},{provide:ht,useClass:gt,deps:[y]}],St=Object(i.createPlatformFactory)(i.platformCore,"browser",Tt);function Ot(){b.makeCurrent(),S.init()}function It(){return new i.ErrorHandler}function Ct(){return document}var kt=[wt,{provide:i["\u0275APP_ROOT"],useValue:!0},{provide:i.ErrorHandler,useFactory:It,deps:[]},{provide:D,useClass:it,multi:!0,deps:[y,i.NgZone,i.PLATFORM_ID]},{provide:D,useClass:pt,multi:!0,deps:[y]},{provide:D,useClass:lt,multi:!0,deps:[y,ot,i["\u0275Console"],[new i.Optional,ut]]},{provide:ot,useClass:ct,deps:[]},{provide:B,useClass:B,deps:[E,M]},{provide:i.RendererFactory2,useExisting:B},{provide:P,useExisting:M},{provide:M,useClass:M,deps:[y]},{provide:i.Testability,useClass:i.Testability,deps:[i.NgZone]},{provide:E,useClass:E,deps:[D,i.NgZone]},A],Nt=function(){function t(t){if(t)throw new Error("BrowserModule has already been loaded. If you need access to common directives such as NgIf and NgFor from a lazy loaded module, import CommonModule instead.")}var e;return e=t,t.withServerTransition=function(t){return{ngModule:e,providers:[{provide:i.APP_ID,useValue:t.appId},{provide:x,useExisting:i.APP_ID},w]}},t}();function Rt(){return new At(Object(i.inject)(y))}var At=function(){function t(t){this._doc=t,this._dom=o()}return t.prototype.addTag=function(t,e){return void 0===e&&(e=!1),t?this._getOrCreateElement(t,e):null},t.prototype.addTags=function(t,e){var n=this;return void 0===e&&(e=!1),t?t.reduce(function(t,a){return a&&t.push(n._getOrCreateElement(a,e)),t},[]):[]},t.prototype.getTag=function(t){return t&&this._dom.querySelector(this._doc,"meta["+t+"]")||null},t.prototype.getTags=function(t){if(!t)return[];var e=this._dom.querySelectorAll(this._doc,"meta["+t+"]");return e?[].slice.call(e):[]},t.prototype.updateTag=function(t,e){if(!t)return null;e=e||this._parseSelector(t);var n=this.getTag(e);return n?this._setMetaElementAttributes(t,n):this._getOrCreateElement(t,!0)},t.prototype.removeTag=function(t){this.removeTagElement(this.getTag(t))},t.prototype.removeTagElement=function(t){t&&this._dom.remove(t)},t.prototype._getOrCreateElement=function(t,e){if(void 0===e&&(e=!1),!e){var n=this._parseSelector(t),a=this.getTag(n);if(a&&this._containsAttributes(t,a))return a}var r=this._dom.createElement("meta");this._setMetaElementAttributes(t,r);var i=this._dom.getElementsByTagName(this._doc,"head")[0];return this._dom.appendChild(i,r),r},t.prototype._setMetaElementAttributes=function(t,e){var n=this;return Object.keys(t).forEach(function(a){return n._dom.setAttribute(e,a,t[a])}),e},t.prototype._parseSelector=function(t){var e=t.name?"name":"property";return e+'="'+t[e]+'"'},t.prototype._containsAttributes=function(t,e){var n=this;return Object.keys(t).every(function(a){return n._dom.getAttribute(e,a)===t[a]})},t.ngInjectableDef=Object(i.defineInjectable)({factory:Rt,token:t,providedIn:"root"}),t}();function Dt(){return new Et(Object(i.inject)(y))}var Et=function(){function t(t){this._doc=t}return t.prototype.getTitle=function(){return o().getTitle(this._doc)},t.prototype.setTitle=function(t){o().setTitle(this._doc,t)},t.ngInjectableDef=Object(i.defineInjectable)({factory:Dt,token:t,providedIn:"root"}),t}(),Lt="undefined"!=typeof window&&window||{},Pt=function(){return function(t,e){this.msPerTick=t,this.numTicks=e}}(),Mt=function(){function t(t){this.appRef=t.injector.get(i.ApplicationRef)}return t.prototype.timeChangeDetection=function(t){var e=t&&t.record,n=null!=Lt.console.profile;e&&n&&Lt.console.profile("Change Detection");for(var a=o().performanceNow(),r=0;r<5||o().performanceNow()-a<500;)this.appRef.tick(),r++;var i=o().performanceNow();e&&n&&Lt.console.profileEnd("Change Detection");var s=(i-a)/r;return Lt.console.log("ran "+r+" change detection cycles"),Lt.console.log(s.toFixed(2)+" ms per check"),new Pt(s,r)},t}(),qt="profiler";function jt(t){return O(qt,new Mt(t)),t}function Ft(){O(qt,null)}function zt(t){var e={"&":"&a;",'"':"&q;","'":"&s;","<":"&l;",">":"&g;"};return t.replace(/[&"'<>]/g,function(t){return e[t]})}function Gt(t){return t}var Yt=function(){function t(){this.store={},this.onSerializeCallbacks={}}var e;return e=t,t.init=function(t){var n=new e;return n.store=t,n},t.prototype.get=function(t,e){return void 0!==this.store[t]?this.store[t]:e},t.prototype.set=function(t,e){this.store[t]=e},t.prototype.remove=function(t){delete this.store[t]},t.prototype.hasKey=function(t){return this.store.hasOwnProperty(t)},t.prototype.onSerialize=function(t,e){this.onSerializeCallbacks[t]=e},t.prototype.toJson=function(){for(var t in this.onSerializeCallbacks)if(this.onSerializeCallbacks.hasOwnProperty(t))try{this.store[t]=this.onSerializeCallbacks[t]()}catch(e){console.warn("Exception in onSerialize callback: ",e)}return JSON.stringify(this.store)},t}();function Vt(t,e){var n,a=t.getElementById(e+"-state"),r={};if(a&&a.textContent)try{r=JSON.parse((n={"&a;":"&","&q;":'"',"&s;":"'","&l;":"<","&g;":">"},a.textContent.replace(/&[^;]+;/g,function(t){return n[t]})))}catch(i){console.warn("Exception while restoring TransferState for app "+e,i)}return Yt.init(r)}var Ht=function(){return function(){}}(),Bt=function(){function t(){}return t.all=function(){return function(t){return!0}},t.css=function(t){return function(e){return null!=e.nativeElement&&o().elementMatches(e.nativeElement,t)}},t.directive=function(t){return function(e){return-1!==e.providerTokens.indexOf(t)}},t}(),Ut=new i.Version("7.2.6")},Zduo:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_a\u016dgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_a\u016dg_sep_okt_nov_dec".split("_"),weekdays:"diman\u0109o_lundo_mardo_merkredo_\u0135a\u016ddo_vendredo_sabato".split("_"),weekdaysShort:"dim_lun_mard_merk_\u0135a\u016d_ven_sab".split("_"),weekdaysMin:"di_lu_ma_me_\u0135a_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D[-a de] MMMM, YYYY",LLL:"D[-a de] MMMM, YYYY HH:mm",LLLL:"dddd, [la] D[-a de] MMMM, YYYY HH:mm"},meridiemParse:/[ap]\.t\.m/i,isPM:function(t){return"p"===t.charAt(0).toLowerCase()},meridiem:function(t,e,n){return t>11?n?"p.t.m.":"P.T.M.":n?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodia\u016d je] LT",nextDay:"[Morga\u016d je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hiera\u016d je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"post %s",past:"anta\u016d %s",s:"sekundoj",ss:"%d sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},dayOfMonthOrdinalParse:/\d{1,2}a/,ordinal:"%da",week:{dow:1,doy:7}})}()},Zn8D:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("psW0"),r=n("mChF");function i(t){return void 0===t&&(t=Number.POSITIVE_INFINITY),Object(a.a)(r.a,t)}},a0VL:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(t){this.datePipe=t}return t.prototype.transform=function(t){return null===t||""===t?"":this.datePipe.transform(t,"shortDate")+" "+this.datePipe.transform(t,"mediumTime")},t}()},a278:function(t,e,n){"use strict";var a=n("CcnG"),r=n("QC43"),i=n("XFyV"),s=n("TZo1"),o=n("9Kw/"),u=n("Jm/i"),c=n("gIcY"),l=n("ANnk"),d=n("f/UV"),f=n("aexS"),p=n("Ip0R");n("insk"),n("mSOc"),n("ZYjt"),n("20UP"),n("+0ag"),n.d(e,"a",function(){return h}),n.d(e,"b",function(){return _});var h=a["\u0275crt"]({encapsulation:0,styles:[[".grafana[_ngcontent-%COMP%]{width:100%;height:600px;z-index:0}.grafana_one[_ngcontent-%COMP%]{height:400px}.grafana_two[_ngcontent-%COMP%]{height:750px}.grafana_three[_ngcontent-%COMP%]{height:900px}.timepicker[_ngcontent-%COMP%] select[_ngcontent-%COMP%]{display:inline-block}.timepicker[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{font-size:1.05em;padding:5px!important}button[_ngcontent-%COMP%]{margin-bottom:10px;margin-left:10px;float:right}button[_ngcontent-%COMP%] i[_ngcontent-%COMP%]{font-size:14px;padding:2px}.dropdown-menu[_ngcontent-%COMP%]{top:20px;right:20px;left:auto}"]],data:{}});function g(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"cd-loading-panel",[],null,null,null,r.b,r.a)),a["\u0275did"](1,49152,null,0,i.a,[],null,null),(t()(),a["\u0275ted"](-1,0,["Loading panel data..."]))],null,null)}function b(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"cd-info-panel",[],null,null,null,s.b,s.a)),a["\u0275did"](1,49152,null,0,o.a,[u.a],null,null),(t()(),a["\u0275ted"](-1,0,["Please consult the "])),(t()(),a["\u0275eld"](3,0,null,0,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["documentation"])),(t()(),a["\u0275ted"](-1,0,[" on how to configure and enable the monitoring functionality."]))],null,function(t,e){t(e,3,0,a["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function m(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"cd-info-panel",[],null,null,null,s.b,s.a)),a["\u0275did"](1,49152,null,0,o.a,[u.a],null,null),(t()(),a["\u0275ted"](-1,0,["Grafana Dashboard doesn't exist. Please refer to "])),(t()(),a["\u0275eld"](3,0,null,0,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["documentation"])),(t()(),a["\u0275ted"](-1,0,[" on how to add dashboards to Grafana."]))],null,function(t,e){t(e,3,0,a["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),a["\u0275did"](1,147456,null,0,c.v,[a.ElementRef,a.Renderer2,[2,c.z]],{ngValue:[0,"ngValue"]},null),a["\u0275did"](2,147456,null,0,c.G,[a.ElementRef,a.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),a["\u0275ted"](3,null,[""," "]))],function(t,e){t(e,1,0,e.context.$implicit.value),t(e,2,0,e.context.$implicit.value)},function(t,e){t(e,3,0,e.context.$implicit.name)})}function v(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,21,"div",[["class","row"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,16,"div",[["class","col-md-12 timepicker"]],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,2,"label",[["class","control-label col-sm-1"],["for","timepicker-control"]],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Grafana Time Picker"])),(t()(),a["\u0275eld"](5,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,8,"select",[["class","form-control "],["id","timepicker"],["name","timepicker-control"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"change"],[null,"blur"]],function(t,e,n){var r=!0,i=t.component;return"change"===e&&(r=!1!==a["\u0275nov"](t,7).onChange(n.target.value)&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,7).onTouched()&&r),"ngModelChange"===e&&(r=!1!==(i.time=n)&&r),"ngModelChange"===e&&(r=!1!==i.onTimepickerChange(n)&&r),r},null,null)),a["\u0275did"](7,16384,null,0,c.z,[a.Renderer2,a.ElementRef],null,null),a["\u0275prd"](1024,null,c.p,function(t){return[t]},[c.z]),a["\u0275did"](9,671744,null,0,c.u,[[8,null],[8,null],[8,null],[6,c.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),a["\u0275prd"](2048,null,c.q,null,[c.u]),a["\u0275did"](11,16384,null,0,c.r,[[4,c.q]],null,null),a["\u0275did"](12,4210688,null,0,l.a,[[2,d.a],f.a,a.ElementRef],null,null),(t()(),a["\u0275and"](16777216,null,null,1,null,y)),a["\u0275did"](14,278528,null,0,p.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275eld"](15,0,null,null,1,"button",[["class","btn btn-sm"],["title","Reset Settings"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.reset()&&a),a},null,null)),(t()(),a["\u0275eld"](16,0,null,null,0,"i",[["class","fa fa-undo"]],null,null,null,null,null)),(t()(),a["\u0275eld"](17,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),a["\u0275eld"](18,0,null,null,3,"div",[["class","col-md-12"]],null,null,null,null,null)),(t()(),a["\u0275eld"](19,0,null,null,2,"div",[["class","grafana-container"]],null,null,null,null,null)),(t()(),a["\u0275eld"](20,0,[["iframe",1]],null,1,"iframe",[["class","grafana"],["frameborder","0"],["id","iframe"],["scrolling","no"]],[[8,"src",5]],null,null,null,null)),a["\u0275did"](21,278528,null,0,p.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null)],function(t,e){var n=e.component;t(e,9,0,"timepicker-control",n.time),t(e,14,0,n.grafanaTimes),t(e,21,0,"grafana",n.panelStyle)},function(t,e){var n=e.component;t(e,6,0,a["\u0275nov"](e,11).ngClassUntouched,a["\u0275nov"](e,11).ngClassTouched,a["\u0275nov"](e,11).ngClassPristine,a["\u0275nov"](e,11).ngClassDirty,a["\u0275nov"](e,11).ngClassValid,a["\u0275nov"](e,11).ngClassInvalid,a["\u0275nov"](e,11).ngClassPending),t(e,20,0,n.grafanaSrc)})}function _(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,g)),a["\u0275did"](1,16384,null,0,p.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,b)),a["\u0275did"](3,16384,null,0,p.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,m)),a["\u0275did"](5,16384,null,0,p.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,v)),a["\u0275did"](7,16384,null,0,p.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.loading&&n.grafanaExist),t(e,3,0,!n.grafanaExist),t(e,5,0,!n.dashboardExist),t(e,7,0,n.grafanaExist&&n.dashboardExist)},null)}},a40w:function(t,e,n){"use strict";var a=n("CcnG"),r=n("EEJc"),i=n("ajRT"),s=n("gIcY"),o=n("Ip0R"),u=n("gp3X"),c=n("sb0X"),l=n("KVJa"),d=n("Z21x"),f=n("sne2"),p=n("OLbh"),h=n("DQlY");n.d(e,"a",function(){return v});var g=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function b(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function m(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,19,"cd-modal",[],null,[[null,"hide"]],function(t,e,n){var a=!0;return"hide"===e&&(a=!1!==t.component.cancel()&&a),a},r.c,r.b)),a["\u0275did"](1,49152,null,0,i.a,[],null,{hide:"hide"}),(t()(),a["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(t()(),a["\u0275ted"](3,null,["",""])),(t()(),a["\u0275eld"](4,0,null,1,15,null,null,null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,14,"form",[["class","form-horizontal"],["name","confirmationForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var r=!0;return"submit"===e&&(r=!1!==a["\u0275nov"](t,7).onSubmit(n)&&r),"reset"===e&&(r=!1!==a["\u0275nov"](t,7).onReset()&&r),r},null,null)),a["\u0275did"](6,16384,null,0,s.D,[],null,null),a["\u0275did"](7,540672,[["formDir",4]],0,s.l,[[8,null],[8,null]],{form:[0,"form"]},null),a["\u0275prd"](2048,null,s.d,null,[s.l]),a["\u0275did"](9,16384,null,0,s.s,[[4,s.d]],null,null),(t()(),a["\u0275eld"](10,0,null,null,2,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,b)),a["\u0275did"](12,540672,null,0,o.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),(t()(),a["\u0275eld"](13,0,null,null,6,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),a["\u0275eld"](14,0,null,null,5,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),a["\u0275eld"](15,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0,r=t.component;return"submitAction"===e&&(a=!1!==r.onSubmit(r.confirmationForm.value)&&a),a},u.b,u.a)),a["\u0275did"](16,114688,null,0,c.a,[a.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),a["\u0275ted"](17,0,[" "," "])),(t()(),a["\u0275eld"](18,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,l.b,l.a)),a["\u0275did"](19,49152,null,0,d.a,[o.Location,f.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,7,0,n.confirmationForm),t(e,12,0,n.bodyContext,n.bodyTpl),t(e,16,0,n.confirmationForm),t(e,19,0,"Cancel",n.boundCancel)},function(t,e){var n=e.component;t(e,3,0,n.titleText),t(e,5,0,a["\u0275nov"](e,9).ngClassUntouched,a["\u0275nov"](e,9).ngClassTouched,a["\u0275nov"](e,9).ngClassPristine,a["\u0275nov"](e,9).ngClassDirty,a["\u0275nov"](e,9).ngClassValid,a["\u0275nov"](e,9).ngClassInvalid,a["\u0275nov"](e,9).ngClassPending),t(e,17,0,n.buttonText)})}function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"cd-confirmation-modal",[],null,null,null,m,g)),a["\u0275did"](1,114688,null,0,p.a,[h.a],null,null)],function(t,e){t(e,1,0)},null)}var v=a["\u0275ccf"]("cd-confirmation-modal",p.a,y,{},{},[])},a96k:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(t,e,n,a){void 0===a&&(a=!0),this.selected=t,this.name=e,this.description=n,this.enabled=a}}()},aB2c:function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),t.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:r.Line,dataElementType:r.Point,linkScales:i.noop,update:function(t){var e=this,n=e.getMeta(),a=n.data,r=n.dataset.custom||{},s=e.getDataset(),o=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),i.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:i.valueOrDefault(s.lineTension,o.tension),backgroundColor:r.backgroundColor?r.backgroundColor:s.backgroundColor||o.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:s.borderWidth||o.borderWidth,borderColor:r.borderColor?r.borderColor:s.borderColor||o.borderColor,fill:r.fill?r.fill:void 0!==s.fill?s.fill:o.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:s.borderCapStyle||o.borderCapStyle,borderDash:r.borderDash?r.borderDash:s.borderDash||o.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:s.borderDashOffset||o.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:s.borderJoinStyle||o.borderJoinStyle}}),n.dataset.pivot(),i.each(a,function(n,a){e.updateElement(n,a,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var a=this,r=t.custom||{},s=a.getDataset(),o=a.chart.scale,u=a.chart.options.elements.point,c=o.getPointPositionForValue(e,s.data[e]);void 0!==s.radius&&void 0===s.pointRadius&&(s.pointRadius=s.radius),void 0!==s.hitRadius&&void 0===s.pointHitRadius&&(s.pointHitRadius=s.hitRadius),i.extend(t,{_datasetIndex:a.index,_index:e,_scale:o,_model:{x:n?o.xCenter:c.x,y:n?o.yCenter:c.y,tension:r.tension?r.tension:i.valueOrDefault(s.lineTension,a.chart.options.elements.line.tension),radius:r.radius?r.radius:i.valueAtIndexOrDefault(s.pointRadius,e,u.radius),backgroundColor:r.backgroundColor?r.backgroundColor:i.valueAtIndexOrDefault(s.pointBackgroundColor,e,u.backgroundColor),borderColor:r.borderColor?r.borderColor:i.valueAtIndexOrDefault(s.pointBorderColor,e,u.borderColor),borderWidth:r.borderWidth?r.borderWidth:i.valueAtIndexOrDefault(s.pointBorderWidth,e,u.borderWidth),pointStyle:r.pointStyle?r.pointStyle:i.valueAtIndexOrDefault(s.pointStyle,e,u.pointStyle),rotation:r.rotation?r.rotation:i.valueAtIndexOrDefault(s.pointRotation,e,u.rotation),hitRadius:r.hitRadius?r.hitRadius:i.valueAtIndexOrDefault(s.pointHitRadius,e,u.hitRadius)}}),t._model.skip=r.skip?r.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();i.each(e.data,function(n,a){var r=n._model,s=i.splineCurve(i.previousItem(e.data,a,!0)._model,r,i.nextItem(e.data,a,!0)._model,r.tension);r.controlPointPreviousX=Math.max(Math.min(s.previous.x,t.right),t.left),r.controlPointPreviousY=Math.max(Math.min(s.previous.y,t.bottom),t.top),r.controlPointNextX=Math.max(Math.min(s.next.x,t.right),t.left),r.controlPointNextY=Math.max(Math.min(s.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},a=t._index,r=t._model;t.$previousStyle={backgroundColor:r.backgroundColor,borderColor:r.borderColor,borderWidth:r.borderWidth,radius:r.radius},r.radius=n.hoverRadius?n.hoverRadius:i.valueAtIndexOrDefault(e.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),r.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:i.valueAtIndexOrDefault(e.pointHoverBackgroundColor,a,i.getHoverColor(r.backgroundColor)),r.borderColor=n.hoverBorderColor?n.hoverBorderColor:i.valueAtIndexOrDefault(e.pointHoverBorderColor,a,i.getHoverColor(r.borderColor)),r.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:i.valueAtIndexOrDefault(e.pointHoverBorderWidth,a,r.borderWidth)}})}},aGNc:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t){return function(e){return e.lift(new s(t))}}var s=function(){function t(t){this.value=t}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.value))},t}(),o=function(t){function e(e,n){var a=t.call(this,e)||this;return a.value=n,a}return a.__extends(e,t),e.prototype._next=function(t){this.destination.next(this.value)},e}(r.a)},aIdf:function(t,e,n){!function(t){"use strict";function e(t,e,n){return t+" "+function(t,e){return 2===e?function(t){var e={m:"v",b:"v",d:"z"};return void 0===e[t.charAt(0)]?t:e[t.charAt(0)]+t.substring(1)}(t):t}({mm:"munutenn",MM:"miz",dd:"devezh"}[n],t)}n("wd/R").defineLocale("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h[e]mm A",LTS:"h[e]mm:ss A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY h[e]mm A",LLLL:"dddd, D [a viz] MMMM YYYY h[e]mm A"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondenno\xf9",ss:"%d eilenn",m:"ur vunutenn",mm:e,h:"un eur",hh:"%d eur",d:"un devezh",dd:e,M:"ur miz",MM:e,y:"ur bloaz",yy:function(t){switch(function t(e){return e>9?t(e%10):e}(t)){case 1:case 3:case 4:case 5:case 9:return t+" bloaz";default:return t+" vloaz"}}},dayOfMonthOrdinalParse:/\d{1,2}(a\xf1|vet)/,ordinal:function(t){return t+(1===t?"a\xf1":"vet")},week:{dow:1,doy:4}})}()},aIsn:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("mi",{months:"Kohi-t\u0101te_Hui-tanguru_Pout\u016b-te-rangi_Paenga-wh\u0101wh\u0101_Haratua_Pipiri_H\u014dngoingoi_Here-turi-k\u014dk\u0101_Mahuru_Whiringa-\u0101-nuku_Whiringa-\u0101-rangi_Hakihea".split("_"),monthsShort:"Kohi_Hui_Pou_Pae_Hara_Pipi_H\u014dngoi_Here_Mahu_Whi-nu_Whi-ra_Haki".split("_"),monthsRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,monthsShortStrictRegex:/(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,weekdays:"R\u0101tapu_Mane_T\u016brei_Wenerei_T\u0101ite_Paraire_H\u0101tarei".split("_"),weekdaysShort:"Ta_Ma_T\u016b_We_T\u0101i_Pa_H\u0101".split("_"),weekdaysMin:"Ta_Ma_T\u016b_We_T\u0101i_Pa_H\u0101".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [i] HH:mm",LLLL:"dddd, D MMMM YYYY [i] HH:mm"},calendar:{sameDay:"[i teie mahana, i] LT",nextDay:"[apopo i] LT",nextWeek:"dddd [i] LT",lastDay:"[inanahi i] LT",lastWeek:"dddd [whakamutunga i] LT",sameElse:"L"},relativeTime:{future:"i roto i %s",past:"%s i mua",s:"te h\u0113kona ruarua",ss:"%d h\u0113kona",m:"he meneti",mm:"%d meneti",h:"te haora",hh:"%d haora",d:"he ra",dd:"%d ra",M:"he marama",MM:"%d marama",y:"he tau",yy:"%d tau"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},aQkU:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("mk",{months:"\u0458\u0430\u043d\u0443\u0430\u0440\u0438_\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0438\u043b_\u043c\u0430\u0458_\u0458\u0443\u043d\u0438_\u0458\u0443\u043b\u0438_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438_\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438_\u043d\u043e\u0435\u043c\u0432\u0440\u0438_\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438".split("_"),monthsShort:"\u0458\u0430\u043d_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0458_\u0458\u0443\u043d_\u0458\u0443\u043b_\u0430\u0432\u0433_\u0441\u0435\u043f_\u043e\u043a\u0442_\u043d\u043e\u0435_\u0434\u0435\u043a".split("_"),weekdays:"\u043d\u0435\u0434\u0435\u043b\u0430_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0440\u0442\u043e\u043a_\u043f\u0435\u0442\u043e\u043a_\u0441\u0430\u0431\u043e\u0442\u0430".split("_"),weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0442\u043e_\u0441\u0440\u0435_\u0447\u0435\u0442_\u043f\u0435\u0442_\u0441\u0430\u0431".split("_"),weekdaysMin:"\u043de_\u043fo_\u0432\u0442_\u0441\u0440_\u0447\u0435_\u043f\u0435_\u0441a".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[\u0414\u0435\u043d\u0435\u0441 \u0432\u043e] LT",nextDay:"[\u0423\u0442\u0440\u0435 \u0432\u043e] LT",nextWeek:"[\u0412\u043e] dddd [\u0432\u043e] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432\u043e] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[\u0418\u0437\u043c\u0438\u043d\u0430\u0442\u0430\u0442\u0430] dddd [\u0432\u043e] LT";case 1:case 2:case 4:case 5:return"[\u0418\u0437\u043c\u0438\u043d\u0430\u0442\u0438\u043e\u0442] dddd [\u0432\u043e] LT"}},sameElse:"L"},relativeTime:{future:"\u043f\u043e\u0441\u043b\u0435 %s",past:"\u043f\u0440\u0435\u0434 %s",s:"\u043d\u0435\u043a\u043e\u043b\u043a\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0438",ss:"%d \u0441\u0435\u043a\u0443\u043d\u0434\u0438",m:"\u043c\u0438\u043d\u0443\u0442\u0430",mm:"%d \u043c\u0438\u043d\u0443\u0442\u0438",h:"\u0447\u0430\u0441",hh:"%d \u0447\u0430\u0441\u0430",d:"\u0434\u0435\u043d",dd:"%d \u0434\u0435\u043d\u0430",M:"\u043c\u0435\u0441\u0435\u0446",MM:"%d \u043c\u0435\u0441\u0435\u0446\u0438",y:"\u0433\u043e\u0434\u0438\u043d\u0430",yy:"%d \u0433\u043e\u0434\u0438\u043d\u0438"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0435\u0432|\u0435\u043d|\u0442\u0438|\u0432\u0438|\u0440\u0438|\u043c\u0438)/,ordinal:function(t){var e=t%10,n=t%100;return 0===t?t+"-\u0435\u0432":0===n?t+"-\u0435\u043d":n>10&&n<20?t+"-\u0442\u0438":1===e?t+"-\u0432\u0438":2===e?t+"-\u0440\u0438":7===e||8===e?t+"-\u043c\u0438":t+"-\u0442\u0438"},week:{dow:1,doy:7}})}()},aTeT:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.multi="multi"}(e.SortType||(e.SortType={}))},aXbf:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("LvDl"),r=n("CcnG"),i=function(){function t(){}return t.prototype.format_number=function(t,e,n,r){if(void 0===r&&(r=1),a.isString(t)&&(t=Number(t)),!a.isNumber(t))return"-";var i=t<1?0:Math.floor(Math.log(t)/Math.log(e));i=i>=n.length?n.length-1:i;var s=a.round(t/Math.pow(e,i),r).toString();return""===s?"-":(""!==n[i]&&(s=s+" "+n[i]),s)},t.prototype.toBytes=function(t,e){void 0===e&&(e=null);var n=["b","k","m","g","t","p","e","z","y"],r=RegExp("^(\\d+(.\\d+)?) ?(["+n.join("")+"]?(b|ib|B/s)?)?$","i").exec(t);if(null===r)return e;var i=parseFloat(r[1]);return a.isString(r[3])&&(i*=Math.pow(1024,n.indexOf(r[3].toLowerCase()[0]))),Math.round(i)},t.prototype.toMilliseconds=function(t){var e=/^\s*(\d+)\s*(ms)?\s*$/i.exec(t);return null!==e?+e[1]:0},t.prototype.toIops=function(t){var e=/^\s*(\d+)\s*(IOPS)?\s*$/i.exec(t);return null!==e?+e[1]:0},t.ngInjectableDef=r.defineInjectable({factory:function(){return new t},token:t,providedIn:"root"}),t}()},ad02:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t,e){return function(n){return n.lift(new s(t,e))}}var s=function(){function t(t,e){this.compare=t,this.keySelector=e}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.compare,this.keySelector))},t}(),o=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.keySelector=a,r.hasKey=!1,"function"==typeof n&&(r.compare=n),r}return a.__extends(e,t),e.prototype.compare=function(t,e){return t===e},e.prototype._next=function(t){var e;try{var n=this.keySelector;e=n?n(t):t}catch(r){return this.destination.error(r)}var a=!1;if(this.hasKey)try{a=(0,this.compare)(this.key,e)}catch(r){return this.destination.error(r)}else this.hasKey=!0;a||(this.key=e,this.destination.next(t))},e}(r.a)},ae7Z:function(t,e,n){"use strict";function a(t){var e={left:[],center:[],right:[]};if(t)for(var n=0,a=t;n<a.length;n++){var r=a[n];r.frozenLeft?e.left.push(r):r.frozenRight?e.right.push(r):e.center.push(r)}return e}function r(t,e){var n=0;if(t)for(var a=0,r=t;a<r.length;a++){var i=r[a];n+=parseFloat(e&&i[e]?i[e]:i.width)}return n}Object.defineProperty(e,"__esModule",{value:!0}),e.columnsByPin=a,e.columnGroupWidths=function(t,e){return{left:r(t.left),center:r(t.center),right:r(t.right),total:Math.floor(r(e))}},e.columnTotalWidth=r,e.columnsTotalWidth=function(t,e){for(var n=0,a=0,r=t;a<r.length;a++){var i=r[a];n+=e&&i[e]?i[e]:i.width}return n},e.columnsByPinArr=function(t){var e=[],n=a(t);return e.push({type:"left",columns:n.left}),e.push({type:"center",columns:n.center}),e.push({type:"right",columns:n.right}),e}},aexS:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("jKX/"),r=n("CcnG"),i=function(){function t(){}return t.prototype.set=function(t,e){void 0===e&&(e={}),localStorage.setItem("dashboard_username",t),localStorage.setItem("dashboard_permissions",JSON.stringify(new a.a(e)))},t.prototype.remove=function(){localStorage.removeItem("dashboard_username")},t.prototype.isLoggedIn=function(){return null!==localStorage.getItem("dashboard_username")},t.prototype.getUsername=function(){return localStorage.getItem("dashboard_username")},t.prototype.getPermissions=function(){return JSON.parse(localStorage.getItem("dashboard_permissions")||JSON.stringify(new a.a({})))},t.ngInjectableDef=r.defineInjectable({factory:function(){return new t},token:t,providedIn:"root"}),t}()},ahDk:function(t,e,n){"use strict";n.r(e);var a=n("mrSG"),r=n("MGBS"),i=n("zotm");function s(t){return function(e){return e.lift(new o(t))}}var o=function(){function t(t){this.durationSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.durationSelector))},t}(),u=function(t){function e(e,n){var a=t.call(this,e)||this;return a.durationSelector=n,a.hasValue=!1,a}return a.__extends(e,t),e.prototype._next=function(t){if(this.value=t,this.hasValue=!0,!this.throttled){var e=void 0;try{e=(0,this.durationSelector)(t)}catch(a){return this.destination.error(a)}var n=Object(i.a)(this,e);!n||n.closed?this.clearThrottle():this.add(this.throttled=n)}},e.prototype.clearThrottle=function(){var t=this.value,e=this.hasValue,n=this.throttled;n&&(this.remove(n),this.throttled=null,n.unsubscribe()),e&&(this.value=null,this.hasValue=!1,this.destination.next(t))},e.prototype.notifyNext=function(t,e,n,a){this.clearThrottle()},e.prototype.notifyComplete=function(){this.clearThrottle()},e}(r.a),c=n("T1DM"),l=n("gI3B");function d(t,e){return void 0===e&&(e=c.a),s(function(){return Object(l.a)(t,e)})}function f(t){return function(e){return e.lift(new p(t))}}var p=function(){function t(t){this.closingNotifier=t}return t.prototype.call=function(t,e){return e.subscribe(new h(t,this.closingNotifier))},t}(),h=function(t){function e(e,n){var a=t.call(this,e)||this;return a.buffer=[],a.add(Object(i.a)(a,n)),a}return a.__extends(e,t),e.prototype._next=function(t){this.buffer.push(t)},e.prototype.notifyNext=function(t,e,n,a,r){var i=this.buffer;this.buffer=[],this.destination.next(i)},e}(r.a),g=n("FFOo");function b(t,e){return void 0===e&&(e=null),function(n){return n.lift(new m(t,e))}}var m=function(){function t(t,e){this.bufferSize=t,this.startBufferEvery=e,this.subscriberClass=e&&t!==e?v:y}return t.prototype.call=function(t,e){return e.subscribe(new this.subscriberClass(t,this.bufferSize,this.startBufferEvery))},t}(),y=function(t){function e(e,n){var a=t.call(this,e)||this;return a.bufferSize=n,a.buffer=[],a}return a.__extends(e,t),e.prototype._next=function(t){var e=this.buffer;e.push(t),e.length==this.bufferSize&&(this.destination.next(e),this.buffer=[])},e.prototype._complete=function(){var e=this.buffer;e.length>0&&this.destination.next(e),t.prototype._complete.call(this)},e}(g.a),v=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.bufferSize=n,r.startBufferEvery=a,r.buffers=[],r.count=0,r}return a.__extends(e,t),e.prototype._next=function(t){var e=this.bufferSize,n=this.startBufferEvery,a=this.buffers,r=this.count;this.count++,r%n==0&&a.push([]);for(var i=a.length;i--;){var s=a[i];s.push(t),s.length===e&&(a.splice(i,1),this.destination.next(s))}},e.prototype._complete=function(){for(var e=this.buffers,n=this.destination;e.length>0;){var a=e.shift();a.length>0&&n.next(a)}t.prototype._complete.call(this)},e}(g.a),_=n("nkY7");function x(t){var e=arguments.length,n=c.a;Object(_.a)(arguments[arguments.length-1])&&(n=arguments[arguments.length-1],e--);var a=null;e>=2&&(a=arguments[1]);var r=Number.POSITIVE_INFINITY;return e>=3&&(r=arguments[2]),function(e){return e.lift(new T(t,a,r,n))}}var T=function(){function t(t,e,n,a){this.bufferTimeSpan=t,this.bufferCreationInterval=e,this.maxBufferSize=n,this.scheduler=a}return t.prototype.call=function(t,e){return e.subscribe(new S(t,this.bufferTimeSpan,this.bufferCreationInterval,this.maxBufferSize,this.scheduler))},t}(),w=function(){return function(){this.buffer=[]}}(),S=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;s.bufferTimeSpan=n,s.bufferCreationInterval=a,s.maxBufferSize=r,s.scheduler=i,s.contexts=[];var o=s.openContext();if(s.timespanOnly=null==a||a<0,s.timespanOnly)s.add(o.closeAction=i.schedule(O,n,{subscriber:s,context:o,bufferTimeSpan:n}));else{var u={bufferTimeSpan:n,bufferCreationInterval:a,subscriber:s,scheduler:i};s.add(o.closeAction=i.schedule(C,n,{subscriber:s,context:o})),s.add(i.schedule(I,a,u))}return s}return a.__extends(e,t),e.prototype._next=function(t){for(var e,n=this.contexts,a=n.length,r=0;r<a;r++){var i=n[r],s=i.buffer;s.push(t),s.length==this.maxBufferSize&&(e=i)}e&&this.onBufferFull(e)},e.prototype._error=function(e){this.contexts.length=0,t.prototype._error.call(this,e)},e.prototype._complete=function(){for(var e=this.contexts,n=this.destination;e.length>0;){var a=e.shift();n.next(a.buffer)}t.prototype._complete.call(this)},e.prototype._unsubscribe=function(){this.contexts=null},e.prototype.onBufferFull=function(t){this.closeContext(t);var e=t.closeAction;if(e.unsubscribe(),this.remove(e),!this.closed&&this.timespanOnly){t=this.openContext();var n=this.bufferTimeSpan;this.add(t.closeAction=this.scheduler.schedule(O,n,{subscriber:this,context:t,bufferTimeSpan:n}))}},e.prototype.openContext=function(){var t=new w;return this.contexts.push(t),t},e.prototype.closeContext=function(t){this.destination.next(t.buffer);var e=this.contexts;(e?e.indexOf(t):-1)>=0&&e.splice(e.indexOf(t),1)},e}(g.a);function O(t){var e=t.subscriber,n=t.context;n&&e.closeContext(n),e.closed||(t.context=e.openContext(),t.context.closeAction=this.schedule(t,t.bufferTimeSpan))}function I(t){var e=t.bufferCreationInterval,n=t.bufferTimeSpan,a=t.subscriber,r=t.scheduler,i=a.openContext();a.closed||(a.add(i.closeAction=r.schedule(C,n,{subscriber:a,context:i})),this.schedule(t,e))}function C(t){t.subscriber.closeContext(t.context)}var k=n("pugT");function N(t,e){return function(n){return n.lift(new R(t,e))}}var R=function(){function t(t,e){this.openings=t,this.closingSelector=e}return t.prototype.call=function(t,e){return e.subscribe(new A(t,this.openings,this.closingSelector))},t}(),A=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.openings=n,r.closingSelector=a,r.contexts=[],r.add(Object(i.a)(r,n)),r}return a.__extends(e,t),e.prototype._next=function(t){for(var e=this.contexts,n=e.length,a=0;a<n;a++)e[a].buffer.push(t)},e.prototype._error=function(e){for(var n=this.contexts;n.length>0;){var a=n.shift();a.subscription.unsubscribe(),a.buffer=null,a.subscription=null}this.contexts=null,t.prototype._error.call(this,e)},e.prototype._complete=function(){for(var e=this.contexts;e.length>0;){var n=e.shift();this.destination.next(n.buffer),n.subscription.unsubscribe(),n.buffer=null,n.subscription=null}this.contexts=null,t.prototype._complete.call(this)},e.prototype.notifyNext=function(t,e,n,a,r){t?this.closeBuffer(t):this.openBuffer(e)},e.prototype.notifyComplete=function(t){this.closeBuffer(t.context)},e.prototype.openBuffer=function(t){try{var e=this.closingSelector.call(this,t);e&&this.trySubscribe(e)}catch(n){this._error(n)}},e.prototype.closeBuffer=function(t){var e=this.contexts;if(e&&t){var n=t.subscription;this.destination.next(t.buffer),e.splice(e.indexOf(t),1),this.remove(n),n.unsubscribe()}},e.prototype.trySubscribe=function(t){var e=this.contexts,n=new k.a,a={buffer:[],subscription:n};e.push(a);var r=Object(i.a)(this,t,a);!r||r.closed?this.closeBuffer(a):(r.context=a,this.add(r),n.add(r))},e}(r.a);function D(t){return function(e){return e.lift(new E(t))}}var E=function(){function t(t){this.closingSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new L(t,this.closingSelector))},t}(),L=function(t){function e(e,n){var a=t.call(this,e)||this;return a.closingSelector=n,a.subscribing=!1,a.openBuffer(),a}return a.__extends(e,t),e.prototype._next=function(t){this.buffer.push(t)},e.prototype._complete=function(){var e=this.buffer;e&&this.destination.next(e),t.prototype._complete.call(this)},e.prototype._unsubscribe=function(){this.buffer=null,this.subscribing=!1},e.prototype.notifyNext=function(t,e,n,a,r){this.openBuffer()},e.prototype.notifyComplete=function(){this.subscribing?this.complete():this.openBuffer()},e.prototype.openBuffer=function(){var t,e=this.closingSubscription;e&&(this.remove(e),e.unsubscribe()),this.buffer&&this.destination.next(this.buffer),this.buffer=[];try{t=(0,this.closingSelector)()}catch(n){return this.error(n)}e=new k.a,this.closingSubscription=e,this.add(e),this.subscribing=!0,e.add(Object(i.a)(this,t)),this.subscribing=!1},e}(r.a),P=n("9Z1F"),M=n("dzgT");function q(t){return function(e){return e.lift(new M.a(t))}}var j=n("isby"),F=n("0/uQ");function z(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=null;return"function"==typeof t[t.length-1]&&(n=t.pop()),1===t.length&&Object(j.a)(t[0])&&(t=t[0].slice()),function(e){return e.lift.call(Object(F.a)([e].concat(t)),new M.a(n))}}var G=n("wbK0"),Y=n("Txjg"),V=n("Phjn");function H(t,e){return Object(V.a)(function(){return t},e)}function B(t){return function(e){return e.lift(new U(t,e))}}var U=function(){function t(t,e){this.predicate=t,this.source=e}return t.prototype.call=function(t,e){return e.subscribe(new W(t,this.predicate,this.source))},t}(),W=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.predicate=n,r.source=a,r.count=0,r.index=0,r}return a.__extends(e,t),e.prototype._next=function(t){this.predicate?this._tryPredicate(t):this.count++},e.prototype._tryPredicate=function(t){var e;try{e=this.predicate(t,this.index++,this.source)}catch(n){return void this.destination.error(n)}e&&this.count++},e.prototype._complete=function(){this.destination.next(this.count),this.destination.complete()},e}(g.a);function K(t){return function(e){return e.lift(new $(t))}}var $=function(){function t(t){this.durationSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new Z(t,this.durationSelector))},t}(),Z=function(t){function e(e,n){var a=t.call(this,e)||this;return a.durationSelector=n,a.hasValue=!1,a.durationSubscription=null,a}return a.__extends(e,t),e.prototype._next=function(t){try{var e=this.durationSelector.call(this,t);e&&this._tryNext(t,e)}catch(n){this.destination.error(n)}},e.prototype._complete=function(){this.emitValue(),this.destination.complete()},e.prototype._tryNext=function(t,e){var n=this.durationSubscription;this.value=t,this.hasValue=!0,n&&(n.unsubscribe(),this.remove(n)),(n=Object(i.a)(this,e))&&!n.closed&&this.add(this.durationSubscription=n)},e.prototype.notifyNext=function(t,e,n,a,r){this.emitValue()},e.prototype.notifyComplete=function(){this.emitValue()},e.prototype.emitValue=function(){if(this.hasValue){var e=this.value,n=this.durationSubscription;n&&(this.durationSubscription=null,n.unsubscribe(),this.remove(n)),this.value=null,this.hasValue=!1,t.prototype._next.call(this,e)}},e}(r.a),X=n("Gi3i"),J=n("HJBe");function Q(t){return t instanceof Date&&!isNaN(+t)}var tt=n("60iU");function et(t,e){void 0===e&&(e=c.a);var n=Q(t)?+t-e.now():Math.abs(t);return function(t){return t.lift(new nt(n,e))}}var nt=function(){function t(t,e){this.delay=t,this.scheduler=e}return t.prototype.call=function(t,e){return e.subscribe(new at(t,this.delay,this.scheduler))},t}(),at=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.delay=n,r.scheduler=a,r.queue=[],r.active=!1,r.errored=!1,r}return a.__extends(e,t),e.dispatch=function(t){for(var e=t.source,n=e.queue,a=t.scheduler,r=t.destination;n.length>0&&n[0].time-a.now()<=0;)n.shift().notification.observe(r);if(n.length>0){var i=Math.max(0,n[0].time-a.now());this.schedule(t,i)}else this.unsubscribe(),e.active=!1},e.prototype._schedule=function(t){this.active=!0,this.destination.add(t.schedule(e.dispatch,this.delay,{source:this,destination:this.destination,scheduler:t}))},e.prototype.scheduleNotification=function(t){if(!0!==this.errored){var e=this.scheduler,n=new rt(e.now()+this.delay,t);this.queue.push(n),!1===this.active&&this._schedule(e)}},e.prototype._next=function(t){this.scheduleNotification(tt.a.createNext(t))},e.prototype._error=function(t){this.errored=!0,this.queue=[],this.destination.error(t),this.unsubscribe()},e.prototype._complete=function(){this.scheduleNotification(tt.a.createComplete()),this.unsubscribe()},e}(g.a),rt=function(){return function(t,e){this.time=t,this.notification=e}}(),it=n("6blF");function st(t,e){return e?function(n){return new ct(n,e).lift(new ot(t))}:function(e){return e.lift(new ot(t))}}var ot=function(){function t(t){this.delayDurationSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new ut(t,this.delayDurationSelector))},t}(),ut=function(t){function e(e,n){var a=t.call(this,e)||this;return a.delayDurationSelector=n,a.completed=!1,a.delayNotifierSubscriptions=[],a.index=0,a}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.destination.next(t),this.removeSubscription(r),this.tryComplete()},e.prototype.notifyError=function(t,e){this._error(t)},e.prototype.notifyComplete=function(t){var e=this.removeSubscription(t);e&&this.destination.next(e),this.tryComplete()},e.prototype._next=function(t){var e=this.index++;try{var n=this.delayDurationSelector(t,e);n&&this.tryDelay(n,t)}catch(a){this.destination.error(a)}},e.prototype._complete=function(){this.completed=!0,this.tryComplete(),this.unsubscribe()},e.prototype.removeSubscription=function(t){t.unsubscribe();var e=this.delayNotifierSubscriptions.indexOf(t);return-1!==e&&this.delayNotifierSubscriptions.splice(e,1),t.outerValue},e.prototype.tryDelay=function(t,e){var n=Object(i.a)(this,t,e);n&&!n.closed&&(this.destination.add(n),this.delayNotifierSubscriptions.push(n))},e.prototype.tryComplete=function(){this.completed&&0===this.delayNotifierSubscriptions.length&&this.destination.complete()},e}(r.a),ct=function(t){function e(e,n){var a=t.call(this)||this;return a.source=e,a.subscriptionDelay=n,a}return a.__extends(e,t),e.prototype._subscribe=function(t){this.subscriptionDelay.subscribe(new lt(t,this.source))},e}(it.a),lt=function(t){function e(e,n){var a=t.call(this)||this;return a.parent=e,a.source=n,a.sourceSubscribed=!1,a}return a.__extends(e,t),e.prototype._next=function(t){this.subscribeToSource()},e.prototype._error=function(t){this.unsubscribe(),this.parent.error(t)},e.prototype._complete=function(){this.unsubscribe(),this.subscribeToSource()},e.prototype.subscribeToSource=function(){this.sourceSubscribed||(this.sourceSubscribed=!0,this.unsubscribe(),this.source.subscribe(this.parent))},e}(g.a);function dt(){return function(t){return t.lift(new ft)}}var ft=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new pt(t))},t}(),pt=function(t){function e(e){return t.call(this,e)||this}return a.__extends(e,t),e.prototype._next=function(t){t.observe(this.destination)},e}(g.a),ht=n("ou9H"),gt=n("ad02");function bt(t,e){return Object(gt.a)(function(n,a){return e?e(n[t],a[t]):n[t]===a[t]})}var mt=n("b7mW"),yt=n("VnD/"),vt=n("tNVB"),_t=n("t9fZ");function xt(t,e){if(t<0)throw new mt.a;var n=arguments.length>=2;return function(a){return a.pipe(Object(yt.a)(function(e,n){return n===t}),Object(_t.a)(1),n?Object(J.a)(e):Object(vt.a)(function(){return new mt.a}))}}var Tt=n("dEwP"),wt=n("F/XL");function St(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){return Object(Tt.a)(e,wt.a.apply(void 0,t))}}var Ot=n("zAZS");function It(){return function(t){return t.lift(new Ct)}}var Ct=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new kt(t))},t}(),kt=function(t){function e(e){var n=t.call(this,e)||this;return n.hasCompleted=!1,n.hasSubscription=!1,n}return a.__extends(e,t),e.prototype._next=function(t){this.hasSubscription||(this.hasSubscription=!0,this.add(Object(i.a)(this,t)))},e.prototype._complete=function(){this.hasCompleted=!0,this.hasSubscription||this.destination.complete()},e.prototype.notifyComplete=function(t){this.remove(t),this.hasSubscription=!1,this.hasCompleted&&this.destination.complete()},e}(r.a),Nt=n("rPjj"),Rt=n("67Y/");function At(t,e){return e?function(n){return n.pipe(At(function(n,a){return Object(F.a)(t(n,a)).pipe(Object(Rt.a)(function(t,r){return e(n,t,a,r)}))}))}:function(e){return e.lift(new Dt(t))}}var Dt=function(){function t(t){this.project=t}return t.prototype.call=function(t,e){return e.subscribe(new Et(t,this.project))},t}(),Et=function(t){function e(e,n){var a=t.call(this,e)||this;return a.project=n,a.hasSubscription=!1,a.hasCompleted=!1,a.index=0,a}return a.__extends(e,t),e.prototype._next=function(t){this.hasSubscription||this.tryNext(t)},e.prototype.tryNext=function(t){var e,n=this.index++;try{e=this.project(t,n)}catch(a){return void this.destination.error(a)}this.hasSubscription=!0,this._innerSub(e,t,n)},e.prototype._innerSub=function(t,e,n){var a=new Nt.a(this,void 0,void 0);this.destination.add(a),Object(i.a)(this,t,e,n,a)},e.prototype._complete=function(){this.hasCompleted=!0,this.hasSubscription||this.destination.complete(),this.unsubscribe()},e.prototype.notifyNext=function(t,e,n,a,r){this.destination.next(e)},e.prototype.notifyError=function(t){this.destination.error(t)},e.prototype.notifyComplete=function(t){this.destination.remove(t),this.hasSubscription=!1,this.hasCompleted&&this.destination.complete()},e}(r.a);function Lt(t,e,n){return void 0===e&&(e=Number.POSITIVE_INFINITY),void 0===n&&(n=void 0),e=(e||0)<1?Number.POSITIVE_INFINITY:e,function(a){return a.lift(new Pt(t,e,n))}}var Pt=function(){function t(t,e,n){this.project=t,this.concurrent=e,this.scheduler=n}return t.prototype.call=function(t,e){return e.subscribe(new Mt(t,this.project,this.concurrent,this.scheduler))},t}(),Mt=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.project=n,i.concurrent=a,i.scheduler=r,i.index=0,i.active=0,i.hasCompleted=!1,a<Number.POSITIVE_INFINITY&&(i.buffer=[]),i}return a.__extends(e,t),e.dispatch=function(t){t.subscriber.subscribeToProjection(t.result,t.value,t.index)},e.prototype._next=function(t){var n=this.destination;if(n.closed)this._complete();else{var a=this.index++;if(this.active<this.concurrent){n.next(t);try{var r=(0,this.project)(t,a);this.scheduler?this.destination.add(this.scheduler.schedule(e.dispatch,0,{subscriber:this,result:r,value:t,index:a})):this.subscribeToProjection(r,t,a)}catch(i){n.error(i)}}else this.buffer.push(t)}},e.prototype.subscribeToProjection=function(t,e,n){this.active++,this.destination.add(Object(i.a)(this,t,e,n))},e.prototype._complete=function(){this.hasCompleted=!0,this.hasCompleted&&0===this.active&&this.destination.complete(),this.unsubscribe()},e.prototype.notifyNext=function(t,e,n,a,r){this._next(e)},e.prototype.notifyComplete=function(t){var e=this.buffer;this.destination.remove(t),this.active--,e&&e.length>0&&this._next(e.shift()),this.hasCompleted&&0===this.active&&this.destination.complete()},e}(r.a),qt=n("2WpN");function jt(t,e){if("function"!=typeof t)throw new TypeError("predicate is not a function");return function(n){return n.lift(new Ft(t,n,!1,e))}}var Ft=function(){function t(t,e,n,a){this.predicate=t,this.source=e,this.yieldIndex=n,this.thisArg=a}return t.prototype.call=function(t,e){return e.subscribe(new zt(t,this.predicate,this.source,this.yieldIndex,this.thisArg))},t}(),zt=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;return s.predicate=n,s.source=a,s.yieldIndex=r,s.thisArg=i,s.index=0,s}return a.__extends(e,t),e.prototype.notifyComplete=function(t){var e=this.destination;e.next(t),e.complete(),this.unsubscribe()},e.prototype._next=function(t){var e=this.predicate,n=this.thisArg,a=this.index++;try{e.call(n||this,t,a,this.source)&&this.notifyComplete(this.yieldIndex?a:t)}catch(r){this.destination.error(r)}},e.prototype._complete=function(){this.notifyComplete(this.yieldIndex?-1:void 0)},e}(g.a);function Gt(t,e){return function(n){return n.lift(new Ft(t,n,!0,e))}}var Yt=n("P6uZ"),Vt=n("IxPp");function Ht(){return function(t){return t.lift(new Bt)}}var Bt=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new Ut(t))},t}(),Ut=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e.prototype._next=function(t){},e}(g.a);function Wt(){return function(t){return t.lift(new Kt)}}var Kt=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new $t(t))},t}(),$t=function(t){function e(e){return t.call(this,e)||this}return a.__extends(e,t),e.prototype.notifyComplete=function(t){var e=this.destination;e.next(t),e.complete()},e.prototype._next=function(t){this.notifyComplete(!1)},e.prototype._complete=function(){this.notifyComplete(!0)},e}(g.a),Zt=n("w1EH"),Xt=n("aGNc");function Jt(){return function(t){return t.lift(new Qt)}}var Qt=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new te(t))},t}(),te=function(t){function e(e){return t.call(this,e)||this}return a.__extends(e,t),e.prototype._next=function(t){this.destination.next(tt.a.createNext(t))},e.prototype._error=function(t){var e=this.destination;e.next(tt.a.createError(t)),e.complete()},e.prototype._complete=function(){var t=this.destination;t.next(tt.a.createComplete()),t.complete()},e}(g.a),ee=n("Qgas");function ne(t){var e="function"==typeof t?function(e,n){return t(e,n)>0?e:n}:function(t,e){return t>e?t:e};return Object(ee.a)(e)}var ae=n("p0ib");function re(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){return e.lift.call(ae.a.apply(void 0,[e].concat(t)))}}var ie=n("Zn8D"),se=n("psW0");function oe(t,e,n){return void 0===n&&(n=Number.POSITIVE_INFINITY),"function"==typeof e?Object(se.a)(function(){return t},e,n):("number"==typeof e&&(n=e),Object(se.a)(function(){return t},n))}function ue(t,e,n){return void 0===n&&(n=Number.POSITIVE_INFINITY),function(a){return a.lift(new ce(t,e,n))}}var ce=function(){function t(t,e,n){this.accumulator=t,this.seed=e,this.concurrent=n}return t.prototype.call=function(t,e){return e.subscribe(new le(t,this.accumulator,this.seed,this.concurrent))},t}(),le=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.accumulator=n,i.acc=a,i.concurrent=r,i.hasValue=!1,i.hasCompleted=!1,i.buffer=[],i.active=0,i.index=0,i}return a.__extends(e,t),e.prototype._next=function(t){if(this.active<this.concurrent){var e=this.index++,n=this.destination,a=void 0;try{a=(0,this.accumulator)(this.acc,t,e)}catch(r){return n.error(r)}this.active++,this._innerSub(a,t,e)}else this.buffer.push(t)},e.prototype._innerSub=function(t,e,n){var a=new Nt.a(this,void 0,void 0);this.destination.add(a),Object(i.a)(this,t,e,n,a)},e.prototype._complete=function(){this.hasCompleted=!0,0===this.active&&0===this.buffer.length&&(!1===this.hasValue&&this.destination.next(this.acc),this.destination.complete()),this.unsubscribe()},e.prototype.notifyNext=function(t,e,n,a,r){var i=this.destination;this.acc=e,this.hasValue=!0,i.next(e)},e.prototype.notifyComplete=function(t){var e=this.buffer;this.destination.remove(t),this.active--,e.length>0?this._next(e.shift()):0===this.active&&this.hasCompleted&&(!1===this.hasValue&&this.destination.next(this.acc),this.destination.complete())},e}(r.a);function de(t){var e="function"==typeof t?function(e,n){return t(e,n)<0?e:n}:function(t,e){return t<e?t:e};return Object(ee.a)(e)}var fe=n("xlPZ"),pe=n("mZXl");function he(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return 1===t.length&&Object(j.a)(t[0])&&(t=t[0]),function(e){return e.lift(new ge(t))}}var ge=function(){function t(t){this.nextSources=t}return t.prototype.call=function(t,e){return e.subscribe(new be(t,this.nextSources))},t}(),be=function(t){function e(e,n){var a=t.call(this,e)||this;return a.destination=e,a.nextSources=n,a}return a.__extends(e,t),e.prototype.notifyError=function(t,e){this.subscribeToNextSource()},e.prototype.notifyComplete=function(t){this.subscribeToNextSource()},e.prototype._error=function(t){this.subscribeToNextSource(),this.unsubscribe()},e.prototype._complete=function(){this.subscribeToNextSource(),this.unsubscribe()},e.prototype.subscribeToNextSource=function(){var t=this.nextSources.shift();if(t){var e=new Nt.a(this,void 0,void 0);this.destination.add(e),Object(i.a)(this,t,void 0,void 0,e)}else this.destination.complete()},e}(r.a);function me(){return function(t){return t.lift(new ye)}}var ye=function(){function t(){}return t.prototype.call=function(t,e){return e.subscribe(new ve(t))},t}(),ve=function(t){function e(e){var n=t.call(this,e)||this;return n.hasPrev=!1,n}return a.__extends(e,t),e.prototype._next=function(t){var e;this.hasPrev?e=[this.prev,t]:this.hasPrev=!0,this.prev=t,e&&this.destination.next(e)},e}(g.a),_e=n("jFaF");function xe(t,e){return function(n){return[Object(yt.a)(t,e)(n),Object(yt.a)(Object(_e.a)(t,e))(n)]}}function Te(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t.length;if(0===n)throw new Error("list of properties cannot be empty.");return function(e){return Object(Rt.a)(function(t,e){return function(n){for(var a=n,r=0;r<e;r++){var i=a[t[r]];if(void 0===i)return;a=i}return a}}(t,n))(e)}}var we=n("K9Ia");function Se(t){return t?Object(fe.a)(function(){return new we.a},t):Object(fe.a)(new we.a)}var Oe=n("26FU");function Ie(t){return function(e){return Object(fe.a)(new Oe.a(t))(e)}}var Ce=n("svcd");function ke(){return function(t){return Object(fe.a)(new Ce.a)(t)}}var Ne=n("S5bw");function Re(t,e,n,a){n&&"function"!=typeof n&&(a=n);var r="function"==typeof n?n:void 0,i=new Ne.a(t,e,a);return function(t){return Object(fe.a)(function(){return i},r)(t)}}var Ae=n("W0Ae");function De(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){return 1===t.length&&Object(j.a)(t[0])&&(t=t[0]),e.lift.call(Ae.a.apply(void 0,[e].concat(t)))}}var Ee=n("G5J1");function Le(t){return void 0===t&&(t=-1),function(e){return 0===t?Object(Ee.b)():e.lift(new Pe(t<0?-1:t-1,e))}}var Pe=function(){function t(t,e){this.count=t,this.source=e}return t.prototype.call=function(t,e){return e.subscribe(new Me(t,this.count,this.source))},t}(),Me=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.count=n,r.source=a,r}return a.__extends(e,t),e.prototype.complete=function(){if(!this.isStopped){var e=this.source,n=this.count;if(0===n)return t.prototype.complete.call(this);n>-1&&(this.count=n-1),e.subscribe(this._unsubscribeAndRecycle())}},e}(g.a);function qe(t){return function(e){return e.lift(new je(t))}}var je=function(){function t(t){this.notifier=t}return t.prototype.call=function(t,e){return e.subscribe(new Fe(t,this.notifier,e))},t}(),Fe=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.notifier=n,r.source=a,r.sourceIsBeingSubscribedTo=!0,r}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.sourceIsBeingSubscribedTo=!0,this.source.subscribe(this)},e.prototype.notifyComplete=function(e){if(!1===this.sourceIsBeingSubscribedTo)return t.prototype.complete.call(this)},e.prototype.complete=function(){if(this.sourceIsBeingSubscribedTo=!1,!this.isStopped){if(this.retries||this.subscribeToRetries(),!this.retriesSubscription||this.retriesSubscription.closed)return t.prototype.complete.call(this);this._unsubscribeAndRecycle(),this.notifications.next()}},e.prototype._unsubscribe=function(){var t=this.notifications,e=this.retriesSubscription;t&&(t.unsubscribe(),this.notifications=null),e&&(e.unsubscribe(),this.retriesSubscription=null),this.retries=null},e.prototype._unsubscribeAndRecycle=function(){var e=this._unsubscribe;return this._unsubscribe=null,t.prototype._unsubscribeAndRecycle.call(this),this._unsubscribe=e,this},e.prototype.subscribeToRetries=function(){var e;this.notifications=new we.a;try{e=(0,this.notifier)(this.notifications)}catch(n){return t.prototype.complete.call(this)}this.retries=e,this.retriesSubscription=Object(i.a)(this,e)},e}(r.a);function ze(t){return void 0===t&&(t=-1),function(e){return e.lift(new Ge(t,e))}}var Ge=function(){function t(t,e){this.count=t,this.source=e}return t.prototype.call=function(t,e){return e.subscribe(new Ye(t,this.count,this.source))},t}(),Ye=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.count=n,r.source=a,r}return a.__extends(e,t),e.prototype.error=function(e){if(!this.isStopped){var n=this.source,a=this.count;if(0===a)return t.prototype.error.call(this,e);a>-1&&(this.count=a-1),n.subscribe(this._unsubscribeAndRecycle())}},e}(g.a);function Ve(t){return function(e){return e.lift(new He(t,e))}}var He=function(){function t(t,e){this.notifier=t,this.source=e}return t.prototype.call=function(t,e){return e.subscribe(new Be(t,this.notifier,this.source))},t}(),Be=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.notifier=n,r.source=a,r}return a.__extends(e,t),e.prototype.error=function(e){if(!this.isStopped){var n=this.errors,a=this.retries,r=this.retriesSubscription;if(a)this.errors=null,this.retriesSubscription=null;else{n=new we.a;try{a=(0,this.notifier)(n)}catch(s){return t.prototype.error.call(this,s)}r=Object(i.a)(this,a)}this._unsubscribeAndRecycle(),this.errors=n,this.retries=a,this.retriesSubscription=r,n.next(e)}},e.prototype._unsubscribe=function(){var t=this.errors,e=this.retriesSubscription;t&&(t.unsubscribe(),this.errors=null),e&&(e.unsubscribe(),this.retriesSubscription=null),this.retries=null},e.prototype.notifyNext=function(t,e,n,a,r){var i=this._unsubscribe;this._unsubscribe=null,this._unsubscribeAndRecycle(),this._unsubscribe=i,this.source.subscribe(this)},e}(r.a),Ue=n("yGWI");function We(t){return function(e){return e.lift(new Ke(t))}}var Ke=function(){function t(t){this.notifier=t}return t.prototype.call=function(t,e){var n=new $e(t),a=e.subscribe(n);return a.add(Object(i.a)(n,this.notifier)),a},t}(),$e=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.hasValue=!1,e}return a.__extends(e,t),e.prototype._next=function(t){this.value=t,this.hasValue=!0},e.prototype.notifyNext=function(t,e,n,a,r){this.emitValue()},e.prototype.notifyComplete=function(){this.emitValue()},e.prototype.emitValue=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.value))},e}(r.a);function Ze(t,e){return void 0===e&&(e=c.a),function(n){return n.lift(new Xe(t,e))}}var Xe=function(){function t(t,e){this.period=t,this.scheduler=e}return t.prototype.call=function(t,e){return e.subscribe(new Je(t,this.period,this.scheduler))},t}(),Je=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.period=n,r.scheduler=a,r.hasValue=!1,r.add(a.schedule(Qe,n,{subscriber:r,period:n})),r}return a.__extends(e,t),e.prototype._next=function(t){this.lastValue=t,this.hasValue=!0},e.prototype.notifyNext=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.lastValue))},e}(g.a);function Qe(t){var e=t.period;t.subscriber.notifyNext(),this.schedule(t,e)}var tn=n("dC0D");function en(t,e){return function(n){return n.lift(new nn(t,e))}}var nn=function(){function t(t,e){this.compareTo=t,this.comparator=e}return t.prototype.call=function(t,e){return e.subscribe(new an(t,this.compareTo,this.comparator))},t}(),an=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.compareTo=n,r.comparator=a,r._a=[],r._b=[],r._oneComplete=!1,r.destination.add(n.subscribe(new rn(e,r))),r}return a.__extends(e,t),e.prototype._next=function(t){this._oneComplete&&0===this._b.length?this.emit(!1):(this._a.push(t),this.checkValues())},e.prototype._complete=function(){this._oneComplete?this.emit(0===this._a.length&&0===this._b.length):this._oneComplete=!0,this.unsubscribe()},e.prototype.checkValues=function(){for(var t=this._a,e=this._b,n=this.comparator;t.length>0&&e.length>0;){var a=t.shift(),r=e.shift(),i=!1;try{i=n?n(a,r):a===r}catch(s){this.destination.error(s)}i||this.emit(!1)}},e.prototype.emit=function(t){var e=this.destination;e.next(t),e.complete()},e.prototype.nextB=function(t){this._oneComplete&&0===this._a.length?this.emit(!1):(this._b.push(t),this.checkValues())},e.prototype.completeB=function(){this._oneComplete?this.emit(0===this._a.length&&0===this._b.length):this._oneComplete=!0},e}(g.a),rn=function(t){function e(e,n){var a=t.call(this,e)||this;return a.parent=n,a}return a.__extends(e,t),e.prototype._next=function(t){this.parent.nextB(t)},e.prototype._error=function(t){this.parent.error(t),this.unsubscribe()},e.prototype._complete=function(){this.parent.completeB(),this.unsubscribe()},e}(g.a),sn=n("S1nX"),on=n("klSw"),un=n("3fWJ");function cn(t){return function(e){return e.lift(new ln(t,e))}}var ln=function(){function t(t,e){this.predicate=t,this.source=e}return t.prototype.call=function(t,e){return e.subscribe(new dn(t,this.predicate,this.source))},t}(),dn=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.predicate=n,r.source=a,r.seenValue=!1,r.index=0,r}return a.__extends(e,t),e.prototype.applySingleValue=function(t){this.seenValue?this.destination.error("Sequence contains more than one element"):(this.seenValue=!0,this.singleValue=t)},e.prototype._next=function(t){var e=this.index++;this.predicate?this.tryNext(t,e):this.applySingleValue(t)},e.prototype.tryNext=function(t,e){try{this.predicate(t,e,this.source)&&this.applySingleValue(t)}catch(n){this.destination.error(n)}},e.prototype._complete=function(){var t=this.destination;this.index>0?(t.next(this.seenValue?this.singleValue:void 0),t.complete()):t.error(new un.a)},e}(g.a);function fn(t){return function(e){return e.lift(new pn(t))}}var pn=function(){function t(t){this.total=t}return t.prototype.call=function(t,e){return e.subscribe(new hn(t,this.total))},t}(),hn=function(t){function e(e,n){var a=t.call(this,e)||this;return a.total=n,a.count=0,a}return a.__extends(e,t),e.prototype._next=function(t){++this.count>this.total&&this.destination.next(t)},e}(g.a);function gn(t){return function(e){return e.lift(new bn(t))}}var bn=function(){function t(t){if(this._skipCount=t,this._skipCount<0)throw new mt.a}return t.prototype.call=function(t,e){return e.subscribe(0===this._skipCount?new g.a(t):new mn(t,this._skipCount))},t}(),mn=function(t){function e(e,n){var a=t.call(this,e)||this;return a._skipCount=n,a._count=0,a._ring=new Array(n),a}return a.__extends(e,t),e.prototype._next=function(t){var e=this._skipCount,n=this._count++;if(n<e)this._ring[n]=t;else{var a=n%e,r=this._ring,i=r[a];r[a]=t,this.destination.next(i)}},e}(g.a);function yn(t){return function(e){return e.lift(new vn(t))}}var vn=function(){function t(t){this.notifier=t}return t.prototype.call=function(t,e){return e.subscribe(new _n(t,this.notifier))},t}(),_n=function(t){function e(e,n){var a=t.call(this,e)||this;a.hasValue=!1;var r=new Nt.a(a,void 0,void 0);return a.add(r),a.innerSubscription=r,Object(i.a)(a,n,void 0,void 0,r),a}return a.__extends(e,t),e.prototype._next=function(e){this.hasValue&&t.prototype._next.call(this,e)},e.prototype.notifyNext=function(t,e,n,a,r){this.hasValue=!0,this.innerSubscription&&this.innerSubscription.unsubscribe()},e.prototype.notifyComplete=function(){},e}(r.a);function xn(t){return function(e){return e.lift(new Tn(t))}}var Tn=function(){function t(t){this.predicate=t}return t.prototype.call=function(t,e){return e.subscribe(new wn(t,this.predicate))},t}(),wn=function(t){function e(e,n){var a=t.call(this,e)||this;return a.predicate=n,a.skipping=!0,a.index=0,a}return a.__extends(e,t),e.prototype._next=function(t){var e=this.destination;this.skipping&&this.tryCallPredicate(t),this.skipping||e.next(t)},e.prototype.tryCallPredicate=function(t){try{var e=this.predicate(t,this.index++);this.skipping=Boolean(e)}catch(n){this.destination.error(n)}},e}(g.a),Sn=n("p0Sj"),On=n("KQya"),In=n("/21U"),Cn=function(t){function e(e,n,a){void 0===n&&(n=0),void 0===a&&(a=On.a);var r=t.call(this)||this;return r.source=e,r.delayTime=n,r.scheduler=a,(!Object(In.a)(n)||n<0)&&(r.delayTime=0),a&&"function"==typeof a.schedule||(r.scheduler=On.a),r}return a.__extends(e,t),e.create=function(t,n,a){return void 0===n&&(n=0),void 0===a&&(a=On.a),new e(t,n,a)},e.dispatch=function(t){return this.add(t.source.subscribe(t.subscriber))},e.prototype._subscribe=function(t){return this.scheduler.schedule(e.dispatch,this.delayTime,{source:this.source,subscriber:t})},e}(it.a);function kn(t,e){return void 0===e&&(e=0),function(n){return n.lift(new Nn(t,e))}}var Nn=function(){function t(t,e){this.scheduler=t,this.delay=e}return t.prototype.call=function(t,e){return new Cn(e,this.delay,this.scheduler).subscribe(t)},t}(),Rn=n("15JJ"),An=n("mChF");function Dn(){return Object(Rn.a)(An.a)}var En=n("zQHH"),Ln=n("AxiF");function Pn(t){return function(e){return e.lift(new Mn(t))}}var Mn=function(){function t(t){this.notifier=t}return t.prototype.call=function(t,e){var n=new qn(t),a=Object(i.a)(n,this.notifier);return a&&!n.seenValue?(n.add(a),e.subscribe(n)):n},t}(),qn=function(t){function e(e){var n=t.call(this,e)||this;return n.seenValue=!1,n}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.seenValue=!0,this.complete()},e.prototype.notifyComplete=function(){},e}(r.a);function jn(t,e){return void 0===e&&(e=!1),function(n){return n.lift(new Fn(t,e))}}var Fn=function(){function t(t,e){this.predicate=t,this.inclusive=e}return t.prototype.call=function(t,e){return e.subscribe(new zn(t,this.predicate,this.inclusive))},t}(),zn=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.predicate=n,r.inclusive=a,r.index=0,r}return a.__extends(e,t),e.prototype._next=function(t){var e,n=this.destination;try{e=this.predicate(t,this.index++)}catch(a){return void n.error(a)}this.nextOrComplete(t,e)},e.prototype.nextOrComplete=function(t,e){var n=this.destination;Boolean(e)?n.next(t):(this.inclusive&&n.next(t),n.complete())},e}(g.a),Gn=n("xMyE"),Yn={leading:!0,trailing:!1};function Vn(t,e){return void 0===e&&(e=Yn),function(n){return n.lift(new Hn(t,e.leading,e.trailing))}}var Hn=function(){function t(t,e,n){this.durationSelector=t,this.leading=e,this.trailing=n}return t.prototype.call=function(t,e){return e.subscribe(new Bn(t,this.durationSelector,this.leading,this.trailing))},t}(),Bn=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.destination=e,i.durationSelector=n,i._leading=a,i._trailing=r,i._hasValue=!1,i}return a.__extends(e,t),e.prototype._next=function(t){this._hasValue=!0,this._sendValue=t,this._throttled||(this._leading?this.send():this.throttle(t))},e.prototype.send=function(){var t=this._sendValue;this._hasValue&&(this.destination.next(t),this.throttle(t)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(t){var e=this.tryDurationSelector(t);e&&this.add(this._throttled=Object(i.a)(this,e))},e.prototype.tryDurationSelector=function(t){try{return this.durationSelector(t)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var t=this._throttled,e=this._trailing;t&&t.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(t,e,n,a,r){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(r.a);function Un(t,e,n){return void 0===e&&(e=c.a),void 0===n&&(n=Yn),function(a){return a.lift(new Wn(t,e,n.leading,n.trailing))}}var Wn=function(){function t(t,e,n,a){this.duration=t,this.scheduler=e,this.leading=n,this.trailing=a}return t.prototype.call=function(t,e){return e.subscribe(new Kn(t,this.duration,this.scheduler,this.leading,this.trailing))},t}(),Kn=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;return s.duration=n,s.scheduler=a,s.leading=r,s.trailing=i,s._hasTrailingValue=!1,s._trailingValue=null,s}return a.__extends(e,t),e.prototype._next=function(t){this.throttled?this.trailing&&(this._trailingValue=t,this._hasTrailingValue=!0):(this.add(this.throttled=this.scheduler.schedule($n,this.duration,{subscriber:this})),this.leading?this.destination.next(t):this.trailing&&(this._trailingValue=t,this._hasTrailingValue=!0))},e.prototype._complete=function(){this._hasTrailingValue?(this.destination.next(this._trailingValue),this.destination.complete()):this.destination.complete()},e.prototype.clearThrottle=function(){var t=this.throttled;t&&(this.trailing&&this._hasTrailingValue&&(this.destination.next(this._trailingValue),this._trailingValue=null,this._hasTrailingValue=!1),t.unsubscribe(),this.remove(t),this.throttled=null)},e}(g.a);function $n(t){t.subscriber.clearThrottle()}var Zn=n("lYZG");function Xn(t){return void 0===t&&(t=c.a),function(e){return Object(Zn.a)(function(){return e.pipe(Object(tn.a)(function(e,n){var a=e.current;return{value:n,current:t.now(),last:a}},{current:t.now(),value:void 0,last:void 0}),Object(Rt.a)(function(t){return new Jn(t.value,t.current-t.last)}))})}}var Jn=function(){return function(t,e){this.value=t,this.interval=e}}(),Qn=n("3U0i");function ta(t,e,n){return void 0===n&&(n=c.a),function(a){var r=Q(t),i=r?+t-n.now():Math.abs(t);return a.lift(new ea(i,r,e,n))}}var ea=function(){function t(t,e,n,a){this.waitFor=t,this.absoluteTimeout=e,this.withObservable=n,this.scheduler=a}return t.prototype.call=function(t,e){return e.subscribe(new na(t,this.absoluteTimeout,this.waitFor,this.withObservable,this.scheduler))},t}(),na=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;return s.absoluteTimeout=n,s.waitFor=a,s.withObservable=r,s.scheduler=i,s.action=null,s.scheduleTimeout(),s}return a.__extends(e,t),e.dispatchTimeout=function(t){var e=t.withObservable;t._unsubscribeAndRecycle(),t.add(Object(i.a)(t,e))},e.prototype.scheduleTimeout=function(){var t=this.action;t?this.action=t.schedule(this,this.waitFor):this.add(this.action=this.scheduler.schedule(e.dispatchTimeout,this.waitFor,this))},e.prototype._next=function(e){this.absoluteTimeout||this.scheduleTimeout(),t.prototype._next.call(this,e)},e.prototype._unsubscribe=function(){this.action=null,this.scheduler=null,this.withObservable=null},e}(r.a),aa=n("XlPw");function ra(t,e){return void 0===e&&(e=c.a),ta(t,Object(aa.a)(new Qn.a),e)}function ia(t){return void 0===t&&(t=c.a),Object(Rt.a)(function(e){return new sa(e,t.now())})}var sa=function(){return function(t,e){this.value=t,this.timestamp=e}}(),oa=n("R+r5");function ua(t){return function(e){return e.lift(new ca(t))}}var ca=function(){function t(t){this.windowBoundaries=t}return t.prototype.call=function(t,e){var n=new la(t),a=e.subscribe(n);return a.closed||n.add(Object(i.a)(n,this.windowBoundaries)),a},t}(),la=function(t){function e(e){var n=t.call(this,e)||this;return n.window=new we.a,e.next(n.window),n}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.openWindow()},e.prototype.notifyError=function(t,e){this._error(t)},e.prototype.notifyComplete=function(t){this._complete()},e.prototype._next=function(t){this.window.next(t)},e.prototype._error=function(t){this.window.error(t),this.destination.error(t)},e.prototype._complete=function(){this.window.complete(),this.destination.complete()},e.prototype._unsubscribe=function(){this.window=null},e.prototype.openWindow=function(){var t=this.window;t&&t.complete();var e=this.destination,n=this.window=new we.a;e.next(n)},e}(r.a);function da(t,e){return void 0===e&&(e=0),function(n){return n.lift(new fa(t,e))}}var fa=function(){function t(t,e){this.windowSize=t,this.startWindowEvery=e}return t.prototype.call=function(t,e){return e.subscribe(new pa(t,this.windowSize,this.startWindowEvery))},t}(),pa=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.destination=e,r.windowSize=n,r.startWindowEvery=a,r.windows=[new we.a],r.count=0,e.next(r.windows[0]),r}return a.__extends(e,t),e.prototype._next=function(t){for(var e=this.startWindowEvery>0?this.startWindowEvery:this.windowSize,n=this.destination,a=this.windowSize,r=this.windows,i=r.length,s=0;s<i&&!this.closed;s++)r[s].next(t);var o=this.count-a+1;if(o>=0&&o%e==0&&!this.closed&&r.shift().complete(),++this.count%e==0&&!this.closed){var u=new we.a;r.push(u),n.next(u)}},e.prototype._error=function(t){var e=this.windows;if(e)for(;e.length>0&&!this.closed;)e.shift().error(t);this.destination.error(t)},e.prototype._complete=function(){var t=this.windows;if(t)for(;t.length>0&&!this.closed;)t.shift().complete();this.destination.complete()},e.prototype._unsubscribe=function(){this.count=0,this.windows=null},e}(g.a);function ha(t){var e=c.a,n=null,a=Number.POSITIVE_INFINITY;return Object(_.a)(arguments[3])&&(e=arguments[3]),Object(_.a)(arguments[2])?e=arguments[2]:Object(In.a)(arguments[2])&&(a=arguments[2]),Object(_.a)(arguments[1])?e=arguments[1]:Object(In.a)(arguments[1])&&(n=arguments[1]),function(r){return r.lift(new ga(t,n,a,e))}}var ga=function(){function t(t,e,n,a){this.windowTimeSpan=t,this.windowCreationInterval=e,this.maxWindowSize=n,this.scheduler=a}return t.prototype.call=function(t,e){return e.subscribe(new ma(t,this.windowTimeSpan,this.windowCreationInterval,this.maxWindowSize,this.scheduler))},t}(),ba=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e._numberOfNextedValues=0,e}return a.__extends(e,t),e.prototype.next=function(e){this._numberOfNextedValues++,t.prototype.next.call(this,e)},Object.defineProperty(e.prototype,"numberOfNextedValues",{get:function(){return this._numberOfNextedValues},enumerable:!0,configurable:!0}),e}(we.a),ma=function(t){function e(e,n,a,r,i){var s=t.call(this,e)||this;s.destination=e,s.windowTimeSpan=n,s.windowCreationInterval=a,s.maxWindowSize=r,s.scheduler=i,s.windows=[];var o=s.openWindow();if(null!==a&&a>=0){var u={windowTimeSpan:n,windowCreationInterval:a,subscriber:s,scheduler:i};s.add(i.schedule(_a,n,{subscriber:s,window:o,context:null})),s.add(i.schedule(va,a,u))}else s.add(i.schedule(ya,n,{subscriber:s,window:o,windowTimeSpan:n}));return s}return a.__extends(e,t),e.prototype._next=function(t){for(var e=this.windows,n=e.length,a=0;a<n;a++){var r=e[a];r.closed||(r.next(t),r.numberOfNextedValues>=this.maxWindowSize&&this.closeWindow(r))}},e.prototype._error=function(t){for(var e=this.windows;e.length>0;)e.shift().error(t);this.destination.error(t)},e.prototype._complete=function(){for(var t=this.windows;t.length>0;){var e=t.shift();e.closed||e.complete()}this.destination.complete()},e.prototype.openWindow=function(){var t=new ba;return this.windows.push(t),this.destination.next(t),t},e.prototype.closeWindow=function(t){t.complete();var e=this.windows;e.splice(e.indexOf(t),1)},e}(g.a);function ya(t){var e=t.subscriber,n=t.windowTimeSpan,a=t.window;a&&e.closeWindow(a),t.window=e.openWindow(),this.schedule(t,n)}function va(t){var e=t.windowTimeSpan,n=t.subscriber,a=t.scheduler,r=t.windowCreationInterval,i=n.openWindow(),s={action:this,subscription:null};s.subscription=a.schedule(_a,e,{subscriber:n,window:i,context:s}),this.add(s.subscription),this.schedule(t,r)}function _a(t){var e=t.subscriber,n=t.window,a=t.context;a&&a.action&&a.subscription&&a.action.remove(a.subscription),e.closeWindow(n)}function xa(t,e){return function(n){return n.lift(new Ta(t,e))}}var Ta=function(){function t(t,e){this.openings=t,this.closingSelector=e}return t.prototype.call=function(t,e){return e.subscribe(new wa(t,this.openings,this.closingSelector))},t}(),wa=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.openings=n,r.closingSelector=a,r.contexts=[],r.add(r.openSubscription=Object(i.a)(r,n,n)),r}return a.__extends(e,t),e.prototype._next=function(t){var e=this.contexts;if(e)for(var n=e.length,a=0;a<n;a++)e[a].window.next(t)},e.prototype._error=function(e){var n=this.contexts;if(this.contexts=null,n)for(var a=n.length,r=-1;++r<a;){var i=n[r];i.window.error(e),i.subscription.unsubscribe()}t.prototype._error.call(this,e)},e.prototype._complete=function(){var e=this.contexts;if(this.contexts=null,e)for(var n=e.length,a=-1;++a<n;){var r=e[a];r.window.complete(),r.subscription.unsubscribe()}t.prototype._complete.call(this)},e.prototype._unsubscribe=function(){var t=this.contexts;if(this.contexts=null,t)for(var e=t.length,n=-1;++n<e;){var a=t[n];a.window.unsubscribe(),a.subscription.unsubscribe()}},e.prototype.notifyNext=function(t,e,n,a,r){if(t===this.openings){var s=void 0;try{s=(0,this.closingSelector)(e)}catch(d){return this.error(d)}var o=new we.a,u=new k.a,c={window:o,subscription:u};this.contexts.push(c);var l=Object(i.a)(this,s,c);l.closed?this.closeWindow(this.contexts.length-1):(l.context=c,u.add(l)),this.destination.next(o)}else this.closeWindow(this.contexts.indexOf(t))},e.prototype.notifyError=function(t){this.error(t)},e.prototype.notifyComplete=function(t){t!==this.openSubscription&&this.closeWindow(this.contexts.indexOf(t.context))},e.prototype.closeWindow=function(t){if(-1!==t){var e=this.contexts,n=e[t],a=n.window,r=n.subscription;e.splice(t,1),a.complete(),r.unsubscribe()}},e}(r.a);function Sa(t){return function(e){return e.lift(new Oa(t))}}var Oa=function(){function t(t){this.closingSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new Ia(t,this.closingSelector))},t}(),Ia=function(t){function e(e,n){var a=t.call(this,e)||this;return a.destination=e,a.closingSelector=n,a.openWindow(),a}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.openWindow(r)},e.prototype.notifyError=function(t,e){this._error(t)},e.prototype.notifyComplete=function(t){this.openWindow(t)},e.prototype._next=function(t){this.window.next(t)},e.prototype._error=function(t){this.window.error(t),this.destination.error(t),this.unsubscribeClosingNotification()},e.prototype._complete=function(){this.window.complete(),this.destination.complete(),this.unsubscribeClosingNotification()},e.prototype.unsubscribeClosingNotification=function(){this.closingNotification&&this.closingNotification.unsubscribe()},e.prototype.openWindow=function(t){void 0===t&&(t=null),t&&(this.remove(t),t.unsubscribe());var e=this.window;e&&e.complete();var n,a=this.window=new we.a;this.destination.next(a);try{n=(0,this.closingSelector)()}catch(r){return this.destination.error(r),void this.window.error(r)}this.add(this.closingNotification=Object(i.a)(this,n))},e}(r.a);function Ca(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){var n;return"function"==typeof t[t.length-1]&&(n=t.pop()),e.lift(new ka(t,n))}}var ka=function(){function t(t,e){this.observables=t,this.project=e}return t.prototype.call=function(t,e){return e.subscribe(new Na(t,this.observables,this.project))},t}(),Na=function(t){function e(e,n,a){var r=t.call(this,e)||this;r.observables=n,r.project=a,r.toRespond=[];var s=n.length;r.values=new Array(s);for(var o=0;o<s;o++)r.toRespond.push(o);for(o=0;o<s;o++){var u=n[o];r.add(Object(i.a)(r,u,u,o))}return r}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.values[n]=e;var i=this.toRespond;if(i.length>0){var s=i.indexOf(n);-1!==s&&i.splice(s,1)}},e.prototype.notifyComplete=function(){},e.prototype._next=function(t){if(0===this.toRespond.length){var e=[t].concat(this.values);this.project?this._tryProject(e):this.destination.next(e)}},e.prototype._tryProject=function(t){var e;try{e=this.project.apply(this,t)}catch(n){return void this.destination.error(n)}this.destination.next(e)},e}(r.a),Ra=n("909l");function Aa(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){return e.lift.call(Ra.b.apply(void 0,[e].concat(t)))}}function Da(t){return function(e){return e.lift(new Ra.a(t))}}n.d(e,"audit",function(){return s}),n.d(e,"auditTime",function(){return d}),n.d(e,"buffer",function(){return f}),n.d(e,"bufferCount",function(){return b}),n.d(e,"bufferTime",function(){return x}),n.d(e,"bufferToggle",function(){return N}),n.d(e,"bufferWhen",function(){return D}),n.d(e,"catchError",function(){return P.a}),n.d(e,"combineAll",function(){return q}),n.d(e,"combineLatest",function(){return z}),n.d(e,"concat",function(){return G.a}),n.d(e,"concatAll",function(){return Y.a}),n.d(e,"concatMap",function(){return V.a}),n.d(e,"concatMapTo",function(){return H}),n.d(e,"count",function(){return B}),n.d(e,"debounce",function(){return K}),n.d(e,"debounceTime",function(){return X.a}),n.d(e,"defaultIfEmpty",function(){return J.a}),n.d(e,"delay",function(){return et}),n.d(e,"delayWhen",function(){return st}),n.d(e,"dematerialize",function(){return dt}),n.d(e,"distinct",function(){return ht.a}),n.d(e,"distinctUntilChanged",function(){return gt.a}),n.d(e,"distinctUntilKeyChanged",function(){return bt}),n.d(e,"elementAt",function(){return xt}),n.d(e,"endWith",function(){return St}),n.d(e,"every",function(){return Ot.a}),n.d(e,"exhaust",function(){return It}),n.d(e,"exhaustMap",function(){return At}),n.d(e,"expand",function(){return Lt}),n.d(e,"filter",function(){return yt.a}),n.d(e,"finalize",function(){return qt.a}),n.d(e,"find",function(){return jt}),n.d(e,"findIndex",function(){return Gt}),n.d(e,"first",function(){return Yt.a}),n.d(e,"groupBy",function(){return Vt.b}),n.d(e,"ignoreElements",function(){return Ht}),n.d(e,"isEmpty",function(){return Wt}),n.d(e,"last",function(){return Zt.a}),n.d(e,"map",function(){return Rt.a}),n.d(e,"mapTo",function(){return Xt.a}),n.d(e,"materialize",function(){return Jt}),n.d(e,"max",function(){return ne}),n.d(e,"merge",function(){return re}),n.d(e,"mergeAll",function(){return ie.a}),n.d(e,"mergeMap",function(){return se.a}),n.d(e,"flatMap",function(){return se.a}),n.d(e,"mergeMapTo",function(){return oe}),n.d(e,"mergeScan",function(){return ue}),n.d(e,"min",function(){return de}),n.d(e,"multicast",function(){return fe.a}),n.d(e,"observeOn",function(){return pe.b}),n.d(e,"onErrorResumeNext",function(){return he}),n.d(e,"pairwise",function(){return me}),n.d(e,"partition",function(){return xe}),n.d(e,"pluck",function(){return Te}),n.d(e,"publish",function(){return Se}),n.d(e,"publishBehavior",function(){return Ie}),n.d(e,"publishLast",function(){return ke}),n.d(e,"publishReplay",function(){return Re}),n.d(e,"race",function(){return De}),n.d(e,"reduce",function(){return ee.a}),n.d(e,"repeat",function(){return Le}),n.d(e,"repeatWhen",function(){return qe}),n.d(e,"retry",function(){return ze}),n.d(e,"retryWhen",function(){return Ve}),n.d(e,"refCount",function(){return Ue.a}),n.d(e,"sample",function(){return We}),n.d(e,"sampleTime",function(){return Ze}),n.d(e,"scan",function(){return tn.a}),n.d(e,"sequenceEqual",function(){return en}),n.d(e,"share",function(){return sn.a}),n.d(e,"shareReplay",function(){return on.a}),n.d(e,"single",function(){return cn}),n.d(e,"skip",function(){return fn}),n.d(e,"skipLast",function(){return gn}),n.d(e,"skipUntil",function(){return yn}),n.d(e,"skipWhile",function(){return xn}),n.d(e,"startWith",function(){return Sn.a}),n.d(e,"subscribeOn",function(){return kn}),n.d(e,"switchAll",function(){return Dn}),n.d(e,"switchMap",function(){return Rn.a}),n.d(e,"switchMapTo",function(){return En.a}),n.d(e,"take",function(){return _t.a}),n.d(e,"takeLast",function(){return Ln.a}),n.d(e,"takeUntil",function(){return Pn}),n.d(e,"takeWhile",function(){return jn}),n.d(e,"tap",function(){return Gn.a}),n.d(e,"throttle",function(){return Vn}),n.d(e,"throttleTime",function(){return Un}),n.d(e,"throwIfEmpty",function(){return vt.a}),n.d(e,"timeInterval",function(){return Xn}),n.d(e,"timeout",function(){return ra}),n.d(e,"timeoutWith",function(){return ta}),n.d(e,"timestamp",function(){return ia}),n.d(e,"toArray",function(){return oa.a}),n.d(e,"window",function(){return ua}),n.d(e,"windowCount",function(){return da}),n.d(e,"windowTime",function(){return ha}),n.d(e,"windowToggle",function(){return xa}),n.d(e,"windowWhen",function(){return Sa}),n.d(e,"withLatestFrom",function(){return Ca}),n.d(e,"zip",function(){return Aa}),n.d(e,"zipAll",function(){return Da})},ajRT:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("CcnG"),r=function(){function t(){this.hide=new a.EventEmitter}return t.prototype.close=function(){this.modalRef&&this.modalRef.hide(),this.hide.emit()},t}()},atuK:function(t,e,n){"use strict";n.d(e,"a",function(){return v}),n.d(e,"b",function(){return D}),n.d(e,"c",function(){return B});var a=n("CcnG"),r=n("ARl4"),i=n("Ip0R"),s=(n("gIcY"),n("NJnL")),o=a["\u0275crt"]({encapsulation:2,styles:[],data:{animation:[{type:7,name:"datepickerAnimation",definitions:[{type:0,name:"animated-down",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-down",animation:[{type:6,styles:{height:0,overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:0,name:"animated-up",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-up",animation:[{type:6,styles:{height:"*",overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:1,expr:"* => unanimated",animation:{type:4,styles:null,timings:"0s"},options:null}],options:{}}]}});function u(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-days-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onHoverWeek"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.dayHoverHandler(n)&&a),"onHoverWeek"===e&&(a=!1!==r.weekHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.daySelectHandler(n)&&a),a},dt,it)),a["\u0275did"](1,49152,null,0,r.z,[r.a],{calendar:[0,"calendar"],options:[1,"options"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover",onHoverWeek:"onHoverWeek"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,e.context.$implicit,a["\u0275unv"](e,1,1,a["\u0275nov"](e,2).transform(n.options)))},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,3).transform(r.daysCalendar)))?null:n.length)>1)})}function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,u)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.daysCalendar)))},null)}function l(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-month-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.monthHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.monthSelectHandler(n)&&a),a},gt,ft)),a["\u0275did"](1,49152,null,0,r.A,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function d(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,l)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.monthsCalendar)))},null)}function f(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-years-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.yearHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.yearSelectHandler(n)&&a),a},vt,bt)),a["\u0275did"](1,49152,null,0,r.B,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function p(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,f)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.yearsCalendar)))},null)}function h(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["class","bs-datepicker-buttons"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-success"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Apply"])),(t()(),a["\u0275eld"](3,0,null,null,1,"button",[["class","btn btn-default"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Cancel"]))],null,null)}function g(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","bs-datepicker-custom-range"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"bs-custom-date-view",[],null,null,null,wt,_t)),a["\u0275did"](2,49152,null,0,r.C,[],{ranges:[0,"ranges"]},null)],function(t,e){t(e,2,0,e.component._customRangesFish)},null)}function b(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,15,"div",[["class","bs-datepicker"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275eld"](2,0,null,null,11,"div",[["class","bs-datepicker-container"]],[[24,"@datepickerAnimation",0]],[[null,"@datepickerAnimation.done"]],function(t,e,n){var a=!0;return"@datepickerAnimation.done"===e&&(a=!1!==t.component.positionServiceEnable()&&a),a},null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"div",[["class","bs-calendar-container"],["role","application"]],null,null,null,null,null)),a["\u0275did"](4,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),(t()(),a["\u0275and"](16777216,null,null,1,null,c)),a["\u0275did"](7,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,d)),a["\u0275did"](9,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,p)),a["\u0275did"](11,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,h)),a["\u0275did"](13,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,g)),a["\u0275did"](15,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"bs-datepicker",n.containerClass),t(e,4,0,a["\u0275unv"](e,4,0,a["\u0275nov"](e,5).transform(n.viewMode))),t(e,7,0,"day"),t(e,9,0,"month"),t(e,11,0,"year"),t(e,13,0,!1),t(e,15,0,!1)},function(t,e){t(e,2,0,e.component.animationState)})}function m(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,b)),a["\u0275did"](1,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,a["\u0275unv"](e,1,0,a["\u0275nov"](e,2).transform(n.viewMode)))},null)}function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-datepicker-container",[["aria-label","calendar"],["class","bottom"],["role","dialog"],["style","position: absolute; display: block;"]],null,[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,3)._stopPropagation(n)&&r),r},m,o)),a["\u0275prd"](512,null,r.r,r.r,[]),a["\u0275prd"](512,null,r.s,r.s,[r.t,r.j]),a["\u0275did"](3,245760,null,0,r.b,[r.a,r.r,a.ElementRef,r.t,r.s,s.a],null,null)],function(t,e){t(e,3,0)},null)}var v=a["\u0275ccf"]("bs-datepicker-container",r.b,y,{},{},[]),_=a["\u0275crt"]({encapsulation:2,styles:[],data:{animation:[{type:7,name:"datepickerAnimation",definitions:[{type:0,name:"animated-down",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-down",animation:[{type:6,styles:{height:0,overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:0,name:"animated-up",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-up",animation:[{type:6,styles:{height:"*",overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:1,expr:"* => unanimated",animation:{type:4,styles:null,timings:"0s"},options:null}],options:{}}]}});function x(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-days-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onHoverWeek"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.dayHoverHandler(n)&&a),"onHoverWeek"===e&&(a=!1!==r.weekHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.daySelectHandler(n)&&a),a},dt,it)),a["\u0275did"](1,49152,null,0,r.z,[r.a],{calendar:[0,"calendar"],options:[1,"options"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover",onHoverWeek:"onHoverWeek"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,e.context.$implicit,a["\u0275unv"](e,1,1,a["\u0275nov"](e,2).transform(n.options)))},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,3).transform(r.daysCalendar)))?null:n.length)>1)})}function T(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,x)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.daysCalendar)))},null)}function w(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-month-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.monthHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.monthSelectHandler(n)&&a),a},gt,ft)),a["\u0275did"](1,49152,null,0,r.A,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function S(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,w)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.monthsCalendar)))},null)}function O(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-years-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.yearHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.yearSelectHandler(n)&&a),a},vt,bt)),a["\u0275did"](1,49152,null,0,r.B,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function I(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,O)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.yearsCalendar)))},null)}function C(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["class","bs-datepicker-buttons"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-success"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Apply"])),(t()(),a["\u0275eld"](3,0,null,null,1,"button",[["class","btn btn-default"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Cancel"]))],null,null)}function k(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","bs-datepicker-custom-range"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"bs-custom-date-view",[],null,null,null,wt,_t)),a["\u0275did"](2,49152,null,0,r.C,[],{ranges:[0,"ranges"]},null)],function(t,e){t(e,2,0,e.component._customRangesFish)},null)}function N(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,15,"div",[["class","bs-datepicker"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275eld"](2,0,null,null,11,"div",[["class","bs-datepicker-container"]],[[24,"@datepickerAnimation",0]],[[null,"@datepickerAnimation.done"]],function(t,e,n){var a=!0;return"@datepickerAnimation.done"===e&&(a=!1!==t.component.positionServiceEnable()&&a),a},null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"div",[["class","bs-calendar-container"],["role","application"]],null,null,null,null,null)),a["\u0275did"](4,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),(t()(),a["\u0275and"](16777216,null,null,1,null,T)),a["\u0275did"](7,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,S)),a["\u0275did"](9,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,I)),a["\u0275did"](11,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,C)),a["\u0275did"](13,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,k)),a["\u0275did"](15,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"bs-datepicker",n.containerClass),t(e,4,0,a["\u0275unv"](e,4,0,a["\u0275nov"](e,5).transform(n.viewMode))),t(e,7,0,"day"),t(e,9,0,"month"),t(e,11,0,"year"),t(e,13,0,!1),t(e,15,0,!1)},function(t,e){t(e,2,0,e.component.animationState)})}function R(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,N)),a["\u0275did"](1,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,a["\u0275unv"](e,1,0,a["\u0275nov"](e,2).transform(n.viewMode)))},null)}function A(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-datepicker-inline-container",[["style","display: inline-block;"]],null,[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,3)._stopPropagation(n)&&r),r},R,_)),a["\u0275prd"](512,null,r.r,r.r,[]),a["\u0275prd"](512,null,r.s,r.s,[r.t,r.j]),a["\u0275did"](3,245760,null,0,r.e,[r.a,r.r,a.ElementRef,r.t,r.s,s.a],null,null)],function(t,e){t(e,3,0)},null)}var D=a["\u0275ccf"]("bs-datepicker-inline-container",r.e,A,{},{},[]),E=a["\u0275crt"]({encapsulation:2,styles:[],data:{animation:[{type:7,name:"datepickerAnimation",definitions:[{type:0,name:"animated-down",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-down",animation:[{type:6,styles:{height:0,overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:0,name:"animated-up",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-up",animation:[{type:6,styles:{height:"*",overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:1,expr:"* => unanimated",animation:{type:4,styles:null,timings:"0s"},options:null}],options:{}}]}});function L(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-days-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onHoverWeek"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.dayHoverHandler(n)&&a),"onHoverWeek"===e&&(a=!1!==r.weekHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.daySelectHandler(n)&&a),a},dt,it)),a["\u0275did"](1,49152,null,0,r.z,[r.a],{calendar:[0,"calendar"],options:[1,"options"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover",onHoverWeek:"onHoverWeek"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,e.context.$implicit,a["\u0275unv"](e,1,1,a["\u0275nov"](e,2).transform(n.options)))},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,3).transform(r.daysCalendar)))?null:n.length)>1)})}function P(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,L)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.daysCalendar)))},null)}function M(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-month-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.monthHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.monthSelectHandler(n)&&a),a},gt,ft)),a["\u0275did"](1,49152,null,0,r.A,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function q(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,M)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.monthsCalendar)))},null)}function j(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"bs-years-calendar-view",[],[[2,"bs-datepicker-multiple",null]],[[null,"onNavigate"],[null,"onViewMode"],[null,"onHover"],[null,"onSelect"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.setViewMode(n)&&a),"onHover"===e&&(a=!1!==r.yearHoverHandler(n)&&a),"onSelect"===e&&(a=!1!==r.yearSelectHandler(n)&&a),a},vt,bt)),a["\u0275did"](1,49152,null,0,r.B,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode",onSelect:"onSelect",onHover:"onHover"}),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){t(e,1,0,e.context.$implicit)},function(t,e){var n,r=e.component;t(e,0,0,(null==(n=a["\u0275unv"](e,0,0,a["\u0275nov"](e,2).transform(r.daysCalendar)))?null:n.length)>1)})}function F(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"div",[["class","bs-media-container"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,2,null,j)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,2,0,a["\u0275unv"](e,2,0,a["\u0275nov"](e,3).transform(n.yearsCalendar)))},null)}function z(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["class","bs-datepicker-buttons"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-success"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Apply"])),(t()(),a["\u0275eld"](3,0,null,null,1,"button",[["class","btn btn-default"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Cancel"]))],null,null)}function G(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","bs-datepicker-custom-range"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"bs-custom-date-view",[],null,null,null,wt,_t)),a["\u0275did"](2,49152,null,0,r.C,[],{ranges:[0,"ranges"]},null)],function(t,e){t(e,2,0,e.component._customRangesFish)},null)}function Y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,15,"div",[["class","bs-datepicker"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275eld"](2,0,null,null,11,"div",[["class","bs-datepicker-container"]],[[24,"@datepickerAnimation",0]],[[null,"@datepickerAnimation.done"]],function(t,e,n){var a=!0;return"@datepickerAnimation.done"===e&&(a=!1!==t.component.positionServiceEnable()&&a),a},null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"div",[["class","bs-calendar-container"],["role","application"]],null,null,null,null,null)),a["\u0275did"](4,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef]),(t()(),a["\u0275and"](16777216,null,null,1,null,P)),a["\u0275did"](7,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,q)),a["\u0275did"](9,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,F)),a["\u0275did"](11,278528,null,0,i.NgSwitchCase,[a.ViewContainerRef,a.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,z)),a["\u0275did"](13,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,G)),a["\u0275did"](15,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"bs-datepicker",n.containerClass),t(e,4,0,a["\u0275unv"](e,4,0,a["\u0275nov"](e,5).transform(n.viewMode))),t(e,7,0,"day"),t(e,9,0,"month"),t(e,11,0,"year"),t(e,13,0,!1),t(e,15,0,!1)},function(t,e){t(e,2,0,e.component.animationState)})}function V(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,Y)),a["\u0275did"](1,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),a["\u0275pid"](131072,i.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,1,0,a["\u0275unv"](e,1,0,a["\u0275nov"](e,2).transform(n.viewMode)))},null)}function H(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"bs-daterangepicker-container",[["aria-label","calendar"],["class","bottom"],["role","dialog"],["style","position: absolute; display: block;"]],null,[[null,"click"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,3)._stopPropagation(n)&&r),r},V,E)),a["\u0275prd"](512,null,r.s,r.s,[r.t,r.j]),a["\u0275prd"](512,null,r.r,r.r,[]),a["\u0275did"](3,245760,null,0,r.i,[r.s,r.t,r.a,r.r,a.ElementRef,s.a],null,null)],function(t,e){t(e,3,0)},null)}var B=a["\u0275ccf"]("bs-daterangepicker-container",r.i,H,{},{},[]),U=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function W(t){return a["\u0275vid"](2,[(t()(),a["\u0275ted"](0,null,["",""]))],null,function(t,e){t(e,0,0,e.component.day.label)})}var K=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function $(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["class","current-timedate"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.component.title)})}var Z=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function X(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"button",[["class","current"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.view("month")&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.component.calendar.monthTitle)})}function J(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,2,"button",[["class","previous"]],[[8,"disabled",0],[4,"visibility",null]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.navTo(!0)&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["\u2039"])),(t()(),a["\u0275ted"](-1,null,[" \u200b "])),(t()(),a["\u0275and"](16777216,null,null,1,null,X)),a["\u0275did"](5,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275ted"](-1,null,[" \u200b "])),(t()(),a["\u0275eld"](7,0,null,null,2,"button",[["class","current"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.view("year")&&a),a},null,null)),(t()(),a["\u0275eld"](8,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](9,null,["",""])),(t()(),a["\u0275ted"](-1,null,[" \u200b "])),(t()(),a["\u0275eld"](11,0,null,null,2,"button",[["class","next"]],[[8,"disabled",0],[4,"visibility",null]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.navTo(!1)&&a),a},null,null)),(t()(),a["\u0275eld"](12,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["\u203a"]))],function(t,e){t(e,5,0,e.component.calendar.monthTitle)},function(t,e){var n=e.component;t(e,0,0,n.calendar.disableLeftArrow,n.calendar.hideLeftArrow?"hidden":"visible"),t(e,9,0,n.calendar.yearTitle),t(e,11,0,n.calendar.disableRightArrow,n.calendar.hideRightArrow?"hidden":"visible")})}var Q=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function tt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,15,"div",[["class","bs-timepicker-container"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,5,"div",[["class","bs-timepicker-controls"]],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,1,"button",[["class","bs-decrease"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["-"])),(t()(),a["\u0275eld"](4,0,null,null,0,"input",[["placeholder","00"],["type","text"]],[[8,"value",0]],null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"button",[["class","bs-increase"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["+"])),(t()(),a["\u0275eld"](7,0,null,null,5,"div",[["class","bs-timepicker-controls"]],null,null,null,null,null)),(t()(),a["\u0275eld"](8,0,null,null,1,"button",[["class","bs-decrease"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["-"])),(t()(),a["\u0275eld"](10,0,null,null,0,"input",[["placeholder","00"],["type","text"]],[[8,"value",0]],null,null,null,null)),(t()(),a["\u0275eld"](11,0,null,null,1,"button",[["class","bs-increase"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["+"])),(t()(),a["\u0275eld"](13,0,null,null,2,"button",[["class","switch-time-format"]],null,null,null,null,null)),(t()(),a["\u0275ted"](14,null,[""," "])),(t()(),a["\u0275eld"](15,0,null,null,0,"img",[["alt",""],["src","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAABSElEQVQYV3XQPUvDUBQG4HNuagtVqc6KgouCv6GIuIntYBLB9hcIQpLStCAIV7DYmpTcRWcXqZio3Vwc/UCc/QEqfgyKGbr0I7nS1EiHeqYzPO/h5SD0jaxUZjmSLCB+OFb+UFINFwASAEAdpu9gaGXVyAHHFQBkHpKHc6a9dzECvADyY9sqlAMsK9W0jzxDXqeytr3mhQckxSji27TJJ5/rPmIpwJJq3HrtduriYOurv1a4i1p5HnhkG9OFymi0ReoO05cGwb+ayv4dysVygjeFmsP05f8wpZQ8fsdvfmuY9zjWSNqUtgYFVnOVReILYoBFzdQI5/GGFzNHhGbeZnopDGU29sZbscgldmC99w35VOATTycIMMcBXIfpSVGzZhA6C8hh00conln6VQ9TGgV32OEAKQC4DrBq7CJwd0ggR7Vq/rPrfgB+C3sGypY5DAAAAABJRU5ErkJggg=="]],null,null,null,null,null))],null,function(t,e){var n=e.component;t(e,4,0,n.hours),t(e,10,0,n.minutes),t(e,14,0,n.ampm)})}var et=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function nt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"bs-current-date",[["title","hey there"]],null,null,null,$,K)),a["\u0275did"](1,49152,null,0,r.v,[],{title:[0,"title"]},null)],function(t,e){t(e,1,0,"hey there")},null)}function at(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"bs-timepicker",[],null,null,null,tt,Q)),a["\u0275did"](1,49152,null,0,r.x,[],null,null)],null,null)}function rt(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,1,null,nt)),a["\u0275did"](1,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275eld"](2,0,null,null,1,"div",[["class","bs-datepicker-head"]],null,null,null,null,null)),a["\u0275ncd"](null,0),(t()(),a["\u0275eld"](4,0,null,null,1,"div",[["class","bs-datepicker-body"]],null,null,null,null,null)),a["\u0275ncd"](null,1),(t()(),a["\u0275and"](16777216,null,null,1,null,at)),a["\u0275did"](7,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,!1),t(e,7,0,!1)},null)}var it=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function st(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"th",[],null,null,null,null,null))],null,null)}function ot(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"th",[["aria-label","weekday"]],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,[""," "]))],null,function(t,e){t(e,1,0,e.component.calendar.weekdays[e.context.index])})}function ut(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"td",[["class","week"]],[[2,"active-week",null]],null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,[[null,"click"],[null,"mouseenter"],[null,"mouseleave"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.selectWeek(t.parent.context.$implicit)&&a),"mouseenter"===e&&(a=!1!==r.weekHoverHandler(t.parent.context.$implicit,!0)&&a),"mouseleave"===e&&(a=!1!==r.weekHoverHandler(t.parent.context.$implicit,!1)&&a),a},null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){var n=e.component;t(e,0,0,n.isWeekHovered),t(e,2,0,n.calendar.weekNumbers[e.parent.context.index])})}function ct(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"td",[["role","gridcell"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,2,"span",[["bsDatepickerDayDecorator",""]],[[2,"disabled",null],[2,"is-highlighted",null],[2,"is-other-month",null],[2,"is-active-other-month",null],[2,"in-range",null],[2,"select-start",null],[2,"select-end",null],[2,"selected",null]],[[null,"click"],[null,"mouseenter"],[null,"mouseleave"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.selectDay(t.context.$implicit)&&a),"mouseenter"===e&&(a=!1!==r.hoverDay(t.context.$implicit,!0)&&a),"mouseleave"===e&&(a=!1!==r.hoverDay(t.context.$implicit,!1)&&a),a},W,U)),a["\u0275did"](2,114688,null,0,r.u,[r.a,a.ElementRef,a.Renderer2],{day:[0,"day"]},null),(t()(),a["\u0275ted"](3,null,["",""]))],function(t,e){t(e,2,0,e.context.$implicit)},function(t,e){t(e,1,0,a["\u0275nov"](e,2).day.isDisabled,a["\u0275nov"](e,2).day.isHovered,a["\u0275nov"](e,2).day.isOtherMonth,a["\u0275nov"](e,2).day.isOtherMonthHovered,a["\u0275nov"](e,2).day.isInRange,a["\u0275nov"](e,2).day.isSelectionStart,a["\u0275nov"](e,2).day.isSelectionEnd,a["\u0275nov"](e,2).day.isSelected),t(e,3,0,e.context.$implicit.label)})}function lt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,ut)),a["\u0275did"](2,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,ct)),a["\u0275did"](4,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.options.showWeekNumbers),t(e,4,0,e.context.$implicit.days)},null)}function dt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,13,"bs-calendar-layout",[],null,null,null,rt,et)),a["\u0275did"](1,49152,null,0,r.y,[],null,null),(t()(),a["\u0275eld"](2,0,null,0,1,"bs-datepicker-navigation-view",[],null,[[null,"onNavigate"],[null,"onViewMode"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.changeViewMode(n)&&a),a},J,Z)),a["\u0275did"](3,49152,null,0,r.w,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode"}),(t()(),a["\u0275eld"](4,0,null,1,9,"table",[["class","days weeks"],["role","grid"]],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,5,"thead",[],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,st)),a["\u0275did"](8,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,ot)),a["\u0275did"](10,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275eld"](11,0,null,null,2,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,lt)),a["\u0275did"](13,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.calendar),t(e,8,0,n.options.showWeekNumbers),t(e,10,0,n.calendar.weekdays),t(e,13,0,n.calendar.weeks)},null)}var ft=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function pt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"td",[["role","gridcell"]],[[2,"disabled",null],[2,"is-highlighted",null]],[[null,"click"],[null,"mouseenter"],[null,"mouseleave"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.viewMonth(t.context.$implicit)&&a),"mouseenter"===e&&(a=!1!==r.hoverMonth(t.context.$implicit,!0)&&a),"mouseleave"===e&&(a=!1!==r.hoverMonth(t.context.$implicit,!1)&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,0,0,e.context.$implicit.isDisabled,e.context.$implicit.isHovered),t(e,2,0,e.context.$implicit.label)})}function ht(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"tr",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,pt)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.context.$implicit)},null)}function gt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,7,"bs-calendar-layout",[],null,null,null,rt,et)),a["\u0275did"](1,49152,null,0,r.y,[],null,null),(t()(),a["\u0275eld"](2,0,null,0,1,"bs-datepicker-navigation-view",[],null,[[null,"onNavigate"],[null,"onViewMode"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.changeViewMode(n)&&a),a},J,Z)),a["\u0275did"](3,49152,null,0,r.w,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode"}),(t()(),a["\u0275eld"](4,0,null,1,3,"table",[["class","months"],["role","grid"]],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,2,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,ht)),a["\u0275did"](7,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.calendar),t(e,7,0,n.calendar.months)},null)}var bt=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function mt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"td",[["role","gridcell"]],[[2,"disabled",null],[2,"is-highlighted",null]],[[null,"click"],[null,"mouseenter"],[null,"mouseleave"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.viewYear(t.context.$implicit)&&a),"mouseenter"===e&&(a=!1!==r.hoverYear(t.context.$implicit,!0)&&a),"mouseleave"===e&&(a=!1!==r.hoverYear(t.context.$implicit,!1)&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,0,0,e.context.$implicit.isDisabled,e.context.$implicit.isHovered),t(e,2,0,e.context.$implicit.label)})}function yt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"tr",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,mt)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.context.$implicit)},null)}function vt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,7,"bs-calendar-layout",[],null,null,null,rt,et)),a["\u0275did"](1,49152,null,0,r.y,[],null,null),(t()(),a["\u0275eld"](2,0,null,0,1,"bs-datepicker-navigation-view",[],null,[[null,"onNavigate"],[null,"onViewMode"]],function(t,e,n){var a=!0,r=t.component;return"onNavigate"===e&&(a=!1!==r.navigateTo(n)&&a),"onViewMode"===e&&(a=!1!==r.changeViewMode(n)&&a),a},J,Z)),a["\u0275did"](3,49152,null,0,r.w,[],{calendar:[0,"calendar"]},{onNavigate:"onNavigate",onViewMode:"onViewMode"}),(t()(),a["\u0275eld"](4,0,null,1,3,"table",[["class","years"],["role","grid"]],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,2,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,yt)),a["\u0275did"](7,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.calendar),t(e,7,0,n.calendar.years)},null)}var _t=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function xt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"button",[],null,null,null,null,null)),(t()(),a["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.context.$implicit.label)})}function Tt(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"button",[],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Custom Range"]))],null,null)}function wt(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,4,"div",[["class","bs-datepicker-predefined-btns"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,xt)),a["\u0275did"](2,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,Tt)),a["\u0275did"](4,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.ranges),t(e,4,0,n.isCustomRangeShown)},null)}},awvh:function(t,e,n){"use strict";function a(t){return Error.call(this),this.message=t?t.length+" errors occurred during unsubscription:\n"+t.map(function(t,e){return e+1+") "+t.toString()}).join("\n "):"",this.name="UnsubscriptionError",this.errors=t,this}n.d(e,"a",function(){return r}),a.prototype=Object.create(Error.prototype);var r=a},b1Dy:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},b5OY:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("pxLl");var a=function(){function t(t,e){this.performanceCounterService=t,this.i18n=e,this.columns=[],this.counters=[]}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"name",flexGrow:1},{name:this.i18n("Description"),prop:"description",flexGrow:1},{name:this.i18n("Value"),prop:"value",cellTemplate:this.valueTpl,flexGrow:1}]},t.prototype.getCounters=function(t){var e=this;this.performanceCounterService.get(this.serviceType,this.serviceId).subscribe(function(t){e.counters=t},function(n){404===n.status?(n.preventDefault(),e.counters=null):t.error()})},t}()},b7mW:function(t,e,n){"use strict";function a(){return Error.call(this),this.message="argument out of range",this.name="ArgumentOutOfRangeError",this}n.d(e,"a",function(){return r}),a.prototype=Object.create(Error.prototype);var r=a},bOMt:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"s\xf8ndag_mandag_tirsdag_onsdag_torsdag_fredag_l\xf8rdag".split("_"),weekdaysShort:"s\xf8._ma._ti._on._to._fr._l\xf8.".split("_"),weekdaysMin:"s\xf8_ma_ti_on_to_fr_l\xf8".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i g\xe5r kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",ss:"%d sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"ett \xe5r",yy:"%d \xe5r"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},bXm7:function(t,e,n){!function(t){"use strict";var e={0:"-\u0448\u0456",1:"-\u0448\u0456",2:"-\u0448\u0456",3:"-\u0448\u0456",4:"-\u0448\u0456",5:"-\u0448\u0456",6:"-\u0448\u044b",7:"-\u0448\u0456",8:"-\u0448\u0456",9:"-\u0448\u044b",10:"-\u0448\u044b",20:"-\u0448\u044b",30:"-\u0448\u044b",40:"-\u0448\u044b",50:"-\u0448\u0456",60:"-\u0448\u044b",70:"-\u0448\u0456",80:"-\u0448\u0456",90:"-\u0448\u044b",100:"-\u0448\u0456"};t.defineLocale("kk",{months:"\u049b\u0430\u04a3\u0442\u0430\u0440_\u0430\u049b\u043f\u0430\u043d_\u043d\u0430\u0443\u0440\u044b\u0437_\u0441\u04d9\u0443\u0456\u0440_\u043c\u0430\u043c\u044b\u0440_\u043c\u0430\u0443\u0441\u044b\u043c_\u0448\u0456\u043b\u0434\u0435_\u0442\u0430\u043c\u044b\u0437_\u049b\u044b\u0440\u043a\u04af\u0439\u0435\u043a_\u049b\u0430\u0437\u0430\u043d_\u049b\u0430\u0440\u0430\u0448\u0430_\u0436\u0435\u043b\u0442\u043e\u049b\u0441\u0430\u043d".split("_"),monthsShort:"\u049b\u0430\u04a3_\u0430\u049b\u043f_\u043d\u0430\u0443_\u0441\u04d9\u0443_\u043c\u0430\u043c_\u043c\u0430\u0443_\u0448\u0456\u043b_\u0442\u0430\u043c_\u049b\u044b\u0440_\u049b\u0430\u0437_\u049b\u0430\u0440_\u0436\u0435\u043b".split("_"),weekdays:"\u0436\u0435\u043a\u0441\u0435\u043d\u0431\u0456_\u0434\u04af\u0439\u0441\u0435\u043d\u0431\u0456_\u0441\u0435\u0439\u0441\u0435\u043d\u0431\u0456_\u0441\u04d9\u0440\u0441\u0435\u043d\u0431\u0456_\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456_\u0436\u04b1\u043c\u0430_\u0441\u0435\u043d\u0431\u0456".split("_"),weekdaysShort:"\u0436\u0435\u043a_\u0434\u04af\u0439_\u0441\u0435\u0439_\u0441\u04d9\u0440_\u0431\u0435\u0439_\u0436\u04b1\u043c_\u0441\u0435\u043d".split("_"),weekdaysMin:"\u0436\u043a_\u0434\u0439_\u0441\u0439_\u0441\u0440_\u0431\u0439_\u0436\u043c_\u0441\u043d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0411\u04af\u0433\u0456\u043d \u0441\u0430\u0493\u0430\u0442] LT",nextDay:"[\u0415\u0440\u0442\u0435\u04a3 \u0441\u0430\u0493\u0430\u0442] LT",nextWeek:"dddd [\u0441\u0430\u0493\u0430\u0442] LT",lastDay:"[\u041a\u0435\u0448\u0435 \u0441\u0430\u0493\u0430\u0442] LT",lastWeek:"[\u04e8\u0442\u043a\u0435\u043d \u0430\u043f\u0442\u0430\u043d\u044b\u04a3] dddd [\u0441\u0430\u0493\u0430\u0442] LT",sameElse:"L"},relativeTime:{future:"%s \u0456\u0448\u0456\u043d\u0434\u0435",past:"%s \u0431\u04b1\u0440\u044b\u043d",s:"\u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u0441\u0435\u043a\u0443\u043d\u0434",ss:"%d \u0441\u0435\u043a\u0443\u043d\u0434",m:"\u0431\u0456\u0440 \u043c\u0438\u043d\u0443\u0442",mm:"%d \u043c\u0438\u043d\u0443\u0442",h:"\u0431\u0456\u0440 \u0441\u0430\u0493\u0430\u0442",hh:"%d \u0441\u0430\u0493\u0430\u0442",d:"\u0431\u0456\u0440 \u043a\u04af\u043d",dd:"%d \u043a\u04af\u043d",M:"\u0431\u0456\u0440 \u0430\u0439",MM:"%d \u0430\u0439",y:"\u0431\u0456\u0440 \u0436\u044b\u043b",yy:"%d \u0436\u044b\u043b"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0448\u0456|\u0448\u044b)/,ordinal:function(t){return t+(e[t]||e[t%10]||e[t>=100?100:null])},week:{dow:1,doy:7}})}(n("wd/R"))},bYM6:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ar-tn",{months:"\u062c\u0627\u0646\u0641\u064a_\u0641\u064a\u0641\u0631\u064a_\u0645\u0627\u0631\u0633_\u0623\u0641\u0631\u064a\u0644_\u0645\u0627\u064a_\u062c\u0648\u0627\u0646_\u062c\u0648\u064a\u0644\u064a\u0629_\u0623\u0648\u062a_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),monthsShort:"\u062c\u0627\u0646\u0641\u064a_\u0641\u064a\u0641\u0631\u064a_\u0645\u0627\u0631\u0633_\u0623\u0641\u0631\u064a\u0644_\u0645\u0627\u064a_\u062c\u0648\u0627\u0646_\u062c\u0648\u064a\u0644\u064a\u0629_\u0623\u0648\u062a_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0623\u062d\u062f_\u0625\u062b\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0623\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",ss:"%d \u062b\u0627\u0646\u064a\u0629",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:1,doy:4}})}()},bidN:function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": ("+t.xLabel+", "+t.yLabel+", "+e.datasets[t.datasetIndex].data[t.index].r+")"}}}}),t.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:r.Point,update:function(t){var e=this,n=e.getMeta();i.each(n.data,function(n,a){e.updateElement(n,a,t)})},updateElement:function(t,e,n){var a=this,r=a.getMeta(),i=t.custom||{},s=a.getScaleForId(r.xAxisID),o=a.getScaleForId(r.yAxisID),u=a._resolveElementOptions(t,e),c=a.getDataset().data[e],l=a.index,d=n?s.getPixelForDecimal(.5):s.getPixelForValue("object"==typeof c?c:NaN,e,l),f=n?o.getBasePixel():o.getPixelForValue(c,e,l);t._xScale=s,t._yScale=o,t._options=u,t._datasetIndex=l,t._index=e,t._model={backgroundColor:u.backgroundColor,borderColor:u.borderColor,borderWidth:u.borderWidth,hitRadius:u.hitRadius,pointStyle:u.pointStyle,rotation:u.rotation,radius:n?0:u.radius,skip:i.skip||isNaN(d)||isNaN(f),x:d,y:f},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=i.valueOrDefault(n.hoverBackgroundColor,i.getHoverColor(n.backgroundColor)),e.borderColor=i.valueOrDefault(n.hoverBorderColor,i.getHoverColor(n.borderColor)),e.borderWidth=i.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},_resolveElementOptions:function(t,e){var n,a,r,s=this.chart,o=s.data.datasets[this.index],u=t.custom||{},c=s.options.elements.point,l=i.options.resolve,d=o.data[e],f={},p={chart:s,dataIndex:e,dataset:o,datasetIndex:this.index},h=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle","rotation"];for(n=0,a=h.length;n<a;++n)f[r=h[n]]=l([u[r],o[r],c[r]],p,e);return f.radius=l([u.radius,d?d.r:void 0,o.radius,c.radius],p,e),f}})}},bne5:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("6blF"),r=n("isby"),i=n("2Bdj"),s=n("67Y/");function o(t,e,n,u){return Object(i.a)(n)&&(u=n,n=void 0),u?o(t,e,n).pipe(Object(s.a)(function(t){return Object(r.a)(t)?u.apply(void 0,t):u(t)})):new a.a(function(a){!function t(e,n,a,r,i){var s;if(function(t){return t&&"function"==typeof t.addEventListener&&"function"==typeof t.removeEventListener}(e)){var o=e;e.addEventListener(n,a,i),s=function(){return o.removeEventListener(n,a,i)}}else if(function(t){return t&&"function"==typeof t.on&&"function"==typeof t.off}(e)){var u=e;e.on(n,a),s=function(){return u.off(n,a)}}else if(function(t){return t&&"function"==typeof t.addListener&&"function"==typeof t.removeListener}(e)){var c=e;e.addListener(n,a),s=function(){return c.removeListener(n,a)}}else{if(!e||!e.length)throw new TypeError("Invalid event target");for(var l=0,d=e.length;l<d;l++)t(e[l],n,a,r,i)}r.add(s)}(t,e,function(t){a.next(arguments.length>1?Array.prototype.slice.call(arguments):t)},a,n)})}},bpWZ:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("FO+L")),a(n("nhM1")),a(n("BARL"))},bpih:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_luned\xec_marted\xec_mercoled\xec_gioved\xec_venerd\xec_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(t){return(/^[0-9].+$/.test(t)?"tra":"in")+" "+t},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},buEt:function(t,e,n){"use strict";n.r(e);var a=n("DtyJ");n.d(e,"Subject",function(){return a.Subject})},bxKX:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("it-ch",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_luned\xec_marted\xec_mercoled\xec_gioved\xec_venerd\xec_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(t){return(/^[0-9].+$/.test(t)?"tra":"in")+" "+t},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},cRix:function(t,e,n){!function(t){"use strict";var e="jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.".split("_"),n="jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_");t.defineLocale("fy",{months:"jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsParseExact:!0,weekdays:"snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon".split("_"),weekdaysShort:"si._mo._ti._wo._to._fr._so.".split("_"),weekdaysMin:"Si_Mo_Ti_Wo_To_Fr_So".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[hjoed om] LT",nextDay:"[moarn om] LT",nextWeek:"dddd [om] LT",lastDay:"[juster om] LT",lastWeek:"[\xf4fr\xfbne] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oer %s",past:"%s lyn",s:"in pear sekonden",ss:"%d sekonden",m:"ien min\xfat",mm:"%d minuten",h:"ien oere",hh:"%d oeren",d:"ien dei",dd:"%d dagen",M:"ien moanne",MM:"%d moannen",y:"ien jier",yy:"%d jierren"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}})}(n("wd/R"))},cdu6:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha"),s=n("g8vO");function o(t){var e,n,a=[];for(e=0,n=t.length;e<n;++e)a.push(t[e].label);return a}function u(t,e,n){var a=t.getPixelForTick(e);return n&&(a-=0===e?(t.getPixelForTick(1)-a)/2:(a-t.getPixelForTick(e-1))/2),a}function c(t,e,n){return i.isArray(e)?i.longestText(t,n,e):t.measureText(e).width}function l(t){var e=i.valueOrDefault,n=a.global,r=e(t.fontSize,n.defaultFontSize),s=e(t.fontStyle,n.defaultFontStyle),o=e(t.fontFamily,n.defaultFontFamily);return{size:r,style:s,family:o,font:i.fontString(r,s,o)}}function d(t){return i.options.toLineHeight(i.valueOrDefault(t.lineHeight,1.2),i.valueOrDefault(t.fontSize,a.global.defaultFontSize))}a._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:s.formatters.values,minor:{},major:{}}}),t.exports=r.extend({getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;for(var e in!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1}),t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){i.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var a,r,s,o,u,c,l=this;for(l.beforeUpdate(),l.maxWidth=t,l.maxHeight=e,l.margins=i.extend({left:0,right:0,top:0,bottom:0},n),l.longestTextCache=l.longestTextCache||{},l.beforeSetDimensions(),l.setDimensions(),l.afterSetDimensions(),l.beforeDataLimits(),l.determineDataLimits(),l.afterDataLimits(),l.beforeBuildTicks(),u=l.buildTicks()||[],l.afterBuildTicks(),l.beforeTickToLabelConversion(),s=l.convertTicksToLabels(u)||l.ticks,l.afterTickToLabelConversion(),l.ticks=s,a=0,r=s.length;a<r;++a)o=s[a],(c=u[a])?c.label=o:u.push(c={label:o,major:!1});return l._ticks=u,l.beforeCalculateTickRotation(),l.calculateTickRotation(),l.afterCalculateTickRotation(),l.beforeFit(),l.fit(),l.afterFit(),l.afterUpdate(),l.minSize},afterUpdate:function(){i.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){i.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){i.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){i.callback(this.options.beforeDataLimits,[this])},determineDataLimits:i.noop,afterDataLimits:function(){i.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){i.callback(this.options.beforeBuildTicks,[this])},buildTicks:i.noop,afterBuildTicks:function(){i.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){i.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){i.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){i.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,n=t.options.ticks,a=o(t._ticks),r=l(n);e.font=r.font;var s=n.minRotation||0;if(a.length&&t.options.display&&t.isHorizontal())for(var u,c=i.longestText(e,r.font,a,t.longestTextCache),d=c,f=t.getPixelForTick(1)-t.getPixelForTick(0)-6;d>f&&s<n.maxRotation;){var p=i.toRadians(s);if(u=Math.cos(p),Math.sin(p)*c>t.maxHeight){s--;break}s++,d=u*c}t.labelRotation=s},afterCalculateTickRotation:function(){i.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){i.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=o(t._ticks),a=t.options,r=a.ticks,s=a.scaleLabel,u=a.gridLines,f=a.display,p=t.isHorizontal(),h=l(r),g=a.gridLines.tickMarkLength;if(e.width=p?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:f&&u.drawTicks?g:0,e.height=p?f&&u.drawTicks?g:0:t.maxHeight,s.display&&f){var b=d(s)+i.options.toPadding(s.padding).height;p?e.height+=b:e.width+=b}if(r.display&&f){var m=i.longestText(t.ctx,h.font,n,t.longestTextCache),y=i.numberOfLabelLines(n),v=.5*h.size,_=t.options.ticks.padding;if(p){t.longestLabelWidth=m;var x=i.toRadians(t.labelRotation),T=Math.cos(x),w=Math.sin(x);e.height=Math.min(t.maxHeight,e.height+(w*m+h.size*y+v*(y-1)+v)+_),t.ctx.font=h.font;var S=c(t.ctx,n[0],h.font),O=c(t.ctx,n[n.length-1],h.font);0!==t.labelRotation?(t.paddingLeft="bottom"===a.position?T*S+3:T*v+3,t.paddingRight="bottom"===a.position?T*v+3:T*O+3):(t.paddingLeft=S/2+3,t.paddingRight=O/2+3)}else r.mirror?m=0:m+=_+v,e.width=Math.min(t.maxWidth,e.width+m),t.paddingTop=h.size/2,t.paddingBottom=h.size/2}t.handleMargins(),t.width=e.width,t.height=e.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){i.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(i.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:i.noop,getPixelForValue:i.noop,getValueForPixel:i.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var a=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),r=a*t+e.paddingLeft;return n&&(r+=a/2),e.left+Math.round(r)+(e.isFullWidth()?e.margins.left:0)}return e.top+t*((e.height-(e.paddingTop+e.paddingBottom))/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;return e.isHorizontal()?e.left+Math.round((e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft)+(e.isFullWidth()?e.margins.left:0):e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,n,a,r,s=this,o=s.isHorizontal(),u=s.options.ticks.minor,c=t.length,l=i.toRadians(s.labelRotation),d=Math.cos(l),f=s.longestLabelWidth*d,p=[];for(u.maxTicksLimit&&(r=u.maxTicksLimit),o&&(e=!1,(f+u.autoSkipPadding)*c>s.width-(s.paddingLeft+s.paddingRight)&&(e=1+Math.floor((f+u.autoSkipPadding)*c/(s.width-(s.paddingLeft+s.paddingRight)))),r&&c>r&&(e=Math.max(e,Math.floor(c/r)))),n=0;n<c;n++)a=t[n],(e>1&&n%e>0||n%e==0&&n+e>=c)&&n!==c-1&&delete a.label,p.push(a);return p},draw:function(t){var e=this,n=e.options;if(n.display){var r=e.ctx,s=a.global,o=n.ticks.minor,c=n.ticks.major||o,f=n.gridLines,p=n.scaleLabel,h=0!==e.labelRotation,g=e.isHorizontal(),b=o.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),m=i.valueOrDefault(o.fontColor,s.defaultFontColor),y=l(o),v=i.valueOrDefault(c.fontColor,s.defaultFontColor),_=l(c),x=f.drawTicks?f.tickMarkLength:0,T=i.valueOrDefault(p.fontColor,s.defaultFontColor),w=l(p),S=i.options.toPadding(p.padding),O=i.toRadians(e.labelRotation),I=[],C=e.options.gridLines.lineWidth,k="right"===n.position?e.left:e.right-C-x,N="right"===n.position?e.left+x:e.right,R="bottom"===n.position?e.top+C:e.bottom-x-C,A="bottom"===n.position?e.top+C+x:e.bottom+C;if(i.each(b,function(a,r){if(!i.isNullOrUndef(a.label)){var c,l,d,p,m,y,v,_,T,w,S,D,E,L,P=a.label;r===e.zeroLineIndex&&n.offset===f.offsetGridLines?(c=f.zeroLineWidth,l=f.zeroLineColor,d=f.zeroLineBorderDash,p=f.zeroLineBorderDashOffset):(c=i.valueAtIndexOrDefault(f.lineWidth,r),l=i.valueAtIndexOrDefault(f.color,r),d=i.valueOrDefault(f.borderDash,s.borderDash),p=i.valueOrDefault(f.borderDashOffset,s.borderDashOffset));var M="middle",q="middle",j=o.padding;if(g){var F=x+j;"bottom"===n.position?(q=h?"middle":"top",M=h?"right":"center",L=e.top+F):(q=h?"middle":"bottom",M=h?"left":"center",L=e.bottom-F);var z=u(e,r,f.offsetGridLines&&b.length>1);z<e.left&&(l="rgba(0,0,0,0)"),z+=i.aliasPixel(c),E=e.getPixelForTick(r)+o.labelOffset,m=v=T=S=z,y=R,_=A,w=t.top,D=t.bottom+C}else{var G,Y="left"===n.position;o.mirror?(M=Y?"left":"right",G=j):(M=Y?"right":"left",G=x+j),E=Y?e.right-G:e.left+G;var V=u(e,r,f.offsetGridLines&&b.length>1);V<e.top&&(l="rgba(0,0,0,0)"),V+=i.aliasPixel(c),L=e.getPixelForTick(r)+o.labelOffset,m=k,v=N,T=t.left,S=t.right+C,y=_=w=D=V}I.push({tx1:m,ty1:y,tx2:v,ty2:_,x1:T,y1:w,x2:S,y2:D,labelX:E,labelY:L,glWidth:c,glColor:l,glBorderDash:d,glBorderDashOffset:p,rotation:-1*O,label:P,major:a.major,textBaseline:q,textAlign:M})}}),i.each(I,function(t){if(f.display&&(r.save(),r.lineWidth=t.glWidth,r.strokeStyle=t.glColor,r.setLineDash&&(r.setLineDash(t.glBorderDash),r.lineDashOffset=t.glBorderDashOffset),r.beginPath(),f.drawTicks&&(r.moveTo(t.tx1,t.ty1),r.lineTo(t.tx2,t.ty2)),f.drawOnChartArea&&(r.moveTo(t.x1,t.y1),r.lineTo(t.x2,t.y2)),r.stroke(),r.restore()),o.display){r.save(),r.translate(t.labelX,t.labelY),r.rotate(t.rotation),r.font=t.major?_.font:y.font,r.fillStyle=t.major?v:m,r.textBaseline=t.textBaseline,r.textAlign=t.textAlign;var n=t.label;if(i.isArray(n))for(var a=n.length,s=1.5*y.size,u=e.isHorizontal()?0:-s*(a-1)/2,c=0;c<a;++c)r.fillText(""+n[c],0,u),u+=s;else r.fillText(n,0,0);r.restore()}}),p.display){var D,E,L=0,P=d(p)/2;if(g)D=e.left+(e.right-e.left)/2,E="bottom"===n.position?e.bottom-P-S.bottom:e.top+P+S.top;else{var M="left"===n.position;D=M?e.left+P+S.top:e.right-P-S.top,E=e.top+(e.bottom-e.top)/2,L=M?-.5*Math.PI:.5*Math.PI}r.save(),r.translate(D,E),r.rotate(L),r.textAlign="center",r.textBaseline="middle",r.fillStyle=T,r.font=w.font,r.fillText(p.labelString,0,0),r.restore()}if(f.drawBorder){r.lineWidth=i.valueAtIndexOrDefault(f.lineWidth,0),r.strokeStyle=i.valueAtIndexOrDefault(f.color,0);var q=e.left,j=e.right+C,F=e.top,z=e.bottom+C,G=i.aliasPixel(r.lineWidth);g?(F=z="top"===n.position?e.bottom:e.top,F+=G,z+=G):(q=j="left"===n.position?e.right:e.left,q+=G,j+=G),r.beginPath(),r.moveTo(q,F),r.lineTo(j,z),r.stroke()}}}})},crnd:function(t,e,n){var a={"./ceph/block/block.module.ngfactory":["J6Oi",2,0,7],"./ceph/pool/pool.module.ngfactory":["nOaW",2,0,8],"./ceph/rgw/rgw.module.ngfactory":["Znkk",0,6],"./core/auth/auth.module.ngfactory":["DY6s",0,9]};function r(t){var e=a[t];return e?Promise.all(e.slice(1).map(n.e)).then(function(){return n(e[0])}):Promise.resolve().then(function(){var e=new Error("Cannot find module '"+t+"'");throw e.code="MODULE_NOT_FOUND",e})}r.keys=function(){return Object.keys(a)},r.id="crnd",t.exports=r},csGn:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="es-ES">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Alternar navegaci\xf3n</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Consola</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Cl\xfaster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Hosts</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitores</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSDs</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Configuraci\xf3n</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>Mapa de CRUSH</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>M\xf3dulos de gestor</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Registros</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Alertas</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Repositorios</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Bloque</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Im\xe1genes</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Duplicaci\xf3n</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Sistemas de archivos</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Object Gateway</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemons</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Usuarios</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Papeleras</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Obteniendo datos \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\npara \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Espere.\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Mostrando datos guardados previamente en cach\xe9\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\npara \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>No se han podido cargar los datos\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> para\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\nConsulte el estado del cl\xfaster.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Atr\xe1s</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Seleccione un idioma</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Cargando datos del panel...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Consulte la\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentaci\xf3n\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre c\xf3mo\nconfigurar y habilitar la supervisi\xf3n.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>No existe la consola de Grafana. Consulte la\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentaci\xf3n\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre c\xf3mo\n a\xf1adir consolas a Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Selector de hora de Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Restablecer ajustes</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Error al cargar los datos.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>seleccionados</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>encontrados</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>total</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Editar</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nombre</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Descripci\xf3n</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Descripci\xf3n larga</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Opci\xf3n por defecto</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Daemon por defecto</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Servicios</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Valores</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>El valor introducido es demasiado alto. No debe ser mayor que \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>El valor introducido es demasiado bajo. No debe ser menor que \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Guardar</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>Visor del mapa de CRUSH</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Lista de hosts</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Rendimiento general</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>No se encuentra ninguna entrada</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Registros del cl\xfaster</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Registros de auditor\xeda</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Cargando configuraci\xf3n...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>No es posible cargar la configuraci\xf3n.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>M\xf3dulo del gestor de edici\xf3n</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>El valor introducido no es un UUID v\xe1lido, por ejemplo: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>El valor introducido debe ser una direcci\xf3n IP v\xe1lida.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Este campo es obligatorio.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>El valor introducido es demasiado alto. Debe ser menor o igual que \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>El valor introducido es demasiado bajo. Debe ser mayor o igual que \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>El valor introducido debe ser un n\xfamero.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>El valor introducido debe ser un n\xfamero o un decimal.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Actualizar</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Estado</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>ID de cl\xfaster</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>Mapa de supervisi\xf3n modificado</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>\xc9poca de mapa de supervisi\xf3n</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>qu\xf3rum de con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>qu\xf3rum de mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>con requerido</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>mon requerido</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>Con qu\xf3rum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Sin qu\xf3rum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Cancelar</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>\xbfSeguro que quiere \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> el elemento \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> seleccionado?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>S\xed, seguro.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Indicadores OSD de todo el cl\xfaster</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Enviar</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Avanzado...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Prioridad de recuperaci\xf3n de OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Prioridad</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Personalizar valores de prioridad</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Este campo es obligatorio.</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>El valor introducido es demasiado alto. No debe ser mayor que \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>El valor introducido es demasiado bajo. No debe ser menor que \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Reequilibrar peso de OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>El valor debe estar entre 0 y 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Reequilibrar peso</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Depuraci\xf3n de OSDs\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Profundo} }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Se dispone a aplicar una \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>depuraci\xf3n\n al OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {profundo} }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Lista de OSD</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Si contin\xfaa, el \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n se marcar\xe1 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>No es seguro destruir el OSD.</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>Si contin\xfaa, el \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n se \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Detalles</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Valor</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Cerrar</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Suprimir</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Estado</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Estad\xedsticas</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Consulte la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentaci\xf3n\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre c\xf3mo configurar y habilitar la funci\xf3n de gesti\xf3n de NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Clientes</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Cualquier cliente puede acceder</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Destinatarios</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Campo requerido</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Debe contener uno o varios valores separados por comas</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Por ejemplo:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Tipo de acceso</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Reducir privilegios</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>A\xf1adir clientes</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Cargando...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- No hay ning\xfan cl\xfaster disponible --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Seleccione el cl\xfaster --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>A\xf1adir daemon</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Motor de almacenamiento</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- No hay ning\xfan repositorio de datos disponible --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Seleccione el motor de almacenamiento --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Usuario de Object Gateway</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- No hay ning\xfan usuario disponible --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Seleccione el usuario de Object Gateway --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>ID de usuario de CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- No hay ning\xfan cliente disponible --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Seleccione el cliente de CephX --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nombre de CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Etiqueta de seguridad</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Habilitar etiqueta de seguridad</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>Ruta de CephFS</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>La ruta debe empezar por "/" y puede ir seguida de una palabra</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Se crear\xe1 un directorio nuevo</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Ruta</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>La ruta solo puede ser una "/" o una palabra</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Se crear\xe1 una papelera nueva</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protocolo NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Etiqueta NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Acceso alternativo para montajes \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (no debe empezar con /).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Puede que los clientes no monten subdirectorios (es decir, si Etiqueta = foo, el cliente puede que no monte foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>Al usar distintas opciones de Etiqueta, la misma Ruta se puede exportar varias veces.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>La posici\xf3n que ocupa esta exportaci\xf3n \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n en \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (debe ser exclusiva).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>Al usar distintas opciones de Pseudo, la misma Ruta se puede exportar varias veces.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- No hay ning\xfan tipo de acceso disponible --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Seleccione el tipo de acceso --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- No hay ninguna reducci\xf3n de privilegios disponible --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- Seleccione el tipo de reducci\xf3n de privilegios de ID de usuario que se va a realizar --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protocolo de transporte</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>\xa1Bienvenidos a Ceph!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>El nombre de usuario es obligatorio</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>La contrase\xf1a es obligatoria</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Entrada</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Lo sentimos. El usuario no existe en Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Vuelva a la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>P\xe1gina de entrada\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Saldr\xe1 del proveedor de identidad cuando vuelva a intentar entrar a la sesi\xf3n.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Prohibido</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Lo sentimos. No tiene permiso para ver lo que busca.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Lo sentimos. No se encuentra lo que busca</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Eliminar todo</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Notificaciones recientes</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>No hay tareas en segundo plano.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Tareas en segundo plano</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Ayuda</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Documentaci\xf3n</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>Acerca de</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Ajustes de la consola</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Gesti\xf3n del usuario</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Usuario que ha entrado</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Ha entrado como\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Salir</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nombre...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>El nombre que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Descripci\xf3n...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Permisos</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Funciones</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nombre de usuario</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Contrase\xf1a</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Confirmar contrase\xf1a</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Las contrase\xf1as no coinciden.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Nombre completo</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>Correo electr\xf3nico</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>Correo electr\xf3nico no v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Se dispone a eliminar los permisos "lectura/actualizaci\xf3n de usuario" de su propio usuario.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Si contin\xfaa, no podr\xe1 a\xf1adir ni eliminar funciones en ning\xfan usuario.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>\xbfSeguro que desea continuar?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Los contadores de rendimiento no est\xe1n disponibles</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Atributos (mapa de OSD)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Los metadatos no est\xe1n disponibles</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadatos</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Contandor de rendimiento</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>El histograma no est\xe1 disponible: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Escrituras</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Lecturas</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histograma</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Detalles de rendimiento</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Valores actuales</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Tipo</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>M\xedn.</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>M\xe1x.</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Indicadores</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Origen</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Nivel</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Se puede actualizar en el tiempo de ejecuci\xf3n (editable)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Etiquetas</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Valores Enum</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>V\xe9ase tambi\xe9n</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Estado del cl\xfaster</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Daemons de gestor</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Instancias de Object Gateway</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Servidores de metadatos</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>Puertas de enlace iSCSI</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>IOPS de cliente</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Rendimiento del cliente</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Lectura/escritura de cliente</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Rendimiento de recuperaci\xf3n</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Depuraci\xf3n</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Rendimiento</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Capacidad en bruto</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objetos</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>Grupos de colocaci\xf3n por OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Estado del grupo de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Capacidad</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consulte la secci\xf3n \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Registros\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> para obtener m\xe1s datos.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Clasificaciones</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Clientes: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Mover una imagen a la papelera</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Para mover \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> a la papelera,\n haga clic en \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mover imagen\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Opcionalmente, puede seleccionar una fecha de caducidad.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>La protecci\xf3n caduca a las</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>SIN PROTECCI\xd3N</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Formato de fecha err\xf3neo. Use el formato "AAAA-MM-DD HH:mm:ss".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>La protecci\xf3n ya ha caducado. Seleccione una fecha del futuro o deje el campo vac\xedo.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Mover imagen</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Resumen</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Destinos</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Autenticaci\xf3n de descubrimiento</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Usuario</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Los nombres de usuario deben tener entre 8 y 64 caracteres y\n solo pueden incluir letras y estos caracteres: ".", "@", "-", "_" o ":".</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Usuario mutuo</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Contrase\xf1a mutua</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Consulte la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentaci\xf3n\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre c\xf3mo configurar y habilitar la funci\xf3n de gesti\xf3n de destinos iSCSI.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informaci\xf3n disponible:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>Destinos iSCSI no disponibles</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Solo disponible para im\xe1genes RBD con \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> habilitado\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Repositorio</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Repositorio de datos</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Creados</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Tama\xf1o</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Tama\xf1o del objeto</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Caracter\xedsticas</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Aprovisionados</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/D</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Total aprovisionado</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Unidad de repartici\xf3n</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Recuento de repartici\xf3n</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Padre</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Prefijo de nombre de bloque</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Orden</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Instant\xe1neas</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Imagen</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Este ajuste sustituye al valor global</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Global</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Este es el valor global. No se ha definido ning\xfan valor para esta opci\xf3n para esta imagen.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>No se permiten los caracteres "/" ni "@".</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- No hay ning\xfan repositorio RBD disponible --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Seleccione un repositorio --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Usar un repositorio dedicado para datos</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Repositorio de datos</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Repositorio dedicado para almacenar los datos de objeto de RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>ej.: 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Debe aumentar el tama\xf1o.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Avanzado</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Repartici\xf3n</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Unidad de repartici\xf3n</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Seleccione la unidad de repartici\xf3n --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Este campo es obligatorio porque se ha definido el recuento de repartici\xf3n.</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>La unidad de repartici\xf3n es mayor que el tama\xf1o del objeto.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Recuento de repartici\xf3n</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Este campo es obligatorio porque se ha definido la unidad de repartici\xf3n.</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>El recuento de repartici\xf3n debe ser mayor que 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instant\xe1nea RBD\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Renombrar} other {Crear} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instant\xe1nea\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>CON PROTECCI\xd3N</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>SIN PROTECCI\xd3N</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Se dispone a revertir</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Vaciar papelera</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Para limpiar, seleccione una imagen, o todas las im\xe1genes, y haga clic en</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Repositorio:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nombre del repositorio...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Todas</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Restaurar im\xe1genes</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Para restaurar</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>escriba el nombre nuevo de la imagen y haga clic en</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nombre nuevo</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Caduc\xf3 a las</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Protecci\xf3n hasta</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Esta imagen est\xe1 protegida hasta el \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Papelera</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topolog\xeda iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Normalmente no es necesario cambiar los valores por defecto de estos par\xe1metros.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Ajustes</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Almac\xe9n</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Confirmar</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Ajustes avanzados</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>IQN de destino</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>El IQN tiene un patr\xf3n err\xf3neo.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Los IQN tienen esta notaci\xf3n: iqn.$year-$month.$reversedAddress:$definedName</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Por ejemplo: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>M\xe1s informaci\xf3n</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Este destino tiene ajustes avanzados modificados.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portales</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Se requieren al menos \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> puertas de enlace.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>A\xf1adir portal</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Esta imagen tiene ajustes modificados.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>A\xf1adir imagen</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Autenticaci\xf3n de ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Iniciadores</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Iniciador</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>IQN del cliente</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>El IQN del iniciador debe ser exclusivo.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Los nombres de usuario deben tener entre 8 y 64 caracteres y\n solo pueden incluir letras y estos caracteres: ".", "@", "-", "_" o ":".</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>El iniciador pertenece a un grupo. Las im\xe1genes se configurar\xe1n en el grupo.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>No se ha a\xf1adido ning\xfan elemento.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>A\xf1adir iniciador</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Grupos</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Grupo</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>A\xf1adir grupo</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Configuraci\xf3n de RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Elimina el valor de configuraci\xf3n local. Se heredar\xe1 y usar\xe1 en su lugar el valor de configuraci\xf3n padre.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>El valor m\xednimo es 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Problemas</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Sincronizando</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Listo</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Editar modo de duplicaci\xf3n de repositorio</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Para editar el modo de duplicaci\xf3n del repositorio\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, seleccione un modo nuevo en la lista y haga clic\xa0\n en \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Actualizar\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Modo</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Los cl\xfasteres de par deben eliminarse antes de inhabilitar la duplicaci\xf3n.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\nduplicar par de repositorio\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Editar} other {A\xf1adir} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> los atributos del par\n de duplicaci\xf3n del respositorio \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> y haga clic en \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Enviar\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nombre del cl\xfaster</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>El nombre del cl\xfaster no es v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>ID de CephX</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>ID de CephX...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>El ID de CephX no es v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Direcciones de monitores</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Direcciones delimitadas por comas...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>La direcci\xf3n del monitor no es v\xe1lida.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>Clave de CephX</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Clave con cifrado base64...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>La clave de CephX debe tener cifrado base64</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Lista de repositorios</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>El nombre solo puede tener caracteres alfanum\xe9ricos, guiones y guiones bajos.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>El nombre del perfil de c\xf3digo de borrado que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Complemento</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Porciones de datos (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Debe ser igual o mayor que 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Porciones de c\xf3digo (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Debe ser igual o mayor que 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Estimador de durabilidad (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Localizaci\xf3n (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Dominio de error de CRUSH</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Localizaci\xf3n de CRUSH</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Ninguna</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>T\xe9cnica</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Tama\xf1o del paquete</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Ra\xedz de CRUSH</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Clase de dispositivo de CRUSH</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>cualquiera</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Directorio</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>El nombre del repositorio de Ceph que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Tipo de repositorio</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Seleccione un tipo de repositorio --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Grupos de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Se necesita al menos un grupo de colocaci\xf3n.</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>El cl\xfaster no puede gestionar tantos grupos de colocaci\xf3n. Vuelva a calcular la cantidad que necesita.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Ayuda para el c\xe1lculo</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>El n\xfamero grupos de colocaci\xf3n actual se ha calculado\n\xa0 autom\xe1ticamente. Debe asegurarse de que sirve para sus necesidades antes de enviar.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Conjunto de reglas de CRUSH</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Seleccione una regla de CRUSH --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Regla de CRUSH</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Pasos de CRUSH</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>La regla no se puede usar en el cl\xfaster actual, ya que\n no tiene suficientes OSD que cumplan el m\xednimo requerido.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Tama\xf1o replicado</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>M\xednimo: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>M\xe1ximo: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>El tama\xf1o especificado est\xe1 fuera del intervalo. Los valores v\xe1lidos\n son del \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> al \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Perfil de c\xf3digo de borrado</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- No hay ning\xfan perfil de c\xf3digo de borrado disponible --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Seleccione un perfil de c\xf3digo de borrado --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>Sustituciones de c\xf3digos de borrado</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Aplicaciones</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Compresi\xf3n</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algoritmo</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- No hay ning\xfan algoritmo de compresi\xf3n de borrado disponible --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Tama\xf1o de Blob m\xednimo</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>p. ej. 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>El valor debe ser mayor que 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Tama\xf1o de Blob m\xe1ximo</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>p. ej. 512 KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>El valor debe ser mayor que el tama\xf1o de Blob m\xednimo</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Relaci\xf3n</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Relaci\xf3n de compresi\xf3n</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>El valor debe estar entre 0,0 y 1,0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>No es posible crear un repositorio RBD con el nombre "/".</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Cambie el nombre o elimine "rbd" de la lista de aplicaciones.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Detalles de niveles de cach\xe9</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Consulte la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentaci\xf3n\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n sobre c\xf3mo configurar y habilitar la funci\xf3n de gesti\xf3n de Object Gateway.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Lista de daemons</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Contadores de rendimiento</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Cargando datos de la papelera...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>No es posible cargar los datos de la papelera.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>El valor no es v\xe1lido.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Propietario</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Seleccione un usuario --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Tipo de \xedndice</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Regla de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Marcador</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Marcador m\xe1ximo</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Versi\xf3n</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Versi\xf3n maestra</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Hora de modificaci\xf3n</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Grupo de zona</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Cuota de papelera</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Habilitado</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Tama\xf1o m\xe1ximo</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Sin l\xedmite</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>N\xfamero m\xe1ximo de objetos</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Seleccione un nombre de usuario --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Autogenerar clave</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Clave de acceso</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Clave secreta</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Direcci\xf3n de correo electr\xf3nico</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Suspendido</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Sistema</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {No} 1 {S\xed} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>N\xfamero m\xe1ximo de papeleras</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Subusuarios</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Capacidades</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Cuota de usuario</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Mostrar</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Claves</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Seleccione un tipo --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Permiso</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Seleccione un permiso --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Subusuario</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>El ID de subusuario que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>lectura, escritura</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>todos</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Clave Swift</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Autogenerar secreto</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Cargando datos del usuario...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>No es posible cargar los datos del usuario.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>El ID de usuario que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Esta direcci\xf3n no es v\xe1lida.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>La direcci\xf3n de correo electr\xf3nico que ha elegido ya est\xe1 en uso.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>M\xe1x. papeleras</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>El valor introducido debe ser mayor o igual que 0.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>Clave S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>No hay ning\xfan subusuario.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>No hay ninguna clave.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>No hay ninguna capacidad</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Tama\xf1o ilimitado</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Tama\xf1o m\xe1x.</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Objetos ilimitados</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Objetos m\xe1x.</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Actual</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Autenticaci\xf3n de descubrimiento actualizada</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>No hay ning\xfan portal disponible.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>No hay ninguna imagen disponible.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>No hay ninguna imagen disponible. Aseg\xfarese de a\xf1adir una imagen al destino.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>No hay ning\xfan iniciador disponible. Aseg\xfarese de a\xf1adir un iniciador al destino.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Destino</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Estado</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Bytes de lectura</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Bytes de escritura</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Operaciones de lectura</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Operaciones de escritura</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O desde</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instancia</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nombre de host</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Problema</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Progreso</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Inhabilitado</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Editar modo</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>A\xf1adir par</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Editar par</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Suprimir par</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>L\xedder</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>N.\xba locales</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>N.\xba remotos</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>duplicar par</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Clave</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Aplanamiento profundo</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>En capas</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Bloqueo exclusivo</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Mapa de objetos (requiere bloqueo exclusivo)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>En diario (requiere bloqueo exclusivo)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Reversi\xf3n de instant\xe1nea RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Revertir</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Instant\xe1nea RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Suprimido a las</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>tipo</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>estado</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>versi\xf3n</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>ra\xedz</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Clasificaci\xf3n</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Actividad</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inodos</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Uso</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Daemons de reserva</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>El valor se puede actualizar en el tiempo de ejecuci\xf3n.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Los daemons/clientes no extraen este valor de la\n base de datos de configuraci\xf3n del monitor. No se recomienda definir esta opci\xf3n con "ceph config\n set ...". Esta opci\xf3n se debe configurar mediante ceph.conf o a trav\xe9s\n de la l\xednea de comandos.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>La opci\xf3n solo surte efecto durante el inicio del daemon.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>La opci\xf3n solo afecta a la creaci\xf3n del cl\xfaster.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>La opci\xf3n solo afecta a la creaci\xf3n del daemon.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Opci\xf3n de configuraci\xf3n actualizada \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Servicio</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Valor actual</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Editable</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Opciones actualizadas para el m\xf3dulo \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Habilitar</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Inhabilitar</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Conectando de nuevo. Espere...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Direcci\xf3n p\xfablica</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Sesiones abiertas</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>No incluir</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>Los OSD que se excluyeron anteriormente no se volver\xe1n a incluir cuando se inicien</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>No excluir</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>Los OSD no se excluir\xe1n autom\xe1ticamente despu\xe9s del intervalo configurado</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>No activar</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>No se permite que los OSD se inicien</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>No desactivar</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Se ignoran los informes de error de OSD, de forma que los monitores no desactivar\xe1n los OSD</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pausa</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Pone en pausa las lecturas y escrituras</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>No depurar</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>La depuraci\xf3n est\xe1 inhabilitada</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>No depuraci\xf3n profunda</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>La depuraci\xf3n profunda est\xe1 inhabilitada</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>No reponer</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>La reposici\xf3n de grupos de colocaci\xf3n se suspende</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>No recuperar</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>La recuperaci\xf3n de los grupos de colocaci\xf3n se suspende</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Orden bit a bit</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Usar orden bit a bit</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Snapdir limpiados</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>Los OSD tienen snapset convertidos</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Supresiones de recuperaci\xf3n</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Supresiones realizadas durante la recuperaci\xf3n, en lugar de emparejamientos</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>L\xedmite estricto de registro del grupo de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Establece un l\xedmite estricto para la longitud del registro del grupo de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Indicadores de OSD actualizados</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>excluir</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>Incluir</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>desactivar</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Marcar</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD perdido</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>marcado como perdido</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Limpiar</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>limpiado</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>destruir</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>destruido</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>Grupos de colocaci\xf3n</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Bytes de lectura</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Bytes de escritura</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Operaciones de lectura</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Operaciones de escritura</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marcar OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marcar \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>N\xfamero m\xe1ximo de reposiciones</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>M\xe1ximo de recuperaciones activas</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>M\xe1ximo de recuperaciones de inicio \xfanico</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Reposo de recuperaci\xf3n</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Personalizar</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Prioridad de velocidad de recuperaci\xf3n de OSD actualizada \n <x id="INTERPOLATION" equiv-text="{{value}}"/>\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> se ha inicializado en el siguiente OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Trabajo</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Gravedad</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Iniciado</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Actualizado</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Usado</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Dispon.</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Limpio</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>En curso</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Advertencia</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Desconocido</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>activo</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>sin sistemas de archivos</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>activo</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>reserva</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/d</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>daemon activo</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>qu\xf3rum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>El servicio NFS Ganesha no est\xe1 configurado.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transportar</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>Usuario de CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>Sistemas de archivos CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(se hereda de la configuraci\xf3n global)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>se hereda de la configuraci\xf3n global</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Seleccione el tipo de reducci\xf3n de privilegios de ID de usuario que se va a realizar --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>No hay ning\xfan daemon disponible.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Modo de cach\xe9</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Antig\xfcedad m\xednima de expulsi\xf3n</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Antig\xfcedad m\xednima de vaciado</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>N\xfamero m\xe1ximo de bytes de destino</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>N\xfamero m\xe1ximo de objetos de destino</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>No se ha a\xf1adido ninguna aplicaci\xf3n</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Se ha alcanzado el l\xedmite de aplicaciones</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Un repositorio solo puede tener hasta cuatro definiciones de aplicaciones.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Caracteres permitidos: _, a-z, A-Z y 0-9</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>La longitud m\xe1xima es 128 caracteres</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtrar o a\xf1adir aplicaciones</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>A\xf1adir aplicaci\xf3n</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>perfil de c\xf3digo de borrado</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Tama\xf1o de r\xe9plica</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\xdaltimo cambio</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Perfil de c\xf3digo de borrado</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Conjunto de reglas de CRUSH</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Bytes de escritura</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>papelera</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Papelera de Object Gateway actualizada "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Papelera de Object Gateway creada "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>papeleras</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>usuario</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Usuario de Object Gateway actualizado "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Usuario de Object Gateway creado "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>usuarios</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>\xc1mbito</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Lectura</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Crear</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Se ha creado la funci\xf3n \n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Se ha actualizado la funci\xf3n \n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Funci\xf3n del sistema</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Se ha suprimido la funci\xf3n \n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Se ha creado el usuario \n <x id="INTERPOLATION" equiv-text="{{username}}"/>\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Actualizar usuario</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Continuar</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>La sesi\xf3n se ha cerrado autom\xe1ticamente porque sus funciones han cambiado.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Se ha actualizado el usuario \n <x id="INTERPOLATION" equiv-text="{{username}}"/>\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Se ha suprimido el usuario \n <x id="INTERPOLATION" equiv-text="{{username}}"/>\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Error al suprimir el usuario \n <x id="INTERPOLATION" equiv-text="{{username}}"/>\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Ha entrado a la sesi\xf3n como \n <x id="INTERPOLATION" equiv-text="{{username}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Cada objeto se divide en porciones de datos, cada una almacenada en un OSD distinto.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Calcula las porciones de c\xf3digo para cada objeto y las almacena en distintos OSD.\n El n\xfamero de porciones de c\xf3digo es tambi\xe9n el n\xfamero de OSD que pueden estar inactivos sin que se pierdan datos.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>El complemento jerasure es el m\xe1s gen\xe9rico y flexible,\n y tambi\xe9n el complemento por defecto para los repositorios de c\xf3digo de borrado de Ceph.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>La t\xe9cnica m\xe1s flexible es reed_sol_van: basta con definir k y m.\n La t\xe9cnica cauchy_good puede ser m\xe1s r\xe1pida, pero hay que elegir con cuidado el tama\xf1o\n del paquete. reed_sol_r6_op, liberation, blaum_roth y liber8tion son todas equivalentes a RAID6\n en el sentido de que solo se pueden configurar con m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>La codificaci\xf3n se realizar\xe1 seg\xfan el tama\xf1o de los paquetes de bytes de uno en uno.\n Elegir el tama\xf1o correcto es dif\xedcil.\n La documentaci\xf3n de jerasure incluye informaci\xf3n completa sobre el tema.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Con el complemento jerasure, cuando un objeto de c\xf3digo de borrado se almacena\n en varios OSD, para recuperarse de la p\xe9rdida de un OSD es necesario leer de todos los dem\xe1s.\n Por ejemplo, si jerasure est\xe1 configurado con k=8 y m=4, cuando se pierde un OSD es necesario leer\n de los otros once para repararlo.\n\n El complemento de c\xf3digo de borrado lrc crea porciones de paridad local para poder realizar la recuperaci\xf3n con\n menos OSDs. Por ejemplo, is lrc est\xe1 configurado con k=8, m=4 y l=4, crear\xe1\n una porci\xf3n de paridad adicional para cada cuatro OSDs. Si se pierde un solo OSD, se puede recuperar\n solo con cuatro OSD, en lugar de con once.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Agrupa las porciones de c\xf3digo y de datos en localizaciones de conjuntos de tama\xf1o. Por ejemplo,\n para k=4 y m=2, si locality=3, se crean dos grupos de tres. Cada conjunto\n se puede recuperar sin leer porciones de otro conjunto.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>El tipo de papelera de CRUSH en el que se almacenar\xe1 cada\n conjunto de porciones definido por l. Por ejemplo, si se define como bastidor, cada grupo de l porciones\n se colocar\xe1 en un bastidor distinto. Se usa para crear un paso de regla de CRUSH, por ejemplo, "step choose\n rack". Si no se define, no se realiza este tipo de agrupamiento.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>El complemento isa encapsula la biblioteca ISA. Solo funciona en procesadores Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>El complemento ISA viene en dos formatos de Reed Solomon.\n Si se define reed_sol_van, se trata de Vandermonde; si se define cauchy, se trata de Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>El complemento shec encapsula las distintas bibliotecas SHEC.\n Permite a Ceph recuperar datos de forma m\xe1s eficiente que los c\xf3digos de Reed Solomon.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>El n\xfamero de porciones de paridad. Cada uno de ellas incluye cada porci\xf3n de datos\n en su intervalo de c\xe1lculo. El n\xfamero se usa como estimador de durabilidad. Por ejemplo, si c=2,\n 2 OSD pueden estar inactivos sin que se pierdan datos.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>El nombre de la papelera de CRUSH usado para el primer paso de la regla de CRUSH.\n Por ejemplo, "step take default".</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Aseg\xfarese de que no hay dos porciones en una papelera con el mismo\n dominio de error. Por ejemplo, si el dominio de error es host, no debe haber dos porciones almacenadas en el mismo\n host. Se usa para crear un paso de regla de CRUSH, por ejemplo, "step chooseleaf host".</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Restringe la colocaci\xf3n a dispositivos de una clase concreta\n (p.ej., ssd o hdd) usando los nombre de clase de dispositivo CRUSH en el mapa de CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Define el nombre de directorio del que se cargar\xe1 el complemento de c\xf3digo de borrado.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Permite todas las operaciones</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Permite solo las operaciones que no modifican el servidor</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>No permite operaciones de lectura o escritura, pero s\xed cualquier otra</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>No permite operaciones de lectura o escritura, ni ninguna otra que modifique los atributos del archivo o el contenido del directorio</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>No permite ning\xfan tipo de acceso</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Seleccione la prioridad --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Baja</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Alta</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\xdaltimos 5 minutos</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\xdaltimos 15 minutos</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\xdaltimos 30 minutos</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\xdaltima hora (opci\xf3n por defecto)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\xdaltimas 3 horas</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\xdaltimas 6 horas</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\xdaltimas 12 horas</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\xdaltimas 24 horas</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Ayer</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Hoy</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Hoy hasta ahora</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Anteayer</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Los \xfaltimos 2 d\xedas</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Este d\xeda la semana pasada</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>La semana pasada</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Esta semana</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Esta semana hasta ahora</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Los \xfaltimos 7 d\xedas</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>El mes pasado</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Este mes</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Este mes hasta ahora</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Los \xfaltimos 30 d\xedas</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Los \xfaltimos 90 d\xedas</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Los \xfaltimos 6 meses</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>El \xfaltimo a\xf1o</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>El a\xf1o pasado</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Este a\xf1o</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Este a\xf1o hasta ahora</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Los \xfaltimos 2 a\xf1os</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Los \xfaltimos 5 a\xf1os</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informaci\xf3n</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>No se ha seleccionado ning\xfan elemento.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Deseleccione el elemento para volver a seleccionarlo</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Se ha alcanzado el l\xedmite de selecci\xf3n</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Filtrar etiquetas</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>A\xf1adir insignia</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>No hay ning\xfan elemento disponible.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>A\xf1adir</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Clonar</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Copiar</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Depuraci\xf3n profunda</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Destruir</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Aplanar</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Marcar para desactivar</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Marcar para incluir</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Marcar como perdido</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Marcar para excluir</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Proteger</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Renombrar</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Restaurar</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>Mover a la papelera</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Desproteger</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Suprimido</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Clonado</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Copiado</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>S\xed</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>No</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Calidad del servicio</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>L\xedmite de BPS</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>El l\xedmite deseado de bytes de E/S por segundo.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>L\xedmite de IOPS</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>El l\xedmite deseado de operaciones de E/S por segundo.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>L\xedmite de BPS de lectura</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>El l\xedmite deseado de bytes de lectura por segundo.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>L\xedmite de IOPS de lectura</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>El l\xedmite deseado de operaciones de lectura por segundo.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>L\xedmite de BPS de escritura</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>El l\xedmite deseado de bytes de escritura por segundo.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>L\xedmite de IOPS de escritura</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>El l\xedmite deseado de operaciones de escritura por segundo.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>R\xe1faga de BPS</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>El l\xedmite deseado de r\xe1faga de bytes de E/S.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>R\xe1faga de IOPS</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>El l\xedmite deseado de r\xe1faga de operaciones de E/S.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>R\xe1faga de BPS de lectura</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>El l\xedmite deseado de r\xe1faga de bytes de lectura.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>R\xe1faga de IOPS de lectura</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>El l\xedmite deseado de r\xe1faga de operaciones de lectura.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>R\xe1faga de BPS de escritura</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>El l\xedmite deseado de r\xe1faga de bytes de escritura.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>R\xe1faga de IOPS de escritura</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>El l\xedmite deseado de r\xe1faga de operaciones de escritura.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Error al \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Ejecutando</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>ejecutar</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Ejecutado</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>tarea desconocida</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Creando</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>crear</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Actualizando</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>actualizar</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Suprimiendo</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>suprimir</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \n <x id="INTERPOLATION" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Instant\xe1nea RBD \n <x id="INTERPOLATION" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>modo de duplicaci\xf3n para repositorio \n <x id="INTERPOLATION" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>par de duplicaci\xf3n para repositorio \n <x id="INTERPOLATION" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> ya est\xe1 usando el nombre.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{name}}"/> ya est\xe1 usando el nombre.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> ya est\xe1 usando el nombre.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contiene instant\xe1neas.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Clonando</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>clonar</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>La instant\xe1nea de \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> debe estar protegida.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Copiando</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>copiar</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Aplanando</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>aplanar</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Aplanado</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> ya est\xe1 usando el nombre.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>No es posible desproteger \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque contiene im\xe1genes hijas.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>No es posible suprimir \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque est\xe1 protegido.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Revirtiendo</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>revertir</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Revertido</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Moviendo</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>mover</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>Movido</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>la imagen \n <x id="INTERPOLATION" equiv-text="{{id}}"/> a la papelera\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>No se encuentra la imagen.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Restaurando</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>restaurar</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Restaurado</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>la imagen \n <x id="INTERPOLATION" equiv-text="{{id}}"/> en \n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>El nombre de imagen \n <x id="INTERPOLATION" equiv-text="{{id}}"/> ya est\xe1 en uso.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>la imagen \n <x id="INTERPOLATION" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>Limpiando</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>limpiar</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Limpiado</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>todos los repositorios</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>im\xe1genes de \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>No es posible inhabilitar la duplicaci\xf3n porque contiene un par</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>repositorio \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>perfil de c\xf3digo de borrado \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>destino \n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},czA5:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MouseEvent=("undefined"!=typeof window&&window||global).MouseEvent,e.KeyboardEvent=("undefined"!=typeof window&&window||global).KeyboardEvent,e.Event=("undefined"!=typeof window&&window||global).Event},czMo:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-il",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}})}()},"d+Og":function(t,e,n){"use strict";var a=n("LvDl"),r=function(){function t(t){if(this.type=t,!this.isValidType())throw new Error("Wrong placement group category type");this.setTypeStates()}return t.prototype.isValidType=function(){return t.VALID_CATEGORIES.includes(this.type)},t.prototype.setTypeStates=function(){switch(this.type){case t.CATEGORY_CLEAN:this.states=["active","clean"];break;case t.CATEGORY_WORKING:this.states=["activating","backfill_wait","backfilling","creating","deep","degraded","forced_backfill","forced_recovery","peering","peered","recovering","recovery_wait","repair","scrubbing","snaptrim","snaptrim_wait"];break;case t.CATEGORY_WARNING:this.states=["backfill_toofull","backfill_unfound","down","incomplete","inconsistent","recovery_toofull","recovery_unfound","remapped","snaptrim_error","stale","undersized"];break;default:this.states=[]}},t.VALID_CATEGORIES=[t.CATEGORY_CLEAN="clean",t.CATEGORY_WORKING="working",t.CATEGORY_WARNING="warning",t.CATEGORY_UNKNOWN="unknown"],t}(),i=n("CcnG"),s=n("kJI8");n.d(e,"a",function(){return o});var o=function(){function t(){this.categories=this.createCategories()}return t.prototype.getAllTypes=function(){return r.VALID_CATEGORIES},t.prototype.getTypeByStates=function(t){var e=this,n=this.getPgStatesFromText(t);if(0===n.length)return r.CATEGORY_UNKNOWN;var i=a.zipObject(r.VALID_CATEGORIES,r.VALID_CATEGORIES.map(function(t){return a.intersection(e.categories[t].states,n).length}));if(i[r.CATEGORY_WARNING]>0)return r.CATEGORY_WARNING;var s=i[r.CATEGORY_WORKING];return n.length>i[r.CATEGORY_CLEAN]+s?r.CATEGORY_UNKNOWN:s?r.CATEGORY_WORKING:r.CATEGORY_CLEAN},t.prototype.createCategories=function(){return a.zipObject(r.VALID_CATEGORIES,r.VALID_CATEGORIES.map(function(t){return new r(t)}))},t.prototype.getPgStatesFromText=function(t){var e=t.replace(/[^a-z]+/g," ").trim().split(" ");return a.uniq(e)},t.ngInjectableDef=i.defineInjectable({factory:function(){return new t},token:t,providedIn:s.a}),t}()},dC0D:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t,e){var n=!1;return arguments.length>=2&&(n=!0),function(a){return a.lift(new s(t,e,n))}}var s=function(){function t(t,e,n){void 0===n&&(n=!1),this.accumulator=t,this.seed=e,this.hasSeed=n}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.accumulator,this.seed,this.hasSeed))},t}(),o=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.accumulator=n,i._seed=a,i.hasSeed=r,i.index=0,i}return a.__extends(e,t),Object.defineProperty(e.prototype,"seed",{get:function(){return this._seed},set:function(t){this.hasSeed=!0,this._seed=t},enumerable:!0,configurable:!0}),e.prototype._next=function(t){if(this.hasSeed)return this._tryNext(t);this.seed=t,this.destination.next(t)},e.prototype._tryNext=function(t){var e,n=this.index++;try{e=this.accumulator(this.seed,t,n)}catch(a){this.destination.error(a)}this.seed=e,this.destination.next(e)},e}(r.a)},dEH0:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){return t+" ms"},t}()},dEwP:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("F/XL"),r=n("Txjg");function i(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return Object(r.a)()(a.a.apply(void 0,t))}},dNwA:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("sw",{months:"Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des".split("_"),weekdays:"Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi".split("_"),weekdaysShort:"Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos".split("_"),weekdaysMin:"J2_J3_J4_J5_Al_Ij_J1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[leo saa] LT",nextDay:"[kesho saa] LT",nextWeek:"[wiki ijayo] dddd [saat] LT",lastDay:"[jana] LT",lastWeek:"[wiki iliyopita] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s baadaye",past:"tokea %s",s:"hivi punde",ss:"sekunde %d",m:"dakika moja",mm:"dakika %d",h:"saa limoja",hh:"masaa %d",d:"siku moja",dd:"masiku %d",M:"mwezi mmoja",MM:"miezi %d",y:"mwaka mmoja",yy:"miaka %d"},week:{dow:1,doy:7}})}()},dgut:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("NEZu"),r=(n("Fgil"),function(){function t(t){var e=this;this.dimlessBinaryPipe=t,this.style={height:"30px",width:"100px"},this.colors=[{backgroundColor:"rgba(40,140,234,0.2)",borderColor:"rgba(40,140,234,1)",pointBackgroundColor:"rgba(40,140,234,1)",pointBorderColor:"#fff",pointHoverBackgroundColor:"#fff",pointHoverBorderColor:"rgba(40,140,234,0.8)"}],this.options={animation:{duration:0},responsive:!0,maintainAspectRatio:!1,legend:{display:!1},elements:{line:{borderWidth:1}},tooltips:{enabled:!1,mode:"index",intersect:!1,custom:void 0,callbacks:{label:function(t){return e.isBinary?e.dimlessBinaryPipe.transform(t.yLabel):t.yLabel},title:function(){return""}}},scales:{yAxes:[{display:!1}],xAxes:[{display:!1}]}},this.datasets=[{data:[]}],this.labels=[]}return t.prototype.ngOnInit=function(){var t=new a.a(this.chartCanvasRef,this.chartTooltipRef,function(t,e){return e+t.caretX+"px"},function(t){return t.caretY-t.height-t.yPadding-5+"px"});t.customColors={backgroundColor:this.colors[0].pointBackgroundColor,borderColor:this.colors[0].pointBorderColor},this.options.tooltips.custom=function(e){t.customTooltips(e)}},t.prototype.ngOnChanges=function(t){this.datasets[0].data=t.data.currentValue,this.labels=Array(t.data.currentValue.length).slice()},t}())},dpnK:function(t,e,n){"use strict";var a=n("CDJp"),r=n("RDha");a._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),t.exports={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,a){var r,i,s=this.animations;for(e.chart=t,a||(t.animating=!0),r=0,i=s.length;r<i;++r)if(s[r].chart===t)return void(s[r]=e);s.push(e),1===s.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=r.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=r.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var a=Date.now();t.dropFrames+=(a-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,a=this.animations,i=0;i<a.length;)n=(e=a[i]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),r.callback(e.render,[n,e],n),r.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,a.splice(i,1)):++i}}},dzgT:function(t,e,n){"use strict";n.d(e,"b",function(){return l}),n.d(e,"a",function(){return d});var a=n("mrSG"),r=n("nkY7"),i=n("isby"),s=n("MGBS"),o=n("zotm"),u=n("IUTb"),c={};function l(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=null,a=null;return Object(r.a)(t[t.length-1])&&(a=t.pop()),"function"==typeof t[t.length-1]&&(n=t.pop()),1===t.length&&Object(i.a)(t[0])&&(t=t[0]),Object(u.a)(t,a).lift(new d(n))}var d=function(){function t(t){this.resultSelector=t}return t.prototype.call=function(t,e){return e.subscribe(new f(t,this.resultSelector))},t}(),f=function(t){function e(e,n){var a=t.call(this,e)||this;return a.resultSelector=n,a.active=0,a.values=[],a.observables=[],a}return a.__extends(e,t),e.prototype._next=function(t){this.values.push(c),this.observables.push(t)},e.prototype._complete=function(){var t=this.observables,e=t.length;if(0===e)this.destination.complete();else{this.active=e,this.toRespond=e;for(var n=0;n<e;n++){var a=t[n];this.add(Object(o.a)(this,a,a,n))}}},e.prototype.notifyComplete=function(t){0==(this.active-=1)&&this.destination.complete()},e.prototype.notifyNext=function(t,e,n,a,r){var i=this.values,s=this.toRespond?i[n]===c?--this.toRespond:this.toRespond:0;i[n]=e,0===s&&(this.resultSelector?this._tryResultSelector(i):this.destination.next(i.slice()))},e.prototype._tryResultSelector=function(t){var e;try{e=this.resultSelector.apply(this,t)}catch(n){return void this.destination.error(n)}this.destination.next(e)},e}(s.a)},"e+ae":function(t,e,n){!function(t){"use strict";var e="janu\xe1r_febru\xe1r_marec_apr\xedl_m\xe1j_j\xfan_j\xfal_august_september_okt\xf3ber_november_december".split("_"),n="jan_feb_mar_apr_m\xe1j_j\xfan_j\xfal_aug_sep_okt_nov_dec".split("_");function a(t){return t>1&&t<5}function r(t,e,n,r){var i=t+" ";switch(n){case"s":return e||r?"p\xe1r sek\xfand":"p\xe1r sekundami";case"ss":return e||r?i+(a(t)?"sekundy":"sek\xfand"):i+"sekundami";case"m":return e?"min\xfata":r?"min\xfatu":"min\xfatou";case"mm":return e||r?i+(a(t)?"min\xfaty":"min\xfat"):i+"min\xfatami";case"h":return e?"hodina":r?"hodinu":"hodinou";case"hh":return e||r?i+(a(t)?"hodiny":"hod\xedn"):i+"hodinami";case"d":return e||r?"de\u0148":"d\u0148om";case"dd":return e||r?i+(a(t)?"dni":"dn\xed"):i+"d\u0148ami";case"M":return e||r?"mesiac":"mesiacom";case"MM":return e||r?i+(a(t)?"mesiace":"mesiacov"):i+"mesiacmi";case"y":return e||r?"rok":"rokom";case"yy":return e||r?i+(a(t)?"roky":"rokov"):i+"rokmi"}}t.defineLocale("sk",{months:e,monthsShort:n,weekdays:"nede\u013ea_pondelok_utorok_streda_\u0161tvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_\u0161t_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_\u0161t_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nede\u013eu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo \u0161tvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[v\u010dera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minul\xfa nede\u013eu o] LT";case 1:case 2:return"[minul\xfd] dddd [o] LT";case 3:return"[minul\xfa stredu o] LT";case 4:case 5:return"[minul\xfd] dddd [o] LT";case 6:return"[minul\xfa sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:r,ss:r,m:r,mm:r,h:r,hh:r,d:r,dd:r,M:r,MM:r,y:r,yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},eTJe:function(t,e,n){"use strict";var a,r=n("gIcY"),i=n("LvDl"),s=n("VNr4"),o=(n("SgmB"),n("ZDA6"),n("sne2"),n("mtw6")),u=n("QFaf"),c=n("1Ni5");n("9nlD"),function(t){t.editing="editing"}(a||(a={}));var l=function(){return function(){}}();n.d(e,"a",function(){return d});var d=function(){function t(t,e,n,r,i,s,o){this.route=t,this.router=e,this.roleService=n,this.scopeService=r,this.notificationService=i,this.i18n=s,this.actionLabels=o,this.scopes=[],this.scopes_permissions=[],this.roleFormMode=a,this.resource=this.i18n("role"),this.createForm(),this.listenToChanges()}return t.prototype.createForm=function(){this.roleForm=new u.a({name:new r.i("",{validators:[r.A.required],asyncValidators:[c.a.unique(this.roleService.exists,this.roleService)]}),description:new r.i(""),scopes_permissions:new r.i({})})},t.prototype.ngOnInit=function(){this.columns=[{prop:"scope",name:this.i18n("All"),flexGrow:2,cellTemplate:this.cellScopeCheckboxTpl,headerTemplate:this.headerPermissionCheckboxTpl},{prop:"read",name:this.i18n("Read"),flexGrow:1,cellClass:"text-center",cellTemplate:this.cellPermissionCheckboxTpl,headerTemplate:this.headerPermissionCheckboxTpl},{prop:"create",name:this.i18n("Create"),flexGrow:1,cellClass:"text-center",cellTemplate:this.cellPermissionCheckboxTpl,headerTemplate:this.headerPermissionCheckboxTpl},{prop:"update",name:this.i18n("Update"),flexGrow:1,cellClass:"text-center",cellTemplate:this.cellPermissionCheckboxTpl,headerTemplate:this.headerPermissionCheckboxTpl},{prop:"delete",name:this.i18n("Delete"),flexGrow:1,cellClass:"text-center",cellTemplate:this.cellPermissionCheckboxTpl,headerTemplate:this.headerPermissionCheckboxTpl}],this.router.url.startsWith("/user-management/roles/edit")?(this.mode=this.roleFormMode.editing,this.action=this.actionLabels.EDIT):this.action=this.actionLabels.CREATE,this.mode===this.roleFormMode.editing?this.initEdit():this.initCreate()},t.prototype.initCreate=function(){var t=this;this.scopeService.list().subscribe(function(e){t.scopes=e,t.roleForm.get("scopes_permissions").setValue({})})},t.prototype.initEdit=function(){var t=this;this.roleForm.get("name").disable(),this.route.params.subscribe(function(e){var n=[];n.push(t.scopeService.list()),n.push(t.roleService.get(e.name)),Object(s.a)(n).subscribe(function(e){t.scopes=e[0],["name","description","scopes_permissions"].forEach(function(n){return t.roleForm.get(n).setValue(e[1][n])})})})},t.prototype.listenToChanges=function(){var t=this;this.roleForm.get("scopes_permissions").valueChanges.subscribe(function(e){var n=[];i.each(t.scopes,function(t){var a={read:!1,create:!1,update:!1,delete:!1};a.scope=t,t in e&&i.each(e[t],function(t){a[t]=!0}),n.push(a)}),t.scopes_permissions=n})},t.prototype.isRowChecked=function(t){var e=i.find(this.scopes_permissions,function(e){return e.scope===t});return!i.isUndefined(e)&&e.read&&e.create&&e.update&&e.delete},t.prototype.isHeaderChecked=function(t){var e=this,n=[t];return"scope"===t&&(n=["read","create","update","delete"]),n.every(function(t){return e.scopes_permissions.every(function(e){return e[t]})})},t.prototype.onClickCellCheckbox=function(t,e,n){void 0===n&&(n=null);var a=i.cloneDeep(this.roleForm.getValue("scopes_permissions")),r=[e];"scope"===e&&(r=["read","create","update","delete"]),t in a||(a[t]=[]),n&&n.target.checked||!i.isEqual(r.sort(),i.intersection(a[t],r).sort())?a[t]=i.union(a[t],r):(a[t]=i.difference(a[t],r),i.isEmpty(a[t])&&i.unset(a,t)),this.roleForm.get("scopes_permissions").setValue(a)},t.prototype.onClickHeaderCheckbox=function(t,e){var n=this,a=i.cloneDeep(this.roleForm.getValue("scopes_permissions")),r=[t];"scope"===t&&(r=["read","create","update","delete"]),i.each(r,function(t){i.each(n.scopes,function(n){e.target.checked?a[n]=i.union(a[n],[t]):(a[n]=i.difference(a[n],[t]),i.isEmpty(a[n])&&i.unset(a,n))})}),this.roleForm.get("scopes_permissions").setValue(a)},t.prototype.getRequest=function(){var t=this,e=new l;return["name","description","scopes_permissions"].forEach(function(n){return e[n]=t.roleForm.get(n).value}),e},t.prototype.createAction=function(){var t=this,e=this.getRequest();this.roleService.create(e).subscribe(function(){t.notificationService.show(o.a.success,t.i18n("Created role '{{role_name}}'",{role_name:e.name})),t.router.navigate(["/user-management/roles"])},function(){t.roleForm.setErrors({cdSubmitButton:!0})})},t.prototype.editAction=function(){var t=this,e=this.getRequest();this.roleService.update(e).subscribe(function(){t.notificationService.show(o.a.success,t.i18n("Updated role '{{role_name}}'",{role_name:e.name})),t.router.navigate(["/user-management/roles"])},function(){t.roleForm.setErrors({cdSubmitButton:!0})})},t.prototype.submit=function(){this.mode===this.roleFormMode.editing?this.editAction():this.createAction()},t}()},eajB:function(t,e,n){"use strict";n.d(e,"a",function(){return c}),n.d(e,"b",function(){return l}),n.d(e,"c",function(){return f}),n.d(e,"d",function(){return p});var a=n("CcnG"),r=n("rpEJ"),i=n("mrSG"),s=n("lqqz"),o=n("NJnL"),u=n("gI3B"),c=function(){return function(){this.adaptivePosition=!0,this.placement="top",this.triggers="hover focus",this.delay=0}}(),l=function(){function t(t){Object.assign(this,t)}return Object.defineProperty(t.prototype,"isBs3",{get:function(){return Object(r.d)()},enumerable:!0,configurable:!0}),t.prototype.ngAfterViewInit=function(){this.classMap={in:!1,fade:!1},this.classMap[this.placement]=!0,this.classMap["tooltip-"+this.placement]=!0,this.classMap.in=!0,this.animation&&(this.classMap.fade=!0),this.containerClass&&(this.classMap[this.containerClass]=!0)},t}(),d=0,f=function(){function t(t,e,n,r,i,s){this._elementRef=r,this._renderer=i,this._positionService=s,this.tooltipId=d++,this.tooltipChange=new a.EventEmitter,this.containerClass="",this.tooltipAnimation=!0,this.tooltipFadeDuration=150,this.ariaDescribedby="tooltip-"+this.tooltipId,this.tooltipStateChanged=new a.EventEmitter,this._tooltip=e.createLoader(this._elementRef,t,this._renderer).provide({provide:c,useValue:n}),Object.assign(this,n),this.onShown=this._tooltip.onShown,this.onHidden=this._tooltip.onHidden}return Object.defineProperty(t.prototype,"isOpen",{get:function(){return this._tooltip.isShown},set:function(t){t?this.show():this.hide()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"htmlContent",{set:function(t){Object(r.i)("tooltipHtml was deprecated, please use `tooltip` instead"),this.tooltip=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_placement",{set:function(t){Object(r.i)("tooltipPlacement was deprecated, please use `placement` instead"),this.placement=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_isOpen",{get:function(){return Object(r.i)("tooltipIsOpen was deprecated, please use `isOpen` instead"),this.isOpen},set:function(t){Object(r.i)("tooltipIsOpen was deprecated, please use `isOpen` instead"),this.isOpen=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_enable",{get:function(){return Object(r.i)("tooltipEnable was deprecated, please use `isDisabled` instead"),this.isDisabled},set:function(t){Object(r.i)("tooltipEnable was deprecated, please use `isDisabled` instead"),this.isDisabled=!t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_appendToBody",{get:function(){return Object(r.i)('tooltipAppendToBody was deprecated, please use `container="body"` instead'),"body"===this.container},set:function(t){Object(r.i)('tooltipAppendToBody was deprecated, please use `container="body"` instead'),this.container=t?"body":this.container},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_popupClass",{set:function(t){Object(r.i)("tooltipClass deprecated")},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_tooltipContext",{set:function(t){Object(r.i)("tooltipContext deprecated")},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_tooltipPopupDelay",{set:function(t){Object(r.i)("tooltipPopupDelay is deprecated, use `delay` instead"),this.delay=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_tooltipTrigger",{get:function(){return Object(r.i)("tooltipTrigger was deprecated, please use `triggers` instead"),this.triggers},set:function(t){Object(r.i)("tooltipTrigger was deprecated, please use `triggers` instead"),this.triggers=(t||"").toString()},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this._tooltip.listen({triggers:this.triggers,show:function(){return t.show()}}),this.tooltipChange.subscribe(function(e){e||t._tooltip.hide()})},t.prototype.toggle=function(){if(this.isOpen)return this.hide();this.show()},t.prototype.show=function(){var t=this;if(this._positionService.setOptions({modifiers:{flip:{enabled:this.adaptivePosition},preventOverflow:{enabled:this.adaptivePosition}}}),!(this.isOpen||this.isDisabled||this._delayTimeoutId)&&this.tooltip){var e=function(){t._delayTimeoutId&&(t._delayTimeoutId=void 0),t._tooltip.attach(l).to(t.container).position({attachment:t.placement}).show({content:t.tooltip,placement:t.placement,containerClass:t.containerClass,id:t.ariaDescribedby})},n=function(){t._tooltipCancelShowFn&&t._tooltipCancelShowFn()};if(this.delay){var a=Object(u.a)(this.delay).subscribe(function(){e(),n()});if(this.triggers){var i=Object(r.f)(this.triggers);this._tooltipCancelShowFn=this._renderer.listen(this._elementRef.nativeElement,i[0].close,function(){a.unsubscribe(),n()})}}else e()}},t.prototype.hide=function(){var t=this;this._delayTimeoutId&&(clearTimeout(this._delayTimeoutId),this._delayTimeoutId=void 0),this._tooltip.isShown&&(this._tooltip.instance.classMap.in=!1,setTimeout(function(){t._tooltip.hide()},this.tooltipFadeDuration))},t.prototype.ngOnDestroy=function(){this._tooltip.dispose()},Object(i.__decorate)([Object(r.a)(),Object(i.__metadata)("design:type",Object)],t.prototype,"tooltip",void 0),t}(),p=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[c,s.a,o.a]}},t}()},"ej+x":function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("gI3B"),r=n("psW0"),i=n("klSw"),s=n("CcnG"),o=n("t/Na"),u=function(){function t(t){var e=this;this.http=t,this.API_URL="api/feature_toggles",this.REFRESH_INTERVAL=2e4,this.featureToggleMap$=Object(a.a)(0,this.REFRESH_INTERVAL).pipe(Object(r.a)(function(){return e.http.get(e.API_URL)}),Object(i.a)(1))}return t.prototype.get=function(){return this.featureToggleMap$},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(o.c))},token:t,providedIn:"root"}),t}()},ejVf:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.standard="standard",t.flex="flex",t.force="force"}(e.ColumnMode||(e.ColumnMode={}))},"f/UV":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},fB8H:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="zh-CN">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>\u5207\u6362\u5bfc\u822a</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>\u4eea\u8868\u76d8</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>\u96c6\u7fa4</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>\u4e3b\u673a</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitor</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>\u914d\u7f6e\u9879</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH \u7d22\u5f15</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Manager \u6269\u5c55\u6a21\u5757</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>\u65e5\u5fd7</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>\u8b66\u544a</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>\u5b58\u50a8\u6c60</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>\u5757\u8bbe\u5907</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>\u6620\u50cf</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>\u955c\u50cf</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>\u6587\u4ef6\u7cfb\u7edf</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>\u5bf9\u8c61\u7f51\u5173</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>\u5b88\u62a4\u8fdb\u7a0b</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>\u5b58\u50a8\u6876</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>\u5173\u4e8e\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> \u7684\u6570\u636e\uff0c\u6b63\u4e3a\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\u83b7\u53d6\u4e2d\uff0c\u8bf7\u7a0d\u5019...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>\u5173\u4e8e\u4e4b\u524d\u7f13\u5b58\u7684\u6570\u636e\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\uff0c\u6b63\u4e3a\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\u663e\u793a\u3002\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>\u5173\u4e8e\u6570\u636e\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> \uff0c\u65e0\u6cd5\u4e3a\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\u52a0\u8f7d\u3002\n \u8bf7\u68c0\u67e5\u96c6\u7fa4\u7684\u5065\u5eb7\u72b6\u51b5\u3002\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>\u8fd4\u56de</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>\u8bf7\u9009\u62e9\u8bed\u8a00</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>\u6b63\u5728\u52a0\u8f7d\u9762\u677f\u7684\u76f8\u5173\u6570\u636e\u2026</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>\u5173\u4e8e\u5982\u4f55\u914d\u7f6e\u4ee5\u53ca\u6253\u5f00\u76d1\u63a7\u529f\u80fd\uff0c\n\u8bf7\u53c2\u9605\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u6863\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>\u65e0 Grafana \u4eea\u8868\u76d8\u3002\u5173\u4e8e\u5982\u4f55\u4e3a Grafana \u6dfb\u52a0\n\u4eea\u8868\u76d8\uff0c\u8bf7\u53c2\u8003\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u6863\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> \u3002\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Grafana \u65f6\u95f4\u9009\u62e9\u5de5\u5177</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>\u91cd\u65b0\u8bbe\u7f6e</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>\u65e0\u6cd5\u52a0\u8f7d\u6570\u636e\u3002</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>\u9009\u4e2d\u4e2a\u6570</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>\u547d\u4e2d\u4e2a\u6570</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>\u603b\u6570</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>\u7f16\u8f91</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>\u540d\u79f0</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>\u89e3\u91ca</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>\u66f4\u8be6\u5c3d\u7684\u89e3\u91ca</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>\u7f3a\u7701\u503c</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>\u5b88\u62a4\u8fdb\u7a0b\u7684\u7f3a\u7701\u503c</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>\u5bf9\u5e94\u7684\u670d\u52a1</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>\u53ef\u9009\u503c</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>\u8bbe\u7f6e\u7684\u503c\u592a\u5927\u4e86\uff01\u5e94\u4f4e\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>\u8bbe\u7f6e\u7684\u503c\u592a\u5c0f\u4e86\uff01\u4e0d\u80fd\u4f4e\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>\u4fdd\u5b58</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>\u68c0\u67e5 CRUSH \u7d22\u5f15\u56fe</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>\u4e3b\u673a\u5217\u8868</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>\u603b\u4f53\u6027\u80fd</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>\u65e0\u6cd5\u627e\u5230\u76f8\u5173\u6761\u76ee</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>\u96c6\u7fa4\u65e5\u5fd7</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>\u5ba1\u8ba1\u65e5\u5fd7</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>\u6b63\u5728\u52a0\u8f7d\u76f8\u5173\u914d\u7f6e\u4fe1\u606f...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>\u914d\u7f6e\u4fe1\u606f\u65e0\u6cd5\u52a0\u8f7d\u3002</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>\u7f16\u8f91 Manager \u6269\u5c55\u6a21\u5757</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>\u8f93\u5165\u503c\u4e0d\u662f\u6709\u6548\u7684 UUID\uff0c\u5982\uff1a67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>\u8f93\u5165\u7684\u5e94\u8be5\u662f\u4e2a\u6709\u6548\u7684 IP \u5730\u5740\u3002</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>\u8bf7\u586b\u5199\u6b64\u680f\u76ee\uff01</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>\u8f93\u5165\u503c\u8fc7\u5927\uff01\u5fc5\u987b\u5c0f\u4e8e\u6216\u7b49\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>\u8f93\u5165\u503c\u8fc7\u5c0f\uff01\u5fc5\u987b\u5927\u4e8e\u6216\u7b49\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>\u8f93\u5165\u987b\u4e3a\u6570\u5b57\u3002</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>\u8f93\u5165\u7684\u5e94\u8be5\u662f\u4e00\u4e2a\u6d6e\u70b9\u6570\u6216\u8005\u5341\u8fdb\u5236\u6574\u6570\u3002</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>\u72b6\u6001</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>\u96c6\u7fa4 ID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap \u4fee\u6539\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap epoch</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con </target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>required con</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>required mon</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>\u4ef2\u88c1\u6210\u5458</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>\u975e\u4ef2\u88c1\u6210\u5458</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>\u53d6\u6d88</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>\u60a8\u786e\u5b9a\u8981\n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\u9009\u4e2d\u7684\n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\u5417\uff1f\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>\u662f\u7684\uff0c\u6211\u786e\u5b9a\u3002</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>\u96c6\u7fa4\u8303\u56f4\u7684 OSD \u6807\u5fd7</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>\u63d0\u4ea4</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>\u9ad8\u7ea7\u8bbe\u7f6e\u2026</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>OSD \u6062\u590d\u4f18\u5148\u7ea7</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>\u4f18\u5148\u7ea7</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>\u81ea\u5b9a\u4e49\u4f18\u5148\u7ea7</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>\u8fd9\u4e2a\u5b57\u6bb5\u662f\u5fc5\u586b\u7684\uff01</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>\u8f93\u5165\u503c\u8fc7\u5927\uff01\u4e0d\u80fd\u5927\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>\u8f93\u5165\u503c\u8fc7\u5c0f\uff01\u4e0d\u80fd\u5c0f\u4e8e \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>\u91cd\u65b0\u8bbe\u7f6e OSD \u7684\u6743\u91cd</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>\u6743\u91cd\u503c\u5fc5\u987b\u5728 0 \u548c 1 \u4e4b\u95f4</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>\u91cd\u8bbe\u6743\u91cd</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\u6d17\u5237\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {\u6df1\u5ea6}}</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>\u5373\u5c06\u5bf9 OSD\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u6267\u884c\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> \u6d17\u5237\u3002\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {\u6df1\u5ea6} }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>OSD \u5217\u8868</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u5982\u679c\u7ee7\u7eed\uff0c\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD\n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n\u5c06\u88ab\u6807\u8bb0\u4e3a\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>OSD \u4e0d\u5b89\u5168\uff0c\u65e0\u6cd5\u9500\u6bc1\uff01</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u5982\u679c\u7ee7\u7eed\uff0c\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD\n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n\u5c06\u88ab\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>\u8be6\u60c5</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>\u503c</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>\u5173\u95ed</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>\u5220\u9664</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>\u5065\u5eb7\u72b6\u51b5</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>\u7edf\u8ba1\u6570\u636e</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>\u5173\u4e8e\u5982\u4f55\u914d\u7f6e\u548c\u542f\u7528 NFS Ganesha \u7ba1\u7406\u529f\u80fd\uff0c\n\u8bf7\u53c2\u8003\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u6863\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>\u5ba2\u6237\u7aef</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>\u4efb\u4f55\u5ba2\u6237\u7aef\u5747\u53ef\u8bbf\u95ee</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>\u5730\u5740</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>\u5fc5\u586b\u9879</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u9017\u53f7\u5206\u9694\u503c</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>\u4f8b\u5982\uff1a</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>\u8bbf\u95ee\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>\u6dfb\u52a0\u5ba2\u6237\u7aef</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>\u6b63\u5728\u52a0\u8f7d\u2026</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- \u65e0\u53ef\u7528\u96c6\u7fa4 --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- \u8bf7\u9009\u62e9\u4e00\u4e2a\u96c6\u7fa4 --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>\u6dfb\u52a0\u5b88\u62a4\u8fdb\u7a0b</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>\u5b58\u50a8\u540e\u7aef</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- \u6ca1\u6709\u53ef\u7528\u7684\u6570\u636e\u5b58\u50a8\u6c60 --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- \u8bf7\u9009\u62e9\u5b58\u50a8\u540e\u7aef --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>\u5bf9\u8c61\u7f51\u5173\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- \u65e0\u53ef\u9009\u7528\u6237 --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- \u8bf7\u9009\u62e9\u5bf9\u8c61\u7f51\u5173\u7528\u6237 --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS \u7528\u6237 ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- \u65e0\u53ef\u7528\u5ba2\u6237\u7aef --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- \u8bf7\u9009\u62e9 cephx \u5ba2\u6237\u7aef --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>CephFS \u540d\u79f0</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>\u5b89\u5168\u6807\u7b7e</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>\u542f\u7528\u5b89\u5168\u6807\u7b7e</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS \u8def\u5f84</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>\u8def\u5f84\u9700\u4ee5\u201c/\u201d\u5f00\u5934\uff0c\u540e\u9762\u53ef\u8ddf\u5355\u8bcd</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>\u5c06\u521b\u5efa\u65b0\u6587\u4ef6\u5939</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>\u8def\u5f84</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>\u8def\u5f84\u53ea\u80fd\u662f\u5355\u4e2a\u201c/\u201d\u6216\u5355\u8bcd</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>\u5c06\u521b\u5efa\u65b0\u7684\u6876</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS \u534f\u8bae</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS \u6807\u7b7e</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u88c5\u5165\u7684\u5907\u7528\u8bbf\u95ee\uff08\u4e0d\u5f97\u5305\u542b\u524d\u7f6e /\uff09\u3002\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>\u5ba2\u6237\u7aef\u4e0d\u80fd\u88c5\u5165\u5b50\u76ee\u5f55\uff08\u5373\u5982\u679c\u6807\u8bb0\u4e3a foo\uff0c\u5219\u5ba2\u6237\u7aef\u65e0\u6cd5\u88c5\u5165 foo/baz\uff09\u3002</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>\u901a\u8fc7\u4f7f\u7528\u4e0d\u540c\u6807\u8bb0\u9009\u9879\uff0c\u53ef\u5c06\u540c\u4e00\u8def\u5f84\u5bfc\u51fa\u591a\u6b21\u3002</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>\u4f2a</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>\u6b64 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u5bfc\u51fa\u5728\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\u4f2a\u6587\u4ef6\u7cfb\u7edf\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u4e2d\n \u6240\u5360\u7528\u7684\u4f4d\u7f6e\uff08\u5fc5\u987b\u552f\u4e00\uff09\u3002\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>\u901a\u8fc7\u4f7f\u7528\u4e0d\u540c\u4f2a\u9009\u9879\uff0c\u53ef\u5c06\u540c\u4e00\u8def\u5f84\u5bfc\u51fa\u591a\u6b21\u3002</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- \u6ca1\u6709\u53ef\u7528\u7684\u8bbf\u95ee\u7c7b\u578b --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- \u9009\u62e9\u8bbf\u95ee\u7c7b\u578b --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- \u6ca1\u6709\u53ef\u7528\u7684 squash --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- \u9009\u62e9\u6267\u884c\u54ea\u79cd\u7c7b\u578b\u7684\u7528\u6237 ID \u533f\u540d\u8bbf\u95ee --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>\u4f20\u8f93\u534f\u8bae</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>\u6b22\u8fce\u4f7f\u7528 Ceph\uff01</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>\u8bf7\u8f93\u5165\u7528\u6237\u540d</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>\u8bf7\u8f93\u5165\u5bc6\u7801</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>\u767b\u5f55</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>\u62b1\u6b49\uff0c\u6b64\u7528\u6237\u4e0d\u5b58\u5728\u3002</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>\u8fd4\u56de\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u767b\u5f55\u9875\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\u60a8\u5c06\u5728\u91cd\u65b0\u767b\u5f55\u65f6\u4ece\u8eab\u4efd\u63d0\u4f9b\u7a0b\u5e8f\u6ce8\u9500\u3002\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>\u7981\u6b62\u8bbf\u95ee</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>\u62b1\u6b49\uff0c\u60a8\u65e0\u6743\u8bbf\u95ee\u8fd9\u4e2a\u9875\u9762\u3002</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>\u62b1\u6b49\uff0c\u6211\u4eec\u627e\u4e0d\u5230\u60a8\u8981\u770b\u7684\u4e1c\u897f\u3002</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>\u5168\u90e8\u5df2\u8bfb</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>\u6700\u65b0\u7684\u901a\u77e5</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>\u6ca1\u6709\u540e\u53f0\u4efb\u52a1\u6b63\u5728\u6267\u884c\u3002</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>\u540e\u53f0\u4efb\u52a1</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>\u5e2e\u52a9</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>\u6587\u6863</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\u5173\u4e8e</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>\u4eea\u8868\u76d8\u8bbe\u7f6e</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>\u7528\u6237\u7ba1\u7406</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>\u767b\u5f55\u7684\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>\u4ee5\u7528\u6237\u540d \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n\u8fdb\u884c\u767b\u5f55\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>\u767b\u51fa</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>\u540d\u79f0\u2026</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>\u6240\u9009\u540d\u79f0\u5df2\u7ecf\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>\u63cf\u8ff0\u2026</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>\u6743\u9650</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>\u89d2\u8272</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>\u7528\u6237\u540d</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>\u5bc6\u7801</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>\u786e\u8ba4\u5bc6\u7801</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>\u5bc6\u7801\u548c\u4e4b\u524d\u7684\u8f93\u5165\u4e0d\u5339\u914d\u3002</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>\u5168\u540d</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>\u90ae\u7bb1</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>\u90ae\u7bb1\u5730\u5740\u65e0\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>\u60a8\u5373\u5c06\u53d6\u6d88\u60a8\u81ea\u5df1\u7528\u6237\u7684 "user read / update" \u6743\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>\u5982\u679c\u60a8\u7ee7\u7eed\u7684\u8bdd\uff0c\u60a8\u4ee5\u540e\u5c31\u6ca1\u529e\u6cd5\u4e3a\u5176\u4ed6\u7528\u6237\u6dfb\u52a0\u6216\u8005\u5220\u9664\u89d2\u8272\u4e86\u3002</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>\u60a8\u786e\u5b9e\u8981\u7ee7\u7eed\u5417\uff1f</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>\u65e0\u6cd5\u8bfb\u53d6\u6027\u80fd\u8ba1\u6570\u5668</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>OSD map</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>\u5143\u6570\u636e\u4e0d\u53ef\u7528</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>\u76f8\u5173\u5143\u6570\u636e</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>\u6027\u80fd\u8ba1\u6570\u5668</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>\u76f4\u65b9\u56fe\u4e0d\u53ef\u7528\uff1a\n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>\u5199\u5165\u8bf7\u6c42</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>\u8bfb\u53d6\u8bf7\u6c42</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>\u76f4\u65b9\u56fe</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>\u6027\u80fd\u8be6\u60c5</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>\u5f53\u524d\u503c</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>\u4e0b\u9650</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>\u6807\u5fd7</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>\u6765\u6e90</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>\u7ea7\u522b</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>\u53ef\u5728\u8fd0\u884c\u65f6\u66f4\u65b0\uff08\u53ef\u7f16\u8f91\uff09</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>\u6807\u8bb0</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>\u53ef\u9009\u9879</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>\u53c2\u89c1</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>\u96c6\u7fa4\u72b6\u6001</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>manager \u5b88\u62a4\u8fdb\u7a0b</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>\u5bf9\u8c61\u7f51\u5173</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>metadata \u670d\u52a1\u5668</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI \u7f51\u5173</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>\u5ba2\u6237\u7aef IOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>\u5ba2\u6237\u7aef\u541e\u5410\u91cf</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>\u5ba2\u6237\u7aef\u8bfb/\u5199</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>\u6062\u590d\u541e\u5410\u91cf</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>\u6d17\u5237</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>\u6027\u80fd</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>\u57fa\u672c\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>\u5bf9\u8c61\u6570</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>\u6bcf\u4e2a OSD \u7684 PG \u6570</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>PG \u72b6\u6001</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>\u67e5\u770b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u65e5\u5fd7\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u4ee5\u83b7\u5f97\u66f4\u591a\u7ec6\u8282\u3002\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>\u6392\u4f4d</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>\u5ba2\u6237\u7aef\uff1a\n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>\u5c06\u6620\u50cf\u79fb\u81f3\u56de\u6536\u7ad9</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>\u8981\u5c06 \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u79fb\u81f3\u56de\u6536\u7ad9\uff0c\n \u8bf7\u70b9\u51fb \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u79fb\u52a8\u6620\u50cf\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\u6b64\u5916\uff0c\u53ef\u9009\u62e9\u8bbe\u7f6e\u4e00\u4e2a\u8fc7\u671f\u65f6\u95f4\u3002\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>\u4fdd\u62a4\u671f\u4e00\u76f4\u5230</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>\u65e0\u4fdd\u62a4</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>\u65e5\u671f\u683c\u5f0f\u6709\u95ee\u9898\u3002\u8bf7\u4f7f\u7528\u201cYYYY-MM-DD HH:mm:ss\u201d\u3002</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>\u4fdd\u62a4\u671f\u9650\u5df2\u7ecf\u8fc7\u4e86\u3002\u8bf7\u8bbe\u7f6e\u4e00\u4e2a\u5c06\u6765\u7684\u65e5\u671f\uff0c\u6216\u8005\u6e05\u7a7a\u4e0d\u586b\u3002</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>\u79fb\u52a8\u6620\u50cf</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>\u6982\u89c8</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>\u76ee\u6807</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>\u53d1\u73b0\u8eab\u4efd\u9a8c\u8bc1</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u7528\u6237\u540d\u957f\u5ea6\u5fc5\u987b\u5728 8 \u5230 64 \u4e2a\u5b57\u7b26\u4e4b\u95f4\uff0c\u4e14\u53ea\u80fd\u5305\u542b\n\u4ee5\u4e0b\u5b57\u7b26\uff1a\u82f1\u6587\u5b57\u6bcd\u3001\u201c.\u201d\u3001\u201c@\u201d\u3001\u201c-\u201d\u3001\u201c_\u201d\u6216\u201c:\u201d\u3002</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>\u4e92\u8ba4\u8bc1\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>\u4e92\u8ba4\u8bc1\u5bc6\u7801</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>\u5173\u4e8e\u5982\u4f55\u914d\u7f6e\u548c\u542f\u7528 iSCSI \u76ee\u6807\u7ba1\u7406\u529f\u80fd\uff0c\n\u8bf7\u53c2\u8003\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u6863\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>\u53ef\u7528\u4fe1\u606f\uff1a</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>\u65e0\u53ef\u7528 iSCSI \u76ee\u6807</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>\u53ea\u5bf9\u542f\u52a8\u4e86 \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> \u529f\u80fd\u7684 RBD \u6620\u50cf\u53ef\u7528\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>\u5b58\u50a8\u6c60</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>\u6570\u636e\u5b58\u50a8\u6c60</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>\u521b\u5efa</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>\u5bf9\u8c61\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>\u7279\u6027</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>\u4f9b\u7ed9\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/A</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>\u603b\u4f9b\u7ed9\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>\u6761\u5e26\u5355\u5143</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>\u6761\u5e26\u4e2a\u6570</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>\u7236\u8282\u70b9</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>\u5757\u5b58\u50a8\u540d\u5b57\u524d\u7f00</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>order</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>\u5feb\u7167</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>\u6620\u50cf</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>\u6b64\u8bbe\u7f6e\u4f1a\u8986\u76d6\u5168\u5c40\u503c</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>\u5168\u5c40</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>\u8be5\u503c\u4e3a\u5168\u5c40\u503c\u3002\u6ca1\u6709\u4e3a\u6b64\u6620\u50cf\u8bbe\u7f6e\u6b64\u9009\u9879\u7684\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\u4e0d\u5141\u8bb8\u4f7f\u7528\u201c/\u201d\u548c\u201c@\u201d\u3002</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- \u6ca1\u6709\u53ef\u7528\u7684 RBD \u5b58\u50a8\u6c60 --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- \u8bf7\u9009\u62e9\u5b58\u50a8\u6c60 --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>\u4f7f\u7528\u4e00\u4e2a\u4e13\u7528\u7684\u6570\u636e\u6c60</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>\u6570\u636e\u6c60</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>\u4e3a\u4fdd\u5b58 RBD \u7684\u5bf9\u8c61\u6570\u636e\u5355\u72ec\u5206\u914d\u7684\u5b58\u50a8\u6c60\u3002</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>\u5982 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>\u60a8\u9700\u8981\u8bbe\u7f6e\u5927\u4e00\u4e9b\u7684\u5bb9\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>\u9ad8\u7ea7\u8bbe\u7f6e</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>\u6761\u5e26</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>\u6761\u5e26\u5355\u5143\u5927\u5c0f</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- \u9009\u62e9\u6761\u5e26\u5355\u5143\u5927\u5c0f --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>\u56e0\u4e3a\u8bbe\u7f6e\u4e86\u6761\u5e26\u4e2a\u6570\uff0c\u6240\u4ee5\u8fd9\u4e2a\u5b57\u6bb5\u662f\u5fc5\u9009\u7684\uff01</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>\u6761\u5e26\u5355\u5143\u5927\u5c0f\u8d85\u8fc7\u4e86\u5bf9\u8c61\u5927\u5c0f\u3002</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>\u6761\u5e26\u4e2a\u6570</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>\u56e0\u4e3a\u8bbe\u7f6e\u4e86\u6761\u5e26\u5355\u5143\u5927\u5c0f\uff0c\u6240\u4ee5\u8fd9\u4e2a\u5b57\u6bb5\u662f\u5fc5\u9009\u7684\uff01</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>\u6761\u5e26\u7684\u4e2a\u6570\u5fc5\u987b\u5927\u4e8e 0\u3002</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>RBD \u5feb\u7167\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {\u6539\u540d} other {\u521b\u5efa} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>\u5feb\u7167\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>\u53d7\u4fdd\u62a4\u7684</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>\u65e0\u4fdd\u62a4\u7684</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>\u60a8\u5373\u5c06\u8fdb\u884c\u56de\u6eda\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>\u6e05\u7a7a\u56de\u6536\u7ad9</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>\u8981\u5f7b\u5e95\u6e05\u7a7a\u7684\u8bdd\uff0c\u8bf7\u9009\u62e9\u5355\u4e2a\u6216\u6240\u6709\u7684\u6620\u50cf\uff0c\u7136\u540e\u70b9\u51fb</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>\u5b58\u50a8\u6c60\uff1a</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>\u5b58\u50a8\u6c60\u540d\u79f0\u2026</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>\u5168\u9009</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>\u6062\u590d\u6620\u50cf</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>\u8981\u6062\u590d</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>\u8f93\u5165\u6620\u50cf\u7684\u65b0\u540d\u79f0\uff0c\u5e76\u70b9\u51fb</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>\u65b0\u540d\u79f0</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>\u8fc7\u671f\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>\u4fdd\u62a4\u671f\u9650</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>\u4e00\u76f4\u5230\n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>\uff0c\u8be5\u6620\u50cf\u90fd\u4f1a\u53d7\u4fdd\u62a4\u3002\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>\u56de\u6536\u7ad9</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>iSCSI \u7ed3\u6784\u56fe</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>\u901a\u5e38\u65e0\u987b\u6539\u53d8\u8fd9\u4e9b\u9ed8\u8ba4\u53c2\u6570\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>\u8bbe\u7f6e</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>\u540e\u5907\u5b58\u50a8</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>\u786e\u8ba4</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>\u9ad8\u7ea7\u8bbe\u7f6e</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>\u76ee\u6807\u9650\u5b9a\u540d</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN \u683c\u5f0f\u9519\u8bef\u3002</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN \u5e94\u7531\u4ee5\u4e0b\u683c\u5f0f\u6784\u6210\uff1a\u201ciqn.$year-$month.$reversedAddress:$definedName\u201d</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>\u4f8b\u5982\uff1aiqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>\u66f4\u591a\u4fe1\u606f</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>\u6b64\u76ee\u6807\u7684\u9ad8\u7ea7\u8bbe\u7f6e\u9879\u5b58\u5728\u4fee\u6539\u3002</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>\u7aef\u53e3</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>\u81f3\u5c11\u9700\u8981 \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> \u4e2a\u7f51\u5173\u3002\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>\u6dfb\u52a0\u7aef\u53e3</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>\u6b64\u6620\u50cf\u7684\u8bbe\u7f6e\u9879\u5b58\u5728\u4fee\u6539\u3002</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>\u6dfb\u52a0\u6620\u50cf</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL \u8eab\u4efd\u9a8c\u8bc1</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>\u6388\u6743\u4eba</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>\u6388\u6743\u4eba</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>\u5ba2\u6237\u7aef IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>\u6388\u6743\u4eba IQN \u5fc5\u987b\u552f\u4e00\u3002</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u7528\u6237\u540d\u957f\u5ea6\u5fc5\u987b\u5728 8 \u5230 64 \u4e2a\u5b57\u7b26\u4e4b\u95f4\uff0c\u4e14\u53ea\u80fd\u5305\u542b\n\u4ee5\u4e0b\u5b57\u7b26\uff1a\u82f1\u6587\u5b57\u6bcd\u3001\u201c.\u201d\u3001\u201c@\u201d\u3001\u201c-\u201d\u3001\u201c_\u201d\u6216\u201c:\u201d\u3002</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>\u6388\u6743\u4eba\u5c5e\u4e8e\u7fa4\u7ec4\u3002\u6620\u50cf\u987b\u5728\u7fa4\u7ec4\u4e2d\u8fdb\u884c\u8bbe\u7f6e\u3002</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>\u65e0\u9879\u76ee\u6dfb\u52a0\u3002</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>\u6dfb\u52a0\u6388\u6743\u4eba</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>\u7fa4\u7ec4</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>\u7fa4\u7ec4</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>\u6dfb\u52a0\u7fa4\u7ec4</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>RBD \u914d\u7f6e</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>\u5220\u9664\u672c\u5730\u7684\u914d\u7f6e\u9879\uff0c\u6539\u7528\u66f4\u9ad8\u4f5c\u7528\u57df\u7684\u914d\u7f6e\u503c\u3002</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>\u6700\u5c0f\u503c\u4e3a 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>\u95ee\u9898</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>\u6b63\u5728\u540c\u6b65</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>\u5df2\u5c31\u7eea</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>\u7f16\u8f91\u5b58\u50a8\u6c60\u955c\u50cf\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\u8981\u7f16\u8f91\u5b58\u50a8\u6c60\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\xa0\n \u7684\u955c\u50cf\u6a21\u5f0f\uff0c\u8bf7\u4ece\u5217\u8868\u4e2d\u9009\u62e9\u4e00\u9879\uff0c\u5e76\u70b9\u51fb\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u66f4\u65b0\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>\u5728\u7981\u7528\u955c\u50cf\u529f\u80fd\u524d\u5fc5\u987b\u5148\u79fb\u9664\u540c\u4f34\u96c6\u7fa4\u3002</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n\u5b58\u50a8\u6c60\u955c\u50cf\u540c\u4f34\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {\u7f16\u8f91} other {\u6dfb\u52a0} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\u5b58\u50a8\u6c60\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\n \u7684\u5b58\u50a8\u6c60\u955c\u50cf\u540c\u4f34\u5c5e\u6027\uff0c\u5e76\u70b9\u51fb\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\u63d0\u4ea4\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3002\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>\u96c6\u7fa4\u540d\u79f0</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>\u96c6\u7fa4\u540d\u79f0\u65e0\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>CephX ID \u65e0\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Monitor \u5730\u5740</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>\u9017\u53f7\u5206\u5272\u7684\u5730\u5740...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>Monitor \u5730\u5740\u65e0\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX \u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64 \u7f16\u7801\u7684\u5bc6\u94a5...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>CephX \u5bc6\u94a5\u5fc5\u987b\u662f base64 \u7f16\u7801\u7684\u3002</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>\u5b58\u50a8\u6c60\u5217\u8868</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>\u540d\u79f0\u53ea\u80fd\u7531\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u77ed\u5212\u7ebf\u548c\u4e0b\u5212\u7ebf\u7ec4\u6210\u3002</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>\u6b64\u7ea0\u5220\u7801\u914d\u7f6e\u540d\u79f0\u5df2\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>\u7ea0\u5220\u7801\u7b97\u6cd5</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>\u6570\u636e\u5757 (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>\u5fc5\u987b\u5927\u4e8e\u7b49\u4e8e 2</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>\u6821\u9a8c\u5757 (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>\u5fc5\u987b\u5927\u4e8e\u7b49\u4e8e 1</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>\u6301\u4e45\u56e0\u5b50 (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>\u5c40\u90e8\u6027\u56e0\u5b50 (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>CRUSH \u6545\u969c\u57df</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>CRUSH \u5c40\u90e8\u6027</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>\u65e0</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>\u7b97\u6cd5</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>packetsize</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>CRUSH \u6839</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>CRUSH \u8bbe\u5907\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>\u4efb\u610f</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>\u76ee\u5f55</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>\u6b64 Ceph \u5b58\u50a8\u6c60\u540d\u79f0\u5df2\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>\u5b58\u50a8\u6c60\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- \u8bf7\u9009\u62e9\u5b58\u50a8\u6c60\u7684\u7c7b\u578b --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>\u5f52\u7f6e\u7ec4 (PG)</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>\u81f3\u5c11\u9700\u8981\u4e00\u4e2a\u5f52\u7f6e\u7ec4\uff01</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>\u60a8\u7684\u96c6\u7fa4\u6ca1\u6cd5\u652f\u6301\u8fd9\u4e48\u591a\u7684 PG\u3002\u8bf7\u91cd\u65b0\u8ba1\u7b97\u9700\u8981\u7684 PG \u4e2a\u6570\u3002</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>\u5728\u7ebf PG \u8ba1\u7b97\u5668</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>\u5df2\u6839\u636e\u5f53\u524d\u60c5\u51b5\u4e3a\u60a8\u63a8\u7b97\u51fa\u4e86 PG \u7684\u8bbe\u7f6e\uff0c\u60a8\n\u6700\u597d\u5728\u63d0\u4ea4\u4e4b\u524d\u786e\u8ba4\u8fd9\u4e9b\u8bbe\u7f6e\u662f\u5408\u9002\u7684\u3002</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>CRUSH \u7b97\u6cd5\u89c4\u5219\u7ec4</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- \u9009\u62e9 CRUSH \u89c4\u5219 --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>CRUSH \u89c4\u5219</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>CRUSH \u6b65\u9aa4</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>\u5f53\u524d\u7684\u96c6\u7fa4\u65e0\u6cd5\u4f7f\u7528\u8be5\u89c4\u5219\uff0c\u56e0\u4e3a\u96c6\u7fa4\u7684 OSD \u4e2a\u6570\u8fc7\u5c11\uff0c\n \u65e0\u6cd5\u6ee1\u8db3\u89c4\u5219\u6240\u9700\u7684\u6700\u4f4e OSD \u6570\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>\u526f\u672c\u4e2a\u6570</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>\u6700\u4f4e\uff1a\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>\u6700\u9ad8\uff1a\n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>\u8bbe\u7f6e\u7684\u8d85\u8fc7\u4e86\u9650\u5236\u3002\u8bbe\u7f6e\u503c\u5e94\u8be5\u5728\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> \u548c \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> \u4e2d\u95f4\u4e3a\u5b9c.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>\u7ea0\u5220\u7801\u914d\u7f6e</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- \u65e0\u7ea0\u5220\u7801\u914d\u7f6e\u53ef\u9009 --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- \u8bf7\u9009\u62e9\u4e00\u4e2a\u7ea0\u5220\u7801\u914d\u7f6e --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC \u91cd\u5199 (overwrite)</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>\u5e94\u7528\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>\u538b\u7f29</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>\u7b97\u6cd5</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- \u65e0\u53ef\u7528\u7684\u7ea0\u5220\u7801\u538b\u7f29\u7b97\u6cd5 --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>blob \u5927\u5c0f\u4e0b\u9650</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>\u6bd4\u5982 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>\u53d6\u503c\u5fc5\u987b\u5927\u4e8e 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>blob \u5927\u5c0f\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>\u5982 512KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>\u53d6\u503c\u5fc5\u987b\u5927\u4e8e blob \u5927\u5c0f\u4e0b\u9650</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>\u6bd4\u4f8b</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>\u538b\u7f29\u7387</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>\u53d6\u503c\u5fc5\u987b\u5728 0.0 \u548c 1.0 \u4e4b\u95f4</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>\u65e0\u6cd5\u65b0\u5efa\u540d\u5b57\u4e2d\u6709\u201c/\u201d\u7684 RBD \u5b58\u50a8\u6c60\u3002</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>\u8bf7\u91cd\u65b0\u547d\u540d\uff0c\u6216\u8005\u628a\u5b58\u50a8\u6c60\u7684\u201crbd\u201d\u5e94\u7528\u6807\u8bb0\u53bb\u6389\u3002</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>\u7f13\u5b58\u5c42\u8be6\u7ec6\u4fe1\u606f</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>\u5173\u4e8e\u5982\u4f55\u914d\u7f6e\u548c\u542f\u7528\u5bf9\u8c61\u7f51\u5173\u7684\u529f\u80fd\uff0c\n \u8bf7\u53c2\u8003\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u6587\u6863\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> \u3002\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>\u5b88\u62a4\u8fdb\u7a0b\u5217\u8868</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>\u6027\u80fd\u8ba1\u6570\u5668</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>\u6b63\u5728\u52a0\u8f7d\u5b58\u50a8\u6876\u6570\u636e\u2026</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>\u5b58\u50a8\u6876\u6570\u636e\u65e0\u6cd5\u52a0\u8f7d\u3002</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>\u8f93\u5165\u503c\u65e0\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>\u6240\u6709\u8005</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- \u8bf7\u9009\u62e9\u4e00\u4e2a\u7528\u6237 --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>\u7d22\u5f15\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>\u5f52\u7f6e\u89c4\u5219</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>\u6807\u8bc6</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>max marker</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>\u4e3b\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>\u4fee\u6539\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>zonegroup</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>\u5b58\u50a8\u6876\u914d\u989d</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>\u5f00\u542f</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>\u6700\u5927\u6570\u76ee</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>\u65e0\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>\u6700\u5927\u5bf9\u8c61\u6570\u76ee</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- \u8bf7\u9009\u62e9\u7528\u6237\u540d --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>\u81ea\u52a8\u751f\u6210\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>\u8bbf\u95ee\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>\u79d8\u5bc6\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>\u90ae\u7bb1</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>\u51bb\u7ed3</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>\u7cfb\u7edf</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {\u5426} 1 {\u662f} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>\u6700\u5927\u5b58\u50a8\u6876\u6570\u76ee</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>\u5b50\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>\u7528\u6237\u6743\u9650</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>\u7528\u6237\u914d\u989d</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>\u663e\u793a</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- \u8bf7\u9009\u62e9\u4e00\u4e2a\u7c7b\u578b --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>\u6743\u9650</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- \u8bf7\u9009\u62e9\u6743\u9650\u7c7b\u578b --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>\u5b50\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>\u6240\u9009\u7684\u5b50\u7528\u6237 ID \u5df2\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>\u8bfb\u3001\u5199</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>\u5168\u90e8</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Swift \u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>\u81ea\u52a8\u751f\u6210\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>\u6b63\u5728\u52a0\u8f7d\u7528\u6237\u6570\u636e\u2026</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>\u7528\u6237\u6570\u636e\u65e0\u6cd5\u52a0\u8f7d\u3002 </target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>\u6240\u9009\u7684\u7528\u6237 ID \u5df2\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>\u65e0\u6548\u7684\u90ae\u7bb1\u5730\u5740\u3002</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>\u6b64\u90ae\u7bb1\u5730\u5740\u5df2\u88ab\u4f7f\u7528\u3002</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>\u5b58\u50a8\u6876\u4e2a\u6570\u7684\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>\u8bbe\u7f6e\u7684\u503c\u5fc5\u987b &gt;= 0\u3002</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3 \u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>\u6ca1\u6709\u5b50\u7528\u6237\u3002</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>\u6ca1\u6709\u4efb\u4f55\u5bc6\u94a5\u3002</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>\u6743\u9650\u4e3a\u7a7a\u3002</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>\u7a7a\u95f4\u65e0\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>\u7a7a\u95f4\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>\u5bf9\u8c61\u4e2a\u6570\u65e0\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>\u5bf9\u8c61\u4e2a\u6570\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>\u5f53\u524d</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>\u5df2\u66f4\u65b0\u53d1\u73b0\u8eab\u4efd\u9a8c\u8bc1</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>\u65e0\u53ef\u7528\u7aef\u53e3\u3002</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>\u65e0\u53ef\u7528\u6620\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>\u65e0\u53ef\u7528\u6620\u50cf\u3002\u8bf7\u786e\u4fdd\u4e3a\u76ee\u6807\u6dfb\u52a0\u4e00\u4e2a\u6620\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>\u65e0\u53ef\u7528\u6388\u6743\u4eba\u3002\u8bf7\u786e\u4fdd\u4e3a\u76ee\u6807\u6dfb\u52a0\u4e00\u4e2a\u6388\u6743\u4eba\u3002</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>\u76ee\u6807</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>\u72b6\u6001</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>\u8bfb\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>\u5199\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>\u8bfb\u8bf7\u6c42\u6570</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>\u5199\u8bf7\u6c42\u6570</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>\u6d3b\u52a8/\u4f18\u5316\u81ea</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>\u5b9e\u4f8b</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>\u4e3b\u673a\u540d</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>\u95ee\u9898</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>\u8fdb\u5ea6</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>\u7981\u7528</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>\u7f16\u8f91\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>\u6dfb\u52a0 peer</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>\u7f16\u8f91 peer</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>\u5220\u9664 peer</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Leader</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># \u672c\u5730</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># \u8fdc\u7a0b</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>\u955c\u50cf peer</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>\u5bc6\u94a5</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>\u5b8c\u5168\u5c55\u5f00</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>\u5206\u5c42</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>\u4e92\u65a5\u9501</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>object map\uff08\u8981\u6c42\u4e92\u65a5\u9501\u652f\u6301\uff09</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>\u65e5\u5fd7\uff08\u8981\u6c42\u4e92\u65a5\u9501\u652f\u6301\uff09</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>RBD \u5feb\u7167\u56de\u6eda</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>\u56de\u6eda</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>RBD \u5feb\u7167</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>\u5b9a\u70b9\u5220\u9664</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>\u7c7b\u578b</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>\u72b6\u6001</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>\u7248\u672c</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>\u4e3b\u673a</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>\u6839</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>\u6392\u4f4d</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>\u5b88\u62a4\u8fdb\u7a0b</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>\u6d3b\u8dc3\u5ea6</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>inodes</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>\u4f7f\u7528\u7387</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>\u5907\u7528\u670d\u52a1</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\u8be5\u503c\u53ef\u5728\u8fd0\u884c\u65f6\u66f4\u65b0\u3002</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>\u670d\u52a1\u5668\u6216\u5ba2\u6237\u7aef\u4e0d\u4f1a\u4e3b\u52a8\u4ece monitor \u7684\u914d\u7f6e\u6570\u636e\u5e93\u8bfb\u53d6\u8fd9\u4e2a\u914d\u7f6e\u3002\n \u6240\u4ee5\u4e0d\u80fd\u7528\u201cceph config set ...\u201d\u8bbe\u7f6e\u5b83\u3002\u4f46\u662f\u53ef\u4ee5\u901a\u8fc7\n ceph.conf \u6216\u8005\u7528\u547d\u4ee4\u884c\u8fdb\u884c\u914d\u7f6e\u3002</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>\u8be5\u914d\u7f6e\u53ea\u6709\u5728\u670d\u52a1\u542f\u52a8\u7684\u65f6\u5019\u624d\u4f1a\u751f\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>\u8be5\u914d\u7f6e\u53ea\u5728\u521b\u5efa\u96c6\u7fa4\u7684\u65f6\u5019\u624d\u4f1a\u751f\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>\u8be5\u914d\u7f6e\u53ea\u5728\u670d\u52a1\u521b\u5efa\u7684\u65f6\u5019\u624d\u4f1a\u751f\u6548\u3002</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>\u5df2\u66f4\u65b0\u914d\u7f6e\u9009\u9879\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>\u670d\u52a1</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>\u5f53\u524d\u503c</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>\u53ef\u7f16\u8f91</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>\u5df2\u66f4\u65b0\u6269\u5c55\u6a21\u5757\u201c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u201d\u7684\u9009\u9879\u3002\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>\u542f\u7528</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>\u7981\u7528</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>\u6b63\u5728\u91cd\u65b0\u8fde\u63a5\uff0c\u8bf7\u7a0d\u5019\u2026</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>\u5916\u90e8\u5730\u5740</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>\u6d3b\u52a8\u4f1a\u8bdd</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>\u7981\u6b62\u52a0\u5165</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>\u4e4b\u524d\u88ab\u9664\u540d\u7684 OSD \u5728\u542f\u52a8\u4e4b\u540e\uff0c\u4e0d\u4f1a\u88ab\u52a0\u5165\u96c6\u7fa4</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>\u7981\u6b62\u9664\u540d</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>\u5728\u53d1\u73b0 OSD \u6ca1\u6709\u54cd\u5e94\u4e4b\u540e\u4e00\u6bb5\u65f6\u95f4\uff0c\u8be5 OSD \u4f1a\u88ab\u8e22\u51fa\u96c6\u7fa4\u3002\u8be5\u6807\u5fd7\u4f1a\u7981\u6b62\u8fd9\u4e2a\u529f\u80fd\u3002</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>\u7981\u6b62\u542f\u7528</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>\u4e0d\u5141\u8bb8 OSD \u542f\u52a8</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>\u7981\u6b62\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>\u5f53\u524d\u4e0d\u53d7\u7406\u5bf9 OSD \u7684\u5931\u6548\u62a5\u544a\uff0c\u56e0\u800c monitor \u4e0d\u4f1a\u505c\u7528 OSD</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>\u6682\u505c</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>\u6682\u505c\u8bfb\u5199</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>\u7981\u6b62\u6d17\u5237</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>\u6d17\u5237\u5df2\u7981\u6b62</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>\u7981\u6b62\u6df1\u5c42\u6d17\u5237</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>\u6df1\u5c42\u6d17\u5237\u5df2\u7981\u6b62</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>\u7981\u6b62\u56de\u586b</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>PG \u56de\u586b\u5df2\u63a8\u8fdf</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>\u7981\u6b62\u6062\u590d</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>PG \u6062\u590d\u5df2\u63a8\u8fdf</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>\u9010\u4f4d\u6392\u5e8f</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>\u4f7f\u7528\u9010\u4f4d\u6392\u5e8f</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>\u8001\u7248\u672c\u7684\u5feb\u7167\u5df2\u5168\u90e8\u5347\u7ea7</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD \u4e0a\u7684\u5feb\u7167\u5df2\u5168\u90e8\u8f6c\u6362\u5b8c\u6bd5</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>\u5728\u6062\u590d\u65f6\u8fdb\u884c\u5220\u9664\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>\u5728\u6062\u590d\u65f6\uff0c\u800c\u975e\u5bf9\u9f50\u9636\u6bb5\u8fdb\u884c\u5220\u9664</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>PG \u65e5\u5fd7\u786c\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>\u4e3a pg \u65e5\u5fd7\u957f\u5ea6\u6dfb\u52a0\u786c\u9650\u5236</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>\u5df2\u66f4\u65b0 OSD \u6807\u5fd7</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>\u9664\u540d</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>\u52a0\u5165</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>\u6807\u8bb0</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD \u4e22\u5931</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>\u5df2\u6807\u8bb0\u4e22\u5931</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>\u5df2\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>\u9500\u6bc1</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>\u5df2\u9500\u6bc1</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>PG</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>\u8bfb\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>\u5199\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>\u8bfb\u8bf7\u6c42\u6570</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>\u5199\u8bf7\u6c42\u6570</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\u6807\u8bb0 OSD \u4e3a\n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\u6807\u8bb0\u4e3a\n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>\u6700\u5927\u56de\u586b\u91cf</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>\u6700\u5927\u6d3b\u8dc3\u6062\u590d\u8bf7\u6c42\u6570</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>\u6700\u5927\u5355\u6b21\u6062\u590d\u64cd\u4f5c\u6570</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>\u6062\u590d/\u56de\u586b\u64cd\u4f5c\u95f4\u9694\u7761\u7720\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>\u81ea\u5b9a\u4e49</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0 OSD \u6062\u590d\u901f\u5ea6\u4f18\u5148\u7ea7\u201c\n <x id="INTERPOLATION" equiv-text="{{value}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\u5982\u4e0b OSD \u5df2\u7ecf\u542f\u52a8\u4e86\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> \u64cd\u4f5c\uff1a\n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>\u4efb\u52a1</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>\u4e25\u91cd\u7a0b\u5ea6</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>\u5df2\u542f\u52a8</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>\u66f4\u65b0\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>\u5df2\u4f7f\u7528</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>\u7a7a\u95f2</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>\u6b63\u5e38</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>\u8fd0\u884c\u4e2d</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>\u8b66\u62a5</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>\u672a\u77e5</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>\u542f\u7528\u4e2d</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>\u65e0\u6587\u4ef6\u7cfb\u7edf</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>\u5de5\u4f5c</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>\u5f85\u673a</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/a</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>\u5de5\u4f5c\u7684\u5b88\u62a4\u8fdb\u7a0b</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>NFS Ganesha \u670d\u52a1\u7684\u914d\u7f6e\u8fd8\u6ca1\u6709\u5b8c\u6210\u3002</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>\u4f20\u8f93</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS \u7528\u6237</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>CephFS \u6587\u4ef6\u7cfb\u7edf</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>\uff08\u7ee7\u627f\u81ea\u5168\u5c40\u914d\u7f6e\uff09</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>\u7ee7\u627f\u81ea\u5168\u5c40\u914d\u7f6e</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- \u9009\u62e9\u6267\u884c\u54ea\u79cd\u7c7b\u578b\u7684\u7528\u6237 ID \u533f\u540d\u8bbf\u95ee --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>\u6ca1\u6709\u53ef\u7528\u7684\u5b88\u62a4\u8fdb\u7a0b\u3002</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>\u7f13\u5b58\u6a21\u5f0f</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>\u6700\u5c11\u5ef6\u8fdf\u8d76\u51fa\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>\u6700\u5c11\u5ef6\u8fdf\u5237\u56de\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>\u76ee\u6807\u5668\u6700\u5927\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>\u76ee\u6807\u5668\u6700\u5927\u5bf9\u8c61\u6570</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>\u8fd8\u6ca1\u6709\u4efb\u4f55\u5e94\u7528\u6807\u8bb0</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>\u5e94\u7528\u6807\u8bb0\u5230\u4e86\u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>\u4e00\u4e2a\u5b58\u50a8\u6c60\u6700\u591a\u80fd\u6709\u56db\u4e2a\u5e94\u7528\u6807\u8bb0\u3002</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>\u53ef\u7528\u7684\u5b57\u7b26\u4e3a\u201c_a-zA-Z0-9\u201d</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>\u957f\u5ea6\u9650\u5236\u4e3a 128 \u4e2a\u5b57\u7b26</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>\u6dfb\u52a0\u5e94\u7528\u6807\u8bb0\u6216\u6839\u636e\u5176\u8fdb\u884c\u7b5b\u9009</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>\u6dfb\u52a0\u5e94\u7528\u6807\u8bb0</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>\u7ea0\u5220\u7801\u914d\u7f6e</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>\u526f\u672c\u4e2a\u6570</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\u6700\u540e\u4fee\u6539\u65f6\u95f4</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>\u7ea0\u5220\u7801\u914d\u7f6e</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>CRUSH \u89c4\u5219\u96c6</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>\u5199\u5b57\u8282\u6570</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>\u5b58\u50a8\u6876</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u5bf9\u8c61\u7f51\u5173\u5b58\u50a8\u6876\u201c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u5df2\u521b\u5efa\u5bf9\u8c61\u7f51\u5173\u5b58\u50a8\u6876\u201c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>\u5b58\u50a8\u6876</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u5bf9\u8c61\u7f51\u5173\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u5df2\u521b\u5efa\u5bf9\u8c61\u7f51\u5173\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>\u4f5c\u7528\u8303\u56f4</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>\u8bfb\u6743\u9650</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>\u65b0\u5efa</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u65b0\u5efa\u89d2\u8272\u201c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u66f4\u65b0\u89d2\u8272\u201c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>\u7cfb\u7edf\u89d2\u8272</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5df2\u5220\u9664\u89d2\u8272\u201c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u65b0\u5efa\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>\u66f4\u65b0\u7528\u6237</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>\u7ee7\u7eed</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>\u60a8\u88ab\u81ea\u52a8\u767b\u51fa\uff0c\u56e0\u4e3a\u60a8\u7684\u89d2\u8272\u6709\u4e86\u53d8\u52a8\u3002</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u66f4\u65b0\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5df2\u5220\u9664\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u5220\u9664\u7528\u6237\u201c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201d\u5931\u8d25\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>\u60a8\u5f53\u524d\u5728\u7528\u201c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u201d\u7684\u8eab\u4efd\u767b\u5f55\u3002\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target> \u5404\u5bf9\u8c61\u90fd\u88ab\u5206\u5272\u4e3a\u6570\u636e\u5757\uff0c\u5206\u522b\u5b58\u50a8\u4e8e\u4e0d\u540c OSD \u3002</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>\u8ba1\u7b97\u5404\u5bf9\u8c61\u7684\u7f16\u7801\u5757\u3001\u5e76\u5b58\u50a8\u4e8e\u4e0d\u540c OSD \u3002\n\u7f16\u7801\u5757\u7684\u6570\u91cf\u7b49\u540c\u4e8e\u5728\u4e0d\u4e22\u6570\u636e\u7684\u524d\u63d0\u4e0b\u5141\u8bb8\u540c\u65f6\u5931\u6548\u7684 OSD \u6570\u91cf\u3002</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>jerasure \u63d2\u4ef6\u662f\u6700\u901a\u7528\u3001\u6700\u7075\u6d3b\u7684\u63d2\u4ef6\uff0c\n\u4e5f\u662f Ceph \u7ea0\u5220\u7801\u5b58\u50a8\u6c60\u7684\u9ed8\u8ba4\u63d2\u4ef6\u3002</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>reed_sol_van \u6280\u672f\u66f4\u7075\u6d3b\uff1a\u5b83\u8db3\u4ee5\u8bbe\u7f6e k \u548c m \u503c\u3002 \ncauchy_good \u6280\u672f\u66f4\u5feb\uff0c\u4f46\u4f60\u5f97\u8c28\u614e\u5730\u9009\u62e9 packetsize \u503c\u3002\nreed_sol_r6_op \u3001 liberation \u3001 blaum_roth \u3001 liber8tion \u90fd\u662f\u4e0e RAID6 \u7b49\u4ef7\u7684\u6280\u672f\uff0c\n\u5b83\u4eec\u53ea\u80fd\u914d\u7f6e\u4e3a m=2 \u3002</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target> \u4ee5 bytes \u5927\u5c0f\u7684\u5305\u4e3a\u5355\u4f4d\u8fdb\u884c\u7f16\u7801\u3002\n\u786e\u5b9a\u5408\u9002\u7684\u5305\u5c3a\u5bf8\u5f88\u96be\uff0c \njerasure \u6587\u6863\u5bf9\u6b64\u6709\u5f88\u8be6\u7ec6\u7684\u63cf\u8ff0\u3002</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>\u7528 jerasure \u63d2\u4ef6\u65f6\uff0c\u7ea0\u5220\u7801\u7f16\u7801\u7684\u5bf9\u8c61\u5b58\u50a8\u5728\u591a\u4e2a OSD \u4e0a\uff0c\n\u4e22\u5931\u4e00\u4e2a OSD \u7684\u6062\u590d\u8fc7\u7a0b\u9700\u8bfb\u53d6\u6240\u6709\u5176\u4ed6\u7684 OSD \u3002\n\u6bd4\u5982 jerasure \u7684\u914d\u7f6e\u4e3a k=8 \u4e14 m=4 \uff0c\u4e22\u5931\u4e00\u4e2a OSD \u540e\u9700\u8bfb\u53d6\u5176\u4ed6 11 \u4e2a OSD \u624d\u80fd\u6062\u590d\u3002\n\nlrc \u7ea0\u5220\u7801\u63d2\u4ef6\u521b\u5efa\u7684\u662f\u5c40\u90e8\u6821\u9a8c\u5757\uff0c\u8fd9\u6837\u53ea\u9700\u8f83\u5c11\u7684 OSD \u5373\u53ef\u6062\u590d\u3002\n\u6bd4\u5982 lrc \u7684\u914d\u7f6e\u4e3a k=8 \u3001 m=4 \u4e14 l=4 \uff0c\u5b83\u5c06\u4e3a\u6bcf\u56db\u4e2a OSD \u521b\u5efa\u989d\u5916\u7684\u6821\u9a8c\u5757\uff0c\n\u5f53\u4e00\u4e2a OSD \u4e22\u5931\u65f6\uff0c\u5b83\u53ea\u9700\u56db\u4e2a OSD \u5373\u53ef\u6062\u590d\uff0c\u800c\u4e0d\u9700\u8981\u5341\u4e00\u4e2a\u3002</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>\u628a\u7f16\u7801\u5757\u548c\u6570\u636e\u5757\u5206\u7ec4\u4e3a\u5927\u5c0f\u4e3a locality \u7684\u96c6\u5408\u3002\n\u6bd4\u5982\uff0c k=4 \u4e14 m=2 \u65f6\uff0c\u82e5\u8bbe\u7f6e locality=3 \uff0c\u5c06\u4f1a\u5206\u7ec4\u4e3a\u5927\u5c0f\u4e3a\u4e09\u7684\u4e24\u7ec4\uff0c\n\u8fd9\u6837\u5404\u7ec4\u90fd\u80fd\u81ea\u884c\u6062\u590d\uff0c\u65e0\u9700\u4ece\u53e6\u4e00\u7ec4\u8bfb\u6570\u636e\u5757\u3002</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>\u7531 l \u5b9a\u4e49\u7684\u5757\u96c6\u5408\u5c06\u6309\u54ea\u79cd crush \u6876\u7c7b\u578b\u5b58\u50a8\u3002\n\u6bd4\u5982\uff0c\u82e5\u8bbe\u7f6e\u4e3a rack \uff0c\u5927\u5c0f\u4e3a l \u5757\u7684\u5404\u7ec4\u5c06\u88ab\u5b58\u5165\u4e0d\u540c\u7684\u673a\u67b6\uff0c\n\u6b64\u503c\u4f1a\u88ab\u7528\u4e8e\u521b\u5efa\u7c7b\u4f3c step choose rack \u7684\u89c4\u5219\u96c6\u3002\n\u5982\u679c\u6ca1\u8bbe\u7f6e\uff0c\u5c31\u4e0d\u4f1a\u8fd9\u6837\u5206\u7ec4\u3002</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>isa \u63d2\u4ef6\u5c01\u88c5\u4e86 ISA \u5e93\u3002\u5b83\u53ea\u80fd\u8fd0\u884c\u5728 Intel \u5904\u7406\u5668\u4e0a\u3002</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>ISA \u63d2\u4ef6\u5305\u542b\u4e24\u79cd Reed Solomon \u7f16\u7801\u5f62\u5f0f\u3002\n\u8bbe\u7f6e\u4e3a reed_sol_van \u8868\u793a\u7528 Vandermonde \u7b97\u6cd5\uff0c\u8bbe\u7f6e\u4e3a cauchy \u8868\u793a\u7528 Cauchy \u7b97\u6cd5\u3002</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>shec \u63d2\u4ef6\u5c01\u88c5\u4e86 multiple SHEC \u5e93\u3002\n\u4e0e Reed Solomon \u7f16\u7801\u76f8\u6bd4\uff0c\u5b83\u80fd\u4f7f Ceph \u66f4\u9ad8\u6548\u5730\u6062\u590d\u6570\u636e\u3002</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target> \u5947\u5076\u6821\u9a8c\u5757\u6570\u91cf\uff0c\u5b83\u4eec\u5728\u5404\u81ea\u7684\u8ba1\u7b97\u8303\u56f4\u5185\u5305\u542b\u4e86\u5404\u6570\u636e\u5757\u3002\n\u6b64\u6570\u503c\u88ab\u7528\u4f5c\u6301\u4e45\u6027\u4f30\u503c\u3002\n\u4f8b\u5982\uff0c\u5047\u8bbe c=2 \uff0c\u5c31\u662f\u8bf4\u4e0d\u4e1f\u6570\u636e\u7684\u60c5\u51b5\u4e0b\u53ef\u635f\u5931 2 \u4e2a OSD \u3002</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>\u89c4\u5219\u96c6\u7b2c\u4e00\u6b65\u6240\u6307\u5411\u7684 CRUSH \u6876\u4e4b\u540d\uff0c\n\u5982 step take default \u3002</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>\u786e\u4fdd\u4e24\u4e2a\u7f16\u7801\u5757\u4e0d\u4f1a\u5b58\u5728\u4e8e\u540c\u4e00\u6545\u969c\u57df\u7684\u6876\u91cc\u9762\u3002\n\u6bd4\u5982\uff0c\u5047\u8bbe\u6545\u969c\u57df\u662f host \uff0c\u5c31\u4e0d\u4f1a\u6709\u4e24\u4e2a\u7f16\u7801\u5757\u5b58\u50a8\u5230\u540c\u4e00\u4e3b\u673a\uff1b\n\u6b64\u503c\u7528\u4e8e\u5728\u89c4\u5219\u96c6\u4e2d\u521b\u5efa\u7c7b\u4f3c step chooseleaf host \u7684\u6b65\u9aa4\u3002</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>\u4f7f\u7528 CRUSH \u7d22\u5f15\u4e2d\u7684 crush \u8bbe\u5907\u7c7b\u540d\uff0c\n\u5c06\u5f52\u7f6e\u9650\u5236\u4e8e\u7279\u5b9a\u7c7b\u7684\u8bbe\u5907\uff08\u4f8b\u5982\uff0cssd \u6216 hdd\uff09\u3002</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>\u8bbe\u7f6e\u7ea0\u5220\u7801\u63d2\u4ef6\u6240\u5728\u76ee\u5f55\u3002</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>\u5141\u8bb8\u6240\u6709\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>\u53ea\u5141\u8bb8\u4e0d\u4fee\u6539\u670d\u52a1\u5668\u7aef\u6570\u636e\u7684\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>\u7981\u6b62\u8bfb\u5199\uff0c\u4f46\u662f\u5141\u8bb8\u5176\u4ed6\u7684\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>\u7981\u6b62\u8bfb\u3001\u5199\u4ee5\u53ca\u4efb\u4f55\u53ef\u80fd\u4fee\u6539\u6587\u4ef6\u5185\u5bb9\u7684\u64cd\u4f5c</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>\u5b8c\u5168\u7981\u6b62\u8bbf\u95ee</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- \u9009\u62e9\u4f18\u5148\u7ea7 --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>\u4f4e</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>\u9ad8</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\u8fc7\u53bb 5 \u5206\u949f</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\u8fc7\u53bb 15 \u5206\u949f</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\u8fc7\u53bb 30 \u5206\u949f</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\u8fc7\u53bb 1 \u5c0f\u65f6\uff08\u9ed8\u8ba4\uff09</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\u8fc7\u53bb 3 \u5c0f\u65f6</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\u8fc7\u53bb 6 \u5c0f\u65f6</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\u8fc7\u53bb 12 \u5c0f\u65f6</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\u8fc7\u53bb 24 \u5c0f\u65f6</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>\u6628\u5929</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>\u4eca\u5929</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>\u4eca\u5929\u5230\u73b0\u5728\u4e3a\u6b62</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>\u524d\u5929</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>\u8fc7\u53bb 2 \u5929</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>\u4e0a\u5468\u7684\u4eca\u5929</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>\u4e0a\u4e2a\u661f\u671f</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>\u672c\u5468</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>\u672c\u5468\u4ee5\u6765</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>\u8fc7\u53bb 7 \u5929</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>\u4e0a\u4e2a\u6708</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>\u5f53\u6708</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>\u672c\u6708\u4ee5\u6765</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>\u8fc7\u53bb 30 \u5929</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>\u8fc7\u53bb 90 \u5929</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>\u8fc7\u53bb 6 \u4e2a\u6708</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>\u8fc7\u53bb 1 \u5e74</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>\u53bb\u5e74</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>\u4eca\u5e74</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>\u4eca\u5e74\u4ee5\u6765</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>\u8fc7\u53bb 2 \u5e74</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>\u8fc7\u53bb 5 \u5e74</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>\u4fe1\u606f</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>\u65e0\u9009\u4e2d\u9879\u76ee\u3002</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>\u53d6\u6d88\u9009\u62e9</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>\u8fbe\u5230\u9009\u62e9\u9879\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>\u8fc7\u6ee4\u6807\u7b7e</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>\u6dfb\u52a0 badge</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>\u65e0\u53ef\u9009\u9879\u76ee\u3002</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>\u6dfb\u52a0</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>\u590d\u5236</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>\u6df1\u5c42\u6d17\u5237</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>\u9500\u6bc1</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>\u5c55\u5f00</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>\u6807\u8bb0\u4e3a\u505c\u7528</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>\u6807\u8bb0\u4e3a\u52a0\u5165</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>\u6807\u8bb0\u4e3a\u4e22\u5931</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>\u6807\u8bb0\u4e3a\u5df2\u9664\u540d</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>\u4fdd\u62a4</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>\u91cd\u547d\u540d</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>\u6062\u590d</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>\u79fb\u81f3\u56de\u6536\u7ad9</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>\u89e3\u9664\u4fdd\u62a4</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>\u5220\u9664\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>\u514b\u9686\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>\u590d\u5236\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>\u662f</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>\u5426</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>\u670d\u52a1\u8d28\u91cf (QoS)</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2 IO \u5b57\u8282\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2 IO \u64cd\u4f5c\u6b21\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>\u8bfb BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5185\u8bfb\u53d6\u7684\u5b57\u8282\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>\u8bfb IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u8bfb\u64cd\u4f5c\u6b21\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>\u5199 BPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5185\u5199\u5165\u7684\u5b57\u8282\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>\u5199 IOPS \u4e0a\u9650</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>\u6307\u5b9a\u7684\u6bcf\u79d2\u5199\u64cd\u4f5c\u6b21\u6570\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>\u6307\u5b9a\u7684 IO \u5b57\u8282\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>\u6307\u5b9a\u7684 IO \u64cd\u4f5c\u6b21\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>\u8bfb BPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>\u6307\u5b9a\u7684\u8bfb\u53d6\u7684\u5b57\u8282\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>\u8bfb IOPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>\u6307\u5b9a\u7684\u8bfb\u64cd\u4f5c\u6b21\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>\u5199 BPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>\u6307\u5b9a\u7684\u5199\u5165\u7684\u5b57\u8282\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>\u5199 IOPS \u7a81\u53d1</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>\u6307\u5b9a\u7684\u5199\u64cd\u4f5c\u6b21\u6570\u7a81\u53d1\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\u5931\u8d25\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>\u6b63\u5728\u6267\u884c</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>\u6267\u884c</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>\u6267\u884c\u5b8c\u6bd5</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>\u672a\u77e5\u4efb\u52a1</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>\u6b63\u5728\u521b\u5efa</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>\u521b\u5efa</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>\u6b63\u5728\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>\u6b63\u5728\u5220\u9664</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>\u5220\u9664</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \u5feb\u7167\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u5b58\u50a8\u6c60\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\u7684\u955c\u50cf\u6a21\u5f0f\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u5b58\u50a8\u6c60\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\u7684\u955c\u50cf\u540c\u4f34\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>\u8be5\u540d\u79f0\u5df2\u88ab\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>\u8be5\u540d\u79f0\u5df2\u88ab\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>\u8be5\u540d\u79f0\u5df2\u88ab\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u5305\u542b\u6709\u5feb\u7167\u3002\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>\u6b63\u5728\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>\u514b\u9686</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u7684\u5feb\u7167\u5fc5\u987b\u5904\u4e8e\u53d7\u4fdd\u62a4\u72b6\u6001\u3002\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>\u6b63\u5728\u590d\u5236</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>\u590d\u5236</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>\u6b63\u5728\u5c55\u5f00</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>\u5c55\u5f00</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>\u5c55\u5f00\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>\u8be5\u540d\u79f0\u5df2\u88ab\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>\u65e0\u6cd5\u53bb\u6389\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\u7684\u4fdd\u62a4\u72b6\u6001\uff0c\u56e0\u4e3a\u5b83\u6709\u5b50\u6620\u50cf\u3002\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>\u65e0\u6cd5\u5220\u9664\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\uff0c\u56e0\u4e3a\u5b83\u5904\u4e8e\u53d7\u4fdd\u62a4\u72b6\u6001\u3002\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>\u6b63\u5728\u56de\u6eda</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>\u56de\u6eda</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>\u56de\u6eda\u5b8c\u6210</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>\u6b63\u5728\u628a</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>\u628a</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>\u5df2\u7ecf\u628a</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>\u6620\u50cf\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\u79fb\u81f3\u56de\u6536\u7ad9\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>\u65e0\u6cd5\u627e\u5230\u6620\u50cf\u3002</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>\u6b63\u5728\u628a</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>\u628a</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>\u5df2\u7ecf\u628a</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>\u6620\u50cf\u4ece\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\u6062\u590d\u5230\u201c\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>\u6620\u50cf\u540d\u79f0\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\u5df2\u88ab\u4f7f\u7528\u3002\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u6620\u50cf\u201c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>\u6b63\u5728\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>\u5df2\u6e05\u9664</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>\u6240\u6709\u5b58\u50a8\u6c60</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{message}}"/>\u91cc\u7684\u6620\u50cf\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>\u56e0\u4e3a\u5305\u542b\u540c\u4f34\u96c6\u7fa4\uff0c\u65e0\u6cd5\u7981\u7528\u955c\u50cf\u529f\u80fd</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>\u5b58\u50a8\u6c60\u201c\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>\u7ea0\u5220\u7801\u914d\u7f6e\u201c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>\u76ee\u6807\u5668\u201c\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\u201d\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},fELs:function(t,e,n){"use strict";var a=n("RDha");function r(t,e){return a.where(t,function(t){return t.position===e})}function i(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var a=e?n:t,r=e?t:n;return a.weight===r.weight?a._tmpIndex_-r._tmpIndex_:a.weight-r.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.exports={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var a,r=["fullWidth","position","weight"],i=r.length,s=0;s<i;++s)n.hasOwnProperty(a=r[s])&&(e[a]=n[a])},update:function(t,e,n){if(t){var s=a.options.toPadding((t.options.layout||{}).padding),o=s.left,u=s.right,c=s.top,l=s.bottom,d=r(t.boxes,"left"),f=r(t.boxes,"right"),p=r(t.boxes,"top"),h=r(t.boxes,"bottom"),g=r(t.boxes,"chartArea");i(d,!0),i(f,!1),i(p,!0),i(h,!1);var b=e-o-u,m=n-c-l,y=(e-b/2)/(d.length+f.length),v=(n-m/2)/(p.length+h.length),_=b,x=m,T=[];a.each(d.concat(f,p,h),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?b:_,v),x-=e.height):(e=t.update(y,x),_-=e.width),T.push({horizontal:n,minSize:e,box:t})});var w=0,S=0,O=0,I=0;a.each(p.concat(h),function(t){if(t.getPadding){var e=t.getPadding();w=Math.max(w,e.left),S=Math.max(S,e.right)}}),a.each(d.concat(f),function(t){if(t.getPadding){var e=t.getPadding();O=Math.max(O,e.top),I=Math.max(I,e.bottom)}});var C=o,k=u,N=c,R=l;a.each(d.concat(f),q),a.each(d,function(t){C+=t.width}),a.each(f,function(t){k+=t.width}),a.each(p.concat(h),q),a.each(p,function(t){N+=t.height}),a.each(h,function(t){R+=t.height}),a.each(d.concat(f),function(t){var e=a.findNextWhere(T,function(e){return e.box===t});e&&t.update(e.minSize.width,x,{left:0,right:0,top:N,bottom:R})}),C=o,k=u,N=c,R=l,a.each(d,function(t){C+=t.width}),a.each(f,function(t){k+=t.width}),a.each(p,function(t){N+=t.height}),a.each(h,function(t){R+=t.height});var A=Math.max(w-C,0);C+=A,k+=Math.max(S-k,0);var D=Math.max(O-N,0);N+=D,R+=Math.max(I-R,0);var E=n-N-R,L=e-C-k;L===_&&E===x||(a.each(d,function(t){t.height=E}),a.each(f,function(t){t.height=E}),a.each(p,function(t){t.fullWidth||(t.width=L)}),a.each(h,function(t){t.fullWidth||(t.width=L)}),x=E,_=L);var P=o+A,M=c+D;a.each(d.concat(p),j),P+=_,M+=x,a.each(f,j),a.each(h,j),t.chartArea={left:C,top:N,right:C+_,bottom:N+x},a.each(g,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(_,x)})}function q(t){var e=a.findNextWhere(T,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(C,w),right:Math.max(k,S),top:0,bottom:0};t.update(t.fullWidth?b:_,m/2,n)}else t.update(e.minSize.width,x)}function j(t){t.isHorizontal()?(t.left=t.fullWidth?o:C,t.right=t.fullWidth?e-u:C+_,t.top=M,t.bottom=M+t.height,M=t.bottom):(t.left=P,t.right=P+t.width,t.top=N,t.bottom=N+x,P=t.right)}}}},fhFe:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG");e.DataTablePagerComponent=function(){function t(){this.change=new i.EventEmitter,this._count=0,this._page=1,this._size=0}return Object.defineProperty(t.prototype,"size",{get:function(){return this._size},set:function(t){this._size=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"count",{get:function(){return this._count},set:function(t){this._count=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"page",{get:function(){return this._page},set:function(t){this._page=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"totalPages",{get:function(){var t=this.size<1?1:Math.ceil(this.count/this.size);return Math.max(t||0,1)},enumerable:!0,configurable:!0}),t.prototype.canPrevious=function(){return this.page>1},t.prototype.canNext=function(){return this.page<this.totalPages},t.prototype.prevPage=function(){this.selectPage(this.page-1)},t.prototype.nextPage=function(){this.selectPage(this.page+1)},t.prototype.selectPage=function(t){t>0&&t<=this.totalPages&&t!==this.page&&(this.page=t,this.change.emit({page:t}))},t.prototype.calcPages=function(t){var e=[],n=1,a=this.totalPages;t=t||this.page,5<this.totalPages&&(n=t-Math.floor(2.5),a=t+Math.floor(2.5),n<1?(n=1,a=Math.min(n+5-1,this.totalPages)):a>this.totalPages&&(n=Math.max(this.totalPages-5+1,1),a=this.totalPages));for(var r=n;r<=a;r++)e.push({number:r,text:r});return e},a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"size",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"count",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"page",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"change",void 0),a([i.Component({selector:"datatable-pager",template:'\n <ul class="pager">\n <li [class.disabled]="!canPrevious()">\n <a\n role="button"\n aria-label="go to first page"\n href="javascript:void(0)"\n (click)="selectPage(1)">\n <i class="{{pagerPreviousIcon}}"></i>\n </a>\n </li>\n <li [class.disabled]="!canPrevious()">\n <a\n role="button"\n aria-label="go to previous page"\n href="javascript:void(0)"\n (click)="prevPage()">\n <i class="{{pagerLeftArrowIcon}}"></i>\n </a>\n </li>\n <li\n role="button"\n [attr.aria-label]="\'page \' + pg.number"\n class="pages"\n *ngFor="let pg of pages"\n [class.active]="pg.number === page">\n <a\n href="javascript:void(0)"\n (click)="selectPage(pg.number)">\n {{pg.text}}\n </a>\n </li>\n <li [class.disabled]="!canNext()">\n <a\n role="button"\n aria-label="go to next page"\n href="javascript:void(0)"\n (click)="nextPage()">\n <i class="{{pagerRightArrowIcon}}"></i>\n </a>\n </li>\n <li [class.disabled]="!canNext()">\n <a\n role="button"\n aria-label="go to last page"\n href="javascript:void(0)"\n (click)="selectPage(totalPages)">\n <i class="{{pagerNextIcon}}"></i>\n </a>\n </li>\n </ul>\n ',host:{class:"datatable-pager"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},fktO:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("Ahxa")),a(n("fhFe")),a(n("lUjN")),a(n("vxfy"))},fzPg:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("yo",{months:"S\u1eb9\u0301r\u1eb9\u0301_E\u0300re\u0300le\u0300_\u1eb8r\u1eb9\u0300na\u0300_I\u0300gbe\u0301_E\u0300bibi_O\u0300ku\u0300du_Ag\u1eb9mo_O\u0300gu\u0301n_Owewe_\u1ecc\u0300wa\u0300ra\u0300_Be\u0301lu\u0301_\u1ecc\u0300p\u1eb9\u0300\u0300".split("_"),monthsShort:"S\u1eb9\u0301r_E\u0300rl_\u1eb8rn_I\u0300gb_E\u0300bi_O\u0300ku\u0300_Ag\u1eb9_O\u0300gu\u0301_Owe_\u1ecc\u0300wa\u0300_Be\u0301l_\u1ecc\u0300p\u1eb9\u0300\u0300".split("_"),weekdays:"A\u0300i\u0300ku\u0301_Aje\u0301_I\u0300s\u1eb9\u0301gun_\u1eccj\u1ecd\u0301ru\u0301_\u1eccj\u1ecd\u0301b\u1ecd_\u1eb8ti\u0300_A\u0300ba\u0301m\u1eb9\u0301ta".split("_"),weekdaysShort:"A\u0300i\u0300k_Aje\u0301_I\u0300s\u1eb9\u0301_\u1eccjr_\u1eccjb_\u1eb8ti\u0300_A\u0300ba\u0301".split("_"),weekdaysMin:"A\u0300i\u0300_Aj_I\u0300s_\u1eccr_\u1eccb_\u1eb8t_A\u0300b".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[O\u0300ni\u0300 ni] LT",nextDay:"[\u1ecc\u0300la ni] LT",nextWeek:"dddd [\u1eccs\u1eb9\u0300 to\u0301n'b\u1ecd] [ni] LT",lastDay:"[A\u0300na ni] LT",lastWeek:"dddd [\u1eccs\u1eb9\u0300 to\u0301l\u1ecd\u0301] [ni] LT",sameElse:"L"},relativeTime:{future:"ni\u0301 %s",past:"%s k\u1ecdja\u0301",s:"i\u0300s\u1eb9ju\u0301 aaya\u0301 die",ss:"aaya\u0301 %d",m:"i\u0300s\u1eb9ju\u0301 kan",mm:"i\u0300s\u1eb9ju\u0301 %d",h:"wa\u0301kati kan",hh:"wa\u0301kati %d",d:"\u1ecdj\u1ecd\u0301 kan",dd:"\u1ecdj\u1ecd\u0301 %d",M:"osu\u0300 kan",MM:"osu\u0300 %d",y:"\u1ecddu\u0301n kan",yy:"\u1ecddu\u0301n %d"},dayOfMonthOrdinalParse:/\u1ecdj\u1ecd\u0301\s\d{1,2}/,ordinal:"\u1ecdj\u1ecd\u0301 %d",week:{dow:1,doy:4}})}()},g8vO:function(t,e,n){"use strict";var a=n("RDha");t.exports={formatters:{values:function(t){return a.isArray(t)?t:""+t},linear:function(t,e,n){var r=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(r)>1&&t!==Math.floor(t)&&(r=t-Math.floor(t));var i=a.log10(Math.abs(r)),s="";if(0!==t)if(Math.max(Math.abs(n[0]),Math.abs(n[n.length-1]))<1e-4){var o=a.log10(Math.abs(t));s=t.toExponential(Math.floor(o)-Math.floor(i))}else{var u=-1*Math.floor(i);u=Math.max(Math.min(u,20),0),s=t.toFixed(u)}else s="0";return s},logarithmic:function(t,e,n){var r=t/Math.pow(10,Math.floor(a.log10(t)));return 0===t?"0":1===r||2===r||5===r||0===e||e===n.length-1?t.toExponential():""}}}},gI3B:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("6blF"),r=n("T1DM"),i=n("/21U"),s=n("nkY7");function o(t,e,n){void 0===t&&(t=0);var o=-1;return Object(i.a)(e)?o=Number(e)<1?1:Number(e):Object(s.a)(e)&&(n=e),Object(s.a)(n)||(n=r.a),new a.a(function(e){var a=Object(i.a)(t)?t:+t-n.now();return n.schedule(u,a,{index:0,period:o,subscriber:e})})}function u(t){var e=t.index,n=t.period,a=t.subscriber;if(a.next(e),!a.closed){if(-1===n)return a.complete();t.index=e+1,this.schedule(t,n)}}},gIcY:function(t,e,n){"use strict";n.d(e,"B",function(){return It}),n.d(e,"D",function(){return Ot}),n.d(e,"C",function(){return S}),n.d(e,"E",function(){return C}),n.d(e,"F",function(){return mt}),n.d(e,"G",function(){return F}),n.d(e,"c",function(){return v}),n.d(e,"d",function(){return l}),n.d(e,"p",function(){return y}),n.d(e,"b",function(){return _}),n.d(e,"e",function(){return x}),n.d(e,"q",function(){return I}),n.d(e,"r",function(){return et}),n.d(e,"s",function(){return nt}),n.d(e,"t",function(){return dt}),n.d(e,"u",function(){return bt}),n.d(e,"w",function(){return k}),n.d(e,"j",function(){return Tt}),n.d(e,"l",function(){return yt}),n.d(e,"g",function(){return _t}),n.d(e,"m",function(){return vt}),n.d(e,"v",function(){return M}),n.d(e,"z",function(){return P}),n.d(e,"y",function(){return wt}),n.d(e,"h",function(){return St}),n.d(e,"a",function(){return st}),n.d(e,"f",function(){return ct}),n.d(e,"i",function(){return ot}),n.d(e,"k",function(){return ut}),n.d(e,"o",function(){return f}),n.d(e,"A",function(){return h}),n.d(e,"n",function(){return Ct}),n.d(e,"x",function(){return kt});var a=n("mrSG"),r=n("CcnG"),i=n("VNr4"),s=n("0/uQ"),o=n("67Y/"),u=n("ZYjt"),c=function(){function t(){}return Object.defineProperty(t.prototype,"value",{get:function(){return this.control?this.control.value:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"valid",{get:function(){return this.control?this.control.valid:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"invalid",{get:function(){return this.control?this.control.invalid:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"pending",{get:function(){return this.control?this.control.pending:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"disabled",{get:function(){return this.control?this.control.disabled:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"enabled",{get:function(){return this.control?this.control.enabled:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"errors",{get:function(){return this.control?this.control.errors:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"pristine",{get:function(){return this.control?this.control.pristine:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"dirty",{get:function(){return this.control?this.control.dirty:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"touched",{get:function(){return this.control?this.control.touched:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"status",{get:function(){return this.control?this.control.status:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"untouched",{get:function(){return this.control?this.control.untouched:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"statusChanges",{get:function(){return this.control?this.control.statusChanges:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"valueChanges",{get:function(){return this.control?this.control.valueChanges:null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"path",{get:function(){return null},enumerable:!0,configurable:!0}),t.prototype.reset=function(t){void 0===t&&(t=void 0),this.control&&this.control.reset(t)},t.prototype.hasError=function(t,e){return!!this.control&&this.control.hasError(t,e)},t.prototype.getError=function(t,e){return this.control?this.control.getError(t,e):null},t}(),l=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"formDirective",{get:function(){return null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"path",{get:function(){return null},enumerable:!0,configurable:!0}),e}(c);function d(t){return null==t||0===t.length}var f=new r.InjectionToken("NgValidators"),p=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,h=function(){function t(){}return t.min=function(t){return function(e){if(d(e.value)||d(t))return null;var n=parseFloat(e.value);return!isNaN(n)&&n<t?{min:{min:t,actual:e.value}}:null}},t.max=function(t){return function(e){if(d(e.value)||d(t))return null;var n=parseFloat(e.value);return!isNaN(n)&&n>t?{max:{max:t,actual:e.value}}:null}},t.required=function(t){return d(t.value)?{required:!0}:null},t.requiredTrue=function(t){return!0===t.value?null:{required:!0}},t.email=function(t){return d(t.value)?null:p.test(t.value)?null:{email:!0}},t.minLength=function(t){return function(e){if(d(e.value))return null;var n=e.value?e.value.length:0;return n<t?{minlength:{requiredLength:t,actualLength:n}}:null}},t.maxLength=function(t){return function(e){var n=e.value?e.value.length:0;return n>t?{maxlength:{requiredLength:t,actualLength:n}}:null}},t.pattern=function(e){return e?("string"==typeof e?(a="","^"!==e.charAt(0)&&(a+="^"),a+=e,"$"!==e.charAt(e.length-1)&&(a+="$"),n=new RegExp(a)):(a=e.toString(),n=e),function(t){if(d(t.value))return null;var e=t.value;return n.test(e)?null:{pattern:{requiredPattern:a,actualValue:e}}}):t.nullValidator;var n,a},t.nullValidator=function(t){return null},t.compose=function(t){if(!t)return null;var e=t.filter(g);return 0==e.length?null:function(t){return m(function(t,n){return e.map(function(e){return e(t)})}(t))}},t.composeAsync=function(t){if(!t)return null;var e=t.filter(g);return 0==e.length?null:function(t){var n=function(t,n){return e.map(function(e){return e(t)})}(t).map(b);return Object(i.a)(n).pipe(Object(o.a)(m))}},t}();function g(t){return null!=t}function b(t){var e=Object(r["\u0275isPromise"])(t)?Object(s.a)(t):t;if(!Object(r["\u0275isObservable"])(e))throw new Error("Expected validator to return Promise or Observable.");return e}function m(t){var e=t.reduce(function(t,e){return null!=e?Object(a.__assign)({},t,e):t},{});return 0===Object.keys(e).length?null:e}var y=new r.InjectionToken("NgValueAccessor"),v=function(){function t(t,e){this._renderer=t,this._elementRef=e,this.onChange=function(t){},this.onTouched=function(){}}return t.prototype.writeValue=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"checked",t)},t.prototype.registerOnChange=function(t){this.onChange=t},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t}(),_=new r.InjectionToken("CompositionEventMode"),x=function(){function t(t,e,n){var a;this._renderer=t,this._elementRef=e,this._compositionMode=n,this.onChange=function(t){},this.onTouched=function(){},this._composing=!1,null==this._compositionMode&&(this._compositionMode=(a=Object(u["\u0275getDOM"])()?Object(u["\u0275getDOM"])().getUserAgent():"",!/android (\d+)/.test(a.toLowerCase())))}return t.prototype.writeValue=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"value",null==t?"":t)},t.prototype.registerOnChange=function(t){this.onChange=t},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t.prototype._handleInput=function(t){(!this._compositionMode||this._compositionMode&&!this._composing)&&this.onChange(t)},t.prototype._compositionStart=function(){this._composing=!0},t.prototype._compositionEnd=function(t){this._composing=!1,this._compositionMode&&this.onChange(t)},t}();function T(t){return t.validate?function(e){return t.validate(e)}:t}function w(t){return t.validate?function(e){return t.validate(e)}:t}var S=function(){function t(t,e){this._renderer=t,this._elementRef=e,this.onChange=function(t){},this.onTouched=function(){}}return t.prototype.writeValue=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"value",null==t?"":t)},t.prototype.registerOnChange=function(t){this.onChange=function(e){t(""==e?null:parseFloat(e))}},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t}();function O(){throw new Error("unimplemented")}var I=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e._parent=null,e.name=null,e.valueAccessor=null,e._rawValidators=[],e._rawAsyncValidators=[],e}return Object(a.__extends)(e,t),Object.defineProperty(e.prototype,"validator",{get:function(){return O()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"asyncValidator",{get:function(){return O()},enumerable:!0,configurable:!0}),e}(c),C=function(){function t(){this._accessors=[]}return t.prototype.add=function(t,e){this._accessors.push([t,e])},t.prototype.remove=function(t){for(var e=this._accessors.length-1;e>=0;--e)if(this._accessors[e][1]===t)return void this._accessors.splice(e,1)},t.prototype.select=function(t){var e=this;this._accessors.forEach(function(n){e._isSameGroup(n,t)&&n[1]!==t&&n[1].fireUncheck(t.value)})},t.prototype._isSameGroup=function(t,e){return!!t[0].control&&t[0]._parent===e._control._parent&&t[1].name===e.name},t}(),k=function(){function t(t,e,n,a){this._renderer=t,this._elementRef=e,this._registry=n,this._injector=a,this.onChange=function(){},this.onTouched=function(){}}return t.prototype.ngOnInit=function(){this._control=this._injector.get(I),this._checkName(),this._registry.add(this._control,this)},t.prototype.ngOnDestroy=function(){this._registry.remove(this)},t.prototype.writeValue=function(t){this._state=t===this.value,this._renderer.setProperty(this._elementRef.nativeElement,"checked",this._state)},t.prototype.registerOnChange=function(t){var e=this;this._fn=t,this.onChange=function(){t(e.value),e._registry.select(e)}},t.prototype.fireUncheck=function(t){this.writeValue(t)},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t.prototype._checkName=function(){this.name&&this.formControlName&&this.name!==this.formControlName&&this._throwNameError(),!this.name&&this.formControlName&&(this.name=this.formControlName)},t.prototype._throwNameError=function(){throw new Error('\n If you define both a name and a formControlName attribute on your radio button, their values\n must match. Ex: <input type="radio" formControlName="food" name="food">\n ')},t}(),N=function(){function t(t,e){this._renderer=t,this._elementRef=e,this.onChange=function(t){},this.onTouched=function(){}}return t.prototype.writeValue=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"value",parseFloat(t))},t.prototype.registerOnChange=function(t){this.onChange=function(e){t(""==e?null:parseFloat(e))}},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t}(),R='\n <div [formGroup]="myGroup">\n <input formControlName="firstName">\n </div>\n\n In your class:\n\n this.myGroup = new FormGroup({\n firstName: new FormControl()\n });',A='\n <div [formGroup]="myGroup">\n <div formGroupName="person">\n <input formControlName="firstName">\n </div>\n </div>\n\n In your class:\n\n this.myGroup = new FormGroup({\n person: new FormGroup({ firstName: new FormControl() })\n });',D='\n <form>\n <div ngModelGroup="person">\n <input [(ngModel)]="person.name" name="firstName">\n </div>\n </form>',E=function(){function t(){}return t.controlParentException=function(){throw new Error("formControlName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n "+R)},t.ngModelGroupException=function(){throw new Error('formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents\n that also have a "form" prefix: formGroupName, formArrayName, or formGroup.\n\n Option 1: Update the parent to be formGroupName (reactive form strategy)\n\n '+A+"\n\n Option 2: Use ngModel instead of formControlName (template-driven strategy)\n\n "+D)},t.missingFormException=function(){throw new Error("formGroup expects a FormGroup instance. Please pass one in.\n\n Example:\n\n "+R)},t.groupParentException=function(){throw new Error("formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n "+A)},t.arrayParentException=function(){throw new Error('formArrayName must be used with a parent formGroup directive. You\'ll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n \n <div [formGroup]="myGroup">\n <div formArrayName="cities">\n <div *ngFor="let city of cityArray.controls; index as i">\n <input [formControlName]="i">\n </div>\n </div>\n </div>\n\n In your class:\n\n this.cityArray = new FormArray([new FormControl(\'SF\')]);\n this.myGroup = new FormGroup({\n cities: this.cityArray\n });')},t.disabledAttrWarning=function(){console.warn("\n It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true\n when you set up this control in your component class, the disabled attribute will actually be set in the DOM for\n you. We recommend using this approach to avoid 'changed after checked' errors.\n \n Example: \n form = new FormGroup({\n first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),\n last: new FormControl('Drew', Validators.required)\n });\n ")},t.ngModelWarning=function(t){console.warn("\n It looks like you're using ngModel on the same form field as "+t+". \n Support for using the ngModel input property and ngModelChange event with \n reactive form directives has been deprecated in Angular v6 and will be removed \n in Angular v7.\n \n For more information on this, see our API docs here:\n https://angular.io/api/forms/"+("formControl"===t?"FormControlDirective":"FormControlName")+"#use-with-ngmodel\n ")},t}();function L(t,e){return null==t?""+e:(e&&"object"==typeof e&&(e="Object"),(t+": "+e).slice(0,50))}var P=function(){function t(t,e){this._renderer=t,this._elementRef=e,this._optionMap=new Map,this._idCounter=0,this.onChange=function(t){},this.onTouched=function(){},this._compareWith=r["\u0275looseIdentical"]}return Object.defineProperty(t.prototype,"compareWith",{set:function(t){if("function"!=typeof t)throw new Error("compareWith must be a function, but received "+JSON.stringify(t));this._compareWith=t},enumerable:!0,configurable:!0}),t.prototype.writeValue=function(t){this.value=t;var e=this._getOptionId(t);null==e&&this._renderer.setProperty(this._elementRef.nativeElement,"selectedIndex",-1);var n=L(e,t);this._renderer.setProperty(this._elementRef.nativeElement,"value",n)},t.prototype.registerOnChange=function(t){var e=this;this.onChange=function(n){e.value=e._getOptionValue(n),t(e.value)}},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t.prototype._registerOption=function(){return(this._idCounter++).toString()},t.prototype._getOptionId=function(t){var e,n;try{for(var r=Object(a.__values)(Array.from(this._optionMap.keys())),i=r.next();!i.done;i=r.next()){var s=i.value;if(this._compareWith(this._optionMap.get(s),t))return s}}catch(o){e={error:o}}finally{try{i&&!i.done&&(n=r.return)&&n.call(r)}finally{if(e)throw e.error}}return null},t.prototype._getOptionValue=function(t){var e=function(t){return t.split(":")[0]}(t);return this._optionMap.has(e)?this._optionMap.get(e):t},t}(),M=function(){function t(t,e,n){this._element=t,this._renderer=e,this._select=n,this._select&&(this.id=this._select._registerOption())}return Object.defineProperty(t.prototype,"ngValue",{set:function(t){null!=this._select&&(this._select._optionMap.set(this.id,t),this._setElementValue(L(this.id,t)),this._select.writeValue(this._select.value))},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"value",{set:function(t){this._setElementValue(t),this._select&&this._select.writeValue(this._select.value)},enumerable:!0,configurable:!0}),t.prototype._setElementValue=function(t){this._renderer.setProperty(this._element.nativeElement,"value",t)},t.prototype.ngOnDestroy=function(){this._select&&(this._select._optionMap.delete(this.id),this._select.writeValue(this._select.value))},t}();function q(t,e){return null==t?""+e:("string"==typeof e&&(e="'"+e+"'"),e&&"object"==typeof e&&(e="Object"),(t+": "+e).slice(0,50))}var j=function(){function t(t,e){this._renderer=t,this._elementRef=e,this._optionMap=new Map,this._idCounter=0,this.onChange=function(t){},this.onTouched=function(){},this._compareWith=r["\u0275looseIdentical"]}return Object.defineProperty(t.prototype,"compareWith",{set:function(t){if("function"!=typeof t)throw new Error("compareWith must be a function, but received "+JSON.stringify(t));this._compareWith=t},enumerable:!0,configurable:!0}),t.prototype.writeValue=function(t){var e,n=this;if(this.value=t,Array.isArray(t)){var a=t.map(function(t){return n._getOptionId(t)});e=function(t,e){t._setSelected(a.indexOf(e.toString())>-1)}}else e=function(t,e){t._setSelected(!1)};this._optionMap.forEach(e)},t.prototype.registerOnChange=function(t){var e=this;this.onChange=function(n){var a=[];if(n.hasOwnProperty("selectedOptions"))for(var r=n.selectedOptions,i=0;i<r.length;i++){var s=r.item(i),o=e._getOptionValue(s.value);a.push(o)}else for(r=n.options,i=0;i<r.length;i++)(s=r.item(i)).selected&&(o=e._getOptionValue(s.value),a.push(o));e.value=a,t(a)}},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this._renderer.setProperty(this._elementRef.nativeElement,"disabled",t)},t.prototype._registerOption=function(t){var e=(this._idCounter++).toString();return this._optionMap.set(e,t),e},t.prototype._getOptionId=function(t){var e,n;try{for(var r=Object(a.__values)(Array.from(this._optionMap.keys())),i=r.next();!i.done;i=r.next()){var s=i.value;if(this._compareWith(this._optionMap.get(s)._value,t))return s}}catch(o){e={error:o}}finally{try{i&&!i.done&&(n=r.return)&&n.call(r)}finally{if(e)throw e.error}}return null},t.prototype._getOptionValue=function(t){var e=function(t){return t.split(":")[0]}(t);return this._optionMap.has(e)?this._optionMap.get(e)._value:t},t}(),F=function(){function t(t,e,n){this._element=t,this._renderer=e,this._select=n,this._select&&(this.id=this._select._registerOption(this))}return Object.defineProperty(t.prototype,"ngValue",{set:function(t){null!=this._select&&(this._value=t,this._setElementValue(q(this.id,t)),this._select.writeValue(this._select.value))},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"value",{set:function(t){this._select?(this._value=t,this._setElementValue(q(this.id,t)),this._select.writeValue(this._select.value)):this._setElementValue(t)},enumerable:!0,configurable:!0}),t.prototype._setElementValue=function(t){this._renderer.setProperty(this._element.nativeElement,"value",t)},t.prototype._setSelected=function(t){this._renderer.setProperty(this._element.nativeElement,"selected",t)},t.prototype.ngOnDestroy=function(){this._select&&(this._select._optionMap.delete(this.id),this._select.writeValue(this._select.value))},t}();function z(t,e){return Object(a.__spread)(e.path,[t])}function G(t,e){t||B(e,"Cannot find control with"),e.valueAccessor||B(e,"No value accessor for form control with"),t.validator=h.compose([t.validator,e.validator]),t.asyncValidator=h.composeAsync([t.asyncValidator,e.asyncValidator]),e.valueAccessor.writeValue(t.value),function(t,e){e.valueAccessor.registerOnChange(function(n){t._pendingValue=n,t._pendingChange=!0,t._pendingDirty=!0,"change"===t.updateOn&&Y(t,e)})}(t,e),function(t,e){t.registerOnChange(function(t,n){e.valueAccessor.writeValue(t),n&&e.viewToModelUpdate(t)})}(t,e),function(t,e){e.valueAccessor.registerOnTouched(function(){t._pendingTouched=!0,"blur"===t.updateOn&&t._pendingChange&&Y(t,e),"submit"!==t.updateOn&&t.markAsTouched()})}(t,e),e.valueAccessor.setDisabledState&&t.registerOnDisabledChange(function(t){e.valueAccessor.setDisabledState(t)}),e._rawValidators.forEach(function(e){e.registerOnValidatorChange&&e.registerOnValidatorChange(function(){return t.updateValueAndValidity()})}),e._rawAsyncValidators.forEach(function(e){e.registerOnValidatorChange&&e.registerOnValidatorChange(function(){return t.updateValueAndValidity()})})}function Y(t,e){t._pendingDirty&&t.markAsDirty(),t.setValue(t._pendingValue,{emitModelToViewChange:!1}),e.viewToModelUpdate(t._pendingValue),t._pendingChange=!1}function V(t,e){null==t&&B(e,"Cannot find control with"),t.validator=h.compose([t.validator,e.validator]),t.asyncValidator=h.composeAsync([t.asyncValidator,e.asyncValidator])}function H(t){return B(t,"There is no FormControl instance attached to form control element with")}function B(t,e){var n;throw n=t.path.length>1?"path: '"+t.path.join(" -> ")+"'":t.path[0]?"name: '"+t.path+"'":"unspecified name attribute",new Error(e+" "+n)}function U(t){return null!=t?h.compose(t.map(T)):null}function W(t){return null!=t?h.composeAsync(t.map(w)):null}function K(t,e){if(!t.hasOwnProperty("model"))return!1;var n=t.model;return!!n.isFirstChange()||!Object(r["\u0275looseIdentical"])(e,n.currentValue)}var $=[v,N,S,P,j,k];function Z(t,e){t._syncPendingControls(),e.forEach(function(t){var e=t.control;"submit"===e.updateOn&&e._pendingChange&&(t.viewToModelUpdate(e._pendingValue),e._pendingChange=!1)})}function X(t,e){if(!e)return null;Array.isArray(e)||B(t,"Value accessor was not provided as an array for form control with");var n=void 0,a=void 0,r=void 0;return e.forEach(function(e){var i;e.constructor===x?n=e:(i=e,$.some(function(t){return i.constructor===t})?(a&&B(t,"More than one built-in value accessor matches form control with"),a=e):(r&&B(t,"More than one custom value accessor matches form control with"),r=e))}),r||a||n||(B(t,"No valid value accessor for form control with"),null)}function J(t,e){var n=t.indexOf(e);n>-1&&t.splice(n,1)}var Q=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(a.__extends)(e,t),e.prototype.ngOnInit=function(){this._checkParentType(),this.formDirective.addFormGroup(this)},e.prototype.ngOnDestroy=function(){this.formDirective&&this.formDirective.removeFormGroup(this)},Object.defineProperty(e.prototype,"control",{get:function(){return this.formDirective.getFormGroup(this)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"path",{get:function(){return z(this.name,this._parent)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"formDirective",{get:function(){return this._parent?this._parent.formDirective:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"validator",{get:function(){return U(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"asyncValidator",{get:function(){return W(this._asyncValidators)},enumerable:!0,configurable:!0}),e.prototype._checkParentType=function(){},e}(l),tt=function(){function t(t){this._cd=t}return Object.defineProperty(t.prototype,"ngClassUntouched",{get:function(){return!!this._cd.control&&this._cd.control.untouched},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassTouched",{get:function(){return!!this._cd.control&&this._cd.control.touched},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassPristine",{get:function(){return!!this._cd.control&&this._cd.control.pristine},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassDirty",{get:function(){return!!this._cd.control&&this._cd.control.dirty},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassValid",{get:function(){return!!this._cd.control&&this._cd.control.valid},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassInvalid",{get:function(){return!!this._cd.control&&this._cd.control.invalid},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"ngClassPending",{get:function(){return!!this._cd.control&&this._cd.control.pending},enumerable:!0,configurable:!0}),t}(),et=function(t){function e(e){return t.call(this,e)||this}return Object(a.__extends)(e,t),e}(tt),nt=function(t){function e(e){return t.call(this,e)||this}return Object(a.__extends)(e,t),e}(tt);function at(t){var e=it(t)?t.validators:t;return Array.isArray(e)?U(e):e||null}function rt(t,e){var n=it(e)?e.asyncValidators:t;return Array.isArray(n)?W(n):n||null}function it(t){return null!=t&&!Array.isArray(t)&&"object"==typeof t}var st=function(){function t(t,e){this.validator=t,this.asyncValidator=e,this._onCollectionChange=function(){},this.pristine=!0,this.touched=!1,this._onDisabledChange=[]}return Object.defineProperty(t.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"valid",{get:function(){return"VALID"===this.status},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"invalid",{get:function(){return"INVALID"===this.status},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"pending",{get:function(){return"PENDING"==this.status},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"disabled",{get:function(){return"DISABLED"===this.status},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"enabled",{get:function(){return"DISABLED"!==this.status},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"dirty",{get:function(){return!this.pristine},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"untouched",{get:function(){return!this.touched},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"updateOn",{get:function(){return this._updateOn?this._updateOn:this.parent?this.parent.updateOn:"change"},enumerable:!0,configurable:!0}),t.prototype.setValidators=function(t){this.validator=at(t)},t.prototype.setAsyncValidators=function(t){this.asyncValidator=rt(t)},t.prototype.clearValidators=function(){this.validator=null},t.prototype.clearAsyncValidators=function(){this.asyncValidator=null},t.prototype.markAsTouched=function(t){void 0===t&&(t={}),this.touched=!0,this._parent&&!t.onlySelf&&this._parent.markAsTouched(t)},t.prototype.markAsUntouched=function(t){void 0===t&&(t={}),this.touched=!1,this._pendingTouched=!1,this._forEachChild(function(t){t.markAsUntouched({onlySelf:!0})}),this._parent&&!t.onlySelf&&this._parent._updateTouched(t)},t.prototype.markAsDirty=function(t){void 0===t&&(t={}),this.pristine=!1,this._parent&&!t.onlySelf&&this._parent.markAsDirty(t)},t.prototype.markAsPristine=function(t){void 0===t&&(t={}),this.pristine=!0,this._pendingDirty=!1,this._forEachChild(function(t){t.markAsPristine({onlySelf:!0})}),this._parent&&!t.onlySelf&&this._parent._updatePristine(t)},t.prototype.markAsPending=function(t){void 0===t&&(t={}),this.status="PENDING",!1!==t.emitEvent&&this.statusChanges.emit(this.status),this._parent&&!t.onlySelf&&this._parent.markAsPending(t)},t.prototype.disable=function(t){void 0===t&&(t={}),this.status="DISABLED",this.errors=null,this._forEachChild(function(e){e.disable(Object(a.__assign)({},t,{onlySelf:!0}))}),this._updateValue(),!1!==t.emitEvent&&(this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),this._updateAncestors(t),this._onDisabledChange.forEach(function(t){return t(!0)})},t.prototype.enable=function(t){void 0===t&&(t={}),this.status="VALID",this._forEachChild(function(e){e.enable(Object(a.__assign)({},t,{onlySelf:!0}))}),this.updateValueAndValidity({onlySelf:!0,emitEvent:t.emitEvent}),this._updateAncestors(t),this._onDisabledChange.forEach(function(t){return t(!1)})},t.prototype._updateAncestors=function(t){this._parent&&!t.onlySelf&&(this._parent.updateValueAndValidity(t),this._parent._updatePristine(),this._parent._updateTouched())},t.prototype.setParent=function(t){this._parent=t},t.prototype.updateValueAndValidity=function(t){void 0===t&&(t={}),this._setInitialStatus(),this._updateValue(),this.enabled&&(this._cancelExistingSubscription(),this.errors=this._runValidator(),this.status=this._calculateStatus(),"VALID"!==this.status&&"PENDING"!==this.status||this._runAsyncValidator(t.emitEvent)),!1!==t.emitEvent&&(this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),this._parent&&!t.onlySelf&&this._parent.updateValueAndValidity(t)},t.prototype._updateTreeValidity=function(t){void 0===t&&(t={emitEvent:!0}),this._forEachChild(function(e){return e._updateTreeValidity(t)}),this.updateValueAndValidity({onlySelf:!0,emitEvent:t.emitEvent})},t.prototype._setInitialStatus=function(){this.status=this._allControlsDisabled()?"DISABLED":"VALID"},t.prototype._runValidator=function(){return this.validator?this.validator(this):null},t.prototype._runAsyncValidator=function(t){var e=this;if(this.asyncValidator){this.status="PENDING";var n=b(this.asyncValidator(this));this._asyncValidationSubscription=n.subscribe(function(n){return e.setErrors(n,{emitEvent:t})})}},t.prototype._cancelExistingSubscription=function(){this._asyncValidationSubscription&&this._asyncValidationSubscription.unsubscribe()},t.prototype.setErrors=function(t,e){void 0===e&&(e={}),this.errors=t,this._updateControlsErrors(!1!==e.emitEvent)},t.prototype.get=function(t){return function(t,e,n){return null==e?null:(e instanceof Array||(e=e.split(".")),e instanceof Array&&0===e.length?null:e.reduce(function(t,e){return t instanceof ut?t.controls.hasOwnProperty(e)?t.controls[e]:null:t instanceof ct&&t.at(e)||null},t))}(this,t)},t.prototype.getError=function(t,e){var n=e?this.get(e):this;return n&&n.errors?n.errors[t]:null},t.prototype.hasError=function(t,e){return!!this.getError(t,e)},Object.defineProperty(t.prototype,"root",{get:function(){for(var t=this;t._parent;)t=t._parent;return t},enumerable:!0,configurable:!0}),t.prototype._updateControlsErrors=function(t){this.status=this._calculateStatus(),t&&this.statusChanges.emit(this.status),this._parent&&this._parent._updateControlsErrors(t)},t.prototype._initObservables=function(){this.valueChanges=new r.EventEmitter,this.statusChanges=new r.EventEmitter},t.prototype._calculateStatus=function(){return this._allControlsDisabled()?"DISABLED":this.errors?"INVALID":this._anyControlsHaveStatus("PENDING")?"PENDING":this._anyControlsHaveStatus("INVALID")?"INVALID":"VALID"},t.prototype._anyControlsHaveStatus=function(t){return this._anyControls(function(e){return e.status===t})},t.prototype._anyControlsDirty=function(){return this._anyControls(function(t){return t.dirty})},t.prototype._anyControlsTouched=function(){return this._anyControls(function(t){return t.touched})},t.prototype._updatePristine=function(t){void 0===t&&(t={}),this.pristine=!this._anyControlsDirty(),this._parent&&!t.onlySelf&&this._parent._updatePristine(t)},t.prototype._updateTouched=function(t){void 0===t&&(t={}),this.touched=this._anyControlsTouched(),this._parent&&!t.onlySelf&&this._parent._updateTouched(t)},t.prototype._isBoxedValue=function(t){return"object"==typeof t&&null!==t&&2===Object.keys(t).length&&"value"in t&&"disabled"in t},t.prototype._registerOnCollectionChange=function(t){this._onCollectionChange=t},t.prototype._setUpdateStrategy=function(t){it(t)&&null!=t.updateOn&&(this._updateOn=t.updateOn)},t}(),ot=function(t){function e(e,n,a){void 0===e&&(e=null);var r=t.call(this,at(n),rt(a,n))||this;return r._onChange=[],r._applyFormState(e),r._setUpdateStrategy(n),r.updateValueAndValidity({onlySelf:!0,emitEvent:!1}),r._initObservables(),r}return Object(a.__extends)(e,t),e.prototype.setValue=function(t,e){var n=this;void 0===e&&(e={}),this.value=this._pendingValue=t,this._onChange.length&&!1!==e.emitModelToViewChange&&this._onChange.forEach(function(t){return t(n.value,!1!==e.emitViewToModelChange)}),this.updateValueAndValidity(e)},e.prototype.patchValue=function(t,e){void 0===e&&(e={}),this.setValue(t,e)},e.prototype.reset=function(t,e){void 0===t&&(t=null),void 0===e&&(e={}),this._applyFormState(t),this.markAsPristine(e),this.markAsUntouched(e),this.setValue(this.value,e),this._pendingChange=!1},e.prototype._updateValue=function(){},e.prototype._anyControls=function(t){return!1},e.prototype._allControlsDisabled=function(){return this.disabled},e.prototype.registerOnChange=function(t){this._onChange.push(t)},e.prototype._clearChangeFns=function(){this._onChange=[],this._onDisabledChange=[],this._onCollectionChange=function(){}},e.prototype.registerOnDisabledChange=function(t){this._onDisabledChange.push(t)},e.prototype._forEachChild=function(t){},e.prototype._syncPendingControls=function(){return!("submit"!==this.updateOn||(this._pendingDirty&&this.markAsDirty(),this._pendingTouched&&this.markAsTouched(),!this._pendingChange)||(this.setValue(this._pendingValue,{onlySelf:!0,emitModelToViewChange:!1}),0))},e.prototype._applyFormState=function(t){this._isBoxedValue(t)?(this.value=this._pendingValue=t.value,t.disabled?this.disable({onlySelf:!0,emitEvent:!1}):this.enable({onlySelf:!0,emitEvent:!1})):this.value=this._pendingValue=t},e}(st),ut=function(t){function e(e,n,a){var r=t.call(this,at(n),rt(a,n))||this;return r.controls=e,r._initObservables(),r._setUpdateStrategy(n),r._setUpControls(),r.updateValueAndValidity({onlySelf:!0,emitEvent:!1}),r}return Object(a.__extends)(e,t),e.prototype.registerControl=function(t,e){return this.controls[t]?this.controls[t]:(this.controls[t]=e,e.setParent(this),e._registerOnCollectionChange(this._onCollectionChange),e)},e.prototype.addControl=function(t,e){this.registerControl(t,e),this.updateValueAndValidity(),this._onCollectionChange()},e.prototype.removeControl=function(t){this.controls[t]&&this.controls[t]._registerOnCollectionChange(function(){}),delete this.controls[t],this.updateValueAndValidity(),this._onCollectionChange()},e.prototype.setControl=function(t,e){this.controls[t]&&this.controls[t]._registerOnCollectionChange(function(){}),delete this.controls[t],e&&this.registerControl(t,e),this.updateValueAndValidity(),this._onCollectionChange()},e.prototype.contains=function(t){return this.controls.hasOwnProperty(t)&&this.controls[t].enabled},e.prototype.setValue=function(t,e){var n=this;void 0===e&&(e={}),this._checkAllValuesPresent(t),Object.keys(t).forEach(function(a){n._throwIfControlMissing(a),n.controls[a].setValue(t[a],{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e)},e.prototype.patchValue=function(t,e){var n=this;void 0===e&&(e={}),Object.keys(t).forEach(function(a){n.controls[a]&&n.controls[a].patchValue(t[a],{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e)},e.prototype.reset=function(t,e){void 0===t&&(t={}),void 0===e&&(e={}),this._forEachChild(function(n,a){n.reset(t[a],{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e),this._updatePristine(e),this._updateTouched(e)},e.prototype.getRawValue=function(){return this._reduceChildren({},function(t,e,n){return t[n]=e instanceof ot?e.value:e.getRawValue(),t})},e.prototype._syncPendingControls=function(){var t=this._reduceChildren(!1,function(t,e){return!!e._syncPendingControls()||t});return t&&this.updateValueAndValidity({onlySelf:!0}),t},e.prototype._throwIfControlMissing=function(t){if(!Object.keys(this.controls).length)throw new Error("\n There are no form controls registered with this group yet. If you're using ngModel,\n you may want to check next tick (e.g. use setTimeout).\n ");if(!this.controls[t])throw new Error("Cannot find form control with name: "+t+".")},e.prototype._forEachChild=function(t){var e=this;Object.keys(this.controls).forEach(function(n){return t(e.controls[n],n)})},e.prototype._setUpControls=function(){var t=this;this._forEachChild(function(e){e.setParent(t),e._registerOnCollectionChange(t._onCollectionChange)})},e.prototype._updateValue=function(){this.value=this._reduceValue()},e.prototype._anyControls=function(t){var e=this,n=!1;return this._forEachChild(function(a,r){n=n||e.contains(r)&&t(a)}),n},e.prototype._reduceValue=function(){var t=this;return this._reduceChildren({},function(e,n,a){return(n.enabled||t.disabled)&&(e[a]=n.value),e})},e.prototype._reduceChildren=function(t,e){var n=t;return this._forEachChild(function(t,a){n=e(n,t,a)}),n},e.prototype._allControlsDisabled=function(){var t,e;try{for(var n=Object(a.__values)(Object.keys(this.controls)),r=n.next();!r.done;r=n.next())if(this.controls[r.value].enabled)return!1}catch(i){t={error:i}}finally{try{r&&!r.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}return Object.keys(this.controls).length>0||this.disabled},e.prototype._checkAllValuesPresent=function(t){this._forEachChild(function(e,n){if(void 0===t[n])throw new Error("Must supply a value for form control with name: '"+n+"'.")})},e}(st),ct=function(t){function e(e,n,a){var r=t.call(this,at(n),rt(a,n))||this;return r.controls=e,r._initObservables(),r._setUpdateStrategy(n),r._setUpControls(),r.updateValueAndValidity({onlySelf:!0,emitEvent:!1}),r}return Object(a.__extends)(e,t),e.prototype.at=function(t){return this.controls[t]},e.prototype.push=function(t){this.controls.push(t),this._registerControl(t),this.updateValueAndValidity(),this._onCollectionChange()},e.prototype.insert=function(t,e){this.controls.splice(t,0,e),this._registerControl(e),this.updateValueAndValidity()},e.prototype.removeAt=function(t){this.controls[t]&&this.controls[t]._registerOnCollectionChange(function(){}),this.controls.splice(t,1),this.updateValueAndValidity()},e.prototype.setControl=function(t,e){this.controls[t]&&this.controls[t]._registerOnCollectionChange(function(){}),this.controls.splice(t,1),e&&(this.controls.splice(t,0,e),this._registerControl(e)),this.updateValueAndValidity(),this._onCollectionChange()},Object.defineProperty(e.prototype,"length",{get:function(){return this.controls.length},enumerable:!0,configurable:!0}),e.prototype.setValue=function(t,e){var n=this;void 0===e&&(e={}),this._checkAllValuesPresent(t),t.forEach(function(t,a){n._throwIfControlMissing(a),n.at(a).setValue(t,{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e)},e.prototype.patchValue=function(t,e){var n=this;void 0===e&&(e={}),t.forEach(function(t,a){n.at(a)&&n.at(a).patchValue(t,{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e)},e.prototype.reset=function(t,e){void 0===t&&(t=[]),void 0===e&&(e={}),this._forEachChild(function(n,a){n.reset(t[a],{onlySelf:!0,emitEvent:e.emitEvent})}),this.updateValueAndValidity(e),this._updatePristine(e),this._updateTouched(e)},e.prototype.getRawValue=function(){return this.controls.map(function(t){return t instanceof ot?t.value:t.getRawValue()})},e.prototype._syncPendingControls=function(){var t=this.controls.reduce(function(t,e){return!!e._syncPendingControls()||t},!1);return t&&this.updateValueAndValidity({onlySelf:!0}),t},e.prototype._throwIfControlMissing=function(t){if(!this.controls.length)throw new Error("\n There are no form controls registered with this array yet. If you're using ngModel,\n you may want to check next tick (e.g. use setTimeout).\n ");if(!this.at(t))throw new Error("Cannot find form control at index "+t)},e.prototype._forEachChild=function(t){this.controls.forEach(function(e,n){t(e,n)})},e.prototype._updateValue=function(){var t=this;this.value=this.controls.filter(function(e){return e.enabled||t.disabled}).map(function(t){return t.value})},e.prototype._anyControls=function(t){return this.controls.some(function(e){return e.enabled&&t(e)})},e.prototype._setUpControls=function(){var t=this;this._forEachChild(function(e){return t._registerControl(e)})},e.prototype._checkAllValuesPresent=function(t){this._forEachChild(function(e,n){if(void 0===t[n])throw new Error("Must supply a value for form control at index: "+n+".")})},e.prototype._allControlsDisabled=function(){var t,e;try{for(var n=Object(a.__values)(this.controls),r=n.next();!r.done;r=n.next())if(r.value.enabled)return!1}catch(i){t={error:i}}finally{try{r&&!r.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}return this.controls.length>0||this.disabled},e.prototype._registerControl=function(t){t.setParent(this),t._registerOnCollectionChange(this._onCollectionChange)},e}(st),lt=Promise.resolve(null),dt=function(t){function e(e,n){var a=t.call(this)||this;return a.submitted=!1,a._directives=[],a.ngSubmit=new r.EventEmitter,a.form=new ut({},U(e),W(n)),a}return Object(a.__extends)(e,t),e.prototype.ngAfterViewInit=function(){this._setUpdateStrategy()},Object.defineProperty(e.prototype,"formDirective",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"control",{get:function(){return this.form},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"controls",{get:function(){return this.form.controls},enumerable:!0,configurable:!0}),e.prototype.addControl=function(t){var e=this;lt.then(function(){var n=e._findContainer(t.path);t.control=n.registerControl(t.name,t.control),G(t.control,t),t.control.updateValueAndValidity({emitEvent:!1}),e._directives.push(t)})},e.prototype.getControl=function(t){return this.form.get(t.path)},e.prototype.removeControl=function(t){var e=this;lt.then(function(){var n=e._findContainer(t.path);n&&n.removeControl(t.name),J(e._directives,t)})},e.prototype.addFormGroup=function(t){var e=this;lt.then(function(){var n=e._findContainer(t.path),a=new ut({});V(a,t),n.registerControl(t.name,a),a.updateValueAndValidity({emitEvent:!1})})},e.prototype.removeFormGroup=function(t){var e=this;lt.then(function(){var n=e._findContainer(t.path);n&&n.removeControl(t.name)})},e.prototype.getFormGroup=function(t){return this.form.get(t.path)},e.prototype.updateModel=function(t,e){var n=this;lt.then(function(){n.form.get(t.path).setValue(e)})},e.prototype.setValue=function(t){this.control.setValue(t)},e.prototype.onSubmit=function(t){return this.submitted=!0,Z(this.form,this._directives),this.ngSubmit.emit(t),!1},e.prototype.onReset=function(){this.resetForm()},e.prototype.resetForm=function(t){void 0===t&&(t=void 0),this.form.reset(t),this.submitted=!1},e.prototype._setUpdateStrategy=function(){this.options&&null!=this.options.updateOn&&(this.form._updateOn=this.options.updateOn)},e.prototype._findContainer=function(t){return t.pop(),t.length?this.form.get(t):this.form},e}(l),ft=function(){function t(){}return t.modelParentException=function(){throw new Error('\n ngModel cannot be used to register form controls with a parent formGroup directive. Try using\n formGroup\'s partner directive "formControlName" instead. Example:\n\n '+R+'\n\n Or, if you\'d like to avoid registering this form control, indicate that it\'s standalone in ngModelOptions:\n\n Example:\n\n \n <div [formGroup]="myGroup">\n <input formControlName="firstName">\n <input [(ngModel)]="showMoreControls" [ngModelOptions]="{standalone: true}">\n </div>\n ')},t.formGroupNameException=function(){throw new Error("\n ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.\n\n Option 1: Use formControlName instead of ngModel (reactive strategy):\n\n "+A+"\n\n Option 2: Update ngModel's parent be ngModelGroup (template-driven strategy):\n\n "+D)},t.missingNameException=function(){throw new Error('If ngModel is used within a form tag, either the name attribute must be set or the form\n control must be defined as \'standalone\' in ngModelOptions.\n\n Example 1: <input [(ngModel)]="person.firstName" name="first">\n Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">')},t.modelGroupParentException=function(){throw new Error("\n ngModelGroup cannot be used with a parent formGroup directive.\n\n Option 1: Use formGroupName instead of ngModelGroup (reactive strategy):\n\n "+A+"\n\n Option 2: Use a regular form tag instead of the formGroup directive (template-driven strategy):\n\n "+D)},t.ngFormWarning=function(){console.warn("\n It looks like you're using 'ngForm'.\n\n Support for using the 'ngForm' element selector has been deprecated in Angular v6 and will be removed\n in Angular v9.\n\n Use 'ng-form' instead.\n\n Before:\n <ngForm #myForm=\"ngForm\">\n\n After:\n <ng-form #myForm=\"ngForm\">\n ")},t}(),pt=new r.InjectionToken("NgFormSelectorWarning"),ht=function(t){function e(e,n,a){var r=t.call(this)||this;return r._parent=e,r._validators=n,r._asyncValidators=a,r}var n;return Object(a.__extends)(e,t),n=e,e.prototype._checkParentType=function(){this._parent instanceof n||this._parent instanceof dt||ft.modelGroupParentException()},e}(Q),gt=Promise.resolve(null),bt=function(t){function e(e,n,a,i){var s=t.call(this)||this;return s.control=new ot,s._registered=!1,s.update=new r.EventEmitter,s._parent=e,s._rawValidators=n||[],s._rawAsyncValidators=a||[],s.valueAccessor=X(s,i),s}return Object(a.__extends)(e,t),e.prototype.ngOnChanges=function(t){this._checkForErrors(),this._registered||this._setUpControl(),"isDisabled"in t&&this._updateDisabled(t),K(t,this.viewModel)&&(this._updateValue(this.model),this.viewModel=this.model)},e.prototype.ngOnDestroy=function(){this.formDirective&&this.formDirective.removeControl(this)},Object.defineProperty(e.prototype,"path",{get:function(){return this._parent?z(this.name,this._parent):[this.name]},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"formDirective",{get:function(){return this._parent?this._parent.formDirective:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"validator",{get:function(){return U(this._rawValidators)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"asyncValidator",{get:function(){return W(this._rawAsyncValidators)},enumerable:!0,configurable:!0}),e.prototype.viewToModelUpdate=function(t){this.viewModel=t,this.update.emit(t)},e.prototype._setUpControl=function(){this._setUpdateStrategy(),this._isStandalone()?this._setUpStandalone():this.formDirective.addControl(this),this._registered=!0},e.prototype._setUpdateStrategy=function(){this.options&&null!=this.options.updateOn&&(this.control._updateOn=this.options.updateOn)},e.prototype._isStandalone=function(){return!this._parent||!(!this.options||!this.options.standalone)},e.prototype._setUpStandalone=function(){G(this.control,this),this.control.updateValueAndValidity({emitEvent:!1})},e.prototype._checkForErrors=function(){this._isStandalone()||this._checkParentType(),this._checkName()},e.prototype._checkParentType=function(){!(this._parent instanceof ht)&&this._parent instanceof Q?ft.formGroupNameException():this._parent instanceof ht||this._parent instanceof dt||ft.modelParentException()},e.prototype._checkName=function(){this.options&&this.options.name&&(this.name=this.options.name),this._isStandalone()||this.name||ft.missingNameException()},e.prototype._updateValue=function(t){var e=this;gt.then(function(){e.control.setValue(t,{emitViewToModelChange:!1})})},e.prototype._updateDisabled=function(t){var e=this,n=t.isDisabled.currentValue,a=""===n||n&&"false"!==n;gt.then(function(){a&&!e.control.disabled?e.control.disable():!a&&e.control.disabled&&e.control.enable()})},e}(I),mt=new r.InjectionToken("NgModelWithFormControlWarning"),yt=function(t){function e(e,n){var a=t.call(this)||this;return a._validators=e,a._asyncValidators=n,a.submitted=!1,a.directives=[],a.form=null,a.ngSubmit=new r.EventEmitter,a}return Object(a.__extends)(e,t),e.prototype.ngOnChanges=function(t){this._checkFormPresent(),t.hasOwnProperty("form")&&(this._updateValidators(),this._updateDomValue(),this._updateRegistrations())},Object.defineProperty(e.prototype,"formDirective",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"control",{get:function(){return this.form},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),e.prototype.addControl=function(t){var e=this.form.get(t.path);return G(e,t),e.updateValueAndValidity({emitEvent:!1}),this.directives.push(t),e},e.prototype.getControl=function(t){return this.form.get(t.path)},e.prototype.removeControl=function(t){J(this.directives,t)},e.prototype.addFormGroup=function(t){var e=this.form.get(t.path);V(e,t),e.updateValueAndValidity({emitEvent:!1})},e.prototype.removeFormGroup=function(t){},e.prototype.getFormGroup=function(t){return this.form.get(t.path)},e.prototype.addFormArray=function(t){var e=this.form.get(t.path);V(e,t),e.updateValueAndValidity({emitEvent:!1})},e.prototype.removeFormArray=function(t){},e.prototype.getFormArray=function(t){return this.form.get(t.path)},e.prototype.updateModel=function(t,e){this.form.get(t.path).setValue(e)},e.prototype.onSubmit=function(t){return this.submitted=!0,Z(this.form,this.directives),this.ngSubmit.emit(t),!1},e.prototype.onReset=function(){this.resetForm()},e.prototype.resetForm=function(t){void 0===t&&(t=void 0),this.form.reset(t),this.submitted=!1},e.prototype._updateDomValue=function(){var t=this;this.directives.forEach(function(e){var n=t.form.get(e.path);e.control!==n&&(function(t,e){e.valueAccessor.registerOnChange(function(){return H(e)}),e.valueAccessor.registerOnTouched(function(){return H(e)}),e._rawValidators.forEach(function(t){t.registerOnValidatorChange&&t.registerOnValidatorChange(null)}),e._rawAsyncValidators.forEach(function(t){t.registerOnValidatorChange&&t.registerOnValidatorChange(null)}),t&&t._clearChangeFns()}(e.control,e),n&&G(n,e),e.control=n)}),this.form._updateTreeValidity({emitEvent:!1})},e.prototype._updateRegistrations=function(){var t=this;this.form._registerOnCollectionChange(function(){return t._updateDomValue()}),this._oldForm&&this._oldForm._registerOnCollectionChange(function(){}),this._oldForm=this.form},e.prototype._updateValidators=function(){var t=U(this._validators);this.form.validator=h.compose([this.form.validator,t]);var e=W(this._asyncValidators);this.form.asyncValidator=h.composeAsync([this.form.asyncValidator,e])},e.prototype._checkFormPresent=function(){this.form||E.missingFormException()},e}(l),vt=function(t){function e(e,n,a){var r=t.call(this)||this;return r._parent=e,r._validators=n,r._asyncValidators=a,r}return Object(a.__extends)(e,t),e.prototype._checkParentType=function(){xt(this._parent)&&E.groupParentException()},e}(Q),_t=function(t){function e(e,n,a){var r=t.call(this)||this;return r._parent=e,r._validators=n,r._asyncValidators=a,r}return Object(a.__extends)(e,t),e.prototype.ngOnInit=function(){this._checkParentType(),this.formDirective.addFormArray(this)},e.prototype.ngOnDestroy=function(){this.formDirective&&this.formDirective.removeFormArray(this)},Object.defineProperty(e.prototype,"control",{get:function(){return this.formDirective.getFormArray(this)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"formDirective",{get:function(){return this._parent?this._parent.formDirective:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"path",{get:function(){return z(this.name,this._parent)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"validator",{get:function(){return U(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"asyncValidator",{get:function(){return W(this._asyncValidators)},enumerable:!0,configurable:!0}),e.prototype._checkParentType=function(){xt(this._parent)&&E.arrayParentException()},e}(l);function xt(t){return!(t instanceof vt||t instanceof yt||t instanceof _t)}var Tt=function(t){function e(e,n,a,i,s){var o=t.call(this)||this;return o._ngModelWarningConfig=s,o._added=!1,o.update=new r.EventEmitter,o._ngModelWarningSent=!1,o._parent=e,o._rawValidators=n||[],o._rawAsyncValidators=a||[],o.valueAccessor=X(o,i),o}var n;return Object(a.__extends)(e,t),n=e,Object.defineProperty(e.prototype,"isDisabled",{set:function(t){E.disabledAttrWarning()},enumerable:!0,configurable:!0}),e.prototype.ngOnChanges=function(t){var e,a;this._added||this._setUpControl(),K(t,this.viewModel)&&("formControlName",e=n,this,a=this._ngModelWarningConfig,Object(r.isDevMode)()&&"never"!==a&&((null!==a&&"once"!==a||e._ngModelWarningSentOnce)&&("always"!==a||this._ngModelWarningSent)||(E.ngModelWarning("formControlName"),e._ngModelWarningSentOnce=!0,this._ngModelWarningSent=!0)),this.viewModel=this.model,this.formDirective.updateModel(this,this.model))},e.prototype.ngOnDestroy=function(){this.formDirective&&this.formDirective.removeControl(this)},e.prototype.viewToModelUpdate=function(t){this.viewModel=t,this.update.emit(t)},Object.defineProperty(e.prototype,"path",{get:function(){return z(this.name,this._parent)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"formDirective",{get:function(){return this._parent?this._parent.formDirective:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"validator",{get:function(){return U(this._rawValidators)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"asyncValidator",{get:function(){return W(this._rawAsyncValidators)},enumerable:!0,configurable:!0}),e.prototype._checkParentType=function(){!(this._parent instanceof vt)&&this._parent instanceof Q?E.ngModelGroupException():this._parent instanceof vt||this._parent instanceof yt||this._parent instanceof _t||E.controlParentException()},e.prototype._setUpControl=function(){this._checkParentType(),this.control=this.formDirective.addControl(this),this.control.disabled&&this.valueAccessor.setDisabledState&&this.valueAccessor.setDisabledState(!0),this._added=!0},e._ngModelWarningSentOnce=!1,e}(I),wt=function(){function t(){}return Object.defineProperty(t.prototype,"required",{get:function(){return this._required},set:function(t){this._required=null!=t&&!1!==t&&""+t!="false",this._onChange&&this._onChange()},enumerable:!0,configurable:!0}),t.prototype.validate=function(t){return this.required?h.required(t):null},t.prototype.registerOnValidatorChange=function(t){this._onChange=t},t}(),St=function(){function t(){}return t.prototype.group=function(t,e){void 0===e&&(e=null);var n=this._reduceControls(t),a=null,r=null,i=void 0;return null!=e&&(function(t){return void 0!==t.asyncValidators||void 0!==t.validators||void 0!==t.updateOn}(e)?(a=null!=e.validators?e.validators:null,r=null!=e.asyncValidators?e.asyncValidators:null,i=null!=e.updateOn?e.updateOn:void 0):(a=null!=e.validator?e.validator:null,r=null!=e.asyncValidator?e.asyncValidator:null)),new ut(n,{asyncValidators:r,updateOn:i,validators:a})},t.prototype.control=function(t,e,n){return new ot(t,e,n)},t.prototype.array=function(t,e,n){var a=this,r=t.map(function(t){return a._createControl(t)});return new ct(r,e,n)},t.prototype._reduceControls=function(t){var e=this,n={};return Object.keys(t).forEach(function(a){n[a]=e._createControl(t[a])}),n},t.prototype._createControl=function(t){return t instanceof ot||t instanceof ut||t instanceof ct?t:Array.isArray(t)?this.control(t[0],t.length>1?t[1]:null,t.length>2?t[2]:null):this.control(t)},t}(),Ot=function(){return function(){}}(),It=function(){return function(){}}(),Ct=function(){function t(){}var e;return e=t,t.withConfig=function(t){return{ngModule:e,providers:[{provide:pt,useValue:t.warnOnDeprecatedNgFormSelector}]}},t}(),kt=function(){function t(){}var e;return e=t,t.withConfig=function(t){return{ngModule:e,providers:[{provide:mt,useValue:t.warnOnNgModelWithFormControl}]}},t}()},gVVK:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r=t+" ";switch(n){case"s":return e||a?"nekaj sekund":"nekaj sekundami";case"ss":return r+(1===t?e?"sekundo":"sekundi":2===t?e||a?"sekundi":"sekundah":t<5?e||a?"sekunde":"sekundah":"sekund");case"m":return e?"ena minuta":"eno minuto";case"mm":return r+(1===t?e?"minuta":"minuto":2===t?e||a?"minuti":"minutama":t<5?e||a?"minute":"minutami":e||a?"minut":"minutami");case"h":return e?"ena ura":"eno uro";case"hh":return r+(1===t?e?"ura":"uro":2===t?e||a?"uri":"urama":t<5?e||a?"ure":"urami":e||a?"ur":"urami");case"d":return e||a?"en dan":"enim dnem";case"dd":return r+(1===t?e||a?"dan":"dnem":2===t?e||a?"dni":"dnevoma":e||a?"dni":"dnevi");case"M":return e||a?"en mesec":"enim mesecem";case"MM":return r+(1===t?e||a?"mesec":"mesecem":2===t?e||a?"meseca":"mesecema":t<5?e||a?"mesece":"meseci":e||a?"mesecev":"meseci");case"y":return e||a?"eno leto":"enim letom";case"yy":return r+(1===t?e||a?"leto":"letom":2===t?e||a?"leti":"letoma":t<5?e||a?"leta":"leti":e||a?"let":"leti")}}n("wd/R").defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_\u010detrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._\u010det._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_\u010de_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[v\u010deraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prej\u0161njo] [nedeljo] [ob] LT";case 3:return"[prej\u0161njo] [sredo] [ob] LT";case 6:return"[prej\u0161njo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prej\u0161nji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"\u010dez %s",past:"pred %s",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}()},gekB:function(t,e,n){!function(t){"use strict";var e="nolla yksi kaksi kolme nelj\xe4 viisi kuusi seitsem\xe4n kahdeksan yhdeks\xe4n".split(" "),n=["nolla","yhden","kahden","kolmen","nelj\xe4n","viiden","kuuden",e[7],e[8],e[9]];function a(t,a,r,i){var s="";switch(r){case"s":return i?"muutaman sekunnin":"muutama sekunti";case"ss":return i?"sekunnin":"sekuntia";case"m":return i?"minuutin":"minuutti";case"mm":s=i?"minuutin":"minuuttia";break;case"h":return i?"tunnin":"tunti";case"hh":s=i?"tunnin":"tuntia";break;case"d":return i?"p\xe4iv\xe4n":"p\xe4iv\xe4";case"dd":s=i?"p\xe4iv\xe4n":"p\xe4iv\xe4\xe4";break;case"M":return i?"kuukauden":"kuukausi";case"MM":s=i?"kuukauden":"kuukautta";break;case"y":return i?"vuoden":"vuosi";case"yy":s=i?"vuoden":"vuotta"}return function(t,a){return t<10?a?n[t]:e[t]:t}(t,i)+" "+s}t.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kes\xe4kuu_hein\xe4kuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kes\xe4_hein\xe4_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[t\xe4n\xe4\xe4n] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s p\xe4\xe4st\xe4",past:"%s sitten",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},gjCT:function(t,e,n){!function(t){"use strict";var e={1:"\u0661",2:"\u0662",3:"\u0663",4:"\u0664",5:"\u0665",6:"\u0666",7:"\u0667",8:"\u0668",9:"\u0669",0:"\u0660"},n={"\u0661":"1","\u0662":"2","\u0663":"3","\u0664":"4","\u0665":"5","\u0666":"6","\u0667":"7","\u0668":"8","\u0669":"9","\u0660":"0"};t.defineLocale("ar-sa",{months:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a\u0648_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648_\u0623\u063a\u0633\u0637\u0633_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a\u0648_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648_\u0623\u063a\u0633\u0637\u0633_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0623\u062d\u062f_\u0625\u062b\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0623\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/\u0635|\u0645/,isPM:function(t){return"\u0645"===t},meridiem:function(t,e,n){return t<12?"\u0635":"\u0645"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",ss:"%d \u062b\u0627\u0646\u064a\u0629",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},preparse:function(t){return t.replace(/[\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660]/g,function(t){return n[t]}).replace(/\u060c/g,",")},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]}).replace(/,/g,"\u060c")},week:{dow:0,doy:6}})}(n("wd/R"))},gp3X:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R");n("sb0X"),n.d(e,"a",function(){return i}),n.d(e,"b",function(){return o});var i=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function s(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"i",[["class","fa fa-spinner fa-spin fa-fw"]],null,null,null,null,null))],null,null)}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"button",[["class","btn btn-sm btn-primary tc_submitButton"]],[[8,"type",0],[8,"disabled",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.submit(n)&&a),a},null,null)),a["\u0275ncd"](null,0),(t()(),a["\u0275and"](16777216,null,null,1,null,s)),a["\u0275did"](3,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,3,0,e.component.loading)},function(t,e){var n=e.component;t(e,0,0,n.type,n.loading||n.disabled)})}},"h+PQ":function(t,e,n){"use strict";function a(){return""}function r(t,e){if(null==t)return"";if(!t||null==e)return t;var n=t[e];return null==n?"":n}function i(t,e){if(null==t)return"";if(!t||!e)return t;var n=t[e];return null==n?"":n}function s(t,e){if(null==t)return"";if(!t||!e)return t;var n=t[e];if(void 0!==n)return n;n=t;var a=e.split(".");if(a.length)for(var r=0;r<a.length;r++)if(null==(n=n[a[r]]))return"";return n}Object.defineProperty(e,"__esModule",{value:!0}),e.emptyStringGetter=a,e.getterForProp=function(t){return null==t?a:"number"==typeof t?r:-1!==t.indexOf(".")?s:i},e.numericIndexGetter=r,e.shallowValueGetter=i,e.deepValueGetter=s},h6KF:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("qwkt"),r=n("h+PQ");function i(t,e){if(null==t&&(t=0),null==e&&(e=0),t instanceof Date&&e instanceof Date){if(t<e)return-1;if(t>e)return 1}else if(isNaN(parseFloat(t))||!isFinite(t)||isNaN(parseFloat(e))||!isFinite(e)){if(t=String(t),e=String(e),t.toLowerCase()<e.toLowerCase())return-1;if(t.toLowerCase()>e.toLowerCase())return 1}else{if(parseFloat(t)<parseFloat(e))return-1;if(parseFloat(t)>parseFloat(e))return 1}return 0}e.nextSortDir=function(t,e){return t===a.SortType.single?e===a.SortDirection.asc?a.SortDirection.desc:a.SortDirection.asc:e?e===a.SortDirection.asc?a.SortDirection.desc:void 0:a.SortDirection.asc},e.orderByComparator=i,e.sortRows=function(t,e,n){if(!t)return[];if(!n||!n.length||!e)return t.slice();var s=new Map;t.forEach(function(t,e){return s.set(t,e)});var o=t.slice(),u=e.reduce(function(t,e){return e.comparator&&"function"==typeof e.comparator&&(t[e.prop]=e.comparator),t},{}),c=n.map(function(t){var e=t.prop;return{prop:e,dir:t.dir,valueGetter:r.getterForProp(e),compareFn:u[e]||i}});return o.sort(function(t,e){for(var n=0,r=c;n<r.length;n++){var i=r[n],o=i.prop,u=i.valueGetter,l=u(t,o),d=u(e,o),f=i.dir!==a.SortDirection.desc?i.compareFn(l,d,t,e,i.dir):-i.compareFn(l,d,t,e,i.dir);if(0!==f)return f}return s.has(t)&&s.has(e)?s.get(t)<s.get(e)?-1:1:0})}},h9Dq:function(t,e,n){"use strict";var a=n("mrSG"),r=function(t){function e(e,n){return t.call(this)||this}return a.__extends(e,t),e.prototype.schedule=function(t,e){return void 0===e&&(e=0),this},e}(n("pugT").a);n.d(e,"a",function(){return i});var i=function(t){function e(e,n){var a=t.call(this,e,n)||this;return a.scheduler=e,a.work=n,a.pending=!1,a}return a.__extends(e,t),e.prototype.schedule=function(t,e){if(void 0===e&&(e=0),this.closed)return this;this.state=t;var n=this.id,a=this.scheduler;return null!=n&&(this.id=this.recycleAsyncId(a,n,e)),this.pending=!0,this.delay=e,this.id=this.id||this.requestAsyncId(a,this.id,e),this},e.prototype.requestAsyncId=function(t,e,n){return void 0===n&&(n=0),setInterval(t.flush.bind(t,this),n)},e.prototype.recycleAsyncId=function(t,e,n){if(void 0===n&&(n=0),null!==n&&this.delay===n&&!1===this.pending)return e;clearInterval(e)},e.prototype.execute=function(t,e){if(this.closed)return new Error("executing a cancelled action");this.pending=!1;var n=this._execute(t,e);if(n)return n;!1===this.pending&&null!=this.id&&(this.id=this.recycleAsyncId(this.scheduler,this.id,null))},e.prototype._execute=function(t,e){var n=!1,a=void 0;try{this.work(t)}catch(r){n=!0,a=!!r&&r||new Error(r)}if(n)return this.unsubscribe(),a},e.prototype._unsubscribe=function(){var t=this.id,e=this.scheduler,n=e.actions,a=n.indexOf(this);this.work=null,this.state=null,this.pending=!1,this.scheduler=null,-1!==a&&n.splice(a,1),null!=t&&(this.id=this.recycleAsyncId(e,t,null)),this.delay=null},e}(r)},hHou:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="it-IT">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Attiva/Disattiva barra di navigazione</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Dashboard</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Cluster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitor</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Configurazione</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>Mappa CRUSH</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Moduli Manager</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Log</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Avvisi</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Blocco</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Immagini</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Esecuzione della copia speculare</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI </target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>File system</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Object Gateway</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Utenti</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Compartimenti</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Recupero dati\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> per\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Attendere...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Visualizzazione dei dati memorizzati in precedenza nella cache\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n per \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Impossibile caricare i dati\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> per\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Verificare lo stato del cluster.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Indietro</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Selezionare una lingua</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Caricamento pannello dati in corso...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Consultare la\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> su come\n configurare e abilitare la funzionalit\xe0 di monitoraggio.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Il dashboard di Grafana non esiste. Consultare la\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> su come\n aggiungere dashboard a Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Selezione ora di Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Impostazioni di ripristino</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Non \xe8 stato possibile caricare i dati.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>selezionato</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>trovato</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>totale</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Modifica</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nome</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Descrizione</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Descrizione lunga</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Default</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Default del daemon</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Servizi</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Valori</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo alto. Non deve essere maggiore di \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo basso. Non deve essere minore di \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Salva</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>Visualizzatore mappa CRUSH</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Elenco degli host</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Prestazioni complessive</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Nessuna voce trovata</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Log dei cluster</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Log delle revisioni</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Caricamento della configurazione in corso...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>Impossibile caricare la configurazione.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Modifica modulo Manager</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>Il valore immesso non \xe8 un UUID valido, ad es.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>Il valore immesso deve essere un indirizzo IP valido.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Questo campo \xe8 obbligatorio.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo alto. Deve essere minore o uguale a \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo basso. Deve essere maggiore o uguale a \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>Il valore immesso deve essere un numero.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>Il valore immesso deve essere un numero o un decimale.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Aggiorna</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Stato</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>ID cluster</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>mappa mon modificata</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>epoca mappa mon</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>con richiesta</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>mon richiesto</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>Nel quorum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Non nel quorum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Annulla</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Si \xe8 sicuri di voler \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> l\'elemento \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> selezionato?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>S\xec.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Flag OSD in tutto il cluster</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Invia</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Avanzate...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Priorit\xe0 di recupero OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Priorit\xe0</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Personalizza valori di priorit\xe0</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Questo campo \xe8 obbligatorio.</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo alto. Non deve essere maggiore di \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>Il valore immesso \xe8 troppo basso. Non deve essere minore di \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Ripesa OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>Il valore deve essere compreso tra 0 e 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Ripesa</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>Pulitura degli \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>OSD\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Deep } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Si sta per eseguire una \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>pulitura\n dell\'OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {deep } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Elenco degli OSD</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L\'OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> viene contrassegnato\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se si procede.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>Non \xe8 sicuro eliminare definitivamente l\'OSD.</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L\'OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> viene\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se si procede.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Dettagli</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Valore</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Chiudi</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Elimina</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Stato</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statistiche</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Consultare la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n su come configurare e abilitare la funzionalit\xe0 di gestione di NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Client</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Pu\xf2 accedere qualsiasi client</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Indirizzi</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Campo obbligatorio</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Deve contenere uno o pi\xf9 valori delimitati da virgole</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Ad esempio:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Tipo di accesso</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Esegui squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Aggiungi client</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Caricamento in corso...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- Nessun cluster disponibile --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Selezionare il cluster --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Aggiungi daemon</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Backend di storage</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- Nessun pool di dati disponibile --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Selezionare il backend di storage --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Utente Object Gateway</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- Nessun utente disponibile --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Selezionare l\'utente Object Gateway --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>ID utente CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- Nessun client disponibile --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Selezionare il client Cephx --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nome CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Etichetta di sicurezza</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Abilita etichetta di sicurezza</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>Percorso CephFS</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>Il percorso deve iniziare con una barra \'/\' e pu\xf2 essere seguito da una parola</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Viene creata la nuova directory</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Percorso</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>Il percorso pu\xf2 essere solo una singola barra \'/\' o parola</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Viene creato il nuovo compartimento</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protocollo NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Tag NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Accesso alternativo per montaggi \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (non deve contenere una / iniziale).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>I client non possono montare le sottodirectory (ad es. se Tag = foo, il client non pu\xf2 montare foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>Utilizzando diverse opzioni Tag, \xe8 possibile esportare pi\xf9 volte lo stesso percorso.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>La posizione che occupa l\'esportazione \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n nello \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (deve essere univoca).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>Utilizzando diverse opzioni Pseudo, \xe8 possibile esportare pi\xf9 volte lo stesso percorso.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- Nessun tipo di accesso disponibile --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Selezionare il tipo di accesso --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- Nessuno squash disponibile --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>--Selezionare il tipo di squash dell\'ID utente da eseguire --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protocollo di trasporto</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Benvenuto in Ceph.</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Nome utente necessario</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Password richiesta</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Login</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Spiacenti, l\'utente non esiste in Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Tornale alla \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Pagina di login\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Si viene disconnessi dal Provider di identit\xe0\n quando si riprova a eseguire il login.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Non consentito</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Spiacenti, non \xe8 consentito visualizzare ci\xf2 che si stava cercando.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Spiacenti, impossibile trovare ci\xf2 che si stava cercando</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Rimuovi tutto</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Notifiche recenti</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Non esistono task in background.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Task in background</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Guida</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Documentazione</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>Informazioni su</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Impostazioni del dashboard</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Gestione utenti</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Utente connesso</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Connesso come\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Disconnetti</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nome...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Il nome scelto \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Descrizione...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Autorizzazioni</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Ruoli</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nome utente</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Password</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Conferma password</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>La password di conferma non corrisponde alla password.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Nome completo</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>E-mail</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>E-mail non valida.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Si stanno per rimuovere le autorizzazioni di "lettura/aggiornamento utente" dal proprio utente.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Se si continua, non \xe8 pi\xf9 possibile aggiungere o rimuovere ruoli da qualsiasi utente.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Continuare?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Contatori delle prestazioni non disponibili</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Attributi (mappa OSD)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Metadati non disponibili</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadati</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Contatore delle prestazioni</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Istogramma non disponibile: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Scritture</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Letture</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Istogramma</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Dettagli sulle prestazioni</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Valori attuali</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Tipo</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Min</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Max</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Flag</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Origine</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Livello</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Pu\xf2 essere aggiornato al runtime (modificabile)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Tag</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Valori di enumerazione</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Vedere anche</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Stato del cluster</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Manager Daemon</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Object Gateway</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Server di metadati</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI Gateway</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>IOPS client</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Velocit\xe0 effettiva client</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Lettura/scrittura client</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Velocit\xe0 effettiva di recupero</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Pulitura</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Prestazioni</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Capacit\xe0 di base</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Oggetti</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>Gruppi di posizionamento per OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Stato gruppo di posizionamento</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Capacit\xe0</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Vedere \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Log\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> per ulteriori informazioni.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Classificazioni</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Client: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Sposta un\'immagine nel cestino</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Per spostare \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> nel cestino,\n fare clic su \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Sposta immagine\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Facoltativamente, \xe8 possibile selezionare una data di scadenza.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>La protezione scade alle</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>NON PROTETTO</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Formato data errato. Utilizzare "AAAA-MM-GG HH:mm:ss".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>La protezione \xe8 gi\xe0 scaduta. Selezionare una data futura o lasciarla vuota.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Sposta immagine</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Panoramica</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Destinazioni</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Autenticazione rilevazione</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Utente</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>I nomi utente devono avere una lunghezza compresa tra 8 e 64 caratteri e\n possono contenere solo lettere, \'.\', \'@\', \'-\', \'_\' o \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Utente reciproco</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Password reciproca</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Consultare la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n su come configurare e abilitare la funzionalit\xe0 di gestione delle destinazioni iSCSI.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informazioni disponibili:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>Destinazioni iSCSI non disponibili</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Disponibile solo per le immagini RDB con \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> abilitata\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Pool di dati</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Creato</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Dimensioni</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Dimensioni oggetto</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Funzioni</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Soggetto al provisioning</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/D</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Totale soggetto al provisioning</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Unit\xe0 di striping</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Conteggio di striping</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Superiore</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Prefisso nome blocco</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Ordine</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Snapshot</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Immagine</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Questa impostazione sostituisce il valore globale</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Globale</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Questo \xe8 il valore globale. Nessun valore di opzione \xe8 stato impostato per questa immagine.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' e \'@\' non sono consentiti.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- Nessun pool rbd disponibile --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Selezionare un pool --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Utilizza un pool di dati dedicato</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Pool di dati</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Pool dedicato che archivia i dati oggetto dell\'RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>ad es. 10 GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>\xc8 necessario aumentare le dimensioni.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Avanzate</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Striping</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Unit\xe0 di striping</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Selezionare l\'unit\xe0 di striping --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Questo campo \xe8 obbligatorio perch\xe9 \xe8 specificato il numero di striping.</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>L\'unit\xe0 di striping \xe8 maggiore delle dimensioni dell\'oggetto.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Numero di striping</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Questo campo \xe8 obbligatorio perch\xe9 \xe8 specificata l\'unit\xe0 di striping.</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Il numero di striping deve essere maggiore di 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot RBD\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>PROTETTO</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>NON PROTETTO</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Si sta per eseguire il rollback</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Elimina definitivamente contenuto del cestino</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Per eliminare definitivamente, selezionare una o tutte le immagini e fare clic su</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Pool:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nome pool...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Tutto</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Ripristina immagine</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Per ripristinare,</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>digitare il nuovo nome dell\'immagine e fare clic su</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nuovo nome</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Scaduto alle</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Protetto fino alle</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Questa immagine \xe8 protetta fino alle \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Cestino</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologia iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Di solito non \xe8 necessario modificare questi parametri rispetto ai valori di default.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Impostazioni</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Conferma</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Impostazioni avanzate</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>IQN di destinazione</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN contiene un modello errato.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Un IQN contiene la notazione seguente \'iqn.$year-$month.$reversedAddress:$definedName\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Ad esempio: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Ulteriori informazioni</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Questa destinazione contiene impostazioni avanzate modificate.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portali</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Gateway richiesti: almeno \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Aggiungi portale</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Questa immagine contiene impostazioni modificate.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Aggiungi immagine</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Autenticazione ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Iniziatori</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Iniziatore</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>IQN client</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>L\'IQN dell\'iniziatore deve essere univoco.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>I nomi utente devono avere una lunghezza compresa tra 8 e 64 caratteri e\n possono contenere solo lettere, \'.\', \'@\', \'-\', \'_\' o \':\'.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>L\'iniziatore appartiene a un gruppo. Le immagini verranno configurate nel gruppo.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Nessun elemento aggiunto.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Aggiungi iniziatore</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Gruppi</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Gruppo</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Aggiungi gruppo</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Configurazione RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Rimuovere il valore della configurazione locale. Al suo posto verr\xe0 ereditato e utilizzato il valore della configurazione superiore.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>Il valore minimo \xe8 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Problemi</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Sincronizzazione in corso</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Pronto</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Modifica modalit\xe0 speculare per il pool</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Per modificare la modalit\xe0 speculare per il pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, selezionare una nuova modalit\xe0 dall\'elenco e fare clic su\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aggiorna\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Modalit\xe0</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>\xc8 necessario rimuovere i cluster peer prima di disabilitare la copia speculare.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n peer copia speculare del pool\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> gli attributi peer della\n copia speculare per il pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> e fare clic su \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Invia\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nome cluster</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>Il nome del cluster non \xe8 valido.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>ID CephX</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>ID CephX...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>L\'ID CephX non \xe8 valido.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Indirizzi dei monitor</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Indirizzi con valori delimitati da virgole...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>L\'indirizzo del monitor non \xe8 valido.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>Chiave CephX</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Chiave con codifica Base64...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>La chiave CephX deve essere con codifica Base64.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Elenco dei pool</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>Il nome pu\xf2 contenere solo caratteri alfanumerici, trattini e caratteri di sottolineatura.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Il nome del profilo del codice di cancellazione selezionato \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Plugin</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Porzioni di dati (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Deve essere uguale o maggiore di 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Porzioni di codice (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Deve essere uguale o maggiore di 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Stima durata (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Localit\xe0 (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Dominio di errore Crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Localit\xe0 Crush</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Nessuno</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Tecnica</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Dimensione del pacchetto</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Radice Crush</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Classe dispositivo Crush</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>qualsiasi</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Directory</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Il nome del pool Ceph scelto \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Tipo di pool</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Selezionare un tipo di pool --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Gruppi di posizionamento</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>\xc8 necessario almeno un gruppo di posizionamento.</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Il cluster non pu\xf2 gestire questo numero eccessivo di gruppi di posizionamento. Ricalcolare il numero di gruppi di posizionamento necessari.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Guida per il calcolo</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>Sono state calcolate le impostazioni dei gruppi di posizionamento attuali;\n prima di inviare, assicurarsi che i valori soddisfino le proprie esigenze.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Set di regole Crush</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Selezionare una regola Crush --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Regola Crush</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Passaggi Crush</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Non \xe8 possibile utilizzare la regola nel cluster attuale perch\xe9 il numero degli\n OSD che contiene \xe8 troppo basso e non soddisfa il numero minimo di OSD richiesto da questa regola.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Dimensioni replicate</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Minime: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Massime: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>Le dimensioni specificate non sono comprese nell\'intervallo. L\'intervallo valido \xe8 da\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> a\n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Profilo del codice di cancellazione</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- Nessun profilo del codice di cancellazione disponibile --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Selezionare un profilo del codice di cancellazione --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>Sovrascritture EC</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Applicazioni</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Compressione</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algoritmo</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- Nessun algoritmo di compressione della cancellazione disponibile --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Dimensioni minime del blob</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>ad es. 128 KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>Il valore deve essere maggiore di 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Dimensioni massime del blob</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>ad es. 512 KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>Il valore deve essere maggiore delle dimensioni minime del blob</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Rapporto</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Rapporto di compressione</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>Il valore deve essere compreso tra 0,0 e 1,0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Non \xe8 possibile creare un pool RBD con una \'/\' nel nome.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Modificare il nome o rimuovere \'rbd\' dall\'elenco delle applicazioni.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Dettagli livelli cache</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Consultare la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n su come configurare e abilitare la funzionalit\xe0 di gestione di Object Gateway.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Elenco dei daemon</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Contatori delle prestazioni</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Caricamento dati compartimento in corso...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Impossibile caricare i dati del compartimento.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>Il valore non \xe8 valido.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Proprietario</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Selezionare un utente --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Tipo di indice</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Regola di posizionamento</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Contrassegno</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Contrassegno massimo</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Versione</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Versione master</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Ora di modifica</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Gruppo di zone</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Quota compartimenti</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Abilitato</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Dimensioni massime</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Illimitato</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Numero massimo di oggetti</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Selezionare un nome utente --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Generazione automatica chiave</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Chiave di accesso</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Chiave segreta</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Indirizzo e-mail</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Sospeso</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Sistema</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Numero massimo di compartimenti</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Sottoutenti</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Capacit\xe0</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Quota utenti</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Mostra</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Chiavi</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Selezionare un tipo --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Autorizzazione</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Selezionare un\'autorizzazione --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Sottoutente</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>L\'ID del sottoutente scelto \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>lettura, scrittura</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>pieno</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Chiave Swift</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Generazione automatica segreto</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Caricamento dati utente in corso...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>Impossibile caricare i dati utente.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>L\'ID utente scelto \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Non \xe8 un indirizzo e-mail valido.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>L\'indirizzo e-mail scelto \xe8 gi\xe0 in uso.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Numero max. di compartimenti</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>Il valore immesso deve essere &gt;= a 0.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>Chiave S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Non esistono sottoutenti.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Non esistono chiavi.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Non esistono capacit\xe0.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Dimensioni illimitate</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Dimensione max.</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Oggetti illimitati</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Numero max. di oggetti</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Attuale</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Autenticazione rilevazione aggiornata</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Non sono disponibili pool.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Non sono disponibili immagini.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Non sono disponibili immagini. Assicurarsi di aggiungere un\'immagine alla destinazione.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Non sono disponibili iniziatori. Assicurarsi di aggiungere un iniziatore alla destinazione.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Destinazione</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Stato</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Byte letti</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Byte scritti</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Operazioni di lettura</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Operazioni di scrittura</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O da</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Istanza</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nome host</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Problema</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Avanzamento</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Disabilitato</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Modalit\xe0 di modifica</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Aggiungi peer</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Modifica peer</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Elimina peer</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Sequenza iniziale</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># Locale</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># Remoto</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>peer copia speculare</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Chiave</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Appiattimento profondo</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Su strati</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Blocco esclusivo</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Mappa oggetti (richiede il blocco escluso)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Journaling (richiede il blocco esclusivo)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Rollback snapshot RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Esegui rollback</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Snapshot RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Eliminato alle</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>tipo</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>stato</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>versione</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Host</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>root</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Classificazione</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Task</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentry</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inode</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Utilizzo</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Daemon in standby</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\xc8 possibile aggiornare il valore al runtime.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>I daemon/client non estraggono questo valore dal\n database della configurazione di monitoraggio. Non \xe8 consentito impostare questa opzione tramite \'ceph config\n set ...\'. \xc8 necessario configurare questa opzione tramite ceph.conf o dalla\n riga di comando.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>L\'opzione diventa attiva solo all\'avvio del daemon.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>L\'opzione interessa solo la creazione del cluster.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>L\'opzione interessa solo la creazione del daemon.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Aggiornata opzione di configurazione \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Servizio</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Valore attuale</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Modificabile</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Opzioni aggiornate per il modulo &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Abilita</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Disabilita</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Riconnessione in corso. Attendere.</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Indirizzo pubblico</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Sessioni aperte</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Nessuno in entrata</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>Gli OSD che sono stati contrassegnati come disattivi in precedenza non verranno contrassegnati nuovamente come attivi all\'avvio</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Nessuno in uscita</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>Gli OSD non verranno disattivati automaticamente dopo l\'intervallo configurato</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Nessuno attivo</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>Non \xe8 consentito l\'avvio degli OSD</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Nessuno disattivo</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>I rapporti di errore degli OSD vengono ignorati in modo che i monitor non disattivino gli OSD</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Sospendi</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Sospende le operazioni di lettura e scrittura</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Nessuna pulitura</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Pulitura disabilitata</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Nessun pulitura approfondita</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Pulitura approfondita disabilitata</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Nessuna operazione di recupero</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Recupero dei gruppi di posizionamento sospeso</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Nessun recupero</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Recupero dei gruppi di posizionamento sospeso</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Ordinamento bitwise</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Usa ordinamento bitwise</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Snapdir eliminate definitivamente</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>Gli OSD contengono set di snap convertiti</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Eliminazioni recuperi</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Eliminazioni eseguite durante il recupero invece del peering</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Limite rigido log gruppo di posizionamento</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Inserisce un limite rigido alla lunghezza del log del gruppo di posizionamento</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Flag OSD aggiornati</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>esterno</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>interno</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>in basso</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Contrassegna</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD perso</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>contrassegnato come perso</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Elimina definitivamente</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>eliminato definitivamente</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>elimina definitivamente</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>eliminato definitivamente</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>Gruppi di posizionamento</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Byte letti</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Byte scritti</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Operazioni di lettura</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Operazioni di scrittura</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Contrassegna OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Contrassegna \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Numero max di recuperi informazioni</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Numero max di recuperi attivi</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Avvio singolo numero max di recuperi</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Sospensione recupero</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Personalizzato</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Aggiornata la priorit\xe0 della velocit\xe0 di recupero dell\'OSD &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> \xe8 stato inizializzato dall\'OSD seguente: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Lavoro</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Gravit\xe0</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Avviato</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Aggiornato</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Utilizzato</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Dispon.</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Pulisci</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>In funzione</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Avviso</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Sconosciuto</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>su</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>nessun file system</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>attivo</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>standby</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/d</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>daemon attivo</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target> quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Il servizio NFS Ganesha non \xe8 configurato.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Trasporto</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>Utente CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>File system CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(ereditato dalla configurazione globale)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>importato dalla configurazione globale</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Selezionare il tipo di squash dell\'ID utente che viene eseguito --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Non vi sono daemon disponibili.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Modalit\xe0 cache</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Numero minimo di giorni per la rimozione</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Numero minimo di giorni per la cancellazione</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Numero max di byte di destinazione</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Numero max di oggetti di destinazione</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Non sono state aggiunte applicazioni.</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Raggiunto il limite di applicazioni</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Un pool pu\xf2 contenere solo fino a quattro definizioni delle applicazioni.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Caratteri consentiti \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>La lunghezza massima \xe8 di 128 caratteri</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtra o aggiungi applicazioni</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Aggiungi applicazione</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>profilo del codice di cancellazione</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Dimensioni della replica</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Ultima modifica</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Profilo con codice di cancellazione</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Set di regole Crush</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Byte scritti</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>compartimento</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Aggiornato compartimento Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Creato compartimento Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>compartimenti</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>utente</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Aggiornato utente Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Creato utente Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>utenti</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Ambito</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Lettura</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Crea</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Creato ruolo \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Aggiornato ruolo \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Ruolo di sistema</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Eliminato ruolo \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Creato utente &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Aggiorna utente</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Continua</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Si \xe8 stati automaticamente disconnessi perch\xe9 i ruoli sono stati modificati.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Aggiornato utente &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Eliminato utente &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Impossibile eliminare l\'utente &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Si \xe8 attualmente connessi come &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Ogni oggetto \xe8 suddiviso in porzioni di dati, ciascuna delle quali \xe8 memorizzata su un diverso OSD.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Calcola le porzioni di codice relative a ciascun oggetto e le memorizza su diversi OSD.\n Il numero di porzioni di codice \xe8 anche il numero degli OSD che \xe8 possibile disattivare senza perdere i dati.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Il plugin jerasure \xe8 il plugin pi\xf9 generico e flessibile,\n ed \xe8 anche il plugin di default dei pool con codice di cancellazione di Ceph.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>La tecnica pi\xf9 flessibile \xe8 reed_sol_van: \xe8 sufficiente impostare k\n ed m. La tecnica cauchy_good pu\xf2 essere pi\xf9 rapida ma occorre selezionare attentamente la dimensione del\n pacchetto. reed_sol_r6_op, liberation, blaum_roth, liber8tion sono tutti equivalenti a RAID6,\n nel senso che \xe8 possibile configurarli solo con m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>La codifica viene eseguita su pacchetti di dimensioni in byte, uno alla volta.\n \xc8 difficile scegliere la dimensione del pacchetto corretta.\n La documentazione su jerasure fornisce informazioni esaustive su questo argomento.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Con il plugin di jerasure, quando un oggetto con codice di cancellazione viene memorizzato su\n pi\xf9 OSD, il recupero della perdita di un OSD richiede la lettura di tutti gli altri.\n Ad esempio, se jerasure \xe8 configurato con k=8 e m=4, la perdita di un OSD richiede la lettura\n degli altri undici per il ripristino.\n\n Il plugin del codice di cancellazione lrc crea porzioni di parit\xe0 locali che \xe8 possibile recuperare utilizzando un\n minor numero di OSD. Ad esempio, se lrc \xe8 configurato con k=8, m=4 e l=4, crea\n una porzione di parit\xe0 aggiuntiva ogni quattro OSD. Quando si perde un singolo OSD, \xe8 possibile\n recuperarlo solo con quattro OSD invece che con undici.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Raggruppa le porzioni di codice e dati in set di localit\xe0 dimensione. Ad esempio,\n per k=4 e m=2, se localit\xe0=3 vengono creati due gruppi su tre. \xc8 possibile recuperare ciascun set\n senza leggere le porzioni di un altro set.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>Il tipo di compartimento Crush in cui viene memorizzato ciascun set di porzioni definito\n dall\'utente. Ad esempio, se \xe8 impostato su rack, ciascun gruppo di porzioni viene\n posizionato in un diverso rack. Viene utilizzato per creare un passaggio della regola CRUSH come il passaggio choose\n rack. Se non \xe8 impostato, il raggruppamento non viene eseguito.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Il plugin ISA incapsula la libreria ISA. Viene eseguito solo su processori Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>Il plugin ISA \xe8 disponibile in due formati Reed Solomon.\n Se \xe8 impostato reed_sol_van, il formato \xe8 Vandermonde, se \xe8 impostato cauchy, il formato \xe8 Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>Il plugin shec incapsula la libreria SHEC multipla.\n Consente a Ceph di recuperare i dati in modo pi\xf9 efficiente rispetto ai codici Reed Solomon.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>Il numero di compartimenti di parit\xe0, ciascuno dei quali include i singoli compartimenti di dati\n nell\'intervallo di calcolo. Il numero viene utilizzato come strumento di stima della durabilit\xe0. Ad esempio, se c=2,\n \xe8 possibile disattivare 2 OSD senza perdere i dati.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>Il nome del compartimento Crush utilizzato per il primo passaggio della regola CRUSH.\n Ad esempio il passaggio take default.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Assicurarsi che non esistano due porzioni in un compartimento con lo stesso dominio\n di errore. Ad esempio, se il dominio di errore \xe8 l\'host, non verranno memorizzate due porzioni sullo stesso\n host. Viene utilizzato per creare un passaggio della regola CRUSH come passaggio chooseleaf host.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Limitare il posizionamento ai dispositivi di una classe specifica\n (ad es. ssd o hdd) usando i nomi delle classi di dispositivi Crush nella mappa CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Impostare il nome della directory da cui viene caricato il plugin del codice di cancellazione.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Consente tutte le operazioni</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Consente solo le operazioni che non modificano il server</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>Non consente operazioni di lettura o scrittura, ma consente qualsiasi altra operazione</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>Non consente operazioni di lettura o scrittura o qualsiasi operazione che modifichi gli attributi dei file o il contenuto della directory</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>Non consente alcun accesso</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Selezionare la priorit\xe0 --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Bassa</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Alta</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>Ultimi 5 minuti</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>Ultimi 15 minuti</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>Ultimi 30 minuti</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>Ultima ora (Default)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>Ultime 3 ore</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>Ultime 6 ore</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>Ultime 12 ore</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>Ultime 24 ore</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Ieri</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Oggi</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Fino a oggi</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Giorno prima di ieri</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Ultimi 2 giorni</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Questo giorno della scorsa settimana</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>Settimana precedente</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Questa settimana</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Fino a questa settimana</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Ultimi 7 giorni</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>Mese precedente</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Questo mese</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Fino a questo mese</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Ultimi 30 giorni</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Ultimi 90 giorni</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Ultimi 6 mesi</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>Ultimo anno</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>Anno precedente</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Quest\'anno</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Fino a quest\'anno</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Ultimi 2 anni</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Ultimi 5 anni</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informazioni</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Nessun elemento selezionato.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Deselezionare l\'elemento per selezionare di nuovo</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target> Raggiunto il limite per la selezione</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Filtra tag</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Aggiungi badge</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Non vi sono elementi disponibili.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Aggiungi</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Clona</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Copia</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Pulitura approfondita</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Eliminazione definitiva</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Appiattisci</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Declassa</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Attiva</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Contrassegna come perso</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Disattiva</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Proteggi</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Rinomina</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Ripristina</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>Sposta nel cestino</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Rimuovi protezione</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Eliminato</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Clonato</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Copiato</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>S\xec</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>No</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Qualit\xe0 di servizio</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>Limite di BPS</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Il limite desiderato di byte I/O al secondo.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>Limite di IOPS</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Il limite desiderato di operazioni I/O al secondo.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>Limite BPS in lettura</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Il limite desiderato dei byte letti al secondo.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>Limite di IOPS in lettura</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Il limite desiderato di operazioni di lettura al secondo.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Limite di BPS in scrittura</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Il limite desiderato di byte scritti al secondo.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Limite di IOPS in scrittura</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Il limite desiderato di operazioni di scrittura al secondo.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>Burst BPS</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>Il limite di burst desiderato dei byte di I/O.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>Burst IOPS</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>Il limite di burst desiderato delle operazioni di I/O.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Burst BPS in lettura</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>Il limite di burst desiderato dei byte letti.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Burst IOPS in lettura</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>Il limite di burst desiderato delle operazioni di lettura.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Burst BPS in scrittura</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>Il limite di burst desiderato dei byte scritti.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Burst di IOPS in scrittura</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>Il limite di burst desiderato delle operazioni di scrittura.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Non \xe8 stato possibile \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>In esecuzione</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>esegui</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Eseguito</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>task sconosciuto</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Creazione in corso</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>crea</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Aggiornamento in corso</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>aggiorna</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Eliminazione in corso</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>elimina</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Snapshot RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>modalit\xe0 speculare per il pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>peer della copia speculare per il pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Il nome \xe8 gi\xe0 utilizzato da \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Il nome \xe8 gi\xe0 utilizzato da \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Il nome \xe8 gi\xe0 utilizzato da \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contiene snapshot.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Clonazione in corso</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>clona</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>La snapshot di \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> deve essere protetta.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Copia in corso</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>copia</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Appiattimento</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>appiattisci</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Appiattito</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Il nome \xe8 gi\xe0 utilizzato da \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Impossibile rimuovere la protezione da \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> perch\xe9 contiene immagini figlio.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Impossibile eliminare \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> perch\xe9 \xe8 protetto.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Rollback in corso</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>rollback</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Rollback eseguito</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Spostamento in corso</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>sposta</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>Spostato</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>immagine \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' nel cestino\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Impossibile trovare l\'immagine.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Ripristino in corso</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>ripristina</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Ripristinato</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>immagine \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' in \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Il nome dell\'immagine \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' \xe8 gi\xe0 in uso.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>immagine \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>Eliminazione in corso</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>elimina definitivamente</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Eliminato definitivamente</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>tutti i pool</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>Immagini da \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Impossibile disabilitare l\'esecuzione della copia speculare perch\xe9 contiene un peer.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>profilo del codice di cancellazione \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>destinazione \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},hKrs:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("bg",{months:"\u044f\u043d\u0443\u0430\u0440\u0438_\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0438\u043b_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438_\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438_\u043d\u043e\u0435\u043c\u0432\u0440\u0438_\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438".split("_"),monthsShort:"\u044f\u043d\u0440_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433_\u0441\u0435\u043f_\u043e\u043a\u0442_\u043d\u043e\u0435_\u0434\u0435\u043a".split("_"),weekdays:"\u043d\u0435\u0434\u0435\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u044f\u0434\u0430_\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a_\u043f\u0435\u0442\u044a\u043a_\u0441\u044a\u0431\u043e\u0442\u0430".split("_"),weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0442\u043e_\u0441\u0440\u044f_\u0447\u0435\u0442_\u043f\u0435\u0442_\u0441\u044a\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[\u0414\u043d\u0435\u0441 \u0432] LT",nextDay:"[\u0423\u0442\u0440\u0435 \u0432] LT",nextWeek:"dddd [\u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0430\u0442\u0430] dddd [\u0432] LT";case 1:case 2:case 4:case 5:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0438\u044f] dddd [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0441\u043b\u0435\u0434 %s",past:"\u043f\u0440\u0435\u0434\u0438 %s",s:"\u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434\u0438",ss:"%d \u0441\u0435\u043a\u0443\u043d\u0434\u0438",m:"\u043c\u0438\u043d\u0443\u0442\u0430",mm:"%d \u043c\u0438\u043d\u0443\u0442\u0438",h:"\u0447\u0430\u0441",hh:"%d \u0447\u0430\u0441\u0430",d:"\u0434\u0435\u043d",dd:"%d \u0434\u043d\u0438",M:"\u043c\u0435\u0441\u0435\u0446",MM:"%d \u043c\u0435\u0441\u0435\u0446\u0430",y:"\u0433\u043e\u0434\u0438\u043d\u0430",yy:"%d \u0433\u043e\u0434\u0438\u043d\u0438"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0435\u0432|\u0435\u043d|\u0442\u0438|\u0432\u0438|\u0440\u0438|\u043c\u0438)/,ordinal:function(t){var e=t%10,n=t%100;return 0===t?t+"-\u0435\u0432":0===n?t+"-\u0435\u043d":n>10&&n<20?t+"-\u0442\u0438":1===e?t+"-\u0432\u0438":2===e?t+"-\u0440\u0438":7===e||8===e?t+"-\u043c\u0438":t+"-\u0442\u0438"},week:{dow:1,doy:7}})}()},honF:function(t,e,n){!function(t){"use strict";var e={1:"\u1041",2:"\u1042",3:"\u1043",4:"\u1044",5:"\u1045",6:"\u1046",7:"\u1047",8:"\u1048",9:"\u1049",0:"\u1040"},n={"\u1041":"1","\u1042":"2","\u1043":"3","\u1044":"4","\u1045":"5","\u1046":"6","\u1047":"7","\u1048":"8","\u1049":"9","\u1040":"0"};t.defineLocale("my",{months:"\u1007\u1014\u103a\u1014\u101d\u102b\u101b\u102e_\u1016\u1031\u1016\u1031\u102c\u103a\u101d\u102b\u101b\u102e_\u1019\u1010\u103a_\u1027\u1015\u103c\u102e_\u1019\u1031_\u1007\u103d\u1014\u103a_\u1007\u1030\u101c\u102d\u102f\u1004\u103a_\u101e\u103c\u1002\u102f\u1010\u103a_\u1005\u1000\u103a\u1010\u1004\u103a\u1018\u102c_\u1021\u1031\u102c\u1000\u103a\u1010\u102d\u102f\u1018\u102c_\u1014\u102d\u102f\u101d\u1004\u103a\u1018\u102c_\u1012\u102e\u1007\u1004\u103a\u1018\u102c".split("_"),monthsShort:"\u1007\u1014\u103a_\u1016\u1031_\u1019\u1010\u103a_\u1015\u103c\u102e_\u1019\u1031_\u1007\u103d\u1014\u103a_\u101c\u102d\u102f\u1004\u103a_\u101e\u103c_\u1005\u1000\u103a_\u1021\u1031\u102c\u1000\u103a_\u1014\u102d\u102f_\u1012\u102e".split("_"),weekdays:"\u1010\u1014\u1004\u103a\u1039\u1002\u1014\u103d\u1031_\u1010\u1014\u1004\u103a\u1039\u101c\u102c_\u1021\u1004\u103a\u1039\u1002\u102b_\u1017\u102f\u1012\u1039\u1013\u101f\u1030\u1038_\u1000\u103c\u102c\u101e\u1015\u1010\u1031\u1038_\u101e\u1031\u102c\u1000\u103c\u102c_\u1005\u1014\u1031".split("_"),weekdaysShort:"\u1014\u103d\u1031_\u101c\u102c_\u1002\u102b_\u101f\u1030\u1038_\u1000\u103c\u102c_\u101e\u1031\u102c_\u1014\u1031".split("_"),weekdaysMin:"\u1014\u103d\u1031_\u101c\u102c_\u1002\u102b_\u101f\u1030\u1038_\u1000\u103c\u102c_\u101e\u1031\u102c_\u1014\u1031".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u101a\u1014\u1031.] LT [\u1019\u103e\u102c]",nextDay:"[\u1019\u1014\u1000\u103a\u1016\u103c\u1014\u103a] LT [\u1019\u103e\u102c]",nextWeek:"dddd LT [\u1019\u103e\u102c]",lastDay:"[\u1019\u1014\u1031.\u1000] LT [\u1019\u103e\u102c]",lastWeek:"[\u1015\u103c\u102e\u1038\u1001\u1032\u1037\u101e\u1031\u102c] dddd LT [\u1019\u103e\u102c]",sameElse:"L"},relativeTime:{future:"\u101c\u102c\u1019\u100a\u103a\u1037 %s \u1019\u103e\u102c",past:"\u101c\u103d\u1014\u103a\u1001\u1032\u1037\u101e\u1031\u102c %s \u1000",s:"\u1005\u1000\u1039\u1000\u1014\u103a.\u1021\u1014\u100a\u103a\u1038\u1004\u101a\u103a",ss:"%d \u1005\u1000\u1039\u1000\u1014\u1037\u103a",m:"\u1010\u1005\u103a\u1019\u102d\u1014\u1005\u103a",mm:"%d \u1019\u102d\u1014\u1005\u103a",h:"\u1010\u1005\u103a\u1014\u102c\u101b\u102e",hh:"%d \u1014\u102c\u101b\u102e",d:"\u1010\u1005\u103a\u101b\u1000\u103a",dd:"%d \u101b\u1000\u103a",M:"\u1010\u1005\u103a\u101c",MM:"%d \u101c",y:"\u1010\u1005\u103a\u1014\u103e\u1005\u103a",yy:"%d \u1014\u103e\u1005\u103a"},preparse:function(t){return t.replace(/[\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049\u1040]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},week:{dow:1,doy:4}})}(n("wd/R"))},i3PA:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("jvuA")),a(n("UReH"))},i4X3:function(t,e,n){"use strict";var a=n("6blF"),r=n("pugT"),i=n("xTla"),s=n("JF+6"),o=n("En8+"),u=n("/WYv"),c=n("2ePl");function l(t,e){if(null!=t){if(function(t){return t&&"function"==typeof t[i.a]}(t))return function(t,e){return new a.a(function(n){var a=new r.a;return a.add(e.schedule(function(){var r=t[i.a]();a.add(r.subscribe({next:function(t){a.add(e.schedule(function(){return n.next(t)}))},error:function(t){a.add(e.schedule(function(){return n.error(t)}))},complete:function(){a.add(e.schedule(function(){return n.complete()}))}}))})),a})}(t,e);if(Object(u.a)(t))return function(t,e){return new a.a(function(n){var a=new r.a;return a.add(e.schedule(function(){return t.then(function(t){a.add(e.schedule(function(){n.next(t),a.add(e.schedule(function(){return n.complete()}))}))},function(t){a.add(e.schedule(function(){return n.error(t)}))})})),a})}(t,e);if(Object(c.a)(t))return Object(s.a)(t,e);if(function(t){return t&&"function"==typeof t[o.a]}(t)||"string"==typeof t)return function(t,e){if(!t)throw new Error("Iterable cannot be null");return new a.a(function(n){var a,i=new r.a;return i.add(function(){a&&"function"==typeof a.return&&a.return()}),i.add(e.schedule(function(){a=t[o.a](),i.add(e.schedule(function(){if(!n.closed){var t,e;try{var r=a.next();t=r.value,e=r.done}catch(i){return void n.error(i)}e?n.complete():(n.next(t),this.schedule())}}))})),i})}(t,e)}throw new TypeError((null!==t&&typeof t||t)+" is not observable")}n.d(e,"a",function(){return l})},iEDd:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("gl",{months:"xaneiro_febreiro_marzo_abril_maio_xu\xf1o_xullo_agosto_setembro_outubro_novembro_decembro".split("_"),monthsShort:"xan._feb._mar._abr._mai._xu\xf1._xul._ago._set._out._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"domingo_luns_martes_m\xe9rcores_xoves_venres_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._m\xe9r._xov._ven._s\xe1b.".split("_"),weekdaysMin:"do_lu_ma_m\xe9_xo_ve_s\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextDay:function(){return"[ma\xf1\xe1 "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"\xe1s":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"\xe1":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"\xe1s":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(t){return 0===t.indexOf("un")?"n"+t:"en "+t},past:"hai %s",s:"uns segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}()},iExv:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t,e,n){return void 0===e&&(e=this.i18n("Yes")),void 0===n&&(n=this.i18n("No")),Boolean(t)?e:n},t}()},iLxQ:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=!1,r={Promise:void 0,set useDeprecatedSynchronousErrorHandling(t){a=t},get useDeprecatedSynchronousErrorHandling(){return a}}},iM7B:function(t,e,n){"use strict";var a=n("RDha"),r=n("Hg4g"),i=n("q8Fl");t.exports=a.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},i._enabled?i:r)},iYGd:function(t,e,n){"use strict";t.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},iYuL:function(t,e,n){!function(t){"use strict";var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),a=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;t.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,a){return t?/-MMM-/.test(a)?n[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:a,longMonthsParse:a,shortMonthsParse:a,weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_s\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[ma\xf1ana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}})}(n("wd/R"))},ihYY:function(t,e,n){"use strict";n.d(e,"b",function(){return a}),n.d(e,"c",function(){return r}),n.d(e,"a",function(){return i}),n.d(e,"e",function(){return o}),n.d(e,"f",function(){return u}),n.d(e,"g",function(){return l}),n.d(e,"h",function(){return c}),n.d(e,"i",function(){return d}),n.d(e,"j",function(){return s}),n.d(e,"d",function(){return p}),n.d(e,"l",function(){return g}),n.d(e,"k",function(){return h});var a=function(){return function(){}}(),r=function(){return function(){}}(),i="*";function s(t,e){return{type:7,name:t,definitions:e,options:{}}}function o(t,e){return void 0===e&&(e=null),{type:4,styles:e,timings:t}}function u(t,e){return void 0===e&&(e=null),{type:2,steps:t,options:e}}function c(t){return{type:6,styles:t,offset:null}}function l(t,e,n){return{type:0,name:t,styles:e,options:n}}function d(t,e,n){return void 0===n&&(n=null),{type:1,expr:t,animation:e,options:n}}function f(t){Promise.resolve(null).then(t)}var p=function(){function t(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this._onDoneFns=[],this._onStartFns=[],this._onDestroyFns=[],this._started=!1,this._destroyed=!1,this._finished=!1,this.parentPlayer=null,this.totalTime=t+e}return t.prototype._onFinish=function(){this._finished||(this._finished=!0,this._onDoneFns.forEach(function(t){return t()}),this._onDoneFns=[])},t.prototype.onStart=function(t){this._onStartFns.push(t)},t.prototype.onDone=function(t){this._onDoneFns.push(t)},t.prototype.onDestroy=function(t){this._onDestroyFns.push(t)},t.prototype.hasStarted=function(){return this._started},t.prototype.init=function(){},t.prototype.play=function(){this.hasStarted()||(this._onStart(),this.triggerMicrotask()),this._started=!0},t.prototype.triggerMicrotask=function(){var t=this;f(function(){return t._onFinish()})},t.prototype._onStart=function(){this._onStartFns.forEach(function(t){return t()}),this._onStartFns=[]},t.prototype.pause=function(){},t.prototype.restart=function(){},t.prototype.finish=function(){this._onFinish()},t.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.hasStarted()||this._onStart(),this.finish(),this._onDestroyFns.forEach(function(t){return t()}),this._onDestroyFns=[])},t.prototype.reset=function(){},t.prototype.setPosition=function(t){},t.prototype.getPosition=function(){return 0},t.prototype.triggerCallback=function(t){var e="start"==t?this._onStartFns:this._onDoneFns;e.forEach(function(t){return t()}),e.length=0},t}(),h=function(){function t(t){var e=this;this._onDoneFns=[],this._onStartFns=[],this._finished=!1,this._started=!1,this._destroyed=!1,this._onDestroyFns=[],this.parentPlayer=null,this.totalTime=0,this.players=t;var n=0,a=0,r=0,i=this.players.length;0==i?f(function(){return e._onFinish()}):this.players.forEach(function(t){t.onDone(function(){++n==i&&e._onFinish()}),t.onDestroy(function(){++a==i&&e._onDestroy()}),t.onStart(function(){++r==i&&e._onStart()})}),this.totalTime=this.players.reduce(function(t,e){return Math.max(t,e.totalTime)},0)}return t.prototype._onFinish=function(){this._finished||(this._finished=!0,this._onDoneFns.forEach(function(t){return t()}),this._onDoneFns=[])},t.prototype.init=function(){this.players.forEach(function(t){return t.init()})},t.prototype.onStart=function(t){this._onStartFns.push(t)},t.prototype._onStart=function(){this.hasStarted()||(this._started=!0,this._onStartFns.forEach(function(t){return t()}),this._onStartFns=[])},t.prototype.onDone=function(t){this._onDoneFns.push(t)},t.prototype.onDestroy=function(t){this._onDestroyFns.push(t)},t.prototype.hasStarted=function(){return this._started},t.prototype.play=function(){this.parentPlayer||this.init(),this._onStart(),this.players.forEach(function(t){return t.play()})},t.prototype.pause=function(){this.players.forEach(function(t){return t.pause()})},t.prototype.restart=function(){this.players.forEach(function(t){return t.restart()})},t.prototype.finish=function(){this._onFinish(),this.players.forEach(function(t){return t.finish()})},t.prototype.destroy=function(){this._onDestroy()},t.prototype._onDestroy=function(){this._destroyed||(this._destroyed=!0,this._onFinish(),this.players.forEach(function(t){return t.destroy()}),this._onDestroyFns.forEach(function(t){return t()}),this._onDestroyFns=[])},t.prototype.reset=function(){this.players.forEach(function(t){return t.reset()}),this._destroyed=!1,this._finished=!1,this._started=!1},t.prototype.setPosition=function(t){var e=t*this.totalTime;this.players.forEach(function(t){var n=t.totalTime?Math.min(1,e/t.totalTime):1;t.setPosition(n)})},t.prototype.getPosition=function(){var t=0;return this.players.forEach(function(e){var n=e.getPosition();t=Math.min(n,t)}),t},t.prototype.beforeDestroy=function(){this.players.forEach(function(t){t.beforeDestroy&&t.beforeDestroy()})},t.prototype.triggerCallback=function(t){var e="start"==t?this._onStartFns:this._onDoneFns;e.forEach(function(t){return t()}),e.length=0},t}(),g="!"},insk:function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("+0ag"),n("mSOc"),n("20UP");var a=function(){function t(t,e,n,a,r){this.summaryService=t,this.sanitizer=e,this.settingsService=n,this.cephReleaseNamePipe=a,this.i18n=r,this.grafanaExist=!1,this.mode="&kiosk",this.loading=!0,this.styles={},this.dashboardExist=!0,this.DEFAULT_TIME="from=now-1h&to=now",this.grafanaTimes=[{name:this.i18n("Last 5 minutes"),value:"from=now-5m&to=now"},{name:this.i18n("Last 15 minutes"),value:"from=now-15m&to=now"},{name:this.i18n("Last 30 minutes"),value:"from=now-30m&to=now"},{name:this.i18n("Last 1 hour (Default)"),value:"from=now-1h&to=now"},{name:this.i18n("Last 3 hours"),value:"from=now-3h&to=now"},{name:this.i18n("Last 6 hours"),value:"from=now-6h&to=now"},{name:this.i18n("Last 12 hours"),value:"from=now-12h&to=now"},{name:this.i18n("Last 24 hours"),value:"from=now-24h&to=now"},{name:this.i18n("Yesterday"),value:"from=now-1d%2Fd&to=now-1d%2Fd"},{name:this.i18n("Today so far"),value:"from=now%2Fd&to=now"},{name:this.i18n("Day before yesterday"),value:"from=now-2d%2Fd&to=now-2d%2Fd"},{name:this.i18n("Last 2 days"),value:"from=now-2d&to=now"},{name:this.i18n("This day last week"),value:"from=now-7d%2Fd&to=now-7d%2Fd"},{name:this.i18n("Previous week"),value:"from=now-1w%2Fw&to=now-1w%2Fw"},{name:this.i18n("This week so far"),value:"from=now%2Fw&to=now"},{name:this.i18n("Last 7 days"),value:"from=now-7d&to=now"},{name:this.i18n("Previous month"),value:"from=now-1M%2FM&to=now-1M%2FM"},{name:this.i18n("This month so far"),value:"from=now%2FM&to=now"},{name:this.i18n("Last 30 days"),value:"from=now-30d&to=now"},{name:this.i18n("Last 90 days"),value:"from=now-90d&to=now"},{name:this.i18n("Last 6 months"),value:"from=now-6M&to=now"},{name:this.i18n("Last 1 year"),value:"from=now-1y&to=now"},{name:this.i18n("Previous year"),value:"from=now-1y%2Fy&to=now-1y%2Fy"},{name:this.i18n("This year so far"),value:"from=now%2Fy&to=now"},{name:this.i18n("Last 2 years"),value:"from=now-2y&to=now"},{name:this.i18n("Last 5 years"),value:"from=now-5y&to=now"}]}return t.prototype.ngOnInit=function(){var t=this;this.time=this.DEFAULT_TIME,this.styles={one:"grafana_one",two:"grafana_two",three:"grafana_three"};var e=this.summaryService.subscribe(function(n){if(n){var a=t.cephReleaseNamePipe.transform(n.version);t.docsUrl="http://docs.ceph.com/docs/"+a+"/mgr/dashboard/#enabling-the-embedding-of-grafana-dashboards",setTimeout(function(){e.unsubscribe()},0)}});this.settingsService.ifSettingConfigured("api/grafana/url",function(e){t.grafanaExist=!0,t.loading=!1,t.baseUrl=e+"/d/",t.getFrame()}),this.panelStyle=this.styles[this.grafanaStyle]},t.prototype.getFrame=function(){var t=this;this.settingsService.validateGrafanaDashboardUrl(this.uid).subscribe(function(e){return t.dashboardExist=200===e}),this.url=this.baseUrl+this.uid+"/"+this.grafanaPath+"&refresh=2s"+this.mode+"&"+this.time,this.grafanaSrc=this.sanitizer.bypassSecurityTrustResourceUrl(this.url)},t.prototype.onTimepickerChange=function(){this.grafanaExist&&this.getFrame()},t.prototype.reset=function(){this.time=this.DEFAULT_TIME,this.grafanaExist&&this.getFrame()},t.prototype.ngOnChanges=function(){this.grafanaExist&&this.getFrame()},t}()},isby:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=Array.isArray||function(t){return t&&"number"==typeof t.length}},iutN:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("CcnG"),r=n("xtZt"),i=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function s(t){return a["\u0275vid"](2,[(t()(),a["\u0275eld"](0,0,null,null,1,"div",[],[[2,"dropup",null],[2,"dropdown",null],[2,"show",null],[2,"open",null]],null,null,null,null)),a["\u0275ncd"](null,0)],null,function(t,e){var n=e.component;t(e,0,0,"up"===n.direction,"down"===n.direction,n.isOpen,n.isOpen)})}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"bs-dropdown-container",[["style","display:block;position: absolute;"]],null,null,null,s,i)),a["\u0275did"](1,180224,null,0,r.b,[r.f,a.ChangeDetectorRef,a.Renderer2,a.ElementRef],null,null)],null,null)}var u=a["\u0275ccf"]("bs-dropdown-container",r.b,o,{},{},["*"])},j8L6:function(t,e,n){"use strict";var a=n("CcnG"),r=n("25BL"),i=n("uIqm"),s=n("xbqr"),o=n("9GXa"),u=n("o4+5"),c=n("aXbf"),l=n("Ip0R");n("b5OY"),n("pxLl"),n("Jm/i"),n.d(e,"a",function(){return d}),n.d(e,"b",function(){return g});var d=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function f(t){return a["\u0275vid"](0,[(t()(),a["\u0275ted"](0,null,[" "," "," "])),a["\u0275ppd"](1,1)],null,function(t,e){var n=a["\u0275unv"](e,0,0,t(e,1,0,a["\u0275nov"](e.parent.parent,0),e.context.row.value));t(e,0,0,n,e.context.row.unit)})}function p(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"cd-table",[["columnMode","flex"]],null,[[null,"fetchData"]],function(t,e,n){var a=!0;return"fetchData"===e&&(a=!1!==t.component.getCounters(n)&&a),a},r.b,r.a)),a["\u0275did"](1,2867200,null,0,i.a,[a.NgZone,a.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoSave:[3,"autoSave"]},{fetchData:"fetchData"}),(t()(),a["\u0275and"](0,[[1,2],["valueTpl",2]],null,0,null,f))],function(t,e){var n=e.component;t(e,1,0,n.counters,n.columns,"flex",!1)},null)}function h(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"cd-warning-panel",[],null,null,null,s.b,s.a)),a["\u0275did"](1,49152,null,0,o.a,[],null,null),(t()(),a["\u0275ted"](-1,0,["Performance counters not available"]))],null,null)}function g(t){return a["\u0275vid"](0,[a["\u0275pid"](0,u.a,[c.a]),a["\u0275qud"](671088640,1,{valueTpl:0}),(t()(),a["\u0275and"](16777216,null,null,1,null,p)),a["\u0275did"](3,16384,null,0,l.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),a["\u0275and"](0,[["warning",2]],null,0,null,h))],function(t,e){t(e,3,0,e.component.counters,a["\u0275nov"](e,4))},null)}},jFaF:function(t,e,n){"use strict";function a(t,e){function n(){return!n.pred.apply(n.thisArg,arguments)}return n.pred=t,n.thisArg=e,n}n.d(e,"a",function(){return a})},"jKX/":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=function(){return function(t){void 0===t&&(t=[]);var e=this;["read","create","update","delete"].forEach(function(n){return e[n]=t.includes(n)})}}(),r=function(){return function(t){this.hosts=new a(t.hosts),this.configOpt=new a(t["config-opt"]),this.pool=new a(t.pool),this.osd=new a(t.osd),this.monitor=new a(t.monitor),this.rbdImage=new a(t["rbd-image"]),this.iscsi=new a(t.iscsi),this.rbdMirroring=new a(t["rbd-mirroring"]),this.rgw=new a(t.rgw),this.cephfs=new a(t.cephfs),this.manager=new a(t.manager),this.log=new a(t.log),this.user=new a(t.user),this.grafana=new a(t.grafana),this.prometheus=new a(t.prometheus),this.nfs=new a(t["nfs-ganesha"])}}()},jUeY:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("el",{monthsNominativeEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u039c\u03ac\u03c1\u03c4\u03b9\u03bf\u03c2_\u0391\u03c0\u03c1\u03af\u03bb\u03b9\u03bf\u03c2_\u039c\u03ac\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bd\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bb\u03b9\u03bf\u03c2_\u0391\u03cd\u03b3\u03bf\u03c5\u03c3\u03c4\u03bf\u03c2_\u03a3\u03b5\u03c0\u03c4\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u039f\u03ba\u03c4\u03ce\u03b2\u03c1\u03b9\u03bf\u03c2_\u039d\u03bf\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u0394\u03b5\u03ba\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2".split("_"),monthsGenitiveEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5_\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5_\u039c\u03b1\u0390\u03bf\u03c5_\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5_\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5_\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5_\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5_\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5".split("_"),months:function(t,e){return t?"string"==typeof e&&/D/.test(e.substring(0,e.indexOf("MMMM")))?this._monthsGenitiveEl[t.month()]:this._monthsNominativeEl[t.month()]:this._monthsNominativeEl},monthsShort:"\u0399\u03b1\u03bd_\u03a6\u03b5\u03b2_\u039c\u03b1\u03c1_\u0391\u03c0\u03c1_\u039c\u03b1\u03ca_\u0399\u03bf\u03c5\u03bd_\u0399\u03bf\u03c5\u03bb_\u0391\u03c5\u03b3_\u03a3\u03b5\u03c0_\u039f\u03ba\u03c4_\u039d\u03bf\u03b5_\u0394\u03b5\u03ba".split("_"),weekdays:"\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae_\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1_\u03a4\u03c1\u03af\u03c4\u03b7_\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7_\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7_\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae_\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf".split("_"),weekdaysShort:"\u039a\u03c5\u03c1_\u0394\u03b5\u03c5_\u03a4\u03c1\u03b9_\u03a4\u03b5\u03c4_\u03a0\u03b5\u03bc_\u03a0\u03b1\u03c1_\u03a3\u03b1\u03b2".split("_"),weekdaysMin:"\u039a\u03c5_\u0394\u03b5_\u03a4\u03c1_\u03a4\u03b5_\u03a0\u03b5_\u03a0\u03b1_\u03a3\u03b1".split("_"),meridiem:function(t,e,n){return t>11?n?"\u03bc\u03bc":"\u039c\u039c":n?"\u03c0\u03bc":"\u03a0\u039c"},isPM:function(t){return"\u03bc"===(t+"").toLowerCase()[0]},meridiemParse:/[\u03a0\u039c]\.?\u039c?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[\u03a3\u03ae\u03bc\u03b5\u03c1\u03b1 {}] LT",nextDay:"[\u0391\u03cd\u03c1\u03b9\u03bf {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[\u03a7\u03b8\u03b5\u03c2 {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[\u03c4\u03bf \u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf] dddd [{}] LT";default:return"[\u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03b7] dddd [{}] LT"}},sameElse:"L"},calendar:function(t,e){var n,a=this._calendarEl[t],r=e&&e.hours();return((n=a)instanceof Function||"[object Function]"===Object.prototype.toString.call(n))&&(a=a.apply(e)),a.replace("{}",r%12==1?"\u03c3\u03c4\u03b7":"\u03c3\u03c4\u03b9\u03c2")},relativeTime:{future:"\u03c3\u03b5 %s",past:"%s \u03c0\u03c1\u03b9\u03bd",s:"\u03bb\u03af\u03b3\u03b1 \u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1",ss:"%d \u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1",m:"\u03ad\u03bd\u03b1 \u03bb\u03b5\u03c0\u03c4\u03cc",mm:"%d \u03bb\u03b5\u03c0\u03c4\u03ac",h:"\u03bc\u03af\u03b1 \u03ce\u03c1\u03b1",hh:"%d \u03ce\u03c1\u03b5\u03c2",d:"\u03bc\u03af\u03b1 \u03bc\u03ad\u03c1\u03b1",dd:"%d \u03bc\u03ad\u03c1\u03b5\u03c2",M:"\u03ad\u03bd\u03b1\u03c2 \u03bc\u03ae\u03bd\u03b1\u03c2",MM:"%d \u03bc\u03ae\u03bd\u03b5\u03c2",y:"\u03ad\u03bd\u03b1\u03c2 \u03c7\u03c1\u03cc\u03bd\u03bf\u03c2",yy:"%d \u03c7\u03c1\u03cc\u03bd\u03b9\u03b1"},dayOfMonthOrdinalParse:/\d{1,2}\u03b7/,ordinal:"%d\u03b7",week:{dow:1,doy:4}})}()},jVdC:function(t,e,n){!function(t){"use strict";var e="stycze\u0144_luty_marzec_kwiecie\u0144_maj_czerwiec_lipiec_sierpie\u0144_wrzesie\u0144_pa\u017adziernik_listopad_grudzie\u0144".split("_"),n="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_wrze\u015bnia_pa\u017adziernika_listopada_grudnia".split("_");function a(t){return t%10<5&&t%10>1&&~~(t/10)%10!=1}function r(t,e,n){var r=t+" ";switch(n){case"ss":return r+(a(t)?"sekundy":"sekund");case"m":return e?"minuta":"minut\u0119";case"mm":return r+(a(t)?"minuty":"minut");case"h":return e?"godzina":"godzin\u0119";case"hh":return r+(a(t)?"godziny":"godzin");case"MM":return r+(a(t)?"miesi\u0105ce":"miesi\u0119cy");case"yy":return r+(a(t)?"lata":"lat")}}t.defineLocale("pl",{months:function(t,a){return t?""===a?"("+n[t.month()]+"|"+e[t.month()]+")":/D MMMM/.test(a)?n[t.month()]:e[t.month()]:e},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_pa\u017a_lis_gru".split("_"),weekdays:"niedziela_poniedzia\u0142ek_wtorek_\u015broda_czwartek_pi\u0105tek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_\u015br_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_\u015ar_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dzi\u015b o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedziel\u0119 o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W \u015brod\u0119 o] LT";case 6:return"[W sobot\u0119 o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zesz\u0142\u0105 niedziel\u0119 o] LT";case 3:return"[W zesz\u0142\u0105 \u015brod\u0119 o] LT";case 6:return"[W zesz\u0142\u0105 sobot\u0119 o] LT";default:return"[W zesz\u0142y] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:r,m:r,mm:r,h:r,hh:r,d:"1 dzie\u0144",dd:"%d dni",M:"miesi\u0105c",MM:r,y:"rok",yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},jXIB:function(t,e,n){"use strict";t.exports={},t.exports.filler=n("vpM6"),t.exports.legend=n("AX6q"),t.exports.title=n("mjYD")},jfSC:function(t,e,n){!function(t){"use strict";var e={1:"\u06f1",2:"\u06f2",3:"\u06f3",4:"\u06f4",5:"\u06f5",6:"\u06f6",7:"\u06f7",8:"\u06f8",9:"\u06f9",0:"\u06f0"},n={"\u06f1":"1","\u06f2":"2","\u06f3":"3","\u06f4":"4","\u06f5":"5","\u06f6":"6","\u06f7":"7","\u06f8":"8","\u06f9":"9","\u06f0":"0"};t.defineLocale("fa",{months:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),monthsShort:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),weekdays:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysShort:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysMin:"\u06cc_\u062f_\u0633_\u0686_\u067e_\u062c_\u0634".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/\u0642\u0628\u0644 \u0627\u0632 \u0638\u0647\u0631|\u0628\u0639\u062f \u0627\u0632 \u0638\u0647\u0631/,isPM:function(t){return/\u0628\u0639\u062f \u0627\u0632 \u0638\u0647\u0631/.test(t)},meridiem:function(t,e,n){return t<12?"\u0642\u0628\u0644 \u0627\u0632 \u0638\u0647\u0631":"\u0628\u0639\u062f \u0627\u0632 \u0638\u0647\u0631"},calendar:{sameDay:"[\u0627\u0645\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",nextDay:"[\u0641\u0631\u062f\u0627 \u0633\u0627\u0639\u062a] LT",nextWeek:"dddd [\u0633\u0627\u0639\u062a] LT",lastDay:"[\u062f\u06cc\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",lastWeek:"dddd [\u067e\u06cc\u0634] [\u0633\u0627\u0639\u062a] LT",sameElse:"L"},relativeTime:{future:"\u062f\u0631 %s",past:"%s \u067e\u06cc\u0634",s:"\u0686\u0646\u062f \u062b\u0627\u0646\u06cc\u0647",ss:"\u062b\u0627\u0646\u06cc\u0647 d%",m:"\u06cc\u06a9 \u062f\u0642\u06cc\u0642\u0647",mm:"%d \u062f\u0642\u06cc\u0642\u0647",h:"\u06cc\u06a9 \u0633\u0627\u0639\u062a",hh:"%d \u0633\u0627\u0639\u062a",d:"\u06cc\u06a9 \u0631\u0648\u0632",dd:"%d \u0631\u0648\u0632",M:"\u06cc\u06a9 \u0645\u0627\u0647",MM:"%d \u0645\u0627\u0647",y:"\u06cc\u06a9 \u0633\u0627\u0644",yy:"%d \u0633\u0627\u0644"},preparse:function(t){return t.replace(/[\u06f0-\u06f9]/g,function(t){return n[t]}).replace(/\u060c/g,",")},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]}).replace(/,/g,"\u060c")},dayOfMonthOrdinalParse:/\d{1,2}\u0645/,ordinal:"%d\u0645",week:{dow:6,doy:12}})}(n("wd/R"))},jnO4:function(t,e,n){!function(t){"use strict";var e={1:"\u0661",2:"\u0662",3:"\u0663",4:"\u0664",5:"\u0665",6:"\u0666",7:"\u0667",8:"\u0668",9:"\u0669",0:"\u0660"},n={"\u0661":"1","\u0662":"2","\u0663":"3","\u0664":"4","\u0665":"5","\u0666":"6","\u0667":"7","\u0668":"8","\u0669":"9","\u0660":"0"},a=function(t){return 0===t?0:1===t?1:2===t?2:t%100>=3&&t%100<=10?3:t%100>=11?4:5},r={s:["\u0623\u0642\u0644 \u0645\u0646 \u062b\u0627\u0646\u064a\u0629","\u062b\u0627\u0646\u064a\u0629 \u0648\u0627\u062d\u062f\u0629",["\u062b\u0627\u0646\u064a\u062a\u0627\u0646","\u062b\u0627\u0646\u064a\u062a\u064a\u0646"],"%d \u062b\u0648\u0627\u0646","%d \u062b\u0627\u0646\u064a\u0629","%d \u062b\u0627\u0646\u064a\u0629"],m:["\u0623\u0642\u0644 \u0645\u0646 \u062f\u0642\u064a\u0642\u0629","\u062f\u0642\u064a\u0642\u0629 \u0648\u0627\u062d\u062f\u0629",["\u062f\u0642\u064a\u0642\u062a\u0627\u0646","\u062f\u0642\u064a\u0642\u062a\u064a\u0646"],"%d \u062f\u0642\u0627\u0626\u0642","%d \u062f\u0642\u064a\u0642\u0629","%d \u062f\u0642\u064a\u0642\u0629"],h:["\u0623\u0642\u0644 \u0645\u0646 \u0633\u0627\u0639\u0629","\u0633\u0627\u0639\u0629 \u0648\u0627\u062d\u062f\u0629",["\u0633\u0627\u0639\u062a\u0627\u0646","\u0633\u0627\u0639\u062a\u064a\u0646"],"%d \u0633\u0627\u0639\u0627\u062a","%d \u0633\u0627\u0639\u0629","%d \u0633\u0627\u0639\u0629"],d:["\u0623\u0642\u0644 \u0645\u0646 \u064a\u0648\u0645","\u064a\u0648\u0645 \u0648\u0627\u062d\u062f",["\u064a\u0648\u0645\u0627\u0646","\u064a\u0648\u0645\u064a\u0646"],"%d \u0623\u064a\u0627\u0645","%d \u064a\u0648\u0645\u064b\u0627","%d \u064a\u0648\u0645"],M:["\u0623\u0642\u0644 \u0645\u0646 \u0634\u0647\u0631","\u0634\u0647\u0631 \u0648\u0627\u062d\u062f",["\u0634\u0647\u0631\u0627\u0646","\u0634\u0647\u0631\u064a\u0646"],"%d \u0623\u0634\u0647\u0631","%d \u0634\u0647\u0631\u0627","%d \u0634\u0647\u0631"],y:["\u0623\u0642\u0644 \u0645\u0646 \u0639\u0627\u0645","\u0639\u0627\u0645 \u0648\u0627\u062d\u062f",["\u0639\u0627\u0645\u0627\u0646","\u0639\u0627\u0645\u064a\u0646"],"%d \u0623\u0639\u0648\u0627\u0645","%d \u0639\u0627\u0645\u064b\u0627","%d \u0639\u0627\u0645"]},i=function(t){return function(e,n,i,s){var o=a(e),u=r[t][a(e)];return 2===o&&(u=u[n?0:1]),u.replace(/%d/i,e)}},s=["\u064a\u0646\u0627\u064a\u0631","\u0641\u0628\u0631\u0627\u064a\u0631","\u0645\u0627\u0631\u0633","\u0623\u0628\u0631\u064a\u0644","\u0645\u0627\u064a\u0648","\u064a\u0648\u0646\u064a\u0648","\u064a\u0648\u0644\u064a\u0648","\u0623\u063a\u0633\u0637\u0633","\u0633\u0628\u062a\u0645\u0628\u0631","\u0623\u0643\u062a\u0648\u0628\u0631","\u0646\u0648\u0641\u0645\u0628\u0631","\u062f\u064a\u0633\u0645\u0628\u0631"];t.defineLocale("ar",{months:s,monthsShort:s,weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0623\u062d\u062f_\u0625\u062b\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0623\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/\u200fM/\u200fYYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/\u0635|\u0645/,isPM:function(t){return"\u0645"===t},meridiem:function(t,e,n){return t<12?"\u0635":"\u0645"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u064b\u0627 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0646\u062f \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0628\u0639\u062f %s",past:"\u0645\u0646\u0630 %s",s:i("s"),ss:i("s"),m:i("m"),mm:i("m"),h:i("h"),hh:i("h"),d:i("d"),dd:i("d"),M:i("M"),MM:i("M"),y:i("y"),yy:i("y")},preparse:function(t){return t.replace(/[\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660]/g,function(t){return n[t]}).replace(/\u060c/g,",")},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]}).replace(/,/g,"\u060c")},week:{dow:6,doy:12}})}(n("wd/R"))},jvuA:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("UReH");e.DatatableRowDetailDirective=function(){function t(){this.rowHeight=0,this.toggle=new i.EventEmitter}return t.prototype.toggleExpandRow=function(t){this.toggle.emit({type:"row",value:t})},t.prototype.expandAllRows=function(){this.toggle.emit({type:"all",value:!0})},t.prototype.collapseAllRows=function(){this.toggle.emit({type:"all",value:!1})},a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),i.ContentChild(s.DatatableRowDetailTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"toggle",void 0),a([i.Directive({selector:"ngx-datatable-row-detail"})],t)}()},kEOa:function(t,e,n){!function(t){"use strict";var e={1:"\u09e7",2:"\u09e8",3:"\u09e9",4:"\u09ea",5:"\u09eb",6:"\u09ec",7:"\u09ed",8:"\u09ee",9:"\u09ef",0:"\u09e6"},n={"\u09e7":"1","\u09e8":"2","\u09e9":"3","\u09ea":"4","\u09eb":"5","\u09ec":"6","\u09ed":"7","\u09ee":"8","\u09ef":"9","\u09e6":"0"};t.defineLocale("bn",{months:"\u099c\u09be\u09a8\u09c1\u09df\u09be\u09b0\u09c0_\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09df\u09be\u09b0\u09bf_\u09ae\u09be\u09b0\u09cd\u099a_\u098f\u09aa\u09cd\u09b0\u09bf\u09b2_\u09ae\u09c7_\u099c\u09c1\u09a8_\u099c\u09c1\u09b2\u09be\u0987_\u0986\u0997\u09b8\u09cd\u099f_\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0_\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0_\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0_\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0".split("_"),monthsShort:"\u099c\u09be\u09a8\u09c1_\u09ab\u09c7\u09ac_\u09ae\u09be\u09b0\u09cd\u099a_\u098f\u09aa\u09cd\u09b0_\u09ae\u09c7_\u099c\u09c1\u09a8_\u099c\u09c1\u09b2_\u0986\u0997_\u09b8\u09c7\u09aa\u09cd\u099f_\u0985\u0995\u09cd\u099f\u09cb_\u09a8\u09ad\u09c7_\u09a1\u09bf\u09b8\u09c7".split("_"),weekdays:"\u09b0\u09ac\u09bf\u09ac\u09be\u09b0_\u09b8\u09cb\u09ae\u09ac\u09be\u09b0_\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09b0_\u09ac\u09c1\u09a7\u09ac\u09be\u09b0_\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0_\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0_\u09b6\u09a8\u09bf\u09ac\u09be\u09b0".split("_"),weekdaysShort:"\u09b0\u09ac\u09bf_\u09b8\u09cb\u09ae_\u09ae\u0999\u09cd\u0997\u09b2_\u09ac\u09c1\u09a7_\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf_\u09b6\u09c1\u0995\u09cd\u09b0_\u09b6\u09a8\u09bf".split("_"),weekdaysMin:"\u09b0\u09ac\u09bf_\u09b8\u09cb\u09ae_\u09ae\u0999\u09cd\u0997_\u09ac\u09c1\u09a7_\u09ac\u09c3\u09b9\u0983_\u09b6\u09c1\u0995\u09cd\u09b0_\u09b6\u09a8\u09bf".split("_"),longDateFormat:{LT:"A h:mm \u09b8\u09ae\u09df",LTS:"A h:mm:ss \u09b8\u09ae\u09df",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm \u09b8\u09ae\u09df",LLLL:"dddd, D MMMM YYYY, A h:mm \u09b8\u09ae\u09df"},calendar:{sameDay:"[\u0986\u099c] LT",nextDay:"[\u0986\u0997\u09be\u09ae\u09c0\u0995\u09be\u09b2] LT",nextWeek:"dddd, LT",lastDay:"[\u0997\u09a4\u0995\u09be\u09b2] LT",lastWeek:"[\u0997\u09a4] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u09aa\u09b0\u09c7",past:"%s \u0986\u0997\u09c7",s:"\u0995\u09df\u09c7\u0995 \u09b8\u09c7\u0995\u09c7\u09a8\u09cd\u09a1",ss:"%d \u09b8\u09c7\u0995\u09c7\u09a8\u09cd\u09a1",m:"\u098f\u0995 \u09ae\u09bf\u09a8\u09bf\u099f",mm:"%d \u09ae\u09bf\u09a8\u09bf\u099f",h:"\u098f\u0995 \u0998\u09a8\u09cd\u099f\u09be",hh:"%d \u0998\u09a8\u09cd\u099f\u09be",d:"\u098f\u0995 \u09a6\u09bf\u09a8",dd:"%d \u09a6\u09bf\u09a8",M:"\u098f\u0995 \u09ae\u09be\u09b8",MM:"%d \u09ae\u09be\u09b8",y:"\u098f\u0995 \u09ac\u099b\u09b0",yy:"%d \u09ac\u099b\u09b0"},preparse:function(t){return t.replace(/[\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ee\u09ef\u09e6]/g,function(t){return n[t]})},postformat:function(t){return t.replace(/\d/g,function(t){return e[t]})},meridiemParse:/\u09b0\u09be\u09a4|\u09b8\u0995\u09be\u09b2|\u09a6\u09c1\u09aa\u09c1\u09b0|\u09ac\u09bf\u0995\u09be\u09b2|\u09b0\u09be\u09a4/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u09b0\u09be\u09a4"===e&&t>=4||"\u09a6\u09c1\u09aa\u09c1\u09b0"===e&&t<5||"\u09ac\u09bf\u0995\u09be\u09b2"===e?t+12:t},meridiem:function(t,e,n){return t<4?"\u09b0\u09be\u09a4":t<10?"\u09b8\u0995\u09be\u09b2":t<17?"\u09a6\u09c1\u09aa\u09c1\u09b0":t<20?"\u09ac\u09bf\u0995\u09be\u09b2":"\u09b0\u09be\u09a4"},week:{dow:0,doy:6}})}(n("wd/R"))},kJI8:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},kOpN:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("zh-tw",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u9031\u65e5_\u9031\u4e00_\u9031\u4e8c_\u9031\u4e09_\u9031\u56db_\u9031\u4e94_\u9031\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5 HH:mm",LLLL:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm",l:"YYYY/M/D",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm"},meridiemParse:/\u51cc\u6668|\u65e9\u4e0a|\u4e0a\u5348|\u4e2d\u5348|\u4e0b\u5348|\u665a\u4e0a/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u51cc\u6668"===e||"\u65e9\u4e0a"===e||"\u4e0a\u5348"===e?t:"\u4e2d\u5348"===e?t>=11?t:t+12:"\u4e0b\u5348"===e||"\u665a\u4e0a"===e?t+12:void 0},meridiem:function(t,e,n){var a=100*t+e;return a<600?"\u51cc\u6668":a<900?"\u65e9\u4e0a":a<1130?"\u4e0a\u5348":a<1230?"\u4e2d\u5348":a<1800?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929] LT",nextDay:"[\u660e\u5929] LT",nextWeek:"[\u4e0b]dddd LT",lastDay:"[\u6628\u5929] LT",lastWeek:"[\u4e0a]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(\u65e5|\u6708|\u9031)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\u65e5";case"M":return t+"\u6708";case"w":case"W":return t+"\u9031";default:return t}},relativeTime:{future:"%s\u5167",past:"%s\u524d",s:"\u5e7e\u79d2",ss:"%d \u79d2",m:"1 \u5206\u9418",mm:"%d \u5206\u9418",h:"1 \u5c0f\u6642",hh:"%d \u5c0f\u6642",d:"1 \u5929",dd:"%d \u5929",M:"1 \u500b\u6708",MM:"%d \u500b\u6708",y:"1 \u5e74",yy:"%d \u5e74"}})}()},kQXf:function(t,e,n){"use strict";function a(t){return"string"==typeof t?!/\S/.test(t):Array.isArray(t)?0===t.length:i(t)}function r(t,e){return!i(t)&&t.indexOf(e)>-1}function i(t){return null==t}Object.defineProperty(e,"__esModule",{value:!0}),e.isEmpty=a,e.trim=function(t){return i(t)?"":t.trim()},e.has=function(t,e){return t&&"object"==typeof t&&t.hasOwnProperty(e)},e.isFunction=function(t){return"function"==typeof t},e.get=function(t,e,n){for(var a=t,r=0,s=e.split(".");r<s.length;r++){var o=s[r];if(!a||!Reflect.has(a,o))return n;a=a[o]}return i(a)||a===t?n:a},e.omit=function(t,e){if(!t)return t;var n="string"==typeof e?[e]:e;return Object.keys(t).reduce(function(e,a){return r(n,a)?e:Object.assign(e,((i={})[a]=t[a],i));var i},{})},e.size=function(t){return a(t)?0:t.length},e.once=function(t){var e;return function(){for(var n=[],a=0;a<arguments.length;a++)n[a]=arguments[a];return t&&(e=t.apply(null,n),t=null),e}},e.defaultsDeep=function t(e){for(var n=[],a=1;a<arguments.length;a++)n[a-1]=arguments[a];return[e].concat(n).reduce(function(e,n){return n?(Object.keys(n).forEach(function(a){i(e[a])?e[a]=n[a]:"object"!=typeof e[a]||Array.isArray(e[a])||(e[a]=t(e[a],n[a]))}),e):e},{})},e.includes=r,e.isNil=i},klSw:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("S5bw");function r(t,e,n){var r;return r=t&&"object"==typeof t?t:{bufferSize:t,windowTime:e,refCount:!1,scheduler:n},function(t){return t.lift((o=void 0===(s=(e=r).bufferSize)?Number.POSITIVE_INFINITY:s,c=void 0===(u=e.windowTime)?Number.POSITIVE_INFINITY:u,l=e.refCount,d=e.scheduler,f=0,p=!1,h=!1,function(t){f++,n&&!p||(p=!1,n=new a.a(o,c,d),i=t.subscribe({next:function(t){n.next(t)},error:function(t){p=!0,n.error(t)},complete:function(){h=!0,n.complete()}}));var e=n.subscribe(this);this.add(function(){f--,e.unsubscribe(),i&&!h&&l&&0===f&&(i.unsubscribe(),i=void 0,n=void 0)})}));var e,n,i,s,o,u,c,l,d,f,p,h}}},"kn/O":function(t,e,n){"use strict";n.d(e,"a",function(){return d});var a=n("6blF"),r=n("mtw6"),i=n("QTAa"),s=n("9nlD"),o=n("mSOc"),u=n("VXsX"),c=n("ufoC"),l=n("CcnG"),d=function(){function t(t,e,n,a){this.notificationService=t,this.summaryService=e,this.taskMessageService=n,this.taskManagerService=a}return t.prototype.wrapTaskAroundCall=function(t){var e=this,n=t.task,r=t.call;return new a.a(function(t){r.subscribe(function(t){202===t.status?e._handleExecutingTasks(n):(e.summaryService.refresh(),n.success=!0,e.notificationService.notifyTask(n))},function(e){n.success=!1,n.exception=e.error,t.error(e)},function(){t.complete()})})},t.prototype._handleExecutingTasks=function(t){var e=this;this.notificationService.show(r.a.info,this.taskMessageService.getRunningTitle(t));var n=new i.a(t.name,t.metadata);this.summaryService.addRunningTask(n),this.taskManagerService.subscribe(n.name,n.metadata,function(t){e.notificationService.notifyTask(t)})},t.ngInjectableDef=l.defineInjectable({factory:function(){return new t(l.inject(s.a),l.inject(o.a),l.inject(c.a),l.inject(u.a))},token:t,providedIn:"root"}),t}()},kvvV:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e}(n("t/zF").a)},l5ep:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn \xf4l",s:"ychydig eiliadau",ss:"%d eiliad",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},dayOfMonthOrdinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,ordinal:function(t){var e="";return t>20?e=40===t||50===t||60===t||80===t||100===t?"fed":"ain":t>0&&(e=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"][t]),t+e},week:{dow:1,doy:4}})}()},lHUG:function(t,e,n){"use strict";function a(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function r(t){return"string"==typeof t}function i(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function s(t){return t&&t.getTime&&!isNaN(t.getTime())}function o(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function u(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function c(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function l(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function d(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function f(t){return void 0===t}function p(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=a(e)),n}n.d(e,"a",function(){return sn}),n.d(e,"b",function(){return un}),n.d(e,"c",function(){return oe}),n.d(e,"d",function(){return At}),n.d(e,"e",function(){return pn}),n.d(e,"f",function(){return Ne}),n.d(e,"g",function(){return hn}),n.d(e,"h",function(){return j}),n.d(e,"i",function(){return Y}),n.d(e,"j",function(){return G}),n.d(e,"k",function(){return ue}),n.d(e,"l",function(){return z}),n.d(e,"m",function(){return gn}),n.d(e,"n",function(){return Fe}),n.d(e,"o",function(){return c}),n.d(e,"p",function(){return ze}),n.d(e,"q",function(){return i}),n.d(e,"r",function(){return s}),n.d(e,"s",function(){return Ge}),n.d(e,"t",function(){return V}),n.d(e,"u",function(){return Ye}),n.d(e,"v",function(){return U}),n.d(e,"w",function(){return H}),n.d(e,"x",function(){return B}),n.d(e,"y",function(){return bn}),n.d(e,"z",function(){return mn}),n.d(e,"A",function(){return yn}),n.d(e,"B",function(){return qe}),n.d(e,"C",function(){return wn}),n.d(e,"D",function(){return Sn}),n.d(e,"E",function(){return Ot}),n.d(e,"F",function(){return St}),n.d(e,"G",function(){return Rt}),n.d(e,"H",function(){return On});var h={},g={date:"day",hour:"hours",minute:"minutes",second:"seconds",millisecond:"milliseconds"};function b(t,e){var n=t.toLowerCase(),a=t;n in g&&(a=g[n]),h[n]=h[n+"s"]=h[e]=a}function m(t){return r(t)?h[t]||h[t.toLowerCase()]:void 0}var y=0,v=1,_=2,x=3,T=4,w=5,S=6,O=7,I=8;function C(t,e,n){var a=""+Math.abs(t);return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,e-a.length)).toString().substr(1)+a}var k={},N={},R=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;function A(t,e,n,a){t&&(N[t]=a),e&&(N[e[0]]=function(){return C(a.apply(null,arguments),e[1],e[2])}),n&&(N[n]=function(e,n){return n.locale.ordinal(a.apply(null,arguments),t)})}function D(t,e,n){var a=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(a.getUTCFullYear())&&a.setUTCFullYear(t),a}function E(t,e,n,a,r,i,s){void 0===e&&(e=0),void 0===n&&(n=1),void 0===a&&(a=0),void 0===r&&(r=0),void 0===i&&(i=0),void 0===s&&(s=0);var o=new Date(t,e,n,a,r,i,s);return t<100&&t>=0&&isFinite(o.getFullYear())&&o.setFullYear(t),o}function L(t,e){return void 0===e&&(e=!1),e?t.getUTCHours():t.getHours()}function P(t,e){return void 0===e&&(e=!1),e?t.getUTCMinutes():t.getMinutes()}function M(t,e){return void 0===e&&(e=!1),e?t.getUTCSeconds():t.getSeconds()}function q(t,e){return void 0===e&&(e=!1),e?t.getUTCMilliseconds():t.getMilliseconds()}function j(t,e){return void 0===e&&(e=!1),e?t.getUTCDay():t.getDay()}function F(t,e){return void 0===e&&(e=!1),e?t.getUTCDate():t.getDate()}function z(t,e){return void 0===e&&(e=!1),e?t.getUTCMonth():t.getMonth()}function G(t,e){return void 0===e&&(e=!1),e?t.getUTCFullYear():t.getFullYear()}function Y(t){return E(t.getFullYear(),t.getMonth(),1,t.getHours(),t.getMinutes(),t.getSeconds())}function V(t,e){return t.getDay()===e}function H(t,e){return!(!t||!e)&&B(t,e)&&z(t)===z(e)}function B(t,e){return!(!t||!e)&&G(t)===G(e)}function U(t,e){return!(!t||!e)&&B(t,e)&&H(t,e)&&F(t)===F(e)}var W=/\d/,K=/\d\d/,$=/\d{3}/,Z=/\d{4}/,X=/[+-]?\d{6}/,J=/\d\d?/,Q=/\d\d\d\d?/,tt=/\d\d\d\d\d\d?/,et=/\d{1,3}/,nt=/\d{1,4}/,at=/[+-]?\d{1,6}/,rt=/\d+/,it=/[+-]?\d+/,st=/Z|[+-]\d\d(?::?\d\d)?/gi,ot=/[+-]?\d+(\.\d{1,3})?/,ut=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,ct={};function lt(t,e,n){ct[t]=o(e)?e:function(t,a){return t&&n?n:e}}function dt(t,e){return l(ct,t)?ct[t](!1,e):new RegExp(ft(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,a,r){return e||n||a||r})))}function ft(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var pt={};function ht(t,e){var n=r(t)?[t]:t,a=e;if(u(e)&&(a=function(t,n,a){return n[e]=p(t),a}),c(n)&&o(a)){var i=void 0;for(i=0;i<n.length;i++)pt[n[i]]=a}}function gt(t,e){ht(t,function(t,n,a,r){return a._w=a._w||{},e(t,a._w,a,r)})}function bt(t,e,n){return null!=e&&l(pt,t)&&pt[t](e,n._a,n,t),n}function mt(t){return null==t._pf&&(t._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),t._pf}function yt(t,e){return G(t,e.isUTC).toString()}function vt(t){return p(t)+(p(t)>68?1900:2e3)}function _t(t){return xt(t)?366:365}function xt(t){return t%4==0&&t%100!=0||t%400==0}function Tt(t,e){if(isNaN(t)||isNaN(e))return NaN;var n=(e%12+12)%12;return 1===n?xt(t+(e-n)/12)?29:28:31-n%7%2}var wt={year:0,month:0,day:0,hour:0,minute:0,seconds:0};function St(t,e){var n=Object.assign({},wt,e),a=t.getFullYear()+(n.year||0),r=t.getMonth()+(n.month||0),i=t.getDate()+(n.day||0);return n.month&&!n.day&&(i=Math.min(i,Tt(a,r))),E(a,r,i,t.getHours()+(n.hour||0),t.getMinutes()+(n.minute||0),t.getSeconds()+(n.seconds||0))}function Ot(t,e){return E(It(t.getFullYear(),e.year),It(t.getMonth(),e.month),It(t.getDate(),e.day),It(t.getHours(),e.hour),It(t.getMinutes(),e.minute),It(t.getSeconds(),e.seconds),It(t.getMilliseconds(),e.milliseconds))}function It(t,e){return u(e)?e:t}function Ct(t,e,n){var a=Math.min(F(t),Tt(G(t),e));return n?t.setUTCMonth(e,a):t.setMonth(e,a),t}function kt(t,e,n){return n?t.setUTCDate(e):t.setDate(e),t}function Nt(t){return new Date(t.getTime())}function Rt(t,e,n){var a,i=Nt(t);switch(e){case"year":Ct(i,0,n);case"quarter":case"month":kt(i,1,n);case"week":case"isoWeek":case"day":case"date":!function(t,e,n){n?t.setUTCHours(0):t.setHours(0)}(i,0,n);case"hours":!function(t,e,n){n?t.setUTCMinutes(0):t.setMinutes(0)}(i,0,n);case"minutes":!function(t,e,n){n?t.setUTCSeconds(0):t.setSeconds(0)}(i,0,n);case"seconds":!function(t,e,n){n?t.setUTCMilliseconds(0):t.setMilliseconds(0)}(i,0,n)}return"week"===e&&(void 0===(a={isUTC:n})&&(a={}),Ke(i,0-Je(i,a.locale,a.isUTC),"day")),"isoWeek"===e&&function(t,e,n){void 0===n&&(n={});var a,i=(void 0===(a=n.locale)&&(a=ue()),r(1)?a.weekdaysParse(1)%7||7:u(1)&&isNaN(1)?null:1);Ze(t,Xe(t)%7?i:i-7)}(i),"quarter"===e&&Ct(i,3*Math.floor(z(i,n)/3),n),i}function At(t,e,n){var a=e;return"date"===a&&(a="day"),function(t,e,n,a){return $e(t,Be(1,"milliseconds"),-1,a)}(Ke(Rt(t,a,n),1,"isoWeek"===a?"week":a,n),0,0,n)}function Dt(t,e){var n=+Rt(t,"day",e),a=+Rt(t,"year",e);return Math.round((n-a)/864e5)+1}function Et(t,e,n){var a=e-n+7;return-(D(t,0,a).getUTCDay()-e+7)%7+a-1}function Lt(t,e,n,a){var r,i,s=Et(G(t,a),e,n),o=Math.floor((Dt(t,a)-s-1)/7)+1;return o<1?r=o+Pt(i=G(t,a)-1,e,n):o>Pt(G(t,a),e,n)?(r=o-Pt(G(t,a),e,n),i=G(t,a)+1):(i=G(t,a),r=o),{week:r,year:i}}function Pt(t,e,n){var a=Et(t,e,n),r=Et(t+1,e,n);return(_t(t)-a+r)/7}var Mt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,qt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),jt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Ft="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),zt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Yt={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Vt=ut,Ht=ut,Bt=function(){function t(t){t&&this.set(t)}return t.prototype.set=function(t){var e;for(e in t)if(t.hasOwnProperty(e)){var n=t[e];this[o(n)?e:"_"+e]=n}this._config=t},t.prototype.calendar=function(t,e,n){var a=this._calendar[t]||this._calendar.sameElse;return o(a)?a.call(null,e,n):a},t.prototype.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},Object.defineProperty(t.prototype,"invalidDate",{get:function(){return this._invalidDate},set:function(t){this._invalidDate=t},enumerable:!0,configurable:!0}),t.prototype.ordinal=function(t,e){return this._ordinal.replace("%d",t.toString(10))},t.prototype.preparse=function(t){return t},t.prototype.postformat=function(t){return t},t.prototype.relativeTime=function(t,e,n,a){var r=this._relativeTime[n];return o(r)?r(t,e,n,a):r.replace(/%d/i,t.toString(10))},t.prototype.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return o(n)?n(e):n.replace(/%s/i,e)},t.prototype.months=function(t,e,n){if(void 0===n&&(n=!1),!t)return c(this._months)?this._months:this._months.standalone;if(c(this._months))return this._months[z(t,n)];var a=(this._months.isFormat||Mt).test(e)?"format":"standalone";return this._months[a][z(t,n)]},t.prototype.monthsShort=function(t,e,n){if(void 0===n&&(n=!1),!t)return c(this._monthsShort)?this._monthsShort:this._monthsShort.standalone;if(c(this._monthsShort))return this._monthsShort[z(t,n)];var a=Mt.test(e)?"format":"standalone";return this._monthsShort[a][z(t,n)]},t.prototype.monthsParse=function(t,e,n){var a,r,i;if(this._monthsParseExact)return this.handleMonthStrictParse(t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=new Date(Date.UTC(2e3,i)),n&&!this._longMonthsParse[i]){var s=this.months(a,"",!0).replace(".",""),o=this.monthsShort(a,"",!0).replace(".","");this._longMonthsParse[i]=new RegExp("^"+s+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+o+"$","i")}if(n||this._monthsParse[i]||(r="^"+this.months(a,"",!0)+"|^"+this.monthsShort(a,"",!0),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},t.prototype.monthsRegex=function(t){return this._monthsParseExact?(l(this,"_monthsRegex")||this.computeMonthsParse(),t?this._monthsStrictRegex:this._monthsRegex):(l(this,"_monthsRegex")||(this._monthsRegex=Ht),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},t.prototype.monthsShortRegex=function(t){return this._monthsParseExact?(l(this,"_monthsRegex")||this.computeMonthsParse(),t?this._monthsShortStrictRegex:this._monthsShortRegex):(l(this,"_monthsShortRegex")||(this._monthsShortRegex=Vt),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},t.prototype.week=function(t,e){return Lt(t,this._week.dow,this._week.doy,e).week},t.prototype.firstDayOfWeek=function(){return this._week.dow},t.prototype.firstDayOfYear=function(){return this._week.doy},t.prototype.weekdays=function(t,e,n){if(!t)return c(this._weekdays)?this._weekdays:this._weekdays.standalone;if(c(this._weekdays))return this._weekdays[j(t,n)];var a=this._weekdays.isFormat.test(e)?"format":"standalone";return this._weekdays[a][j(t,n)]},t.prototype.weekdaysMin=function(t,e,n){return t?this._weekdaysMin[j(t,n)]:this._weekdaysMin},t.prototype.weekdaysShort=function(t,e,n){return t?this._weekdaysShort[j(t,n)]:this._weekdaysShort},t.prototype.weekdaysParse=function(t,e,n){var a,r;if(this._weekdaysParseExact)return this.handleWeekStrictParse(t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),a=0;a<7;a++){var i=Ze(new Date(Date.UTC(2e3,1)),a,null,!0);if(n&&!this._fullWeekdaysParse[a]&&(this._fullWeekdaysParse[a]=new RegExp("^"+this.weekdays(i,"",!0).replace(".",".?")+"$","i"),this._shortWeekdaysParse[a]=new RegExp("^"+this.weekdaysShort(i,"",!0).replace(".",".?")+"$","i"),this._minWeekdaysParse[a]=new RegExp("^"+this.weekdaysMin(i,"",!0).replace(".",".?")+"$","i")),this._weekdaysParse[a]||(r="^"+this.weekdays(i,"",!0)+"|^"+this.weekdaysShort(i,"",!0)+"|^"+this.weekdaysMin(i,"",!0),this._weekdaysParse[a]=new RegExp(r.replace(".",""),"i")),!(c(this._fullWeekdaysParse)&&c(this._shortWeekdaysParse)&&c(this._minWeekdaysParse)&&c(this._weekdaysParse)))return;if(n&&"dddd"===e&&this._fullWeekdaysParse[a].test(t))return a;if(n&&"ddd"===e&&this._shortWeekdaysParse[a].test(t))return a;if(n&&"dd"===e&&this._minWeekdaysParse[a].test(t))return a;if(!n&&this._weekdaysParse[a].test(t))return a}},t.prototype.weekdaysRegex=function(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||this.computeWeekdaysParse(),t?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=ut),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},t.prototype.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||this.computeWeekdaysParse(),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=ut),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},t.prototype.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||this.computeWeekdaysParse(),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ut),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},t.prototype.isPM=function(t){return"p"===t.toLowerCase().charAt(0)},t.prototype.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},t.prototype.formatLongDate=function(t){this._longDateFormat=this._longDateFormat?this._longDateFormat:Yt;var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},t.prototype.handleMonthStrictParse=function(t,e,n){var a,r,i,s=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],a=0;a<12;++a)i=new Date(2e3,a),this._shortMonthsParse[a]=this.monthsShort(i,"").toLocaleLowerCase(),this._longMonthsParse[a]=this.months(i,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(r=this._shortMonthsParse.indexOf(s))?r:null:-1!==(r=this._longMonthsParse.indexOf(s))?r:null:"MMM"===e?-1!==(r=this._shortMonthsParse.indexOf(s))?r:-1!==(r=this._longMonthsParse.indexOf(s))?r:null:-1!==(r=this._longMonthsParse.indexOf(s))?r:-1!==(r=this._shortMonthsParse.indexOf(s))?r:null},t.prototype.handleWeekStrictParse=function(t,e,n){var a,r=t.toLocaleLowerCase();if(!this._weekdaysParse){this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[];var i=void 0;for(i=0;i<7;++i){var s=Ze(new Date(Date.UTC(2e3,1)),i,null,!0);this._minWeekdaysParse[i]=this.weekdaysMin(s).toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(s).toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(s,"").toLocaleLowerCase()}}if(c(this._weekdaysParse)&&c(this._shortWeekdaysParse)&&c(this._minWeekdaysParse))return n?"dddd"===e?-1!==(a=this._weekdaysParse.indexOf(r))?a:null:"ddd"===e?-1!==(a=this._shortWeekdaysParse.indexOf(r))?a:null:-1!==(a=this._minWeekdaysParse.indexOf(r))?a:null:"dddd"===e?-1!==(a=this._weekdaysParse.indexOf(r))?a:-1!==(a=this._shortWeekdaysParse.indexOf(r))?a:-1!==(a=this._minWeekdaysParse.indexOf(r))?a:null:"ddd"===e?-1!==(a=this._shortWeekdaysParse.indexOf(r))?a:-1!==(a=this._weekdaysParse.indexOf(r))?a:-1!==(a=this._minWeekdaysParse.indexOf(r))?a:null:-1!==(a=this._minWeekdaysParse.indexOf(r))?a:-1!==(a=this._weekdaysParse.indexOf(r))?a:-1!==(a=this._shortWeekdaysParse.indexOf(r))?a:null},t.prototype.computeMonthsParse=function(){var t,e,n=[],a=[],r=[];for(e=0;e<12;e++)t=new Date(2e3,e),n.push(this.monthsShort(t,"")),a.push(this.months(t,"")),r.push(this.months(t,"")),r.push(this.monthsShort(t,""));for(n.sort(Ut),a.sort(Ut),r.sort(Ut),e=0;e<12;e++)n[e]=ft(n[e]),a[e]=ft(a[e]);for(e=0;e<24;e++)r[e]=ft(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+n.join("|")+")","i")},t.prototype.computeWeekdaysParse=function(){var t,e=[],n=[],a=[],r=[];for(t=0;t<7;t++){var i=Ze(new Date(Date.UTC(2e3,1)),t,null,!0),s=this.weekdaysMin(i),o=this.weekdaysShort(i),u=this.weekdays(i);e.push(s),n.push(o),a.push(u),r.push(s),r.push(o),r.push(u)}for(e.sort(Ut),n.sort(Ut),a.sort(Ut),r.sort(Ut),t=0;t<7;t++)n[t]=ft(n[t]),a[t]=ft(a[t]),r[t]=ft(r[t]);this._weekdaysRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+n.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+e.join("|")+")","i")},t}();function Ut(t,e){return e.length-t.length}var Wt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:Yt,invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:qt,monthsShort:jt,week:{dow:0,doy:6},weekdays:Ft,weekdaysMin:Gt,weekdaysShort:zt,meridiemParse:/[ap]\.?m?\.?/i};function Kt(t,e,n){var a,r=Math.min(t.length,e.length),i=Math.abs(t.length-e.length),s=0;for(a=0;a<r;a++)(n&&t[a]!==e[a]||!n&&p(t[a])!==p(e[a]))&&s++;return s+i}function $t(t,e){A(null,[t,t.length,!1],null,e)}function Zt(t,e){return Jt(t,e.locale).toString()}function Xt(t){return Qt(t).toString()}function Jt(t,e,n){return void 0===e&&(e=ue()),Lt(t,e.firstDayOfWeek(),e.firstDayOfYear(),n).year}function Qt(t,e){return Lt(t,1,4,e).year}function te(t,e){A(t,null,null,function(t,n){var a=function(t,e){return void 0===e&&(e={}),e._isUTC?e._offset||0:function(t){return 15*-Math.round(t.getTimezoneOffset()/15)}(t)}(t,{_isUTC:n.isUTC,_offset:n.offset}),r="+";return a<0&&(a=-a,r="-"),r+C(~~(a/60),2)+e+C(~~a%60,2)})}var ee,ne=/([\+\-]|\d\d)/gi,ae={},re={};function ie(t){return t?t.toLowerCase().replace("_","-"):t}function se(t,e){var n;return t&&(f(e)?n=ue(t):r(t)&&(n=oe(t,e)),n&&(ee=n)),ee&&ee._abbr}function oe(t,e){if(null===e)return delete ae[t],ee=ue("en"),null;if(e){var n=Wt;if(e.abbr=t,null!=e.parentLocale){if(null==ae[e.parentLocale])return re[e.parentLocale]||(re[e.parentLocale]=[]),re[e.parentLocale].push({name:t,config:e}),null;n=ae[e.parentLocale]._config}return ae[t]=new Bt(function(t,e){var n,a=Object.assign({},t);for(var r in e)l(e,r)&&(d(t[r])&&d(e[r])?(a[r]={},Object.assign(a[r],t[r]),Object.assign(a[r],e[r])):null!=e[r]?a[r]=e[r]:delete a[r]);for(n in t)l(t,n)&&!l(e,n)&&d(t[n])&&(a[n]=Object.assign({},a[n]));return a}(n,e)),re[t]&&re[t].forEach(function(t){oe(t.name,t.config)}),se(t),ae[t]}}function ue(t){return ae.en||(se("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===p(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),A("w",["ww",2,!1],"wo",function(t,e){return function(t,e,n){return void 0===e&&(e=ue()),e.week(t,void 0)}(t,e.locale).toString(10)}),A("W",["WW",2,!1],"Wo",function(t){return function(t,e){return Lt(t,1,4,void 0).week}(t).toString(10)}),b("week","w"),b("isoWeek","W"),lt("w",J),lt("ww",J,K),lt("W",J),lt("WW",J,K),gt(["w","ww","W","WW"],function(t,e,n,a){return e[a.substr(0,1)]=p(t),n}),A(null,["gg",2,!1],null,function(t,e){return(Jt(t,e.locale)%100).toString()}),A(null,["GG",2,!1],null,function(t){return(Qt(t)%100).toString()}),$t("gggg",Zt),$t("ggggg",Zt),$t("GGGG",Xt),$t("GGGGG",Xt),b("weekYear","gg"),b("isoWeekYear","GG"),lt("G",it),lt("g",it),lt("GG",J,K),lt("gg",J,K),lt("GGGG",nt,Z),lt("gggg",nt,Z),lt("GGGGG",at,X),lt("ggggg",at,X),gt(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,a){return e[a.substr(0,2)]=p(t),n}),gt(["gg","GG"],function(t,e,n,a){return e[a]=vt(t),n}),A("Y",null,null,function(t,e){var n=G(t,e.isUTC);return n<=9999?n.toString(10):"+"+n}),A(null,["YY",2,!1],null,function(t,e){return(G(t,e.isUTC)%100).toString(10)}),A(null,["YYYY",4,!1],null,yt),A(null,["YYYYY",5,!1],null,yt),A(null,["YYYYYY",6,!0],null,yt),b("year","y"),lt("Y",it),lt("YY",J,K),lt("YYYY",nt,Z),lt("YYYYY",at,X),lt("YYYYYY",at,X),ht(["YYYYY","YYYYYY"],y),ht("YYYY",function(t,e,n){return e[y]=2===t.length?vt(t):p(t),n}),ht("YY",function(t,e,n){return e[y]=vt(t),n}),ht("Y",function(t,e,n){return e[y]=parseInt(t,10),n}),A("z",null,null,function(t,e){return e.isUTC?"UTC":""}),A("zz",null,null,function(t,e){return e.isUTC?"Coordinated Universal Time":""}),A("X",null,null,function(t){return function(t){return Math.floor(t.valueOf()/1e3)}(t).toString(10)}),A("x",null,null,function(t){return t.valueOf().toString(10)}),lt("x",it),lt("X",ot),ht("X",function(t,e,n){return n._d=new Date(1e3*parseFloat(t)),n}),ht("x",function(t,e,n){return n._d=new Date(p(t)),n}),A("s",["ss",2,!1],null,function(t,e){return M(t,e.isUTC).toString(10)}),b("second","s"),lt("s",J),lt("ss",J,K),ht(["s","ss"],w),A("Q",null,"Qo",function(t,e){return function(t,e){return void 0===e&&(e=!1),Math.ceil((z(t,e)+1)/3)}(t,e.isUTC).toString(10)}),b("quarter","Q"),lt("Q",W),ht("Q",function(t,e,n){return e[v]=3*(p(t)-1),n}),te("Z",":"),te("ZZ",""),lt("Z",st),lt("ZZ",st),ht(["Z","ZZ"],function(t,e,n){return n._useUTC=!0,n._tzm=function(e,n){var a=(t||"").match(st);if(null===a)return null;var r=a[a.length-1].match(ne)||["-","0","0"],i=60*parseInt(r[1],10)+p(r[2]);return 0===i?0:"+"===r[0]?i:-i}(),n}),A("M",["MM",2,!1],"Mo",function(t,e){return(z(t,e.isUTC)+1).toString(10)}),A("MMM",null,null,function(t,e){return e.locale.monthsShort(t,e.format,e.isUTC)}),A("MMMM",null,null,function(t,e){return e.locale.months(t,e.format,e.isUTC)}),b("month","M"),lt("M",J),lt("MM",J,K),lt("MMM",function(t,e){return e.monthsShortRegex(t)}),lt("MMMM",function(t,e){return e.monthsRegex(t)}),ht(["M","MM"],function(t,e,n){return e[v]=p(t)-1,n}),ht(["MMM","MMMM"],function(t,e,n,a){var r=n._locale.monthsParse(t,a,n._strict);return null!=r?e[v]=r:mt(n).invalidMonth=!!t,n}),A("m",["mm",2,!1],null,function(t,e){return P(t,e.isUTC).toString(10)}),b("minute","m"),lt("m",J),lt("mm",J,K),ht(["m","mm"],T),function(){var t;for(A("S",null,null,function(t,e){return(~~(q(t,e.isUTC)/100)).toString(10)}),A(null,["SS",2,!1],null,function(t,e){return(~~(q(t,e.isUTC)/10)).toString(10)}),A(null,["SSS",3,!1],null,function(t,e){return q(t,e.isUTC).toString(10)}),A(null,["SSSS",4,!1],null,function(t,e){return(10*q(t,e.isUTC)).toString(10)}),A(null,["SSSSS",5,!1],null,function(t,e){return(100*q(t,e.isUTC)).toString(10)}),A(null,["SSSSSS",6,!1],null,function(t,e){return(1e3*q(t,e.isUTC)).toString(10)}),A(null,["SSSSSSS",7,!1],null,function(t,e){return(1e4*q(t,e.isUTC)).toString(10)}),A(null,["SSSSSSSS",8,!1],null,function(t,e){return(1e5*q(t,e.isUTC)).toString(10)}),A(null,["SSSSSSSSS",9,!1],null,function(t,e){return(1e6*q(t,e.isUTC)).toString(10)}),b("millisecond","ms"),lt("S",et,W),lt("SS",et,K),lt("SSS",et,$),t="SSSS";t.length<=9;t+="S")lt(t,rt);function e(t,e,n){return e[S]=p(1e3*parseFloat("0."+t)),n}for(t="S";t.length<=9;t+="S")ht(t,e)}(),function(){function t(t,e){return L(t,e)%12||12}function e(t,e){A(t,null,null,function(t,n){return n.locale.meridiem(L(t,n.isUTC),P(t,n.isUTC),e)})}function n(t,e){return e._meridiemParse}A("H",["HH",2,!1],null,function(t,e){return L(t,e.isUTC).toString(10)}),A("h",["hh",2,!1],null,function(e,n){return t(e,n.isUTC).toString(10)}),A("k",["kk",2,!1],null,function(t,e){return function(t,n){return L(t,e.isUTC)||24}(t).toString(10)}),A("hmm",null,null,function(e,n){return""+t(e,n.isUTC)+C(P(e,n.isUTC),2)}),A("hmmss",null,null,function(e,n){return""+t(e,n.isUTC)+C(P(e,n.isUTC),2)+C(M(e,n.isUTC),2)}),A("Hmm",null,null,function(t,e){return""+L(t,e.isUTC)+C(P(t,e.isUTC),2)}),A("Hmmss",null,null,function(t,e){return""+L(t,e.isUTC)+C(P(t,e.isUTC),2)+C(M(t,e.isUTC),2)}),e("a",!0),e("A",!1),b("hour","h"),lt("a",n),lt("A",n),lt("H",J),lt("h",J),lt("k",J),lt("HH",J,K),lt("hh",J,K),lt("kk",J,K),lt("hmm",Q),lt("hmmss",tt),lt("Hmm",Q),lt("Hmmss",tt),ht(["H","HH"],x),ht(["k","kk"],function(t,e,n){var a=p(t);return e[x]=24===a?0:a,n}),ht(["a","A"],function(t,e,n){return n._isPm=n._locale.isPM(t),n._meridiem=t,n}),ht(["h","hh"],function(t,e,n){return e[x]=p(t),mt(n).bigHour=!0,n}),ht("hmm",function(t,e,n){var a=t.length-2;return e[x]=p(t.substr(0,a)),e[T]=p(t.substr(a)),mt(n).bigHour=!0,n}),ht("hmmss",function(t,e,n){var a=t.length-4,r=t.length-2;return e[x]=p(t.substr(0,a)),e[T]=p(t.substr(a,2)),e[w]=p(t.substr(r)),mt(n).bigHour=!0,n}),ht("Hmm",function(t,e,n){var a=t.length-2;return e[x]=p(t.substr(0,a)),e[T]=p(t.substr(a)),n}),ht("Hmmss",function(t,e,n){var a=t.length-4,r=t.length-2;return e[x]=p(t.substr(0,a)),e[T]=p(t.substr(a,2)),e[w]=p(t.substr(r)),n})}(),A("DDD",["DDDD",3,!1],"DDDo",function(t){return Dt(t).toString(10)}),b("dayOfYear","DDD"),lt("DDD",et),lt("DDDD",$),ht(["DDD","DDDD"],function(t,e,n){return n._dayOfYear=p(t),n}),A("d",null,"do",function(t,e){return j(t,e.isUTC).toString(10)}),A("dd",null,null,function(t,e){return e.locale.weekdaysMin(t,e.format,e.isUTC)}),A("ddd",null,null,function(t,e){return e.locale.weekdaysShort(t,e.format,e.isUTC)}),A("dddd",null,null,function(t,e){return e.locale.weekdays(t,e.format,e.isUTC)}),A("e",null,null,function(t,e){return Je(t,e.locale,e.isUTC).toString(10)}),A("E",null,null,function(t,e){return function(t,n){return j(t,e.isUTC)||7}(t).toString(10)}),b("day","d"),b("weekday","e"),b("isoWeekday","E"),lt("d",J),lt("e",J),lt("E",J),lt("dd",function(t,e){return e.weekdaysMinRegex(t)}),lt("ddd",function(t,e){return e.weekdaysShortRegex(t)}),lt("dddd",function(t,e){return e.weekdaysRegex(t)}),gt(["dd","ddd","dddd"],function(t,e,n,a){var r=n._locale.weekdaysParse(t,a,n._strict);return null!=r?e.d=r:mt(n).invalidWeekday=!!t,n}),gt(["d","e","E"],function(t,e,n,a){return e[a]=p(t),n}),A("D",["DD",2,!1],"Do",function(t,e){return F(t,e.isUTC).toString(10)}),b("date","D"),lt("D",J),lt("DD",J,K),lt("Do",function(t,e){return e._dayOfMonthOrdinalParse||e._ordinalParse}),ht(["D","DD"],_),ht("Do",function(t,e,n){return e[_]=p(t.match(J)[0]),n})),t?function(t){for(var e,n,a=0;a<t.length;){var r=ie(t[a]).split("-"),i=r.length;for(e=(e=ie(t[a+1]))?e.split("-"):null;i>0;){if(s=r.slice(0,i).join("-"),ae[s]||console.error('Khronos locale error: please load locale "'+s+'" before using it'),n=ae[s])return n;if(e&&e.length>=i&&Kt(r,e,!0)>=i-1)break;i--}a++}var s;return null}(c(t)?t:[t]):ee}var ce=["year","quarter","month","week","day","hours","minutes","seconds","milliseconds"],le=ce.reduce(function(t,e){return t[e]=!0,t},{});function de(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function pe(t){return 146097*t/4800}var he=Math.round,ge=function(){function t(t,e){void 0===e&&(e={}),this._data={},this._locale=ue(),this._locale=e&&e._locale||ue();var n=t.year||0,r=t.quarter||0,i=t.month||0,s=t.week||0,o=t.day||0,u=t.hours||0,c=t.minutes||0,l=t.seconds||0,d=t.milliseconds||0;return this._isValid=function(t){if(Object.keys(t).some(function(e){return e in le&&null===t[e]||isNaN(t[e])}))return!1;for(var e=!1,n=0;n<ce.length;++n)if(t[ce[n]]){if(e)return!1;t[ce[n]]!==p(t[ce[n]])&&(e=!0)}return!0}(t),this._milliseconds=+d+1e3*l+60*c*1e3+1e3*u*60*60,this._days=+o+7*s,this._months=+i+3*r+12*n,function(t){var e=t._milliseconds,n=t._days,r=t._months,i=t._data;e>=0&&n>=0&&r>=0||e<=0&&n<=0&&r<=0||(e+=864e5*de(pe(r)+n),n=0,r=0),i.milliseconds=e%1e3;var s=a(e/1e3);i.seconds=s%60;var o=a(s/60);i.minutes=o%60;var u=a(o/60);i.hours=u%24,n+=a(u/24);var c=a(fe(n));r+=c,n-=de(pe(c));var l=a(r/12);return r%=12,i.day=n,i.month=r,i.year=l,t}(this)}return t.prototype.isValid=function(){return this._isValid},t.prototype.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate;var e=this.localeData(),n=function(t,e,n){var a=Be(t).abs(),r=he(a.as("s")),i=he(a.as("m")),s=he(a.as("h")),o=he(a.as("d")),u=he(a.as("M")),c=he(a.as("y")),l=r<=44&&["s",r]||r<45&&["ss",r]||i<=1&&["m"]||i<45&&["mm",i]||s<=1&&["h"]||s<22&&["hh",s]||o<=1&&["d"]||o<26&&["dd",o]||u<=1&&["M"]||u<11&&["MM",u]||c<=1&&["y"]||["yy",c];return(function(t,e,n,a,r){return r.relativeTime(e||1,!!n,t,a)}).apply(null,[l[0],l[1],e,+t>0,n])}(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},t.prototype.localeData=function(){return this._locale},t.prototype.locale=function(t){return t?(this._locale=ue(t)||this._locale,this):this._locale._abbr},t.prototype.abs=function(){var t=Math.abs,e=this._data;return this._milliseconds=t(this._milliseconds),this._days=t(this._days),this._months=t(this._months),e.milliseconds=t(e.milliseconds),e.seconds=t(e.seconds),e.minutes=t(e.minutes),e.hours=t(e.hours),e.month=t(e.month),e.year=t(e.year),this},t.prototype.as=function(t){if(!this.isValid())return NaN;var e,n,a=this._milliseconds,r=m(t);if("month"===r||"year"===r)return n=this._months+fe(e=this._days+a/864e5),"month"===r?n:n/12;switch(e=this._days+Math.round(pe(this._months)),r){case"week":return e/7+a/6048e5;case"day":return e+a/864e5;case"hours":return 24*e+a/36e5;case"minutes":return 1440*e+a/6e4;case"seconds":return 86400*e+a/1e3;case"milliseconds":return Math.floor(864e5*e)+a;default:throw new Error("Unknown unit "+r)}},t.prototype.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*p(this._months/12):NaN},t}();function be(t){if(null==t._isValid){var e=mt(t),n=Array.prototype.some.call(e.parsedDateParts,function(t){return null!=t}),a=!isNaN(t._d&&t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.weekdayMismatch&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(a=a&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return a;t._isValid=a}return t._isValid}function me(t,e){return t._d=new Date(NaN),Object.assign(mt(t),e||{userInvalidated:!0}),t}var ye=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ve=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_e=/Z|[+-]\d\d(?::?\d\d)?/,xe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/,!0],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/,!0],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/,!0],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/,!0],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/,!0],["YYYYMMDD",/\d{8}/,!0],["GGGG[W]WWE",/\d{4}W\d{3}/,!0],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/,!0]],Te=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],we=/^\/?Date\((\-?\d+)/i,Se={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480},Oe=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Ie(t){if(!r(t._i))return t;var e,n,a,i,s,o,u=t._i,c=ye.exec(u)||ve.exec(u);if(!c)return t._isValid=!1,t;for(s=0,o=xe.length;s<o;s++)if(xe[s][1].exec(c[1])){n=xe[s][0],e=!1!==xe[s][2];break}if(null==n)return t._isValid=!1,t;if(c[3]){for(s=0,o=Te.length;s<o;s++)if(Te[s][1].exec(c[3])){a=(c[2]||" ")+Te[s][0];break}if(null==a)return t._isValid=!1,t}if(!e&&null!=a)return t._isValid=!1,t;if(c[4]){if(!_e.exec(c[4]))return t._isValid=!1,t;i="Z"}return t._f=n+(a||"")+(i||""),Me(t)}function Ce(t){var e=parseInt(t,10);return e<=49?e+2e3:e}function ke(t){if(!r(t._i))return t;var e=Oe.exec(t._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim());if(!e)return function(t){return t._isValid=!1,t}(t);var n,a,i,s,o,u,c=(n=e[3],a=e[2],i=e[5],s=e[6],o=e[7],u=[Ce(e[4]),jt.indexOf(n),parseInt(a,10),parseInt(i,10),parseInt(s,10)],o&&u.push(parseInt(o,10)),u);return function(t,e,n){return!t||zt.indexOf(t)===new Date(e[0],e[1],e[2]).getDay()||(mt(n).weekdayMismatch=!0,n._isValid=!1,!1)}(e[1],c,t)?(t._a=c,t._tzm=function(t,n,a){if(t)return Se[t];if(e[9])return 0;var r=parseInt(e[10],10),i=r%100;return(r-i)/100*60+i}(e[8]),t._d=D.apply(null,t._a),t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),mt(t).rfc2822=!0,t):t}function Ne(t,e,n,a,r){void 0===r&&(r=0);var i=ue(n||"en");if(!i)throw new Error('Locale "'+n+'" is not defined, please add it with "defineLocale(...)"');var u=function(t,e,n,a,r){if(void 0===r&&(r=0),!s(t))return n.invalidDate;var i=Re(e,n);return k[i]=k[i]||function(t){for(var e=t.match(R),n=e.length,a=new Array(n),r=0;r<n;r++)a[r]=N[e[r]]?N[e[r]]:(i=e[r]).match(/\[[\s\S]/)?i.replace(/^\[|\]$/g,""):i.replace(/\\/g,"");var i;return function(e,r,i,s){void 0===s&&(s=0);for(var u="",c=0;c<n;c++)u+=o(a[c])?a[c].call(null,e,{format:t,locale:r,isUTC:i,offset:s}):a[c];return u}}(i),k[i](t,n,a,r)}(t,e||(a?"YYYY-MM-DDTHH:mm:ss[Z]":"YYYY-MM-DDTHH:mm:ssZ"),i,a,r);return u?i.postformat(u):u}function Re(t,e){var n=t,a=5,r=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,i=function(t){return e.formatLongDate(t)||t};for(r.lastIndex=0;a>=0&&r.test(n);)n=n.replace(r,i),r.lastIndex=0,a-=1;return n}function Ae(t,e,n){return null!=t?t:null!=e?e:n}function De(t){var e,n,a,r,i,s=[];if(t._d)return t;for(a=function(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}(t),t._w&&null==t._a[_]&&null==t._a[v]&&function(t){var e,n,a,r,i,s,o,u;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)i=1,s=4,n=Ae(e.GG,t._a[y],Lt(new Date,1,4).year),a=Ae(e.W,1),((r=Ae(e.E,1))<1||r>7)&&(u=!0);else{i=t._locale._week.dow,s=t._locale._week.doy;var c=Lt(new Date,i,s);n=Ae(e.gg,t._a[y],c.year),a=Ae(e.w,c.week),null!=e.d?((r=e.d)<0||r>6)&&(u=!0):null!=e.e?(r=e.e+i,(e.e<0||e.e>6)&&(u=!0)):r=i}a<1||a>Pt(n,i,s)?mt(t)._overflowWeeks=!0:null!=u?mt(t)._overflowWeekday=!0:(o=function(t,e,n,a,r){var i,s,o=1+7*(e-1)+(7+n-a)%7+Et(t,a,r);return o<=0?s=_t(i=t-1)+o:o>_t(t)?(i=t+1,s=o-_t(t)):(i=t,s=o),{year:i,dayOfYear:s}}(n,a,r,i,s),t._a[y]=o.year,t._dayOfYear=o.dayOfYear)}(t),null!=t._dayOfYear&&(i=Ae(t._a[y],a[y]),(t._dayOfYear>_t(i)||0===t._dayOfYear)&&(mt(t)._overflowDayOfYear=!0),n=new Date(Date.UTC(i,0,t._dayOfYear)),t._a[v]=n.getUTCMonth(),t._a[_]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=a[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];return 24===t._a[x]&&0===t._a[T]&&0===t._a[w]&&0===t._a[S]&&(t._nextDay=!0,t._a[x]=0),t._d=(t._useUTC?D:E).apply(null,s),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[x]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(mt(t).weekdayMismatch=!0),t}function Ee(t){var e,n=t._a;return n&&-2===mt(t).overflow&&(e=n[v]<0||n[v]>11?v:n[_]<1||n[_]>Tt(n[y],n[v])?_:n[x]<0||n[x]>24||24===n[x]&&(0!==n[T]||0!==n[w]||0!==n[S])?x:n[T]<0||n[T]>59?T:n[w]<0||n[w]>59?w:n[S]<0||n[S]>999?S:-1,mt(t)._overflowDayOfYear&&(e<y||e>_)&&(e=_),mt(t)._overflowWeeks&&-1===e&&(e=O),mt(t)._overflowWeekday&&-1===e&&(e=I),mt(t).overflow=e),t}var Le="ISO_8601",Pe="RFC_2822";function Me(t){if(t._f===Le)return Ie(t);if(t._f===Pe)return ke(t);if(t._a=[],mt(t).empty=!0,c(t._f)||!t._i&&0!==t._i)return t;var e,n,a,r,i=t._i.toString(),s=0,o=i.length,u=Re(t._f,t._locale).match(R)||[];for(e=0;e<u.length;e++)(a=(i.match(dt(n=u[e],t._locale))||[])[0])&&((r=i.substr(0,i.indexOf(a))).length>0&&mt(t).unusedInput.push(r),i=i.slice(i.indexOf(a)+a.length),s+=a.length),N[n]?(a?mt(t).empty=!1:mt(t).unusedTokens.push(n),bt(n,a,t)):t._strict&&!a&&mt(t).unusedTokens.push(n);return mt(t).charsLeftOver=o-s,i.length>0&&mt(t).unusedInput.push(i),t._a[x]<=12&&!0===mt(t).bigHour&&t._a[x]>0&&(mt(t).bigHour=void 0),mt(t).parsedDateParts=t._a.slice(0),mt(t).meridiem=t._meridiem,t._a[x]=function(e,n,a){var r=t._a[x];if(null==a)return r;if(null!=e.meridiemHour)return e.meridiemHour(r,a);if(null==e.isPM)return r;var i=e.isPM(a);return i&&r<12&&(r+=12),i||12!==r||(r=0),r}(t._locale,0,t._meridiem),De(t),Ee(t)}function qe(t,e,n,a,s){return i(t)?t:function(t,e,n,a,s){var o={},p=t;return(d(p)&&function(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}(p)||c(p)&&0===p.length)&&(p=void 0),o._useUTC=o._isUTC=s,o._l=n,o._i=p,o._f=e,o._strict=a,function(t){var e=Ee(function(t){var e=t._i,n=t._f;return t._locale=t._locale||ue(t._l),null===e||void 0===n&&""===e?me(t,{nullInput:!0}):(r(e)&&(t._i=e=t._locale.preparse(e)),i(e)?(t._d=Nt(e),t):(c(n)?function(t){var e,n,a,r,i;if(!t._f||0===t._f.length)return mt(t).invalidFormat=!0,me(t);for(i=0;i<t._f.length;i++)r=0,e=Object.assign({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[i],Me(e),be(e)&&(r+=mt(e).charsLeftOver,r+=10*mt(e).unusedTokens.length,mt(e).score=r,(null==a||r<a)&&(a=r,n=e));Object.assign(t,n||e)}(t):n?Me(t):function(t){var e=t._i;if(f(e))t._d=new Date;else if(i(e))t._d=Nt(e);else if(r(e))!function(t){if(!r(t._i))return t;var e=we.exec(t._i);null!==e?t._d=new Date(+e[1]):(Ie(t),!1!==t._isValid||(delete t._isValid,ke(t),!1!==t._isValid||(delete t._isValid,me(t))))}(t);else if(c(e)&&e.length){var n=e.slice(0);t._a=n.map(function(t){return r(t)?parseInt(t,10):t}),De(t)}else if(d(e))!function(t){if(t._d)return t;var e=t._i;if(d(e)){var n=function(t){var e,n,a={};for(n in t)l(t,n)&&(e=m(n))&&(a[e]=t[n]);return a}(e);t._a=[n.year,n.month,n.day,n.hours,n.minutes,n.seconds,n.milliseconds].map(function(t){return r(t)?parseInt(t,10):t})}De(t)}(t);else{if(!u(e))return me(t);t._d=new Date(e)}}(t),be(t)||(t._d=null),t))}(t));return e._d=new Date(null!=e._d?e._d.getTime():NaN),be(Object.assign({},e,{_isValid:null}))||(e._d=new Date(NaN)),e}(o)}(t,e,n,a,s)._d}function je(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function Fe(t,e,n){return void 0===n&&(n="milliseconds"),!(!t||!e)&&("milliseconds"===n?t.valueOf()>e.valueOf():e.valueOf()<Rt(t,n).valueOf())}function ze(t,e,n){return void 0===n&&(n="milliseconds"),!(!t||!e)&&("milliseconds"===n?t.valueOf()<e.valueOf():At(t,n).valueOf()<e.valueOf())}function Ge(t,e){return!(void 0===e||!e||!e.length)&&e.some(function(e){return e===t.getDay()})}function Ye(t,e,n){if(void 0===n&&(n="milliseconds"),!t||!e)return!1;if("milliseconds"===n)return t.valueOf()===e.valueOf();var a=e.valueOf();return Rt(t,n).valueOf()<=a&&a<=At(t,n).valueOf()}var Ve=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,He=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Be(t,e,n){void 0===n&&(n={});var a=function(t,e){var n;if(null==t)return{};if(t instanceof ge)return{milliseconds:t._milliseconds,day:t._days,month:t._months};if(u(t))return e?((n={})[e]=t,n):{milliseconds:t};if(r(t)){var a=Ve.exec(t);if(a){var i="-"===a[1]?-1:1;return{year:0,day:p(a[_])*i,hours:p(a[x])*i,minutes:p(a[T])*i,seconds:p(a[w])*i,milliseconds:p(je(1e3*p(a[S])))*i}}if(a=He.exec(t))return{year:Ue(a[2],i="-"===a[1]?-1:1),month:Ue(a[3],i),week:Ue(a[4],i),day:Ue(a[5],i),hours:Ue(a[6],i),minutes:Ue(a[7],i),seconds:Ue(a[8],i)}}if(d(t)&&("from"in t||"to"in t)){var o=function(t,e){if(!s(t)||!s(e))return{milliseconds:0,months:0};var n,a=function(t,e,n){if(void 0===n&&(n={}),!n._isUTC)return t;var a=Nt(e),r=6e4*(n._offset||0),i=t.valueOf()-a.valueOf()+r;return a.setTime(a.valueOf()+i),a}(e,t,{_offset:t.getTimezoneOffset()});return ze(t,a)?n=We(t,a):((n=We(a,t)).milliseconds=-n.milliseconds,n.months=-n.months),n}(qe(t.from),qe(t.to));return{milliseconds:o.milliseconds,month:o.months}}return t}(t,e);return new ge(a,n)}function Ue(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function We(t,e){var n={milliseconds:0,months:0};return n.months=z(e)-z(t)+12*(G(e)-G(t)),Fe(Ke(Nt(t),n.months,"month"),e)&&--n.months,n.milliseconds=+e-+Ke(Nt(t),n.months,"month"),n}function Ke(t,e,n,a){return $e(t,Be(e,n),1,a)}function $e(t,e,n,a){var r=e._milliseconds,i=je(e._days),s=je(e._months);return s&&Ct(t,z(t,a)+s*n,a),i&&kt(t,F(t,a)+i*n,a),r&&function(t,e){t.setTime(e)}(t,function(t){return t.getTime()}(t)+r*n),Nt(t)}function Ze(t,e,n,a){void 0===n&&(n=ue());var i=j(t,a);return Ke(t,function(t,e){if(!r(t))return t;var n=parseInt(t,10);if(!isNaN(n))return n;var a=e.weekdaysParse(t);return u(a)?a:null}(e,n)-i,"day")}function Xe(t,e){return j(t,e)}function Je(t,e,n){return void 0===e&&(e=ue()),(j(t,n)+7-e.firstDayOfWeek())%7}var Qe="leden_\xfanor_b\u0159ezen_duben_kv\u011bten_\u010derven_\u010dervenec_srpen_z\xe1\u0159\xed_\u0159\xedjen_listopad_prosinec".split("_"),tn="led_\xfano_b\u0159e_dub_kv\u011b_\u010dvn_\u010dvc_srp_z\xe1\u0159_\u0159\xedj_lis_pro".split("_");function en(t){return t>1&&t<5&&1!=~~(t/10)}function nn(t,e,n,a){var r=t+" ";switch(n){case"s":return e||a?"p\xe1r sekund":"p\xe1r sekundami";case"ss":return e||a?r+(en(t)?"sekundy":"sekund"):r+"sekundami";case"m":return e?"minuta":a?"minutu":"minutou";case"mm":return e||a?r+(en(t)?"minuty":"minut"):r+"minutami";case"h":return e?"hodina":a?"hodinu":"hodinou";case"hh":return e||a?r+(en(t)?"hodiny":"hodin"):r+"hodinami";case"d":return e||a?"den":"dnem";case"dd":return e||a?r+(en(t)?"dny":"dn\xed"):r+"dny";case"M":return e||a?"m\u011bs\xedc":"m\u011bs\xedcem";case"MM":return e||a?r+(en(t)?"m\u011bs\xedce":"m\u011bs\xedc\u016f"):r+"m\u011bs\xedci";case"y":return e||a?"rok":"rokem";case"yy":return e||a?r+(en(t)?"roky":"let"):r+"lety"}}var an=function(t){var e,n=[];for(e=0;e<12;e++)n[e]=new RegExp("^"+t[e]+"$","i");return n},rn=function(t){var e,n=[];for(e=0;e<12;e++)n[e]=new RegExp("^"+t[e]+"$","i");return n},sn={abbr:"cs",months:Qe,monthsShort:tn,monthsParse:function(t,e){var n,a=[];for(n=0;n<12;n++)a[n]=new RegExp("^"+t[n]+"$|^"+e[n]+"$","i");return a}(Qe,tn),shortMonthsParse:an(tn),longMonthsParse:rn(Qe),weekdays:"ned\u011ble_pond\u011bl\xed_\xfater\xfd_st\u0159eda_\u010dtvrtek_p\xe1tek_sobota".split("_"),weekdaysShort:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),weekdaysMin:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[z\xedtra v] LT",nextWeek:function(t){switch(Xe(t)){case 0:return"[v ned\u011bli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve st\u0159edu v] LT";case 4:return"[ve \u010dtvrtek v] LT";case 5:return"[v p\xe1tek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[v\u010dera v] LT",lastWeek:function(t){switch(Xe(t)){case 0:return"[minulou ned\u011bli v] LT";case 1:case 2:return"[minul\xe9] dddd [v] LT";case 3:return"[minulou st\u0159edu v] LT";case 4:case 5:return"[minul\xfd] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"p\u0159ed %s",s:nn,ss:nn,m:nn,mm:nn,h:nn,hh:nn,d:nn,dd:nn,M:nn,MM:nn,y:nn,yy:nn},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}};function on(t,e,n,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[n][0]:r[n][1]}var un={abbr:"de",months:"Januar_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._M\xe4rz_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:on,mm:"%d Minuten",h:on,hh:"%d Stunden",d:on,dd:on,M:on,MM:on,y:on,yy:on},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}},cn="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),ln="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),dn=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],fn=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,pn={abbr:"es",months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,e,n){return t?/-MMM-/.test(e)?ln[z(t,n)]:cn[z(t,n)]:cn},monthsRegex:fn,monthsShortRegex:fn,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:dn,longMonthsParse:dn,shortMonthsParse:dn,weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_s\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(t){return"[hoy a la"+(1!==L(t)?"s":"")+"] LT"},nextDay:function(t){return"[ma\xf1ana a la"+(1!==L(t)?"s":"")+"] LT"},nextWeek:function(t){return"dddd [a la"+(1!==L(t)?"s":"")+"] LT"},lastDay:function(t){return"[ayer a la"+(1!==L(t)?"s":"")+"] LT"},lastWeek:function(t){return"[el] dddd [pasado a la"+(1!==L(t)?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}},hn={abbr:"fr",months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd\u2019hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(t,e){var n=Number(t);switch(e){case"D":return n+(1===n?"er":"");default:case"M":case"Q":case"DDD":case"d":return n+(1===n?"er":"e");case"w":case"W":return n+(1===n?"re":"e")}},week:{dow:1,doy:4}},gn={abbr:"id",months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(t,e){return 12===t&&(t=0),"pagi"===e?t:"siang"===e?t>=11?t:t+12:"sore"===e||"malam"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"pagi":t<15?"siang":t<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}},bn={abbr:"it",months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_luned\xec_marted\xec_mercoled\xec_gioved\xec_venerd\xec_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(t){switch(Xe(t)){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(t){return(/^[0-9].+$/.test(t.toString(10))?"tra":"in")+" "+t},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba",week:{dow:1,doy:4}},mn={abbr:"ja",months:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u65e5\u66dc\u65e5_\u6708\u66dc\u65e5_\u706b\u66dc\u65e5_\u6c34\u66dc\u65e5_\u6728\u66dc\u65e5_\u91d1\u66dc\u65e5_\u571f\u66dc\u65e5".split("_"),weekdaysShort:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),weekdaysMin:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5 HH:mm",LLLL:"YYYY\u5e74M\u6708D\u65e5 HH:mm dddd",l:"YYYY/MM/DD",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5 HH:mm dddd"},meridiemParse:/\u5348\u524d|\u5348\u5f8c/i,isPM:function(t){return"\u5348\u5f8c"===t},meridiem:function(t,e,n){return t<12?"\u5348\u524d":"\u5348\u5f8c"},calendar:{sameDay:"[\u4eca\u65e5] LT",nextDay:"[\u660e\u65e5] LT",nextWeek:"[\u6765\u9031]dddd LT",lastDay:"[\u6628\u65e5] LT",lastWeek:"[\u524d\u9031]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}\u65e5/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\u65e5";default:return t.toString(10)}},relativeTime:{future:"%s\u5f8c",past:"%s\u524d",s:"\u6570\u79d2",ss:"%d\u79d2",m:"1\u5206",mm:"%d\u5206",h:"1\u6642\u9593",hh:"%d\u6642\u9593",d:"1\u65e5",dd:"%d\u65e5",M:"1\u30f6\u6708",MM:"%d\u30f6\u6708",y:"1\u5e74",yy:"%d\u5e74"}},yn={abbr:"ko",months:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),monthsShort:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),weekdays:"\uc77c\uc694\uc77c_\uc6d4\uc694\uc77c_\ud654\uc694\uc77c_\uc218\uc694\uc77c_\ubaa9\uc694\uc77c_\uae08\uc694\uc77c_\ud1a0\uc694\uc77c".split("_"),weekdaysShort:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),weekdaysMin:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"YYYY.MM.DD",LL:"YYYY\ub144 MMMM D\uc77c",LLL:"YYYY\ub144 MMMM D\uc77c A h:mm",LLLL:"YYYY\ub144 MMMM D\uc77c dddd A h:mm",l:"YYYY.MM.DD",ll:"YYYY\ub144 MMMM D\uc77c",lll:"YYYY\ub144 MMMM D\uc77c A h:mm",llll:"YYYY\ub144 MMMM D\uc77c dddd A h:mm"},calendar:{sameDay:"\uc624\ub298 LT",nextDay:"\ub0b4\uc77c LT",nextWeek:"dddd LT",lastDay:"\uc5b4\uc81c LT",lastWeek:"\uc9c0\ub09c\uc8fc dddd LT",sameElse:"L"},relativeTime:{future:"%s \ud6c4",past:"%s \uc804",s:"\uba87 \ucd08",ss:"%d\ucd08",m:"1\ubd84",mm:"%d\ubd84",h:"\ud55c \uc2dc\uac04",hh:"%d\uc2dc\uac04",d:"\ud558\ub8e8",dd:"%d\uc77c",M:"\ud55c \ub2ec",MM:"%d\ub2ec",y:"\uc77c \ub144",yy:"%d\ub144"},dayOfMonthOrdinalParse:/\d{1,2}(\uc77c|\uc6d4|\uc8fc)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"\uc77c";case"M":return t+"\uc6d4";case"w":case"W":return t+"\uc8fc";default:return t.toString(10)}},meridiemParse:/\uc624\uc804|\uc624\ud6c4/,isPM:function(t){return"\uc624\ud6c4"===t},meridiem:function(t,e,n){return t<12?"\uc624\uc804":"\uc624\ud6c4"}},vn="stycze\u0144_luty_marzec_kwiecie\u0144_maj_czerwiec_lipiec_sierpie\u0144_wrzesie\u0144_pa\u017adziernik_listopad_grudzie\u0144".split("_"),_n="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_wrze\u015bnia_pa\u017adziernika_listopada_grudnia".split("_");function xn(t){return t%10<5&&t%10>1&&~~(t/10)%10!=1}function Tn(t,e,n){var a=t+" ";switch(n){case"ss":return a+(xn(t)?"sekundy":"sekund");case"m":return e?"minuta":"minut\u0119";case"mm":return a+(xn(t)?"minuty":"minut");case"h":return e?"godzina":"godzin\u0119";case"hh":return a+(xn(t)?"godziny":"godzin");case"MM":return a+(xn(t)?"miesi\u0105ce":"miesi\u0119cy");case"yy":return a+(xn(t)?"lata":"lat")}}var wn={abbr:"pl",months:function(t,e,n){return t?""===e?"("+_n[z(t,n)]+"|"+vn[z(t,n)]+")":/D MMMM/.test(e)?_n[z(t,n)]:vn[z(t,n)]:vn},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_pa\u017a_lis_gru".split("_"),weekdays:"niedziela_poniedzia\u0142ek_wtorek_\u015broda_czwartek_pi\u0105tek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_\u015br_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_\u015ar_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dzi\u015b o] LT",nextDay:"[Jutro o] LT",nextWeek:function(t){switch(Xe(t)){case 0:return"[W niedziel\u0119 o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W \u015brod\u0119 o] LT";case 5:return"[W pi\u0105tek o] LT";case 6:return"[W sobot\u0119 o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(t){switch(Xe(t)){case 0:return"[W zesz\u0142\u0105 niedziel\u0119 o] LT";case 3:return"[W zesz\u0142\u0105 \u015brod\u0119 o] LT";case 4:return"[W zesz\u0142\u0105 czwartek o] LT";case 5:return"[W zesz\u0142\u0105 pi\u0105tek o] LT";case 6:return"[W zesz\u0142\u0105 sobot\u0119 o] LT";default:return"[W zesz\u0142y] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:Tn,m:Tn,mm:Tn,h:Tn,hh:Tn,d:"1 dzie\u0144",dd:"%d dni",M:"miesi\u0105c",MM:Tn,y:"rok",yy:Tn},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}},Sn={abbr:"pt-br",months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Do_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [\xe0s] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [\xe0s] HH:mm"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(t){return 0===Xe(t)||6===Xe(t)?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atr\xe1s",s:"poucos segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}\xba/,ordinal:"%d\xba"},On={abbr:"zh-cn",months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u5468\u65e5_\u5468\u4e00_\u5468\u4e8c_\u5468\u4e09_\u5468\u56db_\u5468\u4e94_\u5468\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5Ah\u70b9mm\u5206",LLLL:"YYYY\u5e74M\u6708D\u65e5ddddAh\u70b9mm\u5206",l:"YYYY/M/D",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm"},meridiemParse:/\u51cc\u6668|\u65e9\u4e0a|\u4e0a\u5348|\u4e2d\u5348|\u4e0b\u5348|\u665a\u4e0a/,meridiemHour:function(t,e){return 12===t&&(t=0),"\u51cc\u6668"===e||"\u65e9\u4e0a"===e||"\u4e0a\u5348"===e?t:"\u4e0b\u5348"===e||"\u665a\u4e0a"===e?t+12:t>=11?t:t+12},meridiem:function(t,e,n){var a=100*t+e;return a<600?"\u51cc\u6668":a<900?"\u65e9\u4e0a":a<1130?"\u4e0a\u5348":a<1230?"\u4e2d\u5348":a<1800?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(\u65e5|\u6708|\u5468)/,ordinal:function(t,e){var n=Number(t);switch(e){case"d":case"D":case"DDD":return n+"\u65e5";case"M":return n+"\u6708";case"w":case"W":return n+"\u5468";default:return n.toString()}},relativeTime:{future:"%s\u5185",past:"%s\u524d",s:"\u51e0\u79d2",ss:"%d \u79d2",m:"1 \u5206\u949f",mm:"%d \u5206\u949f",h:"1 \u5c0f\u65f6",hh:"%d \u5c0f\u65f6",d:"1 \u5929",dd:"%d \u5929",M:"1 \u4e2a\u6708",MM:"%d \u4e2a\u6708",y:"1 \u5e74",yy:"%d \u5e74"},week:{dow:1,doy:4}}},lJMN:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("QG5k"),r=n("TCh0"),i=n("kQXf");e.TreeController=function(){function t(t){this.component=t,this.tree=this.component.tree,this.treeService=this.component.treeService}return t.prototype.select=function(){this.isSelected()||this.component.onNodeSelected({button:r.MouseButtons.Left})},t.prototype.unselect=function(){this.isSelected()&&this.component.onNodeUnselected({button:r.MouseButtons.Left})},t.prototype.isSelected=function(){return this.component.isSelected},t.prototype.expand=function(){this.isCollapsed()&&this.component.onSwitchFoldingType()},t.prototype.expandToParent=function(t){var e=this;if(void 0===t&&(t=this.tree),t){var n=this.treeService.getController(t.id);n&&requestAnimationFrame(function(){n.expand(),e.expandToParent(t.parent)})}},t.prototype.isExpanded=function(){return this.tree.isNodeExpanded()},t.prototype.collapse=function(){this.isExpanded()&&this.component.onSwitchFoldingType()},t.prototype.isCollapsed=function(){return this.tree.isNodeCollapsed()},t.prototype.toTreeModel=function(){return this.tree.toTreeModel()},t.prototype.rename=function(t){this.tree.markAsBeingRenamed(),this.component.applyNewValue({type:"keyup",value:t})},t.prototype.remove=function(){this.component.onMenuItemSelected({nodeMenuItemAction:a.NodeMenuItemAction.Remove})},t.prototype.addChild=function(t){if(!this.tree.hasDeferredChildren()||this.tree.childrenWereLoaded()){var e=this.tree.createNode(Array.isArray(t.children),t);this.treeService.fireNodeCreated(e)}},t.prototype.addChildAsync=function(t){if(this.tree.hasDeferredChildren()&&!this.tree.childrenWereLoaded())return Promise.reject(new Error("This node loads its children asynchronously, hence child cannot be added this way"));var e=this.tree.createNode(Array.isArray(t.children),t);return this.treeService.fireNodeCreated(e),new Promise(function(t){setTimeout(function(){t(e)})})},t.prototype.changeNodeId=function(t){if(!t)throw Error("You should supply an id!");if(this.treeService.hasController(t))throw Error("Controller already exists for the given id: "+t);this.treeService.deleteController(this.tree.id),this.tree.id=t,this.treeService.setController(this.tree.id,this)},t.prototype.reloadChildren=function(){this.tree.reloadChildren()},t.prototype.setChildren=function(t){this.tree.isLeaf()||this.tree.setChildren(t)},t.prototype.startRenaming=function(){this.tree.markAsBeingRenamed()},t.prototype.check=function(){this.component.onNodeChecked()},t.prototype.uncheck=function(){this.component.onNodeUnchecked()},t.prototype.isChecked=function(){return this.tree.checked},t.prototype.isIndetermined=function(){return i.get(this.component,"checkboxElementRef.nativeElement.indeterminate")},t.prototype.allowSelection=function(){this.tree.selectionAllowed=!0},t.prototype.forbidSelection=function(){this.tree.selectionAllowed=!1},t.prototype.isSelectionAllowed=function(){return this.tree.selectionAllowed},t}()},lTVp:function(t,e,n){"use strict";n.d(e,"a",function(){return o}),n.d(e,"b",function(){return s}),n.d(e,"c",function(){return u});var a=n("mrSG"),r=n("CcnG"),i=n("rpEJ"),s=function(){return function(){this.type="warning",this.dismissible=!1,this.dismissOnTimeout=void 0}}(),o=function(){function t(t,e){var n=this;this.changeDetection=e,this.type="warning",this.dismissible=!1,this.isOpen=!0,this.onClose=new r.EventEmitter,this.onClosed=new r.EventEmitter,this.classes="",this.dismissibleChange=new r.EventEmitter,Object.assign(this,t),this.dismissibleChange.subscribe(function(t){n.classes=n.dismissible?"alert-dismissible":"",n.changeDetection.markForCheck()})}return t.prototype.ngOnInit=function(){var t=this;this.dismissOnTimeout&&setTimeout(function(){return t.close()},parseInt(this.dismissOnTimeout,10))},t.prototype.close=function(){this.isOpen&&(this.onClose.emit(this),this.isOpen=!1,this.changeDetection.markForCheck(),this.onClosed.emit(this))},Object(a.__decorate)([Object(i.a)(),Object(a.__metadata)("design:type",Object)],t.prototype,"dismissible",void 0),t}(),u=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[s]}},t}()},lUjN:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("vxfy");e.DatatableFooterDirective=function(){function t(){}return a([i.Input(),r("design:type",Number)],t.prototype,"footerHeight",void 0),a([i.Input(),r("design:type",String)],t.prototype,"totalMessage",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectedMessage",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),i.ContentChild(s.DataTableFooterTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Directive({selector:"ngx-datatable-footer"})],t)}()},lXzo:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a,r;return"m"===n?e?"\u043c\u0438\u043d\u0443\u0442\u0430":"\u043c\u0438\u043d\u0443\u0442\u0443":t+" "+(a=+t,r={ss:e?"\u0441\u0435\u043a\u0443\u043d\u0434\u0430_\u0441\u0435\u043a\u0443\u043d\u0434\u044b_\u0441\u0435\u043a\u0443\u043d\u0434":"\u0441\u0435\u043a\u0443\u043d\u0434\u0443_\u0441\u0435\u043a\u0443\u043d\u0434\u044b_\u0441\u0435\u043a\u0443\u043d\u0434",mm:e?"\u043c\u0438\u043d\u0443\u0442\u0430_\u043c\u0438\u043d\u0443\u0442\u044b_\u043c\u0438\u043d\u0443\u0442":"\u043c\u0438\u043d\u0443\u0442\u0443_\u043c\u0438\u043d\u0443\u0442\u044b_\u043c\u0438\u043d\u0443\u0442",hh:"\u0447\u0430\u0441_\u0447\u0430\u0441\u0430_\u0447\u0430\u0441\u043e\u0432",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u044f_\u0434\u043d\u0435\u0439",MM:"\u043c\u0435\u0441\u044f\u0446_\u043c\u0435\u0441\u044f\u0446\u0430_\u043c\u0435\u0441\u044f\u0446\u0435\u0432",yy:"\u0433\u043e\u0434_\u0433\u043e\u0434\u0430_\u043b\u0435\u0442"}[n].split("_"),a%10==1&&a%100!=11?r[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?r[1]:r[2])}var a=[/^\u044f\u043d\u0432/i,/^\u0444\u0435\u0432/i,/^\u043c\u0430\u0440/i,/^\u0430\u043f\u0440/i,/^\u043c\u0430[\u0439\u044f]/i,/^\u0438\u044e\u043d/i,/^\u0438\u044e\u043b/i,/^\u0430\u0432\u0433/i,/^\u0441\u0435\u043d/i,/^\u043e\u043a\u0442/i,/^\u043d\u043e\u044f/i,/^\u0434\u0435\u043a/i];n("wd/R").defineLocale("ru",{months:{format:"\u044f\u043d\u0432\u0430\u0440\u044f_\u0444\u0435\u0432\u0440\u0430\u043b\u044f_\u043c\u0430\u0440\u0442\u0430_\u0430\u043f\u0440\u0435\u043b\u044f_\u043c\u0430\u044f_\u0438\u044e\u043d\u044f_\u0438\u044e\u043b\u044f_\u0430\u0432\u0433\u0443\u0441\u0442\u0430_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f_\u043e\u043a\u0442\u044f\u0431\u0440\u044f_\u043d\u043e\u044f\u0431\u0440\u044f_\u0434\u0435\u043a\u0430\u0431\u0440\u044f".split("_"),standalone:"\u044f\u043d\u0432\u0430\u0440\u044c_\u0444\u0435\u0432\u0440\u0430\u043b\u044c_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b\u044c_\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c_\u043e\u043a\u0442\u044f\u0431\u0440\u044c_\u043d\u043e\u044f\u0431\u0440\u044c_\u0434\u0435\u043a\u0430\u0431\u0440\u044c".split("_")},monthsShort:{format:"\u044f\u043d\u0432._\u0444\u0435\u0432\u0440._\u043c\u0430\u0440._\u0430\u043f\u0440._\u043c\u0430\u044f_\u0438\u044e\u043d\u044f_\u0438\u044e\u043b\u044f_\u0430\u0432\u0433._\u0441\u0435\u043d\u0442._\u043e\u043a\u0442._\u043d\u043e\u044f\u0431._\u0434\u0435\u043a.".split("_"),standalone:"\u044f\u043d\u0432._\u0444\u0435\u0432\u0440._\u043c\u0430\u0440\u0442_\u0430\u043f\u0440._\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433._\u0441\u0435\u043d\u0442._\u043e\u043a\u0442._\u043d\u043e\u044f\u0431._\u0434\u0435\u043a.".split("_")},weekdays:{standalone:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0430_\u0441\u0443\u0431\u0431\u043e\u0442\u0430".split("_"),format:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0443_\u0441\u0443\u0431\u0431\u043e\u0442\u0443".split("_"),isFormat:/\[ ?[\u0412\u0432] ?(?:\u043f\u0440\u043e\u0448\u043b\u0443\u044e|\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e|\u044d\u0442\u0443)? ?\] ?dddd/},weekdaysShort:"\u0432\u0441_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),weekdaysMin:"\u0432\u0441_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),monthsParse:a,longMonthsParse:a,shortMonthsParse:a,monthsRegex:/^(\u044f\u043d\u0432\u0430\u0440[\u044c\u044f]|\u044f\u043d\u0432\.?|\u0444\u0435\u0432\u0440\u0430\u043b[\u044c\u044f]|\u0444\u0435\u0432\u0440?\.?|\u043c\u0430\u0440\u0442\u0430?|\u043c\u0430\u0440\.?|\u0430\u043f\u0440\u0435\u043b[\u044c\u044f]|\u0430\u043f\u0440\.?|\u043c\u0430[\u0439\u044f]|\u0438\u044e\u043d[\u044c\u044f]|\u0438\u044e\u043d\.?|\u0438\u044e\u043b[\u044c\u044f]|\u0438\u044e\u043b\.?|\u0430\u0432\u0433\u0443\u0441\u0442\u0430?|\u0430\u0432\u0433\.?|\u0441\u0435\u043d\u0442\u044f\u0431\u0440[\u044c\u044f]|\u0441\u0435\u043d\u0442?\.?|\u043e\u043a\u0442\u044f\u0431\u0440[\u044c\u044f]|\u043e\u043a\u0442\.?|\u043d\u043e\u044f\u0431\u0440[\u044c\u044f]|\u043d\u043e\u044f\u0431?\.?|\u0434\u0435\u043a\u0430\u0431\u0440[\u044c\u044f]|\u0434\u0435\u043a\.?)/i,monthsShortRegex:/^(\u044f\u043d\u0432\u0430\u0440[\u044c\u044f]|\u044f\u043d\u0432\.?|\u0444\u0435\u0432\u0440\u0430\u043b[\u044c\u044f]|\u0444\u0435\u0432\u0440?\.?|\u043c\u0430\u0440\u0442\u0430?|\u043c\u0430\u0440\.?|\u0430\u043f\u0440\u0435\u043b[\u044c\u044f]|\u0430\u043f\u0440\.?|\u043c\u0430[\u0439\u044f]|\u0438\u044e\u043d[\u044c\u044f]|\u0438\u044e\u043d\.?|\u0438\u044e\u043b[\u044c\u044f]|\u0438\u044e\u043b\.?|\u0430\u0432\u0433\u0443\u0441\u0442\u0430?|\u0430\u0432\u0433\.?|\u0441\u0435\u043d\u0442\u044f\u0431\u0440[\u044c\u044f]|\u0441\u0435\u043d\u0442?\.?|\u043e\u043a\u0442\u044f\u0431\u0440[\u044c\u044f]|\u043e\u043a\u0442\.?|\u043d\u043e\u044f\u0431\u0440[\u044c\u044f]|\u043d\u043e\u044f\u0431?\.?|\u0434\u0435\u043a\u0430\u0431\u0440[\u044c\u044f]|\u0434\u0435\u043a\.?)/i,monthsStrictRegex:/^(\u044f\u043d\u0432\u0430\u0440[\u044f\u044c]|\u0444\u0435\u0432\u0440\u0430\u043b[\u044f\u044c]|\u043c\u0430\u0440\u0442\u0430?|\u0430\u043f\u0440\u0435\u043b[\u044f\u044c]|\u043c\u0430[\u044f\u0439]|\u0438\u044e\u043d[\u044f\u044c]|\u0438\u044e\u043b[\u044f\u044c]|\u0430\u0432\u0433\u0443\u0441\u0442\u0430?|\u0441\u0435\u043d\u0442\u044f\u0431\u0440[\u044f\u044c]|\u043e\u043a\u0442\u044f\u0431\u0440[\u044f\u044c]|\u043d\u043e\u044f\u0431\u0440[\u044f\u044c]|\u0434\u0435\u043a\u0430\u0431\u0440[\u044f\u044c])/i,monthsShortStrictRegex:/^(\u044f\u043d\u0432\.|\u0444\u0435\u0432\u0440?\.|\u043c\u0430\u0440[\u0442.]|\u0430\u043f\u0440\.|\u043c\u0430[\u044f\u0439]|\u0438\u044e\u043d[\u044c\u044f.]|\u0438\u044e\u043b[\u044c\u044f.]|\u0430\u0432\u0433\.|\u0441\u0435\u043d\u0442?\.|\u043e\u043a\u0442\.|\u043d\u043e\u044f\u0431?\.|\u0434\u0435\u043a\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0433.",LLL:"D MMMM YYYY \u0433., H:mm",LLLL:"dddd, D MMMM YYYY \u0433., H:mm"},calendar:{sameDay:"[\u0421\u0435\u0433\u043e\u0434\u043d\u044f, \u0432] LT",nextDay:"[\u0417\u0430\u0432\u0442\u0440\u0430, \u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430, \u0432] LT",nextWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[\u0412\u043e] dddd, [\u0432] LT":"[\u0412] dddd, [\u0432] LT";switch(this.day()){case 0:return"[\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435] dddd, [\u0432] LT";case 1:case 2:case 4:return"[\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439] dddd, [\u0432] LT";case 3:case 5:case 6:return"[\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e] dddd, [\u0432] LT"}},lastWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[\u0412\u043e] dddd, [\u0432] LT":"[\u0412] dddd, [\u0432] LT";switch(this.day()){case 0:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0435] dddd, [\u0432] LT";case 1:case 2:case 4:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439] dddd, [\u0432] LT";case 3:case 5:case 6:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u0443\u044e] dddd, [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0447\u0435\u0440\u0435\u0437 %s",past:"%s \u043d\u0430\u0437\u0430\u0434",s:"\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434",ss:e,m:e,mm:e,h:"\u0447\u0430\u0441",hh:e,d:"\u0434\u0435\u043d\u044c",dd:e,M:"\u043c\u0435\u0441\u044f\u0446",MM:e,y:"\u0433\u043e\u0434",yy:e},meridiemParse:/\u043d\u043e\u0447\u0438|\u0443\u0442\u0440\u0430|\u0434\u043d\u044f|\u0432\u0435\u0447\u0435\u0440\u0430/i,isPM:function(t){return/^(\u0434\u043d\u044f|\u0432\u0435\u0447\u0435\u0440\u0430)$/.test(t)},meridiem:function(t,e,n){return t<4?"\u043d\u043e\u0447\u0438":t<12?"\u0443\u0442\u0440\u0430":t<17?"\u0434\u043d\u044f":"\u0432\u0435\u0447\u0435\u0440\u0430"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0439|\u0433\u043e|\u044f)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":return t+"-\u0439";case"D":return t+"-\u0433\u043e";case"w":case"W":return t+"-\u044f";default:return t}},week:{dow:1,doy:4}})}()},lYZG:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("6blF"),r=n("0/uQ"),i=n("G5J1");function s(t){return new a.a(function(e){var n;try{n=t()}catch(a){return void e.error(a)}return(n?Object(r.a)(n):Object(i.b)()).subscribe(e)})}},lYtQ:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){switch(n){case"s":return e?"\u0445\u044d\u0434\u0445\u044d\u043d \u0441\u0435\u043a\u0443\u043d\u0434":"\u0445\u044d\u0434\u0445\u044d\u043d \u0441\u0435\u043a\u0443\u043d\u0434\u044b\u043d";case"ss":return t+(e?" \u0441\u0435\u043a\u0443\u043d\u0434":" \u0441\u0435\u043a\u0443\u043d\u0434\u044b\u043d");case"m":case"mm":return t+(e?" \u043c\u0438\u043d\u0443\u0442":" \u043c\u0438\u043d\u0443\u0442\u044b\u043d");case"h":case"hh":return t+(e?" \u0446\u0430\u0433":" \u0446\u0430\u0433\u0438\u0439\u043d");case"d":case"dd":return t+(e?" \u04e9\u0434\u04e9\u0440":" \u04e9\u0434\u0440\u0438\u0439\u043d");case"M":case"MM":return t+(e?" \u0441\u0430\u0440":" \u0441\u0430\u0440\u044b\u043d");case"y":case"yy":return t+(e?" \u0436\u0438\u043b":" \u0436\u0438\u043b\u0438\u0439\u043d");default:return t}}n("wd/R").defineLocale("mn",{months:"\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440_\u0425\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0413\u0443\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0414\u04e9\u0440\u04e9\u0432\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440_\u0422\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0417\u0443\u0440\u0433\u0430\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0414\u043e\u043b\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u041d\u0430\u0439\u043c\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0415\u0441\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440_\u0410\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440_\u0410\u0440\u0432\u0430\u043d \u043d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440_\u0410\u0440\u0432\u0430\u043d \u0445\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440".split("_"),monthsShort:"1 \u0441\u0430\u0440_2 \u0441\u0430\u0440_3 \u0441\u0430\u0440_4 \u0441\u0430\u0440_5 \u0441\u0430\u0440_6 \u0441\u0430\u0440_7 \u0441\u0430\u0440_8 \u0441\u0430\u0440_9 \u0441\u0430\u0440_10 \u0441\u0430\u0440_11 \u0441\u0430\u0440_12 \u0441\u0430\u0440".split("_"),monthsParseExact:!0,weekdays:"\u041d\u044f\u043c_\u0414\u0430\u0432\u0430\u0430_\u041c\u044f\u0433\u043c\u0430\u0440_\u041b\u0445\u0430\u0433\u0432\u0430_\u041f\u04af\u0440\u044d\u0432_\u0411\u0430\u0430\u0441\u0430\u043d_\u0411\u044f\u043c\u0431\u0430".split("_"),weekdaysShort:"\u041d\u044f\u043c_\u0414\u0430\u0432_\u041c\u044f\u0433_\u041b\u0445\u0430_\u041f\u04af\u0440_\u0411\u0430\u0430_\u0411\u044f\u043c".split("_"),weekdaysMin:"\u041d\u044f_\u0414\u0430_\u041c\u044f_\u041b\u0445_\u041f\u04af_\u0411\u0430_\u0411\u044f".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY \u043e\u043d\u044b MMMM\u044b\u043d D",LLL:"YYYY \u043e\u043d\u044b MMMM\u044b\u043d D HH:mm",LLLL:"dddd, YYYY \u043e\u043d\u044b MMMM\u044b\u043d D HH:mm"},meridiemParse:/\u04ae\u04e8|\u04ae\u0425/i,isPM:function(t){return"\u04ae\u0425"===t},meridiem:function(t,e,n){return t<12?"\u04ae\u04e8":"\u04ae\u0425"},calendar:{sameDay:"[\u04e8\u043d\u04e9\u04e9\u0434\u04e9\u0440] LT",nextDay:"[\u041c\u0430\u0440\u0433\u0430\u0430\u0448] LT",nextWeek:"[\u0418\u0440\u044d\u0445] dddd LT",lastDay:"[\u04e8\u0447\u0438\u0433\u0434\u04e9\u0440] LT",lastWeek:"[\u04e8\u043d\u0433\u04e9\u0440\u0441\u04e9\u043d] dddd LT",sameElse:"L"},relativeTime:{future:"%s \u0434\u0430\u0440\u0430\u0430",past:"%s \u04e9\u043c\u043d\u04e9",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2} \u04e9\u0434\u04e9\u0440/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+" \u04e9\u0434\u04e9\u0440";default:return t}}})}()},lZOh:function(t,e,n){"use strict";n.r(e);var a=n("6blF"),r=n("F/XL");a.a.of=r.a},lgnt:function(t,e,n){!function(t){"use strict";var e={0:"-\u0447\u04af",1:"-\u0447\u0438",2:"-\u0447\u0438",3:"-\u0447\u04af",4:"-\u0447\u04af",5:"-\u0447\u0438",6:"-\u0447\u044b",7:"-\u0447\u0438",8:"-\u0447\u0438",9:"-\u0447\u0443",10:"-\u0447\u0443",20:"-\u0447\u044b",30:"-\u0447\u0443",40:"-\u0447\u044b",50:"-\u0447\u04af",60:"-\u0447\u044b",70:"-\u0447\u0438",80:"-\u0447\u0438",90:"-\u0447\u0443",100:"-\u0447\u04af"};t.defineLocale("ky",{months:"\u044f\u043d\u0432\u0430\u0440\u044c_\u0444\u0435\u0432\u0440\u0430\u043b\u044c_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b\u044c_\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c_\u043e\u043a\u0442\u044f\u0431\u0440\u044c_\u043d\u043e\u044f\u0431\u0440\u044c_\u0434\u0435\u043a\u0430\u0431\u0440\u044c".split("_"),monthsShort:"\u044f\u043d\u0432_\u0444\u0435\u0432_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440_\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433_\u0441\u0435\u043d_\u043e\u043a\u0442_\u043d\u043e\u044f_\u0434\u0435\u043a".split("_"),weekdays:"\u0416\u0435\u043a\u0448\u0435\u043c\u0431\u0438_\u0414\u04af\u0439\u0448\u04e9\u043c\u0431\u04af_\u0428\u0435\u0439\u0448\u0435\u043c\u0431\u0438_\u0428\u0430\u0440\u0448\u0435\u043c\u0431\u0438_\u0411\u0435\u0439\u0448\u0435\u043c\u0431\u0438_\u0416\u0443\u043c\u0430_\u0418\u0448\u0435\u043c\u0431\u0438".split("_"),weekdaysShort:"\u0416\u0435\u043a_\u0414\u04af\u0439_\u0428\u0435\u0439_\u0428\u0430\u0440_\u0411\u0435\u0439_\u0416\u0443\u043c_\u0418\u0448\u0435".split("_"),weekdaysMin:"\u0416\u043a_\u0414\u0439_\u0428\u0439_\u0428\u0440_\u0411\u0439_\u0416\u043c_\u0418\u0448".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0411\u04af\u0433\u04af\u043d \u0441\u0430\u0430\u0442] LT",nextDay:"[\u042d\u0440\u0442\u0435\u04a3 \u0441\u0430\u0430\u0442] LT",nextWeek:"dddd [\u0441\u0430\u0430\u0442] LT",lastDay:"[\u041a\u0435\u0447\u044d\u044d \u0441\u0430\u0430\u0442] LT",lastWeek:"[\u04e8\u0442\u043a\u04e9\u043d \u0430\u043f\u0442\u0430\u043d\u044b\u043d] dddd [\u043a\u04af\u043d\u04af] [\u0441\u0430\u0430\u0442] LT",sameElse:"L"},relativeTime:{future:"%s \u0438\u0447\u0438\u043d\u0434\u0435",past:"%s \u043c\u0443\u0440\u0443\u043d",s:"\u0431\u0438\u0440\u043d\u0435\u0447\u0435 \u0441\u0435\u043a\u0443\u043d\u0434",ss:"%d \u0441\u0435\u043a\u0443\u043d\u0434",m:"\u0431\u0438\u0440 \u043c\u04af\u043d\u04e9\u0442",mm:"%d \u043c\u04af\u043d\u04e9\u0442",h:"\u0431\u0438\u0440 \u0441\u0430\u0430\u0442",hh:"%d \u0441\u0430\u0430\u0442",d:"\u0431\u0438\u0440 \u043a\u04af\u043d",dd:"%d \u043a\u04af\u043d",M:"\u0431\u0438\u0440 \u0430\u0439",MM:"%d \u0430\u0439",y:"\u0431\u0438\u0440 \u0436\u044b\u043b",yy:"%d \u0436\u044b\u043b"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0447\u0438|\u0447\u044b|\u0447\u04af|\u0447\u0443)/,ordinal:function(t){return t+(e[t]||e[t%10]||e[t>=100?100:null])},week:{dow:1,doy:7}})}(n("wd/R"))},lmqd:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.multi="multi",t.multiClick="multiClick",t.cell="cell",t.checkbox="checkbox"}(e.SelectionType||(e.SelectionType={}))},lqqz:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("CcnG"),r=n("rpEJ"),i=function(){return function(t,e,n){this.nodes=t,this.viewRef=e,this.componentRef=n}}(),s=function(){function t(t,e,n,r,i,s,o,u){this._viewContainerRef=t,this._renderer=e,this._elementRef=n,this._injector=r,this._componentFactoryResolver=i,this._ngZone=s,this._applicationRef=o,this._posService=u,this.onBeforeShow=new a.EventEmitter,this.onShown=new a.EventEmitter,this.onBeforeHide=new a.EventEmitter,this.onHidden=new a.EventEmitter,this._providers=[],this._isHiding=!1,this.containerDefaultSelector="body",this._listenOpts={},this._globalListener=Function.prototype}return Object.defineProperty(t.prototype,"isShown",{get:function(){return!this._isHiding&&!!this._componentRef},enumerable:!0,configurable:!0}),t.prototype.attach=function(t){return this._componentFactory=this._componentFactoryResolver.resolveComponentFactory(t),this},t.prototype.to=function(t){return this.container=t||this.container,this},t.prototype.position=function(t){return this.attachment=t.attachment||this.attachment,this._elementRef=t.target||this._elementRef,this},t.prototype.provide=function(t){return this._providers.push(t),this},t.prototype.show=function(t){if(void 0===t&&(t={}),this._subscribePositioning(),this._innerComponent=null,!this._componentRef){this.onBeforeShow.emit(),this._contentRef=this._getContentRef(t.content,t.context,t.initialState);var e=a.Injector.create({providers:this._providers,parent:this._injector});this._componentRef=this._componentFactory.create(e,this._contentRef.nodes),this._applicationRef.attachView(this._componentRef.hostView),this.instance=this._componentRef.instance,Object.assign(this._componentRef.instance,t),this.container instanceof a.ElementRef&&this.container.nativeElement.appendChild(this._componentRef.location.nativeElement),"string"==typeof this.container&&"undefined"!=typeof document&&(document.querySelector(this.container)||document.querySelector(this.containerDefaultSelector)).appendChild(this._componentRef.location.nativeElement),!this.container&&this._elementRef&&this._elementRef.nativeElement.parentElement&&this._elementRef.nativeElement.parentElement.appendChild(this._componentRef.location.nativeElement),this._contentRef.componentRef&&(this._innerComponent=this._contentRef.componentRef.instance,this._contentRef.componentRef.changeDetectorRef.markForCheck(),this._contentRef.componentRef.changeDetectorRef.detectChanges()),this._componentRef.changeDetectorRef.markForCheck(),this._componentRef.changeDetectorRef.detectChanges(),this.onShown.emit(this._componentRef.instance)}return this._registerOutsideClick(),this._componentRef},t.prototype.hide=function(){if(!this._componentRef)return this;this._posService.deletePositionElement(this._componentRef.location),this.onBeforeHide.emit(this._componentRef.instance);var t=this._componentRef.location.nativeElement;return t.parentNode.removeChild(t),this._contentRef.componentRef&&this._contentRef.componentRef.destroy(),this._componentRef.destroy(),this._viewContainerRef&&this._contentRef.viewRef&&this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef)),this._contentRef.viewRef&&this._contentRef.viewRef.destroy(),this._contentRef=null,this._componentRef=null,this._removeGlobalListener(),this.onHidden.emit(),this},t.prototype.toggle=function(){this.isShown?this.hide():this.show()},t.prototype.dispose=function(){this.isShown&&this.hide(),this._unsubscribePositioning(),this._unregisterListenersFn&&this._unregisterListenersFn()},t.prototype.listen=function(t){var e=this;this.triggers=t.triggers||this.triggers,this._listenOpts.outsideClick=t.outsideClick,this._listenOpts.outsideEsc=t.outsideEsc,t.target=t.target||this._elementRef.nativeElement;var n=this._listenOpts.hide=function(){return t.hide?t.hide():void e.hide()},a=this._listenOpts.show=function(n){t.show?t.show(n):e.show(n),n()};return this._unregisterListenersFn=Object(r.e)(this._renderer,{target:t.target,triggers:t.triggers,show:a,hide:n,toggle:function(t){e.isShown?n():a(t)}}),this},t.prototype._removeGlobalListener=function(){this._globalListener&&(this._globalListener(),this._globalListener=null)},t.prototype.attachInline=function(t,e){return this._inlineViewRef=t.createEmbeddedView(e),this},t.prototype._registerOutsideClick=function(){var t=this;if(this._componentRef&&this._componentRef.location){if(this._listenOpts.outsideClick){var e=this._componentRef.location.nativeElement;setTimeout(function(){t._globalListener=Object(r.h)(t._renderer,{targets:[e,t._elementRef.nativeElement],outsideClick:t._listenOpts.outsideClick,hide:function(){return t._listenOpts.hide()}})})}if(this._listenOpts.outsideEsc){var n=this._componentRef.location.nativeElement;this._globalListener=Object(r.g)(this._renderer,{targets:[n,this._elementRef.nativeElement],outsideEsc:this._listenOpts.outsideEsc,hide:function(){return t._listenOpts.hide()}})}}},t.prototype.getInnerComponent=function(){return this._innerComponent},t.prototype._subscribePositioning=function(){var t=this;!this._zoneSubscription&&this.attachment&&(this.onShown.subscribe(function(){t._posService.position({element:t._componentRef.location,target:t._elementRef,attachment:t.attachment,appendToBody:"body"===t.container})}),this._zoneSubscription=this._ngZone.onStable.subscribe(function(){t._componentRef&&t._posService.calcPosition()}))},t.prototype._unsubscribePositioning=function(){this._zoneSubscription&&(this._zoneSubscription.unsubscribe(),this._zoneSubscription=null)},t.prototype._getContentRef=function(t,e,n){if(!t)return new i([]);if(t instanceof a.TemplateRef){if(this._viewContainerRef){var r=this._viewContainerRef.createEmbeddedView(t,e);return r.markForCheck(),new i([r.rootNodes],r)}var s=t.createEmbeddedView({});return this._applicationRef.attachView(s),new i([s.rootNodes],s)}if("function"==typeof t){var o=this._componentFactoryResolver.resolveComponentFactory(t),u=a.Injector.create({providers:this._providers,parent:this._injector}),c=o.create(u);return Object.assign(c.instance,n),this._applicationRef.attachView(c.hostView),new i([[c.location.nativeElement]],c.hostView,c)}return new i([[this._renderer.createText(""+t)]])},t}(),o=function(){function t(t,e,n,a,r){this._componentFactoryResolver=t,this._ngZone=e,this._injector=n,this._posService=a,this._applicationRef=r}return t.prototype.createLoader=function(t,e,n){return new s(e,n,t,this._injector,this._componentFactoryResolver,this._ngZone,this._applicationRef,this._posService)},t}()},lyxo:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a=" ";return(t%100>=20||t>=100&&t%100==0)&&(a=" de "),t+a+{ss:"secunde",mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"}[n]}n("wd/R").defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminic\u0103_luni_mar\u021bi_miercuri_joi_vineri_s\xe2mb\u0103t\u0103".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_S\xe2m".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_S\xe2".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[m\xe2ine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s \xeen urm\u0103",s:"c\xe2teva secunde",ss:e,m:"un minut",mm:e,h:"o or\u0103",hh:e,d:"o zi",dd:e,M:"o lun\u0103",MM:e,y:"un an",yy:e},week:{dow:1,doy:7}})}()},mChF:function(t,e,n){"use strict";function a(t){return t}n.d(e,"a",function(){return a})},mSOc:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("LvDl"),r=n("26FU"),i=n("CcnG"),s=n("t/Na"),o=n("ZYCi"),u=function(){function t(t,e,n){this.http=t,this.router=e,this.ngZone=n,this.summaryDataSource=new r.a(null),this.summaryData$=this.summaryDataSource.asObservable(),this.enablePolling()}return t.prototype.enablePolling=function(){var t=this;this.refresh(),this.ngZone.runOutsideAngular(function(){t.polling=window.setInterval(function(){t.ngZone.run(function(){t.refresh()})},5e3)})},t.prototype.refresh=function(){var t=this;"/login"!==this.router.url&&this.http.get("api/summary").subscribe(function(e){t.summaryDataSource.next(e)})},t.prototype.getCurrentSummary=function(){return this.summaryDataSource.getValue()},t.prototype.subscribe=function(t,e){return this.summaryData$.subscribe(t,e)},t.prototype.addRunningTask=function(t){var e=this.summaryDataSource.getValue();e&&(a.isArray(e.executing_tasks)?e.executing_tasks.find(function(e){return e.name===t.name&&a.isEqual(e.metadata,t.metadata)})||e.executing_tasks.push(t):e.executing_tasks=[t],this.summaryDataSource.next(e))},t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(s.c),i.inject(o.l),i.inject(i.NgZone))},token:t,providedIn:"root"}),t}()},mZXl:function(t,e,n){"use strict";n.d(e,"b",function(){return s}),n.d(e,"a",function(){return u});var a=n("mrSG"),r=n("FFOo"),i=n("60iU");function s(t,e){return void 0===e&&(e=0),function(n){return n.lift(new o(t,e))}}var o=function(){function t(t,e){void 0===e&&(e=0),this.scheduler=t,this.delay=e}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.scheduler,this.delay))},t}(),u=function(t){function e(e,n,a){void 0===a&&(a=0);var r=t.call(this,e)||this;return r.scheduler=n,r.delay=a,r}return a.__extends(e,t),e.dispatch=function(t){t.notification.observe(t.destination),this.unsubscribe()},e.prototype.scheduleMessage=function(t){this.destination.add(this.scheduler.schedule(e.dispatch,this.delay,new c(t,this.destination)))},e.prototype._next=function(t){this.scheduleMessage(i.a.createNext(t))},e.prototype._error=function(t){this.scheduleMessage(i.a.createError(t)),this.unsubscribe()},e.prototype._complete=function(){this.scheduleMessage(i.a.createComplete()),this.unsubscribe()},e}(r.a),c=function(){return function(t,e){this.notification=t,this.destination=e}}()},mgIt:function(t,e,n){var a=n("T016");function r(t){if(t){var e=[0,0,0],n=1,r=t.match(/^#([a-fA-F0-9]{3,4})$/i),i="";if(r){i=(r=r[1])[3];for(var s=0;s<e.length;s++)e[s]=parseInt(r[s]+r[s],16);i&&(n=Math.round(parseInt(i+i,16)/255*100)/100)}else if(r=t.match(/^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i)){for(i=r[2],r=r[1],s=0;s<e.length;s++)e[s]=parseInt(r.slice(2*s,2*s+2),16);i&&(n=Math.round(parseInt(i,16)/255*100)/100)}else if(r=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(s=0;s<e.length;s++)e[s]=parseInt(r[s+1]);n=parseFloat(r[4])}else if(r=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(s=0;s<e.length;s++)e[s]=Math.round(2.55*parseFloat(r[s+1]));n=parseFloat(r[4])}else if(r=t.match(/(\w+)/)){if("transparent"==r[1])return[0,0,0,0];if(!(e=a[r[1]]))return}for(s=0;s<e.length;s++)e[s]=l(e[s],0,255);return n=n||0==n?l(n,0,1):1,e[3]=n,e}}function i(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[l(parseInt(e[1]),0,360),l(parseFloat(e[2]),0,100),l(parseFloat(e[3]),0,100),l(isNaN(n)?1:n,0,1)]}}}function s(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[l(parseInt(e[1]),0,360),l(parseFloat(e[2]),0,100),l(parseFloat(e[3]),0,100),l(isNaN(n)?1:n,0,1)]}}}function o(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function u(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function c(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function l(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}t.exports={getRgba:r,getHsla:i,getRgb:function(t){var e=r(t);return e&&e.slice(0,3)},getHsl:function(t){var e=i(t);return e&&e.slice(0,3)},getHwb:s,getAlpha:function(t){var e=r(t);return e?e[3]:(e=i(t))?e[3]:(e=s(t))?e[3]:void 0},hexString:function(t,e){return e=void 0!==e&&3===t.length?e:t[3],"#"+d(t[0])+d(t[1])+d(t[2])+(e>=0&&e<1?d(Math.round(255*e)):"")},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?o(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:o,percentString:function(t,e){return e<1||t[3]&&t[3]<1?u(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:u,hslString:function(t,e){return e<1||t[3]&&t[3]<1?c(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:c,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return f[t.slice(0,3)]}};var f={};for(var p in a)f[a[p]]=p},mjYD:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha"),s=n("fELs"),o=i.noop;a._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var u=r.extend({initialize:function(t){i.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var a=this;return a.beforeUpdate(),a.maxWidth=t,a.maxHeight=e,a.margins=n,a.beforeSetDimensions(),a.setDimensions(),a.afterSetDimensions(),a.beforeBuildLabels(),a.buildLabels(),a.afterBuildLabels(),a.beforeFit(),a.fit(),a.afterFit(),a.afterUpdate(),a.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=t.options,n=e.display,r=(0,i.valueOrDefault)(e.fontSize,a.global.defaultFontSize),s=t.minSize,o=i.isArray(e.text)?e.text.length:1,u=i.options.toLineHeight(e.lineHeight,r),c=n?o*u+2*e.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=c):(s.width=c,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=i.valueOrDefault,r=t.options,s=a.global;if(r.display){var o,u,c,l=n(r.fontSize,s.defaultFontSize),d=n(r.fontStyle,s.defaultFontStyle),f=n(r.fontFamily,s.defaultFontFamily),p=i.fontString(l,d,f),h=i.options.toLineHeight(r.lineHeight,l),g=h/2+r.padding,b=0,m=t.top,y=t.left,v=t.bottom,_=t.right;e.fillStyle=n(r.fontColor,s.defaultFontColor),e.font=p,t.isHorizontal()?(u=y+(_-y)/2,c=m+g,o=_-y):(u="left"===r.position?y+g:_-g,c=m+(v-m)/2,o=v-m,b=Math.PI*("left"===r.position?-.5:.5)),e.save(),e.translate(u,c),e.rotate(b),e.textAlign="center",e.textBaseline="middle";var x=r.text;if(i.isArray(x))for(var T=0,w=0;w<x.length;++w)e.fillText(x[w],0,T,o),T+=h;else e.fillText(x,0,0,o);e.restore()}}});function c(t,e){var n=new u({ctx:t.ctx,options:e,chart:t});s.configure(t,n,e),s.addBox(t,n),t.titleBlock=n}t.exports={id:"title",_element:u,beforeInit:function(t){var e=t.options.title;e&&c(t,e)},beforeUpdate:function(t){var e=t.options.title,n=t.titleBlock;e?(i.mergeIf(e,a.global.title),n?(s.configure(t,n,e),n.options=e):c(t,e)):n&&(s.removeBox(t,n),delete t.titleBlock)}}},mlr9:function(t,e,n){"use strict";var a=n("RDha");function r(t,e){return t.native?{x:t.x,y:t.y}:a.getRelativePosition(t,e)}function i(t,e){var n,a,r,i,s;for(a=0,i=t.data.datasets.length;a<i;++a)if(t.isDatasetVisible(a))for(r=0,s=(n=t.getDatasetMeta(a)).data.length;r<s;++r){var o=n.data[r];o._view.skip||e(o)}}function s(t,e){var n=[];return i(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function o(t,e,n,a){var r=Number.POSITIVE_INFINITY,s=[];return i(t,function(t){if(!n||t.inRange(e.x,e.y)){var i=t.getCenterPoint(),o=a(e,i);o<r?(s=[t],r=o):o===r&&s.push(t)}}),s}function u(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,a){var r=e?Math.abs(t.x-a.x):0,i=n?Math.abs(t.y-a.y):0;return Math.sqrt(Math.pow(r,2)+Math.pow(i,2))}}function c(t,e,n){var a=r(e,t);n.axis=n.axis||"x";var i=u(n.axis),c=n.intersect?s(t,a):o(t,a,!1,i),l=[];return c.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var a=t.getDatasetMeta(n).data[c[0]._index];a&&!a._view.skip&&l.push(a)}}),l):[]}t.exports={modes:{single:function(t,e){var n=r(e,t),a=[];return i(t,function(t){if(t.inRange(n.x,n.y))return a.push(t),a}),a.slice(0,1)},label:c,index:c,dataset:function(t,e,n){var a=r(e,t);n.axis=n.axis||"xy";var i=u(n.axis),c=n.intersect?s(t,a):o(t,a,!1,i);return c.length>0&&(c=t.getDatasetMeta(c[0]._datasetIndex).data),c},"x-axis":function(t,e){return c(t,e,{intersect:!1})},point:function(t,e){return s(t,r(e,t))},nearest:function(t,e,n){var a=r(e,t);n.axis=n.axis||"xy";var i=u(n.axis),s=o(t,a,n.intersect,i);return s.length>1&&s.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),s.slice(0,1)},x:function(t,e,n){var a=r(e,t),s=[],o=!1;return i(t,function(t){t.inXRange(a.x)&&s.push(t),t.inRange(a.x,a.y)&&(o=!0)}),n.intersect&&!o&&(s=[]),s},y:function(t,e,n){var a=r(e,t),s=[],o=!1;return i(t,function(t){t.inYRange(a.y)&&s.push(t),t.inRange(a.x,a.y)&&(o=!0)}),n.intersect&&!o&&(s=[]),s}}}},mn2k:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("3MdB")),a(n("Cc8h")),a(n("ylLw")),a(n("M9eX")),a(n("uKs4"))},mrSG:function(t,e,n){"use strict";n.r(e),n.d(e,"__extends",function(){return r}),n.d(e,"__assign",function(){return i}),n.d(e,"__rest",function(){return s}),n.d(e,"__decorate",function(){return o}),n.d(e,"__param",function(){return u}),n.d(e,"__metadata",function(){return c}),n.d(e,"__awaiter",function(){return l}),n.d(e,"__generator",function(){return d}),n.d(e,"__exportStar",function(){return f}),n.d(e,"__values",function(){return p}),n.d(e,"__read",function(){return h}),n.d(e,"__spread",function(){return g}),n.d(e,"__await",function(){return b}),n.d(e,"__asyncGenerator",function(){return m}),n.d(e,"__asyncDelegator",function(){return y}),n.d(e,"__asyncValues",function(){return v}),n.d(e,"__makeTemplateObject",function(){return _}),n.d(e,"__importStar",function(){return x}),n.d(e,"__importDefault",function(){return T});var a=function(t,e){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)};function r(t,e){function n(){this.constructor=t}a(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var i=function(){return(i=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};function s(t,e){var n={};for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&e.indexOf(a)<0&&(n[a]=t[a]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(a=Object.getOwnPropertySymbols(t);r<a.length;r++)e.indexOf(a[r])<0&&(n[a[r]]=t[a[r]])}return n}function o(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s}function u(t,e){return function(n,a){e(n,a,t)}}function c(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)}function l(t,e,n,a){return new(n||(n=Promise))(function(r,i){function s(t){try{u(a.next(t))}catch(e){i(e)}}function o(t){try{u(a.throw(t))}catch(e){i(e)}}function u(t){t.done?r(t.value):new n(function(e){e(t.value)}).then(s,o)}u((a=a.apply(t,e||[])).next())})}function d(t,e){var n,a,r,i,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return i={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function o(i){return function(o){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,a&&(r=2&i[0]?a.return:i[0]?a.throw||((r=a.return)&&r.call(a),0):a.next)&&!(r=r.call(a,i[1])).done)return r;switch(a=0,r&&(i=[2&i[0],r.value]),i[0]){case 0:case 1:r=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,a=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!r||i[1]>r[0]&&i[1]<r[3])){s.label=i[1];break}if(6===i[0]&&s.label<r[1]){s.label=r[1],r=i;break}if(r&&s.label<r[2]){s.label=r[2],s.ops.push(i);break}r[2]&&s.ops.pop(),s.trys.pop();continue}i=e.call(t,s)}catch(o){i=[6,o],a=0}finally{n=r=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,o])}}}function f(t,e){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}function p(t){var e="function"==typeof Symbol&&t[Symbol.iterator],n=0;return e?e.call(t):{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}}}function h(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator];if(!n)return t;var a,r,i=n.call(t),s=[];try{for(;(void 0===e||e-- >0)&&!(a=i.next()).done;)s.push(a.value)}catch(o){r={error:o}}finally{try{a&&!a.done&&(n=i.return)&&n.call(i)}finally{if(r)throw r.error}}return s}function g(){for(var t=[],e=0;e<arguments.length;e++)t=t.concat(h(arguments[e]));return t}function b(t){return this instanceof b?(this.v=t,this):new b(t)}function m(t,e,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var a,r=n.apply(t,e||[]),i=[];return a={},s("next"),s("throw"),s("return"),a[Symbol.asyncIterator]=function(){return this},a;function s(t){r[t]&&(a[t]=function(e){return new Promise(function(n,a){i.push([t,e,n,a])>1||o(t,e)})})}function o(t,e){try{(n=r[t](e)).value instanceof b?Promise.resolve(n.value.v).then(u,c):l(i[0][2],n)}catch(a){l(i[0][3],a)}var n}function u(t){o("next",t)}function c(t){o("throw",t)}function l(t,e){t(e),i.shift(),i.length&&o(i[0][0],i[0][1])}}function y(t){var e,n;return e={},a("next"),a("throw",function(t){throw t}),a("return"),e[Symbol.iterator]=function(){return this},e;function a(a,r){e[a]=t[a]?function(e){return(n=!n)?{value:b(t[a](e)),done:"return"===a}:r?r(e):e}:r}}function v(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,n=t[Symbol.asyncIterator];return n?n.call(t):(t=p(t),e={},a("next"),a("throw"),a("return"),e[Symbol.asyncIterator]=function(){return this},e);function a(n){e[n]=t[n]&&function(e){return new Promise(function(a,r){!function(t,e,n,a){Promise.resolve(a).then(function(e){t({value:e,done:n})},e)}(a,r,(e=t[n](e)).done,e.value)})}}}function _(t,e){return Object.defineProperty?Object.defineProperty(t,"raw",{value:e}):t.raw=e,t}function x(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}function T(t){return t&&t.__esModule?t:{default:t}}},mtw6:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(t){return t[t.error=0]="error",t[t.info=1]="info",t[t.success=2]="success",t}({})},"n/D3":function(t,e,n){"use strict";n.d(e,"a",function(){return c}),n.d(e,"b",function(){return u});var a=n("VNr4"),r=(n("SgmB"),n("ZDA6"),n("0+/T")),i=(n("sne2"),n("x38r")),s=n("mtw6"),o=n("vCyI"),u=(n("nSDx"),n("aexS"),n("9nlD"),new(n("EgGo").a)("user-management/roles")),c=function(){function t(t,e,n,a,r,i,s,u,c){var l=this;this.roleService=t,this.scopeService=e,this.emptyPipe=n,this.authStorageService=a,this.modalService=r,this.notificationService=i,this.i18n=s,this.urlBuilder=u,this.actionLabels=c,this.selection=new o.a,this.permission=this.authStorageService.getPermissions().user,this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return l.urlBuilder.getCreate()},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",disable:function(){return!l.selection.hasSingleSelection||l.selection.first().system},routerLink:function(){return l.selection.first()&&l.urlBuilder.getEdit(l.selection.first().name)},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-times",disable:function(){return!l.selection.hasSingleSelection||l.selection.first().system},click:function(){return l.deleteRoleModal()},name:this.actionLabels.DELETE}]}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"name",flexGrow:3},{name:this.i18n("Description"),prop:"description",flexGrow:5,pipe:this.emptyPipe},{name:this.i18n("System Role"),prop:"system",cellClass:"text-center",flexGrow:1,cellTransformation:i.a.checkIcon}]},t.prototype.getRoles=function(){var t=this;Object(a.a)([this.roleService.list(),this.scopeService.list()]).subscribe(function(e){t.roles=e[0],t.scopes=e[1]})},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.deleteRole=function(t){var e=this;this.roleService.delete(t).subscribe(function(){e.getRoles(),e.modalRef.hide(),e.notificationService.show(s.a.success,e.i18n("Deleted role '{{role_name}}'",{role_name:t}))},function(){e.modalRef.content.stopLoadingSpinner()})},t.prototype.deleteRoleModal=function(){var t=this,e=this.selection.first().name;this.modalRef=this.modalService.show(r.a,{initialState:{itemDescription:"Role",itemNames:[e],submitAction:function(){return t.deleteRole(e)}}})},t}()},n1nk:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.header="header",t.body="body"}(e.ContextmenuType||(e.ContextmenuType={}))},nDWh:function(t,e,n){"use strict";var a=n("6ww4"),r=n("CDJp"),i=n("RDha"),s=n("tjFV");t.exports=function(){function t(t,e,n){var a;return"string"==typeof t?(a=parseInt(t,10),-1!==t.indexOf("%")&&(a=a/100*e.parentNode[n])):a=t,a}function e(t){return null!=t&&"none"!==t}function n(n,a,r){var s=document.defaultView,o=i._getParentNode(n),u=s.getComputedStyle(n)[a],c=s.getComputedStyle(o)[a],l=e(u),d=e(c),f=Number.POSITIVE_INFINITY;return l||d?Math.min(l?t(u,n,r):f,d?t(c,o,r):f):"none"}i.configMerge=function(){return i.merge(i.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(t,e,n,a){var r=e[t]||{},o=n[t];"scales"===t?e[t]=i.scaleMerge(r,o):"scale"===t?e[t]=i.merge(r,[s.getScaleDefaults(o.type),o]):i._merger(t,e,n,a)}})},i.scaleMerge=function(){return i.merge(i.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(t,e,n,a){if("xAxes"===t||"yAxes"===t){var r,o,u,c=n[t].length;for(e[t]||(e[t]=[]),r=0;r<c;++r)o=i.valueOrDefault((u=n[t][r]).type,"xAxes"===t?"category":"linear"),r>=e[t].length&&e[t].push({}),i.merge(e[t][r],!e[t][r].type||u.type&&u.type!==e[t][r].type?[s.getScaleDefaults(o),u]:u)}else i._merger(t,e,n,a)}})},i.where=function(t,e){if(i.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return i.each(t,function(t){e(t)&&n.push(t)}),n},i.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var a=0,r=t.length;a<r;++a)if(e.call(n,t[a],a,t))return a;return-1},i.findNextWhere=function(t,e,n){i.isNullOrUndef(n)&&(n=-1);for(var a=n+1;a<t.length;a++){var r=t[a];if(e(r))return r}},i.findPreviousWhere=function(t,e,n){i.isNullOrUndef(n)&&(n=t.length);for(var a=n-1;a>=0;a--){var r=t[a];if(e(r))return r}},i.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},i.almostEquals=function(t,e,n){return Math.abs(t-e)<n},i.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},i.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},i.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},i.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},i.log10=Math.log10?function(t){return Math.log10(t)}:function(t){var e=Math.log(t)*Math.LOG10E,n=Math.round(e);return t===Math.pow(10,n)?n:e},i.toRadians=function(t){return t*(Math.PI/180)},i.toDegrees=function(t){return t*(180/Math.PI)},i.getAngleFromPoint=function(t,e){var n=e.x-t.x,a=e.y-t.y,r=Math.sqrt(n*n+a*a),i=Math.atan2(a,n);return i<-.5*Math.PI&&(i+=2*Math.PI),{angle:i,distance:r}},i.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},i.aliasPixel=function(t){return t%2==0?0:.5},i.splineCurve=function(t,e,n,a){var r=t.skip?e:t,i=e,s=n.skip?e:n,o=Math.sqrt(Math.pow(i.x-r.x,2)+Math.pow(i.y-r.y,2)),u=Math.sqrt(Math.pow(s.x-i.x,2)+Math.pow(s.y-i.y,2)),c=o/(o+u),l=u/(o+u),d=a*(c=isNaN(c)?0:c),f=a*(l=isNaN(l)?0:l);return{previous:{x:i.x-d*(s.x-r.x),y:i.y-d*(s.y-r.y)},next:{x:i.x+f*(s.x-r.x),y:i.y+f*(s.y-r.y)}}},i.EPSILON=Number.EPSILON||1e-14,i.splineCurveMonotone=function(t){var e,n,a,r,s,o,u,c,l,d=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),f=d.length;for(e=0;e<f;++e)if(!(a=d[e]).model.skip){if(n=e>0?d[e-1]:null,(r=e<f-1?d[e+1]:null)&&!r.model.skip){var p=r.model.x-a.model.x;a.deltaK=0!==p?(r.model.y-a.model.y)/p:0}a.mK=!n||n.model.skip?a.deltaK:!r||r.model.skip?n.deltaK:this.sign(n.deltaK)!==this.sign(a.deltaK)?0:(n.deltaK+a.deltaK)/2}for(e=0;e<f-1;++e)r=d[e+1],(a=d[e]).model.skip||r.model.skip||(i.almostEquals(a.deltaK,0,this.EPSILON)?a.mK=r.mK=0:(s=a.mK/a.deltaK,o=r.mK/a.deltaK,(c=Math.pow(s,2)+Math.pow(o,2))<=9||(u=3/Math.sqrt(c),a.mK=s*u*a.deltaK,r.mK=o*u*a.deltaK)));for(e=0;e<f;++e)(a=d[e]).model.skip||(r=e<f-1?d[e+1]:null,(n=e>0?d[e-1]:null)&&!n.model.skip&&(a.model.controlPointPreviousX=a.model.x-(l=(a.model.x-n.model.x)/3),a.model.controlPointPreviousY=a.model.y-l*a.mK),r&&!r.model.skip&&(a.model.controlPointNextX=a.model.x+(l=(r.model.x-a.model.x)/3),a.model.controlPointNextY=a.model.y+l*a.mK))},i.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},i.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},i.niceNum=function(t,e){var n=Math.floor(i.log10(t)),a=t/Math.pow(10,n);return(e?a<1.5?1:a<3?2:a<7?5:10:a<=1?1:a<=2?2:a<=5?5:10)*Math.pow(10,n)},i.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},i.getRelativePosition=function(t,e){var n,a,r=t.originalEvent||t,s=t.target||t.srcElement,o=s.getBoundingClientRect(),u=r.touches;u&&u.length>0?(n=u[0].clientX,a=u[0].clientY):(n=r.clientX,a=r.clientY);var c=parseFloat(i.getStyle(s,"padding-left")),l=parseFloat(i.getStyle(s,"padding-top")),d=parseFloat(i.getStyle(s,"padding-right")),f=parseFloat(i.getStyle(s,"padding-bottom")),p=o.bottom-o.top-l-f;return{x:n=Math.round((n-o.left-c)/(o.right-o.left-c-d)*s.width/e.currentDevicePixelRatio),y:a=Math.round((a-o.top-l)/p*s.height/e.currentDevicePixelRatio)}},i.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},i.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},i._calculatePadding=function(t,e,n){return(e=i.getStyle(t,e)).indexOf("%")>-1?n/parseInt(e,10):parseInt(e,10)},i._getParentNode=function(t){var e=t.parentNode;return e&&e.host&&(e=e.host),e},i.getMaximumWidth=function(t){var e=i._getParentNode(t);if(!e)return t.clientWidth;var n=e.clientWidth,a=n-i._calculatePadding(e,"padding-left",n)-i._calculatePadding(e,"padding-right",n),r=i.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},i.getMaximumHeight=function(t){var e=i._getParentNode(t);if(!e)return t.clientHeight;var n=e.clientHeight,a=n-i._calculatePadding(e,"padding-top",n)-i._calculatePadding(e,"padding-bottom",n),r=i.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},i.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},i.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&window.devicePixelRatio||1;if(1!==n){var a=t.canvas,r=t.height,i=t.width;a.height=r*n,a.width=i*n,t.ctx.scale(n,n),a.style.height||a.style.width||(a.style.height=r+"px",a.style.width=i+"px")}},i.fontString=function(t,e,n){return e+" "+t+"px "+n},i.longestText=function(t,e,n,a){var r=(a=a||{}).data=a.data||{},s=a.garbageCollect=a.garbageCollect||[];a.font!==e&&(r=a.data={},s=a.garbageCollect=[],a.font=e),t.font=e;var o=0;i.each(n,function(e){null!=e&&!0!==i.isArray(e)?o=i.measureText(t,r,s,o,e):i.isArray(e)&&i.each(e,function(e){null==e||i.isArray(e)||(o=i.measureText(t,r,s,o,e))})});var u=s.length/2;if(u>n.length){for(var c=0;c<u;c++)delete r[s[c]];s.splice(0,u)}return o},i.measureText=function(t,e,n,a,r){var i=e[r];return i||(i=e[r]=t.measureText(r).width,n.push(r)),i>a&&(a=i),a},i.numberOfLabelLines=function(t){var e=1;return i.each(t,function(t){i.isArray(t)&&t.length>e&&(e=t.length)}),e},i.color=a?function(t){return t instanceof CanvasGradient&&(t=r.global.defaultColor),a(t)}:function(t){return console.error("Color.js not found!"),t},i.getHoverColor=function(t){return t instanceof CanvasPattern?t:i.color(t).saturate(.5).darken(.1).rgbString()}}},nSDx:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("LvDl"),r=function(){function t(){}return t.prototype.transform=function(t){return a.isUndefined(t)||a.isNull(t)?"-":t},t}()},nhM1:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DimensionsHelper=function(){function t(){}return t.prototype.getDimensions=function(t){return t.getBoundingClientRect()},a([r.Injectable()],t)}()},nkY7:function(t,e,n){"use strict";function a(t){return t&&"function"==typeof t.schedule}n.d(e,"a",function(){return a})},nmKl:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="id-ID">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Pengalih navigasi</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Dasbor</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Klaster</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Hos</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Monitor</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Konfigurasi</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>peta CRUSH</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Modul Ceph Manajer</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Log</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Peringatan</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Blok</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Image</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Pencerminan</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Sistemfile</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Gerbang Objek</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Pengguna</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Buket</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Menerima data \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> untuk \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Mohon tunggu...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Menampilkan data \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> sebelumnya \nuntuk \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Gagal memuat data \n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> untuk\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\nMohon periksa kesehatan klaster.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Kembali</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>Pilih bahasa</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Memuat data panel...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Silakan merujuk ke\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentasi \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> tentang\ncara mengonfigurasi dan mengaktifkan fungsi pemantauan.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Dasbor Grafana tidak ada. Mohon merujuk ke\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> tentang cara\nmenambahkan dasbor ke Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Pemilih Waktu Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>Reset Pengaturan</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>Gagal memuat data.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>dipilih</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>ditemukan</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>total</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Edit</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nama</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Deskripsi</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Deskripsi lengkap</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Bawaan</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Daemon bawaan</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Layanan</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Nilai</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu tinggi! Tidak boleh lebih besar dari \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu rendah! Tidak boleh lebih rendah dari \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Simpan</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>Penampil peta CRUSH</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Daftar Hos</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Performa Keseluruhan</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Entri tidak ditemukan</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Log Klaster</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Log Audit</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Memuat konfigurasi...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>Konfigurasi tidak dapat dimuat.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Edit modul Ceph Manajer</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>Nilai yang dimasukkan bukan UUID yang valid, cth: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>Nilai yang dimasukkan harus alamat IP yang valid.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Isian ini tidak boleh kosong.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu tinggi! Harus lebih kecil atau sama dengan \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu rendah! Harus lebih besar atau sama dengan \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>Nilai yang dimasukkan harus berupa angka.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>Nilai yang dimasukkan harus berupa angka atau desimal.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Perbarui</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Status</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>ID Klaster</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap diubah</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap epoch</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>kuorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>kuorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>con yang dibutuhkan</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>mon yang dibutuhkan</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>Memenuhi Kuorum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Tidak dalam Kuorum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Batal</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Anda yakin ingin \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> dari \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Ya, saya yakin.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Flag OSD Klaster</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Kirim</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Tingkat lanjut...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Prioritas pemulihan OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Prioritas</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Ubah nilai prioritas</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Isian ini harus diisi!</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu tinggi! Tidak boleh lebih tinggi dari \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>Nilai yang dimasukkan terlalu rendah! Tidak boleh lebih rendah dari \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>Ubah bobot OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>Nilai harus antara 0 dan 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>Ubah bobot</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Dalam } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Anda akan menerapkan\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> scrub pada\nOSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {dalam } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Daftar OSD</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> akan ditandai\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> jika ingin melanjutkan.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>OSD tidak aman untuk dihancurkan!</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> akan\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> jika ingin melanjutkan.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>Detail</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Nilai</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Tutup</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Hapus</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Kesehatan</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statistik </target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Mohon periksa \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\ntentang cara mengonfigurasi dan aktfikan fungsi manajemen NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Klien</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Semua klien dapat mengakses</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Alamat</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Wajib diisi</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Harus mengandung satu atau lebih nilai yang dipisahkan koma</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Contoh:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Tipe Akses</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Tambah klien</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Memuat...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- Klaster tidak tersedia --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- Pilih klaster --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Tambah daemon</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Backend Penyimpanan</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- Tidak ada pool data tersedia --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- Pilih backend penyimpanan --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Pengguna Gerbang Objek</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- Pengguna tidak tersedia --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- Pilih pengguna gerbang objek --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>ID Pengguna CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- Klien tidak tersedia --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- Pilih klien cephx --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nama CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Label Keamanan</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Aktifkan label keamanan</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS Path</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>Lintasan atau path harus dimulai dengan \'/\' dan diikuti dengan kata</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Direktori baru akan dibuat</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Path</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>Path hanya boleh berupa \'/\' atau kata</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Buket baru akan dibuat</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protokol NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Tag NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Alternatif akses untuk mount \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFSv3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (tidak boleh diawali /).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Klien mungkin tidak dapat mount subdirektori (cth. jika Tag = foo, klien mungkin tidak bisa mount foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>Dengan menggunakan opsi Tag yang berbeda, Path yang sama akan diekspor beberapa kali.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>Posisi dari \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> yang diekspor ini menempati \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> Pseudo FS \n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (ini harus unik).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>Dengan menggunakan opsi Pseudo yang berbeda, Path yang sama akan diekspor beberapa kali.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- Tipe akses tidak tersedia --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- Pilih tipe akses --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- Squash tidak tersedia --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- Pilih jenis squashing id pengguna yang akan dilakukan --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protokol Transport</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Selamat datang di Ceph!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Nama pengguna harus diisi</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Kata sandi harus diisi</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Masuk</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>Maaf, pengguna tidak terdaftar di Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Kembali ke Halaman Masuk \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Anda akan dikeluarkan dari Penyedia Identitas saat Anda mencoba masuk.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Terlarang</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>Maaf, Anda tidak dizinkan melihat hal yang Anda inginkan.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>Maaf, kami tidak dapat menemukan yang Anda cari</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Hapus semua</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Notifikasi terkini</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Tidak ada tugas latar belakang.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>Tugas Latar Belakang</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Bantuan</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Dokumentasi </target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>Tentang</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Pengaturan Dasbor</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Manajemen Pengguna</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Pengguna masuk</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Masuk sebagai\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Keluar</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nama...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Nama yang dipilih sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Deskripsi...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Izin</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>Peran</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nama pengguna</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Kata sandi</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Konfirmasi kata sandi</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Konfirmasi kata sandi tidak sesuai dengan kata sandi.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Nama lengkap</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>Email</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>Email tidak valid.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Anda akan menghapus izin "pengguna baca / perbarui" dari diri Anda sendiri.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Jika melanjutkan, Anda tidak akan lagi dapat menambahkan atau menghapus peran dari pengguna manapun.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Anda yakin ingin melanjutkan?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Penghitung kinerja tidak tersedia</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Atribut (peta OSD)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>Metadata tidak tersedia</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>Metadata</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Penghitung kinerja</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histogram tidak tersedia: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>Tulis</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Baca</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histogram</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>Detail Performa</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Nilai saat ini</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Tipe</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Min</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Maks</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Flag</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Sumber</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Level</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Boleh diperbarui saat dijalankan (bisa diedit)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Tag</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Nilai Enum</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Lihat juga</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Status Klaster</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Manajer Daemon</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Gerbang Objek</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Server Metadata</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>Gateway iSCSI</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>IOPS klien</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>Throughput Pengguna</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Baca/Tulis Klien</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>Throughput Pemulihan</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Scrub</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Kinerja</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Kapasitas mentah</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objek</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>PG per OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Status PG</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Kapasitas</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Lihat \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> Log untuk detil lainnya.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Peringkat</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Klien: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>Pindahkan image ke tempat sampah</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Untuk pindahkan \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> ke tempat sampah,\ntekan \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Pindah Image \n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Anda juga dapat memilih tanggal kedaluwarsa.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>Proteksi berakhir pada</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>TIDAK DIPROTEKSI</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Format tanggal salah. Mohon gunakan "TTTT-BB-HH JJ:mm:dd".</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>Proteksi telah kedaluarsa. Mohon pilih tanggal masa mendatang atau kosongkan.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>Pindahkan Image</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Ikhtisar</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Target</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Otentikasi Discovery</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Pengguna</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Nama pengguna harus terdiri dari 8 hingga 64 karakter dan\nhanya boleh mengandung huruf, \'.\', \'@\', \'-\', \'_\' atau \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Pengguna Bersama</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Kata sandi bersama</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Mohon cek ke \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\ntentang cara mengonfigurasi dan mengaktifkan fungsi manajemen iSCSI Target.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informasi tersedia:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>iSCSI Target tidak tersedia</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Hanya tersedia untuk image RBD dengan \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> yang diaktifkan.\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>Pool</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>Pool Data</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Dibuat</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Ukuran</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Ukuran objek</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Fitur</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Disiapkan</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/A</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Total disiapkan</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Unit setrip</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Jumlah setrip</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Induk</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Awalan nama blok</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Urutan</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Snapshot</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Image</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Pengaturan ini akan membatalkan nilai global</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Global</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Ini adalah nilai global. Tidak ada nilai yang diset untuk image ini.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\'/\' dan \'@\' tidak diperbolehkan.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- Tidak ada pool rbd tersedia --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- Pilih pool --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Gunakan pool data terdedikasi</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>Pool data</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>Pool terdedikasi yang menyimpan data-objek dari RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>cth. 10GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Anda harus menaikkan ukuran.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Tingkat lanjut</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Setrip</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Unit setrip</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- Pilih ukuran setrip --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Isian ini harus diisi karena jumlah setrip telah ditentukan!</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>Unit setrip lebih besar dari ukuran objek.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Jumlah setrip</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Isian wajib diisi karena unit setrip didefinisikan!</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Jumlah setrip harus lebih besar dari 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot RBD\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Ganti nama} other {Buat} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>DIPROTEKSI</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>TIDAK DIPROTEKSI</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Anda akan mengembalikan semula</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Kosongkan Tempah Sampah</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Untuk menghapus, pilih satu atau Semua image dan pilih</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>Pool:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nama Pool...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Semua</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Pulihkan Image</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Untuk memulihkan</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>ketik nama baru image dan pilih</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nama Baru</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Kedaluwarsa pada</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Diproteksi hingga</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Image ini diproteksi hingga \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Tempat sampah</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologi iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Mengganti parameter ini dari nilai bawaan biasanya tidak diperlukan.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Pengaturan</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Konfirmasi</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Pengaturan Lanjut</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>Target IQN</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>Pola IQN salah.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Suatu IQN memiliki notasi seperti ini \'iqn.$tahun-$bulan.$reversedAddress:$definedName\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Contoh: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Informasi lainnya</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Pengaturan lanjutan target ini telah dimodifikasi.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portal</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Dibutuhkan min \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gerbang/gateway.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Tambahkan portal</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Pengaturan Image ini telah dimodifikasi.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Tambahkan image</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Otentikasi ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Inisiator</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Inisiator</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>Klien IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>Inisiator IQN harus unik.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Nama pengguna harus terdiri atas 8 hingga 64 karakter dan\nhanya boleh mengandung huruf, \'.\', \'@\', \'-\', \'_\' atau \':\'.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>Inisiator termasuk ke dalam grup. Image akan dikonfigurasi di dalam grup.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Tidak ada yang ditambahkan.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Tambahkan inisiator</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Grup</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Grup</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Tambahkan grup</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Konfigurasi RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Menghapus nilai konfigurasi lokal. Nilai konfigurasi induk akan diturun dan digunakan.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>Nilai minimum adalah 0</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Masalah</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Menyinkronkan</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Siap</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Edit mode pencerminan pool</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Untuk mengubah mode pencerminan pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, pilih mode baru dari daftar dan klik\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Perbarui\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Mode</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Klaster mitra harus dihapus sebelum menonaktfikan pencerminan.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\nmitra pencerminan pool\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Edit} other {Tambah} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> pool\natribut mitra pencerminan untuk pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> dan klik \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Kirim\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nama Klaster</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>Nama klaster tidak valid.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>CephX ID tidak valid.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Alamat Monitor</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Alamat dengan pemisah-koma...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>Alamat monitor tidak valid.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX Key</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64-encoded key...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>Kunci CephX harus base64 encoded.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Daftar pool</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>Nama hanya boleh terdiri dari alfanumerik, tanda hubung, dan garis bawah.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Nama profil erasure code sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Plugin</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Pecahan data (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Harus sama dengan atau lebih dari 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Pecahan Coding (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Harus sama dengan atau lebih dari 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Penduga daya tahan (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Lokalitas (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Domain kegagalan Crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Lokalitas Crush</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Tidak ada</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Teknik</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Ukuran paket</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Crush root</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Kelas perangkat Crush</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>apa saja</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>Direktori</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Nama pool Ceph yang dipilih sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Jenis pool</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- Pilih jenis pool --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Grup penempatan</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Dibutuhkan setidaknya satu grup penempatan!</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Klaster Anda tidak dapat menangani PG sebanyak ini. Mohon hitung ulang jumlah PG yang dibutuhkan.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Bantuan penghitungan</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>Pengaturan PG saat ini telah dihitung untuk Anda, Anda\nharus memastikan nilai tersebut sesuai kebutuhan sebelum mengajukan.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Aturan CRUSH</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Pilih aturan crush --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Aturan crush</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Crush steps</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>Aturan crush tidak dapat digunakan di klaster ini karena\njumlah OSD terlalu sedikit untuk memenuhi syarat minimal OSD untuk aturan ini.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Jumlah replikasi</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Maksimum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>Ukuran yang dimasukkan di luar jangkauan. Nilai yang valid\ndari \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> hingga \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Profil erasure code</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- Tidak ada profil erasure code --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- Pilih profil erasure code --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC Overwrites</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Aplikasi</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Kompresi</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algoritma</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- Tidak ada algoritma pengompresian erasure --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Ukuran blob minimum</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>cth. 128KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>Nilai harus lebih besar dari 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Ukuran maksimum blob</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>cth. 512KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>Nilai harus lebih besar dari ukuran minimum blob</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Rasio</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Rasio kompresi</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>Nilai harus antara 0.0 dan 1.0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Tidak boleh membuat pool RBD dengan nama yang mengandung \'/\'.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Mohon ganti atau hapus \'rbd\' dari daftar aplikasi.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>Detil Cache Bertingkat</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Silakan cek kembali \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi \n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\ntentang cara mengonfigurasi dan mengaktifkan fungsi manajemen Gerbang Objek.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Daftar Daemon</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Penghitung Performa</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Memuat data buket...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Buket data tidak dapat dimuat.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>Id</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>Nilai tidak valid.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Pemilik</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- Pilih pengguna --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Jenis indeks</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>Aturan penempatan</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Penanda</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Penanda maksimum</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Versi</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Versi Master</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Modifikasi waktu</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Zona grup</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Kuota Buket</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Diaktifkan</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Ukuran maksimum</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Tak terbatas</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Objek maksimum</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- Pilih nama pengguna --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>Kunci otomatis-dibuat</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Kunci akses</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Kunci rahasia</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Alamat email</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Dihentikan</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Sistem</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {Tidak} 1 {Ya} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Buket maksimum</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Subpengguna</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Kemampuan</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Kuota pengguna</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Tampilkan</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Kunci</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- Pilih tipe --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Izin</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- Pilih izin --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Subpengguna</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>ID subpengguna sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>baca, tulis</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>penuh</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Kunci Swift</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>Sandi otomatis-dibuat</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Memuat data pengguna...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>Data pengguna tidak dapat dimuat.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>ID pengguna yang dipilih sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Ini bukan alamat email yang valid.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>Alamat email yang dipilih sudah digunakan.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Maks. buket</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>Nilai yang dimasukkan harus &gt;= 0.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>Kunci S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Tidak ada sub-pengguna.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Kunci tidak ditemukan.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Kemampuan tidak ada.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Ukuran tak terbatas</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Ukuran maks.</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Objek tak terbatas</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Objek maks.</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Terkini</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Otentikasi penemuan telah diperbarui</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Tidak ada portal yang tersedia.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Tidak ada image yang tersedia.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Tidak ada image yang tersedia. Mohon pastikan Anda telah menambahkan image ke target.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Tidak ada inisiator tersedia. Mohon pastikan Anda telah menambahkan inisiator ke target.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Target</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>Keadaan</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Baca Bytes</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Tulis Bytes</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Ops Baca</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Ops Tulis</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O Sejak</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instance</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nama hos</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Isu</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Kemajuan</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>Dimatikan</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Mode Edit</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Tambahkan Mitra</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Edit Mitra</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Hapus Mitra</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Pemimpin</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target># Lokal</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target># Jauh</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>mitra pencerminan</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Kunci</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Perataan mendalam</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Lapisan</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Kunci eksklusif</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Peta objek (butuh kunci-eksklusif)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Penjurnalan (membutuhkan kunci-eksklusif)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Kembalikan snapshot RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Kembalikan</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Snapshot RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Dihapus pada</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>id</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>tipe</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>keadaan</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>versi</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>Hos</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>induk</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Peringkat</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Aktivitas</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inode</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Penggunaan</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Daemon siaga</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>Nilai dapat diperbarui saat runtime.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Daemon/klien tidak dapat mengambil nilai dari\nbasis data konfigurasi monitor. Kami tidak mengizinkan mengubah ini dari \'ceph config\nset ...\'. Pilihan ini harus dikonfigurasi melalui ceph.conf atau CLI.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>Pilihan hanya dapat bekerja selama daemon dimulai.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>Pilihan hanya berpengaruh pada pembuatan klaster.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>Pilihan hanya berpengaruh pada pembuatan daemon.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Perbarui opsi konfigurasi \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Layanan</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Nilai saat ini</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Dapat diedit</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Opsi diperbarui untuk modul &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Aktifkan</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>Nonaktifkan</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Menghubungkan kembali, mohon tunggu...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Alamat Publik</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Buka Sesi</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Tidak boleh Masuk</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>OSD yang telah ditandai keluar tidak akan ditandai masuk saat mereka menyala</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Tidak boleh Keluar</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD tidak akan otomatis ditandai keluar setelah interval dikonfigurasi</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Tidak Nyala</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSD tidak diizinkan menyala</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Tidak Mati</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Laporan kegagalan OSD sedang diabaikan sehingga monitor tidak akan menandai OSD mati</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Jeda</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Jeda baca dan tulis</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Nonaktifkan Scrub</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Scrubbing dinonaktifkan</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Nonaktifkan Deep Scrub</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Deep Scrubing dinonaktifkan</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Tidak ada Penambalan</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Penambalan PG dihentikan</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Tidak ada Pemulihan</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>Pemulihan PG dihentikan</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Urutan Bitwise</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Gunakan urutan bitwise</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Buang Snapdirs</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD memiliki snapset yang dikonversi</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Pulihkan yang telah dihapus</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Penghapusan dilakukan saat pemulihan bukan saat bermitra</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Batas Maks Log PG</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Taruh batas maks pada panjang log pg</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Flag OSD diperbarui</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>keluar</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>masuk</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>gugur</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Tandai</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD hilang</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>ditandai hilang</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Buang</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>dibuang</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>hancurkan</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>dihancurkan</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>PG</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Bita baca</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Bita tulis</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Ops baca</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Ops tulis</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Tandai OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Tandai \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Maks Penambalan</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Maks Pemulihan Aktif</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Maks Menjalankan Pemulihan Tunggal</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Jeda Pemulihan</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Ubahsuai</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Piroritas &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot; kecepatan pemulihan OSD diperbarui.\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> telah diinisialisasi pada OSD berikut: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Tugas</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Keparahan</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>Dimulai</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Diperbarui</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Terpakai</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Tersedia</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Bersih</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>Bekerja</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Peringatan</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Tidak diketahui</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>nyala</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>tidak ada filesistem</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>aktif</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>siaga</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/a</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>daemon aktif</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>kuorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Layanan NFS Ganesha belum dikonfigurasi.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transport</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>Pengguna CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>Filesistem CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(diturunkan dari konfig global)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>diturunkan dari konfig global</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- Pilih jenis squashing id pengguna yang akan dilakukan --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Tidak ada daemon tersedia.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Mode Cache</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>Min Waktu Usir</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>Min Waktu Buang</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Target Maks Bita</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Target Maks Objek</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Tidak ada aplikasi ditambahkan</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Batas aplikasi tercapai</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Sebuah pool hanya dapat memiliki empat definisi aplikasi.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Karakter diperbolehkan \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>Panjang maksimum 128 karakter</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Saring atau tambah aplikasi</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Tambah aplikasi</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>profil erasure code</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Ukuran Replikasi</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Perubahan Terakhir</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Profil Erasure Code</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Aturan Crush</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Bita tulis</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>buket</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Buket Gerbang Objek &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; diperbarui\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Buat buket Gerbang Objek &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>buket</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>pengguna</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Perbarui pengguna Gerbang Objek &amp;quot\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>;&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Buat pengguna Gerbang Objek &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>pengguna</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>Cakupan</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Baca</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Buat</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Peran \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' dibuat\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Peran \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' diperbarui\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>Peran Sistem</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>Peran \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' dihapus\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Pengguna &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; dibuat\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Perbarui pengguna</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Lanjutkan</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Anda dikeluarkan otomatis karena peran Anda telah berubah.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Perbarui pengguna &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Hapus pengguna &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Gagal menghapus pengguna &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Saat ini Anda masuk sebagai &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Tiap objek dipecah dalam pecahan-data, masing-masing disimpan pada OSD yang berbeda.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Hitung pecahan coding untuk tiap objek dan simpan pada OSD yang berbeda.\nJumlah pecahan data juga menjadi jumlah OSD yang diperbolehkan mati tanpa kehilangan data.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Plugin jerasure merupakan plugin paling umum dan fleksibel,\nserta merupakan plugin bawaan Ceph untuk pool erasure code.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>Teknik yang lebih fleksibel yaitu reed_sol_van : cukup mengeset k\ndan m. Teknik cauchy_good bisa lebih cepat, namun Anda harus memilih ukuran paket\ndengan seksama. Semua reed_sol_r6_op, liberation, blaum_roth, liber8tion setara dengan RAID6\ndalam hal mereka hanya bisa diatur dengan m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>Penyandian dilakukan setiap saat pada ukuran bita paket.\nSulit untuk menentukan ukuran paket yang tepat.\nSilakan cek dokumentasi jerasure untuk informasi lebih mendalam.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Pada plugin jerasure, saat objek dengan erasure code disimpan pada\nbanyak OSD, pemulihan dari OSD yang hilang membutuhkan akses dari OSD lainnya.\nContoh, saat jerasure dikonfigurasi dengan k=8 dan m=4, saat satu OSD mati, maka pemulihan akan membutuhkan pembacaan dari tujuh OSD lainnya.\n\nPlugin lrc erasure code membuat pecahan paritas lokal agar dapat memulihkan \ndengan OSD yang lebih sedikit. Contoh, jika lrc dikonfigurasi dengan k=8, m=4, dan l=4, maka lrc akan\nmembuat pecahan paritas tambahan tiap empat OSD. Saat satu OSD mati, maka pemulihan dapat dilakukan hanya dengan 4 OSD, alih-alih 7 OSD.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Kelompokkan pecahan data dan coding ke dalam ukuran lokalitas. Controh\nuntuk k=4 dan m=2, saat lokalitas=3 dua grup dari tiga akan dibuat. Setiap set akan\ndipulihkan tanpa membaca pecahan dari set lainnya.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>Tipe buket crush setiap set pecahan yang didefinisikan oleh l \nakan disimpan. Contoh, jika diset pada rak, tiap grup pecahan l akan \nditempatkan pada rak berbeda. Ini akan digunakan pada aturan step CRUSH yaitu \nmemilih tiap rak. Jika tidak diset, tidak akan ada pengelompokkan.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Plugin isa menghimpun perpustakaan ISA. Hanya dapat berjalan pada prosesor Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>Plugin ISA memiliki dua jenis Reed Solomon.\nJika reed_sol_van diset, maka menjadi Vandermonde, jika cauchy diset, maka menjadi Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>Plugin shec mengenkapsulasi banyak pustaka SHEC.\nHal ini agar ceph dapat dipulihkan dengan lebih efisien dari kode Reed Solomon.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>Jumlah potongan paritas yang masing-masing mencakup setiap potongan data \ndalam rentang perhitungannya. Nilai ini digunakan untuk perkiraan daya tahan. Contoh, jika c=2, \n2 OSD dapat mati tanpa kehilangan data.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>Nama buket crush digunakan sebagai langkah pertama dari aturan CRUSH.\nContoh diambil langkah bawaan.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>Memastikan tidak ada pecahan data berada pada buket dengan domain kegagalan\nyang sama. Contoh, saat domain gagal adalah hos, maka tidak ada pecahan data yang akan disimpan \npada hos yang sama. Aturan CRUSH seperti step chooseleaf hos akan digunakan untuk hal tersebut.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Batasi penempatan ke perangkat dengan kelas tertentu\n(cth. ssd atau hdd), menggunakan nama kelas perangkat crush pada peta CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>Set nama direktori empat plugin erasure code akan dimuat.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Izinkan semua operasi</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Izinkan hanya untuk operasi yang tidak mengubah server</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>Tidak diizinkan untuk operasi baca dan tulis, namun izinkan operasi lainnya</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>Tidak diizinkan untuk baca, tulis, atau operasi lainnya yang mengubah atribut berkas atau konten direktori</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>Tidak diizinkan untuk semua hal</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- Pilih prioritas --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Rendah</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>Tinggi</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>5 menit terakhir</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>15 menit terakhir</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>30 menit terakhir</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>1 Jam Terakhir (Bawaan)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>3 jam terakhir</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>6 jam terakhir</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>12 jam terakhir</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>24 jam terakhir</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Kemarin</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Hari ini</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Sejauh hari ini</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Kemarin dulu</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>2 hari terakhir</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Hari ini minggu lalu</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>Minggu lalu</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Minggu ini</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Sejauh minggu ini</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>7 hari terakhir</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>Bulan lalu</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Bulan ini</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Sejauh bulan ini</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>30 hari terakhir</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>90 hari terakhir</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>6 bulan terakhir</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>1 tahun terakhir</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>Tahun lalu</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Tahun ini</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Sejauh tahun ini</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>2 tahun terakhir</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>5 tahun terakhir</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informasi</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Tidak ada yang dipilih.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>Batalkan memilih untuk memilih ulang</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Batas pemilihan tercapai</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Tanda penyaringan</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Tambahkan lencana</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Tidak ada yang tersedia.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Tambah</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Klon</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Salin</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Deep Scrub</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>Hancurkan</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Ratakan</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Tandai Gugur</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Tandai Masuk</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Tandai Hilang</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Tandai Keluar</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Proteksi</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Ubah nama</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Pulihkan</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>Pindahkan ke Tempat Sampah</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Tidak diproteksi</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Dihapus</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Diklon</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Disalin</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Ya</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>Tidak</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Kualitas Layanan atau QoS</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>Limit BPS</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Limit IO bytes per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>Limit IOPS</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Limit operasi IO per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>Limit Baca BPS </target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Limit byte baca per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>Limit IOPS Baca</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Limit operasi baca per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Limit Tulis BPS</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Limit tulis byte per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Limit IOPS Tulis</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Limit operasi tulis per detik yang diinginkan.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>Letupan BPS</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>Limit yang diinginkan untuk letupan atau burst dari IO byte.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>Letupan IOPS</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>Limit yang diinginkan untuk letupan atau burst operasi IO.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Letupan Baca BPS</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>Limit yang diinginkan untuk letupan atau burst dari baca byte.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Letupan IOPS Baca</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>Limit yang diinginkan untuk letupan atau burst operasi baca.</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Letupan BPS Tulis</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>Limit yang diinginkan untuk letupan atau burst dari tulis byte.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Letupan IOPS Tulis</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>Limit yang diinginkan untuk letupan atau burst dari operasi baca.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Gagal untuk \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>Mengeksekusi</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>eksekusi</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Dieksekusi</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>tugas tak diketahui</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>Membuat</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>buat</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>Memperbarui</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>perbarui</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>Menghapus</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>hapus</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Snapshot RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>mode pencerminan untuk pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>mitra pencerminan untuk pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Nama telah digunakan oleh \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Nama telah digunakan oleh \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Nama telah digunakan oleh \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> berisi snapshot.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Pengklonan</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>klon</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>Snapshot \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> harus diproteksi.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>Menyalin</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>salin</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Meratakan</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>ratakan</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Diratakan</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Nama telah digunakan oleh \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Tidak dapat menghapus proteksi \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> karena mengandung child image.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Tidak dapat menghapus \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> karena diproteksi.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Mengembalikan</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>kembalikan</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>Dikembalikan</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>Memindahkan</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>pindah</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>dipindahkan</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' ke tempat sampah\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Tidak dapat menemukan image.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>Memulihkan</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>pulihkan</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Dipulihkan</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' ke \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Nama image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' sudah digunakan.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>Membuang</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>buang</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Dibuang</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>semua pool</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>image dari \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Gagal menonaktifkan pencerminan karena sedang bermitra.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>profil erasure code \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},nuQ0:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Ip0R"),i=n("ty8c"),s=n("FYBg"),o=n("JZ5S"),u=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"li",[["class","node-menu-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onMenuItemSelected(n,t.context.$implicit)&&a),a},null,null)),(t()(),a["\u0275eld"](1,0,null,null,0,"div",[],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,1,"span",[["class","node-menu-item-value"]],null,null,null,null,null)),(t()(),a["\u0275ted"](3,null,["",""]))],null,function(t,e){t(e,1,0,a["\u0275inlineInterpolate"](1,"node-menu-item-icon ",e.context.$implicit.cssClass,"")),t(e,3,0,e.context.$implicit.name)})}function l(t){return a["\u0275vid"](0,[a["\u0275qud"](402653184,1,{menuContainer:0}),(t()(),a["\u0275eld"](1,0,null,null,3,"div",[["class","node-menu"]],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,[[1,0],["menuContainer",1]],null,2,"ul",[["class","node-menu-content"]],null,null,null,null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,c)),a["\u0275did"](4,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,4,0,e.component.availableMenuItems)},null)}var d=n("HHO+"),f=n("Tff5"),p=n("/TVo"),h=n("urB8"),g=n("VUo1"),b=n("ZYjt"),m=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function y(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"div",[["class","node-checkbox"]],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,[[1,0],["checkbox",1]],null,0,"input",[["checkbox",""],["type","checkbox"]],[[8,"disabled",0],[8,"checked",0]],[[null,"change"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==t.component.switchNodeCheckStatus()&&a),a},null,null))],null,function(t,e){var n=e.component;t(e,1,0,n.isReadOnly,n.tree.checked)})}function v(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"div",[["class","node-template"]],[[8,"innerHTML",1]],null,null,null,null)),a["\u0275ppd"](1,1)],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,0,0,t(e,1,0,a["\u0275nov"](e.parent.parent.parent,0),n.tree.nodeTemplate));t(e,0,0,r)})}function _(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","node-name"]],[[8,"innerHTML",1]],null,null,null,null)),a["\u0275ppd"](1,1)],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,0,0,t(e,1,0,a["\u0275nov"](e.parent.parent.parent,0),n.tree.value));t(e,0,0,r)})}function x(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"span",[["class","loading-children"]],null,null,null,null,null))],null,null)}function T(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](0,null,null,0))],null,null)}function w(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,9,"div",[["class","node-value"]],[[2,"node-selected",null]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onNodeSelected(n)&&a),a},null,null)),(t()(),a["\u0275and"](16777216,null,null,1,null,v)),a["\u0275did"](2,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,_)),a["\u0275did"](4,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,x)),a["\u0275did"](6,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,2,null,T)),a["\u0275did"](8,540672,null,0,r.NgTemplateOutlet,[a.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),a["\u0275pod"](9,{$implicit:0})],function(t,e){var n=e.component;t(e,2,0,n.tree.nodeTemplate),t(e,4,0,!n.template),t(e,6,0,n.tree.childrenAreBeingLoaded());var a=t(e,9,0,n.tree.node);t(e,8,0,a,n.template)},function(t,e){t(e,0,0,e.component.isSelected)})}function S(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"input",[["class","node-value"],["type","text"]],null,[[null,"valueChanged"],[null,"keyup.enter"],[null,"blur"],[null,"keyup.esc"]],function(t,e,n){var r=!0,i=t.component;return"keyup.enter"===e&&(r=!1!==a["\u0275nov"](t,1).applyNewValue(n.target.value)&&r),"blur"===e&&(r=!1!==a["\u0275nov"](t,1).applyNewValueByLoosingFocus(n.target.value)&&r),"keyup.esc"===e&&(r=!1!==a["\u0275nov"](t,1).cancelEditing()&&r),"valueChanged"===e&&(r=!1!==i.applyNewValue(n)&&r),r},null,null)),a["\u0275did"](1,81920,null,0,i.NodeEditableDirective,[a.Renderer2,a.ElementRef],{nodeValue:[0,"nodeValue"]},{valueChanged:"valueChanged"})],function(t,e){t(e,1,0,e.component.tree.value)},null)}function O(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,0,"div",[["class","node-left-menu"]],[[8,"innerHTML",1]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.showLeftMenu(n)&&a),a},null,null))],null,function(t,e){t(e,0,0,e.component.tree.leftMenuTemplate)})}function I(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"node-menu",[],null,[[null,"menuItemSelected"]],function(t,e,n){var a=!0;return"menuItemSelected"===e&&(a=!1!==t.component.onMenuItemSelected(n)&&a),a},l,u)),a["\u0275did"](1,245760,null,0,s.NodeMenuComponent,[a.Renderer2,o.NodeMenuService],null,{menuItemSelected:"menuItemSelected"})],function(t,e){t(e,1,0)},null)}function C(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"node-menu",[],null,[[null,"menuItemSelected"]],function(t,e,n){var a=!0;return"menuItemSelected"===e&&(a=!1!==t.component.onMenuItemSelected(n)&&a),a},l,u)),a["\u0275did"](1,245760,null,0,s.NodeMenuComponent,[a.Renderer2,o.NodeMenuService],null,{menuItemSelected:"menuItemSelected"})],function(t,e){t(e,1,0)},null)}function k(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"node-menu",[],null,[[null,"menuItemSelected"]],function(t,e,n){var a=!0;return"menuItemSelected"===e&&(a=!1!==t.component.onMenuItemSelected(n)&&a),a},l,u)),a["\u0275did"](1,245760,null,0,s.NodeMenuComponent,[a.Renderer2,o.NodeMenuService],{menuItems:[0,"menuItems"]},{menuItemSelected:"menuItemSelected"})],function(t,e){t(e,1,0,e.component.tree.menuItems)},null)}function N(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"tree-internal",[],null,null,null,L,m)),a["\u0275did"](1,4964352,null,0,d.TreeInternalComponent,[o.NodeMenuService,f.TreeService,a.ElementRef],{tree:[0,"tree"],settings:[1,"settings"],template:[2,"template"]},null)],function(t,e){var n=e.component;t(e,1,0,e.context.$implicit,n.settings,n.template)},null)}function R(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,5,"div",[],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,r.NgStyle,[a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngStyle:[0,"ngStyle"]},null),a["\u0275pod"](2,{display:0}),(t()(),a["\u0275and"](16777216,null,null,2,null,N)),a["\u0275did"](4,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,r.AsyncPipe,[a.ChangeDetectorRef])],function(t,e){var n=e.component,r=t(e,2,0,n.tree.isNodeExpanded()?"block":"none");t(e,1,0,r),t(e,4,0,a["\u0275unv"](e,4,0,a["\u0275nov"](e,5).transform(n.tree.childrenAsync)))},null)}function A(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"tree-internal",[],null,null,null,L,m)),a["\u0275did"](1,4964352,null,0,d.TreeInternalComponent,[o.NodeMenuService,f.TreeService,a.ElementRef],{tree:[0,"tree"],settings:[1,"settings"],template:[2,"template"]},null)],function(t,e){var n=e.component;t(e,1,0,e.context.$implicit,n.settings,n.template)},null)}function D(t){return a["\u0275vid"](0,[(t()(),a["\u0275and"](16777216,null,null,2,null,A)),a["\u0275did"](1,278528,null,0,r.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),a["\u0275pid"](131072,r.AsyncPipe,[a.ChangeDetectorRef]),(t()(),a["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,a["\u0275unv"](e,1,0,a["\u0275nov"](e,2).transform(n.tree.childrenAsync)))},null)}function E(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,27,"ul",[["class","tree"]],null,null,null,null,null)),a["\u0275did"](1,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](2,{rootless:0}),(t()(),a["\u0275eld"](3,0,null,null,24,"li",[],null,null,null,null,null)),(t()(),a["\u0275eld"](4,0,null,null,15,"div",[["class","value-container"]],[[2,"selected",null]],[[null,"contextmenu"]],function(t,e,n){var a=!0;return"contextmenu"===e&&(a=!1!==t.component.showRightMenu(n)&&a),a},null,null)),a["\u0275did"](5,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),a["\u0275pod"](6,{rootless:0}),a["\u0275did"](7,212992,null,0,p.NodeDraggableDirective,[a.ElementRef,h.NodeDraggableService,a.Renderer2],{nodeDraggable:[0,"nodeDraggable"],tree:[1,"tree"]},null),(t()(),a["\u0275eld"](8,0,null,null,1,"div",[["class","folding"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.onSwitchFoldingType()&&a),a},null,null)),a["\u0275did"](9,278528,null,0,r.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,y)),a["\u0275did"](11,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,w)),a["\u0275did"](13,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,S)),a["\u0275did"](15,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,O)),a["\u0275did"](17,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,I)),a["\u0275did"](19,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,C)),a["\u0275did"](21,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,k)),a["\u0275did"](23,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,R)),a["\u0275did"](25,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,D)),a["\u0275did"](27,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.isRootHidden());t(e,1,0,"tree",a);var r=t(e,6,0,n.isRootHidden());t(e,5,0,"value-container",r),t(e,7,0,n.nodeElementRef,n.tree),t(e,9,0,"folding",n.tree.foldingCssClass),t(e,11,0,n.settings.showCheckboxes),t(e,13,0,!n.shouldShowInputForTreeValue()),t(e,15,0,n.shouldShowInputForTreeValue()),t(e,17,0,n.tree.hasLeftMenu()),t(e,19,0,n.tree.hasLeftMenu()&&n.isLeftMenuVisible&&!n.hasCustomMenu()),t(e,21,0,n.isRightMenuVisible&&!n.hasCustomMenu()),t(e,23,0,n.hasCustomMenu()&&(n.isRightMenuVisible||n.isLeftMenuVisible)),t(e,25,0,n.tree.keepNodesInDOM()),t(e,27,0,n.tree.isNodeExpanded()&&!n.tree.keepNodesInDOM())},function(t,e){t(e,4,0,e.component.isSelected)})}function L(t){return a["\u0275vid"](0,[a["\u0275pid"](0,g.SafeHtmlPipe,[b.DomSanitizer]),a["\u0275qud"](671088640,1,{checkboxElementRef:0}),(t()(),a["\u0275and"](16777216,null,null,1,null,E)),a["\u0275did"](3,16384,null,0,r.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,3,0,e.component.tree)},null)}n("xtUU"),n.d(e,"a",function(){return P}),n.d(e,"b",function(){return M});var P=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function M(t){return a["\u0275vid"](0,[a["\u0275qud"](402653184,1,{rootComponent:0}),(t()(),a["\u0275eld"](1,0,null,null,1,"tree-internal",[],null,null,null,L,m)),a["\u0275did"](2,4964352,[[1,4],["rootComponent",4]],0,d.TreeInternalComponent,[o.NodeMenuService,f.TreeService,a.ElementRef],{tree:[0,"tree"],settings:[1,"settings"],template:[2,"template"]},null)],function(t,e){var n=e.component;t(e,2,0,n.tree,n.settings,n.template)},null)}},nyYc:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("fr",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd\u2019hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(t,e){switch(e){case"D":return t+(1===t?"er":"");default:case"M":case"Q":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}},week:{dow:1,doy:4}})}()},o1bE:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("ar-dz",{months:"\u062c\u0627\u0646\u0641\u064a_\u0641\u064a\u0641\u0631\u064a_\u0645\u0627\u0631\u0633_\u0623\u0641\u0631\u064a\u0644_\u0645\u0627\u064a_\u062c\u0648\u0627\u0646_\u062c\u0648\u064a\u0644\u064a\u0629_\u0623\u0648\u062a_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),monthsShort:"\u062c\u0627\u0646\u0641\u064a_\u0641\u064a\u0641\u0631\u064a_\u0645\u0627\u0631\u0633_\u0623\u0641\u0631\u064a\u0644_\u0645\u0627\u064a_\u062c\u0648\u0627\u0646_\u062c\u0648\u064a\u0644\u064a\u0629_\u0623\u0648\u062a_\u0633\u0628\u062a\u0645\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0641\u0645\u0628\u0631_\u062f\u064a\u0633\u0645\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u062d\u062f_\u0627\u062b\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u0623\u062d_\u0625\u062b_\u062b\u0644\u0627_\u0623\u0631_\u062e\u0645_\u062c\u0645_\u0633\u0628".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",ss:"%d \u062b\u0627\u0646\u064a\u0629",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:0,doy:4}})}()},"o4+5":function(t,e,n){"use strict";n.d(e,"a",function(){return a}),n("aXbf");var a=function(){function t(t){this.formatter=t}return t.prototype.transform=function(t){return this.formatter.format_number(t,1e3,["","k","M","G","T","P","E","Z","Y"])},t}()},obpP:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="fr-FR">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>Activer/D\xe9sactiver la navigation</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>Tableau de bord</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>Grappe</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>Serveurs</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>Moniteurs</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>Configuration</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>Carte CRUSH</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>Modules Manager</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>Journaux</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>Alertes</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>R\xe9serves</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>Bloc</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>Images</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>Mise en miroir</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>Syst\xe8mes de fichiers</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>Object Gateway</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>Daemons</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>Utilisateurs</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>Compartiments</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>R\xe9cup\xe9ration des donn\xe9es\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pour\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Veuillez patienter...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Affichage des donn\xe9es\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pr\xe9c\xe9demment mises en cache\n pour \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Impossible de charger les donn\xe9es\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pour\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Veuillez v\xe9rifier l\'\xe9tat de sant\xe9 de la grappe.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>Retour</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>S\xe9lectionner une langue</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>Chargement des donn\xe9es du panneau...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>Veuillez consulter la\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> relative \xe0\n la configuration et \xe0 l\'activation de la fonctionnalit\xe9 de surveillance.\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Le tableau de bord Grafana n\'existe pas. Veuillez consulter\n la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> relative \xe0\n l\'ajout de tableaux de bord \xe0 Grafana.\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>S\xe9lecteur d\'heure Grafana</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>R\xe9initialiser les param\xe8tres</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>\xc9chec du chargement des donn\xe9es.</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>s\xe9lectionn\xe9(e)(s)</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>trouv\xe9(e)(s)</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>total</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>Modifier</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>Nom</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>Description</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>Description longue</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>Valeur par d\xe9faut</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>Valeur par d\xe9faut du daemon</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>Services</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>Valeurs</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop \xe9lev\xe9e ! Elle ne peut pas \xeatre sup\xe9rieure \xe0 \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop faible ! Elle ne peut pas \xeatre inf\xe9rieure \xe0 \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>Sauvegarder</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>Visionneuse de carte CRUSH</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>Liste d\'h\xf4tes</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>Performance globale</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>Aucune entr\xe9e trouv\xe9e</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>Journaux de grappes</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>Journaux d\'audit</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>Chargement de la configuration...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>La configuration n\'a pas pu \xeatre charg\xe9e.</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>Modifier le module Manager</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>La valeur entr\xe9e n\'est pas un UUID valide, par exemple : 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>La valeur entr\xe9e doit \xeatre une adresse IP valide.</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>Ce champs est requis.</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop \xe9lev\xe9e ! Elle doit \xeatre inf\xe9rieure ou \xe9gale \xe0 \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop faible ! Elle doit \xeatre sup\xe9rieure ou \xe9gale \xe0 \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>La valeur entr\xe9e doit \xeatre un nombre.</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>La valeur entr\xe9e doit \xeatre un nombre ou une valeur d\xe9cimale.</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>Mise \xe0 jour</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>Statut</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>ID de grappe</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap modifi\xe9</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap epoch</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>quorum con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>quorum mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>required con</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>required mon</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>Dans le quorum</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>Hors quorum</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>Annuler</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>Voulez-vous vraiment \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> l\'\xe9l\xe9ment s\xe9lectionn\xe9 \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> ?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>Oui.</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>Drapeaux OSD \xe0 l\'\xe9chelle de la grappe</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>Soumettre</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>Avanc\xe9...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>Priorit\xe9 de r\xe9cup\xe9ration des OSD</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>Priorit\xe9</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>Personnaliser les valeurs de priorit\xe9</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>Ce champ est obligatoire !</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop \xe9lev\xe9e ! Elle ne peut pas \xeatre sup\xe9rieure \xe0 \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>La valeur entr\xe9e est trop faible ! Elle ne peut pas \xeatre inf\xe9rieure \xe0 \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>R\xe9\xe9valuer l\'OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>La valeur doit \xeatre comprise entre 0 et 1.</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>R\xe9\xe9valuer</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>Nettoyage des \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>OSD\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Profondeur } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>Vous \xeates sur le point d\'appliquer un nettoyage \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\n \xe0 l\'OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {profondeur } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>Liste des OSD</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>L\'\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> sera marqu\xe9\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> si vous continuez.\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>L\'OSD ne peut pas \xeatre d\xe9truit de fa\xe7on s\xe9curis\xe9e !</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L\'OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> sera\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> si vous continuez.\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>D\xe9tails</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>Valeur</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>Fermer</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>Supprimer</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>Sant\xe9</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>Statistiques</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>Veuillez consulter la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n relative \xe0 la configuration et \xe0 l\'activation de la fonctionnalit\xe9 de gestion du NFS Ganesha.\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>Clients</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>Acc\xe8s possible par tous les clients</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>Adresses</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>Champ obligatoire</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>Doit contenir une ou plusieurs valeurs s\xe9par\xe9es par une virgule</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>Par exemple :</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>Type d\'acc\xe8s</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>Squash</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>Ajouter des clients</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>Chargement...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- Aucune grappe disponible --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- S\xe9lectionner la grappe --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>Ajouter un daemon</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>Backend de stockage</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- Aucune r\xe9serve de donn\xe9es disponible --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- S\xe9lectionner le backend de stockage --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>Utilisateur Object Gateway</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- Aucun utilisateur disponible --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- S\xe9lectionner l\'utilisateur Object Gateway --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>ID utilisateur CephFS</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- Aucun client disponible --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- S\xe9lectionner le client cephx --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>Nom CephFS</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>Libell\xe9 de s\xe9curit\xe9</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>Activer le libell\xe9 de s\xe9curit\xe9</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>Chemin CephFS</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>Le chemin doit commencer par \'/\' et peut \xeatre suivi d\'un mot</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>Un nouveau r\xe9pertoire sera cr\xe9\xe9</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>Chemin</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>Le chemin peut \xeatre constitu\xe9 d\'un seul \'/\' ou d\'un seul mot</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>Un compartiment sera cr\xe9\xe9</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>Protocole NFS</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>Balise NFS</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>Autre chemin d\'acc\xe8s aux montages \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (doit commencer par /).\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>Les clients ne peuvent pas monter de sous-r\xe9pertoires (si la balise = foo, le client ne peut pas monter foo/baz).</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>En utilisant diff\xe9rentes options de balise, il est possible d\'exporter plusieurs fois le m\xeame chemin.</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>Pseudo</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>Position occup\xe9e par cet export \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n dans le \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>syst\xe8me de fichiers Pseudo\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (doit \xeatre unique).\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>En utilisant diff\xe9rentes options de pseudo, il est possible d\'exporter exporter plusieurs fois le m\xeame chemin.</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- Aucun type d\'acc\xe8s disponible --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- S\xe9lectionner le type d\'acc\xe8s --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- Aucun squash disponible --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- S\xe9lectionnez le type de squash d\'ID utilisateur qui est effectu\xe9 --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>Protocole de transport</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Bienvenue dans Ceph !</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>Nom d\'utilisateur requis</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>Mot de passe requis</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>Connexion</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>D\xe9sol\xe9, l\'utilisateur n\'existe pas dans Ceph.</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>Retournez \xe0 la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>page de connexion\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Vous serez d\xe9connect\xe9 du fournisseur d\'identit\xe9 lorsque vous tenterez de vous reconnecter.\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>Interdit</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>D\xe9sol\xe9, vous n\'\xeates pas autoris\xe9 \xe0 voir ce que vous cherchez.</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>D\xe9sol\xe9s, nous ne parvenons pas \xe0 trouver ce que vous cherchez.</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>Tout supprimer</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>Notifications r\xe9centes</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>Il n\'y a aucune t\xe2che en arri\xe8re-plan.</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>T\xe2ches en arri\xe8re-plan</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>Aide</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>Documentation</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\xc0 propos de</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>Param\xe8tres du tableau de bord</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>Gestion des utilisateurs</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>Utilisateur connect\xe9</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>Connect\xe9 en tant que\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>Se d\xe9connecter</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>Nom...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>Le nom s\xe9lectionn\xe9 est d\xe9j\xe0 en cours d\'utilisation.</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>Description...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>Autorisations</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>R\xf4les</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>Nom d\'utilisateur</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>Mot de passe</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>Confirmer le mot de passe</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>Le mot de passe de confirmation ne correspond pas au mot de passe.</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>Nom complet</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>Adresse \xe9lectronique</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>L\'adresse \xe9lectronique n\'est pas valide.</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>Vous \xeates sur le point de supprimer les autorisations "lecture/mise \xe0 jour utilisateur" de votre propre utilisateur.</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>Si vous continuez, vous ne serez plus en mesure d\'ajouter ni de supprimer des r\xf4les pour n\'importe quel utilisateur.</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>Voulez-vous vraiment continuer ?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>Compteurs de performance non disponibles</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>Attributs (carte OSD)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>M\xe9tadonn\xe9es non disponibles</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>M\xe9tadonn\xe9es</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>Compteur de performance</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>Histogramme non disponible : \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>\xc9critures</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>Lectures</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>Histogramme</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>D\xe9tails des performances</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>Valeurs actuelles</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>Type</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>Minimum</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>Maximum</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>Drapeaux</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>Source</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>Niveau</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>Mise \xe0 jour possible lors de l\'ex\xe9cution (modifiable)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>Balises</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>Valeurs d\'\xe9num\xe9nation</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>Voir aussi</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>Statut de la grappe</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>Daemons du gestionnaire</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>Passerelles d\'objet</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>Serveurs de m\xe9tadonn\xe9es</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>Passerelles iSCSI</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>IOPS client</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>D\xe9bit client</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>Lectures/\xc9critures client</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>D\xe9bit de r\xe9cup\xe9ration</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>Nettoyer</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>Performance</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>Capacit\xe9 brute</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>Objets</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>Groupes de placements par OSD</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>Statut du groupe de placements</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>Capacit\xe9</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consultez les \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>journaux\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> pour plus d\'informations.\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>Rangs</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>Clients : \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>D\xe9placer une image vers la corbeille.</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>Pour d\xe9placer \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> vers la corbeille,\n cliquez sur \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>D\xe9placer une image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Vous pouvez \xe9galement s\xe9lectionner une date d\'expiration.\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>La protection expire le </target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>NON PROT\xc9G\xc9</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>Format de date incorrect. Veuillez utiliser "AAAA-MM-JJ HH:mm:ss"</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>La protection a d\xe9j\xe0 expir\xe9. Veuillez s\xe9lectionner une date ult\xe9rieure ou laisser le champ vide.</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>D\xe9placer une image</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>Pr\xe9sentation</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>Cibles</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>Authentification de la d\xe9couverte</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>Utilisateur</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Les noms d\'utilisateur doivent comporter entre 8 et 64 caract\xe8res et\n ne peuvent contenir que des lettres et les caract\xe8res \'.\', \'@\', \'-\', \'_\' ou \':\'.</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>Utilisateur commun</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>Mot de passe commun</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>Veuillez consulter la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\nrelative \xe0 la configuration et \xe0 l\'activation de la fonctionnalit\xe9 de gestion des cibles iSCSI.\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>Informations disponibles :</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>Cibles iSCSI non disponibles</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>Disponible uniquement pour les images RBD pour lesquelles \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> est activ\xe9\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>R\xe9serve</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>R\xe9serve de donn\xe9es</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>Cr\xe9\xe9</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>Taille</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>Taille de l\'objet</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>Fonctionnalit\xe9s</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>Provisionn\xe9</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>N/A</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>Provisionnement total</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>Unit\xe9 de segmentation</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>Nombre de segmentations</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>Parent</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>Pr\xe9fixe du nom de bloc</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>Tri</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>Instantan\xe9s</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>Image</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>Ce param\xe8tre remplace la valeur globale</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>Global</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>Il s\'agit de la valeur globale. Aucune valeur de cette option n\'a \xe9t\xe9 d\xe9finie pour cette image.</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>Les caract\xe8res \'/\' et \'@\' ne sont pas autoris\xe9s.</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- Aucune r\xe9serve RBD disponible --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- S\xe9lectionner une r\xe9serve --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>Utiliser une r\xe9serve de donn\xe9es d\xe9di\xe9e</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>R\xe9serve de donn\xe9es</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>R\xe9serve d\xe9di\xe9e qui stocke les donn\xe9es objet du RBD.</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>par exemple, 10 Gio</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>Vous devez augmenter la taille.</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>Avanc\xe9</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>Segmentation</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>Unit\xe9 de segmentation</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- S\xe9lectionner une unit\xe9 de segmentation --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>Ce champ est obligatoire, car le nombre de segments est d\xe9fini.</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>L\'unit\xe9 de segmentation est sup\xe9rieure \xe0 la taille de l\'objet.</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>Nombre de segments</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>Ce champ est obligatoire, car l\'unit\xe9 de segmentation est d\xe9finie.</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>Le nombre de segments doit \xeatre sup\xe9rieur \xe0 0.</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantan\xe9 RDB \n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Renommer} other {Cr\xe9er} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantan\xe9\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>PROT\xc9G\xc9</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>NON PROT\xc9G\xc9</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>Vous \xeates sur le point de revenir \xe0 l\'\xe9tat initial</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>Vider la corbeille</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>Pour purger, s\xe9lectionner une image ou toutes, puis cliquez sur</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>R\xe9serve :</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>Nom de la r\xe9serve...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>Tout</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>Restaurer l\'image</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>Pour restaurer</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>saisissez le nouveau nom de l\'image, puis cliquez sur</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>Nouveau nom</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>Expiration le </target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>Protection jusqu\'au</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>Cette image est prot\xe9g\xe9e jusqu\'au \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>Corbeille</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>Topologie iSCSI</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>Il n\'est g\xe9n\xe9ralement pas n\xe9cessaire de modifier ces param\xe8tres par d\xe9faut.</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>Param\xe8tres</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>Backstore</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>Confirmer</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>Param\xe8tres avanc\xe9s</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>IQN cible</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>Mod\xe8le IQN incorrect.</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>Un IQN est associ\xe9 \xe0 la notation \'iqn.$year-$month.$reversedAddress:$definedName\'</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>Par exemple : iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>Plus d\'informations</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>Des param\xe8tres avanc\xe9s de cette cible ont \xe9t\xe9 modifi\xe9s.</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>Portails</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>Au moins \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> passerelles sont n\xe9cessaires.\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>Ajouter un portail</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>Des param\xe8tres avanc\xe9s de cette image ont \xe9t\xe9 modifi\xe9s.</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>Ajouter une image</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>Authentification ACL</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>Initiateurs</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>Initiateur</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>IQN client</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>L\'IQN de l\'initiateur doit \xeatre unique.</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Les noms d\'utilisateur doivent comporter entre 8 et 64 caract\xe8res et\n ne peuvent contenir que des lettres et les caract\xe8res \'.\', \'@\', \'-\', \'_\' ou \':\'.</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>L\'initiateur appartient \xe0 un groupe dans lequel les images seront configur\xe9es.</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>Aucun \xe9l\xe9ment ajout\xe9.</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>Ajouter un initiateur</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>Groupes</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>Groupe</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>Ajouter un groupe</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>Configuration RBD</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>Supprimez la valeur de configuration locale. La valeur de configuration parent sera h\xe9rit\xe9e et utilis\xe9e \xe0 la place.</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>La valeur minimale est 0.</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>Probl\xe8mes</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>Synchronisation en cours</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>Pr\xeat</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>Modifier le mode de mise en miroir de la r\xe9serve</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>Pour modifier le mode de mise en miroir de la r\xe9serve\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, s\xe9lectionnez un nouveau mode dans la liste, puis cliquez sur \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mettre \xe0 jour\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>Mode</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>Les grappes d\'homologues doivent \xeatre supprim\xe9es avant de d\xe9sactiver la mise en miroir.</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n homologue de mise en miroir de la r\xe9serve\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Modifier} other {Ajouter} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> les attributs\n de mise en miroir de la r\xe9serve \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> et cliquez sur \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Soumettre\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>Nom de grappe</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>Le nom de grappe n\'est pas valide.</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>ID CephX</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>ID CephX</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>L\'ID CephX n\'est pas valide.</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>Adresses du moniteur</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>Adresses s\xe9par\xe9es par une virgule...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>L\'adresse du moniteur n\'est pas valide.</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>Clef CephX</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Clef Base64...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>La clef CephX doit \xeatre cod\xe9e en base64.</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>Liste des r\xe9serves</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>Le nom doit \xeatre exclusivement compos\xe9 de caract\xe8res alphanum\xe9riques, de tirets et de traits de soulignement.</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>Le nom de profil du code d\'effacement s\xe9lectionn\xe9 est d\xe9j\xe0 utilis\xe9.</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>Plug-in</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>Blocs de donn\xe9es (k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>Doit \xeatre \xe9gal ou sup\xe9rieur \xe0 2.</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>Blocs de codage (m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>Doit \xeatre \xe9gal ou sup\xe9rieur \xe0 1.</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>Estimateur de durabilit\xe9 (c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>Localit\xe9 (l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Domaine de d\xe9faillance Crush</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Localit\xe9 Crush</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>Aucun</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>Technique</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>Taille de paquet</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Racine Crush</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Classe de p\xe9riph\xe9rique Crush</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>tout</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>R\xe9pertoire</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>Le nom de r\xe9serve Ceph s\xe9lectionn\xe9 est d\xe9j\xe0 utilis\xe9.</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>Type de r\xe9serve</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- S\xe9lectionner un type de r\xe9serve --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>Groupes de placements</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>Au moins un groupe de placements est n\xe9cessaire.</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>Votre grappe ne peut pas g\xe9rer autant de groupes de placements. Veuillez recalculer le nombre de groupes de placements n\xe9cessaires.</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>Aide au calcul</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>Les param\xe8tres actuels des groupes de placements ont \xe9t\xe9 calcul\xe9s pour vous.\nV\xe9rifiez que les valeurs correspondent \xe0 vos besoins avant de les soumettre.</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Jeu de r\xe8gles Crush</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- S\xe9lectionner une r\xe8gle crush --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>R\xe8gle Crush</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>\xc9tapes Crush</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>La r\xe8gle ne peut pas \xeatre utilis\xe9e dans la grappe active, car celle-ci\n comporte un nombre d\'OSD inf\xe9rieur au nombre d\'OSD minimum requis par cette r\xe8gle.</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>Taille de r\xe9plication</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>Minimum : \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>Maximum : \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>La taille sp\xe9cifi\xe9e est en dehors de la plage. Une valeur comprise entre\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> et \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> est valide.\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>Profil de code d\'effacement</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- Aucun profil de code d\'effacement n\'est disponible --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- S\xe9lectionner un profil de code d\'effacement --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>\xc9crasements EC</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>Applications</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>Compression</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>Algorithme</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- Aucun algorithme de compression d\'effacement n\'est disponible --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>Taille de blob minimale</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>par ex. 128 Kio</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>La valeur doit \xeatre sup\xe9rieure \xe0 0</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>Taille de blob maximale</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>par ex., 512 Kio</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>La valeur doit \xeatre sup\xe9rieure \xe0 la taille de blob minimale.</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>Rapport</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>Rapport de compression</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>La valeur doit se situer entre 0.0 et 1.0</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>Il n\'est pas possible de cr\xe9er une r\xe9serve RBD dont le nom contient \'/\'.</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>Modifiez le nom ou supprimez \'rbd\' de la liste des applications.</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>D\xe9tails des niveaux de mise en cache</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>Veuillez consulter la \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n relative \xe0 la configuration et \xe0 l\'activation de la fonctionnalit\xe9 de gestion Object Gateway.\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>Liste de daemons</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>Compteurs de performance</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>Chargement des donn\xe9es de compartiment...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>Les donn\xe9es du compartiment n\'ont pas pu \xeatre charg\xe9es.</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>La valeur n\'est pas valide.</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>Propri\xe9taire</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- S\xe9lectionner un utilisateur --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>Type d\'index</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>R\xe8gle de placement</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>Marqueur</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>Marqueur maximum</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>Version</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>Version principale</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>Date de modification</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>Groupe de zones</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>Quota de compartiments</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>Activ\xe9</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>Taille maximale</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>Illimit\xe9</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>Nombre maximal d\'objets</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- S\xe9lectionner un nom d\'utilisateur --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>G\xe9n\xe9rer automatiquement la clef</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>Clef d\'acc\xe8s</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>Clef secr\xe8te</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>Adresse \xe9lectronique</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>Suspendu</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>Syst\xe8me</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {Non} 1 {Oui} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>Nombre maximal de compartiments</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>Utilisateurs secondaires</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>Fonctionnalit\xe9s</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>Quota utilisateur</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>Afficher</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>Clefs</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- S\xe9lectionner un type --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>Autorisation</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- S\xe9lectionner une autorisation --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>Utilisateur secondaire</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>L\'ID d\'utilisateur secondaire s\xe9lectionn\xe9 est d\xe9j\xe0 utilis\xe9.</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>lire, \xe9crire</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>complet</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>Cl\xe9 Swift</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>G\xe9n\xe9rer automatiquement le secret</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>Chargement des donn\xe9s utilisateur\u2026</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>Les donn\xe9s utilisateur n\'ont pas pu \xeatre charg\xe9es.</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>L\'ID utilisateur sp\xe9cifi\xe9 est d\xe9j\xe0 utilis\xe9.</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>Ceci n\'est pas une adresse \xe9lectronique valide.</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>L\'adresse \xe9lectronique sp\xe9cifi\xe9e est d\xe9j\xe0 utilis\xe9e.</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>Nombre max. de compartiments</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>La valeur saisie doit \xeatre &gt;= 0.</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>Clef S3</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>Il n\'y a aucun utilisateur secondaire.</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>Il n\'y a pas de clefs.</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>Swift</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>Il n\'y a aucune fonctionnalit\xe9.</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>Taille illimit\xe9e</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>Taille max.</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>Objets illimit\xe9s</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>Nombre max. d\'objets</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>Actuel</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>Authentification de la d\xe9couverte mise \xe0 jour</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>Il n\'y a aucun portail disponible.</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>Il n\'y a aucune image disponible.</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>Il n\'y a aucune image disponible. Veillez \xe0 ajouter une image \xe0 la cible.</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>Il n\'y a aucun initiateur disponible. Veillez \xe0 ajouter un initiateur \xe0 la cible.</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>Cible</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>\xc9tat</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>Octets de lecture</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>Octets d\'\xe9criture</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>Op\xe9rations de lecture</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>Op\xe9rations d\'\xe9criture</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>A/O depuis</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>Instance</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>Nom d\'h\xf4te</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>Probl\xe8me</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>Avancement</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>D\xe9sactiv\xe9</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>Mode d\'\xe9dition</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>Ajouter un homologue</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>Modifier un homologue</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>Supprimer un homologue</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>Leader</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>nb en local</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>nb \xe0 distance</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>mettre en miroir l\'homologue</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>Clef</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>Aplatissement en profondeur</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>Superposition</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>Verrou exclusif</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>Assignation d\'objet (n\xe9cessite exclusive-lock)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>Journalisation (n\xe9cessite exclusive-lock)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>Retour \xe0 l\'\xe9tat initial de l\'instantan\xe9 RBD</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>Revenir \xe0 l\'\xe9tat initial</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>Intantan\xe9 RBD</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>Supprim\xe9 le</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>type</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>\xe9tat</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>version</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>H\xf4te</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>racine</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>Rang</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>Daemon</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>Activit\xe9</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>Dentries</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>Inodes</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>Utilisation</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>Daemons en veille</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>La valeur peut \xeatre mise \xe0 jour au moment de l\'ex\xe9cution.</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>Les daemons/clients ne tirent pas cette valeur de\n\xa0 la base de donn\xe9es de configuration de Monitor. Nous n\'autorisons pas le r\xe9glage de cette option via \'ceph config\n\xa0 set ...\'. Cette option doit \xeatre configur\xe9e via ceph.conf ou via\n\xa0 la ligne de commande.</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>L\'option ne prend effet qu\'au d\xe9marrage du daemon.</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>L\'option n\'affecte que la cr\xe9ation des grappes.</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>L\'option n\'affecte que la cr\xe9ation des daemons.</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>Option de configuration mise \xe0 jour \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>Service</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>Valeur actuelle</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>Modifiable</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>Options mises \xe0 jour pour le module &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>Activer</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>D\xe9sactiver</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>Reconnexion en cours\u2026 Veuillez patienter.</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>Adresse publique</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>Sessions ouvertes</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>Pas rentr\xe9s</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>Les OSD qui ont \xe9t\xe9 marqu\xe9s comme sortis ne seront pas marqu\xe9s comme rentr\xe9s \xe0 leur d\xe9marrage.</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>Pas sortis</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>Les OSD ne seront pas marqu\xe9s automatiquement comme sortis apr\xe8s l\'intervalle configur\xe9.</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>Pas d\xe9marr\xe9s</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>Les OSD ne sont pas autoris\xe9s \xe0 d\xe9marrer.</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>Pas arr\xeat\xe9s</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>Les rapports de d\xe9faillance des OSD sont ignor\xe9s, de sorte que les moniteurs ne marquent pas les OSD comme \xe9tant arr\xeat\xe9s.</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>Pause</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>Met en pause les lectures et \xe9critures</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>Pas de nettoyage</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>Nettoyage d\xe9sactiv\xe9</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>Pas de nettoyage en profondeur</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>Le nettoyage en profondeur est d\xe9sactiv\xe9</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>Pas de renvoi</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>Le renvoi des groupes de placements est suspendu</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>Pas de r\xe9cup\xe9ration</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>La r\xe9cup\xe9ration des groupes de placements est suspendue</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>Tri au niveau du bit</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>Utiliser le tri au niveau du bit</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>Variables snapdir purg\xe9es</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>Les OSD ont converti les variables snapset</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>Suppressions des r\xe9cup\xe9rations</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>Suppressions effectu\xe9es pendant la restauration et non l\'homologation</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>Limite stricte de journalisation des groupes de placements</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>Impose une limite stricte \xe0 la longueur du journal des groupes de placements</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>Drapeaux OSD mis \xe0 jour</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>sorti</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>rentr\xe9</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>arr\xeat\xe9</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>Marquer</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>OSD perdu</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>marqu\xe9 comme perdu</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>Purger</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>purg\xe9</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>d\xe9truire</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>d\xe9truit</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>Groupes de placements</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>Octets de lecture</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>Octets d\'\xe9criture</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>Op\xe9rations de lecture</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>Op\xe9rations d\'\xe9criture</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marquer l\'OSD comme \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>Marquer comme \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>Nbre max. de renvois</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>Nombre maximum de r\xe9cup\xe9rations actives</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>Nombre maximum de d\xe9marrages uniques de r\xe9cup\xe9rations</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>Mise en veille de la r\xe9cup\xe9ration</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>Personnalis\xe9</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>Priorit\xe9 de la vitesse de r\xe9cup\xe9ration des OSD&amp;quot;\n <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot; mise \xe0 jour\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> a \xe9t\xe9 initialis\xe9(e) sur l\'OSD suivant : \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>Travail</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>Gravit\xe9</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>D\xe9marr\xe9</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>Mis \xe0 jour</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>Utilis\xe9</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>Dispo.</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>Nettoy\xe9</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>En cours</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>Avertissement</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>Inconnu</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>op\xe9rationnel</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>aucun syst\xe8me de fichiers</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>actif</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>veille</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>n/a</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>daemon actif</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>quorum</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>Le service NFS Ganesha n\'est pas configur\xe9.</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>Transport</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>Utilisateur CephFS</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>Syst\xe8me de fichiers CephFS</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(h\xe9rit\xe9 de la configuration globale)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>h\xe9rit\xe9 de la configuration globale</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- S\xe9lectionner le type de squashing d\'ID utilisateur effectu\xe9 --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>Aucun daemon n\'est disponible.</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>Mode cache</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>\xc2ge \xe9vict min.</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>\xc2ge vidage min.</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>Nombre max d\'octets cibles</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>Nombre max. d\'objets cibles</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>Aucune application ajout\xe9e</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>Limite d\'applications atteinte</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>Une r\xe9serve peut avoir quatre d\xe9finitions d\'application maximum.</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>Caract\xe8re autoris\xe9s \'_a-zA-Z0-9\'</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>La longueur maximale est de 128 caract\xe8res.</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>Filtrer ou ajouter des applications</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>Ajouter une application</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>profil de code d\'effacement</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>Taille de la r\xe9plique</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>Dernier changement</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>Profil de code d\'effacement</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Jeu de r\xe8gles Crush</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>Octets d\'\xe9criture</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>compartiment</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Compartiment Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; mis \xe0 jour\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>Compartiment Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; cr\xe9\xe9\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>compartiments</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>utilisateur</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Utilisateur Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; mis \xe0 jour\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>Utilisateur Object Gateway &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; cr\xe9\xe9\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>utilisateurs</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>P\xe9rim\xe8tre</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>Lecture</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>Cr\xe9er</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>R\xf4le \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' cr\xe9\xe9\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>R\xf4le \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' mis \xe0 jour\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>R\xf4le syst\xe8me</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>R\xf4le \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\' supprim\xe9\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Utilisateur &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; cr\xe9\xe9\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>Mettre \xe0 jour l\'utilisateur</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>Continuer</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>Vous avez \xe9t\xe9 automatiquement d\xe9connect\xe9, car vos r\xf4les ont chang\xe9.</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Utilisateur &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; mis \xe0 jour\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>Utilisateur &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; supprim\xe9\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\xc9chec de la suppression de l\'utilisateur &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>Vous \xeates connect\xe9 en tant que &amp;quot;\n <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>Chaque objet est divis\xe9 en parties de blocs de donn\xe9es, chacune \xe9tant stock\xe9e sur un OSD diff\xe9rent.</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>Calculez des blocs de codage pour chaque objet et stockez-les sur diff\xe9rents OSD.\n Le nombre de blocs de codage correspond \xe9galement au nombre d\'OSD qui peuvent \xeatre arr\xeat\xe9s sans perdre de donn\xe9es.</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>Le plugin jerasure est le plugin le plus g\xe9n\xe9rique et le plus flexible,\n\xa0 c\'est aussi la valeur par d\xe9faut des r\xe9serves cod\xe9es \xe0 effacement Ceph.</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>La technique la plus flexible est reed_sol_van_van : il suffit de d\xe9finir k\n et m. La technique cauchy_good peut \xeatre plus rapide, mais vous devez choisir la taille du paquet\n avec pr\xe9caution. reed_sol_r6_op, liberation, blaum_roth et liber8tion sont des \xe9quivalents RAID6\n en ce sens qu\'ils ne peuvent \xeatre configur\xe9s qu\'avec m=2.</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>L\'encodage se fera sur des paquets de taille d\'octets.\n\xa0 Choisir la bonne taille de paquet est difficile.\n\xa0 La documentation de jerasure contient de nombreuses informations \xe0 ce sujet.</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>Avec le plugin jerasure, lorsqu\'un objet cod\xe9 \xe0 effacement est stock\xe9 sur\n plusieurs OSD, la r\xe9cup\xe9ration \xe0 la suite de la perte d\'un OSD n\xe9cessite la lecture de tous les autres.\n Par exemple, si jerasure est configur\xe9 avec k=8 et m=4, la perte d\'un OSD n\xe9cessite de lire\n les onze autres pour pouvoir effectuer une r\xe9paration.\n\n Le plugin de code d\'effacement lrc cr\xe9e des blocs de parit\xe9 locale pour permettre la r\xe9cup\xe9ration avec\n moins d\'OSD. Par exemple, si lrc est configur\xe9 avec k=8, m=4 et l=4,\n un bloc de parit\xe9 suppl\xe9mentaire est cr\xe9\xe9 pour chaque groupe de quatre OSD. Lorsqu\'un seul OSD est perdu, il peut \xeatre\n r\xe9cup\xe9r\xe9 avec seulement quatre OSD au lieu de onze.</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>Regroupez les blocs de donn\xe9es et de codage en ensembles de localit\xe9 de taille. Par exemple,\n pour k=4 et m=2, lorsque locality=3, deux groupes de trois sont cr\xe9\xe9s. Chaque ensemble peut\n \xeatre r\xe9cup\xe9r\xe9 sans lire les blocs d\'un autre jeu.</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>Type de compartiment Crush dans lequel chaque ensemble de blocs d\xe9fini\n par I sera stock\xe9. Par exemple, s\'il est r\xe9gl\xe9 sur rack, chaque groupe de blocs I sera\n plac\xe9 dans un rack diff\xe9rent. Il est utilis\xe9 pour cr\xe9er une \xe9tape de la r\xe8gle CRUSH telle que l\'\xe9tape de choix\n d\'un rack. S\'il n\'est pas d\xe9fini, aucun regroupement de ce type n\'est effectu\xe9.</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>Le plug-in isa encapsule la biblioth\xe8que ISA. Il ne fonctionne qu\'avec des processeurs Intel.</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>Le plugin ISA se pr\xe9sente sous deux formes Reed Solomon.\n Si reed_sol_van est d\xe9fini, il \xe9quivaut \xe0 Vandermonde. Si cauchy est configur\xe9, il \xe9quivaut \xe0 Cauchy.</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>Le plug-in shec encapsule la biblioth\xe8que SHEC multiple.\n Il permet \xe0 Ceph de r\xe9cup\xe9rer les donn\xe9es plus efficacement qu\'avec les codes Reed Solomon.</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>Nombre de blocs de parit\xe9, chacun incluant chaque bloc de donn\xe9es dans sa\n plage de calcul. Ce nombre est utilis\xe9 comme estimateur de durabilit\xe9. Par exemple, si c=2,\n 2 OSD peuvent \xeatre arr\xeat\xe9s sans perte de donn\xe9es.</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>Nom du compartiment crush utilis\xe9 pour la premi\xe8re \xe9tape de la r\xe8gle CRUSH.\n Par exemple, l\'\xe9tape de d\xe9finition des valeurs par d\xe9faut.</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>V\xe9rifiez qu\'il n\'existe pas deux blocs dans un compartiment avec le m\xeame domaine de\n d\xe9faillance. Par exemple, si le domaine de d\xe9faillance est un h\xf4te, deux blocs ne seront pas stock\xe9s sur le m\xeame\n h\xf4te. Cette option est utilis\xe9e pour cr\xe9er une \xe9tape de la r\xe8gle CRUSH telle que chooseleaf host.</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>Restreindre le placement aux p\xe9riph\xe9riques d\'une classe sp\xe9cifique\n (par exemple, ssd ou hdd), en utilisant les noms des classes de p\xe9riph\xe9riques crush dans la carte CRUSH.</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>D\xe9finissez le nom du r\xe9pertoire \xe0 partir duquel le plug-in de code d\'effacement est charg\xe9.</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>Autoriser toutes les op\xe9rations</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>Autorise uniquement les op\xe9rations qui ne modifient pas le serveur</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>N\'autorise pas les op\xe9rations de lecture ou d\'\xe9criture, mais toutes les autres.</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>N\'autorise pas la lecture, l\'\xe9criture ni aucune autre op\xe9ration modifiant les attributs d\'un fichier ou le contenu d\'un r\xe9pertoire.</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>N\'autorise aucun acc\xe8s</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- S\xe9lectionner la priorit\xe9 --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>Faible</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>\xc9lev\xe9e</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>Les 5 derni\xe8res minutes</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>Les 15 derni\xe8res minutes</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>Les 30 derni\xe8res minutes</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>La derni\xe8re heure (par d\xe9faut)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>Les 3 derni\xe8res heures</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>Les 6 derni\xe8res heures</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>Les 12 derni\xe8res heures</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>Les 24 derni\xe8res heures</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>Hier</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>Aujourd\'hui</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>Depuis le d\xe9but de la journ\xe9e</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>Avant-hier</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>Les 2 derniers jours</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>Il y a huit jours</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>La semaine derni\xe8re</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>Cette semaine</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>Depuis le d\xe9but de la semaine</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>Les 7 derniers jours</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>Le mois dernier</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>Ce mois</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>Depuis le d\xe9but du mois</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>Les 30 derniers jours</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>Les 90 derniers jours</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>Les 6 derniers mois</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>L\'ann\xe9e \xe9coul\xe9e</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>L\'ann\xe9e derni\xe8re</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>Cette ann\xe9e</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>Depuis le d\xe9but de l\'ann\xe9e</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>Les 2 derni\xe8res ann\xe9es</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>Les 5 derni\xe8res ann\xe9es</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>Informations</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>Aucun \xe9l\xe9ment s\xe9lectionn\xe9.</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>D\xe9s\xe9lectionnez l\'\xe9l\xe9ment pour le s\xe9lectionner \xe0 nouveau.</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>Limite de s\xe9lection atteinte</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>Balises de filtre</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>Ajouter un badge</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>Aucun \xe9l\xe9ment disponible.</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>Ajouter</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>Cloner</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>Copier</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>Nettoyage en profondeur</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>D\xe9truire</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>Aplatir</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>Marquer comme arr\xeat\xe9</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>Marquer comme rentr\xe9</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>Marquer comme perdu</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>Marquer comme sorti</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>Prot\xe9ger</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>Renommer</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>Restaurer</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>D\xe9placer vers la corbeille</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>Annuler la protection</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>Supprim\xe9</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>Clon\xe9</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>Copi\xe9</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>Oui</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>Non</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>Qualit\xe9 de service</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>Limite de bits/s</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>Limite souhait\xe9e d\'octets E/S par seconde.</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>Limite E/S par seconde</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>Limite souhait\xe9e d\'op\xe9rations E/S par seconde.</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>Limite de bits/s en lecture</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>Limite souhait\xe9e de lecture d\'octets par seconde.</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>Limite E/S par seconde en lecture</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>Limite souhait\xe9e d\'op\xe9rations de lecture par seconde.</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>Limite de bits/s en \xe9criture</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>Limite souhait\xe9e d\'\xe9criture d\'octets par seconde.</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>Limite E/S par seconde en \xe9criture</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>Limite souhait\xe9e d\'op\xe9rations d\'\xe9criture par seconde.</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>Rafale de bits/s</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>Limite de rafale d\'octets en E/S souhait\xe9e.</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>Rafale E/S par seconde</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>Limite de rafale d\'op\xe9rations E/S souhait\xe9e.</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>Rafale E/S par seconde en lecture</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>Limite de rafale d\'octets lus par seconde.</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>Rafale E/S par seconde en lecture</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>Limite de rafale d\'op\xe9rations de lecture</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>Rafale E/S par seconde en \xe9criture</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>Limite de rafale de lectures d\'octets souhait\xe9e.</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>Rafale d\'E/S par seconde en \xe9criture</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>Limite de rafale d\'op\xe9rations d\'\xe9criture souhait\xe9e.</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>Impossible de \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>En cours d\'ex\xe9cution</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>ex\xe9cuter</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>Ex\xe9cut\xe9</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>t\xe2che inconnue</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>En cours de cr\xe9ation</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>cr\xe9er</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>En cours de mise \xe0 jour</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>mettre \xe0 jour</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>En cours de suppression</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>supprimer</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>Instantan\xe9 RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>mode miroir pour la r\xe9serve \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>mettre en miroir l\'homologue pour la r\xe9serve \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>Le nom est d\xe9j\xe0 utilis\xe9 par \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>Le nom est d\xe9j\xe0 utilis\xe9 par \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>Le nom est d\xe9j\xe0 utilis\xe9 par \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contient des instantan\xe9s.\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>Clonage en cours</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>cloner</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>L\'instantan\xe9 de \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> doit \xeatre prot\xe9g\xe9.\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>En cours de copie</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>copie</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>Aplatissement</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>aplatir</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>Applati</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>Nom d\xe9j\xe0 utilis\xe9 par \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>Impossible d\'annuler la protection de \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> , car cet \xe9l\xe9ment contient des images enfants.\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>Impossible de supprimer \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, car cet \xe9l\xe9ment est prot\xe9g\xe9.\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>Retour \xe0 l\'\xe9tat initial</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>r\xe9tablir l\'\xe9tat initial</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>R\xe9tabli \xe0 l\'\xe9tat initial</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>En cours de d\xe9placement</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>d\xe9placer</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>D\xe9plac\xe9</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' d\xe9plac\xe9e vers la corbeille\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>Impossible de trouver l\'image.</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>En cours de restauration.</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>restaurer</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>Restaur\xe9</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' vers \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>Le nom d\'image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' est d\xe9j\xe0 utilis\xe9.\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>En cours de purge</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>purger</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>Purg\xe9</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>toutes les r\xe9serves</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>images de \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>Impossible de d\xe9sactiver la mise en miroir, car l\'\xe9l\xe9ment contient un homologue.</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>r\xe9serve \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>profil de code d\'effacement \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>cible \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},ohIB:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("ae7Z");function r(t){for(var e=0,n=0,a=t;n<a.length;n++)e+=a[n].flexGrow||0;return e}function i(t,e){for(var n=0,a=e;n<a.length;n++){var r=t.indexOf(a[n]);t.splice(r,1)}}function s(t,e){void 0===e&&(e=300);for(var n=0,a=0,r=t;a<r.length;a++)n+=r[a].width||e;return n}e.getTotalFlexGrow=r,e.adjustColumnWidths=function(t,e){var n=a.columnsTotalWidth(t),i=r(t),s=a.columnsByPin(t);n!==e&&function(t,e,n){for(var a in t)for(var r=0,i=t[a];r<i.length;r++)(d=i[r]).canAutoResize?d.width=0:(e-=d.width,n-=d.flexGrow?d.flexGrow:0);var s={},o=e;do{var u=o/n;for(var a in o=0,t)for(var c=0,l=t[a];c<l.length;c++){var d;if((d=l[c]).canAutoResize&&!s[d.prop]){var f=d.width+d.flexGrow*u;void 0!==d.minWidth&&f<d.minWidth?(o+=f-d.minWidth,d.width=d.minWidth,s[d.prop]=!0):d.width=f}}}while(0!==o)}(s,e,i)},e.forceFillColumnWidths=function(t,e,n,a,r){void 0===r&&(r=300);for(var o=t.slice(n+1,t.length).filter(function(t){return!1!==t.canAutoResize}),u=0,c=o;u<c.length;u++)(m=c[u]).$$oldWidth||(m.$$oldWidth=m.width);var l=0,d=!1,f=s(t,r),p=e-f,h=[];do{l=p/o.length,d=f>=e;for(var g=0,b=o;g<b.length;g++){var m=b[g];if(d&&a)m.width=m.$$oldWidth||m.width||r;else{var y=(m.width||r)+l;m.minWidth&&y<m.minWidth?(m.width=m.minWidth,h.push(m)):m.maxWidth&&y>m.maxWidth?(m.width=m.maxWidth,h.push(m)):m.width=y}m.width=Math.max(0,m.width)}p=e-(f=s(t)),i(o,h)}while(p>0&&0!==o.length)}},ou9H:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("MGBS"),i=n("zotm");function s(t,e){return function(n){return n.lift(new o(t,e))}}var o=function(){function t(t,e){this.keySelector=t,this.flushes=e}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.keySelector,this.flushes))},t}(),u=function(t){function e(e,n,a){var r=t.call(this,e)||this;return r.keySelector=n,r.values=new Set,a&&r.add(Object(i.a)(r,a)),r}return a.__extends(e,t),e.prototype.notifyNext=function(t,e,n,a,r){this.values.clear()},e.prototype.notifyError=function(t,e){this._error(t)},e.prototype._next=function(t){this.keySelector?this._useKeySelector(t):this._finalizeNext(t,t)},e.prototype._useKeySelector=function(t){var e,n=this.destination;try{e=this.keySelector(t)}catch(a){return void n.error(a)}this._finalizeNext(e,t)},e.prototype._finalizeNext=function(t,e){var n=this.values;n.has(t)||(n.add(t),this.destination.next(e))},e}(r.a)},"p/rL":function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("bm",{months:"Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_M\u025bkalo_Zuw\u025bnkalo_Zuluyekalo_Utikalo_S\u025btanburukalo_\u0254kut\u0254burukalo_Nowanburukalo_Desanburukalo".split("_"),monthsShort:"Zan_Few_Mar_Awi_M\u025b_Zuw_Zul_Uti_S\u025bt_\u0254ku_Now_Des".split("_"),weekdays:"Kari_Nt\u025bn\u025bn_Tarata_Araba_Alamisa_Juma_Sibiri".split("_"),weekdaysShort:"Kar_Nt\u025b_Tar_Ara_Ala_Jum_Sib".split("_"),weekdaysMin:"Ka_Nt_Ta_Ar_Al_Ju_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"MMMM [tile] D [san] YYYY",LLL:"MMMM [tile] D [san] YYYY [l\u025br\u025b] HH:mm",LLLL:"dddd MMMM [tile] D [san] YYYY [l\u025br\u025b] HH:mm"},calendar:{sameDay:"[Bi l\u025br\u025b] LT",nextDay:"[Sini l\u025br\u025b] LT",nextWeek:"dddd [don l\u025br\u025b] LT",lastDay:"[Kunu l\u025br\u025b] LT",lastWeek:"dddd [t\u025bm\u025bnen l\u025br\u025b] LT",sameElse:"L"},relativeTime:{future:"%s k\u0254n\u0254",past:"a b\u025b %s b\u0254",s:"sanga dama dama",ss:"sekondi %d",m:"miniti kelen",mm:"miniti %d",h:"l\u025br\u025b kelen",hh:"l\u025br\u025b %d",d:"tile kelen",dd:"tile %d",M:"kalo kelen",MM:"kalo %d",y:"san kelen",yy:"san %d"},week:{dow:1,doy:4}})}()},p0Sj:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("dEwP"),r=n("nkY7");function i(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=t[t.length-1];return Object(r.a)(n)?(t.pop(),function(e){return Object(a.a)(t,e,n)}):function(e){return Object(a.a)(t,e)}}},p0ib:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("6blF"),r=n("nkY7"),i=n("Zn8D"),s=n("IUTb");function o(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=Number.POSITIVE_INFINITY,o=null,u=t[t.length-1];return Object(r.a)(u)?(o=t.pop(),t.length>1&&"number"==typeof t[t.length-1]&&(n=t.pop())):"number"==typeof u&&(n=t.pop()),null===o&&1===t.length&&t[0]instanceof a.a?t[0]:Object(i.a)(n)(Object(s.a)(t,o))}},p4Cf:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},pKUh:function(t,e,n){"use strict";n.d(e,"a",function(){return s}),n.d(e,"b",function(){return c});var a=n("CcnG"),r=n("YAQW"),i=n("Ip0R"),s=a["\u0275crt"]({encapsulation:0,styles:["[_nghost-%COMP%] .nav-tabs[_ngcontent-%COMP%] .nav-item.disabled[_ngcontent-%COMP%] a.disabled[_ngcontent-%COMP%]{cursor:default}"],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"span",[["class","bs-remove-tab"]],null,[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(n.preventDefault(),a=!1!==r.removeTab(t.parent.context.$implicit)&&a),a},null,null)),(t()(),a["\u0275ted"](-1,null,[" \u274c"]))],null,null)}function u(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,8,"li",[],[[2,"active",null],[2,"disabled",null]],[[null,"keydown"]],function(t,e,n){var a=!0;return"keydown"===e&&(a=!1!==t.component.keyNavActions(n,t.context.index)&&a),a},null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{ngClass:[0,"ngClass"]},null),a["\u0275pad"](2,2),(t()(),a["\u0275eld"](3,0,null,null,5,"a",[["class","nav-link"],["href","javascript:void(0);"]],[[1,"id",0],[2,"active",null],[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=0!=(t.context.$implicit.active=!0)&&a),a},null,null)),(t()(),a["\u0275eld"](4,16777216,null,null,2,"span",[],null,null,null,null,null)),a["\u0275did"](5,16384,null,0,r.a,[a.ViewContainerRef],{ngTransclude:[0,"ngTransclude"]},null),(t()(),a["\u0275ted"](6,null,["",""])),(t()(),a["\u0275and"](16777216,null,null,1,null,o)),a["\u0275did"](8,16384,null,0,i.NgIf,[a.ViewContainerRef,a.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=t(e,2,0,"nav-item",e.context.$implicit.customClass||"");t(e,1,0,n),t(e,5,0,e.context.$implicit.headingRef),t(e,8,0,e.context.$implicit.removable)},function(t,e){t(e,0,0,e.context.$implicit.active,e.context.$implicit.disabled),t(e,3,0,e.context.$implicit.id?e.context.$implicit.id+"-link":"",e.context.$implicit.active,e.context.$implicit.disabled),t(e,6,0,e.context.$implicit.heading)})}function c(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,3,"ul",[["class","nav"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==n.preventDefault()&&a),a},null,null)),a["\u0275did"](1,278528,null,0,i.NgClass,[a.IterableDiffers,a.KeyValueDiffers,a.ElementRef,a.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),a["\u0275and"](16777216,null,null,1,null,u)),a["\u0275did"](3,278528,null,0,i.NgForOf,[a.ViewContainerRef,a.TemplateRef,a.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),a["\u0275eld"](4,0,null,null,1,"div",[["class","tab-content"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],function(t,e){var n=e.component;t(e,1,0,"nav",n.classMap),t(e,3,0,n.tabs)},null)}},pL04:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},pMnS:function(t,e,n){"use strict";n.d(e,"a",function(){return u});var a=n("CcnG"),r=n("ZYCi"),i=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function s(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,16777216,null,null,1,"router-outlet",[],null,null,null,null,null)),a["\u0275did"](1,212992,null,0,r.q,[r.b,a.ViewContainerRef,a.ComponentFactoryResolver,[8,null],a.ChangeDetectorRef],null,null)],function(t,e){t(e,1,0)},null)}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"ng-component",[],null,null,null,s,i)),a["\u0275did"](1,49152,null,0,r.u,[],null,null)],null,null)}var u=a["\u0275ccf"]("ng-component",r.u,o,{},{},[])},paOr:function(t,e,n){"use strict";var a=n("RDha"),r=n("cdu6");t.exports=function(t){var e=a.noop;t.LinearScaleBase=r.extend({getRightValue:function(t){return"string"==typeof t?+t:r.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=a.sign(t.min),r=a.sign(t.max);n<0&&r<0?t.max=0:n>0&&r>0&&(t.min=0)}var i=void 0!==e.min||void 0!==e.suggestedMin,s=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(t.min=null===t.min?e.suggestedMin:Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(t.max=null===t.max?e.suggestedMax:Math.max(t.max,e.suggestedMax)),i!==s&&t.min>=t.max&&(i?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:a.valueOrDefault(e.fixedStepSize,e.stepSize)},i=t.ticks=function(t,e){var n,r,i,s=[];if(t.stepSize&&t.stepSize>0)i=t.stepSize;else{var o=a.niceNum(e.max-e.min,!1);i=a.niceNum(o/(t.maxTicks-1),!0),void 0!==(r=t.precision)&&(n=Math.pow(10,r),i=Math.ceil(i*n)/n)}var u=Math.floor(e.min/i)*i,c=Math.ceil(e.max/i)*i;a.isNullOrUndef(t.min)||a.isNullOrUndef(t.max)||!t.stepSize||a.almostWhole((t.max-t.min)/t.stepSize,i/1e3)&&(u=t.min,c=t.max);var l=(c-u)/i;l=a.almostEquals(l,Math.round(l),i/1e3)?Math.round(l):Math.ceil(l),r=1,i<1&&(r=Math.pow(10,1-Math.floor(a.log10(i))),u=Math.round(u*r)/r,c=Math.round(c*r)/r),s.push(void 0!==t.min?t.min:u);for(var d=1;d<l;++d)s.push(Math.round((u+d*i)*r)/r);return s.push(void 0!==t.max?t.max:c),s}(r,t);t.handleDirectionalChanges(),t.max=a.max(i),t.min=a.min(i),e.reverse?(i.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var t=this;t.ticksAsNumbers=t.ticks.slice(),t.zeroLineIndex=t.ticks.indexOf(0),r.prototype.convertTicksToLabels.call(t)}})}},psW0:function(t,e,n){"use strict";n.d(e,"a",function(){return c});var a=n("mrSG"),r=n("zotm"),i=n("MGBS"),s=n("rPjj"),o=n("67Y/"),u=n("0/uQ");function c(t,e,n){return void 0===n&&(n=Number.POSITIVE_INFINITY),"function"==typeof e?function(a){return a.pipe(c(function(n,a){return Object(u.a)(t(n,a)).pipe(Object(o.a)(function(t,r){return e(n,t,a,r)}))},n))}:("number"==typeof e&&(n=e),function(e){return e.lift(new l(t,n))})}var l=function(){function t(t,e){void 0===e&&(e=Number.POSITIVE_INFINITY),this.project=t,this.concurrent=e}return t.prototype.call=function(t,e){return e.subscribe(new d(t,this.project,this.concurrent))},t}(),d=function(t){function e(e,n,a){void 0===a&&(a=Number.POSITIVE_INFINITY);var r=t.call(this,e)||this;return r.project=n,r.concurrent=a,r.hasCompleted=!1,r.buffer=[],r.active=0,r.index=0,r}return a.__extends(e,t),e.prototype._next=function(t){this.active<this.concurrent?this._tryNext(t):this.buffer.push(t)},e.prototype._tryNext=function(t){var e,n=this.index++;try{e=this.project(t,n)}catch(a){return void this.destination.error(a)}this.active++,this._innerSub(e,t,n)},e.prototype._innerSub=function(t,e,n){var a=new s.a(this,void 0,void 0);this.destination.add(a),Object(r.a)(this,t,e,n,a)},e.prototype._complete=function(){this.hasCompleted=!0,0===this.active&&0===this.buffer.length&&this.destination.complete(),this.unsubscribe()},e.prototype.notifyNext=function(t,e,n,a,r){this.destination.next(e)},e.prototype.notifyComplete=function(t){var e=this.buffer;this.remove(t),this.active--,e.length>0?this._next(e.shift()):0===this.active&&this.hasCompleted&&this.destination.complete()},e}(i.a)},pugT:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("isby"),r=n("McSo"),i=n("2Bdj"),s=n("awvh"),o=function(){function t(t){this.closed=!1,this._parentOrParents=null,this._subscriptions=null,t&&(this._unsubscribe=t)}var e;return t.prototype.unsubscribe=function(){var e;if(!this.closed){var n=this._parentOrParents,o=this._unsubscribe,c=this._subscriptions;if(this.closed=!0,this._parentOrParents=null,this._subscriptions=null,n instanceof t)n.remove(this);else if(null!==n)for(var l=0;l<n.length;++l)n[l].remove(this);if(Object(i.a)(o))try{o.call(this)}catch(p){e=p instanceof s.a?u(p.errors):[p]}if(Object(a.a)(c)){l=-1;for(var d=c.length;++l<d;){var f=c[l];if(Object(r.a)(f))try{f.unsubscribe()}catch(p){e=e||[],p instanceof s.a?e=e.concat(u(p.errors)):e.push(p)}}}if(e)throw new s.a(e)}},t.prototype.add=function(e){var n=e;if(!e)return t.EMPTY;switch(typeof e){case"function":n=new t(e);case"object":if(n===this||n.closed||"function"!=typeof n.unsubscribe)return n;if(this.closed)return n.unsubscribe(),n;if(!(n instanceof t)){var a=n;(n=new t)._subscriptions=[a]}break;default:throw new Error("unrecognized teardown "+e+" added to Subscription.")}var r=n._parentOrParents;if(null===r)n._parentOrParents=this;else if(r instanceof t){if(r===this)return n;n._parentOrParents=[r,this]}else{if(-1!==r.indexOf(this))return n;r.push(this)}var i=this._subscriptions;return null===i?this._subscriptions=[n]:i.push(n),n},t.prototype.remove=function(t){var e=this._subscriptions;if(e){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}},t.EMPTY=((e=new t).closed=!0,e),t}();function u(t){return t.reduce(function(t,e){return t.concat(e instanceof s.a?e.errors:e)},[])}},pxLl:function(t,e,n){"use strict";n.d(e,"a",function(){return l});var a=n("mrSG"),r=n("t/Na"),i=n("F/XL"),s=n("psW0"),o=n("xTzq"),u=n("CcnG"),c=n("pL04"),l=function(){function t(t){this.http=t,this.url="api/perf_counters"}return t.prototype.list=function(){return this.http.get(this.url)},t.prototype.get=function(t,e){return this.http.get(this.url+"/"+t+"/"+e).pipe(Object(s.a)(function(t){return Object(i.a)(t.counters)}))},t.ngInjectableDef=u.defineInjectable({factory:function(){return new t(u.inject(r.c))},token:t,providedIn:c.a}),t=a.__decorate([o.a,a.__metadata("design:paramtypes",[r.c])],t)}()},q8Fl:function(t,e,n){"use strict";var a=n("RDha"),r=["animationstart","webkitAnimationStart"],i={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function s(t,e){var n=a.getStyle(t,e),r=n&&n.match(/^(\d+)(\.\d+)?px$/);return r?Number(r[1]):void 0}var o=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(n){}return t}()&&{passive:!0};function u(t,e,n){t.addEventListener(e,n,o)}function c(t,e,n){t.removeEventListener(e,n,o)}function l(t,e,n,a,r){return{type:t,chart:e,native:r||null,x:void 0!==n?n:null,y:void 0!==a?a:null}}t.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,n="from{opacity:0.99}to{opacity:1}";t="@-webkit-keyframes chartjs-render-animation{"+n+"}@keyframes chartjs-render-animation{"+n+"}.chartjs-render-monitor{-webkit-animation:chartjs-render-animation 0.001s;animation:chartjs-render-animation 0.001s;}",e=this._style||document.createElement("style"),this._style||(this._style=e,t="/* Chart.js */\n"+t,e.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(e)),e.appendChild(document.createTextNode(t))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(function(t,e){var n=t.style,a=t.getAttribute("height"),r=t.getAttribute("width");if(t.$chartjs={initial:{height:a,width:r,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===r||""===r){var i=s(t,"width");void 0!==i&&(t.width=i)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var o=s(t,"height");void 0!==i&&(t.height=o)}}(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e.$chartjs){var n=e.$chartjs.initial;["height","width"].forEach(function(t){var r=n[t];a.isNullOrUndef(r)?e.removeAttribute(t):e.setAttribute(t,r)}),a.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e.$chartjs}},addEventListener:function(t,e,n){var s=t.canvas;if("resize"!==e){var o=n.$chartjs||(n.$chartjs={});u(s,e,(o.proxies||(o.proxies={}))[t.id+"_"+e]=function(e){n(function(t,e){var n=i[t.type]||t.type,r=a.getRelativePosition(t,e);return l(n,e,r.x,r.y,t)}(e,t))})}else!function(t,e,n){var i,s,o,c,d=t.$chartjs||(t.$chartjs={}),f=d.resizer=function(t){var e=document.createElement("div"),n="chartjs-size-monitor",a="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=a,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+a+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+a+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var r=e.childNodes[0],i=e.childNodes[1];e._reset=function(){r.scrollLeft=1e6,r.scrollTop=1e6,i.scrollLeft=1e6,i.scrollTop=1e6};var s=function(){e._reset(),t()};return u(r,"scroll",s.bind(r,"expand")),u(i,"scroll",s.bind(i,"shrink")),e}((i=function(){if(d.resizer)return e(l("resize",n))},o=!1,c=[],function(){c=Array.prototype.slice.call(arguments),s=s||this,o||(o=!0,a.requestAnimFrame.call(window,function(){o=!1,i.apply(s,c)}))}));!function(t,e){var n=t.$chartjs||(t.$chartjs={}),i=n.renderProxy=function(t){"chartjs-render-animation"===t.animationName&&e()};a.each(r,function(e){u(t,e,i)}),n.reflow=!!t.offsetParent,t.classList.add("chartjs-render-monitor")}(t,function(){if(d.resizer){var e=t.parentNode;e&&e!==f.parentNode&&e.insertBefore(f,e.firstChild),f._reset()}})}(s,n,t)},removeEventListener:function(t,e,n){var i,s,o,u=t.canvas;if("resize"!==e){var l=((n.$chartjs||{}).proxies||{})[t.id+"_"+e];l&&c(u,e,l)}else o=(s=(i=u).$chartjs||{}).resizer,delete s.resizer,function(t){var e=t.$chartjs||{},n=e.renderProxy;n&&(a.each(r,function(e){c(t,e,n)}),delete e.renderProxy),t.classList.remove("chartjs-render-monitor")}(i),o&&o.parentNode&&o.parentNode.removeChild(o)}},a.addEvent=u,a.removeEvent=c},qwkt:function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("ejVf")),a(n("aTeT")),a(n("WOoz")),a(n("lmqd")),a(n("ILDN")),a(n("n1nk"))},qzaf:function(t,e,n){"use strict";t.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},rLYq:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata,i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var s=n("CcnG");function o(t){var e=t.filter(function(t){return!!t});return e.length?e.some(function(t){return"number"!=typeof t})?null:e.reduce(function(t,e){return t+e}):null}function u(t){return null}e.DataTableSummaryRowComponent=function(){function t(){this.summaryRow={}}return t.prototype.ngOnChanges=function(){this.columns&&this.rows&&(this.updateInternalColumns(),this.updateValues())},t.prototype.updateInternalColumns=function(){this._internalColumns=this.columns.map(function(t){return i({},t,{cellTemplate:t.summaryTemplate})})},t.prototype.updateValues=function(){var t=this;this.summaryRow={},this.columns.filter(function(t){return!t.summaryTemplate}).forEach(function(e){var n=t.rows.map(function(t){return t[e.prop]}),a=t.getSummaryFunction(e);t.summaryRow[e.prop]=e.pipe?e.pipe.transform(a(n)):a(n)})},t.prototype.getSummaryFunction=function(t){return void 0===t.summaryFunc?o:null===t.summaryFunc?u:t.summaryFunc},a([s.Input(),r("design:type",Array)],t.prototype,"rows",void 0),a([s.Input(),r("design:type",Array)],t.prototype,"columns",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"rowHeight",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"offsetX",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"innerWidth",void 0),a([s.Component({selector:"datatable-summary-row",template:'\n <datatable-body-row\n *ngIf="summaryRow && _internalColumns"\n tabindex="-1"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="_internalColumns"\n [rowHeight]="rowHeight"\n [row]="summaryRow"\n [rowIndex]="-1">\n </datatable-body-row>\n ',host:{class:"datatable-summary-row"}})],t)}()},rPjj:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(e,n,a){var r=t.call(this)||this;return r.parent=e,r.outerValue=n,r.outerIndex=a,r.index=0,r}return a.__extends(e,t),e.prototype._next=function(t){this.parent.notifyNext(this.outerValue,t,this.outerIndex,this.index++,this)},e.prototype._error=function(t){this.parent.notifyError(t,this),this.unsubscribe()},e.prototype._complete=function(){this.parent.notifyComplete(this),this.unsubscribe()},e}(n("FFOo").a)},raLr:function(t,e,n){!function(t){"use strict";function e(t,e,n){var a,r;return"m"===n?e?"\u0445\u0432\u0438\u043b\u0438\u043d\u0430":"\u0445\u0432\u0438\u043b\u0438\u043d\u0443":"h"===n?e?"\u0433\u043e\u0434\u0438\u043d\u0430":"\u0433\u043e\u0434\u0438\u043d\u0443":t+" "+(a=+t,r={ss:e?"\u0441\u0435\u043a\u0443\u043d\u0434\u0430_\u0441\u0435\u043a\u0443\u043d\u0434\u0438_\u0441\u0435\u043a\u0443\u043d\u0434":"\u0441\u0435\u043a\u0443\u043d\u0434\u0443_\u0441\u0435\u043a\u0443\u043d\u0434\u0438_\u0441\u0435\u043a\u0443\u043d\u0434",mm:e?"\u0445\u0432\u0438\u043b\u0438\u043d\u0430_\u0445\u0432\u0438\u043b\u0438\u043d\u0438_\u0445\u0432\u0438\u043b\u0438\u043d":"\u0445\u0432\u0438\u043b\u0438\u043d\u0443_\u0445\u0432\u0438\u043b\u0438\u043d\u0438_\u0445\u0432\u0438\u043b\u0438\u043d",hh:e?"\u0433\u043e\u0434\u0438\u043d\u0430_\u0433\u043e\u0434\u0438\u043d\u0438_\u0433\u043e\u0434\u0438\u043d":"\u0433\u043e\u0434\u0438\u043d\u0443_\u0433\u043e\u0434\u0438\u043d\u0438_\u0433\u043e\u0434\u0438\u043d",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u0456_\u0434\u043d\u0456\u0432",MM:"\u043c\u0456\u0441\u044f\u0446\u044c_\u043c\u0456\u0441\u044f\u0446\u0456_\u043c\u0456\u0441\u044f\u0446\u0456\u0432",yy:"\u0440\u0456\u043a_\u0440\u043e\u043a\u0438_\u0440\u043e\u043a\u0456\u0432"}[n].split("_"),a%10==1&&a%100!=11?r[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?r[1]:r[2])}function a(t){return function(){return t+"\u043e"+(11===this.hours()?"\u0431":"")+"] LT"}}n("wd/R").defineLocale("uk",{months:{format:"\u0441\u0456\u0447\u043d\u044f_\u043b\u044e\u0442\u043e\u0433\u043e_\u0431\u0435\u0440\u0435\u0437\u043d\u044f_\u043a\u0432\u0456\u0442\u043d\u044f_\u0442\u0440\u0430\u0432\u043d\u044f_\u0447\u0435\u0440\u0432\u043d\u044f_\u043b\u0438\u043f\u043d\u044f_\u0441\u0435\u0440\u043f\u043d\u044f_\u0432\u0435\u0440\u0435\u0441\u043d\u044f_\u0436\u043e\u0432\u0442\u043d\u044f_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430_\u0433\u0440\u0443\u0434\u043d\u044f".split("_"),standalone:"\u0441\u0456\u0447\u0435\u043d\u044c_\u043b\u044e\u0442\u0438\u0439_\u0431\u0435\u0440\u0435\u0437\u0435\u043d\u044c_\u043a\u0432\u0456\u0442\u0435\u043d\u044c_\u0442\u0440\u0430\u0432\u0435\u043d\u044c_\u0447\u0435\u0440\u0432\u0435\u043d\u044c_\u043b\u0438\u043f\u0435\u043d\u044c_\u0441\u0435\u0440\u043f\u0435\u043d\u044c_\u0432\u0435\u0440\u0435\u0441\u0435\u043d\u044c_\u0436\u043e\u0432\u0442\u0435\u043d\u044c_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434_\u0433\u0440\u0443\u0434\u0435\u043d\u044c".split("_")},monthsShort:"\u0441\u0456\u0447_\u043b\u044e\u0442_\u0431\u0435\u0440_\u043a\u0432\u0456\u0442_\u0442\u0440\u0430\u0432_\u0447\u0435\u0440\u0432_\u043b\u0438\u043f_\u0441\u0435\u0440\u043f_\u0432\u0435\u0440_\u0436\u043e\u0432\u0442_\u043b\u0438\u0441\u0442_\u0433\u0440\u0443\u0434".split("_"),weekdays:function(t,e){var n={nominative:"\u043d\u0435\u0434\u0456\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044f_\u0441\u0443\u0431\u043e\u0442\u0430".split("_"),accusative:"\u043d\u0435\u0434\u0456\u043b\u044e_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044e_\u0441\u0443\u0431\u043e\u0442\u0443".split("_"),genitive:"\u043d\u0435\u0434\u0456\u043b\u0456_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043a\u0430_\u0432\u0456\u0432\u0442\u043e\u0440\u043a\u0430_\u0441\u0435\u0440\u0435\u0434\u0438_\u0447\u0435\u0442\u0432\u0435\u0440\u0433\u0430_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u0456_\u0441\u0443\u0431\u043e\u0442\u0438".split("_")};return!0===t?n.nominative.slice(1,7).concat(n.nominative.slice(0,1)):t?n[/(\[[\u0412\u0432\u0423\u0443]\]) ?dddd/.test(e)?"accusative":/\[?(?:\u043c\u0438\u043d\u0443\u043b\u043e\u0457|\u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457)? ?\] ?dddd/.test(e)?"genitive":"nominative"][t.day()]:n.nominative},weekdaysShort:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0440.",LLL:"D MMMM YYYY \u0440., HH:mm",LLLL:"dddd, D MMMM YYYY \u0440., HH:mm"},calendar:{sameDay:a("[\u0421\u044c\u043e\u0433\u043e\u0434\u043d\u0456 "),nextDay:a("[\u0417\u0430\u0432\u0442\u0440\u0430 "),lastDay:a("[\u0412\u0447\u043e\u0440\u0430 "),nextWeek:a("[\u0423] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return a("[\u041c\u0438\u043d\u0443\u043b\u043e\u0457] dddd [").call(this);case 1:case 2:case 4:return a("[\u041c\u0438\u043d\u0443\u043b\u043e\u0433\u043e] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"\u0437\u0430 %s",past:"%s \u0442\u043e\u043c\u0443",s:"\u0434\u0435\u043a\u0456\u043b\u044c\u043a\u0430 \u0441\u0435\u043a\u0443\u043d\u0434",ss:e,m:e,mm:e,h:"\u0433\u043e\u0434\u0438\u043d\u0443",hh:e,d:"\u0434\u0435\u043d\u044c",dd:e,M:"\u043c\u0456\u0441\u044f\u0446\u044c",MM:e,y:"\u0440\u0456\u043a",yy:e},meridiemParse:/\u043d\u043e\u0447\u0456|\u0440\u0430\u043d\u043a\u0443|\u0434\u043d\u044f|\u0432\u0435\u0447\u043e\u0440\u0430/,isPM:function(t){return/^(\u0434\u043d\u044f|\u0432\u0435\u0447\u043e\u0440\u0430)$/.test(t)},meridiem:function(t,e,n){return t<4?"\u043d\u043e\u0447\u0456":t<12?"\u0440\u0430\u043d\u043a\u0443":t<17?"\u0434\u043d\u044f":"\u0432\u0435\u0447\u043e\u0440\u0430"},dayOfMonthOrdinalParse:/\d{1,2}-(\u0439|\u0433\u043e)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-\u0439";case"D":return t+"-\u0433\u043e";default:return t}},week:{dow:1,doy:7}})}()},rdkg:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CVuo"),r={},i="undefined"!=typeof document?document.createElement("div").style:void 0,s=function(){var t="undefined"!=typeof window?window.getComputedStyle(document.documentElement,""):void 0,e=void 0!==t?Array.prototype.slice.call(t).join("").match(/-(moz|webkit|ms)-/):null,n=null!==e?e[1]:void 0,a=void 0!==n?"WebKit|Moz|MS|O".match(new RegExp("("+n+")","i"))[1]:void 0;return a?{dom:a,lowercase:n,css:"-"+n+"-",js:n[0].toUpperCase()+n.substr(1)}:void 0};e.\u02750=s;var o=s();e.getVendorPrefixedName=function(t){var e=a.camelCase(t);return r[e]||(void 0!==o&&void 0!==i[o.css+t]?r[e]=o.css+t:void 0!==i[t]&&(r[e]=t)),r[e]}},rpEJ:function(t,e,n){"use strict";n.d(e,"a",function(){return h}),n.d(e,"b",function(){return g}),n.d(e,"c",function(){return f}),n.d(e,"d",function(){return p}),n.d(e,"e",function(){return o}),n.d(e,"f",function(){return s}),n.d(e,"g",function(){return c}),n.d(e,"h",function(){return u}),n.d(e,"i",function(){return y}),n.d(e,"j",function(){return d});var a=n("CcnG"),r=function(){function t(t,e){this.open=t,this.close=e||t}return t.prototype.isManual=function(){return"manual"===this.open||"manual"===this.close},t}(),i={hover:["mouseover","mouseout"],focus:["focusin","focusout"]};function s(t,e){void 0===e&&(e=i);var n=(t||"").trim();if(0===n.length)return[];var a=n.split(/\s+/).map(function(t){return t.split(":")}).map(function(t){var n=e[t[0]]||t;return new r(n[0],n[1])}),s=a.filter(function(t){return t.isManual()});if(s.length>1)throw new Error("Triggers parse error: only one manual trigger is allowed");if(1===s.length&&a.length>1)throw new Error("Triggers parse error: manual trigger can't be mixed with other triggers");return a}function o(t,e){var n=s(e.triggers),a=e.target;if(1===n.length&&n[0].isManual())return Function.prototype;var r=[],i=[],o=function(){i.forEach(function(t){return r.push(t())}),i.length=0};return n.forEach(function(n){var s=n.open===n.close,u=s?e.toggle:e.show;s||i.push(function(){return t.listen(a,n.close,e.hide)}),r.push(t.listen(a,n.open,function(){return u(o)}))}),function(){r.forEach(function(t){return t()})}}function u(t,e){return e.outsideClick?t.listen("document","click",function(t){e.target&&e.target.contains(t.target)||e.targets&&e.targets.some(function(e){return e.contains(t.target)})||e.hide()}):Function.prototype}function c(t,e){return e.outsideEsc?t.listen("document","keyup.esc",function(t){e.target&&e.target.contains(t.target)||e.targets&&e.targets.some(function(e){return e.contains(t.target)})||e.hide()}):Function.prototype}var l,d="undefined"!=typeof window&&window||{},f=d.document;function p(){return void 0===d||(void 0===d.__theme?l?"bs3"===l:"bs3"===(l=function(){if("undefined"==typeof document)return null;var t=document.createElement("span");t.innerText="test bs version",document.body.appendChild(t),t.classList.add("d-none");var e=t.getBoundingClientRect();return document.body.removeChild(t),e&&0===e.top?"bs4":"bs3"}()):"bs4"!==d.__theme)}function h(t){return function(t,e){var n=" __"+e+"Value";Object.defineProperty(t,e,{get:function(){return this[n]},set:function(t){var a=this[n];this[n]=t,a!==t&&this[e+"Change"]&&this[e+"Change"].emit(t)}})}}var g=function(){function t(){}return t.reflow=function(t){},t.getStyles=function(t){var e=t.ownerDocument.defaultView;return e&&e.opener||(e=d),e.getComputedStyle(t)},t}(),b={},m="undefined"==typeof console||!("warn"in console);function y(t){!Object(a.isDevMode)()||m||t in b||(b[t]=!0,console.warn(t))}},"s+uk":function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[n][0]:r[n][1]}n("wd/R").defineLocale("de-at",{months:"J\xe4nner_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"J\xe4n._Feb._M\xe4rz_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},sLuX:function(t,e,n){"use strict";var a=n("CcnG"),r=n("25BL"),i=n("uIqm");n("FSuO"),n("a0VL"),n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o});var s=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function o(t){return a["\u0275vid"](0,[a["\u0275qud"](402653184,1,{table:0}),(t()(),a["\u0275eld"](1,0,null,null,1,"cd-table",[["columnMode","flex"]],null,null,null,r.b,r.a)),a["\u0275did"](2,2867200,[[1,4],["table",4]],0,i.a,[a.NgZone,a.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],toolHeader:[3,"toolHeader"],header:[4,"header"],footer:[5,"footer"],limit:[6,"limit"],autoReload:[7,"autoReload"],autoSave:[8,"autoSave"],customCss:[9,"customCss"]},null)],function(t,e){var n=e.component;t(e,2,0,n.tableData,n.columns,"flex",!1,!1,!1,0,n.autoReload,!1,n.customCss)},null)}},sb0X:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("CcnG"),r=n("gIcY"),i=n("LvDl"),s=function(){function t(t){this.elRef=t,this.type="submit",this.submitAction=new a.EventEmitter,this.disabled=!1,this.loading=!1}return t.prototype.ngOnInit=function(){var t=this;this.form.statusChanges.subscribe(function(){i.has(t.form.errors,"cdSubmitButton")&&(t.loading=!1,i.unset(t.form.errors,"cdSubmitButton"),t.form instanceof r.a&&t.form.updateValueAndValidity())})},t.prototype.submit=function(t){this.focusButton(),this.form instanceof r.l&&this.form.onSubmit(t),this.form.invalid?this.focusInvalid():(this.loading=!0,this.submitAction.emit())},t.prototype.focusButton=function(){this.elRef.nativeElement.offsetParent.querySelector('button[type="'+this.type+'"]').focus()},t.prototype.focusInvalid=function(){var t=this.elRef.nativeElement.offsetParent.querySelector("input.ng-invalid, select.ng-invalid");t&&t.focus()},t}()},siIJ:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(e,n){void 0===n&&(n=t.now),this.SchedulerAction=e,this.now=n}return t.prototype.schedule=function(t,e,n){return void 0===e&&(e=0),new this.SchedulerAction(this,t).schedule(n,e)},t.now=function(){return Date.now()},t}()},sne2:function(t,e,n){"use strict";n.d(e,"c",function(){return o}),n.d(e,"e",function(){return a}),n.d(e,"a",function(){return r}),n.d(e,"b",function(){return u}),n.d(e,"d",function(){return c});var a,r,i=n("CcnG"),s=n("Jm/i"),o=function(){function t(){}return t.organization="ceph",t.projectName="Ceph Manager Dashboard",t.license="Free software (LGPL 2.1).",t}();!function(t){t.CREATE="create",t.EDIT="edit",t.UPDATE="update",t.REMOVE="remove",t.DELETE="delete",t.ADD="add",t.COPY="copy",t.CLONE="clone",t.RECREATE="recreate",t.EXPIRE="expire"}(a||(a={})),function(t){t.CREATE="Create",t.DELETE="Delete",t.ADD="Add",t.REMOVE="Remove",t.EDIT="Edit",t.CANCEL="Cancel",t.COPY="Copy",t.CLONE="Clone",t.SHOW="Show",t.RECREATE="Recreate",t.EXPIRE="Expire"}(r||(r={}));var u=function(){function t(t){this.i18n=t,this.CREATE=this.i18n("Create"),this.DELETE=this.i18n("Delete"),this.ADD=this.i18n("Add"),this.REMOVE=this.i18n("Remove"),this.EDIT=this.i18n("Edit"),this.CANCEL=this.i18n("Cancel"),this.CLONE=this.i18n("Clone"),this.COPY=this.i18n("Copy"),this.DEEP_SCRUB=this.i18n("Deep Scrub"),this.DESTROY=this.i18n("Destroy"),this.FLATTEN=this.i18n("Flatten"),this.MARK_DOWN=this.i18n("Mark Down"),this.MARK_IN=this.i18n("Mark In"),this.MARK_LOST=this.i18n("Mark Lost"),this.MARK_OUT=this.i18n("Mark Out"),this.PROTECT=this.i18n("Protect"),this.PURGE=this.i18n("Purge"),this.RENAME=this.i18n("Rename"),this.RESTORE=this.i18n("Restore"),this.REWEIGHT=this.i18n("Reweight"),this.ROLLBACK=this.i18n("Rollback"),this.SCRUB=this.i18n("Scrub"),this.SHOW=this.i18n("Show"),this.TRASH=this.i18n("Move to Trash"),this.UNPROTECT=this.i18n("Unprotect"),this.RECREATE=this.i18n("Recreate"),this.EXPIRE=this.i18n("Expire")}return t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(s.a))},token:t,providedIn:"root"}),t}(),c=function(){function t(t){this.i18n=t,this.CREATED=this.i18n("Created"),this.DELETED=this.i18n("Deleted"),this.ADDED=this.i18n("Added"),this.REMOVED=this.i18n("Removed"),this.EDITED=this.i18n("Edited"),this.CANCELED=this.i18n("Canceled"),this.CLONED=this.i18n("Cloned"),this.COPIED=this.i18n("Copied"),this.SHOWED=this.i18n("Showed"),this.TRASHED=this.i18n("Moved to Trash"),this.UNPROTECTED=this.i18n("Unprotected"),this.RECREATED=this.i18n("Recreated"),this.EXPIRED=this.i18n("Expired")}return t.ngInjectableDef=i.defineInjectable({factory:function(){return new t(i.inject(s.a))},token:t,providedIn:"root"}),t}()},sp3z:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("lo",{months:"\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99_\u0e81\u0eb8\u0ea1\u0e9e\u0eb2_\u0ea1\u0eb5\u0e99\u0eb2_\u0ec0\u0ea1\u0eaa\u0eb2_\u0e9e\u0eb6\u0e94\u0eaa\u0eb0\u0e9e\u0eb2_\u0ea1\u0eb4\u0e96\u0eb8\u0e99\u0eb2_\u0e81\u0ecd\u0ea5\u0eb0\u0e81\u0ebb\u0e94_\u0eaa\u0eb4\u0e87\u0eab\u0eb2_\u0e81\u0eb1\u0e99\u0e8d\u0eb2_\u0e95\u0eb8\u0ea5\u0eb2_\u0e9e\u0eb0\u0e88\u0eb4\u0e81_\u0e97\u0eb1\u0e99\u0ea7\u0eb2".split("_"),monthsShort:"\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99_\u0e81\u0eb8\u0ea1\u0e9e\u0eb2_\u0ea1\u0eb5\u0e99\u0eb2_\u0ec0\u0ea1\u0eaa\u0eb2_\u0e9e\u0eb6\u0e94\u0eaa\u0eb0\u0e9e\u0eb2_\u0ea1\u0eb4\u0e96\u0eb8\u0e99\u0eb2_\u0e81\u0ecd\u0ea5\u0eb0\u0e81\u0ebb\u0e94_\u0eaa\u0eb4\u0e87\u0eab\u0eb2_\u0e81\u0eb1\u0e99\u0e8d\u0eb2_\u0e95\u0eb8\u0ea5\u0eb2_\u0e9e\u0eb0\u0e88\u0eb4\u0e81_\u0e97\u0eb1\u0e99\u0ea7\u0eb2".split("_"),weekdays:"\u0ead\u0eb2\u0e97\u0eb4\u0e94_\u0e88\u0eb1\u0e99_\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99_\u0e9e\u0eb8\u0e94_\u0e9e\u0eb0\u0eab\u0eb1\u0e94_\u0eaa\u0eb8\u0e81_\u0ec0\u0eaa\u0ebb\u0eb2".split("_"),weekdaysShort:"\u0e97\u0eb4\u0e94_\u0e88\u0eb1\u0e99_\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99_\u0e9e\u0eb8\u0e94_\u0e9e\u0eb0\u0eab\u0eb1\u0e94_\u0eaa\u0eb8\u0e81_\u0ec0\u0eaa\u0ebb\u0eb2".split("_"),weekdaysMin:"\u0e97_\u0e88_\u0ead\u0e84_\u0e9e_\u0e9e\u0eab_\u0eaa\u0e81_\u0eaa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"\u0ea7\u0eb1\u0e99dddd D MMMM YYYY HH:mm"},meridiemParse:/\u0e95\u0ead\u0e99\u0ec0\u0e8a\u0ebb\u0ec9\u0eb2|\u0e95\u0ead\u0e99\u0ec1\u0ea5\u0e87/,isPM:function(t){return"\u0e95\u0ead\u0e99\u0ec1\u0ea5\u0e87"===t},meridiem:function(t,e,n){return t<12?"\u0e95\u0ead\u0e99\u0ec0\u0e8a\u0ebb\u0ec9\u0eb2":"\u0e95\u0ead\u0e99\u0ec1\u0ea5\u0e87"},calendar:{sameDay:"[\u0ea1\u0eb7\u0ec9\u0e99\u0eb5\u0ec9\u0ec0\u0ea7\u0ea5\u0eb2] LT",nextDay:"[\u0ea1\u0eb7\u0ec9\u0ead\u0eb7\u0ec8\u0e99\u0ec0\u0ea7\u0ea5\u0eb2] LT",nextWeek:"[\u0ea7\u0eb1\u0e99]dddd[\u0edc\u0ec9\u0eb2\u0ec0\u0ea7\u0ea5\u0eb2] LT",lastDay:"[\u0ea1\u0eb7\u0ec9\u0ea7\u0eb2\u0e99\u0e99\u0eb5\u0ec9\u0ec0\u0ea7\u0ea5\u0eb2] LT",lastWeek:"[\u0ea7\u0eb1\u0e99]dddd[\u0ec1\u0ea5\u0ec9\u0ea7\u0e99\u0eb5\u0ec9\u0ec0\u0ea7\u0ea5\u0eb2] LT",sameElse:"L"},relativeTime:{future:"\u0ead\u0eb5\u0e81 %s",past:"%s\u0e9c\u0ec8\u0eb2\u0e99\u0ea1\u0eb2",s:"\u0e9a\u0ecd\u0ec8\u0ec0\u0e97\u0ebb\u0ec8\u0eb2\u0ec3\u0e94\u0ea7\u0eb4\u0e99\u0eb2\u0e97\u0eb5",ss:"%d \u0ea7\u0eb4\u0e99\u0eb2\u0e97\u0eb5",m:"1 \u0e99\u0eb2\u0e97\u0eb5",mm:"%d \u0e99\u0eb2\u0e97\u0eb5",h:"1 \u0e8a\u0ebb\u0ec8\u0ea7\u0ec2\u0ea1\u0e87",hh:"%d \u0e8a\u0ebb\u0ec8\u0ea7\u0ec2\u0ea1\u0e87",d:"1 \u0ea1\u0eb7\u0ec9",dd:"%d \u0ea1\u0eb7\u0ec9",M:"1 \u0ec0\u0e94\u0eb7\u0ead\u0e99",MM:"%d \u0ec0\u0e94\u0eb7\u0ead\u0e99",y:"1 \u0e9b\u0eb5",yy:"%d \u0e9b\u0eb5"},dayOfMonthOrdinalParse:/(\u0e97\u0eb5\u0ec8)\d{1,2}/,ordinal:function(t){return"\u0e97\u0eb5\u0ec8"+t}})}()},svcd:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("K9Ia"),i=n("pugT"),s=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.value=null,e.hasNext=!1,e.hasCompleted=!1,e}return a.__extends(e,t),e.prototype._subscribe=function(e){return this.hasError?(e.error(this.thrownError),i.a.EMPTY):this.hasCompleted&&this.hasNext?(e.next(this.value),e.complete(),i.a.EMPTY):t.prototype._subscribe.call(this,e)},e.prototype.next=function(t){this.hasCompleted||(this.value=t,this.hasNext=!0)},e.prototype.error=function(e){this.hasCompleted||t.prototype.error.call(this,e)},e.prototype.complete=function(){this.hasCompleted=!0,this.hasNext&&t.prototype.next.call(this,this.value),t.prototype.complete.call(this)},e}(r.a)},syrc:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("5tze");n("bpWZ"),n("czA5"),e.DataTableBodyRowComponent=function(){function t(t,e,n,a){this.differs=t,this.scrollbarHelper=e,this.cd=n,this.treeStatus="collapsed",this.activate=new i.EventEmitter,this.treeAction=new i.EventEmitter,this._groupStyles={left:{},center:{},right:{}},this._element=a.nativeElement,this._rowDiffer=t.find({}).create()}return Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t,this.recalculateColumns(t),this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"innerWidth",{get:function(){return this._innerWidth},set:function(t){if(this._columns){var e=s.columnsByPin(this._columns);this._columnGroupWidths=s.columnGroupWidths(e,e)}this._innerWidth=t,this.recalculateColumns(),this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offsetX",{get:function(){return this._offsetX},set:function(t){this._offsetX=t,this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"cssClass",{get:function(){var t="datatable-body-row";if(this.isSelected&&(t+=" active"),this.rowIndex%2!=0&&(t+=" datatable-row-odd"),this.rowIndex%2==0&&(t+=" datatable-row-even"),this.rowClass){var e=this.rowClass(this.row);if("string"==typeof e)t+=" "+e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}return t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnsTotalWidths",{get:function(){return this._columnGroupWidths.total},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this._rowDiffer.diff(this.row)&&this.cd.markForCheck()},t.prototype.trackByGroups=function(t,e){return e.type},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.buildStylesByGroup=function(){this._groupStyles.left=this.calcStylesByGroup("left"),this._groupStyles.center=this.calcStylesByGroup("center"),this._groupStyles.right=this.calcStylesByGroup("right"),this.cd.markForCheck()},t.prototype.calcStylesByGroup=function(t){var e=this._columnGroupWidths,n=this.offsetX,a={width:e[t]+"px"};if("left"===t)s.translateXY(a,n,0);else if("right"===t){var r=parseInt(this.innerWidth+"",0);s.translateXY(a,-1*(e.total-r-n+this.scrollbarHelper.width),0)}return a},t.prototype.onActivate=function(t,e){t.cellIndex=e,t.rowElement=this._element,this.activate.emit(t)},t.prototype.onKeyDown=function(t){var e=t.keyCode;(e===s.Keys.return||e===s.Keys.down||e===s.Keys.up||e===s.Keys.left||e===s.Keys.right)&&t.target===this._element&&(t.preventDefault(),t.stopPropagation(),this.activate.emit({type:"keydown",event:t,row:this.row,rowElement:this._element}))},t.prototype.onMouseenter=function(t){this.activate.emit({type:"mouseenter",event:t,row:this.row,rowElement:this._element})},t.prototype.recalculateColumns=function(t){void 0===t&&(t=this.columns),this._columns=t;var e=s.columnsByPin(this._columns);this._columnsByPin=s.columnsByPinArr(this._columns),this._columnGroupWidths=s.columnGroupWidths(e,this._columns)},t.prototype.onTreeAction=function(){this.treeAction.emit()},a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"innerWidth",null),a([i.Input(),r("design:type",Boolean)],t.prototype,"expanded",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowClass",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"row",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"group",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"isSelected",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"rowIndex",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"displayCheck",void 0),a([i.Input(),r("design:type",String)],t.prototype,"treeStatus",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offsetX",null),a([i.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"cssClass",null),a([i.HostBinding("style.height.px"),i.Input(),r("design:type",Number)],t.prototype,"rowHeight",void 0),a([i.HostBinding("style.width.px"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"columnsTotalWidths",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"treeAction",void 0),a([i.HostListener("keydown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onKeyDown",null),a([i.HostListener("mouseenter",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMouseenter",null),a([i.Component({selector:"datatable-body-row",changeDetection:i.ChangeDetectionStrategy.OnPush,template:'\n <div\n *ngFor="let colGroup of _columnsByPin; let i = index; trackBy: trackByGroups"\n class="datatable-row-{{colGroup.type}} datatable-row-group"\n [ngStyle]="_groupStyles[colGroup.type]">\n <datatable-body-cell\n *ngFor="let column of colGroup.columns; let ii = index; trackBy: columnTrackingFn"\n tabindex="-1"\n [row]="row"\n [group]="group"\n [expanded]="expanded"\n [isSelected]="isSelected"\n [rowIndex]="rowIndex"\n [column]="column"\n [rowHeight]="rowHeight"\n [displayCheck]="displayCheck"\n [treeStatus]="treeStatus"\n (activate)="onActivate($event, ii)"\n (treeAction)="onTreeAction()">\n </datatable-body-cell>\n </div>\n '})],t)}()},"t/Na":function(t,e,n){"use strict";n.d(e,"m",function(){return E}),n.d(e,"p",function(){return j}),n.d(e,"q",function(){return F}),n.d(e,"n",function(){return P}),n.d(e,"o",function(){return M}),n.d(e,"b",function(){return f}),n.d(e,"g",function(){return d}),n.d(e,"c",function(){return C}),n.d(e,"a",function(){return N}),n.d(e,"d",function(){return Y}),n.d(e,"e",function(){return G}),n.d(e,"l",function(){return z}),n.d(e,"h",function(){return b}),n.d(e,"f",function(){return O}),n.d(e,"i",function(){return L}),n.d(e,"k",function(){return D}),n.d(e,"j",function(){return q});var a=n("mrSG"),r=n("CcnG"),i=n("F/XL"),s=n("6blF"),o=n("Phjn"),u=n("VnD/"),c=n("67Y/"),l=n("Ip0R"),d=function(){return function(){}}(),f=function(){return function(){}}(),p=function(){function t(t){var e=this;this.normalizedNames=new Map,this.lazyUpdate=null,t?this.lazyInit="string"==typeof t?function(){e.headers=new Map,t.split("\n").forEach(function(t){var n=t.indexOf(":");if(n>0){var a=t.slice(0,n),r=a.toLowerCase(),i=t.slice(n+1).trim();e.maybeSetNormalizedName(a,r),e.headers.has(r)?e.headers.get(r).push(i):e.headers.set(r,[i])}})}:function(){e.headers=new Map,Object.keys(t).forEach(function(n){var a=t[n],r=n.toLowerCase();"string"==typeof a&&(a=[a]),a.length>0&&(e.headers.set(r,a),e.maybeSetNormalizedName(n,r))})}:this.headers=new Map}return t.prototype.has=function(t){return this.init(),this.headers.has(t.toLowerCase())},t.prototype.get=function(t){this.init();var e=this.headers.get(t.toLowerCase());return e&&e.length>0?e[0]:null},t.prototype.keys=function(){return this.init(),Array.from(this.normalizedNames.values())},t.prototype.getAll=function(t){return this.init(),this.headers.get(t.toLowerCase())||null},t.prototype.append=function(t,e){return this.clone({name:t,value:e,op:"a"})},t.prototype.set=function(t,e){return this.clone({name:t,value:e,op:"s"})},t.prototype.delete=function(t,e){return this.clone({name:t,value:e,op:"d"})},t.prototype.maybeSetNormalizedName=function(t,e){this.normalizedNames.has(e)||this.normalizedNames.set(e,t)},t.prototype.init=function(){var e=this;this.lazyInit&&(this.lazyInit instanceof t?this.copyFrom(this.lazyInit):this.lazyInit(),this.lazyInit=null,this.lazyUpdate&&(this.lazyUpdate.forEach(function(t){return e.applyUpdate(t)}),this.lazyUpdate=null))},t.prototype.copyFrom=function(t){var e=this;t.init(),Array.from(t.headers.keys()).forEach(function(n){e.headers.set(n,t.headers.get(n)),e.normalizedNames.set(n,t.normalizedNames.get(n))})},t.prototype.clone=function(e){var n=new t;return n.lazyInit=this.lazyInit&&this.lazyInit instanceof t?this.lazyInit:this,n.lazyUpdate=(this.lazyUpdate||[]).concat([e]),n},t.prototype.applyUpdate=function(t){var e=t.name.toLowerCase();switch(t.op){case"a":case"s":var n=t.value;if("string"==typeof n&&(n=[n]),0===n.length)return;this.maybeSetNormalizedName(t.name,e);var r=("a"===t.op?this.headers.get(e):void 0)||[];r.push.apply(r,Object(a.__spread)(n)),this.headers.set(e,r);break;case"d":var i=t.value;if(i){var s=this.headers.get(e);if(!s)return;0===(s=s.filter(function(t){return-1===i.indexOf(t)})).length?(this.headers.delete(e),this.normalizedNames.delete(e)):this.headers.set(e,s)}else this.headers.delete(e),this.normalizedNames.delete(e)}},t.prototype.forEach=function(t){var e=this;this.init(),Array.from(this.normalizedNames.keys()).forEach(function(n){return t(e.normalizedNames.get(n),e.headers.get(n))})},t}(),h=function(){function t(){}return t.prototype.encodeKey=function(t){return g(t)},t.prototype.encodeValue=function(t){return g(t)},t.prototype.decodeKey=function(t){return decodeURIComponent(t)},t.prototype.decodeValue=function(t){return decodeURIComponent(t)},t}();function g(t){return encodeURIComponent(t).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/gi,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%2B/gi,"+").replace(/%3D/gi,"=").replace(/%3F/gi,"?").replace(/%2F/gi,"/")}var b=function(){function t(t){void 0===t&&(t={});var e,n,r,i=this;if(this.updates=null,this.cloneFrom=null,this.encoder=t.encoder||new h,t.fromString){if(t.fromObject)throw new Error("Cannot specify both fromString and fromObject.");this.map=(e=t.fromString,n=this.encoder,r=new Map,e.length>0&&e.split("&").forEach(function(t){var e=t.indexOf("="),i=Object(a.__read)(-1==e?[n.decodeKey(t),""]:[n.decodeKey(t.slice(0,e)),n.decodeValue(t.slice(e+1))],2),s=i[0],o=i[1],u=r.get(s)||[];u.push(o),r.set(s,u)}),r)}else t.fromObject?(this.map=new Map,Object.keys(t.fromObject).forEach(function(e){var n=t.fromObject[e];i.map.set(e,Array.isArray(n)?n:[n])})):this.map=null}return t.prototype.has=function(t){return this.init(),this.map.has(t)},t.prototype.get=function(t){this.init();var e=this.map.get(t);return e?e[0]:null},t.prototype.getAll=function(t){return this.init(),this.map.get(t)||null},t.prototype.keys=function(){return this.init(),Array.from(this.map.keys())},t.prototype.append=function(t,e){return this.clone({param:t,value:e,op:"a"})},t.prototype.set=function(t,e){return this.clone({param:t,value:e,op:"s"})},t.prototype.delete=function(t,e){return this.clone({param:t,value:e,op:"d"})},t.prototype.toString=function(){var t=this;return this.init(),this.keys().map(function(e){var n=t.encoder.encodeKey(e);return t.map.get(e).map(function(e){return n+"="+t.encoder.encodeValue(e)}).join("&")}).join("&")},t.prototype.clone=function(e){var n=new t({encoder:this.encoder});return n.cloneFrom=this.cloneFrom||this,n.updates=(this.updates||[]).concat([e]),n},t.prototype.init=function(){var t=this;null===this.map&&(this.map=new Map),null!==this.cloneFrom&&(this.cloneFrom.init(),this.cloneFrom.keys().forEach(function(e){return t.map.set(e,t.cloneFrom.map.get(e))}),this.updates.forEach(function(e){switch(e.op){case"a":case"s":var n=("a"===e.op?t.map.get(e.param):void 0)||[];n.push(e.value),t.map.set(e.param,n);break;case"d":if(void 0===e.value){t.map.delete(e.param);break}var a=t.map.get(e.param)||[],r=a.indexOf(e.value);-1!==r&&a.splice(r,1),a.length>0?t.map.set(e.param,a):t.map.delete(e.param)}}),this.cloneFrom=null)},t}();function m(t){return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer}function y(t){return"undefined"!=typeof Blob&&t instanceof Blob}function v(t){return"undefined"!=typeof FormData&&t instanceof FormData}var _=function(){function t(t,e,n,a){var r;if(this.url=e,this.body=null,this.reportProgress=!1,this.withCredentials=!1,this.responseType="json",this.method=t.toUpperCase(),function(t){switch(t){case"DELETE":case"GET":case"HEAD":case"OPTIONS":case"JSONP":return!1;default:return!0}}(this.method)||a?(this.body=void 0!==n?n:null,r=a):r=n,r&&(this.reportProgress=!!r.reportProgress,this.withCredentials=!!r.withCredentials,r.responseType&&(this.responseType=r.responseType),r.headers&&(this.headers=r.headers),r.params&&(this.params=r.params)),this.headers||(this.headers=new p),this.params){var i=this.params.toString();if(0===i.length)this.urlWithParams=e;else{var s=e.indexOf("?");this.urlWithParams=e+(-1===s?"?":s<e.length-1?"&":"")+i}}else this.params=new b,this.urlWithParams=e}return t.prototype.serializeBody=function(){return null===this.body?null:m(this.body)||y(this.body)||v(this.body)||"string"==typeof this.body?this.body:this.body instanceof b?this.body.toString():"object"==typeof this.body||"boolean"==typeof this.body||Array.isArray(this.body)?JSON.stringify(this.body):this.body.toString()},t.prototype.detectContentTypeHeader=function(){return null===this.body?null:v(this.body)?null:y(this.body)?this.body.type||null:m(this.body)?null:"string"==typeof this.body?"text/plain":this.body instanceof b?"application/x-www-form-urlencoded;charset=UTF-8":"object"==typeof this.body||"number"==typeof this.body||Array.isArray(this.body)?"application/json":null},t.prototype.clone=function(e){void 0===e&&(e={});var n=e.method||this.method,a=e.url||this.url,r=e.responseType||this.responseType,i=void 0!==e.body?e.body:this.body,s=void 0!==e.withCredentials?e.withCredentials:this.withCredentials,o=void 0!==e.reportProgress?e.reportProgress:this.reportProgress,u=e.headers||this.headers,c=e.params||this.params;return void 0!==e.setHeaders&&(u=Object.keys(e.setHeaders).reduce(function(t,n){return t.set(n,e.setHeaders[n])},u)),e.setParams&&(c=Object.keys(e.setParams).reduce(function(t,n){return t.set(n,e.setParams[n])},c)),new t(n,a,i,{params:c,headers:u,reportProgress:o,responseType:r,withCredentials:s})},t}(),x=function(t){return t[t.Sent=0]="Sent",t[t.UploadProgress=1]="UploadProgress",t[t.ResponseHeader=2]="ResponseHeader",t[t.DownloadProgress=3]="DownloadProgress",t[t.Response=4]="Response",t[t.User=5]="User",t}({}),T=function(){return function(t,e,n){void 0===e&&(e=200),void 0===n&&(n="OK"),this.headers=t.headers||new p,this.status=void 0!==t.status?t.status:e,this.statusText=t.statusText||n,this.url=t.url||null,this.ok=this.status>=200&&this.status<300}}(),w=function(t){function e(e){void 0===e&&(e={});var n=t.call(this,e)||this;return n.type=x.ResponseHeader,n}return Object(a.__extends)(e,t),e.prototype.clone=function(t){return void 0===t&&(t={}),new e({headers:t.headers||this.headers,status:void 0!==t.status?t.status:this.status,statusText:t.statusText||this.statusText,url:t.url||this.url||void 0})},e}(T),S=function(t){function e(e){void 0===e&&(e={});var n=t.call(this,e)||this;return n.type=x.Response,n.body=void 0!==e.body?e.body:null,n}return Object(a.__extends)(e,t),e.prototype.clone=function(t){return void 0===t&&(t={}),new e({body:void 0!==t.body?t.body:this.body,headers:t.headers||this.headers,status:void 0!==t.status?t.status:this.status,statusText:t.statusText||this.statusText,url:t.url||this.url||void 0})},e}(T),O=function(t){function e(e){var n=t.call(this,e,0,"Unknown Error")||this;return n.name="HttpErrorResponse",n.ok=!1,n.message=n.status>=200&&n.status<300?"Http failure during parsing for "+(e.url||"(unknown url)"):"Http failure response for "+(e.url||"(unknown url)")+": "+e.status+" "+e.statusText,n.error=e.error||null,n}return Object(a.__extends)(e,t),e}(T);function I(t,e){return{body:e,headers:t.headers,observe:t.observe,params:t.params,reportProgress:t.reportProgress,responseType:t.responseType,withCredentials:t.withCredentials}}var C=function(){function t(t){this.handler=t}return t.prototype.request=function(t,e,n){var a,r=this;if(void 0===n&&(n={}),t instanceof _)a=t;else{var s;s=n.headers instanceof p?n.headers:new p(n.headers);var l=void 0;n.params&&(l=n.params instanceof b?n.params:new b({fromObject:n.params})),a=new _(t,e,void 0!==n.body?n.body:null,{headers:s,params:l,reportProgress:n.reportProgress,responseType:n.responseType||"json",withCredentials:n.withCredentials})}var d=Object(i.a)(a).pipe(Object(o.a)(function(t){return r.handler.handle(t)}));if(t instanceof _||"events"===n.observe)return d;var f=d.pipe(Object(u.a)(function(t){return t instanceof S}));switch(n.observe||"body"){case"body":switch(a.responseType){case"arraybuffer":return f.pipe(Object(c.a)(function(t){if(null!==t.body&&!(t.body instanceof ArrayBuffer))throw new Error("Response is not an ArrayBuffer.");return t.body}));case"blob":return f.pipe(Object(c.a)(function(t){if(null!==t.body&&!(t.body instanceof Blob))throw new Error("Response is not a Blob.");return t.body}));case"text":return f.pipe(Object(c.a)(function(t){if(null!==t.body&&"string"!=typeof t.body)throw new Error("Response is not a string.");return t.body}));case"json":default:return f.pipe(Object(c.a)(function(t){return t.body}))}case"response":return f;default:throw new Error("Unreachable: unhandled observe type "+n.observe+"}")}},t.prototype.delete=function(t,e){return void 0===e&&(e={}),this.request("DELETE",t,e)},t.prototype.get=function(t,e){return void 0===e&&(e={}),this.request("GET",t,e)},t.prototype.head=function(t,e){return void 0===e&&(e={}),this.request("HEAD",t,e)},t.prototype.jsonp=function(t,e){return this.request("JSONP",t,{params:(new b).append(e,"JSONP_CALLBACK"),observe:"body",responseType:"json"})},t.prototype.options=function(t,e){return void 0===e&&(e={}),this.request("OPTIONS",t,e)},t.prototype.patch=function(t,e,n){return void 0===n&&(n={}),this.request("PATCH",t,I(n,e))},t.prototype.post=function(t,e,n){return void 0===n&&(n={}),this.request("POST",t,I(n,e))},t.prototype.put=function(t,e,n){return void 0===n&&(n={}),this.request("PUT",t,I(n,e))},t}(),k=function(){function t(t,e){this.next=t,this.interceptor=e}return t.prototype.handle=function(t){return this.interceptor.intercept(t,this.next)},t}(),N=new r.InjectionToken("HTTP_INTERCEPTORS"),R=function(){function t(){}return t.prototype.intercept=function(t,e){return e.handle(t)},t}(),A=/^\)\]\}',?\n/,D=function(){return function(){}}(),E=function(){function t(){}return t.prototype.build=function(){return new XMLHttpRequest},t}(),L=function(){function t(t){this.xhrFactory=t}return t.prototype.handle=function(t){var e=this;if("JSONP"===t.method)throw new Error("Attempted to construct Jsonp request without JsonpClientModule installed.");return new s.a(function(n){var a=e.xhrFactory.build();if(a.open(t.method,t.urlWithParams),t.withCredentials&&(a.withCredentials=!0),t.headers.forEach(function(t,e){return a.setRequestHeader(t,e.join(","))}),t.headers.has("Accept")||a.setRequestHeader("Accept","application/json, text/plain, */*"),!t.headers.has("Content-Type")){var r=t.detectContentTypeHeader();null!==r&&a.setRequestHeader("Content-Type",r)}if(t.responseType){var i=t.responseType.toLowerCase();a.responseType="json"!==i?i:"text"}var s=t.serializeBody(),o=null,u=function(){if(null!==o)return o;var e=1223===a.status?204:a.status,n=a.statusText||"OK",r=new p(a.getAllResponseHeaders()),i=function(t){return"responseURL"in t&&t.responseURL?t.responseURL:/^X-Request-URL:/m.test(t.getAllResponseHeaders())?t.getResponseHeader("X-Request-URL"):null}(a)||t.url;return o=new w({headers:r,status:e,statusText:n,url:i})},c=function(){var e=u(),r=e.headers,i=e.status,s=e.statusText,o=e.url,c=null;204!==i&&(c=void 0===a.response?a.responseText:a.response),0===i&&(i=c?200:0);var l=i>=200&&i<300;if("json"===t.responseType&&"string"==typeof c){var d=c;c=c.replace(A,"");try{c=""!==c?JSON.parse(c):null}catch(f){c=d,l&&(l=!1,c={error:f,text:c})}}l?(n.next(new S({body:c,headers:r,status:i,statusText:s,url:o||void 0})),n.complete()):n.error(new O({error:c,headers:r,status:i,statusText:s,url:o||void 0}))},l=function(t){var e=u().url,r=new O({error:t,status:a.status||0,statusText:a.statusText||"Unknown Error",url:e||void 0});n.error(r)},d=!1,f=function(e){d||(n.next(u()),d=!0);var r={type:x.DownloadProgress,loaded:e.loaded};e.lengthComputable&&(r.total=e.total),"text"===t.responseType&&a.responseText&&(r.partialText=a.responseText),n.next(r)},h=function(t){var e={type:x.UploadProgress,loaded:t.loaded};t.lengthComputable&&(e.total=t.total),n.next(e)};return a.addEventListener("load",c),a.addEventListener("error",l),t.reportProgress&&(a.addEventListener("progress",f),null!==s&&a.upload&&a.upload.addEventListener("progress",h)),a.send(s),n.next({type:x.Sent}),function(){a.removeEventListener("error",l),a.removeEventListener("load",c),t.reportProgress&&(a.removeEventListener("progress",f),null!==s&&a.upload&&a.upload.removeEventListener("progress",h)),a.abort()}})},t}(),P=new r.InjectionToken("XSRF_COOKIE_NAME"),M=new r.InjectionToken("XSRF_HEADER_NAME"),q=function(){return function(){}}(),j=function(){function t(t,e,n){this.doc=t,this.platform=e,this.cookieName=n,this.lastCookieString="",this.lastToken=null,this.parseCount=0}return t.prototype.getToken=function(){if("server"===this.platform)return null;var t=this.doc.cookie||"";return t!==this.lastCookieString&&(this.parseCount++,this.lastToken=Object(l["\u0275parseCookieValue"])(t,this.cookieName),this.lastCookieString=t),this.lastToken},t}(),F=function(){function t(t,e){this.tokenService=t,this.headerName=e}return t.prototype.intercept=function(t,e){var n=t.url.toLowerCase();if("GET"===t.method||"HEAD"===t.method||n.startsWith("http://")||n.startsWith("https://"))return e.handle(t);var a=this.tokenService.getToken();return null===a||t.headers.has(this.headerName)||(t=t.clone({headers:t.headers.set(this.headerName,a)})),e.handle(t)},t}(),z=function(){function t(t,e){this.backend=t,this.injector=e,this.chain=null}return t.prototype.handle=function(t){if(null===this.chain){var e=this.injector.get(N,[]);this.chain=e.reduceRight(function(t,e){return new k(t,e)},this.backend)}return this.chain.handle(t)},t}(),G=function(){function t(){}var e;return e=t,t.disable=function(){return{ngModule:e,providers:[{provide:F,useClass:R}]}},t.withOptions=function(t){return void 0===t&&(t={}),{ngModule:e,providers:[t.cookieName?{provide:P,useValue:t.cookieName}:[],t.headerName?{provide:M,useValue:t.headerName}:[]]}},t}(),Y=function(){return function(){}}()},"t/zF":function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(t,e){this.name=t,this.metadata=e}}()},t1N5:function(t,e){function n(t){var e,n,a=t[0]/255,r=t[1]/255,i=t[2]/255,s=Math.min(a,r,i),o=Math.max(a,r,i),u=o-s;return o==s?e=0:a==o?e=(r-i)/u:r==o?e=2+(i-a)/u:i==o&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),n=(s+o)/2,[e,100*(o==s?0:n<=.5?u/(o+s):u/(2-o-s)),100*n]}function a(t){var e,n,a=t[0],r=t[1],i=t[2],s=Math.min(a,r,i),o=Math.max(a,r,i),u=o-s;return n=0==o?0:u/o*1e3/10,o==s?e=0:a==o?e=(r-i)/u:r==o?e=2+(i-a)/u:i==o&&(e=4+(a-r)/u),(e=Math.min(60*e,360))<0&&(e+=360),[e,n,o/255*1e3/10]}function i(t){var e=t[0],a=t[1],r=t[2];return[n(t)[0],1/255*Math.min(e,Math.min(a,r))*100,100*(r=1-1/255*Math.max(e,Math.max(a,r)))]}function s(t){var e,n=t[0]/255,a=t[1]/255,r=t[2]/255;return[100*((1-n-(e=Math.min(1-n,1-a,1-r)))/(1-e)||0),100*((1-a-e)/(1-e)||0),100*((1-r-e)/(1-e)||0),100*e]}function o(t){return S[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,a=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(a=a>.04045?Math.pow((a+.055)/1.055,2.4):a/12.92)),100*(.2126*e+.7152*n+.0722*a),100*(.0193*e+.1192*n+.9505*a)]}function c(t){var e=u(t),n=e[0],a=e[1],r=e[2];return a/=100,r/=108.883,n=(n/=95.047)>.008856?Math.pow(n,1/3):7.787*n+16/116,[116*(a=a>.008856?Math.pow(a,1/3):7.787*a+16/116)-16,500*(n-a),200*(a-(r=r>.008856?Math.pow(r,1/3):7.787*r+16/116))]}function l(t){var e,n,a,r,i,s=t[0]/360,o=t[1]/100,u=t[2]/100;if(0==o)return[i=255*u,i,i];e=2*u-(n=u<.5?u*(1+o):u+o-u*o),r=[0,0,0];for(var c=0;c<3;c++)(a=s+1/3*-(c-1))<0&&a++,a>1&&a--,r[c]=255*(i=6*a<1?e+6*(n-e)*a:2*a<1?n:3*a<2?e+(n-e)*(2/3-a)*6:e);return r}function d(t){var e=t[0]/60,n=t[1]/100,a=t[2]/100,r=Math.floor(e)%6,i=e-Math.floor(e),s=255*a*(1-n),o=255*a*(1-n*i),u=255*a*(1-n*(1-i));switch(a*=255,r){case 0:return[a,u,s];case 1:return[o,a,s];case 2:return[s,a,u];case 3:return[s,o,a];case 4:return[u,s,a];case 5:return[a,s,o]}}function f(t){var e,n,a,i,s=t[0]/360,o=t[1]/100,u=t[2]/100,c=o+u;switch(c>1&&(o/=c,u/=c),a=6*s-(e=Math.floor(6*s)),0!=(1&e)&&(a=1-a),i=o+a*((n=1-u)-o),e){default:case 6:case 0:r=n,g=i,b=o;break;case 1:r=i,g=n,b=o;break;case 2:r=o,g=n,b=i;break;case 3:r=o,g=i,b=n;break;case 4:r=i,g=o,b=n;break;case 5:r=n,g=o,b=i}return[255*r,255*g,255*b]}function p(t){var e=t[1]/100,n=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,t[0]/100*(1-a)+a)),255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a))]}function h(t){var e,n,a,r=t[0]/100,i=t[1]/100,s=t[2]/100;return n=-.9689*r+1.8758*i+.0415*s,a=.0557*r+-.204*i+1.057*s,e=(e=3.2406*r+-1.5372*i+-.4986*s)>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,a=a>.0031308?1.055*Math.pow(a,1/2.4)-.055:a*=12.92,[255*(e=Math.min(Math.max(0,e),1)),255*(n=Math.min(Math.max(0,n),1)),255*(a=Math.min(Math.max(0,a),1))]}function m(t){var e=t[0],n=t[1],a=t[2];return n/=100,a/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(e-n),200*(n-(a=a>.008856?Math.pow(a,1/3):7.787*a+16/116))]}function y(t){var e,n,a,r,i=t[0],s=t[1],o=t[2];return i<=8?r=(n=100*i/903.3)/100*7.787+16/116:(n=100*Math.pow((i+16)/116,3),r=Math.pow(n/100,1/3)),[e=e/95.047<=.008856?e=95.047*(s/500+r-16/116)/7.787:95.047*Math.pow(s/500+r,3),n,a=a/108.883<=.008859?a=108.883*(r-o/200-16/116)/7.787:108.883*Math.pow(r-o/200,3)]}function v(t){var e,n=t[0],a=t[1],r=t[2];return(e=360*Math.atan2(r,a)/2/Math.PI)<0&&(e+=360),[n,Math.sqrt(a*a+r*r),e]}function _(t){return h(y(t))}function x(t){var e,n=t[1];return e=t[2]/360*2*Math.PI,[t[0],n*Math.cos(e),n*Math.sin(e)]}function T(t){return w[t]}t.exports={rgb2hsl:n,rgb2hsv:a,rgb2hwb:i,rgb2cmyk:s,rgb2keyword:o,rgb2xyz:u,rgb2lab:c,rgb2lch:function(t){return v(c(t))},hsl2rgb:l,hsl2hsv:function(t){var e=t[1]/100,n=t[2]/100;return 0===n?[0,0,0]:[t[0],2*(e*=(n*=2)<=1?n:2-n)/(n+e)*100,(n+e)/2*100]},hsl2hwb:function(t){return i(l(t))},hsl2cmyk:function(t){return s(l(t))},hsl2keyword:function(t){return o(l(t))},hsv2rgb:d,hsv2hsl:function(t){var e,n,a=t[1]/100,r=t[2]/100;return e=a*r,[t[0],100*(e=(e/=(n=(2-a)*r)<=1?n:2-n)||0),100*(n/=2)]},hsv2hwb:function(t){return i(d(t))},hsv2cmyk:function(t){return s(d(t))},hsv2keyword:function(t){return o(d(t))},hwb2rgb:f,hwb2hsl:function(t){return n(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return o(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return n(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return i(p(t))},cmyk2keyword:function(t){return o(p(t))},keyword2rgb:T,keyword2hsl:function(t){return n(T(t))},keyword2hsv:function(t){return a(T(t))},keyword2hwb:function(t){return i(T(t))},keyword2cmyk:function(t){return s(T(t))},keyword2lab:function(t){return c(T(t))},keyword2xyz:function(t){return u(T(t))},xyz2rgb:h,xyz2lab:m,xyz2lch:function(t){return v(m(t))},lab2xyz:y,lab2rgb:_,lab2lch:v,lch2lab:x,lch2xyz:function(t){return y(x(t))},lch2rgb:function(t){return _(x(t))}};var w={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var O in w)S[JSON.stringify(w[O])]=O},t9fZ:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("mrSG"),r=n("FFOo"),i=n("b7mW"),s=n("G5J1");function o(t){return function(e){return 0===t?Object(s.b)():e.lift(new u(t))}}var u=function(){function t(t){if(this.total=t,this.total<0)throw new i.a}return t.prototype.call=function(t,e){return e.subscribe(new c(t,this.total))},t}(),c=function(t){function e(e,n){var a=t.call(this,e)||this;return a.total=n,a.count=0,a}return a.__extends(e,t),e.prototype._next=function(t){var e=this.total,n=++this.count;n<=e&&(this.destination.next(t),n===e&&(this.destination.complete(),this.unsubscribe()))},e}(r.a)},tAZD:function(t,e,n){var a,r,i;!function(s){if("object"==typeof t.exports){var o=s(0,e);void 0!==o&&(t.exports=o)}else r=[n,e],void 0===(i="function"==typeof(a=s)?a.apply(e,r):a)||(t.exports=i)}(function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=void 0;e.default=["en",[["a","p"],["AM","PM"],n],[["AM","PM"],n,n],[["S","M","T","W","T","F","S"],["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],["Su","Mo","Tu","We","Th","Fr","Sa"]],n,[["J","F","M","A","M","J","J","A","S","O","N","D"],["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],["January","February","March","April","May","June","July","August","September","October","November","December"]],n,[["B","A"],["BC","AD"],["Before Christ","Anno Domini"]],0,[6,0],["M/d/yy","MMM d, y","MMMM d, y","EEEE, MMMM d, y"],["h:mm a","h:mm:ss a","h:mm:ss a z","h:mm:ss a zzzz"],["{1}, {0}",n,"{1} 'at' {0}",n],[".",",",";","%","+","-","E","\xd7","\u2030","\u221e","NaN",":"],["#,##0.###","#,##0%","\xa4#,##0.00","#E0"],"$","US Dollar",{},function(t){var e=Math.floor(Math.abs(t)),n=t.toString().replace(/^[^.]*\.?/,"").length;return 1===e&&0===n?1:5}]})},tFKq:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata,i=this&&this.__assign||function(){return(i=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};Object.defineProperty(e,"__esModule",{value:!0});var s=n("CcnG"),o=n("qwkt"),u=n("5tze");e.DataTableHeaderComponent=function(){function t(t){this.cd=t,this.sort=new s.EventEmitter,this.reorder=new s.EventEmitter,this.resize=new s.EventEmitter,this.select=new s.EventEmitter,this.columnContextmenu=new s.EventEmitter(!1),this._styleByGroup={left:{},center:{},right:{}}}return Object.defineProperty(t.prototype,"innerWidth",{get:function(){return this._innerWidth},set:function(t){if(this._innerWidth=t,this._columns){var e=u.columnsByPin(this._columns);this._columnGroupWidths=u.columnGroupWidths(e,this._columns),this.setStylesByGroup()}},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"headerHeight",{get:function(){return this._headerHeight},set:function(t){this._headerHeight="auto"!==t?t+"px":t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t;var e=u.columnsByPin(t);this._columnsByPin=u.columnsByPinArr(t),this._columnGroupWidths=u.columnGroupWidths(e,t),this.setStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offsetX",{get:function(){return this._offsetX},set:function(t){this._offsetX=t,this.setStylesByGroup()},enumerable:!0,configurable:!0}),t.prototype.onLongPressStart=function(t){var e=t.event;t.model.dragging=!0,this.dragEventTarget=e},t.prototype.onLongPressEnd=function(t){var e=this,n=t.model;this.dragEventTarget=t.event,setTimeout(function(){var t=e._columns.find(function(t){return t.$$id===n.$$id});t&&(t.dragging=!1)},5)},Object.defineProperty(t.prototype,"headerWidth",{get:function(){return this.scrollbarH?this.innerWidth+"px":"100%"},enumerable:!0,configurable:!0}),t.prototype.trackByGroups=function(t,e){return e.type},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.onColumnResized=function(t,e){t<=e.minWidth?t=e.minWidth:t>=e.maxWidth&&(t=e.maxWidth),this.resize.emit({column:e,prevValue:e.width,newValue:t})},t.prototype.onColumnReordered=function(t){var e=t.prevIndex,n=t.newIndex,a=t.model,r=this.getColumn(n);r.isTarget=!1,r.targetMarkerContext=void 0,this.reorder.emit({column:a,prevValue:e,newValue:n})},t.prototype.onTargetChanged=function(t){var e=t.prevIndex,n=t.newIndex,a=t.initialIndex;if(e||0===e){var r=this.getColumn(e);r.isTarget=!1,r.targetMarkerContext=void 0}if(n||0===n){var i=this.getColumn(n);i.isTarget=!0,a!==n&&(i.targetMarkerContext={class:"targetMarker ".concat(a>n?"dragFromRight":"dragFromLeft")})}},t.prototype.getColumn=function(t){var e=this._columnsByPin[0].columns.length;if(t<e)return this._columnsByPin[0].columns[t];var n=this._columnsByPin[1].columns.length;return t<e+n?this._columnsByPin[1].columns[t-e]:this._columnsByPin[2].columns[t-e-n]},t.prototype.onSort=function(t){var e=t.column,n=t.prevValue,a=t.newValue;if(!e.dragging){var r=this.calcNewSorts(e,n,a);this.sort.emit({sorts:r,column:e,prevValue:n,newValue:a})}},t.prototype.calcNewSorts=function(t,e,n){var a=0;this.sorts||(this.sorts=[]);var r=this.sorts.map(function(e,n){return(e=i({},e)).prop===t.prop&&(a=n),e});return void 0===n?r.splice(a,1):e?r[a].dir=n:(this.sortType===o.SortType.single&&r.splice(0,this.sorts.length),r.push({dir:n,prop:t.prop})),r},t.prototype.setStylesByGroup=function(){this._styleByGroup.left=this.calcStylesByGroup("left"),this._styleByGroup.center=this.calcStylesByGroup("center"),this._styleByGroup.right=this.calcStylesByGroup("right"),this.cd.detectChanges()},t.prototype.calcStylesByGroup=function(t){var e=this._columnGroupWidths,n={width:e[t]+"px"};return"center"===t?u.translateXY(n,-1*this.offsetX,0):"right"===t&&u.translateXY(n,-1*(e.total-this.innerWidth),0),n},a([s.Input(),r("design:type",Object)],t.prototype,"sortAscendingIcon",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"sortDescendingIcon",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"dealsWithGroup",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"innerWidth",null),a([s.Input(),r("design:type",Array)],t.prototype,"sorts",void 0),a([s.Input(),r("design:type",String)],t.prototype,"sortType",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"allRowsSelected",void 0),a([s.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"reorderable",void 0),a([s.HostBinding("style.height"),s.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"headerHeight",null),a([s.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offsetX",null),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"sort",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"reorder",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"resize",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"select",void 0),a([s.Output(),r("design:type",Object)],t.prototype,"columnContextmenu",void 0),a([s.HostBinding("style.width"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"headerWidth",null),a([s.Component({selector:"datatable-header",template:'\n <div\n orderable\n (reorder)="onColumnReordered($event)"\n (targetChanged)="onTargetChanged($event)"\n [style.width.px]="_columnGroupWidths.total"\n class="datatable-header-inner">\n <div\n *ngFor="let colGroup of _columnsByPin; trackBy: trackByGroups"\n [class]="\'datatable-row-\' + colGroup.type"\n [ngStyle]="_styleByGroup[colGroup.type]">\n <datatable-header-cell\n *ngFor="let column of colGroup.columns; trackBy: columnTrackingFn"\n resizeable\n [resizeEnabled]="column.resizeable"\n (resize)="onColumnResized($event, column)"\n long-press\n [pressModel]="column"\n [pressEnabled]="reorderable && column.draggable"\n (longPressStart)="onLongPressStart($event)"\n (longPressEnd)="onLongPressEnd($event)"\n draggable\n [dragX]="reorderable && column.draggable && column.dragging"\n [dragY]="false"\n [dragModel]="column"\n [dragEventTarget]="dragEventTarget"\n [headerHeight]="headerHeight"\n [isTarget]="column.isTarget"\n [targetMarkerTemplate]="targetMarkerTemplate"\n [targetMarkerContext]="column.targetMarkerContext"\n [column]="column"\n [sortType]="sortType"\n [sorts]="sorts"\n [selectionType]="selectionType"\n [sortAscendingIcon]="sortAscendingIcon"\n [sortDescendingIcon]="sortDescendingIcon"\n [allRowsSelected]="allRowsSelected"\n (sort)="onSort($event)"\n (select)="select.emit($event)"\n (columnContextmenu)="columnContextmenu.emit($event)">\n </datatable-header-cell>\n </div>\n </div>\n ',host:{class:"datatable-header"},changeDetection:s.ChangeDetectionStrategy.OnPush})],t)}()},tGlX:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[n][0]:r[n][1]}n("wd/R").defineLocale("de",{months:"Januar_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._M\xe4rz_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},tHPV:function(t,e,n){"use strict";var a=n("mrSG"),r=function(t){function e(e,n){var a=t.call(this,e,n)||this;return a.scheduler=e,a.work=n,a}return a.__extends(e,t),e.prototype.requestAsyncId=function(e,n,a){return void 0===a&&(a=0),null!==a&&a>0?t.prototype.requestAsyncId.call(this,e,n,a):(e.actions.push(this),e.scheduled||(e.scheduled=requestAnimationFrame(function(){return e.flush(null)})))},e.prototype.recycleAsyncId=function(e,n,a){if(void 0===a&&(a=0),null!==a&&a>0||null===a&&this.delay>0)return t.prototype.recycleAsyncId.call(this,e,n,a);0===e.actions.length&&(cancelAnimationFrame(n),e.scheduled=void 0)},e}(n("h9Dq").a),i=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e.prototype.flush=function(t){this.active=!0,this.scheduled=void 0;var e,n=this.actions,a=-1,r=n.length;t=t||n.shift();do{if(e=t.execute(t.state,t.delay))break}while(++a<r&&(t=n.shift()));if(this.active=!1,e){for(;++a<r&&(t=n.shift());)t.unsubscribe();throw e}},e}(n("CS9Q").a);n.d(e,"a",function(){return s});var s=new i(r)},tKjC:function(t,e,n){"use strict";n.r(e);var a=n("6blF"),r=n("p0ib");a.a.prototype.merge=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return this.lift.call(r.a.apply(void 0,[this].concat(t)))}},tNVB:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("mrSG"),r=n("3fWJ"),i=n("FFOo");function s(t){return void 0===t&&(t=c),function(e){return e.lift(new o(t))}}var o=function(){function t(t){this.errorFactory=t}return t.prototype.call=function(t,e){return e.subscribe(new u(t,this.errorFactory))},t}(),u=function(t){function e(e,n){var a=t.call(this,e)||this;return a.errorFactory=n,a.hasValue=!1,a}return a.__extends(e,t),e.prototype._next=function(t){this.hasValue=!0,this.destination.next(t)},e.prototype._complete=function(){if(this.hasValue)return this.destination.complete();var t=void 0;try{t=this.errorFactory()}catch(e){t=e}this.destination.error(t)},e}(i.a);function c(){return new r.a}},tT3J:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("tzm-latn",{months:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",ss:"%d imik",m:"minu\u1e0d",mm:"%d minu\u1e0d",h:"sa\u025ba",hh:"%d tassa\u025bin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}()},tUCv:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(t,e){return 12===t&&(t=0),"enjing"===e?t:"siyang"===e?t>=11?t:t+12:"sonten"===e||"ndalu"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"enjing":t<15?"siyang":t<19?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",ss:"%d detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,doy:7}})}()},tjFV:function(t,e,n){"use strict";var a=n("CDJp"),r=n("RDha"),i=n("fELs");t.exports={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=r.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?r.merge({},[a.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=r.extend(this.defaults[t],e))},addScalesToLayout:function(t){r.each(t.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,i.addBox(t,e)})}}},ty8c:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=n("1PfE");e.NodeEditableDirective=function(){function t(t,e){this.renderer=t,this.elementRef=e,this.valueChanged=new a.EventEmitter(!1)}return t.prototype.ngOnInit=function(){var t=this.elementRef.nativeElement;t&&t.focus(),this.renderer.setProperty(t,"value",this.nodeValue)},t.prototype.applyNewValue=function(t){this.valueChanged.emit({type:"keyup",value:t})},t.prototype.applyNewValueByLoosingFocus=function(t){this.valueChanged.emit({type:"blur",value:t})},t.prototype.cancelEditing=function(){this.valueChanged.emit({type:"keyup",value:this.nodeValue,action:r.NodeEditableEventAction.Cancel})},t.decorators=[{type:a.Directive,args:[{selector:"[nodeEditable]"}]}],t.propDecorators={nodeValue:[{type:a.Input,args:["nodeEditable"]}],valueChanged:[{type:a.Output}],applyNewValue:[{type:a.HostListener,args:["keyup.enter",["$event.target.value"]]}],applyNewValueByLoosingFocus:[{type:a.HostListener,args:["blur",["$event.target.value"]]}],cancelEditing:[{type:a.HostListener,args:["keyup.esc"]}]},t}()},u0Op:function(t,e,n){"use strict";var a=n("TC34"),r={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,a=1;return 0===t?0:1===t?1:(n||(n=.3),a<1?(a=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/a),-a*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,a=1;return 0===t?0:1===t?1:(n||(n=.3),a<1?(a=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/a),a*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,a=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),a<1?(a=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/a),t<1?a*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:a*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};t.exports={effects:r},a.easingEffects=r},u3GI:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[n][0]:r[n][1]}n("wd/R").defineLocale("de-ch",{months:"Januar_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._M\xe4rz_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},uEye:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_m\xe5ndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_m\xe5n_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_m\xe5_ty_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I g\xe5r klokka] LT",lastWeek:"[F\xf8reg\xe5ande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",M:"ein m\xe5nad",MM:"%d m\xe5nader",y:"eit \xe5r",yy:"%d \xe5r"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},uIqm:function(t,e,n){"use strict";var a=n("CcnG"),r=n("y9jh"),i=n("LvDl"),s=n("gI3B"),o=n("6blF"),u=n("x38r"),c=function(){return function(t){this.errorConfig={resetData:!0,displayError:!0},this.error=t}}(),l=n("vCyI");n.d(e,"a",function(){return d});var d=function(){function t(t,e){this.ngZone=t,this.cdRef=e,this.columnMode="flex",this.toolHeader=!0,this.header=!0,this.footer=!0,this.limit=10,this.autoReload=5e3,this.identifier="id",this.forceIdentifier=!1,this.selectionType=void 0,this.updateSelectionOnRefresh="onChange",this.autoSave=!0,this.searchableObjects=!1,this.fetchData=new a.EventEmitter,this.updateSelection=new a.EventEmitter,this.selection=new l.a,this.cellTemplates={},this.search="",this.rows=[],this.loadingIndicator=!0,this.loadingError=!1,this.paginationClasses={pagerLeftArrow:"i fa fa-angle-double-left",pagerRightArrow:"i fa fa-angle-double-right",pagerPrevious:"i fa fa-angle-left",pagerNext:"i fa fa-angle-right"},this.userConfig={},this.localStorage=window.localStorage,this.updating=!1}return t.prototype.ngOnInit=function(){var t=this;if(window.addEventListener("mouseenter",function(t){t.stopPropagation()},!0),this._addTemplates(),!this.sorts){var e=-1!==i.findIndex(this.columns,["prop",this.identifier]);this.sorts=this.createSortingDefinition(e?this.identifier:this.columns[0].prop+""),e||this.forceIdentifier||(this.identifier=this.columns[0].prop+"")}this.initUserConfig(),this.columns.forEach(function(e){e.cellTransformation&&(e.cellTemplate=t.cellTemplates[e.cellTransformation]),e.flexGrow||(e.flexGrow=e.prop+""===t.identifier?1:2),e.resizeable||(e.resizeable=!1)}),this.filterHiddenColumns(),this.fetchData.observers.length>0&&(this.loadingIndicator=!0),i.isInteger(this.autoReload)&&this.autoReload>0?this.ngZone.runOutsideAngular(function(){t.reloadSubscriber=Object(s.a)(0,t.autoReload).subscribe(function(){t.ngZone.run(function(){return t.reloadData()})})}):this.reloadData()},t.prototype.initUserConfig=function(){var t=this;this.autoSave&&(this.tableName=this._calculateUniqueTableName(this.columns),this._loadUserConfig(),this._initUserConfigAutoSave()),this.userConfig.limit||(this.userConfig.limit=this.limit),this.userConfig.sorts||(this.userConfig.sorts=this.sorts),this.userConfig.columns?this.columns.forEach(function(e,n){e.isHidden=t.userConfig.columns[n].isHidden}):this.updateUserColumns()},t.prototype._calculateUniqueTableName=function(t){var e=function(t){if(!i.isString(t))return 0;for(var e=0,n=0;n<t.length;n++)e+=t.charCodeAt(n)*n;return e};return t.reduce(function(t,n,a){return(e(n.prop)+e(n.name))*(a+1)+t},0).toString()},t.prototype._loadUserConfig=function(){var t=this.localStorage.getItem(this.tableName);t&&(this.userConfig=JSON.parse(t))},t.prototype._initUserConfigAutoSave=function(){var t=o.a.create(this._initUserConfigProxy.bind(this));this.saveSubscriber=t.subscribe(this._saveUserConfig.bind(this))},t.prototype._initUserConfigProxy=function(t){this.userConfig=new Proxy(this.userConfig,{set:function(e,n,a){return e[n]=a,t.next(e),!0}})},t.prototype._saveUserConfig=function(t){this.localStorage.setItem(this.tableName,JSON.stringify(t))},t.prototype.updateUserColumns=function(){this.userConfig.columns=this.columns.map(function(t){return{prop:t.prop,name:t.name,isHidden:!!t.isHidden}})},t.prototype.filterHiddenColumns=function(){this.tableColumns=this.columns.filter(function(t){return!t.isHidden})},t.prototype.ngOnDestroy=function(){this.reloadSubscriber&&this.reloadSubscriber.unsubscribe(),this.saveSubscriber&&this.saveSubscriber.unsubscribe()},t.prototype.ngAfterContentChecked=function(){this.table&&this.table.element.clientWidth!==this.currentWidth&&(this.currentWidth=this.table.element.clientWidth,this.table.recalculate(),i.get(this.table,"cd").markForCheck())},t.prototype._addTemplates=function(){this.cellTemplates.bold=this.tableCellBoldTpl,this.cellTemplates.checkIcon=this.checkIconTpl,this.cellTemplates.sparkline=this.sparklineTpl,this.cellTemplates.routerLink=this.routerLinkTpl,this.cellTemplates.perSecond=this.perSecondTpl,this.cellTemplates.executing=this.executingTpl,this.cellTemplates.classAdding=this.classAddingTpl,this.cellTemplates.map=this.mapTpl},t.prototype.useCustomClass=function(t){if(!this.customCss)throw new Error("Custom classes are not set!");var e=Object.keys(this.customCss),n=Object.values(this.customCss).map(function(n,a){return(i.isFunction(n)&&n(t)||n===t)&&e[a]}).filter(function(t){return t}).join(" ");return i.isEmpty(n)?void 0:n},t.prototype.ngOnChanges=function(){this.useData()},t.prototype.setLimit=function(t){var e=parseInt(t.target.value,10);e>0&&(this.userConfig.limit=e)},t.prototype.reloadData=function(){var t=this;if(!this.updating){this.loadingError=!1;var e=new c(function(){t.loadingError=e.errorConfig.displayError,e.errorConfig.resetData&&(t.data=[]),t.useData()});this.fetchData.emit(e),this.updating=!0}},t.prototype.refreshBtn=function(){this.loadingIndicator=!0,this.reloadData()},t.prototype.rowIdentity=function(){var t=this;return function(e){var n=e[t.identifier];if(i.isUndefined(n))throw new Error('Wrong identifier "'+t.identifier+'" -> "'+n+'"');return n}},t.prototype.useData=function(){this.data&&(this.search.length>0?this.updateFilter():this.rows=this.data.slice(),this.reset(),this.updateSelected())},t.prototype.reset=function(){this.loadingIndicator=!1,this.updating=!1},t.prototype.updateSelected=function(){var t=this;if("never"!==this.updateSelectionOnRefresh){var e=[];this.selection.selected.forEach(function(n){for(var a=0,r=t.data;a<r.length;a++){var i=r[a];n[t.identifier]===i[t.identifier]&&e.push(i)}}),"onChange"===this.updateSelectionOnRefresh&&i.isEqual(this.selection.selected,e)||(this.selection.selected=e,this.onSelect(this.selection))}},t.prototype.onSelect=function(t){i.has(t,"selected")&&(this.selection.selected=t.selected),this.selection.update(),this.updateSelection.emit(i.clone(this.selection))},t.prototype.toggleColumn=function(t){var e=t.target.name,n=!t.target.checked;n&&1===this.tableColumns.length?t.target.checked=!0:(i.find(this.columns,function(t){return t.prop===e}).isHidden=n,this.updateColumns())},t.prototype.updateColumns=function(){this.updateUserColumns(),this.filterHiddenColumns();var t=this.userConfig.sorts[0].prop;i.find(this.tableColumns,function(e){return e.prop===t})||(this.userConfig.sorts=this.createSortingDefinition(this.tableColumns[0].prop),this.table.onColumnSort({sorts:this.userConfig.sorts})),this.table.recalculate(),this.cdRef.detectChanges()},t.prototype.createSortingDefinition=function(t){return[{prop:t,dir:r.SortDirection.asc}]},t.prototype.changeSorting=function(t){this.userConfig.sorts=t.sorts},t.prototype.updateFilter=function(t){void 0===t&&(t=!1),t&&(this.search="");var e=this.search.toLowerCase().replace(/,/g,""),n=this.columns.filter(function(t){return t.cellTransformation!==u.a.sparkline});e.match(/['"][^'"]+['"]/)&&(e=e.replace(/['"][^'"]+['"]/g,function(t){return t.replace(/(['"])([^'"]+)(['"])/g,"$2").replace(/ /g,"+")})),this.rows=this.subSearch(this.data,e.split(" ").filter(function(t){return t.length>0}),n),this.table.offset=0},t.prototype.subSearch=function(t,e,n){if(0===e.length||0===t.length)return t;var a=e.pop().replace("+"," ").split(":"),r=n.slice();return 2===a.length&&(n=r.filter(function(t){return-1!==t.name.toLowerCase().indexOf(a[0])})),t=this.basicDataSearch(i.last(a),t,n),this.subSearch(t,e,r)},t.prototype.basicDataSearch=function(t,e,n){var a=this;return 0===t.length?e:e.filter(function(e){return n.filter(function(n){var r=i.get(e,n.prop);if(i.isUndefined(n.pipe)||(r=n.pipe.transform(r)),i.isUndefined(r)||i.isNull(r))return!1;if(i.isArray(r)?r=r.join(" "):(i.isNumber(r)||i.isBoolean(r))&&(r=r.toString()),i.isObjectLike(r)){if(!a.searchableObjects)return!1;r=JSON.stringify(r)}return-1!==r.toLowerCase().indexOf(t)}).length>0})},t.prototype.getRowClass=function(){var t=this;return function(){return{clickable:!i.isUndefined(t.selectionType)}}},t}()},uKs4:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG");e.VisibilityDirective=function(){function t(t,e){this.element=t,this.zone=e,this.isVisible=!1,this.visible=new i.EventEmitter}return t.prototype.ngOnInit=function(){this.runCheck()},t.prototype.ngOnDestroy=function(){clearTimeout(this.timeout)},t.prototype.onVisibilityChange=function(){var t=this;this.zone.run(function(){t.isVisible=!0,t.visible.emit(!0)})},t.prototype.runCheck=function(){var t=this,e=function(){var n=t.element.nativeElement;n.offsetHeight&&n.offsetWidth?(clearTimeout(t.timeout),t.onVisibilityChange()):(clearTimeout(t.timeout),t.zone.runOutsideAngular(function(){t.timeout=setTimeout(function(){return e()},50)}))};this.timeout=setTimeout(function(){return e()})},a([i.HostBinding("class.visible"),r("design:type",Boolean)],t.prototype,"isVisible",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"visible",void 0),a([i.Directive({selector:"[visibilityObserver]"})],t)}()},uMaO:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("mrSG"),r=function(t){function e(e,n){var a=t.call(this)||this;return a.subject=e,a.subscriber=n,a.closed=!1,a}return a.__extends(e,t),e.prototype.unsubscribe=function(){if(!this.closed){this.closed=!0;var t=this.subject,e=t.observers;if(this.subject=null,e&&0!==e.length&&!t.isStopped&&!t.closed){var n=e.indexOf(this.subscriber);-1!==n&&e.splice(n,1)}}},e}(n("pugT").a)},uXwI:function(t,e,n){!function(t){"use strict";var e={ss:"sekundes_sekund\u0113m_sekunde_sekundes".split("_"),m:"min\u016btes_min\u016bt\u0113m_min\u016bte_min\u016btes".split("_"),mm:"min\u016btes_min\u016bt\u0113m_min\u016bte_min\u016btes".split("_"),h:"stundas_stund\u0101m_stunda_stundas".split("_"),hh:"stundas_stund\u0101m_stunda_stundas".split("_"),d:"dienas_dien\u0101m_diena_dienas".split("_"),dd:"dienas_dien\u0101m_diena_dienas".split("_"),M:"m\u0113ne\u0161a_m\u0113ne\u0161iem_m\u0113nesis_m\u0113ne\u0161i".split("_"),MM:"m\u0113ne\u0161a_m\u0113ne\u0161iem_m\u0113nesis_m\u0113ne\u0161i".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")};function n(t,e,n){return n?e%10==1&&e%100!=11?t[2]:t[3]:e%10==1&&e%100!=11?t[0]:t[1]}function a(t,a,r){return t+" "+n(e[r],t,a)}function r(t,a,r){return n(e[r],t,a)}t.defineLocale("lv",{months:"janv\u0101ris_febru\u0101ris_marts_apr\u012blis_maijs_j\u016bnijs_j\u016blijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_j\u016bn_j\u016bl_aug_sep_okt_nov_dec".split("_"),weekdays:"sv\u0113tdiena_pirmdiena_otrdiena_tre\u0161diena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[\u0160odien pulksten] LT",nextDay:"[R\u012bt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pag\u0101ju\u0161\u0101] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"p\u0113c %s",past:"pirms %s",s:function(t,e){return e?"da\u017eas sekundes":"da\u017e\u0101m sekund\u0113m"},ss:a,m:r,mm:a,h:r,hh:a,d:r,dd:a,M:r,MM:a,y:r,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},uYzU:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){switch(t){case"user:rbd":return"user:rbd (tcmu-runner)";default:return t}},t}()},ufoC:function(t,e,n){"use strict";var a;!function(t){t.auth="Login",t.cephfs="CephFS",t.rbd="RBD",t.pool="Pool",t.osd="OSD",t.role="Role",t.user="User"}(a||(a={}));var r=n("CcnG"),i=n("Jm/i");n.d(e,"a",function(){return u});var s=function(){return function(t,e,n){this.running=t,this.failure=e,this.success=n}}(),o=function(){function t(t,e,n,a){this.i18n=t,this.operation=e,this.involves=n,this.errors=a||function(){return{}}}return t.prototype.failure=function(t){return this.i18n("Failed to {{failure}} {{metadata}}",{failure:this.operation.failure,metadata:this.involves(t)})},t.prototype.running=function(t){return this.operation.running+" "+this.involves(t)},t.prototype.success=function(t){return this.operation.success+" "+this.involves(t)},t}(),u=function(){function t(t){var e=this;this.i18n=t,this.defaultMessage=this.newTaskMessage(new s(this.i18n("Executing"),this.i18n("execute"),this.i18n("Executed")),function(t){return t&&(a[t.component]||t.component)||e.i18n("unknown task")},function(){return{}}),this.commonOperations={create:new s(this.i18n("Creating"),this.i18n("create"),this.i18n("Created")),update:new s(this.i18n("Updating"),this.i18n("update"),this.i18n("Updated")),delete:new s(this.i18n("Deleting"),this.i18n("delete"),this.i18n("Deleted"))},this.rbd={default:function(t){return e.i18n("RBD '{{id}}'",{id:t.pool_name+"/"+t.image_name})},child:function(t){return e.i18n("RBD '{{id}}'",{id:t.child_pool_name+"/"+t.child_image_name})},destination:function(t){return e.i18n("RBD '{{id}}'",{id:t.dest_pool_name+"/"+t.dest_image_name})},snapshot:function(t){return e.i18n("RBD snapshot '{{id}}'",{id:t.pool_name+"/"+t.image_name+"@"+t.snapshot_name})}},this.rbd_mirroring={pool:function(t){return e.i18n("mirror mode for pool '{{id}}'",{id:""+t.pool_name})},pool_peer:function(t){return e.i18n("mirror peer for pool '{{id}}'",{id:""+t.pool_name})}},this.grafana={update_dashboards:function(){return e.i18n("all dashboards")}},this.messages={"pool/create":this.newTaskMessage(this.commonOperations.create,function(t){return e.pool(t)},function(t){return{17:e.i18n("Name is already used by {{pool_name}}.",{pool_name:e.pool(t)})}}),"pool/edit":this.newTaskMessage(this.commonOperations.update,function(t){return e.pool(t)},function(t){return{17:e.i18n("Name is already used by {{pool_name}}.",{pool_name:e.pool(t)})}}),"pool/delete":this.newTaskMessage(this.commonOperations.delete,function(t){return e.pool(t)}),"ecp/create":this.newTaskMessage(this.commonOperations.create,function(t){return e.ecp(t)},function(t){return{17:e.i18n("Name is already used by {{name}}.",{name:e.ecp(t)})}}),"ecp/delete":this.newTaskMessage(this.commonOperations.delete,function(t){return e.ecp(t)}),"rbd/create":this.newTaskMessage(this.commonOperations.create,this.rbd.default,function(t){return{17:e.i18n("Name is already used by {{rbd_name}}.",{rbd_name:e.rbd.default(t)})}}),"rbd/edit":this.newTaskMessage(this.commonOperations.update,this.rbd.default,function(t){return{17:e.i18n("Name is already used by {{rbd_name}}.",{rbd_name:e.rbd.default(t)})}}),"rbd/delete":this.newTaskMessage(this.commonOperations.delete,this.rbd.default,function(t){return{39:e.i18n("{{rbd_name}} contains snapshots.",{rbd_name:e.rbd.default(t)})}}),"rbd/clone":this.newTaskMessage(new s(this.i18n("Cloning"),this.i18n("clone"),this.i18n("Cloned")),this.rbd.child,function(t){return{17:e.i18n("Name is already used by {{rbd_name}}.",{rbd_name:e.rbd.child(t)}),22:e.i18n("Snapshot of {{rbd_name}} must be protected.",{rbd_name:e.rbd.child(t)})}}),"rbd/copy":this.newTaskMessage(new s(this.i18n("Copying"),this.i18n("copy"),this.i18n("Copied")),this.rbd.destination,function(t){return{17:e.i18n("Name is already used by {{rbd_name}}.",{rbd_name:e.rbd.destination(t)})}}),"rbd/flatten":this.newTaskMessage(new s(this.i18n("Flattening"),this.i18n("flatten"),this.i18n("Flattened")),this.rbd.default),"rbd/snap/create":this.newTaskMessage(this.commonOperations.create,this.rbd.snapshot,function(t){return{17:e.i18n("Name is already used by {{snap_name}}.",{snap_name:e.rbd.snapshot(t)})}}),"rbd/snap/edit":this.newTaskMessage(this.commonOperations.update,this.rbd.snapshot,function(t){return{16:e.i18n("Cannot unprotect {{snap_name}} because it contains child images.",{snap_name:e.rbd.snapshot(t)})}}),"rbd/snap/delete":this.newTaskMessage(this.commonOperations.delete,this.rbd.snapshot,function(t){return{16:e.i18n("Cannot delete {{snap_name}} because it's protected.",{snap_name:e.rbd.snapshot(t)})}}),"rbd/snap/rollback":this.newTaskMessage(new s(this.i18n("Rolling back"),this.i18n("rollback"),this.i18n("Rolled back")),this.rbd.snapshot),"rbd/trash/move":this.newTaskMessage(new s(this.i18n("Moving"),this.i18n("move"),this.i18n("Moved")),function(t){return e.i18n("image '{{id}}' to trash",{id:t.pool_name+"/"+t.image_name})},function(){return{2:e.i18n("Could not find image.")}}),"rbd/trash/restore":this.newTaskMessage(new s(this.i18n("Restoring"),this.i18n("restore"),this.i18n("Restored")),function(t){return e.i18n("image '{{id}}' into '{{new_id}}'",{id:t.pool_name+"@"+t.image_id,new_id:t.pool_name+"/"+t.new_image_name})},function(t){return{17:e.i18n("Image name '{{id}}' is already in use.",{id:t.pool_name+"/"+t.new_image_name})}}),"rbd/trash/remove":this.newTaskMessage(new s(this.i18n("Deleting"),this.i18n("delete"),this.i18n("Deleted")),function(t){return e.i18n("image '{{id}}'",{id:t.pool_name+"/"+t.image_name+"@"+t.image_id})}),"rbd/trash/purge":this.newTaskMessage(new s(this.i18n("Purging"),this.i18n("purge"),this.i18n("Purged")),function(t){var n=e.i18n("all pools");return t.pool_name&&(n="'"+t.pool_name+"'"),e.i18n("images from {{message}}",{message:n})}),"rbd/mirroring/pool/edit":this.newTaskMessage(this.commonOperations.update,this.rbd_mirroring.pool,function(){return{16:e.i18n("Cannot disable mirroring because it contains a peer.")}}),"rbd/mirroring/peer/add":this.newTaskMessage(this.commonOperations.create,this.rbd_mirroring.pool_peer,function(){return{}}),"rbd/mirroring/peer/edit":this.newTaskMessage(this.commonOperations.update,this.rbd_mirroring.pool_peer,function(){return{}}),"rbd/mirroring/peer/delete":this.newTaskMessage(this.commonOperations.delete,this.rbd_mirroring.pool_peer,function(){return{}}),"iscsi/target/create":this.newTaskMessage(this.commonOperations.create,function(t){return e.iscsiTarget(t)}),"iscsi/target/edit":this.newTaskMessage(this.commonOperations.update,function(t){return e.iscsiTarget(t)}),"iscsi/target/delete":this.newTaskMessage(this.commonOperations.delete,function(t){return e.iscsiTarget(t)}),"nfs/create":this.newTaskMessage(this.commonOperations.create,function(t){return e.nfs(t)}),"nfs/edit":this.newTaskMessage(this.commonOperations.update,function(t){return e.nfs(t)}),"nfs/delete":this.newTaskMessage(this.commonOperations.delete,function(t){return e.nfs(t)}),"grafana/dashboards/update":this.newTaskMessage(this.commonOperations.update,this.grafana.update_dashboards,function(){return{}})}}return t.prototype.newTaskMessage=function(t,e,n){return new o(this.i18n,t,e,n)},t.prototype.pool=function(t){return this.i18n("pool '{{pool_name}}'",{pool_name:t.pool_name})},t.prototype.ecp=function(t){return this.i18n("erasure code profile '{{name}}'",{name:t.name})},t.prototype.iscsiTarget=function(t){return this.i18n("target '{{target_iqn}}'",{target_iqn:t.target_iqn})},t.prototype.nfs=function(t){return this.i18n("NFS {{nfs_id}}",{nfs_id:"'"+t.cluster_id+":"+(t.export_id?t.export_id:t.path)+"'"})},t.prototype._getTaskTitle=function(t){return this.messages[t.name]||this.defaultMessage},t.prototype.getSuccessTitle=function(t){return this._getTaskTitle(t).success(t.metadata)},t.prototype.getErrorMessage=function(t){return this._getTaskTitle(t).errors(t.metadata)[t.exception.code]||t.exception.detail},t.prototype.getErrorTitle=function(t){return this._getTaskTitle(t).failure(t.metadata)},t.prototype.getRunningTitle=function(t){return this._getTaskTitle(t).running(t.metadata)},t.prototype.getRunningText=function(t){return this._getTaskTitle(t).operation.running},t.ngInjectableDef=r.defineInjectable({factory:function(){return new t(r.inject(i.a))},token:t,providedIn:"root"}),t}()},uhwM:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){}return t.prototype.transform=function(t){return t.join(", ")},t}()},urB8:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=n("buEt"),i=n("QGcS");e.NodeDraggableService=function(){function t(){this.draggableNodeEvents$=new r.Subject}return t.prototype.fireNodeDragged=function(t,e){t.tree&&!t.tree.isStatic()&&this.draggableNodeEvents$.next(new i.NodeDraggableEvent(t,e))},t.prototype.captureNode=function(t){this.capturedNode=t},t.prototype.getCapturedNode=function(){return this.capturedNode},t.prototype.releaseCapturedNode=function(){this.capturedNode=null},t.decorators=[{type:a.Injectable}],t}()},uxXc:function(t,e,n){var a=n("t1N5"),r=function(){return new c};for(var i in a){r[i+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),a[t](e)}}(i);var s=/(\w+)2(\w+)/.exec(i),o=s[1],u=s[2];(r[o]=r[o]||{})[u]=r[i]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=a[t](e);if("string"==typeof n||void 0===n)return n;for(var r=0;r<n.length;r++)n[r]=Math.round(n[r]);return n}}(i)}var c=function(){this.convs={}};c.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},c.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},c.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space;e=r[n][t](this.convs[n]),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){c.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),t.exports=r},vCyI:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){function t(){this.selected=[],this.update()}return t.prototype.update=function(){this.hasSelection=this.selected.length>0,this.hasSingleSelection=1===this.selected.length,this.hasMultiSelection=this.selected.length>1},t.prototype.first=function(){return this.hasSelection?this.selected[0]:null},t}()},vOVK:function(t,e,n){var a={"./messages.cs.xlf":"MaEZ","./messages.de-DE.xlf":"BY/9","./messages.es-ES.xlf":"csGn","./messages.fr-FR.xlf":"obpP","./messages.id-ID.xlf":"nmKl","./messages.it-IT.xlf":"hHou","./messages.ja-JP.xlf":"waXJ","./messages.ko-KR.xlf":"Q3dv","./messages.pl-PL.xlf":"/6aS","./messages.pt-BR.xlf":"OWV/","./messages.zh-CN.xlf":"fB8H","./messages.zh-TW.xlf":"Dysq"};function r(t){var e=i(t);return n(e)}function i(t){var e=a[t];if(!(e+1)){var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}return e}r.keys=function(){return Object.keys(a)},r.resolve=i,t.exports=r,r.id="vOVK"},vpM6:function(t,e,n){"use strict";var a=n("CDJp"),r=n("vvH+"),i=n("RDha");a._set("global",{plugins:{filler:{propagate:!0}}});var s={dataset:function(t){var e=t.fill,n=t.chart,a=n.getDatasetMeta(e),r=a&&n.isDatasetVisible(e)&&a.dataset._children||[],i=r.length||0;return i?function(t,e){return e<i&&r[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,a=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===a?t.y:a}}}};function o(t,e,n){var a,r=t._model||{},i=r.fill;if(void 0===i&&(i=!!r.backgroundColor),!1===i||null===i)return!1;if(!0===i)return"origin";if(a=parseFloat(i,10),isFinite(a)&&Math.floor(a)===a)return"-"!==i[0]&&"+"!==i[0]||(a=e+a),!(a===e||a<0||a>=n)&&a;switch(i){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return i;default:return!1}}function u(t){var e,n=t.el._model||{},a=t.el._scale||{},r=t.fill,i=null;if(isFinite(r))return null;if("start"===r?i=void 0===n.scaleBottom?a.bottom:n.scaleBottom:"end"===r?i=void 0===n.scaleTop?a.top:n.scaleTop:void 0!==n.scaleZero?i=n.scaleZero:a.getBasePosition?i=a.getBasePosition():a.getBasePixel&&(i=a.getBasePixel()),null!=i){if(void 0!==i.x&&void 0!==i.y)return i;if("number"==typeof i&&isFinite(i))return{x:(e=a.isHorizontal())?i:null,y:e?null:i}}return null}function c(t,e,n){var a,r=t[e].fill,i=[e];if(!n)return r;for(;!1!==r&&-1===i.indexOf(r);){if(!isFinite(r))return r;if(!(a=t[r]))return!1;if(a.visible)return r;i.push(r),r=a.fill}return!1}function l(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),s[n](t))}function d(t){return t&&!t.skip}function f(t,e,n,a,r){var s;if(a&&r){for(t.moveTo(e[0].x,e[0].y),s=1;s<a;++s)i.canvas.lineTo(t,e[s-1],e[s]);for(t.lineTo(n[r-1].x,n[r-1].y),s=r-1;s>0;--s)i.canvas.lineTo(t,n[s],n[s-1],!0)}}t.exports={id:"filler",afterDatasetsUpdate:function(t,e){var n,a,i,s,d=(t.data.datasets||[]).length,f=e.propagate,p=[];for(a=0;a<d;++a)s=null,(i=(n=t.getDatasetMeta(a)).dataset)&&i._model&&i instanceof r.Line&&(s={visible:t.isDatasetVisible(a),fill:o(i,a,d),chart:t,el:i}),n.$filler=s,p.push(s);for(a=0;a<d;++a)(s=p[a])&&(s.fill=c(p,a,f),s.boundary=u(s),s.mapper=l(s))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var r=t.ctx,s=n.el,o=s._view,u=s._children||[],c=n.mapper,l=o.backgroundColor||a.global.defaultColor;c&&l&&u.length&&(i.canvas.clipArea(r,t.chartArea),function(t,e,n,a,r,i){var s,o,u,c,l,p,h,g=e.length,b=a.spanGaps,m=[],y=[],v=0,_=0;for(t.beginPath(),s=0,o=g+!!i;s<o;++s)l=n(c=e[u=s%g]._view,u,a),p=d(c),h=d(l),p&&h?(v=m.push(c),_=y.push(l)):v&&_&&(b?(p&&m.push(c),h&&y.push(l)):(f(t,m,y,v,_),v=_=0,m=[],y=[]));f(t,m,y,v,_),t.closePath(),t.fillStyle=r,t.fill()}(r,u,c,o,l,s._loop),i.canvas.unclipArea(r))}}}},"vvH+":function(t,e,n){"use strict";t.exports={},t.exports.Arc=n("X8CM"),t.exports.Line=n("UqmZ"),t.exports.Point=n("OXbD"),t.exports.Rectangle=n("2UWG")},vxfy:function(t,e,n){var a=n("mrSG").__decorate;Object.defineProperty(e,"__esModule",{value:!0});var r=n("CcnG");e.DataTableFooterTemplateDirective=function(){return a([r.Directive({selector:"[ngx-datatable-footer-template]"})],function(t){this.template=t})}()},w1EH:function(t,e,n){"use strict";n.d(e,"a",function(){return c});var a=n("3fWJ"),r=n("VnD/"),i=n("AxiF"),s=n("tNVB"),o=n("HJBe"),u=n("mChF");function c(t,e){var n=arguments.length>=2;return function(c){return c.pipe(t?Object(r.a)(function(e,n){return t(e,n,c)}):u.a,Object(i.a)(1),n?Object(o.a)(e):Object(s.a)(function(){return new a.a}))}}},wQk9:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("tzm",{months:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),monthsShort:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),weekdays:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysShort:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysMin:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[\u2d30\u2d59\u2d37\u2d45 \u2d34] LT",nextDay:"[\u2d30\u2d59\u2d3d\u2d30 \u2d34] LT",nextWeek:"dddd [\u2d34] LT",lastDay:"[\u2d30\u2d5a\u2d30\u2d4f\u2d5c \u2d34] LT",lastWeek:"dddd [\u2d34] LT",sameElse:"L"},relativeTime:{future:"\u2d37\u2d30\u2d37\u2d45 \u2d59 \u2d62\u2d30\u2d4f %s",past:"\u2d62\u2d30\u2d4f %s",s:"\u2d49\u2d4e\u2d49\u2d3d",ss:"%d \u2d49\u2d4e\u2d49\u2d3d",m:"\u2d4e\u2d49\u2d4f\u2d53\u2d3a",mm:"%d \u2d4e\u2d49\u2d4f\u2d53\u2d3a",h:"\u2d59\u2d30\u2d44\u2d30",hh:"%d \u2d5c\u2d30\u2d59\u2d59\u2d30\u2d44\u2d49\u2d4f",d:"\u2d30\u2d59\u2d59",dd:"%d o\u2d59\u2d59\u2d30\u2d4f",M:"\u2d30\u2d62o\u2d53\u2d54",MM:"%d \u2d49\u2d62\u2d62\u2d49\u2d54\u2d4f",y:"\u2d30\u2d59\u2d33\u2d30\u2d59",yy:"%d \u2d49\u2d59\u2d33\u2d30\u2d59\u2d4f"},week:{dow:6,doy:12}})}()},waXJ:function(t,e){t.exports='<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">\n <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="ja-JP">\n <body>\n <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">\n <source>Toggle navigation</source>\n <target>\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u306e\u5207\u308a\u66ff\u3048</target>\n </trans-unit>\n <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">\n <source>Dashboard</source>\n <target>\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">\n <source>Cluster</source>\n <target>\u30af\u30e9\u30b9\u30bf</target>\n </trans-unit>\n <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">\n <source>Hosts</source>\n <target>\u30db\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">\n <source>Monitors</source>\n <target>\u30e2\u30cb\u30bf\u30fc</target>\n </trans-unit>\n <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">\n <source>OSDs</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">\n <source>Configuration</source>\n <target>\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">\n <source>CRUSH map</source>\n <target>CRUSH\u30de\u30c3\u30d7</target>\n </trans-unit>\n <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">\n <source>Manager modules</source>\n <target>\u30de\u30cd\u30fc\u30b8\u30e3\u30e2\u30b8\u30e5\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">\n <source>Logs</source>\n <target>\u30ed\u30b0</target>\n </trans-unit>\n <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">\n <source>Alerts</source>\n <target>\u30a2\u30e9\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">\n <source>Silences</source>\n <target>Silences</target>\n </trans-unit>\n <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">\n <source>Pools</source>\n <target>\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">\n <source>Block</source>\n <target>\u30d6\u30ed\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">\n <source>Images</source>\n <target>\u30a4\u30e1\u30fc\u30b8</target>\n </trans-unit>\n <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">\n <source>Mirroring</source>\n <target>\u30df\u30e9\u30fc\u30ea\u30f3\u30b0</target>\n </trans-unit>\n <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">\n <source>iSCSI</source>\n <target>iSCSI</target>\n </trans-unit>\n <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">\n <source>NFS</source>\n <target>NFS</target>\n </trans-unit>\n <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">\n <source>Filesystems</source>\n <target>\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0</target>\n </trans-unit>\n <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">\n <source>Object Gateway</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4</target>\n </trans-unit>\n <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">\n <source>Daemons</source>\n <target>\u30c7\u30fc\u30e2\u30f3</target>\n </trans-unit>\n <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">\n <source>Users</source>\n <target>\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">\n <source>Buckets</source>\n <target>\u30d0\u30b1\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">\n <source>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </source>\n <target>Retrieving data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...\n </target>\n </trans-unit>\n <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">\n <source>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </source>\n <target>Displaying previously cached data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>\n for \n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n </target>\n </trans-unit>\n <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">\n <source>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </source>\n <target>Could not load data\n <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.\n Please check the cluster health.\n </target>\n </trans-unit>\n <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">\n <source>Back</source>\n <target>\u623b\u308b</target>\n </trans-unit>\n <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">\n <source>Select a Language</source>\n <target>\u8a00\u8a9e\u306e\u9078\u629e</target>\n </trans-unit>\n <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">\n <source>Loading panel data...</source>\n <target>\u30d1\u30cd\u30eb\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059...</target>\n </trans-unit>\n <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">\n <source>Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n configure and enable the monitoring functionality.\n </source>\n <target>\u76e3\u8996\u6a5f\u80fd\u3092\u8a2d\u5b9a\u304a\u3088\u3073\u6709\u52b9\u5316\n\u3059\u308b\u65b9\u6cd5\u306b\u95a2\u3059\u308b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3092\n\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">\n <source>Grafana Dashboard doesn\'t exist. Please refer to\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to\n add dashboards to Grafana.\n </source>\n <target>Grafana\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u305b\u3093\u3002\nGrafana\u306b\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3092\u8ffd\u52a0\u3059\u308b\u65b9\u6cd5\u306b\u95a2\u3059\u308b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">\n <source>Grafana Time Picker</source>\n <target>Grafana Time Picker</target>\n </trans-unit>\n <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">\n <source>Reset Settings</source>\n <target>\u8a2d\u5b9a\u306e\u30ea\u30bb\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">\n <source>Refresh</source>\n <target>Refresh</target>\n </trans-unit>\n <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">\n <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>\n <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>\n </trans-unit>\n <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </source>\n <target>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </source>\n <target>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">\n <source>Failed to load data.</source>\n <target>\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">\n <source>selected</source>\n <target>\u9078\u629e\u6e08\u307f</target>\n <note>X selected</note>\n </trans-unit>\n <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">\n <source>found</source>\n <target>\u691c\u51fa\u6e08\u307f</target>\n <note>X found</note>\n </trans-unit>\n <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">\n <source>total</source>\n <target>\u5408\u8a08</target>\n <note>X total</note>\n </trans-unit>\n <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">\n <source>Edit</source>\n <target>\u7de8\u96c6</target>\n </trans-unit>\n <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">\n <source>Name</source>\n <target>\u540d\u524d</target>\n </trans-unit>\n <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">\n <source>Description</source>\n <target>\u8aac\u660e</target>\n </trans-unit>\n <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">\n <source>Long description</source>\n <target>\u9577\u3044\u8aac\u660e</target>\n </trans-unit>\n <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">\n <source>Default</source>\n <target>\u30c7\u30d5\u30a9\u30eb\u30c8</target>\n </trans-unit>\n <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">\n <source>Daemon default</source>\n <target>\u30c7\u30fc\u30e2\u30f3\u306e\u30c7\u30d5\u30a9\u30eb\u30c8</target>\n </trans-unit>\n <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">\n <source>Services</source>\n <target>\u30b5\u30fc\u30d3\u30b9</target>\n </trans-unit>\n <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">\n <source>Values</source>\n <target>\u5024</target>\n </trans-unit>\n <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5927\u304d\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>\u3088\u308a\u5927\u304d\u3044\u5024\u3092\u5165\u529b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>\u3088\u308a\u5c0f\u3055\u3044\u5024\u3092\u5165\u529b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">\n <source>Save</source>\n <target>\u4fdd\u5b58</target>\n </trans-unit>\n <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">\n <source>CRUSH map viewer</source>\n <target>CRUSH\u30de\u30c3\u30d7\u30d3\u30e5\u30fc\u30a2</target>\n </trans-unit>\n <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">\n <source>Hosts List</source>\n <target>\u30db\u30b9\u30c8\u30ea\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">\n <source>Overall Performance</source>\n <target>\u5168\u4f53\u7684\u306a\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9</target>\n </trans-unit>\n <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">\n <source>No entries found</source>\n <target>\u30a8\u30f3\u30c8\u30ea\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">\n <source>Cluster Logs</source>\n <target>\u30af\u30e9\u30b9\u30bf\u30ed\u30b0</target>\n </trans-unit>\n <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">\n <source>Audit Logs</source>\n <target>\u76e3\u67fb\u30ed\u30b0</target>\n </trans-unit>\n <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">\n <source>Priority:</source>\n <target>Priority:</target>\n </trans-unit>\n <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">\n <source>Keyword:</source>\n <target>Keyword:</target>\n </trans-unit>\n <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">\n <source>Date:</source>\n <target>Date:</target>\n </trans-unit>\n <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">\n <source>Datepicker</source>\n <target>Datepicker</target>\n </trans-unit>\n <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">\n <source>Time range:</source>\n <target>Time range:</target>\n </trans-unit>\n <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">\n <source>Loading configuration...</source>\n <target>\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059...</target>\n </trans-unit>\n <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">\n <source>The configuration could not be loaded.</source>\n <target>\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">\n <source>Edit Manager module</source>\n <target>\u30de\u30cd\u30fc\u30b8\u30e3\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u7de8\u96c6</target>\n </trans-unit>\n <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">\n <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u6709\u52b9\u306aUUID\u3067\u306f\u3042\u308a\u307e\u305b\u3093(\u6709\u52b9\u306aUUID\u306e\u4f8b: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8)\u3002</target>\n </trans-unit>\n <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">\n <source>The entered value needs to be a valid IP address.</source>\n <target>\u6709\u52b9\u306aIP\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">\n <source>This field is required.</source>\n <target>\u3053\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306f\u5fc5\u9808\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">\n <source>The entered value is too high! It must be lower or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5927\u304d\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>\u4ee5\u4e0b\u306e\u5024\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">\n <source>The entered value is too low! It must be greater or equal to \n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>\u4ee5\u4e0a\u306e\u5024\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">\n <source>The entered value needs to be a number.</source>\n <target>\u6570\u5b57\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">\n <source>The entered value needs to be a number or decimal.</source>\n <target>\u6570\u5b57\u307e\u305f\u306f\u5c0f\u6570\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">\n <source>Update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">\n <source>Status</source>\n <target>\u30b9\u30c6\u30fc\u30bf\u30b9</target>\n </trans-unit>\n <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">\n <source>Cluster ID</source>\n <target>\u30af\u30e9\u30b9\u30bfID</target>\n </trans-unit>\n <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">\n <source>monmap modified</source>\n <target>monmap\u304c\u5909\u66f4\u3055\u308c\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">\n <source>monmap epoch</source>\n <target>monmap\u30a8\u30dd\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">\n <source>quorum con</source>\n <target>\u5b9a\u6570con</target>\n </trans-unit>\n <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">\n <source>quorum mon</source>\n <target>\u5b9a\u6570mon</target>\n </trans-unit>\n <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">\n <source>required con</source>\n <target>\u5fc5\u9808\u306econ</target>\n </trans-unit>\n <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">\n <source>required mon</source>\n <target>\u5fc5\u9808\u306emon</target>\n </trans-unit>\n <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">\n <source>In Quorum</source>\n <target>\u5b9a\u6570\u5185</target>\n </trans-unit>\n <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">\n <source>Not In Quorum</source>\n <target>\u975e\u5b9a\u6570\u5185</target>\n </trans-unit>\n <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">\n <source>Cancel</source>\n <target>\u30ad\u30e3\u30f3\u30bb\u30eb</target>\n </trans-unit>\n <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?\n </target>\n </trans-unit>\n <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </source>\n <target>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?\n </target>\n </trans-unit>\n <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">\n <source>Are you sure that you want to \n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected \n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?\n </source>\n <target>\u9078\u629e\u3055\u308c\u305f\n <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>\u3092\n <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b?\n </target>\n </trans-unit>\n <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">\n <source>Yes, I am sure.</source>\n <target>\u306f\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">\n <source>Cluster-wide OSD Flags</source>\n <target>\u30af\u30e9\u30b9\u30bf\u5168\u4f53\u306eOSD\u30d5\u30e9\u30b0</target>\n </trans-unit>\n <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">\n <source>Submit</source>\n <target>\u9001\u4fe1</target>\n </trans-unit>\n <trans-unit id="formTitle" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form title</note>\n </trans-unit>\n <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">\n <source>Advanced...</source>\n <target>\u8a73\u7d30...</target>\n </trans-unit>\n <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">\n <source>Advanced configuration options</source>\n <target>Advanced configuration options</target>\n </trans-unit>\n <trans-unit id="formActionButton" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>\n </target>\n <note>form action button</note>\n </trans-unit>\n <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">\n <source>OSD Recovery Priority</source>\n <target>OSD\u56de\u5fa9\u512a\u5148\u5ea6</target>\n </trans-unit>\n <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">\n <source>Priority</source>\n <target>\u512a\u5148\u5ea6</target>\n </trans-unit>\n <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">\n <source>Customize priority values</source>\n <target>\u512a\u5148\u5ea6\u5024\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">\n <source>This field is required!</source>\n <target>\u3053\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306f\u5fc5\u9808\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">\n <source>The entered value is too high! It must not be greater than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5927\u304d\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>\u3088\u308a\u5927\u304d\u3044\u5024\u3092\u5165\u529b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">\n <source>The entered value is too low! It must not be lower than \n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.\n </source>\n <target>\u5165\u529b\u3055\u308c\u305f\u5024\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002\n <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>\u3088\u308a\u5c0f\u3055\u3044\u5024\u3092\u5165\u529b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">\n <source>Reweight OSD</source>\n <target>\u518d\u91cd\u307f\u3065\u3051OSD</target>\n </trans-unit>\n <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">\n <source>The value needs to be between 0 and 1.</source>\n <target>\u5024\u306f0\u30681\u306e\u9593\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">\n <source>Reweight</source>\n <target>\u518d\u91cd\u307f\u3065\u3051</target>\n </trans-unit>\n <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">\n <source>OSDs \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub\n </source>\n <target>OSD \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\u30b9\u30af\u30e9\u30d6\n </target>\n </trans-unit>\n <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">\n <source>{VAR_SELECT, select, 1 {Deep } }</source>\n <target>{VAR_SELECT, select, 1 {Deep } }</target>\n </trans-unit>\n <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">\n <source>You are about to apply a \n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to\n the OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>\u30b9\u30af\u30e9\u30d6\u3092OSD \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u306b\n\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">\n <source>{VAR_SELECT, select, 1 {deep } }</source>\n <target>{VAR_SELECT, select, 1 {deep } }</target>\n </trans-unit>\n <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">\n <source>OSDs List</source>\n <target>OSD\u30ea\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u7d9a\u884c\u3057\u305f\u5834\u5408\u306f\u3001\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u306f\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3068\u30de\u30fc\u30af\u3055\u308c\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">\n <source>The OSD is not safe to destroy!</source>\n <target>\u3053\u306eOSD\u3092\u5b89\u5168\u306b\u7834\u68c4\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">\n <source>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.\n </source>\n <target>\u7d9a\u884c\u3057\u305f\u5834\u5408\u306f\u3001\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD \n <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u306f\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u3055\u308c\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">\n <source>Details</source>\n <target>\u8a73\u7d30</target>\n </trans-unit>\n <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">\n <source>Matcher</source>\n <target>Matcher</target>\n </trans-unit>\n <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">\n <source>-- Select an attribute to match against --</source>\n <target>-- Select an attribute to match against --</target>\n </trans-unit>\n <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">\n <source>Value</source>\n <target>\u5024</target>\n </trans-unit>\n <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">\n <source>Use regular expression</source>\n <target>Use regular expression</target>\n </trans-unit>\n <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">\n <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>\n <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">\n <source>Close</source>\n <target>\u9589\u3058\u308b</target>\n </trans-unit>\n <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">\n <source>Delete</source>\n <target>\u524a\u9664</target>\n </trans-unit>\n <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">\n <source>Editing a silence will expire the old silence and recreate it as a new silence</source>\n <target>Editing a silence will expire the old silence and recreate it as a new silence</target>\n </trans-unit>\n <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">\n <source>Creator</source>\n <target>Creator</target>\n </trans-unit>\n <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">\n <source>Comment</source>\n <target>Comment</target>\n </trans-unit>\n <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">\n <source>Start time</source>\n <target>Start time</target>\n </trans-unit>\n <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">\n <source>If the start time lies in the past the creation time will be used</source>\n <target>If the start time lies in the past the creation time will be used</target>\n </trans-unit>\n <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">\n <source>Duration</source>\n <target>Duration</target>\n </trans-unit>\n <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">\n <source>End time</source>\n <target>End time</target>\n </trans-unit>\n <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">\n <source>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </source>\n <target>Matchers\n <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*\n <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>\n </target>\n </trans-unit>\n <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">\n <source>A silence requires at least one matcher</source>\n <target>A silence requires at least one matcher</target>\n </trans-unit>\n <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">\n <source>Add matcher</source>\n <target>Add matcher</target>\n </trans-unit>\n <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">\n <source>Health</source>\n <target>\u30d8\u30eb\u30b9</target>\n </trans-unit>\n <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">\n <source>Statistics</source>\n <target>\u7d71\u8a08\u60c5\u5831</target>\n </trans-unit>\n <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the NFS Ganesha management functionality.\n </source>\n <target>NFS Ganesha\u306e\u7ba1\u7406\u6a5f\u80fd\u3092\u8a2d\u5b9a\u304a\u3088\u3073\u6709\u52b9\u5316\n\u3059\u308b\u65b9\u6cd5\u306b\u95a2\u3059\u308b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">\n <source>Clients</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8</target>\n </trans-unit>\n <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">\n <source>Any client can access</source>\n <target>\u4efb\u610f\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">\n <source>Addresses</source>\n <target>\u30a2\u30c9\u30ec\u30b9</target>\n </trans-unit>\n <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">\n <source>Required field</source>\n <target>\u5fc5\u9808\u30d5\u30a3\u30fc\u30eb\u30c9</target>\n </trans-unit>\n <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">\n <source>Must contain one or more comma-separated values</source>\n <target>1\u3064\u4ee5\u4e0a\u306e\u30ab\u30f3\u30de\u533a\u5207\u308a\u5024\u3092\u542b\u3093\u3067\u3044\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">\n <source>For example:</source>\n <target>\u4f8b:</target>\n </trans-unit>\n <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">\n <source>Access Type</source>\n <target>\u30a2\u30af\u30bb\u30b9\u30bf\u30a4\u30d7</target>\n </trans-unit>\n <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">\n <source>Squash</source>\n <target>\u30b9\u30ab\u30c3\u30b7\u30e5</target>\n </trans-unit>\n <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">\n <source>Add clients</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">\n <source>Loading...</source>\n <target>\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059...</target>\n </trans-unit>\n <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">\n <source>-- No cluster available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30af\u30e9\u30b9\u30bf\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">\n <source>-- Select the cluster --</source>\n <target>-- \u30af\u30e9\u30b9\u30bf\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">\n <source>Add daemon</source>\n <target>\u30c7\u30fc\u30e2\u30f3\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">\n <source>Storage Backend</source>\n <target>\u30b9\u30c8\u30ec\u30fc\u30b8\u30d0\u30c3\u30af\u30a8\u30f3\u30c9</target>\n </trans-unit>\n <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">\n <source>-- No data pools available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30c7\u30fc\u30bf\u30d7\u30fc\u30eb\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">\n <source>-- Select the storage backend --</source>\n <target>-- \u30b9\u30c8\u30ec\u30fc\u30b8\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">\n <source>Object Gateway User</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">\n <source>-- No users available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30e6\u30fc\u30b6\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">\n <source>-- Select the object gateway user --</source>\n <target>-- \u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30e6\u30fc\u30b6\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">\n <source>CephFS User ID</source>\n <target>CephFS\u30e6\u30fc\u30b6ID</target>\n </trans-unit>\n <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">\n <source>-- No clients available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">\n <source>-- Select the cephx client --</source>\n <target>-- cephx\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">\n <source>CephFS Name</source>\n <target>CephFS\u540d</target>\n </trans-unit>\n <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">\n <source>-- No CephFS filesystem available --</source>\n <target>-- No CephFS filesystem available --</target>\n </trans-unit>\n <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">\n <source>-- Select the CephFS filesystem --</source>\n <target>-- Select the CephFS filesystem --</target>\n </trans-unit>\n <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">\n <source>Security Label</source>\n <target>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30e9\u30d9\u30eb</target>\n </trans-unit>\n <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">\n <source>Enable security label</source>\n <target>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30e9\u30d9\u30eb\u306e\u6709\u52b9\u5316</target>\n </trans-unit>\n <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">\n <source>CephFS Path</source>\n <target>CephFS\u30d1\u30b9</target>\n </trans-unit>\n <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">\n <source>Path need to start with a \'/\' and can be followed by a word</source>\n <target>\u30d1\u30b9\u306f\u300c/\u300d\u3067\u59cb\u307e\u308b\u5fc5\u8981\u304c\u3042\u308a\u3001\u305d\u306e\u5f8c\u308d\u306b1\u3064\u306e\u5358\u8a9e\u3092\u914d\u7f6e\u3067\u304d\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">\n <source>New directory will be created</source>\n <target>\u65b0\u3057\u3044\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u4f5c\u6210\u3055\u308c\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">\n <source>Path</source>\n <target>\u30d1\u30b9</target>\n </trans-unit>\n <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">\n <source>Path can only be a single \'/\' or a word</source>\n <target>\u30d1\u30b9\u306f\u5358\u4e00\u306e\u300c/\u300d\u307e\u305f\u306f1\u3064\u306e\u5358\u8a9e\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">\n <source>New bucket will be created</source>\n <target>\u65b0\u3057\u3044\u30d0\u30b1\u30c3\u30c8\u304c\u4f5c\u6210\u3055\u308c\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">\n <source>NFS Protocol</source>\n <target>NFS\u30d7\u30ed\u30c8\u30b3\u30eb</target>\n </trans-unit>\n <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">\n <source>NFSv3</source>\n <target>NFSv3</target>\n </trans-unit>\n <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">\n <source>NFSv4</source>\n <target>NFSv4</target>\n </trans-unit>\n <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">\n <source>NFS Tag</source>\n <target>NFS\u30bf\u30b0</target>\n </trans-unit>\n <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">\n <source>Alternative access for \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u30de\u30a6\u30f3\u30c8\u306e\u4ee3\u66ff\u30a2\u30af\u30bb\u30b9(\u5148\u982d\u306b\u300c/\u300d\u304c\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093)\u3002\n </target>\n </trans-unit>\n <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">\n <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u30b5\u30d6\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u30de\u30a6\u30f3\u30c8\u3067\u304d\u307e\u305b\u3093(\u305f\u3068\u3048\u3070\u3001\uff3b\u30bf\u30b0\uff3d = foo\u306e\u5834\u5408\u306f\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306ffoo/baz\u3092\u30de\u30a6\u30f3\u30c8\u3067\u304d\u307e\u305b\u3093)\u3002</target>\n </trans-unit>\n <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">\n <source>By using different Tag options, the same Path may be exported multiple times.</source>\n <target>\u7570\u306a\u308b\uff3b\u30bf\u30b0\uff3d\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u540c\u3058\u30d1\u30b9\u3092\u8907\u6570\u56de\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">\n <source>Pseudo</source>\n <target>\u7591\u4f3c</target>\n </trans-unit>\n <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">\n <source>The position that this \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies\n in the \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).\n </source>\n <target>\u3053\u306e\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u304c\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\u7591\u4f3cFS\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u5185\u3067\n\u5360\u6709\u3059\u308b\u4f4d\u7f6e(\u3053\u306e\u4f4d\u7f6e\u306f\u4e00\u610f\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059)\u3002\n </target>\n </trans-unit>\n <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">\n <source>By using different Pseudo options, the same Path may be exported multiple times.</source>\n <target>\u7570\u306a\u308b\uff3b\u7591\u4f3c\uff3d\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u540c\u3058\u30d1\u30b9\u3092\u8907\u6570\u56de\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">\n <source>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>\n <target>Pseudo needs to start with a \'/\' and can\'t contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>\n </trans-unit>\n <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">\n <source>-- No access type available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30a2\u30af\u30bb\u30b9\u30bf\u30a4\u30d7\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">\n <source>-- Select the access type --</source>\n <target>-- \u30a2\u30af\u30bb\u30b9\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">\n <source>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </source>\n <target>The Object Gateway NFS backend has a number of\n limitations which will seriously affect applications writing to\n the share. Please consult the\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.\n </target>\n </trans-unit>\n <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">\n <source>-- No squash available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30b9\u30ab\u30c3\u30b7\u30e5\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">\n <source>--Select what kind of user id squashing is performed --</source>\n <target>-- \u5b9f\u884c\u3055\u308c\u308b\u30e6\u30fc\u30b6ID\u30b9\u30ab\u30c3\u30b7\u30e5\u64cd\u4f5c\u306e\u7a2e\u985e\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">\n <source>Transport Protocol</source>\n <target>\u30c8\u30e9\u30f3\u30b9\u30dd\u30fc\u30c8\u30d7\u30ed\u30c8\u30b3\u30eb</target>\n </trans-unit>\n <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">\n <source>UDP</source>\n <target>UDP</target>\n </trans-unit>\n <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">\n <source>TCP</source>\n <target>TCP</target>\n </trans-unit>\n <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">\n <source>CephFS</source>\n <target>CephFS</target>\n </trans-unit>\n <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">\n <source>Welcome to Ceph!</source>\n <target>Ceph\u306b\u3088\u3046\u3053\u305d!</target>\n <note>The welcome message on the login page</note>\n </trans-unit>\n <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">\n <source>Username is required</source>\n <target>\u30e6\u30fc\u30b6\u540d\u306f\u5fc5\u9808\u3067\u3059</target>\n </trans-unit>\n <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">\n <source>Password is required</source>\n <target>\u30d1\u30b9\u30ef\u30fc\u30c9\u306f\u5fc5\u9808\u3067\u3059</target>\n </trans-unit>\n <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">\n <source>Login</source>\n <target>\u30ed\u30b0\u30a4\u30f3</target>\n </trans-unit>\n <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">\n <source>Sorry, the user does not exist in Ceph.</source>\n <target>\u3053\u306e\u30e6\u30fc\u30b6\u306fCeph\u306b\u5b58\u5728\u3057\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">\n <source>Return to \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You\'ll be logged out from the Identity Provider when you retry logging in.\n </source>\n <target>\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\uff3b\u30ed\u30b0\u30a4\u30f3\uff3d\u30da\u30fc\u30b8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u306b\u623b\u308a\u307e\u3059\u3002\u30ed\u30b0\u30a4\u30f3\u3092\u518d\u8a66\u884c\u3059\u308b\u3068\u3001Identity Provider\u304b\u3089\u30ed\u30b0\u30a2\u30a6\u30c8\u3055\u308c\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">\n <source>Forbidden</source>\n <target>\u7981\u6b62</target>\n </trans-unit>\n <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">\n <source>Sorry, you are not allowed to see what you were looking for.</source>\n <target>\u691c\u7d22\u3057\u3066\u3044\u305f\u5185\u5bb9\u3092\u8868\u793a\u3059\u308b\u3053\u3068\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">\n <source>Sorry, we could not find what you were looking for</source>\n <target>\u691c\u7d22\u3057\u3066\u3044\u305f\u5185\u5bb9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">\n <source>Remove all</source>\n <target>\u3059\u3079\u3066\u524a\u9664</target>\n </trans-unit>\n <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">\n <source>Recent Notifications</source>\n <target>\u6700\u8fd1\u306e\u901a\u77e5</target>\n </trans-unit>\n <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">\n <source>There are no background tasks.</source>\n <target>\u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u30bf\u30b9\u30af\u304c\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">\n <source>Background Tasks</source>\n <target>\u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u30bf\u30b9\u30af</target>\n </trans-unit>\n <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">\n <source>Help</source>\n <target>\u30d8\u30eb\u30d7</target>\n </trans-unit>\n <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">\n <source>Documentation</source>\n <target>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8</target>\n </trans-unit>\n <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">\n <source>API</source>\n <target>API</target>\n </trans-unit>\n <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">\n <source>About</source>\n <target>\u30d0\u30fc\u30b8\u30e7\u30f3\u60c5\u5831</target>\n </trans-unit>\n <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">\n <source>Dashboard Settings</source>\n <target>\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">\n <source>User management</source>\n <target>\u30e6\u30fc\u30b6\u7ba1\u7406</target>\n </trans-unit>\n <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">\n <source>Logged in user</source>\n <target>\u30ed\u30b0\u30a4\u30f3\u6e08\u307f\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">\n <source>Signed in as\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>\n <x id="INTERPOLATION" equiv-text="{{ username }}"/>\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\n\u3068\u3057\u3066\u30b5\u30a4\u30f3\u30a4\u30f3\u6e08\u307f\n </target>\n </trans-unit>\n <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">\n <source>Sign out</source>\n <target>\u30b5\u30a4\u30f3\u30a2\u30a6\u30c8</target>\n </trans-unit>\n <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">\n <source>Name...</source>\n <target>\u540d\u524d...</target>\n </trans-unit>\n <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">\n <source>The chosen name is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305f\u540d\u524d\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">\n <source>Description...</source>\n <target>\u8aac\u660e...</target>\n </trans-unit>\n <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">\n <source>Permissions</source>\n <target>\u8a31\u53ef</target>\n </trans-unit>\n <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">\n <source>Roles</source>\n <target>\u5f79\u5272</target>\n </trans-unit>\n <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">\n <source>Username</source>\n <target>\u30e6\u30fc\u30b6\u540d</target>\n </trans-unit>\n <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">\n <source>Password</source>\n <target>\u30d1\u30b9\u30ef\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">\n <source>Confirm password</source>\n <target>\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u78ba\u8a8d\u5165\u529b</target>\n </trans-unit>\n <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">\n <source>Password confirmation doesn\'t match the password.</source>\n <target>\u78ba\u8a8d\u5165\u529b\u3055\u308c\u305f\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u30d1\u30b9\u30ef\u30fc\u30c9\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">\n <source>Full name</source>\n <target>\u6c0f\u540d</target>\n </trans-unit>\n <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">\n <source>Email</source>\n <target>\u96fb\u5b50\u30e1\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">\n <source>Invalid email.</source>\n <target>\u7121\u52b9\u306a\u96fb\u5b50\u30e1\u30fc\u30eb\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">\n <source>You are about to remove "user read / update" permissions from your own user.</source>\n <target>\u81ea\u8eab\u306e\u30e6\u30fc\u30b6\u304b\u3089\u300cuser read / update\u300d\u3068\u3044\u3046\u8a31\u53ef\u3092\u524a\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">\n <source>If you continue, you will no longer be able to add or remove roles from any user.</source>\n <target>\u7d9a\u884c\u3057\u305f\u5834\u5408\u306f\u3001\u3069\u306e\u30e6\u30fc\u30b6\u306e\u5f79\u5272\u3082\u8ffd\u52a0\u304a\u3088\u3073\u524a\u9664\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">\n <source>Are you sure you want to continue?</source>\n <target>\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b?</target>\n </trans-unit>\n <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">\n <source>Performance counters not available</source>\n <target>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30ab\u30a6\u30f3\u30bf\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">\n <source>Attributes (OSD map)</source>\n <target>\u5c5e\u6027(OSD\u30de\u30c3\u30d7)</target>\n </trans-unit>\n <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">\n <source>Metadata not available</source>\n <target>\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">\n <source>Metadata</source>\n <target>\u30e1\u30bf\u30c7\u30fc\u30bf</target>\n </trans-unit>\n <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">\n <source>Performance counter</source>\n <target>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30ab\u30a6\u30f3\u30bf</target>\n </trans-unit>\n <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">\n <source>Histogram not available: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </source>\n <target>\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093: \n <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>\n </target>\n </trans-unit>\n <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">\n <source>Writes</source>\n <target>\u66f8\u304d\u8fbc\u307f\u56de\u6570</target>\n </trans-unit>\n <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">\n <source>Reads</source>\n <target>\u8aad\u307f\u53d6\u308a\u56de\u6570</target>\n </trans-unit>\n <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">\n <source>Histogram</source>\n <target>\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0</target>\n </trans-unit>\n <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">\n <source>Performance Details</source>\n <target>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u306e\u8a73\u7d30</target>\n </trans-unit>\n <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">\n <source>Current values</source>\n <target>\u73fe\u884c\u5024</target>\n </trans-unit>\n <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">\n <source>Type</source>\n <target>\u30bf\u30a4\u30d7</target>\n </trans-unit>\n <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">\n <source>Min</source>\n <target>\u6700\u5c0f</target>\n </trans-unit>\n <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">\n <source>Max</source>\n <target>\u6700\u5927</target>\n </trans-unit>\n <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">\n <source>Flags</source>\n <target>\u30d5\u30e9\u30b0</target>\n </trans-unit>\n <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">\n <source>Source</source>\n <target>\u30bd\u30fc\u30b9</target>\n </trans-unit>\n <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">\n <source>Level</source>\n <target>\u30ec\u30d9\u30eb</target>\n </trans-unit>\n <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">\n <source>Can be updated at runtime (editable)</source>\n <target>\u5b9f\u884c\u6642\u306b\u66f4\u65b0\u3067\u304d\u307e\u3059(\u7de8\u96c6\u53ef\u80fd)</target>\n </trans-unit>\n <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">\n <source>Tags</source>\n <target>\u30bf\u30b0</target>\n </trans-unit>\n <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">\n <source>Enum values</source>\n <target>\u5217\u6319\u5024</target>\n </trans-unit>\n <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">\n <source>See also</source>\n <target>\u95a2\u9023\u9805\u76ee</target>\n </trans-unit>\n <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">\n <source>Cluster Status</source>\n <target>\u30af\u30e9\u30b9\u30bf\u306e\u30b9\u30c6\u30fc\u30bf\u30b9</target>\n </trans-unit>\n <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">\n <source>Manager Daemons</source>\n <target>\u30de\u30cd\u30fc\u30b8\u30e3\u30c7\u30fc\u30e2\u30f3</target>\n </trans-unit>\n <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">\n <source>Object Gateways</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4</target>\n </trans-unit>\n <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">\n <source>Metadata Servers</source>\n <target>\u30e1\u30bf\u30c7\u30fc\u30bf\u30b5\u30fc\u30d0</target>\n </trans-unit>\n <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">\n <source>iSCSI Gateways</source>\n <target>iSCSI\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4</target>\n </trans-unit>\n <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">\n <source>Client IOPS</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306eIOPS</target>\n </trans-unit>\n <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">\n <source>Client Throughput</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u30b9\u30eb\u30fc\u30d7\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">\n <source>Client Read/Write</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u8aad\u307f\u53d6\u308a/\u66f8\u304d\u8fbc\u307f</target>\n </trans-unit>\n <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">\n <source>Recovery Throughput</source>\n <target>\u56de\u5fa9\u30b9\u30eb\u30fc\u30d7\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">\n <source>Scrub</source>\n <target>\u30b9\u30af\u30e9\u30d6</target>\n </trans-unit>\n <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">\n <source>Performance</source>\n <target>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9</target>\n </trans-unit>\n <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">\n <source>Raw Capacity</source>\n <target>\u672a\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u6642\u306e\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">\n <source>Objects</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">\n <source>PGs per OSD</source>\n <target>OSD\u3042\u305f\u308a\u306e\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u6570</target>\n </trans-unit>\n <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">\n <source>PG Status</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u306e\u30b9\u30c6\u30fc\u30bf\u30b9</target>\n </trans-unit>\n <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">\n <source>Capacity</source>\n <target>\u5bb9\u91cf</target>\n </trans-unit>\n <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">\n <source>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.\n </source>\n <target>\n <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>\n <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001\u300c\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30ed\u30b0\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u300d\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">\n <source>Ranks</source>\n <target>\u30e9\u30f3\u30af</target>\n </trans-unit>\n <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">\n <source>MDS performance counters</source>\n <target>MDS performance counters</target>\n </trans-unit>\n <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">\n <source>Clients: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u6570: \n <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>\n </target>\n </trans-unit>\n <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">\n <source>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </source>\n <target>Clients (\n <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)\n </target>\n </trans-unit>\n <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">\n <source>Move an image to trash</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u3092\u3054\u307f\u7bb1\u306b\u79fb\u52d5\u3059\u308b</target>\n </trans-unit>\n <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">\n <source>To move \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,\n click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.\n </source>\n <target>\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/\n <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3092\u3054\u307f\u7bb1\u306b\u79fb\u52d5\u3059\u308b\u306b\u306f\u3001\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\uff3b\u30a4\u30e1\u30fc\u30b8\u306e\u79fb\u52d5\uff3d\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059\u3002\u5e0c\u671b\u306b\u5fdc\u3058\u3066\u3001\u5931\u52b9\u65e5\u3092\u9078\u629e\u3067\u304d\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">\n <source>Protection expires at</source>\n <target>\u4fdd\u8b77\u306e\u5931\u52b9\u65e5</target>\n </trans-unit>\n <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">\n <source>NOT PROTECTED</source>\n <target>\u4fdd\u8b77\u3055\u308c\u3066\u3044\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">\n <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>\n <target>\u65e5\u4ed8\u306e\u5f62\u5f0f\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\u300cYYYY-MM-DD HH:mm:ss\u300d\u3068\u3044\u3046\u5f62\u5f0f\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">\n <source>Protection has already expired. Please pick a future date or leave it empty.</source>\n <target>\u4fdd\u8b77\u306f\u3059\u3067\u306b\u5931\u52b9\u3057\u3066\u3044\u307e\u3059\u3002\u5c06\u6765\u306e\u65e5\u4ed8\u3092\u9078\u629e\u3059\u308b\u304b\u3001\u65e5\u4ed8\u3092\u7a7a\u767d\u306e\u307e\u307e\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">\n <source>Move Image</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u306e\u79fb\u52d5</target>\n </trans-unit>\n <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">\n <source>Gateways</source>\n <target>Gateways</target>\n </trans-unit>\n <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">\n <source>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </source>\n <target>Must be greater than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'min\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">\n <source>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </source>\n <target>Must be less than or equal to \n <x id="INTERPOLATION" equiv-text="{{ limits[\'max\'] }}"/>.\n </target>\n </trans-unit>\n <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">\n <source>Overview</source>\n <target>\u6982\u8981</target>\n </trans-unit>\n <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">\n <source>Targets</source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">\n <source>Discovery Authentication</source>\n <target>\u691c\u51fa\u8a8d\u8a3c</target>\n </trans-unit>\n <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">\n <source>User</source>\n <target>\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u30e6\u30fc\u30b6\u540d\u306f8\uff5e64\u6587\u5b57\u306e\u9577\u3055\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u3001\n\u82f1\u5b57\u3001\u300c.\u300d\u3001\u300c@\u300d\u3001\u300c-\u300d\u3001\u300c_\u300d\u3001\u307e\u305f\u306f\u300c:\u300d\u306e\u307f\u3067\u69cb\u6210\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">\n <source>Mutual User</source>\n <target>\u76f8\u4e92\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">\n <source>Mutual Password</source>\n <target>\u76f8\u4e92\u30d1\u30b9\u30ef\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the iSCSI Targets management functionality.\n </source>\n <target>iSCSI\u30bf\u30fc\u30b2\u30c3\u30c8\u306e\u7ba1\u7406\u6a5f\u80fd\u3092\u8a2d\u5b9a\u304a\u3088\u3073\u6709\u52b9\u5316\n\u3059\u308b\u65b9\u6cd5\u306b\u95a2\u3059\u308b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">\n <source>Available information:</source>\n <target>\u53d6\u5f97\u53ef\u80fd\u306a\u60c5\u5831:</target>\n </trans-unit>\n <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">\n <source>iSCSI Targets not available</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306aiSCSI\u30bf\u30fc\u30b2\u30c3\u30c8\u304c\u3042\u308a\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">\n <source>Discovery authentication</source>\n <target>Discovery authentication</target>\n </trans-unit>\n <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">\n <source>Only available for RBD images with \n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled\n </source>\n <target>\n <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff\n <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u308bRBD\u30a4\u30e1\u30fc\u30b8\u306e\u307f\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\n </target>\n </trans-unit>\n <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">\n <source>Pool</source>\n <target>\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">\n <source>Data Pool</source>\n <target>\u30c7\u30fc\u30bf\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">\n <source>Created</source>\n <target>\u4f5c\u6210\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">\n <source>Size</source>\n <target>\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">\n <source>Object size</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">\n <source>Features</source>\n <target>\u6a5f\u80fd</target>\n </trans-unit>\n <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">\n <source>Provisioned</source>\n <target>\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">\n <source>N/A</source>\n <target>\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">\n <source>Total provisioned</source>\n <target>\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u6e08\u307f\u5408\u8a08</target>\n </trans-unit>\n <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">\n <source>Striping unit</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d4\u30f3\u30b0\u5358\u4f4d</target>\n </trans-unit>\n <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">\n <source>Striping count</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d4\u30f3\u30b0\u6570</target>\n </trans-unit>\n <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">\n <source>Parent</source>\n <target>\u89aa</target>\n </trans-unit>\n <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">\n <source>Block name prefix</source>\n <target>\u30d6\u30ed\u30c3\u30af\u540d\u306e\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9</target>\n </trans-unit>\n <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">\n <source>Order</source>\n <target>\u9806\u756a</target>\n </trans-unit>\n <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">\n <source>Snapshots</source>\n <target>\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">\n <source>Image</source>\n <target>\u30a4\u30e1\u30fc\u30b8</target>\n </trans-unit>\n <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">\n <source>This setting overrides the global value</source>\n <target>\u3053\u306e\u8a2d\u5b9a\u306f\u30b0\u30ed\u30fc\u30d0\u30eb\u5024\u3088\u308a\u3082\u512a\u5148\u3055\u308c\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">\n <source>Global</source>\n <target>\u30b0\u30ed\u30fc\u30d0\u30eb</target>\n </trans-unit>\n <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">\n <source>This is the global value. No value for this option has been set for this image.</source>\n <target>\u3053\u308c\u306f\u30b0\u30ed\u30fc\u30d0\u30eb\u5024\u3067\u3059\u3002\u3053\u306e\u30a4\u30e1\u30fc\u30b8\u306b\u3064\u3044\u3066\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u5024\u306f\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from\n </target>\n </trans-unit>\n <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">\n <source>\'/\' and \'@\' are not allowed.</source>\n <target>\u300c/\u300d\u3068\u300c@\u300d\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">\n <source>-- No rbd pools available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306arbd\u30d7\u30fc\u30eb\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">\n <source>-- Select a pool --</source>\n <target>-- \u30d7\u30fc\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">\n <source>Use a dedicated data pool</source>\n <target>\u5c02\u7528\u306e\u30c7\u30fc\u30bf\u30d7\u30fc\u30eb\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044</target>\n </trans-unit>\n <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">\n <source>Data pool</source>\n <target>\u30c7\u30fc\u30bf\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">\n <source>Dedicated pool that stores the object-data of the RBD.</source>\n <target>RBD\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30c7\u30fc\u30bf\u3092\u4fdd\u7ba1\u3059\u308b\u305f\u3081\u306e\u5c02\u7528\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">\n <source>e.g., 10GiB</source>\n <target>\u4f8b: 10GiB</target>\n </trans-unit>\n <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">\n <source>You have to increase the size.</source>\n <target>\u30b5\u30a4\u30ba\u3092\u5927\u304d\u304f\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">\n <source>Advanced</source>\n <target>\u8a73\u7d30</target>\n </trans-unit>\n <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">\n <source>Striping</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d4\u30f3\u30b0</target>\n </trans-unit>\n <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">\n <source>Stripe unit</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u5358\u4f4d</target>\n </trans-unit>\n <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">\n <source>-- Select stripe unit --</source>\n <target>-- \u30b9\u30c8\u30e9\u30a4\u30d7\u5358\u4f4d\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">\n <source>This field is required because stripe count is defined!</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u6570\u304c\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u3053\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306f\u5fc5\u9808\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">\n <source>Stripe unit is greater than object size.</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u5358\u4f4d\u304c\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b5\u30a4\u30ba\u3088\u308a\u5927\u304d\u3044\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">\n <source>Stripe count</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u6570</target>\n </trans-unit>\n <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">\n <source>This field is required because stripe unit is defined!</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u5358\u4f4d\u304c\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u3053\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306f\u5fc5\u9808\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">\n <source>Stripe count must be greater than 0.</source>\n <target>\u30b9\u30c8\u30e9\u30a4\u30d7\u6570\u306f0\u3088\u308a\u5927\u304d\u3044\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\n </target>\n </trans-unit>\n <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">\n <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>\n <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>\n </trans-unit>\n <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">\n <source>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot\n </source>\n <target>\n <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\n </target>\n </trans-unit>\n <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">\n <source>PROTECTED</source>\n <target>\u4fdd\u8b77\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">\n <source>UNPROTECTED</source>\n <target>\u672a\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">\n <source>You are about to rollback</source>\n <target>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">\n <source>Purge Trash</source>\n <target>\u3054\u307f\u7bb1\u3092\u7a7a\u306b\u3059\u308b</target>\n </trans-unit>\n <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">\n <source>To purge, select one or All images and click</source>\n <target>\u7a7a\u306b\u3059\u308b\u306b\u306f\u30011\u3064\u307e\u305f\u306f\u3059\u3079\u3066\u306e\u30a4\u30e1\u30fc\u30b8\u3092\u9078\u629e\u3057\u3066\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">\n <source>Pool:</source>\n <target>\u30d7\u30fc\u30eb:</target>\n </trans-unit>\n <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">\n <source>Pool name...</source>\n <target>\u30d7\u30fc\u30eb\u540d...</target>\n </trans-unit>\n <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">\n <source>All</source>\n <target>\u3059\u3079\u3066</target>\n </trans-unit>\n <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">\n <source>Restore Image</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u306e\u5fa9\u5143</target>\n </trans-unit>\n <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">\n <source>To restore</source>\n <target>\u5fa9\u5143\u3059\u308b\u306b\u306f</target>\n </trans-unit>\n <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">\n <source>type the image\'s new name and click</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u306e\u65b0\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">\n <source>New Name</source>\n <target>\u65b0\u3057\u3044\u540d\u524d</target>\n </trans-unit>\n <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">\n <source>Expired at</source>\n <target>\u5931\u52b9\u65e5</target>\n </trans-unit>\n <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">\n <source>Protected until</source>\n <target>\u4fdd\u8b77\u306e\u7d42\u4e86\u65e5</target>\n </trans-unit>\n <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">\n <source>This image is protected until \n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.\n </source>\n <target>\u3053\u306e\u30a4\u30e1\u30fc\u30b8\u306f\n <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>\u307e\u3067\u4fdd\u8b77\u3055\u308c\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">\n <source>Trash</source>\n <target>\u3054\u307f\u7bb1</target>\n </trans-unit>\n <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">\n <source>iSCSI Topology</source>\n <target>iSCSI\u30c8\u30dd\u30ed\u30b8</target>\n </trans-unit>\n <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">\n <source>Configure</source>\n <target>Configure</target>\n </trans-unit>\n <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">\n <source>Changing these parameters from their default values is usually not necessary.</source>\n <target>\u901a\u5e38\u306f\u3053\u308c\u3089\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u304b\u3089\u5909\u66f4\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">\n <source>Identifier</source>\n <target>Identifier</target>\n </trans-unit>\n <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">\n <source>lun</source>\n <target>lun</target>\n </trans-unit>\n <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">\n <source>wwn</source>\n <target>wwn</target>\n </trans-unit>\n <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">\n <source>Settings</source>\n <target>\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">\n <source>Backstore</source>\n <target>\u30d0\u30c3\u30af\u30b9\u30c8\u30a2</target>\n </trans-unit>\n <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">\n <source>Confirm</source>\n <target>\u78ba\u8a8d</target>\n </trans-unit>\n <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">\n <source>Advanced Settings</source>\n <target>\u8a73\u7d30\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">\n <source>Target IQN</source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8IQN</target>\n </trans-unit>\n <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">\n <source>IQN has wrong pattern.</source>\n <target>IQN\u306e\u30d1\u30bf\u30fc\u30f3\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">\n <source>An IQN has the following notation \'iqn.$year-$month.$reversedAddress:$definedName\'</source>\n <target>IQN\u306f\u300ciqn.$year-$month.$reversedAddress:$definedName\u300d\u3068\u3044\u3046\u5f62\u5f0f\u3067\u8868\u8a18\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">\n <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>\n <target>\u4f8b: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>\n </trans-unit>\n <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">\n <source>More information</source>\n <target>\u8a73\u7d30\u60c5\u5831</target>\n </trans-unit>\n <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">\n <source>This target has modified advanced settings.</source>\n <target>\u3053\u306e\u30bf\u30fc\u30b2\u30c3\u30c8\u306e\u8a73\u7d30\u8a2d\u5b9a\u306f\u5909\u66f4\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">\n <source>Portals</source>\n <target>\u30dd\u30fc\u30bf\u30eb</target>\n </trans-unit>\n <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">\n <source>At least \n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.\n </source>\n <target>\u5c11\u306a\u304f\u3068\u3082\n <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/>\u53f0\u306e\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u304c\u5fc5\u8981\u3067\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">\n <source>Add portal</source>\n <target>\u30dd\u30fc\u30bf\u30eb\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">\n <source>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </source>\n <target>Backstore: \n <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>.\xa0\n </target>\n </trans-unit>\n <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">\n <source>This image has modified settings.</source>\n <target>\u3053\u306e\u30a4\u30e1\u30fc\u30b8\u306e\u8a2d\u5b9a\u306f\u5909\u66f4\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">\n <source>Duplicated LUN numbers.</source>\n <target>Duplicated LUN numbers.</target>\n </trans-unit>\n <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">\n <source>Duplicated WWN.</source>\n <target>Duplicated WWN.</target>\n </trans-unit>\n <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">\n <source>Add image</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">\n <source>ACL authentication</source>\n <target>ACL\u8a8d\u8a3c</target>\n </trans-unit>\n <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</target>\n </trans-unit>\n <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">\n <source>Initiators</source>\n <target>\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf</target>\n </trans-unit>\n <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">\n <source>Initiator</source>\n <target>\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf</target>\n </trans-unit>\n <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">\n <source>Client IQN</source>\n <target>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8IQN</target>\n </trans-unit>\n <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">\n <source>Initiator IQN needs to be unique.</source>\n <target>\u30a4\u30cb\u30b7\u30a8\u30fc\u30bfIQN\u306f\u4e00\u610f\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">\n <source>Usernames must have a length of 8 to 64 characters and\n can only contain letters, \'.\', \'@\', \'-\', \'_\' or \':\'.</source>\n <target>\u30e6\u30fc\u30b6\u540d\u306f8\uff5e64\u6587\u5b57\u306e\u9577\u3055\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u3001\n\u82f1\u5b57\u3001\u300c.\u300d\u3001\u300c@\u300d\u3001\u300c-\u300d\u3001\u300c_\u300d\u3001\u307e\u305f\u306f\u300c:\u300d\u306e\u307f\u3067\u69cb\u6210\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters\n and can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">\n <source>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</source>\n <target>Passwords must have a length of 12 to 16 characters and\n can only contain letters, \'@\', \'-\', \'_\' or \'/\'.</target>\n </trans-unit>\n <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">\n <source>Initiator belongs to a group. Images will be configure in the group.</source>\n <target>\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf\u306f\u3044\u305a\u308c\u304b\u306e\u30b0\u30eb\u30fc\u30d7\u306b\u5c5e\u3057\u307e\u3059\u3002\u30a4\u30e1\u30fc\u30b8\u306f\u305d\u306e\u30b0\u30eb\u30fc\u30d7\u5185\u3067\u8a2d\u5b9a\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">\n <source>No items added.</source>\n <target>\u30a2\u30a4\u30c6\u30e0\u304c\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">\n <source>Add initiator</source>\n <target>\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">\n <source>Groups</source>\n <target>\u30b0\u30eb\u30fc\u30d7</target>\n </trans-unit>\n <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">\n <source>Group</source>\n <target>\u30b0\u30eb\u30fc\u30d7</target>\n </trans-unit>\n <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">\n <source>Add group</source>\n <target>\u30b0\u30eb\u30fc\u30d7\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">\n <source>[object Object]</source>\n <target>[object Object]</target>\n </trans-unit>\n <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">\n <source>RBD Configuration</source>\n <target>RBD\u8a2d\u5b9a</target>\n </trans-unit>\n <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">\n <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>\n <target>\u30ed\u30fc\u30ab\u30eb\u8a2d\u5b9a\u5024\u3092\u524a\u9664\u3057\u307e\u3059\u3002\u89aa\u8a2d\u5b9a\u5024\u304c\u7d99\u627f\u3055\u308c\u3066\u4ee3\u308f\u308a\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">\n <source>The mininum value is 0</source>\n <target>\u6700\u5c0f\u5024\u306f0\u3067\u3059</target>\n </trans-unit>\n <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">\n <source>Issues</source>\n <target>\u554f\u984c</target>\n </trans-unit>\n <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">\n <source>Syncing</source>\n <target>\u540c\u671f\u4e2d</target>\n </trans-unit>\n <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">\n <source>Ready</source>\n <target>\u6e96\u5099\u5b8c\u4e86</target>\n </trans-unit>\n <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">\n <source>Edit pool mirror mode</source>\n <target>\u30d7\u30fc\u30eb\u306e\u30df\u30e9\u30fc\u30e2\u30fc\u30c9\u306e\u7de8\u96c6</target>\n </trans-unit>\n <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">\n <source>To edit the mirror mode for pool\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click\xa0\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\u30d7\u30fc\u30eb\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u306e\u30df\u30e9\u30fc\u30e2\u30fc\u30c9\u3092\u7de8\u96c6\u3059\u308b\u306b\u306f\u3001\n\u30ea\u30b9\u30c8\u304b\u3089\u65b0\u3057\u3044\u30e2\u30fc\u30c9\u3092\u9078\u629e\u3057\u3066\u3001\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\uff3b\u66f4\u65b0\uff3d\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">\n <source>Mode</source>\n <target>\u30e2\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">\n <source>Peer clusters must be removed prior to disabling mirror.</source>\n <target>\u30df\u30e9\u30fc\u3092\u7121\u52b9\u306b\u3059\u308b\u524d\u306b\u3001\u30d4\u30a2\u30af\u30e9\u30b9\u30bf\u3092\u524a\u9664\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n pool mirror peer\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\n\u30d7\u30fc\u30eb\u306e\u30df\u30e9\u30fc\u30d4\u30a2\n </target>\n </trans-unit>\n <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">\n <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>\n <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>\n </trans-unit>\n <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">\n <source>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool\n mirror peer attributes for pool \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click \n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.\n </source>\n <target>\n <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>\u30d7\u30fc\u30eb\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\n <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\n\u306e\u30d7\u30fc\u30eb\u30df\u30e9\u30fc\u30d4\u30a2\u5c5e\u6027\u3001\u304a\u3088\u3073\n <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>\uff3b\u9001\u4fe1\uff3d\n <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">\n <source>Cluster Name</source>\n <target>\u30af\u30e9\u30b9\u30bf\u540d</target>\n </trans-unit>\n <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">\n <source>The cluster name is not valid.</source>\n <target>\u3053\u306e\u30af\u30e9\u30b9\u30bf\u540d\u306f\u7121\u52b9\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">\n <source>CephX ID</source>\n <target>CephX ID</target>\n </trans-unit>\n <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">\n <source>CephX ID...</source>\n <target>CephX ID...</target>\n </trans-unit>\n <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">\n <source>The CephX ID is not valid.</source>\n <target>\u3053\u306eCephX ID\u306f\u7121\u52b9\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">\n <source>Monitor Addresses</source>\n <target>\u30e2\u30cb\u30bf\u30fc\u30a2\u30c9\u30ec\u30b9</target>\n </trans-unit>\n <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">\n <source>Comma-delimited addresses...</source>\n <target>\u30ab\u30f3\u30de\u533a\u5207\u308a\u30a2\u30c9\u30ec\u30b9...</target>\n </trans-unit>\n <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">\n <source>The monitory address is not valid.</source>\n <target>\u3053\u306e\u8b66\u544a\u30a2\u30c9\u30ec\u30b9\u306f\u7121\u52b9\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">\n <source>CephX Key</source>\n <target>CephX\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">\n <source>Base64-encoded key...</source>\n <target>Base64\u30a8\u30f3\u30b3\u30fc\u30c9\u5316\u6e08\u307f\u30ad\u30fc...</target>\n </trans-unit>\n <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">\n <source>CephX key must be base64 encoded.</source>\n <target>CephX\u30ad\u30fc\u306fbase64\u3067\u30a8\u30f3\u30b3\u30fc\u30c9\u3055\u308c\u3066\u3044\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">\n <source>Pools List</source>\n <target>\u30d7\u30fc\u30eb\u30ea\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">\n <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>\n <target>\u540d\u524d\u306f\u82f1\u6570\u5b57\u3001\u30c0\u30c3\u30b7\u30e5\u3001\u304a\u3088\u3073\u4e0b\u7dda\u306e\u307f\u3067\u69cb\u6210\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">\n <source>The chosen erasure code profile name is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305f\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u540d\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">\n <source>Plugin</source>\n <target>\u30d7\u30e9\u30b0\u30a4\u30f3</target>\n </trans-unit>\n <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">\n <source>Data chunks (k)</source>\n <target>\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30af(k)</target>\n </trans-unit>\n <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">\n <source>Must be equal to or greater than 2.</source>\n <target>2\u4ee5\u4e0a\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">\n <source>Coding chunks (m)</source>\n <target>\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30c1\u30e3\u30f3\u30af(m)</target>\n </trans-unit>\n <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">\n <source>Must be equal to or greater than 1.</source>\n <target>1\u4ee5\u4e0a\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">\n <source>Durability estimator (c)</source>\n <target>\u8010\u4e45\u6027\u63a8\u5b9a\u5b50(c)</target>\n </trans-unit>\n <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">\n <source>Locality (l)</source>\n <target>\u5730\u57df(l)</target>\n </trans-unit>\n <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">\n <source>Crush failure domain</source>\n <target>Crush\u969c\u5bb3\u30c9\u30e1\u30a4\u30f3</target>\n </trans-unit>\n <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">\n <source>Crush Locality</source>\n <target>Crush\u5730\u57df</target>\n </trans-unit>\n <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">\n <source>None</source>\n <target>\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">\n <source>Technique</source>\n <target>\u6280\u6cd5</target>\n </trans-unit>\n <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">\n <source>Packetsize</source>\n <target>\u30d1\u30b1\u30c3\u30c8\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">\n <source>Crush root</source>\n <target>Crush\u30eb\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">\n <source>Crush device class</source>\n <target>Crush\u30c7\u30d0\u30a4\u30b9\u30af\u30e9\u30b9</target>\n </trans-unit>\n <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">\n <source>any</source>\n <target>\u4efb\u610f</target>\n </trans-unit>\n <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">\n <source>Directory</source>\n <target>\u30c7\u30a3\u30ec\u30af\u30c8\u30ea</target>\n </trans-unit>\n <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">\n <source>The chosen Ceph pool name is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305fCeph\u30d7\u30fc\u30eb\u540d\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">\n <source>Pool type</source>\n <target>\u30d7\u30fc\u30eb\u30bf\u30a4\u30d7</target>\n </trans-unit>\n <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">\n <source>-- Select a pool type --</source>\n <target>-- \u30d7\u30fc\u30eb\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">\n <source>Placement groups</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7</target>\n </trans-unit>\n <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">\n <source>At least one placement group is needed!</source>\n <target>\u5c11\u306a\u304f\u3068\u30821\u3064\u306e\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u304c\u5fc5\u8981\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">\n <source>Your cluster can\'t handle this many PGs. Please recalculate the PG amount needed.</source>\n <target>\u3054\u4f7f\u7528\u306e\u30af\u30e9\u30b9\u30bf\u306f\u3053\u308c\u3060\u3051\u591a\u6570\u306e\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u3092\u51e6\u7406\u3067\u304d\u307e\u305b\u3093\u3002\u5fc5\u8981\u306a\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u306e\u6570\u3092\u518d\u8a08\u7b97\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">\n <source>Calculation help</source>\n <target>\u8a08\u7b97\u306e\u30d8\u30eb\u30d7</target>\n </trans-unit>\n <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">\n <source>The current PGs settings were calculated for you, you\n should make sure the values suit your needs before submit.</source>\n <target>\u73fe\u5728\u306e\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u8a2d\u5b9a\u306f\u81ea\u52d5\u7684\u306b\u8a08\u7b97\u3055\u308c\u305f\u305f\u3081\u3001\n\u9001\u4fe1\u524d\u306b\u3001\u3053\u308c\u3089\u306e\u5024\u304c\u30cb\u30fc\u30ba\u306b\u5408\u3063\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">\n <source>Crush ruleset</source>\n <target>Crush\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">\n <source>-- Select a crush rule --</source>\n <target>-- Crush\u30eb\u30fc\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">\n <source>Crush rule</source>\n <target>Crush\u30eb\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">\n <source>Crush steps</source>\n <target>Crush\u30b9\u30c6\u30c3\u30d7</target>\n </trans-unit>\n <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">\n <source>The rule can\'t be used in the current cluster as it has\n to few OSDs to meet the minimum required OSD by this rule.</source>\n <target>\u73fe\u5728\u306e\u30af\u30e9\u30b9\u30bf\u5185\u306eOSD\u6570\u306f\u3053\u306e\u30eb\u30fc\u30eb\u3067\u8981\u6c42\u3055\u308c\u308b\u6700\u5c0fOSD\u6570\u3092\u4e0b\u56de\u3063\u3066\u3044\u308b\u305f\u3081\u3001\n\u3053\u306e\u30eb\u30fc\u30eb\u3092\u73fe\u5728\u306e\u30af\u30e9\u30b9\u30bf\u3067\u4f7f\u7528\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">\n <source>Replicated size</source>\n <target>\u8907\u88fd\u3055\u308c\u305f\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">\n <source>Minimum: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </source>\n <target>\u6700\u5c0f: \n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">\n <source>Maximum: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </source>\n <target>\u6700\u5927: \n <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>\n </target>\n </trans-unit>\n <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">\n <source>The size specified is out of range. A value from\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to \n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.\n </source>\n <target>\u6307\u5b9a\u3055\u308c\u305f\u30b5\u30a4\u30ba\u306f\u7bc4\u56f2\u5916\u3067\u3059\u3002\n\u6709\u52b9\u306a\u5024\u306e\u7bc4\u56f2\u306f\n <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>\uff5e\n <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>\u3067\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">\n <source>Erasure code profile</source>\n <target>\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb</target>\n </trans-unit>\n <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">\n <source>-- No erasure code profile available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">\n <source>-- Select an erasure code profile --</source>\n <target>-- \u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">\n <source>EC Overwrites</source>\n <target>EC\u306e\u4e0a\u66f8\u304d</target>\n </trans-unit>\n <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">\n <source>Applications</source>\n <target>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3</target>\n </trans-unit>\n <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">\n <source>Compression</source>\n <target>\u5727\u7e2e</target>\n </trans-unit>\n <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">\n <source>Algorithm</source>\n <target>\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0</target>\n </trans-unit>\n <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">\n <source>-- No erasure compression algorithm available --</source>\n <target>-- \u4f7f\u7528\u53ef\u80fd\u306a\u30a4\u30ec\u30a4\u30b8\u30e3\u5727\u7e2e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u304c\u3042\u308a\u307e\u305b\u3093 --</target>\n </trans-unit>\n <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">\n <source>Minimum blob size</source>\n <target>\u6700\u5c0fblob\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">\n <source>e.g., 128KiB</source>\n <target>\u4f8b: 128KiB</target>\n </trans-unit>\n <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">\n <source>Value should be greater than 0</source>\n <target>\u5024\u306f0\u3088\u308a\u5927\u304d\u3044\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">\n <source>Value should be less than the maximum blob size</source>\n <target>Value should be less than the maximum blob size</target>\n </trans-unit>\n <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">\n <source>Maximum blob size</source>\n <target>\u6700\u5927blob\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">\n <source>e.g., 512KiB</source>\n <target>\u4f8b: 512KiB</target>\n </trans-unit>\n <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">\n <source>Value should be greater than the minimum blob size</source>\n <target>\u5024\u306f\u6700\u5c0fblob\u30b5\u30a4\u30ba\u3088\u308a\u5927\u304d\u3044\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">\n <source>Ratio</source>\n <target>\u7387</target>\n </trans-unit>\n <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">\n <source>Compression ratio</source>\n <target>\u5727\u7e2e\u7387</target>\n </trans-unit>\n <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">\n <source>Value should be between 0.0 and 1.0</source>\n <target>\u5024\u306f0.0\uff5e1.0\u306e\u9593\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">\n <source>It\'s not possible to create an RBD pool with \'/\' in the name.</source>\n <target>\u540d\u524d\u306b\u300c/\u300d\u304c\u542b\u307e\u308c\u305fRBD\u30d7\u30fc\u30eb\u3092\u4f5c\u6210\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">\n <source>Please change the name or remove \'rbd\' from the applications list.</source>\n <target>\u540d\u524d\u3092\u5909\u66f4\u3059\u308b\u304b\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30ea\u30b9\u30c8\u304b\u3089\u300crbd\u300d\u3092\u524a\u9664\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">\n <source>Cache Tiers Details</source>\n <target>\u30ad\u30e3\u30c3\u30b7\u30e5\u5c64\u306e\u8a73\u7d30</target>\n </trans-unit>\n <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">\n <source>Please consult the \n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\n on how to configure and enable the Object Gateway management functionality.\n </source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u306e\u7ba1\u7406\u6a5f\u80fd\u3092\u8a2d\u5b9a\u304a\u3088\u3073\u6709\u52b9\u5316\n\u3059\u308b\u65b9\u6cd5\u306b\u95a2\u3059\u308b\n <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\n <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n </target>\n </trans-unit>\n <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">\n <source>Daemons List</source>\n <target>\u30c7\u30fc\u30e2\u30f3\u30ea\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">\n <source>Performance Counters</source>\n <target>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30ab\u30a6\u30f3\u30bf</target>\n </trans-unit>\n <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">\n <source>Loading bucket data...</source>\n <target>\u30d0\u30b1\u30c3\u30c8\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059...</target>\n </trans-unit>\n <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">\n <source>The bucket data could not be loaded.</source>\n <target>\u30d0\u30b1\u30c3\u30c8\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">\n <source>Id</source>\n <target>Id</target>\n </trans-unit>\n <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">\n <source>The value is not valid.</source>\n <target>\u3053\u306e\u5024\u306f\u7121\u52b9\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">\n <source>Owner</source>\n <target>\u6240\u6709\u8005</target>\n </trans-unit>\n <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">\n <source>-- Select a user --</source>\n <target>-- \u30e6\u30fc\u30b6\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">\n <source>ID</source>\n <target>ID</target>\n </trans-unit>\n <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">\n <source>Index type</source>\n <target>\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30bf\u30a4\u30d7</target>\n </trans-unit>\n <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">\n <source>Placement rule</source>\n <target>\u914d\u7f6e\u30eb\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">\n <source>Marker</source>\n <target>\u30de\u30fc\u30ab\u30fc</target>\n </trans-unit>\n <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">\n <source>Maximum marker</source>\n <target>\u6700\u5927\u30de\u30fc\u30ab\u30fc</target>\n </trans-unit>\n <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">\n <source>Version</source>\n <target>\u30d0\u30fc\u30b8\u30e7\u30f3</target>\n </trans-unit>\n <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">\n <source>Master version</source>\n <target>\u30de\u30b9\u30bf\u30d0\u30fc\u30b8\u30e7\u30f3</target>\n </trans-unit>\n <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">\n <source>Modification time</source>\n <target>\u5909\u66f4\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">\n <source>Zonegroup</source>\n <target>\u30be\u30fc\u30f3\u30b0\u30eb\u30fc\u30d7</target>\n </trans-unit>\n <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">\n <source>Bucket quota</source>\n <target>\u30d0\u30b1\u30c3\u30c8\u30af\u30a9\u30fc\u30bf</target>\n </trans-unit>\n <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">\n <source>Enabled</source>\n <target>\u6709\u52b9\u5316\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">\n <source>Maximum size</source>\n <target>\u6700\u5927\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">\n <source>Unlimited</source>\n <target>\u7121\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">\n <source>Maximum objects</source>\n <target>\u6700\u5927\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">\n <source>-- Select a username --</source>\n <target>-- \u30e6\u30fc\u30b6\u540d\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">\n <source>Auto-generate key</source>\n <target>\u30ad\u30fc\u306e\u81ea\u52d5\u751f\u6210</target>\n </trans-unit>\n <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">\n <source>Access key</source>\n <target>\u30a2\u30af\u30bb\u30b9\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">\n <source>Secret key</source>\n <target>\u79d8\u5bc6\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">\n <source>Email address</source>\n <target>\u96fb\u5b50\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9</target>\n </trans-unit>\n <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">\n <source>Suspended</source>\n <target>\u4e2d\u65ad\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">\n <source>System</source>\n <target>\u30b7\u30b9\u30c6\u30e0</target>\n </trans-unit>\n <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">\n <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>\n <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>\n </trans-unit>\n <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">\n <source>Maximum buckets</source>\n <target>\u6700\u5927\u30d0\u30b1\u30c3\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">\n <source>Subusers</source>\n <target>\u30b5\u30d6\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">\n <source>Capabilities</source>\n <target>\u6a5f\u80fd</target>\n </trans-unit>\n <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">\n <source>User quota</source>\n <target>\u30e6\u30fc\u30b6\u30af\u30a9\u30fc\u30bf</target>\n </trans-unit>\n <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">\n <source>Show</source>\n <target>\u8868\u793a</target>\n </trans-unit>\n <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">\n <source>Keys</source>\n <target>\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">\n <source>-- Select a type --</source>\n <target>-- \u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">\n <source>Permission</source>\n <target>\u8a31\u53ef</target>\n </trans-unit>\n <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">\n <source>-- Select a permission --</source>\n <target>-- \u8a31\u53ef\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">\n <source>Subuser</source>\n <target>\u30b5\u30d6\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">\n <source>The chosen subuser ID is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305f\u30b5\u30d6\u30e6\u30fc\u30b6ID\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">\n <source>read, write</source>\n <target>\u8aad\u307f\u53d6\u308a\u3001\u66f8\u304d\u8fbc\u307f</target>\n </trans-unit>\n <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">\n <source>full</source>\n <target>\u30d5\u30eb</target>\n </trans-unit>\n <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">\n <source>Swift key</source>\n <target>\u30b9\u30a6\u30a3\u30d5\u30c8\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">\n <source>Auto-generate secret</source>\n <target>\u79d8\u5bc6\u306e\u81ea\u52d5\u751f\u6210</target>\n </trans-unit>\n <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">\n <source>Loading user data...</source>\n <target>\u30e6\u30fc\u30b6\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059...</target>\n </trans-unit>\n <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">\n <source>The user data could not be loaded.</source>\n <target>\u30e6\u30fc\u30b6\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">\n <source>The chosen user ID is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305f\u30e6\u30fc\u30b6ID\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">\n <source>This is not a valid email address.</source>\n <target>\u3053\u308c\u306f\u6709\u52b9\u306a\u96fb\u5b50\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">\n <source>The chosen email address is already in use.</source>\n <target>\u9078\u629e\u3055\u308c\u305f\u96fb\u5b50\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">\n <source>Max. buckets</source>\n <target>\u6700\u5927\u30d0\u30b1\u30c3\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">\n <source>The entered value must be &gt;= 0.</source>\n <target>0\u4ee5\u4e0a\u306e\u5024\u3092\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">\n <source>S3 key</source>\n <target>S3\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">\n <source>There are no subusers.</source>\n <target>\u30b5\u30d6\u30e6\u30fc\u30b6\u304c\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">\n <source>S3</source>\n <target>S3</target>\n </trans-unit>\n <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">\n <source>There are no keys.</source>\n <target>\u30ad\u30fc\u304c\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">\n <source>Swift</source>\n <target>\u30b9\u30a6\u30a3\u30d5\u30c8</target>\n </trans-unit>\n <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">\n <source>There are no capabilities.</source>\n <target>\u6a5f\u80fd\u304c\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>\n <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>\n </target>\n </trans-unit>\n <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">\n <source>Unlimited size</source>\n <target>\u7121\u5236\u9650\u306e\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">\n <source>Max. size</source>\n <target>\u6700\u5927\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">\n <source>Unlimited objects</source>\n <target>\u7121\u5236\u9650\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">\n <source>Max. objects</source>\n <target>\u6700\u5927\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">\n <source>Current</source>\n <target>\u73fe\u5728</target>\n </trans-unit>\n <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">\n <source>Updated discovery authentication</source>\n <target>\u691c\u51fa\u8a8d\u8a3c\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">\n <source>There are no portals available.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30dd\u30fc\u30bf\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">\n <source>There are no images available.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30a4\u30e1\u30fc\u30b8\u306f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">\n <source>There are no images available. Please make sure you add an image to the target.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30a4\u30e1\u30fc\u30b8\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30bf\u30fc\u30b2\u30c3\u30c8\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u305f\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">\n <source>There are no initiators available. Please make sure you add an initiator to the target.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30bf\u30fc\u30b2\u30c3\u30c8\u306b\u30a4\u30cb\u30b7\u30a8\u30fc\u30bf\u3092\u8ffd\u52a0\u3057\u305f\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002</target>\n </trans-unit>\n <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">\n <source>target</source>\n <target>target</target>\n </trans-unit>\n <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">\n <source>Target</source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">\n <source># Sessions</source>\n <target># Sessions</target>\n </trans-unit>\n <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">\n <source>iSCSI target</source>\n <target>iSCSI target</target>\n </trans-unit>\n <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">\n <source>State</source>\n <target>\u72b6\u614b</target>\n </trans-unit>\n <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">\n <source># Targets</source>\n <target># Targets</target>\n </trans-unit>\n <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">\n <source>Read Bytes</source>\n <target>\u8aad\u307f\u53d6\u308a\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">\n <source>Write Bytes</source>\n <target>\u66f8\u304d\u8fbc\u307f\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">\n <source>Read Ops</source>\n <target>\u8aad\u307f\u53d6\u308a\u64cd\u4f5c\u6570</target>\n </trans-unit>\n <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">\n <source>Write Ops</source>\n <target>\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u6570</target>\n </trans-unit>\n <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">\n <source>A/O Since</source>\n <target>\u6b21\u306e\u65e5\u4ed8\u4ee5\u964d\u306eA/O</target>\n </trans-unit>\n <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">\n <source>Instance</source>\n <target>\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9</target>\n </trans-unit>\n <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">\n <source>Hostname</source>\n <target>\u30db\u30b9\u30c8\u540d</target>\n </trans-unit>\n <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">\n <source>Issue</source>\n <target>\u554f\u984c</target>\n </trans-unit>\n <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">\n <source>Progress</source>\n <target>\u9032\u6357</target>\n </trans-unit>\n <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">\n <source>Disabled</source>\n <target>\u7121\u52b9\u5316\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">\n <source>Edit Mode</source>\n <target>\u30e2\u30fc\u30c9\u306e\u7de8\u96c6</target>\n </trans-unit>\n <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">\n <source>Add Peer</source>\n <target>\u30d4\u30a2\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">\n <source>Edit Peer</source>\n <target>\u30d4\u30a2\u306e\u7de8\u96c6</target>\n </trans-unit>\n <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">\n <source>Delete Peer</source>\n <target>\u30d4\u30a2\u306e\u524a\u9664</target>\n </trans-unit>\n <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">\n <source>Leader</source>\n <target>\u30ea\u30fc\u30c0\u30fc</target>\n </trans-unit>\n <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">\n <source># Local</source>\n <target>#\u30ed\u30fc\u30ab\u30eb</target>\n </trans-unit>\n <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">\n <source># Remote</source>\n <target>#\u30ea\u30e2\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">\n <source>mirror peer</source>\n <target>\u30df\u30e9\u30fc\u30d4\u30a2</target>\n </trans-unit>\n <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">\n <source>Key</source>\n <target>\u30ad\u30fc</target>\n </trans-unit>\n <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">\n <source>RBD</source>\n <target>RBD</target>\n </trans-unit>\n <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">\n <source>Deep flatten</source>\n <target>\u30c7\u30a3\u30fc\u30d7\u30d5\u30e9\u30c3\u30c8\u5316</target>\n </trans-unit>\n <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">\n <source>Layering</source>\n <target>\u968e\u5c64\u5316</target>\n </trans-unit>\n <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">\n <source>Exclusive lock</source>\n <target>\u6392\u4ed6\u30ed\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">\n <source>Object map (requires exclusive-lock)</source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30de\u30c3\u30d7(\u6392\u4ed6\u30ed\u30c3\u30af\u304c\u5fc5\u8981)</target>\n </trans-unit>\n <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">\n <source>Journaling (requires exclusive-lock)</source>\n <target>\u30b8\u30e3\u30fc\u30ca\u30ea\u30f3\u30b0(\u6392\u4ed6\u30ed\u30c3\u30af\u304c\u5fc5\u8981)</target>\n </trans-unit>\n <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">\n <source>Fast diff (interlocked with object-map)</source>\n <target>Fast diff (interlocked with object-map)</target>\n </trans-unit>\n <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">\n <source>RBD snapshot rollback</source>\n <target>RBD\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306e\u30ed\u30fc\u30eb\u30d0\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">\n <source>Rollback</source>\n <target>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">\n <source>RBD snapshot</source>\n <target>RBD\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">\n <source>Deleted At</source>\n <target>\u524a\u9664\u65e5\u6642</target>\n </trans-unit>\n <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">\n <source>id</source>\n <target>id</target>\n </trans-unit>\n <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">\n <source>type</source>\n <target>\u30bf\u30a4\u30d7</target>\n </trans-unit>\n <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">\n <source>state</source>\n <target>\u72b6\u614b</target>\n </trans-unit>\n <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">\n <source>version</source>\n <target>\u30d0\u30fc\u30b8\u30e7\u30f3</target>\n </trans-unit>\n <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">\n <source>Host</source>\n <target>\u30db\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">\n <source>root</source>\n <target>\u30eb\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">\n <source>Rank</source>\n <target>\u30e9\u30f3\u30af</target>\n </trans-unit>\n <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">\n <source>Daemon</source>\n <target>\u30c7\u30fc\u30e2\u30f3</target>\n </trans-unit>\n <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">\n <source>Activity</source>\n <target>\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3</target>\n </trans-unit>\n <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">\n <source>Dentries</source>\n <target>d\u30a8\u30f3\u30c8\u30ea</target>\n </trans-unit>\n <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">\n <source>Inodes</source>\n <target>i\u30ce\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">\n <source>Usage</source>\n <target>\u4f7f\u7528\u91cf</target>\n </trans-unit>\n <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">\n <source>Standby daemons</source>\n <target>\u30b9\u30bf\u30f3\u30d0\u30a4\u30c7\u30fc\u30e2\u30f3</target>\n </trans-unit>\n <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">\n <source>The value can be updated at runtime.</source>\n <target>\u3053\u306e\u5024\u306f\u5b9f\u884c\u6642\u306b\u66f4\u65b0\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">\n <source>Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via \'ceph config\n set ...\'. This option should be configured via ceph.conf or via the\n command line.</source>\n <target>\u30c7\u30fc\u30e2\u30f3/\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u3053\u306e\u5024\u3092\u30e2\u30cb\u30bf\u30fc\u8a2d\u5b9a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u53d6\u5f97\u3057\u307e\u305b\u3093\u3002\n\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u300cceph config set ...\u300d\u3092\u901a\u3058\u3066\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u306f\u7981\u6b62\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3001ceph.conf\u307e\u305f\u306f\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u3092\u901a\u3058\u3066\n\u8a2d\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">\n <source>Option takes effect only during daemon startup.</source>\n <target>\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u30c7\u30fc\u30e2\u30f3\u59cb\u52d5\u6642\u306e\u307f\u306b\u6709\u52b9\u306b\u306a\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">\n <source>Option only affects cluster creation.</source>\n <target>\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u30af\u30e9\u30b9\u30bf\u306e\u4f5c\u6210\u306e\u307f\u306b\u9069\u7528\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">\n <source>Option only affects daemon creation.</source>\n <target>\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u30c7\u30fc\u30e2\u30f3\u306e\u4f5c\u6210\u306e\u307f\u306b\u9069\u7528\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">\n <source>Updated config option \n <x id="INTERPOLATION" equiv-text="{{name}}"/>\n </source>\n <target>\u8a2d\u5b9a\u30aa\u30d7\u30b7\u30e7\u30f3\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">\n <source>Service</source>\n <target>\u30b5\u30fc\u30d3\u30b9</target>\n </trans-unit>\n <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">\n <source>Current value</source>\n <target>\u73fe\u884c\u5024</target>\n </trans-unit>\n <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">\n <source>Editable</source>\n <target>\u7de8\u96c6\u53ef\u80fd</target>\n </trans-unit>\n <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">\n <source>Updated options for module "\n <x id="INTERPOLATION" equiv-text="{{name}}"/>".\n </source>\n <target>\u30e2\u30b8\u30e5\u30fc\u30eb\u300c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u300d\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n </target>\n </trans-unit>\n <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">\n <source>Enable</source>\n <target>\u6709\u52b9\u5316</target>\n </trans-unit>\n <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">\n <source>Disable</source>\n <target>\u7121\u52b9\u5316</target>\n </trans-unit>\n <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">\n <source>Reconnecting, please wait ...</source>\n <target>\u518d\u63a5\u7d9a\u3057\u3066\u3044\u307e\u3059\u306e\u3067\u3001\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044...</target>\n </trans-unit>\n <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">\n <source>Public Address</source>\n <target>\u30d1\u30d6\u30ea\u30c3\u30af\u30a2\u30c9\u30ec\u30b9</target>\n </trans-unit>\n <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">\n <source>Open Sessions</source>\n <target>\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u958b\u59cb</target>\n </trans-unit>\n <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">\n <source>No In</source>\n <target>\u30a4\u30f3\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">\n <source>OSDs that were previously marked out will not be marked back in when they start</source>\n <target>\u4ee5\u524d\u306b\u30a2\u30a6\u30c8\u3068\u3057\u3066\u30de\u30fc\u30af\u3055\u308c\u305fOSD\u306f\u3001\u305d\u308c\u3089\u306e\u59cb\u52d5\u6642\u306b\u30a4\u30f3\u3068\u3057\u3066\u30de\u30fc\u30af\u3055\u308c\u308b\u3053\u3068\u306f\u3042\u308a\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">\n <source>No Out</source>\n <target>\u30a2\u30a6\u30c8\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">\n <source>OSDs will not automatically be marked out after the configured interval</source>\n <target>OSD\u306f\u3001\u8a2d\u5b9a\u6e08\u307f\u306e\u9593\u9694\u304c\u7d4c\u904e\u3057\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30a2\u30a6\u30c8\u3068\u3057\u3066\u30de\u30fc\u30af\u3055\u308c\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">\n <source>No Up</source>\n <target>\u30a2\u30c3\u30d7\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">\n <source>OSDs are not allowed to start</source>\n <target>OSD\u3092\u59cb\u52d5\u3059\u308b\u3053\u3068\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">\n <source>No Down</source>\n <target>\u30c0\u30a6\u30f3\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">\n <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>\n <target>OSD\u306e\u969c\u5bb3\u30ec\u30dd\u30fc\u30c8\u306f\u7121\u8996\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001OSD\u306f\u30e2\u30cb\u30bf\u30fc\u306b\u3088\u3063\u3066\u30c0\u30a6\u30f3\u3068\u3057\u3066\u30de\u30fc\u30af\u3055\u308c\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">\n <source>Pause</source>\n <target>\u4e00\u6642\u505c\u6b62</target>\n </trans-unit>\n <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">\n <source>Pauses reads and writes</source>\n <target>\u8aad\u307f\u53d6\u308a\u3068\u66f8\u304d\u8fbc\u307f\u3092\u4e00\u6642\u505c\u6b62\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">\n <source>No Scrub</source>\n <target>\u30b9\u30af\u30e9\u30d6\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">\n <source>Scrubbing is disabled</source>\n <target>\u30b9\u30af\u30e9\u30d6\u51e6\u7406\u306f\u7121\u52b9\u5316\u3055\u308c\u3066\u3044\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">\n <source>No Deep Scrub</source>\n <target>\u30c7\u30a3\u30fc\u30d7\u30b9\u30af\u30e9\u30d6\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">\n <source>Deep Scrubbing is disabled</source>\n <target>\u30c7\u30a3\u30fc\u30d7\u30b9\u30af\u30e9\u30d6\u51e6\u7406\u306f\u7121\u52b9\u5316\u3055\u308c\u3066\u3044\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">\n <source>No Backfill</source>\n <target>\u30d0\u30c3\u30af\u30d5\u30a3\u30eb\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">\n <source>Backfilling of PGs is suspended</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u306e\u30d0\u30c3\u30af\u30d5\u30a3\u30eb\u306f\u4e2d\u65ad\u3055\u308c\u3066\u3044\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">\n <source>No Recover</source>\n <target>\u56de\u5fa9\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">\n <source>Recovery of PGs is suspended</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u306e\u56de\u5fa9\u306f\u4e2d\u65ad\u3055\u308c\u3066\u3044\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">\n <source>Bitwise Sort</source>\n <target>\u30d3\u30c3\u30c8\u5358\u4f4d\u306e\u30bd\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">\n <source>Use bitwise sort</source>\n <target>\u30d3\u30c3\u30c8\u5358\u4f4d\u306e\u30bd\u30fc\u30c8\u3092\u4f7f\u7528\u3059\u308b</target>\n </trans-unit>\n <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">\n <source>Purged Snapdirs</source>\n <target>\u6d88\u53bb\u3055\u308c\u305f\u30b9\u30ca\u30c3\u30d7\u30c7\u30a3\u30ec\u30af\u30c8\u30ea</target>\n </trans-unit>\n <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">\n <source>OSDs have converted snapsets</source>\n <target>OSD\u306b\u3088\u3063\u3066\u30b9\u30ca\u30c3\u30d7\u30bb\u30c3\u30c8\u304c\u5909\u63db\u3055\u308c\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">\n <source>Recovery Deletes</source>\n <target>\u56de\u5fa9\u306e\u524a\u9664</target>\n </trans-unit>\n <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">\n <source>Deletes performed during recovery instead of peering</source>\n <target>\u30d4\u30a2\u30ea\u30f3\u30b0\u306e\u4ee3\u308f\u308a\u306b\u56de\u5fa9\u6642\u306b\u524a\u9664\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">\n <source>PG Log Hard Limit</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u30ed\u30b0\u306e\u30cf\u30fc\u30c9\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">\n <source>Puts a hard limit on pg log length</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u30ed\u30b0\u9577\u306e\u30cf\u30fc\u30c9\u5236\u9650\u3092\u9069\u7528\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">\n <source>Updated OSD Flags</source>\n <target>OSD\u30d5\u30e9\u30b0\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">\n <source>out</source>\n <target>\u30a2\u30a6\u30c8</target>\n </trans-unit>\n <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">\n <source>in</source>\n <target>\u30a4\u30f3</target>\n </trans-unit>\n <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">\n <source>down</source>\n <target>\u30c0\u30a6\u30f3</target>\n </trans-unit>\n <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">\n <source>Mark</source>\n <target>\u30de\u30fc\u30af</target>\n </trans-unit>\n <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">\n <source>OSD lost</source>\n <target>\u55aa\u5931\u3057\u305fOSD</target>\n </trans-unit>\n <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">\n <source>marked lost</source>\n <target>\u55aa\u5931\u3068\u3057\u3066\u30de\u30fc\u30af\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">\n <source>Purge</source>\n <target>\u6d88\u53bb</target>\n </trans-unit>\n <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">\n <source>OSD</source>\n <target>OSD</target>\n </trans-unit>\n <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">\n <source>purged</source>\n <target>\u6d88\u53bb\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">\n <source>destroy</source>\n <target>\u7834\u68c4</target>\n </trans-unit>\n <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">\n <source>destroyed</source>\n <target>\u7834\u68c4\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">\n <source>Cluster-wide Flags</source>\n <target>Cluster-wide Flags</target>\n </trans-unit>\n <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">\n <source>Cluster-wide Recovery Priority</source>\n <target>Cluster-wide Recovery Priority</target>\n </trans-unit>\n <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">\n <source>PG scrub</source>\n <target>PG scrub</target>\n </trans-unit>\n <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">\n <source>PGs</source>\n <target>\u914d\u7f6e\u30b0\u30eb\u30fc\u30d7\u6570</target>\n </trans-unit>\n <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">\n <source>Read bytes</source>\n <target>\u8aad\u307f\u53d6\u308a\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">\n <source>Writes bytes</source>\n <target>\u66f8\u304d\u8fbc\u307f\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">\n <source>Read ops</source>\n <target>\u8aad\u307f\u53d6\u308a\u64cd\u4f5c\u6570</target>\n </trans-unit>\n <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">\n <source>Write ops</source>\n <target>\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u6570</target>\n </trans-unit>\n <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">\n <source>Mark OSD \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>OSD\n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\u3092\u30de\u30fc\u30af\n </target>\n </trans-unit>\n <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">\n <source>Mark \n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{markAction}}"/>\u3092\u30de\u30fc\u30af\n </target>\n </trans-unit>\n <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">\n <source>PG scrub options</source>\n <target>PG scrub options</target>\n </trans-unit>\n <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">\n <source>Updated PG scrub options</source>\n <target>Updated PG scrub options</target>\n </trans-unit>\n <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">\n <source>Max Backfills</source>\n <target>\u6700\u5927\u30d0\u30c3\u30af\u30d5\u30a3\u30eb\u6570</target>\n </trans-unit>\n <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">\n <source>Recovery Max Active</source>\n <target>\u56de\u5fa9\u6700\u5927\u30a2\u30af\u30c6\u30a3\u30d6</target>\n </trans-unit>\n <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">\n <source>Recovery Max Single Start</source>\n <target>\u56de\u5fa9\u6700\u5927\u5358\u4e00\u59cb\u52d5</target>\n </trans-unit>\n <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">\n <source>Recovery Sleep</source>\n <target>\u56de\u5fa9\u30b9\u30ea\u30fc\u30d7</target>\n </trans-unit>\n <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">\n <source>Custom</source>\n <target>\u30ab\u30b9\u30bf\u30e0</target>\n </trans-unit>\n <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">\n <source>Updated OSD recovery speed priority "\n <x id="INTERPOLATION" equiv-text="{{value}}"/>"\n </source>\n <target>OSD\u306e\u56de\u5fa9\u901f\u5ea6\u512a\u5148\u5ea6\u300c\n <x id="INTERPOLATION" equiv-text="{{value}}"/>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{operation}}"/>\u306f\u6b21\u306eOSD\u3067\u521d\u671f\u5316\u3055\u308c\u307e\u3057\u305f: \n <x id="INTERPOLATION_1" equiv-text="{{id}}"/>\n </target>\n </trans-unit>\n <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">\n <source>Create silence</source>\n <target>Create silence</target>\n </trans-unit>\n <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">\n <source>Job</source>\n <target>\u30b8\u30e7\u30d6</target>\n </trans-unit>\n <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">\n <source>Severity</source>\n <target>\u91cd\u5927\u5ea6</target>\n </trans-unit>\n <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">\n <source>Started</source>\n <target>\u59cb\u52d5\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">\n <source>URL</source>\n <target>URL</target>\n </trans-unit>\n <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">\n <source>silence</source>\n <target>silence</target>\n </trans-unit>\n <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">\n <source>Attribute name</source>\n <target>Attribute name</target>\n </trans-unit>\n <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">\n <source>Regular expression</source>\n <target>Regular expression</target>\n </trans-unit>\n <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">\n <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>\n <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>\n </trans-unit>\n <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">\n <source>Created by</source>\n <target>Created by</target>\n </trans-unit>\n <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">\n <source>Updated</source>\n <target>\u66f4\u65b0\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">\n <source>Ends</source>\n <target>Ends</target>\n </trans-unit>\n <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">\n <source>Silence</source>\n <target>Silence</target>\n </trans-unit>\n <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">\n <source>Used</source>\n <target>\u4f7f\u7528\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">\n <source>Avail.</source>\n <target>\u4f7f\u7528\u53ef\u80fd</target>\n </trans-unit>\n <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">\n <source>Clean</source>\n <target>\u30af\u30ea\u30fc\u30f3</target>\n </trans-unit>\n <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">\n <source>Working</source>\n <target>\u52d5\u4f5c\u4e2d</target>\n </trans-unit>\n <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">\n <source>Warning</source>\n <target>\u8b66\u544a</target>\n </trans-unit>\n <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">\n <source>Unknown</source>\n <target>\u4e0d\u660e</target>\n </trans-unit>\n <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">\n <source>Healthy</source>\n <target>Healthy</target>\n </trans-unit>\n <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">\n <source>Misplaced</source>\n <target>Misplaced</target>\n </trans-unit>\n <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">\n <source>Degraded</source>\n <target>Degraded</target>\n </trans-unit>\n <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">\n <source>Unfound</source>\n <target>Unfound</target>\n </trans-unit>\n <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">\n <source>replicas</source>\n <target>replicas</target>\n </trans-unit>\n <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">\n <source>up</source>\n <target>\u30a2\u30c3\u30d7</target>\n </trans-unit>\n <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">\n <source>no filesystems</source>\n <target>\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u304c\u3042\u308a\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">\n <source>active</source>\n <target>\u30a2\u30af\u30c6\u30a3\u30d6</target>\n </trans-unit>\n <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">\n <source>standby</source>\n <target>\u30b9\u30bf\u30f3\u30d0\u30a4</target>\n </trans-unit>\n <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">\n <source>n/a</source>\n <target>\u306a\u3057</target>\n </trans-unit>\n <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">\n <source>active daemon</source>\n <target>\u30a2\u30af\u30c6\u30a3\u30d6\u30c7\u30fc\u30e2\u30f3</target>\n </trans-unit>\n <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">\n <source>quorum</source>\n <target>\u5b9a\u6570</target>\n </trans-unit>\n <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">\n <source>The NFS Ganesha service is not configured.</source>\n <target>NFS Ganesha\u30b5\u30fc\u30d3\u30b9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">\n <source>Transport</source>\n <target>\u30c8\u30e9\u30f3\u30b9\u30dd\u30fc\u30c8</target>\n </trans-unit>\n <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">\n <source>CephFS User</source>\n <target>CephFS\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">\n <source>CephFS Filesystem</source>\n <target>CephFS\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0</target>\n </trans-unit>\n <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">\n <source>(inherited from global config)</source>\n <target>(\u30b0\u30ed\u30fc\u30d0\u30eb\u8a2d\u5b9a\u304b\u3089\u7d99\u627f)</target>\n </trans-unit>\n <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">\n <source>inherited from global config</source>\n <target>\u30b0\u30ed\u30fc\u30d0\u30eb\u8a2d\u5b9a\u304b\u3089\u7d99\u627f\u3055\u308c\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">\n <source>-- Select what kind of user id squashing is performed --</source>\n <target>-- \u5b9f\u884c\u3055\u308c\u308b\u30e6\u30fc\u30b6ID\u30b9\u30ab\u30c3\u30b7\u30e5\u64cd\u4f5c\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">\n <source>There are no daemons available.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30c7\u30fc\u30e2\u30f3\u304c\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">\n <source>NFS export</source>\n <target>NFS export</target>\n </trans-unit>\n <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">\n <source>EC Profile</source>\n <target>EC Profile</target>\n </trans-unit>\n <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">\n <source>Cache Mode</source>\n <target>\u30ad\u30e3\u30c3\u30b7\u30e5\u30e2\u30fc\u30c9</target>\n </trans-unit>\n <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">\n <source>Min Evict Age</source>\n <target>\u9000\u53bb\u307e\u3067\u306e\u6700\u5c0f\u7d4c\u904e\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">\n <source>Min Flush Age</source>\n <target>\u6d88\u53bb\u307e\u3067\u306e\u6700\u5c0f\u7d4c\u904e\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">\n <source>Target Max Bytes</source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8\u306e\u6700\u5927\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">\n <source>Target Max Objects</source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8\u306e\u6700\u5927\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">\n <source>No applications added</source>\n <target>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">\n <source>Applications limit reached</source>\n <target>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u6570\u306e\u4e0a\u9650\u306b\u9054\u3057\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">\n <source>A pool can only have up to four applications definitions.</source>\n <target>1\u3064\u306e\u30d7\u30fc\u30eb\u306f\u6700\u5927\u30674\u3064\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5b9a\u7fa9\u3057\u304b\u4fdd\u6709\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">\n <source>Allowed characters \'_a-zA-Z0-9\'</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u6587\u5b57\u300c_a-zA-Z0-9\u300d</target>\n </trans-unit>\n <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">\n <source>Maximum length is 128 characters</source>\n <target>\u6700\u5927\u9577\u306f128\u6587\u5b57\u3067\u3059</target>\n </trans-unit>\n <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">\n <source>Filter or add applications</source>\n <target>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u307e\u305f\u306f\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">\n <source>Add application</source>\n <target>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">\n <source>pool</source>\n <target>pool</target>\n </trans-unit>\n <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">\n <source>erasure code profile</source>\n <target>\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb</target>\n </trans-unit>\n <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">\n <source>Replica Size</source>\n <target>\u30ec\u30d7\u30ea\u30ab\u30b5\u30a4\u30ba</target>\n </trans-unit>\n <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">\n <source>Last Change</source>\n <target>\u6700\u5f8c\u306e\u5909\u66f4</target>\n </trans-unit>\n <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">\n <source>Erasure Coded Profile</source>\n <target>\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u5316\u6e08\u307f\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb</target>\n </trans-unit>\n <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">\n <source>Crush Ruleset</source>\n <target>Crush\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">\n <source>Write bytes</source>\n <target>\u66f8\u304d\u8fbc\u307f\u30d0\u30a4\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">\n <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>\n <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>\n </trans-unit>\n <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">\n <source>bucket</source>\n <target>\u30d0\u30b1\u30c3\u30c8</target>\n </trans-unit>\n <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">\n <source>Updated Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30d0\u30b1\u30c3\u30c8\u300c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">\n <source>Created Object Gateway bucket "\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>"\n </source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30d0\u30b1\u30c3\u30c8\u300c\n <x id="INTERPOLATION" equiv-text="{{bid}}"/>\u300d\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">\n <source>buckets</source>\n <target>\u30d0\u30b1\u30c3\u30c8\u6570</target>\n </trans-unit>\n <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">\n <source>capability</source>\n <target>capability</target>\n </trans-unit>\n <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">\n <source>user</source>\n <target>\u30e6\u30fc\u30b6</target>\n </trans-unit>\n <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">\n <source>subuser</source>\n <target>subuser</target>\n </trans-unit>\n <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">\n <source>S3 Key</source>\n <target>S3 Key</target>\n </trans-unit>\n <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">\n <source>Updated Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">\n <source>Created Object Gateway user "\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>"\n </source>\n <target>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{uid}}"/>\u300d\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">\n <source>users</source>\n <target>\u30e6\u30fc\u30b6\u6570</target>\n </trans-unit>\n <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">\n <source>Swift Key</source>\n <target>Swift Key</target>\n </trans-unit>\n <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">\n <source>Scope</source>\n <target>\u7bc4\u56f2</target>\n </trans-unit>\n <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">\n <source>Read</source>\n <target>\u8aad\u307f\u53d6\u308a</target>\n </trans-unit>\n <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">\n <source>Create</source>\n <target>\u4f5c\u6210</target>\n </trans-unit>\n <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">\n <source>role</source>\n <target>role</target>\n </trans-unit>\n <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">\n <source>Created role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5f79\u5272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">\n <source>Updated role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5f79\u5272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">\n <source>System Role</source>\n <target>\u30b7\u30b9\u30c6\u30e0\u5f79\u5272</target>\n </trans-unit>\n <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">\n <source>Deleted role \'\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\'\n </source>\n <target>\u5f79\u5272\u300c\n <x id="INTERPOLATION" equiv-text="{{role_name}}"/>\u300d\u3092\u524a\u9664\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">\n <source>Created user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">\n <source>Update user</source>\n <target>\u30e6\u30fc\u30b6\u306e\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">\n <source>Continue</source>\n <target>\u7d9a\u884c</target>\n </trans-unit>\n <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">\n <source>You were automatically logged out because your roles have been changed.</source>\n <target>\u3053\u306e\u30e6\u30fc\u30b6\u306e\u5f79\u5272\u304c\u5909\u66f4\u3055\u308c\u305f\u305f\u3081\u3001\u3053\u306e\u30e6\u30fc\u30b6\u306f\u81ea\u52d5\u7684\u306b\u30ed\u30b0\u30a2\u30a6\u30c8\u3055\u308c\u307e\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">\n <source>Updated user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">\n <source>Deleted user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u3092\u524a\u9664\u3057\u307e\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">\n <source>Failed to delete user "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>"\n </source>\n <target>\u30e6\u30fc\u30b6\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">\n <source>You are currently logged in as "\n <x id="INTERPOLATION" equiv-text="{{username}}"/>".\n </source>\n <target>\u73fe\u5728\u3053\u306e\u30e6\u30fc\u30b6\u306f\u300c\n <x id="INTERPOLATION" equiv-text="{{username}}"/>\u300d\u3068\u3057\u3066\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">\n <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>\n <target>\u5404\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u8907\u6570\u306e\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30af\u30d1\u30fc\u30c8\u306b\u5206\u5272\u3055\u308c\u3066\u304a\u308a\u3001\u305d\u308c\u305e\u308c\u306e\u30d1\u30fc\u30c8\u306f\u7570\u306a\u308bOSD\u306b\u4fdd\u7ba1\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">\n <source>Compute coding chunks for each object and store them on different OSDs.\n The number of coding chunks is also the number of OSDs that can be down without losing data.</source>\n <target>\u5404\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30c1\u30e3\u30f3\u30af\u3092\u8a08\u7b97\u3057\u3066\u3001\u3053\u308c\u3089\u306e\u30c1\u30e3\u30f3\u30af\u3092\u5225\u3005\u306eOSD\u306b\u4fdd\u7ba1\u3057\u307e\u3059\u3002\n\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30c1\u30e3\u30f3\u30af\u306e\u6570\u306f\u3001\u30c7\u30fc\u30bf\u3092\u5931\u3046\u3053\u3068\u306a\u304f\u30c0\u30a6\u30f3\u72b6\u614b\u306b\u306a\u308b\u3053\u3068\u304c\u3067\u304d\u308bOSD\u306e\u6570\u3067\u3082\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">\n <source>The jerasure plugin is the most generic and flexible plugin,\n it is also the default for Ceph erasure coded pools.</source>\n <target>jerasure\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u6700\u3082\u6c4e\u7528\u7684\u3067\u67d4\u8edf\u6027\u306e\u9ad8\u3044\u30d7\u30e9\u30b0\u30a4\u30f3\u3067\u3059\u3002\n\u3053\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u3001Ceph\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u5316\u6e08\u307f\u30d7\u30fc\u30eb\u7528\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u3082\u3042\u308a\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">\n <source>The more flexible technique is reed_sol_van : it is enough to set k\n and m. The cauchy_good technique can be faster but you need to chose the packetsize\n carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents\n in the sense that they can only be configured with m=2.</source>\n <target>\u3055\u3089\u306b\u67d4\u8edf\u6027\u306e\u9ad8\u3044\u6280\u6cd5\u306freed_sol_van\u3067\u3059\u3002k\u3068m\u3092\n\u8a2d\u5b9a\u3059\u308b\u3060\u3051\u3067\u5341\u5206\u3067\u3059\u3002\ncauchy_good\u6280\u6cd5\u306f\u3088\u308a\u9ad8\u901f\u3068\u306a\u308a\u5f97\u307e\u3059\u304c\u3001\u30d1\u30b1\u30c3\u30c8\u30b5\u30a4\u30ba\u3092\u614e\u91cd\u306b\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\nreed_sol_r6_op\u3001liberation\u3001blaum_roth\u3001liber8tion\u306f\u3059\u3079\u3066\u3001\nm=2\u3092\u4f7f\u7528\u3057\u305f\u8a2d\u5b9a\u306e\u307f\u304c\u53ef\u80fd\u3068\u3044\u3046\u610f\u5473\u3067RAID6\u3068\u540c\u7b49\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">\n <source>The encoding will be done on packets of bytes size at a time.\n Chosing the right packet size is difficult.\n The jerasure documentation contains extensive information on this topic.</source>\n <target>\u30a8\u30f3\u30b3\u30fc\u30c9\u306f\u30d0\u30a4\u30c8\u30b5\u30a4\u30ba\u306e\u30d1\u30b1\u30c3\u30c8\u7fa4\u306b\u5bfe\u3057\u3066\u540c\u6642\u306b\u5b9f\u884c\u3055\u308c\u307e\u3059\u3002\n\u9069\u5207\u306a\u30d1\u30b1\u30c3\u30c8\u30b5\u30a4\u30ba\u3092\u9078\u629e\u3059\u308b\u3053\u3068\u306f\u56f0\u96e3\u3067\u3059\u3002\njerasure\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306b\u306f\u3053\u306e\u30c8\u30d4\u30c3\u30af\u306b\u95a2\u3059\u308b\u8a73\u7d30\u306a\u60c5\u5831\u304c\u8a18\u8f09\u3055\u308c\u3066\u3044\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">\n <source>With the jerasure plugin, when an erasure coded object is stored on\n multiple OSDs, recovering from the loss of one OSD requires reading from all the others.\n For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading\n from the eleven others to repair.\n\n The lrc erasure code plugin creates local parity chunks to be able to recover using\n less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create\n an additional parity chunk for every four OSDs. When a single OSD is lost, it can be\n recovered with only four OSDs instead of eleven.</source>\n <target>jerasure\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3068\u3001\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u5316\u6e08\u307f\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u8907\u6570\u306eOSD\u306b\u4fdd\u7ba1\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u3001\n1\u3064\u306eOSD\u306e\u55aa\u5931\u304b\u3089\u56de\u5fa9\u3059\u308b\u306b\u306f\u3001\u4ed6\u306e\u3059\u3079\u3066\u306eOSD\u304b\u3089\u306e\u8aad\u307f\u53d6\u308a\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\n\u305f\u3068\u3048\u3070\u3001k=8\u304a\u3088\u3073m=4\u3092\u4f7f\u7528\u3057\u3066jerasure\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u30011\u3064\u306eOSD\u304c\u5931\u308f\u308c\u305f\u5834\u5408\u3001\n\u4fee\u5fa9\u306e\u305f\u3081\u306b\u306f\u4ed6\u306e11\u500b\u306eOSD\u304b\u3089\u306e\u8aad\u307f\u53d6\u308a\u304c\u5fc5\u8981\u306b\u306a\u308a\u307e\u3059\u3002\n\nlrc\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u3001\u3053\u308c\u3088\u308a\u5c11\u306a\u3044OSD\u3092\u4f7f\u7528\u3057\u305f\u56de\u5fa9\u3092\u53ef\u80fd\u306b\u3059\u308b\u305f\u3081\u306b\u3001\n\u30ed\u30fc\u30ab\u30eb\u30d1\u30ea\u30c6\u30a3\u30c1\u30e3\u30f3\u30af\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\u305f\u3068\u3048\u3070\u3001lrc\u304ck=8\u3001m=4\u3001\u304a\u3088\u3073l=4\u3092\u4f7f\u7528\u3057\u3066\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u3001\nlrc\u306f\u30014\u3064\u306eOSD\u3054\u3068\u306b1\u3064\u306e\u8ffd\u52a0\u30d1\u30ea\u30c6\u30a3\u30c1\u30e3\u30f3\u30af\u3092\u4f5c\u6210\u3057\u307e\u3059\u30021\u3064\u306eOSD\u304c\u5931\u308f\u308c\u305f\u5834\u5408\u306f\u3001\n11\u500b\u306e\u4ee3\u308f\u308a\u306b4\u3064\u306eOSD\u306e\u307f\u3092\u4f7f\u7528\u3057\u3066\u305d\u306eOSD\u3092\u56de\u5fa9\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">\n <source>Group the coding and data chunks into sets of size locality. For instance,\n for k=4 and m=2, when locality=3 two groups of three are created. Each set can\n be recovered without reading chunks from another set.</source>\n <target>\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30c1\u30e3\u30f3\u30af\u3068\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30af\u3092\u30b5\u30a4\u30ba\u5730\u57df\u306e\u8907\u6570\u30bb\u30c3\u30c8\u306b\u30b0\u30eb\u30fc\u30d7\u5206\u3051\u3057\u307e\u3059\u3002\n\u305f\u3068\u3048\u3070\u3001k=4\u304a\u3088\u3073m=2\u306e\u5834\u5408\u306b\u3001\uff3b\u5730\u57df\uff3d=3\u306e\u5834\u5408\u306f\u30013\u3064\u306e\u30c1\u30e3\u30f3\u30af\u304b\u3089\u306a\u308b\u30b0\u30eb\u30fc\u30d7\u304c2\u3064\u4f5c\u6210\u3055\u308c\u307e\u3059\u3002\n\u5404\u30bb\u30c3\u30c8\u306f\u3001\u5225\u306e\u30bb\u30c3\u30c8\u304b\u3089\u30c1\u30e3\u30f3\u30af\u3092\u8aad\u307f\u53d6\u308b\u3053\u3068\u306a\u304f\u56de\u5fa9\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">\n <source>The type of the crush bucket in which each set of chunks defined\n by l will be stored. For instance, if it is set to rack, each group of l chunks will be\n placed in a different rack. It is used to create a CRUSH rule step such as step choose\n rack. If it is not set, no such grouping is done.</source>\n <target>1\u306b\u3088\u3063\u3066\u5b9a\u7fa9\u3055\u308c\u305f\u30c1\u30e3\u30f3\u30af\u306e\u5404\u30bb\u30c3\u30c8\u304c\u4fdd\u7ba1\u3055\u308c\u308bCrush\u30d0\u30b1\u30c3\u30c8\u306e\u30bf\u30a4\u30d7\u3002\n\u305f\u3068\u3048\u3070\u3001\u3053\u306e\u30d0\u30b1\u30c3\u30c8\u30bf\u30a4\u30d7\u304c\u30e9\u30c3\u30af\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u30011\u306e\u30c1\u30e3\u30f3\u30af\u306e\u5404\u30b0\u30eb\u30fc\u30d7\u306f\u7570\u306a\u308b\u30e9\u30c3\u30af\u306b\u914d\u7f6e\u3055\u308c\u307e\u3059\u3002\n\u3053\u306e\u30d0\u30b1\u30c3\u30c8\u30bf\u30a4\u30d7\u3092\u4f7f\u7528\u3057\u3066\u3001\u300c\u30e9\u30c3\u30af\u306e\u9078\u629e\u300d\u30b9\u30c6\u30c3\u30d7\u306a\u3069\u306eCRUSH\u30eb\u30fc\u30eb\u30b9\u30c6\u30c3\u30d7\u304c\u4f5c\u6210\u3055\u308c\u307e\u3059\u3002\n\u3053\u306e\u30d0\u30b1\u30c3\u30c8\u30bf\u30a4\u30d7\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u3001\u3053\u306e\u3088\u3046\u306a\u30b0\u30eb\u30fc\u30d7\u5206\u3051\u306f\u884c\u308f\u308c\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">\n <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>\n <target>isa\u30d7\u30e9\u30b0\u30a4\u30f3\u306fISA\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30ab\u30d7\u30bb\u30eb\u5316\u3057\u307e\u3059\u3002\u3053\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306fIntel\u30d7\u30ed\u30bb\u30c3\u30b5\u4e0a\u306e\u307f\u3067\u52d5\u4f5c\u3057\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">\n <source>The ISA plugin comes in two Reed Solomon forms.\n If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>\n <target>ISA\u30d7\u30e9\u30b0\u30a4\u30f3\u306f2\u3064\u306e\u30ea\u30fc\u30c9\u30bd\u30ed\u30e2\u30f3\u5f62\u5f0f\u3067\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u3059\u3002reed_sol_van\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u3001Vandermonde\u3067\u3042\u308a\u3001cauchy\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u3001Cauchy\u3067\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">\n <source>The shec plugin encapsulates the multiple SHEC library.\n It allows ceph to recover data more efficiently than Reed Solomon codes.</source>\n <target>shec\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u8907\u6570\u306eSHEC\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u30ab\u30d7\u30bb\u30eb\u5316\u3057\u307e\u3059\u3002\n\u3053\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3068\u3001ceph\u306f\u30ea\u30fc\u30c9\u30bd\u30ed\u30e2\u30f3\u30b3\u30fc\u30c9\u3088\u308a\u52b9\u7387\u7684\u306b\u30c7\u30fc\u30bf\u3092\u56de\u5fa9\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">\n <source>The number of parity chunks each of which includes each data chunk in its\n calculation range. The number is used as a durability estimator. For instance, if c=2,\n 2 OSDs can be down without losing data.</source>\n <target>\u305d\u308c\u305e\u308c\u304c\u5404\u30c7\u30fc\u30bf\u30c1\u30e3\u30f3\u30af\u3092\u5404\u81ea\u306e\u8a08\u7b97\u7bc4\u56f2\u5185\u306b\u542b\u3093\u3067\u3044\u308b\u30d1\u30ea\u30c6\u30a3\u30c1\u30e3\u30f3\u30af\u306e\u6570\u3002\n\u3053\u306e\u6570\u306f\u3001\u8010\u4e45\u6027\u63a8\u5b9a\u5b50\u3068\u3057\u3066\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002\n\u305f\u3068\u3048\u3070\u3001c=2\u306e\u5834\u5408\u306f\u3001\u30c7\u30fc\u30bf\u3092\u5931\u3046\u3053\u3068\u306a\u304f2\u3064\u306eOSD\u304c\u30c0\u30a6\u30f3\u72b6\u614b\u306b\u306a\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">\n <source>The name of the crush bucket used for the first step of the CRUSH rule.\n For instance step take default.</source>\n <target>CRUSH\u30eb\u30fc\u30eb\u306e\u6700\u521d\u306e\u30b9\u30c6\u30c3\u30d7(\u300c\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u4f7f\u7528\u300d\u30b9\u30c6\u30c3\u30d7\u306a\u3069)\u7528\u306b\n\u4f7f\u7528\u3055\u308c\u308bCrush\u30d0\u30b1\u30c3\u30c8\u306e\u540d\u524d\u3002</target>\n </trans-unit>\n <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">\n <source>Ensure that no two chunks are in a bucket with the same failure\n domain. For instance, if the failure domain is host no two chunks will be stored on the same\n host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>\n <target>\u540c\u3058\u969c\u5bb3\u30c9\u30e1\u30a4\u30f3\u306e\u5358\u4e00\u30d0\u30b1\u30c3\u30c8\u5185\u306b2\u3064\u306e\u30c1\u30e3\u30f3\u30af\u304c\u914d\u7f6e\u3055\u308c\u308b\u3053\u3068\u3092\u9632\u6b62\u3057\u307e\u3059\u3002\n\u305f\u3068\u3048\u3070\u3001\u969c\u5bb3\u30c9\u30e1\u30a4\u30f3\u304c\u30db\u30b9\u30c8\u3067\u3042\u308b\u5834\u5408\u306f\u30012\u3064\u306e\u30c1\u30e3\u30f3\u30af\u304c\u540c\u3058\u30db\u30b9\u30c8\u306b\u4fdd\u7ba1\u3055\u308c\u308b\u3053\u3068\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u3053\u308c\u3092\u4f7f\u7528\u3057\u3066\u3001\u300c\u30ea\u30fc\u30d5\u30db\u30b9\u30c8\u306e\u9078\u629e\u300d\u30b9\u30c6\u30c3\u30d7\u306a\u3069\u306eCRUSH\u30eb\u30fc\u30eb\u30b9\u30c6\u30c3\u30d7\u304c\u4f5c\u6210\u3055\u308c\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">\n <source>Restrict placement to devices of a specific class\n (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>\n <target>CRUSH\u30de\u30c3\u30d7\u5185\u3067Crush\u30c7\u30d0\u30a4\u30b9\u30af\u30e9\u30b9\u540d\u3092\u4f7f\u7528\u3057\u3066\u3001\u914d\u7f6e\u5148\u3092\u7279\u5b9a\u30af\u30e9\u30b9(ssd\u3084hdd\u306a\u3069)\u306e\u30c7\u30d0\u30a4\u30b9\u306e\u307f\u306b\u5236\u9650\u3057\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">\n <source>Set the directory name from which the erasure code plugin is loaded.</source>\n <target>\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8aad\u307f\u8fbc\u307f\u5143\u3068\u306a\u308b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u540d\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002</target>\n </trans-unit>\n <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">\n <source>Allows all operations</source>\n <target>\u3059\u3079\u3066\u306e\u64cd\u4f5c\u3092\u8a31\u53ef\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">\n <source>Allows only operations that do not modify the server</source>\n <target>\u30b5\u30fc\u30d0\u306b\u5909\u66f4\u3092\u52a0\u3048\u306a\u3044\u64cd\u4f5c\u306e\u307f\u3092\u8a31\u53ef\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">\n <source>Does not allow read or write operations, but allows any other operation</source>\n <target>\u8aad\u307f\u53d6\u308a/\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u3092\u8a31\u53ef\u3057\u307e\u305b\u3093\u304c\u3001\u4ed6\u306e\u3059\u3079\u3066\u306e\u64cd\u4f5c\u3092\u8a31\u53ef\u3057\u307e\u3059</target>\n </trans-unit>\n <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">\n <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>\n <target>\u8aad\u307f\u53d6\u308a/\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u3001\u304a\u3088\u3073\u30d5\u30a1\u30a4\u30eb\u5c5e\u6027\u3084\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u5185\u5bb9\u3092\u5909\u66f4\u3059\u308b\u3069\u306e\u64cd\u4f5c\u3082\u8a31\u53ef\u3057\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">\n <source>Allows no access at all</source>\n <target>\u30a2\u30af\u30bb\u30b9\u3092\u4e00\u5207\u8a31\u53ef\u3057\u307e\u305b\u3093</target>\n </trans-unit>\n <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">\n <source>-- Select the priority --</source>\n <target>-- \u512a\u5148\u5ea6\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044 --</target>\n </trans-unit>\n <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">\n <source>Low</source>\n <target>\u4f4e</target>\n </trans-unit>\n <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">\n <source>High</source>\n <target>\u9ad8</target>\n </trans-unit>\n <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">\n <source>Last 5 minutes</source>\n <target>\u76f4\u524d\u306e5\u5206\u9593</target>\n </trans-unit>\n <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">\n <source>Last 15 minutes</source>\n <target>\u76f4\u524d\u306e15\u5206\u9593</target>\n </trans-unit>\n <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">\n <source>Last 30 minutes</source>\n <target>\u76f4\u524d\u306e30\u5206\u9593</target>\n </trans-unit>\n <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">\n <source>Last 1 hour (Default)</source>\n <target>\u76f4\u524d\u306e1\u6642\u9593(\u30c7\u30d5\u30a9\u30eb\u30c8)</target>\n </trans-unit>\n <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">\n <source>Last 3 hours</source>\n <target>\u76f4\u524d\u306e3\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">\n <source>Last 6 hours</source>\n <target>\u76f4\u524d\u306e6\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">\n <source>Last 12 hours</source>\n <target>\u76f4\u524d\u306e12\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">\n <source>Last 24 hours</source>\n <target>\u76f4\u524d\u306e24\u6642\u9593</target>\n </trans-unit>\n <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">\n <source>Yesterday</source>\n <target>\u6628\u65e5</target>\n </trans-unit>\n <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">\n <source>Today</source>\n <target>\u672c\u65e5</target>\n </trans-unit>\n <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">\n <source>Today so far</source>\n <target>\u672c\u65e5\u306e\u73fe\u6642\u70b9\u307e\u3067</target>\n </trans-unit>\n <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">\n <source>Day before yesterday</source>\n <target>\u4e00\u6628\u65e5</target>\n </trans-unit>\n <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">\n <source>Last 2 days</source>\n <target>\u904e\u53bb2\u65e5\u9593</target>\n </trans-unit>\n <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">\n <source>This day last week</source>\n <target>\u5148\u9031\u306e\u540c\u3058\u66dc\u65e5</target>\n </trans-unit>\n <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">\n <source>Previous week</source>\n <target>\u524d\u9031</target>\n </trans-unit>\n <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">\n <source>This week</source>\n <target>\u4eca\u9031</target>\n </trans-unit>\n <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">\n <source>This week so far</source>\n <target>\u4eca\u9031\u306e\u73fe\u6642\u70b9\u307e\u3067</target>\n </trans-unit>\n <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">\n <source>Last 7 days</source>\n <target>\u904e\u53bb7\u65e5\u9593</target>\n </trans-unit>\n <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">\n <source>Previous month</source>\n <target>\u524d\u6708</target>\n </trans-unit>\n <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">\n <source>This month</source>\n <target>\u4eca\u6708</target>\n </trans-unit>\n <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">\n <source>This month so far</source>\n <target>\u4eca\u6708\u306e\u73fe\u6642\u70b9\u307e\u3067</target>\n </trans-unit>\n <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">\n <source>Last 30 days</source>\n <target>\u904e\u53bb30\u65e5\u9593</target>\n </trans-unit>\n <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">\n <source>Last 90 days</source>\n <target>\u904e\u53bb90\u65e5\u9593</target>\n </trans-unit>\n <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">\n <source>Last 6 months</source>\n <target>\u904e\u53bb6\u30ab\u6708</target>\n </trans-unit>\n <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">\n <source>Last 1 year</source>\n <target>\u904e\u53bb1\u5e74\u9593</target>\n </trans-unit>\n <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">\n <source>Previous year</source>\n <target>\u524d\u5e74</target>\n </trans-unit>\n <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">\n <source>This year</source>\n <target>\u4eca\u5e74</target>\n </trans-unit>\n <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">\n <source>This year so far</source>\n <target>\u4eca\u5e74\u306e\u73fe\u6642\u70b9\u307e\u3067</target>\n </trans-unit>\n <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">\n <source>Last 2 years</source>\n <target>\u904e\u53bb2\u5e74\u9593</target>\n </trans-unit>\n <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">\n <source>Last 5 years</source>\n <target>\u904e\u53bb5\u5e74\u9593</target>\n </trans-unit>\n <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">\n <source>Information</source>\n <target>\u60c5\u5831</target>\n </trans-unit>\n <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">\n <source>No items selected.</source>\n <target>\u30a2\u30a4\u30c6\u30e0\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">\n <source>Deselect item to select again</source>\n <target>\u30a2\u30a4\u30c6\u30e0\u3092\u9078\u629e\u89e3\u9664\u3057\u3066\u518d\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044</target>\n </trans-unit>\n <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">\n <source>Selection limit reached</source>\n <target>\u9078\u629e\u306e\u4e0a\u9650\u306b\u9054\u3057\u307e\u3057\u305f</target>\n </trans-unit>\n <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">\n <source>Filter tags</source>\n <target>\u30bf\u30b0\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0</target>\n </trans-unit>\n <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">\n <source>Add badge</source>\n <target>\u30d0\u30c3\u30b8\u306e\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">\n <source>There are no items available.</source>\n <target>\u4f7f\u7528\u53ef\u80fd\u306a\u30a2\u30a4\u30c6\u30e0\u306f\u3042\u308a\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">\n <source>Add</source>\n <target>\u8ffd\u52a0</target>\n </trans-unit>\n <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">\n <source>Remove</source>\n <target>Remove</target>\n </trans-unit>\n <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">\n <source>Clone</source>\n <target>\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">\n <source>Copy</source>\n <target>\u30b3\u30d4\u30fc</target>\n </trans-unit>\n <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">\n <source>Deep Scrub</source>\n <target>\u30c7\u30a3\u30fc\u30d7\u30b9\u30af\u30e9\u30d6</target>\n </trans-unit>\n <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">\n <source>Destroy</source>\n <target>\u7834\u68c4</target>\n </trans-unit>\n <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">\n <source>Flatten</source>\n <target>\u30d5\u30e9\u30c3\u30c8\u5316</target>\n </trans-unit>\n <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">\n <source>Mark Down</source>\n <target>\u30c0\u30a6\u30f3\u3068\u3057\u3066\u30de\u30fc\u30af</target>\n </trans-unit>\n <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">\n <source>Mark In</source>\n <target>\u30a4\u30f3\u3068\u3057\u3066\u30de\u30fc\u30af</target>\n </trans-unit>\n <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">\n <source>Mark Lost</source>\n <target>\u55aa\u5931\u3068\u3057\u3066\u30de\u30fc\u30af</target>\n </trans-unit>\n <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">\n <source>Mark Out</source>\n <target>\u30a2\u30a6\u30c8\u3068\u3057\u3066\u30de\u30fc\u30af</target>\n </trans-unit>\n <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">\n <source>Protect</source>\n <target>\u4fdd\u8b77</target>\n </trans-unit>\n <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">\n <source>Rename</source>\n <target>\u540d\u524d\u306e\u5909\u66f4</target>\n </trans-unit>\n <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">\n <source>Restore</source>\n <target>\u5fa9\u5143</target>\n </trans-unit>\n <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">\n <source>Move to Trash</source>\n <target>\u3054\u307f\u7bb1\u306b\u79fb\u52d5\u3059\u308b</target>\n </trans-unit>\n <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">\n <source>Unprotect</source>\n <target>\u4fdd\u8b77\u89e3\u9664</target>\n </trans-unit>\n <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">\n <source>Recreate</source>\n <target>Recreate</target>\n </trans-unit>\n <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">\n <source>Expire</source>\n <target>Expire</target>\n </trans-unit>\n <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">\n <source>Deleted</source>\n <target>\u524a\u9664\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">\n <source>Added</source>\n <target>Added</target>\n </trans-unit>\n <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">\n <source>Removed</source>\n <target>Removed</target>\n </trans-unit>\n <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">\n <source>Edited</source>\n <target>Edited</target>\n </trans-unit>\n <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">\n <source>Canceled</source>\n <target>Canceled</target>\n </trans-unit>\n <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">\n <source>Cloned</source>\n <target>\u8907\u88fd\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">\n <source>Copied</source>\n <target>\u30b3\u30d4\u30fc\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">\n <source>Showed</source>\n <target>Showed</target>\n </trans-unit>\n <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">\n <source>Moved to Trash</source>\n <target>Moved to Trash</target>\n </trans-unit>\n <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">\n <source>Unprotected</source>\n <target>Unprotected</target>\n </trans-unit>\n <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">\n <source>Recreated</source>\n <target>Recreated</target>\n </trans-unit>\n <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">\n <source>Expired</source>\n <target>Expired</target>\n </trans-unit>\n <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">\n <source>Yes</source>\n <target>\u306f\u3044</target>\n </trans-unit>\n <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">\n <source>No</source>\n <target>\u3044\u3044\u3048</target>\n </trans-unit>\n <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">\n <source>Your matcher seems to match no currently defined rule or active alert.</source>\n <target>Your matcher seems to match no currently defined rule or active alert.</target>\n </trans-unit>\n <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">\n <source>no active alerts</source>\n <target>no active alerts</target>\n </trans-unit>\n <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">\n <source>1 active alert</source>\n <target>1 active alert</target>\n </trans-unit>\n <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts\n </target>\n </trans-unit>\n <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">\n <source>Matches 1 rule</source>\n <target>Matches 1 rule</target>\n </trans-unit>\n <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">\n <source>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </source>\n <target>Matches \n <x id="INTERPOLATION" equiv-text="{{n}}"/> rules\n </target>\n </trans-unit>\n <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rules}}"/> with \n <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.\n </target>\n </trans-unit>\n <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">\n <source>Quality of Service</source>\n <target>\u30b5\u30fc\u30d3\u30b9\u54c1\u8cea</target>\n </trans-unit>\n <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">\n <source>BPS Limit</source>\n <target>BPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">\n <source>The desired limit of IO bytes per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u5165\u51fa\u529b\u30d0\u30a4\u30c8\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">\n <source>IOPS Limit</source>\n <target>IOPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">\n <source>The desired limit of IO operations per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u5165\u51fa\u529b\u64cd\u4f5c\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">\n <source>Read BPS Limit</source>\n <target>\u8aad\u307f\u53d6\u308aBPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">\n <source>The desired limit of read bytes per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u8aad\u307f\u53d6\u308a\u30d0\u30a4\u30c8\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">\n <source>Read IOPS Limit</source>\n <target>\u8aad\u307f\u53d6\u308aIOPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">\n <source>The desired limit of read operations per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u8aad\u307f\u53d6\u308a\u64cd\u4f5c\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">\n <source>Write BPS Limit</source>\n <target>\u66f8\u304d\u8fbc\u307fBPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">\n <source>The desired limit of write bytes per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u66f8\u304d\u8fbc\u307f\u30d0\u30a4\u30c8\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">\n <source>Write IOPS Limit</source>\n <target>\u66f8\u304d\u8fbc\u307fIOPS\u5236\u9650</target>\n </trans-unit>\n <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">\n <source>The desired limit of write operations per second.</source>\n <target>\u5e0c\u671b\u3059\u308b\u79d2\u3042\u305f\u308a\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u6570\u306e\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">\n <source>BPS Burst</source>\n <target>BPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">\n <source>The desired burst limit of IO bytes.</source>\n <target>\u5e0c\u671b\u3059\u308b\u5165\u51fa\u529b\u30d0\u30a4\u30c8\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">\n <source>IOPS Burst</source>\n <target>IOPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">\n <source>The desired burst limit of IO operations.</source>\n <target>\u5e0c\u671b\u3059\u308b\u5165\u51fa\u529b\u64cd\u4f5c\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">\n <source>Read BPS Burst</source>\n <target>\u8aad\u307f\u53d6\u308aBPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">\n <source>The desired burst limit of read bytes.</source>\n <target>\u5e0c\u671b\u3059\u308b\u8aad\u307f\u53d6\u308a\u30d0\u30a4\u30c8\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">\n <source>Read IOPS Burst</source>\n <target>\u8aad\u307f\u53d6\u308aIOPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">\n <source>The desired burst limit of read operations.</source>\n <target>\u5e0c\u671b\u3059\u308b\u8aad\u307f\u53d6\u308a\u64cd\u4f5c\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">\n <source>Write BPS Burst</source>\n <target>\u66f8\u304d\u8fbc\u307fBPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">\n <source>The desired burst limit of write bytes.</source>\n <target>\u5e0c\u671b\u3059\u308b\u66f8\u304d\u8fbc\u307f\u30d0\u30a4\u30c8\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">\n <source>Write IOPS Burst</source>\n <target>\u66f8\u304d\u8fbc\u307fIOPS\u30d0\u30fc\u30b9\u30c8</target>\n </trans-unit>\n <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">\n <source>The desired burst limit of write operations.</source>\n <target>\u5e0c\u671b\u3059\u308b\u66f8\u304d\u8fbc\u307f\u64cd\u4f5c\u6570\u306e\u30d0\u30fc\u30b9\u30c8\u4e0a\u9650\u3002</target>\n </trans-unit>\n <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">\n <source>Failed to \n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{failure}}"/>\n <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\n </target>\n </trans-unit>\n <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">\n <source>Executing</source>\n <target>\u5b9f\u884c\u4e2d</target>\n </trans-unit>\n <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">\n <source>execute</source>\n <target>\u5b9f\u884c</target>\n </trans-unit>\n <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">\n <source>Executed</source>\n <target>\u5b9f\u884c\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">\n <source>unknown task</source>\n <target>\u4e0d\u660e\u306a\u30bf\u30b9\u30af</target>\n </trans-unit>\n <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">\n <source>Creating</source>\n <target>\u4f5c\u6210\u4e2d</target>\n </trans-unit>\n <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">\n <source>create</source>\n <target>\u4f5c\u6210</target>\n </trans-unit>\n <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">\n <source>Updating</source>\n <target>\u66f4\u65b0\u4e2d</target>\n </trans-unit>\n <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">\n <source>update</source>\n <target>\u66f4\u65b0</target>\n </trans-unit>\n <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">\n <source>Deleting</source>\n <target>\u524a\u9664\u4e2d</target>\n </trans-unit>\n <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">\n <source>delete</source>\n <target>\u524a\u9664</target>\n </trans-unit>\n <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">\n <source>RBD \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">\n <source>RBD snapshot \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>RBD\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">\n <source>mirror mode for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u30d7\u30fc\u30eb\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u306e\u30df\u30e9\u30fc\u30e2\u30fc\u30c9\n </target>\n </trans-unit>\n <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">\n <source>mirror peer for pool \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u30d7\u30fc\u30eb\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u306e\u30df\u30e9\u30fc\u30d4\u30a2\n </target>\n </trans-unit>\n <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">\n <source>all dashboards</source>\n <target>all dashboards</target>\n </trans-unit>\n <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.\n </source>\n <target>\u3053\u306e\u540d\u524d\u306f\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u306b\u3088\u3063\u3066\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{name}}"/>.\n </source>\n <target>\u3053\u306e\u540d\u524d\u306f\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u306b\u3088\u3063\u3066\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.\n </source>\n <target>\u3053\u306e\u540d\u524d\u306f\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u306b\u3088\u3063\u3066\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">\n <source>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u306b\u306f\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">\n <source>Cloning</source>\n <target>\u8907\u88fd\u4e2d</target>\n </trans-unit>\n <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">\n <source>clone</source>\n <target>\u8907\u88fd</target>\n </trans-unit>\n <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">\n <source>Snapshot of \n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306f\u4fdd\u8b77\u3055\u308c\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">\n <source>Copying</source>\n <target>\u30b3\u30d4\u30fc\u4e2d</target>\n </trans-unit>\n <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">\n <source>copy</source>\n <target>\u30b3\u30d4\u30fc</target>\n </trans-unit>\n <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">\n <source>Flattening</source>\n <target>\u30d5\u30e9\u30c3\u30c8\u5316\u4e2d</target>\n </trans-unit>\n <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">\n <source>flatten</source>\n <target>\u30d5\u30e9\u30c3\u30c8\u5316</target>\n </trans-unit>\n <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">\n <source>Flattened</source>\n <target>\u30d5\u30e9\u30c3\u30c8\u5316\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">\n <source>Name is already used by \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.\n </source>\n <target>\u3053\u306e\u540d\u524d\u306f\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\u306b\u3088\u3063\u3066\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">\n <source>Cannot unprotect \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\u306f\u5b50\u30a4\u30e1\u30fc\u30b8\u3092\u542b\u3093\u3067\u3044\u308b\u305f\u3081\u4fdd\u8b77\u89e3\u9664\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">\n <source>Cannot delete \n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it\'s protected.\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>\u306f\u4fdd\u8b77\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002\n </target>\n </trans-unit>\n <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">\n <source>Rolling back</source>\n <target>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u4e2d</target>\n </trans-unit>\n <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">\n <source>rollback</source>\n <target>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af</target>\n </trans-unit>\n <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">\n <source>Rolled back</source>\n <target>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">\n <source>Moving</source>\n <target>\u79fb\u52d5\u4e2d</target>\n </trans-unit>\n <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">\n <source>move</source>\n <target>\u79fb\u52d5</target>\n </trans-unit>\n <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">\n <source>Moved</source>\n <target>\u79fb\u52d5\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' to trash\n </source>\n <target>\u30a4\u30e1\u30fc\u30b8\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u3092\u3054\u307f\u7bb1\u306b\n </target>\n </trans-unit>\n <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">\n <source>Could not find image.</source>\n <target>\u30a4\u30e1\u30fc\u30b8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002</target>\n </trans-unit>\n <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">\n <source>Restoring</source>\n <target>\u5fa9\u5143\u4e2d</target>\n </trans-unit>\n <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">\n <source>restore</source>\n <target>\u5fa9\u5143</target>\n </trans-unit>\n <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">\n <source>Restored</source>\n <target>\u5fa9\u5143\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' into \'\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\'\n </source>\n <target>\u30a4\u30e1\u30fc\u30b8\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u3092\u300c\n <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>\u300d\u306b\n </target>\n </trans-unit>\n <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">\n <source>Image name \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\' is already in use.\n </source>\n <target>\u30a4\u30e1\u30fc\u30b8\u540d\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\n </target>\n </trans-unit>\n <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">\n <source>image \'\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\'\n </source>\n <target>\u30a4\u30e1\u30fc\u30b8\u300c\n <x id="INTERPOLATION" equiv-text="{{id}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">\n <source>Purging</source>\n <target>\u6d88\u53bb\u4e2d</target>\n </trans-unit>\n <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">\n <source>purge</source>\n <target>\u6d88\u53bb</target>\n </trans-unit>\n <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">\n <source>Purged</source>\n <target>\u6d88\u53bb\u6e08\u307f</target>\n </trans-unit>\n <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">\n <source>all pools</source>\n <target>\u3059\u3079\u3066\u306e\u30d7\u30fc\u30eb</target>\n </trans-unit>\n <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">\n <source>images from \n <x id="INTERPOLATION" equiv-text="{{message}}"/>\n </source>\n <target>\n <x id="INTERPOLATION" equiv-text="{{message}}"/>\u304b\u3089\u306e\u30a4\u30e1\u30fc\u30b8\n </target>\n </trans-unit>\n <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">\n <source>Cannot disable mirroring because it contains a peer.</source>\n <target>\u30d4\u30a2\u3092\u542b\u3093\u3067\u3044\u308b\u305f\u3081\u30df\u30e9\u30fc\u30ea\u30f3\u30b0\u3092\u7121\u52b9\u5316\u3067\u304d\u307e\u305b\u3093\u3002</target>\n </trans-unit>\n <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">\n <source>pool \'\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\'\n </source>\n <target>\u30d7\u30fc\u30eb\u300c\n <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">\n <source>erasure code profile \'\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\'\n </source>\n <target>\u30a4\u30ec\u30a4\u30b8\u30e3\u30b3\u30fc\u30c9\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u300c\n <x id="INTERPOLATION" equiv-text="{{name}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">\n <source>target \'\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\'\n </source>\n <target>\u30bf\u30fc\u30b2\u30c3\u30c8\u300c\n <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>\u300d\n </target>\n </trans-unit>\n <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">\n <source>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </source>\n <target>NFS \n <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>\n </target>\n </trans-unit>\n </body>\n </file>\n</xliff>'},wbK0:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("dEwP");function r(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(e){return e.lift.call(a.a.apply(void 0,[e].concat(t)))}}},"wd/R":function(t,e,n){(function(t){t.exports=function(){"use strict";var e,a;function r(){return e.apply(null,arguments)}function i(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function s(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function o(t){return void 0===t}function u(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function c(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function l(t,e){var n,a=[];for(n=0;n<t.length;++n)a.push(e(t[n],n));return a}function d(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function f(t,e){for(var n in e)d(e,n)&&(t[n]=e[n]);return d(e,"toString")&&(t.toString=e.toString),d(e,"valueOf")&&(t.valueOf=e.valueOf),t}function p(t,e,n,a){return Re(t,e,n,a,!0).utc()}function h(t){return null==t._pf&&(t._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),t._pf}function g(t){if(null==t._isValid){var e=h(t),n=a.call(e.parsedDateParts,function(t){return null!=t}),r=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.weekdayMismatch&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(r=r&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return r;t._isValid=r}return t._isValid}function b(t){var e=p(NaN);return null!=t?f(h(e),t):h(e).userInvalidated=!0,e}a=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,a=0;a<n;a++)if(a in e&&t.call(this,e[a],a,e))return!0;return!1};var m=r.momentProperties=[];function y(t,e){var n,a,r;if(o(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),o(e._i)||(t._i=e._i),o(e._f)||(t._f=e._f),o(e._l)||(t._l=e._l),o(e._strict)||(t._strict=e._strict),o(e._tzm)||(t._tzm=e._tzm),o(e._isUTC)||(t._isUTC=e._isUTC),o(e._offset)||(t._offset=e._offset),o(e._pf)||(t._pf=h(e)),o(e._locale)||(t._locale=e._locale),m.length>0)for(n=0;n<m.length;n++)o(r=e[a=m[n]])||(t[a]=r);return t}var v=!1;function _(t){y(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===v&&(v=!0,r.updateOffset(this),v=!1)}function x(t){return t instanceof _||null!=t&&null!=t._isAMomentObject}function T(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function w(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=T(e)),n}function S(t,e,n){var a,r=Math.min(t.length,e.length),i=Math.abs(t.length-e.length),s=0;for(a=0;a<r;a++)(n&&t[a]!==e[a]||!n&&w(t[a])!==w(e[a]))&&s++;return s+i}function O(t){!1===r.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function I(t,e){var n=!0;return f(function(){if(null!=r.deprecationHandler&&r.deprecationHandler(null,t),n){for(var a,i=[],s=0;s<arguments.length;s++){if(a="","object"==typeof arguments[s]){for(var o in a+="\n["+s+"] ",arguments[0])a+=o+": "+arguments[0][o]+", ";a=a.slice(0,-2)}else a=arguments[s];i.push(a)}O(t+"\nArguments: "+Array.prototype.slice.call(i).join("")+"\n"+(new Error).stack),n=!1}return e.apply(this,arguments)},e)}var C,k={};function N(t,e){null!=r.deprecationHandler&&r.deprecationHandler(t,e),k[t]||(O(e),k[t]=!0)}function R(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function A(t,e){var n,a=f({},t);for(n in e)d(e,n)&&(s(t[n])&&s(e[n])?(a[n]={},f(a[n],t[n]),f(a[n],e[n])):null!=e[n]?a[n]=e[n]:delete a[n]);for(n in t)d(t,n)&&!d(e,n)&&s(t[n])&&(a[n]=f({},a[n]));return a}function D(t){null!=t&&this.set(t)}r.suppressDeprecationWarnings=!1,r.deprecationHandler=null,C=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)d(t,e)&&n.push(e);return n};var E={};function L(t,e){var n=t.toLowerCase();E[n]=E[n+"s"]=E[e]=t}function P(t){return"string"==typeof t?E[t]||E[t.toLowerCase()]:void 0}function M(t){var e,n,a={};for(n in t)d(t,n)&&(e=P(n))&&(a[e]=t[n]);return a}var q={};function j(t,e){q[t]=e}function F(t,e,n){var a=""+Math.abs(t);return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,e-a.length)).toString().substr(1)+a}var z=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Y={},V={};function H(t,e,n,a){var r=a;"string"==typeof a&&(r=function(){return this[a]()}),t&&(V[t]=r),e&&(V[e[0]]=function(){return F(r.apply(this,arguments),e[1],e[2])}),n&&(V[n]=function(){return this.localeData().ordinal(r.apply(this,arguments),t)})}function B(t,e){return t.isValid()?(e=U(e,t.localeData()),Y[e]=Y[e]||function(t){var e,n,a,r=t.match(z);for(e=0,n=r.length;e<n;e++)r[e]=V[r[e]]?V[r[e]]:(a=r[e]).match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"");return function(e){var a,i="";for(a=0;a<n;a++)i+=R(r[a])?r[a].call(e,t):r[a];return i}}(e),Y[e](t)):t.localeData().invalidDate()}function U(t,e){var n=5;function a(t){return e.longDateFormat(t)||t}for(G.lastIndex=0;n>=0&&G.test(t);)t=t.replace(G,a),G.lastIndex=0,n-=1;return t}var W=/\d/,K=/\d\d/,$=/\d{3}/,Z=/\d{4}/,X=/[+-]?\d{6}/,J=/\d\d?/,Q=/\d\d\d\d?/,tt=/\d\d\d\d\d\d?/,et=/\d{1,3}/,nt=/\d{1,4}/,at=/[+-]?\d{1,6}/,rt=/\d+/,it=/[+-]?\d+/,st=/Z|[+-]\d\d:?\d\d/gi,ot=/Z|[+-]\d\d(?::?\d\d)?/gi,ut=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,ct={};function lt(t,e,n){ct[t]=R(e)?e:function(t,a){return t&&n?n:e}}function dt(t,e){return d(ct,t)?ct[t](e._strict,e._locale):new RegExp(ft(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,a,r){return e||n||a||r})))}function ft(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var pt={};function ht(t,e){var n,a=e;for("string"==typeof t&&(t=[t]),u(e)&&(a=function(t,n){n[e]=w(t)}),n=0;n<t.length;n++)pt[t[n]]=a}function gt(t,e){ht(t,function(t,n,a,r){a._w=a._w||{},e(t,a._w,a,r)})}function bt(t,e,n){null!=e&&d(pt,t)&&pt[t](e,n._a,n,t)}var mt=0,yt=1,vt=2,_t=3,xt=4,Tt=5,wt=6,St=7,Ot=8;function It(t){return Ct(t)?366:365}function Ct(t){return t%4==0&&t%100!=0||t%400==0}H("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),L("year","y"),j("year",1),lt("Y",it),lt("YY",J,K),lt("YYYY",nt,Z),lt("YYYYY",at,X),lt("YYYYYY",at,X),ht(["YYYYY","YYYYYY"],mt),ht("YYYY",function(t,e){e[mt]=2===t.length?r.parseTwoDigitYear(t):w(t)}),ht("YY",function(t,e){e[mt]=r.parseTwoDigitYear(t)}),ht("Y",function(t,e){e[mt]=parseInt(t,10)}),r.parseTwoDigitYear=function(t){return w(t)+(w(t)>68?1900:2e3)};var kt,Nt=Rt("FullYear",!0);function Rt(t,e){return function(n){return null!=n?(Dt(this,t,n),r.updateOffset(this,e),this):At(this,t)}}function At(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function Dt(t,e,n){t.isValid()&&!isNaN(n)&&("FullYear"===e&&Ct(t.year())&&1===t.month()&&29===t.date()?t._d["set"+(t._isUTC?"UTC":"")+e](n,t.month(),Et(n,t.month())):t._d["set"+(t._isUTC?"UTC":"")+e](n))}function Et(t,e){if(isNaN(t)||isNaN(e))return NaN;var n=(e%12+12)%12;return t+=(e-n)/12,1===n?Ct(t)?29:28:31-n%7%2}kt=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),H("MMMM",0,0,function(t){return this.localeData().months(this,t)}),L("month","M"),j("month",8),lt("M",J),lt("MM",J,K),lt("MMM",function(t,e){return e.monthsShortRegex(t)}),lt("MMMM",function(t,e){return e.monthsRegex(t)}),ht(["M","MM"],function(t,e){e[yt]=w(t)-1}),ht(["MMM","MMMM"],function(t,e,n,a){var r=n._locale.monthsParse(t,a,n._strict);null!=r?e[yt]=r:h(n).invalidMonth=t});var Lt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Pt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Mt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function qt(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=w(e);else if(!u(e=t.localeData().monthsParse(e)))return t;return n=Math.min(t.date(),Et(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function jt(t){return null!=t?(qt(this,t),r.updateOffset(this,!0),this):At(this,"Month")}var Ft=ut,zt=ut;function Gt(){function t(t,e){return e.length-t.length}var e,n,a=[],r=[],i=[];for(e=0;e<12;e++)n=p([2e3,e]),a.push(this.monthsShort(n,"")),r.push(this.months(n,"")),i.push(this.months(n,"")),i.push(this.monthsShort(n,""));for(a.sort(t),r.sort(t),i.sort(t),e=0;e<12;e++)a[e]=ft(a[e]),r[e]=ft(r[e]);for(e=0;e<24;e++)i[e]=ft(i[e]);this._monthsRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Yt(t){var e;if(t<100&&t>=0){var n=Array.prototype.slice.call(arguments);n[0]=t+400,e=new Date(Date.UTC.apply(null,n)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)}else e=new Date(Date.UTC.apply(null,arguments));return e}function Vt(t,e,n){var a=7+e-n;return-(7+Yt(t,0,a).getUTCDay()-e)%7+a-1}function Ht(t,e,n,a,r){var i,s,o=1+7*(e-1)+(7+n-a)%7+Vt(t,a,r);return o<=0?s=It(i=t-1)+o:o>It(t)?(i=t+1,s=o-It(t)):(i=t,s=o),{year:i,dayOfYear:s}}function Bt(t,e,n){var a,r,i=Vt(t.year(),e,n),s=Math.floor((t.dayOfYear()-i-1)/7)+1;return s<1?a=s+Ut(r=t.year()-1,e,n):s>Ut(t.year(),e,n)?(a=s-Ut(t.year(),e,n),r=t.year()+1):(r=t.year(),a=s),{week:a,year:r}}function Ut(t,e,n){var a=Vt(t,e,n),r=Vt(t+1,e,n);return(It(t)-a+r)/7}function Wt(t,e){return t.slice(e,7).concat(t.slice(0,e))}H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),j("week",5),j("isoWeek",5),lt("w",J),lt("ww",J,K),lt("W",J),lt("WW",J,K),gt(["w","ww","W","WW"],function(t,e,n,a){e[a.substr(0,1)]=w(t)}),H("d",0,"do","day"),H("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),H("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),H("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),j("day",11),j("weekday",11),j("isoWeekday",11),lt("d",J),lt("e",J),lt("E",J),lt("dd",function(t,e){return e.weekdaysMinRegex(t)}),lt("ddd",function(t,e){return e.weekdaysShortRegex(t)}),lt("dddd",function(t,e){return e.weekdaysRegex(t)}),gt(["dd","ddd","dddd"],function(t,e,n,a){var r=n._locale.weekdaysParse(t,a,n._strict);null!=r?e.d=r:h(n).invalidWeekday=t}),gt(["d","e","E"],function(t,e,n,a){e[a]=w(t)});var Kt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),$t="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Zt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Xt=ut,Jt=ut,Qt=ut;function te(){function t(t,e){return e.length-t.length}var e,n,a,r,i,s=[],o=[],u=[],c=[];for(e=0;e<7;e++)n=p([2e3,1]).day(e),a=this.weekdaysMin(n,""),r=this.weekdaysShort(n,""),i=this.weekdays(n,""),s.push(a),o.push(r),u.push(i),c.push(a),c.push(r),c.push(i);for(s.sort(t),o.sort(t),u.sort(t),c.sort(t),e=0;e<7;e++)o[e]=ft(o[e]),u[e]=ft(u[e]),c[e]=ft(c[e]);this._weekdaysRegex=new RegExp("^("+c.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+s.join("|")+")","i")}function ee(){return this.hours()%12||12}function ne(t,e){H(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function ae(t,e){return e._meridiemParse}H("H",["HH",2],0,"hour"),H("h",["hh",2],0,ee),H("k",["kk",2],0,function(){return this.hours()||24}),H("hmm",0,0,function(){return""+ee.apply(this)+F(this.minutes(),2)}),H("hmmss",0,0,function(){return""+ee.apply(this)+F(this.minutes(),2)+F(this.seconds(),2)}),H("Hmm",0,0,function(){return""+this.hours()+F(this.minutes(),2)}),H("Hmmss",0,0,function(){return""+this.hours()+F(this.minutes(),2)+F(this.seconds(),2)}),ne("a",!0),ne("A",!1),L("hour","h"),j("hour",13),lt("a",ae),lt("A",ae),lt("H",J),lt("h",J),lt("k",J),lt("HH",J,K),lt("hh",J,K),lt("kk",J,K),lt("hmm",Q),lt("hmmss",tt),lt("Hmm",Q),lt("Hmmss",tt),ht(["H","HH"],_t),ht(["k","kk"],function(t,e,n){var a=w(t);e[_t]=24===a?0:a}),ht(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),ht(["h","hh"],function(t,e,n){e[_t]=w(t),h(n).bigHour=!0}),ht("hmm",function(t,e,n){var a=t.length-2;e[_t]=w(t.substr(0,a)),e[xt]=w(t.substr(a)),h(n).bigHour=!0}),ht("hmmss",function(t,e,n){var a=t.length-4,r=t.length-2;e[_t]=w(t.substr(0,a)),e[xt]=w(t.substr(a,2)),e[Tt]=w(t.substr(r)),h(n).bigHour=!0}),ht("Hmm",function(t,e,n){var a=t.length-2;e[_t]=w(t.substr(0,a)),e[xt]=w(t.substr(a))}),ht("Hmmss",function(t,e,n){var a=t.length-4,r=t.length-2;e[_t]=w(t.substr(0,a)),e[xt]=w(t.substr(a,2)),e[Tt]=w(t.substr(r))});var re,ie=Rt("Hours",!0),se={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Pt,monthsShort:Mt,week:{dow:0,doy:6},weekdays:Kt,weekdaysMin:Zt,weekdaysShort:$t,meridiemParse:/[ap]\.?m?\.?/i},oe={},ue={};function ce(t){return t?t.toLowerCase().replace("_","-"):t}function le(e){var a=null;if(!oe[e]&&void 0!==t&&t&&t.exports)try{a=re._abbr,n("RnhZ")("./"+e),de(a)}catch(r){}return oe[e]}function de(t,e){var n;return t&&((n=o(e)?pe(t):fe(t,e))?re=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),re._abbr}function fe(t,e){if(null!==e){var n,a=se;if(e.abbr=t,null!=oe[t])N("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),a=oe[t]._config;else if(null!=e.parentLocale)if(null!=oe[e.parentLocale])a=oe[e.parentLocale]._config;else{if(null==(n=le(e.parentLocale)))return ue[e.parentLocale]||(ue[e.parentLocale]=[]),ue[e.parentLocale].push({name:t,config:e}),null;a=n._config}return oe[t]=new D(A(a,e)),ue[t]&&ue[t].forEach(function(t){fe(t.name,t.config)}),de(t),oe[t]}return delete oe[t],null}function pe(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return re;if(!i(t)){if(e=le(t))return e;t=[t]}return function(t){for(var e,n,a,r,i=0;i<t.length;){for(e=(r=ce(t[i]).split("-")).length,n=(n=ce(t[i+1]))?n.split("-"):null;e>0;){if(a=le(r.slice(0,e).join("-")))return a;if(n&&n.length>=e&&S(r,n,!0)>=e-1)break;e--}i++}return re}(t)}function he(t){var e,n=t._a;return n&&-2===h(t).overflow&&(e=n[yt]<0||n[yt]>11?yt:n[vt]<1||n[vt]>Et(n[mt],n[yt])?vt:n[_t]<0||n[_t]>24||24===n[_t]&&(0!==n[xt]||0!==n[Tt]||0!==n[wt])?_t:n[xt]<0||n[xt]>59?xt:n[Tt]<0||n[Tt]>59?Tt:n[wt]<0||n[wt]>999?wt:-1,h(t)._overflowDayOfYear&&(e<mt||e>vt)&&(e=vt),h(t)._overflowWeeks&&-1===e&&(e=St),h(t)._overflowWeekday&&-1===e&&(e=Ot),h(t).overflow=e),t}function ge(t,e,n){return null!=t?t:null!=e?e:n}function be(t){var e,n,a,i,s,o=[];if(!t._d){for(a=function(t){var e=new Date(r.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}(t),t._w&&null==t._a[vt]&&null==t._a[yt]&&function(t){var e,n,a,r,i,s,o,u;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)i=1,s=4,n=ge(e.GG,t._a[mt],Bt(Ae(),1,4).year),a=ge(e.W,1),((r=ge(e.E,1))<1||r>7)&&(u=!0);else{i=t._locale._week.dow,s=t._locale._week.doy;var c=Bt(Ae(),i,s);n=ge(e.gg,t._a[mt],c.year),a=ge(e.w,c.week),null!=e.d?((r=e.d)<0||r>6)&&(u=!0):null!=e.e?(r=e.e+i,(e.e<0||e.e>6)&&(u=!0)):r=i}a<1||a>Ut(n,i,s)?h(t)._overflowWeeks=!0:null!=u?h(t)._overflowWeekday=!0:(o=Ht(n,a,r,i,s),t._a[mt]=o.year,t._dayOfYear=o.dayOfYear)}(t),null!=t._dayOfYear&&(s=ge(t._a[mt],a[mt]),(t._dayOfYear>It(s)||0===t._dayOfYear)&&(h(t)._overflowDayOfYear=!0),n=Yt(s,0,t._dayOfYear),t._a[yt]=n.getUTCMonth(),t._a[vt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=o[e]=a[e];for(;e<7;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[_t]&&0===t._a[xt]&&0===t._a[Tt]&&0===t._a[wt]&&(t._nextDay=!0,t._a[_t]=0),t._d=(t._useUTC?Yt:function(t,e,n,a,r,i,s){var o;return t<100&&t>=0?(o=new Date(t+400,e,n,a,r,i,s),isFinite(o.getFullYear())&&o.setFullYear(t)):o=new Date(t,e,n,a,r,i,s),o}).apply(null,o),i=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[_t]=24),t._w&&void 0!==t._w.d&&t._w.d!==i&&(h(t).weekdayMismatch=!0)}}var me=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ye=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ve=/Z|[+-]\d\d(?::?\d\d)?/,_e=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],xe=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Te=/^\/?Date\((\-?\d+)/i;function we(t){var e,n,a,r,i,s,o=t._i,u=me.exec(o)||ye.exec(o);if(u){for(h(t).iso=!0,e=0,n=_e.length;e<n;e++)if(_e[e][1].exec(u[1])){r=_e[e][0],a=!1!==_e[e][2];break}if(null==r)return void(t._isValid=!1);if(u[3]){for(e=0,n=xe.length;e<n;e++)if(xe[e][1].exec(u[3])){i=(u[2]||" ")+xe[e][0];break}if(null==i)return void(t._isValid=!1)}if(!a&&null!=i)return void(t._isValid=!1);if(u[4]){if(!ve.exec(u[4]))return void(t._isValid=!1);s="Z"}t._f=r+(i||"")+(s||""),ke(t)}else t._isValid=!1}var Se=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Oe(t){var e=parseInt(t,10);return e<=49?2e3+e:e<=999?1900+e:e}var Ie={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Ce(t){var e,n,a,r,i,s,o=Se.exec(t._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(o){var u=(e=o[3],n=o[2],a=o[5],r=o[6],i=o[7],s=[Oe(o[4]),Mt.indexOf(e),parseInt(n,10),parseInt(a,10),parseInt(r,10)],i&&s.push(parseInt(i,10)),s);if(!function(t,e,n){return!t||$t.indexOf(t)===new Date(e[0],e[1],e[2]).getDay()||(h(n).weekdayMismatch=!0,n._isValid=!1,!1)}(o[1],u,t))return;t._a=u,t._tzm=function(t,e,n){if(t)return Ie[t];if(o[9])return 0;var a=parseInt(o[10],10),r=a%100;return(a-r)/100*60+r}(o[8]),t._d=Yt.apply(null,t._a),t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),h(t).rfc2822=!0}else t._isValid=!1}function ke(t){if(t._f!==r.ISO_8601)if(t._f!==r.RFC_2822){t._a=[],h(t).empty=!0;var e,n,a,i,s,o=""+t._i,u=o.length,c=0;for(a=U(t._f,t._locale).match(z)||[],e=0;e<a.length;e++)(n=(o.match(dt(i=a[e],t))||[])[0])&&((s=o.substr(0,o.indexOf(n))).length>0&&h(t).unusedInput.push(s),o=o.slice(o.indexOf(n)+n.length),c+=n.length),V[i]?(n?h(t).empty=!1:h(t).unusedTokens.push(i),bt(i,n,t)):t._strict&&!n&&h(t).unusedTokens.push(i);h(t).charsLeftOver=u-c,o.length>0&&h(t).unusedInput.push(o),t._a[_t]<=12&&!0===h(t).bigHour&&t._a[_t]>0&&(h(t).bigHour=void 0),h(t).parsedDateParts=t._a.slice(0),h(t).meridiem=t._meridiem,t._a[_t]=(l=t._locale,d=t._a[_t],null==(f=t._meridiem)?d:null!=l.meridiemHour?l.meridiemHour(d,f):null!=l.isPM?((p=l.isPM(f))&&d<12&&(d+=12),p||12!==d||(d=0),d):d),be(t),he(t)}else Ce(t);else we(t);var l,d,f,p}function Ne(t){var e=t._i,n=t._f;return t._locale=t._locale||pe(t._l),null===e||void 0===n&&""===e?b({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),x(e)?new _(he(e)):(c(e)?t._d=e:i(n)?function(t){var e,n,a,r,i;if(0===t._f.length)return h(t).invalidFormat=!0,void(t._d=new Date(NaN));for(r=0;r<t._f.length;r++)i=0,e=y({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[r],ke(e),g(e)&&(i+=h(e).charsLeftOver,i+=10*h(e).unusedTokens.length,h(e).score=i,(null==a||i<a)&&(a=i,n=e));f(t,n||e)}(t):n?ke(t):function(t){var e=t._i;o(e)?t._d=new Date(r.now()):c(e)?t._d=new Date(e.valueOf()):"string"==typeof e?function(t){var e=Te.exec(t._i);null===e?(we(t),!1===t._isValid&&(delete t._isValid,Ce(t),!1===t._isValid&&(delete t._isValid,r.createFromInputFallback(t)))):t._d=new Date(+e[1])}(t):i(e)?(t._a=l(e.slice(0),function(t){return parseInt(t,10)}),be(t)):s(e)?function(t){if(!t._d){var e=M(t._i);t._a=l([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),be(t)}}(t):u(e)?t._d=new Date(e):r.createFromInputFallback(t)}(t),g(t)||(t._d=null),t))}function Re(t,e,n,a,r){var o,u={};return!0!==n&&!1!==n||(a=n,n=void 0),(s(t)&&function(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}(t)||i(t)&&0===t.length)&&(t=void 0),u._isAMomentObject=!0,u._useUTC=u._isUTC=r,u._l=n,u._i=t,u._f=e,u._strict=a,(o=new _(he(Ne(u))))._nextDay&&(o.add(1,"d"),o._nextDay=void 0),o}function Ae(t,e,n,a){return Re(t,e,n,a,!1)}r.createFromInputFallback=I("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),r.ISO_8601=function(){},r.RFC_2822=function(){};var De=I("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Ae.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:b()}),Ee=I("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Ae.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:b()});function Le(t,e){var n,a;if(1===e.length&&i(e[0])&&(e=e[0]),!e.length)return Ae();for(n=e[0],a=1;a<e.length;++a)e[a].isValid()&&!e[a][t](n)||(n=e[a]);return n}var Pe=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Me(t){var e=M(t),n=e.year||0,a=e.quarter||0,r=e.month||0,i=e.week||e.isoWeek||0,s=e.day||0,o=e.hour||0,u=e.minute||0,c=e.second||0,l=e.millisecond||0;this._isValid=function(t){for(var e in t)if(-1===kt.call(Pe,e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,a=0;a<Pe.length;++a)if(t[Pe[a]]){if(n)return!1;parseFloat(t[Pe[a]])!==w(t[Pe[a]])&&(n=!0)}return!0}(e),this._milliseconds=+l+1e3*c+6e4*u+1e3*o*60*60,this._days=+s+7*i,this._months=+r+3*a+12*n,this._data={},this._locale=pe(),this._bubble()}function qe(t){return t instanceof Me}function je(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function Fe(t,e){H(t,0,0,function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+F(~~(t/60),2)+e+F(~~t%60,2)})}Fe("Z",":"),Fe("ZZ",""),lt("Z",ot),lt("ZZ",ot),ht(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ge(ot,t)});var ze=/([\+\-]|\d\d)/gi;function Ge(t,e){var n=(e||"").match(t);if(null===n)return null;var a=((n[n.length-1]||[])+"").match(ze)||["-",0,0],r=60*a[1]+w(a[2]);return 0===r?0:"+"===a[0]?r:-r}function Ye(t,e){var n,a;return e._isUTC?(n=e.clone(),a=(x(t)||c(t)?t.valueOf():Ae(t).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+a),r.updateOffset(n,!1),n):Ae(t).local()}function Ve(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function He(){return!!this.isValid()&&this._isUTC&&0===this._offset}r.updateOffset=function(){};var Be=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ue=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function We(t,e){var n,a,r,i,s,o,c=t,l=null;return qe(t)?c={ms:t._milliseconds,d:t._days,M:t._months}:u(t)?(c={},e?c[e]=t:c.milliseconds=t):(l=Be.exec(t))?(n="-"===l[1]?-1:1,c={y:0,d:w(l[vt])*n,h:w(l[_t])*n,m:w(l[xt])*n,s:w(l[Tt])*n,ms:w(je(1e3*l[wt]))*n}):(l=Ue.exec(t))?c={y:Ke(l[2],n="-"===l[1]?-1:1),M:Ke(l[3],n),w:Ke(l[4],n),d:Ke(l[5],n),h:Ke(l[6],n),m:Ke(l[7],n),s:Ke(l[8],n)}:null==c?c={}:"object"==typeof c&&("from"in c||"to"in c)&&(i=Ae(c.from),s=Ae(c.to),r=i.isValid()&&s.isValid()?(s=Ye(s,i),i.isBefore(s)?o=$e(i,s):((o=$e(s,i)).milliseconds=-o.milliseconds,o.months=-o.months),o):{milliseconds:0,months:0},(c={}).ms=r.milliseconds,c.M=r.months),a=new Me(c),qe(t)&&d(t,"_locale")&&(a._locale=t._locale),a}function Ke(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function $e(t,e){var n={};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function Ze(t,e){return function(n,a){var r;return null===a||isNaN(+a)||(N(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=a,a=r),Xe(this,We(n="string"==typeof n?+n:n,a),t),this}}function Xe(t,e,n,a){var i=e._milliseconds,s=je(e._days),o=je(e._months);t.isValid()&&(a=null==a||a,o&&qt(t,At(t,"Month")+o*n),s&&Dt(t,"Date",At(t,"Date")+s*n),i&&t._d.setTime(t._d.valueOf()+i*n),a&&r.updateOffset(t,s||o))}We.fn=Me.prototype,We.invalid=function(){return We(NaN)};var Je=Ze(1,"add"),Qe=Ze(-1,"subtract");function tn(t,e){var n=12*(e.year()-t.year())+(e.month()-t.month()),a=t.clone().add(n,"months");return-(n+(e-a<0?(e-a)/(a-t.clone().add(n-1,"months")):(e-a)/(t.clone().add(n+1,"months")-a)))||0}function en(t){var e;return void 0===t?this._locale._abbr:(null!=(e=pe(t))&&(this._locale=e),this)}r.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",r.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var nn=I("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});function an(){return this._locale}var rn=126227808e5;function sn(t,e){return(t%e+e)%e}function on(t,e,n){return t<100&&t>=0?new Date(t+400,e,n)-rn:new Date(t,e,n).valueOf()}function un(t,e,n){return t<100&&t>=0?Date.UTC(t+400,e,n)-rn:Date.UTC(t,e,n)}function cn(t,e){H(0,[t,t.length],0,e)}function ln(t,e,n,a,r){var i;return null==t?Bt(this,a,r).year:(e>(i=Ut(t,a,r))&&(e=i),(function(t,e,n,a,r){var i=Ht(t,e,n,a,r),s=Yt(i.year,0,i.dayOfYear);return this.year(s.getUTCFullYear()),this.month(s.getUTCMonth()),this.date(s.getUTCDate()),this}).call(this,t,e,n,a,r))}H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),cn("gggg","weekYear"),cn("ggggg","weekYear"),cn("GGGG","isoWeekYear"),cn("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),j("weekYear",1),j("isoWeekYear",1),lt("G",it),lt("g",it),lt("GG",J,K),lt("gg",J,K),lt("GGGG",nt,Z),lt("gggg",nt,Z),lt("GGGGG",at,X),lt("ggggg",at,X),gt(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,a){e[a.substr(0,2)]=w(t)}),gt(["gg","GG"],function(t,e,n,a){e[a]=r.parseTwoDigitYear(t)}),H("Q",0,"Qo","quarter"),L("quarter","Q"),j("quarter",7),lt("Q",W),ht("Q",function(t,e){e[yt]=3*(w(t)-1)}),H("D",["DD",2],"Do","date"),L("date","D"),j("date",9),lt("D",J),lt("DD",J,K),lt("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),ht(["D","DD"],vt),ht("Do",function(t,e){e[vt]=w(t.match(J)[0])});var dn=Rt("Date",!0);H("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),j("dayOfYear",4),lt("DDD",et),lt("DDDD",$),ht(["DDD","DDDD"],function(t,e,n){n._dayOfYear=w(t)}),H("m",["mm",2],0,"minute"),L("minute","m"),j("minute",14),lt("m",J),lt("mm",J,K),ht(["m","mm"],xt);var fn=Rt("Minutes",!1);H("s",["ss",2],0,"second"),L("second","s"),j("second",15),lt("s",J),lt("ss",J,K),ht(["s","ss"],Tt);var pn,hn=Rt("Seconds",!1);for(H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),L("millisecond","ms"),j("millisecond",16),lt("S",et,W),lt("SS",et,K),lt("SSS",et,$),pn="SSSS";pn.length<=9;pn+="S")lt(pn,rt);function gn(t,e){e[wt]=w(1e3*("0."+t))}for(pn="S";pn.length<=9;pn+="S")ht(pn,gn);var bn=Rt("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var mn=_.prototype;function yn(t){return t}mn.add=Je,mn.calendar=function(t,e){var n=t||Ae(),a=Ye(n,this).startOf("day"),i=r.calendarFormat(this,a)||"sameElse",s=e&&(R(e[i])?e[i].call(this,n):e[i]);return this.format(s||this.localeData().calendar(i,this,Ae(n)))},mn.clone=function(){return new _(this)},mn.diff=function(t,e,n){var a,r,i;if(!this.isValid())return NaN;if(!(a=Ye(t,this)).isValid())return NaN;switch(r=6e4*(a.utcOffset()-this.utcOffset()),e=P(e)){case"year":i=tn(this,a)/12;break;case"month":i=tn(this,a);break;case"quarter":i=tn(this,a)/3;break;case"second":i=(this-a)/1e3;break;case"minute":i=(this-a)/6e4;break;case"hour":i=(this-a)/36e5;break;case"day":i=(this-a-r)/864e5;break;case"week":i=(this-a-r)/6048e5;break;default:i=this-a}return n?i:T(i)},mn.endOf=function(t){var e;if(void 0===(t=P(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?un:on;switch(t){case"year":e=n(this.year()+1,0,1)-1;break;case"quarter":e=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=n(this.year(),this.month()+1,1)-1;break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=36e5-sn(e+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":e=this._d.valueOf(),e+=6e4-sn(e,6e4)-1;break;case"second":e=this._d.valueOf(),e+=1e3-sn(e,1e3)-1}return this._d.setTime(e),r.updateOffset(this,!0),this},mn.format=function(t){t||(t=this.isUtc()?r.defaultFormatUtc:r.defaultFormat);var e=B(this,t);return this.localeData().postformat(e)},mn.from=function(t,e){return this.isValid()&&(x(t)&&t.isValid()||Ae(t).isValid())?We({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},mn.fromNow=function(t){return this.from(Ae(),t)},mn.to=function(t,e){return this.isValid()&&(x(t)&&t.isValid()||Ae(t).isValid())?We({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},mn.toNow=function(t){return this.to(Ae(),t)},mn.get=function(t){return R(this[t=P(t)])?this[t]():this},mn.invalidAt=function(){return h(this).overflow},mn.isAfter=function(t,e){var n=x(t)?t:Ae(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=P(e)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},mn.isBefore=function(t,e){var n=x(t)?t:Ae(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=P(e)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},mn.isBetween=function(t,e,n,a){var r=x(t)?t:Ae(t),i=x(e)?e:Ae(e);return!!(this.isValid()&&r.isValid()&&i.isValid())&&("("===(a=a||"()")[0]?this.isAfter(r,n):!this.isBefore(r,n))&&(")"===a[1]?this.isBefore(i,n):!this.isAfter(i,n))},mn.isSame=function(t,e){var n,a=x(t)?t:Ae(t);return!(!this.isValid()||!a.isValid())&&("millisecond"===(e=P(e)||"millisecond")?this.valueOf()===a.valueOf():(n=a.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},mn.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},mn.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},mn.isValid=function(){return g(this)},mn.lang=nn,mn.locale=en,mn.localeData=an,mn.max=Ee,mn.min=De,mn.parsingFlags=function(){return f({},h(this))},mn.set=function(t,e){if("object"==typeof t)for(var n=function(t){var e=[];for(var n in t)e.push({unit:n,priority:q[n]});return e.sort(function(t,e){return t.priority-e.priority}),e}(t=M(t)),a=0;a<n.length;a++)this[n[a].unit](t[n[a].unit]);else if(R(this[t=P(t)]))return this[t](e);return this},mn.startOf=function(t){var e;if(void 0===(t=P(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?un:on;switch(t){case"year":e=n(this.year(),0,1);break;case"quarter":e=n(this.year(),this.month()-this.month()%3,1);break;case"month":e=n(this.year(),this.month(),1);break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=n(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=sn(e+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":e=this._d.valueOf(),e-=sn(e,6e4);break;case"second":e=this._d.valueOf(),e-=sn(e,1e3)}return this._d.setTime(e),r.updateOffset(this,!0),this},mn.subtract=Qe,mn.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},mn.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(t){if(!this.isValid())return null;var e=!0!==t,n=e?this.clone().utc():this;return n.year()<0||n.year()>9999?B(n,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):R(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",B(n,"Z")):B(n,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',a=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY";return this.format(n+a+"-MM-DD[T]HH:mm:ss.SSS"+e+'[")]')},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Nt,mn.isLeapYear=function(){return Ct(this.year())},mn.weekYear=function(t){return ln.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(t){return ln.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},mn.month=jt,mn.daysInMonth=function(){return Et(this.year(),this.month())},mn.week=mn.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},mn.isoWeek=mn.isoWeeks=function(t){var e=Bt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},mn.weeksInYear=function(){var t=this.localeData()._week;return Ut(this.year(),t.dow,t.doy)},mn.isoWeeksInYear=function(){return Ut(this.year(),1,4)},mn.date=dn,mn.day=mn.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=function(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}(t,this.localeData()),this.add(t-e,"d")):e},mn.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},mn.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=function(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},mn.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},mn.hour=mn.hours=ie,mn.minute=mn.minutes=fn,mn.second=mn.seconds=hn,mn.millisecond=mn.milliseconds=bn,mn.utcOffset=function(t,e,n){var a,i=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ge(ot,t)))return this}else Math.abs(t)<16&&!n&&(t*=60);return!this._isUTC&&e&&(a=Ve(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),i!==t&&(!e||this._changeInProgress?Xe(this,We(t-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,r.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?i:Ve(this)},mn.utc=function(t){return this.utcOffset(0,t)},mn.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Ve(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ge(st,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Ae(t).utcOffset():0,(this.utcOffset()-t)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=He,mn.isUTC=He,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=I("dates accessor is deprecated. Use date instead.",dn),mn.months=I("months accessor is deprecated. Use month instead",jt),mn.years=I("years accessor is deprecated. Use year instead",Nt),mn.zone=I("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),mn.isDSTShifted=I("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(y(t,this),(t=Ne(t))._a){var e=t._isUTC?p(t._a):Ae(t._a);this._isDSTShifted=this.isValid()&&S(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var vn=D.prototype;function _n(t,e,n,a){var r=pe(),i=p().set(a,e);return r[n](i,t)}function xn(t,e,n){if(u(t)&&(e=t,t=void 0),t=t||"",null!=e)return _n(t,e,n,"month");var a,r=[];for(a=0;a<12;a++)r[a]=_n(t,a,n,"month");return r}function Tn(t,e,n,a){"boolean"==typeof t?(u(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,u(e)&&(n=e,e=void 0),e=e||"");var r,i=pe(),s=t?i._week.dow:0;if(null!=n)return _n(e,(n+s)%7,a,"day");var o=[];for(r=0;r<7;r++)o[r]=_n(e,(r+s)%7,a,"day");return o}vn.calendar=function(t,e,n){var a=this._calendar[t]||this._calendar.sameElse;return R(a)?a.call(e,n):a},vn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},vn.invalidDate=function(){return this._invalidDate},vn.ordinal=function(t){return this._ordinal.replace("%d",t)},vn.preparse=yn,vn.postformat=yn,vn.relativeTime=function(t,e,n,a){var r=this._relativeTime[n];return R(r)?r(t,e,n,a):r.replace(/%d/i,t)},vn.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return R(n)?n(e):n.replace(/%s/i,e)},vn.set=function(t){var e,n;for(n in t)R(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},vn.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||Lt).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},vn.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Lt.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},vn.monthsParse=function(t,e,n){var a,r,i;if(this._monthsParseExact)return(function(t,e,n){var a,r,i,s=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],a=0;a<12;++a)i=p([2e3,a]),this._shortMonthsParse[a]=this.monthsShort(i,"").toLocaleLowerCase(),this._longMonthsParse[a]=this.months(i,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(r=kt.call(this._shortMonthsParse,s))?r:null:-1!==(r=kt.call(this._longMonthsParse,s))?r:null:"MMM"===e?-1!==(r=kt.call(this._shortMonthsParse,s))?r:-1!==(r=kt.call(this._longMonthsParse,s))?r:null:-1!==(r=kt.call(this._longMonthsParse,s))?r:-1!==(r=kt.call(this._shortMonthsParse,s))?r:null}).call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),a=0;a<12;a++){if(r=p([2e3,a]),n&&!this._longMonthsParse[a]&&(this._longMonthsParse[a]=new RegExp("^"+this.months(r,"").replace(".","")+"$","i"),this._shortMonthsParse[a]=new RegExp("^"+this.monthsShort(r,"").replace(".","")+"$","i")),n||this._monthsParse[a]||(i="^"+this.months(r,"")+"|^"+this.monthsShort(r,""),this._monthsParse[a]=new RegExp(i.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[a].test(t))return a;if(n&&"MMM"===e&&this._shortMonthsParse[a].test(t))return a;if(!n&&this._monthsParse[a].test(t))return a}},vn.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||Gt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=zt),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},vn.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||Gt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=Ft),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},vn.week=function(t){return Bt(t,this._week.dow,this._week.doy).week},vn.firstDayOfYear=function(){return this._week.doy},vn.firstDayOfWeek=function(){return this._week.dow},vn.weekdays=function(t,e){var n=i(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?Wt(n,this._week.dow):t?n[t.day()]:n},vn.weekdaysMin=function(t){return!0===t?Wt(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin},vn.weekdaysShort=function(t){return!0===t?Wt(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort},vn.weekdaysParse=function(t,e,n){var a,r,i;if(this._weekdaysParseExact)return(function(t,e,n){var a,r,i,s=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],a=0;a<7;++a)i=p([2e3,1]).day(a),this._minWeekdaysParse[a]=this.weekdaysMin(i,"").toLocaleLowerCase(),this._shortWeekdaysParse[a]=this.weekdaysShort(i,"").toLocaleLowerCase(),this._weekdaysParse[a]=this.weekdays(i,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(r=kt.call(this._weekdaysParse,s))?r:null:"ddd"===e?-1!==(r=kt.call(this._shortWeekdaysParse,s))?r:null:-1!==(r=kt.call(this._minWeekdaysParse,s))?r:null:"dddd"===e?-1!==(r=kt.call(this._weekdaysParse,s))?r:-1!==(r=kt.call(this._shortWeekdaysParse,s))?r:-1!==(r=kt.call(this._minWeekdaysParse,s))?r:null:"ddd"===e?-1!==(r=kt.call(this._shortWeekdaysParse,s))?r:-1!==(r=kt.call(this._weekdaysParse,s))?r:-1!==(r=kt.call(this._minWeekdaysParse,s))?r:null:-1!==(r=kt.call(this._minWeekdaysParse,s))?r:-1!==(r=kt.call(this._weekdaysParse,s))?r:-1!==(r=kt.call(this._shortWeekdaysParse,s))?r:null}).call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),a=0;a<7;a++){if(r=p([2e3,1]).day(a),n&&!this._fullWeekdaysParse[a]&&(this._fullWeekdaysParse[a]=new RegExp("^"+this.weekdays(r,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[a]=new RegExp("^"+this.weekdaysShort(r,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[a]=new RegExp("^"+this.weekdaysMin(r,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[a]||(i="^"+this.weekdays(r,"")+"|^"+this.weekdaysShort(r,"")+"|^"+this.weekdaysMin(r,""),this._weekdaysParse[a]=new RegExp(i.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[a].test(t))return a;if(n&&"ddd"===e&&this._shortWeekdaysParse[a].test(t))return a;if(n&&"dd"===e&&this._minWeekdaysParse[a].test(t))return a;if(!n&&this._weekdaysParse[a].test(t))return a}},vn.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||te.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=Xt),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},vn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||te.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Jt),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},vn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||te.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Qt),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},vn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},vn.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},de("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===w(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),r.lang=I("moment.lang is deprecated. Use moment.locale instead.",de),r.langData=I("moment.langData is deprecated. Use moment.localeData instead.",pe);var wn=Math.abs;function Sn(t,e,n,a){var r=We(e,n);return t._milliseconds+=a*r._milliseconds,t._days+=a*r._days,t._months+=a*r._months,t._bubble()}function On(t){return t<0?Math.floor(t):Math.ceil(t)}function In(t){return 4800*t/146097}function Cn(t){return 146097*t/4800}function kn(t){return function(){return this.as(t)}}var Nn=kn("ms"),Rn=kn("s"),An=kn("m"),Dn=kn("h"),En=kn("d"),Ln=kn("w"),Pn=kn("M"),Mn=kn("Q"),qn=kn("y");function jn(t){return function(){return this.isValid()?this._data[t]:NaN}}var Fn=jn("milliseconds"),zn=jn("seconds"),Gn=jn("minutes"),Yn=jn("hours"),Vn=jn("days"),Hn=jn("months"),Bn=jn("years"),Un=Math.round,Wn={ss:44,s:45,m:45,h:22,d:26,M:11},Kn=Math.abs;function $n(t){return(t>0)-(t<0)||+t}function Zn(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n=Kn(this._milliseconds)/1e3,a=Kn(this._days),r=Kn(this._months);t=T(n/60),e=T(t/60),n%=60,t%=60;var i=T(r/12),s=r%=12,o=a,u=e,c=t,l=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var f=d<0?"-":"",p=$n(this._months)!==$n(d)?"-":"",h=$n(this._days)!==$n(d)?"-":"",g=$n(this._milliseconds)!==$n(d)?"-":"";return f+"P"+(i?p+i+"Y":"")+(s?p+s+"M":"")+(o?h+o+"D":"")+(u||c||l?"T":"")+(u?g+u+"H":"")+(c?g+c+"M":"")+(l?g+l+"S":"")}var Xn=Me.prototype;return Xn.isValid=function(){return this._isValid},Xn.abs=function(){var t=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),t.milliseconds=wn(t.milliseconds),t.seconds=wn(t.seconds),t.minutes=wn(t.minutes),t.hours=wn(t.hours),t.months=wn(t.months),t.years=wn(t.years),this},Xn.add=function(t,e){return Sn(this,t,e,1)},Xn.subtract=function(t,e){return Sn(this,t,e,-1)},Xn.as=function(t){if(!this.isValid())return NaN;var e,n,a=this._milliseconds;if("month"===(t=P(t))||"quarter"===t||"year"===t)switch(n=this._months+In(e=this._days+a/864e5),t){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(e=this._days+Math.round(Cn(this._months)),t){case"week":return e/7+a/6048e5;case"day":return e+a/864e5;case"hour":return 24*e+a/36e5;case"minute":return 1440*e+a/6e4;case"second":return 86400*e+a/1e3;case"millisecond":return Math.floor(864e5*e)+a;default:throw new Error("Unknown unit "+t)}},Xn.asMilliseconds=Nn,Xn.asSeconds=Rn,Xn.asMinutes=An,Xn.asHours=Dn,Xn.asDays=En,Xn.asWeeks=Ln,Xn.asMonths=Pn,Xn.asQuarters=Mn,Xn.asYears=qn,Xn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*w(this._months/12):NaN},Xn._bubble=function(){var t,e,n,a,r,i=this._milliseconds,s=this._days,o=this._months,u=this._data;return i>=0&&s>=0&&o>=0||i<=0&&s<=0&&o<=0||(i+=864e5*On(Cn(o)+s),s=0,o=0),u.milliseconds=i%1e3,t=T(i/1e3),u.seconds=t%60,e=T(t/60),u.minutes=e%60,n=T(e/60),u.hours=n%24,s+=T(n/24),o+=r=T(In(s)),s-=On(Cn(r)),a=T(o/12),o%=12,u.days=s,u.months=o,u.years=a,this},Xn.clone=function(){return We(this)},Xn.get=function(t){return t=P(t),this.isValid()?this[t+"s"]():NaN},Xn.milliseconds=Fn,Xn.seconds=zn,Xn.minutes=Gn,Xn.hours=Yn,Xn.days=Vn,Xn.weeks=function(){return T(this.days()/7)},Xn.months=Hn,Xn.years=Bn,Xn.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=function(t,e,n){var a=We(t).abs(),r=Un(a.as("s")),i=Un(a.as("m")),s=Un(a.as("h")),o=Un(a.as("d")),u=Un(a.as("M")),c=Un(a.as("y")),l=r<=Wn.ss&&["s",r]||r<Wn.s&&["ss",r]||i<=1&&["m"]||i<Wn.m&&["mm",i]||s<=1&&["h"]||s<Wn.h&&["hh",s]||o<=1&&["d"]||o<Wn.d&&["dd",o]||u<=1&&["M"]||u<Wn.M&&["MM",u]||c<=1&&["y"]||["yy",c];return l[2]=e,l[3]=+t>0,l[4]=n,(function(t,e,n,a,r){return r.relativeTime(e||1,!!n,t,a)}).apply(null,l)}(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},Xn.toISOString=Zn,Xn.toString=Zn,Xn.toJSON=Zn,Xn.locale=en,Xn.localeData=an,Xn.toIsoString=I("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Zn),Xn.lang=nn,H("X",0,0,"unix"),H("x",0,0,"valueOf"),lt("x",it),lt("X",/[+-]?\d+(\.\d{1,3})?/),ht("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),ht("x",function(t,e,n){n._d=new Date(w(t))}),r.version="2.24.0",e=Ae,r.fn=mn,r.min=function(){return Le("isBefore",[].slice.call(arguments,0))},r.max=function(){return Le("isAfter",[].slice.call(arguments,0))},r.now=function(){return Date.now?Date.now():+new Date},r.utc=p,r.unix=function(t){return Ae(1e3*t)},r.months=function(t,e){return xn(t,e,"months")},r.isDate=c,r.locale=de,r.invalid=b,r.duration=We,r.isMoment=x,r.weekdays=function(t,e,n){return Tn(t,e,n,"weekdays")},r.parseZone=function(){return Ae.apply(null,arguments).parseZone()},r.localeData=pe,r.isDuration=qe,r.monthsShort=function(t,e){return xn(t,e,"monthsShort")},r.weekdaysMin=function(t,e,n){return Tn(t,e,n,"weekdaysMin")},r.defineLocale=fe,r.updateLocale=function(t,e){if(null!=e){var n,a,r=se;null!=(a=le(t))&&(r=a._config),(n=new D(e=A(r,e))).parentLocale=oe[t],oe[t]=n,de(t)}else null!=oe[t]&&(null!=oe[t].parentLocale?oe[t]=oe[t].parentLocale:null!=oe[t]&&delete oe[t]);return oe[t]},r.locales=function(){return C(oe)},r.weekdaysShort=function(t,e,n){return Tn(t,e,n,"weekdaysShort")},r.normalizeUnits=P,r.relativeTimeRounding=function(t){return void 0===t?Un:"function"==typeof t&&(Un=t,!0)},r.relativeTimeThreshold=function(t,e){return void 0!==Wn[t]&&(void 0===e?Wn[t]:(Wn[t]=e,"s"===t&&(Wn.ss=e-1),!0))},r.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},r.prototype=mn,r.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},r}()}).call(this,n("YuTi")(t))},wnGv:function(t,e,n){"use strict";n.d(e,"a",function(){return c});var a=n("CcnG"),r=n("gIcY"),i=n("LvDl"),s=n("QFaf"),o=n("DNAf"),u=n("a96k"),c=function(){function t(t){this.i18n=t,this.data=[],this.options=[],this.messages=new o.a({},this.i18n),this.customBadges=!1,this.customBadgeValidators=[],this.selection=new a.EventEmitter,this.Object=Object,this.filteredOptions=[]}return t.prototype.ngOnInit=function(){this.initFilter(),this.data.length>0&&this.initMissingOptions(),this.options=i.sortBy(this.options,["name"]),this.updateOptions()},t.prototype.initFilter=function(){this.filter=new r.i("",{validators:this.customBadgeValidators}),this.form=new s.a({filter:this.filter}),this.filteredOptions=(this.options||[]).slice()},t.prototype.initMissingOptions=function(){var t=this,e=this.options.map(function(t){return t.name});this.data.filter(function(t){return-1===e.indexOf(t)}).forEach(function(e){return t.addOption(e)}),this.forceOptionsToReflectData()},t.prototype.addOption=function(t){this.options.push(new u.a(!1,t,"")),this.options=i.sortBy(this.options,["name"]),this.triggerSelection(this.options.find(function(e){return e.name===t}))},t.prototype.triggerSelection=function(t){!t||this.selectionLimit&&!t.selected&&this.data.length>=this.selectionLimit||(t.selected=!t.selected,this.updateOptions(),this.selection.emit({option:t}))},t.prototype.updateOptions=function(){var t=this;this.data.splice(0,this.data.length),this.options.forEach(function(e){e.selected&&t.data.push(e.name)}),this.updateFilter()},t.prototype.updateFilter=function(){var t=this;this.filteredOptions=this.options.filter(function(e){return e.name.includes(t.filter.value)})},t.prototype.forceOptionsToReflectData=function(){var t=this;this.options.forEach(function(e){-1!==t.data.indexOf(e.name)&&(e.selected=!0)})},t.prototype.ngOnChanges=function(){this.filter&&this.updateFilter(),this.options&&this.data&&0!==this.data.length&&this.forceOptionsToReflectData()},t.prototype.selectOption=function(){0===this.filteredOptions.length?this.addCustomOption():(this.triggerSelection(this.filteredOptions[0]),this.resetFilter())},t.prototype.addCustomOption=function(){this.isCreatable()&&(this.addOption(this.filter.value),this.resetFilter())},t.prototype.isCreatable=function(){var t=this;return this.customBadges&&this.filter.valid&&this.filter.value.length>0&&this.filteredOptions.every(function(e){return e.name!==t.filter.value})},t.prototype.resetFilter=function(){this.filter.setValue(""),this.updateFilter()},t.prototype.removeItem=function(t){this.triggerSelection(this.options.find(function(e){return e.name===t&&e.selected}))},t}()},x38r:function(t,e,n){"use strict";var a;n.d(e,"a",function(){return a}),function(t){t.bold="bold",t.sparkline="sparkline",t.perSecond="perSecond",t.checkIcon="checkIcon",t.routerLink="routerLink",t.executing="executing",t.classAdding="classAdding",t.map="map"}(a||(a={}))},x6pH:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("he",{months:"\u05d9\u05e0\u05d5\u05d0\u05e8_\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05d9\u05dc_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8_\u05e1\u05e4\u05d8\u05de\u05d1\u05e8_\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8_\u05e0\u05d5\u05d1\u05de\u05d1\u05e8_\u05d3\u05e6\u05de\u05d1\u05e8".split("_"),monthsShort:"\u05d9\u05e0\u05d5\u05f3_\u05e4\u05d1\u05e8\u05f3_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05f3_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05f3_\u05e1\u05e4\u05d8\u05f3_\u05d0\u05d5\u05e7\u05f3_\u05e0\u05d5\u05d1\u05f3_\u05d3\u05e6\u05de\u05f3".split("_"),weekdays:"\u05e8\u05d0\u05e9\u05d5\u05df_\u05e9\u05e0\u05d9_\u05e9\u05dc\u05d9\u05e9\u05d9_\u05e8\u05d1\u05d9\u05e2\u05d9_\u05d7\u05de\u05d9\u05e9\u05d9_\u05e9\u05d9\u05e9\u05d9_\u05e9\u05d1\u05ea".split("_"),weekdaysShort:"\u05d0\u05f3_\u05d1\u05f3_\u05d2\u05f3_\u05d3\u05f3_\u05d4\u05f3_\u05d5\u05f3_\u05e9\u05f3".split("_"),weekdaysMin:"\u05d0_\u05d1_\u05d2_\u05d3_\u05d4_\u05d5_\u05e9".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [\u05d1]MMMM YYYY",LLL:"D [\u05d1]MMMM YYYY HH:mm",LLLL:"dddd, D [\u05d1]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[\u05d4\u05d9\u05d5\u05dd \u05d1\u05be]LT",nextDay:"[\u05de\u05d7\u05e8 \u05d1\u05be]LT",nextWeek:"dddd [\u05d1\u05e9\u05e2\u05d4] LT",lastDay:"[\u05d0\u05ea\u05de\u05d5\u05dc \u05d1\u05be]LT",lastWeek:"[\u05d1\u05d9\u05d5\u05dd] dddd [\u05d4\u05d0\u05d7\u05e8\u05d5\u05df \u05d1\u05e9\u05e2\u05d4] LT",sameElse:"L"},relativeTime:{future:"\u05d1\u05e2\u05d5\u05d3 %s",past:"\u05dc\u05e4\u05e0\u05d9 %s",s:"\u05de\u05e1\u05e4\u05e8 \u05e9\u05e0\u05d9\u05d5\u05ea",ss:"%d \u05e9\u05e0\u05d9\u05d5\u05ea",m:"\u05d3\u05e7\u05d4",mm:"%d \u05d3\u05e7\u05d5\u05ea",h:"\u05e9\u05e2\u05d4",hh:function(t){return 2===t?"\u05e9\u05e2\u05ea\u05d9\u05d9\u05dd":t+" \u05e9\u05e2\u05d5\u05ea"},d:"\u05d9\u05d5\u05dd",dd:function(t){return 2===t?"\u05d9\u05d5\u05de\u05d9\u05d9\u05dd":t+" \u05d9\u05de\u05d9\u05dd"},M:"\u05d7\u05d5\u05d3\u05e9",MM:function(t){return 2===t?"\u05d7\u05d5\u05d3\u05e9\u05d9\u05d9\u05dd":t+" \u05d7\u05d5\u05d3\u05e9\u05d9\u05dd"},y:"\u05e9\u05e0\u05d4",yy:function(t){return 2===t?"\u05e9\u05e0\u05ea\u05d9\u05d9\u05dd":t%10==0&&10!==t?t+" \u05e9\u05e0\u05d4":t+" \u05e9\u05e0\u05d9\u05dd"}},meridiemParse:/\u05d0\u05d7\u05d4"\u05e6|\u05dc\u05e4\u05e0\u05d4"\u05e6|\u05d0\u05d7\u05e8\u05d9 \u05d4\u05e6\u05d4\u05e8\u05d9\u05d9\u05dd|\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e6\u05d4\u05e8\u05d9\u05d9\u05dd|\u05dc\u05e4\u05e0\u05d5\u05ea \u05d1\u05d5\u05e7\u05e8|\u05d1\u05d1\u05d5\u05e7\u05e8|\u05d1\u05e2\u05e8\u05d1/i,isPM:function(t){return/^(\u05d0\u05d7\u05d4"\u05e6|\u05d0\u05d7\u05e8\u05d9 \u05d4\u05e6\u05d4\u05e8\u05d9\u05d9\u05dd|\u05d1\u05e2\u05e8\u05d1)$/.test(t)},meridiem:function(t,e,n){return t<5?"\u05dc\u05e4\u05e0\u05d5\u05ea \u05d1\u05d5\u05e7\u05e8":t<10?"\u05d1\u05d1\u05d5\u05e7\u05e8":t<12?n?'\u05dc\u05e4\u05e0\u05d4"\u05e6':"\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e6\u05d4\u05e8\u05d9\u05d9\u05dd":t<18?n?'\u05d0\u05d7\u05d4"\u05e6':"\u05d0\u05d7\u05e8\u05d9 \u05d4\u05e6\u05d4\u05e8\u05d9\u05d9\u05dd":"\u05d1\u05e2\u05e8\u05d1"}})}()},x8uC:function(t,e,n){"use strict";var a=n("CDJp"),r=n("K2E3"),i=n("RDha");a._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:i.noop,title:function(t,e){var n="",a=e.labels,r=a?a.length:0;if(t.length>0){var i=t[0];i.xLabel?n=i.xLabel:r>0&&i.index<r&&(n=a[i.index])}return n},afterTitle:i.noop,beforeBody:i.noop,beforeLabel:i.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:i.noop,afterBody:i.noop,beforeFooter:i.noop,footer:i.noop,afterFooter:i.noop}}});var s={average:function(t){if(!t.length)return!1;var e,n,a=0,r=0,i=0;for(e=0,n=t.length;e<n;++e){var s=t[e];if(s&&s.hasValue()){var o=s.tooltipPosition();a+=o.x,r+=o.y,++i}}return{x:Math.round(a/i),y:Math.round(r/i)}},nearest:function(t,e){var n,a,r,s=e.x,o=e.y,u=Number.POSITIVE_INFINITY;for(n=0,a=t.length;n<a;++n){var c=t[n];if(c&&c.hasValue()){var l=c.getCenterPoint(),d=i.distanceBetweenPoints(e,l);d<u&&(u=d,r=c)}}if(r){var f=r.tooltipPosition();s=f.x,o=f.y}return{x:s,y:o}}};function o(t,e){var n=i.color(t);return n.alpha(e*n.alpha()).rgbaString()}function u(t,e){return e&&(i.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function c(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function l(t){var e=a.global,n=i.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function d(t){return u([],c(t))}(t.exports=r.extend({initialize:function(){this._model=l(this._options),this._lastActive=[]},getTitle:function(){var t=this._options.callbacks,e=t.beforeTitle.apply(this,arguments),n=t.title.apply(this,arguments),a=t.afterTitle.apply(this,arguments),r=[];return r=u(r,c(e)),r=u(r,c(n)),u(r,c(a))},getBeforeBody:function(){return d(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var n=this,a=n._options.callbacks,r=[];return i.each(t,function(t){var i={before:[],lines:[],after:[]};u(i.before,c(a.beforeLabel.call(n,t,e))),u(i.lines,a.label.call(n,t,e)),u(i.after,c(a.afterLabel.call(n,t,e))),r.push(i)}),r},getAfterBody:function(){return d(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this._options.callbacks,e=t.beforeFooter.apply(this,arguments),n=t.footer.apply(this,arguments),a=t.afterFooter.apply(this,arguments),r=[];return r=u(r,c(e)),r=u(r,c(n)),u(r,c(a))},update:function(t){var e,n,a,r,o,u,c,d=this,f=d._options,p=d._model,h=d._model=l(f),g=d._active,b=d._data,m={xAlign:p.xAlign,yAlign:p.yAlign},y={x:p.x,y:p.y},v={width:p.width,height:p.height},_={x:p.caretX,y:p.caretY};if(g.length){h.opacity=1;var x=[],T=[];_=s[f.position].call(d,g,d._eventPosition);var w=[];for(e=0,n=g.length;e<n;++e)w.push((r=void 0,o=void 0,o=(a=g[e])._yScale||a._scale,u=a._index,c=a._datasetIndex,{xLabel:(r=a._xScale)?r.getLabelForIndex(u,c):"",yLabel:o?o.getLabelForIndex(u,c):"",index:u,datasetIndex:c,x:a._model.x,y:a._model.y}));f.filter&&(w=w.filter(function(t){return f.filter(t,b)})),f.itemSort&&(w=w.sort(function(t,e){return f.itemSort(t,e,b)})),i.each(w,function(t){x.push(f.callbacks.labelColor.call(d,t,d._chart)),T.push(f.callbacks.labelTextColor.call(d,t,d._chart))}),h.title=d.getTitle(w,b),h.beforeBody=d.getBeforeBody(w,b),h.body=d.getBody(w,b),h.afterBody=d.getAfterBody(w,b),h.footer=d.getFooter(w,b),h.x=Math.round(_.x),h.y=Math.round(_.y),h.caretPadding=f.caretPadding,h.labelColors=x,h.labelTextColors=T,h.dataPoints=w,v=function(t,e){var n=t._chart.ctx,a=2*e.yPadding,r=0,s=e.body,o=s.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0),u=e.title.length,c=e.footer.length,l=e.titleFontSize,d=e.bodyFontSize,f=e.footerFontSize;a+=u*l,a+=u?(u-1)*e.titleSpacing:0,a+=u?e.titleMarginBottom:0,a+=(o+=e.beforeBody.length+e.afterBody.length)*d,a+=o?(o-1)*e.bodySpacing:0,a+=c?e.footerMarginTop:0,a+=c*f,a+=c?(c-1)*e.footerSpacing:0;var p=0,h=function(t){r=Math.max(r,n.measureText(t).width+p)};return n.font=i.fontString(l,e._titleFontStyle,e._titleFontFamily),i.each(e.title,h),n.font=i.fontString(d,e._bodyFontStyle,e._bodyFontFamily),i.each(e.beforeBody.concat(e.afterBody),h),p=e.displayColors?d+2:0,i.each(s,function(t){i.each(t.before,h),i.each(t.lines,h),i.each(t.after,h)}),p=0,n.font=i.fontString(f,e._footerFontStyle,e._footerFontFamily),i.each(e.footer,h),{width:r+=2*e.xPadding,height:a}}(this,h),y=function(t,e,n,a){var r=t.x,i=t.y,s=t.caretPadding,o=n.xAlign,u=n.yAlign,c=t.caretSize+s,l=t.cornerRadius+s;return"right"===o?r-=e.width:"center"===o&&((r-=e.width/2)+e.width>a.width&&(r=a.width-e.width),r<0&&(r=0)),"top"===u?i+=c:i-="bottom"===u?e.height+c:e.height/2,"center"===u?"left"===o?r+=c:"right"===o&&(r-=c):"left"===o?r-=l:"right"===o&&(r+=l),{x:r,y:i}}(h,v,m=function(t,e){var n,a,r,i,s,o=t._model,u=t._chart,c=t._chart.chartArea,l="center",d="center";o.y<e.height?d="top":o.y>u.height-e.height&&(d="bottom");var f=(c.left+c.right)/2,p=(c.top+c.bottom)/2;"center"===d?(n=function(t){return t<=f},a=function(t){return t>f}):(n=function(t){return t<=e.width/2},a=function(t){return t>=u.width-e.width/2}),r=function(t){return t+e.width+o.caretSize+o.caretPadding>u.width},i=function(t){return t-e.width-o.caretSize-o.caretPadding<0},s=function(t){return t<=p?"top":"bottom"},n(o.x)?(l="left",r(o.x)&&(l="center",d=s(o.y))):a(o.x)&&(l="right",i(o.x)&&(l="center",d=s(o.y)));var h=t._options;return{xAlign:h.xAlign?h.xAlign:l,yAlign:h.yAlign?h.yAlign:d}}(this,v),d._chart)}else h.opacity=0;return h.xAlign=m.xAlign,h.yAlign=m.yAlign,h.x=y.x,h.y=y.y,h.width=v.width,h.height=v.height,h.caretX=_.x,h.caretY=_.y,d._model=h,t&&f.custom&&f.custom.call(d,h),d},drawCaret:function(t,e){var n=this._chart.ctx,a=this.getCaretPosition(t,e,this._view);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var a,r,i,s,o,u,c=n.caretSize,l=n.cornerRadius,d=n.xAlign,f=n.yAlign,p=t.x,h=t.y,g=e.width,b=e.height;if("center"===f)o=h+b/2,"left"===d?(r=(a=p)-c,i=a,s=o+c,u=o-c):(r=(a=p+g)+c,i=a,s=o-c,u=o+c);else if("left"===d?(a=(r=p+l+c)-c,i=r+c):"right"===d?(a=(r=p+g-l-c)-c,i=r+c):(a=(r=n.caretX)-c,i=r+c),"top"===f)o=(s=h)-c,u=s;else{o=(s=h+b)+c,u=s;var m=i;i=a,a=m}return{x1:a,x2:r,x3:i,y1:s,y2:o,y3:u}},drawTitle:function(t,e,n,a){var r=e.title;if(r.length){n.textAlign=e._titleAlign,n.textBaseline="top";var s,u,c=e.titleFontSize,l=e.titleSpacing;for(n.fillStyle=o(e.titleFontColor,a),n.font=i.fontString(c,e._titleFontStyle,e._titleFontFamily),s=0,u=r.length;s<u;++s)n.fillText(r[s],t.x,t.y),t.y+=c+l,s+1===r.length&&(t.y+=e.titleMarginBottom-l)}},drawBody:function(t,e,n,a){var r=e.bodyFontSize,s=e.bodySpacing,u=e.body;n.textAlign=e._bodyAlign,n.textBaseline="top",n.font=i.fontString(r,e._bodyFontStyle,e._bodyFontFamily);var c=0,l=function(e){n.fillText(e,t.x+c,t.y),t.y+=r+s};n.fillStyle=o(e.bodyFontColor,a),i.each(e.beforeBody,l);var d=e.displayColors;c=d?r+2:0,i.each(u,function(s,u){var c=o(e.labelTextColors[u],a);n.fillStyle=c,i.each(s.before,l),i.each(s.lines,function(i){d&&(n.fillStyle=o(e.legendColorBackground,a),n.fillRect(t.x,t.y,r,r),n.lineWidth=1,n.strokeStyle=o(e.labelColors[u].borderColor,a),n.strokeRect(t.x,t.y,r,r),n.fillStyle=o(e.labelColors[u].backgroundColor,a),n.fillRect(t.x+1,t.y+1,r-2,r-2),n.fillStyle=c),l(i)}),i.each(s.after,l)}),c=0,i.each(e.afterBody,l),t.y-=s},drawFooter:function(t,e,n,a){var r=e.footer;r.length&&(t.y+=e.footerMarginTop,n.textAlign=e._footerAlign,n.textBaseline="top",n.fillStyle=o(e.footerFontColor,a),n.font=i.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),i.each(r,function(a){n.fillText(a,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing}))},drawBackground:function(t,e,n,a,r){n.fillStyle=o(e.backgroundColor,r),n.strokeStyle=o(e.borderColor,r),n.lineWidth=e.borderWidth;var i=e.xAlign,s=e.yAlign,u=t.x,c=t.y,l=a.width,d=a.height,f=e.cornerRadius;n.beginPath(),n.moveTo(u+f,c),"top"===s&&this.drawCaret(t,a),n.lineTo(u+l-f,c),n.quadraticCurveTo(u+l,c,u+l,c+f),"center"===s&&"right"===i&&this.drawCaret(t,a),n.lineTo(u+l,c+d-f),n.quadraticCurveTo(u+l,c+d,u+l-f,c+d),"bottom"===s&&this.drawCaret(t,a),n.lineTo(u+f,c+d),n.quadraticCurveTo(u,c+d,u,c+d-f),"center"===s&&"left"===i&&this.drawCaret(t,a),n.lineTo(u,c+f),n.quadraticCurveTo(u,c,u+f,c),n.closePath(),n.fill(),e.borderWidth>0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},a={x:e.x,y:e.y},r=Math.abs(e.opacity<.001)?0:e.opacity;this._options.enabled&&(e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length)&&(this.drawBackground(a,e,t,n,r),a.x+=e.xPadding,a.y+=e.yPadding,this.drawTitle(a,e,t,r),this.drawBody(a,e,t,r),this.drawFooter(a,e,t,r))}},handleEvent:function(t){var e,n=this,a=n._options;return n._lastActive=n._lastActive||[],n._active="mouseout"===t.type?[]:n._chart.getElementsAtEventForMode(t,a.mode,a),(e=!i.arrayEquals(n._active,n._lastActive))&&(n._lastActive=n._active,(a.enabled||a.custom)&&(n._eventPosition={x:t.x,y:t.y},n.update(!0),n.pivot())),e}})).positioners=s},xMyE:function(t,e,n){"use strict";n.d(e,"a",function(){return o});var a=n("mrSG"),r=n("FFOo"),i=n("+umK"),s=n("2Bdj");function o(t,e,n){return function(a){return a.lift(new u(t,e,n))}}var u=function(){function t(t,e,n){this.nextOrObserver=t,this.error=e,this.complete=n}return t.prototype.call=function(t,e){return e.subscribe(new c(t,this.nextOrObserver,this.error,this.complete))},t}(),c=function(t){function e(e,n,a,r){var o=t.call(this,e)||this;return o._tapNext=i.a,o._tapError=i.a,o._tapComplete=i.a,o._tapError=a||i.a,o._tapComplete=r||i.a,Object(s.a)(n)?(o._context=o,o._tapNext=n):n&&(o._context=n,o._tapNext=n.next||i.a,o._tapError=n.error||i.a,o._tapComplete=n.complete||i.a),o}return a.__extends(e,t),e.prototype._next=function(t){try{this._tapNext.call(this._context,t)}catch(e){return void this.destination.error(e)}this.destination.next(t)},e.prototype._error=function(t){try{this._tapError.call(this._context,t)}catch(t){return void this.destination.error(t)}this.destination.error(t)},e.prototype._complete=function(){try{this._tapComplete.call(this._context)}catch(t){return void this.destination.error(t)}return this.destination.complete()},e}(r.a)},xSw7:function(t,e,n){"use strict";var a=n("CcnG"),r=n("Fgil"),i=n("aXbf"),s=n("o4+5"),o=n("Ip0R"),u=n("eajB"),c=n("lqqz"),l=n("NJnL");n("GgAd"),n.d(e,"a",function(){return d}),n.d(e,"b",function(){return p});var d=a["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function f(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,17,"table",[],null,null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,16,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275eld"](2,0,null,null,7,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,1,"td",[["class","text-left"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Used:\xa0"])),(t()(),a["\u0275eld"](5,0,null,null,4,"td",[["class","text-right"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,3,"strong",[],null,null,null,null,null)),(t()(),a["\u0275ted"](7,null,[" ",""])),a["\u0275ppd"](8,1),a["\u0275ppd"](9,1),(t()(),a["\u0275eld"](10,0,null,null,7,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](11,0,null,null,1,"td",[["class","text-left"]],null,null,null,null,null)),(t()(),a["\u0275ted"](-1,null,["Free:\xa0"])),(t()(),a["\u0275eld"](13,0,null,null,4,"td",[["class","'text-right"]],null,null,null,null,null)),(t()(),a["\u0275eld"](14,0,null,null,3,"strong",[],null,null,null,null,null)),(t()(),a["\u0275ted"](15,null,["",""])),a["\u0275ppd"](16,1),a["\u0275ppd"](17,1)],null,function(t,e){var n=e.component,r=a["\u0275unv"](e,7,0,n.isBinary?t(e,8,0,a["\u0275nov"](e.parent,0),n.used):t(e,9,0,a["\u0275nov"](e.parent,1),n.used));t(e,7,0,r);var i=a["\u0275unv"](e,15,0,n.isBinary?t(e,16,0,a["\u0275nov"](e.parent,0),n.total-n.used):t(e,17,0,a["\u0275nov"](e.parent,1),n.total-n.used));t(e,15,0,i)})}function p(t){return a["\u0275vid"](0,[a["\u0275pid"](0,r.a,[i.a]),a["\u0275pid"](0,s.a,[i.a]),a["\u0275pid"](0,o.DecimalPipe,[a.LOCALE_ID]),(t()(),a["\u0275and"](0,[["usageTooltipTpl",2]],null,0,null,f)),(t()(),a["\u0275eld"](4,16777216,null,null,6,"div",[["class","progress oaprogress"],["data-placement","left"]],[[1,"aria-describedby",0]],null,null,null,null)),a["\u0275did"](5,212992,null,0,u.c,[a.ViewContainerRef,c.a,u.a,a.ElementRef,a.Renderer2,l.a],{tooltip:[0,"tooltip"],placement:[1,"placement"]},null),(t()(),a["\u0275eld"](6,0,null,null,3,"div",[["class","progress-bar progress-bar-info"],["role","progressbar"]],[[4,"width",null]],null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,["","%"])),a["\u0275ppd"](9,2),(t()(),a["\u0275eld"](10,0,null,null,0,"div",[["class","progress-bar progress-bar-freespace"],["role","progressbar"]],[[4,"width",null]],null,null,null,null))],function(t,e){t(e,5,0,a["\u0275nov"](e,3),"left")},function(t,e){var n=e.component;t(e,4,0,a["\u0275nov"](e,5).ariaDescribedby),t(e,6,0,n.usedPercentage+"%");var r=a["\u0275unv"](e,8,0,t(e,9,0,a["\u0275nov"](e,2),n.usedPercentage,"1.0-"+n.decimals));t(e,8,0,r),t(e,10,0,n.freePercentage+"%")})}},xTla:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a="function"==typeof Symbol&&Symbol.observable||"@@observable"},xTzq:function(t,e,n){"use strict";n.d(e,"a",function(){return r}),n.d(e,"b",function(){return i});var a=n("LvDl");function r(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];switch(t.length){case 1:return(function(t){for(var e=0,n=Object.keys(t.prototype);e<n.length;e++){var a=n[e],r=Object.getOwnPropertyDescriptor(t.prototype,a);r.value instanceof Function&&(s(t.prototype,a,r),Object.defineProperty(t.prototype,a,r))}}).apply(this,t);case 3:return s.apply(this,t);default:throw new Error}}function i(t,e,n){var a="__ignore_"+e;Array.isArray(t[a])?t[a].push(n):t[a]=[n]}function s(t,e,n){void 0===n&&(n=Object.getOwnPropertyDescriptor(t,e));var r=n.value;n.value=function(){for(var n=t["__ignore_"+e]||[],i=[],s=0;s<arguments.length;s++)i[s]=a.isString(arguments[s])&&-1===n.indexOf(s)?encodeURIComponent(arguments[s]):arguments[s];return r.apply(this,i)}}},xXU7:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("6blF"),r=n("T1DM"),i=n("/21U");function s(t,e){return void 0===t&&(t=0),void 0===e&&(e=r.a),(!Object(i.a)(t)||t<0)&&(t=0),e&&"function"==typeof e.schedule||(e=r.a),new a.a(function(n){return n.add(e.schedule(o,t,{subscriber:n,counter:0,period:t})),n})}function o(t){var e=t.subscriber,n=t.counter,a=t.period;e.next(n),this.schedule({subscriber:e,counter:n+1,period:a},a)}},xZld:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("kQXf"),r=n("88/t"),i=n("58b6"),s=n("xk4V"),o=function(t){return t[t.NotStarted=0]="NotStarted",t[t.Loading=1]="Loading",t[t.Completed=2]="Completed",t}({});e.Tree=function(){function t(e,n,i){void 0===n&&(n=null),void 0===i&&(i=!1);var s=this;this._childrenLoadingState=o.NotStarted,this._childrenAsyncOnce=a.once(function(){return new r.Observable(function(e){setTimeout(function(){s._childrenLoadingState=o.Loading,s._loadChildren(function(n){s._children=(n||[]).map(function(e){return new t(e,s)}),s._childrenLoadingState=o.Completed,e.next(s.children),e.complete()})})})}),this.buildTreeFromModel(e,n,i||Array.isArray(e.children))}return t.isValueEmpty=function(t){return a.isEmpty(a.trim(t))},t.isRenamable=function(t){return a.has(t,"setName")&&a.isFunction(t.setName)&&a.has(t,"toString")&&a.isFunction(t.toString)&&t.toString!==Object.toString},t.cloneTreeShallow=function(e){var n=new t(Object.assign({},e.node));return n._children=e._children,n},t.applyNewValueToRenamable=function(t,e){var n=Object.assign({},t);return n.setName(e),n},t.prototype.buildTreeFromModel=function(e,n,r){var s=this;this.parent=n,this.node=Object.assign(a.omit(e,"children"),{settings:i.TreeModelSettings.merge(e,a.get(n,"node"))},{emitLoadNextLevel:!0===e.emitLoadNextLevel}),a.isFunction(this.node.loadChildren)?this._loadChildren=this.node.loadChildren:a.get(e,"children",[]).forEach(function(e,n){s._addChild(new t(e,s),n)}),Array.isArray(this._children)||(this._children=this.node.loadChildren||r?[]:null)},t.prototype.hasDeferredChildren=function(){return"function"==typeof this._loadChildren},t.prototype.loadingChildrenRequested=function(){this._childrenLoadingState=o.Loading},t.prototype.childrenAreBeingLoaded=function(){return this._childrenLoadingState===o.Loading},t.prototype.childrenWereLoaded=function(){return this._childrenLoadingState===o.Completed},t.prototype.canLoadChildren=function(){return this._childrenLoadingState===o.NotStarted&&this.foldingType===i.FoldingType.Expanded&&!!this._loadChildren},t.prototype.childrenShouldBeLoaded=function(){return!(this.childrenWereLoaded()||!this._loadChildren&&!0!==this.node.emitLoadNextLevel)},Object.defineProperty(t.prototype,"children",{get:function(){return this._children},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"childrenAsync",{get:function(){return this.canLoadChildren()?this._childrenAsyncOnce():r.Observable.of(this.children)},enumerable:!0,configurable:!0}),t.prototype.reloadChildren=function(){var e=this;this.childrenShouldBeLoaded()&&(this._childrenLoadingState=o.Loading,this._loadChildren(function(n){e._children=n&&n.map(function(n){return new t(n,e)}),e._childrenLoadingState=o.Completed}))},t.prototype.setChildren=function(e){var n=this;this._children=e&&e.map(function(e){return new t(e,n)}),this.childrenShouldBeLoaded()&&(this._childrenLoadingState=o.Completed)},t.prototype.createNode=function(e,n){void 0===n&&(n={value:""});var a=new t(n,this,e);return n.id||a.markAsNew(),a.id=a.id||s(),!this.childrenShouldBeLoaded()||this.childrenAreBeingLoaded()||this.childrenWereLoaded()?this.isLeaf()?this.addSibling(a):this.addChild(a):null},Object.defineProperty(t.prototype,"value",{get:function(){return this.node.value},set:function(e){if("string"==typeof e||t.isRenamable(e)){var n=""+e;this.node.value=t.isRenamable(this.value)?t.applyNewValueToRenamable(this.value,n):t.isValueEmpty(n)?this.node.value:n}},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"checked",{get:function(){return!!a.get(this.node.settings,"checked")},set:function(t){this.node.settings=Object.assign({},this.node.settings,{checked:t})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"checkedChildren",{get:function(){return this.hasLoadedChildern()?this.children.filter(function(t){return t.checked}):[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"selectionAllowed",{get:function(){var t=a.get(this.node.settings,"selectionAllowed");return!!a.isNil(t)||!!t},set:function(t){this.node.settings=Object.assign({},this.node.settings,{selectionAllowed:t})},enumerable:!0,configurable:!0}),t.prototype.hasLoadedChildern=function(){return!a.isEmpty(this.children)},t.prototype.loadedChildrenAmount=function(){return a.size(this.children)},t.prototype.checkedChildrenAmount=function(){return a.size(this.checkedChildren)},t.prototype.addSibling=function(t,e){return Array.isArray(a.get(this.parent,"children"))?this.parent.addChild(t,e):null},t.prototype.addChild=function(e,n){var a=this._addChild(t.cloneTreeShallow(e),n);return this._setFoldingType(),this.isNodeCollapsed()&&this.switchFoldingType(),a},t.prototype._addChild=function(t,e){return void 0===e&&(e=a.size(this._children)||0),t.parent=this,Array.isArray(this._children)?this._children.splice(e,0,t):this._children=[t],t},t.prototype.swapWithSibling=function(t){if(this.hasSibling(t)){var e=this.positionInParent;this.parent._children[t.positionInParent]=this,this.parent._children[e]=t}},Object.defineProperty(t.prototype,"positionInParent",{get:function(){return this.isRoot()?-1:this.parent.children?this.parent.children.indexOf(this):-1},enumerable:!0,configurable:!0}),t.prototype.isStatic=function(){return a.get(this.node.settings,"static",!1)},t.prototype.hasLeftMenu=function(){return!a.get(this.node.settings,"static",!1)&&a.get(this.node.settings,"leftMenu",!1)},t.prototype.hasRightMenu=function(){return!a.get(this.node.settings,"static",!1)&&a.get(this.node.settings,"rightMenu",!1)},t.prototype.isLeaf=function(){return!this.isBranch()},Object.defineProperty(t.prototype,"menuItems",{get:function(){return a.get(this.node.settings,"menuItems")},enumerable:!0,configurable:!0}),t.prototype.hasCustomMenu=function(){return!this.isStatic()&&!!a.get(this.node.settings,"menuItems",!1)},t.prototype.isBranch=function(){return!0===this.node.emitLoadNextLevel||Array.isArray(this._children)},t.prototype.hasChildren=function(){return!a.isEmpty(this._children)||this.childrenShouldBeLoaded()},t.prototype.isRoot=function(){return a.isNil(this.parent)},t.prototype.hasSibling=function(t){return!this.isRoot()&&a.includes(this.parent.children,t)},t.prototype.hasChild=function(t){return a.includes(this._children,t)},t.prototype.removeChild=function(t){if(this.hasChildren()){var e=this._children.findIndex(function(e){return e===t});e>=0&&this._children.splice(e,1),this._setFoldingType()}},t.prototype.removeItselfFromParent=function(){this.parent&&this.parent.removeChild(this)},t.prototype.switchFoldingType=function(){!this.isLeaf()&&this.hasChildren()&&(this.disableCollapseOnInit(),this.node._foldingType=this.isNodeExpanded()?i.FoldingType.Collapsed:i.FoldingType.Expanded)},t.prototype.isNodeExpanded=function(){return this.foldingType===i.FoldingType.Expanded},t.prototype.isNodeCollapsed=function(){return this.foldingType===i.FoldingType.Collapsed},t.prototype._setFoldingType=function(){this.node._foldingType=this.childrenShouldBeLoaded()?i.FoldingType.Collapsed:this._children&&!a.isEmpty(this._children)?this.isCollapsedOnInit()?i.FoldingType.Collapsed:i.FoldingType.Expanded:Array.isArray(this._children)?i.FoldingType.Empty:i.FoldingType.Leaf},Object.defineProperty(t.prototype,"foldingType",{get:function(){return this.node._foldingType||this._setFoldingType(),this.node._foldingType},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"foldingCssClass",{get:function(){return this.getCssClassesFromSettings()||this.foldingType.cssClass},enumerable:!0,configurable:!0}),t.prototype.getCssClassesFromSettings=function(){return this.node._foldingType||this._setFoldingType(),a.get(this.node.settings,this.node._foldingType===i.FoldingType.Collapsed?"cssClasses.collapsed":this.node._foldingType===i.FoldingType.Expanded?"cssClasses.expanded":this.node._foldingType===i.FoldingType.Empty?"cssClasses.empty":"cssClasses.leaf",null)},Object.defineProperty(t.prototype,"nodeTemplate",{get:function(){return this.getTemplateFromSettings()},enumerable:!0,configurable:!0}),t.prototype.getTemplateFromSettings=function(){return this.isLeaf()?a.get(this.node.settings,"templates.leaf",""):a.get(this.node.settings,"templates.node","")},Object.defineProperty(t.prototype,"leftMenuTemplate",{get:function(){return this.hasLeftMenu()?a.get(this.node.settings,"templates.leftMenu","<span></span>"):""},enumerable:!0,configurable:!0}),t.prototype.disableCollapseOnInit=function(){this.node.settings&&(this.node.settings.isCollapsedOnInit=!1)},t.prototype.isCollapsedOnInit=function(){return!!a.get(this.node.settings,"isCollapsedOnInit")},t.prototype.keepNodesInDOM=function(){return a.get(this.node.settings,"keepNodesInDOM")},t.prototype.isNew=function(){return this.node._status===i.TreeStatus.New},Object.defineProperty(t.prototype,"id",{get:function(){return a.get(this.node,"id")},set:function(t){this.node.id=t},enumerable:!0,configurable:!0}),t.prototype.markAsNew=function(){this.node._status=i.TreeStatus.New},t.prototype.isBeingRenamed=function(){return this.node._status===i.TreeStatus.IsBeingRenamed},t.prototype.markAsBeingRenamed=function(){this.node._status=i.TreeStatus.IsBeingRenamed},t.prototype.isModified=function(){return this.node._status===i.TreeStatus.Modified},t.prototype.markAsModified=function(){this.node._status=i.TreeStatus.Modified},t.prototype.toTreeModel=function(){var t=a.defaultsDeep(this.isLeaf()?{}:{children:[]},this.node);return this.children&&this.children.forEach(function(e){t.children.push(e.toTreeModel())}),t},t}()},xbqr:function(t,e,n){"use strict";var a=n("CcnG"),r=n("MdoF"),i=n("lTVp");n("9GXa"),n.d(e,"a",function(){return s}),n.d(e,"b",function(){return o});var s=a["\u0275crt"]({encapsulation:0,styles:[[".warning-panel-alert-icon[_ngcontent-%COMP%]{vertical-align:top;padding-right:15px}.warning-panel-alert-title[_ngcontent-%COMP%]{font-weight:700}"]],data:{}});function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,11,"alert",[["type","warning"]],null,null,null,r.c,r.b)),a["\u0275did"](1,114688,null,0,i.a,[i.b,a.ChangeDetectorRef],{type:[0,"type"]},null),(t()(),a["\u0275eld"](2,0,null,0,9,"table",[],null,null,null,null,null)),(t()(),a["\u0275eld"](3,0,null,null,8,"tbody",[],null,null,null,null,null)),(t()(),a["\u0275eld"](4,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](5,0,null,null,1,"td",[["class","warning-panel-alert-icon"],["rowspan","2"]],null,null,null,null,null)),(t()(),a["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-3x fa-warning alert-warning"]],null,null,null,null,null)),(t()(),a["\u0275eld"](7,0,null,null,1,"td",[["class","warning-panel-alert-title"]],null,null,null,null,null)),(t()(),a["\u0275ted"](8,null,[" "," "])),(t()(),a["\u0275eld"](9,0,null,null,2,"tr",[],null,null,null,null,null)),(t()(),a["\u0275eld"](10,0,null,null,1,"td",[["class","warning-panel-alert-text"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],function(t,e){t(e,1,0,"warning")},function(t,e){t(e,8,0,e.component.title)})}},xdbM:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata,i=n("CcnG"),s=n("WyAD"),o=function(){function t(t){this.labels=[],this.options={},this.chartClick=new i.EventEmitter,this.chartHover=new i.EventEmitter,this.initFlag=!1,this.element=t}return t.prototype.ngOnInit=function(){this.ctx=this.element.nativeElement.getContext("2d"),this.cvs=this.element.nativeElement,this.initFlag=!0,(this.data||this.datasets)&&this.refresh()},t.prototype.ngOnChanges=function(t){this.initFlag&&(t.hasOwnProperty("data")||t.hasOwnProperty("datasets")?(this.updateChartData(t.data?t.data.currentValue:t.datasets.currentValue),this.chart.update()):this.refresh())},t.prototype.ngOnDestroy=function(){this.chart&&(this.chart.destroy(),this.chart=void 0)},t.prototype.getChartBuilder=function(t){var e=this,n=this.getDatasets(),a=Object.assign({},this.options);return!1===this.legend&&(a.legend={display:!1}),a.hover=a.hover||{},a.hover.onHover||(a.hover.onHover=function(t){t&&!t.length||e.chartHover.emit({active:t})}),a.onClick||(a.onClick=function(t,n){e.chartClick.emit({event:t,active:n})}),new s.Chart(t,{type:this.chartType,data:{labels:this.labels,datasets:n},options:a})},t.prototype.updateChartData=function(t){Array.isArray(t[0].data)?this.chart.data.datasets.forEach(function(e,n){e.data=t[n].data,t[n].label&&(e.label=t[n].label)}):this.chart.data.datasets[0].data=t},t.prototype.getDatasets=function(){var t=this,e=void 0;if((!this.datasets||!this.datasets.length&&this.data&&this.data.length)&&(e=Array.isArray(this.data[0])?this.data.map(function(e,n){return{data:e,label:t.labels[n]||"Label "+n}}):[{data:this.data,label:"Label 0"}]),(this.datasets&&this.datasets.length||e&&e.length)&&(e=(this.datasets||e).map(function(e,n){var a=Object.assign({},e);return t.colors&&t.colors.length?Object.assign(a,t.colors[n]):Object.assign(a,function(t,e,n){return"pie"===t||"doughnut"===t?{backgroundColor:(a=f(n)).map(function(t){return u(t,.6)}),borderColor:a.map(function(){return"#fff"}),pointBackgroundColor:a.map(function(t){return u(t,1)}),pointBorderColor:a.map(function(){return"#fff"}),pointHoverBackgroundColor:a.map(function(t){return u(t,1)}),pointHoverBorderColor:a.map(function(t){return u(t,1)})}:"polarArea"===t?function(t){return{backgroundColor:t.map(function(t){return u(t,.6)}),borderColor:t.map(function(t){return u(t,1)}),hoverBackgroundColor:t.map(function(t){return u(t,.8)}),hoverBorderColor:t.map(function(t){return u(t,1)})}}(f(n)):"line"===t||"radar"===t?function(t){return{backgroundColor:u(t,.4),borderColor:u(t,1),pointBackgroundColor:u(t,1),pointBorderColor:"#fff",pointHoverBackgroundColor:"#fff",pointHoverBorderColor:u(t,.8)}}(d(e)):"bar"===t||"horizontalBar"===t?function(t){return{backgroundColor:u(t,.6),borderColor:u(t,1),hoverBackgroundColor:u(t,.8),hoverBorderColor:u(t,1)}}(d(e)):d(e);var a}(t.chartType,n,a.data.length)),a})),!e)throw new Error("ng-charts configuration error,\n data or datasets field are required to render char "+this.chartType);return e},t.prototype.refresh=function(){this.ngOnDestroy(),this.chart=this.getChartBuilder(this.ctx)},t.defaultColors=[[255,99,132],[54,162,235],[255,206,86],[231,233,237],[75,192,192],[151,187,205],[220,220,220],[247,70,74],[70,191,189],[253,180,92],[148,159,177],[77,83,96]],t}();function u(t,e){return"rgba("+t.concat(e).join(",")+")"}function c(t,e){return Math.floor(Math.random()*(e-t+1))+t}function l(){return[c(0,255),c(0,255),c(0,255)]}function d(t){return o.defaultColors[t]||l()}function f(t){for(var e=new Array(t),n=0;n<t;n++)e[n]=o.defaultColors[n]||l();return e}a([i.Input(),r("design:type",Array)],o.prototype,"data",void 0),a([i.Input(),r("design:type",Array)],o.prototype,"datasets",void 0),a([i.Input(),r("design:type",Array)],o.prototype,"labels",void 0),a([i.Input(),r("design:type",Object)],o.prototype,"options",void 0),a([i.Input(),r("design:type",String)],o.prototype,"chartType",void 0),a([i.Input(),r("design:type",Array)],o.prototype,"colors",void 0),a([i.Input(),r("design:type",Boolean)],o.prototype,"legend",void 0),a([i.Output(),r("design:type",i.EventEmitter)],o.prototype,"chartClick",void 0),a([i.Output(),r("design:type",i.EventEmitter)],o.prototype,"chartHover",void 0),o=a([i.Directive({selector:"canvas[baseChart]",exportAs:"base-chart"})],o),e.BaseChartDirective=o;var p=function(){return function(){}}();p=a([i.NgModule({declarations:[o],exports:[o],imports:[]})],p),e.ChartsModule=p},xk4V:function(t,e,n){var a=n("4fRq"),r=n("I2ZF");t.exports=function(t,e,n){var i=e&&n||0;"string"==typeof t&&(e="binary"===t?new Array(16):null,t=null);var s=(t=t||{}).random||(t.rng||a)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,e)for(var o=0;o<16;++o)e[i+o]=s[o];return e||r(s)}},xlPZ:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("KhEm");function r(t,e){return function(n){var r;if(r="function"==typeof t?t:function(){return t},"function"==typeof e)return n.lift(new i(r,e));var s=Object.create(n,a.b);return s.source=n,s.subjectFactory=r,s}}var i=function(){function t(t,e){this.subjectFactory=t,this.selector=e}return t.prototype.call=function(t,e){var n=this.selector,a=this.subjectFactory(),r=n(a).subscribe(t);return r.add(e.subscribe(a)),r},t}()},xtUU:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("CcnG"),r=n("Tff5"),i=(n("58b6"),n("xZld"));e.TreeComponent=function(){function t(t){this.treeService=t,this.nodeCreated=new a.EventEmitter,this.nodeRemoved=new a.EventEmitter,this.nodeRenamed=new a.EventEmitter,this.nodeSelected=new a.EventEmitter,this.nodeUnselected=new a.EventEmitter,this.nodeMoved=new a.EventEmitter,this.nodeExpanded=new a.EventEmitter,this.nodeCollapsed=new a.EventEmitter,this.loadNextLevel=new a.EventEmitter,this.nodeChecked=new a.EventEmitter,this.nodeUnchecked=new a.EventEmitter,this.menuItemSelected=new a.EventEmitter,this.subscriptions=[]}return t.prototype.ngOnChanges=function(e){this.tree=this.treeModel?new i.Tree(this.treeModel):t.EMPTY_TREE},t.prototype.ngOnInit=function(){var t=this;this.subscriptions.push(this.treeService.nodeRemoved$.subscribe(function(e){t.nodeRemoved.emit(e)})),this.subscriptions.push(this.treeService.nodeRenamed$.subscribe(function(e){t.nodeRenamed.emit(e)})),this.subscriptions.push(this.treeService.nodeCreated$.subscribe(function(e){t.nodeCreated.emit(e)})),this.subscriptions.push(this.treeService.nodeSelected$.subscribe(function(e){t.nodeSelected.emit(e)})),this.subscriptions.push(this.treeService.nodeUnselected$.subscribe(function(e){t.nodeUnselected.emit(e)})),this.subscriptions.push(this.treeService.nodeMoved$.subscribe(function(e){t.nodeMoved.emit(e)})),this.subscriptions.push(this.treeService.nodeExpanded$.subscribe(function(e){t.nodeExpanded.emit(e)})),this.subscriptions.push(this.treeService.nodeCollapsed$.subscribe(function(e){t.nodeCollapsed.emit(e)})),this.subscriptions.push(this.treeService.menuItemSelected$.subscribe(function(e){t.menuItemSelected.emit(e)})),this.subscriptions.push(this.treeService.loadNextLevel$.subscribe(function(e){t.loadNextLevel.emit(e)})),this.subscriptions.push(this.treeService.nodeChecked$.subscribe(function(e){t.nodeChecked.emit(e)})),this.subscriptions.push(this.treeService.nodeUnchecked$.subscribe(function(e){t.nodeUnchecked.emit(e)}))},t.prototype.getController=function(){return this.rootComponent.controller},t.prototype.getControllerByNodeId=function(t){return this.treeService.getController(t)},t.prototype.ngOnDestroy=function(){this.subscriptions.forEach(function(t){return t&&t.unsubscribe()})},t.EMPTY_TREE=new i.Tree({value:""}),t.decorators=[{type:a.Component,args:[{selector:"tree",template:'<tree-internal #rootComponent [tree]="tree" [settings]="settings" [template]="template"></tree-internal>',providers:[r.TreeService]}]}],t.propDecorators={treeModel:[{type:a.Input,args:["tree"]}],settings:[{type:a.Input}],nodeCreated:[{type:a.Output}],nodeRemoved:[{type:a.Output}],nodeRenamed:[{type:a.Output}],nodeSelected:[{type:a.Output}],nodeUnselected:[{type:a.Output}],nodeMoved:[{type:a.Output}],nodeExpanded:[{type:a.Output}],nodeCollapsed:[{type:a.Output}],loadNextLevel:[{type:a.Output}],nodeChecked:[{type:a.Output}],nodeUnchecked:[{type:a.Output}],menuItemSelected:[{type:a.Output}],rootComponent:[{type:a.ViewChild,args:["rootComponent"]}],template:[{type:a.ContentChild,args:[a.TemplateRef]}]},t}()},xtZt:function(t,e,n){"use strict";n.d(e,"a",function(){return c}),n.d(e,"b",function(){return d}),n.d(e,"c",function(){return f}),n.d(e,"d",function(){return p}),n.d(e,"e",function(){return g}),n.d(e,"f",function(){return l}),n.d(e,"g",function(){return h});var a=n("mrSG"),r=n("CcnG"),i=n("VnD/"),s=n("lqqz"),o=n("rpEJ"),u=n("NJnL"),c=function(){return function(){this.autoClose=!0,this.insideClick=!1}}(),l=function(){return function(){var t=this;this.direction="down",this.isOpenChange=new r.EventEmitter,this.isDisabledChange=new r.EventEmitter,this.toggleClick=new r.EventEmitter,this.dropdownMenu=new Promise(function(e){t.resolveDropdownMenu=e})}}(),d=function(){function t(t,e,n,a){var r=this;this._state=t,this.cd=e,this._renderer=n,this._element=a,this.isOpen=!1,this._subscription=t.isOpenChange.subscribe(function(t){r.isOpen=t;var e=r._element.nativeElement.querySelector(".dropdown-menu");e&&!Object(o.d)()&&(r._renderer.addClass(e,"show"),e.classList.contains("dropdown-menu-right")&&(r._renderer.setStyle(e,"left","auto"),r._renderer.setStyle(e,"right","0")),"up"===r.direction&&(r._renderer.setStyle(e,"top","auto"),r._renderer.setStyle(e,"transform","translateY(-101%)"))),r.cd.markForCheck(),r.cd.detectChanges()})}return Object.defineProperty(t.prototype,"direction",{get:function(){return this._state.direction},enumerable:!0,configurable:!0}),t.prototype._contains=function(t){return this._element.nativeElement.contains(t)},t.prototype.ngOnDestroy=function(){this._subscription.unsubscribe()},t}(),f=function(){function t(t,e,n,a,r,i){this._elementRef=t,this._renderer=e,this._viewContainerRef=n,this._cis=a,this._config=r,this._state=i,this._isInlineOpen=!1,this._subscriptions=[],this._isInited=!1,this._state.autoClose=this._config.autoClose,this._state.insideClick=this._config.insideClick,this._dropdown=this._cis.createLoader(this._elementRef,this._viewContainerRef,this._renderer).provide({provide:l,useValue:this._state}),this.onShown=this._dropdown.onShown,this.onHidden=this._dropdown.onHidden,this.isOpenChange=this._state.isOpenChange}return Object.defineProperty(t.prototype,"autoClose",{get:function(){return this._state.autoClose},set:function(t){this._state.autoClose=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"insideClick",{get:function(){return this._state.insideClick},set:function(t){this._state.insideClick=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isDisabled",{get:function(){return this._isDisabled},set:function(t){this._isDisabled=t,this._state.isDisabledChange.emit(t),t&&this.hide()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isOpen",{get:function(){return this._showInline?this._isInlineOpen:this._dropdown.isShown},set:function(t){t?this.show():this.hide()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isBs4",{get:function(){return!Object(o.d)()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"_showInline",{get:function(){return!this.container},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this._isInited||(this._isInited=!0,this._dropdown.listen({outsideClick:!1,triggers:this.triggers,show:function(){return t.show()}}),this._subscriptions.push(this._state.toggleClick.subscribe(function(e){return t.toggle(e)})),this._subscriptions.push(this._state.isDisabledChange.pipe(Object(i.a)(function(t){return t})).subscribe(function(e){return t.hide()})))},t.prototype.show=function(){var t=this;if(!this.isOpen&&!this.isDisabled)return this._showInline?(this._inlinedMenu||this._state.dropdownMenu.then(function(e){t._dropdown.attachInline(e.viewContainer,e.templateRef),t._inlinedMenu=t._dropdown._inlineViewRef,t.addBs4Polyfills()}).catch(),this.addBs4Polyfills(),this._isInlineOpen=!0,this.onShown.emit(!0),void this._state.isOpenChange.emit(!0)):void this._state.dropdownMenu.then(function(e){var n=t.dropup||void 0!==t.dropup&&t.dropup;t._state.direction=n?"up":"down";var a=t.placement||(n?"top start":"bottom start");t._dropdown.attach(d).to(t.container).position({attachment:a}).show({content:e.templateRef,placement:a}),t._state.isOpenChange.emit(!0)}).catch()},t.prototype.hide=function(){this.isOpen&&(this._showInline?(this.removeShowClass(),this.removeDropupStyles(),this._isInlineOpen=!1,this.onHidden.emit(!0)):this._dropdown.hide(),this._state.isOpenChange.emit(!1))},t.prototype.toggle=function(t){return this.isOpen||!t?this.hide():this.show()},t.prototype._contains=function(t){return this._elementRef.nativeElement.contains(t.target)||this._dropdown.instance&&this._dropdown.instance._contains(t.target)},t.prototype.ngOnDestroy=function(){var t,e;try{for(var n=Object(a.__values)(this._subscriptions),r=n.next();!r.done;r=n.next())r.value.unsubscribe()}catch(i){t={error:i}}finally{try{r&&!r.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}this._dropdown.dispose()},t.prototype.addBs4Polyfills=function(){Object(o.d)()||(this.addShowClass(),this.checkRightAlignment(),this.addDropupStyles())},t.prototype.addShowClass=function(){this._inlinedMenu&&this._inlinedMenu.rootNodes[0]&&this._renderer.addClass(this._inlinedMenu.rootNodes[0],"show")},t.prototype.removeShowClass=function(){this._inlinedMenu&&this._inlinedMenu.rootNodes[0]&&this._renderer.removeClass(this._inlinedMenu.rootNodes[0],"show")},t.prototype.checkRightAlignment=function(){if(this._inlinedMenu&&this._inlinedMenu.rootNodes[0]){var t=this._inlinedMenu.rootNodes[0].classList.contains("dropdown-menu-right");this._renderer.setStyle(this._inlinedMenu.rootNodes[0],"left",t?"auto":"0"),this._renderer.setStyle(this._inlinedMenu.rootNodes[0],"right",t?"0":"auto")}},t.prototype.addDropupStyles=function(){this._inlinedMenu&&this._inlinedMenu.rootNodes[0]&&(this._renderer.setStyle(this._inlinedMenu.rootNodes[0],"top",this.dropup?"auto":"100%"),this._renderer.setStyle(this._inlinedMenu.rootNodes[0],"transform",this.dropup?"translateY(-101%)":"translateY(0)"),this._renderer.setStyle(this._inlinedMenu.rootNodes[0],"bottom","auto"))},t.prototype.removeDropupStyles=function(){this._inlinedMenu&&this._inlinedMenu.rootNodes[0]&&(this._renderer.removeStyle(this._inlinedMenu.rootNodes[0],"top"),this._renderer.removeStyle(this._inlinedMenu.rootNodes[0],"transform"),this._renderer.removeStyle(this._inlinedMenu.rootNodes[0],"bottom"))},t}(),p=function(){return function(t,e,n){t.resolveDropdownMenu({templateRef:n,viewContainer:e})}}(),h=function(){function t(t,e,n,a,r){var i=this;this._changeDetectorRef=t,this._dropdown=e,this._element=n,this._renderer=a,this._state=r,this.isDisabled=null,this._subscriptions=[],this._subscriptions.push(this._state.isOpenChange.subscribe(function(t){i.isOpen=t,t?(i._documentClickListener=i._renderer.listen("document","click",function(t){!i._state.autoClose||2===t.button||i._element.nativeElement.contains(t.target)||i._state.insideClick&&i._dropdown._contains(t)||(i._state.toggleClick.emit(!1),i._changeDetectorRef.detectChanges())}),i._escKeyUpListener=i._renderer.listen(i._element.nativeElement,"keyup.esc",function(){i._state.autoClose&&(i._state.toggleClick.emit(!1),i._changeDetectorRef.detectChanges())})):(i._documentClickListener(),i._escKeyUpListener())})),this._subscriptions.push(this._state.isDisabledChange.subscribe(function(t){return i.isDisabled=t||null}))}return t.prototype.onClick=function(){this.isDisabled||this._state.toggleClick.emit(!0)},t.prototype.ngOnDestroy=function(){var t,e;this._documentClickListener&&this._documentClickListener(),this._escKeyUpListener&&this._escKeyUpListener();try{for(var n=Object(a.__values)(this._subscriptions),r=n.next();!r.done;r=n.next())r.value.unsubscribe()}catch(i){t={error:i}}finally{try{r&&!r.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}},t}(),g=function(){function t(){}return t.forRoot=function(e){return{ngModule:t,providers:[s.a,u.a,l,{provide:c,useValue:e||{autoClose:!0,insideClick:!1}}]}},t}()},y3By:function(t,e,n){"use strict";n.d(e,"a",function(){return r}),n.d(e,"b",function(){return i});var a=n("+umK");function r(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return i(t)}function i(t){return t?1===t.length?t[0]:function(e){return t.reduce(function(t,e){return e(t)},e)}:a.a}},y9Z7:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.selectRows=function(t,e,n){var a=n(e,t);return a>-1?t.splice(a,1):t.push(e),t},e.selectRowsBetween=function(t,e,n,a,r){for(var i=n<a,s=0;s<e.length;s++){var o;o=i?{start:n,end:a}:{start:a,end:n+1},(i&&s<=a&&s>=n||!i&&s>=a&&s<=n)&&s>=o.start&&s<=o.end&&t.push(e[s])}return t}},y9jh:function(t,e,n){var a;"undefined"!=typeof self&&self,a=function(t,e,n,a,r){return function(t){var e={};function n(a){if(e[a])return e[a].exports;var r=e[a]={i:a,l:!1,exports:{}};return t[a].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,a){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:a})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s="./src/index.ts")}({"./node_modules/css-loader/index.js!./node_modules/postcss-loader/index.js!./node_modules/sass-loader/lib/loader.js??ref--3-4!./src/components/datatable.component.scss":function(t,e,n){(t.exports=n("./node_modules/css-loader/lib/css-base.js")(!1)).push([t.i,".ngx-datatable {\n display: block;\n overflow: hidden;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n position: relative;\n -webkit-transform: translate3d(0, 0, 0);\n /**\n * Vertical Scrolling Adjustments\n */\n /**\n * Horizontal Scrolling Adjustments\n */\n /**\n * Fixed Header Height Adjustments\n */\n /**\n * Fixed row height adjustments\n */\n /**\n * Shared Styles\n */\n /**\n * Header Styles\n */\n /**\n * Body Styles\n */\n /**\n * Footer Styles\n */ }\n .ngx-datatable [hidden] {\n display: none !important; }\n .ngx-datatable *, .ngx-datatable *:before, .ngx-datatable *:after {\n -webkit-box-sizing: border-box;\n box-sizing: border-box; }\n .ngx-datatable.scroll-vertical .datatable-body {\n overflow-y: auto; }\n .ngx-datatable.scroll-vertical.virtualized .datatable-body .datatable-row-wrapper {\n position: absolute; }\n .ngx-datatable.scroll-horz .datatable-body {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch; }\n .ngx-datatable.fixed-header .datatable-header .datatable-header-inner {\n white-space: nowrap; }\n .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis; }\n .ngx-datatable.fixed-row .datatable-scroll {\n white-space: nowrap; }\n .ngx-datatable.fixed-row .datatable-scroll .datatable-body-row {\n white-space: nowrap; }\n .ngx-datatable.fixed-row .datatable-scroll .datatable-body-row .datatable-body-cell {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis; }\n .ngx-datatable.fixed-row .datatable-scroll .datatable-body-row .datatable-body-group-cell {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis; }\n .ngx-datatable .datatable-body-row,\n .ngx-datatable .datatable-row-center,\n .ngx-datatable .datatable-header-inner {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: horizontal;\n -webkit-box-direction: normal;\n -ms-flex-direction: row;\n flex-direction: row;\n -ms-flex-flow: row;\n -o-flex-flow: row;\n flex-flow: row; }\n .ngx-datatable .datatable-body-cell,\n .ngx-datatable .datatable-header-cell {\n overflow-x: hidden;\n vertical-align: top;\n display: inline-block;\n line-height: 1.625; }\n .ngx-datatable .datatable-body-cell:focus,\n .ngx-datatable .datatable-header-cell:focus {\n outline: none; }\n .ngx-datatable .datatable-row-left,\n .ngx-datatable .datatable-row-right {\n z-index: 9; }\n .ngx-datatable .datatable-row-left,\n .ngx-datatable .datatable-row-center,\n .ngx-datatable .datatable-row-group,\n .ngx-datatable .datatable-row-right {\n position: relative; }\n .ngx-datatable .datatable-header {\n display: block;\n overflow: hidden; }\n .ngx-datatable .datatable-header .datatable-header-inner {\n -webkit-box-align: stretch;\n -ms-flex-align: stretch;\n align-items: stretch;\n -webkit-align-items: stretch; }\n .ngx-datatable .datatable-header .datatable-header-cell {\n position: relative;\n display: inline-block; }\n .ngx-datatable .datatable-header .datatable-header-cell.sortable .datatable-header-cell-wrapper {\n cursor: pointer; }\n .ngx-datatable .datatable-header .datatable-header-cell.longpress .datatable-header-cell-wrapper {\n cursor: move; }\n .ngx-datatable .datatable-header .datatable-header-cell .sort-btn {\n line-height: 100%;\n vertical-align: middle;\n display: inline-block;\n cursor: pointer; }\n .ngx-datatable .datatable-header .datatable-header-cell .resize-handle, .ngx-datatable .datatable-header .datatable-header-cell .resize-handle--not-resizable {\n display: inline-block;\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n width: 5px;\n padding: 0 4px;\n visibility: hidden; }\n .ngx-datatable .datatable-header .datatable-header-cell .resize-handle {\n cursor: ew-resize; }\n .ngx-datatable .datatable-header .datatable-header-cell.resizeable:hover .resize-handle {\n visibility: visible; }\n .ngx-datatable .datatable-header .datatable-header-cell:hover .resize-handle--not-resizable {\n visibility: visible; }\n .ngx-datatable .datatable-header .datatable-header-cell .targetMarker {\n position: absolute;\n top: 0;\n bottom: 0; }\n .ngx-datatable .datatable-header .datatable-header-cell .targetMarker.dragFromLeft {\n right: 0; }\n .ngx-datatable .datatable-header .datatable-header-cell .targetMarker.dragFromRight {\n left: 0; }\n .ngx-datatable .datatable-header .datatable-header-cell .datatable-header-cell-template-wrap {\n height: inherit; }\n .ngx-datatable .datatable-body {\n position: relative;\n z-index: 10;\n display: block; }\n .ngx-datatable .datatable-body .datatable-scroll {\n display: inline-block; }\n .ngx-datatable .datatable-body .datatable-row-detail {\n overflow-y: hidden; }\n .ngx-datatable .datatable-body .datatable-row-wrapper {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column; }\n .ngx-datatable .datatable-body .datatable-body-row {\n outline: none; }\n .ngx-datatable .datatable-body .datatable-body-row > div {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex; }\n .ngx-datatable .datatable-footer {\n display: block;\n width: 100%; }\n .ngx-datatable .datatable-footer .datatable-footer-inner {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n width: 100%; }\n .ngx-datatable .datatable-footer .selected-count .page-count {\n -webkit-box-flex: 1;\n -ms-flex: 1 1 40%;\n flex: 1 1 40%; }\n .ngx-datatable .datatable-footer .selected-count .datatable-pager {\n -webkit-box-flex: 1;\n -ms-flex: 1 1 60%;\n flex: 1 1 60%; }\n .ngx-datatable .datatable-footer .page-count {\n -webkit-box-flex: 1;\n -ms-flex: 1 1 20%;\n flex: 1 1 20%; }\n .ngx-datatable .datatable-footer .datatable-pager {\n -webkit-box-flex: 1;\n -ms-flex: 1 1 80%;\n flex: 1 1 80%;\n text-align: right; }\n .ngx-datatable .datatable-footer .datatable-pager .pager,\n .ngx-datatable .datatable-footer .datatable-pager .pager li {\n padding: 0;\n margin: 0;\n display: inline-block;\n list-style: none; }\n .ngx-datatable .datatable-footer .datatable-pager .pager li, .ngx-datatable .datatable-footer .datatable-pager .pager li a {\n outline: none; }\n .ngx-datatable .datatable-footer .datatable-pager .pager li a {\n cursor: pointer;\n display: inline-block; }\n .ngx-datatable .datatable-footer .datatable-pager .pager li.disabled a {\n cursor: not-allowed; }\n",""])},"./node_modules/css-loader/lib/css-base.js":function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",a=t[3];if(!a)return n;if(e&&"function"==typeof btoa){var r="/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */",i=a.sources.map(function(t){return"/*# sourceURL="+a.sourceRoot+t+" */"});return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var a={},r=0;r<this.length;r++){var i=this[r][0];"number"==typeof i&&(a[i]=!0)}for(r=0;r<t.length;r++){var s=t[r];"number"==typeof s[0]&&a[s[0]]||(n&&!s[2]?s[2]=n:n&&(s[2]="("+s[2]+") and ("+n+")"),e.push(s))}},e}},"./node_modules/webpack/buildin/global.js":function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(a){"object"==typeof window&&(n=window)}t.exports=n},"./src/components/body/body-cell.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/utils/index.ts"),o=n("./src/types/index.ts");n("./src/events.ts"),e.DataTableBodyCellComponent=function(){function t(t,e){this.cd=e,this.activate=new i.EventEmitter,this.treeAction=new i.EventEmitter,this.isFocused=!1,this.onCheckboxChangeFn=this.onCheckboxChange.bind(this),this.activateFn=this.activate.emit.bind(this.activate),this.cellContext={onCheckboxChangeFn:this.onCheckboxChangeFn,activateFn:this.activateFn,row:this.row,group:this.group,value:this.value,column:this.column,rowHeight:this.rowHeight,isSelected:this.isSelected,rowIndex:this.rowIndex,treeStatus:this.treeStatus,onTreeAction:this.onTreeAction.bind(this)},this._element=t.nativeElement}return Object.defineProperty(t.prototype,"group",{get:function(){return this._group},set:function(t){this._group=t,this.cellContext.group=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowHeight",{get:function(){return this._rowHeight},set:function(t){this._rowHeight=t,this.cellContext.rowHeight=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSelected",{get:function(){return this._isSelected},set:function(t){this._isSelected=t,this.cellContext.isSelected=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"expanded",{get:function(){return this._expanded},set:function(t){this._expanded=t,this.cellContext.expanded=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowIndex",{get:function(){return this._rowIndex},set:function(t){this._rowIndex=t,this.cellContext.rowIndex=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"column",{get:function(){return this._column},set:function(t){this._column=t,this.cellContext.column=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"row",{get:function(){return this._row},set:function(t){this._row=t,this.cellContext.row=t,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"sorts",{get:function(){return this._sorts},set:function(t){this._sorts=t,this.calcSortDir=this.calcSortDir(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"treeStatus",{get:function(){return this._treeStatus},set:function(t){this._treeStatus="collapsed"!==t&&"expanded"!==t&&"loading"!==t&&"disabled"!==t?"collapsed":t,this.cellContext.treeStatus=this._treeStatus,this.checkValueUpdates(),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnCssClasses",{get:function(){var t="datatable-body-cell";if(this.column.cellClass)if("string"==typeof this.column.cellClass)t+=" "+this.column.cellClass;else if("function"==typeof this.column.cellClass){var e=this.column.cellClass({row:this.row,group:this.group,column:this.column,value:this.value,rowHeight:this.rowHeight});if("string"==typeof e)t+=e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}return this.sortDir||(t+=" sort-active"),this.isFocused&&(t+=" active"),this.sortDir===o.SortDirection.asc&&(t+=" sort-asc"),this.sortDir===o.SortDirection.desc&&(t+=" sort-desc"),t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"width",{get:function(){return this.column.width},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"minWidth",{get:function(){return this.column.minWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"maxWidth",{get:function(){return this.column.maxWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"height",{get:function(){var t=this.rowHeight;return isNaN(t)?t:t+"px"},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this.checkValueUpdates()},t.prototype.ngOnDestroy=function(){this.cellTemplate&&this.cellTemplate.clear()},t.prototype.checkValueUpdates=function(){var t="";if(this.row&&this.column){var e=this.column.$$valueGetter(this.row,this.column.prop),n=this.column.pipe;n?t=n.transform(e):void 0!==t&&(t=e)}else t="";this.value!==t&&(this.value=t,this.cellContext.value=t,this.sanitizedValue=null!=t?this.stripHtml(t):t,this.cd.markForCheck())},t.prototype.onFocus=function(){this.isFocused=!0},t.prototype.onBlur=function(){this.isFocused=!1},t.prototype.onClick=function(t){this.activate.emit({type:"click",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element})},t.prototype.onDblClick=function(t){this.activate.emit({type:"dblclick",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element})},t.prototype.onKeyDown=function(t){var e=t.keyCode;(e===s.Keys.return||e===s.Keys.down||e===s.Keys.up||e===s.Keys.left||e===s.Keys.right)&&t.target===this._element&&(t.preventDefault(),t.stopPropagation(),this.activate.emit({type:"keydown",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element}))},t.prototype.onCheckboxChange=function(t){this.activate.emit({type:"checkbox",event:t,row:this.row,group:this.group,rowHeight:this.rowHeight,column:this.column,value:this.value,cellElement:this._element,treeStatus:"collapsed"})},t.prototype.calcSortDir=function(t){var e=this;if(t){var n=t.find(function(t){return t.prop===e.column.prop});return n?n.dir:void 0}},t.prototype.stripHtml=function(t){return t.replace?t.replace(/<\/?[^>]+(>|$)/g,""):t},t.prototype.onTreeAction=function(){this.treeAction.emit(this.row)},t.prototype.calcLeftMargin=function(t,e){return t.isTreeColumn?e.level*(null!=t.treeLevelIndent?t.treeLevelIndent:50):0},a([i.Input(),r("design:type",Function)],t.prototype,"displayCheck",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"group",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowHeight",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"isSelected",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"expanded",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowIndex",null),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"column",null),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"row",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"sorts",null),a([i.Input(),r("design:type",String),r("design:paramtypes",[String])],t.prototype,"treeStatus",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"treeAction",void 0),a([i.ViewChild("cellTemplate",{read:i.ViewContainerRef}),r("design:type",i.ViewContainerRef)],t.prototype,"cellTemplate",void 0),a([i.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"columnCssClasses",null),a([i.HostBinding("style.width.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"width",null),a([i.HostBinding("style.minWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"minWidth",null),a([i.HostBinding("style.maxWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"maxWidth",null),a([i.HostBinding("style.height"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"height",null),a([i.HostListener("focus"),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",void 0)],t.prototype,"onFocus",null),a([i.HostListener("blur"),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",void 0)],t.prototype,"onBlur",null),a([i.HostListener("click",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onClick",null),a([i.HostListener("dblclick",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onDblClick",null),a([i.HostListener("keydown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onKeyDown",null),a([i.Component({selector:"datatable-body-cell",changeDetection:i.ChangeDetectionStrategy.OnPush,template:'\n <div class="datatable-body-cell-label"\n [style.margin-left.px]="calcLeftMargin(column, row)">\n <label\n *ngIf="column.checkboxable && (!displayCheck || displayCheck(row, column, value))"\n class="datatable-checkbox">\n <input\n type="checkbox"\n [checked]="isSelected"\n (click)="onCheckboxChange($event)"\n />\n </label>\n <ng-container *ngIf="column.isTreeColumn">\n <button *ngIf="!column.treeToggleTemplate"\n class="datatable-tree-button"\n [disabled]="treeStatus===\'disabled\'"\n (click)="onTreeAction()">\n <span>\n <i *ngIf="treeStatus===\'loading\'"\n class="icon datatable-icon-collapse"></i>\n <i *ngIf="treeStatus===\'collapsed\'"\n class="icon datatable-icon-up"></i>\n <i *ngIf="treeStatus===\'expanded\' ||\n treeStatus===\'disabled\'"\n class="icon datatable-icon-down"></i>\n </span>\n </button>\n <ng-template *ngIf="column.treeToggleTemplate"\n [ngTemplateOutlet]="column.treeToggleTemplate"\n [ngTemplateOutletContext]="{ cellContext: cellContext }">\n </ng-template>\n </ng-container>\n\n <span\n *ngIf="!column.cellTemplate"\n [title]="sanitizedValue"\n [innerHTML]="value">\n </span>\n <ng-template #cellTemplate\n *ngIf="column.cellTemplate"\n [ngTemplateOutlet]="column.cellTemplate"\n [ngTemplateOutletContext]="cellContext">\n </ng-template>\n </div>\n '}),r("design:paramtypes",[i.ElementRef,i.ChangeDetectorRef])],t)}()},"./src/components/body/body-group-header-template.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DatatableGroupHeaderTemplateDirective=function(){return a([i.Directive({selector:"[ngx-datatable-group-header-template]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/body/body-group-header.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/components/body/body-group-header-template.directive.ts");e.DatatableGroupHeaderDirective=function(){function t(){this.rowHeight=0,this.toggle=new i.EventEmitter}return t.prototype.toggleExpandGroup=function(t){this.toggle.emit({type:"group",value:t})},t.prototype.expandAllGroups=function(){this.toggle.emit({type:"all",value:!0})},t.prototype.collapseAllGroups=function(){this.toggle.emit({type:"all",value:!1})},a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),i.ContentChild(s.DatatableGroupHeaderTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"toggle",void 0),a([i.Directive({selector:"ngx-datatable-group-header"})],t)}()},"./src/components/body/body-row-wrapper.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");n("./src/events.ts"),e.DataTableRowWrapperComponent=function(){function t(t,e){this.cd=t,this.differs=e,this.rowContextmenu=new i.EventEmitter(!1),this.groupContext={group:this.row,expanded:this.expanded,rowIndex:this.rowIndex},this.rowContext={row:this.row,expanded:this.expanded,rowIndex:this.rowIndex},this._expanded=!1,this.rowDiffer=e.find({}).create()}return Object.defineProperty(t.prototype,"rowIndex",{get:function(){return this._rowIndex},set:function(t){this._rowIndex=t,this.rowContext.rowIndex=t,this.groupContext.rowIndex=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"expanded",{get:function(){return this._expanded},set:function(t){this._expanded=t,this.groupContext.expanded=t,this.rowContext.expanded=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this.rowDiffer.diff(this.row)&&(this.rowContext.row=this.row,this.groupContext.group=this.row,this.cd.markForCheck())},t.prototype.onContextmenu=function(t){this.rowContextmenu.emit({event:t,row:this.row})},t.prototype.getGroupHeaderStyle=function(){var t={};return t.transform="translate3d("+this.offsetX+"px, 0px, 0px)",t["backface-visibility"]="hidden",t.width=this.innerWidth,t},a([i.Input(),r("design:type",Number)],t.prototype,"innerWidth",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowDetail",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupHeader",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offsetX",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"detailRowHeight",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"row",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupedRows",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"rowContextmenu",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowIndex",null),a([i.Input(),r("design:type",Boolean),r("design:paramtypes",[Boolean])],t.prototype,"expanded",null),a([i.HostListener("contextmenu",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onContextmenu",null),a([i.Component({selector:"datatable-row-wrapper",changeDetection:i.ChangeDetectionStrategy.OnPush,template:'\n <div \n *ngIf="groupHeader && groupHeader.template"\n class="datatable-group-header"\n [ngStyle]="getGroupHeaderStyle()">\n <ng-template\n *ngIf="groupHeader && groupHeader.template"\n [ngTemplateOutlet]="groupHeader.template"\n [ngTemplateOutletContext]="groupContext">\n </ng-template>\n </div>\n <ng-content \n *ngIf="(groupHeader && groupHeader.template && expanded) || \n (!groupHeader || !groupHeader.template)">\n </ng-content>\n <div\n *ngIf="rowDetail && rowDetail.template && expanded"\n [style.height.px]="detailRowHeight"\n class="datatable-row-detail">\n <ng-template\n *ngIf="rowDetail && rowDetail.template"\n [ngTemplateOutlet]="rowDetail.template"\n [ngTemplateOutletContext]="rowContext">\n </ng-template>\n </div>\n ',host:{class:"datatable-row-wrapper"}}),r("design:paramtypes",[i.ChangeDetectorRef,i.KeyValueDiffers])],t)}()},"./src/components/body/body-row.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)},i=this&&this.__param||function(t,e){return function(n,a){e(n,a,t)}};Object.defineProperty(e,"__esModule",{value:!0});var s=n("@angular/core"),o=n("./src/utils/index.ts"),u=n("./src/services/index.ts");n("./src/events.ts"),e.DataTableBodyRowComponent=function(){function t(t,e,n,a){this.differs=t,this.scrollbarHelper=e,this.cd=n,this.treeStatus="collapsed",this.activate=new s.EventEmitter,this.treeAction=new s.EventEmitter,this._groupStyles={left:{},center:{},right:{}},this._element=a.nativeElement,this._rowDiffer=t.find({}).create()}return Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t,this.recalculateColumns(t),this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"innerWidth",{get:function(){return this._innerWidth},set:function(t){if(this._columns){var e=o.columnsByPin(this._columns);this._columnGroupWidths=o.columnGroupWidths(e,e)}this._innerWidth=t,this.recalculateColumns(),this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offsetX",{get:function(){return this._offsetX},set:function(t){this._offsetX=t,this.buildStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"cssClass",{get:function(){var t="datatable-body-row";if(this.isSelected&&(t+=" active"),this.rowIndex%2!=0&&(t+=" datatable-row-odd"),this.rowIndex%2==0&&(t+=" datatable-row-even"),this.rowClass){var e=this.rowClass(this.row);if("string"==typeof e)t+=" "+e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}return t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnsTotalWidths",{get:function(){return this._columnGroupWidths.total},enumerable:!0,configurable:!0}),t.prototype.ngDoCheck=function(){this._rowDiffer.diff(this.row)&&this.cd.markForCheck()},t.prototype.trackByGroups=function(t,e){return e.type},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.buildStylesByGroup=function(){this._groupStyles.left=this.calcStylesByGroup("left"),this._groupStyles.center=this.calcStylesByGroup("center"),this._groupStyles.right=this.calcStylesByGroup("right"),this.cd.markForCheck()},t.prototype.calcStylesByGroup=function(t){var e=this._columnGroupWidths,n=this.offsetX,a={width:e[t]+"px"};if("left"===t)o.translateXY(a,n,0);else if("right"===t){var r=parseInt(this.innerWidth+"",0);o.translateXY(a,-1*(e.total-r-n+this.scrollbarHelper.width),0)}return a},t.prototype.onActivate=function(t,e){t.cellIndex=e,t.rowElement=this._element,this.activate.emit(t)},t.prototype.onKeyDown=function(t){var e=t.keyCode;(e===o.Keys.return||e===o.Keys.down||e===o.Keys.up||e===o.Keys.left||e===o.Keys.right)&&t.target===this._element&&(t.preventDefault(),t.stopPropagation(),this.activate.emit({type:"keydown",event:t,row:this.row,rowElement:this._element}))},t.prototype.onMouseenter=function(t){this.activate.emit({type:"mouseenter",event:t,row:this.row,rowElement:this._element})},t.prototype.recalculateColumns=function(t){void 0===t&&(t=this.columns),this._columns=t;var e=o.columnsByPin(this._columns);this._columnsByPin=o.columnsByPinArr(this._columns),this._columnGroupWidths=o.columnGroupWidths(e,this._columns)},t.prototype.onTreeAction=function(){this.treeAction.emit()},a([s.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"innerWidth",null),a([s.Input(),r("design:type",Boolean)],t.prototype,"expanded",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"rowClass",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"row",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"group",void 0),a([s.Input(),r("design:type",Boolean)],t.prototype,"isSelected",void 0),a([s.Input(),r("design:type",Number)],t.prototype,"rowIndex",void 0),a([s.Input(),r("design:type",Object)],t.prototype,"displayCheck",void 0),a([s.Input(),r("design:type",String)],t.prototype,"treeStatus",void 0),a([s.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offsetX",null),a([s.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"cssClass",null),a([s.HostBinding("style.height.px"),s.Input(),r("design:type",Number)],t.prototype,"rowHeight",void 0),a([s.HostBinding("style.width.px"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"columnsTotalWidths",null),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"activate",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"treeAction",void 0),a([s.HostListener("keydown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onKeyDown",null),a([s.HostListener("mouseenter",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMouseenter",null),a([s.Component({selector:"datatable-body-row",changeDetection:s.ChangeDetectionStrategy.OnPush,template:'\n <div\n *ngFor="let colGroup of _columnsByPin; let i = index; trackBy: trackByGroups"\n class="datatable-row-{{colGroup.type}} datatable-row-group"\n [ngStyle]="_groupStyles[colGroup.type]">\n <datatable-body-cell\n *ngFor="let column of colGroup.columns; let ii = index; trackBy: columnTrackingFn"\n tabindex="-1"\n [row]="row"\n [group]="group"\n [expanded]="expanded"\n [isSelected]="isSelected"\n [rowIndex]="rowIndex"\n [column]="column"\n [rowHeight]="rowHeight"\n [displayCheck]="displayCheck"\n [treeStatus]="treeStatus"\n (activate)="onActivate($event, ii)"\n (treeAction)="onTreeAction()">\n </datatable-body-cell>\n </div>\n '}),i(1,s.SkipSelf()),r("design:paramtypes",[s.KeyValueDiffers,u.ScrollbarHelper,s.ChangeDetectorRef,s.ElementRef])],t)}()},"./src/components/body/body.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/utils/index.ts"),o=(n("./src/types/index.ts"),n("./src/components/body/scroller.component.ts"));e.DataTableBodyComponent=function(){function t(t){var e=this;this.cd=t,this.selected=[],this.scroll=new i.EventEmitter,this.page=new i.EventEmitter,this.activate=new i.EventEmitter,this.select=new i.EventEmitter,this.detailToggle=new i.EventEmitter,this.rowContextmenu=new i.EventEmitter(!1),this.treeAction=new i.EventEmitter,this.rowHeightsCache=new s.RowHeightCache,this.temp=[],this.offsetY=0,this.indexes={},this.rowIndexes=new Map,this.rowExpansions=new Map,this.getDetailRowHeight=function(t,n){if(!e.rowDetail)return 0;var a=e.rowDetail.rowHeight;return"function"==typeof a?a(t,n):a},this.rowTrackingFn=(function(t,e){var n=this.getRowIndex(e);return this.trackByProp?n+"-"+this.trackByProp:n}).bind(this)}return Object.defineProperty(t.prototype,"pageSize",{get:function(){return this._pageSize},set:function(t){this._pageSize=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rows",{get:function(){return this._rows},set:function(t){this._rows=t,this.rowExpansions.clear(),this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t;var e=s.columnsByPin(t);this.columnGroupWidths=s.columnGroupWidths(e,t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offset",{get:function(){return this._offset},set:function(t){this._offset=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rowCount",{get:function(){return this._rowCount},set:function(t){this._rowCount=t,this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bodyWidth",{get:function(){return this.scrollbarH?this.innerWidth+"px":"100%"},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bodyHeight",{get:function(){return this._bodyHeight},set:function(t){this._bodyHeight=this.scrollbarV?t+"px":"auto",this.recalcLayout()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"selectEnabled",{get:function(){return!!this.selectionType},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"scrollHeight",{get:function(){if(this.scrollbarV&&this.virtualization&&this.rowCount)return this.rowHeightsCache.query(this.rowCount-1)},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){var t=this;this.rowDetail&&(this.listener=this.rowDetail.toggle.subscribe(function(e){var n=e.type,a=e.value;"row"===n&&t.toggleRowExpansion(a),"all"===n&&t.toggleAllRows(a),t.updateIndexes(),t.updateRows(),t.cd.markForCheck()})),this.groupHeader&&(this.listener=this.groupHeader.toggle.subscribe(function(e){var n=e.type,a=e.value;"group"===n&&t.toggleRowExpansion(a),"all"===n&&t.toggleAllRows(a),t.updateIndexes(),t.updateRows(),t.cd.markForCheck()}))},t.prototype.ngOnDestroy=function(){this.rowDetail&&this.listener.unsubscribe(),this.groupHeader&&this.listener.unsubscribe()},t.prototype.updateOffsetY=function(t){this.scroller&&(this.scrollbarV&&this.virtualization&&t?t=this.rowHeightsCache.query(this.pageSize*t-1):this.scrollbarV&&!this.virtualization&&(t=0),this.scroller.setOffset(t||0))},t.prototype.onBodyScroll=function(t){var e=t.scrollYPos,n=t.scrollXPos;this.offsetY===e&&this.offsetX===n||this.scroll.emit({offsetY:e,offsetX:n}),this.offsetY=e,this.offsetX=n,this.updateIndexes(),this.updatePage(t.direction),this.updateRows()},t.prototype.updatePage=function(t){var e=this.indexes.first/this.pageSize;"up"===t?e=Math.ceil(e):"down"===t&&(e=Math.floor(e)),void 0===t||isNaN(e)||this.page.emit({offset:e})},t.prototype.updateRows=function(){var t=this.indexes,e=t.last,n=t.first,a=0,r=[];if(this.rowIndexes.clear(),this.groupedRows)for(;n<e&&n<this.groupedRows.length;)r[a]=this.groupedRows[n],a++,n++;else for(;n<e&&n<this.rowCount;){var i=this.rows[n];i&&(this.rowIndexes.set(i,n),r[a]=i),a++,n++}this.temp=r},t.prototype.getRowHeight=function(t){return"function"==typeof this.rowHeight?this.rowHeight(t):this.rowHeight},t.prototype.getGroupHeight=function(t){var e=0;if(t.value)for(var n=0;n<t.value.length;n++)e+=this.getRowAndDetailHeight(t.value[n]);return e},t.prototype.getRowAndDetailHeight=function(t){var e=this.getRowHeight(t);return 1===this.rowExpansions.get(t)&&(e+=this.getDetailRowHeight(t)),e},t.prototype.getRowsStyles=function(t){var e={};if(this.groupedRows&&(e.width=this.columnGroupWidths.total),this.scrollbarV&&this.virtualization){var n=0;if(this.groupedRows){var a=t[t.length-1];n=a?this.getRowIndex(a):0}else n=this.getRowIndex(t);var r=this.rowHeightsCache.query(n-1);s.translateXY(e,0,r)}return e},t.prototype.getBottomSummaryRowStyles=function(){if(!this.scrollbarV||!this.rows||!this.rows.length)return null;var t={position:"absolute"},e=this.rowHeightsCache.query(this.rows.length-1);return s.translateXY(t,0,e),t},t.prototype.hideIndicator=function(){var t=this;setTimeout(function(){return t.loadingIndicator=!1},500)},t.prototype.updateIndexes=function(){var t=0,e=0;if(this.scrollbarV)if(this.virtualization){var n=parseInt(this.bodyHeight,0);t=this.rowHeightsCache.getRowIndex(this.offsetY),e=this.rowHeightsCache.getRowIndex(n+this.offsetY)+1}else t=0,e=this.rowCount;else this.externalPaging||(t=Math.max(this.offset*this.pageSize,0)),e=Math.min(t+this.pageSize,this.rowCount);this.indexes={first:t,last:e}},t.prototype.refreshRowHeightCache=function(){!this.scrollbarV||this.scrollbarV&&!this.virtualization||(this.rowHeightsCache.clearCache(),this.rows&&this.rows.length&&this.rowHeightsCache.initCache({rows:this.rows,rowHeight:this.rowHeight,detailRowHeight:this.getDetailRowHeight,externalVirtual:this.scrollbarV&&this.externalPaging,rowCount:this.rowCount,rowIndexes:this.rowIndexes,rowExpansions:this.rowExpansions}))},t.prototype.getAdjustedViewPortIndex=function(){var t=this.indexes.first;return this.scrollbarV&&this.virtualization&&this.rowHeightsCache.query(t-1)<=this.offsetY?t-1:t},t.prototype.toggleRowExpansion=function(t){var e=this.getAdjustedViewPortIndex(),n=this.rowExpansions.get(t);if(this.scrollbarV&&this.virtualization){var a=this.getDetailRowHeight(t)*(n?-1:1),r=this.getRowIndex(t);this.rowHeightsCache.update(r,a)}n=n^=1,this.rowExpansions.set(t,n),this.detailToggle.emit({rows:[t],currentIndex:e})},t.prototype.toggleAllRows=function(t){this.rowExpansions.clear();for(var e=t?1:0,n=this.getAdjustedViewPortIndex(),a=0,r=this.rows;a<r.length;a++)this.rowExpansions.set(r[a],e);this.scrollbarV&&this.recalcLayout(),this.detailToggle.emit({rows:this.rows,currentIndex:n})},t.prototype.recalcLayout=function(){this.refreshRowHeightCache(),this.updateIndexes(),this.updateRows()},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.stylesByGroup=function(t){var e=this.columnGroupWidths,n=this.offsetX,a={width:e[t]+"px"};if("left"===t)s.translateXY(a,n,0);else if("right"===t){var r=parseInt(this.innerWidth+"",0);s.translateXY(a,-1*(e.total-r-n),0)}return a},t.prototype.getRowExpanded=function(t){if(0===this.rowExpansions.size&&this.groupExpansionDefault)for(var e=0,n=this.groupedRows;e<n.length;e++)this.rowExpansions.set(n[e],1);return 1===this.rowExpansions.get(t)},t.prototype.getRowIndex=function(t){return this.rowIndexes.get(t)||0},t.prototype.onTreeAction=function(t){this.treeAction.emit({row:t})},a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarV",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"loadingIndicator",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"externalPaging",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offsetX",void 0),a([i.Input(),r("design:type",String)],t.prototype,"emptyMessage",void 0),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Array)],t.prototype,"selected",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowIdentity",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowDetail",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupHeader",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectCheck",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"displayCheck",void 0),a([i.Input(),r("design:type",String)],t.prototype,"trackByProp",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowClass",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"groupedRows",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"groupExpansionDefault",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"innerWidth",void 0),a([i.Input(),r("design:type",String)],t.prototype,"groupRowsBy",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"virtualization",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"summaryRow",void 0),a([i.Input(),r("design:type",String)],t.prototype,"summaryPosition",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"summaryHeight",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"pageSize",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"rows",null),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"columns",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"offset",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"rowCount",null),a([i.HostBinding("style.width"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"bodyWidth",null),a([i.Input(),i.HostBinding("style.height"),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"bodyHeight",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"scroll",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"page",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"detailToggle",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"rowContextmenu",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"treeAction",void 0),a([i.ViewChild(o.ScrollerComponent),r("design:type",o.ScrollerComponent)],t.prototype,"scroller",void 0),a([i.Component({selector:"datatable-body",template:'\n <datatable-selection\n #selector\n [selected]="selected"\n [rows]="rows"\n [selectCheck]="selectCheck"\n [selectEnabled]="selectEnabled"\n [selectionType]="selectionType"\n [rowIdentity]="rowIdentity"\n (select)="select.emit($event)"\n (activate)="activate.emit($event)">\n <datatable-progress\n *ngIf="loadingIndicator">\n </datatable-progress>\n <datatable-scroller\n *ngIf="rows?.length"\n [scrollbarV]="scrollbarV"\n [scrollbarH]="scrollbarH"\n [scrollHeight]="scrollHeight"\n [scrollWidth]="columnGroupWidths?.total"\n (scroll)="onBodyScroll($event)">\n <datatable-summary-row\n *ngIf="summaryRow && summaryPosition === \'top\'"\n [rowHeight]="summaryHeight"\n [offsetX]="offsetX"\n [innerWidth]="innerWidth"\n [rows]="rows"\n [columns]="columns">\n </datatable-summary-row>\n <datatable-row-wrapper\n [groupedRows]="groupedRows"\n *ngFor="let group of temp; let i = index; trackBy: rowTrackingFn;"\n [innerWidth]="innerWidth"\n [ngStyle]="getRowsStyles(group)"\n [rowDetail]="rowDetail"\n [groupHeader]="groupHeader"\n [offsetX]="offsetX"\n [detailRowHeight]="getDetailRowHeight(group[i],i)"\n [row]="group"\n [expanded]="getRowExpanded(group)"\n [rowIndex]="getRowIndex(group[i])"\n (rowContextmenu)="rowContextmenu.emit($event)">\n <datatable-body-row\n *ngIf="!groupedRows; else groupedRowsTemplate"\n tabindex="-1"\n [isSelected]="selector.getRowSelected(group)"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="columns"\n [rowHeight]="getRowHeight(group)"\n [row]="group"\n [rowIndex]="getRowIndex(group)"\n [expanded]="getRowExpanded(group)"\n [rowClass]="rowClass"\n [displayCheck]="displayCheck"\n [treeStatus]="group.treeStatus"\n (treeAction)="onTreeAction(group)"\n (activate)="selector.onActivate($event, indexes.first + i)">\n </datatable-body-row>\n <ng-template #groupedRowsTemplate>\n <datatable-body-row\n *ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn;"\n tabindex="-1"\n [isSelected]="selector.getRowSelected(row)"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="columns"\n [rowHeight]="getRowHeight(row)"\n [row]="row"\n [group]="group.value"\n [rowIndex]="getRowIndex(row)"\n [expanded]="getRowExpanded(row)"\n [rowClass]="rowClass"\n (activate)="selector.onActivate($event, i)">\n </datatable-body-row>\n </ng-template>\n </datatable-row-wrapper>\n <datatable-summary-row\n *ngIf="summaryRow && summaryPosition === \'bottom\'"\n [ngStyle]="getBottomSummaryRowStyles()"\n [rowHeight]="summaryHeight"\n [offsetX]="offsetX"\n [innerWidth]="innerWidth"\n [rows]="rows"\n [columns]="columns">\n </datatable-summary-row>\n </datatable-scroller>\n <div\n class="empty-row"\n *ngIf="!rows?.length && !loadingIndicator"\n [innerHTML]="emptyMessage">\n </div>\n </datatable-selection>\n ',changeDetection:i.ChangeDetectionStrategy.OnPush,host:{class:"datatable-body"}}),r("design:paramtypes",[i.ChangeDetectorRef])],t)}()},"./src/components/body/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/body/body.component.ts")),a(n("./src/components/body/body-cell.component.ts")),a(n("./src/components/body/body-row.component.ts")),a(n("./src/components/body/progress-bar.component.ts")),a(n("./src/components/body/scroller.component.ts")),a(n("./src/components/body/body-row-wrapper.component.ts")),a(n("./src/components/body/selection.component.ts")),a(n("./src/components/body/body-group-header.directive.ts")),a(n("./src/components/body/body-group-header-template.directive.ts")),a(n("./src/components/body/summary/index.ts"))},"./src/components/body/progress-bar.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s};Object.defineProperty(e,"__esModule",{value:!0});var r=n("@angular/core");e.ProgressBarComponent=function(){return a([r.Component({selector:"datatable-progress",template:'\n <div class="progress-linear" role="progressbar">\n <div class="container">\n <div class="bar"></div>\n </div>\n </div>\n ',changeDetection:r.ChangeDetectionStrategy.OnPush})],function(){})}()},"./src/components/body/scroller.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.ScrollerComponent=function(){function t(t,e,n){this.ngZone=t,this.renderer=n,this.scrollbarV=!1,this.scrollbarH=!1,this.scroll=new i.EventEmitter,this.scrollYPos=0,this.scrollXPos=0,this.prevScrollYPos=0,this.prevScrollXPos=0,this.element=e.nativeElement}return t.prototype.ngOnInit=function(){if(this.scrollbarV||this.scrollbarH){var t=this.renderer;this.parentElement=t.parentNode(t.parentNode(this.element)),this.parentElement.addEventListener("scroll",this.onScrolled.bind(this))}},t.prototype.ngOnDestroy=function(){(this.scrollbarV||this.scrollbarH)&&this.parentElement.removeEventListener("scroll",this.onScrolled.bind(this))},t.prototype.setOffset=function(t){this.parentElement&&(this.parentElement.scrollTop=t)},t.prototype.onScrolled=function(t){var e=this,n=t.currentTarget;requestAnimationFrame(function(){e.scrollYPos=n.scrollTop,e.scrollXPos=n.scrollLeft,e.updateOffset()})},t.prototype.updateOffset=function(){var t;this.scrollYPos<this.prevScrollYPos?t="down":this.scrollYPos>this.prevScrollYPos&&(t="up"),this.scroll.emit({direction:t,scrollYPos:this.scrollYPos,scrollXPos:this.scrollXPos}),this.prevScrollYPos=this.scrollYPos,this.prevScrollXPos=this.scrollXPos},a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarV",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"scrollbarH",void 0),a([i.HostBinding("style.height.px"),i.Input(),r("design:type",Number)],t.prototype,"scrollHeight",void 0),a([i.HostBinding("style.width.px"),i.Input(),r("design:type",Number)],t.prototype,"scrollWidth",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"scroll",void 0),a([i.Component({selector:"datatable-scroller",template:"\n <ng-content></ng-content>\n ",host:{class:"datatable-scroll"},changeDetection:i.ChangeDetectionStrategy.OnPush}),r("design:paramtypes",[i.NgZone,i.ElementRef,i.Renderer2])],t)}()},"./src/components/body/selection.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/utils/index.ts"),o=n("./src/types/index.ts");e.DataTableSelectionComponent=function(){function t(){this.activate=new i.EventEmitter,this.select=new i.EventEmitter}return t.prototype.selectRow=function(t,e,n){var a;if(this.selectEnabled){var r=this.selectionType===o.SelectionType.checkbox,i=this.selectionType===o.SelectionType.multiClick,u=[];u=this.selectionType===o.SelectionType.multi||r||i?t.shiftKey?s.selectRowsBetween([],this.rows,e,this.prevIndex,this.getRowSelectedIdx.bind(this)):s.selectRows(t.ctrlKey||t.metaKey||i||r?this.selected.slice():[],n,this.getRowSelectedIdx.bind(this)):s.selectRows([],n,this.getRowSelectedIdx.bind(this)),"function"==typeof this.selectCheck&&(u=u.filter(this.selectCheck.bind(this))),this.selected.splice(0,this.selected.length),(a=this.selected).push.apply(a,u),this.prevIndex=e,this.select.emit({selected:u})}},t.prototype.onActivate=function(t,e){var n=t.type,a=t.event,r=t.row,i=this.selectionType===o.SelectionType.checkbox;!i&&("click"===n||"dblclick"===n)||i&&"checkbox"===n?this.selectRow(a,e,r):"keydown"===n&&(a.keyCode===s.Keys.return?this.selectRow(a,e,r):this.onKeyboardFocus(t)),this.activate.emit(t)},t.prototype.onKeyboardFocus=function(t){var e=t.event.keyCode;if(e===s.Keys.up||e===s.Keys.down||e===s.Keys.right||e===s.Keys.left){var n=this.selectionType===o.SelectionType.cell;t.cellElement&&n?n&&this.focusCell(t.cellElement,t.rowElement,e,t.cellIndex):this.focusRow(t.rowElement,e)}},t.prototype.focusRow=function(t,e){var n=this.getPrevNextRow(t,e);n&&n.focus()},t.prototype.getPrevNextRow=function(t,e){var n=t.parentElement;if(n){var a=void 0;if(e===s.Keys.up?a=n.previousElementSibling:e===s.Keys.down&&(a=n.nextElementSibling),a&&a.children.length)return a.children[0]}},t.prototype.focusCell=function(t,e,n,a){var r;if(n===s.Keys.left)r=t.previousElementSibling;else if(n===s.Keys.right)r=t.nextElementSibling;else if(n===s.Keys.up||n===s.Keys.down){var i=this.getPrevNextRow(e,n);if(i){var o=i.getElementsByClassName("datatable-body-cell");o.length&&(r=o[a])}}r&&r.focus()},t.prototype.getRowSelected=function(t){return this.getRowSelectedIdx(t,this.selected)>-1},t.prototype.getRowSelectedIdx=function(t,e){var n=this;if(!e||!e.length)return-1;var a=this.rowIdentity(t);return e.findIndex(function(t){return n.rowIdentity(t)===a})},a([i.Input(),r("design:type",Array)],t.prototype,"rows",void 0),a([i.Input(),r("design:type",Array)],t.prototype,"selected",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"selectEnabled",void 0),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"rowIdentity",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectCheck",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"activate",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Component({selector:"datatable-selection",template:"\n <ng-content></ng-content>\n ",changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},"./src/components/body/summary/index.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}(n("./src/components/body/summary/summary-row.component.ts"))},"./src/components/body/summary/summary-row.component.ts":function(t,e,n){"use strict";var a=this&&this.__assign||function(){return(a=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)},r=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},i=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var s=n("@angular/core");function o(t){var e=t.filter(function(t){return!!t});return e.length?e.some(function(t){return"number"!=typeof t})?null:e.reduce(function(t,e){return t+e}):null}function u(t){return null}e.DataTableSummaryRowComponent=function(){function t(){this.summaryRow={}}return t.prototype.ngOnChanges=function(){this.columns&&this.rows&&(this.updateInternalColumns(),this.updateValues())},t.prototype.updateInternalColumns=function(){this._internalColumns=this.columns.map(function(t){return a({},t,{cellTemplate:t.summaryTemplate})})},t.prototype.updateValues=function(){var t=this;this.summaryRow={},this.columns.filter(function(t){return!t.summaryTemplate}).forEach(function(e){var n=t.rows.map(function(t){return t[e.prop]}),a=t.getSummaryFunction(e);t.summaryRow[e.prop]=e.pipe?e.pipe.transform(a(n)):a(n)})},t.prototype.getSummaryFunction=function(t){return void 0===t.summaryFunc?o:null===t.summaryFunc?u:t.summaryFunc},r([s.Input(),i("design:type",Array)],t.prototype,"rows",void 0),r([s.Input(),i("design:type",Array)],t.prototype,"columns",void 0),r([s.Input(),i("design:type",Number)],t.prototype,"rowHeight",void 0),r([s.Input(),i("design:type",Number)],t.prototype,"offsetX",void 0),r([s.Input(),i("design:type",Number)],t.prototype,"innerWidth",void 0),r([s.Component({selector:"datatable-summary-row",template:'\n <datatable-body-row\n *ngIf="summaryRow && _internalColumns"\n tabindex="-1"\n [innerWidth]="innerWidth"\n [offsetX]="offsetX"\n [columns]="_internalColumns"\n [rowHeight]="rowHeight"\n [row]="summaryRow"\n [rowIndex]="-1">\n </datatable-body-row>\n ',host:{class:"datatable-summary-row"}})],t)}()},"./src/components/columns/column-cell.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DataTableColumnCellDirective=function(){return a([i.Directive({selector:"[ngx-datatable-cell-template]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/columns/column-header.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DataTableColumnHeaderDirective=function(){return a([i.Directive({selector:"[ngx-datatable-header-template]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/columns/column.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/components/columns/column-header.directive.ts"),o=n("./src/components/columns/column-cell.directive.ts"),u=n("./src/components/columns/tree.directive.ts"),c=n("./src/services/column-changes.service.ts");e.DataTableColumnDirective=function(){function t(t){this.columnChangesService=t,this.isFirstChange=!0}return t.prototype.ngOnChanges=function(){this.isFirstChange?this.isFirstChange=!1:this.columnChangesService.onInputChange()},a([i.Input(),r("design:type",String)],t.prototype,"name",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"prop",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"frozenLeft",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"frozenRight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"flexGrow",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"resizeable",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"comparator",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"pipe",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"sortable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"draggable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"canAutoResize",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"minWidth",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"width",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"maxWidth",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"checkboxable",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"headerCheckboxable",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"headerClass",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"cellClass",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"isTreeColumn",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"treeLevelIndent",void 0),a([i.Input(),r("design:type",Function)],t.prototype,"summaryFunc",void 0),a([i.Input(),r("design:type",i.TemplateRef)],t.prototype,"summaryTemplate",void 0),a([i.Input(),i.ContentChild(o.DataTableColumnCellDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"cellTemplate",void 0),a([i.Input(),i.ContentChild(s.DataTableColumnHeaderDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"headerTemplate",void 0),a([i.Input(),i.ContentChild(u.DataTableColumnCellTreeToggle,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"treeToggleTemplate",void 0),a([i.Directive({selector:"ngx-datatable-column"}),r("design:paramtypes",[c.ColumnChangesService])],t)}()},"./src/components/columns/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/columns/column.directive.ts")),a(n("./src/components/columns/column-header.directive.ts")),a(n("./src/components/columns/column-cell.directive.ts")),a(n("./src/components/columns/tree.directive.ts"))},"./src/components/columns/tree.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DataTableColumnCellTreeToggle=function(){return a([i.Directive({selector:"[ngx-datatable-tree-toggle]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/datatable.component.scss":function(t,e,n){var a=n("./node_modules/css-loader/index.js!./node_modules/postcss-loader/index.js!./node_modules/sass-loader/lib/loader.js??ref--3-4!./src/components/datatable.component.scss");t.exports="string"==typeof a?a:a.toString()},"./src/components/datatable.component.ts":function(t,e,n){"use strict";var a=this&&this.__assign||function(){return(a=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)},r=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},i=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)},s=this&&this.__param||function(t,e){return function(n,a){e(n,a,t)}};Object.defineProperty(e,"__esModule",{value:!0});var o=n("@angular/core"),u=n("./src/utils/index.ts"),c=n("./src/services/index.ts"),l=n("./src/types/index.ts"),d=n("./src/components/body/index.ts"),f=n("./src/components/body/body-group-header.directive.ts"),p=n("./src/components/columns/index.ts"),h=n("./src/components/row-detail/index.ts"),g=n("./src/components/footer/index.ts"),b=n("./src/components/header/index.ts"),m=n("rxjs");e.DatatableComponent=function(){function t(t,e,n,a,r,i){this.scrollbarHelper=t,this.dimensionsHelper=e,this.cd=n,this.columnChangesService=i,this.selected=[],this.scrollbarV=!1,this.scrollbarH=!1,this.rowHeight=30,this.columnMode=l.ColumnMode.standard,this.headerHeight=30,this.footerHeight=0,this.externalPaging=!1,this.externalSorting=!1,this.loadingIndicator=!1,this.reorderable=!0,this.swapColumns=!0,this.sortType=l.SortType.single,this.sorts=[],this.cssClasses={sortAscending:"datatable-icon-up",sortDescending:"datatable-icon-down",pagerLeftArrow:"datatable-icon-left",pagerRightArrow:"datatable-icon-right",pagerPrevious:"datatable-icon-prev",pagerNext:"datatable-icon-skip"},this.messages={emptyMessage:"No data to display",totalMessage:"total",selectedMessage:"selected"},this.rowIdentity=function(t){return t},this.groupExpansionDefault=!1,this.selectAllRowsOnPage=!1,this.virtualization=!0,this.summaryRow=!1,this.summaryHeight=30,this.summaryPosition="top",this.scroll=new o.EventEmitter,this.activate=new o.EventEmitter,this.select=new o.EventEmitter,this.sort=new o.EventEmitter,this.page=new o.EventEmitter,this.reorder=new o.EventEmitter,this.resize=new o.EventEmitter,this.tableContextmenu=new o.EventEmitter(!1),this.treeAction=new o.EventEmitter,this.rowCount=0,this._offsetX=new m.BehaviorSubject(0),this._count=0,this._offset=0,this._subscriptions=[],this.element=a.nativeElement,this.rowDiffer=r.find({}).create()}return Object.defineProperty(t.prototype,"rows",{get:function(){return this._rows},set:function(t){this._rows=t,t&&(this._internalRows=t.slice()),this.externalSorting||this.sortInternalRows(),this._internalRows=u.groupRowsByParents(this._internalRows,u.optionalGetterForProp(this.treeFromRelation),u.optionalGetterForProp(this.treeToRelation)),this.recalculate(),this._rows&&this._groupRowsBy&&(this.groupedRows=this.groupArrayBy(this._rows,this._groupRowsBy)),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"groupRowsBy",{get:function(){return this._groupRowsBy},set:function(t){t&&(this._groupRowsBy=t,this._rows&&this._groupRowsBy&&(this.groupedRows=this.groupArrayBy(this._rows,this._groupRowsBy)))},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){t&&(this._internalColumns=t.slice(),u.setColumnDefaults(this._internalColumns),this.recalculateColumns()),this._columns=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"limit",{get:function(){return this._limit},set:function(t){this._limit=t,this.recalculate()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"count",{get:function(){return this._count},set:function(t){this._count=t,this.recalculate()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offset",{get:function(){return Math.max(Math.min(this._offset,Math.ceil(this.rowCount/this.pageSize)-1),0)},set:function(t){this._offset=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isFixedHeader",{get:function(){var t=this.headerHeight;return"string"!=typeof t||"auto"!==t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isFixedRow",{get:function(){var t=this.rowHeight;return"string"!=typeof t||"auto"!==t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isVertScroll",{get:function(){return this.scrollbarV},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isVirtualized",{get:function(){return this.virtualization},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isHorScroll",{get:function(){return this.scrollbarH},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSelectable",{get:function(){return void 0!==this.selectionType},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCheckboxSelection",{get:function(){return this.selectionType===l.SelectionType.checkbox},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCellSelection",{get:function(){return this.selectionType===l.SelectionType.cell},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSingleSelection",{get:function(){return this.selectionType===l.SelectionType.single},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isMultiSelection",{get:function(){return this.selectionType===l.SelectionType.multi},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isMultiClickSelection",{get:function(){return this.selectionType===l.SelectionType.multiClick},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnTemplates",{get:function(){return this._columnTemplates},set:function(t){this._columnTemplates=t,this.translateColumns(t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"allRowsSelected",{get:function(){var t=this.rows&&this.selected&&this.selected.length===this.rows.length;if(this.selectAllRowsOnPage){var e=this.bodyComponent.indexes;t=this.selected.length===e.last-e.first}return this.selected&&this.rows&&0!==this.rows.length&&t},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.recalculate()},t.prototype.ngAfterViewInit=function(){var t=this;this.externalSorting||this.sortInternalRows(),"undefined"!=typeof requestAnimationFrame&&requestAnimationFrame(function(){t.recalculate(),t.externalPaging&&t.scrollbarV&&t.page.emit({count:t.count,pageSize:t.pageSize,limit:t.limit,offset:0})})},t.prototype.ngAfterContentInit=function(){var t=this;this.columnTemplates.changes.subscribe(function(e){return t.translateColumns(e)}),this.listenForColumnInputChanges()},t.prototype.translateColumns=function(t){if(t){var e=t.toArray();e.length&&(this._internalColumns=u.translateTemplates(e),u.setColumnDefaults(this._internalColumns),this.recalculateColumns(),this.sortInternalRows(),this.cd.markForCheck())}},t.prototype.groupArrayBy=function(t,e){var n=new Map;return t.forEach(function(t){var a=t[e];n.has(a)?n.get(a).push(t):n.set(a,[t])}),Array.from(n,function(t){return{key:t[0],value:t[1]}})},t.prototype.ngDoCheck=function(){this.rowDiffer.diff(this.rows)&&(this.externalSorting?this._internalRows=this.rows.slice():this.sortInternalRows(),this._internalRows=u.groupRowsByParents(this._internalRows,u.optionalGetterForProp(this.treeFromRelation),u.optionalGetterForProp(this.treeToRelation)),this.recalculatePages(),this.cd.markForCheck())},t.prototype.recalculate=function(){this.recalculateDims(),this.recalculateColumns()},t.prototype.onWindowResize=function(){this.recalculate()},t.prototype.recalculateColumns=function(t,e,n){if(void 0===t&&(t=this._internalColumns),void 0===e&&(e=-1),void 0===n&&(n=this.scrollbarH),t){var a=this._innerWidth;return this.scrollbarV&&(a-=this.scrollbarHelper.width),this.columnMode===l.ColumnMode.force?u.forceFillColumnWidths(t,a,e,n):this.columnMode===l.ColumnMode.flex&&u.adjustColumnWidths(t,a),t}},t.prototype.recalculateDims=function(){var t=this.dimensionsHelper.getDimensions(this.element);if(this._innerWidth=Math.floor(t.width),this.scrollbarV){var e=t.height;this.headerHeight&&(e-=this.headerHeight),this.footerHeight&&(e-=this.footerHeight),this.bodyHeight=e}this.recalculatePages()},t.prototype.recalculatePages=function(){this.pageSize=this.calcPageSize(),this.rowCount=this.calcRowCount()},t.prototype.onBodyPage=function(t){this.externalPaging&&!this.virtualization||(this.offset=t.offset,this.page.emit({count:this.count,pageSize:this.pageSize,limit:this.limit,offset:this.offset}))},t.prototype.onBodyScroll=function(t){this._offsetX.next(t.offsetX),this.scroll.emit(t),this.cd.detectChanges()},t.prototype.onFooterPage=function(t){this.offset=t.page-1,this.bodyComponent.updateOffsetY(this.offset),this.page.emit({count:this.count,pageSize:this.pageSize,limit:this.limit,offset:this.offset}),this.selectAllRowsOnPage&&(this.selected=[],this.select.emit({selected:this.selected}))},t.prototype.calcPageSize=function(t){if(void 0===t&&(t=this.rows),this.scrollbarV&&this.virtualization){var e=Math.ceil(this.bodyHeight/this.rowHeight);return Math.max(e,0)}return void 0!==this.limit?this.limit:t?t.length:0},t.prototype.calcRowCount=function(t){return void 0===t&&(t=this.rows),this.externalPaging?this.count:t?this.groupedRows?this.groupedRows.length:null!=this.treeFromRelation&&null!=this.treeToRelation?this._internalRows.length:t.length:0},t.prototype.onColumnContextmenu=function(t){this.tableContextmenu.emit({event:t.event,type:l.ContextmenuType.header,content:t.column})},t.prototype.onRowContextmenu=function(t){this.tableContextmenu.emit({event:t.event,type:l.ContextmenuType.body,content:t.row})},t.prototype.onColumnResize=function(t){var e=t.column,n=t.newValue;if(void 0!==e){var r,i=this._internalColumns.map(function(t,i){return(t=a({},t)).$$id===e.$$id&&(r=i,t.width=n,t.$$oldWidth=n),t});this.recalculateColumns(i,r),this._internalColumns=i,this.resize.emit({column:e,newValue:n})}},t.prototype.onColumnReorder=function(t){var e=t.column,n=t.newValue,r=t.prevValue,i=this._internalColumns.map(function(t){return a({},t)});if(this.swapColumns){var s=i[n];i[n]=e,i[r]=s}else if(n>r){for(var o=i[r],u=r;u<n;u++)i[u]=i[u+1];i[n]=o}else{for(o=i[r],u=r;u>n;u--)i[u]=i[u-1];i[n]=o}this._internalColumns=i,this.reorder.emit({column:e,newValue:n,prevValue:r})},t.prototype.onColumnSort=function(t){this.selectAllRowsOnPage&&(this.selected=[],this.select.emit({selected:this.selected})),this.sorts=t.sorts,!1===this.externalSorting&&this.sortInternalRows(),this._internalRows=u.groupRowsByParents(this._internalRows,u.optionalGetterForProp(this.treeFromRelation),u.optionalGetterForProp(this.treeToRelation)),this.offset=0,this.bodyComponent.updateOffsetY(this.offset),this.sort.emit(t)},t.prototype.onHeaderSelect=function(t){var e,n;if(this.selectAllRowsOnPage){var a=this.bodyComponent.indexes.first,r=this.bodyComponent.indexes.last,i=this.selected.length===r-a;this.selected=[],i||(e=this.selected).push.apply(e,this._internalRows.slice(a,r))}else i=this.selected.length===this.rows.length,this.selected=[],i||(n=this.selected).push.apply(n,this.rows);this.select.emit({selected:this.selected})},t.prototype.onBodySelect=function(t){this.select.emit(t)},t.prototype.onTreeAction=function(t){var e=this,n=t.row,a=this._rows.findIndex(function(n){return n[e.treeToRelation]===t.row[e.treeToRelation]});this.treeAction.emit({row:n,rowIndex:a})},t.prototype.ngOnDestroy=function(){this._subscriptions.forEach(function(t){return t.unsubscribe()})},t.prototype.listenForColumnInputChanges=function(){var t=this;this._subscriptions.push(this.columnChangesService.columnInputChanges$.subscribe(function(){t.columnTemplates&&t.columnTemplates.notifyOnChanges()}))},t.prototype.sortInternalRows=function(){this._internalRows=u.sortRows(this._internalRows,this._internalColumns,this.sorts)},r([o.Input(),i("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),r([o.Input(),i("design:type",Object),i("design:paramtypes",[Object])],t.prototype,"rows",null),r([o.Input(),i("design:type",String),i("design:paramtypes",[String])],t.prototype,"groupRowsBy",null),r([o.Input(),i("design:type",Array)],t.prototype,"groupedRows",void 0),r([o.Input(),i("design:type",Array),i("design:paramtypes",[Array])],t.prototype,"columns",null),r([o.Input(),i("design:type",Array)],t.prototype,"selected",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"scrollbarV",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"scrollbarH",void 0),r([o.Input(),i("design:type",Number)],t.prototype,"rowHeight",void 0),r([o.Input(),i("design:type",String)],t.prototype,"columnMode",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"headerHeight",void 0),r([o.Input(),i("design:type",Number)],t.prototype,"footerHeight",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"externalPaging",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"externalSorting",void 0),r([o.Input(),i("design:type",Number),i("design:paramtypes",[Number])],t.prototype,"limit",null),r([o.Input(),i("design:type",Number),i("design:paramtypes",[Number])],t.prototype,"count",null),r([o.Input(),i("design:type",Number),i("design:paramtypes",[Number])],t.prototype,"offset",null),r([o.Input(),i("design:type",Boolean)],t.prototype,"loadingIndicator",void 0),r([o.Input(),i("design:type",String)],t.prototype,"selectionType",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"reorderable",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"swapColumns",void 0),r([o.Input(),i("design:type",String)],t.prototype,"sortType",void 0),r([o.Input(),i("design:type",Array)],t.prototype,"sorts",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"cssClasses",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"messages",void 0),r([o.Input(),i("design:type",Function)],t.prototype,"rowIdentity",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"rowClass",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"selectCheck",void 0),r([o.Input(),i("design:type",Function)],t.prototype,"displayCheck",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"groupExpansionDefault",void 0),r([o.Input(),i("design:type",String)],t.prototype,"trackByProp",void 0),r([o.Input(),i("design:type",Object)],t.prototype,"selectAllRowsOnPage",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"virtualization",void 0),r([o.Input(),i("design:type",String)],t.prototype,"treeFromRelation",void 0),r([o.Input(),i("design:type",String)],t.prototype,"treeToRelation",void 0),r([o.Input(),i("design:type",Boolean)],t.prototype,"summaryRow",void 0),r([o.Input(),i("design:type",Number)],t.prototype,"summaryHeight",void 0),r([o.Input(),i("design:type",String)],t.prototype,"summaryPosition",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"scroll",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"activate",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"select",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"sort",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"page",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"reorder",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"resize",void 0),r([o.Output(),i("design:type",Object)],t.prototype,"tableContextmenu",void 0),r([o.Output(),i("design:type",o.EventEmitter)],t.prototype,"treeAction",void 0),r([o.HostBinding("class.fixed-header"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isFixedHeader",null),r([o.HostBinding("class.fixed-row"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isFixedRow",null),r([o.HostBinding("class.scroll-vertical"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isVertScroll",null),r([o.HostBinding("class.virtualized"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isVirtualized",null),r([o.HostBinding("class.scroll-horz"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isHorScroll",null),r([o.HostBinding("class.selectable"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isSelectable",null),r([o.HostBinding("class.checkbox-selection"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isCheckboxSelection",null),r([o.HostBinding("class.cell-selection"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isCellSelection",null),r([o.HostBinding("class.single-selection"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isSingleSelection",null),r([o.HostBinding("class.multi-selection"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isMultiSelection",null),r([o.HostBinding("class.multi-click-selection"),i("design:type",Boolean),i("design:paramtypes",[])],t.prototype,"isMultiClickSelection",null),r([o.ContentChildren(p.DataTableColumnDirective),i("design:type",o.QueryList),i("design:paramtypes",[o.QueryList])],t.prototype,"columnTemplates",null),r([o.ContentChild(h.DatatableRowDetailDirective),i("design:type",h.DatatableRowDetailDirective)],t.prototype,"rowDetail",void 0),r([o.ContentChild(f.DatatableGroupHeaderDirective),i("design:type",f.DatatableGroupHeaderDirective)],t.prototype,"groupHeader",void 0),r([o.ContentChild(g.DatatableFooterDirective),i("design:type",g.DatatableFooterDirective)],t.prototype,"footer",void 0),r([o.ViewChild(d.DataTableBodyComponent),i("design:type",d.DataTableBodyComponent)],t.prototype,"bodyComponent",void 0),r([o.ViewChild(b.DataTableHeaderComponent),i("design:type",b.DataTableHeaderComponent)],t.prototype,"headerComponent",void 0),r([o.HostListener("window:resize"),u.throttleable(5),i("design:type",Function),i("design:paramtypes",[]),i("design:returntype",void 0)],t.prototype,"onWindowResize",null),r([o.Component({selector:"ngx-datatable",template:'\n <div\n visibilityObserver\n (visible)="recalculate()">\n <datatable-header\n *ngIf="headerHeight"\n [sorts]="sorts"\n [sortType]="sortType"\n [scrollbarH]="scrollbarH"\n [innerWidth]="_innerWidth"\n [offsetX]="_offsetX | async"\n [dealsWithGroup]="groupedRows"\n [columns]="_internalColumns"\n [headerHeight]="headerHeight"\n [reorderable]="reorderable"\n [targetMarkerTemplate]="targetMarkerTemplate"\n [sortAscendingIcon]="cssClasses.sortAscending"\n [sortDescendingIcon]="cssClasses.sortDescending"\n [allRowsSelected]="allRowsSelected"\n [selectionType]="selectionType"\n (sort)="onColumnSort($event)"\n (resize)="onColumnResize($event)"\n (reorder)="onColumnReorder($event)"\n (select)="onHeaderSelect($event)"\n (columnContextmenu)="onColumnContextmenu($event)">\n </datatable-header>\n <datatable-body\n [groupRowsBy]="groupRowsBy"\n [groupedRows]="groupedRows"\n [rows]="_internalRows"\n [groupExpansionDefault]="groupExpansionDefault"\n [scrollbarV]="scrollbarV"\n [scrollbarH]="scrollbarH"\n [virtualization]="virtualization"\n [loadingIndicator]="loadingIndicator"\n [externalPaging]="externalPaging"\n [rowHeight]="rowHeight"\n [rowCount]="rowCount"\n [offset]="offset"\n [trackByProp]="trackByProp"\n [columns]="_internalColumns"\n [pageSize]="pageSize"\n [offsetX]="_offsetX | async"\n [rowDetail]="rowDetail"\n [groupHeader]="groupHeader"\n [selected]="selected"\n [innerWidth]="_innerWidth"\n [bodyHeight]="bodyHeight"\n [selectionType]="selectionType"\n [emptyMessage]="messages.emptyMessage"\n [rowIdentity]="rowIdentity"\n [rowClass]="rowClass"\n [selectCheck]="selectCheck"\n [displayCheck]="displayCheck"\n [summaryRow]="summaryRow"\n [summaryHeight]="summaryHeight"\n [summaryPosition]="summaryPosition"\n (page)="onBodyPage($event)"\n (activate)="activate.emit($event)"\n (rowContextmenu)="onRowContextmenu($event)"\n (select)="onBodySelect($event)"\n (scroll)="onBodyScroll($event)"\n (treeAction)="onTreeAction($event)">\n </datatable-body>\n <datatable-footer\n *ngIf="footerHeight"\n [rowCount]="rowCount"\n [pageSize]="pageSize"\n [offset]="offset"\n [footerHeight]="footerHeight"\n [footerTemplate]="footer"\n [totalMessage]="messages.totalMessage"\n [pagerLeftArrowIcon]="cssClasses.pagerLeftArrow"\n [pagerRightArrowIcon]="cssClasses.pagerRightArrow"\n [pagerPreviousIcon]="cssClasses.pagerPrevious"\n [selectedCount]="selected.length"\n [selectedMessage]="!!selectionType && messages.selectedMessage"\n [pagerNextIcon]="cssClasses.pagerNext"\n (page)="onFooterPage($event)">\n </datatable-footer>\n </div>\n ',changeDetection:o.ChangeDetectionStrategy.OnPush,encapsulation:o.ViewEncapsulation.None,styles:[n("./src/components/datatable.component.scss")],host:{class:"ngx-datatable"}}),s(0,o.SkipSelf()),s(1,o.SkipSelf()),i("design:paramtypes",[c.ScrollbarHelper,c.DimensionsHelper,o.ChangeDetectorRef,o.ElementRef,o.KeyValueDiffers,c.ColumnChangesService])],t)}()},"./src/components/footer/footer-template.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DataTableFooterTemplateDirective=function(){return a([i.Directive({selector:"[ngx-datatable-footer-template]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/footer/footer.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/components/footer/footer.directive.ts");e.DataTableFooterComponent=function(){function t(){this.selectedCount=0,this.page=new i.EventEmitter}return Object.defineProperty(t.prototype,"isVisible",{get:function(){return this.rowCount/this.pageSize>1},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"curPage",{get:function(){return this.offset+1},enumerable:!0,configurable:!0}),a([i.Input(),r("design:type",Number)],t.prototype,"footerHeight",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"rowCount",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"pageSize",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"offset",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"totalMessage",void 0),a([i.Input(),r("design:type",s.DatatableFooterDirective)],t.prototype,"footerTemplate",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"selectedCount",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectedMessage",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"page",void 0),a([i.Component({selector:"datatable-footer",template:'\n <div\n class="datatable-footer-inner"\n [ngClass]="{\'selected-count\': selectedMessage}"\n [style.height.px]="footerHeight">\n <ng-template\n *ngIf="footerTemplate"\n [ngTemplateOutlet]="footerTemplate.template"\n [ngTemplateOutletContext]="{ \n rowCount: rowCount, \n pageSize: pageSize, \n selectedCount: selectedCount,\n curPage: curPage,\n offset: offset\n }">\n </ng-template>\n <div class="page-count" *ngIf="!footerTemplate">\n <span *ngIf="selectedMessage">\n {{selectedCount?.toLocaleString()}} {{selectedMessage}} / \n </span>\n {{rowCount?.toLocaleString()}} {{totalMessage}}\n </div>\n <datatable-pager *ngIf="!footerTemplate"\n [pagerLeftArrowIcon]="pagerLeftArrowIcon"\n [pagerRightArrowIcon]="pagerRightArrowIcon"\n [pagerPreviousIcon]="pagerPreviousIcon"\n [pagerNextIcon]="pagerNextIcon"\n [page]="curPage"\n [size]="pageSize"\n [count]="rowCount"\n [hidden]="!isVisible"\n (change)="page.emit($event)">\n </datatable-pager>\n </div>\n ',host:{class:"datatable-footer"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},"./src/components/footer/footer.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/components/footer/footer-template.directive.ts");e.DatatableFooterDirective=function(){function t(){}return a([i.Input(),r("design:type",Number)],t.prototype,"footerHeight",void 0),a([i.Input(),r("design:type",String)],t.prototype,"totalMessage",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"selectedMessage",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),i.ContentChild(s.DataTableFooterTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Directive({selector:"ngx-datatable-footer"})],t)}()},"./src/components/footer/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/footer/footer.component.ts")),a(n("./src/components/footer/pager.component.ts")),a(n("./src/components/footer/footer.directive.ts")),a(n("./src/components/footer/footer-template.directive.ts"))},"./src/components/footer/pager.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DataTablePagerComponent=function(){function t(){this.change=new i.EventEmitter,this._count=0,this._page=1,this._size=0}return Object.defineProperty(t.prototype,"size",{get:function(){return this._size},set:function(t){this._size=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"count",{get:function(){return this._count},set:function(t){this._count=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"page",{get:function(){return this._page},set:function(t){this._page=t,this.pages=this.calcPages()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"totalPages",{get:function(){var t=this.size<1?1:Math.ceil(this.count/this.size);return Math.max(t||0,1)},enumerable:!0,configurable:!0}),t.prototype.canPrevious=function(){return this.page>1},t.prototype.canNext=function(){return this.page<this.totalPages},t.prototype.prevPage=function(){this.selectPage(this.page-1)},t.prototype.nextPage=function(){this.selectPage(this.page+1)},t.prototype.selectPage=function(t){t>0&&t<=this.totalPages&&t!==this.page&&(this.page=t,this.change.emit({page:t}))},t.prototype.calcPages=function(t){var e=[],n=1,a=this.totalPages;t=t||this.page,5<this.totalPages&&(n=t-Math.floor(2.5),a=t+Math.floor(2.5),n<1?(n=1,a=Math.min(n+5-1,this.totalPages)):a>this.totalPages&&(n=Math.max(this.totalPages-5+1,1),a=this.totalPages));for(var r=n;r<=a;r++)e.push({number:r,text:r});return e},a([i.Input(),r("design:type",String)],t.prototype,"pagerLeftArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerRightArrowIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerPreviousIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"pagerNextIcon",void 0),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"size",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"count",null),a([i.Input(),r("design:type",Number),r("design:paramtypes",[Number])],t.prototype,"page",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"change",void 0),a([i.Component({selector:"datatable-pager",template:'\n <ul class="pager">\n <li [class.disabled]="!canPrevious()">\n <a\n role="button"\n aria-label="go to first page"\n href="javascript:void(0)"\n (click)="selectPage(1)">\n <i class="{{pagerPreviousIcon}}"></i>\n </a>\n </li>\n <li [class.disabled]="!canPrevious()">\n <a\n role="button"\n aria-label="go to previous page"\n href="javascript:void(0)"\n (click)="prevPage()">\n <i class="{{pagerLeftArrowIcon}}"></i>\n </a>\n </li>\n <li\n role="button"\n [attr.aria-label]="\'page \' + pg.number"\n class="pages"\n *ngFor="let pg of pages"\n [class.active]="pg.number === page">\n <a\n href="javascript:void(0)"\n (click)="selectPage(pg.number)">\n {{pg.text}}\n </a>\n </li>\n <li [class.disabled]="!canNext()">\n <a\n role="button"\n aria-label="go to next page"\n href="javascript:void(0)"\n (click)="nextPage()">\n <i class="{{pagerRightArrowIcon}}"></i>\n </a>\n </li>\n <li [class.disabled]="!canNext()">\n <a\n role="button"\n aria-label="go to last page"\n href="javascript:void(0)"\n (click)="selectPage(totalPages)">\n <i class="{{pagerNextIcon}}"></i>\n </a>\n </li>\n </ul>\n ',host:{class:"datatable-pager"},changeDetection:i.ChangeDetectionStrategy.OnPush})],t)}()},"./src/components/header/header-cell.component.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/types/index.ts"),o=n("./src/utils/index.ts");n("./src/events.ts"),e.DataTableHeaderCellComponent=function(){function t(t){this.cd=t,this.sort=new i.EventEmitter,this.select=new i.EventEmitter,this.columnContextmenu=new i.EventEmitter(!1),this.sortFn=this.onSort.bind(this),this.selectFn=this.select.emit.bind(this.select),this.cellContext={column:this.column,sortDir:this.sortDir,sortFn:this.sortFn,allRowsSelected:this.allRowsSelected,selectFn:this.selectFn}}return Object.defineProperty(t.prototype,"allRowsSelected",{get:function(){return this._allRowsSelected},set:function(t){this._allRowsSelected=t,this.cellContext.allRowsSelected=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"column",{get:function(){return this._column},set:function(t){this._column=t,this.cellContext.column=t,this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"sorts",{get:function(){return this._sorts},set:function(t){this._sorts=t,this.sortDir=this.calcSortDir(t),this.cellContext.sortDir=this.sortDir,this.sortClass=this.calcSortClass(this.sortDir),this.cd.markForCheck()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columnCssClasses",{get:function(){var t="datatable-header-cell";if(this.column.sortable&&(t+=" sortable"),this.column.resizeable&&(t+=" resizeable"),this.column.headerClass)if("string"==typeof this.column.headerClass)t+=" "+this.column.headerClass;else if("function"==typeof this.column.headerClass){var e=this.column.headerClass({column:this.column});if("string"==typeof e)t+=e;else if("object"==typeof e)for(var n=0,a=Object.keys(e);n<a.length;n++){var r=a[n];!0===e[r]&&(t+=" "+r)}}var i=this.sortDir;return i&&(t+=" sort-active sort-"+i),t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return void 0===this.column.headerTemplate?this.column.name:void 0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"minWidth",{get:function(){return this.column.minWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"maxWidth",{get:function(){return this.column.maxWidth},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"width",{get:function(){return this.column.width},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isCheckboxable",{get:function(){return this.column.checkboxable&&this.column.headerCheckboxable&&this.selectionType===s.SelectionType.checkbox},enumerable:!0,configurable:!0}),t.prototype.onContextmenu=function(t){this.columnContextmenu.emit({event:t,column:this.column})},t.prototype.calcSortDir=function(t){var e=this;if(t&&this.column){var n=t.find(function(t){return t.prop===e.column.prop});if(n)return n.dir}},t.prototype.onSort=function(){if(this.column.sortable){var t=o.nextSortDir(this.sortType,this.sortDir);this.sort.emit({column:this.column,prevValue:this.sortDir,newValue:t})}},t.prototype.calcSortClass=function(t){return t===s.SortDirection.asc?"sort-btn sort-asc "+this.sortAscendingIcon:t===s.SortDirection.desc?"sort-btn sort-desc "+this.sortDescendingIcon:"sort-btn"},a([i.Input(),r("design:type",String)],t.prototype,"sortType",void 0),a([i.Input(),r("design:type",String)],t.prototype,"sortAscendingIcon",void 0),a([i.Input(),r("design:type",String)],t.prototype,"sortDescendingIcon",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"isTarget",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"targetMarkerContext",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"allRowsSelected",null),a([i.Input(),r("design:type",String)],t.prototype,"selectionType",void 0),a([i.Input(),r("design:type",Object),r("design:paramtypes",[Object])],t.prototype,"column",null),a([i.HostBinding("style.height.px"),i.Input(),r("design:type",Number)],t.prototype,"headerHeight",void 0),a([i.Input(),r("design:type",Array),r("design:paramtypes",[Array])],t.prototype,"sorts",null),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"sort",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"select",void 0),a([i.Output(),r("design:type",Object)],t.prototype,"columnContextmenu",void 0),a([i.HostBinding("class"),r("design:type",Object),r("design:paramtypes",[])],t.prototype,"columnCssClasses",null),a([i.HostBinding("attr.title"),r("design:type",String),r("design:paramtypes",[])],t.prototype,"name",null),a([i.HostBinding("style.minWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"minWidth",null),a([i.HostBinding("style.maxWidth.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"maxWidth",null),a([i.HostBinding("style.width.px"),r("design:type",Number),r("design:paramtypes",[])],t.prototype,"width",null),a([i.HostListener("contextmenu",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onContextmenu",null),a([i.Component({selector:"datatable-header-cell",template:'\n <div class="datatable-header-cell-template-wrap">\n <ng-template\n *ngIf="isTarget"\n [ngTemplateOutlet]="targetMarkerTemplate"\n [ngTemplateOutletContext]="targetMarkerContext">\n </ng-template>\n <label\n *ngIf="isCheckboxable"\n class="datatable-checkbox">\n <input\n type="checkbox"\n [checked]="allRowsSelected"\n (change)="select.emit(!allRowsSelected)"\n />\n </label>\n <span\n *ngIf="!column.headerTemplate"\n class="datatable-header-cell-wrapper">\n <span\n class="datatable-header-cell-label draggable"\n (click)="onSort()"\n [innerHTML]="name">\n </span>\n </span>\n <ng-template\n *ngIf="column.headerTemplate"\n [ngTemplateOutlet]="column.headerTemplate"\n [ngTemplateOutletContext]="cellContext">\n </ng-template>\n <span\n (click)="onSort()"\n [class]="sortClass">\n </span>\n </div>\n ',host:{class:"datatable-header-cell"},changeDetection:i.ChangeDetectionStrategy.OnPush}),r("design:paramtypes",[i.ChangeDetectorRef])],t)}()},"./src/components/header/header.component.ts":function(t,e,n){"use strict";var a=this&&this.__assign||function(){return(a=Object.assign||function(t){for(var e,n=1,a=arguments.length;n<a;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)},r=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},i=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var s=n("@angular/core"),o=n("./src/types/index.ts"),u=n("./src/utils/index.ts");e.DataTableHeaderComponent=function(){function t(t){this.cd=t,this.sort=new s.EventEmitter,this.reorder=new s.EventEmitter,this.resize=new s.EventEmitter,this.select=new s.EventEmitter,this.columnContextmenu=new s.EventEmitter(!1),this._styleByGroup={left:{},center:{},right:{}}}return Object.defineProperty(t.prototype,"innerWidth",{get:function(){return this._innerWidth},set:function(t){if(this._innerWidth=t,this._columns){var e=u.columnsByPin(this._columns);this._columnGroupWidths=u.columnGroupWidths(e,this._columns),this.setStylesByGroup()}},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"headerHeight",{get:function(){return this._headerHeight},set:function(t){this._headerHeight="auto"!==t?t+"px":t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"columns",{get:function(){return this._columns},set:function(t){this._columns=t;var e=u.columnsByPin(t);this._columnsByPin=u.columnsByPinArr(t),this._columnGroupWidths=u.columnGroupWidths(e,t),this.setStylesByGroup()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"offsetX",{get:function(){return this._offsetX},set:function(t){this._offsetX=t,this.setStylesByGroup()},enumerable:!0,configurable:!0}),t.prototype.onLongPressStart=function(t){var e=t.event;t.model.dragging=!0,this.dragEventTarget=e},t.prototype.onLongPressEnd=function(t){var e=this,n=t.model;this.dragEventTarget=t.event,setTimeout(function(){var t=e._columns.find(function(t){return t.$$id===n.$$id});t&&(t.dragging=!1)},5)},Object.defineProperty(t.prototype,"headerWidth",{get:function(){return this.scrollbarH?this.innerWidth+"px":"100%"},enumerable:!0,configurable:!0}),t.prototype.trackByGroups=function(t,e){return e.type},t.prototype.columnTrackingFn=function(t,e){return e.$$id},t.prototype.onColumnResized=function(t,e){t<=e.minWidth?t=e.minWidth:t>=e.maxWidth&&(t=e.maxWidth),this.resize.emit({column:e,prevValue:e.width,newValue:t})},t.prototype.onColumnReordered=function(t){var e=t.prevIndex,n=t.newIndex,a=t.model,r=this.getColumn(n);r.isTarget=!1,r.targetMarkerContext=void 0,this.reorder.emit({column:a,prevValue:e,newValue:n})},t.prototype.onTargetChanged=function(t){var e=t.prevIndex,n=t.newIndex,a=t.initialIndex;if(e||0===e){var r=this.getColumn(e);r.isTarget=!1,r.targetMarkerContext=void 0}if(n||0===n){var i=this.getColumn(n);i.isTarget=!0,a!==n&&(i.targetMarkerContext={class:"targetMarker ".concat(a>n?"dragFromRight":"dragFromLeft")})}},t.prototype.getColumn=function(t){var e=this._columnsByPin[0].columns.length;if(t<e)return this._columnsByPin[0].columns[t];var n=this._columnsByPin[1].columns.length;return t<e+n?this._columnsByPin[1].columns[t-e]:this._columnsByPin[2].columns[t-e-n]},t.prototype.onSort=function(t){var e=t.column,n=t.prevValue,a=t.newValue;if(!e.dragging){var r=this.calcNewSorts(e,n,a);this.sort.emit({sorts:r,column:e,prevValue:n,newValue:a})}},t.prototype.calcNewSorts=function(t,e,n){var r=0;this.sorts||(this.sorts=[]);var i=this.sorts.map(function(e,n){return(e=a({},e)).prop===t.prop&&(r=n),e});return void 0===n?i.splice(r,1):e?i[r].dir=n:(this.sortType===o.SortType.single&&i.splice(0,this.sorts.length),i.push({dir:n,prop:t.prop})),i},t.prototype.setStylesByGroup=function(){this._styleByGroup.left=this.calcStylesByGroup("left"),this._styleByGroup.center=this.calcStylesByGroup("center"),this._styleByGroup.right=this.calcStylesByGroup("right"),this.cd.detectChanges()},t.prototype.calcStylesByGroup=function(t){var e=this._columnGroupWidths,n={width:e[t]+"px"};return"center"===t?u.translateXY(n,-1*this.offsetX,0):"right"===t&&u.translateXY(n,-1*(e.total-this.innerWidth),0),n},r([s.Input(),i("design:type",Object)],t.prototype,"sortAscendingIcon",void 0),r([s.Input(),i("design:type",Object)],t.prototype,"sortDescendingIcon",void 0),r([s.Input(),i("design:type",Boolean)],t.prototype,"scrollbarH",void 0),r([s.Input(),i("design:type",Boolean)],t.prototype,"dealsWithGroup",void 0),r([s.Input(),i("design:type",Object)],t.prototype,"targetMarkerTemplate",void 0),r([s.Input(),i("design:type",Number),i("design:paramtypes",[Number])],t.prototype,"innerWidth",null),r([s.Input(),i("design:type",Array)],t.prototype,"sorts",void 0),r([s.Input(),i("design:type",String)],t.prototype,"sortType",void 0),r([s.Input(),i("design:type",Boolean)],t.prototype,"allRowsSelected",void 0),r([s.Input(),i("design:type",String)],t.prototype,"selectionType",void 0),r([s.Input(),i("design:type",Boolean)],t.prototype,"reorderable",void 0),r([s.HostBinding("style.height"),s.Input(),i("design:type",Object),i("design:paramtypes",[Object])],t.prototype,"headerHeight",null),r([s.Input(),i("design:type",Array),i("design:paramtypes",[Array])],t.prototype,"columns",null),r([s.Input(),i("design:type",Number),i("design:paramtypes",[Number])],t.prototype,"offsetX",null),r([s.Output(),i("design:type",s.EventEmitter)],t.prototype,"sort",void 0),r([s.Output(),i("design:type",s.EventEmitter)],t.prototype,"reorder",void 0),r([s.Output(),i("design:type",s.EventEmitter)],t.prototype,"resize",void 0),r([s.Output(),i("design:type",s.EventEmitter)],t.prototype,"select",void 0),r([s.Output(),i("design:type",Object)],t.prototype,"columnContextmenu",void 0),r([s.HostBinding("style.width"),i("design:type",String),i("design:paramtypes",[])],t.prototype,"headerWidth",null),r([s.Component({selector:"datatable-header",template:'\n <div\n orderable\n (reorder)="onColumnReordered($event)"\n (targetChanged)="onTargetChanged($event)"\n [style.width.px]="_columnGroupWidths.total"\n class="datatable-header-inner">\n <div\n *ngFor="let colGroup of _columnsByPin; trackBy: trackByGroups"\n [class]="\'datatable-row-\' + colGroup.type"\n [ngStyle]="_styleByGroup[colGroup.type]">\n <datatable-header-cell\n *ngFor="let column of colGroup.columns; trackBy: columnTrackingFn"\n resizeable\n [resizeEnabled]="column.resizeable"\n (resize)="onColumnResized($event, column)"\n long-press\n [pressModel]="column"\n [pressEnabled]="reorderable && column.draggable"\n (longPressStart)="onLongPressStart($event)"\n (longPressEnd)="onLongPressEnd($event)"\n draggable\n [dragX]="reorderable && column.draggable && column.dragging"\n [dragY]="false"\n [dragModel]="column"\n [dragEventTarget]="dragEventTarget"\n [headerHeight]="headerHeight"\n [isTarget]="column.isTarget"\n [targetMarkerTemplate]="targetMarkerTemplate"\n [targetMarkerContext]="column.targetMarkerContext"\n [column]="column"\n [sortType]="sortType"\n [sorts]="sorts"\n [selectionType]="selectionType"\n [sortAscendingIcon]="sortAscendingIcon"\n [sortDescendingIcon]="sortDescendingIcon"\n [allRowsSelected]="allRowsSelected"\n (sort)="onSort($event)"\n (select)="select.emit($event)"\n (columnContextmenu)="columnContextmenu.emit($event)">\n </datatable-header-cell>\n </div>\n </div>\n ',host:{class:"datatable-header"},changeDetection:s.ChangeDetectionStrategy.OnPush}),i("design:paramtypes",[s.ChangeDetectorRef])],t)}()},"./src/components/header/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/header/header.component.ts")),a(n("./src/components/header/header-cell.component.ts"))},"./src/components/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/datatable.component.ts")),a(n("./src/components/header/index.ts")),a(n("./src/components/body/index.ts")),a(n("./src/components/footer/index.ts")),a(n("./src/components/columns/index.ts")),a(n("./src/components/row-detail/index.ts"))},"./src/components/row-detail/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/components/row-detail/row-detail.directive.ts")),a(n("./src/components/row-detail/row-detail-template.directive.ts"))},"./src/components/row-detail/row-detail-template.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.DatatableRowDetailTemplateDirective=function(){return a([i.Directive({selector:"[ngx-datatable-row-detail-template]"}),r("design:paramtypes",[i.TemplateRef])],function(t){this.template=t})}()},"./src/components/row-detail/row-detail.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("./src/components/row-detail/row-detail-template.directive.ts");e.DatatableRowDetailDirective=function(){function t(){this.rowHeight=0,this.toggle=new i.EventEmitter}return t.prototype.toggleExpandRow=function(t){this.toggle.emit({type:"row",value:t})},t.prototype.expandAllRows=function(){this.toggle.emit({type:"all",value:!0})},t.prototype.collapseAllRows=function(){this.toggle.emit({type:"all",value:!1})},a([i.Input(),r("design:type",Object)],t.prototype,"rowHeight",void 0),a([i.Input(),i.ContentChild(s.DatatableRowDetailTemplateDirective,{read:i.TemplateRef}),r("design:type",i.TemplateRef)],t.prototype,"template",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"toggle",void 0),a([i.Directive({selector:"ngx-datatable-row-detail"})],t)}()},"./src/datatable.module.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s};Object.defineProperty(e,"__esModule",{value:!0});var r=n("@angular/core"),i=n("@angular/common"),s=n("./src/components/index.ts"),o=n("./src/directives/index.ts"),u=n("./src/services/index.ts");e.NgxDatatableModule=function(){return a([r.NgModule({imports:[i.CommonModule],providers:[u.ScrollbarHelper,u.DimensionsHelper,u.ColumnChangesService],declarations:[s.DataTableFooterTemplateDirective,o.VisibilityDirective,o.DraggableDirective,o.ResizeableDirective,o.OrderableDirective,o.LongPressDirective,s.ScrollerComponent,s.DatatableComponent,s.DataTableColumnDirective,s.DataTableHeaderComponent,s.DataTableHeaderCellComponent,s.DataTableBodyComponent,s.DataTableFooterComponent,s.DataTablePagerComponent,s.ProgressBarComponent,s.DataTableBodyRowComponent,s.DataTableRowWrapperComponent,s.DatatableRowDetailDirective,s.DatatableGroupHeaderDirective,s.DatatableRowDetailTemplateDirective,s.DataTableBodyCellComponent,s.DataTableSelectionComponent,s.DataTableColumnHeaderDirective,s.DataTableColumnCellDirective,s.DataTableColumnCellTreeToggle,s.DatatableFooterDirective,s.DatatableGroupHeaderTemplateDirective,s.DataTableSummaryRowComponent],exports:[s.DatatableComponent,s.DatatableRowDetailDirective,s.DatatableGroupHeaderDirective,s.DatatableRowDetailTemplateDirective,s.DataTableColumnDirective,s.DataTableColumnHeaderDirective,s.DataTableColumnCellDirective,s.DataTableColumnCellTreeToggle,s.DataTableFooterTemplateDirective,s.DatatableFooterDirective,s.DataTablePagerComponent,s.DatatableGroupHeaderTemplateDirective]})],function(){})}()},"./src/directives/draggable.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("rxjs"),o=n("rxjs/operators");e.DraggableDirective=function(){function t(t){this.dragX=!0,this.dragY=!0,this.dragStart=new i.EventEmitter,this.dragging=new i.EventEmitter,this.dragEnd=new i.EventEmitter,this.isDragging=!1,this.element=t.nativeElement}return t.prototype.ngOnChanges=function(t){t.dragEventTarget&&t.dragEventTarget.currentValue&&this.dragModel.dragging&&this.onMousedown(t.dragEventTarget.currentValue)},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype.onMouseup=function(t){this.isDragging&&(this.isDragging=!1,this.element.classList.remove("dragging"),this.subscription&&(this._destroySubscription(),this.dragEnd.emit({event:t,element:this.element,model:this.dragModel})))},t.prototype.onMousedown=function(t){var e=this;if(t.target.classList.contains("draggable")&&(this.dragX||this.dragY)){t.preventDefault(),this.isDragging=!0;var n={x:t.clientX,y:t.clientY},a=s.fromEvent(document,"mouseup");this.subscription=a.subscribe(function(t){return e.onMouseup(t)});var r=s.fromEvent(document,"mousemove").pipe(o.takeUntil(a)).subscribe(function(t){return e.move(t,n)});this.subscription.add(r),this.dragStart.emit({event:t,element:this.element,model:this.dragModel})}},t.prototype.move=function(t,e){if(this.isDragging){var n=t.clientY-e.y;this.dragX&&(this.element.style.left=t.clientX-e.x+"px"),this.dragY&&(this.element.style.top=n+"px"),this.element.classList.add("dragging"),this.dragging.emit({event:t,element:this.element,model:this.dragModel})}},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Object)],t.prototype,"dragEventTarget",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"dragModel",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"dragX",void 0),a([i.Input(),r("design:type",Boolean)],t.prototype,"dragY",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragStart",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragging",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"dragEnd",void 0),a([i.Directive({selector:"[draggable]"}),r("design:paramtypes",[i.ElementRef])],t)}()},"./src/directives/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/directives/draggable.directive.ts")),a(n("./src/directives/long-press.directive.ts")),a(n("./src/directives/orderable.directive.ts")),a(n("./src/directives/resizeable.directive.ts")),a(n("./src/directives/visibility.directive.ts"))},"./src/directives/long-press.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("rxjs"),o=n("rxjs/operators");n("./src/events.ts"),e.LongPressDirective=function(){function t(){this.pressEnabled=!0,this.duration=500,this.longPressStart=new i.EventEmitter,this.longPressing=new i.EventEmitter,this.longPressEnd=new i.EventEmitter,this.mouseX=0,this.mouseY=0}return Object.defineProperty(t.prototype,"press",{get:function(){return this.pressing},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isLongPress",{get:function(){return this.isLongPressing},enumerable:!0,configurable:!0}),t.prototype.onMouseDown=function(t){var e=this;if(1===t.which&&this.pressEnabled&&!t.target.classList.contains("resize-handle")){this.mouseX=t.clientX,this.mouseY=t.clientY,this.pressing=!0,this.isLongPressing=!1;var n=s.fromEvent(document,"mouseup");this.subscription=n.subscribe(function(t){return e.onMouseup()}),this.timeout=setTimeout(function(){e.isLongPressing=!0,e.longPressStart.emit({event:t,model:e.pressModel}),e.subscription.add(s.fromEvent(document,"mousemove").pipe(o.takeUntil(n)).subscribe(function(t){return e.onMouseMove(t)})),e.loop(t)},this.duration),this.loop(t)}},t.prototype.onMouseMove=function(t){if(this.pressing&&!this.isLongPressing){var e=Math.abs(t.clientX-this.mouseX)>10,n=Math.abs(t.clientY-this.mouseY)>10;(e||n)&&this.endPress()}},t.prototype.loop=function(t){var e=this;this.isLongPressing&&(this.timeout=setTimeout(function(){e.longPressing.emit({event:t,model:e.pressModel}),e.loop(t)},50))},t.prototype.endPress=function(){clearTimeout(this.timeout),this.isLongPressing=!1,this.pressing=!1,this._destroySubscription(),this.longPressEnd.emit({model:this.pressModel})},t.prototype.onMouseup=function(){this.endPress()},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Boolean)],t.prototype,"pressEnabled",void 0),a([i.Input(),r("design:type",Object)],t.prototype,"pressModel",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"duration",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressStart",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressing",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"longPressEnd",void 0),a([i.HostBinding("class.press"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"press",null),a([i.HostBinding("class.longpress"),r("design:type",Boolean),r("design:paramtypes",[])],t.prototype,"isLongPress",null),a([i.HostListener("mousedown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMouseDown",null),a([i.Directive({selector:"[long-press]"})],t)}()},"./src/directives/orderable.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)},i=this&&this.__param||function(t,e){return function(n,a){e(n,a,t)}};Object.defineProperty(e,"__esModule",{value:!0});var s=n("@angular/core"),o=n("./src/directives/draggable.directive.ts"),u=n("@angular/platform-browser");e.OrderableDirective=function(){function t(t,e){this.document=e,this.reorder=new s.EventEmitter,this.targetChanged=new s.EventEmitter,this.differ=t.find({}).create()}return t.prototype.ngAfterContentInit=function(){this.updateSubscriptions(),this.draggables.changes.subscribe(this.updateSubscriptions.bind(this))},t.prototype.ngOnDestroy=function(){this.draggables.forEach(function(t){t.dragStart.unsubscribe(),t.dragging.unsubscribe(),t.dragEnd.unsubscribe()})},t.prototype.updateSubscriptions=function(){var t=this,e=this.differ.diff(this.createMapDiffs());if(e){var n=function(t){var e=t.previousValue;e&&(e.dragStart.unsubscribe(),e.dragging.unsubscribe(),e.dragEnd.unsubscribe())};e.forEachAddedItem((function(e){var a=e.currentValue;n({previousValue:e.previousValue}),a&&(a.dragStart.subscribe(t.onDragStart.bind(t)),a.dragging.subscribe(t.onDragging.bind(t)),a.dragEnd.subscribe(t.onDragEnd.bind(t)))}).bind(this)),e.forEachRemovedItem(n.bind(this))}},t.prototype.onDragStart=function(){this.positions={};for(var t=0,e=0,n=this.draggables.toArray();e<n.length;e++){var a=n[e],r=a.element,i=parseInt(r.offsetLeft.toString(),0);this.positions[a.dragModel.prop]={left:i,right:i+parseInt(r.offsetWidth.toString(),0),index:t++,element:r}}},t.prototype.onDragging=function(t){var e=t.model,n=this.positions[e.prop],a=this.isTarget(e,t.event);a?this.lastDraggingIndex!==a.i&&(this.targetChanged.emit({prevIndex:this.lastDraggingIndex,newIndex:a.i,initialIndex:n.index}),this.lastDraggingIndex=a.i):this.lastDraggingIndex!==n.index&&(this.targetChanged.emit({prevIndex:this.lastDraggingIndex,initialIndex:n.index}),this.lastDraggingIndex=n.index)},t.prototype.onDragEnd=function(t){var e=t.element,n=t.model,a=this.positions[n.prop],r=this.isTarget(n,t.event);r&&this.reorder.emit({prevIndex:a.index,newIndex:r.i,model:n}),this.lastDraggingIndex=void 0,e.style.left="auto"},t.prototype.isTarget=function(t,e){var n=0,a=this.document.elementsFromPoint(e.x||e.clientX,e.y||e.clientY),r=function(e){var r=i.positions[e];if(t.prop!==e&&a.find(function(t){return t===r.element}))return{value:{pos:r,i:n}};n++},i=this;for(var s in this.positions){var o=r(s);if("object"==typeof o)return o.value}},t.prototype.createMapDiffs=function(){return this.draggables.toArray().reduce(function(t,e){return t[e.dragModel.$$id]=e,t},{})},a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"reorder",void 0),a([s.Output(),r("design:type",s.EventEmitter)],t.prototype,"targetChanged",void 0),a([s.ContentChildren(o.DraggableDirective,{descendants:!0}),r("design:type",s.QueryList)],t.prototype,"draggables",void 0),a([s.Directive({selector:"[orderable]"}),i(1,s.Inject(u.DOCUMENT)),r("design:paramtypes",[s.KeyValueDiffers,Object])],t)}()},"./src/directives/resizeable.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core"),s=n("rxjs"),o=(n("./src/events.ts"),n("rxjs/operators"));e.ResizeableDirective=function(){function t(t,e){this.renderer=e,this.resizeEnabled=!0,this.resize=new i.EventEmitter,this.resizing=!1,this.element=t.nativeElement}return t.prototype.ngAfterViewInit=function(){var t=this.renderer,e=t.createElement("span");t.addClass(e,this.resizeEnabled?"resize-handle":"resize-handle--not-resizable"),t.appendChild(this.element,e)},t.prototype.ngOnDestroy=function(){this._destroySubscription()},t.prototype.onMouseup=function(){this.resizing=!1,this.subscription&&!this.subscription.closed&&(this._destroySubscription(),this.resize.emit(this.element.clientWidth))},t.prototype.onMousedown=function(t){var e=this,n=t.target.classList.contains("resize-handle"),a=this.element.clientWidth,r=t.screenX;if(n){t.stopPropagation(),this.resizing=!0;var i=s.fromEvent(document,"mouseup");this.subscription=i.subscribe(function(t){return e.onMouseup()});var u=s.fromEvent(document,"mousemove").pipe(o.takeUntil(i)).subscribe(function(t){return e.move(t,a,r)});this.subscription.add(u)}},t.prototype.move=function(t,e,n){var a=e+(t.screenX-n);(!this.minWidth||a>=this.minWidth)&&(!this.maxWidth||a<=this.maxWidth)&&(this.element.style.width=a+"px")},t.prototype._destroySubscription=function(){this.subscription&&(this.subscription.unsubscribe(),this.subscription=void 0)},a([i.Input(),r("design:type",Boolean)],t.prototype,"resizeEnabled",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"minWidth",void 0),a([i.Input(),r("design:type",Number)],t.prototype,"maxWidth",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"resize",void 0),a([i.HostListener("mousedown",["$event"]),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",void 0)],t.prototype,"onMousedown",null),a([i.Directive({selector:"[resizeable]",host:{"[class.resizeable]":"resizeEnabled"}}),r("design:paramtypes",[i.ElementRef,i.Renderer2])],t)}()},"./src/directives/visibility.directive.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)};Object.defineProperty(e,"__esModule",{value:!0});var i=n("@angular/core");e.VisibilityDirective=function(){function t(t,e){this.element=t,this.zone=e,this.isVisible=!1,this.visible=new i.EventEmitter}return t.prototype.ngOnInit=function(){this.runCheck()},t.prototype.ngOnDestroy=function(){clearTimeout(this.timeout)},t.prototype.onVisibilityChange=function(){var t=this;this.zone.run(function(){t.isVisible=!0,t.visible.emit(!0)})},t.prototype.runCheck=function(){var t=this,e=function(){var n=t.element.nativeElement;n.offsetHeight&&n.offsetWidth?(clearTimeout(t.timeout),t.onVisibilityChange()):(clearTimeout(t.timeout),t.zone.runOutsideAngular(function(){t.timeout=setTimeout(function(){return e()},50)}))};this.timeout=setTimeout(function(){return e()})},a([i.HostBinding("class.visible"),r("design:type",Boolean)],t.prototype,"isVisible",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"visible",void 0),a([i.Directive({selector:"[visibilityObserver]"}),r("design:paramtypes",[i.ElementRef,i.NgZone])],t)}()},"./src/events.ts":function(t,e,n){"use strict";(function(t){Object.defineProperty(e,"__esModule",{value:!0}),e.MouseEvent=("undefined"!=typeof window&&window||t).MouseEvent,e.KeyboardEvent=("undefined"!=typeof window&&window||t).KeyboardEvent,e.Event=("undefined"!=typeof window&&window||t).Event}).call(e,n("./node_modules/webpack/buildin/global.js"))},"./src/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/datatable.module.ts")),a(n("./src/types/index.ts")),a(n("./src/components/index.ts")),a(n("./src/services/index.ts"))},"./src/services/column-changes.service.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s};Object.defineProperty(e,"__esModule",{value:!0});var r=n("@angular/core"),i=n("rxjs");e.ColumnChangesService=function(){function t(){this.columnInputChanges=new i.Subject}return Object.defineProperty(t.prototype,"columnInputChanges$",{get:function(){return this.columnInputChanges.asObservable()},enumerable:!0,configurable:!0}),t.prototype.onInputChange=function(){this.columnInputChanges.next()},a([r.Injectable()],t)}()},"./src/services/dimensions-helper.service.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s};Object.defineProperty(e,"__esModule",{value:!0});var r=n("@angular/core");e.DimensionsHelper=function(){function t(){}return t.prototype.getDimensions=function(t){return t.getBoundingClientRect()},a([r.Injectable()],t)}()},"./src/services/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/services/scrollbar-helper.service.ts")),a(n("./src/services/dimensions-helper.service.ts")),a(n("./src/services/column-changes.service.ts"))},"./src/services/scrollbar-helper.service.ts":function(t,e,n){"use strict";var a=this&&this.__decorate||function(t,e,n,a){var r,i=arguments.length,s=i<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,n):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,a);else for(var o=t.length-1;o>=0;o--)(r=t[o])&&(s=(i<3?r(s):i>3?r(e,n,s):r(e,n))||s);return i>3&&s&&Object.defineProperty(e,n,s),s},r=this&&this.__metadata||function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)},i=this&&this.__param||function(t,e){return function(n,a){e(n,a,t)}};Object.defineProperty(e,"__esModule",{value:!0});var s=n("@angular/core"),o=n("@angular/platform-browser");e.ScrollbarHelper=function(){function t(t){this.document=t,this.width=this.getWidth()}return t.prototype.getWidth=function(){var t=this.document.createElement("div");t.style.visibility="hidden",t.style.width="100px",t.style.msOverflowStyle="scrollbar",this.document.body.appendChild(t);var e=t.offsetWidth;t.style.overflow="scroll";var n=this.document.createElement("div");n.style.width="100%",t.appendChild(n);var a=n.offsetWidth;return t.parentNode.removeChild(t),e-a},a([s.Injectable(),i(0,s.Inject(o.DOCUMENT)),r("design:paramtypes",[Object])],t)}()},"./src/types/click.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.double="double"}(e.ClickType||(e.ClickType={}))},"./src/types/column-mode.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.standard="standard",t.flex="flex",t.force="force"}(e.ColumnMode||(e.ColumnMode={}))},"./src/types/contextmenu.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.header="header",t.body="body"}(e.ContextmenuType||(e.ContextmenuType={}))},"./src/types/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/types/column-mode.type.ts")),a(n("./src/types/sort.type.ts")),a(n("./src/types/sort-direction.type.ts")),a(n("./src/types/selection.type.ts")),a(n("./src/types/click.type.ts")),a(n("./src/types/contextmenu.type.ts"))},"./src/types/selection.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.multi="multi",t.multiClick="multiClick",t.cell="cell",t.checkbox="checkbox"}(e.SelectionType||(e.SelectionType={}))},"./src/types/sort-direction.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.asc="asc",t.desc="desc"}(e.SortDirection||(e.SortDirection={}))},"./src/types/sort.type.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.single="single",t.multi="multi"}(e.SortType||(e.SortType={}))},"./src/utils/camel-case.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.camelCase=function(t){return(t=(t=(t=t.replace(/[^a-zA-Z0-9 ]/g," ")).replace(/([a-z](?=[A-Z]))/g,"$1 ")).replace(/([^a-zA-Z0-9 ])|^[0-9]+/g,"").trim().toLowerCase()).replace(/([ 0-9]+)([a-zA-Z])/g,function(t,e,n){return e.trim()+n.toUpperCase()})},e.deCamelCase=function(t){return t.replace(/([A-Z])/g,function(t){return" "+t}).replace(/^./,function(t){return t.toUpperCase()})}},"./src/utils/column-helper.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("./src/utils/camel-case.ts"),r=n("./src/utils/id.ts"),i=n("./src/utils/column-prop-getters.ts");function s(t){return null==t}e.setColumnDefaults=function(t){if(t)for(var e=!1,n=0,o=t;n<o.length;n++){var u=o[n];u.$$id||(u.$$id=r.id()),s(u.prop)&&u.name&&(u.prop=a.camelCase(u.name)),u.$$valueGetter||(u.$$valueGetter=i.getterForProp(u.prop)),!s(u.prop)&&s(u.name)&&(u.name=a.deCamelCase(String(u.prop))),s(u.prop)&&s(u.name)&&(u.name=""),u.hasOwnProperty("resizeable")||(u.resizeable=!0),u.hasOwnProperty("sortable")||(u.sortable=!0),u.hasOwnProperty("draggable")||(u.draggable=!0),u.hasOwnProperty("canAutoResize")||(u.canAutoResize=!0),u.hasOwnProperty("width")||(u.width=150),u.hasOwnProperty("isTreeColumn")&&u.isTreeColumn&&!e?e=!0:u.isTreeColumn=!1}},e.isNullOrUndefined=s,e.translateTemplates=function(t){for(var e=[],n=0,a=t;n<a.length;n++){for(var r=a[n],i={},s=0,o=Object.getOwnPropertyNames(r);s<o.length;s++){var u=o[s];i[u]=r[u]}r.headerTemplate&&(i.headerTemplate=r.headerTemplate),r.cellTemplate&&(i.cellTemplate=r.cellTemplate),r.summaryFunc&&(i.summaryFunc=r.summaryFunc),r.summaryTemplate&&(i.summaryTemplate=r.summaryTemplate),e.push(i)}return e}},"./src/utils/column-prop-getters.ts":function(t,e,n){"use strict";function a(){return""}function r(t,e){if(null==t)return"";if(!t||null==e)return t;var n=t[e];return null==n?"":n}function i(t,e){if(null==t)return"";if(!t||!e)return t;var n=t[e];return null==n?"":n}function s(t,e){if(null==t)return"";if(!t||!e)return t;var n=t[e];if(void 0!==n)return n;n=t;var a=e.split(".");if(a.length)for(var r=0;r<a.length;r++)if(null==(n=n[a[r]]))return"";return n}Object.defineProperty(e,"__esModule",{value:!0}),e.emptyStringGetter=a,e.getterForProp=function(t){return null==t?a:"number"==typeof t?r:-1!==t.indexOf(".")?s:i},e.numericIndexGetter=r,e.shallowValueGetter=i,e.deepValueGetter=s},"./src/utils/column.ts":function(t,e,n){"use strict";function a(t){var e={left:[],center:[],right:[]};if(t)for(var n=0,a=t;n<a.length;n++){var r=a[n];r.frozenLeft?e.left.push(r):r.frozenRight?e.right.push(r):e.center.push(r)}return e}function r(t,e){var n=0;if(t)for(var a=0,r=t;a<r.length;a++){var i=r[a];n+=parseFloat(e&&i[e]?i[e]:i.width)}return n}Object.defineProperty(e,"__esModule",{value:!0}),e.columnsByPin=a,e.columnGroupWidths=function(t,e){return{left:r(t.left),center:r(t.center),right:r(t.right),total:Math.floor(r(e))}},e.columnTotalWidth=r,e.columnsTotalWidth=function(t,e){for(var n=0,a=0,r=t;a<r.length;a++){var i=r[a];n+=e&&i[e]?i[e]:i.width}return n},e.columnsByPinArr=function(t){var e=[],n=a(t);return e.push({type:"left",columns:n.left}),e.push({type:"center",columns:n.center}),e.push({type:"right",columns:n.right}),e}},"./src/utils/elm-from-point.ts":function(t,e,n){"use strict";function a(t,e){for(var n,a,r,i=[],s=[];(n=document.elementFromPoint(t,e))&&-1===i.indexOf(n)&&null!=n;)i.push(n),s.push({value:n.style.getPropertyValue("pointer-events"),priority:n.style.getPropertyPriority("pointer-events")}),n.style.setProperty("pointer-events","none","important");for(a=s.length;r=s[--a];)i[a].style.setProperty("pointer-events",r.value?r.value:"",r.priority);return i}Object.defineProperty(e,"__esModule",{value:!0}),"undefined"==typeof document||document.elementsFromPoint||(document.elementsFromPoint=a),e.elementsFromPoint=a},"./src/utils/id.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.id=function(){return("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)}},"./src/utils/index.ts":function(t,e,n){"use strict";function a(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),a(n("./src/utils/id.ts")),a(n("./src/utils/column.ts")),a(n("./src/utils/column-prop-getters.ts")),a(n("./src/utils/camel-case.ts")),a(n("./src/utils/keys.ts")),a(n("./src/utils/math.ts")),a(n("./src/utils/prefixes.ts")),a(n("./src/utils/selection.ts")),a(n("./src/utils/translate.ts")),a(n("./src/utils/throttle.ts")),a(n("./src/utils/sort.ts")),a(n("./src/utils/row-height-cache.ts")),a(n("./src/utils/column-helper.ts")),a(n("./src/utils/elm-from-point.ts")),a(n("./src/utils/tree.ts"))},"./src/utils/keys.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Keys=function(t){return t[t.up=38]="up",t[t.down=40]="down",t[t.return=13]="return",t[t.escape=27]="escape",t[t.left=37]="left",t[t.right=39]="right",t}(e.Keys||{})},"./src/utils/math.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("./src/utils/column.ts");function r(t){for(var e=0,n=0,a=t;n<a.length;n++)e+=a[n].flexGrow||0;return e}function i(t,e){for(var n=0,a=e;n<a.length;n++){var r=t.indexOf(a[n]);t.splice(r,1)}}function s(t,e){void 0===e&&(e=300);for(var n=0,a=0,r=t;a<r.length;a++)n+=r[a].width||e;return n}e.getTotalFlexGrow=r,e.adjustColumnWidths=function(t,e){var n=a.columnsTotalWidth(t),i=r(t),s=a.columnsByPin(t);n!==e&&function(t,e,n){for(var a in t)for(var r=0,i=t[a];r<i.length;r++)(d=i[r]).canAutoResize?d.width=0:(e-=d.width,n-=d.flexGrow?d.flexGrow:0);var s={},o=e;do{var u=o/n;for(var a in o=0,t)for(var c=0,l=t[a];c<l.length;c++){var d;if((d=l[c]).canAutoResize&&!s[d.prop]){var f=d.width+d.flexGrow*u;void 0!==d.minWidth&&f<d.minWidth?(o+=f-d.minWidth,d.width=d.minWidth,s[d.prop]=!0):d.width=f}}}while(0!==o)}(s,e,i)},e.forceFillColumnWidths=function(t,e,n,a,r){void 0===r&&(r=300);for(var o=t.slice(n+1,t.length).filter(function(t){return!1!==t.canAutoResize}),u=0,c=o;u<c.length;u++)(m=c[u]).$$oldWidth||(m.$$oldWidth=m.width);var l=0,d=!1,f=s(t,r),p=e-f,h=[];do{l=p/o.length,d=f>=e;for(var g=0,b=o;g<b.length;g++){var m=b[g];if(d&&a)m.width=m.$$oldWidth||m.width||r;else{var y=(m.width||r)+l;m.minWidth&&y<m.minWidth?(m.width=m.minWidth,h.push(m)):m.maxWidth&&y>m.maxWidth?(m.width=m.maxWidth,h.push(m)):m.width=y}m.width=Math.max(0,m.width)}p=e-(f=s(t)),i(o,h)}while(p>0&&0!==o.length)}},"./src/utils/prefixes.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a,r,i,s,o=n("./src/utils/camel-case.ts"),u={},c="undefined"!=typeof document?document.createElement("div").style:void 0,l=(s=void 0!==(i=null!==(r=void 0!==(a="undefined"!=typeof window?window.getComputedStyle(document.documentElement,""):void 0)?Array.prototype.slice.call(a).join("").match(/-(moz|webkit|ms)-/):null)?r[1]:void 0)?"WebKit|Moz|MS|O".match(new RegExp("("+i+")","i"))[1]:void 0)?{dom:s,lowercase:i,css:"-"+i+"-",js:i[0].toUpperCase()+i.substr(1)}:void 0;e.getVendorPrefixedName=function(t){var e=o.camelCase(t);return u[e]||(void 0!==l&&void 0!==c[l.css+t]?u[e]=l.css+t:void 0!==c[t]&&(u[e]=t)),u[e]}},"./src/utils/row-height-cache.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RowHeightCache=function(){function t(){this.treeArray=[]}return t.prototype.clearCache=function(){this.treeArray=[]},t.prototype.initCache=function(t){var e=t.rows,n=t.rowHeight,a=t.detailRowHeight,r=t.externalVirtual,i=t.rowCount,s=t.rowIndexes,o=t.rowExpansions,u="function"==typeof n,c="function"==typeof a;if(!u&&isNaN(n))throw new Error("Row Height cache initialization failed. Please ensure that 'rowHeight' is a\n valid number or function value: ("+n+") when 'scrollbarV' is enabled.");if(!c&&isNaN(a))throw new Error("Row Height cache initialization failed. Please ensure that 'detailRowHeight' is a\n valid number or function value: ("+a+") when 'scrollbarV' is enabled.");var l=r?i:e.length;this.treeArray=new Array(l);for(var d=0;d<l;++d)this.treeArray[d]=0;for(d=0;d<l;++d){var f=e[d],p=n;u&&(p=n(f));var h=o.get(f);f&&1===h&&(p+=c?a(f,s.get(f)):a),this.update(d,p)}},t.prototype.getRowIndex=function(t){return 0===t?0:this.calcRowIndex(t)},t.prototype.update=function(t,e){if(!this.treeArray.length)throw new Error("Update at index "+t+" with value "+e+" failed:\n Row Height cache not initialized.");var n=this.treeArray.length;for(t|=0;t<n;)this.treeArray[t]+=e,t|=t+1},t.prototype.query=function(t){if(!this.treeArray.length)throw new Error("query at index "+t+" failed: Fenwick tree array not initialized.");var e=0;for(t|=0;t>=0;)e+=this.treeArray[t],t=(t&t+1)-1;return e},t.prototype.queryBetween=function(t,e){return this.query(e)-this.query(t-1)},t.prototype.calcRowIndex=function(t){if(!this.treeArray.length)return 0;for(var e=-1,n=this.treeArray.length,a=Math.pow(2,n.toString(2).length-1);0!==a;a>>=1){var r=e+a;r<n&&t>=this.treeArray[r]&&(t-=this.treeArray[r],e=r)}return e+1},t}()},"./src/utils/selection.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.selectRows=function(t,e,n){var a=n(e,t);return a>-1?t.splice(a,1):t.push(e),t},e.selectRowsBetween=function(t,e,n,a,r){for(var i=n<a,s=0;s<e.length;s++){var o;o=i?{start:n,end:a}:{start:a,end:n+1},(i&&s<=a&&s>=n||!i&&s>=a&&s<=n)&&s>=o.start&&s<=o.end&&t.push(e[s])}return t}},"./src/utils/sort.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("./src/types/index.ts"),r=n("./src/utils/column-prop-getters.ts");function i(t,e){if(null==t&&(t=0),null==e&&(e=0),t instanceof Date&&e instanceof Date){if(t<e)return-1;if(t>e)return 1}else if(isNaN(parseFloat(t))||!isFinite(t)||isNaN(parseFloat(e))||!isFinite(e)){if(t=String(t),e=String(e),t.toLowerCase()<e.toLowerCase())return-1;if(t.toLowerCase()>e.toLowerCase())return 1}else{if(parseFloat(t)<parseFloat(e))return-1;if(parseFloat(t)>parseFloat(e))return 1}return 0}e.nextSortDir=function(t,e){return t===a.SortType.single?e===a.SortDirection.asc?a.SortDirection.desc:a.SortDirection.asc:e?e===a.SortDirection.asc?a.SortDirection.desc:void 0:a.SortDirection.asc},e.orderByComparator=i,e.sortRows=function(t,e,n){if(!t)return[];if(!n||!n.length||!e)return t.slice();var s=new Map;t.forEach(function(t,e){return s.set(t,e)});var o=t.slice(),u=e.reduce(function(t,e){return e.comparator&&"function"==typeof e.comparator&&(t[e.prop]=e.comparator),t},{}),c=n.map(function(t){var e=t.prop;return{prop:e,dir:t.dir,valueGetter:r.getterForProp(e),compareFn:u[e]||i}});return o.sort(function(t,e){for(var n=0,r=c;n<r.length;n++){var i=r[n],o=i.prop,u=i.valueGetter,l=u(t,o),d=u(e,o),f=i.dir!==a.SortDirection.desc?i.compareFn(l,d,t,e,i.dir):-i.compareFn(l,d,t,e,i.dir);if(0!==f)return f}return s.has(t)&&s.has(e)?s.get(t)<s.get(e)?-1:1:0})}},"./src/utils/throttle.ts":function(t,e,n){"use strict";function a(t,e,n){var a,r,i;n=n||{};var s=null,o=0;function u(){o=!1===n.leading?0:+new Date,s=null,i=t.apply(a,r)}return function(){var c=+new Date;o||!1!==n.leading||(o=c);var l=e-(c-o);return a=this,r=arguments,l<=0?(clearTimeout(s),s=null,o=c,i=t.apply(a,r)):s||!1===n.trailing||(s=setTimeout(u,l)),i}}Object.defineProperty(e,"__esModule",{value:!0}),e.throttle=a,e.throttleable=function(t,e){return function(n,r,i){return{configurable:!0,enumerable:i.enumerable,get:function(){return Object.defineProperty(this,r,{configurable:!0,enumerable:i.enumerable,value:a(i.value,t,e)}),this[r]}}}}},"./src/utils/translate.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("./src/utils/prefixes.ts"),r=n("./src/utils/camel-case.ts"),i="undefined"!=typeof window?a.getVendorPrefixedName("transform"):void 0,s="undefined"!=typeof window?a.getVendorPrefixedName("backfaceVisibility"):void 0,o="undefined"!=typeof window?!!a.getVendorPrefixedName("transform"):void 0,u="undefined"!=typeof window?!!a.getVendorPrefixedName("perspective"):void 0,c="undefined"!=typeof window?window.navigator.userAgent:"Chrome",l=/Safari\//.test(c)&&!/Chrome\//.test(c);e.translateXY=function(t,e,n){void 0!==i&&o?!l&&u?(t[i]="translate3d("+e+"px, "+n+"px, 0)",t[s]="hidden"):t[r.camelCase(i)]="translate("+e+"px, "+n+"px)":(t.top=n+"px",t.left=e+"px")}},"./src/utils/tree.ts":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=n("./src/utils/index.ts");e.optionalGetterForProp=function(t){return t&&function(e){return a.getterForProp(t)(e,t)}},e.groupRowsByParents=function(t,e,n){if(e&&n){var a={},i=t.length,s=null;a[0]=new r;for(var o=t.reduce(function(t,e){var a=n(e);return-1===t.indexOf(a)&&t.push(a),t},[]),u=0;u<i;u++)a[n(t[u])]=new r(t[u]);for(u=0;u<i;u++){var c=0,l=e((s=a[n(t[u])]).row);l&&o.indexOf(l)>-1&&(c=l),s.parent=a[c],s.row.level=s.parent.row.level+1,s.parent.children.push(s)}var d=[];return a[0].flatten(function(){d=d.concat([this.row])},!0),d}return t};var r=function(){function t(t){void 0===t&&(t=null),t||(t={level:-1,treeStatus:"expanded"}),this.row=t,this.parent=null,this.children=[]}return t.prototype.flatten=function(t,e){if("expanded"===this.row.treeStatus)for(var n=0,a=this.children.length;n<a;n++){var r=this.children[n];t.apply(r,Array.prototype.slice.call(arguments,2)),e&&r.flatten.apply(r,arguments)}},t}()},"@angular/common":function(e,n){e.exports=t},"@angular/core":function(t,n){t.exports=e},"@angular/platform-browser":function(t,e){t.exports=n},rxjs:function(t,e){t.exports=a},"rxjs/operators":function(t,e){t.exports=r}})},t.exports=a(n("Ip0R"),n("CcnG"),n("ZYjt"),n("DtyJ"),n("ahDk"))},yGOH:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(){return function(){}}()},yGWI:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(){return function(t){return t.lift(new s(t))}}var s=function(){function t(t){this.connectable=t}return t.prototype.call=function(t,e){var n=this.connectable;n._refCount++;var a=new o(t,n),r=e.subscribe(a);return a.closed||(a.connection=n.connect()),r},t}(),o=function(t){function e(e,n){var a=t.call(this,e)||this;return a.connectable=n,a}return a.__extends(e,t),e.prototype._unsubscribe=function(){var t=this.connectable;if(t){this.connectable=null;var e=t._refCount;if(e<=0)this.connection=null;else if(t._refCount=e-1,e>1)this.connection=null;else{var n=this.connection,a=t._connection;this.connection=null,!a||n&&a!==n||a.unsubscribe()}}else this.connection=null},e}(r.a)},yJti:function(t,e,n){"use strict";n.d(e,"a",function(){return a});var a=function(t){return t[t.ValueOk=0]="ValueOk",t[t.ValueStale=1]="ValueStale",t[t.ValueNone=2]="ValueNone",t[t.ValueException=3]="ValueException",t}({})},yPMN:function(t,e,n){"use strict";n("CDJp")._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),t.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},yPMs:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_N\xebntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_N\xebn_Dhj".split("_"),weekdays:"E Diel_E H\xebn\xeb_E Mart\xeb_E M\xebrkur\xeb_E Enjte_E Premte_E Shtun\xeb".split("_"),weekdaysShort:"Die_H\xebn_Mar_M\xebr_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_M\xeb_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(t){return"M"===t.charAt(0)},meridiem:function(t,e,n){return t<12?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot n\xeb] LT",nextDay:"[Nes\xebr n\xeb] LT",nextWeek:"dddd [n\xeb] LT",lastDay:"[Dje n\xeb] LT",lastWeek:"dddd [e kaluar n\xeb] LT",sameElse:"L"},relativeTime:{future:"n\xeb %s",past:"%s m\xeb par\xeb",s:"disa sekonda",ss:"%d sekonda",m:"nj\xeb minut\xeb",mm:"%d minuta",h:"nj\xeb or\xeb",hh:"%d or\xeb",d:"nj\xeb dit\xeb",dd:"%d dit\xeb",M:"nj\xeb muaj",MM:"%d muaj",y:"nj\xeb vit",yy:"%d vite"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},ylLw:function(t,e,n){var a=n("mrSG").__decorate,r=n("mrSG").__metadata;Object.defineProperty(e,"__esModule",{value:!0});var i=n("CcnG"),s=n("3MdB");n("ZYjt"),e.OrderableDirective=function(){function t(t,e){this.document=e,this.reorder=new i.EventEmitter,this.targetChanged=new i.EventEmitter,this.differ=t.find({}).create()}return t.prototype.ngAfterContentInit=function(){this.updateSubscriptions(),this.draggables.changes.subscribe(this.updateSubscriptions.bind(this))},t.prototype.ngOnDestroy=function(){this.draggables.forEach(function(t){t.dragStart.unsubscribe(),t.dragging.unsubscribe(),t.dragEnd.unsubscribe()})},t.prototype.updateSubscriptions=function(){var t=this,e=this.differ.diff(this.createMapDiffs());if(e){var n=function(t){var e=t.previousValue;e&&(e.dragStart.unsubscribe(),e.dragging.unsubscribe(),e.dragEnd.unsubscribe())};e.forEachAddedItem((function(e){var a=e.currentValue;n({previousValue:e.previousValue}),a&&(a.dragStart.subscribe(t.onDragStart.bind(t)),a.dragging.subscribe(t.onDragging.bind(t)),a.dragEnd.subscribe(t.onDragEnd.bind(t)))}).bind(this)),e.forEachRemovedItem(n.bind(this))}},t.prototype.onDragStart=function(){this.positions={};for(var t=0,e=0,n=this.draggables.toArray();e<n.length;e++){var a=n[e],r=a.element,i=parseInt(r.offsetLeft.toString(),0);this.positions[a.dragModel.prop]={left:i,right:i+parseInt(r.offsetWidth.toString(),0),index:t++,element:r}}},t.prototype.onDragging=function(t){var e=t.model,n=this.positions[e.prop],a=this.isTarget(e,t.event);a?this.lastDraggingIndex!==a.i&&(this.targetChanged.emit({prevIndex:this.lastDraggingIndex,newIndex:a.i,initialIndex:n.index}),this.lastDraggingIndex=a.i):this.lastDraggingIndex!==n.index&&(this.targetChanged.emit({prevIndex:this.lastDraggingIndex,initialIndex:n.index}),this.lastDraggingIndex=n.index)},t.prototype.onDragEnd=function(t){var e=t.element,n=t.model,a=this.positions[n.prop],r=this.isTarget(n,t.event);r&&this.reorder.emit({prevIndex:a.index,newIndex:r.i,model:n}),this.lastDraggingIndex=void 0,e.style.left="auto"},t.prototype.isTarget=function(t,e){var n=0,a=this.document.elementsFromPoint(e.x||e.clientX,e.y||e.clientY),r=function(e){var r=i.positions[e];if(t.prop!==e&&a.find(function(t){return t===r.element}))return{value:{pos:r,i:n}};n++},i=this;for(var s in this.positions){var o=r(s);if("object"==typeof o)return o.value}},t.prototype.createMapDiffs=function(){return this.draggables.toArray().reduce(function(t,e){return t[e.dragModel.$$id]=e,t},{})},a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"reorder",void 0),a([i.Output(),r("design:type",i.EventEmitter)],t.prototype,"targetChanged",void 0),a([i.ContentChildren(s.DraggableDirective,{descendants:!0}),r("design:type",i.QueryList)],t.prototype,"draggables",void 0),a([i.Directive({selector:"[orderable]"})],t)}()},z1FC:function(t,e,n){!function(t){"use strict";function e(t,e,n,a){var r={s:["viensas secunds","'iensas secunds"],ss:[t+" secunds",t+" secunds"],m:["'n m\xedut","'iens m\xedut"],mm:[t+" m\xeduts",t+" m\xeduts"],h:["'n \xfeora","'iensa \xfeora"],hh:[t+" \xfeoras",t+" \xfeoras"],d:["'n ziua","'iensa ziua"],dd:[t+" ziuas",t+" ziuas"],M:["'n mes","'iens mes"],MM:[t+" mesen",t+" mesen"],y:["'n ar","'iens ar"],yy:[t+" ars",t+" ars"]};return a?r[n][0]:e?r[n][0]:r[n][1]}n("wd/R").defineLocale("tzl",{months:"Januar_Fevraglh_Mar\xe7_Avr\xefu_Mai_G\xfcn_Julia_Guscht_Setemvar_Listop\xe4ts_Noemvar_Zecemvar".split("_"),monthsShort:"Jan_Fev_Mar_Avr_Mai_G\xfcn_Jul_Gus_Set_Lis_Noe_Zec".split("_"),weekdays:"S\xfaladi_L\xfane\xe7i_Maitzi_M\xe1rcuri_Xh\xfaadi_Vi\xe9ner\xe7i_S\xe1turi".split("_"),weekdaysShort:"S\xfal_L\xfan_Mai_M\xe1r_Xh\xfa_Vi\xe9_S\xe1t".split("_"),weekdaysMin:"S\xfa_L\xfa_Ma_M\xe1_Xh_Vi_S\xe1".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"D. MMMM [dallas] YYYY",LLL:"D. MMMM [dallas] YYYY HH.mm",LLLL:"dddd, [li] D. MMMM [dallas] YYYY HH.mm"},meridiemParse:/d\'o|d\'a/i,isPM:function(t){return"d'o"===t.toLowerCase()},meridiem:function(t,e,n){return t>11?n?"d'o":"D'O":n?"d'a":"D'A"},calendar:{sameDay:"[oxhi \xe0] LT",nextDay:"[dem\xe0 \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[ieiri \xe0] LT",lastWeek:"[s\xfcr el] dddd [lasteu \xe0] LT",sameElse:"L"},relativeTime:{future:"osprei %s",past:"ja%s",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}()},z3Vd:function(t,e,n){!function(t){"use strict";var e="pagh_wa\u2019_cha\u2019_wej_loS_vagh_jav_Soch_chorgh_Hut".split("_");function n(t,n,a,r){var i=function(t){var n=Math.floor(t%1e3/100),a=Math.floor(t%100/10),r=t%10,i="";return n>0&&(i+=e[n]+"vatlh"),a>0&&(i+=(""!==i?" ":"")+e[a]+"maH"),r>0&&(i+=(""!==i?" ":"")+e[r]),""===i?"pagh":i}(t);switch(a){case"ss":return i+" lup";case"mm":return i+" tup";case"hh":return i+" rep";case"dd":return i+" jaj";case"MM":return i+" jar";case"yy":return i+" DIS"}}t.defineLocale("tlh",{months:"tera\u2019 jar wa\u2019_tera\u2019 jar cha\u2019_tera\u2019 jar wej_tera\u2019 jar loS_tera\u2019 jar vagh_tera\u2019 jar jav_tera\u2019 jar Soch_tera\u2019 jar chorgh_tera\u2019 jar Hut_tera\u2019 jar wa\u2019maH_tera\u2019 jar wa\u2019maH wa\u2019_tera\u2019 jar wa\u2019maH cha\u2019".split("_"),monthsShort:"jar wa\u2019_jar cha\u2019_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa\u2019maH_jar wa\u2019maH wa\u2019_jar wa\u2019maH cha\u2019".split("_"),monthsParseExact:!0,weekdays:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysShort:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysMin:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[DaHjaj] LT",nextDay:"[wa\u2019leS] LT",nextWeek:"LLL",lastDay:"[wa\u2019Hu\u2019] LT",lastWeek:"LLL",sameElse:"L"},relativeTime:{future:function(t){var e=t;return-1!==t.indexOf("jaj")?e.slice(0,-3)+"leS":-1!==t.indexOf("jar")?e.slice(0,-3)+"waQ":-1!==t.indexOf("DIS")?e.slice(0,-3)+"nem":e+" pIq"},past:function(t){var e=t;return-1!==t.indexOf("jaj")?e.slice(0,-3)+"Hu\u2019":-1!==t.indexOf("jar")?e.slice(0,-3)+"wen":-1!==t.indexOf("DIS")?e.slice(0,-3)+"ben":e+" ret"},s:"puS lup",ss:n,m:"wa\u2019 tup",mm:n,h:"wa\u2019 rep",hh:n,d:"wa\u2019 jaj",dd:n,M:"wa\u2019 jar",MM:n,y:"wa\u2019 DIS",yy:n},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(n("wd/R"))},z5nN:function(t,e,n){"use strict";n.d(e,"b",function(){return u}),n.d(e,"a",function(){return f});var a=n("CcnG"),r=n("DQlY"),i=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function s(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,2,"div",[["role","document"]],[[8,"className",0]],null,null,null,null)),(t()(),a["\u0275eld"](1,0,null,null,1,"div",[["class","modal-content"]],null,null,null,null,null)),a["\u0275ncd"](null,0)],null,function(t,e){var n=e.component;t(e,0,0,"modal-dialog"+(n.config.class?" "+n.config.class:""))})}function o(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"modal-container",[["class","modal"],["role","dialog"],["tabindex","-1"]],[[1,"aria-modal",0]],[[null,"click"],["window","keydown.esc"]],function(t,e,n){var r=!0;return"click"===e&&(r=!1!==a["\u0275nov"](t,1).onClick(n)&&r),"window:keydown.esc"===e&&(r=!1!==a["\u0275nov"](t,1).onEsc(n)&&r),r},s,i)),a["\u0275did"](1,245760,null,0,r.d,[r.f,a.ElementRef,a.Renderer2],null,null)],function(t,e){t(e,1,0)},function(t,e){t(e,0,0,!0)})}var u=a["\u0275ccf"]("modal-container",r.d,o,{},{},["*"]),c=a["\u0275crt"]({encapsulation:2,styles:[],data:{}});function l(t){return a["\u0275vid"](0,[],null,null)}function d(t){return a["\u0275vid"](0,[(t()(),a["\u0275eld"](0,0,null,null,1,"bs-modal-backdrop",[["class","modal-backdrop"]],null,null,null,l,c)),a["\u0275did"](1,114688,null,0,r.c,[a.ElementRef,a.Renderer2],null,null)],function(t,e){t(e,1,0)},null)}var f=a["\u0275ccf"]("bs-modal-backdrop",r.c,d,{},{},[])},zAZS:function(t,e,n){"use strict";n.d(e,"a",function(){return i});var a=n("mrSG"),r=n("FFOo");function i(t,e){return function(n){return n.lift(new s(t,e,n))}}var s=function(){function t(t,e,n){this.predicate=t,this.thisArg=e,this.source=n}return t.prototype.call=function(t,e){return e.subscribe(new o(t,this.predicate,this.thisArg,this.source))},t}(),o=function(t){function e(e,n,a,r){var i=t.call(this,e)||this;return i.predicate=n,i.thisArg=a,i.source=r,i.index=0,i.thisArg=a||i,i}return a.__extends(e,t),e.prototype.notifyComplete=function(t){this.destination.next(t),this.destination.complete()},e.prototype._next=function(t){var e=!1;try{e=this.predicate.call(this.thisArg,t,this.index++,this.source)}catch(n){return void this.destination.error(n)}e||this.notifyComplete(!1)},e.prototype._complete=function(){this.notifyComplete(!0)},e}(r.a)},zQHH:function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("15JJ");function r(t,e){return e?Object(a.a)(function(){return t},e):Object(a.a)(function(){return t})}},zUnb:function(t,e,n){"use strict";n.r(e);var a=n("tAZD"),r=n.n(a),i=n("Ip0R"),s=n("CcnG"),o=function(t){t=t||"en-US";try{return n("vOVK")("./messages."+t+".xlf")}catch(e){return[]}},u=function(){return function(){}}(),c=n("eajB"),l=n("aexS"),d=function(){return Object.assign(new c.a,{container:"body"})},f=function(){function t(t,e){this.authStorageService=t,this.router=e,this.title="cd"}return t.prototype.isLoginActive=function(){return"/login"===this.router.url||!this.authStorageService.isLoggedIn()},t.prototype.isDashboardPage=function(){return"/dashboard"===this.router.url},t}(),p=n("mrSG"),h=n("S5bw"),g=function(){function t(){}return t.START="start",t.STOP="stop",t.UPDATE="update",t.RESET="reset",t.UNSUBSCRIBE="unsubscribe",t}(),b="block-ui-main",m=function(){function t(){this.blockUISettings={},this.blockUIInstances={},this.blockUISubject=new h.a,this.blockUIObservable=this.blockUISubject.asObservable(),this.blockUIObservable.subscribe(this.blockUIMiddleware.bind(this))}return t.prototype.getSettings=function(){return this.blockUISettings},t.prototype.updateSettings=function(t){void 0===t&&(t={}),this.blockUISettings=Object(p.__assign)({},this.blockUISettings,t)},t.prototype.decorate=function(t){void 0===t&&(t=b);var e={name:t,isActive:!1,blockCount:0,start:this.dispatch(this.blockUISubject,g.START,t),update:this.dispatch(this.blockUISubject,g.UPDATE,t),stop:this.dispatch(this.blockUISubject,g.STOP,t),reset:this.dispatch(this.blockUISubject,g.RESET,t),unsubscribe:this.dispatch(this.blockUISubject,g.UNSUBSCRIBE,t)};return this.blockUIInstances[t]=this.blockUIInstances[t]||e,e},t.prototype.observe=function(){return this.blockUIObservable},t.prototype.blockUIMiddleware=function(t){var e=t.name,n=null;switch(t.action){case g.START:n=!0;break;case g.STOP:case g.RESET:n=!1}null!==n&&(this.blockUIInstances[e].isActive=n)},t.prototype.dispatch=function(t,e,n){return void 0===n&&(n=b),function(a){t.next({name:n,action:e,message:a})}},t}(),y=function(){function t(t){this.blockUI=t}return t.prototype.ngOnInit=function(){this.name=this.name||b,this.template=this.template||this.blockUI.blockUISettings.template},t}(),v=function(){function t(t,e,n){this.blockUI=t,this.resolver=e,this.changeDetectionRef=n,this.name=b,this.delayStart=0,this.delayStop=0,this.state={startTimeout:null,stopTimeout:null,blockCount:0},this.active=!1}return t.prototype.ngOnInit=function(){this.settings=this.blockUI.getSettings(),this.blockUISubscription=this.subscribeToBlockUI(this.blockUI.observe())},t.prototype.ngAfterViewInit=function(){try{if(!this.templateCmp)return!1;if(this.templateCmp instanceof s.TemplateRef)this.templateOutlet.createEmbeddedView(this.templateCmp);else{var t=this.resolver.resolveComponentFactory(this.templateCmp);this.templateCompRef=this.templateOutlet.createComponent(t),this.updateBlockTemplate(this.message)}}catch(e){console.error("ng-block-ui:",e)}},t.prototype.ngAfterViewChecked=function(){this.changeDetectionRef.detectChanges()},t.prototype.subscribeToBlockUI=function(t){var e=this;return t.subscribe(function(t){return e.onDispatchedEvent(t)})},t.prototype.onDispatchedEvent=function(t){switch(t.action){case g.START:this.onStart(t);break;case g.STOP:this.onStop(t);break;case g.UPDATE:this.onUpdate(t);break;case g.RESET:this.onReset();break;case g.UNSUBSCRIBE:this.onStop(t),this.onUnsubscribe(t.name)}},t.prototype.onStart=function(t){var e=this,n=t.message;if(t.name===this.name){var a=this.delayStart||this.settings.delayStart||0;a?(null===this.state.startTimeout&&(this.state.startTimeout=setTimeout(function(){e.showBlock(n)},a)),this.state.blockCount++):this.showBlock(n),this.updateInstanceBlockCount()}},t.prototype.onStop=function(t){var e=this;if(t.name===this.name){if(this.state.blockCount>1)this.state.blockCount--;else if(this.active){var n=this.delayStop||this.settings.delayStop||0;n?null===this.state.stopTimeout&&(this.state.stopTimeout=setTimeout(function(){e.hideBlock()},n)):this.hideBlock()}else this.clearState();this.updateInstanceBlockCount()}},t.prototype.onReset=function(){this.hideBlock()},t.prototype.onUpdate=function(t){var e=t.message;t.name===this.name&&(this.active=!0,this.message=e||this.defaultMessage||this.settings.message,this.updateBlockTemplate(this.message),this.changeDetectionRef.detectChanges())},t.prototype.showBlock=function(t){this.active=!0,this.message=t||this.defaultMessage||this.settings.message,this.updateBlockTemplate(this.message),this.changeDetectionRef.detectChanges()},t.prototype.hideBlock=function(){this.clearState(),this.active=!1,this.changeDetectionRef.detectChanges()},t.prototype.clearState=function(){null!=this.state.startTimeout&&clearTimeout(this.state.startTimeout),null!=this.state.stopTimeout&&clearTimeout(this.state.stopTimeout),this.state.blockCount=0,this.state.startTimeout=null,this.state.stopTimeout=null,this.updateInstanceBlockCount()},t.prototype.updateBlockTemplate=function(t){this.templateCompRef&&this.templateCompRef instanceof s.ComponentRef&&(this.templateCompRef.instance.message=t)},t.prototype.onUnsubscribe=function(t){this.blockUISubscription&&t===this.name&&this.blockUISubscription.unsubscribe()},t.prototype.updateInstanceBlockCount=function(){this.blockUI.blockUIInstances[this.name]&&(this.blockUI.blockUIInstances[this.name].blockCount=this.state.blockCount)},t.prototype.ngOnDestroy=function(){this.onUnsubscribe(this.name)},t}(),_=function(){function t(t){this.blockUIInstance=t}return t.prototype.start=function(t,e){this.dispatch(t,g.START,e)},t.prototype.stop=function(t){this.dispatch(t,g.STOP)},t.prototype.unsubscribe=function(t){this.dispatch(t,g.UNSUBSCRIBE)},t.prototype.isActive=function(t){void 0===t&&(t=null);var e=t?this.toArray(t):null,n=this.blockUIInstance.blockUIInstances;return Object.keys(n).some(function(t){return e?e.indexOf(n[t].name)>=0&&n[t].isActive:n[t].isActive})},t.prototype.dispatch=function(t,e,n){var a=this;void 0===t&&(t=[]),this.toArray(t).forEach(function(t){return a.blockUIInstance.decorate(t)[e](n)})},t.prototype.toArray=function(t){return void 0===t&&(t=[]),"string"==typeof t?[t]:t},t}(),x=new m,T=new s.InjectionToken("BlockUIModuleSettings");function w(t){return x.updateSettings(t),x}var S=function(){function t(){}return t.forRoot=function(e){return void 0===e&&(e={}),{ngModule:t,providers:[{provide:T,useValue:e},{provide:m,useFactory:w,deps:[T]},_]}},t}(),O=s["\u0275crt"]({encapsulation:2,styles:[],data:{}});function I(t){return s["\u0275vid"](0,[s["\u0275ncd"](null,0),(t()(),s["\u0275eld"](1,0,null,null,1,"block-ui-content",[],null,null,null,L,N)),s["\u0275did"](2,12828672,null,0,v,[m,s.ComponentFactoryResolver,s.ChangeDetectorRef],{name:[0,"name"],delayStart:[1,"delayStart"],delayStop:[2,"delayStop"],defaultMessage:[3,"defaultMessage"],templateCmp:[4,"templateCmp"]},null)],function(t,e){var n=e.component;t(e,2,0,n.name,n.delayStart,n.delayStop,n.message,n.template)},null)}function C(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"block-ui",[],null,null,null,I,O)),s["\u0275did"](1,114688,null,0,y,[m],null,null)],function(t,e){t(e,1,0)},null)}var k=s["\u0275ccf"]("block-ui",y,C,{name:"name",message:"message",delayStart:"delayStart",delayStop:"delayStop",template:"template"},{},["*"]),N=s["\u0275crt"]({encapsulation:2,styles:["\n.block-ui-wrapper {\n display: none;\n position: fixed;\n height: 100%;\n width: 100%;\n top: 0;\n left: 0;\n background: rgba(0, 0, 0, 0.70);\n z-index: 30000;\n cursor: wait;\n}\n\n.block-ui-wrapper.block-ui-wrapper--element {\n position: absolute;\n}\n\n.block-ui-wrapper.active {\n display: block;\n}\n\n.block-ui-wrapper.block-ui-main {\n position: fixed;\n}\n\n.block-ui-spinner,\n.block-ui-template {\n position: absolute;\n top: 40%;\n margin: 0 auto;\n left: 0;\n right: 0;\n transform: translateY(-50%);\n}\n\n.block-ui-spinner > .message {\n font-size: 1.3em;\n text-align: center;\n color: #fff;\n}\n\n.block-ui__element {\n position: relative;\n}\n\n.loader,\n.loader:after {\n border-radius: 50%;\n width: 10em;\n height: 10em;\n}\n.loader {\n margin: 7px auto;\n font-size: 5px;\n position: relative;\n text-indent: -9999em;\n border-top: 1.1em solid rgba(255, 255, 255, 0.2);\n border-right: 1.1em solid rgba(255, 255, 255, 0.2);\n border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);\n border-left: 1.1em solid #ffffff;\n -webkit-transform: translateZ(0);\n -ms-transform: translateZ(0);\n transform: translateZ(0);\n -webkit-animation: load8 1.1s infinite linear;\n animation: load8 1.1s infinite linear;\n}\n\n@-webkit-keyframes load8 {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n@keyframes load8 {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n"],data:{}});function R(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["class","message"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){var n=e.component;t(e,1,0,n.message||n.defaultMessage)})}function A(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"div",[["class","block-ui-spinner"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,0,"div",[["class","loader"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,R)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,n.message||n.defaultMessage)},null)}function D(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](0,null,null,0))],null,null)}function E(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,[[1,3],["templateOutlet",2]],null,0,null,D)),(t()(),s["\u0275and"](0,null,null,0))],null,null)}function L(t){return s["\u0275vid"](0,[s["\u0275qud"](671088640,1,{templateOutlet:0}),(t()(),s["\u0275eld"](1,0,null,null,6,"div",[],null,null,null,null,null)),s["\u0275did"](2,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](3,{active:0}),(t()(),s["\u0275and"](16777216,null,null,1,null,A)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,E)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=s["\u0275inlineInterpolate"](2,"block-ui-wrapper ",n.name," ",n.className,""),r=t(e,3,0,n.active);t(e,2,0,a,r),t(e,5,0,!n.templateCmp),t(e,7,0,n.templateCmp)},null)}function P(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"block-ui-content",[],null,null,null,L,N)),s["\u0275did"](1,12828672,null,0,v,[m,s.ComponentFactoryResolver,s.ChangeDetectorRef],null,null)],function(t,e){t(e,1,0)},null)}var M=s["\u0275ccf"]("block-ui-content",v,P,{name:"name",delayStart:"delayStart",delayStop:"delayStop",defaultMessage:"message",templateCmp:"template"},{},[]),q=n("SZbH"),j=s["\u0275crt"]({encapsulation:2,styles:[],data:{animation:[{type:7,name:"flyInOut",definitions:[{type:0,name:"inactive",styles:{type:6,styles:{opacity:0},offset:null},options:void 0},{type:0,name:"active",styles:{type:6,styles:{opacity:1},offset:null},options:void 0},{type:0,name:"removed",styles:{type:6,styles:{opacity:0},offset:null},options:void 0},{type:1,expr:"inactive => active",animation:{type:4,styles:null,timings:"{{ easeTime }}ms {{ easing }}"},options:null},{type:1,expr:"active => removed",animation:{type:4,styles:null,timings:"{{ easeTime }}ms {{ easing }}"},options:null}],options:{}}]}});function F(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"button",[["aria-label","Close"],["class","toast-close-button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.remove()&&a),a},null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xd7"]))],null,null)}function z(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["[","]"]))],null,function(t,e){t(e,1,0,e.component.duplicatesCount+1)})}function G(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"div",[],[[8,"className",0],[1,"aria-label",0]],null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "])),(t()(),s["\u0275and"](16777216,null,null,1,null,z)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,3,0,e.component.duplicatesCount)},function(t,e){var n=e.component;t(e,0,0,n.options.titleClass,n.title),t(e,1,0,n.title)})}function Y(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"div",[["aria-live","polite"],["role","alertdialog"]],[[8,"className",0],[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){var n=e.component;t(e,0,0,n.options.messageClass,n.message)})}function V(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["aria-live","polite"],["role","alertdialog"]],[[8,"className",0],[1,"aria-label",0]],null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){var n=e.component;t(e,0,0,n.options.messageClass,n.message),t(e,1,0,n.message)})}function H(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,0,"div",[["class","toast-progress"]],[[4,"width",null]],null,null,null,null))],null,function(t,e){t(e,1,0,e.component.width+"%")})}function B(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,F)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,G)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Y)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,V)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,H)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.options.closeButton),t(e,3,0,n.title),t(e,5,0,n.message&&n.options.enableHtml),t(e,7,0,n.message&&!n.options.enableHtml),t(e,9,0,n.options.progressBar)},null)}function U(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["toast-component",""]],[[8,"className",0],[40,"@flyInOut",0],[4,"display",null]],[[null,"click"],[null,"mouseenter"],[null,"mouseleave"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,1).tapToast()&&a),"mouseenter"===e&&(a=!1!==s["\u0275nov"](t,1).stickAround()&&a),"mouseleave"===e&&(a=!1!==s["\u0275nov"](t,1).delayedHideToast()&&a),a},B,j)),s["\u0275did"](1,180224,null,0,q.c,[q.j,q.g,s.NgZone],null,null)],null,function(t,e){t(e,0,0,s["\u0275nov"](e,1).toastClasses,s["\u0275nov"](e,1).state,s["\u0275nov"](e,1).displayStyle)})}var W=s["\u0275ccf"]("[toast-component]",q.c,U,{},{},[]),K=n("pMnS"),$=n("pKUh"),Z=n("YAQW"),X=n("OZfm"),J=n("lqqz"),Q=n("NJnL"),tt=n("ZYCi"),et=function(){return function(){this.cardClass=""}}(),nt=s["\u0275crt"]({encapsulation:0,styles:[[".card[_ngcontent-%COMP%]{border:.5px solid #ddd;border-radius:3px;background-color:#fff;box-shadow:0 1px 1px rgba(3,3,3,.175);margin:0 auto 20px;padding:0 20px;width:auto;height:auto;min-height:6vw;position:relative;font-size:12px}@media screen and (min-width:320px){.card[_ngcontent-%COMP%]{font-size:calc(12px + 9 * ((100vw - 320px)/ 1728))}}@media screen and (min-width:2048px){.card[_ngcontent-%COMP%]{font-size:21px}}.card-title[_ngcontent-%COMP%]{margin:1.1vw 0;padding:0}.card-body[_ngcontent-%COMP%]{text-align:center;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%)}.content-chart[_ngcontent-%COMP%]{margin-top:-.7vw;position:unset;top:unset;left:unset;-webkit-transform:unset;transform:unset}.no-center[_ngcontent-%COMP%]{position:unset;top:unset;left:unset;-webkit-transform:unset;transform:unset}.text-area-size-2[_ngcontent-%COMP%]{margin-right:-50%;-webkit-transform:translate(-50%,-20%);transform:translate(-50%,-20%)}.text-area-size-3[_ngcontent-%COMP%]{margin-right:-50%;-webkit-transform:translate(-50%,-40%);transform:translate(-50%,-40%)}.content-highlight[_ngcontent-%COMP%]{font-weight:700}.card-medium[_ngcontent-%COMP%]{min-height:12vw}.scroll[_ngcontent-%COMP%]{max-height:18vw;overflow-y:auto}.text-monospace[_ngcontent-%COMP%]{font-size:12px;font-family:monospace;text-align:left}@media (max-width:1599px){.card[_ngcontent-%COMP%]{min-height:7.8vw}.card-medium[_ngcontent-%COMP%]{min-height:14.4vw}}@media (max-width:calc(1200px - 1px)){.card-medium[_ngcontent-%COMP%]{min-height:18vw}.content-chart[_ngcontent-%COMP%]{margin-top:-.6vw}}@media (max-width:calc(992px - 1px)){.card[_ngcontent-%COMP%]{min-height:12vw}.content-chart[_ngcontent-%COMP%]{margin-top:-.3vw}}@media (max-width:calc(992px - 1px)) and (min-width:768px){.card-medium[_ngcontent-%COMP%]{min-height:26.4vw}}@media (max-width:599px){.card[_ngcontent-%COMP%]{min-height:18vw}}@media (max-width:319px){.card[_ngcontent-%COMP%]{min-height:24vw}}"]],data:{}});function at(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"a",[],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,1).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](1,671744,null,0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](2,null,["",""]))],function(t,e){t(e,1,0,e.component.link)},function(t,e){var n=e.component;t(e,0,0,s["\u0275nov"](e,1).target,s["\u0275nov"](e,1).href),t(e,2,0,n.cardTitle)})}function rt(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](0,null,[" "," "]))],null,function(t,e){t(e,0,0,e.component.cardTitle)})}function it(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"div",[["class","card"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),s["\u0275eld"](2,0,null,null,3,"div",[["class","card-title"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,at)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),s["\u0275and"](0,[["noLinkTitle",2]],null,0,null,rt)),(t()(),s["\u0275eld"](6,0,null,null,2,"div",[["class","card-body"]],null,null,null,null,null)),s["\u0275did"](7,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275ncd"](null,0)],function(t,e){var n=e.component;t(e,1,0,"card",n.cardClass),t(e,4,0,n.link,s["\u0275nov"](e,5)),t(e,7,0,"card-body",n.contentClass)},null)}var st=function(){return function(){}}(),ot=s["\u0275crt"]({encapsulation:0,styles:[[".info-group-title[_ngcontent-%COMP%]{margin:0 0 .5vw .5vw;padding:0;font-size:21px}"]],data:{}});function ut(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["class","info-group-title"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ","\n"])),s["\u0275ncd"](null,0)],null,function(t,e){t(e,1,0,e.component.groupTitle)})}var ct,lt=n("xdbM"),dt=n("WyAD"),ft=n("LvDl"),pt=n("NEZu"),ht=n("Fgil"),gt=n("o4+5");!function(t){t.DEFAULT_RED="#ff7592",t.DEFAULT_BLUE="#1d699d",t.DEFAULT_ORANGE="#ffa500",t.DEFAULT_MAGENTA="#564d65",t.DEFAULT_GREEN="#00bb00"}(ct||(ct={}));var bt=function(){function t(t,e){var n=this;this.dimlessBinary=t,this.dimless=e,this.config={},this.isBytesData=!1,this.showLabelAsTooltip=!1,this.prepareFn=new s.EventEmitter,this.chartConfig={chartType:"pie",dataset:[{label:null,borderWidth:0}],options:{legend:{display:!0,position:"right",labels:{usePointStyle:!0},onClick:function(t,e){n.onLegendClick(t,e)}},animation:{duration:0},tooltips:{enabled:!1},title:{display:!1}}},this.hiddenSlices=[]}return t.prototype.ngOnInit=function(){var t=this;dt.pluginService.register({beforeDraw:function(t){if(t.options.center_text){var e=t.chart.width,n=t.chart.height,a=t.chart.ctx;a.restore();var r=(n/114).toFixed(2);a.font=r+"em sans-serif",a.textBaseline="middle";var i=t.options.center_text,s=Math.round((e-a.measureText(i).width)/2);a.fillText(i,s,n/2),a.save()}}});var e=new pt.a(this.chartCanvasRef,this.chartTooltipRef,function(t,e){return e+t.caretX+"px"},function(t,e){return e+t.caretY-t.height-10+"px"});e.getBody=function(e){return t.getChartTooltipBody(e)},this.chartConfig.options.tooltips.custom=function(t){e.customTooltips(t)},this.chartConfig.colors=[{backgroundColor:[ct.DEFAULT_RED,ct.DEFAULT_BLUE,ct.DEFAULT_ORANGE,ct.DEFAULT_GREEN,ct.DEFAULT_MAGENTA]}],ft.merge(this.chartConfig,this.config),this.prepareFn.emit([this.chartConfig,this.data])},t.prototype.ngOnChanges=function(){this.prepareFn.emit([this.chartConfig,this.data]),this.hideSlices(),this.setChartSliceBorderWidth()},t.prototype.getChartTooltipBody=function(t){var e=t[0].split(": ");return this.showLabelAsTooltip?e[0]:(e[1]=this.isBytesData?this.dimlessBinary.transform(e[1]):this.dimless.transform(e[1]),e.join(": "))},t.prototype.setChartSliceBorderWidth=function(){var t=0;ft.forEach(this.chartConfig.dataset[0].data,function(e){e>0&&(t+=1)}),this.chartConfig.dataset[0].borderWidth=t>1?1:0},t.prototype.onLegendClick=function(t,e){t.stopPropagation(),this.hiddenSlices[e.index]=!e.hidden,this.ngOnChanges()},t.prototype.hideSlices=function(){var t=this;ft.forEach(this.chartConfig.dataset[0].data,function(e,n){t.hiddenSlices[n]&&(t.chartConfig.dataset[0].data[n]=void 0)})},t}(),mt=s["\u0275crt"]({encapsulation:0,styles:[["canvas[_ngcontent-%COMP%]{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.chartjs-tooltip[_ngcontent-%COMP%]{opacity:0;position:absolute;background:rgba(0,0,0,.7);color:#fff;border-radius:3px;-webkit-transition:.1s;transition:all .1s ease;pointer-events:none;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif!important;-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]{-webkit-transform:translate(-10%,0);transform:translate(-10%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]::after{left:10%}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]{-webkit-transform:translate(-90%,0);transform:translate(-90%,0)}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]::after{left:90%}.chartjs-tooltip[_ngcontent-%COMP%]::after{content:' ';position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:#000 transparent transparent} .chartjs-tooltip-key{display:inline-block;width:10px;height:10px;margin-right:10px}.chart-container[_ngcontent-%COMP%]{margin:auto;cursor:pointer;overflow:visible;position:unset;width:100%;height:100%}.chart-canvas[_ngcontent-%COMP%]{position:unset;width:100%;height:100%;margin-left:auto;margin-right:auto;max-width:100%;max-height:100%}"]],data:{}});function yt(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{chartCanvasRef:0}),s["\u0275qud"](402653184,2,{chartTooltipRef:0}),(t()(),s["\u0275eld"](2,0,null,null,4,"div",[["class","chart-container"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,[[1,0],["chartCanvas",1]],null,1,"canvas",[["baseChart",""],["class","chart-canvas"]],null,null,null,null,null)),s["\u0275did"](4,737280,null,0,lt.BaseChartDirective,[s.ElementRef],{datasets:[0,"datasets"],labels:[1,"labels"],options:[2,"options"],chartType:[3,"chartType"],colors:[4,"colors"]},null),(t()(),s["\u0275eld"](5,0,[[2,0],["chartTooltip",1]],null,1,"div",[["class","chartjs-tooltip"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,0,"table",[],null,null,null,null,null))],function(t,e){var n=e.component;t(e,4,0,n.chartConfig.dataset,n.chartConfig.labels,n.chartConfig.options,n.chartConfig.chartType,n.chartConfig.colors)},null)}var vt=function(){function t(){}return t.prototype.transform=function(t){return"HEALTH_OK"===t?{color:"#00bb00"}:"HEALTH_WARN"===t?{color:"#ffa500"}:"HEALTH_ERR"===t?{color:"#ff0000"}:null},t}(),_t=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t){return t?t.monmap.mons.length.toString()+" ("+this.i18n("quorum")+" "+t.quorum.join(", ")+")":""},t}(),xt=n("Jm/i"),Tt=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t){if(!t)return"";var e=0,n=0;ft.each(t.osds,function(t){t.in&&e++,t.up&&n++});var a=[{content:t.osds.length+" "+this.i18n("total"),class:""}];a.push({content:"",class:"card-text-line-break"}),a.push({content:n+" "+this.i18n("up")+", "+e+" "+this.i18n("in"),class:""});var r=t.osds.length-n,i=n-e;if(r>0||i>0){a.push({content:"",class:"card-text-line-break"});var s=r>0?r+" "+this.i18n("down"):"",o=r>0&&i>0?", ":"",u=i>0?i+" "+this.i18n("out"):"";a.push({content:""+s+o+u,class:"card-text-error"})}return a},t}(),wt=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t){if(!t)return"";var e=this.i18n("n/a"),n=ft.isUndefined(t.active_name)?"":this.i18n("active daemon")+": "+t.active_name;n.length>0&&(e="1");var a=t.standbys.map(function(t){return t.name}).join(", "),r=a?this.i18n("standby daemons")+": "+a:"",i=t.standbys.length,s=[{content:e+" "+this.i18n("active"),class:"popover-info",titleText:n}];return s.push({content:"",class:"card-text-line-break",titleText:""}),s.push({content:i+" "+this.i18n("standby"),class:"popover-info",titleText:r}),s},t}(),St=function(){function t(t){this.i18n=t}return t.prototype.transform=function(t){if(!t)return"";var e="",n="",a=0,r=0,i=0;ft.each(t.standbys,function(){a+=1}),t.standbys&&!t.filesystems?(e=a+" "+this.i18n("up"),n=this.i18n("no filesystems")):0===t.filesystems.length?e=this.i18n("no filesystems"):(ft.each(t.filesystems,function(t){ft.each(t.mdsmap.info,function(t){"up:standby-replay"===t.state?i+=1:r+=1})}),e=r+" "+this.i18n("active"),n=a+i+" "+this.i18n("standby"));var s=t.standbys.map(function(t){return t.name}).join(", "),o=s?this.i18n("standby daemons")+": "+s:"",u=t.filesystems?t.filesystems.length:0,c=Object.values(u>0?t.filesystems[0].mdsmap.info:{}).map(function(t){return t.name}).join(", "),l=c?this.i18n("active daemon")+": "+c:"";!r&&u>0&&(l=i+" "+this.i18n("standbyReplay"));var d=[{content:e,class:"popover-info",titleText:l}];return n&&(d.push({content:"",class:"card-text-line-break",titleText:""}),d.push({content:n,class:"popover-info",titleText:o})),d},t}(),Ot=function(){function t(){}return t.prototype.transform=function(t,e){return ft.round(t,e)},t}(),It=n("aXbf"),Ct=n("DtyJ"),kt=n("t/Na"),Nt=n("pL04"),Rt=function(){function t(t){this.http=t}return t.prototype.getFullHealth=function(){return this.http.get("api/health/full")},t.prototype.getMinimalHealth=function(){return this.http.get("api/health/minimal")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),At=n("ej+x"),Dt=n("26FU"),Et=n("xXU7"),Lt=function(){function t(){this.intervalDataSource=new Dt.a(null),this.intervalData$=this.intervalDataSource.asObservable();var t=parseInt(sessionStorage.getItem("dashboard_interval"),10)||5e3;this.setRefreshInterval(t)}return t.prototype.setRefreshInterval=function(t){var e=this;this.intervalTime=t,sessionStorage.setItem("dashboard_interval",t.toString()),this.intervalSubscription&&this.intervalSubscription.unsubscribe(),this.intervalSubscription=Object(Et.a)(this.intervalTime).subscribe(function(){return e.intervalDataSource.next(e.intervalTime)})},t.prototype.getRefreshInterval=function(){return this.intervalTime},t.prototype.ngOnDestroy=function(){this.intervalSubscription&&this.intervalSubscription.unsubscribe()},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t},token:t,providedIn:"root"}),t}(),Pt=n("d+Og"),Mt=function(){function t(t,e,n,a,r,i,s,o){this.healthService=t,this.i18n=e,this.authStorageService=n,this.pgCategoryService=a,this.featureToggles=r,this.refreshIntervalService=i,this.dimlessBinary=s,this.dimless=o,this.interval=new Ct.Subscription,this.rawCapacityChartConfig={options:{title:{display:!0,position:"bottom"}}},this.objectsChartConfig={options:{title:{display:!0,position:"bottom"}},colors:[{backgroundColor:[ct.DEFAULT_GREEN,ct.DEFAULT_MAGENTA,ct.DEFAULT_ORANGE,ct.DEFAULT_RED]}]},this.pgStatusChartConfig={colors:[{backgroundColor:[ct.DEFAULT_GREEN,ct.DEFAULT_BLUE,ct.DEFAULT_ORANGE,ct.DEFAULT_RED]}]},this.permissions=this.authStorageService.getPermissions(),this.enabledFeature$=this.featureToggles.get()}return t.prototype.ngOnInit=function(){var t=this;this.getHealth(),this.interval=this.refreshIntervalService.intervalData$.subscribe(function(){t.getHealth()})},t.prototype.ngOnDestroy=function(){this.interval.unsubscribe()},t.prototype.getHealth=function(){var t=this;this.healthService.getMinimalHealth().subscribe(function(e){t.healthData=e})},t.prototype.prepareReadWriteRatio=function(t){var e=[],n=[],a=this.healthData.client_perf.write_op_per_sec+this.healthData.client_perf.read_op_per_sec;e.push(this.i18n("Writes")+" ("+this.calcPercentage(this.healthData.client_perf.write_op_per_sec,a)+"%)"),n.push(this.healthData.client_perf.write_op_per_sec),e.push(this.i18n("Reads")+" ("+this.calcPercentage(this.healthData.client_perf.read_op_per_sec,a)+"%)"),n.push(this.healthData.client_perf.read_op_per_sec),t.dataset[0].data=n,t.labels=e},t.prototype.prepareRawUsage=function(t,e){var n=this.calcPercentage(e.df.stats.total_bytes-e.df.stats.total_used_raw_bytes,e.df.stats.total_bytes),a=this.calcPercentage(e.df.stats.total_used_raw_bytes,e.df.stats.total_bytes);t.dataset[0].data=[e.df.stats.total_used_raw_bytes,e.df.stats.total_avail_bytes],t.labels=[this.dimlessBinary.transform(e.df.stats.total_used_raw_bytes)+" "+this.i18n("Used")+" ("+a+"%)",this.dimlessBinary.transform(e.df.stats.total_bytes-e.df.stats.total_used_raw_bytes)+" "+this.i18n("Avail.")+" ("+n+"%)"],t.options.title.text=this.dimlessBinary.transform(e.df.stats.total_bytes)+" "+this.i18n("total")},t.prototype.preparePgStatus=function(t,e){var n=this,a={},r=0;ft.forEach(e.pg_info.statuses,function(t,e){var i=n.pgCategoryService.getTypeByStates(e);ft.isUndefined(a[i])&&(a[i]=0),a[i]+=t,r+=t}),t.dataset[0].data=this.pgCategoryService.getAllTypes().map(function(t){return a[t]}),t.labels=[this.i18n("Clean")+" ("+this.calcPercentage(a.clean,r)+"%)",this.i18n("Working")+" ("+this.calcPercentage(a.working,r)+"%)",this.i18n("Warning")+" ("+this.calcPercentage(a.warning,r)+"%)",this.i18n("Unknown")+" ("+this.calcPercentage(a.unknown,r)+"%)"]},t.prototype.prepareObjects=function(t,e){var n=e.pg_info.object_stats.num_object_copies,a=n-e.pg_info.object_stats.num_objects_misplaced-e.pg_info.object_stats.num_objects_degraded-e.pg_info.object_stats.num_objects_unfound;t.labels=[this.i18n("Healthy")+" ("+this.calcPercentage(a,n)+"%)",this.i18n("Misplaced")+" ("+this.calcPercentage(e.pg_info.object_stats.num_objects_misplaced,n)+"%)",this.i18n("Degraded")+" ("+this.calcPercentage(e.pg_info.object_stats.num_objects_degraded,n)+"%)",this.i18n("Unfound")+" ("+this.calcPercentage(e.pg_info.object_stats.num_objects_unfound,n)+"%)"],t.dataset[0].data=[a,e.pg_info.object_stats.num_objects_misplaced,e.pg_info.object_stats.num_objects_degraded,e.pg_info.object_stats.num_objects_unfound],t.options.title.text=this.dimless.transform(e.pg_info.object_stats.num_objects)+" "+this.i18n("total")+" ("+this.dimless.transform(n)+" "+this.i18n("replicas")+")",t.options.maintainAspectRatio=window.innerWidth>=375},t.prototype.isClientReadWriteChartShowable=function(){return(this.healthData.client_perf.read_op_per_sec||0)+(this.healthData.client_perf.write_op_per_sec||0)>0},t.prototype.calcPercentage=function(t,e){return ft.isNumber(t)&&ft.isNumber(e)&&0!==e?Math.round(t/e*100):0},t}(),qt=s["\u0275crt"]({encapsulation:0,styles:[["cd-info-card[_ngcontent-%COMP%]{padding:0 .5vw}.cd-container-flex[_ngcontent-%COMP%]{margin:0;padding:0;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-pack:justify;justify-content:space-between}.cd-col-5[_ngcontent-%COMP%]{width:20%}@media (max-width:1599px){.cd-col-5[_ngcontent-%COMP%]{width:25%}}@media (max-width:calc(1200px - 1px)){.cd-col-5[_ngcontent-%COMP%]{width:33%}}@media (max-width:calc(992px - 1px)){.cd-col-5[_ngcontent-%COMP%]{width:50%}}@media (max-width:calc(768px - 1px)){cd-info-card[_ngcontent-%COMP%]{padding:0}.cd-col-5[_ngcontent-%COMP%]{width:100%}}.info-group[_ngcontent-%COMP%]{margin:0;padding:0} .pg-status-popover-wrapper{position:relative} .pg-status-popover-wrapper .popover{position:absolute;width:116%;max-height:20vh;min-width:unset!important;max-width:unset!important} .pg-status-popover-wrapper .popover .popover-body{max-width:100%;max-height:19vh;font-size:12px}.logs-link[_ngcontent-%COMP%]{text-align:center}.card-text-error[_ngcontent-%COMP%]{display:inline;color:red}.card-text-line-break[_ngcontent-%COMP%]:after{content:'\\A';white-space:pre}.popover-info[_ngcontent-%COMP%]:hover{cursor:pointer}"]],data:{}});function jt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function Ft(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,3,"span",[],null,null,null,null,null)),s["\u0275did"](2,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null),s["\u0275ppd"](3,1),(t()(),s["\u0275ted"](4,null,["",""])),(t()(),s["\u0275ted"](5,null,[": "," "]))],function(t,e){var n=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent.parent.parent.parent,0),e.context.$implicit.severity));t(e,2,0,n)},function(t,e){t(e,4,0,e.context.$implicit.type),t(e,5,0,e.context.$implicit.summary.message)})}function zt(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,jt)),s["\u0275did"](1,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),s["\u0275eld"](2,0,null,null,2,"ul",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ft)),s["\u0275did"](4,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,1,0,s["\u0275nov"](e.parent.parent.parent.parent,7)),t(e,4,0,n.healthData.health.checks)},null)}function Gt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(t()(),s["\u0275and"](0,[["healthChecks",2]],null,0,null,zt)),(t()(),s["\u0275eld"](2,16777216,null,null,4,"div",[["class","info-card-content-clickable"],["container","body"],["containerClass","info-card-popover-cluster-status"],["placement","bottom"],["triggers",""]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).toggle()&&a),a},null,null)),s["\u0275did"](3,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null),s["\u0275ppd"](4,1),s["\u0275did"](5,212992,[["healthChecksTarget",4]],0,X.c,[X.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,Q.a],{popover:[0,"popover"],placement:[1,"placement"],triggers:[2,"triggers"],container:[3,"container"],containerClass:[4,"containerClass"]},null),(t()(),s["\u0275ted"](6,null,[" "," "])),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.component,a=s["\u0275unv"](e,3,0,t(e,4,0,s["\u0275nov"](e.parent.parent.parent.parent,0),n.healthData.health.status));t(e,3,0,a),t(e,5,0,s["\u0275nov"](e,1),"bottom","","body","info-card-popover-cluster-status")},function(t,e){t(e,6,0,e.component.healthData.health.status)})}function Yt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,3,"div",[],null,null,null,null,null)),s["\u0275did"](2,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null),s["\u0275ppd"](3,1),(t()(),s["\u0275ted"](4,null,[" "," "]))],function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent.parent,0),n.healthData.health.status));t(e,2,0,a)},function(t,e){t(e,4,0,e.component.healthData.health.status)})}function Vt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-info-card",[["cardTitle","Cluster Status"],["class","col-sm-6 col-md-4 col-lg-3"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],contentClass:[1,"contentClass"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Gt)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Yt)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"Cluster Status",(null==n.healthData.health?null:null==n.healthData.health.checks?null:n.healthData.health.checks.length)>0?"content-highlight text-area-size-2":"content-highlight"),t(e,3,0,(null==n.healthData.health?null:null==n.healthData.health.checks?null:n.healthData.health.checks.length)>0),t(e,5,0,!(null!=n.healthData.health&&null!=n.healthData.health.checks&&n.healthData.health.checks.length))},null)}function Ht(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardTitle","Monitors"],["class","col-sm-6 col-md-4 col-lg-3"],["contentClass","content-highlight"],["link","/monitor"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,1)],function(t,e){t(e,1,0,"Monitors","/monitor","content-highlight")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,1),n.healthData.mon_status));t(e,2,0,a)})}function Bt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),(t()(),s["\u0275ted"](2,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit.class)},function(t,e){t(e,2,0,e.context.$implicit.content)})}function Ut(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardTitle","OSDs"],["class","col-sm-6 col-md-4 col-lg-3"],["link","/osd"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Bt)),s["\u0275did"](3,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,1,0,"OSDs","/osd",(5==e.context.ngIf.length?"text-area-size-3":"text-area-size-2")+" content-highlight"),t(e,3,0,e.context.ngIf)},null)}function Wt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],[[8,"title",0]],null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),(t()(),s["\u0275ted"](2,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit.class)},function(t,e){t(e,0,0,null!=e.context.$implicit.titleText?e.context.$implicit.titleText:""),t(e,2,0,e.context.$implicit.content)})}function Kt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"cd-info-card",[["cardTitle","Manager Daemons"],["class","col-sm-6 col-md-4 col-lg-3"],["contentClass","content-highlight text-area-size-2"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],contentClass:[1,"contentClass"]},null),(t()(),s["\u0275and"](16777216,null,0,2,null,Wt)),s["\u0275did"](3,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275ppd"](4,1)],function(t,e){var n=e.component;t(e,1,0,"Manager Daemons","content-highlight text-area-size-2");var a=s["\u0275unv"](e,3,0,t(e,4,0,s["\u0275nov"](e.parent.parent.parent,3),n.healthData.mgr_map));t(e,3,0,a)},null)}function $t(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-info-card",[["cardTitle","Hosts"],["class","col-sm-6 col-md-4 col-lg-3"],["contentClass","content-medium content-highlight"],["link","/hosts"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," total "]))],function(t,e){t(e,1,0,"Hosts","/hosts","content-medium content-highlight")},function(t,e){t(e,2,0,e.component.healthData.hosts)})}function Zt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-info-card",[["cardTitle","Object Gateways"],["class","col-sm-6 col-md-4 col-lg-3"],["contentClass","content-medium content-highlight"],["link","/rgw/daemon"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," total "]))],function(t,e){t(e,1,0,"Object Gateways","/rgw/daemon","content-medium content-highlight")},function(t,e){t(e,2,0,e.component.healthData.rgw)})}function Xt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],[[8,"title",0]],null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),(t()(),s["\u0275ted"](2,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit.class)},function(t,e){t(e,0,0,null!=e.context.$implicit.titleText?e.context.$implicit.titleText:""),t(e,2,0,e.context.$implicit.content)})}function Jt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardTitle","Metadata Servers"],["class","col-sm-6 col-md-4 col-lg-3"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],contentClass:[1,"contentClass"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Xt)),s["\u0275did"](3,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,1,0,"Metadata Servers",(e.context.ngIf.length>1?"text-area-size-2":"")+" content-highlight"),t(e,3,0,e.context.ngIf)},null)}function Qt(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-info-card",[["cardTitle","iSCSI Gateways"],["class","col-sm-6 col-md-4 col-lg-3"],["contentClass","content-medium content-highlight"],["link","/block/iscsi"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," total "]))],function(t,e){t(e,1,0,"iSCSI Gateways","/block/iscsi","content-medium content-highlight")},function(t,e){t(e,2,0,e.component.healthData.iscsi_daemons)})}function te(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,19,"cd-info-group",[["class","row info-group"],["groupTitle","Status"]],null,null,null,ut,ot)),s["\u0275did"](1,49152,null,0,st,[],{groupTitle:[0,"groupTitle"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Vt)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Ht)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,2,null,Ut)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275ppd"](8,1),(t()(),s["\u0275and"](16777216,null,0,1,null,Kt)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,$t)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Zt)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,2,null,Jt)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275ppd"](17,1),(t()(),s["\u0275and"](16777216,null,0,1,null,Qt)),s["\u0275did"](19,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"Status"),t(e,3,0,null==n.healthData.health?null:n.healthData.health.status),t(e,5,0,n.healthData.mon_status);var a=s["\u0275unv"](e,7,0,t(e,8,0,s["\u0275nov"](e.parent.parent,2),n.healthData.osd_map));t(e,7,0,a),t(e,10,0,n.healthData.mgr_map),t(e,12,0,null!=n.healthData.hosts),t(e,14,0,e.parent.context.ngIf.rgw&&null!=n.healthData.rgw);var r=s["\u0275unv"](e,16,0,t(e,17,0,s["\u0275nov"](e.parent.parent,4),e.parent.context.ngIf.cephfs&&n.healthData.fs_map));t(e,16,0,r),t(e,19,0,e.parent.context.ngIf.iscsi&&null!=n.healthData.iscsi_daemons)},null)}function ee(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Client IOPS"],["class","cd-col-5"],["contentClass","content-medium content-highlight"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,2)],function(t,e){t(e,1,0,"Client IOPS","card-medium","content-medium content-highlight")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,5),n.healthData.client_perf.read_op_per_sec+n.healthData.client_perf.write_op_per_sec,1));t(e,2,0,a)})}function ne(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Client Throughput"],["class","cd-col-5"],["contentClass","content-medium content-highlight"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,1)],function(t,e){t(e,1,0,"Client Throughput","card-medium","content-medium content-highlight")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,6),n.healthData.client_perf.read_bytes_sec+n.healthData.client_perf.write_bytes_sec))+"/s";t(e,2,0,a)})}function ae(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-health-pie",[],null,[[null,"prepareFn"]],function(t,e,n){var a=!0;return"prepareFn"===e&&(a=!1!==t.component.prepareReadWriteRatio(n[0],n[1])&&a),a},yt,mt)),s["\u0275did"](1,638976,null,0,bt,[ht.a,gt.a],{data:[0,"data"]},{prepareFn:"prepareFn"})],function(t,e){t(e,1,0,e.component.healthData)},null)}function re(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" N/A "]))],null,null)}function ie(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Client Read/Write"],["class","cd-col-5"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,ae)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,re)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"Client Read/Write","card-medium",n.isClientReadWriteChartShowable()?"content-chart":"content-medium content-highlight"),t(e,3,0,n.isClientReadWriteChartShowable()),t(e,5,0,!n.isClientReadWriteChartShowable())},null)}function se(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Recovery Throughput"],["class","cd-col-5"],["contentClass","content-medium content-highlight"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,1)],function(t,e){t(e,1,0,"Recovery Throughput","card-medium","content-medium content-highlight")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,6),n.healthData.client_perf.recovering_bytes_per_sec))+"/s";t(e,2,0,a)})}function oe(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Scrub"],["class","cd-col-5"],["contentClass","content-medium content-highlight"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "]))],function(t,e){t(e,1,0,"Scrub","card-medium","content-medium content-highlight")},function(t,e){t(e,2,0,e.component.healthData.scrub_status)})}function ue(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,12,"cd-info-group",[["class","row info-group"],["groupTitle","Performance"]],null,null,null,ut,ot)),s["\u0275did"](1,49152,null,0,st,[],{groupTitle:[0,"groupTitle"]},null),(t()(),s["\u0275eld"](2,0,null,0,10,"div",[["class","cd-container-flex"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,ee)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ne)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ie)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,se)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,oe)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"Performance"),t(e,4,0,n.healthData.client_perf),t(e,6,0,n.healthData.client_perf),t(e,8,0,n.healthData.client_perf),t(e,10,0,n.healthData.client_perf),t(e,12,0,n.healthData.scrub_status)},null)}function ce(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Pools"],["class","cd-col-5"],["contentClass","content-medium content-highlight"],["link","/pool"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],link:[1,"link"],cardClass:[2,"cardClass"],contentClass:[3,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "]))],function(t,e){t(e,1,0,"Pools","/pool","card-medium","content-medium content-highlight")},function(t,e){t(e,2,0,e.component.healthData.pools.length)})}function le(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Raw Capacity"],["class","cd-col-5"],["contentClass","content-chart"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275eld"](2,0,null,0,1,"cd-health-pie",[],null,[[null,"prepareFn"]],function(t,e,n){var a=!0;return"prepareFn"===e&&(a=!1!==t.component.prepareRawUsage(n[0],n[1])&&a),a},yt,mt)),s["\u0275did"](3,638976,null,0,bt,[ht.a,gt.a],{data:[0,"data"],config:[1,"config"],showLabelAsTooltip:[2,"showLabelAsTooltip"]},{prepareFn:"prepareFn"})],function(t,e){var n=e.component;t(e,1,0,"Raw Capacity","card-medium","content-chart"),t(e,3,0,n.healthData,n.rawCapacityChartConfig,!0)},null)}function de(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","Objects"],["class","cd-col-5"],["contentClass","content-chart"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275eld"](2,0,null,0,1,"cd-health-pie",[],null,[[null,"prepareFn"]],function(t,e,n){var a=!0;return"prepareFn"===e&&(a=!1!==t.component.prepareObjects(n[0],n[1])&&a),a},yt,mt)),s["\u0275did"](3,638976,null,0,bt,[ht.a,gt.a],{data:[0,"data"],config:[1,"config"]},{prepareFn:"prepareFn"})],function(t,e){var n=e.component;t(e,1,0,"Objects","card-medium","content-chart"),t(e,3,0,n.healthData,n.objectsChartConfig)},null)}function fe(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-info-card",[["cardClass","card-medium"],["cardTitle","PGs per OSD"],["class","cd-col-5"],["contentClass","content-medium content-highlight"]],null,null,null,it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,1)],function(t,e){t(e,1,0,"PGs per OSD","card-medium","content-medium content-highlight")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,7),n.healthData.pg_info.pgs_per_osd));t(e,2,0,a)})}function pe(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function he(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"li",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ",": "," "]))],null,function(t,e){t(e,1,0,e.context.$implicit.key,e.context.$implicit.value)})}function ge(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,pe)),s["\u0275did"](1,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),s["\u0275eld"](2,0,null,null,3,"ul",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,he)),s["\u0275did"](4,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.KeyValuePipe,[s.KeyValueDiffers])],function(t,e){var n=e.component;t(e,1,0,s["\u0275nov"](e.parent.parent.parent,7)),t(e,4,0,s["\u0275unv"](e,4,0,s["\u0275nov"](e,5).transform(n.healthData.pg_info.statuses)))},null)}function be(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,"cd-info-card",[["cardClass","card-medium"],["cardTitle","PG Status"],["class","cd-col-5"],["contentClass","content-chart"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).toggle()&&a),a},it,nt)),s["\u0275did"](1,49152,null,0,et,[],{cardTitle:[0,"cardTitle"],cardClass:[1,"cardClass"],contentClass:[2,"contentClass"]},null),(t()(),s["\u0275and"](0,[["pgStatus",2]],0,0,null,ge)),(t()(),s["\u0275eld"](3,0,null,0,4,"div",[["class","pg-status-popover-wrapper"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,16777216,null,null,3,"div",[["placement","bottom"],["triggers",""]],null,null,null,null,null)),s["\u0275did"](5,212992,[["pgStatusTarget",4]],0,X.c,[X.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,Q.a],{popover:[0,"popover"],placement:[1,"placement"],triggers:[2,"triggers"]},null),(t()(),s["\u0275eld"](6,0,null,null,1,"cd-health-pie",[],null,[[null,"prepareFn"]],function(t,e,n){var a=!0;return"prepareFn"===e&&(a=!1!==t.component.preparePgStatus(n[0],n[1])&&a),a},yt,mt)),s["\u0275did"](7,638976,null,0,bt,[ht.a,gt.a],{data:[0,"data"],config:[1,"config"]},{prepareFn:"prepareFn"})],function(t,e){var n=e.component;t(e,1,0,"PG Status","card-medium","content-chart"),t(e,5,0,s["\u0275nov"](e,2),"bottom",""),t(e,7,0,n.healthData,n.pgStatusChartConfig)},null)}function me(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,12,"cd-info-group",[["class","row info-group"],["groupTitle","Capacity"]],null,null,null,ut,ot)),s["\u0275did"](1,49152,null,0,st,[],{groupTitle:[0,"groupTitle"]},null),(t()(),s["\u0275eld"](2,0,null,0,10,"div",[["class","cd-container-flex"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,ce)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,le)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,de)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,fe)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,be)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"Capacity"),t(e,4,0,n.healthData.pools),t(e,6,0,n.healthData.df),t(e,8,0,null!=(null==n.healthData.pg_info?null:null==n.healthData.pg_info.object_stats?null:n.healthData.pg_info.object_stats.num_objects)),t(e,10,0,n.healthData.pg_info),t(e,12,0,n.healthData.pg_info)},null)}function ye(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,6,"p",[["class","logs-link"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"i",[["class","fa fa-info-circle"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" See "])),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["routerLink","/logs"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,null,0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Logs"])),(t()(),s["\u0275ted"](-1,null,[" for more details."]))],function(t,e){t(e,5,0,"/logs")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function ve(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,ye)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.component.permissions.log.read)},null)}function _e(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,"div",[["class","container-fluid"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,te)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ue)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,me)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,[["logsLink",2]],null,0,null,ve))],function(t,e){var n=e.component;t(e,2,0,(null==n.healthData.health?null:n.healthData.health.status)||n.healthData.mon_status||n.healthData.osd_map||n.healthData.mgr_map||null!=n.healthData.hosts||null!=n.healthData.rgw||n.healthData.fs_map||null!=n.healthData.iscsi_daemons),t(e,4,0,n.healthData.client_perf||n.healthData.scrub_status),t(e,6,0,n.healthData.pools||n.healthData.df||n.healthData.pg_info)},null)}function xe(t){return s["\u0275vid"](0,[s["\u0275pid"](0,vt,[]),s["\u0275pid"](0,_t,[xt.a]),s["\u0275pid"](0,Tt,[xt.a]),s["\u0275pid"](0,wt,[xt.a]),s["\u0275pid"](0,St,[xt.a]),s["\u0275pid"](0,Ot,[]),s["\u0275pid"](0,ht.a,[It.a]),s["\u0275pid"](0,gt.a,[It.a]),(t()(),s["\u0275and"](16777216,null,null,2,null,_e)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275pid"](131072,i.AsyncPipe,[s.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,9,0,s["\u0275unv"](e,9,0,s["\u0275nov"](e,10).transform(n.healthData&&n.enabledFeature$)))},null)}var Te=n("gIcY"),we=n("ANnk"),Se=n("f/UV"),Oe=function(){function t(t){this.refreshIntervalService=t,this.intervalList={"5 s":5e3,"10 s":1e4,"15 s":15e3,"30 s":3e4,"1 min":6e4,"3 min":18e4,"5 min":3e5},this.intervalKeys=Object.keys(this.intervalList)}return t.prototype.ngOnInit=function(){this.selectedInterval=this.refreshIntervalService.getRefreshInterval()||5e3},t.prototype.changeRefreshInterval=function(t){this.refreshIntervalService.setRefreshInterval(t)},t}(),Ie=s["\u0275crt"]({encapsulation:0,styles:[[".refresh-selector[_ngcontent-%COMP%]{padding:0;float:right;margin-right:60px}.refresh-selector[_ngcontent-%COMP%] *[_ngcontent-%COMP%]{padding:0;box-sizing:border-box}.refresh-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{padding:10px 10px 0 0;text-align:right;margin:0}@media (min-width:500px) and (max-width:767px){.refresh-selector[_ngcontent-%COMP%]{width:24vw}}@media (min-width:1200px){.refresh-selector[_ngcontent-%COMP%]{width:12vw}}@media (min-width:1400px){.refresh-selector[_ngcontent-%COMP%]{width:10vw}}"]],data:{}});function Ce(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){var n=e.component;t(e,1,0,n.intervalList[e.context.$implicit]),t(e,2,0,n.intervalList[e.context.$implicit])},function(t,e){t(e,3,0,e.context.$implicit)})}function ke(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,14,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,13,"div",[["class","col-xs-5 col-sm-2 refresh-selector"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,2,"label",[["class","control-label col-xs-5 col-sm-5"],["for","refreshInterval"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Refresh"])),(t()(),s["\u0275eld"](5,0,null,null,9,"div",[["class","col-xs-7 col-sm-7"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,8,"select",[["class","form-control"],["id","refreshInterval"],["name","refreshInterval"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"ngModelChange"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,7).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,7).onTouched()&&a),"change"===e&&(a=!1!==r.changeRefreshInterval(n.target.value)&&a),"ngModelChange"===e&&(a=!1!==(r.selectedInterval=n)&&a),a},null,null)),s["\u0275did"](7,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](9,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](11,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](12,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ce)),s["\u0275did"](14,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,9,0,"refreshInterval",n.selectedInterval),t(e,14,0,n.intervalKeys)},function(t,e){t(e,6,0,s["\u0275nov"](e,11).ngClassUntouched,s["\u0275nov"](e,11).ngClassTouched,s["\u0275nov"](e,11).ngClassPristine,s["\u0275nov"](e,11).ngClassDirty,s["\u0275nov"](e,11).ngClassValid,s["\u0275nov"](e,11).ngClassInvalid,s["\u0275nov"](e,11).ngClassPending)})}var Ne=function(){function t(){this.hasGrafana=!1}return t.prototype.ngOnInit=function(){},t}(),Re=s["\u0275crt"]({encapsulation:0,styles:[["div[_ngcontent-%COMP%]{padding-top:20px}"]],data:{}});function Ae(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Health"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-health",[],null,null,null,xe,qt)),s["\u0275did"](5,245760,null,0,Mt,[Rt,xt.a,l.a,Pt.a,At.a,Lt,ht.a,gt.a],null,null),(t()(),s["\u0275eld"](6,0,null,0,1,"tab",[["heading","Statistics"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](7,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null)],function(t,e){t(e,3,0,"Health"),t(e,5,0),t(e,7,0,"Statistics")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass),t(e,6,0,s["\u0275nov"](e,7).id,s["\u0275nov"](e,7).active,s["\u0275nov"](e,7).addClass)})}function De(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-health",[],null,null,null,xe,qt)),s["\u0275did"](1,245760,null,0,Mt,[Rt,xt.a,l.a,Pt.a,At.a,Lt,ht.a,gt.a],null,null)],function(t,e){t(e,1,0)},null)}function Ee(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"cd-refresh-selector",[],null,null,null,ke,Ie)),s["\u0275did"](2,114688,null,0,Oe,[Lt],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ae)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,De)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0),t(e,4,0,n.hasGrafana),t(e,6,0,!n.hasGrafana)},null)}function Le(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-dashboard",[],null,null,null,Ee,Re)),s["\u0275did"](1,114688,null,0,Ne,[],null,null)],function(t,e){t(e,1,0)},null)}var Pe=s["\u0275ccf"]("cd-dashboard",Ne,Le,{},{},[]),Me=n("a278"),qe=n("insk"),je=n("mSOc"),Fe=n("ZYjt"),ze=n("20UP"),Ge=n("+0ag"),Ye=n("25BL"),Ve=n("uIqm"),He=n("vCyI"),Be=function(){function t(t){this.authStorageService=t,this.grafanaPermission=this.authStorageService.getPermissions().grafana}return t.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.host=this.selection.first())},t}(),Ue=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function We(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Performance Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-grafana",[["grafanaStyle","three"],["uid","rtOg0AiWz"]],null,null,null,Me.b,Me.a)),s["\u0275did"](5,638976,null,0,qe.a,[je.a,Fe.DomSanitizer,ze.a,Ge.a,xt.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(t,e){var n=e.component;t(e,3,0,"Performance Details"),t(e,5,0,"host-details?var-ceph_hosts="+n.host.hostname,"three","rtOg0AiWz")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass)})}function Ke(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,We)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.selection.hasSingleSelection&&n.grafanaPermission.read)},null)}var $e=function(){function t(t){this.http=t}return t.prototype.list=function(){return this.http.get("api/host").toPromise().then(function(t){return t})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),Ze=n("85J/"),Xe=function(){function t(t,e,n,a){this.authStorageService=t,this.hostService=e,this.cephShortVersionPipe=n,this.i18n=a,this.columns=[],this.hosts=[],this.isLoadingHosts=!1,this.cdParams={fromLink:"/hosts"},this.selection=new He.a,this.permissions=this.authStorageService.getPermissions()}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Hostname"),prop:"hostname",flexGrow:1},{name:this.i18n("Services"),prop:"services",flexGrow:3,cellTemplate:this.servicesTpl},{name:this.i18n("Version"),prop:"ceph_version",flexGrow:1,pipe:this.cephShortVersionPipe}]},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.getHosts=function(t){var e=this;if(!this.isLoadingHosts){var n={mds:"cephfs",mon:"monitor",osd:"osd",rgw:"rgw","rbd-mirror":"rbdMirroring",mgr:"manager","tcmu-runner":"iscsi"};this.isLoadingHosts=!0,this.hostService.list().then(function(t){t.map(function(t){return t.services.map(function(t){t.cdLink="/perf_counters/"+t.type+"/"+encodeURIComponent(t.id);var a=e.permissions[n[t.type]];return t.canRead=!!a&&a.read,t}),t}),e.hosts=t,e.isLoadingHosts=!1}).catch(function(){e.isLoadingHosts=!1,t.error()})}},t}(),Je=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Qe(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"a",[],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,1).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](1,671744,null,0,tt.o,[tt.l,tt.a,i.LocationStrategy],{queryParams:[0,"queryParams"],routerLink:[1,"routerLink"]},null),s["\u0275pad"](2,1),(t()(),s["\u0275ted"](3,null,["","."," "]))],function(t,e){var n=e.component.cdParams,a=t(e,2,0,e.parent.context.$implicit.cdLink);t(e,1,0,n,a)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).target,s["\u0275nov"](e,1).href),t(e,3,0,e.parent.context.$implicit.type,e.parent.context.$implicit.id)})}function tn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ","."," "]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.type,e.parent.context.$implicit.id)})}function en(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"span",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Qe)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,tn)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275ted"](5,null,[" "," "]))],function(t,e){t(e,2,0,e.context.$implicit.canRead),t(e,4,0,!e.context.$implicit.canRead)},function(t,e){t(e,5,0,e.context.last?"":", ")})}function nn(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,en)),s["\u0275did"](1,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.context.value)},null)}function an(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"tab",[["heading","Overall Performance"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](1,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","two"],["uid","y0KGL0iZz"]],null,null,null,Me.b,Me.a)),s["\u0275did"](3,638976,null,0,qe.a,[je.a,Fe.DomSanitizer,ze.a,Ge.a,xt.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(t,e){t(e,1,0,"Overall Performance"),t(e,3,0,"host-overview?","two","y0KGL0iZz")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).id,s["\u0275nov"](e,1).active,s["\u0275nov"](e,1).addClass)})}function rn(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{servicesTpl:0}),(t()(),s["\u0275eld"](1,0,null,null,10,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](2,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](3,0,null,0,6,"tab",[["heading","Hosts List"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](4,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](5,0,null,null,4,"cd-table",[["columnMode","flex"],["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(t,e,n){var a=!0,r=t.component;return"fetchData"===e&&(a=!1!==r.getHosts(n)&&a),"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](6,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],selectionType:[3,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(t()(),s["\u0275and"](0,[[1,2],["servicesTpl",2]],null,0,null,nn)),(t()(),s["\u0275eld"](8,0,null,2,1,"cd-host-details",[["cdTableDetail",""]],null,null,null,Ke,Ue)),s["\u0275did"](9,573440,null,0,Be,[l.a],{selection:[0,"selection"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,an)),s["\u0275did"](11,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,4,0,"Hosts List"),t(e,6,0,n.hosts,n.columns,"flex","single"),t(e,9,0,n.selection),t(e,11,0,n.permissions.grafana.read)},function(t,e){t(e,1,0,s["\u0275nov"](e,2).clazz),t(e,3,0,s["\u0275nov"](e,4).id,s["\u0275nov"](e,4).active,s["\u0275nov"](e,4).addClass)})}function sn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-hosts",[],null,null,null,rn,Je)),s["\u0275did"](1,114688,null,0,Xe,[l.a,$e,Ze.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var on=s["\u0275ccf"]("cd-hosts",Xe,sn,{},{},[]),un=function(){function t(t){this.http=t}return t.prototype.getMonitor=function(){return this.http.get("api/monitor")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),cn=n("x38r"),ln=function(){function t(t,e){this.monitorService=t,this.i18n=e,this.inQuorum={columns:[{prop:"name",name:this.i18n("Name"),cellTransformation:cn.a.routerLink},{prop:"rank",name:this.i18n("Rank")},{prop:"public_addr",name:this.i18n("Public Address")},{prop:"cdOpenSessions",name:this.i18n("Open Sessions"),cellTransformation:cn.a.sparkline,comparator:function(t,e){var n=ft.last(t),a=ft.last(e);return n&&a&&n!==a?n>a?1:-1:0}}],data:[]},this.notInQuorum={columns:[{prop:"name",name:this.i18n("Name"),cellTransformation:cn.a.routerLink},{prop:"rank",name:this.i18n("Rank")},{prop:"public_addr",name:this.i18n("Public Address")}],data:[]}}return t.prototype.refresh=function(){var t=this;this.monitorService.getMonitor().subscribe(function(e){e.in_quorum.map(function(t){return t.cdOpenSessions=t.stats.num_sessions.map(function(t){return t[1]}),t.cdLink="/perf_counters/mon/"+t.name,t.cdParams={fromLink:"/monitor"},t}),e.out_quorum.map(function(t){return t.cdLink="/perf_counters/mon/"+t.name,t.cdParams={fromLink:"/monitor"},t}),t.inQuorum.data=e.in_quorum.slice(),t.notInQuorum.data=e.out_quorum.slice(),t.mon_status=e.mon_status})},t}(),dn=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function fn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,36,"table",[["class","table table-striped"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,35,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Cluster ID"])),(t()(),s["\u0275eld"](5,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](6,null,["",""])),(t()(),s["\u0275eld"](7,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["monmap modified"])),(t()(),s["\u0275eld"](10,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](11,null,["",""])),(t()(),s["\u0275eld"](12,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["monmap epoch"])),(t()(),s["\u0275eld"](15,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](16,null,["",""])),(t()(),s["\u0275eld"](17,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["quorum con"])),(t()(),s["\u0275eld"](20,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](21,null,["",""])),(t()(),s["\u0275eld"](22,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](23,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["quorum mon"])),(t()(),s["\u0275eld"](25,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](26,null,["",""])),(t()(),s["\u0275eld"](27,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](28,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["required con"])),(t()(),s["\u0275eld"](30,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](31,null,["",""])),(t()(),s["\u0275eld"](32,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](33,0,null,null,1,"td",[["class","bold"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["required mon"])),(t()(),s["\u0275eld"](35,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](36,null,["",""]))],null,function(t,e){var n=e.component;t(e,6,0,n.mon_status.monmap.fsid),t(e,11,0,n.mon_status.monmap.modified),t(e,16,0,n.mon_status.monmap.epoch),t(e,21,0,n.mon_status.features.quorum_con),t(e,26,0,n.mon_status.features.quorum_mon),t(e,31,0,n.mon_status.features.required_con),t(e,36,0,n.mon_status.features.required_mon)})}function pn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,15,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,5,"div",[["class","col-md-4"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,4,"fieldset",[],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Status"])),(t()(),s["\u0275and"](16777216,null,null,1,null,fn)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](7,0,null,null,8,"div",[["class","col-md-8"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,1,"legend",[["class","in-quorum"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["In Quorum"])),(t()(),s["\u0275eld"](10,0,null,null,1,"cd-table",[],null,null,null,Ye.b,Ye.a)),s["\u0275did"](11,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"]},null),(t()(),s["\u0275eld"](12,0,null,null,1,"legend",[["class","in-quorum"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Not In Quorum"])),(t()(),s["\u0275eld"](14,0,null,null,1,"cd-table",[],null,[[null,"fetchData"]],function(t,e,n){var a=!0;return"fetchData"===e&&(a=!1!==t.component.refresh()&&a),a},Ye.b,Ye.a)),s["\u0275did"](15,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"]},{fetchData:"fetchData"})],function(t,e){var n=e.component;t(e,6,0,n.mon_status),t(e,11,0,n.inQuorum.data,n.inQuorum.columns),t(e,15,0,n.notInQuorum.data,n.notInQuorum.columns)},null)}function hn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-monitor",[],null,null,null,pn,dn)),s["\u0275did"](1,49152,null,0,ln,[un,xt.a],null,null)],null,null)}var gn=s["\u0275ccf"]("cd-monitor",ln,hn,{},{},[]),bn=n("xtZt"),mn=n("xSw7"),yn=n("GgAd"),vn=n("xbqr"),_n=n("9GXa"),xn=n("NUGo"),Tn=n("S7zO"),wn=n("sLuX"),Sn=n("FSuO"),On=n("a0VL"),In=n("j8L6"),Cn=n("b5OY"),kn=n("pxLl"),Nn=function(){function t(){this.last={}}return t.prototype.ngOnChanges=function(){this.render()},t.prototype.hexdigits=function(t){var e=Math.floor(255*t).toString(16);return 1===e.length?"0"+e:e},t.prototype.hexcolor=function(t,e,n){return"#"+this.hexdigits(t)+this.hexdigits(e)+this.hexdigits(n)},t.prototype.render=function(){var t=this;if(this.histogram){var e=0;ft.each(this.histogram.values,function(n,a){ft.each(n,function(n,r){e=Math.max(e,t.last&&t.last[a]&&t.last[a][r]?n-t.last[a][r]:n)})}),this.valuesStyle=this.histogram.values.map(function(n,a){return n.map(function(n,r){var i=e?(t.last&&t.last[a]&&t.last[a][r]?n-t.last[a][r]:n)/e:0;return{backgroundColor:t.hexcolor(1-i,i,0)}})}),this.last=this.histogram.values}},t}(),Rn=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function An(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[["style","width: 10px; height: 10px;"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null)],function(t,e){t(e,1,0,e.context.$implicit)},null)}function Dn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"tr",[["style","height: 10px;"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,An)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.context.$implicit)},null)}function En(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"table",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Dn)),s["\u0275did"](3,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,3,0,e.component.valuesStyle)},null)}var Ln=function(){function t(t,e){this.http=t,this.i18n=e,this.path="api/osd",this.osdRecvSpeedModalPriorities={KNOWN_PRIORITIES:[{name:null,text:this.i18n("-- Select the priority --"),values:{osd_max_backfills:null,osd_recovery_max_active:null,osd_recovery_max_single_start:null,osd_recovery_sleep:null}},{name:"low",text:this.i18n("Low"),values:{osd_max_backfills:1,osd_recovery_max_active:1,osd_recovery_max_single_start:1,osd_recovery_sleep:.5}},{name:"default",text:this.i18n("Default"),values:{osd_max_backfills:1,osd_recovery_max_active:3,osd_recovery_max_single_start:1,osd_recovery_sleep:0}},{name:"high",text:this.i18n("High"),values:{osd_max_backfills:4,osd_recovery_max_active:4,osd_recovery_max_single_start:4,osd_recovery_sleep:0}}]}}return t.prototype.getList=function(){return this.http.get(""+this.path)},t.prototype.getDetails=function(t){return this.http.get(this.path+"/"+t)},t.prototype.scrub=function(t,e){return this.http.post(this.path+"/"+t+"/scrub?deep="+e,null)},t.prototype.getFlags=function(){return this.http.get(this.path+"/flags")},t.prototype.updateFlags=function(t){return this.http.put(this.path+"/flags",{flags:t})},t.prototype.markOut=function(t){return this.http.post(this.path+"/"+t+"/mark_out",null)},t.prototype.markIn=function(t){return this.http.post(this.path+"/"+t+"/mark_in",null)},t.prototype.markDown=function(t){return this.http.post(this.path+"/"+t+"/mark_down",null)},t.prototype.reweight=function(t,e){return this.http.post(this.path+"/"+t+"/reweight",{weight:e})},t.prototype.markLost=function(t){return this.http.post(this.path+"/"+t+"/mark_lost",null)},t.prototype.purge=function(t){return this.http.post(this.path+"/"+t+"/purge",null)},t.prototype.destroy=function(t){return this.http.post(this.path+"/"+t+"/destroy",null)},t.prototype.safeToDestroy=function(t){return this.http.get(this.path+"/"+t+"/safe_to_destroy")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c),s.inject(xt.a))},token:t,providedIn:Nt.a}),t}(),Pn=function(){function t(t,e){this.osdService=t,this.authStorageService=e,this.grafanaPermission=this.authStorageService.getPermissions().grafana}return t.prototype.ngOnChanges=function(){this.osd={loaded:!1},this.selection.hasSelection&&(this.osd=this.selection.first(),this.refresh())},t.prototype.refresh=function(){var t=this;this.osdService.getDetails(this.osd.id).subscribe(function(e){t.osd.details=e,t.osd.histogram_failed="",ft.isObject(e.histogram)||(t.osd.histogram_failed=e.histogram,t.osd.details.histogram=void 0),t.osd.loaded=!0})},t}(),Mn=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function qn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](1,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},null)],function(t,e){t(e,1,0,e.component.osd.details.osd_map)},null)}function jn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-table-key-value",[],null,[[null,"fetchData"]],function(t,e,n){var a=!0;return"fetchData"===e&&(a=!1!==t.component.refresh()&&a),a},wn.b,wn.a)),s["\u0275did"](1,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},{fetchData:"fetchData"})],function(t,e){t(e,1,0,e.component.osd.details.osd_metadata)},null)}function Fn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-warning-panel",[],null,null,null,vn.b,vn.a)),s["\u0275did"](1,49152,null,0,_n.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["Metadata not available"]))],null,null)}function zn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-table-performance-counter",[["serviceType","osd"]],null,null,null,In.b,In.a)),s["\u0275did"](1,114688,null,0,Cn.a,[kn.a,xt.a],{serviceType:[0,"serviceType"],serviceId:[1,"serviceId"]},null)],function(t,e){t(e,1,0,"osd",e.component.osd.id)},null)}function Gn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-warning-panel",[],null,null,null,vn.b,vn.a)),s["\u0275did"](1,49152,null,0,_n.a,[],null,null),(t()(),s["\u0275ted"](2,0,["Histogram not available: ",""]))],null,function(t,e){t(e,2,0,e.component.osd.histogram_failed)})}function Yn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,4,"div",[["class","col-md-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"h4",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Writes"])),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-osd-performance-histogram",[],null,null,null,En,Rn)),s["\u0275did"](5,573440,null,0,Nn,[],{histogram:[0,"histogram"]},null),(t()(),s["\u0275eld"](6,0,null,null,4,"div",[["class","col-md-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,1,"h4",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Reads"])),(t()(),s["\u0275eld"](9,0,null,null,1,"cd-osd-performance-histogram",[],null,null,null,En,Rn)),s["\u0275did"](10,573440,null,0,Nn,[],{histogram:[0,"histogram"]},null)],function(t,e){var n=e.component;t(e,5,0,n.osd.details.histogram.osd.op_w_latency_in_bytes_histogram),t(e,10,0,n.osd.details.histogram.osd.op_r_latency_out_bytes_histogram)},null)}function Vn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"tab",[["heading","Performance Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](1,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","GrafanaStyles.two"],["uid","CrAHE0iZz"]],null,null,null,Me.b,Me.a)),s["\u0275did"](3,638976,null,0,qe.a,[je.a,Fe.DomSanitizer,ze.a,Ge.a,xt.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(t,e){var n=e.component;t(e,1,0,"Performance Details"),t(e,3,0,"osd-device-details?var-osd=osd."+n.osd.id,"GrafanaStyles.two","CrAHE0iZz")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).id,s["\u0275nov"](e,1).active,s["\u0275nov"](e,1).addClass)})}function Hn(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,22,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Attributes (OSD map)"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,qn)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](6,0,null,0,4,"tab",[["heading","Metadata"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](7,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,jn)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"],ngIfElse:[1,"ngIfElse"]},null),(t()(),s["\u0275and"](0,[["noMetaData",2]],null,0,null,Fn)),(t()(),s["\u0275eld"](11,0,null,0,3,"tab",[["heading","Performance counter"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](12,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,zn)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](15,0,null,0,5,"tab",[["heading","Histogram"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](16,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Gn)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Yn)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,Vn)),s["\u0275did"](22,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,"Attributes (OSD map)"),t(e,5,0,n.osd.loaded),t(e,7,0,"Metadata"),t(e,9,0,n.osd.loaded&&n.osd.details.osd_metadata,s["\u0275nov"](e,10)),t(e,12,0,"Performance counter"),t(e,14,0,n.osd.loaded),t(e,16,0,"Histogram"),t(e,18,0,n.osd.loaded&&n.osd.histogram_failed),t(e,20,0,n.osd.loaded&&n.osd.details.histogram),t(e,22,0,n.grafanaPermission.read)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass),t(e,6,0,s["\u0275nov"](e,7).id,s["\u0275nov"](e,7).active,s["\u0275nov"](e,7).addClass),t(e,11,0,s["\u0275nov"](e,12).id,s["\u0275nov"](e,12).active,s["\u0275nov"](e,12).addClass),t(e,15,0,s["\u0275nov"](e,16).id,s["\u0275nov"](e,16).active,s["\u0275nov"](e,16).addClass)})}function Bn(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Hn)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.selection.hasSingleSelection)},null)}function Un(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-details",[],null,null,null,Bn,Mn)),s["\u0275did"](1,573440,null,0,Pn,[Ln,l.a],null,null)],null,null)}var Wn=s["\u0275ccf"]("cd-osd-details",Pn,Un,{selection:"selection"},{},[]),Kn=n("OLbh"),$n=n("0+/T"),Zn=n("sne2"),Xn=n("mtw6"),Jn=n("9nlD"),Qn=function(){function t(t,e,n,a,r){this.bsModalRef=t,this.authStorageService=e,this.osdService=n,this.notificationService=a,this.i18n=r,this.osdFlagsForm=new Te.k({}),this.allFlags={noin:{code:"noin",name:this.i18n("No In"),value:!1,description:this.i18n("OSDs that were previously marked out will not be marked back in when they start")},noout:{code:"noout",name:this.i18n("No Out"),value:!1,description:this.i18n("OSDs will not automatically be marked out after the configured interval")},noup:{code:"noup",name:this.i18n("No Up"),value:!1,description:this.i18n("OSDs are not allowed to start")},nodown:{code:"nodown",name:this.i18n("No Down"),value:!1,description:this.i18n("OSD failure reports are being ignored, such that the monitors will not mark OSDs down")},pause:{code:"pause",name:this.i18n("Pause"),value:!1,description:this.i18n("Pauses reads and writes")},noscrub:{code:"noscrub",name:this.i18n("No Scrub"),value:!1,description:this.i18n("Scrubbing is disabled")},"nodeep-scrub":{code:"nodeep-scrub",name:this.i18n("No Deep Scrub"),value:!1,description:this.i18n("Deep Scrubbing is disabled")},nobackfill:{code:"nobackfill",name:this.i18n("No Backfill"),value:!1,description:this.i18n("Backfilling of PGs is suspended")},norebalance:{code:"norebalance",name:this.i18n("No Rebalance"),value:!1,description:this.i18n("OSD will choose not to backfill unless PG is also degraded")},norecover:{code:"norecover",name:this.i18n("No Recover"),value:!1,description:this.i18n("Recovery of PGs is suspended")},sortbitwise:{code:"sortbitwise",name:this.i18n("Bitwise Sort"),value:!1,description:this.i18n("Use bitwise sort"),disabled:!0},purged_snapdirs:{code:"purged_snapdirs",name:this.i18n("Purged Snapdirs"),value:!1,description:this.i18n("OSDs have converted snapsets"),disabled:!0},recovery_deletes:{code:"recovery_deletes",name:this.i18n("Recovery Deletes"),value:!1,description:this.i18n("Deletes performed during recovery instead of peering"),disabled:!0},pglog_hardlimit:{code:"pglog_hardlimit",name:this.i18n("PG Log Hard Limit"),value:!1,description:this.i18n("Puts a hard limit on pg log length"),disabled:!0}},this.unknownFlags=[],this.permissions=this.authStorageService.getPermissions()}return t.prototype.ngOnInit=function(){var t=this;this.osdService.getFlags().subscribe(function(e){e.forEach(function(e){t.allFlags[e]?t.allFlags[e].value=!0:t.unknownFlags.push(e)}),t.flags=ft.toArray(t.allFlags)})},t.prototype.submitAction=function(){var t=this,e=this.flags.filter(function(t){return t.value}).map(function(t){return t.code}).concat(this.unknownFlags);this.osdService.updateFlags(e).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n("Updated OSD Flags")),t.bsModalRef.hide()},function(){t.bsModalRef.hide()})},t}(),ta=n("VNr4"),ea=n("MuvH"),na=n("QFaf"),aa=n("1Ni5"),ra=function(){function t(){}return t.getType=function(t){var e=ft.find(this.knownTypes,function(e){return e.name===t});if(void 0!==e)return e;throw new Error('Found unknown type "'+t+'" for config option.')},t.getTypeValidators=function(e){var n=t.getType(e.type);if("bool"!==n.name&&"str"!==n.name){var a={validators:[],patternHelpText:n.patternHelpText};return n.isNumberType?(e.max&&""!==e.max&&(a.max=e.max,a.validators.push(Te.A.max(e.max))),e.min&&""!==e.min?(a.min=e.min,a.validators.push(Te.A.min(e.min))):"defaultMin"in n&&(a.min=n.defaultMin,a.validators.push(Te.A.min(n.defaultMin))),a.validators.push("float"===e.type?aa.a.decimalNumber():aa.a.number(n.allowsNegative))):"addr"===e.type?a.validators=[aa.a.ip()]:"uuid"===e.type&&(a.validators=[aa.a.uuid()]),a}},t.getTypeStep=function(t,e){if(["uint","int","size","secs"].includes(t))return 1;if("float"===t){if(null!==e&&-1!==e.toString().indexOf(".")){var n=e.toString().split(".");return Math.pow(10,-n[1].length)}return.1}},t.knownTypes=[{name:"uint",inputType:"number",humanReadable:"Unsigned integer value",defaultMin:0,patternHelpText:"The entered value needs to be an unsigned number.",isNumberType:!0,allowsNegative:!1},{name:"int",inputType:"number",humanReadable:"Integer value",patternHelpText:"The entered value needs to be a number.",isNumberType:!0,allowsNegative:!0},{name:"size",inputType:"number",humanReadable:"Unsigned integer value (>=16bit)",defaultMin:0,patternHelpText:"The entered value needs to be a unsigned number.",isNumberType:!0,allowsNegative:!1},{name:"secs",inputType:"number",humanReadable:"Number of seconds",defaultMin:1,patternHelpText:"The entered value needs to be a number >= 1.",isNumberType:!0,allowsNegative:!1},{name:"float",inputType:"number",humanReadable:"Double value",patternHelpText:"The entered value needs to be a number or decimal.",isNumberType:!0,allowsNegative:!0},{name:"str",inputType:"text",humanReadable:"Text",isNumberType:!1},{name:"addr",inputType:"text",humanReadable:"IPv4 or IPv6 address",patternHelpText:"The entered value needs to be a valid IP address.",isNumberType:!1},{name:"uuid",inputType:"text",humanReadable:"UUID",patternHelpText:"The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8",isNumberType:!1},{name:"bool",inputType:"checkbox",humanReadable:"Boolean value",isNumberType:!1}],t}(),ia=function(){function t(t){this.configService=t,this.optionNames=[],this.optionsForm=new na.a({}),this.optionsFormDir=new Te.t([],[]),this.optionsFormGroupName="",this.optionsFormShowReset=!0,this.options=[],this.optionsFormGroup=new na.a({})}return t.optionNameToText=function(t){var e=["mon","mgr","osd","mds","client"];return t.split("_").filter(function(t,n){return 0!==n||!e.includes(t)}).map(function(t){return t.charAt(0).toUpperCase()+t.substring(1)}).join(" ")},t.prototype.ngOnInit=function(){this.createForm(),this.loadStoredData()},t.prototype.createForm=function(){var t=this;this.optionsForm.addControl(this.optionsFormGroupName,this.optionsFormGroup),this.optionNames.forEach(function(e){t.optionsFormGroup.addControl(e,new Te.i(null))})},t.prototype.getStep=function(t,e){return ra.getTypeStep(t,e)},t.prototype.loadStoredData=function(){var e=this;this.configService.filter(this.optionNames).subscribe(function(n){e.options=n.map(function(n){var a=e.optionsForm.get(n.name),r=ra.getTypeValidators(n);return n.additionalTypeInfo=ra.getType(n.type),n.text=t.optionNameToText(n.name),n.value=ft.find(n.value,function(t){return"osd"===t.section}),n.value&&a.setValue("bool"===n.additionalTypeInfo.name?"true"===n.value.value:n.value.value),r&&(n.patternHelpText=r.patternHelpText,"max"in r&&""!==r.max&&(n.maxValue=r.max),"min"in r&&""!==r.min&&(n.minValue=r.min),a.setValidators(r.validators)),n})})},t.prototype.saveValues=function(){var t=this,e={};return this.optionNames.forEach(function(n){var a=t.optionsForm.getValue(n);null!==a&&""!==a&&(e[n]={section:"osd",value:a})}),this.configService.bulkCreate({options:e})},t.prototype.resetValue=function(t){var e=this;this.configService.delete(t,"osd").subscribe(function(){e.optionsForm.get(t).reset()})},t}(),sa=function(){function t(){}return t.basicOptions=["osd_scrub_during_recovery","osd_scrub_begin_hour","osd_scrub_end_hour","osd_scrub_begin_week_day","osd_scrub_end_week_day","osd_scrub_min_interval","osd_scrub_max_interval","osd_deep_scrub_interval","osd_scrub_auto_repair","osd_max_scrubs","osd_scrub_priority","osd_scrub_sleep"],t.advancedOptions=["osd_scrub_auto_repair_num_errors","osd_debug_deep_scrub_sleep","osd_deep_scrub_keys","osd_deep_scrub_large_omap_object_key_threshold","osd_deep_scrub_large_omap_object_value_sum_threshold","osd_deep_scrub_randomize_ratio","osd_deep_scrub_stride","osd_deep_scrub_update_digest_min_age","osd_op_queue_mclock_scrub_lim","osd_op_queue_mclock_scrub_res","osd_op_queue_mclock_scrub_wgt","osd_requested_scrub_priority","osd_scrub_backoff_ratio","osd_scrub_chunk_max","osd_scrub_chunk_min","osd_scrub_cost","osd_scrub_interval_randomize_ratio","osd_scrub_invalid_stats","osd_scrub_load_threshold","osd_scrub_max_preemptions"],t}(),oa=function(){function t(t,e,n,a,r){this.bsModalRef=t,this.authStorageService=e,this.notificationService=n,this.i18n=a,this.actionLabels=r,this.basicOptions=sa.basicOptions,this.advancedOptions=sa.advancedOptions,this.advancedEnabled=!1,this.osdPgScrubForm=new na.a({}),this.resource=this.i18n("PG scrub options"),this.action=this.actionLabels.EDIT,this.permissions=this.authStorageService.getPermissions()}return t.prototype.submitAction=function(){var t=this,e=[this.basicOptionsValues.saveValues()];this.advancedOptionsValues&&e.push(this.advancedOptionsValues.saveValues()),Object(ta.a)(e).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n("Updated PG scrub options")),t.bsModalRef.hide()},function(){t.bsModalRef.hide()})},t}(),ua=function(){function t(t,e,n,a,r,i){var s=this;this.bsModalRef=t,this.authStorageService=e,this.configService=n,this.notificationService=a,this.i18n=r,this.osdService=i,this.priorities=[],this.priorityAttrs={},this.permissions=this.authStorageService.getPermissions(),this.priorities=this.osdService.osdRecvSpeedModalPriorities.KNOWN_PRIORITIES,this.osdRecvSpeedForm=new na.a({priority:new Te.i(null,{validators:[Te.A.required]}),customizePriority:new Te.i(!1)}),this.priorityAttrs={osd_max_backfills:{text:this.i18n("Max Backfills"),desc:"",patternHelpText:"",maxValue:void 0,minValue:void 0},osd_recovery_max_active:{text:this.i18n("Recovery Max Active"),desc:"",patternHelpText:"",maxValue:void 0,minValue:void 0},osd_recovery_max_single_start:{text:this.i18n("Recovery Max Single Start"),desc:"",patternHelpText:"",maxValue:void 0,minValue:void 0},osd_recovery_sleep:{text:this.i18n("Recovery Sleep"),desc:"",patternHelpText:"",maxValue:void 0,minValue:void 0}},Object.keys(this.priorityAttrs).forEach(function(t){s.osdRecvSpeedForm.addControl(t,new Te.i(null,{validators:[Te.A.required]}))})}return t.prototype.ngOnInit=function(){var t=this;this.configService.filter(Object.keys(this.priorityAttrs)).subscribe(function(e){var n=t.getCurrentValues(e);t.detectPriority(n.values,function(e){t.setPriority(e)}),t.setDescription(n.configOptions),t.setValidators(n.configOptions)})},t.prototype.detectPriority=function(t,e){var n=ft.find(this.priorities,function(e){return ft.isEqual(e.values,t)});return this.osdRecvSpeedForm.controls.customizePriority.setValue(!1),n?e(n):4===Object.entries(t).length?(this.osdRecvSpeedForm.controls.customizePriority.setValue(!0),e(Object({name:"custom",text:this.i18n("Custom"),values:t}))):e(this.priorities[0])},t.prototype.getCurrentValues=function(t){var e={values:{},configOptions:[]};return t.forEach(function(t){e.configOptions.push(t),"value"in t?t.value.forEach(function(n){"osd"===n.section&&(e.values[t.name]=Number(n.value))}):"default"in t&&null!==t.default&&(e.values[t.name]=Number(t.default))}),e},t.prototype.setDescription=function(t){var e=this;t.forEach(function(t){""!==t.desc&&(e.priorityAttrs[t.name].desc=t.desc)})},t.prototype.setPriority=function(t){var e=this,n=ft.find(this.priorities,function(t){return"custom"===t.name});"custom"===t.name?n||this.priorities.push(t):n&&this.priorities.splice(this.priorities.indexOf(n),1),this.osdRecvSpeedForm.controls.priority.setValue(t.name),Object.entries(t.values).forEach(function(t){e.osdRecvSpeedForm.controls[t[0]].setValue(t[1])})},t.prototype.setValidators=function(t){var e=this;t.forEach(function(t){var n=ra.getTypeValidators(t);n?(n.validators.push(Te.A.required),"max"in n&&""!==n.max&&(e.priorityAttrs[t.name].maxValue=n.max),"min"in n&&""!==n.min&&(e.priorityAttrs[t.name].minValue=n.min),e.priorityAttrs[t.name].patternHelpText=n.patternHelpText,e.osdRecvSpeedForm.controls[t.name].setValidators(n.validators)):e.osdRecvSpeedForm.controls[t.name].setValidators(Te.A.required)})},t.prototype.onCustomizePriorityChange=function(){var t=this,e={};if(Object.keys(this.priorityAttrs).forEach(function(n){e[n]=t.osdRecvSpeedForm.getValue(n)}),this.osdRecvSpeedForm.getValue("customizePriority")){var n={name:"custom",text:this.i18n("Custom"),values:e};this.setPriority(n)}else this.detectPriority(e,function(e){t.setPriority(e)})},t.prototype.onPriorityChange=function(t){var e=ft.find(this.priorities,function(e){return e.name===t})||this.priorities[0];this.osdRecvSpeedForm.get("customizePriority").setValue(!1),this.setPriority(e)},t.prototype.submitAction=function(){var t=this,e={};Object.keys(this.priorityAttrs).forEach(function(n){e[n]={section:"osd",value:t.osdRecvSpeedForm.getValue(n)}}),this.configService.bulkCreate({options:e}).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n('Updated OSD recovery speed priority "{{value}}"',{value:t.osdRecvSpeedForm.getValue("priority")})),t.bsModalRef.hide()},function(){t.bsModalRef.hide()})},t}(),ca=n("2EZI"),la=function(){function t(t,e,n){this.bsModalRef=t,this.osdService=e,this.fb=n,this.currentWeight=1}return Object.defineProperty(t.prototype,"weight",{get:function(){return this.reweightForm.get("weight")},enumerable:!0,configurable:!0}),t.prototype.ngOnInit=function(){this.reweightForm=this.fb.group({weight:this.fb.control(this.currentWeight,[Te.A.required,Te.A.max(1),Te.A.min(0)])})},t.prototype.reweight=function(){var t=this;this.osdService.reweight(this.osdId,this.reweightForm.value.weight).subscribe(function(){return t.bsModalRef.hide()})},t}(),da=function(){function t(t,e,n,a){this.bsModalRef=t,this.osdService=e,this.notificationService=n,this.i18n=a,this.selected=[]}return t.prototype.ngOnInit=function(){this.scrubForm=new Te.k({})},t.prototype.scrub=function(){var t=this,e=this.selected[0].id;this.osdService.scrub(e,this.deep).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n("{{operation}} was initialized in the following OSD: {{id}}",{operation:t.deep?"Deep scrub":"Scrub",id:e})),t.bsModalRef.hide()},function(){t.bsModalRef.hide()})},t}(),fa=function(){function t(t,e,n,a,r,i){var s=this;this.authStorageService=t,this.osdService=e,this.dimlessBinaryPipe=n,this.modalService=a,this.i18n=r,this.actionLabels=i,this.osds=[],this.selection=new He.a,this.permissions=this.authStorageService.getPermissions(),this.tableActions=[{name:this.actionLabels.SCRUB,permission:"update",icon:"fa-stethoscope",click:function(){return s.scrubAction(!1)},disable:function(){return!s.hasOsdSelected}},{name:this.actionLabels.DEEP_SCRUB,permission:"update",icon:"fa-cog",click:function(){return s.scrubAction(!0)},disable:function(){return!s.hasOsdSelected}},{name:this.actionLabels.REWEIGHT,permission:"update",click:function(){return s.reweight()},disable:function(){return!s.hasOsdSelected},icon:"fa-balance-scale"},{name:this.actionLabels.MARK_OUT,permission:"update",click:function(){return s.showConfirmationModal(s.i18n("out"),s.osdService.markOut)},disable:function(){return s.isNotSelectedOrInState("out")},icon:"fa-arrow-left"},{name:this.actionLabels.MARK_IN,permission:"update",click:function(){return s.showConfirmationModal(s.i18n("in"),s.osdService.markIn)},disable:function(){return s.isNotSelectedOrInState("in")},icon:"fa-arrow-right"},{name:this.actionLabels.MARK_DOWN,permission:"update",click:function(){return s.showConfirmationModal(s.i18n("down"),s.osdService.markDown)},disable:function(){return s.isNotSelectedOrInState("down")},icon:"fa-arrow-down"},{name:this.actionLabels.MARK_LOST,permission:"delete",click:function(){return s.showCriticalConfirmationModal(s.i18n("Mark"),s.i18n("OSD lost"),s.i18n("marked lost"),s.osdService.markLost)},disable:function(){return s.isNotSelectedOrInState("up")},icon:"fa-unlink"},{name:this.actionLabels.PURGE,permission:"delete",click:function(){return s.showCriticalConfirmationModal(s.i18n("Purge"),s.i18n("OSD"),s.i18n("purged"),s.osdService.purge)},disable:function(){return s.isNotSelectedOrInState("up")},icon:"fa-eraser"},{name:this.actionLabels.DESTROY,permission:"delete",click:function(){return s.showCriticalConfirmationModal(s.i18n("destroy"),s.i18n("OSD"),s.i18n("destroyed"),s.osdService.destroy)},disable:function(){return s.isNotSelectedOrInState("up")},icon:"fa-remove"}],this.advancedTableActions=[{name:this.i18n("Cluster-wide Flags"),icon:"fa-flag",click:function(){return s.configureFlagsAction()},permission:this.permissions.osd.read},{name:this.i18n("Cluster-wide Recovery Priority"),icon:"fa-cog",click:function(){return s.configureQosParamsAction()},permission:this.permissions.configOpt.read},{name:this.i18n("PG scrub"),icon:"fa-stethoscope",click:function(){return s.configurePgScrubAction()},permission:this.permissions.configOpt.read}]}return t.collectStates=function(t){return[t.in?"in":"out",t.up?"up":"down"]},t.prototype.ngOnInit=function(){this.columns=[{prop:"host.name",name:this.i18n("Host")},{prop:"id",name:this.i18n("ID"),cellTransformation:cn.a.bold},{prop:"collectedStates",name:this.i18n("Status"),cellTemplate:this.statusColor},{prop:"stats.numpg",name:this.i18n("PGs")},{prop:"stats.stat_bytes",name:this.i18n("Size"),pipe:this.dimlessBinaryPipe},{prop:"stats.usage",name:this.i18n("Usage"),cellTemplate:this.osdUsageTpl},{prop:"stats_history.out_bytes",name:this.i18n("Read bytes"),cellTransformation:cn.a.sparkline},{prop:"stats_history.in_bytes",name:this.i18n("Write bytes"),cellTransformation:cn.a.sparkline},{prop:"stats.op_r",name:this.i18n("Read ops"),cellTransformation:cn.a.perSecond},{prop:"stats.op_w",name:this.i18n("Write ops"),cellTransformation:cn.a.perSecond}],this.removeActionsWithNoPermissions()},Object.defineProperty(t.prototype,"hasOsdSelected",{get:function(){if(this.selection.hasSelection){var t=this.selection.first().id;return!!this.osds.filter(function(e){return e.id===t}).pop()}return!1},enumerable:!0,configurable:!0}),t.prototype.updateSelection=function(t){this.selection=t},t.prototype.isNotSelectedOrInState=function(t){if(!this.hasOsdSelected)return!0;var e=this.selection.first().id,n=this.osds.filter(function(t){return t.id===e}).pop();if(!n)return!0;switch(t){case"in":return 1===n.in;case"out":return 1!==n.in;case"down":return 1!==n.up;case"up":return 1===n.up}},t.prototype.getOsdList=function(){var e=this;this.osdService.getList().subscribe(function(n){e.osds=n.map(function(e){return e.collectedStates=t.collectStates(e),e.stats_history.out_bytes=e.stats_history.op_out_bytes.map(function(t){return t[1]}),e.stats_history.in_bytes=e.stats_history.op_in_bytes.map(function(t){return t[1]}),e.stats.usage=e.stats.stat_bytes_used/e.stats.stat_bytes,e.cdIsBinary=!0,e})})},t.prototype.scrubAction=function(t){this.hasOsdSelected&&(this.bsModalRef=this.modalService.show(da,{initialState:{selected:this.tableComponent.selection.selected,deep:t}}))},t.prototype.configureFlagsAction=function(){this.bsModalRef=this.modalService.show(Qn,{})},t.prototype.showConfirmationModal=function(t,e){var n=this;this.bsModalRef=this.modalService.show(Kn.a,{initialState:{titleText:this.i18n("Mark OSD {{markAction}}",{markAction:t}),buttonText:this.i18n("Mark {{markAction}}",{markAction:t}),bodyTpl:this.markOsdConfirmationTpl,bodyContext:{markActionDescription:t},onSubmit:function(){e.call(n.osdService,n.selection.first().id).subscribe(function(){return n.bsModalRef.hide()})}}})},t.prototype.reweight=function(){var t=this,e=this.osds.filter(function(e){return e.id===t.selection.first().id}).pop();this.modalService.show(la,{initialState:{currentWeight:e.weight,osdId:e.id}})},t.prototype.showCriticalConfirmationModal=function(t,e,n,a){var r=this;this.osdService.safeToDestroy(this.selection.first().id).subscribe(function(i){var s=r.modalService.show($n.a,{initialState:{actionDescription:t,itemDescription:e,bodyTemplate:r.criticalConfirmationTpl,bodyContext:{result:i,actionDescription:n},submitAction:function(){a.call(r.osdService,r.selection.first().id).subscribe(function(){return s.hide()})}}})})},t.prototype.configureQosParamsAction=function(){this.bsModalRef=this.modalService.show(ua,{})},t.prototype.configurePgScrubAction=function(){this.bsModalRef=this.modalService.show(oa,{class:"modal-lg"})},t.prototype.removeActionsWithNoPermissions=function(){this.advancedTableActions=this.permissions?this.advancedTableActions.filter(function(t){return t.permission}):[]},t}(),pa=n("DQlY"),ha=s["\u0275crt"]({encapsulation:0,styles:[[".caret.caret-black[_ngcontent-%COMP%]{color:#000}"]],data:{}});function ga(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"button",[["class","btn btn-sm btn-default dropdown-toggle dropdown-toggle-split"],["dropdownToggle",""],["type","button"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,1).onClick()&&a),a},null,null)),s["\u0275did"](1,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](2,0,null,null,0,"span",[["class","caret caret-black"]],null,null,null,null,null))],null,function(t,e){t(e,0,0,!0,s["\u0275nov"](e,1).isDisabled,s["\u0275nov"](e,1).isOpen)})}function ba(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,4,"li",[["role","menuitem"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,3,"a",[["class","dropdown-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.context.$implicit.click()&&a),a},null,null)),(t()(),s["\u0275eld"](3,0,null,null,0,"i",[["aria-hidden","true"]],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](5,null,["",""]))],null,function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"fa fa-fw ",e.context.$implicit.icon,"")),t(e,5,0,e.context.$implicit.name)})}function ma(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"ul",[["class","dropdown-menu"],["role","menu"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,ba)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.SlicePipe,[])],function(t,e){var n=e.component;t(e,2,0,s["\u0275unv"](e,2,0,s["\u0275nov"](e,3).transform(n.advancedTableActions,1)))},null)}function ya(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,10,"div",[["class","btn-group"],["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),(t()(),s["\u0275eld"](3,0,null,null,3,"button",[["class","btn btn-sm btn-default btn-label tc_configureCluster"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.advancedTableActions[0].click()&&a),a},null,null)),(t()(),s["\u0275eld"](4,0,null,null,0,"i",[],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](6,null,["",""])),(t()(),s["\u0275and"](16777216,null,null,1,null,ga)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ma)),s["\u0275did"](10,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,2,0),t(e,8,0,n.advancedTableActions.length>1)},function(t,e){var n=e.component;t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,4,0,s["\u0275inlineInterpolate"](1,"fa fa-fw ",n.advancedTableActions[0].icon,"")),t(e,6,0,n.advancedTableActions[0].name)})}function va(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0"]))],null,null)}function _a(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,5,"span",[["class","label"]],null,null,null,null,null)),s["\u0275did"](2,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pad"](3,2),s["\u0275pad"](4,2),s["\u0275pod"](5,{"label-success":0,"label-danger":1}),(t()(),s["\u0275ted"](6,null,["",""])),(t()(),s["\u0275and"](16777216,null,null,1,null,va)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=t(e,5,0,t(e,3,0,"in","up").includes(e.context.$implicit),t(e,4,0,"down","out").includes(e.context.$implicit));t(e,2,0,"label",n),t(e,8,0,!e.context.last)},function(t,e){t(e,6,0,e.context.$implicit)})}function xa(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,_a)),s["\u0275did"](1,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.context.value)},null)}function Ta(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-usage-bar",[],null,null,null,mn.b,mn.a)),s["\u0275did"](1,573440,null,0,yn.a,[],{total:[0,"total"],used:[1,"used"]},null)],function(t,e){t(e,1,0,e.context.row.stats.stat_bytes,e.context.row.stats.stat_bytes_used)},null)}function wa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"tab",[["heading","Overall Performance"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](1,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","three"],["uid","lo02I1Aiz"]],null,null,null,Me.b,Me.a)),s["\u0275did"](3,638976,null,0,qe.a,[je.a,Fe.DomSanitizer,ze.a,Ge.a,xt.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(t,e){t(e,1,0,"Overall Performance"),t(e,3,0,"osd-overview?","three","lo02I1Aiz")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).id,s["\u0275nov"](e,1).active,s["\u0275nov"](e,1).addClass)})}function Sa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["OSD ",""])),(t()(),s["\u0275ted"](-1,null,[" will be marked "])),(t()(),s["\u0275eld"](4,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275ted"](-1,null,[" if you proceed."]))],null,function(t,e){t(e,2,0,e.component.selection.first().id),t(e,5,0,e.context.markActionDescription)})}function Oa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"div",[["class","danger"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"cd-warning-panel",[],null,null,null,vn.b,vn.a)),s["\u0275did"](2,49152,null,0,_n.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["The OSD is not safe to destroy!"]))],null,null)}function Ia(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Oa)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](2,0,null,null,6,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](4,null,["OSD ",""])),(t()(),s["\u0275ted"](-1,null,[" will be "])),(t()(),s["\u0275eld"](6,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,["",""])),(t()(),s["\u0275ted"](-1,null,[" if you proceed."]))],function(t,e){t(e,1,0,!e.context.result.is_safe_to_destroy)},function(t,e){t(e,4,0,e.component.selection.first().id),t(e,7,0,e.context.actionDescription)})}function Ca(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{statusColor:0}),s["\u0275qud"](402653184,2,{osdUsageTpl:0}),s["\u0275qud"](402653184,3,{markOsdConfirmationTpl:0}),s["\u0275qud"](402653184,4,{criticalConfirmationTpl:0}),s["\u0275qud"](402653184,5,{tableComponent:0}),s["\u0275qud"](402653184,6,{reweightBodyTpl:0}),s["\u0275qud"](402653184,7,{safeToDestroyBodyTpl:0}),(t()(),s["\u0275eld"](7,0,null,null,16,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](8,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](9,0,null,0,12,"tab",[["heading","OSDs List"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](10,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](11,0,null,null,8,"cd-table",[["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(t,e,n){var a=!0,r=t.component;return"fetchData"===e&&(a=!1!==r.getOsdList()&&a),"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](12,2867200,[[5,4]],0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],selectionType:[2,"selectionType"],updateSelectionOnRefresh:[3,"updateSelectionOnRefresh"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](13,0,null,0,4,"div",[["class","table-actions btn-toolbar"]],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,null,1,"cd-table-actions",[["class","btn-group"]],null,null,null,xn.b,xn.a)),s["\u0275did"](15,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ya)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,2,1,"cd-osd-details",[["cdTableDetail",""]],null,null,null,Bn,Mn)),s["\u0275did"](19,573440,null,0,Pn,[Ln,l.a],{selection:[0,"selection"]},null),(t()(),s["\u0275and"](0,[[1,2],["statusColor",2]],null,0,null,xa)),(t()(),s["\u0275and"](0,[[2,2],["osdUsageTpl",2]],null,0,null,Ta)),(t()(),s["\u0275and"](16777216,null,0,1,null,wa)),s["\u0275did"](23,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,[[3,2],["markOsdConfirmationTpl",2]],null,0,null,Sa)),(t()(),s["\u0275and"](0,[[4,2],["criticalConfirmationTpl",2]],null,0,null,Ia))],function(t,e){var n=e.component;t(e,10,0,"OSDs List"),t(e,12,0,n.osds,n.columns,"single","never"),t(e,15,0,n.permissions.osd,n.selection,n.tableActions),t(e,17,0,n.advancedTableActions.length>0),t(e,19,0,n.selection),t(e,23,0,n.permissions.grafana.read)},function(t,e){t(e,7,0,s["\u0275nov"](e,8).clazz),t(e,9,0,s["\u0275nov"](e,10).id,s["\u0275nov"](e,10).active,s["\u0275nov"](e,10).addClass)})}function ka(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-list",[],null,null,null,Ca,ha)),s["\u0275did"](1,114688,null,0,fa,[l.a,Ln,ht.a,pa.b,xt.a,Zn.b],null,null)],function(t,e){t(e,1,0)},null)}var Na=s["\u0275ccf"]("cd-osd-list",fa,ka,{},{},[]),Ra=function(){function t(){}return t.prototype.transform=function(t,e){return t.filter(function(t){var n=!0;return e.forEach(function(e){if(e.value)return(n=n&&e.applyFilter(t,e.value))?void 0:n}),n})},t}(),Aa=n("iExv"),Da=function(){function t(t){this.i18n=t,this.flags={runtime:this.i18n("The value can be updated at runtime."),no_mon_update:this.i18n("Daemons/clients do not pull this value from the\n monitor config database. We disallow setting this option via 'ceph config\n set ...'. This option should be configured via ceph.conf or via the\n command line."),startup:this.i18n("Option takes effect only during daemon startup."),cluster_create:this.i18n("Option only affects cluster creation."),create:this.i18n("Option only affects daemon creation.")}}return t.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.selectedItem=this.selection.first(),this.selectedItem.services=ft.split(this.selectedItem.services,","))},t}(),Ea=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function La(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ",": ","",""])),(t()(),s["\u0275eld"](2,0,null,null,0,"br",[],null,null,null,null,null))],null,function(t,e){t(e,1,0,e.context.$implicit.section,e.context.$implicit.value,e.context.last?"":",")})}function Pa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,3,"span",[],[[8,"title",0]],null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,2,"span",[["class","badge badge-pill badge-primary margin-right-sm"]],null,null,null,null,null)),(t()(),s["\u0275ted"](3,null,["",""])),s["\u0275ppd"](4,1)],null,function(t,e){t(e,1,0,s["\u0275inlineInterpolate"](1,"",e.component.flags[e.context.$implicit],""));var n=s["\u0275unv"](e,3,0,t(e,4,0,s["\u0275nov"](e.parent.parent,0),e.context.$implicit));t(e,3,0,n)})}function Ma(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["class","badge badge-pill badge-primary margin-right-sm"]],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit)})}function qa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,94,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,92,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,90,"table",[["class","table table-striped table-bordered"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,89,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Name"])),(t()(),s["\u0275eld"](9,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](10,null,["",""])),(t()(),s["\u0275eld"](11,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Description"])),(t()(),s["\u0275eld"](14,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](15,null,["",""])),(t()(),s["\u0275eld"](16,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Long description"])),(t()(),s["\u0275eld"](19,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](20,null,["",""])),(t()(),s["\u0275eld"](21,0,null,null,5,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](22,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Current values"])),(t()(),s["\u0275eld"](24,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,La)),s["\u0275did"](26,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](27,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](28,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Default"])),(t()(),s["\u0275eld"](30,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](31,null,["",""])),(t()(),s["\u0275eld"](32,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](33,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Daemon default"])),(t()(),s["\u0275eld"](35,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](36,null,["",""])),(t()(),s["\u0275eld"](37,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](38,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Type"])),(t()(),s["\u0275eld"](40,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](41,null,["",""])),(t()(),s["\u0275eld"](42,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](43,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Min"])),(t()(),s["\u0275eld"](45,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](46,null,["",""])),(t()(),s["\u0275eld"](47,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](48,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Max"])),(t()(),s["\u0275eld"](50,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](51,null,["",""])),(t()(),s["\u0275eld"](52,0,null,null,5,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](53,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Flags"])),(t()(),s["\u0275eld"](55,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Pa)),s["\u0275did"](57,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](58,0,null,null,5,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](59,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Services"])),(t()(),s["\u0275eld"](61,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ma)),s["\u0275did"](63,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](64,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](65,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Source"])),(t()(),s["\u0275eld"](67,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](68,null,["",""])),(t()(),s["\u0275eld"](69,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](70,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Level"])),(t()(),s["\u0275eld"](72,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](73,null,["",""])),(t()(),s["\u0275eld"](74,0,null,null,5,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](75,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Can be updated at runtime (editable)"])),(t()(),s["\u0275eld"](77,0,null,null,2,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](78,null,["",""])),s["\u0275ppd"](79,1),(t()(),s["\u0275eld"](80,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](81,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Tags"])),(t()(),s["\u0275eld"](83,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](84,null,["",""])),(t()(),s["\u0275eld"](85,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](86,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Enum values"])),(t()(),s["\u0275eld"](88,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](89,null,["",""])),(t()(),s["\u0275eld"](90,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](91,0,null,null,1,"td",[["class","bold col-sm-1"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["See also"])),(t()(),s["\u0275eld"](93,0,null,null,1,"td",[["class","col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](94,null,["",""]))],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,26,0,n.selectedItem.value),t(e,57,0,n.selectedItem.flags),t(e,63,0,n.selectedItem.services)},function(t,e){var n=e.component;t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass),t(e,10,0,n.selectedItem.name),t(e,15,0,n.selectedItem.desc),t(e,20,0,n.selectedItem.long_desc),t(e,31,0,n.selectedItem.default),t(e,36,0,n.selectedItem.daemon_default),t(e,41,0,n.selectedItem.type),t(e,46,0,n.selectedItem.min),t(e,51,0,n.selectedItem.max),t(e,68,0,n.selectedItem.source),t(e,73,0,n.selectedItem.level);var a=s["\u0275unv"](e,78,0,t(e,79,0,s["\u0275nov"](e.parent,1),n.selectedItem.can_update_at_runtime));t(e,78,0,a),t(e,84,0,n.selectedItem.tags),t(e,89,0,n.selectedItem.enum_values),t(e,94,0,n.selectedItem.see_also)})}function ja(t){return s["\u0275vid"](0,[s["\u0275pid"](0,i.UpperCasePipe,[]),s["\u0275pid"](0,Aa.a,[xt.a]),(t()(),s["\u0275and"](16777216,null,null,1,null,qa)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,null==n.selection?null:n.selection.hasSingleSelection)},null)}var Fa=function(){function t(t,e,n,a){var r=this;this.authStorageService=t,this.configurationService=e,this.i18n=n,this.actionLabels=a,this.data=[],this.selection=new He.a,this.filters=[{label:this.i18n("Level"),prop:"level",initValue:"basic",value:"basic",options:["basic","advanced","dev"],applyFilter:function(t,e){var n=function(t){return t[t.basic=0]="basic",t[t.advanced=1]="advanced",t[t.dev=2]="dev",t}({});return n[t.level]<=n[e]}},{label:this.i18n("Service"),prop:"services",initValue:"any",value:"any",options:["any","mon","mgr","osd","mds","common","mds_client","rgw"],applyFilter:function(t,e){return"any"===e||t.services.includes(e)}},{label:this.i18n("Source"),prop:"source",initValue:"any",value:"any",options:["any","mon"],applyFilter:function(t,e){return"any"===e||!!t.hasOwnProperty("source")&&t.source.includes(e)}}],this.permission=this.authStorageService.getPermissions().configOpt,this.tableActions=[{permission:"update",icon:"fa-pencil",routerLink:function(){return"/configuration/edit/"+(r.selection.first()&&""+encodeURIComponent(r.selection.first().name))},name:this.actionLabels.EDIT,disable:function(){return!r.isEditable(r.selection)}}]}return t.prototype.ngOnInit=function(){this.columns=[{canAutoResize:!0,prop:"name",name:this.i18n("Name")},{prop:"desc",name:this.i18n("Description"),cellClass:"wrap"},{prop:"value",name:this.i18n("Current value"),cellClass:"wrap",cellTemplate:this.confValTpl},{prop:"default",name:this.i18n("Default"),cellClass:"wrap"},{prop:"can_update_at_runtime",name:this.i18n("Editable"),cellTransformation:cn.a.checkIcon,flexGrow:.4,cellClass:"text-center"}]},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.getConfigurationList=function(t){var e=this;this.configurationService.getConfigData().subscribe(function(t){e.data=t},function(){t.error()})},t.prototype.updateFilter=function(){this.data=this.data.slice()},t.prototype.resetFilter=function(){this.filters.forEach(function(t){t.value=t.initValue}),this.data=this.data.slice()},t.prototype.isEditable=function(t){return 1===t.selected.length&&t.selected[0].can_update_at_runtime},t}(),za=s["\u0275crt"]({encapsulation:0,styles:[[".filter[_ngcontent-%COMP%]{padding-right:8px} datatable-body-cell.wrap{word-break:break-all}"]],data:{}});function Ga(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],null,null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],null,null),(t()(),s["\u0275ted"](3,null,["",""]))],null,function(t,e){t(e,3,0,e.context.$implicit)})}function Ya(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,11,"div",[["class","form-group filter"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",": "])),(t()(),s["\u0275eld"](3,0,null,null,8,"select",[["class","form-control input-sm"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,5).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,5).onTouched()&&a),"ngModelChange"===e&&(a=!1!==(t.context.$implicit.value=n)&&a),"ngModelChange"===e&&(a=!1!==r.updateFilter()&&a),a},null,null)),s["\u0275did"](4,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](5,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](7,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](9,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ga)),s["\u0275did"](11,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,7,0,e.context.$implicit.value),t(e,11,0,e.context.$implicit.options)},function(t,e){t(e,2,0,e.context.$implicit.label),t(e,3,0,s["\u0275nov"](e,9).ngClassUntouched,s["\u0275nov"](e,9).ngClassTouched,s["\u0275nov"](e,9).ngClassPristine,s["\u0275nov"](e,9).ngClassDirty,s["\u0275nov"](e,9).ngClassValid,s["\u0275nov"](e,9).ngClassInvalid,s["\u0275nov"](e,9).ngClassPending)})}function Va(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ",": ","",""])),(t()(),s["\u0275eld"](2,0,null,null,0,"br",[],null,null,null,null,null))],null,function(t,e){t(e,1,0,e.context.$implicit.section,e.context.$implicit.value,e.context.last?"":",")})}function Ha(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Va)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.parent.context.value)},null)}function Ba(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Ha)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.context.value)},null)}function Ua(t){return s["\u0275vid"](0,[s["\u0275pid"](0,Ra,[]),s["\u0275qud"](402653184,1,{confValTpl:0}),s["\u0275qud"](402653184,2,{confFlagTpl:0}),(t()(),s["\u0275eld"](3,0,null,null,12,"cd-table",[["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(t,e,n){var a=!0,r=t.component;return"fetchData"===e&&(a=!1!==r.getConfigurationList(n)&&a),"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](4,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],selectionType:[2,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),s["\u0275ppd"](5,2),(t()(),s["\u0275eld"](6,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,xn.b,xn.a)),s["\u0275did"](7,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275eld"](8,0,null,1,5,"div",[["class","table-filters"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ya)),s["\u0275did"](10,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](11,0,null,null,2,"a",[["class","fa-stack"],["title","Reset filters"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.resetFilter()&&a),a},null,null)),(t()(),s["\u0275eld"](12,0,null,null,0,"i",[["class","fa fa-filter fa-stack-2x"]],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,0,"i",[["class","fa fa-times fa-stack-1x"],["style","margin-left: 8px; margin-top: 5px;"]],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,2,1,"cd-configuration-details",[["cdTableDetail",""]],null,null,null,ja,Ea)),s["\u0275did"](15,573440,null,0,Da,[xt.a],{selection:[0,"selection"]},null),(t()(),s["\u0275and"](0,[[1,2],["confValTpl",2]],null,0,null,Ba))],function(t,e){var n=e.component,a=s["\u0275unv"](e,4,0,t(e,5,0,s["\u0275nov"](e,0),n.data,n.filters));t(e,4,0,a,n.columns,"single"),t(e,7,0,n.permission,n.selection,n.tableActions),t(e,10,0,n.filters),t(e,15,0,n.selection)},null)}function Wa(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-configuration",[],null,null,null,Ua,za)),s["\u0275did"](1,114688,null,0,Fa,[l.a,ea.a,xt.a,Zn.b],null,null)],function(t,e){t(e,1,0)},null)}var Ka=s["\u0275ccf"]("cd-configuration",Fa,Wa,{},{},[]),$a=n("gp3X"),Za=n("sb0X"),Xa=n("KVJa"),Ja=n("Z21x"),Qa=function(){return function(){this.value=[]}}(),tr=function(){function t(t,e,n,a,r){this.route=t,this.router=e,this.configService=n,this.notificationService=a,this.i18n=r,this.availSections=["global","mon","mgr","osd","mds","client"],this.createForm()}return t.prototype.createForm=function(){var t={name:new Te.i({value:null}),desc:new Te.i({value:null}),long_desc:new Te.i({value:null}),values:new Te.k({}),default:new Te.i({value:null}),daemon_default:new Te.i({value:null}),services:new Te.i([])};this.availSections.forEach(function(e){t.values.addControl(e,new Te.i(null))}),this.configForm=new na.a(t)},t.prototype.ngOnInit=function(){var t=this;this.route.params.subscribe(function(e){t.configService.get(e.name).subscribe(function(e){t.setResponse(e)})})},t.prototype.getValidators=function(t){var e=ra.getTypeValidators(t);if(e)return this.patternHelpText=e.patternHelpText,"max"in e&&""!==e.max&&(this.maxValue=e.max),"min"in e&&""!==e.min&&(this.minValue=e.min),e.validators},t.prototype.getStep=function(t,e){return ra.getTypeStep(t,e)},t.prototype.setResponse=function(t){var e=this;this.response=t;var n=this.getValidators(t);this.configForm.get("name").setValue(t.name),this.configForm.get("desc").setValue(t.desc),this.configForm.get("long_desc").setValue(t.long_desc),this.configForm.get("default").setValue(t.default),this.configForm.get("daemon_default").setValue(t.daemon_default),this.configForm.get("services").setValue(t.services),this.response.value&&this.response.value.forEach(function(t){var n;n="true"===t.value||"false"!==t.value&&t.value,e.configForm.get("values").get(t.section).setValue(n)}),this.availSections.forEach(function(t){e.configForm.get("values").get(t).setValidators(n)});var a=ra.getType(t.type);this.type=a.name,this.inputType=a.inputType,this.humanReadableType=a.humanReadable},t.prototype.createRequest=function(){var t=this,e=[];if(this.availSections.forEach(function(n){var a=t.configForm.getValue(n);null!==a&&""!==a&&e.push({section:n,value:a})}),!ft.isEqual(this.response.value,e)){var n=new Qa;return n.name=this.configForm.getValue("name"),n.value=e,n}return null},t.prototype.submit=function(){var t=this,e=this.createRequest();e&&this.configService.create(e).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n("Updated config option {{name}}",{name:e.name})),t.router.navigate(["/configuration"])},function(){t.configForm.setErrors({cdSubmitButton:!0})}),this.router.navigate(["/configuration"])},t}(),er=s["\u0275crt"]({encapsulation:0,styles:[[".form-component-badge[_ngcontent-%COMP%]{height:34px;display:block}.form-component-badge[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{margin-top:7px}.resize-vertical[_ngcontent-%COMP%]{resize:vertical}"]],data:{}});function nr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Description"])),(t()(),s["\u0275eld"](3,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,6,"textarea",[["class","form-control resize-vertical"],["formControlName","desc"],["id","desc"],["readonly",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,5)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,5).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,5)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,5)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](5,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](7,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](9,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275ted"](-1,null,[" "]))],function(t,e){t(e,7,0,"desc")},function(t,e){t(e,4,0,s["\u0275nov"](e,9).ngClassUntouched,s["\u0275nov"](e,9).ngClassTouched,s["\u0275nov"](e,9).ngClassPristine,s["\u0275nov"](e,9).ngClassDirty,s["\u0275nov"](e,9).ngClassValid,s["\u0275nov"](e,9).ngClassInvalid,s["\u0275nov"](e,9).ngClassPending)})}function ar(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Long description"])),(t()(),s["\u0275eld"](3,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,6,"textarea",[["class","form-control resize-vertical"],["formControlName","long_desc"],["id","long_desc"],["readonly",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,5)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,5).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,5)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,5)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](5,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](7,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](9,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275ted"](-1,null,[" "]))],function(t,e){t(e,7,0,"long_desc")},function(t,e){t(e,4,0,s["\u0275nov"](e,9).ngClassUntouched,s["\u0275nov"](e,9).ngClassTouched,s["\u0275nov"](e,9).ngClassPristine,s["\u0275nov"](e,9).ngClassDirty,s["\u0275nov"](e,9).ngClassValid,s["\u0275nov"](e,9).ngClassInvalid,s["\u0275nov"](e,9).ngClassPending)})}function rr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Default"])),(t()(),s["\u0275eld"](3,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,6,"input",[["class","form-control"],["formControlName","default"],["id","default"],["readonly",""],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,6)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,6).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,6)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,6)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](5,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](6,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](8,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](10,16384,null,0,Te.r,[[4,Te.q]],null,null)],function(t,e){t(e,8,0,"default")},function(t,e){t(e,4,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending)})}function ir(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Daemon default"])),(t()(),s["\u0275eld"](3,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,6,"input",[["class","form-control"],["formControlName","daemon_default"],["id","daemon_default"],["readonly",""],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,6)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,6).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,6)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,6)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](5,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](6,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](8,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](10,16384,null,0,Te.r,[[4,Te.q]],null,null)],function(t,e){t(e,8,0,"daemon_default")},function(t,e){t(e,4,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending)})}function sr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[["class","form-component-badge"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["class","badge badge-pill badge-primary"]],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit)})}function or(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Services"])),(t()(),s["\u0275eld"](3,0,null,null,2,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,sr)),s["\u0275did"](5,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,5,0,e.component.configForm.getValue("services"))},null)}function ur(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"label",[["class","control-label col-sm-3"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](2,null,[""," "])),(t()(),s["\u0275eld"](3,0,null,null,19,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,18,"select",[["class","form-control custom-select"],["id","pool"],["name","pool"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,6).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,6).onTouched()&&a),a},null,null)),s["\u0275did"](5,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](6,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](8,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](10,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](11,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](12,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{ngValue:[0,"ngValue"]},null),s["\u0275did"](13,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),s["\u0275ted"](-1,null,["-- Default --"])),(t()(),s["\u0275eld"](15,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](16,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{ngValue:[0,"ngValue"]},null),s["\u0275did"](17,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),s["\u0275ted"](-1,null,["true"])),(t()(),s["\u0275eld"](19,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](20,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{ngValue:[0,"ngValue"]},null),s["\u0275did"](21,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),s["\u0275ted"](-1,null,["false"]))],function(t,e){t(e,8,0,e.parent.context.$implicit),t(e,12,0,null),t(e,13,0,null),t(e,16,0,!0),t(e,17,0,!0),t(e,20,0,!1),t(e,21,0,!1)},function(t,e){t(e,1,0,e.parent.context.$implicit),t(e,2,0,e.parent.context.$implicit),t(e,4,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending)})}function cr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){t(e,1,0,e.component.patternHelpText)})}function lr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){t(e,1,0,e.component.patternHelpText)})}function dr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too high! It must not be greater than ","."]))],null,function(t,e){t(e,1,0,e.component.maxValue)})}function fr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too low! It must not be lower than ","."]))],null,function(t,e){t(e,1,0,e.component.minValue)})}function pr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,1,"label",[["class","control-label col-sm-3"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](4,null,[""," "])),(t()(),s["\u0275eld"](5,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,6,"input",[["class","form-control"]],[[8,"type",0],[8,"id",0],[8,"placeholder",0],[8,"step",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,8)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,8).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,8)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,8)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](7,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](8,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](10,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](12,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,cr)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,lr)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,dr)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,fr)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.configForm.showError(e.parent.context.$implicit,s["\u0275nov"](e.parent.parent,3)));t(e,1,0,"form-group",a),t(e,10,0,e.parent.context.$implicit),t(e,14,0,n.configForm.showError(e.parent.context.$implicit,s["\u0275nov"](e.parent.parent,3),"pattern")),t(e,16,0,n.configForm.showError(e.parent.context.$implicit,s["\u0275nov"](e.parent.parent,3),"invalidUuid")),t(e,18,0,n.configForm.showError(e.parent.context.$implicit,s["\u0275nov"](e.parent.parent,3),"max")),t(e,20,0,n.configForm.showError(e.parent.context.$implicit,s["\u0275nov"](e.parent.parent,3),"min"))},function(t,e){var n=e.component;t(e,3,0,e.parent.context.$implicit),t(e,4,0,e.parent.context.$implicit),t(e,6,1,[n.inputType,e.parent.context.$implicit,n.humanReadableType,n.getStep(n.type,n.configForm.getValue(e.parent.context.$implicit)),s["\u0275nov"](e,12).ngClassUntouched,s["\u0275nov"](e,12).ngClassTouched,s["\u0275nov"](e,12).ngClassPristine,s["\u0275nov"](e,12).ngClassDirty,s["\u0275nov"](e,12).ngClassValid,s["\u0275nov"](e,12).ngClassInvalid,s["\u0275nov"](e,12).ngClassPending])})}function hr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,ur)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,pr)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,"bool"===n.type),t(e,4,0,"bool"!==n.type)},null)}function gr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,49,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,48,"form",[["class","form-horizontal"],["name","configForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,3).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,3).onReset()&&a),a},null,null)),s["\u0275did"](2,16384,null,0,Te.D,[],null,null),s["\u0275did"](3,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](5,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](6,0,null,null,43,"div",[["class","panel panel-default"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Edit"])),(t()(),s["\u0275ted"](11,null,[" "," "])),(t()(),s["\u0275eld"](12,0,null,null,29,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,10,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,null,1,"label",[["class","control-label col-sm-3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Name"])),(t()(),s["\u0275eld"](16,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,6,"input",[["class","form-control"],["formControlName","name"],["id","name"],["readonly",""],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,19)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,19).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](18,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](19,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](21,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](23,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,nr)),s["\u0275did"](25,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ar)),s["\u0275did"](27,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,rr)),s["\u0275did"](29,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ir)),s["\u0275did"](31,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,or)),s["\u0275did"](33,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](34,0,null,null,7,"div",[["class","col-sm-12"],["formGroupName","values"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),s["\u0275did"](35,212992,null,0,Te.m,[[3,Te.d],[8,null],[8,null]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.m]),s["\u0275did"](37,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](38,0,null,null,1,"h2",[["class","page-header"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Values"])),(t()(),s["\u0275and"](16777216,null,null,1,null,hr)),s["\u0275did"](41,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](42,0,null,null,7,"div",[["class","panel-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](43,0,null,null,6,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275eld"](44,0,null,null,3,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submit()&&a),a},$a.b,$a.a)),s["\u0275did"](45,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(t()(),s["\u0275eld"](46,0,null,0,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Save"])),(t()(),s["\u0275eld"](48,0,null,null,1,"cd-back-button",[],null,null,null,Xa.b,Xa.a)),s["\u0275did"](49,49152,null,0,Ja.a,[i.Location,Zn.b],null,null)],function(t,e){var n=e.component;t(e,3,0,n.configForm),t(e,21,0,"name"),t(e,25,0,n.configForm.getValue("desc")),t(e,27,0,n.configForm.getValue("long_desc")),t(e,29,0,""!==n.configForm.getValue("default")),t(e,31,0,""!==n.configForm.getValue("daemon_default")),t(e,33,0,n.configForm.getValue("services").length>0),t(e,35,0,"values"),t(e,41,0,n.availSections),t(e,45,0,s["\u0275nov"](e,3),"button")},function(t,e){var n=e.component;t(e,1,0,s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending),t(e,11,0,n.configForm.getValue("name")),t(e,17,0,s["\u0275nov"](e,23).ngClassUntouched,s["\u0275nov"](e,23).ngClassTouched,s["\u0275nov"](e,23).ngClassPristine,s["\u0275nov"](e,23).ngClassDirty,s["\u0275nov"](e,23).ngClassValid,s["\u0275nov"](e,23).ngClassInvalid,s["\u0275nov"](e,23).ngClassPending),t(e,34,0,s["\u0275nov"](e,37).ngClassUntouched,s["\u0275nov"](e,37).ngClassTouched,s["\u0275nov"](e,37).ngClassPristine,s["\u0275nov"](e,37).ngClassDirty,s["\u0275nov"](e,37).ngClassValid,s["\u0275nov"](e,37).ngClassInvalid,s["\u0275nov"](e,37).ngClassPending)})}function br(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-configuration-form",[],null,null,null,gr,er)),s["\u0275did"](1,114688,null,0,tr,[tt.a,tt.l,ea.a,Jn.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var mr=s["\u0275ccf"]("cd-configuration-form",tr,br,{},{},[]),yr=n("nuQ0"),vr=n("Tff5"),_r=n("urB8"),xr=n("xtUU"),Tr=function(){function t(t){this.healthService=t,this.metadataKeyMap={}}return t.prototype.ngOnInit=function(){var t=this;this.healthService.getFullHealth().subscribe(function(e){t.tree=t._abstractTreeData(e)})},t.prototype._abstractTreeData=function(t){var e=this,n=t.osd_map.tree.nodes||[],a={};if(0===n.length)return{value:"No nodes!",settings:{static:!0}};var r=[];return n.reverse().forEach(function(t){"root"===t.type&&r.push(t.id),a[t.id]=e.generateTreeLeaf(t,a)}),{value:"CRUSH map",children:r.map(function(t){return a[t]})}},t.prototype.generateTreeLeaf=function(t,e){var n=t.id;this.metadataKeyMap[n]=t;var a={static:!0},r=t.name+" ("+t.type+")",i=t.status,s=[];return t.children?(t.children.sort().forEach(function(t){s.push(e[t])}),{value:r,status:i,settings:a,id:n,children:s}):{value:r,status:i,settings:a,id:n}},t.prototype.onNodeSelected=function(t){var e=this.metadataKeyMap[t.node.id],n=e.name,a=e.type,r=p.__rest(e,["name","type","status"]);this.metadata=r,this.metadataTitle=n+" ("+a+")"},t}(),wr=s["\u0275crt"]({encapsulation:0,styles:[["tree-internal .tree li{cursor:pointer} tree-internal .tree .node-value{color:#2b99a8;border-radius:5px} tree-internal .tree .node-selected{background-color:#d9edf7;color:#212121} tree-internal .tree .node-value:hover{color:#212121} tree-internal .tree .node-value:after{height:0}"]],data:{}});function Sr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"span",[["class","label"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pad"](2,2),s["\u0275pad"](3,3),s["\u0275pod"](4,{"label-success":0,"label-danger":1}),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0"])),(t()(),s["\u0275eld"](8,0,null,null,0,"span",[["class","node-name"]],[[8,"innerHTML",1]],null,null,null,null))],function(t,e){var n=t(e,4,0,t(e,2,0,"in","up").includes(e.context.$implicit.status),t(e,3,0,"down","out","destroyed").includes(e.context.$implicit.status));t(e,1,0,"label",n)},function(t,e){t(e,5,0,e.context.$implicit.status),t(e,8,0,e.context.$implicit.value)})}function Or(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"div",[["class","col-sm-6 col-lg-6 metadata"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",""])),(t()(),s["\u0275eld"](3,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](4,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},null)],function(t,e){t(e,4,0,e.component.metadata)},function(t,e){t(e,2,0,e.component.metadataTitle)})}function Ir(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,16,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,15,"div",[["class","col-sm-12 col-lg-12"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,14,"div",[["class","panel panel-default"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,3,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,2,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CRUSH map viewer"])),(t()(),s["\u0275eld"](7,0,null,null,9,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,6,"div",[["class","col-sm-6 col-lg-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,5,"tree",[],null,[[null,"nodeSelected"]],function(t,e,n){var a=!0;return"nodeSelected"===e&&(a=!1!==t.component.onNodeSelected(n)&&a),a},yr.b,yr.a)),s["\u0275prd"](512,null,vr.TreeService,vr.TreeService,[_r.NodeDraggableService]),s["\u0275did"](11,770048,null,1,xr.TreeComponent,[vr.TreeService],{treeModel:[0,"treeModel"],settings:[1,"settings"]},{nodeSelected:"nodeSelected"}),s["\u0275qud"](335544320,1,{template:0}),s["\u0275pod"](13,{rootIsVisible:0}),(t()(),s["\u0275and"](0,[[1,2]],null,0,null,Sr)),(t()(),s["\u0275and"](16777216,null,null,1,null,Or)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=n.tree,r=t(e,13,0,!1);t(e,11,0,a,r),t(e,16,0,n.metadata)},null)}function Cr(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-crushmap",[],null,null,null,Ir,wr)),s["\u0275did"](1,114688,null,0,Tr,[Rt],null,null)],function(t,e){t(e,1,0)},null)}var kr=s["\u0275ccf"]("cd-crushmap",Tr,Cr,{},{},[]),Nr=n("ARl4"),Rr=n("MwfX"),Ar=function(){function t(){}return t.prototype.writeValue=function(e){return{type:t.WRITE_VALUE,payload:e}},t.prototype.changeHours=function(e){return{type:t.CHANGE_HOURS,payload:e}},t.prototype.changeMinutes=function(e){return{type:t.CHANGE_MINUTES,payload:e}},t.prototype.changeSeconds=function(e){return{type:t.CHANGE_SECONDS,payload:e}},t.prototype.setTime=function(e){return{type:t.SET_TIME_UNIT,payload:e}},t.prototype.updateControls=function(e){return{type:t.UPDATE_CONTROLS,payload:e}},t.WRITE_VALUE="[timepicker] write value from ng model",t.CHANGE_HOURS="[timepicker] change hours",t.CHANGE_MINUTES="[timepicker] change minutes",t.CHANGE_SECONDS="[timepicker] change seconds",t.SET_TIME_UNIT="[timepicker] set time unit",t.UPDATE_CONTROLS="[timepicker] update controls",t}(),Dr=10,Er=24,Lr=12,Pr=60,Mr=60;function qr(t){return!!t&&!(t instanceof Date&&isNaN(t.getHours()))&&("string"!=typeof t||qr(new Date(t)))}function jr(t,e){return!(t.min&&e<t.min||t.max&&e>t.max)}function Fr(t){return"number"==typeof t?t:parseInt(t,Dr)}function zr(t,e){void 0===e&&(e=!1);var n=Fr(t);return isNaN(n)||n<0||n>(e?Lr:Er)?NaN:n!==Lr||e?n:0}function Gr(t){var e=Fr(t);return isNaN(e)||e<0||e>Pr?NaN:e}function Yr(t){var e=Fr(t);return isNaN(e)||e<0||e>Mr?NaN:e}function Vr(t){return"string"==typeof t?new Date(t):t}function Hr(t,e){if(!t)return Hr(Ur(new Date,0,0,0),e);var n=t.getHours(),a=t.getMinutes(),r=t.getSeconds();return e.hour&&(n=(n+Fr(e.hour))%Er)<0&&(n+=Er),e.minute&&(a+=Fr(e.minute)),e.seconds&&(r+=Fr(e.seconds)),Ur(t,n,a,r)}function Br(t,e){var n=zr(e.hour),a=Gr(e.minute),r=Yr(e.seconds)||0;return e.isPM&&12!==n&&(n+=Lr),t?isNaN(n)||isNaN(a)?t:Ur(t,n,a,r):isNaN(n)||isNaN(a)?t:Ur(new Date,n,a,r)}function Ur(t,e,n,a){return new Date(t.getFullYear(),t.getMonth(),t.getDate(),e,n,a,t.getMilliseconds())}function Wr(t){var e=t.toString();return e.length>1?e:"0"+e}function Kr(t,e){return!isNaN(zr(t,e))}function $r(t){return!isNaN(Gr(t))}function Zr(t){return!isNaN(Yr(t))}function Xr(t,e,n,a){return void 0===e&&(e="0"),void 0===n&&(n="0"),Kr(t,a)&&$r(e)&&Zr(n)}function Jr(t,e){if(t.readonlyInput||t.disabled)return!1;if(e){if("wheel"===e.source&&!t.mousewheel)return!1;if("key"===e.source&&!t.arrowkeys)return!1}return!0}function Qr(t){return{hourStep:t.hourStep,minuteStep:t.minuteStep,secondsStep:t.secondsStep,readonlyInput:t.readonlyInput,disabled:t.disabled,mousewheel:t.mousewheel,arrowkeys:t.arrowkeys,showSpinners:t.showSpinners,showMeridian:t.showMeridian,showSeconds:t.showSeconds,meridians:t.meridians,min:t.min,max:t.max}}var ti=function(){return function(){this.hourStep=1,this.minuteStep=5,this.secondsStep=10,this.showMeridian=!0,this.meridians=["AM","PM"],this.readonlyInput=!1,this.disabled=!1,this.mousewheel=!0,this.arrowkeys=!0,this.showSpinners=!0,this.showSeconds=!1,this.showMinutes=!0}}(),ei={value:null,config:new ti,controls:{canIncrementHours:!0,canIncrementMinutes:!0,canIncrementSeconds:!0,canDecrementHours:!0,canDecrementMinutes:!0,canDecrementSeconds:!0,canToggleMeridian:!0}};function ni(t,e){switch(void 0===t&&(t=ei),e.type){case Ar.WRITE_VALUE:return Object.assign({},t,{value:e.payload});case Ar.CHANGE_HOURS:if(!Jr(t.config,e.payload)||(s=t.controls,!(i=e.payload).step||i.step>0&&!s.canIncrementHours||i.step<0&&!s.canDecrementHours))return t;var n=Hr(t.value,{hour:e.payload.step});return!t.config.max&&!t.config.min||jr(t.config,n)?Object.assign({},t,{value:n}):t;case Ar.CHANGE_MINUTES:return Jr(t.config,e.payload)&&function(t,e){return!(!t.step||t.step>0&&!e.canIncrementMinutes||t.step<0&&!e.canDecrementMinutes)}(e.payload,t.controls)?(n=Hr(t.value,{minute:e.payload.step}),!t.config.max&&!t.config.min||jr(t.config,n)?Object.assign({},t,{value:n}):t):t;case Ar.CHANGE_SECONDS:return Jr(t.config,e.payload)&&function(t,e){return!(!t.step||t.step>0&&!e.canIncrementSeconds||t.step<0&&!e.canDecrementSeconds)}(e.payload,t.controls)?(n=Hr(t.value,{seconds:e.payload.step}),!t.config.max&&!t.config.min||jr(t.config,n)?Object.assign({},t,{value:n}):t):t;case Ar.SET_TIME_UNIT:return Jr(t.config)?(n=Br(t.value,e.payload),Object.assign({},t,{value:n})):t;case Ar.UPDATE_CONTROLS:var a=function(t,e){var n=e.min,a=e.max,r=e.hourStep,i=e.minuteStep,s=e.secondsStep,o=e.showSeconds,u={canIncrementHours:!0,canIncrementMinutes:!0,canIncrementSeconds:!0,canDecrementHours:!0,canDecrementMinutes:!0,canDecrementSeconds:!0,canToggleMeridian:!0};if(!t)return u;if(a){var c=Hr(t,{hour:r});if(u.canIncrementHours=a>c,!u.canIncrementHours){var l=Hr(t,{minute:i});u.canIncrementMinutes=o?a>l:a>=l}if(!u.canIncrementMinutes){var d=Hr(t,{seconds:s});u.canIncrementSeconds=a>=d}t.getHours()<12&&(u.canToggleMeridian=Hr(t,{hour:12})<a)}return n&&(c=Hr(t,{hour:-r}),u.canDecrementHours=n<c,u.canDecrementHours||(l=Hr(t,{minute:-i}),u.canDecrementMinutes=o?n<l:n<=l),u.canDecrementMinutes||(d=Hr(t,{seconds:-s}),u.canDecrementSeconds=n<=d),t.getHours()>=12&&(u.canToggleMeridian=Hr(t,{hour:-12})>n)),u}(t.value,e.payload),r={value:t.value,config:e.payload,controls:a};return t.config.showMeridian!==r.config.showMeridian&&t.value&&(r.value=new Date(t.value)),Object.assign({},t,r);default:return t}var i,s}var ai=function(t){function e(){var e=new Dt.a({type:"[mini-ngrx] dispatcher init"}),n=new Rr.a(ei,e,ni);return t.call(this,e,ni,n)||this}return Object(p.__extends)(e,t),e}(Rr.b),ri=function(){function t(t,e,n,a){var r=this;this._cd=e,this._store=n,this._timepickerActions=a,this.isValid=new s.EventEmitter,this.invalidHours=!1,this.invalidMinutes=!1,this.invalidSeconds=!1,this.onChange=Function.prototype,this.onTouched=Function.prototype,Object.assign(this,t),this.timepickerSub=n.select(function(t){return t.value}).subscribe(function(t){r._renderTime(t),r.onChange(t),r._store.dispatch(r._timepickerActions.updateControls(Qr(r)))}),n.select(function(t){return t.controls}).subscribe(function(t){r.isValid.emit(Xr(r.hours,r.minutes,r.seconds,r.isPM())),Object.assign(r,t),e.markForCheck()})}return Object.defineProperty(t.prototype,"isSpinnersVisible",{get:function(){return this.showSpinners&&!this.readonlyInput},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isEditable",{get:function(){return!(this.readonlyInput||this.disabled)},enumerable:!0,configurable:!0}),t.prototype.resetValidation=function(){this.invalidHours=!1,this.invalidMinutes=!1,this.invalidSeconds=!1},t.prototype.isPM=function(){return this.showMeridian&&this.meridian===this.meridians[1]},t.prototype.prevDef=function(t){t.preventDefault()},t.prototype.wheelSign=function(t){return-1*Math.sign(t.deltaY)},t.prototype.ngOnChanges=function(t){this._store.dispatch(this._timepickerActions.updateControls(Qr(this)))},t.prototype.changeHours=function(t,e){void 0===e&&(e=""),this.resetValidation(),this._store.dispatch(this._timepickerActions.changeHours({step:t,source:e}))},t.prototype.changeMinutes=function(t,e){void 0===e&&(e=""),this.resetValidation(),this._store.dispatch(this._timepickerActions.changeMinutes({step:t,source:e}))},t.prototype.changeSeconds=function(t,e){void 0===e&&(e=""),this.resetValidation(),this._store.dispatch(this._timepickerActions.changeSeconds({step:t,source:e}))},t.prototype.updateHours=function(t){if(this.resetValidation(),this.hours=t,!Kr(this.hours,this.isPM())||!this.isValidLimit())return this.invalidHours=!0,this.isValid.emit(!1),void this.onChange(null);this._updateTime()},t.prototype.updateMinutes=function(t){if(this.resetValidation(),this.minutes=t,!$r(this.minutes)||!this.isValidLimit())return this.invalidMinutes=!0,this.isValid.emit(!1),void this.onChange(null);this._updateTime()},t.prototype.updateSeconds=function(t){if(this.resetValidation(),this.seconds=t,!Zr(this.seconds)||!this.isValidLimit())return this.invalidSeconds=!0,this.isValid.emit(!1),void this.onChange(null);this._updateTime()},t.prototype.isValidLimit=function(){return t={hour:this.hours,minute:this.minutes,seconds:this.seconds,isPM:this.isPM()},e=this.max,n=this.min,a=Br(new Date,t),!(e&&a>e||n&&a<n);var t,e,n,a},t.prototype._updateTime=function(){if(!Xr(this.hours,this.showMinutes?this.minutes:void 0,this.showSeconds?this.seconds:void 0,this.isPM()))return this.isValid.emit(!1),void this.onChange(null);this._store.dispatch(this._timepickerActions.setTime({hour:this.hours,minute:this.minutes,seconds:this.seconds,isPM:this.isPM()}))},t.prototype.toggleMeridian=function(){this.showMeridian&&this.isEditable&&this._store.dispatch(this._timepickerActions.changeHours({step:12,source:""}))},t.prototype.writeValue=function(t){qr(t)?this._store.dispatch(this._timepickerActions.writeValue(Vr(t))):null==t&&this._store.dispatch(this._timepickerActions.writeValue(null))},t.prototype.registerOnChange=function(t){this.onChange=t},t.prototype.registerOnTouched=function(t){this.onTouched=t},t.prototype.setDisabledState=function(t){this.disabled=t,this._cd.markForCheck()},t.prototype.ngOnDestroy=function(){this.timepickerSub.unsubscribe()},t.prototype._renderTime=function(t){if(!qr(t))return this.hours="",this.minutes="",this.seconds="",void(this.meridian=this.meridians[0]);var e=Vr(t),n=e.getHours();this.showMeridian&&(this.meridian=this.meridians[n>=12?1:0],0==(n%=12)&&(n=12)),this.hours=Wr(n),this.minutes=Wr(e.getMinutes()),this.seconds=Wr(e.getUTCSeconds())},t}(),ii=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[ti,Ar,ai]}},t}(),si=s["\u0275crt"]({encapsulation:2,styles:["\n .bs-chevron {\n border-style: solid;\n display: block;\n width: 9px;\n height: 9px;\n position: relative;\n border-width: 3px 0px 0 3px;\n }\n\n .bs-chevron-up {\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg);\n top: 2px;\n }\n\n .bs-chevron-down {\n -webkit-transform: rotate(-135deg);\n transform: rotate(-135deg);\n top: -2px;\n }\n\n .bs-timepicker-field {\n width: 50px;\n }\n "],data:{}});function oi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\xa0\xa0"]))],null,null)}function ui(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeMinutes(r.minuteStep)&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"span",[["class","bs-chevron bs-chevron-up"]],null,null,null,null,null))],null,function(t,e){var n=e.component;t(e,1,0,!n.canIncrementMinutes||!n.isEditable)})}function ci(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0"]))],null,null)}function li(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeSeconds(r.secondsStep)&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"span",[["class","bs-chevron bs-chevron-up"]],null,null,null,null,null))],null,function(t,e){var n=e.component;t(e,1,0,!n.canIncrementSeconds||!n.isEditable)})}function di(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\xa0\xa0"]))],null,null)}function fi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"td",[],null,null,null,null,null))],null,null)}function pi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0:\xa0"]))],null,null)}function hi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[["class","form-group"]],[[2,"has-error",null]],null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,0,"input",[["class","form-control text-center bs-timepicker-field"],["maxlength","2"],["placeholder","MM"],["type","text"]],[[2,"is-invalid",null],[8,"readOnly",0],[8,"disabled",0],[8,"value",0]],[[null,"wheel"],[null,"keydown.ArrowUp"],[null,"keydown.ArrowDown"],[null,"change"]],function(t,e,n){var a=!0,r=t.component;return"wheel"===e&&(r.prevDef(n),a=!1!==r.changeMinutes(r.minuteStep*r.wheelSign(n),"wheel")&&a),"keydown.ArrowUp"===e&&(a=!1!==r.changeMinutes(r.minuteStep,"key")&&a),"keydown.ArrowDown"===e&&(a=!1!==r.changeMinutes(0-r.minuteStep,"key")&&a),"change"===e&&(a=!1!==r.updateMinutes(n.target.value)&&a),a},null,null))],null,function(t,e){var n=e.component;t(e,0,0,n.invalidMinutes),t(e,1,0,n.invalidMinutes,n.readonlyInput,n.disabled,n.minutes)})}function gi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0:\xa0"]))],null,null)}function bi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[["class","form-group"]],[[2,"has-error",null]],null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,0,"input",[["class","form-control text-center bs-timepicker-field"],["maxlength","2"],["placeholder","SS"],["type","text"]],[[2,"is-invalid",null],[8,"readOnly",0],[8,"disabled",0],[8,"value",0]],[[null,"wheel"],[null,"keydown.ArrowUp"],[null,"keydown.ArrowDown"],[null,"change"]],function(t,e,n){var a=!0,r=t.component;return"wheel"===e&&(r.prevDef(n),a=!1!==r.changeSeconds(r.secondsStep*r.wheelSign(n),"wheel")&&a),"keydown.ArrowUp"===e&&(a=!1!==r.changeSeconds(r.secondsStep,"key")&&a),"keydown.ArrowDown"===e&&(a=!1!==r.changeSeconds(0-r.secondsStep,"key")&&a),"change"===e&&(a=!1!==r.updateSeconds(n.target.value)&&a),a},null,null))],null,function(t,e){var n=e.component;t(e,0,0,n.invalidSeconds),t(e,1,0,n.invalidSeconds,n.readonlyInput,n.disabled,n.seconds)})}function mi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\xa0\xa0"]))],null,null)}function yi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-default text-center"],["type","button"]],[[8,"disabled",0],[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.toggleMeridian()&&a),a},null,null)),(t()(),s["\u0275ted"](2,null,[""," "]))],null,function(t,e){var n=e.component;t(e,1,0,!n.isEditable||!n.canToggleMeridian,!n.isEditable||!n.canToggleMeridian),t(e,2,0,n.meridian)})}function vi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\xa0\xa0"]))],null,null)}function _i(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeMinutes(0-r.minuteStep)&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"span",[["class","bs-chevron bs-chevron-down"]],null,null,null,null,null))],null,function(t,e){var n=e.component;t(e,1,0,!n.canDecrementMinutes||!n.isEditable)})}function xi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0"]))],null,null)}function Ti(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeSeconds(0-r.secondsStep)&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"span",[["class","bs-chevron bs-chevron-down"]],null,null,null,null,null))],null,function(t,e){var n=e.component;t(e,1,0,!n.canDecrementSeconds||!n.isEditable)})}function wi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"td",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\xa0\xa0"]))],null,null)}function Si(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"td",[],null,null,null,null,null))],null,null)}function Oi(t){return s["\u0275vid"](2,[(t()(),s["\u0275eld"](0,0,null,null,48,"table",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,47,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,15,"tr",[["class","text-center"]],[[8,"hidden",0]],null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeHours(r.hourStep)&&a),a},null,null)),(t()(),s["\u0275eld"](5,0,null,null,0,"span",[["class","bs-chevron bs-chevron-up"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,oi)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ui)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ci)),s["\u0275did"](11,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,li)),s["\u0275did"](13,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,di)),s["\u0275did"](15,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,fi)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,14,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,1,"td",[["class","form-group"]],[[2,"has-error",null]],null,null,null,null)),(t()(),s["\u0275eld"](20,0,null,null,0,"input",[["class","form-control text-center bs-timepicker-field"],["maxlength","2"],["placeholder","HH"],["type","text"]],[[2,"is-invalid",null],[8,"readOnly",0],[8,"disabled",0],[8,"value",0]],[[null,"wheel"],[null,"keydown.ArrowUp"],[null,"keydown.ArrowDown"],[null,"change"]],function(t,e,n){var a=!0,r=t.component;return"wheel"===e&&(r.prevDef(n),a=!1!==r.changeHours(r.hourStep*r.wheelSign(n),"wheel")&&a),"keydown.ArrowUp"===e&&(a=!1!==r.changeHours(r.hourStep,"key")&&a),"keydown.ArrowDown"===e&&(a=!1!==r.changeHours(0-r.hourStep,"key")&&a),"change"===e&&(a=!1!==r.updateHours(n.target.value)&&a),a},null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,pi)),s["\u0275did"](22,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,hi)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,gi)),s["\u0275did"](26,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,bi)),s["\u0275did"](28,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,mi)),s["\u0275did"](30,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,yi)),s["\u0275did"](32,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](33,0,null,null,15,"tr",[["class","text-center"]],[[8,"hidden",0]],null,null,null,null)),(t()(),s["\u0275eld"](34,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](35,0,null,null,1,"a",[["class","btn btn-link"]],[[2,"disabled",null]],[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=!1!==r.changeHours(0-r.hourStep)&&a),a},null,null)),(t()(),s["\u0275eld"](36,0,null,null,0,"span",[["class","bs-chevron bs-chevron-down"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,vi)),s["\u0275did"](38,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,_i)),s["\u0275did"](40,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,xi)),s["\u0275did"](42,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ti)),s["\u0275did"](44,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,wi)),s["\u0275did"](46,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Si)),s["\u0275did"](48,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,7,0,n.showMinutes),t(e,9,0,n.showMinutes),t(e,11,0,n.showSeconds),t(e,13,0,n.showSeconds),t(e,15,0,n.showMeridian),t(e,17,0,n.showMeridian),t(e,22,0,n.showMinutes),t(e,24,0,n.showMinutes),t(e,26,0,n.showSeconds),t(e,28,0,n.showSeconds),t(e,30,0,n.showMeridian),t(e,32,0,n.showMeridian),t(e,38,0,n.showMinutes),t(e,40,0,n.showMinutes),t(e,42,0,n.showSeconds),t(e,44,0,n.showSeconds),t(e,46,0,n.showMeridian),t(e,48,0,n.showMeridian)},function(t,e){var n=e.component;t(e,2,0,!n.showSpinners),t(e,4,0,!n.canIncrementHours||!n.isEditable),t(e,19,0,n.invalidHours),t(e,20,0,n.invalidHours,n.readonlyInput,n.disabled,n.hours),t(e,33,0,!n.showSpinners),t(e,35,0,!n.canDecrementHours||!n.isEditable)})}var Ii=n("E2fk"),Ci=function(){function t(t){this.http=t}return t.prototype.getLogs=function(){return this.http.get("api/logs/all")},t.prototype.validateDashboardUrl=function(t){return this.http.get("api/grafana/validation/"+t)},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),ki=function(){function t(t){this.logsService=t,this.bsConfig={dateInputFormat:"YYYY-MM-DD",containerClass:"theme-default"},this.prioritys=[{name:"Info",value:"[INF]"},{name:"Warning",value:"[WRN]"},{name:"Error",value:"[ERR]"},{name:"All",value:"All"}],this.priority="All",this.search="",this.startTime=new Date,this.endTime=new Date,this.startTime.setHours(0,0),this.endTime.setHours(23,59)}return t.prototype.ngOnInit=function(){var t=this;this.getInfo(),this.interval=window.setInterval(function(){t.getInfo()},5e3)},t.prototype.ngOnDestroy=function(){clearInterval(this.interval)},t.prototype.getInfo=function(){var t=this;this.logsService.getLogs().subscribe(function(e){t.contentData=e,t.filterLogs()})},t.prototype.abstractfilters=function(){var t,e=this.priority,n=this.search.toLowerCase().replace(/,/g,"");if(this.selectedDate){var a=this.selectedDate.getMonth()+1,r=this.selectedDate.getDate();t=this.selectedDate.getFullYear().toString()+"-"+(a<=9?"0"+a:""+a)+"-"+(r<=9?"0"+r:""+r)}else t="";return{priority:e,key:n,yearMonthDay:t,sTime:60*(this.startTime?this.startTime.getHours():0)+(this.startTime?this.startTime.getMinutes():0),eTime:60*(this.endTime?this.endTime.getHours():23)+(this.endTime?this.endTime.getMinutes():59)}},t.prototype.filterExecutor=function(t,e){return t.filter(function(t){var n,a,r=parseInt(t.stamp.slice(11,13),10),i=parseInt(t.stamp.slice(14,16),10);return n=e.yearMonthDay?e.yearMonthDay:t.stamp,a=60*r+i,t.priority===("All"===e.priority?t.priority:e.priority)&&-1!==t.message.toLowerCase().indexOf(e.key)&&-1!==t.stamp.indexOf(n)&&a>=e.sTime&&a<=e.eTime})},t.prototype.filterLogs=function(){var t=this.abstractfilters();this.clog=this.filterExecutor(this.contentData.clog,t),this.audit_log=this.filterExecutor(this.contentData.audit_log,t)},t.prototype.clearSearchKey=function(){this.search="",this.filterLogs()},t.prototype.clearDate=function(){this.selectedDate=null,this.filterLogs()},t}(),Ni=s["\u0275crt"]({encapsulation:0,styles:[["p[_ngcontent-%COMP%]{font-family:monospace;color:#000}.well[_ngcontent-%COMP%] div[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{display:-webkit-box;display:flex}.well[_ngcontent-%COMP%] div[_ngcontent-%COMP%] p[_ngcontent-%COMP%]:last-child{margin-bottom:0}.well[_ngcontent-%COMP%] .timestamp[_ngcontent-%COMP%]{font-weight:700;flex-shrink:0}.well[_ngcontent-%COMP%] .priority[_ngcontent-%COMP%]{margin-left:.5rem}.well[_ngcontent-%COMP%] .message[_ngcontent-%COMP%]{margin-left:1rem}.well[_ngcontent-%COMP%] .err[_ngcontent-%COMP%]{color:#a94442}.well[_ngcontent-%COMP%] .warn[_ngcontent-%COMP%]{color:#ffc200}.well[_ngcontent-%COMP%] .info[_ngcontent-%COMP%]{color:#2b99a8} timepicker table tbody tr td .bs-timepicker-field{width:3.5rem;font-size:1rem;padding:4px 6px} timepicker table tbody tr td .btn{font-size:1rem}.log-filters[_ngcontent-%COMP%]{margin-bottom:5px;padding:0 30px}.log-filters[_ngcontent-%COMP%] *[_ngcontent-%COMP%]{box-sizing:border-box}.log-filters[_ngcontent-%COMP%] .filter-box[_ngcontent-%COMP%]{margin:0;padding:0 15px 5px 0;display:-webkit-box;display:flex;-webkit-box-pack:start;justify-content:flex-start;-webkit-box-align:center;align-items:center}.log-filters[_ngcontent-%COMP%] .filter-box[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{padding-top:5px;padding-right:5px}@media (max-width:991px){.log-filters[_ngcontent-%COMP%] .time-box[_ngcontent-%COMP%]{margin-top:20px}}@media (min-width:1200px){.log-filters[_ngcontent-%COMP%] .cd-col-4[_ngcontent-%COMP%]{width:28vw}.log-filters[_ngcontent-%COMP%] .cd-col-3[_ngcontent-%COMP%]{width:20vw}.log-filters[_ngcontent-%COMP%] .cd-col-2[_ngcontent-%COMP%]{width:16vw}.log-filters[_ngcontent-%COMP%] .cd-col-1[_ngcontent-%COMP%]{width:14vw}}@media (min-width:1400px){.log-filters[_ngcontent-%COMP%] .cd-col-4[_ngcontent-%COMP%]{width:24vw}.log-filters[_ngcontent-%COMP%] .cd-col-3[_ngcontent-%COMP%]{width:18vw}.log-filters[_ngcontent-%COMP%] .cd-col-2[_ngcontent-%COMP%]{width:14vw}.log-filters[_ngcontent-%COMP%] .cd-col-1[_ngcontent-%COMP%]{width:12vw}}@media (min-width:1600px){.log-filters[_ngcontent-%COMP%] .cd-col-4[_ngcontent-%COMP%]{width:22vw}.log-filters[_ngcontent-%COMP%] .cd-col-3[_ngcontent-%COMP%]{width:16vw}.log-filters[_ngcontent-%COMP%] .cd-col-2[_ngcontent-%COMP%]{width:12vw}.log-filters[_ngcontent-%COMP%] .cd-col-1[_ngcontent-%COMP%]{width:10vw}}@media (min-width:1800px){.log-filters[_ngcontent-%COMP%] .cd-col-3[_ngcontent-%COMP%]{width:14vw}.log-filters[_ngcontent-%COMP%] .cd-col-2[_ngcontent-%COMP%]{width:11vw}.log-filters[_ngcontent-%COMP%] .cd-col-1[_ngcontent-%COMP%]{width:9vw}}"]],data:{}});function Ri(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function Ai(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,"p",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["class","timestamp"]],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",""])),(t()(),s["\u0275eld"](3,0,null,null,2,"span",[],[[8,"className",0]],null,null,null,null)),s["\u0275ppd"](4,1),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","message"]],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit.stamp);var n=s["\u0275inlineInterpolate"](1,"priority ",s["\u0275unv"](e,3,0,t(e,4,0,s["\u0275nov"](e.parent.parent.parent,0),e.context.$implicit.priority)),"");t(e,3,0,n),t(e,5,0,e.context.$implicit.priority),t(e,7,0,e.context.$implicit.message)})}function Di(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ai)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.clog)},null)}function Ei(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["No entries found"]))],null,null)}function Li(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,7,"p",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["class","timestamp"]],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,["",""])),(t()(),s["\u0275eld"](3,0,null,null,2,"span",[],[[8,"className",0]],null,null,null,null)),s["\u0275ppd"](4,1),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","message"]],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit.stamp);var n=s["\u0275inlineInterpolate"](1,"priority ",s["\u0275unv"](e,3,0,t(e,4,0,s["\u0275nov"](e.parent.parent.parent,0),e.context.$implicit.priority)),"");t(e,3,0,n),t(e,5,0,e.context.$implicit.priority),t(e,7,0,e.context.$implicit.message)})}function Pi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Li)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.audit_log)},null)}function Mi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["No entries found"]))],null,null)}function qi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,18,"div",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ri)),s["\u0275did"](2,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),s["\u0275eld"](3,0,null,null,15,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](4,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](5,0,null,0,6,"tab",[["heading","Cluster Logs"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](6,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](7,0,null,null,4,"div",[["class","well"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Di)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ei)),s["\u0275did"](11,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](12,0,null,0,6,"tab",[["heading","Audit Logs"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](13,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](14,0,null,null,4,"div",[["class","well"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Pi)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Mi)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,s["\u0275nov"](e.parent,3)),t(e,6,0,"Cluster Logs"),t(e,9,0,n.clog),t(e,11,0,0===n.contentData.clog.length),t(e,13,0,"Audit Logs"),t(e,16,0,n.audit_log),t(e,18,0,0===n.contentData.audit_log.length)},function(t,e){t(e,3,0,s["\u0275nov"](e,4).clazz),t(e,5,0,s["\u0275nov"](e,6).id,s["\u0275nov"](e,6).active,s["\u0275nov"](e,6).addClass),t(e,12,0,s["\u0275nov"](e,13).id,s["\u0275nov"](e,13).active,s["\u0275nov"](e,13).addClass)})}function ji(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["class","form-control"]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.value),t(e,2,0,e.context.$implicit.value)},function(t,e){t(e,3,0,e.context.$implicit.name)})}function Fi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,65,"div",[["class","row log-filters"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,11,"div",[["class","col-xs-4 col-md-2 cd-col-1 filter-box"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"label",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Priority:"])),(t()(),s["\u0275eld"](4,0,null,null,8,"select",[["class","form-control"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,6).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,6).onTouched()&&a),"ngModelChange"===e&&(a=!1!==(r.priority=n)&&a),"ngModelChange"===e&&(a=!1!==r.filterLogs()&&a),a},null,null)),s["\u0275did"](5,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](6,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](8,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](10,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,ji)),s["\u0275did"](12,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](13,0,null,null,15,"div",[["class","col-xs-4 col-md-3 cd-col-3 filter-box"]],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,null,1,"label",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Keyword:"])),(t()(),s["\u0275eld"](16,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,1,"span",[["class","input-group-addon"]],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,0,"i",[["class","glyphicon glyphicon-search"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,6,"input",[["class","form-control"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"keyup"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,21)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,21).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,21)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,21)._compositionEnd(n.target.value)&&a),"ngModelChange"===e&&(a=!1!==(r.search=n)&&a),"keyup"===e&&(a=!1!==r.filterLogs()&&a),a},null,null)),s["\u0275did"](20,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](21,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](23,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](25,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](26,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](27,0,null,null,1,"button",[["class","btn btn-default clear-input tc_clearInputBtn"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.clearSearchKey()&&a),a},null,null)),(t()(),s["\u0275eld"](28,0,null,null,0,"i",[["class","icon-prepend fa fa-remove"]],null,null,null,null,null)),(t()(),s["\u0275eld"](29,0,null,null,16,"div",[["class","col-xs-4 col-md-3 cd-col-2 filter-box"]],null,null,null,null,null)),(t()(),s["\u0275eld"](30,0,null,null,1,"label",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Date:"])),(t()(),s["\u0275eld"](32,0,null,null,13,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](33,16777216,null,null,9,"input",[["bsDatepicker",""],["class","form-control"],["placeholder","Datepicker"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"],[null,"keyup.esc"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,35)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,35).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,35)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,35)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,37).onChange(n)&&a),"keyup.esc"===e&&(a=!1!==s["\u0275nov"](t,37).hide()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,37).onBlur()&&a),"ngModelChange"===e&&(a=!1!==(r.selectedDate=n)&&a),"ngModelChange"===e&&(a=!1!==r.filterLogs()&&a),a},null,null)),s["\u0275did"](34,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](35,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](36,737280,null,0,Nr.c,[Nr.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a],{bsConfig:[0,"bsConfig"]},null),s["\u0275did"](37,16384,null,0,Nr.f,[Nr.c,Nr.j,s.Renderer2,s.ElementRef,s.ChangeDetectorRef],null,null),s["\u0275prd"](1024,null,Te.o,function(t){return[t]},[Nr.f]),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Nr.f]),s["\u0275did"](40,671744,null,0,Te.u,[[8,null],[6,Te.o],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](42,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](43,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](44,0,null,null,1,"button",[["class","btn btn-default clear-input tc_clearInputBtn"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.clearDate()&&a),a},null,null)),(t()(),s["\u0275eld"](45,0,null,null,0,"i",[["class","icon-prepend fa fa-remove"]],null,null,null,null,null)),(t()(),s["\u0275eld"](46,0,null,null,0,"div",[["class","clearfix visible-xs-block"]],null,null,null,null,null)),(t()(),s["\u0275eld"](47,0,null,null,18,"div",[["class","col-xs-8 col-md-4 cd-col-4 filter-box time-box"]],null,null,null,null,null)),(t()(),s["\u0275eld"](48,0,null,null,1,"label",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Time range:"])),(t()(),s["\u0275eld"](50,0,null,null,6,"timepicker",[],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"]],function(t,e,n){var a=!0,r=t.component;return"ngModelChange"===e&&(a=!1!==(r.startTime=n)&&a),"ngModelChange"===e&&(a=!1!==r.filterLogs()&&a),a},Oi,si)),s["\u0275prd"](512,null,ai,ai,[]),s["\u0275did"](52,704512,null,0,ri,[ti,s.ChangeDetectorRef,ai,Ar],{minuteStep:[0,"minuteStep"],showSpinners:[1,"showSpinners"],showMeridian:[2,"showMeridian"]},null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[ri]),s["\u0275did"](54,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](56,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](57,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xa0\u2014\xa0"])),(t()(),s["\u0275eld"](59,0,null,null,6,"timepicker",[],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"]],function(t,e,n){var a=!0,r=t.component;return"ngModelChange"===e&&(a=!1!==(r.endTime=n)&&a),"ngModelChange"===e&&(a=!1!==r.filterLogs()&&a),a},Oi,si)),s["\u0275prd"](512,null,ai,ai,[]),s["\u0275did"](61,704512,null,0,ri,[ti,s.ChangeDetectorRef,ai,Ar],{minuteStep:[0,"minuteStep"],showSpinners:[1,"showSpinners"],showMeridian:[2,"showMeridian"]},null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[ri]),s["\u0275did"](63,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](65,16384,null,0,Te.r,[[4,Te.q]],null,null)],function(t,e){var n=e.component;t(e,8,0,n.priority),t(e,12,0,n.prioritys),t(e,23,0,n.search),t(e,36,0,n.bsConfig),t(e,40,0,n.selectedDate),t(e,52,0,1,n.showSpinners,!1),t(e,54,0,n.startTime),t(e,61,0,1,n.showSpinners,!1),t(e,63,0,n.endTime)},function(t,e){t(e,4,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending),t(e,19,0,s["\u0275nov"](e,25).ngClassUntouched,s["\u0275nov"](e,25).ngClassTouched,s["\u0275nov"](e,25).ngClassPristine,s["\u0275nov"](e,25).ngClassDirty,s["\u0275nov"](e,25).ngClassValid,s["\u0275nov"](e,25).ngClassInvalid,s["\u0275nov"](e,25).ngClassPending),t(e,33,0,s["\u0275nov"](e,42).ngClassUntouched,s["\u0275nov"](e,42).ngClassTouched,s["\u0275nov"](e,42).ngClassPristine,s["\u0275nov"](e,42).ngClassDirty,s["\u0275nov"](e,42).ngClassValid,s["\u0275nov"](e,42).ngClassInvalid,s["\u0275nov"](e,42).ngClassPending),t(e,50,0,s["\u0275nov"](e,56).ngClassUntouched,s["\u0275nov"](e,56).ngClassTouched,s["\u0275nov"](e,56).ngClassPristine,s["\u0275nov"](e,56).ngClassDirty,s["\u0275nov"](e,56).ngClassValid,s["\u0275nov"](e,56).ngClassInvalid,s["\u0275nov"](e,56).ngClassPending),t(e,59,0,s["\u0275nov"](e,65).ngClassUntouched,s["\u0275nov"](e,65).ngClassTouched,s["\u0275nov"](e,65).ngClassPristine,s["\u0275nov"](e,65).ngClassDirty,s["\u0275nov"](e,65).ngClassValid,s["\u0275nov"](e,65).ngClassInvalid,s["\u0275nov"](e,65).ngClassPending)})}function zi(t){return s["\u0275vid"](0,[s["\u0275pid"](0,Ii.a,[]),(t()(),s["\u0275and"](16777216,null,null,1,null,qi)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,[["logFiltersTpl",2]],null,0,null,Fi))],function(t,e){t(e,2,0,e.component.contentData)},null)}function Gi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-logs",[],null,null,null,zi,Ni)),s["\u0275did"](1,245760,null,0,ki,[Ci],null,null)],function(t,e){t(e,1,0)},null)}var Yi,Vi=s["\u0275ccf"]("cd-logs",ki,Gi,{},{},[]),Hi=n("EgGo");!function(t){t.add="fa fa-plus",t.addCircle="fa fa-plus-circle",t.minusCircle="fa fa-minus-circle",t.edit="fa fa-pencil",t.destroy="fa fa-times",t.destroyCircle="fa fa-times-circle",t.exchange="fa fa-exchange",t.copy="fa fa-copy",t.clipboard="fa fa-clipboard",t.flatten="fa-chain-broken",t.trash="fa fa-trash-o",t.lock="fa fa-lock",t.unlock="fa fa-unlock",t.clone="fa fa-clone",t.undo="fa fa-undo",t.search="fa fa-search",t.start="fa fa-play",t.stop="fa fa-stop",t.analyse="fa fa-stethoscope",t.deepCheck="fa fa-cog",t.reweight="fa-balance-scale",t.left="fa fa-arrow-left",t.right="fa fa-arrow-right",t.down="fa fa-arrow-down",t.erase="fa fa-eraser",t.user="fa fa-user",t.share="fa fa-share-alt",t.key="fa fa-key-modern",t.warning="fa fa-exclamation-triangle",t.info="fa fa-info",t.infoCircle="fa fa-info-circle",t.questionCircle="fa fa-question-circle-o",t.check="fa fa-check",t.show="fa fa-eye",t.paragraph="fa fa-paragraph",t.terminal="fa fa-terminal",t.magic="fa fa-magic",t.hourglass="fa fa-hourglass-o",t.filledHourglass="fa fa-hourglass",t.table="fa fa-table",t.spinner="fa spinner",t.refresh="fa fa-refresh",t.bullseye="fa fa-bullseye",t.disk="fa fa-hdd-o",t.server="fa fa-server",t.filter="fa fa-filter",t.lineChart="fa fa-line-chart",t.signOut="fa fa-sign-out",t.health="fa fa-heartbeat",t.circle="fa fa-circle",t.bell="fa fa-bell",t.tag="fa fa-tag",t.leftArrow="fa fa-angle-left",t.rightArrow="fa fa-angle-right",t.leftArrowDouble="fa fa-angle-double-left",t.rightArrowDouble="fa fa-angle-double-right",t.flag="fa fa-flag",t.width="fa fa-fw",t.large="fa fa-lg",t.large2x="fa fa-2x",t.large3x="fa fa-3x",t.stack="fa fa-stack",t.stack1x="fa fa-stack-1x",t.stack2x="fa fa-stack-2x",t.pulse="fa fa-pulse",t.spin="fa fa-spin",t.inverse="fa fa-inverse"}(Yi||(Yi={}));var Bi=n("67Y/"),Ui=function(){function t(t,e){this.http=t,this.settingsService=e,this.baseURL="api/prometheus",this.settingsKey={alertmanager:"api/settings/alertmanager-api-host",prometheus:"api/settings/prometheus-api-host"}}return t.prototype.ifAlertmanagerConfigured=function(t,e){this.settingsService.ifSettingConfigured(this.settingsKey.alertmanager,t,e)},t.prototype.disableAlertmanagerConfig=function(){this.settingsService.disableSetting(this.settingsKey.alertmanager)},t.prototype.ifPrometheusConfigured=function(t,e){this.settingsService.ifSettingConfigured(this.settingsKey.prometheus,t,e)},t.prototype.disablePrometheusConfig=function(){this.settingsService.disableSetting(this.settingsKey.prometheus)},t.prototype.getAlerts=function(t){return void 0===t&&(t={}),this.http.get(this.baseURL,{params:t})},t.prototype.getSilences=function(t){return void 0===t&&(t={}),this.http.get(this.baseURL+"/silences",{params:t})},t.prototype.getRules=function(t){void 0===t&&(t="all");var e,n=this.http.get(this.baseURL+"/rules");switch(t){case"alerting":case"rewrites":e=t,n=n.pipe(Object(Bi.a)(function(t){return t.groups=t.groups.map(function(t){return t.rules=t.rules.filter(function(t){return t.type===e}),t}),t}))}return n},t.prototype.setSilence=function(t){return this.http.post(this.baseURL+"/silence",t,{observe:"response"})},t.prototype.expireSilence=function(t){return this.http.delete(this.baseURL+"/silence/"+t,{observe:"response"})},t.prototype.getNotifications=function(t){return this.http.get(this.baseURL+"/notifications?from="+(t&&t.id?t.id:"last"))},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c),s.inject(ze.a))},token:t,providedIn:Nt.a}),t}(),Wi=n("G1I9"),Ki=function(){function t(t){this.notificationService=t}return t.prototype.sendNotifications=function(t){var e=this;t.forEach(function(t){return e.notificationService.show(t)})},t.prototype.convertToCustomAlerts=function(t){var e=this;return ft.uniqWith(t.map(function(t){return{status:ft.isObject(t.status)?t.status.state:e.getPrometheusNotificationStatus(t),name:t.labels.alertname,url:t.generatorURL,summary:t.annotations.summary,fingerprint:ft.isObject(t.status)&&t.fingerprint}}),ft.isEqual)},t.prototype.getPrometheusNotificationStatus=function(t){var e=t.status;return"firing"===e?"active":e},t.prototype.convertAlertToNotification=function(t){return new Wi.b(this.formatType(t.status),t.name+" ("+t.status+")",this.appendSourceLink(t,t.summary),void 0,"Prometheus")},t.prototype.formatType=function(t){return Xn.a[ft.findKey({error:["firing","active"],info:["suppressed","unprocessed"],success:["resolved"]},function(e){return e.includes(t)})]},t.prototype.appendSourceLink=function(t,e){return e+' <a href="'+t.url+'" target="_blank"><i class="fa fa-line-chart"></i></a>'},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(Jn.a))},token:t,providedIn:"root"}),t}(),$i=function(){function t(t,e){this.alertFormatter=t,this.prometheusService=e,this.canAlertsBeNotified=!1,this.alerts=[],this.rules=[]}return t.prototype.getAlerts=function(){var t=this;this.prometheusService.ifAlertmanagerConfigured(function(){t.prometheusService.getAlerts().subscribe(function(e){return t.handleAlerts(e)},function(e){[404,504].includes(e.status)&&t.prometheusService.disableAlertmanagerConfig()})})},t.prototype.getRules=function(){var t=this;this.prometheusService.ifPrometheusConfigured(function(){t.prometheusService.getRules("alerting").subscribe(function(e){t.rules=e.groups.reduce(function(t,e){return t.concat(e.rules.map(function(t){return t.group=e.name,t}))},[])})})},t.prototype.refresh=function(){this.getAlerts(),this.getRules()},t.prototype.handleAlerts=function(t){this.canAlertsBeNotified&&this.notifyOnAlertChanges(t,this.alerts),this.alerts=t,this.canAlertsBeNotified=!0},t.prototype.notifyOnAlertChanges=function(t,e){var n=this,a=this.getChangedAlerts(this.alertFormatter.convertToCustomAlerts(t),this.alertFormatter.convertToCustomAlerts(e)).map(function(t){return n.alertFormatter.convertAlertToNotification(t)});this.alertFormatter.sendNotifications(a)},t.prototype.getChangedAlerts=function(t,e){return ft.differenceWith(t,e,ft.isEqual).concat(this.getVanishedAlerts(t,e))},t.prototype.getVanishedAlerts=function(t,e){return ft.differenceWith(e,t,function(t,e){return t.fingerprint===e.fingerprint}).map(function(t){return t.status="resolved",t})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(Ki),s.inject(Ui))},token:t,providedIn:"root"}),t}(),Zi=new Hi.a("silence"),Xi=function(){function t(t,e,n,a,r){var i=this;this.authStorageService=t,this.prometheusAlertService=e,this.urlBuilder=n,this.i18n=a,this.cdDatePipe=r,this.selection=new He.a,this.icons=Yi,this.customCss={"label label-danger":"active","label label-warning":"unprocessed","label label-info":"suppressed"},this.permission=this.authStorageService.getPermissions().prometheus,this.tableActions=[{permission:"create",canBePrimary:function(t){return t.hasSingleSelection},disable:function(t){return!t.hasSingleSelection||t.first().cdExecuting},icon:Yi.add,routerLink:function(){return"/monitoring"+i.urlBuilder.getCreateFrom(i.selection.first().fingerprint)},name:this.i18n("Create Silence")}]}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"labels.alertname",flexGrow:2},{name:this.i18n("Job"),prop:"labels.job",flexGrow:2},{name:this.i18n("Severity"),prop:"labels.severity"},{name:this.i18n("State"),prop:"status.state",cellTransformation:cn.a.classAdding},{name:this.i18n("Started"),prop:"startsAt",pipe:this.cdDatePipe},{name:this.i18n("URL"),prop:"generatorURL",sortable:!1,cellTemplate:this.externalLinkTpl}]},t.prototype.updateSelection=function(t){this.selection=t},t}(),Ji=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Qi(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"tabset",[["cdTableDetail",""]],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](5,638976,null,0,Sn.a,[On.a],{data:[0,"data"],autoReload:[1,"autoReload"],renderObjects:[2,"renderObjects"],appendParentKey:[3,"appendParentKey"],hideEmpty:[4,"hideEmpty"],customCss:[5,"customCss"]},null)],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,5,0,n.selection.first(),!1,!0,!1,!0,n.customCss)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass)})}function ts(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,0,"i",[["class","fa fa-line-chart"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" Source"]))],null,function(t,e){t(e,0,0,e.context.value)})}function es(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{externalLinkTpl:0}),(t()(),s["\u0275eld"](1,0,null,null,5,"cd-table",[["identifier","fingerprint"],["selectionType","single"]],null,[[null,"updateSelection"]],function(t,e,n){var a=!0;return"updateSelection"===e&&(a=!1!==t.component.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](2,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],identifier:[2,"identifier"],forceIdentifier:[3,"forceIdentifier"],selectionType:[4,"selectionType"],customCss:[5,"customCss"]},{updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](3,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,xn.b,xn.a)),s["\u0275did"](4,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275and"](16777216,null,2,1,null,Qi)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,[[1,2],["externalLinkTpl",2]],null,0,null,ts))],function(t,e){var n=e.component;t(e,2,0,n.prometheusAlertService.alerts,n.columns,"fingerprint",!0,"single",n.customCss),t(e,4,0,n.permission,n.selection,n.tableActions),t(e,6,0,n.selection.hasSingleSelection)},null)}var ns=n("TZo1"),as=n("9Kw/"),rs=n("wd/R"),is=function(){function t(){}return t.prototype.transform=function(t,e){return void 0===e&&(e=!1),e?rs(t).fromNow():this._forHumans(t)},t.prototype._forHumans=function(t){for(var e=[[""+Math.floor(t/31536e3),"years"],[""+Math.floor(t%31536e3/86400),"days"],[""+Math.floor(t%86400/3600),"hours"],[""+Math.floor(t%3600/60),"minutes"],[""+Math.floor(t%60),"seconds"]],n="",a=0,r=e.length;a<r;a++)"0"!==e[a][0]&&(n+=" "+e[a][0]+" "+("1"===e[a][0]?e[a][1].substr(0,e[a][1].length-1):e[a][1]));return n.trim()||"1 second"},t}(),ss=function(){function t(t){this.i18n=t,this.hideKeys=["alerts","type"]}return t.prototype.ngOnInit=function(){this.columns=[{prop:"name",name:this.i18n("Name")},{prop:"labels.severity",name:this.i18n("Severity")},{prop:"group",name:this.i18n("Group")},{prop:"duration",name:this.i18n("Duration"),pipe:new is},{prop:"query",name:this.i18n("Query"),isHidden:!0},{prop:"annotations.description",name:this.i18n("Description")}]},t.prototype.selectionUpdated=function(t){this.selectedRule=t.first()},t}(),os=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function us(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](1,638976,null,0,Sn.a,[On.a],{data:[0,"data"],renderObjects:[1,"renderObjects"],hideKeys:[2,"hideKeys"]},null)],function(t,e){var n=e.component;t(e,1,0,n.selectedRule,!0,n.hideKeys)},null)}function cs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-table",[],null,[[null,"updateSelection"]],function(t,e,n){var a=!0;return"updateSelection"===e&&(a=!1!==t.component.selectionUpdated(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](1,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],selectionType:[2,"selectionType"]},{updateSelection:"updateSelection"}),(t()(),s["\u0275and"](16777216,null,null,1,null,us)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.data,n.columns,"single"),t(e,3,0,n.selectedRule)},null)}var ls=n("y9jh"),ds=n("6blF"),fs=new Hi.a("monitoring/silence"),ps=function(){function t(t,e,n,a,r,i,s,o,u){this.authStorageService=t,this.i18n=e,this.cdDatePipe=n,this.prometheusService=a,this.modalService=r,this.notificationService=i,this.urlBuilder=s,this.actionLabels=o,this.succeededLabels=u,this.silences=[],this.selection=new He.a,this.customCss={"label label-danger":"active","label label-warning":"pending","label label-default":"expired"},this.sorts=[{prop:"endsAt",dir:ls.SortDirection.desc}],this.permission=this.authStorageService.getPermissions().prometheus}return t.prototype.ngOnInit=function(){var t=this,e=function(t){return t.first()&&"expired"===t.first().status.state};this.tableActions=[{permission:"create",icon:Yi.add,routerLink:function(){return t.urlBuilder.getCreate()},preserveFragment:!0,canBePrimary:function(t){return!t.hasSingleSelection},name:this.actionLabels.CREATE},{permission:"create",canBePrimary:function(t){return t.hasSingleSelection&&e(t)},disable:function(t){return!t.hasSingleSelection||t.first().cdExecuting||t.first().cdExecuting&&e(t)||!e(t)},icon:Yi.copy,routerLink:function(){return t.urlBuilder.getRecreate(t.selection.first().id)},preserveFragment:!0,name:this.actionLabels.RECREATE},{permission:"update",icon:Yi.edit,canBePrimary:function(t){return t.hasSingleSelection&&!e(t)},disable:function(t){return!t.hasSingleSelection||t.first().cdExecuting||t.first().cdExecuting&&!e(t)||e(t)},routerLink:function(){return t.urlBuilder.getEdit(t.selection.first().id)},preserveFragment:!0,name:this.actionLabels.EDIT},{permission:"delete",icon:Yi.trash,canBePrimary:function(t){return t.hasSingleSelection&&!e(t)},disable:function(t){return!t.hasSingleSelection||t.first().cdExecuting||e(t)},click:function(){return t.expireSilence()},name:this.actionLabels.EXPIRE}],this.columns=[{name:this.i18n("ID"),prop:"id",flexGrow:3},{name:this.i18n("Created by"),prop:"createdBy",flexGrow:2},{name:this.i18n("Started"),prop:"startsAt",pipe:this.cdDatePipe},{name:this.i18n("Updated"),prop:"updatedAt",pipe:this.cdDatePipe},{name:this.i18n("Ends"),prop:"endsAt",pipe:this.cdDatePipe},{name:this.i18n("Status"),prop:"status.state",cellTransformation:cn.a.classAdding}]},t.prototype.refresh=function(){var t=this;this.prometheusService.ifAlertmanagerConfigured(function(){t.prometheusService.getSilences().subscribe(function(e){t.silences=e},function(){t.prometheusService.disableAlertmanagerConfig()})})},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.expireSilence=function(){var t=this,e=this.selection.first().id,n=this.i18n("Silence");this.modalRef=this.modalService.show($n.a,{initialState:{itemDescription:n,itemNames:[e],actionDescription:this.actionLabels.EXPIRE,submitActionObservable:function(){return new ds.a(function(a){t.prometheusService.expireSilence(e).subscribe(function(){t.notificationService.show(Xn.a.success,t.succeededLabels.EXPIRED+" "+n+" "+e,void 0,void 0,"Prometheus")},function(t){t.application="Prometheus",a.error(t)},function(){a.complete(),t.refresh()})})}}})},t}(),hs=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function gs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"tabset",[["cdTableDetail",""]],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](5,638976,null,0,Sn.a,[On.a],{data:[0,"data"],autoReload:[1,"autoReload"],renderObjects:[2,"renderObjects"],appendParentKey:[3,"appendParentKey"],hideEmpty:[4,"hideEmpty"],customCss:[5,"customCss"]},null)],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,5,0,n.selection.first(),!1,!0,!1,!0,n.customCss)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass)})}function bs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-table",[["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(t,e,n){var a=!0,r=t.component;return"fetchData"===e&&(a=!1!==r.refresh()&&a),"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](1,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],sorts:[2,"sorts"],forceIdentifier:[3,"forceIdentifier"],selectionType:[4,"selectionType"],customCss:[5,"customCss"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](2,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,xn.b,xn.a)),s["\u0275did"](3,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275and"](16777216,null,2,1,null,gs)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.silences,n.columns,n.sorts,!0,"single",n.customCss),t(e,3,0,n.permission,n.selection,n.tableActions),t(e,5,0,n.selection.hasSingleSelection)},null)}var ms=function(){function t(t,e,n,a,r,i){this.prometheusAlertService=t,this.prometheusService=e,this.route=n,this.router=a,this.summaryService=r,this.cephReleaseNamePipe=i,this.isPrometheusConfigured=!1,this.isAlertmanagerConfigured=!1,this.docsUrl=""}return t.prototype.ngOnInit=function(){var t=this;this.prometheusService.ifAlertmanagerConfigured(function(){t.isAlertmanagerConfigured=!0}),this.prometheusService.ifPrometheusConfigured(function(){t.isPrometheusConfigured=!0});var e=this.summaryService.subscribe(function(n){if(n){var a=t.cephReleaseNamePipe.transform(n.version);t.docsUrl="https://docs.ceph.com/docs/"+a+"/mgr/dashboard/#enabling-prometheus-alerting",setTimeout(function(){e.unsubscribe()},0)}});if(this.route.snapshot.fragment){var n=this.tabs.tabs.find(function(e){return e.elementRef.nativeElement.id===t.route.snapshot.fragment});n&&(n.active=!0),this.router.navigate([],{fragment:this.route.snapshot.fragment})}},t.prototype.setFragment=function(t){this.router.navigate([],{fragment:t.id})},t}(),ys=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function vs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-active-alert-list",[],null,null,null,es,Ji)),s["\u0275prd"](256,null,Hi.a,Zi,[]),s["\u0275did"](2,114688,null,0,Xi,[l.a,$i,Hi.a,xt.a,On.a],null,null)],function(t,e){t(e,2,0)},null)}function _s(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-info-panel",[],null,null,null,ns.b,ns.a)),s["\u0275did"](1,49152,null,0,as.a,[xt.a],null,null),(t()(),s["\u0275ted"](-1,0,["To see all active Prometheus alerts, please provide the URL to the API of Prometheus' Alertmanager as described in the "])),(t()(),s["\u0275eld"](3,0,null,0,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["documentation"])),(t()(),s["\u0275ted"](-1,0,["."]))],null,function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function xs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-rules-list",[],null,null,null,cs,os)),s["\u0275did"](1,114688,null,0,ss,[xt.a],{data:[0,"data"]},null)],function(t,e){t(e,1,0,e.component.prometheusAlertService.rules)},null)}function Ts(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-info-panel",[],null,null,null,ns.b,ns.a)),s["\u0275did"](1,49152,null,0,as.a,[xt.a],null,null),(t()(),s["\u0275ted"](-1,0,["To see all configured Prometheus alerts, please provide the URL to the API of Prometheus as described in the "])),(t()(),s["\u0275eld"](3,0,null,0,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["documentation"])),(t()(),s["\u0275ted"](-1,0,["."]))],null,function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function ws(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-silences-list",[],null,null,null,bs,hs)),s["\u0275prd"](256,null,Hi.a,fs,[]),s["\u0275did"](2,114688,null,0,ps,[l.a,xt.a,On.a,Ui,pa.b,Jn.a,Hi.a,Zn.b,Zn.d],null,null)],function(t,e){t(e,2,0)},null)}function Ss(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"cd-info-panel",[],null,null,null,ns.b,ns.a)),s["\u0275did"](1,49152,null,0,as.a,[xt.a],null,null),(t()(),s["\u0275ted"](-1,0,["To enable Silences, please provide the URL to the API of the Prometheus' Alertmanager as described in the "])),(t()(),s["\u0275eld"](3,0,null,0,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["documentation"])),(t()(),s["\u0275ted"](-1,0,["."]))],null,function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function Os(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{tabs:0}),(t()(),s["\u0275eld"](1,0,null,null,19,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](2,180224,[[1,4],["tabs",4]],0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](3,0,null,0,5,"tab",[["heading","Active Alerts"],["id","active-alerts"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(t,e,n){var a=!0;return"selectTab"===e&&(a=!1!==t.component.setFragment(n)&&a),a},null,null)),s["\u0275did"](4,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"],id:[1,"id"]},{selectTab:"selectTab"}),(t()(),s["\u0275and"](16777216,null,null,1,null,vs)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,_s)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](9,0,null,0,5,"tab",[["heading","All Alerts"],["id","all-alerts"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(t,e,n){var a=!0;return"selectTab"===e&&(a=!1!==t.component.setFragment(n)&&a),a},null,null)),s["\u0275did"](10,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"],id:[1,"id"]},{selectTab:"selectTab"}),(t()(),s["\u0275and"](16777216,null,null,1,null,xs)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ts)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](15,0,null,0,5,"tab",[["heading","Silences"],["id","silences"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"]],function(t,e,n){var a=!0;return"selectTab"===e&&(a=!1!==t.component.setFragment(n)&&a),a},null,null)),s["\u0275did"](16,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"],id:[1,"id"]},{selectTab:"selectTab"}),(t()(),s["\u0275and"](16777216,null,null,1,null,ws)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ss)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,4,0,"Active Alerts","active-alerts"),t(e,6,0,n.isAlertmanagerConfigured),t(e,8,0,!n.isAlertmanagerConfigured),t(e,10,0,"All Alerts","all-alerts"),t(e,12,0,n.isPrometheusConfigured),t(e,14,0,!n.isPrometheusConfigured),t(e,16,0,"Silences","silences"),t(e,18,0,n.isAlertmanagerConfigured),t(e,20,0,!n.isAlertmanagerConfigured)},function(t,e){t(e,1,0,s["\u0275nov"](e,2).clazz),t(e,3,0,s["\u0275nov"](e,4).id,s["\u0275nov"](e,4).active,s["\u0275nov"](e,4).addClass),t(e,9,0,s["\u0275nov"](e,10).id,s["\u0275nov"](e,10).active,s["\u0275nov"](e,10).addClass),t(e,15,0,s["\u0275nov"](e,16).id,s["\u0275nov"](e,16).active,s["\u0275nov"](e,16).addClass)})}function Is(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-monitoring-list",[],null,null,null,Os,ys)),s["\u0275did"](1,114688,null,0,ms,[$i,Ui,tt.a,tt.l,je.a,Ge.a],null,null)],function(t,e){t(e,1,0)},null)}var Cs=s["\u0275ccf"]("cd-monitoring-list",ms,Is,{},{},[]),ks=n("4HWh"),Ns=n("p4Cf"),Rs=n("8xTl"),As=function(){function t(t){this.i18n=t,this.valueAttributePath={alertname:"name",instance:"alerts.0.labels.instance",job:"alerts.0.labels.job",severity:"labels.severity"}}return t.prototype.singleMatch=function(t,e){return this.multiMatch([t],e)},t.prototype.multiMatch=function(t,e){var n=this;if(!t.some(function(t){return t.isRegex}))return t.forEach(function(t){e=n.getMatchedRules(t,e)}),this.describeMatch(e)},t.prototype.getMatchedRules=function(t,e){var n=this.getAttributePath(t.name);return e.filter(function(e){return ft.get(e,n)===t.value})},t.prototype.describeMatch=function(t){var e=0;return t.forEach(function(t){return e+=t.alerts.length}),{status:this.getMatchText(t.length,e),cssClass:e?"has-success":"has-warning"}},t.prototype.getAttributePath=function(t){return this.valueAttributePath[t]},t.prototype.getMatchText=function(t,e){var n={noRule:this.i18n("Your matcher seems to match no currently defined rule or active alert."),noAlerts:this.i18n("no active alerts"),alert:this.i18n("1 active alert"),alerts:this.i18n("{{n}} active alerts",{n:e}),rule:this.i18n("Matches 1 rule"),rules:this.i18n("Matches {{n}} rules",{n:t})};return t?this.i18n("{{rules}} with {{alerts}}.",{rules:t>1?n.rules:n.rule,alerts:e?e>1?n.alerts:n.alert:n.noAlerts}):n.noRule},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(xt.a))},token:t,providedIn:"root"}),t}(),Ds=function(){function t(){}return t.prototype.calculateDuration=function(t,e){var n=+t,a=+e,r=this.getDuration(Math.abs(n-a));return n>a?"-"+r:r},t.prototype.getDuration=function(t){var e=new Date(t),n=e.getUTCHours(),a=e.getUTCMinutes(),r=function(t,e){return t?t+e:t};return[r(Math.floor(t/864e5),"d"),r(n,"h"),r(a,"m")].filter(function(t){return t}).join(" ")},t.prototype.calculateDate=function(t,e,n){var a=+t;if(!ft.isNaN(a)){var r=this.getDurationMs(e)*(n?-1:1);return new Date(a+r)}},t.prototype.getDurationMs=function(t){return 6e4*(60*(24*this.getNumbersFromString(t,"d")+this.getNumbersFromString(t,"h"))+this.getNumbersFromString(t,"m"))},t.prototype.getNumbersFromString=function(t,e){var n=t.match(new RegExp("[0-9 ]+"+e,"i"));return n?parseInt(n,10):0},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t},token:t,providedIn:"root"}),t}(),Es=function(){function t(t,e,n){this.formBuilder=t,this.silenceMatcher=e,this.bsModalRef=n,this.submitAction=new s.EventEmitter,this.editMode=!1,this.nameAttributes=["alertname","instance","job","severity"],this.possibleValues=[],this.matcherMatch=void 0,this.createForm(),this.subscribeToChanges()}return t.prototype.createForm=function(){this.form=this.formBuilder.group({name:[null,[Te.A.required]],value:[{value:null,disabled:!0},[Te.A.required]],isRegex:new Te.i(!1)})},t.prototype.subscribeToChanges=function(){var t=this;this.form.get("name").valueChanges.subscribe(function(e){null!==e?(t.setPossibleValues(e),t.form.get("value").enable()):t.form.get("value").disable()}),this.form.get("value").valueChanges.subscribe(function(e){var n=t.form.value;n.value=e,t.matcherMatch=t.silenceMatcher.singleMatch(n,t.rules)})},t.prototype.setPossibleValues=function(t){var e=this;this.possibleValues=ft.sortedUniq(this.rules.map(function(n){return ft.get(n,e.silenceMatcher.getAttributePath(t))}).filter(function(t){return t}))},t.prototype.preFillControls=function(t){this.form.setValue(t)},t.prototype.onSubmit=function(){this.submitAction.emit(this.form.value),this.bsModalRef.hide()},t}(),Ls=function(){function t(t,e,n,a,r,i,s,o,u,c,l,d){this.i18n=t,this.router=e,this.authStorageService=n,this.formBuilder=a,this.prometheusService=r,this.notificationService=i,this.route=s,this.timeDiff=o,this.bsModalService=u,this.silenceMatcher=c,this.actionLabels=l,this.succeededLabels=d,this.icons=Yi,this.bsConfig={dateInputFormat:"YYYY-MM-DDT HH:mm"},this.recreate=!1,this.edit=!1,this.resource=this.i18n("silence"),this.matchers=[],this.matcherMatch=void 0,this.matcherConfig=[{tooltip:this.i18n("Attribute name"),icon:this.icons.paragraph,attribute:"name"},{tooltip:this.i18n("Value"),icon:this.icons.terminal,attribute:"value"},{tooltip:this.i18n("Regular expression"),icon:this.icons.magic,attribute:"isRegex"}],this.init()}return t.prototype.init=function(){this.chooseMode(),this.authenticate(),this.createForm(),this.setupDates(),this.getData()},t.prototype.chooseMode=function(){this.edit=this.router.url.startsWith("/monitoring/silence/edit"),this.recreate=this.router.url.startsWith("/monitoring/silence/recreate"),this.action=this.edit?this.actionLabels.EDIT:this.recreate?this.actionLabels.RECREATE:this.actionLabels.CREATE},t.prototype.authenticate=function(){this.permission=this.authStorageService.getPermissions().prometheus,this.permission.read&&(this.edit?this.permission.update:this.permission.create)||this.router.navigate(["/404"])},t.prototype.createForm=function(){var t=this;this.form=this.formBuilder.group({startsAt:[null,[Te.A.required]],duration:["2h",[Te.A.min(1)]],endsAt:[null,[Te.A.required]],createdBy:[this.authStorageService.getUsername(),[Te.A.required]],comment:[null,[Te.A.required]]},{validators:aa.a.custom("matcherRequired",function(){return 0===t.matchers.length})})},t.prototype.setupDates=function(){var t=new Date;t.setSeconds(0,0),this.form.silentSet("startsAt",t),this.updateDate(),this.subscribeDateChanges()},t.prototype.updateDate=function(t){var e=this.timeDiff.calculateDate(this.form.getValue(t?"endsAt":"startsAt"),this.form.getValue("duration"),t);e&&this.form.silentSet(t?"startsAt":"endsAt",e)},t.prototype.subscribeDateChanges=function(){var t=this;this.form.get("startsAt").valueChanges.subscribe(function(){t.onDateChange()}),this.form.get("duration").valueChanges.subscribe(function(){t.updateDate()}),this.form.get("endsAt").valueChanges.subscribe(function(){t.onDateChange(!0)})},t.prototype.onDateChange=function(t){this.form.getValue("startsAt")<this.form.getValue("endsAt")?this.updateDuration():this.updateDate(t)},t.prototype.updateDuration=function(){this.form.silentSet("duration",this.timeDiff.calculateDuration(this.form.getValue("startsAt"),this.form.getValue("endsAt")))},t.prototype.getData=function(){this.getRules(),this.getModeSpecificData()},t.prototype.getRules=function(){var t=this;this.prometheusService.ifPrometheusConfigured(function(){return t.prometheusService.getRules().subscribe(function(e){t.rules=e.groups.reduce(function(t,e){return ft.concat(t,e.rules)},[])},function(){t.prometheusService.disablePrometheusConfig(),t.rules=[]})},function(){t.rules=[],t.notificationService.show(Xn.a.info,t.i18n("Please add your Prometheus host to the dashboard configuration and refresh the page"),void 0,void 0,"Prometheus")})},t.prototype.getModeSpecificData=function(){var t=this;this.route.params.subscribe(function(e){e.id&&(t.edit||t.recreate?t.prometheusService.getSilences(e).subscribe(function(e){t.fillFormWithSilence(e[0])}):t.prometheusService.getAlerts(e).subscribe(function(e){t.fillFormByAlert(e[0])}))})},t.prototype.fillFormWithSilence=function(t){var e=this;this.id=t.id,this.edit&&(["startsAt","endsAt"].forEach(function(n){return e.form.silentSet(n,new Date(t[n]))}),this.updateDuration()),["createdBy","comment"].forEach(function(n){return e.form.silentSet(n,t[n])}),this.matchers=t.matchers,this.validateMatchers()},t.prototype.validateMatchers=function(){var t=this;this.rules?(this.matcherMatch=this.silenceMatcher.multiMatch(this.matchers,this.rules),this.form.markAsDirty(),this.form.updateValueAndValidity()):window.setTimeout(function(){return t.validateMatchers()},100)},t.prototype.fillFormByAlert=function(t){var e=this,n=t.labels;Object.keys(n).forEach(function(t){return e.setMatcher({name:t,value:n[t],isRegex:!1})})},t.prototype.setMatcher=function(t,e){ft.isNumber(e)?this.matchers[e]=t:this.matchers.push(t),this.validateMatchers()},t.prototype.showMatcherModal=function(t){var e=this,n=this.bsModalService.show(Es),a=n.content;a.rules=this.rules,ft.isNumber(t)&&(a.editMode=!0,a.preFillControls(this.matchers[t])),n.content.submitAction.subscribe(function(n){e.setMatcher(n,t)})},t.prototype.deleteMatcher=function(t){this.matchers.splice(t,1),this.validateMatchers()},t.prototype.submit=function(){var t=this;this.form.invalid||this.prometheusService.setSilence(this.getSubmitData()).subscribe(function(e){t.router.navigate(["/monitoring"],{fragment:"silences"}),t.notificationService.show(Xn.a.success,t.getNotificationTile(e.body.silenceId),void 0,void 0,"Prometheus")},function(){return t.form.setErrors({cdSubmitButton:!0})})},t.prototype.getSubmitData=function(){var t=this.form.value;return delete t.duration,t.startsAt=t.startsAt.toISOString(),t.endsAt=t.endsAt.toISOString(),t.matchers=this.matchers,this.edit&&(t.id=this.id),t},t.prototype.getNotificationTile=function(t){return(this.edit?this.succeededLabels.EDITED:this.recreate?this.succeededLabels.RECREATED:this.succeededLabels.CREATED)+" "+this.resource+" "+t},t}(),Ps=s["\u0275crt"]({encapsulation:0,styles:[["textarea[_ngcontent-%COMP%]{resize:vertical}"]],data:{}});function Ms(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"input",[["class","form-control"],["disabled",""],["readonly",""],["type","text"]],[[8,"id",0],[8,"value",0]],null,null,null,null)),s["\u0275did"](2,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],null,function(t,e){t(e,1,0,s["\u0275inlineInterpolate"](2,"matcher-",e.parent.context.$implicit.attribute,"-",e.parent.parent.context.index,""),e.parent.parent.context.matcher[e.parent.context.$implicit.attribute])})}function qs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"span",[["class","input-group-addon"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"input",[["disabled",""],["readonly",""],["type","checkbox"]],[[8,"id",0],[8,"checked",0]],null,null,null,null)),s["\u0275did"](3,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],null,function(t,e){t(e,2,0,s["\u0275inlineInterpolate"](2,"matcher-",e.parent.context.$implicit.attribute,"-",e.parent.parent.context.index,""),e.parent.parent.context.matcher[e.parent.context.$implicit.attribute])})}function js(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,9,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,16777216,null,null,4,"span",[["class","input-group-addon"]],[[1,"aria-describedby",0]],null,null,null,null)),s["\u0275did"](2,212992,null,0,c.c,[s.ViewContainerRef,J.a,c.a,s.ElementRef,s.Renderer2,Q.a],{tooltip:[0,"tooltip"]},null),(t()(),s["\u0275eld"](3,0,null,null,2,"i",[["class","icon-prepend"]],null,null,null,null,null)),s["\u0275did"](4,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pad"](5,1),(t()(),s["\u0275and"](16777216,null,null,1,null,Ms)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,qs)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,2,0,e.context.$implicit.tooltip);var n=t(e,5,0,e.context.$implicit.icon);t(e,4,0,"icon-prepend",n),t(e,7,0,"isRegex"!==e.context.$implicit.attribute),t(e,9,0,"isRegex"===e.context.$implicit.attribute)},function(t,e){t(e,1,0,s["\u0275nov"](e,2).ariaDescribedby)})}function Fs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,13,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,js)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](3,0,null,null,10,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,16777216,null,null,4,"button",[["class","btn btn-default"],["tooltip","Edit"],["type","button"]],[[8,"id",0],[1,"aria-describedby",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.showMatcherModal(t.context.index)&&a),a},null,null)),s["\u0275did"](5,212992,null,0,c.c,[s.ViewContainerRef,J.a,c.a,s.ElementRef,s.Renderer2,Q.a],{tooltip:[0,"tooltip"]},null),(t()(),s["\u0275eld"](6,0,null,null,2,"i",[],null,null,null,null,null)),s["\u0275did"](7,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pad"](8,1),(t()(),s["\u0275eld"](9,16777216,null,null,4,"button",[["class","btn btn-default"],["tooltip","Delete"],["type","button"]],[[8,"id",0],[1,"aria-describedby",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.deleteMatcher(t.context.index)&&a),a},null,null)),s["\u0275did"](10,212992,null,0,c.c,[s.ViewContainerRef,J.a,c.a,s.ElementRef,s.Renderer2,Q.a],{tooltip:[0,"tooltip"]},null),(t()(),s["\u0275eld"](11,0,null,null,2,"i",[],null,null,null,null,null)),s["\u0275did"](12,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pad"](13,1),(t()(),s["\u0275eld"](14,0,null,null,0,"span",[["class","help-block"]],null,null,null,null,null))],function(t,e){var n=e.component;t(e,2,0,n.matcherConfig),t(e,5,0,"Edit");var a=t(e,8,0,n.icons.edit);t(e,7,0,a),t(e,10,0,"Delete");var r=t(e,13,0,n.icons.trash);t(e,12,0,r)},function(t,e){t(e,4,0,s["\u0275inlineInterpolate"](1,"matcher-edit-",e.context.index,""),s["\u0275nov"](e,5).ariaDescribedby),t(e,9,0,s["\u0275inlineInterpolate"](1,"matcher-delete-",e.context.index,""),s["\u0275nov"](e,10).ariaDescribedby)})}function zs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](1,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["Editing a silence will expire the old silence and recreate it as a new silence"]))],null,null)}function Gs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Ys(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Vs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Hs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Bs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Us(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"h5",[],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pod"](2,{"text-warning":0,"text-danger":1}),(t()(),s["\u0275eld"](3,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["A silence requires at least one matcher"]))],function(t,e){var n=t(e,2,0,!s["\u0275nov"](e.parent,6).submitted,s["\u0275nov"](e.parent,6).submitted);t(e,1,0,n)},null)}function Ws(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function Ks(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,Ws)),s["\u0275did"](2,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),s["\u0275pod"](3,{index:0,matcher:1})],function(t,e){var n=t(e,3,0,e.context.index,e.context.$implicit);t(e,2,0,n,s["\u0275nov"](e.parent,2))},null)}function $s(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[["id","match-state"]],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275ted"](2,null,[" "," "]))],null,function(t,e){var n=e.component;t(e,0,0,s["\u0275inlineInterpolate"](1,"col-sm-offset-3 col-sm-9 ",n.matcherMatch.cssClass,"")),t(e,1,0,s["\u0275inlineInterpolate"](1,"help-block ",n.matcherMatch.cssClass,"")),t(e,2,0,n.matcherMatch.status)})}function Zs(t){return s["\u0275vid"](0,[s["\u0275pid"](0,i.TitleCasePipe,[]),s["\u0275pid"](0,Rs.a,[]),(t()(),s["\u0275and"](0,[["matcherTpl",2]],null,0,null,Fs)),(t()(),s["\u0275eld"](3,0,null,null,139,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,138,"form",[["class","form-horizontal"],["name","form"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,6).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,6).onReset()&&a),a},null,null)),s["\u0275did"](5,16384,null,0,Te.D,[],null,null),s["\u0275did"](6,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](8,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](9,0,null,null,133,"div",[["class","panel panel-default"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,7,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](11,0,null,null,6,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](13,null,[" "," "," "])),s["\u0275ppd"](14,1),s["\u0275ppd"](15,1),(t()(),s["\u0275and"](16777216,null,null,1,null,zs)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,115,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](20,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](21,{"has-error":0}),(t()(),s["\u0275eld"](22,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","created-by"]],null,null,null,null,null)),(t()(),s["\u0275eld"](23,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Creator"])),(t()(),s["\u0275eld"](25,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](26,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](27,0,null,null,6,"input",[["class","form-control"],["formControlName","createdBy"],["id","created-by"],["name","created-by"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,29)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,29).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,29)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,29)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](28,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](29,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](31,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](33,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Gs)),s["\u0275did"](35,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](36,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](37,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](38,{"has-error":0}),(t()(),s["\u0275eld"](39,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","comment"]],null,null,null,null,null)),(t()(),s["\u0275eld"](40,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Comment"])),(t()(),s["\u0275eld"](42,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](43,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](44,0,null,null,6,"textarea",[["class","form-control"],["formControlName","comment"],["id","comment"],["name","comment"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,45)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,45).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,45)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,45)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](45,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](47,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](49,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275ted"](-1,null,[" "])),(t()(),s["\u0275and"](16777216,null,null,1,null,Ys)),s["\u0275did"](52,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](53,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](54,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](55,{"has-error":0}),(t()(),s["\u0275eld"](56,0,null,null,6,"label",[["class","control-label col-sm-3"],["for","starts-at"]],null,null,null,null,null)),(t()(),s["\u0275eld"](57,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Start time"])),(t()(),s["\u0275eld"](59,0,null,null,2,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](60,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["If the start time lies in the past the creation time will be used"])),(t()(),s["\u0275eld"](62,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](63,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](64,16777216,null,null,9,"input",[["bsDatepicker",""],["class","form-control"],["formControlName","startsAt"],["id","starts-at"],["name","starts-at"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"],[null,"keyup.esc"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,66)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,66).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,66)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,66)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,68).onChange(n)&&a),"keyup.esc"===e&&(a=!1!==s["\u0275nov"](t,68).hide()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,68).onBlur()&&a),a},null,null)),s["\u0275did"](65,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](66,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](67,737280,null,0,Nr.c,[Nr.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a],{bsConfig:[0,"bsConfig"]},null),s["\u0275did"](68,16384,null,0,Nr.f,[Nr.c,Nr.j,s.Renderer2,s.ElementRef,s.ChangeDetectorRef],null,null),s["\u0275prd"](1024,null,Te.o,function(t){return[t]},[Nr.f]),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Nr.f]),s["\u0275did"](71,671744,null,0,Te.j,[[3,Te.d],[6,Te.o],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](73,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Vs)),s["\u0275did"](75,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](76,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](77,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](78,{"has-error":0}),(t()(),s["\u0275eld"](79,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","duration"]],null,null,null,null,null)),(t()(),s["\u0275eld"](80,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Duration"])),(t()(),s["\u0275eld"](82,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](83,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](84,0,null,null,6,"input",[["class","form-control"],["formControlName","duration"],["id","duration"],["name","duration"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,86)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,86).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,86)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,86)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](85,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](86,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](88,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](90,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Hs)),s["\u0275did"](92,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](93,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](94,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](95,{"has-error":0}),(t()(),s["\u0275eld"](96,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","ends-at"]],null,null,null,null,null)),(t()(),s["\u0275eld"](97,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["End time"])),(t()(),s["\u0275eld"](99,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](100,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](101,16777216,null,null,9,"input",[["bsDatepicker",""],["class","form-control"],["formControlName","endsAt"],["id","ends-at"],["name","ends-at"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"],[null,"keyup.esc"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,103)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,103).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,103)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,103)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,105).onChange(n)&&a),"keyup.esc"===e&&(a=!1!==s["\u0275nov"](t,105).hide()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,105).onBlur()&&a),a},null,null)),s["\u0275did"](102,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](103,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](104,737280,null,0,Nr.c,[Nr.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a],{bsConfig:[0,"bsConfig"]},null),s["\u0275did"](105,16384,null,0,Nr.f,[Nr.c,Nr.j,s.Renderer2,s.ElementRef,s.ChangeDetectorRef],null,null),s["\u0275prd"](1024,null,Te.o,function(t){return[t]},[Nr.f]),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Nr.f]),s["\u0275did"](108,671744,null,0,Te.j,[[3,Te.d],[6,Te.o],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](110,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Bs)),s["\u0275did"](112,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](113,0,null,null,20,"fieldset",[],null,null,null,null,null)),(t()(),s["\u0275eld"](114,0,null,null,3,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Matchers"])),(t()(),s["\u0275eld"](116,0,null,null,1,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["*"])),(t()(),s["\u0275eld"](118,0,null,null,13,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Us)),s["\u0275did"](120,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ks)),s["\u0275did"](122,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](123,0,null,null,8,"span",[["class","form-control no-border"]],null,null,null,null,null)),(t()(),s["\u0275eld"](124,0,null,null,7,"button",[["class","btn btn-sm btn-default btn-label pull-right"],["id","add-matcher"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.showMatcherModal()&&a),a},null,null)),s["\u0275did"](125,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](126,{"btn-warning":0}),(t()(),s["\u0275eld"](127,0,null,null,2,"i",[],null,null,null,null,null)),s["\u0275did"](128,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pad"](129,2),(t()(),s["\u0275eld"](130,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Add matcher"])),(t()(),s["\u0275and"](16777216,null,null,1,null,$s)),s["\u0275did"](133,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](134,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](135,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275eld"](136,0,null,null,4,"cd-submit-button",[["id","submit"],["type","button"]],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submit()&&a),a},$a.b,$a.a)),s["\u0275did"](137,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](138,0,[" "," "," "])),s["\u0275ppd"](139,1),s["\u0275ppd"](140,1),(t()(),s["\u0275eld"](141,0,null,null,1,"cd-back-button",[],null,null,null,Xa.b,Xa.a)),s["\u0275did"](142,49152,null,0,Ja.a,[i.Location,Zn.b],null,null)],function(t,e){var n=e.component;t(e,6,0,n.form),t(e,17,0,n.edit);var a=t(e,21,0,n.form.showError("createdBy",s["\u0275nov"](e,6)));t(e,20,0,"form-group",a),t(e,31,0,"createdBy"),t(e,35,0,n.form.showError("createdBy",s["\u0275nov"](e,6),"required"));var r=t(e,38,0,n.form.showError("comment",s["\u0275nov"](e,6)));t(e,37,0,"form-group",r),t(e,47,0,"comment"),t(e,52,0,n.form.showError("comment",s["\u0275nov"](e,6),"required"));var i=t(e,55,0,n.form.showError("startsAt",s["\u0275nov"](e,6)));t(e,54,0,"form-group",i),t(e,67,0,n.bsConfig),t(e,71,0,"startsAt"),t(e,75,0,n.form.showError("startsAt",s["\u0275nov"](e,6),"required"));var o=t(e,78,0,n.form.showError("duration",s["\u0275nov"](e,6)));t(e,77,0,"form-group",o),t(e,88,0,"duration"),t(e,92,0,n.form.showError("duration",s["\u0275nov"](e,6),"required"));var u=t(e,95,0,n.form.showError("endsAt",s["\u0275nov"](e,6)));t(e,94,0,"form-group",u),t(e,104,0,n.bsConfig),t(e,108,0,"endsAt"),t(e,112,0,n.form.showError("endsAt",s["\u0275nov"](e,6),"required")),t(e,120,0,0===n.matchers.length),t(e,122,0,n.matchers);var c=t(e,126,0,s["\u0275nov"](e,6).submitted&&0===n.matchers.length);t(e,125,0,"btn btn-sm btn-default btn-label pull-right",c);var l=t(e,129,0,n.icons.width,n.icons.add);t(e,128,0,l),t(e,133,0,n.matchers.length&&n.matcherMatch),t(e,137,0,s["\u0275nov"](e,6),"button")},function(t,e){var n=e.component;t(e,4,0,s["\u0275nov"](e,8).ngClassUntouched,s["\u0275nov"](e,8).ngClassTouched,s["\u0275nov"](e,8).ngClassPristine,s["\u0275nov"](e,8).ngClassDirty,s["\u0275nov"](e,8).ngClassValid,s["\u0275nov"](e,8).ngClassInvalid,s["\u0275nov"](e,8).ngClassPending);var a=s["\u0275unv"](e,13,0,t(e,14,0,s["\u0275nov"](e,0),n.action)),r=s["\u0275unv"](e,13,1,t(e,15,0,s["\u0275nov"](e,1),n.resource));t(e,13,0,a,r),t(e,27,0,s["\u0275nov"](e,33).ngClassUntouched,s["\u0275nov"](e,33).ngClassTouched,s["\u0275nov"](e,33).ngClassPristine,s["\u0275nov"](e,33).ngClassDirty,s["\u0275nov"](e,33).ngClassValid,s["\u0275nov"](e,33).ngClassInvalid,s["\u0275nov"](e,33).ngClassPending),t(e,44,0,s["\u0275nov"](e,49).ngClassUntouched,s["\u0275nov"](e,49).ngClassTouched,s["\u0275nov"](e,49).ngClassPristine,s["\u0275nov"](e,49).ngClassDirty,s["\u0275nov"](e,49).ngClassValid,s["\u0275nov"](e,49).ngClassInvalid,s["\u0275nov"](e,49).ngClassPending),t(e,64,0,s["\u0275nov"](e,73).ngClassUntouched,s["\u0275nov"](e,73).ngClassTouched,s["\u0275nov"](e,73).ngClassPristine,s["\u0275nov"](e,73).ngClassDirty,s["\u0275nov"](e,73).ngClassValid,s["\u0275nov"](e,73).ngClassInvalid,s["\u0275nov"](e,73).ngClassPending),t(e,84,0,s["\u0275nov"](e,90).ngClassUntouched,s["\u0275nov"](e,90).ngClassTouched,s["\u0275nov"](e,90).ngClassPristine,s["\u0275nov"](e,90).ngClassDirty,s["\u0275nov"](e,90).ngClassValid,s["\u0275nov"](e,90).ngClassInvalid,s["\u0275nov"](e,90).ngClassPending),t(e,101,0,s["\u0275nov"](e,110).ngClassUntouched,s["\u0275nov"](e,110).ngClassTouched,s["\u0275nov"](e,110).ngClassPristine,s["\u0275nov"](e,110).ngClassDirty,s["\u0275nov"](e,110).ngClassValid,s["\u0275nov"](e,110).ngClassInvalid,s["\u0275nov"](e,110).ngClassPending);var i=s["\u0275unv"](e,138,0,t(e,139,0,s["\u0275nov"](e,0),n.action)),o=s["\u0275unv"](e,138,1,t(e,140,0,s["\u0275nov"](e,1),n.resource));t(e,138,0,i,o)})}function Xs(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-prometheus-form",[],null,null,null,Zs,Ps)),s["\u0275did"](1,49152,null,0,Ls,[xt.a,tt.l,l.a,ca.a,Ui,Jn.a,tt.a,Ds,pa.b,As,Zn.b,Zn.d],null,null)],null,null)}var Js=s["\u0275ccf"]("cd-prometheus-form",Ls,Xs,{},{},[]),Qs=function(){function t(e){var n=this;this.route=e,this.route.queryParams.subscribe(function(e){n.fromLink=e.fromLink||t.defaultFromLink}),this.route.params.subscribe(function(t){n.serviceId=decodeURIComponent(t.id),n.serviceType=t.type})}return t.defaultFromLink="/hosts",t}(),to=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function eo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",".",""])),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-table-performance-counter",[],null,null,null,In.b,In.a)),s["\u0275did"](3,114688,null,0,Cn.a,[kn.a,xt.a],{serviceType:[0,"serviceType"],serviceId:[1,"serviceId"]},null)],function(t,e){var n=e.component;t(e,3,0,n.serviceType,n.serviceId)},function(t,e){var n=e.component;t(e,1,0,n.serviceType,n.serviceId)})}function no(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-performance-counter",[],null,null,null,eo,to)),s["\u0275did"](1,49152,null,0,Qs,[tt.a],null,null)],null,null)}var ao=s["\u0275ccf"]("cd-performance-counter",Qs,no,{},{},[]),ro=function(){function t(t){this.http=t,this.url="api/mgr/module"}return t.prototype.list=function(){return this.http.get(""+this.url)},t.prototype.getConfig=function(t){return this.http.get(this.url+"/"+t)},t.prototype.updateConfig=function(t,e){return this.http.put(this.url+"/"+t,{config:e})},t.prototype.enable=function(t){return this.http.post(this.url+"/"+t+"/enable",null)},t.prototype.disable=function(t){return this.http.post(this.url+"/"+t+"/disable",null)},t.prototype.getOptions=function(t){return this.http.get(this.url+"/"+t+"/options")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),io=function(){function t(t){this.mgrModuleService=t}return t.prototype.ngOnChanges=function(){var t=this;if(this.selection.hasSelection){var e=this.selection.first();this.mgrModuleService.getConfig(e.name).subscribe(function(e){t.module_config=e})}},t}(),so=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function oo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](5,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},null)],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,5,0,n.module_config)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass)})}function uo(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,oo)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.selection.hasSingleSelection)},null)}var co=n("gI3B"),lo=function(){function t(t,e,n,a){var r=this;this.authStorageService=t,this.mgrModuleService=e,this.notificationService=n,this.i18n=a,this.columns=[],this.modules=[],this.selection=new He.a,this.permission=this.authStorageService.getPermissions().configOpt,this.columns=[{name:this.i18n("Name"),prop:"name",flexGrow:1},{name:this.i18n("Enabled"),prop:"enabled",flexGrow:1,cellClass:"text-center",cellTransformation:cn.a.checkIcon}],this.tableActions=[{name:this.i18n("Edit"),permission:"update",disable:function(){return!r.selection.hasSelection||0===Object.values(r.selection.first().options).length},routerLink:function(){return"/mgr-modules/edit/"+(r.selection.first()&&encodeURIComponent(r.selection.first().name))},icon:"fa-pencil"},{name:this.i18n("Enable"),permission:"update",click:function(){return r.updateModuleState()},disable:function(){return r.isTableActionDisabled("enabled")},icon:"fa-play"},{name:this.i18n("Disable"),permission:"update",click:function(){return r.updateModuleState()},disable:function(){return r.isTableActionDisabled("disabled")},disableDesc:function(){return r.getTableActionDisabledDesc()},icon:"fa-stop"}]}return t.prototype.getModuleList=function(t){var e=this;this.mgrModuleService.list().subscribe(function(t){e.modules=t},function(){t.error()})},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.isTableActionDisabled=function(t){if(!this.selection.hasSelection)return!0;var e=this.selection.first();if("dashboard"===e.name)return!0;if(e.always_on)return!0;switch(t){case"enabled":return e.enabled;case"disabled":return!e.enabled}},t.prototype.getTableActionDisabledDesc=function(){if(this.selection.hasSelection&&this.selection.first().always_on)return this.i18n("This Manager module is always on.")},t.prototype.updateModuleState=function(){var t=this;if(this.selection.hasSelection){var e=function(){Object(co.a)(2e3).subscribe(function(){t.mgrModuleService.list().subscribe(function(){t.notificationService.suspendToasties(!1),t.blockUI.stop(),t.table.refreshBtn()},function(){e()})})},n=this.selection.first();(n.enabled?this.mgrModuleService.disable(n.name):this.mgrModuleService.enable(n.name)).subscribe(function(){},function(){t.notificationService.suspendToasties(!0),t.blockUI.start(t.i18n("Reconnecting, please wait ...")),e()})}},p.__decorate([function(t,e,n){t[e]=x.decorate(void 0)},p.__metadata("design:type",Object)],t.prototype,"blockUI",void 0),t}(),fo=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function po(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{table:0}),(t()(),s["\u0275eld"](1,0,null,null,5,"cd-table",[["columnMode","flex"],["identifier","module"],["selectionType","single"]],null,[[null,"updateSelection"],[null,"fetchData"]],function(t,e,n){var a=!0,r=t.component;return"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),"fetchData"===e&&(a=!1!==r.getModuleList(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](2,2867200,[[1,4],["table",4]],0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],autoReload:[3,"autoReload"],identifier:[4,"identifier"],selectionType:[5,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](3,0,null,0,1,"cd-table-actions",[["class","table-actions"]],null,null,null,xn.b,xn.a)),s["\u0275did"](4,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275eld"](5,0,null,2,1,"cd-mgr-module-details",[["cdTableDetail",""]],null,null,null,uo,so)),s["\u0275did"](6,573440,null,0,io,[ro],{selection:[0,"selection"]},null)],function(t,e){var n=e.component;t(e,2,0,n.modules,n.columns,"flex",!1,"module","single"),t(e,4,0,n.permission,n.selection,n.tableActions),t(e,6,0,n.selection)},null)}function ho(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-mgr-module-list",[],null,null,null,po,fo)),s["\u0275did"](1,49152,null,0,lo,[l.a,ro,Jn.a,xt.a],null,null)],null,null)}var go=s["\u0275ccf"]("cd-mgr-module-list",lo,ho,{},{},[]),bo=n("QC43"),mo=n("XFyV"),yo=n("M/6F"),vo=n("NDi4"),_o=function(){function t(t,e,n,a,r,i){this.route=t,this.router=e,this.formBuilder=n,this.mgrModuleService=a,this.notificationService=r,this.i18n=i,this.error=!1,this.loading=!1,this.moduleName="",this.moduleOptions=[]}return t.prototype.ngOnInit=function(){var t=this;this.route.params.subscribe(function(e){t.moduleName=decodeURIComponent(e.name),t.loading=!0;var n=[];n.push(t.mgrModuleService.getOptions(t.moduleName)),n.push(t.mgrModuleService.getConfig(t.moduleName)),Object(ta.a)(n).subscribe(function(e){t.loading=!1,t.moduleOptions=e[0],t.createForm(),t.mgrModuleForm.setValue(e[1])},function(e){t.error=e})},function(e){t.error=e})},t.prototype.getValidators=function(t){var e=[];switch(t.type){case"addr":e.push(aa.a.ip());break;case"uint":case"int":case"size":case"secs":e.push(aa.a.number()),e.push(Te.A.required),ft.isNumber(t.min)&&e.push(Te.A.min(t.min)),ft.isNumber(t.max)&&e.push(Te.A.max(t.max));break;case"str":ft.isNumber(t.min)&&e.push(Te.A.minLength(t.min)),ft.isNumber(t.max)&&e.push(Te.A.maxLength(t.max));break;case"float":e.push(Te.A.required),e.push(aa.a.decimalNumber());break;case"uuid":e.push(aa.a.uuid())}return e},t.prototype.createForm=function(){var t=this,e={};ft.forEach(this.moduleOptions,function(n){e[n.name]=[n.default_value,t.getValidators(n)]}),this.mgrModuleForm=this.formBuilder.group(e)},t.prototype.goToListView=function(){this.router.navigate(["/mgr-modules"])},t.prototype.onSubmit=function(){var t=this;if(this.mgrModuleForm.pristine)this.goToListView();else{var e={};ft.forEach(this.moduleOptions,function(n){var a=t.mgrModuleForm.get(n.name);a.dirty&&a.valid&&(e[n.name]=a.value)}),this.mgrModuleService.updateConfig(this.moduleName,e).subscribe(function(){t.notificationService.show(Xn.a.success,t.i18n('Updated options for module "{{name}}".',{name:t.moduleName})),t.goToListView()},function(){t.mgrModuleForm.setErrors({cdSubmitButton:!0})})}},t}(),xo=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function To(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-loading-panel",[],null,null,null,bo.b,bo.a)),s["\u0275did"](1,49152,null,0,mo.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["Loading configuration..."]))],null,null)}function wo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-error-panel",[],null,null,null,yo.b,yo.a)),s["\u0275did"](1,49152,null,0,vo.a,[],null,null),(t()(),s["\u0275ted"](-1,0,["The configuration could not be loaded."]))],null,null)}function So(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](1,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](2,0,[" "," "])),s["\u0275ppd"](3,1)],null,function(t,e){var n=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent.parent.parent,0),e.parent.context.$implicit.value.long_desc||e.parent.context.$implicit.value.desc));t(e,2,0,n)})}function Oo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,9,"div",[["class","col-sm-7"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,8,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,6,"input",[["type","checkbox"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,3).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,3).onTouched()&&a),a},null,null)),s["\u0275did"](3,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](5,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](7,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](8,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](9,0,null,null,0,"label",[],[[8,"htmlFor",0]],null,null,null,null))],function(t,e){t(e,5,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,""))},function(t,e){t(e,2,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,""),s["\u0275nov"](e,7).ngClassUntouched,s["\u0275nov"](e,7).ngClassTouched,s["\u0275nov"](e,7).ngClassPristine,s["\u0275nov"](e,7).ngClassDirty,s["\u0275nov"](e,7).ngClassValid,s["\u0275nov"](e,7).ngClassInvalid,s["\u0275nov"](e,7).ngClassPending),t(e,9,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,""))})}function Io(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["type","text"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,1)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,1).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,1)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,1)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](1,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](3,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](5,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](6,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.parent.parent.context.$implicit.value.name,""))},function(t,e){t(e,0,0,s["\u0275inlineInterpolate"](1,"",e.parent.parent.context.$implicit.value.name,""),s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending)})}function Co(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{ngValue:[0,"ngValue"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),s["\u0275ted"](3,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function ko(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"select",[["class","form-control"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,1).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,1).onTouched()&&a),a},null,null)),s["\u0275did"](1,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](3,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](5,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](6,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Co)),s["\u0275did"](8,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.parent.parent.context.$implicit.value.name,"")),t(e,8,0,e.parent.parent.context.$implicit.value.enum_allowed)},function(t,e){t(e,0,0,s["\u0275inlineInterpolate"](1,"",e.parent.parent.context.$implicit.value.name,""),s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending)})}function No(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8"]))],null,null)}function Ro(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The entered value needs to be a valid IP address."]))],null,null)}function Ao(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"div",[["class","col-sm-7"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Io)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ko)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,No)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ro)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,0===e.parent.context.$implicit.value.enum_allowed.length),t(e,4,0,e.parent.context.$implicit.value.enum_allowed.length>0),t(e,6,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"invalidUuid")),t(e,8,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"pattern"))},null)}function Do(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Eo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too high! It must be lower or equal to ","."]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.value.max)})}function Lo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too low! It must be greater or equal to ","."]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.value.min)})}function Po(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The entered value needs to be a number."]))],null,null)}function Mo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,16,"div",[["class","col-sm-7"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,7,"input",[["class","form-control"],["type","number"]],[[8,"id",0],[8,"min",0],[8,"max",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,2)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,2).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,2)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,2)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,3).onChange(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,3).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,3).onTouched()&&a),a},null,null)),s["\u0275did"](2,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](3,16384,null,0,Te.C,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Te.C]),s["\u0275did"](5,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](7,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](8,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Do)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Eo)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Lo)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Po)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,5,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,"")),t(e,10,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"required")),t(e,12,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"max")),t(e,14,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"min")),t(e,16,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"pattern"))},function(t,e){t(e,1,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,""),s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.min,""),s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.max,""),s["\u0275nov"](e,7).ngClassUntouched,s["\u0275nov"](e,7).ngClassTouched,s["\u0275nov"](e,7).ngClassPristine,s["\u0275nov"](e,7).ngClassDirty,s["\u0275nov"](e,7).ngClassValid,s["\u0275nov"](e,7).ngClassInvalid,s["\u0275nov"](e,7).ngClassPending)})}function qo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required."]))],null,null)}function jo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The entered value needs to be a number or decimal."]))],null,null)}function Fo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,12,"div",[["class","col-sm-7"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,7,"input",[["class","form-control"],["type","number"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,2)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,2).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,2)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,2)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,3).onChange(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,3).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,3).onTouched()&&a),a},null,null)),s["\u0275did"](2,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](3,16384,null,0,Te.C,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Te.C]),s["\u0275did"](5,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](7,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](8,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,qo)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,jo)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,5,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,"")),t(e,10,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"required")),t(e,12,0,n.mgrModuleForm.showError(e.parent.context.$implicit.value.name,s["\u0275nov"](e.parent.parent,3),"pattern"))},function(t,e){t(e,1,0,s["\u0275inlineInterpolate"](1,"",e.parent.context.$implicit.value.name,""),s["\u0275nov"](e,7).ngClassUntouched,s["\u0275nov"](e,7).ngClassTouched,s["\u0275nov"](e,7).ngClassPristine,s["\u0275nov"](e,7).ngClassDirty,s["\u0275nov"](e,7).ngClassValid,s["\u0275nov"](e,7).ngClassInvalid,s["\u0275nov"](e,7).ngClassPending)})}function zo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","control-label col-sm-3"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](4,null,[" "," "])),(t()(),s["\u0275and"](16777216,null,null,1,null,So)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Oo)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,2,null,Ao)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275pad"](11,3),(t()(),s["\u0275and"](16777216,null,null,2,null,Mo)),s["\u0275did"](13,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275pad"](14,4),(t()(),s["\u0275and"](16777216,null,null,1,null,Fo)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=t(e,2,0,e.component.mgrModuleForm.showError(e.context.$implicit.value.name,s["\u0275nov"](e.parent,3)));t(e,1,0,"form-group",n),t(e,6,0,e.context.$implicit.value.long_desc||e.context.$implicit.value.desc),t(e,8,0,"bool"===e.context.$implicit.value.type);var a=t(e,11,0,"addr","str","uuid").includes(e.context.$implicit.value.type);t(e,10,0,a);var r=t(e,14,0,"uint","int","size","secs").includes(e.context.$implicit.value.type);t(e,13,0,r),t(e,16,0,"float"===e.context.$implicit.value.type)},function(t,e){t(e,3,0,s["\u0275inlineInterpolate"](1,"",e.context.$implicit.value.name,"")),t(e,4,0,e.context.$implicit.value.name)})}function Go(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,22,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,21,"form",[["class","form-horizontal"],["name","mgrModuleForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,3).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,3).onReset()&&a),a},null,null)),s["\u0275did"](2,16384,null,0,Te.D,[],null,null),s["\u0275did"](3,540672,[["frm",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](5,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](6,0,null,null,16,"div",[["class","panel panel-default"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,2,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,1,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Edit Manager module"])),(t()(),s["\u0275eld"](10,0,null,null,3,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,zo)),s["\u0275did"](12,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.KeyValuePipe,[s.KeyValueDiffers]),(t()(),s["\u0275eld"](14,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](15,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275eld"](16,0,null,null,3,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.onSubmit()&&a),a},$a.b,$a.a)),s["\u0275did"](17,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(t()(),s["\u0275eld"](18,0,null,0,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Update"])),(t()(),s["\u0275eld"](20,0,null,null,2,"button",[["class","btn btn-sm btn-default"],["routerLink","/mgr-modules"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,21).onClick()&&a),a},null,null)),s["\u0275did"](21,16384,null,0,tt.m,[tt.l,tt.a,[8,null],s.Renderer2,s.ElementRef],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Back"]))],function(t,e){var n=e.component;t(e,3,0,n.mgrModuleForm),t(e,12,0,s["\u0275unv"](e,12,0,s["\u0275nov"](e,13).transform(n.moduleOptions))),t(e,17,0,n.mgrModuleForm,"button"),t(e,21,0,"/mgr-modules")},function(t,e){t(e,1,0,s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending)})}function Yo(t){return s["\u0275vid"](0,[s["\u0275pid"](0,Rs.a,[]),(t()(),s["\u0275and"](16777216,null,null,1,null,To)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,wo)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Go)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.loading&&!n.error),t(e,4,0,n.loading&&n.error),t(e,6,0,!n.loading&&!n.error)},null)}function Vo(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-mgr-module-form",[],null,null,null,Yo,xo)),s["\u0275did"](1,114688,null,0,_o,[tt.a,tt.l,ca.a,ro,Jn.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var Ho=s["\u0275ccf"]("cd-mgr-module-form",_o,Vo,{},{},[]),Bo=function(){function t(){this.lhsCounter="mds_mem.ino",this.rhsCounter="mds_server.handle_client_request",this.chart={datasets:[{label:this.lhsCounter,yAxisID:"LHS",data:[],lineTension:.1},{label:this.rhsCounter,yAxisID:"RHS",data:[],lineTension:.1}],options:{title:{text:"",display:!0},responsive:!0,maintainAspectRatio:!1,legend:{position:"top"},scales:{xAxes:[{position:"top",type:"time",time:{displayFormats:{quarter:"MMM YYYY"}},ticks:{maxRotation:0}}],yAxes:[{id:"LHS",type:"linear",position:"left"},{id:"RHS",type:"linear",position:"right"}]},tooltips:{enabled:!1,mode:"index",intersect:!1,position:"nearest",callbacks:{title:function(t,e){var n=0;if(t.length>0){var a=t[0];n=e.datasets[a.datasetIndex].data[a.index].x}return n.toString()}}}},chartType:"line"}}return t.prototype.ngOnInit=function(){ft.isUndefined(this.mdsCounter)||(this.setChartTooltip(),this.updateChart())},t.prototype.ngOnChanges=function(){ft.isUndefined(this.mdsCounter)||this.updateChart()},t.prototype.setChartTooltip=function(){var t=new pt.a(this.chartCanvas,this.chartTooltip,function(t){return t.caretX+"px"},function(t){return t.caretY-t.height-23+"px"});t.getTitle=function(t){return rs(t,"x").format("LTS")},t.checkOffset=!0,ft.merge(this.chart,{options:{title:{text:this.mdsCounter.name},tooltips:{custom:function(e){return t.customTooltips(e)}}}})},t.prototype.updateChart=function(){var t=[{data:this.convertTimeSeries(this.mdsCounter[this.lhsCounter])},{data:this.deltaTimeSeries(this.mdsCounter[this.rhsCounter])}];ft.merge(this.chart,{datasets:t}),this.chart.datasets=this.chart.datasets.slice()},t.prototype.convertTimeSeries=function(t){var e=[];return ft.each(t,function(t){e.push({x:1e3*t[0],y:t[1]})}),e.shift(),e},t.prototype.deltaTimeSeries=function(t){var e,n=t[0],a=[];for(e=1;e<t.length;e++){var r=t[e];a.push({x:1e3*r[0],y:r[1]-n[1]}),n=r}return a},t}(),Uo=s["\u0275crt"]({encapsulation:0,styles:[["canvas[_ngcontent-%COMP%]{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.chartjs-tooltip[_ngcontent-%COMP%]{opacity:0;position:absolute;background:rgba(0,0,0,.7);color:#fff;border-radius:3px;-webkit-transition:.1s;transition:all .1s ease;pointer-events:none;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif!important;-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]{-webkit-transform:translate(-10%,0);transform:translate(-10%,0)}.chartjs-tooltip.transform-left[_ngcontent-%COMP%]::after{left:10%}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]{-webkit-transform:translate(-90%,0);transform:translate(-90%,0)}.chartjs-tooltip.transform-right[_ngcontent-%COMP%]::after{left:90%}.chartjs-tooltip[_ngcontent-%COMP%]::after{content:' ';position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:#000 transparent transparent} .chartjs-tooltip-key{display:inline-block;width:10px;height:10px;margin-right:10px}.chart-container[_ngcontent-%COMP%]{margin:auto auto 20px;cursor:pointer;overflow:visible;position:relative;height:500px;width:100%}"]],data:{}});function Wo(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{chartCanvas:0}),s["\u0275qud"](402653184,2,{chartTooltip:0}),(t()(),s["\u0275eld"](2,0,null,null,4,"div",[["class","chart-container"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,[[1,0],["chartCanvas",1]],null,1,"canvas",[["baseChart",""]],null,null,null,null,null)),s["\u0275did"](4,737280,null,0,lt.BaseChartDirective,[s.ElementRef],{datasets:[0,"datasets"],options:[1,"options"],chartType:[2,"chartType"]},null),(t()(),s["\u0275eld"](5,0,[[2,0],["chartTooltip",1]],null,1,"div",[["class","chartjs-tooltip"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,0,"table",[],null,null,null,null,null))],function(t,e){var n=e.component;t(e,4,0,n.chart.datasets,n.chart.options,n.chart.chartType)},null)}var Ko=n("C6Ij"),$o=n("AWcq"),Zo=function(){function t(t){this.http=t,this.baseURL="api/cephfs"}return t.prototype.list=function(){return this.http.get(""+this.baseURL)},t.prototype.getCephfs=function(t){return this.http.get(this.baseURL+"/"+t)},t.prototype.getClients=function(t){return this.http.get(this.baseURL+"/"+t+"/clients")},t.prototype.getMdsCounters=function(t){return this.http.get(this.baseURL+"/"+t+"/mds_counters")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),Xo=n("yJti"),Jo=function(){function t(t,e){this.cephfsService=t,this.i18n=e}return t.prototype.ngOnInit=function(){this.clients={columns:[{prop:"id",name:this.i18n("id")},{prop:"type",name:this.i18n("type")},{prop:"state",name:this.i18n("state")},{prop:"version",name:this.i18n("version")},{prop:"hostname",name:this.i18n("Host")},{prop:"root",name:this.i18n("root")}],data:[]},this.clients.data=[],this.viewCacheStatus=Xo.a.ValueNone},t.prototype.refresh=function(){var t=this;this.cephfsService.getClients(this.id).subscribe(function(e){t.viewCacheStatus=e.status,t.clients.data=e.data})},t}(),Qo=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function tu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-view-cache",[],null,null,null,Ko.b,Ko.a)),s["\u0275did"](1,114688,null,0,$o.a,[],{status:[0,"status"]},null),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-table",[],null,[[null,"fetchData"]],function(t,e,n){var a=!0;return"fetchData"===e&&(a=!1!==t.component.refresh()&&a),a},Ye.b,Ye.a)),s["\u0275did"](3,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"]},{fetchData:"fetchData"})],function(t,e){var n=e.component;t(e,1,0,n.viewCacheStatus),t(e,3,0,n.clients.data,n.clients.columns)},null)}var eu=function(){function t(t,e,n,a,r){this.authStorageService=t,this.cephfsService=e,this.dimlessBinary=n,this.dimless=a,this.i18n=r,this.standbys=[],this.mdsCounters={},this.objectValues=Object.values,this.clientsSelect=!1,this.grafanaPermission=this.authStorageService.getPermissions().grafana}return t.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.selectedItem=this.selection.first(),this.grafanaId=Object.values(this.selectedItem.mdsmap.info)[0].name,this.id!==this.selectedItem.id&&(this.id=this.selectedItem.id,this.ranks.data=[],this.pools.data=[],this.standbys=[],this.mdsCounters={}))},t.prototype.ngOnInit=function(){this.ranks={columns:[{prop:"rank",name:this.i18n("Rank")},{prop:"state",name:this.i18n("State")},{prop:"mds",name:this.i18n("Daemon")},{prop:"activity",name:this.i18n("Activity"),cellTemplate:this.activityTmpl},{prop:"dns",name:this.i18n("Dentries"),pipe:this.dimless},{prop:"inos",name:this.i18n("Inodes"),pipe:this.dimless}],data:[]},this.pools={columns:[{prop:"pool",name:this.i18n("Pool")},{prop:"type",name:this.i18n("Type")},{prop:"size",name:this.i18n("Size"),pipe:this.dimlessBinary},{name:this.i18n("Usage"),cellTemplate:this.poolUsageTpl,comparator:function(t,e,n,a){var r=n.used/n.avail,i=a.used/a.avail;return r===i?0:r>i?1:-1}}],data:[]}},t.prototype.refresh=function(){var t=this;this.cephfsService.getCephfs(this.id).subscribe(function(e){t.ranks.data=e.cephfs.ranks,t.pools.data=e.cephfs.pools,t.pools.data.forEach(function(t){t.size=t.used+t.avail}),t.standbys=[{key:t.i18n("Standby daemons"),value:e.standbys.map(function(t){return t.name}).join(", ")}],t.name=e.cephfs.name,t.clientCount=e.cephfs.client_count}),this.cephfsService.getMdsCounters(this.id).subscribe(function(e){ft.each(t.mdsCounters,function(n,a){void 0===e[a]&&delete t.mdsCounters[a]}),ft.each(e,function(e,n){e.name=n,t.mdsCounters[n]=e})})},t.prototype.trackByFn=function(t,e){return e.name},t}(),nu=s["\u0275crt"]({encapsulation:0,styles:[[".progress[_ngcontent-%COMP%]{margin-bottom:0}"]],data:{}});function au(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"div",[["class","col-md-12"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-cephfs-chart",[],null,null,null,Wo,Uo)),s["\u0275did"](3,638976,null,0,Bo,[],{mdsCounter:[0,"mdsCounter"]},null)],function(t,e){t(e,3,0,e.context.$implicit)},null)}function ru(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-cephfs-clients",[],null,null,null,tu,Qo)),s["\u0275did"](1,114688,null,0,Jo,[Zo,xt.a],{id:[0,"id"]},null)],function(t,e){t(e,1,0,e.component.id)},null)}function iu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"tab",[["heading","Performance Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](1,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](2,0,null,null,1,"cd-grafana",[["grafanaStyle","one"],["uid","tbO9LAiZz"]],null,null,null,Me.b,Me.a)),s["\u0275did"](3,638976,null,0,qe.a,[je.a,Fe.DomSanitizer,ze.a,Ge.a,xt.a],{grafanaPath:[0,"grafanaPath"],grafanaStyle:[1,"grafanaStyle"],uid:[2,"uid"]},null)],function(t,e){var n=e.component;t(e,1,0,"Performance Details"),t(e,3,0,"mds-performance?var-mds_servers=mds."+n.grafanaId,"one","tbO9LAiZz")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).id,s["\u0275nov"](e,1).active,s["\u0275nov"](e,1).addClass)})}function su(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,26,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,18,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,12,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,6,"div",[["class","col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Ranks"])),(t()(),s["\u0275eld"](8,0,null,null,1,"cd-table",[],null,[[null,"fetchData"]],function(t,e,n){var a=!0;return"fetchData"===e&&(a=!1!==t.component.refresh()&&a),a},Ye.b,Ye.a)),s["\u0275did"](9,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],toolHeader:[2,"toolHeader"]},{fetchData:"fetchData"}),(t()(),s["\u0275eld"](10,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](11,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},null),(t()(),s["\u0275eld"](12,0,null,null,4,"div",[["class","col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Pools"])),(t()(),s["\u0275eld"](15,0,null,null,1,"cd-table",[],null,null,null,Ye.b,Ye.a)),s["\u0275did"](16,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],toolHeader:[2,"toolHeader"]},null),(t()(),s["\u0275eld"](17,0,null,null,1,"legend",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["MDS performance counters"])),(t()(),s["\u0275and"](16777216,null,null,1,null,au)),s["\u0275did"](20,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null),(t()(),s["\u0275eld"](21,0,null,0,3,"tab",[],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],[[null,"selectTab"],[null,"deselect"]],function(t,e,n){var a=!0,r=t.component;return"selectTab"===e&&(a=0!=(r.clientsSelect=!0)&&a),"deselect"===e&&(a=0!=(r.clientsSelect=!1)&&a),a},null,null)),s["\u0275did"](22,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},{selectTab:"selectTab",deselect:"deselect"}),(t()(),s["\u0275and"](16777216,null,null,1,null,ru)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,0,1,null,iu)),s["\u0275did"](26,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,9,0,n.ranks.data,n.ranks.columns,!1),t(e,11,0,n.standbys),t(e,16,0,n.pools.data,n.pools.columns,!1),t(e,20,0,n.objectValues(n.mdsCounters),n.trackByFn),t(e,22,0,s["\u0275inlineInterpolate"](1,"Clients: ",n.clientCount,"")),t(e,24,0,n.clientsSelect),t(e,26,0,n.grafanaPermission.read)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass),t(e,21,0,s["\u0275nov"](e,22).id,s["\u0275nov"](e,22).active,s["\u0275nov"](e,22).addClass)})}function ou(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-usage-bar",[],null,null,null,mn.b,mn.a)),s["\u0275did"](1,573440,null,0,yn.a,[],{total:[0,"total"],used:[1,"used"]},null)],function(t,e){t(e,1,0,e.context.row.size,e.context.row.used)},null)}function uu(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](0,null,[" ",": "," /s\n"])),s["\u0275ppd"](1,1)],null,function(t,e){var n="standby-replay"===e.context.row.state?"Evts":"Reqs",a=s["\u0275unv"](e,0,1,t(e,1,0,s["\u0275nov"](e.parent,0),e.context.value));t(e,0,0,n,a)})}function cu(t){return s["\u0275vid"](0,[s["\u0275pid"](0,gt.a,[It.a]),s["\u0275qud"](402653184,1,{poolUsageTpl:0}),s["\u0275qud"](402653184,2,{activityTmpl:0}),(t()(),s["\u0275and"](16777216,null,null,1,null,su)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,[[1,2],["poolUsageTpl",2]],null,0,null,ou)),(t()(),s["\u0275and"](0,[[2,2],["activityTmpl",2]],null,0,null,uu))],function(t,e){t(e,4,0,e.component.selectedItem)},null)}var lu=function(){function t(t,e){this.cephfsService=t,this.i18n=e,this.filesystems=[],this.selection=new He.a}return t.prototype.ngOnInit=function(){this.columns=[{name:this.i18n("Name"),prop:"mdsmap.fs_name",flexGrow:2},{name:this.i18n("Created"),prop:"mdsmap.created",flexGrow:2},{name:this.i18n("Enabled"),prop:"mdsmap.enabled",flexGrow:1}]},t.prototype.loadFilesystems=function(t){var e=this;this.cephfsService.list().subscribe(function(t){e.filesystems=t},function(){t.error()})},t.prototype.updateSelection=function(t){this.selection=t},t}(),du=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function fu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","id"],["selectionType","single"]],null,[[null,"fetchData"],[null,"updateSelection"]],function(t,e,n){var a=!0,r=t.component;return"fetchData"===e&&(a=!1!==r.loadFilesystems(n)&&a),"updateSelection"===e&&(a=!1!==r.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](1,2867200,null,0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"]},{fetchData:"fetchData",updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](2,0,null,2,1,"cd-cephfs-detail",[["cdTableDetail",""]],null,null,null,cu,nu)),s["\u0275did"](3,638976,null,0,eu,[l.a,Zo,ht.a,gt.a,xt.a],{selection:[0,"selection"]},null)],function(t,e){var n=e.component;t(e,1,0,n.filesystems,n.columns,"flex","id","true","single"),t(e,3,0,n.selection)},null)}function pu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-cephfs-list",[],null,null,null,fu,du)),s["\u0275did"](1,114688,null,0,lu,[Zo,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var hu=s["\u0275ccf"]("cd-cephfs-list",lu,pu,{},{},[]),gu=function(){function t(t,e,n,a){this.route=t,this.summaryService=e,this.cephReleaseNamePipe=n,this.i18n=a,this.message=this.i18n("The NFS Ganesha service is not configured.")}return t.prototype.ngOnInit=function(){var t=this,e=this.summaryService.subscribe(function(n){if(n){var a=t.cephReleaseNamePipe.transform(n.version);t.docsUrl="http://docs.ceph.com/docs/"+a+"/mgr/dashboard/#configuring-nfs-ganesha-in-the-dashboard",setTimeout(function(){e.unsubscribe()},0)}});this.routeParamsSubscribe=this.route.params.subscribe(function(e){t.message=e.message})},t.prototype.ngOnDestroy=function(){this.routeParamsSubscribe.unsubscribe()},t}(),bu=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function mu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"cd-info-panel",[],null,null,null,ns.b,ns.a)),s["\u0275did"](1,49152,null,0,as.a,[xt.a],null,null),(t()(),s["\u0275ted"](2,0,[" ",""])),(t()(),s["\u0275eld"](3,0,null,0,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,0,4,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Please consult the "])),(t()(),s["\u0275eld"](6,0,null,null,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["documentation"])),(t()(),s["\u0275ted"](-1,null,[" on how to configure and enable the NFS Ganesha management functionality."]))],null,function(t,e){var n=e.component;t(e,2,0,n.message),t(e,6,0,s["\u0275inlineInterpolate"](1,"",n.docsUrl,""))})}function yu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-nfs-501",[],null,null,null,mu,bu)),s["\u0275did"](1,245760,null,0,gu,[tt.a,je.a,Ge.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var vu=s["\u0275ccf"]("cd-nfs-501",gu,yu,{},{},[]),_u=function(){function t(t){this.i18n=t,this.clients=[],this.clientsColumns=[{name:this.i18n("Addresses"),prop:"addresses",flexGrow:2},{name:this.i18n("Access Type"),prop:"access_type",flexGrow:1},{name:this.i18n("Squash"),prop:"squash",flexGrow:1}]}return t.prototype.ngOnChanges=function(){this.selection.hasSelection&&(this.selectedItem=this.selection.first(),this.clients=this.selectedItem.clients,this.data={},this.data[this.i18n("Cluster")]=this.selectedItem.cluster_id,this.data[this.i18n("Daemons")]=this.selectedItem.daemons,this.data[this.i18n("NFS Protocol")]=this.selectedItem.protocols.map(function(t){return"NFSv"+t}),this.data[this.i18n("Pseudo")]=this.selectedItem.pseudo,this.data[this.i18n("Access Type")]=this.selectedItem.access_type,this.data[this.i18n("Squash")]=this.selectedItem.squash,this.data[this.i18n("Transport")]=this.selectedItem.transports,this.data[this.i18n("Path")]=this.selectedItem.path,"CEPH"===this.selectedItem.fsal.name?(this.data[this.i18n("Storage Backend")]=this.i18n("CephFS"),this.data[this.i18n("CephFS User")]=this.selectedItem.fsal.user_id,this.data[this.i18n("CephFS Filesystem")]=this.selectedItem.fsal.fs_name,this.data[this.i18n("Security Label")]=this.selectedItem.fsal.sec_label_xattr):(this.data[this.i18n("Storage Backend")]=this.i18n("Object Gateway"),this.data[this.i18n("Object Gateway User")]=this.selectedItem.fsal.rgw_user_id))},t}(),xu=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Tu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,9,"tabset",[],[[2,"tab-container",null]],null,null,$.b,$.a)),s["\u0275did"](1,180224,null,0,Z.d,[Z.e,s.Renderer2,s.ElementRef],null,null),(t()(),s["\u0275eld"](2,0,null,0,3,"tab",[["heading","Details"]],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](3,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"cd-table-key-value",[],null,null,null,wn.b,wn.a)),s["\u0275did"](5,638976,null,0,Sn.a,[On.a],{data:[0,"data"]},null),(t()(),s["\u0275eld"](6,0,null,0,3,"tab",[],[[1,"id",0],[2,"active",null],[2,"tab-pane",null]],null,null,null,null)),s["\u0275did"](7,212992,null,0,Z.b,[Z.d,s.ElementRef,s.Renderer2],{heading:[0,"heading"]},null),(t()(),s["\u0275eld"](8,0,null,null,1,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","addresses"],["selectionType",""]],null,null,null,Ye.b,Ye.a)),s["\u0275did"](9,2867200,[["table",4]],0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"]},null)],function(t,e){var n=e.component;t(e,3,0,"Details"),t(e,5,0,n.data),t(e,7,0,s["\u0275inlineInterpolate"](1,"Clients (",n.clients.length,")")),t(e,9,0,n.clients,n.clientsColumns,"flex","addresses","true","")},function(t,e){t(e,0,0,s["\u0275nov"](e,1).clazz),t(e,2,0,s["\u0275nov"](e,3).id,s["\u0275nov"](e,3).active,s["\u0275nov"](e,3).addClass),t(e,6,0,s["\u0275nov"](e,7).id,s["\u0275nov"](e,7).active,s["\u0275nov"](e,7).addClass)})}function wu(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Tu)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,null==n.selection?null:n.selection.hasSingleSelection)},null)}var Su=n("VTlA"),Ou=n("ufoC"),Iu=function(){function t(t,e){this.http=t,this.i18n=e,this.apiPath="api/nfs-ganesha",this.uiApiPath="ui-api/nfs-ganesha",this.nfsAccessType=[{value:"RW",help:this.i18n("Allows all operations")},{value:"RO",help:this.i18n("Allows only operations that do not modify the server")},{value:"MDONLY",help:this.i18n("Does not allow read or write operations, but allows any other operation")},{value:"MDONLY_RO",help:this.i18n("Does not allow read, write, or any operation that modifies file attributes or directory content")},{value:"NONE",help:this.i18n("Allows no access at all")}],this.nfsFsal=[{value:"CEPH",descr:this.i18n("CephFS")},{value:"RGW",descr:this.i18n("Object Gateway")}],this.nfsSquash=["no_root_squash","root_id_squash","root_squash","all_squash"]}return t.prototype.list=function(){return this.http.get(this.apiPath+"/export")},t.prototype.get=function(t,e){return this.http.get(this.apiPath+"/export/"+t+"/"+e)},t.prototype.create=function(t){return this.http.post(this.apiPath+"/export",t,{observe:"response"})},t.prototype.update=function(t,e,n){return this.http.put(this.apiPath+"/export/"+t+"/"+e,n,{observe:"response"})},t.prototype.delete=function(t,e){return this.http.delete(this.apiPath+"/export/"+t+"/"+e,{observe:"response"})},t.prototype.lsDir=function(t){return this.http.get(this.uiApiPath+"/lsdir?root_dir="+t)},t.prototype.buckets=function(t){return this.http.get(this.uiApiPath+"/rgw/buckets?user_id="+t)},t.prototype.clients=function(){return this.http.get(this.uiApiPath+"/cephx/clients")},t.prototype.fsals=function(){return this.http.get(this.uiApiPath+"/fsals")},t.prototype.filesystems=function(){return this.http.get(this.uiApiPath+"/cephfs/filesystems")},t.prototype.daemon=function(){return this.http.get(this.apiPath+"/daemon")},t.prototype.start=function(t){return this.http.put(this.apiPath+"/service/"+t+"/start",null,{observe:"response"})},t.prototype.stop=function(t){return this.http.put(this.apiPath+"/service/"+t+"/stop",null,{observe:"response"})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c),s.inject(xt.a))},token:t,providedIn:Nt.a}),t}(),Cu=n("kvvV"),ku=n("kn/O"),Nu=function(){function t(t,e,n,a,r,i,s){var o=this;this.authStorageService=t,this.i18n=e,this.modalService=n,this.nfsService=a,this.taskListService=r,this.taskWrapper=i,this.actionLabels=s,this.selection=new He.a,this.isDefaultCluster=!1,this.builders={"nfs/create":function(t){return{path:t.path,cluster_id:t.cluster_id,fsal:t.fsal}}},this.permission=this.authStorageService.getPermissions().nfs,this.tableActions=[{permission:"create",icon:"fa-plus",routerLink:function(){return"/nfs/create"},canBePrimary:function(t){return!t.hasSingleSelection},name:this.actionLabels.CREATE},{permission:"update",icon:"fa-pencil",routerLink:function(){return"/nfs/edit/"+(o.selection.first()&&encodeURI(o.selection.first().cluster_id)+"/"+encodeURI(o.selection.first().export_id))},name:this.actionLabels.EDIT},{permission:"delete",icon:"fa-times",click:function(){return o.deleteNfsModal()},name:this.actionLabels.DELETE}]}return t.prototype.ngOnInit=function(){var t=this;this.columns=[{name:this.i18n("Path"),prop:"path",flexGrow:2,cellTransformation:cn.a.executing},{name:this.i18n("Pseudo"),prop:"pseudo",flexGrow:2},{name:this.i18n("Cluster"),prop:"cluster_id",flexGrow:2},{name:this.i18n("Daemons"),prop:"daemons",flexGrow:2},{name:this.i18n("Storage Backend"),prop:"fsal",flexGrow:2,cellTemplate:this.nfsFsal},{name:this.i18n("Access Type"),prop:"access_type",flexGrow:2}],this.nfsService.daemon().subscribe(function(e){var n=ft(e).map(function(t){return t.cluster_id}).uniq().value();t.isDefaultCluster=1===n.length&&"_default_"===n[0],t.columns[2].isHidden=t.isDefaultCluster,t.table&&t.table.updateColumns(),t.taskListService.init(function(){return t.nfsService.list()},function(e){return t.prepareResponse(e)},function(e){return t.exports=e},function(){return t.onFetchError()},t.taskFilter,t.itemFilter,t.builders)},function(){t.onFetchError()})},t.prototype.ngOnDestroy=function(){this.summaryDataSubscription&&this.summaryDataSubscription.unsubscribe()},t.prototype.prepareResponse=function(t){var e=[];return t.forEach(function(t){t.id=t.cluster_id+":"+t.export_id,t.state="LOADING",e=e.concat(t)}),e},t.prototype.onFetchError=function(){this.table.reset(),this.viewCacheStatus={status:Xo.a.ValueException}},t.prototype.itemFilter=function(t,e){return t.cluster_id===e.metadata.cluster_id&&t.export_id===e.metadata.export_id},t.prototype.taskFilter=function(t){return["nfs/create","nfs/delete","nfs/edit"].includes(t.name)},t.prototype.updateSelection=function(t){this.selection=t},t.prototype.deleteNfsModal=function(){var t=this,e=this.selection.first().cluster_id,n=this.selection.first().export_id;this.modalRef=this.modalService.show($n.a,{initialState:{itemDescription:this.i18n("NFS export"),itemNames:[e+":"+n],submitActionObservable:function(){return t.taskWrapper.wrapTaskAroundCall({task:new Cu.a("nfs/delete",{cluster_id:e,export_id:n}),call:t.nfsService.delete(e,n)})}}})},t}(),Ru=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Au(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CephFS"]))],null,null)}function Du(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Object Gateway"]))],null,null)}function Eu(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Au)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Du)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,"CEPH"===e.context.value.name),t(e,3,0,"RGW"===e.context.value.name)},null)}function Lu(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{nfsState:0}),s["\u0275qud"](402653184,2,{nfsFsal:0}),s["\u0275qud"](402653184,3,{table:0}),(t()(),s["\u0275eld"](3,0,null,null,6,"cd-table",[["columnMode","flex"],["forceIdentifier","true"],["identifier","id"],["selectionType","single"]],null,[[null,"updateSelection"]],function(t,e,n){var a=!0;return"updateSelection"===e&&(a=!1!==t.component.updateSelection(n)&&a),a},Ye.b,Ye.a)),s["\u0275did"](4,2867200,[[3,4],["table",4]],0,Ve.a,[s.NgZone,s.ChangeDetectorRef],{data:[0,"data"],columns:[1,"columns"],columnMode:[2,"columnMode"],identifier:[3,"identifier"],forceIdentifier:[4,"forceIdentifier"],selectionType:[5,"selectionType"]},{updateSelection:"updateSelection"}),(t()(),s["\u0275eld"](5,0,null,0,2,"div",[["class","table-actions btn-toolbar"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"cd-table-actions",[["class","btn-group"]],null,null,null,xn.b,xn.a)),s["\u0275did"](7,114688,null,0,Tn.a,[],{permission:[0,"permission"],selection:[1,"selection"],tableActions:[2,"tableActions"]},null),(t()(),s["\u0275eld"](8,0,null,2,1,"cd-nfs-details",[["cdTableDetail",""]],null,null,null,wu,xu)),s["\u0275did"](9,573440,null,0,_u,[xt.a],{selection:[0,"selection"]},null),(t()(),s["\u0275and"](0,[[2,2],["nfsFsal",2]],null,0,null,Eu))],function(t,e){var n=e.component;t(e,4,0,n.exports,n.columns,"flex","id","true","single"),t(e,7,0,n.permission,n.selection,n.tableActions),t(e,9,0,n.selection)},null)}function Pu(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-nfs-list",[],null,null,null,Lu,Ru)),s["\u0275prd"](131584,null,Su.a,Su.a,[Ou.a,je.a]),s["\u0275did"](2,245760,null,0,Nu,[l.a,xt.a,pa.b,Iu,Su.a,ku.a,Zn.b],null,null)],function(t,e){t(e,2,0)},null)}var Mu=s["\u0275ccf"]("cd-nfs-list",Nu,Pu,{},{},[]),qu=n("rpEJ"),ju=n("ihYY"),Fu=n("t9fZ"),zu=n("Gi3i"),Gu=n("15JJ"),Yu=n("psW0"),Vu=n("VnD/"),Hu=n("R+r5"),Bu=n("zrt+"),Uu=n("0/uQ"),Wu={"\xc1":"A","\u0102":"A","\u1eae":"A","\u1eb6":"A","\u1eb0":"A","\u1eb2":"A","\u1eb4":"A","\u01cd":"A","\xc2":"A","\u1ea4":"A","\u1eac":"A","\u1ea6":"A","\u1ea8":"A","\u1eaa":"A","\xc4":"A","\u01de":"A","\u0226":"A","\u01e0":"A","\u1ea0":"A","\u0200":"A","\xc0":"A","\u1ea2":"A","\u0202":"A","\u0100":"A","\u0104":"A","\xc5":"A","\u01fa":"A","\u1e00":"A","\u023a":"A","\xc3":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u1e02":"B","\u1e04":"B","\u0181":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0106":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0108":"C","\u010a":"C","\u0187":"C","\u023b":"C","\u010e":"D","\u1e10":"D","\u1e12":"D","\u1e0a":"D","\u1e0c":"D","\u018a":"D","\u1e0e":"D","\u01f2":"D","\u01c5":"D","\u0110":"D","\u018b":"D","\u01f1":"DZ","\u01c4":"DZ","\xc9":"E","\u0114":"E","\u011a":"E","\u0228":"E","\u1e1c":"E","\xca":"E","\u1ebe":"E","\u1ec6":"E","\u1ec0":"E","\u1ec2":"E","\u1ec4":"E","\u1e18":"E","\xcb":"E","\u0116":"E","\u1eb8":"E","\u0204":"E","\xc8":"E","\u1eba":"E","\u0206":"E","\u0112":"E","\u1e16":"E","\u1e14":"E","\u0118":"E","\u0246":"E","\u1ebc":"E","\u1e1a":"E","\ua76a":"ET","\u1e1e":"F","\u0191":"F","\u01f4":"G","\u011e":"G","\u01e6":"G","\u0122":"G","\u011c":"G","\u0120":"G","\u0193":"G","\u1e20":"G","\u01e4":"G","\u1e2a":"H","\u021e":"H","\u1e28":"H","\u0124":"H","\u2c67":"H","\u1e26":"H","\u1e22":"H","\u1e24":"H","\u0126":"H","\xcd":"I","\u012c":"I","\u01cf":"I","\xce":"I","\xcf":"I","\u1e2e":"I","\u0130":"I","\u1eca":"I","\u0208":"I","\xcc":"I","\u1ec8":"I","\u020a":"I","\u012a":"I","\u012e":"I","\u0197":"I","\u0128":"I","\u1e2c":"I","\ua779":"D","\ua77b":"F","\ua77d":"G","\ua782":"R","\ua784":"S","\ua786":"T","\ua76c":"IS","\u0134":"J","\u0248":"J","\u1e30":"K","\u01e8":"K","\u0136":"K","\u2c69":"K","\ua742":"K","\u1e32":"K","\u0198":"K","\u1e34":"K","\ua740":"K","\ua744":"K","\u0139":"L","\u023d":"L","\u013d":"L","\u013b":"L","\u1e3c":"L","\u1e36":"L","\u1e38":"L","\u2c60":"L","\ua748":"L","\u1e3a":"L","\u013f":"L","\u2c62":"L","\u01c8":"L","\u0141":"L","\u01c7":"LJ","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u0143":"N","\u0147":"N","\u0145":"N","\u1e4a":"N","\u1e44":"N","\u1e46":"N","\u01f8":"N","\u019d":"N","\u1e48":"N","\u0220":"N","\u01cb":"N","\xd1":"N","\u01ca":"NJ","\xd3":"O","\u014e":"O","\u01d1":"O","\xd4":"O","\u1ed0":"O","\u1ed8":"O","\u1ed2":"O","\u1ed4":"O","\u1ed6":"O","\xd6":"O","\u022a":"O","\u022e":"O","\u0230":"O","\u1ecc":"O","\u0150":"O","\u020c":"O","\xd2":"O","\u1ece":"O","\u01a0":"O","\u1eda":"O","\u1ee2":"O","\u1edc":"O","\u1ede":"O","\u1ee0":"O","\u020e":"O","\ua74a":"O","\ua74c":"O","\u014c":"O","\u1e52":"O","\u1e50":"O","\u019f":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\xd5":"O","\u1e4c":"O","\u1e4e":"O","\u022c":"O","\u01a2":"OI","\ua74e":"OO","\u0190":"E","\u0186":"O","\u0222":"OU","\u1e54":"P","\u1e56":"P","\ua752":"P","\u01a4":"P","\ua754":"P","\u2c63":"P","\ua750":"P","\ua758":"Q","\ua756":"Q","\u0154":"R","\u0158":"R","\u0156":"R","\u1e58":"R","\u1e5a":"R","\u1e5c":"R","\u0210":"R","\u0212":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua73e":"C","\u018e":"E","\u015a":"S","\u1e64":"S","\u0160":"S","\u1e66":"S","\u015e":"S","\u015c":"S","\u0218":"S","\u1e60":"S","\u1e62":"S","\u1e68":"S","\u0164":"T","\u0162":"T","\u1e70":"T","\u021a":"T","\u023e":"T","\u1e6a":"T","\u1e6c":"T","\u01ac":"T","\u1e6e":"T","\u01ae":"T","\u0166":"T","\u2c6f":"A","\ua780":"L","\u019c":"M","\u0245":"V","\ua728":"TZ","\xda":"U","\u016c":"U","\u01d3":"U","\xdb":"U","\u1e76":"U","\xdc":"U","\u01d7":"U","\u01d9":"U","\u01db":"U","\u01d5":"U","\u1e72":"U","\u1ee4":"U","\u0170":"U","\u0214":"U","\xd9":"U","\u1ee6":"U","\u01af":"U","\u1ee8":"U","\u1ef0":"U","\u1eea":"U","\u1eec":"U","\u1eee":"U","\u0216":"U","\u016a":"U","\u1e7a":"U","\u0172":"U","\u016e":"U","\u0168":"U","\u1e78":"U","\u1e74":"U","\ua75e":"V","\u1e7e":"V","\u01b2":"V","\u1e7c":"V","\ua760":"VY","\u1e82":"W","\u0174":"W","\u1e84":"W","\u1e86":"W","\u1e88":"W","\u1e80":"W","\u2c72":"W","\u1e8c":"X","\u1e8a":"X","\xdd":"Y","\u0176":"Y","\u0178":"Y","\u1e8e":"Y","\u1ef4":"Y","\u1ef2":"Y","\u01b3":"Y","\u1ef6":"Y","\u1efe":"Y","\u0232":"Y","\u024e":"Y","\u1ef8":"Y","\u0179":"Z","\u017d":"Z","\u1e90":"Z","\u2c6b":"Z","\u017b":"Z","\u1e92":"Z","\u0224":"Z","\u1e94":"Z","\u01b5":"Z","\u0132":"IJ","\u0152":"OE","\u1d00":"A","\u1d01":"AE","\u0299":"B","\u1d03":"B","\u1d04":"C","\u1d05":"D","\u1d07":"E","\ua730":"F","\u0262":"G","\u029b":"G","\u029c":"H","\u026a":"I","\u0281":"R","\u1d0a":"J","\u1d0b":"K","\u029f":"L","\u1d0c":"L","\u1d0d":"M","\u0274":"N","\u1d0f":"O","\u0276":"OE","\u1d10":"O","\u1d15":"OU","\u1d18":"P","\u0280":"R","\u1d0e":"N","\u1d19":"R","\ua731":"S","\u1d1b":"T","\u2c7b":"E","\u1d1a":"R","\u1d1c":"U","\u1d20":"V","\u1d21":"W","\u028f":"Y","\u1d22":"Z","\xe1":"a","\u0103":"a","\u1eaf":"a","\u1eb7":"a","\u1eb1":"a","\u1eb3":"a","\u1eb5":"a","\u01ce":"a","\xe2":"a","\u1ea5":"a","\u1ead":"a","\u1ea7":"a","\u1ea9":"a","\u1eab":"a","\xe4":"a","\u01df":"a","\u0227":"a","\u01e1":"a","\u1ea1":"a","\u0201":"a","\xe0":"a","\u1ea3":"a","\u0203":"a","\u0101":"a","\u0105":"a","\u1d8f":"a","\u1e9a":"a","\xe5":"a","\u01fb":"a","\u1e01":"a","\u2c65":"a","\xe3":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u1e03":"b","\u1e05":"b","\u0253":"b","\u1e07":"b","\u1d6c":"b","\u1d80":"b","\u0180":"b","\u0183":"b","\u0275":"o","\u0107":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0109":"c","\u0255":"c","\u010b":"c","\u0188":"c","\u023c":"c","\u010f":"d","\u1e11":"d","\u1e13":"d","\u0221":"d","\u1e0b":"d","\u1e0d":"d","\u0257":"d","\u1d91":"d","\u1e0f":"d","\u1d6d":"d","\u1d81":"d","\u0111":"d","\u0256":"d","\u018c":"d","\u0131":"i","\u0237":"j","\u025f":"j","\u0284":"j","\u01f3":"dz","\u01c6":"dz","\xe9":"e","\u0115":"e","\u011b":"e","\u0229":"e","\u1e1d":"e","\xea":"e","\u1ebf":"e","\u1ec7":"e","\u1ec1":"e","\u1ec3":"e","\u1ec5":"e","\u1e19":"e","\xeb":"e","\u0117":"e","\u1eb9":"e","\u0205":"e","\xe8":"e","\u1ebb":"e","\u0207":"e","\u0113":"e","\u1e17":"e","\u1e15":"e","\u2c78":"e","\u0119":"e","\u1d92":"e","\u0247":"e","\u1ebd":"e","\u1e1b":"e","\ua76b":"et","\u1e1f":"f","\u0192":"f","\u1d6e":"f","\u1d82":"f","\u01f5":"g","\u011f":"g","\u01e7":"g","\u0123":"g","\u011d":"g","\u0121":"g","\u0260":"g","\u1e21":"g","\u1d83":"g","\u01e5":"g","\u1e2b":"h","\u021f":"h","\u1e29":"h","\u0125":"h","\u2c68":"h","\u1e27":"h","\u1e23":"h","\u1e25":"h","\u0266":"h","\u1e96":"h","\u0127":"h","\u0195":"hv","\xed":"i","\u012d":"i","\u01d0":"i","\xee":"i","\xef":"i","\u1e2f":"i","\u1ecb":"i","\u0209":"i","\xec":"i","\u1ec9":"i","\u020b":"i","\u012b":"i","\u012f":"i","\u1d96":"i","\u0268":"i","\u0129":"i","\u1e2d":"i","\ua77a":"d","\ua77c":"f","\u1d79":"g","\ua783":"r","\ua785":"s","\ua787":"t","\ua76d":"is","\u01f0":"j","\u0135":"j","\u029d":"j","\u0249":"j","\u1e31":"k","\u01e9":"k","\u0137":"k","\u2c6a":"k","\ua743":"k","\u1e33":"k","\u0199":"k","\u1e35":"k","\u1d84":"k","\ua741":"k","\ua745":"k","\u013a":"l","\u019a":"l","\u026c":"l","\u013e":"l","\u013c":"l","\u1e3d":"l","\u0234":"l","\u1e37":"l","\u1e39":"l","\u2c61":"l","\ua749":"l","\u1e3b":"l","\u0140":"l","\u026b":"l","\u1d85":"l","\u026d":"l","\u0142":"l","\u01c9":"lj","\u017f":"s","\u1e9c":"s","\u1e9b":"s","\u1e9d":"s","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u1d6f":"m","\u1d86":"m","\u0144":"n","\u0148":"n","\u0146":"n","\u1e4b":"n","\u0235":"n","\u1e45":"n","\u1e47":"n","\u01f9":"n","\u0272":"n","\u1e49":"n","\u019e":"n","\u1d70":"n","\u1d87":"n","\u0273":"n","\xf1":"n","\u01cc":"nj","\xf3":"o","\u014f":"o","\u01d2":"o","\xf4":"o","\u1ed1":"o","\u1ed9":"o","\u1ed3":"o","\u1ed5":"o","\u1ed7":"o","\xf6":"o","\u022b":"o","\u022f":"o","\u0231":"o","\u1ecd":"o","\u0151":"o","\u020d":"o","\xf2":"o","\u1ecf":"o","\u01a1":"o","\u1edb":"o","\u1ee3":"o","\u1edd":"o","\u1edf":"o","\u1ee1":"o","\u020f":"o","\ua74b":"o","\ua74d":"o","\u2c7a":"o","\u014d":"o","\u1e53":"o","\u1e51":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\xf5":"o","\u1e4d":"o","\u1e4f":"o","\u022d":"o","\u01a3":"oi","\ua74f":"oo","\u025b":"e","\u1d93":"e","\u0254":"o","\u1d97":"o","\u0223":"ou","\u1e55":"p","\u1e57":"p","\ua753":"p","\u01a5":"p","\u1d71":"p","\u1d88":"p","\ua755":"p","\u1d7d":"p","\ua751":"p","\ua759":"q","\u02a0":"q","\u024b":"q","\ua757":"q","\u0155":"r","\u0159":"r","\u0157":"r","\u1e59":"r","\u1e5b":"r","\u1e5d":"r","\u0211":"r","\u027e":"r","\u1d73":"r","\u0213":"r","\u1e5f":"r","\u027c":"r","\u1d72":"r","\u1d89":"r","\u024d":"r","\u027d":"r","\u2184":"c","\ua73f":"c","\u0258":"e","\u027f":"r","\u015b":"s","\u1e65":"s","\u0161":"s","\u1e67":"s","\u015f":"s","\u015d":"s","\u0219":"s","\u1e61":"s","\u1e63":"s","\u1e69":"s","\u0282":"s","\u1d74":"s","\u1d8a":"s","\u023f":"s","\u0261":"g","\u1d11":"o","\u1d13":"o","\u1d1d":"u","\u0165":"t","\u0163":"t","\u1e71":"t","\u021b":"t","\u0236":"t","\u1e97":"t","\u2c66":"t","\u1e6b":"t","\u1e6d":"t","\u01ad":"t","\u1e6f":"t","\u1d75":"t","\u01ab":"t","\u0288":"t","\u0167":"t","\u1d7a":"th","\u0250":"a","\u1d02":"ae","\u01dd":"e","\u1d77":"g","\u0265":"h","\u02ae":"h","\u02af":"h","\u1d09":"i","\u029e":"k","\ua781":"l","\u026f":"m","\u0270":"m","\u1d14":"oe","\u0279":"r","\u027b":"r","\u027a":"r","\u2c79":"r","\u0287":"t","\u028c":"v","\u028d":"w","\u028e":"y","\ua729":"tz","\xfa":"u","\u016d":"u","\u01d4":"u","\xfb":"u","\u1e77":"u","\xfc":"u","\u01d8":"u","\u01da":"u","\u01dc":"u","\u01d6":"u","\u1e73":"u","\u1ee5":"u","\u0171":"u","\u0215":"u","\xf9":"u","\u1ee7":"u","\u01b0":"u","\u1ee9":"u","\u1ef1":"u","\u1eeb":"u","\u1eed":"u","\u1eef":"u","\u0217":"u","\u016b":"u","\u1e7b":"u","\u0173":"u","\u1d99":"u","\u016f":"u","\u0169":"u","\u1e79":"u","\u1e75":"u","\u1d6b":"ue","\ua778":"um","\u2c74":"v","\ua75f":"v","\u1e7f":"v","\u028b":"v","\u1d8c":"v","\u2c71":"v","\u1e7d":"v","\ua761":"vy","\u1e83":"w","\u0175":"w","\u1e85":"w","\u1e87":"w","\u1e89":"w","\u1e81":"w","\u2c73":"w","\u1e98":"w","\u1e8d":"x","\u1e8b":"x","\u1d8d":"x","\xfd":"y","\u0177":"y","\xff":"y","\u1e8f":"y","\u1ef5":"y","\u1ef3":"y","\u01b4":"y","\u1ef7":"y","\u1eff":"y","\u0233":"y","\u1e99":"y","\u024f":"y","\u1ef9":"y","\u017a":"z","\u017e":"z","\u1e91":"z","\u0291":"z","\u2c6c":"z","\u017c":"z","\u1e93":"z","\u0225":"z","\u1e95":"z","\u1d76":"z","\u1d8e":"z","\u0290":"z","\u01b6":"z","\u0240":"z","\ufb00":"ff","\ufb03":"ffi","\ufb04":"ffl","\ufb01":"fi","\ufb02":"fl","\u0133":"ij","\u0153":"oe","\ufb06":"st","\u2090":"a","\u2091":"e","\u1d62":"i","\u2c7c":"j","\u2092":"o","\u1d63":"r","\u1d64":"u","\u1d65":"v","\u2093":"x"},Ku=function(){function t(t,e,n){void 0===e&&(e=t),void 0===n&&(n=!1),this.item=t,this.value=e,this.header=n}return t.prototype.isHeader=function(){return this.header},t.prototype.toString=function(){return this.value},t}();function $u(t){return t?t.replace(/[^A-Za-z0-9\[\] ]/g,function(t){return Wu[t]||t}):""}function Zu(t,e,n){void 0===e&&(e=" "),void 0===n&&(n="");for(var a,r=t.split(new RegExp("(?:["+n+"])([^"+n+"]+)(?:["+n+"])|([^"+e+"]+)","g")),i=[],s=r.length,o=new RegExp("["+n+"]+","g"),u=0;u<s;u+=1)(a=r[u])&&a.length&&a!==e&&i.push(a.replace(o,""));return i}function Xu(t,e){var n,a;if(!e||"object"!=typeof t)return t.toString();if(e.endsWith("()"))return t[e.slice(0,e.length-2)]().toString();var r=e.replace(/\[(\w+)\]/g,".$1").replace(/^\./,"").split(".");try{for(var i=Object(p.__values)(r),s=i.next();!s.done;s=i.next()){var o=s.value;o in t&&(t=t[o])}}catch(u){n={error:u}}finally{try{s&&!s.done&&(a=i.return)&&a.call(i)}finally{if(n)throw n.error}}return t?t.toString():""}var Ju=function(){function t(t,e,n){this.positionService=t,this.renderer=e,this.element=n,this.isFocused=!1,this.visibility="hidden",this.height=0,this._matches=[],this.isScrolledIntoView=function(t){var e=this.ulElement.nativeElement.scrollTop,n=e+Number(this.ulElement.nativeElement.offsetHeight),a=t.offsetTop;return a+t.offsetHeight<=n&&a>=e}}return Object.defineProperty(t.prototype,"isBs4",{get:function(){return!Object(qu.d)()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"active",{get:function(){return this._active},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"matches",{get:function(){return this._matches},set:function(t){var e=this;if(this.positionService.setOptions({modifiers:{flip:{enabled:this.adaptivePosition}},allowedPositions:["top","bottom"]}),this.positionService.event$.pipe(Object(Fu.a)(1)).subscribe(function(){e.positionService.disable(),e.visibility=e.typeaheadScrollable?"hidden":"visible",e.animationState=e.isAnimated?e.isTopPosition?"animated-up":"animated-down":"unanimated"}),this._matches=t,this.needScrollbar=this.typeaheadScrollable&&this.typeaheadOptionsInScrollableView<this.matches.length,this.typeaheadScrollable&&setTimeout(function(){e.setScrollableMode()}),this.typeaheadIsFirstItemActive&&this._matches.length>0&&(this._active=this._matches[0],this._active.isHeader()&&this.nextActiveMatch()),this._active&&!this.typeaheadIsFirstItemActive){var n=this._matches.find(function(t){return t.value===e._active.value});if(n)return void this.selectActive(n);this._active=null}},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isTopPosition",{get:function(){return this.element.nativeElement.classList.contains("top")},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"optionsListTemplate",{get:function(){return this.parent?this.parent.optionsListTemplate:void 0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isAnimated",{get:function(){return!!this.parent&&this.parent.isAnimated},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"adaptivePosition",{get:function(){return!!this.parent&&this.parent.adaptivePosition},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"typeaheadScrollable",{get:function(){return!!this.parent&&this.parent.typeaheadScrollable},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"typeaheadOptionsInScrollableView",{get:function(){return this.parent?this.parent.typeaheadOptionsInScrollableView:5},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"typeaheadIsFirstItemActive",{get:function(){return!this.parent||this.parent.typeaheadIsFirstItemActive},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"itemTemplate",{get:function(){return this.parent?this.parent.typeaheadItemTemplate:void 0},enumerable:!0,configurable:!0}),t.prototype.selectActiveMatch=function(t){this._active&&this.parent.typeaheadSelectFirstItem&&this.selectMatch(this._active),!this.parent.typeaheadSelectFirstItem&&t&&this.selectMatch(this._active)},t.prototype.positionServiceEnable=function(){this.positionService.enable()},t.prototype.prevActiveMatch=function(){var t=this.matches.indexOf(this._active);this._active=this.matches[t-1<0?this.matches.length-1:t-1],this._active.isHeader()&&this.prevActiveMatch(),this.typeaheadScrollable&&this.scrollPrevious(t)},t.prototype.nextActiveMatch=function(){var t=this.matches.indexOf(this._active);this._active=this.matches[t+1>this.matches.length-1?0:t+1],this._active.isHeader()&&this.nextActiveMatch(),this.typeaheadScrollable&&this.scrollNext(t)},t.prototype.selectActive=function(t){this.isFocused=!0,this._active=t},t.prototype.highlight=function(t,e){var n,a,r=t.value,i=(this.parent&&this.parent.typeaheadLatinize?$u(r):r).toLowerCase();if("object"==typeof e)for(var s=e.length,o=0;o<s;o+=1)n=i.indexOf(e[o]),a=e[o].length,n>=0&&a>0&&(r=r.substring(0,n)+"<strong>"+r.substring(n,n+a)+"</strong>"+r.substring(n+a),i=i.substring(0,n)+" "+" ".repeat(a)+" "+i.substring(n+a));else e&&(n=i.indexOf(e),a=e.length,n>=0&&a>0&&(r=r.substring(0,n)+"<strong>"+r.substring(n,n+a)+"</strong>"+r.substring(n+a)));return r},t.prototype.focusLost=function(){this.isFocused=!1},t.prototype.isActive=function(t){return this._active===t},t.prototype.selectMatch=function(t,e){var n=this;return void 0===e&&(e=void 0),e&&(e.stopPropagation(),e.preventDefault()),this.parent.changeModel(t),setTimeout(function(){return n.parent.typeaheadOnSelect.emit(t)},0),!1},t.prototype.setScrollableMode=function(){if(this.ulElement||(this.ulElement=this.element),this.liElements.first){var t=qu.b.getStyles(this.ulElement.nativeElement),e=qu.b.getStyles(this.liElements.first.nativeElement),n=parseFloat((t["padding-bottom"]?t["padding-bottom"]:"").replace("px","")),a=parseFloat((t["padding-top"]?t["padding-top"]:"0").replace("px","")),r=parseFloat((e.height?e.height:"0").replace("px",""));this.guiHeight=this.typeaheadOptionsInScrollableView*r+a+n+"px"}this.renderer.setStyle(this.element.nativeElement,"visibility","visible")},t.prototype.scrollPrevious=function(t){if(0!==t){if(this.liElements){var e=this.liElements.toArray()[t-1];e&&!this.isScrolledIntoView(e.nativeElement)&&(this.ulElement.nativeElement.scrollTop=e.nativeElement.offsetTop)}}else this.scrollToBottom()},t.prototype.scrollNext=function(t){if(t+1>this.matches.length-1)this.scrollToTop();else if(this.liElements){var e=this.liElements.toArray()[t+1];e&&!this.isScrolledIntoView(e.nativeElement)&&(this.ulElement.nativeElement.scrollTop=e.nativeElement.offsetTop-Number(this.ulElement.nativeElement.offsetHeight)+Number(e.nativeElement.offsetHeight))}},t.prototype.scrollToBottom=function(){this.ulElement.nativeElement.scrollTop=this.ulElement.nativeElement.scrollHeight},t.prototype.scrollToTop=function(){this.ulElement.nativeElement.scrollTop=0},t}(),Qu=function(){return function(){this.adaptivePosition=!1,this.isAnimated=!1,this.hideResultsOnBlur=!0,this.selectFirstItem=!0,this.isFirstItemActive=!0,this.minLength=1}}(),tc=function(){function t(t,e,n,a,r,i,o){this.changeDetection=n,this.element=a,this.ngControl=r,this.renderer=i,this.typeaheadMinLength=void 0,this.isAnimated=!1,this.typeaheadAsync=void 0,this.typeaheadLatinize=!0,this.typeaheadSingleWords=!0,this.typeaheadWordDelimiters=" ",this.typeaheadPhraseDelimiters="'\"",this.typeaheadScrollable=!1,this.typeaheadOptionsInScrollableView=5,this.typeaheadSelectFirstItem=!0,this.typeaheadIsFirstItemActive=!0,this.typeaheadLoading=new s.EventEmitter,this.typeaheadNoResults=new s.EventEmitter,this.typeaheadOnSelect=new s.EventEmitter,this.typeaheadOnBlur=new s.EventEmitter,this.dropup=!1,this.isActiveItemChanged=!1,this.isTypeaheadOptionsListActive=!1,this.keyUpEventEmitter=new s.EventEmitter,this.placement="bottom-left",this._subscriptions=[],this._typeahead=t.createLoader(a,o,i).provide({provide:Qu,useValue:e}),Object.assign(this,{typeaheadHideResultsOnBlur:e.hideResultsOnBlur,typeaheadSelectFirstItem:e.selectFirstItem,typeaheadIsFirstItemActive:e.isFirstItemActive,typeaheadMinLength:e.minLength,adaptivePosition:e.adaptivePosition,isAnimated:e.isAnimated})}return t.prototype.ngOnInit=function(){this.typeaheadOptionsLimit=this.typeaheadOptionsLimit||20,this.typeaheadMinLength=void 0===this.typeaheadMinLength?1:this.typeaheadMinLength,this.typeaheadWaitMs=this.typeaheadWaitMs||0,void 0!==this.typeaheadAsync||Object(Bu.a)(this.typeahead)||(this.typeaheadAsync=!1),Object(Bu.a)(this.typeahead)&&(this.typeaheadAsync=!0),this.typeaheadAsync?this.asyncActions():this.syncActions()},t.prototype.onInput=function(t){var e=void 0!==t.target.value?t.target.value:void 0!==t.target.textContent?t.target.textContent:t.target.innerText;null!=e&&e.trim().length>=this.typeaheadMinLength?(this.typeaheadLoading.emit(!0),this.keyUpEventEmitter.emit(t.target.value)):(this.typeaheadLoading.emit(!1),this.typeaheadNoResults.emit(!1),this.hide())},t.prototype.onChange=function(t){if(this._container){if(27===t.keyCode||"Escape"===t.key)return void this.hide();if(38===t.keyCode||"ArrowUp"===t.key)return this.isActiveItemChanged=!0,void this._container.prevActiveMatch();if(40===t.keyCode||"ArrowDown"===t.key)return this.isActiveItemChanged=!0,void this._container.nextActiveMatch();if(13===t.keyCode||"Enter"===t.key)return void this._container.selectActiveMatch()}},t.prototype.onFocus=function(){0===this.typeaheadMinLength&&(this.typeaheadLoading.emit(!0),this.keyUpEventEmitter.emit(this.element.nativeElement.value||""))},t.prototype.onBlur=function(){this._container&&!this._container.isFocused&&this.typeaheadOnBlur.emit(this._container.active)},t.prototype.onKeydown=function(t){if(this._container&&(9===t.keyCode||"Tab"===t.key||13===t.keyCode||"Enter"===t.key)){if(t.preventDefault(),this.typeaheadSelectFirstItem)return void this._container.selectActiveMatch();this.typeaheadSelectFirstItem||(this._container.selectActiveMatch(this.isActiveItemChanged),this.isActiveItemChanged=!1,this.hide())}},t.prototype.changeModel=function(t){var e=t.value;this.ngControl.viewToModelUpdate(e),this.ngControl.control.setValue(e),this.changeDetection.markForCheck(),this.hide()},Object.defineProperty(t.prototype,"matches",{get:function(){return this._matches},enumerable:!0,configurable:!0}),t.prototype.show=function(){var t=this;this._typeahead.attach(Ju).to(this.container).position({attachment:(this.dropup?"top":"bottom")+" start"}).show({typeaheadRef:this,placement:this.placement,animation:!1,dropup:this.dropup}),this._outsideClickListener=this.renderer.listen("document","click",function(e){0===t.typeaheadMinLength&&t.element.nativeElement.contains(e.target)||t.typeaheadHideResultsOnBlur&&!t.element.nativeElement.contains(e.target)&&t.onOutsideClick()}),this._container=this._typeahead.instance,this._container.parent=this;var e=(this.typeaheadLatinize?$u(this.ngControl.control.value):this.ngControl.control.value).toString().toLowerCase();this._container.query=this.typeaheadSingleWords?Zu(e,this.typeaheadWordDelimiters,this.typeaheadPhraseDelimiters):e,this._container.matches=this._matches,this.element.nativeElement.focus()},t.prototype.hide=function(){this._typeahead.isShown&&(this._typeahead.hide(),this._outsideClickListener(),this._container=null)},t.prototype.onOutsideClick=function(){this._container&&!this._container.isFocused&&this.hide()},t.prototype.ngOnDestroy=function(){var t,e;try{for(var n=Object(p.__values)(this._subscriptions),a=n.next();!a.done;a=n.next())a.value.unsubscribe()}catch(r){t={error:r}}finally{try{a&&!a.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}this._typeahead.dispose()},t.prototype.asyncActions=function(){var t=this;this._subscriptions.push(this.keyUpEventEmitter.pipe(Object(zu.a)(this.typeaheadWaitMs),Object(Gu.a)(function(){return t.typeahead})).subscribe(function(e){t.finalizeAsyncCall(e)}))},t.prototype.syncActions=function(){var t=this;this._subscriptions.push(this.keyUpEventEmitter.pipe(Object(zu.a)(this.typeaheadWaitMs),Object(Yu.a)(function(e){var n=t.normalizeQuery(e);return Object(Uu.a)(t.typeahead).pipe(Object(Vu.a)(function(e){return e&&t.testMatch(t.normalizeOption(e),n)}),Object(Hu.a)())})).subscribe(function(e){t.finalizeAsyncCall(e)}))},t.prototype.normalizeOption=function(t){var e=Xu(t,this.typeaheadOptionField);return(this.typeaheadLatinize?$u(e):e).toLowerCase()},t.prototype.normalizeQuery=function(t){var e=(this.typeaheadLatinize?$u(t):t).toString().toLowerCase();return this.typeaheadSingleWords?Zu(e,this.typeaheadWordDelimiters,this.typeaheadPhraseDelimiters):e},t.prototype.testMatch=function(t,e){var n;if("object"==typeof e){n=e.length;for(var a=0;a<n;a+=1)if(e[a].length>0&&t.indexOf(e[a])<0)return!1;return!0}return t.indexOf(e)>=0},t.prototype.finalizeAsyncCall=function(t){if(this.prepareMatches(t||[]),this.typeaheadLoading.emit(!1),this.typeaheadNoResults.emit(!this.hasMatches()),this.hasMatches())if(this._container){var e=((this.typeaheadLatinize?$u(this.ngControl.control.value):this.ngControl.control.value)||"").toString().toLowerCase();this._container.query=this.typeaheadSingleWords?Zu(e,this.typeaheadWordDelimiters,this.typeaheadPhraseDelimiters):e,this._container.matches=this._matches}else this.show();else this.hide()},t.prototype.prepareMatches=function(t){var e=this,n=t.slice(0,this.typeaheadOptionsLimit);if(this.typeaheadGroupField){var a=[];n.map(function(t){return Xu(t,e.typeaheadGroupField)}).filter(function(t,e,n){return n.indexOf(t)===e}).forEach(function(t){a.push(new Ku(t,t,!0)),a=a.concat(n.filter(function(n){return Xu(n,e.typeaheadGroupField)===t}).map(function(t){return new Ku(t,Xu(t,e.typeaheadOptionField))}))}),this._matches=a}else this._matches=n.map(function(t){return new Ku(t,Xu(t,e.typeaheadOptionField))})},t.prototype.hasMatches=function(){return this._matches.length>0},t}(),ec=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[J.a,Q.a,Qu]}},t}(),nc=n("WiuZ"),ac=n("wnGv"),rc=n("TYzs"),ic=function(){function t(t,e){this.nfsService=t,this.i18n=e,this.nfsSquash=this.nfsService.nfsSquash,this.nfsAccessType=this.nfsService.nfsAccessType}return t.prototype.getNoAccessTypeDescr=function(){return this.form.getValue("access_type")?this.form.getValue("access_type")+" "+this.i18n("(inherited from global config)"):this.i18n("-- Select the access type --")},t.prototype.getAccessTypeHelp=function(t){var e=this,n=this.nfsAccessType.find(function(n){return e.getValue(t,"access_type")===n.value});return ft.isObjectLike(n)?n.help:""},t.prototype.getNoSquashDescr=function(){return this.form.getValue("squash")?this.form.getValue("squash")+" ("+this.i18n("inherited from global config")+")":this.i18n("-- Select what kind of user id squashing is performed --")},t.prototype.addClient=function(){var t=this.form.get("clients"),e=new na.a({addresses:new Te.i("",{validators:[Te.A.required,Te.A.pattern("(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3}).([0-9]{1,3})([/](\\d|[1-2]\\d|3[0-2]))?)([ ,]{1,2}(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3}).([0-9]{1,3})([/](\\d|[1-2]\\d|3[0-2]))?))*")]}),access_type:new Te.i(""),squash:new Te.i("")});return t.push(e),e},t.prototype.removeClient=function(t){this.form.get("clients").removeAt(t)},t.prototype.showError=function(t,e,n,a){return this.form.controls.clients.controls[t].showError(e,n,a)},t.prototype.getValue=function(t,e){return this.form.get("clients").at(t).getValue(e)},t.prototype.resolveModel=function(t){var e=this;ft.forEach(t,function(t){e.addClient().patchValue(t)})},t.prototype.trackByFn=function(t){return t},t}(),sc=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function oc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[["class","form-control no-border text-muted"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Any client can access"]))],null,null)}function uc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function cc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Must contain one or more comma-separated values"])),(t()(),s["\u0275eld"](3,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["For example:"])),(t()(),s["\u0275ted"](-1,null,[" 192.168.0.10, 192.168.1.0/8 "]))],null,null)}function lc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.value),t(e,2,0,e.context.$implicit.value)},function(t,e){t(e,3,0,e.context.$implicit.value)})}function dc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){t(e,1,0,e.component.getAccessTypeHelp(e.parent.context.index))})}function fc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function pc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,65,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,64,"div",[["class","panel panel-default"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),s["\u0275did"](2,212992,null,0,Te.m,[[3,Te.d],[8,null],[8,null]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.m]),s["\u0275did"](4,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](5,0,null,null,5,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,4,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,[""," "])),s["\u0275ppd"](8,1),(t()(),s["\u0275eld"](9,0,null,null,1,"span",[["class","pull-right clickable"],["tooltip","Remove"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.removeClient(t.context.index)&&a),a},null,null)),(t()(),s["\u0275ted"](-1,null,["\xd7"])),(t()(),s["\u0275eld"](11,0,null,null,54,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,17,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](13,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](14,{"has-error":0}),(t()(),s["\u0275eld"](15,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","addresses"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Addresses"])),(t()(),s["\u0275eld"](17,0,null,null,12,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,6,"input",[["class","form-control"],["formControlName","addresses"],["id","addresses"],["name","addresses"],["placeholder","192.168.0.10, 192.168.1.0/8"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,19)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,19).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](19,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](21,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](23,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](24,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](25,0,null,null,4,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,uc)),s["\u0275did"](27,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,cc)),s["\u0275did"](29,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](30,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](31,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","access_type"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Access Type"])),(t()(),s["\u0275eld"](33,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](34,0,null,null,12,"select",[["class","form-control"],["formControlName","access_type"],["id","access_type"],["name","access_type"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,35).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,35).onTouched()&&a),a},null,null)),s["\u0275did"](35,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](37,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](39,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](40,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](41,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](42,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](43,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](44,null,["",""])),(t()(),s["\u0275and"](16777216,null,null,1,null,lc)),s["\u0275did"](46,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,dc)),s["\u0275did"](48,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](49,0,null,null,16,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](50,0,null,null,1,"label",[["class","col-sm-3 control-label"],["for","squash"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Squash"])),(t()(),s["\u0275eld"](52,0,null,null,13,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](53,0,null,null,12,"select",[["class","form-control"],["formControlName","squash"],["id","squash"],["name","squash"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,54).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,54).onTouched()&&a),a},null,null)),s["\u0275did"](54,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](56,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](58,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](59,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](60,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](61,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](62,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](63,null,["",""])),(t()(),s["\u0275and"](16777216,null,null,1,null,fc)),s["\u0275did"](65,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,2,0,e.context.index);var a=t(e,14,0,n.showError(e.context.index,"addresses",s["\u0275nov"](e.parent,5)));t(e,13,0,"form-group",a),t(e,21,0,"addresses"),t(e,27,0,n.showError(e.context.index,"addresses",s["\u0275nov"](e.parent,5),"required")),t(e,29,0,n.showError(e.context.index,"addresses",s["\u0275nov"](e.parent,5),"pattern")),t(e,37,0,"access_type"),t(e,42,0,""),t(e,43,0,""),t(e,46,0,n.nfsAccessType),t(e,48,0,n.getValue(e.context.index,"access_type")),t(e,56,0,"squash"),t(e,61,0,""),t(e,62,0,""),t(e,65,0,n.nfsSquash)},function(t,e){var n=e.component;t(e,1,0,s["\u0275nov"](e,4).ngClassUntouched,s["\u0275nov"](e,4).ngClassTouched,s["\u0275nov"](e,4).ngClassPristine,s["\u0275nov"](e,4).ngClassDirty,s["\u0275nov"](e,4).ngClassValid,s["\u0275nov"](e,4).ngClassInvalid,s["\u0275nov"](e,4).ngClassPending);var a=s["\u0275unv"](e,7,0,t(e,8,0,s["\u0275nov"](e.parent,0),e.context.index+1));t(e,7,0,a),t(e,18,0,s["\u0275nov"](e,23).ngClassUntouched,s["\u0275nov"](e,23).ngClassTouched,s["\u0275nov"](e,23).ngClassPristine,s["\u0275nov"](e,23).ngClassDirty,s["\u0275nov"](e,23).ngClassValid,s["\u0275nov"](e,23).ngClassInvalid,s["\u0275nov"](e,23).ngClassPending),t(e,34,0,s["\u0275nov"](e,39).ngClassUntouched,s["\u0275nov"](e,39).ngClassTouched,s["\u0275nov"](e,39).ngClassPristine,s["\u0275nov"](e,39).ngClassDirty,s["\u0275nov"](e,39).ngClassValid,s["\u0275nov"](e,39).ngClassInvalid,s["\u0275nov"](e,39).ngClassPending),t(e,44,0,n.getNoAccessTypeDescr()),t(e,53,0,s["\u0275nov"](e,58).ngClassUntouched,s["\u0275nov"](e,58).ngClassTouched,s["\u0275nov"](e,58).ngClassPristine,s["\u0275nov"](e,58).ngClassDirty,s["\u0275nov"](e,58).ngClassValid,s["\u0275nov"](e,58).ngClassInvalid,s["\u0275nov"](e,58).ngClassPending),t(e,63,0,n.getNoSquashDescr())})}function hc(t){return s["\u0275vid"](0,[s["\u0275pid"](0,rc.a,[]),(t()(),s["\u0275eld"](1,0,null,null,20,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"label",[["class","col-sm-3 control-label"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Clients"])),(t()(),s["\u0275eld"](4,0,null,null,17,"div",[["class","col-sm-9"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,5).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,5).onReset()&&a),a},null,null)),s["\u0275did"](5,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](7,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,oc)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](10,0,null,null,5,null,null,null,null,null,null,null)),s["\u0275did"](11,212992,null,0,Te.g,[[3,Te.d],[8,null],[8,null]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.g]),s["\u0275did"](13,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,pc)),s["\u0275did"](15,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"],ngForTrackBy:[1,"ngForTrackBy"]},null),(t()(),s["\u0275eld"](16,0,null,null,4,"span",[["class","form-control no-border"]],null,null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,3,"button",[["class","btn btn-default btn-label pull-right"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.addClient()&&a),a},null,null)),(t()(),s["\u0275eld"](18,0,null,null,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Add clients"])),(t()(),s["\u0275eld"](21,0,null,null,0,"hr",[],null,null,null,null,null))],function(t,e){var n=e.component;t(e,5,0,n.form),t(e,9,0,0===n.form.get("clients").value.length),t(e,11,0,"clients"),t(e,15,0,n.form.get("clients").value,n.trackByFn)},function(t,e){t(e,4,0,s["\u0275nov"](e,7).ngClassUntouched,s["\u0275nov"](e,7).ngClassTouched,s["\u0275nov"](e,7).ngClassPristine,s["\u0275nov"](e,7).ngClassDirty,s["\u0275nov"](e,7).ngClassValid,s["\u0275nov"](e,7).ngClassInvalid,s["\u0275nov"](e,7).ngClassPending)})}var gc=n("F/XL"),bc=n("P8lu"),mc=n("DNAf"),yc=n("a96k"),vc=function(){function t(t,e,n,a,r,i,s,o,u,c,l,d){var f=this;this.authStorageService=t,this.nfsService=e,this.route=n,this.router=a,this.rgwUserService=r,this.formBuilder=i,this.summaryservice=s,this.cephReleaseNamePipe=o,this.taskWrapper=u,this.cdRef=c,this.i18n=l,this.actionLabels=d,this.isEdit=!1,this.cluster_id=null,this.export_id=null,this.isNewDirectory=!1,this.isNewBucket=!1,this.isDefaultCluster=!1,this.allClusters=null,this.allDaemons={},this.allFsals=[],this.allRgwUsers=[],this.allCephxClients=null,this.allFsNames=null,this.defaultAccessType={RGW:"RO"},this.nfsAccessType=this.nfsService.nfsAccessType,this.nfsSquash=this.nfsService.nfsSquash,this.daemonsSelections=[],this.daemonsMessages=new mc.a({noOptions:this.i18n("There are no daemons available.")},this.i18n),this.pathDataSource=ds.a.create(function(t){t.next(f.nfsForm.getValue("path"))}).pipe(Object(Yu.a)(function(t){return f.getPathTypeahead(t)}),Object(Bi.a)(function(t){return t.paths})),this.bucketDataSource=ds.a.create(function(t){t.next(f.nfsForm.getValue("path"))}).pipe(Object(Yu.a)(function(t){return f.getBucketTypeahead(t)})),this.permission=this.authStorageService.getPermissions().pool,this.resource=this.i18n("NFS export"),this.createForm()}return t.prototype.ngOnInit=function(){var t=this,e=[this.nfsService.daemon(),this.nfsService.fsals(),this.nfsService.clients(),this.nfsService.filesystems()];this.router.url.startsWith("/nfs/edit")&&(this.isEdit=!0),this.isEdit?(this.action=this.actionLabels.EDIT,this.route.params.subscribe(function(n){t.cluster_id=decodeURIComponent(n.cluster_id),t.export_id=decodeURIComponent(n.export_id),e.push(t.nfsService.get(t.cluster_id,t.export_id)),t.getData(e)}),this.nfsForm.get("cluster_id").disable()):(this.action=this.actionLabels.CREATE,this.getData(e));var n=this.summaryservice.getCurrentSummary(),a=this.cephReleaseNamePipe.transform(n.version);this.docsUrl="http://docs.ceph.com/docs/"+a+"/radosgw/nfs/"},t.prototype.getData=function(t){var e=this;Object(ta.a)(t).subscribe(function(t){e.resolveDaemons(t[0]),e.resolvefsals(t[1]),e.resolveClients(t[2]),e.resolveFilesystems(t[3]),t[4]&&e.resolveModel(t[4])})},t.prototype.createForm=function(){this.nfsForm=new na.a({cluster_id:new Te.i("",{validators:[Te.A.required]}),daemons:new Te.i([]),fsal:new na.a({name:new Te.i("",{validators:[Te.A.required]}),user_id:new Te.i("",{validators:[aa.a.requiredIf({name:"CEPH"})]}),fs_name:new Te.i("",{validators:[aa.a.requiredIf({name:"CEPH"})]}),rgw_user_id:new Te.i("",{validators:[aa.a.requiredIf({name:"RGW"})]})}),path:new Te.i(""),protocolNfsv3:new Te.i(!0,{validators:[aa.a.requiredIf({protocolNfsv4:!1},function(t){return!t})]}),protocolNfsv4:new Te.i(!0,{validators:[aa.a.requiredIf({protocolNfsv3:!1},function(t){return!t})]}),tag:new Te.i(""),pseudo:new Te.i("",{validators:[aa.a.requiredIf({protocolNfsv4:!0}),Te.A.pattern("^/[^><|&()]*$")]}),access_type:new Te.i("RW",{validators:[Te.A.required]}),squash:new Te.i("",{validators:[Te.A.required]}),transportUDP:new Te.i(!0,{validators:[aa.a.requiredIf({transportTCP:!1},function(t){return!t})]}),transportTCP:new Te.i(!0,{validators:[aa.a.requiredIf({transportUDP:!1},function(t){return!t})]}),clients:this.formBuilder.array([]),security_label:new Te.i(!1),sec_label_xattr:new Te.i("security.selinux",aa.a.requiredIf({security_label:!0,"fsal.name":"CEPH"}))})},t.prototype.resolveModel=function(t){"CEPH"===t.fsal.name&&(t.sec_label_xattr=t.fsal.sec_label_xattr),this.daemonsSelections=ft.map(this.allDaemons[t.cluster_id],function(e){return new yc.a(-1!==t.daemons.indexOf(e),e,"")}),this.daemonsSelections=this.daemonsSelections.slice(),t.protocolNfsv3=-1!==t.protocols.indexOf(3),t.protocolNfsv4=-1!==t.protocols.indexOf(4),delete t.protocols,t.transportTCP=-1!==t.transports.indexOf("TCP"),t.transportUDP=-1!==t.transports.indexOf("UDP"),delete t.transports,t.clients.forEach(function(t){var e="";t.addresses.forEach(function(t){e+=t+", "}),e.length>=2&&(e=e.substring(0,e.length-2)),t.addresses=e}),this.nfsForm.patchValue(t),this.setPathValidation(),this.nfsClients.resolveModel(t.clients)},t.prototype.resolveDaemons=function(t){var e=this;t=ft.sortBy(t,["daemon_id"]),this.allClusters=ft(t).map(function(t){return t.cluster_id}).sortedUniq().value(),ft.forEach(this.allClusters,function(t){e.allDaemons[t]=[]}),ft.forEach(t,function(t){e.allDaemons[t.cluster_id].push(t.daemon_id)});var n=ft.isArray(this.allClusters)&&1===this.allClusters.length;this.isDefaultCluster=n&&"_default_"===this.allClusters[0],n&&(this.nfsForm.patchValue({cluster_id:this.allClusters[0]}),this.onClusterChange())},t.prototype.resolvefsals=function(t){var e=this;t.forEach(function(t){var n=e.nfsService.nfsFsal.find(function(e){return t===e.value});ft.isObjectLike(n)&&(e.allFsals.push(n),"RGW"===n.value&&e.rgwUserService.list().subscribe(function(t){t.forEach(function(t){0===t.suspended&&t.keys.length>0&&e.allRgwUsers.push(t.user_id)})}))}),1===this.allFsals.length&&ft.isUndefined(this.nfsForm.getValue("fsal"))&&this.nfsForm.patchValue({fsal:this.allFsals[0]})},t.prototype.resolveClients=function(t){this.allCephxClients=t},t.prototype.resolveFilesystems=function(t){this.allFsNames=t,1===t.length&&this.nfsForm.patchValue({fsal:{fs_name:t[0].name}})},t.prototype.fsalChangeHandler=function(){this.nfsForm.patchValue({tag:this._generateTag(),pseudo:this._generatePseudo(),access_type:this._updateAccessType()}),this.setPathValidation(),this.cdRef.detectChanges()},t.prototype.accessTypeChangeHandler=function(){var t=this.nfsForm.getValue("name"),e=this.nfsForm.getValue("access_type");this.defaultAccessType[t]=e},t.prototype.setPathValidation=function(){"RGW"===this.nfsForm.getValue("name")?this.nfsForm.get("path").setValidators([Te.A.required,Te.A.pattern("^(/|[^/><|&()#?]+)$")]):this.nfsForm.get("path").setValidators([Te.A.required,Te.A.pattern("^/[^><|&()?]*$")])},t.prototype.rgwUserIdChangeHandler=function(){this.nfsForm.patchValue({pseudo:this._generatePseudo()})},t.prototype.getAccessTypeHelp=function(t){var e=this.nfsAccessType.find(function(e){if(t===e.value)return e});return ft.isObjectLike(e)?e.help:""},t.prototype.getId=function(){return ft.isString(this.nfsForm.getValue("cluster_id"))&&ft.isString(this.nfsForm.getValue("path"))?this.nfsForm.getValue("cluster_id")+":"+this.nfsForm.getValue("path"):""},t.prototype.getPathTypeahead=function(t){return ft.isString(t)&&"/"!==t?this.nfsService.lsDir(t):Object(gc.a)([])},t.prototype.pathChangeHandler=function(){var t=this;this.nfsForm.patchValue({pseudo:this._generatePseudo()});var e=this.nfsForm.getValue("path");this.getPathTypeahead(e).subscribe(function(n){t.isNewDirectory="/"!==e&&-1===n.paths.indexOf(e)})},t.prototype.bucketChangeHandler=function(){var t=this;this.nfsForm.patchValue({tag:this._generateTag(),pseudo:this._generatePseudo()});var e=this.nfsForm.getValue("path");this.getBucketTypeahead(e).subscribe(function(n){t.isNewBucket=""!==e&&-1===n.indexOf(e)})},t.prototype.getBucketTypeahead=function(t){var e=this.nfsForm.getValue("rgw_user_id");return ft.isString(e)&&ft.isString(t)&&"/"!==t&&""!==t?this.nfsService.buckets(e):Object(gc.a)([])},t.prototype._generateTag=function(){var t=this.nfsForm.getValue("tag");return this.nfsForm.get("tag").dirty||(t=void 0,"RGW"===this.nfsForm.getValue("fsal")&&(t=this.nfsForm.getValue("path"))),t},t.prototype._generatePseudo=function(){var t=this.nfsForm.getValue("pseudo");return this.nfsForm.get("pseudo")&&!this.nfsForm.get("pseudo").dirty&&(t=void 0,"CEPH"===this.nfsForm.getValue("fsal")?(t="/cephfs",ft.isString(this.nfsForm.getValue("path"))&&(t+=this.nfsForm.getValue("path"))):"RGW"===this.nfsForm.getValue("fsal")&&ft.isString(this.nfsForm.getValue("rgw_user_id"))&&(t="/"+this.nfsForm.getValue("rgw_user_id"),ft.isString(this.nfsForm.getValue("path"))&&(t+="/"+this.nfsForm.getValue("path")))),t},t.prototype._updateAccessType=function(){var t=this.nfsForm.getValue("name"),e=this.defaultAccessType[t];return e||(e="RW"),e},t.prototype.onClusterChange=function(){var t=this.nfsForm.getValue("cluster_id");this.daemonsSelections=ft.map(this.allDaemons[t],function(t){return new yc.a(!1,t,"")}),this.daemonsSelections=this.daemonsSelections.slice(),this.nfsForm.patchValue({daemons:[]})},t.prototype.removeDaemon=function(t,e){this.daemonsSelections.forEach(function(t){t.name===e&&(t.selected=!1)});var n=this.nfsForm.get("daemons");return n.value.splice(t,1),n.setValue(n.value),!1},t.prototype.onDaemonSelection=function(){this.nfsForm.get("daemons").setValue(this.nfsForm.getValue("daemons"))},t.prototype.submitAction=function(){var t=this,e=this._buildRequest();this.taskWrapper.wrapTaskAroundCall(this.isEdit?{task:new Cu.a("nfs/edit",{cluster_id:this.cluster_id,export_id:this.export_id}),call:this.nfsService.update(this.cluster_id,this.export_id,e)}:{task:new Cu.a("nfs/create",{path:e.path,fsal:e.fsal,cluster_id:e.cluster_id}),call:this.nfsService.create(e)}).subscribe(void 0,function(){return t.nfsForm.setErrors({cdSubmitButton:!0})},function(){return t.router.navigate(["/nfs"])})},t.prototype._buildRequest=function(){var t=ft.cloneDeep(this.nfsForm.value);return(ft.isUndefined(t.tag)||""===t.tag)&&(t.tag=null),this.isEdit&&(t.export_id=this.export_id),"CEPH"===t.fsal.name?delete t.fsal.rgw_user_id:(delete t.fsal.fs_name,delete t.fsal.user_id),t.protocols=[],t.protocolNfsv3?t.protocols.push(3):t.tag=null,delete t.protocolNfsv3,t.protocolNfsv4?t.protocols.push(4):t.pseudo=null,delete t.protocolNfsv4,t.transports=[],t.transportTCP&&t.transports.push("TCP"),delete t.transportTCP,t.transportUDP&&t.transports.push("UDP"),delete t.transportUDP,t.clients.forEach(function(e){e.addresses=ft.isString(e.addresses)?ft(e.addresses).split(/[ ,]+/).uniq().filter(function(t){return""!==t}).value():[],e.squash||(e.squash=t.squash),e.access_type||(e.access_type=t.access_type)}),t.fsal.sec_label_xattr=!1===t.security_label||"RGW"===t.fsal.name?null:t.sec_label_xattr,delete t.sec_label_xattr,t},t}(),_c=s["\u0275crt"]({encapsulation:0,styles:[[".cd-mb[_ngcontent-%COMP%]{margin-bottom:10px}"]],data:{}});function xc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Tc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No cluster available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function wc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the cluster --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Sc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function Oc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Ic(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","cluster_id"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Cluster"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,14,"select",[["class","form-control"],["formControlName","cluster_id"],["id","cluster_id"],["name","cluster_id"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,9).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),"change"===e&&(a=!1!==r.onClusterChange()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,xc)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Tc)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,wc)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Sc)),s["\u0275did"](22,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Oc)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("cluster_id",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"cluster_id"),t(e,16,0,null===n.allClusters),t(e,18,0,null!==n.allClusters&&0===n.allClusters.length),t(e,20,0,null!==n.allClusters&&n.allClusters.length>0),t(e,22,0,n.allClusters),t(e,24,0,n.nfsForm.showError("cluster_id",s["\u0275nov"](e.parent,6),"required"))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function Cc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,5,"div",[["class","input-group cd-mb"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"input",[["class","form-control"],["disabled",""],["type","text"]],[[8,"value",0]],null,null,null,null)),s["\u0275did"](3,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](4,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,1,"button",[["class","btn btn-default"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.removeDaemon(t.context.index,t.context.$implicit)&&a),a},null,null)),(t()(),s["\u0275eld"](6,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-remove fa-fw"]],null,null,null,null,null))],null,function(t,e){t(e,2,0,e.context.$implicit)})}function kc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Nc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No data pools available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Rc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the storage backend --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Ac(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.value),t(e,2,0,e.context.$implicit.value)},function(t,e){t(e,3,0,e.context.$implicit.descr)})}function Dc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Ec(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Lc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No users available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Pc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the object gateway user --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Mc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function qc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function jc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","rgw_user_id"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Object Gateway User"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,14,"select",[["class","form-control"],["formControlName","rgw_user_id"],["id","rgw_user_id"],["name","rgw_user_id"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,9).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),"change"===e&&(a=!1!==r.rgwUserIdChangeHandler()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ec)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Lc)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Pc)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Mc)),s["\u0275did"](22,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,qc)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("rgw_user_id",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"rgw_user_id"),t(e,16,0,null===n.allRgwUsers),t(e,18,0,null!==n.allRgwUsers&&0===n.allRgwUsers.length),t(e,20,0,null!==n.allRgwUsers&&n.allRgwUsers.length>0),t(e,22,0,n.allRgwUsers),t(e,24,0,n.nfsForm.showError("rgw_user_id",s["\u0275nov"](e.parent,6),"required"))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function Fc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function zc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No clients available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Gc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the cephx client --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Yc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function Vc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Hc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","user_id"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CephFS User ID"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,14,"select",[["class","form-control"],["formControlName","user_id"],["id","user_id"],["name","user_id"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,9).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Fc)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,zc)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Gc)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Yc)),s["\u0275did"](22,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Vc)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("user_id",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"user_id"),t(e,16,0,null===n.allCephxClients),t(e,18,0,null!==n.allCephxClients&&0===n.allCephxClients.length),t(e,20,0,null!==n.allCephxClients&&n.allCephxClients.length>0),t(e,22,0,n.allCephxClients),t(e,24,0,n.nfsForm.showError("user_id",s["\u0275nov"](e.parent,6),"required"))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function Bc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Uc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No CephFS filesystem available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Wc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the CephFS filesystem --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Kc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.name),t(e,2,0,e.context.$implicit.name)},function(t,e){t(e,3,0,e.context.$implicit.name)})}function $c(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Zc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","fs_name"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CephFS Name"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,14,"select",[["class","form-control"],["formControlName","fs_name"],["id","fs_name"],["name","fs_name"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,9).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),"change"===e&&(a=!1!==r.rgwUserIdChangeHandler()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Bc)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Uc)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Wc)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Kc)),s["\u0275did"](22,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,$c)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("fs_name",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"fs_name"),t(e,16,0,null===n.allFsNames),t(e,18,0,null!==n.allFsNames&&0===n.allFsNames.length),t(e,20,0,null!==n.allFsNames&&n.allFsNames.length>0),t(e,22,0,n.allFsNames),t(e,24,0,n.nfsForm.showError("fs_name",s["\u0275nov"](e.parent,6),"required"))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function Xc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function Jc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"input",[["class","form-control"],["formControlName","sec_label_xattr"],["id","sec_label_xattr"],["name","sec_label_xattr"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,1)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,1).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,1)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,1)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](1,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](3,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](5,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](6,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],function(t,e){t(e,3,0,"sec_label_xattr")},function(t,e){t(e,0,0,s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending)})}function Qc(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function tl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,23,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,4,"label",[["class","col-sm-3 control-label"],["for","security_label"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Security Label"])),(t()(),s["\u0275and"](16777216,null,null,1,null,Xc)),s["\u0275did"](7,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](8,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,6,"input",[["formControlName","security_label"],["id","security_label"],["name","security_label"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,11).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,11).onTouched()&&a),a},null,null)),s["\u0275did"](11,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](13,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](15,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](16,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](17,0,null,null,1,"label",[["for","security_label"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Enable security label"])),(t()(),s["\u0275eld"](19,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Jc)),s["\u0275did"](21,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Qc)),s["\u0275did"](23,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("security_label",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,7,0,n.nfsForm.getValue("security_label")),t(e,13,0,"security_label"),t(e,21,0,n.nfsForm.getValue("security_label")),t(e,23,0,n.nfsForm.showError("sec_label_xattr",s["\u0275nov"](e.parent,6),"required"))},function(t,e){t(e,10,0,s["\u0275nov"](e,15).ngClassUntouched,s["\u0275nov"](e,15).ngClassTouched,s["\u0275nov"](e,15).ngClassPristine,s["\u0275nov"](e,15).ngClassDirty,s["\u0275nov"](e,15).ngClassValid,s["\u0275nov"](e,15).ngClassInvalid,s["\u0275nov"](e,15).ngClassPending)})}function el(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function nl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Path need to start with a '/' and can be followed by a word"]))],null,null)}function al(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["New directory will be created"]))],null,null)}function rl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,21,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","path"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CephFS Path"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,14,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,16777216,null,null,7,"input",[["class","form-control"],["formControlName","path"],["id","path"],["name","path"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"typeaheadOnSelect"],[null,"blur"],[null,"input"],[null,"compositionstart"],[null,"compositionend"],[null,"keyup"],[null,"click"],[null,"focus"],[null,"keydown"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,9)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,9)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,9)._compositionEnd(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,15).onInput(n)&&a),"keyup"===e&&(a=!1!==s["\u0275nov"](t,15).onChange(n)&&a),"click"===e&&(a=!1!==s["\u0275nov"](t,15).onFocus()&&a),"focus"===e&&(a=!1!==s["\u0275nov"](t,15).onFocus()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,15).onBlur()&&a),"keydown"===e&&(a=!1!==s["\u0275nov"](t,15).onKeydown(n)&&a),"typeaheadOnSelect"===e&&(a=!1!==r.pathChangeHandler()&&a),"blur"===e&&(a=!1!==r.pathChangeHandler()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](15,212992,null,0,tc,[J.a,Qu,s.ChangeDetectorRef,s.ElementRef,Te.q,s.Renderer2,s.ViewContainerRef],{typeahead:[0,"typeahead"]},{typeaheadOnSelect:"typeaheadOnSelect"}),(t()(),s["\u0275and"](16777216,null,null,1,null,el)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,nl)),s["\u0275did"](19,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,al)),s["\u0275did"](21,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"path"),t(e,15,0,n.pathDataSource),t(e,17,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6),"required")),t(e,19,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6),"pattern")),t(e,21,0,n.isNewDirectory&&!n.nfsForm.showError("path",s["\u0275nov"](e.parent,6)))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function il(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function sl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Path can only be a single '/' or a word"]))],null,null)}function ol(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["New bucket will be created"]))],null,null)}function ul(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,21,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","path"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Path"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,14,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,16777216,null,null,7,"input",[["class","form-control"],["formControlName","path"],["id","path"],["name","path"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"typeaheadOnSelect"],[null,"blur"],[null,"input"],[null,"compositionstart"],[null,"compositionend"],[null,"keyup"],[null,"click"],[null,"focus"],[null,"keydown"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,9)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,9).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,9)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,9)._compositionEnd(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,15).onInput(n)&&a),"keyup"===e&&(a=!1!==s["\u0275nov"](t,15).onChange(n)&&a),"click"===e&&(a=!1!==s["\u0275nov"](t,15).onFocus()&&a),"focus"===e&&(a=!1!==s["\u0275nov"](t,15).onFocus()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,15).onBlur()&&a),"keydown"===e&&(a=!1!==s["\u0275nov"](t,15).onKeydown(n)&&a),"typeaheadOnSelect"===e&&(a=!1!==r.bucketChangeHandler()&&a),"blur"===e&&(a=!1!==r.bucketChangeHandler()&&a),a},null,null)),s["\u0275did"](9,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](11,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](13,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](14,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](15,212992,null,0,tc,[J.a,Qu,s.ChangeDetectorRef,s.ElementRef,Te.q,s.Renderer2,s.ViewContainerRef],{typeahead:[0,"typeahead"]},{typeaheadOnSelect:"typeaheadOnSelect"}),(t()(),s["\u0275and"](16777216,null,null,1,null,il)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,sl)),s["\u0275did"](19,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ol)),s["\u0275did"](21,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,11,0,"path"),t(e,15,0,n.bucketDataSource),t(e,17,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6),"required")),t(e,19,0,n.nfsForm.showError("path",s["\u0275nov"](e.parent,6),"pattern")),t(e,21,0,n.isNewBucket&&!n.nfsForm.showError("path",s["\u0275nov"](e.parent,6)))},function(t,e){t(e,8,0,s["\u0275nov"](e,13).ngClassUntouched,s["\u0275nov"](e,13).ngClassTouched,s["\u0275nov"](e,13).ngClassPristine,s["\u0275nov"](e,13).ngClassDirty,s["\u0275nov"](e,13).ngClassValid,s["\u0275nov"](e,13).ngClassInvalid,s["\u0275nov"](e,13).ngClassPending)})}function cl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function ll(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,13,"label",[["class","col-sm-3 control-label"],["for","tag"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFS Tag"])),(t()(),s["\u0275eld"](4,0,null,null,10,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](5,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275eld"](6,0,null,0,4,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Alternative access for "])),(t()(),s["\u0275eld"](8,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFS v3"])),(t()(),s["\u0275ted"](-1,null,[" mounts (it must not have a leading /)."])),(t()(),s["\u0275eld"](11,0,null,0,1,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz)."])),(t()(),s["\u0275eld"](13,0,null,0,1,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["By using different Tag options, the same Path may be exported multiple times."])),(t()(),s["\u0275eld"](15,0,null,null,7,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](16,0,null,null,6,"input",[["class","form-control"],["formControlName","tag"],["id","tag"],["name","tag"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,17)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,17).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,17)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,17)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](17,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](19,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](21,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](22,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],function(t,e){t(e,19,0,"tag")},function(t,e){t(e,16,0,s["\u0275nov"](e,21).ngClassUntouched,s["\u0275nov"](e,21).ngClassTouched,s["\u0275nov"](e,21).ngClassPristine,s["\u0275nov"](e,21).ngClassDirty,s["\u0275nov"](e,21).ngClassValid,s["\u0275nov"](e,21).ngClassInvalid,s["\u0275nov"](e,21).ngClassPending)})}function dl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function fl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Pseudo needs to start with a '/' and can't contain any of the following: >, <, |, &, ( or )."]))],null,null)}function pl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,30,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,15,"label",[["class","col-sm-3 control-label"],["for","pseudo"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Pseudo"])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,11,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](8,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275eld"](9,0,null,0,7,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The position that this "])),(t()(),s["\u0275eld"](11,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFS v4"])),(t()(),s["\u0275ted"](-1,null,[" export occupies in the "])),(t()(),s["\u0275eld"](14,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Pseudo FS"])),(t()(),s["\u0275ted"](-1,null,[" (it must be unique)."])),(t()(),s["\u0275eld"](17,0,null,0,1,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["By using different Pseudo options, the same Path may be exported multiple times."])),(t()(),s["\u0275eld"](19,0,null,null,11,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](20,0,null,null,6,"input",[["class","form-control"],["formControlName","pseudo"],["id","pseudo"],["name","pseudo"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,21)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,21).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,21)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,21)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](21,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](23,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](25,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](26,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,dl)),s["\u0275did"](28,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,fl)),s["\u0275did"](30,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.nfsForm.showError("pseudo",s["\u0275nov"](e.parent,6)));t(e,1,0,"form-group",a),t(e,23,0,"pseudo"),t(e,28,0,n.nfsForm.showError("pseudo",s["\u0275nov"](e.parent,6),"required")),t(e,30,0,n.nfsForm.showError("pseudo",s["\u0275nov"](e.parent,6),"pattern"))},function(t,e){t(e,20,0,s["\u0275nov"](e,25).ngClassUntouched,s["\u0275nov"](e,25).ngClassTouched,s["\u0275nov"](e,25).ngClassPristine,s["\u0275nov"](e,25).ngClassDirty,s["\u0275nov"](e,25).ngClassValid,s["\u0275nov"](e,25).ngClassInvalid,s["\u0275nov"](e,25).ngClassPending)})}function hl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function gl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No access type available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function bl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select the access type --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function ml(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.value),t(e,2,0,e.context.$implicit.value)},function(t,e){t(e,3,0,e.context.$implicit.value)})}function yl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){var n=e.component;t(e,1,0,n.getAccessTypeHelp(n.nfsForm.getValue("access_type")))})}function vl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"span",[["class","text-warning"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The Object Gateway NFS backend has a number of limitations which will seriously affect applications writing to the share. Please consult the "])),(t()(),s["\u0275eld"](2,0,null,null,1,"a",[["target","_blank"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" documentation"])),(t()(),s["\u0275ted"](-1,null,[" for details before enabling write access."]))],null,function(t,e){t(e,2,0,s["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function _l(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function xl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["Loading..."]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Tl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["-- No squash available --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function wl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[["value",""]],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](-1,null,["--Select what kind of user id squashing is performed --"]))],function(t,e){t(e,1,0,""),t(e,2,0,"")},null)}function Sl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function Ol(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Il(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Required field"]))],null,null)}function Cl(t){return s["\u0275vid"](0,[s["\u0275pid"](0,i.TitleCasePipe,[]),s["\u0275pid"](0,Rs.a,[]),s["\u0275qud"](402653184,1,{nfsClients:0}),(t()(),s["\u0275eld"](3,0,null,null,201,"div",[["class","col-sm-12 col-lg-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,200,"form",[["class","form-horizontal"],["name","nfsForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,6).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,6).onReset()&&a),a},null,null)),s["\u0275did"](5,16384,null,0,Te.D,[],null,null),s["\u0275did"](6,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](8,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](9,0,null,null,195,"div",[["class","panel panel-default"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,4,"div",[["class","panel-heading"]],null,null,null,null,null)),(t()(),s["\u0275eld"](11,0,null,null,3,"h3",[["class","panel-title"]],null,null,null,null,null)),(t()(),s["\u0275ted"](12,null,[""," ",""])),s["\u0275ppd"](13,1),s["\u0275ppd"](14,1),(t()(),s["\u0275eld"](15,0,null,null,180,"div",[["class","panel-body"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Ic)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,15,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](19,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](20,{"has-error":0}),(t()(),s["\u0275eld"](21,0,null,null,2,"label",[["class","col-sm-3 control-label"],["for","daemons"]],null,null,null,null,null)),(t()(),s["\u0275eld"](22,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Daemons"])),(t()(),s["\u0275eld"](24,0,null,null,9,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Cc)),s["\u0275did"](26,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](27,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](28,0,null,null,5,"div",[["class","col-md-12"]],null,null,null,null,null)),(t()(),s["\u0275eld"](29,0,null,null,4,"cd-select",[["elemClass","btn btn-default pull-right"]],null,[[null,"selection"]],function(t,e,n){var a=!0;return"selection"===e&&(a=!1!==t.component.onDaemonSelection()&&a),a},nc.b,nc.a)),s["\u0275did"](30,638976,null,0,ac.a,[xt.a],{elemClass:[0,"elemClass"],data:[1,"data"],options:[2,"options"],messages:[3,"messages"]},{selection:"selection"}),(t()(),s["\u0275eld"](31,0,null,0,0,"i",[["class","fa fa-fw fa-plus"]],null,null,null,null,null)),(t()(),s["\u0275eld"](32,0,null,0,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Add daemon"])),(t()(),s["\u0275eld"](34,0,null,null,34,"div",[["formGroupName","fsal"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],null,null,null,null)),s["\u0275did"](35,212992,null,0,Te.m,[[3,Te.d],[8,null],[8,null]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.m]),s["\u0275did"](37,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](38,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](39,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](40,{"has-error":0}),(t()(),s["\u0275eld"](41,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","name"]],null,null,null,null,null)),(t()(),s["\u0275eld"](42,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Storage Backend"])),(t()(),s["\u0275eld"](44,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](45,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](46,0,null,null,14,"select",[["class","form-control"],["formControlName","name"],["id","name"],["name","name"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,47).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,47).onTouched()&&a),"change"===e&&(a=!1!==r.fsalChangeHandler()&&a),a},null,null)),s["\u0275did"](47,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](49,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](51,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](52,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,kc)),s["\u0275did"](54,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Nc)),s["\u0275did"](56,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Rc)),s["\u0275did"](58,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ac)),s["\u0275did"](60,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Dc)),s["\u0275did"](62,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,jc)),s["\u0275did"](64,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Hc)),s["\u0275did"](66,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Zc)),s["\u0275did"](68,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,tl)),s["\u0275did"](70,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,rl)),s["\u0275did"](72,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ul)),s["\u0275did"](74,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](75,0,null,null,29,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](76,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](77,{"has-error":0}),(t()(),s["\u0275eld"](78,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","protocols"]],null,null,null,null,null)),(t()(),s["\u0275eld"](79,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFS Protocol"])),(t()(),s["\u0275eld"](81,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](82,0,null,null,22,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](83,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](84,0,null,null,6,"input",[["formControlName","protocolNfsv3"],["id","protocolNfsv3"],["name","protocolNfsv3"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,85).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,85).onTouched()&&a),a},null,null)),s["\u0275did"](85,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](87,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](89,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](90,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](91,0,null,null,1,"label",[["for","protocolNfsv3"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFSv3"])),(t()(),s["\u0275eld"](93,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](94,0,null,null,6,"input",[["formControlName","protocolNfsv4"],["id","protocolNfsv4"],["name","protocolNfsv4"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,95).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,95).onTouched()&&a),a},null,null)),s["\u0275did"](95,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](97,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](99,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](100,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](101,0,null,null,1,"label",[["for","protocolNfsv4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["NFSv4"])),(t()(),s["\u0275and"](16777216,null,null,1,null,cl)),s["\u0275did"](104,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ll)),s["\u0275did"](106,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,pl)),s["\u0275did"](108,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](109,0,null,null,28,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](110,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](111,{"has-error":0}),(t()(),s["\u0275eld"](112,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","access_type"]],null,null,null,null,null)),(t()(),s["\u0275eld"](113,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Access Type"])),(t()(),s["\u0275eld"](115,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](116,0,null,null,21,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](117,0,null,null,14,"select",[["class","form-control"],["formControlName","access_type"],["id","access_type"],["name","access_type"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,118).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,118).onTouched()&&a),"change"===e&&(a=!1!==r.accessTypeChangeHandler()&&a),a},null,null)),s["\u0275did"](118,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](120,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](122,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](123,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,hl)),s["\u0275did"](125,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,gl)),s["\u0275did"](127,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,bl)),s["\u0275did"](129,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ml)),s["\u0275did"](131,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,yl)),s["\u0275did"](133,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,vl)),s["\u0275did"](135,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,_l)),s["\u0275did"](137,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](138,0,null,null,24,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](139,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](140,{"has-error":0}),(t()(),s["\u0275eld"](141,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","squash"]],null,null,null,null,null)),(t()(),s["\u0275eld"](142,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Squash"])),(t()(),s["\u0275eld"](144,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](145,0,null,null,17,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](146,0,null,null,14,"select",[["class","form-control"],["formControlName","squash"],["id","squash"],["name","squash"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,147).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,147).onTouched()&&a),a},null,null)),s["\u0275did"](147,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](149,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](151,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](152,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,xl)),s["\u0275did"](154,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Tl)),s["\u0275did"](156,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,wl)),s["\u0275did"](158,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Sl)),s["\u0275did"](160,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ol)),s["\u0275did"](162,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](163,0,null,null,30,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](164,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](165,{"has-error":0}),(t()(),s["\u0275eld"](166,0,null,null,3,"label",[["class","col-sm-3 control-label"],["for","transports"]],null,null,null,null,null)),(t()(),s["\u0275eld"](167,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Transport Protocol"])),(t()(),s["\u0275eld"](169,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](170,0,null,null,23,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](171,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](172,0,null,null,6,"input",[["formControlName","transportUDP"],["id","transportUDP"],["name","transportUDP"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,173).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,173).onTouched()&&a),a},null,null)),s["\u0275did"](173,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](175,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](177,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](178,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](179,0,null,null,1,"label",[["for","transportUDP"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["UDP"])),(t()(),s["\u0275eld"](181,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](182,0,null,null,6,"input",[["formControlName","transportTCP"],["id","transportTCP"],["name","transportTCP"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,183).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,183).onTouched()&&a),a},null,null)),s["\u0275did"](183,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](185,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](187,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](188,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](189,0,null,null,1,"label",[["for","transportTCP"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["TCP"])),(t()(),s["\u0275and"](16777216,null,null,1,null,Il)),s["\u0275did"](192,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](193,0,null,null,0,"hr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](194,0,null,null,1,"cd-nfs-form-client",[],null,null,null,hc,sc)),s["\u0275did"](195,49152,[[1,4],["nfsClients",4]],0,ic,[Iu,xt.a],{form:[0,"form"]},null),(t()(),s["\u0275eld"](196,0,null,null,8,"div",[["class","panel-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](197,0,null,null,7,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275eld"](198,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submitAction()&&a),a},$a.b,$a.a)),s["\u0275did"](199,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](200,0,[""," ",""])),s["\u0275ppd"](201,1),s["\u0275ppd"](202,1),(t()(),s["\u0275eld"](203,0,null,null,1,"cd-back-button",[],null,null,null,Xa.b,Xa.a)),s["\u0275did"](204,49152,null,0,Ja.a,[i.Location,Zn.b],null,null)],function(t,e){var n=e.component;t(e,6,0,n.nfsForm),t(e,17,0,!n.isDefaultCluster);var a=t(e,20,0,n.nfsForm.showError("daemons",s["\u0275nov"](e,6)));t(e,19,0,"form-group",a),t(e,26,0,n.nfsForm.getValue("daemons")),t(e,30,0,"btn btn-default pull-right",n.nfsForm.get("daemons").value,n.daemonsSelections,n.daemonsMessages),t(e,35,0,"fsal");var r=t(e,40,0,n.nfsForm.showError("name",s["\u0275nov"](e,6)));t(e,39,0,"form-group",r),t(e,49,0,"name"),t(e,54,0,null===n.allFsals),t(e,56,0,null!==n.allFsals&&0===n.allFsals.length),t(e,58,0,null!==n.allFsals&&n.allFsals.length>0),t(e,60,0,n.allFsals),t(e,62,0,n.nfsForm.showError("name",s["\u0275nov"](e,6),"required")),t(e,64,0,"RGW"===n.nfsForm.getValue("name")),t(e,66,0,"CEPH"===n.nfsForm.getValue("name")),t(e,68,0,"CEPH"===n.nfsForm.getValue("name")),t(e,70,0,"CEPH"===n.nfsForm.getValue("name")),t(e,72,0,"CEPH"===n.nfsForm.getValue("name")),t(e,74,0,"RGW"===n.nfsForm.getValue("name"));var i=t(e,77,0,n.nfsForm.showError("protocolNfsv3",s["\u0275nov"](e,6))||n.nfsForm.showError("protocolNfsv4",s["\u0275nov"](e,6)));t(e,76,0,"form-group",i),t(e,87,0,"protocolNfsv3"),t(e,97,0,"protocolNfsv4"),t(e,104,0,n.nfsForm.showError("protocolNfsv3",s["\u0275nov"](e,6),"required")||n.nfsForm.showError("protocolNfsv4",s["\u0275nov"](e,6),"required")),t(e,106,0,n.nfsForm.getValue("protocolNfsv3")),t(e,108,0,n.nfsForm.getValue("protocolNfsv4"));var o=t(e,111,0,n.nfsForm.showError("access_type",s["\u0275nov"](e,6)));t(e,110,0,"form-group",o),t(e,120,0,"access_type"),t(e,125,0,null===n.nfsAccessType),t(e,127,0,null!==n.nfsAccessType&&0===n.nfsAccessType.length),t(e,129,0,null!==n.nfsAccessType&&n.nfsAccessType.length>0),t(e,131,0,n.nfsAccessType),t(e,133,0,n.nfsForm.getValue("access_type")),t(e,135,0,"RW"===n.nfsForm.getValue("access_type")&&"RGW"===n.nfsForm.getValue("name")),t(e,137,0,n.nfsForm.showError("access_type",s["\u0275nov"](e,6),"required"));var u=t(e,140,0,n.nfsForm.showError("squash",s["\u0275nov"](e,6)));t(e,139,0,"form-group",u),t(e,149,0,"squash"),t(e,154,0,null===n.nfsSquash),t(e,156,0,null!==n.nfsSquash&&0===n.nfsSquash.length),t(e,158,0,null!==n.nfsSquash&&n.nfsSquash.length>0),t(e,160,0,n.nfsSquash),t(e,162,0,n.nfsForm.showError("squash",s["\u0275nov"](e,6),"required"));var c=t(e,165,0,n.nfsForm.showError("transportUDP",s["\u0275nov"](e,6))||n.nfsForm.showError("transportTCP",s["\u0275nov"](e,6)));t(e,164,0,"form-group",c),t(e,175,0,"transportUDP"),t(e,185,0,"transportTCP"),t(e,192,0,n.nfsForm.showError("transportUDP",s["\u0275nov"](e,6),"required")||n.nfsForm.showError("transportTCP",s["\u0275nov"](e,6),"required")),t(e,195,0,n.nfsForm),t(e,199,0,s["\u0275nov"](e,6),"button")},function(t,e){var n=e.component;t(e,4,0,s["\u0275nov"](e,8).ngClassUntouched,s["\u0275nov"](e,8).ngClassTouched,s["\u0275nov"](e,8).ngClassPristine,s["\u0275nov"](e,8).ngClassDirty,s["\u0275nov"](e,8).ngClassValid,s["\u0275nov"](e,8).ngClassInvalid,s["\u0275nov"](e,8).ngClassPending);var a=s["\u0275unv"](e,12,0,t(e,13,0,s["\u0275nov"](e,0),n.action)),r=s["\u0275unv"](e,12,1,t(e,14,0,s["\u0275nov"](e,1),n.resource));t(e,12,0,a,r),t(e,34,0,s["\u0275nov"](e,37).ngClassUntouched,s["\u0275nov"](e,37).ngClassTouched,s["\u0275nov"](e,37).ngClassPristine,s["\u0275nov"](e,37).ngClassDirty,s["\u0275nov"](e,37).ngClassValid,s["\u0275nov"](e,37).ngClassInvalid,s["\u0275nov"](e,37).ngClassPending),t(e,46,0,s["\u0275nov"](e,51).ngClassUntouched,s["\u0275nov"](e,51).ngClassTouched,s["\u0275nov"](e,51).ngClassPristine,s["\u0275nov"](e,51).ngClassDirty,s["\u0275nov"](e,51).ngClassValid,s["\u0275nov"](e,51).ngClassInvalid,s["\u0275nov"](e,51).ngClassPending),t(e,84,0,s["\u0275nov"](e,89).ngClassUntouched,s["\u0275nov"](e,89).ngClassTouched,s["\u0275nov"](e,89).ngClassPristine,s["\u0275nov"](e,89).ngClassDirty,s["\u0275nov"](e,89).ngClassValid,s["\u0275nov"](e,89).ngClassInvalid,s["\u0275nov"](e,89).ngClassPending),t(e,94,0,s["\u0275nov"](e,99).ngClassUntouched,s["\u0275nov"](e,99).ngClassTouched,s["\u0275nov"](e,99).ngClassPristine,s["\u0275nov"](e,99).ngClassDirty,s["\u0275nov"](e,99).ngClassValid,s["\u0275nov"](e,99).ngClassInvalid,s["\u0275nov"](e,99).ngClassPending),t(e,117,0,s["\u0275nov"](e,122).ngClassUntouched,s["\u0275nov"](e,122).ngClassTouched,s["\u0275nov"](e,122).ngClassPristine,s["\u0275nov"](e,122).ngClassDirty,s["\u0275nov"](e,122).ngClassValid,s["\u0275nov"](e,122).ngClassInvalid,s["\u0275nov"](e,122).ngClassPending),t(e,146,0,s["\u0275nov"](e,151).ngClassUntouched,s["\u0275nov"](e,151).ngClassTouched,s["\u0275nov"](e,151).ngClassPristine,s["\u0275nov"](e,151).ngClassDirty,s["\u0275nov"](e,151).ngClassValid,s["\u0275nov"](e,151).ngClassInvalid,s["\u0275nov"](e,151).ngClassPending),t(e,172,0,s["\u0275nov"](e,177).ngClassUntouched,s["\u0275nov"](e,177).ngClassTouched,s["\u0275nov"](e,177).ngClassPristine,s["\u0275nov"](e,177).ngClassDirty,s["\u0275nov"](e,177).ngClassValid,s["\u0275nov"](e,177).ngClassInvalid,s["\u0275nov"](e,177).ngClassPending),t(e,182,0,s["\u0275nov"](e,187).ngClassUntouched,s["\u0275nov"](e,187).ngClassTouched,s["\u0275nov"](e,187).ngClassPristine,s["\u0275nov"](e,187).ngClassDirty,s["\u0275nov"](e,187).ngClassValid,s["\u0275nov"](e,187).ngClassInvalid,s["\u0275nov"](e,187).ngClassPending);var i=s["\u0275unv"](e,200,0,t(e,201,0,s["\u0275nov"](e,0),n.action)),o=s["\u0275unv"](e,200,1,t(e,202,0,s["\u0275nov"](e,1),n.resource));t(e,200,0,i,o)})}function kl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-nfs-form",[],null,null,null,Cl,_c)),s["\u0275did"](1,114688,null,0,vc,[l.a,Iu,tt.a,tt.l,bc.a,ca.a,je.a,Ge.a,ku.a,s.ChangeDetectorRef,xt.a,Zn.b],null,null)],function(t,e){t(e,1,0)},null)}var Nl=s["\u0275ccf"]("cd-nfs-form",vc,kl,{},{},[]),Rl=function(){return function(){this.logoutUrl=window.location.origin+"/auth/saml2/slo"}}(),Al=s["\u0275crt"]({encapsulation:0,styles:[["h1[_ngcontent-%COMP%]{font-size:-webkit-xxx-large}*[_ngcontent-%COMP%]{font-family:monospace}img[_ngcontent-%COMP%]{width:50vw}"]],data:{}});function Dl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,16,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,15,"div",[["class","col-md-12 text-center"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"h1",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Sorry, the user does not exist in Ceph."])),(t()(),s["\u0275eld"](4,0,null,null,4,"h4",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Return to "])),(t()(),s["\u0275eld"](6,0,null,null,1,"a",[["class","sso-logout"]],[[8,"href",4]],null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Login Page"])),(t()(),s["\u0275ted"](-1,null,[". You'll be logged out from the Identity Provider when you retry logging in."])),(t()(),s["\u0275eld"](9,0,null,null,0,"img",[["class","img-responsive center-block img-rounded"],["src","assets/1280px-Nautilus_Octopus.jpg"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,6,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[' "'])),(t()(),s["\u0275eld"](12,0,null,null,1,"a",[["href","https://www.flickr.com/photos/146401137@N06/40335060661"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Nautilus Octopus"])),(t()(),s["\u0275ted"](-1,null,['" by Jin Kemoole is licensed under '])),(t()(),s["\u0275eld"](15,0,null,null,1,"a",[["class","external text"],["href","https://creativecommons.org/licenses/by/2.0/"],["rel","nofollow"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CC BY 2.0"]))],null,function(t,e){t(e,6,0,e.component.logoutUrl)})}function El(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-sso-not-found",[],null,null,null,Dl,Al)),s["\u0275did"](1,49152,null,0,Rl,[],null,null)],null,null)}var Ll,Pl=s["\u0275ccf"]("cd-sso-not-found",Rl,El,{},{},[]),Ml=n("lHUG"),ql=function(){function t(t,e){this.http=t,this.localeId=e}return t.prototype.getLocale=function(){return this.localeId||"en-US"},t.prototype.setLocale=function(t){document.cookie="cd-lang="+t},t.prototype.getLanguages=function(){return this.http.get("ui-api/langs")},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c),s.inject(s.LOCALE_ID))},token:t,providedIn:"root"}),t}();!function(t){t.cs="\u010ce\u0161tina",t["de-DE"]="Deutsch",t["en-US"]="English",t["es-ES"]="Espa\xf1ol",t["fr-FR"]="Fran\xe7ais",t["id-ID"]="Bahasa Indonesia",t["it-IT"]="Italiano",t["ja-JP"]="\u65e5\u672c\u8a9e",t["ko-KR"]="\ud55c\uad6d\uc5b4",t["pl-PL"]="Polski",t["pt-BR"]="Portugu\xeas",t["zh-CN"]="\u4e2d\u6587 (\u7b80\u4f53)",t["zh-TW"]="\u4e2d\u6587 (\u7e41\u9ad4\uff09"}(Ll||(Ll={}));var jl={cs:Ml.a,de:Ml.b,es:Ml.e,fr:Ml.g,id:Ml.m,it:Ml.y,ja:Ml.z,ko:Ml.A,pl:Ml.C,pt:Ml.D,zh:Ml.H},Fl=function(){function t(t,e){this.localeService=t,this.languageService=e,this.isDropdown=!0,this.supportedLanguages=Ll}return t.prototype.ngOnInit=function(){var t=this;this.selectedLanguage=this.languageService.getLocale(),this.defineUsedLanguage(),this.languageService.getLanguages().subscribe(function(e){t.supportedLanguages=ft.pick(t.supportedLanguages,e)})},t.prototype.defineUsedLanguage=function(){var t=this.selectedLanguage.slice(0,2);t in jl&&(Object(Ml.c)(t,jl[t]),this.localeService.use(t))},t.prototype.reloadWindow=function(){window.location.reload()},t.prototype.changeLanguage=function(t){this.languageService.setLocale(t),this.reloadWindow()},t}(),zl=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Gl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"a",[["class","dropdown-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.changeLanguage(t.context.$implicit.key)&&a),a},null,null)),(t()(),s["\u0275ted"](2,null,["",""]))],null,function(t,e){t(e,2,0,e.context.$implicit.value)})}function Yl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"ul",[["class","dropdown-menu dropdown-menu-right"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,Gl)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.KeyValuePipe,[s.KeyValueDiffers])],function(t,e){var n=e.component;t(e,2,0,s["\u0275unv"](e,2,0,s["\u0275nov"](e,3).transform(n.supportedLanguages)))},null)}function Vl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,8,"div",[["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),(t()(),s["\u0275eld"](3,0,null,null,3,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""],["title","Select a Language"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,4).onClick()&&a),a},null,null)),s["\u0275did"](4,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275ted"](5,null,[" "," "])),(t()(),s["\u0275eld"](6,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Yl)),s["\u0275did"](8,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,2,0)},function(t,e){var n=e.component;t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,3,0,!0,s["\u0275nov"](e,4).isDisabled,s["\u0275nov"](e,4).isOpen),t(e,5,0,n.supportedLanguages[n.selectedLanguage])})}function Hl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,["",""]))],function(t,e){t(e,1,0,e.context.$implicit.key),t(e,2,0,e.context.$implicit.key)},function(t,e){t(e,3,0,e.context.$implicit.value)})}function Bl(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,9,"select",[["class","form-control"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"ngModelChange"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,1).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,1).onTouched()&&a),"change"===e&&(a=!1!==r.changeLanguage(n.target.value)&&a),"ngModelChange"===e&&(a=!1!==(r.selectedLanguage=n)&&a),a},null,null)),s["\u0275did"](1,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](3,671744,null,0,Te.u,[[8,null],[8,null],[8,null],[6,Te.p]],{model:[0,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](5,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](6,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,2,null,Hl)),s["\u0275did"](8,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.KeyValuePipe,[s.KeyValueDiffers])],function(t,e){var n=e.component;t(e,3,0,n.selectedLanguage),t(e,8,0,s["\u0275unv"](e,8,0,s["\u0275nov"](e,9).transform(n.supportedLanguages)))},function(t,e){t(e,0,0,s["\u0275nov"](e,5).ngClassUntouched,s["\u0275nov"](e,5).ngClassTouched,s["\u0275nov"](e,5).ngClassPristine,s["\u0275nov"](e,5).ngClassDirty,s["\u0275nov"](e,5).ngClassValid,s["\u0275nov"](e,5).ngClassInvalid,s["\u0275nov"](e,5).ngClassPending)})}function Ul(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Vl)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Bl)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.isDropdown),t(e,3,0,!n.isDropdown)},null)}var Wl=n("IZUe"),Kl=n("D4zM"),$l=n("DSvg"),Zl=function(){return function(){}}(),Xl=function(){function t(t,e,n,a,r){this.authService=t,this.authStorageService=e,this.bsModalService=n,this.route=a,this.router=r,this.model=new Zl,this.isLoginActive=!1}return t.prototype.ngOnInit=function(){var t=this;if(this.authStorageService.isLoggedIn())this.router.navigate([""]);else{for(var e=this.bsModalService.getModalsCount(),n=1;n<=e;n++)this.bsModalService.hide(n);var a=null;if(-1!==window.location.hash.indexOf("access_token=")){a=window.location.hash.split("access_token=")[1];var r=window.location.toString();window.history.replaceState({},document.title,r.split("?")[0])}this.authService.check(a).subscribe(function(e){e.login_url?"#/login"===e.login_url?t.isLoginActive=!0:window.location.replace(e.login_url):(t.authStorageService.set(e.username,e.permissions),t.router.navigate([""]))})}},t.prototype.login=function(){var t=this;this.authService.login(this.model).then(function(){var e=ft.get(t.route.snapshot.queryParams,"returnUrl","/");t.router.navigate([e])})},t}(),Jl=s["\u0275crt"]({encapsulation:0,styles:[[".login{height:100%} .login .row{color:#fff;background-color:#374249} .login h1{margin-top:0;margin-bottom:30px} .login .btn-password, .login .form-control{color:#fff;background-color:#555} .login .btn-password:focus{outline-color:#2b99a8} .login .checkbox-primary input[type=checkbox]:checked+label::before, .login .checkbox-primary input[type=radio]:checked+label::before{background-color:#2b99a8;border-color:#2b99a8}"]],data:{}});function Ql(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Username is required"]))],null,null)}function td(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"div",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Password is required"]))],null,null)}function ed(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,49,"div",[["class","login"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,48,"div",[["class","row full-height vertical-align"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"div",[["class","col-sm-6 hidden-xs"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,0,"img",[["alt","Ceph"],["class","pull-right"],["src","assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,45,"div",[["class","col-xs-10 col-sm-4 col-lg-3 col-xs-offset-1 col-sm-offset-0 col-md-offset-0 col-lg-offset-0"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,1,"h1",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Welcome to Ceph!"])),(t()(),s["\u0275eld"](7,0,null,null,42,"form",[["name","loginForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngSubmit"],[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0,r=t.component;return"submit"===e&&(a=!1!==s["\u0275nov"](t,9).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,9).onReset()&&a),"ngSubmit"===e&&(a=!1!==r.login()&&a),a},null,null)),s["\u0275did"](8,16384,null,0,Te.D,[],null,null),s["\u0275did"](9,4210688,[["loginForm",4]],0,Te.t,[[8,null],[8,null]],null,{ngSubmit:"ngSubmit"}),s["\u0275prd"](2048,null,Te.d,null,[Te.t]),s["\u0275did"](11,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](12,0,null,null,2,"div",[["class","form-group has-feedback"]],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,1,"cd-language-selector",[],null,null,null,Ul,zl)),s["\u0275did"](14,114688,null,0,Fl,[Nr.j,ql],{isDropdown:[0,"isDropdown"]},null),(t()(),s["\u0275eld"](15,0,null,null,14,"div",[["class","form-group has-feedback"]],null,null,null,null,null)),s["\u0275did"](16,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](17,{"has-error":0}),(t()(),s["\u0275eld"](18,0,null,null,9,"input",[["autofocus",""],["class","form-control"],["name","username"],["placeholder","Enter your username..."],["required",""],["type","text"]],[[1,"required",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,19)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,19).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionEnd(n.target.value)&&a),"ngModelChange"===e&&(a=!1!==(r.model.username=n)&&a),a},null,null)),s["\u0275did"](19,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](20,16384,null,0,Te.y,[],{required:[0,"required"]},null),s["\u0275prd"](1024,null,Te.o,function(t){return[t]},[Te.y]),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](23,671744,[["username",4]],0,Te.u,[[2,Te.d],[6,Te.o],[8,null],[6,Te.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](25,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](26,4210688,null,0,Wl.a,[s.ElementRef],null,null),s["\u0275did"](27,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ql)),s["\u0275did"](29,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](30,0,null,null,17,"div",[["class","form-group has-feedback"]],null,null,null,null,null)),s["\u0275did"](31,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](32,{"has-error":0}),(t()(),s["\u0275eld"](33,0,null,null,12,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](34,0,null,null,8,"input",[["class","form-control"],["id","password"],["name","password"],["placeholder","Enter your password..."],["required",""],["type","password"]],[[1,"required",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"ngModelChange"],[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0,r=t.component;return"input"===e&&(a=!1!==s["\u0275nov"](t,35)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,35).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,35)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,35)._compositionEnd(n.target.value)&&a),"ngModelChange"===e&&(a=!1!==(r.model.password=n)&&a),a},null,null)),s["\u0275did"](35,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](36,16384,null,0,Te.y,[],{required:[0,"required"]},null),s["\u0275prd"](1024,null,Te.o,function(t){return[t]},[Te.y]),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](39,671744,[["password",4]],0,Te.u,[[2,Te.d],[6,Te.o],[8,null],[6,Te.p]],{name:[0,"name"],model:[1,"model"]},{update:"ngModelChange"}),s["\u0275prd"](2048,null,Te.q,null,[Te.u]),s["\u0275did"](41,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](42,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](43,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](44,0,null,null,1,"button",[["cdPasswordButton","password"],["class","btn btn-default btn-password"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,45).onClick()&&a),a},null,null)),s["\u0275did"](45,81920,null,0,Kl.a,[s.ElementRef,s.Renderer2],{cdPasswordButton:[0,"cdPasswordButton"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,td)),s["\u0275did"](47,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](48,0,null,null,1,"input",[["class","btn btn-primary btn-block"],["type","submit"],["value","Login"]],[[8,"disabled",0]],null,null,null,null)),s["\u0275did"](49,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null)],function(t,e){var n=e.component;t(e,14,0,!1);var a=t(e,17,0,(s["\u0275nov"](e,9).submitted||s["\u0275nov"](e,23).dirty)&&s["\u0275nov"](e,23).invalid);t(e,16,0,"form-group has-feedback",a),t(e,20,0,""),t(e,23,0,"username",n.model.username),t(e,29,0,(s["\u0275nov"](e,9).submitted||s["\u0275nov"](e,23).dirty)&&s["\u0275nov"](e,23).invalid);var r=t(e,32,0,(s["\u0275nov"](e,9).submitted||s["\u0275nov"](e,39).dirty)&&s["\u0275nov"](e,39).invalid);t(e,31,0,"form-group has-feedback",r),t(e,36,0,""),t(e,39,0,"password",n.model.password),t(e,45,0,"password"),t(e,47,0,(s["\u0275nov"](e,9).submitted||s["\u0275nov"](e,39).dirty)&&s["\u0275nov"](e,39).invalid)},function(t,e){t(e,7,0,s["\u0275nov"](e,11).ngClassUntouched,s["\u0275nov"](e,11).ngClassTouched,s["\u0275nov"](e,11).ngClassPristine,s["\u0275nov"](e,11).ngClassDirty,s["\u0275nov"](e,11).ngClassValid,s["\u0275nov"](e,11).ngClassInvalid,s["\u0275nov"](e,11).ngClassPending),t(e,18,0,s["\u0275nov"](e,20).required?"":null,s["\u0275nov"](e,25).ngClassUntouched,s["\u0275nov"](e,25).ngClassTouched,s["\u0275nov"](e,25).ngClassPristine,s["\u0275nov"](e,25).ngClassDirty,s["\u0275nov"](e,25).ngClassValid,s["\u0275nov"](e,25).ngClassInvalid,s["\u0275nov"](e,25).ngClassPending),t(e,34,0,s["\u0275nov"](e,36).required?"":null,s["\u0275nov"](e,41).ngClassUntouched,s["\u0275nov"](e,41).ngClassTouched,s["\u0275nov"](e,41).ngClassPristine,s["\u0275nov"](e,41).ngClassDirty,s["\u0275nov"](e,41).ngClassValid,s["\u0275nov"](e,41).ngClassInvalid,s["\u0275nov"](e,41).ngClassPending),t(e,48,0,s["\u0275nov"](e,9).invalid)})}function nd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,ed)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.isLoginActive)},null)}function ad(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-login",[],null,null,null,nd,Jl)),s["\u0275did"](1,114688,null,0,Xl,[$l.a,l.a,pa.b,tt.a,tt.l],null,null)],function(t,e){t(e,1,0)},null)}var rd=s["\u0275ccf"]("cd-login",Xl,ad,{},{},[]),id=function(){return function(){}}(),sd=s["\u0275crt"]({encapsulation:0,styles:[["h1[_ngcontent-%COMP%]{font-size:-webkit-xxx-large;font-family:monospace}h2[_ngcontent-%COMP%]{font-size:xx-large;font-family:monospace}i[_ngcontent-%COMP%]{font-size:200px}"]],data:{}});function od(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,5,"div",[["class","col-md-12 text-center"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"h1",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Forbidden"])),(t()(),s["\u0275eld"](4,0,null,null,0,"i",[["class","fa fa-lock text-danger"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,1,"h2",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Sorry, you are not allowed to see what you were looking for."]))],null,null)}function ud(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-forbidden",[],null,null,null,od,sd)),s["\u0275did"](1,49152,null,0,id,[],null,null)],null,null)}var cd=s["\u0275ccf"]("cd-forbidden",id,ud,{},{},[]),ld=function(){return function(){}}(),dd=s["\u0275crt"]({encapsulation:0,styles:[["h1[_ngcontent-%COMP%]{font-size:-webkit-xxx-large}*[_ngcontent-%COMP%]{font-family:monospace}img[_ngcontent-%COMP%]{width:50vw}"]],data:{}});function fd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,11,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,10,"div",[["class","col-md-12 text-center"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"h1",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Sorry, we could not find what you were looking for"])),(t()(),s["\u0275eld"](4,0,null,null,0,"img",[["class","img-responsive center-block img-rounded"],["src","assets/1280px-Nautilus_Octopus.jpg"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,6,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[' "'])),(t()(),s["\u0275eld"](7,0,null,null,1,"a",[["href","https://www.flickr.com/photos/146401137@N06/40335060661"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Nautilus Octopus"])),(t()(),s["\u0275ted"](-1,null,['" by Jin Kemoole is licensed under '])),(t()(),s["\u0275eld"](10,0,null,null,1,"a",[["class","external text"],["href","https://creativecommons.org/licenses/by/2.0/"],["rel","nofollow"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["CC BY 2.0"]))],null,null)}function pd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-not-found",[],null,null,null,fd,dd)),s["\u0275did"](1,49152,null,0,ld,[],null,null)],null,null)}var hd=s["\u0275ccf"]("cd-not-found",ld,pd,{},{},[]),gd=n("iutN"),bd=n("ES0t"),md=n("MdoF"),yd=n("Xg1U"),vd=n("z5nN"),_d=n("EEJc"),xd=n("PEr+"),Td=n("a40w"),wd=n("SjWX"),Sd=n("Mxhz"),Od=function(){function t(t,e,n,a){this.modalRef=t,this.summaryService=e,this.userService=n,this.authStorageService=a,this.userPermission=this.authStorageService.getPermissions().user}return t.prototype.ngOnInit=function(){var t=this;this.copyright="Copyright(c) 2021 Ceph contributors.",this.projectConstants=Zn.c,this.hostAddr=window.location.hostname,this.modalVariables=this.setVariables(),this.subs=this.summaryService.subscribe(function(e){if(e){var n=e.version.replace("ceph version ","").split(" ");t.hostAddr=e.mgr_host.replace(/(^\w+:|^)\/\//,"").replace(/\/$/,""),t.versionNumber=n[0],t.versionHash=n[1],t.versionName=n.slice(2,n.length).join(" ")}})},t.prototype.ngOnDestroy=function(){this.subs.unsubscribe()},t.prototype.setVariables=function(){var t={};t.user=localStorage.getItem("dashboard_username"),t.role="user",this.userPermission.read&&this.userService.get(t.user).subscribe(function(e){t.role=e.roles});var e=Object(wd.detect)();return t.browserName=e&&e.name?e.name:"Not detected",t.browserVersion=e&&e.version?e.version:"Not detected",t.browserOS=e&&e.os?e.os:"Not detected",t},t}(),Id=s["\u0275crt"]({encapsulation:0,styles:[[".product-versions[_ngcontent-%COMP%]{margin-top:30px}.product-versions[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{margin-right:10px}.modal-header[_ngcontent-%COMP%]{border-bottom:none}.modal-body[_ngcontent-%COMP%]{padding-left:80px;padding-right:80px}.modal-footer[_ngcontent-%COMP%]{border-top:none;padding:15px 80px 35px}h2[_ngcontent-%COMP%]{font-size:3em}.ceph-logo[_ngcontent-%COMP%]{width:10%}.list-unstyled[_ngcontent-%COMP%] li[_ngcontent-%COMP%]{margin-top:5px}.modal-body[_ngcontent-%COMP%]{margin-top:0;padding-top:0}.modal-body[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin-top:0}"]],data:{}});function Cd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"div",[["class","modal-header"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.modalRef.hide()&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xd7"])),(t()(),s["\u0275eld"](4,0,null,null,45,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,2,"h2",[],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,0,"img",[["class","ceph-logo"],["src","assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png"]],[[8,"alt",0]],null,null,null,null)),(t()(),s["\u0275ted"](7,null,[" "," "])),(t()(),s["\u0275eld"](8,0,null,null,2,"h3",[],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](10,null,["",""])),(t()(),s["\u0275eld"](11,0,null,null,6,"div",[["class","product-versions"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Version"])),(t()(),s["\u0275eld"](14,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275ted"](15,null,[" "," "," "])),(t()(),s["\u0275eld"](16,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275ted"](17,null,[" "," "])),(t()(),s["\u0275eld"](18,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,30,"ul",[["class","list-unstyled"]],null,null,null,null,null)),(t()(),s["\u0275eld"](20,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](21,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Ceph Manager"])),(t()(),s["\u0275eld"](23,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](24,null,["",""])),(t()(),s["\u0275eld"](25,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](26,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["User"])),(t()(),s["\u0275eld"](28,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](29,null,["",""])),(t()(),s["\u0275eld"](30,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](31,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["User Role"])),(t()(),s["\u0275eld"](33,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](34,null,["",""])),(t()(),s["\u0275eld"](35,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](36,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Browser"])),(t()(),s["\u0275eld"](38,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](39,null,["",""])),(t()(),s["\u0275eld"](40,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](41,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Browser Version"])),(t()(),s["\u0275eld"](43,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](44,null,["",""])),(t()(),s["\u0275eld"](45,0,null,null,4,"li",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](46,0,null,null,1,"strong",[["class","col-xs-6 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Browser OS"])),(t()(),s["\u0275eld"](48,0,null,null,1,"span",[["class","col-xs-4 col-sm-4"]],null,null,null,null,null)),(t()(),s["\u0275ted"](49,null,["",""])),(t()(),s["\u0275eld"](50,0,null,null,2,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](51,0,null,null,1,"div",[["class","text-left"]],null,null,null,null,null)),(t()(),s["\u0275ted"](52,null,[" "," "," "]))],null,function(t,e){var n=e.component;t(e,6,0,s["\u0275inlineInterpolate"](1,"",n.projectConstants.organization,"")),t(e,7,0,n.projectConstants.organization),t(e,10,0,n.projectConstants.projectName),t(e,15,0,n.versionNumber,n.versionHash),t(e,17,0,n.versionName),t(e,24,0,n.hostAddr),t(e,29,0,n.modalVariables.user),t(e,34,0,n.modalVariables.role),t(e,39,0,n.modalVariables.browserName),t(e,44,0,n.modalVariables.browserVersion),t(e,49,0,n.modalVariables.browserOS),t(e,52,0,n.copyright,n.projectConstants.license)})}function kd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-about",[],null,null,null,Cd,Id)),s["\u0275did"](1,245760,null,0,Od,[pa.a,je.a,Sd.a,l.a],null,null)],function(t,e){t(e,1,0)},null)}var Nd=s["\u0275ccf"]("cd-about",Od,kd,{},{},[]),Rd=n("atuK"),Ad=s["\u0275crt"]({encapsulation:0,styles:[".dropdown[_nghost-%COMP%] {\n z-index: 1000;\n }"],data:{animation:[{type:7,name:"typeaheadAnimation",definitions:[{type:0,name:"animated-down",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-down",animation:[{type:6,styles:{height:0,overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:0,name:"animated-up",styles:{type:6,styles:{height:"*",overflow:"hidden"},offset:null},options:void 0},{type:1,expr:"* => animated-up",animation:[{type:6,styles:{height:"*",overflow:"hidden"},offset:null},{type:4,styles:null,timings:"220ms cubic-bezier(0, 0, 0.2, 1)"}],options:null},{type:1,expr:"* => unanimated",animation:{type:4,styles:null,timings:"0s"},options:null}],options:{}}]}});function Dd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](0,null,null,0))],null,null)}function Ed(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"span",[],[[8,"innerHTML",1]],null,null,null,null))],null,function(t,e){t(e,0,0,e.component.highlight(e.context.match,e.context.query))})}function Ld(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,[[2,0],["liElements",1]],null,1,"li",[["class","dropdown-header"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit)})}function Pd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](0,null,null,0))],null,null)}function Md(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,[[2,0],["liElements",1]],null,4,"li",[],[[24,"@typeaheadAnimation",0],[2,"active",null]],[[null,"@typeaheadAnimation.done"],[null,"mouseenter"]],function(t,e,n){var a=!0,r=t.component;return"@typeaheadAnimation.done"===e&&(a=!1!==r.positionServiceEnable()&&a),"mouseenter"===e&&(a=!1!==r.selectActive(t.parent.context.$implicit)&&a),a},null,null)),(t()(),s["\u0275eld"](1,0,null,null,3,"a",[["href","#"],["tabindex","-1"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.selectMatch(t.parent.context.$implicit,n)&&a),a},null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,Pd)),s["\u0275did"](3,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),s["\u0275pod"](4,{item:0,index:1,match:2,query:3})],function(t,e){var n=e.component,a=t(e,4,0,e.parent.context.$implicit.item,e.parent.context.index,e.parent.context.$implicit,n.query);t(e,3,0,a,n.itemTemplate||s["\u0275nov"](e.parent.parent.parent,5))},function(t,e){var n=e.component;t(e,0,0,n.animationState,n.isActive(e.parent.context.$implicit))})}function qd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Ld)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Md)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.context.$implicit.isHeader();t(e,1,0,n);var a=!e.context.$implicit.isHeader();t(e,3,0,a)},null)}function jd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,[[1,0],["ulElement",1]],null,2,"ul",[["class","dropdown-menu"]],[[4,"overflow-y",null],[4,"height",null]],null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,qd)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.matches)},function(t,e){var n=e.component;t(e,0,0,n.needScrollbar?"scroll":"auto",n.needScrollbar?n.guiHeight:"auto")})}function Fd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"h6",[["class","dropdown-header"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit)})}function zd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](0,null,null,0))],null,null)}function Gd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,[[2,0],["liElements",1]],null,3,"button",[["class","dropdown-item"]],[[24,"@typeaheadAnimation",0],[2,"active",null]],[[null,"@typeaheadAnimation.done"],[null,"click"],[null,"mouseenter"]],function(t,e,n){var a=!0,r=t.component;return"@typeaheadAnimation.done"===e&&(a=!1!==r.positionServiceEnable()&&a),"click"===e&&(a=!1!==r.selectMatch(t.parent.context.$implicit,n)&&a),"mouseenter"===e&&(a=!1!==r.selectActive(t.parent.context.$implicit)&&a),a},null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,zd)),s["\u0275did"](2,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),s["\u0275pod"](3,{item:0,index:1,match:2,query:3})],function(t,e){var n=e.component,a=t(e,3,0,e.parent.context.$implicit.item,e.parent.context.index,e.parent.context.$implicit,n.query);t(e,2,0,a,n.itemTemplate||s["\u0275nov"](e.parent.parent.parent,5))},function(t,e){var n=e.component;t(e,0,0,n.animationState,n.isActive(e.parent.context.$implicit))})}function Yd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Fd)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Gd)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.context.$implicit.isHeader();t(e,1,0,n);var a=!e.context.$implicit.isHeader();t(e,3,0,a)},null)}function Vd(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Yd)),s["\u0275did"](1,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.component.matches)},null)}function Hd(t){return s["\u0275vid"](0,[s["\u0275qud"](671088640,1,{ulElement:0}),s["\u0275qud"](671088640,2,{liElements:1}),(t()(),s["\u0275and"](16777216,null,null,2,null,Dd)),s["\u0275did"](3,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutletContext:[0,"ngTemplateOutletContext"],ngTemplateOutlet:[1,"ngTemplateOutlet"]},null),s["\u0275pod"](4,{matches:0,itemTemplate:1,query:2}),(t()(),s["\u0275and"](0,[["bsItemTemplate",2]],null,0,null,Ed)),(t()(),s["\u0275and"](0,[["bs3Template",2]],null,0,null,jd)),(t()(),s["\u0275and"](0,[["bs4Template",2]],null,0,null,Vd))],function(t,e){var n=e.component,a=t(e,4,0,n.matches,n.itemTemplate,n.query);t(e,3,0,a,n.optionsListTemplate||s["\u0275nov"](e,n.isBs4?7:6))},null)}function Bd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"typeahead-container",[["class","dropdown open bottom"],["style","position: absolute;display: block;"]],[[2,"dropdown-menu",null],[4,"overflow-y",null],[4,"height",null],[4,"visibility",null],[2,"dropup",null]],[[null,"mouseleave"],[null,"blur"]],function(t,e,n){var a=!0;return"mouseleave"===e&&(a=!1!==s["\u0275nov"](t,1).focusLost()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,1).focusLost()&&a),a},Hd,Ad)),s["\u0275did"](1,49152,null,0,Ju,[Q.a,s.Renderer2,s.ElementRef],null,null)],null,function(t,e){t(e,0,0,s["\u0275nov"](e,1).isBs4,s["\u0275nov"](e,1).isBs4&&s["\u0275nov"](e,1).needScrollbar?"scroll":"visible",s["\u0275nov"](e,1).isBs4&&s["\u0275nov"](e,1).needScrollbar?s["\u0275nov"](e,1).guiHeight:"auto",s["\u0275nov"](e,1).visibility,s["\u0275nov"](e,1).dropup)})}var Ud=s["\u0275ccf"]("typeahead-container",Ju,Bd,{},{},[]),Wd=n("ajRT"),Kd=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function $d(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](-1,null,["Deep "]))],null,null)}function Zd(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](-1,null,["deep "]))],null,null)}function Xd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,9,"p",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["You are about to apply a "])),(t()(),s["\u0275eld"](3,0,null,null,3,null,null,null,null,null,null,null)),s["\u0275did"](4,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Zd)),s["\u0275did"](6,278528,null,0,i.NgSwitchCase,[s.ViewContainerRef,s.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),s["\u0275ted"](-1,null,["scrub to the OSD "])),(t()(),s["\u0275eld"](8,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](9,null,["",""])),(t()(),s["\u0275ted"](-1,null,["."]))],function(t,e){t(e,4,0,e.component.deep),t(e,6,0,"1")},function(t,e){t(e,9,0,e.component.selected[0].id)})}function Jd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,23,"cd-modal",[],null,null,null,_d.c,_d.b)),s["\u0275did"](1,49152,null,0,Wd.a,[],{modalRef:[0,"modalRef"]},null),(t()(),s["\u0275eld"](2,0,null,0,6,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["OSDs "])),(t()(),s["\u0275eld"](4,0,null,null,3,null,null,null,null,null,null,null)),s["\u0275did"](5,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,$d)),s["\u0275did"](7,278528,null,0,i.NgSwitchCase,[s.ViewContainerRef,s.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),s["\u0275ted"](-1,null,["Scrub"])),(t()(),s["\u0275eld"](9,0,null,1,14,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,13,"form",[["class","form-horizontal"],["name","scrubForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,12).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,12).onReset()&&a),a},null,null)),s["\u0275did"](11,16384,null,0,Te.D,[],null,null),s["\u0275did"](12,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](14,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](15,0,null,null,2,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Xd)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.scrub()&&a),a},$a.b,$a.a)),s["\u0275did"](20,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](-1,0,["Submit"])),(t()(),s["\u0275eld"](22,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,Xa.b,Xa.a)),s["\u0275did"](23,49152,null,0,Ja.a,[i.Location,Zn.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,1,0,n.bsModalRef),t(e,5,0,n.deep),t(e,7,0,"1"),t(e,12,0,n.scrubForm),t(e,17,0,1===n.selected.length),t(e,20,0,n.scrubForm),t(e,23,0,"Cancel",n.bsModalRef.hide)},function(t,e){t(e,10,0,s["\u0275nov"](e,14).ngClassUntouched,s["\u0275nov"](e,14).ngClassTouched,s["\u0275nov"](e,14).ngClassPristine,s["\u0275nov"](e,14).ngClassDirty,s["\u0275nov"](e,14).ngClassValid,s["\u0275nov"](e,14).ngClassInvalid,s["\u0275nov"](e,14).ngClassPending)})}function Qd(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-scrub-modal",[],null,null,null,Jd,Kd)),s["\u0275did"](1,114688,null,0,da,[pa.a,Ln,Jn.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var tf=s["\u0275ccf"]("cd-osd-scrub-modal",da,Qd,{},{},[]),ef=s["\u0275crt"]({encapsulation:0,styles:[[".osd-modal[_ngcontent-%COMP%] .oa-hr-small[_ngcontent-%COMP%]{margin:5px}"]],data:{}});function nf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"hr",[["class","oa-hr-small"]],null,null,null,null,null))],null,null)}function af(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,10,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"input",[["type","checkbox"]],[[8,"checked",0],[8,"name",0],[8,"id",0],[8,"disabled",0]],[[null,"change"]],function(t,e,n){var a=!0;return"change"===e&&(a=0!=(t.context.$implicit.value=!t.context.$implicit.value)&&a),a},null,null)),s["\u0275did"](2,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](3,0,null,null,5,"label",[["ng-class","['tc_' + key]"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275eld"](6,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,1,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),s["\u0275ted"](8,null,["",""])),(t()(),s["\u0275and"](16777216,null,null,1,null,nf)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,10,0,!e.context.last)},function(t,e){t(e,1,0,e.context.$implicit.value,e.context.$implicit.code,e.context.$implicit.code,e.context.$implicit.disabled),t(e,3,0,e.context.$implicit.code),t(e,5,0,e.context.$implicit.name),t(e,8,0,e.context.$implicit.description)})}function rf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submitAction()&&a),a},$a.b,$a.a)),s["\u0275did"](1,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](-1,0,["Submit"]))],function(t,e){t(e,1,0,e.component.osdFlagsForm)},null)}function sf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,19,"cd-modal",[],null,null,null,_d.c,_d.b)),s["\u0275did"](1,49152,null,0,Wd.a,[],{modalRef:[0,"modalRef"]},null),(t()(),s["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Cluster-wide OSD Flags"])),(t()(),s["\u0275eld"](4,0,null,1,15,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,14,"form",[["cdFormScope","osd"],["name","osdFlagsForm"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,8).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,8).onReset()&&a),a},null,null)),s["\u0275did"](6,16384,null,0,Se.a,[],{cdFormScope:[0,"cdFormScope"]},null),s["\u0275did"](7,16384,null,0,Te.D,[],null,null),s["\u0275did"](8,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](10,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](11,0,null,null,2,"div",[["class","modal-body osd-modal"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,af)),s["\u0275did"](13,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275eld"](14,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](15,0,null,null,4,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,rf)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,Xa.b,Xa.a)),s["\u0275did"](19,49152,null,0,Ja.a,[i.Location,Zn.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,1,0,n.bsModalRef),t(e,6,0,"osd"),t(e,8,0,n.osdFlagsForm),t(e,13,0,n.flags),t(e,17,0,n.permissions.osd.update),t(e,19,0,"Cancel",n.bsModalRef.hide)},function(t,e){t(e,5,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending)})}function of(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-flags-modal",[],null,null,null,sf,ef)),s["\u0275did"](1,114688,null,0,Qn,[pa.a,l.a,Ln,Jn.a,xt.a],null,null)],function(t,e){t(e,1,0)},null)}var uf=s["\u0275ccf"]("cd-osd-flags-modal",Qn,of,{},{},[]),cf=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function lf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit.name),t(e,2,0,e.context.$implicit.name)},function(t,e){t(e,3,0,e.context.$implicit.text)})}function df(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required."]))],null,null)}function ff(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](1,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](2,0,["",""]))],null,function(t,e){t(e,2,0,e.parent.context.$implicit.value.desc)})}function pf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"span",[["class","required"]],null,null,null,null,null))],null,null)}function hf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function gf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.value.patternHelpText)})}function bf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too high! It must not be greater than ","."]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.value.maxValue)})}function mf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too low! It must not be lower than ","."]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.value.minValue)})}function yf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,25,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,5,"label",[["class","control-label col-sm-6"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](4,null,[""," "])),(t()(),s["\u0275and"](16777216,null,null,1,null,ff)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,pf)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](9,0,null,null,16,"div",[["class","col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,7,"input",[["class","form-control"],["type","number"]],[[8,"id",0],[8,"readOnly",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,12)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,12).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,12)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,12)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,13).onChange(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,13).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,13).onTouched()&&a),a},null,null)),s["\u0275did"](11,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](12,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](13,16384,null,0,Te.C,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Te.C]),s["\u0275did"](15,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](17,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,hf)),s["\u0275did"](19,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,gf)),s["\u0275did"](21,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,bf)),s["\u0275did"](23,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,mf)),s["\u0275did"](25,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.osdRecvSpeedForm.getValue("customizePriority")&&n.osdRecvSpeedForm.showError(e.context.$implicit.key,s["\u0275nov"](e.parent,8)));t(e,1,0,"form-group",a),t(e,6,0,e.context.$implicit.value.desc),t(e,8,0,n.osdRecvSpeedForm.getValue("customizePriority")),t(e,15,0,e.context.$implicit.key),t(e,19,0,n.osdRecvSpeedForm.getValue("customizePriority")&&n.osdRecvSpeedForm.showError(e.context.$implicit.key,s["\u0275nov"](e.parent,8),"required")),t(e,21,0,n.osdRecvSpeedForm.getValue("customizePriority")&&n.osdRecvSpeedForm.showError(e.context.$implicit.key,s["\u0275nov"](e.parent,8),"pattern")),t(e,23,0,n.osdRecvSpeedForm.getValue("customizePriority")&&n.osdRecvSpeedForm.showError(e.context.$implicit.key,s["\u0275nov"](e.parent,8),"max")),t(e,25,0,n.osdRecvSpeedForm.getValue("customizePriority")&&n.osdRecvSpeedForm.showError(e.context.$implicit.key,s["\u0275nov"](e.parent,8),"min"))},function(t,e){var n=e.component;t(e,3,0,e.context.$implicit.key),t(e,4,0,e.context.$implicit.value.text),t(e,10,0,e.context.$implicit.key,!n.osdRecvSpeedForm.getValue("customizePriority"),s["\u0275nov"](e,17).ngClassUntouched,s["\u0275nov"](e,17).ngClassTouched,s["\u0275nov"](e,17).ngClassPristine,s["\u0275nov"](e,17).ngClassDirty,s["\u0275nov"](e,17).ngClassValid,s["\u0275nov"](e,17).ngClassInvalid,s["\u0275nov"](e,17).ngClassPending)})}function vf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submitAction()&&a),a},$a.b,$a.a)),s["\u0275did"](1,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](-1,0,["Submit"]))],function(t,e){t(e,1,0,e.component.osdRecvSpeedForm)},null)}function _f(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,51,"cd-modal",[],null,null,null,_d.c,_d.b)),s["\u0275did"](1,49152,null,0,Wd.a,[],{modalRef:[0,"modalRef"]},null),(t()(),s["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["OSD Recovery Priority"])),(t()(),s["\u0275eld"](4,0,null,1,47,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,46,"form",[["cdFormScope","osd"],["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,8).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,8).onReset()&&a),a},null,null)),s["\u0275did"](6,16384,null,0,Se.a,[],{cdFormScope:[0,"cdFormScope"]},null),s["\u0275did"](7,16384,null,0,Te.D,[],null,null),s["\u0275did"](8,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](10,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](11,0,null,null,34,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](13,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](14,{"has-error":0}),(t()(),s["\u0275eld"](15,0,null,null,3,"label",[["class","control-label col-sm-6"],["for","priority"]],null,null,null,null,null)),(t()(),s["\u0275eld"](16,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Priority"])),(t()(),s["\u0275eld"](18,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,11,"div",[["class","col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](20,0,null,null,8,"select",[["class","form-control"],["formControlName","priority"],["id","priority"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,22).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,22).onTouched()&&a),"change"===e&&(a=!1!==r.onPriorityChange(n.target.value)&&a),a},null,null)),s["\u0275did"](21,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](22,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](24,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](26,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,lf)),s["\u0275did"](28,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,df)),s["\u0275did"](30,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](31,0,null,null,11,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](32,0,null,null,10,"div",[["class","col-sm-offset-6 col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](33,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](34,0,null,null,6,"input",[["formControlName","customizePriority"],["id","customizePriority"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0,r=t.component;return"change"===e&&(a=!1!==s["\u0275nov"](t,36).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,36).onTouched()&&a),"change"===e&&(a=!1!==r.onCustomizePriorityChange()&&a),a},null,null)),s["\u0275did"](35,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](36,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](38,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](40,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](41,0,null,null,1,"label",[["for","customizePriority"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Customize priority values"])),(t()(),s["\u0275and"](16777216,null,null,2,null,yf)),s["\u0275did"](44,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),s["\u0275pid"](0,i.KeyValuePipe,[s.KeyValueDiffers]),(t()(),s["\u0275eld"](46,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](47,0,null,null,4,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,vf)),s["\u0275did"](49,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](50,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,Xa.b,Xa.a)),s["\u0275did"](51,49152,null,0,Ja.a,[i.Location,Zn.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,1,0,n.bsModalRef),t(e,6,0,"osd"),t(e,8,0,n.osdRecvSpeedForm);var a=t(e,14,0,n.osdRecvSpeedForm.showError("priority",s["\u0275nov"](e,8)));t(e,13,0,"form-group",a),t(e,24,0,"priority"),t(e,28,0,n.priorities),t(e,30,0,n.osdRecvSpeedForm.showError("priority",s["\u0275nov"](e,8),"required")),t(e,38,0,"customizePriority"),t(e,44,0,s["\u0275unv"](e,44,0,s["\u0275nov"](e,45).transform(n.priorityAttrs))),t(e,49,0,n.permissions.configOpt.update),t(e,51,0,"Cancel",n.bsModalRef.hide)},function(t,e){t(e,5,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending),t(e,20,0,s["\u0275nov"](e,26).ngClassUntouched,s["\u0275nov"](e,26).ngClassTouched,s["\u0275nov"](e,26).ngClassPristine,s["\u0275nov"](e,26).ngClassDirty,s["\u0275nov"](e,26).ngClassValid,s["\u0275nov"](e,26).ngClassInvalid,s["\u0275nov"](e,26).ngClassPending),t(e,34,0,s["\u0275nov"](e,40).ngClassUntouched,s["\u0275nov"](e,40).ngClassTouched,s["\u0275nov"](e,40).ngClassPristine,s["\u0275nov"](e,40).ngClassDirty,s["\u0275nov"](e,40).ngClassValid,s["\u0275nov"](e,40).ngClassInvalid,s["\u0275nov"](e,40).ngClassPending)})}function xf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-recv-speed-modal",[],null,null,null,_f,cf)),s["\u0275did"](1,114688,null,0,ua,[pa.a,l.a,ea.a,Jn.a,xt.a,Ln],null,null)],function(t,e){t(e,1,0)},null)}var Tf=s["\u0275ccf"]("cd-osd-recv-speed-modal",ua,xf,{},{},[]),wf=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Sf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required."]))],null,null)}function Of(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["The value needs to be between 0 and 1."]))],null,null)}function If(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Sf)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Of)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,null==n.weight.errors?null:n.weight.errors.required),t(e,4,0,(null==n.weight.errors?null:n.weight.errors.max)||(null==n.weight.errors?null:n.weight.errors.min))},null)}function Cf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,32,"cd-modal",[],null,null,null,_d.c,_d.b)),s["\u0275did"](1,49152,null,0,Wd.a,[],{modalRef:[0,"modalRef"]},null),(t()(),s["\u0275eld"](2,0,null,0,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Reweight OSD"])),(t()(),s["\u0275eld"](4,0,null,1,28,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,27,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,7).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,7).onReset()&&a),a},null,null)),s["\u0275did"](6,16384,null,0,Te.D,[],null,null),s["\u0275did"](7,540672,null,0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](9,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](10,0,null,null,16,"div",[["class","modal-body"]],null,null,null,null,null)),s["\u0275did"](11,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](12,{"has-error":0}),(t()(),s["\u0275eld"](13,0,null,null,13,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,null,1,"label",[["class","col-sm-2 control-label"],["for","weight"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Weight"])),(t()(),s["\u0275eld"](16,0,null,null,10,"div",[["class","col-sm-10"]],null,null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,7,"input",[["class","form-control"],["formControlName","weight"],["id","weight"],["max","1"],["min","0"],["step","0.1"],["type","number"]],[[8,"value",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"change"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,19)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,19).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,19)._compositionEnd(n.target.value)&&a),"change"===e&&(a=!1!==s["\u0275nov"](t,20).onChange(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,20).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,20).onTouched()&&a),a},null,null)),s["\u0275did"](18,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](19,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275did"](20,16384,null,0,Te.C,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t,e){return[t,e]},[Te.e,Te.C]),s["\u0275did"](22,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](24,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,If)),s["\u0275did"](26,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](27,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](28,0,null,null,2,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.reweight()&&a),a},$a.b,$a.a)),s["\u0275did"](29,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],disabled:[1,"disabled"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](-1,0,["Reweight"])),(t()(),s["\u0275eld"](31,0,null,null,1,"cd-back-button",[["name","Cancel"]],null,null,null,Xa.b,Xa.a)),s["\u0275did"](32,49152,null,0,Ja.a,[i.Location,Zn.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,1,0,n.bsModalRef),t(e,7,0,n.reweightForm);var a=t(e,12,0,n.weight.errors);t(e,11,0,"modal-body",a),t(e,22,0,"weight"),t(e,26,0,n.weight.errors),t(e,29,0,n.reweightForm,n.reweightForm.invalid),t(e,32,0,"Cancel",n.bsModalRef.hide)},function(t,e){var n=e.component;t(e,5,0,s["\u0275nov"](e,9).ngClassUntouched,s["\u0275nov"](e,9).ngClassTouched,s["\u0275nov"](e,9).ngClassPristine,s["\u0275nov"](e,9).ngClassDirty,s["\u0275nov"](e,9).ngClassValid,s["\u0275nov"](e,9).ngClassInvalid,s["\u0275nov"](e,9).ngClassPending),t(e,17,0,n.currentWeight,s["\u0275nov"](e,24).ngClassUntouched,s["\u0275nov"](e,24).ngClassTouched,s["\u0275nov"](e,24).ngClassPristine,s["\u0275nov"](e,24).ngClassDirty,s["\u0275nov"](e,24).ngClassValid,s["\u0275nov"](e,24).ngClassInvalid,s["\u0275nov"](e,24).ngClassPending)})}function kf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-reweight-modal",[],null,null,null,Cf,wf)),s["\u0275did"](1,114688,null,0,la,[pa.a,Ln,ca.a],null,null)],function(t,e){t(e,1,0)},null)}var Nf=s["\u0275ccf"]("cd-osd-reweight-modal",la,kf,{},{},[]),Rf=s["\u0275crt"]({encapsulation:0,styles:[["hr[_ngcontent-%COMP%]{margin-top:5px;margin-bottom:5px}.control-label[_ngcontent-%COMP%]{text-align:left}.checkbox-primary[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{width:23px;height:15px;margin-left:0;cursor:pointer}.checkbox-primary[_ngcontent-%COMP%] label[_ngcontent-%COMP%]{cursor:auto}.checkbox-primary[_ngcontent-%COMP%] label[_ngcontent-%COMP%]:after, .checkbox-primary[_ngcontent-%COMP%] label[_ngcontent-%COMP%]:before{margin-left:0}.form-group[_ngcontent-%COMP%] .col-sm-6[_ngcontent-%COMP%]{padding-top:7px}"]],data:{}});function Af(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](1,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](2,0,[" ",""]))],null,function(t,e){t(e,2,0,e.parent.parent.context.$implicit.long_desc)})}function Df(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,18,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,6,"label",[["class","col-sm-6 control-label"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](4,null,[" "," "])),(t()(),s["\u0275eld"](5,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,3,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,[" "," "])),(t()(),s["\u0275and"](16777216,null,null,1,null,Af)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](10,0,null,null,8,"div",[["class","col-sm-6 checkbox-primary checkbox"]],null,null,null,null,null)),(t()(),s["\u0275eld"](11,0,null,null,6,"input",[["type","checkbox"]],[[8,"id",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,12).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,12).onTouched()&&a),a},null,null)),s["\u0275did"](12,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](14,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](16,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](17,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](18,0,null,null,0,"label",[],null,null,null,null,null))],function(t,e){var n=e.component,a=t(e,2,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir));t(e,1,0,"form-group",a),t(e,9,0,e.parent.context.$implicit.long_desc),t(e,14,0,e.parent.context.$implicit.name)},function(t,e){t(e,3,0,e.parent.context.$implicit.name),t(e,4,0,e.parent.context.$implicit.text),t(e,7,0,e.parent.context.$implicit.desc),t(e,11,0,e.parent.context.$implicit.name,s["\u0275nov"](e,16).ngClassUntouched,s["\u0275nov"](e,16).ngClassTouched,s["\u0275nov"](e,16).ngClassPristine,s["\u0275nov"](e,16).ngClassDirty,s["\u0275nov"](e,16).ngClassValid,s["\u0275nov"](e,16).ngClassInvalid,s["\u0275nov"](e,16).ngClassPending)})}function Ef(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-helper",[],null,null,null,ks.b,ks.a)),s["\u0275did"](1,49152,null,0,Ns.a,[],null,null),(t()(),s["\u0275ted"](2,0,[" ",""]))],null,function(t,e){t(e,2,0,e.parent.parent.context.$implicit.long_desc)})}function Lf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"span",[["class","input-group-btn"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"button",[["class","btn btn-default"],["data-toggle","button"],["title","Remove the custom configuration value. The default configuration will be inherited and used instead."],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.resetValue(t.parent.parent.context.$implicit.name)&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-eraser"]],null,null,null,null,null))],null,null)}function Pf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ",""]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.additionalTypeInfo.patternHelpText)})}function Mf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" ",""]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.additionalTypeInfo.patternHelpText)})}function qf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too high! It must not be greater than ","."]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.maxValue)})}function jf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["The entered value is too low! It must not be lower than ","."]))],null,function(t,e){t(e,1,0,e.parent.parent.context.$implicit.minValue)})}function Ff(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,28,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{"has-error":0}),(t()(),s["\u0275eld"](3,0,null,null,6,"label",[["class","col-sm-6 control-label"]],[[8,"htmlFor",0]],null,null,null,null)),(t()(),s["\u0275ted"](4,null,[""," "])),(t()(),s["\u0275eld"](5,0,null,null,0,"br",[],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,3,"span",[["class","text-muted"]],null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,[" "," "])),(t()(),s["\u0275and"](16777216,null,null,1,null,Ef)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](10,0,null,null,18,"div",[["class","col-sm-6"]],null,null,null,null,null)),(t()(),s["\u0275eld"](11,0,null,null,9,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,6,"input",[["class","form-control"]],[[8,"type",0],[8,"id",0],[8,"placeholder",0],[8,"step",0],[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,13)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,13).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,13)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,13)._compositionEnd(n.target.value)&&a),a},null,null)),s["\u0275did"](13,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](15,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](17,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](18,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Lf)),s["\u0275did"](20,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Pf)),s["\u0275did"](22,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Mf)),s["\u0275did"](24,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,qf)),s["\u0275did"](26,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,jf)),s["\u0275did"](28,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component,a=t(e,2,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir));t(e,1,0,"form-group",a),t(e,9,0,e.parent.context.$implicit.long_desc),t(e,15,0,e.parent.context.$implicit.name),t(e,20,0,n.optionsFormShowReset),t(e,22,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir,"pattern")),t(e,24,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir,"invalidUuid")),t(e,26,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir,"max")),t(e,28,0,n.optionsForm.showError(e.parent.context.$implicit.name,n.optionsFormDir,"min"))},function(t,e){var n=e.component;t(e,3,0,e.parent.context.$implicit.name),t(e,4,0,e.parent.context.$implicit.text),t(e,7,0,e.parent.context.$implicit.desc),t(e,12,1,[e.parent.context.$implicit.additionalTypeInfo.inputType,e.parent.context.$implicit.name,e.parent.context.$implicit.additionalTypeInfo.humanReadable,n.getStep(e.parent.context.$implicit.type,n.optionsForm.getValue(e.parent.context.$implicit.name)),s["\u0275nov"](e,17).ngClassUntouched,s["\u0275nov"](e,17).ngClassTouched,s["\u0275nov"](e,17).ngClassPristine,s["\u0275nov"](e,17).ngClassDirty,s["\u0275nov"](e,17).ngClassValid,s["\u0275nov"](e,17).ngClassInvalid,s["\u0275nov"](e,17).ngClassPending])})}function zf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,"hr",[],null,null,null,null,null))],null,null)}function Gf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"div",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Df)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ff)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,zf)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,2,0,"bool"===e.context.$implicit.type),t(e,4,0,"bool"!==e.context.$implicit.type),t(e,6,0,!e.context.last)},null)}function Yf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"div",[],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,1).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,1).onReset()&&a),a},null,null)),s["\u0275did"](1,540672,null,0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](3,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275and"](16777216,null,null,1,null,Gf)),s["\u0275did"](5,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){var n=e.component;t(e,1,0,n.optionsFormGroup),t(e,5,0,n.options)},function(t,e){t(e,0,0,s["\u0275nov"](e,3).ngClassUntouched,s["\u0275nov"](e,3).ngClassTouched,s["\u0275nov"](e,3).ngClassPristine,s["\u0275nov"](e,3).ngClassDirty,s["\u0275nov"](e,3).ngClassValid,s["\u0275nov"](e,3).ngClassInvalid,s["\u0275nov"](e,3).ngClassPending)})}var Vf=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Hf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"a",[["class","pull-right margin-right-md"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=0!=(t.component.advancedEnabled=!0)&&a),a},null,null)),(t()(),s["\u0275ted"](-1,null,["Advanced..."]))],null,null)}function Bf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"h2",[["class","page-header"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Advanced configuration options"])),(t()(),s["\u0275eld"](3,0,null,null,1,"cd-config-option",[],null,null,null,Yf,Rf)),s["\u0275did"](4,114688,[[2,4],["advancedOptionsValues",4]],0,ia,[ea.a],{optionNames:[0,"optionNames"],optionsForm:[1,"optionsForm"],optionsFormDir:[2,"optionsFormDir"],optionsFormGroupName:[3,"optionsFormGroupName"]},null)],function(t,e){var n=e.component;t(e,4,0,n.advancedOptions,n.osdPgScrubForm,s["\u0275nov"](e.parent,14),"advancedFormGroup")},null)}function Uf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,4,"cd-submit-button",[["type","button"]],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.submitAction()&&a),a},$a.b,$a.a)),s["\u0275did"](1,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"],type:[1,"type"]},{submitAction:"submitAction"}),(t()(),s["\u0275ted"](2,0,[""," ",""])),s["\u0275ppd"](3,1),s["\u0275ppd"](4,1)],function(t,e){t(e,1,0,e.component.osdPgScrubForm,"button")},function(t,e){var n=e.component,a=s["\u0275unv"](e,2,0,t(e,3,0,s["\u0275nov"](e.parent,0),n.action)),r=s["\u0275unv"](e,2,1,t(e,4,0,s["\u0275nov"](e.parent,1),n.resource));t(e,2,0,a,r)})}function Wf(t){return s["\u0275vid"](0,[s["\u0275pid"](0,i.TitleCasePipe,[]),s["\u0275pid"](0,Rs.a,[]),s["\u0275qud"](402653184,1,{basicOptionsValues:0}),s["\u0275qud"](671088640,2,{advancedOptionsValues:0}),(t()(),s["\u0275eld"](4,0,null,null,27,"cd-modal",[],null,null,null,_d.c,_d.b)),s["\u0275did"](5,49152,null,0,Wd.a,[],{modalRef:[0,"modalRef"]},null),(t()(),s["\u0275eld"](6,0,null,0,3,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](7,null,[""," ",""])),s["\u0275ppd"](8,1),s["\u0275ppd"](9,1),(t()(),s["\u0275eld"](10,0,null,1,21,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](11,0,null,null,20,"form",[["cdFormScope","osd"],["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,14).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,14).onReset()&&a),a},null,null)),s["\u0275did"](12,16384,null,0,Se.a,[],{cdFormScope:[0,"cdFormScope"]},null),s["\u0275did"](13,16384,null,0,Te.D,[],null,null),s["\u0275did"](14,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](16,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](17,0,null,null,8,"div",[["class","modal-body osd-modal"]],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,1,"cd-config-option",[],null,null,null,Yf,Rf)),s["\u0275did"](19,114688,[[1,4],["basicOptionsValues",4]],0,ia,[ea.a],{optionNames:[0,"optionNames"],optionsForm:[1,"optionsForm"],optionsFormDir:[2,"optionsFormDir"],optionsFormGroupName:[3,"optionsFormGroupName"]},null),(t()(),s["\u0275eld"](20,0,null,null,3,"div",[["class","row"]],null,null,null,null,null)),(t()(),s["\u0275eld"](21,0,null,null,2,"div",[["class","col-sm-12"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Hf)),s["\u0275did"](23,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Bf)),s["\u0275did"](25,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](26,0,null,null,5,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](27,0,null,null,4,"div",[["class","button-group text-right"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Uf)),s["\u0275did"](29,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](30,0,null,null,1,"cd-back-button",[],null,null,null,Xa.b,Xa.a)),s["\u0275did"](31,49152,null,0,Ja.a,[i.Location,Zn.b],{back:[0,"back"]},null)],function(t,e){var n=e.component;t(e,5,0,n.bsModalRef),t(e,12,0,"osd"),t(e,14,0,n.osdPgScrubForm),t(e,19,0,n.basicOptions,n.osdPgScrubForm,s["\u0275nov"](e,14),"basicFormGroup"),t(e,23,0,!n.advancedEnabled),t(e,25,0,n.advancedEnabled),t(e,29,0,n.permissions.configOpt.update),t(e,31,0,n.bsModalRef.hide)},function(t,e){var n=e.component,a=s["\u0275unv"](e,7,0,t(e,8,0,s["\u0275nov"](e,0),n.action)),r=s["\u0275unv"](e,7,1,t(e,9,0,s["\u0275nov"](e,1),n.resource));t(e,7,0,a,r),t(e,11,0,s["\u0275nov"](e,16).ngClassUntouched,s["\u0275nov"](e,16).ngClassTouched,s["\u0275nov"](e,16).ngClassPristine,s["\u0275nov"](e,16).ngClassDirty,s["\u0275nov"](e,16).ngClassValid,s["\u0275nov"](e,16).ngClassInvalid,s["\u0275nov"](e,16).ngClassPending)})}function Kf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-osd-pg-scrub-modal",[],null,null,null,Wf,Vf)),s["\u0275did"](1,49152,null,0,oa,[pa.a,l.a,Jn.a,xt.a,Zn.b],null,null)],null,null)}var $f=s["\u0275ccf"]("cd-osd-pg-scrub-modal",oa,Kf,{},{},[]),Zf=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Xf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](1,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{value:[0,"value"]},null),s["\u0275did"](2,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{value:[0,"value"]},null),(t()(),s["\u0275ted"](3,null,[" "," "]))],function(t,e){t(e,1,0,e.context.$implicit),t(e,2,0,e.context.$implicit)},function(t,e){t(e,3,0,e.context.$implicit)})}function Jf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function Qf(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","help-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["This field is required!"]))],null,null)}function tp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[["id","match-state"]],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[],[[8,"className",0]],null,null,null,null)),(t()(),s["\u0275ted"](2,null,[" "," "]))],null,function(t,e){var n=e.component;t(e,0,0,s["\u0275inlineInterpolate"](1,"col-sm-offset-3 col-sm-9 ",n.matcherMatch.cssClass,"")),t(e,1,0,s["\u0275inlineInterpolate"](1,"help-block ",n.matcherMatch.cssClass,"")),t(e,2,0,n.matcherMatch.status)})}function ep(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](-1,null,["Update"]))],null,null)}function np(t){return s["\u0275vid"](0,[(t()(),s["\u0275ted"](-1,null,["Add"]))],null,null)}function ap(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"div",[["class","modal-header"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"h4",[["class","modal-title pull-left"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Matcher"])),(t()(),s["\u0275eld"](3,0,null,null,2,"button",[["aria-label","Close"],["class","close pull-right"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.bsModalRef.hide()&&a),a},null,null)),(t()(),s["\u0275eld"](4,0,null,null,1,"span",[["aria-hidden","true"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["\xd7"])),(t()(),s["\u0275eld"](6,0,null,null,73,"form",[["class","form-horizontal"],["novalidate",""]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"submit"],[null,"reset"]],function(t,e,n){var a=!0;return"submit"===e&&(a=!1!==s["\u0275nov"](t,8).onSubmit(n)&&a),"reset"===e&&(a=!1!==s["\u0275nov"](t,8).onReset()&&a),a},null,null)),s["\u0275did"](7,16384,null,0,Te.D,[],null,null),s["\u0275did"](8,540672,[["formDir",4]],0,Te.l,[[8,null],[8,null]],{form:[0,"form"]},null),s["\u0275prd"](2048,null,Te.d,null,[Te.l]),s["\u0275did"](10,16384,null,0,Te.s,[[4,Te.d]],null,null),(t()(),s["\u0275eld"](11,0,null,null,56,"div",[["class","modal-body"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,22,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](13,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](14,{"has-error":0}),(t()(),s["\u0275eld"](15,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","name"]],null,null,null,null,null)),(t()(),s["\u0275eld"](16,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Name"])),(t()(),s["\u0275eld"](18,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,15,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](20,0,null,null,12,"select",[["class","form-control"],["formControlName","name"],["id","name"],["name","name"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,22).onChange(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,22).onTouched()&&a),a},null,null)),s["\u0275did"](21,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](22,16384,null,0,Te.z,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.z]),s["\u0275did"](24,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](26,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](27,0,null,null,3,"option",[],null,null,null,null,null)),s["\u0275did"](28,147456,null,0,Te.v,[s.ElementRef,s.Renderer2,[2,Te.z]],{ngValue:[0,"ngValue"]},null),s["\u0275did"](29,147456,null,0,Te.G,[s.ElementRef,s.Renderer2,[8,null]],{ngValue:[0,"ngValue"]},null),(t()(),s["\u0275ted"](-1,null,["-- Select an attribute to match against --"])),(t()(),s["\u0275and"](16777216,null,null,1,null,Xf)),s["\u0275did"](32,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Jf)),s["\u0275did"](34,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](35,0,null,null,19,"div",[["class","form-group"]],null,null,null,null,null)),s["\u0275did"](36,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](37,{"has-error":0}),(t()(),s["\u0275eld"](38,0,null,null,3,"label",[["class","control-label col-sm-3"],["for","value"]],null,null,null,null,null)),(t()(),s["\u0275eld"](39,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Value"])),(t()(),s["\u0275eld"](41,0,null,null,0,"span",[["class","required"]],null,null,null,null,null)),(t()(),s["\u0275eld"](42,0,null,null,10,"div",[["class","col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](43,16777216,null,null,7,"input",[["class","form-control"],["formControlName","value"],["id","value"],["type","text"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"input"],[null,"blur"],[null,"compositionstart"],[null,"compositionend"],[null,"keyup"],[null,"click"],[null,"focus"],[null,"keydown"]],function(t,e,n){var a=!0;return"input"===e&&(a=!1!==s["\u0275nov"](t,45)._handleInput(n.target.value)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,45).onTouched()&&a),"compositionstart"===e&&(a=!1!==s["\u0275nov"](t,45)._compositionStart()&&a),"compositionend"===e&&(a=!1!==s["\u0275nov"](t,45)._compositionEnd(n.target.value)&&a),"input"===e&&(a=!1!==s["\u0275nov"](t,50).onInput(n)&&a),"keyup"===e&&(a=!1!==s["\u0275nov"](t,50).onChange(n)&&a),"click"===e&&(a=!1!==s["\u0275nov"](t,50).onFocus()&&a),"focus"===e&&(a=!1!==s["\u0275nov"](t,50).onFocus()&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,50).onBlur()&&a),"keydown"===e&&(a=!1!==s["\u0275nov"](t,50).onKeydown(n)&&a),a},null,null)),s["\u0275did"](44,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](45,16384,null,0,Te.e,[s.Renderer2,s.ElementRef,[2,Te.b]],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.e]),s["\u0275did"](47,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](49,16384,null,0,Te.r,[[4,Te.q]],null,null),s["\u0275did"](50,212992,null,0,tc,[J.a,Qu,s.ChangeDetectorRef,s.ElementRef,Te.q,s.Renderer2,s.ViewContainerRef],{typeahead:[0,"typeahead"],typeaheadMinLength:[1,"typeaheadMinLength"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Qf)),s["\u0275did"](52,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,tp)),s["\u0275did"](54,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](55,0,null,null,12,"div",[["class","form-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](56,0,null,null,11,"div",[["class","col-sm-offset-3 col-sm-9"]],null,null,null,null,null)),(t()(),s["\u0275eld"](57,0,null,null,10,"div",[["class","input-group"]],null,null,null,null,null)),(t()(),s["\u0275eld"](58,0,null,null,9,"div",[["class","checkbox checkbox-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](59,0,null,null,6,"input",[["formControlName","isRegex"],["id","is-regex"],["type","checkbox"]],[[2,"ng-untouched",null],[2,"ng-touched",null],[2,"ng-pristine",null],[2,"ng-dirty",null],[2,"ng-valid",null],[2,"ng-invalid",null],[2,"ng-pending",null]],[[null,"change"],[null,"blur"]],function(t,e,n){var a=!0;return"change"===e&&(a=!1!==s["\u0275nov"](t,61).onChange(n.target.checked)&&a),"blur"===e&&(a=!1!==s["\u0275nov"](t,61).onTouched()&&a),a},null,null)),s["\u0275did"](60,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),s["\u0275did"](61,16384,null,0,Te.c,[s.Renderer2,s.ElementRef],null,null),s["\u0275prd"](1024,null,Te.p,function(t){return[t]},[Te.c]),s["\u0275did"](63,671744,null,0,Te.j,[[3,Te.d],[8,null],[8,null],[6,Te.p],[2,Te.F]],{name:[0,"name"]},null),s["\u0275prd"](2048,null,Te.q,null,[Te.j]),s["\u0275did"](65,16384,null,0,Te.r,[[4,Te.q]],null,null),(t()(),s["\u0275eld"](66,0,null,null,1,"label",[["for","is-regex"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Use regular expression"])),(t()(),s["\u0275eld"](68,0,null,null,11,"div",[["class","modal-footer"]],null,null,null,null,null)),(t()(),s["\u0275eld"](69,0,null,null,8,"cd-submit-button",[],null,[[null,"submitAction"]],function(t,e,n){var a=!0;return"submitAction"===e&&(a=!1!==t.component.onSubmit()&&a),a},$a.b,$a.a)),s["\u0275did"](70,114688,null,0,Za.a,[s.ElementRef],{form:[0,"form"]},{submitAction:"submitAction"}),(t()(),s["\u0275eld"](71,0,null,0,6,null,null,null,null,null,null,null)),(t()(),s["\u0275eld"](72,0,null,null,5,null,null,null,null,null,null,null)),s["\u0275did"](73,16384,null,0,i.NgSwitch,[],{ngSwitch:[0,"ngSwitch"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ep)),s["\u0275did"](75,278528,null,0,i.NgSwitchCase,[s.ViewContainerRef,s.TemplateRef,i.NgSwitch],{ngSwitchCase:[0,"ngSwitchCase"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,np)),s["\u0275did"](77,16384,null,0,i.NgSwitchDefault,[s.ViewContainerRef,s.TemplateRef,i.NgSwitch],null,null),(t()(),s["\u0275eld"](78,0,null,null,1,"cd-back-button",[["name","Close"]],null,null,null,Xa.b,Xa.a)),s["\u0275did"](79,49152,null,0,Ja.a,[i.Location,Zn.b],{name:[0,"name"],back:[1,"back"]},null)],function(t,e){var n=e.component;t(e,8,0,n.form);var a=t(e,14,0,n.form.showError("name",s["\u0275nov"](e,8)));t(e,13,0,"form-group",a),t(e,24,0,"name"),t(e,28,0,null),t(e,29,0,null),t(e,32,0,n.nameAttributes),t(e,34,0,n.form.showError("name",s["\u0275nov"](e,8),"required"));var r=t(e,37,0,n.form.showError("value",s["\u0275nov"](e,8)));t(e,36,0,"form-group",r),t(e,47,0,"value"),t(e,50,0,n.possibleValues,0),t(e,52,0,n.form.showError("value",s["\u0275nov"](e,8),"required")),t(e,54,0,n.form.getValue("value")&&!n.form.getValue("isRegex")&&n.matcherMatch),t(e,63,0,"isRegex"),t(e,70,0,n.form),t(e,73,0,n.editMode),t(e,75,0,"1"),t(e,79,0,"Close",n.bsModalRef.hide)},function(t,e){t(e,6,0,s["\u0275nov"](e,10).ngClassUntouched,s["\u0275nov"](e,10).ngClassTouched,s["\u0275nov"](e,10).ngClassPristine,s["\u0275nov"](e,10).ngClassDirty,s["\u0275nov"](e,10).ngClassValid,s["\u0275nov"](e,10).ngClassInvalid,s["\u0275nov"](e,10).ngClassPending),t(e,20,0,s["\u0275nov"](e,26).ngClassUntouched,s["\u0275nov"](e,26).ngClassTouched,s["\u0275nov"](e,26).ngClassPristine,s["\u0275nov"](e,26).ngClassDirty,s["\u0275nov"](e,26).ngClassValid,s["\u0275nov"](e,26).ngClassInvalid,s["\u0275nov"](e,26).ngClassPending),t(e,43,0,s["\u0275nov"](e,49).ngClassUntouched,s["\u0275nov"](e,49).ngClassTouched,s["\u0275nov"](e,49).ngClassPristine,s["\u0275nov"](e,49).ngClassDirty,s["\u0275nov"](e,49).ngClassValid,s["\u0275nov"](e,49).ngClassInvalid,s["\u0275nov"](e,49).ngClassPending),t(e,59,0,s["\u0275nov"](e,65).ngClassUntouched,s["\u0275nov"](e,65).ngClassTouched,s["\u0275nov"](e,65).ngClassPristine,s["\u0275nov"](e,65).ngClassDirty,s["\u0275nov"](e,65).ngClassValid,s["\u0275nov"](e,65).ngClassInvalid,s["\u0275nov"](e,65).ngClassPending)})}function rp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-silence-matcher-modal",[],null,null,null,ap,Zf)),s["\u0275did"](1,49152,null,0,Es,[ca.a,As,pa.a],null,null)],null,null)}var ip=s["\u0275ccf"]("cd-silence-matcher-modal",Es,rp,{},{submitAction:"submitAction"},[]),sp=[Object(ju.h)({height:0,visibility:"hidden"}),Object(ju.e)("400ms cubic-bezier(0.4,0.0,0.2,1)",Object(ju.h)({height:"*",visibility:"visible"}))],op=[Object(ju.h)({height:"*",visibility:"visible"}),Object(ju.e)("400ms cubic-bezier(0.4,0.0,0.2,1)",Object(ju.h)({height:0,visibility:"hidden"}))],up=function(){function t(t,e,n){this._el=t,this._renderer=e,this.collapsed=new s.EventEmitter,this.collapses=new s.EventEmitter,this.expanded=new s.EventEmitter,this.expands=new s.EventEmitter,this.isExpanded=!0,this.isCollapsed=!1,this.isCollapse=!0,this.isCollapsing=!1,this.isAnimated=!1,this._display="block",this._stylesLoaded=!1,this._COLLAPSE_ACTION_NAME="collapse",this._EXPAND_ACTION_NAME="expand",this._factoryCollapseAnimation=n.build(op),this._factoryExpandAnimation=n.build(sp)}return Object.defineProperty(t.prototype,"display",{set:function(t){this.isAnimated?(this._display=t,"none"!==t?this.show():this.hide()):this._renderer.setStyle(this._el.nativeElement,"display",t)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"collapse",{get:function(){return this.isExpanded},set:function(t){this.isExpanded=t,this.toggle()},enumerable:!0,configurable:!0}),t.prototype.ngAfterViewChecked=function(){this._stylesLoaded=!0},t.prototype.toggle=function(){this.isExpanded?this.hide():this.show()},t.prototype.hide=function(){var t=this;this.isCollapsing=!0,this.isExpanded=!1,this.isCollapsed=!0,this.isCollapsing=!1,this.collapses.emit(this),this.animationRun(this.isAnimated,this._COLLAPSE_ACTION_NAME)(function(){t.collapsed.emit(t),t._renderer.setStyle(t._el.nativeElement,"display","none")})},t.prototype.show=function(){var t=this;this._renderer.setStyle(this._el.nativeElement,"display",this._display),this.isCollapsing=!0,this.isExpanded=!0,this.isCollapsed=!1,this.isCollapsing=!1,this.expands.emit(this),this.animationRun(this.isAnimated,this._EXPAND_ACTION_NAME)(function(){t.expanded.emit(t)})},t.prototype.animationRun=function(t,e){var n=this;if(!t||!this._stylesLoaded)return function(t){return t()};this._renderer.setStyle(this._el.nativeElement,"overflow","hidden"),this._renderer.addClass(this._el.nativeElement,"collapse");var a=e===this._EXPAND_ACTION_NAME?this._factoryExpandAnimation:this._factoryCollapseAnimation;return this._player&&this._player.destroy(),this._player=a.create(this._el.nativeElement),this._player.play(),function(t){return n._player.onDone(t)}},t}(),cp=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[]}},t}(),lp=function(){function t(t,e){this.summaryService=t,this.taskMessageService=e,this.executingTasks=[],this.finishedTasks=[],this.icon="fa-hourglass-o"}return t.prototype.ngOnInit=function(){var t=this;this.summaryService.subscribe(function(e){e&&(t._handleTasks(e.executing_tasks,e.finished_tasks),t._setIcon(e.executing_tasks.length))})},t.prototype._handleTasks=function(t,e){for(var n=0,a=t;n<a.length;n++){var r=a[n];r.description=this.taskMessageService.getRunningTitle(r)}for(var i=0,s=e;i<s.length;i++){var o=s[i];!1===o.success?(o.description=this.taskMessageService.getErrorTitle(o),o.errorMessage=this.taskMessageService.getErrorMessage(o)):o.description=this.taskMessageService.getSuccessTitle(o)}this.executingTasks=t,this.finishedTasks=e},t.prototype._setIcon=function(t){this.icon="fa-hourglass-"+["o","start","half","end"][t>0?1:0]},t}(),dp=s["\u0275crt"]({encapsulation:0,styles:[[".popover-content{padding:.5em;height:auto;max-height:70vh;overflow-x:hidden} .popover{min-width:276px!important}.separator[_ngcontent-%COMP%]{padding:5px 12px;color:#90949c;background-color:#eee;font-size:12px}.message[_ngcontent-%COMP%]{padding:10px 16px;color:#474544;font-size:12px}table[_ngcontent-%COMP%]{width:252px;margin:5px 12px 5px 5px;font-size:12px;color:#474544}.icon-col[_ngcontent-%COMP%]{width:50px;font-size:10px}.date[_ngcontent-%COMP%]{color:#555}hr[_ngcontent-%COMP%]{margin-top:0;margin-bottom:0}"]],data:{}});function fp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"td",[["class","text-right italic"],["nowrap",""]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](2,null,[""," %"]))],null,function(t,e){t(e,2,0,e.parent.context.$implicit.progress)})}function pp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,18,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,16,"table",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,15,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,7,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,3,"td",[["class","icon-col text-center"],["rowspan","3"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,2,"span",[["class","fa-stack fa-2x text-info"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,0,"i",[["class","fa fa-circle fa-stack-2x"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,0,"i",[["class","fa fa-stack-1x fa-inverse fa-spinner fa-spin"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,2,"td",[["colspan","3"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](10,null,["",""])),(t()(),s["\u0275eld"](11,0,null,null,6,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,3,"td",[["colspan","2"]],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,2,"small",[["class","date"]],null,null,null,null,null)),(t()(),s["\u0275ted"](14,null,["",""])),s["\u0275ppd"](15,1),(t()(),s["\u0275and"](16777216,null,null,1,null,fp)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](18,0,null,null,0,"hr",[],null,null,null,null,null))],function(t,e){t(e,17,0,e.context.$implicit.progress)},function(t,e){t(e,10,0,e.context.$implicit.description);var n=s["\u0275unv"](e,14,0,t(e,15,0,s["\u0275nov"](e.parent.parent.parent,0),e.context.$implicit.begin_time));t(e,14,0,n)})}function hp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"div",[["class","separator"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["EXECUTING"])),(t()(),s["\u0275eld"](3,0,null,null,0,"hr",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,pp)),s["\u0275did"](5,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,5,0,e.component.executingTasks)},null)}function gp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"span",[["class","fa-stack fa-2x text-success"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"i",[["class","fa fa-circle fa-stack-2x"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,0,"i",[["class","fa fa-stack-1x fa-inverse fa-check"]],null,null,null,null,null))],null,null)}function bp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"span",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"span",[["class","fa-stack fa-2x text-danger"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"i",[["class","fa fa-circle fa-stack-2x"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,0,"i",[["class","fa fa-stack-1x fa-inverse fa-exclamation-triangle"]],null,null,null,null,null))],null,null)}function mp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[["class","text-danger"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" "," "]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.errorMessage)})}function yp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,22,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,20,"table",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,19,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,8,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,4,"td",[["class","icon-col text-center"],["rowspan","3"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,gp)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,bp)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](9,0,null,null,2,"td",[["colspan","2"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](11,null,["",""])),(t()(),s["\u0275eld"](12,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,0,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](14,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,mp)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](17,0,null,null,4,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,3,"td",[["colspan","2"]],null,null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,2,"small",[["class","date"]],null,null,null,null,null)),(t()(),s["\u0275ted"](20,null,["",""])),s["\u0275ppd"](21,1),(t()(),s["\u0275eld"](22,0,null,null,0,"hr",[],null,null,null,null,null))],function(t,e){t(e,6,0,!e.context.$implicit.errorMessage),t(e,8,0,e.context.$implicit.errorMessage),t(e,16,0,e.context.$implicit.errorMessage)},function(t,e){t(e,11,0,e.context.$implicit.description);var n=s["\u0275unv"](e,20,0,t(e,21,0,s["\u0275nov"](e.parent.parent.parent,0),e.context.$implicit.end_time));t(e,20,0,n)})}function vp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,5,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"div",[["class","separator"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["FINISHED"])),(t()(),s["\u0275eld"](3,0,null,null,0,"hr",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,yp)),s["\u0275did"](5,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,5,0,e.component.finishedTasks)},null)}function _p(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"div",[["class","message"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["There are no background tasks."]))],null,null)}function xp(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,hp)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,vp)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,_p)),s["\u0275did"](5,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,1,0,n.executingTasks.length>0),t(e,3,0,n.finishedTasks.length>0),t(e,5,0,0===n.executingTasks.length&&0===n.finishedTasks.length)},null)}function Tp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,[" (",")"]))],null,function(t,e){t(e,1,0,e.component.executingTasks.length)})}function wp(t){return s["\u0275vid"](0,[s["\u0275pid"](0,On.a,[i.DatePipe]),(t()(),s["\u0275and"](0,[["popTemplate",2]],null,0,null,xp)),(t()(),s["\u0275eld"](2,16777216,null,null,7,"a",[["container","body"],["outsideClick","true"],["placement","bottom"],["title","Background Tasks"]],null,null,null,null,null)),s["\u0275did"](3,212992,null,0,X.c,[X.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,Q.a],{popover:[0,"popover"],placement:[1,"placement"],outsideClick:[2,"outsideClick"],container:[3,"container"]},null),(t()(),s["\u0275eld"](4,0,null,null,1,"i",[["class","fa fa-fw"]],null,null,null,null,null)),s["\u0275did"](5,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","visible-xs-inline-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Background Tasks"])),(t()(),s["\u0275and"](16777216,null,null,1,null,Tp)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,3,0,s["\u0275nov"](e,1),"bottom","true","body"),t(e,5,0,"fa fa-fw",n.icon),t(e,9,0,n.executingTasks.length>0)},null)}var Sp=function(){function t(t,e){this.alertFormatter=t,this.prometheusService=e,this.backendFailure=!1,this.notifications=[]}return t.prototype.refresh=function(){var t=this;this.backendFailure||this.prometheusService.getNotifications(ft.last(this.notifications)).subscribe(function(e){return t.handleNotifications(e)},function(){return t.backendFailure=!0})},t.prototype.handleNotifications=function(t){var e=this;0!==t.length&&(this.notifications.length>0&&this.alertFormatter.sendNotifications(ft.flatten(t.map(function(t){return e.formatNotification(t)}))),this.notifications=this.notifications.concat(t))},t.prototype.formatNotification=function(t){var e=this;return this.alertFormatter.convertToCustomAlerts(t.alerts).map(function(t){return e.alertFormatter.convertAlertToNotification(t)})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(Ki),s.inject(Ui))},token:t,providedIn:"root"}),t}(),Op=function(){function t(t,e,n,a,r){this.notificationService=t,this.prometheusNotificationService=e,this.authStorageService=n,this.prometheusAlertService=a,this.ngZone=r,this.notifications=[]}return t.prototype.ngOnDestroy=function(){window.clearInterval(this.interval)},t.prototype.ngOnInit=function(){var t=this;this.authStorageService.getPermissions().prometheus.read&&(this.triggerPrometheusAlerts(),this.ngZone.runOutsideAngular(function(){t.interval=window.setInterval(function(){t.ngZone.run(function(){t.triggerPrometheusAlerts()})},5e3)})),this.notificationService.data$.subscribe(function(e){t.notifications=ft.orderBy(e,["timestamp"],["desc"])})},t.prototype.triggerPrometheusAlerts=function(){this.prometheusAlertService.refresh(),this.prometheusNotificationService.refresh()},t.prototype.removeAll=function(){this.notificationService.removeAll()},t}(),Ip=s["\u0275crt"]({encapsulation:0,styles:[[".popover-content{padding:.5em;height:auto;max-height:70vh;overflow-x:hidden} .popover{min-width:276px!important}.separator[_ngcontent-%COMP%]{padding:5px 12px;color:#90949c;background-color:#eee;font-size:12px}.message[_ngcontent-%COMP%]{padding:10px 16px;color:#474544;font-size:12px}table[_ngcontent-%COMP%]{width:252px;margin:5px 12px 5px 5px;font-size:12px;color:#474544}.icon-col[_ngcontent-%COMP%]{width:50px;font-size:10px}.date[_ngcontent-%COMP%]{color:#555}hr[_ngcontent-%COMP%]{margin-top:0;margin-bottom:0}"]],data:{}});function Cp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,19,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,17,"table",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,16,"tbody",[],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,11,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,7,"td",[["class","icon-col text-center"],["rowspan","3"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,6,"span",[],null,null,null,null,null)),s["\u0275did"](6,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pad"](7,2),(t()(),s["\u0275eld"](8,0,null,null,0,"i",[["class","fa fa-circle fa-stack-2x"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,2,"i",[],null,null,null,null,null)),s["\u0275did"](10,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngClass:[0,"ngClass"]},null),s["\u0275pad"](11,2),(t()(),s["\u0275eld"](12,0,null,null,2,"td",[],null,null,null,null,null)),(t()(),s["\u0275eld"](13,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](14,null,["",""])),(t()(),s["\u0275eld"](15,0,null,null,1,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](16,0,null,null,0,"td",[],[[8,"innerHTML",1]],null,null,null,null)),(t()(),s["\u0275eld"](17,0,null,null,1,"tr",[],null,null,null,null,null)),(t()(),s["\u0275eld"](18,0,null,null,0,"td",[],[[8,"innerHTML",1]],null,null,null,null)),(t()(),s["\u0275eld"](19,0,null,null,0,"hr",[],null,null,null,null,null))],function(t,e){var n=t(e,7,0,"fa-stack fa-2x",e.context.$implicit.textClass);t(e,6,0,n);var a=t(e,11,0,"fa fa-stack-1x fa-inverse",e.context.$implicit.iconClass);t(e,10,0,a)},function(t,e){var n=e.component;t(e,14,0,e.context.$implicit.title),t(e,16,0,e.context.$implicit.message),t(e,18,0,n.notificationService.renderTimeAndApplicationHtml(e.context.$implicit))})}function kp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,8,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,4,"button",[["class","btn btn-default btn-sm btn-block"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.removeAll()&&a),a},null,null)),(t()(),s["\u0275eld"](2,0,null,null,0,"i",[["aria-hidden","true"],["class","fa fa-trash-o"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" \xa0 "])),(t()(),s["\u0275eld"](4,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Remove all"])),(t()(),s["\u0275eld"](6,0,null,null,0,"hr",[],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Cp)),s["\u0275did"](8,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,8,0,e.component.notifications)},null)}function Np(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,kp)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,e.component.notifications.length>0)},null)}function Rp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"div",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,1,"div",[["class","message"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,[" There are no notifications. "]))],null,null)}function Ap(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Rp)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,0===e.component.notifications.length)},null)}function Dp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function Ep(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,0,null,null,null,null,null,null,null))],null,null)}function Lp(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Dp)),s["\u0275did"](1,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Ep)),s["\u0275did"](3,540672,null,0,i.NgTemplateOutlet,[s.ViewContainerRef],{ngTemplateOutlet:[0,"ngTemplateOutlet"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,1,0,s["\u0275nov"](e.parent,0)),t(e,3,0,s["\u0275nov"](e.parent,1))},null)}function Pp(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](0,[["notificationsTpl",2]],null,0,null,Np)),(t()(),s["\u0275and"](0,[["emptyTpl",2]],null,0,null,Ap)),(t()(),s["\u0275and"](0,[["popTpl",2]],null,0,null,Lp)),(t()(),s["\u0275eld"](3,16777216,null,null,4,"a",[["container","body"],["outsideClick","true"],["placement","bottom"],["title","Recent Notifications"]],null,null,null,null,null)),s["\u0275did"](4,212992,null,0,X.c,[X.a,s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,Q.a],{popover:[0,"popover"],placement:[1,"placement"],outsideClick:[2,"outsideClick"],container:[3,"container"]},null),(t()(),s["\u0275eld"](5,0,null,null,0,"i",[["class","fa fa-fw fa-bell"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","visible-xs-inline-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Recent Notifications"]))],function(t,e){t(e,4,0,s["\u0275nov"](e,2),"bottom","true","body")},null)}var Mp=function(){function t(t,e,n){this.summaryService=t,this.cephReleaseNamePipe=e,this.modalService=n}return t.prototype.ngOnInit=function(){var t=this,e=this.summaryService.subscribe(function(n){if(n){var a=t.cephReleaseNamePipe.transform(n.version);t.docsUrl="http://docs.ceph.com/docs/"+a+"/mgr/dashboard/",setTimeout(function(){e.unsubscribe()},0)}})},t.prototype.openAboutModal=function(){this.modalRef=this.modalService.show(Od)},t.prototype.goToApiDocs=function(){this.docsFormElement.nativeElement.submit()},t}(),qp=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function jp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,11,"ul",[["class","dropdown-menu dropdown-menu-right"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,4,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,3,"a",[["class","dropdown-item"],["target","_blank"]],[[8,"href",4]],null,null,null,null)),s["\u0275did"](3,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](4,{disabled:0}),(t()(),s["\u0275ted"](-1,null,["Documentation"])),(t()(),s["\u0275eld"](6,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,1,"a",[["class","dropdown-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.goToApiDocs()&&a),a},null,null)),(t()(),s["\u0275ted"](-1,null,["API"])),(t()(),s["\u0275eld"](9,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,1,"a",[["class","dropdown-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.openAboutModal()&&a),a},null,null)),(t()(),s["\u0275ted"](-1,null,["About"]))],function(t,e){var n=t(e,4,0,!e.component.docsUrl);t(e,3,0,"dropdown-item",n)},function(t,e){t(e,2,0,s["\u0275inlineInterpolate"](1,"",e.component.docsUrl,""))})}function Fp(t){return s["\u0275vid"](0,[s["\u0275qud"](402653184,1,{docsFormElement:0}),(t()(),s["\u0275eld"](1,0,[[1,0],["docsForm",1]],null,2,"form",[["action","/docs"],["method","post"],["target","_blank"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,1,"input",[["name","token"],["type","hidden"]],null,null,null,null,null)),s["\u0275did"](3,4210688,null,0,we.a,[[2,Se.a],l.a,s.ElementRef],null,null),(t()(),s["\u0275eld"](4,16777216,null,null,10,"div",[["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](6,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),(t()(),s["\u0275eld"](7,0,null,null,5,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""],["title","Help"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,8).onClick()&&a),a},null,null)),s["\u0275did"](8,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-fw fa-question-circle-o"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,1,"span",[["class","visible-xs-inline-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Help"])),(t()(),s["\u0275eld"](12,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,jp)),s["\u0275did"](14,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null)],function(t,e){t(e,6,0)},function(t,e){t(e,4,0,s["\u0275nov"](e,6).dropup,s["\u0275nov"](e,6).isOpen,s["\u0275nov"](e,6).isOpen&&s["\u0275nov"](e,6).isBs4),t(e,7,0,!0,s["\u0275nov"](e,8).isDisabled,s["\u0275nov"](e,8).isOpen)})}var zp=function(){function t(t){this.authStorageService=t,this.userPermission=this.authStorageService.getPermissions().user}return t.prototype.ngOnInit=function(){},t}(),Gp=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Yp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,3,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/user-management"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,2).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](2,671744,null,0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["User management"]))],function(t,e){t(e,2,0,"/user-management")},function(t,e){t(e,1,0,s["\u0275nov"](e,2).target,s["\u0275nov"](e,2).href)})}function Vp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"ul",[["class","dropdown-menu dropdown-menu-right"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Yp)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,2,0,e.component.userPermission.read)},null)}function Hp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,10,"div",[["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),(t()(),s["\u0275eld"](3,0,null,null,5,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""],["title","Dashboard Settings"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,4).onClick()&&a),a},null,null)),s["\u0275did"](4,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](5,0,null,null,0,"i",[["class","fa fa-fw fa-cog"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","visible-xs-inline-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Dashboard Settings"])),(t()(),s["\u0275eld"](8,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Vp)),s["\u0275did"](10,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,2,0)},function(t,e){t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,3,0,!0,s["\u0275nov"](e,4).isDisabled,s["\u0275nov"](e,4).isOpen)})}function Bp(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Hp)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.userPermission.read)},null)}var Up=function(){function t(t,e){this.authStorageService=t,this.authService=e}return t.prototype.ngOnInit=function(){this.username=this.authStorageService.getUsername()},t.prototype.logout=function(){this.authService.logout()},t}(),Wp=s["\u0275crt"]({encapsulation:0,styles:[[""]],data:{}});function Kp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,11,"ul",[["class","dropdown-menu dropdown-menu-right"],["role","menu"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,4,"li",[["class","disabled"],["role","menuitem"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,3,"a",[["class","dropdown-item disabled"],["href","#"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Signed in as "])),(t()(),s["\u0275eld"](4,0,null,null,1,"strong",[],null,null,null,null,null)),(t()(),s["\u0275ted"](5,null,["",""])),(t()(),s["\u0275eld"](6,0,null,null,0,"li",[["class","divider dropdown-divider"]],null,null,null,null,null)),(t()(),s["\u0275eld"](7,0,null,null,4,"li",[["role","menuitem"]],null,null,null,null,null)),(t()(),s["\u0275eld"](8,0,null,null,3,"a",[["class","dropdown-item"]],null,[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==t.component.logout()&&a),a},null,null)),(t()(),s["\u0275eld"](9,0,null,null,0,"i",[["class","fa fa-sign-out fa-fw"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Sign out"]))],null,function(t,e){t(e,5,0,e.component.username)})}function $p(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,10,"div",[["dropdown",""]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),(t()(),s["\u0275eld"](3,0,null,null,5,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""],["title","Logged in user"]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,4).onClick()&&a),a},null,null)),s["\u0275did"](4,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](5,0,null,null,0,"i",[["class","fa fa-fw fa-user"]],null,null,null,null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","visible-xs-inline-block"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Logged in user"])),(t()(),s["\u0275eld"](8,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Kp)),s["\u0275did"](10,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null)],function(t,e){t(e,2,0)},function(t,e){t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,3,0,!0,s["\u0275nov"](e,4).isDisabled,s["\u0275nov"](e,4).isOpen)})}var Zp=function(){function t(t,e,n,a,r){this.authStorageService=t,this.prometheusService=e,this.summaryService=n,this.featureToggles=a,this.prometheusAlertService=r,this.isCollapsed=!0,this.isAlertmanagerConfigured=!1,this.isPrometheusConfigured=!1,this.permissions=this.authStorageService.getPermissions(),this.enabledFeature$=this.featureToggles.get()}return t.prototype.ngOnInit=function(){var t=this;this.summaryService.subscribe(function(e){e&&(t.summaryData=e)}),this.permissions.configOpt.read&&(this.prometheusService.ifAlertmanagerConfigured(function(){t.isAlertmanagerConfigured=!0}),this.prometheusService.ifPrometheusConfigured(function(){t.isPrometheusConfigured=!0}))},t.prototype.blockHealthColor=function(){if(this.summaryData&&this.summaryData.rbd_mirroring){if(this.summaryData.rbd_mirroring.errors>0)return{color:"#d9534f"};if(this.summaryData.rbd_mirroring.warnings>0)return{color:"#f0ad4e"}}},t}(),Xp=s["\u0275crt"]({encapsulation:0,styles:[[".navbar-main{margin-bottom:0;background:#374249;border:0;border-radius:0;border-top:4px solid #2b99a8;font-size:1.2em} .navbar-main .navbar-header{display:-webkit-box;display:flex;float:none} .navbar-main .navbar-brand, .navbar-main .navbar-brand:hover{color:#eee;height:auto;margin:15px 0 15px 20px;padding:0;-webkit-align-self:flex-start;align-self:flex-start} .navbar-main .navbar-brand>img{height:25px} .navbar-main .navbar-toggle{margin-left:auto;border:0} .navbar-main .navbar-toggle:focus, .navbar-main .navbar-toggle:hover{background-color:transparent;outline:0} .navbar-main .navbar-toggle .icon-bar{background-color:#eee} .navbar-main .navbar-toggle:focus .icon-bar, .navbar-main .navbar-toggle:hover .icon-bar{box-shadow:0 0 3px #fff} .navbar-main .navbar-collapse{padding:0} .navbar-main .navbar-nav>li>.oa-navbar>[dropdown]>ul>li>.dropdown-item{font-size:12px} .navbar-main .navbar-nav>li>.oa-navbar>[dropdown]>a, .navbar-main .navbar-nav>li>.oa-navbar>a, .navbar-main .navbar-nav>li>a{color:#eee;line-height:1;padding:10px 18px;position:relative;display:block;text-decoration:none} .navbar-main .navbar-nav>li>.oa-navbar>[dropdown]>a:focus, .navbar-main .navbar-nav>li>.oa-navbar>[dropdown]>a:hover, .navbar-main .navbar-nav>li>.oa-navbar>a:focus, .navbar-main .navbar-nav>li>.oa-navbar>a:hover, .navbar-main .navbar-nav>li>a:focus, .navbar-main .navbar-nav>li>a:hover{color:#eee} .navbar-main .navbar-nav>li>.oa-navbar>[dropdown].open>a, .navbar-main .navbar-nav>li>.oa-navbar>[dropdown]>a:hover, .navbar-main .navbar-nav>li>.oa-navbar>a:hover, .navbar-main .navbar-nav>li>a:hover{background-color:#2b99a8} .navbar-main .navbar-nav>li a.dropdown-toggle span.caret{margin-left:5px} .navbar-main .navbar-nav>.open>.oa-navbar>[dropdown]>a, .navbar-main .navbar-nav>.open>.oa-navbar>[dropdown]>a:hover, .navbar-main .navbar-nav>.open>.oa-navbar>a, .navbar-main .navbar-nav>.open>.oa-navbar>a:focus, .navbar-main .navbar-nav>.open>.oa-navbar>a:hover, .navbar-main .navbar-nav>.open>.oa-navbar>li>a:focus, .navbar-main .navbar-nav>.open>a, .navbar-main .navbar-nav>.open>a:focus, .navbar-main .navbar-nav>.open>a:hover{color:#eee;border-color:transparent;background-color:transparent} .navbar-main .navbar-primary>li>a{border:0} .navbar-main .navbar-primary>.active>a, .navbar-main .navbar-primary>.active>a:focus, .navbar-main .navbar-primary>.active>a:hover{color:#eee;background-color:#2b99a8;border:0} .navbar-main .navbar-utility .fa, .navbar-main .navbar-utility a{font-size:1.1em} .navbar-main .navbar-utility>.active>a{color:#eee;background-color:#2b99a8} .navbar-main .navbar-utility>li>.open>a, .navbar-main .navbar-utility>li>.open>a:focus, .navbar-main .navbar-utility>li>.open>a:hover{color:#eee;border-color:transparent;background-color:transparent}@media (min-width:768px){ .navbar-main .navbar-primary>li>a{border-bottom:4px solid transparent} .navbar-main .navbar-primary>.active>a, .navbar-main .navbar-primary>.active>a:focus, .navbar-main .navbar-primary>.active>a:hover{background-color:transparent;border-bottom:4px solid #2b99a8} .navbar-main .navbar-utility{border-bottom:0;font-size:11px;position:absolute;right:0;top:0}}@media (max-width:calc(768px - 1px)){ .navbar-main .navbar-nav{margin:0} .navbar-main .navbar-nav .fa{margin-right:.5em} .navbar-main .navbar-collapse, .navbar-main .navbar-form{border-color:#eee} .navbar-main .navbar-collapse{padding:0} .navbar-main .navbar-nav .open .dropdown-menu{padding-top:0;padding-bottom:0;background-color:#2b99a8} .navbar-main .navbar-nav .open .dropdown-menu .dropdown-header, .navbar-main .navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 35px} .navbar-main .navbar-nav .open .dropdown-menu>li>a{color:#eee} .navbar-main .navbar-nav .open .dropdown-menu>.active>a{color:#eee;background-color:#2b99a8} .navbar-main .navbar-nav>li>a:hover{background-color:#2b99a8} .navbar-main .navbar-utility{border-top:1px solid #eee} .navbar-main .navbar-utility a{font-size:1em} .navbar-main .navbar-primary>.active>a, .navbar-main .navbar-primary>.active>a:focus, .navbar-main .navbar-primary>.active>a:hover{background-color:#2b99a8}}"]],data:{}});function Jp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_hosts"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,5,{links:1}),s["\u0275qud"](603979776,6,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/hosts"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[6,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Hosts"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/hosts")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function Qp(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_cluster_monitor"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,7,{links:1}),s["\u0275qud"](603979776,8,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/monitor/"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[8,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Monitors"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/monitor/")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function th(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_hosts"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,9,{links:1}),s["\u0275qud"](603979776,10,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/osd"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[10,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["OSDs"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/osd")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function eh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_configuration"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,11,{links:1}),s["\u0275qud"](603979776,12,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/configuration"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[12,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Configuration"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/configuration")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function nh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_crush"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,13,{links:1}),s["\u0275qud"](603979776,14,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/crush-map"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[14,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["CRUSH map"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/crush-map")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function ah(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_modules"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,15,{links:1}),s["\u0275qud"](603979776,16,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/mgr-modules"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[16,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Manager modules"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/mgr-modules")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function rh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_log"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,17,{links:1}),s["\u0275qud"](603979776,18,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/logs"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[18,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Logs"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/logs")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function ih(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"small",[["class","badge badge-danger"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.component.prometheusAlertService.alerts.length)})}function sh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,9,"li",[["class","tc_submenuitem tc_submenuitem_monitoring"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,19,{links:1}),s["\u0275qud"](603979776,20,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,5,"a",[["routerLink","/monitoring"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[20,4],[4,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275eld"](6,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Monitoring"])),(t()(),s["\u0275and"](16777216,null,null,1,null,ih)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"active"),t(e,5,0,"/monitoring"),t(e,9,0,n.prometheusAlertService.alerts.length>0)},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function oh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,16,"ul",[["class","dropdown-menu"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Jp)),s["\u0275did"](2,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Qp)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,th)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,eh)),s["\u0275did"](8,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,nh)),s["\u0275did"](10,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ah)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,rh)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,sh)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,2,0,n.permissions.hosts.read),t(e,4,0,n.permissions.monitor.read),t(e,6,0,n.permissions.osd.read),t(e,8,0,n.permissions.configOpt.read),t(e,10,0,n.permissions.hosts.read&&n.permissions.osd.read),t(e,12,0,n.permissions.configOpt.read),t(e,14,0,n.permissions.log.read),t(e,16,0,(n.isAlertmanagerConfigured||n.isPrometheusConfigured)&&n.permissions.prometheus.read)},null)}function uh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,12,"li",[["class","dropdown tc_menuitem tc_menuitem_cluster"],["dropdown",""],["routerLinkActive","active"]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),s["\u0275did"](3,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,3,{links:1}),s["\u0275qud"](603979776,4,{linksWithHrefs:1}),(t()(),s["\u0275eld"](6,0,null,null,4,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,7).onClick()&&a),a},null,null)),s["\u0275did"](7,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](8,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Cluster"])),(t()(),s["\u0275eld"](10,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,oh)),s["\u0275did"](12,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,2,0),t(e,3,0,"active")},function(t,e){t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,6,0,!0,s["\u0275nov"](e,7).isDisabled,s["\u0275nov"](e,7).isOpen)})}function ch(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_menuitem tc_menuitem_pool"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,21,{links:1}),s["\u0275qud"](603979776,22,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["routerLink","/pool"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[22,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Pools"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/pool")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function lh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,25,{links:1}),s["\u0275qud"](603979776,26,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/block/rbd"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[26,4],[24,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Images"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/block/rbd")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function dh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"small",[["class","label label-warning"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){var n=e.component;t(e,1,0,null==n.summaryData?null:null==n.summaryData.rbd_mirroring?null:n.summaryData.rbd_mirroring.warnings)})}function fh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"small",[["class","label label-danger"]],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){var n=e.component;t(e,1,0,null==n.summaryData?null:null==n.summaryData.rbd_mirroring?null:n.summaryData.rbd_mirroring.errors)})}function ph(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,11,"li",[["class","tc_submenuitem tc_submenuitem_block_mirroring"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,27,{links:1}),s["\u0275qud"](603979776,28,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,7,"a",[["class","dropdown-item"],["routerLink","/block/mirroring"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[28,4],[24,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275eld"](6,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Mirroring"])),(t()(),s["\u0275and"](16777216,null,null,1,null,dh)),s["\u0275did"](9,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,fh)),s["\u0275did"](11,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=e.component;t(e,1,0,"active"),t(e,5,0,"/block/mirroring"),t(e,9,0,0!==(null==n.summaryData?null:null==n.summaryData.rbd_mirroring?null:n.summaryData.rbd_mirroring.warnings)),t(e,11,0,0!==(null==n.summaryData?null:null==n.summaryData.rbd_mirroring?null:n.summaryData.rbd_mirroring.errors))},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function hh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,29,{links:1}),s["\u0275qud"](603979776,30,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/block/iscsi"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[30,4],[24,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["iSCSI"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/block/iscsi")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function gh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,18,"li",[["class","dropdown tc_menuitem tc_menuitem_block"],["dropdown",""],["routerLinkActive","active"]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),s["\u0275did"](3,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,23,{links:1}),s["\u0275qud"](603979776,24,{linksWithHrefs:1}),(t()(),s["\u0275eld"](6,0,null,null,5,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,8).onClick()&&a),a},null,null)),s["\u0275did"](7,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null),s["\u0275did"](8,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](9,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Block"])),(t()(),s["\u0275eld"](11,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275eld"](12,0,null,null,6,"ul",[["class","dropdown-menu"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,lh)),s["\u0275did"](14,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ph)),s["\u0275did"](16,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,hh)),s["\u0275did"](18,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){var n=e.component;t(e,2,0),t(e,3,0,"active"),t(e,7,0,n.blockHealthColor()),t(e,14,0,e.parent.context.ngIf.rbd&&n.permissions.rbdImage.read),t(e,16,0,e.parent.context.ngIf.mirroring&&n.permissions.rbdMirroring.read),t(e,18,0,e.parent.context.ngIf.iscsi&&n.permissions.iscsi.read)},function(t,e){t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,6,0,!0,s["\u0275nov"](e,8).isDisabled,s["\u0275nov"](e,8).isOpen)})}function bh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_menuitem tc_menuitem_nfs"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,31,{links:1}),s["\u0275qud"](603979776,32,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["routerLink","/nfs"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[32,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["NFS"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/nfs")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function mh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","tc_menuitem tc_menuitem_cephs"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](1,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,33,{links:1}),s["\u0275qud"](603979776,34,{linksWithHrefs:1}),(t()(),s["\u0275eld"](4,0,null,null,2,"a",[["routerLink","/cephfs"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,5).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](5,671744,[[34,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Filesystems"]))],function(t,e){t(e,1,0,"active"),t(e,5,0,"/cephfs")},function(t,e){t(e,4,0,s["\u0275nov"](e,5).target,s["\u0275nov"](e,5).href)})}function yh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,21,"ul",[["class","dropdown-menu"]],null,null,null,null,null)),(t()(),s["\u0275eld"](1,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_rgw_daemons"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](2,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,37,{links:1}),s["\u0275qud"](603979776,38,{linksWithHrefs:1}),(t()(),s["\u0275eld"](5,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/rgw/daemon"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,6).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](6,671744,[[38,4],[36,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Daemons"])),(t()(),s["\u0275eld"](8,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_rgw_users"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](9,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,39,{links:1}),s["\u0275qud"](603979776,40,{linksWithHrefs:1}),(t()(),s["\u0275eld"](12,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/rgw/user"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,13).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](13,671744,[[40,4],[36,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Users"])),(t()(),s["\u0275eld"](15,0,null,null,6,"li",[["class","tc_submenuitem tc_submenuitem_rgw_buckets"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](16,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,41,{links:1}),s["\u0275qud"](603979776,42,{linksWithHrefs:1}),(t()(),s["\u0275eld"](19,0,null,null,2,"a",[["class","dropdown-item"],["routerLink","/rgw/bucket"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,20).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](20,671744,[[42,4],[36,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275ted"](-1,null,["Buckets"]))],function(t,e){t(e,2,0,"active"),t(e,6,0,"/rgw/daemon"),t(e,9,0,"active"),t(e,13,0,"/rgw/user"),t(e,16,0,"active"),t(e,20,0,"/rgw/bucket")},function(t,e){t(e,5,0,s["\u0275nov"](e,6).target,s["\u0275nov"](e,6).href),t(e,12,0,s["\u0275nov"](e,13).target,s["\u0275nov"](e,13).href),t(e,19,0,s["\u0275nov"](e,20).target,s["\u0275nov"](e,20).href)})}function vh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,16777216,null,null,12,"li",[["class","dropdown tc_menuitem tc_menuitem_rgw"],["dropdown",""],["routerLinkActive","active"]],[[2,"dropup",null],[2,"open",null],[2,"show",null]],null,null,null,null)),s["\u0275prd"](512,null,bn.f,bn.f,[]),s["\u0275did"](2,212992,null,0,bn.c,[s.ElementRef,s.Renderer2,s.ViewContainerRef,J.a,bn.a,bn.f],null,null),s["\u0275did"](3,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,35,{links:1}),s["\u0275qud"](603979776,36,{linksWithHrefs:1}),(t()(),s["\u0275eld"](6,0,null,null,4,"a",[["class","dropdown-toggle"],["data-toggle","dropdown"],["dropdownToggle",""]],[[1,"aria-haspopup",0],[1,"disabled",0],[1,"aria-expanded",0]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,7).onClick()&&a),a},null,null)),s["\u0275did"](7,147456,null,0,bn.g,[s.ChangeDetectorRef,bn.c,s.ElementRef,s.Renderer2,bn.f],null,null),(t()(),s["\u0275eld"](8,0,null,null,1,null,null,null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Object Gateway"])),(t()(),s["\u0275eld"](10,0,null,null,0,"span",[["class","caret"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,yh)),s["\u0275did"](12,16384,null,0,bn.d,[bn.f,s.ViewContainerRef,s.TemplateRef],null,null),(t()(),s["\u0275and"](0,null,null,0))],function(t,e){t(e,2,0),t(e,3,0,"active")},function(t,e){t(e,0,0,s["\u0275nov"](e,2).dropup,s["\u0275nov"](e,2).isOpen,s["\u0275nov"](e,2).isOpen&&s["\u0275nov"](e,2).isBs4),t(e,6,0,!0,s["\u0275nov"](e,7).isDisabled,s["\u0275nov"](e,7).isOpen)})}function _h(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,44,"div",[["class","collapse navbar-collapse"],["id","bs-example-navbar-collapse-1"]],[[2,"collapse",null],[2,"in",null],[2,"show",null],[1,"aria-expanded",0],[1,"aria-hidden",0],[2,"collapsing",null]],null,null,null,null)),s["\u0275did"](1,8404992,null,0,up,[s.ElementRef,s.Renderer2,ju.b],{collapse:[0,"collapse"]},null),(t()(),s["\u0275eld"](2,0,null,null,23,"ul",[["class","nav navbar-nav navbar-primary"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,10,"li",[["class","tc_menuitem tc_menuitem_dashboard"],["routerLinkActive","active"]],null,null,null,null,null)),s["\u0275did"](4,1720320,null,2,tt.n,[tt.l,s.ElementRef,s.Renderer2,s.ChangeDetectorRef],{routerLinkActive:[0,"routerLinkActive"]},null),s["\u0275qud"](603979776,1,{links:1}),s["\u0275qud"](603979776,2,{linksWithHrefs:1}),(t()(),s["\u0275eld"](7,0,null,null,6,"a",[["routerLink","/dashboard"]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,8).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](8,671744,[[2,4]],0,tt.o,[tt.l,tt.a,i.LocationStrategy],{routerLink:[0,"routerLink"]},null),(t()(),s["\u0275eld"](9,0,null,null,2,"i",[["class","fa fa-heartbeat fa-fw"]],null,null,null,null,null)),s["\u0275did"](10,278528,null,0,i.NgStyle,[s.KeyValueDiffers,s.ElementRef,s.Renderer2],{ngStyle:[0,"ngStyle"]},null),s["\u0275ppd"](11,1),(t()(),s["\u0275eld"](12,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Dashboard"])),(t()(),s["\u0275and"](16777216,null,null,1,null,uh)),s["\u0275did"](15,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,ch)),s["\u0275did"](17,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,gh)),s["\u0275did"](19,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,bh)),s["\u0275did"](21,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,mh)),s["\u0275did"](23,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,vh)),s["\u0275did"](25,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](26,0,null,null,18,"ul",[["class","nav navbar-nav navbar-utility"]],null,null,null,null,null)),(t()(),s["\u0275eld"](27,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](28,0,null,null,1,"cd-language-selector",[["class","oa-navbar"]],null,null,null,Ul,zl)),s["\u0275did"](29,114688,null,0,Fl,[Nr.j,ql],null,null),(t()(),s["\u0275eld"](30,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](31,0,null,null,1,"cd-task-manager",[["class","oa-navbar"]],null,null,null,wp,dp)),s["\u0275did"](32,114688,null,0,lp,[je.a,Ou.a],null,null),(t()(),s["\u0275eld"](33,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](34,0,null,null,1,"cd-notifications",[["class","oa-navbar"]],null,null,null,Pp,Ip)),s["\u0275did"](35,245760,null,0,Op,[Jn.a,Sp,l.a,$i,s.NgZone],null,null),(t()(),s["\u0275eld"](36,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](37,0,null,null,1,"cd-dashboard-help",[["class","oa-navbar"]],null,null,null,Fp,qp)),s["\u0275did"](38,114688,null,0,Mp,[je.a,Ge.a,pa.b],null,null),(t()(),s["\u0275eld"](39,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](40,0,null,null,1,"cd-administration",[["class","oa-navbar"]],null,null,null,Bp,Gp)),s["\u0275did"](41,114688,null,0,zp,[l.a],null,null),(t()(),s["\u0275eld"](42,0,null,null,2,"li",[],null,null,null,null,null)),(t()(),s["\u0275eld"](43,0,null,null,1,"cd-identity",[["class","oa-navbar"]],null,null,null,$p,Wp)),s["\u0275did"](44,114688,null,0,Up,[l.a,$l.a],null,null)],function(t,e){var n=e.component;t(e,1,0,n.isCollapsed),t(e,4,0,"active"),t(e,8,0,"/dashboard");var a=s["\u0275unv"](e,10,0,t(e,11,0,s["\u0275nov"](e.parent,0),null==n.summaryData?null:n.summaryData.health_status));t(e,10,0,a),t(e,15,0,n.permissions.hosts.read||n.permissions.monitor.read||n.permissions.osd.read||n.permissions.configOpt.read),t(e,17,0,n.permissions.pool.read),t(e,19,0,(e.context.ngIf.rbd||e.context.ngIf.mirroring||e.context.ngIf.iscsi)&&(n.permissions.rbdImage.read||n.permissions.rbdMirroring.read||n.permissions.iscsi.read)),t(e,21,0,null==n.permissions?null:null==n.permissions.nfs?null:n.permissions.nfs.read),t(e,23,0,e.context.ngIf.cephfs&&n.permissions.cephfs.read),t(e,25,0,e.context.ngIf.rgw&&n.permissions.rgw.read),t(e,29,0),t(e,32,0),t(e,35,0),t(e,38,0),t(e,41,0),t(e,44,0)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).isCollapse,s["\u0275nov"](e,1).isExpanded,s["\u0275nov"](e,1).isExpanded,s["\u0275nov"](e,1).isExpanded,s["\u0275nov"](e,1).isCollapsed,s["\u0275nov"](e,1).isCollapsing),t(e,7,0,s["\u0275nov"](e,8).target,s["\u0275nov"](e,8).href)})}function xh(t){return s["\u0275vid"](0,[s["\u0275pid"](0,vt,[]),(t()(),s["\u0275eld"](1,0,null,null,12,"nav",[["class","navbar navbar-default navbar-main"]],null,null,null,null,null)),(t()(),s["\u0275eld"](2,0,null,null,8,"div",[["class","navbar-header tc_logo_component"]],null,null,null,null,null)),(t()(),s["\u0275eld"](3,0,null,null,1,"a",[["class","navbar-brand"],["href","#"]],null,null,null,null,null)),(t()(),s["\u0275eld"](4,0,null,null,0,"img",[["alt","Ceph"],["src","assets/Ceph_Logo_Standard_RGB_White_120411_fa.png"]],null,null,null,null,null)),(t()(),s["\u0275eld"](5,0,null,null,5,"button",[["class","navbar-toggle collapsed"],["type","button"]],null,[[null,"click"]],function(t,e,n){var a=!0,r=t.component;return"click"===e&&(a=0!=(r.isCollapsed=!r.isCollapsed)&&a),a},null,null)),(t()(),s["\u0275eld"](6,0,null,null,1,"span",[["class","sr-only"]],null,null,null,null,null)),(t()(),s["\u0275ted"](-1,null,["Toggle navigation"])),(t()(),s["\u0275eld"](8,0,null,null,0,"span",[["class","icon-bar"]],null,null,null,null,null)),(t()(),s["\u0275eld"](9,0,null,null,0,"span",[["class","icon-bar"]],null,null,null,null,null)),(t()(),s["\u0275eld"](10,0,null,null,0,"span",[["class","icon-bar"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,2,null,_h)),s["\u0275did"](12,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),s["\u0275pid"](131072,i.AsyncPipe,[s.ChangeDetectorRef])],function(t,e){var n=e.component;t(e,12,0,s["\u0275unv"](e,12,0,s["\u0275nov"](e,13).transform(n.enabledFeature$)))},null)}var Th=n("ou9H"),wh=n("P6uZ"),Sh=n("wbK0"),Oh=function(){function t(){}return t.prototype.resolve=function(t){var e=t.routeConfig.data,n=null===e.path?null:this.getFullPath(t),a=[{text:"string"==typeof e.breadcrumbs?e.breadcrumbs:e.breadcrumbs.text||e.text||n,path:n}];return Object(gc.a)(a)},t.prototype.getFullPath=function(t){return t.pathFromRoot.reduce(function(t,e){return t+e.url.reduce(function(t,e){return t+"/"+e.path},"")},"")},t}(),Ih=function(){function t(t,e){var n=this;this.router=t,this.injector=e,this.crumbs=[],this.defaultResolver=new Oh,this.subscription=this.router.events.pipe(Object(Vu.a)(function(t){return t instanceof tt.d})).subscribe(function(){n._resolveCrumbs(t.routerState.snapshot.root).pipe(Object(Yu.a)(function(t){return t}),Object(Th.a)(function(t){return t.text}),Object(Hu.a)(),Object(Yu.a)(function(t){var e=n.postProcess(t);return n.wrapIntoObservable(e).pipe(Object(wh.a)())})).subscribe(function(t){n.crumbs=t})})}return t.prototype.ngOnDestroy=function(){this.subscription.unsubscribe()},t.prototype._resolveCrumbs=function(t){var e,n=t.routeConfig&&t.routeConfig.data;if(n&&n.breadcrumbs){var a=(n.breadcrumbs.prototype instanceof Oh?this.injector.get(n.breadcrumbs):this.defaultResolver).resolve(t);e=this.wrapIntoObservable(a).pipe(Object(wh.a)())}else e=Object(gc.a)([]);return t.firstChild&&(e=e.pipe(Object(Sh.a)(this._resolveCrumbs(t.firstChild)))),e},t.prototype.postProcess=function(t){var e=[];return t.forEach(function(t){var n=t.text.split("/");if(n.length>1){t.text=n[n.length-1];for(var a=0;a<n.length-1;a++)e.push({text:n[a],path:null})}e.push(t)}),e},t.prototype.isPromise=function(t){return t&&"function"==typeof t.then},t.prototype.wrapIntoObservable=function(t){return t instanceof ds.a?t:this.isPromise(t)?Object(Uu.a)(Promise.resolve(t)):Object(gc.a)(t)},t}(),Ch=s["\u0275crt"]({encapsulation:0,styles:[[".breadcrumb[_ngcontent-%COMP%]{padding:8px 0;background-color:transparent;border-radius:0}.breadcrumb[_ngcontent-%COMP%] > li[_ngcontent-%COMP%] + li[_ngcontent-%COMP%]:before{padding:0 5px 0 7px;color:#474544;font-family:ForkAwesome;content:'\\f101'}.breadcrumb[_ngcontent-%COMP%] > li[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{color:#474544}"]],data:{}});function kh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"a",[["preserveFragment",""]],[[1,"target",0],[8,"href",4]],[[null,"click"]],function(t,e,n){var a=!0;return"click"===e&&(a=!1!==s["\u0275nov"](t,1).onClick(n.button,n.ctrlKey,n.metaKey,n.shiftKey)&&a),a},null,null)),s["\u0275did"](1,671744,null,0,tt.o,[tt.l,tt.a,i.LocationStrategy],{preserveFragment:[0,"preserveFragment"],routerLink:[1,"routerLink"]},null),(t()(),s["\u0275ted"](2,null,["",""]))],function(t,e){t(e,1,0,"",e.parent.context.$implicit.path)},function(t,e){t(e,0,0,s["\u0275nov"](e,1).target,s["\u0275nov"](e,1).href),t(e,2,0,e.parent.context.$implicit.text)})}function Nh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"span",[],null,null,null,null,null)),(t()(),s["\u0275ted"](1,null,["",""]))],null,function(t,e){t(e,1,0,e.parent.context.$implicit.text)})}function Rh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,6,"li",[["class","breadcrumb-item"]],null,null,null,null,null)),s["\u0275did"](1,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](2,{active:0}),(t()(),s["\u0275and"](16777216,null,null,1,null,kh)),s["\u0275did"](4,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275and"](16777216,null,null,1,null,Nh)),s["\u0275did"](6,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){var n=t(e,2,0,e.context.last);t(e,1,0,"breadcrumb-item",n),t(e,4,0,!e.context.last&&null!==e.context.$implicit.path),t(e,6,0,e.context.last||null===e.context.$implicit.path)},null)}function Ah(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"ol",[["class","breadcrumb"]],null,null,null,null,null)),(t()(),s["\u0275and"](16777216,null,null,1,null,Rh)),s["\u0275did"](2,278528,null,0,i.NgForOf,[s.ViewContainerRef,s.TemplateRef,s.IterableDiffers],{ngForOf:[0,"ngForOf"]},null)],function(t,e){t(e,2,0,e.component.crumbs)},null)}function Dh(t){return s["\u0275vid"](0,[(t()(),s["\u0275and"](16777216,null,null,1,null,Ah)),s["\u0275did"](1,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null)],function(t,e){t(e,1,0,e.component.crumbs.length)},null)}var Eh=s["\u0275crt"]({encapsulation:0,styles:[[".dashboard[_ngcontent-%COMP%]{background-color:#f5f5f5;margin:0;padding:0} #toast-container{margin-top:2vw}@media (max-width:1600px){ #toast-container{margin-top:2.5vw}}@media (max-width:calc(992px - 1px)){ #toast-container{margin-top:9vw}}@media (max-width:900px){ #toast-container{margin-top:10vw}}@media (max-width:319px){ #toast-container{margin-top:11vw}}@media (max-width:260px){ #toast-container{margin-top:14vw}}"]],data:{}});function Lh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,1,"cd-navigation",[],null,null,null,xh,Xp)),s["\u0275did"](1,114688,null,0,Zp,[l.a,Ui,je.a,At.a,$i],null,null)],function(t,e){t(e,1,0)},null)}function Ph(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,12,"block-ui",[],null,null,null,I,O)),s["\u0275did"](1,114688,null,0,y,[m],null,null),(t()(),s["\u0275and"](16777216,null,0,1,null,Lh)),s["\u0275did"](3,16384,null,0,i.NgIf,[s.ViewContainerRef,s.TemplateRef],{ngIf:[0,"ngIf"]},null),(t()(),s["\u0275eld"](4,0,null,0,6,"div",[["class","container-fluid"]],null,null,null,null,null)),s["\u0275did"](5,278528,null,0,i.NgClass,[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer2],{klass:[0,"klass"],ngClass:[1,"ngClass"]},null),s["\u0275pod"](6,{"full-height":0,dashboard:1}),(t()(),s["\u0275eld"](7,0,null,null,1,"cd-breadcrumbs",[],null,null,null,Dh,Ch)),s["\u0275did"](8,180224,null,0,Ih,[tt.l,s.Injector],null,null),(t()(),s["\u0275eld"](9,16777216,null,null,1,"router-outlet",[],null,null,null,null,null)),s["\u0275did"](10,212992,null,0,tt.q,[tt.b,s.ViewContainerRef,s.ComponentFactoryResolver,[8,null],s.ChangeDetectorRef],null,null),(t()(),s["\u0275eld"](11,0,null,0,1,"block-ui",[],null,null,null,I,O)),s["\u0275did"](12,114688,null,0,y,[m],null,null)],function(t,e){var n=e.component;t(e,1,0),t(e,3,0,!n.isLoginActive());var a=t(e,6,0,n.isLoginActive(),n.isDashboardPage());t(e,5,0,"container-fluid",a),t(e,10,0),t(e,12,0)},null)}function Mh(t){return s["\u0275vid"](0,[(t()(),s["\u0275eld"](0,0,null,null,2,"cd-root",[],null,null,null,Ph,Eh)),s["\u0275prd"](5120,null,c.a,d,[]),s["\u0275did"](2,49152,null,0,f,[l.a,tt.l],null,null)],null,null)}var qh=s["\u0275ccf"]("cd-root",f,Mh,{},{},[]),jh=n("XlPw"),Fh=n("9Z1F"),zh=function(){function t(t,e,n){this.router=t,this.authStorageService=e,this.notificationService=n}return t.prototype.intercept=function(t,e){var n=this;return e.handle(t).pipe(Object(Fh.a)(function(t){if(t instanceof kt.f){var e;switch(t.status){case 400:var a=new Cu.a,r=t.error.task;ft.isPlainObject(r)?(r.metadata.component=r.metadata.component||t.error.component,a.name=r.name,a.metadata=r.metadata):a.metadata=t.error,a.success=!1,a.exception=t.error,e=n.notificationService.notifyTask(a);break;case 401:n.authStorageService.remove(),n.router.navigate(["/login"]);break;case 403:n.router.navigate(["/403"]);break;default:e=n.prepareNotification(t)}t.preventDefault=function(){n.notificationService.cancel(e)},t.ignoreStatusCode=function(t){this.status===t&&this.preventDefault()}}return Object(jh.a)(t)}))},t.prototype.prepareNotification=function(t){return this.notificationService.show(function(){var e="";return ft.isPlainObject(t.error)&&ft.isString(t.error.detail)?e=t.error.detail:ft.isString(t.error)?e=t.error:ft.isString(t.message)&&(e=t.message),new Wi.b(Xn.a.error,t.status+" - "+t.statusText,e,void 0,t.application)})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(tt.l),s.inject(l.a),s.inject(Jn.a))},token:t,providedIn:"root"}),t}();function Gh(){return"undefined"!=typeof process}function Yh(t){switch(t.length){case 0:return new ju.d;case 1:return t[0];default:return new ju.k(t)}}function Vh(t,e,n,a,r,i){void 0===r&&(r={}),void 0===i&&(i={});var s=[],o=[],u=-1,c=null;if(a.forEach(function(t){var n=t.offset,a=n==u,l=a&&c||{};Object.keys(t).forEach(function(n){var a=n,o=t[n];if("offset"!==n)switch(a=e.normalizePropertyName(a,s),o){case ju.l:o=r[n];break;case ju.a:o=i[n];break;default:o=e.normalizeStyleValue(n,a,o,s)}l[a]=o}),a||o.push(l),c=l,u=n}),s.length)throw new Error("Unable to animate due to the following errors:\n - "+s.join("\n - "));return o}function Hh(t,e,n,a){switch(e){case"start":t.onStart(function(){return a(n&&Bh(n,"start",t))});break;case"done":t.onDone(function(){return a(n&&Bh(n,"done",t))});break;case"destroy":t.onDestroy(function(){return a(n&&Bh(n,"destroy",t))})}}function Bh(t,e,n){var a=n.totalTime,r=Uh(t.element,t.triggerName,t.fromState,t.toState,e||t.phaseName,null==a?t.totalTime:a,!!n.disabled),i=t._data;return null!=i&&(r._data=i),r}function Uh(t,e,n,a,r,i,s){return void 0===r&&(r=""),void 0===i&&(i=0),{element:t,triggerName:e,fromState:n,toState:a,phaseName:r,totalTime:i,disabled:!!s}}function Wh(t,e,n){var a;return t instanceof Map?(a=t.get(e))||t.set(e,a=n):(a=t[e])||(a=t[e]=n),a}function Kh(t){var e=t.indexOf(":");return[t.substring(1,e),t.substr(e+1)]}var $h=function(t,e){return!1},Zh=function(t,e){return!1},Xh=function(t,e,n){return[]},Jh=Gh();if(Jh||"undefined"!=typeof Element){if($h=function(t,e){return t.contains(e)},Jh||Element.prototype.matches)Zh=function(t,e){return t.matches(e)};else{var Qh=Element.prototype,tg=Qh.matchesSelector||Qh.mozMatchesSelector||Qh.msMatchesSelector||Qh.oMatchesSelector||Qh.webkitMatchesSelector;tg&&(Zh=function(t,e){return tg.apply(t,[e])})}Xh=function(t,e,n){var a=[];if(n)a.push.apply(a,Object(p.__spread)(t.querySelectorAll(e)));else{var r=t.querySelector(e);r&&a.push(r)}return a}}var eg=null,ng=!1;function ag(t){eg||(eg=("undefined"!=typeof document?document.body:null)||{},ng=!!eg.style&&"WebkitAppearance"in eg.style);var e=!0;return eg.style&&!function(t){return"ebkit"==t.substring(1,6)}(t)&&!(e=t in eg.style)&&ng&&(e="Webkit"+t.charAt(0).toUpperCase()+t.substr(1)in eg.style),e}var rg=Zh,ig=$h,sg=Xh;function og(t){var e={};return Object.keys(t).forEach(function(n){var a=n.replace(/([a-z])([A-Z])/g,"$1-$2");e[a]=t[n]}),e}var ug=function(){function t(){}return t.prototype.validateStyleProperty=function(t){return ag(t)},t.prototype.matchesElement=function(t,e){return rg(t,e)},t.prototype.containsElement=function(t,e){return ig(t,e)},t.prototype.query=function(t,e,n){return sg(t,e,n)},t.prototype.computeStyle=function(t,e,n){return n||""},t.prototype.animate=function(t,e,n,a,r,i,s){return void 0===i&&(i=[]),new ju.d(n,a)},t}(),cg=function(){function t(){}return t.NOOP=new ug,t}(),lg=1e3;function dg(t){if("number"==typeof t)return t;var e=t.match(/^(-?[\.\d]+)(m?s)/);return!e||e.length<2?0:fg(parseFloat(e[1]),e[2])}function fg(t,e){switch(e){case"s":return t*lg;default:return t}}function pg(t,e,n){return t.hasOwnProperty("duration")?t:function(t,e,n){var a,r=0,i="";if("string"==typeof t){var s=t.match(/^(-?[\.\d]+)(m?s)(?:\s+(-?[\.\d]+)(m?s))?(?:\s+([-a-z]+(?:\(.+?\))?))?$/i);if(null===s)return e.push('The provided timing value "'+t+'" is invalid.'),{duration:0,delay:0,easing:""};a=fg(parseFloat(s[1]),s[2]);var o=s[3];null!=o&&(r=fg(parseFloat(o),s[4]));var u=s[5];u&&(i=u)}else a=t;if(!n){var c=!1,l=e.length;a<0&&(e.push("Duration values below 0 are not allowed for this animation step."),c=!0),r<0&&(e.push("Delay values below 0 are not allowed for this animation step."),c=!0),c&&e.splice(l,0,'The provided timing value "'+t+'" is invalid.')}return{duration:a,delay:r,easing:i}}(t,e,n)}function hg(t,e){return void 0===e&&(e={}),Object.keys(t).forEach(function(n){e[n]=t[n]}),e}function gg(t,e,n){if(void 0===n&&(n={}),e)for(var a in t)n[a]=t[a];else hg(t,n);return n}function bg(t,e,n){return n?e+":"+n+";":""}function mg(t){for(var e="",n=0;n<t.style.length;n++)e+=bg(0,a=t.style.item(n),t.style.getPropertyValue(a));for(var a in t.style)t.style.hasOwnProperty(a)&&!a.startsWith("_")&&(e+=bg(0,a.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),t.style[a]));t.setAttribute("style",e)}function yg(t,e){t.style&&(Object.keys(e).forEach(function(n){var a=Ig(n);t.style[a]=e[n]}),Gh()&&mg(t))}function vg(t,e){t.style&&(Object.keys(e).forEach(function(e){var n=Ig(e);t.style[n]=""}),Gh()&&mg(t))}function _g(t){return Array.isArray(t)?1==t.length?t[0]:Object(ju.f)(t):t}var xg=new RegExp("{{\\s*(.+?)\\s*}}","g");function Tg(t){var e=[];if("string"==typeof t){for(var n=t.toString(),a=void 0;a=xg.exec(n);)e.push(a[1]);xg.lastIndex=0}return e}function wg(t,e,n){var a=t.toString(),r=a.replace(xg,function(t,a){var r=e[a];return e.hasOwnProperty(a)||(n.push("Please provide a value for the animation param "+a),r=""),r.toString()});return r==a?t:r}function Sg(t){for(var e=[],n=t.next();!n.done;)e.push(n.value),n=t.next();return e}var Og=/-+([a-z0-9])/g;function Ig(t){return t.replace(Og,function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return t[1].toUpperCase()})}function Cg(t,e){return 0===t||0===e}function kg(t,e,n){var a=Object.keys(n);if(a.length&&e.length){var r=e[0],i=[];if(a.forEach(function(t){r.hasOwnProperty(t)||i.push(t),r[t]=n[t]}),i.length)for(var s=function(){var n=e[o];i.forEach(function(e){n[e]=Rg(t,e)})},o=1;o<e.length;o++)s()}return e}function Ng(t,e,n){switch(e.type){case 7:return t.visitTrigger(e,n);case 0:return t.visitState(e,n);case 1:return t.visitTransition(e,n);case 2:return t.visitSequence(e,n);case 3:return t.visitGroup(e,n);case 4:return t.visitAnimate(e,n);case 5:return t.visitKeyframes(e,n);case 6:return t.visitStyle(e,n);case 8:return t.visitReference(e,n);case 9:return t.visitAnimateChild(e,n);case 10:return t.visitAnimateRef(e,n);case 11:return t.visitQuery(e,n);case 12:return t.visitStagger(e,n);default:throw new Error("Unable to resolve animation metadata node #"+e.type)}}function Rg(t,e){return window.getComputedStyle(t)[e]}var Ag="*",Dg=new Set(["true","1"]),Eg=new Set(["false","0"]);function Lg(t,e){var n=Dg.has(t)||Eg.has(t),a=Dg.has(e)||Eg.has(e);return function(r,i){var s=t==Ag||t==r,o=e==Ag||e==i;return!s&&n&&"boolean"==typeof r&&(s=r?Dg.has(t):Eg.has(t)),!o&&a&&"boolean"==typeof i&&(o=i?Dg.has(e):Eg.has(e)),s&&o}}var Pg=new RegExp("s*:selfs*,?","g");function Mg(t,e,n){return new qg(t).build(e,n)}var qg=function(){function t(t){this._driver=t}return t.prototype.build=function(t,e){var n=new jg(e);return this._resetContextStyleTimingState(n),Ng(this,_g(t),n)},t.prototype._resetContextStyleTimingState=function(t){t.currentQuerySelector="",t.collectedStyles={},t.collectedStyles[""]={},t.currentTime=0},t.prototype.visitTrigger=function(t,e){var n=this,a=e.queryCount=0,r=e.depCount=0,i=[],s=[];return"@"==t.name.charAt(0)&&e.errors.push("animation triggers cannot be prefixed with an `@` sign (e.g. trigger('@foo', [...]))"),t.definitions.forEach(function(t){if(n._resetContextStyleTimingState(e),0==t.type){var o=t,u=o.name;u.toString().split(/\s*,\s*/).forEach(function(t){o.name=t,i.push(n.visitState(o,e))}),o.name=u}else if(1==t.type){var c=n.visitTransition(t,e);a+=c.queryCount,r+=c.depCount,s.push(c)}else e.errors.push("only state() and transition() definitions can sit inside of a trigger()")}),{type:7,name:t.name,states:i,transitions:s,queryCount:a,depCount:r,options:null}},t.prototype.visitState=function(t,e){var n=this.visitStyle(t.styles,e),a=t.options&&t.options.params||null;if(n.containsDynamicStyles){var r=new Set,i=a||{};if(n.styles.forEach(function(t){if(Fg(t)){var e=t;Object.keys(e).forEach(function(t){Tg(e[t]).forEach(function(t){i.hasOwnProperty(t)||r.add(t)})})}}),r.size){var s=Sg(r.values());e.errors.push('state("'+t.name+'", ...) must define default values for all the following style substitutions: '+s.join(", "))}}return{type:0,name:t.name,style:n,options:a?{params:a}:null}},t.prototype.visitTransition=function(t,e){e.queryCount=0,e.depCount=0;var n,a,r,i=Ng(this,_g(t.animation),e);return{type:1,matchers:(n=t.expr,a=e.errors,r=[],"string"==typeof n?n.split(/\s*,\s*/).forEach(function(t){return function(t,e,n){if(":"==t[0]){var a=function(t,e){switch(t){case":enter":return"void => *";case":leave":return"* => void";case":increment":return function(t,e){return parseFloat(e)>parseFloat(t)};case":decrement":return function(t,e){return parseFloat(e)<parseFloat(t)};default:return e.push('The transition alias value "'+t+'" is not supported'),"* => *"}}(t,n);if("function"==typeof a)return void e.push(a);t=a}var r=t.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);if(null==r||r.length<4)return n.push('The provided transition expression "'+t+'" is not supported'),e;var i=r[1],s=r[2],o=r[3];e.push(Lg(i,o)),"<"!=s[0]||i==Ag&&o==Ag||e.push(Lg(o,i))}(t,r,a)}):r.push(n),r),animation:i,queryCount:e.queryCount,depCount:e.depCount,options:zg(t.options)}},t.prototype.visitSequence=function(t,e){var n=this;return{type:2,steps:t.steps.map(function(t){return Ng(n,t,e)}),options:zg(t.options)}},t.prototype.visitGroup=function(t,e){var n=this,a=e.currentTime,r=0,i=t.steps.map(function(t){e.currentTime=a;var i=Ng(n,t,e);return r=Math.max(r,e.currentTime),i});return e.currentTime=r,{type:3,steps:i,options:zg(t.options)}},t.prototype.visitAnimate=function(t,e){var n,a=function(t,e){var n=null;if(t.hasOwnProperty("duration"))n=t;else if("number"==typeof t)return Gg(pg(t,e).duration,0,"");var a=t;if(a.split(/\s+/).some(function(t){return"{"==t.charAt(0)&&"{"==t.charAt(1)})){var r=Gg(0,0,"");return r.dynamic=!0,r.strValue=a,r}return Gg((n=n||pg(a,e)).duration,n.delay,n.easing)}(t.timings,e.errors);e.currentAnimateTimings=a;var r=t.styles?t.styles:Object(ju.h)({});if(5==r.type)n=this.visitKeyframes(r,e);else{var i=t.styles,s=!1;if(!i){s=!0;var o={};a.easing&&(o.easing=a.easing),i=Object(ju.h)(o)}e.currentTime+=a.duration+a.delay;var u=this.visitStyle(i,e);u.isEmptyStep=s,n=u}return e.currentAnimateTimings=null,{type:4,timings:a,style:n,options:null}},t.prototype.visitStyle=function(t,e){var n=this._makeStyleAst(t,e);return this._validateStyleAst(n,e),n},t.prototype._makeStyleAst=function(t,e){var n=[];Array.isArray(t.styles)?t.styles.forEach(function(t){"string"==typeof t?t==ju.a?n.push(t):e.errors.push("The provided style string value "+t+" is not allowed."):n.push(t)}):n.push(t.styles);var a=!1,r=null;return n.forEach(function(t){if(Fg(t)){var e=t,n=e.easing;if(n&&(r=n,delete e.easing),!a)for(var i in e)if(e[i].toString().indexOf("{{")>=0){a=!0;break}}}),{type:6,styles:n,easing:r,offset:t.offset,containsDynamicStyles:a,options:null}},t.prototype._validateStyleAst=function(t,e){var n=this,a=e.currentAnimateTimings,r=e.currentTime,i=e.currentTime;a&&i>0&&(i-=a.duration+a.delay),t.styles.forEach(function(t){"string"!=typeof t&&Object.keys(t).forEach(function(a){if(n._driver.validateStyleProperty(a)){var s,o,u,c=e.collectedStyles[e.currentQuerySelector],l=c[a],d=!0;l&&(i!=r&&i>=l.startTime&&r<=l.endTime&&(e.errors.push('The CSS property "'+a+'" that exists between the times of "'+l.startTime+'ms" and "'+l.endTime+'ms" is also being animated in a parallel animation between the times of "'+i+'ms" and "'+r+'ms"'),d=!1),i=l.startTime),d&&(c[a]={startTime:i,endTime:r}),e.options&&(s=e.errors,o=e.options.params||{},(u=Tg(t[a])).length&&u.forEach(function(t){o.hasOwnProperty(t)||s.push("Unable to resolve the local animation param "+t+" in the given list of values")}))}else e.errors.push('The provided animation property "'+a+'" is not a supported CSS property for animations')})})},t.prototype.visitKeyframes=function(t,e){var n=this,a={type:5,styles:[],options:null};if(!e.currentAnimateTimings)return e.errors.push("keyframes() must be placed inside of a call to animate()"),a;var r=0,i=[],s=!1,o=!1,u=0,c=t.steps.map(function(t){var a=n._makeStyleAst(t,e),c=null!=a.offset?a.offset:function(t){if("string"==typeof t)return null;var e=null;if(Array.isArray(t))t.forEach(function(t){if(Fg(t)&&t.hasOwnProperty("offset")){var n=t;e=parseFloat(n.offset),delete n.offset}});else if(Fg(t)&&t.hasOwnProperty("offset")){var n=t;e=parseFloat(n.offset),delete n.offset}return e}(a.styles),l=0;return null!=c&&(r++,l=a.offset=c),o=o||l<0||l>1,s=s||l<u,u=l,i.push(l),a});o&&e.errors.push("Please ensure that all keyframe offsets are between 0 and 1"),s&&e.errors.push("Please ensure that all keyframe offsets are in order");var l=t.steps.length,d=0;r>0&&r<l?e.errors.push("Not all style() steps within the declared keyframes() contain offsets"):0==r&&(d=1/(l-1));var f=l-1,p=e.currentTime,h=e.currentAnimateTimings,g=h.duration;return c.forEach(function(t,r){var s=d>0?r==f?1:d*r:i[r],o=s*g;e.currentTime=p+h.delay+o,h.duration=o,n._validateStyleAst(t,e),t.offset=s,a.styles.push(t)}),a},t.prototype.visitReference=function(t,e){return{type:8,animation:Ng(this,_g(t.animation),e),options:zg(t.options)}},t.prototype.visitAnimateChild=function(t,e){return e.depCount++,{type:9,options:zg(t.options)}},t.prototype.visitAnimateRef=function(t,e){return{type:10,animation:this.visitReference(t.animation,e),options:zg(t.options)}},t.prototype.visitQuery=function(t,e){var n=e.currentQuerySelector,a=t.options||{};e.queryCount++,e.currentQuery=t;var r=Object(p.__read)(function(t){var e=!!t.split(/\s*,\s*/).find(function(t){return":self"==t});return e&&(t=t.replace(Pg,"")),[t=t.replace(/@\*/g,".ng-trigger").replace(/@\w+/g,function(t){return".ng-trigger-"+t.substr(1)}).replace(/:animating/g,".ng-animating"),e]}(t.selector),2),i=r[0],s=r[1];e.currentQuerySelector=n.length?n+" "+i:i,Wh(e.collectedStyles,e.currentQuerySelector,{});var o=Ng(this,_g(t.animation),e);return e.currentQuery=null,e.currentQuerySelector=n,{type:11,selector:i,limit:a.limit||0,optional:!!a.optional,includeSelf:s,animation:o,originalSelector:t.selector,options:zg(t.options)}},t.prototype.visitStagger=function(t,e){e.currentQuery||e.errors.push("stagger() can only be used inside of query()");var n="full"===t.timings?{duration:0,delay:0,easing:"full"}:pg(t.timings,e.errors,!0);return{type:12,animation:Ng(this,_g(t.animation),e),timings:n,options:null}},t}(),jg=function(){return function(t){this.errors=t,this.queryCount=0,this.depCount=0,this.currentTransition=null,this.currentQuery=null,this.currentQuerySelector=null,this.currentAnimateTimings=null,this.currentTime=0,this.collectedStyles={},this.options=null}}();function Fg(t){return!Array.isArray(t)&&"object"==typeof t}function zg(t){var e;return t?(t=hg(t)).params&&(t.params=(e=t.params)?hg(e):null):t={},t}function Gg(t,e,n){return{duration:t,delay:e,easing:n}}function Yg(t,e,n,a,r,i,s,o){return void 0===s&&(s=null),void 0===o&&(o=!1),{type:1,element:t,keyframes:e,preStyleProps:n,postStyleProps:a,duration:r,delay:i,totalTime:r+i,easing:s,subTimeline:o}}var Vg=function(){function t(){this._map=new Map}return t.prototype.consume=function(t){var e=this._map.get(t);return e?this._map.delete(t):e=[],e},t.prototype.append=function(t,e){var n=this._map.get(t);n||this._map.set(t,n=[]),n.push.apply(n,Object(p.__spread)(e))},t.prototype.has=function(t){return this._map.has(t)},t.prototype.clear=function(){this._map.clear()},t}(),Hg=new RegExp(":enter","g"),Bg=new RegExp(":leave","g");function Ug(t,e,n,a,r,i,s,o,u,c){return void 0===i&&(i={}),void 0===s&&(s={}),void 0===c&&(c=[]),(new Wg).buildKeyframes(t,e,n,a,r,i,s,o,u,c)}var Wg=function(){function t(){}return t.prototype.buildKeyframes=function(t,e,n,a,r,i,s,o,u,c){void 0===c&&(c=[]),u=u||new Vg;var l=new $g(t,e,u,a,r,c,[]);l.options=o,l.currentTimeline.setStyles([i],null,l.errors,o),Ng(this,n,l);var d=l.timelines.filter(function(t){return t.containsAnimation()});if(d.length&&Object.keys(s).length){var f=d[d.length-1];f.allowOnlyTimelineStyles()||f.setStyles([s],null,l.errors,o)}return d.length?d.map(function(t){return t.buildKeyframes()}):[Yg(e,[],[],[],0,0,"",!1)]},t.prototype.visitTrigger=function(t,e){},t.prototype.visitState=function(t,e){},t.prototype.visitTransition=function(t,e){},t.prototype.visitAnimateChild=function(t,e){var n=e.subInstructions.consume(e.element);if(n){var a=e.createSubContext(t.options),r=e.currentTimeline.currentTime,i=this._visitSubInstructions(n,a,a.options);r!=i&&e.transformIntoNewTimeline(i)}e.previousNode=t},t.prototype.visitAnimateRef=function(t,e){var n=e.createSubContext(t.options);n.transformIntoNewTimeline(),this.visitReference(t.animation,n),e.transformIntoNewTimeline(n.currentTimeline.currentTime),e.previousNode=t},t.prototype._visitSubInstructions=function(t,e,n){var a=e.currentTimeline.currentTime,r=null!=n.duration?dg(n.duration):null,i=null!=n.delay?dg(n.delay):null;return 0!==r&&t.forEach(function(t){var n=e.appendInstructionToTimeline(t,r,i);a=Math.max(a,n.duration+n.delay)}),a},t.prototype.visitReference=function(t,e){e.updateOptions(t.options,!0),Ng(this,t.animation,e),e.previousNode=t},t.prototype.visitSequence=function(t,e){var n=this,a=e.subContextCount,r=e,i=t.options;if(i&&(i.params||i.delay)&&((r=e.createSubContext(i)).transformIntoNewTimeline(),null!=i.delay)){6==r.previousNode.type&&(r.currentTimeline.snapshotCurrentStyles(),r.previousNode=Kg);var s=dg(i.delay);r.delayNextStep(s)}t.steps.length&&(t.steps.forEach(function(t){return Ng(n,t,r)}),r.currentTimeline.applyStylesToKeyframe(),r.subContextCount>a&&r.transformIntoNewTimeline()),e.previousNode=t},t.prototype.visitGroup=function(t,e){var n=this,a=[],r=e.currentTimeline.currentTime,i=t.options&&t.options.delay?dg(t.options.delay):0;t.steps.forEach(function(s){var o=e.createSubContext(t.options);i&&o.delayNextStep(i),Ng(n,s,o),r=Math.max(r,o.currentTimeline.currentTime),a.push(o.currentTimeline)}),a.forEach(function(t){return e.currentTimeline.mergeTimelineCollectedStyles(t)}),e.transformIntoNewTimeline(r),e.previousNode=t},t.prototype._visitTiming=function(t,e){if(t.dynamic){var n=t.strValue;return pg(e.params?wg(n,e.params,e.errors):n,e.errors)}return{duration:t.duration,delay:t.delay,easing:t.easing}},t.prototype.visitAnimate=function(t,e){var n=e.currentAnimateTimings=this._visitTiming(t.timings,e),a=e.currentTimeline;n.delay&&(e.incrementTime(n.delay),a.snapshotCurrentStyles());var r=t.style;5==r.type?this.visitKeyframes(r,e):(e.incrementTime(n.duration),this.visitStyle(r,e),a.applyStylesToKeyframe()),e.currentAnimateTimings=null,e.previousNode=t},t.prototype.visitStyle=function(t,e){var n=e.currentTimeline,a=e.currentAnimateTimings;!a&&n.getCurrentStyleProperties().length&&n.forwardFrame();var r=a&&a.easing||t.easing;t.isEmptyStep?n.applyEmptyStep(r):n.setStyles(t.styles,r,e.errors,e.options),e.previousNode=t},t.prototype.visitKeyframes=function(t,e){var n=e.currentAnimateTimings,a=e.currentTimeline.duration,r=n.duration,i=e.createSubContext().currentTimeline;i.easing=n.easing,t.styles.forEach(function(t){i.forwardTime((t.offset||0)*r),i.setStyles(t.styles,t.easing,e.errors,e.options),i.applyStylesToKeyframe()}),e.currentTimeline.mergeTimelineCollectedStyles(i),e.transformIntoNewTimeline(a+r),e.previousNode=t},t.prototype.visitQuery=function(t,e){var n=this,a=e.currentTimeline.currentTime,r=t.options||{},i=r.delay?dg(r.delay):0;i&&(6===e.previousNode.type||0==a&&e.currentTimeline.getCurrentStyleProperties().length)&&(e.currentTimeline.snapshotCurrentStyles(),e.previousNode=Kg);var s=a,o=e.invokeQuery(t.selector,t.originalSelector,t.limit,t.includeSelf,!!r.optional,e.errors);e.currentQueryTotal=o.length;var u=null;o.forEach(function(a,r){e.currentQueryIndex=r;var o=e.createSubContext(t.options,a);i&&o.delayNextStep(i),a===e.element&&(u=o.currentTimeline),Ng(n,t.animation,o),o.currentTimeline.applyStylesToKeyframe(),s=Math.max(s,o.currentTimeline.currentTime)}),e.currentQueryIndex=0,e.currentQueryTotal=0,e.transformIntoNewTimeline(s),u&&(e.currentTimeline.mergeTimelineCollectedStyles(u),e.currentTimeline.snapshotCurrentStyles()),e.previousNode=t},t.prototype.visitStagger=function(t,e){var n=e.parentContext,a=e.currentTimeline,r=t.timings,i=Math.abs(r.duration),s=i*(e.currentQueryTotal-1),o=i*e.currentQueryIndex;switch(r.duration<0?"reverse":r.easing){case"reverse":o=s-o;break;case"full":o=n.currentStaggerTime}var u=e.currentTimeline;o&&u.delayNextStep(o);var c=u.currentTime;Ng(this,t.animation,e),e.previousNode=t,n.currentStaggerTime=a.currentTime-c+(a.startTime-n.currentTimeline.startTime)},t}(),Kg={},$g=function(){function t(t,e,n,a,r,i,s,o){this._driver=t,this.element=e,this.subInstructions=n,this._enterClassName=a,this._leaveClassName=r,this.errors=i,this.timelines=s,this.parentContext=null,this.currentAnimateTimings=null,this.previousNode=Kg,this.subContextCount=0,this.options={},this.currentQueryIndex=0,this.currentQueryTotal=0,this.currentStaggerTime=0,this.currentTimeline=o||new Zg(this._driver,e,0),s.push(this.currentTimeline)}return Object.defineProperty(t.prototype,"params",{get:function(){return this.options.params},enumerable:!0,configurable:!0}),t.prototype.updateOptions=function(t,e){var n=this;if(t){var a=t,r=this.options;null!=a.duration&&(r.duration=dg(a.duration)),null!=a.delay&&(r.delay=dg(a.delay));var i=a.params;if(i){var s=r.params;s||(s=this.options.params={}),Object.keys(i).forEach(function(t){e&&s.hasOwnProperty(t)||(s[t]=wg(i[t],s,n.errors))})}}},t.prototype._copyOptions=function(){var t={};if(this.options){var e=this.options.params;if(e){var n=t.params={};Object.keys(e).forEach(function(t){n[t]=e[t]})}}return t},t.prototype.createSubContext=function(e,n,a){void 0===e&&(e=null);var r=n||this.element,i=new t(this._driver,r,this.subInstructions,this._enterClassName,this._leaveClassName,this.errors,this.timelines,this.currentTimeline.fork(r,a||0));return i.previousNode=this.previousNode,i.currentAnimateTimings=this.currentAnimateTimings,i.options=this._copyOptions(),i.updateOptions(e),i.currentQueryIndex=this.currentQueryIndex,i.currentQueryTotal=this.currentQueryTotal,i.parentContext=this,this.subContextCount++,i},t.prototype.transformIntoNewTimeline=function(t){return this.previousNode=Kg,this.currentTimeline=this.currentTimeline.fork(this.element,t),this.timelines.push(this.currentTimeline),this.currentTimeline},t.prototype.appendInstructionToTimeline=function(t,e,n){var a={duration:null!=e?e:t.duration,delay:this.currentTimeline.currentTime+(null!=n?n:0)+t.delay,easing:""},r=new Xg(this._driver,t.element,t.keyframes,t.preStyleProps,t.postStyleProps,a,t.stretchStartingKeyframe);return this.timelines.push(r),a},t.prototype.incrementTime=function(t){this.currentTimeline.forwardTime(this.currentTimeline.duration+t)},t.prototype.delayNextStep=function(t){t>0&&this.currentTimeline.delayNextStep(t)},t.prototype.invokeQuery=function(t,e,n,a,r,i){var s=[];if(a&&s.push(this.element),t.length>0){t=(t=t.replace(Hg,"."+this._enterClassName)).replace(Bg,"."+this._leaveClassName);var o=this._driver.query(this.element,t,1!=n);0!==n&&(o=n<0?o.slice(o.length+n,o.length):o.slice(0,n)),s.push.apply(s,Object(p.__spread)(o))}return r||0!=s.length||i.push('`query("'+e+'")` returned zero elements. (Use `query("'+e+'", { optional: true })` if you wish to allow this.)'),s},t}(),Zg=function(){function t(t,e,n,a){this._driver=t,this.element=e,this.startTime=n,this._elementTimelineStylesLookup=a,this.duration=0,this._previousKeyframe={},this._currentKeyframe={},this._keyframes=new Map,this._styleSummary={},this._pendingStyles={},this._backFill={},this._currentEmptyStepKeyframe=null,this._elementTimelineStylesLookup||(this._elementTimelineStylesLookup=new Map),this._localTimelineStyles=Object.create(this._backFill,{}),this._globalTimelineStyles=this._elementTimelineStylesLookup.get(e),this._globalTimelineStyles||(this._globalTimelineStyles=this._localTimelineStyles,this._elementTimelineStylesLookup.set(e,this._localTimelineStyles)),this._loadKeyframe()}return t.prototype.containsAnimation=function(){switch(this._keyframes.size){case 0:return!1;case 1:return this.getCurrentStyleProperties().length>0;default:return!0}},t.prototype.getCurrentStyleProperties=function(){return Object.keys(this._currentKeyframe)},Object.defineProperty(t.prototype,"currentTime",{get:function(){return this.startTime+this.duration},enumerable:!0,configurable:!0}),t.prototype.delayNextStep=function(t){var e=1==this._keyframes.size&&Object.keys(this._pendingStyles).length;this.duration||e?(this.forwardTime(this.currentTime+t),e&&this.snapshotCurrentStyles()):this.startTime+=t},t.prototype.fork=function(e,n){return this.applyStylesToKeyframe(),new t(this._driver,e,n||this.currentTime,this._elementTimelineStylesLookup)},t.prototype._loadKeyframe=function(){this._currentKeyframe&&(this._previousKeyframe=this._currentKeyframe),this._currentKeyframe=this._keyframes.get(this.duration),this._currentKeyframe||(this._currentKeyframe=Object.create(this._backFill,{}),this._keyframes.set(this.duration,this._currentKeyframe))},t.prototype.forwardFrame=function(){this.duration+=1,this._loadKeyframe()},t.prototype.forwardTime=function(t){this.applyStylesToKeyframe(),this.duration=t,this._loadKeyframe()},t.prototype._updateStyle=function(t,e){this._localTimelineStyles[t]=e,this._globalTimelineStyles[t]=e,this._styleSummary[t]={time:this.currentTime,value:e}},t.prototype.allowOnlyTimelineStyles=function(){return this._currentEmptyStepKeyframe!==this._currentKeyframe},t.prototype.applyEmptyStep=function(t){var e=this;t&&(this._previousKeyframe.easing=t),Object.keys(this._globalTimelineStyles).forEach(function(t){e._backFill[t]=e._globalTimelineStyles[t]||ju.a,e._currentKeyframe[t]=ju.a}),this._currentEmptyStepKeyframe=this._currentKeyframe},t.prototype.setStyles=function(t,e,n,a){var r=this;e&&(this._previousKeyframe.easing=e);var i=a&&a.params||{},s=function(t,e){var n,a={};return t.forEach(function(t){"*"===t?(n=n||Object.keys(e)).forEach(function(t){a[t]=ju.a}):gg(t,!1,a)}),a}(t,this._globalTimelineStyles);Object.keys(s).forEach(function(t){var e=wg(s[t],i,n);r._pendingStyles[t]=e,r._localTimelineStyles.hasOwnProperty(t)||(r._backFill[t]=r._globalTimelineStyles.hasOwnProperty(t)?r._globalTimelineStyles[t]:ju.a),r._updateStyle(t,e)})},t.prototype.applyStylesToKeyframe=function(){var t=this,e=this._pendingStyles,n=Object.keys(e);0!=n.length&&(this._pendingStyles={},n.forEach(function(n){t._currentKeyframe[n]=e[n]}),Object.keys(this._localTimelineStyles).forEach(function(e){t._currentKeyframe.hasOwnProperty(e)||(t._currentKeyframe[e]=t._localTimelineStyles[e])}))},t.prototype.snapshotCurrentStyles=function(){var t=this;Object.keys(this._localTimelineStyles).forEach(function(e){var n=t._localTimelineStyles[e];t._pendingStyles[e]=n,t._updateStyle(e,n)})},t.prototype.getFinalKeyframe=function(){return this._keyframes.get(this.duration)},Object.defineProperty(t.prototype,"properties",{get:function(){var t=[];for(var e in this._currentKeyframe)t.push(e);return t},enumerable:!0,configurable:!0}),t.prototype.mergeTimelineCollectedStyles=function(t){var e=this;Object.keys(t._styleSummary).forEach(function(n){var a=e._styleSummary[n],r=t._styleSummary[n];(!a||r.time>a.time)&&e._updateStyle(n,r.value)})},t.prototype.buildKeyframes=function(){var t=this;this.applyStylesToKeyframe();var e=new Set,n=new Set,a=1===this._keyframes.size&&0===this.duration,r=[];this._keyframes.forEach(function(i,s){var o=gg(i,!0);Object.keys(o).forEach(function(t){var a=o[t];a==ju.l?e.add(t):a==ju.a&&n.add(t)}),a||(o.offset=s/t.duration),r.push(o)});var i=e.size?Sg(e.values()):[],s=n.size?Sg(n.values()):[];if(a){var o=r[0],u=hg(o);o.offset=0,u.offset=1,r=[o,u]}return Yg(this.element,r,i,s,this.duration,this.startTime,this.easing,!1)},t}(),Xg=function(t){function e(e,n,a,r,i,s,o){void 0===o&&(o=!1);var u=t.call(this,e,n,s.delay)||this;return u.element=n,u.keyframes=a,u.preStyleProps=r,u.postStyleProps=i,u._stretchStartingKeyframe=o,u.timings={duration:s.duration,delay:s.delay,easing:s.easing},u}return Object(p.__extends)(e,t),e.prototype.containsAnimation=function(){return this.keyframes.length>1},e.prototype.buildKeyframes=function(){var t=this.keyframes,e=this.timings,n=e.delay,a=e.duration,r=e.easing;if(this._stretchStartingKeyframe&&n){var i=[],s=a+n,o=n/s,u=gg(t[0],!1);u.offset=0,i.push(u);var c=gg(t[0],!1);c.offset=Jg(o),i.push(c);for(var l=t.length-1,d=1;d<=l;d++){var f=gg(t[d],!1);f.offset=Jg((n+f.offset*a)/s),i.push(f)}a=s,n=0,r="",t=i}return Yg(this.element,t,this.preStyleProps,this.postStyleProps,a,n,r,!0)},e}(Zg);function Jg(t,e){void 0===e&&(e=3);var n=Math.pow(10,e-1);return Math.round(t*n)/n}var Qg=function(){return function(){}}(),tb=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return Object(p.__extends)(e,t),e.prototype.normalizePropertyName=function(t,e){return Ig(t)},e.prototype.normalizeStyleValue=function(t,e,n,a){var r="",i=n.toString().trim();if(eb[e]&&0!==n&&"0"!==n)if("number"==typeof n)r="px";else{var s=n.match(/^[+-]?[\d\.]+([a-z]*)$/);s&&0==s[1].length&&a.push("Please provide a CSS unit value for "+t+":"+n)}return i+r},e}(Qg),eb=nb("width,height,minWidth,minHeight,maxWidth,maxHeight,left,top,bottom,right,fontSize,outlineWidth,outlineOffset,paddingTop,paddingLeft,paddingBottom,paddingRight,marginTop,marginLeft,marginBottom,marginRight,borderRadius,borderWidth,borderTopWidth,borderLeftWidth,borderRightWidth,borderBottomWidth,textIndent,perspective".split(","));function nb(t){var e={};return t.forEach(function(t){return e[t]=!0}),e}function ab(t,e,n,a,r,i,s,o,u,c,l,d,f){return{type:0,element:t,triggerName:e,isRemovalTransition:r,fromState:n,fromStyles:i,toState:a,toStyles:s,timelines:o,queriedElements:u,preStyleProps:c,postStyleProps:l,totalTime:d,errors:f}}var rb={},ib=function(){function t(t,e,n){this._triggerName=t,this.ast=e,this._stateStyles=n}return t.prototype.match=function(t,e,n,a){return function(t,e,n,a,r){return t.some(function(t){return t(e,n,a,r)})}(this.ast.matchers,t,e,n,a)},t.prototype.buildStyles=function(t,e,n){var a=this._stateStyles["*"],r=this._stateStyles[t],i=a?a.buildStyles(e,n):{};return r?r.buildStyles(e,n):i},t.prototype.build=function(t,e,n,a,r,i,s,o,u,c){var l=[],d=this.ast.options&&this.ast.options.params||rb,f=this.buildStyles(n,s&&s.params||rb,l),h=o&&o.params||rb,g=this.buildStyles(a,h,l),b=new Set,m=new Map,y=new Map,v="void"===a,_={params:Object(p.__assign)({},d,h)},x=c?[]:Ug(t,e,this.ast.animation,r,i,f,g,_,u,l),T=0;if(x.forEach(function(t){T=Math.max(t.duration+t.delay,T)}),l.length)return ab(e,this._triggerName,n,a,v,f,g,[],[],m,y,T,l);x.forEach(function(t){var n=t.element,a=Wh(m,n,{});t.preStyleProps.forEach(function(t){return a[t]=!0});var r=Wh(y,n,{});t.postStyleProps.forEach(function(t){return r[t]=!0}),n!==e&&b.add(n)});var w=Sg(b.values());return ab(e,this._triggerName,n,a,v,f,g,x,w,m,y,T)},t}(),sb=function(){function t(t,e){this.styles=t,this.defaultParams=e}return t.prototype.buildStyles=function(t,e){var n={},a=hg(this.defaultParams);return Object.keys(t).forEach(function(e){var n=t[e];null!=n&&(a[e]=n)}),this.styles.styles.forEach(function(t){if("string"!=typeof t){var r=t;Object.keys(r).forEach(function(t){var i=r[t];i.length>1&&(i=wg(i,a,e)),n[t]=i})}}),n},t}(),ob=function(){function t(t,e){var n=this;this.name=t,this.ast=e,this.transitionFactories=[],this.states={},e.states.forEach(function(t){n.states[t.name]=new sb(t.style,t.options&&t.options.params||{})}),ub(this.states,"true","1"),ub(this.states,"false","0"),e.transitions.forEach(function(e){n.transitionFactories.push(new ib(t,e,n.states))}),this.fallbackTransition=new ib(t,{type:1,animation:{type:2,steps:[],options:null},matchers:[function(t,e){return!0}],options:null,queryCount:0,depCount:0},this.states)}return Object.defineProperty(t.prototype,"containsQueries",{get:function(){return this.ast.queryCount>0},enumerable:!0,configurable:!0}),t.prototype.matchTransition=function(t,e,n,a){return this.transitionFactories.find(function(r){return r.match(t,e,n,a)})||null},t.prototype.matchStyles=function(t,e,n){return this.fallbackTransition.buildStyles(t,e,n)},t}();function ub(t,e,n){t.hasOwnProperty(e)?t.hasOwnProperty(n)||(t[n]=t[e]):t.hasOwnProperty(n)&&(t[e]=t[n])}var cb=new Vg,lb=function(){function t(t,e,n){this.bodyNode=t,this._driver=e,this._normalizer=n,this._animations={},this._playersById={},this.players=[]}return t.prototype.register=function(t,e){var n=[],a=Mg(this._driver,e,n);if(n.length)throw new Error("Unable to build the animation due to the following errors: "+n.join("\n"));this._animations[t]=a},t.prototype._buildPlayer=function(t,e,n){var a=t.element,r=Vh(0,this._normalizer,0,t.keyframes,e,n);return this._driver.animate(a,r,t.duration,t.delay,t.easing,[],!0)},t.prototype.create=function(t,e,n){var a=this;void 0===n&&(n={});var r,i=[],s=this._animations[t],o=new Map;if(s?(r=Ug(this._driver,e,s,"ng-enter","ng-leave",{},{},n,cb,i)).forEach(function(t){var e=Wh(o,t.element,{});t.postStyleProps.forEach(function(t){return e[t]=null})}):(i.push("The requested animation doesn't exist or has already been destroyed"),r=[]),i.length)throw new Error("Unable to create the animation due to the following errors: "+i.join("\n"));o.forEach(function(t,e){Object.keys(t).forEach(function(n){t[n]=a._driver.computeStyle(e,n,ju.a)})});var u=Yh(r.map(function(t){var e=o.get(t.element);return a._buildPlayer(t,{},e)}));return this._playersById[t]=u,u.onDestroy(function(){return a.destroy(t)}),this.players.push(u),u},t.prototype.destroy=function(t){var e=this._getPlayer(t);e.destroy(),delete this._playersById[t];var n=this.players.indexOf(e);n>=0&&this.players.splice(n,1)},t.prototype._getPlayer=function(t){var e=this._playersById[t];if(!e)throw new Error("Unable to find the timeline player referenced by "+t);return e},t.prototype.listen=function(t,e,n,a){var r=Uh(e,"","","");return Hh(this._getPlayer(t),n,r,a),function(){}},t.prototype.command=function(t,e,n,a){if("register"!=n)if("create"!=n){var r=this._getPlayer(t);switch(n){case"play":r.play();break;case"pause":r.pause();break;case"reset":r.reset();break;case"restart":r.restart();break;case"finish":r.finish();break;case"init":r.init();break;case"setPosition":r.setPosition(parseFloat(a[0]));break;case"destroy":this.destroy(t)}}else this.create(t,e,a[0]||{});else this.register(t,a[0])},t}(),db=[],fb={namespaceId:"",setForRemoval:!1,setForMove:!1,hasAnimation:!1,removedBeforeQueried:!1},pb={namespaceId:"",setForMove:!1,setForRemoval:!1,hasAnimation:!1,removedBeforeQueried:!0},hb="__ng_removed",gb=function(){function t(t,e){void 0===e&&(e=""),this.namespaceId=e;var n=t&&t.hasOwnProperty("value");if(this.value=function(t){return null!=t?t:null}(n?t.value:t),n){var a=hg(t);delete a.value,this.options=a}else this.options={};this.options.params||(this.options.params={})}return Object.defineProperty(t.prototype,"params",{get:function(){return this.options.params},enumerable:!0,configurable:!0}),t.prototype.absorbOptions=function(t){var e=t.params;if(e){var n=this.options.params;Object.keys(e).forEach(function(t){null==n[t]&&(n[t]=e[t])})}},t}(),bb=new gb("void"),mb=function(){function t(t,e,n){this.id=t,this.hostElement=e,this._engine=n,this.players=[],this._triggers={},this._queue=[],this._elementListeners=new Map,this._hostClassName="ng-tns-"+t,Ob(e,this._hostClassName)}return t.prototype.listen=function(t,e,n,a){var r,i=this;if(!this._triggers.hasOwnProperty(e))throw new Error('Unable to listen on the animation trigger event "'+n+'" because the animation trigger "'+e+"\" doesn't exist!");if(null==n||0==n.length)throw new Error('Unable to listen on the animation trigger "'+e+'" because the provided event is undefined!');if("start"!=(r=n)&&"done"!=r)throw new Error('The provided animation trigger event "'+n+'" for the animation trigger "'+e+'" is not supported!');var s=Wh(this._elementListeners,t,[]),o={name:e,phase:n,callback:a};s.push(o);var u=Wh(this._engine.statesByElement,t,{});return u.hasOwnProperty(e)||(Ob(t,"ng-trigger"),Ob(t,"ng-trigger-"+e),u[e]=bb),function(){i._engine.afterFlush(function(){var t=s.indexOf(o);t>=0&&s.splice(t,1),i._triggers[e]||delete u[e]})}},t.prototype.register=function(t,e){return!this._triggers[t]&&(this._triggers[t]=e,!0)},t.prototype._getTrigger=function(t){var e=this._triggers[t];if(!e)throw new Error('The provided animation trigger "'+t+'" has not been registered!');return e},t.prototype.trigger=function(t,e,n,a){var r=this;void 0===a&&(a=!0);var i=this._getTrigger(e),s=new vb(this.id,e,t),o=this._engine.statesByElement.get(t);o||(Ob(t,"ng-trigger"),Ob(t,"ng-trigger-"+e),this._engine.statesByElement.set(t,o={}));var u=o[e],c=new gb(n,this.id);if(!(n&&n.hasOwnProperty("value"))&&u&&c.absorbOptions(u.options),o[e]=c,u||(u=bb),"void"===c.value||u.value!==c.value){var l=Wh(this._engine.playersByElement,t,[]);l.forEach(function(t){t.namespaceId==r.id&&t.triggerName==e&&t.queued&&t.destroy()});var d=i.matchTransition(u.value,c.value,t,c.params),f=!1;if(!d){if(!a)return;d=i.fallbackTransition,f=!0}return this._engine.totalQueuedPlayers++,this._queue.push({element:t,triggerName:e,transition:d,fromState:u,toState:c,player:s,isFallbackTransition:f}),f||(Ob(t,"ng-animate-queued"),s.onStart(function(){Ib(t,"ng-animate-queued")})),s.onDone(function(){var e=r.players.indexOf(s);e>=0&&r.players.splice(e,1);var n=r._engine.playersByElement.get(t);if(n){var a=n.indexOf(s);a>=0&&n.splice(a,1)}}),this.players.push(s),l.push(s),s}if(!function(t,e){var n=Object.keys(t),a=Object.keys(e);if(n.length!=a.length)return!1;for(var r=0;r<n.length;r++){var i=n[r];if(!e.hasOwnProperty(i)||t[i]!==e[i])return!1}return!0}(u.params,c.params)){var p=[],h=i.matchStyles(u.value,u.params,p),g=i.matchStyles(c.value,c.params,p);p.length?this._engine.reportError(p):this._engine.afterFlush(function(){vg(t,h),yg(t,g)})}},t.prototype.deregister=function(t){var e=this;delete this._triggers[t],this._engine.statesByElement.forEach(function(e,n){delete e[t]}),this._elementListeners.forEach(function(n,a){e._elementListeners.set(a,n.filter(function(e){return e.name!=t}))})},t.prototype.clearElementCache=function(t){this._engine.statesByElement.delete(t),this._elementListeners.delete(t);var e=this._engine.playersByElement.get(t);e&&(e.forEach(function(t){return t.destroy()}),this._engine.playersByElement.delete(t))},t.prototype._signalRemovalForInnerTriggers=function(t,e,n){var a=this;void 0===n&&(n=!1),this._engine.driver.query(t,".ng-trigger",!0).forEach(function(t){if(!t[hb]){var n=a._engine.fetchNamespacesByElement(t);n.size?n.forEach(function(n){return n.triggerLeaveAnimation(t,e,!1,!0)}):a.clearElementCache(t)}})},t.prototype.triggerLeaveAnimation=function(t,e,n,a){var r=this,i=this._engine.statesByElement.get(t);if(i){var s=[];if(Object.keys(i).forEach(function(e){if(r._triggers[e]){var n=r.trigger(t,e,"void",a);n&&s.push(n)}}),s.length)return this._engine.markElementAsRemoved(this.id,t,!0,e),n&&Yh(s).onDone(function(){return r._engine.processLeaveNode(t)}),!0}return!1},t.prototype.prepareLeaveAnimationListeners=function(t){var e=this,n=this._elementListeners.get(t);if(n){var a=new Set;n.forEach(function(n){var r=n.name;if(!a.has(r)){a.add(r);var i=e._triggers[r].fallbackTransition,s=e._engine.statesByElement.get(t)[r]||bb,o=new gb("void"),u=new vb(e.id,r,t);e._engine.totalQueuedPlayers++,e._queue.push({element:t,triggerName:r,transition:i,fromState:s,toState:o,player:u,isFallbackTransition:!0})}})}},t.prototype.removeNode=function(t,e){var n=this,a=this._engine;if(t.childElementCount&&this._signalRemovalForInnerTriggers(t,e,!0),!this.triggerLeaveAnimation(t,e,!0)){var r=!1;if(a.totalAnimations){var i=a.players.length?a.playersByQueriedElement.get(t):[];if(i&&i.length)r=!0;else for(var s=t;s=s.parentNode;)if(a.statesByElement.get(s)){r=!0;break}}this.prepareLeaveAnimationListeners(t),r?a.markElementAsRemoved(this.id,t,!1,e):(a.afterFlush(function(){return n.clearElementCache(t)}),a.destroyInnerAnimations(t),a._onRemovalComplete(t,e))}},t.prototype.insertNode=function(t,e){Ob(t,this._hostClassName)},t.prototype.drainQueuedTransitions=function(t){var e=this,n=[];return this._queue.forEach(function(a){var r=a.player;if(!r.destroyed){var i=a.element,s=e._elementListeners.get(i);s&&s.forEach(function(e){if(e.name==a.triggerName){var n=Uh(i,a.triggerName,a.fromState.value,a.toState.value);n._data=t,Hh(a.player,e.phase,n,e.callback)}}),r.markedForDestroy?e._engine.afterFlush(function(){r.destroy()}):n.push(a)}}),this._queue=[],n.sort(function(t,n){var a=t.transition.ast.depCount,r=n.transition.ast.depCount;return 0==a||0==r?a-r:e._engine.driver.containsElement(t.element,n.element)?1:-1})},t.prototype.destroy=function(t){this.players.forEach(function(t){return t.destroy()}),this._signalRemovalForInnerTriggers(this.hostElement,t)},t.prototype.elementContainsData=function(t){var e=!1;return this._elementListeners.has(t)&&(e=!0),!!this._queue.find(function(e){return e.element===t})||e},t}(),yb=function(){function t(t,e,n){this.bodyNode=t,this.driver=e,this._normalizer=n,this.players=[],this.newHostElements=new Map,this.playersByElement=new Map,this.playersByQueriedElement=new Map,this.statesByElement=new Map,this.disabledNodes=new Set,this.totalAnimations=0,this.totalQueuedPlayers=0,this._namespaceLookup={},this._namespaceList=[],this._flushFns=[],this._whenQuietFns=[],this.namespacesByHostElement=new Map,this.collectedEnterElements=[],this.collectedLeaveElements=[],this.onRemovalComplete=function(t,e){}}return t.prototype._onRemovalComplete=function(t,e){this.onRemovalComplete(t,e)},Object.defineProperty(t.prototype,"queuedPlayers",{get:function(){var t=[];return this._namespaceList.forEach(function(e){e.players.forEach(function(e){e.queued&&t.push(e)})}),t},enumerable:!0,configurable:!0}),t.prototype.createNamespace=function(t,e){var n=new mb(t,e,this);return e.parentNode?this._balanceNamespaceList(n,e):(this.newHostElements.set(e,n),this.collectEnterElement(e)),this._namespaceLookup[t]=n},t.prototype._balanceNamespaceList=function(t,e){var n=this._namespaceList.length-1;if(n>=0){for(var a=!1,r=n;r>=0;r--)if(this.driver.containsElement(this._namespaceList[r].hostElement,e)){this._namespaceList.splice(r+1,0,t),a=!0;break}a||this._namespaceList.splice(0,0,t)}else this._namespaceList.push(t);return this.namespacesByHostElement.set(e,t),t},t.prototype.register=function(t,e){var n=this._namespaceLookup[t];return n||(n=this.createNamespace(t,e)),n},t.prototype.registerTrigger=function(t,e,n){var a=this._namespaceLookup[t];a&&a.register(e,n)&&this.totalAnimations++},t.prototype.destroy=function(t,e){var n=this;if(t){var a=this._fetchNamespace(t);this.afterFlush(function(){n.namespacesByHostElement.delete(a.hostElement),delete n._namespaceLookup[t];var e=n._namespaceList.indexOf(a);e>=0&&n._namespaceList.splice(e,1)}),this.afterFlushAnimationsDone(function(){return a.destroy(e)})}},t.prototype._fetchNamespace=function(t){return this._namespaceLookup[t]},t.prototype.fetchNamespacesByElement=function(t){var e=new Set,n=this.statesByElement.get(t);if(n)for(var a=Object.keys(n),r=0;r<a.length;r++){var i=n[a[r]].namespaceId;if(i){var s=this._fetchNamespace(i);s&&e.add(s)}}return e},t.prototype.trigger=function(t,e,n,a){if(_b(e)){var r=this._fetchNamespace(t);if(r)return r.trigger(e,n,a),!0}return!1},t.prototype.insertNode=function(t,e,n,a){if(_b(e)){var r=e[hb];if(r&&r.setForRemoval){r.setForRemoval=!1,r.setForMove=!0;var i=this.collectedLeaveElements.indexOf(e);i>=0&&this.collectedLeaveElements.splice(i,1)}if(t){var s=this._fetchNamespace(t);s&&s.insertNode(e,n)}a&&this.collectEnterElement(e)}},t.prototype.collectEnterElement=function(t){this.collectedEnterElements.push(t)},t.prototype.markElementAsDisabled=function(t,e){e?this.disabledNodes.has(t)||(this.disabledNodes.add(t),Ob(t,"ng-animate-disabled")):this.disabledNodes.has(t)&&(this.disabledNodes.delete(t),Ib(t,"ng-animate-disabled"))},t.prototype.removeNode=function(t,e,n){if(_b(e)){var a=t?this._fetchNamespace(t):null;a?a.removeNode(e,n):this.markElementAsRemoved(t,e,!1,n)}else this._onRemovalComplete(e,n)},t.prototype.markElementAsRemoved=function(t,e,n,a){this.collectedLeaveElements.push(e),e[hb]={namespaceId:t,setForRemoval:a,hasAnimation:n,removedBeforeQueried:!1}},t.prototype.listen=function(t,e,n,a,r){return _b(e)?this._fetchNamespace(t).listen(e,n,a,r):function(){}},t.prototype._buildInstruction=function(t,e,n,a,r){return t.transition.build(this.driver,t.element,t.fromState.value,t.toState.value,n,a,t.fromState.options,t.toState.options,e,r)},t.prototype.destroyInnerAnimations=function(t){var e=this,n=this.driver.query(t,".ng-trigger",!0);n.forEach(function(t){return e.destroyActiveAnimationsForElement(t)}),0!=this.playersByQueriedElement.size&&(n=this.driver.query(t,".ng-animating",!0)).forEach(function(t){return e.finishActiveQueriedAnimationOnElement(t)})},t.prototype.destroyActiveAnimationsForElement=function(t){var e=this.playersByElement.get(t);e&&e.forEach(function(t){t.queued?t.markedForDestroy=!0:t.destroy()})},t.prototype.finishActiveQueriedAnimationOnElement=function(t){var e=this.playersByQueriedElement.get(t);e&&e.forEach(function(t){return t.finish()})},t.prototype.whenRenderingDone=function(){var t=this;return new Promise(function(e){if(t.players.length)return Yh(t.players).onDone(function(){return e()});e()})},t.prototype.processLeaveNode=function(t){var e=this,n=t[hb];if(n&&n.setForRemoval){if(t[hb]=fb,n.namespaceId){this.destroyInnerAnimations(t);var a=this._fetchNamespace(n.namespaceId);a&&a.clearElementCache(t)}this._onRemovalComplete(t,n.setForRemoval)}this.driver.matchesElement(t,".ng-animate-disabled")&&this.markElementAsDisabled(t,!1),this.driver.query(t,".ng-animate-disabled",!0).forEach(function(t){e.markElementAsDisabled(t,!1)})},t.prototype.flush=function(t){var e=this;void 0===t&&(t=-1);var n=[];if(this.newHostElements.size&&(this.newHostElements.forEach(function(t,n){return e._balanceNamespaceList(t,n)}),this.newHostElements.clear()),this.totalAnimations&&this.collectedEnterElements.length)for(var a=0;a<this.collectedEnterElements.length;a++)Ob(this.collectedEnterElements[a],"ng-star-inserted");if(this._namespaceList.length&&(this.totalQueuedPlayers||this.collectedLeaveElements.length)){var r=[];try{n=this._flushAnimations(r,t)}finally{for(a=0;a<r.length;a++)r[a]()}}else for(a=0;a<this.collectedLeaveElements.length;a++)this.processLeaveNode(this.collectedLeaveElements[a]);if(this.totalQueuedPlayers=0,this.collectedEnterElements.length=0,this.collectedLeaveElements.length=0,this._flushFns.forEach(function(t){return t()}),this._flushFns=[],this._whenQuietFns.length){var i=this._whenQuietFns;this._whenQuietFns=[],n.length?Yh(n).onDone(function(){i.forEach(function(t){return t()})}):i.forEach(function(t){return t()})}},t.prototype.reportError=function(t){throw new Error("Unable to process animations due to the following failed trigger transitions\n "+t.join("\n"))},t.prototype._flushAnimations=function(t,e){var n=this,a=new Vg,r=[],i=new Map,s=[],o=new Map,u=new Map,c=new Map,l=new Set;this.disabledNodes.forEach(function(t){l.add(t);for(var e=n.driver.query(t,".ng-animate-queued",!0),a=0;a<e.length;a++)l.add(e[a])});var d=this.bodyNode,f=Array.from(this.statesByElement.keys()),h=wb(f,this.collectedEnterElements),g=new Map,b=0;h.forEach(function(t,e){var n="ng-enter"+b++;g.set(e,n),t.forEach(function(t){return Ob(t,n)})});for(var m=[],y=new Set,v=new Set,_=0;_<this.collectedLeaveElements.length;_++)(q=(M=this.collectedLeaveElements[_])[hb])&&q.setForRemoval&&(m.push(M),y.add(M),q.hasAnimation?this.driver.query(M,".ng-star-inserted",!0).forEach(function(t){return y.add(t)}):v.add(M));var x=new Map,T=wb(f,Array.from(y));T.forEach(function(t,e){var n="ng-leave"+b++;x.set(e,n),t.forEach(function(t){return Ob(t,n)})}),t.push(function(){h.forEach(function(t,e){var n=g.get(e);t.forEach(function(t){return Ib(t,n)})}),T.forEach(function(t,e){var n=x.get(e);t.forEach(function(t){return Ib(t,n)})}),m.forEach(function(t){n.processLeaveNode(t)})});for(var w=[],S=[],O=this._namespaceList.length-1;O>=0;O--)this._namespaceList[O].drainQueuedTransitions(e).forEach(function(t){var e=t.player,i=t.element;if(w.push(e),n.collectedEnterElements.length){var l=i[hb];if(l&&l.setForMove)return void e.destroy()}var f=!d||!n.driver.containsElement(d,i),p=x.get(i),h=g.get(i),b=n._buildInstruction(t,a,h,p,f);if(b.errors&&b.errors.length)S.push(b);else{if(f)return e.onStart(function(){return vg(i,b.fromStyles)}),e.onDestroy(function(){return yg(i,b.toStyles)}),void r.push(e);if(t.isFallbackTransition)return e.onStart(function(){return vg(i,b.fromStyles)}),e.onDestroy(function(){return yg(i,b.toStyles)}),void r.push(e);b.timelines.forEach(function(t){return t.stretchStartingKeyframe=!0}),a.append(i,b.timelines),s.push({instruction:b,player:e,element:i}),b.queriedElements.forEach(function(t){return Wh(o,t,[]).push(e)}),b.preStyleProps.forEach(function(t,e){var n=Object.keys(t);if(n.length){var a=u.get(e);a||u.set(e,a=new Set),n.forEach(function(t){return a.add(t)})}}),b.postStyleProps.forEach(function(t,e){var n=Object.keys(t),a=c.get(e);a||c.set(e,a=new Set),n.forEach(function(t){return a.add(t)})})}});if(S.length){var I=[];S.forEach(function(t){I.push("@"+t.triggerName+" has failed due to:\n"),t.errors.forEach(function(t){return I.push("- "+t+"\n")})}),w.forEach(function(t){return t.destroy()}),this.reportError(I)}var C=new Map,k=new Map;s.forEach(function(t){var e=t.element;a.has(e)&&(k.set(e,e),n._beforeAnimationBuild(t.player.namespaceId,t.instruction,C))}),r.forEach(function(t){var e=t.element;n._getPreviousPlayers(e,!1,t.namespaceId,t.triggerName,null).forEach(function(t){Wh(C,e,[]).push(t),t.destroy()})});var N=m.filter(function(t){return kb(t,u,c)}),R=new Map;Tb(R,this.driver,v,c,ju.a).forEach(function(t){kb(t,u,c)&&N.push(t)});var A=new Map;h.forEach(function(t,e){Tb(A,n.driver,new Set(t),u,ju.l)}),N.forEach(function(t){var e=R.get(t),n=A.get(t);R.set(t,Object(p.__assign)({},e,n))});var D=[],E=[],L={};s.forEach(function(t){var e=t.element,s=t.player,o=t.instruction;if(a.has(e)){if(l.has(e))return s.onDestroy(function(){return yg(e,o.toStyles)}),s.disabled=!0,s.overrideTotalTime(o.totalTime),void r.push(s);var u=L;if(k.size>1){for(var c=e,d=[];c=c.parentNode;){var f=k.get(c);if(f){u=f;break}d.push(c)}d.forEach(function(t){return k.set(t,u)})}var p=n._buildAnimation(s.namespaceId,o,C,i,A,R);if(s.setRealPlayer(p),u===L)D.push(s);else{var h=n.playersByElement.get(u);h&&h.length&&(s.parentPlayer=Yh(h)),r.push(s)}}else vg(e,o.fromStyles),s.onDestroy(function(){return yg(e,o.toStyles)}),E.push(s),l.has(e)&&r.push(s)}),E.forEach(function(t){var e=i.get(t.element);if(e&&e.length){var n=Yh(e);t.setRealPlayer(n)}}),r.forEach(function(t){t.parentPlayer?t.syncPlayerEvents(t.parentPlayer):t.destroy()});for(var P=0;P<m.length;P++){var M,q=(M=m[P])[hb];if(Ib(M,"ng-leave"),!q||!q.hasAnimation){var j=[];if(o.size){var F=o.get(M);F&&F.length&&j.push.apply(j,Object(p.__spread)(F));for(var z=this.driver.query(M,".ng-animating",!0),G=0;G<z.length;G++){var Y=o.get(z[G]);Y&&Y.length&&j.push.apply(j,Object(p.__spread)(Y))}}var V=j.filter(function(t){return!t.destroyed});V.length?Cb(this,M,V):this.processLeaveNode(M)}}return m.length=0,D.forEach(function(t){n.players.push(t),t.onDone(function(){t.destroy();var e=n.players.indexOf(t);n.players.splice(e,1)}),t.play()}),D},t.prototype.elementContainsData=function(t,e){var n=!1,a=e[hb];return a&&a.setForRemoval&&(n=!0),this.playersByElement.has(e)&&(n=!0),this.playersByQueriedElement.has(e)&&(n=!0),this.statesByElement.has(e)&&(n=!0),this._fetchNamespace(t).elementContainsData(e)||n},t.prototype.afterFlush=function(t){this._flushFns.push(t)},t.prototype.afterFlushAnimationsDone=function(t){this._whenQuietFns.push(t)},t.prototype._getPreviousPlayers=function(t,e,n,a,r){var i=[];if(e){var s=this.playersByQueriedElement.get(t);s&&(i=s)}else{var o=this.playersByElement.get(t);if(o){var u=!r||"void"==r;o.forEach(function(t){t.queued||(u||t.triggerName==a)&&i.push(t)})}}return(n||a)&&(i=i.filter(function(t){return!(n&&n!=t.namespaceId||a&&a!=t.triggerName)})),i},t.prototype._beforeAnimationBuild=function(t,e,n){var a,r,i=e.element,s=e.isRemovalTransition?void 0:t,o=e.isRemovalTransition?void 0:e.triggerName,u=function(t){var a=t.element,r=a!==i,u=Wh(n,a,[]);c._getPreviousPlayers(a,r,s,o,e.toState).forEach(function(t){var e=t.getRealPlayer();e.beforeDestroy&&e.beforeDestroy(),t.destroy(),u.push(t)})},c=this;try{for(var l=Object(p.__values)(e.timelines),d=l.next();!d.done;d=l.next())u(d.value)}catch(f){a={error:f}}finally{try{d&&!d.done&&(r=l.return)&&r.call(l)}finally{if(a)throw a.error}}vg(i,e.fromStyles)},t.prototype._buildAnimation=function(t,e,n,a,r,i){var s=this,o=e.triggerName,u=e.element,c=[],l=new Set,d=new Set,f=e.timelines.map(function(e){var f=e.element;l.add(f);var p=f[hb];if(p&&p.removedBeforeQueried)return new ju.d(e.duration,e.delay);var h,g,b=f!==u,m=(h=(n.get(f)||db).map(function(t){return t.getRealPlayer()}),g=[],function t(e,n){for(var a=0;a<e.length;a++){var r=e[a];r instanceof ju.k?t(r.players,n):n.push(r)}}(h,g),g).filter(function(t){return!!t.element&&t.element===f}),y=r.get(f),v=i.get(f),_=Vh(0,s._normalizer,0,e.keyframes,y,v),x=s._buildPlayer(e,_,m);if(e.subTimeline&&a&&d.add(f),b){var T=new vb(t,o,f);T.setRealPlayer(x),c.push(T)}return x});c.forEach(function(t){Wh(s.playersByQueriedElement,t.element,[]).push(t),t.onDone(function(){return function(t,e,n){var a;if(t instanceof Map){if(a=t.get(e)){if(a.length){var r=a.indexOf(n);a.splice(r,1)}0==a.length&&t.delete(e)}}else(a=t[e])&&(a.length&&(r=a.indexOf(n),a.splice(r,1)),0==a.length&&delete t[e]);return a}(s.playersByQueriedElement,t.element,t)})}),l.forEach(function(t){return Ob(t,"ng-animating")});var p=Yh(f);return p.onDestroy(function(){l.forEach(function(t){return Ib(t,"ng-animating")}),yg(u,e.toStyles)}),d.forEach(function(t){Wh(a,t,[]).push(p)}),p},t.prototype._buildPlayer=function(t,e,n){return e.length>0?this.driver.animate(t.element,e,t.duration,t.delay,t.easing,n):new ju.d(t.duration,t.delay)},t}(),vb=function(){function t(t,e,n){this.namespaceId=t,this.triggerName=e,this.element=n,this._player=new ju.d,this._containsRealPlayer=!1,this._queuedCallbacks={},this.destroyed=!1,this.markedForDestroy=!1,this.disabled=!1,this.queued=!0,this.totalTime=0}return t.prototype.setRealPlayer=function(t){var e=this;this._containsRealPlayer||(this._player=t,Object.keys(this._queuedCallbacks).forEach(function(n){e._queuedCallbacks[n].forEach(function(e){return Hh(t,n,void 0,e)})}),this._queuedCallbacks={},this._containsRealPlayer=!0,this.overrideTotalTime(t.totalTime),this.queued=!1)},t.prototype.getRealPlayer=function(){return this._player},t.prototype.overrideTotalTime=function(t){this.totalTime=t},t.prototype.syncPlayerEvents=function(t){var e=this,n=this._player;n.triggerCallback&&t.onStart(function(){return n.triggerCallback("start")}),t.onDone(function(){return e.finish()}),t.onDestroy(function(){return e.destroy()})},t.prototype._queueEvent=function(t,e){Wh(this._queuedCallbacks,t,[]).push(e)},t.prototype.onDone=function(t){this.queued&&this._queueEvent("done",t),this._player.onDone(t)},t.prototype.onStart=function(t){this.queued&&this._queueEvent("start",t),this._player.onStart(t)},t.prototype.onDestroy=function(t){this.queued&&this._queueEvent("destroy",t),this._player.onDestroy(t)},t.prototype.init=function(){this._player.init()},t.prototype.hasStarted=function(){return!this.queued&&this._player.hasStarted()},t.prototype.play=function(){!this.queued&&this._player.play()},t.prototype.pause=function(){!this.queued&&this._player.pause()},t.prototype.restart=function(){!this.queued&&this._player.restart()},t.prototype.finish=function(){this._player.finish()},t.prototype.destroy=function(){this.destroyed=!0,this._player.destroy()},t.prototype.reset=function(){!this.queued&&this._player.reset()},t.prototype.setPosition=function(t){this.queued||this._player.setPosition(t)},t.prototype.getPosition=function(){return this.queued?0:this._player.getPosition()},t.prototype.triggerCallback=function(t){var e=this._player;e.triggerCallback&&e.triggerCallback(t)},t}();function _b(t){return t&&1===t.nodeType}function xb(t,e){var n=t.style.display;return t.style.display=null!=e?e:"none",n}function Tb(t,e,n,a,r){var i=[];n.forEach(function(t){return i.push(xb(t))});var s=[];a.forEach(function(n,a){var i={};n.forEach(function(t){var n=i[t]=e.computeStyle(a,t,r);n&&0!=n.length||(a[hb]=pb,s.push(a))}),t.set(a,i)});var o=0;return n.forEach(function(t){return xb(t,i[o++])}),s}function wb(t,e){var n=new Map;if(t.forEach(function(t){return n.set(t,[])}),0==e.length)return n;var a=new Set(e),r=new Map;return e.forEach(function(t){var e=function t(e){if(!e)return 1;var i=r.get(e);if(i)return i;var s=e.parentNode;return i=n.has(s)?s:a.has(s)?1:t(s),r.set(e,i),i}(t);1!==e&&n.get(e).push(t)}),n}var Sb="$$classes";function Ob(t,e){if(t.classList)t.classList.add(e);else{var n=t[Sb];n||(n=t[Sb]={}),n[e]=!0}}function Ib(t,e){if(t.classList)t.classList.remove(e);else{var n=t[Sb];n&&delete n[e]}}function Cb(t,e,n){Yh(n).onDone(function(){return t.processLeaveNode(e)})}function kb(t,e,n){var a=n.get(t);if(!a)return!1;var r=e.get(t);return r?a.forEach(function(t){return r.add(t)}):e.set(t,a),n.delete(t),!0}var Nb=function(){function t(t,e,n){var a=this;this.bodyNode=t,this._driver=e,this._triggerCache={},this.onRemovalComplete=function(t,e){},this._transitionEngine=new yb(t,e,n),this._timelineEngine=new lb(t,e,n),this._transitionEngine.onRemovalComplete=function(t,e){return a.onRemovalComplete(t,e)}}return t.prototype.registerTrigger=function(t,e,n,a,r){var i=t+"-"+a,s=this._triggerCache[i];if(!s){var o=[],u=Mg(this._driver,r,o);if(o.length)throw new Error('The animation trigger "'+a+'" has failed to build due to the following errors:\n - '+o.join("\n - "));s=function(t,e){return new ob(t,e)}(a,u),this._triggerCache[i]=s}this._transitionEngine.registerTrigger(e,a,s)},t.prototype.register=function(t,e){this._transitionEngine.register(t,e)},t.prototype.destroy=function(t,e){this._transitionEngine.destroy(t,e)},t.prototype.onInsert=function(t,e,n,a){this._transitionEngine.insertNode(t,e,n,a)},t.prototype.onRemove=function(t,e,n){this._transitionEngine.removeNode(t,e,n)},t.prototype.disableAnimations=function(t,e){this._transitionEngine.markElementAsDisabled(t,e)},t.prototype.process=function(t,e,n,a){if("@"==n.charAt(0)){var r=Object(p.__read)(Kh(n),2);this._timelineEngine.command(r[0],e,r[1],a)}else this._transitionEngine.trigger(t,e,n,a)},t.prototype.listen=function(t,e,n,a,r){if("@"==n.charAt(0)){var i=Object(p.__read)(Kh(n),2);return this._timelineEngine.listen(i[0],e,i[1],r)}return this._transitionEngine.listen(t,e,n,a,r)},t.prototype.flush=function(t){void 0===t&&(t=-1),this._transitionEngine.flush(t)},Object.defineProperty(t.prototype,"players",{get:function(){return this._transitionEngine.players.concat(this._timelineEngine.players)},enumerable:!0,configurable:!0}),t.prototype.whenRenderingDone=function(){return this._transitionEngine.whenRenderingDone()},t}(),Rb="animation",Ab="animationend",Db=function(){function t(t,e,n,a,r,i,s){var o=this;this._element=t,this._name=e,this._duration=n,this._delay=a,this._easing=r,this._fillMode=i,this._onDoneFn=s,this._finished=!1,this._destroyed=!1,this._startTime=0,this._position=0,this._eventFn=function(t){return o._handleCallback(t)}}return t.prototype.apply=function(){var t,e,n;e=this._duration+"ms "+this._easing+" "+this._delay+"ms 1 normal "+this._fillMode+" "+this._name,(n=jb(t=this._element,"").trim()).length&&(function(t,e){for(var n=0;n<t.length;n++)","===t.charAt(n)&&0}(n),e=n+", "+e),qb(t,"",e),Mb(this._element,this._eventFn,!1),this._startTime=Date.now()},t.prototype.pause=function(){Eb(this._element,this._name,"paused")},t.prototype.resume=function(){Eb(this._element,this._name,"running")},t.prototype.setPosition=function(t){var e=Lb(this._element,this._name);this._position=t*this._duration,qb(this._element,"Delay","-"+this._position+"ms",e)},t.prototype.getPosition=function(){return this._position},t.prototype._handleCallback=function(t){var e=t._ngTestManualTimestamp||Date.now(),n=1e3*parseFloat(t.elapsedTime.toFixed(3));t.animationName==this._name&&Math.max(e-this._startTime,0)>=this._delay&&n>=this._duration&&this.finish()},t.prototype.finish=function(){this._finished||(this._finished=!0,this._onDoneFn(),Mb(this._element,this._eventFn,!0))},t.prototype.destroy=function(){var t,e,n,a;this._destroyed||(this._destroyed=!0,this.finish(),e=this._name,(a=Pb(n=jb(t=this._element,"").split(","),e))>=0&&(n.splice(a,1),qb(t,"",n.join(","))))},t}();function Eb(t,e,n){qb(t,"PlayState",n,Lb(t,e))}function Lb(t,e){var n=jb(t,"");return n.indexOf(",")>0?Pb(n.split(","),e):Pb([n],e)}function Pb(t,e){for(var n=0;n<t.length;n++)if(t[n].indexOf(e)>=0)return n;return-1}function Mb(t,e,n){n?t.removeEventListener(Ab,e):t.addEventListener(Ab,e)}function qb(t,e,n,a){var r=Rb+e;if(null!=a){var i=t.style[r];if(i.length){var s=i.split(",");s[a]=n,n=s.join(",")}}t.style[r]=n}function jb(t,e){return t.style[Rb+e]}var Fb="linear",zb=function(){function t(t,e,n,a,r,i,s){this.element=t,this.keyframes=e,this.animationName=n,this._duration=a,this._delay=r,this._finalStyles=s,this._onDoneFns=[],this._onStartFns=[],this._onDestroyFns=[],this._started=!1,this.currentSnapshot={},this._state=0,this.easing=i||Fb,this.totalTime=a+r,this._buildStyler()}return t.prototype.onStart=function(t){this._onStartFns.push(t)},t.prototype.onDone=function(t){this._onDoneFns.push(t)},t.prototype.onDestroy=function(t){this._onDestroyFns.push(t)},t.prototype.destroy=function(){this.init(),this._state>=4||(this._state=4,this._styler.destroy(),this._flushStartFns(),this._flushDoneFns(),this._onDestroyFns.forEach(function(t){return t()}),this._onDestroyFns=[])},t.prototype._flushDoneFns=function(){this._onDoneFns.forEach(function(t){return t()}),this._onDoneFns=[]},t.prototype._flushStartFns=function(){this._onStartFns.forEach(function(t){return t()}),this._onStartFns=[]},t.prototype.finish=function(){this.init(),this._state>=3||(this._state=3,this._styler.finish(),this._flushStartFns(),this._flushDoneFns())},t.prototype.setPosition=function(t){this._styler.setPosition(t)},t.prototype.getPosition=function(){return this._styler.getPosition()},t.prototype.hasStarted=function(){return this._state>=2},t.prototype.init=function(){this._state>=1||(this._state=1,this._styler.apply(),this._delay&&this._styler.pause())},t.prototype.play=function(){this.init(),this.hasStarted()||(this._flushStartFns(),this._state=2),this._styler.resume()},t.prototype.pause=function(){this.init(),this._styler.pause()},t.prototype.restart=function(){this.reset(),this.play()},t.prototype.reset=function(){this._styler.destroy(),this._buildStyler(),this._styler.apply()},t.prototype._buildStyler=function(){var t=this;this._styler=new Db(this.element,this.animationName,this._duration,this._delay,this.easing,"forwards",function(){return t.finish()})},t.prototype.triggerCallback=function(t){var e="start"==t?this._onStartFns:this._onDoneFns;e.forEach(function(t){return t()}),e.length=0},t.prototype.beforeDestroy=function(){var t=this;this.init();var e={};if(this.hasStarted()){var n=this._state>=3;Object.keys(this._finalStyles).forEach(function(a){"offset"!=a&&(e[a]=n?t._finalStyles[a]:Rg(t.element,a))})}this.currentSnapshot=e},t}(),Gb=function(t){function e(e,n){var a=t.call(this)||this;return a.element=e,a._startingStyles={},a.__initialized=!1,a._styles=og(n),a}return Object(p.__extends)(e,t),e.prototype.init=function(){var e=this;!this.__initialized&&this._startingStyles&&(this.__initialized=!0,Object.keys(this._styles).forEach(function(t){e._startingStyles[t]=e.element.style[t]}),t.prototype.init.call(this))},e.prototype.play=function(){var e=this;this._startingStyles&&(this.init(),Object.keys(this._styles).forEach(function(t){return e.element.style.setProperty(t,e._styles[t])}),t.prototype.play.call(this))},e.prototype.destroy=function(){var e=this;this._startingStyles&&(Object.keys(this._startingStyles).forEach(function(t){var n=e._startingStyles[t];n?e.element.style.setProperty(t,n):e.element.style.removeProperty(t)}),this._startingStyles=null,t.prototype.destroy.call(this))},e}(ju.d),Yb=function(){function t(){this._count=0,this._head=document.querySelector("head"),this._warningIssued=!1}return t.prototype.validateStyleProperty=function(t){return ag(t)},t.prototype.matchesElement=function(t,e){return rg(t,e)},t.prototype.containsElement=function(t,e){return ig(t,e)},t.prototype.query=function(t,e,n){return sg(t,e,n)},t.prototype.computeStyle=function(t,e,n){return window.getComputedStyle(t)[e]},t.prototype.buildKeyframeElement=function(t,e,n){n=n.map(function(t){return og(t)});var a="@keyframes "+e+" {\n",r="";n.forEach(function(t){r=" ";var e=parseFloat(t.offset);a+=""+r+100*e+"% {\n",r+=" ",Object.keys(t).forEach(function(e){var n=t[e];switch(e){case"offset":return;case"easing":return void(n&&(a+=r+"animation-timing-function: "+n+";\n"));default:return void(a+=""+r+e+": "+n+";\n")}}),a+=r+"}\n"}),a+="}\n";var i=document.createElement("style");return i.innerHTML=a,i},t.prototype.animate=function(t,e,n,a,r,i,s){void 0===i&&(i=[]),s&&this._notifyFaultyScrubber();var o=i.filter(function(t){return t instanceof zb}),u={};Cg(n,a)&&o.forEach(function(t){var e=t.currentSnapshot;Object.keys(e).forEach(function(t){return u[t]=e[t]})});var c=function(t){var e={};return t&&(Array.isArray(t)?t:[t]).forEach(function(t){Object.keys(t).forEach(function(n){"offset"!=n&&"easing"!=n&&(e[n]=t[n])})}),e}(e=kg(t,e,u));if(0==n)return new Gb(t,c);var l="gen_css_kf_"+this._count++,d=this.buildKeyframeElement(t,l,e);document.querySelector("head").appendChild(d);var f=new zb(t,e,l,n,a,r,c);return f.onDestroy(function(){var t;(t=d).parentNode.removeChild(t)}),f},t.prototype._notifyFaultyScrubber=function(){this._warningIssued||(console.warn("@angular/animations: please load the web-animations.js polyfill to allow programmatic access...\n"," visit http://bit.ly/IWukam to learn more about using the web-animation-js polyfill."),this._warningIssued=!0)},t}(),Vb=function(){function t(t,e,n){this.element=t,this.keyframes=e,this.options=n,this._onDoneFns=[],this._onStartFns=[],this._onDestroyFns=[],this._initialized=!1,this._finished=!1,this._started=!1,this._destroyed=!1,this.time=0,this.parentPlayer=null,this.currentSnapshot={},this._duration=n.duration,this._delay=n.delay||0,this.time=this._duration+this._delay}return t.prototype._onFinish=function(){this._finished||(this._finished=!0,this._onDoneFns.forEach(function(t){return t()}),this._onDoneFns=[])},t.prototype.init=function(){this._buildPlayer(),this._preparePlayerBeforeStart()},t.prototype._buildPlayer=function(){var t=this;if(!this._initialized){this._initialized=!0;var e=this.keyframes;this.domPlayer=this._triggerWebAnimation(this.element,e,this.options),this._finalKeyframe=e.length?e[e.length-1]:{},this.domPlayer.addEventListener("finish",function(){return t._onFinish()})}},t.prototype._preparePlayerBeforeStart=function(){this._delay?this._resetDomPlayerState():this.domPlayer.pause()},t.prototype._triggerWebAnimation=function(t,e,n){return t.animate(e,n)},t.prototype.onStart=function(t){this._onStartFns.push(t)},t.prototype.onDone=function(t){this._onDoneFns.push(t)},t.prototype.onDestroy=function(t){this._onDestroyFns.push(t)},t.prototype.play=function(){this._buildPlayer(),this.hasStarted()||(this._onStartFns.forEach(function(t){return t()}),this._onStartFns=[],this._started=!0),this.domPlayer.play()},t.prototype.pause=function(){this.init(),this.domPlayer.pause()},t.prototype.finish=function(){this.init(),this._onFinish(),this.domPlayer.finish()},t.prototype.reset=function(){this._resetDomPlayerState(),this._destroyed=!1,this._finished=!1,this._started=!1},t.prototype._resetDomPlayerState=function(){this.domPlayer&&this.domPlayer.cancel()},t.prototype.restart=function(){this.reset(),this.play()},t.prototype.hasStarted=function(){return this._started},t.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this._resetDomPlayerState(),this._onFinish(),this._onDestroyFns.forEach(function(t){return t()}),this._onDestroyFns=[])},t.prototype.setPosition=function(t){this.domPlayer.currentTime=t*this.time},t.prototype.getPosition=function(){return this.domPlayer.currentTime/this.time},Object.defineProperty(t.prototype,"totalTime",{get:function(){return this._delay+this._duration},enumerable:!0,configurable:!0}),t.prototype.beforeDestroy=function(){var t=this,e={};this.hasStarted()&&Object.keys(this._finalKeyframe).forEach(function(n){"offset"!=n&&(e[n]=t._finished?t._finalKeyframe[n]:Rg(t.element,n))}),this.currentSnapshot=e},t.prototype.triggerCallback=function(t){var e="start"==t?this._onStartFns:this._onDoneFns;e.forEach(function(t){return t()}),e.length=0},t}(),Hb=function(){function t(){this._isNativeImpl=/\{\s*\[native\s+code\]\s*\}/.test(Bb().toString()),this._cssKeyframesDriver=new Yb}return t.prototype.validateStyleProperty=function(t){return ag(t)},t.prototype.matchesElement=function(t,e){return rg(t,e)},t.prototype.containsElement=function(t,e){return ig(t,e)},t.prototype.query=function(t,e,n){return sg(t,e,n)},t.prototype.computeStyle=function(t,e,n){return window.getComputedStyle(t)[e]},t.prototype.overrideWebAnimationsSupport=function(t){this._isNativeImpl=t},t.prototype.animate=function(t,e,n,a,r,i,s){if(void 0===i&&(i=[]),!s&&!this._isNativeImpl)return this._cssKeyframesDriver.animate(t,e,n,a,r,i);var o={duration:n,delay:a,fill:0==a?"both":"forwards"};r&&(o.easing=r);var u={},c=i.filter(function(t){return t instanceof Vb});return Cg(n,a)&&c.forEach(function(t){var e=t.currentSnapshot;Object.keys(e).forEach(function(t){return u[t]=e[t]})}),e=kg(t,e=e.map(function(t){return gg(t,!1)}),u),new Vb(t,e,o)},t}();function Bb(){return"undefined"!=typeof window&&void 0!==window.document&&Element.prototype.animate||{}}var Ub=function(t){function e(e,n){var a=t.call(this)||this;return a._nextAnimationId=0,a._renderer=e.createRenderer(n.body,{id:"0",encapsulation:s.ViewEncapsulation.None,styles:[],data:{animation:[]}}),a}return Object(p.__extends)(e,t),e.prototype.build=function(t){var e=this._nextAnimationId.toString();this._nextAnimationId++;var n=Array.isArray(t)?Object(ju.f)(t):t;return $b(this._renderer,null,e,"register",[n]),new Wb(e,this._renderer)},e}(ju.b),Wb=function(t){function e(e,n){var a=t.call(this)||this;return a._id=e,a._renderer=n,a}return Object(p.__extends)(e,t),e.prototype.create=function(t,e){return new Kb(this._id,t,e||{},this._renderer)},e}(ju.c),Kb=function(){function t(t,e,n,a){this.id=t,this.element=e,this._renderer=a,this.parentPlayer=null,this._started=!1,this.totalTime=0,this._command("create",n)}return t.prototype._listen=function(t,e){return this._renderer.listen(this.element,"@@"+this.id+":"+t,e)},t.prototype._command=function(t){for(var e=[],n=1;n<arguments.length;n++)e[n-1]=arguments[n];return $b(this._renderer,this.element,this.id,t,e)},t.prototype.onDone=function(t){this._listen("done",t)},t.prototype.onStart=function(t){this._listen("start",t)},t.prototype.onDestroy=function(t){this._listen("destroy",t)},t.prototype.init=function(){this._command("init")},t.prototype.hasStarted=function(){return this._started},t.prototype.play=function(){this._command("play"),this._started=!0},t.prototype.pause=function(){this._command("pause")},t.prototype.restart=function(){this._command("restart")},t.prototype.finish=function(){this._command("finish")},t.prototype.destroy=function(){this._command("destroy")},t.prototype.reset=function(){this._command("reset")},t.prototype.setPosition=function(t){this._command("setPosition",t)},t.prototype.getPosition=function(){return 0},t}();function $b(t,e,n,a,r){return t.setProperty(e,"@@"+n+":"+a,r)}var Zb=function(){function t(t,e,n){this.delegate=t,this.engine=e,this._zone=n,this._currentId=0,this._microtaskId=1,this._animationCallbacksBuffer=[],this._rendererCache=new Map,this._cdRecurDepth=0,this.promise=Promise.resolve(0),e.onRemovalComplete=function(t,e){e&&e.parentNode(t)&&e.removeChild(t.parentNode,t)}}return t.prototype.createRenderer=function(t,e){var n=this,a=this.delegate.createRenderer(t,e);if(!(t&&e&&e.data&&e.data.animation)){var r=this._rendererCache.get(a);return r||(r=new Xb("",a,this.engine),this._rendererCache.set(a,r)),r}var i=e.id,s=e.id+"-"+this._currentId;return this._currentId++,this.engine.register(s,t),e.data.animation.forEach(function(e){return n.engine.registerTrigger(i,s,t,e.name,e)}),new Jb(this,s,a,this.engine)},t.prototype.begin=function(){this._cdRecurDepth++,this.delegate.begin&&this.delegate.begin()},t.prototype._scheduleCountTask=function(){var t=this;this.promise.then(function(){t._microtaskId++})},t.prototype.scheduleListenerCallback=function(t,e,n){var a=this;t>=0&&t<this._microtaskId?this._zone.run(function(){return e(n)}):(0==this._animationCallbacksBuffer.length&&Promise.resolve(null).then(function(){a._zone.run(function(){a._animationCallbacksBuffer.forEach(function(t){var e=Object(p.__read)(t,2);(0,e[0])(e[1])}),a._animationCallbacksBuffer=[]})}),this._animationCallbacksBuffer.push([e,n]))},t.prototype.end=function(){var t=this;this._cdRecurDepth--,0==this._cdRecurDepth&&this._zone.runOutsideAngular(function(){t._scheduleCountTask(),t.engine.flush(t._microtaskId)}),this.delegate.end&&this.delegate.end()},t.prototype.whenRenderingDone=function(){return this.engine.whenRenderingDone()},t}(),Xb=function(){function t(t,e,n){this.namespaceId=t,this.delegate=e,this.engine=n,this.destroyNode=this.delegate.destroyNode?function(t){return e.destroyNode(t)}:null}return Object.defineProperty(t.prototype,"data",{get:function(){return this.delegate.data},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){this.engine.destroy(this.namespaceId,this.delegate),this.delegate.destroy()},t.prototype.createElement=function(t,e){return this.delegate.createElement(t,e)},t.prototype.createComment=function(t){return this.delegate.createComment(t)},t.prototype.createText=function(t){return this.delegate.createText(t)},t.prototype.appendChild=function(t,e){this.delegate.appendChild(t,e),this.engine.onInsert(this.namespaceId,e,t,!1)},t.prototype.insertBefore=function(t,e,n){this.delegate.insertBefore(t,e,n),this.engine.onInsert(this.namespaceId,e,t,!0)},t.prototype.removeChild=function(t,e){this.engine.onRemove(this.namespaceId,e,this.delegate)},t.prototype.selectRootElement=function(t,e){return this.delegate.selectRootElement(t,e)},t.prototype.parentNode=function(t){return this.delegate.parentNode(t)},t.prototype.nextSibling=function(t){return this.delegate.nextSibling(t)},t.prototype.setAttribute=function(t,e,n,a){this.delegate.setAttribute(t,e,n,a)},t.prototype.removeAttribute=function(t,e,n){this.delegate.removeAttribute(t,e,n)},t.prototype.addClass=function(t,e){this.delegate.addClass(t,e)},t.prototype.removeClass=function(t,e){this.delegate.removeClass(t,e)},t.prototype.setStyle=function(t,e,n,a){this.delegate.setStyle(t,e,n,a)},t.prototype.removeStyle=function(t,e,n){this.delegate.removeStyle(t,e,n)},t.prototype.setProperty=function(t,e,n){"@"==e.charAt(0)&&"@.disabled"==e?this.disableAnimations(t,!!n):this.delegate.setProperty(t,e,n)},t.prototype.setValue=function(t,e){this.delegate.setValue(t,e)},t.prototype.listen=function(t,e,n){return this.delegate.listen(t,e,n)},t.prototype.disableAnimations=function(t,e){this.engine.disableAnimations(t,e)},t}(),Jb=function(t){function e(e,n,a,r){var i=t.call(this,n,a,r)||this;return i.factory=e,i.namespaceId=n,i}return Object(p.__extends)(e,t),e.prototype.setProperty=function(t,e,n){"@"==e.charAt(0)?"."==e.charAt(1)&&"@.disabled"==e?this.disableAnimations(t,n=void 0===n||!!n):this.engine.process(this.namespaceId,t,e.substr(1),n):this.delegate.setProperty(t,e,n)},e.prototype.listen=function(t,e,n){var a,r,i,s=this;if("@"==e.charAt(0)){var o=function(t){switch(t){case"body":return document.body;case"document":return document;case"window":return window;default:return t}}(t),u=e.substr(1),c="";return"@"!=u.charAt(0)&&(u=(a=Object(p.__read)((r=u,i=r.indexOf("."),[r.substring(0,i),r.substr(i+1)]),2))[0],c=a[1]),this.engine.listen(this.namespaceId,o,u,c,function(t){s.factory.scheduleListenerCallback(t._data||-1,n,t)})}return this.delegate.listen(t,e,n)},e}(Xb),Qb=function(t){function e(e,n,a){return t.call(this,e.body,n,a)||this}return Object(p.__extends)(e,t),e}(Nb);function tm(){return"function"==typeof Bb()?new Hb:new Yb}function em(){return new tb}function nm(t,e,n){return new Zb(t,e,n)}var am=new s.InjectionToken("AnimationModuleType"),rm=function(){return function(){}}(),im=n("Avrn"),sm=n("Vhfg"),om=function(){function t(t,e){this.http=t,this.router=e}return t.prototype.canActivate=function(t){return this.doCheck(t)},t.prototype.canActivateChild=function(t){return this.doCheck(t)},t.prototype.doCheck=function(e){var n=this;if(e.url.length>0&&t.WHITELIST.includes(e.url[0].path))return Object(gc.a)(!0);var a=e.data.moduleStatusGuardConfig;return this.http.get("api/"+a.apiPath+"/status").pipe(Object(Bi.a)(function(t){return t.available||n.router.navigate([a.redirectTo,t.message||""]),t.available}),Object(Fh.a)(function(){return n.router.navigate([a.redirectTo]),Object(gc.a)(!1)}))},t.WHITELIST=["501"],t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c),s.inject(tt.l))},token:t,providedIn:"root"}),t}(),um=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return p.__extends(e,t),e.prototype.resolve=function(t){var e=[],n=t.queryParams.fromLink||null,a="";switch(n){case"/monitor":a="Monitors";break;case"/hosts":a="Hosts"}return e.push({text:"Cluster",path:null}),e.push({text:a,path:n}),e.push({text:"Performance Counters",path:""}),e},e}(Oh),cm=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return p.__extends(e,t),e.prototype.resolve=function(t){var e=t.params.name;return[{text:ft.startCase(e),path:e}]},e}(Oh),lm={breadcrumbs:"Cluster/Hosts"},dm={breadcrumbs:"Cluster/Monitors"},fm={breadcrumbs:"Cluster/OSDs"},pm={breadcrumbs:"Cluster/Configuration"},hm={breadcrumbs:Zn.a.EDIT},gm={breadcrumbs:"Cluster/CRUSH map"},bm={breadcrumbs:"Cluster/Logs"},mm={breadcrumbs:"Cluster/Monitoring"},ym={breadcrumbs:Zn.a.CREATE+" Silence"},vm={breadcrumbs:Zn.a.CREATE},_m={breadcrumbs:Zn.a.EDIT},xm={breadcrumbs:Zn.a.RECREATE},Tm={breadcrumbs:um},wm={breadcrumbs:"Cluster/Manager modules"},Sm={breadcrumbs:cm},Om={breadcrumbs:"Pools"},Im={breadcrumbs:!0,text:"Block",path:null},Cm={breadcrumbs:"Filesystems"},km={moduleStatusGuardConfig:{apiPath:"rgw",redirectTo:"rgw/501"},breadcrumbs:!0,text:"Object Gateway",path:null},Nm={breadcrumbs:"User management",path:null},Rm={breadcrumbs:"NFS"},Am={moduleStatusGuardConfig:{apiPath:"nfs-ganesha",redirectTo:"nfs/501"},breadcrumbs:"NFS"},Dm={breadcrumbs:Zn.a.CREATE},Em={breadcrumbs:Zn.a.EDIT},Lm=function(){return function(){}}(),Pm=n("IzCI"),Mm=n("Dwqy"),qm=n("uYzU"),jm=n("uhwM"),Fm=n("nSDx"),zm=n("SB+Q"),Gm=n("BQkM"),Ym=n("dEH0"),Vm=n("G1/K"),Hm=n("TJUb"),Bm=n("lTVp"),Um=n("FO+L"),Wm=n("nhM1"),Km=n("BARL"),$m=n("JZ5S"),Zm=n("Da1D"),Xm=function(){return function(){this.closeOthers=!1,this.isAnimated=!1}}(),Jm=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[Xm]}},t}(),Qm=function(){function t(t){this.http=t}return t.prototype.jsError=function(t,e,n){return this.http.post("ui-api/logging/js-error",{url:t,message:e,stack:n})},t.ngInjectableDef=s.defineInjectable({factory:function(){return new t(s.inject(kt.c))},token:t,providedIn:Nt.a}),t}(),ty=function(){function t(t){this.injector=t}return t.prototype.handleError=function(t){var e=this.injector.get(Qm),n=window.location.href;throw e.jsError(n,t&&t.message,t&&t.stack).subscribe(),t},t}(),ey=n("9Xeq"),ny=n("yGOH"),ay=n("V/fk"),ry=n("F8xH"),iy=n("ChqD"),sy=n("PCNd"),oy=n("LceX"),uy=function(){return function(){}}(),cy=function(){return function(){}}(),ly=n("G6Q+"),dy=n("STEd"),fy=function(){return function(){}}(),py=function(){return function(){}}(),hy=n("kJI8"),gy=function(){return function(){}}(),by=function(){return function(){}}(),my=function(){return function(){}}(),yy=function(){return function(){}}(),vy=s["\u0275cmf"](u,[f],function(t){return s["\u0275mod"]([s["\u0275mpd"](512,s.ComponentFactoryResolver,s["\u0275CodegenComponentFactoryResolver"],[[8,[k,M,W,K.a,Pe,on,gn,Na,Ka,mr,kr,Vi,Cs,Js,ao,go,Ho,hu,vu,Mu,Nl,Pl,rd,cd,hd,gd.a,bd.a,md.a,yd.a,vd.a,vd.b,_d.a,xd.a,Td.a,Nd,Rd.a,Rd.c,Rd.b,Ud,Wn,tf,uf,Tf,Nf,$f,ip,qh]],[3,s.ComponentFactoryResolver],s.NgModuleRef]),s["\u0275mpd"](4608,kt.j,kt.p,[i.DOCUMENT,s.PLATFORM_ID,kt.n]),s["\u0275mpd"](4608,kt.q,kt.q,[kt.j,kt.o]),s["\u0275mpd"](4608,l.a,l.a,[]),s["\u0275mpd"](5120,kt.a,function(t,e,n,a){return[t,new zh(e,n,a)]},[kt.q,tt.l,l.a,Jn.a]),s["\u0275mpd"](4608,kt.m,kt.m,[]),s["\u0275mpd"](6144,kt.k,null,[kt.m]),s["\u0275mpd"](4608,kt.i,kt.i,[kt.k]),s["\u0275mpd"](6144,kt.b,null,[kt.i]),s["\u0275mpd"](4608,kt.g,kt.l,[kt.b,s.Injector]),s["\u0275mpd"](4608,kt.c,kt.c,[kt.g]),s["\u0275mpd"](4352,s.LOCALE_ID,"en-US",[]),s["\u0275mpd"](4608,i.NgLocalization,i.NgLocaleLocalization,[s.LOCALE_ID,[2,i["\u0275angular_packages_common_common_a"]]]),s["\u0275mpd"](5120,s.APP_ID,s["\u0275angular_packages_core_core_h"],[]),s["\u0275mpd"](5120,s.IterableDiffers,s["\u0275angular_packages_core_core_q"],[]),s["\u0275mpd"](5120,s.KeyValueDiffers,s["\u0275angular_packages_core_core_r"],[]),s["\u0275mpd"](4608,Fe.DomSanitizer,Fe["\u0275DomSanitizerImpl"],[i.DOCUMENT]),s["\u0275mpd"](6144,s.Sanitizer,null,[Fe.DomSanitizer]),s["\u0275mpd"](4608,Fe.HAMMER_GESTURE_CONFIG,Fe.HammerGestureConfig,[]),s["\u0275mpd"](5120,Fe.EVENT_MANAGER_PLUGINS,function(t,e,n,a,r,i,s,o){return[new Fe["\u0275DomEventsPlugin"](t,e,n),new Fe["\u0275KeyEventsPlugin"](a),new Fe["\u0275HammerGesturesPlugin"](r,i,s,o)]},[i.DOCUMENT,s.NgZone,s.PLATFORM_ID,i.DOCUMENT,i.DOCUMENT,Fe.HAMMER_GESTURE_CONFIG,s["\u0275Console"],[2,Fe.HAMMER_LOADER]]),s["\u0275mpd"](4608,Fe.EventManager,Fe.EventManager,[Fe.EVENT_MANAGER_PLUGINS,s.NgZone]),s["\u0275mpd"](135680,Fe["\u0275DomSharedStylesHost"],Fe["\u0275DomSharedStylesHost"],[i.DOCUMENT]),s["\u0275mpd"](4608,Fe["\u0275DomRendererFactory2"],Fe["\u0275DomRendererFactory2"],[Fe.EventManager,Fe["\u0275DomSharedStylesHost"]]),s["\u0275mpd"](5120,cg,tm,[]),s["\u0275mpd"](5120,Qg,em,[]),s["\u0275mpd"](4608,Nb,Qb,[i.DOCUMENT,cg,Qg]),s["\u0275mpd"](5120,s.RendererFactory2,nm,[Fe["\u0275DomRendererFactory2"],Nb,s.NgZone]),s["\u0275mpd"](6144,Fe["\u0275SharedStylesHost"],null,[Fe["\u0275DomSharedStylesHost"]]),s["\u0275mpd"](4608,s.Testability,s.Testability,[s.NgZone]),s["\u0275mpd"](4608,ju.b,Ub,[s.RendererFactory2,Fe.DOCUMENT]),s["\u0275mpd"](5120,tt.a,tt.B,[tt.l]),s["\u0275mpd"](4608,tt.f,tt.f,[]),s["\u0275mpd"](6144,tt.g,null,[tt.f]),s["\u0275mpd"](135680,tt.r,tt.r,[tt.l,s.NgModuleFactoryLoader,s.Compiler,s.Injector,tt.g]),s["\u0275mpd"](4608,tt.e,tt.e,[]),s["\u0275mpd"](5120,tt.F,tt.x,[tt.l,i.ViewportScroller,tt.h]),s["\u0275mpd"](5120,tt.i,tt.E,[tt.C]),s["\u0275mpd"](5120,s.APP_BOOTSTRAP_LISTENER,function(t){return[t]},[tt.i]),s["\u0275mpd"](4608,cm,cm,[]),s["\u0275mpd"](4608,um,um,[]),s["\u0275mpd"](4608,Te.E,Te.E,[]),s["\u0275mpd"](4608,Te.h,Te.h,[]),s["\u0275mpd"](5120,s.TRANSLATIONS,o,[s.LOCALE_ID]),s["\u0275mpd"](4608,xt.a,xt.a,[s.TRANSLATIONS_FORMAT,s.TRANSLATIONS,s.LOCALE_ID,[2,xt.b]]),s["\u0275mpd"](4608,Aa.a,Aa.a,[xt.a]),s["\u0275mpd"](4608,i.DatePipe,i.DatePipe,[s.LOCALE_ID]),s["\u0275mpd"](4608,Ze.a,Ze.a,[]),s["\u0275mpd"](4608,Ge.a,Ge.a,[]),s["\u0275mpd"](4608,It.a,It.a,[]),s["\u0275mpd"](4608,ht.a,ht.a,[It.a]),s["\u0275mpd"](4608,Pm.a,Pm.a,[It.a]),s["\u0275mpd"](4608,gt.a,gt.a,[It.a]),s["\u0275mpd"](4608,Mm.a,Mm.a,[]),s["\u0275mpd"](4608,qm.a,qm.a,[]),s["\u0275mpd"](4608,jm.a,jm.a,[]),s["\u0275mpd"](4608,Ii.a,Ii.a,[]),s["\u0275mpd"](4608,On.a,On.a,[i.DatePipe]),s["\u0275mpd"](4608,Fm.a,Fm.a,[]),s["\u0275mpd"](4608,zm.a,zm.a,[]),s["\u0275mpd"](4608,rc.a,rc.a,[]),s["\u0275mpd"](4608,Gm.a,Gm.a,[]),s["\u0275mpd"](4608,Ym.a,Ym.a,[]),s["\u0275mpd"](4608,Vm.a,Vm.a,[xt.a]),s["\u0275mpd"](4608,Rs.a,Rs.a,[]),s["\u0275mpd"](4608,Hm.a,Hm.a,[]),s["\u0275mpd"](4608,Bm.b,Bm.b,[]),s["\u0275mpd"](4608,X.a,X.a,[]),s["\u0275mpd"](4608,Q.a,Q.a,[s.RendererFactory2,s.PLATFORM_ID]),s["\u0275mpd"](4608,J.a,J.a,[s.ComponentFactoryResolver,s.NgZone,s.Injector,Q.a,s.ApplicationRef]),s["\u0275mpd"](4608,c.a,c.a,[]),s["\u0275mpd"](4608,pa.b,pa.b,[s.RendererFactory2,J.a]),s["\u0275mpd"](4608,Um.ScrollbarHelper,Um.ScrollbarHelper,[Fe.DOCUMENT]),s["\u0275mpd"](4608,Wm.DimensionsHelper,Wm.DimensionsHelper,[]),s["\u0275mpd"](4608,Km.ColumnChangesService,Km.ColumnChangesService,[]),s["\u0275mpd"](4608,bn.f,bn.f,[]),s["\u0275mpd"](4608,im.a,im.a,[tt.l,l.a]),s["\u0275mpd"](4608,Z.e,Z.e,[]),s["\u0275mpd"](4608,_r.NodeDraggableService,_r.NodeDraggableService,[]),s["\u0275mpd"](4608,$m.NodeMenuService,$m.NodeMenuService,[]),s["\u0275mpd"](4608,vr.TreeService,vr.TreeService,[_r.NodeDraggableService]),s["\u0275mpd"](4608,Nr.r,Nr.r,[]),s["\u0275mpd"](4608,Nr.t,Nr.t,[]),s["\u0275mpd"](4608,Nr.a,Nr.a,[]),s["\u0275mpd"](4608,Nr.h,Nr.h,[]),s["\u0275mpd"](4608,Nr.d,Nr.d,[]),s["\u0275mpd"](4608,Nr.j,Nr.j,[]),s["\u0275mpd"](4608,Nr.s,Nr.s,[Nr.t,Nr.j]),s["\u0275mpd"](4608,Qu,Qu,[]),s["\u0275mpd"](4608,ti,ti,[]),s["\u0275mpd"](4608,Ar,Ar,[]),s["\u0275mpd"](4608,ai,ai,[]),s["\u0275mpd"](4608,Zm.c,Zm.c,[]),s["\u0275mpd"](5120,m,w,[T]),s["\u0275mpd"](4608,_,_,[m]),s["\u0275mpd"](4608,Xm,Xm,[]),s["\u0275mpd"](1073742336,kt.e,kt.e,[]),s["\u0275mpd"](1073742336,kt.d,kt.d,[]),s["\u0275mpd"](1073742336,i.CommonModule,i.CommonModule,[]),s["\u0275mpd"](1073742336,S,S,[]),s["\u0275mpd"](512,s.ErrorHandler,ty,[s.Injector]),s["\u0275mpd"](1024,s.NgProbeToken,function(){return[tt.w()]},[]),s["\u0275mpd"](512,tt.C,tt.C,[s.Injector]),s["\u0275mpd"](1024,s.APP_INITIALIZER,function(t,e){return[Fe["\u0275angular_packages_platform_browser_platform_browser_j"](t),tt.D(e)]},[[2,s.NgProbeToken],tt.C]),s["\u0275mpd"](512,s.ApplicationInitStatus,s.ApplicationInitStatus,[[2,s.APP_INITIALIZER]]),s["\u0275mpd"](131584,s.ApplicationRef,s.ApplicationRef,[s.NgZone,s["\u0275Console"],s.Injector,s.ErrorHandler,s.ComponentFactoryResolver,s.ApplicationInitStatus]),s["\u0275mpd"](1073742336,s.ApplicationModule,s.ApplicationModule,[s.ApplicationRef]),s["\u0275mpd"](1073742336,Fe.BrowserModule,Fe.BrowserModule,[[3,Fe.BrowserModule]]),s["\u0275mpd"](1073742336,rm,rm,[]),s["\u0275mpd"](1073742336,q.i,q.i,[]),s["\u0275mpd"](1024,tt.v,tt.z,[[3,tt.l]]),s["\u0275mpd"](512,tt.t,tt.c,[]),s["\u0275mpd"](512,tt.b,tt.b,[]),s["\u0275mpd"](256,tt.h,{useHash:!0,preloadingStrategy:tt.f},[]),s["\u0275mpd"](1024,i.LocationStrategy,tt.y,[i.PlatformLocation,[2,i.APP_BASE_HREF],tt.h]),s["\u0275mpd"](512,i.Location,i.Location,[i.LocationStrategy]),s["\u0275mpd"](512,s.Compiler,s.Compiler,[]),s["\u0275mpd"](512,s.NgModuleFactoryLoader,s.SystemJsNgModuleLoader,[s.Compiler,[2,s.SystemJsNgModuleLoaderConfig]]),s["\u0275mpd"](1024,tt.j,function(){return[[{path:"",redirectTo:"dashboard",pathMatch:"full"},{path:"dashboard",component:Ne,canActivate:[im.a]},{path:"hosts",component:Xe,canActivate:[im.a],data:lm},{path:"monitor",component:ln,canActivate:[im.a],data:dm},{path:"osd",canActivate:[im.a],canActivateChild:[im.a],data:fm,children:[{path:"",component:fa}]},{path:"configuration",data:pm,children:[{path:"",component:Fa},{path:"edit/:name",component:tr,data:hm}]},{path:"crush-map",component:Tr,canActivate:[im.a],data:gm},{path:"logs",component:ki,canActivate:[im.a],data:bm},{path:"monitoring",canActivate:[im.a],data:mm,children:[{path:"",component:ms},{path:"silence/create",component:Ls,data:ym},{path:"silence/create/:id",component:Ls,data:vm},{path:"silence/edit/:id",component:Ls,data:_m},{path:"silence/recreate/:id",component:Ls,data:xm}]},{path:"perf_counters/:type/:id",component:Qs,canActivate:[im.a],data:Tm},{path:"mgr-modules",canActivate:[im.a],canActivateChild:[im.a],data:wm,children:[{path:"",component:lo},{path:"edit/:name",component:_o,data:Sm}]},{path:"pool",canActivate:[im.a],canActivateChild:[im.a],data:Om,loadChildren:"./ceph/pool/pool.module#RoutedPoolModule"},{path:"block",canActivateChild:[im.a],canActivate:[im.a],data:Im,loadChildren:"./ceph/block/block.module#RoutedBlockModule"},{path:"cephfs",component:lu,canActivate:[sm.a,im.a],data:Cm},{path:"rgw",canActivateChild:[sm.a,om,im.a],data:km,loadChildren:"./ceph/rgw/rgw.module#RoutedRgwModule"},{path:"user-management",canActivate:[im.a],canActivateChild:[im.a],data:Nm,loadChildren:"./core/auth/auth.module#RoutedAuthModule"},{path:"nfs/501/:message",component:gu,canActivate:[im.a],data:Rm},{path:"nfs",canActivate:[im.a],canActivateChild:[im.a,om],data:Am,children:[{path:"",component:Nu},{path:"create",component:vc,data:Dm},{path:"edit/:cluster_id/:export_id",component:vc,data:Em}]},{path:"sso/404",component:Rl},{path:"login",component:Xl},{path:"logout",children:[]},{path:"403",component:id},{path:"404",component:ld},{path:"**",redirectTo:"/404"}]]},[]),s["\u0275mpd"](1024,tt.l,tt.A,[s.ApplicationRef,tt.t,tt.b,i.Location,s.Injector,s.NgModuleFactoryLoader,s.Compiler,tt.j,tt.h,[2,tt.s],[2,tt.k]]),s["\u0275mpd"](1073742336,tt.p,tt.p,[[2,tt.v],[2,tt.l]]),s["\u0275mpd"](1073742336,Lm,Lm,[]),s["\u0275mpd"](1073742336,bn.e,bn.e,[]),s["\u0275mpd"](1073742336,Te.B,Te.B,[]),s["\u0275mpd"](1073742336,Te.n,Te.n,[]),s["\u0275mpd"](1073742336,X.d,X.d,[]),s["\u0275mpd"](1073742336,Te.x,Te.x,[]),s["\u0275mpd"](1073742336,ey.a,ey.a,[]),s["\u0275mpd"](1073742336,Bm.c,Bm.c,[]),s["\u0275mpd"](1073742336,c.d,c.d,[]),s["\u0275mpd"](1073742336,lt.ChartsModule,lt.ChartsModule,[]),s["\u0275mpd"](1073742336,pa.e,pa.e,[]),s["\u0275mpd"](1073742336,ny.a,ny.a,[]),s["\u0275mpd"](1073742336,ay.a,ay.a,[]),s["\u0275mpd"](1073742336,ry.NgxDatatableModule,ry.NgxDatatableModule,[]),s["\u0275mpd"](1073742336,iy.a,iy.a,[]),s["\u0275mpd"](1073742336,Nt.a,Nt.a,[]),s["\u0275mpd"](1073742336,sy.a,sy.a,[]),s["\u0275mpd"](1073742336,Z.c,Z.c,[]),s["\u0275mpd"](1073742336,oy.a,oy.a,[]),s["\u0275mpd"](1073742336,cp,cp,[]),s["\u0275mpd"](1073742336,uy,uy,[]),s["\u0275mpd"](1073742336,cy,cy,[]),s["\u0275mpd"](1073742336,ly.a,ly.a,[]),s["\u0275mpd"](1073742336,Nr.g,Nr.g,[]),s["\u0275mpd"](1073742336,dy.TreeModule,dy.TreeModule,[]),s["\u0275mpd"](1073742336,fy,fy,[]),s["\u0275mpd"](1073742336,ec,ec,[]),s["\u0275mpd"](1073742336,ii,ii,[]),s["\u0275mpd"](1073742336,py,py,[]),s["\u0275mpd"](1073742336,hy.a,hy.a,[]),s["\u0275mpd"](1073742336,gy,gy,[]),s["\u0275mpd"](1073742336,Zm.d,Zm.d,[]),s["\u0275mpd"](1073742336,by,by,[]),s["\u0275mpd"](1073742336,my,my,[]),s["\u0275mpd"](1073742336,yy,yy,[]),s["\u0275mpd"](1073742336,Jm,Jm,[]),s["\u0275mpd"](1073742336,u,u,[]),s["\u0275mpd"](256,kt.n,"XSRF-TOKEN",[]),s["\u0275mpd"](256,kt.o,"X-XSRF-TOKEN",[]),s["\u0275mpd"](256,s["\u0275APP_ROOT"],!0,[]),s["\u0275mpd"](256,am,"BrowserAnimations",[]),s["\u0275mpd"](256,s.TRANSLATIONS_FORMAT,"xlf",[]),s["\u0275mpd"](256,bn.a,{autoClose:!0,insideClick:!1},[]),s["\u0275mpd"](256,T,{},[]),s["\u0275mpd"](256,q.b,{default:q.a,config:{positionClass:"toast-top-right",preventDuplicates:!0,enableHtml:!0}},[])])});i.registerLocaleData(r.a),Object(s.enableProdMode)(),Fe.platformBrowser().bootstrapModuleFactory(vy).catch(function(t){return console.log(t)})},zavE:function(t,e,n){!function(t){"use strict";n("wd/R").defineLocale("en-SG",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10;return t+(1==~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")},week:{dow:1,doy:4}})}()},zo3G:function(t,e,n){"use strict";var a=n("mrSG"),r=function(t){function e(e,n){var a=t.call(this,e,n)||this;return a.scheduler=e,a.work=n,a}return a.__extends(e,t),e.prototype.schedule=function(e,n){return void 0===n&&(n=0),n>0?t.prototype.schedule.call(this,e,n):(this.delay=n,this.state=e,this.scheduler.flush(this),this)},e.prototype.execute=function(e,n){return n>0||this.closed?t.prototype.execute.call(this,e,n):this._execute(e,n)},e.prototype.requestAsyncId=function(e,n,a){return void 0===a&&(a=0),null!==a&&a>0||null===a&&this.delay>0?t.prototype.requestAsyncId.call(this,e,n,a):e.flush(this)},e}(n("h9Dq").a),i=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a.__extends(e,t),e}(n("CS9Q").a);n.d(e,"a",function(){return s});var s=new i(r)},zotm:function(t,e,n){"use strict";n.d(e,"a",function(){return s});var a=n("rPjj"),r=n("Fxb1"),i=n("6blF");function s(t,e,n,s,o){if(void 0===o&&(o=new a.a(t,n,s)),!o.closed)return e instanceof i.a?e.subscribe(o):Object(r.a)(e)(o)}},"zrt+":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var a=n("6blF");function r(t){return!!t&&(t instanceof a.a||"function"==typeof t.lift&&"function"==typeof t.subscribe)}},zx6S:function(t,e,n){!function(t){"use strict";var e={words:{ss:["sekunda","sekunde","sekundi"],m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(t,e){return 1===t?e[0]:t>=2&&t<=4?e[1]:e[2]},translate:function(t,n,a){var r=e.words[a];return 1===a.length?n?r[0]:r[1]:t+" "+e.correctGrammaticalCase(t,r)}};t.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_\u010detvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._\u010det._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_\u010de_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[ju\u010de u] LT",lastWeek:function(){return["[pro\u0161le] [nedelje] [u] LT","[pro\u0161log] [ponedeljka] [u] LT","[pro\u0161log] [utorka] [u] LT","[pro\u0161le] [srede] [u] LT","[pro\u0161log] [\u010detvrtka] [u] LT","[pro\u0161log] [petka] [u] LT","[pro\u0161le] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",ss:e.translate,m:e.translate,mm:e.translate,h:e.translate,hh:e.translate,d:"dan",dd:e.translate,M:"mesec",MM:e.translate,y:"godinu",yy:e.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})}(n("wd/R"))}},[[0,1]]]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/polyfills.f31db31652a3fd9f4bca.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/polyfills.f31db31652a3fd9f4bca.js
new file mode 100644
index 00000000..6b77d727
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/polyfills.f31db31652a3fd9f4bca.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{"+auO":function(t,e,n){var r=n("XKFU"),o=n("lvtm");r(r.S,"Math",{cbrt:function(t){return o(t=+t)*Math.pow(Math.abs(t),1/3)}})},"+lvF":function(t,e,n){t.exports=n("VTer")("native-function-to-string",Function.toString)},"+oPb":function(t,e,n){"use strict";n("OGtf")("blink",function(t){return function(){return t(this,"blink","","")}})},"+rLv":function(t,e,n){var r=n("dyZX").document;t.exports=r&&r.documentElement},"/8Fb":function(t,e,n){var r=n("XKFU"),o=n("UExd")(!0);r(r.S,"Object",{entries:function(t){return o(t)}})},"/KAi":function(t,e,n){var r=n("XKFU"),o=n("dyZX").isFinite;r(r.S,"Number",{isFinite:function(t){return"number"==typeof t&&o(t)}})},"/SS/":function(t,e,n){var r=n("XKFU");r(r.S,"Object",{setPrototypeOf:n("i5dc").set})},"/e88":function(t,e){t.exports="\t\n\v\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff"},"/uf1":function(t,e,n){"use strict";var r=n("XKFU"),o=n("S/j/"),i=n("2OiF"),a=n("hswa");n("nh4g")&&r(r.P+n("xbSm"),"Object",{__defineSetter__:function(t,e){a.f(o(this),t,{set:i(e),enumerable:!0,configurable:!0})}})},"0/R4":function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},"0E+W":function(t,e,n){n("elZq")("Array")},"0LDn":function(t,e,n){"use strict";n("OGtf")("italics",function(t){return function(){return t(this,"i","","")}})},"0TWp":function(t,e,n){!function(){"use strict";!function(t){var e=t.performance;function n(t){e&&e.mark&&e.mark(t)}function r(t,n){e&&e.measure&&e.measure(t,n)}n("Zone");var o=!0===t.__zone_symbol__forceDuplicateZoneCheck;if(t.Zone){if(o||"function"!=typeof t.Zone.__symbol__)throw new Error("Zone already loaded.");return t.Zone}var i,a=function(){function e(t,e){this._parent=t,this._name=e?e.name||"unnamed":"<root>",this._properties=e&&e.properties||{},this._zoneDelegate=new c(this,this._parent&&this._parent._zoneDelegate,e)}return e.assertZonePatched=function(){if(t.Promise!==F.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(e,"root",{get:function(){for(var t=e.current;t.parent;)t=t.parent;return t},enumerable:!0,configurable:!0}),Object.defineProperty(e,"current",{get:function(){return P.zone},enumerable:!0,configurable:!0}),Object.defineProperty(e,"currentTask",{get:function(){return j},enumerable:!0,configurable:!0}),e.__load_patch=function(i,a){if(F.hasOwnProperty(i)){if(o)throw Error("Already loaded patch: "+i)}else if(!t["__Zone_disable_"+i]){var u="Zone:"+i;n(u),F[i]=a(t,e,O),r(u,u)}},Object.defineProperty(e.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),e.prototype.get=function(t){var e=this.getZoneWith(t);if(e)return e._properties[t]},e.prototype.getZoneWith=function(t){for(var e=this;e;){if(e._properties.hasOwnProperty(t))return e;e=e._parent}return null},e.prototype.fork=function(t){if(!t)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,t)},e.prototype.wrap=function(t,e){if("function"!=typeof t)throw new Error("Expecting function got: "+t);var n=this._zoneDelegate.intercept(this,t,e),r=this;return function(){return r.runGuarded(n,this,arguments,e)}},e.prototype.run=function(t,e,n,r){P={parent:P,zone:this};try{return this._zoneDelegate.invoke(this,t,e,n,r)}finally{P=P.parent}},e.prototype.runGuarded=function(t,e,n,r){void 0===e&&(e=null),P={parent:P,zone:this};try{try{return this._zoneDelegate.invoke(this,t,e,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{P=P.parent}},e.prototype.runTask=function(t,e,n){if(t.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(t.zone||y).name+"; Execution: "+this.name+")");if(t.state!==m||t.type!==E&&t.type!==T){var r=t.state!=k;r&&t._transitionTo(k,_),t.runCount++;var o=j;j=t,P={parent:P,zone:this};try{t.type==T&&t.data&&!t.data.isPeriodic&&(t.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,t,e,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{t.state!==m&&t.state!==x&&(t.type==E||t.data&&t.data.isPeriodic?r&&t._transitionTo(_,k):(t.runCount=0,this._updateTaskCount(t,-1),r&&t._transitionTo(m,k,m))),P=P.parent,j=o}}},e.prototype.scheduleTask=function(t){if(t.zone&&t.zone!==this)for(var e=this;e;){if(e===t.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+t.zone.name);e=e.parent}t._transitionTo(b,m);var n=[];t._zoneDelegates=n,t._zone=this;try{t=this._zoneDelegate.scheduleTask(this,t)}catch(r){throw t._transitionTo(x,b,m),this._zoneDelegate.handleError(this,r),r}return t._zoneDelegates===n&&this._updateTaskCount(t,1),t.state==b&&t._transitionTo(_,b),t},e.prototype.scheduleMicroTask=function(t,e,n,r){return this.scheduleTask(new s(w,t,e,n,r,void 0))},e.prototype.scheduleMacroTask=function(t,e,n,r,o){return this.scheduleTask(new s(T,t,e,n,r,o))},e.prototype.scheduleEventTask=function(t,e,n,r,o){return this.scheduleTask(new s(E,t,e,n,r,o))},e.prototype.cancelTask=function(t){if(t.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(t.zone||y).name+"; Execution: "+this.name+")");t._transitionTo(S,_,k);try{this._zoneDelegate.cancelTask(this,t)}catch(e){throw t._transitionTo(x,S),this._zoneDelegate.handleError(this,e),e}return this._updateTaskCount(t,-1),t._transitionTo(m,S),t.runCount=0,t},e.prototype._updateTaskCount=function(t,e){var n=t._zoneDelegates;-1==e&&(t._zoneDelegates=null);for(var r=0;r<n.length;r++)n[r]._updateTaskCount(t.type,e)},e.__symbol__=I,e}(),u={name:"",onHasTask:function(t,e,n,r){return t.hasTask(n,r)},onScheduleTask:function(t,e,n,r){return t.scheduleTask(n,r)},onInvokeTask:function(t,e,n,r,o,i){return t.invokeTask(n,r,o,i)},onCancelTask:function(t,e,n,r){return t.cancelTask(n,r)}},c=function(){function t(t,e,n){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=t,this._parentDelegate=e,this._forkZS=n&&(n&&n.onFork?n:e._forkZS),this._forkDlgt=n&&(n.onFork?e:e._forkDlgt),this._forkCurrZone=n&&(n.onFork?this.zone:e.zone),this._interceptZS=n&&(n.onIntercept?n:e._interceptZS),this._interceptDlgt=n&&(n.onIntercept?e:e._interceptDlgt),this._interceptCurrZone=n&&(n.onIntercept?this.zone:e.zone),this._invokeZS=n&&(n.onInvoke?n:e._invokeZS),this._invokeDlgt=n&&(n.onInvoke?e:e._invokeDlgt),this._invokeCurrZone=n&&(n.onInvoke?this.zone:e.zone),this._handleErrorZS=n&&(n.onHandleError?n:e._handleErrorZS),this._handleErrorDlgt=n&&(n.onHandleError?e:e._handleErrorDlgt),this._handleErrorCurrZone=n&&(n.onHandleError?this.zone:e.zone),this._scheduleTaskZS=n&&(n.onScheduleTask?n:e._scheduleTaskZS),this._scheduleTaskDlgt=n&&(n.onScheduleTask?e:e._scheduleTaskDlgt),this._scheduleTaskCurrZone=n&&(n.onScheduleTask?this.zone:e.zone),this._invokeTaskZS=n&&(n.onInvokeTask?n:e._invokeTaskZS),this._invokeTaskDlgt=n&&(n.onInvokeTask?e:e._invokeTaskDlgt),this._invokeTaskCurrZone=n&&(n.onInvokeTask?this.zone:e.zone),this._cancelTaskZS=n&&(n.onCancelTask?n:e._cancelTaskZS),this._cancelTaskDlgt=n&&(n.onCancelTask?e:e._cancelTaskDlgt),this._cancelTaskCurrZone=n&&(n.onCancelTask?this.zone:e.zone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;var r=n&&n.onHasTask;(r||e&&e._hasTaskZS)&&(this._hasTaskZS=r?n:u,this._hasTaskDlgt=e,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=t,n.onScheduleTask||(this._scheduleTaskZS=u,this._scheduleTaskDlgt=e,this._scheduleTaskCurrZone=this.zone),n.onInvokeTask||(this._invokeTaskZS=u,this._invokeTaskDlgt=e,this._invokeTaskCurrZone=this.zone),n.onCancelTask||(this._cancelTaskZS=u,this._cancelTaskDlgt=e,this._cancelTaskCurrZone=this.zone))}return t.prototype.fork=function(t,e){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,t,e):new a(t,e)},t.prototype.intercept=function(t,e,n){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,t,e,n):e},t.prototype.invoke=function(t,e,n,r,o){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,t,e,n,r,o):e.apply(n,r)},t.prototype.handleError=function(t,e){return!this._handleErrorZS||this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,t,e)},t.prototype.scheduleTask=function(t,e){var n=e;if(this._scheduleTaskZS)this._hasTaskZS&&n._zoneDelegates.push(this._hasTaskDlgtOwner),(n=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,t,e))||(n=e);else if(e.scheduleFn)e.scheduleFn(e);else{if(e.type!=w)throw new Error("Task is missing scheduleFn.");d(e)}return n},t.prototype.invokeTask=function(t,e,n,r){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,t,e,n,r):e.callback.apply(n,r)},t.prototype.cancelTask=function(t,e){var n;if(this._cancelTaskZS)n=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,t,e);else{if(!e.cancelFn)throw Error("Task is not cancelable");n=e.cancelFn(e)}return n},t.prototype.hasTask=function(t,e){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,t,e)}catch(n){this.handleError(t,n)}},t.prototype._updateTaskCount=function(t,e){var n=this._taskCounts,r=n[t],o=n[t]=r+e;if(o<0)throw new Error("More tasks executed then were scheduled.");0!=r&&0!=o||this.hasTask(this.zone,{microTask:n.microTask>0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:t})},t}(),s=function(){function e(n,r,o,i,a,u){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=i,this.scheduleFn=a,this.cancelFn=u,this.callback=o;var c=this;this.invoke=n===E&&i&&i.useG?e.invokeTask:function(){return e.invokeTask.call(t,c,this,arguments)}}return e.invokeTask=function(t,e,n){t||(t=this),M++;try{return t.runCount++,t.zone.runTask(t,e,n)}finally{1==M&&g(),M--}},Object.defineProperty(e.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),e.prototype.cancelScheduleRequest=function(){this._transitionTo(m,b)},e.prototype._transitionTo=function(t,e,n){if(this._state!==e&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+t+"', expecting state '"+e+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=t,t==m&&(this._zoneDelegates=null)},e.prototype.toString=function(){return this.data&&void 0!==this.data.handleId?this.data.handleId.toString():Object.prototype.toString.call(this)},e.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},e}(),f=I("setTimeout"),l=I("Promise"),h=I("then"),p=[],v=!1;function d(e){if(0===M&&0===p.length)if(i||t[l]&&(i=t[l].resolve(0)),i){var n=i[h];n||(n=i.then),n.call(i,g)}else t[f](g,0);e&&p.push(e)}function g(){if(!v){for(v=!0;p.length;){var t=p;p=[];for(var e=0;e<t.length;e++){var n=t[e];try{n.zone.runTask(n,null,null)}catch(r){O.onUnhandledError(r)}}}O.microtaskDrainDone(),v=!1}}var y={name:"NO ZONE"},m="notScheduled",b="scheduling",_="scheduled",k="running",S="canceling",x="unknown",w="microTask",T="macroTask",E="eventTask",F={},O={symbol:I,currentZoneFrame:function(){return P},onUnhandledError:D,microtaskDrainDone:D,scheduleMicroTask:d,showUncaughtError:function(){return!a[I("ignoreConsoleErrorUncaughtError")]},patchEventTarget:function(){return[]},patchOnProperties:D,patchMethod:function(){return D},bindArguments:function(){return[]},patchThen:function(){return D},setNativePromise:function(t){t&&"function"==typeof t.resolve&&(i=t.resolve(0))}},P={parent:null,zone:new a(null,null)},j=null,M=0;function D(){}function I(t){return"__zone_symbol__"+t}r("Zone","Zone"),t.Zone=a}("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global);var t=function(t){var e="function"==typeof Symbol&&t[Symbol.iterator],n=0;return e?e.call(t):{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}}};Zone.__load_patch("ZoneAwarePromise",function(e,n,r){var o=Object.getOwnPropertyDescriptor,i=Object.defineProperty,a=r.symbol,u=[],c=a("Promise"),s=a("then"),f="__creationTrace__";r.onUnhandledError=function(t){if(r.showUncaughtError()){var e=t&&t.rejection;e?console.error("Unhandled Promise rejection:",e instanceof Error?e.message:e,"; Zone:",t.zone.name,"; Task:",t.task&&t.task.source,"; Value:",e,e instanceof Error?e.stack:void 0):console.error(t)}},r.microtaskDrainDone=function(){for(;u.length;)for(var t=function(){var t=u.shift();try{t.zone.runGuarded(function(){throw t})}catch(e){h(e)}};u.length;)t()};var l=a("unhandledPromiseRejectionHandler");function h(t){r.onUnhandledError(t);try{var e=n[l];e&&"function"==typeof e&&e.call(this,t)}catch(o){}}function p(t){return t&&t.then}function v(t){return t}function d(t){return A.reject(t)}var g=a("state"),y=a("value"),m=a("finally"),b=a("parentPromiseValue"),_=a("parentPromiseState"),k="Promise.then",S=null,x=!0,w=!1,T=0;function E(t,e){return function(n){try{j(t,e,n)}catch(r){j(t,!1,r)}}}var F=function(){var t=!1;return function(e){return function(){t||(t=!0,e.apply(null,arguments))}}},O="Promise resolved with itself",P=a("currentTaskTrace");function j(t,e,o){var a,c=F();if(t===o)throw new TypeError(O);if(t[g]===S){var s=null;try{"object"!=typeof o&&"function"!=typeof o||(s=o&&o.then)}catch(d){return c(function(){j(t,!1,d)})(),t}if(e!==w&&o instanceof A&&o.hasOwnProperty(g)&&o.hasOwnProperty(y)&&o[g]!==S)D(o),j(t,o[g],o[y]);else if(e!==w&&"function"==typeof s)try{s.call(o,c(E(t,e)),c(E(t,!1)))}catch(d){c(function(){j(t,!1,d)})()}else{t[g]=e;var l=t[y];if(t[y]=o,t[m]===m&&e===x&&(t[g]=t[_],t[y]=t[b]),e===w&&o instanceof Error){var h=n.currentTask&&n.currentTask.data&&n.currentTask.data[f];h&&i(o,P,{configurable:!0,enumerable:!1,writable:!0,value:h})}for(var p=0;p<l.length;)I(t,l[p++],l[p++],l[p++],l[p++]);if(0==l.length&&e==w){t[g]=T;try{throw new Error("Uncaught (in promise): "+((a=o)&&a.toString===Object.prototype.toString?(a.constructor&&a.constructor.name||"")+": "+JSON.stringify(a):a?a.toString():Object.prototype.toString.call(a))+(o&&o.stack?"\n"+o.stack:""))}catch(d){var v=d;v.rejection=o,v.promise=t,v.zone=n.current,v.task=n.currentTask,u.push(v),r.scheduleMicroTask()}}}}return t}var M=a("rejectionHandledHandler");function D(t){if(t[g]===T){try{var e=n[M];e&&"function"==typeof e&&e.call(this,{rejection:t[y],promise:t})}catch(o){}t[g]=w;for(var r=0;r<u.length;r++)t===u[r].promise&&u.splice(r,1)}}function I(t,e,n,r,o){D(t);var i=t[g],a=i?"function"==typeof r?r:v:"function"==typeof o?o:d;e.scheduleMicroTask(k,function(){try{var r=t[y],o=n&&m===n[m];o&&(n[b]=r,n[_]=i);var u=e.run(a,void 0,o&&a!==d&&a!==v?[]:[r]);j(n,!0,u)}catch(c){j(n,!1,c)}},n)}var A=function(){function e(t){if(!(this instanceof e))throw new Error("Must be an instanceof Promise.");this[g]=S,this[y]=[];try{t&&t(E(this,x),E(this,w))}catch(n){j(this,!1,n)}}return e.toString=function(){return"function ZoneAwarePromise() { [native code] }"},e.resolve=function(t){return j(new this(null),x,t)},e.reject=function(t){return j(new this(null),w,t)},e.race=function(e){var n,r,o,i,a=new this(function(t,e){o=t,i=e});function u(t){a&&(a=o(t))}function c(t){a&&(a=i(t))}try{for(var s=t(e),f=s.next();!f.done;f=s.next()){var l=f.value;p(l)||(l=this.resolve(l)),l.then(u,c)}}catch(h){n={error:h}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(n)throw n.error}}return a},e.all=function(e){var n,r,o,i,a=new this(function(t,e){o=t,i=e}),u=2,c=0,s=[],f=function(t){p(t)||(t=l.resolve(t));var e=c;t.then(function(t){s[e]=t,0==--u&&o(s)},i),u++,c++},l=this;try{for(var h=t(e),v=h.next();!v.done;v=h.next())f(v.value)}catch(d){n={error:d}}finally{try{v&&!v.done&&(r=h.return)&&r.call(h)}finally{if(n)throw n.error}}return 0==(u-=2)&&o(s),a},e.prototype.then=function(t,e){var r=new this.constructor(null),o=n.current;return this[g]==S?this[y].push(o,r,t,e):I(this,o,r,t,e),r},e.prototype.catch=function(t){return this.then(null,t)},e.prototype.finally=function(t){var e=new this.constructor(null);e[m]=m;var r=n.current;return this[g]==S?this[y].push(r,e,t,t):I(this,r,e,t,t),e},e}();A.resolve=A.resolve,A.reject=A.reject,A.race=A.race,A.all=A.all;var U=e[c]=e.Promise,X=n.__symbol__("ZoneAwarePromise"),Z=o(e,"Promise");Z&&!Z.configurable||(Z&&delete Z.writable,Z&&delete Z.value,Z||(Z={configurable:!0,enumerable:!0}),Z.get=function(){return e[X]?e[X]:e[c]},Z.set=function(t){t===A?e[X]=t:(e[c]=t,t.prototype[s]||C(t),r.setNativePromise(t))},i(e,"Promise",Z)),e.Promise=A;var K=a("thenPatched");function C(t){var e=t.prototype,n=o(e,"then");if(!n||!1!==n.writable&&n.configurable){var r=e.then;e[s]=r,t.prototype.then=function(t,e){var n=this;return new A(function(t,e){r.call(n,t,e)}).then(t,e)},t[K]=!0}}return r.patchThen=C,U&&C(U),Promise[n.__symbol__("uncaughtPromiseErrors")]=u,A}),Zone.__load_patch("fetch",function(t,e,n){var r=t.fetch,o=t.Promise,i=n.symbol("thenPatched"),a=n.symbol("fetchTaskScheduling"),u=n.symbol("fetchTaskAborting");if("function"==typeof r){var c=t.AbortController,s="function"==typeof c,f=null;s&&(t.AbortController=function(){var t=new c;return t.signal.abortController=t,t},f=n.patchMethod(c.prototype,"abort",function(t){return function(e,n){return e.task?e.task.zone.cancelTask(e.task):t.apply(e,n)}}));var l=function(){};t.fetch=function(){var t=this,c=Array.prototype.slice.call(arguments),h=c.length>1?c[1]:null,p=h&&h.signal;return new Promise(function(h,v){var d=e.current.scheduleMacroTask("fetch",l,c,function(){var u,s=e.current;try{s[a]=!0,u=r.apply(t,c)}catch(l){return void v(l)}finally{s[a]=!1}if(!(u instanceof o)){var f=u.constructor;f[i]||n.patchThen(f)}u.then(function(t){"notScheduled"!==d.state&&d.invoke(),h(t)},function(t){"notScheduled"!==d.state&&d.invoke(),v(t)})},function(){if(s)if(p&&p.abortController&&!p.aborted&&"function"==typeof p.abortController.abort&&f)try{e.current[u]=!0,f.call(p.abortController)}finally{e.current[u]=!1}else v("cancel fetch need a AbortController.signal");else v("No AbortController supported, can not cancel fetch")});p&&p.abortController&&(p.abortController.task=d)})}}});var e=Object.getOwnPropertyDescriptor,n=Object.defineProperty,r=Object.getPrototypeOf,o=Object.create,i=Array.prototype.slice,a="addEventListener",u="removeEventListener",c=Zone.__symbol__(a),s=Zone.__symbol__(u),f="true",l="false",h="__zone_symbol__";function p(t,e){return Zone.current.wrap(t,e)}function v(t,e,n,r,o){return Zone.current.scheduleMacroTask(t,e,n,r,o)}var d=Zone.__symbol__,g="undefined"!=typeof window,y=g?window:void 0,m=g&&y||"object"==typeof self&&self||global,b="removeAttribute",_=[null];function k(t,e){for(var n=t.length-1;n>=0;n--)"function"==typeof t[n]&&(t[n]=p(t[n],e+"_"+n));return t}function S(t){return!t||!1!==t.writable&&!("function"==typeof t.get&&void 0===t.set)}var x="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,w=!("nw"in m)&&void 0!==m.process&&"[object process]"==={}.toString.call(m.process),T=!w&&!x&&!(!g||!y.HTMLElement),E=void 0!==m.process&&"[object process]"==={}.toString.call(m.process)&&!x&&!(!g||!y.HTMLElement),F={},O=function(t){if(t=t||m.event){var e=F[t.type];e||(e=F[t.type]=d("ON_PROPERTY"+t.type));var n,r=this||t.target||m,o=r[e];return T&&r===y&&"error"===t.type?!0===(n=o&&o.call(this,t.message,t.filename,t.lineno,t.colno,t.error))&&t.preventDefault():null==(n=o&&o.apply(this,arguments))||n||t.preventDefault(),n}};function P(t,r,o){var i=e(t,r);if(!i&&o&&e(o,r)&&(i={enumerable:!0,configurable:!0}),i&&i.configurable){var a=d("on"+r+"patched");if(!t.hasOwnProperty(a)||!t[a]){delete i.writable,delete i.value;var u=i.get,c=i.set,s=r.substr(2),f=F[s];f||(f=F[s]=d("ON_PROPERTY"+s)),i.set=function(e){var n=this;n||t!==m||(n=m),n&&(n[f]&&n.removeEventListener(s,O),c&&c.apply(n,_),"function"==typeof e?(n[f]=e,n.addEventListener(s,O,!1)):n[f]=null)},i.get=function(){var e=this;if(e||t!==m||(e=m),!e)return null;var n=e[f];if(n)return n;if(u){var o=u&&u.call(this);if(o)return i.set.call(this,o),"function"==typeof e[b]&&e.removeAttribute(r),o}return null},n(t,r,i),t[a]=!0}}}function j(t,e,n){if(e)for(var r=0;r<e.length;r++)P(t,"on"+e[r],n);else{var o=[];for(var i in t)"on"==i.substr(0,2)&&o.push(i);for(var a=0;a<o.length;a++)P(t,o[a],n)}}var M=d("originalInstance");function D(t){var e=m[t];if(e){m[d(t)]=e,m[t]=function(){var n=k(arguments,t);switch(n.length){case 0:this[M]=new e;break;case 1:this[M]=new e(n[0]);break;case 2:this[M]=new e(n[0],n[1]);break;case 3:this[M]=new e(n[0],n[1],n[2]);break;case 4:this[M]=new e(n[0],n[1],n[2],n[3]);break;default:throw new Error("Arg list too long.")}},U(m[t],e);var r,o=new e(function(){});for(r in o)"XMLHttpRequest"===t&&"responseBlob"===r||function(e){"function"==typeof o[e]?m[t].prototype[e]=function(){return this[M][e].apply(this[M],arguments)}:n(m[t].prototype,e,{set:function(n){"function"==typeof n?(this[M][e]=p(n,t+"."+e),U(this[M][e],n)):this[M][e]=n},get:function(){return this[M][e]}})}(r);for(r in e)"prototype"!==r&&e.hasOwnProperty(r)&&(m[t][r]=e[r])}}var I=!1;function A(t,n,o){for(var i=t;i&&!i.hasOwnProperty(n);)i=r(i);!i&&t[n]&&(i=t);var a,u,c=d(n),s=null;if(i&&!(s=i[c])&&(s=i[c]=i[n],S(i&&e(i,n)))){var f=o(s,c,n);i[n]=function(){return f(this,arguments)},U(i[n],s),I&&(a=s,u=i[n],"function"==typeof Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(a).forEach(function(t){var e=Object.getOwnPropertyDescriptor(a,t);Object.defineProperty(u,t,{get:function(){return a[t]},set:function(n){(!e||e.writable&&"function"==typeof e.set)&&(a[t]=n)},enumerable:!e||e.enumerable,configurable:!e||e.configurable})}))}return s}function U(t,e){t[d("OriginalDelegate")]=e}var X=!1,Z=!1;function K(){try{var t=y.navigator.userAgent;if(-1!==t.indexOf("MSIE ")||-1!==t.indexOf("Trident/"))return!0}catch(e){}return!1}function C(){if(X)return Z;X=!0;try{var t=y.navigator.userAgent;return-1===t.indexOf("MSIE ")&&-1===t.indexOf("Trident/")&&-1===t.indexOf("Edge/")||(Z=!0),Z}catch(e){}}Zone.__load_patch("toString",function(t){var e=Function.prototype.toString,n=d("OriginalDelegate"),r=d("Promise"),o=d("Error"),i=function(){if("function"==typeof this){var i=this[n];if(i)return"function"==typeof i?e.apply(this[n],arguments):Object.prototype.toString.call(i);if(this===Promise){var a=t[r];if(a)return e.apply(a,arguments)}if(this===Error){var u=t[o];if(u)return e.apply(u,arguments)}}return e.apply(this,arguments)};i[n]=e,Function.prototype.toString=i;var a=Object.prototype.toString;Object.prototype.toString=function(){return this instanceof Promise?"[object Promise]":a.apply(this,arguments)}});var L=!1;if("undefined"!=typeof window)try{var R=Object.defineProperty({},"passive",{get:function(){L=!0}});window.addEventListener("test",R,R),window.removeEventListener("test",R,R)}catch(mt){L=!1}var z={useG:!0},N={},q={},V=/^__zone_symbol__(\w+)(true|false)$/,G="__zone_symbol__propagationStopped";function H(t,e,n){var o=n&&n.add||a,i=n&&n.rm||u,c=n&&n.listeners||"eventListeners",s=n&&n.rmAll||"removeAllListeners",p=d(o),v="."+o+":",g="prependListener",y="."+g+":",m=function(t,e,n){if(!t.isRemoved){var r=t.callback;"object"==typeof r&&r.handleEvent&&(t.callback=function(t){return r.handleEvent(t)},t.originalDelegate=r),t.invoke(t,e,[n]);var o=t.options;o&&"object"==typeof o&&o.once&&e[i].call(e,n.type,t.originalDelegate?t.originalDelegate:t.callback,o)}},b=function(e){if(e=e||t.event){var n=this||e.target||t,r=n[N[e.type][l]];if(r)if(1===r.length)m(r[0],n,e);else for(var o=r.slice(),i=0;i<o.length&&(!e||!0!==e[G]);i++)m(o[i],n,e)}},_=function(e){if(e=e||t.event){var n=this||e.target||t,r=n[N[e.type][f]];if(r)if(1===r.length)m(r[0],n,e);else for(var o=r.slice(),i=0;i<o.length&&(!e||!0!==e[G]);i++)m(o[i],n,e)}};function k(e,n){if(!e)return!1;var a=!0;n&&void 0!==n.useG&&(a=n.useG);var u=n&&n.vh,m=!0;n&&void 0!==n.chkDup&&(m=n.chkDup);var k=!1;n&&void 0!==n.rt&&(k=n.rt);for(var S=e;S&&!S.hasOwnProperty(o);)S=r(S);if(!S&&e[o]&&(S=e),!S)return!1;if(S[p])return!1;var x,T=n&&n.eventNameToString,E={},F=S[p]=S[o],O=S[d(i)]=S[i],P=S[d(c)]=S[c],j=S[d(s)]=S[s];function M(t){L||"boolean"==typeof E.options||null==E.options||(t.options=!!E.options.capture,E.options=t.options)}n&&n.prepend&&(x=S[d(n.prepend)]=S[n.prepend]);var D=a?function(t){if(!E.isExisting)return M(t),F.call(E.target,E.eventName,E.capture?_:b,E.options)}:function(t){return M(t),F.call(E.target,E.eventName,t.invoke,E.options)},I=a?function(t){if(!t.isRemoved){var e=N[t.eventName],n=void 0;e&&(n=e[t.capture?f:l]);var r=n&&t.target[n];if(r)for(var o=0;o<r.length;o++)if(r[o]===t){r.splice(o,1),t.isRemoved=!0,0===r.length&&(t.allRemoved=!0,t.target[n]=null);break}}if(t.allRemoved)return O.call(t.target,t.eventName,t.capture?_:b,t.options)}:function(t){return O.call(t.target,t.eventName,t.invoke,t.options)},A=n&&n.diff?n.diff:function(t,e){var n=typeof e;return"function"===n&&t.callback===e||"object"===n&&t.originalDelegate===e},X=Zone[Zone.__symbol__("BLACK_LISTED_EVENTS")],Z=function(e,n,r,o,i,c){return void 0===i&&(i=!1),void 0===c&&(c=!1),function(){var s=this||t,p=arguments[0],v=arguments[1];if(!v)return e.apply(this,arguments);if(w&&"uncaughtException"===p)return e.apply(this,arguments);var d=!1;if("function"!=typeof v){if(!v.handleEvent)return e.apply(this,arguments);d=!0}if(!u||u(e,v,s,arguments)){var g,y=arguments[2];if(X)for(var b=0;b<X.length;b++)if(p===X[b])return e.apply(this,arguments);var _=!1;void 0===y?g=!1:!0===y?g=!0:!1===y?g=!1:(g=!!y&&!!y.capture,_=!!y&&!!y.once);var k,S=Zone.current,x=N[p];if(x)k=x[g?f:l];else{var F=(T?T(p):p)+l,O=(T?T(p):p)+f,P=h+F,j=h+O;N[p]={},N[p][l]=P,N[p][f]=j,k=g?j:P}var M,D=s[k],I=!1;if(D){if(I=!0,m)for(b=0;b<D.length;b++)if(A(D[b],v))return}else D=s[k]=[];var U=s.constructor.name,Z=q[U];Z&&(M=Z[p]),M||(M=U+n+(T?T(p):p)),E.options=y,_&&(E.options.once=!1),E.target=s,E.capture=g,E.eventName=p,E.isExisting=I;var K=a?z:void 0;K&&(K.taskData=E);var C=S.scheduleEventTask(M,v,K,r,o);return E.target=null,K&&(K.taskData=null),_&&(y.once=!0),(L||"boolean"!=typeof C.options)&&(C.options=y),C.target=s,C.capture=g,C.eventName=p,d&&(C.originalDelegate=v),c?D.unshift(C):D.push(C),i?s:void 0}}};return S[o]=Z(F,v,D,I,k),x&&(S[g]=Z(x,y,function(t){return x.call(E.target,E.eventName,t.invoke,E.options)},I,k,!0)),S[i]=function(){var e,n=this||t,r=arguments[0],o=arguments[2];e=void 0!==o&&(!0===o||!1!==o&&!!o&&!!o.capture);var i=arguments[1];if(!i)return O.apply(this,arguments);if(!u||u(O,i,n,arguments)){var a,c=N[r];c&&(a=c[e?f:l]);var s=a&&n[a];if(s)for(var h=0;h<s.length;h++){var p=s[h];if(A(p,i))return s.splice(h,1),p.isRemoved=!0,0===s.length&&(p.allRemoved=!0,n[a]=null),p.zone.cancelTask(p),k?n:void 0}return O.apply(this,arguments)}},S[c]=function(){for(var e=arguments[0],n=[],r=W(this||t,T?T(e):e),o=0;o<r.length;o++){var i=r[o];n.push(i.originalDelegate?i.originalDelegate:i.callback)}return n},S[s]=function(){var e=this||t,n=arguments[0];if(n){var r=N[n];if(r){var o=e[r[l]],a=e[r[f]];if(o){var u=o.slice();for(p=0;p<u.length;p++)this[i].call(this,n,(c=u[p]).originalDelegate?c.originalDelegate:c.callback,c.options)}if(a)for(u=a.slice(),p=0;p<u.length;p++){var c;this[i].call(this,n,(c=u[p]).originalDelegate?c.originalDelegate:c.callback,c.options)}}}else{for(var h=Object.keys(e),p=0;p<h.length;p++){var v=V.exec(h[p]),d=v&&v[1];d&&"removeListener"!==d&&this[s].call(this,d)}this[s].call(this,"removeListener")}if(k)return this},U(S[o],F),U(S[i],O),j&&U(S[s],j),P&&U(S[c],P),!0}for(var S=[],x=0;x<e.length;x++)S[x]=k(e[x],n);return S}function W(t,e){var n=[];for(var r in t){var o=V.exec(r),i=o&&o[1];if(i&&(!e||i===e)){var a=t[r];if(a)for(var u=0;u<a.length;u++)n.push(a[u])}}return n}var Y=d("zoneTask");function B(t,e,n,r){var o=null,i=null;n+=r;var a={};function u(e){var n=e.data;return n.args[0]=function(){try{e.invoke.apply(this,arguments)}finally{e.data&&e.data.isPeriodic||("number"==typeof n.handleId?delete a[n.handleId]:n.handleId&&(n.handleId[Y]=null))}},n.handleId=o.apply(t,n.args),e}function c(t){return i(t.data.handleId)}o=A(t,e+=r,function(n){return function(o,i){if("function"==typeof i[0]){var s=v(e,i[0],{isPeriodic:"Interval"===r,delay:"Timeout"===r||"Interval"===r?i[1]||0:void 0,args:i},u,c);if(!s)return s;var f=s.data.handleId;return"number"==typeof f?a[f]=s:f&&(f[Y]=s),f&&f.ref&&f.unref&&"function"==typeof f.ref&&"function"==typeof f.unref&&(s.ref=f.ref.bind(f),s.unref=f.unref.bind(f)),"number"==typeof f||f?f:s}return n.apply(t,i)}}),i=A(t,n,function(e){return function(n,r){var o,i=r[0];"number"==typeof i?o=a[i]:(o=i&&i[Y])||(o=i),o&&"string"==typeof o.type?"notScheduled"!==o.state&&(o.cancelFn&&o.data.isPeriodic||0===o.runCount)&&("number"==typeof i?delete a[i]:i&&(i[Y]=null),o.zone.cancelTask(o)):e.apply(t,r)}})}var J=Object[d("defineProperty")]=Object.defineProperty,Q=Object[d("getOwnPropertyDescriptor")]=Object.getOwnPropertyDescriptor,$=Object.create,tt=d("unconfigurables");function et(t,e){return t&&t[tt]&&t[tt][e]}function nt(t,e,n){return Object.isFrozen(n)||(n.configurable=!0),n.configurable||(t[tt]||Object.isFrozen(t)||J(t,tt,{writable:!0,value:{}}),t[tt]&&(t[tt][e]=!0)),n}function rt(t,e,n,r){try{return J(t,e,n)}catch(i){if(!n.configurable)throw i;void 0===r?delete n.configurable:n.configurable=r;try{return J(t,e,n)}catch(i){var o=null;try{o=JSON.stringify(n)}catch(i){o=n.toString()}console.log("Attempting to configure '"+e+"' with descriptor '"+o+"' on object '"+t+"' and got error, giving up: "+i)}}}var ot=["absolutedeviceorientation","afterinput","afterprint","appinstalled","beforeinstallprompt","beforeprint","beforeunload","devicelight","devicemotion","deviceorientation","deviceorientationabsolute","deviceproximity","hashchange","languagechange","message","mozbeforepaint","offline","online","paint","pageshow","pagehide","popstate","rejectionhandled","storage","unhandledrejection","unload","userproximity","vrdisplyconnected","vrdisplaydisconnected","vrdisplaypresentchange"],it=["encrypted","waitingforkey","msneedkey","mozinterruptbegin","mozinterruptend"],at=["load"],ut=["blur","error","focus","load","resize","scroll","messageerror"],ct=["bounce","finish","start"],st=["loadstart","progress","abort","error","load","progress","timeout","loadend","readystatechange"],ft=["upgradeneeded","complete","abort","success","error","blocked","versionchange","close"],lt=["close","error","open","message"],ht=["error","message"],pt=["abort","animationcancel","animationend","animationiteration","auxclick","beforeinput","blur","cancel","canplay","canplaythrough","change","compositionstart","compositionupdate","compositionend","cuechange","click","close","contextmenu","curechange","dblclick","drag","dragend","dragenter","dragexit","dragleave","dragover","drop","durationchange","emptied","ended","error","focus","focusin","focusout","gotpointercapture","input","invalid","keydown","keypress","keyup","load","loadstart","loadeddata","loadedmetadata","lostpointercapture","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","mousewheel","orientationchange","pause","play","playing","pointercancel","pointerdown","pointerenter","pointerleave","pointerlockchange","mozpointerlockchange","webkitpointerlockerchange","pointerlockerror","mozpointerlockerror","webkitpointerlockerror","pointermove","pointout","pointerover","pointerup","progress","ratechange","reset","resize","scroll","seeked","seeking","select","selectionchange","selectstart","show","sort","stalled","submit","suspend","timeupdate","volumechange","touchcancel","touchmove","touchstart","touchend","transitioncancel","transitionend","waiting","wheel"].concat(["webglcontextrestored","webglcontextlost","webglcontextcreationerror"],["autocomplete","autocompleteerror"],["toggle"],["afterscriptexecute","beforescriptexecute","DOMContentLoaded","freeze","fullscreenchange","mozfullscreenchange","webkitfullscreenchange","msfullscreenchange","fullscreenerror","mozfullscreenerror","webkitfullscreenerror","msfullscreenerror","readystatechange","visibilitychange","resume"],ot,["beforecopy","beforecut","beforepaste","copy","cut","paste","dragstart","loadend","animationstart","search","transitionrun","transitionstart","webkitanimationend","webkitanimationiteration","webkitanimationstart","webkittransitionend"],["activate","afterupdate","ariarequest","beforeactivate","beforedeactivate","beforeeditfocus","beforeupdate","cellchange","controlselect","dataavailable","datasetchanged","datasetcomplete","errorupdate","filterchange","layoutcomplete","losecapture","move","moveend","movestart","propertychange","resizeend","resizestart","rowenter","rowexit","rowsdelete","rowsinserted","command","compassneedscalibration","deactivate","help","mscontentzoom","msmanipulationstatechanged","msgesturechange","msgesturedoubletap","msgestureend","msgesturehold","msgesturestart","msgesturetap","msgotpointercapture","msinertiastart","mslostpointercapture","mspointercancel","mspointerdown","mspointerenter","mspointerhover","mspointerleave","mspointermove","mspointerout","mspointerover","mspointerup","pointerout","mssitemodejumplistitemremoved","msthumbnailclick","stop","storagecommit"]);function vt(t,e,n,r){t&&j(t,function(t,e,n){if(!n||0===n.length)return e;var r=n.filter(function(e){return e.target===t});if(!r||0===r.length)return e;var o=r[0].ignoreProperties;return e.filter(function(t){return-1===o.indexOf(t)})}(t,e,n),r)}function dt(t,c){if(!w||E){var s="undefined"!=typeof WebSocket;if(function(){if((T||E)&&!e(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var t=e(Element.prototype,"onclick");if(t&&!t.configurable)return!1}var r=XMLHttpRequest.prototype,o=e(r,"onreadystatechange");if(o){n(r,"onreadystatechange",{enumerable:!0,configurable:!0,get:function(){return!0}});var i=!!(u=new XMLHttpRequest).onreadystatechange;return n(r,"onreadystatechange",o||{}),i}var a=d("fake");n(r,"onreadystatechange",{enumerable:!0,configurable:!0,get:function(){return this[a]},set:function(t){this[a]=t}});var u,c=function(){};return(u=new XMLHttpRequest).onreadystatechange=c,i=u[a]===c,u.onreadystatechange=null,i}()){var f=c.__Zone_ignore_on_properties;if(T){var l=window,h=K?[{target:l,ignoreProperties:["error"]}]:[];vt(l,pt.concat(["messageerror"]),f?f.concat(h):f,r(l)),vt(Document.prototype,pt,f),void 0!==l.SVGElement&&vt(l.SVGElement.prototype,pt,f),vt(Element.prototype,pt,f),vt(HTMLElement.prototype,pt,f),vt(HTMLMediaElement.prototype,it,f),vt(HTMLFrameSetElement.prototype,ot.concat(ut),f),vt(HTMLBodyElement.prototype,ot.concat(ut),f),vt(HTMLFrameElement.prototype,at,f),vt(HTMLIFrameElement.prototype,at,f);var v=l.HTMLMarqueeElement;v&&vt(v.prototype,ct,f);var g=l.Worker;g&&vt(g.prototype,ht,f)}vt(XMLHttpRequest.prototype,st,f);var y=c.XMLHttpRequestEventTarget;y&&vt(y&&y.prototype,st,f),"undefined"!=typeof IDBIndex&&(vt(IDBIndex.prototype,ft,f),vt(IDBRequest.prototype,ft,f),vt(IDBOpenDBRequest.prototype,ft,f),vt(IDBDatabase.prototype,ft,f),vt(IDBTransaction.prototype,ft,f),vt(IDBCursor.prototype,ft,f)),s&&vt(WebSocket.prototype,lt,f)}else!function(){for(var t=function(t){var e=pt[t],n="on"+e;self.addEventListener(e,function(t){var e,r,o=t.target;for(r=o?o.constructor.name+"."+n:"unknown."+n;o;)o[n]&&!o[n][gt]&&((e=p(o[n],r))[gt]=o[n],o[n]=e),o=o.parentElement},!0)},e=0;e<pt.length;e++)t(e)}(),D("XMLHttpRequest"),s&&function(t,n){var r=n.WebSocket;n.EventTarget||H(n,[r.prototype]),n.WebSocket=function(t,n){var c,s,f=arguments.length>1?new r(t,n):new r(t),l=e(f,"onmessage");return l&&!1===l.configurable?(c=o(f),s=f,[a,u,"send","close"].forEach(function(t){c[t]=function(){var e=i.call(arguments);if(t===a||t===u){var n=e.length>0?e[0]:void 0;if(n){var r=Zone.__symbol__("ON_PROPERTY"+n);f[r]=c[r]}}return f[t].apply(f,e)}})):c=f,j(c,["close","error","message","open"],s),c};var c=n.WebSocket;for(var s in r)c[s]=r[s]}(0,c)}}var gt=d("unbound");function yt(t,n,r,o){var i=Zone.__symbol__(r);if(!t[i]){var a=t[i]=t[r];t[r]=function(i,u,c){return u&&u.prototype&&o.forEach(function(t){var o,i,a,c,s=n+"."+r+"::"+t,f=u.prototype;if(f.hasOwnProperty(t)){var l=e(f,t);l&&l.value?(l.value=p(l.value,s),c=(a=l).configurable,rt(o=u.prototype,i=t,a=nt(o,i,a),c)):f[t]&&(f[t]=p(f[t],s))}else f[t]&&(f[t]=p(f[t],s))}),a.call(t,i,u,c)},U(t[r],a)}}Zone.__load_patch("util",function(t,e,n){n.patchOnProperties=j,n.patchMethod=A,n.bindArguments=k}),Zone.__load_patch("timers",function(t){B(t,"set","clear","Timeout"),B(t,"set","clear","Interval"),B(t,"set","clear","Immediate")}),Zone.__load_patch("requestAnimationFrame",function(t){B(t,"request","cancel","AnimationFrame"),B(t,"mozRequest","mozCancel","AnimationFrame"),B(t,"webkitRequest","webkitCancel","AnimationFrame")}),Zone.__load_patch("blocking",function(t,e){for(var n=["alert","prompt","confirm"],r=0;r<n.length;r++)A(t,n[r],function(n,r,o){return function(r,i){return e.current.run(n,t,i,o)}})}),Zone.__load_patch("EventTarget",function(t,e,n){var r=e.__symbol__("BLACK_LISTED_EVENTS");t[r]&&(e[r]=t[r]),function(t,e){!function(t,e){var n=t.Event;n&&n.prototype&&e.patchMethod(n.prototype,"stopImmediatePropagation",function(t){return function(e,n){e[G]=!0,t&&t.apply(e,n)}})}(t,e)}(t,n),function(t,e){var n="Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video",r="ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket".split(","),o=[],i=t.wtf,a=n.split(",");i?o=a.map(function(t){return"HTML"+t+"Element"}).concat(r):t.EventTarget?o.push("EventTarget"):o=r;for(var u=t.__Zone_disable_IE_check||!1,c=t.__Zone_enable_cross_context_check||!1,s=C(),p="function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }",v=0;v<pt.length;v++){var d=h+((_=pt[v])+l),g=h+(_+f);N[_]={},N[_][l]=d,N[_][f]=g}for(v=0;v<n.length;v++)for(var y=a[v],m=q[y]={},b=0;b<pt.length;b++){var _;m[_=pt[b]]=y+".addEventListener:"+_}var k=[];for(v=0;v<o.length;v++){var S=t[o[v]];k.push(S&&S.prototype)}H(t,k,{vh:function(t,e,n,r){if(!u&&s){if(c)try{var o;if("[object FunctionWrapper]"===(o=e.toString())||o==p)return t.apply(n,r),!1}catch(i){return t.apply(n,r),!1}else if("[object FunctionWrapper]"===(o=e.toString())||o==p)return t.apply(n,r),!1}else if(c)try{e.toString()}catch(i){return t.apply(n,r),!1}return!0}}),e.patchEventTarget=H}(t,n);var o=t.XMLHttpRequestEventTarget;o&&o.prototype&&n.patchEventTarget(t,[o.prototype]),D("MutationObserver"),D("WebKitMutationObserver"),D("IntersectionObserver"),D("FileReader")}),Zone.__load_patch("on_property",function(t,e,n){dt(0,t),Object.defineProperty=function(t,e,n){if(et(t,e))throw new TypeError("Cannot assign to read only property '"+e+"' of "+t);var r=n.configurable;return"prototype"!==e&&(n=nt(t,e,n)),rt(t,e,n,r)},Object.defineProperties=function(t,e){return Object.keys(e).forEach(function(n){Object.defineProperty(t,n,e[n])}),t},Object.create=function(t,e){return"object"!=typeof e||Object.isFrozen(e)||Object.keys(e).forEach(function(n){e[n]=nt(t,n,e[n])}),$(t,e)},Object.getOwnPropertyDescriptor=function(t,e){var n=Q(t,e);return n&&et(t,e)&&(n.configurable=!1),n}}),Zone.__load_patch("customElements",function(t,e,n){(T||E)&&"registerElement"in t.document&&yt(document,"Document","registerElement",["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"]),(T||E)&&"customElements"in t&&yt(t.customElements,"customElements","define",["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback"])}),Zone.__load_patch("canvas",function(t){var e=t.HTMLCanvasElement;void 0!==e&&e.prototype&&e.prototype.toBlob&&function(t,n,r){var o=null;function i(t){var e=t.data;return e.args[e.cbIdx]=function(){t.invoke.apply(this,arguments)},o.apply(e.target,e.args),t}o=A(e.prototype,"toBlob",function(t){return function(e,n){var r=function(t,e){return{name:"HTMLCanvasElement.toBlob",target:t,cbIdx:0,args:e}}(e,n);return r.cbIdx>=0&&"function"==typeof n[r.cbIdx]?v(r.name,n[r.cbIdx],r,i):t.apply(e,n)}})}()}),Zone.__load_patch("XHR",function(t,e){!function(f){var l=XMLHttpRequest.prototype,h=l[c],p=l[s];if(!h){var g=t.XMLHttpRequestEventTarget;if(g){var y=g.prototype;h=y[c],p=y[s]}}var m="readystatechange",b="scheduled";function _(t){var e=t.data,r=e.target;r[i]=!1,r[u]=!1;var a=r[o];h||(h=r[c],p=r[s]),a&&p.call(r,m,a);var f=r[o]=function(){if(r.readyState===r.DONE)if(!e.aborted&&r[i]&&t.state===b){var n=r.__zone_symbol__loadfalse;if(n&&n.length>0){var o=t.invoke;t.invoke=function(){for(var n=r.__zone_symbol__loadfalse,i=0;i<n.length;i++)n[i]===t&&n.splice(i,1);e.aborted||t.state!==b||o.call(t)},n.push(t)}else t.invoke()}else e.aborted||!1!==r[i]||(r[u]=!0)};return h.call(r,m,f),r[n]||(r[n]=t),E.apply(r,e.args),r[i]=!0,t}function k(){}function S(t){var e=t.data;return e.aborted=!0,F.apply(e.target,e.args)}var x=A(l,"open",function(){return function(t,e){return t[r]=0==e[2],t[a]=e[1],x.apply(t,e)}}),w=d("fetchTaskAborting"),T=d("fetchTaskScheduling"),E=A(l,"send",function(){return function(t,n){if(!0===e.current[T])return E.apply(t,n);if(t[r])return E.apply(t,n);var o={target:t,url:t[a],isPeriodic:!1,args:n,aborted:!1},i=v("XMLHttpRequest.send",k,o,_,S);t&&!0===t[u]&&!o.aborted&&i.state===b&&i.invoke()}}),F=A(l,"abort",function(){return function(t,r){var o=t[n];if(o&&"string"==typeof o.type){if(null==o.cancelFn||o.data&&o.data.aborted)return;o.zone.cancelTask(o)}else if(!0===e.current[w])return F.apply(t,r)}})}();var n=d("xhrTask"),r=d("xhrSync"),o=d("xhrListener"),i=d("xhrScheduled"),a=d("xhrURL"),u=d("xhrErrorBeforeScheduled")}),Zone.__load_patch("geolocation",function(t){t.navigator&&t.navigator.geolocation&&function(t,n){for(var r=t.constructor.name,o=function(o){var i=n[o],a=t[i];if(a){if(!S(e(t,i)))return"continue";t[i]=function(t){var e=function(){return t.apply(this,k(arguments,r+"."+i))};return U(e,t),e}(a)}},i=0;i<n.length;i++)o(i)}(t.navigator.geolocation,["getCurrentPosition","watchPosition"])}),Zone.__load_patch("PromiseRejectionEvent",function(t,e){function n(e){return function(n){W(t,e).forEach(function(r){var o=t.PromiseRejectionEvent;if(o){var i=new o(e,{promise:n.promise,reason:n.rejection});r.invoke(i)}})}}t.PromiseRejectionEvent&&(e[d("unhandledPromiseRejectionHandler")]=n("unhandledrejection"),e[d("rejectionHandledHandler")]=n("rejectionhandled"))})}()},"0l/t":function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(2);r(r.P+r.F*!n("LyE8")([].filter,!0),"Array",{filter:function(t){return o(this,t,arguments[1])}})},"0mN4":function(t,e,n){"use strict";n("OGtf")("fixed",function(t){return function(){return t(this,"tt","","")}})},"0sh+":function(t,e,n){var r=n("quPj"),o=n("vhPU");t.exports=function(t,e,n){if(r(e))throw TypeError("String#"+n+" doesn't accept regex!");return String(o(t))}},1:function(t,e,n){t.exports=n("hN/g")},"11IZ":function(t,e,n){var r=n("dyZX").parseFloat,o=n("qncB").trim;t.exports=1/r(n("/e88")+"-0")!=-1/0?function(t){var e=o(String(t),3),n=r(e);return 0===n&&"-"==e.charAt(0)?-0:n}:r},"1MBn":function(t,e,n){var r=n("DVgA"),o=n("JiEa"),i=n("UqcF");t.exports=function(t){var e=r(t),n=o.f;if(n)for(var a,u=n(t),c=i.f,s=0;u.length>s;)c.call(t,a=u[s++])&&e.push(a);return e}},"1TsA":function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},"1sa7":function(t,e){t.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&t<1e-8?t-t*t/2:Math.log(1+t)}},"25dN":function(t,e,n){var r=n("XKFU");r(r.S,"Object",{is:n("g6HL")})},"2OiF":function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},"2Spj":function(t,e,n){var r=n("XKFU");r(r.P,"Function",{bind:n("8MEG")})},"2atp":function(t,e,n){var r=n("XKFU"),o=Math.atanh;r(r.S+r.F*!(o&&1/o(-0)<0),"Math",{atanh:function(t){return 0==(t=+t)?t:Math.log((1+t)/(1-t))/2}})},"3Lyj":function(t,e,n){var r=n("KroJ");t.exports=function(t,e,n){for(var o in e)r(t,o,e[o],n);return t}},"4A4+":function(t,e,n){n("2Spj"),n("f3/d"),n("IXt9"),t.exports=n("g3g5").Function},"4LiD":function(t,e,n){"use strict";var r=n("dyZX"),o=n("XKFU"),i=n("KroJ"),a=n("3Lyj"),u=n("Z6vF"),c=n("SlkY"),s=n("9gX7"),f=n("0/R4"),l=n("eeVq"),h=n("XMVh"),p=n("fyDq"),v=n("Xbzi");t.exports=function(t,e,n,d,g,y){var m=r[t],b=m,_=g?"set":"add",k=b&&b.prototype,S={},x=function(t){var e=k[t];i(k,t,"delete"==t?function(t){return!(y&&!f(t))&&e.call(this,0===t?0:t)}:"has"==t?function(t){return!(y&&!f(t))&&e.call(this,0===t?0:t)}:"get"==t?function(t){return y&&!f(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof b&&(y||k.forEach&&!l(function(){(new b).entries().next()}))){var w=new b,T=w[_](y?{}:-0,1)!=w,E=l(function(){w.has(1)}),F=h(function(t){new b(t)}),O=!y&&l(function(){for(var t=new b,e=5;e--;)t[_](e,e);return!t.has(-0)});F||((b=e(function(e,n){s(e,b,t);var r=v(new m,e,b);return null!=n&&c(n,g,r[_],r),r})).prototype=k,k.constructor=b),(E||O)&&(x("delete"),x("has"),g&&x("get")),(O||T)&&x(_),y&&k.clear&&delete k.clear}else b=d.getConstructor(e,t,g,_),a(b.prototype,n),u.NEED=!0;return p(b,t),S[t]=b,o(o.G+o.W+o.F*(b!=m),S),y||d.setStrong(b,t,g),b}},"4R4u":function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},"5Pf0":function(t,e,n){var r=n("S/j/"),o=n("OP3Y");n("Xtr8")("getPrototypeOf",function(){return function(t){return o(r(t))}})},"69bn":function(t,e,n){var r=n("y3w9"),o=n("2OiF"),i=n("K0xU")("species");t.exports=function(t,e){var n,a=r(t).constructor;return void 0===a||null==(n=r(a)[i])?e:o(n)}},"6AQ9":function(t,e,n){"use strict";var r=n("XKFU"),o=n("8a7r");r(r.S+r.F*n("eeVq")(function(){function t(){}return!(Array.of.call(t)instanceof t)}),"Array",{of:function(){for(var t=0,e=arguments.length,n=new("function"==typeof this?this:Array)(e);e>t;)o(n,t,arguments[t++]);return n.length=e,n}})},"6FMO":function(t,e,n){var r=n("0/R4"),o=n("EWmC"),i=n("K0xU")("species");t.exports=function(t){var e;return o(t)&&("function"!=typeof(e=t.constructor)||e!==Array&&!o(e.prototype)||(e=void 0),r(e)&&null===(e=e[i])&&(e=void 0)),void 0===e?Array:e}},"7h0T":function(t,e,n){var r=n("XKFU");r(r.S,"Number",{isNaN:function(t){return t!=t}})},"8+KV":function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(0),i=n("LyE8")([].forEach,!0);r(r.P+r.F*!i,"Array",{forEach:function(t){return o(this,t,arguments[1])}})},"84bF":function(t,e,n){"use strict";n("OGtf")("small",function(t){return function(){return t(this,"small","","")}})},"8MEG":function(t,e,n){"use strict";var r=n("2OiF"),o=n("0/R4"),i=n("MfQN"),a=[].slice,u={};t.exports=Function.bind||function(t){var e=r(this),n=a.call(arguments,1),c=function(){var r=n.concat(a.call(arguments));return this instanceof c?function(t,e,n){if(!(e in u)){for(var r=[],o=0;o<e;o++)r[o]="a["+o+"]";u[e]=Function("F,a","return new F("+r.join(",")+")")}return u[e](t,n)}(e,r.length,r):i(e,r,t)};return o(e.prototype)&&(c.prototype=e.prototype),c}},"8a7r":function(t,e,n){"use strict";var r=n("hswa"),o=n("RjD/");t.exports=function(t,e,n){e in t?r.f(t,e,o(0,n)):t[e]=n}},"91GP":function(t,e,n){var r=n("XKFU");r(r.S+r.F,"Object",{assign:n("czNK")})},"99sg":function(t,e,n){n("ioFf"),n("hHhE"),n("HAE/"),n("WLL4"),n("mYba"),n("5Pf0"),n("RW0V"),n("JduL"),n("DW2E"),n("z2o2"),n("mura"),n("Zshi"),n("V/DX"),n("FlsD"),n("91GP"),n("25dN"),n("/SS/"),n("Btvt"),t.exports=n("g3g5").Object},"9AAn":function(t,e,n){"use strict";var r=n("wmvG"),o=n("s5qY");t.exports=n("4LiD")("Map",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var e=r.getEntry(o(this,"Map"),t);return e&&e.v},set:function(t,e){return r.def(o(this,"Map"),0===t?0:t,e)}},r,!0)},"9P93":function(t,e,n){var r=n("XKFU"),o=Math.imul;r(r.S+r.F*n("eeVq")(function(){return-5!=o(4294967295,5)||2!=o.length}),"Math",{imul:function(t,e){var n=+t,r=+e,o=65535&n,i=65535&r;return 0|o*i+((65535&n>>>16)*i+o*(65535&r>>>16)<<16>>>0)}})},"9VmF":function(t,e,n){"use strict";var r=n("XKFU"),o=n("ne8i"),i=n("0sh+"),a="".startsWith;r(r.P+r.F*n("UUeW")("startsWith"),"String",{startsWith:function(t){var e=i(this,t,"startsWith"),n=o(Math.min(arguments.length>1?arguments[1]:void 0,e.length)),r=String(t);return a?a.call(e,r,n):e.slice(n,n+r.length)===r}})},"9gX7":function(t,e){t.exports=function(t,e,n,r){if(!(t instanceof e)||void 0!==r&&r in t)throw TypeError(n+": incorrect invocation!");return t}},A2zW:function(t,e,n){"use strict";var r=n("XKFU"),o=n("RYi7"),i=n("vvmO"),a=n("l0Rn"),u=1..toFixed,c=Math.floor,s=[0,0,0,0,0,0],f="Number.toFixed: incorrect invocation!",l=function(t,e){for(var n=-1,r=e;++n<6;)s[n]=(r+=t*s[n])%1e7,r=c(r/1e7)},h=function(t){for(var e=6,n=0;--e>=0;)s[e]=c((n+=s[e])/t),n=n%t*1e7},p=function(){for(var t=6,e="";--t>=0;)if(""!==e||0===t||0!==s[t]){var n=String(s[t]);e=""===e?n:e+a.call("0",7-n.length)+n}return e},v=function(t,e,n){return 0===e?n:e%2==1?v(t,e-1,n*t):v(t*t,e/2,n)};r(r.P+r.F*(!!u&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!n("eeVq")(function(){u.call({})})),"Number",{toFixed:function(t){var e,n,r,u,c=i(this,f),s=o(t),d="",g="0";if(s<0||s>20)throw RangeError(f);if(c!=c)return"NaN";if(c<=-1e21||c>=1e21)return String(c);if(c<0&&(d="-",c=-c),c>1e-21)if(n=(e=function(t){for(var e=0,n=t;n>=4096;)e+=12,n/=4096;for(;n>=2;)e+=1,n/=2;return e}(c*v(2,69,1))-69)<0?c*v(2,-e,1):c/v(2,e,1),n*=4503599627370496,(e=52-e)>0){for(l(0,n),r=s;r>=7;)l(1e7,0),r-=7;for(l(v(10,r,1),0),r=e-1;r>=23;)h(1<<23),r-=23;h(1<<r),l(1,1),h(2),g=p()}else l(0,n),l(1<<-e,0),g=p()+a.call("0",s);return s>0?d+((u=g.length)<=s?"0."+a.call("0",s-u)+g:g.slice(0,u-s)+"."+g.slice(u-s)):d+g}})},A5AN:function(t,e,n){"use strict";var r=n("AvRE")(!0);t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},Afnz:function(t,e,n){"use strict";var r=n("LQAc"),o=n("XKFU"),i=n("KroJ"),a=n("Mukb"),u=n("hPIQ"),c=n("QaDb"),s=n("fyDq"),f=n("OP3Y"),l=n("K0xU")("iterator"),h=!([].keys&&"next"in[].keys()),p=function(){return this};t.exports=function(t,e,n,v,d,g,y){c(n,e,v);var m,b,_,k=function(t){if(!h&&t in T)return T[t];switch(t){case"keys":case"values":return function(){return new n(this,t)}}return function(){return new n(this,t)}},S=e+" Iterator",x="values"==d,w=!1,T=t.prototype,E=T[l]||T["@@iterator"]||d&&T[d],F=E||k(d),O=d?x?k("entries"):F:void 0,P="Array"==e&&T.entries||E;if(P&&(_=f(P.call(new t)))!==Object.prototype&&_.next&&(s(_,S,!0),r||"function"==typeof _[l]||a(_,l,p)),x&&E&&"values"!==E.name&&(w=!0,F=function(){return E.call(this)}),r&&!y||!h&&!w&&T[l]||a(T,l,F),u[e]=F,u[S]=p,d)if(m={values:x?F:k("values"),keys:g?F:k("keys"),entries:O},y)for(b in m)b in T||i(T,b,m[b]);else o(o.P+o.F*(h||w),e,m);return m}},AphP:function(t,e,n){"use strict";var r=n("XKFU"),o=n("S/j/"),i=n("apmT");r(r.P+r.F*n("eeVq")(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(t){var e=o(this),n=i(e);return"number"!=typeof n||isFinite(n)?e.toISOString():null}})},AvRE:function(t,e,n){var r=n("RYi7"),o=n("vhPU");t.exports=function(t){return function(e,n){var i,a,u=String(o(e)),c=r(n),s=u.length;return c<0||c>=s?t?"":void 0:(i=u.charCodeAt(c))<55296||i>56319||c+1===s||(a=u.charCodeAt(c+1))<56320||a>57343?t?u.charAt(c):i:t?u.slice(c,c+2):a-56320+(i-55296<<10)+65536}}},BC7C:function(t,e,n){var r=n("XKFU");r(r.S,"Math",{fround:n("kcoS")})},"BJ/l":function(t,e,n){var r=n("XKFU");r(r.S,"Math",{log1p:n("1sa7")})},BP8U:function(t,e,n){var r=n("XKFU"),o=n("PKUr");r(r.S+r.F*(Number.parseInt!=o),"Number",{parseInt:o})},Btvt:function(t,e,n){"use strict";var r=n("I8a+"),o={};o[n("K0xU")("toStringTag")]="z",o+""!="[object z]"&&n("KroJ")(Object.prototype,"toString",function(){return"[object "+r(this)+"]"},!0)},"C/va":function(t,e,n){"use strict";var r=n("y3w9");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},CkkT:function(t,e,n){var r=n("m0Pp"),o=n("Ymqv"),i=n("S/j/"),a=n("ne8i"),u=n("zRwo");t.exports=function(t,e){var n=1==t,c=2==t,s=3==t,f=4==t,l=6==t,h=5==t||l,p=e||u;return function(e,u,v){for(var d,g,y=i(e),m=o(y),b=r(u,v,3),_=a(m.length),k=0,S=n?p(e,_):c?p(e,0):void 0;_>k;k++)if((h||k in m)&&(g=b(d=m[k],k,y),t))if(n)S[k]=g;else if(g)switch(t){case 3:return!0;case 5:return d;case 6:return k;case 2:S.push(d)}else if(f)return!1;return l?-1:s||f?f:S}}},CuTL:function(t,e,n){n("fyVe"),n("U2t9"),n("2atp"),n("+auO"),n("MtdB"),n("Jcmo"),n("nzyx"),n("BC7C"),n("x8ZO"),n("9P93"),n("eHKK"),n("BJ/l"),n("pp/T"),n("CyHz"),n("bBoP"),n("x8Yj"),n("hLT2"),t.exports=n("g3g5").Math},CyHz:function(t,e,n){var r=n("XKFU");r(r.S,"Math",{sign:n("lvtm")})},DNiP:function(t,e,n){"use strict";var r=n("XKFU"),o=n("eyMr");r(r.P+r.F*!n("LyE8")([].reduce,!0),"Array",{reduce:function(t){return o(this,t,arguments.length,arguments[1],!1)}})},DVgA:function(t,e,n){var r=n("zhAb"),o=n("4R4u");t.exports=Object.keys||function(t){return r(t,o)}},DW2E:function(t,e,n){var r=n("0/R4"),o=n("Z6vF").onFreeze;n("Xtr8")("freeze",function(t){return function(e){return t&&r(e)?t(o(e)):e}})},EK0E:function(t,e,n){"use strict";var r,o=n("dyZX"),i=n("CkkT")(0),a=n("KroJ"),u=n("Z6vF"),c=n("czNK"),s=n("ZD67"),f=n("0/R4"),l=n("s5qY"),h=n("s5qY"),p=!o.ActiveXObject&&"ActiveXObject"in o,v=u.getWeak,d=Object.isExtensible,g=s.ufstore,y=function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},m={get:function(t){if(f(t)){var e=v(t);return!0===e?g(l(this,"WeakMap")).get(t):e?e[this._i]:void 0}},set:function(t,e){return s.def(l(this,"WeakMap"),t,e)}},b=t.exports=n("4LiD")("WeakMap",y,m,s,!0,!0);h&&p&&(c((r=s.getConstructor(y,"WeakMap")).prototype,m),u.NEED=!0,i(["delete","has","get","set"],function(t){var e=b.prototype,n=e[t];a(e,t,function(e,o){if(f(e)&&!d(e)){this._f||(this._f=new r);var i=this._f[t](e,o);return"set"==t?this:i}return n.call(this,e,o)})}))},EWmC:function(t,e,n){var r=n("LZWt");t.exports=Array.isArray||function(t){return"Array"==r(t)}},EemH:function(t,e,n){var r=n("UqcF"),o=n("RjD/"),i=n("aCFj"),a=n("apmT"),u=n("aagx"),c=n("xpql"),s=Object.getOwnPropertyDescriptor;e.f=n("nh4g")?s:function(t,e){if(t=i(t),e=a(e,!0),c)try{return s(t,e)}catch(n){}if(u(t,e))return o(!r.f.call(t,e),t[e])}},FEjr:function(t,e,n){"use strict";n("OGtf")("strike",function(t){return function(){return t(this,"strike","","")}})},FJW5:function(t,e,n){var r=n("hswa"),o=n("y3w9"),i=n("DVgA");t.exports=n("nh4g")?Object.defineProperties:function(t,e){o(t);for(var n,a=i(e),u=a.length,c=0;u>c;)r.f(t,n=a[c++],e[n]);return t}},FLlr:function(t,e,n){var r=n("XKFU");r(r.P,"String",{repeat:n("l0Rn")})},FlsD:function(t,e,n){var r=n("0/R4");n("Xtr8")("isExtensible",function(t){return function(e){return!!r(e)&&(!t||t(e))}})},GNAe:function(t,e,n){var r=n("XKFU"),o=n("PKUr");r(r.G+r.F*(parseInt!=o),{parseInt:o})},H6hf:function(t,e,n){var r=n("y3w9");t.exports=function(t,e,n,o){try{return o?e(r(n)[0],n[1]):e(n)}catch(a){var i=t.return;throw void 0!==i&&r(i.call(t)),a}}},"HAE/":function(t,e,n){var r=n("XKFU");r(r.S+r.F*!n("nh4g"),"Object",{defineProperty:n("hswa").f})},HEwt:function(t,e,n){"use strict";var r=n("m0Pp"),o=n("XKFU"),i=n("S/j/"),a=n("H6hf"),u=n("M6Qj"),c=n("ne8i"),s=n("8a7r"),f=n("J+6e");o(o.S+o.F*!n("XMVh")(function(t){Array.from(t)}),"Array",{from:function(t){var e,n,o,l,h=i(t),p="function"==typeof this?this:Array,v=arguments.length,d=v>1?arguments[1]:void 0,g=void 0!==d,y=0,m=f(h);if(g&&(d=r(d,v>2?arguments[2]:void 0,2)),null==m||p==Array&&u(m))for(n=new p(e=c(h.length));e>y;y++)s(n,y,g?d(h[y],y):h[y]);else for(l=m.call(h),n=new p;!(o=l.next()).done;y++)s(n,y,g?a(l,d,[o.value,y],!0):o.value);return n.length=y,n}})},I78e:function(t,e,n){"use strict";var r=n("XKFU"),o=n("+rLv"),i=n("LZWt"),a=n("d/Gc"),u=n("ne8i"),c=[].slice;r(r.P+r.F*n("eeVq")(function(){o&&c.call(o)}),"Array",{slice:function(t,e){var n=u(this.length),r=i(this);if(e=void 0===e?n:e,"Array"==r)return c.call(this,t,e);for(var o=a(t,n),s=a(e,n),f=u(s-o),l=new Array(f),h=0;h<f;h++)l[h]="String"==r?this.charAt(o+h):this[o+h];return l}})},"I8a+":function(t,e,n){var r=n("LZWt"),o=n("K0xU")("toStringTag"),i="Arguments"==r(function(){return arguments}());t.exports=function(t){var e,n,a;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(n){}}(e=Object(t),o))?n:i?r(e):"Object"==(a=r(e))&&"function"==typeof e.callee?"Arguments":a}},INYr:function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(6),i="findIndex",a=!0;i in[]&&Array(1)[i](function(){a=!1}),r(r.P+r.F*a,"Array",{findIndex:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}}),n("nGyu")(i)},"IU+Z":function(t,e,n){"use strict";n("sMXx");var r=n("KroJ"),o=n("Mukb"),i=n("eeVq"),a=n("vhPU"),u=n("K0xU"),c=n("Ugos"),s=u("species"),f=!i(function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$<a>")}),l=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2===n.length&&"a"===n[0]&&"b"===n[1]}();t.exports=function(t,e,n){var h=u(t),p=!i(function(){var e={};return e[h]=function(){return 7},7!=""[t](e)}),v=p?!i(function(){var e=!1,n=/a/;return n.exec=function(){return e=!0,null},"split"===t&&(n.constructor={},n.constructor[s]=function(){return n}),n[h](""),!e}):void 0;if(!p||!v||"replace"===t&&!f||"split"===t&&!l){var d=/./[h],g=n(a,h,""[t],function(t,e,n,r,o){return e.exec===c?p&&!o?{done:!0,value:d.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),y=g[1];r(String.prototype,t,g[0]),o(RegExp.prototype,h,2==e?function(t,e){return y.call(t,this,e)}:function(t){return y.call(t,this)})}}},IXt9:function(t,e,n){"use strict";var r=n("0/R4"),o=n("OP3Y"),i=n("K0xU")("hasInstance"),a=Function.prototype;i in a||n("hswa").f(a,i,{value:function(t){if("function"!=typeof this||!r(t))return!1;if(!r(this.prototype))return t instanceof this;for(;t=o(t);)if(this.prototype===t)return!0;return!1}})},Iw71:function(t,e,n){var r=n("0/R4"),o=n("dyZX").document,i=r(o)&&r(o.createElement);t.exports=function(t){return i?o.createElement(t):{}}},"J+6e":function(t,e,n){var r=n("I8a+"),o=n("K0xU")("iterator"),i=n("hPIQ");t.exports=n("g3g5").getIteratorMethod=function(t){if(null!=t)return t[o]||t["@@iterator"]||i[r(t)]}},JCqj:function(t,e,n){"use strict";n("OGtf")("sup",function(t){return function(){return t(this,"sup","","")}})},Jcmo:function(t,e,n){var r=n("XKFU"),o=Math.exp;r(r.S,"Math",{cosh:function(t){return(o(t=+t)+o(-t))/2}})},JduL:function(t,e,n){n("Xtr8")("getOwnPropertyNames",function(){return n("e7yV").f})},JiEa:function(t,e){e.f=Object.getOwnPropertySymbols},K0xU:function(t,e,n){var r=n("VTer")("wks"),o=n("ylqs"),i=n("dyZX").Symbol,a="function"==typeof i;(t.exports=function(t){return r[t]||(r[t]=a&&i[t]||(a?i:o)("Symbol."+t))}).store=r},KKXr:function(t,e,n){"use strict";var r=n("quPj"),o=n("y3w9"),i=n("69bn"),a=n("A5AN"),u=n("ne8i"),c=n("Xxuz"),s=n("Ugos"),f=n("eeVq"),l=Math.min,h=[].push,p=!f(function(){RegExp(4294967295,"y")});n("IU+Z")("split",2,function(t,e,n,f){var v;return v="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,e){var o=String(this);if(void 0===t&&0===e)return[];if(!r(t))return n.call(o,t,e);for(var i,a,u,c=[],f=0,l=void 0===e?4294967295:e>>>0,p=new RegExp(t.source,(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":"")+"g");(i=s.call(p,o))&&!((a=p.lastIndex)>f&&(c.push(o.slice(f,i.index)),i.length>1&&i.index<o.length&&h.apply(c,i.slice(1)),u=i[0].length,f=a,c.length>=l));)p.lastIndex===i.index&&p.lastIndex++;return f===o.length?!u&&p.test("")||c.push(""):c.push(o.slice(f)),c.length>l?c.slice(0,l):c}:"0".split(void 0,0).length?function(t,e){return void 0===t&&0===e?[]:n.call(this,t,e)}:n,[function(n,r){var o=t(this),i=null==n?void 0:n[e];return void 0!==i?i.call(n,o,r):v.call(String(o),n,r)},function(t,e){var r=f(v,t,this,e,v!==n);if(r.done)return r.value;var s=o(t),h=String(this),d=i(s,RegExp),g=s.unicode,y=new d(p?s:"^(?:"+s.source+")",(s.ignoreCase?"i":"")+(s.multiline?"m":"")+(s.unicode?"u":"")+(p?"y":"g")),m=void 0===e?4294967295:e>>>0;if(0===m)return[];if(0===h.length)return null===c(y,h)?[h]:[];for(var b=0,_=0,k=[];_<h.length;){y.lastIndex=p?_:0;var S,x=c(y,p?h:h.slice(_));if(null===x||(S=l(u(y.lastIndex+(p?0:_)),h.length))===b)_=a(h,_,g);else{if(k.push(h.slice(b,_)),k.length===m)return k;for(var w=1;w<=x.length-1;w++)if(k.push(x[w]),k.length===m)return k;_=b=S}}return k.push(h.slice(b)),k}]})},KroJ:function(t,e,n){var r=n("dyZX"),o=n("Mukb"),i=n("aagx"),a=n("ylqs")("src"),u=n("+lvF"),c=(""+u).split("toString");n("g3g5").inspectSource=function(t){return u.call(t)},(t.exports=function(t,e,n,u){var s="function"==typeof n;s&&(i(n,"name")||o(n,"name",e)),t[e]!==n&&(s&&(i(n,a)||o(n,a,t[e]?""+t[e]:c.join(String(e)))),t===r?t[e]=n:u?t[e]?t[e]=n:o(t,e,n):(delete t[e],o(t,e,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[a]||u.call(this)})},Kuth:function(t,e,n){var r=n("y3w9"),o=n("FJW5"),i=n("4R4u"),a=n("YTvA")("IE_PROTO"),u=function(){},c=function(){var t,e=n("Iw71")("iframe"),r=i.length;for(e.style.display="none",n("+rLv").appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write("<script>document.F=Object<\/script>"),t.close(),c=t.F;r--;)delete c.prototype[i[r]];return c()};t.exports=Object.create||function(t,e){var n;return null!==t?(u.prototype=r(t),n=new u,u.prototype=null,n[a]=t):n=c(),void 0===e?n:o(n,e)}},L9s1:function(t,e,n){"use strict";var r=n("XKFU"),o=n("0sh+");r(r.P+r.F*n("UUeW")("includes"),"String",{includes:function(t){return!!~o(this,t,"includes").indexOf(t,arguments.length>1?arguments[1]:void 0)}})},LK8F:function(t,e,n){var r=n("XKFU");r(r.S,"Array",{isArray:n("EWmC")})},LQAc:function(t,e){t.exports=!1},LVwc:function(t,e){var n=Math.expm1;t.exports=!n||n(10)>22025.465794806718||n(10)<22025.465794806718||-2e-17!=n(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&t<1e-6?t+t*t/2:Math.exp(t)-1}:n},LZWt:function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},Ljet:function(t,e,n){var r=n("XKFU");r(r.S,"Number",{EPSILON:Math.pow(2,-52)})},Lmuc:function(t,e,n){n("xfY5"),n("A2zW"),n("VKir"),n("Ljet"),n("/KAi"),n("fN96"),n("7h0T"),n("sbF8"),n("h/M4"),n("knhD"),n("XfKG"),n("BP8U"),t.exports=n("g3g5").Number},LyE8:function(t,e,n){"use strict";var r=n("eeVq");t.exports=function(t,e){return!!t&&r(function(){e?t.call(null,function(){},1):t.call(null)})}},M6Qj:function(t,e,n){var r=n("hPIQ"),o=n("K0xU")("iterator"),i=Array.prototype;t.exports=function(t){return void 0!==t&&(r.Array===t||i[o]===t)}},MfQN:function(t,e){t.exports=function(t,e,n){var r=void 0===n;switch(e.length){case 0:return r?t():t.call(n);case 1:return r?t(e[0]):t.call(n,e[0]);case 2:return r?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return r?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return r?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},MtdB:function(t,e,n){var r=n("XKFU");r(r.S,"Math",{clz32:function(t){return(t>>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},Mukb:function(t,e,n){var r=n("hswa"),o=n("RjD/");t.exports=n("nh4g")?function(t,e,n){return r.f(t,e,o(1,n))}:function(t,e,n){return t[e]=n,t}},N8g3:function(t,e,n){e.f=n("K0xU")},Nr18:function(t,e,n){"use strict";var r=n("S/j/"),o=n("d/Gc"),i=n("ne8i");t.exports=function(t){for(var e=r(this),n=i(e.length),a=arguments.length,u=o(a>1?arguments[1]:void 0,n),c=a>2?arguments[2]:void 0,s=void 0===c?n:o(c,n);s>u;)e[u++]=t;return e}},Nz9U:function(t,e,n){"use strict";var r=n("XKFU"),o=n("aCFj"),i=[].join;r(r.P+r.F*(n("Ymqv")!=Object||!n("LyE8")(i)),"Array",{join:function(t){return i.call(o(this),void 0===t?",":t)}})},OEbY:function(t,e,n){n("nh4g")&&"g"!=/./g.flags&&n("hswa").f(RegExp.prototype,"flags",{configurable:!0,get:n("C/va")})},OG14:function(t,e,n){"use strict";var r=n("y3w9"),o=n("g6HL"),i=n("Xxuz");n("IU+Z")("search",1,function(t,e,n,a){return[function(n){var r=t(this),o=null==n?void 0:n[e];return void 0!==o?o.call(n,r):new RegExp(n)[e](String(r))},function(t){var e=a(n,t,this);if(e.done)return e.value;var u=r(t),c=String(this),s=u.lastIndex;o(s,0)||(u.lastIndex=0);var f=i(u,c);return o(u.lastIndex,s)||(u.lastIndex=s),null===f?-1:f.index}]})},OGtf:function(t,e,n){var r=n("XKFU"),o=n("eeVq"),i=n("vhPU"),a=/"/g,u=function(t,e,n,r){var o=String(i(t)),u="<"+e;return""!==n&&(u+=" "+n+'="'+String(r).replace(a,"&quot;")+'"'),u+">"+o+"</"+e+">"};t.exports=function(t,e){var n={};n[t]=e(u),r(r.P+r.F*o(function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}),"String",n)}},OP3Y:function(t,e,n){var r=n("aagx"),o=n("S/j/"),i=n("YTvA")("IE_PROTO"),a=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=o(t),r(t,i)?t[i]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?a:null}},OnI7:function(t,e,n){var r=n("dyZX"),o=n("g3g5"),i=n("LQAc"),a=n("N8g3"),u=n("hswa").f;t.exports=function(t){var e=o.Symbol||(o.Symbol=i?{}:r.Symbol||{});"_"==t.charAt(0)||t in e||u(e,t,{value:a.f(t)})}},Oyvg:function(t,e,n){var r=n("dyZX"),o=n("Xbzi"),i=n("hswa").f,a=n("kJMx").f,u=n("quPj"),c=n("C/va"),s=r.RegExp,f=s,l=s.prototype,h=/a/g,p=/a/g,v=new s(h)!==h;if(n("nh4g")&&(!v||n("eeVq")(function(){return p[n("K0xU")("match")]=!1,s(h)!=h||s(p)==p||"/a/i"!=s(h,"i")}))){s=function(t,e){var n=this instanceof s,r=u(t),i=void 0===e;return!n&&r&&t.constructor===s&&i?t:o(v?new f(r&&!i?t.source:t,e):f((r=t instanceof s)?t.source:t,r&&i?c.call(t):e),n?this:l,s)};for(var d=function(t){t in s||i(s,t,{configurable:!0,get:function(){return f[t]},set:function(e){f[t]=e}})},g=a(f),y=0;g.length>y;)d(g[y++]);l.constructor=s,s.prototype=l,n("KroJ")(r,"RegExp",s)}n("elZq")("RegExp")},PKUr:function(t,e,n){var r=n("dyZX").parseInt,o=n("qncB").trim,i=n("/e88"),a=/^[-+]?0[xX]/;t.exports=8!==r(i+"08")||22!==r(i+"0x16")?function(t,e){var n=o(String(t),3);return r(n,e>>>0||(a.test(n)?16:10))}:r},QaDb:function(t,e,n){"use strict";var r=n("Kuth"),o=n("RjD/"),i=n("fyDq"),a={};n("Mukb")(a,n("K0xU")("iterator"),function(){return this}),t.exports=function(t,e,n){t.prototype=r(a,{next:o(1,n)}),i(t,e+" Iterator")}},RQRG:function(t,e,n){"use strict";var r=n("XKFU"),o=n("S/j/"),i=n("2OiF"),a=n("hswa");n("nh4g")&&r(r.P+n("xbSm"),"Object",{__defineGetter__:function(t,e){a.f(o(this),t,{get:i(e),enumerable:!0,configurable:!0})}})},RW0V:function(t,e,n){var r=n("S/j/"),o=n("DVgA");n("Xtr8")("keys",function(){return function(t){return o(r(t))}})},RYi7:function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},"RjD/":function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},"S/j/":function(t,e,n){var r=n("vhPU");t.exports=function(t){return Object(r(t))}},SMB2:function(t,e,n){"use strict";n("OGtf")("bold",function(t){return function(){return t(this,"b","","")}})},SPin:function(t,e,n){"use strict";var r=n("XKFU"),o=n("eyMr");r(r.P+r.F*!n("LyE8")([].reduceRight,!0),"Array",{reduceRight:function(t){return o(this,t,arguments.length,arguments[1],!0)}})},SRfc:function(t,e,n){"use strict";var r=n("y3w9"),o=n("ne8i"),i=n("A5AN"),a=n("Xxuz");n("IU+Z")("match",1,function(t,e,n,u){return[function(n){var r=t(this),o=null==n?void 0:n[e];return void 0!==o?o.call(n,r):new RegExp(n)[e](String(r))},function(t){var e=u(n,t,this);if(e.done)return e.value;var c=r(t),s=String(this);if(!c.global)return a(c,s);var f=c.unicode;c.lastIndex=0;for(var l,h=[],p=0;null!==(l=a(c,s));){var v=String(l[0]);h[p]=v,""===v&&(c.lastIndex=i(s,o(c.lastIndex),f)),p++}return 0===p?null:h}]})},SlkY:function(t,e,n){var r=n("m0Pp"),o=n("H6hf"),i=n("M6Qj"),a=n("y3w9"),u=n("ne8i"),c=n("J+6e"),s={},f={};(e=t.exports=function(t,e,n,l,h){var p,v,d,g,y=h?function(){return t}:c(t),m=r(n,l,e?2:1),b=0;if("function"!=typeof y)throw TypeError(t+" is not iterable!");if(i(y)){for(p=u(t.length);p>b;b++)if((g=e?m(a(v=t[b])[0],v[1]):m(t[b]))===s||g===f)return g}else for(d=y.call(t);!(v=d.next()).done;)if((g=o(d,m,v.value,e))===s||g===f)return g}).BREAK=s,e.RETURN=f},T39b:function(t,e,n){"use strict";var r=n("wmvG"),o=n("s5qY");t.exports=n("4LiD")("Set",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return r.def(o(this,"Set"),t=0===t?0:t,t)}},r)},Tze0:function(t,e,n){"use strict";n("qncB")("trim",function(t){return function(){return t(this,3)}})},U2t9:function(t,e,n){var r=n("XKFU"),o=Math.asinh;r(r.S+r.F*!(o&&1/o(0)>0),"Math",{asinh:function t(e){return isFinite(e=+e)&&0!=e?e<0?-t(-e):Math.log(e+Math.sqrt(e*e+1)):e}})},UExd:function(t,e,n){var r=n("DVgA"),o=n("aCFj"),i=n("UqcF").f;t.exports=function(t){return function(e){for(var n,a=o(e),u=r(a),c=u.length,s=0,f=[];c>s;)i.call(a,n=u[s++])&&f.push(t?[n,a[n]]:a[n]);return f}}},UUeW:function(t,e,n){var r=n("K0xU")("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[r]=!1,!"/./"[t](e)}catch(o){}}return!0}},Ugos:function(t,e,n){"use strict";var r,o,i=n("C/va"),a=RegExp.prototype.exec,u=String.prototype.replace,c=a,s=(o=/b*/g,a.call(r=/a/,"a"),a.call(o,"a"),0!==r.lastIndex||0!==o.lastIndex),f=void 0!==/()??/.exec("")[1];(s||f)&&(c=function(t){var e,n,r,o,c=this;return f&&(n=new RegExp("^"+c.source+"$(?!\\s)",i.call(c))),s&&(e=c.lastIndex),r=a.call(c,t),s&&r&&(c.lastIndex=c.global?r.index+r[0].length:e),f&&r&&r.length>1&&u.call(r[0],n,function(){for(o=1;o<arguments.length-2;o++)void 0===arguments[o]&&(r[o]=void 0)}),r}),t.exports=c},UqcF:function(t,e){e.f={}.propertyIsEnumerable},"V+eJ":function(t,e,n){"use strict";var r=n("XKFU"),o=n("w2a5")(!1),i=[].indexOf,a=!!i&&1/[1].indexOf(1,-0)<0;r(r.P+r.F*(a||!n("LyE8")(i)),"Array",{indexOf:function(t){return a?i.apply(this,arguments)||0:o(this,t,arguments[1])}})},"V/DX":function(t,e,n){var r=n("0/R4");n("Xtr8")("isSealed",function(t){return function(e){return!r(e)||!!t&&t(e)}})},"V5/Y":function(t,e,n){n("VpUO"),n("eI33"),n("Tze0"),n("XfO3"),n("oDIu"),n("rvZc"),n("L9s1"),n("FLlr"),n("9VmF"),n("hEkN"),n("nIY7"),n("+oPb"),n("SMB2"),n("0mN4"),n("bDcW"),n("nsiH"),n("0LDn"),n("tUrg"),n("84bF"),n("FEjr"),n("Zz4T"),n("JCqj"),n("SRfc"),n("pIFo"),n("OG14"),n("KKXr"),t.exports=n("g3g5").String},VKir:function(t,e,n){"use strict";var r=n("XKFU"),o=n("eeVq"),i=n("vvmO"),a=1..toPrecision;r(r.P+r.F*(o(function(){return"1"!==a.call(1,void 0)})||!o(function(){a.call({})})),"Number",{toPrecision:function(t){var e=i(this,"Number#toPrecision: incorrect invocation!");return void 0===t?a.call(e):a.call(e,t)}})},VTer:function(t,e,n){var r=n("g3g5"),o=n("dyZX"),i=o["__core-js_shared__"]||(o["__core-js_shared__"]={});(t.exports=function(t,e){return i[t]||(i[t]=void 0!==e?e:{})})("versions",[]).push({version:r.version,mode:n("LQAc")?"pure":"global",copyright:"\xa9 2019 Denis Pushkarev (zloirock.ru)"})},VXxg:function(t,e,n){n("Btvt"),n("XfO3"),n("rGqo"),n("T39b"),t.exports=n("g3g5").Set},Vd3H:function(t,e,n){"use strict";var r=n("XKFU"),o=n("2OiF"),i=n("S/j/"),a=n("eeVq"),u=[].sort,c=[1,2,3];r(r.P+r.F*(a(function(){c.sort(void 0)})||!a(function(){c.sort(null)})||!n("LyE8")(u)),"Array",{sort:function(t){return void 0===t?u.call(i(this)):u.call(i(this),o(t))}})},VpUO:function(t,e,n){var r=n("XKFU"),o=n("d/Gc"),i=String.fromCharCode,a=String.fromCodePoint;r(r.S+r.F*(!!a&&1!=a.length),"String",{fromCodePoint:function(t){for(var e,n=[],r=arguments.length,a=0;r>a;){if(e=+arguments[a++],o(e,1114111)!==e)throw RangeError(e+" is not a valid code point");n.push(e<65536?i(e):i(55296+((e-=65536)>>10),e%1024+56320))}return n.join("")}})},WLL4:function(t,e,n){var r=n("XKFU");r(r.S+r.F*!n("nh4g"),"Object",{defineProperties:n("FJW5")})},XKFU:function(t,e,n){var r=n("dyZX"),o=n("g3g5"),i=n("Mukb"),a=n("KroJ"),u=n("m0Pp"),c=function(t,e,n){var s,f,l,h,p=t&c.F,v=t&c.G,d=t&c.P,g=t&c.B,y=v?r:t&c.S?r[e]||(r[e]={}):(r[e]||{}).prototype,m=v?o:o[e]||(o[e]={}),b=m.prototype||(m.prototype={});for(s in v&&(n=e),n)l=((f=!p&&y&&void 0!==y[s])?y:n)[s],h=g&&f?u(l,r):d&&"function"==typeof l?u(Function.call,l):l,y&&a(y,s,l,t&c.U),m[s]!=l&&i(m,s,h),d&&b[s]!=l&&(b[s]=l)};r.core=o,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,t.exports=c},XMVh:function(t,e,n){var r=n("K0xU")("iterator"),o=!1;try{var i=[7][r]();i.return=function(){o=!0},Array.from(i,function(){throw 2})}catch(a){}t.exports=function(t,e){if(!e&&!o)return!1;var n=!1;try{var i=[7],u=i[r]();u.next=function(){return{done:n=!0}},i[r]=function(){return u},t(i)}catch(a){}return n}},Xbzi:function(t,e,n){var r=n("0/R4"),o=n("i5dc").set;t.exports=function(t,e,n){var i,a=e.constructor;return a!==n&&"function"==typeof a&&(i=a.prototype)!==n.prototype&&r(i)&&o&&o(t,i),t}},XfKG:function(t,e,n){var r=n("XKFU"),o=n("11IZ");r(r.S+r.F*(Number.parseFloat!=o),"Number",{parseFloat:o})},XfO3:function(t,e,n){"use strict";var r=n("AvRE")(!0);n("Afnz")(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=r(e,n),this._i+=t.length,{value:t,done:!1})})},Xtr8:function(t,e,n){var r=n("XKFU"),o=n("g3g5"),i=n("eeVq");t.exports=function(t,e){var n=(o.Object||{})[t]||Object[t],a={};a[t]=e(n),r(r.S+r.F*i(function(){n(1)}),"Object",a)}},Xxuz:function(t,e,n){"use strict";var r=n("I8a+"),o=RegExp.prototype.exec;t.exports=function(t,e){var n=t.exec;if("function"==typeof n){var i=n.call(t,e);if("object"!=typeof i)throw new TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==r(t))throw new TypeError("RegExp#exec called on incompatible receiver");return o.call(t,e)}},YJVH:function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(4);r(r.P+r.F*!n("LyE8")([].every,!0),"Array",{every:function(t){return o(this,t,arguments[1])}})},YTvA:function(t,e,n){var r=n("VTer")("keys"),o=n("ylqs");t.exports=function(t){return r[t]||(r[t]=o(t))}},Ymqv:function(t,e,n){var r=n("LZWt");t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==r(t)?t.split(""):Object(t)}},Z6vF:function(t,e,n){var r=n("ylqs")("meta"),o=n("0/R4"),i=n("aagx"),a=n("hswa").f,u=0,c=Object.isExtensible||function(){return!0},s=!n("eeVq")(function(){return c(Object.preventExtensions({}))}),f=function(t){a(t,r,{value:{i:"O"+ ++u,w:{}}})},l=t.exports={KEY:r,NEED:!1,fastKey:function(t,e){if(!o(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!i(t,r)){if(!c(t))return"F";if(!e)return"E";f(t)}return t[r].i},getWeak:function(t,e){if(!i(t,r)){if(!c(t))return!0;if(!e)return!1;f(t)}return t[r].w},onFreeze:function(t){return s&&l.NEED&&c(t)&&!i(t,r)&&f(t),t}}},ZD67:function(t,e,n){"use strict";var r=n("3Lyj"),o=n("Z6vF").getWeak,i=n("y3w9"),a=n("0/R4"),u=n("9gX7"),c=n("SlkY"),s=n("CkkT"),f=n("aagx"),l=n("s5qY"),h=s(5),p=s(6),v=0,d=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},y=function(t,e){return h(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=y(this,t);if(e)return e[1]},has:function(t){return!!y(this,t)},set:function(t,e){var n=y(this,t);n?n[1]=e:this.a.push([t,e])},delete:function(t){var e=p(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},t.exports={getConstructor:function(t,e,n,i){var s=t(function(t,r){u(t,s,e,"_i"),t._t=e,t._i=v++,t._l=void 0,null!=r&&c(r,n,t[i],t)});return r(s.prototype,{delete:function(t){if(!a(t))return!1;var n=o(t);return!0===n?d(l(this,e)).delete(t):n&&f(n,this._i)&&delete n[this._i]},has:function(t){if(!a(t))return!1;var n=o(t);return!0===n?d(l(this,e)).has(t):n&&f(n,this._i)}}),s},def:function(t,e,n){var r=o(i(e),!0);return!0===r?d(t).set(e,n):r[t._i]=n,t},ufstore:d}},"ZNX/":function(t,e,n){"use strict";var r=n("XKFU"),o=n("S/j/"),i=n("apmT"),a=n("OP3Y"),u=n("EemH").f;n("nh4g")&&r(r.P+n("xbSm"),"Object",{__lookupSetter__:function(t){var e,n=o(this),r=i(t,!0);do{if(e=u(n,r))return e.set}while(n=a(n))}})},Zshi:function(t,e,n){var r=n("0/R4");n("Xtr8")("isFrozen",function(t){return function(e){return!r(e)||!!t&&t(e)}})},Zz4T:function(t,e,n){"use strict";n("OGtf")("sub",function(t){return function(){return t(this,"sub","","")}})},a0L2:function(t,e,n){n("jm62"),n("hhXQ"),n("/8Fb"),n("RQRG"),n("/uf1"),n("uaHG"),n("ZNX/"),t.exports=n("g3g5").Object},a1Th:function(t,e,n){"use strict";n("OEbY");var r=n("y3w9"),o=n("C/va"),i=n("nh4g"),a=/./.toString,u=function(t){n("KroJ")(RegExp.prototype,"toString",t,!0)};n("eeVq")(function(){return"/a/b"!=a.call({source:"a",flags:"b"})})?u(function(){var t=r(this);return"/".concat(t.source,"/","flags"in t?t.flags:!i&&t instanceof RegExp?o.call(t):void 0)}):"toString"!=a.name&&u(function(){return a.call(this)})},aCFj:function(t,e,n){var r=n("Ymqv"),o=n("vhPU");t.exports=function(t){return r(o(t))}},aagx:function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},apmT:function(t,e,n){var r=n("0/R4");t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},bBoP:function(t,e,n){var r=n("XKFU"),o=n("LVwc"),i=Math.exp;r(r.S+r.F*n("eeVq")(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(o(t)-o(-t))/2:(i(t-1)-i(-t-1))*(Math.E/2)}})},bDcW:function(t,e,n){"use strict";n("OGtf")("fontcolor",function(t){return function(e){return t(this,"font","color",e)}})},bHtr:function(t,e,n){var r=n("XKFU");r(r.P,"Array",{fill:n("Nr18")}),n("nGyu")("fill")},bWfx:function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(1);r(r.P+r.F*!n("LyE8")([].map,!0),"Array",{map:function(t){return o(this,t,arguments[1])}})},czNK:function(t,e,n){"use strict";var r=n("DVgA"),o=n("JiEa"),i=n("UqcF"),a=n("S/j/"),u=n("Ymqv"),c=Object.assign;t.exports=!c||n("eeVq")(function(){var t={},e={},n=Symbol(),r="abcdefghijklmnopqrst";return t[n]=7,r.split("").forEach(function(t){e[t]=t}),7!=c({},t)[n]||Object.keys(c({},e)).join("")!=r})?function(t,e){for(var n=a(t),c=arguments.length,s=1,f=o.f,l=i.f;c>s;)for(var h,p=u(arguments[s++]),v=f?r(p).concat(f(p)):r(p),d=v.length,g=0;d>g;)l.call(p,h=v[g++])&&(n[h]=p[h]);return n}:c},"d/Gc":function(t,e,n){var r=n("RYi7"),o=Math.max,i=Math.min;t.exports=function(t,e){return(t=r(t))<0?o(t+e,0):i(t,e)}},"dE+T":function(t,e,n){var r=n("XKFU");r(r.P,"Array",{copyWithin:n("upKx")}),n("nGyu")("copyWithin")},dQfE:function(t,e,n){n("XfO3"),n("LK8F"),n("HEwt"),n("6AQ9"),n("Nz9U"),n("I78e"),n("Vd3H"),n("8+KV"),n("bWfx"),n("0l/t"),n("dZ+Y"),n("YJVH"),n("DNiP"),n("SPin"),n("V+eJ"),n("mGWK"),n("dE+T"),n("bHtr"),n("dRSK"),n("INYr"),n("0E+W"),n("yt8O"),t.exports=n("g3g5").Array},dRSK:function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(5),i=!0;"find"in[]&&Array(1).find(function(){i=!1}),r(r.P+r.F*i,"Array",{find:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}}),n("nGyu")("find")},"dZ+Y":function(t,e,n){"use strict";var r=n("XKFU"),o=n("CkkT")(3);r(r.P+r.F*!n("LyE8")([].some,!0),"Array",{some:function(t){return o(this,t,arguments[1])}})},dyZX:function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},e7yV:function(t,e,n){var r=n("aCFj"),o=n("kJMx").f,i={}.toString,a="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];t.exports.f=function(t){return a&&"[object Window]"==i.call(t)?function(t){try{return o(t)}catch(e){return a.slice()}}(t):o(r(t))}},eHKK:function(t,e,n){var r=n("XKFU");r(r.S,"Math",{log10:function(t){return Math.log(t)*Math.LOG10E}})},eI33:function(t,e,n){var r=n("XKFU"),o=n("aCFj"),i=n("ne8i");r(r.S,"String",{raw:function(t){for(var e=o(t.raw),n=i(e.length),r=arguments.length,a=[],u=0;n>u;)a.push(String(e[u++])),u<r&&a.push(String(arguments[u]));return a.join("")}})},eM6i:function(t,e,n){var r=n("XKFU");r(r.S,"Date",{now:function(){return(new Date).getTime()}})},eeVq:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},elZq:function(t,e,n){"use strict";var r=n("dyZX"),o=n("hswa"),i=n("nh4g"),a=n("K0xU")("species");t.exports=function(t){var e=r[t];i&&e&&!e[a]&&o.f(e,a,{configurable:!0,get:function(){return this}})}},eyMr:function(t,e,n){var r=n("2OiF"),o=n("S/j/"),i=n("Ymqv"),a=n("ne8i");t.exports=function(t,e,n,u,c){r(e);var s=o(t),f=i(s),l=a(s.length),h=c?l-1:0,p=c?-1:1;if(n<2)for(;;){if(h in f){u=f[h],h+=p;break}if(h+=p,c?h<0:l<=h)throw TypeError("Reduce of empty array with no initial value")}for(;c?h>=0:l>h;h+=p)h in f&&(u=e(u,f[h],h,s));return u}},"f3/d":function(t,e,n){var r=n("hswa").f,o=Function.prototype,i=/^\s*function ([^ (]*)/;"name"in o||n("nh4g")&&r(o,"name",{configurable:!0,get:function(){try{return(""+this).match(i)[1]}catch(t){return""}}})},fN96:function(t,e,n){var r=n("XKFU");r(r.S,"Number",{isInteger:n("nBIS")})},fyDq:function(t,e,n){var r=n("hswa").f,o=n("aagx"),i=n("K0xU")("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,i)&&r(t,i,{configurable:!0,value:e})}},fyVe:function(t,e,n){var r=n("XKFU"),o=n("1sa7"),i=Math.sqrt,a=Math.acosh;r(r.S+r.F*!(a&&710==Math.floor(a(Number.MAX_VALUE))&&a(1/0)==1/0),"Math",{acosh:function(t){return(t=+t)<1?NaN:t>94906265.62425156?Math.log(t)+Math.LN2:o(t-1+i(t-1)*i(t+1))}})},g3g5:function(t,e){var n=t.exports={version:"2.6.5"};"number"==typeof __e&&(__e=n)},g4EE:function(t,e,n){"use strict";var r=n("y3w9"),o=n("apmT");t.exports=function(t){if("string"!==t&&"number"!==t&&"default"!==t)throw TypeError("Incorrect hint");return o(r(this),"number"!=t)}},g6HL:function(t,e){t.exports=Object.is||function(t,e){return t===e?0!==t||1/t==1/e:t!=t&&e!=e}},"h/M4":function(t,e,n){var r=n("XKFU");r(r.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},h7Nl:function(t,e,n){var r=Date.prototype,o=r.toString,i=r.getTime;new Date(NaN)+""!="Invalid Date"&&n("KroJ")(r,"toString",function(){var t=i.call(this);return t==t?o.call(this):"Invalid Date"})},hEkN:function(t,e,n){"use strict";n("OGtf")("anchor",function(t){return function(e){return t(this,"a","name",e)}})},hHhE:function(t,e,n){var r=n("XKFU");r(r.S,"Object",{create:n("Kuth")})},hLT2:function(t,e,n){var r=n("XKFU");r(r.S,"Math",{trunc:function(t){return(t>0?Math.floor:Math.ceil)(t)}})},"hN/g":function(t,e,n){"use strict";n.r(e),n("dQfE"),n("nx1v"),n("4A4+"),n("qKs0"),n("CuTL"),n("Lmuc"),n("99sg"),n("ifmr"),n("oka+"),n("rfyP"),n("VXxg"),n("V5/Y"),n("vqGA"),n("hYbK"),n("a0L2"),n("0TWp")},hPIQ:function(t,e){t.exports={}},hYbK:function(t,e,n){n("Btvt"),n("yt8O"),n("EK0E"),t.exports=n("g3g5").WeakMap},hhXQ:function(t,e,n){var r=n("XKFU"),o=n("UExd")(!1);r(r.S,"Object",{values:function(t){return o(t)}})},hswa:function(t,e,n){var r=n("y3w9"),o=n("xpql"),i=n("apmT"),a=Object.defineProperty;e.f=n("nh4g")?Object.defineProperty:function(t,e,n){if(r(t),e=i(e,!0),r(n),o)try{return a(t,e,n)}catch(u){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},i5dc:function(t,e,n){var r=n("0/R4"),o=n("y3w9"),i=function(t,e){if(o(t),!r(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,e,r){try{(r=n("m0Pp")(Function.call,n("EemH").f(Object.prototype,"__proto__").set,2))(t,[]),e=!(t instanceof Array)}catch(o){e=!0}return function(t,n){return i(t,n),e?t.__proto__=n:r(t,n),t}}({},!1):void 0),check:i}},ifmr:function(t,e,n){n("tyy+"),t.exports=n("g3g5").parseFloat},ioFf:function(t,e,n){"use strict";var r=n("dyZX"),o=n("aagx"),i=n("nh4g"),a=n("XKFU"),u=n("KroJ"),c=n("Z6vF").KEY,s=n("eeVq"),f=n("VTer"),l=n("fyDq"),h=n("ylqs"),p=n("K0xU"),v=n("N8g3"),d=n("OnI7"),g=n("1MBn"),y=n("EWmC"),m=n("y3w9"),b=n("0/R4"),_=n("aCFj"),k=n("apmT"),S=n("RjD/"),x=n("Kuth"),w=n("e7yV"),T=n("EemH"),E=n("hswa"),F=n("DVgA"),O=T.f,P=E.f,j=w.f,M=r.Symbol,D=r.JSON,I=D&&D.stringify,A=p("_hidden"),U=p("toPrimitive"),X={}.propertyIsEnumerable,Z=f("symbol-registry"),K=f("symbols"),C=f("op-symbols"),L=Object.prototype,R="function"==typeof M,z=r.QObject,N=!z||!z.prototype||!z.prototype.findChild,q=i&&s(function(){return 7!=x(P({},"a",{get:function(){return P(this,"a",{value:7}).a}})).a})?function(t,e,n){var r=O(L,e);r&&delete L[e],P(t,e,n),r&&t!==L&&P(L,e,r)}:P,V=function(t){var e=K[t]=x(M.prototype);return e._k=t,e},G=R&&"symbol"==typeof M.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof M},H=function(t,e,n){return t===L&&H(C,e,n),m(t),e=k(e,!0),m(n),o(K,e)?(n.enumerable?(o(t,A)&&t[A][e]&&(t[A][e]=!1),n=x(n,{enumerable:S(0,!1)})):(o(t,A)||P(t,A,S(1,{})),t[A][e]=!0),q(t,e,n)):P(t,e,n)},W=function(t,e){m(t);for(var n,r=g(e=_(e)),o=0,i=r.length;i>o;)H(t,n=r[o++],e[n]);return t},Y=function(t){var e=X.call(this,t=k(t,!0));return!(this===L&&o(K,t)&&!o(C,t))&&(!(e||!o(this,t)||!o(K,t)||o(this,A)&&this[A][t])||e)},B=function(t,e){if(t=_(t),e=k(e,!0),t!==L||!o(K,e)||o(C,e)){var n=O(t,e);return!n||!o(K,e)||o(t,A)&&t[A][e]||(n.enumerable=!0),n}},J=function(t){for(var e,n=j(_(t)),r=[],i=0;n.length>i;)o(K,e=n[i++])||e==A||e==c||r.push(e);return r},Q=function(t){for(var e,n=t===L,r=j(n?C:_(t)),i=[],a=0;r.length>a;)!o(K,e=r[a++])||n&&!o(L,e)||i.push(K[e]);return i};R||(u((M=function(){if(this instanceof M)throw TypeError("Symbol is not a constructor!");var t=h(arguments.length>0?arguments[0]:void 0),e=function(n){this===L&&e.call(C,n),o(this,A)&&o(this[A],t)&&(this[A][t]=!1),q(this,t,S(1,n))};return i&&N&&q(L,t,{configurable:!0,set:e}),V(t)}).prototype,"toString",function(){return this._k}),T.f=B,E.f=H,n("kJMx").f=w.f=J,n("UqcF").f=Y,n("JiEa").f=Q,i&&!n("LQAc")&&u(L,"propertyIsEnumerable",Y,!0),v.f=function(t){return V(p(t))}),a(a.G+a.W+a.F*!R,{Symbol:M});for(var $="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),tt=0;$.length>tt;)p($[tt++]);for(var et=F(p.store),nt=0;et.length>nt;)d(et[nt++]);a(a.S+a.F*!R,"Symbol",{for:function(t){return o(Z,t+="")?Z[t]:Z[t]=M(t)},keyFor:function(t){if(!G(t))throw TypeError(t+" is not a symbol!");for(var e in Z)if(Z[e]===t)return e},useSetter:function(){N=!0},useSimple:function(){N=!1}}),a(a.S+a.F*!R,"Object",{create:function(t,e){return void 0===e?x(t):W(x(t),e)},defineProperty:H,defineProperties:W,getOwnPropertyDescriptor:B,getOwnPropertyNames:J,getOwnPropertySymbols:Q}),D&&a(a.S+a.F*(!R||s(function(){var t=M();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){for(var e,n,r=[t],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=e=r[1],(b(e)||void 0!==t)&&!G(t))return y(e)||(e=function(t,e){if("function"==typeof n&&(e=n.call(this,t,e)),!G(e))return e}),r[1]=e,I.apply(D,r)}}),M.prototype[U]||n("Mukb")(M.prototype,U,M.prototype.valueOf),l(M,"Symbol"),l(Math,"Math",!0),l(r.JSON,"JSON",!0)},jm62:function(t,e,n){var r=n("XKFU"),o=n("mQtv"),i=n("aCFj"),a=n("EemH"),u=n("8a7r");r(r.S,"Object",{getOwnPropertyDescriptors:function(t){for(var e,n,r=i(t),c=a.f,s=o(r),f={},l=0;s.length>l;)void 0!==(n=c(r,e=s[l++]))&&u(f,e,n);return f}})},jqX0:function(t,e,n){var r=n("XKFU"),o=n("jtBr");r(r.P+r.F*(Date.prototype.toISOString!==o),"Date",{toISOString:o})},jtBr:function(t,e,n){"use strict";var r=n("eeVq"),o=Date.prototype.getTime,i=Date.prototype.toISOString,a=function(t){return t>9?t:"0"+t};t.exports=r(function(){return"0385-07-25T07:06:39.999Z"!=i.call(new Date(-5e13-1))})||!r(function(){i.call(new Date(NaN))})?function(){if(!isFinite(o.call(this)))throw RangeError("Invalid time value");var t=this,e=t.getUTCFullYear(),n=t.getUTCMilliseconds(),r=e<0?"-":e>9999?"+":"";return r+("00000"+Math.abs(e)).slice(r?-6:-4)+"-"+a(t.getUTCMonth()+1)+"-"+a(t.getUTCDate())+"T"+a(t.getUTCHours())+":"+a(t.getUTCMinutes())+":"+a(t.getUTCSeconds())+"."+(n>99?n:"0"+a(n))+"Z"}:i},kJMx:function(t,e,n){var r=n("zhAb"),o=n("4R4u").concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,o)}},kcoS:function(t,e,n){var r=n("lvtm"),o=Math.pow,i=o(2,-52),a=o(2,-23),u=o(2,127)*(2-a),c=o(2,-126);t.exports=Math.fround||function(t){var e,n,o=Math.abs(t),s=r(t);return o<c?s*(o/c/a+1/i-1/i)*c*a:(n=(e=(1+a/i)*o)-(e-o))>u||n!=n?s*(1/0):s*n}},knhD:function(t,e,n){var r=n("XKFU");r(r.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},l0Rn:function(t,e,n){"use strict";var r=n("RYi7"),o=n("vhPU");t.exports=function(t){var e=String(o(this)),n="",i=r(t);if(i<0||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},lvtm:function(t,e){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},m0Pp:function(t,e,n){var r=n("2OiF");t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},mGWK:function(t,e,n){"use strict";var r=n("XKFU"),o=n("aCFj"),i=n("RYi7"),a=n("ne8i"),u=[].lastIndexOf,c=!!u&&1/[1].lastIndexOf(1,-0)<0;r(r.P+r.F*(c||!n("LyE8")(u)),"Array",{lastIndexOf:function(t){if(c)return u.apply(this,arguments)||0;var e=o(this),n=a(e.length),r=n-1;for(arguments.length>1&&(r=Math.min(r,i(arguments[1]))),r<0&&(r=n+r);r>=0;r--)if(r in e&&e[r]===t)return r||0;return-1}})},mQtv:function(t,e,n){var r=n("kJMx"),o=n("JiEa"),i=n("y3w9"),a=n("dyZX").Reflect;t.exports=a&&a.ownKeys||function(t){var e=r.f(i(t)),n=o.f;return n?e.concat(n(t)):e}},mYba:function(t,e,n){var r=n("aCFj"),o=n("EemH").f;n("Xtr8")("getOwnPropertyDescriptor",function(){return function(t,e){return o(r(t),e)}})},mura:function(t,e,n){var r=n("0/R4"),o=n("Z6vF").onFreeze;n("Xtr8")("preventExtensions",function(t){return function(e){return t&&r(e)?t(o(e)):e}})},nBIS:function(t,e,n){var r=n("0/R4"),o=Math.floor;t.exports=function(t){return!r(t)&&isFinite(t)&&o(t)===t}},nGyu:function(t,e,n){var r=n("K0xU")("unscopables"),o=Array.prototype;null==o[r]&&n("Mukb")(o,r,{}),t.exports=function(t){o[r][t]=!0}},nIY7:function(t,e,n){"use strict";n("OGtf")("big",function(t){return function(){return t(this,"big","","")}})},ne8i:function(t,e,n){var r=n("RYi7"),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},nh4g:function(t,e,n){t.exports=!n("eeVq")(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},nsiH:function(t,e,n){"use strict";n("OGtf")("fontsize",function(t){return function(e){return t(this,"font","size",e)}})},nx1v:function(t,e,n){n("eM6i"),n("AphP"),n("jqX0"),n("h7Nl"),n("yM4b"),t.exports=Date},nzyx:function(t,e,n){var r=n("XKFU"),o=n("LVwc");r(r.S+r.F*(o!=Math.expm1),"Math",{expm1:o})},oDIu:function(t,e,n){"use strict";var r=n("XKFU"),o=n("AvRE")(!1);r(r.P,"String",{codePointAt:function(t){return o(this,t)}})},"oka+":function(t,e,n){n("GNAe"),t.exports=n("g3g5").parseInt},pIFo:function(t,e,n){"use strict";var r=n("y3w9"),o=n("S/j/"),i=n("ne8i"),a=n("RYi7"),u=n("A5AN"),c=n("Xxuz"),s=Math.max,f=Math.min,l=Math.floor,h=/\$([$&`']|\d\d?|<[^>]*>)/g,p=/\$([$&`']|\d\d?)/g;n("IU+Z")("replace",2,function(t,e,n,v){return[function(r,o){var i=t(this),a=null==r?void 0:r[e];return void 0!==a?a.call(r,i,o):n.call(String(i),r,o)},function(t,e){var o=v(n,t,this,e);if(o.done)return o.value;var l=r(t),h=String(this),p="function"==typeof e;p||(e=String(e));var g=l.global;if(g){var y=l.unicode;l.lastIndex=0}for(var m=[];;){var b=c(l,h);if(null===b)break;if(m.push(b),!g)break;""===String(b[0])&&(l.lastIndex=u(h,i(l.lastIndex),y))}for(var _,k="",S=0,x=0;x<m.length;x++){b=m[x];for(var w=String(b[0]),T=s(f(a(b.index),h.length),0),E=[],F=1;F<b.length;F++)E.push(void 0===(_=b[F])?_:String(_));var O=b.groups;if(p){var P=[w].concat(E,T,h);void 0!==O&&P.push(O);var j=String(e.apply(void 0,P))}else j=d(w,h,T,E,O,e);T>=S&&(k+=h.slice(S,T)+j,S=T+w.length)}return k+h.slice(S)}];function d(t,e,r,i,a,u){var c=r+t.length,s=i.length,f=p;return void 0!==a&&(a=o(a),f=h),n.call(u,f,function(n,o){var u;switch(o.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,r);case"'":return e.slice(c);case"<":u=a[o.slice(1,-1)];break;default:var f=+o;if(0===f)return n;if(f>s){var h=l(f/10);return 0===h?n:h<=s?void 0===i[h-1]?o.charAt(1):i[h-1]+o.charAt(1):n}u=i[f-1]}return void 0===u?"":u})}})},"pp/T":function(t,e,n){var r=n("XKFU");r(r.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},qKs0:function(t,e,n){n("Btvt"),n("XfO3"),n("rGqo"),n("9AAn"),t.exports=n("g3g5").Map},qncB:function(t,e,n){var r=n("XKFU"),o=n("vhPU"),i=n("eeVq"),a=n("/e88"),u="["+a+"]",c=RegExp("^"+u+u+"*"),s=RegExp(u+u+"*$"),f=function(t,e,n){var o={},u=i(function(){return!!a[t]()||"\u200b\x85"!="\u200b\x85"[t]()}),c=o[t]=u?e(l):a[t];n&&(o[n]=c),r(r.P+r.F*u,"String",o)},l=f.trim=function(t,e){return t=String(o(t)),1&e&&(t=t.replace(c,"")),2&e&&(t=t.replace(s,"")),t};t.exports=f},quPj:function(t,e,n){var r=n("0/R4"),o=n("LZWt"),i=n("K0xU")("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==o(t))}},rGqo:function(t,e,n){for(var r=n("yt8O"),o=n("DVgA"),i=n("KroJ"),a=n("dyZX"),u=n("Mukb"),c=n("hPIQ"),s=n("K0xU"),f=s("iterator"),l=s("toStringTag"),h=c.Array,p={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},v=o(p),d=0;d<v.length;d++){var g,y=v[d],m=p[y],b=a[y],_=b&&b.prototype;if(_&&(_[f]||u(_,f,h),_[l]||u(_,l,y),c[y]=h,m))for(g in r)_[g]||i(_,g,r[g],!0)}},rfyP:function(t,e,n){n("Oyvg"),n("sMXx"),n("a1Th"),n("OEbY"),n("SRfc"),n("pIFo"),n("OG14"),n("KKXr"),t.exports=n("g3g5").RegExp},rvZc:function(t,e,n){"use strict";var r=n("XKFU"),o=n("ne8i"),i=n("0sh+"),a="".endsWith;r(r.P+r.F*n("UUeW")("endsWith"),"String",{endsWith:function(t){var e=i(this,t,"endsWith"),n=arguments.length>1?arguments[1]:void 0,r=o(e.length),u=void 0===n?r:Math.min(o(n),r),c=String(t);return a?a.call(e,c,u):e.slice(u-c.length,u)===c}})},s5qY:function(t,e,n){var r=n("0/R4");t.exports=function(t,e){if(!r(t)||t._t!==e)throw TypeError("Incompatible receiver, "+e+" required!");return t}},sMXx:function(t,e,n){"use strict";var r=n("Ugos");n("XKFU")({target:"RegExp",proto:!0,forced:r!==/./.exec},{exec:r})},sbF8:function(t,e,n){var r=n("XKFU"),o=n("nBIS"),i=Math.abs;r(r.S,"Number",{isSafeInteger:function(t){return o(t)&&i(t)<=9007199254740991}})},tUrg:function(t,e,n){"use strict";n("OGtf")("link",function(t){return function(e){return t(this,"a","href",e)}})},"tyy+":function(t,e,n){var r=n("XKFU"),o=n("11IZ");r(r.G+r.F*(parseFloat!=o),{parseFloat:o})},uaHG:function(t,e,n){"use strict";var r=n("XKFU"),o=n("S/j/"),i=n("apmT"),a=n("OP3Y"),u=n("EemH").f;n("nh4g")&&r(r.P+n("xbSm"),"Object",{__lookupGetter__:function(t){var e,n=o(this),r=i(t,!0);do{if(e=u(n,r))return e.get}while(n=a(n))}})},upKx:function(t,e,n){"use strict";var r=n("S/j/"),o=n("d/Gc"),i=n("ne8i");t.exports=[].copyWithin||function(t,e){var n=r(this),a=i(n.length),u=o(t,a),c=o(e,a),s=arguments.length>2?arguments[2]:void 0,f=Math.min((void 0===s?a:o(s,a))-c,a-u),l=1;for(c<u&&u<c+f&&(l=-1,c+=f-1,u+=f-1);f-- >0;)c in n?n[u]=n[c]:delete n[u],u+=l,c+=l;return n}},vhPU:function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},vqGA:function(t,e,n){n("ioFf"),n("Btvt"),t.exports=n("g3g5").Symbol},vvmO:function(t,e,n){var r=n("LZWt");t.exports=function(t,e){if("number"!=typeof t&&"Number"!=r(t))throw TypeError(e);return+t}},w2a5:function(t,e,n){var r=n("aCFj"),o=n("ne8i"),i=n("d/Gc");t.exports=function(t){return function(e,n,a){var u,c=r(e),s=o(c.length),f=i(a,s);if(t&&n!=n){for(;s>f;)if((u=c[f++])!=u)return!0}else for(;s>f;f++)if((t||f in c)&&c[f]===n)return t||f||0;return!t&&-1}}},wmvG:function(t,e,n){"use strict";var r=n("hswa").f,o=n("Kuth"),i=n("3Lyj"),a=n("m0Pp"),u=n("9gX7"),c=n("SlkY"),s=n("Afnz"),f=n("1TsA"),l=n("elZq"),h=n("nh4g"),p=n("Z6vF").fastKey,v=n("s5qY"),d=h?"_s":"size",g=function(t,e){var n,r=p(e);if("F"!==r)return t._i[r];for(n=t._f;n;n=n.n)if(n.k==e)return n};t.exports={getConstructor:function(t,e,n,s){var f=t(function(t,r){u(t,f,e,"_i"),t._t=e,t._i=o(null),t._f=void 0,t._l=void 0,t[d]=0,null!=r&&c(r,n,t[s],t)});return i(f.prototype,{clear:function(){for(var t=v(this,e),n=t._i,r=t._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete n[r.i];t._f=t._l=void 0,t[d]=0},delete:function(t){var n=v(this,e),r=g(n,t);if(r){var o=r.n,i=r.p;delete n._i[r.i],r.r=!0,i&&(i.n=o),o&&(o.p=i),n._f==r&&(n._f=o),n._l==r&&(n._l=i),n[d]--}return!!r},forEach:function(t){v(this,e);for(var n,r=a(t,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(r(n.v,n.k,this);n&&n.r;)n=n.p},has:function(t){return!!g(v(this,e),t)}}),h&&r(f.prototype,"size",{get:function(){return v(this,e)[d]}}),f},def:function(t,e,n){var r,o,i=g(t,e);return i?i.v=n:(t._l=i={i:o=p(e,!0),k:e,v:n,p:r=t._l,n:void 0,r:!1},t._f||(t._f=i),r&&(r.n=i),t[d]++,"F"!==o&&(t._i[o]=i)),t},getEntry:g,setStrong:function(t,e,n){s(t,e,function(t,n){this._t=v(t,e),this._k=n,this._l=void 0},function(){for(var t=this._k,e=this._l;e&&e.r;)e=e.p;return this._t&&(this._l=e=e?e.n:this._t._f)?f(0,"keys"==t?e.k:"values"==t?e.v:[e.k,e.v]):(this._t=void 0,f(1))},n?"entries":"values",!n,!0),l(e)}}},x8Yj:function(t,e,n){var r=n("XKFU"),o=n("LVwc"),i=Math.exp;r(r.S,"Math",{tanh:function(t){var e=o(t=+t),n=o(-t);return e==1/0?1:n==1/0?-1:(e-n)/(i(t)+i(-t))}})},x8ZO:function(t,e,n){var r=n("XKFU"),o=Math.abs;r(r.S,"Math",{hypot:function(t,e){for(var n,r,i=0,a=0,u=arguments.length,c=0;a<u;)c<(n=o(arguments[a++]))?(i=i*(r=c/n)*r+1,c=n):i+=n>0?(r=n/c)*r:n;return c===1/0?1/0:c*Math.sqrt(i)}})},xbSm:function(t,e,n){"use strict";t.exports=n("LQAc")||!n("eeVq")(function(){var t=Math.random();__defineSetter__.call(null,t,function(){}),delete n("dyZX")[t]})},xfY5:function(t,e,n){"use strict";var r=n("dyZX"),o=n("aagx"),i=n("LZWt"),a=n("Xbzi"),u=n("apmT"),c=n("eeVq"),s=n("kJMx").f,f=n("EemH").f,l=n("hswa").f,h=n("qncB").trim,p=r.Number,v=p,d=p.prototype,g="Number"==i(n("Kuth")(d)),y="trim"in String.prototype,m=function(t){var e=u(t,!1);if("string"==typeof e&&e.length>2){var n,r,o,i=(e=y?e.trim():h(e,3)).charCodeAt(0);if(43===i||45===i){if(88===(n=e.charCodeAt(2))||120===n)return NaN}else if(48===i){switch(e.charCodeAt(1)){case 66:case 98:r=2,o=49;break;case 79:case 111:r=8,o=55;break;default:return+e}for(var a,c=e.slice(2),s=0,f=c.length;s<f;s++)if((a=c.charCodeAt(s))<48||a>o)return NaN;return parseInt(c,r)}}return+e};if(!p(" 0o1")||!p("0b1")||p("+0x1")){p=function(t){var e=arguments.length<1?0:t,n=this;return n instanceof p&&(g?c(function(){d.valueOf.call(n)}):"Number"!=i(n))?a(new v(m(e)),n,p):m(e)};for(var b,_=n("nh4g")?s(v):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),k=0;_.length>k;k++)o(v,b=_[k])&&!o(p,b)&&l(p,b,f(v,b));p.prototype=d,d.constructor=p,n("KroJ")(r,"Number",p)}},xpql:function(t,e,n){t.exports=!n("nh4g")&&!n("eeVq")(function(){return 7!=Object.defineProperty(n("Iw71")("div"),"a",{get:function(){return 7}}).a})},y3w9:function(t,e,n){var r=n("0/R4");t.exports=function(t){if(!r(t))throw TypeError(t+" is not an object!");return t}},yM4b:function(t,e,n){var r=n("K0xU")("toPrimitive"),o=Date.prototype;r in o||n("Mukb")(o,r,n("g4EE"))},ylqs:function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},yt8O:function(t,e,n){"use strict";var r=n("nGyu"),o=n("1TsA"),i=n("hPIQ"),a=n("aCFj");t.exports=n("Afnz")(Array,"Array",function(t,e){this._t=a(t),this._i=0,this._k=e},function(){var t=this._t,e=this._k,n=this._i++;return!t||n>=t.length?(this._t=void 0,o(1)):o(0,"keys"==e?n:"values"==e?t[n]:[n,t[n]])},"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},z2o2:function(t,e,n){var r=n("0/R4"),o=n("Z6vF").onFreeze;n("Xtr8")("seal",function(t){return function(e){return t&&r(e)?t(o(e)):e}})},zRwo:function(t,e,n){var r=n("6FMO");t.exports=function(t,e){return new(r(t))(e)}},zhAb:function(t,e,n){var r=n("aagx"),o=n("aCFj"),i=n("w2a5")(!1),a=n("YTvA")("IE_PROTO");t.exports=function(t,e){var n,u=o(t),c=0,s=[];for(n in u)n!=a&&r(u,n)&&s.push(n);for(;e.length>c;)r(u,n=e[c++])&&(~i(s,n)||s.push(n));return s}}},[[1,1]]]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/prometheus_logo.074db273ef932a67d91b.svg b/src/pybind/mgr/dashboard/frontend/dist/en-US/prometheus_logo.074db273ef932a67d91b.svg
new file mode 100644
index 00000000..5c51f66d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/prometheus_logo.074db273ef932a67d91b.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="115.333px"
+ height="114px"
+ viewBox="0 0 115.333 114"
+ enable-background="new 0 0 115.333 114"
+ xml:space="preserve"
+ sodipodi:docname="prometheus_logo_orange.svg"
+ inkscape:version="0.92.1 r15371"><metadata
+ id="metadata4495"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs4493" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1484"
+ inkscape:window-height="886"
+ id="namedview4491"
+ showgrid="false"
+ inkscape:zoom="5.2784901"
+ inkscape:cx="60.603667"
+ inkscape:cy="60.329656"
+ inkscape:window-x="54"
+ inkscape:window-y="7"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" /><g
+ id="Layer_2" /><path
+ style="fill:#e6522c;fill-opacity:1"
+ inkscape:connector-curvature="0"
+ id="path4486"
+ d="M 56.667,0.667 C 25.372,0.667 0,26.036 0,57.332 c 0,31.295 25.372,56.666 56.667,56.666 31.295,0 56.666,-25.371 56.666,-56.666 0,-31.296 -25.372,-56.665 -56.666,-56.665 z m 0,106.055 c -8.904,0 -16.123,-5.948 -16.123,-13.283 H 72.79 c 0,7.334 -7.219,13.283 -16.123,13.283 z M 83.297,89.04 H 30.034 V 79.382 H 83.298 V 89.04 Z M 83.106,74.411 H 30.186 C 30.01,74.208 29.83,74.008 29.66,73.802 24.208,67.182 22.924,63.726 21.677,60.204 c -0.021,-0.116 6.611,1.355 11.314,2.413 0,0 2.42,0.56 5.958,1.205 -3.397,-3.982 -5.414,-9.044 -5.414,-14.218 0,-11.359 8.712,-21.285 5.569,-29.308 3.059,0.249 6.331,6.456 6.552,16.161 3.252,-4.494 4.613,-12.701 4.613,-17.733 0,-5.21 3.433,-11.262 6.867,-11.469 -3.061,5.045 0.793,9.37 4.219,20.099 1.285,4.03 1.121,10.812 2.113,15.113 C 63.797,33.534 65.333,20.5 71,16 c -2.5,5.667 0.37,12.758 2.333,16.167 3.167,5.5 5.087,9.667 5.087,17.548 0,5.284 -1.951,10.259 -5.242,14.148 3.742,-0.702 6.326,-1.335 6.326,-1.335 l 12.152,-2.371 c 10e-4,-10e-4 -1.765,7.261 -8.55,14.254 z" /></svg> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/runtime.ff444394af058f159c51.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/runtime.ff444394af058f159c51.js
new file mode 100644
index 00000000..e2ef17c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/runtime.ff444394af058f159c51.js
@@ -0,0 +1 @@
+!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],p=0,d=[];p<a.length;p++)o[i=a[p]]&&d.push(o[i][0]),o[i]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);d.length;)d.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++)0!==o[t[a]]&&(n=!1);n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={1:0},u=[];function i(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise(function(r,n){t=o[e]=[r,n]});r.push(t[2]=n);var u,a=document.createElement("script");a.charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.src=function(e){return i.p+""+({0:"common"}[e]||e)+"."+{0:"8a53d98b04768bd15706",2:"22b12bf9358f95829e55",6:"f054f1f260c137d64363",7:"76846491986b0ea6c0bd",8:"7550b99d388b9ca165da",9:"b19f6391d5c667b85d12"}[e]+".js"}(e),u=function(r){a.onerror=a.onload=null,clearTimeout(c);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src,i=new Error("Loading chunk "+e+" failed.\n("+n+": "+u+")");i.type=n,i.request=u,t[1](i)}o[e]=void 0}};var c=setTimeout(function(){u({type:"timeout",target:a})},12e4);a.onerror=a.onload=u,document.head.appendChild(a)}return Promise.all(r)},i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,(function(r){return e[r]}).bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="",i.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/scripts.fc88ef4a23399c760d0b.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/scripts.fc88ef4a23399c760d0b.js
new file mode 100644
index 00000000..1aa39bbb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/scripts.fc88ef4a23399c760d0b.js
@@ -0,0 +1 @@
+!function(t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}(function(){return function t(e,n,i){function a(o,s){if(!n[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[o]={exports:{}};e[o][0].call(d.exports,function(t){return a(e[o][1][t]||t)},d,d.exports,t,e,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)a(i[o]);return a}({1:[function(t,e,n){var i=t(5);function a(t){if(t){var e=[0,0,0],n=1,a=t.match(/^#([a-fA-F0-9]{3})$/i);if(a){a=a[1];for(var r=0;r<e.length;r++)e[r]=parseInt(a[r]+a[r],16)}else if(a=t.match(/^#([a-fA-F0-9]{6})$/i))for(a=a[1],r=0;r<e.length;r++)e[r]=parseInt(a.slice(2*r,2*r+2),16);else if(a=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=parseInt(a[r+1]);n=parseFloat(a[4])}else if(a=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(r=0;r<e.length;r++)e[r]=Math.round(2.55*parseFloat(a[r+1]));n=parseFloat(a[4])}else if(a=t.match(/(\w+)/)){if("transparent"==a[1])return[0,0,0,0];if(!(e=i[a[1]]))return}for(r=0;r<e.length;r++)e[r]=d(e[r],0,255);return n=n||0==n?d(n,0,1):1,e[3]=n,e}}function r(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(n)?1:n,0,1)]}}}function o(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(n)?1:n,0,1)]}}}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function u(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function d(t,e,n){return Math.min(Math.max(e,t),n)}function h(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}e.exports={getRgba:a,getHsla:r,getRgb:function(t){var e=a(t);return e&&e.slice(0,3)},getHsl:function(t){var e=r(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=a(t);return e?e[3]:(e=r(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+h(t[0])+h(t[1])+h(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:s,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?u(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:u,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return c[t.slice(0,3)]}};var c={};for(var f in i)c[i[f]]=f},{5:5}],2:[function(t,e,n){var i=t(4),a=t(1),r=function(t){return t instanceof r?t:this instanceof r?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new r(t);var e};r.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=t,i=void 0===e?.5:e,a=2*i-1,r=this.alpha()-n.alpha(),o=((a*r==-1?a:(a+r)/(1+a*r))+1)/2,s=1-o;return this.rgb(o*this.red()+s*n.red(),o*this.green()+s*n.green(),o*this.blue()+s*n.blue()).alpha(this.alpha()*i+n.alpha()*(1-i))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&("[object Array]"===(e={}.toString.call(t=i[o]))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},r.prototype.setValues=function(t,e){var n,a,r=this.values,o=this.spaces,s=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)r[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)r[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var u=o[t];for(n=0;n<t.length;n++)r[t][n]=e[u[n]];l=e.alpha}if(r.alpha=Math.max(0,Math.min(1,void 0===l?r.alpha:l)),"alpha"===t)return!1;for(n=0;n<t.length;n++)a=Math.max(0,Math.min(s[t][n],r[t][n])),r[t][n]=Math.round(a);for(var d in o)d!==t&&(r[d]=i[t][d](r[t]));return!0},r.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},r.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=r),e.exports=r},{1:1,4:4}],3:[function(t,e,n){function i(t){var e,n,i=t[0]/255,a=t[1]/255,r=t[2]/255,o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;return s==o?e=0:i==s?e=(a-r)/l:a==s?e=2+(r-i)/l:r==s&&(e=4+(i-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),n=(o+s)/2,[e,100*(s==o?0:n<=.5?l/(s+o):l/(2-s-o)),100*n]}function a(t){var e,n,i=t[0],a=t[1],r=t[2],o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;return n=0==s?0:l/s*1e3/10,s==o?e=0:i==s?e=(a-r)/l:a==s?e=2+(r-i)/l:r==s&&(e=4+(i-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),[e,n,s/255*1e3/10]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],1/255*Math.min(e,Math.min(n,a))*100,100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function s(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255;return[100*((1-n-(e=Math.min(1-n,1-i,1-a)))/(1-e)||0),100*((1-i-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]}function l(t){return S[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e=u(t),n=e[0],i=e[1],a=e[2];return i/=100,a/=108.883,n=(n/=95.047)>.008856?Math.pow(n,1/3):7.787*n+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(n-i),200*(i-(a=a>.008856?Math.pow(a,1/3):7.787*a+16/116))]}function h(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return[r=255*l,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,a[u]=255*(r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e);return a}function c(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r));switch(i*=255,a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),i=6*o-(e=Math.floor(6*o)),0!=(1&e)&&(i=1-i),a=s+i*((n=1-l)-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e=t[1]/100,n=t[2]/100,i=t[3]/100;return[255*(1-Math.min(1,t[0]/100*(1-i)+i)),255*(1-Math.min(1,e*(1-i)+i)),255*(1-Math.min(1,n*(1-i)+i))]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=(e=3.2406*a+-1.5372*r+-.4986*o)>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,[255*(e=Math.min(Math.max(0,e),1)),255*(n=Math.min(Math.max(0,n),1)),255*(i=Math.min(Math.max(0,i),1))]}function v(t){var e=t[0],n=t[1],i=t[2];return n/=100,i/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(e-n),200*(n-(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116))]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),[e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),n,i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3)]}function x(t){var e,n=t[0],i=t[1],a=t[2];return(e=360*Math.atan2(a,i)/2/Math.PI)<0&&(e+=360),[n,Math.sqrt(i*i+a*a),e]}function _(t){return p(y(t))}function k(t){var e,n=t[1];return e=t[2]/360*2*Math.PI,[t[0],n*Math.cos(e),n*Math.sin(e)]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:h,hsl2hsv:function(t){var e=t[1]/100,n=t[2]/100;return 0===n?[0,0,0]:[t[0],2*(e*=(n*=2)<=1?n:2-n)/(n+e)*100,(n+e)/2*100]},hsl2hwb:function(t){return o(h(t))},hsl2cmyk:function(t){return s(h(t))},hsl2keyword:function(t){return l(h(t))},hsv2rgb:c,hsv2hsl:function(t){var e,n,i=t[1]/100,a=t[2]/100;return e=i*a,[t[0],100*(e=(e/=(n=(2-i)*a)<=1?n:2-n)||0),100*(n/=2)]},hsv2hwb:function(t){return o(c(t))},hsv2cmyk:function(t){return s(c(t))},hsv2keyword:function(t){return l(c(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(r)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space;e=a[n][t](this.convs[n]),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{3:3}],5:[function(t,e,n){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(t,e,n){var i;i=function(){"use strict";var n,i;function a(){return n.apply(null,arguments)}function r(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function s(t){return void 0===t}function l(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function u(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function d(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function h(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function c(t,e){for(var n in e)h(e,n)&&(t[n]=e[n]);return h(e,"toString")&&(t.toString=e.toString),h(e,"valueOf")&&(t.valueOf=e.valueOf),t}function f(t,e,n,i){return Te(t,e,n,i,!0).utc()}function g(t){return null==t._pf&&(t._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),t._pf}function m(t){if(null==t._isValid){var e=g(t),n=i.call(e.parsedDateParts,function(t){return null!=t}),a=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.weekdayMismatch&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(a=a&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return a;t._isValid=a}return t._isValid}function p(t){var e=f(NaN);return null!=t?c(g(e),t):g(e).userInvalidated=!0,e}i=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i<n;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1};var v=a.momentProperties=[];function y(t,e){var n,i,a;if(s(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),s(e._i)||(t._i=e._i),s(e._f)||(t._f=e._f),s(e._l)||(t._l=e._l),s(e._strict)||(t._strict=e._strict),s(e._tzm)||(t._tzm=e._tzm),s(e._isUTC)||(t._isUTC=e._isUTC),s(e._offset)||(t._offset=e._offset),s(e._pf)||(t._pf=g(e)),s(e._locale)||(t._locale=e._locale),v.length>0)for(n=0;n<v.length;n++)s(a=e[i=v[n]])||(t[i]=a);return t}var b=!1;function x(t){y(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===b&&(b=!0,a.updateOffset(this),b=!1)}function _(t){return t instanceof x||null!=t&&null!=t._isAMomentObject}function k(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function w(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=k(e)),n}function M(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;i<a;i++)(n&&t[i]!==e[i]||!n&&w(t[i])!==w(e[i]))&&o++;return o+r}function S(t){!1===a.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function D(t,e){var n=!0;return c(function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,t),n){for(var i,r=[],o=0;o<arguments.length;o++){if(i="","object"==typeof arguments[o]){for(var s in i+="\n["+o+"] ",arguments[0])i+=s+": "+arguments[0][s]+", ";i=i.slice(0,-2)}else i=arguments[o];r.push(i)}S(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),n=!1}return e.apply(this,arguments)},e)}var C,P={};function T(t,e){null!=a.deprecationHandler&&a.deprecationHandler(t,e),P[t]||(S(e),P[t]=!0)}function O(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function I(t,e){var n,i=c({},t);for(n in e)h(e,n)&&(o(t[n])&&o(e[n])?(i[n]={},c(i[n],t[n]),c(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);for(n in t)h(t,n)&&!h(e,n)&&o(t[n])&&(i[n]=c({},i[n]));return i}function A(t){null!=t&&this.set(t)}a.suppressDeprecationWarnings=!1,a.deprecationHandler=null,C=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)h(t,e)&&n.push(e);return n};var F={};function R(t,e){var n=t.toLowerCase();F[n]=F[n+"s"]=F[e]=t}function L(t){return"string"==typeof t?F[t]||F[t.toLowerCase()]:void 0}function Y(t){var e,n,i={};for(n in t)h(t,n)&&(e=L(n))&&(i[e]=t[n]);return i}var W={};function N(t,e){W[t]=e}function z(t,e,n){var i=""+Math.abs(t);return(t>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,e-i.length)).toString().substr(1)+i}var V=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,H=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,B={},E={};function j(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(E[t]=a),e&&(E[e[0]]=function(){return z(a.apply(this,arguments),e[1],e[2])}),n&&(E[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function U(t,e){return t.isValid()?(e=G(e,t.localeData()),B[e]=B[e]||function(t){var e,n,i,a=t.match(V);for(e=0,n=a.length;e<n;e++)a[e]=E[a[e]]?E[a[e]]:(i=a[e]).match(/\[[\s\S]/)?i.replace(/^\[|\]$/g,""):i.replace(/\\/g,"");return function(e){var i,r="";for(i=0;i<n;i++)r+=O(a[i])?a[i].call(e,t):a[i];return r}}(e),B[e](t)):t.localeData().invalidDate()}function G(t,e){var n=5;function i(t){return e.longDateFormat(t)||t}for(H.lastIndex=0;n>=0&&H.test(t);)t=t.replace(H,i),H.lastIndex=0,n-=1;return t}var q=/\d/,Z=/\d\d/,$=/\d{3}/,X=/\d{4}/,J=/[+-]?\d{6}/,K=/\d\d?/,Q=/\d\d\d\d?/,tt=/\d\d\d\d\d\d?/,et=/\d{1,3}/,nt=/\d{1,4}/,it=/[+-]?\d{1,6}/,at=/\d+/,rt=/[+-]?\d+/,ot=/Z|[+-]\d\d:?\d\d/gi,st=/Z|[+-]\d\d(?::?\d\d)?/gi,lt=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,ut={};function dt(t,e,n){ut[t]=O(e)?e:function(t,i){return t&&n?n:e}}function ht(t,e){return h(ut,t)?ut[t](e._strict,e._locale):new RegExp(ct(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a})))}function ct(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var ft={};function gt(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),l(e)&&(i=function(t,n){n[e]=w(t)}),n=0;n<t.length;n++)ft[t[n]]=i}function mt(t,e){gt(t,function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)})}function pt(t,e,n){null!=e&&h(ft,t)&&ft[t](e,n._a,n,t)}var vt=0,yt=1,bt=2,xt=3,_t=4,kt=5,wt=6,Mt=7,St=8;function Dt(t){return Ct(t)?366:365}function Ct(t){return t%4==0&&t%100!=0||t%400==0}j("Y",0,0,function(){var t=this.year();return t<=9999?""+t:"+"+t}),j(0,["YY",2],0,function(){return this.year()%100}),j(0,["YYYY",4],0,"year"),j(0,["YYYYY",5],0,"year"),j(0,["YYYYYY",6,!0],0,"year"),R("year","y"),N("year",1),dt("Y",rt),dt("YY",K,Z),dt("YYYY",nt,X),dt("YYYYY",it,J),dt("YYYYYY",it,J),gt(["YYYYY","YYYYYY"],vt),gt("YYYY",function(t,e){e[vt]=2===t.length?a.parseTwoDigitYear(t):w(t)}),gt("YY",function(t,e){e[vt]=a.parseTwoDigitYear(t)}),gt("Y",function(t,e){e[vt]=parseInt(t,10)}),a.parseTwoDigitYear=function(t){return w(t)+(w(t)>68?1900:2e3)};var Pt,Tt=Ot("FullYear",!0);function Ot(t,e){return function(n){return null!=n?(At(this,t,n),a.updateOffset(this,e),this):It(this,t)}}function It(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function At(t,e,n){t.isValid()&&!isNaN(n)&&("FullYear"===e&&Ct(t.year())&&1===t.month()&&29===t.date()?t._d["set"+(t._isUTC?"UTC":"")+e](n,t.month(),Ft(n,t.month())):t._d["set"+(t._isUTC?"UTC":"")+e](n))}function Ft(t,e){if(isNaN(t)||isNaN(e))return NaN;var n=(e%12+12)%12;return t+=(e-n)/12,1===n?Ct(t)?29:28:31-n%7%2}Pt=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},j("M",["MM",2],"Mo",function(){return this.month()+1}),j("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),j("MMMM",0,0,function(t){return this.localeData().months(this,t)}),R("month","M"),N("month",8),dt("M",K),dt("MM",K,Z),dt("MMM",function(t,e){return e.monthsShortRegex(t)}),dt("MMMM",function(t,e){return e.monthsRegex(t)}),gt(["M","MM"],function(t,e){e[yt]=w(t)-1}),gt(["MMM","MMMM"],function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[yt]=a:g(n).invalidMonth=t});var Rt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Lt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Yt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Wt(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=w(e);else if(!l(e=t.localeData().monthsParse(e)))return t;return n=Math.min(t.date(),Ft(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function Nt(t){return null!=t?(Wt(this,t),a.updateOffset(this,!0),this):It(this,"Month")}var zt=lt,Vt=lt;function Ht(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;e<12;e++)n=f([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;e<12;e++)i[e]=ct(i[e]),a[e]=ct(a[e]);for(e=0;e<24;e++)r[e]=ct(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function Bt(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function Et(t,e,n){var i=7+e-n;return-(7+Bt(t,0,i).getUTCDay()-e)%7+i-1}function jt(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+Et(t,i,a);return s<=0?o=Dt(r=t-1)+s:s>Dt(t)?(r=t+1,o=s-Dt(t)):(r=t,o=s),{year:r,dayOfYear:o}}function Ut(t,e,n){var i,a,r=Et(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+Gt(a=t.year()-1,e,n):o>Gt(t.year(),e,n)?(i=o-Gt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function Gt(t,e,n){var i=Et(t,e,n),a=Et(t+1,e,n);return(Dt(t)-i+a)/7}j("w",["ww",2],"wo","week"),j("W",["WW",2],"Wo","isoWeek"),R("week","w"),R("isoWeek","W"),N("week",5),N("isoWeek",5),dt("w",K),dt("ww",K,Z),dt("W",K),dt("WW",K,Z),mt(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=w(t)}),j("d",0,"do","day"),j("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),j("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),j("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),j("e",0,0,"weekday"),j("E",0,0,"isoWeekday"),R("day","d"),R("weekday","e"),R("isoWeekday","E"),N("day",11),N("weekday",11),N("isoWeekday",11),dt("d",K),dt("e",K),dt("E",K),dt("dd",function(t,e){return e.weekdaysMinRegex(t)}),dt("ddd",function(t,e){return e.weekdaysShortRegex(t)}),dt("dddd",function(t,e){return e.weekdaysRegex(t)}),mt(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),mt(["d","e","E"],function(t,e,n,i){e[i]=w(t)});var qt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Zt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),$t="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Xt=lt,Jt=lt,Kt=lt;function Qt(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=f([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=ct(s[e]),l[e]=ct(l[e]),u[e]=ct(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function te(){return this.hours()%12||12}function ee(t,e){j(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function ne(t,e){return e._meridiemParse}j("H",["HH",2],0,"hour"),j("h",["hh",2],0,te),j("k",["kk",2],0,function(){return this.hours()||24}),j("hmm",0,0,function(){return""+te.apply(this)+z(this.minutes(),2)}),j("hmmss",0,0,function(){return""+te.apply(this)+z(this.minutes(),2)+z(this.seconds(),2)}),j("Hmm",0,0,function(){return""+this.hours()+z(this.minutes(),2)}),j("Hmmss",0,0,function(){return""+this.hours()+z(this.minutes(),2)+z(this.seconds(),2)}),ee("a",!0),ee("A",!1),R("hour","h"),N("hour",13),dt("a",ne),dt("A",ne),dt("H",K),dt("h",K),dt("k",K),dt("HH",K,Z),dt("hh",K,Z),dt("kk",K,Z),dt("hmm",Q),dt("hmmss",tt),dt("Hmm",Q),dt("Hmmss",tt),gt(["H","HH"],xt),gt(["k","kk"],function(t,e,n){var i=w(t);e[xt]=24===i?0:i}),gt(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),gt(["h","hh"],function(t,e,n){e[xt]=w(t),g(n).bigHour=!0}),gt("hmm",function(t,e,n){var i=t.length-2;e[xt]=w(t.substr(0,i)),e[_t]=w(t.substr(i)),g(n).bigHour=!0}),gt("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[xt]=w(t.substr(0,i)),e[_t]=w(t.substr(i,2)),e[kt]=w(t.substr(a)),g(n).bigHour=!0}),gt("Hmm",function(t,e,n){var i=t.length-2;e[xt]=w(t.substr(0,i)),e[_t]=w(t.substr(i))}),gt("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[xt]=w(t.substr(0,i)),e[_t]=w(t.substr(i,2)),e[kt]=w(t.substr(a))});var ie,ae=Ot("Hours",!0),re={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Lt,monthsShort:Yt,week:{dow:0,doy:6},weekdays:qt,weekdaysMin:$t,weekdaysShort:Zt,meridiemParse:/[ap]\.?m?\.?/i},oe={},se={};function le(t){return t?t.toLowerCase().replace("_","-"):t}function ue(n){var i=null;if(!oe[n]&&void 0!==e&&e&&e.exports)try{i=ie._abbr,t("./locale/"+n),de(i)}catch(a){}return oe[n]}function de(t,e){var n;return t&&((n=s(e)?ce(t):he(t,e))?ie=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),ie._abbr}function he(t,e){if(null!==e){var n,i=re;if(e.abbr=t,null!=oe[t])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=oe[t]._config;else if(null!=e.parentLocale)if(null!=oe[e.parentLocale])i=oe[e.parentLocale]._config;else{if(null==(n=ue(e.parentLocale)))return se[e.parentLocale]||(se[e.parentLocale]=[]),se[e.parentLocale].push({name:t,config:e}),null;i=n._config}return oe[t]=new A(I(i,e)),se[t]&&se[t].forEach(function(t){he(t.name,t.config)}),de(t),oe[t]}return delete oe[t],null}function ce(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return ie;if(!r(t)){if(e=ue(t))return e;t=[t]}return function(t){for(var e,n,i,a,r=0;r<t.length;){for(e=(a=le(t[r]).split("-")).length,n=(n=le(t[r+1]))?n.split("-"):null;e>0;){if(i=ue(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&M(a,n,!0)>=e-1)break;e--}r++}return ie}(t)}function fe(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[yt]<0||n[yt]>11?yt:n[bt]<1||n[bt]>Ft(n[vt],n[yt])?bt:n[xt]<0||n[xt]>24||24===n[xt]&&(0!==n[_t]||0!==n[kt]||0!==n[wt])?xt:n[_t]<0||n[_t]>59?_t:n[kt]<0||n[kt]>59?kt:n[wt]<0||n[wt]>999?wt:-1,g(t)._overflowDayOfYear&&(e<vt||e>bt)&&(e=bt),g(t)._overflowWeeks&&-1===e&&(e=Mt),g(t)._overflowWeekday&&-1===e&&(e=St),g(t).overflow=e),t}function ge(t,e,n){return null!=t?t:null!=e?e:n}function me(t){var e,n,i,r,o,s=[];if(!t._d){for(i=function(t){var e=new Date(a.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}(t),t._w&&null==t._a[bt]&&null==t._a[yt]&&function(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=ge(e.GG,t._a[vt],Ut(Oe(),1,4).year),i=ge(e.W,1),((a=ge(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=Ut(Oe(),r,o);n=ge(e.gg,t._a[vt],u.year),i=ge(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>Gt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=jt(n,i,a,r,o),t._a[vt]=s.year,t._dayOfYear=s.dayOfYear)}(t),null!=t._dayOfYear&&(o=ge(t._a[vt],i[vt]),(t._dayOfYear>Dt(o)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=Bt(o,0,t._dayOfYear),t._a[yt]=n.getUTCMonth(),t._a[bt]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=i[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[xt]&&0===t._a[_t]&&0===t._a[kt]&&0===t._a[wt]&&(t._nextDay=!0,t._a[xt]=0),t._d=(t._useUTC?Bt:function(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return t<100&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}).apply(null,s),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[xt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(g(t).weekdayMismatch=!0)}}var pe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ve=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ye=/Z|[+-]\d\d(?::?\d\d)?/,be=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],xe=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],_e=/^\/?Date\((\-?\d+)/i;function ke(t){var e,n,i,a,r,o,s=t._i,l=pe.exec(s)||ve.exec(s);if(l){for(g(t).iso=!0,e=0,n=be.length;e<n;e++)if(be[e][1].exec(l[1])){a=be[e][0],i=!1!==be[e][2];break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=xe.length;e<n;e++)if(xe[e][1].exec(l[3])){r=(l[2]||" ")+xe[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!ye.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),Ce(t)}else t._isValid=!1}var we=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Me(t){var e=parseInt(t,10);return e<=49?2e3+e:e<=999?1900+e:e}var Se={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function De(t){var e,n,i,a,r,o,s=we.exec(t._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(s){var l=(e=s[3],n=s[2],i=s[5],a=s[6],r=s[7],o=[Me(s[4]),Yt.indexOf(e),parseInt(n,10),parseInt(i,10),parseInt(a,10)],r&&o.push(parseInt(r,10)),o);if(!function(t,e,n){return!t||Zt.indexOf(t)===new Date(e[0],e[1],e[2]).getDay()||(g(n).weekdayMismatch=!0,n._isValid=!1,!1)}(s[1],l,t))return;t._a=l,t._tzm=function(t,e,n){if(t)return Se[t];if(s[9])return 0;var i=parseInt(s[10],10),a=i%100;return(i-a)/100*60+a}(s[8]),t._d=Bt.apply(null,t._a),t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),g(t).rfc2822=!0}else t._isValid=!1}function Ce(t){if(t._f!==a.ISO_8601)if(t._f!==a.RFC_2822){t._a=[],g(t).empty=!0;var e,n,i,r,o,s=""+t._i,l=s.length,u=0;for(i=G(t._f,t._locale).match(V)||[],e=0;e<i.length;e++)(n=(s.match(ht(r=i[e],t))||[])[0])&&((o=s.substr(0,s.indexOf(n))).length>0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(n)+n.length),u+=n.length),E[r]?(n?g(t).empty=!1:g(t).unusedTokens.push(r),pt(r,n,t)):t._strict&&!n&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[xt]<=12&&!0===g(t).bigHour&&t._a[xt]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[xt]=(d=t._locale,h=t._a[xt],null==(c=t._meridiem)?h:null!=d.meridiemHour?d.meridiemHour(h,c):null!=d.isPM?((f=d.isPM(c))&&h<12&&(h+=12),f||12!==h||(h=0),h):h),me(t),fe(t)}else De(t);else ke(t);var d,h,c,f}function Pe(t){var e=t._i,n=t._f;return t._locale=t._locale||ce(t._l),null===e||void 0===n&&""===e?p({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),_(e)?new x(fe(e)):(u(e)?t._d=e:r(n)?function(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=y({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],Ce(e),m(e)&&(r+=g(e).charsLeftOver,r+=10*g(e).unusedTokens.length,g(e).score=r,(null==i||r<i)&&(i=r,n=e));c(t,n||e)}(t):n?Ce(t):function(t){var e=t._i;s(e)?t._d=new Date(a.now()):u(e)?t._d=new Date(e.valueOf()):"string"==typeof e?function(t){var e=_e.exec(t._i);null===e?(ke(t),!1===t._isValid&&(delete t._isValid,De(t),!1===t._isValid&&(delete t._isValid,a.createFromInputFallback(t)))):t._d=new Date(+e[1])}(t):r(e)?(t._a=d(e.slice(0),function(t){return parseInt(t,10)}),me(t)):o(e)?function(t){if(!t._d){var e=Y(t._i);t._a=d([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),me(t)}}(t):l(e)?t._d=new Date(e):a.createFromInputFallback(t)}(t),m(t)||(t._d=null),t))}function Te(t,e,n,i,a){var s,l={};return!0!==n&&!1!==n||(i=n,n=void 0),(o(t)&&function(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}(t)||r(t)&&0===t.length)&&(t=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=a,l._l=n,l._i=t,l._f=e,l._strict=i,(s=new x(fe(Pe(l))))._nextDay&&(s.add(1,"d"),s._nextDay=void 0),s}function Oe(t,e,n,i){return Te(t,e,n,i,!1)}a.createFromInputFallback=D("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),a.ISO_8601=function(){},a.RFC_2822=function(){};var Ie=D("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Oe.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:p()}),Ae=D("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Oe.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:p()});function Fe(t,e){var n,i;if(1===e.length&&r(e[0])&&(e=e[0]),!e.length)return Oe();for(n=e[0],i=1;i<e.length;++i)e[i].isValid()&&!e[i][t](n)||(n=e[i]);return n}var Re=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Le(t){var e=Y(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||0,o=e.day||0,s=e.hour||0,l=e.minute||0,u=e.second||0,d=e.millisecond||0;this._isValid=function(t){for(var e in t)if(-1===Pt.call(Re,e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,i=0;i<Re.length;++i)if(t[Re[i]]){if(n)return!1;parseFloat(t[Re[i]])!==w(t[Re[i]])&&(n=!0)}return!0}(e),this._milliseconds=+d+1e3*u+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=ce(),this._bubble()}function Ye(t){return t instanceof Le}function We(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function Ne(t,e){j(t,0,0,function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+z(~~(t/60),2)+e+z(~~t%60,2)})}Ne("Z",":"),Ne("ZZ",""),dt("Z",st),dt("ZZ",st),gt(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ve(st,t)});var ze=/([\+\-]|\d\d)/gi;function Ve(t,e){var n=(e||"").match(t);if(null===n)return null;var i=((n[n.length-1]||[])+"").match(ze)||["-",0,0],a=60*i[1]+w(i[2]);return 0===a?0:"+"===i[0]?a:-a}function He(t,e){var n,i;return e._isUTC?(n=e.clone(),i=(_(t)||u(t)?t.valueOf():Oe(t).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+i),a.updateOffset(n,!1),n):Oe(t).local()}function Be(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Ee(){return!!this.isValid()&&this._isUTC&&0===this._offset}a.updateOffset=function(){};var je=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ue=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Ge(t,e){var n,i,a,r,o,s,u=t,d=null;return Ye(t)?u={ms:t._milliseconds,d:t._days,M:t._months}:l(t)?(u={},e?u[e]=t:u.milliseconds=t):(d=je.exec(t))?(n="-"===d[1]?-1:1,u={y:0,d:w(d[bt])*n,h:w(d[xt])*n,m:w(d[_t])*n,s:w(d[kt])*n,ms:w(We(1e3*d[wt]))*n}):(d=Ue.exec(t))?u={y:qe(d[2],n="-"===d[1]?-1:1),M:qe(d[3],n),w:qe(d[4],n),d:qe(d[5],n),h:qe(d[6],n),m:qe(d[7],n),s:qe(d[8],n)}:null==u?u={}:"object"==typeof u&&("from"in u||"to"in u)&&(r=Oe(u.from),o=Oe(u.to),a=r.isValid()&&o.isValid()?(o=He(o,r),r.isBefore(o)?s=Ze(r,o):((s=Ze(o,r)).milliseconds=-s.milliseconds,s.months=-s.months),s):{milliseconds:0,months:0},(u={}).ms=a.milliseconds,u.M=a.months),i=new Le(u),Ye(t)&&h(t,"_locale")&&(i._locale=t._locale),i}function qe(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Ze(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function $e(t,e){return function(n,i){var a;return null===i||isNaN(+i)||(T(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),a=n,n=i,i=a),Xe(this,Ge(n="string"==typeof n?+n:n,i),t),this}}function Xe(t,e,n,i){var r=e._milliseconds,o=We(e._days),s=We(e._months);t.isValid()&&(i=null==i||i,s&&Wt(t,It(t,"Month")+s*n),o&&At(t,"Date",It(t,"Date")+o*n),r&&t._d.setTime(t._d.valueOf()+r*n),i&&a.updateOffset(t,o||s))}Ge.fn=Le.prototype,Ge.invalid=function(){return Ge(NaN)};var Je=$e(1,"add"),Ke=$e(-1,"subtract");function Qe(t,e){var n=12*(e.year()-t.year())+(e.month()-t.month()),i=t.clone().add(n,"months");return-(n+(e-i<0?(e-i)/(i-t.clone().add(n-1,"months")):(e-i)/(t.clone().add(n+1,"months")-i)))||0}function tn(t){var e;return void 0===t?this._locale._abbr:(null!=(e=ce(t))&&(this._locale=e),this)}a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var en=D("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});function nn(){return this._locale}function an(t,e){j(0,[t,t.length],0,e)}function rn(t,e,n,i,a){var r;return null==t?Ut(this,i,a).year:(e>(r=Gt(t,i,a))&&(e=r),(function(t,e,n,i,a){var r=jt(t,e,n,i,a),o=Bt(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}).call(this,t,e,n,i,a))}j(0,["gg",2],0,function(){return this.weekYear()%100}),j(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),R("weekYear","gg"),R("isoWeekYear","GG"),N("weekYear",1),N("isoWeekYear",1),dt("G",rt),dt("g",rt),dt("GG",K,Z),dt("gg",K,Z),dt("GGGG",nt,X),dt("gggg",nt,X),dt("GGGGG",it,J),dt("ggggg",it,J),mt(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=w(t)}),mt(["gg","GG"],function(t,e,n,i){e[i]=a.parseTwoDigitYear(t)}),j("Q",0,"Qo","quarter"),R("quarter","Q"),N("quarter",7),dt("Q",q),gt("Q",function(t,e){e[yt]=3*(w(t)-1)}),j("D",["DD",2],"Do","date"),R("date","D"),N("date",9),dt("D",K),dt("DD",K,Z),dt("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),gt(["D","DD"],bt),gt("Do",function(t,e){e[bt]=w(t.match(K)[0])});var on=Ot("Date",!0);j("DDD",["DDDD",3],"DDDo","dayOfYear"),R("dayOfYear","DDD"),N("dayOfYear",4),dt("DDD",et),dt("DDDD",$),gt(["DDD","DDDD"],function(t,e,n){n._dayOfYear=w(t)}),j("m",["mm",2],0,"minute"),R("minute","m"),N("minute",14),dt("m",K),dt("mm",K,Z),gt(["m","mm"],_t);var sn=Ot("Minutes",!1);j("s",["ss",2],0,"second"),R("second","s"),N("second",15),dt("s",K),dt("ss",K,Z),gt(["s","ss"],kt);var ln,un=Ot("Seconds",!1);for(j("S",0,0,function(){return~~(this.millisecond()/100)}),j(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),j(0,["SSS",3],0,"millisecond"),j(0,["SSSS",4],0,function(){return 10*this.millisecond()}),j(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),j(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),j(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),j(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),j(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),R("millisecond","ms"),N("millisecond",16),dt("S",et,q),dt("SS",et,Z),dt("SSS",et,$),ln="SSSS";ln.length<=9;ln+="S")dt(ln,at);function dn(t,e){e[wt]=w(1e3*("0."+t))}for(ln="S";ln.length<=9;ln+="S")gt(ln,dn);var hn=Ot("Milliseconds",!1);j("z",0,0,"zoneAbbr"),j("zz",0,0,"zoneName");var cn=x.prototype;function fn(t){return t}cn.add=Je,cn.calendar=function(t,e){var n=t||Oe(),i=He(n,this).startOf("day"),r=a.calendarFormat(this,i)||"sameElse",o=e&&(O(e[r])?e[r].call(this,n):e[r]);return this.format(o||this.localeData().calendar(r,this,Oe(n)))},cn.clone=function(){return new x(this)},cn.diff=function(t,e,n){var i,a,r;if(!this.isValid())return NaN;if(!(i=He(t,this)).isValid())return NaN;switch(a=6e4*(i.utcOffset()-this.utcOffset()),e=L(e)){case"year":r=Qe(this,i)/12;break;case"month":r=Qe(this,i);break;case"quarter":r=Qe(this,i)/3;break;case"second":r=(this-i)/1e3;break;case"minute":r=(this-i)/6e4;break;case"hour":r=(this-i)/36e5;break;case"day":r=(this-i-a)/864e5;break;case"week":r=(this-i-a)/6048e5;break;default:r=this-i}return n?r:k(r)},cn.endOf=function(t){return void 0===(t=L(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},cn.format=function(t){t||(t=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var e=U(this,t);return this.localeData().postformat(e)},cn.from=function(t,e){return this.isValid()&&(_(t)&&t.isValid()||Oe(t).isValid())?Ge({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},cn.fromNow=function(t){return this.from(Oe(),t)},cn.to=function(t,e){return this.isValid()&&(_(t)&&t.isValid()||Oe(t).isValid())?Ge({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},cn.toNow=function(t){return this.to(Oe(),t)},cn.get=function(t){return O(this[t=L(t)])?this[t]():this},cn.invalidAt=function(){return g(this).overflow},cn.isAfter=function(t,e){var n=_(t)?t:Oe(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=L(s(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},cn.isBefore=function(t,e){var n=_(t)?t:Oe(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=L(s(e)?"millisecond":e))?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},cn.isBetween=function(t,e,n,i){return("("===(i=i||"()")[0]?this.isAfter(t,n):!this.isBefore(t,n))&&(")"===i[1]?this.isBefore(e,n):!this.isAfter(e,n))},cn.isSame=function(t,e){var n,i=_(t)?t:Oe(t);return!(!this.isValid()||!i.isValid())&&("millisecond"===(e=L(e||"millisecond"))?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},cn.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},cn.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},cn.isValid=function(){return m(this)},cn.lang=en,cn.locale=tn,cn.localeData=nn,cn.max=Ae,cn.min=Ie,cn.parsingFlags=function(){return c({},g(this))},cn.set=function(t,e){if("object"==typeof t)for(var n=function(t){var e=[];for(var n in t)e.push({unit:n,priority:W[n]});return e.sort(function(t,e){return t.priority-e.priority}),e}(t=Y(t)),i=0;i<n.length;i++)this[n[i].unit](t[n[i].unit]);else if(O(this[t=L(t)]))return this[t](e);return this},cn.startOf=function(t){switch(t=L(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},cn.subtract=Ke,cn.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},cn.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},cn.toDate=function(){return new Date(this.valueOf())},cn.toISOString=function(t){if(!this.isValid())return null;var e=!0!==t,n=e?this.clone().utc():this;return n.year()<0||n.year()>9999?U(n,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):O(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",U(n,"Z")):U(n,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},cn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY";return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+e+'[")]')},cn.toJSON=function(){return this.isValid()?this.toISOString():null},cn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},cn.unix=function(){return Math.floor(this.valueOf()/1e3)},cn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},cn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},cn.year=Tt,cn.isLeapYear=function(){return Ct(this.year())},cn.weekYear=function(t){return rn.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},cn.isoWeekYear=function(t){return rn.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},cn.quarter=cn.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},cn.month=Nt,cn.daysInMonth=function(){return Ft(this.year(),this.month())},cn.week=cn.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},cn.isoWeek=cn.isoWeeks=function(t){var e=Ut(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},cn.weeksInYear=function(){var t=this.localeData()._week;return Gt(this.year(),t.dow,t.doy)},cn.isoWeeksInYear=function(){return Gt(this.year(),1,4)},cn.date=on,cn.day=cn.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=function(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}(t,this.localeData()),this.add(t-e,"d")):e},cn.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},cn.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=function(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},cn.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},cn.hour=cn.hours=ae,cn.minute=cn.minutes=sn,cn.second=cn.seconds=un,cn.millisecond=cn.milliseconds=hn,cn.utcOffset=function(t,e,n){var i,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ve(st,t)))return this}else Math.abs(t)<16&&!n&&(t*=60);return!this._isUTC&&e&&(i=Be(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!e||this._changeInProgress?Xe(this,Ge(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Be(this)},cn.utc=function(t){return this.utcOffset(0,t)},cn.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Be(this),"m")),this},cn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ve(ot,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},cn.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Oe(t).utcOffset():0,(this.utcOffset()-t)%60==0)},cn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},cn.isLocal=function(){return!!this.isValid()&&!this._isUTC},cn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},cn.isUtc=Ee,cn.isUTC=Ee,cn.zoneAbbr=function(){return this._isUTC?"UTC":""},cn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},cn.dates=D("dates accessor is deprecated. Use date instead.",on),cn.months=D("months accessor is deprecated. Use month instead",Nt),cn.years=D("years accessor is deprecated. Use year instead",Tt),cn.zone=D("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),cn.isDSTShifted=D("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!s(this._isDSTShifted))return this._isDSTShifted;var t={};if(y(t,this),(t=Pe(t))._a){var e=t._isUTC?f(t._a):Oe(t._a);this._isDSTShifted=this.isValid()&&M(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var gn=A.prototype;function mn(t,e,n,i){var a=ce(),r=f().set(i,e);return a[n](r,t)}function pn(t,e,n){if(l(t)&&(e=t,t=void 0),t=t||"",null!=e)return mn(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=mn(t,i,n,"month");return a}function vn(t,e,n,i){"boolean"==typeof t?(l(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,l(e)&&(n=e,e=void 0),e=e||"");var a,r=ce(),o=t?r._week.dow:0;if(null!=n)return mn(e,(n+o)%7,i,"day");var s=[];for(a=0;a<7;a++)s[a]=mn(e,(a+o)%7,i,"day");return s}gn.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return O(i)?i.call(e,n):i},gn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},gn.invalidDate=function(){return this._invalidDate},gn.ordinal=function(t){return this._ordinal.replace("%d",t)},gn.preparse=fn,gn.postformat=fn,gn.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return O(a)?a(t,e,n,i):a.replace(/%d/i,t)},gn.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return O(n)?n(e):n.replace(/%s/i,e)},gn.set=function(t){var e,n;for(n in t)O(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},gn.months=function(t,e){return t?r(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||Rt).test(e)?"format":"standalone"][t.month()]:r(this._months)?this._months:this._months.standalone},gn.monthsShort=function(t,e){return t?r(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Rt.test(e)?"format":"standalone"][t.month()]:r(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},gn.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return(function(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;i<12;++i)r=f([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(a=Pt.call(this._shortMonthsParse,o))?a:null:-1!==(a=Pt.call(this._longMonthsParse,o))?a:null:"MMM"===e?-1!==(a=Pt.call(this._shortMonthsParse,o))?a:-1!==(a=Pt.call(this._longMonthsParse,o))?a:null:-1!==(a=Pt.call(this._longMonthsParse,o))?a:-1!==(a=Pt.call(this._shortMonthsParse,o))?a:null}).call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=f([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},gn.monthsRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Ht.call(this),t?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=Vt),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},gn.monthsShortRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Ht.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=zt),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},gn.week=function(t){return Ut(t,this._week.dow,this._week.doy).week},gn.firstDayOfYear=function(){return this._week.doy},gn.firstDayOfWeek=function(){return this._week.dow},gn.weekdays=function(t,e){return t?r(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:r(this._weekdays)?this._weekdays:this._weekdays.standalone},gn.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},gn.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},gn.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return(function(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=f([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=Pt.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:null:-1!==(a=Pt.call(this._minWeekdaysParse,o))?a:-1!==(a=Pt.call(this._weekdaysParse,o))?a:-1!==(a=Pt.call(this._shortWeekdaysParse,o))?a:null}).call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=f([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},gn.weekdaysRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Qt.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=Xt),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},gn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Qt.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Jt),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},gn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Qt.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Kt),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},gn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},gn.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},de("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===w(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),a.lang=D("moment.lang is deprecated. Use moment.locale instead.",de),a.langData=D("moment.langData is deprecated. Use moment.localeData instead.",ce);var yn=Math.abs;function bn(t,e,n,i){var a=Ge(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function xn(t){return t<0?Math.floor(t):Math.ceil(t)}function _n(t){return 4800*t/146097}function kn(t){return 146097*t/4800}function wn(t){return function(){return this.as(t)}}var Mn=wn("ms"),Sn=wn("s"),Dn=wn("m"),Cn=wn("h"),Pn=wn("d"),Tn=wn("w"),On=wn("M"),In=wn("y");function An(t){return function(){return this.isValid()?this._data[t]:NaN}}var Fn=An("milliseconds"),Rn=An("seconds"),Ln=An("minutes"),Yn=An("hours"),Wn=An("days"),Nn=An("months"),zn=An("years"),Vn=Math.round,Hn={ss:44,s:45,m:45,h:22,d:26,M:11},Bn=Math.abs;function En(t){return(t>0)-(t<0)||+t}function jn(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n=Bn(this._milliseconds)/1e3,i=Bn(this._days),a=Bn(this._months);t=k(n/60),e=k(t/60),n%=60,t%=60;var r=k(a/12),o=a%=12,s=i,l=e,u=t,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=En(this._months)!==En(h)?"-":"",g=En(this._days)!==En(h)?"-":"",m=En(this._milliseconds)!==En(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(o?f+o+"M":"")+(s?g+s+"D":"")+(l||u||d?"T":"")+(l?m+l+"H":"")+(u?m+u+"M":"")+(d?m+d+"S":"")}var Un=Le.prototype;return Un.isValid=function(){return this._isValid},Un.abs=function(){var t=this._data;return this._milliseconds=yn(this._milliseconds),this._days=yn(this._days),this._months=yn(this._months),t.milliseconds=yn(t.milliseconds),t.seconds=yn(t.seconds),t.minutes=yn(t.minutes),t.hours=yn(t.hours),t.months=yn(t.months),t.years=yn(t.years),this},Un.add=function(t,e){return bn(this,t,e,1)},Un.subtract=function(t,e){return bn(this,t,e,-1)},Un.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=L(t))||"year"===t)return n=this._months+_n(e=this._days+i/864e5),"month"===t?n:n/12;switch(e=this._days+Math.round(kn(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},Un.asMilliseconds=Mn,Un.asSeconds=Sn,Un.asMinutes=Dn,Un.asHours=Cn,Un.asDays=Pn,Un.asWeeks=Tn,Un.asMonths=On,Un.asYears=In,Un.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*w(this._months/12):NaN},Un._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*xn(kn(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=k(r/1e3),l.seconds=t%60,e=k(t/60),l.minutes=e%60,n=k(e/60),l.hours=n%24,o+=k(n/24),s+=a=k(_n(o)),o-=xn(kn(a)),i=k(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},Un.clone=function(){return Ge(this)},Un.get=function(t){return t=L(t),this.isValid()?this[t+"s"]():NaN},Un.milliseconds=Fn,Un.seconds=Rn,Un.minutes=Ln,Un.hours=Yn,Un.days=Wn,Un.weeks=function(){return k(this.days()/7)},Un.months=Nn,Un.years=zn,Un.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=function(t,e,n){var i=Ge(t).abs(),a=Vn(i.as("s")),r=Vn(i.as("m")),o=Vn(i.as("h")),s=Vn(i.as("d")),l=Vn(i.as("M")),u=Vn(i.as("y")),d=a<=Hn.ss&&["s",a]||a<Hn.s&&["ss",a]||r<=1&&["m"]||r<Hn.m&&["mm",r]||o<=1&&["h"]||o<Hn.h&&["hh",o]||s<=1&&["d"]||s<Hn.d&&["dd",s]||l<=1&&["M"]||l<Hn.M&&["MM",l]||u<=1&&["y"]||["yy",u];return d[2]=e,d[3]=+t>0,d[4]=n,(function(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}).apply(null,d)}(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},Un.toISOString=jn,Un.toString=jn,Un.toJSON=jn,Un.locale=tn,Un.localeData=nn,Un.toIsoString=D("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",jn),Un.lang=en,j("X",0,0,"unix"),j("x",0,0,"valueOf"),dt("x",rt),dt("X",/[+-]?\d+(\.\d{1,3})?/),gt("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),gt("x",function(t,e,n){n._d=new Date(w(t))}),a.version="2.22.2",n=Oe,a.fn=cn,a.min=function(){return Fe("isBefore",[].slice.call(arguments,0))},a.max=function(){return Fe("isAfter",[].slice.call(arguments,0))},a.now=function(){return Date.now?Date.now():+new Date},a.utc=f,a.unix=function(t){return Oe(1e3*t)},a.months=function(t,e){return pn(t,e,"months")},a.isDate=u,a.locale=de,a.invalid=p,a.duration=Ge,a.isMoment=_,a.weekdays=function(t,e,n){return vn(t,e,n,"weekdays")},a.parseZone=function(){return Oe.apply(null,arguments).parseZone()},a.localeData=ce,a.isDuration=Ye,a.monthsShort=function(t,e){return pn(t,e,"monthsShort")},a.weekdaysMin=function(t,e,n){return vn(t,e,n,"weekdaysMin")},a.defineLocale=he,a.updateLocale=function(t,e){if(null!=e){var n,i,a=re;null!=(i=ue(t))&&(a=i._config),(n=new A(e=I(a,e))).parentLocale=oe[t],oe[t]=n,de(t)}else null!=oe[t]&&(null!=oe[t].parentLocale?oe[t]=oe[t].parentLocale:null!=oe[t]&&delete oe[t]);return oe[t]},a.locales=function(){return C(oe)},a.weekdaysShort=function(t,e,n){return vn(t,e,n,"weekdaysShort")},a.normalizeUnits=L,a.relativeTimeRounding=function(t){return void 0===t?Vn:"function"==typeof t&&(Vn=t,!0)},a.relativeTimeThreshold=function(t,e){return void 0!==Hn[t]&&(void 0===e?Hn[t]:(Hn[t]=e,"s"===t&&(Hn.ss=e-1),!0))},a.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},a.prototype=cn,a.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"YYYY-[W]WW",MONTH:"YYYY-MM"},a},"object"==typeof n&&void 0!==e?e.exports=i():this.moment=i()},{}],7:[function(t,e,n){var i=t(30)();i.helpers=t(46),t(28)(i),i.Animation=t(22),i.animationService=t(23),i.defaults=t(26),i.Element=t(27),i.elements=t(41),i.Interaction=t(29),i.layouts=t(31),i.platform=t(49),i.plugins=t(32),i.Scale=t(33),i.scaleService=t(34),i.Ticks=t(35),i.Tooltip=t(36),t(24)(i),t(25)(i),t(56)(i),t(54)(i),t(55)(i),t(57)(i),t(58)(i),t(59)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=t(50);for(var r in a)a.hasOwnProperty(r)&&i.plugins.register(a[r]);i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.Legend=a.legend._element,i.Title=a.title._element,i.pluginService=i.plugins,i.PluginBase=i.Element.extend({}),i.canvasHelpers=i.helpers.canvas,i.layoutService=i.layouts},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,41:41,46:46,49:49,50:50,54:54,55:55,56:56,57:57,58:58,59:59,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e;t.DatasetController.prototype.initialize.apply(this,arguments),(e=this.getMeta()).stack=this.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,n=i.length;e<n;++e)this.updateElement(i[e],e,t)},updateElement:function(t,e,n){var i=this,a=i.chart,o=i.getMeta(),s=i.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=i.getScaleForId(o.xAxisID),t._yScale=i.getScaleForId(o.yAxisID),t._datasetIndex=i.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:r.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:r.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:r.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},i.updateElementGeometry(t,e,n),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,r=i.getValueScale(),o=r.getBasePixel(),s=r.isHorizontal(),l=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,l);a.horizontal=s,a.base=n?o:u.base,a.x=s?n?o:u.head:d.center,a.y=s?d.center:n?o:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},_getStacks:function(t){var e,n,i=this.chart,a=this.getIndexScale().options.stacked,r=void 0===t?i.data.datasets.length:t+1,o=[];for(e=0;e<r;++e)(n=i.getDatasetMeta(e)).bar&&i.isDatasetVisible(e)&&(!1===a||!0===a&&-1===o.indexOf(n.stack)||void 0===a&&(void 0===n.stack||-1===o.indexOf(n.stack)))&&o.push(n.stack);return o},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var n=this._getStacks(t),i=void 0!==e?n.indexOf(e):-1;return-1===i?n.length-1:i},getRuler:function(){var t,e,n=this.getIndexScale(),i=this.getStackCount(),a=this.index,o=n.isHorizontal(),s=o?n.left:n.top,l=s+(o?n.width:n.height),u=[];for(t=0,e=this.getMeta().data.length;t<e;++t)u.push(n.getPixelForValue(null,t,a));return{min:r.isNullOrUndef(n.options.barThickness)?function(t,e){var n,i,a,r,o=t.isHorizontal()?t.width:t.height,s=t.getTicks();for(a=1,r=e.length;a<r;++a)o=Math.min(o,e[a]-e[a-1]);for(a=0,r=s.length;a<r;++a)i=t.getPixelForTick(a),o=a>0?Math.min(o,i-n):o,n=i;return o}(n,u):-1,pixels:u,start:s,end:l,stackCount:i,scale:n}},calculateBarValuePixels:function(t,e){var n,i,a,r,o,s,l=this.chart,u=this.getMeta(),d=this.getValueScale(),h=l.data.datasets,c=d.getRightValue(h[t].data[e]),f=d.options.stacked,g=u.stack,m=0;if(f||void 0===f&&void 0!==g)for(n=0;n<t;++n)(i=l.getDatasetMeta(n)).bar&&i.stack===g&&i.controller.getValueScaleId()===d.id&&l.isDatasetVisible(n)&&(a=d.getRightValue(h[n].data[e]),(c<0&&a<0||c>=0&&a>0)&&(m+=a));return r=d.getPixelForValue(m),{size:s=((o=d.getPixelForValue(m+c))-r)/2,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i=n.scale.options,a="flex"===i.barThickness?function(t,e,n){var i=e.pixels,a=i[t],r=t>0?i[t-1]:null,o=t<i.length-1?i[t+1]:null,s=n.categoryPercentage;return null===r&&(r=a-(null===o?e.end-a:o-a)),null===o&&(o=a+a-r),{chunk:(o-r)/2*s/e.stackCount,ratio:n.barPercentage,start:a-(a-r)/2*s}}(e,n,i):function(t,e,n){var i,a,o=n.barThickness,s=e.stackCount,l=e.pixels[t];return r.isNullOrUndef(o)?(i=e.min*n.categoryPercentage,a=n.barPercentage):(i=o*s,a=1),{chunk:i/s,ratio:a,start:l-i/2}}(e,n,i),o=this.getStackIndex(t,this.getMeta().stack),s=a.start+a.chunk*o+a.chunk/2,l=Math.min(r.valueOrDefault(i.maxBarThickness,1/0),a.chunk*a.ratio);return{base:s-l/2,head:s+l/2,center:s,size:l}},draw:function(){var t=this.chart,e=this.getValueScale(),n=this.getMeta().data,i=this.getDataset(),a=n.length,o=0;for(r.canvas.clipArea(t.ctx,t.chartArea);o<a;++o)isNaN(e.getRightValue(i.data[o]))||n[o].draw();r.canvas.unclipArea(t.ctx)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{26:26,41:41,46:46}],16:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": ("+t.xLabel+", "+t.yLabel+", "+e.datasets[t.datasetIndex].data[t.index].r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,n=e.getMeta();r.each(n.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.getMeta(),r=t.custom||{},o=i.getScaleForId(a.xAxisID),s=i.getScaleForId(a.yAxisID),l=i._resolveElementOptions(t,e),u=i.getDataset().data[e],d=i.index,h=n?o.getPixelForDecimal(.5):o.getPixelForValue("object"==typeof u?u:NaN,e,d),c=n?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=o,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,rotation:l.rotation,radius:n?0:l.radius,skip:r.skip||isNaN(h)||isNaN(c),x:h,y:c},t.pivot()},setHoverStyle:function(t){var e=t._model,n=t._options;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth,radius:e.radius},e.backgroundColor=r.valueOrDefault(n.hoverBackgroundColor,r.getHoverColor(n.backgroundColor)),e.borderColor=r.valueOrDefault(n.hoverBorderColor,r.getHoverColor(n.borderColor)),e.borderWidth=r.valueOrDefault(n.hoverBorderWidth,n.borderWidth),e.radius=n.radius+n.hoverRadius},_resolveElementOptions:function(t,e){var n,i,a,o=this.chart,s=o.data.datasets[this.index],l=t.custom||{},u=o.options.elements.point,d=r.options.resolve,h=s.data[e],c={},f={chart:o,dataIndex:e,dataset:s,datasetIndex:this.index},g=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle","rotation"];for(n=0,i=g.length;n<i;++n)c[a=g[n]]=d([l[a],s[a],u[a]],f,e);return c.radius=d([l.radius,h?h.r:void 0,s.radius,u.radius],f,e),c}})}},{26:26,41:41,46:46}],17:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r]&&(a.data[r].hidden=!a.data[r].hidden);o.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.labels[t.index],i=": "+e.datasets[t.datasetIndex].data[t.index];return r.isArray(n)?(n=n.slice())[0]+=i:n+=i,n}}}}),i._set("pie",r.clone(i.doughnut)),i._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var e=this,n=e.chart,i=n.chartArea,a=n.options,o=a.elements.arc,s=i.right-i.left-o.borderWidth,l=i.bottom-i.top-o.borderWidth,u=Math.min(s,l),d={x:0,y:0},h=e.getMeta(),c=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),m=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=c/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(h.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(c?n.outerRadius/100*c:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,h.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(h.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,h=s.rotation,c=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI));r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:h,endAngle:c,circumference:g,outerRadius:n&&l.animateScale?0:i.outerRadius,innerRadius:n&&l.animateScale?0:i.innerRadius,label:(0,r.valueAtIndexOrDefault)(f.label,e,a.data.labels[e])}});var m=t._model,p=t.custom||{},v=r.valueAtIndexOrDefault,y=this.chart.options.elements.arc;m.backgroundColor=p.backgroundColor?p.backgroundColor:v(f.backgroundColor,e,y.backgroundColor),m.borderColor=p.borderColor?p.borderColor:v(f.borderColor,e,y.borderColor),m.borderWidth=p.borderWidth?p.borderWidth:v(f.borderWidth,e,y.borderWidth),n&&l.animateRotate||(m.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,m.endAngle=m.startAngle+m.circumference),t.pivot()},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o<r;o++)i=(n=t[o]._chart?t[o]._chart.config.data.datasets[a].hoverBorderWidth:0)>(i=(e=t[o]._model?t[o]._model.borderWidth:0)>i?e:i)?n:i;return i}})}},{26:26,41:41,46:46}],18:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,h=d.elements.line,c=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=c,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,h.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||h.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||h.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||h.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||h.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||h.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||h.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||h.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:h.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,h.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,h.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n<i;++n)o.updateElement(u[n],n,t);for(g&&0!==l._model.tension&&o.updateBezierControlPoints(),n=0,i=u.length;n<i;++n)u[n].pivot()},getPointBackgroundColor:function(t,e){var n=this.chart.options.elements.point.backgroundColor,i=this.getDataset(),a=t.custom||{};return a.backgroundColor?n=a.backgroundColor:i.pointBackgroundColor?n=r.valueAtIndexOrDefault(i.pointBackgroundColor,e,n):i.backgroundColor&&(n=i.backgroundColor),n},getPointBorderColor:function(t,e){var n=this.chart.options.elements.point.borderColor,i=this.getDataset(),a=t.custom||{};return a.borderColor?n=a.borderColor:i.pointBorderColor?n=r.valueAtIndexOrDefault(i.pointBorderColor,e,n):i.borderColor&&(n=i.borderColor),n},getPointBorderWidth:function(t,e){var n=this.chart.options.elements.point.borderWidth,i=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(i.pointBorderWidth)||r.isArray(i.pointBorderWidth)?n=r.valueAtIndexOrDefault(i.pointBorderWidth,e,n):isNaN(i.borderWidth)||(n=i.borderWidth):n=a.borderWidth,n},getPointRotation:function(t,e){var n=this.chart.options.elements.point.rotation,i=this.getDataset(),a=t.custom||{};return isNaN(a.rotation)?isNaN(i.pointRotation)&&!r.isArray(i.pointRotation)||(n=r.valueAtIndexOrDefault(i.pointRotation,e,n)):n=a.rotation,n},updateElement:function(t,e,n){var i,a,o=this,s=o.getMeta(),l=t.custom||{},u=o.getDataset(),d=o.index,h=u.data[e],c=o.getScaleForId(s.yAxisID),f=o.getScaleForId(s.xAxisID),g=o.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),i=f.getPixelForValue("object"==typeof h?h:NaN,e,d),a=n?c.getBasePixel():o.calculatePointY(h,e,d),t._xScale=f,t._yScale=c,t._datasetIndex=d,t._index=e,t._model={x:i,y:a,skip:l.skip||isNaN(i)||isNaN(a),radius:l.radius||r.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||r.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),rotation:o.getPointRotation(t,e),backgroundColor:o.getPointBackgroundColor(t,e),borderColor:o.getPointBorderColor(t,e),borderWidth:o.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||r.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,r,o=this.chart,s=this.getMeta(),l=this.getScaleForId(s.yAxisID),u=0,d=0;if(l.options.stacked){for(i=0;i<n;i++)if(a=o.data.datasets[i],"line"===(r=o.getDatasetMeta(i)).type&&r.yAxisID===l.id&&o.isDatasetVisible(i)){var h=Number(l.getRightValue(a.data[e]));h<0?d+=h||0:u+=h||0}var c=Number(l.getRightValue(t));return l.getPixelForValue(c<0?d+c:u+c)}return l.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,n,i,a=this.getMeta(),o=this.chart.chartArea,s=a.data||[];function l(t,e,n){return Math.max(Math.min(t,n),e)}if(a.dataset._model.spanGaps&&(s=s.filter(function(t){return!t._model.skip})),"monotone"===a.dataset._model.cubicInterpolationMode)r.splineCurveMonotone(s);else for(t=0,e=s.length;t<e;++t)n=s[t]._model,i=r.splineCurve(r.previousItem(s,t)._model,n,r.nextItem(s,t)._model,a.dataset._model.tension),n.controlPointPreviousX=i.previous.x,n.controlPointPreviousY=i.previous.y,n.controlPointNextX=i.next.x,n.controlPointNextY=i.next.y;if(this.chart.options.elements.line.capBezierPoints)for(t=0,e=s.length;t<e;++t)(n=s[t]._model).controlPointPreviousX=l(n.controlPointPreviousX,o.left,o.right),n.controlPointPreviousY=l(n.controlPointPreviousY,o.top,o.bottom),n.controlPointNextX=l(n.controlPointNextX,o.left,o.right),n.controlPointNextY=l(n.controlPointNextY,o.top,o.bottom)},draw:function(){var t,n=this.chart,i=this.getMeta(),a=i.data||[],o=n.chartArea,s=a.length,l=0;for(e(this.getDataset(),n.options)&&(r.canvas.clipArea(n.ctx,{left:o.left,right:o.right,top:o.top-(t=(i.dataset._model.borderWidth||0)/2),bottom:o.bottom+t}),i.dataset.draw(),r.canvas.unclipArea(n.ctx));l<s;++l)a[l].draw(o)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,i=t.custom||{},a=t._model;t.$previousStyle={backgroundColor:a.backgroundColor,borderColor:a.borderColor,borderWidth:a.borderWidth,radius:a.radius},a.backgroundColor=i.hoverBackgroundColor||r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,r.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor||r.valueAtIndexOrDefault(e.pointHoverBorderColor,n,r.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth||r.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth),a.radius=i.hoverRadius||r.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius)}})}},{26:26,41:41,46:46}],19:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n<i;++n)(a=o.getDatasetMeta(n)).data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:r.noop,update:function(t){var e,n,i,a=this,o=a.getDataset(),s=a.getMeta(),l=a.chart.options.startAngle||0,u=a._starts=[],d=a._angles=[];for(a._updateRadius(),s.count=a.countVisibleElements(),e=0,n=o.data.length;e<n;e++)u[e]=l,i=a._computeAngle(e),d[e]=i,l+=i;r.each(s.data,function(e,n){a.updateElement(e,n,t)})},_updateRadius:function(){var t=this,e=t.chart,n=e.chartArea,i=e.options,a=i.elements.arc,r=Math.min(n.right-n.left,n.bottom-n.top);e.outerRadius=Math.max((r-a.borderWidth/2)/2,0),e.innerRadius=Math.max(i.cutoutPercentage?e.outerRadius/100*i.cutoutPercentage:1,0),e.radiusLength=(e.outerRadius-e.innerRadius)/e.getVisibleDatasetCount(),t.outerRadius=e.outerRadius-e.radiusLength*t.index,t.innerRadius=t.outerRadius-e.radiusLength},updateElement:function(t,e,n){var i=this,a=i.chart,o=i.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,h=u.xCenter,c=u.yCenter,f=s.startAngle,g=t.hidden?0:u.getDistanceFromCenterForValue(o.data[e]),m=i._starts[e],p=m+(t.hidden?0:i._angles[e]),v=l.animateScale?0:u.getDistanceFromCenterForValue(o.data[e]);r.extend(t,{_datasetIndex:i.index,_index:e,_scale:u,_model:{x:h,y:c,innerRadius:0,outerRadius:n?v:g,startAngle:n&&l.animateRotate?f:m,endAngle:n&&l.animateRotate?f:p,label:r.valueAtIndexOrDefault(d,e,d[e])}});var y=this.chart.options.elements.arc,b=t.custom||{},x=r.valueAtIndexOrDefault,_=t._model;_.backgroundColor=b.backgroundColor?b.backgroundColor:x(o.backgroundColor,e,y.backgroundColor),_.borderColor=b.borderColor?b.borderColor:x(o.borderColor,e,y.borderColor),_.borderWidth=b.borderWidth?b.borderWidth:x(o.borderWidth,e,y.borderWidth),t.pivot()},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),n=0;return r.each(e.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},_computeAngle:function(t){var e=this,n=this.getMeta().count,i=e.getDataset(),a=e.getMeta();return isNaN(i.data[t])||a.data[t].hidden?0:r.options.resolve([e.chart.options.elements.arc.angle,2*Math.PI/n],{chart:e.chart,dataIndex:t,dataset:i,datasetIndex:e.index},t)}})}},{26:26,41:41,46:46}],20:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.data,a=n.dataset.custom||{},o=e.getDataset(),s=e.chart.options.elements.line,l=e.chart.scale;void 0!==o.tension&&void 0===o.lineTension&&(o.lineTension=o.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:l,_children:i,_loop:!0,_model:{tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,s.tension),backgroundColor:a.backgroundColor?a.backgroundColor:o.backgroundColor||s.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:o.borderWidth||s.borderWidth,borderColor:a.borderColor?a.borderColor:o.borderColor||s.borderColor,fill:a.fill?a.fill:void 0!==o.fill?o.fill:s.fill,borderCapStyle:a.borderCapStyle?a.borderCapStyle:o.borderCapStyle||s.borderCapStyle,borderDash:a.borderDash?a.borderDash:o.borderDash||s.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:o.borderDashOffset||s.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:o.borderJoinStyle||s.borderJoinStyle}}),n.dataset.pivot(),r.each(i,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),rotation:a.rotation?a.rotation:r.valueAtIndexOrDefault(o.pointRotation,e,l.rotation),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;t.$previousStyle={backgroundColor:a.backgroundColor,borderColor:a.borderColor,borderWidth:a.borderWidth,radius:a.radius},a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)}})}},{26:26,41:41,46:46}],21:[function(t,e,n){"use strict";t(26)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{26:26}],22:[function(t,e,n){"use strict";var i=t(27);n=e.exports=i.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),Object.defineProperty(n.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(n.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})},{27:27}],23:[function(t,e,n){"use strict";var i=t(26),a=t(46);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:a.noop,onComplete:a.noop}}),e.exports={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a<r;++a)if(o[a].chart===t)return void(o[a]=e);o.push(e),1===o.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=a.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=a.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,r=0;r<i.length;)n=(e=i[r]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),a.callback(e.render,[n,e],n),a.callback(e.onAnimationProgress,[e],n),e.currentStep>=e.numSteps?(a.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(r,1)):++r}}},{26:26,46:46}],24:[function(t,e,n){"use strict";var i=t(22),a=t(23),r=t(26),o=t(46),s=t(29),l=t(31),u=t(49),d=t(32),h=t(34),c=t(36);e.exports=function(t){function e(t){return"top"===t||"bottom"===t}t.types={},t.instances={},t.controllers={},o.extend(t.prototype,{construct:function(e,n){var i=this;n=function(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=o.configMerge(r.global,r[t.type],t.options||{}),t}(n);var a=u.acquireContext(e,n),s=a&&a.canvas,l=s&&s.height,d=s&&s.width;i.id=o.uid(),i.ctx=a,i.canvas=s,i.config=n,i.width=d,i.height=l,i.aspectRatio=l?d/l:null,i.options=n.options,i._bufferedRender=!1,i.chart=i,i.controller=i,t.instances[i.id]=i,Object.defineProperty(i,"data",{get:function(){return i.config.data},set:function(t){i.config.data=t}}),a&&s?(i.initialize(),i.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return d.notify(t,"beforeInit"),o.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),d.notify(t,"afterInit"),t},clear:function(){return o.canvas.clear(this),this},stop:function(){return a.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(o.getMaximumWidth(i))),s=Math.max(0,Math.floor(a?r/a:o.getMaximumHeight(i)));if((e.width!==r||e.height!==s)&&(i.width=e.width=r,i.height=e.height=s,i.style.width=r+"px",i.style.height=s+"px",o.retinaScale(e,n.devicePixelRatio),!t)){var l={width:r,height:s};d.notify(e,"resize",[l]),e.options.onResize&&e.options.onResize(e,l),e.stop(),e.update({duration:e.options.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;o.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),o.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var t=this,n=t.options,i=t.scales||{},a=[],r=Object.keys(i).reduce(function(t,e){return t[e]=!1,t},{});n.scales&&(a=a.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&a.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),o.each(a,function(n){var a=n.options,s=a.id,l=o.valueOrDefault(a.type,n.dtype);e(a.position)!==e(n.dposition)&&(a.position=n.dposition),r[s]=!0;var u=null;if(s in i&&i[s].type===l)(u=i[s]).options=a,u.ctx=t.ctx,u.chart=t;else{var d=h.getScaleConstructor(l);if(!d)return;u=new d({id:s,type:l,options:a,ctx:t.ctx,chart:t}),i[u.id]=u}u.mergeTicksOptions(),n.isDefault&&(t.scale=u)}),o.each(r,function(t,e){t||delete i[e]}),t.scales=i,h.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return o.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r),o.controller.linkScales();else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;o.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(e){var n,i,a=this;if(e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]}),i=(n=a).options,o.each(n.scales,function(t){l.removeBox(n,t)}),i=o.configMerge(t.defaults.global,t.defaults[n.config.type],i),n.options=n.config.options=i,n.ensureScalesHaveIDs(),n.buildOrUpdateScales(),n.tooltip._options=i.tooltips,n.tooltip.initialize(),d._invalidate(a),!1!==d.notify(a,"beforeUpdate")){a.tooltip._data=a.data;var r=a.buildOrUpdateControllers();o.each(a.data.datasets,function(t,e){a.getDatasetMeta(e).controller.buildOrUpdateElements()},a),a.updateLayout(),a.options.animation&&a.options.animation.duration&&o.each(r,function(t){t.reset()}),a.updateDatasets(),a.tooltip.initialize(),a.lastActive=[],d.notify(a,"afterUpdate"),a._bufferedRender?a._bufferedRequest={duration:e.duration,easing:e.easing,lazy:e.lazy}:a.render(e)}},updateLayout:function(){!1!==d.notify(this,"beforeLayout")&&(l.update(this,this.width,this.height),d.notify(this,"afterScaleUpdate"),d.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==d.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);d.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),n={meta:e,index:t};!1!==d.notify(this,"beforeDatasetUpdate",[n])&&(e.controller.update(),d.notify(this,"afterDatasetUpdate",[n]))},render:function(t){var e=this;t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]});var n=t.duration,r=t.lazy;if(!1!==d.notify(e,"beforeRender")){var s=e.options.animation,l=function(t){d.notify(e,"afterRender"),o.callback(s&&s.onComplete,[t],e)};if(s&&(void 0!==n&&0!==n||void 0===n&&0!==s.duration)){var u=new i({numSteps:(n||s.duration)/16.66,easing:t.easing||s.easing,render:function(t,e){var n=e.currentStep,i=n/e.numSteps;t.draw((0,o.easing.effects[e.easing])(i),i,n)},onAnimationProgress:s.onProgress,onAnimationComplete:l});a.addAnimation(e,u,n,r)}else e.draw(),l(new i({numSteps:0,chart:e}));return e}},draw:function(t){var e=this;e.clear(),o.isNullOrUndef(t)&&(t=1),e.transition(t),e.width<=0||e.height<=0||!1!==d.notify(e,"beforeDraw",[t])&&(o.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e._drawTooltip(t),d.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=0,n=(this.data.datasets||[]).length;e<n;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==d.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);d.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this.getDatasetMeta(t),i={meta:n,index:t,easingValue:e};!1!==d.notify(this,"beforeDatasetDraw",[i])&&(n.controller.draw(e),d.notify(this,"afterDatasetDraw",[i]))},_drawTooltip:function(t){var e=this.tooltip,n={tooltip:e,easingValue:t};!1!==d.notify(this,"beforeTooltipDraw",[n])&&(e.draw(),d.notify(this,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return s.modes.single(this,t)},getElementsAtEvent:function(t){return s.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return s.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=s.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return s.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var n=e._meta[this.id];return n||(n=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),n},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,n=this.data.datasets[t],i=n._meta&&n._meta[e];i&&(i.controller.destroy(),delete n._meta[e])},destroy:function(){var e,n,i=this,a=i.canvas;for(i.stop(),e=0,n=i.data.datasets.length;e<n;++e)i.destroyDatasetMeta(e);a&&(i.unbindEvents(),o.canvas.clear(i),u.releaseContext(i.ctx),i.canvas=null,i.ctx=null),d.notify(i,"destroy"),delete t.instances[i.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var t=this;t.tooltip=new c({_chart:t,_chartInstance:t,_data:t.data,_options:t.options.tooltips},t)},bindEvents:function(){var t=this,e=t._listeners={},n=function(){t.eventHandler.apply(t,arguments)};o.each(t.options.events,function(i){u.addEventListener(t,i,n),e[i]=n}),t.options.responsive&&(n=function(){t.resize()},u.addEventListener(t,"resize",n),e.resize=n)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,o.each(e,function(e,n){u.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"setHoverStyle":"removeHoverStyle";for(a=0,r=t.length;a<r;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[o](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==d.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var i=e.handleEvent(t);n&&(i=n._start?n.handleEvent(t):i|n.handleEvent(t)),d.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):i&&!e.animating&&(e.stop(),e.render({duration:e.options.hover.animationDuration,lazy:!0})),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,n=this,i=n.options||{},a=i.hover;return n.lastActive=n.lastActive||[],n.active="mouseout"===t.type?[]:n.getElementsAtEventForMode(t,a.mode,a),o.callback(i.onHover||i.hover.onHover,[t.native,n.active],n),"mouseup"!==t.type&&"click"!==t.type||i.onClick&&i.onClick.call(n,t.native,n.active),n.lastActive.length&&n.updateHoverStyle(n.lastActive,a.mode,!1),n.active.length&&a.mode&&n.updateHoverStyle(n.active,a.mode,!0),e=!o.arrayEquals(n.active,n.lastActive),n.lastActive=n.active,e}}),t.Controller=t}},{22:22,23:23,26:26,29:29,31:31,32:32,34:34,36:36,46:46,49:49}],25:[function(t,e,n){"use strict";var i=t(46);e.exports=function(t){var e=["push","pop","shift","splice","unshift"];function n(t,n){var i=t._chartjs;if(i){var a=i.listeners,r=a.indexOf(n);-1!==r&&a.splice(r,1),a.length>0||(e.forEach(function(e){delete t[e]}),delete t._chartjs)}}t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null!==e.xAxisID&&e.xAxisID in t.chart.scales||(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null!==e.yAxisID&&e.yAxisID in t.chart.scales||(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,n=this.getMeta(),i=this.getDataset().data||[],a=n.data;for(t=0,e=i.length;t<e;++t)a[t]=a[t]||this.createMetaData(t);n.dataset=n.dataset||this.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t,a,r=this,o=r.getDataset(),s=o.data||(o.data=[]);r._data!==s&&(r._data&&n(r._data,r),a=r,(t=s)._chartjs?t._chartjs.listeners.push(a):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[a]}}),e.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),r=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),r}})})),r._data=s),r.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t){i.merge(t._model,t.$previousStyle||{}),delete t.$previousStyle},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=i.valueAtIndexOrDefault,o=i.getHoverColor,s=t._model;t.$previousStyle={backgroundColor:s.backgroundColor,borderColor:s.borderColor,borderWidth:s.borderWidth},s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:r(e.hoverBackgroundColor,n,o(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:r(e.hoverBorderColor,n,o(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:r(e.hoverBorderWidth,n,s.borderWidth)},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,n=t.data.length,i=e.length;i<n?t.data.splice(i,n-i):i>n&&this.insertElements(n,i-n)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{46:46}],26:[function(t,e,n){"use strict";var i=t(46);e.exports={_set:function(t,e){return i.merge(this[t]||(this[t]={}),e)}}},{46:46}],27:[function(t,e,n){"use strict";var i=t(2),a=t(46),r=function(t){a.extend(this,t),this.initialize.apply(this,arguments)};a.extend(r.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=a.clone(t._model)),t._start={},t},transition:function(t){var e=this,n=e._model,a=e._start,r=e._view;return n&&1!==t?(r||(r=e._view={}),a||(a=e._start={}),function(t,e,n,a){var r,o,s,l,u,d,h,c,f,g=Object.keys(n);for(r=0,o=g.length;r<o;++r)if(d=n[s=g[r]],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),(h=typeof d)==typeof(u=t[s]))if("string"===h){if((c=i(u)).valid&&(f=i(d)).valid){e[s]=f.mix(c,a).rgbString();continue}}else if("number"===h&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*a;continue}e[s]=d}}(a,r,n,t),e):(e._view=n,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return a.isNumber(this._model.x)&&a.isNumber(this._model.y)}}),r.extend=a.inherits,e.exports=r},{2:2,46:46}],28:[function(t,e,n){"use strict";var i=t(2),a=t(26),r=t(46),o=t(34);e.exports=function(){function t(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function e(t){return null!=t&&"none"!==t}function n(n,i,a){var o=document.defaultView,s=r._getParentNode(n),l=o.getComputedStyle(n)[i],u=o.getComputedStyle(s)[i],d=e(l),h=e(u),c=Number.POSITIVE_INFINITY;return d||h?Math.min(d?t(l,n,a):c,h?t(u,s,a):c):"none"}r.configMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(t,e,n,i){var a=e[t]||{},s=n[t];"scales"===t?e[t]=r.scaleMerge(a,s):"scale"===t?e[t]=r.merge(a,[o.getScaleDefaults(s.type),s]):r._merger(t,e,n,i)}})},r.scaleMerge=function(){return r.merge(r.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(t,e,n,i){if("xAxes"===t||"yAxes"===t){var a,s,l,u=n[t].length;for(e[t]||(e[t]=[]),a=0;a<u;++a)s=r.valueOrDefault((l=n[t][a]).type,"xAxes"===t?"category":"linear"),a>=e[t].length&&e[t].push({}),r.merge(e[t][a],!e[t][a].type||l.type&&l.type!==e[t][a].type?[o.getScaleDefaults(s),l]:l)}else r._merger(t,e,n,i)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},r.findNextWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},r.findPreviousWhere=function(t,e,n){r.isNullOrUndef(n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)<n},r.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){var e=Math.log(t)*Math.LOG10E,n=Math.round(e);return t===Math.pow(10,n)?n:e},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),h=i*(u=isNaN(u)?0:u),c=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-h*(o.x-a.x),y:r.y-h*(o.y-a.y)},next:{x:r.x+c*(o.x-a.x),y:r.y+c*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o,s,l,u,d,h=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),c=h.length;for(e=0;e<c;++e)if(!(i=h[e]).model.skip){if(n=e>0?h[e-1]:null,(a=e<c-1?h[e+1]:null)&&!a.model.skip){var f=a.model.x-i.model.x;i.deltaK=0!==f?(a.model.y-i.model.y)/f:0}i.mK=!n||n.model.skip?i.deltaK:!a||a.model.skip?n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?0:(n.deltaK+i.deltaK)/2}for(e=0;e<c-1;++e)a=h[e+1],(i=h[e]).model.skip||a.model.skip||(r.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(o=i.mK/i.deltaK,s=a.mK/i.deltaK,(u=Math.pow(o,2)+Math.pow(s,2))<=9||(l=3/Math.sqrt(u),i.mK=o*l*i.deltaK,a.mK=s*l*i.deltaK)));for(e=0;e<c;++e)(i=h[e]).model.skip||(a=e<c-1?h[e+1]:null,(n=e>0?h[e-1]:null)&&!n.model.skip&&(i.model.controlPointPreviousX=i.model.x-(d=(i.model.x-n.model.x)/3),i.model.controlPointPreviousY=i.model.y-d*i.mK),a&&!a.model.skip&&(i.model.controlPointNextX=i.model.x+(d=(a.model.x-i.model.x)/3),i.model.controlPointNextY=i.model.y+d*i.mK))},r.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.target||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),h=parseFloat(r.getStyle(o,"padding-right")),c=parseFloat(r.getStyle(o,"padding-bottom")),f=s.bottom-s.top-d-c;return{x:n=Math.round((n-s.left-u)/(s.right-s.left-u-h)*o.width/e.currentDevicePixelRatio),y:i=Math.round((i-s.top-d)/f*o.height/e.currentDevicePixelRatio)}},r.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},r._calculatePadding=function(t,e,n){return(e=r.getStyle(t,e)).indexOf("%")>-1?n/parseInt(e,10):parseInt(e,10)},r._getParentNode=function(t){var e=t.parentNode;return e&&e.host&&(e=e.host),e},r.getMaximumWidth=function(t){var e=r._getParentNode(t);if(!e)return t.clientWidth;var n=e.clientWidth,i=n-r._calculatePadding(e,"padding-left",n)-r._calculatePadding(e,"padding-right",n),a=r.getConstraintWidth(t);return isNaN(a)?i:Math.min(i,a)},r.getMaximumHeight=function(t){var e=r._getParentNode(t);if(!e)return t.clientHeight;var n=e.clientHeight,i=n-r._calculatePadding(e,"padding-top",n)-r._calculatePadding(e,"padding-bottom",n),a=r.getConstraintHeight(t);return isNaN(a)?i:Math.min(i,a)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height||i.style.width||(i.style.height=a+"px",i.style.width=r+"px")}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){null!=e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){null==e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;u<l;u++)delete a[o[u]];o.splice(0,l)}return s},r.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,26:26,34:34,46:46}],29:[function(t,e,n){"use strict";var i=t(46);function a(t,e){return t.native?{x:t.x,y:t.y}:i.getRelativePosition(t,e)}function r(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i<r;++i)if(t.isDatasetVisible(i))for(a=0,o=(n=t.getDatasetMeta(i)).data.length;a<o;++a){var s=n.data[a];s._view.skip||e(s)}}function o(t,e){var n=[];return r(t,function(t){t.inRange(e.x,e.y)&&n.push(t)}),n}function s(t,e,n,i){var a=Number.POSITIVE_INFINITY,o=[];return r(t,function(t){if(!n||t.inRange(e.x,e.y)){var r=t.getCenterPoint(),s=i(e,r);s<a?(o=[t],a=s):s===a&&o.push(t)}}),o}function l(t){var e=-1!==t.indexOf("x"),n=-1!==t.indexOf("y");return function(t,i){var a=e?Math.abs(t.x-i.x):0,r=n?Math.abs(t.y-i.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(r,2))}}function u(t,e,n){var i=a(e,t);n.axis=n.axis||"x";var r=l(n.axis),u=n.intersect?o(t,i):s(t,i,!1,r),d=[];return u.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[u[0]._index];i&&!i._view.skip&&d.push(i)}}),d):[]}e.exports={modes:{single:function(t,e){var n=a(e,t),i=[];return r(t,function(t){if(t.inRange(n.x,n.y))return i.push(t),i}),i.slice(0,1)},label:u,index:u,dataset:function(t,e,n){var i=a(e,t);n.axis=n.axis||"xy";var r=l(n.axis),u=n.intersect?o(t,i):s(t,i,!1,r);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return u(t,e,{intersect:!1})},point:function(t,e){return o(t,a(e,t))},nearest:function(t,e,n){var i=a(e,t);n.axis=n.axis||"xy";var r=l(n.axis),o=s(t,i,n.intersect,r);return o.length>1&&o.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),o.slice(0,1)},x:function(t,e,n){var i=a(e,t),o=[],s=!1;return r(t,function(t){t.inXRange(i.x)&&o.push(t),t.inRange(i.x,i.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var i=a(e,t),o=[],s=!1;return r(t,function(t){t.inYRange(i.y)&&o.push(t),t.inRange(i.x,i.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{46:46}],30:[function(t,e,n){"use strict";t(26)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{26:26}],31:[function(t,e,n){"use strict";var i=t(46);function a(t,e){return i.where(t,function(t){return t.position===e})}function r(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}e.exports={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;o<r;++o)n.hasOwnProperty(i=a[o])&&(e[i]=n[i])},update:function(t,e,n){if(t){var o=i.options.toPadding((t.options.layout||{}).padding),s=o.left,l=o.right,u=o.top,d=o.bottom,h=a(t.boxes,"left"),c=a(t.boxes,"right"),f=a(t.boxes,"top"),g=a(t.boxes,"bottom"),m=a(t.boxes,"chartArea");r(h,!0),r(c,!1),r(f,!0),r(g,!1);var p=e-s-l,v=n-u-d,y=(e-p/2)/(h.length+c.length),b=(n-v/2)/(f.length+g.length),x=p,_=v,k=[];i.each(h.concat(c,f,g),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?p:x,b),_-=e.height):(e=t.update(y,_),x-=e.width),k.push({horizontal:n,minSize:e,box:t})});var w=0,M=0,S=0,D=0;i.each(f.concat(g),function(t){if(t.getPadding){var e=t.getPadding();w=Math.max(w,e.left),M=Math.max(M,e.right)}}),i.each(h.concat(c),function(t){if(t.getPadding){var e=t.getPadding();S=Math.max(S,e.top),D=Math.max(D,e.bottom)}});var C=s,P=l,T=u,O=d;i.each(h.concat(c),W),i.each(h,function(t){C+=t.width}),i.each(c,function(t){P+=t.width}),i.each(f.concat(g),W),i.each(f,function(t){T+=t.height}),i.each(g,function(t){O+=t.height}),i.each(h.concat(c),function(t){var e=i.findNextWhere(k,function(e){return e.box===t});e&&t.update(e.minSize.width,_,{left:0,right:0,top:T,bottom:O})}),C=s,P=l,T=u,O=d,i.each(h,function(t){C+=t.width}),i.each(c,function(t){P+=t.width}),i.each(f,function(t){T+=t.height}),i.each(g,function(t){O+=t.height});var I=Math.max(w-C,0);C+=I,P+=Math.max(M-P,0);var A=Math.max(S-T,0);T+=A,O+=Math.max(D-O,0);var F=n-T-O,R=e-C-P;R===x&&F===_||(i.each(h,function(t){t.height=F}),i.each(c,function(t){t.height=F}),i.each(f,function(t){t.fullWidth||(t.width=R)}),i.each(g,function(t){t.fullWidth||(t.width=R)}),_=F,x=R);var L=s+I,Y=u+A;i.each(h.concat(f),N),L+=x,Y+=_,i.each(c,N),i.each(g,N),t.chartArea={left:C,top:T,right:C+x,bottom:T+_},i.each(m,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(x,_)})}function W(t){var e=i.findNextWhere(k,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(C,w),right:Math.max(P,M),top:0,bottom:0};t.update(t.fullWidth?p:x,v/2,n)}else t.update(e.minSize.width,_)}function N(t){t.isHorizontal()?(t.left=t.fullWidth?s:C,t.right=t.fullWidth?e-l:C+x,t.top=Y,t.bottom=Y+t.height,Y=t.bottom):(t.left=L,t.right=L+t.width,t.top=T,t.bottom=T+_,L=t.right)}}}},{46:46}],32:[function(t,e,n){"use strict";var i=t(26),a=t(46);i._set("global",{plugins:{}}),e.exports={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,r,o,s,l=this.descriptors(t),u=l.length;for(i=0;i<u;++i)if("function"==typeof(s=(r=(a=l[i]).plugin)[e])&&((o=[t].concat(n||[])).push(a.options),!1===s.apply(r,o)))return!1;return!0},descriptors:function(t){var e=t.$plugins||(t.$plugins={});if(e.id===this._cacheId)return e.descriptors;var n=[],r=[],o=t&&t.config||{},s=o.options&&o.options.plugins||{};return this._plugins.concat(o.plugins||[]).forEach(function(t){if(-1===n.indexOf(t)){var e=t.id,o=s[e];!1!==o&&(!0===o&&(o=a.clone(i.global.plugins[e])),n.push(t),r.push({plugin:t,options:o||{}}))}}),e.descriptors=r,e.id=this._cacheId,r},_invalidate:function(t){delete t.$plugins}}},{26:26,46:46}],33:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46),o=t(35);function s(t){var e,n,i=[];for(e=0,n=t.length;e<n;++e)i.push(t[e].label);return i}function l(t,e,n){var i=t.getPixelForTick(e);return n&&(i-=0===e?(t.getPixelForTick(1)-i)/2:(i-t.getPixelForTick(e-1))/2),i}function u(t,e,n){return r.isArray(e)?r.longestText(t,n,e):t.measureText(e).width}function d(t){var e=r.valueOrDefault,n=i.global,a=e(t.fontSize,n.defaultFontSize),o=e(t.fontStyle,n.defaultFontStyle),s=e(t.fontFamily,n.defaultFontFamily);return{size:a,style:o,family:s,font:r.fontString(a,o,s)}}function h(t){return r.options.toLineHeight(r.valueOrDefault(t.lineHeight,1.2),r.valueOrDefault(t.fontSize,i.global.defaultFontSize))}i._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:o.formatters.values,minor:{},major:{}}}),e.exports=a.extend({getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;for(var e in!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1}),t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){r.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var i,a,o,s,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=r.extend({left:0,right:0,top:0,bottom:0},n),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),o=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=o,i=0,a=o.length;i<a;++i)s=o[i],(u=l[i])?u.label=s:l.push(u={label:s,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){r.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){r.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){r.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){r.callback(this.options.beforeDataLimits,[this])},determineDataLimits:r.noop,afterDataLimits:function(){r.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){r.callback(this.options.beforeBuildTicks,[this])},buildTicks:r.noop,afterBuildTicks:function(){r.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){r.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){r.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){r.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,n=t.options.ticks,i=s(t._ticks),a=d(n);e.font=a.font;var o=n.minRotation||0;if(i.length&&t.options.display&&t.isHorizontal())for(var l,u=r.longestText(e,a.font,i,t.longestTextCache),h=u,c=t.getPixelForTick(1)-t.getPixelForTick(0)-6;h>c&&o<n.maxRotation;){var f=r.toRadians(o);if(l=Math.cos(f),Math.sin(f)*u>t.maxHeight){o--;break}o++,h=l*u}t.labelRotation=o},afterCalculateTickRotation:function(){r.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){r.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=s(t._ticks),i=t.options,a=i.ticks,o=i.scaleLabel,l=i.gridLines,c=i.display,f=t.isHorizontal(),g=d(a),m=i.gridLines.tickMarkLength;if(e.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:c&&l.drawTicks?m:0,e.height=f?c&&l.drawTicks?m:0:t.maxHeight,o.display&&c){var p=h(o)+r.options.toPadding(o.padding).height;f?e.height+=p:e.width+=p}if(a.display&&c){var v=r.longestText(t.ctx,g.font,n,t.longestTextCache),y=r.numberOfLabelLines(n),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=r.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_);e.height=Math.min(t.maxHeight,e.height+(w*v+g.size*y+b*(y-1)+b)+x),t.ctx.font=g.font;var M=u(t.ctx,n[0],g.font),S=u(t.ctx,n[n.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===i.position?k*M+3:k*b+3,t.paddingRight="bottom"===i.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else a.mirror?v=0:v+=x+b,e.width=Math.min(t.maxWidth,e.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=e.width,t.height=e.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){r.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(r.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:r.noop,getPixelForValue:r.noop,getValueForPixel:r.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;return n&&(a+=i/2),e.left+Math.round(a)+(e.isFullWidth()?e.margins.left:0)}return e.top+t*((e.height-(e.paddingTop+e.paddingBottom))/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;return e.isHorizontal()?e.left+Math.round((e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft)+(e.isFullWidth()?e.margins.left:0):e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,n,i,a,o=this,s=o.isHorizontal(),l=o.options.ticks.minor,u=t.length,d=r.toRadians(o.labelRotation),h=Math.cos(d),c=o.longestLabelWidth*h,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),s&&(e=!1,(c+l.autoSkipPadding)*u>o.width-(o.paddingLeft+o.paddingRight)&&(e=1+Math.floor((c+l.autoSkipPadding)*u/(o.width-(o.paddingLeft+o.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n<u;n++)i=t[n],(e>1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,n=e.options;if(n.display){var a=e.ctx,o=i.global,s=n.ticks.minor,u=n.ticks.major||s,c=n.gridLines,f=n.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=s.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=r.valueOrDefault(s.fontColor,o.defaultFontColor),y=d(s),b=r.valueOrDefault(u.fontColor,o.defaultFontColor),x=d(u),_=c.drawTicks?c.tickMarkLength:0,k=r.valueOrDefault(f.fontColor,o.defaultFontColor),w=d(f),M=r.options.toPadding(f.padding),S=r.toRadians(e.labelRotation),D=[],C=e.options.gridLines.lineWidth,P="right"===n.position?e.left:e.right-C-_,T="right"===n.position?e.left+_:e.right,O="bottom"===n.position?e.top+C:e.bottom-_-C,I="bottom"===n.position?e.top+C+_:e.bottom+C;if(r.each(p,function(i,a){if(!r.isNullOrUndef(i.label)){var u,d,h,f,v,y,b,x,k,w,M,A,F,R,L=i.label;a===e.zeroLineIndex&&n.offset===c.offsetGridLines?(u=c.zeroLineWidth,d=c.zeroLineColor,h=c.zeroLineBorderDash,f=c.zeroLineBorderDashOffset):(u=r.valueAtIndexOrDefault(c.lineWidth,a),d=r.valueAtIndexOrDefault(c.color,a),h=r.valueOrDefault(c.borderDash,o.borderDash),f=r.valueOrDefault(c.borderDashOffset,o.borderDashOffset));var Y="middle",W="middle",N=s.padding;if(m){var z=_+N;"bottom"===n.position?(W=g?"middle":"top",Y=g?"right":"center",R=e.top+z):(W=g?"middle":"bottom",Y=g?"left":"center",R=e.bottom-z);var V=l(e,a,c.offsetGridLines&&p.length>1);V<e.left&&(d="rgba(0,0,0,0)"),V+=r.aliasPixel(u),F=e.getPixelForTick(a)+s.labelOffset,v=b=k=M=V,y=O,x=I,w=t.top,A=t.bottom+C}else{var H,B="left"===n.position;s.mirror?(Y=B?"left":"right",H=N):(Y=B?"right":"left",H=_+N),F=B?e.right-H:e.left+H;var E=l(e,a,c.offsetGridLines&&p.length>1);E<e.top&&(d="rgba(0,0,0,0)"),E+=r.aliasPixel(u),R=e.getPixelForTick(a)+s.labelOffset,v=P,b=T,k=t.left,M=t.right+C,y=x=w=A=E}D.push({tx1:v,ty1:y,tx2:b,ty2:x,x1:k,y1:w,x2:M,y2:A,labelX:F,labelY:R,glWidth:u,glColor:d,glBorderDash:h,glBorderDashOffset:f,rotation:-1*S,label:L,major:i.major,textBaseline:W,textAlign:Y})}}),r.each(D,function(t){if(c.display&&(a.save(),a.lineWidth=t.glWidth,a.strokeStyle=t.glColor,a.setLineDash&&(a.setLineDash(t.glBorderDash),a.lineDashOffset=t.glBorderDashOffset),a.beginPath(),c.drawTicks&&(a.moveTo(t.tx1,t.ty1),a.lineTo(t.tx2,t.ty2)),c.drawOnChartArea&&(a.moveTo(t.x1,t.y1),a.lineTo(t.x2,t.y2)),a.stroke(),a.restore()),s.display){a.save(),a.translate(t.labelX,t.labelY),a.rotate(t.rotation),a.font=t.major?x.font:y.font,a.fillStyle=t.major?b:v,a.textBaseline=t.textBaseline,a.textAlign=t.textAlign;var n=t.label;if(r.isArray(n))for(var i=n.length,o=1.5*y.size,l=e.isHorizontal()?0:-o*(i-1)/2,u=0;u<i;++u)a.fillText(""+n[u],0,l),l+=o;else a.fillText(n,0,0);a.restore()}}),f.display){var A,F,R=0,L=h(f)/2;if(m)A=e.left+(e.right-e.left)/2,F="bottom"===n.position?e.bottom-L-M.bottom:e.top+L+M.top;else{var Y="left"===n.position;A=Y?e.left+L+M.top:e.right-L-M.top,F=e.top+(e.bottom-e.top)/2,R=Y?-.5*Math.PI:.5*Math.PI}a.save(),a.translate(A,F),a.rotate(R),a.textAlign="center",a.textBaseline="middle",a.fillStyle=k,a.font=w.font,a.fillText(f.labelString,0,0),a.restore()}if(c.drawBorder){a.lineWidth=r.valueAtIndexOrDefault(c.lineWidth,0),a.strokeStyle=r.valueAtIndexOrDefault(c.color,0);var W=e.left,N=e.right+C,z=e.top,V=e.bottom+C,H=r.aliasPixel(a.lineWidth);m?(z=V="top"===n.position?e.bottom:e.top,z+=H,V+=H):(W=N="left"===n.position?e.right:e.left,W+=H,N+=H),a.beginPath(),a.moveTo(W,z),a.lineTo(N,V),a.stroke()}}}})},{26:26,27:27,35:35,46:46}],34:[function(t,e,n){"use strict";var i=t(26),a=t(46),r=t(31);e.exports={constructors:{},defaults:{},registerScaleType:function(t,e,n){this.constructors[t]=e,this.defaults[t]=a.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[i.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=a.extend(this.defaults[t],e))},addScalesToLayout:function(t){a.each(t.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,r.addBox(t,e)})}}},{26:26,31:31,46:46}],35:[function(t,e,n){"use strict";var i=t(46);e.exports={formatters:{values:function(t){return i.isArray(t)?t:""+t},linear:function(t,e,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t)if(Math.max(Math.abs(n[0]),Math.abs(n[n.length-1]))<1e-4){var s=i.log10(Math.abs(t));o=t.toExponential(Math.floor(s)-Math.floor(r))}else{var l=-1*Math.floor(r);l=Math.max(Math.min(l,20),0),o=t.toFixed(l)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{46:46}],36:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:r.noop,beforeBody:r.noop,beforeLabel:r.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:r.noop,afterBody:r.noop,beforeFooter:r.noop,footer:r.noop,afterFooter:r.noop}}});var o={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;e<n;++e){var o=t[e];if(o&&o.hasValue()){var s=o.tooltipPosition();i+=s.x,a+=s.y,++r}}return{x:Math.round(i/r),y:Math.round(a/r)}},nearest:function(t,e){var n,i,a,o=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(n=0,i=t.length;n<i;++n){var u=t[n];if(u&&u.hasValue()){var d=u.getCenterPoint(),h=r.distanceBetweenPoints(e,d);h<l&&(l=h,a=u)}}if(a){var c=a.tooltipPosition();o=c.x,s=c.y}return{x:o,y:s}}};function s(t,e){var n=r.color(t);return n.alpha(e*n.alpha()).rgbaString()}function l(t,e){return e&&(r.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function u(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function d(t){var e=i.global,n=r.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:n(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:n(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:n(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:n(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:n(t.titleFontStyle,e.defaultFontStyle),titleFontSize:n(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:n(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:n(t.footerFontStyle,e.defaultFontStyle),footerFontSize:n(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function h(t){return l([],u(t))}(e.exports=a.extend({initialize:function(){this._model=d(this._options),this._lastActive=[]},getTitle:function(){var t=this._options.callbacks,e=t.beforeTitle.apply(this,arguments),n=t.title.apply(this,arguments),i=t.afterTitle.apply(this,arguments),a=[];return a=l(a,u(e)),a=l(a,u(n)),l(a,u(i))},getBeforeBody:function(){return h(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var n=this,i=n._options.callbacks,a=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};l(r.before,u(i.beforeLabel.call(n,t,e))),l(r.lines,i.label.call(n,t,e)),l(r.after,u(i.afterLabel.call(n,t,e))),a.push(r)}),a},getAfterBody:function(){return h(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this._options.callbacks,e=t.beforeFooter.apply(this,arguments),n=t.footer.apply(this,arguments),i=t.afterFooter.apply(this,arguments),a=[];return a=l(a,u(e)),a=l(a,u(n)),l(a,u(i))},update:function(t){var e,n,i,a,s,l,u,h=this,c=h._options,f=h._model,g=h._model=d(c),m=h._active,p=h._data,v={xAlign:f.xAlign,yAlign:f.yAlign},y={x:f.x,y:f.y},b={width:f.width,height:f.height},x={x:f.caretX,y:f.caretY};if(m.length){g.opacity=1;var _=[],k=[];x=o[c.position].call(h,m,h._eventPosition);var w=[];for(e=0,n=m.length;e<n;++e)w.push((a=void 0,s=void 0,s=(i=m[e])._yScale||i._scale,l=i._index,u=i._datasetIndex,{xLabel:(a=i._xScale)?a.getLabelForIndex(l,u):"",yLabel:s?s.getLabelForIndex(l,u):"",index:l,datasetIndex:u,x:i._model.x,y:i._model.y}));c.filter&&(w=w.filter(function(t){return c.filter(t,p)})),c.itemSort&&(w=w.sort(function(t,e){return c.itemSort(t,e,p)})),r.each(w,function(t){_.push(c.callbacks.labelColor.call(h,t,h._chart)),k.push(c.callbacks.labelTextColor.call(h,t,h._chart))}),g.title=h.getTitle(w,p),g.beforeBody=h.getBeforeBody(w,p),g.body=h.getBody(w,p),g.afterBody=h.getAfterBody(w,p),g.footer=h.getFooter(w,p),g.x=Math.round(x.x),g.y=Math.round(x.y),g.caretPadding=c.caretPadding,g.labelColors=_,g.labelTextColors=k,g.dataPoints=w,b=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,o=e.body,s=o.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0),l=e.title.length,u=e.footer.length,d=e.titleFontSize,h=e.bodyFontSize,c=e.footerFontSize;i+=l*d,i+=l?(l-1)*e.titleSpacing:0,i+=l?e.titleMarginBottom:0,i+=(s+=e.beforeBody.length+e.afterBody.length)*h,i+=s?(s-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*c,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=r.fontString(d,e._titleFontStyle,e._titleFontFamily),r.each(e.title,g),n.font=r.fontString(h,e._bodyFontStyle,e._bodyFontFamily),r.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?h+2:0,r.each(o,function(t){r.each(t.before,g),r.each(t.lines,g),r.each(t.after,g)}),f=0,n.font=r.fontString(c,e._footerFontStyle,e._footerFontFamily),r.each(e.footer,g),{width:a+=2*e.xPadding,height:i}}(this,g),y=function(t,e,n,i){var a=t.x,r=t.y,o=t.caretPadding,s=n.xAlign,l=n.yAlign,u=t.caretSize+o,d=t.cornerRadius+o;return"right"===s?a-=e.width:"center"===s&&((a-=e.width/2)+e.width>i.width&&(a=i.width-e.width),a<0&&(a=0)),"top"===l?r+=u:r-="bottom"===l?e.height+u:e.height/2,"center"===l?"left"===s?a+=u:"right"===s&&(a-=u):"left"===s?a-=d:"right"===s&&(a+=d),{x:a,y:r}}(g,b,v=function(t,e){var n,i,a,r,o,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",h="center";s.y<e.height?h="top":s.y>l.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===h?(n=function(t){return t<=c},i=function(t){return t>c}):(n=function(t){return t<=e.width/2},i=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,b),h._chart)}else g.opacity=0;return g.xAlign=v.xAlign,g.yAlign=v.yAlign,g.x=y.x,g.y=y.y,g.width=b.width,g.height=b.height,g.caretX=x.x,g.caretY=x.y,h._model=g,t&&c.custom&&c.custom.call(h,g),h},drawCaret:function(t,e){var n=this._chart.ctx,i=this.getCaretPosition(t,e,this._view);n.lineTo(i.x1,i.y1),n.lineTo(i.x2,i.y2),n.lineTo(i.x3,i.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,m=e.width,p=e.height;if("center"===c)s=g+p/2,"left"===h?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+m)+u,r=i,o=s-u,l=s+u);else if("left"===h?(i=(a=f+d+u)-u,r=a+u):"right"===h?(i=(a=f+m-d-u)-u,r=a+u):(i=(a=n.caretX)-u,r=a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+p)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,e,n,i){var a=e.title;if(a.length){n.textAlign=e._titleAlign,n.textBaseline="top";var o,l,u=e.titleFontSize,d=e.titleSpacing;for(n.fillStyle=s(e.titleFontColor,i),n.font=r.fontString(u,e._titleFontStyle,e._titleFontFamily),o=0,l=a.length;o<l;++o)n.fillText(a[o],t.x,t.y),t.y+=u+d,o+1===a.length&&(t.y+=e.titleMarginBottom-d)}},drawBody:function(t,e,n,i){var a=e.bodyFontSize,o=e.bodySpacing,l=e.body;n.textAlign=e._bodyAlign,n.textBaseline="top",n.font=r.fontString(a,e._bodyFontStyle,e._bodyFontFamily);var u=0,d=function(e){n.fillText(e,t.x+u,t.y),t.y+=a+o};n.fillStyle=s(e.bodyFontColor,i),r.each(e.beforeBody,d);var h=e.displayColors;u=h?a+2:0,r.each(l,function(o,l){var u=s(e.labelTextColors[l],i);n.fillStyle=u,r.each(o.before,d),r.each(o.lines,function(r){h&&(n.fillStyle=s(e.legendColorBackground,i),n.fillRect(t.x,t.y,a,a),n.lineWidth=1,n.strokeStyle=s(e.labelColors[l].borderColor,i),n.strokeRect(t.x,t.y,a,a),n.fillStyle=s(e.labelColors[l].backgroundColor,i),n.fillRect(t.x+1,t.y+1,a-2,a-2),n.fillStyle=u),d(r)}),r.each(o.after,d)}),u=0,r.each(e.afterBody,d),t.y-=o},drawFooter:function(t,e,n,i){var a=e.footer;a.length&&(t.y+=e.footerMarginTop,n.textAlign=e._footerAlign,n.textBaseline="top",n.fillStyle=s(e.footerFontColor,i),n.font=r.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),r.each(a,function(i){n.fillText(i,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing}))},drawBackground:function(t,e,n,i,a){n.fillStyle=s(e.backgroundColor,a),n.strokeStyle=s(e.borderColor,a),n.lineWidth=e.borderWidth;var r=e.xAlign,o=e.yAlign,l=t.x,u=t.y,d=i.width,h=i.height,c=e.cornerRadius;n.beginPath(),n.moveTo(l+c,u),"top"===o&&this.drawCaret(t,i),n.lineTo(l+d-c,u),n.quadraticCurveTo(l+d,u,l+d,u+c),"center"===o&&"right"===r&&this.drawCaret(t,i),n.lineTo(l+d,u+h-c),n.quadraticCurveTo(l+d,u+h,l+d-c,u+h),"bottom"===o&&this.drawCaret(t,i),n.lineTo(l+c,u+h),n.quadraticCurveTo(l,u+h,l,u+h-c),"center"===o&&"left"===r&&this.drawCaret(t,i),n.lineTo(l,u+c),n.quadraticCurveTo(l,u,l+c,u),n.closePath(),n.fill(),e.borderWidth>0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity;this._options.enabled&&(e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length)&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e,n=this,i=n._options;return n._lastActive=n._lastActive||[],n._active="mouseout"===t.type?[]:n._chart.getElementsAtEventForMode(t,i.mode,i),(e=!r.arrayEquals(n._active,n._lastActive))&&(n._lastActive=n._active,(i.enabled||i.custom)&&(n._eventPosition={x:t.x,y:t.y},n.update(!0),n.pivot())),e}})).positioners=o},{26:26,27:27,46:46}],37:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46);i._set("global",{elements:{arc:{backgroundColor:i.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var n=this._view;if(n){for(var i=r.getAngleFromPoint(n,{x:t,y:e}),a=i.angle,o=i.distance,s=n.startAngle,l=n.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;return a>=s&&a<=l&&o>=n.innerRadius&&o<=n.outerRadius}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{26:26,27:27,46:46}],38:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this._view,s=this._chart.ctx,l=a.spanGaps,u=this._children.slice(),d=o.elements.line,h=-1;for(this._loop&&u.length&&u.push(u[0]),s.save(),s.lineCap=a.borderCapStyle||d.borderCapStyle,s.setLineDash&&s.setLineDash(a.borderDash||d.borderDash),s.lineDashOffset=a.borderDashOffset||d.borderDashOffset,s.lineJoin=a.borderJoinStyle||d.borderJoinStyle,s.lineWidth=a.borderWidth||d.borderWidth,s.strokeStyle=a.borderColor||o.defaultColor,s.beginPath(),h=-1,t=0;t<u.length;++t)e=u[t],n=r.previousItem(u,t),i=e._view,0===t?i.skip||(s.moveTo(i.x,i.y),h=t):(n=-1===h?n:u[h],i.skip||(h!==t-1&&!l||-1===h?s.moveTo(i.x,i.y):r.canvas.lineTo(s,n._view,e._view),h=t));s.stroke(),s.restore()}})},{26:26,27:27,46:46}],39:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46),o=i.global.defaultColor;function s(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}i._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:o,borderColor:o,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=a.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:s,inXRange:s,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,n=this._model,a=this._chart.ctx,s=e.pointStyle,l=e.rotation,u=e.radius,d=e.x,h=e.y;e.skip||(void 0===t||n.x>=t.left&&1.01*t.right>=n.x&&n.y>=t.top&&1.01*t.bottom>=n.y)&&(a.strokeStyle=e.borderColor||o,a.lineWidth=r.valueOrDefault(e.borderWidth,i.global.elements.point.borderWidth),a.fillStyle=e.backgroundColor||o,r.canvas.drawPoint(a,s,u,d,h,l))}})},{26:26,27:27,46:46}],40:[function(t,e,n){"use strict";var i=t(26),a=t(27);function r(t){return void 0!==t._view.width}function o(t){var e,n,i,a,o=t._view;if(r(t)){var s=o.width/2;e=o.x-s,n=o.x+s,i=Math.min(o.y,o.base),a=Math.max(o.y,o.base)}else{var l=o.height/2;e=Math.min(o.x,o.base),n=Math.max(o.x,o.base),i=o.y-l,a=o.y+l}return{left:e,top:i,right:n,bottom:a}}i._set("global",{elements:{rectangle:{backgroundColor:i.global.defaultColor,borderColor:i.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a,r,o,s=this._chart.ctx,l=this._view,u=l.borderWidth;if(l.horizontal?(n=l.y-l.height/2,i=l.y+l.height/2,a=(e=l.x)>(t=l.base)?1:-1,r=1,o=l.borderSkipped||"left"):(t=l.x-l.width/2,e=l.x+l.width/2,a=1,r=(i=l.base)>(n=l.y)?1:-1,o=l.borderSkipped||"bottom"),u){var d=Math.min(Math.abs(t-e),Math.abs(n-i)),h=(u=u>d?d:u)/2,c=t+("left"!==o?h*a:0),f=e+("right"!==o?-h*a:0),g=n+("top"!==o?h*r:0),m=i+("bottom"!==o?-h*r:0);c!==f&&(n=g,i=m),g!==m&&(t=c,e=f)}s.beginPath(),s.fillStyle=l.backgroundColor,s.strokeStyle=l.borderColor,s.lineWidth=u;var p=[[t,i],[t,n],[e,n],[e,i]],v=["bottom","left","top","right"].indexOf(o,0);function y(t){return p[(v+t)%4]}-1===v&&(v=0);var b=y(0);s.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=y(x),s.lineTo(b[0],b[1]);s.fill(),u&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=o(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){if(!this._view)return!1;var n=o(this);return r(this)?t>=n.left&&t<=n.right:e>=n.top&&e<=n.bottom},inXRange:function(t){var e=o(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=o(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return r(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{26:26,27:27}],41:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(37),e.exports.Line=t(38),e.exports.Point=t(39),e.exports.Rectangle=t(40)},{37:37,38:38,39:39,40:40}],42:[function(t,e,n){"use strict";var i=t(43);n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,a/2-1e-7,i/2-1e-7);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.arcTo(e+i,n,e+i,n+o,o),t.lineTo(e+i,n+a-o),t.arcTo(e+i,n+a,e+i-o,n+a,o),t.lineTo(e+o,n+a),t.arcTo(e,n+a,e,n+a-o,o),t.lineTo(e,n+o),t.arcTo(e,n,e+o,n,o),t.closePath(),t.moveTo(e,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a,r){var o,s,l,u,d,h;if(r=r||0,!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(n)||n<=0)){switch(t.save(),t.translate(i,a),t.rotate(r*Math.PI/180),t.beginPath(),e){default:t.arc(0,0,n,0,2*Math.PI),t.closePath();break;case"triangle":d=(s=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(-s/2,d/3),t.lineTo(s/2,d/3),t.lineTo(0,-2*d/3),t.closePath();break;case"rect":h=1/Math.SQRT2*n,t.rect(-h,-h,2*h,2*h);break;case"rectRounded":var c=n/Math.SQRT2,f=Math.SQRT2*n;this.roundedRect(t,-c,-c,f,f,.425*n);break;case"rectRot":h=1/Math.SQRT2*n,t.moveTo(-h,0),t.lineTo(0,h),t.lineTo(h,0),t.lineTo(0,-h),t.closePath();break;case"cross":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0);break;case"crossRot":l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"star":t.moveTo(0,n),t.lineTo(0,-n),t.moveTo(-n,0),t.lineTo(n,0),l=Math.cos(Math.PI/4)*n,u=Math.sin(Math.PI/4)*n,t.moveTo(-l,-u),t.lineTo(l,u),t.moveTo(-l,u),t.lineTo(l,-u);break;case"line":t.moveTo(-n,0),t.lineTo(n,0);break;case"dash":t.moveTo(0,0),t.lineTo(n,0)}t.fill(),t.stroke(),t.restore()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}},i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments)}},{43:43}],43:[function(t,e,n){"use strict";var i,a={noop:function(){},uid:(i=0,function(){return i++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return a.valueOrDefault(a.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,i){var r,o,s;if(a.isArray(t))if(o=t.length,i)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r<o;r++)e.call(n,t[r],r);else if(a.isObject(t))for(o=(s=Object.keys(t)).length,r=0;r<o;r++)e.call(n,t[s[r]],s[r])},arrayEquals:function(t,e){var n,i,r,o;if(!t||!e||t.length!==e.length)return!1;for(n=0,i=t.length;n<i;++n)if(o=e[n],(r=t[n])instanceof Array&&o instanceof Array){if(!a.arrayEquals(r,o))return!1}else if(r!==o)return!1;return!0},clone:function(t){if(a.isArray(t))return t.map(a.clone);if(a.isObject(t)){for(var e={},n=Object.keys(t),i=n.length,r=0;r<i;++r)e[n[r]]=a.clone(t[n[r]]);return e}return t},_merger:function(t,e,n,i){var r=e[t],o=n[t];a.isObject(r)&&a.isObject(o)?a.merge(r,o,i):e[t]=a.clone(o)},_mergerIf:function(t,e,n){var i=e[t],r=n[t];a.isObject(i)&&a.isObject(r)?a.mergeIf(i,r):e.hasOwnProperty(t)||(e[t]=a.clone(r))},merge:function(t,e,n){var i,r,o,s,l,u=a.isArray(e)?e:[e],d=u.length;if(!a.isObject(t))return t;for(i=(n=n||{}).merger||a._merger,r=0;r<d;++r)if(a.isObject(e=u[r]))for(l=0,s=(o=Object.keys(e)).length;l<s;++l)i(o[l],t,e,n);return t},mergeIf:function(t,e){return a.merge(t,e,{merger:a._mergerIf})},extend:function(t){for(var e=function(e,n){t[n]=e},n=1,i=arguments.length;n<i;++n)a.each(arguments[n],e);return t},inherits:function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=a.inherits,t&&a.extend(n.prototype,t),n.__super__=e.prototype,n}};e.exports=a,a.callCallback=a.callback,a.indexOf=function(t,e,n){return Array.prototype.indexOf.call(t,e,n)},a.getValueOrDefault=a.valueOrDefault,a.getValueAtIndexOrDefault=a.valueAtIndexOrDefault},{}],44:[function(t,e,n){"use strict";var i=t(43),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{43:43}],45:[function(t,e,n){"use strict";var i=t(43);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a<r;++a)if(void 0!==(o=t[a])&&(void 0!==e&&"function"==typeof o&&(o=o(e)),void 0!==n&&i.isArray(o)&&(o=o[n]),void 0!==o))return o}}},{43:43}],46:[function(t,e,n){"use strict";e.exports=t(43),e.exports.easing=t(44),e.exports.canvas=t(42),e.exports.options=t(45)},{42:42,43:43,44:44,45:45}],47:[function(t,e,n){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],48:[function(t,e,n){"use strict";var i=t(46),a=["animationstart","webkitAnimationStart"],r={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function o(t,e){var n=i.getStyle(t,e),a=n&&n.match(/^(\d+)(\.\d+)?px$/);return a?Number(a[1]):void 0}var s=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(n){}return t}()&&{passive:!0};function l(t,e,n){t.addEventListener(e,n,s)}function u(t,e,n){t.removeEventListener(e,n,s)}function d(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,n="from{opacity:0.99}to{opacity:1}";t="@-webkit-keyframes chartjs-render-animation{"+n+"}@keyframes chartjs-render-animation{"+n+"}.chartjs-render-monitor{-webkit-animation:chartjs-render-animation 0.001s;animation:chartjs-render-animation 0.001s;}",e=this._style||document.createElement("style"),this._style||(this._style=e,t="/* Chart.js */\n"+t,e.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(e)),e.appendChild(document.createTextNode(t))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(function(t,e){var n=t.style,i=t.getAttribute("height"),a=t.getAttribute("width");if(t.$chartjs={initial:{height:i,width:a,style:{display:n.display,height:n.height,width:n.width}}},n.display=n.display||"block",null===a||""===a){var r=o(t,"width");void 0!==r&&(t.width=r)}if(null===i||""===i)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=o(t,"height");void 0!==r&&(t.height=s)}}(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e.$chartjs){var n=e.$chartjs.initial;["height","width"].forEach(function(t){var a=n[t];i.isNullOrUndef(a)?e.removeAttribute(t):e.setAttribute(t,a)}),i.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e.$chartjs}},addEventListener:function(t,e,n){var o=t.canvas;if("resize"!==e){var s=n.$chartjs||(n.$chartjs={});l(o,e,(s.proxies||(s.proxies={}))[t.id+"_"+e]=function(e){n(function(t,e){var n=r[t.type]||t.type,a=i.getRelativePosition(t,e);return d(n,e,a.x,a.y,t)}(e,t))})}else!function(t,e,n){var r,o,s,u,h=t.$chartjs||(t.$chartjs={}),c=h.resizer=function(t){var e=document.createElement("div"),n="chartjs-size-monitor",i="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=i,e.className=n,e.innerHTML='<div class="'+n+'-expand" style="'+i+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+n+'-shrink" style="'+i+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var o=function(){e._reset(),t()};return l(a,"scroll",o.bind(a,"expand")),l(r,"scroll",o.bind(r,"shrink")),e}((r=function(){if(h.resizer)return e(d("resize",n))},s=!1,u=[],function(){u=Array.prototype.slice.call(arguments),o=o||this,s||(s=!0,i.requestAnimFrame.call(window,function(){s=!1,r.apply(o,u)}))}));!function(t,e){var n=t.$chartjs||(t.$chartjs={}),r=n.renderProxy=function(t){"chartjs-render-animation"===t.animationName&&e()};i.each(a,function(e){l(t,e,r)}),n.reflow=!!t.offsetParent,t.classList.add("chartjs-render-monitor")}(t,function(){if(h.resizer){var e=t.parentNode;e&&e!==c.parentNode&&e.insertBefore(c,e.firstChild),c._reset()}})}(o,n,t)},removeEventListener:function(t,e,n){var r,o,s,l=t.canvas;if("resize"!==e){var d=((n.$chartjs||{}).proxies||{})[t.id+"_"+e];d&&u(l,e,d)}else s=(o=(r=l).$chartjs||{}).resizer,delete o.resizer,function(t){var e=t.$chartjs||{},n=e.renderProxy;n&&(i.each(a,function(e){u(t,e,n)}),delete e.renderProxy),t.classList.remove("chartjs-render-monitor")}(r),s&&s.parentNode&&s.parentNode.removeChild(s)}},i.addEvent=l,i.removeEvent=u},{46:46}],49:[function(t,e,n){"use strict";var i=t(46),a=t(47),r=t(48);e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r._enabled?r:a)},{46:46,47:47,48:48}],50:[function(t,e,n){"use strict";e.exports={},e.exports.filler=t(51),e.exports.legend=t(52),e.exports.title=t(53)},{51:51,52:52,53:53}],51:[function(t,e,n){"use strict";var i=t(26),a=t(41),r=t(46);i._set("global",{plugins:{filler:{propagate:!0}}});var o={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e<r&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};function s(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function l(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),null!=r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return{x:(e=i.isHorizontal())?r:null,y:e?null:r}}return null}function u(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function d(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),o[n](t))}function h(t){return t&&!t.skip}function c(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)r.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}e.exports={id:"filler",afterDatasetsUpdate:function(t,e){var n,i,r,o,h=(t.data.datasets||[]).length,c=e.propagate,f=[];for(i=0;i<h;++i)o=null,(r=(n=t.getDatasetMeta(i)).dataset)&&r._model&&r instanceof a.Line&&(o={visible:t.isDatasetVisible(i),fill:s(r,i,h),chart:t,el:r}),n.$filler=o,f.push(o);for(i=0;i<h;++i)(o=f[i])&&(o.fill=u(f,i,c),o.boundary=l(o),o.mapper=d(o))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var a=t.ctx,o=n.el,s=o._view,l=o._children||[],u=n.mapper,d=s.backgroundColor||i.global.defaultColor;u&&d&&l.length&&(r.canvas.clipArea(a,t.chartArea),function(t,e,n,i,a,r){var o,s,l,u,d,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,s=m+!!r;o<s;++o)d=n(u=e[l=o%m]._view,l,i),f=h(u),g=h(d),f&&g?(b=v.push(u),x=y.push(d)):b&&x&&(p?(f&&v.push(u),g&&y.push(d)):(c(t,v,y,b,x),b=x=0,v=[],y=[]));c(t,v,y,b,x),t.closePath(),t.fillStyle=a,t.fill()}(a,l,u,s,d,o._loop),r.canvas.unclipArea(a))}}}},{26:26,41:41,46:46}],52:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46),o=t(31),s=r.noop;function l(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}i._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return r.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:r.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}});var u=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=t.options,n=e.labels,a=e.display,o=t.ctx,s=i.global,u=r.valueOrDefault,d=u(n.fontSize,s.defaultFontSize),h=u(n.fontStyle,s.defaultFontStyle),c=u(n.fontFamily,s.defaultFontFamily),f=r.fontString(d,h,c),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=a?10:0):(m.width=a?10:0,m.height=t.maxHeight),a)if(o.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+n.padding:0;o.textAlign="left",o.textBaseline="top",r.each(t.legendItems,function(e,i){var a=l(n,d)+d/2+o.measureText(e.text).width;v[v.length-1]+a+n.padding>=t.width&&(y+=d+n.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:a,height:d},v[v.length-1]+=a+n.padding}),m.height+=y}else{var b=n.padding,x=t.columnWidths=[],_=n.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,e){var i=l(n,d)+d/2+o.measureText(t.text).width;w+M>m.height&&(_+=k+n.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[e]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,n=e.labels,a=i.global,o=a.elements.line,s=t.width,u=t.lineWidths;if(e.display){var d,h=t.ctx,c=r.valueOrDefault,f=c(n.fontColor,a.defaultFontColor),g=c(n.fontSize,a.defaultFontSize),m=c(n.fontStyle,a.defaultFontStyle),p=c(n.fontFamily,a.defaultFontFamily),v=r.fontString(g,m,p);h.textAlign="left",h.textBaseline="middle",h.lineWidth=.5,h.strokeStyle=f,h.fillStyle=f,h.font=v;var y=l(n,g),b=t.legendHitBoxes,x=t.isHorizontal();d=x?{x:t.left+(s-u[0])/2,y:t.top+n.padding,line:0}:{x:t.left+n.padding,y:t.top+n.padding,line:0};var _=g+n.padding;r.each(t.legendItems,function(i,l){var f=h.measureText(i.text).width,m=y+g/2+f,p=d.x,v=d.y;x?p+m>=s&&(v=d.y+=_,d.line++,p=d.x=t.left+(s-u[d.line])/2):v+_>t.bottom&&(p=d.x=p+t.columnWidths[d.line]+n.padding,v=d.y=t.top+n.padding,d.line++),function(t,n,i){if(!(isNaN(y)||y<=0)){h.save(),h.fillStyle=c(i.fillStyle,a.defaultColor),h.lineCap=c(i.lineCap,o.borderCapStyle),h.lineDashOffset=c(i.lineDashOffset,o.borderDashOffset),h.lineJoin=c(i.lineJoin,o.borderJoinStyle),h.lineWidth=c(i.lineWidth,o.borderWidth),h.strokeStyle=c(i.strokeStyle,a.defaultColor);var s=0===c(i.lineWidth,o.borderWidth);if(h.setLineDash&&h.setLineDash(c(i.lineDash,o.borderDash)),e.labels&&e.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2;r.canvas.drawPoint(h,i.pointStyle,l,t+u,n+u)}else s||h.strokeRect(t,n,y,g),h.fillRect(t,n,y,g);h.restore()}}(p,v,i),b[l].left=p,b[l].top=v,function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;h.fillText(n.text,r,o),n.hidden&&(h.beginPath(),h.lineWidth=2,h.moveTo(r,o),h.lineTo(r+i,o),h.stroke())}(p,v,i,f),x?d.x+=m+n.padding:d.y+=_})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(r>=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}});function d(t,e){var n=new u({ctx:t.ctx,options:e,chart:t});o.configure(t,n,e),o.addBox(t,n),t.legend=n}e.exports={id:"legend",_element:u,beforeInit:function(t){var e=t.options.legend;e&&d(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(r.mergeIf(e,i.global.legend),n?(o.configure(t,n,e),n.options=e):d(t,e)):n&&(o.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}},{26:26,27:27,31:31,46:46}],53:[function(t,e,n){"use strict";var i=t(26),a=t(27),r=t(46),o=t(31),s=r.noop;i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var l=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:s,afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=t.options,n=e.display,a=(0,r.valueOrDefault)(e.fontSize,i.global.defaultFontSize),o=t.minSize,s=r.isArray(e.text)?e.text.length:1,l=r.options.toLineHeight(e.lineHeight,a),u=n?s*l+2*e.padding:0;t.isHorizontal()?(o.width=t.maxWidth,o.height=u):(o.width=u,o.height=t.maxHeight),t.width=o.width,t.height=o.height},afterFit:s,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),h=n(a.fontStyle,o.defaultFontStyle),c=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,h,c),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}});function u(t,e){var n=new l({ctx:t.ctx,options:e,chart:t});o.configure(t,n,e),o.addBox(t,n),t.titleBlock=n}e.exports={id:"title",_element:l,beforeInit:function(t){var e=t.options.title;e&&u(t,e)},beforeUpdate:function(t){var e=t.options.title,n=t.titleBlock;e?(r.mergeIf(e,i.global.title),n?(o.configure(t,n,e),n.options=e):u(t,e)):n&&(o.removeBox(t,n),delete t.titleBlock)}}},{26:26,27:27,31:31,46:46}],54:[function(t,e,n){"use strict";var i=t(33),a=t(34);e.exports=function(){var t=i.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t,e=this,n=e.getLabels();e.minIndex=0,e.maxIndex=n.length-1,void 0!==e.options.ticks.min&&(t=n.indexOf(e.options.ticks.min),e.minIndex=-1!==t?t:e.minIndex),void 0!==e.options.ticks.max&&(t=n.indexOf(e.options.ticks.max),e.maxIndex=-1!==t?t:e.maxIndex),e.min=n[e.minIndex],e.max=n[e.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(null!=t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels().indexOf(t=n||t);e=-1!==o?o:e}if(i.isHorizontal()){var s=i.width/r,l=s*(e-i.minIndex);return a&&(l+=s/2),i.left+Math.round(l)}var u=i.height/r,d=u*(e-i.minIndex);return a&&(d+=u/2),i.top+Math.round(d)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});a.registerScaleType("category",t,{position:"bottom"})}},{33:33,34:34}],55:[function(t,e,n){"use strict";var i=t(26),a=t(46),r=t(34),o=t(35);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){var t=this,e=t.options,n=t.chart,i=n.data.datasets,r=t.isHorizontal();function o(e){return r?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null;var s=e.stacked;if(void 0===s&&a.each(i,function(t,e){if(!s){var i=n.getDatasetMeta(e);n.isDatasetVisible(e)&&o(i)&&void 0!==i.stack&&(s=!0)}}),e.stacked||s){var l={};a.each(i,function(i,r){var s=n.getDatasetMeta(r),u=[s.type,void 0===e.stacked&&void 0===s.stack?r:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,h=l[u].negativeValues;n.isDatasetVisible(r)&&o(s)&&a.each(i.data,function(n,i){var a=+t.getRightValue(n);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,h[i]=h[i]||0,e.relativePoints?d[i]=100:a<0?h[i]+=a:d[i]+=a)})}),a.each(l,function(e){var n=e.positiveValues.concat(e.negativeValues),i=a.min(n),r=a.max(n);t.min=null===t.min?i:Math.min(t.min,i),t.max=null===t.max?r:Math.max(t.max,r)})}else a.each(i,function(e,i){var r=n.getDatasetMeta(i);n.isDatasetVisible(i)&&o(r)&&a.each(e.data,function(e,n){var i=+t.getRightValue(e);isNaN(i)||r.data[n].hidden||(null===t.min?t.min=i:i<t.min&&(t.min=i),null===t.max?t.max=i:i>t.max&&(t.max=i))})});t.min=isFinite(t.min)&&!isNaN(t.min)?t.min:0,t.max=isFinite(t.max)&&!isNaN(t.max)?t.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var n=a.valueOrDefault(e.fontSize,i.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*n)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this,n=e.start,i=+e.getRightValue(t),a=e.end-n;return e.isHorizontal()?e.left+e.width/a*(i-n):e.bottom-e.height/a*(i-n)},getValueForPixel:function(t){var e=this,n=e.isHorizontal();return e.start+(n?t-e.left:e.bottom-t)/(n?e.width:e.height)*(e.end-e.start)},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});r.registerScaleType("linear",n,e)}},{26:26,34:34,35:35,46:46}],56:[function(t,e,n){"use strict";var i=t(46),a=t(33);e.exports=function(t){var e=i.noop;t.LinearScaleBase=a.extend({getRightValue:function(t){return"string"==typeof t?+t:a.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(t.min=null===t.min?e.suggestedMin:Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(t.max=null===t.max?e.suggestedMax:Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),a={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},r=t.ticks=function(t,e){var n,a,r,o=[];if(t.stepSize&&t.stepSize>0)r=t.stepSize;else{var s=i.niceNum(e.max-e.min,!1);r=i.niceNum(s/(t.maxTicks-1),!0),void 0!==(a=t.precision)&&(n=Math.pow(10,a),r=Math.ceil(r*n)/n)}var l=Math.floor(e.min/r)*r,u=Math.ceil(e.max/r)*r;i.isNullOrUndef(t.min)||i.isNullOrUndef(t.max)||!t.stepSize||i.almostWhole((t.max-t.min)/t.stepSize,r/1e3)&&(l=t.min,u=t.max);var d=(u-l)/r;d=i.almostEquals(d,Math.round(d),r/1e3)?Math.round(d):Math.ceil(d),a=1,r<1&&(a=Math.pow(10,1-Math.floor(i.log10(r))),l=Math.round(l*a)/a,u=Math.round(u*a)/a),o.push(void 0!==t.min?t.min:l);for(var h=1;h<d;++h)o.push(Math.round((l+h*r)*a)/a);return o.push(void 0!==t.max?t.max:u),o}(a,t);t.handleDirectionalChanges(),t.max=i.max(r),t.min=i.min(r),e.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var t=this;t.ticksAsNumbers=t.ticks.slice(),t.zeroLineIndex=t.ticks.indexOf(0),a.prototype.convertTicksToLabels.call(t)}})}},{33:33,46:46}],57:[function(t,e,n){"use strict";var i=t(46),a=t(33),r=t(34),o=t(35);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.logarithmic}},n=a.extend({determineDataLimits:function(){var t=this,e=t.options,n=t.chart,a=n.data.datasets,r=t.isHorizontal();function o(e){return r?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null,t.minNotZero=null;var s=e.stacked;if(void 0===s&&i.each(a,function(t,e){if(!s){var i=n.getDatasetMeta(e);n.isDatasetVisible(e)&&o(i)&&void 0!==i.stack&&(s=!0)}}),e.stacked||s){var l={};i.each(a,function(a,r){var s=n.getDatasetMeta(r),u=[s.type,void 0===e.stacked&&void 0===s.stack?r:"",s.stack].join(".");n.isDatasetVisible(r)&&o(s)&&(void 0===l[u]&&(l[u]=[]),i.each(a.data,function(e,n){var i=l[u],a=+t.getRightValue(e);isNaN(a)||s.data[n].hidden||a<0||(i[n]=i[n]||0,i[n]+=a)}))}),i.each(l,function(e){if(e.length>0){var n=i.min(e),a=i.max(e);t.min=null===t.min?n:Math.min(t.min,n),t.max=null===t.max?a:Math.max(t.max,a)}})}else i.each(a,function(e,a){var r=n.getDatasetMeta(a);n.isDatasetVisible(a)&&o(r)&&i.each(e.data,function(e,n){var i=+t.getRightValue(e);isNaN(i)||r.data[n].hidden||i<0||(null===t.min?t.min=i:i<t.min&&(t.min=i),null===t.max?t.max=i:i>t.max&&(t.max=i),0!==i&&(null===t.minNotZero||i<t.minNotZero)&&(t.minNotZero=i))})});this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks,n=i.valueOrDefault;t.min=n(e.min,t.min),t.max=n(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(i.log10(t.min))-1),t.max=Math.pow(10,Math.floor(i.log10(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(i.log10(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(i.log10(t.min))+1):10),null===t.minNotZero&&(t.minNotZero=t.min>0?t.min:t.max<1?Math.pow(10,Math.floor(i.log10(t.max))):1)},buildTicks:function(){var t=this,e=t.options.ticks,n=!t.isHorizontal(),a=t.ticks=function(t,e){var n,a,r=[],o=i.valueOrDefault,s=o(t.min,Math.pow(10,Math.floor(i.log10(e.min)))),l=Math.floor(i.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(n=Math.floor(i.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,n)),r.push(s),s=a*Math.pow(10,n)):(n=Math.floor(i.log10(s)),a=Math.floor(s/Math.pow(10,n)));var d=n<0?Math.pow(10,Math.abs(n)):1;do{r.push(s),10==++a&&(a=1,d=++n>=0?1:d),s=Math.round(a*Math.pow(10,n)*d)/d}while(n<l||n===l&&a<u);var h=o(t.max,s);return r.push(h),r}({min:e.min,max:e.max},t);t.max=i.max(a),t.min=i.min(a),e.reverse?(n=!n,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),n&&a.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),a.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},_getFirstTickValue:function(t){var e=Math.floor(i.log10(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},getPixelForValue:function(e){var n,a,r,o,s,l=this,u=l.options.ticks.reverse,d=i.log10,h=l._getFirstTickValue(l.minNotZero),c=0;return e=+l.getRightValue(e),u?(r=l.end,o=l.start,s=-1):(r=l.start,o=l.end,s=1),l.isHorizontal()?(n=l.width,a=u?l.right:l.left):(n=l.height,s*=-1,a=u?l.top:l.bottom),e!==r&&(0===r&&(n-=c=i.getValueOrDefault(l.options.ticks.fontSize,t.defaults.global.defaultFontSize),r=h),0!==e&&(c+=n/(d(o)-d(r))*(d(e)-d(r))),a+=s*c),a},getValueForPixel:function(e){var n,a,r,o,s=this,l=s.options.ticks.reverse,u=i.log10,d=s._getFirstTickValue(s.minNotZero);if(l?(a=s.end,r=s.start):(a=s.start,r=s.end),s.isHorizontal()?(n=s.width,o=l?s.right-e:e-s.left):(n=s.height,o=l?e-s.top:s.bottom-e),o!==a){if(0===a){var h=i.getValueOrDefault(s.options.ticks.fontSize,t.defaults.global.defaultFontSize);o-=h,n-=h,a=d}o*=u(r)-u(a),o/=n,o=Math.pow(10,u(a)+o)}return o}});r.registerScaleType("logarithmic",n,e)}},{33:33,34:34,35:35,46:46}],58:[function(t,e,n){"use strict";var i=t(26),a=t(46),r=t(34),o=t(35);e.exports=function(t){var e=i.global,n={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function s(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function l(t){var n=t.options.pointLabels,i=a.valueOrDefault(n.fontSize,e.defaultFontSize),r=a.valueOrDefault(n.fontStyle,e.defaultFontStyle),o=a.valueOrDefault(n.fontFamily,e.defaultFontFamily);return{size:i,style:r,family:o,font:a.fontString(i,r,o)}}function u(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function h(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s<e.length;++s)t.fillText(e[s],n.x,r),r+=o;else t.fillText(e,n.x,n.y)}function c(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function f(t){return a.isNumber(t)?t:0}var g=t.LinearScaleBase.extend({setDimensions:function(){var t=this,n=t.options,i=n.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var r=a.min([t.height,t.width]),o=a.valueOrDefault(i.fontSize,e.defaultFontSize);t.drawingArea=n.display?r/2-(o/2+i.backdropPaddingY):r/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(r,o){if(e.isDatasetVisible(o)){var s=e.getDatasetMeta(o);a.each(r.data,function(e,a){var r=+t.getRightValue(e);isNaN(r)||s.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,n=a.valueOrDefault(t.fontSize,e.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*n)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t;this.options.pointLabels.display?function(t){var e,n,i,r=l(t),o=Math.min(t.height/2,t.width/2),d={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=r.font,t._pointLabelSizes=[];var c,f,g,m=s(t);for(e=0;e<m;e++){i=t.getPointPosition(e,o),c=t.ctx,f=r.size,n=a.isArray(g=t.pointLabels[e]||"")?{w:a.longestText(c,c.font,g),h:g.length*f+1.5*(g.length-1)*f}:{w:c.measureText(g).width,h:f},t._pointLabelSizes[e]=n;var p=t.getIndexAngle(e),v=a.toDegrees(p)%360,y=u(v,i.x,n.w,0,180),b=u(v,i.y,n.h,90,270);y.start<d.l&&(d.l=y.start,h.l=p),y.end>d.r&&(d.r=y.end,h.r=p),b.start<d.t&&(d.t=b.start,h.t=p),b.end>d.b&&(d.b=b.end,h.b=p)}t.setReductions(o,d,h)}(this):(t=Math.min(this.height/2,this.width/2),this.drawingArea=Math.round(t),this.setCenterPoint(0,0,0,0))},setReductions:function(t,e,n){var i=e.l/Math.sin(n.l),a=Math.max(e.r-this.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),o=-Math.max(e.b-this.height,0)/Math.cos(n.b);i=f(i),a=f(a),r=f(r),o=f(o),this.drawingArea=Math.min(Math.round(t-(i+a)/2),Math.round(t-(r+o)/2)),this.setCenterPoint(i,a,r,o)},setCenterPoint:function(t,e,n,i){var a=this,r=n+a.drawingArea,o=a.height-i-a.drawingArea;a.xCenter=Math.round((t+a.drawingArea+(a.width-e-a.drawingArea))/2+a.left),a.yCenter=Math.round((r+o)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/s(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(n)*e)+this.xCenter,y:Math.round(Math.sin(n)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0)},draw:function(){var t=this,n=t.options,i=n.gridLines,r=n.ticks,o=a.valueOrDefault;if(n.display){var u=t.ctx,f=this.getIndexAngle(0),g=o(r.fontSize,e.defaultFontSize),m=o(r.fontStyle,e.defaultFontStyle),p=o(r.fontFamily,e.defaultFontFamily),v=a.fontString(g,m,p);a.each(t.ticks,function(n,l){if(l>0||r.reverse){var d=t.getDistanceFromCenterForValue(t.ticksAsNumbers[l]);if(i.display&&0!==l&&function(t,e,n,i){var r=t.ctx;if(r.strokeStyle=a.valueAtIndexOrDefault(e.color,i-1),r.lineWidth=a.valueAtIndexOrDefault(e.lineWidth,i-1),t.options.gridLines.circular)r.beginPath(),r.arc(t.xCenter,t.yCenter,n,0,2*Math.PI),r.closePath(),r.stroke();else{var o=s(t);if(0===o)return;r.beginPath();var l=t.getPointPosition(0,n);r.moveTo(l.x,l.y);for(var u=1;u<o;u++)l=t.getPointPosition(u,n),r.lineTo(l.x,l.y);r.closePath(),r.stroke()}}(t,i,d,l),r.display){var h=o(r.fontColor,e.defaultFontColor);if(u.font=v,u.save(),u.translate(t.xCenter,t.yCenter),u.rotate(f),r.showLabelBackdrop){var c=u.measureText(n).width;u.fillStyle=r.backdropColor,u.fillRect(-c/2-r.backdropPaddingX,-d-g/2-r.backdropPaddingY,c+2*r.backdropPaddingX,g+2*r.backdropPaddingY)}u.textAlign="center",u.textBaseline="middle",u.fillStyle=h,u.fillText(n,0,-d),u.restore()}}}),(n.angleLines.display||n.pointLabels.display)&&function(t){var n=t.ctx,i=t.options,r=i.angleLines,o=i.pointLabels;n.lineWidth=r.lineWidth,n.strokeStyle=r.color;var u=t.getDistanceFromCenterForValue(i.ticks.reverse?t.min:t.max),f=l(t);n.textBaseline="top";for(var g=s(t)-1;g>=0;g--){if(r.display){var m=t.getPointPosition(g,u);n.beginPath(),n.moveTo(t.xCenter,t.yCenter),n.lineTo(m.x,m.y),n.stroke(),n.closePath()}if(o.display){var p=t.getPointPosition(g,u+5),v=a.valueAtIndexOrDefault(o.fontColor,g,e.defaultFontColor);n.font=f.font,n.fillStyle=v;var y=t.getIndexAngle(g),b=a.toDegrees(y);n.textAlign=d(b),c(b,t._pointLabelSizes[g],p),h(n,t.pointLabels[g]||"",p,f.size)}}}(t)}}});r.registerScaleType("radialLinear",g,n)}},{26:26,34:34,35:35,46:46}],59:[function(t,e,n){"use strict";var i=t(6);i="function"==typeof i?i:window.moment;var a=t(26),r=t(46),o=t(33),s=t(34),l=Number.MIN_SAFE_INTEGER||-9007199254740991,u=Number.MAX_SAFE_INTEGER||9007199254740991,d={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,15,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,15,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},h=Object.keys(d);function c(t,e){return t-e}function f(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e<n;++e)a[i=t[e]]||(a[i]=!0,r.push(i));return r}function g(t,e,n,i){var a=function(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(r=t[i=o+s>>1],!(a=t[i-1]||null))return{lo:null,hi:r};if(r[e]<n)o=i+1;else{if(!(a[e]>n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e];return r[i]+(o[i]-r[i])*(s?(n-r[e])/s:0)}function m(t,e){var n=e.parser,a=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof a?i(t,a):(t instanceof i||(t=i(t)),t.isValid()?t:"function"==typeof a?a(t):t)}function p(t,e){if(r.isNullOrUndef(t))return null;var n=e.options.time,i=m(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function v(t){for(var e=h.indexOf(t)+1,n=h.length;e<n;++e)if(d[h[e]].common)return h[e]}e.exports=function(){var t=o.extend({initialize:function(){if(!i)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),o.prototype.initialize.call(this)},update:function(){var t=this.options;return t.time&&t.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),o.prototype.update.apply(this,arguments)},getRightValue:function(t){return t&&void 0!==t.t&&(t=t.t),o.prototype.getRightValue.call(this,t)},determineDataLimits:function(){var t,e,n,a,o,s,d=this,h=d.chart,g=d.options.time,m=g.unit||"day",v=u,y=l,b=[],x=[],_=[];for(t=0,n=h.data.labels.length;t<n;++t)_.push(p(h.data.labels[t],d));for(t=0,n=(h.data.datasets||[]).length;t<n;++t)if(h.isDatasetVisible(t))if(r.isObject((o=h.data.datasets[t].data)[0]))for(x[t]=[],e=0,a=o.length;e<a;++e)s=p(o[e],d),b.push(s),x[t][e]=s;else b.push.apply(b,_),x[t]=_.slice(0);else x[t]=[];_.length&&(_=f(_).sort(c),v=Math.min(v,_[0]),y=Math.max(y,_[_.length-1])),b.length&&(b=f(b).sort(c),v=Math.min(v,b[0]),y=Math.max(y,b[b.length-1])),v=p(g.min,d)||v,y=p(g.max,d)||y,v=v===u?+i().startOf(m):v,y=y===l?+i().endOf(m)+1:y,d.min=Math.min(v,y),d.max=Math.max(v+1,y),d._horizontal=d.isHorizontal(),d._table=[],d._timestamps={data:b,datasets:x,labels:_}},buildTicks:function(){var t,e,n,a=this,o=a.min,s=a.max,l=a.options,c=l.time,f=[],y=[];switch(l.ticks.source){case"data":f=a._timestamps.data;break;case"labels":f=a._timestamps.labels;break;case"auto":default:f=function(t,e,n,a){var o,s=a.time,l=s.unit||function(t,e,n,i){var a,r,o=h.length;for(a=h.indexOf(s.minUnit);a<o-1;++a)if((r=d[h[a]]).common&&Math.ceil((n-e)/((r.steps?r.steps[r.steps.length-1]:u)*r.size))<=i)return h[a];return h[o-1]}(0,t,e,n),c=v(l),f=r.valueOrDefault(s.stepSize,s.unitStepSize),g="week"===l&&s.isoWeekday,m=a.ticks.major.enabled,p=d[l],y=i(t),b=i(e),x=[];for(f||(f=function(t,e,n,i){var a,r,o,s=e-t,u=d[l],h=u.size,c=u.steps;if(!c)return Math.ceil(s/(i*h));for(a=0,r=c.length;a<r&&(o=c[a],!(Math.ceil(s/(h*o))<=i));++a);return o}(t,e,0,n)),g&&(y=y.isoWeekday(g),b=b.isoWeekday(g)),y=y.startOf(g?"day":l),(b=b.startOf(g?"day":l))<e&&b.add(1,l),o=i(y),m&&c&&!g&&!s.round&&(o.startOf(c),o.add(~~((y-o)/(p.size*f))*f,l));o<b;o.add(f,l))x.push(+o);return x.push(+o),x}(o,s,a.getLabelCapacity(o),l)}for("ticks"===l.bounds&&f.length&&(o=f[0],s=f[f.length-1]),o=p(c.min,a)||o,s=p(c.max,a)||s,t=0,e=f.length;t<e;++t)(n=f[t])>=o&&n<=s&&y.push(n);return a.min=o,a.max=s,a._unit=c.unit||function(t,e,n,r){var o,s,l=i.duration(i(a.max).diff(i(n)));for(o=h.length-1;o>=h.indexOf(e);o--)if(d[s=h[o]].common&&l.as(s)>=t.length)return s;return h[e?h.indexOf(e):0]}(y,c.minUnit,a.min),a._majorUnit=v(a._unit),a._table=function(t,e,n,i){if("linear"===l.distribution||!t.length)return[{time:e,pos:0},{time:n,pos:1}];var a,r,o,s,u,d=[],h=[e];for(a=0,r=t.length;a<r;++a)(s=t[a])>e&&s<n&&h.push(s);for(h.push(n),a=0,r=h.length;a<r;++a)u=h[a+1],s=h[a],void 0!==(o=h[a-1])&&void 0!==u&&Math.round((u+o)/2)===s||d.push({time:s,pos:a/(r-1)});return d}(a._timestamps.data,o,s),a._offsets=function(t,e,n,i,a){var r,o=0,s=0;return a.offset&&e.length&&(a.time.min||(r=e[0],o=(g(t,"time",e.length>1?e[1]:i,"pos")-g(t,"time",r,"pos"))/2),a.time.max||(r=e.length>1?e[e.length-2]:n,s=(g(t,"time",e[e.length-1],"pos")-g(t,"time",r,"pos"))/2)),{left:o,right:s}}(a._table,y,o,s,l),a._labelFormat=function(t,e){var n,i,a,r=t.length;for(n=0;n<r;n++){if(0!==(i=m(t[n],e)).millisecond())return"MMM D, YYYY h:mm:ss.SSS a";0===i.second()&&0===i.minute()&&0===i.hour()||(a=!0)}return a?"MMM D, YYYY h:mm:ss a":"MMM D, YYYY"}(a._timestamps.data,c),function(t,e){var n,a,r,o,s=[];for(n=0,a=t.length;n<a;++n)r=t[n],o=!!e&&r===+i(r).startOf(e),s.push({value:r,major:o});return s}(y,a._majorUnit)},getLabelForIndex:function(t,e){var n=this.chart.data,i=this.options.time,a=n.labels&&t<n.labels.length?n.labels[t]:"",o=n.datasets[e].data[t];return r.isObject(o)&&(a=this.getRightValue(o)),i.tooltipFormat?m(a,i).format(i.tooltipFormat):"string"==typeof a?a:m(a,i).format(this._labelFormat)},tickFormatFunction:function(t,e,n,i){var a=this.options,o=t.valueOf(),s=a.time.displayFormats,l=s[this._unit],u=this._majorUnit,d=s[u],h=t.clone().startOf(u).valueOf(),c=a.ticks.major,f=c.enabled&&u&&d&&o===h,g=t.format(i||(f?d:l)),m=f?c:a.ticks.minor,p=r.valueOrDefault(m.callback,m.userCallback);return p?p(g,e,n):g},convertTicksToLabels:function(t){var e,n,a=[];for(e=0,n=t.length;e<n;++e)a.push(this.tickFormatFunction(i(t[e].value),e,t));return a},getPixelForOffset:function(t){var e=this,n=e._horizontal?e.width:e.height,i=e._horizontal?e.left:e.top,a=g(e._table,"time",t,"pos");return i+n*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,n){var i=null;if(void 0!==e&&void 0!==n&&(i=this._timestamps.datasets[n][e]),null===i&&(i=p(t,this)),null!==i)return this.getPixelForOffset(i)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,n=e._horizontal?e.width:e.height,a=g(e._table,"pos",(n?(t-(e._horizontal?e.left:e.top))/n:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,"time");return i(a)},getLabelWidth:function(t){var e=this.options.ticks,n=this.ctx.measureText(t).width,i=r.toRadians(e.maxRotation),o=Math.cos(i),s=Math.sin(i);return n*o+r.valueOrDefault(e.fontSize,a.global.defaultFontSize)*s},getLabelCapacity:function(t){var e=this,n=e.options.time.displayFormats.millisecond,a=e.tickFormatFunction(i(t),0,[],n),r=e.getLabelWidth(a),o=e.isHorizontal()?e.width:e.height,s=Math.floor(o/r);return s>0?s:1}});s.registerScaleType("time",t,{position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}})}},{26:26,33:33,34:34,46:46,6:6}]},{},[7])(7)}); \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/styles.f5317b15474518dffebc.css b/src/pybind/mgr/dashboard/frontend/dist/en-US/styles.f5317b15474518dffebc.css
new file mode 100644
index 00000000..c33da468
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/styles.f5317b15474518dffebc.css
@@ -0,0 +1,27 @@
+.toast-center-center{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}.toast-title{font-weight:700}.toast-message{word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#fff;text-shadow:0 1px 0 #fff}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0}.toast-container{pointer-events:none;position:fixed;z-index:999999}.toast-container *{box-sizing:border-box}.toast-container .ngx-toastr{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;background-size:24px;box-shadow:0 0 12px #999;color:#fff}.toast-container .ngx-toastr:hover{box-shadow:0 0 12px #000;opacity:1;cursor:pointer}.toast-info{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='512' height='512'%3E%3Cpath fill='rgb(255,255,255)' d='M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z'/%3E%3C/svg%3E")}.toast-error{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='512' height='512'%3E%3Cpath fill='rgb(255,255,255)' d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z'/%3E%3C/svg%3E")}.toast-success{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='512' height='512'%3E%3Cpath fill='rgb(255,255,255)' d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E")}.toast-container.toast-bottom-center .ngx-toastr,.toast-container.toast-top-center .ngx-toastr{width:300px;margin-left:auto;margin-right:auto}.toast-container.toast-bottom-full-width .ngx-toastr,.toast-container.toast-top-full-width .ngx-toastr{width:96%;margin-left:auto;margin-right:auto}.ngx-toastr{background-color:#030303;pointer-events:auto}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512' width='576' height='512'%3E%3Cpath fill='rgb(255,255,255)' d='M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'/%3E%3C/svg%3E");background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4}@media all and (max-width:240px){.toast-container .ngx-toastr.div{padding:8px 8px 8px 50px;width:11em}.toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px) and (max-width:480px){.toast-container .ngx-toastr.div{padding:8px 8px 8px 50px;width:18em}.toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px) and (max-width:768px){.toast-container .ngx-toastr.div{padding:15px 15px 15px 50px;width:25em}}/*!
+ * Bootstrap v3.4.1 (https://getbootstrap.com/)
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0;vertical-align:middle}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:"Glyphicons Halflings";src:url(glyphicons-halflings-regular.f4769f9bdb7466be6508.eot);src:url(glyphicons-halflings-regular.f4769f9bdb7466be6508.eot?#iefix) format("embedded-opentype"),url(glyphicons-halflings-regular.448c34a56d699c29117a.woff2) format("woff2"),url(glyphicons-halflings-regular.fa2772327f55d8198301.woff) format("woff"),url(glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf) format("truetype"),url(glyphicons-halflings-regular.89889688147bd7575d63.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before,.glyphicon-btc:before,.glyphicon-xbt:before{content:"\e227"}.glyphicon-jpy:before,.glyphicon-yen:before{content:"\00a5"}.glyphicon-rub:before,.glyphicon-ruble:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*,:after,:before{box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}figure{margin:0}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:.2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{box-sizing:content-box;height:0;margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}abbr[data-original-title],abbr[title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{overflow:auto;display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{border-collapse:collapse;border-spacing:0;background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover,.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.checkbox label,.radio label{min-height:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px;outline:0}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child:not(:first-child){border-radius:0 0 4px 4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center;margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0;border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar{border-radius:4px}.navbar-header{float:left}.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}.navbar-static-top{z-index:1000;border-width:0 0 1px}.navbar-brand{float:left;height:50px;padding:15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}.navbar-static-top{border-radius:0}.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}.navbar-toggle{display:none}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}.navbar-form{padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin:8px -15px}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;box-shadow:none}.navbar-text{float:left;margin-right:15px;margin-left:15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:2s linear infinite progress-bar-stripes;animation:2s linear infinite progress-bar-stripes}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-striped .progress-bar-info{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;text-align:center;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:left .6s ease-in-out;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}.visible-xs-block{display:block!important}.visible-xs-inline{display:inline!important}.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}.visible-sm-block{display:block!important}.visible-sm-inline{display:inline!important}.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}.visible-md-block{display:block!important}.visible-md-inline{display:inline!important}.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}.visible-lg-block{display:block!important}.visible-lg-inline{display:inline!important}.visible-lg-inline-block{display:inline-block!important}.hidden-lg{display:none!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}.hidden-print{display:none!important}}/*!
+Fork Awesome 1.1.6
+License - https://forkaweso.me/Fork-Awesome/license
+
+Copyright 2018 Dave Gandy & Fork Awesome
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */@font-face{font-family:ForkAwesome;src:url(forkawesome-webfont.35e77a38ca9d85c4e897.eot?v=1.1.6);src:url(forkawesome-webfont.35e77a38ca9d85c4e897.eot?#iefix&v=1.1.6) format('embedded-opentype'),url(forkawesome-webfont.3a9e014c2469ffa65a0e.woff2?v=1.1.6) format('woff2'),url(forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woff?v=1.1.6) format('woff'),url(forkawesome-webfont.fc46f3dae03b2b2e1cee.ttf?v=1.1.6) format('truetype'),url(forkawesome-webfont.78dcc9c4999659b8026a.svg?v=1.1.6#forkawesomeregular) format('svg');font-weight:400;font-style:normal}.fa{text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-asterisk:before{content:"\f069"}.fa-bell-o:before{content:"\f0f3"}.fa-google-plus-g:before,.fa-google-plus:before{content:"\f0d5"}.fa-bell:before{content:"\f0a2"}.fa-cutlery:before,.fa-utensils:before{content:"\f0f5"}.fa-gbp:before,.fa-pound:before{content:"\f154"}.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-desc:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-desc:before,.fa-sort-amount-up:before{content:"\f161"}.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-desc:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f1b1"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-cc:before,.fa-closed-captioning:before{content:"\f20a"}.fa-diamond:before,.fa-gem:before{content:"\f219"}.fa-vimeo-v:before,.fa-vimeo:before{content:"\f27d"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-gnupg:before{content:"\f30d"}.fa-php:before{content:"\f30e"}.fa-ffmpeg:before{content:"\f30f"}.fa-joplin:before{content:"\f310"}.fa-syncthing:before{content:"\f311"}.fa-inkscape:before{content:"\f312"}.fa-matrix-org:before{content:"\f313"}.fa-pixelfed:before{content:"\f314"}.fa-bootstrap:before{content:"\f315"}.fa-dev-to:before{content:"\f316"}.fa-hashnode:before{content:"\f317"}.fa-jirafeau:before{content:"\f318"}.fa-emby:before{content:"\f319"}.fa-wikidata:before{content:"\f31a"}.fa-gimp:before{content:"\f31b"}.fa-c:before{content:"\f31c"}.fa-digitalocean:before{content:"\f31d"}.fa-att:before{content:"\f31e"}.fa-gitea:before{content:"\f31f"}.fa-file-epub:before{content:"\f321"}.fa-python:before{content:"\f322"}.fa-archlinux:before{content:"\f323"}.fa-pleroma:before{content:"\f324"}.fa-unsplash:before{content:"\f325"}.fa-hackster:before{content:"\f326"}.fa-spell-check:before{content:"\f327"}.fa-moon:before{content:"\f328"}.fa-sun:before{content:"\f329"}.fa-f-droid:before{content:"\f32a"}.fa-biometric:before{content:"\f32b"}.checkbox{padding-left:20px}.checkbox label{display:inline-block;vertical-align:middle;position:relative;padding-left:5px}.checkbox label::before{content:"";display:inline-block;position:absolute;width:17px;height:17px;left:0;margin-left:-20px;border:1px solid #ccc;border-radius:3px;background-color:#fff;-webkit-transition:border .15s ease-in-out,color .15s ease-in-out;transition:border .15s ease-in-out,color .15s ease-in-out}.checkbox label::after{display:inline-block;position:absolute;width:16px;height:16px;left:0;top:0;margin-left:-20px;padding-left:3px;padding-top:1px;font-size:11px;color:#555}.checkbox input[type=checkbox],.checkbox input[type=radio]{opacity:0;z-index:1}.checkbox input[type=checkbox]:focus+label::before,.checkbox input[type=radio]:focus+label::before{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.checkbox input[type=checkbox]:checked+label::after,.checkbox input[type=radio]:checked+label::after{font-family:FontAwesome;content:"\f00c"}.checkbox input[type=checkbox]:indeterminate+label::after,.checkbox input[type=radio]:indeterminate+label::after{display:block;content:"";width:10px;height:3px;background-color:#555;border-radius:2px;margin-left:-16.5px;margin-top:7px}.checkbox input[type=checkbox]:disabled+label,.checkbox input[type=radio]:disabled+label{opacity:.65}.checkbox input[type=checkbox]:disabled+label::before,.checkbox input[type=radio]:disabled+label::before{background-color:#eee;cursor:not-allowed}.checkbox.checkbox-circle label::before{border-radius:50%}.checkbox.checkbox-inline{margin-top:0}.checkbox-primary input[type=checkbox]:checked+label::before,.checkbox-primary input[type=radio]:checked+label::before{background-color:#337ab7;border-color:#337ab7}.checkbox-primary input[type=checkbox]:checked+label::after,.checkbox-primary input[type=radio]:checked+label::after{color:#fff}.checkbox-danger input[type=checkbox]:checked+label::before,.checkbox-danger input[type=radio]:checked+label::before{background-color:#d9534f;border-color:#d9534f}.checkbox-danger input[type=checkbox]:checked+label::after,.checkbox-danger input[type=radio]:checked+label::after{color:#fff}.checkbox-info input[type=checkbox]:checked+label::before,.checkbox-info input[type=radio]:checked+label::before{background-color:#5bc0de;border-color:#5bc0de}.checkbox-info input[type=checkbox]:checked+label::after,.checkbox-info input[type=radio]:checked+label::after{color:#fff}.checkbox-warning input[type=checkbox]:checked+label::before,.checkbox-warning input[type=radio]:checked+label::before{background-color:#f0ad4e;border-color:#f0ad4e}.checkbox-warning input[type=checkbox]:checked+label::after,.checkbox-warning input[type=radio]:checked+label::after{color:#fff}.checkbox-success input[type=checkbox]:checked+label::before,.checkbox-success input[type=radio]:checked+label::before{background-color:#5cb85c;border-color:#5cb85c}.checkbox-success input[type=checkbox]:checked+label::after,.checkbox-success input[type=radio]:checked+label::after{color:#fff}.checkbox-primary input[type=checkbox]:indeterminate+label::before,.checkbox-primary input[type=radio]:indeterminate+label::before{background-color:#337ab7;border-color:#337ab7}.checkbox-primary input[type=checkbox]:indeterminate+label::after,.checkbox-primary input[type=radio]:indeterminate+label::after{background-color:#fff}.checkbox-danger input[type=checkbox]:indeterminate+label::before,.checkbox-danger input[type=radio]:indeterminate+label::before{background-color:#d9534f;border-color:#d9534f}.checkbox-danger input[type=checkbox]:indeterminate+label::after,.checkbox-danger input[type=radio]:indeterminate+label::after{background-color:#fff}.checkbox-info input[type=checkbox]:indeterminate+label::before,.checkbox-info input[type=radio]:indeterminate+label::before{background-color:#5bc0de;border-color:#5bc0de}.checkbox-info input[type=checkbox]:indeterminate+label::after,.checkbox-info input[type=radio]:indeterminate+label::after{background-color:#fff}.checkbox-warning input[type=checkbox]:indeterminate+label::before,.checkbox-warning input[type=radio]:indeterminate+label::before{background-color:#f0ad4e;border-color:#f0ad4e}.checkbox-warning input[type=checkbox]:indeterminate+label::after,.checkbox-warning input[type=radio]:indeterminate+label::after{background-color:#fff}.checkbox-success input[type=checkbox]:indeterminate+label::before,.checkbox-success input[type=radio]:indeterminate+label::before{background-color:#5cb85c;border-color:#5cb85c}.checkbox-success input[type=checkbox]:indeterminate+label::after,.checkbox-success input[type=radio]:indeterminate+label::after{background-color:#fff}.radio{padding-left:20px}.radio label{display:inline-block;vertical-align:middle;position:relative;padding-left:5px}.radio label::before{content:"";display:inline-block;position:absolute;width:17px;height:17px;left:0;margin-left:-20px;border:1px solid #ccc;border-radius:50%;background-color:#fff;-webkit-transition:border .15s ease-in-out;transition:border .15s ease-in-out}.radio label::after{display:inline-block;position:absolute;content:" ";width:11px;height:11px;left:3px;top:3px;margin-left:-20px;border-radius:50%;background-color:#555;-webkit-transform:scale(0,0);transform:scale(0,0);-webkit-transition:-webkit-transform .1s cubic-bezier(.8,-.33,.2,1.33);transition:-webkit-transform .1s cubic-bezier(.8,-.33,.2,1.33);transition:transform .1s cubic-bezier(.8,-.33,.2,1.33);transition:transform .1s cubic-bezier(.8,-.33,.2,1.33),-webkit-transform .1s cubic-bezier(.8,-.33,.2,1.33)}.radio input[type=radio]{opacity:0;z-index:1}.radio input[type=radio]:focus+label::before{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.radio input[type=radio]:checked+label::after{-webkit-transform:scale(1,1);transform:scale(1,1)}.radio input[type=radio]:disabled+label{opacity:.65}.radio input[type=radio]:disabled+label::before{cursor:not-allowed}.radio.radio-inline{margin-top:0}.radio-primary input[type=radio]+label::after{background-color:#337ab7}.radio-primary input[type=radio]:checked+label::before{border-color:#337ab7}.radio-primary input[type=radio]:checked+label::after{background-color:#337ab7}.radio-danger input[type=radio]+label::after{background-color:#d9534f}.radio-danger input[type=radio]:checked+label::before{border-color:#d9534f}.radio-danger input[type=radio]:checked+label::after{background-color:#d9534f}.radio-info input[type=radio]+label::after{background-color:#5bc0de}.radio-info input[type=radio]:checked+label::before{border-color:#5bc0de}.radio-info input[type=radio]:checked+label::after{background-color:#5bc0de}.radio-warning input[type=radio]+label::after{background-color:#f0ad4e}.radio-warning input[type=radio]:checked+label::before{border-color:#f0ad4e}.radio-warning input[type=radio]:checked+label::after{background-color:#f0ad4e}.radio-success input[type=radio]+label::after{background-color:#5cb85c}.radio-success input[type=radio]:checked+label::before{border-color:#5cb85c}.radio-success input[type=radio]:checked+label::after{background-color:#5cb85c}input[type=checkbox].styled:checked+label:after,input[type=radio].styled:checked+label:after{font-family:FontAwesome;content:"\f00c"}input[type=checkbox] .styled:checked+label::after,input[type=checkbox] .styled:checked+label::before,input[type=radio] .styled:checked+label::after,input[type=radio] .styled:checked+label::before{color:#fff}.bs-datepicker{display:-webkit-box;display:flex;-webkit-box-align:stretch;align-items:stretch;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;background:#fff;box-shadow:0 0 10px 0 #aaa;position:relative;z-index:1}.bs-datepicker:after{clear:both;content:'';display:block}.bs-datepicker bs-day-picker{float:left}.bs-datepicker button:active,.bs-datepicker button:focus,.bs-datepicker button:hover,.bs-datepicker input:active,.bs-datepicker input:focus,.bs-datepicker input:hover,.bs-datepicker-btns button:active,.bs-datepicker-btns button:focus,.bs-datepicker-btns button:hover,.bs-datepicker-predefined-btns button:active,.bs-datepicker-predefined-btns button:focus{outline:0}.bs-datepicker-head{min-width:270px;height:50px;padding:10px;border-radius:3px 3px 0 0;text-align:justify}.bs-datepicker-head:after{content:"";display:inline-block;vertical-align:top;width:100%}.bs-datepicker-head button{display:inline-block;vertical-align:top;padding:0;height:30px;line-height:30px;border:0;background:0 0;text-align:center;cursor:pointer;color:#fff;-webkit-transition:.3s;transition:.3s}.bs-datepicker-head button[disabled],.bs-datepicker-head button[disabled]:active,.bs-datepicker-head button[disabled]:hover{background:rgba(221,221,221,.3);color:#f5f5f5;cursor:not-allowed}.bs-datepicker-head button.next,.bs-datepicker-head button.previous{border-radius:50%;width:30px;height:30px}.bs-datepicker-head button.next span,.bs-datepicker-head button.previous span{font-size:28px;line-height:1;display:inline-block;position:relative;height:100%;width:100%;border-radius:50%}.bs-datepicker-head button.current{border-radius:15px;max-width:155px;padding:0 13px}.bs-datepicker-head button:hover{background-color:rgba(0,0,0,.1)}.bs-datepicker-head button:active{background-color:rgba(0,0,0,.2)}.bs-datepicker-body{padding:10px;border-radius:0 0 3px 3px;min-height:232px;min-width:278px;border:1px solid #e9edf0}.bs-datepicker-body .days.weeks{position:relative;z-index:1}.bs-datepicker-body table{width:100%;border-collapse:separate;border-spacing:0}.bs-datepicker-body table th{font-size:13px;color:#9aaec1;font-weight:400;text-align:center}.bs-datepicker-body table td{color:#54708b;text-align:center;position:relative;padding:0}.bs-datepicker-body table td span{display:block;margin:0 auto;font-size:13px;border-radius:50%;position:relative;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.bs-datepicker-body table td:not(.disabled):not(.week) span:not(.disabled):not(.is-other-month){cursor:pointer}.bs-datepicker-body table td span.is-highlighted:not(.disabled):not(.selected),.bs-datepicker-body table td.is-highlighted:not(.disabled):not(.selected) span{background-color:#e9edf0;-webkit-transition:none;transition:0s}.bs-datepicker-body table td span.is-active-other-month:not(.disabled):not(.selected),.bs-datepicker-body table td.is-active-other-month:not(.disabled):not(.selected) span{background-color:#e9edf0;-webkit-transition:none;transition:0s;cursor:pointer}.bs-datepicker-body table td span.disabled,.bs-datepicker-body table td.disabled span{color:#9aaec1}.bs-datepicker-body table td span.selected,.bs-datepicker-body table td.selected span{color:#fff}.bs-datepicker-body table td span.is-other-month,.bs-datepicker-body table td.is-other-month span{color:rgba(0,0,0,.25)}.bs-datepicker-body table td.active{position:relative}.bs-datepicker-body table td.active.select-start:before{left:35%}.bs-datepicker-body table td.active.select-end:before{left:-85%}.bs-datepicker-body table td span.active.select-end:after,.bs-datepicker-body table td span.active.select-start:after,.bs-datepicker-body table td.active.select-end span:after,.bs-datepicker-body table td.active.select-start span:after{content:"";display:block;position:absolute;z-index:-1;width:100%;height:100%;-webkit-transition:.3s;transition:.3s;top:0;border-radius:50%}.bs-datepicker-body table td span:before,.bs-datepicker-body table td:before{content:"";display:block;position:absolute;z-index:-1;top:6px;bottom:6px;left:-2px;right:-2px;box-sizing:content-box;background:0 0}.bs-datepicker-body table td.active.select-start+td.active:before{left:-20%}.bs-datepicker-body table td:last-child.active:before{border-radius:0 3px 3px 0;width:125%;left:-25%}.bs-datepicker-body table td span[class*=select-],.bs-datepicker-body table td[class*=select-] span{border-radius:50%;color:#fff}.bs-datepicker-body table.days span.active:not(.select-start):before,.bs-datepicker-body table.days span.in-range:not(.select-start):before,.bs-datepicker-body table.days td.active:not(.select-start):before,.bs-datepicker-body table.days td.in-range:not(.select-start):before{background:#e9edf0}.bs-datepicker-body table.days span{width:32px;height:32px;line-height:32px}.bs-datepicker-body table.days span.select-start{z-index:2}.bs-datepicker-body table.days span.in-range.select-end:before,.bs-datepicker-body table.days span.is-highlighted.in-range:before{background:0 0;right:0;left:0}.bs-datepicker-body table.days td.active+td.is-highlighted:before,.bs-datepicker-body table.days td.active+td.select-end:before,.bs-datepicker-body table.days td.in-range+td.is-highlighted:before,.bs-datepicker-body table.days td.in-range+td.select-end:before,.bs-datepicker-body table.days td.select-start+td.is-highlighted:before,.bs-datepicker-body table.days td.select-start+td.select-end:before{background:#e9edf0;width:100%}.bs-datepicker-body table.weeks tr td:nth-child(2).active:before{border-radius:3px 0 0 3px;left:0;width:100%}.bs-datepicker-body table:not(.weeks) tr td:first-child:before{border-radius:3px 0 0 3px}.bs-datepicker-body table.years td span{width:46px;height:46px;line-height:45px;margin:0 auto}.bs-datepicker-body table.years tr:not(:last-child) td span{margin-bottom:8px}.bs-datepicker-body table.months td{height:52px}.bs-datepicker-body table.months td span{padding:6px;border-radius:15px}.bs-datepicker .current-timedate{color:#54708b;font-size:15px;text-align:center;height:30px;line-height:30px;border-radius:20px;border:1px solid #e9edf0;margin-bottom:10px;cursor:pointer;text-transform:uppercase;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.bs-datepicker .current-timedate span:not(:empty):before{content:"";width:15px;height:16px;display:inline-block;margin-right:4px;vertical-align:text-bottom;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAABMklEQVQoU9VTwW3CQBCcOUgBtEBKSAukAnBKME+wFCAlYIhk8sQlxFABtJAScAsuAPBEewYcxCP8ouxrPDsza61uiVN1o6RNHD4htSCmq49RfO71BvMJqBBkITRf1kmUW49nQRC9h1I5AZlBClaL8aP1fKgOOxCx8aSLs+Q19eZuNO8QmPqJRtDFguy7OAcDbJPs+/BKVPDIPrvD2ZJgWAmVe7O0rI0Vqs1seyWUXpuJoppYCa5L+U++NpNPkr5OE2oMdARsb3gykJT5ydZcL8Z9Ww60nxg2LhjON9li9OwXZzo+xLbp3nC2s9CL2RrueGyVrgwNm8HpsCzZ9EEW6kqXlo1GQe03FzP/7W8Hl0dBtu7Bf7zt6mIwvX1RvzDCm7+q3mAW0Dl/GPdUCeXrZLT9BrDrGkm4qlPvAAAAAElFTkSuQmCC)}.bs-datepicker-multiple{border-radius:4px 0 0 4px}.bs-datepicker-multiple+.bs-datepicker-multiple{margin-left:10px}.bs-datepicker-multiple .bs-datepicker{box-shadow:none;position:relative}.bs-datepicker-multiple .bs-datepicker:not(:last-child){padding-right:10px}.bs-datepicker-multiple .bs-datepicker+.bs-datepicker:after{content:"";display:block;width:14px;height:10px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAKCAYAAABrGwT5AAAA1ElEQVQoU42RsQrCUAxF77VuDu7O4oMWW//BURBBpZvgKk4uIrjoqKOTf+DopIO4uYggtFTfw3+pkQqCW1/G5J7kJiFy4m5MxUlxAzgIPHX+lzMPzupRYlYgxiR7vqsOP8YKzsTx0yxFMCUZ+q7aZzlr+OvgoWcAFyAHgat2jLWu48252DdqAihDJGSSJNUUxYmQjs3+hPQBlAh2rG2LCOPnaw3IiGDX99TRCs7ASJsNhUOA7d/LcuHvRG22FIZvsNXw1MX6VZExCilOQKEfeLXr/10+aC9Ho7arh7oAAAAASUVORK5CYII=);position:absolute;top:25px;left:-8px}.bs-datepicker-multiple .bs-datepicker .left{float:left}.bs-datepicker-multiple .bs-datepicker .right{float:right}.bs-datepicker-container{padding:15px}.bs-datepicker .bs-media-container{display:-webkit-box;display:flex}@media (max-width:768px){.bs-datepicker .bs-media-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column}}.bs-datepicker-custom-range{padding:15px;background:#eee}.bs-datepicker-predefined-btns button{width:100%;display:block;height:30px;background-color:#9aaec1;border-radius:4px;color:#fff;border:0;margin-bottom:10px;padding:0 18px;text-align:left;-webkit-transition:.3s;transition:.3s}.bs-datepicker-predefined-btns button:active,.bs-datepicker-predefined-btns button:hover{background-color:#54708b}.bs-datepicker-buttons{display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-pack:end;justify-content:flex-end;padding-top:10px;border-top:1px solid #e9edf0}.bs-datepicker-buttons .btn-default{margin-left:10px}.bs-timepicker-container{padding:10px 0}.bs-timepicker-label{color:#54708b;margin-bottom:10px}.bs-timepicker-controls{display:inline-block;vertical-align:top;margin-right:10px}.bs-timepicker-controls button{width:20px;height:20px;border-radius:50%;border:0;background-color:#e9edf0;color:#54708b;font-size:16px;font-weight:700;vertical-align:middle;line-height:0;padding:0;-webkit-transition:.3s;transition:.3s}.bs-timepicker-controls button:hover{background-color:#d5dadd}.bs-timepicker-controls input{width:35px;height:25px;border-radius:13px;text-align:center;border:1px solid #e9edf0}.bs-timepicker .switch-time-format{text-transform:uppercase;min-width:54px;height:25px;border-radius:20px;border:1px solid #e9edf0;background:#fff;color:#54708b;font-size:13px}.bs-timepicker .switch-time-format img{vertical-align:initial;margin-left:4px}bs-datepicker-container,bs-daterangepicker-container{z-index:1080}@media (max-width:768px){.bs-datepicker-multiple{display:-webkit-box;display:flex}.bs-datepicker-multiple+.bs-datepicker-multiple{margin-top:10px;margin-left:0}}.theme-default .bs-datepicker-body table td span.selected,.theme-default .bs-datepicker-body table td span[class*=select-]:after,.theme-default .bs-datepicker-body table td.selected span,.theme-default .bs-datepicker-body table td[class*=select-] span:after,.theme-default .bs-datepicker-head{background-color:#777}.theme-default .bs-datepicker-body table td.week span{color:#777}.theme-default .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#777;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}.theme-green .bs-datepicker-body table td span.selected,.theme-green .bs-datepicker-body table td span[class*=select-]:after,.theme-green .bs-datepicker-body table td.selected span,.theme-green .bs-datepicker-body table td[class*=select-] span:after,.theme-green .bs-datepicker-head{background-color:#5cb85c}.theme-green .bs-datepicker-body table td.week span{color:#5cb85c}.theme-green .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#5cb85c;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}.theme-blue .bs-datepicker-body table td span.selected,.theme-blue .bs-datepicker-body table td span[class*=select-]:after,.theme-blue .bs-datepicker-body table td.selected span,.theme-blue .bs-datepicker-body table td[class*=select-] span:after,.theme-blue .bs-datepicker-head{background-color:#5bc0de}.theme-blue .bs-datepicker-body table td.week span{color:#5bc0de}.theme-blue .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#5bc0de;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}.theme-dark-blue .bs-datepicker-body table td span.selected,.theme-dark-blue .bs-datepicker-body table td span[class*=select-]:after,.theme-dark-blue .bs-datepicker-body table td.selected span,.theme-dark-blue .bs-datepicker-body table td[class*=select-] span:after,.theme-dark-blue .bs-datepicker-head{background-color:#337ab7}.theme-dark-blue .bs-datepicker-body table td.week span{color:#337ab7}.theme-dark-blue .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#337ab7;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}.theme-red .bs-datepicker-body table td span.selected,.theme-red .bs-datepicker-body table td span[class*=select-]:after,.theme-red .bs-datepicker-body table td.selected span,.theme-red .bs-datepicker-body table td[class*=select-] span:after,.theme-red .bs-datepicker-head{background-color:#d9534f}.theme-red .bs-datepicker-body table td.week span{color:#d9534f}.theme-red .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#d9534f;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}.theme-orange .bs-datepicker-body table td span.selected,.theme-orange .bs-datepicker-body table td span[class*=select-]:after,.theme-orange .bs-datepicker-body table td.selected span,.theme-orange .bs-datepicker-body table td[class*=select-] span:after,.theme-orange .bs-datepicker-head{background-color:#f0ad4e}.theme-orange .bs-datepicker-body table td.week span{color:#f0ad4e}.theme-orange .bs-datepicker-body table td.active-week span:hover{cursor:pointer;background-color:#f0ad4e;color:#fff;opacity:.5;-webkit-transition:none;transition:0s}/*!
+Fork Awesome 1.1.6
+License - https://forkaweso.me/Fork-Awesome/license
+
+Copyright 2018 Dave Gandy & Fork Awesome
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */@font-face{font-family:ForkAwesome;src:url(forkawesome-webfont.35e77a38ca9d85c4e897.eot?v=1.0.11);src:url(forkawesome-webfont.35e77a38ca9d85c4e897.eot?#iefix&v=1.0.11) format("embedded-opentype"),url(forkawesome-webfont.3a9e014c2469ffa65a0e.woff2?v=1.0.11) format("woff2"),url(forkawesome-webfont.44bbdbbfb5a10ba2d1ce.woff?v=1.0.11) format("woff"),url(forkawesome-webfont.fc46f3dae03b2b2e1cee.ttf?v=1.0.11) format("truetype"),url(forkawesome-webfont.78dcc9c4999659b8026a.svg?v=1.0.11#forkawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.form-group>.col-sm-12>.control-label>span.required,.form-group>.control-label>span.required{display:inline-block;font:14px/1 ForkAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.form-group>.col-sm-12>.control-label>span.fa-pull-left.required,.form-group>.control-label>span.fa-pull-left.required{margin-right:.3em}.fa.fa-pull-right,.form-group>.col-sm-12>.control-label>span.fa-pull-right.required,.form-group>.control-label>span.fa-pull-right.required{margin-left:.3em}.fa.pull-left,.form-group>.col-sm-12>.control-label>span.pull-left.required,.form-group>.control-label>span.pull-left.required{margin-right:.3em}.fa.pull-right,.form-group>.col-sm-12>.control-label>span.pull-right.required,.form-group>.control-label>span.pull-right.required{margin-left:.3em}.fa-spin{-webkit-animation:2s linear infinite fa-spin;animation:2s linear infinite fa-spin}.fa-pulse{-webkit-animation:1s steps(8) infinite fa-spin;animation:1s steps(8) infinite fa-spin}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before,.form-group>.col-sm-12>.control-label>span.required:before,.form-group>.control-label>span.required:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-globe-e:before{content:"\f304"}.fa-globe-w:before{content:"\f305"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-community:before,.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-medium-square:before{content:"\f2f8"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\f2a3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-address-card:before,.fa-vcard:before{content:"\f2bb"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.fa-mastodon:before{content:"\f2e1"}.fa-mastodon-alt:before{content:"\f2e2"}.fa-fork-awesome:before,.fa-fork-circle:before{content:"\f2e3"}.fa-peertube:before{content:"\f2e4"}.fa-diaspora:before{content:"\f2e5"}.fa-friendica:before{content:"\f2e6"}.fa-gnu-social:before{content:"\f2e7"}.fa-liberapay-square:before{content:"\f2e8"}.fa-liberapay:before{content:"\f2e9"}.fa-scuttlebutt:before,.fa-ssb:before{content:"\f2ea"}.fa-hubzilla:before{content:"\f2eb"}.fa-social-home:before{content:"\f2ec"}.fa-artstation:before{content:"\f2ed"}.fa-discord:before{content:"\f2ee"}.fa-discord-alt:before{content:"\f2ef"}.fa-patreon:before{content:"\f2f0"}.fa-snowdrift:before{content:"\f2f1"}.fa-activitypub:before{content:"\f2f2"}.fa-ethereum:before{content:"\f2f3"}.fa-keybase:before{content:"\f2f4"}.fa-shaarli:before{content:"\f2f5"}.fa-shaarli-o:before{content:"\f2f6"}.fa-cut-key:before,.fa-key-modern:before{content:"\f2f7"}.fa-xmpp:before{content:"\f2f9"}.fa-archive-org:before{content:"\f2fc"}.fa-freedombox:before{content:"\f2fd"}.fa-facebook-messenger:before{content:"\f2fe"}.fa-debian:before{content:"\f2ff"}.fa-mastodon-square:before{content:"\f300"}.fa-tipeee:before{content:"\f301"}.fa-react:before{content:"\f302"}.fa-dogmazic:before{content:"\f303"}.fa-zotero:before{content:"\f309"}.fa-nodejs:before{content:"\f308"}.fa-nextcloud:before{content:"\f306"}.fa-nextcloud-square:before{content:"\f307"}.fa-hackaday:before{content:"\f30a"}.fa-laravel:before{content:"\f30b"}.fa-signalapp:before{content:"\f30c"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.info-card-popover-cluster-status{max-width:23vw;max-height:20vh}.info-card-popover-cluster-status .popover-body{max-width:100%;max-height:19vh;font-size:12px}@media (max-width:calc(1200px - 1px)){.info-card-popover-cluster-status{max-width:31vw}}@media (max-width:calc(992px - 1px)){.info-card-popover-cluster-status{max-width:46vw}}@media (max-width:calc(768px - 1px)){.info-card-popover-cluster-status{max-width:83vw}}.info-card-content-clickable{cursor:pointer;padding:7px;border:1px solid #efefef;border-radius:3px}.info-card-content-clickable:hover{border-color:#d1d1d1;background-color:#f3f3f3}html{-webkit-tap-highlight-color:transparent;background-color:#fff}body,html{width:100%;height:100%;font-size:12px}a{text-decoration:none;color:#2b99a8;cursor:pointer}a:focus,a:hover{text-decoration:underline;color:#474544}h1{letter-spacing:-1px;font-size:2em}h2{letter-spacing:-1px;font-size:1.833em}h3{display:block;font-size:1.583em;font-weight:400}h4{font-size:1.5em;line-height:normal}option{font-weight:400;font-style:normal}.checkbox input[type=checkbox]:checked+label:after{font-family:ForkAwesome}.full-height{height:100%}.vertical-align{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center}.loading{position:absolute;top:50%;left:50%}.margin-right-md{margin-right:15px}.no-border{border:0;box-shadow:0 0 0!important}.italic{font-style:italic}.bold{font-weight:700}.text-right{text-align:right}.text-monospace{font-family:monospace}.btn-primary{color:#eee;background-color:#ef5c55;border-color:#ef5c55;border-radius:1.875rem}.btn-primary.active,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open .dropdown-toggle.btn-primary{color:#eee;background-color:#f38984;border-color:#f38984}.btn-primary.active,.btn-primary:active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active:focus,.btn-primary:active:hover,.open .dropdown-toggle.btn-primary:focus,.open .dropdown-toggle.btn-primary:hover{background-color:#f38984;border-color:#f38984}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#ef5c55;border-color:#ef5c55}.btn-primary .badge{color:#2b99a8;background-color:#eee}.btn-primary .caret{color:#eee}.btn-default{border-radius:1.875rem}.form-group .btn-default{border-radius:4px}.btn-group>.btn>i.fa,button.btn.btn-label>i.fa{padding-right:5px}.dropdown-menu{min-width:50px;z-index:999999}.dropdown-menu>li>a{color:#474544;cursor:pointer}.dropdown-menu>li>a>i.fa{padding-right:5px}.dropdown-menu>.active>a{color:#eee}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#21747f}.dataTables_wrapper .dropdown-menu>li.divider{cursor:auto}.container,.container-fluid{padding-left:30px;padding-right:30px}.row{margin-left:-30px;margin-right:-30px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{padding-left:30px;padding-right:30px}.caret{color:#fff}.progress-bar{background-image:none!important}.progress-bar-info{background-color:#2b99a8}.progress-bar-freespace{background-color:#d1d1d1}.oaprogress{position:relative;margin-bottom:0}.oaprogress div.progress-bar{position:static}.oaprogress span{position:absolute;display:block;width:100%;color:#000;font-weight:400}tags-input .tags{border-radius:4px;border:1px solid #d1d1d1;box-shadow:inset 0 1px 1px rgba(0,0,0,.09)}.panel .accordion-title,uib-accordion .panel-title{font-size:14px!important}.panel-body h2:first-child{margin-top:0}.disabled{pointer-events:none}.clickable{cursor:pointer}.has-error .has-error-btn,.has-error .has-error-btn:disabled:hover{background-color:#f2dede;border-color:#a94442}.noscript{padding-top:5em}.noscript p{color:#777}.form-group>.col-sm-12>.control-label>span.required,.form-group>.control-label>span.required,.required{color:#a94442}.form-group>.col-sm-12.form-group>.control-label>span.required,.form-group>.col-sm-12>.control-label>span.required,.form-group>.control-label>span.required{font-size:6px;padding-left:4px;vertical-align:text-top}.form-control{display:table-cell}.form-control:focus{border-color:rgba(43,153,168,.8);outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px 2px rgba(43,153,168,.5)}.modal-footer button.btn:not(:first-child),.panel-footer button.btn:not(:first-child){margin-left:5px}.margin-right-sm{margin-right:10px}.nav-tabs{margin-bottom:15px}.ceph-icon{background:url(Ceph_Logo_Stacked_RGB_120411_fa_228x228.1ed169ccc35367a2dab2.png)}.prometheus-icon{background:url(prometheus_logo.074db273ef932a67d91b.svg)}.custom-icon{padding:10px;margin-right:1em;background-clip:padding-box;background-size:contain;background-repeat:no-repeat}.toast-message .custom-icon{filter:brightness(0) invert(1);-webkit-filter:brightness(0) invert(1);-moz-filter:brightness(0) invert(1);-o-filter:brightness(0) invert(1);-ms-filter:brightness(0) invert(1)}.block-ui-wrapper{background:rgba(0,0,0,.7)!important}h3.page-header{margin-left:1em;margin-top:1em;border-color:#f0f0f0}.tooltip-wide .tooltip-inner{width:400px}.tooltip-inner{background-color:#fff;border:1px solid grey;color:#333;font-size:1.1em}.toast-message>ul{padding-left:1em;margin:0}.node-menu{position:relative;width:150px}.node-menu .node-menu-content{width:100%;padding:5px;position:absolute;border:1px solid #bdbdbd;border-radius:5%;box-shadow:0 0 5px #bdbdbd;background-color:#eee;color:#212121;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;z-index:999}.node-menu .node-menu-content li.node-menu-item{list-style:none;padding:3px}.node-menu .node-menu-content .node-menu-item:hover{border-radius:5%;opacity:unset;cursor:pointer;background-color:#bdbdbd;-webkit-transition:background-color .2s ease-out;transition:background-color .2s ease-out}.node-menu .node-menu-content .node-menu-item .node-menu-item-icon{display:inline-block;width:16px}.node-menu .node-menu-content .node-menu-item .node-menu-item-icon.new-tag:before{content:'\25CF'}.node-menu .node-menu-content .node-menu-item .node-menu-item-icon.new-folder:before{content:'\25B6'}.node-menu .node-menu-content .node-menu-item .node-menu-item-icon.rename:before{content:'\270E'}.node-menu .node-menu-content .node-menu-item .node-menu-item-icon.remove:before{content:'\2716'}.node-menu .node-menu-content .node-menu-item .node-menu-item-value{margin-left:5px}tree-internal ul{padding:3px 0 3px 25px}tree-internal li{padding:0;margin:0;list-style:none}tree-internal .over-drop-target{border:4px solid #757575;-webkit-transition:padding .2s ease-out;transition:padding .2s ease-out;padding:5px;border-radius:5%}tree-internal .tree{box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}tree-internal .tree li{list-style:none;cursor:default}tree-internal .tree li div{display:inline-block;box-sizing:border-box}tree-internal .tree .node-value{display:inline-block;color:#212121}tree-internal .tree .node-value:after{display:block;width:0;height:2px;background-color:#212121;content:'';-webkit-transition:width .3s;transition:width .3s}tree-internal .tree .node-value:hover:after{width:100%}tree-internal .tree .node-left-menu{display:inline-block;height:100%;width:auto}tree-internal .tree .node-left-menu span:before{content:'\2026';color:#757575}tree-internal .tree .node-selected:after{width:100%}tree-internal .tree .folding{width:25px;display:inline-block;line-height:1px;padding:0 5px;font-weight:700}tree-internal .tree .folding.node-collapsed{cursor:pointer}tree-internal .tree .folding.node-collapsed:before{content:'\25B6';color:#757575}tree-internal .tree .folding.node-expanded{cursor:pointer}tree-internal .tree .folding.node-expanded:before{content:'\25BC';color:#757575}tree-internal .tree .folding.node-empty{color:#212121;text-align:center;font-size:.89em}tree-internal .tree .folding.node-empty:before{content:'\25B6';color:#757575}tree-internal .tree .folding.node-leaf{color:#212121;text-align:center;font-size:.89em}tree-internal .tree .folding.node-leaf:before{content:'\25CF';color:#757575}tree-internal ul.rootless{padding:0}tree-internal div.rootless{display:none!important}tree-internal .loading-children:after{content:' loading ...';color:#6a1b9a;font-style:italic;font-size:.9em;-webkit-animation-name:loading-children;animation-name:loading-children;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes loading-children{0%{color:#f3e5f5}12.5%{color:#e1bee7}25%{color:#ce93d8}37.5%{color:#ba68c8}50%{color:#ab47bc}62.5%{color:#9c27b0}75%{color:#8e24aa}87.5%{color:#7b1fa2}100%{color:#6a1b9a}}@keyframes loading-children{0%{color:#f3e5f5}12.5%{color:#e1bee7}25%{color:#ce93d8}37.5%{color:#ba68c8}50%{color:#ab47bc}62.5%{color:#9c27b0}75%{color:#8e24aa}87.5%{color:#7b1fa2}100%{color:#6a1b9a}} \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui-bundle.js b/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui-bundle.js
new file mode 100644
index 00000000..1e3fcbb3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui-bundle.js
@@ -0,0 +1,134 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(function(){try{return require("esprima")}catch(e){}}()):"function"==typeof define&&define.amd?define(["esprima"],t):"object"==typeof exports?exports.SwaggerUIBundle=t(function(){try{return require("esprima")}catch(e){}}()):e.SwaggerUIBundle=t(e.esprima)}(window,function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=481)}([function(e,t,n){"use strict";e.exports=n(100)},function(e,t,n){e.exports=function(){"use strict";var e=Array.prototype.slice;function t(e,t){t&&(e.prototype=Object.create(t.prototype)),e.prototype.constructor=e}function n(e){return a(e)?e:J(e)}function r(e){return s(e)?e:Y(e)}function o(e){return u(e)?e:K(e)}function i(e){return a(e)&&!c(e)?e:G(e)}function a(e){return!(!e||!e[p])}function s(e){return!(!e||!e[f])}function u(e){return!(!e||!e[h])}function c(e){return s(e)||u(e)}function l(e){return!(!e||!e[d])}t(r,n),t(o,n),t(i,n),n.isIterable=a,n.isKeyed=s,n.isIndexed=u,n.isAssociative=c,n.isOrdered=l,n.Keyed=r,n.Indexed=o,n.Set=i;var p="@@__IMMUTABLE_ITERABLE__@@",f="@@__IMMUTABLE_KEYED__@@",h="@@__IMMUTABLE_INDEXED__@@",d="@@__IMMUTABLE_ORDERED__@@",m=5,v=1<<m,g=v-1,y={},b={value:!1},_={value:!1};function w(e){return e.value=!1,e}function x(e){e&&(e.value=!0)}function E(){}function S(e,t){t=t||0;for(var n=Math.max(0,e.length-t),r=new Array(n),o=0;o<n;o++)r[o]=e[o+t];return r}function C(e){return void 0===e.size&&(e.size=e.__iterate(O)),e.size}function k(e,t){if("number"!=typeof t){var n=t>>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?C(e)+t:t}function O(){return!0}function A(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function T(e,t){return P(e,t,0)}function j(e,t){return P(e,t,t)}function P(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}var I=0,M=1,N=2,R="function"==typeof Symbol&&Symbol.iterator,D="@@iterator",L=R||D;function U(e){this.next=e}function q(e,t,n,r){var o=0===e?t:1===e?n:[t,n];return r?r.value=o:r={value:o,done:!1},r}function F(){return{value:void 0,done:!0}}function z(e){return!!H(e)}function B(e){return e&&"function"==typeof e.next}function V(e){var t=H(e);return t&&t.call(e)}function H(e){var t=e&&(R&&e[R]||e[D]);if("function"==typeof t)return t}function W(e){return e&&"number"==typeof e.length}function J(e){return null==e?ie():a(e)?e.toSeq():function(e){var t=ue(e)||"object"==typeof e&&new te(e);if(!t)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+e);return t}(e)}function Y(e){return null==e?ie().toKeyedSeq():a(e)?s(e)?e.toSeq():e.fromEntrySeq():ae(e)}function K(e){return null==e?ie():a(e)?s(e)?e.entrySeq():e.toIndexedSeq():se(e)}function G(e){return(null==e?ie():a(e)?s(e)?e.entrySeq():e:se(e)).toSetSeq()}U.prototype.toString=function(){return"[Iterator]"},U.KEYS=I,U.VALUES=M,U.ENTRIES=N,U.prototype.inspect=U.prototype.toSource=function(){return this.toString()},U.prototype[L]=function(){return this},t(J,n),J.of=function(){return J(arguments)},J.prototype.toSeq=function(){return this},J.prototype.toString=function(){return this.__toString("Seq {","}")},J.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},J.prototype.__iterate=function(e,t){return ce(this,e,t,!0)},J.prototype.__iterator=function(e,t){return le(this,e,t,!0)},t(Y,J),Y.prototype.toKeyedSeq=function(){return this},t(K,J),K.of=function(){return K(arguments)},K.prototype.toIndexedSeq=function(){return this},K.prototype.toString=function(){return this.__toString("Seq [","]")},K.prototype.__iterate=function(e,t){return ce(this,e,t,!1)},K.prototype.__iterator=function(e,t){return le(this,e,t,!1)},t(G,J),G.of=function(){return G(arguments)},G.prototype.toSetSeq=function(){return this},J.isSeq=oe,J.Keyed=Y,J.Set=G,J.Indexed=K;var $,Z,X,Q="@@__IMMUTABLE_SEQ__@@";function ee(e){this._array=e,this.size=e.length}function te(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function ne(e){this._iterable=e,this.size=e.length||e.size}function re(e){this._iterator=e,this._iteratorCache=[]}function oe(e){return!(!e||!e[Q])}function ie(){return $||($=new ee([]))}function ae(e){var t=Array.isArray(e)?new ee(e).fromEntrySeq():B(e)?new re(e).fromEntrySeq():z(e)?new ne(e).fromEntrySeq():"object"==typeof e?new te(e):void 0;if(!t)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+e);return t}function se(e){var t=ue(e);if(!t)throw new TypeError("Expected Array or iterable object of values: "+e);return t}function ue(e){return W(e)?new ee(e):B(e)?new re(e):z(e)?new ne(e):void 0}function ce(e,t,n,r){var o=e._cache;if(o){for(var i=o.length-1,a=0;a<=i;a++){var s=o[n?i-a:a];if(!1===t(s[1],r?s[0]:a,e))return a+1}return a}return e.__iterateUncached(t,n)}function le(e,t,n,r){var o=e._cache;if(o){var i=o.length-1,a=0;return new U(function(){var e=o[n?i-a:a];return a++>i?{value:void 0,done:!0}:q(t,r?e[0]:a-1,e[1])})}return e.__iteratorUncached(t,n)}function pe(e,t){return t?function e(t,n,r,o){return Array.isArray(n)?t.call(o,r,K(n).map(function(r,o){return e(t,r,o,n)})):he(n)?t.call(o,r,Y(n).map(function(r,o){return e(t,r,o,n)})):n}(t,e,"",{"":e}):fe(e)}function fe(e){return Array.isArray(e)?K(e).map(fe).toList():he(e)?Y(e).map(fe).toMap():e}function he(e){return e&&(e.constructor===Object||void 0===e.constructor)}function de(e,t){if(e===t||e!=e&&t!=t)return!0;if(!e||!t)return!1;if("function"==typeof e.valueOf&&"function"==typeof t.valueOf){if(e=e.valueOf(),t=t.valueOf(),e===t||e!=e&&t!=t)return!0;if(!e||!t)return!1}return!("function"!=typeof e.equals||"function"!=typeof t.equals||!e.equals(t))}function me(e,t){if(e===t)return!0;if(!a(t)||void 0!==e.size&&void 0!==t.size&&e.size!==t.size||void 0!==e.__hash&&void 0!==t.__hash&&e.__hash!==t.__hash||s(e)!==s(t)||u(e)!==u(t)||l(e)!==l(t))return!1;if(0===e.size&&0===t.size)return!0;var n=!c(e);if(l(e)){var r=e.entries();return t.every(function(e,t){var o=r.next().value;return o&&de(o[1],e)&&(n||de(o[0],t))})&&r.next().done}var o=!1;if(void 0===e.size)if(void 0===t.size)"function"==typeof e.cacheResult&&e.cacheResult();else{o=!0;var i=e;e=t,t=i}var p=!0,f=t.__iterate(function(t,r){if(n?!e.has(t):o?!de(t,e.get(r,y)):!de(e.get(r,y),t))return p=!1,!1});return p&&e.size===f}function ve(e,t){if(!(this instanceof ve))return new ve(e,t);if(this._value=e,this.size=void 0===t?1/0:Math.max(0,t),0===this.size){if(Z)return Z;Z=this}}function ge(e,t){if(!e)throw new Error(t)}function ye(e,t,n){if(!(this instanceof ye))return new ye(e,t,n);if(ge(0!==n,"Cannot step a Range by 0"),e=e||0,void 0===t&&(t=1/0),n=void 0===n?1:Math.abs(n),t<e&&(n=-n),this._start=e,this._end=t,this._step=n,this.size=Math.max(0,Math.ceil((t-e)/n-1)+1),0===this.size){if(X)return X;X=this}}function be(){throw TypeError("Abstract")}function _e(){}function we(){}function xe(){}J.prototype[Q]=!0,t(ee,K),ee.prototype.get=function(e,t){return this.has(e)?this._array[k(this,e)]:t},ee.prototype.__iterate=function(e,t){for(var n=this._array,r=n.length-1,o=0;o<=r;o++)if(!1===e(n[t?r-o:o],o,this))return o+1;return o},ee.prototype.__iterator=function(e,t){var n=this._array,r=n.length-1,o=0;return new U(function(){return o>r?{value:void 0,done:!0}:q(e,o,n[t?r-o++:o++])})},t(te,Y),te.prototype.get=function(e,t){return void 0===t||this.has(e)?this._object[e]:t},te.prototype.has=function(e){return this._object.hasOwnProperty(e)},te.prototype.__iterate=function(e,t){for(var n=this._object,r=this._keys,o=r.length-1,i=0;i<=o;i++){var a=r[t?o-i:i];if(!1===e(n[a],a,this))return i+1}return i},te.prototype.__iterator=function(e,t){var n=this._object,r=this._keys,o=r.length-1,i=0;return new U(function(){var a=r[t?o-i:i];return i++>o?{value:void 0,done:!0}:q(e,a,n[a])})},te.prototype[d]=!0,t(ne,K),ne.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);var n=this._iterable,r=V(n),o=0;if(B(r))for(var i;!(i=r.next()).done&&!1!==e(i.value,o++,this););return o},ne.prototype.__iteratorUncached=function(e,t){if(t)return this.cacheResult().__iterator(e,t);var n=this._iterable,r=V(n);if(!B(r))return new U(F);var o=0;return new U(function(){var t=r.next();return t.done?t:q(e,o++,t.value)})},t(re,K),re.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);for(var n,r=this._iterator,o=this._iteratorCache,i=0;i<o.length;)if(!1===e(o[i],i++,this))return i;for(;!(n=r.next()).done;){var a=n.value;if(o[i]=a,!1===e(a,i++,this))break}return i},re.prototype.__iteratorUncached=function(e,t){if(t)return this.cacheResult().__iterator(e,t);var n=this._iterator,r=this._iteratorCache,o=0;return new U(function(){if(o>=r.length){var t=n.next();if(t.done)return t;r[o]=t.value}return q(e,o,r[o++])})},t(ve,K),ve.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},ve.prototype.get=function(e,t){return this.has(e)?this._value:t},ve.prototype.includes=function(e){return de(this._value,e)},ve.prototype.slice=function(e,t){var n=this.size;return A(e,t,n)?this:new ve(this._value,j(t,n)-T(e,n))},ve.prototype.reverse=function(){return this},ve.prototype.indexOf=function(e){return de(this._value,e)?0:-1},ve.prototype.lastIndexOf=function(e){return de(this._value,e)?this.size:-1},ve.prototype.__iterate=function(e,t){for(var n=0;n<this.size;n++)if(!1===e(this._value,n,this))return n+1;return n},ve.prototype.__iterator=function(e,t){var n=this,r=0;return new U(function(){return r<n.size?q(e,r++,n._value):{value:void 0,done:!0}})},ve.prototype.equals=function(e){return e instanceof ve?de(this._value,e._value):me(e)},t(ye,K),ye.prototype.toString=function(){return 0===this.size?"Range []":"Range [ "+this._start+"..."+this._end+(1!==this._step?" by "+this._step:"")+" ]"},ye.prototype.get=function(e,t){return this.has(e)?this._start+k(this,e)*this._step:t},ye.prototype.includes=function(e){var t=(e-this._start)/this._step;return t>=0&&t<this.size&&t===Math.floor(t)},ye.prototype.slice=function(e,t){return A(e,t,this.size)?this:(e=T(e,this.size),(t=j(t,this.size))<=e?new ye(0,0):new ye(this.get(e,this._end),this.get(t,this._end),this._step))},ye.prototype.indexOf=function(e){var t=e-this._start;if(t%this._step==0){var n=t/this._step;if(n>=0&&n<this.size)return n}return-1},ye.prototype.lastIndexOf=function(e){return this.indexOf(e)},ye.prototype.__iterate=function(e,t){for(var n=this.size-1,r=this._step,o=t?this._start+n*r:this._start,i=0;i<=n;i++){if(!1===e(o,i,this))return i+1;o+=t?-r:r}return i},ye.prototype.__iterator=function(e,t){var n=this.size-1,r=this._step,o=t?this._start+n*r:this._start,i=0;return new U(function(){var a=o;return o+=t?-r:r,i>n?{value:void 0,done:!0}:q(e,i++,a)})},ye.prototype.equals=function(e){return e instanceof ye?this._start===e._start&&this._end===e._end&&this._step===e._step:me(this,e)},t(be,n),t(_e,be),t(we,be),t(xe,be),be.Keyed=_e,be.Indexed=we,be.Set=xe;var Ee="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function(e,t){var n=65535&(e|=0),r=65535&(t|=0);return n*r+((e>>>16)*r+n*(t>>>16)<<16>>>0)|0};function Se(e){return e>>>1&1073741824|3221225471&e}function Ce(e){if(!1===e||null==e)return 0;if("function"==typeof e.valueOf&&(!1===(e=e.valueOf())||null==e))return 0;if(!0===e)return 1;var t=typeof e;if("number"===t){if(e!=e||e===1/0)return 0;var n=0|e;for(n!==e&&(n^=4294967295*e);e>4294967295;)n^=e/=4294967295;return Se(n)}if("string"===t)return e.length>Me?function(e){var t=De[e];return void 0===t&&(t=ke(e),Re===Ne&&(Re=0,De={}),Re++,De[e]=t),t}(e):ke(e);if("function"==typeof e.hashCode)return e.hashCode();if("object"===t)return function(e){var t;if(je&&void 0!==(t=Oe.get(e)))return t;if(void 0!==(t=e[Ie]))return t;if(!Te){if(void 0!==(t=e.propertyIsEnumerable&&e.propertyIsEnumerable[Ie]))return t;if(void 0!==(t=function(e){if(e&&e.nodeType>0)switch(e.nodeType){case 1:return e.uniqueID;case 9:return e.documentElement&&e.documentElement.uniqueID}}(e)))return t}if(t=++Pe,1073741824&Pe&&(Pe=0),je)Oe.set(e,t);else{if(void 0!==Ae&&!1===Ae(e))throw new Error("Non-extensible objects are not allowed as keys.");if(Te)Object.defineProperty(e,Ie,{enumerable:!1,configurable:!1,writable:!1,value:t});else if(void 0!==e.propertyIsEnumerable&&e.propertyIsEnumerable===e.constructor.prototype.propertyIsEnumerable)e.propertyIsEnumerable=function(){return this.constructor.prototype.propertyIsEnumerable.apply(this,arguments)},e.propertyIsEnumerable[Ie]=t;else{if(void 0===e.nodeType)throw new Error("Unable to set a non-enumerable property on object.");e[Ie]=t}}return t}(e);if("function"==typeof e.toString)return ke(e.toString());throw new Error("Value type "+t+" cannot be hashed.")}function ke(e){for(var t=0,n=0;n<e.length;n++)t=31*t+e.charCodeAt(n)|0;return Se(t)}var Oe,Ae=Object.isExtensible,Te=function(){try{return Object.defineProperty({},"@",{}),!0}catch(e){return!1}}(),je="function"==typeof WeakMap;je&&(Oe=new WeakMap);var Pe=0,Ie="__immutablehash__";"function"==typeof Symbol&&(Ie=Symbol(Ie));var Me=16,Ne=255,Re=0,De={};function Le(e){ge(e!==1/0,"Cannot perform this action with an infinite size.")}function Ue(e){return null==e?Xe():qe(e)&&!l(e)?e:Xe().withMutations(function(t){var n=r(e);Le(n.size),n.forEach(function(e,n){return t.set(n,e)})})}function qe(e){return!(!e||!e[ze])}t(Ue,_e),Ue.of=function(){var t=e.call(arguments,0);return Xe().withMutations(function(e){for(var n=0;n<t.length;n+=2){if(n+1>=t.length)throw new Error("Missing value for key: "+t[n]);e.set(t[n],t[n+1])}})},Ue.prototype.toString=function(){return this.__toString("Map {","}")},Ue.prototype.get=function(e,t){return this._root?this._root.get(0,void 0,e,t):t},Ue.prototype.set=function(e,t){return Qe(this,e,t)},Ue.prototype.setIn=function(e,t){return this.updateIn(e,y,function(){return t})},Ue.prototype.remove=function(e){return Qe(this,e,y)},Ue.prototype.deleteIn=function(e){return this.updateIn(e,function(){return y})},Ue.prototype.update=function(e,t,n){return 1===arguments.length?e(this):this.updateIn([e],t,n)},Ue.prototype.updateIn=function(e,t,n){n||(n=t,t=void 0);var r=function e(t,n,r,o){var i=t===y,a=n.next();if(a.done){var s=i?r:t,u=o(s);return u===s?t:u}ge(i||t&&t.set,"invalid keyPath");var c=a.value,l=i?y:t.get(c,y),p=e(l,n,r,o);return p===l?t:p===y?t.remove(c):(i?Xe():t).set(c,p)}(this,rn(e),t,n);return r===y?void 0:r},Ue.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Xe()},Ue.prototype.merge=function(){return rt(this,void 0,arguments)},Ue.prototype.mergeWith=function(t){var n=e.call(arguments,1);return rt(this,t,n)},Ue.prototype.mergeIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,Xe(),function(e){return"function"==typeof e.merge?e.merge.apply(e,n):n[n.length-1]})},Ue.prototype.mergeDeep=function(){return rt(this,ot,arguments)},Ue.prototype.mergeDeepWith=function(t){var n=e.call(arguments,1);return rt(this,it(t),n)},Ue.prototype.mergeDeepIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,Xe(),function(e){return"function"==typeof e.mergeDeep?e.mergeDeep.apply(e,n):n[n.length-1]})},Ue.prototype.sort=function(e){return Tt(Jt(this,e))},Ue.prototype.sortBy=function(e,t){return Tt(Jt(this,t,e))},Ue.prototype.withMutations=function(e){var t=this.asMutable();return e(t),t.wasAltered()?t.__ensureOwner(this.__ownerID):this},Ue.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new E)},Ue.prototype.asImmutable=function(){return this.__ensureOwner()},Ue.prototype.wasAltered=function(){return this.__altered},Ue.prototype.__iterator=function(e,t){return new Ke(this,e,t)},Ue.prototype.__iterate=function(e,t){var n=this,r=0;return this._root&&this._root.iterate(function(t){return r++,e(t[1],t[0],n)},t),r},Ue.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?Ze(this.size,this._root,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},Ue.isMap=qe;var Fe,ze="@@__IMMUTABLE_MAP__@@",Be=Ue.prototype;function Ve(e,t){this.ownerID=e,this.entries=t}function He(e,t,n){this.ownerID=e,this.bitmap=t,this.nodes=n}function We(e,t,n){this.ownerID=e,this.count=t,this.nodes=n}function Je(e,t,n){this.ownerID=e,this.keyHash=t,this.entries=n}function Ye(e,t,n){this.ownerID=e,this.keyHash=t,this.entry=n}function Ke(e,t,n){this._type=t,this._reverse=n,this._stack=e._root&&$e(e._root)}function Ge(e,t){return q(e,t[0],t[1])}function $e(e,t){return{node:e,index:0,__prev:t}}function Ze(e,t,n,r){var o=Object.create(Be);return o.size=e,o._root=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function Xe(){return Fe||(Fe=Ze(0))}function Qe(e,t,n){var r,o;if(e._root){var i=w(b),a=w(_);if(r=et(e._root,e.__ownerID,0,void 0,t,n,i,a),!a.value)return e;o=e.size+(i.value?n===y?-1:1:0)}else{if(n===y)return e;o=1,r=new Ve(e.__ownerID,[[t,n]])}return e.__ownerID?(e.size=o,e._root=r,e.__hash=void 0,e.__altered=!0,e):r?Ze(o,r):Xe()}function et(e,t,n,r,o,i,a,s){return e?e.update(t,n,r,o,i,a,s):i===y?e:(x(s),x(a),new Ye(t,r,[o,i]))}function tt(e){return e.constructor===Ye||e.constructor===Je}function nt(e,t,n,r,o){if(e.keyHash===r)return new Je(t,r,[e.entry,o]);var i,a=(0===n?e.keyHash:e.keyHash>>>n)&g,s=(0===n?r:r>>>n)&g,u=a===s?[nt(e,t,n+m,r,o)]:(i=new Ye(t,r,o),a<s?[e,i]:[i,e]);return new He(t,1<<a|1<<s,u)}function rt(e,t,n){for(var o=[],i=0;i<n.length;i++){var s=n[i],u=r(s);a(s)||(u=u.map(function(e){return pe(e)})),o.push(u)}return at(e,t,o)}function ot(e,t,n){return e&&e.mergeDeep&&a(t)?e.mergeDeep(t):de(e,t)?e:t}function it(e){return function(t,n,r){if(t&&t.mergeDeepWith&&a(n))return t.mergeDeepWith(e,n);var o=e(t,n,r);return de(t,o)?t:o}}function at(e,t,n){return 0===(n=n.filter(function(e){return 0!==e.size})).length?e:0!==e.size||e.__ownerID||1!==n.length?e.withMutations(function(e){for(var r=t?function(n,r){e.update(r,y,function(e){return e===y?n:t(e,n,r)})}:function(t,n){e.set(n,t)},o=0;o<n.length;o++)n[o].forEach(r)}):e.constructor(n[0])}function st(e){return e=(e=(858993459&(e-=e>>1&1431655765))+(e>>2&858993459))+(e>>4)&252645135,e+=e>>8,127&(e+=e>>16)}function ut(e,t,n,r){var o=r?e:S(e);return o[t]=n,o}Be[ze]=!0,Be.delete=Be.remove,Be.removeIn=Be.deleteIn,Ve.prototype.get=function(e,t,n,r){for(var o=this.entries,i=0,a=o.length;i<a;i++)if(de(n,o[i][0]))return o[i][1];return r},Ve.prototype.update=function(e,t,n,r,o,i,a){for(var s=o===y,u=this.entries,c=0,l=u.length;c<l&&!de(r,u[c][0]);c++);var p=c<l;if(p?u[c][1]===o:s)return this;if(x(a),(s||!p)&&x(i),!s||1!==u.length){if(!p&&!s&&u.length>=ct)return function(e,t,n,r){e||(e=new E);for(var o=new Ye(e,Ce(n),[n,r]),i=0;i<t.length;i++){var a=t[i];o=o.update(e,0,void 0,a[0],a[1])}return o}(e,u,r,o);var f=e&&e===this.ownerID,h=f?u:S(u);return p?s?c===l-1?h.pop():h[c]=h.pop():h[c]=[r,o]:h.push([r,o]),f?(this.entries=h,this):new Ve(e,h)}},He.prototype.get=function(e,t,n,r){void 0===t&&(t=Ce(n));var o=1<<((0===e?t:t>>>e)&g),i=this.bitmap;return 0==(i&o)?r:this.nodes[st(i&o-1)].get(e+m,t,n,r)},He.prototype.update=function(e,t,n,r,o,i,a){void 0===n&&(n=Ce(r));var s=(0===t?n:n>>>t)&g,u=1<<s,c=this.bitmap,l=0!=(c&u);if(!l&&o===y)return this;var p=st(c&u-1),f=this.nodes,h=l?f[p]:void 0,d=et(h,e,t+m,n,r,o,i,a);if(d===h)return this;if(!l&&d&&f.length>=lt)return function(e,t,n,r,o){for(var i=0,a=new Array(v),s=0;0!==n;s++,n>>>=1)a[s]=1&n?t[i++]:void 0;return a[r]=o,new We(e,i+1,a)}(e,f,c,s,d);if(l&&!d&&2===f.length&&tt(f[1^p]))return f[1^p];if(l&&d&&1===f.length&&tt(d))return d;var b=e&&e===this.ownerID,_=l?d?c:c^u:c|u,w=l?d?ut(f,p,d,b):function(e,t,n){var r=e.length-1;if(n&&t===r)return e.pop(),e;for(var o=new Array(r),i=0,a=0;a<r;a++)a===t&&(i=1),o[a]=e[a+i];return o}(f,p,b):function(e,t,n,r){var o=e.length+1;if(r&&t+1===o)return e[t]=n,e;for(var i=new Array(o),a=0,s=0;s<o;s++)s===t?(i[s]=n,a=-1):i[s]=e[s+a];return i}(f,p,d,b);return b?(this.bitmap=_,this.nodes=w,this):new He(e,_,w)},We.prototype.get=function(e,t,n,r){void 0===t&&(t=Ce(n));var o=(0===e?t:t>>>e)&g,i=this.nodes[o];return i?i.get(e+m,t,n,r):r},We.prototype.update=function(e,t,n,r,o,i,a){void 0===n&&(n=Ce(r));var s=(0===t?n:n>>>t)&g,u=o===y,c=this.nodes,l=c[s];if(u&&!l)return this;var p=et(l,e,t+m,n,r,o,i,a);if(p===l)return this;var f=this.count;if(l){if(!p&&--f<pt)return function(e,t,n,r){for(var o=0,i=0,a=new Array(n),s=0,u=1,c=t.length;s<c;s++,u<<=1){var l=t[s];void 0!==l&&s!==r&&(o|=u,a[i++]=l)}return new He(e,o,a)}(e,c,f,s)}else f++;var h=e&&e===this.ownerID,d=ut(c,s,p,h);return h?(this.count=f,this.nodes=d,this):new We(e,f,d)},Je.prototype.get=function(e,t,n,r){for(var o=this.entries,i=0,a=o.length;i<a;i++)if(de(n,o[i][0]))return o[i][1];return r},Je.prototype.update=function(e,t,n,r,o,i,a){void 0===n&&(n=Ce(r));var s=o===y;if(n!==this.keyHash)return s?this:(x(a),x(i),nt(this,e,t,n,[r,o]));for(var u=this.entries,c=0,l=u.length;c<l&&!de(r,u[c][0]);c++);var p=c<l;if(p?u[c][1]===o:s)return this;if(x(a),(s||!p)&&x(i),s&&2===l)return new Ye(e,this.keyHash,u[1^c]);var f=e&&e===this.ownerID,h=f?u:S(u);return p?s?c===l-1?h.pop():h[c]=h.pop():h[c]=[r,o]:h.push([r,o]),f?(this.entries=h,this):new Je(e,this.keyHash,h)},Ye.prototype.get=function(e,t,n,r){return de(n,this.entry[0])?this.entry[1]:r},Ye.prototype.update=function(e,t,n,r,o,i,a){var s=o===y,u=de(r,this.entry[0]);return(u?o===this.entry[1]:s)?this:(x(a),s?void x(i):u?e&&e===this.ownerID?(this.entry[1]=o,this):new Ye(e,this.keyHash,[r,o]):(x(i),nt(this,e,t,Ce(r),[r,o])))},Ve.prototype.iterate=Je.prototype.iterate=function(e,t){for(var n=this.entries,r=0,o=n.length-1;r<=o;r++)if(!1===e(n[t?o-r:r]))return!1},He.prototype.iterate=We.prototype.iterate=function(e,t){for(var n=this.nodes,r=0,o=n.length-1;r<=o;r++){var i=n[t?o-r:r];if(i&&!1===i.iterate(e,t))return!1}},Ye.prototype.iterate=function(e,t){return e(this.entry)},t(Ke,U),Ke.prototype.next=function(){for(var e=this._type,t=this._stack;t;){var n,r=t.node,o=t.index++;if(r.entry){if(0===o)return Ge(e,r.entry)}else if(r.entries){if(n=r.entries.length-1,o<=n)return Ge(e,r.entries[this._reverse?n-o:o])}else if(n=r.nodes.length-1,o<=n){var i=r.nodes[this._reverse?n-o:o];if(i){if(i.entry)return Ge(e,i.entry);t=this._stack=$e(i,t)}continue}t=this._stack=this._stack.__prev}return{value:void 0,done:!0}};var ct=v/4,lt=v/2,pt=v/4;function ft(e){var t=xt();if(null==e)return t;if(ht(e))return e;var n=o(e),r=n.size;return 0===r?t:(Le(r),r>0&&r<v?wt(0,r,m,null,new vt(n.toArray())):t.withMutations(function(e){e.setSize(r),n.forEach(function(t,n){return e.set(n,t)})}))}function ht(e){return!(!e||!e[dt])}t(ft,we),ft.of=function(){return this(arguments)},ft.prototype.toString=function(){return this.__toString("List [","]")},ft.prototype.get=function(e,t){if((e=k(this,e))>=0&&e<this.size){var n=Ct(this,e+=this._origin);return n&&n.array[e&g]}return t},ft.prototype.set=function(e,t){return function(e,t,n){if((t=k(e,t))!=t)return e;if(t>=e.size||t<0)return e.withMutations(function(e){t<0?kt(e,t).set(0,n):kt(e,0,t+1).set(t,n)});t+=e._origin;var r=e._tail,o=e._root,i=w(_);return t>=At(e._capacity)?r=Et(r,e.__ownerID,0,t,n,i):o=Et(o,e.__ownerID,e._level,t,n,i),i.value?e.__ownerID?(e._root=o,e._tail=r,e.__hash=void 0,e.__altered=!0,e):wt(e._origin,e._capacity,e._level,o,r):e}(this,e,t)},ft.prototype.remove=function(e){return this.has(e)?0===e?this.shift():e===this.size-1?this.pop():this.splice(e,1):this},ft.prototype.insert=function(e,t){return this.splice(e,0,t)},ft.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=this._origin=this._capacity=0,this._level=m,this._root=this._tail=null,this.__hash=void 0,this.__altered=!0,this):xt()},ft.prototype.push=function(){var e=arguments,t=this.size;return this.withMutations(function(n){kt(n,0,t+e.length);for(var r=0;r<e.length;r++)n.set(t+r,e[r])})},ft.prototype.pop=function(){return kt(this,0,-1)},ft.prototype.unshift=function(){var e=arguments;return this.withMutations(function(t){kt(t,-e.length);for(var n=0;n<e.length;n++)t.set(n,e[n])})},ft.prototype.shift=function(){return kt(this,1)},ft.prototype.merge=function(){return Ot(this,void 0,arguments)},ft.prototype.mergeWith=function(t){var n=e.call(arguments,1);return Ot(this,t,n)},ft.prototype.mergeDeep=function(){return Ot(this,ot,arguments)},ft.prototype.mergeDeepWith=function(t){var n=e.call(arguments,1);return Ot(this,it(t),n)},ft.prototype.setSize=function(e){return kt(this,0,e)},ft.prototype.slice=function(e,t){var n=this.size;return A(e,t,n)?this:kt(this,T(e,n),j(t,n))},ft.prototype.__iterator=function(e,t){var n=0,r=_t(this,t);return new U(function(){var t=r();return t===bt?{value:void 0,done:!0}:q(e,n++,t)})},ft.prototype.__iterate=function(e,t){for(var n,r=0,o=_t(this,t);(n=o())!==bt&&!1!==e(n,r++,this););return r},ft.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?wt(this._origin,this._capacity,this._level,this._root,this._tail,e,this.__hash):(this.__ownerID=e,this)},ft.isList=ht;var dt="@@__IMMUTABLE_LIST__@@",mt=ft.prototype;function vt(e,t){this.array=e,this.ownerID=t}mt[dt]=!0,mt.delete=mt.remove,mt.setIn=Be.setIn,mt.deleteIn=mt.removeIn=Be.removeIn,mt.update=Be.update,mt.updateIn=Be.updateIn,mt.mergeIn=Be.mergeIn,mt.mergeDeepIn=Be.mergeDeepIn,mt.withMutations=Be.withMutations,mt.asMutable=Be.asMutable,mt.asImmutable=Be.asImmutable,mt.wasAltered=Be.wasAltered,vt.prototype.removeBefore=function(e,t,n){if(n===t?1<<t:0===this.array.length)return this;var r=n>>>t&g;if(r>=this.array.length)return new vt([],e);var o,i=0===r;if(t>0){var a=this.array[r];if((o=a&&a.removeBefore(e,t-m,n))===a&&i)return this}if(i&&!o)return this;var s=St(this,e);if(!i)for(var u=0;u<r;u++)s.array[u]=void 0;return o&&(s.array[r]=o),s},vt.prototype.removeAfter=function(e,t,n){if(n===(t?1<<t:0)||0===this.array.length)return this;var r,o=n-1>>>t&g;if(o>=this.array.length)return this;if(t>0){var i=this.array[o];if((r=i&&i.removeAfter(e,t-m,n))===i&&o===this.array.length-1)return this}var a=St(this,e);return a.array.splice(o+1),r&&(a.array[o]=r),a};var gt,yt,bt={};function _t(e,t){var n=e._origin,r=e._capacity,o=At(r),i=e._tail;return a(e._root,e._level,0);function a(e,s,u){return 0===s?function(e,a){var s=a===o?i&&i.array:e&&e.array,u=a>n?0:n-a,c=r-a;return c>v&&(c=v),function(){if(u===c)return bt;var e=t?--c:u++;return s&&s[e]}}(e,u):function(e,o,i){var s,u=e&&e.array,c=i>n?0:n-i>>o,l=1+(r-i>>o);return l>v&&(l=v),function(){for(;;){if(s){var e=s();if(e!==bt)return e;s=null}if(c===l)return bt;var n=t?--l:c++;s=a(u&&u[n],o-m,i+(n<<o))}}}(e,s,u)}}function wt(e,t,n,r,o,i,a){var s=Object.create(mt);return s.size=t-e,s._origin=e,s._capacity=t,s._level=n,s._root=r,s._tail=o,s.__ownerID=i,s.__hash=a,s.__altered=!1,s}function xt(){return gt||(gt=wt(0,0,m))}function Et(e,t,n,r,o,i){var a,s=r>>>n&g,u=e&&s<e.array.length;if(!u&&void 0===o)return e;if(n>0){var c=e&&e.array[s],l=Et(c,t,n-m,r,o,i);return l===c?e:((a=St(e,t)).array[s]=l,a)}return u&&e.array[s]===o?e:(x(i),a=St(e,t),void 0===o&&s===a.array.length-1?a.array.pop():a.array[s]=o,a)}function St(e,t){return t&&e&&t===e.ownerID?e:new vt(e?e.array.slice():[],t)}function Ct(e,t){if(t>=At(e._capacity))return e._tail;if(t<1<<e._level+m){for(var n=e._root,r=e._level;n&&r>0;)n=n.array[t>>>r&g],r-=m;return n}}function kt(e,t,n){void 0!==t&&(t|=0),void 0!==n&&(n|=0);var r=e.__ownerID||new E,o=e._origin,i=e._capacity,a=o+t,s=void 0===n?i:n<0?i+n:o+n;if(a===o&&s===i)return e;if(a>=s)return e.clear();for(var u=e._level,c=e._root,l=0;a+l<0;)c=new vt(c&&c.array.length?[void 0,c]:[],r),l+=1<<(u+=m);l&&(a+=l,o+=l,s+=l,i+=l);for(var p=At(i),f=At(s);f>=1<<u+m;)c=new vt(c&&c.array.length?[c]:[],r),u+=m;var h=e._tail,d=f<p?Ct(e,s-1):f>p?new vt([],r):h;if(h&&f>p&&a<i&&h.array.length){for(var v=c=St(c,r),y=u;y>m;y-=m){var b=p>>>y&g;v=v.array[b]=St(v.array[b],r)}v.array[p>>>m&g]=h}if(s<i&&(d=d&&d.removeAfter(r,0,s)),a>=f)a-=f,s-=f,u=m,c=null,d=d&&d.removeBefore(r,0,a);else if(a>o||f<p){for(l=0;c;){var _=a>>>u&g;if(_!==f>>>u&g)break;_&&(l+=(1<<u)*_),u-=m,c=c.array[_]}c&&a>o&&(c=c.removeBefore(r,u,a-l)),c&&f<p&&(c=c.removeAfter(r,u,f-l)),l&&(a-=l,s-=l)}return e.__ownerID?(e.size=s-a,e._origin=a,e._capacity=s,e._level=u,e._root=c,e._tail=d,e.__hash=void 0,e.__altered=!0,e):wt(a,s,u,c,d)}function Ot(e,t,n){for(var r=[],i=0,s=0;s<n.length;s++){var u=n[s],c=o(u);c.size>i&&(i=c.size),a(u)||(c=c.map(function(e){return pe(e)})),r.push(c)}return i>e.size&&(e=e.setSize(i)),at(e,t,r)}function At(e){return e<v?0:e-1>>>m<<m}function Tt(e){return null==e?It():jt(e)?e:It().withMutations(function(t){var n=r(e);Le(n.size),n.forEach(function(e,n){return t.set(n,e)})})}function jt(e){return qe(e)&&l(e)}function Pt(e,t,n,r){var o=Object.create(Tt.prototype);return o.size=e?e.size:0,o._map=e,o._list=t,o.__ownerID=n,o.__hash=r,o}function It(){return yt||(yt=Pt(Xe(),xt()))}function Mt(e,t,n){var r,o,i=e._map,a=e._list,s=i.get(t),u=void 0!==s;if(n===y){if(!u)return e;a.size>=v&&a.size>=2*i.size?(o=a.filter(function(e,t){return void 0!==e&&s!==t}),r=o.toKeyedSeq().map(function(e){return e[0]}).flip().toMap(),e.__ownerID&&(r.__ownerID=o.__ownerID=e.__ownerID)):(r=i.remove(t),o=s===a.size-1?a.pop():a.set(s,void 0))}else if(u){if(n===a.get(s)[1])return e;r=i,o=a.set(s,[t,n])}else r=i.set(t,a.size),o=a.set(a.size,[t,n]);return e.__ownerID?(e.size=r.size,e._map=r,e._list=o,e.__hash=void 0,e):Pt(r,o)}function Nt(e,t){this._iter=e,this._useKeys=t,this.size=e.size}function Rt(e){this._iter=e,this.size=e.size}function Dt(e){this._iter=e,this.size=e.size}function Lt(e){this._iter=e,this.size=e.size}function Ut(e){var t=en(e);return t._iter=e,t.size=e.size,t.flip=function(){return e},t.reverse=function(){var t=e.reverse.apply(this);return t.flip=function(){return e.reverse()},t},t.has=function(t){return e.includes(t)},t.includes=function(t){return e.has(t)},t.cacheResult=tn,t.__iterateUncached=function(t,n){var r=this;return e.__iterate(function(e,n){return!1!==t(n,e,r)},n)},t.__iteratorUncached=function(t,n){if(t===N){var r=e.__iterator(t,n);return new U(function(){var e=r.next();if(!e.done){var t=e.value[0];e.value[0]=e.value[1],e.value[1]=t}return e})}return e.__iterator(t===M?I:M,n)},t}function qt(e,t,n){var r=en(e);return r.size=e.size,r.has=function(t){return e.has(t)},r.get=function(r,o){var i=e.get(r,y);return i===y?o:t.call(n,i,r,e)},r.__iterateUncached=function(r,o){var i=this;return e.__iterate(function(e,o,a){return!1!==r(t.call(n,e,o,a),o,i)},o)},r.__iteratorUncached=function(r,o){var i=e.__iterator(N,o);return new U(function(){var o=i.next();if(o.done)return o;var a=o.value,s=a[0];return q(r,s,t.call(n,a[1],s,e),o)})},r}function Ft(e,t){var n=en(e);return n._iter=e,n.size=e.size,n.reverse=function(){return e},e.flip&&(n.flip=function(){var t=Ut(e);return t.reverse=function(){return e.flip()},t}),n.get=function(n,r){return e.get(t?n:-1-n,r)},n.has=function(n){return e.has(t?n:-1-n)},n.includes=function(t){return e.includes(t)},n.cacheResult=tn,n.__iterate=function(t,n){var r=this;return e.__iterate(function(e,n){return t(e,n,r)},!n)},n.__iterator=function(t,n){return e.__iterator(t,!n)},n}function zt(e,t,n,r){var o=en(e);return r&&(o.has=function(r){var o=e.get(r,y);return o!==y&&!!t.call(n,o,r,e)},o.get=function(r,o){var i=e.get(r,y);return i!==y&&t.call(n,i,r,e)?i:o}),o.__iterateUncached=function(o,i){var a=this,s=0;return e.__iterate(function(e,i,u){if(t.call(n,e,i,u))return s++,o(e,r?i:s-1,a)},i),s},o.__iteratorUncached=function(o,i){var a=e.__iterator(N,i),s=0;return new U(function(){for(;;){var i=a.next();if(i.done)return i;var u=i.value,c=u[0],l=u[1];if(t.call(n,l,c,e))return q(o,r?c:s++,l,i)}})},o}function Bt(e,t,n,r){var o=e.size;if(void 0!==t&&(t|=0),void 0!==n&&(n===1/0?n=o:n|=0),A(t,n,o))return e;var i=T(t,o),a=j(n,o);if(i!=i||a!=a)return Bt(e.toSeq().cacheResult(),t,n,r);var s,u=a-i;u==u&&(s=u<0?0:u);var c=en(e);return c.size=0===s?s:e.size&&s||void 0,!r&&oe(e)&&s>=0&&(c.get=function(t,n){return(t=k(this,t))>=0&&t<s?e.get(t+i,n):n}),c.__iterateUncached=function(t,n){var o=this;if(0===s)return 0;if(n)return this.cacheResult().__iterate(t,n);var a=0,u=!0,c=0;return e.__iterate(function(e,n){if(!u||!(u=a++<i))return c++,!1!==t(e,r?n:c-1,o)&&c!==s}),c},c.__iteratorUncached=function(t,n){if(0!==s&&n)return this.cacheResult().__iterator(t,n);var o=0!==s&&e.__iterator(t,n),a=0,u=0;return new U(function(){for(;a++<i;)o.next();if(++u>s)return{value:void 0,done:!0};var e=o.next();return r||t===M?e:q(t,u-1,t===I?void 0:e.value[1],e)})},c}function Vt(e,t,n,r){var o=en(e);return o.__iterateUncached=function(o,i){var a=this;if(i)return this.cacheResult().__iterate(o,i);var s=!0,u=0;return e.__iterate(function(e,i,c){if(!s||!(s=t.call(n,e,i,c)))return u++,o(e,r?i:u-1,a)}),u},o.__iteratorUncached=function(o,i){var a=this;if(i)return this.cacheResult().__iterator(o,i);var s=e.__iterator(N,i),u=!0,c=0;return new U(function(){var e,i,l;do{if((e=s.next()).done)return r||o===M?e:q(o,c++,o===I?void 0:e.value[1],e);var p=e.value;i=p[0],l=p[1],u&&(u=t.call(n,l,i,a))}while(u);return o===N?e:q(o,i,l,e)})},o}function Ht(e,t){var n=s(e),o=[e].concat(t).map(function(e){return a(e)?n&&(e=r(e)):e=n?ae(e):se(Array.isArray(e)?e:[e]),e}).filter(function(e){return 0!==e.size});if(0===o.length)return e;if(1===o.length){var i=o[0];if(i===e||n&&s(i)||u(e)&&u(i))return i}var c=new ee(o);return n?c=c.toKeyedSeq():u(e)||(c=c.toSetSeq()),(c=c.flatten(!0)).size=o.reduce(function(e,t){if(void 0!==e){var n=t.size;if(void 0!==n)return e+n}},0),c}function Wt(e,t,n){var r=en(e);return r.__iterateUncached=function(r,o){var i=0,s=!1;return function e(u,c){var l=this;u.__iterate(function(o,u){return(!t||c<t)&&a(o)?e(o,c+1):!1===r(o,n?u:i++,l)&&(s=!0),!s},o)}(e,0),i},r.__iteratorUncached=function(r,o){var i=e.__iterator(r,o),s=[],u=0;return new U(function(){for(;i;){var e=i.next();if(!1===e.done){var c=e.value;if(r===N&&(c=c[1]),t&&!(s.length<t)||!a(c))return n?e:q(r,u++,c,e);s.push(i),i=c.__iterator(r,o)}else i=s.pop()}return{value:void 0,done:!0}})},r}function Jt(e,t,n){t||(t=nn);var r=s(e),o=0,i=e.toSeq().map(function(t,r){return[r,t,o++,n?n(t,r,e):t]}).toArray();return i.sort(function(e,n){return t(e[3],n[3])||e[2]-n[2]}).forEach(r?function(e,t){i[t].length=2}:function(e,t){i[t]=e[1]}),r?Y(i):u(e)?K(i):G(i)}function Yt(e,t,n){if(t||(t=nn),n){var r=e.toSeq().map(function(t,r){return[t,n(t,r,e)]}).reduce(function(e,n){return Kt(t,e[1],n[1])?n:e});return r&&r[0]}return e.reduce(function(e,n){return Kt(t,e,n)?n:e})}function Kt(e,t,n){var r=e(n,t);return 0===r&&n!==t&&(null==n||n!=n)||r>0}function Gt(e,t,r){var o=en(e);return o.size=new ee(r).map(function(e){return e.size}).min(),o.__iterate=function(e,t){for(var n,r=this.__iterator(M,t),o=0;!(n=r.next()).done&&!1!==e(n.value,o++,this););return o},o.__iteratorUncached=function(e,o){var i=r.map(function(e){return e=n(e),V(o?e.reverse():e)}),a=0,s=!1;return new U(function(){var n;return s||(n=i.map(function(e){return e.next()}),s=n.some(function(e){return e.done})),s?{value:void 0,done:!0}:q(e,a++,t.apply(null,n.map(function(e){return e.value})))})},o}function $t(e,t){return oe(e)?t:e.constructor(t)}function Zt(e){if(e!==Object(e))throw new TypeError("Expected [K, V] tuple: "+e)}function Xt(e){return Le(e.size),C(e)}function Qt(e){return s(e)?r:u(e)?o:i}function en(e){return Object.create((s(e)?Y:u(e)?K:G).prototype)}function tn(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):J.prototype.cacheResult.call(this)}function nn(e,t){return e>t?1:e<t?-1:0}function rn(e){var t=V(e);if(!t){if(!W(e))throw new TypeError("Expected iterable or array-like: "+e);t=V(n(e))}return t}function on(e,t){var n,r=function(i){if(i instanceof r)return i;if(!(this instanceof r))return new r(i);if(!n){n=!0;var a=Object.keys(e);!function(e,t){try{t.forEach(function(e,t){Object.defineProperty(e,t,{get:function(){return this.get(t)},set:function(e){ge(this.__ownerID,"Cannot set on an immutable record."),this.set(t,e)}})}.bind(void 0,e))}catch(e){}}(o,a),o.size=a.length,o._name=t,o._keys=a,o._defaultValues=e}this._map=Ue(i)},o=r.prototype=Object.create(an);return o.constructor=r,r}t(Tt,Ue),Tt.of=function(){return this(arguments)},Tt.prototype.toString=function(){return this.__toString("OrderedMap {","}")},Tt.prototype.get=function(e,t){var n=this._map.get(e);return void 0!==n?this._list.get(n)[1]:t},Tt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):It()},Tt.prototype.set=function(e,t){return Mt(this,e,t)},Tt.prototype.remove=function(e){return Mt(this,e,y)},Tt.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},Tt.prototype.__iterate=function(e,t){var n=this;return this._list.__iterate(function(t){return t&&e(t[1],t[0],n)},t)},Tt.prototype.__iterator=function(e,t){return this._list.fromEntrySeq().__iterator(e,t)},Tt.prototype.__ensureOwner=function(e){if(e===this.__ownerID)return this;var t=this._map.__ensureOwner(e),n=this._list.__ensureOwner(e);return e?Pt(t,n,e,this.__hash):(this.__ownerID=e,this._map=t,this._list=n,this)},Tt.isOrderedMap=jt,Tt.prototype[d]=!0,Tt.prototype.delete=Tt.prototype.remove,t(Nt,Y),Nt.prototype.get=function(e,t){return this._iter.get(e,t)},Nt.prototype.has=function(e){return this._iter.has(e)},Nt.prototype.valueSeq=function(){return this._iter.valueSeq()},Nt.prototype.reverse=function(){var e=this,t=Ft(this,!0);return this._useKeys||(t.valueSeq=function(){return e._iter.toSeq().reverse()}),t},Nt.prototype.map=function(e,t){var n=this,r=qt(this,e,t);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(e,t)}),r},Nt.prototype.__iterate=function(e,t){var n,r=this;return this._iter.__iterate(this._useKeys?function(t,n){return e(t,n,r)}:(n=t?Xt(this):0,function(o){return e(o,t?--n:n++,r)}),t)},Nt.prototype.__iterator=function(e,t){if(this._useKeys)return this._iter.__iterator(e,t);var n=this._iter.__iterator(M,t),r=t?Xt(this):0;return new U(function(){var o=n.next();return o.done?o:q(e,t?--r:r++,o.value,o)})},Nt.prototype[d]=!0,t(Rt,K),Rt.prototype.includes=function(e){return this._iter.includes(e)},Rt.prototype.__iterate=function(e,t){var n=this,r=0;return this._iter.__iterate(function(t){return e(t,r++,n)},t)},Rt.prototype.__iterator=function(e,t){var n=this._iter.__iterator(M,t),r=0;return new U(function(){var t=n.next();return t.done?t:q(e,r++,t.value,t)})},t(Dt,G),Dt.prototype.has=function(e){return this._iter.includes(e)},Dt.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate(function(t){return e(t,t,n)},t)},Dt.prototype.__iterator=function(e,t){var n=this._iter.__iterator(M,t);return new U(function(){var t=n.next();return t.done?t:q(e,t.value,t.value,t)})},t(Lt,Y),Lt.prototype.entrySeq=function(){return this._iter.toSeq()},Lt.prototype.__iterate=function(e,t){var n=this;return this._iter.__iterate(function(t){if(t){Zt(t);var r=a(t);return e(r?t.get(1):t[1],r?t.get(0):t[0],n)}},t)},Lt.prototype.__iterator=function(e,t){var n=this._iter.__iterator(M,t);return new U(function(){for(;;){var t=n.next();if(t.done)return t;var r=t.value;if(r){Zt(r);var o=a(r);return q(e,o?r.get(0):r[0],o?r.get(1):r[1],t)}}})},Rt.prototype.cacheResult=Nt.prototype.cacheResult=Dt.prototype.cacheResult=Lt.prototype.cacheResult=tn,t(on,_e),on.prototype.toString=function(){return this.__toString(un(this)+" {","}")},on.prototype.has=function(e){return this._defaultValues.hasOwnProperty(e)},on.prototype.get=function(e,t){if(!this.has(e))return t;var n=this._defaultValues[e];return this._map?this._map.get(e,n):n},on.prototype.clear=function(){if(this.__ownerID)return this._map&&this._map.clear(),this;var e=this.constructor;return e._empty||(e._empty=sn(this,Xe()))},on.prototype.set=function(e,t){if(!this.has(e))throw new Error('Cannot set unknown key "'+e+'" on '+un(this));if(this._map&&!this._map.has(e)){var n=this._defaultValues[e];if(t===n)return this}var r=this._map&&this._map.set(e,t);return this.__ownerID||r===this._map?this:sn(this,r)},on.prototype.remove=function(e){if(!this.has(e))return this;var t=this._map&&this._map.remove(e);return this.__ownerID||t===this._map?this:sn(this,t)},on.prototype.wasAltered=function(){return this._map.wasAltered()},on.prototype.__iterator=function(e,t){var n=this;return r(this._defaultValues).map(function(e,t){return n.get(t)}).__iterator(e,t)},on.prototype.__iterate=function(e,t){var n=this;return r(this._defaultValues).map(function(e,t){return n.get(t)}).__iterate(e,t)},on.prototype.__ensureOwner=function(e){if(e===this.__ownerID)return this;var t=this._map&&this._map.__ensureOwner(e);return e?sn(this,t,e):(this.__ownerID=e,this._map=t,this)};var an=on.prototype;function sn(e,t,n){var r=Object.create(Object.getPrototypeOf(e));return r._map=t,r.__ownerID=n,r}function un(e){return e._name||e.constructor.name||"Record"}function cn(e){return null==e?vn():ln(e)&&!l(e)?e:vn().withMutations(function(t){var n=i(e);Le(n.size),n.forEach(function(e){return t.add(e)})})}function ln(e){return!(!e||!e[fn])}an.delete=an.remove,an.deleteIn=an.removeIn=Be.removeIn,an.merge=Be.merge,an.mergeWith=Be.mergeWith,an.mergeIn=Be.mergeIn,an.mergeDeep=Be.mergeDeep,an.mergeDeepWith=Be.mergeDeepWith,an.mergeDeepIn=Be.mergeDeepIn,an.setIn=Be.setIn,an.update=Be.update,an.updateIn=Be.updateIn,an.withMutations=Be.withMutations,an.asMutable=Be.asMutable,an.asImmutable=Be.asImmutable,t(cn,xe),cn.of=function(){return this(arguments)},cn.fromKeys=function(e){return this(r(e).keySeq())},cn.prototype.toString=function(){return this.__toString("Set {","}")},cn.prototype.has=function(e){return this._map.has(e)},cn.prototype.add=function(e){return dn(this,this._map.set(e,!0))},cn.prototype.remove=function(e){return dn(this,this._map.remove(e))},cn.prototype.clear=function(){return dn(this,this._map.clear())},cn.prototype.union=function(){var t=e.call(arguments,0);return 0===(t=t.filter(function(e){return 0!==e.size})).length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations(function(e){for(var n=0;n<t.length;n++)i(t[n]).forEach(function(t){return e.add(t)})}):this.constructor(t[0])},cn.prototype.intersect=function(){var t=e.call(arguments,0);if(0===t.length)return this;t=t.map(function(e){return i(e)});var n=this;return this.withMutations(function(e){n.forEach(function(n){t.every(function(e){return e.includes(n)})||e.remove(n)})})},cn.prototype.subtract=function(){var t=e.call(arguments,0);if(0===t.length)return this;t=t.map(function(e){return i(e)});var n=this;return this.withMutations(function(e){n.forEach(function(n){t.some(function(e){return e.includes(n)})&&e.remove(n)})})},cn.prototype.merge=function(){return this.union.apply(this,arguments)},cn.prototype.mergeWith=function(t){var n=e.call(arguments,1);return this.union.apply(this,n)},cn.prototype.sort=function(e){return gn(Jt(this,e))},cn.prototype.sortBy=function(e,t){return gn(Jt(this,t,e))},cn.prototype.wasAltered=function(){return this._map.wasAltered()},cn.prototype.__iterate=function(e,t){var n=this;return this._map.__iterate(function(t,r){return e(r,r,n)},t)},cn.prototype.__iterator=function(e,t){return this._map.map(function(e,t){return t}).__iterator(e,t)},cn.prototype.__ensureOwner=function(e){if(e===this.__ownerID)return this;var t=this._map.__ensureOwner(e);return e?this.__make(t,e):(this.__ownerID=e,this._map=t,this)},cn.isSet=ln;var pn,fn="@@__IMMUTABLE_SET__@@",hn=cn.prototype;function dn(e,t){return e.__ownerID?(e.size=t.size,e._map=t,e):t===e._map?e:0===t.size?e.__empty():e.__make(t)}function mn(e,t){var n=Object.create(hn);return n.size=e?e.size:0,n._map=e,n.__ownerID=t,n}function vn(){return pn||(pn=mn(Xe()))}function gn(e){return null==e?xn():yn(e)?e:xn().withMutations(function(t){var n=i(e);Le(n.size),n.forEach(function(e){return t.add(e)})})}function yn(e){return ln(e)&&l(e)}hn[fn]=!0,hn.delete=hn.remove,hn.mergeDeep=hn.merge,hn.mergeDeepWith=hn.mergeWith,hn.withMutations=Be.withMutations,hn.asMutable=Be.asMutable,hn.asImmutable=Be.asImmutable,hn.__empty=vn,hn.__make=mn,t(gn,cn),gn.of=function(){return this(arguments)},gn.fromKeys=function(e){return this(r(e).keySeq())},gn.prototype.toString=function(){return this.__toString("OrderedSet {","}")},gn.isOrderedSet=yn;var bn,_n=gn.prototype;function wn(e,t){var n=Object.create(_n);return n.size=e?e.size:0,n._map=e,n.__ownerID=t,n}function xn(){return bn||(bn=wn(It()))}function En(e){return null==e?Tn():Sn(e)?e:Tn().unshiftAll(e)}function Sn(e){return!(!e||!e[kn])}_n[d]=!0,_n.__empty=xn,_n.__make=wn,t(En,we),En.of=function(){return this(arguments)},En.prototype.toString=function(){return this.__toString("Stack [","]")},En.prototype.get=function(e,t){var n=this._head;for(e=k(this,e);n&&e--;)n=n.next;return n?n.value:t},En.prototype.peek=function(){return this._head&&this._head.value},En.prototype.push=function(){if(0===arguments.length)return this;for(var e=this.size+arguments.length,t=this._head,n=arguments.length-1;n>=0;n--)t={value:arguments[n],next:t};return this.__ownerID?(this.size=e,this._head=t,this.__hash=void 0,this.__altered=!0,this):An(e,t)},En.prototype.pushAll=function(e){if(0===(e=o(e)).size)return this;Le(e.size);var t=this.size,n=this._head;return e.reverse().forEach(function(e){t++,n={value:e,next:n}}),this.__ownerID?(this.size=t,this._head=n,this.__hash=void 0,this.__altered=!0,this):An(t,n)},En.prototype.pop=function(){return this.slice(1)},En.prototype.unshift=function(){return this.push.apply(this,arguments)},En.prototype.unshiftAll=function(e){return this.pushAll(e)},En.prototype.shift=function(){return this.pop.apply(this,arguments)},En.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Tn()},En.prototype.slice=function(e,t){if(A(e,t,this.size))return this;var n=T(e,this.size),r=j(t,this.size);if(r!==this.size)return we.prototype.slice.call(this,e,t);for(var o=this.size-n,i=this._head;n--;)i=i.next;return this.__ownerID?(this.size=o,this._head=i,this.__hash=void 0,this.__altered=!0,this):An(o,i)},En.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?An(this.size,this._head,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},En.prototype.__iterate=function(e,t){if(t)return this.reverse().__iterate(e);for(var n=0,r=this._head;r&&!1!==e(r.value,n++,this);)r=r.next;return n},En.prototype.__iterator=function(e,t){if(t)return this.reverse().__iterator(e);var n=0,r=this._head;return new U(function(){if(r){var t=r.value;return r=r.next,q(e,n++,t)}return{value:void 0,done:!0}})},En.isStack=Sn;var Cn,kn="@@__IMMUTABLE_STACK__@@",On=En.prototype;function An(e,t,n,r){var o=Object.create(On);return o.size=e,o._head=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function Tn(){return Cn||(Cn=An(0))}function jn(e,t){var n=function(n){e.prototype[n]=t[n]};return Object.keys(t).forEach(n),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(t).forEach(n),e}On[kn]=!0,On.withMutations=Be.withMutations,On.asMutable=Be.asMutable,On.asImmutable=Be.asImmutable,On.wasAltered=Be.wasAltered,n.Iterator=U,jn(n,{toArray:function(){Le(this.size);var e=new Array(this.size||0);return this.valueSeq().__iterate(function(t,n){e[n]=t}),e},toIndexedSeq:function(){return new Rt(this)},toJS:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJS?e.toJS():e}).__toJS()},toJSON:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJSON?e.toJSON():e}).__toJS()},toKeyedSeq:function(){return new Nt(this,!0)},toMap:function(){return Ue(this.toKeyedSeq())},toObject:function(){Le(this.size);var e={};return this.__iterate(function(t,n){e[n]=t}),e},toOrderedMap:function(){return Tt(this.toKeyedSeq())},toOrderedSet:function(){return gn(s(this)?this.valueSeq():this)},toSet:function(){return cn(s(this)?this.valueSeq():this)},toSetSeq:function(){return new Dt(this)},toSeq:function(){return u(this)?this.toIndexedSeq():s(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return En(s(this)?this.valueSeq():this)},toList:function(){return ft(s(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(e,t){return 0===this.size?e+t:e+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+t},concat:function(){var t=e.call(arguments,0);return $t(this,Ht(this,t))},includes:function(e){return this.some(function(t){return de(t,e)})},entries:function(){return this.__iterator(N)},every:function(e,t){Le(this.size);var n=!0;return this.__iterate(function(r,o,i){if(!e.call(t,r,o,i))return n=!1,!1}),n},filter:function(e,t){return $t(this,zt(this,e,t,!0))},find:function(e,t,n){var r=this.findEntry(e,t);return r?r[1]:n},forEach:function(e,t){return Le(this.size),this.__iterate(t?e.bind(t):e)},join:function(e){Le(this.size),e=void 0!==e?""+e:",";var t="",n=!0;return this.__iterate(function(r){n?n=!1:t+=e,t+=null!=r?r.toString():""}),t},keys:function(){return this.__iterator(I)},map:function(e,t){return $t(this,qt(this,e,t))},reduce:function(e,t,n){var r,o;return Le(this.size),arguments.length<2?o=!0:r=t,this.__iterate(function(t,i,a){o?(o=!1,r=t):r=e.call(n,r,t,i,a)}),r},reduceRight:function(e,t,n){var r=this.toKeyedSeq().reverse();return r.reduce.apply(r,arguments)},reverse:function(){return $t(this,Ft(this,!0))},slice:function(e,t){return $t(this,Bt(this,e,t,!0))},some:function(e,t){return!this.every(Rn(e),t)},sort:function(e){return $t(this,Jt(this,e))},values:function(){return this.__iterator(M)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some(function(){return!0})},count:function(e,t){return C(e?this.toSeq().filter(e,t):this)},countBy:function(e,t){return function(e,t,n){var r=Ue().asMutable();return e.__iterate(function(o,i){r.update(t.call(n,o,i,e),0,function(e){return e+1})}),r.asImmutable()}(this,e,t)},equals:function(e){return me(this,e)},entrySeq:function(){var e=this;if(e._cache)return new ee(e._cache);var t=e.toSeq().map(Nn).toIndexedSeq();return t.fromEntrySeq=function(){return e.toSeq()},t},filterNot:function(e,t){return this.filter(Rn(e),t)},findEntry:function(e,t,n){var r=n;return this.__iterate(function(n,o,i){if(e.call(t,n,o,i))return r=[o,n],!1}),r},findKey:function(e,t){var n=this.findEntry(e,t);return n&&n[0]},findLast:function(e,t,n){return this.toKeyedSeq().reverse().find(e,t,n)},findLastEntry:function(e,t,n){return this.toKeyedSeq().reverse().findEntry(e,t,n)},findLastKey:function(e,t){return this.toKeyedSeq().reverse().findKey(e,t)},first:function(){return this.find(O)},flatMap:function(e,t){return $t(this,function(e,t,n){var r=Qt(e);return e.toSeq().map(function(o,i){return r(t.call(n,o,i,e))}).flatten(!0)}(this,e,t))},flatten:function(e){return $t(this,Wt(this,e,!0))},fromEntrySeq:function(){return new Lt(this)},get:function(e,t){return this.find(function(t,n){return de(n,e)},void 0,t)},getIn:function(e,t){for(var n,r=this,o=rn(e);!(n=o.next()).done;){var i=n.value;if((r=r&&r.get?r.get(i,y):y)===y)return t}return r},groupBy:function(e,t){return function(e,t,n){var r=s(e),o=(l(e)?Tt():Ue()).asMutable();e.__iterate(function(i,a){o.update(t.call(n,i,a,e),function(e){return(e=e||[]).push(r?[a,i]:i),e})});var i=Qt(e);return o.map(function(t){return $t(e,i(t))})}(this,e,t)},has:function(e){return this.get(e,y)!==y},hasIn:function(e){return this.getIn(e,y)!==y},isSubset:function(e){return e="function"==typeof e.includes?e:n(e),this.every(function(t){return e.includes(t)})},isSuperset:function(e){return(e="function"==typeof e.isSubset?e:n(e)).isSubset(this)},keyOf:function(e){return this.findKey(function(t){return de(t,e)})},keySeq:function(){return this.toSeq().map(Mn).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(e){return this.toKeyedSeq().reverse().keyOf(e)},max:function(e){return Yt(this,e)},maxBy:function(e,t){return Yt(this,t,e)},min:function(e){return Yt(this,e?Dn(e):qn)},minBy:function(e,t){return Yt(this,t?Dn(t):qn,e)},rest:function(){return this.slice(1)},skip:function(e){return this.slice(Math.max(0,e))},skipLast:function(e){return $t(this,this.toSeq().reverse().skip(e).reverse())},skipWhile:function(e,t){return $t(this,Vt(this,e,t,!0))},skipUntil:function(e,t){return this.skipWhile(Rn(e),t)},sortBy:function(e,t){return $t(this,Jt(this,t,e))},take:function(e){return this.slice(0,Math.max(0,e))},takeLast:function(e){return $t(this,this.toSeq().reverse().take(e).reverse())},takeWhile:function(e,t){return $t(this,function(e,t,n){var r=en(e);return r.__iterateUncached=function(r,o){var i=this;if(o)return this.cacheResult().__iterate(r,o);var a=0;return e.__iterate(function(e,o,s){return t.call(n,e,o,s)&&++a&&r(e,o,i)}),a},r.__iteratorUncached=function(r,o){var i=this;if(o)return this.cacheResult().__iterator(r,o);var a=e.__iterator(N,o),s=!0;return new U(function(){if(!s)return{value:void 0,done:!0};var e=a.next();if(e.done)return e;var o=e.value,u=o[0],c=o[1];return t.call(n,c,u,i)?r===N?e:q(r,u,c,e):(s=!1,{value:void 0,done:!0})})},r}(this,e,t))},takeUntil:function(e,t){return this.takeWhile(Rn(e),t)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=function(e){if(e.size===1/0)return 0;var t=l(e),n=s(e),r=t?1:0;return function(e,t){return t=Ee(t,3432918353),t=Ee(t<<15|t>>>-15,461845907),t=Ee(t<<13|t>>>-13,5),t=Ee((t=(t+3864292196|0)^e)^t>>>16,2246822507),t=Se((t=Ee(t^t>>>13,3266489909))^t>>>16)}(e.__iterate(n?t?function(e,t){r=31*r+Fn(Ce(e),Ce(t))|0}:function(e,t){r=r+Fn(Ce(e),Ce(t))|0}:t?function(e){r=31*r+Ce(e)|0}:function(e){r=r+Ce(e)|0}),r)}(this))}});var Pn=n.prototype;Pn[p]=!0,Pn[L]=Pn.values,Pn.__toJS=Pn.toArray,Pn.__toStringMapper=Ln,Pn.inspect=Pn.toSource=function(){return this.toString()},Pn.chain=Pn.flatMap,Pn.contains=Pn.includes,jn(r,{flip:function(){return $t(this,Ut(this))},mapEntries:function(e,t){var n=this,r=0;return $t(this,this.toSeq().map(function(o,i){return e.call(t,[i,o],r++,n)}).fromEntrySeq())},mapKeys:function(e,t){var n=this;return $t(this,this.toSeq().flip().map(function(r,o){return e.call(t,r,o,n)}).flip())}});var In=r.prototype;function Mn(e,t){return t}function Nn(e,t){return[t,e]}function Rn(e){return function(){return!e.apply(this,arguments)}}function Dn(e){return function(){return-e.apply(this,arguments)}}function Ln(e){return"string"==typeof e?JSON.stringify(e):String(e)}function Un(){return S(arguments)}function qn(e,t){return e<t?1:e>t?-1:0}function Fn(e,t){return e^t+2654435769+(e<<6)+(e>>2)|0}return In[f]=!0,In[L]=Pn.entries,In.__toJS=Pn.toObject,In.__toStringMapper=function(e,t){return JSON.stringify(t)+": "+Ln(e)},jn(o,{toKeyedSeq:function(){return new Nt(this,!1)},filter:function(e,t){return $t(this,zt(this,e,t,!1))},findIndex:function(e,t){var n=this.findEntry(e,t);return n?n[0]:-1},indexOf:function(e){var t=this.keyOf(e);return void 0===t?-1:t},lastIndexOf:function(e){var t=this.lastKeyOf(e);return void 0===t?-1:t},reverse:function(){return $t(this,Ft(this,!1))},slice:function(e,t){return $t(this,Bt(this,e,t,!1))},splice:function(e,t){var n=arguments.length;if(t=Math.max(0|t,0),0===n||2===n&&!t)return this;e=T(e,e<0?this.count():this.size);var r=this.slice(0,e);return $t(this,1===n?r:r.concat(S(arguments,2),this.slice(e+t)))},findLastIndex:function(e,t){var n=this.findLastEntry(e,t);return n?n[0]:-1},first:function(){return this.get(0)},flatten:function(e){return $t(this,Wt(this,e,!1))},get:function(e,t){return(e=k(this,e))<0||this.size===1/0||void 0!==this.size&&e>this.size?t:this.find(function(t,n){return n===e},void 0,t)},has:function(e){return(e=k(this,e))>=0&&(void 0!==this.size?this.size===1/0||e<this.size:-1!==this.indexOf(e))},interpose:function(e){return $t(this,function(e,t){var n=en(e);return n.size=e.size&&2*e.size-1,n.__iterateUncached=function(n,r){var o=this,i=0;return e.__iterate(function(e,r){return(!i||!1!==n(t,i++,o))&&!1!==n(e,i++,o)},r),i},n.__iteratorUncached=function(n,r){var o,i=e.__iterator(M,r),a=0;return new U(function(){return(!o||a%2)&&(o=i.next()).done?o:a%2?q(n,a++,t):q(n,a++,o.value,o)})},n}(this,e))},interleave:function(){var e=[this].concat(S(arguments)),t=Gt(this.toSeq(),K.of,e),n=t.flatten(!0);return t.size&&(n.size=t.size*e.length),$t(this,n)},keySeq:function(){return ye(0,this.size)},last:function(){return this.get(-1)},skipWhile:function(e,t){return $t(this,Vt(this,e,t,!1))},zip:function(){var e=[this].concat(S(arguments));return $t(this,Gt(this,Un,e))},zipWith:function(e){var t=S(arguments);return t[0]=this,$t(this,Gt(this,e,t))}}),o.prototype[h]=!0,o.prototype[d]=!0,jn(i,{get:function(e,t){return this.has(e)?e:t},includes:function(e){return this.has(e)},keySeq:function(){return this.valueSeq()}}),i.prototype.has=Pn.includes,i.prototype.contains=i.prototype.includes,jn(Y,r.prototype),jn(K,o.prototype),jn(G,i.prototype),jn(_e,r.prototype),jn(we,o.prototype),jn(xe,i.prototype),{Iterable:n,Seq:J,Collection:be,Map:Ue,OrderedMap:Tt,List:ft,Stack:En,Set:cn,OrderedSet:gn,Record:on,Range:ye,Repeat:ve,is:de,fromJS:pe}}()},function(e,t,n){var r=n(51);e.exports=function(e,t,n){return t in e?r(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){"use strict";(function(e){n.d(t,"r",function(){return N}),n.d(t,"y",function(){return R}),n.d(t,"h",function(){return D}),n.d(t,"u",function(){return L}),n.d(t,"p",function(){return U}),n.d(t,"s",function(){return q}),n.d(t,"q",function(){return F}),n.d(t,"o",function(){return z}),n.d(t,"t",function(){return B}),n.d(t,"w",function(){return V}),n.d(t,"x",function(){return H}),n.d(t,"H",function(){return W}),n.d(t,"e",function(){return J}),n.d(t,"l",function(){return Y}),n.d(t,"n",function(){return K}),n.d(t,"g",function(){return G}),n.d(t,"C",function(){return $}),n.d(t,"I",function(){return ce}),n.d(t,"m",function(){return le}),n.d(t,"B",function(){return pe}),n.d(t,"a",function(){return fe}),n.d(t,"F",function(){return he}),n.d(t,"b",function(){return de}),n.d(t,"E",function(){return me}),n.d(t,"D",function(){return ve}),n.d(t,"i",function(){return ge}),n.d(t,"c",function(){return ye}),n.d(t,"f",function(){return be}),n.d(t,"k",function(){return _e}),n.d(t,"j",function(){return we}),n.d(t,"d",function(){return xe}),n.d(t,"G",function(){return Ee}),n.d(t,"v",function(){return Se}),n.d(t,"z",function(){return Ce}),n.d(t,"A",function(){return ke});var r=n(28),o=n.n(r),i=(n(13),n(90),n(16)),a=n.n(i),s=n(17),u=n.n(s),c=n(14),l=n.n(c),p=n(26),f=n.n(p),h=n(1),d=n.n(h),m=n(465),v=n(466),g=n.n(v),y=n(262),b=n.n(y),_=n(263),w=n.n(_),x=n(264),E=n.n(x),S=(n(467),n(89)),C=n.n(S),k=n(116),O=n(18),A=n.n(O),T=n(469),j=n.n(T),P=n(118),I="default",M=function(e){return d.a.Iterable.isIterable(e)};function N(e){try{var t=JSON.parse(e);if(t&&"object"===f()(t))return t}catch(e){}return!1}function R(e){return q(e)?M(e)?e.toJS():e:{}}function D(e){return M(e)?e:e instanceof A.a.File?e:q(e)?l()(e)?d.a.Seq(e).map(D).toList():d.a.OrderedMap(e).map(D):e}function L(e){return l()(e)?e:[e]}function U(e){return"function"==typeof e}function q(e){return!!e&&"object"===f()(e)}function F(e){return"function"==typeof e}function z(e){return l()(e)}var B=w.a;function V(e,t){return u()(e).reduce(function(n,r){return n[r]=t(e[r],r),n},{})}function H(e,t){return u()(e).reduce(function(n,r){var o=t(e[r],r);return o&&"object"===f()(o)&&a()(n,o),n},{})}function W(e){return function(t){t.dispatch,t.getState;return function(t){return function(n){return"function"==typeof n?n(e()):t(n)}}}}function J(e){var t=e.keySeq();return t.contains(I)?I:t.filter(function(e){return"2"===(e+"")[0]}).sort().first()}function Y(e,t){if(!d.a.Iterable.isIterable(e))return d.a.List();var n=e.getIn(l()(t)?t:[t]);return d.a.List.isList(n)?n:d.a.List()}function K(e){var t=document;if(!e)return"";if(e.textContent.length>5e3)return e.textContent;return function(e){for(var n,r,o,i,a,s=e.textContent,u=0,c=s[0],l=1,p=e.innerHTML="",f=0;r=n,n=f<7&&"\\"==n?1:l;){if(l=c,c=s[++u],i=p.length>1,!l||f>8&&"\n"==l||[/\S/.test(l),1,1,!/[$\w]/.test(l),("/"==n||"\n"==n)&&i,'"'==n&&i,"'"==n&&i,s[u-4]+r+n=="--\x3e",r+n=="*/"][f])for(p&&(e.appendChild(a=t.createElement("span")).setAttribute("style",["color: #555; font-weight: bold;","","","color: #555;",""][f?f<3?2:f>6?4:f>3?3:+/^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/.test(p):0]),a.appendChild(t.createTextNode(p))),o=f&&f<7?f:o,p="",f=11;![1,/[\/{}[(\-+*=<>:;|\\.,?!&@~]/.test(l),/[\])]/.test(l),/[$\w]/.test(l),"/"==l&&o<2&&"<"!=n,'"'==l,"'"==l,l+c+s[u+1]+s[u+2]=="\x3c!--",l+c=="/*",l+c=="//","#"==l][--f];);p+=l}}(e)}function G(e){var t;if([/filename\*=[^']+'\w*'"([^"]+)";?/i,/filename\*=[^']+'\w*'([^;]+);?/i,/filename="([^;]*);?"/i,/filename=([^;]*);?/i].some(function(n){return null!==(t=n.exec(e))}),null!==t&&t.length>1)try{return decodeURIComponent(t[1])}catch(e){console.error(e)}return null}function $(e){return t=e.replace(/\.[^.\/]*$/,""),b()(g()(t));var t}var Z=function(e,t){if(e>t)return"Value must be less than Maximum"},X=function(e,t){if(e<t)return"Value must be greater than Minimum"},Q=function(e){if(!/^-?\d+(\.?\d+)?$/.test(e))return"Value must be a number"},ee=function(e){if(!/^-?\d+$/.test(e))return"Value must be an integer"},te=function(e){if(e&&!(e instanceof A.a.File))return"Value must be a file"},ne=function(e){if("true"!==e&&"false"!==e&&!0!==e&&!1!==e)return"Value must be a boolean"},re=function(e){if(e&&"string"!=typeof e)return"Value must be a string"},oe=function(e){if(isNaN(Date.parse(e)))return"Value must be a DateTime"},ie=function(e){if(e=e.toString().toLowerCase(),!/^[{(]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}[)}]?$/.test(e))return"Value must be a Guid"},ae=function(e,t){if(e.length>t)return"Value must be less than MaxLength"},se=function(e,t){if(e.length<t)return"Value must be greater than MinLength"},ue=function(e,t){if(!new RegExp(t).test(e))return"Value must follow pattern "+t},ce=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.isOAS3,o=void 0!==r&&r,i=n.bypassRequiredCheck,a=void 0!==i&&i,s=[],u=e.get("required"),c=Object(P.a)(e,{isOAS3:o});if(!c)return s;var p=c.get("maximum"),h=c.get("minimum"),m=c.get("type"),v=c.get("format"),g=c.get("maxLength"),y=c.get("minLength"),b=c.get("pattern");if(m&&(u||t)){var _="string"===m&&t,w="array"===m&&l()(t)&&t.length,x="array"===m&&d.a.List.isList(t)&&t.count(),E="array"===m&&"string"==typeof t&&t,S="file"===m&&t instanceof A.a.File,C="boolean"===m&&(t||!1===t),k="number"===m&&(t||0===t),O="integer"===m&&(t||0===t),T="object"===m&&"object"===f()(t)&&null!==t,j="object"===m&&"string"==typeof t&&t,I=[_,w,x,E,S,C,k,O,T,j],M=I.some(function(e){return!!e});if(u&&!M&&!a)return s.push("Required field is not provided"),s;if(b){var N=ue(t,b);N&&s.push(N)}if(g||0===g){var R=ae(t,g);R&&s.push(R)}if(y){var D=se(t,y);D&&s.push(D)}if(p||0===p){var L=Z(t,p);L&&s.push(L)}if(h||0===h){var U=X(t,h);U&&s.push(U)}if("string"===m){var q;if(!(q="date-time"===v?oe(t):"uuid"===v?ie(t):re(t)))return s;s.push(q)}else if("boolean"===m){var F=ne(t);if(!F)return s;s.push(F)}else if("number"===m){var z=Q(t);if(!z)return s;s.push(z)}else if("integer"===m){var B=ee(t);if(!B)return s;s.push(B)}else if("array"===m){var V;if(!x||!t.count())return s;V=c.getIn(["items","type"]),t.forEach(function(e,t){var n;"number"===V?n=Q(e):"integer"===V?n=ee(e):"string"===V&&(n=re(e)),n&&s.push({index:t,error:n})})}else if("file"===m){var H=te(t);if(!H)return s;s.push(H)}}return s},le=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(/xml/.test(t)){if(!e.xml||!e.xml.name){if(e.xml=e.xml||{},!e.$$ref)return e.type||e.items||e.properties||e.additionalProperties?'<?xml version="1.0" encoding="UTF-8"?>\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e':null;var r=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=r[1]}return Object(k.memoizedCreateXMLExample)(e,n)}var i=Object(k.memoizedSampleFromSchema)(e,n);return"object"===f()(i)?o()(i,null,2):i},pe=function(){var e={},t=A.a.location.search;if(!t)return{};if(""!=t){var n=t.substr(1).split("&");for(var r in n)n.hasOwnProperty(r)&&(r=n[r].split("="),e[decodeURIComponent(r[0])]=r[1]&&decodeURIComponent(r[1])||"")}return e},fe=function(t){return(t instanceof e?t:new e(t.toString(),"utf-8")).toString("base64")},he={operationsSorter:{alpha:function(e,t){return e.get("path").localeCompare(t.get("path"))},method:function(e,t){return e.get("method").localeCompare(t.get("method"))}},tagsSorter:{alpha:function(e,t){return e.localeCompare(t)}}},de=function(e){var t=[];for(var n in e){var r=e[n];void 0!==r&&""!==r&&t.push([n,"=",encodeURIComponent(r).replace(/%20/g,"+")].join(""))}return t.join("&")},me=function(e,t,n){return!!E()(n,function(n){return C()(e[n],t[n])})};function ve(e){return"string"!=typeof e||""===e?"":Object(m.sanitizeUrl)(e)}function ge(e){if(!d.a.OrderedMap.isOrderedMap(e))return null;if(!e.size)return null;var t=e.find(function(e,t){return t.startsWith("2")&&u()(e.get("content")||{}).length>0}),n=e.get("default")||d.a.OrderedMap(),r=(n.get("content")||d.a.OrderedMap()).keySeq().toJS().length?n:null;return t||r}var ye=function(e){return"string"==typeof e||e instanceof String?e.trim().replace(/\s/g,"%20"):""},be=function(e){return j()(ye(e).replace(/%20/g,"_"))},_e=function(e){return e.filter(function(e,t){return/^x-/.test(t)})},we=function(e){return e.filter(function(e,t){return/^pattern|maxLength|minLength|maximum|minimum/.test(t)})};function xe(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){return!0};if("object"!==f()(e)||l()(e)||null===e||!t)return e;var r=a()({},e);return u()(r).forEach(function(e){e===t&&n(r[e],e)?delete r[e]:r[e]=xe(r[e],t,n)}),r}function Ee(e){if("string"==typeof e)return e;if(e&&e.toJS&&(e=e.toJS()),"object"===f()(e)&&null!==e)try{return o()(e,null,2)}catch(t){return String(e)}return null==e?"":e.toString()}function Se(e){return"number"==typeof e?e.toString():e}function Ce(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.returnAll,r=void 0!==n&&n,o=t.allowHashes,i=void 0===o||o;if(!d.a.Map.isMap(e))throw new Error("paramToIdentifier: received a non-Im.Map parameter as input");var a=e.get("name"),s=e.get("in"),u=[];return e&&e.hashCode&&s&&a&&i&&u.push("".concat(s,".").concat(a,".hash-").concat(e.hashCode())),s&&a&&u.push("".concat(s,".").concat(a)),u.push(a),r?u:u[0]||""}function ke(e,t){return Ce(e,{returnAll:!0}).map(function(e){return t[e]}).filter(function(e){return void 0!==e})[0]}}).call(this,n(61).Buffer)},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){var r=n(51);function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),r(e,o.key,o)}}e.exports=function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}},function(e,t,n){var r=n(26),o=n(9);e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?o(e):t}},function(e,t,n){var r=n(791),o=n(413);function i(t){return e.exports=i=o?r:function(e){return e.__proto__||r(e)},i(t)}e.exports=i},function(e,t,n){var r=n(414),o=n(799);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=r(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t,n){e.exports=n(957)()},function(e,t,n){"use strict";function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function o(e,t){return e===t}function i(e){var t=arguments.length<=1||void 0===arguments[1]?o:arguments[1],n=null,r=null;return function(){for(var o=arguments.length,i=Array(o),a=0;a<o;a++)i[a]=arguments[a];return null!==n&&n.length===i.length&&i.every(function(e,r){return t(e,n[r])})||(r=e.apply(void 0,i)),n=i,r}}function a(e){var t=Array.isArray(e[0])?e[0]:e;if(!t.every(function(e){return"function"==typeof e})){var n=t.map(function(e){return typeof e}).join(", ");throw new Error("Selector creators expect all input-selectors to be functions, instead received the following types: ["+n+"]")}return t}function s(e){for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o<t;o++)n[o-1]=arguments[o];return function(){for(var t=arguments.length,o=Array(t),i=0;i<t;i++)o[i]=arguments[i];var s=0,u=o.pop(),c=a(o),l=e.apply(void 0,[function(){return s++,u.apply(void 0,arguments)}].concat(n)),p=function(e,t){for(var n=arguments.length,o=Array(n>2?n-2:0),i=2;i<n;i++)o[i-2]=arguments[i];var a=c.map(function(n){return n.apply(void 0,[e,t].concat(o))});return l.apply(void 0,r(a))};return p.resultFunc=u,p.recomputations=function(){return s},p.resetRecomputations=function(){return s=0},p}}t.__esModule=!0,t.defaultMemoize=i,t.createSelectorCreator=s,t.createStructuredSelector=function(e){var t=arguments.length<=1||void 0===arguments[1]?u:arguments[1];if("object"!=typeof e)throw new Error("createStructuredSelector expects first argument to be an object where each property is a selector, instead received a "+typeof e);var n=Object.keys(e);return t(n.map(function(t){return e[t]}),function(){for(var e=arguments.length,t=Array(e),r=0;r<e;r++)t[r]=arguments[r];return t.reduce(function(e,t,r){return e[n[r]]=t,e},{})})};var u=t.createSelector=s(i)},function(e,t,n){var r=n(739),o=n(740),i=n(747);e.exports=function(e){return r(e)||o(e)||i()}},function(e,t,n){var r=n(586),o=n(587),i=n(590);e.exports=function(e,t){return r(e)||o(e,t)||i()}},function(e,t,n){e.exports=n(560)},function(e,t,n){"use strict";var r=function(e){};e.exports=function(e,t,n,o,i,a,s,u){if(r(t),!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,o,i,a,s,u],p=0;(c=new Error(t.replace(/%s/g,function(){return l[p++]}))).name="Invariant Violation"}throw c.framesToPop=1,c}}},function(e,t,n){e.exports=n(564)},function(e,t,n){e.exports=n(542)},function(e,t){e.exports=function(){var e={location:{},history:{},open:function(){},close:function(){},File:function(){}};if("undefined"==typeof window)return e;try{e=window;for(var t=0,n=["File","Blob","FormData"];t<n.length;t++){var r=n[t];r in window&&(e[r]=window[r])}}catch(e){console.error(e)}return e}()},function(e,t,n){"use strict";var r=n(1),o="<<anonymous>>",i={listOf:function(e){return c(e,"List",r.List.isList)},mapOf:function(e,t){return l(e,t,"Map",r.Map.isMap)},orderedMapOf:function(e,t){return l(e,t,"OrderedMap",r.OrderedMap.isOrderedMap)},setOf:function(e){return c(e,"Set",r.Set.isSet)},orderedSetOf:function(e){return c(e,"OrderedSet",r.OrderedSet.isOrderedSet)},stackOf:function(e){return c(e,"Stack",r.Stack.isStack)},iterableOf:function(e){return c(e,"Iterable",r.Iterable.isIterable)},recordOf:function(e){return s(function(t,n,o,i,s){for(var u=arguments.length,c=Array(u>5?u-5:0),l=5;l<u;l++)c[l-5]=arguments[l];var p=t[n];if(!(p instanceof r.Record)){var f=a(p),h=i;return new Error("Invalid "+h+" `"+s+"` of type `"+f+"` supplied to `"+o+"`, expected an Immutable.js Record.")}for(var d in e){var m=e[d];if(m){var v=p.toObject(),g=m.apply(void 0,[v,d,o,i,s+"."+d].concat(c));if(g)return g}}})},shape:f,contains:f,mapContains:function(e){return p(e,"Map",r.Map.isMap)},list:u("List",r.List.isList),map:u("Map",r.Map.isMap),orderedMap:u("OrderedMap",r.OrderedMap.isOrderedMap),set:u("Set",r.Set.isSet),orderedSet:u("OrderedSet",r.OrderedSet.isOrderedSet),stack:u("Stack",r.Stack.isStack),seq:u("Seq",r.Seq.isSeq),record:u("Record",function(e){return e instanceof r.Record}),iterable:u("Iterable",r.Iterable.isIterable)};function a(e){var t=typeof e;return Array.isArray(e)?"array":e instanceof RegExp?"object":e instanceof r.Iterable?"Immutable."+e.toSource().split(" ")[0]:t}function s(e){function t(t,n,r,i,a,s){for(var u=arguments.length,c=Array(u>6?u-6:0),l=6;l<u;l++)c[l-6]=arguments[l];return s=s||r,i=i||o,null!=n[r]?e.apply(void 0,[n,r,i,a,s].concat(c)):t?new Error("Required "+a+" `"+s+"` was not specified in `"+i+"`."):void 0}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function u(e,t){return s(function(n,r,o,i,s){var u=n[r];if(!t(u)){var c=a(u);return new Error("Invalid "+i+" `"+s+"` of type `"+c+"` supplied to `"+o+"`, expected `"+e+"`.")}return null})}function c(e,t,n){return s(function(r,o,i,s,u){for(var c=arguments.length,l=Array(c>5?c-5:0),p=5;p<c;p++)l[p-5]=arguments[p];var f=r[o];if(!n(f)){var h=s,d=a(f);return new Error("Invalid "+h+" `"+u+"` of type `"+d+"` supplied to `"+i+"`, expected an Immutable.js "+t+".")}if("function"!=typeof e)return new Error("Invalid typeChecker supplied to `"+i+"` for propType `"+u+"`, expected a function.");for(var m=f.toArray(),v=0,g=m.length;v<g;v++){var y=e.apply(void 0,[m,v,i,s,u+"["+v+"]"].concat(l));if(y instanceof Error)return y}})}function l(e,t,n,r){return s(function(){for(var o=arguments.length,i=Array(o),a=0;a<o;a++)i[a]=arguments[a];return c(e,n,r).apply(void 0,i)||t&&(u=t,s(function(e,t,n,r,o){for(var i=arguments.length,a=Array(i>5?i-5:0),s=5;s<i;s++)a[s-5]=arguments[s];var c=e[t];if("function"!=typeof u)return new Error("Invalid keysTypeChecker (optional second argument) supplied to `"+n+"` for propType `"+o+"`, expected a function.");for(var l=c.keySeq().toArray(),p=0,f=l.length;p<f;p++){var h=u.apply(void 0,[l,p,n,r,o+" -> key("+l[p]+")"].concat(a));if(h instanceof Error)return h}})).apply(void 0,i);var u})}function p(e){var t=void 0===arguments[1]?"Iterable":arguments[1],n=void 0===arguments[2]?r.Iterable.isIterable:arguments[2];return s(function(r,o,i,s,u){for(var c=arguments.length,l=Array(c>5?c-5:0),p=5;p<c;p++)l[p-5]=arguments[p];var f=r[o];if(!n(f)){var h=a(f);return new Error("Invalid "+s+" `"+u+"` of type `"+h+"` supplied to `"+i+"`, expected an Immutable.js "+t+".")}var d=f.toObject();for(var m in e){var v=e[m];if(v){var g=v.apply(void 0,[d,m,i,s,u+"."+m].concat(l));if(g)return g}}})}function f(e){return p(e)}e.exports=i},function(e,t,n){var r=n(16);function o(){return e.exports=o=r||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o.apply(this,arguments)}e.exports=o},function(e,t,n){"use strict";e.exports=function(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,r=0;r<t;r++)n+="&args[]="+encodeURIComponent(arguments[r+1]);n+=" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";var o=new Error(n);throw o.name="Invariant Violation",o.framesToPop=1,o}},function(e,t){var n=e.exports={version:"2.6.9"};"number"==typeof __e&&(__e=n)},function(e,t,n){"use strict";var r=n(54);e.exports=r},function(e,t,n){"use strict";n.r(t),n.d(t,"isOAS3",function(){return s}),n.d(t,"isSwagger2",function(){return u}),n.d(t,"OAS3ComponentWrapFactory",function(){return c});var r=n(20),o=n.n(r),i=n(0),a=n.n(i);function s(e){var t=e.get("openapi");return"string"==typeof t&&(t.startsWith("3.0.")&&t.length>4)}function u(e){var t=e.get("swagger");return"string"==typeof t&&t.startsWith("2.0")}function c(e){return function(t,n){return function(r){return n&&n.specSelectors&&n.specSelectors.specJson?s(n.specSelectors.specJson())?a.a.createElement(e,o()({},r,n,{Ori:t})):a.a.createElement(t,r):(console.warn("OAS3 wrapper: couldn't get spec"),null)}}}},function(e,t,n){"use strict";
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(e){r[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,s,u=a(e),c=1;c<arguments.length;c++){for(var l in n=Object(arguments[c]))o.call(n,l)&&(u[l]=n[l]);if(r){s=r(n);for(var p=0;p<s.length;p++)i.call(n,s[p])&&(u[s[p]]=n[s[p]])}}return u}},function(e,t,n){var r=n(546),o=n(552);function i(e){return(i="function"==typeof o&&"symbol"==typeof r?function(e){return typeof e}:function(e){return e&&"function"==typeof o&&e.constructor===o&&e!==o.prototype?"symbol":typeof e})(e)}function a(t){return"function"==typeof o&&"symbol"===i(r)?e.exports=a=function(e){return i(e)}:e.exports=a=function(e){return e&&"function"==typeof o&&e.constructor===o&&e!==o.prototype?"symbol":i(e)},a(t)}e.exports=a},function(e,t,n){"use strict";var r=n(21),o=n(111),i=n(415),a=(n(15),o.ID_ATTRIBUTE_NAME),s=i,u="__reactInternalInstance$"+Math.random().toString(36).slice(2);function c(e,t){return 1===e.nodeType&&e.getAttribute(a)===String(t)||8===e.nodeType&&e.nodeValue===" react-text: "+t+" "||8===e.nodeType&&e.nodeValue===" react-empty: "+t+" "}function l(e){for(var t;t=e._renderedComponent;)e=t;return e}function p(e,t){var n=l(e);n._hostNode=t,t[u]=n}function f(e,t){if(!(e._flags&s.hasCachedChildNodes)){var n=e._renderedChildren,o=t.firstChild;e:for(var i in n)if(n.hasOwnProperty(i)){var a=n[i],u=l(a)._domID;if(0!==u){for(;null!==o;o=o.nextSibling)if(c(o,u)){p(a,o);continue e}r("32",u)}}e._flags|=s.hasCachedChildNodes}}function h(e){if(e[u])return e[u];for(var t,n,r=[];!e[u];){if(r.push(e),!e.parentNode)return null;e=e.parentNode}for(;e&&(n=e[u]);e=r.pop())t=n,r.length&&f(n,e);return t}var d={getClosestInstanceFromNode:h,getInstanceFromNode:function(e){var t=h(e);return null!=t&&t._hostNode===e?t:null},getNodeFromInstance:function(e){if(void 0===e._hostNode&&r("33"),e._hostNode)return e._hostNode;for(var t=[];!e._hostNode;)t.push(e),e._hostParent||r("34"),e=e._hostParent;for(;t.length;e=t.pop())f(e,e._hostNode);return e._hostNode},precacheChildNodes:f,precacheNode:p,uncacheNode:function(e){var t=e._hostNode;t&&(delete t[u],e._hostNode=null)}};e.exports=d},function(e,t,n){e.exports=n(541)},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_SPEC",function(){return G}),n.d(t,"UPDATE_URL",function(){return $}),n.d(t,"UPDATE_JSON",function(){return Z}),n.d(t,"UPDATE_PARAM",function(){return X}),n.d(t,"UPDATE_EMPTY_PARAM_INCLUSION",function(){return Q}),n.d(t,"VALIDATE_PARAMS",function(){return ee}),n.d(t,"SET_RESPONSE",function(){return te}),n.d(t,"SET_REQUEST",function(){return ne}),n.d(t,"SET_MUTATED_REQUEST",function(){return re}),n.d(t,"LOG_REQUEST",function(){return oe}),n.d(t,"CLEAR_RESPONSE",function(){return ie}),n.d(t,"CLEAR_REQUEST",function(){return ae}),n.d(t,"CLEAR_VALIDATE_PARAMS",function(){return se}),n.d(t,"UPDATE_OPERATION_META_VALUE",function(){return ue}),n.d(t,"UPDATE_RESOLVED",function(){return ce}),n.d(t,"UPDATE_RESOLVED_SUBTREE",function(){return le}),n.d(t,"SET_SCHEME",function(){return pe}),n.d(t,"updateSpec",function(){return he}),n.d(t,"updateResolved",function(){return de}),n.d(t,"updateUrl",function(){return me}),n.d(t,"updateJsonSpec",function(){return ve}),n.d(t,"parseToJson",function(){return ge}),n.d(t,"resolveSpec",function(){return be}),n.d(t,"requestResolvedSubtree",function(){return xe}),n.d(t,"changeParam",function(){return Ee}),n.d(t,"changeParamByIdentity",function(){return Se}),n.d(t,"updateResolvedSubtree",function(){return Ce}),n.d(t,"invalidateResolvedSubtreeCache",function(){return ke}),n.d(t,"validateParams",function(){return Oe}),n.d(t,"updateEmptyParamInclusion",function(){return Ae}),n.d(t,"clearValidateParams",function(){return Te}),n.d(t,"changeConsumesValue",function(){return je}),n.d(t,"changeProducesValue",function(){return Pe}),n.d(t,"setResponse",function(){return Ie}),n.d(t,"setRequest",function(){return Me}),n.d(t,"setMutatedRequest",function(){return Ne}),n.d(t,"logRequest",function(){return Re}),n.d(t,"executeRequest",function(){return De}),n.d(t,"execute",function(){return Le}),n.d(t,"clearResponse",function(){return Ue}),n.d(t,"clearRequest",function(){return qe}),n.d(t,"setScheme",function(){return Fe});var r=n(92),o=n.n(r),i=n(57),a=n.n(i),s=n(58),u=n.n(s),c=n(52),l=n.n(c),p=n(2),f=n.n(p),h=n(46),d=n.n(h),m=n(324),v=n.n(m),g=n(16),y=n.n(g),b=n(17),_=n.n(b),w=n(189),x=n.n(w),E=n(119),S=n.n(E),C=n(190),k=n.n(C),O=n(51),A=n.n(O),T=n(14),j=n.n(T),P=n(26),I=n.n(P),M=n(143),N=n.n(M),R=n(1),D=n(93),L=n.n(D),U=n(115),q=n.n(U),F=n(275),z=n.n(F),B=n(471),V=n.n(B),H=n(325),W=n.n(H),J=n(3);function Y(e,t){var n=_()(e);if(l.a){var r=l()(e);t&&(r=r.filter(function(t){return u()(e,t).enumerable})),n.push.apply(n,r)}return n}function K(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Y(n,!0).forEach(function(t){f()(e,t,n[t])}):a.a?o()(e,a()(n)):Y(n).forEach(function(t){A()(e,t,u()(n,t))})}return e}var G="spec_update_spec",$="spec_update_url",Z="spec_update_json",X="spec_update_param",Q="spec_update_empty_param_inclusion",ee="spec_validate_param",te="spec_set_response",ne="spec_set_request",re="spec_set_mutated_request",oe="spec_log_request",ie="spec_clear_response",ae="spec_clear_request",se="spec_clear_validate_param",ue="spec_update_operation_meta_value",ce="spec_update_resolved",le="spec_update_resolved_subtree",pe="set_scheme",fe=function(e){return z()(e)?e:""};function he(e){var t=fe(e).replace(/\t/g," ");if("string"==typeof e)return{type:G,payload:t}}function de(e){return{type:ce,payload:e}}function me(e){return{type:$,payload:e}}function ve(e){return{type:Z,payload:e}}var ge=function(e){return function(t){var n=t.specActions,r=t.specSelectors,o=t.errActions,i=r.specStr,a=null;try{e=e||i(),o.clear({source:"parser"}),a=N.a.safeLoad(e)}catch(e){return console.error(e),o.newSpecErr({source:"parser",level:"error",message:e.reason,line:e.mark&&e.mark.line?e.mark.line+1:void 0})}return a&&"object"===I()(a)?n.updateJsonSpec(a):{}}},ye=!1,be=function(e,t){return function(n){var r=n.specActions,o=n.specSelectors,i=n.errActions,a=n.fn,s=a.fetch,u=a.resolve,c=a.AST,l=void 0===c?{}:c,p=n.getConfigs;ye||(console.warn("specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use requestResolvedSubtree instead!"),ye=!0);var f=p(),h=f.modelPropertyMacro,d=f.parameterMacro,m=f.requestInterceptor,v=f.responseInterceptor;void 0===e&&(e=o.specJson()),void 0===t&&(t=o.url());var g=l.getLineNumberForPath?l.getLineNumberForPath:function(){},y=o.specStr();return u({fetch:s,spec:e,baseDoc:t,modelPropertyMacro:h,parameterMacro:d,requestInterceptor:m,responseInterceptor:v}).then(function(e){var t=e.spec,n=e.errors;if(i.clear({type:"thrown"}),j()(n)&&n.length>0){var o=n.map(function(e){return console.error(e),e.line=e.fullPath?g(y,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",A()(e,"message",{enumerable:!0,value:e.message}),e});i.newThrownErrBatch(o)}return r.updateResolved(t)})}},_e=[],we=V()(k()(S.a.mark(function e(){var t,n,r,o,i,a,s,u,c,l,p,f,h,d,m,v,g;return S.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t=_e.system){e.next=4;break}return console.error("debResolveSubtrees: don't have a system to operate on, aborting."),e.abrupt("return");case 4:if(n=t.errActions,r=t.errSelectors,o=t.fn,i=o.resolveSubtree,a=o.AST,s=void 0===a?{}:a,u=t.specSelectors,c=t.specActions,i){e.next=8;break}return console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing."),e.abrupt("return");case 8:return l=s.getLineNumberForPath?s.getLineNumberForPath:function(){},p=u.specStr(),f=t.getConfigs(),h=f.modelPropertyMacro,d=f.parameterMacro,m=f.requestInterceptor,v=f.responseInterceptor,e.prev=11,e.next=14,_e.reduce(function(){var e=k()(S.a.mark(function e(t,o){var a,s,c,f,g,y,b;return S.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t;case 2:return a=e.sent,s=a.resultMap,c=a.specWithCurrentSubtrees,e.next=7,i(c,o,{baseDoc:u.url(),modelPropertyMacro:h,parameterMacro:d,requestInterceptor:m,responseInterceptor:v});case 7:return f=e.sent,g=f.errors,y=f.spec,r.allErrors().size&&n.clearBy(function(e){return"thrown"!==e.get("type")||"resolver"!==e.get("source")||!e.get("fullPath").every(function(e,t){return e===o[t]||void 0===o[t]})}),j()(g)&&g.length>0&&(b=g.map(function(e){return e.line=e.fullPath?l(p,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",A()(e,"message",{enumerable:!0,value:e.message}),e}),n.newThrownErrBatch(b)),W()(s,o,y),W()(c,o,y),e.abrupt("return",{resultMap:s,specWithCurrentSubtrees:c});case 15:case"end":return e.stop()}},e)}));return function(t,n){return e.apply(this,arguments)}}(),x.a.resolve({resultMap:(u.specResolvedSubtree([])||Object(R.Map)()).toJS(),specWithCurrentSubtrees:u.specJson().toJS()}));case 14:g=e.sent,delete _e.system,_e=[],e.next=22;break;case 19:e.prev=19,e.t0=e.catch(11),console.error(e.t0);case 22:c.updateResolvedSubtree([],g.resultMap);case 23:case"end":return e.stop()}},e,null,[[11,19]])})),35),xe=function(e){return function(t){_e.map(function(e){return e.join("@@")}).indexOf(e.join("@@"))>-1||(_e.push(e),_e.system=t,we())}};function Ee(e,t,n,r,o){return{type:X,payload:{path:e,value:r,paramName:t,paramIn:n,isXml:o}}}function Se(e,t,n,r){return{type:X,payload:{path:e,param:t,value:n,isXml:r}}}var Ce=function(e,t){return{type:le,payload:{path:e,value:t}}},ke=function(){return{type:le,payload:{path:[],value:Object(R.Map)()}}},Oe=function(e,t){return{type:ee,payload:{pathMethod:e,isOAS3:t}}},Ae=function(e,t,n,r){return{type:Q,payload:{pathMethod:e,paramName:t,paramIn:n,includeEmptyValue:r}}};function Te(e){return{type:se,payload:{pathMethod:e}}}function je(e,t){return{type:ue,payload:{path:e,value:t,key:"consumes_value"}}}function Pe(e,t){return{type:ue,payload:{path:e,value:t,key:"produces_value"}}}var Ie=function(e,t,n){return{payload:{path:e,method:t,res:n},type:te}},Me=function(e,t,n){return{payload:{path:e,method:t,req:n},type:ne}},Ne=function(e,t,n){return{payload:{path:e,method:t,req:n},type:re}},Re=function(e){return{payload:e,type:oe}},De=function(e){return function(t){var n=t.fn,r=t.specActions,o=t.specSelectors,i=t.getConfigs,a=t.oas3Selectors,s=e.pathName,u=e.method,c=e.operation,l=i(),p=l.requestInterceptor,f=l.responseInterceptor,h=c.toJS();if(c&&c.get("parameters")&&c.get("parameters").filter(function(e){return e&&!0===e.get("allowEmptyValue")}).forEach(function(t){if(o.parameterInclusionSettingFor([s,u],t.get("name"),t.get("in"))){e.parameters=e.parameters||{};var n=Object(J.A)(t,e.parameters);(!n||n&&0===n.size)&&(e.parameters[t.get("name")]="")}}),e.contextUrl=L()(o.url()).toString(),h&&h.operationId?e.operationId=h.operationId:h&&s&&u&&(e.operationId=n.opId(h,s,u)),o.isOAS3()){var d="".concat(s,":").concat(u);e.server=a.selectedServer(d)||a.selectedServer();var m=a.serverVariables({server:e.server,namespace:d}).toJS(),g=a.serverVariables({server:e.server}).toJS();e.serverVariables=_()(m).length?m:g,e.requestContentType=a.requestContentType(s,u),e.responseContentType=a.responseContentType(s,u)||"*/*";var b=a.requestBodyValue(s,u);Object(J.r)(b)?e.requestBody=JSON.parse(b):b&&b.toJS?e.requestBody=b.toJS():e.requestBody=b}var w=y()({},e);w=n.buildRequest(w),r.setRequest(e.pathName,e.method,w);e.requestInterceptor=function(t){var n=p.apply(this,[t]),o=y()({},n);return r.setMutatedRequest(e.pathName,e.method,o),n},e.responseInterceptor=f;var x=v()();return n.execute(e).then(function(t){t.duration=v()()-x,r.setResponse(e.pathName,e.method,t)}).catch(function(t){console.error(t),r.setResponse(e.pathName,e.method,{error:!0,err:q()(t)})})}},Le=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.path,n=e.method,r=d()(e,["path","method"]);return function(e){var o=e.fn.fetch,i=e.specSelectors,a=e.specActions,s=i.specJsonWithResolvedSubtrees().toJS(),u=i.operationScheme(t,n),c=i.contentTypeValues([t,n]).toJS(),l=c.requestContentType,p=c.responseContentType,f=/xml/i.test(l),h=i.parameterValues([t,n],f).toJS();return a.executeRequest(K({},r,{fetch:o,spec:s,pathName:t,method:n,parameters:h,requestContentType:l,scheme:u,responseContentType:p}))}};function Ue(e,t){return{type:ie,payload:{path:e,method:t}}}function qe(e,t){return{type:ae,payload:{path:e,method:t}}}function Fe(e,t,n){return{type:pe,payload:{scheme:e,path:t,method:n}}}},function(e,t,n){var r=n(32),o=n(22),i=n(60),a=n(71),s=n(69),u=function(e,t,n){var c,l,p,f=e&u.F,h=e&u.G,d=e&u.S,m=e&u.P,v=e&u.B,g=e&u.W,y=h?o:o[t]||(o[t]={}),b=y.prototype,_=h?r:d?r[t]:(r[t]||{}).prototype;for(c in h&&(n=t),n)(l=!f&&_&&void 0!==_[c])&&s(y,c)||(p=l?_[c]:n[c],y[c]=h&&"function"!=typeof _[c]?n[c]:v&&l?i(p,r):g&&_[c]==p?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(p):m&&"function"==typeof p?i(Function.call,p):p,m&&((y.virtual||(y.virtual={}))[c]=p,e&u.R&&b&&!b[c]&&a(b,c,p)))};u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},function(e,t,n){"use strict";var r=n(135),o=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],i=["scalar","sequence","mapping"];e.exports=function(e,t){var n,a;if(t=t||{},Object.keys(t).forEach(function(t){if(-1===o.indexOf(t))throw new r('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')}),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=(n=t.styleAliases||null,a={},null!==n&&Object.keys(n).forEach(function(e){n[e].forEach(function(t){a[String(t)]=e})}),a),-1===i.indexOf(this.kind))throw new r('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){var r=n(328)("wks"),o=n(195),i=n(43).Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},function(e,t,n){var r=n(206)("wks"),o=n(155),i=n(32).Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){"use strict";var r=!("undefined"==typeof window||!window.document||!window.document.createElement),o={canUseDOM:r,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:r&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:r&&!!window.screen,isInWorker:!r};e.exports=o},function(e,t,n){"use strict";var r=Object.prototype.hasOwnProperty;function o(e,t){return!!e&&r.call(e,t)}var i=/\\([\\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;function a(e){return!(e>=55296&&e<=57343)&&(!(e>=64976&&e<=65007)&&(65535!=(65535&e)&&65534!=(65535&e)&&(!(e>=0&&e<=8)&&(11!==e&&(!(e>=14&&e<=31)&&(!(e>=127&&e<=159)&&!(e>1114111)))))))}function s(e){if(e>65535){var t=55296+((e-=65536)>>10),n=56320+(1023&e);return String.fromCharCode(t,n)}return String.fromCharCode(e)}var u=/&([a-z#][a-z0-9]{1,31});/gi,c=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i,l=n(457);function p(e,t){var n=0;return o(l,t)?l[t]:35===t.charCodeAt(0)&&c.test(t)&&a(n="x"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10))?s(n):e}var f=/[&<>"]/,h=/[&<>"]/g,d={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"};function m(e){return d[e]}t.assign=function(e){return[].slice.call(arguments,1).forEach(function(t){if(t){if("object"!=typeof t)throw new TypeError(t+"must be object");Object.keys(t).forEach(function(n){e[n]=t[n]})}}),e},t.isString=function(e){return"[object String]"===function(e){return Object.prototype.toString.call(e)}(e)},t.has=o,t.unescapeMd=function(e){return e.indexOf("\\")<0?e:e.replace(i,"$1")},t.isValidEntityCode=a,t.fromCodePoint=s,t.replaceEntities=function(e){return e.indexOf("&")<0?e:e.replace(u,p)},t.escapeHtml=function(e){return f.test(e)?e.replace(h,m):e}},function(e,t,n){var r=n(43),o=n(78),i=n(76),a=n(95),s=n(150),u=function(e,t,n){var c,l,p,f,h=e&u.F,d=e&u.G,m=e&u.S,v=e&u.P,g=e&u.B,y=d?r:m?r[t]||(r[t]={}):(r[t]||{}).prototype,b=d?o:o[t]||(o[t]={}),_=b.prototype||(b.prototype={});for(c in d&&(n=t),n)p=((l=!h&&y&&void 0!==y[c])?y:n)[c],f=g&&l?s(p,r):v&&"function"==typeof p?s(Function.call,p):p,y&&a(y,c,p,e&u.U),b[c]!=p&&i(b,c,f),v&&_[c]!=p&&(_[c]=p)};r.core=o,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},function(e,t,n){var r=n(38),o=n(123),i=n(68),a=/"/g,s=function(e,t,n,r){var o=String(i(e)),s="<"+t;return""!==n&&(s+=" "+n+'="'+String(r).replace(a,"&quot;")+'"'),s+">"+o+"</"+t+">"};e.exports=function(e,t){var n={};n[e]=t(s),r(r.P+r.F*o(function(){var t=""[e]('"');return t!==t.toLowerCase()||t.split('"').length>3}),"String",n)}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";n.r(t),n.d(t,"NEW_THROWN_ERR",function(){return i}),n.d(t,"NEW_THROWN_ERR_BATCH",function(){return a}),n.d(t,"NEW_SPEC_ERR",function(){return s}),n.d(t,"NEW_SPEC_ERR_BATCH",function(){return u}),n.d(t,"NEW_AUTH_ERR",function(){return c}),n.d(t,"CLEAR",function(){return l}),n.d(t,"CLEAR_BY",function(){return p}),n.d(t,"newThrownErr",function(){return f}),n.d(t,"newThrownErrBatch",function(){return h}),n.d(t,"newSpecErr",function(){return d}),n.d(t,"newSpecErrBatch",function(){return m}),n.d(t,"newAuthErr",function(){return v}),n.d(t,"clear",function(){return g}),n.d(t,"clearBy",function(){return y});var r=n(115),o=n.n(r),i="err_new_thrown_err",a="err_new_thrown_err_batch",s="err_new_spec_err",u="err_new_spec_err_batch",c="err_new_auth_err",l="err_clear",p="err_clear_by";function f(e){return{type:i,payload:o()(e)}}function h(e){return{type:a,payload:e}}function d(e){return{type:s,payload:e}}function m(e){return{type:u,payload:e}}function v(e){return{type:c,payload:e}}function g(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:l,payload:e}}function y(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!0};return{type:p,payload:e}}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){var r=n(40);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){e.exports=!n(80)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,n){var r=n(52),o=n(756);e.exports=function(e,t){if(null==e)return{};var n,i,a=o(e,t);if(r){var s=r(e);for(i=0;i<s.length;i++)n=s[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}},function(e,t,n){var r=n(44),o=n(344),i=n(210),a=Object.defineProperty;t.f=n(45)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){var r=n(361),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();e.exports=i},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t,n){"use strict";e.exports={debugTool:null}},function(e,t,n){e.exports=n(562)},function(e,t,n){e.exports=n(755)},function(e,t,n){e.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([function(e,t){e.exports=n(17)},function(e,t){e.exports=n(14)},function(e,t){e.exports=n(26)},function(e,t){e.exports=n(16)},function(e,t){e.exports=n(119)},function(e,t){e.exports=n(57)},function(e,t){e.exports=n(58)},function(e,t){e.exports=n(52)},function(e,t){e.exports=n(2)},function(e,t){e.exports=n(51)},function(e,t){e.exports=n(92)},function(e,t){e.exports=n(28)},function(e,t){e.exports=n(916)},function(e,t){e.exports=n(12)},function(e,t){e.exports=n(189)},function(e,t){e.exports=n(922)},function(e,t){e.exports=n(91)},function(e,t){e.exports=n(190)},function(e,t){e.exports=n(925)},function(e,t){e.exports=n(929)},function(e,t){e.exports=n(930)},function(e,t){e.exports=n(90)},function(e,t){e.exports=n(13)},function(e,t){e.exports=n(143)},function(e,t){e.exports=n(4)},function(e,t){e.exports=n(5)},function(e,t){e.exports=n(932)},function(e,t){e.exports=n(414)},function(e,t){e.exports=n(935)},function(e,t){e.exports=n(49)},function(e,t){e.exports=n(61)},function(e,t){e.exports=n(275)},function(e,t){e.exports=n(264)},function(e,t){e.exports=n(936)},function(e,t){e.exports=n(142)},function(e,t){e.exports=n(937)},function(e,t){e.exports=n(945)},function(e,t){e.exports=n(946)},function(e,t){e.exports=n(947)},function(e,t){e.exports=n(46)},function(e,t){e.exports=n(256)},function(e,t){e.exports=n(35)},function(e,t){e.exports=n(950)},function(e,t){e.exports=n(951)},function(e,t){e.exports=n(952)},function(e,t,n){e.exports=n(50)},function(e,t){e.exports=n(953)},function(e,t){e.exports=n(954)},function(e,t){e.exports=n(955)},function(e,t){e.exports=n(956)},function(e,t,n){"use strict";n.r(t);var r={};n.r(r),n.d(r,"path",function(){return dn}),n.d(r,"query",function(){return mn}),n.d(r,"header",function(){return gn}),n.d(r,"cookie",function(){return yn});var o=n(9),i=n.n(o),a=n(10),s=n.n(a),u=n(5),c=n.n(u),l=n(6),p=n.n(l),f=n(7),h=n.n(f),d=n(0),m=n.n(d),v=n(8),g=n.n(v),y=(n(46),n(15)),b=n.n(y),_=n(20),w=n.n(_),x=n(12),E=n.n(x),S=n(4),C=n.n(S),k=n(22),O=n.n(k),A=n(11),T=n.n(A),j=n(2),P=n.n(j),I=n(1),M=n.n(I),N=n(17),R=n.n(N),D=(n(47),n(26)),L=n.n(D),U=n(23),q=n.n(U),F=n(31),z=n.n(F),B={serializeRes:J,mergeInQueryOrForm:Z};function V(e){return H.apply(this,arguments)}function H(){return(H=R()(C.a.mark(function e(t){var n,r,o,i,a,s=arguments;return C.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(n=s.length>1&&void 0!==s[1]?s[1]:{},"object"===P()(t)&&(t=(n=t).url),n.headers=n.headers||{},B.mergeInQueryOrForm(n),n.headers&&m()(n.headers).forEach(function(e){var t=n.headers[e];"string"==typeof t&&(n.headers[e]=t.replace(/\n+/g," "))}),!n.requestInterceptor){e.next=12;break}return e.next=8,n.requestInterceptor(n);case 8:if(e.t0=e.sent,e.t0){e.next=11;break}e.t0=n;case 11:n=e.t0;case 12:return r=n.headers["content-type"]||n.headers["Content-Type"],/multipart\/form-data/i.test(r)&&(delete n.headers["content-type"],delete n.headers["Content-Type"]),e.prev=14,e.next=17,(n.userFetch||fetch)(n.url,n);case 17:return o=e.sent,e.next=20,B.serializeRes(o,t,n);case 20:if(o=e.sent,!n.responseInterceptor){e.next=28;break}return e.next=24,n.responseInterceptor(o);case 24:if(e.t1=e.sent,e.t1){e.next=27;break}e.t1=o;case 27:o=e.t1;case 28:e.next=38;break;case 30:if(e.prev=30,e.t2=e.catch(14),o){e.next=34;break}throw e.t2;case 34:throw(i=new Error(o.statusText)).statusCode=i.status=o.status,i.responseError=e.t2,i;case 38:if(o.ok){e.next=43;break}throw(a=new Error(o.statusText)).statusCode=a.status=o.status,a.response=o,a;case 43:return e.abrupt("return",o);case 44:case"end":return e.stop()}},e,null,[[14,30]])}))).apply(this,arguments)}var W=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return/(json|xml|yaml|text)\b/.test(e)};function J(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).loadSpec,r=void 0!==n&&n,o={ok:e.ok,url:e.url||t,status:e.status,statusText:e.statusText,headers:Y(e.headers)},i=o.headers["content-type"],a=r||W(i);return(a?e.text:e.blob||e.buffer).call(e).then(function(e){if(o.text=e,o.data=e,a)try{var t=function(e,t){return t&&(0===t.indexOf("application/json")||t.indexOf("+json")>0)?JSON.parse(e):q.a.safeLoad(e)}(e,i);o.body=t,o.obj=t}catch(e){o.parseError=e}return o})}function Y(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t={};return"function"==typeof e.forEach?(e.forEach(function(e,n){void 0!==t[n]?(t[n]=M()(t[n])?t[n]:[t[n]],t[n].push(e)):t[n]=e}),t):t}function K(e,t){return t||"undefined"==typeof navigator||(t=navigator),t&&"ReactNative"===t.product?!(!e||"object"!==P()(e)||"string"!=typeof e.uri):"undefined"!=typeof File?e instanceof File:null!==e&&"object"===P()(e)&&"function"==typeof e.pipe}function G(e,t){var n=e.collectionFormat,r=e.allowEmptyValue,o="object"===P()(e)?e.value:e;if(void 0===o&&r)return"";if(K(o)||"boolean"==typeof o)return o;var i=encodeURIComponent;return t&&(i=z()(o)?function(e){return e}:function(e){return T()(e)}),"object"!==P()(o)||M()(o)?M()(o)?M()(o)&&!n?o.map(i).join(","):"multi"===n?o.map(i):o.map(i).join({csv:",",ssv:"%20",tsv:"%09",pipes:"|"}[n]):i(o):""}function $(e){var t=m()(e).reduce(function(t,n){var r,o=e[n],i=!!o.skipEncoding,a=i?n:encodeURIComponent(n),s=(r=o)&&"object"===P()(r)&&!M()(o);return t[a]=G(s?o:{value:o},i),t},{});return L.a.stringify(t,{encode:!1,indices:!1})||""}function Z(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,r=void 0===t?"":t,o=e.query,i=e.form;if(i){var a=m()(i).some(function(e){return K(i[e].value)}),s=e.headers["content-type"]||e.headers["Content-Type"];if(a||/multipart\/form-data/i.test(s)){var u=n(48);e.body=new u,m()(i).forEach(function(t){e.body.append(t,G(i[t],!0))})}else e.body=$(i);delete e.form}if(o){var c=r.split("?"),l=O()(c,2),p=l[0],f=l[1],h="";if(f){var d=L.a.parse(f);m()(o).forEach(function(e){return delete d[e]}),h=L.a.stringify(d,{encode:!0})}var v=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=t.filter(function(e){return e}).join("&");return r?"?".concat(r):""}(h,$(o));e.url=p+v,delete e.query}return e}var X=n(14),Q=n.n(X),ee=n(21),te=n.n(ee),ne=n(27),re=n.n(ne),oe=n(3),ie=n.n(oe),ae=n(24),se=n.n(ae),ue=n(25),ce=n.n(ue),le=n(32),pe=n.n(le),fe=n(13),he=n.n(fe),de=n(18),me=n.n(de),ve=n(33),ge=n.n(ve),ye=n(34),be=n.n(ye),_e={add:function(e,t){return{op:"add",path:e,value:t}},replace:xe,remove:function(e,t){return{op:"remove",path:e}},merge:function(e,t){return{type:"mutation",op:"merge",path:e,value:t}},mergeDeep:function(e,t){return{type:"mutation",op:"mergeDeep",path:e,value:t}},context:function(e,t){return{type:"context",path:e,value:t}},getIn:function(e,t){return t.reduce(function(e,t){return void 0!==t&&e?e[t]:e},e)},applyPatch:function(e,t,n){if(n=n||{},"merge"===(t=ie()({},t,{path:t.path&&we(t.path)})).op){var r=Re(e,t.path);ie()(r,t.value),me.a.applyPatch(e,[xe(t.path,r)])}else if("mergeDeep"===t.op){var o=Re(e,t.path);for(var i in t.value){var a=t.value[i],s=M()(a);if(s){var u=o[i]||[];o[i]=u.concat(a)}else if(Te(a)&&!s){var c=ie()({},o[i]);for(var l in a){if(Object.prototype.hasOwnProperty.call(c,l)){c=ge()(be()({},c),a);break}ie()(c,g()({},l,a[l]))}o[i]=c}else o[i]=a}}else if("add"===t.op&&""===t.path&&Te(t.value)){var p=m()(t.value).reduce(function(e,n){return e.push({op:"add",path:"/".concat(we(n)),value:t.value[n]}),e},[]);me.a.applyPatch(e,p)}else if("replace"===t.op&&""===t.path){var f=t.value;n.allowMetaPatches&&t.meta&&Me(t)&&(M()(t.value)||Te(t.value))&&(f=ie()({},f,t.meta)),e=f}else if(me.a.applyPatch(e,[t]),n.allowMetaPatches&&t.meta&&Me(t)&&(M()(t.value)||Te(t.value))){var h=Re(e,t.path),d=ie()({},h,t.meta);me.a.applyPatch(e,[xe(t.path,d)])}return e},parentPathMatch:function(e,t){if(!M()(t))return!1;for(var n=0,r=t.length;n<r;n++)if(t[n]!==e[n])return!1;return!0},flatten:Oe,fullyNormalizeArray:function(e){return Ae(Oe(ke(e)))},normalizeArray:ke,isPromise:function(e){return Te(e)&&je(e.then)},forEachNew:function(e,t){try{return Ee(e,Ce,t)}catch(e){return e}},forEachNewPrimitive:function(e,t){try{return Ee(e,Se,t)}catch(e){return e}},isJsonPatch:Pe,isContextPatch:function(e){return Ne(e)&&"context"===e.type},isPatch:Ne,isMutation:Ie,isAdditiveMutation:Me,isGenerator:function(e){return C.a.isGeneratorFunction(e)},isFunction:je,isObject:Te,isError:function(e){return e instanceof Error}};function we(e){return M()(e)?e.length<1?"":"/"+e.map(function(e){return(e+"").replace(/~/g,"~0").replace(/\//g,"~1")}).join("/"):e}function xe(e,t,n){return{op:"replace",path:e,value:t,meta:n}}function Ee(e,t,n){return Ae(Oe(e.filter(Me).map(function(e){return t(e.value,n,e.path)})||[]))}function Se(e,t,n){return n=n||[],M()(e)?e.map(function(e,r){return Se(e,t,n.concat(r))}):Te(e)?m()(e).map(function(r){return Se(e[r],t,n.concat(r))}):t(e,n[n.length-1],n)}function Ce(e,t,n){var r=[];if((n=n||[]).length>0){var o=t(e,n[n.length-1],n);o&&(r=r.concat(o))}if(M()(e)){var i=e.map(function(e,r){return Ce(e,t,n.concat(r))});i&&(r=r.concat(i))}else if(Te(e)){var a=m()(e).map(function(r){return Ce(e[r],t,n.concat(r))});a&&(r=r.concat(a))}return r=Oe(r)}function ke(e){return M()(e)?e:[e]}function Oe(e){var t;return(t=[]).concat.apply(t,he()(e.map(function(e){return M()(e)?Oe(e):e})))}function Ae(e){return e.filter(function(e){return void 0!==e})}function Te(e){return e&&"object"===P()(e)}function je(e){return e&&"function"==typeof e}function Pe(e){if(Ne(e)){var t=e.op;return"add"===t||"remove"===t||"replace"===t}return!1}function Ie(e){return Pe(e)||Ne(e)&&"mutation"===e.type}function Me(e){return Ie(e)&&("add"===e.op||"replace"===e.op||"merge"===e.op||"mergeDeep"===e.op)}function Ne(e){return e&&"object"===P()(e)}function Re(e,t){try{return me.a.getValueByPointer(e,t)}catch(e){return console.error(e),{}}}var De=n(35),Le=n.n(De),Ue=n(36),qe=n(28),Fe=n.n(qe);function ze(e,t){function n(){Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack;for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];this.message=n[0],t&&t.apply(this,n)}return n.prototype=new Error,n.prototype.name=e,n.prototype.constructor=n,n}var Be=n(37),Ve=n.n(Be),He=["properties"],We=["properties"],Je=["definitions","parameters","responses","securityDefinitions","components/schemas","components/responses","components/parameters","components/securitySchemes"],Ye=["schema/example","items/example"];function Ke(e){var t=e[e.length-1],n=e[e.length-2],r=e.join("/");return He.indexOf(t)>-1&&-1===We.indexOf(n)||Je.indexOf(r)>-1||Ye.some(function(e){return r.indexOf(e)>-1})}function Ge(e,t){var n=e.split("#"),r=O()(n,2),o=r[0],i=r[1],a=E.a.resolve(o||"",t||"");return i?"".concat(a,"#").concat(i):a}var $e=new RegExp("^([a-z]+://|//)","i"),Ze=ze("JSONRefError",function(e,t,n){this.originalError=n,ie()(this,t||{})}),Xe={},Qe=new Le.a,et=[function(e){return"paths"===e[0]&&"responses"===e[3]&&"content"===e[5]&&"example"===e[7]},function(e){return"paths"===e[0]&&"requestBody"===e[3]&&"content"===e[4]&&"example"===e[6]}],tt={key:"$ref",plugin:function(e,t,n,r){var o=r.getInstance(),i=n.slice(0,-1);if(!Ke(i)&&(a=i,!et.some(function(e){return e(a)}))){var a,s=r.getContext(n).baseDoc;if("string"!=typeof e)return new Ze("$ref: must be a string (JSON-Ref)",{$ref:e,baseDoc:s,fullPath:n});var u,c,l,p=at(e),f=p[0],h=p[1]||"";try{u=s||f?ot(f,s):null}catch(t){return it(t,{pointer:h,$ref:e,basePath:u,fullPath:n})}if(function(e,t,n,r){var o=Qe.get(r);o||(o={},Qe.set(r,o));var i=function(e){if(0===e.length)return"";return"/".concat(e.map(ft).join("/"))}(n),a="".concat(t||"<specmap-base>","#").concat(e),s=i.replace(/allOf\/\d+\/?/g,""),u=r.contextTree.get([]).baseDoc;if(t==u&&dt(s,e))return!0;var c="";if(n.some(function(e){return c="".concat(c,"/").concat(ft(e)),o[c]&&o[c].some(function(e){return dt(e,a)||dt(a,e)})}))return!0;o[s]=(o[s]||[]).concat(a)}(h,u,i,r)&&!o.useCircularStructures){var d=Ge(e,u);return e===d?null:_e.replace(n,d)}if(null==u?(l=lt(h),void 0===(c=r.get(l))&&(c=new Ze("Could not resolve reference: ".concat(e),{pointer:h,$ref:e,baseDoc:s,fullPath:n}))):c=null!=(c=st(u,h)).__value?c.__value:c.catch(function(t){throw it(t,{pointer:h,$ref:e,baseDoc:s,fullPath:n})}),c instanceof Error)return[_e.remove(n),c];var v=Ge(e,u),g=_e.replace(i,c,{$$ref:v});if(u&&u!==s)return[g,_e.context(i,{baseDoc:u})];try{if(!function(e,t){var n=[e];return t.path.reduce(function(e,t){return n.push(e[t]),e[t]},e),function e(t){return _e.isObject(t)&&(n.indexOf(t)>=0||m()(t).some(function(n){return e(t[n])}))}(t.value)}(r.state,g)||o.useCircularStructures)return g}catch(e){return null}}}},nt=ie()(tt,{docCache:Xe,absoluteify:ot,clearCache:function(e){void 0!==e?delete Xe[e]:m()(Xe).forEach(function(e){delete Xe[e]})},JSONRefError:Ze,wrapError:it,getDoc:ut,split:at,extractFromDoc:st,fetchJSON:function(e){return Object(Ue.fetch)(e,{headers:{Accept:"application/json, application/yaml"},loadSpec:!0}).then(function(e){return e.text()}).then(function(e){return q.a.safeLoad(e)})},extract:ct,jsonPointerToArray:lt,unescapeJsonPointerToken:pt}),rt=nt;function ot(e,t){if(!$e.test(e)){if(!t)throw new Ze("Tried to resolve a relative URL, without having a basePath. path: '".concat(e,"' basePath: '").concat(t,"'"));return E.a.resolve(t,e)}return e}function it(e,t){var n;return n=e&&e.response&&e.response.body?"".concat(e.response.body.code," ").concat(e.response.body.message):e.message,new Ze("Could not resolve reference: ".concat(n),t,e)}function at(e){return(e+"").split("#")}function st(e,t){var n=Xe[e];if(n&&!_e.isPromise(n))try{var r=ct(t,n);return ie()(Q.a.resolve(r),{__value:r})}catch(e){return Q.a.reject(e)}return ut(e).then(function(e){return ct(t,e)})}function ut(e){var t=Xe[e];return t?_e.isPromise(t)?t:Q.a.resolve(t):(Xe[e]=nt.fetchJSON(e).then(function(t){return Xe[e]=t,t}),Xe[e])}function ct(e,t){var n=lt(e);if(n.length<1)return t;var r=_e.getIn(t,n);if(void 0===r)throw new Ze("Could not resolve pointer: ".concat(e," does not exist in document"),{pointer:e});return r}function lt(e){if("string"!=typeof e)throw new TypeError("Expected a string, got a ".concat(P()(e)));return"/"===e[0]&&(e=e.substr(1)),""===e?[]:e.split("/").map(pt)}function pt(e){return"string"!=typeof e?e:Fe.a.unescape(e.replace(/~1/g,"/").replace(/~0/g,"~"))}function ft(e){return Fe.a.escape(e.replace(/~/g,"~0").replace(/\//g,"~1"))}var ht=function(e){return!e||"/"===e||"#"===e};function dt(e,t){if(ht(t))return!0;var n=e.charAt(t.length),r=t.slice(-1);return 0===e.indexOf(t)&&(!n||"/"===n||"#"===n)&&"#"!==r}var mt={key:"allOf",plugin:function(e,t,n,r,o){if(!o.meta||!o.meta.$$ref){var i=n.slice(0,-1);if(!Ke(i)){if(!M()(e)){var a=new TypeError("allOf must be an array");return a.fullPath=n,a}var s=!1,u=o.value;i.forEach(function(e){u&&(u=u[e])}),delete(u=ie()({},u)).allOf;var c=[];return c.push(r.replace(i,{})),e.forEach(function(e,t){if(!r.isObject(e)){if(s)return null;s=!0;var o=new TypeError("Elements in allOf must be objects");return o.fullPath=n,c.push(o)}c.push(r.mergeDeep(i,e));var a=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.specmap,o=n.getBaseUrlForNodePath,i=void 0===o?function(e){return r.getContext([].concat(he()(t),he()(e))).baseDoc}:o,a=n.targetKeys,s=void 0===a?["$ref","$$ref"]:a,u=[];return Ve()(e).forEach(function(){if(s.indexOf(this.key)>-1){var e=this.path,n=t.concat(this.path),o=Ge(this.node,i(e));u.push(r.replace(n,o))}}),u}(e,n.slice(0,-1),{getBaseUrlForNodePath:function(e){return r.getContext([].concat(he()(n),[t],he()(e))).baseDoc},specmap:r});c.push.apply(c,he()(a))}),c.push(r.mergeDeep(i,u)),u.$$ref||c.push(r.remove([].concat(i,"$$ref"))),c}}}},vt={key:"parameters",plugin:function(e,t,n,r,o){if(M()(e)&&e.length){var i=ie()([],e),a=n.slice(0,-1),s=ie()({},_e.getIn(r.spec,a));return e.forEach(function(e,t){try{i[t].default=r.parameterMacro(s,e)}catch(e){var o=new Error(e);return o.fullPath=n,o}}),_e.replace(n,i)}return _e.replace(n,e)}},gt={key:"properties",plugin:function(e,t,n,r){var o=ie()({},e);for(var i in e)try{o[i].default=r.modelPropertyMacro(o[i])}catch(e){var a=new Error(e);return a.fullPath=n,a}return _e.replace(n,o)}};function yt(e,t){var n=m()(e);if(h.a){var r=h()(e);t&&(r=r.filter(function(t){return p()(e,t).enumerable})),n.push.apply(n,r)}return n}var bt=function(){function e(t){se()(this,e),this.root=_t(t||{})}return ce()(e,[{key:"set",value:function(e,t){var n=this.getParent(e,!0);if(n){var r=e[e.length-1],o=n.children;o[r]?wt(o[r],t,n):o[r]=_t(t,n)}else wt(this.root,t,null)}},{key:"get",value:function(e){if((e=e||[]).length<1)return this.root.value;for(var t,n,r=this.root,o=0;o<e.length&&(n=e[o],(t=r.children)[n]);o++)r=t[n];return r&&r.protoValue}},{key:"getParent",value:function(e,t){return!e||e.length<1?null:e.length<2?this.root:e.slice(0,-1).reduce(function(e,n){if(!e)return e;var r=e.children;return!r[n]&&t&&(r[n]=_t(null,e)),r[n]},this.root)}}]),e}();function _t(e,t){return wt({children:{}},e,t)}function wt(e,t,n){return e.value=t||{},e.protoValue=n?function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?yt(n,!0).forEach(function(t){g()(e,t,n[t])}):c.a?s()(e,c()(n)):yt(n).forEach(function(t){i()(e,t,p()(n,t))})}return e}({},n.protoValue,{},e.value):e.value,m()(e.children).forEach(function(t){var n=e.children[t];e.children[t]=wt(n,n.value,e)}),e}var xt=function(){function e(t){var n=this;se()(this,e),ie()(this,{spec:"",debugLevel:"info",plugins:[],pluginHistory:{},errors:[],mutations:[],promisedPatches:[],state:{},patches:[],context:{},contextTree:new bt,showDebug:!1,allPatches:[],pluginProp:"specMap",libMethods:ie()(re()(this),_e,{getInstance:function(){return n}}),allowMetaPatches:!1},t),this.get=this._get.bind(this),this.getContext=this._getContext.bind(this),this.hasRun=this._hasRun.bind(this),this.wrappedPlugins=this.plugins.map(this.wrapPlugin.bind(this)).filter(_e.isFunction),this.patches.push(_e.add([],this.spec)),this.patches.push(_e.context([],this.context)),this.updatePatches(this.patches)}return ce()(e,[{key:"debug",value:function(e){if(this.debugLevel===e){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];(t=console).log.apply(t,r)}}},{key:"verbose",value:function(e){if("verbose"===this.debugLevel){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];(t=console).log.apply(t,["[".concat(e,"] ")].concat(r))}}},{key:"wrapPlugin",value:function(e,t){var n,r,o,i=this.pathDiscriminator,a=null;return e[this.pluginProp]?(a=e,n=e[this.pluginProp]):_e.isFunction(e)?n=e:_e.isObject(e)&&(r=e,o=function(e,t){return!M()(e)||e.every(function(e,n){return e===t[n]})},n=C.a.mark(function e(t,n){var a,s,u,c,l,p,f,h,d;return C.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:d=function(e,t,u){var c,l,p,f,h,v,g,y,b,_,w,x,E;return C.a.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if(_e.isObject(e)){a.next=6;break}if(r.key!==t[t.length-1]){a.next=4;break}return a.next=4,r.plugin(e,r.key,t,n);case 4:a.next=30;break;case 6:c=t.length-1,l=t[c],p=t.indexOf("properties"),f="properties"===l&&c===p,h=n.allowMetaPatches&&s[e.$$ref],v=0,g=m()(e);case 12:if(!(v<g.length)){a.next=30;break}if(y=g[v],b=e[y],_=t.concat(y),w=_e.isObject(b),x=e.$$ref,h){a.next=22;break}if(!w){a.next=22;break}return n.allowMetaPatches&&x&&(s[x]=!0),a.delegateYield(d(b,_,u),"t0",22);case 22:if(f||y!==r.key){a.next=27;break}if(E=o(i,t),i&&!E){a.next=27;break}return a.next=27,r.plugin(b,y,_,n,u);case 27:v++,a.next=12;break;case 30:case"end":return a.stop()}},a)},a=C.a.mark(d),s={},u=!0,c=!1,l=void 0,e.prev=6,p=te()(t.filter(_e.isAdditiveMutation));case 8:if(u=(f=p.next()).done){e.next=14;break}return h=f.value,e.delegateYield(d(h.value,h.path,h),"t0",11);case 11:u=!0,e.next=8;break;case 14:e.next=20;break;case 16:e.prev=16,e.t1=e.catch(6),c=!0,l=e.t1;case 20:e.prev=20,e.prev=21,u||null==p.return||p.return();case 23:if(e.prev=23,!c){e.next=26;break}throw l;case 26:return e.finish(23);case 27:return e.finish(20);case 28:case"end":return e.stop()}},e,null,[[6,16,20,28],[21,,23,27]])})),ie()(n.bind(a),{pluginName:e.name||t,isGenerator:_e.isGenerator(n)})}},{key:"nextPlugin",value:function(){var e=this;return pe()(this.wrappedPlugins,function(t){return e.getMutationsForPlugin(t).length>0})}},{key:"nextPromisedPatch",value:function(){if(this.promisedPatches.length>0)return Q.a.race(this.promisedPatches.map(function(e){return e.value}))}},{key:"getPluginHistory",value:function(e){var t=this.getPluginName(e);return this.pluginHistory[t]||[]}},{key:"getPluginRunCount",value:function(e){return this.getPluginHistory(e).length}},{key:"getPluginHistoryTip",value:function(e){var t=this.getPluginHistory(e);return t&&t[t.length-1]||{}}},{key:"getPluginMutationIndex",value:function(e){var t=this.getPluginHistoryTip(e).mutationIndex;return"number"!=typeof t?-1:t}},{key:"getPluginName",value:function(e){return e.pluginName}},{key:"updatePluginHistory",value:function(e,t){var n=this.getPluginName(e);(this.pluginHistory[n]=this.pluginHistory[n]||[]).push(t)}},{key:"updatePatches",value:function(e,t){var n=this;_e.normalizeArray(e).forEach(function(e){if(e instanceof Error)n.errors.push(e);else try{if(!_e.isObject(e))return void n.debug("updatePatches","Got a non-object patch",e);if(n.showDebug&&n.allPatches.push(e),_e.isPromise(e.value))return n.promisedPatches.push(e),void n.promisedPatchThen(e);if(_e.isContextPatch(e))return void n.setContext(e.path,e.value);if(_e.isMutation(e))return void n.updateMutations(e)}catch(e){console.error(e),n.errors.push(e)}})}},{key:"updateMutations",value:function(e){"object"===P()(e.value)&&!M()(e.value)&&this.allowMetaPatches&&(e.value=ie()({},e.value));var t=_e.applyPatch(this.state,e,{allowMetaPatches:this.allowMetaPatches});t&&(this.mutations.push(e),this.state=t)}},{key:"removePromisedPatch",value:function(e){var t=this.promisedPatches.indexOf(e);t<0?this.debug("Tried to remove a promisedPatch that isn't there!"):this.promisedPatches.splice(t,1)}},{key:"promisedPatchThen",value:function(e){var t=this;return e.value=e.value.then(function(n){var r=ie()({},e,{value:n});t.removePromisedPatch(e),t.updatePatches(r)}).catch(function(n){t.removePromisedPatch(e),t.updatePatches(n)})}},{key:"getMutations",value:function(e,t){return e=e||0,"number"!=typeof t&&(t=this.mutations.length),this.mutations.slice(e,t)}},{key:"getCurrentMutations",value:function(){return this.getMutationsForPlugin(this.getCurrentPlugin())}},{key:"getMutationsForPlugin",value:function(e){var t=this.getPluginMutationIndex(e);return this.getMutations(t+1)}},{key:"getCurrentPlugin",value:function(){return this.currentPlugin}},{key:"getPatchesOfType",value:function(e,t){return e.filter(t)}},{key:"getLib",value:function(){return this.libMethods}},{key:"_get",value:function(e){return _e.getIn(this.state,e)}},{key:"_getContext",value:function(e){return this.contextTree.get(e)}},{key:"setContext",value:function(e,t){return this.contextTree.set(e,t)}},{key:"_hasRun",value:function(e){return this.getPluginRunCount(this.getCurrentPlugin())>(e||0)}},{key:"_clone",value:function(e){return JSON.parse(T()(e))}},{key:"dispatch",value:function(){var e=this,t=this,n=this.nextPlugin();if(!n){var r=this.nextPromisedPatch();if(r)return r.then(function(){return e.dispatch()}).catch(function(){return e.dispatch()});var o={spec:this.state,errors:this.errors};return this.showDebug&&(o.patches=this.allPatches),Q.a.resolve(o)}if(t.pluginCount=t.pluginCount||{},t.pluginCount[n]=(t.pluginCount[n]||0)+1,t.pluginCount[n]>100)return Q.a.resolve({spec:t.state,errors:t.errors.concat(new Error("We've reached a hard limit of ".concat(100," plugin runs")))});if(n!==this.currentPlugin&&this.promisedPatches.length){var i=this.promisedPatches.map(function(e){return e.value});return Q.a.all(i.map(function(e){return e.then(Function,Function)})).then(function(){return e.dispatch()})}return function(){t.currentPlugin=n;var e=t.getCurrentMutations(),r=t.mutations.length-1;try{if(n.isGenerator){var o=!0,i=!1,s=void 0;try{for(var u,c=te()(n(e,t.getLib()));!(o=(u=c.next()).done);o=!0){var l=u.value;a(l)}}catch(e){i=!0,s=e}finally{try{o||null==c.return||c.return()}finally{if(i)throw s}}}else{var p=n(e,t.getLib());a(p)}}catch(e){console.error(e),a([ie()(re()(e),{plugin:n})])}finally{t.updatePluginHistory(n,{mutationIndex:r})}return t.dispatch()}();function a(e){e&&(e=_e.fullyNormalizeArray(e),t.updatePatches(e,n))}}}]),e}();var Et={refs:rt,allOf:mt,parameters:vt,properties:gt},St=n(29),Ct=n.n(St),kt=function(e){return String.prototype.toLowerCase.call(e)},Ot=function(e){return e.replace(/[^\w]/gi,"_")};function At(e){var t=e.openapi;return!!t&&w()(t,"3")}function Tt(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=(arguments.length>3&&void 0!==arguments[3]?arguments[3]:{}).v2OperationIdCompatibilityMode;return e&&"object"===P()(e)?(e.operationId||"").replace(/\s/g,"").length?Ot(e.operationId):function(e,t){if((arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).v2OperationIdCompatibilityMode){var n="".concat(t.toLowerCase(),"_").concat(e).replace(/[\s!@#$%^&*()_+=[{\]};:<>|.\/?,\\'""-]/g,"_");return(n=n||"".concat(e.substring(1),"_").concat(t)).replace(/((_){2,})/g,"_").replace(/^(_)*/g,"").replace(/([_])*$/g,"")}return"".concat(kt(t)).concat(Ot(e))}(t,n,{v2OperationIdCompatibilityMode:r}):null}function jt(e,t){return"".concat(kt(t),"-").concat(e)}function Pt(e,t){return e&&e.paths?function(e,t){return It(e,t,!0)||null}(e,function(e){var n=e.pathName,r=e.method,o=e.operation;if(!o||"object"!==P()(o))return!1;var i=o.operationId;return[Tt(o,n,r),jt(n,r),i].some(function(e){return e&&e===t})}):null}function It(e,t,n){if(!e||"object"!==P()(e)||!e.paths||"object"!==P()(e.paths))return null;var r=e.paths;for(var o in r)for(var i in r[o])if("PARAMETERS"!==i.toUpperCase()){var a=r[o][i];if(a&&"object"===P()(a)){var s={spec:e,pathName:o,method:i.toUpperCase(),operation:a},u=t(s);if(n&&u)return s}}}function Mt(e){var t=e.spec,n=t.paths,r={};if(!n||t.$$normalized)return e;for(var o in n){var i=n[o];if(Ct()(i)){var a=i.parameters,s=function(e){var n=i[e];if(!Ct()(n))return"continue";var s=Tt(n,o,e);if(s){r[s]?r[s].push(n):r[s]=[n];var u=r[s];if(u.length>1)u.forEach(function(e,t){e.__originalOperationId=e.__originalOperationId||e.operationId,e.operationId="".concat(s).concat(t+1)});else if(void 0!==n.operationId){var c=u[0];c.__originalOperationId=c.__originalOperationId||n.operationId,c.operationId=s}}if("parameters"!==e){var l=[],p={};for(var f in t)"produces"!==f&&"consumes"!==f&&"security"!==f||(p[f]=t[f],l.push(p));if(a&&(p.parameters=a,l.push(p)),l.length)for(var h=0,d=l;h<d.length;h++){var m=d[h];for(var v in m)if(n[v]){if("parameters"===v){var g=!0,y=!1,b=void 0;try{for(var _,w=function(){var e=_.value;n[v].some(function(t){return t.name&&t.name===e.name||t.$ref&&t.$ref===e.$ref||t.$$ref&&t.$$ref===e.$$ref||t===e})||n[v].push(e)},x=te()(m[v]);!(g=(_=x.next()).done);g=!0)w()}catch(e){y=!0,b=e}finally{try{g||null==x.return||x.return()}finally{if(y)throw b}}}}else n[v]=m[v]}}};for(var u in i)s(u)}}return t.$$normalized=!0,e}function Nt(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.requestInterceptor,r=t.responseInterceptor,o=e.withCredentials?"include":"same-origin";return function(t){return e({url:t,loadSpec:!0,requestInterceptor:n,responseInterceptor:r,headers:{Accept:"application/json"},credentials:o}).then(function(e){return e.body})}}function Rt(e){var t=e.fetch,n=e.spec,r=e.url,o=e.mode,i=e.allowMetaPatches,a=void 0===i||i,s=e.pathDiscriminator,u=e.modelPropertyMacro,c=e.parameterMacro,l=e.requestInterceptor,p=e.responseInterceptor,f=e.skipNormalization,h=e.useCircularStructures,d=e.http,m=e.baseDoc;return m=m||r,d=t||d||V,n?v(n):Nt(d,{requestInterceptor:l,responseInterceptor:p})(m).then(v);function v(e){m&&(Et.refs.docCache[m]=e),Et.refs.fetchJSON=Nt(d,{requestInterceptor:l,responseInterceptor:p});var t,n=[Et.refs];return"function"==typeof c&&n.push(Et.parameters),"function"==typeof u&&n.push(Et.properties),"strict"!==o&&n.push(Et.allOf),(t={spec:e,context:{baseDoc:m},plugins:n,allowMetaPatches:a,pathDiscriminator:s,parameterMacro:c,modelPropertyMacro:u,useCircularStructures:h},new xt(t).dispatch()).then(f?function(){var e=R()(C.a.mark(function e(t){return C.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",t);case 1:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}():Mt)}}var Dt=n(16),Lt=n.n(Dt);function Ut(e,t){var n=m()(e);if(h.a){var r=h()(e);t&&(r=r.filter(function(t){return p()(e,t).enumerable})),n.push.apply(n,r)}return n}function qt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Ut(n,!0).forEach(function(t){g()(e,t,n[t])}):c.a?s()(e,c()(n)):Ut(n).forEach(function(t){i()(e,t,p()(n,t))})}return e}function Ft(){return(Ft=R()(C.a.mark(function e(t,n){var r,o,i,a,s,u,c,l,p,f,h,d,m=arguments;return C.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return r=m.length>2&&void 0!==m[2]?m[2]:{},o=r.returnEntireTree,i=r.baseDoc,a=r.requestInterceptor,s=r.responseInterceptor,u=r.parameterMacro,c=r.modelPropertyMacro,l=r.useCircularStructures,p={pathDiscriminator:n,baseDoc:i,requestInterceptor:a,responseInterceptor:s,parameterMacro:u,modelPropertyMacro:c,useCircularStructures:l},f=Mt({spec:t}),h=f.spec,e.next=6,Rt(qt({},p,{spec:h,allowMetaPatches:!0,skipNormalization:!0}));case 6:return d=e.sent,!o&&M()(n)&&n.length&&(d.spec=Lt()(d.spec,n)||null),e.abrupt("return",d);case 9:case"end":return e.stop()}},e)}))).apply(this,arguments)}var zt=n(38),Bt=n.n(zt);function Vt(e,t){var n=m()(e);if(h.a){var r=h()(e);t&&(r=r.filter(function(t){return p()(e,t).enumerable})),n.push.apply(n,r)}return n}function Ht(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Vt(n,!0).forEach(function(t){g()(e,t,n[t])}):c.a?s()(e,c()(n)):Vt(n).forEach(function(t){i()(e,t,p()(n,t))})}return e}var Wt=function(){return null},Jt=function(e){return M()(e)?e:[e]},Yt={mapTagOperations:function(e){var t=e.spec,n=e.cb,r=void 0===n?Wt:n,o=e.defaultTag,i=void 0===o?"default":o,a=e.v2OperationIdCompatibilityMode,s={},u={};return It(t,function(e){var n=e.pathName,o=e.method,c=e.operation;(c.tags?Jt(c.tags):[i]).forEach(function(e){if("string"==typeof e){var i=u[e]=u[e]||{},l=Tt(c,n,o,{v2OperationIdCompatibilityMode:a}),p=r({spec:t,pathName:n,method:o,operation:c,operationId:l});if(s[l])s[l]++,i["".concat(l).concat(s[l])]=p;else if(void 0!==i[l]){var f=s[l]||1;s[l]=f+1,i["".concat(l).concat(s[l])]=p;var h=i[l];delete i[l],i["".concat(l).concat(f)]=h}else i[l]=p}})}),u},makeExecute:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function(t){var n=t.pathName,r=t.method,o=t.operationId;return function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.execute(Ht({spec:e.spec},Bt()(e,"requestInterceptor","responseInterceptor","userFetch"),{pathName:n,method:r,parameters:t,operationId:o},i))}}}};var Kt=n(39),Gt=n.n(Kt),$t=n(40),Zt=n.n($t),Xt=n(41),Qt=n.n(Xt),en=n(19),tn=n.n(en),nn=n(42),rn=n.n(nn),on={body:function(e){var t=e.req,n=e.value;t.body=n},header:function(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{},void 0!==r&&(t.headers[n.name]=r)},query:function(e){var t=e.req,n=e.value,r=e.parameter;t.query=t.query||{},!1===n&&"boolean"===r.type&&(n="false");0===n&&["number","integer"].indexOf(r.type)>-1&&(n="0");if(n)t.query[r.name]={collectionFormat:r.collectionFormat,value:n};else if(r.allowEmptyValue&&void 0!==n){var o=r.name;t.query[o]=t.query[o]||{},t.query[o].allowEmptyValue=!0}},path:function(e){var t=e.req,n=e.value,r=e.parameter;t.url=t.url.split("{".concat(r.name,"}")).join(encodeURIComponent(n))},formData:function(e){var t=e.req,n=e.value,r=e.parameter;(n||r.allowEmptyValue)&&(t.form=t.form||{},t.form[r.name]={value:n,allowEmptyValue:r.allowEmptyValue,collectionFormat:r.collectionFormat})}};n(49);var an=n(43),sn=n.n(an),un=n(44),cn=function(e){return":/?#[]@!$&'()*+,;=".indexOf(e)>-1},ln=function(e){return/^[a-z0-9\-._~]+$/i.test(e)};function pn(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).escape,n=arguments.length>2?arguments[2]:void 0;return"number"==typeof e&&(e=e.toString()),"string"==typeof e&&e.length&&t?n?JSON.parse(e):Object(un.stringToCharArray)(e).map(function(e){return ln(e)?e:cn(e)&&"unsafe"===t?e:(sn()(e)||[]).map(function(e){return"0".concat(e.toString(16).toUpperCase()).slice(-2)}).map(function(e){return"%".concat(e)}).join("")}).join(""):e}function fn(e){var t=e.value;return M()(t)?function(e){var t=e.key,n=e.value,r=e.style,o=e.explode,i=e.escape,a=function(e){return pn(e,{escape:i})};if("simple"===r)return n.map(function(e){return a(e)}).join(",");if("label"===r)return".".concat(n.map(function(e){return a(e)}).join("."));if("matrix"===r)return n.map(function(e){return a(e)}).reduce(function(e,n){return!e||o?"".concat(e||"",";").concat(t,"=").concat(n):"".concat(e,",").concat(n)},"");if("form"===r){var s=o?"&".concat(t,"="):",";return n.map(function(e){return a(e)}).join(s)}if("spaceDelimited"===r){var u=o?"".concat(t,"="):"";return n.map(function(e){return a(e)}).join(" ".concat(u))}if("pipeDelimited"===r){var c=o?"".concat(t,"="):"";return n.map(function(e){return a(e)}).join("|".concat(c))}}(e):"object"===P()(t)?function(e){var t=e.key,n=e.value,r=e.style,o=e.explode,i=e.escape,a=function(e){return pn(e,{escape:i})},s=m()(n);if("simple"===r)return s.reduce(function(e,t){var r=a(n[t]),i=o?"=":",",s=e?"".concat(e,","):"";return"".concat(s).concat(t).concat(i).concat(r)},"");if("label"===r)return s.reduce(function(e,t){var r=a(n[t]),i=o?"=":".",s=e?"".concat(e,"."):".";return"".concat(s).concat(t).concat(i).concat(r)},"");if("matrix"===r&&o)return s.reduce(function(e,t){var r=a(n[t]),o=e?"".concat(e,";"):";";return"".concat(o).concat(t,"=").concat(r)},"");if("matrix"===r)return s.reduce(function(e,r){var o=a(n[r]),i=e?"".concat(e,","):";".concat(t,"=");return"".concat(i).concat(r,",").concat(o)},"");if("form"===r)return s.reduce(function(e,t){var r=a(n[t]),i=e?"".concat(e).concat(o?"&":","):"",s=o?"=":",";return"".concat(i).concat(t).concat(s).concat(r)},"")}(e):function(e){var t=e.key,n=e.value,r=e.style,o=e.escape,i=function(e){return pn(e,{escape:o})};if("simple"===r)return i(n);if("label"===r)return".".concat(i(n));if("matrix"===r)return";".concat(t,"=").concat(i(n));if("form"===r)return i(n);if("deepObject"===r)return i(n)}(e)}function hn(e,t){return t.includes("application/json")?"string"==typeof e?e:T()(e):e.toString()}function dn(e){var t=e.req,n=e.value,r=e.parameter,o=r.name,i=r.style,a=r.explode,s=r.content;if(s){var u=m()(s)[0];t.url=t.url.split("{".concat(o,"}")).join(pn(hn(n,u),{escape:!0}))}else{var c=fn({key:r.name,value:n,style:i||"simple",explode:a||!1,escape:!0});t.url=t.url.split("{".concat(o,"}")).join(c)}}function mn(e){var t=e.req,n=e.value,r=e.parameter;if(t.query=t.query||{},r.content){var o=m()(r.content)[0];t.query[r.name]=hn(n,o)}else if(!1===n&&(n="false"),0===n&&(n="0"),n){var i=P()(n);if("deepObject"===r.style)m()(n).forEach(function(e){var o=n[e];t.query["".concat(r.name,"[").concat(e,"]")]={value:fn({key:e,value:o,style:"deepObject",escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0}});else if("object"!==i||M()(n)||"form"!==r.style&&r.style||!r.explode&&void 0!==r.explode)t.query[r.name]={value:fn({key:r.name,value:n,style:r.style||"form",explode:void 0===r.explode||r.explode,escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0};else{m()(n).forEach(function(e){var o=n[e];t.query[e]={value:fn({key:e,value:o,style:r.style||"form",escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0}})}}else if(r.allowEmptyValue&&void 0!==n){var a=r.name;t.query[a]=t.query[a]||{},t.query[a].allowEmptyValue=!0}}var vn=["accept","authorization","content-type"];function gn(e){var t=e.req,n=e.parameter,r=e.value;if(t.headers=t.headers||{},!(vn.indexOf(n.name.toLowerCase())>-1))if(n.content){var o=m()(n.content)[0];t.headers[n.name]=hn(r,o)}else void 0!==r&&(t.headers[n.name]=fn({key:n.name,value:r,style:n.style||"simple",explode:void 0!==n.explode&&n.explode,escape:!1}))}function yn(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{};var o=P()(r);if(n.content){var i=m()(n.content)[0];t.headers.Cookie="".concat(n.name,"=").concat(hn(r,i))}else if("undefined"!==o){var a="object"===o&&!M()(r)&&n.explode?"":"".concat(n.name,"=");t.headers.Cookie=a+fn({key:n.name,value:r,escape:!1,style:n.style||"form",explode:void 0!==n.explode&&n.explode})}}var bn=n(30),_n=function(e,t){var n=e.operation,r=e.requestBody,o=e.securities,i=e.spec,a=e.attachContentTypeForEmptyPayload,s=e.requestContentType;t=function(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,i=void 0===o?{}:o,a=e.spec,s=b()({},t),u=r.authorized,c=void 0===u?{}:u,l=i.security||a.security||[],p=c&&!!m()(c).length,f=Lt()(a,["components","securitySchemes"])||{};if(s.headers=s.headers||{},s.query=s.query||{},!m()(r).length||!p||!l||M()(i.security)&&!i.security.length)return t;return l.forEach(function(e,t){for(var n in e){var r=c[n],o=f[n];if(r){var i=r.value||r,a=o.type;if(r)if("apiKey"===a)"query"===o.in&&(s.query[o.name]=i),"header"===o.in&&(s.headers[o.name]=i),"cookie"===o.in&&(s.cookies[o.name]=i);else if("http"===a){if("basic"===o.scheme){var u=i.username,l=i.password,p=tn()("".concat(u,":").concat(l));s.headers.Authorization="Basic ".concat(p)}"bearer"===o.scheme&&(s.headers.Authorization="Bearer ".concat(i))}else if("oauth2"===a){var h=r.token||{},d=h.access_token,m=h.token_type;m&&"bearer"!==m.toLowerCase()||(m="Bearer"),s.headers.Authorization="".concat(m," ").concat(d)}}}}),s}({request:t,securities:o,operation:n,spec:i});var u=n.requestBody||{},c=m()(u.content||{}),l=s&&c.indexOf(s)>-1;if(r||a){if(s&&l)t.headers["Content-Type"]=s;else if(!s){var p=c[0];p&&(t.headers["Content-Type"]=p,s=p)}}else s&&l&&(t.headers["Content-Type"]=s);return r&&(s?c.indexOf(s)>-1&&("application/x-www-form-urlencoded"===s||0===s.indexOf("multipart/")?"object"===P()(r)?(t.form={},m()(r).forEach(function(e){var n,o,i=r[e];"undefined"!=typeof File&&(o=i instanceof File),"undefined"!=typeof Blob&&(o=o||i instanceof Blob),void 0!==bn.Buffer&&(o=o||bn.Buffer.isBuffer(i)),n="object"!==P()(i)||o?i:M()(i)?i.toString():T()(i),t.form[e]={value:n}})):t.form=r:t.body=r):t.body=r),t};var wn=function(e,t){var n=e.spec,r=e.operation,o=e.securities,i=e.requestContentType,a=e.attachContentTypeForEmptyPayload;if((t=function(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,i=void 0===o?{}:o,a=e.spec,s=b()({},t),u=r.authorized,c=void 0===u?{}:u,l=r.specSecurity,p=void 0===l?[]:l,f=i.security||p,h=c&&!!m()(c).length,d=a.securityDefinitions;if(s.headers=s.headers||{},s.query=s.query||{},!m()(r).length||!h||!f||M()(i.security)&&!i.security.length)return t;return f.forEach(function(e,t){for(var n in e){var r=c[n];if(r){var o=r.token,i=r.value||r,a=d[n],u=a.type,l=a["x-tokenName"]||"access_token",p=o&&o[l],f=o&&o.token_type;if(r)if("apiKey"===u){var h="query"===a.in?"query":"headers";s[h]=s[h]||{},s[h][a.name]=i}else"basic"===u?i.header?s.headers.authorization=i.header:(i.base64=tn()("".concat(i.username,":").concat(i.password)),s.headers.authorization="Basic ".concat(i.base64)):"oauth2"===u&&p&&(f=f&&"bearer"!==f.toLowerCase()?f:"Bearer",s.headers.authorization="".concat(f," ").concat(p))}}}),s}({request:t,securities:o,operation:r,spec:n})).body||t.form||a)i?t.headers["Content-Type"]=i:M()(r.consumes)?t.headers["Content-Type"]=r.consumes[0]:M()(n.consumes)?t.headers["Content-Type"]=n.consumes[0]:r.parameters&&r.parameters.filter(function(e){return"file"===e.type}).length?t.headers["Content-Type"]="multipart/form-data":r.parameters&&r.parameters.filter(function(e){return"formData"===e.in}).length&&(t.headers["Content-Type"]="application/x-www-form-urlencoded");else if(i){var s=r.parameters&&r.parameters.filter(function(e){return"body"===e.in}).length>0,u=r.parameters&&r.parameters.filter(function(e){return"formData"===e.in}).length>0;(s||u)&&(t.headers["Content-Type"]=i)}return t};function xn(e,t){var n=m()(e);if(h.a){var r=h()(e);t&&(r=r.filter(function(t){return p()(e,t).enumerable})),n.push.apply(n,r)}return n}function En(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?xn(n,!0).forEach(function(t){g()(e,t,n[t])}):c.a?s()(e,c()(n)):xn(n).forEach(function(t){i()(e,t,p()(n,t))})}return e}var Sn=function(e){return M()(e)?e:[]},Cn=ze("OperationNotFoundError",function(e,t,n){this.originalError=n,ie()(this,t||{})}),kn=function(e,t){return t.filter(function(t){return t.name===e})},On=function(e){var t={};e.forEach(function(e){t[e.in]||(t[e.in]={}),t[e.in][e.name]=e});var n=[];return m()(t).forEach(function(e){m()(t[e]).forEach(function(r){n.push(t[e][r])})}),n},An={buildRequest:Tn};function Tn(e){var t=e.spec,n=e.operationId,o=(e.securities,e.requestContentType,e.responseContentType),i=e.scheme,a=e.requestInterceptor,s=e.responseInterceptor,u=e.contextUrl,c=e.userFetch,l=(e.requestBody,e.server),p=e.serverVariables,f=e.http,h=e.parameters,d=e.parameterBuilders,v=At(t);d||(d=v?r:on);var g={url:"",credentials:f&&f.withCredentials?"include":"same-origin",headers:{},cookies:{}};a&&(g.requestInterceptor=a),s&&(g.responseInterceptor=s),c&&(g.userFetch=c);var y=Pt(t,n);if(!y)throw new Cn("Operation ".concat(n," not found"));var b,_=y.operation,w=void 0===_?{}:_,x=y.method,S=y.pathName;if(g.url+=At((b={spec:t,scheme:i,contextUrl:u,server:l,serverVariables:p,pathName:S,method:x}).spec)?function(e){var t=e.spec,n=e.pathName,r=e.method,o=e.server,i=e.contextUrl,a=e.serverVariables,s=void 0===a?{}:a,u=Lt()(t,["paths",n,(r||"").toLowerCase(),"servers"])||Lt()(t,["paths",n,"servers"])||Lt()(t,["servers"]),c="",l=null;if(o&&u&&u.length){var p=u.map(function(e){return e.url});p.indexOf(o)>-1&&(c=o,l=u[p.indexOf(o)])}if(!c&&u&&u.length&&(c=u[0].url,l=u[0]),c.indexOf("{")>-1){var f=function(e){for(var t,n=[],r=/{([^}]+)}/g;t=r.exec(e);)n.push(t[1]);return n}(c);f.forEach(function(e){if(l.variables&&l.variables[e]){var t=l.variables[e],n=s[e]||t.default,r=new RegExp("{".concat(e,"}"),"g");c=c.replace(r,n)}})}return function(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=E.a.parse(t),o=E.a.parse(n),i=jn(r.protocol)||jn(o.protocol)||"",a=r.host||o.host,s=r.pathname||"";return"/"===(e=i&&a?"".concat(i,"://").concat(a+s):s)[e.length-1]?e.slice(0,-1):e}(c,i)}(b):function(e){var t,n=e.spec,r=e.scheme,o=e.contextUrl,i=void 0===o?"":o,a=E.a.parse(i),s=M()(n.schemes)?n.schemes[0]:null,u=r||s||jn(a.protocol)||"http",c=n.host||a.host||"",l=n.basePath||"";return"/"===(t=u&&c?"".concat(u,"://").concat(c+l):l)[t.length-1]?t.slice(0,-1):t}(b),!n)return delete g.cookies,g;g.url+=S,g.method="".concat(x).toUpperCase(),h=h||{};var C=t.paths[S]||{};o&&(g.headers.accept=o);var k=On([].concat(Sn(w.parameters)).concat(Sn(C.parameters)));k.forEach(function(e){var n,r=d[e.in];if("body"===e.in&&e.schema&&e.schema.properties&&(n=h),void 0===(n=e&&e.name&&h[e.name])?n=e&&e.name&&h["".concat(e.in,".").concat(e.name)]:kn(e.name,k).length>1&&console.warn("Parameter '".concat(e.name,"' is ambiguous because the defined spec has more than one parameter with the name: '").concat(e.name,"' and the passed-in parameter values did not define an 'in' value.")),null!==n){if(void 0!==e.default&&void 0===n&&(n=e.default),void 0===n&&e.required&&!e.allowEmptyValue)throw new Error("Required parameter ".concat(e.name," is not provided"));if(v&&e.schema&&"object"===e.schema.type&&"string"==typeof n)try{n=JSON.parse(n)}catch(e){throw new Error("Could not parse object parameter value string as JSON")}r&&r({req:g,parameter:e,value:n,operation:w,spec:t})}});var O=En({},e,{operation:w});if((g=v?_n(O,g):wn(O,g)).cookies&&m()(g.cookies).length){var A=m()(g.cookies).reduce(function(e,t){var n=g.cookies[t];return e+(e?"&":"")+rn.a.serialize(t,n)},"");g.headers.Cookie=A}return g.cookies&&delete g.cookies,Z(g),g}var jn=function(e){return e?e.replace(/\W/g,""):null};function Pn(e,t){var n=m()(e);if(h.a){var r=h()(e);t&&(r=r.filter(function(t){return p()(e,t).enumerable})),n.push.apply(n,r)}return n}function In(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if("string"==typeof e?n.url=e:n=e,!(this instanceof In))return new In(n);b()(this,n);var r=this.resolve().then(function(){return t.disableInterfaces||b()(t,In.makeApisTagOperation(t)),t});return r.client=this,r}In.http=V,In.makeHttp=function(e,t,n){return n=n||function(e){return e},t=t||function(e){return e},function(r){return"string"==typeof r&&(r={url:r}),B.mergeInQueryOrForm(r),r=t(r),n(e(r))}}.bind(null,In.http),In.resolve=Rt,In.resolveSubtree=function(e,t){return Ft.apply(this,arguments)},In.execute=function(e){var t=e.http,n=e.fetch,r=e.spec,o=e.operationId,i=e.pathName,a=e.method,s=e.parameters,u=e.securities,c=Gt()(e,["http","fetch","spec","operationId","pathName","method","parameters","securities"]),l=t||n||V;i&&a&&!o&&(o=jt(i,a));var p=An.buildRequest(En({spec:r,operationId:o,parameters:s,securities:u,http:l},c));return p.body&&(Zt()(p.body)||Qt()(p.body))&&(p.body=T()(p.body)),l(p)},In.serializeRes=J,In.serializeHeaders=Y,In.clearCache=function(){Et.refs.clearCache()},In.makeApisTagOperation=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=Yt.makeExecute(e);return{apis:Yt.mapTagOperations({v2OperationIdCompatibilityMode:e.v2OperationIdCompatibilityMode,spec:e.spec,cb:t})}},In.buildRequest=Tn,In.helpers={opId:Tt},In.prototype={http:V,execute:function(e){return this.applyDefaults(),In.execute(function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Pn(n,!0).forEach(function(t){g()(e,t,n[t])}):c.a?s()(e,c()(n)):Pn(n).forEach(function(t){i()(e,t,p()(n,t))})}return e}({spec:this.spec,http:this.http,securities:{authorized:this.authorizations},contextUrl:"string"==typeof this.url?this.url:void 0},e))},resolve:function(){var e=this;return In.resolve({spec:this.spec,url:this.url,allowMetaPatches:this.allowMetaPatches,useCircularStructures:this.useCircularStructures,requestInterceptor:this.requestInterceptor||null,responseInterceptor:this.responseInterceptor||null}).then(function(t){return e.originalSpec=e.spec,e.spec=t.spec,e.errors=t.errors,e})}},In.prototype.applyDefaults=function(){var e=this.spec,t=this.url;if(t&&w()(t,"http")){var n=E.a.parse(t);e.host||(e.host=n.host),e.schemes||(e.schemes=[n.protocol.replace(":","")]),e.basePath||(e.basePath="/")}};t.default=In}]).default},function(e,t,n){"use strict";function r(e){return function(){return e}}var o=function(){};o.thatReturns=r,o.thatReturnsFalse=r(!1),o.thatReturnsTrue=r(!0),o.thatReturnsNull=r(null),o.thatReturnsThis=function(){return this},o.thatReturnsArgument=function(e){return e},e.exports=o},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(419),a=n(88),s=n(420),u=n(112),c=n(182),l=n(15),p=[],f=0,h=i.getPooled(),d=!1,m=null;function v(){x.ReactReconcileTransaction&&m||r("123")}var g=[{initialize:function(){this.dirtyComponentsLength=p.length},close:function(){this.dirtyComponentsLength!==p.length?(p.splice(0,this.dirtyComponentsLength),w()):p.length=0}},{initialize:function(){this.callbackQueue.reset()},close:function(){this.callbackQueue.notifyAll()}}];function y(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=i.getPooled(),this.reconcileTransaction=x.ReactReconcileTransaction.getPooled(!0)}function b(e,t){return e._mountOrder-t._mountOrder}function _(e){var t=e.dirtyComponentsLength;t!==p.length&&r("124",t,p.length),p.sort(b),f++;for(var n=0;n<t;n++){var o,i=p[n],a=i._pendingCallbacks;if(i._pendingCallbacks=null,s.logTopLevelRenders){var c=i;i._currentElement.type.isReactTopLevelWrapper&&(c=i._renderedComponent),o="React update: "+c.getName(),console.time(o)}if(u.performUpdateIfNecessary(i,e.reconcileTransaction,f),o&&console.timeEnd(o),a)for(var l=0;l<a.length;l++)e.callbackQueue.enqueue(a[l],i.getPublicInstance())}}o(y.prototype,c,{getTransactionWrappers:function(){return g},destructor:function(){this.dirtyComponentsLength=null,i.release(this.callbackQueue),this.callbackQueue=null,x.ReactReconcileTransaction.release(this.reconcileTransaction),this.reconcileTransaction=null},perform:function(e,t,n){return c.perform.call(this,this.reconcileTransaction.perform,this.reconcileTransaction,e,t,n)}}),a.addPoolingTo(y);var w=function(){for(;p.length||d;){if(p.length){var e=y.getPooled();e.perform(_,null,e),y.release(e)}if(d){d=!1;var t=h;h=i.getPooled(),t.notifyAll(),i.release(t)}}};var x={ReactReconcileTransaction:null,batchedUpdates:function(e,t,n,r,o,i){return v(),m.batchedUpdates(e,t,n,r,o,i)},enqueueUpdate:function e(t){v(),m.isBatchingUpdates?(p.push(t),null==t._updateBatchNumber&&(t._updateBatchNumber=f+1)):m.batchedUpdates(e,t)},flushBatchedUpdates:w,injection:{injectReconcileTransaction:function(e){e||r("126"),x.ReactReconcileTransaction=e},injectBatchingStrategy:function(e){e||r("127"),"function"!=typeof e.batchedUpdates&&r("128"),"boolean"!=typeof e.isBatchingUpdates&&r("129"),m=e}},asap:function(e,t){l(m.isBatchingUpdates,"ReactUpdates.asap: Can't enqueue an asap callback in a context whereupdates are not being batched."),h.enqueue(e,t),d=!0}};e.exports=x},function(e,t,n){var r;
+/*!
+ Copyright (c) 2017 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/
+/*!
+ Copyright (c) 2017 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/
+!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if("string"===i||"number"===i)e.push(r);else if(Array.isArray(r)&&r.length){var a=o.apply(null,r);a&&e.push(a)}else if("object"===i)for(var s in r)n.call(r,s)&&r[s]&&e.push(s)}}return e.join(" ")}e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,t,n){e.exports=n(750)},function(e,t,n){e.exports=n(753)},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_SELECTED_SERVER",function(){return r}),n.d(t,"UPDATE_REQUEST_BODY_VALUE",function(){return o}),n.d(t,"UPDATE_ACTIVE_EXAMPLES_MEMBER",function(){return i}),n.d(t,"UPDATE_REQUEST_CONTENT_TYPE",function(){return a}),n.d(t,"UPDATE_RESPONSE_CONTENT_TYPE",function(){return s}),n.d(t,"UPDATE_SERVER_VARIABLE_VALUE",function(){return u}),n.d(t,"setSelectedServer",function(){return c}),n.d(t,"setRequestBodyValue",function(){return l}),n.d(t,"setActiveExamplesMember",function(){return p}),n.d(t,"setRequestContentType",function(){return f}),n.d(t,"setResponseContentType",function(){return h}),n.d(t,"setServerVariableValue",function(){return d});var r="oas3_set_servers",o="oas3_set_request_body_value",i="oas3_set_active_examples_member",a="oas3_set_request_content_type",s="oas3_set_response_content_type",u="oas3_set_server_variable_value";function c(e,t){return{type:r,payload:{selectedServerUrl:e,namespace:t}}}function l(e){var t=e.value,n=e.pathMethod;return{type:o,payload:{value:t,pathMethod:n}}}function p(e){var t=e.name,n=e.pathMethod,r=e.contextType,o=e.contextName;return{type:i,payload:{name:t,pathMethod:n,contextType:r,contextName:o}}}function f(e){var t=e.value,n=e.pathMethod;return{type:a,payload:{value:t,pathMethod:n}}}function h(e){var t=e.value,n=e.path,r=e.method;return{type:s,payload:{value:t,path:n,method:r}}}function d(e){var t=e.server,n=e.namespace,r=e.key,o=e.val;return{type:u,payload:{server:t,namespace:n,key:r,val:o}}}},function(e,t,n){var r=n(129);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";(function(e){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * @license MIT
+ */
+var r=n(558),o=n(559),i=n(350);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()<t)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=u.prototype:(null===e&&(e=new u(t)),e.length=t),e}function u(e,t,n){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return p(this,e)}return c(this,e,t,n)}function c(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);u.TYPED_ARRAY_SUPPORT?(e=t).__proto__=u.prototype:e=f(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!u.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|d(t,n),o=(e=s(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(u.isBuffer(t)){var n=0|h(t.length);return 0===(e=s(e,n)).length?e:(t.copy(e,0,0,n),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?s(e,0):f(e,t);if("Buffer"===t.type&&i(t.data))return f(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function l(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function p(e,t){if(l(t),e=s(e,t<0?0:0|h(t)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function f(e,t){var n=t.length<0?0:0|h(t.length);e=s(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function h(e){if(e>=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return z(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return B(e).length;default:if(r)return z(e).length;t=(""+t).toLowerCase(),r=!0}}function m(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return j(this,t,n);case"utf8":case"utf-8":return k(this,t,n);case"ascii":return A(this,t,n);case"latin1":case"binary":return T(this,t,n);case"base64":return C(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return P(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function v(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function g(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:y(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):y(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function y(e,t,n,r,o){var i,a=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,u/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;i<s;i++)if(c(e,i)===c(t,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===u)return l*a}else-1!==l&&(i-=i-l),l=-1}else for(n+u>s&&(n=s-u),i=n;i>=0;i--){for(var p=!0,f=0;f<u;f++)if(c(e,i+f)!==c(t,f)){p=!1;break}if(p)return i}return-1}function b(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[n+a]=s}return a}function _(e,t,n,r){return V(z(t,e.length-n),e,n,r)}function w(e,t,n,r){return V(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function x(e,t,n,r){return w(e,t,n,r)}function E(e,t,n,r){return V(B(t),e,n,r)}function S(e,t,n,r){return V(function(e,t){for(var n,r,o,i=[],a=0;a<e.length&&!((t-=2)<0);++a)n=e.charCodeAt(a),r=n>>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function C(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function k(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o<n;){var i,a,s,u,c=e[o],l=null,p=c>239?4:c>223?3:c>191?2:1;if(o+p<=n)switch(p){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(u=(15&c)<<12|(63&i)<<6|63&a)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(u=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,p=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=p}return function(e){var t=e.length;if(t<=O)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=O));return n}(r)}t.Buffer=u,t.SlowBuffer=function(e){+e!=e&&(e=0);return u.alloc(+e)},t.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=a(),u.poolSize=8192,u._augment=function(e){return e.__proto__=u.prototype,e},u.from=function(e,t,n){return c(null,e,t,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(e,t,n){return function(e,t,n,r){return l(t),t<=0?s(e,t):void 0!==n?"string"==typeof r?s(e,t).fill(n,r):s(e,t).fill(n):s(e,t)}(null,e,t,n)},u.allocUnsafe=function(e){return p(null,e)},u.allocUnsafeSlow=function(e){return p(null,e)},u.isBuffer=function(e){return!(null==e||!e._isBuffer)},u.compare=function(e,t){if(!u.isBuffer(e)||!u.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o<i;++o)if(e[o]!==t[o]){n=e[o],r=t[o];break}return n<r?-1:r<n?1:0},u.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(e,t){if(!i(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return u.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=u.allocUnsafe(t),o=0;for(n=0;n<e.length;++n){var a=e[n];if(!u.isBuffer(a))throw new TypeError('"list" argument must be an Array of Buffers');a.copy(r,o),o+=a.length}return r},u.byteLength=d,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)v(this,t,t+1);return this},u.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)v(this,t,t+3),v(this,t+1,t+2);return this},u.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)v(this,t,t+7),v(this,t+1,t+6),v(this,t+2,t+5),v(this,t+3,t+4);return this},u.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?k(this,0,e):m.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),"<Buffer "+e+">"},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),l=e.slice(t,n),p=0;p<s;++p)if(c[p]!==l[p]){i=c[p],a=l[p];break}return i<a?-1:a<i?1:0},u.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},u.prototype.indexOf=function(e,t,n){return g(this,e,t,n,!0)},u.prototype.lastIndexOf=function(e,t,n){return g(this,e,t,n,!1)},u.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return _(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return x(this,e,t,n);case"base64":return E(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var O=4096;function A(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(127&e[o]);return r}function T(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;o<n;++o)r+=String.fromCharCode(e[o]);return r}function j(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=t;i<n;++i)o+=F(e[i]);return o}function P(e,t,n){for(var r=e.slice(t,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function I(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function M(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||t<i)throw new RangeError('"value" argument is out of bounds');if(n+r>e.length)throw new RangeError("Index out of range")}function N(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o<i;++o)e[n+o]=(t&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function R(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o<i;++o)e[n+o]=t>>>8*(r?o:3-o)&255}function D(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function L(e,t,n,r,i){return i||D(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||D(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),u.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=u.prototype;else{var o=t-e;n=new u(o,void 0);for(var i=0;i<o;++i)n[i]=this[i+e]}return n},u.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r},u.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e+--t],o=1;t>0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||I(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||I(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||I(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||I(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||I(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e],o=1,i=0;++i<t&&(o*=256);)r+=this[e+i]*o;return r>=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||I(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||I(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||I(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||I(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||I(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||I(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||I(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||I(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||I(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i<n&&(o*=256);)this[t+i]=e/o&255;return t+n},u.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var o=n-1,i=1;for(this[t+o]=255&e;--o>=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):R(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i<n&&(a*=256);)e<0&&0===s&&0!==this[t+i-1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):R(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return L(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return L(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var o,i=r-n;if(this===e&&n<t&&t<r)for(o=i-1;o>=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)e[o+t]=this[o+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+i),t);return i},u.prototype.fill=function(e,t,n,r){if("string"==typeof e){if("string"==typeof t?(r=t,t=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===e.length){var o=e.charCodeAt(0);o<256&&(e=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!u.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError("Out of range index");if(n<=t)return this;var i;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i<n;++i)this[i]=e;else{var a=u.isBuffer(e)?e:z(new u(e,r).toString()),s=a.length;for(i=0;i<n-t;++i)this[i+t]=a[i%s]}return this};var q=/[^+\/0-9A-Za-z-_]/g;function F(e){return e<16?"0"+e.toString(16):e.toString(16)}function z(e,t){var n;t=t||1/0;for(var r=e.length,o=null,i=[],a=0;a<r;++a){if((n=e.charCodeAt(a))>55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function B(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(q,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function V(e,t,n,r){for(var o=0;o<r&&!(o+n>=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(41))},function(e,t,n){"use strict";e.exports={current:null}},function(e,t){e.exports=function(e){return null!=e&&"object"==typeof e}},function(e,t,n){"use strict";var r=n(25),o=n(88),i=n(54),a=(n(23),["dispatchConfig","_targetInst","nativeEvent","isDefaultPrevented","isPropagationStopped","_dispatchListeners","_dispatchInstances"]),s={type:null,target:null,currentTarget:i.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null};function u(e,t,n,r){this.dispatchConfig=e,this._targetInst=t,this.nativeEvent=n;var o=this.constructor.Interface;for(var a in o)if(o.hasOwnProperty(a)){0;var s=o[a];s?this[a]=s(n):"target"===a?this.target=r:this[a]=n[a]}var u=null!=n.defaultPrevented?n.defaultPrevented:!1===n.returnValue;return this.isDefaultPrevented=u?i.thatReturnsTrue:i.thatReturnsFalse,this.isPropagationStopped=i.thatReturnsFalse,this}r(u.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=i.thatReturnsTrue)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=i.thatReturnsTrue)},persist:function(){this.isPersistent=i.thatReturnsTrue},isPersistent:i.thatReturnsFalse,destructor:function(){var e=this.constructor.Interface;for(var t in e)this[t]=null;for(var n=0;n<a.length;n++)this[a[n]]=null}}),u.Interface=s,u.augmentClass=function(e,t){var n=function(){};n.prototype=this.prototype;var i=new n;r(i,e.prototype),e.prototype=i,e.prototype.constructor=e,e.Interface=r({},this.Interface,t),e.augmentClass=this.augmentClass,o.addPoolingTo(e,o.fourArgumentPooler)},o.addPoolingTo(u,o.fourArgumentPooler),e.exports=u},function(e,t,n){var r=n(360);e.exports=function(e){return null==e?"":r(e)}},function(e,t,n){"use strict";n.r(t),n.d(t,"lastError",function(){return d}),n.d(t,"url",function(){return m}),n.d(t,"specStr",function(){return v}),n.d(t,"specSource",function(){return g}),n.d(t,"specJson",function(){return y}),n.d(t,"specResolved",function(){return b}),n.d(t,"specResolvedSubtree",function(){return _}),n.d(t,"specJsonWithResolvedSubtrees",function(){return x}),n.d(t,"spec",function(){return E}),n.d(t,"isOAS3",function(){return S}),n.d(t,"info",function(){return C}),n.d(t,"externalDocs",function(){return k}),n.d(t,"version",function(){return O}),n.d(t,"semver",function(){return A}),n.d(t,"paths",function(){return T}),n.d(t,"operations",function(){return j}),n.d(t,"consumes",function(){return P}),n.d(t,"produces",function(){return I}),n.d(t,"security",function(){return M}),n.d(t,"securityDefinitions",function(){return N}),n.d(t,"findDefinition",function(){return R}),n.d(t,"definitions",function(){return D}),n.d(t,"basePath",function(){return L}),n.d(t,"host",function(){return U}),n.d(t,"schemes",function(){return q}),n.d(t,"operationsWithRootInherited",function(){return F}),n.d(t,"tags",function(){return z}),n.d(t,"tagDetails",function(){return B}),n.d(t,"operationsWithTags",function(){return V}),n.d(t,"taggedOperations",function(){return H}),n.d(t,"responses",function(){return W}),n.d(t,"requests",function(){return J}),n.d(t,"mutatedRequests",function(){return Y}),n.d(t,"responseFor",function(){return K}),n.d(t,"requestFor",function(){return G}),n.d(t,"mutatedRequestFor",function(){return $}),n.d(t,"allowTryItOutFor",function(){return Z}),n.d(t,"parameterWithMetaByIdentity",function(){return X}),n.d(t,"parameterInclusionSettingFor",function(){return Q}),n.d(t,"parameterWithMeta",function(){return ee}),n.d(t,"operationWithMeta",function(){return te}),n.d(t,"getParameter",function(){return ne}),n.d(t,"hasHost",function(){return re}),n.d(t,"parameterValues",function(){return oe}),n.d(t,"parametersIncludeIn",function(){return ie}),n.d(t,"parametersIncludeType",function(){return ae}),n.d(t,"contentTypeValues",function(){return se}),n.d(t,"currentProducesFor",function(){return ue}),n.d(t,"producesOptionsFor",function(){return ce}),n.d(t,"consumesOptionsFor",function(){return le}),n.d(t,"operationScheme",function(){return pe}),n.d(t,"canExecuteScheme",function(){return fe}),n.d(t,"validateBeforeExecute",function(){return he});var r=n(14),o=n.n(r),i=n(13),a=n.n(i),s=n(12),u=n.n(s),c=n(11),l=n(3),p=n(1),f=["get","put","post","delete","options","head","patch","trace"],h=function(e){return e||Object(p.Map)()},d=Object(c.createSelector)(h,function(e){return e.get("lastError")}),m=Object(c.createSelector)(h,function(e){return e.get("url")}),v=Object(c.createSelector)(h,function(e){return e.get("spec")||""}),g=Object(c.createSelector)(h,function(e){return e.get("specSource")||"not-editor"}),y=Object(c.createSelector)(h,function(e){return e.get("json",Object(p.Map)())}),b=Object(c.createSelector)(h,function(e){return e.get("resolved",Object(p.Map)())}),_=function(e,t){return e.getIn(["resolvedSubtrees"].concat(u()(t)),void 0)},w=function e(t,n){return p.Map.isMap(t)&&p.Map.isMap(n)?n.get("$$ref")?n:Object(p.OrderedMap)().mergeWith(e,t,n):n},x=Object(c.createSelector)(h,function(e){return Object(p.OrderedMap)().mergeWith(w,e.get("json"),e.get("resolvedSubtrees"))}),E=function(e){return y(e)},S=Object(c.createSelector)(E,function(){return!1}),C=Object(c.createSelector)(E,function(e){return de(e&&e.get("info"))}),k=Object(c.createSelector)(E,function(e){return de(e&&e.get("externalDocs"))}),O=Object(c.createSelector)(C,function(e){return e&&e.get("version")}),A=Object(c.createSelector)(O,function(e){return/v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e).slice(1)}),T=Object(c.createSelector)(x,function(e){return e.get("paths")}),j=Object(c.createSelector)(T,function(e){if(!e||e.size<1)return Object(p.List)();var t=Object(p.List)();return e&&e.forEach?(e.forEach(function(e,n){if(!e||!e.forEach)return{};e.forEach(function(e,r){f.indexOf(r)<0||(t=t.push(Object(p.fromJS)({path:n,method:r,operation:e,id:"".concat(r,"-").concat(n)})))})}),t):Object(p.List)()}),P=Object(c.createSelector)(E,function(e){return Object(p.Set)(e.get("consumes"))}),I=Object(c.createSelector)(E,function(e){return Object(p.Set)(e.get("produces"))}),M=Object(c.createSelector)(E,function(e){return e.get("security",Object(p.List)())}),N=Object(c.createSelector)(E,function(e){return e.get("securityDefinitions")}),R=function(e,t){var n=e.getIn(["resolvedSubtrees","definitions",t],null),r=e.getIn(["json","definitions",t],null);return n||r||null},D=Object(c.createSelector)(E,function(e){var t=e.get("definitions");return p.Map.isMap(t)?t:Object(p.Map)()}),L=Object(c.createSelector)(E,function(e){return e.get("basePath")}),U=Object(c.createSelector)(E,function(e){return e.get("host")}),q=Object(c.createSelector)(E,function(e){return e.get("schemes",Object(p.Map)())}),F=Object(c.createSelector)(j,P,I,function(e,t,n){return e.map(function(e){return e.update("operation",function(e){if(e){if(!p.Map.isMap(e))return;return e.withMutations(function(e){return e.get("consumes")||e.update("consumes",function(e){return Object(p.Set)(e).merge(t)}),e.get("produces")||e.update("produces",function(e){return Object(p.Set)(e).merge(n)}),e})}return Object(p.Map)()})})}),z=Object(c.createSelector)(E,function(e){var t=e.get("tags",Object(p.List)());return p.List.isList(t)?t.filter(function(e){return p.Map.isMap(e)}):Object(p.List)()}),B=function(e,t){return(z(e)||Object(p.List)()).filter(p.Map.isMap).find(function(e){return e.get("name")===t},Object(p.Map)())},V=Object(c.createSelector)(F,z,function(e,t){return e.reduce(function(e,t){var n=Object(p.Set)(t.getIn(["operation","tags"]));return n.count()<1?e.update("default",Object(p.List)(),function(e){return e.push(t)}):n.reduce(function(e,n){return e.update(n,Object(p.List)(),function(e){return e.push(t)})},e)},t.reduce(function(e,t){return e.set(t.get("name"),Object(p.List)())},Object(p.OrderedMap)()))}),H=function(e){return function(t){var n=(0,t.getConfigs)(),r=n.tagsSorter,o=n.operationsSorter;return V(e).sortBy(function(e,t){return t},function(e,t){var n="function"==typeof r?r:l.F.tagsSorter[r];return n?n(e,t):null}).map(function(t,n){var r="function"==typeof o?o:l.F.operationsSorter[o],i=r?t.sort(r):t;return Object(p.Map)({tagDetails:B(e,n),operations:i})})}},W=Object(c.createSelector)(h,function(e){return e.get("responses",Object(p.Map)())}),J=Object(c.createSelector)(h,function(e){return e.get("requests",Object(p.Map)())}),Y=Object(c.createSelector)(h,function(e){return e.get("mutatedRequests",Object(p.Map)())}),K=function(e,t,n){return W(e).getIn([t,n],null)},G=function(e,t,n){return J(e).getIn([t,n],null)},$=function(e,t,n){return Y(e).getIn([t,n],null)},Z=function(){return!0},X=function(e,t,n){var r=x(e).getIn(["paths"].concat(u()(t),["parameters"]),Object(p.OrderedMap)()),o=e.getIn(["meta","paths"].concat(u()(t),["parameters"]),Object(p.OrderedMap)());return r.map(function(e){var t=o.get("".concat(n.get("in"),".").concat(n.get("name"))),r=o.get("".concat(n.get("in"),".").concat(n.get("name"),".hash-").concat(n.hashCode()));return Object(p.OrderedMap)().merge(e,t,r)}).find(function(e){return e.get("in")===n.get("in")&&e.get("name")===n.get("name")},Object(p.OrderedMap)())},Q=function(e,t,n,r){var o="".concat(r,".").concat(n);return e.getIn(["meta","paths"].concat(u()(t),["parameter_inclusions",o]),!1)},ee=function(e,t,n,r){var o=x(e).getIn(["paths"].concat(u()(t),["parameters"]),Object(p.OrderedMap)()).find(function(e){return e.get("in")===r&&e.get("name")===n},Object(p.OrderedMap)());return X(e,t,o)},te=function(e,t,n){var r=x(e).getIn(["paths",t,n],Object(p.OrderedMap)()),o=e.getIn(["meta","paths",t,n],Object(p.OrderedMap)()),i=r.get("parameters",Object(p.List)()).map(function(r){return X(e,[t,n],r)});return Object(p.OrderedMap)().merge(r,o).set("parameters",i)};function ne(e,t,n,r){return t=t||[],e.getIn(["meta","paths"].concat(u()(t),["parameters"]),Object(p.fromJS)([])).find(function(e){return p.Map.isMap(e)&&e.get("name")===n&&e.get("in")===r})||Object(p.Map)()}var re=Object(c.createSelector)(E,function(e){var t=e.get("host");return"string"==typeof t&&t.length>0&&"/"!==t[0]});function oe(e,t,n){return t=t||[],te.apply(void 0,[e].concat(u()(t))).get("parameters",Object(p.List)()).reduce(function(e,t){var r=n&&"body"===t.get("in")?t.get("value_xml"):t.get("value");return e.set(Object(l.z)(t,{allowHashes:!1}),r)},Object(p.fromJS)({}))}function ie(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(p.List.isList(e))return e.some(function(e){return p.Map.isMap(e)&&e.get("in")===t})}function ae(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(p.List.isList(e))return e.some(function(e){return p.Map.isMap(e)&&e.get("type")===t})}function se(e,t){t=t||[];var n=x(e).getIn(["paths"].concat(u()(t)),Object(p.fromJS)({})),r=e.getIn(["meta","paths"].concat(u()(t)),Object(p.fromJS)({})),o=ue(e,t),i=n.get("parameters")||new p.List,a=r.get("consumes_value")?r.get("consumes_value"):ae(i,"file")?"multipart/form-data":ae(i,"formData")?"application/x-www-form-urlencoded":void 0;return Object(p.fromJS)({requestContentType:a,responseContentType:o})}function ue(e,t){t=t||[];var n=x(e).getIn(["paths"].concat(u()(t)),null);if(null!==n){var r=e.getIn(["meta","paths"].concat(u()(t),["produces_value"]),null),o=n.getIn(["produces",0],null);return r||o||"application/json"}}function ce(e,t){t=t||[];var n=x(e),r=n.getIn(["paths"].concat(u()(t)),null);if(null!==r){var o=t,i=a()(o,1)[0],s=r.get("produces",null),c=n.getIn(["paths",i,"produces"],null),l=n.getIn(["produces"],null);return s||c||l}}function le(e,t){t=t||[];var n=x(e),r=n.getIn(["paths"].concat(u()(t)),null);if(null!==r){var o=t,i=a()(o,1)[0],s=r.get("consumes",null),c=n.getIn(["paths",i,"consumes"],null),l=n.getIn(["consumes"],null);return s||c||l}}var pe=function(e,t,n){var r=e.get("url").match(/^([a-z][a-z0-9+\-.]*):/),i=o()(r)?r[1]:null;return e.getIn(["scheme",t,n])||e.getIn(["scheme","_defaultScheme"])||i||""},fe=function(e,t,n){return["http","https"].indexOf(pe(e,t,n))>-1},he=function(e,t){t=t||[];var n=e.getIn(["meta","paths"].concat(u()(t),["parameters"]),Object(p.fromJS)([])),r=!0;return n.forEach(function(e){var t=e.get("errors");t&&t.count()&&(r=!1)}),r};function de(e){return p.Map.isMap(e)?e:new p.Map}},function(e,t,n){"use strict";n.r(t),n.d(t,"SHOW_AUTH_POPUP",function(){return d}),n.d(t,"AUTHORIZE",function(){return m}),n.d(t,"LOGOUT",function(){return v}),n.d(t,"PRE_AUTHORIZE_OAUTH2",function(){return g}),n.d(t,"AUTHORIZE_OAUTH2",function(){return y}),n.d(t,"VALIDATE",function(){return b}),n.d(t,"CONFIGURE_AUTH",function(){return _}),n.d(t,"showDefinitions",function(){return w}),n.d(t,"authorize",function(){return x}),n.d(t,"logout",function(){return E}),n.d(t,"preAuthorizeImplicit",function(){return S}),n.d(t,"authorizeOauth2",function(){return C}),n.d(t,"authorizePassword",function(){return k}),n.d(t,"authorizeApplication",function(){return O}),n.d(t,"authorizeAccessCodeWithFormParams",function(){return A}),n.d(t,"authorizeAccessCodeWithBasicAuthentication",function(){return T}),n.d(t,"authorizeRequest",function(){return j}),n.d(t,"configureAuth",function(){return P});var r=n(26),o=n.n(r),i=n(16),a=n.n(i),s=n(28),u=n.n(s),c=n(93),l=n.n(c),p=n(18),f=n.n(p),h=n(3),d="show_popup",m="authorize",v="logout",g="pre_authorize_oauth2",y="authorize_oauth2",b="validate",_="configure_auth";function w(e){return{type:d,payload:e}}function x(e){return{type:m,payload:e}}function E(e){return{type:v,payload:e}}var S=function(e){return function(t){var n=t.authActions,r=t.errActions,o=e.auth,i=e.token,a=e.isValid,s=o.schema,c=o.name,l=s.get("flow");delete f.a.swaggerUIRedirectOauth2,"accessCode"===l||a||r.newAuthErr({authId:c,source:"auth",level:"warning",message:"Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"}),i.error?r.newAuthErr({authId:c,source:"auth",level:"error",message:u()(i)}):n.authorizeOauth2({auth:o,token:i})}};function C(e){return{type:y,payload:e}}var k=function(e){return function(t){var n=t.authActions,r=e.schema,o=e.name,i=e.username,s=e.password,u=e.passwordType,c=e.clientId,l=e.clientSecret,p={grant_type:"password",scope:e.scopes.join(" "),username:i,password:s},f={};switch(u){case"request-body":!function(e,t,n){t&&a()(e,{client_id:t});n&&a()(e,{client_secret:n})}(p,c,l);break;case"basic":f.Authorization="Basic "+Object(h.a)(c+":"+l);break;default:console.warn("Warning: invalid passwordType ".concat(u," was passed, not including client id and secret"))}return n.authorizeRequest({body:Object(h.b)(p),url:r.get("tokenUrl"),name:o,headers:f,query:{},auth:e})}};var O=function(e){return function(t){var n=t.authActions,r=e.schema,o=e.scopes,i=e.name,a=e.clientId,s=e.clientSecret,u={Authorization:"Basic "+Object(h.a)(a+":"+s)},c={grant_type:"client_credentials",scope:o.join(" ")};return n.authorizeRequest({body:Object(h.b)(c),name:i,url:r.get("tokenUrl"),auth:e,headers:u})}},A=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,i=t.name,a=t.clientId,s=t.clientSecret,u={grant_type:"authorization_code",code:t.code,client_id:a,client_secret:s,redirect_uri:n};return r.authorizeRequest({body:Object(h.b)(u),name:i,url:o.get("tokenUrl"),auth:t})}},T=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,i=t.name,a=t.clientId,s=t.clientSecret,u={Authorization:"Basic "+Object(h.a)(a+":"+s)},c={grant_type:"authorization_code",code:t.code,client_id:a,redirect_uri:n};return r.authorizeRequest({body:Object(h.b)(c),name:i,url:o.get("tokenUrl"),auth:t,headers:u})}},j=function(e){return function(t){var n,r=t.fn,i=t.getConfigs,s=t.authActions,c=t.errActions,p=t.oas3Selectors,f=t.specSelectors,h=t.authSelectors,d=e.body,m=e.query,v=void 0===m?{}:m,g=e.headers,y=void 0===g?{}:g,b=e.name,_=e.url,w=e.auth,x=(h.getConfigs()||{}).additionalQueryStringParams;n=f.isOAS3()?l()(_,p.selectedServer(),!0):l()(_,f.url(),!0),"object"===o()(x)&&(n.query=a()({},n.query,x));var E=n.toString(),S=a()({Accept:"application/json, text/plain, */*","Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"},y);r.fetch({url:E,method:"post",headers:S,query:v,body:d,requestInterceptor:i().requestInterceptor,responseInterceptor:i().responseInterceptor}).then(function(e){var t=JSON.parse(e.data),n=t&&(t.error||""),r=t&&(t.parseError||"");e.ok?n||r?c.newAuthErr({authId:b,level:"error",source:"auth",message:u()(t)}):s.authorizeOauth2({auth:w,token:t}):c.newAuthErr({authId:b,level:"error",source:"auth",message:e.statusText})}).catch(function(e){var t=new Error(e).message;if(e.response&&e.response.data){var n=e.response.data;try{var r="string"==typeof n?JSON.parse(n):n;r.error&&(t+=", error: ".concat(r.error)),r.error_description&&(t+=", description: ".concat(r.error_description))}catch(e){}}c.newAuthErr({authId:b,level:"error",source:"auth",message:t})})}};function P(e){return{type:_,payload:e}}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(203),o=n(202);e.exports=function(e){return r(o(e))}},function(e,t,n){var r=n(47),o=n(130);e.exports=n(45)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,c=[],l=!1,p=-1;function f(){l&&u&&(l=!1,u.length?c=u.concat(c):p=-1,c.length&&h())}function h(){if(!l){var e=s(f);l=!0;for(var t=c.length;t;){for(u=c,c=[];++p<t;)u&&u[p].run();p=-1,t=c.length}u=null,l=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===a||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function d(e,t){this.fun=e,this.array=t}function m(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new d(e,t)),1!==c.length||l||s(h)},d.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=m,o.addListener=m,o.once=m,o.off=m,o.removeListener=m,o.removeAllListeners=m,o.emit=m,o.prependListener=m,o.prependOnceListener=m,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(e,t,n){"use strict";e.exports=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e}},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_LAYOUT",function(){return o}),n.d(t,"UPDATE_FILTER",function(){return i}),n.d(t,"UPDATE_MODE",function(){return a}),n.d(t,"SHOW",function(){return s}),n.d(t,"updateLayout",function(){return u}),n.d(t,"updateFilter",function(){return c}),n.d(t,"show",function(){return l}),n.d(t,"changeMode",function(){return p});var r=n(3),o="layout_update_layout",i="layout_update_filter",a="layout_update_mode",s="layout_show";function u(e){return{type:o,payload:e}}function c(e){return{type:i,payload:e}}function l(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return e=Object(r.u)(e),{type:s,payload:{thing:e,shown:t}}}function p(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=Object(r.u)(e),{type:a,payload:{thing:e,mode:t}}}},function(e,t,n){"use strict";(function(t){
+/*!
+ * @description Recursive object extending
+ * @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
+ * @license MIT
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2018 Viacheslav Lotsmanov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+function n(e){return e instanceof t||e instanceof Date||e instanceof RegExp}function r(e){if(e instanceof t){var n=t.alloc?t.alloc(e.length):new t(e.length);return e.copy(n),n}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return new RegExp(e);throw new Error("Unexpected situation")}function o(e){var t=[];return e.forEach(function(e,i){"object"==typeof e&&null!==e?Array.isArray(e)?t[i]=o(e):n(e)?t[i]=r(e):t[i]=a({},e):t[i]=e}),t}function i(e,t){return"__proto__"===t?void 0:e[t]}var a=e.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var e,t,s=arguments[0],u=Array.prototype.slice.call(arguments,1);return u.forEach(function(u){"object"!=typeof u||null===u||Array.isArray(u)||Object.keys(u).forEach(function(c){return t=i(s,c),(e=i(u,c))===s?void 0:"object"!=typeof e||null===e?void(s[c]=e):Array.isArray(e)?void(s[c]=o(e)):n(e)?void(s[c]=r(e)):"object"!=typeof t||null===t||Array.isArray(t)?void(s[c]=a({},e)):void(s[c]=a(t,e))})}),s}}).call(this,n(61).Buffer)},function(e,t,n){var r=n(147),o=n(329);e.exports=n(122)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(96);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t){var n=e.exports={version:"2.5.5"};"number"==typeof __e&&(__e=n)},function(e,t,n){var r=n(202);e.exports=function(e){return Object(r(e))}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var r=n(102),o=n(592),i=n(593),a="[object Null]",s="[object Undefined]",u=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?s:a:u&&u in Object(e)?o(e):i(e)}},function(e,t,n){var r=n(610),o=n(613);e.exports=function(e,t){var n=o(e,t);return r(n)?n:void 0}},function(e,t,n){var r=n(375),o=n(650),i=n(103);e.exports=function(e){return i(e)?r(e):o(e)}},function(e,t,n){"use strict";var r=n(174),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=p;var i=n(134);i.inherits=n(106);var a=n(385),s=n(232);i.inherits(p,a);for(var u=o(s.prototype),c=0;c<u.length;c++){var l=u[c];p.prototype[l]||(p.prototype[l]=s.prototype[l])}function p(e){if(!(this instanceof p))return new p(e);a.call(this,e),s.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",f)}function f(){this.allowHalfOpen||this._writableState.ended||r.nextTick(h,this)}function h(e){e.end()}Object.defineProperty(p.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(p.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),p.prototype._destroy=function(e,t){this.push(null),this.end(),r.nextTick(t,e)}},function(e,t,n){"use strict";var r=n(392)();e.exports=function(e){return e!==r&&null!==e}},function(e,t,n){"use strict";var r=n(685),o=Math.max;e.exports=function(e){return o(0,r(e))}},function(e,t,n){},function(e,t,n){"use strict";var r=n(21),o=(n(15),function(e){if(this.instancePool.length){var t=this.instancePool.pop();return this.call(t,e),t}return new this(e)}),i=function(e){e instanceof this||r("25"),e.destructor(),this.instancePool.length<this.poolSize&&this.instancePool.push(e)},a=o,s={addPoolingTo:function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||a,n.poolSize||(n.poolSize=10),n.release=i,n},oneArgumentPooler:o,twoArgumentPooler:function(e,t){if(this.instancePool.length){var n=this.instancePool.pop();return this.call(n,e,t),n}return new this(e,t)},threeArgumentPooler:function(e,t,n){if(this.instancePool.length){var r=this.instancePool.pop();return this.call(r,e,t,n),r}return new this(e,t,n)},fourArgumentPooler:function(e,t,n,r){if(this.instancePool.length){var o=this.instancePool.pop();return this.call(o,e,t,n,r),o}return new this(e,t,n,r)}};e.exports=s},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){e.exports=n(588)},function(e,t,n){var r=n(173);e.exports=function(e,t,n){var o=null==e?void 0:r(e,t);return void 0===o?n:o}},function(e,t,n){e.exports=n(748)},function(e,t,n){"use strict";(function(t){var r=n(788),o=n(789),i=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,a=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,s=new RegExp("^[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]+");function u(e){return(e||"").toString().replace(s,"")}var c=[["#","hash"],["?","query"],function(e){return e.replace("\\","/")},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],l={hash:1,query:1};function p(e){var n,r=("undefined"!=typeof window?window:void 0!==t?t:"undefined"!=typeof self?self:{}).location||{},o={},a=typeof(e=e||r);if("blob:"===e.protocol)o=new h(unescape(e.pathname),{});else if("string"===a)for(n in o=new h(e,{}),l)delete o[n];else if("object"===a){for(n in e)n in l||(o[n]=e[n]);void 0===o.slashes&&(o.slashes=i.test(e.href))}return o}function f(e){e=u(e);var t=a.exec(e);return{protocol:t[1]?t[1].toLowerCase():"",slashes:!!t[2],rest:t[3]}}function h(e,t,n){if(e=u(e),!(this instanceof h))return new h(e,t,n);var i,a,s,l,d,m,v=c.slice(),g=typeof t,y=this,b=0;for("object"!==g&&"string"!==g&&(n=t,t=null),n&&"function"!=typeof n&&(n=o.parse),t=p(t),i=!(a=f(e||"")).protocol&&!a.slashes,y.slashes=a.slashes||i&&t.slashes,y.protocol=a.protocol||t.protocol||"",e=a.rest,a.slashes||(v[3]=[/(.*)/,"pathname"]);b<v.length;b++)"function"!=typeof(l=v[b])?(s=l[0],m=l[1],s!=s?y[m]=e:"string"==typeof s?~(d=e.indexOf(s))&&("number"==typeof l[2]?(y[m]=e.slice(0,d),e=e.slice(d+l[2])):(y[m]=e.slice(d),e=e.slice(0,d))):(d=s.exec(e))&&(y[m]=d[1],e=e.slice(0,d.index)),y[m]=y[m]||i&&l[3]&&t[m]||"",l[4]&&(y[m]=y[m].toLowerCase())):e=l(e);n&&(y.query=n(y.query)),i&&t.slashes&&"/"!==y.pathname.charAt(0)&&(""!==y.pathname||""!==t.pathname)&&(y.pathname=function(e,t){if(""===e)return t;for(var n=(t||"/").split("/").slice(0,-1).concat(e.split("/")),r=n.length,o=n[r-1],i=!1,a=0;r--;)"."===n[r]?n.splice(r,1):".."===n[r]?(n.splice(r,1),a++):a&&(0===r&&(i=!0),n.splice(r,1),a--);return i&&n.unshift(""),"."!==o&&".."!==o||n.push(""),n.join("/")}(y.pathname,t.pathname)),r(y.port,y.protocol)||(y.host=y.hostname,y.port=""),y.username=y.password="",y.auth&&(l=y.auth.split(":"),y.username=l[0]||"",y.password=l[1]||""),y.origin=y.protocol&&y.host&&"file:"!==y.protocol?y.protocol+"//"+y.host:"null",y.href=y.toString()}h.prototype={set:function(e,t,n){var i=this;switch(e){case"query":"string"==typeof t&&t.length&&(t=(n||o.parse)(t)),i[e]=t;break;case"port":i[e]=t,r(t,i.protocol)?t&&(i.host=i.hostname+":"+t):(i.host=i.hostname,i[e]="");break;case"hostname":i[e]=t,i.port&&(t+=":"+i.port),i.host=t;break;case"host":i[e]=t,/:\d+$/.test(t)?(t=t.split(":"),i.port=t.pop(),i.hostname=t.join(":")):(i.hostname=t,i.port="");break;case"protocol":i.protocol=t.toLowerCase(),i.slashes=!n;break;case"pathname":case"hash":if(t){var a="pathname"===e?"/":"#";i[e]=t.charAt(0)!==a?a+t:t}else i[e]=t;break;default:i[e]=t}for(var s=0;s<c.length;s++){var u=c[s];u[4]&&(i[u[1]]=i[u[1]].toLowerCase())}return i.origin=i.protocol&&i.host&&"file:"!==i.protocol?i.protocol+"//"+i.host:"null",i.href=i.toString(),i},toString:function(e){e&&"function"==typeof e||(e=o.stringify);var t,n=this,r=n.protocol;r&&":"!==r.charAt(r.length-1)&&(r+=":");var i=r+(n.slashes?"//":"");return n.username&&(i+=n.username,n.password&&(i+=":"+n.password),i+="@"),i+=n.host+n.pathname,(t="object"==typeof n.query?e(n.query):n.query)&&(i+="?"!==t.charAt(0)?"?"+t:t),n.hash&&(i+=n.hash),i}},h.extractProtocol=f,h.location=p,h.trimLeft=u,h.qs=o,e.exports=h}).call(this,n(41))},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return a});var r=n(470),o=n.n(r),i=[n(267),n(268)];function a(e,t){var n={jsSpec:t.specSelectors.specJson().toJS()};return o()(i,function(e,t){try{return t.transform(e,n).filter(function(e){return!!e})}catch(t){return console.error("Transformer error:",t),e}},e).filter(function(e){return!!e}).map(function(e){return!e.get("line")&&e.get("path"),e})}},function(e,t,n){var r=n(43),o=n(76),i=n(148),a=n(195)("src"),s=Function.toString,u=(""+s).split("toString");n(78).inspectSource=function(e){return s.call(e)},(e.exports=function(e,t,n,s){var c="function"==typeof n;c&&(i(n,"name")||o(n,"name",t)),e[t]!==n&&(c&&(i(n,a)||o(n,a,e[t]?""+e[t]:u.join(String(t)))),e===r?e[t]=n:s?e[t]?e[t]=n:o(e,t,n):(delete e[t],o(e,t,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[a]||s.call(this)})},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){"use strict";var r=n(548)(!0);n(211)(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t){e.exports={}},function(e,t,n){n(550);for(var r=n(32),o=n(71),i=n(98),a=n(34)("toStringTag"),s="CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,TextTrackList,TouchList".split(","),u=0;u<s.length;u++){var c=s[u],l=r[c],p=l&&l.prototype;p&&!p[a]&&o(p,a,c),i[c]=i.Array}},function(e,t,n){"use strict";var r=n(25),o=n(352),i=n(567),a=n(572),s=n(101),u=n(573),c=n(577),l=n(578),p=n(580),f=s.createElement,h=s.createFactory,d=s.cloneElement,m=r,v={Children:{map:i.map,forEach:i.forEach,count:i.count,toArray:i.toArray,only:p},Component:o.Component,PureComponent:o.PureComponent,createElement:f,cloneElement:d,isValidElement:s.isValidElement,PropTypes:u,createClass:l,createFactory:h,createMixin:function(e){return e},DOM:a,version:c,__spread:m};e.exports=v},function(e,t,n){"use strict";var r=n(25),o=n(62),i=(n(23),n(354),Object.prototype.hasOwnProperty),a=n(355),s={key:!0,ref:!0,__self:!0,__source:!0};function u(e){return void 0!==e.ref}function c(e){return void 0!==e.key}var l=function(e,t,n,r,o,i,s){return{$$typeof:a,type:e,key:t,ref:n,props:s,_owner:i}};l.createElement=function(e,t,n){var r,a={},p=null,f=null;if(null!=t)for(r in u(t)&&(f=t.ref),c(t)&&(p=""+t.key),void 0===t.__self?null:t.__self,void 0===t.__source?null:t.__source,t)i.call(t,r)&&!s.hasOwnProperty(r)&&(a[r]=t[r]);var h=arguments.length-2;if(1===h)a.children=n;else if(h>1){for(var d=Array(h),m=0;m<h;m++)d[m]=arguments[m+2];0,a.children=d}if(e&&e.defaultProps){var v=e.defaultProps;for(r in v)void 0===a[r]&&(a[r]=v[r])}return l(e,p,f,0,0,o.current,a)},l.createFactory=function(e){var t=l.createElement.bind(null,e);return t.type=e,t},l.cloneAndReplaceKey=function(e,t){return l(e.type,t,e.ref,e._self,e._source,e._owner,e.props)},l.cloneElement=function(e,t,n){var a,p,f=r({},e.props),h=e.key,d=e.ref,m=(e._self,e._source,e._owner);if(null!=t)for(a in u(t)&&(d=t.ref,m=o.current),c(t)&&(h=""+t.key),e.type&&e.type.defaultProps&&(p=e.type.defaultProps),t)i.call(t,a)&&!s.hasOwnProperty(a)&&(void 0===t[a]&&void 0!==p?f[a]=p[a]:f[a]=t[a]);var v=arguments.length-2;if(1===v)f.children=n;else if(v>1){for(var g=Array(v),y=0;y<v;y++)g[y]=arguments[y+2];f.children=g}return l(e.type,h,d,0,0,m,f)},l.isValidElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===a},e.exports=l},function(e,t,n){var r=n(48).Symbol;e.exports=r},function(e,t,n){var r=n(366),o=n(225);e.exports=function(e){return null!=e&&o(e.length)&&!r(e)}},function(e,t,n){var r=n(35),o=n(228),i=n(658),a=n(65);e.exports=function(e,t){return r(e)?e:o(e,t)?[e]:i(a(e))}},function(e,t,n){var r=n(163),o=1/0;e.exports=function(e){if("string"==typeof e||r(e))return e;var t=e+"";return"0"==t&&1/e==-o?"-0":t}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}},function(e,t,n){"use strict";var r=n(85);e.exports=function(e){if(!r(e))throw new TypeError("Cannot use null or undefined");return e}},function(e,t,n){var r=n(60),o=n(399),i=n(400),a=n(44),s=n(154),u=n(217),c={},l={};(t=e.exports=function(e,t,n,p,f){var h,d,m,v,g=f?function(){return e}:u(e),y=r(n,p,t?2:1),b=0;if("function"!=typeof g)throw TypeError(e+" is not iterable!");if(i(g)){for(h=s(e.length);h>b;b++)if((v=t?y(a(d=e[b])[0],d[1]):y(e[b]))===c||v===l)return v}else for(m=g.call(e);!(d=m.next()).done;)if((v=o(m,y,d.value,t))===c||v===l)return v}).BREAK=c,t.RETURN=l},function(e,t,n){"use strict";function r(e){return null==e}e.exports.isNothing=r,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:r(e)?[]:[e]},e.exports.repeat=function(e,t){var n,r="";for(n=0;n<t;n+=1)r+=e;return r},e.exports.isNegativeZero=function(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e},e.exports.extend=function(e,t){var n,r,o,i;if(t)for(n=0,r=(i=Object.keys(t)).length;n<r;n+=1)e[o=i[n]]=t[o];return e}},function(e,t,n){"use strict";var r=n(109),o=n(135),i=n(31);function a(e,t,n){var r=[];return e.include.forEach(function(e){n=a(e,t,n)}),e[t].forEach(function(e){n.forEach(function(t,n){t.tag===e.tag&&t.kind===e.kind&&r.push(n)}),n.push(e)}),n.filter(function(e,t){return-1===r.indexOf(t)})}function s(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")}),this.compiledImplicit=a(this,"implicit",[]),this.compiledExplicit=a(this,"explicit",[]),this.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{}};function r(e){n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e<t;e+=1)arguments[e].forEach(r);return n}(this.compiledImplicit,this.compiledExplicit)}s.DEFAULT=null,s.create=function(){var e,t;switch(arguments.length){case 1:e=s.DEFAULT,t=arguments[0];break;case 2:e=arguments[0],t=arguments[1];break;default:throw new o("Wrong number of arguments for Schema.create function")}if(e=r.toArray(e),t=r.toArray(t),!e.every(function(e){return e instanceof s}))throw new o("Specified list of super schemas (or a single Schema object) contains a non-Schema object.");if(!t.every(function(e){return e instanceof i}))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.");return new s({include:e,explicit:t})},e.exports=s},function(e,t,n){"use strict";var r=n(21);n(15);function o(e,t){return(e&t)===t}var i={MUST_USE_PROPERTY:1,HAS_BOOLEAN_VALUE:4,HAS_NUMERIC_VALUE:8,HAS_POSITIVE_NUMERIC_VALUE:24,HAS_OVERLOADED_BOOLEAN_VALUE:32,injectDOMPropertyConfig:function(e){var t=i,n=e.Properties||{},a=e.DOMAttributeNamespaces||{},u=e.DOMAttributeNames||{},c=e.DOMPropertyNames||{},l=e.DOMMutationMethods||{};for(var p in e.isCustomAttribute&&s._isCustomAttributeFunctions.push(e.isCustomAttribute),n){s.properties.hasOwnProperty(p)&&r("48",p);var f=p.toLowerCase(),h=n[p],d={attributeName:f,attributeNamespace:null,propertyName:p,mutationMethod:null,mustUseProperty:o(h,t.MUST_USE_PROPERTY),hasBooleanValue:o(h,t.HAS_BOOLEAN_VALUE),hasNumericValue:o(h,t.HAS_NUMERIC_VALUE),hasPositiveNumericValue:o(h,t.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:o(h,t.HAS_OVERLOADED_BOOLEAN_VALUE)};if(d.hasBooleanValue+d.hasNumericValue+d.hasOverloadedBooleanValue<=1||r("50",p),u.hasOwnProperty(p)){var m=u[p];d.attributeName=m}a.hasOwnProperty(p)&&(d.attributeNamespace=a[p]),c.hasOwnProperty(p)&&(d.propertyName=c[p]),l.hasOwnProperty(p)&&(d.mutationMethod=l[p]),s.properties[p]=d}}},a=":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",s={ID_ATTRIBUTE_NAME:"data-reactid",ROOT_ATTRIBUTE_NAME:"data-reactroot",ATTRIBUTE_NAME_START_CHAR:a,ATTRIBUTE_NAME_CHAR:a+"\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<s._isCustomAttributeFunctions.length;t++){if((0,s._isCustomAttributeFunctions[t])(e))return!0}return!1},injection:i};e.exports=s},function(e,t,n){"use strict";var r=n(808);n(50),n(23);function o(){r.attachRefs(this,this._currentElement)}var i={mountComponent:function(e,t,n,r,i,a){var s=e.mountComponent(t,n,r,i,a);return e._currentElement&&null!=e._currentElement.ref&&t.getReactMountReady().enqueue(o,e),s},getHostNode:function(e){return e.getHostNode()},unmountComponent:function(e,t){r.detachRefs(e,e._currentElement),e.unmountComponent(t)},receiveComponent:function(e,t,n,i){var a=e._currentElement;if(t!==a||i!==e._context){0;var s=r.shouldUpdateRefs(a,t);s&&r.detachRefs(e,a),e.receiveComponent(t,n,i),s&&e._currentElement&&null!=e._currentElement.ref&&n.getReactMountReady().enqueue(o,e)}},performUpdateIfNecessary:function(e,t,n){e._updateBatchNumber===n&&e.performUpdateIfNecessary(t)}};e.exports=i},function(e,t,n){"use strict";var r=n(246),o=n(184),i=n(247),a=n(424),s="undefined"!=typeof document&&"number"==typeof document.documentMode||"undefined"!=typeof navigator&&"string"==typeof navigator.userAgent&&/\bEdge\/\d/.test(navigator.userAgent);function u(e){if(s){var t=e.node,n=e.children;if(n.length)for(var r=0;r<n.length;r++)c(t,n[r],null);else null!=e.html?o(t,e.html):null!=e.text&&a(t,e.text)}}var c=i(function(e,t,n){11===t.node.nodeType||1===t.node.nodeType&&"object"===t.node.nodeName.toLowerCase()&&(null==t.node.namespaceURI||t.node.namespaceURI===r.html)?(u(t),e.insertBefore(t.node,n)):(e.insertBefore(t.node,n),u(t))});function l(){return this.node.nodeName}function p(e){return{node:e,children:[],html:null,text:null,toString:l}}p.insertTreeBefore=c,p.replaceChildWithTree=function(e,t){e.parentNode.replaceChild(t.node,e),u(t)},p.queueChild=function(e,t){s?e.children.push(t):e.node.appendChild(t.node)},p.queueHTML=function(e,t){s?e.html=t:o(e.node,t)},p.queueText=function(e,t){s?e.text=t:a(e.node,t)},e.exports=p},function(e,t,n){var r=n(181),o=n(411);e.exports=function(e,t,n,i){var a=!n;n||(n={});for(var s=-1,u=t.length;++s<u;){var c=t[s],l=i?i(n[c],e[c],c,n,e):void 0;void 0===l&&(l=e[c]),a?o(n,c,l):r(n,c,l)}return n}},function(e,t,n){"use strict";e.exports=function(e){return"object"==typeof e?function e(t,n){var r;r=Array.isArray(t)?[]:{};n.push(t);Object.keys(t).forEach(function(o){var i=t[o];"function"!=typeof i&&(i&&"object"==typeof i?-1!==n.indexOf(t[o])?r[o]="[Circular]":r[o]=e(t[o],n.slice(0)):r[o]=i)});"string"==typeof t.name&&(r.name=t.name);"string"==typeof t.message&&(r.message=t.message);"string"==typeof t.stack&&(r.stack=t.stack);return r}(e,[]):"function"==typeof e?"[Function: "+(e.name||"anonymous")+"]":e}},function(e,t,n){"use strict";n.r(t),n.d(t,"sampleFromSchema",function(){return d}),n.d(t,"inferSchema",function(){return m}),n.d(t,"sampleXmlFromSchema",function(){return v}),n.d(t,"createXMLExample",function(){return g}),n.d(t,"memoizedCreateXMLExample",function(){return y}),n.d(t,"memoizedSampleFromSchema",function(){return b});var r=n(14),o=n.n(r),i=n(3),a=n(468),s=n.n(a),u=n(323),c=n.n(u),l=n(142),p=n.n(l),f={string:function(){return"string"},string_email:function(){return"user@example.com"},"string_date-time":function(){return(new Date).toISOString()},string_date:function(){return(new Date).toISOString().substring(0,10)},string_uuid:function(){return"3fa85f64-5717-4562-b3fc-2c963f66afa6"},string_hostname:function(){return"example.com"},string_ipv4:function(){return"198.51.100.42"},string_ipv6:function(){return"2001:0db8:5b96:0000:0000:426f:8e17:642a"},number:function(){return 0},number_float:function(){return 0},integer:function(){return 0},boolean:function(e){return"boolean"!=typeof e.default||e.default}},h=function(e){var t=e=Object(i.y)(e),n=t.type,r=t.format,o=f["".concat(n,"_").concat(r)]||f[n];return Object(i.q)(o)?o(e):"Unknown Type: "+e.type},d=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=Object(i.y)(t),a=r.type,s=r.example,u=r.properties,c=r.additionalProperties,l=r.items,p=n.includeReadOnly,f=n.includeWriteOnly;if(void 0!==s)return Object(i.d)(s,"$$ref",function(e){return"string"==typeof e&&e.indexOf("#")>-1});if(!a)if(u)a="object";else{if(!l)return;a="array"}if("object"===a){var d=Object(i.y)(u),m={};for(var v in d)d[v]&&d[v].deprecated||d[v]&&d[v].readOnly&&!p||d[v]&&d[v].writeOnly&&!f||(m[v]=e(d[v],n));if(!0===c)m.additionalProp1={};else if(c)for(var g=Object(i.y)(c),y=e(g,n),b=1;b<4;b++)m["additionalProp"+b]=y;return m}return"array"===a?o()(l.anyOf)?l.anyOf.map(function(t){return e(t,n)}):o()(l.oneOf)?l.oneOf.map(function(t){return e(t,n)}):[e(l,n)]:t.enum?t.default?t.default:Object(i.u)(t.enum)[0]:"file"!==a?h(t):void 0},m=function(e){return e.schema&&(e=e.schema),e.properties&&(e.type="object"),e},v=function e(t){var n,r,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=p()({},Object(i.y)(t)),u=s.type,c=s.properties,l=s.additionalProperties,f=s.items,d=s.example,m=a.includeReadOnly,v=a.includeWriteOnly,g=s.default,y={},b={},_=t.xml,w=_.name,x=_.prefix,E=_.namespace,S=s.enum;if(!u)if(c||l)u="object";else{if(!f)return;u="array"}if(n=(x?x+":":"")+(w=w||"notagname"),E){var C=x?"xmlns:"+x:"xmlns";b[C]=E}if("array"===u&&f){if(f.xml=f.xml||_||{},f.xml.name=f.xml.name||_.name,_.wrapped)return y[n]=[],o()(d)?d.forEach(function(t){f.example=t,y[n].push(e(f,a))}):o()(g)?g.forEach(function(t){f.default=t,y[n].push(e(f,a))}):y[n]=[e(f,a)],b&&y[n].push({_attr:b}),y;var k=[];return o()(d)?(d.forEach(function(t){f.example=t,k.push(e(f,a))}),k):o()(g)?(g.forEach(function(t){f.default=t,k.push(e(f,a))}),k):e(f,a)}if("object"===u){var O=Object(i.y)(c);for(var A in y[n]=[],d=d||{},O)if(O.hasOwnProperty(A)&&(!O[A].readOnly||m)&&(!O[A].writeOnly||v))if(O[A].xml=O[A].xml||{},O[A].xml.attribute){var T=o()(O[A].enum)&&O[A].enum[0],j=O[A].example,P=O[A].default;b[O[A].xml.name||A]=void 0!==j&&j||void 0!==d[A]&&d[A]||void 0!==P&&P||T||h(O[A])}else{O[A].xml.name=O[A].xml.name||A,void 0===O[A].example&&void 0!==d[A]&&(O[A].example=d[A]);var I=e(O[A]);o()(I)?y[n]=y[n].concat(I):y[n].push(I)}return!0===l?y[n].push({additionalProp:"Anything can be here"}):l&&y[n].push({additionalProp:h(l)}),b&&y[n].push({_attr:b}),y}return r=void 0!==d?d:void 0!==g?g:o()(S)?S[0]:h(t),y[n]=b?[{_attr:b},r]:r,y};function g(e,t){var n=v(e,t);if(n)return s()(n,{declaration:!0,indent:"\t"})}var y=c()(g),b=c()(d)},function(e,t,n){"use strict";n.r(t),n.d(t,"UPDATE_CONFIGS",function(){return i}),n.d(t,"TOGGLE_CONFIGS",function(){return a}),n.d(t,"update",function(){return s}),n.d(t,"toggle",function(){return u}),n.d(t,"loaded",function(){return c});var r=n(2),o=n.n(r),i="configs_update",a="configs_toggle";function s(e,t){return{type:i,payload:o()({},e,t)}}function u(e){return{type:a,payload:e}}var c=function(){return function(){}}},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(1),o=n.n(r),i=o.a.Set.of("type","format","items","default","maximum","exclusiveMaximum","minimum","exclusiveMinimum","maxLength","minLength","pattern","maxItems","minItems","uniqueItems","enum","multipleOf");function a(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).isOAS3;if(!o.a.Map.isMap(e))return o.a.Map();if(!t)return"body"===e.get("in")?e.get("schema",o.a.Map()):e.filter(function(e,t){return i.includes(t)});if(e.get("content")){var n=e.get("content",o.a.Map({})).keySeq();return e.getIn(["content",n.first(),"schema"],o.a.Map())}return e.get("schema",o.a.Map())}},function(e,t,n){e.exports=n(766)},function(e,t,n){"use strict";n.r(t);var r=n(463),o="object"==typeof self&&self&&self.Object===Object&&self,i=(r.a||o||Function("return this")()).Symbol,a=Object.prototype,s=a.hasOwnProperty,u=a.toString,c=i?i.toStringTag:void 0;var l=function(e){var t=s.call(e,c),n=e[c];try{e[c]=void 0;var r=!0}catch(e){}var o=u.call(e);return r&&(t?e[c]=n:delete e[c]),o},p=Object.prototype.toString;var f=function(e){return p.call(e)},h="[object Null]",d="[object Undefined]",m=i?i.toStringTag:void 0;var v=function(e){return null==e?void 0===e?d:h:m&&m in Object(e)?l(e):f(e)};var g=function(e,t){return function(n){return e(t(n))}}(Object.getPrototypeOf,Object);var y=function(e){return null!=e&&"object"==typeof e},b="[object Object]",_=Function.prototype,w=Object.prototype,x=_.toString,E=w.hasOwnProperty,S=x.call(Object);var C=function(e){if(!y(e)||v(e)!=b)return!1;var t=g(e);if(null===t)return!0;var n=E.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&x.call(n)==S},k=n(322),O={INIT:"@@redux/INIT"};function A(e,t,n){var r;if("function"==typeof t&&void 0===n&&(n=t,t=void 0),void 0!==n){if("function"!=typeof n)throw new Error("Expected the enhancer to be a function.");return n(A)(e,t)}if("function"!=typeof e)throw new Error("Expected the reducer to be a function.");var o=e,i=t,a=[],s=a,u=!1;function c(){s===a&&(s=a.slice())}function l(){return i}function p(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var t=!0;return c(),s.push(e),function(){if(t){t=!1,c();var n=s.indexOf(e);s.splice(n,1)}}}function f(e){if(!C(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(u)throw new Error("Reducers may not dispatch actions.");try{u=!0,i=o(i,e)}finally{u=!1}for(var t=a=s,n=0;n<t.length;n++){(0,t[n])()}return e}return f({type:O.INIT}),(r={dispatch:f,subscribe:p,getState:l,replaceReducer:function(e){if("function"!=typeof e)throw new Error("Expected the nextReducer to be a function.");o=e,f({type:O.INIT})}})[k.a]=function(){var e,t=p;return(e={subscribe:function(e){if("object"!=typeof e)throw new TypeError("Expected the observer to be an object.");function n(){e.next&&e.next(l())}return n(),{unsubscribe:t(n)}}})[k.a]=function(){return this},e},r}function T(e,t){var n=t&&t.type;return"Given action "+(n&&'"'+n.toString()+'"'||"an action")+', reducer "'+e+'" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.'}function j(e){for(var t=Object.keys(e),n={},r=0;r<t.length;r++){var o=t[r];0,"function"==typeof e[o]&&(n[o]=e[o])}var i=Object.keys(n);var a=void 0;try{!function(e){Object.keys(e).forEach(function(t){var n=e[t];if(void 0===n(void 0,{type:O.INIT}))throw new Error('Reducer "'+t+"\" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don't want to set a value for this reducer, you can use null instead of undefined.");if(void 0===n(void 0,{type:"@@redux/PROBE_UNKNOWN_ACTION_"+Math.random().toString(36).substring(7).split("").join(".")}))throw new Error('Reducer "'+t+"\" returned undefined when probed with a random type. Don't try to handle "+O.INIT+' or other actions in "redux/*" namespace. They are considered private. Instead, you must return the current state for any unknown actions, unless it is undefined, in which case you must return the initial state, regardless of the action type. The initial state may not be undefined, but can be null.')})}(n)}catch(e){a=e}return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1];if(a)throw a;for(var r=!1,o={},s=0;s<i.length;s++){var u=i[s],c=n[u],l=e[u],p=c(l,t);if(void 0===p){var f=T(u,t);throw new Error(f)}o[u]=p,r=r||p!==l}return r?o:e}}function P(e,t){return function(){return t(e.apply(void 0,arguments))}}function I(e,t){if("function"==typeof e)return P(e,t);if("object"!=typeof e||null===e)throw new Error("bindActionCreators expected an object or a function, instead received "+(null===e?"null":typeof e)+'. Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');for(var n=Object.keys(e),r={},o=0;o<n.length;o++){var i=n[o],a=e[i];"function"==typeof a&&(r[i]=P(a,t))}return r}function M(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return 0===t.length?function(e){return e}:1===t.length?t[0]:t.reduce(function(e,t){return function(){return e(t.apply(void 0,arguments))}})}var N=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e};function R(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return function(e){return function(n,r,o){var i,a=e(n,r,o),s=a.dispatch,u={getState:a.getState,dispatch:function(e){return s(e)}};return i=t.map(function(e){return e(u)}),s=M.apply(void 0,i)(a.dispatch),N({},a,{dispatch:s})}}}n.d(t,"createStore",function(){return A}),n.d(t,"combineReducers",function(){return j}),n.d(t,"bindActionCreators",function(){return I}),n.d(t,"applyMiddleware",function(){return R}),n.d(t,"compose",function(){return M})},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t,n){e.exports=!n(123)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t){e.exports={}},function(e,t,n){var r=n(149),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(343),o=n(207);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t){e.exports=!0},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){var r=n(47).f,o=n(69),i=n(34)("toStringTag");e.exports=function(e,t,n){e&&!o(e=n?e:e.prototype,i)&&r(e,i,{configurable:!0,value:t})}},function(e,t,n){var r=n(155)("meta"),o=n(40),i=n(69),a=n(47).f,s=0,u=Object.isExtensible||function(){return!0},c=!n(80)(function(){return u(Object.preventExtensions({}))}),l=function(e){a(e,r,{value:{i:"O"+ ++s,w:{}}})},p=e.exports={KEY:r,NEED:!1,fastKey:function(e,t){if(!o(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!i(e,r)){if(!u(e))return"F";if(!t)return"E";l(e)}return e[r].i},getWeak:function(e,t){if(!i(e,r)){if(!u(e))return!0;if(!t)return!1;l(e)}return e[r].w},onFreeze:function(e){return c&&p.NEED&&u(e)&&!i(e,r)&&l(e),e}}},function(e,t,n){"use strict";e.exports=function(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,r=0;r<t;r++)n+="&args[]="+encodeURIComponent(arguments[r+1]);n+=" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";var o=new Error(n);throw o.name="Invariant Violation",o.framesToPop=1,o}},function(e,t,n){(function(e){function n(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===n(e)},t.isBoolean=function(e){return"boolean"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return"[object RegExp]"===n(e)},t.isObject=function(e){return"object"==typeof e&&null!==e},t.isDate=function(e){return"[object Date]"===n(e)},t.isError=function(e){return"[object Error]"===n(e)||e instanceof Error},t.isFunction=function(e){return"function"==typeof e},t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,n(61).Buffer)},function(e,t,n){"use strict";function r(e,t){Error.call(this),this.name="YAMLException",this.reason=e,this.mark=t,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||""}r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t},e.exports=r},function(e,t,n){"use strict";var r=n(110);e.exports=new r({include:[n(408)],implicit:[n(777),n(778)],explicit:[n(779),n(780),n(781),n(782)]})},function(e,t,n){"use strict";var r=n(138),o=n(240),i=n(416),a=n(417),s=(n(23),r.getListener);function u(e,t,n){var r=function(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return s(e,r)}(e,n,t);r&&(n._dispatchListeners=i(n._dispatchListeners,r),n._dispatchInstances=i(n._dispatchInstances,e))}function c(e){e&&e.dispatchConfig.phasedRegistrationNames&&o.traverseTwoPhase(e._targetInst,u,e)}function l(e){if(e&&e.dispatchConfig.phasedRegistrationNames){var t=e._targetInst,n=t?o.getParentInstance(t):null;o.traverseTwoPhase(n,u,e)}}function p(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=s(e,r);o&&(n._dispatchListeners=i(n._dispatchListeners,o),n._dispatchInstances=i(n._dispatchInstances,e))}}function f(e){e&&e.dispatchConfig.registrationName&&p(e._targetInst,0,e)}var h={accumulateTwoPhaseDispatches:function(e){a(e,c)},accumulateTwoPhaseDispatchesSkipTarget:function(e){a(e,l)},accumulateDirectDispatches:function(e){a(e,f)},accumulateEnterLeaveDispatches:function(e,t,n,r){o.traverseEnterLeave(n,r,p,e,t)}};e.exports=h},function(e,t,n){"use strict";var r=n(21),o=n(239),i=n(240),a=n(241),s=n(416),u=n(417),c=(n(15),{}),l=null,p=function(e,t){e&&(i.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e))},f=function(e){return p(e,!0)},h=function(e){return p(e,!1)},d=function(e){return"."+e._rootNodeID};var m={injection:{injectEventPluginOrder:o.injectEventPluginOrder,injectEventPluginsByName:o.injectEventPluginsByName},putListener:function(e,t,n){"function"!=typeof n&&r("94",t,typeof n);var i=d(e);(c[t]||(c[t]={}))[i]=n;var a=o.registrationNameModules[t];a&&a.didPutListener&&a.didPutListener(e,t,n)},getListener:function(e,t){var n=c[t];if(function(e,t,n){switch(e){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":return!(!n.disabled||(r=t,"button"!==r&&"input"!==r&&"select"!==r&&"textarea"!==r));default:return!1}var r}(t,e._currentElement.type,e._currentElement.props))return null;var r=d(e);return n&&n[r]},deleteListener:function(e,t){var n=o.registrationNameModules[t];n&&n.willDeleteListener&&n.willDeleteListener(e,t);var r=c[t];r&&delete r[d(e)]},deleteAllListeners:function(e){var t=d(e);for(var n in c)if(c.hasOwnProperty(n)&&c[n][t]){var r=o.registrationNameModules[n];r&&r.willDeleteListener&&r.willDeleteListener(e,n),delete c[n][t]}},extractEvents:function(e,t,n,r){for(var i,a=o.plugins,u=0;u<a.length;u++){var c=a[u];if(c){var l=c.extractEvents(e,t,n,r);l&&(i=s(i,l))}}return i},enqueueEvents:function(e){e&&(l=s(l,e))},processEventQueue:function(e){var t=l;l=null,u(t,e?f:h),l&&r("95"),a.rethrowCaughtError()},__purge:function(){c={}},__getListenerBank:function(){return c}};e.exports=m},function(e,t,n){"use strict";var r=n(64),o=n(242),i={view:function(e){if(e.view)return e.view;var t=o(e);if(t.window===t)return t;var n=t.ownerDocument;return n?n.defaultView||n.parentWindow:window},detail:function(e){return e.detail||0}};function a(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(a,i),e.exports=a},function(e,t,n){"use strict";var r={remove:function(e){e._reactInternalInstance=void 0},get:function(e){return e._reactInternalInstance},has:function(e){return void 0!==e._reactInternalInstance},set:function(e,t){e._reactInternalInstance=t}};e.exports=r},function(e,t,n){var r=n(40);e.exports=function(e,t){if(!r(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e}},function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function o(e){return null===e?"null":void 0===e?"undefined":"object"===(void 0===e?"undefined":r(e))?Array.isArray(e)?"array":"object":void 0===e?"undefined":r(e)}function i(e){return"object"===o(e)?s(e):"array"===o(e)?a(e):e}function a(e){return e.map(i)}function s(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[n]=i(e[n]));return t}function u(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n={arrayBehaviour:(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).arrayBehaviour||"replace"},r=t.map(function(e){return e||{}}),i=e||{},c=0;c<r.length;c++)for(var l=r[c],p=Object.keys(l),f=0;f<p.length;f++){var h=p[f],d=l[h],m=o(d),v=o(i[h]);if("object"===m)if("undefined"!==v){var g="object"===v?i[h]:{};i[h]=u({},[g,s(d)],n)}else i[h]=s(d);else if("array"===m)if("array"===v){var y=a(d);i[h]="merge"===n.arrayBehaviour?i[h].concat(y):y}else i[h]=a(d);else i[h]=d}return i}e.exports=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return u(e,n)},e.exports.noMutate=function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return u({},t)},e.exports.withOptions=function(e,t,n){return u(e,t,n)}},function(e,t,n){"use strict";var r=n(767);e.exports=r},function(e,t,n){"use strict";n.r(t),n.d(t,"parseYamlConfig",function(){return i});var r=n(143),o=n.n(r),i=function(e,t){try{return o.a.safeLoad(e)}catch(e){return t&&t.errActions.newThrownErr(new Error(e)),{}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"makeMappedContainer",function(){return j}),n.d(t,"render",function(){return P}),n.d(t,"getComponent",function(){return N});var r=n(26),o=n.n(r),i=n(17),a=n.n(i),s=n(16),u=n.n(s),c=n(20),l=n.n(c),p=n(4),f=n.n(p),h=n(5),d=n.n(h),m=n(6),v=n.n(m),g=n(7),y=n.n(g),b=n(8),_=n.n(b),w=n(0),x=n.n(w),E=n(472),S=n.n(E),C=n(326),k=n(473),O=n.n(k),A=function(e,t,n){var r=function(e,t){return function(n){function r(){return f()(this,r),v()(this,y()(r).apply(this,arguments))}return _()(r,n),d()(r,[{key:"render",value:function(){return x.a.createElement(t,l()({},e(),this.props,this.context))}}]),r}(w.Component)}(e,t),o=Object(C.connect)(function(n,r){var o=u()({},r,e());return(t.prototype.mapStateToProps||function(e){return{state:e}})(n,o)})(r);return n?function(e,t){return function(n){function r(){return f()(this,r),v()(this,y()(r).apply(this,arguments))}return _()(r,n),d()(r,[{key:"render",value:function(){return x.a.createElement(C.Provider,{store:e},x.a.createElement(t,l()({},this.props,this.context)))}}]),r}(w.Component)}(n,o):o},T=function(e,t,n,r){for(var o in t){var i=t[o];"function"==typeof i&&i(n[o],r[o],e())}},j=function(e,t,n,r,o,i){return function(t){function r(t,n){var o;return f()(this,r),o=v()(this,y()(r).call(this,t,n)),T(e,i,t,{}),o}return _()(r,t),d()(r,[{key:"componentWillReceiveProps",value:function(t){T(e,i,t,this.props)}},{key:"render",value:function(){var e=O()(this.props,i?a()(i):[]),t=n(o,"root");return x.a.createElement(t,e)}}]),r}(w.Component)},P=function(e,t,n,r,o){var i=n(e,t,r,"App","root");S.a.render(x.a.createElement(i,null),o)},I=function(e){var t=e.name;return x.a.createElement("div",{style:{padding:"1em",color:"#aaa"}},"😱 ",x.a.createElement("i",null,"Could not render ","t"===t?"this component":t,", see the console."))},M=function(e){var t=function(e){return!(e.prototype&&e.prototype.isReactComponent)}(e)?function(e){return function(t){function n(){return f()(this,n),v()(this,y()(n).apply(this,arguments))}return _()(n,t),d()(n,[{key:"render",value:function(){return e(this.props)}}]),n}(w.Component)}(e):e,n=t.prototype.render;return t.prototype.render=function(){try{for(var e=arguments.length,r=new Array(e),o=0;o<e;o++)r[o]=arguments[o];return n.apply(this,r)}catch(e){return console.error(e),x.a.createElement(I,{error:e,name:t.name})}},t},N=function(e,t,n,r,i){if("string"!=typeof r)throw new TypeError("Need a string, to fetch a component. Was given a "+o()(r));var a=n(r);return a?i?"root"===i?A(e,a,t()):A(e,M(a)):M(a):(e().log.warn("Could not find component",r),null)}},function(e,t,n){"use strict";n.r(t),n.d(t,"setHash",function(){return r});var r=function(e){return e?history.pushState(null,null,"#".concat(e)):window.location.hash=""}},function(e,t,n){var r=n(77),o=n(485),i=n(486),a=Object.defineProperty;t.f=n(122)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){var r=n(151);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var r=n(491),o=n(68);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";var r=n(76),o=n(95),i=n(123),a=n(68),s=n(33);e.exports=function(e,t,n){var u=s(e),c=n(a,u,""[e]),l=c[0],p=c[1];i(function(){var t={};return t[u]=function(){return 7},7!=""[e](t)})&&(o(String.prototype,e,l),r(RegExp.prototype,u,2==t?function(e,t){return p.call(e,this,t)}:function(e){return p.call(e,this)}))}},function(e,t,n){var r=n(204),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t,n){var r=n(44),o=n(345),i=n(207),a=n(205)("IE_PROTO"),s=function(){},u=function(){var e,t=n(209)("iframe"),r=i.length;for(t.style.display="none",n(346).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),u=e.F;r--;)delete u.prototype[i[r]];return u()};e.exports=Object.create||function(e,t){var n;return null!==e?(s.prototype=r(e),n=new s,s.prototype=null,n[a]=e):n=u(),void 0===t?n:o(n,t)}},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t){t.f={}.propertyIsEnumerable},function(e,t,n){var r=n(158),o=n(130),i=n(70),a=n(210),s=n(69),u=n(344),c=Object.getOwnPropertyDescriptor;t.f=n(45)?c:function(e,t){if(e=i(e),t=a(t,!0),u)try{return c(e,t)}catch(e){}if(s(e,t))return o(!r.f.call(e,t),e[t])}},function(e,t){},function(e,t,n){"use strict";e.exports={}},function(e,t,n){var r=n(127),o=n(34)("toStringTag"),i="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,a;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:i?r(t):"Object"==(a=r(t))&&"function"==typeof t.callee?"Arguments":a}},function(e,t,n){var r=n(81),o=n(63),i="[object Symbol]";e.exports=function(e){return"symbol"==typeof e||o(e)&&r(e)==i}},function(e,t,n){var r=n(82)(Object,"create");e.exports=r},function(e,t,n){var r=n(618),o=n(619),i=n(620),a=n(621),s=n(622);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=s,e.exports=u},function(e,t,n){var r=n(89);e.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},function(e,t,n){var r=n(624);e.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},function(e,t,n){var r=n(629),o=n(657),i=n(229),a=n(35),s=n(662);e.exports=function(e){return"function"==typeof e?e:null==e?i:"object"==typeof e?a(e)?o(e[0],e[1]):r(e):s(e)}},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t){var n=9007199254740991,r=/^(?:0|[1-9]\d*)$/;e.exports=function(e,t){var o=typeof e;return!!(t=null==t?n:t)&&("number"==o||"symbol"!=o&&r.test(e))&&e>-1&&e%1==0&&e<t}},function(e,t){var n=Object.prototype;e.exports=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||n)}},function(e,t,n){var r=n(652),o=n(219),i=n(653),a=n(654),s=n(655),u=n(81),c=n(367),l=c(r),p=c(o),f=c(i),h=c(a),d=c(s),m=u;(r&&"[object DataView]"!=m(new r(new ArrayBuffer(1)))||o&&"[object Map]"!=m(new o)||i&&"[object Promise]"!=m(i.resolve())||a&&"[object Set]"!=m(new a)||s&&"[object WeakMap]"!=m(new s))&&(m=function(e){var t=u(e),n="[object Object]"==t?e.constructor:void 0,r=n?c(n):"";if(r)switch(r){case l:return"[object DataView]";case p:return"[object Map]";case f:return"[object Promise]";case h:return"[object Set]";case d:return"[object WeakMap]"}return t}),e.exports=m},function(e,t,n){var r=n(104),o=n(105);e.exports=function(e,t){for(var n=0,i=(t=r(t,e)).length;null!=e&&n<i;)e=e[o(t[n++])];return n&&n==i?e:void 0}},function(e,t,n){"use strict";(function(t){!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function(e,n,r,o){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var i,a,s=arguments.length;switch(s){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick(function(){e.call(null,n)});case 3:return t.nextTick(function(){e.call(null,n,r)});case 4:return t.nextTick(function(){e.call(null,n,r,o)});default:for(i=new Array(s-1),a=0;a<i.length;)i[a++]=arguments[a];return t.nextTick(function(){e.apply(null,i)})}}}:e.exports=t}).call(this,n(72))},function(e,t,n){var r=n(61),o=r.Buffer;function i(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return o(e,t,n)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?e.exports=r:(i(r,t),t.Buffer=a),i(o,a),a.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return o(e,t,n)},a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=o(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return o(e)},a.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){"use strict";e.exports=n(690)("forEach")},function(e,t,n){"use strict";var r=n(394),o=n(391),i=n(233),a=n(699);(e.exports=function(e,t){var n,i,s,u,c;return arguments.length<2||"string"!=typeof e?(u=t,t=e,e=null):u=arguments[2],null==e?(n=s=!0,i=!1):(n=a.call(e,"c"),i=a.call(e,"e"),s=a.call(e,"w")),c={value:t,configurable:n,enumerable:i,writable:s},u?r(o(u),c):c}).gs=function(e,t,n){var s,u,c,l;return"string"!=typeof e?(c=n,n=t,t=e,e=null):c=arguments[3],null==t?t=void 0:i(t)?null==n?n=void 0:i(n)||(c=n,n=void 0):(c=t,t=n=void 0),null==e?(s=!0,u=!1):(s=a.call(e,"c"),u=a.call(e,"e")),l={get:t,set:n,configurable:s,enumerable:u},c?r(o(c),l):l}},function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},function(e,t,n){var r=n(71);e.exports=function(e,t,n){for(var o in t)n&&e[o]?e[o]=t[o]:r(e,o,t[o]);return e}},function(e,t,n){"use strict";var r=n(110);e.exports=r.DEFAULT=new r({include:[n(136)],explicit:[n(783),n(784),n(785)]})},function(e,t,n){var r=n(411),o=n(89),i=Object.prototype.hasOwnProperty;e.exports=function(e,t,n){var a=e[t];i.call(e,t)&&o(a,n)&&(void 0!==n||t in e)||r(e,t,n)}},function(e,t,n){"use strict";var r=n(21),o=(n(15),{}),i={reinitializeTransaction:function(){this.transactionWrappers=this.getTransactionWrappers(),this.wrapperInitData?this.wrapperInitData.length=0:this.wrapperInitData=[],this._isInTransaction=!1},_isInTransaction:!1,getTransactionWrappers:null,isInTransaction:function(){return!!this._isInTransaction},perform:function(e,t,n,o,i,a,s,u){var c,l;this.isInTransaction()&&r("27");try{this._isInTransaction=!0,c=!0,this.initializeAll(0),l=e.call(t,n,o,i,a,s,u),c=!1}finally{try{if(c)try{this.closeAll(0)}catch(e){}else this.closeAll(0)}finally{this._isInTransaction=!1}}return l},initializeAll:function(e){for(var t=this.transactionWrappers,n=e;n<t.length;n++){var r=t[n];try{this.wrapperInitData[n]=o,this.wrapperInitData[n]=r.initialize?r.initialize.call(this):null}finally{if(this.wrapperInitData[n]===o)try{this.initializeAll(n+1)}catch(e){}}}},closeAll:function(e){this.isInTransaction()||r("28");for(var t=this.transactionWrappers,n=e;n<t.length;n++){var i,a=t[n],s=this.wrapperInitData[n];try{i=!0,s!==o&&a.close&&a.close.call(this,s),i=!1}finally{if(i)try{this.closeAll(n+1)}catch(e){}}}this.wrapperInitData.length=0}};e.exports=i},function(e,t,n){"use strict";var r=n(139),o=n(423),i={screenX:null,screenY:null,clientX:null,clientY:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,getModifierState:n(244),button:function(e){var t=e.button;return"which"in e?t:2===t?2:4===t?1:0},buttons:null,relatedTarget:function(e){return e.relatedTarget||(e.fromElement===e.srcElement?e.toElement:e.fromElement)},pageX:function(e){return"pageX"in e?e.pageX:e.clientX+o.currentScrollLeft},pageY:function(e){return"pageY"in e?e.pageY:e.clientY+o.currentScrollTop}};function a(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(a,i),e.exports=a},function(e,t,n){"use strict";var r,o=n(36),i=n(246),a=/^[ \r\n\t\f]/,s=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,u=n(247)(function(e,t){if(e.namespaceURI!==i.svg||"innerHTML"in e)e.innerHTML=t;else{(r=r||document.createElement("div")).innerHTML="<svg>"+t+"</svg>";for(var n=r.firstChild;n.firstChild;)e.appendChild(n.firstChild)}});if(o.canUseDOM){var c=document.createElement("div");c.innerHTML=" ",""===c.innerHTML&&(u=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),a.test(t)||"<"===t[0]&&s.test(t)){e.innerHTML=String.fromCharCode(65279)+t;var n=e.firstChild;1===n.data.length?e.removeChild(n):n.deleteData(0,1)}else e.innerHTML=t}),c=null}e.exports=u},function(e,t,n){"use strict";var r=/["'&<>]/;e.exports=function(e){return"boolean"==typeof e||"number"==typeof e?""+e:function(e){var t,n=""+e,o=r.exec(n);if(!o)return n;var i="",a=0,s=0;for(a=o.index;a<n.length;a++){switch(n.charCodeAt(a)){case 34:t="&quot;";break;case 38:t="&amp;";break;case 39:t="&#x27;";break;case 60:t="&lt;";break;case 62:t="&gt;";break;default:continue}s!==a&&(i+=n.substring(s,a)),s=a+1,i+=t}return s!==a?i+n.substring(s,a):i}(e)}},function(e,t,n){"use strict";var r,o=n(25),i=n(239),a=n(829),s=n(423),u=n(830),c=n(243),l={},p=!1,f=0,h={topAbort:"abort",topAnimationEnd:u("animationend")||"animationend",topAnimationIteration:u("animationiteration")||"animationiteration",topAnimationStart:u("animationstart")||"animationstart",topBlur:"blur",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topChange:"change",topClick:"click",topCompositionEnd:"compositionend",topCompositionStart:"compositionstart",topCompositionUpdate:"compositionupdate",topContextMenu:"contextmenu",topCopy:"copy",topCut:"cut",topDoubleClick:"dblclick",topDrag:"drag",topDragEnd:"dragend",topDragEnter:"dragenter",topDragExit:"dragexit",topDragLeave:"dragleave",topDragOver:"dragover",topDragStart:"dragstart",topDrop:"drop",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topFocus:"focus",topInput:"input",topKeyDown:"keydown",topKeyPress:"keypress",topKeyUp:"keyup",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topMouseDown:"mousedown",topMouseMove:"mousemove",topMouseOut:"mouseout",topMouseOver:"mouseover",topMouseUp:"mouseup",topPaste:"paste",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topScroll:"scroll",topSeeked:"seeked",topSeeking:"seeking",topSelectionChange:"selectionchange",topStalled:"stalled",topSuspend:"suspend",topTextInput:"textInput",topTimeUpdate:"timeupdate",topTouchCancel:"touchcancel",topTouchEnd:"touchend",topTouchMove:"touchmove",topTouchStart:"touchstart",topTransitionEnd:u("transitionend")||"transitionend",topVolumeChange:"volumechange",topWaiting:"waiting",topWheel:"wheel"},d="_reactListenersID"+String(Math.random()).slice(2);var m=o({},a,{ReactEventListener:null,injection:{injectReactEventListener:function(e){e.setHandleTopLevel(m.handleTopLevel),m.ReactEventListener=e}},setEnabled:function(e){m.ReactEventListener&&m.ReactEventListener.setEnabled(e)},isEnabled:function(){return!(!m.ReactEventListener||!m.ReactEventListener.isEnabled())},listenTo:function(e,t){for(var n=t,r=function(e){return Object.prototype.hasOwnProperty.call(e,d)||(e[d]=f++,l[e[d]]={}),l[e[d]]}(n),o=i.registrationNameDependencies[e],a=0;a<o.length;a++){var s=o[a];r.hasOwnProperty(s)&&r[s]||("topWheel"===s?c("wheel")?m.ReactEventListener.trapBubbledEvent("topWheel","wheel",n):c("mousewheel")?m.ReactEventListener.trapBubbledEvent("topWheel","mousewheel",n):m.ReactEventListener.trapBubbledEvent("topWheel","DOMMouseScroll",n):"topScroll"===s?c("scroll",!0)?m.ReactEventListener.trapCapturedEvent("topScroll","scroll",n):m.ReactEventListener.trapBubbledEvent("topScroll","scroll",m.ReactEventListener.WINDOW_HANDLE):"topFocus"===s||"topBlur"===s?(c("focus",!0)?(m.ReactEventListener.trapCapturedEvent("topFocus","focus",n),m.ReactEventListener.trapCapturedEvent("topBlur","blur",n)):c("focusin")&&(m.ReactEventListener.trapBubbledEvent("topFocus","focusin",n),m.ReactEventListener.trapBubbledEvent("topBlur","focusout",n)),r.topBlur=!0,r.topFocus=!0):h.hasOwnProperty(s)&&m.ReactEventListener.trapBubbledEvent(s,h[s],n),r[s]=!0)}},trapBubbledEvent:function(e,t,n){return m.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return m.ReactEventListener.trapCapturedEvent(e,t,n)},supportsEventPageXY:function(){if(!document.createEvent)return!1;var e=document.createEvent("MouseEvent");return null!=e&&"pageX"in e},ensureScrollValueMonitoring:function(){if(void 0===r&&(r=m.supportsEventPageXY()),!r&&!p){var e=s.refreshScrollValues;m.ReactEventListener.monitorScrollValue(e),p=!0}}});e.exports=m},function(e,t,n){"use strict";function r(){this.__rules__=[],this.__cache__=null}r.prototype.__find__=function(e){for(var t=this.__rules__.length,n=-1;t--;)if(this.__rules__[++n].name===e)return n;return-1},r.prototype.__compile__=function(){var e=this,t=[""];e.__rules__.forEach(function(e){e.enabled&&e.alt.forEach(function(e){t.indexOf(e)<0&&t.push(e)})}),e.__cache__={},t.forEach(function(t){e.__cache__[t]=[],e.__rules__.forEach(function(n){n.enabled&&(t&&n.alt.indexOf(t)<0||e.__cache__[t].push(n.fn))})})},r.prototype.at=function(e,t,n){var r=this.__find__(e),o=n||{};if(-1===r)throw new Error("Parser rule not found: "+e);this.__rules__[r].fn=t,this.__rules__[r].alt=o.alt||[],this.__cache__=null},r.prototype.before=function(e,t,n,r){var o=this.__find__(e),i=r||{};if(-1===o)throw new Error("Parser rule not found: "+e);this.__rules__.splice(o,0,{name:t,enabled:!0,fn:n,alt:i.alt||[]}),this.__cache__=null},r.prototype.after=function(e,t,n,r){var o=this.__find__(e),i=r||{};if(-1===o)throw new Error("Parser rule not found: "+e);this.__rules__.splice(o+1,0,{name:t,enabled:!0,fn:n,alt:i.alt||[]}),this.__cache__=null},r.prototype.push=function(e,t,n){var r=n||{};this.__rules__.push({name:e,enabled:!0,fn:t,alt:r.alt||[]}),this.__cache__=null},r.prototype.enable=function(e,t){e=Array.isArray(e)?e:[e],t&&this.__rules__.forEach(function(e){e.enabled=!1}),e.forEach(function(e){var t=this.__find__(e);if(t<0)throw new Error("Rules manager: invalid rule name "+e);this.__rules__[t].enabled=!0},this),this.__cache__=null},r.prototype.disable=function(e){(e=Array.isArray(e)?e:[e]).forEach(function(e){var t=this.__find__(e);if(t<0)throw new Error("Rules manager: invalid rule name "+e);this.__rules__[t].enabled=!1},this),this.__cache__=null},r.prototype.getRules=function(e){return null===this.__cache__&&this.__compile__(),this.__cache__[e]||[]},e.exports=r},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i=-1,a=e.posMax,s=e.pos,u=e.isInLabel;if(e.isInLabel)return-1;if(e.labelUnmatchedScopes)return e.labelUnmatchedScopes--,-1;for(e.pos=t+1,e.isInLabel=!0,n=1;e.pos<a;){if(91===(o=e.src.charCodeAt(e.pos)))n++;else if(93===o&&0===--n){r=!0;break}e.parser.skipToken(e)}return r?(i=e.pos,e.labelUnmatchedScopes=0):e.labelUnmatchedScopes=n-1,e.pos=s,e.isInLabel=u,i}},function(e,t,n){e.exports=n(759)},function(e,t,n){var r=n(189);function o(e,t,n,o,i,a,s){try{var u=e[a](s),c=u.value}catch(e){return void n(e)}u.done?t(c):r.resolve(c).then(o,i)}e.exports=function(e){return function(){var t=this,n=arguments;return new r(function(r,i){var a=e.apply(t,n);function s(e){o(a,r,i,s,u,"next",e)}function u(e){o(a,r,i,s,u,"throw",e)}s(void 0)})}}},function(e,t,n){"use strict";n.d(t,"a",function(){return O});var r=n(20),o=n.n(r),i=n(4),a=n.n(i),s=n(5),u=n.n(s),c=n(6),l=n.n(c),p=n(7),f=n.n(p),h=n(9),d=n.n(h),m=n(8),v=n.n(m),g=n(2),y=n.n(g),b=n(0),_=n.n(b),w=n(479),x=n.n(w),E=n(19),S=n.n(E),C=n(10),k=n.n(C),O=function(e){function t(){var e,n;a()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=l()(this,(e=f()(t)).call.apply(e,[this].concat(o))),y()(d()(n),"getModelName",function(e){return-1!==e.indexOf("#/definitions/")?e.replace(/^.*#\/definitions\//,""):-1!==e.indexOf("#/components/schemas/")?e.replace(/^.*#\/components\/schemas\//,""):void 0}),y()(d()(n),"getRefSchema",function(e){return n.props.specSelectors.findDefinition(e)}),n}return v()(t,e),u()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,r=e.getConfigs,i=e.specSelectors,a=e.schema,s=e.required,u=e.name,c=e.isRef,l=e.specPath,p=e.displayName,f=t("ObjectModel"),h=t("ArrayModel"),d=t("PrimitiveModel"),m="object",v=a&&a.get("$$ref");if(!u&&v&&(u=this.getModelName(v)),!a&&v&&(a=this.getRefSchema(u)),!a)return _.a.createElement("span",{className:"model model-title"},_.a.createElement("span",{className:"model-title__text"},p||u),_.a.createElement("img",{src:n(456),height:"20px",width:"20px",style:{marginLeft:"1em",position:"relative",bottom:"0px"}}));var g=i.isOAS3()&&a.get("deprecated");switch(c=void 0!==c?c:!!v,m=a&&a.get("type")||m){case"object":return _.a.createElement(f,o()({className:"object"},this.props,{specPath:l,getConfigs:r,schema:a,name:u,deprecated:g,isRef:c}));case"array":return _.a.createElement(h,o()({className:"array"},this.props,{getConfigs:r,schema:a,name:u,deprecated:g,required:s}));case"string":case"number":case"integer":case"boolean":default:return _.a.createElement(d,o()({},this.props,{getComponent:t,getConfigs:r,schema:a,name:u,deprecated:g,required:s}))}}}]),t}(x.a);y()(O,"propTypes",{schema:S.a.orderedMap.isRequired,getComponent:k.a.func.isRequired,getConfigs:k.a.func.isRequired,specSelectors:k.a.object.isRequired,name:k.a.string,displayName:k.a.string,isRef:k.a.bool,required:k.a.bool,expandDepth:k.a.number,depth:k.a.number,specPath:S.a.list.isRequired})},function(e,t,n){"use strict";n.d(t,"b",function(){return p});var r=n(0),o=n.n(r),i=(n(10),n(193)),a=n.n(i),s=n(327),u=n.n(s),c=n(56),l=n.n(c);function p(e){return u.a.sanitize(e,{ADD_ATTR:["target"]})}u.a.addHook("beforeSanitizeElements",function(e){return e.href&&e.setAttribute("rel","noopener noreferrer"),e}),t.a=function(e){var t=e.source,n=e.className,r=void 0===n?"":n;if("string"!=typeof t)return null;var i=new a.a({html:!0,typographer:!0,breaks:!0,linkify:!0,linkTarget:"_blank"});i.core.ruler.disable(["replacements","smartquotes"]);var s=i.render(t),u=p(s);return t&&s&&u?o.a.createElement("div",{className:l()(r,"markdown"),dangerouslySetInnerHTML:{__html:u}}):null}},function(e,t,n){"use strict";e.exports=n(967)},function(e,t,n){var r=n(121),o=n(33)("toStringTag"),i="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,a;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:i?r(t):"Object"==(a=r(t))&&"function"==typeof t.callee?"Arguments":a}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t,n){var r=n(96),o=n(43).document,i=r(o)&&r(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},function(e,t,n){var r=n(328)("keys"),o=n(195);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t,n){var r=n(147).f,o=n(148),i=n(33)("toStringTag");e.exports=function(e,t,n){e&&!o(e=n?e:e.prototype,i)&&r(e,i,{configurable:!0,value:t})}},function(e,t,n){"use strict";var r=n(151);function o(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=r(t),this.reject=r(n)}e.exports.f=function(e){return new o(e)}},function(e,t,n){var r=n(342),o=n(68);e.exports=function(e,t,n){if(r(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(o(e))}},function(e,t,n){var r=n(33)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,!"/./"[e](t)}catch(e){}}return!0}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){var r=n(127);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==r(e)?e.split(""):Object(e)}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){var r=n(206)("keys"),o=n(155);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t,n){var r=n(22),o=n(32),i=o["__core-js_shared__"]||(o["__core-js_shared__"]={});(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})("versions",[]).push({version:r.version,mode:n(128)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var r=n(30),o=n(22),i=n(80);e.exports=function(e,t){var n=(o.Object||{})[e]||Object[e],a={};a[e]=t(n),r(r.S+r.F*i(function(){n(1)}),"Object",a)}},function(e,t,n){var r=n(40),o=n(32).document,i=r(o)&&r(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},function(e,t,n){var r=n(40);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){"use strict";var r=n(128),o=n(30),i=n(212),a=n(71),s=n(98),u=n(549),c=n(131),l=n(347),p=n(34)("iterator"),f=!([].keys&&"next"in[].keys()),h=function(){return this};e.exports=function(e,t,n,d,m,v,g){u(n,t,d);var y,b,_,w=function(e){if(!f&&e in C)return C[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},x=t+" Iterator",E="values"==m,S=!1,C=e.prototype,k=C[p]||C["@@iterator"]||m&&C[m],O=k||w(m),A=m?E?w("entries"):O:void 0,T="Array"==t&&C.entries||k;if(T&&(_=l(T.call(new e)))!==Object.prototype&&_.next&&(c(_,x,!0),r||"function"==typeof _[p]||a(_,p,h)),E&&k&&"values"!==k.name&&(S=!0,O=function(){return k.call(this)}),r&&!g||!f&&!S&&C[p]||a(C,p,O),s[t]=O,s[x]=h,m)if(y={values:E?O:w("values"),keys:v?O:w("keys"),entries:A},g)for(b in y)b in C||i(C,b,y[b]);else o(o.P+o.F*(f||S),t,y);return y}},function(e,t,n){e.exports=n(71)},function(e,t,n){t.f=n(34)},function(e,t,n){var r=n(32),o=n(22),i=n(128),a=n(213),s=n(47).f;e.exports=function(e){var t=o.Symbol||(o.Symbol=i?{}:r.Symbol||{});"_"==e.charAt(0)||e in t||s(t,e,{value:a.f(e)})}},function(e,t,n){var r=n(127);e.exports=Array.isArray||function(e){return"Array"==r(e)}},function(e,t,n){var r=n(343),o=n(207).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,o)}},function(e,t,n){var r=n(162),o=n(34)("iterator"),i=n(98);e.exports=n(22).getIteratorMethod=function(e){if(null!=e)return e[o]||e["@@iterator"]||i[r(e)]}},function(e,t,n){var r=n(607),o=n(623),i=n(625),a=n(626),s=n(627);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=s,e.exports=u},function(e,t,n){var r=n(82)(n(48),"Map");e.exports=r},function(e,t,n){var r=n(165),o=n(631),i=n(632),a=n(633),s=n(634),u=n(635);function c(e){var t=this.__data__=new r(e);this.size=t.size}c.prototype.clear=o,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=s,c.prototype.set=u,e.exports=c},function(e,t){e.exports=function(e,t){for(var n=-1,r=t.length,o=e.length;++n<r;)e[o+n]=t[n];return e}},function(e,t,n){var r=n(645),o=n(374),i=Object.prototype.propertyIsEnumerable,a=Object.getOwnPropertySymbols,s=a?function(e){return null==e?[]:(e=Object(e),r(a(e),function(t){return i.call(e,t)}))}:o;e.exports=s},function(e,t,n){var r=n(647),o=n(63),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,u=r(function(){return arguments}())?r:function(e){return o(e)&&a.call(e,"callee")&&!s.call(e,"callee")};e.exports=u},function(e,t,n){(function(e){var r=n(48),o=n(648),i=t&&!t.nodeType&&t,a=i&&"object"==typeof e&&e&&!e.nodeType&&e,s=a&&a.exports===i?r.Buffer:void 0,u=(s?s.isBuffer:void 0)||o;e.exports=u}).call(this,n(169)(e))},function(e,t){var n=9007199254740991;e.exports=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=n}},function(e,t){e.exports=function(e){return function(t){return e(t)}}},function(e,t,n){(function(e){var r=n(361),o=t&&!t.nodeType&&t,i=o&&"object"==typeof e&&e&&!e.nodeType&&e,a=i&&i.exports===o&&r.process,s=function(){try{var e=i&&i.require&&i.require("util").types;return e||a&&a.binding&&a.binding("util")}catch(e){}}();e.exports=s}).call(this,n(169)(e))},function(e,t,n){var r=n(35),o=n(163),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;e.exports=function(e,t){if(r(e))return!1;var n=typeof e;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!o(e))||a.test(e)||!i.test(e)||null!=t&&e in Object(t)}},function(e,t){e.exports=function(e){return e}},function(e,t,n){"use strict";var r,o="object"==typeof Reflect?Reflect:null,i=o&&"function"==typeof o.apply?o.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=o&&"function"==typeof o.ownKeys?o.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var a=Number.isNaN||function(e){return e!=e};function s(){s.init.call(this)}e.exports=s,s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var u=10;function c(e){return void 0===e._maxListeners?s.defaultMaxListeners:e._maxListeners}function l(e,t,n,r){var o,i,a,s;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),a=i[t]),void 0===a)a=i[t]=n,++e._eventsCount;else if("function"==typeof a?a=i[t]=r?[n,a]:[a,n]:r?a.unshift(n):a.push(n),(o=c(e))>0&&a.length>o&&!a.warned){a.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=a.length,s=u,console&&console.warn&&console.warn(s)}return e}function p(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t<arguments.length;t++)e.push(arguments[t]);this.fired||(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,i(this.listener,this.target,e))}.bind(r);return o.listener=n,r.wrapFn=o,o}function f(e,t,n){var r=e._events;if(void 0===r)return[];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(o):d(o,o.length)}function h(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}Object.defineProperty(s,"defaultMaxListeners",{enumerable:!0,get:function(){return u},set:function(e){if("number"!=typeof e||e<0||a(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");u=e}}),s.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},s.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||a(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},s.prototype.getMaxListeners=function(){return c(this)},s.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,o=this._events;if(void 0!==o)r=r&&void 0===o.error;else if(!r)return!1;if(r){var a;if(t.length>0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var u=o[e];if(void 0===u)return!1;if("function"==typeof u)i(u,this,t);else{var c=u.length,l=d(u,c);for(n=0;n<c;++n)i(l[n],this,t)}return!0},s.prototype.addListener=function(e,t){return l(this,e,t,!1)},s.prototype.on=s.prototype.addListener,s.prototype.prependListener=function(e,t){return l(this,e,t,!0)},s.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.on(e,p(this,e,t)),this},s.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);return this.prependListener(e,p(this,e,t)),this},s.prototype.removeListener=function(e,t){var n,r,o,i,a;if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t);if(void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(o=-1,i=n.length-1;i>=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(n,o),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,a||t)}return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var o,i=Object.keys(n);for(r=0;r<i.length;++r)"removeListener"!==(o=i[r])&&this.removeAllListeners(o);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return f(this,e,!0)},s.prototype.rawListeners=function(e){return f(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):h.call(e,t)},s.prototype.listenerCount=h,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){(t=e.exports=n(385)).Stream=t,t.Readable=t,t.Writable=n(232),t.Duplex=n(84),t.Transform=n(390),t.PassThrough=n(680)},function(e,t,n){"use strict";(function(t,r,o){var i=n(174);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=y;var s,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;y.WritableState=g;var c=n(134);c.inherits=n(106);var l={deprecate:n(679)},p=n(386),f=n(175).Buffer,h=o.Uint8Array||function(){};var d,m=n(387);function v(){}function g(e,t){s=s||n(84),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var p=!1===e.decodeStrings;this.decodeStrings=!p,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),S(e,t))}(e,n,r,t,o);else{var a=x(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||w(e,n),r?u(_,e,n,a,o):_(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function y(e){if(s=s||n(84),!(d.call(y,this)||this instanceof s))return new y(e);this._writableState=new g(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),p.call(this)}function b(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function _(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),S(e,t)}function w(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,u=!0;n;)o[s]=n,n.isBuf||(u=!1),n=n.next,s+=1;o.allBuffers=u,b(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,p=n.callback;if(b(e,t,!1,t.objectMode?1:c.length,c,l,p),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function x(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function E(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),S(e,t)})}function S(e,t){var n=x(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(E,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(y,p),g.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(g.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(y,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===y&&(e&&e._writableState instanceof g)}})):d=function(e){return e instanceof this},y.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},y.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,f.isBuffer(r)||r instanceof h);return s&&!f.isBuffer(e)&&(e=function(e){return f.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=v),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=f.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var u=t.length<t.highWaterMark;u||(t.needDrain=!0);if(t.writing||t.corked){var c=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:o,isBuf:n,callback:i,next:null},c?c.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else b(e,t,!1,s,r,o,i);return u}(this,o,s,e,t,n)),a},y.prototype.cork=function(){this._writableState.corked++},y.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||w(this,e))},y.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(y.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),y.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},y.prototype._writev=null,y.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,S(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),y.prototype.destroy=m.destroy,y.prototype._undestroy=m.undestroy,y.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(72),n(388).setImmediate,n(41))},function(e,t,n){"use strict";e.exports=function(e){return"function"==typeof e}},function(e,t,n){"use strict";e.exports=n(705)()?Array.from:n(706)},function(e,t,n){"use strict";var r=n(719),o=n(86),i=n(107),a=Array.prototype.indexOf,s=Object.prototype.hasOwnProperty,u=Math.abs,c=Math.floor;e.exports=function(e){var t,n,l,p;if(!r(e))return a.apply(this,arguments);for(n=o(i(this).length),l=arguments[1],t=l=isNaN(l)?0:l>=0?c(l):o(this.length)-c(u(l));t<n;++t)if(s.call(this,t)&&(p=this[t],r(p)))return t;return-1}},function(e,t,n){"use strict";(function(t,n){var r,o;r=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e},o=function(e){var t,n,o=document.createTextNode(""),i=0;return new e(function(){var e;if(t)n&&(t=n.concat(t));else{if(!n)return;t=n}if(n=t,t=null,"function"==typeof n)return e=n,n=null,void e();for(o.data=i=++i%2;n;)e=n.shift(),n.length||(n=null),e()}).observe(o,{characterData:!0}),function(e){r(e),t?"function"==typeof t?t=[t,e]:t.push(e):(t=e,o.data=i=++i%2)}},e.exports=function(){if("object"==typeof t&&t&&"function"==typeof t.nextTick)return t.nextTick;if("object"==typeof document&&document){if("function"==typeof MutationObserver)return o(MutationObserver);if("function"==typeof WebKitMutationObserver)return o(WebKitMutationObserver)}return"function"==typeof n?function(e){n(r(e))}:"function"==typeof setTimeout||"object"==typeof setTimeout?function(e){setTimeout(r(e),0)}:null}()}).call(this,n(72),n(388).setImmediate)},function(e,t,n){"use strict";var r=n(129);function o(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=r(t),this.reject=r(n)}e.exports.f=function(e){return new o(e)}},function(e,t,n){"use strict";var r=n(110);e.exports=new r({explicit:[n(770),n(771),n(772)]})},function(e,t,n){"use strict";var r=n(21),o=(n(15),null),i={};function a(){if(o)for(var e in i){var t=i[e],n=o.indexOf(e);if(n>-1||r("96",e),!c.plugins[n]){t.extractEvents||r("97",e),c.plugins[n]=t;var a=t.eventTypes;for(var u in a)s(a[u],t,u)||r("98",u,e)}}}function s(e,t,n){c.eventNameDispatchConfigs.hasOwnProperty(n)&&r("99",n),c.eventNameDispatchConfigs[n]=e;var o=e.phasedRegistrationNames;if(o){for(var i in o){if(o.hasOwnProperty(i))u(o[i],t,n)}return!0}return!!e.registrationName&&(u(e.registrationName,t,n),!0)}function u(e,t,n){c.registrationNameModules[e]&&r("100",e),c.registrationNameModules[e]=t,c.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var c={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},possibleRegistrationNames:null,injectEventPluginOrder:function(e){o&&r("101"),o=Array.prototype.slice.call(e),a()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];i.hasOwnProperty(n)&&i[n]===o||(i[n]&&r("102",n),i[n]=o,t=!0)}t&&a()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return c.registrationNameModules[t.registrationName]||null;if(void 0!==t.phasedRegistrationNames){var n=t.phasedRegistrationNames;for(var r in n)if(n.hasOwnProperty(r)){var o=c.registrationNameModules[n[r]];if(o)return o}}return null},_resetEventPlugins:function(){for(var e in o=null,i)i.hasOwnProperty(e)&&delete i[e];c.plugins.length=0;var t=c.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=c.registrationNameModules;for(var a in r)r.hasOwnProperty(a)&&delete r[a]}};e.exports=c},function(e,t,n){"use strict";var r,o,i=n(21),a=n(241);n(15),n(23);function s(e,t,n,r){var o=e.type||"unknown-event";e.currentTarget=u.getNodeFromInstance(r),t?a.invokeGuardedCallbackWithCatch(o,n,e):a.invokeGuardedCallback(o,n,e),e.currentTarget=null}var u={isEndish:function(e){return"topMouseUp"===e||"topTouchEnd"===e||"topTouchCancel"===e},isMoveish:function(e){return"topMouseMove"===e||"topTouchMove"===e},isStartish:function(e){return"topMouseDown"===e||"topTouchStart"===e},executeDirectDispatch:function(e){var t=e._dispatchListeners,n=e._dispatchInstances;Array.isArray(t)&&i("103"),e.currentTarget=t?u.getNodeFromInstance(n):null;var r=t?t(e):null;return e.currentTarget=null,e._dispatchListeners=null,e._dispatchInstances=null,r},executeDispatchesInOrder:function(e,t){var n=e._dispatchListeners,r=e._dispatchInstances;if(Array.isArray(n))for(var o=0;o<n.length&&!e.isPropagationStopped();o++)s(e,t,n[o],r[o]);else n&&s(e,t,n,r);e._dispatchListeners=null,e._dispatchInstances=null},executeDispatchesInOrderStopAtTrue:function(e){var t=function(e){var t=e._dispatchListeners,n=e._dispatchInstances;if(Array.isArray(t)){for(var r=0;r<t.length&&!e.isPropagationStopped();r++)if(t[r](e,n[r]))return n[r]}else if(t&&t(e,n))return n;return null}(e);return e._dispatchInstances=null,e._dispatchListeners=null,t},hasDispatches:function(e){return!!e._dispatchListeners},getInstanceFromNode:function(e){return r.getInstanceFromNode(e)},getNodeFromInstance:function(e){return r.getNodeFromInstance(e)},isAncestor:function(e,t){return o.isAncestor(e,t)},getLowestCommonAncestor:function(e,t){return o.getLowestCommonAncestor(e,t)},getParentInstance:function(e){return o.getParentInstance(e)},traverseTwoPhase:function(e,t,n){return o.traverseTwoPhase(e,t,n)},traverseEnterLeave:function(e,t,n,r,i){return o.traverseEnterLeave(e,t,n,r,i)},injection:{injectComponentTree:function(e){r=e},injectTreeTraversal:function(e){o=e}}};e.exports=u},function(e,t,n){"use strict";var r=null;function o(e,t,n){try{t(n)}catch(e){null===r&&(r=e)}}var i={invokeGuardedCallback:o,invokeGuardedCallbackWithCatch:o,rethrowCaughtError:function(){if(r){var e=r;throw r=null,e}}};e.exports=i},function(e,t,n){"use strict";e.exports=function(e){var t=e.target||e.srcElement||window;return t.correspondingUseElement&&(t=t.correspondingUseElement),3===t.nodeType?t.parentNode:t}},function(e,t,n){"use strict";var r,o=n(36);o.canUseDOM&&(r=document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("",""))
+/**
+ * Checks if an event is supported in the current execution environment.
+ *
+ * NOTE: This will not work correctly for non-generic events such as `change`,
+ * `reset`, `load`, `error`, and `select`.
+ *
+ * Borrows from Modernizr.
+ *
+ * @param {string} eventNameSuffix Event name, e.g. "click".
+ * @param {?boolean} capture Check if the capture phase is supported.
+ * @return {boolean} True if the event is supported.
+ * @internal
+ * @license Modernizr 3.0.0pre (Custom Build) | MIT
+ */,e.exports=function(e,t){if(!o.canUseDOM||t&&!("addEventListener"in document))return!1;var n="on"+e,i=n in document;if(!i){var a=document.createElement("div");a.setAttribute(n,"return;"),i="function"==typeof a[n]}return!i&&r&&"wheel"===e&&(i=document.implementation.hasFeature("Events.wheel","3.0")),i}},function(e,t,n){"use strict";var r={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function o(e){var t=this.nativeEvent;if(t.getModifierState)return t.getModifierState(e);var n=r[e];return!!n&&!!t[n]}e.exports=function(e){return o}},function(e,t,n){"use strict";var r=n(113),o=n(814),i=(n(27),n(50),n(247)),a=n(184),s=n(424);function u(e,t){return Array.isArray(t)&&(t=t[1]),t?t.nextSibling:e.firstChild}var c=i(function(e,t,n){e.insertBefore(t,n)});function l(e,t,n){r.insertTreeBefore(e,t,n)}function p(e,t,n){Array.isArray(t)?function(e,t,n,r){var o=t;for(;;){var i=o.nextSibling;if(c(e,o,r),o===n)break;o=i}}(e,t[0],t[1],n):c(e,t,n)}function f(e,t){if(Array.isArray(t)){var n=t[1];h(e,t=t[0],n),e.removeChild(n)}e.removeChild(t)}function h(e,t,n){for(;;){var r=t.nextSibling;if(r===n)break;e.removeChild(r)}}var d={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,replaceDelimitedText:function(e,t,n){var r=e.parentNode,o=e.nextSibling;o===t?n&&c(r,document.createTextNode(n),o):n?(s(o,n),h(r,o,t)):h(r,e,t)},processUpdates:function(e,t){for(var n=0;n<t.length;n++){var r=t[n];switch(r.type){case"INSERT_MARKUP":l(e,r.content,u(e,r.afterNode));break;case"MOVE_EXISTING":p(e,r.fromNode,u(e,r.afterNode));break;case"SET_MARKUP":a(e,r.content);break;case"TEXT_CONTENT":s(e,r.content);break;case"REMOVE_NODE":f(e,r.fromNode)}}}};e.exports=d},function(e,t,n){"use strict";e.exports={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"}},function(e,t,n){"use strict";e.exports=function(e){return"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(t,n,r,o){MSApp.execUnsafeLocalFunction(function(){return e(t,n,r,o)})}:e}},function(e,t,n){"use strict";var r=n(21),o=n(832),i=n(356)(n(100).isValidElement),a=(n(15),n(23),{button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0});function s(e){null!=e.checkedLink&&null!=e.valueLink&&r("87")}function u(e){s(e),(null!=e.value||null!=e.onChange)&&r("88")}function c(e){s(e),(null!=e.checked||null!=e.onChange)&&r("89")}var l={value:function(e,t,n){return!e[t]||a[e.type]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t,n){return!e[t]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:i.func},p={};function f(e){if(e){var t=e.getName();if(t)return" Check the render method of `"+t+"`."}return""}var h={checkPropTypes:function(e,t,n){for(var r in l){if(l.hasOwnProperty(r))var i=l[r](t,r,e,"prop",null,o);if(i instanceof Error&&!(i.message in p)){p[i.message]=!0;f(n)}}},getValue:function(e){return e.valueLink?(u(e),e.valueLink.value):e.value},getChecked:function(e){return e.checkedLink?(c(e),e.checkedLink.value):e.checked},executeOnChange:function(e,t){return e.valueLink?(u(e),e.valueLink.requestChange(t.target.value)):e.checkedLink?(c(e),e.checkedLink.requestChange(t.target.checked)):e.onChange?e.onChange.call(void 0,t):void 0}};e.exports=h},function(e,t,n){"use strict";var r=n(21),o=(n(15),!1),i={replaceNodeWithMarkup:null,processChildrenUpdates:null,injection:{injectEnvironment:function(e){o&&r("104"),i.replaceNodeWithMarkup=e.replaceNodeWithMarkup,i.processChildrenUpdates=e.processChildrenUpdates,o=!0}}};e.exports=i},function(e,t,n){"use strict";var r=Object.prototype.hasOwnProperty;function o(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}e.exports=function(e,t){if(o(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),i=Object.keys(t);if(n.length!==i.length)return!1;for(var a=0;a<n.length;a++)if(!r.call(t,n[a])||!o(e[n[a]],t[n[a]]))return!1;return!0}},function(e,t,n){"use strict";e.exports=function(e,t){var n=null===e||!1===e,r=null===t||!1===t;if(n||r)return n===r;var o=typeof e,i=typeof t;return"string"===o||"number"===o?"string"===i||"number"===i:"object"===i&&e.type===t.type&&e.key===t.key}},function(e,t,n){"use strict";var r={escape:function(e){var t={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,function(e){return t[e]})},unescape:function(e){var t={"=0":"=","=2":":"};return(""+("."===e[0]&&"$"===e[1]?e.substring(2):e.substring(1))).replace(/(=0|=2)/g,function(e){return t[e]})}};e.exports=r},function(e,t,n){"use strict";var r=n(21),o=(n(62),n(140)),i=(n(50),n(55));n(15),n(23);function a(e){i.enqueueUpdate(e)}function s(e,t){var n=o.get(e);return n||null}var u={isMounted:function(e){var t=o.get(e);return!!t&&!!t._renderedComponent},enqueueCallback:function(e,t,n){u.validateCallback(t,n);var r=s(e);if(!r)return null;r._pendingCallbacks?r._pendingCallbacks.push(t):r._pendingCallbacks=[t],a(r)},enqueueCallbackInternal:function(e,t){e._pendingCallbacks?e._pendingCallbacks.push(t):e._pendingCallbacks=[t],a(e)},enqueueForceUpdate:function(e){var t=s(e);t&&(t._pendingForceUpdate=!0,a(t))},enqueueReplaceState:function(e,t,n){var r=s(e);r&&(r._pendingStateQueue=[t],r._pendingReplaceState=!0,null!=n&&(u.validateCallback(n,"replaceState"),r._pendingCallbacks?r._pendingCallbacks.push(n):r._pendingCallbacks=[n]),a(r))},enqueueSetState:function(e,t){var n=s(e);n&&((n._pendingStateQueue||(n._pendingStateQueue=[])).push(t),a(n))},enqueueElementInternal:function(e,t,n){e._pendingElement=t,e._context=n,a(e)},validateCallback:function(e,t){e&&"function"!=typeof e&&r("122",t,function(e){var t=typeof e;if("object"!==t)return t;var n=e.constructor&&e.constructor.name||t,r=Object.keys(e);return r.length>0&&r.length<20?n+" (keys: "+r.join(", ")+")":n}(e))}};e.exports=u},function(e,t,n){"use strict";n(25);var r=n(54),o=(n(23),r);e.exports=o},function(e,t,n){"use strict";e.exports=function(e){var t,n=e.keyCode;return"charCode"in e?0===(t=e.charCode)&&13===n&&(t=13):t=n,t>=32||13===t?t:0}},function(e,t,n){var r=n(81),o=n(257),i=n(63),a="[object Object]",s=Function.prototype,u=Object.prototype,c=s.toString,l=u.hasOwnProperty,p=c.call(Object);e.exports=function(e){if(!i(e)||r(e)!=a)return!1;var t=o(e);if(null===t)return!0;var n=l.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&c.call(n)==p}},function(e,t,n){var r=n(377)(Object.getPrototypeOf,Object);e.exports=r},function(e,t,n){var r=n(371);e.exports=function(e){var t=new e.constructor(e.byteLength);return new r(t).set(new r(e)),t}},function(e,t){
+/*!
+ * https://github.com/Starcounter-Jack/JSON-Patch
+ * (c) 2017 Joachim Wester
+ * MIT license
+ */
+var n=this&&this.__extends||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);function r(){this.constructor=e}e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)},r=Object.prototype.hasOwnProperty;function o(e,t){return r.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n<t.length;n++)t[n]=""+n;return t}if(Object.keys)return Object.keys(e);t=[];for(var r in e)o(e,r)&&t.push(r);return t}function a(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function s(e,t){var n;for(var r in e)if(o(e,r)){if(e[r]===t)return a(r)+"/";if("object"==typeof e[r]&&""!=(n=s(e[r],t)))return a(r)+"/"+n}return""}function u(e,t){var n=[e];for(var r in t){var o="object"==typeof t[r]?JSON.stringify(t[r],null,2):t[r];void 0!==o&&n.push(r+": "+o)}return n.join("\n")}t.hasOwnProperty=o,t._objectKeys=i,t._deepClone=function(e){switch(typeof e){case"object":return JSON.parse(JSON.stringify(e));case"undefined":return null;default:return e}},t.isInteger=function(e){for(var t,n=0,r=e.length;n<r;){if(!((t=e.charCodeAt(n))>=48&&t<=57))return!1;n++}return!0},t.escapePathComponent=a,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=s,t.getPath=function(e,t){if(e===t)return"/";var n=s(e,t);if(""===n)throw new Error("Object not found in root");return"/"+n},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,r=t.length;n<r;n++)if(e(t[n]))return!0}else if("object"==typeof t){var o=i(t),a=o.length;for(n=0;n<a;n++)if(e(t[o[n]]))return!0}return!1};var c=function(e){function t(t,n,r,o,i){e.call(this,u(t,{name:n,index:r,operation:o,tree:i})),this.name=n,this.index=r,this.operation=o,this.tree=i,this.message=u(t,{name:n,index:r,operation:o,tree:i})}return n(t,e),t}(Error);t.PatchError=c},function(e,t,n){var r=n(60),o=n(203),i=n(79),a=n(154),s=n(940);e.exports=function(e,t){var n=1==e,u=2==e,c=3==e,l=4==e,p=6==e,f=5==e||p,h=t||s;return function(t,s,d){for(var m,v,g=i(t),y=o(g),b=r(s,d,3),_=a(y.length),w=0,x=n?h(t,_):u?h(t,0):void 0;_>w;w++)if((f||w in y)&&(v=b(m=y[w],w,g),e))if(n)x[w]=v;else if(v)switch(e){case 3:return!0;case 5:return m;case 6:return w;case 2:x.push(m)}else if(l)return!1;return p?-1:c||l?l:x}}},function(e,t,n){"use strict";function r(e,t,n,r,o){this.src=e,this.env=r,this.options=n,this.parser=t,this.tokens=o,this.pos=0,this.posMax=this.src.length,this.level=0,this.pending="",this.pendingLevel=0,this.cache=[],this.isInLabel=!1,this.linkLevel=0,this.linkContent="",this.labelUnmatchedScopes=0}r.prototype.pushPending=function(){this.tokens.push({type:"text",content:this.pending,level:this.pendingLevel}),this.pending=""},r.prototype.push=function(e){this.pending&&this.pushPending(),this.tokens.push(e),this.pendingLevel=this.level},r.prototype.cacheSet=function(e,t){for(var n=this.cache.length;n<=e;n++)this.cache.push(0);this.cache[e]=t},r.prototype.cacheGet=function(e){return e<this.cache.length?this.cache[e]:0},e.exports=r},function(e,t,n){var r=n(594)("toUpperCase");e.exports=r},function(e,t,n){var r=n(218),o="Expected a function";function i(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new TypeError(o);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(i.Cache||r),n}i.Cache=r,e.exports=i},function(e,t,n){var r=n(628)(n(665));e.exports=r},function(e,t,n){"use strict";n.r(t);var r=n(266),o=n(42),i=n(269);t.default=function(e){return{statePlugins:{err:{reducers:Object(r.default)(e),actions:o,selectors:i}}}}},function(e,t,n){"use strict";n.r(t);var r=n(2),o=n.n(r),i=n(16),a=n.n(i),s=n(42),u=n(1),c=n(94),l={line:0,level:"error",message:"Unknown error"};t.default=function(e){var t;return t={},o()(t,s.NEW_THROWN_ERR,function(t,n){var r=n.payload,o=a()(l,r,{type:"thrown"});return t.update("errors",function(e){return(e||Object(u.List)()).push(Object(u.fromJS)(o))}).update("errors",function(t){return Object(c.default)(t,e.getSystem())})}),o()(t,s.NEW_THROWN_ERR_BATCH,function(t,n){var r=n.payload;return r=r.map(function(e){return Object(u.fromJS)(a()(l,e,{type:"thrown"}))}),t.update("errors",function(e){return(e||Object(u.List)()).concat(Object(u.fromJS)(r))}).update("errors",function(t){return Object(c.default)(t,e.getSystem())})}),o()(t,s.NEW_SPEC_ERR,function(t,n){var r=n.payload,o=Object(u.fromJS)(r);return o=o.set("type","spec"),t.update("errors",function(e){return(e||Object(u.List)()).push(Object(u.fromJS)(o)).sortBy(function(e){return e.get("line")})}).update("errors",function(t){return Object(c.default)(t,e.getSystem())})}),o()(t,s.NEW_SPEC_ERR_BATCH,function(t,n){var r=n.payload;return r=r.map(function(e){return Object(u.fromJS)(a()(l,e,{type:"spec"}))}),t.update("errors",function(e){return(e||Object(u.List)()).concat(Object(u.fromJS)(r))}).update("errors",function(t){return Object(c.default)(t,e.getSystem())})}),o()(t,s.NEW_AUTH_ERR,function(t,n){var r=n.payload,o=Object(u.fromJS)(a()({},r));return o=o.set("type","auth"),t.update("errors",function(e){return(e||Object(u.List)()).push(Object(u.fromJS)(o))}).update("errors",function(t){return Object(c.default)(t,e.getSystem())})}),o()(t,s.CLEAR,function(e,t){var n=t.payload;if(!n||!e.get("errors"))return e;var r=e.get("errors").filter(function(e){return e.keySeq().every(function(t){var r=e.get(t),o=n[t];return!o||r!==o})});return e.merge({errors:r})}),o()(t,s.CLEAR_BY,function(e,t){var n=t.payload;if(!n||"function"!=typeof n)return e;var r=e.get("errors").filter(function(e){return n(e)});return e.merge({errors:r})}),t}},function(e,t,n){"use strict";function r(e){return e.map(function(e){var t=e.get("message").indexOf("is not of a type(s)");if(t>-1){var n=e.get("message").slice(t+"is not of a type(s)".length).split(",");return e.set("message",e.get("message").slice(0,t)+function(e){return e.reduce(function(e,t,n,r){return n===r.length-1&&r.length>1?e+"or "+t:r[n+1]&&r.length>2?e+t+", ":r[n+1]?e+t+" ":e+t},"should be a")}(n))}return e})}n.r(t),n.d(t,"transform",function(){return r})},function(e,t,n){"use strict";n.r(t),n.d(t,"transform",function(){return r});n(91),n(1);function r(e,t){t.jsSpec;return e}},function(e,t,n){"use strict";n.r(t),n.d(t,"allErrors",function(){return i}),n.d(t,"lastError",function(){return a});var r=n(1),o=n(11),i=Object(o.createSelector)(function(e){return e},function(e){return e.get("errors",Object(r.List)())}),a=Object(o.createSelector)(i,function(e){return e.last()})},function(e,t,n){"use strict";n.r(t);var r=n(271),o=n(74),i=n(272);t.default=function(){return{statePlugins:{layout:{reducers:r.default,actions:o,selectors:i}}}}},function(e,t,n){"use strict";n.r(t);var r,o=n(2),i=n.n(o),a=n(1),s=n(74);t.default=(r={},i()(r,s.UPDATE_LAYOUT,function(e,t){return e.set("layout",t.payload)}),i()(r,s.UPDATE_FILTER,function(e,t){return e.set("filter",t.payload)}),i()(r,s.SHOW,function(e,t){var n=t.payload.shown,r=Object(a.fromJS)(t.payload.thing);return e.update("shown",Object(a.fromJS)({}),function(e){return e.set(r,n)})}),i()(r,s.UPDATE_MODE,function(e,t){var n=t.payload.thing,r=t.payload.mode;return e.setIn(["modes"].concat(n),(r||"")+"")}),r)},function(e,t,n){"use strict";n.r(t),n.d(t,"current",function(){return u}),n.d(t,"currentFilter",function(){return c}),n.d(t,"isShown",function(){return l}),n.d(t,"whatMode",function(){return p}),n.d(t,"showSummary",function(){return f});var r=n(12),o=n.n(r),i=n(11),a=n(3),s=n(1),u=function(e){return e.get("layout")},c=function(e){return e.get("filter")},l=function(e,t,n){return t=Object(a.u)(t),e.get("shown",Object(s.fromJS)({})).get(Object(s.fromJS)(t),n)},p=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return t=Object(a.u)(t),e.getIn(["modes"].concat(o()(t)),n)},f=Object(i.createSelector)(function(e){return e},function(e){return!l(e,"editor")})},function(e,t,n){"use strict";n.r(t);var r=n(274),o=n(29),i=n(66),a=n(276);t.default=function(){return{statePlugins:{spec:{wrapActions:a,reducers:r.default,actions:o,selectors:i}}}}},function(e,t,n){"use strict";n.r(t);var r,o=n(2),i=n.n(o),a=n(16),s=n.n(a),u=n(12),c=n.n(u),l=n(1),p=n(3),f=n(18),h=n.n(f),d=n(66),m=n(29);t.default=(r={},i()(r,m.UPDATE_SPEC,function(e,t){return"string"==typeof t.payload?e.set("spec",t.payload):e}),i()(r,m.UPDATE_URL,function(e,t){return e.set("url",t.payload+"")}),i()(r,m.UPDATE_JSON,function(e,t){return e.set("json",Object(p.h)(t.payload))}),i()(r,m.UPDATE_RESOLVED,function(e,t){return e.setIn(["resolved"],Object(p.h)(t.payload))}),i()(r,m.UPDATE_RESOLVED_SUBTREE,function(e,t){var n=t.payload,r=n.value,o=n.path;return e.setIn(["resolvedSubtrees"].concat(c()(o)),Object(p.h)(r))}),i()(r,m.UPDATE_PARAM,function(e,t){var n=t.payload,r=n.path,o=n.paramName,i=n.paramIn,a=n.param,s=n.value,u=n.isXml,l=a?Object(p.z)(a):"".concat(i,".").concat(o),f=u?"value_xml":"value";return e.setIn(["meta","paths"].concat(c()(r),["parameters",l,f]),s)}),i()(r,m.UPDATE_EMPTY_PARAM_INCLUSION,function(e,t){var n=t.payload,r=n.pathMethod,o=n.paramName,i=n.paramIn,a=n.includeEmptyValue;if(!o||!i)return console.warn("Warning: UPDATE_EMPTY_PARAM_INCLUSION could not generate a paramKey."),e;var s="".concat(i,".").concat(o);return e.setIn(["meta","paths"].concat(c()(r),["parameter_inclusions",s]),a)}),i()(r,m.VALIDATE_PARAMS,function(e,t){var n=t.payload,r=n.pathMethod,o=n.isOAS3,i=Object(d.specJsonWithResolvedSubtrees)(e).getIn(["paths"].concat(c()(r))),a=Object(d.parameterValues)(e,r).toJS();return e.updateIn(["meta","paths"].concat(c()(r),["parameters"]),Object(l.fromJS)({}),function(t){return i.get("parameters",Object(l.List)()).reduce(function(t,n){var i=Object(p.A)(n,a),s=Object(d.parameterInclusionSettingFor)(e,r,n.get("name"),n.get("in")),u=Object(p.I)(n,i,{bypassRequiredCheck:s,isOAS3:o});return t.setIn([Object(p.z)(n),"errors"],Object(l.fromJS)(u))},t)})}),i()(r,m.CLEAR_VALIDATE_PARAMS,function(e,t){var n=t.payload.pathMethod;return e.updateIn(["meta","paths"].concat(c()(n),["parameters"]),Object(l.fromJS)([]),function(e){return e.map(function(e){return e.set("errors",Object(l.fromJS)([]))})})}),i()(r,m.SET_RESPONSE,function(e,t){var n,r=t.payload,o=r.res,i=r.path,a=r.method;(n=o.error?s()({error:!0,name:o.err.name,message:o.err.message,statusCode:o.err.statusCode},o.err.response):o).headers=n.headers||{};var u=e.setIn(["responses",i,a],Object(p.h)(n));return h.a.Blob&&o.data instanceof h.a.Blob&&(u=u.setIn(["responses",i,a,"text"],o.data)),u}),i()(r,m.SET_REQUEST,function(e,t){var n=t.payload,r=n.req,o=n.path,i=n.method;return e.setIn(["requests",o,i],Object(p.h)(r))}),i()(r,m.SET_MUTATED_REQUEST,function(e,t){var n=t.payload,r=n.req,o=n.path,i=n.method;return e.setIn(["mutatedRequests",o,i],Object(p.h)(r))}),i()(r,m.UPDATE_OPERATION_META_VALUE,function(e,t){var n=t.payload,r=n.path,o=n.value,i=n.key,a=["paths"].concat(c()(r)),s=["meta","paths"].concat(c()(r));return e.getIn(["json"].concat(c()(a)))||e.getIn(["resolved"].concat(c()(a)))||e.getIn(["resolvedSubtrees"].concat(c()(a)))?e.setIn([].concat(c()(s),[i]),Object(l.fromJS)(o)):e}),i()(r,m.CLEAR_RESPONSE,function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["responses",r,o])}),i()(r,m.CLEAR_REQUEST,function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["requests",r,o])}),i()(r,m.SET_SCHEME,function(e,t){var n=t.payload,r=n.scheme,o=n.path,i=n.method;return o&&i?e.setIn(["scheme",o,i],r):o||i?void 0:e.setIn(["scheme","_defaultScheme"],r)}),r)},function(e,t,n){var r=n(81),o=n(35),i=n(63),a="[object String]";e.exports=function(e){return"string"==typeof e||!o(e)&&i(e)&&r(e)==a}},function(e,t,n){"use strict";n.r(t),n.d(t,"updateSpec",function(){return s}),n.d(t,"updateJsonSpec",function(){return u}),n.d(t,"executeRequest",function(){return c}),n.d(t,"validateParams",function(){return l});var r=n(17),o=n.n(r),i=n(91),a=n.n(i),s=function(e,t){var n=t.specActions;return function(){e.apply(void 0,arguments),n.parseToJson.apply(n,arguments)}},u=function(e,t){var n=t.specActions;return function(){for(var t=arguments.length,r=new Array(t),i=0;i<t;i++)r[i]=arguments[i];e.apply(void 0,r),n.invalidateResolvedSubtreeCache();var s=r[0],u=a()(s,["paths"])||{},c=o()(u);c.forEach(function(e){a()(u,[e]).$ref&&n.requestResolvedSubtree(["paths",e])}),n.requestResolvedSubtree(["components","securitySchemes"])}},c=function(e,t){var n=t.specActions;return function(t){return n.logRequest(t),e(t)}},l=function(e,t){var n=t.specSelectors;return function(t){return e(t,n.isOAS3())}}},function(e,t,n){"use strict";n.r(t);var r=n(145),o=n(3);t.default=function(e){var t=e.getComponents,n=e.getStore,i=e.getSystem,a=r.getComponent,s=r.render,u=r.makeMappedContainer,c=Object(o.t)(a.bind(null,i,n,t));return{rootInjects:{getComponent:c,makeMappedContainer:Object(o.t)(u.bind(null,i,n,c,t)),render:s.bind(null,i,n,a,t)}}}},function(e,t,n){"use strict";n.r(t);var r=n(116);t.default=function(){return{fn:r}}},function(e,t,n){"use strict";n.r(t),t.default=function(e){var t=e.configs,n={debug:0,info:1,log:2,warn:3,error:4},r=function(e){return n[e]||-1},o=t.logLevel,i=r(o);function a(e){for(var t,n=arguments.length,o=new Array(n>1?n-1:0),a=1;a<n;a++)o[a-1]=arguments[a];r(e)>=i&&(t=console)[e].apply(t,o)}return a.warn=a.bind(null,"warn"),a.error=a.bind(null,"error"),a.info=a.bind(null,"info"),a.debug=a.bind(null,"debug"),{rootInjects:{log:a}}}},function(e,t,n){"use strict";n.r(t);var r=n(53),o=n.n(r),i=n(281);t.default=function(e){var t=e.configs,n=e.getConfigs;return{fn:{fetch:o.a.makeHttp(t.preFetch,t.postFetch),buildRequest:o.a.buildRequest,execute:o.a.execute,resolve:o.a.resolve,resolveSubtree:function(e,t,r){if(void 0===r){var i=n();r={modelPropertyMacro:i.modelPropertyMacro,parameterMacro:i.parameterMacro,requestInterceptor:i.requestInterceptor,responseInterceptor:i.responseInterceptor}}for(var a=arguments.length,s=new Array(a>3?a-3:0),u=3;u<a;u++)s[u-3]=arguments[u];return o.a.resolveSubtree.apply(o.a,[e,t,r].concat(s))},serializeRes:o.a.serializeRes,opId:o.a.helpers.opId},statePlugins:{configs:{wrapActions:i}}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"loaded",function(){return r});var r=function(e,t){return function(){e.apply(void 0,arguments);var n=t.getConfigs().withCredentials;void 0!==n&&(t.fn.fetch.withCredentials="string"==typeof n?"true"===n:!!n)}}},function(e,t,n){"use strict";n.r(t),n.d(t,"preauthorizeBasic",function(){return c}),n.d(t,"preauthorizeApiKey",function(){return l});var r=n(2),o=n.n(r),i=n(283),a=n(67),s=n(284),u=n(285);function c(e,t,n,r){var i=e.authActions.authorize,a=e.specSelectors,s=a.specJson,u=(0,a.isOAS3)()?["components","securitySchemes"]:["securityDefinitions"],c=s().getIn([].concat(u,[t]));return c?i(o()({},t,{value:{username:n,password:r},schema:c.toJS()})):null}function l(e,t,n){var r=e.authActions.authorize,i=e.specSelectors,a=i.specJson,s=(0,i.isOAS3)()?["components","securitySchemes"]:["securityDefinitions"],u=a().getIn([].concat(s,[t]));return u?r(o()({},t,{value:n,schema:u.toJS()})):null}t.default=function(){return{afterLoad:function(e){this.rootInjects=this.rootInjects||{},this.rootInjects.initOAuth=e.authActions.configureAuth,this.rootInjects.preauthorizeApiKey=l.bind(null,e),this.rootInjects.preauthorizeBasic=c.bind(null,e)},statePlugins:{auth:{reducers:i.default,actions:a,selectors:s},spec:{wrapActions:u}}}}},function(e,t,n){"use strict";n.r(t);var r,o=n(2),i=n.n(o),a=n(16),s=n.n(a),u=n(13),c=n.n(u),l=n(1),p=n(3),f=n(67);t.default=(r={},i()(r,f.SHOW_AUTH_POPUP,function(e,t){var n=t.payload;return e.set("showDefinitions",n)}),i()(r,f.AUTHORIZE,function(e,t){var n=t.payload,r=Object(l.fromJS)(n),o=e.get("authorized")||Object(l.Map)();return r.entrySeq().forEach(function(e){var t=c()(e,2),n=t[0],r=t[1],i=r.getIn(["schema","type"]);if("apiKey"===i||"http"===i)o=o.set(n,r);else if("basic"===i){var a=r.getIn(["value","username"]),s=r.getIn(["value","password"]);o=(o=o.setIn([n,"value"],{username:a,header:"Basic "+Object(p.a)(a+":"+s)})).setIn([n,"schema"],r.get("schema"))}}),e.set("authorized",o)}),i()(r,f.AUTHORIZE_OAUTH2,function(e,t){var n,r=t.payload,o=r.auth,i=r.token;return o.token=s()({},i),n=Object(l.fromJS)(o),e.setIn(["authorized",n.get("name")],n)}),i()(r,f.LOGOUT,function(e,t){var n=t.payload,r=e.get("authorized").withMutations(function(e){n.forEach(function(t){e.delete(t)})});return e.set("authorized",r)}),i()(r,f.CONFIGURE_AUTH,function(e,t){var n=t.payload;return e.set("configs",n)}),r)},function(e,t,n){"use strict";n.r(t),n.d(t,"shownDefinitions",function(){return l}),n.d(t,"definitionsToAuthorize",function(){return p}),n.d(t,"getDefinitionsByNames",function(){return f}),n.d(t,"definitionsForRequirements",function(){return h}),n.d(t,"authorized",function(){return d}),n.d(t,"isAuthorized",function(){return m}),n.d(t,"getConfigs",function(){return v});var r=n(17),o=n.n(r),i=n(13),a=n.n(i),s=n(11),u=n(1),c=function(e){return e},l=Object(s.createSelector)(c,function(e){return e.get("showDefinitions")}),p=Object(s.createSelector)(c,function(){return function(e){var t=e.specSelectors.securityDefinitions()||Object(u.Map)({}),n=Object(u.List)();return t.entrySeq().forEach(function(e){var t=a()(e,2),r=t[0],o=t[1],i=Object(u.Map)();i=i.set(r,o),n=n.push(i)}),n}}),f=function(e,t){return function(e){var n=e.specSelectors;console.warn("WARNING: getDefinitionsByNames is deprecated and will be removed in the next major version.");var r=n.securityDefinitions(),o=Object(u.List)();return t.valueSeq().forEach(function(e){var t=Object(u.Map)();e.entrySeq().forEach(function(e){var n,o=a()(e,2),i=o[0],s=o[1],u=r.get(i);"oauth2"===u.get("type")&&s.size&&((n=u.get("scopes")).keySeq().forEach(function(e){s.contains(e)||(n=n.delete(e))}),u=u.set("allowedScopes",n)),t=t.set(i,u)}),o=o.push(t)}),o}},h=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Object(u.List)();return function(e){return(e.authSelectors.definitionsToAuthorize()||Object(u.List)()).filter(function(e){return t.some(function(t){return t.get(e.keySeq().first())})})}},d=Object(s.createSelector)(c,function(e){return e.get("authorized")||Object(u.Map)()}),m=function(e,t){return function(e){var n=e.authSelectors.authorized();return u.List.isList(t)?!!t.toJS().filter(function(e){return-1===o()(e).map(function(e){return!!n.get(e)}).indexOf(!1)}).length:null}},v=Object(s.createSelector)(c,function(e){return e.get("configs")})},function(e,t,n){"use strict";n.r(t),n.d(t,"execute",function(){return y});var r=n(51),o=n.n(r),i=n(92),a=n.n(i),s=n(57),u=n.n(s),c=n(58),l=n.n(c),p=n(52),f=n.n(p),h=n(17),d=n.n(h),m=n(2),v=n.n(m);function g(e,t){var n=d()(e);if(f.a){var r=f()(e);t&&(r=r.filter(function(t){return l()(e,t).enumerable})),n.push.apply(n,r)}return n}var y=function(e,t){var n=t.authSelectors,r=t.specSelectors;return function(t){var i=t.path,s=t.method,c=t.operation,p=t.extras,f={authorized:n.authorized()&&n.authorized().toJS(),definitions:r.securityDefinitions()&&r.securityDefinitions().toJS(),specSecurity:r.security()&&r.security().toJS()};return e(function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?g(n,!0).forEach(function(t){v()(e,t,n[t])}):u.a?a()(e,u()(n)):g(n).forEach(function(t){o()(e,t,l()(n,t))})}return e}({path:i,method:s,operation:c,securities:f},p))}}},function(e,t,n){"use strict";n.r(t);var r=n(3);t.default=function(){return{fn:{shallowEqualKeys:r.E}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return p});var r=n(28),o=n.n(r),i=n(16),a=n.n(i),s=n(11),u=n(1),c=n(18),l=n.n(c);function p(e){var t=e.fn;return{statePlugins:{spec:{actions:{download:function(e){return function(n){var r=n.errActions,o=n.specSelectors,i=n.specActions,s=n.getConfigs,u=t.fetch,c=s();function p(t){if(t instanceof Error||t.status>=400)return i.updateLoadingStatus("failed"),r.newThrownErr(a()(new Error((t.message||t.statusText)+" "+e),{source:"fetch"})),void(!t.status&&t instanceof Error&&function(){try{var t;if("URL"in l.a?t=new URL(e):(t=document.createElement("a")).href=e,"https:"!==t.protocol&&"https:"===l.a.location.protocol){var n=a()(new Error("Possible mixed-content issue? The page was loaded over https:// but a ".concat(t.protocol,"// URL was specified. Check that you are not attempting to load mixed content.")),{source:"fetch"});return void r.newThrownErr(n)}if(t.origin!==l.a.location.origin){var o=a()(new Error("Possible cross-origin (CORS) issue? The URL origin (".concat(t.origin,") does not match the page (").concat(l.a.location.origin,"). Check the server returns the correct 'Access-Control-Allow-*' headers.")),{source:"fetch"});r.newThrownErr(o)}}catch(e){return}}());i.updateLoadingStatus("success"),i.updateSpec(t.text),o.url()!==e&&i.updateUrl(e)}e=e||o.url(),i.updateLoadingStatus("loading"),r.clear({source:"fetch"}),u({url:e,loadSpec:!0,requestInterceptor:c.requestInterceptor||function(e){return e},responseInterceptor:c.responseInterceptor||function(e){return e},credentials:"same-origin",headers:{Accept:"application/json,*/*"}}).then(p,p)}},updateLoadingStatus:function(e){var t=[null,"loading","failed","success","failedConfig"];return-1===t.indexOf(e)&&console.error("Error: ".concat(e," is not one of ").concat(o()(t))),{type:"spec_update_loading_status",payload:e}}},reducers:{spec_update_loading_status:function(e,t){return"string"==typeof t.payload?e.set("loadingStatus",t.payload):e}},selectors:{loadingStatus:Object(s.createSelector)(function(e){return e||Object(u.Map)()},function(e){return e.get("loadingStatus")||null})}}}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"downloadConfig",function(){return o}),n.d(t,"getConfigByUrl",function(){return i});var r=n(144),o=function(e){return function(t){return(0,t.fn.fetch)(e)}},i=function(e,t){return function(n){var o=n.specActions;if(e)return o.downloadConfig(e).then(i,i);function i(n){n instanceof Error||n.status>=400?(o.updateLoadingStatus("failedConfig"),o.updateLoadingStatus("failedConfig"),o.updateUrl(""),console.error(n.statusText+" "+e.url),t(null)):t(Object(r.parseYamlConfig)(n.text))}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"get",function(){return i});var r=n(14),o=n.n(r),i=function(e,t){return e.getIn(o()(t)?t:[t])}},function(e,t,n){"use strict";n.r(t);var r,o=n(2),i=n.n(o),a=n(1),s=n(117);t.default=(r={},i()(r,s.UPDATE_CONFIGS,function(e,t){return e.merge(Object(a.fromJS)(t.payload))}),i()(r,s.TOGGLE_CONFIGS,function(e,t){var n=t.payload,r=e.get(n);return e.set(n,!r)}),r)},function(e,t,n){"use strict";n.r(t);var r=n(292),o=n(293),i=n(294);t.default=function(){return[r.default,{statePlugins:{configs:{wrapActions:{loaded:function(e,t){return function(){e.apply(void 0,arguments);var n=decodeURIComponent(window.location.hash);t.layoutActions.parseDeepLinkHash(n)}}}}},wrapComponents:{operation:o.default,OperationTag:i.default}}]}},function(e,t,n){"use strict";n.r(t),n.d(t,"show",function(){return v}),n.d(t,"scrollTo",function(){return g}),n.d(t,"parseDeepLinkHash",function(){return y}),n.d(t,"readyToScroll",function(){return b}),n.d(t,"scrollToElement",function(){return _}),n.d(t,"clearScrollTo",function(){return w});var r,o=n(2),i=n.n(o),a=n(13),s=n.n(a),u=n(14),c=n.n(u),l=n(146),p=n(474),f=n.n(p),h=n(3),d=n(1),m=n.n(d),v=function(e,t){var n=t.getConfigs,r=t.layoutSelectors;return function(){for(var t=arguments.length,o=new Array(t),i=0;i<t;i++)o[i]=arguments[i];if(e.apply(void 0,o),n().deepLinking)try{var a=o[0],u=o[1];a=c()(a)?a:[a];var p=r.urlHashArrayFromIsShownKey(a);if(!p.length)return;var f=s()(p,2),d=f[0],m=f[1];if(!u)return Object(l.setHash)("/");2===p.length?Object(l.setHash)(Object(h.c)("/".concat(encodeURIComponent(d),"/").concat(encodeURIComponent(m)))):1===p.length&&Object(l.setHash)(Object(h.c)("/".concat(encodeURIComponent(d))))}catch(e){console.error(e)}}},g=function(e){return{type:"layout_scroll_to",payload:c()(e)?e:[e]}},y=function(e){return function(t){var n=t.layoutActions,r=t.layoutSelectors;if((0,t.getConfigs)().deepLinking&&e){var o=e.slice(1);"!"===o[0]&&(o=o.slice(1)),"/"===o[0]&&(o=o.slice(1));var i=o.split("/").map(function(e){return e||""}),a=r.isShownKeyFromUrlHashArray(i),u=s()(a,3),c=u[0],l=u[1],p=void 0===l?"":l,f=u[2],h=void 0===f?"":f;if("operations"===c){var d=r.isShownKeyFromUrlHashArray([p]);p.indexOf("_")>-1&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(d.map(function(e){return e.replace(/_/g," ")}),!0)),n.show(d,!0)}(p.indexOf("_")>-1||h.indexOf("_")>-1)&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(a.map(function(e){return e.replace(/_/g," ")}),!0)),n.show(a,!0),n.scrollTo(a)}}},b=function(e,t){return function(n){var r=n.layoutSelectors.getScrollToKey();m.a.is(r,Object(d.fromJS)(e))&&(n.layoutActions.scrollToElement(t),n.layoutActions.clearScrollTo())}},_=function(e,t){return function(n){try{t=t||n.fn.getScrollParent(e),f.a.createScroller(t).to(e)}catch(e){console.error(e)}}},w=function(){return{type:"layout_clear_scroll"}};t.default={fn:{getScrollParent:function(e,t){var n=document.documentElement,r=getComputedStyle(e),o="absolute"===r.position,i=t?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===r.position)return n;for(var a=e;a=a.parentElement;)if(r=getComputedStyle(a),(!o||"static"!==r.position)&&i.test(r.overflow+r.overflowY+r.overflowX))return a;return n}},statePlugins:{layout:{actions:{scrollToElement:_,scrollTo:g,clearScrollTo:w,readyToScroll:b,parseDeepLinkHash:y},selectors:{getScrollToKey:function(e){return e.get("scrollToKey")},isShownKeyFromUrlHashArray:function(e,t){var n=s()(t,2),r=n[0],o=n[1];return o?["operations",r,o]:r?["operations-tag",r]:[]},urlHashArrayFromIsShownKey:function(e,t){var n=s()(t,3),r=n[0],o=n[1],i=n[2];return"operations"==r?[o,i]:"operations-tag"==r?[o]:[]}},reducers:(r={},i()(r,"layout_scroll_to",function(e,t){return e.set("scrollToKey",m.a.fromJS(t.payload))}),i()(r,"layout_clear_scroll",function(e){return e.delete("scrollToKey")}),r),wrapActions:{show:v}}}}},function(e,t,n){"use strict";n.r(t);var r=n(4),o=n.n(r),i=n(5),a=n.n(i),s=n(6),u=n.n(s),c=n(7),l=n.n(c),p=n(9),f=n.n(p),h=n(8),d=n.n(h),m=n(2),v=n.n(m),g=n(0),y=n.n(g);n(19);t.default=function(e,t){return function(n){function r(){var e,n;o()(this,r);for(var i=arguments.length,a=new Array(i),s=0;s<i;s++)a[s]=arguments[s];return n=u()(this,(e=l()(r)).call.apply(e,[this].concat(a))),v()(f()(n),"onLoad",function(e){var r=n.props.operation.toObject(),o=["operations",r.tag,r.operationId];t.layoutActions.readyToScroll(o,e)}),n}return d()(r,n),a()(r,[{key:"render",value:function(){return y.a.createElement("span",{ref:this.onLoad},y.a.createElement(e,this.props))}}]),r}(y.a.Component)}},function(e,t,n){"use strict";n.r(t);var r=n(4),o=n.n(r),i=n(5),a=n.n(i),s=n(6),u=n.n(s),c=n(7),l=n.n(c),p=n(9),f=n.n(p),h=n(8),d=n.n(h),m=n(2),v=n.n(m),g=n(0),y=n.n(g);n(10);t.default=function(e,t){return function(n){function r(){var e,n;o()(this,r);for(var i=arguments.length,a=new Array(i),s=0;s<i;s++)a[s]=arguments[s];return n=u()(this,(e=l()(r)).call.apply(e,[this].concat(a))),v()(f()(n),"onLoad",function(e){var r=["operations-tag",n.props.tag];t.layoutActions.readyToScroll(r,e)}),n}return d()(r,n),a()(r,[{key:"render",value:function(){return y.a.createElement("span",{ref:this.onLoad},y.a.createElement(e,this.props))}}]),r}(y.a.Component)}},function(e,t,n){"use strict";n.r(t);var r=n(296);t.default=function(){return{fn:{opsFilter:r.default}}}},function(e,t,n){"use strict";n.r(t),t.default=function(e,t){return e.filter(function(e,n){return-1!==n.indexOf(t)})}},function(e,t,n){"use strict";n.r(t);var r=!1;t.default=function(){return{statePlugins:{spec:{wrapActions:{updateSpec:function(e){return function(){return r=!0,e.apply(void 0,arguments)}},updateJsonSpec:function(e,t){return function(){var n=t.getConfigs().onComplete;return r&&"function"==typeof n&&(setTimeout(n,0),r=!1),e.apply(void 0,arguments)}}}}}}}},function(e,t,n){"use strict";n.r(t);var r=n(299),o=n(300),i=n(301),a=n(302),s=n(311),u=n(59),c=n(318),l=n(319);t.default=function(){return{components:a.default,wrapComponents:s.default,statePlugins:{spec:{wrapSelectors:r,selectors:i},auth:{wrapSelectors:o},oas3:{actions:u,reducers:l.default,selectors:c}}}}},function(e,t,n){"use strict";n.r(t),n.d(t,"definitions",function(){return h}),n.d(t,"hasHost",function(){return d}),n.d(t,"securityDefinitions",function(){return m}),n.d(t,"host",function(){return v}),n.d(t,"basePath",function(){return g}),n.d(t,"consumes",function(){return y}),n.d(t,"produces",function(){return b}),n.d(t,"schemes",function(){return _}),n.d(t,"servers",function(){return w}),n.d(t,"isOAS3",function(){return x}),n.d(t,"isSwagger2",function(){return E});var r=n(11),o=n(66),i=n(1),a=n(24);function s(e){return function(t,n){return function(){var r=n.getSystem().specSelectors.specJson();return Object(a.isOAS3)(r)?e.apply(void 0,arguments):t.apply(void 0,arguments)}}}var u=function(e){return e||Object(i.Map)()},c=s(Object(r.createSelector)(function(){return null})),l=Object(r.createSelector)(u,function(e){return e.get("json",Object(i.Map)())}),p=Object(r.createSelector)(u,function(e){return e.get("resolved",Object(i.Map)())}),f=function(e){var t=p(e);return t.count()<1&&(t=l(e)),t},h=s(Object(r.createSelector)(f,function(e){var t=e.getIn(["components","schemas"]);return i.Map.isMap(t)?t:Object(i.Map)()})),d=s(function(e){return f(e).hasIn(["servers",0])}),m=s(Object(r.createSelector)(o.specJsonWithResolvedSubtrees,function(e){return e.getIn(["components","securitySchemes"])||null})),v=c,g=c,y=c,b=c,_=c,w=s(Object(r.createSelector)(f,function(e){return e.getIn(["servers"])||Object(i.Map)()})),x=function(e,t){return function(){var e=t.getSystem().specSelectors.specJson();return Object(a.isOAS3)(i.Map.isMap(e)?e:Object(i.Map)())}},E=function(e,t){return function(){var e=t.getSystem().specSelectors.specJson();return Object(a.isSwagger2)(i.Map.isMap(e)?e:Object(i.Map)())}}},function(e,t,n){"use strict";n.r(t),n.d(t,"definitionsToAuthorize",function(){return p});var r=n(2),o=n.n(r),i=n(13),a=n.n(i),s=n(11),u=n(1),c=n(24);var l,p=(l=Object(s.createSelector)(function(e){return e},function(e){return e.specSelectors.securityDefinitions()},function(e,t){var n=Object(u.List)();return t?(t.entrySeq().forEach(function(e){var t=a()(e,2),r=t[0],i=t[1],s=i.get("type");"oauth2"===s&&i.get("flows").entrySeq().forEach(function(e){var t=a()(e,2),s=t[0],c=t[1],l=Object(u.fromJS)({flow:s,authorizationUrl:c.get("authorizationUrl"),tokenUrl:c.get("tokenUrl"),scopes:c.get("scopes"),type:i.get("type")});n=n.push(new u.Map(o()({},r,l.filter(function(e){return void 0!==e}))))}),"http"!==s&&"apiKey"!==s||(n=n.push(new u.Map(o()({},r,i))))}),n):n}),function(e,t){return function(n){for(var r=t.getSystem().specSelectors.specJson(),o=arguments.length,i=new Array(o>1?o-1:0),a=1;a<o;a++)i[a-1]=arguments[a];return Object(c.isOAS3)(r)?l.apply(void 0,[t].concat(i)):e.apply(void 0,i)}})},function(e,t,n){"use strict";n.r(t),n.d(t,"servers",function(){return l}),n.d(t,"isSwagger2",function(){return p});var r=n(11),o=n(1),i=n(24);var a,s=function(e){return e||Object(o.Map)()},u=Object(r.createSelector)(s,function(e){return e.get("json",Object(o.Map)())}),c=Object(r.createSelector)(s,function(e){return e.get("resolved",Object(o.Map)())}),l=(a=Object(r.createSelector)(function(e){var t=c(e);return t.count()<1&&(t=u(e)),t},function(e){return e.getIn(["servers"])||Object(o.Map)()}),function(){return function(e){var t=e.getSystem().specSelectors.specJson();if(Object(i.isOAS3)(t)){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return a.apply(void 0,r)}return null}}),p=function(e,t){return function(){var e=t.getSystem().specSelectors.specJson();return Object(i.isSwagger2)(e)}}},function(e,t,n){"use strict";n.r(t);var r=n(303),o=n(304),i=n(305),a=n(306),s=n(307),u=n(308),c=n(309),l=n(310);t.default={Callbacks:r.default,HttpAuth:c.default,RequestBody:o.default,Servers:a.default,ServersContainer:s.default,RequestBodyEditor:u.default,OperationServers:l.default,operationLink:i.default}},function(e,t,n){"use strict";n.r(t);var r=n(20),o=n.n(r),i=n(0),a=n.n(i),s=(n(10),n(19),n(1));t.default=function(e){var t=e.callbacks,n=e.getComponent,r=e.specPath,i=n("OperationContainer",!0);if(!t)return a.a.createElement("span",null,"No callbacks");var u=t.map(function(t,n){return a.a.createElement("div",{key:n},a.a.createElement("h2",null,n),t.map(function(t,u){return"$$ref"===u?null:a.a.createElement("div",{key:u},t.map(function(t,c){if("$$ref"===c)return null;var l=Object(s.fromJS)({operation:t});return a.a.createElement(i,o()({},e,{op:l,key:c,tag:"",method:c,path:u,specPath:r.push(n,u,c),allowTryItOut:!1}))}))}))});return a.a.createElement("div",null,u)}},function(e,t,n){"use strict";n.r(t);var r=n(0),o=n.n(r),i=(n(10),n(19),n(1)),a=n(3);function s(e,t,n){var r=e.getIn(["content",t]),o=r.get("schema").toJS(),i=void 0!==r.get("example")?Object(a.G)(r.get("example")):null,s=r.getIn(["examples",n,"value"]);return r.get("examples")?Object(a.G)(s)||"":Object(a.G)(i||Object(a.m)(o,t,{includeWriteOnly:!0})||"")}t.default=function(e){var t=e.requestBody,n=e.requestBodyValue,r=e.getComponent,u=e.getConfigs,c=e.specSelectors,l=e.fn,p=e.contentType,f=e.isExecute,h=e.specPath,d=e.onChange,m=e.activeExamplesKey,v=e.updateActiveExamplesKey,g=r("Markdown"),y=r("modelExample"),b=r("RequestBodyEditor"),_=r("highlightCode"),w=r("ExamplesSelectValueRetainer"),x=r("Example"),E=u().showCommonExtensions,S=t&&t.get("description")||null,C=t&&t.get("content")||new i.OrderedMap;p=p||C.keySeq().first()||"";var k=C.get(p,Object(i.OrderedMap)()),O=k.get("schema",Object(i.OrderedMap)()),A=k.get("examples",null);if(!k.size)return null;var T="object"===k.getIn(["schema","type"]);if("application/octet-stream"===p||0===p.indexOf("image/")||0===p.indexOf("audio/")||0===p.indexOf("video/")){var j=r("Input");return f?o.a.createElement(j,{type:"file",onChange:function(e){d(e.target.files[0])}}):o.a.createElement("i",null,"Example values are not available for ",o.a.createElement("code",null,"application/octet-stream")," media types.")}if(T&&("application/x-www-form-urlencoded"===p||0===p.indexOf("multipart/"))&&O.get("properties",Object(i.OrderedMap)()).size>0){var P=r("JsonSchemaForm"),I=r("ParameterExt"),M=O.get("properties",Object(i.OrderedMap)());return n=i.Map.isMap(n)?n:Object(i.OrderedMap)(),o.a.createElement("div",{className:"table-container"},S&&o.a.createElement(g,{source:S}),o.a.createElement("table",null,o.a.createElement("tbody",null,M.map(function(e,t){var s=E?Object(a.j)(e):null,u=O.get("required",Object(i.List)()).includes(t),c=e.get("type"),p=e.get("format"),h=e.get("description"),m=n.get(t),v=e.get("default")||e.get("example")||"";""===v&&"object"===c&&(v=Object(a.m)(e,!1,{includeWriteOnly:!0})),"string"!=typeof v&&"object"===c&&(v=Object(a.G)(v));var y="string"===c&&("binary"===p||"base64"===p);return o.a.createElement("tr",{key:t,className:"parameters","data-property-name":t},o.a.createElement("td",{className:"parameters-col_name"},o.a.createElement("div",{className:u?"parameter__name required":"parameter__name"},t,u?o.a.createElement("span",{style:{color:"red"}}," *"):null),o.a.createElement("div",{className:"parameter__type"},c,p&&o.a.createElement("span",{className:"prop-format"},"($",p,")"),E&&s.size?s.map(function(e,t){return o.a.createElement(I,{key:"".concat(t,"-").concat(e),xKey:t,xVal:e})}):null),o.a.createElement("div",{className:"parameter__deprecated"},e.get("deprecated")?"deprecated":null)),o.a.createElement("td",{className:"parameters-col_description"},o.a.createElement(g,{source:h}),f?o.a.createElement("div",null,o.a.createElement(P,{fn:l,dispatchInitialValue:!y,schema:e,description:t,getComponent:r,value:void 0===m?v:m,onChange:function(e){d(e,[t])}})):null))}))))}return o.a.createElement("div",null,S&&o.a.createElement(g,{source:S}),A?o.a.createElement(w,{examples:A,currentKey:m,currentUserInputValue:n,onSelect:function(e){v(e)},updateValue:d,defaultToFirstExample:!0,getComponent:r}):null,f?o.a.createElement("div",null,o.a.createElement(b,{value:n,defaultValue:s(t,p,m),onChange:d,getComponent:r})):o.a.createElement(y,{getComponent:r,getConfigs:u,specSelectors:c,expandDepth:1,isExecute:f,schema:k.get("schema"),specPath:h.push("content",p),example:o.a.createElement(_,{className:"body-param__example",value:Object(a.G)(n)||s(t,p,m)})}),A?o.a.createElement(x,{example:A.get(m),getComponent:r}):null)}},function(e,t,n){"use strict";n.r(t);var r=n(28),o=n.n(r),i=n(4),a=n.n(i),s=n(5),u=n.n(s),c=n(6),l=n.n(c),p=n(7),f=n.n(p),h=n(8),d=n.n(h),m=n(0),v=n.n(m),g=(n(10),n(19),function(e){function t(){return a()(this,t),l()(this,f()(t).apply(this,arguments))}return d()(t,e),u()(t,[{key:"render",value:function(){var e=this.props,t=e.link,n=e.name,r=(0,e.getComponent)("Markdown"),i=t.get("operationId")||t.get("operationRef"),a=t.get("parameters")&&t.get("parameters").toJS(),s=t.get("description");return v.a.createElement("div",{style:{marginBottom:"1.5em"}},v.a.createElement("div",{style:{marginBottom:".5em"}},v.a.createElement("b",null,v.a.createElement("code",null,n)),s?v.a.createElement(r,{source:s}):null),v.a.createElement("pre",null,"Operation `",i,"`",v.a.createElement("br",null),v.a.createElement("br",null),"Parameters ",function(e,t){if("string"!=typeof t)return"";return t.split("\n").map(function(t,n){return n>0?Array(e+1).join(" ")+t:t}).join("\n")}(0,o()(a,null,2))||"{}",v.a.createElement("br",null)))}}]),t}(m.Component));t.default=g},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return _});var r=n(4),o=n.n(r),i=n(5),a=n.n(i),s=n(6),u=n.n(s),c=n(7),l=n.n(c),p=n(9),f=n.n(p),h=n(8),d=n.n(h),m=n(2),v=n.n(m),g=n(0),y=n.n(g),b=n(1),_=(n(10),n(19),function(e){function t(){var e,n;o()(this,t);for(var r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];return n=u()(this,(e=l()(t)).call.apply(e,[this].concat(i))),v()(f()(n),"onServerChange",function(e){n.setServer(e.target.value)}),v()(f()(n),"onServerVariableValueChange",function(e){var t=n.props,r=t.setServerVariableValue,o=t.currentServer,i=e.target.getAttribute("data-variable"),a=e.target.value;"function"==typeof r&&r({server:o,key:i,val:a})}),v()(f()(n),"setServer",function(e){(0,n.props.setSelectedServer)(e)}),n}return d()(t,e),a()(t,[{key:"componentDidMount",value:function(){var e=this.props,t=e.servers;e.currentServer||this.setServer(t.first().get("url"))}},{key:"componentWillReceiveProps",value:function(e){var t=this.props,n=t.servers,r=t.setServerVariableValue,o=t.getServerVariable;if(this.props.currentServer!==e.currentServer){var i=n.find(function(t){return t.get("url")===e.currentServer});if(!i)return this.setServer(n.first().get("url"));(i.get("variables")||Object(b.OrderedMap)()).map(function(t,n){o(e.currentServer,n)||r({server:e.currentServer,key:n,val:t.get("default")||""})})}}},{key:"render",value:function(){var e=this,t=this.props,n=t.servers,r=t.currentServer,o=t.getServerVariable,i=t.getEffectiveServerValue,a=(n.find(function(e){return e.get("url")===r})||Object(b.OrderedMap)()).get("variables")||Object(b.OrderedMap)(),s=0!==a.size;return y.a.createElement("div",{className:"servers"},y.a.createElement("label",{htmlFor:"servers"},y.a.createElement("select",{onChange:this.onServerChange},n.valueSeq().map(function(e){return y.a.createElement("option",{value:e.get("url"),key:e.get("url")},e.get("url"),e.get("description")&&" - ".concat(e.get("description")))}).toArray())),s?y.a.createElement("div",null,y.a.createElement("div",{className:"computed-url"},"Computed URL:",y.a.createElement("code",null,i(r))),y.a.createElement("h4",null,"Server variables"),y.a.createElement("table",null,y.a.createElement("tbody",null,a.map(function(t,n){return y.a.createElement("tr",{key:n},y.a.createElement("td",null,n),y.a.createElement("td",null,t.get("enum")?y.a.createElement("select",{"data-variable":n,onChange:e.onServerVariableValueChange},t.get("enum").map(function(e){return y.a.createElement("option",{selected:e===o(r,n),key:e,value:e},e)})):y.a.createElement("input",{type:"text",value:o(r,n)||"",onChange:e.onServerVariableValueChange,"data-variable":n})))})))):null)}}]),t}(y.a.Component))},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return m});var r=n(4),o=n.n(r),i=n(5),a=n.n(i),s=n(6),u=n.n(s),c=n(7),l=n.n(c),p=n(8),f=n.n(p),h=n(0),d=n.n(h),m=(n(10),function(e){function t(){return o()(this,t),u()(this,l()(t).apply(this,arguments))}return f()(t,e),a()(t,[{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.oas3Selectors,r=e.oas3Actions,o=e.getComponent,i=t.servers(),a=o("Servers");return i&&i.size?d.a.createElement("div",null,d.a.createElement("span",{className:"servers-title"},"Servers"),d.a.createElement(a,{servers:i,currentServer:n.selectedServer(),setSelectedServer:r.setSelectedServer,setServerVariableValue:r.setServerVariableValue,getServerVariable:n.serverVariableValue,getEffectiveServerValue:n.serverEffectiveValue})):null}}]),t}(d.a.Component))},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return w});var r=n(4),o=n.n(r),i=n(5),a=n.n(i),s=n(6),u=n.n(s),c=n(7),l=n.n(c),p=n(9),f=n.n(p),h=n(8),d=n.n(h),m=n(2),v=n.n(m),g=n(0),y=n.n(g),b=(n(10),n(3)),_=Function.prototype,w=function(e){function t(e,n){var r;return o()(this,t),r=u()(this,l()(t).call(this,e,n)),v()(f()(r),"applyDefaultValue",function(e){var t=e||r.props,n=t.onChange,o=t.defaultValue;return r.setState({value:o}),n(o)}),v()(f()(r),"onChange",function(e){r.props.onChange(Object(b.G)(e))}),v()(f()(r),"onDomChange",function(e){var t=e.target.value;r.setState({value:t},function(){return r.onChange(t)})}),r.state={value:Object(b.G)(e.value)||e.defaultValue},e.onChange(e.value),r}return d()(t,e),a()(t,[{key:"componentWillReceiveProps",value:function(e){this.props.value!==e.value&&e.value!==this.state.value&&this.setState({value:Object(b.G)(e.value)}),!e.value&&e.defaultValue&&this.state.value&&this.applyDefaultValue(e)}},{key:"render",value:function(){var e=this.props.getComponent,t=this.state.value,n=e("TextArea");return y.a.createElement("div",{className:"body-param"},y.a.createElement(n,{className:"body-param__text",value:t,onChange:this.onDomChange}))}}]),t}(g.PureComponent);v()(w,"defaultProps",{onChange:_})},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return w});var r=n(16),o=n.n(r),i=n(4),a=n.n(i),s=n(5),u=n.n(s),c=n(6),l=n.n(c),p=n(7),f=n.n(p),h=n(9),d=n.n(h),m=n(8),v=n.n(m),g=n(2),y=n.n(g),b=n(0),_=n.n(b),w=(n(10),function(e){function t(e,n){var r;a()(this,t),r=l()(this,f()(t).call(this,e,n)),y()(d()(r),"onChange",function(e){var t=r.props.onChange,n=e.target,i=n.value,a=n.name,s=o()({},r.state.value);a?s[a]=i:s=i,r.setState({value:s},function(){return t(r.state)})});var i=r.props,s=i.name,u=i.schema,c=r.getValue();return r.state={name:s,schema:u,value:c},r}return v()(t,e),u()(t,[{key:"getValue",value:function(){var e=this.props,t=e.name,n=e.authorized;return n&&n.getIn([t,"value"])}},{key:"render",value:function(){var e=this.props,t=e.schema,n=e.getComponent,r=e.errSelectors,o=e.name,i=n("Input"),a=n("Row"),s=n("Col"),u=n("authError"),c=n("Markdown"),l=n("JumpToPath",!0),p=(t.get("scheme")||"").toLowerCase(),f=this.getValue(),h=r.allErrors().filter(function(e){return e.get("authId")===o});if("basic"===p){var d=f?f.get("username"):null;return _.a.createElement("div",null,_.a.createElement("h4",null,_.a.createElement("code",null,o||t.get("name")),"  (http, Basic)",_.a.createElement(l,{path:["securityDefinitions",o]})),d&&_.a.createElement("h6",null,"Authorized"),_.a.createElement(a,null,_.a.createElement(c,{source:t.get("description")})),_.a.createElement(a,null,_.a.createElement("label",null,"Username:"),d?_.a.createElement("code",null," ",d," "):_.a.createElement(s,null,_.a.createElement(i,{type:"text",required:"required",name:"username",onChange:this.onChange}))),_.a.createElement(a,null,_.a.createElement("label",null,"Password:"),d?_.a.createElement("code",null," ****** "):_.a.createElement(s,null,_.a.createElement(i,{required:"required",autoComplete:"new-password",name:"password",type:"password",onChange:this.onChange}))),h.valueSeq().map(function(e,t){return _.a.createElement(u,{error:e,key:t})}))}return"bearer"===p?_.a.createElement("div",null,_.a.createElement("h4",null,_.a.createElement("code",null,o||t.get("name")),"  (http, Bearer)",_.a.createElement(l,{path:["securityDefinitions",o]})),f&&_.a.createElement("h6",null,"Authorized"),_.a.createElement(a,null,_.a.createElement(c,{source:t.get("description")})),_.a.createElement(a,null,_.a.createElement("label",null,"Value:"),f?_.a.createElement("code",null," ****** "):_.a.createElement(s,null,_.a.createElement(i,{type:"text",onChange:this.onChange}))),h.valueSeq().map(function(e,t){return _.a.createElement(u,{error:e,key:t})})):_.a.createElement("div",null,_.a.createElement("em",null,_.a.createElement("b",null,o)," HTTP authentication: unsupported scheme ","'".concat(p,"'")))}}]),t}(_.a.Component))},function(e,t,n){"use strict";n.r(t),n.d(t,"default",function(){return I});var r=n(51),o=n.n(r),i=n(92),a=n.n(i),s=n(57),u=n.n(s),c=n(58),l=n.n(c),p=n(52),f=n.n(p),h=n(17),d=n.n(h),m=n(4),v=n.n(m),g=n(5),y=n.n(g),b=n(6),_=n.n(b),w=n(7),x=n.n(w),E=n(9),S=n.n(E),C=n(8),k=n.n(C),O=n(2),A=n.n(O),T=n(0),j=n.n(T);n(10),n(19);function P(e,t){var n=d()(e);if(f.a){var r=f()(e);t&&(r=r.filter(function(t){return l()(e,t).enumerable})),n.push.apply(n,r)}return n}var I=function(e){function t(){var e,n;v()(this,t);for(var r=arguments.length,i=new Array(r),s=0;s<r;s++)i[s]=arguments[s];return n=_()(this,(e=x()(t)).call.apply(e,[this].concat(i))),A()(S()(n),"setSelectedServer",function(e){var t=n.props,r=t.path,o=t.method;return n.forceUpdate(),n.props.setSelectedServer(e,"".concat(r,":").concat(o))}),A()(S()(n),"setServerVariableValue",function(e){var t=n.props,r=t.path,i=t.method;return n.forceUpdate(),n.props.setServerVariableValue(function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?P(n,!0).forEach(function(t){A()(e,t,n[t])}):u.a?a()(e,u()(n)):P(n).forEach(function(t){o()(e,t,l()(n,t))})}return e}({},e,{namespace:"".concat(r,":").concat(i)}))}),A()(S()(n),"getSelectedServer",function(){var e=n.props,t=e.path,r=e.method;return n.props.getSelectedServer("".concat(t,":").concat(r))}),A()(S()(n),"getServerVariable",function(e,t){var r=n.props,o=r.path,i=r.method;return n.props.getServerVariable({namespace:"".concat(o,":").concat(i),server:e},t)}),A()(S()(n),"getEffectiveServerValue",function(e){var t=n.props,r=t.path,o=t.method;return n.props.getEffectiveServerValue({server:e,namespace:"".concat(r,":").concat(o)})}),n}return k()(t,e),y()(t,[{key:"render",value:function(){var e=this.props,t=e.operationServers,n=e.pathServers,r=e.getComponent;if(!t&&!n)return null;var o=r("Servers"),i=t||n,a=t?"operation":"path";return j.a.createElement("div",{className:"opblock-section operation-servers"},j.a.createElement("div",{className:"opblock-section-header"},j.a.createElement("div",{className:"tab-header"},j.a.createElement("h4",{className:"opblock-title"},"Servers"))),j.a.createElement("div",{className:"opblock-description-wrapper"},j.a.createElement("h4",{className:"message"},"These ",a,"-level options override the global server options."),j.a.createElement(o,{servers:i,currentServer:this.getSelectedServer(),setSelectedServer:this.setSelectedServer,setServerVariableValue:this.setServerVariableValue,getServerVariable:this.getServerVariable,getEffectiveServerValue:this.getEffectiveServerValue})))}}]),t}(j.a.Component)},function(e,t,n){"use strict";n.r(t);var r=n(312),o=n(313),i=n(314),a=n(315),s=n(316),u=n(317);t.default={Markdown:r.default,AuthItem:o.default,JsonSchema_string:u.default,VersionStamp:i.default,model:s.default,onlineValidatorBadge:a.default}},function(e,t,n){"use strict";n.r(t),n.d(t,"Markdown",function(){return f});var r=n(0),o=n.n(r),i=(n(10),n(56)),a=n.n(i),s=n(193),u=n.n(s),c=n(24),l=n(192),p=new u.a("commonmark");p.block.ruler.enable(["table"]),p.set({linkTarget:"_blank"});var f=function(e){var t=e.source,n=e.className,r=void 0===n?"":n;if("string"!=typeof t)return null;if(t){var i,s=p.render(t),u=Object(l.b)(s);return"string"==typeof u&&(i=u.trim()),o.a.createElement("div",{dangerouslySetInnerHTML:{__html:i},className:a()(r,"renderedMarkdown")})}return null};t.default=Object(c.OAS3ComponentWrapFactory)(f)},function(e,t,n){"use strict";n.r(t);var r=n(46),o=n.n(r),i=n(0),a=n.n(i),s=n(24);t.default=Object(s.OAS3ComponentWrapFactory)(function(e){var t=e.Ori,n=o()(e,["Ori"]),r=n.schema,i=n.getComponent,s=n.errSelectors,u=n.authorized,c=n.onAuthChange,l=n.name,p=i("HttpAuth");return"http"===r.get("type")?a.a.createElement(p,{key:l,schema:r,name:l,errSelectors:s,authorized:u,getComponent:i,onChange:c}):a.a.createElement(t,n)})},function(e,t,n){"use strict";n.r(t);var r=n(0),o=n.n(r),i=n(24);t.default=Object(i.OAS3ComponentWrapFactory)(function(e){var t=e.Ori;return o.a.createElement("span",null,o.a.createElement(t,e),o.a.createElement("small",{style:{backgroundColor:"#89bf04"}},o.a.createElement("pre",{className:"version"},"OAS3")))})},function(e,t,n){"use strict";n.r(t);var r=n(24);t.default=Object(r.OAS3ComponentWrapFactory)(function(){return null})},function(e,t,n){"use strict";n.r(t);var r=n(20),o=n.n(r),i=n(4),a=n.n(i),s=n(5),u=n.n(s),c=n(6),l=n.n(c),p=n(7),f=n.n(p),h=n(8),d=n.n(h),m=n(0),v=n.n(m),g=(n(10),n(24)),y=n(191),b=function(e){function t(){return a()(this,t),l()(this,f()(t).apply(this,arguments))}return d()(t,e),u()(t,[{key:"render",value:function(){var e=this.props,t=e.getConfigs,n=["model-box"],r=null;return!0===e.schema.get("deprecated")&&(n.push("deprecated"),r=v.a.createElement("span",{className:"model-deprecated-warning"},"Deprecated:")),v.a.createElement("div",{className:n.join(" ")},r,v.a.createElement(y.a,o()({},this.props,{getConfigs:t,depth:1,expandDepth:this.props.expandDepth||0})))}}]),t}(m.Component);t.default=Object(g.OAS3ComponentWrapFactory)(b)},function(e,t,n){"use strict";n.r(t);var r=n(46),o=n.n(r),i=n(0),a=n.n(i),s=n(24);t.default=Object(s.OAS3ComponentWrapFactory)(function(e){var t=e.Ori,n=o()(e,["Ori"]),r=n.schema,i=n.getComponent,s=n.errors,u=n.onChange,c=r.type,l=r.format,p=i("Input");return"string"!==c||"binary"!==l&&"base64"!==l?a.a.createElement(t,n):a.a.createElement(p,{type:"file",className:s.length?"invalid":"",title:s.length?s:"",onChange:function(e){u(e.target.files[0])},disabled:t.isDisabled})})},function(e,t,n){"use strict";n.r(t),n.d(t,"selectedServer",function(){return a}),n.d(t,"requestBodyValue",function(){return s}),n.d(t,"activeExamplesMember",function(){return u}),n.d(t,"requestContentType",function(){return c}),n.d(t,"responseContentType",function(){return l}),n.d(t,"serverVariableValue",function(){return p}),n.d(t,"serverVariables",function(){return f}),n.d(t,"serverEffectiveValue",function(){return h});var r=n(1),o=n(24);function i(e){return function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return function(t){var r=t.getSystem().specSelectors.specJson();return Object(o.isOAS3)(r)?e.apply(void 0,n):null}}}var a=i(function(e,t){var n=t?[t,"selectedServer"]:["selectedServer"];return e.getIn(n)||""}),s=i(function(e,t,n){return e.getIn(["requestData",t,n,"bodyValue"])||null}),u=i(function(e,t,n,r,o){return e.getIn(["examples",t,n,r,o,"activeExample"])||null}),c=i(function(e,t,n){return e.getIn(["requestData",t,n,"requestContentType"])||null}),l=i(function(e,t,n){return e.getIn(["requestData",t,n,"responseContentType"])||null}),p=i(function(e,t,n){var r;if("string"!=typeof t){var o=t.server,i=t.namespace;r=i?[i,"serverVariableValues",o,n]:["serverVariableValues",o,n]}else{r=["serverVariableValues",t,n]}return e.getIn(r)||null}),f=i(function(e,t){var n;if("string"!=typeof t){var o=t.server,i=t.namespace;n=i?[i,"serverVariableValues",o]:["serverVariableValues",o]}else{n=["serverVariableValues",t]}return e.getIn(n)||Object(r.OrderedMap)()}),h=i(function(e,t){var n,o;if("string"!=typeof t){var i=t.server,a=t.namespace;o=i,n=a?e.getIn([a,"serverVariableValues",o]):e.getIn(["serverVariableValues",o])}else o=t,n=e.getIn(["serverVariableValues",o]);n=n||Object(r.OrderedMap)();var s=o;return n.map(function(e,t){s=s.replace(new RegExp("{".concat(t,"}"),"g"),e)}),s})},function(e,t,n){"use strict";n.r(t);var r,o=n(2),i=n.n(o),a=n(13),s=n.n(a),u=n(59);t.default=(r={},i()(r,u.UPDATE_SELECTED_SERVER,function(e,t){var n=t.payload,r=n.selectedServerUrl,o=n.namespace,i=o?[o,"selectedServer"]:["selectedServer"];return e.setIn(i,r)}),i()(r,u.UPDATE_REQUEST_BODY_VALUE,function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,i=s()(o,2),a=i[0],u=i[1];return e.setIn(["requestData",a,u,"bodyValue"],r)}),i()(r,u.UPDATE_ACTIVE_EXAMPLES_MEMBER,function(e,t){var n=t.payload,r=n.name,o=n.pathMethod,i=n.contextType,a=n.contextName,u=s()(o,2),c=u[0],l=u[1];return e.setIn(["examples",c,l,i,a,"activeExample"],r)}),i()(r,u.UPDATE_REQUEST_CONTENT_TYPE,function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,i=s()(o,2),a=i[0],u=i[1];return e.setIn(["requestData",a,u,"requestContentType"],r)}),i()(r,u.UPDATE_RESPONSE_CONTENT_TYPE,function(e,t){var n=t.payload,r=n.value,o=n.path,i=n.method;return e.setIn(["requestData",o,i,"responseContentType"],r)}),i()(r,u.UPDATE_SERVER_VARIABLE_VALUE,function(e,t){var n=t.payload,r=n.server,o=n.namespace,i=n.key,a=n.val,s=o?[o,"serverVariableValues",r,i]:["serverVariableValues",r,i];return e.setIn(s,a)}),r)},function(e,t,n){"use strict";n.r(t);var r=n(3),o=n(1020),i={};o.keys().forEach(function(e){if("./index.js"!==e){var t=o(e);i[Object(r.C)(e)]=t.default?t.default:t}}),t.default=i},function(e,t,n){"use strict";n.r(t);var r=n(144),o=n(117),i=n(288),a=n(289),s=n(290);n.d(t,"default",function(){return c});var u={getLocalConfig:function(){return Object(r.parseYamlConfig)('---\nurl: "https://petstore.swagger.io/v2/swagger.json"\ndom_id: "#swagger-ui"\nvalidatorUrl: "https://validator.swagger.io/validator"\n')}};function c(){return{statePlugins:{spec:{actions:i,selectors:u},configs:{reducers:s.default,actions:o,selectors:a}}}}},function(e,t,n){"use strict";(function(e,r){var o,i=n(462);o="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e?e:r;var a=Object(i.a)(o);t.a=a}).call(this,n(41),n(581)(e))},function(e,t,n){"use strict";var r=n(391),o=n(393),i=n(689);e.exports=function(e){var t,a=r(arguments[1]);return a.normalizer||0!==(t=a.length=o(a.length,e.length,a.async))&&(a.primitive?!1===t?a.normalizer=n(716):t>1&&(a.normalizer=n(717)(t)):a.normalizer=!1===t?n(718)():1===t?n(722)():n(723)(t)),a.async&&n(724),a.promise&&n(725),a.dispose&&n(731),a.maxAge&&n(732),a.max&&n(735),a.refCounter&&n(737),i(e,a)}},function(e,t,n){e.exports=n(757)},function(e,t,n){var r=n(410);e.exports=function(e,t,n){return null==e?e:r(e,t,n)}},function(e,t,n){"use strict";t.__esModule=!0,t.connect=t.Provider=void 0;var r=i(n(876)),o=i(n(879));function i(e){return e&&e.__esModule?e:{default:e}}t.Provider=r.default,t.connect=o.default},function(e,t,n){e.exports=function(){"use strict";var e=Object.freeze||function(e){return e},t=e(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),n=e(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","audio","canvas","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","video","view","vkern"]),r=e(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),o=e(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),i=e(["#text"]),a=Object.freeze||function(e){return e},s=a(["accept","action","align","alt","autocomplete","background","bgcolor","border","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","coords","crossorigin","datetime","default","dir","disabled","download","enctype","face","for","headers","height","hidden","high","href","hreflang","id","integrity","ismap","label","lang","list","loop","low","max","maxlength","media","method","min","multiple","name","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","type","usemap","valign","value","width","xmlns"]),u=a(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","tabindex","targetx","targety","transform","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),c=a(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),l=a(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),p=Object.hasOwnProperty,f=Object.setPrototypeOf,h=("undefined"!=typeof Reflect&&Reflect).apply;function d(e,t){f&&f(e,null);for(var n=t.length;n--;){var r=t[n];if("string"==typeof r){var o=r.toLowerCase();o!==r&&(Object.isFrozen(t)||(t[n]=o),r=o)}e[r]=!0}return e}function m(e){var t={},n=void 0;for(n in e)h(p,e,[n])&&(t[n]=e[n]);return t}h||(h=function(e,t,n){return e.apply(t,n)});var v=Object.seal||function(e){return e},g=v(/\{\{[\s\S]*|[\s\S]*\}\}/gm),y=v(/<%[\s\S]*|[\s\S]*%>/gm),b=v(/^data-[\-\w.\u00B7-\uFFFF]/),_=v(/^aria-[\-\w]+$/),w=v(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),x=v(/^(?:\w+script|data):/i),E=v(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g),S="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function C(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}var k=("undefined"!=typeof Reflect&&Reflect).apply,O=Array.prototype.slice,A=Object.freeze,T=function(){return"undefined"==typeof window?null:window};k||(k=function(e,t,n){return e.apply(t,n)});var j=function(e,t){if("object"!==(void 0===e?"undefined":S(e))||"function"!=typeof e.createPolicy)return null;var n=null;t.currentScript&&t.currentScript.hasAttribute("data-tt-policy-suffix")&&(n=t.currentScript.getAttribute("data-tt-policy-suffix"));var r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};return function e(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:T(),p=function(t){return e(t)};if(p.version="1.0.11",p.removed=[],!a||!a.document||9!==a.document.nodeType)return p.isSupported=!1,p;var f=a.document,h=!1,v=!1,P=a.document,I=a.DocumentFragment,M=a.HTMLTemplateElement,N=a.Node,R=a.NodeFilter,D=a.NamedNodeMap,L=void 0===D?a.NamedNodeMap||a.MozNamedAttrMap:D,U=a.Text,q=a.Comment,F=a.DOMParser,z=a.TrustedTypes;if("function"==typeof M){var B=P.createElement("template");B.content&&B.content.ownerDocument&&(P=B.content.ownerDocument)}var V=j(z,f),H=V?V.createHTML(""):"",W=P,J=W.implementation,Y=W.createNodeIterator,K=W.getElementsByTagName,G=W.createDocumentFragment,$=f.importNode,Z={};p.isSupported=J&&void 0!==J.createHTMLDocument&&9!==P.documentMode;var X=g,Q=y,ee=b,te=_,ne=x,re=E,oe=w,ie=null,ae=d({},[].concat(C(t),C(n),C(r),C(o),C(i))),se=null,ue=d({},[].concat(C(s),C(u),C(c),C(l))),ce=null,le=null,pe=!0,fe=!0,he=!1,de=!1,me=!1,ve=!1,ge=!1,ye=!1,be=!1,_e=!1,we=!1,xe=!0,Ee=!0,Se=!1,Ce={},ke=d({},["audio","head","math","script","style","template","svg","video"]),Oe=d({},["audio","video","img","source","image"]),Ae=null,Te=d({},["alt","class","for","id","label","name","pattern","placeholder","summary","title","value","style","xmlns"]),je=null,Pe=P.createElement("form"),Ie=function(e){je&&je===e||(e&&"object"===(void 0===e?"undefined":S(e))||(e={}),ie="ALLOWED_TAGS"in e?d({},e.ALLOWED_TAGS):ae,se="ALLOWED_ATTR"in e?d({},e.ALLOWED_ATTR):ue,Ae="ADD_URI_SAFE_ATTR"in e?d({},e.ADD_URI_SAFE_ATTR):Te,ce="FORBID_TAGS"in e?d({},e.FORBID_TAGS):{},le="FORBID_ATTR"in e?d({},e.FORBID_ATTR):{},Ce="USE_PROFILES"in e&&e.USE_PROFILES,pe=!1!==e.ALLOW_ARIA_ATTR,fe=!1!==e.ALLOW_DATA_ATTR,he=e.ALLOW_UNKNOWN_PROTOCOLS||!1,de=e.SAFE_FOR_JQUERY||!1,me=e.SAFE_FOR_TEMPLATES||!1,ve=e.WHOLE_DOCUMENT||!1,be=e.RETURN_DOM||!1,_e=e.RETURN_DOM_FRAGMENT||!1,we=e.RETURN_DOM_IMPORT||!1,ye=e.FORCE_BODY||!1,xe=!1!==e.SANITIZE_DOM,Ee=!1!==e.KEEP_CONTENT,Se=e.IN_PLACE||!1,oe=e.ALLOWED_URI_REGEXP||oe,me&&(fe=!1),_e&&(be=!0),Ce&&(ie=d({},[].concat(C(i))),se=[],!0===Ce.html&&(d(ie,t),d(se,s)),!0===Ce.svg&&(d(ie,n),d(se,u),d(se,l)),!0===Ce.svgFilters&&(d(ie,r),d(se,u),d(se,l)),!0===Ce.mathMl&&(d(ie,o),d(se,c),d(se,l))),e.ADD_TAGS&&(ie===ae&&(ie=m(ie)),d(ie,e.ADD_TAGS)),e.ADD_ATTR&&(se===ue&&(se=m(se)),d(se,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&d(Ae,e.ADD_URI_SAFE_ATTR),Ee&&(ie["#text"]=!0),ve&&d(ie,["html","head","body"]),ie.table&&d(ie,["tbody"]),A&&A(e),je=e)},Me=function(e){p.removed.push({element:e});try{e.parentNode.removeChild(e)}catch(t){e.outerHTML=H}},Ne=function(e,t){try{p.removed.push({attribute:t.getAttributeNode(e),from:t})}catch(e){p.removed.push({attribute:null,from:t})}t.removeAttribute(e)},Re=function(e){var t=void 0,n=void 0;if(ye)e="<remove></remove>"+e;else{var r=e.match(/^[\s]+/);(n=r&&r[0])&&(e=e.slice(n.length))}if(h)try{t=(new F).parseFromString(e,"text/html")}catch(e){}if(v&&d(ce,["title"]),!t||!t.documentElement){var o=t=J.createHTMLDocument(""),i=o.body;i.parentNode.removeChild(i.parentNode.firstElementChild),i.outerHTML=V?V.createHTML(e):e}return n&&t.body.insertBefore(P.createTextNode(n),t.body.childNodes[0]||null),K.call(t,ve?"html":"body")[0]};p.isSupported&&(function(){try{var e=Re('<svg><p><style><img src="</style><img src=x onerror=1//">');e.querySelector("svg img")&&(h=!0)}catch(e){}}(),function(){try{var e=Re("<x/><title>&lt;/title&gt;&lt;img&gt;");e.querySelector("title").innerHTML.match(/<\/title/)&&(v=!0)}catch(e){}}());var De=function(e){return Y.call(e.ownerDocument||e,e,R.SHOW_ELEMENT|R.SHOW_COMMENT|R.SHOW_TEXT,function(){return R.FILTER_ACCEPT},!1)},Le=function(e){return"object"===(void 0===N?"undefined":S(N))?e instanceof N:e&&"object"===(void 0===e?"undefined":S(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},Ue=function(e,t,n){Z[e]&&Z[e].forEach(function(e){e.call(p,t,n,je)})},qe=function(e){var t,n=void 0;if(Ue("beforeSanitizeElements",e,null),!((t=e)instanceof U||t instanceof q||"string"==typeof t.nodeName&&"string"==typeof t.textContent&&"function"==typeof t.removeChild&&t.attributes instanceof L&&"function"==typeof t.removeAttribute&&"function"==typeof t.setAttribute))return Me(e),!0;var r=e.nodeName.toLowerCase();if(Ue("uponSanitizeElement",e,{tagName:r,allowedTags:ie}),!ie[r]||ce[r]){if(Ee&&!ke[r]&&"function"==typeof e.insertAdjacentHTML)try{var o=e.innerHTML;e.insertAdjacentHTML("AfterEnd",V?V.createHTML(o):o)}catch(e){}return Me(e),!0}return"noscript"===r&&e.innerHTML.match(/<\/noscript/i)?(Me(e),!0):"noembed"===r&&e.innerHTML.match(/<\/noembed/i)?(Me(e),!0):(!de||e.firstElementChild||e.content&&e.content.firstElementChild||!/</g.test(e.textContent)||(p.removed.push({element:e.cloneNode()}),e.innerHTML?e.innerHTML=e.innerHTML.replace(/</g,"&lt;"):e.innerHTML=e.textContent.replace(/</g,"&lt;")),me&&3===e.nodeType&&(n=(n=(n=e.textContent).replace(X," ")).replace(Q," "),e.textContent!==n&&(p.removed.push({element:e.cloneNode()}),e.textContent=n)),Ue("afterSanitizeElements",e,null),!1)},Fe=function(e,t,n){if(xe&&("id"===t||"name"===t)&&(n in P||n in Pe))return!1;if(fe&&ee.test(t));else if(pe&&te.test(t));else{if(!se[t]||le[t])return!1;if(Ae[t]);else if(oe.test(n.replace(re,"")));else if("src"!==t&&"xlink:href"!==t||"script"===e||0!==n.indexOf("data:")||!Oe[e])if(he&&!ne.test(n.replace(re,"")));else if(n)return!1}return!0},ze=function(e){var t=void 0,n=void 0,r=void 0,o=void 0,i=void 0;Ue("beforeSanitizeAttributes",e,null);var a=e.attributes;if(a){var s={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:se};for(i=a.length;i--;){var u=t=a[i],c=u.name,l=u.namespaceURI;if(n=t.value.trim(),r=c.toLowerCase(),s.attrName=r,s.attrValue=n,s.keepAttr=!0,Ue("uponSanitizeAttribute",e,s),n=s.attrValue,"name"===r&&"IMG"===e.nodeName&&a.id)o=a.id,a=k(O,a,[]),Ne("id",e),Ne(c,e),a.indexOf(o)>i&&e.setAttribute("id",o.value);else{if("INPUT"===e.nodeName&&"type"===r&&"file"===n&&s.keepAttr&&(se[r]||!le[r]))continue;"id"===c&&e.setAttribute(c,""),Ne(c,e)}if(s.keepAttr){me&&(n=(n=n.replace(X," ")).replace(Q," "));var f=e.nodeName.toLowerCase();if(Fe(f,r,n))try{l?e.setAttributeNS(l,c,n):e.setAttribute(c,n),p.removed.pop()}catch(e){}}}Ue("afterSanitizeAttributes",e,null)}},Be=function e(t){var n=void 0,r=De(t);for(Ue("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)Ue("uponSanitizeShadowNode",n,null),qe(n)||(n.content instanceof I&&e(n.content),ze(n));Ue("afterSanitizeShadowDOM",t,null)};return p.sanitize=function(e,t){var n=void 0,r=void 0,o=void 0,i=void 0,s=void 0;if(e||(e="\x3c!--\x3e"),"string"!=typeof e&&!Le(e)){if("function"!=typeof e.toString)throw new TypeError("toString is not a function");if("string"!=typeof(e=e.toString()))throw new TypeError("dirty is not a string, aborting")}if(!p.isSupported){if("object"===S(a.toStaticHTML)||"function"==typeof a.toStaticHTML){if("string"==typeof e)return a.toStaticHTML(e);if(Le(e))return a.toStaticHTML(e.outerHTML)}return e}if(ge||Ie(t),p.removed=[],Se);else if(e instanceof N)n=Re("\x3c!--\x3e"),1===(r=n.ownerDocument.importNode(e,!0)).nodeType&&"BODY"===r.nodeName?n=r:"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!be&&!me&&!ve&&-1===e.indexOf("<"))return V?V.createHTML(e):e;if(!(n=Re(e)))return be?null:H}n&&ye&&Me(n.firstChild);for(var u=De(Se?e:n);o=u.nextNode();)3===o.nodeType&&o===i||qe(o)||(o.content instanceof I&&Be(o.content),ze(o),i=o);if(i=null,Se)return e;if(be){if(_e)for(s=G.call(n.ownerDocument);n.firstChild;)s.appendChild(n.firstChild);else s=n;return we&&(s=$.call(f,s,!0)),s}var c=ve?n.outerHTML:n.innerHTML;return me&&(c=(c=c.replace(X," ")).replace(Q," ")),V?V.createHTML(c):c},p.setConfig=function(e){Ie(e),ge=!0},p.clearConfig=function(){je=null,ge=!1},p.isValidAttribute=function(e,t,n){je||Ie({});var r=e.toLowerCase(),o=t.toLowerCase();return Fe(r,o,n)},p.addHook=function(e,t){"function"==typeof t&&(Z[e]=Z[e]||[],Z[e].push(t))},p.removeHook=function(e){Z[e]&&Z[e].pop()},p.removeHooks=function(e){Z[e]&&(Z[e]=[])},p.removeAllHooks=function(){Z={}},p}()}()},function(e,t,n){var r=n(43),o=r["__core-js_shared__"]||(r["__core-js_shared__"]={});e.exports=function(e){return o[e]||(o[e]={})}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){"use strict";var r=n(331)(!0);n(332)(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var r=n(149),o=n(68);e.exports=function(e){return function(t,n){var i,a,s=String(o(t)),u=r(n),c=s.length;return u<0||u>=c?e?"":void 0:(i=s.charCodeAt(u))<55296||i>56319||u+1===c||(a=s.charCodeAt(u+1))<56320||a>57343?e?s.charAt(u):i:e?s.slice(u,u+2):a-56320+(i-55296<<10)+65536}}},function(e,t,n){"use strict";var r=n(333),o=n(38),i=n(95),a=n(76),s=n(124),u=n(487),c=n(198),l=n(493),p=n(33)("iterator"),f=!([].keys&&"next"in[].keys()),h=function(){return this};e.exports=function(e,t,n,d,m,v,g){u(n,t,d);var y,b,_,w=function(e){if(!f&&e in C)return C[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},x=t+" Iterator",E="values"==m,S=!1,C=e.prototype,k=C[p]||C["@@iterator"]||m&&C[m],O=k||w(m),A=m?E?w("entries"):O:void 0,T="Array"==t&&C.entries||k;if(T&&(_=l(T.call(new e)))!==Object.prototype&&_.next&&(c(_,x,!0),r||"function"==typeof _[p]||a(_,p,h)),E&&k&&"values"!==k.name&&(S=!0,O=function(){return k.call(this)}),r&&!g||!f&&!S&&C[p]||a(C,p,O),s[t]=O,s[x]=h,m)if(y={values:E?O:w("values"),keys:v?O:w("keys"),entries:A},g)for(b in y)b in C||i(C,b,y[b]);else o(o.P+o.F*(f||S),t,y);return y}},function(e,t){e.exports=!1},function(e,t,n){var r=n(490),o=n(336);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t,n){var r=n(149),o=Math.max,i=Math.min;e.exports=function(e,t){return(e=r(e))<0?o(e+t,0):i(e,t)}},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var r=n(43).document;e.exports=r&&r.documentElement},function(e,t,n){var r=n(77),o=n(151),i=n(33)("species");e.exports=function(e,t){var n,a=r(e).constructor;return void 0===a||null==(n=r(a)[i])?t:o(n)}},function(e,t,n){var r,o,i,a=n(150),s=n(505),u=n(337),c=n(196),l=n(43),p=l.process,f=l.setImmediate,h=l.clearImmediate,d=l.MessageChannel,m=l.Dispatch,v=0,g={},y=function(){var e=+this;if(g.hasOwnProperty(e)){var t=g[e];delete g[e],t()}},b=function(e){y.call(e.data)};f&&h||(f=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return g[++v]=function(){s("function"==typeof e?e:Function(e),t)},r(v),v},h=function(e){delete g[e]},"process"==n(121)(p)?r=function(e){p.nextTick(a(y,e,1))}:m&&m.now?r=function(e){m.now(a(y,e,1))}:d?(i=(o=new d).port2,o.port1.onmessage=b,r=a(i.postMessage,i,1)):l.addEventListener&&"function"==typeof postMessage&&!l.importScripts?(r=function(e){l.postMessage(e+"","*")},l.addEventListener("message",b,!1)):r="onreadystatechange"in c("script")?function(e){u.appendChild(c("script")).onreadystatechange=function(){u.removeChild(this),y.call(e)}}:function(e){setTimeout(a(y,e,1),0)}),e.exports={set:f,clear:h}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,n){var r=n(77),o=n(96),i=n(199);e.exports=function(e,t){if(r(e),o(t)&&t.constructor===e)return t;var n=i.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){var r=n(96),o=n(121),i=n(33)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[i])?!!t:"RegExp"==o(e))}},function(e,t,n){var r=n(69),o=n(70),i=n(544)(!1),a=n(205)("IE_PROTO");e.exports=function(e,t){var n,s=o(e),u=0,c=[];for(n in s)n!=a&&r(s,n)&&c.push(n);for(;t.length>u;)r(s,n=t[u++])&&(~i(c,n)||c.push(n));return c}},function(e,t,n){e.exports=!n(45)&&!n(80)(function(){return 7!=Object.defineProperty(n(209)("div"),"a",{get:function(){return 7}}).a})},function(e,t,n){var r=n(47),o=n(44),i=n(126);e.exports=n(45)?Object.defineProperties:function(e,t){o(e);for(var n,a=i(t),s=a.length,u=0;s>u;)r.f(e,n=a[u++],t[n]);return e}},function(e,t,n){var r=n(32).document;e.exports=r&&r.documentElement},function(e,t,n){var r=n(69),o=n(79),i=n(205)("IE_PROTO"),a=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=o(e),r(e,i)?e[i]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?a:null}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){"use strict";var r=n(32),o=n(69),i=n(45),a=n(30),s=n(212),u=n(132).KEY,c=n(80),l=n(206),p=n(131),f=n(155),h=n(34),d=n(213),m=n(214),v=n(554),g=n(215),y=n(44),b=n(40),_=n(79),w=n(70),x=n(210),E=n(130),S=n(156),C=n(555),k=n(159),O=n(157),A=n(47),T=n(126),j=k.f,P=A.f,I=C.f,M=r.Symbol,N=r.JSON,R=N&&N.stringify,D=h("_hidden"),L=h("toPrimitive"),U={}.propertyIsEnumerable,q=l("symbol-registry"),F=l("symbols"),z=l("op-symbols"),B=Object.prototype,V="function"==typeof M&&!!O.f,H=r.QObject,W=!H||!H.prototype||!H.prototype.findChild,J=i&&c(function(){return 7!=S(P({},"a",{get:function(){return P(this,"a",{value:7}).a}})).a})?function(e,t,n){var r=j(B,t);r&&delete B[t],P(e,t,n),r&&e!==B&&P(B,t,r)}:P,Y=function(e){var t=F[e]=S(M.prototype);return t._k=e,t},K=V&&"symbol"==typeof M.iterator?function(e){return"symbol"==typeof e}:function(e){return e instanceof M},G=function(e,t,n){return e===B&&G(z,t,n),y(e),t=x(t,!0),y(n),o(F,t)?(n.enumerable?(o(e,D)&&e[D][t]&&(e[D][t]=!1),n=S(n,{enumerable:E(0,!1)})):(o(e,D)||P(e,D,E(1,{})),e[D][t]=!0),J(e,t,n)):P(e,t,n)},$=function(e,t){y(e);for(var n,r=v(t=w(t)),o=0,i=r.length;i>o;)G(e,n=r[o++],t[n]);return e},Z=function(e){var t=U.call(this,e=x(e,!0));return!(this===B&&o(F,e)&&!o(z,e))&&(!(t||!o(this,e)||!o(F,e)||o(this,D)&&this[D][e])||t)},X=function(e,t){if(e=w(e),t=x(t,!0),e!==B||!o(F,t)||o(z,t)){var n=j(e,t);return!n||!o(F,t)||o(e,D)&&e[D][t]||(n.enumerable=!0),n}},Q=function(e){for(var t,n=I(w(e)),r=[],i=0;n.length>i;)o(F,t=n[i++])||t==D||t==u||r.push(t);return r},ee=function(e){for(var t,n=e===B,r=I(n?z:w(e)),i=[],a=0;r.length>a;)!o(F,t=r[a++])||n&&!o(B,t)||i.push(F[t]);return i};V||(s((M=function(){if(this instanceof M)throw TypeError("Symbol is not a constructor!");var e=f(arguments.length>0?arguments[0]:void 0),t=function(n){this===B&&t.call(z,n),o(this,D)&&o(this[D],e)&&(this[D][e]=!1),J(this,e,E(1,n))};return i&&W&&J(B,e,{configurable:!0,set:t}),Y(e)}).prototype,"toString",function(){return this._k}),k.f=X,A.f=G,n(216).f=C.f=Q,n(158).f=Z,O.f=ee,i&&!n(128)&&s(B,"propertyIsEnumerable",Z,!0),d.f=function(e){return Y(h(e))}),a(a.G+a.W+a.F*!V,{Symbol:M});for(var te="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),ne=0;te.length>ne;)h(te[ne++]);for(var re=T(h.store),oe=0;re.length>oe;)m(re[oe++]);a(a.S+a.F*!V,"Symbol",{for:function(e){return o(q,e+="")?q[e]:q[e]=M(e)},keyFor:function(e){if(!K(e))throw TypeError(e+" is not a symbol!");for(var t in q)if(q[t]===e)return t},useSetter:function(){W=!0},useSimple:function(){W=!1}}),a(a.S+a.F*!V,"Object",{create:function(e,t){return void 0===t?S(e):$(S(e),t)},defineProperty:G,defineProperties:$,getOwnPropertyDescriptor:X,getOwnPropertyNames:Q,getOwnPropertySymbols:ee});var ie=c(function(){O.f(1)});a(a.S+a.F*ie,"Object",{getOwnPropertySymbols:function(e){return O.f(_(e))}}),N&&a(a.S+a.F*(!V||c(function(){var e=M();return"[null]"!=R([e])||"{}"!=R({a:e})||"{}"!=R(Object(e))})),"JSON",{stringify:function(e){for(var t,n,r=[e],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=t=r[1],(b(t)||void 0!==e)&&!K(e))return g(t)||(t=function(e,t){if("function"==typeof n&&(t=n.call(this,e,t)),!K(t))return t}),r[1]=t,R.apply(N,r)}}),M.prototype[L]||n(71)(M.prototype,L,M.prototype.valueOf),p(M,"Symbol"),p(Math,"Math",!0),p(r.JSON,"JSON",!0)},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";var r=n(45),o=n(126),i=n(157),a=n(158),s=n(79),u=n(203),c=Object.assign;e.exports=!c||n(80)(function(){var e={},t={},n=Symbol(),r="abcdefghijklmnopqrst";return e[n]=7,r.split("").forEach(function(e){t[e]=e}),7!=c({},e)[n]||Object.keys(c({},t)).join("")!=r})?function(e,t){for(var n=s(e),c=arguments.length,l=1,p=i.f,f=a.f;c>l;)for(var h,d=u(arguments[l++]),m=p?o(d).concat(p(d)):o(d),v=m.length,g=0;v>g;)h=m[g++],r&&!f.call(d,h)||(n[h]=d[h]);return n}:c},function(e,t,n){"use strict";var r=n(133),o=n(25),i=n(353),a=(n(354),n(161));n(15),n(566);function s(e,t,n){this.props=e,this.context=t,this.refs=a,this.updater=n||i}function u(e,t,n){this.props=e,this.context=t,this.refs=a,this.updater=n||i}function c(){}s.prototype.isReactComponent={},s.prototype.setState=function(e,t){"object"!=typeof e&&"function"!=typeof e&&null!=e&&r("85"),this.updater.enqueueSetState(this,e),t&&this.updater.enqueueCallback(this,t,"setState")},s.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this),e&&this.updater.enqueueCallback(this,e,"forceUpdate")},c.prototype=s.prototype,u.prototype=new c,u.prototype.constructor=u,o(u.prototype,s.prototype),u.prototype.isPureReactComponent=!0,e.exports={Component:s,PureComponent:u}},function(e,t,n){"use strict";n(23);var r={isMounted:function(e){return!1},enqueueCallback:function(e,t){},enqueueForceUpdate:function(e){},enqueueReplaceState:function(e,t){},enqueueSetState:function(e,t){}};e.exports=r},function(e,t,n){"use strict";e.exports=!1},function(e,t,n){"use strict";var r="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103;e.exports=r},function(e,t,n){"use strict";var r=n(574);e.exports=function(e){return r(e,!1)}},function(e,t,n){"use strict";e.exports=n(575)},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return e&&"@@redux/INIT"===e.type?"initialState argument passed to createStore":"previous state received by the reducer"},e.exports=t.default},function(e,t,n){var r=n(102),o=n(362),i=n(35),a=n(163),s=1/0,u=r?r.prototype:void 0,c=u?u.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(i(t))return o(t,e)+"";if(a(t))return c?c.call(t):"";var n=t+"";return"0"==n&&1/t==-s?"-0":n}},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(41))},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,o=Array(r);++n<r;)o[n]=t(e[n],n,e);return o}},function(e,t){e.exports=function(e,t,n){var r=-1,o=e.length;t<0&&(t=-t>o?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var i=Array(o);++r<o;)i[r]=e[r+t];return i}},function(e,t){var n=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]");e.exports=function(e){return n.test(e)}},function(e,t){e.exports=function(e,t,n,r){var o=-1,i=null==e?0:e.length;for(r&&i&&(n=e[++o]);++o<i;)n=t(n,e[o],o,e);return n}},function(e,t,n){var r=n(81),o=n(49),i="[object AsyncFunction]",a="[object Function]",s="[object GeneratorFunction]",u="[object Proxy]";e.exports=function(e){if(!o(e))return!1;var t=r(e);return t==a||t==s||t==i||t==u}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t,n){var r=n(636),o=n(63);e.exports=function e(t,n,i,a,s){return t===n||(null==t||null==n||!o(t)&&!o(n)?t!=t&&n!=n:r(t,n,i,a,e,s))}},function(e,t,n){var r=n(637),o=n(370),i=n(640),a=1,s=2;e.exports=function(e,t,n,u,c,l){var p=n&a,f=e.length,h=t.length;if(f!=h&&!(p&&h>f))return!1;var d=l.get(e);if(d&&l.get(t))return d==t;var m=-1,v=!0,g=n&s?new r:void 0;for(l.set(e,t),l.set(t,e);++m<f;){var y=e[m],b=t[m];if(u)var _=p?u(b,y,m,t,e,l):u(y,b,m,e,t,l);if(void 0!==_){if(_)continue;v=!1;break}if(g){if(!o(t,function(e,t){if(!i(g,t)&&(y===e||c(y,e,n,u,l)))return g.push(t)})){v=!1;break}}else if(y!==b&&!c(y,b,n,u,l)){v=!1;break}}return l.delete(e),l.delete(t),v}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1}},function(e,t,n){var r=n(48).Uint8Array;e.exports=r},function(e,t,n){var r=n(373),o=n(222),i=n(83);e.exports=function(e){return r(e,i,o)}},function(e,t,n){var r=n(221),o=n(35);e.exports=function(e,t,n){var i=t(e);return o(e)?i:r(i,n(e))}},function(e,t){e.exports=function(){return[]}},function(e,t,n){var r=n(646),o=n(223),i=n(35),a=n(224),s=n(170),u=n(376),c=Object.prototype.hasOwnProperty;e.exports=function(e,t){var n=i(e),l=!n&&o(e),p=!n&&!l&&a(e),f=!n&&!l&&!p&&u(e),h=n||l||p||f,d=h?r(e.length,String):[],m=d.length;for(var v in e)!t&&!c.call(e,v)||h&&("length"==v||p&&("offset"==v||"parent"==v)||f&&("buffer"==v||"byteLength"==v||"byteOffset"==v)||s(v,m))||d.push(v);return d}},function(e,t,n){var r=n(649),o=n(226),i=n(227),a=i&&i.isTypedArray,s=a?o(a):r;e.exports=s},function(e,t){e.exports=function(e,t){return function(n){return e(t(n))}}},function(e,t,n){var r=n(49);e.exports=function(e){return e==e&&!r(e)}},function(e,t){e.exports=function(e,t){return function(n){return null!=n&&n[e]===t&&(void 0!==t||e in Object(n))}}},function(e,t,n){var r=n(660),o=n(661);e.exports=function(e,t){return null!=e&&o(e,t,r)}},function(e,t,n){var r=n(667);e.exports=function(e){var t=r(e),n=t%1;return t==t?n?t-n:t:0}},function(e,t,n){var r=n(49),o=n(163),i=NaN,a=/^\s+|\s+$/g,s=/^[-+]0x[0-9a-f]+$/i,u=/^0b[01]+$/i,c=/^0o[0-7]+$/i,l=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(o(e))return i;if(r(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=r(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(a,"");var n=u.test(e);return n||c.test(e)?l(e.slice(2),n?2:8):s.test(e)?i:+e}},function(e,t,n){var r=n(669),o=n(672)(r);e.exports=o},function(e,t,n){var r=n(89),o=n(103),i=n(170),a=n(49);e.exports=function(e,t,n){if(!a(n))return!1;var s=typeof t;return!!("number"==s?o(n)&&i(t,n.length):"string"==s&&t in n)&&r(n[t],e)}},function(e,t,n){"use strict";(function(t,r){var o=n(174);e.exports=b;var i,a=n(350);b.ReadableState=y;n(230).EventEmitter;var s=function(e,t){return e.listeners(t).length},u=n(386),c=n(175).Buffer,l=t.Uint8Array||function(){};var p=n(134);p.inherits=n(106);var f=n(675),h=void 0;h=f&&f.debuglog?f.debuglog("stream"):function(){};var d,m=n(676),v=n(387);p.inherits(b,u);var g=["error","close","destroy","pause","resume"];function y(e,t){e=e||{};var r=t instanceof(i=i||n(84));this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var o=e.highWaterMark,a=e.readableHighWaterMark,s=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(a||0===a)?a:s,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new m,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(d||(d=n(389).StringDecoder),this.decoder=new d(e.encoding),this.encoding=e.encoding)}function b(e){if(i=i||n(84),!(this instanceof b))return new b(e);this._readableState=new y(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),u.call(this)}function _(e,t,n,r,o){var i,a=e._readableState;null===t?(a.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,S(e)}(e,a)):(o||(i=function(e,t){var n;r=t,c.isBuffer(r)||r instanceof l||"string"==typeof t||void 0===t||e.objectMode||(n=new TypeError("Invalid non-string/buffer chunk"));var r;return n}(a,t)),i?e.emit("error",i):a.objectMode||t&&t.length>0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):w(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?w(e,a,t,!1):k(e,a)):w(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(a)}function w(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(e.emit("data",n),e.read(0)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&S(e)),k(e,t)}Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),b.prototype.destroy=v.destroy,b.prototype._undestroy=v.undestroy,b.prototype._destroy=function(e,t){this.push(null),t(e)},b.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=c.from(e,t),t=""),n=!0),_(this,e,t,!1,n)},b.prototype.unshift=function(e){return _(this,e,null,!0,!1)},b.prototype.isPaused=function(){return!1===this._readableState.flowing},b.prototype.setEncoding=function(e){return d||(d=n(389).StringDecoder),this._readableState.decoder=new d(e),this._readableState.encoding=e,this};var x=8388608;function E(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=x?e=x:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function S(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(h("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(C,e):C(e))}function C(e){h("emit readable"),e.emit("readable"),j(e)}function k(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(O,e,t))}function O(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(h("maybeReadMore read 0"),e.read(0),n!==t.length);)n=t.length;t.readingMore=!1}function A(e){h("readable nexttick read 0"),e.read(0)}function T(e,t){t.reading||(h("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),j(e),t.flowing&&!t.reading&&e.read(0)}function j(e){var t=e._readableState;for(h("flow",t.flowing);t.flowing&&null!==e.read(););}function P(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;e<t.head.data.length?(r=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):r=e===t.head.data.length?t.shift():n?function(e,t){var n=t.head,r=1,o=n.data;e-=o.length;for(;n=n.next;){var i=n.data,a=e>i.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function I(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(M,t,e))}function M(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function N(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}b.prototype.read=function(e){h("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return h("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?I(this):S(this),null;if(0===(e=E(e,t))&&t.ended)return 0===t.length&&I(this),null;var r,o=t.needReadable;return h("need readable",o),(0===t.length||t.length-e<t.highWaterMark)&&h("length less than watermark",o=!0),t.ended||t.reading?h("reading or ended",o=!1):o&&(h("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=E(n,t))),null===(r=e>0?P(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&I(this)),null!==r&&this.emit("data",r),r},b.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},b.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,h("pipe count=%d opts=%j",i.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:b;function c(t,r){h("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,h("cleanup"),e.removeListener("close",g),e.removeListener("finish",y),e.removeListener("drain",p),e.removeListener("error",v),e.removeListener("unpipe",c),n.removeListener("end",l),n.removeListener("end",b),n.removeListener("data",m),f=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||p())}function l(){h("onend"),e.end()}i.endEmitted?o.nextTick(u):n.once("end",u),e.on("unpipe",c);var p=function(e){return function(){var t=e._readableState;h("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,j(e))}}(n);e.on("drain",p);var f=!1;var d=!1;function m(t){h("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==N(i.pipes,e))&&!f&&(h("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function v(t){h("onerror",t),b(),e.removeListener("error",v),0===s(e,"error")&&e.emit("error",t)}function g(){e.removeListener("finish",y),b()}function y(){h("onfinish"),e.removeListener("close",g),b()}function b(){h("unpipe"),n.unpipe(e)}return n.on("data",m),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",v),e.once("close",g),e.once("finish",y),e.emit("pipe",n),i.flowing||(h("pipe resume"),n.resume()),e},b.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<o;i++)r[i].emit("unpipe",this,n);return this}var a=N(t.pipes,e);return-1===a?this:(t.pipes.splice(a,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n),this)},b.prototype.on=function(e,t){var n=u.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var r=this._readableState;r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.emittedReadable=!1,r.reading?r.length&&S(this):o.nextTick(A,this))}return n},b.prototype.addListener=b.prototype.on,b.prototype.resume=function(){var e=this._readableState;return e.flowing||(h("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,o.nextTick(T,e,t))}(this,e)),this},b.prototype.pause=function(){return h("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(h("pause"),this._readableState.flowing=!1,this.emit("pause")),this},b.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var o in e.on("end",function(){if(h("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)}),e.on("data",function(o){(h("wrapped data"),n.decoder&&(o=n.decoder.write(o)),n.objectMode&&null==o)||(n.objectMode||o&&o.length)&&(t.push(o)||(r=!0,e.pause()))}),e)void 0===this[o]&&"function"==typeof e[o]&&(this[o]=function(t){return function(){return e[t].apply(e,arguments)}}(o));for(var i=0;i<g.length;i++)e.on(g[i],this.emit.bind(this,g[i]));return this._read=function(t){h("wrapped _read",t),r&&(r=!1,e.resume())},this},Object.defineProperty(b.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),b._fromList=P}).call(this,n(41),n(72))},function(e,t,n){e.exports=n(230).EventEmitter},function(e,t,n){"use strict";var r=n(174);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(678),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(41))},function(e,t,n){"use strict";var r=n(175).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=p,t=3;break;default:return this.write=f,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function p(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function f(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},i.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},i.prototype.text=function(e,t){var n=function(e,t,n){var r=t.length-1;if(r<n)return 0;var o=a(t[r]);if(o>=0)return o>0&&(e.lastNeed=o-1),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(e.lastNeed=o-2),o;if(--r<n||-2===o)return 0;if((o=a(t[r]))>=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";e.exports=a;var r=n(84),o=n(134);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}function a(e){if(!(this instanceof a))return new a(e);r.call(this,e),this._transformState={afterTransform:i.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",s)}function s(){var e=this;"function"==typeof this._flush?this._flush(function(t,n){u(e,t,n)}):u(this,null,null)}function u(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new Error("Calling transform done when ws.length != 0");if(e._transformState.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}o.inherits=n(106),o.inherits(a,r),a.prototype.push=function(e,t){return this._transformState.needTransform=!1,r.prototype.push.call(this,e,t)},a.prototype._transform=function(e,t,n){throw new Error("_transform() is not implemented")},a.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var o=this._readableState;(r.needTransform||o.needReadable||o.length<o.highWaterMark)&&this._read(o.highWaterMark)}},a.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},a.prototype._destroy=function(e,t){var n=this;r.prototype._destroy.call(this,e,function(e){t(e),n.emit("close")})}},function(e,t,n){"use strict";var r=n(85),o=Array.prototype.forEach,i=Object.create,a=function(e,t){var n;for(n in e)t[n]=e[n]};e.exports=function(e){var t=i(null);return o.call(arguments,function(e){r(e)&&a(Object(e),t)}),t}},function(e,t,n){"use strict";e.exports=function(){}},function(e,t,n){"use strict";var r=n(86);e.exports=function(e,t,n){var o;return isNaN(e)?(o=t)>=0?n&&o?o-1:o:1:!1!==e&&r(e)}},function(e,t,n){"use strict";e.exports=n(693)()?Object.assign:n(694)},function(e,t,n){"use strict";var r,o,i,a,s,u=n(86),c=function(e,t){return t};try{Object.defineProperty(c,"length",{configurable:!0,writable:!1,enumerable:!1,value:1})}catch(e){}1===c.length?(r={configurable:!0,writable:!1,enumerable:!1},o=Object.defineProperty,e.exports=function(e,t){return t=u(t),e.length===t?e:(r.value=t,o(e,"length",r))}):(a=n(396),s=[],i=function(e){var t,n=0;if(s[e])return s[e];for(t=[];e--;)t.push("a"+(++n).toString(36));return new Function("fn","return function ("+t.join(", ")+") { return fn.apply(this, arguments); };")},e.exports=function(e,t){var n;if(t=u(t),e.length===t)return e;n=i(t)(e);try{a(n,e)}catch(e){}return n})},function(e,t,n){"use strict";var r=n(107),o=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,s=Object.getOwnPropertySymbols;e.exports=function(e,t){var n,u=Object(r(t));if(e=Object(r(e)),a(u).forEach(function(r){try{o(e,r,i(t,r))}catch(e){n=e}}),"function"==typeof s&&s(u).forEach(function(r){try{o(e,r,i(t,r))}catch(e){n=e}}),void 0!==n)throw n;return e}},function(e,t,n){"use strict";var r=n(73),o=n(176),i=Function.prototype.call;e.exports=function(e,t){var n={},a=arguments[2];return r(t),o(e,function(e,r,o,s){n[r]=i.call(t,a,e,r,o,s)}),n}},function(e,t){e.exports=function(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}},function(e,t,n){var r=n(44);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){var i=e.return;throw void 0!==i&&r(i.call(e)),t}}},function(e,t,n){var r=n(98),o=n(34)("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(r.Array===e||i[o]===e)}},function(e,t,n){"use strict";var r=n(47),o=n(130);e.exports=function(e,t,n){t in e?r.f(e,t,o(0,n)):e[t]=n}},function(e,t,n){var r=n(34)("iterator"),o=!1;try{var i=[7][r]();i.return=function(){o=!0},Array.from(i,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var i=[7],a=i[r]();a.next=function(){return{done:n=!0}},i[r]=function(){return a},e(i)}catch(e){}return n}},function(e,t,n){var r=n(44),o=n(129),i=n(34)("species");e.exports=function(e,t){var n,a=r(e).constructor;return void 0===a||null==(n=r(a)[i])?t:o(n)}},function(e,t,n){var r,o,i,a=n(60),s=n(761),u=n(346),c=n(209),l=n(32),p=l.process,f=l.setImmediate,h=l.clearImmediate,d=l.MessageChannel,m=l.Dispatch,v=0,g={},y=function(){var e=+this;if(g.hasOwnProperty(e)){var t=g[e];delete g[e],t()}},b=function(e){y.call(e.data)};f&&h||(f=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return g[++v]=function(){s("function"==typeof e?e:Function(e),t)},r(v),v},h=function(e){delete g[e]},"process"==n(127)(p)?r=function(e){p.nextTick(a(y,e,1))}:m&&m.now?r=function(e){m.now(a(y,e,1))}:d?(i=(o=new d).port2,o.port1.onmessage=b,r=a(i.postMessage,i,1)):l.addEventListener&&"function"==typeof postMessage&&!l.importScripts?(r=function(e){l.postMessage(e+"","*")},l.addEventListener("message",b,!1)):r="onreadystatechange"in c("script")?function(e){u.appendChild(c("script")).onreadystatechange=function(){u.removeChild(this),y.call(e)}}:function(e){setTimeout(a(y,e,1),0)}),e.exports={set:f,clear:h}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,n){var r=n(44),o=n(40),i=n(237);e.exports=function(e,t){if(r(e),o(t)&&t.constructor===e)return t;var n=i.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){"use strict";var r=n(32),o=n(22),i=n(47),a=n(45),s=n(34)("species");e.exports=function(e){var t="function"==typeof o[e]?o[e]:r[e];a&&t&&!t[s]&&i.f(t,s,{configurable:!0,get:function(){return this}})}},function(e,t,n){"use strict";var r=n(110);e.exports=new r({include:[n(409)]})},function(e,t,n){"use strict";var r=n(110);e.exports=new r({include:[n(238)],implicit:[n(773),n(774),n(775),n(776)]})},function(e,t,n){var r=n(181),o=n(104),i=n(170),a=n(49),s=n(105);e.exports=function(e,t,n,u){if(!a(e))return e;for(var c=-1,l=(t=o(t,e)).length,p=l-1,f=e;null!=f&&++c<l;){var h=s(t[c]),d=n;if(c!=p){var m=f[h];void 0===(d=u?u(m,h,f):void 0)&&(d=a(m)?m:i(t[c+1])?[]:{})}r(f,h,d),f=f[h]}return e}},function(e,t,n){var r=n(412);e.exports=function(e,t,n){"__proto__"==t&&r?r(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}},function(e,t,n){var r=n(82),o=function(){try{var e=r(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();e.exports=o},function(e,t,n){e.exports=n(794)},function(e,t,n){e.exports=n(797)},function(e,t,n){"use strict";e.exports={hasCachedChildNodes:1}},function(e,t,n){"use strict";var r=n(21);n(15);e.exports=function(e,t){return null==t&&r("30"),null==e?t:Array.isArray(e)?Array.isArray(t)?(e.push.apply(e,t),e):(e.push(t),e):Array.isArray(t)?[e].concat(t):[e,t]}},function(e,t,n){"use strict";e.exports=function(e,t,n){Array.isArray(e)?e.forEach(t,n):e&&t.call(n,e)}},function(e,t,n){"use strict";var r=n(36),o=null;e.exports=function(){return!o&&r.canUseDOM&&(o="textContent"in document.documentElement?"textContent":"innerText"),o}},function(e,t,n){"use strict";var r=n(21);var o=n(88),i=(n(15),function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this._callbacks=null,this._contexts=null,this._arg=t}return e.prototype.enqueue=function(e,t){this._callbacks=this._callbacks||[],this._callbacks.push(e),this._contexts=this._contexts||[],this._contexts.push(t)},e.prototype.notifyAll=function(){var e=this._callbacks,t=this._contexts,n=this._arg;if(e&&t){e.length!==t.length&&r("24"),this._callbacks=null,this._contexts=null;for(var o=0;o<e.length;o++)e[o].call(t[o],n);e.length=0,t.length=0}},e.prototype.checkpoint=function(){return this._callbacks?this._callbacks.length:0},e.prototype.rollback=function(e){this._callbacks&&this._contexts&&(this._callbacks.length=e,this._contexts.length=e)},e.prototype.reset=function(){this._callbacks=null,this._contexts=null},e.prototype.destructor=function(){this.reset()},e}());e.exports=o.addPoolingTo(i)},function(e,t,n){"use strict";e.exports={logTopLevelRenders:!1}},function(e,t,n){"use strict";var r=n(27);function o(e){var t=e.type,n=e.nodeName;return n&&"input"===n.toLowerCase()&&("checkbox"===t||"radio"===t)}function i(e){return e._wrapperState.valueTracker}var a={_getTrackerFromNode:function(e){return i(r.getInstanceFromNode(e))},track:function(e){if(!i(e)){var t=r.getNodeFromInstance(e),n=o(t)?"checked":"value",a=Object.getOwnPropertyDescriptor(t.constructor.prototype,n),s=""+t[n];t.hasOwnProperty(n)||"function"!=typeof a.get||"function"!=typeof a.set||(Object.defineProperty(t,n,{enumerable:a.enumerable,configurable:!0,get:function(){return a.get.call(this)},set:function(e){s=""+e,a.set.call(this,e)}}),function(e,t){e._wrapperState.valueTracker=t}(e,{getValue:function(){return s},setValue:function(e){s=""+e},stopTracking:function(){!function(e){e._wrapperState.valueTracker=null}(e),delete t[n]}}))}},updateValueIfChanged:function(e){if(!e)return!1;var t=i(e);if(!t)return a.track(e),!0;var n,s,u=t.getValue(),c=((n=r.getNodeFromInstance(e))&&(s=o(n)?""+n.checked:n.value),s);return c!==u&&(t.setValue(c),!0)},stopTracking:function(e){var t=i(e);t&&t.stopTracking()}};e.exports=a},function(e,t,n){"use strict";var r={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};e.exports=function(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!r[e.type]:"textarea"===t}},function(e,t,n){"use strict";var r={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(e){r.currentScrollLeft=e.x,r.currentScrollTop=e.y}};e.exports=r},function(e,t,n){"use strict";var r=n(36),o=n(185),i=n(184),a=function(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t};r.canUseDOM&&("textContent"in document.documentElement||(a=function(e,t){3!==e.nodeType?i(e,o(t)):e.nodeValue=t})),e.exports=a},function(e,t,n){"use strict";e.exports=function(e){try{e.focus()}catch(e){}}},function(e,t,n){"use strict";var r={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0};var o=["Webkit","ms","Moz","O"];Object.keys(r).forEach(function(e){o.forEach(function(t){r[function(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}(t,e)]=r[e]})});var i={isUnitlessNumber:r,shorthandPropertyExpansions:{background:{backgroundAttachment:!0,backgroundColor:!0,backgroundImage:!0,backgroundPositionX:!0,backgroundPositionY:!0,backgroundRepeat:!0},backgroundPosition:{backgroundPositionX:!0,backgroundPositionY:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0},outline:{outlineWidth:!0,outlineStyle:!0,outlineColor:!0}}};e.exports=i},function(e,t,n){"use strict";var r=n(111),o=(n(27),n(50),n(828)),i=(n(23),new RegExp("^["+r.ATTRIBUTE_NAME_START_CHAR+"]["+r.ATTRIBUTE_NAME_CHAR+"]*$")),a={},s={};function u(e){return!!s.hasOwnProperty(e)||!a.hasOwnProperty(e)&&(i.test(e)?(s[e]=!0,!0):(a[e]=!0,!1))}function c(e,t){return null==t||e.hasBooleanValue&&!t||e.hasNumericValue&&isNaN(t)||e.hasPositiveNumericValue&&t<1||e.hasOverloadedBooleanValue&&!1===t}var l={createMarkupForID:function(e){return r.ID_ATTRIBUTE_NAME+"="+o(e)},setAttributeForID:function(e,t){e.setAttribute(r.ID_ATTRIBUTE_NAME,t)},createMarkupForRoot:function(){return r.ROOT_ATTRIBUTE_NAME+'=""'},setAttributeForRoot:function(e){e.setAttribute(r.ROOT_ATTRIBUTE_NAME,"")},createMarkupForProperty:function(e,t){var n=r.properties.hasOwnProperty(e)?r.properties[e]:null;if(n){if(c(n,t))return"";var i=n.attributeName;return n.hasBooleanValue||n.hasOverloadedBooleanValue&&!0===t?i+'=""':i+"="+o(t)}return r.isCustomAttribute(e)?null==t?"":e+"="+o(t):null},createMarkupForCustomAttribute:function(e,t){return u(e)&&null!=t?e+"="+o(t):""},setValueForProperty:function(e,t,n){var o=r.properties.hasOwnProperty(t)?r.properties[t]:null;if(o){var i=o.mutationMethod;if(i)i(e,n);else{if(c(o,n))return void this.deleteValueForProperty(e,t);if(o.mustUseProperty)e[o.propertyName]=n;else{var a=o.attributeName,s=o.attributeNamespace;s?e.setAttributeNS(s,a,""+n):o.hasBooleanValue||o.hasOverloadedBooleanValue&&!0===n?e.setAttribute(a,""):e.setAttribute(a,""+n)}}}else if(r.isCustomAttribute(t))return void l.setValueForAttribute(e,t,n)},setValueForAttribute:function(e,t,n){u(t)&&(null==n?e.removeAttribute(t):e.setAttribute(t,""+n))},deleteValueForAttribute:function(e,t){e.removeAttribute(t)},deleteValueForProperty:function(e,t){var n=r.properties.hasOwnProperty(t)?r.properties[t]:null;if(n){var o=n.mutationMethod;if(o)o(e,void 0);else if(n.mustUseProperty){var i=n.propertyName;n.hasBooleanValue?e[i]=!1:e[i]=""}else e.removeAttribute(n.attributeName)}else r.isCustomAttribute(t)&&e.removeAttribute(t)}};e.exports=l},function(e,t,n){"use strict";var r=n(25),o=n(248),i=n(27),a=n(55),s=(n(23),!1);function u(){if(this._rootNodeID&&this._wrapperState.pendingUpdate){this._wrapperState.pendingUpdate=!1;var e=this._currentElement.props,t=o.getValue(e);null!=t&&c(this,Boolean(e.multiple),t)}}function c(e,t,n){var r,o,a=i.getNodeFromInstance(e).options;if(t){for(r={},o=0;o<n.length;o++)r[""+n[o]]=!0;for(o=0;o<a.length;o++){var s=r.hasOwnProperty(a[o].value);a[o].selected!==s&&(a[o].selected=s)}}else{for(r=""+n,o=0;o<a.length;o++)if(a[o].value===r)return void(a[o].selected=!0);a.length&&(a[0].selected=!0)}}var l={getHostProps:function(e,t){return r({},t,{onChange:e._wrapperState.onChange,value:void 0})},mountWrapper:function(e,t){var n=o.getValue(t);e._wrapperState={pendingUpdate:!1,initialValue:null!=n?n:t.defaultValue,listeners:null,onChange:p.bind(e),wasMultiple:Boolean(t.multiple)},void 0===t.value||void 0===t.defaultValue||s||(s=!0)},getSelectValueContext:function(e){return e._wrapperState.initialValue},postUpdateWrapper:function(e){var t=e._currentElement.props;e._wrapperState.initialValue=void 0;var n=e._wrapperState.wasMultiple;e._wrapperState.wasMultiple=Boolean(t.multiple);var r=o.getValue(t);null!=r?(e._wrapperState.pendingUpdate=!1,c(e,Boolean(t.multiple),r)):n!==Boolean(t.multiple)&&(null!=t.defaultValue?c(e,Boolean(t.multiple),t.defaultValue):c(e,Boolean(t.multiple),t.multiple?[]:""))}};function p(e){var t=this._currentElement.props,n=o.executeOnChange(t,e);return this._rootNodeID&&(this._wrapperState.pendingUpdate=!0),a.asap(u,this),n}e.exports=l},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(837),a=n(431),s=n(432),u=(n(838),n(15),n(23),function(e){this.construct(e)});function c(e,t){var n;if(null===e||!1===e)n=a.create(c);else if("object"==typeof e){var o=e,i=o.type;if("function"!=typeof i&&"string"!=typeof i){var l="";0,l+=function(e){if(e){var t=e.getName();if(t)return" Check the render method of `"+t+"`."}return""}(o._owner),r("130",null==i?i:typeof i,l)}"string"==typeof o.type?n=s.createInternalComponent(o):!function(e){return"function"==typeof e&&void 0!==e.prototype&&"function"==typeof e.prototype.mountComponent&&"function"==typeof e.prototype.receiveComponent}(o.type)?n=new u(o):(n=new o.type(o)).getHostNode||(n.getHostNode=n.getNativeNode)}else"string"==typeof e||"number"==typeof e?n=s.createInstanceForText(e):r("131",typeof e);return n._mountIndex=0,n._mountImage=null,n}o(u.prototype,i,{_instantiateReactComponent:c}),e.exports=c},function(e,t,n){"use strict";var r=n(21),o=n(100),i=(n(15),{HOST:0,COMPOSITE:1,EMPTY:2,getType:function(e){return null===e||!1===e?i.EMPTY:o.isValidElement(e)?"function"==typeof e.type?i.COMPOSITE:i.HOST:void r("26",e)}});e.exports=i},function(e,t,n){"use strict";var r,o={injectEmptyComponentFactory:function(e){r=e}},i={create:function(e){return r(e)}};i.injection=o,e.exports=i},function(e,t,n){"use strict";var r=n(21),o=(n(15),null),i=null;var a={createInternalComponent:function(e){return o||r("111",e.type),new o(e)},createInstanceForText:function(e){return new i(e)},isTextComponent:function(e){return e instanceof i},injection:{injectGenericComponentClass:function(e){o=e},injectTextComponentClass:function(e){i=e}}};e.exports=a},function(e,t,n){"use strict";var r=n(21),o=(n(62),n(839)),i=n(840),a=(n(15),n(252)),s=(n(23),"."),u=":";function c(e,t){return e&&"object"==typeof e&&null!=e.key?a.escape(e.key):t.toString(36)}e.exports=function(e,t,n){return null==e?0:function e(t,n,l,p){var f,h=typeof t;if("undefined"!==h&&"boolean"!==h||(t=null),null===t||"string"===h||"number"===h||"object"===h&&t.$$typeof===o)return l(p,t,""===n?s+c(t,0):n),1;var d=0,m=""===n?s:n+u;if(Array.isArray(t))for(var v=0;v<t.length;v++)d+=e(f=t[v],m+c(f,v),l,p);else{var g=i(t);if(g){var y,b=g.call(t);if(g!==t.entries)for(var _=0;!(y=b.next()).done;)d+=e(f=y.value,m+c(f,_++),l,p);else for(;!(y=b.next()).done;){var w=y.value;w&&(d+=e(f=w[1],m+a.escape(w[0])+u+c(f,0),l,p))}}else if("object"===h){var x=String(t);r("31","[object Object]"===x?"object with keys {"+Object.keys(t).join(", ")+"}":x,"")}}return d}(e,"",t,n)}},function(e,t,n){"use strict";var r,o,i,a,s,u,c,l=n(133),p=n(62);n(15),n(23);function f(e){var t=Function.prototype.toString,n=Object.prototype.hasOwnProperty,r=RegExp("^"+t.call(n).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");try{var o=t.call(e);return r.test(o)}catch(e){return!1}}if("function"==typeof Array.from&&"function"==typeof Map&&f(Map)&&null!=Map.prototype&&"function"==typeof Map.prototype.keys&&f(Map.prototype.keys)&&"function"==typeof Set&&f(Set)&&null!=Set.prototype&&"function"==typeof Set.prototype.keys&&f(Set.prototype.keys)){var h=new Map,d=new Set;r=function(e,t){h.set(e,t)},o=function(e){return h.get(e)},i=function(e){h.delete(e)},a=function(){return Array.from(h.keys())},s=function(e){d.add(e)},u=function(e){d.delete(e)},c=function(){return Array.from(d.keys())}}else{var m={},v={},g=function(e){return"."+e},y=function(e){return parseInt(e.substr(1),10)};r=function(e,t){var n=g(e);m[n]=t},o=function(e){var t=g(e);return m[t]},i=function(e){var t=g(e);delete m[t]},a=function(){return Object.keys(m).map(y)},s=function(e){var t=g(e);v[t]=!0},u=function(e){var t=g(e);delete v[t]},c=function(){return Object.keys(v).map(y)}}var b=[];function _(e){var t=o(e);if(t){var n=t.childIDs;i(e),n.forEach(_)}}function w(e,t,n){return"\n in "+(e||"Unknown")+(t?" (at "+t.fileName.replace(/^.*[\\\/]/,"")+":"+t.lineNumber+")":n?" (created by "+n+")":"")}function x(e){return null==e?"#empty":"string"==typeof e||"number"==typeof e?"#text":"string"==typeof e.type?e.type:e.type.displayName||e.type.name||"Unknown"}function E(e){var t,n=S.getDisplayName(e),r=S.getElement(e),o=S.getOwnerID(e);return o&&(t=S.getDisplayName(o)),w(n,r&&r._source,t)}var S={onSetChildren:function(e,t){var n=o(e);n||l("144"),n.childIDs=t;for(var r=0;r<t.length;r++){var i=t[r],a=o(i);a||l("140"),null==a.childIDs&&"object"==typeof a.element&&null!=a.element&&l("141"),a.isMounted||l("71"),null==a.parentID&&(a.parentID=e),a.parentID!==e&&l("142",i,a.parentID,e)}},onBeforeMountComponent:function(e,t,n){r(e,{element:t,parentID:n,text:null,childIDs:[],isMounted:!1,updateCount:0})},onBeforeUpdateComponent:function(e,t){var n=o(e);n&&n.isMounted&&(n.element=t)},onMountComponent:function(e){var t=o(e);t||l("144"),t.isMounted=!0,0===t.parentID&&s(e)},onUpdateComponent:function(e){var t=o(e);t&&t.isMounted&&t.updateCount++},onUnmountComponent:function(e){var t=o(e);t&&(t.isMounted=!1,0===t.parentID&&u(e));b.push(e)},purgeUnmountedComponents:function(){if(!S._preventPurging){for(var e=0;e<b.length;e++){_(b[e])}b.length=0}},isMounted:function(e){var t=o(e);return!!t&&t.isMounted},getCurrentStackAddendum:function(e){var t="";if(e){var n=x(e),r=e._owner;t+=w(n,e._source,r&&r.getName())}var o=p.current,i=o&&o._debugID;return t+=S.getStackAddendumByID(i)},getStackAddendumByID:function(e){for(var t="";e;)t+=E(e),e=S.getParentID(e);return t},getChildIDs:function(e){var t=o(e);return t?t.childIDs:[]},getDisplayName:function(e){var t=S.getElement(e);return t?x(t):null},getElement:function(e){var t=o(e);return t?t.element:null},getOwnerID:function(e){var t=S.getElement(e);return t&&t._owner?t._owner._debugID:null},getParentID:function(e){var t=o(e);return t?t.parentID:null},getSource:function(e){var t=o(e),n=t?t.element:null;return null!=n?n._source:null},getText:function(e){var t=S.getElement(e);return"string"==typeof t?t:"number"==typeof t?""+t:null},getUpdateCount:function(e){var t=o(e);return t?t.updateCount:0},getRootIDs:c,getRegisteredIDs:a,pushNonStandardWarningStack:function(e,t){if("function"==typeof console.reactStack){var n=[],r=p.current,o=r&&r._debugID;try{for(e&&n.push({name:o?S.getDisplayName(o):null,fileName:t?t.fileName:null,lineNumber:t?t.lineNumber:null});o;){var i=S.getElement(o),a=S.getParentID(o),s=S.getOwnerID(o),u=s?S.getDisplayName(s):null,c=i&&i._source;n.push({name:u,fileName:c?c.fileName:null,lineNumber:c?c.lineNumber:null}),o=a}}catch(e){}console.reactStack(n)}},popNonStandardWarningStack:function(){"function"==typeof console.reactStackEnd&&console.reactStackEnd()}};e.exports=S},function(e,t,n){"use strict";var r=n(54),o={listen:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!1),{remove:function(){e.removeEventListener(t,n,!1)}}):e.attachEvent?(e.attachEvent("on"+t,n),{remove:function(){e.detachEvent("on"+t,n)}}):void 0},capture:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!0),{remove:function(){e.removeEventListener(t,n,!0)}}):{remove:r}},registerDefault:function(){}};e.exports=o},function(e,t,n){"use strict";var r=n(852),o=n(854),i=n(425),a=n(437);var s={hasSelectionCapabilities:function(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&"text"===e.type||"textarea"===t||"true"===e.contentEditable)},getSelectionInformation:function(){var e=a();return{focusedElem:e,selectionRange:s.hasSelectionCapabilities(e)?s.getSelection(e):null}},restoreSelection:function(e){var t,n=a(),r=e.focusedElem,u=e.selectionRange;n!==r&&(t=r,o(document.documentElement,t))&&(s.hasSelectionCapabilities(r)&&s.setSelection(r,u),i(r))},getSelection:function(e){var t;if("selectionStart"in e)t={start:e.selectionStart,end:e.selectionEnd};else if(document.selection&&e.nodeName&&"input"===e.nodeName.toLowerCase()){var n=document.selection.createRange();n.parentElement()===e&&(t={start:-n.moveStart("character",-e.value.length),end:-n.moveEnd("character",-e.value.length)})}else t=r.getOffsets(e);return t||{start:0,end:0}},setSelection:function(e,t){var n=t.start,o=t.end;if(void 0===o&&(o=n),"selectionStart"in e)e.selectionStart=n,e.selectionEnd=Math.min(o,e.value.length);else if(document.selection&&e.nodeName&&"input"===e.nodeName.toLowerCase()){var i=e.createTextRange();i.collapse(!0),i.moveStart("character",n),i.moveEnd("character",o-n),i.select()}else r.setOffsets(e,t)}};e.exports=s},function(e,t,n){"use strict";e.exports=function(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}},function(e,t,n){"use strict";var r=n(21),o=n(113),i=n(111),a=n(100),s=n(186),u=(n(62),n(27)),c=n(869),l=n(870),p=n(420),f=n(140),h=(n(50),n(871)),d=n(112),m=n(253),v=n(55),g=n(161),y=n(429),b=(n(15),n(184)),_=n(251),w=(n(23),i.ID_ATTRIBUTE_NAME),x=i.ROOT_ATTRIBUTE_NAME,E=1,S=9,C=11,k={};function O(e){return e?e.nodeType===S?e.documentElement:e.firstChild:null}function A(e,t,n,r,o){var i;if(p.logTopLevelRenders){var a=e._currentElement.props.child.type;i="React mount: "+("string"==typeof a?a:a.displayName||a.name),console.time(i)}var s=d.mountComponent(e,n,null,c(e,t),o,0);i&&console.timeEnd(i),e._renderedComponent._topLevelWrapper=e,D._mountImageIntoNode(s,t,e,r,n)}function T(e,t,n,r){var o=v.ReactReconcileTransaction.getPooled(!n&&l.useCreateElement);o.perform(A,null,e,t,o,n,r),v.ReactReconcileTransaction.release(o)}function j(e,t,n){for(0,d.unmountComponent(e,n),t.nodeType===S&&(t=t.documentElement);t.lastChild;)t.removeChild(t.lastChild)}function P(e){var t=O(e);if(t){var n=u.getInstanceFromNode(t);return!(!n||!n._hostParent)}}function I(e){return!(!e||e.nodeType!==E&&e.nodeType!==S&&e.nodeType!==C)}function M(e){var t=function(e){var t=O(e),n=t&&u.getInstanceFromNode(t);return n&&!n._hostParent?n:null}(e);return t?t._hostContainerInfo._topLevelWrapper:null}var N=1,R=function(){this.rootID=N++};R.prototype.isReactComponent={},R.prototype.render=function(){return this.props.child},R.isReactTopLevelWrapper=!0;var D={TopLevelWrapper:R,_instancesByReactRootID:k,scrollMonitor:function(e,t){t()},_updateRootComponent:function(e,t,n,r,o){return D.scrollMonitor(r,function(){m.enqueueElementInternal(e,t,n),o&&m.enqueueCallbackInternal(e,o)}),e},_renderNewRootComponent:function(e,t,n,o){I(t)||r("37"),s.ensureScrollValueMonitoring();var i=y(e,!1);v.batchedUpdates(T,i,t,n,o);var a=i._instance.rootID;return k[a]=i,i},renderSubtreeIntoContainer:function(e,t,n,o){return null!=e&&f.has(e)||r("38"),D._renderSubtreeIntoContainer(e,t,n,o)},_renderSubtreeIntoContainer:function(e,t,n,o){m.validateCallback(o,"ReactDOM.render"),a.isValidElement(t)||r("39","string"==typeof t?" Instead of passing a string like 'div', pass React.createElement('div') or <div />.":"function"==typeof t?" Instead of passing a class like Foo, pass React.createElement(Foo) or <Foo />.":null!=t&&void 0!==t.props?" This may be caused by unintentionally loading two independent copies of React.":"");var i,s=a.createElement(R,{child:t});if(e){var u=f.get(e);i=u._processChildContext(u._context)}else i=g;var c=M(n);if(c){var l=c._currentElement.props.child;if(_(l,t)){var p=c._renderedComponent.getPublicInstance(),h=o&&function(){o.call(p)};return D._updateRootComponent(c,s,i,n,h),p}D.unmountComponentAtNode(n)}var d,v=O(n),y=v&&!(!(d=v).getAttribute||!d.getAttribute(w)),b=P(n),x=y&&!c&&!b,E=D._renderNewRootComponent(s,n,x,i)._renderedComponent.getPublicInstance();return o&&o.call(E),E},render:function(e,t,n){return D._renderSubtreeIntoContainer(null,e,t,n)},unmountComponentAtNode:function(e){I(e)||r("40");var t=M(e);if(!t){P(e),1===e.nodeType&&e.hasAttribute(x);return!1}return delete k[t._instance.rootID],v.batchedUpdates(j,t,e,!1),!0},_mountImageIntoNode:function(e,t,n,i,a){if(I(t)||r("41"),i){var s=O(t);if(h.canReuseMarkup(e,s))return void u.precacheNode(n,s);var c=s.getAttribute(h.CHECKSUM_ATTR_NAME);s.removeAttribute(h.CHECKSUM_ATTR_NAME);var l=s.outerHTML;s.setAttribute(h.CHECKSUM_ATTR_NAME,c);var p=e,f=function(e,t){for(var n=Math.min(e.length,t.length),r=0;r<n;r++)if(e.charAt(r)!==t.charAt(r))return r;return e.length===t.length?-1:n}(p,l),d=" (client) "+p.substring(f-20,f+20)+"\n (server) "+l.substring(f-20,f+20);t.nodeType===S&&r("42",d)}if(t.nodeType===S&&r("43"),a.useCreateElement){for(;t.lastChild;)t.removeChild(t.lastChild);o.insertTreeBefore(t,e,null)}else b(t,e),u.precacheNode(n,t.firstChild)}};e.exports=D},function(e,t,n){"use strict";var r=n(430);e.exports=function(e){for(var t;(t=e._renderedNodeType)===r.COMPOSITE;)e=e._renderedComponent;return t===r.HOST?e._renderedComponent:t===r.EMPTY?null:void 0}},function(e,t,n){e.exports=n(877)()},function(e,t,n){"use strict";t.__esModule=!0;var r,o=n(440),i=(r=o)&&r.__esModule?r:{default:r};t.default=i.default.shape({subscribe:i.default.func.isRequired,dispatch:i.default.func.isRequired,getState:i.default.func.isRequired})},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(e);try{throw new Error(e)}catch(e){}}},function(e,t,n){var r=n(220),o=n(884),i=n(181),a=n(885),s=n(886),u=n(889),c=n(890),l=n(891),p=n(892),f=n(372),h=n(446),d=n(172),m=n(893),v=n(894),g=n(899),y=n(35),b=n(224),_=n(901),w=n(49),x=n(903),E=n(83),S=1,C=2,k=4,O="[object Arguments]",A="[object Function]",T="[object GeneratorFunction]",j="[object Object]",P={};P[O]=P["[object Array]"]=P["[object ArrayBuffer]"]=P["[object DataView]"]=P["[object Boolean]"]=P["[object Date]"]=P["[object Float32Array]"]=P["[object Float64Array]"]=P["[object Int8Array]"]=P["[object Int16Array]"]=P["[object Int32Array]"]=P["[object Map]"]=P["[object Number]"]=P[j]=P["[object RegExp]"]=P["[object Set]"]=P["[object String]"]=P["[object Symbol]"]=P["[object Uint8Array]"]=P["[object Uint8ClampedArray]"]=P["[object Uint16Array]"]=P["[object Uint32Array]"]=!0,P["[object Error]"]=P[A]=P["[object WeakMap]"]=!1,e.exports=function e(t,n,I,M,N,R){var D,L=n&S,U=n&C,q=n&k;if(I&&(D=N?I(t,M,N,R):I(t)),void 0!==D)return D;if(!w(t))return t;var F=y(t);if(F){if(D=m(t),!L)return c(t,D)}else{var z=d(t),B=z==A||z==T;if(b(t))return u(t,L);if(z==j||z==O||B&&!N){if(D=U||B?{}:g(t),!L)return U?p(t,s(D,t)):l(t,a(D,t))}else{if(!P[z])return N?t:{};D=v(t,z,L)}}R||(R=new r);var V=R.get(t);if(V)return V;R.set(t,D),x(t)?t.forEach(function(r){D.add(e(r,n,I,r,t,R))}):_(t)&&t.forEach(function(r,o){D.set(o,e(r,n,I,o,t,R))});var H=q?U?h:f:U?keysIn:E,W=F?void 0:H(t);return o(W||t,function(r,o){W&&(r=t[o=r]),i(D,o,e(r,n,I,o,t,R))}),D}},function(e,t,n){var r=n(375),o=n(887),i=n(103);e.exports=function(e){return i(e)?r(e,!0):o(e)}},function(e,t,n){var r=n(221),o=n(257),i=n(222),a=n(374),s=Object.getOwnPropertySymbols?function(e){for(var t=[];e;)r(t,i(e)),e=o(e);return t}:a;e.exports=s},function(e,t,n){var r=n(373),o=n(445),i=n(444);e.exports=function(e){return r(e,i,o)}},function(e,t,n){var r=n(909),o=n(448),i=n(449);e.exports=function(e){return i(o(e,void 0,r),e+"")}},function(e,t,n){var r=n(912),o=Math.max;e.exports=function(e,t,n){return t=o(void 0===t?e.length-1:t,0),function(){for(var i=arguments,a=-1,s=o(i.length-t,0),u=Array(s);++a<s;)u[a]=i[t+a];a=-1;for(var c=Array(t+1);++a<t;)c[a]=i[a];return c[t]=n(u),r(e,this,c)}}},function(e,t,n){var r=n(913),o=n(915)(r);e.exports=o},function(e,t,n){var r={strict:!0},o=n(926),i=function(e,t){return o(e,t,r)},a=n(259);t.JsonPatchError=a.PatchError,t.deepClone=a._deepClone;var s={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var r=e[t];return delete e[t],{newDocument:n,removed:r}},replace:function(e,t,n){var r=e[t];return e[t]=this.value,{newDocument:n,removed:r}},move:function(e,t,n){var r=c(n,this.path);r&&(r=a._deepClone(r));var o=l(n,{op:"remove",path:this.from}).removed;return l(n,{op:"add",path:this.path,value:o}),{newDocument:n,removed:r}},copy:function(e,t,n){var r=c(n,this.from);return l(n,{op:"add",path:this.path,value:a._deepClone(r)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:i(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},u={add:function(e,t,n){return a.isInteger(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var r=e[t];return e[t]=this.value,{newDocument:n,removed:r}},move:s.move,copy:s.copy,test:s.test,_get:s._get};function c(e,t){if(""==t)return e;var n={op:"_get",path:t};return l(e,n),n.value}function l(e,n,r,o,l,p){if(void 0===r&&(r=!1),void 0===o&&(o=!0),void 0===l&&(l=!0),void 0===p&&(p=0),r&&("function"==typeof r?r(n,0,e,n.path):f(n,0)),""===n.path){var h={newDocument:e};if("add"===n.op)return h.newDocument=n.value,h;if("replace"===n.op)return h.newDocument=n.value,h.removed=e,h;if("move"===n.op||"copy"===n.op)return h.newDocument=c(e,n.from),"move"===n.op&&(h.removed=e),h;if("test"===n.op){if(h.test=i(e,n.value),!1===h.test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",p,n,e);return h.newDocument=e,h}if("remove"===n.op)return h.removed=e,h.newDocument=null,h;if("_get"===n.op)return n.value=e,h;if(r)throw new t.JsonPatchError("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",p,n,e);return h}o||(e=a._deepClone(e));var d=(n.path||"").split("/"),m=e,v=1,g=d.length,y=void 0,b=void 0,_=void 0;for(_="function"==typeof r?r:f;;){if(b=d[v],l&&"__proto__"==b)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(r&&void 0===y&&(void 0===m[b]?y=d.slice(0,v).join("/"):v==g-1&&(y=n.path),void 0!==y&&_(n,0,e,y)),v++,Array.isArray(m)){if("-"===b)b=m.length;else{if(r&&!a.isInteger(b))throw new t.JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",p,n,e);a.isInteger(b)&&(b=~~b)}if(v>=g){if(r&&"add"===n.op&&b>m.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",p,n,e);if(!1===(h=u[n.op].call(n,m,b,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",p,n,e);return h}}else if(b&&-1!=b.indexOf("~")&&(b=a.unescapePathComponent(b)),v>=g){if(!1===(h=s[n.op].call(n,m,b,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",p,n,e);return h}m=m[b]}}function p(e,n,r,o,i){if(void 0===o&&(o=!0),void 0===i&&(i=!0),r&&!Array.isArray(n))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=a._deepClone(e));for(var s=new Array(n.length),u=0,c=n.length;u<c;u++)s[u]=l(e,n[u],r,!0,i,u),e=s[u].newDocument;return s.newDocument=e,s}function f(e,n,r,o){if("object"!=typeof e||null===e||Array.isArray(e))throw new t.JsonPatchError("Operation is not an object","OPERATION_NOT_AN_OBJECT",n,e,r);if(!s[e.op])throw new t.JsonPatchError("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",n,e,r);if("string"!=typeof e.path)throw new t.JsonPatchError("Operation `path` property is not a string","OPERATION_PATH_INVALID",n,e,r);if(0!==e.path.indexOf("/")&&e.path.length>0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",n,e,r);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",n,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",n,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&a.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",n,e,r);if(r)if("add"==e.op){var i=e.path.split("/").length,u=o.split("/").length;if(i!==u+1&&i!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",n,e,r)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==o)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",n,e,r)}else if("move"===e.op||"copy"===e.op){var c=h([{op:"_get",path:e.from,value:void 0}],r);if(c&&"OPERATION_PATH_UNRESOLVABLE"===c.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",n,e,r)}}function h(e,n,r){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(n)p(a._deepClone(n),a._deepClone(e),r||!0);else{r=r||f;for(var o=0;o<e.length;o++)r(e[o],o,n,void 0)}}catch(e){if(e instanceof t.JsonPatchError)return e;throw e}}t.getValueByPointer=c,t.applyOperation=l,t.applyPatch=p,t.applyReducer=function(e,n,r){var o=l(e,n);if(!1===o.test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",r,n,e);return o.newDocument},t.validator=f,t.validate=h},function(e,t,n){"use strict";var r=Object.prototype.hasOwnProperty,o=Array.isArray,i=function(){for(var e=[],t=0;t<256;++t)e.push("%"+((t<16?"0":"")+t.toString(16)).toUpperCase());return e}(),a=function(e,t){for(var n=t&&t.plainObjects?Object.create(null):{},r=0;r<e.length;++r)void 0!==e[r]&&(n[r]=e[r]);return n};e.exports={arrayToObject:a,assign:function(e,t){return Object.keys(t).reduce(function(e,n){return e[n]=t[n],e},e)},combine:function(e,t){return[].concat(e,t)},compact:function(e){for(var t=[{obj:{o:e},prop:"o"}],n=[],r=0;r<t.length;++r)for(var i=t[r],a=i.obj[i.prop],s=Object.keys(a),u=0;u<s.length;++u){var c=s[u],l=a[c];"object"==typeof l&&null!==l&&-1===n.indexOf(l)&&(t.push({obj:a,prop:c}),n.push(l))}return function(e){for(;e.length>1;){var t=e.pop(),n=t.obj[t.prop];if(o(n)){for(var r=[],i=0;i<n.length;++i)void 0!==n[i]&&r.push(n[i]);t.obj[t.prop]=r}}}(t),e},decode:function(e,t,n){var r=e.replace(/\+/g," ");if("iso-8859-1"===n)return r.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(r)}catch(e){return r}},encode:function(e,t,n){if(0===e.length)return e;var r="string"==typeof e?e:String(e);if("iso-8859-1"===n)return escape(r).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var o="",a=0;a<r.length;++a){var s=r.charCodeAt(a);45===s||46===s||95===s||126===s||s>=48&&s<=57||s>=65&&s<=90||s>=97&&s<=122?o+=r.charAt(a):s<128?o+=i[s]:s<2048?o+=i[192|s>>6]+i[128|63&s]:s<55296||s>=57344?o+=i[224|s>>12]+i[128|s>>6&63]+i[128|63&s]:(a+=1,s=65536+((1023&s)<<10|1023&r.charCodeAt(a)),o+=i[240|s>>18]+i[128|s>>12&63]+i[128|s>>6&63]+i[128|63&s])}return o},isBuffer:function(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},merge:function e(t,n,i){if(!n)return t;if("object"!=typeof n){if(o(t))t.push(n);else{if(!t||"object"!=typeof t)return[t,n];(i&&(i.plainObjects||i.allowPrototypes)||!r.call(Object.prototype,n))&&(t[n]=!0)}return t}if(!t||"object"!=typeof t)return[t].concat(n);var s=t;return o(t)&&!o(n)&&(s=a(t,i)),o(t)&&o(n)?(n.forEach(function(n,o){if(r.call(t,o)){var a=t[o];a&&"object"==typeof a&&n&&"object"==typeof n?t[o]=e(a,n,i):t.push(n)}else t[o]=n}),t):Object.keys(n).reduce(function(t,o){var a=n[o];return r.call(t,o)?t[o]=e(t[o],a,i):t[o]=a,t},s)}}},function(e,t,n){"use strict";var r=String.prototype.replace,o=/%20/g;e.exports={default:"RFC3986",formatters:{RFC1738:function(e){return r.call(e,o,"+")},RFC3986:function(e){return e}},RFC1738:"RFC1738",RFC3986:"RFC3986"}},function(e,t,n){"use strict";var r=n(32),o=n(30),i=n(132),a=n(80),s=n(71),u=n(179),c=n(108),l=n(178),p=n(40),f=n(131),h=n(47).f,d=n(260)(0),m=n(45);e.exports=function(e,t,n,v,g,y){var b=r[e],_=b,w=g?"set":"add",x=_&&_.prototype,E={};return m&&"function"==typeof _&&(y||x.forEach&&!a(function(){(new _).entries().next()}))?(_=t(function(t,n){l(t,_,e,"_c"),t._c=new b,null!=n&&c(n,g,t[w],t)}),d("add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON".split(","),function(e){var t="add"==e||"set"==e;e in x&&(!y||"clear"!=e)&&s(_.prototype,e,function(n,r){if(l(this,_,e),!t&&y&&!p(n))return"get"==e&&void 0;var o=this._c[e](0===n?0:n,r);return t?this:o})}),y||h(_.prototype,"size",{get:function(){return this._c.size}})):(_=v.getConstructor(t,e,g,w),u(_.prototype,n),i.NEED=!0),f(_,e),E[e]=_,o(o.G+o.W+o.F,E),y||v.setStrong(_,e,g),_}},function(e,t,n){"use strict";var r=n(30);e.exports=function(e){r(r.S,e,{of:function(){for(var e=arguments.length,t=new Array(e);e--;)t[e]=arguments[e];return new this(t)}})}},function(e,t,n){"use strict";var r=n(30),o=n(129),i=n(60),a=n(108);e.exports=function(e){r(r.S,e,{from:function(e){var t,n,r,s,u=arguments[1];return o(this),(t=void 0!==u)&&o(u),null==e?new this:(n=[],t?(r=0,s=i(u,arguments[2],2),a(e,!1,function(e){n.push(s(e,r++))})):a(e,!1,n.push,n),new this(n))}})}},function(e,t){e.exports="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwcHgiICBoZWlnaHQ9IjIwMHB4IiAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiIGNsYXNzPSJsZHMtcm9sbGluZyIgc3R5bGU9ImJhY2tncm91bmQtaW1hZ2U6IG5vbmU7IGJhY2tncm91bmQtcG9zaXRpb246IGluaXRpYWwgaW5pdGlhbDsgYmFja2dyb3VuZC1yZXBlYXQ6IGluaXRpYWwgaW5pdGlhbDsiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIG5nLWF0dHItc3Ryb2tlPSJ7e2NvbmZpZy5jb2xvcn19IiBuZy1hdHRyLXN0cm9rZS13aWR0aD0ie3tjb25maWcud2lkdGh9fSIgbmctYXR0ci1yPSJ7e2NvbmZpZy5yYWRpdXN9fSIgbmctYXR0ci1zdHJva2UtZGFzaGFycmF5PSJ7e2NvbmZpZy5kYXNoYXJyYXl9fSIgc3Ryb2tlPSIjNTU1NTU1IiBzdHJva2Utd2lkdGg9IjEwIiByPSIzNSIgc3Ryb2tlLWRhc2hhcnJheT0iMTY0LjkzMzYxNDMxMzQ2NDE1IDU2Ljk3Nzg3MTQzNzgyMTM4Ij48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgY2FsY01vZGU9ImxpbmVhciIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCIga2V5VGltZXM9IjA7MSIgZHVyPSIxcyIgYmVnaW49IjBzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSI+PC9hbmltYXRlVHJhbnNmb3JtPjwvY2lyY2xlPjwvc3ZnPgo="},function(e,t,n){"use strict";e.exports={Aacute:"Á",aacute:"á",Abreve:"Ă",abreve:"ă",ac:"∾",acd:"∿",acE:"∾̳",Acirc:"Â",acirc:"â",acute:"´",Acy:"А",acy:"а",AElig:"Æ",aelig:"æ",af:"⁡",Afr:"𝔄",afr:"𝔞",Agrave:"À",agrave:"à",alefsym:"ℵ",aleph:"ℵ",Alpha:"Α",alpha:"α",Amacr:"Ā",amacr:"ā",amalg:"⨿",AMP:"&",amp:"&",And:"⩓",and:"∧",andand:"⩕",andd:"⩜",andslope:"⩘",andv:"⩚",ang:"∠",ange:"⦤",angle:"∠",angmsd:"∡",angmsdaa:"⦨",angmsdab:"⦩",angmsdac:"⦪",angmsdad:"⦫",angmsdae:"⦬",angmsdaf:"⦭",angmsdag:"⦮",angmsdah:"⦯",angrt:"∟",angrtvb:"⊾",angrtvbd:"⦝",angsph:"∢",angst:"Å",angzarr:"⍼",Aogon:"Ą",aogon:"ą",Aopf:"𝔸",aopf:"𝕒",ap:"≈",apacir:"⩯",apE:"⩰",ape:"≊",apid:"≋",apos:"'",ApplyFunction:"⁡",approx:"≈",approxeq:"≊",Aring:"Å",aring:"å",Ascr:"𝒜",ascr:"𝒶",Assign:"≔",ast:"*",asymp:"≈",asympeq:"≍",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",awconint:"∳",awint:"⨑",backcong:"≌",backepsilon:"϶",backprime:"‵",backsim:"∽",backsimeq:"⋍",Backslash:"∖",Barv:"⫧",barvee:"⊽",Barwed:"⌆",barwed:"⌅",barwedge:"⌅",bbrk:"⎵",bbrktbrk:"⎶",bcong:"≌",Bcy:"Б",bcy:"б",bdquo:"„",becaus:"∵",Because:"∵",because:"∵",bemptyv:"⦰",bepsi:"϶",bernou:"ℬ",Bernoullis:"ℬ",Beta:"Β",beta:"β",beth:"ℶ",between:"≬",Bfr:"𝔅",bfr:"𝔟",bigcap:"⋂",bigcirc:"◯",bigcup:"⋃",bigodot:"⨀",bigoplus:"⨁",bigotimes:"⨂",bigsqcup:"⨆",bigstar:"★",bigtriangledown:"▽",bigtriangleup:"△",biguplus:"⨄",bigvee:"⋁",bigwedge:"⋀",bkarow:"⤍",blacklozenge:"⧫",blacksquare:"▪",blacktriangle:"▴",blacktriangledown:"▾",blacktriangleleft:"◂",blacktriangleright:"▸",blank:"␣",blk12:"▒",blk14:"░",blk34:"▓",block:"█",bne:"=⃥",bnequiv:"≡⃥",bNot:"⫭",bnot:"⌐",Bopf:"𝔹",bopf:"𝕓",bot:"⊥",bottom:"⊥",bowtie:"⋈",boxbox:"⧉",boxDL:"╗",boxDl:"╖",boxdL:"╕",boxdl:"┐",boxDR:"╔",boxDr:"╓",boxdR:"╒",boxdr:"┌",boxH:"═",boxh:"─",boxHD:"╦",boxHd:"╤",boxhD:"╥",boxhd:"┬",boxHU:"╩",boxHu:"╧",boxhU:"╨",boxhu:"┴",boxminus:"⊟",boxplus:"⊞",boxtimes:"⊠",boxUL:"╝",boxUl:"╜",boxuL:"╛",boxul:"┘",boxUR:"╚",boxUr:"╙",boxuR:"╘",boxur:"└",boxV:"║",boxv:"│",boxVH:"╬",boxVh:"╫",boxvH:"╪",boxvh:"┼",boxVL:"╣",boxVl:"╢",boxvL:"╡",boxvl:"┤",boxVR:"╠",boxVr:"╟",boxvR:"╞",boxvr:"├",bprime:"‵",Breve:"˘",breve:"˘",brvbar:"¦",Bscr:"ℬ",bscr:"𝒷",bsemi:"⁏",bsim:"∽",bsime:"⋍",bsol:"\\",bsolb:"⧅",bsolhsub:"⟈",bull:"•",bullet:"•",bump:"≎",bumpE:"⪮",bumpe:"≏",Bumpeq:"≎",bumpeq:"≏",Cacute:"Ć",cacute:"ć",Cap:"⋒",cap:"∩",capand:"⩄",capbrcup:"⩉",capcap:"⩋",capcup:"⩇",capdot:"⩀",CapitalDifferentialD:"ⅅ",caps:"∩︀",caret:"⁁",caron:"ˇ",Cayleys:"ℭ",ccaps:"⩍",Ccaron:"Č",ccaron:"č",Ccedil:"Ç",ccedil:"ç",Ccirc:"Ĉ",ccirc:"ĉ",Cconint:"∰",ccups:"⩌",ccupssm:"⩐",Cdot:"Ċ",cdot:"ċ",cedil:"¸",Cedilla:"¸",cemptyv:"⦲",cent:"¢",CenterDot:"·",centerdot:"·",Cfr:"ℭ",cfr:"𝔠",CHcy:"Ч",chcy:"ч",check:"✓",checkmark:"✓",Chi:"Χ",chi:"χ",cir:"○",circ:"ˆ",circeq:"≗",circlearrowleft:"↺",circlearrowright:"↻",circledast:"⊛",circledcirc:"⊚",circleddash:"⊝",CircleDot:"⊙",circledR:"®",circledS:"Ⓢ",CircleMinus:"⊖",CirclePlus:"⊕",CircleTimes:"⊗",cirE:"⧃",cire:"≗",cirfnint:"⨐",cirmid:"⫯",cirscir:"⧂",ClockwiseContourIntegral:"∲",CloseCurlyDoubleQuote:"”",CloseCurlyQuote:"’",clubs:"♣",clubsuit:"♣",Colon:"∷",colon:":",Colone:"⩴",colone:"≔",coloneq:"≔",comma:",",commat:"@",comp:"∁",compfn:"∘",complement:"∁",complexes:"ℂ",cong:"≅",congdot:"⩭",Congruent:"≡",Conint:"∯",conint:"∮",ContourIntegral:"∮",Copf:"ℂ",copf:"𝕔",coprod:"∐",Coproduct:"∐",COPY:"©",copy:"©",copysr:"℗",CounterClockwiseContourIntegral:"∳",crarr:"↵",Cross:"⨯",cross:"✗",Cscr:"𝒞",cscr:"𝒸",csub:"⫏",csube:"⫑",csup:"⫐",csupe:"⫒",ctdot:"⋯",cudarrl:"⤸",cudarrr:"⤵",cuepr:"⋞",cuesc:"⋟",cularr:"↶",cularrp:"⤽",Cup:"⋓",cup:"∪",cupbrcap:"⩈",CupCap:"≍",cupcap:"⩆",cupcup:"⩊",cupdot:"⊍",cupor:"⩅",cups:"∪︀",curarr:"↷",curarrm:"⤼",curlyeqprec:"⋞",curlyeqsucc:"⋟",curlyvee:"⋎",curlywedge:"⋏",curren:"¤",curvearrowleft:"↶",curvearrowright:"↷",cuvee:"⋎",cuwed:"⋏",cwconint:"∲",cwint:"∱",cylcty:"⌭",Dagger:"‡",dagger:"†",daleth:"ℸ",Darr:"↡",dArr:"⇓",darr:"↓",dash:"‐",Dashv:"⫤",dashv:"⊣",dbkarow:"⤏",dblac:"˝",Dcaron:"Ď",dcaron:"ď",Dcy:"Д",dcy:"д",DD:"ⅅ",dd:"ⅆ",ddagger:"‡",ddarr:"⇊",DDotrahd:"⤑",ddotseq:"⩷",deg:"°",Del:"∇",Delta:"Δ",delta:"δ",demptyv:"⦱",dfisht:"⥿",Dfr:"𝔇",dfr:"𝔡",dHar:"⥥",dharl:"⇃",dharr:"⇂",DiacriticalAcute:"´",DiacriticalDot:"˙",DiacriticalDoubleAcute:"˝",DiacriticalGrave:"`",DiacriticalTilde:"˜",diam:"⋄",Diamond:"⋄",diamond:"⋄",diamondsuit:"♦",diams:"♦",die:"¨",DifferentialD:"ⅆ",digamma:"ϝ",disin:"⋲",div:"÷",divide:"÷",divideontimes:"⋇",divonx:"⋇",DJcy:"Ђ",djcy:"ђ",dlcorn:"⌞",dlcrop:"⌍",dollar:"$",Dopf:"𝔻",dopf:"𝕕",Dot:"¨",dot:"˙",DotDot:"⃜",doteq:"≐",doteqdot:"≑",DotEqual:"≐",dotminus:"∸",dotplus:"∔",dotsquare:"⊡",doublebarwedge:"⌆",DoubleContourIntegral:"∯",DoubleDot:"¨",DoubleDownArrow:"⇓",DoubleLeftArrow:"⇐",DoubleLeftRightArrow:"⇔",DoubleLeftTee:"⫤",DoubleLongLeftArrow:"⟸",DoubleLongLeftRightArrow:"⟺",DoubleLongRightArrow:"⟹",DoubleRightArrow:"⇒",DoubleRightTee:"⊨",DoubleUpArrow:"⇑",DoubleUpDownArrow:"⇕",DoubleVerticalBar:"∥",DownArrow:"↓",Downarrow:"⇓",downarrow:"↓",DownArrowBar:"⤓",DownArrowUpArrow:"⇵",DownBreve:"̑",downdownarrows:"⇊",downharpoonleft:"⇃",downharpoonright:"⇂",DownLeftRightVector:"⥐",DownLeftTeeVector:"⥞",DownLeftVector:"↽",DownLeftVectorBar:"⥖",DownRightTeeVector:"⥟",DownRightVector:"⇁",DownRightVectorBar:"⥗",DownTee:"⊤",DownTeeArrow:"↧",drbkarow:"⤐",drcorn:"⌟",drcrop:"⌌",Dscr:"𝒟",dscr:"𝒹",DScy:"Ѕ",dscy:"ѕ",dsol:"⧶",Dstrok:"Đ",dstrok:"đ",dtdot:"⋱",dtri:"▿",dtrif:"▾",duarr:"⇵",duhar:"⥯",dwangle:"⦦",DZcy:"Џ",dzcy:"џ",dzigrarr:"⟿",Eacute:"É",eacute:"é",easter:"⩮",Ecaron:"Ě",ecaron:"ě",ecir:"≖",Ecirc:"Ê",ecirc:"ê",ecolon:"≕",Ecy:"Э",ecy:"э",eDDot:"⩷",Edot:"Ė",eDot:"≑",edot:"ė",ee:"ⅇ",efDot:"≒",Efr:"𝔈",efr:"𝔢",eg:"⪚",Egrave:"È",egrave:"è",egs:"⪖",egsdot:"⪘",el:"⪙",Element:"∈",elinters:"⏧",ell:"ℓ",els:"⪕",elsdot:"⪗",Emacr:"Ē",emacr:"ē",empty:"∅",emptyset:"∅",EmptySmallSquare:"◻",emptyv:"∅",EmptyVerySmallSquare:"▫",emsp:" ",emsp13:" ",emsp14:" ",ENG:"Ŋ",eng:"ŋ",ensp:" ",Eogon:"Ę",eogon:"ę",Eopf:"𝔼",eopf:"𝕖",epar:"⋕",eparsl:"⧣",eplus:"⩱",epsi:"ε",Epsilon:"Ε",epsilon:"ε",epsiv:"ϵ",eqcirc:"≖",eqcolon:"≕",eqsim:"≂",eqslantgtr:"⪖",eqslantless:"⪕",Equal:"⩵",equals:"=",EqualTilde:"≂",equest:"≟",Equilibrium:"⇌",equiv:"≡",equivDD:"⩸",eqvparsl:"⧥",erarr:"⥱",erDot:"≓",Escr:"ℰ",escr:"ℯ",esdot:"≐",Esim:"⩳",esim:"≂",Eta:"Η",eta:"η",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",excl:"!",exist:"∃",Exists:"∃",expectation:"ℰ",ExponentialE:"ⅇ",exponentiale:"ⅇ",fallingdotseq:"≒",Fcy:"Ф",fcy:"ф",female:"♀",ffilig:"ffi",fflig:"ff",ffllig:"ffl",Ffr:"𝔉",ffr:"𝔣",filig:"fi",FilledSmallSquare:"◼",FilledVerySmallSquare:"▪",fjlig:"fj",flat:"♭",fllig:"fl",fltns:"▱",fnof:"ƒ",Fopf:"𝔽",fopf:"𝕗",ForAll:"∀",forall:"∀",fork:"⋔",forkv:"⫙",Fouriertrf:"ℱ",fpartint:"⨍",frac12:"½",frac13:"⅓",frac14:"¼",frac15:"⅕",frac16:"⅙",frac18:"⅛",frac23:"⅔",frac25:"⅖",frac34:"¾",frac35:"⅗",frac38:"⅜",frac45:"⅘",frac56:"⅚",frac58:"⅝",frac78:"⅞",frasl:"⁄",frown:"⌢",Fscr:"ℱ",fscr:"𝒻",gacute:"ǵ",Gamma:"Γ",gamma:"γ",Gammad:"Ϝ",gammad:"ϝ",gap:"⪆",Gbreve:"Ğ",gbreve:"ğ",Gcedil:"Ģ",Gcirc:"Ĝ",gcirc:"ĝ",Gcy:"Г",gcy:"г",Gdot:"Ġ",gdot:"ġ",gE:"≧",ge:"≥",gEl:"⪌",gel:"⋛",geq:"≥",geqq:"≧",geqslant:"⩾",ges:"⩾",gescc:"⪩",gesdot:"⪀",gesdoto:"⪂",gesdotol:"⪄",gesl:"⋛︀",gesles:"⪔",Gfr:"𝔊",gfr:"𝔤",Gg:"⋙",gg:"≫",ggg:"⋙",gimel:"ℷ",GJcy:"Ѓ",gjcy:"ѓ",gl:"≷",gla:"⪥",glE:"⪒",glj:"⪤",gnap:"⪊",gnapprox:"⪊",gnE:"≩",gne:"⪈",gneq:"⪈",gneqq:"≩",gnsim:"⋧",Gopf:"𝔾",gopf:"𝕘",grave:"`",GreaterEqual:"≥",GreaterEqualLess:"⋛",GreaterFullEqual:"≧",GreaterGreater:"⪢",GreaterLess:"≷",GreaterSlantEqual:"⩾",GreaterTilde:"≳",Gscr:"𝒢",gscr:"ℊ",gsim:"≳",gsime:"⪎",gsiml:"⪐",GT:">",Gt:"≫",gt:">",gtcc:"⪧",gtcir:"⩺",gtdot:"⋗",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"⋗",gtreqless:"⋛",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"ℋ",HARDcy:"Ъ",hardcy:"ъ",hArr:"⇔",harr:"↔",harrcir:"⥈",harrw:"↭",Hat:"^",hbar:"ℏ",Hcirc:"Ĥ",hcirc:"ĥ",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",Hfr:"ℌ",hfr:"𝔥",HilbertSpace:"ℋ",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",Hopf:"ℍ",hopf:"𝕙",horbar:"―",HorizontalLine:"─",Hscr:"ℋ",hscr:"𝒽",hslash:"ℏ",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"≏",hybull:"⁃",hyphen:"‐",Iacute:"Í",iacute:"í",ic:"⁣",Icirc:"Î",icirc:"î",Icy:"И",icy:"и",Idot:"İ",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",Ifr:"ℑ",ifr:"𝔦",Igrave:"Ì",igrave:"ì",ii:"ⅈ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"℩",IJlig:"IJ",ijlig:"ij",Im:"ℑ",Imacr:"Ī",imacr:"ī",image:"ℑ",ImaginaryI:"ⅈ",imagline:"ℐ",imagpart:"ℑ",imath:"ı",imof:"⊷",imped:"Ƶ",Implies:"⇒",in:"∈",incare:"℅",infin:"∞",infintie:"⧝",inodot:"ı",Int:"∬",int:"∫",intcal:"⊺",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"⋂",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"⁣",InvisibleTimes:"⁢",IOcy:"Ё",iocy:"ё",Iogon:"Į",iogon:"į",Iopf:"𝕀",iopf:"𝕚",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",Iscr:"ℐ",iscr:"𝒾",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"⋴",isinsv:"⋳",isinv:"∈",it:"⁢",Itilde:"Ĩ",itilde:"ĩ",Iukcy:"І",iukcy:"і",Iuml:"Ï",iuml:"ï",Jcirc:"Ĵ",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"𝔍",jfr:"𝔧",jmath:"ȷ",Jopf:"𝕁",jopf:"𝕛",Jscr:"𝒥",jscr:"𝒿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"є",Kappa:"Κ",kappa:"κ",kappav:"ϰ",Kcedil:"Ķ",kcedil:"ķ",Kcy:"К",kcy:"к",Kfr:"𝔎",kfr:"𝔨",kgreen:"ĸ",KHcy:"Х",khcy:"х",KJcy:"Ќ",kjcy:"ќ",Kopf:"𝕂",kopf:"𝕜",Kscr:"𝒦",kscr:"𝓀",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"ℒ",Lambda:"Λ",lambda:"λ",Lang:"⟪",lang:"⟨",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"ℒ",laquo:"«",Larr:"↞",lArr:"⇐",larr:"←",larrb:"⇤",larrbfs:"⤟",larrfs:"⤝",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",lat:"⪫",lAtail:"⤛",latail:"⤙",late:"⪭",lates:"⪭︀",lBarr:"⤎",lbarr:"⤌",lbbrk:"❲",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"⦏",lbrkslu:"⦍",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ļ",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",lE:"≦",le:"≤",LeftAngleBracket:"⟨",LeftArrow:"←",Leftarrow:"⇐",leftarrow:"←",LeftArrowBar:"⇤",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVector:"⇃",LeftDownVectorBar:"⥙",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrow:"↔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTee:"⊣",LeftTeeArrow:"↤",LeftTeeVector:"⥚",leftthreetimes:"⋋",LeftTriangle:"⊲",LeftTriangleBar:"⧏",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVector:"↿",LeftUpVectorBar:"⥘",LeftVector:"↼",LeftVectorBar:"⥒",lEg:"⪋",leg:"⋚",leq:"≤",leqq:"≦",leqslant:"⩽",les:"⩽",lescc:"⪨",lesdot:"⩿",lesdoto:"⪁",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"⋖",lesseqgtr:"⋚",lesseqqgtr:"⪋",LessEqualGreater:"⋚",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"𝔏",lfr:"𝔩",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"▄",LJcy:"Љ",ljcy:"љ",Ll:"⋘",ll:"≪",llarr:"⇇",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"◺",Lmidot:"Ŀ",lmidot:"ŀ",lmoust:"⎰",lmoustache:"⎰",lnap:"⪉",lnapprox:"⪉",lnE:"≨",lne:"⪇",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftarrow:"⟵",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longleftrightarrow:"⟷",longmapsto:"⟼",LongRightArrow:"⟶",Longrightarrow:"⟹",longrightarrow:"⟶",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"𝕃",lopf:"𝕝",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"◊",lozenge:"◊",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"‎",lrtri:"⊿",lsaquo:"‹",Lscr:"ℒ",lscr:"𝓁",Lsh:"↰",lsh:"↰",lsim:"≲",lsime:"⪍",lsimg:"⪏",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Ł",lstrok:"ł",LT:"<",Lt:"≪",lt:"<",ltcc:"⪦",ltcir:"⩹",ltdot:"⋖",lthree:"⋋",ltimes:"⋉",ltlarr:"⥶",ltquest:"⩻",ltri:"◃",ltrie:"⊴",ltrif:"◂",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"▮",mcomma:"⨩",Mcy:"М",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:" ",Mellintrf:"ℳ",Mfr:"𝔐",mfr:"𝔪",mho:"℧",micro:"µ",mid:"∣",midast:"*",midcir:"⫰",middot:"·",minus:"−",minusb:"⊟",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"⫛",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"𝕄",mopf:"𝕞",mp:"∓",Mscr:"ℳ",mscr:"𝓂",mstpos:"∾",Mu:"Μ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"ń",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natur:"♮",natural:"♮",naturals:"ℕ",nbsp:" ",nbump:"≎̸",nbumpe:"≏̸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Ņ",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"⩂",Ncy:"Н",ncy:"н",ndash:"–",ne:"≠",nearhk:"⤤",neArr:"⇗",nearr:"↗",nearrow:"↗",nedot:"≐̸",NegativeMediumSpace:"​",NegativeThickSpace:"​",NegativeThinSpace:"​",NegativeVeryThinSpace:"​",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"𝔑",nfr:"𝔫",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nhArr:"⇎",nharr:"↮",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"њ",nlArr:"⇍",nlarr:"↚",nldr:"‥",nlE:"≦̸",nle:"≰",nLeftarrow:"⇍",nleftarrow:"↚",nLeftrightarrow:"⇎",nleftrightarrow:"↮",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"⁠",NonBreakingSpace:" ",Nopf:"ℕ",nopf:"𝕟",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"≏̸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"⋷",notinvc:"⋶",NotLeftTriangle:"⋪",NotLeftTriangleBar:"⧏̸",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"⋠",NotReverseElement:"∌",NotRightTriangle:"⋫",NotRightTriangleBar:"⧐̸",NotRightTriangleEqual:"⋭",NotSquareSubset:"⊏̸",NotSquareSubsetEqual:"⋢",NotSquareSuperset:"⊐̸",NotSquareSupersetEqual:"⋣",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"⊁",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"⋡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"≁",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",npar:"∦",nparallel:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"⋠",npre:"⪯̸",nprec:"⊀",npreceq:"⪯̸",nrArr:"⇏",nrarr:"↛",nrarrc:"⤳̸",nrarrw:"↝̸",nRightarrow:"⇏",nrightarrow:"↛",nrtri:"⋫",nrtrie:"⋭",nsc:"⊁",nsccue:"⋡",nsce:"⪰̸",Nscr:"𝒩",nscr:"𝓃",nshortmid:"∤",nshortparallel:"∦",nsim:"≁",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"⋢",nsqsupe:"⋣",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"⊁",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"⋫",ntrianglerighteq:"⋭",Nu:"Ν",nu:"ν",num:"#",numero:"№",numsp:" ",nvap:"≍⃒",nVDash:"⊯",nVdash:"⊮",nvDash:"⊭",nvdash:"⊬",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwArr:"⇖",nwarr:"↖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",ocir:"⊚",Ocirc:"Ô",ocirc:"ô",Ocy:"О",ocy:"о",odash:"⊝",Odblac:"Ő",odblac:"ő",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Œ",oelig:"œ",ofcir:"⦿",Ofr:"𝔒",ofr:"𝔬",ogon:"˛",Ograve:"Ò",ograve:"ò",ogt:"⧁",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"Ō",omacr:"ō",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"𝕆",oopf:"𝕠",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",Or:"⩔",or:"∨",orarr:"↻",ord:"⩝",order:"ℴ",orderof:"ℴ",ordf:"ª",ordm:"º",origof:"⊶",oror:"⩖",orslope:"⩗",orv:"⩛",oS:"Ⓢ",Oscr:"𝒪",oscr:"ℴ",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",Otimes:"⨷",otimes:"⊗",otimesas:"⨶",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"⏞",OverBracket:"⎴",OverParenthesis:"⏜",par:"∥",para:"¶",parallel:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"𝔓",pfr:"𝔭",Phi:"Φ",phi:"φ",phiv:"ϕ",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"π",pitchfork:"⋔",piv:"ϖ",planck:"ℏ",planckh:"ℎ",plankv:"ℏ",plus:"+",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"ℌ",pointint:"⨕",Popf:"ℙ",popf:"𝕡",pound:"£",Pr:"⪻",pr:"≺",prap:"⪷",prcue:"≼",prE:"⪳",pre:"⪯",prec:"≺",precapprox:"⪷",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",precsim:"≾",Prime:"″",prime:"′",primes:"ℙ",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"∏",Product:"∏",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"∝",Proportion:"∷",Proportional:"∝",propto:"∝",prsim:"≾",prurel:"⊰",Pscr:"𝒫",pscr:"𝓅",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"𝔔",qfr:"𝔮",qint:"⨌",Qopf:"ℚ",qopf:"𝕢",qprime:"⁗",Qscr:"𝒬",qscr:"𝓆",quaternions:"ℍ",quatint:"⨖",quest:"?",questeq:"≟",QUOT:'"',quot:'"',rAarr:"⇛",race:"∽̱",Racute:"Ŕ",racute:"ŕ",radic:"√",raemptyv:"⦳",Rang:"⟫",rang:"⟩",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",Rarr:"↠",rArr:"⇒",rarr:"→",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"↝",rAtail:"⤜",ratail:"⤚",ratio:"∶",rationals:"ℚ",RBarr:"⤐",rBarr:"⤏",rbarr:"⤍",rbbrk:"❳",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"⦐",Rcaron:"Ř",rcaron:"ř",Rcedil:"Ŗ",rcedil:"ŗ",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"р",rdca:"⤷",rdldhar:"⥩",rdquo:"”",rdquor:"”",rdsh:"↳",Re:"ℜ",real:"ℜ",realine:"ℛ",realpart:"ℜ",reals:"ℝ",rect:"▭",REG:"®",reg:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",Rfr:"ℜ",rfr:"𝔯",rHar:"⥤",rhard:"⇁",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"ρ",rhov:"ϱ",RightAngleBracket:"⟩",RightArrow:"→",Rightarrow:"⇒",rightarrow:"→",RightArrowBar:"⇥",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"⥝",RightDownVector:"⇂",RightDownVectorBar:"⥕",RightFloor:"⌋",rightharpoondown:"⇁",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"↝",RightTee:"⊢",RightTeeArrow:"↦",RightTeeVector:"⥛",rightthreetimes:"⋌",RightTriangle:"⊳",RightTriangleBar:"⧐",RightTriangleEqual:"⊵",RightUpDownVector:"⥏",RightUpTeeVector:"⥜",RightUpVector:"↾",RightUpVectorBar:"⥔",RightVector:"⇀",RightVectorBar:"⥓",ring:"˚",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"‏",rmoust:"⎱",rmoustache:"⎱",rnmid:"⫮",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",Ropf:"ℝ",ropf:"𝕣",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",Rscr:"ℛ",rscr:"𝓇",Rsh:"↱",rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"⋌",rtimes:"⋊",rtri:"▹",rtrie:"⊵",rtrif:"▸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"℞",Sacute:"Ś",sacute:"ś",sbquo:"‚",Sc:"⪼",sc:"≻",scap:"⪸",Scaron:"Š",scaron:"š",sccue:"≽",scE:"⪴",sce:"⪰",Scedil:"Ş",scedil:"ş",Scirc:"Ŝ",scirc:"ŝ",scnap:"⪺",scnE:"⪶",scnsim:"⋩",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"с",sdot:"⋅",sdotb:"⊡",sdote:"⩦",searhk:"⤥",seArr:"⇘",searr:"↘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"𝔖",sfr:"𝔰",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"←",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"­",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sigmav:"ς",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"⪝",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"←",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ь",sol:"/",solb:"⧄",solbar:"⌿",Sopf:"𝕊",sopf:"𝕤",spades:"♠",spadesuit:"♠",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"⊏",sqsube:"⊑",sqsubset:"⊏",sqsubseteq:"⊑",sqsup:"⊐",sqsupe:"⊒",sqsupset:"⊐",sqsupseteq:"⊒",squ:"□",Square:"□",square:"□",SquareIntersection:"⊓",SquareSubset:"⊏",SquareSubsetEqual:"⊑",SquareSuperset:"⊐",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"▪",squf:"▪",srarr:"→",Sscr:"𝒮",sscr:"𝓈",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"ϕ",strns:"¯",Sub:"⋐",sub:"⊂",subdot:"⪽",subE:"⫅",sube:"⊆",subedot:"⫃",submult:"⫁",subnE:"⫋",subne:"⊊",subplus:"⪿",subrarr:"⥹",Subset:"⋐",subset:"⊂",subseteq:"⊆",subseteqq:"⫅",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"⫋",subsim:"⫇",subsub:"⫕",subsup:"⫓",succ:"≻",succapprox:"⪸",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"⋩",succsim:"≿",SuchThat:"∋",Sum:"∑",sum:"∑",sung:"♪",Sup:"⋑",sup:"⊃",sup1:"¹",sup2:"²",sup3:"³",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"⫄",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"⫗",suplarr:"⥻",supmult:"⫂",supnE:"⫌",supne:"⊋",supplus:"⫀",Supset:"⋑",supset:"⊃",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"⫌",supsim:"⫈",supsub:"⫔",supsup:"⫖",swarhk:"⤦",swArr:"⇙",swarr:"↙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:"\t",target:"⌖",Tau:"Τ",tau:"τ",tbrk:"⎴",Tcaron:"Ť",tcaron:"ť",Tcedil:"Ţ",tcedil:"ţ",Tcy:"Т",tcy:"т",tdot:"⃛",telrec:"⌕",Tfr:"𝔗",tfr:"𝔱",there4:"∴",Therefore:"∴",therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thetav:"ϑ",thickapprox:"≈",thicksim:"∼",ThickSpace:"  ",thinsp:" ",ThinSpace:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",Tilde:"∼",tilde:"˜",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",times:"×",timesb:"⊠",timesbar:"⨱",timesd:"⨰",tint:"∭",toea:"⤨",top:"⊤",topbot:"⌶",topcir:"⫱",Topf:"𝕋",topf:"𝕥",topfork:"⫚",tosa:"⤩",tprime:"‴",TRADE:"™",trade:"™",triangle:"▵",triangledown:"▿",triangleleft:"◃",trianglelefteq:"⊴",triangleq:"≜",triangleright:"▹",trianglerighteq:"⊵",tridot:"◬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"⧍",tritime:"⨻",trpezium:"⏢",Tscr:"𝒯",tscr:"𝓉",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"ћ",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",Uarr:"↟",uArr:"⇑",uarr:"↑",Uarrocir:"⥉",Ubrcy:"Ў",ubrcy:"ў",Ubreve:"Ŭ",ubreve:"ŭ",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Ű",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"𝔘",ufr:"𝔲",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"▀",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"⌏",ultri:"◸",Umacr:"Ū",umacr:"ū",uml:"¨",UnderBar:"_",UnderBrace:"⏟",UnderBracket:"⎵",UnderParenthesis:"⏝",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"𝕌",uopf:"𝕦",UpArrow:"↑",Uparrow:"⇑",uparrow:"↑",UpArrowBar:"⤒",UpArrowDownArrow:"⇅",UpDownArrow:"↕",Updownarrow:"⇕",updownarrow:"↕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",Upsi:"ϒ",upsi:"υ",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",UpTee:"⊥",UpTeeArrow:"↥",upuparrows:"⇈",urcorn:"⌝",urcorner:"⌝",urcrop:"⌎",Uring:"Ů",uring:"ů",urtri:"◹",Uscr:"𝒰",uscr:"𝓊",utdot:"⋰",Utilde:"Ũ",utilde:"ũ",utri:"▵",utrif:"▴",uuarr:"⇈",Uuml:"Ü",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"ϰ",varnothing:"∅",varphi:"ϕ",varpi:"ϖ",varpropto:"∝",vArr:"⇕",varr:"↕",varrho:"ϱ",varsigma:"ς",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"ϑ",vartriangleleft:"⊲",vartriangleright:"⊳",Vbar:"⫫",vBar:"⫨",vBarv:"⫩",Vcy:"В",vcy:"в",VDash:"⊫",Vdash:"⊩",vDash:"⊨",vdash:"⊢",Vdashl:"⫦",Vee:"⋁",vee:"∨",veebar:"⊻",veeeq:"≚",vellip:"⋮",Verbar:"‖",verbar:"|",Vert:"‖",vert:"|",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"❘",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"𝔙",vfr:"𝔳",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"𝕍",vopf:"𝕧",vprop:"∝",vrtri:"⊳",Vscr:"𝒱",vscr:"𝓋",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Ŵ",wcirc:"ŵ",wedbar:"⩟",Wedge:"⋀",wedge:"∧",wedgeq:"≙",weierp:"℘",Wfr:"𝔚",wfr:"𝔴",Wopf:"𝕎",wopf:"𝕨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"𝒲",wscr:"𝓌",xcap:"⋂",xcirc:"◯",xcup:"⋃",xdtri:"▽",Xfr:"𝔛",xfr:"𝔵",xhArr:"⟺",xharr:"⟷",Xi:"Ξ",xi:"ξ",xlArr:"⟸",xlarr:"⟵",xmap:"⟼",xnis:"⋻",xodot:"⨀",Xopf:"𝕏",xopf:"𝕩",xoplus:"⨁",xotime:"⨂",xrArr:"⟹",xrarr:"⟶",Xscr:"𝒳",xscr:"𝓍",xsqcup:"⨆",xuplus:"⨄",xutri:"△",xvee:"⋁",xwedge:"⋀",Yacute:"Ý",yacute:"ý",YAcy:"Я",yacy:"я",Ycirc:"Ŷ",ycirc:"ŷ",Ycy:"Ы",ycy:"ы",yen:"¥",Yfr:"𝔜",yfr:"𝔶",YIcy:"Ї",yicy:"ї",Yopf:"𝕐",yopf:"𝕪",Yscr:"𝒴",yscr:"𝓎",YUcy:"Ю",yucy:"ю",Yuml:"Ÿ",yuml:"ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Ż",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"​",Zeta:"Ζ",zeta:"ζ",Zfr:"ℨ",zfr:"𝔷",ZHcy:"Ж",zhcy:"ж",zigrarr:"⇝",Zopf:"ℤ",zopf:"𝕫",Zscr:"𝒵",zscr:"𝓏",zwj:"‍",zwnj:"‌"}},function(e,t,n){"use strict";var r=n(459),o=n(37).unescapeMd;e.exports=function(e,t){var n,i,a,s=t,u=e.posMax;if(60===e.src.charCodeAt(t)){for(t++;t<u;){if(10===(n=e.src.charCodeAt(t)))return!1;if(62===n)return a=r(o(e.src.slice(s+1,t))),!!e.parser.validateLink(a)&&(e.pos=t+1,e.linkContent=a,!0);92===n&&t+1<u?t+=2:t++}return!1}for(i=0;t<u&&32!==(n=e.src.charCodeAt(t))&&!(n<32||127===n);)if(92===n&&t+1<u)t+=2;else{if(40===n&&++i>1)break;if(41===n&&--i<0)break;t++}return s!==t&&(a=o(e.src.slice(s,t)),!!e.parser.validateLink(a)&&(e.linkContent=a,e.pos=t,!0))}},function(e,t,n){"use strict";var r=n(37).replaceEntities;e.exports=function(e){var t=r(e);try{t=decodeURI(t)}catch(e){}return encodeURI(t)}},function(e,t,n){"use strict";var r=n(37).unescapeMd;e.exports=function(e,t){var n,o=t,i=e.posMax,a=e.src.charCodeAt(t);if(34!==a&&39!==a&&40!==a)return!1;for(t++,40===a&&(a=41);t<i;){if((n=e.src.charCodeAt(t))===a)return e.pos=t+1,e.linkContent=r(e.src.slice(o+1,t)),!0;92===n&&t+1<i?t+=2:t++}return!1}},function(e,t,n){"use strict";e.exports=function(e){return e.trim().replace(/\s+/g," ").toUpperCase()}},function(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.d(t,"a",function(){return r})},function(e,t,n){"use strict";(function(e){var n="object"==typeof e&&e&&e.Object===Object&&e;t.a=n}).call(this,n(41))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.combineReducers=void 0;var r,o=n(582),i=(r=o)&&r.__esModule?r:{default:r};t.combineReducers=i.default},function(e,t,n){"use strict";var r=/^(%20|\s)*(javascript|data)/im,o=/[^\x20-\x7E]/gim,i=/^([^:]+):/gm,a=[".","/"];e.exports={sanitizeUrl:function(e){var t,n,s=e.replace(o,"");return function(e){return a.indexOf(e[0])>-1}(s)?s:(n=s.match(i))?(t=n[0],r.test(t)?"about:blank":s):"about:blank"}}},function(e,t,n){var r=n(591),o=n(599)(function(e,t,n){return t=t.toLowerCase(),e+(n?r(t):t)});e.exports=o},function(e,t,n){var r=n(370),o=n(168),i=n(668),a=n(35),s=n(384);e.exports=function(e,t,n){var u=a(e)?r:i;return n&&s(e,t,n)&&(t=void 0),u(e,o(t,3))}},function(e,t,n){(function(t){var r=n(673),o=n(674).Stream,i=" ";function a(e,t,n){n=n||0;var o,i,s=(o=t,new Array(n||0).join(o||"")),u=e;if("object"==typeof e&&((u=e[i=Object.keys(e)[0]])&&u._elem))return u._elem.name=i,u._elem.icount=n,u._elem.indent=t,u._elem.indents=s,u._elem.interrupt=u,u._elem;var c,l=[],p=[];function f(e){Object.keys(e).forEach(function(t){l.push(function(e,t){return e+'="'+r(t)+'"'}(t,e[t]))})}switch(typeof u){case"object":if(null===u)break;u._attr&&f(u._attr),u._cdata&&p.push(("<![CDATA["+u._cdata).replace(/\]\]>/g,"]]]]><![CDATA[>")+"]]>"),u.forEach&&(c=!1,p.push(""),u.forEach(function(e){"object"==typeof e?"_attr"==Object.keys(e)[0]?f(e._attr):p.push(a(e,t,n+1)):(p.pop(),c=!0,p.push(r(e)))}),c||p.push(""));break;default:p.push(r(u))}return{name:i,interrupt:!1,attributes:l,content:p,icount:n,indents:s,indent:t}}function s(e,t,n){if("object"!=typeof t)return e(!1,t);var r=t.interrupt?1:t.content.length;function o(){for(;t.content.length;){var o=t.content.shift();if(void 0!==o){if(i(o))return;s(e,o)}}e(!1,(r>1?t.indents:"")+(t.name?"</"+t.name+">":"")+(t.indent&&!n?"\n":"")),n&&n()}function i(t){return!!t.interrupt&&(t.interrupt.append=e,t.interrupt.end=o,t.interrupt=!1,e(!0),!0)}if(e(!1,t.indents+(t.name?"<"+t.name:"")+(t.attributes.length?" "+t.attributes.join(" "):"")+(r?t.name?">":"":t.name?"/>":"")+(t.indent&&r>1?"\n":"")),!r)return e(!1,t.indent?"\n":"");i(t)||o()}e.exports=function(e,n){"object"!=typeof n&&(n={indent:n});var r,u,c=n.stream?new o:null,l="",p=!1,f=n.indent?!0===n.indent?i:n.indent:"",h=!0;function d(e){h?t.nextTick(e):e()}function m(e,t){if(void 0!==t&&(l+=t),e&&!p&&(c=c||new o,p=!0),e&&p){var n=l;d(function(){c.emit("data",n)}),l=""}}function v(e,t){s(m,a(e,f,f?1:0),t)}function g(){if(c){var e=l;d(function(){c.emit("data",e),c.emit("end"),c.readable=!1,c.emit("close")})}}return d(function(){h=!1}),n.declaration&&(r=n.declaration,u={version:"1.0",encoding:r.encoding||"UTF-8"},r.standalone&&(u.standalone=r.standalone),v({"?xml":{_attr:u}}),l=l.replace("/>","?>")),e&&e.forEach?e.forEach(function(t,n){var r;n+1===e.length&&(r=g),v(t,r)}):v(e,g),c?(c.readable=!0,c):l},e.exports.element=e.exports.Element=function(){var e={_elem:a(Array.prototype.slice.call(arguments)),push:function(e){if(!this.append)throw new Error("not assigned to a parent!");var t=this,n=this._elem.indent;s(this.append,a(e,n,this._elem.icount+(n?1:0)),function(){t.append(!0)})},close:function(e){void 0!==e&&this.push(e),this.end&&this.end()}};return e}}).call(this,n(72))},function(e,t,n){(function(t){var n;n=void 0!==t?t:this,e.exports=function(e){if(e.CSS&&e.CSS.escape)return e.CSS.escape;var t=function(e){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var t,n=String(e),r=n.length,o=-1,i="",a=n.charCodeAt(0);++o<r;)0!=(t=n.charCodeAt(o))?i+=t>=1&&t<=31||127==t||0==o&&t>=48&&t<=57||1==o&&t>=48&&t<=57&&45==a?"\\"+t.toString(16)+" ":0==o&&1==r&&45==t||!(t>=128||45==t||95==t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122)?"\\"+n.charAt(o):n.charAt(o):i+="�";return i};return e.CSS||(e.CSS={}),e.CSS.escape=t,t}(n)}).call(this,n(41))},function(e,t,n){var r=n(365),o=n(383),i=n(168),a=n(738),s=n(35);e.exports=function(e,t,n){var u=s(e)?r:a,c=arguments.length<3;return u(e,i(t,4),n,c,o)}},function(e,t,n){var r=n(49),o=n(790),i=n(382),a="Expected a function",s=Math.max,u=Math.min;e.exports=function(e,t,n){var c,l,p,f,h,d,m=0,v=!1,g=!1,y=!0;if("function"!=typeof e)throw new TypeError(a);function b(t){var n=c,r=l;return c=l=void 0,m=t,f=e.apply(r,n)}function _(e){var n=e-d;return void 0===d||n>=t||n<0||g&&e-m>=p}function w(){var e=o();if(_(e))return x(e);h=setTimeout(w,function(e){var n=t-(e-d);return g?u(n,p-(e-m)):n}(e))}function x(e){return h=void 0,y&&c?b(e):(c=l=void 0,f)}function E(){var e=o(),n=_(e);if(c=arguments,l=this,d=e,n){if(void 0===h)return function(e){return m=e,h=setTimeout(w,t),v?b(e):f}(d);if(g)return clearTimeout(h),h=setTimeout(w,t),b(d)}return void 0===h&&(h=setTimeout(w,t)),f}return t=i(t)||0,r(n)&&(v=!!n.leading,p=(g="maxWait"in n)?s(i(n.maxWait)||0,t):p,y="trailing"in n?!!n.trailing:y),E.cancel=function(){void 0!==h&&clearTimeout(h),m=0,c=d=l=h=void 0},E.flush=function(){return void 0===h?f:x(o())},E}},function(e,t,n){"use strict";e.exports=n(800)},function(e,t,n){var r=n(362),o=n(443),i=n(905),a=n(104),s=n(114),u=n(908),c=n(447),l=n(446),p=c(function(e,t){var n={};if(null==e)return n;var c=!1;t=r(t,function(t){return t=a(t,e),c||(c=t.length>1),t}),s(e,l(e),n),c&&(n=o(n,7,u));for(var p=t.length;p--;)i(n,t[p]);return n});e.exports=p},function(e,t,n){var r,o,i;o=[],r=function(){"use strict";var e=function(e){return e&&"getComputedStyle"in window&&"smooth"===window.getComputedStyle(e)["scroll-behavior"]};if("undefined"==typeof window||!("document"in window))return{};var t=function(t,n,r){var o;n=n||999,r||0===r||(r=9);var i=function(e){o=e},a=function(){clearTimeout(o),i(0)},s=function(e){return Math.max(0,t.getTopOf(e)-r)},u=function(r,o,s){if(a(),0===o||o&&o<0||e(t.body))t.toY(r),s&&s();else{var u=t.getY(),c=Math.max(0,r)-u,l=(new Date).getTime();o=o||Math.min(Math.abs(c),n),function e(){i(setTimeout(function(){var n=Math.min(1,((new Date).getTime()-l)/o),r=Math.max(0,Math.floor(u+c*(n<.5?2*n*n:n*(4-2*n)-1)));t.toY(r),n<1&&t.getHeight()+r<t.body.scrollHeight?e():(setTimeout(a,99),s&&s())},9))}()}},c=function(e,t,n){u(s(e),t,n)};return{setup:function(e,t){return(0===e||e)&&(n=e),(0===t||t)&&(r=t),{defaultDuration:n,edgeOffset:r}},to:c,toY:u,intoView:function(e,n,o){var i=e.getBoundingClientRect().height,a=t.getTopOf(e)+i,l=t.getHeight(),p=t.getY(),f=p+l;s(e)<p||i+r>l?c(e,n,o):a+r>f?u(a-l+r,n,o):o&&o()},center:function(e,n,r,o){u(Math.max(0,t.getTopOf(e)-t.getHeight()/2+(r||e.getBoundingClientRect().height/2)),n,o)},stop:a,moving:function(){return!!o},getY:t.getY,getTopOf:t.getTopOf}},n=document.documentElement,r=function(){return window.scrollY||n.scrollTop},o=t({body:document.scrollingElement||document.body,toY:function(e){window.scrollTo(0,e)},getY:r,getHeight:function(){return window.innerHeight||n.clientHeight},getTopOf:function(e){return e.getBoundingClientRect().top+r()-n.offsetTop}});if(o.createScroller=function(e,r,o){return t({body:e,toY:function(t){e.scrollTop=t},getY:function(){return e.scrollTop},getHeight:function(){return Math.min(e.clientHeight,window.innerHeight||n.clientHeight)},getTopOf:function(e){return e.offsetTop}},r,o)},"addEventListener"in window&&!window.noZensmooth&&!e(document.body)){var i="history"in window&&"pushState"in history,a=i&&"scrollRestoration"in history;a&&(history.scrollRestoration="auto"),window.addEventListener("load",function(){a&&(setTimeout(function(){history.scrollRestoration="manual"},9),window.addEventListener("popstate",function(e){e.state&&"zenscrollY"in e.state&&o.toY(e.state.zenscrollY)},!1)),window.location.hash&&setTimeout(function(){var e=o.setup().edgeOffset;if(e){var t=document.getElementById(window.location.href.split("#")[1]);if(t){var n=Math.max(0,o.getTopOf(t)-e),r=o.getY()-n;0<=r&&r<9&&window.scrollTo(0,n)}}},9)},!1);var s=new RegExp("(^|\\s)noZensmooth(\\s|$)");window.addEventListener("click",function(e){for(var t=e.target;t&&"A"!==t.tagName;)t=t.parentNode;if(!(!t||1!==e.which||e.shiftKey||e.metaKey||e.ctrlKey||e.altKey)){if(a){var n=history.state&&"object"==typeof history.state?history.state:{};n.zenscrollY=o.getY();try{history.replaceState(n,"")}catch(e){}}var r=t.getAttribute("href")||"";if(0===r.indexOf("#")&&!s.test(t.className)){var u=0,c=document.getElementById(r.substring(1));if("#"!==r){if(!c)return;u=o.getTopOf(c)}e.preventDefault();var l=function(){window.location=r},p=o.setup().edgeOffset;p&&(u=Math.max(0,u-p),i&&(l=function(){history.pushState({},"",r)})),o.toY(u,null,l)}}},!1)}return o}(),void 0===(i="function"==typeof r?r.apply(t,o):r)||(e.exports=i)},function(e,t,n){e.exports=n(958)},function(e,t){e.exports=function(e,t,n){var r=new Blob([e],{type:n||"application/octet-stream"});if(void 0!==window.navigator.msSaveBlob)window.navigator.msSaveBlob(r,t);else{var o=window.URL.createObjectURL(r),i=document.createElement("a");i.style.display="none",i.href=o,i.setAttribute("download",t),void 0===i.download&&i.setAttribute("target","_blank"),document.body.appendChild(i),i.click(),document.body.removeChild(i),window.URL.revokeObjectURL(o)}}},function(e,t,n){"use strict";var r=n(966),o=function(e){return e.split(/(<\/?[^>]+>)/g).filter(function(e){return""!==e.trim()})},i=function(e){return/<\/+[^>]+>/.test(e)},a=function(e){return/<[^>]+\/>/.test(e)},s=function(e){return function(e){return/<[^>!]+>/.test(e)}(e)&&!i(e)&&!a(e)};function u(e){return o(e).map(function(e){return{value:e,type:c(e)}})}function c(e){return i(e)?"ClosingTag":s(e)?"OpeningTag":a(e)?"SelfClosingTag":"Text"}e.exports=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.indentor,o=t.textNodesOnSameLine,i=0,a=[];n=n||" ";var s=u(e).map(function(e,t,s){var u=e.value,c=e.type;"ClosingTag"===c&&i--;var l=r(n,i),p=l+u;if("OpeningTag"===c&&i++,o){var f=s[t-1],h=s[t-2];"ClosingTag"===c&&"Text"===f.type&&"OpeningTag"===h.type&&(p=""+l+h.value+f.value+u,a.push(t-2,t-1))}return p});return a.forEach(function(e){return s[e]=null}),s.filter(function(e){return!!e}).join("\n")}},function(e,t,n){var r=n(65);e.exports=function(e){return r(e).toLowerCase()}},function(e,t,n){!function(e,t,n){"use strict";t=t&&"default"in t?t.default:t;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),o(t,[{key:"shouldComponentUpdate",value:function(e){var t=this,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=this.state||{};return!(this.updateOnProps||Object.keys(r({},e,this.props))).every(function(r){return n.is(e[r],t.props[r])})||!(this.updateOnStates||Object.keys(r({},o,i))).every(function(e){return n.is(o[e],i[e])})}}]),t}(t.Component);e.ImmutablePureComponent=i,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}(t,n(0),n(1))},function(e,t,n){"use strict";var r=n(1018).DebounceInput;r.DebounceInput=r,e.exports=r},function(e,t,n){n(482),e.exports=n(1021)},function(e,t,n){"use strict";n.r(t);var r=n(18);void 0===n.n(r).a.Promise&&n(483),String.prototype.startsWith||n(512)},function(e,t,n){n(484),n(330),n(495),n(499),n(510),n(511),e.exports=n(78).Promise},function(e,t,n){"use strict";var r=n(194),o={};o[n(33)("toStringTag")]="z",o+""!="[object z]"&&n(95)(Object.prototype,"toString",function(){return"[object "+r(this)+"]"},!0)},function(e,t,n){e.exports=!n(122)&&!n(123)(function(){return 7!=Object.defineProperty(n(196)("div"),"a",{get:function(){return 7}}).a})},function(e,t,n){var r=n(96);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){"use strict";var r=n(488),o=n(329),i=n(198),a={};n(76)(a,n(33)("iterator"),function(){return this}),e.exports=function(e,t,n){e.prototype=r(a,{next:o(1,n)}),i(e,t+" Iterator")}},function(e,t,n){var r=n(77),o=n(489),i=n(336),a=n(197)("IE_PROTO"),s=function(){},u=function(){var e,t=n(196)("iframe"),r=i.length;for(t.style.display="none",n(337).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),u=e.F;r--;)delete u.prototype[i[r]];return u()};e.exports=Object.create||function(e,t){var n;return null!==e?(s.prototype=r(e),n=new s,s.prototype=null,n[a]=e):n=u(),void 0===t?n:o(n,t)}},function(e,t,n){var r=n(147),o=n(77),i=n(334);e.exports=n(122)?Object.defineProperties:function(e,t){o(e);for(var n,a=i(t),s=a.length,u=0;s>u;)r.f(e,n=a[u++],t[n]);return e}},function(e,t,n){var r=n(148),o=n(152),i=n(492)(!1),a=n(197)("IE_PROTO");e.exports=function(e,t){var n,s=o(e),u=0,c=[];for(n in s)n!=a&&r(s,n)&&c.push(n);for(;t.length>u;)r(s,n=t[u++])&&(~i(c,n)||c.push(n));return c}},function(e,t,n){var r=n(121);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==r(e)?e.split(""):Object(e)}},function(e,t,n){var r=n(152),o=n(125),i=n(335);e.exports=function(e){return function(t,n,a){var s,u=r(t),c=o(u.length),l=i(a,c);if(e&&n!=n){for(;c>l;)if((s=u[l++])!=s)return!0}else for(;c>l;l++)if((e||l in u)&&u[l]===n)return e||l||0;return!e&&-1}}},function(e,t,n){var r=n(148),o=n(494),i=n(197)("IE_PROTO"),a=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=o(e),r(e,i)?e[i]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?a:null}},function(e,t,n){var r=n(68);e.exports=function(e){return Object(r(e))}},function(e,t,n){for(var r=n(496),o=n(334),i=n(95),a=n(43),s=n(76),u=n(124),c=n(33),l=c("iterator"),p=c("toStringTag"),f=u.Array,h={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},d=o(h),m=0;m<d.length;m++){var v,g=d[m],y=h[g],b=a[g],_=b&&b.prototype;if(_&&(_[l]||s(_,l,f),_[p]||s(_,p,g),u[g]=f,y))for(v in r)_[v]||i(_,v,r[v],!0)}},function(e,t,n){"use strict";var r=n(497),o=n(498),i=n(124),a=n(152);e.exports=n(332)(Array,"Array",function(e,t){this._t=a(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(e,t,n){var r=n(33)("unscopables"),o=Array.prototype;null==o[r]&&n(76)(o,r,{}),e.exports=function(e){o[r][e]=!0}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){"use strict";var r,o,i,a,s=n(333),u=n(43),c=n(150),l=n(194),p=n(38),f=n(96),h=n(151),d=n(500),m=n(501),v=n(338),g=n(339).set,y=n(506)(),b=n(199),_=n(340),w=n(341),x=u.TypeError,E=u.process,S=u.Promise,C="process"==l(E),k=function(){},O=o=b.f,A=!!function(){try{var e=S.resolve(1),t=(e.constructor={})[n(33)("species")]=function(e){e(k,k)};return(C||"function"==typeof PromiseRejectionEvent)&&e.then(k)instanceof t}catch(e){}}(),T=function(e){var t;return!(!f(e)||"function"!=typeof(t=e.then))&&t},j=function(e,t){if(!e._n){e._n=!0;var n=e._c;y(function(){for(var r=e._v,o=1==e._s,i=0,a=function(t){var n,i,a,s=o?t.ok:t.fail,u=t.resolve,c=t.reject,l=t.domain;try{s?(o||(2==e._h&&M(e),e._h=1),!0===s?n=r:(l&&l.enter(),n=s(r),l&&(l.exit(),a=!0)),n===t.promise?c(x("Promise-chain cycle")):(i=T(n))?i.call(n,u,c):u(n)):c(r)}catch(e){l&&!a&&l.exit(),c(e)}};n.length>i;)a(n[i++]);e._c=[],e._n=!1,t&&!e._h&&P(e)})}},P=function(e){g.call(u,function(){var t,n,r,o=e._v,i=I(e);if(i&&(t=_(function(){C?E.emit("unhandledRejection",o,e):(n=u.onunhandledrejection)?n({promise:e,reason:o}):(r=u.console)&&r.error&&r.error("Unhandled promise rejection",o)}),e._h=C||I(e)?2:1),e._a=void 0,i&&t.e)throw t.v})},I=function(e){return 1!==e._h&&0===(e._a||e._c).length},M=function(e){g.call(u,function(){var t;C?E.emit("rejectionHandled",e):(t=u.onrejectionhandled)&&t({promise:e,reason:e._v})})},N=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),j(t,!0))},R=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw x("Promise can't be resolved itself");(t=T(e))?y(function(){var r={_w:n,_d:!1};try{t.call(e,c(R,r,1),c(N,r,1))}catch(e){N.call(r,e)}}):(n._v=e,n._s=1,j(n,!1))}catch(e){N.call({_w:n,_d:!1},e)}}};A||(S=function(e){d(this,S,"Promise","_h"),h(e),r.call(this);try{e(c(R,this,1),c(N,this,1))}catch(e){N.call(this,e)}},(r=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=n(507)(S.prototype,{then:function(e,t){var n=O(v(this,S));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=C?E.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&j(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),i=function(){var e=new r;this.promise=e,this.resolve=c(R,e,1),this.reject=c(N,e,1)},b.f=O=function(e){return e===S||e===a?new i(e):o(e)}),p(p.G+p.W+p.F*!A,{Promise:S}),n(198)(S,"Promise"),n(508)("Promise"),a=n(78).Promise,p(p.S+p.F*!A,"Promise",{reject:function(e){var t=O(this);return(0,t.reject)(e),t.promise}}),p(p.S+p.F*(s||!A),"Promise",{resolve:function(e){return w(s&&this===a?S:this,e)}}),p(p.S+p.F*!(A&&n(509)(function(e){S.all(e).catch(k)})),"Promise",{all:function(e){var t=this,n=O(t),r=n.resolve,o=n.reject,i=_(function(){var n=[],i=0,a=1;m(e,!1,function(e){var s=i++,u=!1;n.push(void 0),a++,t.resolve(e).then(function(e){u||(u=!0,n[s]=e,--a||r(n))},o)}),--a||r(n)});return i.e&&o(i.v),n.promise},race:function(e){var t=this,n=O(t),r=n.reject,o=_(function(){m(e,!1,function(e){t.resolve(e).then(n.resolve,r)})});return o.e&&r(o.v),n.promise}})},function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},function(e,t,n){var r=n(150),o=n(502),i=n(503),a=n(77),s=n(125),u=n(504),c={},l={};(t=e.exports=function(e,t,n,p,f){var h,d,m,v,g=f?function(){return e}:u(e),y=r(n,p,t?2:1),b=0;if("function"!=typeof g)throw TypeError(e+" is not iterable!");if(i(g)){for(h=s(e.length);h>b;b++)if((v=t?y(a(d=e[b])[0],d[1]):y(e[b]))===c||v===l)return v}else for(m=g.call(e);!(d=m.next()).done;)if((v=o(m,y,d.value,t))===c||v===l)return v}).BREAK=c,t.RETURN=l},function(e,t,n){var r=n(77);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){var i=e.return;throw void 0!==i&&r(i.call(e)),t}}},function(e,t,n){var r=n(124),o=n(33)("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(r.Array===e||i[o]===e)}},function(e,t,n){var r=n(194),o=n(33)("iterator"),i=n(124);e.exports=n(78).getIteratorMethod=function(e){if(null!=e)return e[o]||e["@@iterator"]||i[r(e)]}},function(e,t){e.exports=function(e,t,n){var r=void 0===n;switch(t.length){case 0:return r?e():e.call(n);case 1:return r?e(t[0]):e.call(n,t[0]);case 2:return r?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return r?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return r?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}return e.apply(n,t)}},function(e,t,n){var r=n(43),o=n(339).set,i=r.MutationObserver||r.WebKitMutationObserver,a=r.process,s=r.Promise,u="process"==n(121)(a);e.exports=function(){var e,t,n,c=function(){var r,o;for(u&&(r=a.domain)&&r.exit();e;){o=e.fn,e=e.next;try{o()}catch(r){throw e?n():t=void 0,r}}t=void 0,r&&r.enter()};if(u)n=function(){a.nextTick(c)};else if(!i||r.navigator&&r.navigator.standalone)if(s&&s.resolve){var l=s.resolve();n=function(){l.then(c)}}else n=function(){o.call(r,c)};else{var p=!0,f=document.createTextNode("");new i(c).observe(f,{characterData:!0}),n=function(){f.data=p=!p}}return function(r){var o={fn:r,next:void 0};t&&(t.next=o),e||(e=o,n()),t=o}}},function(e,t,n){var r=n(95);e.exports=function(e,t,n){for(var o in t)r(e,o,t[o],n);return e}},function(e,t,n){"use strict";var r=n(43),o=n(147),i=n(122),a=n(33)("species");e.exports=function(e){var t=r[e];i&&t&&!t[a]&&o.f(t,a,{configurable:!0,get:function(){return this}})}},function(e,t,n){var r=n(33)("iterator"),o=!1;try{var i=[7][r]();i.return=function(){o=!0},Array.from(i,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var i=[7],a=i[r]();a.next=function(){return{done:n=!0}},i[r]=function(){return a},e(i)}catch(e){}return n}},function(e,t,n){"use strict";var r=n(38),o=n(78),i=n(43),a=n(338),s=n(341);r(r.P+r.R,"Promise",{finally:function(e){var t=a(this,o.Promise||i.Promise),n="function"==typeof e;return this.then(n?function(n){return s(t,e()).then(function(){return n})}:e,n?function(n){return s(t,e()).then(function(){throw n})}:e)}})},function(e,t,n){"use strict";var r=n(38),o=n(199),i=n(340);r(r.S,"Promise",{try:function(e){var t=o.f(this),n=i(e);return(n.e?t.reject:t.resolve)(n.v),t.promise}})},function(e,t,n){n(513),n(514),n(515),n(330),n(518),n(519),n(520),n(521),n(523),n(524),n(525),n(526),n(527),n(528),n(529),n(530),n(531),n(532),n(533),n(534),n(535),n(536),n(537),n(538),n(539),n(540),e.exports=n(78).String},function(e,t,n){var r=n(38),o=n(335),i=String.fromCharCode,a=String.fromCodePoint;r(r.S+r.F*(!!a&&1!=a.length),"String",{fromCodePoint:function(e){for(var t,n=[],r=arguments.length,a=0;r>a;){if(t=+arguments[a++],o(t,1114111)!==t)throw RangeError(t+" is not a valid code point");n.push(t<65536?i(t):i(55296+((t-=65536)>>10),t%1024+56320))}return n.join("")}})},function(e,t,n){var r=n(38),o=n(152),i=n(125);r(r.S,"String",{raw:function(e){for(var t=o(e.raw),n=i(t.length),r=arguments.length,a=[],s=0;n>s;)a.push(String(t[s++])),s<r&&a.push(String(arguments[s]));return a.join("")}})},function(e,t,n){"use strict";n(516)("trim",function(e){return function(){return e(this,3)}})},function(e,t,n){var r=n(38),o=n(68),i=n(123),a=n(517),s="["+a+"]",u=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(e,t,n){var o={},s=i(function(){return!!a[e]()||"​…"!="​…"[e]()}),u=o[e]=s?t(p):a[e];n&&(o[n]=u),r(r.P+r.F*s,"String",o)},p=l.trim=function(e,t){return e=String(o(e)),1&t&&(e=e.replace(u,"")),2&t&&(e=e.replace(c,"")),e};e.exports=l},function(e,t){e.exports="\t\n\v\f\r   ᠎              \u2028\u2029\ufeff"},function(e,t,n){"use strict";var r=n(38),o=n(331)(!1);r(r.P,"String",{codePointAt:function(e){return o(this,e)}})},function(e,t,n){"use strict";var r=n(38),o=n(125),i=n(200),a="".endsWith;r(r.P+r.F*n(201)("endsWith"),"String",{endsWith:function(e){var t=i(this,e,"endsWith"),n=arguments.length>1?arguments[1]:void 0,r=o(t.length),s=void 0===n?r:Math.min(o(n),r),u=String(e);return a?a.call(t,u,s):t.slice(s-u.length,s)===u}})},function(e,t,n){"use strict";var r=n(38),o=n(200);r(r.P+r.F*n(201)("includes"),"String",{includes:function(e){return!!~o(this,e,"includes").indexOf(e,arguments.length>1?arguments[1]:void 0)}})},function(e,t,n){var r=n(38);r(r.P,"String",{repeat:n(522)})},function(e,t,n){"use strict";var r=n(149),o=n(68);e.exports=function(e){var t=String(o(this)),n="",i=r(e);if(i<0||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(t+=t))1&i&&(n+=t);return n}},function(e,t,n){"use strict";var r=n(38),o=n(125),i=n(200),a="".startsWith;r(r.P+r.F*n(201)("startsWith"),"String",{startsWith:function(e){var t=i(this,e,"startsWith"),n=o(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),r=String(e);return a?a.call(t,r,n):t.slice(n,n+r.length)===r}})},function(e,t,n){"use strict";n(39)("anchor",function(e){return function(t){return e(this,"a","name",t)}})},function(e,t,n){"use strict";n(39)("big",function(e){return function(){return e(this,"big","","")}})},function(e,t,n){"use strict";n(39)("blink",function(e){return function(){return e(this,"blink","","")}})},function(e,t,n){"use strict";n(39)("bold",function(e){return function(){return e(this,"b","","")}})},function(e,t,n){"use strict";n(39)("fixed",function(e){return function(){return e(this,"tt","","")}})},function(e,t,n){"use strict";n(39)("fontcolor",function(e){return function(t){return e(this,"font","color",t)}})},function(e,t,n){"use strict";n(39)("fontsize",function(e){return function(t){return e(this,"font","size",t)}})},function(e,t,n){"use strict";n(39)("italics",function(e){return function(){return e(this,"i","","")}})},function(e,t,n){"use strict";n(39)("link",function(e){return function(t){return e(this,"a","href",t)}})},function(e,t,n){"use strict";n(39)("small",function(e){return function(){return e(this,"small","","")}})},function(e,t,n){"use strict";n(39)("strike",function(e){return function(){return e(this,"strike","","")}})},function(e,t,n){"use strict";n(39)("sub",function(e){return function(){return e(this,"sub","","")}})},function(e,t,n){"use strict";n(39)("sup",function(e){return function(){return e(this,"sup","","")}})},function(e,t,n){n(153)("match",1,function(e,t,n){return[function(n){"use strict";var r=e(this),o=null==n?void 0:n[t];return void 0!==o?o.call(n,r):new RegExp(n)[t](String(r))},n]})},function(e,t,n){n(153)("replace",2,function(e,t,n){return[function(r,o){"use strict";var i=e(this),a=null==r?void 0:r[t];return void 0!==a?a.call(r,i,o):n.call(String(i),r,o)},n]})},function(e,t,n){n(153)("search",1,function(e,t,n){return[function(n){"use strict";var r=e(this),o=null==n?void 0:n[t];return void 0!==o?o.call(n,r):new RegExp(n)[t](String(r))},n]})},function(e,t,n){n(153)("split",2,function(e,t,r){"use strict";var o=n(342),i=r,a=[].push;if("c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length){var s=void 0===/()??/.exec("")[1];r=function(e,t){var n=String(this);if(void 0===e&&0===t)return[];if(!o(e))return i.call(n,e,t);var r,u,c,l,p,f=[],h=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),d=0,m=void 0===t?4294967295:t>>>0,v=new RegExp(e.source,h+"g");for(s||(r=new RegExp("^"+v.source+"$(?!\\s)",h));(u=v.exec(n))&&!((c=u.index+u[0].length)>d&&(f.push(n.slice(d,u.index)),!s&&u.length>1&&u[0].replace(r,function(){for(p=1;p<arguments.length-2;p++)void 0===arguments[p]&&(u[p]=void 0)}),u.length>1&&u.index<n.length&&a.apply(f,u.slice(1)),l=u[0].length,d=c,f.length>=m));)v.lastIndex===u.index&&v.lastIndex++;return d===n.length?!l&&v.test("")||f.push(""):f.push(n.slice(d)),f.length>m?f.slice(0,m):f}}else"0".split(void 0,0).length&&(r=function(e,t){return void 0===e&&0===t?[]:i.call(this,e,t)});return[function(n,o){var i=e(this),a=null==n?void 0:n[t];return void 0!==a?a.call(n,i,o):r.call(String(i),n,o)},r]})},function(e,t,n){var r=n(22),o=r.JSON||(r.JSON={stringify:JSON.stringify});e.exports=function(e){return o.stringify.apply(o,arguments)}},function(e,t,n){n(543),e.exports=n(22).Object.keys},function(e,t,n){var r=n(79),o=n(126);n(208)("keys",function(){return function(e){return o(r(e))}})},function(e,t,n){var r=n(70),o=n(154),i=n(545);e.exports=function(e){return function(t,n,a){var s,u=r(t),c=o(u.length),l=i(a,c);if(e&&n!=n){for(;c>l;)if((s=u[l++])!=s)return!0}else for(;c>l;l++)if((e||l in u)&&u[l]===n)return e||l||0;return!e&&-1}}},function(e,t,n){var r=n(204),o=Math.max,i=Math.min;e.exports=function(e,t){return(e=r(e))<0?o(e+t,0):i(e,t)}},function(e,t,n){e.exports=n(547)},function(e,t,n){n(97),n(99),e.exports=n(213).f("iterator")},function(e,t,n){var r=n(204),o=n(202);e.exports=function(e){return function(t,n){var i,a,s=String(o(t)),u=r(n),c=s.length;return u<0||u>=c?e?"":void 0:(i=s.charCodeAt(u))<55296||i>56319||u+1===c||(a=s.charCodeAt(u+1))<56320||a>57343?e?s.charAt(u):i:e?s.slice(u,u+2):a-56320+(i-55296<<10)+65536}}},function(e,t,n){"use strict";var r=n(156),o=n(130),i=n(131),a={};n(71)(a,n(34)("iterator"),function(){return this}),e.exports=function(e,t,n){e.prototype=r(a,{next:o(1,n)}),i(e,t+" Iterator")}},function(e,t,n){"use strict";var r=n(551),o=n(348),i=n(98),a=n(70);e.exports=n(211)(Array,"Array",function(e,t){this._t=a(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,n=this._i++;return!e||n>=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(e,t){e.exports=function(){}},function(e,t,n){e.exports=n(553)},function(e,t,n){n(349),n(160),n(556),n(557),e.exports=n(22).Symbol},function(e,t,n){var r=n(126),o=n(157),i=n(158);e.exports=function(e){var t=r(e),n=o.f;if(n)for(var a,s=n(e),u=i.f,c=0;s.length>c;)u.call(e,a=s[c++])&&t.push(a);return t}},function(e,t,n){var r=n(70),o=n(216).f,i={}.toString,a="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){return a&&"[object Window]"==i.call(e)?function(e){try{return o(e)}catch(e){return a.slice()}}(e):o(r(e))}},function(e,t,n){n(214)("asyncIterator")},function(e,t,n){n(214)("observable")},function(e,t,n){"use strict";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){for(var t,n=c(e),r=n[0],a=n[1],s=new i(function(e,t,n){return 3*(t+n)/4-n}(0,r,a)),u=0,l=a>0?r-4:r,p=0;p<l;p+=4)t=o[e.charCodeAt(p)]<<18|o[e.charCodeAt(p+1)]<<12|o[e.charCodeAt(p+2)]<<6|o[e.charCodeAt(p+3)],s[u++]=t>>16&255,s[u++]=t>>8&255,s[u++]=255&t;2===a&&(t=o[e.charCodeAt(p)]<<2|o[e.charCodeAt(p+1)]>>4,s[u++]=255&t);1===a&&(t=o[e.charCodeAt(p)]<<10|o[e.charCodeAt(p+1)]<<4|o[e.charCodeAt(p+2)]>>2,s[u++]=t>>8&255,s[u++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;a<s;a+=16383)i.push(l(e,a,a+16383>s?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,u=a.length;s<u;++s)r[s]=a[s],o[a.charCodeAt(s)]=s;function c(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s<n;s+=3)o=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(255&e[s+2]),a.push(r[(i=o)>>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,u=(1<<s)-1,c=u>>1,l=-7,p=n?o-1:0,f=n?-1:1,h=e[t+p];for(p+=f,i=h&(1<<-l)-1,h>>=-l,l+=s;l>0;i=256*i+e[t+p],p+=f,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+p],p+=f,l-=8);if(0===i)i=1-c;else{if(i===u)return a?NaN:1/0*(h?-1:1);a+=Math.pow(2,r),i-=c}return(h?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,u,c=8*i-o-1,l=(1<<c)-1,p=l>>1,f=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:i-1,d=r?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-a))<1&&(a--,u*=2),(t+=a+p>=1?f/u:f*Math.pow(2,1-p))*u>=2&&(a++,u/=2),a+p>=l?(s=0,a=l):a+p>=1?(s=(t*u-1)*Math.pow(2,o),a+=p):(s=t*Math.pow(2,p-1)*Math.pow(2,o),a=0));o>=8;e[n+h]=255&s,h+=d,s/=256,o-=8);for(a=a<<o|s,c+=o;c>0;e[n+h]=255&a,h+=d,a/=256,c-=8);e[n+h-d]|=128*m}},function(e,t,n){n(561),e.exports=n(22).Array.isArray},function(e,t,n){var r=n(30);r(r.S,"Array",{isArray:n(215)})},function(e,t,n){n(563);var r=n(22).Object;e.exports=function(e,t,n){return r.defineProperty(e,t,n)}},function(e,t,n){var r=n(30);r(r.S+r.F*!n(45),"Object",{defineProperty:n(47).f})},function(e,t,n){n(565),e.exports=n(22).Object.assign},function(e,t,n){var r=n(30);r(r.S+r.F,"Object",{assign:n(351)})},function(e,t,n){"use strict";e.exports=function(){}},function(e,t,n){"use strict";var r=n(568),o=n(101),i=n(54),a=n(569),s=r.twoArgumentPooler,u=r.fourArgumentPooler,c=/\/+/g;function l(e){return(""+e).replace(c,"$&/")}function p(e,t){this.func=e,this.context=t,this.count=0}function f(e,t,n){var r=e.func,o=e.context;r.call(o,t,e.count++)}function h(e,t,n,r){this.result=e,this.keyPrefix=t,this.func=n,this.context=r,this.count=0}function d(e,t,n){var r=e.result,a=e.keyPrefix,s=e.func,u=e.context,c=s.call(u,t,e.count++);Array.isArray(c)?m(c,r,n,i.thatReturnsArgument):null!=c&&(o.isValidElement(c)&&(c=o.cloneAndReplaceKey(c,a+(!c.key||t&&t.key===c.key?"":l(c.key)+"/")+n)),r.push(c))}function m(e,t,n,r,o){var i="";null!=n&&(i=l(n)+"/");var s=h.getPooled(t,i,r,o);a(e,d,s),h.release(s)}function v(e,t,n){return null}p.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},r.addPoolingTo(p,s),h.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},r.addPoolingTo(h,u);var g={forEach:function(e,t,n){if(null==e)return e;var r=p.getPooled(t,n);a(e,f,r),p.release(r)},map:function(e,t,n){if(null==e)return e;var r=[];return m(e,r,null,t,n),r},mapIntoWithKeyPrefixInternal:m,count:function(e,t){return a(e,v,null)},toArray:function(e){var t=[];return m(e,t,null,i.thatReturnsArgument),t}};e.exports=g},function(e,t,n){"use strict";var r=n(133),o=(n(15),function(e){if(this.instancePool.length){var t=this.instancePool.pop();return this.call(t,e),t}return new this(e)}),i=function(e){e instanceof this||r("25"),e.destructor(),this.instancePool.length<this.poolSize&&this.instancePool.push(e)},a=o,s={addPoolingTo:function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||a,n.poolSize||(n.poolSize=10),n.release=i,n},oneArgumentPooler:o,twoArgumentPooler:function(e,t){if(this.instancePool.length){var n=this.instancePool.pop();return this.call(n,e,t),n}return new this(e,t)},threeArgumentPooler:function(e,t,n){if(this.instancePool.length){var r=this.instancePool.pop();return this.call(r,e,t,n),r}return new this(e,t,n)},fourArgumentPooler:function(e,t,n,r){if(this.instancePool.length){var o=this.instancePool.pop();return this.call(o,e,t,n,r),o}return new this(e,t,n,r)}};e.exports=s},function(e,t,n){"use strict";var r=n(133),o=(n(62),n(355)),i=n(570),a=(n(15),n(571)),s=(n(23),"."),u=":";function c(e,t){return e&&"object"==typeof e&&null!=e.key?a.escape(e.key):t.toString(36)}e.exports=function(e,t,n){return null==e?0:function e(t,n,l,p){var f,h=typeof t;if("undefined"!==h&&"boolean"!==h||(t=null),null===t||"string"===h||"number"===h||"object"===h&&t.$$typeof===o)return l(p,t,""===n?s+c(t,0):n),1;var d=0,m=""===n?s:n+u;if(Array.isArray(t))for(var v=0;v<t.length;v++)d+=e(f=t[v],m+c(f,v),l,p);else{var g=i(t);if(g){var y,b=g.call(t);if(g!==t.entries)for(var _=0;!(y=b.next()).done;)d+=e(f=y.value,m+c(f,_++),l,p);else for(;!(y=b.next()).done;){var w=y.value;w&&(d+=e(f=w[1],m+a.escape(w[0])+u+c(f,0),l,p))}}else if("object"===h){var x=String(t);r("31","[object Object]"===x?"object with keys {"+Object.keys(t).join(", ")+"}":x,"")}}return d}(e,"",t,n)}},function(e,t,n){"use strict";var r="function"==typeof Symbol&&Symbol.iterator,o="@@iterator";e.exports=function(e){var t=e&&(r&&e[r]||e[o]);if("function"==typeof t)return t}},function(e,t,n){"use strict";var r={escape:function(e){var t={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,function(e){return t[e]})},unescape:function(e){var t={"=0":"=","=2":":"};return(""+("."===e[0]&&"$"===e[1]?e.substring(2):e.substring(1))).replace(/(=0|=2)/g,function(e){return t[e]})}};e.exports=r},function(e,t,n){"use strict";var r=n(101).createFactory,o={a:r("a"),abbr:r("abbr"),address:r("address"),area:r("area"),article:r("article"),aside:r("aside"),audio:r("audio"),b:r("b"),base:r("base"),bdi:r("bdi"),bdo:r("bdo"),big:r("big"),blockquote:r("blockquote"),body:r("body"),br:r("br"),button:r("button"),canvas:r("canvas"),caption:r("caption"),cite:r("cite"),code:r("code"),col:r("col"),colgroup:r("colgroup"),data:r("data"),datalist:r("datalist"),dd:r("dd"),del:r("del"),details:r("details"),dfn:r("dfn"),dialog:r("dialog"),div:r("div"),dl:r("dl"),dt:r("dt"),em:r("em"),embed:r("embed"),fieldset:r("fieldset"),figcaption:r("figcaption"),figure:r("figure"),footer:r("footer"),form:r("form"),h1:r("h1"),h2:r("h2"),h3:r("h3"),h4:r("h4"),h5:r("h5"),h6:r("h6"),head:r("head"),header:r("header"),hgroup:r("hgroup"),hr:r("hr"),html:r("html"),i:r("i"),iframe:r("iframe"),img:r("img"),input:r("input"),ins:r("ins"),kbd:r("kbd"),keygen:r("keygen"),label:r("label"),legend:r("legend"),li:r("li"),link:r("link"),main:r("main"),map:r("map"),mark:r("mark"),menu:r("menu"),menuitem:r("menuitem"),meta:r("meta"),meter:r("meter"),nav:r("nav"),noscript:r("noscript"),object:r("object"),ol:r("ol"),optgroup:r("optgroup"),option:r("option"),output:r("output"),p:r("p"),param:r("param"),picture:r("picture"),pre:r("pre"),progress:r("progress"),q:r("q"),rp:r("rp"),rt:r("rt"),ruby:r("ruby"),s:r("s"),samp:r("samp"),script:r("script"),section:r("section"),select:r("select"),small:r("small"),source:r("source"),span:r("span"),strong:r("strong"),style:r("style"),sub:r("sub"),summary:r("summary"),sup:r("sup"),table:r("table"),tbody:r("tbody"),td:r("td"),textarea:r("textarea"),tfoot:r("tfoot"),th:r("th"),thead:r("thead"),time:r("time"),title:r("title"),tr:r("tr"),track:r("track"),u:r("u"),ul:r("ul"),var:r("var"),video:r("video"),wbr:r("wbr"),circle:r("circle"),clipPath:r("clipPath"),defs:r("defs"),ellipse:r("ellipse"),g:r("g"),image:r("image"),line:r("line"),linearGradient:r("linearGradient"),mask:r("mask"),path:r("path"),pattern:r("pattern"),polygon:r("polygon"),polyline:r("polyline"),radialGradient:r("radialGradient"),rect:r("rect"),stop:r("stop"),svg:r("svg"),text:r("text"),tspan:r("tspan")};e.exports=o},function(e,t,n){"use strict";var r=n(101).isValidElement,o=n(356);e.exports=o(r)},function(e,t,n){"use strict";var r=n(357),o=n(25),i=n(358),a=n(576),s=Function.call.bind(Object.prototype.hasOwnProperty),u=function(){};function c(){return null}e.exports=function(e,t){var n="function"==typeof Symbol&&Symbol.iterator,l="@@iterator";var p="<<anonymous>>",f={array:v("array"),bool:v("boolean"),func:v("function"),number:v("number"),object:v("object"),string:v("string"),symbol:v("symbol"),any:m(c),arrayOf:function(e){return m(function(t,n,r,o,a){if("function"!=typeof e)return new d("Property `"+a+"` of component `"+r+"` has invalid PropType notation inside arrayOf.");var s=t[n];if(!Array.isArray(s)){var u=y(s);return new d("Invalid "+o+" `"+a+"` of type `"+u+"` supplied to `"+r+"`, expected an array.")}for(var c=0;c<s.length;c++){var l=e(s,c,r,o,a+"["+c+"]",i);if(l instanceof Error)return l}return null})},element:m(function(t,n,r,o,i){var a=t[n];if(!e(a)){var s=y(a);return new d("Invalid "+o+" `"+i+"` of type `"+s+"` supplied to `"+r+"`, expected a single ReactElement.")}return null}),elementType:m(function(e,t,n,o,i){var a=e[t];if(!r.isValidElementType(a)){var s=y(a);return new d("Invalid "+o+" `"+i+"` of type `"+s+"` supplied to `"+n+"`, expected a single ReactElement type.")}return null}),instanceOf:function(e){return m(function(t,n,r,o,i){if(!(t[n]instanceof e)){var a=e.name||p,s=function(e){if(!e.constructor||!e.constructor.name)return p;return e.constructor.name}(t[n]);return new d("Invalid "+o+" `"+i+"` of type `"+s+"` supplied to `"+r+"`, expected instance of `"+a+"`.")}return null})},node:m(function(e,t,n,r,o){return g(e[t])?null:new d("Invalid "+r+" `"+o+"` supplied to `"+n+"`, expected a ReactNode.")}),objectOf:function(e){return m(function(t,n,r,o,a){if("function"!=typeof e)return new d("Property `"+a+"` of component `"+r+"` has invalid PropType notation inside objectOf.");var u=t[n],c=y(u);if("object"!==c)return new d("Invalid "+o+" `"+a+"` of type `"+c+"` supplied to `"+r+"`, expected an object.");for(var l in u)if(s(u,l)){var p=e(u,l,r,o,a+"."+l,i);if(p instanceof Error)return p}return null})},oneOf:function(e){if(!Array.isArray(e))return c;return m(function(t,n,r,o,i){for(var a=t[n],s=0;s<e.length;s++)if(h(a,e[s]))return null;var u=JSON.stringify(e,function(e,t){var n=b(t);return"symbol"===n?String(t):t});return new d("Invalid "+o+" `"+i+"` of value `"+String(a)+"` supplied to `"+r+"`, expected one of "+u+".")})},oneOfType:function(e){if(!Array.isArray(e))return c;for(var t=0;t<e.length;t++){var n=e[t];if("function"!=typeof n)return u("Invalid argument supplied to oneOfType. Expected an array of check functions, but received "+_(n)+" at index "+t+"."),c}return m(function(t,n,r,o,a){for(var s=0;s<e.length;s++){var u=e[s];if(null==u(t,n,r,o,a,i))return null}return new d("Invalid "+o+" `"+a+"` supplied to `"+r+"`.")})},shape:function(e){return m(function(t,n,r,o,a){var s=t[n],u=y(s);if("object"!==u)return new d("Invalid "+o+" `"+a+"` of type `"+u+"` supplied to `"+r+"`, expected `object`.");for(var c in e){var l=e[c];if(l){var p=l(s,c,r,o,a+"."+c,i);if(p)return p}}return null})},exact:function(e){return m(function(t,n,r,a,s){var u=t[n],c=y(u);if("object"!==c)return new d("Invalid "+a+" `"+s+"` of type `"+c+"` supplied to `"+r+"`, expected `object`.");var l=o({},t[n],e);for(var p in l){var f=e[p];if(!f)return new d("Invalid "+a+" `"+s+"` key `"+p+"` supplied to `"+r+"`.\nBad object: "+JSON.stringify(t[n],null," ")+"\nValid keys: "+JSON.stringify(Object.keys(e),null," "));var h=f(u,p,r,a,s+"."+p,i);if(h)return h}return null})}};function h(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}function d(e){this.message=e,this.stack=""}function m(e){function n(n,r,o,a,s,u,c){if((a=a||p,u=u||o,c!==i)&&t){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}return null==r[o]?n?null===r[o]?new d("The "+s+" `"+u+"` is marked as required in `"+a+"`, but its value is `null`."):new d("The "+s+" `"+u+"` is marked as required in `"+a+"`, but its value is `undefined`."):null:e(r,o,a,s,u)}var r=n.bind(null,!1);return r.isRequired=n.bind(null,!0),r}function v(e){return m(function(t,n,r,o,i,a){var s=t[n];return y(s)!==e?new d("Invalid "+o+" `"+i+"` of type `"+b(s)+"` supplied to `"+r+"`, expected `"+e+"`."):null})}function g(t){switch(typeof t){case"number":case"string":case"undefined":return!0;case"boolean":return!t;case"object":if(Array.isArray(t))return t.every(g);if(null===t||e(t))return!0;var r=function(e){var t=e&&(n&&e[n]||e[l]);if("function"==typeof t)return t}(t);if(!r)return!1;var o,i=r.call(t);if(r!==t.entries){for(;!(o=i.next()).done;)if(!g(o.value))return!1}else for(;!(o=i.next()).done;){var a=o.value;if(a&&!g(a[1]))return!1}return!0;default:return!1}}function y(e){var t=typeof e;return Array.isArray(e)?"array":e instanceof RegExp?"object":function(e,t){return"symbol"===e||!!t&&("Symbol"===t["@@toStringTag"]||"function"==typeof Symbol&&t instanceof Symbol)}(t,e)?"symbol":t}function b(e){if(null==e)return""+e;var t=y(e);if("object"===t){if(e instanceof Date)return"date";if(e instanceof RegExp)return"regexp"}return t}function _(e){var t=b(e);switch(t){case"array":case"object":return"an "+t;case"boolean":case"date":case"regexp":return"a "+t;default:return t}}return d.prototype=Error.prototype,f.checkPropTypes=a,f.resetWarningCache=a.resetWarningCache,f.PropTypes=f,f}},function(e,t,n){"use strict";
+/** @license React v16.8.6
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */Object.defineProperty(t,"__esModule",{value:!0});var r="function"==typeof Symbol&&Symbol.for,o=r?Symbol.for("react.element"):60103,i=r?Symbol.for("react.portal"):60106,a=r?Symbol.for("react.fragment"):60107,s=r?Symbol.for("react.strict_mode"):60108,u=r?Symbol.for("react.profiler"):60114,c=r?Symbol.for("react.provider"):60109,l=r?Symbol.for("react.context"):60110,p=r?Symbol.for("react.async_mode"):60111,f=r?Symbol.for("react.concurrent_mode"):60111,h=r?Symbol.for("react.forward_ref"):60112,d=r?Symbol.for("react.suspense"):60113,m=r?Symbol.for("react.memo"):60115,v=r?Symbol.for("react.lazy"):60116;function g(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case o:switch(e=e.type){case p:case f:case a:case u:case s:case d:return e;default:switch(e=e&&e.$$typeof){case l:case h:case c:return e;default:return t}}case v:case m:case i:return t}}}function y(e){return g(e)===f}t.typeOf=g,t.AsyncMode=p,t.ConcurrentMode=f,t.ContextConsumer=l,t.ContextProvider=c,t.Element=o,t.ForwardRef=h,t.Fragment=a,t.Lazy=v,t.Memo=m,t.Portal=i,t.Profiler=u,t.StrictMode=s,t.Suspense=d,t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===f||e===u||e===s||e===d||"object"==typeof e&&null!==e&&(e.$$typeof===v||e.$$typeof===m||e.$$typeof===c||e.$$typeof===l||e.$$typeof===h)},t.isAsyncMode=function(e){return y(e)||g(e)===p},t.isConcurrentMode=y,t.isContextConsumer=function(e){return g(e)===l},t.isContextProvider=function(e){return g(e)===c},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===o},t.isForwardRef=function(e){return g(e)===h},t.isFragment=function(e){return g(e)===a},t.isLazy=function(e){return g(e)===v},t.isMemo=function(e){return g(e)===m},t.isPortal=function(e){return g(e)===i},t.isProfiler=function(e){return g(e)===u},t.isStrictMode=function(e){return g(e)===s},t.isSuspense=function(e){return g(e)===d}},function(e,t,n){"use strict";function r(e,t,n,r,o){}r.resetWarningCache=function(){0},e.exports=r},function(e,t,n){"use strict";e.exports="15.6.2"},function(e,t,n){"use strict";var r=n(352).Component,o=n(101).isValidElement,i=n(353),a=n(579);e.exports=a(r,o,i)},function(e,t,n){"use strict";var r=n(25),o=n(161),i=n(15),a="mixins";e.exports=function(e,t,n){var s=[],u={mixins:"DEFINE_MANY",statics:"DEFINE_MANY",propTypes:"DEFINE_MANY",contextTypes:"DEFINE_MANY",childContextTypes:"DEFINE_MANY",getDefaultProps:"DEFINE_MANY_MERGED",getInitialState:"DEFINE_MANY_MERGED",getChildContext:"DEFINE_MANY_MERGED",render:"DEFINE_ONCE",componentWillMount:"DEFINE_MANY",componentDidMount:"DEFINE_MANY",componentWillReceiveProps:"DEFINE_MANY",shouldComponentUpdate:"DEFINE_ONCE",componentWillUpdate:"DEFINE_MANY",componentDidUpdate:"DEFINE_MANY",componentWillUnmount:"DEFINE_MANY",UNSAFE_componentWillMount:"DEFINE_MANY",UNSAFE_componentWillReceiveProps:"DEFINE_MANY",UNSAFE_componentWillUpdate:"DEFINE_MANY",updateComponent:"OVERRIDE_BASE"},c={getDerivedStateFromProps:"DEFINE_MANY_MERGED"},l={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)f(e,t[n])},childContextTypes:function(e,t){e.childContextTypes=r({},e.childContextTypes,t)},contextTypes:function(e,t){e.contextTypes=r({},e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps?e.getDefaultProps=d(e.getDefaultProps,t):e.getDefaultProps=t},propTypes:function(e,t){e.propTypes=r({},e.propTypes,t)},statics:function(e,t){!function(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in l;i(!o,'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\'t be on the "statics" key. Define it as an instance property instead; it will still be accessible on the constructor.',n);var a=n in e;if(a){var s=c.hasOwnProperty(n)?c[n]:null;return i("DEFINE_MANY_MERGED"===s,"ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.",n),void(e[n]=d(e[n],r))}e[n]=r}}}(e,t)},autobind:function(){}};function p(e,t){var n=u.hasOwnProperty(t)?u[t]:null;b.hasOwnProperty(t)&&i("OVERRIDE_BASE"===n,"ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.",t),e&&i("DEFINE_MANY"===n||"DEFINE_MANY_MERGED"===n,"ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.",t)}function f(e,n){if(n){i("function"!=typeof n,"ReactClass: You're attempting to use a component class or function as a mixin. Instead, just use a regular object."),i(!t(n),"ReactClass: You're attempting to use a component as a mixin. Instead, just use a regular object.");var r=e.prototype,o=r.__reactAutoBindPairs;for(var s in n.hasOwnProperty(a)&&l.mixins(e,n.mixins),n)if(n.hasOwnProperty(s)&&s!==a){var c=n[s],f=r.hasOwnProperty(s);if(p(f,s),l.hasOwnProperty(s))l[s](e,c);else{var h=u.hasOwnProperty(s);if("function"!=typeof c||h||f||!1===n.autobind)if(f){var v=u[s];i(h&&("DEFINE_MANY_MERGED"===v||"DEFINE_MANY"===v),"ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.",v,s),"DEFINE_MANY_MERGED"===v?r[s]=d(r[s],c):"DEFINE_MANY"===v&&(r[s]=m(r[s],c))}else r[s]=c;else o.push(s,c),r[s]=c}}}}function h(e,t){for(var n in i(e&&t&&"object"==typeof e&&"object"==typeof t,"mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects."),t)t.hasOwnProperty(n)&&(i(void 0===e[n],"mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.",n),e[n]=t[n]);return e}function d(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);if(null==n)return r;if(null==r)return n;var o={};return h(o,n),h(o,r),o}}function m(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}function v(e,t){return t.bind(e)}var g={componentDidMount:function(){this.__isMounted=!0}},y={componentWillUnmount:function(){this.__isMounted=!1}},b={replaceState:function(e,t){this.updater.enqueueReplaceState(this,e,t)},isMounted:function(){return!!this.__isMounted}},_=function(){};return r(_.prototype,e.prototype,b),function(e){var t=function(e,r,a){this.__reactAutoBindPairs.length&&function(e){for(var t=e.__reactAutoBindPairs,n=0;n<t.length;n+=2){var r=t[n],o=t[n+1];e[r]=v(e,o)}}(this),this.props=e,this.context=r,this.refs=o,this.updater=a||n,this.state=null;var s=this.getInitialState?this.getInitialState():null;i("object"==typeof s&&!Array.isArray(s),"%s.getInitialState(): must return an object or null",t.displayName||"ReactCompositeComponent"),this.state=s};for(var r in t.prototype=new _,t.prototype.constructor=t,t.prototype.__reactAutoBindPairs=[],s.forEach(f.bind(null,t)),f(t,g),f(t,e),f(t,y),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),i(t.prototype.render,"createClass(...): Class specification must implement a `render` method."),u)t.prototype[r]||(t.prototype[r]=null);return t}}},function(e,t,n){"use strict";var r=n(133),o=n(101);n(15);e.exports=function(e){return o.isValidElement(e)||r("143"),e}},function(e,t){e.exports=function(e){if(!e.webpackPolyfill){var t=Object.create(e);t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),Object.defineProperty(t,"exports",{enumerable:!0}),t.webpackPolyfill=1}return t}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o=n(1),i=(r=o)&&r.__esModule?r:{default:r},a=n(583);t.default=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.default.Map,n=Object.keys(e);return function(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:t(),o=arguments[1];return r.withMutations(function(t){n.forEach(function(n){var r=(0,e[n])(t.get(n),o);(0,a.validateNextState)(r,n,o),t.set(n,r)})})}},e.exports=t.default},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.validateNextState=t.getUnexpectedInvocationParameterMessage=t.getStateName=void 0;var r=a(n(359)),o=a(n(584)),i=a(n(585));function a(e){return e&&e.__esModule?e:{default:e}}t.getStateName=r.default,t.getUnexpectedInvocationParameterMessage=o.default,t.validateNextState=i.default},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=i(n(1)),o=i(n(359));function i(e){return e&&e.__esModule?e:{default:e}}t.default=function(e,t,n){var i=Object.keys(t);if(!i.length)return"Store does not have a valid reducer. Make sure the argument passed to combineReducers is an object whose values are reducers.";var a=(0,o.default)(n);if(!r.default.Iterable.isIterable(e))return"The "+a+' is of unexpected type. Expected argument to be an instance of Immutable.Iterable with the following properties: "'+i.join('", "')+'".';var s=e.keySeq().toArray().filter(function(e){return!t.hasOwnProperty(e)});return s.length>0?"Unexpected "+(1===s.length?"property":"properties")+' "'+s.join('", "')+'" found in '+a+'. Expected to find one of the known reducer property names instead: "'+i.join('", "')+'". Unexpected properties will be ignored.':null},e.exports=t.default},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,n){if(void 0===e)throw new Error('Reducer "'+t+'" returned undefined when handling "'+n.type+'" action. To ignore an action, you must explicitly return the previous state.')},e.exports=t.default},function(e,t,n){var r=n(14);e.exports=function(e){if(r(e))return e}},function(e,t,n){var r=n(90);e.exports=function(e,t){var n=[],o=!0,i=!1,a=void 0;try{for(var s,u=r(e);!(o=(s=u.next()).done)&&(n.push(s.value),!t||n.length!==t);o=!0);}catch(e){i=!0,a=e}finally{try{o||null==u.return||u.return()}finally{if(i)throw a}}return n}},function(e,t,n){n(99),n(97),e.exports=n(589)},function(e,t,n){var r=n(44),o=n(217);e.exports=n(22).getIterator=function(e){var t=o(e);if("function"!=typeof t)throw TypeError(e+" is not iterable!");return r(t.call(e))}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t,n){var r=n(65),o=n(262);e.exports=function(e){return o(r(e).toLowerCase())}},function(e,t,n){var r=n(102),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=i.call(e,s),n=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=a.call(e);return r&&(t?e[s]=n:delete e[s]),o}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r=n(595),o=n(364),i=n(596),a=n(65);e.exports=function(e){return function(t){t=a(t);var n=o(t)?i(t):void 0,s=n?n[0]:t.charAt(0),u=n?r(n,1).join(""):t.slice(1);return s[e]()+u}}},function(e,t,n){var r=n(363);e.exports=function(e,t,n){var o=e.length;return n=void 0===n?o:n,!t&&n>=o?e:r(e,t,n)}},function(e,t,n){var r=n(597),o=n(364),i=n(598);e.exports=function(e){return o(e)?i(e):r(e)}},function(e,t){e.exports=function(e){return e.split("")}},function(e,t){var n="[\\ud800-\\udfff]",r="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",o="\\ud83c[\\udffb-\\udfff]",i="[^\\ud800-\\udfff]",a="(?:\\ud83c[\\udde6-\\uddff]){2}",s="[\\ud800-\\udbff][\\udc00-\\udfff]",u="(?:"+r+"|"+o+")"+"?",c="[\\ufe0e\\ufe0f]?"+u+("(?:\\u200d(?:"+[i,a,s].join("|")+")[\\ufe0e\\ufe0f]?"+u+")*"),l="(?:"+[i+r+"?",r,a,s,n].join("|")+")",p=RegExp(o+"(?="+o+")|"+l+c,"g");e.exports=function(e){return e.match(p)||[]}},function(e,t,n){var r=n(365),o=n(600),i=n(603),a=RegExp("['’]","g");e.exports=function(e){return function(t){return r(i(o(t).replace(a,"")),e,"")}}},function(e,t,n){var r=n(601),o=n(65),i=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,a=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g");e.exports=function(e){return(e=o(e))&&e.replace(i,r).replace(a,"")}},function(e,t,n){var r=n(602)({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"});e.exports=r},function(e,t){e.exports=function(e){return function(t){return null==e?void 0:e[t]}}},function(e,t,n){var r=n(604),o=n(605),i=n(65),a=n(606);e.exports=function(e,t,n){return e=i(e),void 0===(t=n?void 0:t)?o(e)?a(e):r(e):e.match(t)||[]}},function(e,t){var n=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;e.exports=function(e){return e.match(n)||[]}},function(e,t){var n=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;e.exports=function(e){return n.test(e)}},function(e,t){var n="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",r="["+n+"]",o="\\d+",i="[\\u2700-\\u27bf]",a="[a-z\\xdf-\\xf6\\xf8-\\xff]",s="[^\\ud800-\\udfff"+n+o+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",u="(?:\\ud83c[\\udde6-\\uddff]){2}",c="[\\ud800-\\udbff][\\udc00-\\udfff]",l="[A-Z\\xc0-\\xd6\\xd8-\\xde]",p="(?:"+a+"|"+s+")",f="(?:"+l+"|"+s+")",h="(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?",d="[\\ufe0e\\ufe0f]?"+h+("(?:\\u200d(?:"+["[^\\ud800-\\udfff]",u,c].join("|")+")[\\ufe0e\\ufe0f]?"+h+")*"),m="(?:"+[i,u,c].join("|")+")"+d,v=RegExp([l+"?"+a+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[r,l,"$"].join("|")+")",f+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[r,l+p,"$"].join("|")+")",l+"?"+p+"+(?:['’](?:d|ll|m|re|s|t|ve))?",l+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",o,m].join("|"),"g");e.exports=function(e){return e.match(v)||[]}},function(e,t,n){var r=n(608),o=n(165),i=n(219);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(i||o),string:new r}}},function(e,t,n){var r=n(609),o=n(614),i=n(615),a=n(616),s=n(617);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=s,e.exports=u},function(e,t,n){var r=n(164);e.exports=function(){this.__data__=r?r(null):{},this.size=0}},function(e,t,n){var r=n(366),o=n(611),i=n(49),a=n(367),s=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,l=u.toString,p=c.hasOwnProperty,f=RegExp("^"+l.call(p).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!i(e)||o(e))&&(r(e)?f:s).test(a(e))}},function(e,t,n){var r,o=n(612),i=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!i&&i in e}},function(e,t,n){var r=n(48)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t){e.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},function(e,t,n){var r=n(164),o="__lodash_hash_undefined__",i=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;if(r){var n=t[e];return n===o?void 0:n}return i.call(t,e)?t[e]:void 0}},function(e,t,n){var r=n(164),o=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;return r?void 0!==t[e]:o.call(t,e)}},function(e,t,n){var r=n(164),o="__lodash_hash_undefined__";e.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=r&&void 0===t?o:t,this}},function(e,t){e.exports=function(){this.__data__=[],this.size=0}},function(e,t,n){var r=n(166),o=Array.prototype.splice;e.exports=function(e){var t=this.__data__,n=r(t,e);return!(n<0||(n==t.length-1?t.pop():o.call(t,n,1),--this.size,0))}},function(e,t,n){var r=n(166);e.exports=function(e){var t=this.__data__,n=r(t,e);return n<0?void 0:t[n][1]}},function(e,t,n){var r=n(166);e.exports=function(e){return r(this.__data__,e)>-1}},function(e,t,n){var r=n(166);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},function(e,t,n){var r=n(167);e.exports=function(e){var t=r(this,e).delete(e);return this.size-=t?1:0,t}},function(e,t){e.exports=function(e){var t=typeof e;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},function(e,t,n){var r=n(167);e.exports=function(e){return r(this,e).get(e)}},function(e,t,n){var r=n(167);e.exports=function(e){return r(this,e).has(e)}},function(e,t,n){var r=n(167);e.exports=function(e,t){var n=r(this,e),o=n.size;return n.set(e,t),this.size+=n.size==o?0:1,this}},function(e,t,n){var r=n(168),o=n(103),i=n(83);e.exports=function(e){return function(t,n,a){var s=Object(t);if(!o(t)){var u=r(n,3);t=i(t),n=function(e){return u(s[e],e,s)}}var c=e(t,n,a);return c>-1?s[u?t[c]:c]:void 0}}},function(e,t,n){var r=n(630),o=n(656),i=n(379);e.exports=function(e){var t=o(e);return 1==t.length&&t[0][2]?i(t[0][0],t[0][1]):function(n){return n===e||r(n,e,t)}}},function(e,t,n){var r=n(220),o=n(368),i=1,a=2;e.exports=function(e,t,n,s){var u=n.length,c=u,l=!s;if(null==e)return!c;for(e=Object(e);u--;){var p=n[u];if(l&&p[2]?p[1]!==e[p[0]]:!(p[0]in e))return!1}for(;++u<c;){var f=(p=n[u])[0],h=e[f],d=p[1];if(l&&p[2]){if(void 0===h&&!(f in e))return!1}else{var m=new r;if(s)var v=s(h,d,f,e,t,m);if(!(void 0===v?o(d,h,i|a,s,m):v))return!1}}return!0}},function(e,t,n){var r=n(165);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(165),o=n(219),i=n(218),a=200;e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var s=n.__data__;if(!o||s.length<a-1)return s.push([e,t]),this.size=++n.size,this;n=this.__data__=new i(s)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(220),o=n(369),i=n(641),a=n(644),s=n(172),u=n(35),c=n(224),l=n(376),p=1,f="[object Arguments]",h="[object Array]",d="[object Object]",m=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,v,g,y){var b=u(e),_=u(t),w=b?h:s(e),x=_?h:s(t),E=(w=w==f?d:w)==d,S=(x=x==f?d:x)==d,C=w==x;if(C&&c(e)){if(!c(t))return!1;b=!0,E=!1}if(C&&!E)return y||(y=new r),b||l(e)?o(e,t,n,v,g,y):i(e,t,w,n,v,g,y);if(!(n&p)){var k=E&&m.call(e,"__wrapped__"),O=S&&m.call(t,"__wrapped__");if(k||O){var A=k?e.value():e,T=O?t.value():t;return y||(y=new r),g(A,T,n,v,y)}}return!!C&&(y||(y=new r),a(e,t,n,v,g,y))}},function(e,t,n){var r=n(218),o=n(638),i=n(639);function a(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new r;++t<n;)this.add(e[t])}a.prototype.add=a.prototype.push=o,a.prototype.has=i,e.exports=a},function(e,t){var n="__lodash_hash_undefined__";e.exports=function(e){return this.__data__.set(e,n),this}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t){e.exports=function(e,t){return e.has(t)}},function(e,t,n){var r=n(102),o=n(371),i=n(89),a=n(369),s=n(642),u=n(643),c=1,l=2,p="[object Boolean]",f="[object Date]",h="[object Error]",d="[object Map]",m="[object Number]",v="[object RegExp]",g="[object Set]",y="[object String]",b="[object Symbol]",_="[object ArrayBuffer]",w="[object DataView]",x=r?r.prototype:void 0,E=x?x.valueOf:void 0;e.exports=function(e,t,n,r,x,S,C){switch(n){case w:if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case _:return!(e.byteLength!=t.byteLength||!S(new o(e),new o(t)));case p:case f:case m:return i(+e,+t);case h:return e.name==t.name&&e.message==t.message;case v:case y:return e==t+"";case d:var k=s;case g:var O=r&c;if(k||(k=u),e.size!=t.size&&!O)return!1;var A=C.get(e);if(A)return A==t;r|=l,C.set(e,t);var T=a(k(e),k(t),r,x,S,C);return C.delete(e),T;case b:if(E)return E.call(e)==E.call(t)}return!1}},function(e,t){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach(function(e,r){n[++t]=[r,e]}),n}},function(e,t){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach(function(e){n[++t]=e}),n}},function(e,t,n){var r=n(372),o=1,i=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,a,s,u){var c=n&o,l=r(e),p=l.length;if(p!=r(t).length&&!c)return!1;for(var f=p;f--;){var h=l[f];if(!(c?h in t:i.call(t,h)))return!1}var d=u.get(e);if(d&&u.get(t))return d==t;var m=!0;u.set(e,t),u.set(t,e);for(var v=c;++f<p;){var g=e[h=l[f]],y=t[h];if(a)var b=c?a(y,g,h,t,e,u):a(g,y,h,e,t,u);if(!(void 0===b?g===y||s(g,y,n,a,u):b)){m=!1;break}v||(v="constructor"==h)}if(m&&!v){var _=e.constructor,w=t.constructor;_!=w&&"constructor"in e&&"constructor"in t&&!("function"==typeof _&&_ instanceof _&&"function"==typeof w&&w instanceof w)&&(m=!1)}return u.delete(e),u.delete(t),m}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,o=0,i=[];++n<r;){var a=e[n];t(a,n,e)&&(i[o++]=a)}return i}},function(e,t){e.exports=function(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}},function(e,t,n){var r=n(81),o=n(63),i="[object Arguments]";e.exports=function(e){return o(e)&&r(e)==i}},function(e,t){e.exports=function(){return!1}},function(e,t,n){var r=n(81),o=n(225),i=n(63),a={};a["[object Float32Array]"]=a["[object Float64Array]"]=a["[object Int8Array]"]=a["[object Int16Array]"]=a["[object Int32Array]"]=a["[object Uint8Array]"]=a["[object Uint8ClampedArray]"]=a["[object Uint16Array]"]=a["[object Uint32Array]"]=!0,a["[object Arguments]"]=a["[object Array]"]=a["[object ArrayBuffer]"]=a["[object Boolean]"]=a["[object DataView]"]=a["[object Date]"]=a["[object Error]"]=a["[object Function]"]=a["[object Map]"]=a["[object Number]"]=a["[object Object]"]=a["[object RegExp]"]=a["[object Set]"]=a["[object String]"]=a["[object WeakMap]"]=!1,e.exports=function(e){return i(e)&&o(e.length)&&!!a[r(e)]}},function(e,t,n){var r=n(171),o=n(651),i=Object.prototype.hasOwnProperty;e.exports=function(e){if(!r(e))return o(e);var t=[];for(var n in Object(e))i.call(e,n)&&"constructor"!=n&&t.push(n);return t}},function(e,t,n){var r=n(377)(Object.keys,Object);e.exports=r},function(e,t,n){var r=n(82)(n(48),"DataView");e.exports=r},function(e,t,n){var r=n(82)(n(48),"Promise");e.exports=r},function(e,t,n){var r=n(82)(n(48),"Set");e.exports=r},function(e,t,n){var r=n(82)(n(48),"WeakMap");e.exports=r},function(e,t,n){var r=n(378),o=n(83);e.exports=function(e){for(var t=o(e),n=t.length;n--;){var i=t[n],a=e[i];t[n]=[i,a,r(a)]}return t}},function(e,t,n){var r=n(368),o=n(91),i=n(380),a=n(228),s=n(378),u=n(379),c=n(105),l=1,p=2;e.exports=function(e,t){return a(e)&&s(t)?u(c(e),t):function(n){var a=o(n,e);return void 0===a&&a===t?i(n,e):r(t,a,l|p)}}},function(e,t,n){var r=n(659),o=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,i=/\\(\\)?/g,a=r(function(e){var t=[];return 46===e.charCodeAt(0)&&t.push(""),e.replace(o,function(e,n,r,o){t.push(r?o.replace(i,"$1"):n||e)}),t});e.exports=a},function(e,t,n){var r=n(263),o=500;e.exports=function(e){var t=r(e,function(e){return n.size===o&&n.clear(),e}),n=t.cache;return t}},function(e,t){e.exports=function(e,t){return null!=e&&t in Object(e)}},function(e,t,n){var r=n(104),o=n(223),i=n(35),a=n(170),s=n(225),u=n(105);e.exports=function(e,t,n){for(var c=-1,l=(t=r(t,e)).length,p=!1;++c<l;){var f=u(t[c]);if(!(p=null!=e&&n(e,f)))break;e=e[f]}return p||++c!=l?p:!!(l=null==e?0:e.length)&&s(l)&&a(f,l)&&(i(e)||o(e))}},function(e,t,n){var r=n(663),o=n(664),i=n(228),a=n(105);e.exports=function(e){return i(e)?r(a(e)):o(e)}},function(e,t){e.exports=function(e){return function(t){return null==t?void 0:t[e]}}},function(e,t,n){var r=n(173);e.exports=function(e){return function(t){return r(t,e)}}},function(e,t,n){var r=n(666),o=n(168),i=n(381),a=Math.max;e.exports=function(e,t,n){var s=null==e?0:e.length;if(!s)return-1;var u=null==n?0:i(n);return u<0&&(u=a(s+u,0)),r(e,o(t,3),u)}},function(e,t){e.exports=function(e,t,n,r){for(var o=e.length,i=n+(r?1:-1);r?i--:++i<o;)if(t(e[i],i,e))return i;return-1}},function(e,t,n){var r=n(382),o=1/0,i=17976931348623157e292;e.exports=function(e){return e?(e=r(e))===o||e===-o?(e<0?-1:1)*i:e==e?e:0:0===e?e:0}},function(e,t,n){var r=n(383);e.exports=function(e,t){var n;return r(e,function(e,r,o){return!(n=t(e,r,o))}),!!n}},function(e,t,n){var r=n(670),o=n(83);e.exports=function(e,t){return e&&r(e,t,o)}},function(e,t,n){var r=n(671)();e.exports=r},function(e,t){e.exports=function(e){return function(t,n,r){for(var o=-1,i=Object(t),a=r(t),s=a.length;s--;){var u=a[e?s:++o];if(!1===n(i[u],u,i))break}return t}}},function(e,t,n){var r=n(103);e.exports=function(e,t){return function(n,o){if(null==n)return n;if(!r(n))return e(n,o);for(var i=n.length,a=t?i:-1,s=Object(n);(t?a--:++a<i)&&!1!==o(s[a],a,s););return n}}},function(e,t){var n={"&":"&amp;",'"':"&quot;","'":"&apos;","<":"&lt;",">":"&gt;"};e.exports=function(e){return e&&e.replace?e.replace(/([&"<>'])/g,function(e,t){return n[t]}):e}},function(e,t,n){e.exports=o;var r=n(230).EventEmitter;function o(){r.call(this)}n(106)(o,r),o.Readable=n(231),o.Writable=n(681),o.Duplex=n(682),o.Transform=n(683),o.PassThrough=n(684),o.Stream=o,o.prototype.pipe=function(e,t){var n=this;function o(t){e.writable&&!1===e.write(t)&&n.pause&&n.pause()}function i(){n.readable&&n.resume&&n.resume()}n.on("data",o),e.on("drain",i),e._isStdio||t&&!1===t.end||(n.on("end",s),n.on("close",u));var a=!1;function s(){a||(a=!0,e.end())}function u(){a||(a=!0,"function"==typeof e.destroy&&e.destroy())}function c(e){if(l(),0===r.listenerCount(this,"error"))throw e}function l(){n.removeListener("data",o),e.removeListener("drain",i),n.removeListener("end",s),n.removeListener("close",u),n.removeListener("error",c),e.removeListener("error",c),n.removeListener("end",l),n.removeListener("close",l),e.removeListener("close",l)}return n.on("error",c),e.on("error",c),n.on("end",l),n.on("close",l),e.on("close",l),e.emit("pipe",n),e}},function(e,t){},function(e,t,n){"use strict";var r=n(175).Buffer,o=n(677);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,u=1,c={},l=!1,p=e.document,f=Object.getPrototypeOf&&Object.getPrototypeOf(e);f=f&&f.setTimeout?f:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):p&&"onreadystatechange"in p.createElement("script")?(o=p.documentElement,r=function(e){var t=p.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),f.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var o={callback:e,args:t};return c[u]=o,r(u),u++},f.clearImmediate=h}function h(e){delete c[e]}function d(e){if(l)setTimeout(d,0,e);else{var t=c[e];if(t){l=!0;try{!function(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}(t)}finally{h(e),l=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(41),n(72))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(41))},function(e,t,n){"use strict";e.exports=i;var r=n(390),o=n(134);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}o.inherits=n(106),o.inherits(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){e.exports=n(232)},function(e,t,n){e.exports=n(84)},function(e,t,n){e.exports=n(231).Transform},function(e,t,n){e.exports=n(231).PassThrough},function(e,t,n){"use strict";var r=n(686),o=Math.abs,i=Math.floor;e.exports=function(e){return isNaN(e)?0:0!==(e=Number(e))&&isFinite(e)?r(e)*i(o(e)):e}},function(e,t,n){"use strict";e.exports=n(687)()?Math.sign:n(688)},function(e,t,n){"use strict";e.exports=function(){var e=Math.sign;return"function"==typeof e&&(1===e(10)&&-1===e(-20))}},function(e,t,n){"use strict";e.exports=function(e){return e=Number(e),isNaN(e)||0===e?e:e>0?1:-1}},function(e,t,n){"use strict";var r=n(73),o=n(176),i=n(87),a=n(691),s=n(393);e.exports=function e(t){var n,u,c;if(r(t),(n=Object(arguments[1])).async&&n.promise)throw new Error("Options 'async' and 'promise' cannot be used together");return hasOwnProperty.call(t,"__memoized__")&&!n.force?t:(u=s(n.length,t.length,n.async&&i.async),c=a(t,u,n),o(i,function(e,t){n[t]&&e(n[t],c,n)}),e.__profiler__&&e.__profiler__(c),c.updateEnv(),c.memoized)}},function(e,t,n){"use strict";var r=n(73),o=n(107),i=Function.prototype.bind,a=Function.prototype.call,s=Object.keys,u=Object.prototype.propertyIsEnumerable;e.exports=function(e,t){return function(n,c){var l,p=arguments[2],f=arguments[3];return n=Object(o(n)),r(c),l=s(n),f&&l.sort("function"==typeof f?i.call(f,n):void 0),"function"!=typeof e&&(e=l[e]),a.call(e,l,function(e,r){return u.call(n,e)?a.call(c,p,n[e],e,n,r):t})}}},function(e,t,n){"use strict";var r=n(692),o=n(395),i=n(177),a=n(702).methods,s=n(703),u=n(715),c=Function.prototype.apply,l=Function.prototype.call,p=Object.create,f=Object.defineProperties,h=a.on,d=a.emit;e.exports=function(e,t,n){var a,m,v,g,y,b,_,w,x,E,S,C,k,O,A,T=p(null);return m=!1!==t?t:isNaN(e.length)?1:e.length,n.normalizer&&(E=u(n.normalizer),v=E.get,g=E.set,y=E.delete,b=E.clear),null!=n.resolvers&&(A=s(n.resolvers)),O=v?o(function(t){var n,o,i=arguments;if(A&&(i=A(i)),null!==(n=v(i))&&hasOwnProperty.call(T,n))return S&&a.emit("get",n,i,this),T[n];if(o=1===i.length?l.call(e,this,i[0]):c.call(e,this,i),null===n){if(null!==(n=v(i)))throw r("Circular invocation","CIRCULAR_INVOCATION");n=g(i)}else if(hasOwnProperty.call(T,n))throw r("Circular invocation","CIRCULAR_INVOCATION");return T[n]=o,C&&a.emit("set",n,null,o),o},m):0===t?function(){var t;if(hasOwnProperty.call(T,"data"))return S&&a.emit("get","data",arguments,this),T.data;if(t=arguments.length?c.call(e,this,arguments):l.call(e,this),hasOwnProperty.call(T,"data"))throw r("Circular invocation","CIRCULAR_INVOCATION");return T.data=t,C&&a.emit("set","data",null,t),t}:function(t){var n,o,i=arguments;if(A&&(i=A(arguments)),o=String(i[0]),hasOwnProperty.call(T,o))return S&&a.emit("get",o,i,this),T[o];if(n=1===i.length?l.call(e,this,i[0]):c.call(e,this,i),hasOwnProperty.call(T,o))throw r("Circular invocation","CIRCULAR_INVOCATION");return T[o]=n,C&&a.emit("set",o,null,n),n},a={original:e,memoized:O,profileName:n.profileName,get:function(e){return A&&(e=A(e)),v?v(e):String(e[0])},has:function(e){return hasOwnProperty.call(T,e)},delete:function(e){var t;hasOwnProperty.call(T,e)&&(y&&y(e),t=T[e],delete T[e],k&&a.emit("delete",e,t))},clear:function(){var e=T;b&&b(),T=p(null),a.emit("clear",e)},on:function(e,t){return"get"===e?S=!0:"set"===e?C=!0:"delete"===e&&(k=!0),h.call(this,e,t)},emit:d,updateEnv:function(){e=a.original}},_=v?o(function(e){var t,n=arguments;A&&(n=A(n)),null!==(t=v(n))&&a.delete(t)},m):0===t?function(){return a.delete("data")}:function(e){return A&&(e=A(arguments)[0]),a.delete(e)},w=o(function(){var e,n=arguments;return 0===t?T.data:(A&&(n=A(n)),e=v?v(n):String(n[0]),T[e])}),x=o(function(){var e,n=arguments;return 0===t?a.has("data"):(A&&(n=A(n)),null!==(e=v?v(n):String(n[0]))&&a.has(e))}),f(O,{__memoized__:i(!0),delete:i(_),clear:i(a.clear),_get:i(w),_has:i(x)}),a}},function(e,t,n){"use strict";var r=n(394),o=n(698),i=n(85),a=Error.captureStackTrace;t=e.exports=function(e){var n=new Error(e),s=arguments[1],u=arguments[2];return i(u)||o(s)&&(u=s,s=null),i(u)&&r(n,u),i(s)&&(n.code=s),a&&a(n,t),n}},function(e,t,n){"use strict";e.exports=function(){var e,t=Object.assign;return"function"==typeof t&&(t(e={foo:"raz"},{bar:"dwa"},{trzy:"trzy"}),e.foo+e.bar+e.trzy==="razdwatrzy")}},function(e,t,n){"use strict";var r=n(695),o=n(107),i=Math.max;e.exports=function(e,t){var n,a,s,u=i(arguments.length,2);for(e=Object(o(e)),s=function(r){try{e[r]=t[r]}catch(e){n||(n=e)}},a=1;a<u;++a)t=arguments[a],r(t).forEach(s);if(void 0!==n)throw n;return e}},function(e,t,n){"use strict";e.exports=n(696)()?Object.keys:n(697)},function(e,t,n){"use strict";e.exports=function(){try{return Object.keys("primitive"),!0}catch(e){return!1}}},function(e,t,n){"use strict";var r=n(85),o=Object.keys;e.exports=function(e){return o(r(e)?Object(e):e)}},function(e,t,n){"use strict";var r=n(85),o={function:!0,object:!0};e.exports=function(e){return r(e)&&o[typeof e]||!1}},function(e,t,n){"use strict";e.exports=n(700)()?String.prototype.contains:n(701)},function(e,t,n){"use strict";var r="razdwatrzy";e.exports=function(){return"function"==typeof r.contains&&(!0===r.contains("dwa")&&!1===r.contains("foo"))}},function(e,t,n){"use strict";var r=String.prototype.indexOf;e.exports=function(e){return r.call(this,e,arguments[1])>-1}},function(e,t,n){"use strict";var r,o,i,a,s,u,c,l=n(177),p=n(73),f=Function.prototype.apply,h=Function.prototype.call,d=Object.create,m=Object.defineProperty,v=Object.defineProperties,g=Object.prototype.hasOwnProperty,y={configurable:!0,enumerable:!1,writable:!0};o=function(e,t){var n,o;return p(t),o=this,r.call(this,e,n=function(){i.call(o,e,n),f.call(t,this,arguments)}),n.__eeOnceListener__=t,this},s={on:r=function(e,t){var n;return p(t),g.call(this,"__ee__")?n=this.__ee__:(n=y.value=d(null),m(this,"__ee__",y),y.value=null),n[e]?"object"==typeof n[e]?n[e].push(t):n[e]=[n[e],t]:n[e]=t,this},once:o,off:i=function(e,t){var n,r,o,i;if(p(t),!g.call(this,"__ee__"))return this;if(!(n=this.__ee__)[e])return this;if("object"==typeof(r=n[e]))for(i=0;o=r[i];++i)o!==t&&o.__eeOnceListener__!==t||(2===r.length?n[e]=r[i?0:1]:r.splice(i,1));else r!==t&&r.__eeOnceListener__!==t||delete n[e];return this},emit:a=function(e){var t,n,r,o,i;if(g.call(this,"__ee__")&&(o=this.__ee__[e]))if("object"==typeof o){for(n=arguments.length,i=new Array(n-1),t=1;t<n;++t)i[t-1]=arguments[t];for(o=o.slice(),t=0;r=o[t];++t)f.call(r,this,i)}else switch(arguments.length){case 1:h.call(o,this);break;case 2:h.call(o,this,arguments[1]);break;case 3:h.call(o,this,arguments[1],arguments[2]);break;default:for(n=arguments.length,i=new Array(n-1),t=1;t<n;++t)i[t-1]=arguments[t];f.call(o,this,i)}}},u={on:l(r),once:l(o),off:l(i),emit:l(a)},c=v({},u),e.exports=t=function(e){return null==e?d(c):v(Object(e),u)},t.methods=s},function(e,t,n){"use strict";var r,o=n(704),i=n(85),a=n(73),s=Array.prototype.slice;r=function(e){return this.map(function(t,n){return t?t(e[n]):e[n]}).concat(s.call(e,this.length))},e.exports=function(e){return(e=o(e)).forEach(function(e){i(e)&&a(e)}),r.bind(e)}},function(e,t,n){"use strict";var r=n(234),o=Array.isArray;e.exports=function(e){return o(e)?e:r(e)}},function(e,t,n){"use strict";e.exports=function(){var e,t,n=Array.from;return"function"==typeof n&&(t=n(e=["raz","dwa"]),Boolean(t&&t!==e&&"dwa"===t[1]))}},function(e,t,n){"use strict";var r=n(707).iterator,o=n(712),i=n(713),a=n(86),s=n(73),u=n(107),c=n(85),l=n(714),p=Array.isArray,f=Function.prototype.call,h={configurable:!0,enumerable:!0,writable:!0,value:null},d=Object.defineProperty;e.exports=function(e){var t,n,m,v,g,y,b,_,w,x,E=arguments[1],S=arguments[2];if(e=Object(u(e)),c(E)&&s(E),this&&this!==Array&&i(this))t=this;else{if(!E){if(o(e))return 1!==(g=e.length)?Array.apply(null,e):((v=new Array(1))[0]=e[0],v);if(p(e)){for(v=new Array(g=e.length),n=0;n<g;++n)v[n]=e[n];return v}}v=[]}if(!p(e))if(void 0!==(w=e[r])){for(b=s(w).call(e),t&&(v=new t),_=b.next(),n=0;!_.done;)x=E?f.call(E,S,_.value,n):_.value,t?(h.value=x,d(v,n,h)):v[n]=x,_=b.next(),++n;g=n}else if(l(e)){for(g=e.length,t&&(v=new t),n=0,m=0;n<g;++n)x=e[n],n+1<g&&(y=x.charCodeAt(0))>=55296&&y<=56319&&(x+=e[++n]),x=E?f.call(E,S,x,m):x,t?(h.value=x,d(v,m,h)):v[m]=x,++m;g=m}if(void 0===g)for(g=a(e.length),t&&(v=new t(g)),n=0;n<g;++n)x=E?f.call(E,S,e[n],n):e[n],t?(h.value=x,d(v,n,h)):v[n]=x;return t&&(h.value=null,v.length=g),v}},function(e,t,n){"use strict";e.exports=n(708)()?Symbol:n(709)},function(e,t,n){"use strict";var r={object:!0,symbol:!0};e.exports=function(){var e;if("function"!=typeof Symbol)return!1;e=Symbol("test symbol");try{String(e)}catch(e){return!1}return!!r[typeof Symbol.iterator]&&(!!r[typeof Symbol.toPrimitive]&&!!r[typeof Symbol.toStringTag])}},function(e,t,n){"use strict";var r,o,i,a,s=n(177),u=n(710),c=Object.create,l=Object.defineProperties,p=Object.defineProperty,f=Object.prototype,h=c(null);if("function"==typeof Symbol){r=Symbol;try{String(r()),a=!0}catch(e){}}var d,m=(d=c(null),function(e){for(var t,n,r=0;d[e+(r||"")];)++r;return d[e+=r||""]=!0,p(f,t="@@"+e,s.gs(null,function(e){n||(n=!0,p(this,t,s(e)),n=!1)})),t});i=function(e){if(this instanceof i)throw new TypeError("Symbol is not a constructor");return o(e)},e.exports=o=function e(t){var n;if(this instanceof e)throw new TypeError("Symbol is not a constructor");return a?r(t):(n=c(i.prototype),t=void 0===t?"":String(t),l(n,{__description__:s("",t),__name__:s("",m(t))}))},l(o,{for:s(function(e){return h[e]?h[e]:h[e]=o(String(e))}),keyFor:s(function(e){var t;for(t in u(e),h)if(h[t]===e)return t}),hasInstance:s("",r&&r.hasInstance||o("hasInstance")),isConcatSpreadable:s("",r&&r.isConcatSpreadable||o("isConcatSpreadable")),iterator:s("",r&&r.iterator||o("iterator")),match:s("",r&&r.match||o("match")),replace:s("",r&&r.replace||o("replace")),search:s("",r&&r.search||o("search")),species:s("",r&&r.species||o("species")),split:s("",r&&r.split||o("split")),toPrimitive:s("",r&&r.toPrimitive||o("toPrimitive")),toStringTag:s("",r&&r.toStringTag||o("toStringTag")),unscopables:s("",r&&r.unscopables||o("unscopables"))}),l(i.prototype,{constructor:s(o),toString:s("",function(){return this.__name__})}),l(o.prototype,{toString:s(function(){return"Symbol ("+u(this).__description__+")"}),valueOf:s(function(){return u(this)})}),p(o.prototype,o.toPrimitive,s("",function(){var e=u(this);return"symbol"==typeof e?e:e.toString()})),p(o.prototype,o.toStringTag,s("c","Symbol")),p(i.prototype,o.toStringTag,s("c",o.prototype[o.toStringTag])),p(i.prototype,o.toPrimitive,s("c",o.prototype[o.toPrimitive]))},function(e,t,n){"use strict";var r=n(711);e.exports=function(e){if(!r(e))throw new TypeError(e+" is not a symbol");return e}},function(e,t,n){"use strict";e.exports=function(e){return!!e&&("symbol"==typeof e||!!e.constructor&&("Symbol"===e.constructor.name&&"Symbol"===e[e.constructor.toStringTag]))}},function(e,t,n){"use strict";var r=Object.prototype.toString,o=r.call(function(){return arguments}());e.exports=function(e){return r.call(e)===o}},function(e,t,n){"use strict";var r=Object.prototype.toString,o=r.call(n(392));e.exports=function(e){return"function"==typeof e&&r.call(e)===o}},function(e,t,n){"use strict";var r=Object.prototype.toString,o=r.call("");e.exports=function(e){return"string"==typeof e||e&&"object"==typeof e&&(e instanceof String||r.call(e)===o)||!1}},function(e,t,n){"use strict";var r=n(73);e.exports=function(e){var t;return"function"==typeof e?{set:e,get:e}:(t={get:r(e.get)},void 0!==e.set?(t.set=r(e.set),e.delete&&(t.delete=r(e.delete)),e.clear&&(t.clear=r(e.clear)),t):(t.set=t.get,t))}},function(e,t,n){"use strict";e.exports=function(e){var t,n,r=e.length;if(!r)return"";for(t=String(e[n=0]);--r;)t+=""+e[++n];return t}},function(e,t,n){"use strict";e.exports=function(e){return e?function(t){for(var n=String(t[0]),r=0,o=e;--o;)n+=""+t[++r];return n}:function(){return""}}},function(e,t,n){"use strict";var r=n(235),o=Object.create;e.exports=function(){var e=0,t=[],n=o(null);return{get:function(e){var n,o=0,i=t,a=e.length;if(0===a)return i[a]||null;if(i=i[a]){for(;o<a-1;){if(-1===(n=r.call(i[0],e[o])))return null;i=i[1][n],++o}return-1===(n=r.call(i[0],e[o]))?null:i[1][n]||null}return null},set:function(o){var i,a=0,s=t,u=o.length;if(0===u)s[u]=++e;else{for(s[u]||(s[u]=[[],[]]),s=s[u];a<u-1;)-1===(i=r.call(s[0],o[a]))&&(i=s[0].push(o[a])-1,s[1].push([[],[]])),s=s[1][i],++a;-1===(i=r.call(s[0],o[a]))&&(i=s[0].push(o[a])-1),s[1][i]=++e}return n[e]=o,e},delete:function(e){var o,i=0,a=t,s=n[e],u=s.length,c=[];if(0===u)delete a[u];else if(a=a[u]){for(;i<u-1;){if(-1===(o=r.call(a[0],s[i])))return;c.push(a,o),a=a[1][o],++i}if(-1===(o=r.call(a[0],s[i])))return;for(e=a[1][o],a[0].splice(o,1),a[1].splice(o,1);!a[0].length&&c.length;)o=c.pop(),(a=c.pop())[0].splice(o,1),a[1].splice(o,1)}delete n[e]},clear:function(){t=[],n=o(null)}}}},function(e,t,n){"use strict";e.exports=n(720)()?Number.isNaN:n(721)},function(e,t,n){"use strict";e.exports=function(){var e=Number.isNaN;return"function"==typeof e&&(!e({})&&e(NaN)&&!e(34))}},function(e,t,n){"use strict";e.exports=function(e){return e!=e}},function(e,t,n){"use strict";var r=n(235);e.exports=function(){var e=0,t=[],n=[];return{get:function(e){var o=r.call(t,e[0]);return-1===o?null:n[o]},set:function(r){return t.push(r[0]),n.push(++e),e},delete:function(e){var o=r.call(n,e);-1!==o&&(t.splice(o,1),n.splice(o,1))},clear:function(){t=[],n=[]}}}},function(e,t,n){"use strict";var r=n(235),o=Object.create;e.exports=function(e){var t=0,n=[[],[]],i=o(null);return{get:function(t){for(var o,i=0,a=n;i<e-1;){if(-1===(o=r.call(a[0],t[i])))return null;a=a[1][o],++i}return-1===(o=r.call(a[0],t[i]))?null:a[1][o]||null},set:function(o){for(var a,s=0,u=n;s<e-1;)-1===(a=r.call(u[0],o[s]))&&(a=u[0].push(o[s])-1,u[1].push([[],[]])),u=u[1][a],++s;return-1===(a=r.call(u[0],o[s]))&&(a=u[0].push(o[s])-1),u[1][a]=++t,i[t]=o,t},delete:function(t){for(var o,a=0,s=n,u=[],c=i[t];a<e-1;){if(-1===(o=r.call(s[0],c[a])))return;u.push(s,o),s=s[1][o],++a}if(-1!==(o=r.call(s[0],c[a]))){for(t=s[1][o],s[0].splice(o,1),s[1].splice(o,1);!s[0].length&&u.length;)o=u.pop(),(s=u.pop())[0].splice(o,1),s[1].splice(o,1);delete i[t]}},clear:function(){n=[[],[]],i=o(null)}}}},function(e,t,n){"use strict";var r=n(234),o=n(397),i=n(396),a=n(395),s=n(236),u=Array.prototype.slice,c=Function.prototype.apply,l=Object.create;n(87).async=function(e,t){var n,p,f,h=l(null),d=l(null),m=t.memoized,v=t.original;t.memoized=a(function(e){var t=arguments,r=t[t.length-1];return"function"==typeof r&&(n=r,t=u.call(t,0,-1)),m.apply(p=this,f=t)},m);try{i(t.memoized,m)}catch(e){}t.on("get",function(e){var r,o,i;if(n){if(h[e])return"function"==typeof h[e]?h[e]=[h[e],n]:h[e].push(n),void(n=null);r=n,o=p,i=f,n=p=f=null,s(function(){var a;hasOwnProperty.call(d,e)?(a=d[e],t.emit("getasync",e,i,o),c.call(r,a.context,a.args)):(n=r,p=o,f=i,m.apply(o,i))})}}),t.original=function(){var e,o,i,a;return n?(e=r(arguments),o=function e(n){var o,i,u=e.id;if(null!=u){if(delete e.id,o=h[u],delete h[u],o)return i=r(arguments),t.has(u)&&(n?t.delete(u):(d[u]={context:this,args:i},t.emit("setasync",u,"function"==typeof o?1:o.length))),"function"==typeof o?a=c.call(o,this,i):o.forEach(function(e){a=c.call(e,this,i)},this),a}else s(c.bind(e,this,arguments))},i=n,n=p=f=null,e.push(o),a=c.call(v,this,e),o.cb=i,n=o,a):c.call(v,this,arguments)},t.on("set",function(e){n?(h[e]?"function"==typeof h[e]?h[e]=[h[e],n.cb]:h[e].push(n.cb):h[e]=n.cb,delete n.cb,n.id=e,n=null):t.delete(e)}),t.on("delete",function(e){var n;hasOwnProperty.call(h,e)||d[e]&&(n=d[e],delete d[e],t.emit("deleteasync",e,u.call(n.args,1)))}),t.on("clear",function(){var e=d;d=l(null),t.emit("clearasync",o(e,function(e){return u.call(e.args,1)}))})}},function(e,t,n){"use strict";var r=n(397),o=n(726),i=n(727),a=n(729),s=n(398),u=n(236),c=Object.create,l=o("then","then:finally","done","done:finally");n(87).promise=function(e,t){var n=c(null),o=c(null),p=c(null);if(!0===e)e=null;else if(e=i(e),!l[e])throw new TypeError("'"+a(e)+"' is not valid promise mode");t.on("set",function(r,i,a){var c=!1;if(!s(a))return o[r]=a,void t.emit("setasync",r,1);n[r]=1,p[r]=a;var l=function(e){var i=n[r];if(c)throw new Error("Memoizee error: Detected unordered then|done & finally resolution, which in turn makes proper detection of success/failure impossible (when in 'done:finally' mode)\nConsider to rely on 'then' or 'done' mode instead.");i&&(delete n[r],o[r]=e,t.emit("setasync",r,i))},f=function(){c=!0,n[r]&&(delete n[r],delete p[r],t.delete(r))},h=e;if(h||(h="then"),"then"===h)a.then(function(e){u(l.bind(this,e))},function(){u(f)});else if("done"===h){if("function"!=typeof a.done)throw new Error("Memoizee error: Retrieved promise does not implement 'done' in 'done' mode");a.done(l,f)}else if("done:finally"===h){if("function"!=typeof a.done)throw new Error("Memoizee error: Retrieved promise does not implement 'done' in 'done:finally' mode");if("function"!=typeof a.finally)throw new Error("Memoizee error: Retrieved promise does not implement 'finally' in 'done:finally' mode");a.done(l),a.finally(f)}}),t.on("get",function(e,r,o){var i;if(n[e])++n[e];else{i=p[e];var a=function(){t.emit("getasync",e,r,o)};s(i)?"function"==typeof i.done?i.done(a):i.then(function(){u(a)}):a()}}),t.on("delete",function(e){if(delete p[e],n[e])delete n[e];else if(hasOwnProperty.call(o,e)){var r=o[e];delete o[e],t.emit("deleteasync",e,[r])}}),t.on("clear",function(){var e=o;o=c(null),n=c(null),p=c(null),t.emit("clearasync",r(e,function(e){return[e]}))})}},function(e,t,n){"use strict";var r=Array.prototype.forEach,o=Object.create;e.exports=function(e){var t=o(null);return r.call(arguments,function(e){t[e]=!0}),t}},function(e,t,n){"use strict";var r=n(107),o=n(728);e.exports=function(e){return o(r(e))}},function(e,t,n){"use strict";var r=n(233);e.exports=function(e){try{return e&&r(e.toString)?e.toString():String(e)}catch(e){throw new TypeError("Passed argument cannot be stringifed")}}},function(e,t,n){"use strict";var r=n(730),o=/[\n\r\u2028\u2029]/g;e.exports=function(e){var t=r(e);return t.length>100&&(t=t.slice(0,99)+"…"),t=t.replace(o,function(e){return JSON.stringify(e).slice(1,-1)})}},function(e,t,n){"use strict";var r=n(233);e.exports=function(e){try{return e&&r(e.toString)?e.toString():String(e)}catch(e){return"[Non-coercible (to string) value]"}}},function(e,t,n){"use strict";var r=n(73),o=n(176),i=n(87),a=Function.prototype.apply;i.dispose=function(e,t,n){var s;if(r(e),n.async&&i.async||n.promise&&i.promise)return t.on("deleteasync",s=function(t,n){a.call(e,null,n)}),void t.on("clearasync",function(e){o(e,function(e,t){s(t,e)})});t.on("delete",s=function(t,n){e(n)}),t.on("clear",function(e){o(e,function(e,t){s(t,e)})})}},function(e,t,n){"use strict";var r=n(234),o=n(176),i=n(236),a=n(398),s=n(733),u=n(87),c=Function.prototype,l=Math.max,p=Math.min,f=Object.create;u.maxAge=function(e,t,n){var h,d,m,v;(e=s(e))&&(h=f(null),d=n.async&&u.async||n.promise&&u.promise?"async":"",t.on("set"+d,function(n){h[n]=setTimeout(function(){t.delete(n)},e),"function"==typeof h[n].unref&&h[n].unref(),v&&(v[n]&&"nextTick"!==v[n]&&clearTimeout(v[n]),v[n]=setTimeout(function(){delete v[n]},m),"function"==typeof v[n].unref&&v[n].unref())}),t.on("delete"+d,function(e){clearTimeout(h[e]),delete h[e],v&&("nextTick"!==v[e]&&clearTimeout(v[e]),delete v[e])}),n.preFetch&&(m=!0===n.preFetch||isNaN(n.preFetch)?.333:l(p(Number(n.preFetch),1),0))&&(v={},m=(1-m)*e,t.on("get"+d,function(e,o,s){v[e]||(v[e]="nextTick",i(function(){var i;"nextTick"===v[e]&&(delete v[e],t.delete(e),n.async&&(o=r(o)).push(c),i=t.memoized.apply(s,o),n.promise&&a(i)&&("function"==typeof i.done?i.done(c,c):i.then(c,c)))}))})),t.on("clear"+d,function(){o(h,function(e){clearTimeout(e)}),h={},v&&(o(v,function(e){"nextTick"!==e&&clearTimeout(e)}),v={})}))}},function(e,t,n){"use strict";var r=n(86),o=n(734);e.exports=function(e){if((e=r(e))>o)throw new TypeError(e+" exceeds maximum possible timeout");return e}},function(e,t,n){"use strict";e.exports=2147483647},function(e,t,n){"use strict";var r=n(86),o=n(736),i=n(87);i.max=function(e,t,n){var a,s,u;(e=r(e))&&(s=o(e),a=n.async&&i.async||n.promise&&i.promise?"async":"",t.on("set"+a,u=function(e){void 0!==(e=s.hit(e))&&t.delete(e)}),t.on("get"+a,u),t.on("delete"+a,s.delete),t.on("clear"+a,s.clear))}},function(e,t,n){"use strict";var r=n(86),o=Object.create,i=Object.prototype.hasOwnProperty;e.exports=function(e){var t,n=0,a=1,s=o(null),u=o(null),c=0;return e=r(e),{hit:function(r){var o=u[r],l=++c;if(s[l]=r,u[r]=l,!o){if(++n<=e)return;return r=s[a],t(r),r}if(delete s[o],a===o)for(;!i.call(s,++a);)continue},delete:t=function(e){var t=u[e];if(t&&(delete s[t],delete u[e],--n,a===t)){if(!n)return c=0,void(a=1);for(;!i.call(s,++a);)continue}},clear:function(){n=0,a=1,s=o(null),u=o(null),c=0}}}},function(e,t,n){"use strict";var r=n(177),o=n(87),i=Object.create,a=Object.defineProperties;o.refCounter=function(e,t,n){var s,u;s=i(null),u=n.async&&o.async||n.promise&&o.promise?"async":"",t.on("set"+u,function(e,t){s[e]=t||1}),t.on("get"+u,function(e){++s[e]}),t.on("delete"+u,function(e){delete s[e]}),t.on("clear"+u,function(){s={}}),a(t.memoized,{deleteRef:r(function(){var e=t.get(arguments);return null===e?null:s[e]?!--s[e]&&(t.delete(e),!0):null}),getRefCount:r(function(){var e=t.get(arguments);return null===e?0:s[e]?s[e]:0})})}},function(e,t){e.exports=function(e,t,n,r,o){return o(e,function(e,o,i){n=r?(r=!1,e):t(n,e,o,i)}),n}},function(e,t,n){var r=n(14);e.exports=function(e){if(r(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t,n){var r=n(741),o=n(744);e.exports=function(e){if(o(Object(e))||"[object Arguments]"===Object.prototype.toString.call(e))return r(e)}},function(e,t,n){e.exports=n(742)},function(e,t,n){n(97),n(743),e.exports=n(22).Array.from},function(e,t,n){"use strict";var r=n(60),o=n(30),i=n(79),a=n(399),s=n(400),u=n(154),c=n(401),l=n(217);o(o.S+o.F*!n(402)(function(e){Array.from(e)}),"Array",{from:function(e){var t,n,o,p,f=i(e),h="function"==typeof this?this:Array,d=arguments.length,m=d>1?arguments[1]:void 0,v=void 0!==m,g=0,y=l(f);if(v&&(m=r(m,d>2?arguments[2]:void 0,2)),null==y||h==Array&&s(y))for(n=new h(t=u(f.length));t>g;g++)c(n,g,v?m(f[g],g):f[g]);else for(p=y.call(f),n=new h;!(o=p.next()).done;g++)c(n,g,v?a(p,m,[o.value,g],!0):o.value);return n.length=g,n}})},function(e,t,n){e.exports=n(745)},function(e,t,n){n(99),n(97),e.exports=n(746)},function(e,t,n){var r=n(162),o=n(34)("iterator"),i=n(98);e.exports=n(22).isIterable=function(e){var t=Object(e);return void 0!==t[o]||"@@iterator"in t||i.hasOwnProperty(r(t))}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t,n){n(749);var r=n(22).Object;e.exports=function(e,t){return r.defineProperties(e,t)}},function(e,t,n){var r=n(30);r(r.S+r.F*!n(45),"Object",{defineProperties:n(345)})},function(e,t,n){n(751),e.exports=n(22).Object.getOwnPropertyDescriptors},function(e,t,n){var r=n(30),o=n(752),i=n(70),a=n(159),s=n(401);r(r.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n,r=i(e),u=a.f,c=o(r),l={},p=0;c.length>p;)void 0!==(n=u(r,t=c[p++]))&&s(l,t,n);return l}})},function(e,t,n){var r=n(216),o=n(157),i=n(44),a=n(32).Reflect;e.exports=a&&a.ownKeys||function(e){var t=r.f(i(e)),n=o.f;return n?t.concat(n(e)):t}},function(e,t,n){n(754);var r=n(22).Object;e.exports=function(e,t){return r.getOwnPropertyDescriptor(e,t)}},function(e,t,n){var r=n(70),o=n(159).f;n(208)("getOwnPropertyDescriptor",function(){return function(e,t){return o(r(e),t)}})},function(e,t,n){n(349),e.exports=n(22).Object.getOwnPropertySymbols},function(e,t,n){var r=n(17);e.exports=function(e,t){if(null==e)return{};var n,o,i={},a=r(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(i[n]=e[n]);return i}},function(e,t,n){n(758),e.exports=n(22).Date.now},function(e,t,n){var r=n(30);r(r.S,"Date",{now:function(){return(new Date).getTime()}})},function(e,t,n){n(160),n(97),n(99),n(760),n(764),n(765),e.exports=n(22).Promise},function(e,t,n){"use strict";var r,o,i,a,s=n(128),u=n(32),c=n(60),l=n(162),p=n(30),f=n(40),h=n(129),d=n(178),m=n(108),v=n(403),g=n(404).set,y=n(762)(),b=n(237),_=n(405),w=n(763),x=n(406),E=u.TypeError,S=u.process,C=S&&S.versions,k=C&&C.v8||"",O=u.Promise,A="process"==l(S),T=function(){},j=o=b.f,P=!!function(){try{var e=O.resolve(1),t=(e.constructor={})[n(34)("species")]=function(e){e(T,T)};return(A||"function"==typeof PromiseRejectionEvent)&&e.then(T)instanceof t&&0!==k.indexOf("6.6")&&-1===w.indexOf("Chrome/66")}catch(e){}}(),I=function(e){var t;return!(!f(e)||"function"!=typeof(t=e.then))&&t},M=function(e,t){if(!e._n){e._n=!0;var n=e._c;y(function(){for(var r=e._v,o=1==e._s,i=0,a=function(t){var n,i,a,s=o?t.ok:t.fail,u=t.resolve,c=t.reject,l=t.domain;try{s?(o||(2==e._h&&D(e),e._h=1),!0===s?n=r:(l&&l.enter(),n=s(r),l&&(l.exit(),a=!0)),n===t.promise?c(E("Promise-chain cycle")):(i=I(n))?i.call(n,u,c):u(n)):c(r)}catch(e){l&&!a&&l.exit(),c(e)}};n.length>i;)a(n[i++]);e._c=[],e._n=!1,t&&!e._h&&N(e)})}},N=function(e){g.call(u,function(){var t,n,r,o=e._v,i=R(e);if(i&&(t=_(function(){A?S.emit("unhandledRejection",o,e):(n=u.onunhandledrejection)?n({promise:e,reason:o}):(r=u.console)&&r.error&&r.error("Unhandled promise rejection",o)}),e._h=A||R(e)?2:1),e._a=void 0,i&&t.e)throw t.v})},R=function(e){return 1!==e._h&&0===(e._a||e._c).length},D=function(e){g.call(u,function(){var t;A?S.emit("rejectionHandled",e):(t=u.onrejectionhandled)&&t({promise:e,reason:e._v})})},L=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),M(t,!0))},U=function(e){var t,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===e)throw E("Promise can't be resolved itself");(t=I(e))?y(function(){var r={_w:n,_d:!1};try{t.call(e,c(U,r,1),c(L,r,1))}catch(e){L.call(r,e)}}):(n._v=e,n._s=1,M(n,!1))}catch(e){L.call({_w:n,_d:!1},e)}}};P||(O=function(e){d(this,O,"Promise","_h"),h(e),r.call(this);try{e(c(U,this,1),c(L,this,1))}catch(e){L.call(this,e)}},(r=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=n(179)(O.prototype,{then:function(e,t){var n=j(v(this,O));return n.ok="function"!=typeof e||e,n.fail="function"==typeof t&&t,n.domain=A?S.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&M(this,!1),n.promise},catch:function(e){return this.then(void 0,e)}}),i=function(){var e=new r;this.promise=e,this.resolve=c(U,e,1),this.reject=c(L,e,1)},b.f=j=function(e){return e===O||e===a?new i(e):o(e)}),p(p.G+p.W+p.F*!P,{Promise:O}),n(131)(O,"Promise"),n(407)("Promise"),a=n(22).Promise,p(p.S+p.F*!P,"Promise",{reject:function(e){var t=j(this);return(0,t.reject)(e),t.promise}}),p(p.S+p.F*(s||!P),"Promise",{resolve:function(e){return x(s&&this===a?O:this,e)}}),p(p.S+p.F*!(P&&n(402)(function(e){O.all(e).catch(T)})),"Promise",{all:function(e){var t=this,n=j(t),r=n.resolve,o=n.reject,i=_(function(){var n=[],i=0,a=1;m(e,!1,function(e){var s=i++,u=!1;n.push(void 0),a++,t.resolve(e).then(function(e){u||(u=!0,n[s]=e,--a||r(n))},o)}),--a||r(n)});return i.e&&o(i.v),n.promise},race:function(e){var t=this,n=j(t),r=n.reject,o=_(function(){m(e,!1,function(e){t.resolve(e).then(n.resolve,r)})});return o.e&&r(o.v),n.promise}})},function(e,t){e.exports=function(e,t,n){var r=void 0===n;switch(t.length){case 0:return r?e():e.call(n);case 1:return r?e(t[0]):e.call(n,t[0]);case 2:return r?e(t[0],t[1]):e.call(n,t[0],t[1]);case 3:return r?e(t[0],t[1],t[2]):e.call(n,t[0],t[1],t[2]);case 4:return r?e(t[0],t[1],t[2],t[3]):e.call(n,t[0],t[1],t[2],t[3])}return e.apply(n,t)}},function(e,t,n){var r=n(32),o=n(404).set,i=r.MutationObserver||r.WebKitMutationObserver,a=r.process,s=r.Promise,u="process"==n(127)(a);e.exports=function(){var e,t,n,c=function(){var r,o;for(u&&(r=a.domain)&&r.exit();e;){o=e.fn,e=e.next;try{o()}catch(r){throw e?n():t=void 0,r}}t=void 0,r&&r.enter()};if(u)n=function(){a.nextTick(c)};else if(!i||r.navigator&&r.navigator.standalone)if(s&&s.resolve){var l=s.resolve(void 0);n=function(){l.then(c)}}else n=function(){o.call(r,c)};else{var p=!0,f=document.createTextNode("");new i(c).observe(f,{characterData:!0}),n=function(){f.data=p=!p}}return function(r){var o={fn:r,next:void 0};t&&(t.next=o),e||(e=o,n()),t=o}}},function(e,t,n){var r=n(32).navigator;e.exports=r&&r.userAgent||""},function(e,t,n){"use strict";var r=n(30),o=n(22),i=n(32),a=n(403),s=n(406);r(r.P+r.R,"Promise",{finally:function(e){var t=a(this,o.Promise||i.Promise),n="function"==typeof e;return this.then(n?function(n){return s(t,e()).then(function(){return n})}:e,n?function(n){return s(t,e()).then(function(){throw n})}:e)}})},function(e,t,n){"use strict";var r=n(30),o=n(237),i=n(405);r(r.S,"Promise",{try:function(e){var t=o.f(this),n=i(e);return(n.e?t.reject:t.resolve)(n.v),t.promise}})},function(e,t,n){var r=function(e){"use strict";var t,n=Object.prototype,r=n.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",s=o.toStringTag||"@@toStringTag";function u(e,t,n,r){var o=t&&t.prototype instanceof m?t:m,i=Object.create(o.prototype),a=new O(r||[]);return i._invoke=function(e,t,n){var r=l;return function(o,i){if(r===f)throw new Error("Generator is already running");if(r===h){if("throw"===o)throw i;return T()}for(n.method=o,n.arg=i;;){var a=n.delegate;if(a){var s=S(a,n);if(s){if(s===d)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(r===l)throw r=h,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r=f;var u=c(e,t,n);if("normal"===u.type){if(r=n.done?h:p,u.arg===d)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(r=h,n.method="throw",n.arg=u.arg)}}}(e,n,a),i}function c(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}e.wrap=u;var l="suspendedStart",p="suspendedYield",f="executing",h="completed",d={};function m(){}function v(){}function g(){}var y={};y[i]=function(){return this};var b=Object.getPrototypeOf,_=b&&b(b(A([])));_&&_!==n&&r.call(_,i)&&(y=_);var w=g.prototype=m.prototype=Object.create(y);function x(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function E(e){var t;this._invoke=function(n,o){function i(){return new Promise(function(t,i){!function t(n,o,i,a){var s=c(e[n],e,o);if("throw"!==s.type){var u=s.arg,l=u.value;return l&&"object"==typeof l&&r.call(l,"__await")?Promise.resolve(l.__await).then(function(e){t("next",e,i,a)},function(e){t("throw",e,i,a)}):Promise.resolve(l).then(function(e){u.value=e,i(u)},function(e){return t("throw",e,i,a)})}a(s.arg)}(n,o,t,i)})}return t=t?t.then(i,i):i()}}function S(e,n){var r=e.iterator[n.method];if(r===t){if(n.delegate=null,"throw"===n.method){if(e.iterator.return&&(n.method="return",n.arg=t,S(e,n),"throw"===n.method))return d;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return d}var o=c(r,e.iterator,n.arg);if("throw"===o.type)return n.method="throw",n.arg=o.arg,n.delegate=null,d;var i=o.arg;return i?i.done?(n[e.resultName]=i.value,n.next=e.nextLoc,"return"!==n.method&&(n.method="next",n.arg=t),n.delegate=null,d):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,d)}function C(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function k(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function O(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(C,this),this.reset(!0)}function A(e){if(e){var n=e[i];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,a=function n(){for(;++o<e.length;)if(r.call(e,o))return n.value=e[o],n.done=!1,n;return n.value=t,n.done=!0,n};return a.next=a}}return{next:T}}function T(){return{value:t,done:!0}}return v.prototype=w.constructor=g,g.constructor=v,g[s]=v.displayName="GeneratorFunction",e.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===v||"GeneratorFunction"===(t.displayName||t.name))},e.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,g):(e.__proto__=g,s in e||(e[s]="GeneratorFunction")),e.prototype=Object.create(w),e},e.awrap=function(e){return{__await:e}},x(E.prototype),E.prototype[a]=function(){return this},e.AsyncIterator=E,e.async=function(t,n,r,o){var i=new E(u(t,n,r,o));return e.isGeneratorFunction(n)?i:i.next().then(function(e){return e.done?e.value:i.next()})},x(w),w[s]="Generator",w[i]=function(){return this},w.toString=function(){return"[object Generator]"},e.keys=function(e){var t=[];for(var n in e)t.push(n);return t.reverse(),function n(){for(;t.length;){var r=t.pop();if(r in e)return n.value=r,n.done=!1,n}return n.done=!0,n}},e.values=A,O.prototype={constructor:O,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(k),!e)for(var n in this)"t"===n.charAt(0)&&r.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=t)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var n=this;function o(r,o){return s.type="throw",s.arg=e,n.next=r,o&&(n.method="next",n.arg=t),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=r.call(a,"catchLoc"),c=r.call(a,"finallyLoc");if(u&&c){if(this.prev<a.catchLoc)return o(a.catchLoc,!0);if(this.prev<a.finallyLoc)return o(a.finallyLoc)}else if(u){if(this.prev<a.catchLoc)return o(a.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return o(a.finallyLoc)}}}},abrupt:function(e,t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===e||"continue"===e)&&i.tryLoc<=t&&t<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=e,a.arg=t,i?(this.method="next",this.next=i.finallyLoc,d):this.complete(a)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),d},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),k(n),d}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;k(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,r){return this.delegate={iterator:A(e),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=t),d}},e}(e.exports);try{regeneratorRuntime=r}catch(e){Function("r","regeneratorRuntime = r")(r)}},function(e,t,n){"use strict";var r=n(768),o=n(787);function i(e){return function(){throw new Error("Function "+e+" is deprecated and cannot be used.")}}e.exports.Type=n(31),e.exports.Schema=n(110),e.exports.FAILSAFE_SCHEMA=n(238),e.exports.JSON_SCHEMA=n(409),e.exports.CORE_SCHEMA=n(408),e.exports.DEFAULT_SAFE_SCHEMA=n(136),e.exports.DEFAULT_FULL_SCHEMA=n(180),e.exports.load=r.load,e.exports.loadAll=r.loadAll,e.exports.safeLoad=r.safeLoad,e.exports.safeLoadAll=r.safeLoadAll,e.exports.dump=o.dump,e.exports.safeDump=o.safeDump,e.exports.YAMLException=n(135),e.exports.MINIMAL_SCHEMA=n(238),e.exports.SAFE_SCHEMA=n(136),e.exports.DEFAULT_SCHEMA=n(180),e.exports.scan=i("scan"),e.exports.parse=i("parse"),e.exports.compose=i("compose"),e.exports.addConstructor=i("addConstructor")},function(e,t,n){"use strict";var r=n(109),o=n(135),i=n(769),a=n(136),s=n(180),u=Object.prototype.hasOwnProperty,c=1,l=2,p=3,f=4,h=1,d=2,m=3,v=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,g=/[\x85\u2028\u2029]/,y=/[,\[\]\{\}]/,b=/^(?:!|!!|![a-z\-]+!)$/i,_=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function w(e){return Object.prototype.toString.call(e)}function x(e){return 10===e||13===e}function E(e){return 9===e||32===e}function S(e){return 9===e||32===e||10===e||13===e}function C(e){return 44===e||91===e||93===e||123===e||125===e}function k(e){var t;return 48<=e&&e<=57?e-48:97<=(t=32|e)&&t<=102?t-97+10:-1}function O(e){return 48===e?"\0":97===e?"":98===e?"\b":116===e?"\t":9===e?"\t":110===e?"\n":118===e?"\v":102===e?"\f":114===e?"\r":101===e?"":32===e?" ":34===e?'"':47===e?"/":92===e?"\\":78===e?"…":95===e?" ":76===e?"\u2028":80===e?"\u2029":""}function A(e){return e<=65535?String.fromCharCode(e):String.fromCharCode(55296+(e-65536>>10),56320+(e-65536&1023))}for(var T=new Array(256),j=new Array(256),P=0;P<256;P++)T[P]=O(P)?1:0,j[P]=O(P);function I(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||s,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function M(e,t){return new o(t,new i(e.filename,e.input,e.position,e.line,e.position-e.lineStart))}function N(e,t){throw M(e,t)}function R(e,t){e.onWarning&&e.onWarning.call(null,M(e,t))}var D={YAML:function(e,t,n){var r,o,i;null!==e.version&&N(e,"duplication of %YAML directive"),1!==n.length&&N(e,"YAML directive accepts exactly one argument"),null===(r=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&N(e,"ill-formed argument of the YAML directive"),o=parseInt(r[1],10),i=parseInt(r[2],10),1!==o&&N(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=i<2,1!==i&&2!==i&&R(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var r,o;2!==n.length&&N(e,"TAG directive accepts exactly two arguments"),r=n[0],o=n[1],b.test(r)||N(e,"ill-formed tag handle (first argument) of the TAG directive"),u.call(e.tagMap,r)&&N(e,'there is a previously declared suffix for "'+r+'" tag handle'),_.test(o)||N(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[r]=o}};function L(e,t,n,r){var o,i,a,s;if(t<n){if(s=e.input.slice(t,n),r)for(o=0,i=s.length;o<i;o+=1)9===(a=s.charCodeAt(o))||32<=a&&a<=1114111||N(e,"expected valid JSON character");else v.test(s)&&N(e,"the stream contains non-printable characters");e.result+=s}}function U(e,t,n,o){var i,a,s,c;for(r.isObject(n)||N(e,"cannot merge mappings; the provided source object is unacceptable"),s=0,c=(i=Object.keys(n)).length;s<c;s+=1)a=i[s],u.call(t,a)||(t[a]=n[a],o[a]=!0)}function q(e,t,n,r,o,i,a,s){var c,l;if(Array.isArray(o))for(c=0,l=(o=Array.prototype.slice.call(o)).length;c<l;c+=1)Array.isArray(o[c])&&N(e,"nested arrays are not supported inside keys"),"object"==typeof o&&"[object Object]"===w(o[c])&&(o[c]="[object Object]");if("object"==typeof o&&"[object Object]"===w(o)&&(o="[object Object]"),o=String(o),null===t&&(t={}),"tag:yaml.org,2002:merge"===r)if(Array.isArray(i))for(c=0,l=i.length;c<l;c+=1)U(e,t,i[c],n);else U(e,t,i,n);else e.json||u.call(n,o)||!u.call(t,o)||(e.line=a||e.line,e.position=s||e.position,N(e,"duplicated mapping key")),t[o]=i,delete n[o];return t}function F(e){var t;10===(t=e.input.charCodeAt(e.position))?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):N(e,"a line break is expected"),e.line+=1,e.lineStart=e.position}function z(e,t,n){for(var r=0,o=e.input.charCodeAt(e.position);0!==o;){for(;E(o);)o=e.input.charCodeAt(++e.position);if(t&&35===o)do{o=e.input.charCodeAt(++e.position)}while(10!==o&&13!==o&&0!==o);if(!x(o))break;for(F(e),o=e.input.charCodeAt(e.position),r++,e.lineIndent=0;32===o;)e.lineIndent++,o=e.input.charCodeAt(++e.position)}return-1!==n&&0!==r&&e.lineIndent<n&&R(e,"deficient indentation"),r}function B(e){var t,n=e.position;return!(45!==(t=e.input.charCodeAt(n))&&46!==t||t!==e.input.charCodeAt(n+1)||t!==e.input.charCodeAt(n+2)||(n+=3,0!==(t=e.input.charCodeAt(n))&&!S(t)))}function V(e,t){1===t?e.result+=" ":t>1&&(e.result+=r.repeat("\n",t-1))}function H(e,t){var n,r,o=e.tag,i=e.anchor,a=[],s=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),r=e.input.charCodeAt(e.position);0!==r&&45===r&&S(e.input.charCodeAt(e.position+1));)if(s=!0,e.position++,z(e,!0,-1)&&e.lineIndent<=t)a.push(null),r=e.input.charCodeAt(e.position);else if(n=e.line,Y(e,t,p,!1,!0),a.push(e.result),z(e,!0,-1),r=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==r)N(e,"bad indentation of a sequence entry");else if(e.lineIndent<t)break;return!!s&&(e.tag=o,e.anchor=i,e.kind="sequence",e.result=a,!0)}function W(e){var t,n,r,o,i=!1,a=!1;if(33!==(o=e.input.charCodeAt(e.position)))return!1;if(null!==e.tag&&N(e,"duplication of a tag property"),60===(o=e.input.charCodeAt(++e.position))?(i=!0,o=e.input.charCodeAt(++e.position)):33===o?(a=!0,n="!!",o=e.input.charCodeAt(++e.position)):n="!",t=e.position,i){do{o=e.input.charCodeAt(++e.position)}while(0!==o&&62!==o);e.position<e.length?(r=e.input.slice(t,e.position),o=e.input.charCodeAt(++e.position)):N(e,"unexpected end of the stream within a verbatim tag")}else{for(;0!==o&&!S(o);)33===o&&(a?N(e,"tag suffix cannot contain exclamation marks"):(n=e.input.slice(t-1,e.position+1),b.test(n)||N(e,"named tag handle cannot contain such characters"),a=!0,t=e.position+1)),o=e.input.charCodeAt(++e.position);r=e.input.slice(t,e.position),y.test(r)&&N(e,"tag suffix cannot contain flow indicator characters")}return r&&!_.test(r)&&N(e,"tag name cannot contain such characters: "+r),i?e.tag=r:u.call(e.tagMap,n)?e.tag=e.tagMap[n]+r:"!"===n?e.tag="!"+r:"!!"===n?e.tag="tag:yaml.org,2002:"+r:N(e,'undeclared tag handle "'+n+'"'),!0}function J(e){var t,n;if(38!==(n=e.input.charCodeAt(e.position)))return!1;for(null!==e.anchor&&N(e,"duplication of an anchor property"),n=e.input.charCodeAt(++e.position),t=e.position;0!==n&&!S(n)&&!C(n);)n=e.input.charCodeAt(++e.position);return e.position===t&&N(e,"name of an anchor node must contain at least one character"),e.anchor=e.input.slice(t,e.position),!0}function Y(e,t,n,o,i){var a,s,v,g,y,b,_,w,O=1,P=!1,I=!1;if(null!==e.listener&&e.listener("open",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,a=s=v=f===n||p===n,o&&z(e,!0,-1)&&(P=!0,e.lineIndent>t?O=1:e.lineIndent===t?O=0:e.lineIndent<t&&(O=-1)),1===O)for(;W(e)||J(e);)z(e,!0,-1)?(P=!0,v=a,e.lineIndent>t?O=1:e.lineIndent===t?O=0:e.lineIndent<t&&(O=-1)):v=!1;if(v&&(v=P||i),1!==O&&f!==n||(_=c===n||l===n?t:t+1,w=e.position-e.lineStart,1===O?v&&(H(e,w)||function(e,t,n){var r,o,i,a,s,u=e.tag,c=e.anchor,p={},h={},d=null,m=null,v=null,g=!1,y=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=p),s=e.input.charCodeAt(e.position);0!==s;){if(r=e.input.charCodeAt(e.position+1),i=e.line,a=e.position,63!==s&&58!==s||!S(r)){if(!Y(e,n,l,!1,!0))break;if(e.line===i){for(s=e.input.charCodeAt(e.position);E(s);)s=e.input.charCodeAt(++e.position);if(58===s)S(s=e.input.charCodeAt(++e.position))||N(e,"a whitespace character is expected after the key-value separator within a block mapping"),g&&(q(e,p,h,d,m,null),d=m=v=null),y=!0,g=!1,o=!1,d=e.tag,m=e.result;else{if(!y)return e.tag=u,e.anchor=c,!0;N(e,"can not read an implicit mapping pair; a colon is missed")}}else{if(!y)return e.tag=u,e.anchor=c,!0;N(e,"can not read a block mapping entry; a multiline key may not be an implicit key")}}else 63===s?(g&&(q(e,p,h,d,m,null),d=m=v=null),y=!0,g=!0,o=!0):g?(g=!1,o=!0):N(e,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),e.position+=1,s=r;if((e.line===i||e.lineIndent>t)&&(Y(e,t,f,!0,o)&&(g?m=e.result:v=e.result),g||(q(e,p,h,d,m,v,i,a),d=m=v=null),z(e,!0,-1),s=e.input.charCodeAt(e.position)),e.lineIndent>t&&0!==s)N(e,"bad indentation of a mapping entry");else if(e.lineIndent<t)break}return g&&q(e,p,h,d,m,null),y&&(e.tag=u,e.anchor=c,e.kind="mapping",e.result=p),y}(e,w,_))||function(e,t){var n,r,o,i,a,s,u,l,p,f,h=!0,d=e.tag,m=e.anchor,v={};if(91===(f=e.input.charCodeAt(e.position)))o=93,s=!1,r=[];else{if(123!==f)return!1;o=125,s=!0,r={}}for(null!==e.anchor&&(e.anchorMap[e.anchor]=r),f=e.input.charCodeAt(++e.position);0!==f;){if(z(e,!0,t),(f=e.input.charCodeAt(e.position))===o)return e.position++,e.tag=d,e.anchor=m,e.kind=s?"mapping":"sequence",e.result=r,!0;h||N(e,"missed comma between flow collection entries"),p=null,i=a=!1,63===f&&S(e.input.charCodeAt(e.position+1))&&(i=a=!0,e.position++,z(e,!0,t)),n=e.line,Y(e,t,c,!1,!0),l=e.tag,u=e.result,z(e,!0,t),f=e.input.charCodeAt(e.position),!a&&e.line!==n||58!==f||(i=!0,f=e.input.charCodeAt(++e.position),z(e,!0,t),Y(e,t,c,!1,!0),p=e.result),s?q(e,r,v,l,u,p):i?r.push(q(e,null,v,l,u,p)):r.push(u),z(e,!0,t),44===(f=e.input.charCodeAt(e.position))?(h=!0,f=e.input.charCodeAt(++e.position)):h=!1}N(e,"unexpected end of the stream within a flow collection")}(e,_)?I=!0:(s&&function(e,t){var n,o,i,a,s,u=h,c=!1,l=!1,p=t,f=0,v=!1;if(124===(a=e.input.charCodeAt(e.position)))o=!1;else{if(62!==a)return!1;o=!0}for(e.kind="scalar",e.result="";0!==a;)if(43===(a=e.input.charCodeAt(++e.position))||45===a)h===u?u=43===a?m:d:N(e,"repeat of a chomping mode identifier");else{if(!((i=48<=(s=a)&&s<=57?s-48:-1)>=0))break;0===i?N(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):l?N(e,"repeat of an indentation width identifier"):(p=t+i-1,l=!0)}if(E(a)){do{a=e.input.charCodeAt(++e.position)}while(E(a));if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!x(a)&&0!==a)}for(;0!==a;){for(F(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!l||e.lineIndent<p)&&32===a;)e.lineIndent++,a=e.input.charCodeAt(++e.position);if(!l&&e.lineIndent>p&&(p=e.lineIndent),x(a))f++;else{if(e.lineIndent<p){u===m?e.result+=r.repeat("\n",c?1+f:f):u===h&&c&&(e.result+="\n");break}for(o?E(a)?(v=!0,e.result+=r.repeat("\n",c?1+f:f)):v?(v=!1,e.result+=r.repeat("\n",f+1)):0===f?c&&(e.result+=" "):e.result+=r.repeat("\n",f):e.result+=r.repeat("\n",c?1+f:f),c=!0,l=!0,f=0,n=e.position;!x(a)&&0!==a;)a=e.input.charCodeAt(++e.position);L(e,n,e.position,!1)}}return!0}(e,_)||function(e,t){var n,r,o;if(39!==(n=e.input.charCodeAt(e.position)))return!1;for(e.kind="scalar",e.result="",e.position++,r=o=e.position;0!==(n=e.input.charCodeAt(e.position));)if(39===n){if(L(e,r,e.position,!0),39!==(n=e.input.charCodeAt(++e.position)))return!0;r=e.position,e.position++,o=e.position}else x(n)?(L(e,r,o,!0),V(e,z(e,!1,t)),r=o=e.position):e.position===e.lineStart&&B(e)?N(e,"unexpected end of the document within a single quoted scalar"):(e.position++,o=e.position);N(e,"unexpected end of the stream within a single quoted scalar")}(e,_)||function(e,t){var n,r,o,i,a,s,u;if(34!==(s=e.input.charCodeAt(e.position)))return!1;for(e.kind="scalar",e.result="",e.position++,n=r=e.position;0!==(s=e.input.charCodeAt(e.position));){if(34===s)return L(e,n,e.position,!0),e.position++,!0;if(92===s){if(L(e,n,e.position,!0),x(s=e.input.charCodeAt(++e.position)))z(e,!1,t);else if(s<256&&T[s])e.result+=j[s],e.position++;else if((a=120===(u=s)?2:117===u?4:85===u?8:0)>0){for(o=a,i=0;o>0;o--)(a=k(s=e.input.charCodeAt(++e.position)))>=0?i=(i<<4)+a:N(e,"expected hexadecimal character");e.result+=A(i),e.position++}else N(e,"unknown escape sequence");n=r=e.position}else x(s)?(L(e,n,r,!0),V(e,z(e,!1,t)),n=r=e.position):e.position===e.lineStart&&B(e)?N(e,"unexpected end of the document within a double quoted scalar"):(e.position++,r=e.position)}N(e,"unexpected end of the stream within a double quoted scalar")}(e,_)?I=!0:!function(e){var t,n,r;if(42!==(r=e.input.charCodeAt(e.position)))return!1;for(r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!S(r)&&!C(r);)r=e.input.charCodeAt(++e.position);return e.position===t&&N(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),e.anchorMap.hasOwnProperty(n)||N(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],z(e,!0,-1),!0}(e)?function(e,t,n){var r,o,i,a,s,u,c,l,p=e.kind,f=e.result;if(S(l=e.input.charCodeAt(e.position))||C(l)||35===l||38===l||42===l||33===l||124===l||62===l||39===l||34===l||37===l||64===l||96===l)return!1;if((63===l||45===l)&&(S(r=e.input.charCodeAt(e.position+1))||n&&C(r)))return!1;for(e.kind="scalar",e.result="",o=i=e.position,a=!1;0!==l;){if(58===l){if(S(r=e.input.charCodeAt(e.position+1))||n&&C(r))break}else if(35===l){if(S(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&B(e)||n&&C(l))break;if(x(l)){if(s=e.line,u=e.lineStart,c=e.lineIndent,z(e,!1,-1),e.lineIndent>=t){a=!0,l=e.input.charCodeAt(e.position);continue}e.position=i,e.line=s,e.lineStart=u,e.lineIndent=c;break}}a&&(L(e,o,i,!1),V(e,e.line-s),o=i=e.position,a=!1),E(l)||(i=e.position+1),l=e.input.charCodeAt(++e.position)}return L(e,o,i,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,_,c===n)&&(I=!0,null===e.tag&&(e.tag="?")):(I=!0,null===e.tag&&null===e.anchor||N(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===O&&(I=v&&H(e,w))),null!==e.tag&&"!"!==e.tag)if("?"===e.tag){for(g=0,y=e.implicitTypes.length;g<y;g+=1)if((b=e.implicitTypes[g]).resolve(e.result)){e.result=b.construct(e.result),e.tag=b.tag,null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);break}}else u.call(e.typeMap[e.kind||"fallback"],e.tag)?(b=e.typeMap[e.kind||"fallback"][e.tag],null!==e.result&&b.kind!==e.kind&&N(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+b.kind+'", not "'+e.kind+'"'),b.resolve(e.result)?(e.result=b.construct(e.result),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):N(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")):N(e,"unknown tag !<"+e.tag+">");return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||I}function K(e){var t,n,r,o,i=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};0!==(o=e.input.charCodeAt(e.position))&&(z(e,!0,-1),o=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==o));){for(a=!0,o=e.input.charCodeAt(++e.position),t=e.position;0!==o&&!S(o);)o=e.input.charCodeAt(++e.position);for(r=[],(n=e.input.slice(t,e.position)).length<1&&N(e,"directive name must not be less than one character in length");0!==o;){for(;E(o);)o=e.input.charCodeAt(++e.position);if(35===o){do{o=e.input.charCodeAt(++e.position)}while(0!==o&&!x(o));break}if(x(o))break;for(t=e.position;0!==o&&!S(o);)o=e.input.charCodeAt(++e.position);r.push(e.input.slice(t,e.position))}0!==o&&F(e),u.call(D,n)?D[n](e,n,r):R(e,'unknown document directive "'+n+'"')}z(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,z(e,!0,-1)):a&&N(e,"directives end mark is expected"),Y(e,e.lineIndent-1,f,!1,!0),z(e,!0,-1),e.checkLineBreaks&&g.test(e.input.slice(i,e.position))&&R(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&B(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,z(e,!0,-1)):e.position<e.length-1&&N(e,"end of the stream or a document separator is expected")}function G(e,t){t=t||{},0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0)&&(e=e.slice(1)));var n=new I(e,t);for(n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)K(n);return n.documents}function $(e,t,n){var r,o,i=G(e,n);if("function"!=typeof t)return i;for(r=0,o=i.length;r<o;r+=1)t(i[r])}function Z(e,t){var n=G(e,t);if(0!==n.length){if(1===n.length)return n[0];throw new o("expected a single document in the stream, but found more")}}e.exports.loadAll=$,e.exports.load=Z,e.exports.safeLoadAll=function(e,t,n){if("function"!=typeof t)return $(e,r.extend({schema:a},n));$(e,t,r.extend({schema:a},n))},e.exports.safeLoad=function(e,t){return Z(e,r.extend({schema:a},t))}},function(e,t,n){"use strict";var r=n(109);function o(e,t,n,r,o){this.name=e,this.buffer=t,this.position=n,this.line=r,this.column=o}o.prototype.getSnippet=function(e,t){var n,o,i,a,s;if(!this.buffer)return null;for(e=e||4,t=t||75,n="",o=this.position;o>0&&-1==="\0\r\n…\u2028\u2029".indexOf(this.buffer.charAt(o-1));)if(o-=1,this.position-o>t/2-1){n=" ... ",o+=5;break}for(i="",a=this.position;a<this.buffer.length&&-1==="\0\r\n…\u2028\u2029".indexOf(this.buffer.charAt(a));)if((a+=1)-this.position>t/2-1){i=" ... ",a-=5;break}return s=this.buffer.slice(o,a),r.repeat(" ",e)+n+s+i+"\n"+r.repeat(" ",e+this.position-o+n.length)+"^"},o.prototype.toString=function(e){var t,n="";return this.name&&(n+='in "'+this.name+'" '),n+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet())&&(n+=":\n"+t),n},e.exports=o},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return null!==e?e:""}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return null!==e?e:[]}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:null",{kind:"scalar",resolve:function(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)},construct:function(){return null},predicate:function(e){return null===e},represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:bool",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)},construct:function(e){return"true"===e||"True"===e||"TRUE"===e},predicate:function(e){return"[object Boolean]"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})},function(e,t,n){"use strict";var r=n(109),o=n(31);function i(e){return 48<=e&&e<=55}function a(e){return 48<=e&&e<=57}e.exports=new o("tag:yaml.org,2002:int",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,r=e.length,o=0,s=!1;if(!r)return!1;if("-"!==(t=e[o])&&"+"!==t||(t=e[++o]),"0"===t){if(o+1===r)return!0;if("b"===(t=e[++o])){for(o++;o<r;o++)if("_"!==(t=e[o])){if("0"!==t&&"1"!==t)return!1;s=!0}return s&&"_"!==t}if("x"===t){for(o++;o<r;o++)if("_"!==(t=e[o])){if(!(48<=(n=e.charCodeAt(o))&&n<=57||65<=n&&n<=70||97<=n&&n<=102))return!1;s=!0}return s&&"_"!==t}for(;o<r;o++)if("_"!==(t=e[o])){if(!i(e.charCodeAt(o)))return!1;s=!0}return s&&"_"!==t}if("_"===t)return!1;for(;o<r;o++)if("_"!==(t=e[o])){if(":"===t)break;if(!a(e.charCodeAt(o)))return!1;s=!0}return!(!s||"_"===t)&&(":"!==t||/^(:[0-5]?[0-9])+$/.test(e.slice(o)))},construct:function(e){var t,n,r=e,o=1,i=[];return-1!==r.indexOf("_")&&(r=r.replace(/_/g,"")),"-"!==(t=r[0])&&"+"!==t||("-"===t&&(o=-1),t=(r=r.slice(1))[0]),"0"===r?0:"0"===t?"b"===r[1]?o*parseInt(r.slice(2),2):"x"===r[1]?o*parseInt(r,16):o*parseInt(r,8):-1!==r.indexOf(":")?(r.split(":").forEach(function(e){i.unshift(parseInt(e,10))}),r=0,n=1,i.forEach(function(e){r+=e*n,n*=60}),o*r):o*parseInt(r,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&e%1==0&&!r.isNegativeZero(e)},represent:{binary:function(e){return e>=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0"+e.toString(8):"-0"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})},function(e,t,n){"use strict";var r=n(109),o=n(31),i=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var a=/^[-+]?[0-9]+e/;e.exports=new o("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!i.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n,r,o;return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,o=[],"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:t.indexOf(":")>=0?(t.split(":").forEach(function(e){o.unshift(parseFloat(e,10))}),t=0,r=1,o.forEach(function(e){t+=e*r,r*=60}),n*t):n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||r.isNegativeZero(e))},represent:function(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(r.isNegativeZero(e))return"-0.0";return n=e.toString(10),a.test(n)?n.replace("e",".e"):n},defaultStyle:"lowercase"})},function(e,t,n){"use strict";var r=n(31),o=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),i=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");e.exports=new r("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==o.exec(e)||null!==i.exec(e))},construct:function(e){var t,n,r,a,s,u,c,l,p=0,f=null;if(null===(t=o.exec(e))&&(t=i.exec(e)),null===t)throw new Error("Date resolve error");if(n=+t[1],r=+t[2]-1,a=+t[3],!t[4])return new Date(Date.UTC(n,r,a));if(s=+t[4],u=+t[5],c=+t[6],t[7]){for(p=t[7].slice(0,3);p.length<3;)p+="0";p=+p}return t[9]&&(f=6e4*(60*+t[10]+ +(t[11]||0)),"-"===t[9]&&(f=-f)),l=new Date(Date.UTC(n,r,a,s,u,c,p)),f&&l.setTime(l.getTime()-f),l},instanceOf:Date,represent:function(e){return e.toISOString()}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}})},function(e,t,n){"use strict";var r;try{r=n(61).Buffer}catch(e){}var o=n(31),i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";e.exports=new o("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,r=0,o=e.length,a=i;for(n=0;n<o;n++)if(!((t=a.indexOf(e.charAt(n)))>64)){if(t<0)return!1;r+=6}return r%8==0},construct:function(e){var t,n,o=e.replace(/[\r\n=]/g,""),a=o.length,s=i,u=0,c=[];for(t=0;t<a;t++)t%4==0&&t&&(c.push(u>>16&255),c.push(u>>8&255),c.push(255&u)),u=u<<6|s.indexOf(o.charAt(t));return 0==(n=a%4*6)?(c.push(u>>16&255),c.push(u>>8&255),c.push(255&u)):18===n?(c.push(u>>10&255),c.push(u>>2&255)):12===n&&c.push(u>>4&255),r?r.from?r.from(c):new r(c):c},predicate:function(e){return r&&r.isBuffer(e)},represent:function(e){var t,n,r="",o=0,a=e.length,s=i;for(t=0;t<a;t++)t%3==0&&t&&(r+=s[o>>18&63],r+=s[o>>12&63],r+=s[o>>6&63],r+=s[63&o]),o=(o<<8)+e[t];return 0==(n=a%3)?(r+=s[o>>18&63],r+=s[o>>12&63],r+=s[o>>6&63],r+=s[63&o]):2===n?(r+=s[o>>10&63],r+=s[o>>4&63],r+=s[o<<2&63],r+=s[64]):1===n&&(r+=s[o>>2&63],r+=s[o<<4&63],r+=s[64],r+=s[64]),r}})},function(e,t,n){"use strict";var r=n(31),o=Object.prototype.hasOwnProperty,i=Object.prototype.toString;e.exports=new r("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,r,a,s,u=[],c=e;for(t=0,n=c.length;t<n;t+=1){if(r=c[t],s=!1,"[object Object]"!==i.call(r))return!1;for(a in r)if(o.call(r,a)){if(s)return!1;s=!0}if(!s)return!1;if(-1!==u.indexOf(a))return!1;u.push(a)}return!0},construct:function(e){return null!==e?e:[]}})},function(e,t,n){"use strict";var r=n(31),o=Object.prototype.toString;e.exports=new r("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,r,i,a,s=e;for(a=new Array(s.length),t=0,n=s.length;t<n;t+=1){if(r=s[t],"[object Object]"!==o.call(r))return!1;if(1!==(i=Object.keys(r)).length)return!1;a[t]=[i[0],r[i[0]]]}return!0},construct:function(e){if(null===e)return[];var t,n,r,o,i,a=e;for(i=new Array(a.length),t=0,n=a.length;t<n;t+=1)r=a[t],o=Object.keys(r),i[t]=[o[0],r[o[0]]];return i}})},function(e,t,n){"use strict";var r=n(31),o=Object.prototype.hasOwnProperty;e.exports=new r("tag:yaml.org,2002:set",{kind:"mapping",resolve:function(e){if(null===e)return!0;var t,n=e;for(t in n)if(o.call(n,t)&&null!==n[t])return!1;return!0},construct:function(e){return null!==e?e:{}}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:function(){return!0},construct:function(){},predicate:function(e){return void 0===e},represent:function(){return""}})},function(e,t,n){"use strict";var r=n(31);e.exports=new r("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:function(e){if(null===e)return!1;if(0===e.length)return!1;var t=e,n=/\/([gim]*)$/.exec(e),r="";if("/"===t[0]){if(n&&(r=n[1]),r.length>3)return!1;if("/"!==t[t.length-r.length-1])return!1}return!0},construct:function(e){var t=e,n=/\/([gim]*)$/.exec(e),r="";return"/"===t[0]&&(n&&(r=n[1]),t=t.slice(1,t.length-r.length-1)),new RegExp(t,r)},predicate:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},represent:function(e){var t="/"+e.source+"/";return e.global&&(t+="g"),e.multiline&&(t+="m"),e.ignoreCase&&(t+="i"),t}})},function(e,t,n){"use strict";var r;try{r=n(786)}catch(e){"undefined"!=typeof window&&(r=window.esprima)}var o=n(31);e.exports=new o("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:function(e){if(null===e)return!1;try{var t="("+e+")",n=r.parse(t,{range:!0});return"Program"===n.type&&1===n.body.length&&"ExpressionStatement"===n.body[0].type&&("ArrowFunctionExpression"===n.body[0].expression.type||"FunctionExpression"===n.body[0].expression.type)}catch(e){return!1}},construct:function(e){var t,n="("+e+")",o=r.parse(n,{range:!0}),i=[];if("Program"!==o.type||1!==o.body.length||"ExpressionStatement"!==o.body[0].type||"ArrowFunctionExpression"!==o.body[0].expression.type&&"FunctionExpression"!==o.body[0].expression.type)throw new Error("Failed to resolve function");return o.body[0].expression.params.forEach(function(e){i.push(e.name)}),t=o.body[0].expression.body.range,"BlockStatement"===o.body[0].expression.body.type?new Function(i,n.slice(t[0]+1,t[1]-1)):new Function(i,"return "+n.slice(t[0],t[1]))},predicate:function(e){return"[object Function]"===Object.prototype.toString.call(e)},represent:function(e){return e.toString()}})},function(t,n){if(void 0===e){var r=new Error("Cannot find module 'esprima'");throw r.code="MODULE_NOT_FOUND",r}t.exports=e},function(e,t,n){"use strict";var r=n(109),o=n(135),i=n(180),a=n(136),s=Object.prototype.toString,u=Object.prototype.hasOwnProperty,c=9,l=10,p=32,f=33,h=34,d=35,m=37,v=38,g=39,y=42,b=44,_=45,w=58,x=62,E=63,S=64,C=91,k=93,O=96,A=123,T=124,j=125,P={0:"\\0",7:"\\a",8:"\\b",9:"\\t",10:"\\n",11:"\\v",12:"\\f",13:"\\r",27:"\\e",34:'\\"',92:"\\\\",133:"\\N",160:"\\_",8232:"\\L",8233:"\\P"},I=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function M(e){var t,n,i;if(t=e.toString(16).toUpperCase(),e<=255)n="x",i=2;else if(e<=65535)n="u",i=4;else{if(!(e<=4294967295))throw new o("code point within a string may not be greater than 0xFFFFFFFF");n="U",i=8}return"\\"+n+r.repeat("0",i-t.length)+t}function N(e){this.schema=e.schema||i,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=r.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=function(e,t){var n,r,o,i,a,s,c;if(null===t)return{};for(n={},o=0,i=(r=Object.keys(t)).length;o<i;o+=1)a=r[o],s=String(t[a]),"!!"===a.slice(0,2)&&(a="tag:yaml.org,2002:"+a.slice(2)),(c=e.compiledTypeMap.fallback[a])&&u.call(c.styleAliases,s)&&(s=c.styleAliases[s]),n[a]=s;return n}(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function R(e,t){for(var n,o=r.repeat(" ",t),i=0,a=-1,s="",u=e.length;i<u;)-1===(a=e.indexOf("\n",i))?(n=e.slice(i),i=u):(n=e.slice(i,a+1),i=a+1),n.length&&"\n"!==n&&(s+=o),s+=n;return s}function D(e,t){return"\n"+r.repeat(" ",e.indent*t)}function L(e){return e===p||e===c}function U(e){return 32<=e&&e<=126||161<=e&&e<=55295&&8232!==e&&8233!==e||57344<=e&&e<=65533&&65279!==e||65536<=e&&e<=1114111}function q(e){return U(e)&&65279!==e&&e!==b&&e!==C&&e!==k&&e!==A&&e!==j&&e!==w&&e!==d}function F(e){return/^\n* /.test(e)}var z=1,B=2,V=3,H=4,W=5;function J(e,t,n,r,o){var i,a,s,u=!1,c=!1,p=-1!==r,P=-1,I=U(s=e.charCodeAt(0))&&65279!==s&&!L(s)&&s!==_&&s!==E&&s!==w&&s!==b&&s!==C&&s!==k&&s!==A&&s!==j&&s!==d&&s!==v&&s!==y&&s!==f&&s!==T&&s!==x&&s!==g&&s!==h&&s!==m&&s!==S&&s!==O&&!L(e.charCodeAt(e.length-1));if(t)for(i=0;i<e.length;i++){if(!U(a=e.charCodeAt(i)))return W;I=I&&q(a)}else{for(i=0;i<e.length;i++){if((a=e.charCodeAt(i))===l)u=!0,p&&(c=c||i-P-1>r&&" "!==e[P+1],P=i);else if(!U(a))return W;I=I&&q(a)}c=c||p&&i-P-1>r&&" "!==e[P+1]}return u||c?n>9&&F(e)?W:c?H:V:I&&!o(e)?z:B}function Y(e,t,n,r){e.dump=function(){if(0===t.length)return"''";if(!e.noCompatMode&&-1!==I.indexOf(t))return"'"+t+"'";var i=e.indent*Math.max(1,n),a=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-i),s=r||e.flowLevel>-1&&n>=e.flowLevel;switch(J(t,s,e.indent,a,function(t){return function(e,t){var n,r;for(n=0,r=e.implicitTypes.length;n<r;n+=1)if(e.implicitTypes[n].resolve(t))return!0;return!1}(e,t)})){case z:return t;case B:return"'"+t.replace(/'/g,"''")+"'";case V:return"|"+K(t,e.indent)+G(R(t,i));case H:return">"+K(t,e.indent)+G(R(function(e,t){var n,r,o=/(\n+)([^\n]*)/g,i=(s=e.indexOf("\n"),s=-1!==s?s:e.length,o.lastIndex=s,$(e.slice(0,s),t)),a="\n"===e[0]||" "===e[0];var s;for(;r=o.exec(e);){var u=r[1],c=r[2];n=" "===c[0],i+=u+(a||n||""===c?"":"\n")+$(c,t),a=n}return i}(t,a),i));case W:return'"'+function(e){for(var t,n,r,o="",i=0;i<e.length;i++)(t=e.charCodeAt(i))>=55296&&t<=56319&&(n=e.charCodeAt(i+1))>=56320&&n<=57343?(o+=M(1024*(t-55296)+n-56320+65536),i++):(r=P[t],o+=!r&&U(t)?e[i]:r||M(t));return o}(t)+'"';default:throw new o("impossible error: invalid scalar style")}}()}function K(e,t){var n=F(e)?String(t):"",r="\n"===e[e.length-1];return n+(r&&("\n"===e[e.length-2]||"\n"===e)?"+":r?"":"-")+"\n"}function G(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function $(e,t){if(""===e||" "===e[0])return e;for(var n,r,o=/ [^ ]/g,i=0,a=0,s=0,u="";n=o.exec(e);)(s=n.index)-i>t&&(r=a>i?a:s,u+="\n"+e.slice(i,r),i=r+1),a=s;return u+="\n",e.length-i>t&&a>i?u+=e.slice(i,a)+"\n"+e.slice(a+1):u+=e.slice(i),u.slice(1)}function Z(e,t,n){var r,i,a,c,l,p;for(a=0,c=(i=n?e.explicitTypes:e.implicitTypes).length;a<c;a+=1)if(((l=i[a]).instanceOf||l.predicate)&&(!l.instanceOf||"object"==typeof t&&t instanceof l.instanceOf)&&(!l.predicate||l.predicate(t))){if(e.tag=n?l.tag:"?",l.represent){if(p=e.styleMap[l.tag]||l.defaultStyle,"[object Function]"===s.call(l.represent))r=l.represent(t,p);else{if(!u.call(l.represent,p))throw new o("!<"+l.tag+'> tag resolver accepts not "'+p+'" style');r=l.represent[p](t,p)}e.dump=r}return!0}return!1}function X(e,t,n,r,i,a){e.tag=null,e.dump=n,Z(e,n,!1)||Z(e,n,!0);var u=s.call(e.dump);r&&(r=e.flowLevel<0||e.flowLevel>t);var c,p,f="[object Object]"===u||"[object Array]"===u;if(f&&(p=-1!==(c=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||p||2!==e.indent&&t>0)&&(i=!1),p&&e.usedDuplicates[c])e.dump="*ref_"+c;else{if(f&&p&&!e.usedDuplicates[c]&&(e.usedDuplicates[c]=!0),"[object Object]"===u)r&&0!==Object.keys(e.dump).length?(!function(e,t,n,r){var i,a,s,u,c,p,f="",h=e.tag,d=Object.keys(n);if(!0===e.sortKeys)d.sort();else if("function"==typeof e.sortKeys)d.sort(e.sortKeys);else if(e.sortKeys)throw new o("sortKeys must be a boolean or a function");for(i=0,a=d.length;i<a;i+=1)p="",r&&0===i||(p+=D(e,t)),u=n[s=d[i]],X(e,t+1,s,!0,!0,!0)&&((c=null!==e.tag&&"?"!==e.tag||e.dump&&e.dump.length>1024)&&(e.dump&&l===e.dump.charCodeAt(0)?p+="?":p+="? "),p+=e.dump,c&&(p+=D(e,t)),X(e,t+1,u,!0,c)&&(e.dump&&l===e.dump.charCodeAt(0)?p+=":":p+=": ",f+=p+=e.dump));e.tag=h,e.dump=f||"{}"}(e,t,e.dump,i),p&&(e.dump="&ref_"+c+e.dump)):(!function(e,t,n){var r,o,i,a,s,u="",c=e.tag,l=Object.keys(n);for(r=0,o=l.length;r<o;r+=1)s=e.condenseFlow?'"':"",0!==r&&(s+=", "),a=n[i=l[r]],X(e,t,i,!1,!1)&&(e.dump.length>1024&&(s+="? "),s+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),X(e,t,a,!1,!1)&&(u+=s+=e.dump));e.tag=c,e.dump="{"+u+"}"}(e,t,e.dump),p&&(e.dump="&ref_"+c+" "+e.dump));else if("[object Array]"===u){var h=e.noArrayIndent&&t>0?t-1:t;r&&0!==e.dump.length?(!function(e,t,n,r){var o,i,a="",s=e.tag;for(o=0,i=n.length;o<i;o+=1)X(e,t+1,n[o],!0,!0)&&(r&&0===o||(a+=D(e,t)),e.dump&&l===e.dump.charCodeAt(0)?a+="-":a+="- ",a+=e.dump);e.tag=s,e.dump=a||"[]"}(e,h,e.dump,i),p&&(e.dump="&ref_"+c+e.dump)):(!function(e,t,n){var r,o,i="",a=e.tag;for(r=0,o=n.length;r<o;r+=1)X(e,t,n[r],!1,!1)&&(0!==r&&(i+=","+(e.condenseFlow?"":" ")),i+=e.dump);e.tag=a,e.dump="["+i+"]"}(e,h,e.dump),p&&(e.dump="&ref_"+c+" "+e.dump))}else{if("[object String]"!==u){if(e.skipInvalid)return!1;throw new o("unacceptable kind of an object to dump "+u)}"?"!==e.tag&&Y(e,e.dump,t,a)}null!==e.tag&&"?"!==e.tag&&(e.dump="!<"+e.tag+"> "+e.dump)}return!0}function Q(e,t){var n,r,o=[],i=[];for(function e(t,n,r){var o,i,a;if(null!==t&&"object"==typeof t)if(-1!==(i=n.indexOf(t)))-1===r.indexOf(i)&&r.push(i);else if(n.push(t),Array.isArray(t))for(i=0,a=t.length;i<a;i+=1)e(t[i],n,r);else for(o=Object.keys(t),i=0,a=o.length;i<a;i+=1)e(t[o[i]],n,r)}(e,o,i),n=0,r=i.length;n<r;n+=1)t.duplicates.push(o[i[n]]);t.usedDuplicates=new Array(r)}function ee(e,t){var n=new N(t=t||{});return n.noRefs||Q(e,n),X(n,0,e,!0,!0)?n.dump+"\n":""}e.exports.dump=ee,e.exports.safeDump=function(e,t){return ee(e,r.extend({schema:a},t))}},function(e,t,n){"use strict";e.exports=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}},function(e,t,n){"use strict";var r,o=Object.prototype.hasOwnProperty;function i(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch(e){return null}}t.stringify=function(e,t){t=t||"";var n,i,a=[];for(i in"string"!=typeof t&&(t="?"),e)if(o.call(e,i)){if((n=e[i])||null!==n&&n!==r&&!isNaN(n)||(n=""),i=encodeURIComponent(i),n=encodeURIComponent(n),null===i||null===n)continue;a.push(i+"="+n)}return a.length?t+a.join("&"):""},t.parse=function(e){for(var t,n=/([^=?&]+)=?([^&]*)/g,r={};t=n.exec(e);){var o=i(t[1]),a=i(t[2]);null===o||null===a||o in r||(r[o]=a)}return r}},function(e,t,n){var r=n(48);e.exports=function(){return r.Date.now()}},function(e,t,n){e.exports=n(792)},function(e,t,n){n(793),e.exports=n(22).Object.getPrototypeOf},function(e,t,n){var r=n(79),o=n(347);n(208)("getPrototypeOf",function(){return function(e){return o(r(e))}})},function(e,t,n){n(795),e.exports=n(22).Object.setPrototypeOf},function(e,t,n){var r=n(30);r(r.S,"Object",{setPrototypeOf:n(796).set})},function(e,t,n){var r=n(40),o=n(44),i=function(e,t){if(o(e),!r(t)&&null!==t)throw TypeError(t+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,r){try{(r=n(60)(Function.call,n(159).f(Object.prototype,"__proto__").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,n){return i(e,n),t?e.__proto__=n:r(e,n),e}}({},!1):void 0),check:i}},function(e,t,n){n(798);var r=n(22).Object;e.exports=function(e,t){return r.create(e,t)}},function(e,t,n){var r=n(30);r(r.S,"Object",{create:n(156)})},function(e,t,n){var r=n(413);function o(t,n){return e.exports=o=r||function(e,t){return e.__proto__=t,e},o(t,n)}e.exports=o},function(e,t,n){"use strict";var r=n(27),o=n(801),i=n(438),a=n(112),s=n(55),u=n(873),c=n(874),l=n(439),p=n(875);n(23);o.inject();var f={findDOMNode:c,render:i.render,unmountComponentAtNode:i.unmountComponentAtNode,version:u,unstable_batchedUpdates:s.batchedUpdates,unstable_renderSubtreeIntoContainer:p};"undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject&&__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ComponentTree:{getClosestInstanceFromNode:r.getClosestInstanceFromNode,getNodeFromInstance:function(e){return e._renderedComponent&&(e=l(e)),e?r.getNodeFromInstance(e):null}},Mount:i,Reconciler:a}),e.exports=f},function(e,t,n){"use strict";var r=n(802),o=n(803),i=n(807),a=n(810),s=n(811),u=n(812),c=n(813),l=n(819),p=n(27),f=n(844),h=n(845),d=n(846),m=n(847),v=n(848),g=n(850),y=n(851),b=n(857),_=n(858),w=n(859),x=!1;e.exports={inject:function(){x||(x=!0,g.EventEmitter.injectReactEventListener(v),g.EventPluginHub.injectEventPluginOrder(a),g.EventPluginUtils.injectComponentTree(p),g.EventPluginUtils.injectTreeTraversal(h),g.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:w,EnterLeaveEventPlugin:s,ChangeEventPlugin:i,SelectEventPlugin:_,BeforeInputEventPlugin:o}),g.HostComponent.injectGenericComponentClass(l),g.HostComponent.injectTextComponentClass(d),g.DOMProperty.injectDOMPropertyConfig(r),g.DOMProperty.injectDOMPropertyConfig(u),g.DOMProperty.injectDOMPropertyConfig(b),g.EmptyComponent.injectEmptyComponentFactory(function(e){return new f(e)}),g.Updates.injectReconcileTransaction(y),g.Updates.injectBatchingStrategy(m),g.Component.injectEnvironment(c))}}},function(e,t,n){"use strict";e.exports={Properties:{"aria-current":0,"aria-details":0,"aria-disabled":0,"aria-hidden":0,"aria-invalid":0,"aria-keyshortcuts":0,"aria-label":0,"aria-roledescription":0,"aria-autocomplete":0,"aria-checked":0,"aria-expanded":0,"aria-haspopup":0,"aria-level":0,"aria-modal":0,"aria-multiline":0,"aria-multiselectable":0,"aria-orientation":0,"aria-placeholder":0,"aria-pressed":0,"aria-readonly":0,"aria-required":0,"aria-selected":0,"aria-sort":0,"aria-valuemax":0,"aria-valuemin":0,"aria-valuenow":0,"aria-valuetext":0,"aria-atomic":0,"aria-busy":0,"aria-live":0,"aria-relevant":0,"aria-dropeffect":0,"aria-grabbed":0,"aria-activedescendant":0,"aria-colcount":0,"aria-colindex":0,"aria-colspan":0,"aria-controls":0,"aria-describedby":0,"aria-errormessage":0,"aria-flowto":0,"aria-labelledby":0,"aria-owns":0,"aria-posinset":0,"aria-rowcount":0,"aria-rowindex":0,"aria-rowspan":0,"aria-setsize":0},DOMAttributeNames:{},DOMPropertyNames:{}}},function(e,t,n){"use strict";var r=n(137),o=n(36),i=n(804),a=n(805),s=n(806),u=[9,13,27,32],c=229,l=o.canUseDOM&&"CompositionEvent"in window,p=null;o.canUseDOM&&"documentMode"in document&&(p=document.documentMode);var f,h=o.canUseDOM&&"TextEvent"in window&&!p&&!("object"==typeof(f=window.opera)&&"function"==typeof f.version&&parseInt(f.version(),10)<=12),d=o.canUseDOM&&(!l||p&&p>8&&p<=11);var m=32,v=String.fromCharCode(m),g={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["topCompositionEnd","topKeyPress","topTextInput","topPaste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:["topBlur","topCompositionEnd","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:["topBlur","topCompositionStart","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:["topBlur","topCompositionUpdate","topKeyDown","topKeyPress","topKeyUp","topMouseDown"]}},y=!1;function b(e,t){switch(e){case"topKeyUp":return-1!==u.indexOf(t.keyCode);case"topKeyDown":return t.keyCode!==c;case"topKeyPress":case"topMouseDown":case"topBlur":return!0;default:return!1}}function _(e){var t=e.detail;return"object"==typeof t&&"data"in t?t.data:null}var w=null;function x(e,t,n,o){var s,u;if(l?s=function(e){switch(e){case"topCompositionStart":return g.compositionStart;case"topCompositionEnd":return g.compositionEnd;case"topCompositionUpdate":return g.compositionUpdate}}(e):w?b(e,n)&&(s=g.compositionEnd):function(e,t){return"topKeyDown"===e&&t.keyCode===c}(e,n)&&(s=g.compositionStart),!s)return null;d&&(w||s!==g.compositionStart?s===g.compositionEnd&&w&&(u=w.getData()):w=i.getPooled(o));var p=a.getPooled(s,t,n,o);if(u)p.data=u;else{var f=_(n);null!==f&&(p.data=f)}return r.accumulateTwoPhaseDispatches(p),p}function E(e,t,n,o){var a;if(!(a=h?function(e,t){switch(e){case"topCompositionEnd":return _(t);case"topKeyPress":return t.which!==m?null:(y=!0,v);case"topTextInput":var n=t.data;return n===v&&y?null:n;default:return null}}(e,n):function(e,t){if(w){if("topCompositionEnd"===e||!l&&b(e,t)){var n=w.getData();return i.release(w),w=null,n}return null}switch(e){case"topPaste":return null;case"topKeyPress":return t.which&&!function(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}(t)?String.fromCharCode(t.which):null;case"topCompositionEnd":return d?null:t.data;default:return null}}(e,n)))return null;var u=s.getPooled(g.beforeInput,t,n,o);return u.data=a,r.accumulateTwoPhaseDispatches(u),u}var S={eventTypes:g,extractEvents:function(e,t,n,r){return[x(e,t,n,r),E(e,t,n,r)]}};e.exports=S},function(e,t,n){"use strict";var r=n(25),o=n(88),i=n(418);function a(e){this._root=e,this._startText=this.getText(),this._fallbackText=null}r(a.prototype,{destructor:function(){this._root=null,this._startText=null,this._fallbackText=null},getText:function(){return"value"in this._root?this._root.value:this._root[i()]},getData:function(){if(this._fallbackText)return this._fallbackText;var e,t,n=this._startText,r=n.length,o=this.getText(),i=o.length;for(e=0;e<r&&n[e]===o[e];e++);var a=r-e;for(t=1;t<=a&&n[r-t]===o[i-t];t++);var s=t>1?1-t:void 0;return this._fallbackText=o.slice(e,s),this._fallbackText}}),o.addPoolingTo(a),e.exports=a},function(e,t,n){"use strict";var r=n(64);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{data:null}),e.exports=o},function(e,t,n){"use strict";var r=n(64);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{data:null}),e.exports=o},function(e,t,n){"use strict";var r=n(138),o=n(137),i=n(36),a=n(27),s=n(55),u=n(64),c=n(421),l=n(242),p=n(243),f=n(422),h={change:{phasedRegistrationNames:{bubbled:"onChange",captured:"onChangeCapture"},dependencies:["topBlur","topChange","topClick","topFocus","topInput","topKeyDown","topKeyUp","topSelectionChange"]}};function d(e,t,n){var r=u.getPooled(h.change,e,t,n);return r.type="change",o.accumulateTwoPhaseDispatches(r),r}var m=null,v=null;var g=!1;function y(e){var t=d(v,e,l(e));s.batchedUpdates(b,t)}function b(e){r.enqueueEvents(e),r.processEventQueue(!1)}function _(){m&&(m.detachEvent("onchange",y),m=null,v=null)}function w(e,t){var n=c.updateValueIfChanged(e),r=!0===t.simulated&&P._allowSimulatedPassThrough;if(n||r)return e}function x(e,t){if("topChange"===e)return t}function E(e,t,n){"topFocus"===e?(_(),function(e,t){v=t,(m=e).attachEvent("onchange",y)}(t,n)):"topBlur"===e&&_()}i.canUseDOM&&(g=p("change")&&(!document.documentMode||document.documentMode>8));var S=!1;function C(){m&&(m.detachEvent("onpropertychange",k),m=null,v=null)}function k(e){"value"===e.propertyName&&w(v,e)&&y(e)}function O(e,t,n){"topFocus"===e?(C(),function(e,t){v=t,(m=e).attachEvent("onpropertychange",k)}(t,n)):"topBlur"===e&&C()}function A(e,t,n){if("topSelectionChange"===e||"topKeyUp"===e||"topKeyDown"===e)return w(v,n)}function T(e,t,n){if("topClick"===e)return w(t,n)}function j(e,t,n){if("topInput"===e||"topChange"===e)return w(t,n)}i.canUseDOM&&(S=p("input")&&(!document.documentMode||document.documentMode>9));var P={eventTypes:h,_allowSimulatedPassThrough:!0,_isInputEventSupported:S,extractEvents:function(e,t,n,r){var o,i,s,u,c=t?a.getNodeFromInstance(t):window;if("select"===(u=(s=c).nodeName&&s.nodeName.toLowerCase())||"input"===u&&"file"===s.type?g?o=x:i=E:f(c)?S?o=j:(o=A,i=O):function(e){var t=e.nodeName;return t&&"input"===t.toLowerCase()&&("checkbox"===e.type||"radio"===e.type)}(c)&&(o=T),o){var l=o(e,t,n);if(l)return d(l,n,r)}i&&i(e,c,t),"topBlur"===e&&function(e,t){if(null!=e){var n=e._wrapperState||t._wrapperState;if(n&&n.controlled&&"number"===t.type){var r=""+t.value;t.getAttribute("value")!==r&&t.setAttribute("value",r)}}}(t,c)}};e.exports=P},function(e,t,n){"use strict";var r=n(809),o={};o.attachRefs=function(e,t){if(null!==t&&"object"==typeof t){var n=t.ref;null!=n&&function(e,t,n){"function"==typeof e?e(t.getPublicInstance()):r.addComponentAsRefTo(t,e,n)}(n,e,t._owner)}},o.shouldUpdateRefs=function(e,t){var n=null,r=null;null!==e&&"object"==typeof e&&(n=e.ref,r=e._owner);var o=null,i=null;return null!==t&&"object"==typeof t&&(o=t.ref,i=t._owner),n!==o||"string"==typeof o&&i!==r},o.detachRefs=function(e,t){if(null!==t&&"object"==typeof t){var n=t.ref;null!=n&&function(e,t,n){"function"==typeof e?e(null):r.removeComponentAsRefFrom(t,e,n)}(n,e,t._owner)}},e.exports=o},function(e,t,n){"use strict";var r=n(21);n(15);function o(e){return!(!e||"function"!=typeof e.attachRef||"function"!=typeof e.detachRef)}var i={addComponentAsRefTo:function(e,t,n){o(n)||r("119"),n.attachRef(t,e)},removeComponentAsRefFrom:function(e,t,n){o(n)||r("120");var i=n.getPublicInstance();i&&i.refs[t]===e.getPublicInstance()&&n.detachRef(t)}};e.exports=i},function(e,t,n){"use strict";e.exports=["ResponderEventPlugin","SimpleEventPlugin","TapEventPlugin","EnterLeaveEventPlugin","ChangeEventPlugin","SelectEventPlugin","BeforeInputEventPlugin"]},function(e,t,n){"use strict";var r=n(137),o=n(27),i=n(183),a={mouseEnter:{registrationName:"onMouseEnter",dependencies:["topMouseOut","topMouseOver"]},mouseLeave:{registrationName:"onMouseLeave",dependencies:["topMouseOut","topMouseOver"]}},s={eventTypes:a,extractEvents:function(e,t,n,s){if("topMouseOver"===e&&(n.relatedTarget||n.fromElement))return null;if("topMouseOut"!==e&&"topMouseOver"!==e)return null;var u,c,l;if(s.window===s)u=s;else{var p=s.ownerDocument;u=p?p.defaultView||p.parentWindow:window}if("topMouseOut"===e){c=t;var f=n.relatedTarget||n.toElement;l=f?o.getClosestInstanceFromNode(f):null}else c=null,l=t;if(c===l)return null;var h=null==c?u:o.getNodeFromInstance(c),d=null==l?u:o.getNodeFromInstance(l),m=i.getPooled(a.mouseLeave,c,n,s);m.type="mouseleave",m.target=h,m.relatedTarget=d;var v=i.getPooled(a.mouseEnter,l,n,s);return v.type="mouseenter",v.target=d,v.relatedTarget=h,r.accumulateEnterLeaveDispatches(m,v,c,l),[m,v]}};e.exports=s},function(e,t,n){"use strict";var r=n(111),o=r.injection.MUST_USE_PROPERTY,i=r.injection.HAS_BOOLEAN_VALUE,a=r.injection.HAS_NUMERIC_VALUE,s=r.injection.HAS_POSITIVE_NUMERIC_VALUE,u=r.injection.HAS_OVERLOADED_BOOLEAN_VALUE,c={isCustomAttribute:RegExp.prototype.test.bind(new RegExp("^(data|aria)-["+r.ATTRIBUTE_NAME_CHAR+"]*$")),Properties:{accept:0,acceptCharset:0,accessKey:0,action:0,allowFullScreen:i,allowTransparency:0,alt:0,as:0,async:i,autoComplete:0,autoPlay:i,capture:i,cellPadding:0,cellSpacing:0,charSet:0,challenge:0,checked:o|i,cite:0,classID:0,className:0,cols:s,colSpan:0,content:0,contentEditable:0,contextMenu:0,controls:i,controlsList:0,coords:0,crossOrigin:0,data:0,dateTime:0,default:i,defer:i,dir:0,disabled:i,download:u,draggable:0,encType:0,form:0,formAction:0,formEncType:0,formMethod:0,formNoValidate:i,formTarget:0,frameBorder:0,headers:0,height:0,hidden:i,high:0,href:0,hrefLang:0,htmlFor:0,httpEquiv:0,icon:0,id:0,inputMode:0,integrity:0,is:0,keyParams:0,keyType:0,kind:0,label:0,lang:0,list:0,loop:i,low:0,manifest:0,marginHeight:0,marginWidth:0,max:0,maxLength:0,media:0,mediaGroup:0,method:0,min:0,minLength:0,multiple:o|i,muted:o|i,name:0,nonce:0,noValidate:i,open:i,optimum:0,pattern:0,placeholder:0,playsInline:i,poster:0,preload:0,profile:0,radioGroup:0,readOnly:i,referrerPolicy:0,rel:0,required:i,reversed:i,role:0,rows:s,rowSpan:a,sandbox:0,scope:0,scoped:i,scrolling:0,seamless:i,selected:o|i,shape:0,size:s,sizes:0,span:s,spellCheck:0,src:0,srcDoc:0,srcLang:0,srcSet:0,start:a,step:0,style:0,summary:0,tabIndex:0,target:0,title:0,type:0,useMap:0,value:0,width:0,wmode:0,wrap:0,about:0,datatype:0,inlist:0,prefix:0,property:0,resource:0,typeof:0,vocab:0,autoCapitalize:0,autoCorrect:0,autoSave:0,color:0,itemProp:0,itemScope:i,itemType:0,itemID:0,itemRef:0,results:0,security:0,unselectable:0},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{},DOMMutationMethods:{value:function(e,t){if(null==t)return e.removeAttribute("value");"number"!==e.type||!1===e.hasAttribute("value")?e.setAttribute("value",""+t):e.validity&&!e.validity.badInput&&e.ownerDocument.activeElement!==e&&e.setAttribute("value",""+t)}}};e.exports=c},function(e,t,n){"use strict";var r=n(245),o={processChildrenUpdates:n(818).dangerouslyProcessChildrenUpdates,replaceNodeWithMarkup:r.dangerouslyReplaceNodeWithMarkup};e.exports=o},function(e,t,n){"use strict";var r=n(21),o=n(113),i=n(36),a=n(815),s=n(54),u=(n(15),{dangerouslyReplaceNodeWithMarkup:function(e,t){if(i.canUseDOM||r("56"),t||r("57"),"HTML"===e.nodeName&&r("58"),"string"==typeof t){var n=a(t,s)[0];e.parentNode.replaceChild(n,e)}else o.replaceChildWithTree(e,t)}});e.exports=u},function(e,t,n){"use strict";var r=n(36),o=n(816),i=n(817),a=n(15),s=r.canUseDOM?document.createElement("div"):null,u=/^\s*<(\w+)/;e.exports=function(e,t){var n=s;s||a(!1);var r=function(e){var t=e.match(u);return t&&t[1].toLowerCase()}(e),c=r&&i(r);if(c){n.innerHTML=c[1]+e+c[2];for(var l=c[0];l--;)n=n.lastChild}else n.innerHTML=e;var p=n.getElementsByTagName("script");p.length&&(t||a(!1),o(p).forEach(t));for(var f=Array.from(n.childNodes);n.lastChild;)n.removeChild(n.lastChild);return f}},function(e,t,n){"use strict";var r=n(15);e.exports=function(e){return function(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"length"in e&&!("setInterval"in e)&&"number"!=typeof e.nodeType&&(Array.isArray(e)||"callee"in e||"item"in e)}(e)?Array.isArray(e)?e.slice():function(e){var t=e.length;if((Array.isArray(e)||"object"!=typeof e&&"function"!=typeof e)&&r(!1),"number"!=typeof t&&r(!1),0===t||t-1 in e||r(!1),"function"==typeof e.callee&&r(!1),e.hasOwnProperty)try{return Array.prototype.slice.call(e)}catch(e){}for(var n=Array(t),o=0;o<t;o++)n[o]=e[o];return n}(e):[e]}},function(e,t,n){"use strict";var r=n(36),o=n(15),i=r.canUseDOM?document.createElement("div"):null,a={},s=[1,'<select multiple="true">',"</select>"],u=[1,"<table>","</table>"],c=[3,"<table><tbody><tr>","</tr></tbody></table>"],l=[1,'<svg xmlns="http://www.w3.org/2000/svg">',"</svg>"],p={"*":[1,"?<div>","</div>"],area:[1,"<map>","</map>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],legend:[1,"<fieldset>","</fieldset>"],param:[1,"<object>","</object>"],tr:[2,"<table><tbody>","</tbody></table>"],optgroup:s,option:s,caption:u,colgroup:u,tbody:u,tfoot:u,thead:u,td:c,th:c};["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"].forEach(function(e){p[e]=l,a[e]=!0}),e.exports=function(e){return i||o(!1),p.hasOwnProperty(e)||(e="*"),a.hasOwnProperty(e)||(i.innerHTML="*"===e?"<link />":"<"+e+"></"+e+">",a[e]=!i.firstChild),a[e]?p[e]:null}},function(e,t,n){"use strict";var r=n(245),o=n(27),i={dangerouslyProcessChildrenUpdates:function(e,t){var n=o.getNodeFromInstance(e);r.processUpdates(n,t)}};e.exports=i},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(820),a=n(821),s=n(113),u=n(246),c=n(111),l=n(427),p=n(138),f=n(239),h=n(186),d=n(415),m=n(27),v=n(831),g=n(833),y=n(428),b=n(834),_=(n(50),n(835)),w=n(842),x=(n(54),n(185)),E=(n(15),n(243),n(250),n(421)),S=(n(254),n(23),d),C=p.deleteListener,k=m.getNodeFromInstance,O=h.listenTo,A=f.registrationNameModules,T={string:!0,number:!0},j="__html",P={children:null,dangerouslySetInnerHTML:null,suppressContentEditableWarning:null},I=11;function M(e,t){t&&(W[e._tag]&&(null!=t.children||null!=t.dangerouslySetInnerHTML)&&r("137",e._tag,e._currentElement._owner?" Check the render method of "+e._currentElement._owner.getName()+".":""),null!=t.dangerouslySetInnerHTML&&(null!=t.children&&r("60"),"object"==typeof t.dangerouslySetInnerHTML&&j in t.dangerouslySetInnerHTML||r("61")),null!=t.style&&"object"!=typeof t.style&&r("62",function(e){if(e){var t=e._currentElement._owner||null;if(t){var n=t.getName();if(n)return" This DOM node was rendered by `"+n+"`."}}return""}(e)))}function N(e,t,n,r){if(!(r instanceof w)){0;var o=e._hostContainerInfo,i=o._node&&o._node.nodeType===I?o._node:o._ownerDocument;O(t,i),r.getReactMountReady().enqueue(R,{inst:e,registrationName:t,listener:n})}}function R(){p.putListener(this.inst,this.registrationName,this.listener)}function D(){v.postMountWrapper(this)}function L(){b.postMountWrapper(this)}function U(){g.postMountWrapper(this)}var q={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"};function F(){E.track(this)}function z(){this._rootNodeID||r("63");var e=k(this);switch(e||r("64"),this._tag){case"iframe":case"object":this._wrapperState.listeners=[h.trapBubbledEvent("topLoad","load",e)];break;case"video":case"audio":for(var t in this._wrapperState.listeners=[],q)q.hasOwnProperty(t)&&this._wrapperState.listeners.push(h.trapBubbledEvent(t,q[t],e));break;case"source":this._wrapperState.listeners=[h.trapBubbledEvent("topError","error",e)];break;case"img":this._wrapperState.listeners=[h.trapBubbledEvent("topError","error",e),h.trapBubbledEvent("topLoad","load",e)];break;case"form":this._wrapperState.listeners=[h.trapBubbledEvent("topReset","reset",e),h.trapBubbledEvent("topSubmit","submit",e)];break;case"input":case"select":case"textarea":this._wrapperState.listeners=[h.trapBubbledEvent("topInvalid","invalid",e)]}}function B(){y.postUpdateWrapper(this)}var V={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},H={listing:!0,pre:!0,textarea:!0},W=o({menuitem:!0},V),J=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,Y={},K={}.hasOwnProperty;function G(e,t){return e.indexOf("-")>=0||null!=t.is}var $=1;function Z(e){var t=e.type;!function(e){K.call(Y,e)||(J.test(e)||r("65",e),Y[e]=!0)}(t),this._currentElement=e,this._tag=t.toLowerCase(),this._namespaceURI=null,this._renderedChildren=null,this._previousStyle=null,this._previousStyleCopy=null,this._hostNode=null,this._hostParent=null,this._rootNodeID=0,this._domID=0,this._hostContainerInfo=null,this._wrapperState=null,this._topLevelWrapper=null,this._flags=0}Z.displayName="ReactDOMComponent",Z.Mixin={mountComponent:function(e,t,n,r){this._rootNodeID=$++,this._domID=n._idCounter++,this._hostParent=t,this._hostContainerInfo=n;var o,a,c,p=this._currentElement.props;switch(this._tag){case"audio":case"form":case"iframe":case"img":case"link":case"object":case"source":case"video":this._wrapperState={listeners:null},e.getReactMountReady().enqueue(z,this);break;case"input":v.mountWrapper(this,p,t),p=v.getHostProps(this,p),e.getReactMountReady().enqueue(F,this),e.getReactMountReady().enqueue(z,this);break;case"option":g.mountWrapper(this,p,t),p=g.getHostProps(this,p);break;case"select":y.mountWrapper(this,p,t),p=y.getHostProps(this,p),e.getReactMountReady().enqueue(z,this);break;case"textarea":b.mountWrapper(this,p,t),p=b.getHostProps(this,p),e.getReactMountReady().enqueue(F,this),e.getReactMountReady().enqueue(z,this)}if(M(this,p),null!=t?(o=t._namespaceURI,a=t._tag):n._tag&&(o=n._namespaceURI,a=n._tag),(null==o||o===u.svg&&"foreignobject"===a)&&(o=u.html),o===u.html&&("svg"===this._tag?o=u.svg:"math"===this._tag&&(o=u.mathml)),this._namespaceURI=o,e.useCreateElement){var f,h=n._ownerDocument;if(o===u.html)if("script"===this._tag){var d=h.createElement("div"),_=this._currentElement.type;d.innerHTML="<"+_+"></"+_+">",f=d.removeChild(d.firstChild)}else f=p.is?h.createElement(this._currentElement.type,p.is):h.createElement(this._currentElement.type);else f=h.createElementNS(o,this._currentElement.type);m.precacheNode(this,f),this._flags|=S.hasCachedChildNodes,this._hostParent||l.setAttributeForRoot(f),this._updateDOMProperties(null,p,e);var w=s(f);this._createInitialChildren(e,p,r,w),c=w}else{var x=this._createOpenTagMarkupAndPutListeners(e,p),E=this._createContentMarkup(e,p,r);c=!E&&V[this._tag]?x+"/>":x+">"+E+"</"+this._currentElement.type+">"}switch(this._tag){case"input":e.getReactMountReady().enqueue(D,this),p.autoFocus&&e.getReactMountReady().enqueue(i.focusDOMComponent,this);break;case"textarea":e.getReactMountReady().enqueue(L,this),p.autoFocus&&e.getReactMountReady().enqueue(i.focusDOMComponent,this);break;case"select":case"button":p.autoFocus&&e.getReactMountReady().enqueue(i.focusDOMComponent,this);break;case"option":e.getReactMountReady().enqueue(U,this)}return c},_createOpenTagMarkupAndPutListeners:function(e,t){var n="<"+this._currentElement.type;for(var r in t)if(t.hasOwnProperty(r)){var i=t[r];if(null!=i)if(A.hasOwnProperty(r))i&&N(this,r,i,e);else{"style"===r&&(i&&(i=this._previousStyleCopy=o({},t.style)),i=a.createMarkupForStyles(i,this));var s=null;null!=this._tag&&G(this._tag,t)?P.hasOwnProperty(r)||(s=l.createMarkupForCustomAttribute(r,i)):s=l.createMarkupForProperty(r,i),s&&(n+=" "+s)}}return e.renderToStaticMarkup?n:(this._hostParent||(n+=" "+l.createMarkupForRoot()),n+=" "+l.createMarkupForID(this._domID))},_createContentMarkup:function(e,t,n){var r="",o=t.dangerouslySetInnerHTML;if(null!=o)null!=o.__html&&(r=o.__html);else{var i=T[typeof t.children]?t.children:null,a=null!=i?null:t.children;if(null!=i)r=x(i);else if(null!=a){r=this.mountChildren(a,e,n).join("")}}return H[this._tag]&&"\n"===r.charAt(0)?"\n"+r:r},_createInitialChildren:function(e,t,n,r){var o=t.dangerouslySetInnerHTML;if(null!=o)null!=o.__html&&s.queueHTML(r,o.__html);else{var i=T[typeof t.children]?t.children:null,a=null!=i?null:t.children;if(null!=i)""!==i&&s.queueText(r,i);else if(null!=a)for(var u=this.mountChildren(a,e,n),c=0;c<u.length;c++)s.queueChild(r,u[c])}},receiveComponent:function(e,t,n){var r=this._currentElement;this._currentElement=e,this.updateComponent(t,r,e,n)},updateComponent:function(e,t,n,r){var o=t.props,i=this._currentElement.props;switch(this._tag){case"input":o=v.getHostProps(this,o),i=v.getHostProps(this,i);break;case"option":o=g.getHostProps(this,o),i=g.getHostProps(this,i);break;case"select":o=y.getHostProps(this,o),i=y.getHostProps(this,i);break;case"textarea":o=b.getHostProps(this,o),i=b.getHostProps(this,i)}switch(M(this,i),this._updateDOMProperties(o,i,e),this._updateDOMChildren(o,i,e,r),this._tag){case"input":v.updateWrapper(this),E.updateValueIfChanged(this);break;case"textarea":b.updateWrapper(this);break;case"select":e.getReactMountReady().enqueue(B,this)}},_updateDOMProperties:function(e,t,n){var r,i,s;for(r in e)if(!t.hasOwnProperty(r)&&e.hasOwnProperty(r)&&null!=e[r])if("style"===r){var u=this._previousStyleCopy;for(i in u)u.hasOwnProperty(i)&&((s=s||{})[i]="");this._previousStyleCopy=null}else A.hasOwnProperty(r)?e[r]&&C(this,r):G(this._tag,e)?P.hasOwnProperty(r)||l.deleteValueForAttribute(k(this),r):(c.properties[r]||c.isCustomAttribute(r))&&l.deleteValueForProperty(k(this),r);for(r in t){var p=t[r],f="style"===r?this._previousStyleCopy:null!=e?e[r]:void 0;if(t.hasOwnProperty(r)&&p!==f&&(null!=p||null!=f))if("style"===r)if(p?p=this._previousStyleCopy=o({},p):this._previousStyleCopy=null,f){for(i in f)!f.hasOwnProperty(i)||p&&p.hasOwnProperty(i)||((s=s||{})[i]="");for(i in p)p.hasOwnProperty(i)&&f[i]!==p[i]&&((s=s||{})[i]=p[i])}else s=p;else if(A.hasOwnProperty(r))p?N(this,r,p,n):f&&C(this,r);else if(G(this._tag,t))P.hasOwnProperty(r)||l.setValueForAttribute(k(this),r,p);else if(c.properties[r]||c.isCustomAttribute(r)){var h=k(this);null!=p?l.setValueForProperty(h,r,p):l.deleteValueForProperty(h,r)}}s&&a.setValueForStyles(k(this),s,this)},_updateDOMChildren:function(e,t,n,r){var o=T[typeof e.children]?e.children:null,i=T[typeof t.children]?t.children:null,a=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,s=t.dangerouslySetInnerHTML&&t.dangerouslySetInnerHTML.__html,u=null!=o?null:e.children,c=null!=i?null:t.children,l=null!=o||null!=a,p=null!=i||null!=s;null!=u&&null==c?this.updateChildren(null,n,r):l&&!p&&this.updateTextContent(""),null!=i?o!==i&&this.updateTextContent(""+i):null!=s?a!==s&&this.updateMarkup(""+s):null!=c&&this.updateChildren(c,n,r)},getHostNode:function(){return k(this)},unmountComponent:function(e){switch(this._tag){case"audio":case"form":case"iframe":case"img":case"link":case"object":case"source":case"video":var t=this._wrapperState.listeners;if(t)for(var n=0;n<t.length;n++)t[n].remove();break;case"input":case"textarea":E.stopTracking(this);break;case"html":case"head":case"body":r("66",this._tag)}this.unmountChildren(e),m.uncacheNode(this),p.deleteAllListeners(this),this._rootNodeID=0,this._domID=0,this._wrapperState=null},getPublicInstance:function(){return k(this)}},o(Z.prototype,Z.Mixin,_.Mixin),e.exports=Z},function(e,t,n){"use strict";var r=n(27),o=n(425),i={focusDOMComponent:function(){o(r.getNodeFromInstance(this))}};e.exports=i},function(e,t,n){"use strict";var r=n(426),o=n(36),i=(n(50),n(822),n(824)),a=n(825),s=n(827),u=(n(23),s(function(e){return a(e)})),c=!1,l="cssFloat";if(o.canUseDOM){var p=document.createElement("div").style;try{p.font=""}catch(e){c=!0}void 0===document.documentElement.style.cssFloat&&(l="styleFloat")}var f={createMarkupForStyles:function(e,t){var n="";for(var r in e)if(e.hasOwnProperty(r)){var o=0===r.indexOf("--"),a=e[r];0,null!=a&&(n+=u(r)+":",n+=i(r,a,t,o)+";")}return n||null},setValueForStyles:function(e,t,n){var o=e.style;for(var a in t)if(t.hasOwnProperty(a)){var s=0===a.indexOf("--");0;var u=i(a,t[a],n,s);if("float"!==a&&"cssFloat"!==a||(a=l),s)o.setProperty(a,u);else if(u)o[a]=u;else{var p=c&&r.shorthandPropertyExpansions[a];if(p)for(var f in p)o[f]="";else o[a]=""}}}};e.exports=f},function(e,t,n){"use strict";var r=n(823),o=/^-ms-/;e.exports=function(e){return r(e.replace(o,"ms-"))}},function(e,t,n){"use strict";var r=/-(.)/g;e.exports=function(e){return e.replace(r,function(e,t){return t.toUpperCase()})}},function(e,t,n){"use strict";var r=n(426),o=(n(23),r.isUnitlessNumber);e.exports=function(e,t,n,r){if(null==t||"boolean"==typeof t||""===t)return"";var i=isNaN(t);return r||i||0===t||o.hasOwnProperty(e)&&o[e]?""+t:("string"==typeof t&&(t=t.trim()),t+"px")}},function(e,t,n){"use strict";var r=n(826),o=/^ms-/;e.exports=function(e){return r(e).replace(o,"-ms-")}},function(e,t,n){"use strict";var r=/([A-Z])/g;e.exports=function(e){return e.replace(r,"-$1").toLowerCase()}},function(e,t,n){"use strict";e.exports=function(e){var t={};return function(n){return t.hasOwnProperty(n)||(t[n]=e.call(this,n)),t[n]}}},function(e,t,n){"use strict";var r=n(185);e.exports=function(e){return'"'+r(e)+'"'}},function(e,t,n){"use strict";var r=n(138);var o={handleTopLevel:function(e,t,n,o){!function(e){r.enqueueEvents(e),r.processEventQueue(!1)}(r.extractEvents(e,t,n,o))}};e.exports=o},function(e,t,n){"use strict";var r=n(36);function o(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n["ms"+e]="MS"+t,n["O"+e]="o"+t.toLowerCase(),n}var i={animationend:o("Animation","AnimationEnd"),animationiteration:o("Animation","AnimationIteration"),animationstart:o("Animation","AnimationStart"),transitionend:o("Transition","TransitionEnd")},a={},s={};r.canUseDOM&&(s=document.createElement("div").style,"AnimationEvent"in window||(delete i.animationend.animation,delete i.animationiteration.animation,delete i.animationstart.animation),"TransitionEvent"in window||delete i.transitionend.transition),e.exports=function(e){if(a[e])return a[e];if(!i[e])return e;var t=i[e];for(var n in t)if(t.hasOwnProperty(n)&&n in s)return a[e]=t[n];return""}},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(427),a=n(248),s=n(27),u=n(55);n(15),n(23);function c(){this._rootNodeID&&p.updateWrapper(this)}function l(e){return"checkbox"===e.type||"radio"===e.type?null!=e.checked:null!=e.value}var p={getHostProps:function(e,t){var n=a.getValue(t),r=a.getChecked(t);return o({type:void 0,step:void 0,min:void 0,max:void 0},t,{defaultChecked:void 0,defaultValue:void 0,value:null!=n?n:e._wrapperState.initialValue,checked:null!=r?r:e._wrapperState.initialChecked,onChange:e._wrapperState.onChange})},mountWrapper:function(e,t){var n=t.defaultValue;e._wrapperState={initialChecked:null!=t.checked?t.checked:t.defaultChecked,initialValue:null!=t.value?t.value:n,listeners:null,onChange:f.bind(e),controlled:l(t)}},updateWrapper:function(e){var t=e._currentElement.props,n=t.checked;null!=n&&i.setValueForProperty(s.getNodeFromInstance(e),"checked",n||!1);var r=s.getNodeFromInstance(e),o=a.getValue(t);if(null!=o)if(0===o&&""===r.value)r.value="0";else if("number"===t.type){var u=parseFloat(r.value,10)||0;(o!=u||o==u&&r.value!=o)&&(r.value=""+o)}else r.value!==""+o&&(r.value=""+o);else null==t.value&&null!=t.defaultValue&&r.defaultValue!==""+t.defaultValue&&(r.defaultValue=""+t.defaultValue),null==t.checked&&null!=t.defaultChecked&&(r.defaultChecked=!!t.defaultChecked)},postMountWrapper:function(e){var t=e._currentElement.props,n=s.getNodeFromInstance(e);switch(t.type){case"submit":case"reset":break;case"color":case"date":case"datetime":case"datetime-local":case"month":case"time":case"week":n.value="",n.value=n.defaultValue;break;default:n.value=n.value}var r=n.name;""!==r&&(n.name=""),n.defaultChecked=!n.defaultChecked,n.defaultChecked=!n.defaultChecked,""!==r&&(n.name=r)}};function f(e){var t=this._currentElement.props,n=a.executeOnChange(t,e);u.asap(c,this);var o=t.name;if("radio"===t.type&&null!=o){for(var i=s.getNodeFromInstance(this),l=i;l.parentNode;)l=l.parentNode;for(var p=l.querySelectorAll("input[name="+JSON.stringify(""+o)+'][type="radio"]'),f=0;f<p.length;f++){var h=p[f];if(h!==i&&h.form===i.form){var d=s.getInstanceFromNode(h);d||r("90"),u.asap(c,d)}}}return n}e.exports=p},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";var r=n(25),o=n(100),i=n(27),a=n(428),s=(n(23),!1);function u(e){var t="";return o.Children.forEach(e,function(e){null!=e&&("string"==typeof e||"number"==typeof e?t+=e:s||(s=!0))}),t}var c={mountWrapper:function(e,t,n){var r=null;if(null!=n){var o=n;"optgroup"===o._tag&&(o=o._hostParent),null!=o&&"select"===o._tag&&(r=a.getSelectValueContext(o))}var i,s=null;if(null!=r)if(i=null!=t.value?t.value+"":u(t.children),s=!1,Array.isArray(r)){for(var c=0;c<r.length;c++)if(""+r[c]===i){s=!0;break}}else s=""+r===i;e._wrapperState={selected:s}},postMountWrapper:function(e){var t=e._currentElement.props;null!=t.value&&i.getNodeFromInstance(e).setAttribute("value",t.value)},getHostProps:function(e,t){var n=r({selected:void 0,children:void 0},t);null!=e._wrapperState.selected&&(n.selected=e._wrapperState.selected);var o=u(t.children);return o&&(n.children=o),n}};e.exports=c},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(248),a=n(27),s=n(55);n(15),n(23);function u(){this._rootNodeID&&c.updateWrapper(this)}var c={getHostProps:function(e,t){return null!=t.dangerouslySetInnerHTML&&r("91"),o({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue,onChange:e._wrapperState.onChange})},mountWrapper:function(e,t){var n=i.getValue(t),o=n;if(null==n){var a=t.defaultValue,s=t.children;null!=s&&(null!=a&&r("92"),Array.isArray(s)&&(s.length<=1||r("93"),s=s[0]),a=""+s),null==a&&(a=""),o=a}e._wrapperState={initialValue:""+o,listeners:null,onChange:l.bind(e)}},updateWrapper:function(e){var t=e._currentElement.props,n=a.getNodeFromInstance(e),r=i.getValue(t);if(null!=r){var o=""+r;o!==n.value&&(n.value=o),null==t.defaultValue&&(n.defaultValue=o)}null!=t.defaultValue&&(n.defaultValue=t.defaultValue)},postMountWrapper:function(e){var t=a.getNodeFromInstance(e),n=t.textContent;n===e._wrapperState.initialValue&&(t.value=n)}};function l(e){var t=this._currentElement.props,n=i.executeOnChange(t,e);return s.asap(u,this),n}e.exports=c},function(e,t,n){"use strict";var r=n(21),o=n(249),i=(n(140),n(50),n(62),n(112)),a=n(836),s=(n(54),n(841));n(15);function u(e,t){return t&&(e=e||[]).push(t),e}function c(e,t){o.processChildrenUpdates(e,t)}var l={Mixin:{_reconcilerInstantiateChildren:function(e,t,n){return a.instantiateChildren(e,t,n)},_reconcilerUpdateChildren:function(e,t,n,r,o,i){var u;return u=s(t,0),a.updateChildren(e,u,n,r,o,this,this._hostContainerInfo,i,0),u},mountChildren:function(e,t,n){var r=this._reconcilerInstantiateChildren(e,t,n);this._renderedChildren=r;var o=[],a=0;for(var s in r)if(r.hasOwnProperty(s)){var u=r[s];0;var c=i.mountComponent(u,t,this,this._hostContainerInfo,n,0);u._mountIndex=a++,o.push(c)}return o},updateTextContent:function(e){var t,n=this._renderedChildren;for(var o in a.unmountChildren(n,!1),n)n.hasOwnProperty(o)&&r("118");c(this,[(t=e,{type:"TEXT_CONTENT",content:t,fromIndex:null,fromNode:null,toIndex:null,afterNode:null})])},updateMarkup:function(e){var t,n=this._renderedChildren;for(var o in a.unmountChildren(n,!1),n)n.hasOwnProperty(o)&&r("118");c(this,[(t=e,{type:"SET_MARKUP",content:t,fromIndex:null,fromNode:null,toIndex:null,afterNode:null})])},updateChildren:function(e,t,n){this._updateChildren(e,t,n)},_updateChildren:function(e,t,n){var r=this._renderedChildren,o={},a=[],s=this._reconcilerUpdateChildren(r,e,a,o,t,n);if(s||r){var l,p=null,f=0,h=0,d=0,m=null;for(l in s)if(s.hasOwnProperty(l)){var v=r&&r[l],g=s[l];v===g?(p=u(p,this.moveChild(v,m,f,h)),h=Math.max(v._mountIndex,h),v._mountIndex=f):(v&&(h=Math.max(v._mountIndex,h)),p=u(p,this._mountChildAtIndex(g,a[d],m,f,t,n)),d++),f++,m=i.getHostNode(g)}for(l in o)o.hasOwnProperty(l)&&(p=u(p,this._unmountChild(r[l],o[l])));p&&c(this,p),this._renderedChildren=s}},unmountChildren:function(e){var t=this._renderedChildren;a.unmountChildren(t,e),this._renderedChildren=null},moveChild:function(e,t,n,r){if(e._mountIndex<r)return function(e,t,n){return{type:"MOVE_EXISTING",content:null,fromIndex:e._mountIndex,fromNode:i.getHostNode(e),toIndex:n,afterNode:t}}(e,t,n)},createChild:function(e,t,n){return function(e,t,n){return{type:"INSERT_MARKUP",content:e,fromIndex:null,fromNode:null,toIndex:n,afterNode:t}}(n,t,e._mountIndex)},removeChild:function(e,t){return function(e,t){return{type:"REMOVE_NODE",content:null,fromIndex:e._mountIndex,fromNode:t,toIndex:null,afterNode:null}}(e,t)},_mountChildAtIndex:function(e,t,n,r,o,i){return e._mountIndex=r,this.createChild(e,n,t)},_unmountChild:function(e,t){var n=this.removeChild(e,t);return e._mountIndex=null,n}}};e.exports=l},function(e,t,n){"use strict";(function(t){var r=n(112),o=n(429),i=(n(252),n(251)),a=n(433);n(23);function s(e,t,n,r){var i=void 0===e[n];null!=t&&i&&(e[n]=o(t,!0))}void 0!==t&&t.env;var u={instantiateChildren:function(e,t,n,r){if(null==e)return null;var o={};return a(e,s,o),o},updateChildren:function(e,t,n,a,s,u,c,l,p){if(t||e){var f,h;for(f in t)if(t.hasOwnProperty(f)){var d=(h=e&&e[f])&&h._currentElement,m=t[f];if(null!=h&&i(d,m))r.receiveComponent(h,m,s,l),t[f]=h;else{h&&(a[f]=r.getHostNode(h),r.unmountComponent(h,!1));var v=o(m,!0);t[f]=v;var g=r.mountComponent(v,s,u,c,l,p);n.push(g)}}for(f in e)!e.hasOwnProperty(f)||t&&t.hasOwnProperty(f)||(h=e[f],a[f]=r.getHostNode(h),r.unmountComponent(h,!1))}},unmountChildren:function(e,t){for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];r.unmountComponent(o,t)}}};e.exports=u}).call(this,n(72))},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(100),a=n(249),s=n(62),u=n(241),c=n(140),l=(n(50),n(430)),p=n(112),f=n(161),h=(n(15),n(250)),d=n(251),m=(n(23),0),v=1,g=2;function y(e){}function b(e,t){0}y.prototype.render=function(){var e=c.get(this)._currentElement.type,t=e(this.props,this.context,this.updater);return b(e,t),t};var _=1,w={construct:function(e){this._currentElement=e,this._rootNodeID=0,this._compositeType=null,this._instance=null,this._hostParent=null,this._hostContainerInfo=null,this._updateBatchNumber=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedNodeType=null,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._topLevelWrapper=null,this._pendingCallbacks=null,this._calledComponentWillUnmount=!1},mountComponent:function(e,t,n,o){this._context=o,this._mountOrder=_++,this._hostParent=t,this._hostContainerInfo=n;var a,s=this._currentElement.props,u=this._processContext(o),l=this._currentElement.type,p=e.getUpdateQueue(),h=function(e){return!(!e.prototype||!e.prototype.isReactComponent)}(l),d=this._constructComponent(h,s,u,p);h||null!=d&&null!=d.render?!function(e){return!(!e.prototype||!e.prototype.isPureReactComponent)}(l)?this._compositeType=m:this._compositeType=v:(a=d,b(),null===d||!1===d||i.isValidElement(d)||r("105",l.displayName||l.name||"Component"),d=new y(l),this._compositeType=g),d.props=s,d.context=u,d.refs=f,d.updater=p,this._instance=d,c.set(d,this);var w,x=d.state;return void 0===x&&(d.state=x=null),("object"!=typeof x||Array.isArray(x))&&r("106",this.getName()||"ReactCompositeComponent"),this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,w=d.unstable_handleError?this.performInitialMountWithErrorHandling(a,t,n,e,o):this.performInitialMount(a,t,n,e,o),d.componentDidMount&&e.getReactMountReady().enqueue(d.componentDidMount,d),w},_constructComponent:function(e,t,n,r){return this._constructComponentWithoutOwner(e,t,n,r)},_constructComponentWithoutOwner:function(e,t,n,r){var o=this._currentElement.type;return e?new o(t,n,r):o(t,n,r)},performInitialMountWithErrorHandling:function(e,t,n,r,o){var i,a=r.checkpoint();try{i=this.performInitialMount(e,t,n,r,o)}catch(s){r.rollback(a),this._instance.unstable_handleError(s),this._pendingStateQueue&&(this._instance.state=this._processPendingState(this._instance.props,this._instance.context)),a=r.checkpoint(),this._renderedComponent.unmountComponent(!0),r.rollback(a),i=this.performInitialMount(e,t,n,r,o)}return i},performInitialMount:function(e,t,n,r,o){var i=this._instance;i.componentWillMount&&(i.componentWillMount(),this._pendingStateQueue&&(i.state=this._processPendingState(i.props,i.context))),void 0===e&&(e=this._renderValidatedComponent());var a=l.getType(e);this._renderedNodeType=a;var s=this._instantiateReactComponent(e,a!==l.EMPTY);return this._renderedComponent=s,p.mountComponent(s,r,t,n,this._processChildContext(o),0)},getHostNode:function(){return p.getHostNode(this._renderedComponent)},unmountComponent:function(e){if(this._renderedComponent){var t=this._instance;if(t.componentWillUnmount&&!t._calledComponentWillUnmount)if(t._calledComponentWillUnmount=!0,e){var n=this.getName()+".componentWillUnmount()";u.invokeGuardedCallback(n,t.componentWillUnmount.bind(t))}else t.componentWillUnmount();this._renderedComponent&&(p.unmountComponent(this._renderedComponent,e),this._renderedNodeType=null,this._renderedComponent=null,this._instance=null),this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=0,this._topLevelWrapper=null,c.remove(t)}},_maskContext:function(e){var t=this._currentElement.type.contextTypes;if(!t)return f;var n={};for(var r in t)n[r]=e[r];return n},_processContext:function(e){return this._maskContext(e)},_processChildContext:function(e){var t,n=this._currentElement.type,i=this._instance;if(i.getChildContext&&(t=i.getChildContext()),t){for(var a in"object"!=typeof n.childContextTypes&&r("107",this.getName()||"ReactCompositeComponent"),t)a in n.childContextTypes||r("108",this.getName()||"ReactCompositeComponent",a);return o({},e,t)}return e},_checkContextTypes:function(e,t,n){0},receiveComponent:function(e,t,n){var r=this._currentElement,o=this._context;this._pendingElement=null,this.updateComponent(t,r,e,o,n)},performUpdateIfNecessary:function(e){null!=this._pendingElement?p.receiveComponent(this,this._pendingElement,e,this._context):null!==this._pendingStateQueue||this._pendingForceUpdate?this.updateComponent(e,this._currentElement,this._currentElement,this._context,this._context):this._updateBatchNumber=null},updateComponent:function(e,t,n,o,i){var a=this._instance;null==a&&r("136",this.getName()||"ReactCompositeComponent");var s,u=!1;this._context===i?s=a.context:(s=this._processContext(i),u=!0);var c=t.props,l=n.props;t!==n&&(u=!0),u&&a.componentWillReceiveProps&&a.componentWillReceiveProps(l,s);var p=this._processPendingState(l,s),f=!0;this._pendingForceUpdate||(a.shouldComponentUpdate?f=a.shouldComponentUpdate(l,p,s):this._compositeType===v&&(f=!h(c,l)||!h(a.state,p))),this._updateBatchNumber=null,f?(this._pendingForceUpdate=!1,this._performComponentUpdate(n,l,p,s,e,i)):(this._currentElement=n,this._context=i,a.props=l,a.state=p,a.context=s)},_processPendingState:function(e,t){var n=this._instance,r=this._pendingStateQueue,i=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!r)return n.state;if(i&&1===r.length)return r[0];for(var a=o({},i?r[0]:n.state),s=i?1:0;s<r.length;s++){var u=r[s];o(a,"function"==typeof u?u.call(n,a,e,t):u)}return a},_performComponentUpdate:function(e,t,n,r,o,i){var a,s,u,c=this._instance,l=Boolean(c.componentDidUpdate);l&&(a=c.props,s=c.state,u=c.context),c.componentWillUpdate&&c.componentWillUpdate(t,n,r),this._currentElement=e,this._context=i,c.props=t,c.state=n,c.context=r,this._updateRenderedComponent(o,i),l&&o.getReactMountReady().enqueue(c.componentDidUpdate.bind(c,a,s,u),c)},_updateRenderedComponent:function(e,t){var n=this._renderedComponent,r=n._currentElement,o=this._renderValidatedComponent();if(d(r,o))p.receiveComponent(n,o,e,this._processChildContext(t));else{var i=p.getHostNode(n);p.unmountComponent(n,!1);var a=l.getType(o);this._renderedNodeType=a;var s=this._instantiateReactComponent(o,a!==l.EMPTY);this._renderedComponent=s;var u=p.mountComponent(s,e,this._hostParent,this._hostContainerInfo,this._processChildContext(t),0);this._replaceNodeWithMarkup(i,u,n)}},_replaceNodeWithMarkup:function(e,t,n){a.replaceNodeWithMarkup(e,t,n)},_renderValidatedComponentWithoutOwnerOrContext:function(){return this._instance.render()},_renderValidatedComponent:function(){var e;if(this._compositeType!==g){s.current=this;try{e=this._renderValidatedComponentWithoutOwnerOrContext()}finally{s.current=null}}else e=this._renderValidatedComponentWithoutOwnerOrContext();return null===e||!1===e||i.isValidElement(e)||r("109",this.getName()||"ReactCompositeComponent"),e},attachRef:function(e,t){var n=this.getPublicInstance();null==n&&r("110");var o=t.getPublicInstance();(n.refs===f?n.refs={}:n.refs)[e]=o},detachRef:function(e){delete this.getPublicInstance().refs[e]},getName:function(){var e=this._currentElement.type,t=this._instance&&this._instance.constructor;return e.displayName||t&&t.displayName||e.name||t&&t.name||null},getPublicInstance:function(){var e=this._instance;return this._compositeType===g?null:e},_instantiateReactComponent:null};e.exports=w},function(e,t,n){"use strict";var r=1;e.exports=function(){return r++}},function(e,t,n){"use strict";var r="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103;e.exports=r},function(e,t,n){"use strict";var r="function"==typeof Symbol&&Symbol.iterator,o="@@iterator";e.exports=function(e){var t=e&&(r&&e[r]||e[o]);if("function"==typeof t)return t}},function(e,t,n){"use strict";(function(t){n(252);var r=n(433);n(23);function o(e,t,n,r){if(e&&"object"==typeof e){var o=e;0,void 0===o[n]&&null!=t&&(o[n]=t)}}void 0!==t&&t.env,e.exports=function(e,t){if(null==e)return e;var n={};return r(e,o,n),n}}).call(this,n(72))},function(e,t,n){"use strict";var r=n(25),o=n(88),i=n(182),a=(n(50),n(843)),s=[];var u={enqueue:function(){}};function c(e){this.reinitializeTransaction(),this.renderToStaticMarkup=e,this.useCreateElement=!1,this.updateQueue=new a(this)}var l={getTransactionWrappers:function(){return s},getReactMountReady:function(){return u},getUpdateQueue:function(){return this.updateQueue},destructor:function(){},checkpoint:function(){},rollback:function(){}};r(c.prototype,i,l),o.addPoolingTo(c),e.exports=c},function(e,t,n){"use strict";var r=n(253);n(23);var o=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.transaction=t}return e.prototype.isMounted=function(e){return!1},e.prototype.enqueueCallback=function(e,t,n){this.transaction.isInTransaction()&&r.enqueueCallback(e,t,n)},e.prototype.enqueueForceUpdate=function(e){this.transaction.isInTransaction()&&r.enqueueForceUpdate(e)},e.prototype.enqueueReplaceState=function(e,t){this.transaction.isInTransaction()&&r.enqueueReplaceState(e,t)},e.prototype.enqueueSetState=function(e,t){this.transaction.isInTransaction()&&r.enqueueSetState(e,t)},e}();e.exports=o},function(e,t,n){"use strict";var r=n(25),o=n(113),i=n(27),a=function(e){this._currentElement=null,this._hostNode=null,this._hostParent=null,this._hostContainerInfo=null,this._domID=0};r(a.prototype,{mountComponent:function(e,t,n,r){var a=n._idCounter++;this._domID=a,this._hostParent=t,this._hostContainerInfo=n;var s=" react-empty: "+this._domID+" ";if(e.useCreateElement){var u=n._ownerDocument.createComment(s);return i.precacheNode(this,u),o(u)}return e.renderToStaticMarkup?"":"\x3c!--"+s+"--\x3e"},receiveComponent:function(){},getHostNode:function(){return i.getNodeFromInstance(this)},unmountComponent:function(){i.uncacheNode(this)}}),e.exports=a},function(e,t,n){"use strict";var r=n(21);n(15);function o(e,t){"_hostNode"in e||r("33"),"_hostNode"in t||r("33");for(var n=0,o=e;o;o=o._hostParent)n++;for(var i=0,a=t;a;a=a._hostParent)i++;for(;n-i>0;)e=e._hostParent,n--;for(;i-n>0;)t=t._hostParent,i--;for(var s=n;s--;){if(e===t)return e;e=e._hostParent,t=t._hostParent}return null}e.exports={isAncestor:function(e,t){"_hostNode"in e||r("35"),"_hostNode"in t||r("35");for(;t;){if(t===e)return!0;t=t._hostParent}return!1},getLowestCommonAncestor:o,getParentInstance:function(e){return"_hostNode"in e||r("36"),e._hostParent},traverseTwoPhase:function(e,t,n){for(var r,o=[];e;)o.push(e),e=e._hostParent;for(r=o.length;r-- >0;)t(o[r],"captured",n);for(r=0;r<o.length;r++)t(o[r],"bubbled",n)},traverseEnterLeave:function(e,t,n,r,i){for(var a=e&&t?o(e,t):null,s=[];e&&e!==a;)s.push(e),e=e._hostParent;for(var u,c=[];t&&t!==a;)c.push(t),t=t._hostParent;for(u=0;u<s.length;u++)n(s[u],"bubbled",r);for(u=c.length;u-- >0;)n(c[u],"captured",i)}}},function(e,t,n){"use strict";var r=n(21),o=n(25),i=n(245),a=n(113),s=n(27),u=n(185),c=(n(15),n(254),function(e){this._currentElement=e,this._stringText=""+e,this._hostNode=null,this._hostParent=null,this._domID=0,this._mountIndex=0,this._closingComment=null,this._commentNodes=null});o(c.prototype,{mountComponent:function(e,t,n,r){var o=n._idCounter++,i=" react-text: "+o+" ";if(this._domID=o,this._hostParent=t,e.useCreateElement){var c=n._ownerDocument,l=c.createComment(i),p=c.createComment(" /react-text "),f=a(c.createDocumentFragment());return a.queueChild(f,a(l)),this._stringText&&a.queueChild(f,a(c.createTextNode(this._stringText))),a.queueChild(f,a(p)),s.precacheNode(this,l),this._closingComment=p,f}var h=u(this._stringText);return e.renderToStaticMarkup?h:"\x3c!--"+i+"--\x3e"+h+"\x3c!-- /react-text --\x3e"},receiveComponent:function(e,t){if(e!==this._currentElement){this._currentElement=e;var n=""+e;if(n!==this._stringText){this._stringText=n;var r=this.getHostNode();i.replaceDelimitedText(r[0],r[1],n)}}},getHostNode:function(){var e=this._commentNodes;if(e)return e;if(!this._closingComment)for(var t=s.getNodeFromInstance(this).nextSibling;;){if(null==t&&r("67",this._domID),8===t.nodeType&&" /react-text "===t.nodeValue){this._closingComment=t;break}t=t.nextSibling}return e=[this._hostNode,this._closingComment],this._commentNodes=e,e},unmountComponent:function(){this._closingComment=null,this._commentNodes=null,s.uncacheNode(this)}}),e.exports=c},function(e,t,n){"use strict";var r=n(25),o=n(55),i=n(182),a=n(54),s={initialize:a,close:function(){p.isBatchingUpdates=!1}},u=[{initialize:a,close:o.flushBatchedUpdates.bind(o)},s];function c(){this.reinitializeTransaction()}r(c.prototype,i,{getTransactionWrappers:function(){return u}});var l=new c,p={isBatchingUpdates:!1,batchedUpdates:function(e,t,n,r,o,i){var a=p.isBatchingUpdates;return p.isBatchingUpdates=!0,a?e(t,n,r,o,i):l.perform(e,null,t,n,r,o,i)}};e.exports=p},function(e,t,n){"use strict";var r=n(25),o=n(435),i=n(36),a=n(88),s=n(27),u=n(55),c=n(242),l=n(849);function p(e){for(;e._hostParent;)e=e._hostParent;var t=s.getNodeFromInstance(e).parentNode;return s.getClosestInstanceFromNode(t)}function f(e,t){this.topLevelType=e,this.nativeEvent=t,this.ancestors=[]}function h(e){var t=c(e.nativeEvent),n=s.getClosestInstanceFromNode(t),r=n;do{e.ancestors.push(r),r=r&&p(r)}while(r);for(var o=0;o<e.ancestors.length;o++)n=e.ancestors[o],d._handleTopLevel(e.topLevelType,n,e.nativeEvent,c(e.nativeEvent))}r(f.prototype,{destructor:function(){this.topLevelType=null,this.nativeEvent=null,this.ancestors.length=0}}),a.addPoolingTo(f,a.twoArgumentPooler);var d={_enabled:!0,_handleTopLevel:null,WINDOW_HANDLE:i.canUseDOM?window:null,setHandleTopLevel:function(e){d._handleTopLevel=e},setEnabled:function(e){d._enabled=!!e},isEnabled:function(){return d._enabled},trapBubbledEvent:function(e,t,n){return n?o.listen(n,t,d.dispatchEvent.bind(null,e)):null},trapCapturedEvent:function(e,t,n){return n?o.capture(n,t,d.dispatchEvent.bind(null,e)):null},monitorScrollValue:function(e){var t=function(e){e(l(window))}.bind(null,e);o.listen(window,"scroll",t)},dispatchEvent:function(e,t){if(d._enabled){var n=f.getPooled(e,t);try{u.batchedUpdates(h,n)}finally{f.release(n)}}}};e.exports=d},function(e,t,n){"use strict";e.exports=function(e){return e.Window&&e instanceof e.Window?{x:e.pageXOffset||e.document.documentElement.scrollLeft,y:e.pageYOffset||e.document.documentElement.scrollTop}:{x:e.scrollLeft,y:e.scrollTop}}},function(e,t,n){"use strict";var r=n(111),o=n(138),i=n(240),a=n(249),s=n(431),u=n(186),c=n(432),l=n(55),p={Component:a.injection,DOMProperty:r.injection,EmptyComponent:s.injection,EventPluginHub:o.injection,EventPluginUtils:i.injection,EventEmitter:u.injection,HostComponent:c.injection,Updates:l.injection};e.exports=p},function(e,t,n){"use strict";var r=n(25),o=n(419),i=n(88),a=n(186),s=n(436),u=(n(50),n(182)),c=n(253),l=[{initialize:s.getSelectionInformation,close:s.restoreSelection},{initialize:function(){var e=a.isEnabled();return a.setEnabled(!1),e},close:function(e){a.setEnabled(e)}},{initialize:function(){this.reactMountReady.reset()},close:function(){this.reactMountReady.notifyAll()}}];function p(e){this.reinitializeTransaction(),this.renderToStaticMarkup=!1,this.reactMountReady=o.getPooled(null),this.useCreateElement=e}var f={getTransactionWrappers:function(){return l},getReactMountReady:function(){return this.reactMountReady},getUpdateQueue:function(){return c},checkpoint:function(){return this.reactMountReady.checkpoint()},rollback:function(e){this.reactMountReady.rollback(e)},destructor:function(){o.release(this.reactMountReady),this.reactMountReady=null}};r(p.prototype,u,f),i.addPoolingTo(p),e.exports=p},function(e,t,n){"use strict";var r=n(36),o=n(853),i=n(418);function a(e,t,n,r){return e===n&&t===r}var s=r.canUseDOM&&"selection"in document&&!("getSelection"in window),u={getOffsets:s?function(e){var t=document.selection.createRange(),n=t.text.length,r=t.duplicate();r.moveToElementText(e),r.setEndPoint("EndToStart",t);var o=r.text.length;return{start:o,end:o+n}}:function(e){var t=window.getSelection&&window.getSelection();if(!t||0===t.rangeCount)return null;var n=t.anchorNode,r=t.anchorOffset,o=t.focusNode,i=t.focusOffset,s=t.getRangeAt(0);try{s.startContainer.nodeType,s.endContainer.nodeType}catch(e){return null}var u=a(t.anchorNode,t.anchorOffset,t.focusNode,t.focusOffset)?0:s.toString().length,c=s.cloneRange();c.selectNodeContents(e),c.setEnd(s.startContainer,s.startOffset);var l=a(c.startContainer,c.startOffset,c.endContainer,c.endOffset)?0:c.toString().length,p=l+u,f=document.createRange();f.setStart(n,r),f.setEnd(o,i);var h=f.collapsed;return{start:h?p:l,end:h?l:p}},setOffsets:s?function(e,t){var n,r,o=document.selection.createRange().duplicate();void 0===t.end?r=n=t.start:t.start>t.end?(n=t.end,r=t.start):(n=t.start,r=t.end),o.moveToElementText(e),o.moveStart("character",n),o.setEndPoint("EndToStart",o),o.moveEnd("character",r-n),o.select()}:function(e,t){if(window.getSelection){var n=window.getSelection(),r=e[i()].length,a=Math.min(t.start,r),s=void 0===t.end?a:Math.min(t.end,r);if(!n.extend&&a>s){var u=s;s=a,a=u}var c=o(e,a),l=o(e,s);if(c&&l){var p=document.createRange();p.setStart(c.node,c.offset),n.removeAllRanges(),a>s?(n.addRange(p),n.extend(l.node,l.offset)):(p.setEnd(l.node,l.offset),n.addRange(p))}}}};e.exports=u},function(e,t,n){"use strict";function r(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function o(e){for(;e;){if(e.nextSibling)return e.nextSibling;e=e.parentNode}}e.exports=function(e,t){for(var n=r(e),i=0,a=0;n;){if(3===n.nodeType){if(a=i+n.textContent.length,i<=t&&a>=t)return{node:n,offset:t-i};i=a}n=r(o(n))}}},function(e,t,n){"use strict";var r=n(855);e.exports=function e(t,n){return!(!t||!n)&&(t===n||!r(t)&&(r(n)?e(t,n.parentNode):"contains"in t?t.contains(n):!!t.compareDocumentPosition&&!!(16&t.compareDocumentPosition(n))))}},function(e,t,n){"use strict";var r=n(856);e.exports=function(e){return r(e)&&3==e.nodeType}},function(e,t,n){"use strict";e.exports=function(e){var t=(e?e.ownerDocument||e:document).defaultView||window;return!(!e||!("function"==typeof t.Node?e instanceof t.Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName))}},function(e,t,n){"use strict";var r="http://www.w3.org/1999/xlink",o="http://www.w3.org/XML/1998/namespace",i={accentHeight:"accent-height",accumulate:0,additive:0,alignmentBaseline:"alignment-baseline",allowReorder:"allowReorder",alphabetic:0,amplitude:0,arabicForm:"arabic-form",ascent:0,attributeName:"attributeName",attributeType:"attributeType",autoReverse:"autoReverse",azimuth:0,baseFrequency:"baseFrequency",baseProfile:"baseProfile",baselineShift:"baseline-shift",bbox:0,begin:0,bias:0,by:0,calcMode:"calcMode",capHeight:"cap-height",clip:0,clipPath:"clip-path",clipRule:"clip-rule",clipPathUnits:"clipPathUnits",colorInterpolation:"color-interpolation",colorInterpolationFilters:"color-interpolation-filters",colorProfile:"color-profile",colorRendering:"color-rendering",contentScriptType:"contentScriptType",contentStyleType:"contentStyleType",cursor:0,cx:0,cy:0,d:0,decelerate:0,descent:0,diffuseConstant:"diffuseConstant",direction:0,display:0,divisor:0,dominantBaseline:"dominant-baseline",dur:0,dx:0,dy:0,edgeMode:"edgeMode",elevation:0,enableBackground:"enable-background",end:0,exponent:0,externalResourcesRequired:"externalResourcesRequired",fill:0,fillOpacity:"fill-opacity",fillRule:"fill-rule",filter:0,filterRes:"filterRes",filterUnits:"filterUnits",floodColor:"flood-color",floodOpacity:"flood-opacity",focusable:0,fontFamily:"font-family",fontSize:"font-size",fontSizeAdjust:"font-size-adjust",fontStretch:"font-stretch",fontStyle:"font-style",fontVariant:"font-variant",fontWeight:"font-weight",format:0,from:0,fx:0,fy:0,g1:0,g2:0,glyphName:"glyph-name",glyphOrientationHorizontal:"glyph-orientation-horizontal",glyphOrientationVertical:"glyph-orientation-vertical",glyphRef:"glyphRef",gradientTransform:"gradientTransform",gradientUnits:"gradientUnits",hanging:0,horizAdvX:"horiz-adv-x",horizOriginX:"horiz-origin-x",ideographic:0,imageRendering:"image-rendering",in:0,in2:0,intercept:0,k:0,k1:0,k2:0,k3:0,k4:0,kernelMatrix:"kernelMatrix",kernelUnitLength:"kernelUnitLength",kerning:0,keyPoints:"keyPoints",keySplines:"keySplines",keyTimes:"keyTimes",lengthAdjust:"lengthAdjust",letterSpacing:"letter-spacing",lightingColor:"lighting-color",limitingConeAngle:"limitingConeAngle",local:0,markerEnd:"marker-end",markerMid:"marker-mid",markerStart:"marker-start",markerHeight:"markerHeight",markerUnits:"markerUnits",markerWidth:"markerWidth",mask:0,maskContentUnits:"maskContentUnits",maskUnits:"maskUnits",mathematical:0,mode:0,numOctaves:"numOctaves",offset:0,opacity:0,operator:0,order:0,orient:0,orientation:0,origin:0,overflow:0,overlinePosition:"overline-position",overlineThickness:"overline-thickness",paintOrder:"paint-order",panose1:"panose-1",pathLength:"pathLength",patternContentUnits:"patternContentUnits",patternTransform:"patternTransform",patternUnits:"patternUnits",pointerEvents:"pointer-events",points:0,pointsAtX:"pointsAtX",pointsAtY:"pointsAtY",pointsAtZ:"pointsAtZ",preserveAlpha:"preserveAlpha",preserveAspectRatio:"preserveAspectRatio",primitiveUnits:"primitiveUnits",r:0,radius:0,refX:"refX",refY:"refY",renderingIntent:"rendering-intent",repeatCount:"repeatCount",repeatDur:"repeatDur",requiredExtensions:"requiredExtensions",requiredFeatures:"requiredFeatures",restart:0,result:0,rotate:0,rx:0,ry:0,scale:0,seed:0,shapeRendering:"shape-rendering",slope:0,spacing:0,specularConstant:"specularConstant",specularExponent:"specularExponent",speed:0,spreadMethod:"spreadMethod",startOffset:"startOffset",stdDeviation:"stdDeviation",stemh:0,stemv:0,stitchTiles:"stitchTiles",stopColor:"stop-color",stopOpacity:"stop-opacity",strikethroughPosition:"strikethrough-position",strikethroughThickness:"strikethrough-thickness",string:0,stroke:0,strokeDasharray:"stroke-dasharray",strokeDashoffset:"stroke-dashoffset",strokeLinecap:"stroke-linecap",strokeLinejoin:"stroke-linejoin",strokeMiterlimit:"stroke-miterlimit",strokeOpacity:"stroke-opacity",strokeWidth:"stroke-width",surfaceScale:"surfaceScale",systemLanguage:"systemLanguage",tableValues:"tableValues",targetX:"targetX",targetY:"targetY",textAnchor:"text-anchor",textDecoration:"text-decoration",textRendering:"text-rendering",textLength:"textLength",to:0,transform:0,u1:0,u2:0,underlinePosition:"underline-position",underlineThickness:"underline-thickness",unicode:0,unicodeBidi:"unicode-bidi",unicodeRange:"unicode-range",unitsPerEm:"units-per-em",vAlphabetic:"v-alphabetic",vHanging:"v-hanging",vIdeographic:"v-ideographic",vMathematical:"v-mathematical",values:0,vectorEffect:"vector-effect",version:0,vertAdvY:"vert-adv-y",vertOriginX:"vert-origin-x",vertOriginY:"vert-origin-y",viewBox:"viewBox",viewTarget:"viewTarget",visibility:0,widths:0,wordSpacing:"word-spacing",writingMode:"writing-mode",x:0,xHeight:"x-height",x1:0,x2:0,xChannelSelector:"xChannelSelector",xlinkActuate:"xlink:actuate",xlinkArcrole:"xlink:arcrole",xlinkHref:"xlink:href",xlinkRole:"xlink:role",xlinkShow:"xlink:show",xlinkTitle:"xlink:title",xlinkType:"xlink:type",xmlBase:"xml:base",xmlns:0,xmlnsXlink:"xmlns:xlink",xmlLang:"xml:lang",xmlSpace:"xml:space",y:0,y1:0,y2:0,yChannelSelector:"yChannelSelector",z:0,zoomAndPan:"zoomAndPan"},a={Properties:{},DOMAttributeNamespaces:{xlinkActuate:r,xlinkArcrole:r,xlinkHref:r,xlinkRole:r,xlinkShow:r,xlinkTitle:r,xlinkType:r,xmlBase:o,xmlLang:o,xmlSpace:o},DOMAttributeNames:{}};Object.keys(i).forEach(function(e){a.Properties[e]=0,i[e]&&(a.DOMAttributeNames[e]=i[e])}),e.exports=a},function(e,t,n){"use strict";var r=n(137),o=n(36),i=n(27),a=n(436),s=n(64),u=n(437),c=n(422),l=n(250),p=o.canUseDOM&&"documentMode"in document&&document.documentMode<=11,f={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},dependencies:["topBlur","topContextMenu","topFocus","topKeyDown","topKeyUp","topMouseDown","topMouseUp","topSelectionChange"]}},h=null,d=null,m=null,v=!1,g=!1;function y(e,t){if(v||null==h||h!==u())return null;var n=function(e){if("selectionStart"in e&&a.hasSelectionCapabilities(e))return{start:e.selectionStart,end:e.selectionEnd};if(window.getSelection){var t=window.getSelection();return{anchorNode:t.anchorNode,anchorOffset:t.anchorOffset,focusNode:t.focusNode,focusOffset:t.focusOffset}}if(document.selection){var n=document.selection.createRange();return{parentElement:n.parentElement(),text:n.text,top:n.boundingTop,left:n.boundingLeft}}}(h);if(!m||!l(m,n)){m=n;var o=s.getPooled(f.select,d,e,t);return o.type="select",o.target=h,r.accumulateTwoPhaseDispatches(o),o}return null}var b={eventTypes:f,extractEvents:function(e,t,n,r){if(!g)return null;var o=t?i.getNodeFromInstance(t):window;switch(e){case"topFocus":(c(o)||"true"===o.contentEditable)&&(h=o,d=t,m=null);break;case"topBlur":h=null,d=null,m=null;break;case"topMouseDown":v=!0;break;case"topContextMenu":case"topMouseUp":return v=!1,y(n,r);case"topSelectionChange":if(p)break;case"topKeyDown":case"topKeyUp":return y(n,r)}return null},didPutListener:function(e,t,n){"onSelect"===t&&(g=!0)}};e.exports=b},function(e,t,n){"use strict";var r=n(21),o=n(435),i=n(137),a=n(27),s=n(860),u=n(861),c=n(64),l=n(862),p=n(863),f=n(183),h=n(865),d=n(866),m=n(867),v=n(139),g=n(868),y=n(54),b=n(255),_=(n(15),{}),w={};["abort","animationEnd","animationIteration","animationStart","blur","canPlay","canPlayThrough","click","contextMenu","copy","cut","doubleClick","drag","dragEnd","dragEnter","dragExit","dragLeave","dragOver","dragStart","drop","durationChange","emptied","encrypted","ended","error","focus","input","invalid","keyDown","keyPress","keyUp","load","loadedData","loadedMetadata","loadStart","mouseDown","mouseMove","mouseOut","mouseOver","mouseUp","paste","pause","play","playing","progress","rateChange","reset","scroll","seeked","seeking","stalled","submit","suspend","timeUpdate","touchCancel","touchEnd","touchMove","touchStart","transitionEnd","volumeChange","waiting","wheel"].forEach(function(e){var t=e[0].toUpperCase()+e.slice(1),n="on"+t,r="top"+t,o={phasedRegistrationNames:{bubbled:n,captured:n+"Capture"},dependencies:[r]};_[e]=o,w[r]=o});var x={};function E(e){return"."+e._rootNodeID}function S(e){return"button"===e||"input"===e||"select"===e||"textarea"===e}var C={eventTypes:_,extractEvents:function(e,t,n,o){var a,y=w[e];if(!y)return null;switch(e){case"topAbort":case"topCanPlay":case"topCanPlayThrough":case"topDurationChange":case"topEmptied":case"topEncrypted":case"topEnded":case"topError":case"topInput":case"topInvalid":case"topLoad":case"topLoadedData":case"topLoadedMetadata":case"topLoadStart":case"topPause":case"topPlay":case"topPlaying":case"topProgress":case"topRateChange":case"topReset":case"topSeeked":case"topSeeking":case"topStalled":case"topSubmit":case"topSuspend":case"topTimeUpdate":case"topVolumeChange":case"topWaiting":a=c;break;case"topKeyPress":if(0===b(n))return null;case"topKeyDown":case"topKeyUp":a=p;break;case"topBlur":case"topFocus":a=l;break;case"topClick":if(2===n.button)return null;case"topDoubleClick":case"topMouseDown":case"topMouseMove":case"topMouseUp":case"topMouseOut":case"topMouseOver":case"topContextMenu":a=f;break;case"topDrag":case"topDragEnd":case"topDragEnter":case"topDragExit":case"topDragLeave":case"topDragOver":case"topDragStart":case"topDrop":a=h;break;case"topTouchCancel":case"topTouchEnd":case"topTouchMove":case"topTouchStart":a=d;break;case"topAnimationEnd":case"topAnimationIteration":case"topAnimationStart":a=s;break;case"topTransitionEnd":a=m;break;case"topScroll":a=v;break;case"topWheel":a=g;break;case"topCopy":case"topCut":case"topPaste":a=u}a||r("86",e);var _=a.getPooled(y,t,n,o);return i.accumulateTwoPhaseDispatches(_),_},didPutListener:function(e,t,n){if("onClick"===t&&!S(e._tag)){var r=E(e),i=a.getNodeFromInstance(e);x[r]||(x[r]=o.listen(i,"click",y))}},willDeleteListener:function(e,t){if("onClick"===t&&!S(e._tag)){var n=E(e);x[n].remove(),delete x[n]}}};e.exports=C},function(e,t,n){"use strict";var r=n(64);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{animationName:null,elapsedTime:null,pseudoElement:null}),e.exports=o},function(e,t,n){"use strict";var r=n(64),o={clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}};function i(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(i,o),e.exports=i},function(e,t,n){"use strict";var r=n(139);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{relatedTarget:null}),e.exports=o},function(e,t,n){"use strict";var r=n(139),o=n(255),i={key:n(864),location:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,repeat:null,locale:null,getModifierState:n(244),charCode:function(e){return"keypress"===e.type?o(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?o(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}};function a(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(a,i),e.exports=a},function(e,t,n){"use strict";var r=n(255),o={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},i={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"};e.exports=function(e){if(e.key){var t=o[e.key]||e.key;if("Unidentified"!==t)return t}if("keypress"===e.type){var n=r(e);return 13===n?"Enter":String.fromCharCode(n)}return"keydown"===e.type||"keyup"===e.type?i[e.keyCode]||"Unidentified":""}},function(e,t,n){"use strict";var r=n(183);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{dataTransfer:null}),e.exports=o},function(e,t,n){"use strict";var r=n(139),o={touches:null,targetTouches:null,changedTouches:null,altKey:null,metaKey:null,ctrlKey:null,shiftKey:null,getModifierState:n(244)};function i(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(i,o),e.exports=i},function(e,t,n){"use strict";var r=n(64);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{propertyName:null,elapsedTime:null,pseudoElement:null}),e.exports=o},function(e,t,n){"use strict";var r=n(183);function o(e,t,n,o){return r.call(this,e,t,n,o)}r.augmentClass(o,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:null,deltaMode:null}),e.exports=o},function(e,t,n){"use strict";n(254);var r=9;e.exports=function(e,t){return{_topLevelWrapper:e,_idCounter:1,_ownerDocument:t?t.nodeType===r?t:t.ownerDocument:null,_node:t,_tag:t?t.nodeName.toLowerCase():null,_namespaceURI:t?t.namespaceURI:null}}},function(e,t,n){"use strict";e.exports={useCreateElement:!0,useFiber:!1}},function(e,t,n){"use strict";var r=n(872),o=/\/?>/,i=/^<\!\-\-/,a={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=r(e);return i.test(e)?e:e.replace(o," "+a.CHECKSUM_ATTR_NAME+'="'+t+'"$&')},canReuseMarkup:function(e,t){var n=t.getAttribute(a.CHECKSUM_ATTR_NAME);return n=n&&parseInt(n,10),r(e)===n}};e.exports=a},function(e,t,n){"use strict";var r=65521;e.exports=function(e){for(var t=1,n=0,o=0,i=e.length,a=-4&i;o<a;){for(var s=Math.min(o+4096,a);o<s;o+=4)n+=(t+=e.charCodeAt(o))+(t+=e.charCodeAt(o+1))+(t+=e.charCodeAt(o+2))+(t+=e.charCodeAt(o+3));t%=r,n%=r}for(;o<i;o++)n+=t+=e.charCodeAt(o);return(t%=r)|(n%=r)<<16}},function(e,t,n){"use strict";e.exports="15.6.2"},function(e,t,n){"use strict";var r=n(21),o=(n(62),n(27)),i=n(140),a=n(439);n(15),n(23);e.exports=function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=i.get(e);if(t)return(t=a(t))?o.getNodeFromInstance(t):null;"function"==typeof e.render?r("44"):r("45",Object.keys(e))}},function(e,t,n){"use strict";var r=n(438);e.exports=r.renderSubtreeIntoContainer},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r=n(0),o=a(n(440)),i=a(n(441));a(n(442));function a(e){return e&&e.__esModule?e:{default:e}}var s=function(e){function t(n,r){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var o=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.call(this,n,r));return o.store=n.store,o}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.prototype.getChildContext=function(){return{store:this.store}},t.prototype.render=function(){return r.Children.only(this.props.children)},t}(r.Component);t.default=s,s.propTypes={store:i.default.isRequired,children:o.default.element.isRequired},s.childContextTypes={store:i.default.isRequired}},function(e,t,n){"use strict";var r=n(878);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return n.PropTypes=n,n}},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";t.__esModule=!0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e};t.default=function(e,t,n){var l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},v=Boolean(e),g=e||p,y=void 0;y="function"==typeof t?t:t?(0,s.default)(t):f;var b=n||h,_=l.pure,w=void 0===_||_,x=l.withRef,E=void 0!==x&&x,S=w&&b!==h,C=m++;return function(e){var t="Connect("+function(e){return e.displayName||e.name||"Component"}(e)+")";var n=function(n){function i(e,r){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,i);var o=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,n.call(this,e,r));o.version=C,o.store=e.store||r.store,(0,c.default)(o.store,'Could not find "store" in either the context or props of "'+t+'". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "'+t+'".');var a=o.store.getState();return o.state={storeState:a},o.clearCache(),o}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(i,n),i.prototype.shouldComponentUpdate=function(){return!w||this.haveOwnPropsChanged||this.hasStoreStateChanged},i.prototype.computeStateProps=function(e,t){if(!this.finalMapStateToProps)return this.configureFinalMapState(e,t);var n=e.getState(),r=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(n,t):this.finalMapStateToProps(n);return r},i.prototype.configureFinalMapState=function(e,t){var n=g(e.getState(),t),r="function"==typeof n;return this.finalMapStateToProps=r?n:g,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,r?this.computeStateProps(e,t):n},i.prototype.computeDispatchProps=function(e,t){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(e,t);var n=e.dispatch,r=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(n,t):this.finalMapDispatchToProps(n);return r},i.prototype.configureFinalMapDispatch=function(e,t){var n=y(e.dispatch,t),r="function"==typeof n;return this.finalMapDispatchToProps=r?n:y,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,r?this.computeDispatchProps(e,t):n},i.prototype.updateStatePropsIfNeeded=function(){var e=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,a.default)(e,this.stateProps))&&(this.stateProps=e,!0)},i.prototype.updateDispatchPropsIfNeeded=function(){var e=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,a.default)(e,this.dispatchProps))&&(this.dispatchProps=e,!0)},i.prototype.updateMergedPropsIfNeeded=function(){var e=function(e,t,n){0;return b(e,t,n)}(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&S&&(0,a.default)(e,this.mergedProps))&&(this.mergedProps=e,!0)},i.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},i.prototype.trySubscribe=function(){v&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},i.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},i.prototype.componentDidMount=function(){this.trySubscribe()},i.prototype.componentWillReceiveProps=function(e){w&&(0,a.default)(e,this.props)||(this.haveOwnPropsChanged=!0)},i.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},i.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},i.prototype.handleChange=function(){if(this.unsubscribe){var e=this.store.getState(),t=this.state.storeState;if(!w||t!==e){if(w&&!this.doStatePropsDependOnOwnProps){var n=function(e,t){try{return e.apply(t)}catch(e){return d.value=e,d}}(this.updateStatePropsIfNeeded,this);if(!n)return;n===d&&(this.statePropsPrecalculationError=d.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:e})}}},i.prototype.getWrappedInstance=function(){return(0,c.default)(E,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},i.prototype.render=function(){var t=this.haveOwnPropsChanged,n=this.hasStoreStateChanged,i=this.haveStatePropsBeenPrecalculated,a=this.statePropsPrecalculationError,s=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,a)throw a;var u=!0,c=!0;w&&s&&(u=n||t&&this.doStatePropsDependOnOwnProps,c=t&&this.doDispatchPropsDependOnOwnProps);var l=!1,p=!1;i?l=!0:u&&(l=this.updateStatePropsIfNeeded()),c&&(p=this.updateDispatchPropsIfNeeded());return!(!!(l||p||t)&&this.updateMergedPropsIfNeeded())&&s?s:(this.renderedElement=E?(0,o.createElement)(e,r({},this.mergedProps,{ref:"wrappedInstance"})):(0,o.createElement)(e,this.mergedProps),this.renderedElement)},i}(o.Component);return n.displayName=t,n.WrappedComponent=e,n.contextTypes={store:i.default},n.propTypes={store:i.default},(0,u.default)(n,e)}};var o=n(0),i=l(n(441)),a=l(n(880)),s=l(n(881)),u=(l(n(442)),l(n(256)),l(n(882))),c=l(n(883));function l(e){return e&&e.__esModule?e:{default:e}}var p=function(e){return{}},f=function(e){return{dispatch:e}},h=function(e,t,n){return r({},n,e,t)};var d={value:null};var m=0},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){if(e===t)return!0;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(var o=Object.prototype.hasOwnProperty,i=0;i<n.length;i++)if(!o.call(t,n[i])||e[n[i]]!==t[n[i]])return!1;return!0}},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e){return function(t){return(0,r.bindActionCreators)(e,t)}};var r=n(120)},function(e,t,n){"use strict";var r=n(357),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},i={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},a={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function u(e){return r.isMemo(e)?a:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0};var c=Object.defineProperty,l=Object.getOwnPropertyNames,p=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,h=Object.getPrototypeOf,d=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(d){var o=h(n);o&&o!==d&&e(t,o,r)}var a=l(n);p&&(a=a.concat(p(n)));for(var s=u(t),m=u(n),v=0;v<a.length;++v){var g=a[v];if(!(i[g]||r&&r[g]||m&&m[g]||s&&s[g])){var y=f(n,g);try{c(t,g,y)}catch(e){}}}return t}return t}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o,i,a,s){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,i,a,s],l=0;(u=new Error(t.replace(/%s/g,function(){return c[l++]}))).name="Invariant Violation"}throw u.framesToPop=1,u}}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r&&!1!==t(e[n],n,e););return e}},function(e,t,n){var r=n(114),o=n(83);e.exports=function(e,t){return e&&r(t,o(t),e)}},function(e,t,n){var r=n(114),o=n(444);e.exports=function(e,t){return e&&r(t,o(t),e)}},function(e,t,n){var r=n(49),o=n(171),i=n(888),a=Object.prototype.hasOwnProperty;e.exports=function(e){if(!r(e))return i(e);var t=o(e),n=[];for(var s in e)("constructor"!=s||!t&&a.call(e,s))&&n.push(s);return n}},function(e,t){e.exports=function(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}},function(e,t,n){(function(e){var r=n(48),o=t&&!t.nodeType&&t,i=o&&"object"==typeof e&&e&&!e.nodeType&&e,a=i&&i.exports===o?r.Buffer:void 0,s=a?a.allocUnsafe:void 0;e.exports=function(e,t){if(t)return e.slice();var n=e.length,r=s?s(n):new e.constructor(n);return e.copy(r),r}}).call(this,n(169)(e))},function(e,t){e.exports=function(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n<r;)t[n]=e[n];return t}},function(e,t,n){var r=n(114),o=n(222);e.exports=function(e,t){return r(e,o(e),t)}},function(e,t,n){var r=n(114),o=n(445);e.exports=function(e,t){return r(e,o(e),t)}},function(e,t){var n=Object.prototype.hasOwnProperty;e.exports=function(e){var t=e.length,r=new e.constructor(t);return t&&"string"==typeof e[0]&&n.call(e,"index")&&(r.index=e.index,r.input=e.input),r}},function(e,t,n){var r=n(258),o=n(895),i=n(896),a=n(897),s=n(898),u="[object Boolean]",c="[object Date]",l="[object Map]",p="[object Number]",f="[object RegExp]",h="[object Set]",d="[object String]",m="[object Symbol]",v="[object ArrayBuffer]",g="[object DataView]",y="[object Float32Array]",b="[object Float64Array]",_="[object Int8Array]",w="[object Int16Array]",x="[object Int32Array]",E="[object Uint8Array]",S="[object Uint8ClampedArray]",C="[object Uint16Array]",k="[object Uint32Array]";e.exports=function(e,t,n){var O=e.constructor;switch(t){case v:return r(e);case u:case c:return new O(+e);case g:return o(e,n);case y:case b:case _:case w:case x:case E:case S:case C:case k:return s(e,n);case l:return new O;case p:case d:return new O(e);case f:return i(e);case h:return new O;case m:return a(e)}}},function(e,t,n){var r=n(258);e.exports=function(e,t){var n=t?r(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}},function(e,t){var n=/\w*$/;e.exports=function(e){var t=new e.constructor(e.source,n.exec(e));return t.lastIndex=e.lastIndex,t}},function(e,t,n){var r=n(102),o=r?r.prototype:void 0,i=o?o.valueOf:void 0;e.exports=function(e){return i?Object(i.call(e)):{}}},function(e,t,n){var r=n(258);e.exports=function(e,t){var n=t?r(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}},function(e,t,n){var r=n(900),o=n(257),i=n(171);e.exports=function(e){return"function"!=typeof e.constructor||i(e)?{}:r(o(e))}},function(e,t,n){var r=n(49),o=Object.create,i=function(){function e(){}return function(t){if(!r(t))return{};if(o)return o(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();e.exports=i},function(e,t,n){var r=n(902),o=n(226),i=n(227),a=i&&i.isMap,s=a?o(a):r;e.exports=s},function(e,t,n){var r=n(172),o=n(63),i="[object Map]";e.exports=function(e){return o(e)&&r(e)==i}},function(e,t,n){var r=n(904),o=n(226),i=n(227),a=i&&i.isSet,s=a?o(a):r;e.exports=s},function(e,t,n){var r=n(172),o=n(63),i="[object Set]";e.exports=function(e){return o(e)&&r(e)==i}},function(e,t,n){var r=n(104),o=n(906),i=n(907),a=n(105);e.exports=function(e,t){return t=r(t,e),null==(e=i(e,t))||delete e[a(o(t))]}},function(e,t){e.exports=function(e){var t=null==e?0:e.length;return t?e[t-1]:void 0}},function(e,t,n){var r=n(173),o=n(363);e.exports=function(e,t){return t.length<2?e:r(e,o(t,0,-1))}},function(e,t,n){var r=n(256);e.exports=function(e){return r(e)?void 0:e}},function(e,t,n){var r=n(910);e.exports=function(e){return null!=e&&e.length?r(e,1):[]}},function(e,t,n){var r=n(221),o=n(911);e.exports=function e(t,n,i,a,s){var u=-1,c=t.length;for(i||(i=o),s||(s=[]);++u<c;){var l=t[u];n>0&&i(l)?n>1?e(l,n-1,i,a,s):r(s,l):a||(s[s.length]=l)}return s}},function(e,t,n){var r=n(102),o=n(223),i=n(35),a=r?r.isConcatSpreadable:void 0;e.exports=function(e){return i(e)||o(e)||!!(a&&e&&e[a])}},function(e,t){e.exports=function(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}},function(e,t,n){var r=n(914),o=n(412),i=n(229),a=o?function(e,t){return o(e,"toString",{configurable:!0,enumerable:!1,value:r(t),writable:!0})}:i;e.exports=a},function(e,t){e.exports=function(e){return function(){return e}}},function(e,t){var n=800,r=16,o=Date.now;e.exports=function(e){var t=0,i=0;return function(){var a=o(),s=r-(a-i);if(i=a,s>0){if(++t>=n)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}},function(e,t,n){"use strict";var r=n(917),o=n(918);function i(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}t.parse=b,t.resolve=function(e,t){return b(e,!1,!0).resolve(t)},t.resolveObject=function(e,t){return e?b(e,!1,!0).resolveObject(t):t},t.format=function(e){o.isString(e)&&(e=b(e));return e instanceof i?e.format():i.prototype.format.call(e)},t.Url=i;var a=/^([a-z0-9.+-]+:)/i,s=/:[0-9]*$/,u=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,c=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),l=["'"].concat(c),p=["%","/","?",";","#"].concat(l),f=["/","?","#"],h=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,m={javascript:!0,"javascript:":!0},v={javascript:!0,"javascript:":!0},g={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},y=n(919);function b(e,t,n){if(e&&o.isObject(e)&&e instanceof i)return e;var r=new i;return r.parse(e,t,n),r}i.prototype.parse=function(e,t,n){if(!o.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var i=e.indexOf("?"),s=-1!==i&&i<e.indexOf("#")?"?":"#",c=e.split(s);c[0]=c[0].replace(/\\/g,"/");var b=e=c.join(s);if(b=b.trim(),!n&&1===e.split("#").length){var _=u.exec(b);if(_)return this.path=b,this.href=b,this.pathname=_[1],_[2]?(this.search=_[2],this.query=t?y.parse(this.search.substr(1)):this.search.substr(1)):t&&(this.search="",this.query={}),this}var w=a.exec(b);if(w){var x=(w=w[0]).toLowerCase();this.protocol=x,b=b.substr(w.length)}if(n||w||b.match(/^\/\/[^@\/]+@[^@\/]+/)){var E="//"===b.substr(0,2);!E||w&&v[w]||(b=b.substr(2),this.slashes=!0)}if(!v[w]&&(E||w&&!g[w])){for(var S,C,k=-1,O=0;O<f.length;O++){-1!==(A=b.indexOf(f[O]))&&(-1===k||A<k)&&(k=A)}-1!==(C=-1===k?b.lastIndexOf("@"):b.lastIndexOf("@",k))&&(S=b.slice(0,C),b=b.slice(C+1),this.auth=decodeURIComponent(S)),k=-1;for(O=0;O<p.length;O++){var A;-1!==(A=b.indexOf(p[O]))&&(-1===k||A<k)&&(k=A)}-1===k&&(k=b.length),this.host=b.slice(0,k),b=b.slice(k),this.parseHost(),this.hostname=this.hostname||"";var T="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!T)for(var j=this.hostname.split(/\./),P=(O=0,j.length);O<P;O++){var I=j[O];if(I&&!I.match(h)){for(var M="",N=0,R=I.length;N<R;N++)I.charCodeAt(N)>127?M+="x":M+=I[N];if(!M.match(h)){var D=j.slice(0,O),L=j.slice(O+1),U=I.match(d);U&&(D.push(U[1]),L.unshift(U[2])),L.length&&(b="/"+L.join(".")+b),this.hostname=D.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),T||(this.hostname=r.toASCII(this.hostname));var q=this.port?":"+this.port:"",F=this.hostname||"";this.host=F+q,this.href+=this.host,T&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==b[0]&&(b="/"+b))}if(!m[x])for(O=0,P=l.length;O<P;O++){var z=l[O];if(-1!==b.indexOf(z)){var B=encodeURIComponent(z);B===z&&(B=escape(z)),b=b.split(z).join(B)}}var V=b.indexOf("#");-1!==V&&(this.hash=b.substr(V),b=b.slice(0,V));var H=b.indexOf("?");if(-1!==H?(this.search=b.substr(H),this.query=b.substr(H+1),t&&(this.query=y.parse(this.query)),b=b.slice(0,H)):t&&(this.search="",this.query={}),b&&(this.pathname=b),g[x]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){q=this.pathname||"";var W=this.search||"";this.path=q+W}return this.href=this.format(),this},i.prototype.format=function(){var e=this.auth||"";e&&(e=(e=encodeURIComponent(e)).replace(/%3A/i,":"),e+="@");var t=this.protocol||"",n=this.pathname||"",r=this.hash||"",i=!1,a="";this.host?i=e+this.host:this.hostname&&(i=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(i+=":"+this.port)),this.query&&o.isObject(this.query)&&Object.keys(this.query).length&&(a=y.stringify(this.query));var s=this.search||a&&"?"+a||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||g[t])&&!1!==i?(i="//"+(i||""),n&&"/"!==n.charAt(0)&&(n="/"+n)):i||(i=""),r&&"#"!==r.charAt(0)&&(r="#"+r),s&&"?"!==s.charAt(0)&&(s="?"+s),t+i+(n=n.replace(/[?#]/g,function(e){return encodeURIComponent(e)}))+(s=s.replace("#","%23"))+r},i.prototype.resolve=function(e){return this.resolveObject(b(e,!1,!0)).format()},i.prototype.resolveObject=function(e){if(o.isString(e)){var t=new i;t.parse(e,!1,!0),e=t}for(var n=new i,r=Object.keys(this),a=0;a<r.length;a++){var s=r[a];n[s]=this[s]}if(n.hash=e.hash,""===e.href)return n.href=n.format(),n;if(e.slashes&&!e.protocol){for(var u=Object.keys(e),c=0;c<u.length;c++){var l=u[c];"protocol"!==l&&(n[l]=e[l])}return g[n.protocol]&&n.hostname&&!n.pathname&&(n.path=n.pathname="/"),n.href=n.format(),n}if(e.protocol&&e.protocol!==n.protocol){if(!g[e.protocol]){for(var p=Object.keys(e),f=0;f<p.length;f++){var h=p[f];n[h]=e[h]}return n.href=n.format(),n}if(n.protocol=e.protocol,e.host||v[e.protocol])n.pathname=e.pathname;else{for(var d=(e.pathname||"").split("/");d.length&&!(e.host=d.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==d[0]&&d.unshift(""),d.length<2&&d.unshift(""),n.pathname=d.join("/")}if(n.search=e.search,n.query=e.query,n.host=e.host||"",n.auth=e.auth,n.hostname=e.hostname||e.host,n.port=e.port,n.pathname||n.search){var m=n.pathname||"",y=n.search||"";n.path=m+y}return n.slashes=n.slashes||e.slashes,n.href=n.format(),n}var b=n.pathname&&"/"===n.pathname.charAt(0),_=e.host||e.pathname&&"/"===e.pathname.charAt(0),w=_||b||n.host&&e.pathname,x=w,E=n.pathname&&n.pathname.split("/")||[],S=(d=e.pathname&&e.pathname.split("/")||[],n.protocol&&!g[n.protocol]);if(S&&(n.hostname="",n.port=null,n.host&&(""===E[0]?E[0]=n.host:E.unshift(n.host)),n.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===d[0]?d[0]=e.host:d.unshift(e.host)),e.host=null),w=w&&(""===d[0]||""===E[0])),_)n.host=e.host||""===e.host?e.host:n.host,n.hostname=e.hostname||""===e.hostname?e.hostname:n.hostname,n.search=e.search,n.query=e.query,E=d;else if(d.length)E||(E=[]),E.pop(),E=E.concat(d),n.search=e.search,n.query=e.query;else if(!o.isNullOrUndefined(e.search)){if(S)n.hostname=n.host=E.shift(),(T=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=T.shift(),n.host=n.hostname=T.shift());return n.search=e.search,n.query=e.query,o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!E.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var C=E.slice(-1)[0],k=(n.host||e.host||E.length>1)&&("."===C||".."===C)||""===C,O=0,A=E.length;A>=0;A--)"."===(C=E[A])?E.splice(A,1):".."===C?(E.splice(A,1),O++):O&&(E.splice(A,1),O--);if(!w&&!x)for(;O--;O)E.unshift("..");!w||""===E[0]||E[0]&&"/"===E[0].charAt(0)||E.unshift(""),k&&"/"!==E.join("/").substr(-1)&&E.push("");var T,j=""===E[0]||E[0]&&"/"===E[0].charAt(0);S&&(n.hostname=n.host=j?"":E.length?E.shift():"",(T=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=T.shift(),n.host=n.hostname=T.shift()));return(w=w||n.host&&E.length)&&!j&&E.unshift(""),E.length?n.pathname=E.join("/"):(n.pathname=null,n.path=null),o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},i.prototype.parseHost=function(){var e=this.host,t=s.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){(function(e,r){var o;/*! https://mths.be/punycode v1.3.2 by @mathias */!function(i){t&&t.nodeType,e&&e.nodeType;var a="object"==typeof r&&r;a.global!==a&&a.window!==a&&a.self;var s,u=2147483647,c=36,l=1,p=26,f=38,h=700,d=72,m=128,v="-",g=/^xn--/,y=/[^\x20-\x7E]/,b=/[\x2E\u3002\uFF0E\uFF61]/g,_={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},w=c-l,x=Math.floor,E=String.fromCharCode;function S(e){throw RangeError(_[e])}function C(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function k(e,t){var n=e.split("@"),r="";return n.length>1&&(r=n[0]+"@",e=n[1]),r+C((e=e.replace(b,".")).split("."),t).join(".")}function O(e){for(var t,n,r=[],o=0,i=e.length;o<i;)(t=e.charCodeAt(o++))>=55296&&t<=56319&&o<i?56320==(64512&(n=e.charCodeAt(o++)))?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),o--):r.push(t);return r}function A(e){return C(e,function(e){var t="";return e>65535&&(t+=E((e-=65536)>>>10&1023|55296),e=56320|1023&e),t+=E(e)}).join("")}function T(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:c}function j(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function P(e,t,n){var r=0;for(e=n?x(e/h):e>>1,e+=x(e/t);e>w*p>>1;r+=c)e=x(e/w);return x(r+(w+1)*e/(e+f))}function I(e){var t,n,r,o,i,a,s,f,h,g,y=[],b=e.length,_=0,w=m,E=d;for((n=e.lastIndexOf(v))<0&&(n=0),r=0;r<n;++r)e.charCodeAt(r)>=128&&S("not-basic"),y.push(e.charCodeAt(r));for(o=n>0?n+1:0;o<b;){for(i=_,a=1,s=c;o>=b&&S("invalid-input"),((f=T(e.charCodeAt(o++)))>=c||f>x((u-_)/a))&&S("overflow"),_+=f*a,!(f<(h=s<=E?l:s>=E+p?p:s-E));s+=c)a>x(u/(g=c-h))&&S("overflow"),a*=g;E=P(_-i,t=y.length+1,0==i),x(_/t)>u-w&&S("overflow"),w+=x(_/t),_%=t,y.splice(_++,0,w)}return A(y)}function M(e){var t,n,r,o,i,a,s,f,h,g,y,b,_,w,C,k=[];for(b=(e=O(e)).length,t=m,n=0,i=d,a=0;a<b;++a)(y=e[a])<128&&k.push(E(y));for(r=o=k.length,o&&k.push(v);r<b;){for(s=u,a=0;a<b;++a)(y=e[a])>=t&&y<s&&(s=y);for(s-t>x((u-n)/(_=r+1))&&S("overflow"),n+=(s-t)*_,t=s,a=0;a<b;++a)if((y=e[a])<t&&++n>u&&S("overflow"),y==t){for(f=n,h=c;!(f<(g=h<=i?l:h>=i+p?p:h-i));h+=c)C=f-g,w=c-g,k.push(E(j(g+C%w,0))),f=x(C/w);k.push(E(j(f,0))),i=P(n,_,r==o),n=0,++r}++n,++t}return k.join("")}s={version:"1.3.2",ucs2:{decode:O,encode:A},decode:I,encode:M,toASCII:function(e){return k(e,function(e){return y.test(e)?"xn--"+M(e):e})},toUnicode:function(e){return k(e,function(e){return g.test(e)?I(e.slice(4).toLowerCase()):e})}},void 0===(o=function(){return s}.call(t,n,t,e))||(e.exports=o)}()}).call(this,n(169)(e),n(41))},function(e,t,n){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},function(e,t,n){"use strict";t.decode=t.parse=n(920),t.encode=t.stringify=n(921)},function(e,t,n){"use strict";function r(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,n,i){t=t||"&",n=n||"=";var a={};if("string"!=typeof e||0===e.length)return a;var s=/\+/g;e=e.split(t);var u=1e3;i&&"number"==typeof i.maxKeys&&(u=i.maxKeys);var c=e.length;u>0&&c>u&&(c=u);for(var l=0;l<c;++l){var p,f,h,d,m=e[l].replace(s,"%20"),v=m.indexOf(n);v>=0?(p=m.substr(0,v),f=m.substr(v+1)):(p=m,f=""),h=decodeURIComponent(p),d=decodeURIComponent(f),r(a,h)?o(a[h])?a[h].push(d):a[h]=[a[h],d]:a[h]=d}return a};var o=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var r=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,n,s){return t=t||"&",n=n||"=",null===e&&(e=void 0),"object"==typeof e?i(a(e),function(a){var s=encodeURIComponent(r(a))+n;return o(e[a])?i(e[a],function(e){return s+encodeURIComponent(r(e))}).join(t):s+encodeURIComponent(r(e[a]))}).join(t):s?encodeURIComponent(r(s))+n+encodeURIComponent(r(e)):""};var o=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};function i(e,t){if(e.map)return e.map(t);for(var n=[],r=0;r<e.length;r++)n.push(t(e[r],r));return n}var a=Object.keys||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t}},function(e,t,n){var r=n(181),o=n(114),i=n(923),a=n(103),s=n(171),u=n(83),c=Object.prototype.hasOwnProperty,l=i(function(e,t){if(s(t)||a(t))o(t,u(t),e);else for(var n in t)c.call(t,n)&&r(e,n,t[n])});e.exports=l},function(e,t,n){var r=n(924),o=n(384);e.exports=function(e){return r(function(t,n){var r=-1,i=n.length,a=i>1?n[i-1]:void 0,s=i>2?n[2]:void 0;for(a=e.length>3&&"function"==typeof a?(i--,a):void 0,s&&o(n[0],n[1],s)&&(a=i<3?void 0:a,i=1),t=Object(t);++r<i;){var u=n[r];u&&e(t,u,r,a)}return t})}},function(e,t,n){var r=n(229),o=n(448),i=n(449);e.exports=function(e,t){return i(o(e,t,r),e+"")}},function(e,t,n){
+/*!
+ * https://github.com/Starcounter-Jack/JSON-Patch
+ * (c) 2017 Joachim Wester
+ * MIT license
+ */
+var r=n(259),o=n(450),i=n(450);t.applyOperation=i.applyOperation,t.applyPatch=i.applyPatch,t.applyReducer=i.applyReducer,t.getValueByPointer=i.getValueByPointer,t.validate=i.validate,t.validator=i.validator;var a=n(259);t.JsonPatchError=a.PatchError,t.deepClone=a._deepClone,t.escapePathComponent=a.escapePathComponent,t.unescapePathComponent=a.unescapePathComponent;var s=new WeakMap,u=function(e){this.observers=new Map,this.obj=e},c=function(e,t){this.callback=e,this.observer=t};function l(e){var t=s.get(e.object);p(t.value,e.object,e.patches,""),e.patches.length&&o.applyPatch(t.value,e.patches);var n=e.patches;return n.length>0&&(e.patches=[],e.callback&&e.callback(n)),n}function p(e,t,n,o){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=r._objectKeys(t),a=r._objectKeys(e),s=!1,u=a.length-1;u>=0;u--){var c=e[f=a[u]];if(!r.hasOwnProperty(t,f)||void 0===t[f]&&void 0!==c&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(n.push({op:"remove",path:o+"/"+r.escapePathComponent(f)}),s=!0):(n.push({op:"replace",path:o,value:t}),!0);else{var l=t[f];"object"==typeof c&&null!=c&&"object"==typeof l&&null!=l?p(c,l,n,o+"/"+r.escapePathComponent(f)):c!==l&&(!0,n.push({op:"replace",path:o+"/"+r.escapePathComponent(f),value:r._deepClone(l)}))}}if(s||i.length!=a.length)for(u=0;u<i.length;u++){var f=i[u];r.hasOwnProperty(e,f)||void 0===t[f]||n.push({op:"add",path:o+"/"+r.escapePathComponent(f),value:r._deepClone(t[f])})}}}t.unobserve=function(e,t){t.unobserve()},t.observe=function(e,t){var n,o=function(e){return s.get(e)}(e);if(o){var i=function(e,t){return e.observers.get(t)}(o,t);n=i&&i.observer}else o=new u(e),s.set(e,o);if(n)return n;if(n={},o.value=r._deepClone(e),t){n.callback=t,n.next=null;var a=function(){l(n)},p=function(){clearTimeout(n.next),n.next=setTimeout(a)};"undefined"!=typeof window&&(window.addEventListener?(window.addEventListener("mouseup",p),window.addEventListener("keyup",p),window.addEventListener("mousedown",p),window.addEventListener("keydown",p),window.addEventListener("change",p)):(document.documentElement.attachEvent("onmouseup",p),document.documentElement.attachEvent("onkeyup",p),document.documentElement.attachEvent("onmousedown",p),document.documentElement.attachEvent("onkeydown",p),document.documentElement.attachEvent("onchange",p)))}return n.patches=[],n.object=e,n.unobserve=function(){l(n),clearTimeout(n.next),function(e,t){e.observers.delete(t.callback)}(o,n),"undefined"!=typeof window&&(window.removeEventListener?(window.removeEventListener("mouseup",p),window.removeEventListener("keyup",p),window.removeEventListener("mousedown",p),window.removeEventListener("keydown",p)):(document.documentElement.detachEvent("onmouseup",p),document.documentElement.detachEvent("onkeyup",p),document.documentElement.detachEvent("onmousedown",p),document.documentElement.detachEvent("onkeydown",p)))},o.observers.set(t,new c(t,n)),n},t.generate=l,t.compare=function(e,t){var n=[];return p(e,t,n,""),n}},function(e,t,n){var r=Array.prototype.slice,o=n(927),i=n(928),a=e.exports=function(e,t,n){return n||(n={}),e===t||(e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():!e||!t||"object"!=typeof e&&"object"!=typeof t?n.strict?e===t:e==t:function(e,t,n){var c,l;if(s(e)||s(t))return!1;if(e.prototype!==t.prototype)return!1;if(i(e))return!!i(t)&&(e=r.call(e),t=r.call(t),a(e,t,n));if(u(e)){if(!u(t))return!1;if(e.length!==t.length)return!1;for(c=0;c<e.length;c++)if(e[c]!==t[c])return!1;return!0}try{var p=o(e),f=o(t)}catch(e){return!1}if(p.length!=f.length)return!1;for(p.sort(),f.sort(),c=p.length-1;c>=0;c--)if(p[c]!=f[c])return!1;for(c=p.length-1;c>=0;c--)if(l=p[c],!a(e[l],t[l],n))return!1;return typeof e==typeof t}(e,t,n))};function s(e){return null==e}function u(e){return!(!e||"object"!=typeof e||"number"!=typeof e.length)&&("function"==typeof e.copy&&"function"==typeof e.slice&&!(e.length>0&&"number"!=typeof e[0]))}},function(e,t){function n(e){var t=[];for(var n in e)t.push(n);return t}(e.exports="function"==typeof Object.keys?Object.keys:n).shim=n},function(e,t){var n="[object Arguments]"==function(){return Object.prototype.toString.call(arguments)}();function r(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function o(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Object.prototype.hasOwnProperty.call(e,"callee")&&!Object.prototype.propertyIsEnumerable.call(e,"callee")||!1}(t=e.exports=n?r:o).supported=r,t.unsupported=o},function(e,t,n){(function(t){!function(){"use strict";e.exports=function(e){return(e instanceof t?e:new t(e.toString(),"binary")).toString("base64")}}()}).call(this,n(61).Buffer)},function(e,t,n){var r=n(931),o=n(360),i=n(381),a=n(65);e.exports=function(e,t,n){return e=a(e),n=null==n?0:r(i(n),0,e.length),t=o(t),e.slice(n,n+t.length)==t}},function(e,t){e.exports=function(e,t,n){return e==e&&(void 0!==n&&(e=e<=n?e:n),void 0!==t&&(e=e>=t?e:t)),e}},function(e,t,n){"use strict";var r=n(933),o=n(934),i=n(452);e.exports={formats:i,parse:o,stringify:r}},function(e,t,n){"use strict";var r=n(451),o=n(452),i=Object.prototype.hasOwnProperty,a={brackets:function(e){return e+"[]"},comma:"comma",indices:function(e,t){return e+"["+t+"]"},repeat:function(e){return e}},s=Array.isArray,u=Array.prototype.push,c=function(e,t){u.apply(e,s(t)?t:[t])},l=Date.prototype.toISOString,p={addQueryPrefix:!1,allowDots:!1,charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encoder:r.encode,encodeValuesOnly:!1,formatter:o.formatters[o.default],indices:!1,serializeDate:function(e){return l.call(e)},skipNulls:!1,strictNullHandling:!1},f=function e(t,n,o,i,a,u,l,f,h,d,m,v,g){var y=t;if("function"==typeof l?y=l(n,y):y instanceof Date?y=d(y):"comma"===o&&s(y)&&(y=y.join(",")),null===y){if(i)return u&&!v?u(n,p.encoder,g):n;y=""}if("string"==typeof y||"number"==typeof y||"boolean"==typeof y||r.isBuffer(y))return u?[m(v?n:u(n,p.encoder,g))+"="+m(u(y,p.encoder,g))]:[m(n)+"="+m(String(y))];var b,_=[];if(void 0===y)return _;if(s(l))b=l;else{var w=Object.keys(y);b=f?w.sort(f):w}for(var x=0;x<b.length;++x){var E=b[x];a&&null===y[E]||(s(y)?c(_,e(y[E],"function"==typeof o?o(n,E):n,o,i,a,u,l,f,h,d,m,v,g)):c(_,e(y[E],n+(h?"."+E:"["+E+"]"),o,i,a,u,l,f,h,d,m,v,g)))}return _};e.exports=function(e,t){var n,r=e,u=function(e){if(!e)return p;if(null!==e.encoder&&void 0!==e.encoder&&"function"!=typeof e.encoder)throw new TypeError("Encoder has to be a function.");var t=e.charset||p.charset;if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var n=o.default;if(void 0!==e.format){if(!i.call(o.formatters,e.format))throw new TypeError("Unknown format option provided.");n=e.format}var r=o.formatters[n],a=p.filter;return("function"==typeof e.filter||s(e.filter))&&(a=e.filter),{addQueryPrefix:"boolean"==typeof e.addQueryPrefix?e.addQueryPrefix:p.addQueryPrefix,allowDots:void 0===e.allowDots?p.allowDots:!!e.allowDots,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:p.charsetSentinel,delimiter:void 0===e.delimiter?p.delimiter:e.delimiter,encode:"boolean"==typeof e.encode?e.encode:p.encode,encoder:"function"==typeof e.encoder?e.encoder:p.encoder,encodeValuesOnly:"boolean"==typeof e.encodeValuesOnly?e.encodeValuesOnly:p.encodeValuesOnly,filter:a,formatter:r,serializeDate:"function"==typeof e.serializeDate?e.serializeDate:p.serializeDate,skipNulls:"boolean"==typeof e.skipNulls?e.skipNulls:p.skipNulls,sort:"function"==typeof e.sort?e.sort:null,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:p.strictNullHandling}}(t);"function"==typeof u.filter?r=(0,u.filter)("",r):s(u.filter)&&(n=u.filter);var l,h=[];if("object"!=typeof r||null===r)return"";l=t&&t.arrayFormat in a?t.arrayFormat:t&&"indices"in t?t.indices?"indices":"repeat":"indices";var d=a[l];n||(n=Object.keys(r)),u.sort&&n.sort(u.sort);for(var m=0;m<n.length;++m){var v=n[m];u.skipNulls&&null===r[v]||c(h,f(r[v],v,d,u.strictNullHandling,u.skipNulls,u.encode?u.encoder:null,u.filter,u.sort,u.allowDots,u.serializeDate,u.formatter,u.encodeValuesOnly,u.charset))}var g=h.join(u.delimiter),y=!0===u.addQueryPrefix?"?":"";return u.charsetSentinel&&("iso-8859-1"===u.charset?y+="utf8=%26%2310003%3B&":y+="utf8=%E2%9C%93&"),g.length>0?y+g:""}},function(e,t,n){"use strict";var r=n(451),o=Object.prototype.hasOwnProperty,i={allowDots:!1,allowPrototypes:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decoder:r.decode,delimiter:"&",depth:5,ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictNullHandling:!1},a=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},s=function(e,t,n){if(e){var r=n.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e,i=/(\[[^[\]]*])/g,a=/(\[[^[\]]*])/.exec(r),s=a?r.slice(0,a.index):r,u=[];if(s){if(!n.plainObjects&&o.call(Object.prototype,s)&&!n.allowPrototypes)return;u.push(s)}for(var c=0;null!==(a=i.exec(r))&&c<n.depth;){if(c+=1,!n.plainObjects&&o.call(Object.prototype,a[1].slice(1,-1))&&!n.allowPrototypes)return;u.push(a[1])}return a&&u.push("["+r.slice(a.index)+"]"),function(e,t,n){for(var r=t,o=e.length-1;o>=0;--o){var i,a=e[o];if("[]"===a&&n.parseArrays)i=[].concat(r);else{i=n.plainObjects?Object.create(null):{};var s="["===a.charAt(0)&&"]"===a.charAt(a.length-1)?a.slice(1,-1):a,u=parseInt(s,10);n.parseArrays||""!==s?!isNaN(u)&&a!==s&&String(u)===s&&u>=0&&n.parseArrays&&u<=n.arrayLimit?(i=[])[u]=r:i[s]=r:i={0:r}}r=i}return r}(u,t,n)}};e.exports=function(e,t){var n=function(e){if(!e)return i;if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new Error("The charset option must be either utf-8, iso-8859-1, or undefined");var t=void 0===e.charset?i.charset:e.charset;return{allowDots:void 0===e.allowDots?i.allowDots:!!e.allowDots,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:i.allowPrototypes,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:i.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:i.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:i.comma,decoder:"function"==typeof e.decoder?e.decoder:i.decoder,delimiter:"string"==typeof e.delimiter||r.isRegExp(e.delimiter)?e.delimiter:i.delimiter,depth:"number"==typeof e.depth?e.depth:i.depth,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:i.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:i.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:i.plainObjects,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:i.strictNullHandling}}(t);if(""===e||null==e)return n.plainObjects?Object.create(null):{};for(var u="string"==typeof e?function(e,t){var n,s={},u=t.ignoreQueryPrefix?e.replace(/^\?/,""):e,c=t.parameterLimit===1/0?void 0:t.parameterLimit,l=u.split(t.delimiter,c),p=-1,f=t.charset;if(t.charsetSentinel)for(n=0;n<l.length;++n)0===l[n].indexOf("utf8=")&&("utf8=%E2%9C%93"===l[n]?f="utf-8":"utf8=%26%2310003%3B"===l[n]&&(f="iso-8859-1"),p=n,n=l.length);for(n=0;n<l.length;++n)if(n!==p){var h,d,m=l[n],v=m.indexOf("]="),g=-1===v?m.indexOf("="):v+1;-1===g?(h=t.decoder(m,i.decoder,f),d=t.strictNullHandling?null:""):(h=t.decoder(m.slice(0,g),i.decoder,f),d=t.decoder(m.slice(g+1),i.decoder,f)),d&&t.interpretNumericEntities&&"iso-8859-1"===f&&(d=a(d)),d&&t.comma&&d.indexOf(",")>-1&&(d=d.split(",")),o.call(s,h)?s[h]=r.combine(s[h],d):s[h]=d}return s}(e,n):e,c=n.plainObjects?Object.create(null):{},l=Object.keys(u),p=0;p<l.length;++p){var f=l[p],h=s(f,u[f],n);c=r.merge(c,h,n)}return r.compact(c)}},function(e,t,n){"use strict";var r=t,o=n(61).Buffer;function i(e,t){try{return decodeURIComponent(e)}catch(n){return r.unescapeBuffer(e,t).toString()}}r.unescapeBuffer=function(e,t){for(var n,r,i,a=new o(e.length),s=0,u=0,c=0;u<=e.length;u++){var l=u<e.length?e.charCodeAt(u):NaN;switch(s){case 0:switch(l){case 37:n=0,r=0,s=1;break;case 43:t&&(l=32);default:a[c++]=l}break;case 1:if(i=l,l>=48&&l<=57)n=l-48;else if(l>=65&&l<=70)n=l-65+10;else{if(!(l>=97&&l<=102)){a[c++]=37,a[c++]=l,s=0;break}n=l-97+10}s=2;break;case 2:if(s=0,l>=48&&l<=57)r=l-48;else if(l>=65&&l<=70)r=l-65+10;else{if(!(l>=97&&l<=102)){a[c++]=37,a[c++]=i,a[c++]=l;break}r=l-97+10}a[c++]=16*n+r}}return a.slice(0,c-1)},r.unescape=i;for(var a=new Array(256),s=0;s<256;++s)a[s]="%"+((s<16?"0":"")+s.toString(16)).toUpperCase();r.escape=function(e){"string"!=typeof e&&(e+="");for(var t="",n=0,r=0;r<e.length;++r){var o=e.charCodeAt(r);if(!(33===o||45===o||46===o||95===o||126===o||o>=39&&o<=42||o>=48&&o<=57||o>=65&&o<=90||o>=97&&o<=122))if(r-n>0&&(t+=e.slice(n,r)),o<128)n=r+1,t+=a[o];else if(o<2048)n=r+1,t+=a[192|o>>6]+a[128|63&o];else if(o<55296||o>=57344)n=r+1,t+=a[224|o>>12]+a[128|o>>6&63]+a[128|63&o];else{var i;if(!(++r<e.length))throw new URIError("URI malformed");i=1023&e.charCodeAt(r),n=r+1,t+=a[240|(o=65536+((1023&o)<<10|i))>>18]+a[128|o>>12&63]+a[128|o>>6&63]+a[128|63&o]}}return 0===n?e:n<e.length?t+e.slice(n):t};var u=function(e){return"string"==typeof e?e:"number"==typeof e&&isFinite(e)?""+e:"boolean"==typeof e?e?"true":"false":""};function c(e,t){try{return t(e)}catch(t){return r.unescape(e,!0)}}r.stringify=r.encode=function(e,t,n,o){t=t||"&",n=n||"=";var i=r.escape;if(o&&"function"==typeof o.encodeURIComponent&&(i=o.encodeURIComponent),null!==e&&"object"==typeof e){for(var a=Object.keys(e),s=a.length,c=s-1,l="",p=0;p<s;++p){var f=a[p],h=e[f],d=i(u(f))+n;if(Array.isArray(h)){for(var m=h.length,v=m-1,g=0;g<m;++g)l+=d+i(u(h[g])),g<v&&(l+=t);m&&p<c&&(l+=t)}else l+=d+i(u(h)),p<c&&(l+=t)}return l}return""},r.parse=r.decode=function(e,t,n,o){t=t||"&",n=n||"=";var a={};if("string"!=typeof e||0===e.length)return a;"string"!=typeof t&&(t+="");var s=n.length,u=t.length,l=1e3;o&&"number"==typeof o.maxKeys&&(l=o.maxKeys);var p=1/0;l>0&&(p=l);var f=r.unescape;o&&"function"==typeof o.decodeURIComponent&&(f=o.decodeURIComponent);for(var h=f!==i,d=[],m=0,v=0,g=0,y="",b="",_=h,w=h,x=0,E=0;E<e.length;++E){var S=e.charCodeAt(E);if(S!==t.charCodeAt(v)){if(v=0,w||(37===S?x=1:x>0&&(S>=48&&S<=57||S>=65&&S<=70||S>=97&&S<=102)?3==++x&&(w=!0):x=0),g<s){if(S===n.charCodeAt(g)){if(++g===s)m<(k=E-g+1)&&(y+=e.slice(m,k)),x=0,m=E+1;continue}g=0,_||(37===S?x=1:x>0&&(S>=48&&S<=57||S>=65&&S<=70||S>=97&&S<=102)?3==++x&&(_=!0):x=0)}43===S&&(g<s?(E-m>0&&(y+=e.slice(m,E)),y+="%20",_=!0):(E-m>0&&(b+=e.slice(m,E)),b+="%20",w=!0),m=E+1)}else if(++v===u){var C,k=E-v+1;if(g<s?m<k&&(y+=e.slice(m,k)):m<k&&(b+=e.slice(m,k)),_&&(y=c(y,f)),w&&(b=c(b,f)),-1===d.indexOf(y))a[y]=b,d[d.length]=y;else(C=a[y])instanceof Array?C[C.length]=b:a[y]=[C,b];if(0==--p)break;_=w=h,x=0,y=b="",m=E+1,v=g=0}}p>0&&(m<e.length||g>0)&&(m<e.length&&(g<s?y+=e.slice(m):v<u&&(b+=e.slice(m))),_&&(y=c(y,f)),w&&(b=c(b,f)),-1===d.indexOf(y)?(a[y]=b,d[d.length]=y):(C=a[y])instanceof Array?C[C.length]=b:a[y]=[C,b]);return a}},function(e,t,n){"use strict";(function(t){
+/*!
+ * @description Recursive object extending
+ * @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
+ * @license MIT
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2018 Viacheslav Lotsmanov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+function n(e){return e instanceof t||e instanceof Date||e instanceof RegExp}function r(e){if(e instanceof t){var n=t.alloc?t.alloc(e.length):new t(e.length);return e.copy(n),n}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return new RegExp(e);throw new Error("Unexpected situation")}function o(e){var t=[];return e.forEach(function(e,i){"object"==typeof e&&null!==e?Array.isArray(e)?t[i]=o(e):n(e)?t[i]=r(e):t[i]=a({},e):t[i]=e}),t}function i(e,t){return"__proto__"===t?void 0:e[t]}var a=e.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var e,t,s=arguments[0],u=Array.prototype.slice.call(arguments,1);return u.forEach(function(u){"object"!=typeof u||null===u||Array.isArray(u)||Object.keys(u).forEach(function(c){return t=i(s,c),(e=i(u,c))===s?void 0:"object"!=typeof e||null===e?void(s[c]=e):Array.isArray(e)?void(s[c]=o(e)):n(e)?void(s[c]=r(e)):"object"!=typeof t||null===t||Array.isArray(t)?void(s[c]=a({},e)):void(s[c]=a(t,e))})}),s}}).call(this,n(61).Buffer)},function(e,t,n){e.exports=n(938)},function(e,t,n){n(160),n(99),n(939),n(943),n(944),e.exports=n(22).WeakMap},function(e,t,n){"use strict";var r,o=n(32),i=n(260)(0),a=n(212),s=n(132),u=n(351),c=n(942),l=n(40),p=n(141),f=n(141),h=!o.ActiveXObject&&"ActiveXObject"in o,d=s.getWeak,m=Object.isExtensible,v=c.ufstore,g=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},y={get:function(e){if(l(e)){var t=d(e);return!0===t?v(p(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return c.def(p(this,"WeakMap"),e,t)}},b=e.exports=n(453)("WeakMap",g,y,c,!0,!0);f&&h&&(u((r=c.getConstructor(g,"WeakMap")).prototype,y),s.NEED=!0,i(["delete","has","get","set"],function(e){var t=b.prototype,n=t[e];a(t,e,function(t,o){if(l(t)&&!m(t)){this._f||(this._f=new r);var i=this._f[e](t,o);return"set"==e?this:i}return n.call(this,t,o)})}))},function(e,t,n){var r=n(941);e.exports=function(e,t){return new(r(e))(t)}},function(e,t,n){var r=n(40),o=n(215),i=n(34)("species");e.exports=function(e){var t;return o(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!o(t.prototype)||(t=void 0),r(t)&&null===(t=t[i])&&(t=void 0)),void 0===t?Array:t}},function(e,t,n){"use strict";var r=n(179),o=n(132).getWeak,i=n(44),a=n(40),s=n(178),u=n(108),c=n(260),l=n(69),p=n(141),f=c(5),h=c(6),d=0,m=function(e){return e._l||(e._l=new v)},v=function(){this.a=[]},g=function(e,t){return f(e.a,function(e){return e[0]===t})};v.prototype={get:function(e){var t=g(this,e);if(t)return t[1]},has:function(e){return!!g(this,e)},set:function(e,t){var n=g(this,e);n?n[1]=t:this.a.push([e,t])},delete:function(e){var t=h(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,i){var c=e(function(e,r){s(e,c,t,"_i"),e._t=t,e._i=d++,e._l=void 0,null!=r&&u(r,n,e[i],e)});return r(c.prototype,{delete:function(e){if(!a(e))return!1;var n=o(e);return!0===n?m(p(this,t)).delete(e):n&&l(n,this._i)&&delete n[this._i]},has:function(e){if(!a(e))return!1;var n=o(e);return!0===n?m(p(this,t)).has(e):n&&l(n,this._i)}}),c},def:function(e,t,n){var r=o(i(t),!0);return!0===r?m(e).set(t,n):r[e._i]=n,e},ufstore:m}},function(e,t,n){n(454)("WeakMap")},function(e,t,n){n(455)("WeakMap")},function(e,t){var n={};!function(e){"use strict";function t(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function n(e){return"string"!=typeof e&&(e=String(e)),e}function r(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return d.iterable&&(t[Symbol.iterator]=function(){return t}),t}function o(e){this.map={},e instanceof o?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function i(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function a(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function s(e){var t=new FileReader,n=a(t);return t.readAsArrayBuffer(e),n}function u(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function c(){return this.bodyUsed=!1,this._initBody=function(e){if(this._bodyInit=e,e)if("string"==typeof e)this._bodyText=e;else if(d.blob&&Blob.prototype.isPrototypeOf(e))this._bodyBlob=e;else if(d.formData&&FormData.prototype.isPrototypeOf(e))this._bodyFormData=e;else if(d.searchParams&&URLSearchParams.prototype.isPrototypeOf(e))this._bodyText=e.toString();else if(d.arrayBuffer&&d.blob&&v(e))this._bodyArrayBuffer=u(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else{if(!d.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(e)&&!g(e))throw new Error("unsupported BodyInit type");this._bodyArrayBuffer=u(e)}else this._bodyText="";this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):d.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},d.blob&&(this.blob=function(){var e=i(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?i(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(s)}),this.text=function(){var e=i(this);if(e)return e;if(this._bodyBlob)return function(e){var t=new FileReader,n=a(t);return t.readAsText(e),n}(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(function(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r<t.length;r++)n[r]=String.fromCharCode(t[r]);return n.join("")}(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},d.formData&&(this.formData=function(){return this.text().then(p)}),this.json=function(){return this.text().then(JSON.parse)},this}function l(e,t){var n=(t=t||{}).body;if(e instanceof l){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new o(e.headers)),this.method=e.method,this.mode=e.mode,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"omit",!t.headers&&this.headers||(this.headers=new o(t.headers)),this.method=function(e){var t=e.toUpperCase();return y.indexOf(t)>-1?t:e}(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function p(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),o=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(o))}}),t}function f(e){var t=new o;return e.split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var o=n.join(":").trim();t.append(r,o)}}),t}function h(e,t){t||(t={}),this.type="default",this.status="status"in t?t.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new o(t.headers),this.url=t.url||"",this._initBody(e)}if(!e.fetch){var d={searchParams:"URLSearchParams"in e,iterable:"Symbol"in e&&"iterator"in Symbol,blob:"FileReader"in e&&"Blob"in e&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in e,arrayBuffer:"ArrayBuffer"in e};if(d.arrayBuffer)var m=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],v=function(e){return e&&DataView.prototype.isPrototypeOf(e)},g=ArrayBuffer.isView||function(e){return e&&m.indexOf(Object.prototype.toString.call(e))>-1};o.prototype.append=function(e,r){e=t(e),r=n(r);var o=this.map[e];this.map[e]=o?o+","+r:r},o.prototype.delete=function(e){delete this.map[t(e)]},o.prototype.get=function(e){return e=t(e),this.has(e)?this.map[e]:null},o.prototype.has=function(e){return this.map.hasOwnProperty(t(e))},o.prototype.set=function(e,r){this.map[t(e)]=n(r)},o.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},o.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),r(e)},o.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),r(e)},o.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),r(e)},d.iterable&&(o.prototype[Symbol.iterator]=o.prototype.entries);var y=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];l.prototype.clone=function(){return new l(this,{body:this._bodyInit})},c.call(l.prototype),c.call(h.prototype),h.prototype.clone=function(){return new h(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new o(this.headers),url:this.url})},h.error=function(){var e=new h(null,{status:0,statusText:""});return e.type="error",e};var b=[301,302,303,307,308];h.redirect=function(e,t){if(-1===b.indexOf(t))throw new RangeError("Invalid status code");return new h(null,{status:t,headers:{location:e}})},e.Headers=o,e.Request=l,e.Response=h,e.fetch=function(e,t){return new Promise(function(n,r){var o=new l(e,t),i=new XMLHttpRequest;i.onload=function(){var e={status:i.status,statusText:i.statusText,headers:f(i.getAllResponseHeaders()||"")};e.url="responseURL"in i?i.responseURL:e.headers.get("X-Request-URL");var t="response"in i?i.response:i.responseText;n(new h(t,e))},i.onerror=function(){r(new TypeError("Network request failed"))},i.ontimeout=function(){r(new TypeError("Network request failed"))},i.open(o.method,o.url,!0),"include"===o.credentials&&(i.withCredentials=!0),"responseType"in i&&d.blob&&(i.responseType="blob"),o.headers.forEach(function(e,t){i.setRequestHeader(t,e)}),i.send(void 0===o._bodyInit?null:o._bodyInit)})},e.fetch.polyfill=!0}}(void 0!==n?n:this),e.exports=n},function(e,t){var n=e.exports=function(e){return new r(e)};function r(e){this.value=e}function o(e,t,n){var r=[],o=[],s=!0;return function e(p){var f=n?i(p):p,h={},d=!0,m={node:f,node_:p,path:[].concat(r),parent:o[o.length-1],parents:o,key:r.slice(-1)[0],isRoot:0===r.length,level:r.length,circular:null,update:function(e,t){m.isRoot||(m.parent.node[m.key]=e),m.node=e,t&&(d=!1)},delete:function(e){delete m.parent.node[m.key],e&&(d=!1)},remove:function(e){u(m.parent.node)?m.parent.node.splice(m.key,1):delete m.parent.node[m.key],e&&(d=!1)},keys:null,before:function(e){h.before=e},after:function(e){h.after=e},pre:function(e){h.pre=e},post:function(e){h.post=e},stop:function(){s=!1},block:function(){d=!1}};if(!s)return m;function v(){if("object"==typeof m.node&&null!==m.node){m.keys&&m.node_===m.node||(m.keys=a(m.node)),m.isLeaf=0==m.keys.length;for(var e=0;e<o.length;e++)if(o[e].node_===p){m.circular=o[e];break}}else m.isLeaf=!0,m.keys=null;m.notLeaf=!m.isLeaf,m.notRoot=!m.isRoot}v();var g=t.call(m,m.node);return void 0!==g&&m.update&&m.update(g),h.before&&h.before.call(m,m.node),d?("object"!=typeof m.node||null===m.node||m.circular||(o.push(m),v(),c(m.keys,function(t,o){r.push(t),h.pre&&h.pre.call(m,m.node[t],t);var i=e(m.node[t]);n&&l.call(m.node,t)&&(m.node[t]=i.node),i.isLast=o==m.keys.length-1,i.isFirst=0==o,h.post&&h.post.call(m,i),r.pop()}),o.pop()),h.after&&h.after.call(m,m.node),m):m}(e).node}function i(e){if("object"==typeof e&&null!==e){var t;if(u(e))t=[];else if("[object Date]"===s(e))t=new Date(e.getTime?e.getTime():e);else if(function(e){return"[object RegExp]"===s(e)}(e))t=new RegExp(e);else if(function(e){return"[object Error]"===s(e)}(e))t={message:e.message};else if(function(e){return"[object Boolean]"===s(e)}(e))t=new Boolean(e);else if(function(e){return"[object Number]"===s(e)}(e))t=new Number(e);else if(function(e){return"[object String]"===s(e)}(e))t=new String(e);else if(Object.create&&Object.getPrototypeOf)t=Object.create(Object.getPrototypeOf(e));else if(e.constructor===Object)t={};else{var n=e.constructor&&e.constructor.prototype||e.__proto__||{},r=function(){};r.prototype=n,t=new r}return c(a(e),function(n){t[n]=e[n]}),t}return e}r.prototype.get=function(e){for(var t=this.value,n=0;n<e.length;n++){var r=e[n];if(!t||!l.call(t,r)){t=void 0;break}t=t[r]}return t},r.prototype.has=function(e){for(var t=this.value,n=0;n<e.length;n++){var r=e[n];if(!t||!l.call(t,r))return!1;t=t[r]}return!0},r.prototype.set=function(e,t){for(var n=this.value,r=0;r<e.length-1;r++){var o=e[r];l.call(n,o)||(n[o]={}),n=n[o]}return n[e[r]]=t,t},r.prototype.map=function(e){return o(this.value,e,!0)},r.prototype.forEach=function(e){return this.value=o(this.value,e,!1),this.value},r.prototype.reduce=function(e,t){var n=1===arguments.length,r=n?this.value:t;return this.forEach(function(t){this.isRoot&&n||(r=e.call(this,r,t))}),r},r.prototype.paths=function(){var e=[];return this.forEach(function(t){e.push(this.path)}),e},r.prototype.nodes=function(){var e=[];return this.forEach(function(t){e.push(this.node)}),e},r.prototype.clone=function(){var e=[],t=[];return function n(r){for(var o=0;o<e.length;o++)if(e[o]===r)return t[o];if("object"==typeof r&&null!==r){var s=i(r);return e.push(r),t.push(s),c(a(r),function(e){s[e]=n(r[e])}),e.pop(),t.pop(),s}return r}(this.value)};var a=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};function s(e){return Object.prototype.toString.call(e)}var u=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},c=function(e,t){if(e.forEach)return e.forEach(t);for(var n=0;n<e.length;n++)t(e[n],n,e)};c(a(r.prototype),function(e){n[e]=function(t){var n=[].slice.call(arguments,1),o=new r(t);return o[e].apply(o,n)}});var l=Object.hasOwnProperty||function(e,t){return t in e}},function(e,t,n){var r=n(948),o=n(447)(function(e,t){return null==e?{}:r(e,t)});e.exports=o},function(e,t,n){var r=n(949),o=n(380);e.exports=function(e,t){return r(e,t,function(t,n){return o(e,n)})}},function(e,t,n){var r=n(173),o=n(410),i=n(104);e.exports=function(e,t,n){for(var a=-1,s=t.length,u={};++a<s;){var c=t[a],l=r(e,c);n(l,c)&&o(u,i(c,e),l)}return u}},function(e,t,n){"use strict";
+/*!
+ * cookie
+ * Copyright(c) 2012-2014 Roman Shtylman
+ * Copyright(c) 2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */t.parse=function(e,t){if("string"!=typeof e)throw new TypeError("argument str must be a string");for(var n={},o=t||{},a=e.split(i),u=o.decode||r,c=0;c<a.length;c++){var l=a[c],p=l.indexOf("=");if(!(p<0)){var f=l.substr(0,p).trim(),h=l.substr(++p,l.length).trim();'"'==h[0]&&(h=h.slice(1,-1)),null==n[f]&&(n[f]=s(h,u))}}return n},t.serialize=function(e,t,n){var r=n||{},i=r.encode||o;if("function"!=typeof i)throw new TypeError("option encode is invalid");if(!a.test(e))throw new TypeError("argument name is invalid");var s=i(t);if(s&&!a.test(s))throw new TypeError("argument val is invalid");var u=e+"="+s;if(null!=r.maxAge){var c=r.maxAge-0;if(isNaN(c))throw new Error("maxAge should be a Number");u+="; Max-Age="+Math.floor(c)}if(r.domain){if(!a.test(r.domain))throw new TypeError("option domain is invalid");u+="; Domain="+r.domain}if(r.path){if(!a.test(r.path))throw new TypeError("option path is invalid");u+="; Path="+r.path}if(r.expires){if("function"!=typeof r.expires.toUTCString)throw new TypeError("option expires is invalid");u+="; Expires="+r.expires.toUTCString()}r.httpOnly&&(u+="; HttpOnly");r.secure&&(u+="; Secure");if(r.sameSite){var l="string"==typeof r.sameSite?r.sameSite.toLowerCase():r.sameSite;switch(l){case!0:u+="; SameSite=Strict";break;case"lax":u+="; SameSite=Lax";break;case"strict":u+="; SameSite=Strict";break;default:throw new TypeError("option sameSite is invalid")}}return u};var r=decodeURIComponent,o=encodeURIComponent,i=/; */,a=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function s(e,t){try{return t(e)}catch(t){return e}}},function(e,t){e.exports=function(e){for(var t=[],n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r>=55296&&r<=56319&&n+1<e.length){var o=e.charCodeAt(n+1);if(o>=56320&&o<=57343){var i=1024*(r-55296)+o-56320+65536;t.push(240+Math.floor(i/64/64/64),128+Math.floor(i/64/64)%64,128+Math.floor(i/64)%64,128+i%64),n+=1;continue}}r>=2048?t.push(224+Math.floor(r/64/64),128+Math.floor(r/64)%64,128+r%64):r>=128?t.push(192+Math.floor(r/64),128+r%64):t.push(r)}return t}},function(e,t,n){!function(){var e;function n(e,t){function n(e,t,n){if(!r(e))return n;var o=0,i=0;do{var a=t.exec(e);if(null===a)break;if(!(i<n))break;o+=a[0].length,i++}while(null!==a);return o>=e.length?-1:o}function r(e){return a.test(e)}function o(e,n){null==e&&(e=["[^]"]),null==n&&(n="g");var r=[];return t.forEach(function(e){r.push(e.source)}),r.push(i.source),r=r.concat(e),new RegExp(r.join("|"),n)}e.findCharIndex=function(e,t){if(t>=e.length)return-1;if(!r(e))return t;for(var n=o(),i=0;null!==n.exec(e)&&!(n.lastIndex>t);)i++;return i},e.findByteIndex=function(e,t){return t>=this.length(e)?-1:n(e,o(),t)},e.charAt=function(e,t){var n=this.findByteIndex(e,t);if(n<0||n>=e.length)return"";var r=e.slice(n,n+8),o=a.exec(r);return null===o?r[0]:o[0]},e.charCodeAt=function(e,t){var r=function(e,t){return n(e,new RegExp(i.source,"g"),t)}(e,t);if(r<0)return NaN;var o=e.charCodeAt(r);return 55296<=o&&o<=56319?1024*(o-55296)+(e.charCodeAt(r+1)-56320)+65536:o},e.fromCharCode=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10),56320+(1023&e))):String.fromCharCode(e)},e.indexOf=function(e,t,n){null==n&&(n=0);var r=this.findByteIndex(e,n),o=e.indexOf(t,r);return o<0?-1:this.findCharIndex(e,o)},e.lastIndexOf=function(e,t,n){var r;if(null==n)r=e.lastIndexOf(t);else{var o=this.findByteIndex(e,n);r=e.lastIndexOf(t,o)}return r<0?-1:this.findCharIndex(e,r)},e.slice=function(e,t,n){var r,o=this.findByteIndex(e,t);return o<0&&(o=e.length),null==n?r=e.length:(r=this.findByteIndex(e,n))<0&&(r=e.length),e.slice(o,r)},e.substr=function(e,t,n){return t<0&&(t=this.length(e)+t),null==n?this.slice(e,t):this.slice(e,t,t+n)},e.substring=e.slice,e.length=function(e){return this.findCharIndex(e,e.length-1)+1},e.stringToCodePoints=function(e){for(var t=[],n=0;n<e.length&&(codePoint=this.charCodeAt(e,n),codePoint);n++)t.push(codePoint);return t},e.codePointsToString=function(e){for(var t=[],n=0;n<e.length;n++)t.push(this.fromCharCode(e[n]));return t.join("")},e.stringToBytes=function(e){for(var t=[],n=0;n<e.length;n++){for(var r=e.charCodeAt(n),o=[];r>0;)o.push(255&r),r>>=8;1==o.length&&o.push(0),t=t.concat(o.reverse())}return t},e.bytesToString=function(e){for(var t=[],n=0;n<e.length;n+=2){var r=e[n]<<8|e[n+1];t.push(String.fromCharCode(r))}return t.join("")},e.stringToCharArray=function(e){var t=[],n=o();do{var r=n.exec(e);if(null===r)break;t.push(r[0])}while(null!==r);return t};var i=/[\uD800-\uDBFF][\uDC00-\uDFFF]/,a=o([],"")}null!==t?e=t:"undefined"!=typeof window&&null!==window&&(void 0!==window.UtfString&&null!==window.UtfString||(window.UtfString={}),e=window.UtfString);e.visual={},n(e,[]),n(e.visual,[/\uD83C[\uDDE6-\uDDFF]\uD83C[\uDDE6-\uDDFF]/])}()},function(e,t,n){var r=n(443),o=1,i=4;e.exports=function(e){return r(e,o|i)}},function(e,t){!function(e){"use strict";function t(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function n(e){return"string"!=typeof e&&(e=String(e)),e}function r(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return d.iterable&&(t[Symbol.iterator]=function(){return t}),t}function o(e){this.map={},e instanceof o?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function i(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function a(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function s(e){var t=new FileReader,n=a(t);return t.readAsArrayBuffer(e),n}function u(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function c(){return this.bodyUsed=!1,this._initBody=function(e){if(this._bodyInit=e,e)if("string"==typeof e)this._bodyText=e;else if(d.blob&&Blob.prototype.isPrototypeOf(e))this._bodyBlob=e;else if(d.formData&&FormData.prototype.isPrototypeOf(e))this._bodyFormData=e;else if(d.searchParams&&URLSearchParams.prototype.isPrototypeOf(e))this._bodyText=e.toString();else if(d.arrayBuffer&&d.blob&&v(e))this._bodyArrayBuffer=u(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else{if(!d.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(e)&&!g(e))throw new Error("unsupported BodyInit type");this._bodyArrayBuffer=u(e)}else this._bodyText="";this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):d.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},d.blob&&(this.blob=function(){var e=i(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?i(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(s)}),this.text=function(){var e=i(this);if(e)return e;if(this._bodyBlob)return function(e){var t=new FileReader,n=a(t);return t.readAsText(e),n}(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(function(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r<t.length;r++)n[r]=String.fromCharCode(t[r]);return n.join("")}(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},d.formData&&(this.formData=function(){return this.text().then(p)}),this.json=function(){return this.text().then(JSON.parse)},this}function l(e,t){var n=(t=t||{}).body;if(e instanceof l){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new o(e.headers)),this.method=e.method,this.mode=e.mode,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"omit",!t.headers&&this.headers||(this.headers=new o(t.headers)),this.method=function(e){var t=e.toUpperCase();return y.indexOf(t)>-1?t:e}(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function p(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),o=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(o))}}),t}function f(e){var t=new o;return e.split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var o=n.join(":").trim();t.append(r,o)}}),t}function h(e,t){t||(t={}),this.type="default",this.status="status"in t?t.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new o(t.headers),this.url=t.url||"",this._initBody(e)}if(!e.fetch){var d={searchParams:"URLSearchParams"in e,iterable:"Symbol"in e&&"iterator"in Symbol,blob:"FileReader"in e&&"Blob"in e&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in e,arrayBuffer:"ArrayBuffer"in e};if(d.arrayBuffer)var m=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],v=function(e){return e&&DataView.prototype.isPrototypeOf(e)},g=ArrayBuffer.isView||function(e){return e&&m.indexOf(Object.prototype.toString.call(e))>-1};o.prototype.append=function(e,r){e=t(e),r=n(r);var o=this.map[e];this.map[e]=o?o+","+r:r},o.prototype.delete=function(e){delete this.map[t(e)]},o.prototype.get=function(e){return e=t(e),this.has(e)?this.map[e]:null},o.prototype.has=function(e){return this.map.hasOwnProperty(t(e))},o.prototype.set=function(e,r){this.map[t(e)]=n(r)},o.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},o.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),r(e)},o.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),r(e)},o.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),r(e)},d.iterable&&(o.prototype[Symbol.iterator]=o.prototype.entries);var y=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];l.prototype.clone=function(){return new l(this,{body:this._bodyInit})},c.call(l.prototype),c.call(h.prototype),h.prototype.clone=function(){return new h(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new o(this.headers),url:this.url})},h.error=function(){var e=new h(null,{status:0,statusText:""});return e.type="error",e};var b=[301,302,303,307,308];h.redirect=function(e,t){if(-1===b.indexOf(t))throw new RangeError("Invalid status code");return new h(null,{status:t,headers:{location:e}})},e.Headers=o,e.Request=l,e.Response=h,e.fetch=function(e,t){return new Promise(function(n,r){var o=new l(e,t),i=new XMLHttpRequest;i.onload=function(){var e={status:i.status,statusText:i.statusText,headers:f(i.getAllResponseHeaders()||"")};e.url="responseURL"in i?i.responseURL:e.headers.get("X-Request-URL");var t="response"in i?i.response:i.responseText;n(new h(t,e))},i.onerror=function(){r(new TypeError("Network request failed"))},i.ontimeout=function(){r(new TypeError("Network request failed"))},i.open(o.method,o.url,!0),"include"===o.credentials&&(i.withCredentials=!0),"responseType"in i&&d.blob&&(i.responseType="blob"),o.headers.forEach(function(e,t){i.setRequestHeader(t,e)}),i.send(void 0===o._bodyInit?null:o._bodyInit)})},e.fetch.polyfill=!0}}("undefined"!=typeof self?self:this)},function(e,t){e.exports=FormData},function(e,t,n){"use strict";e.exports=function(e){return encodeURIComponent(e).replace(/[!'()*]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}},function(e,t,n){"use strict";var r=n(358);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return n.PropTypes=n,n}},function(e,t,n){n(160),n(97),n(99),n(959),n(961),n(964),n(965),e.exports=n(22).Map},function(e,t,n){"use strict";var r=n(960),o=n(141);e.exports=n(453)("Map",function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},{get:function(e){var t=r.getEntry(o(this,"Map"),e);return t&&t.v},set:function(e,t){return r.def(o(this,"Map"),0===e?0:e,t)}},r,!0)},function(e,t,n){"use strict";var r=n(47).f,o=n(156),i=n(179),a=n(60),s=n(178),u=n(108),c=n(211),l=n(348),p=n(407),f=n(45),h=n(132).fastKey,d=n(141),m=f?"_s":"size",v=function(e,t){var n,r=h(t);if("F"!==r)return e._i[r];for(n=e._f;n;n=n.n)if(n.k==t)return n};e.exports={getConstructor:function(e,t,n,c){var l=e(function(e,r){s(e,l,t,"_i"),e._t=t,e._i=o(null),e._f=void 0,e._l=void 0,e[m]=0,null!=r&&u(r,n,e[c],e)});return i(l.prototype,{clear:function(){for(var e=d(this,t),n=e._i,r=e._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete n[r.i];e._f=e._l=void 0,e[m]=0},delete:function(e){var n=d(this,t),r=v(n,e);if(r){var o=r.n,i=r.p;delete n._i[r.i],r.r=!0,i&&(i.n=o),o&&(o.p=i),n._f==r&&(n._f=o),n._l==r&&(n._l=i),n[m]--}return!!r},forEach:function(e){d(this,t);for(var n,r=a(e,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(r(n.v,n.k,this);n&&n.r;)n=n.p},has:function(e){return!!v(d(this,t),e)}}),f&&r(l.prototype,"size",{get:function(){return d(this,t)[m]}}),l},def:function(e,t,n){var r,o,i=v(e,t);return i?i.v=n:(e._l=i={i:o=h(t,!0),k:t,v:n,p:r=e._l,n:void 0,r:!1},e._f||(e._f=i),r&&(r.n=i),e[m]++,"F"!==o&&(e._i[o]=i)),e},getEntry:v,setStrong:function(e,t,n){c(e,t,function(e,n){this._t=d(e,t),this._k=n,this._l=void 0},function(){for(var e=this._k,t=this._l;t&&t.r;)t=t.p;return this._t&&(this._l=t=t?t.n:this._t._f)?l(0,"keys"==e?t.k:"values"==e?t.v:[t.k,t.v]):(this._t=void 0,l(1))},n?"entries":"values",!n,!0),p(t)}}},function(e,t,n){var r=n(30);r(r.P+r.R,"Map",{toJSON:n(962)("Map")})},function(e,t,n){var r=n(162),o=n(963);e.exports=function(e){return function(){if(r(this)!=e)throw TypeError(e+"#toJSON isn't generic");return o(this)}}},function(e,t,n){var r=n(108);e.exports=function(e,t){var n=[];return r(e,!1,n.push,n,t),n}},function(e,t,n){n(454)("Map")},function(e,t,n){n(455)("Map")},function(e,t,n){"use strict";
+/*!
+ * repeat-string <https://github.com/jonschlinkert/repeat-string>
+ *
+ * Copyright (c) 2014-2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */var r,o="";e.exports=function(e,t){if("string"!=typeof e)throw new TypeError("expected a string");if(1===t)return e;if(2===t)return e+e;var n=e.length*t;if(r!==e||void 0===r)r=e,o="";else if(o.length>=n)return o.substr(0,n);for(;n>o.length&&t>1;)1&t&&(o+=e),t>>=1,e+=e;return o=(o+=e).substr(0,n)}},function(e,t,n){"use strict";var r=n(37).assign,o=n(968),i=n(970),a=n(981),s=n(996),u=n(187),c={default:n(1015),full:n(1016),commonmark:n(1017)};function l(e,t,n){this.src=t,this.env=n,this.options=e.options,this.tokens=[],this.inlineMode=!1,this.inline=e.inline,this.block=e.block,this.renderer=e.renderer,this.typographer=e.typographer}function p(e,t){"string"!=typeof e&&(t=e,e="default"),this.inline=new s,this.block=new a,this.core=new i,this.renderer=new o,this.ruler=new u,this.options={},this.configure(c[e]),this.set(t||{})}p.prototype.set=function(e){r(this.options,e)},p.prototype.configure=function(e){var t=this;if(!e)throw new Error("Wrong `remarkable` preset, check name/content");e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(n){e.components[n].rules&&t[n].ruler.enable(e.components[n].rules,!0)})},p.prototype.use=function(e,t){return e(this,t),this},p.prototype.parse=function(e,t){var n=new l(this,e,t);return this.core.process(n),n.tokens},p.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)},p.prototype.parseInline=function(e,t){var n=new l(this,e,t);return n.inlineMode=!0,this.core.process(n),n.tokens},p.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)},e.exports=p,e.exports.utils=n(37)},function(e,t,n){"use strict";var r=n(37),o=n(969);function i(){this.rules=r.assign({},o),this.getBreak=o.getBreak}e.exports=i,i.prototype.renderInline=function(e,t,n){for(var r=this.rules,o=e.length,i=0,a="";o--;)a+=r[e[i].type](e,i++,t,n,this);return a},i.prototype.render=function(e,t,n){for(var r=this.rules,o=e.length,i=-1,a="";++i<o;)"inline"===e[i].type?a+=this.renderInline(e[i].children,t,n):a+=r[e[i].type](e,i,t,n,this);return a}},function(e,t,n){"use strict";var r=n(37).has,o=n(37).unescapeMd,i=n(37).replaceEntities,a=n(37).escapeHtml,s={};s.blockquote_open=function(){return"<blockquote>\n"},s.blockquote_close=function(e,t){return"</blockquote>"+u(e,t)},s.code=function(e,t){return e[t].block?"<pre><code>"+a(e[t].content)+"</code></pre>"+u(e,t):"<code>"+a(e[t].content)+"</code>"},s.fence=function(e,t,n,s,c){var l,p,f=e[t],h="",d=n.langPrefix;if(f.params){if(p=(l=f.params.split(/\s+/g)).join(" "),r(c.rules.fence_custom,l[0]))return c.rules.fence_custom[l[0]](e,t,n,s,c);h=' class="'+d+a(i(o(p)))+'"'}return"<pre><code"+h+">"+(n.highlight&&n.highlight.apply(n.highlight,[f.content].concat(l))||a(f.content))+"</code></pre>"+u(e,t)},s.fence_custom={},s.heading_open=function(e,t){return"<h"+e[t].hLevel+">"},s.heading_close=function(e,t){return"</h"+e[t].hLevel+">\n"},s.hr=function(e,t,n){return(n.xhtmlOut?"<hr />":"<hr>")+u(e,t)},s.bullet_list_open=function(){return"<ul>\n"},s.bullet_list_close=function(e,t){return"</ul>"+u(e,t)},s.list_item_open=function(){return"<li>"},s.list_item_close=function(){return"</li>\n"},s.ordered_list_open=function(e,t){var n=e[t];return"<ol"+(n.order>1?' start="'+n.order+'"':"")+">\n"},s.ordered_list_close=function(e,t){return"</ol>"+u(e,t)},s.paragraph_open=function(e,t){return e[t].tight?"":"<p>"},s.paragraph_close=function(e,t){var n=!(e[t].tight&&t&&"inline"===e[t-1].type&&!e[t-1].content);return(e[t].tight?"":"</p>")+(n?u(e,t):"")},s.link_open=function(e,t,n){var r=e[t].title?' title="'+a(i(e[t].title))+'"':"",o=n.linkTarget?' target="'+n.linkTarget+'"':"";return'<a href="'+a(e[t].href)+'"'+r+o+">"},s.link_close=function(){return"</a>"},s.image=function(e,t,n){var r=' src="'+a(e[t].src)+'"',s=e[t].title?' title="'+a(i(e[t].title))+'"':"";return"<img"+r+(' alt="'+(e[t].alt?a(i(o(e[t].alt))):"")+'"')+s+(n.xhtmlOut?" /":"")+">"},s.table_open=function(){return"<table>\n"},s.table_close=function(){return"</table>\n"},s.thead_open=function(){return"<thead>\n"},s.thead_close=function(){return"</thead>\n"},s.tbody_open=function(){return"<tbody>\n"},s.tbody_close=function(){return"</tbody>\n"},s.tr_open=function(){return"<tr>"},s.tr_close=function(){return"</tr>\n"},s.th_open=function(e,t){var n=e[t];return"<th"+(n.align?' style="text-align:'+n.align+'"':"")+">"},s.th_close=function(){return"</th>"},s.td_open=function(e,t){var n=e[t];return"<td"+(n.align?' style="text-align:'+n.align+'"':"")+">"},s.td_close=function(){return"</td>"},s.strong_open=function(){return"<strong>"},s.strong_close=function(){return"</strong>"},s.em_open=function(){return"<em>"},s.em_close=function(){return"</em>"},s.del_open=function(){return"<del>"},s.del_close=function(){return"</del>"},s.ins_open=function(){return"<ins>"},s.ins_close=function(){return"</ins>"},s.mark_open=function(){return"<mark>"},s.mark_close=function(){return"</mark>"},s.sub=function(e,t){return"<sub>"+a(e[t].content)+"</sub>"},s.sup=function(e,t){return"<sup>"+a(e[t].content)+"</sup>"},s.hardbreak=function(e,t,n){return n.xhtmlOut?"<br />\n":"<br>\n"},s.softbreak=function(e,t,n){return n.breaks?n.xhtmlOut?"<br />\n":"<br>\n":"\n"},s.text=function(e,t){return a(e[t].content)},s.htmlblock=function(e,t){return e[t].content},s.htmltag=function(e,t){return e[t].content},s.abbr_open=function(e,t){return'<abbr title="'+a(i(e[t].title))+'">'},s.abbr_close=function(){return"</abbr>"},s.footnote_ref=function(e,t){var n=Number(e[t].id+1).toString(),r="fnref"+n;return e[t].subId>0&&(r+=":"+e[t].subId),'<sup class="footnote-ref"><a href="#fn'+n+'" id="'+r+'">['+n+"]</a></sup>"},s.footnote_block_open=function(e,t,n){return(n.xhtmlOut?'<hr class="footnotes-sep" />\n':'<hr class="footnotes-sep">\n')+'<section class="footnotes">\n<ol class="footnotes-list">\n'},s.footnote_block_close=function(){return"</ol>\n</section>\n"},s.footnote_open=function(e,t){return'<li id="fn'+Number(e[t].id+1).toString()+'" class="footnote-item">'},s.footnote_close=function(){return"</li>\n"},s.footnote_anchor=function(e,t){var n="fnref"+Number(e[t].id+1).toString();return e[t].subId>0&&(n+=":"+e[t].subId),' <a href="#'+n+'" class="footnote-backref">↩</a>'},s.dl_open=function(){return"<dl>\n"},s.dt_open=function(){return"<dt>"},s.dd_open=function(){return"<dd>"},s.dl_close=function(){return"</dl>\n"},s.dt_close=function(){return"</dt>\n"},s.dd_close=function(){return"</dd>\n"};var u=s.getBreak=function(e,t){return(t=function e(t,n){return++n>=t.length-2?n:"paragraph_open"===t[n].type&&t[n].tight&&"inline"===t[n+1].type&&0===t[n+1].content.length&&"paragraph_close"===t[n+2].type&&t[n+2].tight?e(t,n+2):n}(e,t))<e.length&&"list_item_close"===e[t].type?"":"\n"};e.exports=s},function(e,t,n){"use strict";var r=n(187),o=[["block",n(971)],["abbr",n(972)],["references",n(973)],["inline",n(974)],["footnote_tail",n(975)],["abbr2",n(976)],["replacements",n(977)],["smartquotes",n(978)],["linkify",n(979)]];function i(){this.options={},this.ruler=new r;for(var e=0;e<o.length;e++)this.ruler.push(o[e][0],o[e][1])}i.prototype.process=function(e){var t,n,r;for(t=0,n=(r=this.ruler.getRules("")).length;t<n;t++)r[t](e)},e.exports=i},function(e,t,n){"use strict";e.exports=function(e){e.inlineMode?e.tokens.push({type:"inline",content:e.src.replace(/\n/g," ").trim(),level:0,lines:[0,1],children:[]}):e.block.parse(e.src,e.options,e.env,e.tokens)}},function(e,t,n){"use strict";var r=n(261),o=n(188);function i(e,t,n,i){var a,s,u,c,l,p;if(42!==e.charCodeAt(0))return-1;if(91!==e.charCodeAt(1))return-1;if(-1===e.indexOf("]:"))return-1;if(a=new r(e,t,n,i,[]),(s=o(a,1))<0||58!==e.charCodeAt(s+1))return-1;for(c=a.posMax,u=s+2;u<c&&10!==a.src.charCodeAt(u);u++);return l=e.slice(2,s),0===(p=e.slice(s+2,u).trim()).length?-1:(i.abbreviations||(i.abbreviations={}),void 0===i.abbreviations[":"+l]&&(i.abbreviations[":"+l]=p),u)}e.exports=function(e){var t,n,r,o,a=e.tokens;if(!e.inlineMode)for(t=1,n=a.length-1;t<n;t++)if("paragraph_open"===a[t-1].type&&"inline"===a[t].type&&"paragraph_close"===a[t+1].type){for(r=a[t].content;r.length&&!((o=i(r,e.inline,e.options,e.env))<0);)r=r.slice(o).trim();a[t].content=r,r.length||(a[t-1].tight=!0,a[t+1].tight=!0)}}},function(e,t,n){"use strict";var r=n(261),o=n(188),i=n(458),a=n(460),s=n(461);function u(e,t,n,u){var c,l,p,f,h,d,m,v,g;if(91!==e.charCodeAt(0))return-1;if(-1===e.indexOf("]:"))return-1;if(c=new r(e,t,n,u,[]),(l=o(c,0))<0||58!==e.charCodeAt(l+1))return-1;for(f=c.posMax,p=l+2;p<f&&(32===(h=c.src.charCodeAt(p))||10===h);p++);if(!i(c,p))return-1;for(m=c.linkContent,d=p=c.pos,p+=1;p<f&&(32===(h=c.src.charCodeAt(p))||10===h);p++);for(p<f&&d!==p&&a(c,p)?(v=c.linkContent,p=c.pos):(v="",p=d);p<f&&32===c.src.charCodeAt(p);)p++;return p<f&&10!==c.src.charCodeAt(p)?-1:(g=s(e.slice(1,l)),void 0===u.references[g]&&(u.references[g]={title:v,href:m}),p)}e.exports=function(e){var t,n,r,o,i=e.tokens;if(e.env.references=e.env.references||{},!e.inlineMode)for(t=1,n=i.length-1;t<n;t++)if("inline"===i[t].type&&"paragraph_open"===i[t-1].type&&"paragraph_close"===i[t+1].type){for(r=i[t].content;r.length&&!((o=u(r,e.inline,e.options,e.env))<0);)r=r.slice(o).trim();i[t].content=r,r.length||(i[t-1].tight=!0,i[t+1].tight=!0)}}},function(e,t,n){"use strict";e.exports=function(e){var t,n,r,o=e.tokens;for(n=0,r=o.length;n<r;n++)"inline"===(t=o[n]).type&&e.inline.parse(t.content,e.options,e.env,t.children)}},function(e,t,n){"use strict";e.exports=function(e){var t,n,r,o,i,a,s,u,c,l=0,p=!1,f={};if(e.env.footnotes&&(e.tokens=e.tokens.filter(function(e){return"footnote_reference_open"===e.type?(p=!0,u=[],c=e.label,!1):"footnote_reference_close"===e.type?(p=!1,f[":"+c]=u,!1):(p&&u.push(e),!p)}),e.env.footnotes.list)){for(a=e.env.footnotes.list,e.tokens.push({type:"footnote_block_open",level:l++}),t=0,n=a.length;t<n;t++){for(e.tokens.push({type:"footnote_open",id:t,level:l++}),a[t].tokens?((s=[]).push({type:"paragraph_open",tight:!1,level:l++}),s.push({type:"inline",content:"",level:l,children:a[t].tokens}),s.push({type:"paragraph_close",tight:!1,level:--l})):a[t].label&&(s=f[":"+a[t].label]),e.tokens=e.tokens.concat(s),i="paragraph_close"===e.tokens[e.tokens.length-1].type?e.tokens.pop():null,o=a[t].count>0?a[t].count:1,r=0;r<o;r++)e.tokens.push({type:"footnote_anchor",id:t,subId:r,level:l});i&&e.tokens.push(i),e.tokens.push({type:"footnote_close",level:--l})}e.tokens.push({type:"footnote_block_close",level:--l})}}},function(e,t,n){"use strict";function r(e){return e.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1")}e.exports=function(e){var t,n,o,i,a,s,u,c,l,p,f,h,d=e.tokens;if(e.env.abbreviations)for(e.env.abbrRegExp||(h="(^|["+" \n()[]'\".,!?-".split("").map(r).join("")+"])("+Object.keys(e.env.abbreviations).map(function(e){return e.substr(1)}).sort(function(e,t){return t.length-e.length}).map(r).join("|")+")($|["+" \n()[]'\".,!?-".split("").map(r).join("")+"])",e.env.abbrRegExp=new RegExp(h,"g")),p=e.env.abbrRegExp,n=0,o=d.length;n<o;n++)if("inline"===d[n].type)for(t=(i=d[n].children).length-1;t>=0;t--)if("text"===(a=i[t]).type){for(c=0,s=a.content,p.lastIndex=0,l=a.level,u=[];f=p.exec(s);)p.lastIndex>c&&u.push({type:"text",content:s.slice(c,f.index+f[1].length),level:l}),u.push({type:"abbr_open",title:e.env.abbreviations[":"+f[2]],level:l++}),u.push({type:"text",content:f[2],level:l}),u.push({type:"abbr_close",level:--l}),c=p.lastIndex-f[3].length;u.length&&(c<s.length&&u.push({type:"text",content:s.slice(c),level:l}),d[n].children=i=[].concat(i.slice(0,t),u,i.slice(t+1)))}}},function(e,t,n){"use strict";var r=/\+-|\.\.|\?\?\?\?|!!!!|,,|--/,o=/\((c|tm|r|p)\)/gi,i={c:"©",r:"®",p:"§",tm:"™"};e.exports=function(e){var t,n,a,s,u,c;if(e.options.typographer)for(u=e.tokens.length-1;u>=0;u--)if("inline"===e.tokens[u].type)for(t=(s=e.tokens[u].children).length-1;t>=0;t--)"text"===(n=s[t]).type&&(a=n.content,a=(c=a).indexOf("(")<0?c:c.replace(o,function(e,t){return i[t.toLowerCase()]}),r.test(a)&&(a=a.replace(/\+-/g,"±").replace(/\.{2,}/g,"…").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---([^-]|$)/gm,"$1—$2").replace(/(^|\s)--(\s|$)/gm,"$1–$2").replace(/(^|[^-\s])--([^-\s]|$)/gm,"$1–$2")),n.content=a)}},function(e,t,n){"use strict";var r=/['"]/,o=/['"]/g,i=/[-\s()\[\]]/;function a(e,t){return!(t<0||t>=e.length)&&!i.test(e[t])}function s(e,t,n){return e.substr(0,t)+n+e.substr(t+1)}e.exports=function(e){var t,n,i,u,c,l,p,f,h,d,m,v,g,y,b,_,w;if(e.options.typographer)for(w=[],b=e.tokens.length-1;b>=0;b--)if("inline"===e.tokens[b].type)for(_=e.tokens[b].children,w.length=0,t=0;t<_.length;t++)if("text"===(n=_[t]).type&&!r.test(n.text)){for(p=_[t].level,g=w.length-1;g>=0&&!(w[g].level<=p);g--);w.length=g+1,c=0,l=(i=n.content).length;e:for(;c<l&&(o.lastIndex=c,u=o.exec(i));)if(f=!a(i,u.index-1),c=u.index+1,y="'"===u[0],(h=!a(i,c))||f){if(m=!h,v=!f)for(g=w.length-1;g>=0&&(d=w[g],!(w[g].level<p));g--)if(d.single===y&&w[g].level===p){d=w[g],y?(_[d.token].content=s(_[d.token].content,d.pos,e.options.quotes[2]),n.content=s(n.content,u.index,e.options.quotes[3])):(_[d.token].content=s(_[d.token].content,d.pos,e.options.quotes[0]),n.content=s(n.content,u.index,e.options.quotes[1])),w.length=g;continue e}m?w.push({token:t,pos:u.index,single:y,level:p}):v&&y&&(n.content=s(n.content,u.index,"’"))}else y&&(n.content=s(n.content,u.index,"’"))}}},function(e,t,n){"use strict";var r=n(980),o=/www|@|\:\/\//;function i(e){return/^<\/a\s*>/i.test(e)}function a(){var e=[],t=new r({stripPrefix:!1,url:!0,email:!0,twitter:!1,replaceFn:function(t,n){switch(n.getType()){case"url":e.push({text:n.matchedText,url:n.getUrl()});break;case"email":e.push({text:n.matchedText,url:"mailto:"+n.getEmail().replace(/^mailto:/i,"")})}return!1}});return{links:e,autolinker:t}}e.exports=function(e){var t,n,r,s,u,c,l,p,f,h,d,m,v,g,y=e.tokens,b=null;if(e.options.linkify)for(n=0,r=y.length;n<r;n++)if("inline"===y[n].type)for(d=0,t=(s=y[n].children).length-1;t>=0;t--)if("link_close"!==(u=s[t]).type){if("htmltag"===u.type&&(g=u.content,/^<a[>\s]/i.test(g)&&d>0&&d--,i(u.content)&&d++),!(d>0)&&"text"===u.type&&o.test(u.content)){if(b||(m=(b=a()).links,v=b.autolinker),c=u.content,m.length=0,v.link(c),!m.length)continue;for(l=[],h=u.level,p=0;p<m.length;p++)e.inline.validateLink(m[p].url)&&((f=c.indexOf(m[p].text))&&(h=h,l.push({type:"text",content:c.slice(0,f),level:h})),l.push({type:"link_open",href:m[p].url,title:"",level:h++}),l.push({type:"text",content:m[p].text,level:h}),l.push({type:"link_close",level:--h}),c=c.slice(f+m[p].text.length));c.length&&l.push({type:"text",content:c,level:h}),y[n].children=s=[].concat(s.slice(0,t),l,s.slice(t+1))}}else for(t--;s[t].level!==u.level&&"link_open"!==s[t].type;)t--}},function(e,t,n){var r,o,i;
+/*!
+ * Autolinker.js
+ * 0.28.1
+ *
+ * Copyright(c) 2016 Gregory Jacobs <greg@greg-jacobs.com>
+ * MIT License
+ *
+ * https://github.com/gregjacobs/Autolinker.js
+ */o=[],void 0===(i="function"==typeof(r=function(){var e,t,n,r,o,i,a,s=function(e){e=e||{},this.version=s.version,this.urls=this.normalizeUrlsCfg(e.urls),this.email="boolean"!=typeof e.email||e.email,this.twitter="boolean"!=typeof e.twitter||e.twitter,this.phone="boolean"!=typeof e.phone||e.phone,this.hashtag=e.hashtag||!1,this.newWindow="boolean"!=typeof e.newWindow||e.newWindow,this.stripPrefix="boolean"!=typeof e.stripPrefix||e.stripPrefix;var t=this.hashtag;if(!1!==t&&"twitter"!==t&&"facebook"!==t&&"instagram"!==t)throw new Error("invalid `hashtag` cfg - see docs");this.truncate=this.normalizeTruncateCfg(e.truncate),this.className=e.className||"",this.replaceFn=e.replaceFn||null,this.htmlParser=null,this.matchers=null,this.tagBuilder=null};return s.link=function(e,t){return new s(t).link(e)},s.version="0.28.1",s.prototype={constructor:s,normalizeUrlsCfg:function(e){return null==e&&(e=!0),"boolean"==typeof e?{schemeMatches:e,wwwMatches:e,tldMatches:e}:{schemeMatches:"boolean"!=typeof e.schemeMatches||e.schemeMatches,wwwMatches:"boolean"!=typeof e.wwwMatches||e.wwwMatches,tldMatches:"boolean"!=typeof e.tldMatches||e.tldMatches}},normalizeTruncateCfg:function(e){return"number"==typeof e?{length:e,location:"end"}:s.Util.defaults(e||{},{length:Number.POSITIVE_INFINITY,location:"end"})},parse:function(e){for(var t=this.getHtmlParser().parse(e),n=0,r=[],o=0,i=t.length;o<i;o++){var a=t[o],s=a.getType();if("element"===s&&"a"===a.getTagName())a.isClosing()?n=Math.max(n-1,0):n++;else if("text"===s&&0===n){var u=this.parseText(a.getText(),a.getOffset());r.push.apply(r,u)}}return r=this.compactMatches(r),r=this.removeUnwantedMatches(r)},compactMatches:function(e){e.sort(function(e,t){return e.getOffset()-t.getOffset()});for(var t=0;t<e.length-1;t++)for(var n=e[t],r=n.getOffset()+n.getMatchedText().length;t+1<e.length&&e[t+1].getOffset()<=r;)e.splice(t+1,1);return e},removeUnwantedMatches:function(e){var t=s.Util.remove;return this.hashtag||t(e,function(e){return"hashtag"===e.getType()}),this.email||t(e,function(e){return"email"===e.getType()}),this.phone||t(e,function(e){return"phone"===e.getType()}),this.twitter||t(e,function(e){return"twitter"===e.getType()}),this.urls.schemeMatches||t(e,function(e){return"url"===e.getType()&&"scheme"===e.getUrlMatchType()}),this.urls.wwwMatches||t(e,function(e){return"url"===e.getType()&&"www"===e.getUrlMatchType()}),this.urls.tldMatches||t(e,function(e){return"url"===e.getType()&&"tld"===e.getUrlMatchType()}),e},parseText:function(e,t){t=t||0;for(var n=this.getMatchers(),r=[],o=0,i=n.length;o<i;o++){for(var a=n[o].parseMatches(e),s=0,u=a.length;s<u;s++)a[s].setOffset(t+a[s].getOffset());r.push.apply(r,a)}return r},link:function(e){if(!e)return"";for(var t=this.parse(e),n=[],r=0,o=0,i=t.length;o<i;o++){var a=t[o];n.push(e.substring(r,a.getOffset())),n.push(this.createMatchReturnVal(a)),r=a.getOffset()+a.getMatchedText().length}return n.push(e.substring(r)),n.join("")},createMatchReturnVal:function(e){var t;return this.replaceFn&&(t=this.replaceFn.call(this,this,e)),"string"==typeof t?t:!1===t?e.getMatchedText():t instanceof s.HtmlTag?t.toAnchorString():e.buildTag().toAnchorString()},getHtmlParser:function(){var e=this.htmlParser;return e||(e=this.htmlParser=new s.htmlParser.HtmlParser),e},getMatchers:function(){if(this.matchers)return this.matchers;var e=s.matcher,t=this.getTagBuilder(),n=[new e.Hashtag({tagBuilder:t,serviceName:this.hashtag}),new e.Email({tagBuilder:t}),new e.Phone({tagBuilder:t}),new e.Twitter({tagBuilder:t}),new e.Url({tagBuilder:t,stripPrefix:this.stripPrefix})];return this.matchers=n},getTagBuilder:function(){var e=this.tagBuilder;return e||(e=this.tagBuilder=new s.AnchorTagBuilder({newWindow:this.newWindow,truncate:this.truncate,className:this.className})),e}},s.match={},s.matcher={},s.htmlParser={},s.truncate={},s.Util={abstractMethod:function(){throw"abstract"},trimRegex:/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,assign:function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},defaults:function(e,t){for(var n in t)t.hasOwnProperty(n)&&void 0===e[n]&&(e[n]=t[n]);return e},extend:function(e,t){var n,r=e.prototype,o=function(){};o.prototype=r;var i=(n=t.hasOwnProperty("constructor")?t.constructor:function(){r.constructor.apply(this,arguments)}).prototype=new o;return i.constructor=n,i.superclass=r,delete t.constructor,s.Util.assign(i,t),n},ellipsis:function(e,t,n){return e.length>t&&(n=null==n?"..":n,e=e.substring(0,t-n.length)+n),e},indexOf:function(e,t){if(Array.prototype.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},remove:function(e,t){for(var n=e.length-1;n>=0;n--)!0===t(e[n])&&e.splice(n,1)},splitAndCapture:function(e,t){if(!t.global)throw new Error("`splitRegex` must have the 'g' flag set");for(var n,r=[],o=0;n=t.exec(e);)r.push(e.substring(o,n.index)),r.push(n[0]),o=n.index+n[0].length;return r.push(e.substring(o)),r},trim:function(e){return e.replace(this.trimRegex,"")}},s.HtmlTag=s.Util.extend(Object,{whitespaceRegex:/\s+/,constructor:function(e){s.Util.assign(this,e),this.innerHtml=this.innerHtml||this.innerHTML},setTagName:function(e){return this.tagName=e,this},getTagName:function(){return this.tagName||""},setAttr:function(e,t){return this.getAttrs()[e]=t,this},getAttr:function(e){return this.getAttrs()[e]},setAttrs:function(e){var t=this.getAttrs();return s.Util.assign(t,e),this},getAttrs:function(){return this.attrs||(this.attrs={})},setClass:function(e){return this.setAttr("class",e)},addClass:function(e){for(var t,n=this.getClass(),r=this.whitespaceRegex,o=s.Util.indexOf,i=n?n.split(r):[],a=e.split(r);t=a.shift();)-1===o(i,t)&&i.push(t);return this.getAttrs().class=i.join(" "),this},removeClass:function(e){for(var t,n=this.getClass(),r=this.whitespaceRegex,o=s.Util.indexOf,i=n?n.split(r):[],a=e.split(r);i.length&&(t=a.shift());){var u=o(i,t);-1!==u&&i.splice(u,1)}return this.getAttrs().class=i.join(" "),this},getClass:function(){return this.getAttrs().class||""},hasClass:function(e){return-1!==(" "+this.getClass()+" ").indexOf(" "+e+" ")},setInnerHtml:function(e){return this.innerHtml=e,this},getInnerHtml:function(){return this.innerHtml||""},toAnchorString:function(){var e=this.getTagName(),t=this.buildAttrsStr();return["<",e,t=t?" "+t:"",">",this.getInnerHtml(),"</",e,">"].join("")},buildAttrsStr:function(){if(!this.attrs)return"";var e=this.getAttrs(),t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n+'="'+e[n]+'"');return t.join(" ")}}),s.RegexLib={alphaNumericCharsStr:a="A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢴऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡૹଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々〆〱-〵〻〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ0-9٠-٩۰-۹߀-߉०-९০-৯੦-੯૦-૯୦-୯௦-௯౦-౯೦-೯൦-൯෦-෯๐-๙໐-໙༠-༩၀-၉႐-႙០-៩᠐-᠙᥆-᥏᧐-᧙᪀-᪉᪐-᪙᭐-᭙᮰-᮹᱀-᱉᱐-᱙꘠-꘩꣐-꣙꤀-꤉꧐-꧙꧰-꧹꩐-꩙꯰-꯹0-9",domainNameRegex:new RegExp("["+a+".\\-]*["+a+"\\-]"),tldRegex:/(?:travelersinsurance|sandvikcoromant|kerryproperties|cancerresearch|weatherchannel|kerrylogistics|spreadbetting|international|wolterskluwer|lifeinsurance|construction|pamperedchef|scholarships|versicherung|bridgestone|creditunion|kerryhotels|investments|productions|blackfriday|enterprises|lamborghini|photography|motorcycles|williamhill|playstation|contractors|barclaycard|accountants|redumbrella|engineering|management|telefonica|protection|consulting|tatamotors|creditcard|vlaanderen|schaeffler|associates|properties|foundation|republican|bnpparibas|boehringer|eurovision|extraspace|industries|immobilien|university|technology|volkswagen|healthcare|restaurant|cuisinella|vistaprint|apartments|accountant|travelers|homedepot|institute|vacations|furniture|fresenius|insurance|christmas|bloomberg|solutions|barcelona|firestone|financial|kuokgroup|fairwinds|community|passagens|goldpoint|equipment|lifestyle|yodobashi|aquarelle|marketing|analytics|education|amsterdam|statefarm|melbourne|allfinanz|directory|microsoft|stockholm|montblanc|accenture|lancaster|landrover|everbank|istanbul|graphics|grainger|ipiranga|softbank|attorney|pharmacy|saarland|catering|airforce|yokohama|mortgage|frontier|mutuelle|stcgroup|memorial|pictures|football|symantec|cipriani|ventures|telecity|cityeats|verisign|flsmidth|boutique|cleaning|firmdale|clinique|clothing|redstone|infiniti|deloitte|feedback|services|broadway|plumbing|commbank|training|barclays|exchange|computer|brussels|software|delivery|barefoot|builders|business|bargains|engineer|holdings|download|security|helsinki|lighting|movistar|discount|hdfcbank|supplies|marriott|property|diamonds|capetown|partners|democrat|jpmorgan|bradesco|budapest|rexroth|zuerich|shriram|academy|science|support|youtube|singles|surgery|alibaba|statoil|dentist|schwarz|android|cruises|cricket|digital|markets|starhub|systems|courses|coupons|netbank|country|domains|corsica|network|neustar|realtor|lincoln|limited|schmidt|yamaxun|cooking|contact|auction|spiegel|liaison|leclerc|latrobe|lasalle|abogado|compare|lanxess|exposed|express|company|cologne|college|avianca|lacaixa|fashion|recipes|ferrero|komatsu|storage|wanggou|clubmed|sandvik|fishing|fitness|bauhaus|kitchen|flights|florist|flowers|watches|weather|temasek|samsung|bentley|forsale|channel|theater|frogans|theatre|okinawa|website|tickets|jewelry|gallery|tiffany|iselect|shiksha|brother|organic|wedding|genting|toshiba|origins|philips|hyundai|hotmail|hoteles|hosting|rentals|windows|cartier|bugatti|holiday|careers|whoswho|hitachi|panerai|caravan|reviews|guitars|capital|trading|hamburg|hangout|finance|stream|family|abbott|health|review|travel|report|hermes|hiphop|gratis|career|toyota|hockey|dating|repair|google|social|soccer|reisen|global|otsuka|giving|unicom|casino|photos|center|broker|rocher|orange|bostik|garden|insure|ryukyu|bharti|safety|physio|sakura|oracle|online|jaguar|gallup|piaget|tienda|futbol|pictet|joburg|webcam|berlin|office|juegos|kaufen|chanel|chrome|xihuan|church|tennis|circle|kinder|flickr|bayern|claims|clinic|viajes|nowruz|xperia|norton|yachts|studio|coffee|camera|sanofi|nissan|author|expert|events|comsec|lawyer|tattoo|viking|estate|villas|condos|realty|yandex|energy|emerck|virgin|vision|durban|living|school|coupon|london|taobao|natura|taipei|nagoya|luxury|walter|aramco|sydney|madrid|credit|maison|makeup|schule|market|anquan|direct|design|swatch|suzuki|alsace|vuelos|dental|alipay|voyage|shouji|voting|airtel|mutual|degree|supply|agency|museum|mobily|dealer|monash|select|mormon|active|moscow|racing|datsun|quebec|nissay|rodeo|email|gifts|works|photo|chloe|edeka|cheap|earth|vista|tushu|koeln|glass|shoes|globo|tunes|gmail|nokia|space|kyoto|black|ricoh|seven|lamer|sener|epson|cisco|praxi|trust|citic|crown|shell|lease|green|legal|lexus|ninja|tatar|gripe|nikon|group|video|wales|autos|gucci|party|nexus|guide|linde|adult|parts|amica|lixil|boats|azure|loans|locus|cymru|lotte|lotto|stada|click|poker|quest|dabur|lupin|nadex|paris|faith|dance|canon|place|gives|trade|skype|rocks|mango|cloud|boots|smile|final|swiss|homes|honda|media|horse|cards|deals|watch|bosch|house|pizza|miami|osaka|tours|total|xerox|coach|sucks|style|delta|toray|iinet|tools|money|codes|beats|tokyo|salon|archi|movie|baidu|study|actor|yahoo|store|apple|world|forex|today|bible|tmall|tirol|irish|tires|forum|reise|vegas|vodka|sharp|omega|weber|jetzt|audio|promo|build|bingo|chase|gallo|drive|dubai|rehab|press|solar|sale|beer|bbva|bank|band|auto|sapo|sarl|saxo|audi|asia|arte|arpa|army|yoga|ally|zara|scor|scot|sexy|seat|zero|seek|aero|adac|zone|aarp|maif|meet|meme|menu|surf|mini|mobi|mtpc|porn|desi|star|ltda|name|talk|navy|love|loan|live|link|news|limo|like|spot|life|nico|lidl|lgbt|land|taxi|team|tech|kred|kpmg|sony|song|kiwi|kddi|jprs|jobs|sohu|java|itau|tips|info|immo|icbc|hsbc|town|host|page|toys|here|help|pars|haus|guru|guge|tube|goog|golf|gold|sncf|gmbh|gift|ggee|gent|gbiz|game|vana|pics|fund|ford|ping|pink|fish|film|fast|farm|play|fans|fail|plus|skin|pohl|fage|moda|post|erni|dvag|prod|doha|prof|docs|viva|diet|luxe|site|dell|sina|dclk|show|qpon|date|vote|cyou|voto|read|coop|cool|wang|club|city|chat|cern|cash|reit|rent|casa|cars|care|camp|rest|call|cafe|weir|wien|rich|wiki|buzz|wine|book|bond|room|work|rsvp|shia|ruhr|blue|bing|shaw|bike|safe|xbox|best|pwc|mtn|lds|aig|boo|fyi|nra|nrw|ntt|car|gal|obi|zip|aeg|vin|how|one|ong|onl|dad|ooo|bet|esq|org|htc|bar|uol|ibm|ovh|gdn|ice|icu|uno|gea|ifm|bot|top|wtf|lol|day|pet|eus|wtc|ubs|tvs|aco|ing|ltd|ink|tab|abb|afl|cat|int|pid|pin|bid|cba|gle|com|cbn|ads|man|wed|ceb|gmo|sky|ist|gmx|tui|mba|fan|ski|iwc|app|pro|med|ceo|jcb|jcp|goo|dev|men|aaa|meo|pub|jlc|bom|jll|gop|jmp|mil|got|gov|win|jot|mma|joy|trv|red|cfa|cfd|bio|moe|moi|mom|ren|biz|aws|xin|bbc|dnp|buy|kfh|mov|thd|xyz|fit|kia|rio|rip|kim|dog|vet|nyc|bcg|mtr|bcn|bms|bmw|run|bzh|rwe|tel|stc|axa|kpn|fly|krd|cab|bnl|foo|crs|eat|tci|sap|srl|nec|sas|net|cal|sbs|sfr|sca|scb|csc|edu|new|xxx|hiv|fox|wme|ngo|nhk|vip|sex|frl|lat|yun|law|you|tax|soy|sew|om|ac|hu|se|sc|sg|sh|sb|sa|rw|ru|rs|ro|re|qa|py|si|pw|pt|ps|sj|sk|pr|pn|pm|pl|sl|sm|pk|sn|ph|so|pg|pf|pe|pa|zw|nz|nu|nr|np|no|nl|ni|ng|nf|sr|ne|st|nc|na|mz|my|mx|mw|mv|mu|mt|ms|mr|mq|mp|mo|su|mn|mm|ml|mk|mh|mg|me|sv|md|mc|sx|sy|ma|ly|lv|sz|lu|lt|ls|lr|lk|li|lc|lb|la|tc|kz|td|ky|kw|kr|kp|kn|km|ki|kh|tf|tg|th|kg|ke|jp|jo|jm|je|it|is|ir|tj|tk|tl|tm|iq|tn|to|io|in|im|il|ie|ad|sd|ht|hr|hn|hm|tr|hk|gy|gw|gu|gt|gs|gr|gq|tt|gp|gn|gm|gl|tv|gi|tw|tz|ua|gh|ug|uk|gg|gf|ge|gd|us|uy|uz|va|gb|ga|vc|ve|fr|fo|fm|fk|fj|vg|vi|fi|eu|et|es|er|eg|ee|ec|dz|do|dm|dk|vn|dj|de|cz|cy|cx|cw|vu|cv|cu|cr|co|cn|cm|cl|ck|ci|ch|cg|cf|cd|cc|ca|wf|bz|by|bw|bv|bt|bs|br|bo|bn|bm|bj|bi|ws|bh|bg|bf|be|bd|bb|ba|az|ax|aw|au|at|as|ye|ar|aq|ao|am|al|yt|ai|za|ag|af|ae|zm|id)\b/},s.AnchorTagBuilder=s.Util.extend(Object,{constructor:function(e){s.Util.assign(this,e)},build:function(e){return new s.HtmlTag({tagName:"a",attrs:this.createAttrs(e.getType(),e.getAnchorHref()),innerHtml:this.processAnchorText(e.getAnchorText())})},createAttrs:function(e,t){var n={href:t},r=this.createCssClass(e);return r&&(n.class=r),this.newWindow&&(n.target="_blank",n.rel="noopener noreferrer"),n},createCssClass:function(e){var t=this.className;return t?t+" "+t+"-"+e:""},processAnchorText:function(e){return e=this.doTruncate(e)},doTruncate:function(e){var t=this.truncate;if(!t||!t.length)return e;var n=t.length,r=t.location;return"smart"===r?s.truncate.TruncateSmart(e,n,".."):"middle"===r?s.truncate.TruncateMiddle(e,n,".."):s.truncate.TruncateEnd(e,n,"..")}}),s.htmlParser.HtmlParser=s.Util.extend(Object,{htmlRegex:(o=/(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/,i=/[^\s"'>\/=\x00-\x1F\x7F]+/.source+"(?:\\s*=\\s*"+o.source+")?",new RegExp(["(?:","<(!DOCTYPE)","(?:","\\s+","(?:",i,"|",o.source+")",")*",">",")","|","(?:","<(/)?","(?:",/!--([\s\S]+?)--/.source,"|","(?:","("+/[0-9a-zA-Z][0-9a-zA-Z:]*/.source+")","(?:","(?:\\s+|\\b)",i,")*","\\s*/?",")",")",">",")"].join(""),"gi")),htmlCharacterEntitiesRegex:/(&nbsp;|&#160;|&lt;|&#60;|&gt;|&#62;|&quot;|&#34;|&#39;)/gi,parse:function(e){for(var t,n,r=this.htmlRegex,o=0,i=[];null!==(t=r.exec(e));){var a=t[0],s=t[3],u=t[1]||t[4],c=!!t[2],l=t.index,p=e.substring(o,l);p&&(n=this.parseTextAndEntityNodes(o,p),i.push.apply(i,n)),s?i.push(this.createCommentNode(l,a,s)):i.push(this.createElementNode(l,a,u,c)),o=l+a.length}if(o<e.length){var f=e.substring(o);f&&(n=this.parseTextAndEntityNodes(o,f),i.push.apply(i,n))}return i},parseTextAndEntityNodes:function(e,t){for(var n=[],r=s.Util.splitAndCapture(t,this.htmlCharacterEntitiesRegex),o=0,i=r.length;o<i;o+=2){var a=r[o],u=r[o+1];a&&(n.push(this.createTextNode(e,a)),e+=a.length),u&&(n.push(this.createEntityNode(e,u)),e+=u.length)}return n},createCommentNode:function(e,t,n){return new s.htmlParser.CommentNode({offset:e,text:t,comment:s.Util.trim(n)})},createElementNode:function(e,t,n,r){return new s.htmlParser.ElementNode({offset:e,text:t,tagName:n.toLowerCase(),closing:r})},createEntityNode:function(e,t){return new s.htmlParser.EntityNode({offset:e,text:t})},createTextNode:function(e,t){return new s.htmlParser.TextNode({offset:e,text:t})}}),s.htmlParser.HtmlNode=s.Util.extend(Object,{offset:void 0,text:void 0,constructor:function(e){if(s.Util.assign(this,e),null==this.offset)throw new Error("`offset` cfg required");if(null==this.text)throw new Error("`text` cfg required")},getType:s.Util.abstractMethod,getOffset:function(){return this.offset},getText:function(){return this.text}}),s.htmlParser.CommentNode=s.Util.extend(s.htmlParser.HtmlNode,{comment:"",getType:function(){return"comment"},getComment:function(){return this.comment}}),s.htmlParser.ElementNode=s.Util.extend(s.htmlParser.HtmlNode,{tagName:"",closing:!1,getType:function(){return"element"},getTagName:function(){return this.tagName},isClosing:function(){return this.closing}}),s.htmlParser.EntityNode=s.Util.extend(s.htmlParser.HtmlNode,{getType:function(){return"entity"}}),s.htmlParser.TextNode=s.Util.extend(s.htmlParser.HtmlNode,{getType:function(){return"text"}}),s.match.Match=s.Util.extend(Object,{constructor:function(e){if(null==e.tagBuilder)throw new Error("`tagBuilder` cfg required");if(null==e.matchedText)throw new Error("`matchedText` cfg required");if(null==e.offset)throw new Error("`offset` cfg required");this.tagBuilder=e.tagBuilder,this.matchedText=e.matchedText,this.offset=e.offset},getType:s.Util.abstractMethod,getMatchedText:function(){return this.matchedText},setOffset:function(e){this.offset=e},getOffset:function(){return this.offset},getAnchorHref:s.Util.abstractMethod,getAnchorText:s.Util.abstractMethod,buildTag:function(){return this.tagBuilder.build(this)}}),s.match.Email=s.Util.extend(s.match.Match,{constructor:function(e){if(s.match.Match.prototype.constructor.call(this,e),!e.email)throw new Error("`email` cfg required");this.email=e.email},getType:function(){return"email"},getEmail:function(){return this.email},getAnchorHref:function(){return"mailto:"+this.email},getAnchorText:function(){return this.email}}),s.match.Hashtag=s.Util.extend(s.match.Match,{constructor:function(e){if(s.match.Match.prototype.constructor.call(this,e),!e.hashtag)throw new Error("`hashtag` cfg required");this.serviceName=e.serviceName,this.hashtag=e.hashtag},getType:function(){return"hashtag"},getServiceName:function(){return this.serviceName},getHashtag:function(){return this.hashtag},getAnchorHref:function(){var e=this.serviceName,t=this.hashtag;switch(e){case"twitter":return"https://twitter.com/hashtag/"+t;case"facebook":return"https://www.facebook.com/hashtag/"+t;case"instagram":return"https://instagram.com/explore/tags/"+t;default:throw new Error("Unknown service name to point hashtag to: ",e)}},getAnchorText:function(){return"#"+this.hashtag}}),s.match.Phone=s.Util.extend(s.match.Match,{constructor:function(e){if(s.match.Match.prototype.constructor.call(this,e),!e.number)throw new Error("`number` cfg required");if(null==e.plusSign)throw new Error("`plusSign` cfg required");this.number=e.number,this.plusSign=e.plusSign},getType:function(){return"phone"},getNumber:function(){return this.number},getAnchorHref:function(){return"tel:"+(this.plusSign?"+":"")+this.number},getAnchorText:function(){return this.matchedText}}),s.match.Twitter=s.Util.extend(s.match.Match,{constructor:function(e){if(s.match.Match.prototype.constructor.call(this,e),!e.twitterHandle)throw new Error("`twitterHandle` cfg required");this.twitterHandle=e.twitterHandle},getType:function(){return"twitter"},getTwitterHandle:function(){return this.twitterHandle},getAnchorHref:function(){return"https://twitter.com/"+this.twitterHandle},getAnchorText:function(){return"@"+this.twitterHandle}}),s.match.Url=s.Util.extend(s.match.Match,{constructor:function(e){if(s.match.Match.prototype.constructor.call(this,e),"scheme"!==e.urlMatchType&&"www"!==e.urlMatchType&&"tld"!==e.urlMatchType)throw new Error('`urlMatchType` cfg must be one of: "scheme", "www", or "tld"');if(!e.url)throw new Error("`url` cfg required");if(null==e.protocolUrlMatch)throw new Error("`protocolUrlMatch` cfg required");if(null==e.protocolRelativeMatch)throw new Error("`protocolRelativeMatch` cfg required");if(null==e.stripPrefix)throw new Error("`stripPrefix` cfg required");this.urlMatchType=e.urlMatchType,this.url=e.url,this.protocolUrlMatch=e.protocolUrlMatch,this.protocolRelativeMatch=e.protocolRelativeMatch,this.stripPrefix=e.stripPrefix},urlPrefixRegex:/^(https?:\/\/)?(www\.)?/i,protocolRelativeRegex:/^\/\//,protocolPrepended:!1,getType:function(){return"url"},getUrlMatchType:function(){return this.urlMatchType},getUrl:function(){var e=this.url;return this.protocolRelativeMatch||this.protocolUrlMatch||this.protocolPrepended||(e=this.url="http://"+e,this.protocolPrepended=!0),e},getAnchorHref:function(){return this.getUrl().replace(/&amp;/g,"&")},getAnchorText:function(){var e=this.getMatchedText();return this.protocolRelativeMatch&&(e=this.stripProtocolRelativePrefix(e)),this.stripPrefix&&(e=this.stripUrlPrefix(e)),e=this.removeTrailingSlash(e)},stripUrlPrefix:function(e){return e.replace(this.urlPrefixRegex,"")},stripProtocolRelativePrefix:function(e){return e.replace(this.protocolRelativeRegex,"")},removeTrailingSlash:function(e){return"/"===e.charAt(e.length-1)&&(e=e.slice(0,-1)),e}}),s.matcher.Matcher=s.Util.extend(Object,{constructor:function(e){if(!e.tagBuilder)throw new Error("`tagBuilder` cfg required");this.tagBuilder=e.tagBuilder},parseMatches:s.Util.abstractMethod}),s.matcher.Email=s.Util.extend(s.matcher.Matcher,{matcherRegex:(e=s.RegexLib.alphaNumericCharsStr,t=new RegExp("["+e+"\\-_';:&=+$.,]+@"),n=s.RegexLib.domainNameRegex,r=s.RegexLib.tldRegex,new RegExp([t.source,n.source,"\\.",r.source].join(""),"gi")),parseMatches:function(e){for(var t,n=this.matcherRegex,r=this.tagBuilder,o=[];null!==(t=n.exec(e));){var i=t[0];o.push(new s.match.Email({tagBuilder:r,matchedText:i,offset:t.index,email:i}))}return o}}),s.matcher.Hashtag=s.Util.extend(s.matcher.Matcher,{matcherRegex:new RegExp("#[_"+s.RegexLib.alphaNumericCharsStr+"]{1,139}","g"),nonWordCharRegex:new RegExp("[^"+s.RegexLib.alphaNumericCharsStr+"]"),constructor:function(e){s.matcher.Matcher.prototype.constructor.call(this,e),this.serviceName=e.serviceName},parseMatches:function(e){for(var t,n=this.matcherRegex,r=this.nonWordCharRegex,o=this.serviceName,i=this.tagBuilder,a=[];null!==(t=n.exec(e));){var u=t.index,c=e.charAt(u-1);if(0===u||r.test(c)){var l=t[0],p=t[0].slice(1);a.push(new s.match.Hashtag({tagBuilder:i,matchedText:l,offset:u,serviceName:o,hashtag:p}))}}return a}}),s.matcher.Phone=s.Util.extend(s.matcher.Matcher,{matcherRegex:/(?:(\+)?\d{1,3}[-\040.])?\(?\d{3}\)?[-\040.]?\d{3}[-\040.]\d{4}/g,parseMatches:function(e){for(var t,n=this.matcherRegex,r=this.tagBuilder,o=[];null!==(t=n.exec(e));){var i=t[0],a=i.replace(/\D/g,""),u=!!t[1];o.push(new s.match.Phone({tagBuilder:r,matchedText:i,offset:t.index,number:a,plusSign:u}))}return o}}),s.matcher.Twitter=s.Util.extend(s.matcher.Matcher,{matcherRegex:new RegExp("@[_"+s.RegexLib.alphaNumericCharsStr+"]{1,20}","g"),nonWordCharRegex:new RegExp("[^"+s.RegexLib.alphaNumericCharsStr+"]"),parseMatches:function(e){for(var t,n=this.matcherRegex,r=this.nonWordCharRegex,o=this.tagBuilder,i=[];null!==(t=n.exec(e));){var a=t.index,u=e.charAt(a-1);if(0===a||r.test(u)){var c=t[0],l=t[0].slice(1);i.push(new s.match.Twitter({tagBuilder:o,matchedText:c,offset:a,twitterHandle:l}))}}return i}}),s.matcher.Url=s.Util.extend(s.matcher.Matcher,{matcherRegex:function(){var e=s.RegexLib.domainNameRegex,t=s.RegexLib.tldRegex,n=s.RegexLib.alphaNumericCharsStr,r=new RegExp("["+n+"\\-+&@#/%=~_()|'$*\\[\\]?!:,.;]*["+n+"\\-+&@#/%=~_()|'$*\\[\\]]");return new RegExp(["(?:","(",/(?:[A-Za-z][-.+A-Za-z0-9]*:(?![A-Za-z][-.+A-Za-z0-9]*:\/\/)(?!\d+\/?)(?:\/\/)?)/.source,e.source,")","|","(","(//)?",/(?:www\.)/.source,e.source,")","|","(","(//)?",e.source+"\\.",t.source,")",")","(?:"+r.source+")?"].join(""),"gi")}(),wordCharRegExp:/\w/,openParensRe:/\(/g,closeParensRe:/\)/g,constructor:function(e){if(s.matcher.Matcher.prototype.constructor.call(this,e),this.stripPrefix=e.stripPrefix,null==this.stripPrefix)throw new Error("`stripPrefix` cfg required")},parseMatches:function(e){for(var t,n=this.matcherRegex,r=this.stripPrefix,o=this.tagBuilder,i=[];null!==(t=n.exec(e));){var a=t[0],u=t[1],c=t[2],l=t[3],p=t[5],f=t.index,h=l||p,d=e.charAt(f-1);if(s.matcher.UrlMatchValidator.isValid(a,u)&&!(f>0&&"@"===d||f>0&&h&&this.wordCharRegExp.test(d))){if(this.matchHasUnbalancedClosingParen(a))a=a.substr(0,a.length-1);else{var m=this.matchHasInvalidCharAfterTld(a,u);m>-1&&(a=a.substr(0,m))}var v=u?"scheme":c?"www":"tld",g=!!u;i.push(new s.match.Url({tagBuilder:o,matchedText:a,offset:f,urlMatchType:v,url:a,protocolUrlMatch:g,protocolRelativeMatch:!!h,stripPrefix:r}))}}return i},matchHasUnbalancedClosingParen:function(e){if(")"===e.charAt(e.length-1)){var t=e.match(this.openParensRe),n=e.match(this.closeParensRe);if((t&&t.length||0)<(n&&n.length||0))return!0}return!1},matchHasInvalidCharAfterTld:function(e,t){if(!e)return-1;var n=0;t&&(n=e.indexOf(":"),e=e.slice(n));var r=/^((.?\/\/)?[A-Za-z0-9\u00C0-\u017F\.\-]*[A-Za-z0-9\u00C0-\u017F\-]\.[A-Za-z]+)/.exec(e);return null===r?-1:(n+=r[1].length,e=e.slice(r[1].length),/^[^.A-Za-z:\/?#]/.test(e)?n:-1)}}),s.matcher.UrlMatchValidator={hasFullProtocolRegex:/^[A-Za-z][-.+A-Za-z0-9]*:\/\//,uriSchemeRegex:/^[A-Za-z][-.+A-Za-z0-9]*:/,hasWordCharAfterProtocolRegex:/:[^\s]*?[A-Za-z\u00C0-\u017F]/,ipRegex:/[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/,isValid:function(e,t){return!(t&&!this.isValidUriScheme(t)||this.urlMatchDoesNotHaveProtocolOrDot(e,t)||this.urlMatchDoesNotHaveAtLeastOneWordChar(e,t)&&!this.isValidIpAddress(e))},isValidIpAddress:function(e){var t=new RegExp(this.hasFullProtocolRegex.source+this.ipRegex.source);return null!==e.match(t)},isValidUriScheme:function(e){var t=e.match(this.uriSchemeRegex)[0].toLowerCase();return"javascript:"!==t&&"vbscript:"!==t},urlMatchDoesNotHaveProtocolOrDot:function(e,t){return!(!e||t&&this.hasFullProtocolRegex.test(t)||-1!==e.indexOf("."))},urlMatchDoesNotHaveAtLeastOneWordChar:function(e,t){return!(!e||!t||this.hasWordCharAfterProtocolRegex.test(e))}},s.truncate.TruncateEnd=function(e,t,n){return s.Util.ellipsis(e,t,n)},s.truncate.TruncateMiddle=function(e,t,n){if(e.length<=t)return e;var r=t-n.length,o="";return r>0&&(o=e.substr(-1*Math.floor(r/2))),(e.substr(0,Math.ceil(r/2))+n+o).substr(0,t)},s.truncate.TruncateSmart=function(e,t,n){var r=function(e){var t="";return e.scheme&&e.host&&(t+=e.scheme+"://"),e.host&&(t+=e.host),e.path&&(t+="/"+e.path),e.query&&(t+="?"+e.query),e.fragment&&(t+="#"+e.fragment),t},o=function(e,t){var r=t/2,o=Math.ceil(r),i=-1*Math.floor(r),a="";return i<0&&(a=e.substr(i)),e.substr(0,o)+n+a};if(e.length<=t)return e;var i=t-n.length,a=function(e){var t={},n=e,r=n.match(/^([a-z]+):\/\//i);return r&&(t.scheme=r[1],n=n.substr(r[0].length)),(r=n.match(/^(.*?)(?=(\?|#|\/|$))/i))&&(t.host=r[1],n=n.substr(r[0].length)),(r=n.match(/^\/(.*?)(?=(\?|#|$))/i))&&(t.path=r[1],n=n.substr(r[0].length)),(r=n.match(/^\?(.*?)(?=(#|$))/i))&&(t.query=r[1],n=n.substr(r[0].length)),(r=n.match(/^#(.*?)$/i))&&(t.fragment=r[1]),t}(e);if(a.query){var s=a.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i);s&&(a.query=a.query.substr(0,s[1].length),e=r(a))}if(e.length<=t)return e;if(a.host&&(a.host=a.host.replace(/^www\./,""),e=r(a)),e.length<=t)return e;var u="";if(a.host&&(u+=a.host),u.length>=i)return a.host.length==t?(a.host.substr(0,t-n.length)+n).substr(0,t):o(u,i).substr(0,t);var c="";if(a.path&&(c+="/"+a.path),a.query&&(c+="?"+a.query),c){if((u+c).length>=i)return(u+c).length==t?(u+c).substr(0,t):(u+o(c,i-u.length)).substr(0,t);u+=c}if(a.fragment){var l="#"+a.fragment;if((u+l).length>=i)return(u+l).length==t?(u+l).substr(0,t):(u+o(l,i-u.length)).substr(0,t);u+=l}if(a.scheme&&a.host){var p=a.scheme+"://";if((u+p).length<i)return(p+u).substr(0,t)}if(u.length<=t)return u;var f="";return i>0&&(f=u.substr(-1*Math.floor(i/2))),(u.substr(0,Math.ceil(i/2))+n+f).substr(0,t)},s})?r.apply(t,o):r)||(e.exports=i)},function(e,t,n){"use strict";var r=n(187),o=n(982),i=[["code",n(983)],["fences",n(984),["paragraph","blockquote","list"]],["blockquote",n(985),["paragraph","blockquote","list"]],["hr",n(986),["paragraph","blockquote","list"]],["list",n(987),["paragraph","blockquote"]],["footnote",n(988),["paragraph"]],["heading",n(989),["paragraph","blockquote"]],["lheading",n(990)],["htmlblock",n(991),["paragraph","blockquote"]],["table",n(993),["paragraph"]],["deflist",n(994),["paragraph"]],["paragraph",n(995)]];function a(){this.ruler=new r;for(var e=0;e<i.length;e++)this.ruler.push(i[e][0],i[e][1],{alt:(i[e][2]||[]).slice()})}a.prototype.tokenize=function(e,t,n){for(var r,o=this.ruler.getRules(""),i=o.length,a=t,s=!1;a<n&&(e.line=a=e.skipEmptyLines(a),!(a>=n))&&!(e.tShift[a]<e.blkIndent);){for(r=0;r<i&&!o[r](e,a,n,!1);r++);if(e.tight=!s,e.isEmpty(e.line-1)&&(s=!0),(a=e.line)<n&&e.isEmpty(a)){if(s=!0,++a<n&&"list"===e.parentType&&e.isEmpty(a))break;e.line=a}}};var s=/[\n\t]/g,u=/\r[\n\u0085]|[\u2424\u2028\u0085]/g,c=/\u00a0/g;a.prototype.parse=function(e,t,n,r){var i,a=0,l=0;if(!e)return[];(e=(e=e.replace(c," ")).replace(u,"\n")).indexOf("\t")>=0&&(e=e.replace(s,function(t,n){var r;return 10===e.charCodeAt(n)?(a=n+1,l=0,t):(r=" ".slice((n-a-l)%4),l=n-a+1,r)})),i=new o(e,this,t,n,r),this.tokenize(i,i.line,i.lineMax)},e.exports=a},function(e,t,n){"use strict";function r(e,t,n,r,o){var i,a,s,u,c,l,p;for(this.src=e,this.parser=t,this.options=n,this.env=r,this.tokens=o,this.bMarks=[],this.eMarks=[],this.tShift=[],this.blkIndent=0,this.line=0,this.lineMax=0,this.tight=!1,this.parentType="root",this.ddIndent=-1,this.level=0,this.result="",l=0,p=!1,s=u=l=0,c=(a=this.src).length;u<c;u++){if(i=a.charCodeAt(u),!p){if(32===i){l++;continue}p=!0}10!==i&&u!==c-1||(10!==i&&u++,this.bMarks.push(s),this.eMarks.push(u),this.tShift.push(l),p=!1,l=0,s=u+1)}this.bMarks.push(a.length),this.eMarks.push(a.length),this.tShift.push(0),this.lineMax=this.bMarks.length-1}r.prototype.isEmpty=function(e){return this.bMarks[e]+this.tShift[e]>=this.eMarks[e]},r.prototype.skipEmptyLines=function(e){for(var t=this.lineMax;e<t&&!(this.bMarks[e]+this.tShift[e]<this.eMarks[e]);e++);return e},r.prototype.skipSpaces=function(e){for(var t=this.src.length;e<t&&32===this.src.charCodeAt(e);e++);return e},r.prototype.skipChars=function(e,t){for(var n=this.src.length;e<n&&this.src.charCodeAt(e)===t;e++);return e},r.prototype.skipCharsBack=function(e,t,n){if(e<=n)return e;for(;e>n;)if(t!==this.src.charCodeAt(--e))return e+1;return e},r.prototype.getLines=function(e,t,n,r){var o,i,a,s,u,c=e;if(e>=t)return"";if(c+1===t)return i=this.bMarks[c]+Math.min(this.tShift[c],n),a=r?this.eMarks[c]+1:this.eMarks[c],this.src.slice(i,a);for(s=new Array(t-e),o=0;c<t;c++,o++)(u=this.tShift[c])>n&&(u=n),u<0&&(u=0),i=this.bMarks[c]+u,a=c+1<t||r?this.eMarks[c]+1:this.eMarks[c],s[o]=this.src.slice(i,a);return s.join("")},e.exports=r},function(e,t,n){"use strict";e.exports=function(e,t,n){var r,o;if(e.tShift[t]-e.blkIndent<4)return!1;for(o=r=t+1;r<n;)if(e.isEmpty(r))r++;else{if(!(e.tShift[r]-e.blkIndent>=4))break;o=++r}return e.line=r,e.tokens.push({type:"code",content:e.getLines(t,o,4+e.blkIndent,!0),block:!0,lines:[t,e.line],level:e.level}),!0}},function(e,t,n){"use strict";e.exports=function(e,t,n,r){var o,i,a,s,u,c=!1,l=e.bMarks[t]+e.tShift[t],p=e.eMarks[t];if(l+3>p)return!1;if(126!==(o=e.src.charCodeAt(l))&&96!==o)return!1;if(u=l,(i=(l=e.skipChars(l,o))-u)<3)return!1;if((a=e.src.slice(l,p).trim()).indexOf("`")>=0)return!1;if(r)return!0;for(s=t;!(++s>=n)&&!((l=u=e.bMarks[s]+e.tShift[s])<(p=e.eMarks[s])&&e.tShift[s]<e.blkIndent);)if(e.src.charCodeAt(l)===o&&!(e.tShift[s]-e.blkIndent>=4||(l=e.skipChars(l,o))-u<i||(l=e.skipSpaces(l))<p)){c=!0;break}return i=e.tShift[t],e.line=s+(c?1:0),e.tokens.push({type:"fence",params:a,content:e.getLines(t+1,s,i,!0),lines:[t,e.line],level:e.level}),!0}},function(e,t,n){"use strict";e.exports=function(e,t,n,r){var o,i,a,s,u,c,l,p,f,h,d,m=e.bMarks[t]+e.tShift[t],v=e.eMarks[t];if(m>v)return!1;if(62!==e.src.charCodeAt(m++))return!1;if(e.level>=e.options.maxNesting)return!1;if(r)return!0;for(32===e.src.charCodeAt(m)&&m++,u=e.blkIndent,e.blkIndent=0,s=[e.bMarks[t]],e.bMarks[t]=m,i=(m=m<v?e.skipSpaces(m):m)>=v,a=[e.tShift[t]],e.tShift[t]=m-e.bMarks[t],p=e.parser.ruler.getRules("blockquote"),o=t+1;o<n&&!((m=e.bMarks[o]+e.tShift[o])>=(v=e.eMarks[o]));o++)if(62!==e.src.charCodeAt(m++)){if(i)break;for(d=!1,f=0,h=p.length;f<h;f++)if(p[f](e,o,n,!0)){d=!0;break}if(d)break;s.push(e.bMarks[o]),a.push(e.tShift[o]),e.tShift[o]=-1337}else 32===e.src.charCodeAt(m)&&m++,s.push(e.bMarks[o]),e.bMarks[o]=m,i=(m=m<v?e.skipSpaces(m):m)>=v,a.push(e.tShift[o]),e.tShift[o]=m-e.bMarks[o];for(c=e.parentType,e.parentType="blockquote",e.tokens.push({type:"blockquote_open",lines:l=[t,0],level:e.level++}),e.parser.tokenize(e,t,o),e.tokens.push({type:"blockquote_close",level:--e.level}),e.parentType=c,l[1]=e.line,f=0;f<a.length;f++)e.bMarks[f+t]=s[f],e.tShift[f+t]=a[f];return e.blkIndent=u,!0}},function(e,t,n){"use strict";e.exports=function(e,t,n,r){var o,i,a,s=e.bMarks[t],u=e.eMarks[t];if((s+=e.tShift[t])>u)return!1;if(42!==(o=e.src.charCodeAt(s++))&&45!==o&&95!==o)return!1;for(i=1;s<u;){if((a=e.src.charCodeAt(s++))!==o&&32!==a)return!1;a===o&&i++}return!(i<3)&&(!!r||(e.line=t+1,e.tokens.push({type:"hr",lines:[t,e.line],level:e.level}),!0))}},function(e,t,n){"use strict";function r(e,t){var n,r,o;return(r=e.bMarks[t]+e.tShift[t])>=(o=e.eMarks[t])?-1:42!==(n=e.src.charCodeAt(r++))&&45!==n&&43!==n?-1:r<o&&32!==e.src.charCodeAt(r)?-1:r}function o(e,t){var n,r=e.bMarks[t]+e.tShift[t],o=e.eMarks[t];if(r+1>=o)return-1;if((n=e.src.charCodeAt(r++))<48||n>57)return-1;for(;;){if(r>=o)return-1;if(!((n=e.src.charCodeAt(r++))>=48&&n<=57)){if(41===n||46===n)break;return-1}}return r<o&&32!==e.src.charCodeAt(r)?-1:r}e.exports=function(e,t,n,i){var a,s,u,c,l,p,f,h,d,m,v,g,y,b,_,w,x,E,S,C,k,O=!0;if((h=o(e,t))>=0)g=!0;else{if(!((h=r(e,t))>=0))return!1;g=!1}if(e.level>=e.options.maxNesting)return!1;if(v=e.src.charCodeAt(h-1),i)return!0;for(b=e.tokens.length,g?(f=e.bMarks[t]+e.tShift[t],m=Number(e.src.substr(f,h-f-1)),e.tokens.push({type:"ordered_list_open",order:m,lines:w=[t,0],level:e.level++})):e.tokens.push({type:"bullet_list_open",lines:w=[t,0],level:e.level++}),a=t,_=!1,E=e.parser.ruler.getRules("list");!(!(a<n)||((d=(y=e.skipSpaces(h))>=e.eMarks[a]?1:y-h)>4&&(d=1),d<1&&(d=1),s=h-e.bMarks[a]+d,e.tokens.push({type:"list_item_open",lines:x=[t,0],level:e.level++}),c=e.blkIndent,l=e.tight,u=e.tShift[t],p=e.parentType,e.tShift[t]=y-e.bMarks[t],e.blkIndent=s,e.tight=!0,e.parentType="list",e.parser.tokenize(e,t,n,!0),e.tight&&!_||(O=!1),_=e.line-t>1&&e.isEmpty(e.line-1),e.blkIndent=c,e.tShift[t]=u,e.tight=l,e.parentType=p,e.tokens.push({type:"list_item_close",level:--e.level}),a=t=e.line,x[1]=a,y=e.bMarks[t],a>=n)||e.isEmpty(a)||e.tShift[a]<e.blkIndent);){for(k=!1,S=0,C=E.length;S<C;S++)if(E[S](e,a,n,!0)){k=!0;break}if(k)break;if(g){if((h=o(e,a))<0)break}else if((h=r(e,a))<0)break;if(v!==e.src.charCodeAt(h-1))break}return e.tokens.push({type:g?"ordered_list_close":"bullet_list_close",level:--e.level}),w[1]=a,e.line=a,O&&function(e,t){var n,r,o=e.level+2;for(n=t+2,r=e.tokens.length-2;n<r;n++)e.tokens[n].level===o&&"paragraph_open"===e.tokens[n].type&&(e.tokens[n+2].tight=!0,e.tokens[n].tight=!0,n+=2)}(e,b),!0}},function(e,t,n){"use strict";e.exports=function(e,t,n,r){var o,i,a,s,u,c=e.bMarks[t]+e.tShift[t],l=e.eMarks[t];if(c+4>l)return!1;if(91!==e.src.charCodeAt(c))return!1;if(94!==e.src.charCodeAt(c+1))return!1;if(e.level>=e.options.maxNesting)return!1;for(s=c+2;s<l;s++){if(32===e.src.charCodeAt(s))return!1;if(93===e.src.charCodeAt(s))break}return s!==c+2&&(!(s+1>=l||58!==e.src.charCodeAt(++s))&&(!!r||(s++,e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.refs||(e.env.footnotes.refs={}),u=e.src.slice(c+2,s-2),e.env.footnotes.refs[":"+u]=-1,e.tokens.push({type:"footnote_reference_open",label:u,level:e.level++}),o=e.bMarks[t],i=e.tShift[t],a=e.parentType,e.tShift[t]=e.skipSpaces(s)-s,e.bMarks[t]=s,e.blkIndent+=4,e.parentType="footnote",e.tShift[t]<e.blkIndent&&(e.tShift[t]+=e.blkIndent,e.bMarks[t]-=e.blkIndent),e.parser.tokenize(e,t,n,!0),e.parentType=a,e.blkIndent-=4,e.tShift[t]=i,e.bMarks[t]=o,e.tokens.push({type:"footnote_reference_close",level:--e.level}),!0)))}},function(e,t,n){"use strict";e.exports=function(e,t,n,r){var o,i,a,s=e.bMarks[t]+e.tShift[t],u=e.eMarks[t];if(s>=u)return!1;if(35!==(o=e.src.charCodeAt(s))||s>=u)return!1;for(i=1,o=e.src.charCodeAt(++s);35===o&&s<u&&i<=6;)i++,o=e.src.charCodeAt(++s);return!(i>6||s<u&&32!==o)&&(!!r||(u=e.skipCharsBack(u,32,s),(a=e.skipCharsBack(u,35,s))>s&&32===e.src.charCodeAt(a-1)&&(u=a),e.line=t+1,e.tokens.push({type:"heading_open",hLevel:i,lines:[t,e.line],level:e.level}),s<u&&e.tokens.push({type:"inline",content:e.src.slice(s,u).trim(),level:e.level+1,lines:[t,e.line],children:[]}),e.tokens.push({type:"heading_close",hLevel:i,level:e.level}),!0))}},function(e,t,n){"use strict";e.exports=function(e,t,n){var r,o,i,a=t+1;return!(a>=n)&&(!(e.tShift[a]<e.blkIndent)&&(!(e.tShift[a]-e.blkIndent>3)&&(!((o=e.bMarks[a]+e.tShift[a])>=(i=e.eMarks[a]))&&((45===(r=e.src.charCodeAt(o))||61===r)&&(o=e.skipChars(o,r),!((o=e.skipSpaces(o))<i)&&(o=e.bMarks[t]+e.tShift[t],e.line=a+1,e.tokens.push({type:"heading_open",hLevel:61===r?1:2,lines:[t,e.line],level:e.level}),e.tokens.push({type:"inline",content:e.src.slice(o,e.eMarks[t]).trim(),level:e.level+1,lines:[t,e.line-1],children:[]}),e.tokens.push({type:"heading_close",hLevel:61===r?1:2,level:e.level}),!0))))))}},function(e,t,n){"use strict";var r=n(992),o=/^<([a-zA-Z]{1,15})[\s\/>]/,i=/^<\/([a-zA-Z]{1,15})[\s>]/;e.exports=function(e,t,n,a){var s,u,c,l=e.bMarks[t],p=e.eMarks[t],f=e.tShift[t];if(l+=f,!e.options.html)return!1;if(f>3||l+2>=p)return!1;if(60!==e.src.charCodeAt(l))return!1;if(33===(s=e.src.charCodeAt(l+1))||63===s){if(a)return!0}else{if(47!==s&&!function(e){var t=32|e;return t>=97&&t<=122}(s))return!1;if(47===s){if(!(u=e.src.slice(l,p).match(i)))return!1}else if(!(u=e.src.slice(l,p).match(o)))return!1;if(!0!==r[u[1].toLowerCase()])return!1;if(a)return!0}for(c=t+1;c<e.lineMax&&!e.isEmpty(c);)c++;return e.line=c,e.tokens.push({type:"htmlblock",level:e.level,lines:[t,e.line],content:e.getLines(t,c,0,!0)}),!0}},function(e,t,n){"use strict";var r={};["article","aside","button","blockquote","body","canvas","caption","col","colgroup","dd","div","dl","dt","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","iframe","li","map","object","ol","output","p","pre","progress","script","section","style","table","tbody","td","textarea","tfoot","th","tr","thead","ul","video"].forEach(function(e){r[e]=!0}),e.exports=r},function(e,t,n){"use strict";function r(e,t){var n=e.bMarks[t]+e.blkIndent,r=e.eMarks[t];return e.src.substr(n,r-n)}e.exports=function(e,t,n,o){var i,a,s,u,c,l,p,f,h,d,m;if(t+2>n)return!1;if(c=t+1,e.tShift[c]<e.blkIndent)return!1;if((s=e.bMarks[c]+e.tShift[c])>=e.eMarks[c])return!1;if(124!==(i=e.src.charCodeAt(s))&&45!==i&&58!==i)return!1;if(a=r(e,t+1),!/^[-:| ]+$/.test(a))return!1;if((l=a.split("|"))<=2)return!1;for(f=[],u=0;u<l.length;u++){if(!(h=l[u].trim())){if(0===u||u===l.length-1)continue;return!1}if(!/^:?-+:?$/.test(h))return!1;58===h.charCodeAt(h.length-1)?f.push(58===h.charCodeAt(0)?"center":"right"):58===h.charCodeAt(0)?f.push("left"):f.push("")}if(-1===(a=r(e,t).trim()).indexOf("|"))return!1;if(l=a.replace(/^\||\|$/g,"").split("|"),f.length!==l.length)return!1;if(o)return!0;for(e.tokens.push({type:"table_open",lines:d=[t,0],level:e.level++}),e.tokens.push({type:"thead_open",lines:[t,t+1],level:e.level++}),e.tokens.push({type:"tr_open",lines:[t,t+1],level:e.level++}),u=0;u<l.length;u++)e.tokens.push({type:"th_open",align:f[u],lines:[t,t+1],level:e.level++}),e.tokens.push({type:"inline",content:l[u].trim(),lines:[t,t+1],level:e.level,children:[]}),e.tokens.push({type:"th_close",level:--e.level});for(e.tokens.push({type:"tr_close",level:--e.level}),e.tokens.push({type:"thead_close",level:--e.level}),e.tokens.push({type:"tbody_open",lines:m=[t+2,0],level:e.level++}),c=t+2;c<n&&!(e.tShift[c]<e.blkIndent)&&-1!==(a=r(e,c).trim()).indexOf("|");c++){for(l=a.replace(/^\||\|$/g,"").split("|"),e.tokens.push({type:"tr_open",level:e.level++}),u=0;u<l.length;u++)e.tokens.push({type:"td_open",align:f[u],level:e.level++}),p=l[u].substring(124===l[u].charCodeAt(0)?1:0,124===l[u].charCodeAt(l[u].length-1)?l[u].length-1:l[u].length).trim(),e.tokens.push({type:"inline",content:p,level:e.level,children:[]}),e.tokens.push({type:"td_close",level:--e.level});e.tokens.push({type:"tr_close",level:--e.level})}return e.tokens.push({type:"tbody_close",level:--e.level}),e.tokens.push({type:"table_close",level:--e.level}),d[1]=m[1]=c,e.line=c,!0}},function(e,t,n){"use strict";function r(e,t){var n,r,o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];return o>=i?-1:126!==(r=e.src.charCodeAt(o++))&&58!==r?-1:o===(n=e.skipSpaces(o))?-1:n>=i?-1:n}e.exports=function(e,t,n,o){var i,a,s,u,c,l,p,f,h,d,m,v,g,y;if(o)return!(e.ddIndent<0)&&r(e,t)>=0;if(p=t+1,e.isEmpty(p)&&++p>n)return!1;if(e.tShift[p]<e.blkIndent)return!1;if((i=r(e,p))<0)return!1;if(e.level>=e.options.maxNesting)return!1;l=e.tokens.length,e.tokens.push({type:"dl_open",lines:c=[t,0],level:e.level++}),s=t,a=p;e:for(;;){for(y=!0,g=!1,e.tokens.push({type:"dt_open",lines:[s,s],level:e.level++}),e.tokens.push({type:"inline",content:e.getLines(s,s+1,e.blkIndent,!1).trim(),level:e.level+1,lines:[s,s],children:[]}),e.tokens.push({type:"dt_close",level:--e.level});;){if(e.tokens.push({type:"dd_open",lines:u=[p,0],level:e.level++}),v=e.tight,h=e.ddIndent,f=e.blkIndent,m=e.tShift[a],d=e.parentType,e.blkIndent=e.ddIndent=e.tShift[a]+2,e.tShift[a]=i-e.bMarks[a],e.tight=!0,e.parentType="deflist",e.parser.tokenize(e,a,n,!0),e.tight&&!g||(y=!1),g=e.line-a>1&&e.isEmpty(e.line-1),e.tShift[a]=m,e.tight=v,e.parentType=d,e.blkIndent=f,e.ddIndent=h,e.tokens.push({type:"dd_close",level:--e.level}),u[1]=p=e.line,p>=n)break e;if(e.tShift[p]<e.blkIndent)break e;if((i=r(e,p))<0)break;a=p}if(p>=n)break;if(s=p,e.isEmpty(s))break;if(e.tShift[s]<e.blkIndent)break;if((a=s+1)>=n)break;if(e.isEmpty(a)&&a++,a>=n)break;if(e.tShift[a]<e.blkIndent)break;if((i=r(e,a))<0)break}return e.tokens.push({type:"dl_close",level:--e.level}),c[1]=p,e.line=p,y&&function(e,t){var n,r,o=e.level+2;for(n=t+2,r=e.tokens.length-2;n<r;n++)e.tokens[n].level===o&&"paragraph_open"===e.tokens[n].type&&(e.tokens[n+2].tight=!0,e.tokens[n].tight=!0,n+=2)}(e,l),!0}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a,s,u=t+1;if(u<(n=e.lineMax)&&!e.isEmpty(u))for(s=e.parser.ruler.getRules("paragraph");u<n&&!e.isEmpty(u);u++)if(!(e.tShift[u]-e.blkIndent>3)){for(o=!1,i=0,a=s.length;i<a;i++)if(s[i](e,u,n,!0)){o=!0;break}if(o)break}return r=e.getLines(t,u,e.blkIndent,!1).trim(),e.line=u,r.length&&(e.tokens.push({type:"paragraph_open",tight:!1,lines:[t,e.line],level:e.level}),e.tokens.push({type:"inline",content:r,level:e.level+1,lines:[t,e.line],children:[]}),e.tokens.push({type:"paragraph_close",tight:!1,level:e.level})),!0}},function(e,t,n){"use strict";var r=n(187),o=n(261),i=n(37),a=[["text",n(997)],["newline",n(998)],["escape",n(999)],["backticks",n(1e3)],["del",n(1001)],["ins",n(1002)],["mark",n(1003)],["emphasis",n(1004)],["sub",n(1005)],["sup",n(1006)],["links",n(1007)],["footnote_inline",n(1008)],["footnote_ref",n(1009)],["autolink",n(1010)],["htmltag",n(1012)],["entity",n(1014)]];function s(){this.ruler=new r;for(var e=0;e<a.length;e++)this.ruler.push(a[e][0],a[e][1]);this.validateLink=u}function u(e){var t=e.trim().toLowerCase();return-1===(t=i.replaceEntities(t)).indexOf(":")||-1===["vbscript","javascript","file","data"].indexOf(t.split(":")[0])}s.prototype.skipToken=function(e){var t,n,r=this.ruler.getRules(""),o=r.length,i=e.pos;if((n=e.cacheGet(i))>0)e.pos=n;else{for(t=0;t<o;t++)if(r[t](e,!0))return void e.cacheSet(i,e.pos);e.pos++,e.cacheSet(i,e.pos)}},s.prototype.tokenize=function(e){for(var t,n,r=this.ruler.getRules(""),o=r.length,i=e.posMax;e.pos<i;){for(n=0;n<o&&!(t=r[n](e,!1));n++);if(t){if(e.pos>=i)break}else e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()},s.prototype.parse=function(e,t,n,r){var i=new o(e,this,t,n,r);this.tokenize(i)},e.exports=s},function(e,t,n){"use strict";function r(e){switch(e){case 10:case 92:case 96:case 42:case 95:case 94:case 91:case 93:case 33:case 38:case 60:case 62:case 123:case 125:case 36:case 37:case 64:case 126:case 43:case 61:case 58:return!0;default:return!1}}e.exports=function(e,t){for(var n=e.pos;n<e.posMax&&!r(e.src.charCodeAt(n));)n++;return n!==e.pos&&(t||(e.pending+=e.src.slice(e.pos,n)),e.pos=n,!0)}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o=e.pos;if(10!==e.src.charCodeAt(o))return!1;if(n=e.pending.length-1,r=e.posMax,!t)if(n>=0&&32===e.pending.charCodeAt(n))if(n>=1&&32===e.pending.charCodeAt(n-1)){for(var i=n-2;i>=0;i--)if(32!==e.pending.charCodeAt(i)){e.pending=e.pending.substring(0,i+1);break}e.push({type:"hardbreak",level:e.level})}else e.pending=e.pending.slice(0,-1),e.push({type:"softbreak",level:e.level});else e.push({type:"softbreak",level:e.level});for(o++;o<r&&32===e.src.charCodeAt(o);)o++;return e.pos=o,!0}},function(e,t,n){"use strict";for(var r=[],o=0;o<256;o++)r.push(0);"\\!\"#$%&'()*+,./:;<=>?@[]^_`{|}~-".split("").forEach(function(e){r[e.charCodeAt(0)]=1}),e.exports=function(e,t){var n,o=e.pos,i=e.posMax;if(92!==e.src.charCodeAt(o))return!1;if(++o<i){if((n=e.src.charCodeAt(o))<256&&0!==r[n])return t||(e.pending+=e.src[o]),e.pos+=2,!0;if(10===n){for(t||e.push({type:"hardbreak",level:e.level}),o++;o<i&&32===e.src.charCodeAt(o);)o++;return e.pos=o,!0}}return t||(e.pending+="\\"),e.pos++,!0}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a,s=e.pos;if(96!==e.src.charCodeAt(s))return!1;for(n=s,s++,r=e.posMax;s<r&&96===e.src.charCodeAt(s);)s++;for(o=e.src.slice(n,s),i=a=s;-1!==(i=e.src.indexOf("`",a));){for(a=i+1;a<r&&96===e.src.charCodeAt(a);)a++;if(a-i===o.length)return t||e.push({type:"code",content:e.src.slice(s,i).replace(/[ \n]+/g," ").trim(),block:!1,level:e.level}),e.pos=a,!0}return t||(e.pending+=o),e.pos+=o.length,!0}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a,s=e.posMax,u=e.pos;if(126!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=s)return!1;if(126!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(i=u>0?e.src.charCodeAt(u-1):-1,a=e.src.charCodeAt(u+2),126===i)return!1;if(126===a)return!1;if(32===a||10===a)return!1;for(r=u+2;r<s&&126===e.src.charCodeAt(r);)r++;if(r>u+3)return e.pos+=r-u,t||(e.pending+=e.src.slice(u,r)),!0;for(e.pos=u+2,o=1;e.pos+1<s;){if(126===e.src.charCodeAt(e.pos)&&126===e.src.charCodeAt(e.pos+1)&&(i=e.src.charCodeAt(e.pos-1),126!==(a=e.pos+2<s?e.src.charCodeAt(e.pos+2):-1)&&126!==i&&(32!==i&&10!==i?o--:32!==a&&10!==a&&o++,o<=0))){n=!0;break}e.parser.skipToken(e)}return n?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:"del_open",level:e.level++}),e.parser.tokenize(e),e.push({type:"del_close",level:--e.level})),e.pos=e.posMax+2,e.posMax=s,!0):(e.pos=u,!1)}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a,s=e.posMax,u=e.pos;if(43!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=s)return!1;if(43!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(i=u>0?e.src.charCodeAt(u-1):-1,a=e.src.charCodeAt(u+2),43===i)return!1;if(43===a)return!1;if(32===a||10===a)return!1;for(r=u+2;r<s&&43===e.src.charCodeAt(r);)r++;if(r!==u+2)return e.pos+=r-u,t||(e.pending+=e.src.slice(u,r)),!0;for(e.pos=u+2,o=1;e.pos+1<s;){if(43===e.src.charCodeAt(e.pos)&&43===e.src.charCodeAt(e.pos+1)&&(i=e.src.charCodeAt(e.pos-1),43!==(a=e.pos+2<s?e.src.charCodeAt(e.pos+2):-1)&&43!==i&&(32!==i&&10!==i?o--:32!==a&&10!==a&&o++,o<=0))){n=!0;break}e.parser.skipToken(e)}return n?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:"ins_open",level:e.level++}),e.parser.tokenize(e),e.push({type:"ins_close",level:--e.level})),e.pos=e.posMax+2,e.posMax=s,!0):(e.pos=u,!1)}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a,s=e.posMax,u=e.pos;if(61!==e.src.charCodeAt(u))return!1;if(t)return!1;if(u+4>=s)return!1;if(61!==e.src.charCodeAt(u+1))return!1;if(e.level>=e.options.maxNesting)return!1;if(i=u>0?e.src.charCodeAt(u-1):-1,a=e.src.charCodeAt(u+2),61===i)return!1;if(61===a)return!1;if(32===a||10===a)return!1;for(r=u+2;r<s&&61===e.src.charCodeAt(r);)r++;if(r!==u+2)return e.pos+=r-u,t||(e.pending+=e.src.slice(u,r)),!0;for(e.pos=u+2,o=1;e.pos+1<s;){if(61===e.src.charCodeAt(e.pos)&&61===e.src.charCodeAt(e.pos+1)&&(i=e.src.charCodeAt(e.pos-1),61!==(a=e.pos+2<s?e.src.charCodeAt(e.pos+2):-1)&&61!==i&&(32!==i&&10!==i?o--:32!==a&&10!==a&&o++,o<=0))){n=!0;break}e.parser.skipToken(e)}return n?(e.posMax=e.pos,e.pos=u+2,t||(e.push({type:"mark_open",level:e.level++}),e.parser.tokenize(e),e.push({type:"mark_close",level:--e.level})),e.pos=e.posMax+2,e.posMax=s,!0):(e.pos=u,!1)}},function(e,t,n){"use strict";function r(e){return e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122}function o(e,t){var n,o,i,a=t,s=!0,u=!0,c=e.posMax,l=e.src.charCodeAt(t);for(n=t>0?e.src.charCodeAt(t-1):-1;a<c&&e.src.charCodeAt(a)===l;)a++;return a>=c&&(s=!1),(i=a-t)>=4?s=u=!1:(32!==(o=a<c?e.src.charCodeAt(a):-1)&&10!==o||(s=!1),32!==n&&10!==n||(u=!1),95===l&&(r(n)&&(s=!1),r(o)&&(u=!1))),{can_open:s,can_close:u,delims:i}}e.exports=function(e,t){var n,r,i,a,s,u,c,l=e.posMax,p=e.pos,f=e.src.charCodeAt(p);if(95!==f&&42!==f)return!1;if(t)return!1;if(n=(c=o(e,p)).delims,!c.can_open)return e.pos+=n,t||(e.pending+=e.src.slice(p,e.pos)),!0;if(e.level>=e.options.maxNesting)return!1;for(e.pos=p+n,u=[n];e.pos<l;)if(e.src.charCodeAt(e.pos)!==f)e.parser.skipToken(e);else{if(r=(c=o(e,e.pos)).delims,c.can_close){for(a=u.pop(),s=r;a!==s;){if(s<a){u.push(a-s);break}if(s-=a,0===u.length)break;e.pos+=a,a=u.pop()}if(0===u.length){n=a,i=!0;break}e.pos+=r;continue}c.can_open&&u.push(r),e.pos+=r}return i?(e.posMax=e.pos,e.pos=p+n,t||(2!==n&&3!==n||e.push({type:"strong_open",level:e.level++}),1!==n&&3!==n||e.push({type:"em_open",level:e.level++}),e.parser.tokenize(e),1!==n&&3!==n||e.push({type:"em_close",level:--e.level}),2!==n&&3!==n||e.push({type:"strong_close",level:--e.level})),e.pos=e.posMax+n,e.posMax=l,!0):(e.pos=p,!1)}},function(e,t,n){"use strict";var r=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;e.exports=function(e,t){var n,o,i=e.posMax,a=e.pos;if(126!==e.src.charCodeAt(a))return!1;if(t)return!1;if(a+2>=i)return!1;if(e.level>=e.options.maxNesting)return!1;for(e.pos=a+1;e.pos<i;){if(126===e.src.charCodeAt(e.pos)){n=!0;break}e.parser.skipToken(e)}return n&&a+1!==e.pos?(o=e.src.slice(a+1,e.pos)).match(/(^|[^\\])(\\\\)*\s/)?(e.pos=a,!1):(e.posMax=e.pos,e.pos=a+1,t||e.push({type:"sub",level:e.level,content:o.replace(r,"$1")}),e.pos=e.posMax+1,e.posMax=i,!0):(e.pos=a,!1)}},function(e,t,n){"use strict";var r=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;e.exports=function(e,t){var n,o,i=e.posMax,a=e.pos;if(94!==e.src.charCodeAt(a))return!1;if(t)return!1;if(a+2>=i)return!1;if(e.level>=e.options.maxNesting)return!1;for(e.pos=a+1;e.pos<i;){if(94===e.src.charCodeAt(e.pos)){n=!0;break}e.parser.skipToken(e)}return n&&a+1!==e.pos?(o=e.src.slice(a+1,e.pos)).match(/(^|[^\\])(\\\\)*\s/)?(e.pos=a,!1):(e.posMax=e.pos,e.pos=a+1,t||e.push({type:"sup",level:e.level,content:o.replace(r,"$1")}),e.pos=e.posMax+1,e.posMax=i,!0):(e.pos=a,!1)}},function(e,t,n){"use strict";var r=n(188),o=n(458),i=n(460),a=n(461);e.exports=function(e,t){var n,s,u,c,l,p,f,h,d=!1,m=e.pos,v=e.posMax,g=e.pos,y=e.src.charCodeAt(g);if(33===y&&(d=!0,y=e.src.charCodeAt(++g)),91!==y)return!1;if(e.level>=e.options.maxNesting)return!1;if(n=g+1,(s=r(e,g))<0)return!1;if((p=s+1)<v&&40===e.src.charCodeAt(p)){for(p++;p<v&&(32===(h=e.src.charCodeAt(p))||10===h);p++);if(p>=v)return!1;for(g=p,o(e,p)?(c=e.linkContent,p=e.pos):c="",g=p;p<v&&(32===(h=e.src.charCodeAt(p))||10===h);p++);if(p<v&&g!==p&&i(e,p))for(l=e.linkContent,p=e.pos;p<v&&(32===(h=e.src.charCodeAt(p))||10===h);p++);else l="";if(p>=v||41!==e.src.charCodeAt(p))return e.pos=m,!1;p++}else{if(e.linkLevel>0)return!1;for(;p<v&&(32===(h=e.src.charCodeAt(p))||10===h);p++);if(p<v&&91===e.src.charCodeAt(p)&&(g=p+1,(p=r(e,p))>=0?u=e.src.slice(g,p++):p=g-1),u||(void 0===u&&(p=s+1),u=e.src.slice(n,s)),!(f=e.env.references[a(u)]))return e.pos=m,!1;c=f.href,l=f.title}return t||(e.pos=n,e.posMax=s,d?e.push({type:"image",src:c,title:l,alt:e.src.substr(n,s-n),level:e.level}):(e.push({type:"link_open",href:c,title:l,level:e.level++}),e.linkLevel++,e.parser.tokenize(e),e.linkLevel--,e.push({type:"link_close",level:--e.level}))),e.pos=p,e.posMax=v,!0}},function(e,t,n){"use strict";var r=n(188);e.exports=function(e,t){var n,o,i,a,s=e.posMax,u=e.pos;return!(u+2>=s)&&(94===e.src.charCodeAt(u)&&(91===e.src.charCodeAt(u+1)&&(!(e.level>=e.options.maxNesting)&&(n=u+2,!((o=r(e,u+1))<0)&&(t||(e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.list||(e.env.footnotes.list=[]),i=e.env.footnotes.list.length,e.pos=n,e.posMax=o,e.push({type:"footnote_ref",id:i,level:e.level}),e.linkLevel++,a=e.tokens.length,e.parser.tokenize(e),e.env.footnotes.list[i]={tokens:e.tokens.splice(a)},e.linkLevel--),e.pos=o+1,e.posMax=s,!0)))))}},function(e,t,n){"use strict";e.exports=function(e,t){var n,r,o,i,a=e.posMax,s=e.pos;if(s+3>a)return!1;if(!e.env.footnotes||!e.env.footnotes.refs)return!1;if(91!==e.src.charCodeAt(s))return!1;if(94!==e.src.charCodeAt(s+1))return!1;if(e.level>=e.options.maxNesting)return!1;for(r=s+2;r<a;r++){if(32===e.src.charCodeAt(r))return!1;if(10===e.src.charCodeAt(r))return!1;if(93===e.src.charCodeAt(r))break}return r!==s+2&&(!(r>=a)&&(r++,n=e.src.slice(s+2,r-1),void 0!==e.env.footnotes.refs[":"+n]&&(t||(e.env.footnotes.list||(e.env.footnotes.list=[]),e.env.footnotes.refs[":"+n]<0?(o=e.env.footnotes.list.length,e.env.footnotes.list[o]={label:n,count:0},e.env.footnotes.refs[":"+n]=o):o=e.env.footnotes.refs[":"+n],i=e.env.footnotes.list[o].count,e.env.footnotes.list[o].count++,e.push({type:"footnote_ref",id:o,subId:i,level:e.level})),e.pos=r,e.posMax=a,!0)))}},function(e,t,n){"use strict";var r=n(1011),o=n(459),i=/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/,a=/^<([a-zA-Z.\-]{1,25}):([^<>\x00-\x20]*)>/;e.exports=function(e,t){var n,s,u,c,l,p=e.pos;return 60===e.src.charCodeAt(p)&&(!((n=e.src.slice(p)).indexOf(">")<0)&&((s=n.match(a))?!(r.indexOf(s[1].toLowerCase())<0)&&(c=s[0].slice(1,-1),l=o(c),!!e.parser.validateLink(c)&&(t||(e.push({type:"link_open",href:l,level:e.level}),e.push({type:"text",content:c,level:e.level+1}),e.push({type:"link_close",level:e.level})),e.pos+=s[0].length,!0)):!!(u=n.match(i))&&(c=u[0].slice(1,-1),l=o("mailto:"+c),!!e.parser.validateLink(l)&&(t||(e.push({type:"link_open",href:l,level:e.level}),e.push({type:"text",content:c,level:e.level+1}),e.push({type:"link_close",level:e.level})),e.pos+=u[0].length,!0))))}},function(e,t,n){"use strict";e.exports=["coap","doi","javascript","aaa","aaas","about","acap","cap","cid","crid","data","dav","dict","dns","file","ftp","geo","go","gopher","h323","http","https","iax","icap","im","imap","info","ipp","iris","iris.beep","iris.xpc","iris.xpcs","iris.lwz","ldap","mailto","mid","msrp","msrps","mtqp","mupdate","news","nfs","ni","nih","nntp","opaquelocktoken","pop","pres","rtsp","service","session","shttp","sieve","sip","sips","sms","snmp","soap.beep","soap.beeps","tag","tel","telnet","tftp","thismessage","tn3270","tip","tv","urn","vemmi","ws","wss","xcon","xcon-userid","xmlrpc.beep","xmlrpc.beeps","xmpp","z39.50r","z39.50s","adiumxtra","afp","afs","aim","apt","attachment","aw","beshare","bitcoin","bolo","callto","chrome","chrome-extension","com-eventbrite-attendee","content","cvs","dlna-playsingle","dlna-playcontainer","dtn","dvb","ed2k","facetime","feed","finger","fish","gg","git","gizmoproject","gtalk","hcp","icon","ipn","irc","irc6","ircs","itms","jar","jms","keyparc","lastfm","ldaps","magnet","maps","market","message","mms","ms-help","msnim","mumble","mvn","notes","oid","palm","paparazzi","platform","proxy","psyc","query","res","resource","rmi","rsync","rtmp","secondlife","sftp","sgn","skype","smb","soldat","spotify","ssh","steam","svn","teamspeak","things","udp","unreal","ut2004","ventrilo","view-source","webcal","wtai","wyciwyg","xfire","xri","ymsgr"]},function(e,t,n){"use strict";var r=n(1013).HTML_TAG_RE;e.exports=function(e,t){var n,o,i,a=e.pos;return!!e.options.html&&(i=e.posMax,!(60!==e.src.charCodeAt(a)||a+2>=i)&&(!(33!==(n=e.src.charCodeAt(a+1))&&63!==n&&47!==n&&!function(e){var t=32|e;return t>=97&&t<=122}(n))&&(!!(o=e.src.slice(a).match(r))&&(t||e.push({type:"htmltag",content:e.src.slice(a,a+o[0].length),level:e.level}),e.pos+=o[0].length,!0))))}},function(e,t,n){"use strict";function r(e,t){return e=e.source,t=t||"",function n(r,o){return r?(o=o.source||o,e=e.replace(r,o),n):new RegExp(e,t)}}var o=r(/(?:unquoted|single_quoted|double_quoted)/)("unquoted",/[^"'=<>`\x00-\x20]+/)("single_quoted",/'[^']*'/)("double_quoted",/"[^"]*"/)(),i=r(/(?:\s+attr_name(?:\s*=\s*attr_value)?)/)("attr_name",/[a-zA-Z_:][a-zA-Z0-9:._-]*/)("attr_value",o)(),a=r(/<[A-Za-z][A-Za-z0-9]*attribute*\s*\/?>/)("attribute",i)(),s=r(/^(?:open_tag|close_tag|comment|processing|declaration|cdata)/)("open_tag",a)("close_tag",/<\/[A-Za-z][A-Za-z0-9]*\s*>/)("comment",/<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->/)("processing",/<[?].*?[?]>/)("declaration",/<![A-Z]+\s+[^>]*>/)("cdata",/<!\[CDATA\[[\s\S]*?\]\]>/)();e.exports.HTML_TAG_RE=s},function(e,t,n){"use strict";var r=n(457),o=n(37).has,i=n(37).isValidEntityCode,a=n(37).fromCodePoint,s=/^&#((?:x[a-f0-9]{1,8}|[0-9]{1,8}));/i,u=/^&([a-z][a-z0-9]{1,31});/i;e.exports=function(e,t){var n,c,l=e.pos,p=e.posMax;if(38!==e.src.charCodeAt(l))return!1;if(l+1<p)if(35===e.src.charCodeAt(l+1)){if(c=e.src.slice(l).match(s))return t||(n="x"===c[1][0].toLowerCase()?parseInt(c[1].slice(1),16):parseInt(c[1],10),e.pending+=i(n)?a(n):a(65533)),e.pos+=c[0].length,!0}else if((c=e.src.slice(l).match(u))&&o(r,c[1]))return t||(e.pending+=r[c[1]]),e.pos+=c[0].length,!0;return t||(e.pending+="&"),e.pos++,!0}},function(e,t,n){"use strict";e.exports={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,linkTarget:"",typographer:!1,quotes:"“”‘’",highlight:null,maxNesting:20},components:{core:{rules:["block","inline","references","replacements","linkify","smartquotes","references","abbr2","footnote_tail"]},block:{rules:["blockquote","code","fences","footnote","heading","hr","htmlblock","lheading","list","paragraph","table"]},inline:{rules:["autolink","backticks","del","emphasis","entity","escape","footnote_ref","htmltag","links","newline","text"]}}}},function(e,t,n){"use strict";e.exports={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,linkTarget:"",typographer:!1,quotes:"“”‘’",highlight:null,maxNesting:20},components:{core:{},block:{},inline:{}}}},function(e,t,n){"use strict";e.exports={options:{html:!0,xhtmlOut:!0,breaks:!1,langPrefix:"language-",linkify:!1,linkTarget:"",typographer:!1,quotes:"“”‘’",highlight:null,maxNesting:20},components:{core:{rules:["block","inline","references","abbr2"]},block:{rules:["blockquote","code","fences","heading","hr","htmlblock","lheading","list","paragraph"]},inline:{rules:["autolink","backticks","emphasis","entity","escape","htmltag","links","newline","text"]}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DebounceInput=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=s(n(0)),a=s(n(1019));function s(e){return e&&e.__esModule?e:{default:e}}(t.DebounceInput=function(e){function t(e){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.onChange=function(e){e.persist();var t=n.state.value;n.setState({value:e.target.value},function(){var o=n.state.value;o.length>=n.props.minLength?n.notify(e):t.length>o.length&&n.notify(r({},e,{target:r({},e.target,{value:""})}))})},n.onKeyDown=function(e){var t=n.props.onKeyDown;"Enter"===e.key&&n.forceNotify(e),t&&t(e)},n.onBlur=function(e){var t=n.props.onBlur;n.forceNotify(e),t&&t(e)},n.createNotifier=function(e){if(e<0)n.notify=function(){return null};else if(0===e)n.notify=n.doNotify;else{var t=(0,a.default)(function(e){n.isDebouncing=!1,n.doNotify(e)},e);n.notify=function(e){n.isDebouncing=!0,t(e)},n.flush=function(){return t.flush()},n.cancel=function(){n.isDebouncing=!1,t.cancel()}}},n.doNotify=function(){var e=n.props.onChange;e.apply(void 0,arguments)},n.forceNotify=function(e){if(n.isDebouncing){n.cancel&&n.cancel();var t=n.state.value,o=n.props.minLength;t.length>=o?n.doNotify(e):n.doNotify(r({},e,{target:r({},e.target,{value:t})}))}},n.state={value:e.value||""},n.isDebouncing=!1,n}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,i.default.PureComponent),o(t,[{key:"componentWillMount",value:function(){this.createNotifier(this.props.debounceTimeout)}},{key:"componentWillReceiveProps",value:function(e){var t=e.value,n=e.debounceTimeout;this.isDebouncing||(void 0!==t&&this.state.value!==t&&this.setState({value:t}),n!==this.props.debounceTimeout&&this.createNotifier(n))}},{key:"componentWillUnmount",value:function(){this.flush&&this.flush()}},{key:"render",value:function(){var e=this.props,t=e.element,n=(e.onChange,e.value,e.minLength,e.debounceTimeout,e.forceNotifyByEnter),o=e.forceNotifyOnBlur,a=e.onKeyDown,s=e.onBlur,u=e.inputRef,c=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(e,["element","onChange","value","minLength","debounceTimeout","forceNotifyByEnter","forceNotifyOnBlur","onKeyDown","onBlur","inputRef"]),l=void 0;l=n?{onKeyDown:this.onKeyDown}:a?{onKeyDown:a}:{};var p=void 0;p=o?{onBlur:this.onBlur}:s?{onBlur:s}:{};var f=u?{ref:u}:{};return i.default.createElement(t,r({},c,{onChange:this.onChange,value:this.state.value},l,p,f))}}]),t}()).defaultProps={element:"input",type:"text",onKeyDown:void 0,onBlur:void 0,value:void 0,minLength:0,debounceTimeout:100,forceNotifyByEnter:!0,forceNotifyOnBlur:!0,inputRef:void 0}},function(e,t,n){(function(t){var n="Expected a function",r=NaN,o="[object Symbol]",i=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,u=/^0o[0-7]+$/i,c=parseInt,l="object"==typeof t&&t&&t.Object===Object&&t,p="object"==typeof self&&self&&self.Object===Object&&self,f=l||p||Function("return this")(),h=Object.prototype.toString,d=Math.max,m=Math.min,v=function(){return f.Date.now()};function g(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function y(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&h.call(e)==o}(e))return r;if(g(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=g(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(i,"");var n=s.test(e);return n||u.test(e)?c(e.slice(2),n?2:8):a.test(e)?r:+e}e.exports=function(e,t,r){var o,i,a,s,u,c,l=0,p=!1,f=!1,h=!0;if("function"!=typeof e)throw new TypeError(n);function b(t){var n=o,r=i;return o=i=void 0,l=t,s=e.apply(r,n)}function _(e){var n=e-c;return void 0===c||n>=t||n<0||f&&e-l>=a}function w(){var e=v();if(_(e))return x(e);u=setTimeout(w,function(e){var n=t-(e-c);return f?m(n,a-(e-l)):n}(e))}function x(e){return u=void 0,h&&o?b(e):(o=i=void 0,s)}function E(){var e=v(),n=_(e);if(o=arguments,i=this,c=e,n){if(void 0===u)return function(e){return l=e,u=setTimeout(w,t),p?b(e):s}(c);if(f)return u=setTimeout(w,t),b(c)}return void 0===u&&(u=setTimeout(w,t)),s}return t=y(t)||0,g(r)&&(p=!!r.leading,a=(f="maxWait"in r)?d(y(r.maxWait)||0,t):a,h="trailing"in r?!!r.trailing:h),E.cancel=function(){void 0!==u&&clearTimeout(u),l=0,o=c=i=u=void 0},E.flush=function(){return void 0===u?s:x(v())},E}}).call(this,n(41))},function(e,t,n){var r={"./all.js":320,"./auth/actions.js":67,"./auth/index.js":282,"./auth/reducers.js":283,"./auth/selectors.js":284,"./auth/spec-wrap-actions.js":285,"./configs/actions.js":117,"./configs/helpers.js":144,"./configs/index.js":321,"./configs/reducers.js":290,"./configs/selectors.js":289,"./configs/spec-actions.js":288,"./deep-linking/helpers.js":146,"./deep-linking/index.js":291,"./deep-linking/layout.js":292,"./deep-linking/operation-tag-wrapper.jsx":294,"./deep-linking/operation-wrapper.jsx":293,"./download-url.js":287,"./err/actions.js":42,"./err/error-transformers/hook.js":94,"./err/error-transformers/transformers/not-of-type.js":267,"./err/error-transformers/transformers/parameter-oneof.js":268,"./err/index.js":265,"./err/reducers.js":266,"./err/selectors.js":269,"./filter/index.js":295,"./filter/opsFilter.js":296,"./layout/actions.js":74,"./layout/index.js":270,"./layout/reducers.js":271,"./layout/selectors.js":272,"./logs/index.js":279,"./oas3/actions.js":59,"./oas3/auth-extensions/wrap-selectors.js":300,"./oas3/components/callbacks.jsx":303,"./oas3/components/http-auth.jsx":309,"./oas3/components/index.js":302,"./oas3/components/operation-link.jsx":305,"./oas3/components/operation-servers.jsx":310,"./oas3/components/request-body-editor.jsx":308,"./oas3/components/request-body.jsx":304,"./oas3/components/servers-container.jsx":307,"./oas3/components/servers.jsx":306,"./oas3/helpers.jsx":24,"./oas3/index.js":298,"./oas3/reducers.js":319,"./oas3/selectors.js":318,"./oas3/spec-extensions/selectors.js":301,"./oas3/spec-extensions/wrap-selectors.js":299,"./oas3/wrap-components/auth-item.jsx":313,"./oas3/wrap-components/index.js":311,"./oas3/wrap-components/json-schema-string.jsx":317,"./oas3/wrap-components/markdown.jsx":312,"./oas3/wrap-components/model.jsx":316,"./oas3/wrap-components/online-validator-badge.js":315,"./oas3/wrap-components/version-stamp.jsx":314,"./on-complete/index.js":297,"./samples/fn.js":116,"./samples/index.js":278,"./spec/actions.js":29,"./spec/index.js":273,"./spec/reducers.js":274,"./spec/selectors.js":66,"./spec/wrap-actions.js":276,"./swagger-js/configs-wrap-actions.js":281,"./swagger-js/index.js":280,"./util/index.js":286,"./view/index.js":277,"./view/root-injects.jsx":145};function o(e){var t=i(e);return n(t)}function i(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=i,e.exports=o,o.id=1020},function(e,t,n){"use strict";n.r(t);var r={};n.r(r),n.d(r,"Container",function(){return jt}),n.d(r,"Col",function(){return It}),n.d(r,"Row",function(){return Mt}),n.d(r,"Button",function(){return Nt}),n.d(r,"TextArea",function(){return Rt}),n.d(r,"Input",function(){return Dt}),n.d(r,"Select",function(){return Lt}),n.d(r,"Link",function(){return Ut}),n.d(r,"Collapse",function(){return Ft});var o={};n.r(o),n.d(o,"JsonSchemaForm",function(){return An}),n.d(o,"JsonSchema_string",function(){return Tn}),n.d(o,"JsonSchema_array",function(){return jn}),n.d(o,"JsonSchema_boolean",function(){return Pn}),n.d(o,"JsonSchema_object",function(){return In});var i=n(28),a=n.n(i),s=n(17),u=n.n(s),c=n(26),l=n.n(c),p=n(75),f=n.n(p),h=n(14),d=n.n(h),m=n(2),v=n.n(m),g=n(16),y=n.n(g),b=n(4),_=n.n(b),w=n(5),x=n.n(w),E=n(0),S=n.n(E),C=n(120),k=n(1),O=n.n(k),A=n(464),T=n(115),j=n.n(T),P=n(142),I=n.n(P),M=n(42),N=n(18),R=n.n(N),D=n(3),L=function(e){return e};var U=function(){function e(){var t,n,r,o=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_()(this,e),f()(this,{state:{},plugins:[],system:{configs:{},fn:{},components:{},rootInjects:{},statePlugins:{}},boundSystem:{},toolbox:{}},o),this.getSystem=this._getSystem.bind(this),this.store=(t=L,n=Object(k.fromJS)(this.state),r=this.getSystem,function(e,t,n){var r=[Object(D.H)(n)],o=R.a.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__||C.compose;return Object(C.createStore)(e,t,o(C.applyMiddleware.apply(void 0,r)))}(t,n,r)),this.buildSystem(!1),this.register(this.plugins)}return x()(e,[{key:"getStore",value:function(){return this.store}},{key:"register",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=q(e,this.getSystem());z(this.system,n),t&&this.buildSystem();var r=F.call(this.system,e,this.getSystem());r&&this.buildSystem()}},{key:"buildSystem",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.getStore().dispatch,n=this.getStore().getState;this.boundSystem=y()({},this.getRootInjects(),this.getWrappedAndBoundActions(t),this.getWrappedAndBoundSelectors(n,this.getSystem),this.getStateThunks(n),this.getFn(),this.getConfigs()),e&&this.rebuildReducer()}},{key:"_getSystem",value:function(){return this.boundSystem}},{key:"getRootInjects",value:function(){return y()({getSystem:this.getSystem,getStore:this.getStore.bind(this),getComponents:this.getComponents.bind(this),getState:this.getStore().getState,getConfigs:this._getConfigs.bind(this),Im:O.a,React:S.a},this.system.rootInjects||{})}},{key:"_getConfigs",value:function(){return this.system.configs}},{key:"getConfigs",value:function(){return{configs:this.system.configs}}},{key:"setConfigs",value:function(e){this.system.configs=e}},{key:"rebuildReducer",value:function(){var e,t,n;this.store.replaceReducer((n=this.system.statePlugins,e=Object(D.w)(n,function(e){return e.reducers}),t=u()(e).reduce(function(t,n){var r;return t[n]=(r=e[n],function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new k.Map,t=arguments.length>1?arguments[1]:void 0;if(!r)return e;var n=r[t.type];if(n){var o=B(n)(e,t);return null===o?e:o}return e}),t},{}),u()(t).length?Object(A.combineReducers)(t):L))}},{key:"getType",value:function(e){var t=e[0].toUpperCase()+e.slice(1);return Object(D.x)(this.system.statePlugins,function(n,r){var o=n[e];if(o)return v()({},r+t,o)})}},{key:"getSelectors",value:function(){return this.getType("selectors")}},{key:"getActions",value:function(){var e=this.getType("actions");return Object(D.w)(e,function(e){return Object(D.x)(e,function(e,t){if(Object(D.p)(e))return v()({},t,e)})})}},{key:"getWrappedAndBoundActions",value:function(e){var t=this,n=this.getBoundActions(e);return Object(D.w)(n,function(e,n){var r=t.system.statePlugins[n.slice(0,-7)].wrapActions;return r?Object(D.w)(e,function(e,n){var o=r[n];return o?(d()(o)||(o=[o]),o.reduce(function(e,n){var r=function(){return n(e,t.getSystem()).apply(void 0,arguments)};if(!Object(D.p)(r))throw new TypeError("wrapActions needs to return a function that returns a new function (ie the wrapped action)");return B(r)},e||Function.prototype)):e}):e})}},{key:"getWrappedAndBoundSelectors",value:function(e,t){var n=this,r=this.getBoundSelectors(e,t);return Object(D.w)(r,function(t,r){var o=[r.slice(0,-9)],i=n.system.statePlugins[o].wrapSelectors;return i?Object(D.w)(t,function(t,r){var a=i[r];return a?(d()(a)||(a=[a]),a.reduce(function(t,r){var i=function(){for(var i=arguments.length,a=new Array(i),s=0;s<i;s++)a[s]=arguments[s];return r(t,n.getSystem()).apply(void 0,[e().getIn(o)].concat(a))};if(!Object(D.p)(i))throw new TypeError("wrapSelector needs to return a function that returns a new function (ie the wrapped action)");return i},t||Function.prototype)):t}):t})}},{key:"getStates",value:function(e){return u()(this.system.statePlugins).reduce(function(t,n){return t[n]=e.get(n),t},{})}},{key:"getStateThunks",value:function(e){return u()(this.system.statePlugins).reduce(function(t,n){return t[n]=function(){return e().get(n)},t},{})}},{key:"getFn",value:function(){return{fn:this.system.fn}}},{key:"getComponents",value:function(e){var t=this,n=this.system.components[e];return d()(n)?n.reduce(function(e,n){return n(e,t.getSystem())}):void 0!==e?this.system.components[e]:this.system.components}},{key:"getBoundSelectors",value:function(e,t){return Object(D.w)(this.getSelectors(),function(n,r){var o=[r.slice(0,-9)],i=function(){return e().getIn(o)};return Object(D.w)(n,function(e){return function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];var a=B(e).apply(null,[i()].concat(r));return"function"==typeof a&&(a=B(a)(t())),a}})})}},{key:"getBoundActions",value:function(e){e=e||this.getStore().dispatch;var t=this.getActions();return Object(D.w)(t,function(t){return Object(C.bindActionCreators)(function e(t){return"function"!=typeof t?Object(D.w)(t,function(t){return e(t)}):function(){var e=null;try{e=t.apply(void 0,arguments)}catch(t){e={type:M.NEW_THROWN_ERR,error:!0,payload:j()(t)}}finally{return e}}}(t),e)})}},{key:"getMapStateToProps",value:function(){var e=this;return function(){return y()({},e.getSystem())}}},{key:"getMapDispatchToProps",value:function(e){var t=this;return function(n){return f()({},t.getWrappedAndBoundActions(n),t.getFn(),e)}}}]),e}();function q(e,t){return Object(D.s)(e)&&!Object(D.o)(e)?I()({},e):Object(D.q)(e)?q(e(t),t):Object(D.o)(e)?e.map(function(e){return q(e,t)}).reduce(z,{}):{}}function F(e,t){var n=this,r=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).hasLoaded;return Object(D.s)(e)&&!Object(D.o)(e)&&"function"==typeof e.afterLoad&&(r=!0,B(e.afterLoad).call(this,t)),Object(D.q)(e)?F.call(this,e(t),t,{hasLoaded:r}):Object(D.o)(e)?e.map(function(e){return F.call(n,e,t,{hasLoaded:r})}):r}function z(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!Object(D.s)(e))return{};if(!Object(D.s)(t))return e;t.wrapComponents&&(Object(D.w)(t.wrapComponents,function(n,r){var o=e.components&&e.components[r];o&&d()(o)?(e.components[r]=o.concat([n]),delete t.wrapComponents[r]):o&&(e.components[r]=[o,n],delete t.wrapComponents[r])}),u()(t.wrapComponents).length||delete t.wrapComponents);var n=e.statePlugins;if(Object(D.s)(n))for(var r in n){var o=n[r];if(Object(D.s)(o)&&Object(D.s)(o.wrapActions)){var i=o.wrapActions;for(var a in i){var s=i[a];d()(s)||(s=[s],i[a]=s),t&&t.statePlugins&&t.statePlugins[r]&&t.statePlugins[r].wrapActions&&t.statePlugins[r].wrapActions[a]&&(t.statePlugins[r].wrapActions[a]=i[a].concat(t.statePlugins[r].wrapActions[a]))}}}return f()(e,t)}function B(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).logErrors,n=void 0===t||t;return"function"!=typeof e?e:function(){try{for(var t=arguments.length,r=new Array(t),o=0;o<t;o++)r[o]=arguments[o];return e.call.apply(e,[this].concat(r))}catch(e){return n&&console.error(e),null}}}var V=n(265),H=n(270),W=n(273),J=n(277),Y=n(278),K=n(279),G=n(280),$=n(282),Z=n(286),X=n(287),Q=n(321),ee=n(291),te=n(295),ne=n(297),re=n(6),oe=n.n(re),ie=n(7),ae=n.n(ie),se=n(9),ue=n.n(se),ce=n(8),le=n.n(ce),pe=(n(10),n(19),n(53).helpers.opId),fe=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"toggleShown",function(){var e=r.props,t=e.layoutActions,n=e.tag,o=e.operationId,i=e.isShown,a=r.getResolvedSubtree();i||void 0!==a||r.requestResolvedSubtree(),t.show(["operations",n,o],!i)}),v()(ue()(r),"onCancelClick",function(){r.setState({tryItOutEnabled:!r.state.tryItOutEnabled})}),v()(ue()(r),"onTryoutClick",function(){var e=r.props,t=e.specActions,n=e.path,o=e.method;r.setState({tryItOutEnabled:!r.state.tryItOutEnabled}),t.clearValidateParams([n,o])}),v()(ue()(r),"onExecute",function(){r.setState({executeInProgress:!0})}),v()(ue()(r),"getResolvedSubtree",function(){var e=r.props,t=e.specSelectors,n=e.path,o=e.method,i=e.specPath;return i?t.specResolvedSubtree(i.toJS()):t.specResolvedSubtree(["paths",n,o])}),v()(ue()(r),"requestResolvedSubtree",function(){var e=r.props,t=e.specActions,n=e.path,o=e.method,i=e.specPath;return i?t.requestResolvedSubtree(i.toJS()):t.requestResolvedSubtree(["paths",n,o])}),r.state={tryItOutEnabled:!1,executeInProgress:!1},r}return le()(t,e),x()(t,[{key:"mapStateToProps",value:function(e,t){var n=t.op,r=t.layoutSelectors,o=(0,t.getConfigs)(),i=o.docExpansion,a=o.deepLinking,s=o.displayOperationId,u=o.displayRequestDuration,c=o.supportedSubmitMethods,l=r.showSummary(),p=n.getIn(["operation","__originalOperationId"])||n.getIn(["operation","operationId"])||pe(n.get("operation"),t.path,t.method)||n.get("id"),f=["operations",t.tag,p],h=a&&"false"!==a,d=c.indexOf(t.method)>=0&&(void 0===t.allowTryItOut?t.specSelectors.allowTryItOutFor(t.path,t.method):t.allowTryItOut),m=n.getIn(["operation","security"])||t.specSelectors.security();return{operationId:p,isDeepLinkingEnabled:h,showSummary:l,displayOperationId:s,displayRequestDuration:u,allowTryItOut:d,security:m,isAuthorized:t.authSelectors.isAuthorized(m),isShown:r.isShown(f,"full"===i),jumpToKey:"paths.".concat(t.path,".").concat(t.method),response:t.specSelectors.responseFor(t.path,t.method),request:t.specSelectors.requestFor(t.path,t.method)}}},{key:"componentDidMount",value:function(){var e=this.props.isShown,t=this.getResolvedSubtree();e&&void 0===t&&this.requestResolvedSubtree()}},{key:"componentWillReceiveProps",value:function(e){var t=e.response,n=e.isShown,r=this.getResolvedSubtree();t!==this.props.response&&this.setState({executeInProgress:!1}),n&&void 0===r&&this.requestResolvedSubtree()}},{key:"render",value:function(){var e=this.props,t=e.op,n=e.tag,r=e.path,o=e.method,i=e.security,a=e.isAuthorized,s=e.operationId,u=e.showSummary,c=e.isShown,l=e.jumpToKey,p=e.allowTryItOut,f=e.response,h=e.request,d=e.displayOperationId,m=e.displayRequestDuration,v=e.isDeepLinkingEnabled,g=e.specPath,y=e.specSelectors,b=e.specActions,_=e.getComponent,w=e.getConfigs,x=e.layoutSelectors,E=e.layoutActions,C=e.authActions,O=e.authSelectors,A=e.oas3Actions,T=e.oas3Selectors,j=e.fn,P=_("operation"),I=this.getResolvedSubtree()||Object(k.Map)(),M=Object(k.fromJS)({op:I,tag:n,path:r,summary:t.getIn(["operation","summary"])||"",deprecated:I.get("deprecated")||t.getIn(["operation","deprecated"])||!1,method:o,security:i,isAuthorized:a,operationId:s,originalOperationId:I.getIn(["operation","__originalOperationId"]),showSummary:u,isShown:c,jumpToKey:l,allowTryItOut:p,request:h,displayOperationId:d,displayRequestDuration:m,isDeepLinkingEnabled:v,executeInProgress:this.state.executeInProgress,tryItOutEnabled:this.state.tryItOutEnabled});return S.a.createElement(P,{operation:M,response:f,request:h,isShown:c,toggleShown:this.toggleShown,onTryoutClick:this.onTryoutClick,onCancelClick:this.onCancelClick,onExecute:this.onExecute,specPath:g,specActions:b,specSelectors:y,oas3Actions:A,oas3Selectors:T,layoutActions:E,layoutSelectors:x,authActions:C,authSelectors:O,getComponent:_,getConfigs:w,fn:j})}}]),t}(E.PureComponent);v()(fe,"defaultProps",{showSummary:!0,response:null,allowTryItOut:!0,displayOperationId:!1,displayRequestDuration:!1});var he=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"getLayout",value:function(){var e=this.props,t=e.getComponent,n=e.layoutSelectors.current(),r=t(n,!0);return r||function(){return S.a.createElement("h1",null,' No layout defined for "',n,'" ')}}},{key:"render",value:function(){var e=this.getLayout();return S.a.createElement(e,null)}}]),t}(S.a.Component);he.defaultProps={};var de=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"close",function(){n.props.authActions.showDefinitions(!1)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.authSelectors,n=e.authActions,r=e.getComponent,o=e.errSelectors,i=e.specSelectors,a=e.fn.AST,s=void 0===a?{}:a,u=t.shownDefinitions(),c=r("auths");return S.a.createElement("div",{className:"dialog-ux"},S.a.createElement("div",{className:"backdrop-ux"}),S.a.createElement("div",{className:"modal-ux"},S.a.createElement("div",{className:"modal-dialog-ux"},S.a.createElement("div",{className:"modal-ux-inner"},S.a.createElement("div",{className:"modal-ux-header"},S.a.createElement("h3",null,"Available authorizations"),S.a.createElement("button",{type:"button",className:"close-modal",onClick:this.close},S.a.createElement("svg",{width:"20",height:"20"},S.a.createElement("use",{href:"#close",xlinkHref:"#close"})))),S.a.createElement("div",{className:"modal-ux-content"},u.valueSeq().map(function(e,a){return S.a.createElement(c,{key:a,AST:s,definitions:e,getComponent:r,errSelectors:o,authSelectors:t,authActions:n,specSelectors:i})}))))))}}]),t}(S.a.Component),me=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.isAuthorized,n=e.showPopup,r=e.onClick,o=(0,e.getComponent)("authorizationPopup",!0);return S.a.createElement("div",{className:"auth-wrapper"},S.a.createElement("button",{className:t?"btn authorize locked":"btn authorize unlocked",onClick:r},S.a.createElement("span",null,"Authorize"),S.a.createElement("svg",{width:"20",height:"20"},S.a.createElement("use",{href:t?"#locked":"#unlocked",xlinkHref:t?"#locked":"#unlocked"}))),n&&S.a.createElement(o,null))}}]),t}(S.a.Component),ve=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.authActions,n=e.authSelectors,r=e.specSelectors,o=e.getComponent,i=r.securityDefinitions(),a=n.definitionsToAuthorize(),s=o("authorizeBtn");return i?S.a.createElement(s,{onClick:function(){return t.showDefinitions(a)},isAuthorized:!!n.authorized().size,showPopup:!!n.shownDefinitions(),getComponent:o}):null}}]),t}(S.a.Component),ge=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onClick",function(e){e.stopPropagation();var t=n.props.onClick;t&&t()}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props.isAuthorized;return S.a.createElement("button",{className:e?"authorization__btn locked":"authorization__btn unlocked","aria-label":e?"authorization button locked":"authorization button unlocked",onClick:this.onClick},S.a.createElement("svg",{width:"20",height:"20"},S.a.createElement("use",{href:e?"#locked":"#unlocked",xlinkHref:e?"#locked":"#unlocked"})))}}]),t}(S.a.Component),ye=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onAuthChange",function(e){var t=e.name;r.setState(v()({},t,e))}),v()(ue()(r),"submitAuth",function(e){e.preventDefault(),r.props.authActions.authorize(r.state)}),v()(ue()(r),"logoutClick",function(e){e.preventDefault();var t=r.props,n=t.authActions,o=t.definitions.map(function(e,t){return t}).toArray();n.logout(o)}),v()(ue()(r),"close",function(e){e.preventDefault(),r.props.authActions.showDefinitions(!1)}),r.state={},r}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this,t=this.props,n=t.definitions,r=t.getComponent,o=t.authSelectors,i=t.errSelectors,a=r("AuthItem"),s=r("oauth2",!0),u=r("Button"),c=o.authorized(),l=n.filter(function(e,t){return!!c.get(t)}),p=n.filter(function(e){return"oauth2"!==e.get("type")}),f=n.filter(function(e){return"oauth2"===e.get("type")});return S.a.createElement("div",{className:"auth-container"},!!p.size&&S.a.createElement("form",{onSubmit:this.submitAuth},p.map(function(t,n){return S.a.createElement(a,{key:n,schema:t,name:n,getComponent:r,onAuthChange:e.onAuthChange,authorized:c,errSelectors:i})}).toArray(),S.a.createElement("div",{className:"auth-btn-wrapper"},p.size===l.size?S.a.createElement(u,{className:"btn modal-btn auth",onClick:this.logoutClick},"Logout"):S.a.createElement(u,{type:"submit",className:"btn modal-btn auth authorize"},"Authorize"),S.a.createElement(u,{className:"btn modal-btn auth btn-done",onClick:this.close},"Close"))),f&&f.size?S.a.createElement("div",null,S.a.createElement("div",{className:"scope-def"},S.a.createElement("p",null,"Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes."),S.a.createElement("p",null,"API requires the following scopes. Select which ones you want to grant to Swagger UI.")),n.filter(function(e){return"oauth2"===e.get("type")}).map(function(e,t){return S.a.createElement("div",{key:t},S.a.createElement(s,{authorized:c,schema:e,name:t}))}).toArray()):null)}}]),t}(S.a.Component),be=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e,t=this.props,n=t.schema,r=t.name,o=t.getComponent,i=t.onAuthChange,a=t.authorized,s=t.errSelectors,u=o("apiKeyAuth"),c=o("basicAuth"),l=n.get("type");switch(l){case"apiKey":e=S.a.createElement(u,{key:r,schema:n,name:r,errSelectors:s,authorized:a,getComponent:o,onChange:i});break;case"basic":e=S.a.createElement(c,{key:r,schema:n,name:r,errSelectors:s,authorized:a,getComponent:o,onChange:i});break;default:e=S.a.createElement("div",{key:r},"Unknown security definition type ",l)}return S.a.createElement("div",{key:"".concat(r,"-jump")},e)}}]),t}(S.a.Component),_e=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props.error,t=e.get("level"),n=e.get("message"),r=e.get("source");return S.a.createElement("div",{className:"errors",style:{backgroundColor:"#ffeeee",color:"red",margin:"1em"}},S.a.createElement("b",{style:{textTransform:"capitalize",marginRight:"1em"}},r," ",t),S.a.createElement("span",null,n))}}]),t}(S.a.Component),we=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onChange",function(e){var t=r.props.onChange,n=e.target.value,o=y()({},r.state,{value:n});r.setState(o),t(o)});var o=r.props,i=o.name,a=o.schema,s=r.getValue();return r.state={name:i,schema:a,value:s},r}return le()(t,e),x()(t,[{key:"getValue",value:function(){var e=this.props,t=e.name,n=e.authorized;return n&&n.getIn([t,"value"])}},{key:"render",value:function(){var e=this.props,t=e.schema,n=e.getComponent,r=e.errSelectors,o=e.name,i=n("Input"),a=n("Row"),s=n("Col"),u=n("authError"),c=n("Markdown"),l=n("JumpToPath",!0),p=this.getValue(),f=r.allErrors().filter(function(e){return e.get("authId")===o});return S.a.createElement("div",null,S.a.createElement("h4",null,S.a.createElement("code",null,o||t.get("name")),"  (apiKey)",S.a.createElement(l,{path:["securityDefinitions",o]})),p&&S.a.createElement("h6",null,"Authorized"),S.a.createElement(a,null,S.a.createElement(c,{source:t.get("description")})),S.a.createElement(a,null,S.a.createElement("p",null,"Name: ",S.a.createElement("code",null,t.get("name")))),S.a.createElement(a,null,S.a.createElement("p",null,"In: ",S.a.createElement("code",null,t.get("in")))),S.a.createElement(a,null,S.a.createElement("label",null,"Value:"),p?S.a.createElement("code",null," ****** "):S.a.createElement(s,null,S.a.createElement(i,{type:"text",onChange:this.onChange}))),f.valueSeq().map(function(e,t){return S.a.createElement(u,{error:e,key:t})}))}}]),t}(S.a.Component),xe=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onChange",function(e){var t=r.props.onChange,n=e.target,o=n.value,i=n.name,a=r.state.value;a[i]=o,r.setState({value:a}),t(r.state)});var o=r.props,i=o.schema,a=o.name,s=r.getValue().username;return r.state={name:a,schema:i,value:s?{username:s}:{}},r}return le()(t,e),x()(t,[{key:"getValue",value:function(){var e=this.props,t=e.authorized,n=e.name;return t&&t.getIn([n,"value"])||{}}},{key:"render",value:function(){var e=this.props,t=e.schema,n=e.getComponent,r=e.name,o=e.errSelectors,i=n("Input"),a=n("Row"),s=n("Col"),u=n("authError"),c=n("JumpToPath",!0),l=n("Markdown"),p=this.getValue().username,f=o.allErrors().filter(function(e){return e.get("authId")===r});return S.a.createElement("div",null,S.a.createElement("h4",null,"Basic authorization",S.a.createElement(c,{path:["securityDefinitions",r]})),p&&S.a.createElement("h6",null,"Authorized"),S.a.createElement(a,null,S.a.createElement(l,{source:t.get("description")})),S.a.createElement(a,null,S.a.createElement("label",null,"Username:"),p?S.a.createElement("code",null," ",p," "):S.a.createElement(s,null,S.a.createElement(i,{type:"text",required:"required",name:"username",onChange:this.onChange}))),S.a.createElement(a,null,S.a.createElement("label",null,"Password:"),p?S.a.createElement("code",null," ****** "):S.a.createElement(s,null,S.a.createElement(i,{required:"required",autoComplete:"new-password",name:"password",type:"password",onChange:this.onChange}))),f.valueSeq().map(function(e,t){return S.a.createElement(u,{error:e,key:t})}))}}]),t}(S.a.Component);function Ee(e){var t=e.example,n=e.showValue,r=e.getComponent,o=r("Markdown"),i=r("highlightCode");return t?S.a.createElement("div",{className:"example"},t.get("description")?S.a.createElement("section",{className:"example__section"},S.a.createElement("div",{className:"example__section-header"},"Example Description"),S.a.createElement("p",null,S.a.createElement(o,{source:t.get("description")}))):null,n&&t.has("value")?S.a.createElement("section",{className:"example__section"},S.a.createElement("div",{className:"example__section-header"},"Example Value"),S.a.createElement(i,{value:Object(D.G)(t.get("value"))})):null):null}var Se=n(475),Ce=n.n(Se),ke=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"_onSelect",function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.isSyntheticChange,o=void 0!==r&&r;"function"==typeof n.props.onSelect&&n.props.onSelect(e,{isSyntheticChange:o})}),v()(ue()(n),"_onDomSelect",function(e){if("function"==typeof n.props.onSelect){var t=e.target.selectedOptions[0].getAttribute("value");n._onSelect(t,{isSyntheticChange:!1})}}),v()(ue()(n),"getCurrentExample",function(){var e=n.props,t=e.examples,r=e.currentExampleKey,o=t.get(r),i=t.keySeq().first(),a=t.get(i);return o||a||Ce()({})}),n}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){var e=this.props,t=e.onSelect,n=e.examples;if("function"==typeof t){var r=n.first(),o=n.keyOf(r);this._onSelect(o,{isSyntheticChange:!0})}}},{key:"componentWillReceiveProps",value:function(e){var t=e.currentExampleKey,n=e.examples;if(n!==this.props.examples&&!n.has(t)){var r=n.first(),o=n.keyOf(r);this._onSelect(o,{isSyntheticChange:!0})}}},{key:"render",value:function(){var e=this.props,t=e.examples,n=e.currentExampleKey,r=e.isValueModified,o=e.isModifiedValueAvailable,i=e.showLabels;return S.a.createElement("div",{className:"examples-select"},i?S.a.createElement("span",{className:"examples-select__section-label"},"Examples: "):null,S.a.createElement("select",{onChange:this._onDomSelect,value:o&&r?"__MODIFIED__VALUE__":n||""},o?S.a.createElement("option",{value:"__MODIFIED__VALUE__"},"[Modified value]"):null,t.map(function(e,t){return S.a.createElement("option",{key:t,value:t},e.get("summary")||t)}).valueSeq()))}}]),t}(S.a.PureComponent);v()(ke,"defaultProps",{examples:O.a.Map({}),onSelect:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return(e=console).log.apply(e,["DEBUG: ExamplesSelect was not given an onSelect callback"].concat(n))},currentExampleKey:null,showLabels:!0});var Oe=function(e){return k.List.isList(e)?e:Object(D.G)(e)},Ae=function(e){function t(e){var n;_()(this,t),n=oe()(this,ae()(t).call(this,e)),v()(ue()(n),"_getStateForCurrentNamespace",function(){var e=n.props.currentNamespace;return(n.state[e]||Object(k.Map)()).toObject()}),v()(ue()(n),"_setStateForCurrentNamespace",function(e){var t=n.props.currentNamespace;return n._setStateForNamespace(t,e)}),v()(ue()(n),"_setStateForNamespace",function(e,t){var r=(n.state[e]||Object(k.Map)()).mergeDeep(t);return n.setState(v()({},e,r))}),v()(ue()(n),"_isCurrentUserInputSameAsExampleValue",function(){var e=n.props.currentUserInputValue;return n._getCurrentExampleValue()===e}),v()(ue()(n),"_getValueForExample",function(e,t){var r=(t||n.props).examples;return Oe((r||Object(k.Map)({})).getIn([e,"value"]))}),v()(ue()(n),"_getCurrentExampleValue",function(e){var t=(e||n.props).currentKey;return n._getValueForExample(t,e||n.props)}),v()(ue()(n),"_onExamplesSelect",function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.isSyntheticChange,o=n.props,i=o.onSelect,a=o.updateValue,s=o.currentUserInputValue,u=n._getStateForCurrentNamespace(),c=u.lastUserEditedValue,l=n._getValueForExample(e);if("__MODIFIED__VALUE__"===e)return a(Oe(c)),n._setStateForCurrentNamespace({isModifiedValueSelected:!0});if("function"==typeof i){for(var p=arguments.length,f=new Array(p>2?p-2:0),h=2;h<p;h++)f[h-2]=arguments[h];i.apply(void 0,[e,{isSyntheticChange:r}].concat(f))}n._setStateForCurrentNamespace({lastDownstreamValue:l,isModifiedValueSelected:r&&!!s&&s!==l}),r||"function"==typeof a&&a(Oe(l))});var r=n._getCurrentExampleValue();return n.state=v()({},e.currentNamespace,Object(k.Map)({lastUserEditedValue:n.props.currentUserInputValue,lastDownstreamValue:r,isModifiedValueSelected:n.props.currentUserInputValue!==r})),n}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){var t=e.currentUserInputValue,n=e.examples,r=e.onSelect,o=this._getStateForCurrentNamespace(),i=o.lastUserEditedValue,a=o.lastDownstreamValue,s=this._getValueForExample(e.currentKey,e),u=n.find(function(e){return e.get("value")===t||Object(D.G)(e.get("value"))===t});u?r(n.keyOf(u),{isSyntheticChange:!0}):t!==this.props.currentUserInputValue&&t!==i&&t!==a&&this._setStateForNamespace(e.currentNamespace,{lastUserEditedValue:e.currentUserInputValue,isModifiedValueSelected:t!==s})}},{key:"render",value:function(){var e=this.props,t=e.currentUserInputValue,n=e.examples,r=e.currentKey,o=e.getComponent,i=this._getStateForCurrentNamespace(),a=i.lastDownstreamValue,s=i.lastUserEditedValue,u=i.isModifiedValueSelected,c=o("ExamplesSelect");return S.a.createElement(c,{examples:n,currentExampleKey:r,onSelect:this._onExamplesSelect,isModifiedValueAvailable:!!s&&s!==a,isValueModified:void 0!==t&&u&&t!==this._getCurrentExampleValue()})}}]),t}(S.a.PureComponent);v()(Ae,"defaultProps",{examples:Object(k.Map)({}),currentNamespace:"__DEFAULT__NAMESPACE__",onSelect:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return(e=console).log.apply(e,["ExamplesSelectValueRetainer: no `onSelect` function was provided"].concat(n))},updateValue:function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return(e=console).log.apply(e,["ExamplesSelectValueRetainer: no `updateValue` function was provided"].concat(n))}});var Te=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"close",function(e){e.preventDefault(),r.props.authActions.showDefinitions(!1)}),v()(ue()(r),"authorize",function(){var e=r.props,t=e.authActions,n=e.errActions,o=e.getConfigs,i=e.authSelectors,a=o(),s=i.getConfigs();n.clear({authId:name,type:"auth",source:"auth"}),function(e){var t=e.auth,n=e.authActions,r=e.errActions,o=e.configs,i=e.authConfigs,a=void 0===i?{}:i,s=t.schema,u=t.scopes,c=t.name,l=t.clientId,p=s.get("flow"),f=[];switch(p){case"password":return void n.authorizePassword(t);case"application":return void n.authorizeApplication(t);case"accessCode":f.push("response_type=code");break;case"implicit":f.push("response_type=token");break;case"clientCredentials":return void n.authorizeApplication(t);case"authorizationCode":f.push("response_type=code")}"string"==typeof l&&f.push("client_id="+encodeURIComponent(l));var h=o.oauth2RedirectUrl;if(void 0!==h){if(f.push("redirect_uri="+encodeURIComponent(h)),d()(u)&&0<u.length){var m=a.scopeSeparator||" ";f.push("scope="+encodeURIComponent(u.join(m)))}var v=Object(D.a)(new Date);f.push("state="+encodeURIComponent(v)),void 0!==a.realm&&f.push("realm="+encodeURIComponent(a.realm));var g=a.additionalQueryStringParams;for(var y in g)void 0!==g[y]&&f.push([y,g[y]].map(encodeURIComponent).join("="));var b,_=s.get("authorizationUrl"),w=[Object(D.D)(_),f.join("&")].join(-1===_.indexOf("?")?"?":"&");b="implicit"===p?n.preAuthorizeImplicit:a.useBasicAuthenticationWithAccessCodeGrant?n.authorizeAccessCodeWithBasicAuthentication:n.authorizeAccessCodeWithFormParams,R.a.swaggerUIRedirectOauth2={auth:t,state:v,redirectUrl:h,callback:b,errCb:r.newAuthErr},R.a.open(w)}else r.newAuthErr({authId:c,source:"validation",level:"error",message:"oauth2RedirectUrl configuration is not passed. Oauth2 authorization cannot be performed."})}({auth:r.state,authActions:t,errActions:n,configs:a,authConfigs:s})}),v()(ue()(r),"onScopeChange",function(e){var t=e.target,n=t.checked,o=t.dataset.value;if(n&&-1===r.state.scopes.indexOf(o)){var i=r.state.scopes.concat([o]);r.setState({scopes:i})}else!n&&r.state.scopes.indexOf(o)>-1&&r.setState({scopes:r.state.scopes.filter(function(e){return e!==o})})}),v()(ue()(r),"onInputChange",function(e){var t=e.target,n=t.dataset.name,o=t.value,i=v()({},n,o);r.setState(i)}),v()(ue()(r),"logout",function(e){e.preventDefault();var t=r.props,n=t.authActions,o=t.errActions,i=t.name;o.clear({authId:i,type:"auth",source:"auth"}),n.logout([i])});var o=r.props,i=o.name,a=o.schema,s=o.authorized,u=o.authSelectors,c=s&&s.get(i),l=u.getConfigs()||{},p=c&&c.get("username")||"",f=c&&c.get("clientId")||l.clientId||"",h=c&&c.get("clientSecret")||l.clientSecret||"",m=c&&c.get("passwordType")||"basic";return r.state={appName:l.appName,name:i,schema:a,scopes:[],clientId:f,clientSecret:h,username:p,password:"",passwordType:m},r}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this,t=this.props,n=t.schema,r=t.getComponent,o=t.authSelectors,i=t.errSelectors,a=t.name,s=t.specSelectors,u=r("Input"),c=r("Row"),l=r("Col"),p=r("Button"),f=r("authError"),h=r("JumpToPath",!0),d=r("Markdown"),m=s.isOAS3,v=m()?"authorizationCode":"accessCode",g=m()?"clientCredentials":"application",y=n.get("flow"),b=n.get("allowedScopes")||n.get("scopes"),_=!!o.authorized().get(a),w=i.allErrors().filter(function(e){return e.get("authId")===a}),x=!w.filter(function(e){return"validation"===e.get("source")}).size,E=n.get("description");return S.a.createElement("div",null,S.a.createElement("h4",null,a," (OAuth2, ",n.get("flow"),") ",S.a.createElement(h,{path:["securityDefinitions",a]})),this.state.appName?S.a.createElement("h5",null,"Application: ",this.state.appName," "):null,E&&S.a.createElement(d,{source:n.get("description")}),_&&S.a.createElement("h6",null,"Authorized"),("implicit"===y||y===v)&&S.a.createElement("p",null,"Authorization URL: ",S.a.createElement("code",null,n.get("authorizationUrl"))),("password"===y||y===v||y===g)&&S.a.createElement("p",null,"Token URL:",S.a.createElement("code",null," ",n.get("tokenUrl"))),S.a.createElement("p",{className:"flow"},"Flow: ",S.a.createElement("code",null,n.get("flow"))),"password"!==y?null:S.a.createElement(c,null,S.a.createElement(c,null,S.a.createElement("label",{htmlFor:"oauth_username"},"username:"),_?S.a.createElement("code",null," ",this.state.username," "):S.a.createElement(l,{tablet:10,desktop:10},S.a.createElement("input",{id:"oauth_username",type:"text","data-name":"username",onChange:this.onInputChange}))),S.a.createElement(c,null,S.a.createElement("label",{htmlFor:"oauth_password"},"password:"),_?S.a.createElement("code",null," ****** "):S.a.createElement(l,{tablet:10,desktop:10},S.a.createElement("input",{id:"oauth_password",type:"password","data-name":"password",onChange:this.onInputChange}))),S.a.createElement(c,null,S.a.createElement("label",{htmlFor:"password_type"},"Client credentials location:"),_?S.a.createElement("code",null," ",this.state.passwordType," "):S.a.createElement(l,{tablet:10,desktop:10},S.a.createElement("select",{id:"password_type","data-name":"passwordType",onChange:this.onInputChange},S.a.createElement("option",{value:"basic"},"Authorization header"),S.a.createElement("option",{value:"request-body"},"Request body"))))),(y===g||"implicit"===y||y===v||"password"===y)&&(!_||_&&this.state.clientId)&&S.a.createElement(c,null,S.a.createElement("label",{htmlFor:"client_id"},"client_id:"),_?S.a.createElement("code",null," ****** "):S.a.createElement(l,{tablet:10,desktop:10},S.a.createElement("input",{id:"client_id",type:"text",required:"password"===y,value:this.state.clientId,"data-name":"clientId",onChange:this.onInputChange}))),(y===g||y===v||"password"===y)&&S.a.createElement(c,null,S.a.createElement("label",{htmlFor:"client_secret"},"client_secret:"),_?S.a.createElement("code",null," ****** "):S.a.createElement(l,{tablet:10,desktop:10},S.a.createElement("input",{id:"client_secret",value:this.state.clientSecret,type:"text","data-name":"clientSecret",onChange:this.onInputChange}))),!_&&b&&b.size?S.a.createElement("div",{className:"scopes"},S.a.createElement("h2",null,"Scopes:"),b.map(function(t,n){return S.a.createElement(c,{key:n},S.a.createElement("div",{className:"checkbox"},S.a.createElement(u,{"data-value":n,id:"".concat(n,"-").concat(y,"-checkbox-").concat(e.state.name),disabled:_,type:"checkbox",onChange:e.onScopeChange}),S.a.createElement("label",{htmlFor:"".concat(n,"-").concat(y,"-checkbox-").concat(e.state.name)},S.a.createElement("span",{className:"item"}),S.a.createElement("div",{className:"text"},S.a.createElement("p",{className:"name"},n),S.a.createElement("p",{className:"description"},t)))))}).toArray()):null,w.valueSeq().map(function(e,t){return S.a.createElement(f,{error:e,key:t})}),S.a.createElement("div",{className:"auth-btn-wrapper"},x&&(_?S.a.createElement(p,{className:"btn modal-btn auth authorize",onClick:this.logout},"Logout"):S.a.createElement(p,{className:"btn modal-btn auth authorize",onClick:this.authorize},"Authorize")),S.a.createElement(p,{className:"btn modal-btn auth btn-done",onClick:this.close},"Close")))}}]),t}(S.a.Component),je=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onClick",function(){var e=n.props,t=e.specActions,r=e.path,o=e.method;t.clearResponse(r,o),t.clearRequest(r,o)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("button",{className:"btn btn-clear opblock-control__btn",onClick:this.onClick},"Clear")}}]),t}(E.Component),Pe=function(e){var t=e.headers;return S.a.createElement("div",null,S.a.createElement("h5",null,"Response headers"),S.a.createElement("pre",null,t))},Ie=function(e){var t=e.duration;return S.a.createElement("div",null,S.a.createElement("h5",null,"Request duration"),S.a.createElement("pre",null,t," ms"))},Me=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"shouldComponentUpdate",value:function(e){return this.props.response!==e.response||this.props.path!==e.path||this.props.method!==e.method||this.props.displayRequestDuration!==e.displayRequestDuration}},{key:"render",value:function(){var e=this.props,t=e.response,n=e.getComponent,r=e.getConfigs,o=e.displayRequestDuration,i=e.specSelectors,a=e.path,s=e.method,c=r().showMutatedRequest?i.mutatedRequestFor(a,s):i.requestFor(a,s),l=t.get("status"),p=c.get("url"),f=t.get("headers").toJS(),h=t.get("notDocumented"),d=t.get("error"),m=t.get("text"),v=t.get("duration"),g=u()(f),y=f["content-type"]||f["Content-Type"],b=n("curl"),_=n("responseBody"),w=g.map(function(e){return S.a.createElement("span",{className:"headerline",key:e}," ",e,": ",f[e]," ")}),x=0!==w.length;return S.a.createElement("div",null,c&&S.a.createElement(b,{request:c}),p&&S.a.createElement("div",null,S.a.createElement("h4",null,"Request URL"),S.a.createElement("div",{className:"request-url"},S.a.createElement("pre",null,p))),S.a.createElement("h4",null,"Server response"),S.a.createElement("table",{className:"responses-table live-responses-table"},S.a.createElement("thead",null,S.a.createElement("tr",{className:"responses-header"},S.a.createElement("td",{className:"col_header response-col_status"},"Code"),S.a.createElement("td",{className:"col_header response-col_description"},"Details"))),S.a.createElement("tbody",null,S.a.createElement("tr",{className:"response"},S.a.createElement("td",{className:"response-col_status"},l,h?S.a.createElement("div",{className:"response-undocumented"},S.a.createElement("i",null," Undocumented ")):null),S.a.createElement("td",{className:"response-col_description"},d?S.a.createElement("span",null,"".concat(t.get("name"),": ").concat(t.get("message"))):null,m?S.a.createElement(_,{content:m,contentType:y,url:p,headers:f,getComponent:n}):null,x?S.a.createElement(Pe,{headers:w}):null,o&&v?S.a.createElement(Ie,{duration:v}):null)))))}}]),t}(S.a.Component),Ne=n(93),Re=n.n(Ne),De=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"getDefinitionUrl",function(){var e=r.props.specSelectors;return new Re.a(e.url(),R.a.location).toString()});var o=(0,e.getConfigs)().validatorUrl;return r.state={url:r.getDefinitionUrl(),validatorUrl:void 0===o?"https://validator.swagger.io/validator":o},r}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){var t=(0,e.getConfigs)().validatorUrl;this.setState({url:this.getDefinitionUrl(),validatorUrl:void 0===t?"https://validator.swagger.io/validator":t})}},{key:"render",value:function(){var e=(0,this.props.getConfigs)().spec,t=Object(D.D)(this.state.validatorUrl);return"object"===l()(e)&&u()(e).length?null:!this.state.url||!this.state.validatorUrl||this.state.url.indexOf("localhost")>=0||this.state.url.indexOf("127.0.0.1")>=0?null:S.a.createElement("span",{style:{float:"right"}},S.a.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"".concat(t,"/debug?url=").concat(encodeURIComponent(this.state.url))},S.a.createElement(Le,{src:"".concat(t,"?url=").concat(encodeURIComponent(this.state.url)),alt:"Online validator badge"})))}}]),t}(S.a.Component),Le=function(e){function t(e){var n;return _()(this,t),(n=oe()(this,ae()(t).call(this,e))).state={loaded:!1,error:!1},n}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){var e=this,t=new Image;t.onload=function(){e.setState({loaded:!0})},t.onerror=function(){e.setState({error:!0})},t.src=this.props.src}},{key:"componentWillReceiveProps",value:function(e){var t=this;if(e.src!==this.props.src){var n=new Image;n.onload=function(){t.setState({loaded:!0})},n.onerror=function(){t.setState({error:!0})},n.src=e.src}}},{key:"render",value:function(){return this.state.error?S.a.createElement("img",{alt:"Error"}):this.state.loaded?S.a.createElement("img",{src:this.props.src,alt:this.props.alt}):null}}]),t}(S.a.Component),Ue=["get","put","post","delete","options","head","patch"],qe=Ue.concat(["trace"]),Fe=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.getComponent,r=e.layoutSelectors,o=e.layoutActions,i=e.getConfigs,a=e.fn,s=t.taggedOperations(),u=n("OperationContainer",!0),c=n("OperationTag"),l=i().maxDisplayedTags,p=r.currentFilter();return p&&!0!==p&&(s=a.opsFilter(s,p)),l&&!isNaN(l)&&l>=0&&(s=s.slice(0,l)),S.a.createElement("div",null,s.map(function(e,a){var s=e.get("operations");return S.a.createElement(c,{key:"operation-"+a,tagObj:e,tag:a,layoutSelectors:r,layoutActions:o,getConfigs:i,getComponent:n},s.map(function(e){var n=e.get("path"),r=e.get("method"),o=O.a.List(["paths",n,r]);return-1===(t.isOAS3()?qe:Ue).indexOf(r)?null:S.a.createElement(u,{key:"".concat(n,"-").concat(r),specPath:o,op:e,path:n,method:r,tag:a})}).toArray())}).toArray(),s.size<1?S.a.createElement("h3",null," No operations defined in spec! "):null)}}]),t}(S.a.Component),ze=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.tagObj,n=e.tag,r=e.children,o=e.layoutSelectors,i=e.layoutActions,a=e.getConfigs,s=e.getComponent,u=a(),c=u.docExpansion,l=u.deepLinking,p=l&&"false"!==l,f=s("Collapse"),h=s("Markdown"),d=s("DeepLink"),m=s("Link"),v=t.getIn(["tagDetails","description"],null),g=t.getIn(["tagDetails","externalDocs","description"]),y=t.getIn(["tagDetails","externalDocs","url"]),b=["operations-tag",n],_=o.isShown(b,"full"===c||"list"===c);return S.a.createElement("div",{className:_?"opblock-tag-section is-open":"opblock-tag-section"},S.a.createElement("h4",{onClick:function(){return i.show(b,!_)},className:v?"opblock-tag":"opblock-tag no-desc",id:b.map(function(e){return Object(D.f)(e)}).join("-"),"data-tag":n,"data-is-open":_},S.a.createElement(d,{enabled:p,isShown:_,path:Object(D.c)(n),text:n}),v?S.a.createElement("small",null,S.a.createElement(h,{source:v})):S.a.createElement("small",null),S.a.createElement("div",null,g?S.a.createElement("small",null,g,y?": ":null,y?S.a.createElement(m,{href:Object(D.D)(y),onClick:function(e){return e.stopPropagation()},target:"_blank"},y):null):null),S.a.createElement("button",{className:"expand-operation",title:_?"Collapse operation":"Expand operation",onClick:function(){return i.show(b,!_)}},S.a.createElement("svg",{className:"arrow",width:"20",height:"20"},S.a.createElement("use",{href:_?"#large-arrow-down":"#large-arrow",xlinkHref:_?"#large-arrow-down":"#large-arrow"})))),S.a.createElement(f,{isOpened:_},r))}}]),t}(S.a.Component);v()(ze,"defaultProps",{tagObj:O.a.fromJS({}),tag:""});var Be=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.specPath,r=e.response,o=e.request,i=e.toggleShown,a=e.onTryoutClick,s=e.onCancelClick,u=e.onExecute,c=e.fn,l=e.getComponent,p=e.getConfigs,f=e.specActions,h=e.specSelectors,d=e.authActions,m=e.authSelectors,v=e.oas3Actions,g=e.oas3Selectors,y=this.props.operation,b=y.toJS(),_=b.deprecated,w=b.isShown,x=b.path,E=b.method,C=b.op,k=b.tag,O=b.operationId,A=b.allowTryItOut,T=b.displayRequestDuration,j=b.tryItOutEnabled,P=b.executeInProgress,I=C.description,M=C.externalDocs,N=C.schemes,R=y.getIn(["op"]),L=R.get("responses"),U=Object(D.l)(R,["parameters"]),q=h.operationScheme(x,E),F=["operations",k,O],z=Object(D.k)(R),B=l("responses"),V=l("parameters"),H=l("execute"),W=l("clear"),J=l("Collapse"),Y=l("Markdown"),K=l("schemes"),G=l("OperationServers"),$=l("OperationExt"),Z=l("OperationSummary"),X=l("Link"),Q=p().showExtensions;if(L&&r&&r.size>0){var ee=!L.get(String(r.get("status")))&&!L.get("default");r=r.set("notDocumented",ee)}var te=[x,E];return S.a.createElement("div",{className:_?"opblock opblock-deprecated":w?"opblock opblock-".concat(E," is-open"):"opblock opblock-".concat(E),id:Object(D.f)(F.join("-"))},S.a.createElement(Z,{operationProps:y,toggleShown:i,getComponent:l,authActions:d,authSelectors:m,specPath:t}),S.a.createElement(J,{isOpened:w},S.a.createElement("div",{className:"opblock-body"},R&&R.size||null===R?null:S.a.createElement("img",{height:"32px",width:"32px",src:n(456),className:"opblock-loading-animation"}),_&&S.a.createElement("h4",{className:"opblock-title_normal"}," Warning: Deprecated"),I&&S.a.createElement("div",{className:"opblock-description-wrapper"},S.a.createElement("div",{className:"opblock-description"},S.a.createElement(Y,{source:I}))),M&&M.url?S.a.createElement("div",{className:"opblock-external-docs-wrapper"},S.a.createElement("h4",{className:"opblock-title_normal"},"Find more details"),S.a.createElement("div",{className:"opblock-external-docs"},S.a.createElement("span",{className:"opblock-external-docs__description"},S.a.createElement(Y,{source:M.description})),S.a.createElement(X,{target:"_blank",className:"opblock-external-docs__link",href:Object(D.D)(M.url)},M.url))):null,R&&R.size?S.a.createElement(V,{parameters:U,specPath:t.push("parameters"),operation:R,onChangeKey:te,onTryoutClick:a,onCancelClick:s,tryItOutEnabled:j,allowTryItOut:A,fn:c,getComponent:l,specActions:f,specSelectors:h,pathMethod:[x,E],getConfigs:p,oas3Actions:v,oas3Selectors:g}):null,j?S.a.createElement(G,{getComponent:l,path:x,method:E,operationServers:R.get("servers"),pathServers:h.paths().getIn([x,"servers"]),getSelectedServer:g.selectedServer,setSelectedServer:v.setSelectedServer,setServerVariableValue:v.setServerVariableValue,getServerVariable:g.serverVariableValue,getEffectiveServerValue:g.serverEffectiveValue}):null,j&&A&&N&&N.size?S.a.createElement("div",{className:"opblock-schemes"},S.a.createElement(K,{schemes:N,path:x,method:E,specActions:f,currentScheme:q})):null,S.a.createElement("div",{className:j&&r&&A?"btn-group":"execute-wrapper"},j&&A?S.a.createElement(H,{operation:R,specActions:f,specSelectors:h,path:x,method:E,onExecute:u}):null,j&&r&&A?S.a.createElement(W,{specActions:f,path:x,method:E}):null),P?S.a.createElement("div",{className:"loading-container"},S.a.createElement("div",{className:"loading"})):null,L?S.a.createElement(B,{responses:L,request:o,tryItOutResponse:r,getComponent:l,getConfigs:p,specSelectors:h,oas3Actions:v,oas3Selectors:g,specActions:f,produces:h.producesOptionsFor([x,E]),producesValue:h.currentProducesFor([x,E]),specPath:t.push("responses"),path:x,method:E,displayRequestDuration:T,fn:c}):null,Q&&z.size?S.a.createElement($,{extensions:z,getComponent:l}):null)))}}]),t}(E.PureComponent);v()(Be,"defaultProps",{operation:null,response:null,request:null,specPath:Object(k.List)(),summary:""});var Ve=n(65),He=n.n(Ve),We=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.toggleShown,n=e.getComponent,r=e.authActions,o=e.authSelectors,i=e.operationProps,a=e.specPath,s=i.toJS(),u=s.summary,c=s.isAuthorized,l=s.method,p=s.op,f=s.showSummary,h=s.operationId,d=s.originalOperationId,m=s.displayOperationId,v=p.summary,g=i.get("security"),y=n("authorizeOperationBtn"),b=n("OperationSummaryMethod"),_=n("OperationSummaryPath"),w=n("JumpToPath",!0);return S.a.createElement("div",{className:"opblock-summary opblock-summary-".concat(l),onClick:t},S.a.createElement(b,{method:l}),S.a.createElement(_,{getComponent:n,operationProps:i,specPath:a}),f?S.a.createElement("div",{className:"opblock-summary-description"},He()(v||u)):null,m&&(d||h)?S.a.createElement("span",{className:"opblock-summary-operation-id"},d||h):null,g&&g.count()?S.a.createElement(y,{isAuthorized:c,onClick:function(){var e=o.definitionsForRequirements(g);r.showDefinitions(e)}}):null,S.a.createElement(w,{path:a}))}}]),t}(E.PureComponent);v()(We,"defaultProps",{operationProps:null,specPath:Object(k.List)(),summary:""});var Je=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props.method;return S.a.createElement("span",{className:"opblock-summary-method"},e.toUpperCase())}}]),t}(E.PureComponent);v()(Je,"defaultProps",{operationProps:null});var Ye=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onCopyCapture",function(e){e.clipboardData.setData("text/plain",n.props.operationProps.get("path")),e.preventDefault()}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.operationProps.toJS(),r=n.deprecated,o=n.isShown,i=n.path,a=n.tag,s=n.operationId,u=n.isDeepLinkingEnabled,c=t("DeepLink");return S.a.createElement("span",{className:r?"opblock-summary-path__deprecated":"opblock-summary-path",onCopyCapture:this.onCopyCapture,"data-path":i},S.a.createElement(c,{enabled:u,isShown:o,path:Object(D.c)("".concat(a,"/").concat(s)),text:i.replace(/\//g,"​/")}))}}]),t}(E.PureComponent),Ke=n(13),Ge=n.n(Ke),$e=function(e){var t=e.extensions,n=(0,e.getComponent)("OperationExtRow");return S.a.createElement("div",{className:"opblock-section"},S.a.createElement("div",{className:"opblock-section-header"},S.a.createElement("h4",null,"Extensions")),S.a.createElement("div",{className:"table-container"},S.a.createElement("table",null,S.a.createElement("thead",null,S.a.createElement("tr",null,S.a.createElement("td",{className:"col_header"},"Field"),S.a.createElement("td",{className:"col_header"},"Value"))),S.a.createElement("tbody",null,t.entrySeq().map(function(e){var t=Ge()(e,2),r=t[0],o=t[1];return S.a.createElement(n,{key:"".concat(r,"-").concat(o),xKey:r,xVal:o})})))))},Ze=function(e){var t=e.xKey,n=e.xVal,r=n?n.toJS?n.toJS():n:null;return S.a.createElement("tr",null,S.a.createElement("td",null,t),S.a.createElement("td",null,a()(r)))},Xe=n(476),Qe=n.n(Xe),et=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"initializeComponent",function(e){n.el=e}),v()(ue()(n),"downloadText",function(){Qe()(n.props.value,n.props.fileName||"response.txt")}),v()(ue()(n),"preventYScrollingBeyondElement",function(e){var t=e.target,n=e.nativeEvent.deltaY,r=t.scrollHeight,o=t.offsetHeight,i=t.scrollTop;r>o&&(0===i&&n<0||o+i>=r&&n>0)&&e.preventDefault()}),n}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){Object(D.n)(this.el)}},{key:"componentDidUpdate",value:function(){Object(D.n)(this.el)}},{key:"render",value:function(){var e=this.props,t=e.value,n=e.className,r=e.downloadable;return n=n||"",S.a.createElement("div",{className:"highlight-code"},r?S.a.createElement("div",{className:"download-contents",onClick:this.downloadText},"Download"):null,S.a.createElement("pre",{ref:this.initializeComponent,onWheel:this.preventYScrollingBeyondElement,className:n+" microlight"},t))}}]),t}(E.Component),tt=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onChangeProducesWrapper",function(e){return n.props.specActions.changeProducesValue([n.props.path,n.props.method],e)}),v()(ue()(n),"onResponseContentTypeChange",function(e){var t=e.controlsAcceptHeader,r=e.value,o=n.props,i=o.oas3Actions,a=o.path,s=o.method;t&&i.setResponseContentType({value:r,path:a,method:s})}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this,n=this.props,r=n.responses,o=n.tryItOutResponse,i=n.getComponent,a=n.getConfigs,s=n.specSelectors,u=n.fn,c=n.producesValue,l=n.displayRequestDuration,p=n.specPath,f=n.path,h=n.method,d=n.oas3Selectors,m=n.oas3Actions,v=Object(D.e)(r),g=i("contentType"),y=i("liveResponse"),b=i("response"),_=this.props.produces&&this.props.produces.size?this.props.produces:t.defaultProps.produces,w=s.isOAS3()?Object(D.i)(r):null;return S.a.createElement("div",{className:"responses-wrapper"},S.a.createElement("div",{className:"opblock-section-header"},S.a.createElement("h4",null,"Responses"),s.isOAS3()?null:S.a.createElement("label",null,S.a.createElement("span",null,"Response content type"),S.a.createElement(g,{value:c,onChange:this.onChangeProducesWrapper,contentTypes:_,className:"execute-content-type"}))),S.a.createElement("div",{className:"responses-inner"},o?S.a.createElement("div",null,S.a.createElement(y,{response:o,getComponent:i,getConfigs:a,specSelectors:s,path:this.props.path,method:this.props.method,displayRequestDuration:l}),S.a.createElement("h4",null,"Responses")):null,S.a.createElement("table",{className:"responses-table"},S.a.createElement("thead",null,S.a.createElement("tr",{className:"responses-header"},S.a.createElement("td",{className:"col_header response-col_status"},"Code"),S.a.createElement("td",{className:"col_header response-col_description"},"Description"),s.isOAS3()?S.a.createElement("td",{className:"col col_header response-col_links"},"Links"):null)),S.a.createElement("tbody",null,r.entrySeq().map(function(t){var n=Ge()(t,2),r=n[0],l=n[1],g=o&&o.get("status")==r?"response_current":"";return S.a.createElement(b,{key:r,path:f,method:h,specPath:p.push(r),isDefault:v===r,fn:u,className:g,code:r,response:l,specSelectors:s,controlsAcceptHeader:l===w,onContentTypeChange:e.onResponseContentTypeChange,contentType:c,getConfigs:a,activeExamplesKey:d.activeExamplesMember(f,h,"responses",r),oas3Actions:m,getComponent:i})}).toArray()))))}}]),t}(S.a.Component);v()(tt,"defaultProps",{tryItOutResponse:null,produces:Object(k.fromJS)(["application/json"]),displayRequestDuration:!1});var nt=n(56),rt=n.n(nt),ot=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"_onContentTypeChange",function(e){var t=r.props,n=t.onContentTypeChange,o=t.controlsAcceptHeader;r.setState({responseContentType:e}),n({value:e,controlsAcceptHeader:o})}),v()(ue()(r),"getTargetExamplesKey",function(){var e=r.props,t=e.response,n=e.contentType,o=e.activeExamplesKey,i=r.state.responseContentType||n,a=t.getIn(["content",i],Object(k.Map)({})).get("examples",null).keySeq().first();return o||a}),r.state={responseContentType:""},r}return le()(t,e),x()(t,[{key:"render",value:function(){var e,t,n,r=this.props,o=r.path,i=r.method,a=r.code,s=r.response,u=r.className,c=r.specPath,l=r.fn,p=r.getComponent,f=r.getConfigs,h=r.specSelectors,d=r.contentType,m=r.controlsAcceptHeader,v=r.oas3Actions,g=l.inferSchema,y=h.isOAS3(),b=s.get("headers"),_=s.get("links"),w=p("headers"),x=p("highlightCode"),E=p("modelExample"),C=p("Markdown"),O=p("operationLink"),A=p("contentType"),T=p("ExamplesSelect"),j=p("Example"),P=this.state.responseContentType||d,I=s.getIn(["content",P],Object(k.Map)({})),M=I.get("examples",null);if(y){var N=I.get("schema");t=N?g(N.toJS()):null,n=N?Object(k.List)(["content",this.state.responseContentType,"schema"]):c}else t=s.get("schema"),n=s.has("schema")?c.push("schema"):c;if(y){var R=I.get("schema",Object(k.Map)({}));if(M){var L=this.getTargetExamplesKey(),U=M.get(L,Object(k.Map)({}));e=Object(D.G)(U.get("value"))}else e=void 0!==I.get("example")?Object(D.G)(I.get("example")):Object(D.m)(R.toJS(),this.state.responseContentType,{includeReadOnly:!0})}else e=s.getIn(["examples",P])?s.getIn(["examples",P]):t?Object(D.m)(t.toJS(),P,{includeReadOnly:!0,includeWriteOnly:!0}):null;var q=function(e,t){return null!=e?S.a.createElement("div",null,S.a.createElement(t,{className:"example",value:Object(D.G)(e)})):null}(e,x);return S.a.createElement("tr",{className:"response "+(u||""),"data-code":a},S.a.createElement("td",{className:"response-col_status"},a),S.a.createElement("td",{className:"response-col_description"},S.a.createElement("div",{className:"response-col_description__inner"},S.a.createElement(C,{source:s.get("description")})),y&&s.get("content")?S.a.createElement("section",{className:"response-controls"},S.a.createElement("div",{className:rt()("response-control-media-type",{"response-control-media-type--accept-controller":m})},S.a.createElement("small",{className:"response-control-media-type__title"},"Media type"),S.a.createElement(A,{value:this.state.responseContentType,contentTypes:s.get("content")?s.get("content").keySeq():Object(k.Seq)(),onChange:this._onContentTypeChange}),m?S.a.createElement("small",{className:"response-control-media-type__accept-message"},"Controls ",S.a.createElement("code",null,"Accept")," header."):null),M?S.a.createElement("div",{className:"response-control-examples"},S.a.createElement("small",{className:"response-control-examples__title"},"Examples"),S.a.createElement(T,{examples:M,currentExampleKey:this.getTargetExamplesKey(),onSelect:function(e){return v.setActiveExamplesMember({name:e,pathMethod:[o,i],contextType:"responses",contextName:a})},showLabels:!1})):null):null,q||t?S.a.createElement(E,{specPath:n,getComponent:p,getConfigs:f,specSelectors:h,schema:Object(D.h)(t),example:q}):null,y&&M?S.a.createElement(j,{example:M.get(this.getTargetExamplesKey(),Object(k.Map)({})),getComponent:p,omitValue:!0}):null,b?S.a.createElement(w,{headers:b,getComponent:p}):null),y?S.a.createElement("td",{className:"response-col_links"},_?_.toSeq().map(function(e,t){return S.a.createElement(O,{key:t,name:t,link:e,getComponent:p})}):S.a.createElement("i",null,"No links")):null)}}]),t}(S.a.Component);v()(ot,"defaultProps",{response:Object(k.fromJS)({}),onContentTypeChange:function(){}});var it=n(477),at=n.n(it),st=n(478),ut=n.n(st),ct=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"state",{parsedContent:null}),v()(ue()(n),"updateParsedContent",function(e){var t=n.props.content;if(e!==t)if(t&&t instanceof Blob){var r=new FileReader;r.onload=function(){n.setState({parsedContent:r.result})},r.readAsText(t)}else n.setState({parsedContent:t.toString()})}),n}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){this.updateParsedContent(null)}},{key:"componentDidUpdate",value:function(e){this.updateParsedContent(e.content)}},{key:"render",value:function(){var e,t,n=this.props,r=n.content,o=n.contentType,i=n.url,s=n.headers,u=void 0===s?{}:s,c=n.getComponent,l=this.state.parsedContent,p=c("highlightCode"),f="response_"+(new Date).getTime();if(i=i||"",/^application\/octet-stream/i.test(o)||u["Content-Disposition"]&&/attachment/i.test(u["Content-Disposition"])||u["content-disposition"]&&/attachment/i.test(u["content-disposition"])||u["Content-Description"]&&/File Transfer/i.test(u["Content-Description"])||u["content-description"]&&/File Transfer/i.test(u["content-description"]))if("Blob"in window){var h=o||"text/html",d=r instanceof Blob?r:new Blob([r],{type:h}),m=window.URL.createObjectURL(d),v=[h,i.substr(i.lastIndexOf("/")+1),m].join(":"),g=u["content-disposition"]||u["Content-Disposition"];if(void 0!==g){var y=Object(D.g)(g);null!==y&&(v=y)}t=R.a.navigator&&R.a.navigator.msSaveOrOpenBlob?S.a.createElement("div",null,S.a.createElement("a",{href:m,onClick:function(){return R.a.navigator.msSaveOrOpenBlob(d,v)}},"Download file")):S.a.createElement("div",null,S.a.createElement("a",{href:m,download:v},"Download file"))}else t=S.a.createElement("pre",null,"Download headers detected but your browser does not support downloading binary via XHR (Blob).");else if(/json/i.test(o)){try{e=a()(JSON.parse(r),null," ")}catch(t){e="can't parse JSON. Raw result:\n\n"+r}t=S.a.createElement(p,{downloadable:!0,fileName:"".concat(f,".json"),value:e})}else/xml/i.test(o)?(e=at()(r,{textNodesOnSameLine:!0,indentor:" "}),t=S.a.createElement(p,{downloadable:!0,fileName:"".concat(f,".xml"),value:e})):t="text/html"===ut()(o)||/text\/plain/.test(o)?S.a.createElement(p,{downloadable:!0,fileName:"".concat(f,".html"),value:r}):/^image\//i.test(o)?o.includes("svg")?S.a.createElement("div",null," ",r," "):S.a.createElement("img",{style:{maxWidth:"100%"},src:window.URL.createObjectURL(r)}):/^audio\//i.test(o)?S.a.createElement("pre",null,S.a.createElement("audio",{controls:!0},S.a.createElement("source",{src:i,type:o}))):"string"==typeof r?S.a.createElement(p,{downloadable:!0,fileName:"".concat(f,".txt"),value:r}):r.size>0?l?S.a.createElement("div",null,S.a.createElement("p",{className:"i"},"Unrecognized response type; displaying content as text."),S.a.createElement(p,{downloadable:!0,fileName:"".concat(f,".txt"),value:l})):S.a.createElement("p",{className:"i"},"Unrecognized response type; unable to display."):null;return t?S.a.createElement("div",null,S.a.createElement("h5",null,"Response body"),t):null}}]),t}(S.a.PureComponent),lt=n(12),pt=n.n(lt),ft=function(e){function t(e){var n;return _()(this,t),n=oe()(this,ae()(t).call(this,e)),v()(ue()(n),"onChange",function(e,t,r){var o=n.props;(0,o.specActions.changeParamByIdentity)(o.onChangeKey,e,t,r)}),v()(ue()(n),"onChangeConsumesWrapper",function(e){var t=n.props;(0,t.specActions.changeConsumesValue)(t.onChangeKey,e)}),v()(ue()(n),"toggleTab",function(e){return"parameters"===e?n.setState({parametersVisible:!0,callbackVisible:!1}):"callbacks"===e?n.setState({callbackVisible:!0,parametersVisible:!1}):void 0}),n.state={callbackVisible:!1,parametersVisible:!0},n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this,t=this.props,n=t.onTryoutClick,r=t.onCancelClick,o=t.parameters,i=t.allowTryItOut,a=t.tryItOutEnabled,s=t.specPath,u=t.fn,c=t.getComponent,l=t.getConfigs,p=t.specSelectors,f=t.specActions,h=t.pathMethod,d=t.oas3Actions,m=t.oas3Selectors,v=t.operation,g=c("parameterRow"),y=c("TryItOutButton"),b=c("contentType"),_=c("Callbacks",!0),w=c("RequestBody",!0),x=a&&i,E=p.isOAS3(),C=v.get("requestBody");return S.a.createElement("div",{className:"opblock-section"},S.a.createElement("div",{className:"opblock-section-header"},E?S.a.createElement("div",{className:"tab-header"},S.a.createElement("div",{onClick:function(){return e.toggleTab("parameters")},className:"tab-item ".concat(this.state.parametersVisible&&"active")},S.a.createElement("h4",{className:"opblock-title"},S.a.createElement("span",null,"Parameters"))),v.get("callbacks")?S.a.createElement("div",{onClick:function(){return e.toggleTab("callbacks")},className:"tab-item ".concat(this.state.callbackVisible&&"active")},S.a.createElement("h4",{className:"opblock-title"},S.a.createElement("span",null,"Callbacks"))):null):S.a.createElement("div",{className:"tab-header"},S.a.createElement("h4",{className:"opblock-title"},"Parameters")),i?S.a.createElement(y,{enabled:a,onCancelClick:r,onTryoutClick:n}):null),this.state.parametersVisible?S.a.createElement("div",{className:"parameters-container"},o.count()?S.a.createElement("div",{className:"table-container"},S.a.createElement("table",{className:"parameters"},S.a.createElement("thead",null,S.a.createElement("tr",null,S.a.createElement("th",{className:"col_header parameters-col_name"},"Name"),S.a.createElement("th",{className:"col_header parameters-col_description"},"Description"))),S.a.createElement("tbody",null,function(e,t){return e.valueSeq().filter(O.a.Map.isMap).map(t)}(o,function(t,n){return S.a.createElement(g,{fn:u,specPath:s.push(n.toString()),getComponent:c,getConfigs:l,rawParam:t,param:p.parameterWithMetaByIdentity(h,t),key:"".concat(t.get("in"),".").concat(t.get("name")),onChange:e.onChange,onChangeConsumes:e.onChangeConsumesWrapper,specSelectors:p,specActions:f,oas3Actions:d,oas3Selectors:m,pathMethod:h,isExecute:x})}).toArray()))):S.a.createElement("div",{className:"opblock-description-wrapper"},S.a.createElement("p",null,"No parameters"))):null,this.state.callbackVisible?S.a.createElement("div",{className:"callbacks-container opblock-description-wrapper"},S.a.createElement(_,{callbacks:Object(k.Map)(v.get("callbacks")),specPath:s.slice(0,-1).push("callbacks")})):null,E&&C&&this.state.parametersVisible&&S.a.createElement("div",{className:"opblock-section opblock-section-request-body"},S.a.createElement("div",{className:"opblock-section-header"},S.a.createElement("h4",{className:"opblock-title parameter__name ".concat(C.get("required")&&"required")},"Request body"),S.a.createElement("label",null,S.a.createElement(b,{value:m.requestContentType.apply(m,pt()(h)),contentTypes:C.get("content",Object(k.List)()).keySeq(),onChange:function(e){d.setRequestContentType({value:e,pathMethod:h})},className:"body-param-content-type"}))),S.a.createElement("div",{className:"opblock-description-wrapper"},S.a.createElement(w,{specPath:s.slice(0,-1).push("requestBody"),requestBody:C,requestBodyValue:m.requestBodyValue.apply(m,pt()(h)),isExecute:x,activeExamplesKey:m.activeExamplesMember.apply(m,pt()(h).concat(["requestBody","requestBody"])),updateActiveExamplesKey:function(t){e.props.oas3Actions.setActiveExamplesMember({name:t,pathMethod:e.props.pathMethod,contextType:"requestBody",contextName:"requestBody"})},onChange:function(e,t){if(t){var n=m.requestBodyValue.apply(m,pt()(h)),r=k.Map.isMap(n)?n:Object(k.Map)();return d.setRequestBodyValue({pathMethod:h,value:r.setIn(t,e)})}d.setRequestBodyValue({value:e,pathMethod:h})},contentType:m.requestContentType.apply(m,pt()(h))}))))}}]),t}(E.Component);v()(ft,"defaultProps",{onTryoutClick:Function.prototype,onCancelClick:Function.prototype,tryItOutEnabled:!1,allowTryItOut:!0,onChangeKey:[],specPath:[]});var ht=function(e){var t=e.xKey,n=e.xVal;return S.a.createElement("div",{className:"parameter__extension"},t,": ",String(n))},dt=function(e){var t=e.param,n=e.isIncluded,r=e.onChange,o=e.isDisabled;return t.get("allowEmptyValue")?S.a.createElement("div",{className:rt()("parameter__empty_value_toggle",{disabled:o})},S.a.createElement("input",{type:"checkbox",disabled:o,checked:!o&&n,onChange:function(e){r(e.target.checked)}}),"Send empty value"):null},mt=n(118),vt=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onChangeWrapper",function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=r.props,o=n.onChange,i=n.rawParam;return o(i,""===e||e&&0===e.size?null:e,t)}),v()(ue()(r),"_onExampleSelect",function(e){r.props.oas3Actions.setActiveExamplesMember({name:e,pathMethod:r.props.pathMethod,contextType:"parameters",contextName:r.getParamKey()})}),v()(ue()(r),"onChangeIncludeEmpty",function(e){var t=r.props,n=t.specActions,o=t.param,i=t.pathMethod,a=o.get("name"),s=o.get("in");return n.updateEmptyParamInclusion(i,a,s,e)}),v()(ue()(r),"setDefaultValue",function(){var e=r.props,t=e.specSelectors,n=e.pathMethod,o=e.rawParam,i=e.oas3Selectors,a=t.parameterWithMetaByIdentity(n,o)||Object(k.Map)(),s=Object(mt.a)(a,{isOAS3:t.isOAS3()}),u=a.get("content",Object(k.Map)()).keySeq().first(),c=Object(D.m)(s.toJS(),u,{includeWriteOnly:!0});if(a&&void 0===a.get("value")&&"body"!==a.get("in")){var l;if(t.isSwagger2())l=a.get("x-example")||a.getIn(["schema","example"])||s.getIn(["default"]);else if(t.isOAS3()){var p=i.activeExamplesMember.apply(i,pt()(n).concat(["parameters",r.getParamKey()]));l=a.getIn(["examples",p,"value"])||a.getIn(["content",u,"example"])||a.get("example")||s.get("example")||s.get("default")}void 0===l||k.List.isList(l)||(l=Object(D.G)(l)),void 0!==l?r.onChangeWrapper(l):"object"===s.get("type")&&c&&!a.get("examples")&&r.onChangeWrapper(k.List.isList(c)?c:Object(D.G)(c))}}),r.setDefaultValue(),r}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){var t,n=e.specSelectors,r=e.pathMethod,o=e.rawParam,i=n.isOAS3(),a=n.parameterWithMetaByIdentity(r,o)||new k.Map;(a=a.isEmpty()?o:a,i)?t=Object(mt.a)(a,{isOAS3:i}).get("enum"):t=a?a.get("enum"):void 0;var s,u=a?a.get("value"):void 0;void 0!==u?s=u:o.get("required")&&t&&t.size&&(s=t.first()),void 0!==s&&s!==u&&this.onChangeWrapper(Object(D.v)(s)),this.setDefaultValue()}},{key:"getParamKey",value:function(){var e=this.props.param;return e?"".concat(e.get("name"),"-").concat(e.get("in")):null}},{key:"render",value:function(){var e=this.props,t=e.param,n=e.rawParam,r=e.getComponent,o=e.getConfigs,i=e.isExecute,a=e.fn,s=e.onChangeConsumes,u=e.specSelectors,c=e.pathMethod,l=e.specPath,p=e.oas3Selectors,f=u.isOAS3(),h=o(),d=h.showExtensions,m=h.showCommonExtensions;if(t||(t=n),!n)return null;var v,g,y,b=r("JsonSchemaForm"),_=r("ParamBody"),w=t.get("in"),x="body"!==w?null:S.a.createElement(_,{getComponent:r,fn:a,param:t,consumes:u.consumesOptionsFor(c),consumesValue:u.contentTypeValues(c).get("requestContentType"),onChange:this.onChangeWrapper,onChangeConsumes:s,isExecute:i,specSelectors:u,pathMethod:c}),E=r("modelExample"),C=r("Markdown"),O=r("ParameterExt"),A=r("ParameterIncludeEmpty"),T=r("ExamplesSelectValueRetainer"),j=r("Example"),P=u.parameterWithMetaByIdentity(c,n)||Object(k.Map)(),I=t.get("format"),M=Object(mt.a)(t,{isOAS3:f}),N=M.get("type"),L="formData"===w,U="FormData"in R.a,q=t.get("required"),F=M.getIn(["items","type"]),z=P?P.get("value"):"",B=m?Object(D.j)(t):null,V=d?Object(D.k)(t):null,H=!1;return void 0!==t&&(v=M.get("items")),void 0!==v?(g=v.get("enum"),y=v.get("default")):g=M.get("enum"),void 0!==g&&g.size>0&&(H=!0),void 0!==t&&(y=M.get("default"),void 0===t.get("example")&&t.get("x-example")),S.a.createElement("tr",{"data-param-name":t.get("name"),"data-param-in":t.get("in")},S.a.createElement("td",{className:"parameters-col_name"},S.a.createElement("div",{className:q?"parameter__name required":"parameter__name"},t.get("name"),q?S.a.createElement("span",{style:{color:"red"}}," *"):null),S.a.createElement("div",{className:"parameter__type"},N,F&&"[".concat(F,"]"),I&&S.a.createElement("span",{className:"prop-format"},"($",I,")")),S.a.createElement("div",{className:"parameter__deprecated"},f&&t.get("deprecated")?"deprecated":null),S.a.createElement("div",{className:"parameter__in"},"(",t.get("in"),")"),m&&B.size?B.map(function(e,t){return S.a.createElement(O,{key:"".concat(t,"-").concat(e),xKey:t,xVal:e})}):null,d&&V.size?V.map(function(e,t){return S.a.createElement(O,{key:"".concat(t,"-").concat(e),xKey:t,xVal:e})}):null),S.a.createElement("td",{className:"parameters-col_description"},t.get("description")?S.a.createElement(C,{source:t.get("description")}):null,!x&&i||!H?null:S.a.createElement(C,{className:"parameter__enum",source:"<i>Available values</i> : "+g.map(function(e){return e}).toArray().join(", ")}),!x&&i||void 0===y?null:S.a.createElement(C,{className:"parameter__default",source:"<i>Default value</i> : "+y}),L&&!U&&S.a.createElement("div",null,"Error: your browser does not support FormData"),f&&t.get("examples")?S.a.createElement("section",{className:"parameter-controls"},S.a.createElement(T,{examples:t.get("examples"),onSelect:this._onExampleSelect,updateValue:this.onChangeWrapper,getComponent:r,defaultToFirstExample:!0,currentKey:p.activeExamplesMember.apply(p,pt()(c).concat(["parameters",this.getParamKey()])),currentUserInputValue:z})):null,x?null:S.a.createElement(b,{fn:a,getComponent:r,value:z,required:q,disabled:!i,description:t.get("description")?"".concat(t.get("name")," - ").concat(t.get("description")):"".concat(t.get("name")),onChange:this.onChangeWrapper,errors:P.get("errors"),schema:M}),x&&M?S.a.createElement(E,{getComponent:r,specPath:l.push("schema"),getConfigs:o,isExecute:i,specSelectors:u,schema:M,example:x}):null,!x&&i?S.a.createElement(A,{onChange:this.onChangeIncludeEmpty,isIncluded:u.parameterInclusionSettingFor(c,t.get("name"),t.get("in")),isDisabled:z&&0!==z.size,param:t}):null,f&&t.get("examples")?S.a.createElement(j,{example:t.getIn(["examples",p.activeExamplesMember.apply(p,pt()(c).concat(["parameters",this.getParamKey()]))]),getComponent:r}):null))}}]),t}(E.Component),gt=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onClick",function(){var e=n.props,t=e.specSelectors,r=e.specActions,o=e.operation,i=e.path,a=e.method;r.validateParams([i,a]),t.validateBeforeExecute([i,a])&&(n.props.onExecute&&n.props.onExecute(),r.execute({operation:o,path:i,method:a}))}),v()(ue()(n),"onChangeProducesWrapper",function(e){return n.props.specActions.changeProducesValue([n.props.path,n.props.method],e)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("button",{className:"btn execute opblock-control__btn",onClick:this.onClick},"Execute")}}]),t}(E.Component),yt={color:"#999",fontStyle:"italic"},bt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.headers,n=e.getComponent,r=n("Property"),o=n("Markdown");return t&&t.size?S.a.createElement("div",{className:"headers-wrapper"},S.a.createElement("h4",{className:"headers__title"},"Headers:"),S.a.createElement("table",{className:"headers"},S.a.createElement("thead",null,S.a.createElement("tr",{className:"header-row"},S.a.createElement("th",{className:"header-col"},"Name"),S.a.createElement("th",{className:"header-col"},"Description"),S.a.createElement("th",{className:"header-col"},"Type"))),S.a.createElement("tbody",null,t.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],i=t[1];if(!O.a.Map.isMap(i))return null;var a=i.get("description"),s=i.getIn(["schema"])?i.getIn(["schema","type"]):i.getIn(["type"]),u=i.getIn(["schema","example"]);return S.a.createElement("tr",{key:n},S.a.createElement("td",{className:"header-col"},n),S.a.createElement("td",{className:"header-col"},a?S.a.createElement(o,{source:a}):null),S.a.createElement("td",{className:"header-col"},s," ",u?S.a.createElement(r,{propKey:"Example",propVal:u,propStyle:yt}):null))}).toArray()))):null}}]),t}(S.a.Component),_t=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.editorActions,n=e.errSelectors,r=e.layoutSelectors,o=e.layoutActions,i=(0,e.getComponent)("Collapse");if(t&&t.jumpToLine)var a=t.jumpToLine;var s=n.allErrors().filter(function(e){return"thrown"===e.get("type")||"error"===e.get("level")});if(!s||s.count()<1)return null;var u=r.isShown(["errorPane"],!0),c=s.sortBy(function(e){return e.get("line")});return S.a.createElement("pre",{className:"errors-wrapper"},S.a.createElement("hgroup",{className:"error"},S.a.createElement("h4",{className:"errors__title"},"Errors"),S.a.createElement("button",{className:"btn errors__clear-btn",onClick:function(){return o.show(["errorPane"],!u)}},u?"Hide":"Show")),S.a.createElement(i,{isOpened:u,animated:!0},S.a.createElement("div",{className:"errors"},c.map(function(e,t){var n=e.get("type");return"thrown"===n||"auth"===n?S.a.createElement(wt,{key:t,error:e.get("error")||e,jumpToLine:a}):"spec"===n?S.a.createElement(xt,{key:t,error:e,jumpToLine:a}):void 0}))))}}]),t}(S.a.Component),wt=function(e){var t=e.error,n=e.jumpToLine;if(!t)return null;var r=t.get("line");return S.a.createElement("div",{className:"error-wrapper"},t?S.a.createElement("div",null,S.a.createElement("h4",null,t.get("source")&&t.get("level")?Et(t.get("source"))+" "+t.get("level"):"",t.get("path")?S.a.createElement("small",null," at ",t.get("path")):null),S.a.createElement("span",{style:{whiteSpace:"pre-line",maxWidth:"100%"}},t.get("message")),S.a.createElement("div",{style:{"text-decoration":"underline",cursor:"pointer"}},r&&n?S.a.createElement("a",{onClick:n.bind(null,r)},"Jump to line ",r):null)):null)},xt=function(e){var t=e.error,n=e.jumpToLine,r=null;return t.get("path")?r=k.List.isList(t.get("path"))?S.a.createElement("small",null,"at ",t.get("path").join(".")):S.a.createElement("small",null,"at ",t.get("path")):t.get("line")&&!n&&(r=S.a.createElement("small",null,"on line ",t.get("line"))),S.a.createElement("div",{className:"error-wrapper"},t?S.a.createElement("div",null,S.a.createElement("h4",null,Et(t.get("source"))+" "+t.get("level")," ",r),S.a.createElement("span",{style:{whiteSpace:"pre-line"}},t.get("message")),S.a.createElement("div",{style:{"text-decoration":"underline",cursor:"pointer"}},n?S.a.createElement("a",{onClick:n.bind(null,t.get("line"))},"Jump to line ",t.get("line")):null)):null)};function Et(e){return(e||"").split(" ").map(function(e){return e[0].toUpperCase()+e.slice(1)}).join(" ")}wt.defaultProps={jumpToLine:null};var St=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onChangeWrapper",function(e){return n.props.onChange(e.target.value)}),n}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){this.props.contentTypes&&this.props.onChange(this.props.contentTypes.first())}},{key:"componentWillReceiveProps",value:function(e){e.contentTypes&&e.contentTypes.size&&(e.contentTypes.includes(e.value)||e.onChange(e.contentTypes.first()))}},{key:"render",value:function(){var e=this.props,t=e.contentTypes,n=e.className,r=e.value;return t&&t.size?S.a.createElement("div",{className:"content-type-wrapper "+(n||"")},S.a.createElement("select",{className:"content-type",value:r||"",onChange:this.onChangeWrapper},t.map(function(e){return S.a.createElement("option",{key:e,value:e},e)}).toArray())):null}}]),t}(S.a.Component);v()(St,"defaultProps",{onChange:function(){},value:null,contentTypes:Object(k.fromJS)(["application/json"])});var Ct=n(20),kt=n.n(Ct),Ot=n(46),At=n.n(Ot);function Tt(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter(function(e){return!!e}).join(" ").trim()}var jt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.fullscreen,n=e.full,r=At()(e,["fullscreen","full"]);if(t)return S.a.createElement("section",r);var o="swagger-container"+(n?"-full":"");return S.a.createElement("section",kt()({},r,{className:Tt(r.className,o)}))}}]),t}(S.a.Component),Pt={mobile:"",tablet:"-tablet",desktop:"-desktop",large:"-hd"},It=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.hide,n=e.keepContents,r=(e.mobile,e.tablet,e.desktop,e.large,At()(e,["hide","keepContents","mobile","tablet","desktop","large"]));if(t&&!n)return S.a.createElement("span",null);var o=[];for(var i in Pt)if(Pt.hasOwnProperty(i)){var a=Pt[i];if(i in this.props){var s=this.props[i];if(s<1){o.push("none"+a);continue}o.push("block"+a),o.push("col-"+s+a)}}var u=Tt.apply(void 0,[r.className].concat(o));return S.a.createElement("section",kt()({},r,{style:{display:t?"none":null},className:u}))}}]),t}(S.a.Component),Mt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("div",kt()({},this.props,{className:Tt(this.props.className,"wrapper")}))}}]),t}(S.a.Component),Nt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("button",kt()({},this.props,{className:Tt(this.props.className,"button")}))}}]),t}(S.a.Component);v()(Nt,"defaultProps",{className:""});var Rt=function(e){return S.a.createElement("textarea",e)},Dt=function(e){return S.a.createElement("input",e)},Lt=function(e){function t(e,n){var r,o;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onChange",function(e){var t,n=r.props,o=n.onChange,i=n.multiple,a=[].slice.call(e.target.options);t=i?a.filter(function(e){return e.selected}).map(function(e){return e.value}):e.target.value,r.setState({value:t}),o&&o(t)}),o=e.value?e.value:e.multiple?[""]:"",r.state={value:o},r}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){e.value!==this.props.value&&this.setState({value:e.value})}},{key:"render",value:function(){var e,t,n=this.props,r=n.allowedValues,o=n.multiple,i=n.allowEmptyValue,a=n.disabled,s=(null===(e=this.state.value)||void 0===e?void 0:null===(t=e.toJS)||void 0===t?void 0:t.call(e))||this.state.value;return S.a.createElement("select",{className:this.props.className,multiple:o,value:s,onChange:this.onChange,disabled:a},i?S.a.createElement("option",{value:""},"--"):null,r.map(function(e,t){return S.a.createElement("option",{key:t,value:String(e)},String(e))}))}}]),t}(S.a.Component);v()(Lt,"defaultProps",{multiple:!1,allowEmptyValue:!0});var Ut=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("a",kt()({},this.props,{rel:"noopener noreferrer",className:Tt(this.props.className,"link")}))}}]),t}(S.a.Component),qt=function(e){var t=e.children;return S.a.createElement("div",{style:{height:"auto",border:"none",margin:0,padding:0}}," ",t," ")},Ft=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"renderNotAnimated",value:function(){return this.props.isOpened?S.a.createElement(qt,null,this.props.children):S.a.createElement("noscript",null)}},{key:"render",value:function(){var e=this.props,t=e.animated,n=e.isOpened,r=e.children;return t?(r=n?r:null,S.a.createElement(qt,null,r)):this.renderNotAnimated()}}]),t}(S.a.Component);v()(Ft,"defaultProps",{isOpened:!1,animated:!1});var zt=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return(n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o)))).setTagShown=n._setTagShown.bind(ue()(n)),n}return le()(t,e),x()(t,[{key:"_setTagShown",value:function(e,t){this.props.layoutActions.show(e,t)}},{key:"showOp",value:function(e,t){this.props.layoutActions.show(e,t)}},{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.layoutSelectors,r=e.layoutActions,o=e.getComponent,i=t.taggedOperations(),a=o("Collapse");return S.a.createElement("div",null,S.a.createElement("h4",{className:"overview-title"},"Overview"),i.map(function(e,t){var o=e.get("operations"),i=["overview-tags",t],s=n.isShown(i,!0);return S.a.createElement("div",{key:"overview-"+t},S.a.createElement("h4",{onClick:function(){return r.show(i,!s)},className:"link overview-tag"}," ",s?"-":"+",t),S.a.createElement(a,{isOpened:s,animated:!0},o.map(function(e){var t=e.toObject(),o=t.path,i=t.method,a=t.id,s=a,u=n.isShown(["operations",s]);return S.a.createElement(Bt,{key:a,path:o,method:i,id:o+"-"+i,shown:u,showOpId:s,showOpIdPrefix:"operations",href:"#operation-".concat(s),onClick:r.show})}).toArray()))}).toArray(),i.size<1&&S.a.createElement("h3",null," No operations defined in spec! "))}}]),t}(S.a.Component),Bt=function(e){function t(e){var n;return _()(this,t),(n=oe()(this,ae()(t).call(this,e))).onClick=n._onClick.bind(ue()(n)),n}return le()(t,e),x()(t,[{key:"_onClick",value:function(){var e=this.props,t=e.showOpId,n=e.showOpIdPrefix;(0,e.onClick)([n,t],!e.shown)}},{key:"render",value:function(){var e=this.props,t=e.id,n=e.method,r=e.shown,o=e.href;return S.a.createElement(Ut,{href:o,style:{fontWeight:r?"bold":"normal"},onClick:this.onClick,className:"block opblock-link"},S.a.createElement("div",null,S.a.createElement("small",{className:"bold-label-".concat(n)},n.toUpperCase()),S.a.createElement("span",{className:"bold-label"},t)))}}]),t}(S.a.Component),Vt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.host,n=e.basePath;return S.a.createElement("pre",{className:"base-url"},"[ Base URL: ",t,n," ]")}}]),t}(S.a.Component),Ht=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.data,n=e.getComponent,r=t.get("name")||"the developer",o=t.get("url"),i=t.get("email"),a=n("Link");return S.a.createElement("div",{className:"info__contact"},o&&S.a.createElement("div",null,S.a.createElement(a,{href:Object(D.D)(o),target:"_blank"},r," - Website")),i&&S.a.createElement(a,{href:Object(D.D)("mailto:".concat(i))},o?"Send email to ".concat(r):"Contact ".concat(r)))}}]),t}(S.a.Component),Wt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.license,n=(0,e.getComponent)("Link"),r=t.get("name")||"License",o=t.get("url");return S.a.createElement("div",{className:"info__license"},o?S.a.createElement(n,{target:"_blank",href:Object(D.D)(o)},r):S.a.createElement("span",null,r))}}]),t}(S.a.Component),Jt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.url,n=(0,e.getComponent)("Link");return S.a.createElement(n,{target:"_blank",href:Object(D.D)(t)},S.a.createElement("span",{className:"url"}," ",t," "))}}]),t}(S.a.PureComponent),Yt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.info,n=e.url,r=e.host,o=e.basePath,i=e.getComponent,a=e.externalDocs,s=t.get("version"),u=t.get("description"),c=t.get("title"),l=t.get("termsOfService"),p=t.get("contact"),f=t.get("license"),h=(a||Object(k.fromJS)({})).toJS(),d=h.url,m=h.description,v=i("Markdown"),g=i("Link"),y=i("VersionStamp"),b=i("InfoUrl"),_=i("InfoBasePath");return S.a.createElement("div",{className:"info"},S.a.createElement("hgroup",{className:"main"},S.a.createElement("h2",{className:"title"},c,s&&S.a.createElement(y,{version:s})),r||o?S.a.createElement(_,{host:r,basePath:o}):null,n&&S.a.createElement(b,{getComponent:i,url:n})),S.a.createElement("div",{className:"description"},S.a.createElement(v,{source:u})),l&&S.a.createElement("div",{className:"info__tos"},S.a.createElement(g,{target:"_blank",href:Object(D.D)(l)},"Terms of service")),p&&p.size?S.a.createElement(Ht,{getComponent:i,data:p}):null,f&&f.size?S.a.createElement(Wt,{getComponent:i,license:f}):null,d?S.a.createElement(g,{className:"info__extdocs",target:"_blank",href:Object(D.D)(d)},m||d):null)}}]),t}(S.a.Component),Kt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.getComponent,r=t.info(),o=t.url(),i=t.basePath(),a=t.host(),s=t.externalDocs(),u=n("info");return S.a.createElement("div",null,r&&r.count()?S.a.createElement(u,{info:r,url:o,host:a,basePath:i,externalDocs:s,getComponent:n}):null)}}]),t}(S.a.Component),Gt=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){return null}}]),t}(S.a.Component),$t=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){return S.a.createElement("div",{className:"footer"})}}]),t}(S.a.Component),Zt=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onFilterChange",function(e){var t=e.target.value;n.props.layoutActions.updateFilter(t)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.layoutSelectors,r=(0,e.getComponent)("Col"),o="loading"===t.loadingStatus(),i="failed"===t.loadingStatus(),a=n.currentFilter(),s={};return i&&(s.color="red"),o&&(s.color="#aaa"),S.a.createElement("div",null,null===a||!1===a?null:S.a.createElement("div",{className:"filter-container"},S.a.createElement(r,{className:"filter wrapper",mobile:12},S.a.createElement("input",{className:"operation-filter-input",placeholder:"Filter by tag",type:"text",onChange:this.onFilterChange,value:!0===a||"true"===a?"":a,disabled:o,style:s}))))}}]),t}(S.a.Component),Xt=Function.prototype,Qt=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"updateValues",function(e){var t=e.param,n=e.isExecute,o=e.consumesValue,i=void 0===o?"":o,a=/xml/i.test(i),s=/json/i.test(i),u=a?t.get("value_xml"):t.get("value");if(void 0!==u){var c=!u&&s?"{}":u;r.setState({value:c}),r.onChange(c,{isXml:a,isEditBox:n})}else a?r.onChange(r.sample("xml"),{isXml:a,isEditBox:n}):r.onChange(r.sample(),{isEditBox:n})}),v()(ue()(r),"sample",function(e){var t=r.props,n=t.param,o=(0,t.fn.inferSchema)(n.toJS());return Object(D.m)(o,e,{includeWriteOnly:!0})}),v()(ue()(r),"onChange",function(e,t){var n=t.isEditBox,o=t.isXml;r.setState({value:e,isEditBox:n}),r._onChange(e,o)}),v()(ue()(r),"_onChange",function(e,t){(r.props.onChange||Xt)(e,t)}),v()(ue()(r),"handleOnChange",function(e){var t=r.props.consumesValue,n=/xml/i.test(t),o=e.target.value;r.onChange(o,{isXml:n})}),v()(ue()(r),"toggleIsEditBox",function(){return r.setState(function(e){return{isEditBox:!e.isEditBox}})}),r.state={isEditBox:!1,value:""},r}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){this.updateValues.call(this,this.props)}},{key:"componentWillReceiveProps",value:function(e){this.updateValues.call(this,e)}},{key:"render",value:function(){var e=this.props,n=e.onChangeConsumes,r=e.param,o=e.isExecute,i=e.specSelectors,a=e.pathMethod,s=e.getComponent,u=s("Button"),c=s("TextArea"),l=s("highlightCode"),p=s("contentType"),f=(i?i.parameterWithMetaByIdentity(a,r):r).get("errors",Object(k.List)()),h=i.contentTypeValues(a).get("requestContentType"),d=this.props.consumes&&this.props.consumes.size?this.props.consumes:t.defaultProp.consumes,m=this.state,v=m.value,g=m.isEditBox;return S.a.createElement("div",{className:"body-param","data-param-name":r.get("name"),"data-param-in":r.get("in")},g&&o?S.a.createElement(c,{className:"body-param__text"+(f.count()?" invalid":""),value:v,onChange:this.handleOnChange}):v&&S.a.createElement(l,{className:"body-param__example",value:v}),S.a.createElement("div",{className:"body-param-options"},o?S.a.createElement("div",{className:"body-param-edit"},S.a.createElement(u,{className:g?"btn cancel body-param__example-edit":"btn edit body-param__example-edit",onClick:this.toggleIsEditBox},g?"Cancel":"Edit")):null,S.a.createElement("label",{htmlFor:""},S.a.createElement("span",null,"Parameter content type"),S.a.createElement(p,{value:h,contentTypes:d,onChange:n,className:"body-param-content-type"}))))}}]),t}(E.PureComponent);v()(Qt,"defaultProp",{consumes:Object(k.fromJS)(["application/json"]),param:Object(k.fromJS)({}),onChange:Xt,onChangeConsumes:Xt});var en=n(90),tn=n.n(en);var nn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"handleFocus",value:function(e){e.target.select(),document.execCommand("copy")}},{key:"render",value:function(){var e=function(e){var t=[],n="",r=e.get("headers");if(t.push("curl"),t.push("-X",e.get("method")),t.push('"'.concat(e.get("url"),'"')),r&&r.size){var o=!0,i=!1,s=void 0;try{for(var u,c=tn()(e.get("headers").entries());!(o=(u=c.next()).done);o=!0){var l=u.value,p=Ge()(l,2),f=p[0];n=_=p[1],t.push("-H "),t.push('"'.concat(f,": ").concat(_,'"'))}}catch(e){i=!0,s=e}finally{try{o||null==c.return||c.return()}finally{if(i)throw s}}}if(e.get("body"))if("multipart/form-data"===n&&"POST"===e.get("method")){var h=!0,d=!1,m=void 0;try{for(var v,g=tn()(e.get("body").entrySeq());!(h=(v=g.next()).done);h=!0){var y=Ge()(v.value,2),b=y[0],_=y[1];t.push("-F"),_ instanceof R.a.File?t.push('"'.concat(b,"=@").concat(_.name).concat(_.type?";type=".concat(_.type):"",'"')):t.push('"'.concat(b,"=").concat(_,'"'))}}catch(e){d=!0,m=e}finally{try{h||null==g.return||g.return()}finally{if(d)throw m}}}else t.push("-d"),t.push(a()(e.get("body")).replace(/\\n/g,""));return t.join(" ")}(this.props.request);return S.a.createElement("div",null,S.a.createElement("h4",null,"Curl"),S.a.createElement("div",{className:"copy-paste"},S.a.createElement("textarea",{onFocus:this.handleFocus,readOnly:!0,className:"curl",style:{whiteSpace:"normal"},value:e})))}}]),t}(S.a.Component),rn=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onChange",function(e){n.setScheme(e.target.value)}),v()(ue()(n),"setScheme",function(e){var t=n.props,r=t.path,o=t.method;t.specActions.setScheme(e,r,o)}),n}return le()(t,e),x()(t,[{key:"componentWillMount",value:function(){var e=this.props.schemes;this.setScheme(e.first())}},{key:"componentWillReceiveProps",value:function(e){this.props.currentScheme&&e.schemes.includes(this.props.currentScheme)||this.setScheme(e.schemes.first())}},{key:"render",value:function(){var e=this.props,t=e.schemes,n=e.currentScheme;return S.a.createElement("label",{htmlFor:"schemes"},S.a.createElement("span",{className:"schemes-title"},"Schemes"),S.a.createElement("select",{onChange:this.onChange,value:n},t.valueSeq().map(function(e){return S.a.createElement("option",{value:e,key:e},e)}).toArray()))}}]),t}(S.a.Component),on=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.specActions,n=e.specSelectors,r=e.getComponent,o=n.operationScheme(),i=n.schemes(),a=r("schemes");return i&&i.size?S.a.createElement(a,{currentScheme:o,schemes:i,specActions:t}):null}}]),t}(S.a.Component),an=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"toggleCollapsed",function(){r.props.onToggle&&r.props.onToggle(r.props.modelName,!r.state.expanded),r.setState({expanded:!r.state.expanded})});var o=r.props,i=o.expanded,a=o.collapsedContent;return r.state={expanded:i,collapsedContent:a||t.defaultProps.collapsedContent},r}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){var e=this.props,t=e.hideSelfOnExpand,n=e.expanded,r=e.modelName;t&&n&&this.props.onToggle(r,n)}},{key:"componentWillReceiveProps",value:function(e){this.props.expanded!==e.expanded&&this.setState({expanded:e.expanded})}},{key:"render",value:function(){var e=this.props,t=e.title,n=e.classes;return this.state.expanded&&this.props.hideSelfOnExpand?S.a.createElement("span",{className:n||""},this.props.children):S.a.createElement("span",{className:n||""},t&&S.a.createElement("span",{onClick:this.toggleCollapsed,style:{cursor:"pointer"}},t),S.a.createElement("span",{onClick:this.toggleCollapsed,style:{cursor:"pointer"}},S.a.createElement("span",{className:"model-toggle"+(this.state.expanded?"":" collapsed")})),this.state.expanded?this.props.children:this.state.collapsedContent)}}]),t}(E.Component);v()(an,"defaultProps",{collapsedContent:"{...}",expanded:!1,title:null,onToggle:function(){},hideSelfOnExpand:!1});var sn=function(e){function t(e,n){var r;_()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"activeTab",function(e){var t=e.target.dataset.name;r.setState({activeTab:t})});var o=r.props,i=o.getConfigs,a=o.isExecute,s=i().defaultModelRendering,u=s;return"example"!==s&&"model"!==s&&(u="example"),a&&(u="example"),r.state={activeTab:u},r}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){e.isExecute&&!this.props.isExecute&&this.props.example&&this.setState({activeTab:"example"})}},{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.specSelectors,r=e.schema,o=e.example,i=e.isExecute,a=e.getConfigs,s=e.specPath,u=a().defaultModelExpandDepth,c=t("ModelWrapper"),l=t("highlightCode"),p=n.isOAS3();return S.a.createElement("div",{className:"model-example"},S.a.createElement("ul",{className:"tab"},S.a.createElement("li",{className:"tabitem"+("example"===this.state.activeTab?" active":"")},S.a.createElement("a",{className:"tablinks","data-name":"example",onClick:this.activeTab},i?"Edit Value":"Example Value")),r?S.a.createElement("li",{className:"tabitem"+("model"===this.state.activeTab?" active":"")},S.a.createElement("a",{className:"tablinks"+(i?" inactive":""),"data-name":"model",onClick:this.activeTab},p?"Schema":"Model")):null),S.a.createElement("div",null,"example"===this.state.activeTab?o||S.a.createElement(l,{value:"(no example available)"}):null,"model"===this.state.activeTab&&S.a.createElement(c,{schema:r,getComponent:t,getConfigs:a,specSelectors:n,expandDepth:u,specPath:s})))}}]),t}(S.a.Component),un=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onToggle",function(e,t){n.props.layoutActions&&n.props.layoutActions.show(["models",e],t)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e,t=this.props,n=t.getComponent,r=t.getConfigs,o=n("Model");return this.props.layoutSelectors&&(e=this.props.layoutSelectors.isShown(["models",this.props.name])),S.a.createElement("div",{className:"model-box"},S.a.createElement(o,kt()({},this.props,{getConfigs:r,expanded:e,depth:1,onToggle:this.onToggle,expandDepth:this.props.expandDepth||0})))}}]),t}(E.Component),cn=n(191),ln=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"getSchemaBasePath",function(){return n.props.specSelectors.isOAS3()?["components","schemas"]:["definitions"]}),v()(ue()(n),"getCollapsedContent",function(){return" "}),v()(ue()(n),"handleToggle",function(e,t){n.props.layoutActions.show(["models",e],t),t&&n.props.specActions.requestResolvedSubtree([].concat(pt()(n.getSchemaBasePath()),[e]))}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this,t=this.props,n=t.specSelectors,r=t.getComponent,o=t.layoutSelectors,i=t.layoutActions,a=t.getConfigs,s=n.definitions(),u=a(),c=u.docExpansion,l=u.defaultModelsExpandDepth;if(!s.size||l<0)return null;var p=o.isShown("models",l>0&&"none"!==c),f=this.getSchemaBasePath(),h=n.isOAS3(),d=r("ModelWrapper"),m=r("Collapse"),v=r("ModelCollapse"),g=r("JumpToPath");return S.a.createElement("section",{className:p?"models is-open":"models"},S.a.createElement("h4",{onClick:function(){return i.show("models",!p)}},S.a.createElement("span",null,h?"Schemas":"Models"),S.a.createElement("svg",{width:"20",height:"20"},S.a.createElement("use",{xlinkHref:p?"#large-arrow-down":"#large-arrow"}))),S.a.createElement(m,{isOpened:p},s.entrySeq().map(function(t){var s=Ge()(t,1)[0],u=[].concat(pt()(f),[s]),c=n.specResolvedSubtree(u),p=n.specJson().getIn(u),h=k.Map.isMap(c)?c:O.a.Map(),m=k.Map.isMap(p)?p:O.a.Map(),y=h.get("title")||m.get("title")||s,b=o.isShown(["models",s],!1);b&&0===h.size&&m.size>0&&e.props.specActions.requestResolvedSubtree([].concat(pt()(e.getSchemaBasePath()),[s]));var _=O.a.List([].concat(pt()(f),[s])),w=S.a.createElement(d,{name:s,expandDepth:l,schema:h||O.a.Map(),displayName:y,specPath:_,getComponent:r,specSelectors:n,getConfigs:a,layoutSelectors:o,layoutActions:i}),x=S.a.createElement("span",{className:"model-box"},S.a.createElement("span",{className:"model model-title"},y));return S.a.createElement("div",{id:"model-".concat(s),className:"model-container",key:"models-section-".concat(s)},S.a.createElement("span",{className:"models-jump-to-path"},S.a.createElement(g,{specPath:_})),S.a.createElement(v,{classes:"model-box",collapsedContent:e.getCollapsedContent(s),onToggle:e.handleToggle,title:x,displayName:y,modelName:s,hideSelfOnExpand:!0,expanded:l>0&&b},w))}).toArray()))}}]),t}(E.Component),pn=function(e){var t=e.value,n=(0,e.getComponent)("ModelCollapse"),r=S.a.createElement("span",null,"Array [ ",t.count()," ]");return S.a.createElement("span",{className:"prop-enum"},"Enum:",S.a.createElement("br",null),S.a.createElement(n,{collapsedContent:r},"[ ",t.join(", ")," ]"))},fn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.schema,n=e.name,r=e.displayName,o=e.isRef,i=e.getComponent,s=e.getConfigs,u=e.depth,c=e.onToggle,l=e.expanded,p=e.specPath,f=At()(e,["schema","name","displayName","isRef","getComponent","getConfigs","depth","onToggle","expanded","specPath"]),h=f.specSelectors,d=f.expandDepth,m=h.isOAS3;if(!t)return null;var v=s().showExtensions,g=t.get("description"),y=t.get("properties"),b=t.get("additionalProperties"),_=t.get("title")||r||n,w=t.get("required"),x=i("JumpToPath",!0),E=i("Markdown"),C=i("Model"),O=i("ModelCollapse"),A=function(){return S.a.createElement("span",{className:"model-jump-to-path"},S.a.createElement(x,{specPath:p}))},T=S.a.createElement("span",null,S.a.createElement("span",null,"{"),"...",S.a.createElement("span",null,"}"),o?S.a.createElement(A,null):""),j=h.isOAS3()?t.get("anyOf"):null,P=h.isOAS3()?t.get("oneOf"):null,I=h.isOAS3()?t.get("not"):null,M=_&&S.a.createElement("span",{className:"model-title"},o&&t.get("$$ref")&&S.a.createElement("span",{className:"model-hint"},t.get("$$ref")),S.a.createElement("span",{className:"model-title__text"},_));return S.a.createElement("span",{className:"model"},S.a.createElement(O,{modelName:n,title:M,onToggle:c,expanded:!!l||u<=d,collapsedContent:T},S.a.createElement("span",{className:"brace-open object"},"{"),o?S.a.createElement(A,null):null,S.a.createElement("span",{className:"inner-object"},S.a.createElement("table",{className:"model"},S.a.createElement("tbody",null,g?S.a.createElement("tr",{style:{color:"#666",fontWeight:"normal"}},S.a.createElement("td",{style:{fontWeight:"bold"}},"description:"),S.a.createElement("td",null,S.a.createElement(E,{source:g}))):null,y&&y.size?y.entrySeq().map(function(e){var t=Ge()(e,2),r=t[0],o=t[1],a=m()&&o.get("deprecated"),c=k.List.isList(w)&&w.contains(r),l={verticalAlign:"top",paddingRight:"0.2em"};return c&&(l.fontWeight="bold"),S.a.createElement("tr",{key:r,className:a&&"deprecated"},S.a.createElement("td",{style:l},r,c&&S.a.createElement("span",{style:{color:"red"}},"*")),S.a.createElement("td",{style:{verticalAlign:"top"}},S.a.createElement(C,kt()({key:"object-".concat(n,"-").concat(r,"_").concat(o)},f,{required:c,getComponent:i,specPath:p.push("properties",r),getConfigs:s,schema:o,depth:u+1}))))}).toArray():null,v?S.a.createElement("tr",null," "):null,v?t.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],r=t[1];if("x-"===n.slice(0,2)){var o=r?r.toJS?r.toJS():r:null;return S.a.createElement("tr",{key:n,style:{color:"#777"}},S.a.createElement("td",null,n),S.a.createElement("td",{style:{verticalAlign:"top"}},a()(o)))}}).toArray():null,b&&b.size?S.a.createElement("tr",null,S.a.createElement("td",null,"< * >:"),S.a.createElement("td",null,S.a.createElement(C,kt()({},f,{required:!1,getComponent:i,specPath:p.push("additionalProperties"),getConfigs:s,schema:b,depth:u+1})))):null,j?S.a.createElement("tr",null,S.a.createElement("td",null,"anyOf ->"),S.a.createElement("td",null,j.map(function(e,t){return S.a.createElement("div",{key:t},S.a.createElement(C,kt()({},f,{required:!1,getComponent:i,specPath:p.push("anyOf",t),getConfigs:s,schema:e,depth:u+1})))}))):null,P?S.a.createElement("tr",null,S.a.createElement("td",null,"oneOf ->"),S.a.createElement("td",null,P.map(function(e,t){return S.a.createElement("div",{key:t},S.a.createElement(C,kt()({},f,{required:!1,getComponent:i,specPath:p.push("oneOf",t),getConfigs:s,schema:e,depth:u+1})))}))):null,I?S.a.createElement("tr",null,S.a.createElement("td",null,"not ->"),S.a.createElement("td",null,S.a.createElement("div",null,S.a.createElement(C,kt()({},f,{required:!1,getComponent:i,specPath:p.push("not"),getConfigs:s,schema:I,depth:u+1}))))):null))),S.a.createElement("span",{className:"brace-close"},"}")))}}]),t}(E.Component),hn={color:"#999",fontStyle:"italic"},dn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.getConfigs,r=e.schema,o=e.depth,i=e.expandDepth,a=e.name,s=e.displayName,u=e.specPath,c=r.get("description"),l=r.get("items"),p=r.get("title")||s||a,f=r.filter(function(e,t){return-1===["type","items","description","$$ref"].indexOf(t)}),h=t("Markdown"),d=t("ModelCollapse"),m=t("Model"),v=t("Property"),g=p&&S.a.createElement("span",{className:"model-title"},S.a.createElement("span",{className:"model-title__text"},p));return S.a.createElement("span",{className:"model"},S.a.createElement(d,{title:g,expanded:o<=i,collapsedContent:"[...]"},"[",f.size?f.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],r=t[1];return S.a.createElement(v,{key:"".concat(n,"-").concat(r),propKey:n,propVal:r,propStyle:hn})}):null,c?S.a.createElement(h,{source:c}):f.size?S.a.createElement("div",{className:"markdown"}):null,S.a.createElement("span",null,S.a.createElement(m,kt()({},this.props,{getConfigs:n,specPath:u.push("items"),name:null,schema:l,required:!1,depth:o+1}))),"]"))}}]),t}(E.Component),mn={color:"#6b6b6b",fontStyle:"italic"},vn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.schema,n=e.getComponent,r=e.getConfigs,o=e.name,i=e.displayName,a=e.depth,s=r().showExtensions;if(!t||!t.get)return S.a.createElement("div",null);var u=t.get("type"),c=t.get("format"),l=t.get("xml"),p=t.get("enum"),f=t.get("title")||i||o,h=t.get("description"),d=Object(D.k)(t),m=t.filter(function(e,t){return-1===["enum","type","format","description","$$ref"].indexOf(t)}).filterNot(function(e,t){return d.has(t)}),v=n("Markdown"),g=n("EnumModel"),y=n("Property");return S.a.createElement("span",{className:"model"},S.a.createElement("span",{className:"prop"},o&&S.a.createElement("span",{className:"".concat(1===a&&"model-title"," prop-name")},f),S.a.createElement("span",{className:"prop-type"},u),c&&S.a.createElement("span",{className:"prop-format"},"($",c,")"),m.size?m.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],r=t[1];return S.a.createElement(y,{key:"".concat(n,"-").concat(r),propKey:n,propVal:r,propStyle:mn})}):null,s&&d.size?d.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],r=t[1];return S.a.createElement(y,{key:"".concat(n,"-").concat(r),propKey:n,propVal:r,propStyle:mn})}):null,h?S.a.createElement(v,{source:h}):null,l&&l.size?S.a.createElement("span",null,S.a.createElement("br",null),S.a.createElement("span",{style:mn},"xml:"),l.entrySeq().map(function(e){var t=Ge()(e,2),n=t[0],r=t[1];return S.a.createElement("span",{key:"".concat(n,"-").concat(r),style:mn},S.a.createElement("br",null),"   ",n,": ",String(r))}).toArray()):null,p&&S.a.createElement(g,{value:p,getComponent:n})))}}]),t}(E.Component),gn=function(e){var t=e.propKey,n=e.propVal,r=e.propStyle;return S.a.createElement("span",{style:r},S.a.createElement("br",null),t,": ",String(n))},yn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.onTryoutClick,n=e.onCancelClick,r=e.enabled;return S.a.createElement("div",{className:"try-out"},r?S.a.createElement("button",{className:"btn try-out__btn cancel",onClick:n},"Cancel"):S.a.createElement("button",{className:"btn try-out__btn",onClick:t},"Try it out "))}}]),t}(S.a.Component);v()(yn,"defaultProps",{onTryoutClick:Function.prototype,onCancelClick:Function.prototype,enabled:!1});var bn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.bypass,n=e.isSwagger2,r=e.isOAS3,o=e.alsoShow;return t?S.a.createElement("div",null,this.props.children):n&&r?S.a.createElement("div",{className:"version-pragma"},o,S.a.createElement("div",{className:"version-pragma__message version-pragma__message--ambiguous"},S.a.createElement("div",null,S.a.createElement("h3",null,"Unable to render this definition"),S.a.createElement("p",null,S.a.createElement("code",null,"swagger")," and ",S.a.createElement("code",null,"openapi")," fields cannot be present in the same Swagger or OpenAPI definition. Please remove one of the fields."),S.a.createElement("p",null,"Supported version fields are ",S.a.createElement("code",null,"swagger: ",'"2.0"')," and those that match ",S.a.createElement("code",null,"openapi: 3.0.n")," (for example, ",S.a.createElement("code",null,"openapi: 3.0.0"),").")))):n||r?S.a.createElement("div",null,this.props.children):S.a.createElement("div",{className:"version-pragma"},o,S.a.createElement("div",{className:"version-pragma__message version-pragma__message--missing"},S.a.createElement("div",null,S.a.createElement("h3",null,"Unable to render this definition"),S.a.createElement("p",null,"The provided definition does not specify a valid version field."),S.a.createElement("p",null,"Please indicate a valid Swagger or OpenAPI version field. Supported version fields are ",S.a.createElement("code",null,"swagger: ",'"2.0"')," and those that match ",S.a.createElement("code",null,"openapi: 3.0.n")," (for example, ",S.a.createElement("code",null,"openapi: 3.0.0"),")."))))}}]),t}(S.a.PureComponent);v()(bn,"defaultProps",{alsoShow:null,children:null,bypass:!1});var _n=function(e){var t=e.version;return S.a.createElement("small",null,S.a.createElement("pre",{className:"version"}," ",t," "))},wn=function(e){var t=e.enabled,n=e.path,r=e.text;return S.a.createElement("a",{className:"nostyle",onClick:t?function(e){return e.preventDefault()}:null,href:t?"#/".concat(n):null},S.a.createElement("span",null,r))},xn=function(){return S.a.createElement("div",null,S.a.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",style:{position:"absolute",width:0,height:0}},S.a.createElement("defs",null,S.a.createElement("symbol",{viewBox:"0 0 20 20",id:"unlocked"},S.a.createElement("path",{d:"M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"})),S.a.createElement("symbol",{viewBox:"0 0 20 20",id:"locked"},S.a.createElement("path",{d:"M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"})),S.a.createElement("symbol",{viewBox:"0 0 20 20",id:"close"},S.a.createElement("path",{d:"M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"})),S.a.createElement("symbol",{viewBox:"0 0 20 20",id:"large-arrow"},S.a.createElement("path",{d:"M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"})),S.a.createElement("symbol",{viewBox:"0 0 20 20",id:"large-arrow-down"},S.a.createElement("path",{d:"M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"})),S.a.createElement("symbol",{viewBox:"0 0 24 24",id:"jump-to"},S.a.createElement("path",{d:"M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"})),S.a.createElement("symbol",{viewBox:"0 0 24 24",id:"expand"},S.a.createElement("path",{d:"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"})))))},En=n(192),Sn=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.errSelectors,n=e.specSelectors,r=e.getComponent,o=r("SvgAssets"),i=r("InfoContainer",!0),a=r("VersionPragmaFilter"),s=r("operations",!0),u=r("Models",!0),c=r("Row"),l=r("Col"),p=r("errors",!0),f=r("ServersContainer",!0),h=r("SchemesContainer",!0),d=r("AuthorizeBtnContainer",!0),m=r("FilterContainer",!0),v=n.isSwagger2(),g=n.isOAS3(),y=!n.specStr(),b=n.loadingStatus(),_=null;if("loading"===b&&(_=S.a.createElement("div",{className:"info"},S.a.createElement("div",{className:"loading-container"},S.a.createElement("div",{className:"loading"})))),"failed"===b&&(_=S.a.createElement("div",{className:"info"},S.a.createElement("div",{className:"loading-container"},S.a.createElement("h4",{className:"title"},"Failed to load API definition."),S.a.createElement(p,null)))),"failedConfig"===b){var w=t.lastError(),x=w?w.get("message"):"";_=S.a.createElement("div",{className:"info",style:{maxWidth:"880px",marginLeft:"auto",marginRight:"auto",textAlign:"center"}},S.a.createElement("div",{className:"loading-container"},S.a.createElement("h4",{className:"title"},"Failed to load remote configuration."),S.a.createElement("p",null,x)))}if(!_&&y&&(_=S.a.createElement("h4",null,"No API definition provided.")),_)return S.a.createElement("div",{className:"swagger-ui"},S.a.createElement("div",{className:"loading-container"},_));var E=n.servers(),C=n.schemes(),k=E&&E.size,O=C&&C.size,A=!!n.securityDefinitions();return S.a.createElement("div",{className:"swagger-ui"},S.a.createElement(o,null),S.a.createElement(a,{isSwagger2:v,isOAS3:g,alsoShow:S.a.createElement(p,null)},S.a.createElement(p,null),S.a.createElement(c,{className:"information-container"},S.a.createElement(l,{mobile:12},S.a.createElement(i,null))),k||O||A?S.a.createElement("div",{className:"scheme-container"},S.a.createElement(l,{className:"schemes wrapper",mobile:12},k?S.a.createElement(f,null):null,O?S.a.createElement(h,null):null,A?S.a.createElement(d,null):null)):null,S.a.createElement(m,null),S.a.createElement(c,null,S.a.createElement(l,{mobile:12,desktop:12},S.a.createElement(s,null))),S.a.createElement(c,null,S.a.createElement(l,{mobile:12,desktop:12},S.a.createElement(u,null)))))}}]),t}(S.a.Component),Cn=n(480),kn=n.n(Cn),On={value:"",onChange:function(){},schema:{},keyName:"",required:!1,errors:Object(k.List)()},An=function(e){function t(){return _()(this,t),oe()(this,ae()(t).apply(this,arguments))}return le()(t,e),x()(t,[{key:"componentDidMount",value:function(){var e=this.props,t=e.dispatchInitialValue,n=e.value,r=e.onChange;t&&r(n)}},{key:"render",value:function(){var e=this.props,t=e.schema,n=e.errors,r=e.value,o=e.onChange,i=e.getComponent,a=e.fn,s=e.disabled;t.toJS&&(t=t.toJS());var u=t,c=u.type,l=u.format,p=void 0===l?"":l,f=i(p?"JsonSchema_".concat(c,"_").concat(p):"JsonSchema_".concat(c))||i("JsonSchema_string");return S.a.createElement(f,kt()({},this.props,{errors:n,fn:a,getComponent:i,value:r,onChange:o,schema:t,disabled:s}))}}]),t}(E.Component);v()(An,"defaultProps",On);var Tn=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onChange",function(e){var t="file"===n.props.schema.type?e.target.files[0]:e.target.value;n.props.onChange(t,n.props.keyName)}),v()(ue()(n),"onEnumChange",function(e){return n.props.onChange(e)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.value,r=e.schema,o=e.errors,i=e.required,a=e.description,s=e.disabled,u=r.enum;if(o=o.toJS?o.toJS():[],u){var c=t("Select");return S.a.createElement(c,{className:o.length?"invalid":"",title:o.length?o:"",allowedValues:u,value:n,allowEmptyValue:!i,disabled:s,onChange:this.onEnumChange})}var l=s||"formData"===r.in&&!("FormData"in window),p=t("Input");return"file"===r.type?S.a.createElement(p,{type:"file",className:o.length?"invalid":"",title:o.length?o:"",onChange:this.onChange,disabled:l}):S.a.createElement(kn.a,{type:"password"===r.format?"password":"text",className:o.length?"invalid":"",title:o.length?o:"",value:n,minLength:0,debounceTimeout:350,placeholder:a,onChange:this.onChange,disabled:l})}}]),t}(E.Component);v()(Tn,"defaultProps",On);var jn=function(e){function t(e,n){var r;return _()(this,t),r=oe()(this,ae()(t).call(this,e,n)),v()(ue()(r),"onChange",function(){return r.props.onChange(r.state.value)}),v()(ue()(r),"onItemChange",function(e,t){r.setState(function(n){return{value:n.value.set(t,e)}},r.onChange)}),v()(ue()(r),"removeItem",function(e){r.setState(function(t){return{value:t.value.remove(e)}},r.onChange)}),v()(ue()(r),"addItem",function(){r.setState(function(e){return e.value=Mn(e.value),{value:e.value.push("")}},r.onChange)}),v()(ue()(r),"onEnumChange",function(e){r.setState(function(){return{value:e}},r.onChange)}),r.state={value:Mn(e.value)},r}return le()(t,e),x()(t,[{key:"componentWillReceiveProps",value:function(e){e.value!==this.state.value&&this.setState({value:e.value})}},{key:"render",value:function(){var e=this,t=this.props,n=t.getComponent,r=t.required,o=t.schema,i=t.errors,a=t.fn,s=t.disabled;i=i.toJS?i.toJS():[];var u=a.inferSchema(o.items),c=n("JsonSchemaForm"),l=n("Button"),p=u.enum,f=this.state.value;if(p){var h=n("Select");return S.a.createElement(h,{className:i.length?"invalid":"",title:i.length?i:"",multiple:!0,value:f,disabled:s,allowedValues:p,allowEmptyValue:!r,onChange:this.onEnumChange})}return S.a.createElement("div",{className:"json-schema-array"},!f||!f.count||f.count()<1?null:f.map(function(t,r){var o=y()({},u);if(i.length){var p=i.filter(function(e){return e.index===r});p.length&&(i=[p[0].error+r])}return S.a.createElement("div",{key:r,className:"json-schema-form-item"},S.a.createElement(c,{fn:a,getComponent:n,value:t,onChange:function(t){return e.onItemChange(t,r)},schema:o,disabled:s}),s?null:S.a.createElement(l,{className:"btn btn-sm json-schema-form-item-remove",onClick:function(){return e.removeItem(r)}}," - "))}).toArray(),s?null:S.a.createElement(l,{className:"btn btn-sm json-schema-form-item-add ".concat(i.length?"invalid":null),onClick:this.addItem},"Add item"))}}]),t}(E.PureComponent);v()(jn,"defaultProps",On);var Pn=function(e){function t(){var e,n;_()(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return n=oe()(this,(e=ae()(t)).call.apply(e,[this].concat(o))),v()(ue()(n),"onEnumChange",function(e){return n.props.onChange(e)}),n}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.value,r=e.errors,o=e.schema,i=e.required,a=e.disabled;r=r.toJS?r.toJS():[];var s=t("Select");return S.a.createElement(s,{className:r.length?"invalid":"",title:r.length?r:"",value:String(n),disabled:a,allowedValues:Object(k.fromJS)(o.enum||["true","false"]),allowEmptyValue:!o.enum||!i,onChange:this.onEnumChange})}}]),t}(E.Component);v()(Pn,"defaultProps",On);var In=function(e){function t(){var e;return _()(this,t),e=oe()(this,ae()(t).call(this)),v()(ue()(e),"onChange",function(t){e.props.onChange(t)}),v()(ue()(e),"handleOnChange",function(t){var n=t.target.value;e.onChange(n)}),e}return le()(t,e),x()(t,[{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.value,r=e.errors,o=e.disabled,i=t("TextArea");return S.a.createElement("div",null,S.a.createElement(i,{className:rt()({invalid:r.size}),title:r.size?r.join(", "):"",value:Object(D.G)(n),disabled:o,onChange:this.handleOnChange}))}}]),t}(E.PureComponent);function Mn(e){return k.List.isList(e)?e:Object(k.List)()}v()(In,"defaultProps",On);var Nn=function(){var e={components:{App:he,authorizationPopup:de,authorizeBtn:me,AuthorizeBtnContainer:ve,authorizeOperationBtn:ge,auths:ye,AuthItem:be,authError:_e,oauth2:Te,apiKeyAuth:we,basicAuth:xe,clear:je,liveResponse:Me,info:Yt,InfoContainer:Kt,JumpToPath:Gt,onlineValidatorBadge:De,operations:Fe,operation:Be,OperationSummary:We,OperationSummaryMethod:Je,OperationSummaryPath:Ye,highlightCode:et,responses:tt,response:ot,responseBody:ct,parameters:ft,parameterRow:vt,execute:gt,headers:bt,errors:_t,contentType:St,overview:zt,footer:$t,FilterContainer:Zt,ParamBody:Qt,curl:nn,schemes:rn,SchemesContainer:on,modelExample:sn,ModelWrapper:un,ModelCollapse:an,Model:cn.a,Models:ln,EnumModel:pn,ObjectModel:fn,ArrayModel:dn,PrimitiveModel:vn,Property:gn,TryItOutButton:yn,Markdown:En.a,BaseLayout:Sn,VersionPragmaFilter:bn,VersionStamp:_n,OperationExt:$e,OperationExtRow:Ze,ParameterExt:ht,ParameterIncludeEmpty:dt,OperationTag:ze,OperationContainer:fe,DeepLink:wn,InfoUrl:Jt,InfoBasePath:Vt,SvgAssets:xn,Example:Ee,ExamplesSelect:ke,ExamplesSelectValueRetainer:Ae}},t={components:r},n={components:o};return[Q.default,Z.default,K.default,J.default,W.default,V.default,H.default,Y.default,e,t,G.default,n,$.default,X.default,ee.default,te.default,ne.default]},Rn=n(298);function Dn(){return[Nn,Rn.default]}var Ln=n(320);n.d(t,"default",function(){return Vn});var Un=!0,qn="g00c8e964",Fn="3.23.10",zn="jenins-swagger-oss",Bn="Sun, 15 Sep 2019 20:39:09 GMT";function Vn(e){R.a.versions=R.a.versions||{},R.a.versions.swaggerUi={version:Fn,gitRevision:qn,gitDirty:Un,buildTimestamp:Bn,machine:zn};var t={dom_id:null,domNode:null,spec:{},url:"",urls:null,layout:"BaseLayout",docExpansion:"list",maxDisplayedTags:null,filter:null,validatorUrl:"https://validator.swagger.io/validator",oauth2RedirectUrl:"".concat(window.location.protocol,"//").concat(window.location.host,"/oauth2-redirect.html"),configs:{},custom:{},displayOperationId:!1,displayRequestDuration:!1,deepLinking:!1,requestInterceptor:function(e){return e},responseInterceptor:function(e){return e},showMutatedRequest:!0,defaultModelRendering:"example",defaultModelExpandDepth:1,defaultModelsExpandDepth:1,showExtensions:!1,showCommonExtensions:!1,withCredentials:void 0,supportedSubmitMethods:["get","put","post","delete","options","head","patch","trace"],presets:[Dn],plugins:[],initialState:{},fn:{},components:{}},n=Object(D.B)(),r=e.domNode;delete e.domNode;var o=f()({},t,e,n),i={system:{configs:o.configs},plugins:o.presets,state:f()({layout:{layout:o.layout,filter:o.filter},spec:{spec:"",url:o.url}},o.initialState)};if(o.initialState)for(var s in o.initialState)o.initialState.hasOwnProperty(s)&&void 0===o.initialState[s]&&delete i.state[s];var c=new U(i);c.register([o.plugins,function(){return{fn:o.fn,components:o.components,state:o.state}}]);var p=c.getSystem(),h=function(e){var t=p.specSelectors.getLocalConfig?p.specSelectors.getLocalConfig():{},i=f()({},t,o,e||{},n);if(r&&(i.domNode=r),c.setConfigs(i),p.configsActions.loaded(),null!==e&&(!n.url&&"object"===l()(i.spec)&&u()(i.spec).length?(p.specActions.updateUrl(""),p.specActions.updateLoadingStatus("success"),p.specActions.updateSpec(a()(i.spec))):p.specActions.download&&i.url&&!i.urls&&(p.specActions.updateUrl(i.url),p.specActions.download(i.url))),i.domNode)p.render(i.domNode,"App");else if(i.dom_id){var s=document.querySelector(i.dom_id);p.render(s,"App")}else null===i.dom_id||null===i.domNode||console.error("Skipped rendering: no `dom_id` or `domNode` was specified");return p},d=n.config||o.configUrl;return d&&p.specActions&&p.specActions.getConfigByUrl&&(!p.specActions.getConfigByUrl||p.specActions.getConfigByUrl({url:d,loadRemoteConfig:!0,requestInterceptor:o.requestInterceptor,responseInterceptor:o.responseInterceptor},h))?(p.specActions.getConfigByUrl(d,h),p):h()}Vn.presets={apis:Dn},Vn.plugins=Ln.default}]).default});
+//# sourceMappingURL=swagger-ui-bundle.js.map \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui.css b/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui.css
new file mode 100644
index 00000000..5d620da6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/dist/en-US/swagger-ui.css
@@ -0,0 +1,4 @@
+.swagger-ui{
+ /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */font-family:sans-serif;color:#3b4151}.swagger-ui html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}.swagger-ui body{margin:0}.swagger-ui article,.swagger-ui aside,.swagger-ui footer,.swagger-ui header,.swagger-ui nav,.swagger-ui section{display:block}.swagger-ui h1{font-size:2em;margin:.67em 0}.swagger-ui figcaption,.swagger-ui figure,.swagger-ui main{display:block}.swagger-ui figure{margin:1em 40px}.swagger-ui hr{box-sizing:content-box;height:0;overflow:visible}.swagger-ui pre{font-family:monospace,monospace;font-size:1em}.swagger-ui a{background-color:transparent;-webkit-text-decoration-skip:objects}.swagger-ui abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.swagger-ui b,.swagger-ui strong{font-weight:inherit;font-weight:bolder}.swagger-ui code,.swagger-ui kbd,.swagger-ui samp{font-family:monospace,monospace;font-size:1em}.swagger-ui dfn{font-style:italic}.swagger-ui mark{background-color:#ff0;color:#000}.swagger-ui small{font-size:80%}.swagger-ui sub,.swagger-ui sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.swagger-ui sub{bottom:-.25em}.swagger-ui sup{top:-.5em}.swagger-ui audio,.swagger-ui video{display:inline-block}.swagger-ui audio:not([controls]){display:none;height:0}.swagger-ui img{border-style:none}.swagger-ui svg:not(:root){overflow:hidden}.swagger-ui button,.swagger-ui input,.swagger-ui optgroup,.swagger-ui select,.swagger-ui textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}.swagger-ui button,.swagger-ui input{overflow:visible}.swagger-ui button,.swagger-ui select{text-transform:none}.swagger-ui [type=reset],.swagger-ui [type=submit],.swagger-ui button,.swagger-ui html [type=button]{-webkit-appearance:button}.swagger-ui [type=button]::-moz-focus-inner,.swagger-ui [type=reset]::-moz-focus-inner,.swagger-ui [type=submit]::-moz-focus-inner,.swagger-ui button::-moz-focus-inner{border-style:none;padding:0}.swagger-ui [type=button]:-moz-focusring,.swagger-ui [type=reset]:-moz-focusring,.swagger-ui [type=submit]:-moz-focusring,.swagger-ui button:-moz-focusring{outline:1px dotted ButtonText}.swagger-ui fieldset{padding:.35em .75em .625em}.swagger-ui legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}.swagger-ui progress{display:inline-block;vertical-align:baseline}.swagger-ui textarea{overflow:auto}.swagger-ui [type=checkbox],.swagger-ui [type=radio]{box-sizing:border-box;padding:0}.swagger-ui [type=number]::-webkit-inner-spin-button,.swagger-ui [type=number]::-webkit-outer-spin-button{height:auto}.swagger-ui [type=search]{-webkit-appearance:textfield;outline-offset:-2px}.swagger-ui [type=search]::-webkit-search-cancel-button,.swagger-ui [type=search]::-webkit-search-decoration{-webkit-appearance:none}.swagger-ui ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.swagger-ui details,.swagger-ui menu{display:block}.swagger-ui summary{display:list-item}.swagger-ui canvas{display:inline-block}.swagger-ui template{display:none}.swagger-ui [hidden]{display:none}.swagger-ui .debug *{outline:1px solid gold}.swagger-ui .debug-white *{outline:1px solid #fff}.swagger-ui .debug-black *{outline:1px solid #000}.swagger-ui .debug-grid{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) repeat 0 0}.swagger-ui .debug-grid-16{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC) repeat 0 0}.swagger-ui .debug-grid-8-solid{background:#fff url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z) repeat 0 0}.swagger-ui .debug-grid-16-solid{background:#fff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) repeat 0 0}.swagger-ui .border-box,.swagger-ui a,.swagger-ui article,.swagger-ui body,.swagger-ui code,.swagger-ui dd,.swagger-ui div,.swagger-ui dl,.swagger-ui dt,.swagger-ui fieldset,.swagger-ui footer,.swagger-ui form,.swagger-ui h1,.swagger-ui h2,.swagger-ui h3,.swagger-ui h4,.swagger-ui h5,.swagger-ui h6,.swagger-ui header,.swagger-ui html,.swagger-ui input[type=email],.swagger-ui input[type=number],.swagger-ui input[type=password],.swagger-ui input[type=tel],.swagger-ui input[type=text],.swagger-ui input[type=url],.swagger-ui legend,.swagger-ui li,.swagger-ui main,.swagger-ui ol,.swagger-ui p,.swagger-ui pre,.swagger-ui section,.swagger-ui table,.swagger-ui td,.swagger-ui textarea,.swagger-ui th,.swagger-ui tr,.swagger-ui ul{box-sizing:border-box}.swagger-ui .aspect-ratio{height:0;position:relative}.swagger-ui .aspect-ratio--16x9{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1{padding-bottom:100%}.swagger-ui .aspect-ratio--object{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}@media screen and (min-width:30em){.swagger-ui .aspect-ratio-ns{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-ns{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-ns{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-ns{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-ns{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-ns{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-ns{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-ns{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-ns{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-ns{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-ns{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-ns{padding-bottom:100%}.swagger-ui .aspect-ratio--object-ns{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .aspect-ratio-m{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-m{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-m{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-m{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-m{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-m{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-m{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-m{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-m{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-m{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-m{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-m{padding-bottom:100%}.swagger-ui .aspect-ratio--object-m{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}}@media screen and (min-width:60em){.swagger-ui .aspect-ratio-l{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-l{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-l{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-l{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-l{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-l{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-l{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-l{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-l{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-l{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-l{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-l{padding-bottom:100%}.swagger-ui .aspect-ratio--object-l{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:100}}.swagger-ui img{max-width:100%}.swagger-ui .cover{background-size:cover!important}.swagger-ui .contain{background-size:contain!important}@media screen and (min-width:30em){.swagger-ui .cover-ns{background-size:cover!important}.swagger-ui .contain-ns{background-size:contain!important}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .cover-m{background-size:cover!important}.swagger-ui .contain-m{background-size:contain!important}}@media screen and (min-width:60em){.swagger-ui .cover-l{background-size:cover!important}.swagger-ui .contain-l{background-size:contain!important}}.swagger-ui .bg-center{background-repeat:no-repeat;background-position:50%}.swagger-ui .bg-top{background-repeat:no-repeat;background-position:top}.swagger-ui .bg-right{background-repeat:no-repeat;background-position:100%}.swagger-ui .bg-bottom{background-repeat:no-repeat;background-position:bottom}.swagger-ui .bg-left{background-repeat:no-repeat;background-position:0}@media screen and (min-width:30em){.swagger-ui .bg-center-ns{background-repeat:no-repeat;background-position:50%}.swagger-ui .bg-top-ns{background-repeat:no-repeat;background-position:top}.swagger-ui .bg-right-ns{background-repeat:no-repeat;background-position:100%}.swagger-ui .bg-bottom-ns{background-repeat:no-repeat;background-position:bottom}.swagger-ui .bg-left-ns{background-repeat:no-repeat;background-position:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .bg-center-m{background-repeat:no-repeat;background-position:50%}.swagger-ui .bg-top-m{background-repeat:no-repeat;background-position:top}.swagger-ui .bg-right-m{background-repeat:no-repeat;background-position:100%}.swagger-ui .bg-bottom-m{background-repeat:no-repeat;background-position:bottom}.swagger-ui .bg-left-m{background-repeat:no-repeat;background-position:0}}@media screen and (min-width:60em){.swagger-ui .bg-center-l{background-repeat:no-repeat;background-position:50%}.swagger-ui .bg-top-l{background-repeat:no-repeat;background-position:top}.swagger-ui .bg-right-l{background-repeat:no-repeat;background-position:100%}.swagger-ui .bg-bottom-l{background-repeat:no-repeat;background-position:bottom}.swagger-ui .bg-left-l{background-repeat:no-repeat;background-position:0}}.swagger-ui .outline{outline:1px solid}.swagger-ui .outline-transparent{outline:1px solid transparent}.swagger-ui .outline-0{outline:0}@media screen and (min-width:30em){.swagger-ui .outline-ns{outline:1px solid}.swagger-ui .outline-transparent-ns{outline:1px solid transparent}.swagger-ui .outline-0-ns{outline:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .outline-m{outline:1px solid}.swagger-ui .outline-transparent-m{outline:1px solid transparent}.swagger-ui .outline-0-m{outline:0}}@media screen and (min-width:60em){.swagger-ui .outline-l{outline:1px solid}.swagger-ui .outline-transparent-l{outline:1px solid transparent}.swagger-ui .outline-0-l{outline:0}}.swagger-ui .ba{border-style:solid;border-width:1px}.swagger-ui .bt{border-top-style:solid;border-top-width:1px}.swagger-ui .br{border-right-style:solid;border-right-width:1px}.swagger-ui .bb{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl{border-left-style:solid;border-left-width:1px}.swagger-ui .bn{border-style:none;border-width:0}@media screen and (min-width:30em){.swagger-ui .ba-ns{border-style:solid;border-width:1px}.swagger-ui .bt-ns{border-top-style:solid;border-top-width:1px}.swagger-ui .br-ns{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-ns{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-ns{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-ns{border-style:none;border-width:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ba-m{border-style:solid;border-width:1px}.swagger-ui .bt-m{border-top-style:solid;border-top-width:1px}.swagger-ui .br-m{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-m{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-m{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-m{border-style:none;border-width:0}}@media screen and (min-width:60em){.swagger-ui .ba-l{border-style:solid;border-width:1px}.swagger-ui .bt-l{border-top-style:solid;border-top-width:1px}.swagger-ui .br-l{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-l{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-l{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-l{border-style:none;border-width:0}}.swagger-ui .b--black{border-color:#000}.swagger-ui .b--near-black{border-color:#111}.swagger-ui .b--dark-gray{border-color:#333}.swagger-ui .b--mid-gray{border-color:#555}.swagger-ui .b--gray{border-color:#777}.swagger-ui .b--silver{border-color:#999}.swagger-ui .b--light-silver{border-color:#aaa}.swagger-ui .b--moon-gray{border-color:#ccc}.swagger-ui .b--light-gray{border-color:#eee}.swagger-ui .b--near-white{border-color:#f4f4f4}.swagger-ui .b--white{border-color:#fff}.swagger-ui .b--white-90{border-color:hsla(0,0%,100%,.9)}.swagger-ui .b--white-80{border-color:hsla(0,0%,100%,.8)}.swagger-ui .b--white-70{border-color:hsla(0,0%,100%,.7)}.swagger-ui .b--white-60{border-color:hsla(0,0%,100%,.6)}.swagger-ui .b--white-50{border-color:hsla(0,0%,100%,.5)}.swagger-ui .b--white-40{border-color:hsla(0,0%,100%,.4)}.swagger-ui .b--white-30{border-color:hsla(0,0%,100%,.3)}.swagger-ui .b--white-20{border-color:hsla(0,0%,100%,.2)}.swagger-ui .b--white-10{border-color:hsla(0,0%,100%,.1)}.swagger-ui .b--white-05{border-color:hsla(0,0%,100%,.05)}.swagger-ui .b--white-025{border-color:hsla(0,0%,100%,.025)}.swagger-ui .b--white-0125{border-color:hsla(0,0%,100%,.0125)}.swagger-ui .b--black-90{border-color:rgba(0,0,0,.9)}.swagger-ui .b--black-80{border-color:rgba(0,0,0,.8)}.swagger-ui .b--black-70{border-color:rgba(0,0,0,.7)}.swagger-ui .b--black-60{border-color:rgba(0,0,0,.6)}.swagger-ui .b--black-50{border-color:rgba(0,0,0,.5)}.swagger-ui .b--black-40{border-color:rgba(0,0,0,.4)}.swagger-ui .b--black-30{border-color:rgba(0,0,0,.3)}.swagger-ui .b--black-20{border-color:rgba(0,0,0,.2)}.swagger-ui .b--black-10{border-color:rgba(0,0,0,.1)}.swagger-ui .b--black-05{border-color:rgba(0,0,0,.05)}.swagger-ui .b--black-025{border-color:rgba(0,0,0,.025)}.swagger-ui .b--black-0125{border-color:rgba(0,0,0,.0125)}.swagger-ui .b--dark-red{border-color:#e7040f}.swagger-ui .b--red{border-color:#ff4136}.swagger-ui .b--light-red{border-color:#ff725c}.swagger-ui .b--orange{border-color:#ff6300}.swagger-ui .b--gold{border-color:#ffb700}.swagger-ui .b--yellow{border-color:gold}.swagger-ui .b--light-yellow{border-color:#fbf1a9}.swagger-ui .b--purple{border-color:#5e2ca5}.swagger-ui .b--light-purple{border-color:#a463f2}.swagger-ui .b--dark-pink{border-color:#d5008f}.swagger-ui .b--hot-pink{border-color:#ff41b4}.swagger-ui .b--pink{border-color:#ff80cc}.swagger-ui .b--light-pink{border-color:#ffa3d7}.swagger-ui .b--dark-green{border-color:#137752}.swagger-ui .b--green{border-color:#19a974}.swagger-ui .b--light-green{border-color:#9eebcf}.swagger-ui .b--navy{border-color:#001b44}.swagger-ui .b--dark-blue{border-color:#00449e}.swagger-ui .b--blue{border-color:#357edd}.swagger-ui .b--light-blue{border-color:#96ccff}.swagger-ui .b--lightest-blue{border-color:#cdecff}.swagger-ui .b--washed-blue{border-color:#f6fffe}.swagger-ui .b--washed-green{border-color:#e8fdf5}.swagger-ui .b--washed-yellow{border-color:#fffceb}.swagger-ui .b--washed-red{border-color:#ffdfdf}.swagger-ui .b--transparent{border-color:transparent}.swagger-ui .b--inherit{border-color:inherit}.swagger-ui .br0{border-radius:0}.swagger-ui .br1{border-radius:.125rem}.swagger-ui .br2{border-radius:.25rem}.swagger-ui .br3{border-radius:.5rem}.swagger-ui .br4{border-radius:1rem}.swagger-ui .br-100{border-radius:100%}.swagger-ui .br-pill{border-radius:9999px}.swagger-ui .br--bottom{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right{border-top-left-radius:0;border-bottom-left-radius:0}.swagger-ui .br--left{border-top-right-radius:0;border-bottom-right-radius:0}@media screen and (min-width:30em){.swagger-ui .br0-ns{border-radius:0}.swagger-ui .br1-ns{border-radius:.125rem}.swagger-ui .br2-ns{border-radius:.25rem}.swagger-ui .br3-ns{border-radius:.5rem}.swagger-ui .br4-ns{border-radius:1rem}.swagger-ui .br-100-ns{border-radius:100%}.swagger-ui .br-pill-ns{border-radius:9999px}.swagger-ui .br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-ns{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-ns{border-top-left-radius:0;border-bottom-left-radius:0}.swagger-ui .br--left-ns{border-top-right-radius:0;border-bottom-right-radius:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .br0-m{border-radius:0}.swagger-ui .br1-m{border-radius:.125rem}.swagger-ui .br2-m{border-radius:.25rem}.swagger-ui .br3-m{border-radius:.5rem}.swagger-ui .br4-m{border-radius:1rem}.swagger-ui .br-100-m{border-radius:100%}.swagger-ui .br-pill-m{border-radius:9999px}.swagger-ui .br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-m{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-m{border-top-left-radius:0;border-bottom-left-radius:0}.swagger-ui .br--left-m{border-top-right-radius:0;border-bottom-right-radius:0}}@media screen and (min-width:60em){.swagger-ui .br0-l{border-radius:0}.swagger-ui .br1-l{border-radius:.125rem}.swagger-ui .br2-l{border-radius:.25rem}.swagger-ui .br3-l{border-radius:.5rem}.swagger-ui .br4-l{border-radius:1rem}.swagger-ui .br-100-l{border-radius:100%}.swagger-ui .br-pill-l{border-radius:9999px}.swagger-ui .br--bottom-l{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-l{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-l{border-top-left-radius:0;border-bottom-left-radius:0}.swagger-ui .br--left-l{border-top-right-radius:0;border-bottom-right-radius:0}}.swagger-ui .b--dotted{border-style:dotted}.swagger-ui .b--dashed{border-style:dashed}.swagger-ui .b--solid{border-style:solid}.swagger-ui .b--none{border-style:none}@media screen and (min-width:30em){.swagger-ui .b--dotted-ns{border-style:dotted}.swagger-ui .b--dashed-ns{border-style:dashed}.swagger-ui .b--solid-ns{border-style:solid}.swagger-ui .b--none-ns{border-style:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .b--dotted-m{border-style:dotted}.swagger-ui .b--dashed-m{border-style:dashed}.swagger-ui .b--solid-m{border-style:solid}.swagger-ui .b--none-m{border-style:none}}@media screen and (min-width:60em){.swagger-ui .b--dotted-l{border-style:dotted}.swagger-ui .b--dashed-l{border-style:dashed}.swagger-ui .b--solid-l{border-style:solid}.swagger-ui .b--none-l{border-style:none}}.swagger-ui .bw0{border-width:0}.swagger-ui .bw1{border-width:.125rem}.swagger-ui .bw2{border-width:.25rem}.swagger-ui .bw3{border-width:.5rem}.swagger-ui .bw4{border-width:1rem}.swagger-ui .bw5{border-width:2rem}.swagger-ui .bt-0{border-top-width:0}.swagger-ui .br-0{border-right-width:0}.swagger-ui .bb-0{border-bottom-width:0}.swagger-ui .bl-0{border-left-width:0}@media screen and (min-width:30em){.swagger-ui .bw0-ns{border-width:0}.swagger-ui .bw1-ns{border-width:.125rem}.swagger-ui .bw2-ns{border-width:.25rem}.swagger-ui .bw3-ns{border-width:.5rem}.swagger-ui .bw4-ns{border-width:1rem}.swagger-ui .bw5-ns{border-width:2rem}.swagger-ui .bt-0-ns{border-top-width:0}.swagger-ui .br-0-ns{border-right-width:0}.swagger-ui .bb-0-ns{border-bottom-width:0}.swagger-ui .bl-0-ns{border-left-width:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .bw0-m{border-width:0}.swagger-ui .bw1-m{border-width:.125rem}.swagger-ui .bw2-m{border-width:.25rem}.swagger-ui .bw3-m{border-width:.5rem}.swagger-ui .bw4-m{border-width:1rem}.swagger-ui .bw5-m{border-width:2rem}.swagger-ui .bt-0-m{border-top-width:0}.swagger-ui .br-0-m{border-right-width:0}.swagger-ui .bb-0-m{border-bottom-width:0}.swagger-ui .bl-0-m{border-left-width:0}}@media screen and (min-width:60em){.swagger-ui .bw0-l{border-width:0}.swagger-ui .bw1-l{border-width:.125rem}.swagger-ui .bw2-l{border-width:.25rem}.swagger-ui .bw3-l{border-width:.5rem}.swagger-ui .bw4-l{border-width:1rem}.swagger-ui .bw5-l{border-width:2rem}.swagger-ui .bt-0-l{border-top-width:0}.swagger-ui .br-0-l{border-right-width:0}.swagger-ui .bb-0-l{border-bottom-width:0}.swagger-ui .bl-0-l{border-left-width:0}}.swagger-ui .shadow-1{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}@media screen and (min-width:30em){.swagger-ui .shadow-1-ns{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-ns{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-ns{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-ns{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-ns{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .shadow-1-m{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-m{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-m{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-m{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-m{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:60em){.swagger-ui .shadow-1-l{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-l{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-l{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-l{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-l{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}.swagger-ui .pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}.swagger-ui .top-0{top:0}.swagger-ui .right-0{right:0}.swagger-ui .bottom-0{bottom:0}.swagger-ui .left-0{left:0}.swagger-ui .top-1{top:1rem}.swagger-ui .right-1{right:1rem}.swagger-ui .bottom-1{bottom:1rem}.swagger-ui .left-1{left:1rem}.swagger-ui .top-2{top:2rem}.swagger-ui .right-2{right:2rem}.swagger-ui .bottom-2{bottom:2rem}.swagger-ui .left-2{left:2rem}.swagger-ui .top--1{top:-1rem}.swagger-ui .right--1{right:-1rem}.swagger-ui .bottom--1{bottom:-1rem}.swagger-ui .left--1{left:-1rem}.swagger-ui .top--2{top:-2rem}.swagger-ui .right--2{right:-2rem}.swagger-ui .bottom--2{bottom:-2rem}.swagger-ui .left--2{left:-2rem}.swagger-ui .absolute--fill{top:0;right:0;bottom:0;left:0}@media screen and (min-width:30em){.swagger-ui .top-0-ns{top:0}.swagger-ui .left-0-ns{left:0}.swagger-ui .right-0-ns{right:0}.swagger-ui .bottom-0-ns{bottom:0}.swagger-ui .top-1-ns{top:1rem}.swagger-ui .left-1-ns{left:1rem}.swagger-ui .right-1-ns{right:1rem}.swagger-ui .bottom-1-ns{bottom:1rem}.swagger-ui .top-2-ns{top:2rem}.swagger-ui .left-2-ns{left:2rem}.swagger-ui .right-2-ns{right:2rem}.swagger-ui .bottom-2-ns{bottom:2rem}.swagger-ui .top--1-ns{top:-1rem}.swagger-ui .right--1-ns{right:-1rem}.swagger-ui .bottom--1-ns{bottom:-1rem}.swagger-ui .left--1-ns{left:-1rem}.swagger-ui .top--2-ns{top:-2rem}.swagger-ui .right--2-ns{right:-2rem}.swagger-ui .bottom--2-ns{bottom:-2rem}.swagger-ui .left--2-ns{left:-2rem}.swagger-ui .absolute--fill-ns{top:0;right:0;bottom:0;left:0}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .top-0-m{top:0}.swagger-ui .left-0-m{left:0}.swagger-ui .right-0-m{right:0}.swagger-ui .bottom-0-m{bottom:0}.swagger-ui .top-1-m{top:1rem}.swagger-ui .left-1-m{left:1rem}.swagger-ui .right-1-m{right:1rem}.swagger-ui .bottom-1-m{bottom:1rem}.swagger-ui .top-2-m{top:2rem}.swagger-ui .left-2-m{left:2rem}.swagger-ui .right-2-m{right:2rem}.swagger-ui .bottom-2-m{bottom:2rem}.swagger-ui .top--1-m{top:-1rem}.swagger-ui .right--1-m{right:-1rem}.swagger-ui .bottom--1-m{bottom:-1rem}.swagger-ui .left--1-m{left:-1rem}.swagger-ui .top--2-m{top:-2rem}.swagger-ui .right--2-m{right:-2rem}.swagger-ui .bottom--2-m{bottom:-2rem}.swagger-ui .left--2-m{left:-2rem}.swagger-ui .absolute--fill-m{top:0;right:0;bottom:0;left:0}}@media screen and (min-width:60em){.swagger-ui .top-0-l{top:0}.swagger-ui .left-0-l{left:0}.swagger-ui .right-0-l{right:0}.swagger-ui .bottom-0-l{bottom:0}.swagger-ui .top-1-l{top:1rem}.swagger-ui .left-1-l{left:1rem}.swagger-ui .right-1-l{right:1rem}.swagger-ui .bottom-1-l{bottom:1rem}.swagger-ui .top-2-l{top:2rem}.swagger-ui .left-2-l{left:2rem}.swagger-ui .right-2-l{right:2rem}.swagger-ui .bottom-2-l{bottom:2rem}.swagger-ui .top--1-l{top:-1rem}.swagger-ui .right--1-l{right:-1rem}.swagger-ui .bottom--1-l{bottom:-1rem}.swagger-ui .left--1-l{left:-1rem}.swagger-ui .top--2-l{top:-2rem}.swagger-ui .right--2-l{right:-2rem}.swagger-ui .bottom--2-l{bottom:-2rem}.swagger-ui .left--2-l{left:-2rem}.swagger-ui .absolute--fill-l{top:0;right:0;bottom:0;left:0}}.swagger-ui .cf:after,.swagger-ui .cf:before{content:" ";display:table}.swagger-ui .cf:after{clear:both}.swagger-ui .cf{*zoom:1}.swagger-ui .cl{clear:left}.swagger-ui .cr{clear:right}.swagger-ui .cb{clear:both}.swagger-ui .cn{clear:none}@media screen and (min-width:30em){.swagger-ui .cl-ns{clear:left}.swagger-ui .cr-ns{clear:right}.swagger-ui .cb-ns{clear:both}.swagger-ui .cn-ns{clear:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .cl-m{clear:left}.swagger-ui .cr-m{clear:right}.swagger-ui .cb-m{clear:both}.swagger-ui .cn-m{clear:none}}@media screen and (min-width:60em){.swagger-ui .cl-l{clear:left}.swagger-ui .cr-l{clear:right}.swagger-ui .cb-l{clear:both}.swagger-ui .cn-l{clear:none}}.swagger-ui .flex{display:flex}.swagger-ui .inline-flex{display:inline-flex}.swagger-ui .flex-auto{flex:1 1 auto;min-width:0;min-height:0}.swagger-ui .flex-none{flex:none}.swagger-ui .flex-column{flex-direction:column}.swagger-ui .flex-row{flex-direction:row}.swagger-ui .flex-wrap{flex-wrap:wrap}.swagger-ui .flex-nowrap{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse{flex-direction:column-reverse}.swagger-ui .flex-row-reverse{flex-direction:row-reverse}.swagger-ui .items-start{align-items:flex-start}.swagger-ui .items-end{align-items:flex-end}.swagger-ui .items-center{align-items:center}.swagger-ui .items-baseline{align-items:baseline}.swagger-ui .items-stretch{align-items:stretch}.swagger-ui .self-start{align-self:flex-start}.swagger-ui .self-end{align-self:flex-end}.swagger-ui .self-center{align-self:center}.swagger-ui .self-baseline{align-self:baseline}.swagger-ui .self-stretch{align-self:stretch}.swagger-ui .justify-start{justify-content:flex-start}.swagger-ui .justify-end{justify-content:flex-end}.swagger-ui .justify-center{justify-content:center}.swagger-ui .justify-between{justify-content:space-between}.swagger-ui .justify-around{justify-content:space-around}.swagger-ui .content-start{align-content:flex-start}.swagger-ui .content-end{align-content:flex-end}.swagger-ui .content-center{align-content:center}.swagger-ui .content-between{align-content:space-between}.swagger-ui .content-around{align-content:space-around}.swagger-ui .content-stretch{align-content:stretch}.swagger-ui .order-0{order:0}.swagger-ui .order-1{order:1}.swagger-ui .order-2{order:2}.swagger-ui .order-3{order:3}.swagger-ui .order-4{order:4}.swagger-ui .order-5{order:5}.swagger-ui .order-6{order:6}.swagger-ui .order-7{order:7}.swagger-ui .order-8{order:8}.swagger-ui .order-last{order:99999}.swagger-ui .flex-grow-0{flex-grow:0}.swagger-ui .flex-grow-1{flex-grow:1}.swagger-ui .flex-shrink-0{flex-shrink:0}.swagger-ui .flex-shrink-1{flex-shrink:1}@media screen and (min-width:30em){.swagger-ui .flex-ns{display:flex}.swagger-ui .inline-flex-ns{display:inline-flex}.swagger-ui .flex-auto-ns{flex:1 1 auto;min-width:0;min-height:0}.swagger-ui .flex-none-ns{flex:none}.swagger-ui .flex-column-ns{flex-direction:column}.swagger-ui .flex-row-ns{flex-direction:row}.swagger-ui .flex-wrap-ns{flex-wrap:wrap}.swagger-ui .flex-nowrap-ns{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-ns{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-ns{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-ns{flex-direction:row-reverse}.swagger-ui .items-start-ns{align-items:flex-start}.swagger-ui .items-end-ns{align-items:flex-end}.swagger-ui .items-center-ns{align-items:center}.swagger-ui .items-baseline-ns{align-items:baseline}.swagger-ui .items-stretch-ns{align-items:stretch}.swagger-ui .self-start-ns{align-self:flex-start}.swagger-ui .self-end-ns{align-self:flex-end}.swagger-ui .self-center-ns{align-self:center}.swagger-ui .self-baseline-ns{align-self:baseline}.swagger-ui .self-stretch-ns{align-self:stretch}.swagger-ui .justify-start-ns{justify-content:flex-start}.swagger-ui .justify-end-ns{justify-content:flex-end}.swagger-ui .justify-center-ns{justify-content:center}.swagger-ui .justify-between-ns{justify-content:space-between}.swagger-ui .justify-around-ns{justify-content:space-around}.swagger-ui .content-start-ns{align-content:flex-start}.swagger-ui .content-end-ns{align-content:flex-end}.swagger-ui .content-center-ns{align-content:center}.swagger-ui .content-between-ns{align-content:space-between}.swagger-ui .content-around-ns{align-content:space-around}.swagger-ui .content-stretch-ns{align-content:stretch}.swagger-ui .order-0-ns{order:0}.swagger-ui .order-1-ns{order:1}.swagger-ui .order-2-ns{order:2}.swagger-ui .order-3-ns{order:3}.swagger-ui .order-4-ns{order:4}.swagger-ui .order-5-ns{order:5}.swagger-ui .order-6-ns{order:6}.swagger-ui .order-7-ns{order:7}.swagger-ui .order-8-ns{order:8}.swagger-ui .order-last-ns{order:99999}.swagger-ui .flex-grow-0-ns{flex-grow:0}.swagger-ui .flex-grow-1-ns{flex-grow:1}.swagger-ui .flex-shrink-0-ns{flex-shrink:0}.swagger-ui .flex-shrink-1-ns{flex-shrink:1}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .flex-m{display:flex}.swagger-ui .inline-flex-m{display:inline-flex}.swagger-ui .flex-auto-m{flex:1 1 auto;min-width:0;min-height:0}.swagger-ui .flex-none-m{flex:none}.swagger-ui .flex-column-m{flex-direction:column}.swagger-ui .flex-row-m{flex-direction:row}.swagger-ui .flex-wrap-m{flex-wrap:wrap}.swagger-ui .flex-nowrap-m{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-m{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-m{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-m{flex-direction:row-reverse}.swagger-ui .items-start-m{align-items:flex-start}.swagger-ui .items-end-m{align-items:flex-end}.swagger-ui .items-center-m{align-items:center}.swagger-ui .items-baseline-m{align-items:baseline}.swagger-ui .items-stretch-m{align-items:stretch}.swagger-ui .self-start-m{align-self:flex-start}.swagger-ui .self-end-m{align-self:flex-end}.swagger-ui .self-center-m{align-self:center}.swagger-ui .self-baseline-m{align-self:baseline}.swagger-ui .self-stretch-m{align-self:stretch}.swagger-ui .justify-start-m{justify-content:flex-start}.swagger-ui .justify-end-m{justify-content:flex-end}.swagger-ui .justify-center-m{justify-content:center}.swagger-ui .justify-between-m{justify-content:space-between}.swagger-ui .justify-around-m{justify-content:space-around}.swagger-ui .content-start-m{align-content:flex-start}.swagger-ui .content-end-m{align-content:flex-end}.swagger-ui .content-center-m{align-content:center}.swagger-ui .content-between-m{align-content:space-between}.swagger-ui .content-around-m{align-content:space-around}.swagger-ui .content-stretch-m{align-content:stretch}.swagger-ui .order-0-m{order:0}.swagger-ui .order-1-m{order:1}.swagger-ui .order-2-m{order:2}.swagger-ui .order-3-m{order:3}.swagger-ui .order-4-m{order:4}.swagger-ui .order-5-m{order:5}.swagger-ui .order-6-m{order:6}.swagger-ui .order-7-m{order:7}.swagger-ui .order-8-m{order:8}.swagger-ui .order-last-m{order:99999}.swagger-ui .flex-grow-0-m{flex-grow:0}.swagger-ui .flex-grow-1-m{flex-grow:1}.swagger-ui .flex-shrink-0-m{flex-shrink:0}.swagger-ui .flex-shrink-1-m{flex-shrink:1}}@media screen and (min-width:60em){.swagger-ui .flex-l{display:flex}.swagger-ui .inline-flex-l{display:inline-flex}.swagger-ui .flex-auto-l{flex:1 1 auto;min-width:0;min-height:0}.swagger-ui .flex-none-l{flex:none}.swagger-ui .flex-column-l{flex-direction:column}.swagger-ui .flex-row-l{flex-direction:row}.swagger-ui .flex-wrap-l{flex-wrap:wrap}.swagger-ui .flex-nowrap-l{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-l{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-l{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-l{flex-direction:row-reverse}.swagger-ui .items-start-l{align-items:flex-start}.swagger-ui .items-end-l{align-items:flex-end}.swagger-ui .items-center-l{align-items:center}.swagger-ui .items-baseline-l{align-items:baseline}.swagger-ui .items-stretch-l{align-items:stretch}.swagger-ui .self-start-l{align-self:flex-start}.swagger-ui .self-end-l{align-self:flex-end}.swagger-ui .self-center-l{align-self:center}.swagger-ui .self-baseline-l{align-self:baseline}.swagger-ui .self-stretch-l{align-self:stretch}.swagger-ui .justify-start-l{justify-content:flex-start}.swagger-ui .justify-end-l{justify-content:flex-end}.swagger-ui .justify-center-l{justify-content:center}.swagger-ui .justify-between-l{justify-content:space-between}.swagger-ui .justify-around-l{justify-content:space-around}.swagger-ui .content-start-l{align-content:flex-start}.swagger-ui .content-end-l{align-content:flex-end}.swagger-ui .content-center-l{align-content:center}.swagger-ui .content-between-l{align-content:space-between}.swagger-ui .content-around-l{align-content:space-around}.swagger-ui .content-stretch-l{align-content:stretch}.swagger-ui .order-0-l{order:0}.swagger-ui .order-1-l{order:1}.swagger-ui .order-2-l{order:2}.swagger-ui .order-3-l{order:3}.swagger-ui .order-4-l{order:4}.swagger-ui .order-5-l{order:5}.swagger-ui .order-6-l{order:6}.swagger-ui .order-7-l{order:7}.swagger-ui .order-8-l{order:8}.swagger-ui .order-last-l{order:99999}.swagger-ui .flex-grow-0-l{flex-grow:0}.swagger-ui .flex-grow-1-l{flex-grow:1}.swagger-ui .flex-shrink-0-l{flex-shrink:0}.swagger-ui .flex-shrink-1-l{flex-shrink:1}}.swagger-ui .dn{display:none}.swagger-ui .di{display:inline}.swagger-ui .db{display:block}.swagger-ui .dib{display:inline-block}.swagger-ui .dit{display:inline-table}.swagger-ui .dt{display:table}.swagger-ui .dtc{display:table-cell}.swagger-ui .dt-row{display:table-row}.swagger-ui .dt-row-group{display:table-row-group}.swagger-ui .dt-column{display:table-column}.swagger-ui .dt-column-group{display:table-column-group}.swagger-ui .dt--fixed{table-layout:fixed;width:100%}@media screen and (min-width:30em){.swagger-ui .dn-ns{display:none}.swagger-ui .di-ns{display:inline}.swagger-ui .db-ns{display:block}.swagger-ui .dib-ns{display:inline-block}.swagger-ui .dit-ns{display:inline-table}.swagger-ui .dt-ns{display:table}.swagger-ui .dtc-ns{display:table-cell}.swagger-ui .dt-row-ns{display:table-row}.swagger-ui .dt-row-group-ns{display:table-row-group}.swagger-ui .dt-column-ns{display:table-column}.swagger-ui .dt-column-group-ns{display:table-column-group}.swagger-ui .dt--fixed-ns{table-layout:fixed;width:100%}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .dn-m{display:none}.swagger-ui .di-m{display:inline}.swagger-ui .db-m{display:block}.swagger-ui .dib-m{display:inline-block}.swagger-ui .dit-m{display:inline-table}.swagger-ui .dt-m{display:table}.swagger-ui .dtc-m{display:table-cell}.swagger-ui .dt-row-m{display:table-row}.swagger-ui .dt-row-group-m{display:table-row-group}.swagger-ui .dt-column-m{display:table-column}.swagger-ui .dt-column-group-m{display:table-column-group}.swagger-ui .dt--fixed-m{table-layout:fixed;width:100%}}@media screen and (min-width:60em){.swagger-ui .dn-l{display:none}.swagger-ui .di-l{display:inline}.swagger-ui .db-l{display:block}.swagger-ui .dib-l{display:inline-block}.swagger-ui .dit-l{display:inline-table}.swagger-ui .dt-l{display:table}.swagger-ui .dtc-l{display:table-cell}.swagger-ui .dt-row-l{display:table-row}.swagger-ui .dt-row-group-l{display:table-row-group}.swagger-ui .dt-column-l{display:table-column}.swagger-ui .dt-column-group-l{display:table-column-group}.swagger-ui .dt--fixed-l{table-layout:fixed;width:100%}}.swagger-ui .fl{float:left;_display:inline}.swagger-ui .fr{float:right;_display:inline}.swagger-ui .fn{float:none}@media screen and (min-width:30em){.swagger-ui .fl-ns{float:left;_display:inline}.swagger-ui .fr-ns{float:right;_display:inline}.swagger-ui .fn-ns{float:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .fl-m{float:left;_display:inline}.swagger-ui .fr-m{float:right;_display:inline}.swagger-ui .fn-m{float:none}}@media screen and (min-width:60em){.swagger-ui .fl-l{float:left;_display:inline}.swagger-ui .fr-l{float:right;_display:inline}.swagger-ui .fn-l{float:none}}.swagger-ui .sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica,helvetica neue,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.swagger-ui .serif{font-family:georgia,serif}.swagger-ui .system-sans-serif{font-family:sans-serif}.swagger-ui .system-serif{font-family:serif}.swagger-ui .code,.swagger-ui code{font-family:Consolas,monaco,monospace}.swagger-ui .courier{font-family:Courier Next,courier,monospace}.swagger-ui .helvetica{font-family:helvetica neue,helvetica,sans-serif}.swagger-ui .avenir{font-family:avenir next,avenir,sans-serif}.swagger-ui .athelas{font-family:athelas,georgia,serif}.swagger-ui .georgia{font-family:georgia,serif}.swagger-ui .times{font-family:times,serif}.swagger-ui .bodoni{font-family:Bodoni MT,serif}.swagger-ui .calisto{font-family:Calisto MT,serif}.swagger-ui .garamond{font-family:garamond,serif}.swagger-ui .baskerville{font-family:baskerville,serif}.swagger-ui .i{font-style:italic}.swagger-ui .fs-normal{font-style:normal}@media screen and (min-width:30em){.swagger-ui .i-ns{font-style:italic}.swagger-ui .fs-normal-ns{font-style:normal}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .i-m{font-style:italic}.swagger-ui .fs-normal-m{font-style:normal}}@media screen and (min-width:60em){.swagger-ui .i-l{font-style:italic}.swagger-ui .fs-normal-l{font-style:normal}}.swagger-ui .normal{font-weight:400}.swagger-ui .b{font-weight:700}.swagger-ui .fw1{font-weight:100}.swagger-ui .fw2{font-weight:200}.swagger-ui .fw3{font-weight:300}.swagger-ui .fw4{font-weight:400}.swagger-ui .fw5{font-weight:500}.swagger-ui .fw6{font-weight:600}.swagger-ui .fw7{font-weight:700}.swagger-ui .fw8{font-weight:800}.swagger-ui .fw9{font-weight:900}@media screen and (min-width:30em){.swagger-ui .normal-ns{font-weight:400}.swagger-ui .b-ns{font-weight:700}.swagger-ui .fw1-ns{font-weight:100}.swagger-ui .fw2-ns{font-weight:200}.swagger-ui .fw3-ns{font-weight:300}.swagger-ui .fw4-ns{font-weight:400}.swagger-ui .fw5-ns{font-weight:500}.swagger-ui .fw6-ns{font-weight:600}.swagger-ui .fw7-ns{font-weight:700}.swagger-ui .fw8-ns{font-weight:800}.swagger-ui .fw9-ns{font-weight:900}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .normal-m{font-weight:400}.swagger-ui .b-m{font-weight:700}.swagger-ui .fw1-m{font-weight:100}.swagger-ui .fw2-m{font-weight:200}.swagger-ui .fw3-m{font-weight:300}.swagger-ui .fw4-m{font-weight:400}.swagger-ui .fw5-m{font-weight:500}.swagger-ui .fw6-m{font-weight:600}.swagger-ui .fw7-m{font-weight:700}.swagger-ui .fw8-m{font-weight:800}.swagger-ui .fw9-m{font-weight:900}}@media screen and (min-width:60em){.swagger-ui .normal-l{font-weight:400}.swagger-ui .b-l{font-weight:700}.swagger-ui .fw1-l{font-weight:100}.swagger-ui .fw2-l{font-weight:200}.swagger-ui .fw3-l{font-weight:300}.swagger-ui .fw4-l{font-weight:400}.swagger-ui .fw5-l{font-weight:500}.swagger-ui .fw6-l{font-weight:600}.swagger-ui .fw7-l{font-weight:700}.swagger-ui .fw8-l{font-weight:800}.swagger-ui .fw9-l{font-weight:900}}.swagger-ui .input-reset{-webkit-appearance:none;-moz-appearance:none}.swagger-ui .button-reset::-moz-focus-inner,.swagger-ui .input-reset::-moz-focus-inner{border:0;padding:0}.swagger-ui .h1{height:1rem}.swagger-ui .h2{height:2rem}.swagger-ui .h3{height:4rem}.swagger-ui .h4{height:8rem}.swagger-ui .h5{height:16rem}.swagger-ui .h-25{height:25%}.swagger-ui .h-50{height:50%}.swagger-ui .h-75{height:75%}.swagger-ui .h-100{height:100%}.swagger-ui .min-h-100{min-height:100%}.swagger-ui .vh-25{height:25vh}.swagger-ui .vh-50{height:50vh}.swagger-ui .vh-75{height:75vh}.swagger-ui .vh-100{height:100vh}.swagger-ui .min-vh-100{min-height:100vh}.swagger-ui .h-auto{height:auto}.swagger-ui .h-inherit{height:inherit}@media screen and (min-width:30em){.swagger-ui .h1-ns{height:1rem}.swagger-ui .h2-ns{height:2rem}.swagger-ui .h3-ns{height:4rem}.swagger-ui .h4-ns{height:8rem}.swagger-ui .h5-ns{height:16rem}.swagger-ui .h-25-ns{height:25%}.swagger-ui .h-50-ns{height:50%}.swagger-ui .h-75-ns{height:75%}.swagger-ui .h-100-ns{height:100%}.swagger-ui .min-h-100-ns{min-height:100%}.swagger-ui .vh-25-ns{height:25vh}.swagger-ui .vh-50-ns{height:50vh}.swagger-ui .vh-75-ns{height:75vh}.swagger-ui .vh-100-ns{height:100vh}.swagger-ui .min-vh-100-ns{min-height:100vh}.swagger-ui .h-auto-ns{height:auto}.swagger-ui .h-inherit-ns{height:inherit}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .h1-m{height:1rem}.swagger-ui .h2-m{height:2rem}.swagger-ui .h3-m{height:4rem}.swagger-ui .h4-m{height:8rem}.swagger-ui .h5-m{height:16rem}.swagger-ui .h-25-m{height:25%}.swagger-ui .h-50-m{height:50%}.swagger-ui .h-75-m{height:75%}.swagger-ui .h-100-m{height:100%}.swagger-ui .min-h-100-m{min-height:100%}.swagger-ui .vh-25-m{height:25vh}.swagger-ui .vh-50-m{height:50vh}.swagger-ui .vh-75-m{height:75vh}.swagger-ui .vh-100-m{height:100vh}.swagger-ui .min-vh-100-m{min-height:100vh}.swagger-ui .h-auto-m{height:auto}.swagger-ui .h-inherit-m{height:inherit}}@media screen and (min-width:60em){.swagger-ui .h1-l{height:1rem}.swagger-ui .h2-l{height:2rem}.swagger-ui .h3-l{height:4rem}.swagger-ui .h4-l{height:8rem}.swagger-ui .h5-l{height:16rem}.swagger-ui .h-25-l{height:25%}.swagger-ui .h-50-l{height:50%}.swagger-ui .h-75-l{height:75%}.swagger-ui .h-100-l{height:100%}.swagger-ui .min-h-100-l{min-height:100%}.swagger-ui .vh-25-l{height:25vh}.swagger-ui .vh-50-l{height:50vh}.swagger-ui .vh-75-l{height:75vh}.swagger-ui .vh-100-l{height:100vh}.swagger-ui .min-vh-100-l{min-height:100vh}.swagger-ui .h-auto-l{height:auto}.swagger-ui .h-inherit-l{height:inherit}}.swagger-ui .tracked{letter-spacing:.1em}.swagger-ui .tracked-tight{letter-spacing:-.05em}.swagger-ui .tracked-mega{letter-spacing:.25em}@media screen and (min-width:30em){.swagger-ui .tracked-ns{letter-spacing:.1em}.swagger-ui .tracked-tight-ns{letter-spacing:-.05em}.swagger-ui .tracked-mega-ns{letter-spacing:.25em}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .tracked-m{letter-spacing:.1em}.swagger-ui .tracked-tight-m{letter-spacing:-.05em}.swagger-ui .tracked-mega-m{letter-spacing:.25em}}@media screen and (min-width:60em){.swagger-ui .tracked-l{letter-spacing:.1em}.swagger-ui .tracked-tight-l{letter-spacing:-.05em}.swagger-ui .tracked-mega-l{letter-spacing:.25em}}.swagger-ui .lh-solid{line-height:1}.swagger-ui .lh-title{line-height:1.25}.swagger-ui .lh-copy{line-height:1.5}@media screen and (min-width:30em){.swagger-ui .lh-solid-ns{line-height:1}.swagger-ui .lh-title-ns{line-height:1.25}.swagger-ui .lh-copy-ns{line-height:1.5}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .lh-solid-m{line-height:1}.swagger-ui .lh-title-m{line-height:1.25}.swagger-ui .lh-copy-m{line-height:1.5}}@media screen and (min-width:60em){.swagger-ui .lh-solid-l{line-height:1}.swagger-ui .lh-title-l{line-height:1.25}.swagger-ui .lh-copy-l{line-height:1.5}}.swagger-ui .link{text-decoration:none}.swagger-ui .link,.swagger-ui .link:link,.swagger-ui .link:visited{transition:color .15s ease-in}.swagger-ui .link:hover{transition:color .15s ease-in}.swagger-ui .link:active{transition:color .15s ease-in}.swagger-ui .link:focus{transition:color .15s ease-in;outline:1px dotted currentColor}.swagger-ui .list{list-style-type:none}.swagger-ui .mw-100{max-width:100%}.swagger-ui .mw1{max-width:1rem}.swagger-ui .mw2{max-width:2rem}.swagger-ui .mw3{max-width:4rem}.swagger-ui .mw4{max-width:8rem}.swagger-ui .mw5{max-width:16rem}.swagger-ui .mw6{max-width:32rem}.swagger-ui .mw7{max-width:48rem}.swagger-ui .mw8{max-width:64rem}.swagger-ui .mw9{max-width:96rem}.swagger-ui .mw-none{max-width:none}@media screen and (min-width:30em){.swagger-ui .mw-100-ns{max-width:100%}.swagger-ui .mw1-ns{max-width:1rem}.swagger-ui .mw2-ns{max-width:2rem}.swagger-ui .mw3-ns{max-width:4rem}.swagger-ui .mw4-ns{max-width:8rem}.swagger-ui .mw5-ns{max-width:16rem}.swagger-ui .mw6-ns{max-width:32rem}.swagger-ui .mw7-ns{max-width:48rem}.swagger-ui .mw8-ns{max-width:64rem}.swagger-ui .mw9-ns{max-width:96rem}.swagger-ui .mw-none-ns{max-width:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .mw-100-m{max-width:100%}.swagger-ui .mw1-m{max-width:1rem}.swagger-ui .mw2-m{max-width:2rem}.swagger-ui .mw3-m{max-width:4rem}.swagger-ui .mw4-m{max-width:8rem}.swagger-ui .mw5-m{max-width:16rem}.swagger-ui .mw6-m{max-width:32rem}.swagger-ui .mw7-m{max-width:48rem}.swagger-ui .mw8-m{max-width:64rem}.swagger-ui .mw9-m{max-width:96rem}.swagger-ui .mw-none-m{max-width:none}}@media screen and (min-width:60em){.swagger-ui .mw-100-l{max-width:100%}.swagger-ui .mw1-l{max-width:1rem}.swagger-ui .mw2-l{max-width:2rem}.swagger-ui .mw3-l{max-width:4rem}.swagger-ui .mw4-l{max-width:8rem}.swagger-ui .mw5-l{max-width:16rem}.swagger-ui .mw6-l{max-width:32rem}.swagger-ui .mw7-l{max-width:48rem}.swagger-ui .mw8-l{max-width:64rem}.swagger-ui .mw9-l{max-width:96rem}.swagger-ui .mw-none-l{max-width:none}}.swagger-ui .w1{width:1rem}.swagger-ui .w2{width:2rem}.swagger-ui .w3{width:4rem}.swagger-ui .w4{width:8rem}.swagger-ui .w5{width:16rem}.swagger-ui .w-10{width:10%}.swagger-ui .w-20{width:20%}.swagger-ui .w-25{width:25%}.swagger-ui .w-30{width:30%}.swagger-ui .w-33{width:33%}.swagger-ui .w-34{width:34%}.swagger-ui .w-40{width:40%}.swagger-ui .w-50{width:50%}.swagger-ui .w-60{width:60%}.swagger-ui .w-70{width:70%}.swagger-ui .w-75{width:75%}.swagger-ui .w-80{width:80%}.swagger-ui .w-90{width:90%}.swagger-ui .w-100{width:100%}.swagger-ui .w-third{width:33.33333%}.swagger-ui .w-two-thirds{width:66.66667%}.swagger-ui .w-auto{width:auto}@media screen and (min-width:30em){.swagger-ui .w1-ns{width:1rem}.swagger-ui .w2-ns{width:2rem}.swagger-ui .w3-ns{width:4rem}.swagger-ui .w4-ns{width:8rem}.swagger-ui .w5-ns{width:16rem}.swagger-ui .w-10-ns{width:10%}.swagger-ui .w-20-ns{width:20%}.swagger-ui .w-25-ns{width:25%}.swagger-ui .w-30-ns{width:30%}.swagger-ui .w-33-ns{width:33%}.swagger-ui .w-34-ns{width:34%}.swagger-ui .w-40-ns{width:40%}.swagger-ui .w-50-ns{width:50%}.swagger-ui .w-60-ns{width:60%}.swagger-ui .w-70-ns{width:70%}.swagger-ui .w-75-ns{width:75%}.swagger-ui .w-80-ns{width:80%}.swagger-ui .w-90-ns{width:90%}.swagger-ui .w-100-ns{width:100%}.swagger-ui .w-third-ns{width:33.33333%}.swagger-ui .w-two-thirds-ns{width:66.66667%}.swagger-ui .w-auto-ns{width:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .w1-m{width:1rem}.swagger-ui .w2-m{width:2rem}.swagger-ui .w3-m{width:4rem}.swagger-ui .w4-m{width:8rem}.swagger-ui .w5-m{width:16rem}.swagger-ui .w-10-m{width:10%}.swagger-ui .w-20-m{width:20%}.swagger-ui .w-25-m{width:25%}.swagger-ui .w-30-m{width:30%}.swagger-ui .w-33-m{width:33%}.swagger-ui .w-34-m{width:34%}.swagger-ui .w-40-m{width:40%}.swagger-ui .w-50-m{width:50%}.swagger-ui .w-60-m{width:60%}.swagger-ui .w-70-m{width:70%}.swagger-ui .w-75-m{width:75%}.swagger-ui .w-80-m{width:80%}.swagger-ui .w-90-m{width:90%}.swagger-ui .w-100-m{width:100%}.swagger-ui .w-third-m{width:33.33333%}.swagger-ui .w-two-thirds-m{width:66.66667%}.swagger-ui .w-auto-m{width:auto}}@media screen and (min-width:60em){.swagger-ui .w1-l{width:1rem}.swagger-ui .w2-l{width:2rem}.swagger-ui .w3-l{width:4rem}.swagger-ui .w4-l{width:8rem}.swagger-ui .w5-l{width:16rem}.swagger-ui .w-10-l{width:10%}.swagger-ui .w-20-l{width:20%}.swagger-ui .w-25-l{width:25%}.swagger-ui .w-30-l{width:30%}.swagger-ui .w-33-l{width:33%}.swagger-ui .w-34-l{width:34%}.swagger-ui .w-40-l{width:40%}.swagger-ui .w-50-l{width:50%}.swagger-ui .w-60-l{width:60%}.swagger-ui .w-70-l{width:70%}.swagger-ui .w-75-l{width:75%}.swagger-ui .w-80-l{width:80%}.swagger-ui .w-90-l{width:90%}.swagger-ui .w-100-l{width:100%}.swagger-ui .w-third-l{width:33.33333%}.swagger-ui .w-two-thirds-l{width:66.66667%}.swagger-ui .w-auto-l{width:auto}}.swagger-ui .overflow-visible{overflow:visible}.swagger-ui .overflow-hidden{overflow:hidden}.swagger-ui .overflow-scroll{overflow:scroll}.swagger-ui .overflow-auto{overflow:auto}.swagger-ui .overflow-x-visible{overflow-x:visible}.swagger-ui .overflow-x-hidden{overflow-x:hidden}.swagger-ui .overflow-x-scroll{overflow-x:scroll}.swagger-ui .overflow-x-auto{overflow-x:auto}.swagger-ui .overflow-y-visible{overflow-y:visible}.swagger-ui .overflow-y-hidden{overflow-y:hidden}.swagger-ui .overflow-y-scroll{overflow-y:scroll}.swagger-ui .overflow-y-auto{overflow-y:auto}@media screen and (min-width:30em){.swagger-ui .overflow-visible-ns{overflow:visible}.swagger-ui .overflow-hidden-ns{overflow:hidden}.swagger-ui .overflow-scroll-ns{overflow:scroll}.swagger-ui .overflow-auto-ns{overflow:auto}.swagger-ui .overflow-x-visible-ns{overflow-x:visible}.swagger-ui .overflow-x-hidden-ns{overflow-x:hidden}.swagger-ui .overflow-x-scroll-ns{overflow-x:scroll}.swagger-ui .overflow-x-auto-ns{overflow-x:auto}.swagger-ui .overflow-y-visible-ns{overflow-y:visible}.swagger-ui .overflow-y-hidden-ns{overflow-y:hidden}.swagger-ui .overflow-y-scroll-ns{overflow-y:scroll}.swagger-ui .overflow-y-auto-ns{overflow-y:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .overflow-visible-m{overflow:visible}.swagger-ui .overflow-hidden-m{overflow:hidden}.swagger-ui .overflow-scroll-m{overflow:scroll}.swagger-ui .overflow-auto-m{overflow:auto}.swagger-ui .overflow-x-visible-m{overflow-x:visible}.swagger-ui .overflow-x-hidden-m{overflow-x:hidden}.swagger-ui .overflow-x-scroll-m{overflow-x:scroll}.swagger-ui .overflow-x-auto-m{overflow-x:auto}.swagger-ui .overflow-y-visible-m{overflow-y:visible}.swagger-ui .overflow-y-hidden-m{overflow-y:hidden}.swagger-ui .overflow-y-scroll-m{overflow-y:scroll}.swagger-ui .overflow-y-auto-m{overflow-y:auto}}@media screen and (min-width:60em){.swagger-ui .overflow-visible-l{overflow:visible}.swagger-ui .overflow-hidden-l{overflow:hidden}.swagger-ui .overflow-scroll-l{overflow:scroll}.swagger-ui .overflow-auto-l{overflow:auto}.swagger-ui .overflow-x-visible-l{overflow-x:visible}.swagger-ui .overflow-x-hidden-l{overflow-x:hidden}.swagger-ui .overflow-x-scroll-l{overflow-x:scroll}.swagger-ui .overflow-x-auto-l{overflow-x:auto}.swagger-ui .overflow-y-visible-l{overflow-y:visible}.swagger-ui .overflow-y-hidden-l{overflow-y:hidden}.swagger-ui .overflow-y-scroll-l{overflow-y:scroll}.swagger-ui .overflow-y-auto-l{overflow-y:auto}}.swagger-ui .static{position:static}.swagger-ui .relative{position:relative}.swagger-ui .absolute{position:absolute}.swagger-ui .fixed{position:fixed}@media screen and (min-width:30em){.swagger-ui .static-ns{position:static}.swagger-ui .relative-ns{position:relative}.swagger-ui .absolute-ns{position:absolute}.swagger-ui .fixed-ns{position:fixed}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .static-m{position:static}.swagger-ui .relative-m{position:relative}.swagger-ui .absolute-m{position:absolute}.swagger-ui .fixed-m{position:fixed}}@media screen and (min-width:60em){.swagger-ui .static-l{position:static}.swagger-ui .relative-l{position:relative}.swagger-ui .absolute-l{position:absolute}.swagger-ui .fixed-l{position:fixed}}.swagger-ui .o-100{opacity:1}.swagger-ui .o-90{opacity:.9}.swagger-ui .o-80{opacity:.8}.swagger-ui .o-70{opacity:.7}.swagger-ui .o-60{opacity:.6}.swagger-ui .o-50{opacity:.5}.swagger-ui .o-40{opacity:.4}.swagger-ui .o-30{opacity:.3}.swagger-ui .o-20{opacity:.2}.swagger-ui .o-10{opacity:.1}.swagger-ui .o-05{opacity:.05}.swagger-ui .o-025{opacity:.025}.swagger-ui .o-0{opacity:0}.swagger-ui .rotate-45{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swagger-ui .rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui .rotate-135{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.swagger-ui .rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.swagger-ui .rotate-225{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.swagger-ui .rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.swagger-ui .rotate-315{-webkit-transform:rotate(315deg);transform:rotate(315deg)}@media screen and (min-width:30em){.swagger-ui .rotate-45-ns{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swagger-ui .rotate-90-ns{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui .rotate-135-ns{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.swagger-ui .rotate-180-ns{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.swagger-ui .rotate-225-ns{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.swagger-ui .rotate-270-ns{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.swagger-ui .rotate-315-ns{-webkit-transform:rotate(315deg);transform:rotate(315deg)}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .rotate-45-m{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swagger-ui .rotate-90-m{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui .rotate-135-m{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.swagger-ui .rotate-180-m{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.swagger-ui .rotate-225-m{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.swagger-ui .rotate-270-m{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.swagger-ui .rotate-315-m{-webkit-transform:rotate(315deg);transform:rotate(315deg)}}@media screen and (min-width:60em){.swagger-ui .rotate-45-l{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swagger-ui .rotate-90-l{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.swagger-ui .rotate-135-l{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.swagger-ui .rotate-180-l{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.swagger-ui .rotate-225-l{-webkit-transform:rotate(225deg);transform:rotate(225deg)}.swagger-ui .rotate-270-l{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.swagger-ui .rotate-315-l{-webkit-transform:rotate(315deg);transform:rotate(315deg)}}.swagger-ui .black-90{color:rgba(0,0,0,.9)}.swagger-ui .black-80{color:rgba(0,0,0,.8)}.swagger-ui .black-70{color:rgba(0,0,0,.7)}.swagger-ui .black-60{color:rgba(0,0,0,.6)}.swagger-ui .black-50{color:rgba(0,0,0,.5)}.swagger-ui .black-40{color:rgba(0,0,0,.4)}.swagger-ui .black-30{color:rgba(0,0,0,.3)}.swagger-ui .black-20{color:rgba(0,0,0,.2)}.swagger-ui .black-10{color:rgba(0,0,0,.1)}.swagger-ui .black-05{color:rgba(0,0,0,.05)}.swagger-ui .white-90{color:hsla(0,0%,100%,.9)}.swagger-ui .white-80{color:hsla(0,0%,100%,.8)}.swagger-ui .white-70{color:hsla(0,0%,100%,.7)}.swagger-ui .white-60{color:hsla(0,0%,100%,.6)}.swagger-ui .white-50{color:hsla(0,0%,100%,.5)}.swagger-ui .white-40{color:hsla(0,0%,100%,.4)}.swagger-ui .white-30{color:hsla(0,0%,100%,.3)}.swagger-ui .white-20{color:hsla(0,0%,100%,.2)}.swagger-ui .white-10{color:hsla(0,0%,100%,.1)}.swagger-ui .black{color:#000}.swagger-ui .near-black{color:#111}.swagger-ui .dark-gray{color:#333}.swagger-ui .mid-gray{color:#555}.swagger-ui .gray{color:#777}.swagger-ui .silver{color:#999}.swagger-ui .light-silver{color:#aaa}.swagger-ui .moon-gray{color:#ccc}.swagger-ui .light-gray{color:#eee}.swagger-ui .near-white{color:#f4f4f4}.swagger-ui .white{color:#fff}.swagger-ui .dark-red{color:#e7040f}.swagger-ui .red{color:#ff4136}.swagger-ui .light-red{color:#ff725c}.swagger-ui .orange{color:#ff6300}.swagger-ui .gold{color:#ffb700}.swagger-ui .yellow{color:gold}.swagger-ui .light-yellow{color:#fbf1a9}.swagger-ui .purple{color:#5e2ca5}.swagger-ui .light-purple{color:#a463f2}.swagger-ui .dark-pink{color:#d5008f}.swagger-ui .hot-pink{color:#ff41b4}.swagger-ui .pink{color:#ff80cc}.swagger-ui .light-pink{color:#ffa3d7}.swagger-ui .dark-green{color:#137752}.swagger-ui .green{color:#19a974}.swagger-ui .light-green{color:#9eebcf}.swagger-ui .navy{color:#001b44}.swagger-ui .dark-blue{color:#00449e}.swagger-ui .blue{color:#357edd}.swagger-ui .light-blue{color:#96ccff}.swagger-ui .lightest-blue{color:#cdecff}.swagger-ui .washed-blue{color:#f6fffe}.swagger-ui .washed-green{color:#e8fdf5}.swagger-ui .washed-yellow{color:#fffceb}.swagger-ui .washed-red{color:#ffdfdf}.swagger-ui .color-inherit{color:inherit}.swagger-ui .bg-black-90{background-color:rgba(0,0,0,.9)}.swagger-ui .bg-black-80{background-color:rgba(0,0,0,.8)}.swagger-ui .bg-black-70{background-color:rgba(0,0,0,.7)}.swagger-ui .bg-black-60{background-color:rgba(0,0,0,.6)}.swagger-ui .bg-black-50{background-color:rgba(0,0,0,.5)}.swagger-ui .bg-black-40{background-color:rgba(0,0,0,.4)}.swagger-ui .bg-black-30{background-color:rgba(0,0,0,.3)}.swagger-ui .bg-black-20{background-color:rgba(0,0,0,.2)}.swagger-ui .bg-black-10{background-color:rgba(0,0,0,.1)}.swagger-ui .bg-black-05{background-color:rgba(0,0,0,.05)}.swagger-ui .bg-white-90{background-color:hsla(0,0%,100%,.9)}.swagger-ui .bg-white-80{background-color:hsla(0,0%,100%,.8)}.swagger-ui .bg-white-70{background-color:hsla(0,0%,100%,.7)}.swagger-ui .bg-white-60{background-color:hsla(0,0%,100%,.6)}.swagger-ui .bg-white-50{background-color:hsla(0,0%,100%,.5)}.swagger-ui .bg-white-40{background-color:hsla(0,0%,100%,.4)}.swagger-ui .bg-white-30{background-color:hsla(0,0%,100%,.3)}.swagger-ui .bg-white-20{background-color:hsla(0,0%,100%,.2)}.swagger-ui .bg-white-10{background-color:hsla(0,0%,100%,.1)}.swagger-ui .bg-black{background-color:#000}.swagger-ui .bg-near-black{background-color:#111}.swagger-ui .bg-dark-gray{background-color:#333}.swagger-ui .bg-mid-gray{background-color:#555}.swagger-ui .bg-gray{background-color:#777}.swagger-ui .bg-silver{background-color:#999}.swagger-ui .bg-light-silver{background-color:#aaa}.swagger-ui .bg-moon-gray{background-color:#ccc}.swagger-ui .bg-light-gray{background-color:#eee}.swagger-ui .bg-near-white{background-color:#f4f4f4}.swagger-ui .bg-white{background-color:#fff}.swagger-ui .bg-transparent{background-color:transparent}.swagger-ui .bg-dark-red{background-color:#e7040f}.swagger-ui .bg-red{background-color:#ff4136}.swagger-ui .bg-light-red{background-color:#ff725c}.swagger-ui .bg-orange{background-color:#ff6300}.swagger-ui .bg-gold{background-color:#ffb700}.swagger-ui .bg-yellow{background-color:gold}.swagger-ui .bg-light-yellow{background-color:#fbf1a9}.swagger-ui .bg-purple{background-color:#5e2ca5}.swagger-ui .bg-light-purple{background-color:#a463f2}.swagger-ui .bg-dark-pink{background-color:#d5008f}.swagger-ui .bg-hot-pink{background-color:#ff41b4}.swagger-ui .bg-pink{background-color:#ff80cc}.swagger-ui .bg-light-pink{background-color:#ffa3d7}.swagger-ui .bg-dark-green{background-color:#137752}.swagger-ui .bg-green{background-color:#19a974}.swagger-ui .bg-light-green{background-color:#9eebcf}.swagger-ui .bg-navy{background-color:#001b44}.swagger-ui .bg-dark-blue{background-color:#00449e}.swagger-ui .bg-blue{background-color:#357edd}.swagger-ui .bg-light-blue{background-color:#96ccff}.swagger-ui .bg-lightest-blue{background-color:#cdecff}.swagger-ui .bg-washed-blue{background-color:#f6fffe}.swagger-ui .bg-washed-green{background-color:#e8fdf5}.swagger-ui .bg-washed-yellow{background-color:#fffceb}.swagger-ui .bg-washed-red{background-color:#ffdfdf}.swagger-ui .bg-inherit{background-color:inherit}.swagger-ui .hover-black:focus,.swagger-ui .hover-black:hover{color:#000}.swagger-ui .hover-near-black:focus,.swagger-ui .hover-near-black:hover{color:#111}.swagger-ui .hover-dark-gray:focus,.swagger-ui .hover-dark-gray:hover{color:#333}.swagger-ui .hover-mid-gray:focus,.swagger-ui .hover-mid-gray:hover{color:#555}.swagger-ui .hover-gray:focus,.swagger-ui .hover-gray:hover{color:#777}.swagger-ui .hover-silver:focus,.swagger-ui .hover-silver:hover{color:#999}.swagger-ui .hover-light-silver:focus,.swagger-ui .hover-light-silver:hover{color:#aaa}.swagger-ui .hover-moon-gray:focus,.swagger-ui .hover-moon-gray:hover{color:#ccc}.swagger-ui .hover-light-gray:focus,.swagger-ui .hover-light-gray:hover{color:#eee}.swagger-ui .hover-near-white:focus,.swagger-ui .hover-near-white:hover{color:#f4f4f4}.swagger-ui .hover-white:focus,.swagger-ui .hover-white:hover{color:#fff}.swagger-ui .hover-black-90:focus,.swagger-ui .hover-black-90:hover{color:rgba(0,0,0,.9)}.swagger-ui .hover-black-80:focus,.swagger-ui .hover-black-80:hover{color:rgba(0,0,0,.8)}.swagger-ui .hover-black-70:focus,.swagger-ui .hover-black-70:hover{color:rgba(0,0,0,.7)}.swagger-ui .hover-black-60:focus,.swagger-ui .hover-black-60:hover{color:rgba(0,0,0,.6)}.swagger-ui .hover-black-50:focus,.swagger-ui .hover-black-50:hover{color:rgba(0,0,0,.5)}.swagger-ui .hover-black-40:focus,.swagger-ui .hover-black-40:hover{color:rgba(0,0,0,.4)}.swagger-ui .hover-black-30:focus,.swagger-ui .hover-black-30:hover{color:rgba(0,0,0,.3)}.swagger-ui .hover-black-20:focus,.swagger-ui .hover-black-20:hover{color:rgba(0,0,0,.2)}.swagger-ui .hover-black-10:focus,.swagger-ui .hover-black-10:hover{color:rgba(0,0,0,.1)}.swagger-ui .hover-white-90:focus,.swagger-ui .hover-white-90:hover{color:hsla(0,0%,100%,.9)}.swagger-ui .hover-white-80:focus,.swagger-ui .hover-white-80:hover{color:hsla(0,0%,100%,.8)}.swagger-ui .hover-white-70:focus,.swagger-ui .hover-white-70:hover{color:hsla(0,0%,100%,.7)}.swagger-ui .hover-white-60:focus,.swagger-ui .hover-white-60:hover{color:hsla(0,0%,100%,.6)}.swagger-ui .hover-white-50:focus,.swagger-ui .hover-white-50:hover{color:hsla(0,0%,100%,.5)}.swagger-ui .hover-white-40:focus,.swagger-ui .hover-white-40:hover{color:hsla(0,0%,100%,.4)}.swagger-ui .hover-white-30:focus,.swagger-ui .hover-white-30:hover{color:hsla(0,0%,100%,.3)}.swagger-ui .hover-white-20:focus,.swagger-ui .hover-white-20:hover{color:hsla(0,0%,100%,.2)}.swagger-ui .hover-white-10:focus,.swagger-ui .hover-white-10:hover{color:hsla(0,0%,100%,.1)}.swagger-ui .hover-inherit:focus,.swagger-ui .hover-inherit:hover{color:inherit}.swagger-ui .hover-bg-black:focus,.swagger-ui .hover-bg-black:hover{background-color:#000}.swagger-ui .hover-bg-near-black:focus,.swagger-ui .hover-bg-near-black:hover{background-color:#111}.swagger-ui .hover-bg-dark-gray:focus,.swagger-ui .hover-bg-dark-gray:hover{background-color:#333}.swagger-ui .hover-bg-mid-gray:focus,.swagger-ui .hover-bg-mid-gray:hover{background-color:#555}.swagger-ui .hover-bg-gray:focus,.swagger-ui .hover-bg-gray:hover{background-color:#777}.swagger-ui .hover-bg-silver:focus,.swagger-ui .hover-bg-silver:hover{background-color:#999}.swagger-ui .hover-bg-light-silver:focus,.swagger-ui .hover-bg-light-silver:hover{background-color:#aaa}.swagger-ui .hover-bg-moon-gray:focus,.swagger-ui .hover-bg-moon-gray:hover{background-color:#ccc}.swagger-ui .hover-bg-light-gray:focus,.swagger-ui .hover-bg-light-gray:hover{background-color:#eee}.swagger-ui .hover-bg-near-white:focus,.swagger-ui .hover-bg-near-white:hover{background-color:#f4f4f4}.swagger-ui .hover-bg-white:focus,.swagger-ui .hover-bg-white:hover{background-color:#fff}.swagger-ui .hover-bg-transparent:focus,.swagger-ui .hover-bg-transparent:hover{background-color:transparent}.swagger-ui .hover-bg-black-90:focus,.swagger-ui .hover-bg-black-90:hover{background-color:rgba(0,0,0,.9)}.swagger-ui .hover-bg-black-80:focus,.swagger-ui .hover-bg-black-80:hover{background-color:rgba(0,0,0,.8)}.swagger-ui .hover-bg-black-70:focus,.swagger-ui .hover-bg-black-70:hover{background-color:rgba(0,0,0,.7)}.swagger-ui .hover-bg-black-60:focus,.swagger-ui .hover-bg-black-60:hover{background-color:rgba(0,0,0,.6)}.swagger-ui .hover-bg-black-50:focus,.swagger-ui .hover-bg-black-50:hover{background-color:rgba(0,0,0,.5)}.swagger-ui .hover-bg-black-40:focus,.swagger-ui .hover-bg-black-40:hover{background-color:rgba(0,0,0,.4)}.swagger-ui .hover-bg-black-30:focus,.swagger-ui .hover-bg-black-30:hover{background-color:rgba(0,0,0,.3)}.swagger-ui .hover-bg-black-20:focus,.swagger-ui .hover-bg-black-20:hover{background-color:rgba(0,0,0,.2)}.swagger-ui .hover-bg-black-10:focus,.swagger-ui .hover-bg-black-10:hover{background-color:rgba(0,0,0,.1)}.swagger-ui .hover-bg-white-90:focus,.swagger-ui .hover-bg-white-90:hover{background-color:hsla(0,0%,100%,.9)}.swagger-ui .hover-bg-white-80:focus,.swagger-ui .hover-bg-white-80:hover{background-color:hsla(0,0%,100%,.8)}.swagger-ui .hover-bg-white-70:focus,.swagger-ui .hover-bg-white-70:hover{background-color:hsla(0,0%,100%,.7)}.swagger-ui .hover-bg-white-60:focus,.swagger-ui .hover-bg-white-60:hover{background-color:hsla(0,0%,100%,.6)}.swagger-ui .hover-bg-white-50:focus,.swagger-ui .hover-bg-white-50:hover{background-color:hsla(0,0%,100%,.5)}.swagger-ui .hover-bg-white-40:focus,.swagger-ui .hover-bg-white-40:hover{background-color:hsla(0,0%,100%,.4)}.swagger-ui .hover-bg-white-30:focus,.swagger-ui .hover-bg-white-30:hover{background-color:hsla(0,0%,100%,.3)}.swagger-ui .hover-bg-white-20:focus,.swagger-ui .hover-bg-white-20:hover{background-color:hsla(0,0%,100%,.2)}.swagger-ui .hover-bg-white-10:focus,.swagger-ui .hover-bg-white-10:hover{background-color:hsla(0,0%,100%,.1)}.swagger-ui .hover-dark-red:focus,.swagger-ui .hover-dark-red:hover{color:#e7040f}.swagger-ui .hover-red:focus,.swagger-ui .hover-red:hover{color:#ff4136}.swagger-ui .hover-light-red:focus,.swagger-ui .hover-light-red:hover{color:#ff725c}.swagger-ui .hover-orange:focus,.swagger-ui .hover-orange:hover{color:#ff6300}.swagger-ui .hover-gold:focus,.swagger-ui .hover-gold:hover{color:#ffb700}.swagger-ui .hover-yellow:focus,.swagger-ui .hover-yellow:hover{color:gold}.swagger-ui .hover-light-yellow:focus,.swagger-ui .hover-light-yellow:hover{color:#fbf1a9}.swagger-ui .hover-purple:focus,.swagger-ui .hover-purple:hover{color:#5e2ca5}.swagger-ui .hover-light-purple:focus,.swagger-ui .hover-light-purple:hover{color:#a463f2}.swagger-ui .hover-dark-pink:focus,.swagger-ui .hover-dark-pink:hover{color:#d5008f}.swagger-ui .hover-hot-pink:focus,.swagger-ui .hover-hot-pink:hover{color:#ff41b4}.swagger-ui .hover-pink:focus,.swagger-ui .hover-pink:hover{color:#ff80cc}.swagger-ui .hover-light-pink:focus,.swagger-ui .hover-light-pink:hover{color:#ffa3d7}.swagger-ui .hover-dark-green:focus,.swagger-ui .hover-dark-green:hover{color:#137752}.swagger-ui .hover-green:focus,.swagger-ui .hover-green:hover{color:#19a974}.swagger-ui .hover-light-green:focus,.swagger-ui .hover-light-green:hover{color:#9eebcf}.swagger-ui .hover-navy:focus,.swagger-ui .hover-navy:hover{color:#001b44}.swagger-ui .hover-dark-blue:focus,.swagger-ui .hover-dark-blue:hover{color:#00449e}.swagger-ui .hover-blue:focus,.swagger-ui .hover-blue:hover{color:#357edd}.swagger-ui .hover-light-blue:focus,.swagger-ui .hover-light-blue:hover{color:#96ccff}.swagger-ui .hover-lightest-blue:focus,.swagger-ui .hover-lightest-blue:hover{color:#cdecff}.swagger-ui .hover-washed-blue:focus,.swagger-ui .hover-washed-blue:hover{color:#f6fffe}.swagger-ui .hover-washed-green:focus,.swagger-ui .hover-washed-green:hover{color:#e8fdf5}.swagger-ui .hover-washed-yellow:focus,.swagger-ui .hover-washed-yellow:hover{color:#fffceb}.swagger-ui .hover-washed-red:focus,.swagger-ui .hover-washed-red:hover{color:#ffdfdf}.swagger-ui .hover-bg-dark-red:focus,.swagger-ui .hover-bg-dark-red:hover{background-color:#e7040f}.swagger-ui .hover-bg-red:focus,.swagger-ui .hover-bg-red:hover{background-color:#ff4136}.swagger-ui .hover-bg-light-red:focus,.swagger-ui .hover-bg-light-red:hover{background-color:#ff725c}.swagger-ui .hover-bg-orange:focus,.swagger-ui .hover-bg-orange:hover{background-color:#ff6300}.swagger-ui .hover-bg-gold:focus,.swagger-ui .hover-bg-gold:hover{background-color:#ffb700}.swagger-ui .hover-bg-yellow:focus,.swagger-ui .hover-bg-yellow:hover{background-color:gold}.swagger-ui .hover-bg-light-yellow:focus,.swagger-ui .hover-bg-light-yellow:hover{background-color:#fbf1a9}.swagger-ui .hover-bg-purple:focus,.swagger-ui .hover-bg-purple:hover{background-color:#5e2ca5}.swagger-ui .hover-bg-light-purple:focus,.swagger-ui .hover-bg-light-purple:hover{background-color:#a463f2}.swagger-ui .hover-bg-dark-pink:focus,.swagger-ui .hover-bg-dark-pink:hover{background-color:#d5008f}.swagger-ui .hover-bg-hot-pink:focus,.swagger-ui .hover-bg-hot-pink:hover{background-color:#ff41b4}.swagger-ui .hover-bg-pink:focus,.swagger-ui .hover-bg-pink:hover{background-color:#ff80cc}.swagger-ui .hover-bg-light-pink:focus,.swagger-ui .hover-bg-light-pink:hover{background-color:#ffa3d7}.swagger-ui .hover-bg-dark-green:focus,.swagger-ui .hover-bg-dark-green:hover{background-color:#137752}.swagger-ui .hover-bg-green:focus,.swagger-ui .hover-bg-green:hover{background-color:#19a974}.swagger-ui .hover-bg-light-green:focus,.swagger-ui .hover-bg-light-green:hover{background-color:#9eebcf}.swagger-ui .hover-bg-navy:focus,.swagger-ui .hover-bg-navy:hover{background-color:#001b44}.swagger-ui .hover-bg-dark-blue:focus,.swagger-ui .hover-bg-dark-blue:hover{background-color:#00449e}.swagger-ui .hover-bg-blue:focus,.swagger-ui .hover-bg-blue:hover{background-color:#357edd}.swagger-ui .hover-bg-light-blue:focus,.swagger-ui .hover-bg-light-blue:hover{background-color:#96ccff}.swagger-ui .hover-bg-lightest-blue:focus,.swagger-ui .hover-bg-lightest-blue:hover{background-color:#cdecff}.swagger-ui .hover-bg-washed-blue:focus,.swagger-ui .hover-bg-washed-blue:hover{background-color:#f6fffe}.swagger-ui .hover-bg-washed-green:focus,.swagger-ui .hover-bg-washed-green:hover{background-color:#e8fdf5}.swagger-ui .hover-bg-washed-yellow:focus,.swagger-ui .hover-bg-washed-yellow:hover{background-color:#fffceb}.swagger-ui .hover-bg-washed-red:focus,.swagger-ui .hover-bg-washed-red:hover{background-color:#ffdfdf}.swagger-ui .hover-bg-inherit:focus,.swagger-ui .hover-bg-inherit:hover{background-color:inherit}.swagger-ui .pa0{padding:0}.swagger-ui .pa1{padding:.25rem}.swagger-ui .pa2{padding:.5rem}.swagger-ui .pa3{padding:1rem}.swagger-ui .pa4{padding:2rem}.swagger-ui .pa5{padding:4rem}.swagger-ui .pa6{padding:8rem}.swagger-ui .pa7{padding:16rem}.swagger-ui .pl0{padding-left:0}.swagger-ui .pl1{padding-left:.25rem}.swagger-ui .pl2{padding-left:.5rem}.swagger-ui .pl3{padding-left:1rem}.swagger-ui .pl4{padding-left:2rem}.swagger-ui .pl5{padding-left:4rem}.swagger-ui .pl6{padding-left:8rem}.swagger-ui .pl7{padding-left:16rem}.swagger-ui .pr0{padding-right:0}.swagger-ui .pr1{padding-right:.25rem}.swagger-ui .pr2{padding-right:.5rem}.swagger-ui .pr3{padding-right:1rem}.swagger-ui .pr4{padding-right:2rem}.swagger-ui .pr5{padding-right:4rem}.swagger-ui .pr6{padding-right:8rem}.swagger-ui .pr7{padding-right:16rem}.swagger-ui .pb0{padding-bottom:0}.swagger-ui .pb1{padding-bottom:.25rem}.swagger-ui .pb2{padding-bottom:.5rem}.swagger-ui .pb3{padding-bottom:1rem}.swagger-ui .pb4{padding-bottom:2rem}.swagger-ui .pb5{padding-bottom:4rem}.swagger-ui .pb6{padding-bottom:8rem}.swagger-ui .pb7{padding-bottom:16rem}.swagger-ui .pt0{padding-top:0}.swagger-ui .pt1{padding-top:.25rem}.swagger-ui .pt2{padding-top:.5rem}.swagger-ui .pt3{padding-top:1rem}.swagger-ui .pt4{padding-top:2rem}.swagger-ui .pt5{padding-top:4rem}.swagger-ui .pt6{padding-top:8rem}.swagger-ui .pt7{padding-top:16rem}.swagger-ui .pv0{padding-top:0;padding-bottom:0}.swagger-ui .pv1{padding-top:.25rem;padding-bottom:.25rem}.swagger-ui .pv2{padding-top:.5rem;padding-bottom:.5rem}.swagger-ui .pv3{padding-top:1rem;padding-bottom:1rem}.swagger-ui .pv4{padding-top:2rem;padding-bottom:2rem}.swagger-ui .pv5{padding-top:4rem;padding-bottom:4rem}.swagger-ui .pv6{padding-top:8rem;padding-bottom:8rem}.swagger-ui .pv7{padding-top:16rem;padding-bottom:16rem}.swagger-ui .ph0{padding-left:0;padding-right:0}.swagger-ui .ph1{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0{margin:0}.swagger-ui .ma1{margin:.25rem}.swagger-ui .ma2{margin:.5rem}.swagger-ui .ma3{margin:1rem}.swagger-ui .ma4{margin:2rem}.swagger-ui .ma5{margin:4rem}.swagger-ui .ma6{margin:8rem}.swagger-ui .ma7{margin:16rem}.swagger-ui .ml0{margin-left:0}.swagger-ui .ml1{margin-left:.25rem}.swagger-ui .ml2{margin-left:.5rem}.swagger-ui .ml3{margin-left:1rem}.swagger-ui .ml4{margin-left:2rem}.swagger-ui .ml5{margin-left:4rem}.swagger-ui .ml6{margin-left:8rem}.swagger-ui .ml7{margin-left:16rem}.swagger-ui .mr0{margin-right:0}.swagger-ui .mr1{margin-right:.25rem}.swagger-ui .mr2{margin-right:.5rem}.swagger-ui .mr3{margin-right:1rem}.swagger-ui .mr4{margin-right:2rem}.swagger-ui .mr5{margin-right:4rem}.swagger-ui .mr6{margin-right:8rem}.swagger-ui .mr7{margin-right:16rem}.swagger-ui .mb0{margin-bottom:0}.swagger-ui .mb1{margin-bottom:.25rem}.swagger-ui .mb2{margin-bottom:.5rem}.swagger-ui .mb3{margin-bottom:1rem}.swagger-ui .mb4{margin-bottom:2rem}.swagger-ui .mb5{margin-bottom:4rem}.swagger-ui .mb6{margin-bottom:8rem}.swagger-ui .mb7{margin-bottom:16rem}.swagger-ui .mt0{margin-top:0}.swagger-ui .mt1{margin-top:.25rem}.swagger-ui .mt2{margin-top:.5rem}.swagger-ui .mt3{margin-top:1rem}.swagger-ui .mt4{margin-top:2rem}.swagger-ui .mt5{margin-top:4rem}.swagger-ui .mt6{margin-top:8rem}.swagger-ui .mt7{margin-top:16rem}.swagger-ui .mv0{margin-top:0;margin-bottom:0}.swagger-ui .mv1{margin-top:.25rem;margin-bottom:.25rem}.swagger-ui .mv2{margin-top:.5rem;margin-bottom:.5rem}.swagger-ui .mv3{margin-top:1rem;margin-bottom:1rem}.swagger-ui .mv4{margin-top:2rem;margin-bottom:2rem}.swagger-ui .mv5{margin-top:4rem;margin-bottom:4rem}.swagger-ui .mv6{margin-top:8rem;margin-bottom:8rem}.swagger-ui .mv7{margin-top:16rem;margin-bottom:16rem}.swagger-ui .mh0{margin-left:0;margin-right:0}.swagger-ui .mh1{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7{margin-left:16rem;margin-right:16rem}@media screen and (min-width:30em){.swagger-ui .pa0-ns{padding:0}.swagger-ui .pa1-ns{padding:.25rem}.swagger-ui .pa2-ns{padding:.5rem}.swagger-ui .pa3-ns{padding:1rem}.swagger-ui .pa4-ns{padding:2rem}.swagger-ui .pa5-ns{padding:4rem}.swagger-ui .pa6-ns{padding:8rem}.swagger-ui .pa7-ns{padding:16rem}.swagger-ui .pl0-ns{padding-left:0}.swagger-ui .pl1-ns{padding-left:.25rem}.swagger-ui .pl2-ns{padding-left:.5rem}.swagger-ui .pl3-ns{padding-left:1rem}.swagger-ui .pl4-ns{padding-left:2rem}.swagger-ui .pl5-ns{padding-left:4rem}.swagger-ui .pl6-ns{padding-left:8rem}.swagger-ui .pl7-ns{padding-left:16rem}.swagger-ui .pr0-ns{padding-right:0}.swagger-ui .pr1-ns{padding-right:.25rem}.swagger-ui .pr2-ns{padding-right:.5rem}.swagger-ui .pr3-ns{padding-right:1rem}.swagger-ui .pr4-ns{padding-right:2rem}.swagger-ui .pr5-ns{padding-right:4rem}.swagger-ui .pr6-ns{padding-right:8rem}.swagger-ui .pr7-ns{padding-right:16rem}.swagger-ui .pb0-ns{padding-bottom:0}.swagger-ui .pb1-ns{padding-bottom:.25rem}.swagger-ui .pb2-ns{padding-bottom:.5rem}.swagger-ui .pb3-ns{padding-bottom:1rem}.swagger-ui .pb4-ns{padding-bottom:2rem}.swagger-ui .pb5-ns{padding-bottom:4rem}.swagger-ui .pb6-ns{padding-bottom:8rem}.swagger-ui .pb7-ns{padding-bottom:16rem}.swagger-ui .pt0-ns{padding-top:0}.swagger-ui .pt1-ns{padding-top:.25rem}.swagger-ui .pt2-ns{padding-top:.5rem}.swagger-ui .pt3-ns{padding-top:1rem}.swagger-ui .pt4-ns{padding-top:2rem}.swagger-ui .pt5-ns{padding-top:4rem}.swagger-ui .pt6-ns{padding-top:8rem}.swagger-ui .pt7-ns{padding-top:16rem}.swagger-ui .pv0-ns{padding-top:0;padding-bottom:0}.swagger-ui .pv1-ns{padding-top:.25rem;padding-bottom:.25rem}.swagger-ui .pv2-ns{padding-top:.5rem;padding-bottom:.5rem}.swagger-ui .pv3-ns{padding-top:1rem;padding-bottom:1rem}.swagger-ui .pv4-ns{padding-top:2rem;padding-bottom:2rem}.swagger-ui .pv5-ns{padding-top:4rem;padding-bottom:4rem}.swagger-ui .pv6-ns{padding-top:8rem;padding-bottom:8rem}.swagger-ui .pv7-ns{padding-top:16rem;padding-bottom:16rem}.swagger-ui .ph0-ns{padding-left:0;padding-right:0}.swagger-ui .ph1-ns{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-ns{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-ns{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-ns{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-ns{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-ns{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-ns{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-ns{margin:0}.swagger-ui .ma1-ns{margin:.25rem}.swagger-ui .ma2-ns{margin:.5rem}.swagger-ui .ma3-ns{margin:1rem}.swagger-ui .ma4-ns{margin:2rem}.swagger-ui .ma5-ns{margin:4rem}.swagger-ui .ma6-ns{margin:8rem}.swagger-ui .ma7-ns{margin:16rem}.swagger-ui .ml0-ns{margin-left:0}.swagger-ui .ml1-ns{margin-left:.25rem}.swagger-ui .ml2-ns{margin-left:.5rem}.swagger-ui .ml3-ns{margin-left:1rem}.swagger-ui .ml4-ns{margin-left:2rem}.swagger-ui .ml5-ns{margin-left:4rem}.swagger-ui .ml6-ns{margin-left:8rem}.swagger-ui .ml7-ns{margin-left:16rem}.swagger-ui .mr0-ns{margin-right:0}.swagger-ui .mr1-ns{margin-right:.25rem}.swagger-ui .mr2-ns{margin-right:.5rem}.swagger-ui .mr3-ns{margin-right:1rem}.swagger-ui .mr4-ns{margin-right:2rem}.swagger-ui .mr5-ns{margin-right:4rem}.swagger-ui .mr6-ns{margin-right:8rem}.swagger-ui .mr7-ns{margin-right:16rem}.swagger-ui .mb0-ns{margin-bottom:0}.swagger-ui .mb1-ns{margin-bottom:.25rem}.swagger-ui .mb2-ns{margin-bottom:.5rem}.swagger-ui .mb3-ns{margin-bottom:1rem}.swagger-ui .mb4-ns{margin-bottom:2rem}.swagger-ui .mb5-ns{margin-bottom:4rem}.swagger-ui .mb6-ns{margin-bottom:8rem}.swagger-ui .mb7-ns{margin-bottom:16rem}.swagger-ui .mt0-ns{margin-top:0}.swagger-ui .mt1-ns{margin-top:.25rem}.swagger-ui .mt2-ns{margin-top:.5rem}.swagger-ui .mt3-ns{margin-top:1rem}.swagger-ui .mt4-ns{margin-top:2rem}.swagger-ui .mt5-ns{margin-top:4rem}.swagger-ui .mt6-ns{margin-top:8rem}.swagger-ui .mt7-ns{margin-top:16rem}.swagger-ui .mv0-ns{margin-top:0;margin-bottom:0}.swagger-ui .mv1-ns{margin-top:.25rem;margin-bottom:.25rem}.swagger-ui .mv2-ns{margin-top:.5rem;margin-bottom:.5rem}.swagger-ui .mv3-ns{margin-top:1rem;margin-bottom:1rem}.swagger-ui .mv4-ns{margin-top:2rem;margin-bottom:2rem}.swagger-ui .mv5-ns{margin-top:4rem;margin-bottom:4rem}.swagger-ui .mv6-ns{margin-top:8rem;margin-bottom:8rem}.swagger-ui .mv7-ns{margin-top:16rem;margin-bottom:16rem}.swagger-ui .mh0-ns{margin-left:0;margin-right:0}.swagger-ui .mh1-ns{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-ns{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-ns{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-ns{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-ns{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-ns{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-ns{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .pa0-m{padding:0}.swagger-ui .pa1-m{padding:.25rem}.swagger-ui .pa2-m{padding:.5rem}.swagger-ui .pa3-m{padding:1rem}.swagger-ui .pa4-m{padding:2rem}.swagger-ui .pa5-m{padding:4rem}.swagger-ui .pa6-m{padding:8rem}.swagger-ui .pa7-m{padding:16rem}.swagger-ui .pl0-m{padding-left:0}.swagger-ui .pl1-m{padding-left:.25rem}.swagger-ui .pl2-m{padding-left:.5rem}.swagger-ui .pl3-m{padding-left:1rem}.swagger-ui .pl4-m{padding-left:2rem}.swagger-ui .pl5-m{padding-left:4rem}.swagger-ui .pl6-m{padding-left:8rem}.swagger-ui .pl7-m{padding-left:16rem}.swagger-ui .pr0-m{padding-right:0}.swagger-ui .pr1-m{padding-right:.25rem}.swagger-ui .pr2-m{padding-right:.5rem}.swagger-ui .pr3-m{padding-right:1rem}.swagger-ui .pr4-m{padding-right:2rem}.swagger-ui .pr5-m{padding-right:4rem}.swagger-ui .pr6-m{padding-right:8rem}.swagger-ui .pr7-m{padding-right:16rem}.swagger-ui .pb0-m{padding-bottom:0}.swagger-ui .pb1-m{padding-bottom:.25rem}.swagger-ui .pb2-m{padding-bottom:.5rem}.swagger-ui .pb3-m{padding-bottom:1rem}.swagger-ui .pb4-m{padding-bottom:2rem}.swagger-ui .pb5-m{padding-bottom:4rem}.swagger-ui .pb6-m{padding-bottom:8rem}.swagger-ui .pb7-m{padding-bottom:16rem}.swagger-ui .pt0-m{padding-top:0}.swagger-ui .pt1-m{padding-top:.25rem}.swagger-ui .pt2-m{padding-top:.5rem}.swagger-ui .pt3-m{padding-top:1rem}.swagger-ui .pt4-m{padding-top:2rem}.swagger-ui .pt5-m{padding-top:4rem}.swagger-ui .pt6-m{padding-top:8rem}.swagger-ui .pt7-m{padding-top:16rem}.swagger-ui .pv0-m{padding-top:0;padding-bottom:0}.swagger-ui .pv1-m{padding-top:.25rem;padding-bottom:.25rem}.swagger-ui .pv2-m{padding-top:.5rem;padding-bottom:.5rem}.swagger-ui .pv3-m{padding-top:1rem;padding-bottom:1rem}.swagger-ui .pv4-m{padding-top:2rem;padding-bottom:2rem}.swagger-ui .pv5-m{padding-top:4rem;padding-bottom:4rem}.swagger-ui .pv6-m{padding-top:8rem;padding-bottom:8rem}.swagger-ui .pv7-m{padding-top:16rem;padding-bottom:16rem}.swagger-ui .ph0-m{padding-left:0;padding-right:0}.swagger-ui .ph1-m{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-m{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-m{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-m{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-m{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-m{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-m{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-m{margin:0}.swagger-ui .ma1-m{margin:.25rem}.swagger-ui .ma2-m{margin:.5rem}.swagger-ui .ma3-m{margin:1rem}.swagger-ui .ma4-m{margin:2rem}.swagger-ui .ma5-m{margin:4rem}.swagger-ui .ma6-m{margin:8rem}.swagger-ui .ma7-m{margin:16rem}.swagger-ui .ml0-m{margin-left:0}.swagger-ui .ml1-m{margin-left:.25rem}.swagger-ui .ml2-m{margin-left:.5rem}.swagger-ui .ml3-m{margin-left:1rem}.swagger-ui .ml4-m{margin-left:2rem}.swagger-ui .ml5-m{margin-left:4rem}.swagger-ui .ml6-m{margin-left:8rem}.swagger-ui .ml7-m{margin-left:16rem}.swagger-ui .mr0-m{margin-right:0}.swagger-ui .mr1-m{margin-right:.25rem}.swagger-ui .mr2-m{margin-right:.5rem}.swagger-ui .mr3-m{margin-right:1rem}.swagger-ui .mr4-m{margin-right:2rem}.swagger-ui .mr5-m{margin-right:4rem}.swagger-ui .mr6-m{margin-right:8rem}.swagger-ui .mr7-m{margin-right:16rem}.swagger-ui .mb0-m{margin-bottom:0}.swagger-ui .mb1-m{margin-bottom:.25rem}.swagger-ui .mb2-m{margin-bottom:.5rem}.swagger-ui .mb3-m{margin-bottom:1rem}.swagger-ui .mb4-m{margin-bottom:2rem}.swagger-ui .mb5-m{margin-bottom:4rem}.swagger-ui .mb6-m{margin-bottom:8rem}.swagger-ui .mb7-m{margin-bottom:16rem}.swagger-ui .mt0-m{margin-top:0}.swagger-ui .mt1-m{margin-top:.25rem}.swagger-ui .mt2-m{margin-top:.5rem}.swagger-ui .mt3-m{margin-top:1rem}.swagger-ui .mt4-m{margin-top:2rem}.swagger-ui .mt5-m{margin-top:4rem}.swagger-ui .mt6-m{margin-top:8rem}.swagger-ui .mt7-m{margin-top:16rem}.swagger-ui .mv0-m{margin-top:0;margin-bottom:0}.swagger-ui .mv1-m{margin-top:.25rem;margin-bottom:.25rem}.swagger-ui .mv2-m{margin-top:.5rem;margin-bottom:.5rem}.swagger-ui .mv3-m{margin-top:1rem;margin-bottom:1rem}.swagger-ui .mv4-m{margin-top:2rem;margin-bottom:2rem}.swagger-ui .mv5-m{margin-top:4rem;margin-bottom:4rem}.swagger-ui .mv6-m{margin-top:8rem;margin-bottom:8rem}.swagger-ui .mv7-m{margin-top:16rem;margin-bottom:16rem}.swagger-ui .mh0-m{margin-left:0;margin-right:0}.swagger-ui .mh1-m{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-m{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-m{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-m{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-m{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-m{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-m{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:60em){.swagger-ui .pa0-l{padding:0}.swagger-ui .pa1-l{padding:.25rem}.swagger-ui .pa2-l{padding:.5rem}.swagger-ui .pa3-l{padding:1rem}.swagger-ui .pa4-l{padding:2rem}.swagger-ui .pa5-l{padding:4rem}.swagger-ui .pa6-l{padding:8rem}.swagger-ui .pa7-l{padding:16rem}.swagger-ui .pl0-l{padding-left:0}.swagger-ui .pl1-l{padding-left:.25rem}.swagger-ui .pl2-l{padding-left:.5rem}.swagger-ui .pl3-l{padding-left:1rem}.swagger-ui .pl4-l{padding-left:2rem}.swagger-ui .pl5-l{padding-left:4rem}.swagger-ui .pl6-l{padding-left:8rem}.swagger-ui .pl7-l{padding-left:16rem}.swagger-ui .pr0-l{padding-right:0}.swagger-ui .pr1-l{padding-right:.25rem}.swagger-ui .pr2-l{padding-right:.5rem}.swagger-ui .pr3-l{padding-right:1rem}.swagger-ui .pr4-l{padding-right:2rem}.swagger-ui .pr5-l{padding-right:4rem}.swagger-ui .pr6-l{padding-right:8rem}.swagger-ui .pr7-l{padding-right:16rem}.swagger-ui .pb0-l{padding-bottom:0}.swagger-ui .pb1-l{padding-bottom:.25rem}.swagger-ui .pb2-l{padding-bottom:.5rem}.swagger-ui .pb3-l{padding-bottom:1rem}.swagger-ui .pb4-l{padding-bottom:2rem}.swagger-ui .pb5-l{padding-bottom:4rem}.swagger-ui .pb6-l{padding-bottom:8rem}.swagger-ui .pb7-l{padding-bottom:16rem}.swagger-ui .pt0-l{padding-top:0}.swagger-ui .pt1-l{padding-top:.25rem}.swagger-ui .pt2-l{padding-top:.5rem}.swagger-ui .pt3-l{padding-top:1rem}.swagger-ui .pt4-l{padding-top:2rem}.swagger-ui .pt5-l{padding-top:4rem}.swagger-ui .pt6-l{padding-top:8rem}.swagger-ui .pt7-l{padding-top:16rem}.swagger-ui .pv0-l{padding-top:0;padding-bottom:0}.swagger-ui .pv1-l{padding-top:.25rem;padding-bottom:.25rem}.swagger-ui .pv2-l{padding-top:.5rem;padding-bottom:.5rem}.swagger-ui .pv3-l{padding-top:1rem;padding-bottom:1rem}.swagger-ui .pv4-l{padding-top:2rem;padding-bottom:2rem}.swagger-ui .pv5-l{padding-top:4rem;padding-bottom:4rem}.swagger-ui .pv6-l{padding-top:8rem;padding-bottom:8rem}.swagger-ui .pv7-l{padding-top:16rem;padding-bottom:16rem}.swagger-ui .ph0-l{padding-left:0;padding-right:0}.swagger-ui .ph1-l{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-l{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-l{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-l{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-l{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-l{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-l{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-l{margin:0}.swagger-ui .ma1-l{margin:.25rem}.swagger-ui .ma2-l{margin:.5rem}.swagger-ui .ma3-l{margin:1rem}.swagger-ui .ma4-l{margin:2rem}.swagger-ui .ma5-l{margin:4rem}.swagger-ui .ma6-l{margin:8rem}.swagger-ui .ma7-l{margin:16rem}.swagger-ui .ml0-l{margin-left:0}.swagger-ui .ml1-l{margin-left:.25rem}.swagger-ui .ml2-l{margin-left:.5rem}.swagger-ui .ml3-l{margin-left:1rem}.swagger-ui .ml4-l{margin-left:2rem}.swagger-ui .ml5-l{margin-left:4rem}.swagger-ui .ml6-l{margin-left:8rem}.swagger-ui .ml7-l{margin-left:16rem}.swagger-ui .mr0-l{margin-right:0}.swagger-ui .mr1-l{margin-right:.25rem}.swagger-ui .mr2-l{margin-right:.5rem}.swagger-ui .mr3-l{margin-right:1rem}.swagger-ui .mr4-l{margin-right:2rem}.swagger-ui .mr5-l{margin-right:4rem}.swagger-ui .mr6-l{margin-right:8rem}.swagger-ui .mr7-l{margin-right:16rem}.swagger-ui .mb0-l{margin-bottom:0}.swagger-ui .mb1-l{margin-bottom:.25rem}.swagger-ui .mb2-l{margin-bottom:.5rem}.swagger-ui .mb3-l{margin-bottom:1rem}.swagger-ui .mb4-l{margin-bottom:2rem}.swagger-ui .mb5-l{margin-bottom:4rem}.swagger-ui .mb6-l{margin-bottom:8rem}.swagger-ui .mb7-l{margin-bottom:16rem}.swagger-ui .mt0-l{margin-top:0}.swagger-ui .mt1-l{margin-top:.25rem}.swagger-ui .mt2-l{margin-top:.5rem}.swagger-ui .mt3-l{margin-top:1rem}.swagger-ui .mt4-l{margin-top:2rem}.swagger-ui .mt5-l{margin-top:4rem}.swagger-ui .mt6-l{margin-top:8rem}.swagger-ui .mt7-l{margin-top:16rem}.swagger-ui .mv0-l{margin-top:0;margin-bottom:0}.swagger-ui .mv1-l{margin-top:.25rem;margin-bottom:.25rem}.swagger-ui .mv2-l{margin-top:.5rem;margin-bottom:.5rem}.swagger-ui .mv3-l{margin-top:1rem;margin-bottom:1rem}.swagger-ui .mv4-l{margin-top:2rem;margin-bottom:2rem}.swagger-ui .mv5-l{margin-top:4rem;margin-bottom:4rem}.swagger-ui .mv6-l{margin-top:8rem;margin-bottom:8rem}.swagger-ui .mv7-l{margin-top:16rem;margin-bottom:16rem}.swagger-ui .mh0-l{margin-left:0;margin-right:0}.swagger-ui .mh1-l{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-l{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-l{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-l{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-l{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-l{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-l{margin-left:16rem;margin-right:16rem}}.swagger-ui .na1{margin:-.25rem}.swagger-ui .na2{margin:-.5rem}.swagger-ui .na3{margin:-1rem}.swagger-ui .na4{margin:-2rem}.swagger-ui .na5{margin:-4rem}.swagger-ui .na6{margin:-8rem}.swagger-ui .na7{margin:-16rem}.swagger-ui .nl1{margin-left:-.25rem}.swagger-ui .nl2{margin-left:-.5rem}.swagger-ui .nl3{margin-left:-1rem}.swagger-ui .nl4{margin-left:-2rem}.swagger-ui .nl5{margin-left:-4rem}.swagger-ui .nl6{margin-left:-8rem}.swagger-ui .nl7{margin-left:-16rem}.swagger-ui .nr1{margin-right:-.25rem}.swagger-ui .nr2{margin-right:-.5rem}.swagger-ui .nr3{margin-right:-1rem}.swagger-ui .nr4{margin-right:-2rem}.swagger-ui .nr5{margin-right:-4rem}.swagger-ui .nr6{margin-right:-8rem}.swagger-ui .nr7{margin-right:-16rem}.swagger-ui .nb1{margin-bottom:-.25rem}.swagger-ui .nb2{margin-bottom:-.5rem}.swagger-ui .nb3{margin-bottom:-1rem}.swagger-ui .nb4{margin-bottom:-2rem}.swagger-ui .nb5{margin-bottom:-4rem}.swagger-ui .nb6{margin-bottom:-8rem}.swagger-ui .nb7{margin-bottom:-16rem}.swagger-ui .nt1{margin-top:-.25rem}.swagger-ui .nt2{margin-top:-.5rem}.swagger-ui .nt3{margin-top:-1rem}.swagger-ui .nt4{margin-top:-2rem}.swagger-ui .nt5{margin-top:-4rem}.swagger-ui .nt6{margin-top:-8rem}.swagger-ui .nt7{margin-top:-16rem}@media screen and (min-width:30em){.swagger-ui .na1-ns{margin:-.25rem}.swagger-ui .na2-ns{margin:-.5rem}.swagger-ui .na3-ns{margin:-1rem}.swagger-ui .na4-ns{margin:-2rem}.swagger-ui .na5-ns{margin:-4rem}.swagger-ui .na6-ns{margin:-8rem}.swagger-ui .na7-ns{margin:-16rem}.swagger-ui .nl1-ns{margin-left:-.25rem}.swagger-ui .nl2-ns{margin-left:-.5rem}.swagger-ui .nl3-ns{margin-left:-1rem}.swagger-ui .nl4-ns{margin-left:-2rem}.swagger-ui .nl5-ns{margin-left:-4rem}.swagger-ui .nl6-ns{margin-left:-8rem}.swagger-ui .nl7-ns{margin-left:-16rem}.swagger-ui .nr1-ns{margin-right:-.25rem}.swagger-ui .nr2-ns{margin-right:-.5rem}.swagger-ui .nr3-ns{margin-right:-1rem}.swagger-ui .nr4-ns{margin-right:-2rem}.swagger-ui .nr5-ns{margin-right:-4rem}.swagger-ui .nr6-ns{margin-right:-8rem}.swagger-ui .nr7-ns{margin-right:-16rem}.swagger-ui .nb1-ns{margin-bottom:-.25rem}.swagger-ui .nb2-ns{margin-bottom:-.5rem}.swagger-ui .nb3-ns{margin-bottom:-1rem}.swagger-ui .nb4-ns{margin-bottom:-2rem}.swagger-ui .nb5-ns{margin-bottom:-4rem}.swagger-ui .nb6-ns{margin-bottom:-8rem}.swagger-ui .nb7-ns{margin-bottom:-16rem}.swagger-ui .nt1-ns{margin-top:-.25rem}.swagger-ui .nt2-ns{margin-top:-.5rem}.swagger-ui .nt3-ns{margin-top:-1rem}.swagger-ui .nt4-ns{margin-top:-2rem}.swagger-ui .nt5-ns{margin-top:-4rem}.swagger-ui .nt6-ns{margin-top:-8rem}.swagger-ui .nt7-ns{margin-top:-16rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .na1-m{margin:-.25rem}.swagger-ui .na2-m{margin:-.5rem}.swagger-ui .na3-m{margin:-1rem}.swagger-ui .na4-m{margin:-2rem}.swagger-ui .na5-m{margin:-4rem}.swagger-ui .na6-m{margin:-8rem}.swagger-ui .na7-m{margin:-16rem}.swagger-ui .nl1-m{margin-left:-.25rem}.swagger-ui .nl2-m{margin-left:-.5rem}.swagger-ui .nl3-m{margin-left:-1rem}.swagger-ui .nl4-m{margin-left:-2rem}.swagger-ui .nl5-m{margin-left:-4rem}.swagger-ui .nl6-m{margin-left:-8rem}.swagger-ui .nl7-m{margin-left:-16rem}.swagger-ui .nr1-m{margin-right:-.25rem}.swagger-ui .nr2-m{margin-right:-.5rem}.swagger-ui .nr3-m{margin-right:-1rem}.swagger-ui .nr4-m{margin-right:-2rem}.swagger-ui .nr5-m{margin-right:-4rem}.swagger-ui .nr6-m{margin-right:-8rem}.swagger-ui .nr7-m{margin-right:-16rem}.swagger-ui .nb1-m{margin-bottom:-.25rem}.swagger-ui .nb2-m{margin-bottom:-.5rem}.swagger-ui .nb3-m{margin-bottom:-1rem}.swagger-ui .nb4-m{margin-bottom:-2rem}.swagger-ui .nb5-m{margin-bottom:-4rem}.swagger-ui .nb6-m{margin-bottom:-8rem}.swagger-ui .nb7-m{margin-bottom:-16rem}.swagger-ui .nt1-m{margin-top:-.25rem}.swagger-ui .nt2-m{margin-top:-.5rem}.swagger-ui .nt3-m{margin-top:-1rem}.swagger-ui .nt4-m{margin-top:-2rem}.swagger-ui .nt5-m{margin-top:-4rem}.swagger-ui .nt6-m{margin-top:-8rem}.swagger-ui .nt7-m{margin-top:-16rem}}@media screen and (min-width:60em){.swagger-ui .na1-l{margin:-.25rem}.swagger-ui .na2-l{margin:-.5rem}.swagger-ui .na3-l{margin:-1rem}.swagger-ui .na4-l{margin:-2rem}.swagger-ui .na5-l{margin:-4rem}.swagger-ui .na6-l{margin:-8rem}.swagger-ui .na7-l{margin:-16rem}.swagger-ui .nl1-l{margin-left:-.25rem}.swagger-ui .nl2-l{margin-left:-.5rem}.swagger-ui .nl3-l{margin-left:-1rem}.swagger-ui .nl4-l{margin-left:-2rem}.swagger-ui .nl5-l{margin-left:-4rem}.swagger-ui .nl6-l{margin-left:-8rem}.swagger-ui .nl7-l{margin-left:-16rem}.swagger-ui .nr1-l{margin-right:-.25rem}.swagger-ui .nr2-l{margin-right:-.5rem}.swagger-ui .nr3-l{margin-right:-1rem}.swagger-ui .nr4-l{margin-right:-2rem}.swagger-ui .nr5-l{margin-right:-4rem}.swagger-ui .nr6-l{margin-right:-8rem}.swagger-ui .nr7-l{margin-right:-16rem}.swagger-ui .nb1-l{margin-bottom:-.25rem}.swagger-ui .nb2-l{margin-bottom:-.5rem}.swagger-ui .nb3-l{margin-bottom:-1rem}.swagger-ui .nb4-l{margin-bottom:-2rem}.swagger-ui .nb5-l{margin-bottom:-4rem}.swagger-ui .nb6-l{margin-bottom:-8rem}.swagger-ui .nb7-l{margin-bottom:-16rem}.swagger-ui .nt1-l{margin-top:-.25rem}.swagger-ui .nt2-l{margin-top:-.5rem}.swagger-ui .nt3-l{margin-top:-1rem}.swagger-ui .nt4-l{margin-top:-2rem}.swagger-ui .nt5-l{margin-top:-4rem}.swagger-ui .nt6-l{margin-top:-8rem}.swagger-ui .nt7-l{margin-top:-16rem}}.swagger-ui .collapse{border-collapse:collapse;border-spacing:0}.swagger-ui .striped--light-silver:nth-child(odd){background-color:#aaa}.swagger-ui .striped--moon-gray:nth-child(odd){background-color:#ccc}.swagger-ui .striped--light-gray:nth-child(odd){background-color:#eee}.swagger-ui .striped--near-white:nth-child(odd){background-color:#f4f4f4}.swagger-ui .stripe-light:nth-child(odd){background-color:hsla(0,0%,100%,.1)}.swagger-ui .stripe-dark:nth-child(odd){background-color:rgba(0,0,0,.1)}.swagger-ui .strike{text-decoration:line-through}.swagger-ui .underline{text-decoration:underline}.swagger-ui .no-underline{text-decoration:none}@media screen and (min-width:30em){.swagger-ui .strike-ns{text-decoration:line-through}.swagger-ui .underline-ns{text-decoration:underline}.swagger-ui .no-underline-ns{text-decoration:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .strike-m{text-decoration:line-through}.swagger-ui .underline-m{text-decoration:underline}.swagger-ui .no-underline-m{text-decoration:none}}@media screen and (min-width:60em){.swagger-ui .strike-l{text-decoration:line-through}.swagger-ui .underline-l{text-decoration:underline}.swagger-ui .no-underline-l{text-decoration:none}}.swagger-ui .tl{text-align:left}.swagger-ui .tr{text-align:right}.swagger-ui .tc{text-align:center}.swagger-ui .tj{text-align:justify}@media screen and (min-width:30em){.swagger-ui .tl-ns{text-align:left}.swagger-ui .tr-ns{text-align:right}.swagger-ui .tc-ns{text-align:center}.swagger-ui .tj-ns{text-align:justify}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .tl-m{text-align:left}.swagger-ui .tr-m{text-align:right}.swagger-ui .tc-m{text-align:center}.swagger-ui .tj-m{text-align:justify}}@media screen and (min-width:60em){.swagger-ui .tl-l{text-align:left}.swagger-ui .tr-l{text-align:right}.swagger-ui .tc-l{text-align:center}.swagger-ui .tj-l{text-align:justify}}.swagger-ui .ttc{text-transform:capitalize}.swagger-ui .ttl{text-transform:lowercase}.swagger-ui .ttu{text-transform:uppercase}.swagger-ui .ttn{text-transform:none}@media screen and (min-width:30em){.swagger-ui .ttc-ns{text-transform:capitalize}.swagger-ui .ttl-ns{text-transform:lowercase}.swagger-ui .ttu-ns{text-transform:uppercase}.swagger-ui .ttn-ns{text-transform:none}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ttc-m{text-transform:capitalize}.swagger-ui .ttl-m{text-transform:lowercase}.swagger-ui .ttu-m{text-transform:uppercase}.swagger-ui .ttn-m{text-transform:none}}@media screen and (min-width:60em){.swagger-ui .ttc-l{text-transform:capitalize}.swagger-ui .ttl-l{text-transform:lowercase}.swagger-ui .ttu-l{text-transform:uppercase}.swagger-ui .ttn-l{text-transform:none}}.swagger-ui .f-6,.swagger-ui .f-headline{font-size:6rem}.swagger-ui .f-5,.swagger-ui .f-subheadline{font-size:5rem}.swagger-ui .f1{font-size:3rem}.swagger-ui .f2{font-size:2.25rem}.swagger-ui .f3{font-size:1.5rem}.swagger-ui .f4{font-size:1.25rem}.swagger-ui .f5{font-size:1rem}.swagger-ui .f6{font-size:.875rem}.swagger-ui .f7{font-size:.75rem}@media screen and (min-width:30em){.swagger-ui .f-6-ns,.swagger-ui .f-headline-ns{font-size:6rem}.swagger-ui .f-5-ns,.swagger-ui .f-subheadline-ns{font-size:5rem}.swagger-ui .f1-ns{font-size:3rem}.swagger-ui .f2-ns{font-size:2.25rem}.swagger-ui .f3-ns{font-size:1.5rem}.swagger-ui .f4-ns{font-size:1.25rem}.swagger-ui .f5-ns{font-size:1rem}.swagger-ui .f6-ns{font-size:.875rem}.swagger-ui .f7-ns{font-size:.75rem}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .f-6-m,.swagger-ui .f-headline-m{font-size:6rem}.swagger-ui .f-5-m,.swagger-ui .f-subheadline-m{font-size:5rem}.swagger-ui .f1-m{font-size:3rem}.swagger-ui .f2-m{font-size:2.25rem}.swagger-ui .f3-m{font-size:1.5rem}.swagger-ui .f4-m{font-size:1.25rem}.swagger-ui .f5-m{font-size:1rem}.swagger-ui .f6-m{font-size:.875rem}.swagger-ui .f7-m{font-size:.75rem}}@media screen and (min-width:60em){.swagger-ui .f-6-l,.swagger-ui .f-headline-l{font-size:6rem}.swagger-ui .f-5-l,.swagger-ui .f-subheadline-l{font-size:5rem}.swagger-ui .f1-l{font-size:3rem}.swagger-ui .f2-l{font-size:2.25rem}.swagger-ui .f3-l{font-size:1.5rem}.swagger-ui .f4-l{font-size:1.25rem}.swagger-ui .f5-l{font-size:1rem}.swagger-ui .f6-l{font-size:.875rem}.swagger-ui .f7-l{font-size:.75rem}}.swagger-ui .measure{max-width:30em}.swagger-ui .measure-wide{max-width:34em}.swagger-ui .measure-narrow{max-width:20em}.swagger-ui .indent{text-indent:1em;margin-top:0;margin-bottom:0}.swagger-ui .small-caps{font-variant:small-caps}.swagger-ui .truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media screen and (min-width:30em){.swagger-ui .measure-ns{max-width:30em}.swagger-ui .measure-wide-ns{max-width:34em}.swagger-ui .measure-narrow-ns{max-width:20em}.swagger-ui .indent-ns{text-indent:1em;margin-top:0;margin-bottom:0}.swagger-ui .small-caps-ns{font-variant:small-caps}.swagger-ui .truncate-ns{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .measure-m{max-width:30em}.swagger-ui .measure-wide-m{max-width:34em}.swagger-ui .measure-narrow-m{max-width:20em}.swagger-ui .indent-m{text-indent:1em;margin-top:0;margin-bottom:0}.swagger-ui .small-caps-m{font-variant:small-caps}.swagger-ui .truncate-m{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}@media screen and (min-width:60em){.swagger-ui .measure-l{max-width:30em}.swagger-ui .measure-wide-l{max-width:34em}.swagger-ui .measure-narrow-l{max-width:20em}.swagger-ui .indent-l{text-indent:1em;margin-top:0;margin-bottom:0}.swagger-ui .small-caps-l{font-variant:small-caps}.swagger-ui .truncate-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}.swagger-ui .overflow-container{overflow-y:scroll}.swagger-ui .center{margin-right:auto;margin-left:auto}.swagger-ui .mr-auto{margin-right:auto}.swagger-ui .ml-auto{margin-left:auto}@media screen and (min-width:30em){.swagger-ui .center-ns{margin-right:auto;margin-left:auto}.swagger-ui .mr-auto-ns{margin-right:auto}.swagger-ui .ml-auto-ns{margin-left:auto}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .center-m{margin-right:auto;margin-left:auto}.swagger-ui .mr-auto-m{margin-right:auto}.swagger-ui .ml-auto-m{margin-left:auto}}@media screen and (min-width:60em){.swagger-ui .center-l{margin-right:auto;margin-left:auto}.swagger-ui .mr-auto-l{margin-right:auto}.swagger-ui .ml-auto-l{margin-left:auto}}.swagger-ui .clip{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}@media screen and (min-width:30em){.swagger-ui .clip-ns{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .clip-m{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:60em){.swagger-ui .clip-l{position:fixed!important;_position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}.swagger-ui .ws-normal{white-space:normal}.swagger-ui .nowrap{white-space:nowrap}.swagger-ui .pre{white-space:pre}@media screen and (min-width:30em){.swagger-ui .ws-normal-ns{white-space:normal}.swagger-ui .nowrap-ns{white-space:nowrap}.swagger-ui .pre-ns{white-space:pre}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .ws-normal-m{white-space:normal}.swagger-ui .nowrap-m{white-space:nowrap}.swagger-ui .pre-m{white-space:pre}}@media screen and (min-width:60em){.swagger-ui .ws-normal-l{white-space:normal}.swagger-ui .nowrap-l{white-space:nowrap}.swagger-ui .pre-l{white-space:pre}}.swagger-ui .v-base{vertical-align:baseline}.swagger-ui .v-mid{vertical-align:middle}.swagger-ui .v-top{vertical-align:top}.swagger-ui .v-btm{vertical-align:bottom}@media screen and (min-width:30em){.swagger-ui .v-base-ns{vertical-align:baseline}.swagger-ui .v-mid-ns{vertical-align:middle}.swagger-ui .v-top-ns{vertical-align:top}.swagger-ui .v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em) and (max-width:60em){.swagger-ui .v-base-m{vertical-align:baseline}.swagger-ui .v-mid-m{vertical-align:middle}.swagger-ui .v-top-m{vertical-align:top}.swagger-ui .v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.swagger-ui .v-base-l{vertical-align:baseline}.swagger-ui .v-mid-l{vertical-align:middle}.swagger-ui .v-top-l{vertical-align:top}.swagger-ui .v-btm-l{vertical-align:bottom}}.swagger-ui .dim{opacity:1;transition:opacity .15s ease-in}.swagger-ui .dim:focus,.swagger-ui .dim:hover{opacity:.5;transition:opacity .15s ease-in}.swagger-ui .dim:active{opacity:.8;transition:opacity .15s ease-out}.swagger-ui .glow{transition:opacity .15s ease-in}.swagger-ui .glow:focus,.swagger-ui .glow:hover{opacity:1;transition:opacity .15s ease-in}.swagger-ui .hide-child .child{opacity:0;transition:opacity .15s ease-in}.swagger-ui .hide-child:active .child,.swagger-ui .hide-child:focus .child,.swagger-ui .hide-child:hover .child{opacity:1;transition:opacity .15s ease-in}.swagger-ui .underline-hover:focus,.swagger-ui .underline-hover:hover{text-decoration:underline}.swagger-ui .grow{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);transition:-webkit-transform .25s ease-out;transition:transform .25s ease-out;transition:transform .25s ease-out, -webkit-transform .25s ease-out}.swagger-ui .grow:focus,.swagger-ui .grow:hover{-webkit-transform:scale(1.05);transform:scale(1.05)}.swagger-ui .grow:active{-webkit-transform:scale(.9);transform:scale(.9)}.swagger-ui .grow-large{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);transition:-webkit-transform .25s ease-in-out;transition:transform .25s ease-in-out;transition:transform .25s ease-in-out, -webkit-transform .25s ease-in-out}.swagger-ui .grow-large:focus,.swagger-ui .grow-large:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.swagger-ui .grow-large:active{-webkit-transform:scale(.95);transform:scale(.95)}.swagger-ui .pointer:hover{cursor:pointer}.swagger-ui .shadow-hover{cursor:pointer;position:relative;transition:all .5s cubic-bezier(.165,.84,.44,1)}.swagger-ui .shadow-hover:after{content:"";box-shadow:0 0 16px 2px rgba(0,0,0,.2);border-radius:inherit;opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;transition:opacity .5s cubic-bezier(.165,.84,.44,1)}.swagger-ui .shadow-hover:focus:after,.swagger-ui .shadow-hover:hover:after{opacity:1}.swagger-ui .bg-animate,.swagger-ui .bg-animate:focus,.swagger-ui .bg-animate:hover{transition:background-color .15s ease-in-out}.swagger-ui .z-0{z-index:0}.swagger-ui .z-1{z-index:1}.swagger-ui .z-2{z-index:2}.swagger-ui .z-3{z-index:3}.swagger-ui .z-4{z-index:4}.swagger-ui .z-5{z-index:5}.swagger-ui .z-999{z-index:999}.swagger-ui .z-9999{z-index:9999}.swagger-ui .z-max{z-index:2147483647}.swagger-ui .z-inherit{z-index:inherit}.swagger-ui .z-initial{z-index:auto}.swagger-ui .z-unset{z-index:unset}.swagger-ui .nested-copy-line-height ol,.swagger-ui .nested-copy-line-height p,.swagger-ui .nested-copy-line-height ul{line-height:1.5}.swagger-ui .nested-headline-line-height h1,.swagger-ui .nested-headline-line-height h2,.swagger-ui .nested-headline-line-height h3,.swagger-ui .nested-headline-line-height h4,.swagger-ui .nested-headline-line-height h5,.swagger-ui .nested-headline-line-height h6{line-height:1.25}.swagger-ui .nested-list-reset ol,.swagger-ui .nested-list-reset ul{padding-left:0;margin-left:0;list-style-type:none}.swagger-ui .nested-copy-indent p+p{text-indent:.1em;margin-top:0;margin-bottom:0}.swagger-ui .nested-copy-seperator p+p{margin-top:1.5em}.swagger-ui .nested-img img{width:100%;max-width:100%;display:block}.swagger-ui .nested-links a{color:#357edd;transition:color .15s ease-in}.swagger-ui .nested-links a:focus,.swagger-ui .nested-links a:hover{color:#96ccff;transition:color .15s ease-in}.swagger-ui .wrapper{width:100%;max-width:1460px;margin:0 auto;padding:0 20px;box-sizing:border-box}.swagger-ui .opblock-tag-section{display:flex;flex-direction:column}.swagger-ui .opblock-tag{display:flex;align-items:center;padding:10px 20px 10px 10px;cursor:pointer;transition:all .2s;border-bottom:1px solid rgba(59,65,81,.3)}.swagger-ui .opblock-tag:hover{background:rgba(0,0,0,.02)}.swagger-ui .opblock-tag{font-size:24px;margin:0 0 5px;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock-tag.no-desc span{flex:1}.swagger-ui .opblock-tag svg{transition:all .4s}.swagger-ui .opblock-tag small{font-size:14px;font-weight:400;flex:1;padding:0 10px;font-family:sans-serif;color:#3b4151}.swagger-ui .parameter__type{font-size:12px;padding:5px 0;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .parameter-controls{margin-top:.75em}.swagger-ui .examples__title{display:block;font-size:1.1em;font-weight:700;margin-bottom:.75em}.swagger-ui .examples__section{margin-top:1.5em}.swagger-ui .examples__section-header{font-weight:700;font-size:.9rem;margin-bottom:.5rem}.swagger-ui .examples-select{margin-bottom:.75em}.swagger-ui .examples-select__section-label{font-weight:700;font-size:.9rem;margin-right:.5rem}.swagger-ui .example__section{margin-top:1.5em}.swagger-ui .example__section-header{font-weight:700;font-size:.9rem;margin-bottom:.5rem}.swagger-ui .view-line-link{position:relative;top:3px;width:20px;margin:0 5px;cursor:pointer;transition:all .5s}.swagger-ui .opblock{margin:0 0 15px;border:1px solid #000;border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.19)}.swagger-ui .opblock .tab-header{display:flex;flex:1}.swagger-ui .opblock .tab-header .tab-item{padding:0 40px;cursor:pointer}.swagger-ui .opblock .tab-header .tab-item:first-of-type{padding:0 40px 0 0}.swagger-ui .opblock .tab-header .tab-item.active h4 span{position:relative}.swagger-ui .opblock .tab-header .tab-item.active h4 span:after{position:absolute;bottom:-15px;left:50%;width:120%;height:4px;content:"";-webkit-transform:translateX(-50%);transform:translateX(-50%);background:grey}.swagger-ui .opblock.is-open .opblock-summary{border-bottom:1px solid #000}.swagger-ui .opblock .opblock-section-header{display:flex;align-items:center;padding:8px 20px;min-height:50px;background:hsla(0,0%,100%,.8);box-shadow:0 1px 2px rgba(0,0,0,.1)}.swagger-ui .opblock .opblock-section-header>label{font-size:12px;font-weight:700;display:flex;align-items:center;margin:0 0 0 auto;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-section-header>label>span{padding:0 10px 0 0}.swagger-ui .opblock .opblock-section-header h4{font-size:14px;flex:1;margin:0;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-summary-method{font-size:14px;font-weight:700;min-width:80px;padding:6px 15px;text-align:center;border-radius:3px;background:#000;text-shadow:0 1px 0 rgba(0,0,0,.1);font-family:sans-serif;color:#fff}.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{font-size:16px;display:flex;align-items:center;word-break:break-word;padding:0 10px;font-family:monospace;font-weight:600;color:#3b4151}@media (max-width:768px){.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{font-size:12px}}.swagger-ui .opblock .opblock-summary-path__deprecated{text-decoration:line-through}.swagger-ui .opblock .opblock-summary-operation-id{font-size:14px}.swagger-ui .opblock .opblock-summary-description{font-size:13px;flex:1 1 auto;word-break:break-word;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock .opblock-summary{display:flex;align-items:center;padding:5px;cursor:pointer}.swagger-ui .opblock .opblock-summary .view-line-link{position:relative;top:2px;width:0;margin:0;cursor:pointer;transition:all .5s}.swagger-ui .opblock .opblock-summary:hover .view-line-link{width:18px;margin:0 5px}.swagger-ui .opblock.opblock-post{border-color:#49cc90;background:rgba(73,204,144,.1)}.swagger-ui .opblock.opblock-post .opblock-summary-method{background:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary{border-color:#49cc90}.swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span:after{background:#49cc90}.swagger-ui .opblock.opblock-put{border-color:#fca130;background:rgba(252,161,48,.1)}.swagger-ui .opblock.opblock-put .opblock-summary-method{background:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary{border-color:#fca130}.swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span:after{background:#fca130}.swagger-ui .opblock.opblock-delete{border-color:#f93e3e;background:rgba(249,62,62,.1)}.swagger-ui .opblock.opblock-delete .opblock-summary-method{background:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary{border-color:#f93e3e}.swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span:after{background:#f93e3e}.swagger-ui .opblock.opblock-get{border-color:#61affe;background:rgba(97,175,254,.1)}.swagger-ui .opblock.opblock-get .opblock-summary-method{background:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary{border-color:#61affe}.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span:after{background:#61affe}.swagger-ui .opblock.opblock-patch{border-color:#50e3c2;background:rgba(80,227,194,.1)}.swagger-ui .opblock.opblock-patch .opblock-summary-method{background:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary{border-color:#50e3c2}.swagger-ui .opblock.opblock-patch .tab-header .tab-item.active h4 span:after{background:#50e3c2}.swagger-ui .opblock.opblock-head{border-color:#9012fe;background:rgba(144,18,254,.1)}.swagger-ui .opblock.opblock-head .opblock-summary-method{background:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary{border-color:#9012fe}.swagger-ui .opblock.opblock-head .tab-header .tab-item.active h4 span:after{background:#9012fe}.swagger-ui .opblock.opblock-options{border-color:#0d5aa7;background:rgba(13,90,167,.1)}.swagger-ui .opblock.opblock-options .opblock-summary-method{background:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary{border-color:#0d5aa7}.swagger-ui .opblock.opblock-options .tab-header .tab-item.active h4 span:after{background:#0d5aa7}.swagger-ui .opblock.opblock-deprecated{opacity:.6;border-color:#ebebeb;background:hsla(0,0%,92.2%,.1)}.swagger-ui .opblock.opblock-deprecated .opblock-summary-method{background:#ebebeb}.swagger-ui .opblock.opblock-deprecated .opblock-summary{border-color:#ebebeb}.swagger-ui .opblock.opblock-deprecated .tab-header .tab-item.active h4 span:after{background:#ebebeb}.swagger-ui .opblock .opblock-schemes{padding:8px 20px}.swagger-ui .opblock .opblock-schemes .schemes-title{padding:0 10px 0 0}.swagger-ui .filter .operation-filter-input{width:100%;margin:20px 0;padding:10px;border:2px solid #d8dde7}.swagger-ui .model-example{margin-top:1em}.swagger-ui .tab{display:flex;padding:0;list-style:none}.swagger-ui .tab li{font-size:12px;min-width:60px;padding:0;cursor:pointer;font-family:sans-serif;color:#3b4151}.swagger-ui .tab li:first-of-type{position:relative;padding-left:0;padding-right:12px}.swagger-ui .tab li:first-of-type:after{position:absolute;top:0;right:6px;width:1px;height:100%;content:"";background:rgba(0,0,0,.2)}.swagger-ui .tab li.active{font-weight:700}.swagger-ui .opblock-description-wrapper,.swagger-ui .opblock-external-docs-wrapper,.swagger-ui .opblock-title_normal{font-size:12px;margin:0 0 5px;padding:15px 20px;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock-description-wrapper h4,.swagger-ui .opblock-external-docs-wrapper h4,.swagger-ui .opblock-title_normal h4{font-size:12px;margin:0 0 5px;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock-description-wrapper p,.swagger-ui .opblock-external-docs-wrapper p,.swagger-ui .opblock-title_normal p{font-size:14px;margin:0;font-family:sans-serif;color:#3b4151}.swagger-ui .opblock-external-docs-wrapper h4{padding-left:0}.swagger-ui .execute-wrapper{padding:20px;text-align:right}.swagger-ui .execute-wrapper .btn{width:100%;padding:8px 40px}.swagger-ui .body-param-options{display:flex;flex-direction:column}.swagger-ui .body-param-options .body-param-edit{padding:10px 0}.swagger-ui .body-param-options label{padding:8px 0}.swagger-ui .body-param-options label select{margin:3px 0 0}.swagger-ui .responses-inner{padding:20px}.swagger-ui .responses-inner h4,.swagger-ui .responses-inner h5{font-size:12px;margin:10px 0 5px;font-family:sans-serif;color:#3b4151}.swagger-ui .response-col_status{font-size:14px;font-family:sans-serif;color:#3b4151}.swagger-ui .response-col_status .response-undocumented{font-size:11px;font-family:monospace;font-weight:600;color:#909090}.swagger-ui .response-col_links{padding-left:2em;max-width:40em;font-size:14px;font-family:sans-serif;color:#3b4151}.swagger-ui .response-col_links .response-undocumented{font-size:11px;font-family:monospace;font-weight:600;color:#909090}.swagger-ui .opblock-body .opblock-loading-animation{display:block;margin:3em auto}.swagger-ui .opblock-body pre{font-size:12px;margin:0;padding:10px;white-space:pre-wrap;word-wrap:break-word;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;border-radius:4px;background:#41444e;overflow-wrap:break-word;font-family:monospace;font-weight:600;color:#fff}.swagger-ui .opblock-body pre span{color:#fff!important}.swagger-ui .opblock-body pre .headerline{display:block}.swagger-ui .highlight-code{position:relative}.swagger-ui .highlight-code>.microlight{overflow-y:auto;max-height:400px;min-height:6em}.swagger-ui .download-contents{position:absolute;bottom:10px;right:10px;cursor:pointer;background:#7d8293;text-align:center;padding:5px;border-radius:4px;font-family:sans-serif;font-weight:600;color:#fff;font-size:14px;height:30px;width:75px}.swagger-ui .scheme-container{margin:0 0 20px;padding:30px 0;background:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.15)}.swagger-ui .scheme-container .schemes{display:flex;align-items:flex-end}.swagger-ui .scheme-container .schemes>label{font-size:12px;font-weight:700;display:flex;flex-direction:column;margin:-20px 15px 0 0;font-family:sans-serif;color:#3b4151}.swagger-ui .scheme-container .schemes>label select{min-width:130px;text-transform:uppercase}.swagger-ui .loading-container{padding:40px 0 60px;margin-top:1em;min-height:1px;display:flex;justify-content:center;align-items:center;flex-direction:column}.swagger-ui .loading-container .loading{position:relative}.swagger-ui .loading-container .loading:after{font-size:10px;font-weight:700;position:absolute;top:50%;left:50%;content:"loading";-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-transform:uppercase;font-family:sans-serif;color:#3b4151}.swagger-ui .loading-container .loading:before{position:absolute;top:50%;left:50%;display:block;width:60px;height:60px;margin:-30px;content:"";-webkit-animation:rotation 1s linear infinite,opacity .5s;animation:rotation 1s linear infinite,opacity .5s;opacity:1;border:2px solid rgba(85,85,85,.1);border-top-color:rgba(0,0,0,.6);border-radius:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden}@-webkit-keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotation{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.swagger-ui .response-controls{padding-top:1em;display:flex}.swagger-ui .response-control-media-type{margin-right:1em}.swagger-ui .response-control-media-type--accept-controller select{border-color:green}.swagger-ui .response-control-media-type__accept-message{color:green;font-size:.7em}.swagger-ui .response-control-examples__title,.swagger-ui .response-control-media-type__title{display:block;margin-bottom:.2em;font-size:.7em}@-webkit-keyframes blinker{50%{opacity:0}}@keyframes blinker{50%{opacity:0}}.swagger-ui section h3{font-family:sans-serif;color:#3b4151}.swagger-ui a.nostyle{display:inline}.swagger-ui a.nostyle,.swagger-ui a.nostyle:visited{text-decoration:inherit;color:inherit;cursor:pointer}.swagger-ui .version-pragma{height:100%;padding:5em 0}.swagger-ui .version-pragma__message{display:flex;justify-content:center;height:100%;font-size:1.2em;text-align:center;line-height:1.5em;padding:0 .6em}.swagger-ui .version-pragma__message>div{max-width:55ch;flex:1}.swagger-ui .version-pragma__message code{background-color:#dedede;padding:4px 4px 2px;white-space:pre}.swagger-ui .btn{font-size:14px;font-weight:700;padding:5px 23px;transition:all .3s;border:2px solid grey;border-radius:4px;background:transparent;box-shadow:0 1px 2px rgba(0,0,0,.1);font-family:sans-serif;color:#3b4151}.swagger-ui .btn.btn-sm{font-size:12px;padding:4px 23px}.swagger-ui .btn[disabled]{cursor:not-allowed;opacity:.3}.swagger-ui .btn:hover{box-shadow:0 0 5px rgba(0,0,0,.3)}.swagger-ui .btn.cancel{border-color:#ff6060;background-color:transparent;font-family:sans-serif;color:#ff6060}.swagger-ui .btn.authorize{line-height:1;display:inline;color:#49cc90;border-color:#49cc90;background-color:transparent}.swagger-ui .btn.authorize span{float:left;padding:4px 20px 0 0}.swagger-ui .btn.authorize svg{fill:#49cc90}.swagger-ui .btn.execute{background-color:#4990e2;color:#fff;border-color:#4990e2}.swagger-ui .btn-group{display:flex;padding:30px}.swagger-ui .btn-group .btn{flex:1}.swagger-ui .btn-group .btn:first-child{border-radius:4px 0 0 4px}.swagger-ui .btn-group .btn:last-child{border-radius:0 4px 4px 0}.swagger-ui .authorization__btn{padding:0 10px;border:none;background:none}.swagger-ui .authorization__btn.locked{opacity:1}.swagger-ui .authorization__btn.unlocked{opacity:.4}.swagger-ui .expand-methods,.swagger-ui .expand-operation{border:none;background:none}.swagger-ui .expand-methods svg,.swagger-ui .expand-operation svg{width:20px;height:20px}.swagger-ui .expand-methods{padding:0 10px}.swagger-ui .expand-methods:hover svg{fill:#404040}.swagger-ui .expand-methods svg{transition:all .3s;fill:#707070}.swagger-ui button{cursor:pointer;outline:none}.swagger-ui button.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;border-color:#f93e3e;background:#feebeb}.swagger-ui select{font-size:14px;font-weight:700;padding:5px 40px 5px 10px;border:2px solid #41444e;border-radius:4px;background:#f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+PHBhdGggZD0iTTEzLjQxOCA3Ljg1OWEuNjk1LjY5NSAwIDAgMSAuOTc4IDAgLjY4LjY4IDAgMCAxIDAgLjk2OWwtMy45MDggMy44M2EuNjk3LjY5NyAwIDAgMS0uOTc5IDBsLTMuOTA4LTMuODNhLjY4LjY4IDAgMCAxIDAtLjk2OS42OTUuNjk1IDAgMCAxIC45NzggMEwxMCAxMWwzLjQxOC0zLjE0MXoiLz48L3N2Zz4=) right 10px center no-repeat;background-size:20px;box-shadow:0 1px 2px 0 rgba(0,0,0,.25);font-family:sans-serif;color:#3b4151;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui select[multiple]{margin:5px 0;padding:5px;background:#f7f7f7}.swagger-ui select.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;border-color:#f93e3e;background:#feebeb}.swagger-ui .opblock-body select{min-width:230px}@media (max-width:768px){.swagger-ui .opblock-body select{min-width:180px}}.swagger-ui label{font-size:12px;font-weight:700;margin:0 0 5px;font-family:sans-serif;color:#3b4151}.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text],.swagger-ui textarea{min-width:100px;margin:5px 0;padding:8px 10px;border:1px solid #d9d9d9;border-radius:4px;background:#fff}@media (max-width:768px){.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text],.swagger-ui textarea{max-width:175px}}.swagger-ui input[type=email].invalid,.swagger-ui input[type=file].invalid,.swagger-ui input[type=password].invalid,.swagger-ui input[type=search].invalid,.swagger-ui input[type=text].invalid,.swagger-ui textarea.invalid{-webkit-animation:shake .4s 1;animation:shake .4s 1;border-color:#f93e3e;background:#feebeb}.swagger-ui input[disabled],.swagger-ui select[disabled],.swagger-ui textarea[disabled]{background-color:#fafafa;color:#888;cursor:not-allowed}.swagger-ui select[disabled]{border-color:#888}.swagger-ui textarea[disabled]{background-color:#41444e;color:#fff}@-webkit-keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}@keyframes shake{10%,90%{-webkit-transform:translate3d(-1px,0,0);transform:translate3d(-1px,0,0)}20%,80%{-webkit-transform:translate3d(2px,0,0);transform:translate3d(2px,0,0)}30%,50%,70%{-webkit-transform:translate3d(-4px,0,0);transform:translate3d(-4px,0,0)}40%,60%{-webkit-transform:translate3d(4px,0,0);transform:translate3d(4px,0,0)}}.swagger-ui textarea{font-size:12px;width:100%;min-height:280px;padding:10px;border:none;border-radius:4px;outline:none;background:hsla(0,0%,100%,.8);font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui textarea:focus{border:2px solid #61affe}.swagger-ui textarea.curl{font-size:12px;min-height:100px;margin:0;padding:10px;resize:none;border-radius:4px;background:#41444e;font-family:monospace;font-weight:600;color:#fff}.swagger-ui .checkbox{padding:5px 0 10px;transition:opacity .5s;color:#303030}.swagger-ui .checkbox label{display:flex}.swagger-ui .checkbox p{font-weight:400!important;font-style:italic;margin:0!important;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .checkbox input[type=checkbox]{display:none}.swagger-ui .checkbox input[type=checkbox]+label>.item{position:relative;top:3px;display:inline-block;width:16px;height:16px;margin:0 8px 0 0;padding:5px;cursor:pointer;border-radius:1px;background:#e8e8e8;box-shadow:0 0 0 2px #e8e8e8;flex:none}.swagger-ui .checkbox input[type=checkbox]+label>.item:active{-webkit-transform:scale(.9);transform:scale(.9)}.swagger-ui .checkbox input[type=checkbox]:checked+label>.item{background:#e8e8e8 url("data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='8' viewBox='3 7 10 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2341474E' fill-rule='evenodd' d='M6.333 15L3 11.667l1.333-1.334 2 2L11.667 7 13 8.333z'/%3E%3C/svg%3E") 50% no-repeat}.swagger-ui .dialog-ux{position:fixed;z-index:9999;top:0;right:0;bottom:0;left:0}.swagger-ui .dialog-ux .backdrop-ux{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.8)}.swagger-ui .dialog-ux .modal-ux{position:absolute;z-index:9999;top:50%;left:50%;width:100%;min-width:300px;max-width:650px;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);border:1px solid #ebebeb;border-radius:4px;background:#fff;box-shadow:0 10px 30px 0 rgba(0,0,0,.2)}.swagger-ui .dialog-ux .modal-ux-content{overflow-y:auto;max-height:540px;padding:20px}.swagger-ui .dialog-ux .modal-ux-content p{font-size:12px;margin:0 0 5px;color:#41444e;font-family:sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-content h4{font-size:18px;font-weight:600;margin:15px 0 0;font-family:sans-serif;color:#3b4151}.swagger-ui .dialog-ux .modal-ux-header{display:flex;padding:12px 0;border-bottom:1px solid #ebebeb;align-items:center}.swagger-ui .dialog-ux .modal-ux-header .close-modal{padding:0 10px;border:none;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.swagger-ui .dialog-ux .modal-ux-header h3{font-size:20px;font-weight:600;margin:0;padding:0 20px;flex:1;font-family:sans-serif;color:#3b4151}.swagger-ui .model{font-size:12px;font-weight:300;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .model .deprecated span,.swagger-ui .model .deprecated td{color:#a0a0a0!important}.swagger-ui .model .deprecated>td:first-of-type{text-decoration:line-through}.swagger-ui .model-toggle{font-size:10px;position:relative;top:6px;display:inline-block;margin:auto .3em;cursor:pointer;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in, -webkit-transform .15s ease-in;-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:50% 50%;transform-origin:50% 50%}.swagger-ui .model-toggle.collapsed{-webkit-transform:rotate(0deg);transform:rotate(0deg)}.swagger-ui .model-toggle:after{display:block;width:20px;height:20px;content:"";background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E") 50% no-repeat;background-size:100%}.swagger-ui .model-jump-to-path{position:relative;cursor:pointer}.swagger-ui .model-jump-to-path .view-line-link{position:absolute;top:-.4em;cursor:pointer}.swagger-ui .model-title{position:relative}.swagger-ui .model-title:hover .model-hint{visibility:visible}.swagger-ui .model-hint{position:absolute;top:-1.8em;visibility:hidden;padding:.1em .5em;white-space:nowrap;color:#ebebeb;border-radius:4px;background:rgba(0,0,0,.7)}.swagger-ui .model p{margin:0 0 1em}.swagger-ui section.models{margin:30px 0;border:1px solid rgba(59,65,81,.3);border-radius:4px}.swagger-ui section.models.is-open{padding:0 0 20px}.swagger-ui section.models.is-open h4{margin:0 0 5px;border-bottom:1px solid rgba(59,65,81,.3)}.swagger-ui section.models h4{font-size:16px;display:flex;align-items:center;margin:0;padding:10px 20px 10px 10px;cursor:pointer;transition:all .2s;font-family:sans-serif;color:#606060}.swagger-ui section.models h4 svg{transition:all .4s}.swagger-ui section.models h4 span{flex:1}.swagger-ui section.models h4:hover{background:rgba(0,0,0,.02)}.swagger-ui section.models h5{font-size:16px;margin:0 0 10px;font-family:sans-serif;color:#707070}.swagger-ui section.models .model-jump-to-path{position:relative;top:5px}.swagger-ui section.models .model-container{margin:0 20px 15px;position:relative;transition:all .5s;border-radius:4px;background:rgba(0,0,0,.05)}.swagger-ui section.models .model-container:hover{background:rgba(0,0,0,.07)}.swagger-ui section.models .model-container:first-of-type{margin:20px}.swagger-ui section.models .model-container:last-of-type{margin:0 20px}.swagger-ui section.models .model-container .models-jump-to-path{position:absolute;top:8px;right:5px;opacity:.65}.swagger-ui section.models .model-box{background:none}.swagger-ui .model-box{padding:10px;display:inline-block;border-radius:4px;background:rgba(0,0,0,.1)}.swagger-ui .model-box .model-jump-to-path{position:relative;top:4px}.swagger-ui .model-box.deprecated{opacity:.5}.swagger-ui .model-title{font-size:16px;font-family:sans-serif;color:#505050}.swagger-ui .model-deprecated-warning{font-size:16px;font-weight:600;margin-right:1em;font-family:sans-serif;color:#f93e3e}.swagger-ui span>span.model .brace-close{padding:0 0 0 10px}.swagger-ui .prop-name{display:inline-block;margin-right:1em}.swagger-ui .prop-type{color:#55a}.swagger-ui .prop-enum{display:block}.swagger-ui .prop-format{color:#606060}.swagger-ui .servers>label{font-size:12px;margin:-20px 15px 0 0;font-family:sans-serif;color:#3b4151}.swagger-ui .servers>label select{min-width:130px;max-width:100%}.swagger-ui .servers h4.message{padding-bottom:2em}.swagger-ui .servers table tr{width:30em}.swagger-ui .servers table td{display:inline-block;max-width:15em;vertical-align:middle;padding-top:10px;padding-bottom:10px}.swagger-ui .servers table td:first-of-type{padding-right:2em}.swagger-ui .servers table td input{width:100%;height:100%}.swagger-ui .servers .computed-url{margin:2em 0}.swagger-ui .servers .computed-url code{display:inline-block;padding:4px;font-size:16px;margin:0 1em}.swagger-ui .servers-title{font-size:12px;font-weight:700}.swagger-ui .operation-servers h4.message{margin-bottom:2em}.swagger-ui table{width:100%;padding:0 10px;border-collapse:collapse}.swagger-ui table.model tbody tr td{padding:0;vertical-align:top}.swagger-ui table.model tbody tr td:first-of-type{width:174px;padding:0 0 0 2em}.swagger-ui table.headers td{font-size:12px;font-weight:300;vertical-align:middle;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui table tbody tr td{padding:10px 0 0;vertical-align:top}.swagger-ui table tbody tr td:first-of-type{max-width:20%;min-width:6em;padding:10px 0}.swagger-ui table thead tr td,.swagger-ui table thead tr th{font-size:12px;font-weight:700;padding:12px 0;text-align:left;border-bottom:1px solid rgba(59,65,81,.2);font-family:sans-serif;color:#3b4151}.swagger-ui .parameters-col_description{width:99%;margin-bottom:2em}.swagger-ui .parameters-col_description input[type=text]{width:100%;max-width:340px}.swagger-ui .parameters-col_description select{border-width:1px}.swagger-ui .parameter__name{font-size:16px;font-weight:400;margin-right:.75em;font-family:sans-serif;color:#3b4151}.swagger-ui .parameter__name.required{font-weight:700}.swagger-ui .parameter__name.required:after{font-size:10px;position:relative;top:-6px;padding:5px;content:"required";color:rgba(255,0,0,.6)}.swagger-ui .parameter__extension,.swagger-ui .parameter__in{font-size:12px;font-style:italic;font-family:monospace;font-weight:600;color:grey}.swagger-ui .parameter__deprecated{font-size:12px;font-style:italic;font-family:monospace;font-weight:600;color:red}.swagger-ui .parameter__empty_value_toggle{font-size:13px;padding-top:5px;padding-bottom:12px}.swagger-ui .parameter__empty_value_toggle input{margin-right:7px}.swagger-ui .parameter__empty_value_toggle.disabled{opacity:.7}.swagger-ui .table-container{padding:20px}.swagger-ui .response-col_description{width:99%}.swagger-ui .response-col_links{min-width:6em}.swagger-ui .topbar{padding:10px 0;background-color:#1b1b1b}.swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a{display:flex;align-items:center}.swagger-ui .topbar a{font-size:1.5em;font-weight:700;flex:1;max-width:300px;text-decoration:none;font-family:sans-serif;color:#fff}.swagger-ui .topbar a span{margin:0;padding:0 10px}.swagger-ui .topbar .download-url-wrapper{display:flex;flex:3;justify-content:flex-end}.swagger-ui .topbar .download-url-wrapper input[type=text]{width:100%;margin:0;border:2px solid #62a03f;border-radius:4px 0 0 4px;outline:none}.swagger-ui .topbar .download-url-wrapper .select-label{display:flex;align-items:center;width:100%;max-width:600px;margin:0;color:#f0f0f0}.swagger-ui .topbar .download-url-wrapper .select-label span{font-size:16px;flex:1;padding:0 10px 0 0;text-align:right}.swagger-ui .topbar .download-url-wrapper .select-label select{flex:2;width:100%;border:2px solid #62a03f;outline:none;box-shadow:none}.swagger-ui .topbar .download-url-wrapper .download-url-button{font-size:16px;font-weight:700;padding:4px 30px;border:none;border-radius:0 4px 4px 0;background:#62a03f;font-family:sans-serif;color:#fff}.swagger-ui .info{margin:50px 0}.swagger-ui .info hgroup.main{margin:0 0 20px}.swagger-ui .info hgroup.main a{font-size:12px}.swagger-ui .info pre{font-size:14px}.swagger-ui .info li,.swagger-ui .info p,.swagger-ui .info table{font-size:14px;font-family:sans-serif;color:#3b4151}.swagger-ui .info h1,.swagger-ui .info h2,.swagger-ui .info h3,.swagger-ui .info h4,.swagger-ui .info h5{font-family:sans-serif;color:#3b4151}.swagger-ui .info a{font-size:14px;transition:all .4s;font-family:sans-serif;color:#4990e2}.swagger-ui .info a:hover{color:#1f69c0}.swagger-ui .info>div{margin:0 0 5px}.swagger-ui .info .base-url{font-size:12px;font-weight:300!important;margin:0;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .info .title{font-size:36px;margin:0;font-family:sans-serif;color:#3b4151}.swagger-ui .info .title small{font-size:10px;position:relative;top:-5px;display:inline-block;margin:0 0 0 5px;padding:2px 4px;vertical-align:super;border-radius:57px;background:#7d8492}.swagger-ui .info .title small pre{margin:0;padding:0;font-family:sans-serif;color:#fff}.swagger-ui .auth-btn-wrapper{display:flex;padding:10px 0;justify-content:center}.swagger-ui .auth-btn-wrapper .btn-done{margin-right:1em}.swagger-ui .auth-wrapper{display:flex;flex:1;justify-content:flex-end}.swagger-ui .auth-wrapper .authorize{padding-right:20px;margin-right:10px}.swagger-ui .auth-container{margin:0 0 10px;padding:10px 20px;border-bottom:1px solid #ebebeb}.swagger-ui .auth-container:last-of-type{margin:0;padding:10px 20px;border:0}.swagger-ui .auth-container h4{margin:5px 0 15px!important}.swagger-ui .auth-container .wrapper{margin:0;padding:0}.swagger-ui .auth-container input[type=password],.swagger-ui .auth-container input[type=text]{min-width:230px}.swagger-ui .auth-container .errors{font-size:12px;padding:10px;border-radius:4px;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .scopes h2{font-size:14px;font-family:sans-serif;color:#3b4151}.swagger-ui .scope-def{padding:0 0 20px}.swagger-ui .errors-wrapper{margin:20px;padding:10px 20px;-webkit-animation:scaleUp .5s;animation:scaleUp .5s;border:2px solid #f93e3e;border-radius:4px;background:rgba(249,62,62,.1)}.swagger-ui .errors-wrapper .error-wrapper{margin:0 0 10px}.swagger-ui .errors-wrapper .errors h4{font-size:14px;margin:0;font-family:monospace;font-weight:600;color:#3b4151}.swagger-ui .errors-wrapper .errors small{color:#606060}.swagger-ui .errors-wrapper hgroup{display:flex;align-items:center}.swagger-ui .errors-wrapper hgroup h4{font-size:20px;margin:0;flex:1;font-family:sans-serif;color:#3b4151}@-webkit-keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes scaleUp{0%{-webkit-transform:scale(.8);transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.swagger-ui .Resizer.vertical.disabled{display:none}.swagger-ui .markdown p,.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown p,.swagger-ui .renderedMarkdown pre{margin:1em auto}.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown pre{color:#000;font-weight:400;white-space:pre-wrap;background:none;padding:0}.swagger-ui .markdown code,.swagger-ui .renderedMarkdown code{font-size:14px;padding:5px 7px;border-radius:4px;background:rgba(0,0,0,.05);font-family:monospace;font-weight:600;color:#9012fe}.swagger-ui .markdown pre>code,.swagger-ui .renderedMarkdown pre>code{display:block}
+
+/*# sourceMappingURL=swagger-ui.css.map*/ \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/images.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/images.e2e-spec.ts
new file mode 100644
index 00000000..10d71fcc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/images.e2e-spec.ts
@@ -0,0 +1,34 @@
+import { Helper } from '../helper.po';
+import { ImagesPage } from './images.po';
+
+describe('Images page', () => {
+ let page: ImagesPage;
+
+ beforeAll(() => {
+ page = new ImagesPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Images');
+ });
+
+ it('should show three tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(3);
+ });
+
+ it('should show text for all tabs', () => {
+ expect(Helper.getTabText(0)).toEqual('Images');
+ expect(Helper.getTabText(1)).toEqual('Trash');
+ expect(Helper.getTabText(2)).toEqual('Overall Performance');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/images.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/images.po.ts
new file mode 100644
index 00000000..b3fb2f1e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/images.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class ImagesPage {
+ navigateTo() {
+ return browser.get('/#/block/rbd');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.e2e-spec.ts
new file mode 100644
index 00000000..82d1d482
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { IscsiPage } from './iscsi.po';
+
+describe('Iscsi Page', () => {
+ let page: IscsiPage;
+
+ beforeAll(() => {
+ page = new IscsiPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Overview');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.po.ts
new file mode 100644
index 00000000..79eb94c4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/iscsi.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class IscsiPage {
+ navigateTo() {
+ return browser.get('/#/block/iscsi');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.e2e-spec.ts
new file mode 100644
index 00000000..e15cb53e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.e2e-spec.ts
@@ -0,0 +1,34 @@
+import { Helper } from '../helper.po';
+import { MirroringPage } from './mirroring.po';
+
+describe('Mirroring page', () => {
+ let page: MirroringPage;
+
+ beforeAll(() => {
+ page = new MirroringPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Mirroring');
+ });
+
+ it('should show three tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(3);
+ });
+
+ it('should show text for all tabs', () => {
+ expect(Helper.getTabText(0)).toEqual('Issues');
+ expect(Helper.getTabText(1)).toEqual('Syncing');
+ expect(Helper.getTabText(2)).toEqual('Ready');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.po.ts
new file mode 100644
index 00000000..f4a8baeb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class MirroringPage {
+ navigateTo() {
+ return browser.get('/#/block/mirroring');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.e2e-spec.ts
new file mode 100644
index 00000000..e8cc7113
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { ConfigurationPage } from './configuration.po';
+
+describe('Configuration page', () => {
+ let page: ConfigurationPage;
+
+ beforeAll(() => {
+ page = new ConfigurationPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Configuration');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.po.ts
new file mode 100644
index 00000000..b23a078a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/configuration.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class ConfigurationPage {
+ navigateTo() {
+ return browser.get('/#/configuration');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.e2e-spec.ts
new file mode 100644
index 00000000..2c1b004b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { CrushMapPage } from './crush-map.po';
+
+describe('CRUSH map page', () => {
+ let page: CrushMapPage;
+
+ beforeAll(() => {
+ page = new CrushMapPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'CRUSH map');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.po.ts
new file mode 100644
index 00000000..e4d54c61
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class CrushMapPage {
+ navigateTo() {
+ return browser.get('/#/crush-map');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.e2e-spec.ts
new file mode 100644
index 00000000..f0b8a0e2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.e2e-spec.ts
@@ -0,0 +1,36 @@
+import { Helper } from '../helper.po';
+import { HostsPage } from './hosts.po';
+
+describe('Hosts page', () => {
+ let page: HostsPage;
+
+ beforeAll(() => {
+ page = new HostsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Hosts');
+ });
+
+ it('should show two tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(2);
+ });
+
+ it('should show hosts list tab at first', () => {
+ expect(Helper.getTabText(0)).toEqual('Hosts List');
+ });
+
+ it('should show overall performance as a second tab', () => {
+ expect(Helper.getTabText(1)).toEqual('Overall Performance');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.po.ts
new file mode 100644
index 00000000..6a90ef7f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class HostsPage {
+ navigateTo() {
+ return browser.get('/#/hosts');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.e2e-spec.ts
new file mode 100644
index 00000000..45076e66
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.e2e-spec.ts
@@ -0,0 +1,36 @@
+import { Helper } from '../helper.po';
+import { LogsPage } from './logs.po';
+
+describe('Logs page', () => {
+ let page: LogsPage;
+
+ beforeAll(() => {
+ page = new LogsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Logs');
+ });
+
+ it('should show two tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(2);
+ });
+
+ it('should show cluster logs tab at first', () => {
+ expect(Helper.getTabText(0)).toEqual('Cluster Logs');
+ });
+
+ it('should show audit logs as a second tab', () => {
+ expect(Helper.getTabText(1)).toEqual('Audit Logs');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.po.ts
new file mode 100644
index 00000000..14677945
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/logs.po.ts
@@ -0,0 +1,9 @@
+import { browser } from 'protractor';
+
+browser.ignoreSynchronization = true;
+
+export class LogsPage {
+ navigateTo() {
+ return browser.get('/#/logs');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts
new file mode 100644
index 00000000..629b791f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { ManagerModulesPage } from './mgr-modules.po';
+
+describe('Manager modules page', () => {
+ let page: ManagerModulesPage;
+
+ beforeAll(() => {
+ page = new ManagerModulesPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Manager modules');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts
new file mode 100644
index 00000000..208f3033
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class ManagerModulesPage {
+ navigateTo() {
+ return browser.get('/#/mgr-modules');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.e2e-spec.ts
new file mode 100644
index 00000000..5b2676fa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { MonitorsPage } from './monitors.po';
+
+describe('Monitors page', () => {
+ let page: MonitorsPage;
+
+ beforeAll(() => {
+ page = new MonitorsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Monitors');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.po.ts
new file mode 100644
index 00000000..53159d30
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/monitors.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class MonitorsPage {
+ navigateTo() {
+ return browser.get('/#/monitor');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.e2e-spec.ts
new file mode 100644
index 00000000..61cb0c03
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.e2e-spec.ts
@@ -0,0 +1,36 @@
+import { Helper } from '../helper.po';
+import { OSDsPage } from './osds.po';
+
+describe('OSDs page', () => {
+ let page: OSDsPage;
+
+ beforeAll(() => {
+ page = new OSDsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'OSDs');
+ });
+
+ it('should show two tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(2);
+ });
+
+ it('should show OSDs list tab at first', () => {
+ expect(Helper.getTabText(0)).toEqual('OSDs List');
+ });
+
+ it('should show overall performance as a second tab', () => {
+ expect(Helper.getTabText(1)).toEqual('Overall Performance');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.po.ts
new file mode 100644
index 00000000..08e41438
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/osds.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class OSDsPage {
+ navigateTo() {
+ return browser.get('/#/osd');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.e2e-spec.ts
new file mode 100644
index 00000000..9c39a925
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { FilesystemsPage } from './filesystems.po';
+
+describe('Filesystems page', () => {
+ let page: FilesystemsPage;
+
+ beforeAll(() => {
+ page = new FilesystemsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Filesystems');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.po.ts
new file mode 100644
index 00000000..4f763814
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/filesystems/filesystems.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class FilesystemsPage {
+ navigateTo() {
+ return browser.get('/#/cephfs');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts
new file mode 100644
index 00000000..cd6b8f67
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts
@@ -0,0 +1,48 @@
+import { $, $$, browser, ElementFinder } from 'protractor';
+
+export class Helper {
+ static EC = browser.ExpectedConditions;
+ static TIMEOUT = 10000;
+
+ /**
+ * Checks if there are any errors on the browser
+ *
+ * @static
+ * @memberof Helper
+ */
+ static checkConsole() {
+ browser
+ .manage()
+ .logs()
+ .get('browser')
+ .then(function(browserLog) {
+ browserLog = browserLog.filter((log) => {
+ return log.level.value > 900; // SEVERE level
+ });
+
+ if (browserLog.length > 0) {
+ console.log('\n log: ' + require('util').inspect(browserLog));
+ }
+
+ expect(browserLog.length).toEqual(0);
+ });
+ }
+
+ static getBreadcrumb() {
+ return $('.breadcrumb-item.active');
+ }
+
+ static getTabText(idx) {
+ return $$('.nav.nav-tabs li')
+ .get(idx)
+ .getText();
+ }
+
+ static getTabsCount() {
+ return $$('.nav.nav-tabs li').count();
+ }
+
+ static waitTextToBePresent(elem: ElementFinder, text: string, message?: string) {
+ return browser.wait(Helper.EC.textToBePresentInElement(elem, text), Helper.TIMEOUT, message);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.e2e-spec.ts
new file mode 100644
index 00000000..988737a6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.e2e-spec.ts
@@ -0,0 +1,24 @@
+import { Helper } from '../helper.po';
+import { NfsPage } from './nfs.po';
+
+describe('Nfs page', () => {
+ let page: NfsPage;
+
+ beforeAll(() => {
+ page = new NfsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb test', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'NFS');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.po.ts
new file mode 100644
index 00000000..fe6f342e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/nfs/nfs.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class NfsPage {
+ navigateTo() {
+ return browser.get('/#/nfs');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.e2e-spec.ts
new file mode 100644
index 00000000..5d68b0fe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.e2e-spec.ts
@@ -0,0 +1,36 @@
+import { Helper } from '../helper.po';
+import { PoolsPage } from './pools.po';
+
+describe('Pools page', () => {
+ let page: PoolsPage;
+
+ beforeAll(() => {
+ page = new PoolsPage();
+ });
+
+ afterEach(() => {
+ Helper.checkConsole();
+ });
+
+ describe('breadcrumb and tab tests', () => {
+ beforeAll(() => {
+ page.navigateTo();
+ });
+
+ it('should open and show breadcrumb', () => {
+ Helper.waitTextToBePresent(Helper.getBreadcrumb(), 'Pools');
+ });
+
+ it('should show two tabs', () => {
+ expect(Helper.getTabsCount()).toEqual(2);
+ });
+
+ it('should show pools list tab at first', () => {
+ expect(Helper.getTabText(0)).toEqual('Pools List');
+ });
+
+ it('should show overall performance as a second tab', () => {
+ expect(Helper.getTabText(1)).toEqual('Overall Performance');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.po.ts
new file mode 100644
index 00000000..3682c671
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/pools/pools.po.ts
@@ -0,0 +1,7 @@
+import { browser } from 'protractor';
+
+export class PoolsPage {
+ navigateTo() {
+ return browser.get('/#/pool');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/e2e/tsconfig.e2e.json b/src/pybind/mgr/dashboard/frontend/e2e/tsconfig.e2e.json
new file mode 100644
index 00000000..e3d6ae76
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/e2e/tsconfig.e2e.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/e2e",
+ "baseUrl": "./",
+ "module": "commonjs",
+ "target": "es5",
+ "types": [
+ "jasmine",
+ "jasminewd2",
+ "node"
+ ],
+ "noEmit": true
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/environment.build.js b/src/pybind/mgr/dashboard/frontend/environment.build.js
new file mode 100755
index 00000000..54253fbe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/environment.build.js
@@ -0,0 +1,74 @@
+var replace = require('replace-in-file');
+var buildDate = new Date();
+var copyrightYear = buildDate.getFullYear();
+const optionsNewYear = {
+ files:[
+ 'src/environments/environment.ts',
+ 'src/environments/environment.prod.ts'
+ ],
+ from: /{COPYRIGHT_YEAR}/g,
+ to: copyrightYear,
+ allowEmptyPaths: false,
+};
+
+const optionsOldYear = {
+ files:[
+ 'src/environments/environment.ts',
+ 'src/environments/environment.prod.ts'
+ ],
+ from: /year: '(.*)'/g,
+ to: "year: '{COPYRIGHT_YEAR}'",
+ allowEmptyPaths: false,
+};
+
+const optionsNewProd = {
+ files:[
+ 'src/environments/environment.prod.ts'
+ ],
+ from: /'{PRODUCTION}'/g,
+ to: true,
+ allowEmptyPaths: false,
+};
+
+const optionsNewDev = {
+ files:[
+ 'src/environments/environment.ts'
+ ],
+ from: /'{PRODUCTION}'/g,
+ to: false,
+ allowEmptyPaths: false,
+};
+
+const optionsOldProd = {
+ files:[
+ 'src/environments/environment.prod.ts',
+ 'src/environments/environment.ts'
+ ],
+ from: /production: (.*)/g,
+ to: "production: '{PRODUCTION}',",
+ allowEmptyPaths: false,
+};
+
+const optionsDefaultLang = {
+ files: [
+ 'src/environments/environment.prod.ts',
+ 'src/environments/environment.ts'
+ ],
+ from: /'{DEFAULT_LANG}'/g,
+ to: `'${process.env.npm_package_config_locale}'`,
+ allowEmptyPaths: false
+}
+
+try {
+ let changeOldYearFiles = replace.sync(optionsOldYear);
+ let changeNewYearFiles = replace.sync(optionsNewYear);
+ let changeOldProdFiles = replace.sync(optionsOldProd);
+ let changeProdFiles = replace.sync(optionsNewProd);
+ let changeDevFiles = replace.sync(optionsNewDev);
+ let changeDefaultLangFiles = replace.sync(optionsDefaultLang);
+ console.log('Environment variables have been set');
+}
+catch (error) {
+ console.error('Error occurred:', error);
+ throw error
+}
diff --git a/src/pybind/mgr/dashboard/frontend/html-linter.config.json b/src/pybind/mgr/dashboard/frontend/html-linter.config.json
new file mode 100644
index 00000000..bf91475d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/html-linter.config.json
@@ -0,0 +1,12 @@
+{
+ "files": ["src/**/*.html"],
+ "indentation": {
+ "char": "space",
+ "number": 2
+ },
+ "attributes": {
+ "quotes": "double",
+ "whitespace": 0,
+ "vertical-align": true
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/i18n.config.json b/src/pybind/mgr/dashboard/frontend/i18n.config.json
new file mode 100644
index 00000000..111164a4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/i18n.config.json
@@ -0,0 +1,12 @@
+{
+ "sourceDirectory": "src/locale",
+ "targetDirectory": "src/locale",
+ "sourceFile": "messages.xlf",
+ "languages": "cs,de-DE,es-ES,fr-FR,id-ID,it-IT,ja-JP,ko-KR,pl-PL,pt-BR,zh-CN,zh-TW",
+ "organization": "ceph",
+ "project": "ceph-dashboard",
+ "resource": "Nautilus:nautilus",
+ "removeUnusedIds": true,
+ "automate": true,
+ "quiet": false
+}
diff --git a/src/pybind/mgr/dashboard/frontend/package-lock.json b/src/pybind/mgr/dashboard/frontend/package-lock.json
new file mode 100644
index 00000000..a85e7267
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/package-lock.json
@@ -0,0 +1,15346 @@
+{
+ "name": "ceph-dashboard",
+ "version": "0.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.9.tgz",
+ "integrity": "sha512-EAFtCs9dsGhpMRC45PoYsrkiExpWz9Ax15qXfzwdDRacz5DmdOVt+QpkLW1beUOwiyj/bhFyj23eaONK2RTn/w==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.9",
+ "rxjs": "6.3.3"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/build-angular": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.13.9.tgz",
+ "integrity": "sha512-onh07LhdxotDFjja0KKsDWNCwgpM/ymuRr5h0e+vT4AgklP2Uioz1CpzVOgxPIKkdVdGR9QgDinVsWAmY90J8g==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.13.9",
+ "@angular-devkit/build-optimizer": "0.13.9",
+ "@angular-devkit/build-webpack": "0.13.9",
+ "@angular-devkit/core": "7.3.9",
+ "@ngtools/webpack": "7.3.9",
+ "ajv": "6.9.1",
+ "autoprefixer": "9.4.6",
+ "circular-dependency-plugin": "5.0.2",
+ "clean-css": "4.2.1",
+ "copy-webpack-plugin": "4.6.0",
+ "file-loader": "3.0.1",
+ "glob": "7.1.3",
+ "istanbul-instrumenter-loader": "3.0.1",
+ "karma-source-map-support": "1.3.0",
+ "less": "3.9.0",
+ "less-loader": "4.1.0",
+ "license-webpack-plugin": "2.1.0",
+ "loader-utils": "1.2.3",
+ "mini-css-extract-plugin": "0.5.0",
+ "minimatch": "3.0.4",
+ "node-sass": "4.12.0",
+ "open": "6.0.0",
+ "parse5": "4.0.0",
+ "postcss": "7.0.14",
+ "postcss-import": "12.0.1",
+ "postcss-loader": "3.0.0",
+ "raw-loader": "1.0.0",
+ "rxjs": "6.3.3",
+ "sass-loader": "7.1.0",
+ "semver": "5.6.0",
+ "source-map-loader": "0.2.4",
+ "source-map-support": "0.5.10",
+ "speed-measure-webpack-plugin": "1.3.1",
+ "stats-webpack-plugin": "0.7.0",
+ "style-loader": "0.23.1",
+ "stylus": "0.54.5",
+ "stylus-loader": "3.0.2",
+ "terser-webpack-plugin": "1.2.2",
+ "tree-kill": "1.2.1",
+ "webpack": "4.29.0",
+ "webpack-dev-middleware": "3.5.1",
+ "webpack-dev-server": "3.1.14",
+ "webpack-merge": "4.2.1",
+ "webpack-sources": "1.3.0",
+ "webpack-subresource-integrity": "1.1.0-rc.6"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/build-optimizer": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.13.9.tgz",
+ "integrity": "sha512-GQtCntthQHSBv5l1ZY5p00JOECb/WcE1qUBo5kFjp84z0fszDkhOy52M1kcWCX4PFzJaY4DKk58hbUE/2UN0jw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "1.2.3",
+ "source-map": "0.5.6",
+ "typescript": "3.2.4",
+ "webpack-sources": "1.3.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ }
+ }
+ },
+ "@angular-devkit/build-webpack": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.13.9.tgz",
+ "integrity": "sha512-6ypu6pzNmQxzATF4rTWEhGSl5hyGQ8a/3aCZF/ux+XGc3d4hi2HW+NWlDm1UEna6ZjNtgEPlgfP4q8BKrjRmfA==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.13.9",
+ "@angular-devkit/core": "7.3.9",
+ "rxjs": "6.3.3"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "7.3.9",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.9.tgz",
+ "integrity": "sha512-SaxD+nKFW3iCBKsxNR7+66J30EexW/y7tm8m5AvUH+GwSAgIj0ZYmRUzFEPggcaLVA4WnE/YWqIXZMJW5dT7gw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.9.1",
+ "chokidar": "2.0.4",
+ "fast-json-stable-stringify": "2.0.0",
+ "rxjs": "6.3.3",
+ "source-map": "0.7.3"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/schematics": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.3.3.tgz",
+ "integrity": "sha512-SdDq9eKwceb6WLwci1fywtZ/kARR5CYyzi5dZIR1lOxrz00682uUBqH/X39mKdqc6eVqR7rtPceqNm6nQpOIMg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.3",
+ "rxjs": "6.3.3"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.3.tgz",
+ "integrity": "sha512-fosULDtMoDWrOyUzTmBkJccOy7zodo02kENyKai7vOv9EWfv9jytkVdNc+jl0ys9OE2QadvSYBo49jhnZxFXfQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.9.1",
+ "chokidar": "2.0.4",
+ "fast-json-stable-stringify": "2.0.0",
+ "rxjs": "6.3.3",
+ "source-map": "0.7.3"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular/animations": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.6.tgz",
+ "integrity": "sha512-ICKPS+bKabhQNqnPoVZegUAhgNPbVFlrxHoJ+ZZeVGxw5iBE8TnP3a2sRvakdMTKhykDlwVVGMKLxu2Y34uhmg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/cli": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.3.3.tgz",
+ "integrity": "sha512-dw1iBOYbQRN2l/BH21zDItDFC9KXgqeK0A/koDLDukjrUAnW/XVATjxGi+7EPlTpABTFhqu/rHZDy8aBglLDXQ==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.13.3",
+ "@angular-devkit/core": "7.3.3",
+ "@angular-devkit/schematics": "7.3.3",
+ "@schematics/angular": "7.3.3",
+ "@schematics/update": "0.13.3",
+ "@yarnpkg/lockfile": "1.1.0",
+ "ini": "1.3.5",
+ "inquirer": "6.2.1",
+ "npm-package-arg": "6.1.0",
+ "opn": "5.4.0",
+ "pacote": "9.4.0",
+ "semver": "5.6.0",
+ "symbol-observable": "1.2.0"
+ },
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.3.tgz",
+ "integrity": "sha512-89VL75bq3+h3m0jhzWNqXqW+HQcrihnM3i6eiUE6P81LcllP159JMlusAvB1LHLNc6Cc62wTq4BJr7KDILkPOA==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.3",
+ "rxjs": "6.3.3"
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.3.tgz",
+ "integrity": "sha512-fosULDtMoDWrOyUzTmBkJccOy7zodo02kENyKai7vOv9EWfv9jytkVdNc+jl0ys9OE2QadvSYBo49jhnZxFXfQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.9.1",
+ "chokidar": "2.0.4",
+ "fast-json-stable-stringify": "2.0.0",
+ "rxjs": "6.3.3",
+ "source-map": "0.7.3"
+ }
+ },
+ "opn": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz",
+ "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular/common": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.6.tgz",
+ "integrity": "sha512-jzWUgsgS0dmPy7yDHX4qCqVpt7ZZmHhApgkg5RkzTAlp+0cvZ/KsDpBgHXnZUIfmk/5g1/EtTbkbClgp1kCkIg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.6.tgz",
+ "integrity": "sha512-GXdvgH8oxK8HRh/FelN3U5p0tsTUwGh8b/iuuJKaunBSSDDjIy7pPnn3zT+lN4YeEi6qN1XWudt+HpWHYHyymg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler-cli": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.6.tgz",
+ "integrity": "sha512-sB0Bc5hE1zoXKwK4E9pC/UblCEHi3CwLBT/1nmVMYBdGzSSUxO4FaioJi+SCeGJJ+kk85Vny2up08gnupmLKqA==",
+ "dev": true,
+ "requires": {
+ "canonical-path": "1.0.0",
+ "chokidar": "^2.1.1",
+ "convert-source-map": "^1.5.1",
+ "dependency-graph": "^0.7.2",
+ "magic-string": "^0.25.0",
+ "minimist": "^1.2.0",
+ "reflect-metadata": "^0.1.2",
+ "shelljs": "^0.8.1",
+ "source-map": "^0.6.1",
+ "tslib": "^1.9.0",
+ "yargs": "9.0.1"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "dev": true,
+ "requires": {
+ "pify": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^2.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^2.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz",
+ "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0",
+ "cliui": "^3.2.0",
+ "decamelize": "^1.1.1",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "read-pkg-up": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^7.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
+ "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "@angular/core": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.6.tgz",
+ "integrity": "sha512-MZg17DWH1KUoDa9wFYK9Z+3F7DnUW2DjSwGyIi9U4cB54IWFhgt1JsA0mcuSYuRSRpvwaArCDC2AN90f+0/EFA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/forms": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.6.tgz",
+ "integrity": "sha512-At72AJNGe+Zzmryb7DDIG+iws7zKdgZx/eEVjZ/Obu/yREefbZY4R7q83U90Vljtn97BwJPx9ur9ttxE9WpnlA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/http": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.6.tgz",
+ "integrity": "sha512-B5TC8JFW/I+ms5iJthGjf/eg1tKKqpO6yrOpDSQofHG7Dd4dozyGXGznFJTRFfNda5rku61/qnQaa8SyQyuplQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/language-service": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.2.6.tgz",
+ "integrity": "sha512-iFKgaat5MZlixsO5dqy1Km3tb4q3iAU+ZPMJCk7DN419aizF38UFnQY1gCYkw3dxZLZGIkXnwy8szGXUEhra/A==",
+ "dev": true
+ },
+ "@angular/platform-browser": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.6.tgz",
+ "integrity": "sha512-VE4yS4l8Cdx6DlvrbOFOZDKmQuyz1RhVcshgSt9hKlkehvAXMtX8Sqnp6po7z0aPykTh0TZZtMtLEerkFEe+DA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/platform-browser-dynamic": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.6.tgz",
+ "integrity": "sha512-/co/q4v11nKin2MFscCMZyixbW103I2FxbPgCAYBN5NSvfIwTrt5J6xWmDoKJ8HkZBqL3R9B+uhYdzsRN/pQxg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/router": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.6.tgz",
+ "integrity": "sha512-ayMVor4Mu4wk7JKpt51UxHovnLB4munZ8ELR1CA4w+s0rJsSSwyB4WXElC+DbgCyl7BYLAaGui2c5DbTAJ9jlw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+ "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.0.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.4.tgz",
+ "integrity": "sha512-Rm0HGw101GY8FTzpWSyRbki/jzq+/PkNQJ+nSulrdY6gFGOsNseCqD6KHRYe2E+EdzuBdr2pxCp6s4Uk6eJ+XQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.6.4",
+ "@babel/helpers": "^7.6.2",
+ "@babel/parser": "^7.6.4",
+ "@babel/template": "^7.6.0",
+ "@babel/traverse": "^7.6.3",
+ "@babel/types": "^7.6.3",
+ "convert-source-map": "^1.1.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "json5": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz",
+ "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.4.tgz",
+ "integrity": "sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.6.3",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
+ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/template": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
+ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
+ "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
+ "dev": true
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
+ "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.4"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz",
+ "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.6.0",
+ "@babel/traverse": "^7.6.2",
+ "@babel/types": "^7.6.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
+ "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.4.tgz",
+ "integrity": "sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==",
+ "dev": true
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
+ "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
+ "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/template": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz",
+ "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.6.0",
+ "@babel/types": "^7.6.0"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.3.tgz",
+ "integrity": "sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.6.3",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.4.4",
+ "@babel/parser": "^7.6.3",
+ "@babel/types": "^7.6.3",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz",
+ "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ },
+ "dependencies": {
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ }
+ }
+ },
+ "@cnakazawa/watch": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz",
+ "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==",
+ "dev": true,
+ "requires": {
+ "exec-sh": "^0.3.2",
+ "minimist": "^1.2.0"
+ }
+ },
+ "@compodoc/compodoc": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.10.tgz",
+ "integrity": "sha512-dBAHD2gdIVYIa2a0Y5/Pgyoy/XQDLnqC3lUrd6Crp9HnCTMXIfHWygOUTo0u8wWhxqXhLo9ZMwGRsC9tK61dvA==",
+ "dev": true,
+ "requires": {
+ "@compodoc/ngd-transformer": "^2.0.0",
+ "chalk": "^2.4.2",
+ "cheerio": "^1.0.0-rc.3",
+ "chokidar": "^3.0.2",
+ "colors": "^1.3.3",
+ "commander": "^2.20.0",
+ "cosmiconfig": "^5.2.1",
+ "fancy-log": "^1.3.3",
+ "findit2": "^2.2.3",
+ "fs-extra": "^8.0.1",
+ "glob": "^7.1.4",
+ "handlebars": "^4.1.2",
+ "html-entities": "^1.2.1",
+ "i18next": "^17.0.3",
+ "inside": "^1.0.0",
+ "json5": "^2.1.0",
+ "live-server": "^1.2.1",
+ "lodash": "^4.17.11",
+ "lunr": "^2.3.6",
+ "marked": "^0.7.0",
+ "minimist": "^1.2.0",
+ "opencollective-postinstall": "^2.0.2",
+ "os-name": "^3.1.0",
+ "pdfmake": "^0.1.57",
+ "semver": "^6.1.1",
+ "traverse": "^0.6.6",
+ "ts-simple-ast": "12.4.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
+ "dev": true
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "chokidar": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.2.2.tgz",
+ "integrity": "sha512-bw3pm7kZ2Wa6+jQWYP/c7bAZy3i4GwiIiMO2EeRjrE48l8vBqC/WvFhSF0xyM8fQiPEGvwMY/5bqDG7sSEOuhg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.1",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.2.0"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "fsevents": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.1.tgz",
+ "integrity": "sha512-4FRPXWETxtigtJW/gxzEDsX1LVbPAM93VleB83kZB+ellqbHMkyt2aJfuzNLRvFPnGi6bcE5SvfxgbXPeKteJw==",
+ "dev": true,
+ "optional": true
+ },
+ "glob": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
+ "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+ "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz",
+ "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
+ "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.0.4"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "@compodoc/ngd-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@compodoc/ngd-core/-/ngd-core-2.0.0.tgz",
+ "integrity": "sha512-6HpYvXRZBdIYFojWxW5EVNkhYPmblytCve62CNoYBSWfy++vTGH7Ypg2Bhjg2CsqeV8JOVxrPO7JM9M3MgWKEA==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^1.0.1",
+ "fancy-log": "^1.3.2",
+ "typescript": "^2.4.2"
+ },
+ "dependencies": {
+ "ansi-colors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
+ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "^0.1.0"
+ }
+ },
+ "typescript": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
+ "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
+ "dev": true
+ }
+ }
+ },
+ "@compodoc/ngd-transformer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@compodoc/ngd-transformer/-/ngd-transformer-2.0.0.tgz",
+ "integrity": "sha512-9J0KkmuuuvDHxH0oREgrgbqdEFqcltQXIBofeYdIyMKzI3A+pN1Ji4zfi7x1ql0Ax7qQKemp8XWP+cCpP0qY+w==",
+ "dev": true,
+ "requires": {
+ "@compodoc/ngd-core": "~2.0.0",
+ "dot": "^1.1.1",
+ "fs-extra": "^4.0.1",
+ "viz.js": "^1.8.0"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+ "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ }
+ }
+ },
+ "@dsherret/to-absolute-glob": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
+ "integrity": "sha1-H2R13IvZdM6gei2vOGSzF7HdMyw=",
+ "dev": true,
+ "requires": {
+ "is-absolute": "^1.0.0",
+ "is-negated-glob": "^1.0.0"
+ }
+ },
+ "@jest/console": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz",
+ "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==",
+ "dev": true,
+ "requires": {
+ "@jest/source-map": "^24.9.0",
+ "chalk": "^2.0.1",
+ "slash": "^2.0.0"
+ },
+ "dependencies": {
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ }
+ }
+ },
+ "@jest/core": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz",
+ "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^24.7.1",
+ "@jest/reporters": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.1.15",
+ "jest-changed-files": "^24.9.0",
+ "jest-config": "^24.9.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-regex-util": "^24.3.0",
+ "jest-resolve": "^24.9.0",
+ "jest-resolve-dependencies": "^24.9.0",
+ "jest-runner": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-snapshot": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-validate": "^24.9.0",
+ "jest-watcher": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "p-each-series": "^1.0.0",
+ "realpath-native": "^1.1.0",
+ "rimraf": "^2.5.4",
+ "slash": "^2.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "@jest/environment": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz",
+ "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==",
+ "dev": true,
+ "requires": {
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0"
+ }
+ },
+ "@jest/fake-timers": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz",
+ "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-mock": "^24.9.0"
+ }
+ },
+ "@jest/reporters": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz",
+ "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "glob": "^7.1.2",
+ "istanbul-lib-coverage": "^2.0.2",
+ "istanbul-lib-instrument": "^3.0.1",
+ "istanbul-lib-report": "^2.0.4",
+ "istanbul-lib-source-maps": "^3.0.1",
+ "istanbul-reports": "^2.2.6",
+ "jest-haste-map": "^24.9.0",
+ "jest-resolve": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-worker": "^24.6.0",
+ "node-notifier": "^5.4.2",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.0",
+ "string-length": "^2.0.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+ "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+ "dev": true,
+ "requires": {
+ "@babel/generator": "^7.4.0",
+ "@babel/parser": "^7.4.3",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.3",
+ "@babel/types": "^7.4.0",
+ "istanbul-lib-coverage": "^2.0.5",
+ "semver": "^6.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@jest/source-map": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz",
+ "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.1.15",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@jest/test-result": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz",
+ "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/istanbul-lib-coverage": "^2.0.0"
+ }
+ },
+ "@jest/test-sequencer": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz",
+ "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==",
+ "dev": true,
+ "requires": {
+ "@jest/test-result": "^24.9.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-runner": "^24.9.0",
+ "jest-runtime": "^24.9.0"
+ }
+ },
+ "@jest/transform": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz",
+ "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.1.0",
+ "@jest/types": "^24.9.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "chalk": "^2.0.1",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.1.15",
+ "jest-haste-map": "^24.9.0",
+ "jest-regex-util": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "pirates": "^4.0.1",
+ "realpath-native": "^1.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.1",
+ "write-file-atomic": "2.4.1"
+ },
+ "dependencies": {
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@jest/types": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz",
+ "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^1.1.1",
+ "@types/yargs": "^13.0.0"
+ }
+ },
+ "@mrmlnc/readdir-enhanced": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+ "dev": true,
+ "requires": {
+ "call-me-maybe": "^1.0.1",
+ "glob-to-regexp": "^0.3.0"
+ }
+ },
+ "@ngtools/webpack": {
+ "version": "7.3.9",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.9.tgz",
+ "integrity": "sha512-+ROpqfCXLdQwfP+UNDLk4p959ZrocpStkdd2Iy9CeOJ8yDkityqpstTwQC3oHzzu/95BiyZ0hrHbM6AsPPIvJg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.9",
+ "enhanced-resolve": "4.1.0",
+ "rxjs": "6.3.3",
+ "tree-kill": "1.2.1",
+ "webpack-sources": "1.3.0"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@ngx-translate/i18n-polyfill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@ngx-translate/i18n-polyfill/-/i18n-polyfill-1.0.0.tgz",
+ "integrity": "sha512-+UKmSr6cWBJiMDex6w2FwVjEeVnlEsINDGYvTgRaFRI3/IKZrsSVcfISDcBX2wWr6m4jumfOyCcimIl2TxcaoA==",
+ "requires": {
+ "glob": "7.1.2",
+ "tslib": "^1.9.0",
+ "yargs": "10.0.3"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+ "dev": true
+ },
+ "@schematics/angular": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.3.3.tgz",
+ "integrity": "sha512-HbH8vajYPka0xGcFAN5IUBx8n8SFMQLFb9di2dJCOBaEakbKVkk8qtOpil54oFQbx7DFCvutq/p0u42JfEbuMQ==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.3",
+ "@angular-devkit/schematics": "7.3.3",
+ "typescript": "3.2.4"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.3.tgz",
+ "integrity": "sha512-fosULDtMoDWrOyUzTmBkJccOy7zodo02kENyKai7vOv9EWfv9jytkVdNc+jl0ys9OE2QadvSYBo49jhnZxFXfQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.9.1",
+ "chokidar": "2.0.4",
+ "fast-json-stable-stringify": "2.0.0",
+ "rxjs": "6.3.3",
+ "source-map": "0.7.3"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@schematics/update": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.13.3.tgz",
+ "integrity": "sha512-sCOFQ62dd7VdEGiSUJNZshNI31ODwpJjn2WIvFgZLt6sdHHun67s/JOvOUq4mxx6I74oD6RPJPF4AP5sigVxxg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "7.3.3",
+ "@angular-devkit/schematics": "7.3.3",
+ "@yarnpkg/lockfile": "1.1.0",
+ "ini": "1.3.5",
+ "pacote": "9.4.0",
+ "rxjs": "6.3.3",
+ "semver": "5.6.0",
+ "semver-intersect": "1.4.0"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.3.tgz",
+ "integrity": "sha512-fosULDtMoDWrOyUzTmBkJccOy7zodo02kENyKai7vOv9EWfv9jytkVdNc+jl0ys9OE2QadvSYBo49jhnZxFXfQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.9.1",
+ "chokidar": "2.0.4",
+ "fast-json-stable-stringify": "2.0.0",
+ "rxjs": "6.3.3",
+ "source-map": "0.7.3"
+ }
+ },
+ "rxjs": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+ "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@swimlane/ngx-datatable": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/@swimlane/ngx-datatable/-/ngx-datatable-14.0.0.tgz",
+ "integrity": "sha512-zgRY58MzTpg9Jb575cg0O87mLtXYi6fx7NLRPRHdQ/FqH9mKjZ3i7+OjqtR8/w3KRmFP2Hnkmx52VzldZIKspg=="
+ },
+ "@types/babel__core": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz",
+ "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "@types/babel__generator": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.0.tgz",
+ "integrity": "sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__template": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz",
+ "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__traverse": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz",
+ "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "@types/istanbul-lib-coverage": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
+ "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==",
+ "dev": true
+ },
+ "@types/istanbul-lib-report": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz",
+ "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "@types/istanbul-reports": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz",
+ "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "*",
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "@types/jasmine": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.9.tgz",
+ "integrity": "sha512-vw3VyFPa9mlba6NZPBZC3q2Zrnkgy5xuCVI43/tTLX6umdYrYvcFtQUKi2zH3PjFZQ9XCxNM/NMrM9uk8TPOzg==",
+ "dev": true
+ },
+ "@types/jasminewd2": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz",
+ "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==",
+ "dev": true,
+ "requires": {
+ "@types/jasmine": "*"
+ }
+ },
+ "@types/jest": {
+ "version": "24.0.9",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.9.tgz",
+ "integrity": "sha512-k3OOeevcBYLR5pdsOv5g3OP94h3mrJmLPHFEPWgbbVy2tGv0TZ/TlygiC848ogXhK8NL0I5up7YYtwpCp8xCJA==",
+ "dev": true,
+ "requires": {
+ "@types/jest-diff": "*"
+ }
+ },
+ "@types/jest-diff": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz",
+ "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
+ "dev": true
+ },
+ "@types/lodash": {
+ "version": "4.14.121",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz",
+ "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "11.9.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.5.tgz",
+ "integrity": "sha512-vVjM0SVzgaOUpflq4GYBvCpozes8OgIIS5gVXVka+OfK3hvnkC1i93U8WiY2OtNE4XUWyyy/86Kf6e0IHTQw1Q==",
+ "dev": true
+ },
+ "@types/q": {
+ "version": "0.0.32",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+ "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
+ "dev": true
+ },
+ "@types/selenium-webdriver": {
+ "version": "3.0.16",
+ "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz",
+ "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==",
+ "dev": true
+ },
+ "@types/source-list-map": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
+ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
+ "dev": true
+ },
+ "@types/stack-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
+ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
+ "dev": true
+ },
+ "@types/webpack-sources": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
+ "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/source-list-map": "*",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@types/yargs": {
+ "version": "13.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz",
+ "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==",
+ "dev": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "@types/yargs-parser": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz",
+ "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==",
+ "dev": true
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
+ "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz",
+ "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz",
+ "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz",
+ "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz",
+ "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.7.11"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz",
+ "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz",
+ "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz",
+ "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz",
+ "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz",
+ "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==",
+ "dev": true,
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz",
+ "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz",
+ "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==",
+ "dev": true
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz",
+ "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/helper-wasm-section": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-opt": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "@webassemblyjs/wast-printer": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz",
+ "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz",
+ "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz",
+ "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz",
+ "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/floating-point-hex-parser": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-code-frame": "1.7.11",
+ "@webassemblyjs/helper-fsm": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz",
+ "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true
+ },
+ "@xtuc/long": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
+ "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==",
+ "dev": true
+ },
+ "@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "abab": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz",
+ "integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg==",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true,
+ "optional": true
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "acorn": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
+ "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
+ "dev": true
+ },
+ "acorn-dynamic-import": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz",
+ "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==",
+ "dev": true
+ },
+ "acorn-globals": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
+ "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.1",
+ "acorn-walk": "^6.0.1"
+ },
+ "dependencies": {
+ "acorn-walk": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
+ "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+ "dev": true
+ }
+ }
+ },
+ "acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
+ "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
+ "dev": true
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz",
+ "integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg==",
+ "dev": true
+ },
+ "adm-zip": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz",
+ "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==",
+ "dev": true
+ },
+ "agent-base": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "agentkeepalive": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
+ "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+ "dev": true,
+ "requires": {
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "ajv": {
+ "version": "6.9.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
+ "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+ "dev": true
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
+ "ansi-colors": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true
+ },
+ "ansi-gray": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
+ "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ },
+ "dependencies": {
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ }
+ }
+ },
+ "ansi-wrap": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
+ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "apache-crypt": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.1.tgz",
+ "integrity": "sha1-1vxyqm0n2ZyVqU/RiNcx7v/6Zjw=",
+ "dev": true,
+ "requires": {
+ "unix-crypt-td-js": "^1.0.0"
+ }
+ },
+ "apache-md5": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.2.tgz",
+ "integrity": "sha1-7klza2ObTxCLbp5ibG2pkwa0FpI=",
+ "dev": true
+ },
+ "app-root-path": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz",
+ "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==",
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "arg": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz",
+ "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "array-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true,
+ "optional": true
+ },
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": true
+ },
+ "array-from": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
+ "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+ "dev": true,
+ "optional": true
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "ast-transform": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/ast-transform/-/ast-transform-0.0.0.tgz",
+ "integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=",
+ "dev": true,
+ "requires": {
+ "escodegen": "~1.2.0",
+ "esprima": "~1.0.4",
+ "through": "~2.3.4"
+ },
+ "dependencies": {
+ "escodegen": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.2.0.tgz",
+ "integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=",
+ "dev": true,
+ "requires": {
+ "esprima": "~1.0.4",
+ "estraverse": "~1.5.0",
+ "esutils": "~1.0.0",
+ "source-map": "~0.1.30"
+ }
+ },
+ "esprima": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
+ "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=",
+ "dev": true
+ },
+ "estraverse": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz",
+ "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz",
+ "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "ast-types": {
+ "version": "0.7.8",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz",
+ "integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk=",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "dev": true
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+ "dev": true
+ },
+ "async-foreach": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+ "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+ "dev": true,
+ "optional": true
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
+ "autoprefixer": {
+ "version": "9.4.6",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.6.tgz",
+ "integrity": "sha512-Yp51mevbOEdxDUy5WjiKtpQaecqYq9OqZSL04rSoCiry7Tc5I9FEyo3bfxiTJc1DfHeKwSFCUYbBAiOQ2VGfiw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.4.1",
+ "caniuse-lite": "^1.0.30000929",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.13",
+ "postcss-value-parser": "^3.3.1"
+ }
+ },
+ "awesome-bootstrap-checkbox": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/awesome-bootstrap-checkbox/-/awesome-bootstrap-checkbox-0.3.7.tgz",
+ "integrity": "sha1-sRKXPubVv/QKshfEIBhcRwJR0OI="
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "babel-generator": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+ "dev": true,
+ "requires": {
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "detect-indent": "^4.0.0",
+ "jsesc": "^1.3.0",
+ "lodash": "^4.17.4",
+ "source-map": "^0.5.7",
+ "trim-right": "^1.0.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "babel-helper-builder-binary-assignment-operator-visitor": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+ "dev": true,
+ "requires": {
+ "babel-helper-explode-assignable-expression": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-define-map": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "^6.24.1",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-helper-explode-assignable-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "dev": true,
+ "requires": {
+ "babel-helper-get-function-arity": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-regex": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-helper-remap-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "dev": true,
+ "requires": {
+ "babel-helper-optimise-call-expression": "^6.24.1",
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-jest": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz",
+ "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==",
+ "dev": true,
+ "requires": {
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/babel__core": "^7.1.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "babel-preset-jest": "^24.9.0",
+ "chalk": "^2.4.2",
+ "slash": "^2.0.0"
+ },
+ "dependencies": {
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ }
+ }
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz",
+ "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "find-up": "^3.0.0",
+ "istanbul-lib-instrument": "^3.3.0",
+ "test-exclude": "^5.2.3"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+ "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+ "dev": true,
+ "requires": {
+ "@babel/generator": "^7.4.0",
+ "@babel/parser": "^7.4.3",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.3",
+ "@babel/types": "^7.4.0",
+ "istanbul-lib-coverage": "^2.0.5",
+ "semver": "^6.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz",
+ "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==",
+ "dev": true,
+ "requires": {
+ "@types/babel__traverse": "^7.0.6"
+ }
+ },
+ "babel-plugin-syntax-async-functions": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+ "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
+ "dev": true
+ },
+ "babel-plugin-syntax-exponentiation-operator": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+ "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
+ "dev": true
+ },
+ "babel-plugin-syntax-trailing-function-commas": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+ "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
+ "dev": true
+ },
+ "babel-plugin-transform-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+ "dev": true,
+ "requires": {
+ "babel-helper-remap-async-to-generator": "^6.24.1",
+ "babel-plugin-syntax-async-functions": "^6.8.0",
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "babel-template": "^6.26.0",
+ "babel-traverse": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "dev": true,
+ "requires": {
+ "babel-helper-define-map": "^6.24.1",
+ "babel-helper-function-name": "^6.24.1",
+ "babel-helper-optimise-call-expression": "^6.24.1",
+ "babel-helper-replace-supers": "^6.24.1",
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.26.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
+ "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-strict-mode": "^6.24.1",
+ "babel-runtime": "^6.26.0",
+ "babel-template": "^6.26.0",
+ "babel-types": "^6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-amd": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "dev": true,
+ "requires": {
+ "babel-helper-replace-supers": "^6.24.1",
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "dev": true,
+ "requires": {
+ "babel-helper-call-delegate": "^6.24.1",
+ "babel-helper-get-function-arity": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-template": "^6.24.1",
+ "babel-traverse": "^6.24.1",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "^6.24.1",
+ "babel-runtime": "^6.22.0",
+ "regexpu-core": "^2.0.0"
+ }
+ },
+ "babel-plugin-transform-exponentiation-operator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+ "dev": true,
+ "requires": {
+ "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
+ "babel-plugin-syntax-exponentiation-operator": "^6.8.0",
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "^0.10.0"
+ }
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0",
+ "babel-types": "^6.24.1"
+ }
+ },
+ "babel-preset-env": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
+ "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-check-es2015-constants": "^6.22.0",
+ "babel-plugin-syntax-trailing-function-commas": "^6.22.0",
+ "babel-plugin-transform-async-to-generator": "^6.22.0",
+ "babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
+ "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
+ "babel-plugin-transform-es2015-block-scoping": "^6.23.0",
+ "babel-plugin-transform-es2015-classes": "^6.23.0",
+ "babel-plugin-transform-es2015-computed-properties": "^6.22.0",
+ "babel-plugin-transform-es2015-destructuring": "^6.23.0",
+ "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0",
+ "babel-plugin-transform-es2015-for-of": "^6.23.0",
+ "babel-plugin-transform-es2015-function-name": "^6.22.0",
+ "babel-plugin-transform-es2015-literals": "^6.22.0",
+ "babel-plugin-transform-es2015-modules-amd": "^6.22.0",
+ "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0",
+ "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0",
+ "babel-plugin-transform-es2015-modules-umd": "^6.23.0",
+ "babel-plugin-transform-es2015-object-super": "^6.22.0",
+ "babel-plugin-transform-es2015-parameters": "^6.23.0",
+ "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0",
+ "babel-plugin-transform-es2015-spread": "^6.22.0",
+ "babel-plugin-transform-es2015-sticky-regex": "^6.22.0",
+ "babel-plugin-transform-es2015-template-literals": "^6.22.0",
+ "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0",
+ "babel-plugin-transform-es2015-unicode-regex": "^6.22.0",
+ "babel-plugin-transform-exponentiation-operator": "^6.22.0",
+ "babel-plugin-transform-regenerator": "^6.22.0",
+ "browserslist": "^3.2.6",
+ "invariant": "^2.2.2",
+ "semver": "^5.3.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "3.2.8",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
+ "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000844",
+ "electron-to-chromium": "^1.3.47"
+ }
+ }
+ }
+ },
+ "babel-preset-jest": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz",
+ "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-object-rest-spread": "^7.0.0",
+ "babel-plugin-jest-hoist": "^24.9.0"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "dev": true,
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ }
+ },
+ "babel-template": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "babel-traverse": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "babylon": "^6.18.0",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.26.0",
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "babylon": "^6.18.0",
+ "debug": "^2.6.8",
+ "globals": "^9.18.0",
+ "invariant": "^2.2.2",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.4",
+ "to-fast-properties": "^1.0.3"
+ }
+ },
+ "babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
+ "dev": true
+ },
+ "basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=",
+ "dev": true
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "inherits": "~2.0.0"
+ }
+ },
+ "blocking-proxy": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
+ "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
+ "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ }
+ },
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
+ "bootstrap": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz",
+ "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brfs": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz",
+ "integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==",
+ "dev": true,
+ "requires": {
+ "quote-stream": "^1.0.1",
+ "resolve": "^1.1.5",
+ "static-module": "^3.0.2",
+ "through2": "^2.0.0"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "brotli": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz",
+ "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.1.2"
+ }
+ },
+ "browser-process-hrtime": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
+ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==",
+ "dev": true
+ },
+ "browser-resolve": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",
+ "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",
+ "dev": true,
+ "requires": {
+ "resolve": "1.1.7"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ }
+ }
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-optional": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-optional/-/browserify-optional-1.0.1.tgz",
+ "integrity": "sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk=",
+ "dev": true,
+ "requires": {
+ "ast-transform": "0.0.0",
+ "ast-types": "^0.7.0",
+ "browser-resolve": "^1.8.1"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz",
+ "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001004",
+ "electron-to-chromium": "^1.3.295",
+ "node-releases": "^1.1.38"
+ }
+ },
+ "browserstack": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz",
+ "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "requires": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-equal": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
+ "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "builtins": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ },
+ "dependencies": {
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ }
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "call-me-maybe": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
+ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
+ "dev": true
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "dev": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001004",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001004.tgz",
+ "integrity": "sha512-3nfOR4O8Wa2RWoYfJkMtwRVOsK96TQ+eq57wd0iKaEWl8dwG4hKZ/g0MVBfCvysFvMLi9fQGR/DvozMdkEPl3g==",
+ "dev": true
+ },
+ "canonical-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz",
+ "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
+ "dev": true
+ },
+ "capture-exit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
+ "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==",
+ "dev": true,
+ "requires": {
+ "rsvp": "^4.8.4"
+ }
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "chart.js": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.3.tgz",
+ "integrity": "sha512-3+7k/DbR92m6BsMUYP6M0dMsMVZpMnwkUyNSAbqolHKsbIzH2Q4LWVEHHYq7v0fmEV8whXE0DrjANulw9j2K5g==",
+ "requires": {
+ "chartjs-color": "^2.1.0",
+ "moment": "^2.10.2"
+ }
+ },
+ "chartjs-color": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.3.0.tgz",
+ "integrity": "sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==",
+ "requires": {
+ "chartjs-color-string": "^0.6.0",
+ "color-convert": "^0.5.3"
+ }
+ },
+ "chartjs-color-string": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
+ "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
+ "requires": {
+ "color-name": "^1.0.0"
+ }
+ },
+ "cheerio": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+ "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.1",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash": "^4.15.0",
+ "parse5": "^3.0.1"
+ },
+ "dependencies": {
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
+ "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.0",
+ "braces": "^2.3.0",
+ "fsevents": "^1.2.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.1",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "lodash.debounce": "^4.0.8",
+ "normalize-path": "^2.1.1",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.0.0",
+ "upath": "^1.0.5"
+ }
+ },
+ "chownr": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
+ "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
+ "dev": true
+ },
+ "chrome-trace-event": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+ "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "circular-dependency-plugin": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz",
+ "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==",
+ "dev": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-css": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
+ "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
+ "dev": true,
+ "requires": {
+ "for-own": "^1.0.0",
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.0",
+ "shallow-clone": "^1.0.0"
+ }
+ },
+ "closest-file-data": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/closest-file-data/-/closest-file-data-0.1.4.tgz",
+ "integrity": "sha1-l1+HwTLymdJKA3W59jyj+4j3Kzo=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "code-block-writer": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-7.3.1.tgz",
+ "integrity": "sha512-3Jfe6ZmmGzvdQWFo3MUzobn3WdX++jc3Tj0rsviJWYPnP7NGMFEE4qheNeOXeJgB1TTgxYT8XuNvhS/u596yGg==",
+ "dev": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "codelyzer": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz",
+ "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==",
+ "dev": true,
+ "requires": {
+ "app-root-path": "^2.1.0",
+ "css-selector-tokenizer": "^0.7.0",
+ "cssauron": "^1.4.0",
+ "semver-dsl": "^1.0.1",
+ "source-map": "^0.5.7",
+ "sprintf-js": "^1.1.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "dev": true
+ }
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
+ "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true
+ },
+ "compressible": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+ "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
+ "dev": true,
+ "requires": {
+ "mime-db": ">= 1.40.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "dev": true,
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+ "dev": true,
+ "optional": true
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "copy-webpack-plugin": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
+ "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.0",
+ "loader-utils": "^1.1.0",
+ "minimatch": "^3.0.4",
+ "p-limit": "^1.0.0",
+ "serialize-javascript": "^1.4.0"
+ }
+ },
+ "core-js": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
+ "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4",
+ "vary": "^1"
+ }
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "dev": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ },
+ "dependencies": {
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ }
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "crypto-js": {
+ "version": "3.1.9-1",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
+ "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=",
+ "dev": true
+ },
+ "css-parse": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
+ "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
+ "dev": true
+ },
+ "css-select": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0",
+ "css-what": "2.1",
+ "domutils": "1.5.1",
+ "nth-check": "~1.0.1"
+ }
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+ "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^0.1.0",
+ "fastparse": "^1.1.1",
+ "regexpu-core": "^1.0.0"
+ },
+ "dependencies": {
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ }
+ }
+ },
+ "css-what": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+ "dev": true
+ },
+ "cssauron": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
+ "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
+ "dev": true,
+ "requires": {
+ "through": "X.X.X"
+ }
+ },
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true
+ },
+ "cssstyle": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz",
+ "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==",
+ "dev": true,
+ "requires": {
+ "cssom": "0.3.x"
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "cyclist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+ "dev": true
+ },
+ "d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "dev": true,
+ "requires": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "data-urls": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
+ "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.0",
+ "whatwg-mimetype": "^2.2.0",
+ "whatwg-url": "^7.0.0"
+ },
+ "dependencies": {
+ "whatwg-url": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+ "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ }
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
+ "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
+ "dev": true,
+ "requires": {
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.2.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "default-gateway": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz",
+ "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.10.0",
+ "ip-regex": "^2.1.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ }
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+ "dev": true,
+ "requires": {
+ "globby": "^6.1.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "p-map": "^1.1.1",
+ "pify": "^3.0.0",
+ "rimraf": "^2.2.8"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true,
+ "optional": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "dependency-graph": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz",
+ "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-browser": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-4.1.0.tgz",
+ "integrity": "sha512-YKQf1QQDXXJrwNE07xHujoD+meBnjhsYFdPwxFEXS1ylJWD9GKd21lKBjuqtXzAkz4CQjwBO3DYXBU/wWwZCGA=="
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "dev": true
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+ "dev": true
+ },
+ "dfa": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
+ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diff-sequences": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz",
+ "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+ "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "entities": "^1.1.1"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domexception": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
+ "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+ "dev": true,
+ "requires": {
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dot": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.2.tgz",
+ "integrity": "sha1-xzdwGfxOVQeYkosrmv62ar+h8vk=",
+ "dev": true
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.296",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz",
+ "integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ==",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz",
+ "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "err-code": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz",
+ "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz",
+ "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.0",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-inspect": "^1.6.0",
+ "object-keys": "^1.1.1",
+ "string.prototype.trimleft": "^2.1.0",
+ "string.prototype.trimright": "^2.1.0"
+ },
+ "dependencies": {
+ "object-inspect": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
+ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+ "dev": true
+ }
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.51",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz",
+ "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.1",
+ "next-tick": "^1.0.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-set": "~0.1.5",
+ "es6-symbol": "~3.1.1",
+ "event-emitter": "~0.3.5"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+ "dev": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "~0.3.5"
+ },
+ "dependencies": {
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ }
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz",
+ "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==",
+ "dev": true,
+ "requires": {
+ "d": "^1.0.1",
+ "es5-ext": "^0.10.51"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz",
+ "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==",
+ "dev": true,
+ "requires": {
+ "esprima": "^3.1.3",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+ "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "estree-is-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz",
+ "integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "event-stream": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+ "dev": true,
+ "requires": {
+ "duplexer": "~0.1.1",
+ "from": "~0",
+ "map-stream": "~0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.3",
+ "stream-combiner": "~0.0.4",
+ "through": "~2.3.1"
+ }
+ },
+ "eventemitter3": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
+ "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
+ "dev": true
+ },
+ "events": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
+ "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+ "dev": true
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "dev": true,
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "exec-sh": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz",
+ "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==",
+ "dev": true
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "expect": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz",
+ "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "ansi-styles": "^3.2.0",
+ "jest-get-type": "^24.9.0",
+ "jest-matcher-utils": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-regex-util": "^24.9.0"
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "falafel": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz",
+ "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=",
+ "dev": true,
+ "requires": {
+ "acorn": "^5.0.0",
+ "foreach": "^2.0.5",
+ "isarray": "0.0.1",
+ "object-keys": "^1.0.6"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ }
+ }
+ },
+ "fancy-log": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
+ "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
+ "dev": true,
+ "requires": {
+ "ansi-gray": "^0.1.1",
+ "color-support": "^1.1.3",
+ "parse-node-version": "^1.0.0",
+ "time-stamp": "^1.0.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
+ "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==",
+ "dev": true,
+ "requires": {
+ "@mrmlnc/readdir-enhanced": "^2.2.1",
+ "@nodelib/fs.stat": "^1.1.2",
+ "glob-parent": "^3.1.0",
+ "is-glob": "^4.0.0",
+ "merge2": "^1.2.3",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "fb-watchman": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
+ "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=",
+ "dev": true,
+ "requires": {
+ "bser": "^2.0.0"
+ }
+ },
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+ "dev": true
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
+ "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "findit2": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz",
+ "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=",
+ "dev": true
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz",
+ "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "fontkit": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz",
+ "integrity": "sha512-EFDRCca7khfQWYu1iFhsqeABpi87f03MBdkT93ZE6YhqCdMzb5Eojb6c4dlJikGv5liuhByyzA7ikpIPTSBWbQ==",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.11.6",
+ "brfs": "^1.4.0",
+ "brotli": "^1.2.0",
+ "browserify-optional": "^1.0.0",
+ "clone": "^1.0.1",
+ "deep-equal": "^1.0.0",
+ "dfa": "^1.0.0",
+ "restructure": "^0.5.3",
+ "tiny-inflate": "^1.0.2",
+ "unicode-properties": "^1.0.0",
+ "unicode-trie": "^0.3.0"
+ },
+ "dependencies": {
+ "brfs": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz",
+ "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==",
+ "dev": true,
+ "requires": {
+ "quote-stream": "^1.0.1",
+ "resolve": "^1.1.5",
+ "static-module": "^2.2.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "magic-string": {
+ "version": "0.22.5",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
+ "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
+ "dev": true,
+ "requires": {
+ "vlq": "^0.2.2"
+ }
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ },
+ "static-module": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz",
+ "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "~1.6.0",
+ "convert-source-map": "^1.5.1",
+ "duplexer2": "~0.1.4",
+ "escodegen": "~1.9.0",
+ "falafel": "^2.1.0",
+ "has": "^1.0.1",
+ "magic-string": "^0.22.4",
+ "merge-source-map": "1.0.4",
+ "object-inspect": "~1.4.0",
+ "quote-stream": "~1.0.2",
+ "readable-stream": "~2.3.3",
+ "shallow-copy": "~0.0.1",
+ "static-eval": "^2.0.0",
+ "through2": "~2.0.3"
+ }
+ },
+ "unicode-trie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
+ "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
+ "dev": true,
+ "requires": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.1"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "fork-awesome": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/fork-awesome/-/fork-awesome-1.1.6.tgz",
+ "integrity": "sha512-fFWz7LqRGMbyewY0Vxclw4712Cy+6Vd+1RAIJb7XY5qHpZi8BAA+Ue5sr4jAlDSI1+AD4b5WYl99NrGMtSaPzw=="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "dev": true
+ },
+ "from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+ "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.12.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "gaze": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+ "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "globule": "^1.0.0"
+ }
+ },
+ "genfun": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz",
+ "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==",
+ "dev": true
+ },
+ "get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true,
+ "optional": true
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "glob-to-regexp": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
+ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
+ "dev": true
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "globule": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
+ "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "~7.1.1",
+ "lodash": "~4.17.10",
+ "minimatch": "~3.0.2"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+ "dev": true
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true
+ },
+ "handle-thing": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
+ "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.5.tgz",
+ "integrity": "sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==",
+ "dev": true,
+ "requires": {
+ "neo-async": "^2.6.0",
+ "optimist": "^0.6.1",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true,
+ "optional": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true,
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
+ "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
+ "dev": true
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "html-encoding-sniffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
+ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
+ "dev": true,
+ "requires": {
+ "whatwg-encoding": "^1.0.1"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "html-linter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/html-linter/-/html-linter-1.1.1.tgz",
+ "integrity": "sha512-DJfLevdq+YmY4R7yMdD0zaCAJOvWihg+eCe5o/jeTw86grvgmvSCIwBv1mDi+UdeJP9mDoi5rB6KtcFOn8StrA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "commander": "^2.12.2",
+ "glob": "^7.1.2"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+ "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "http-auth": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz",
+ "integrity": "sha1-lFz63WZSHq+PfISRPTd9exXyTjE=",
+ "dev": true,
+ "requires": {
+ "apache-crypt": "^1.1.2",
+ "apache-md5": "^1.0.6",
+ "bcryptjs": "^2.3.0",
+ "uuid": "^3.0.0"
+ }
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ }
+ }
+ },
+ "http-parser-js": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
+ "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-agent": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
+ "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "4",
+ "debug": "3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz",
+ "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==",
+ "dev": true,
+ "requires": {
+ "http-proxy": "^1.16.2",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.5",
+ "micromatch": "^3.1.9"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+ "dev": true
+ },
+ "https-proxy-agent": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.3.tgz",
+ "integrity": "sha512-Ytgnz23gm2DVftnzqRRz2dOXZbGd2uiajSw/95bPp6v53zPRspQjLm/AfBgqbJ2qfeRXWIOMVLpp86+/5yX39Q==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^4.3.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "i18next": {
+ "version": "17.3.1",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-17.3.1.tgz",
+ "integrity": "sha512-4nY+yaENaoZKmpbiDXPzucVHCN3hN9Z9Zk7LyQXVOKVIpnYOJ3L/yxHJlBPtJDq3PGgjFwA0QBFm/26Z0iDT5A==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.3.1"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+ "dev": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+ "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "image-size": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+ "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+ "dev": true,
+ "optional": true
+ },
+ "immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
+ "dev": true
+ },
+ "import-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
+ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+ "dev": true,
+ "requires": {
+ "import-from": "^2.1.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "dev": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-from": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
+ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ }
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "in-publish": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+ "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
+ "dev": true,
+ "optional": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz",
+ "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.0",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.0",
+ "figures": "^2.0.0",
+ "lodash": "^4.17.10",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.1.0",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^5.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "inside": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/inside/-/inside-1.0.0.tgz",
+ "integrity": "sha1-20Xpk1c82z23C5gy6ChbrUZCR3A=",
+ "dev": true
+ },
+ "internal-ip": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz",
+ "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==",
+ "dev": true,
+ "requires": {
+ "default-gateway": "^2.6.0",
+ "ipaddr.js": "^1.5.2"
+ }
+ },
+ "interpret": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+ "dev": true
+ },
+ "is-absolute": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+ "dev": true,
+ "requires": {
+ "is-relative": "^1.0.0",
+ "is-windows": "^1.0.1"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-negated-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
+ "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-relative": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+ "dev": true,
+ "requires": {
+ "is-unc-path": "^1.0.0"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-unc-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+ "dev": true,
+ "requires": {
+ "unc-path-regex": "^0.1.2"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true,
+ "optional": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "istanbul-instrumenter-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz",
+ "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "^1.5.0",
+ "istanbul-lib-instrument": "^1.7.3",
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^0.3.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
+ "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
+ "dev": true,
+ "requires": {
+ "ajv": "^5.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz",
+ "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz",
+ "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==",
+ "dev": true,
+ "requires": {
+ "babel-generator": "^6.18.0",
+ "babel-template": "^6.16.0",
+ "babel-traverse": "^6.18.0",
+ "babel-types": "^6.18.0",
+ "babylon": "^6.18.0",
+ "istanbul-lib-coverage": "^1.2.1",
+ "semver": "^5.3.0"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+ "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+ "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "rimraf": "^2.6.3",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
+ "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
+ "dev": true,
+ "requires": {
+ "handlebars": "^4.1.2"
+ }
+ },
+ "jasmine": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
+ "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
+ "dev": true,
+ "requires": {
+ "exit": "^0.1.2",
+ "glob": "^7.0.6",
+ "jasmine-core": "~2.8.0"
+ },
+ "dependencies": {
+ "jasmine-core": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
+ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
+ "dev": true
+ }
+ }
+ },
+ "jasmine-core": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz",
+ "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==",
+ "dev": true
+ },
+ "jasmine-spec-reporter": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
+ "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
+ "dev": true,
+ "requires": {
+ "colors": "1.1.2"
+ },
+ "dependencies": {
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ }
+ }
+ },
+ "jasminewd2": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
+ "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
+ "dev": true
+ },
+ "jest": {
+ "version": "24.8.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-24.8.0.tgz",
+ "integrity": "sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==",
+ "dev": true,
+ "requires": {
+ "import-local": "^2.0.0",
+ "jest-cli": "^24.8.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "jest-cli": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz",
+ "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==",
+ "dev": true,
+ "requires": {
+ "@jest/core": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "import-local": "^2.0.0",
+ "is-ci": "^2.0.0",
+ "jest-config": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-validate": "^24.9.0",
+ "prompts": "^2.0.1",
+ "realpath-native": "^1.1.0",
+ "yargs": "^13.3.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
+ "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "jest-canvas-mock": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-1.1.0.tgz",
+ "integrity": "sha512-D2VoKl+L6r9VpqTPygXKvIOQ1aou7gz3PvstlWDZqPT7EVYcSz0Nj+yjJ9G+Y9EqJd2X95f3dzcmmXb2dvQ1DQ==",
+ "dev": true
+ },
+ "jest-changed-files": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz",
+ "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "execa": "^1.0.0",
+ "throat": "^4.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "jest-config": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz",
+ "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.1.0",
+ "@jest/test-sequencer": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "babel-jest": "^24.9.0",
+ "chalk": "^2.0.1",
+ "glob": "^7.1.1",
+ "jest-environment-jsdom": "^24.9.0",
+ "jest-environment-node": "^24.9.0",
+ "jest-get-type": "^24.9.0",
+ "jest-jasmine2": "^24.9.0",
+ "jest-regex-util": "^24.3.0",
+ "jest-resolve": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-validate": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "pretty-format": "^24.9.0",
+ "realpath-native": "^1.1.0"
+ }
+ },
+ "jest-diff": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz",
+ "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "diff-sequences": "^24.9.0",
+ "jest-get-type": "^24.9.0",
+ "pretty-format": "^24.9.0"
+ }
+ },
+ "jest-docblock": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz",
+ "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==",
+ "dev": true,
+ "requires": {
+ "detect-newline": "^2.1.0"
+ }
+ },
+ "jest-each": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz",
+ "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "jest-get-type": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "pretty-format": "^24.9.0"
+ }
+ },
+ "jest-environment-jsdom": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz",
+ "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^24.9.0",
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jsdom": "^11.5.1"
+ }
+ },
+ "jest-environment-node": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz",
+ "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^24.9.0",
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0",
+ "jest-util": "^24.9.0"
+ }
+ },
+ "jest-get-type": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz",
+ "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==",
+ "dev": true
+ },
+ "jest-haste-map": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz",
+ "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "anymatch": "^2.0.0",
+ "fb-watchman": "^2.0.0",
+ "fsevents": "^1.2.7",
+ "graceful-fs": "^4.1.15",
+ "invariant": "^2.2.4",
+ "jest-serializer": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-worker": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "sane": "^4.0.3",
+ "walker": "^1.0.7"
+ }
+ },
+ "jest-jasmine2": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz",
+ "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==",
+ "dev": true,
+ "requires": {
+ "@babel/traverse": "^7.1.0",
+ "@jest/environment": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "co": "^4.6.0",
+ "expect": "^24.9.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^24.9.0",
+ "jest-matcher-utils": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-snapshot": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "pretty-format": "^24.9.0",
+ "throat": "^4.0.0"
+ }
+ },
+ "jest-leak-detector": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz",
+ "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==",
+ "dev": true,
+ "requires": {
+ "jest-get-type": "^24.9.0",
+ "pretty-format": "^24.9.0"
+ }
+ },
+ "jest-matcher-utils": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz",
+ "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1",
+ "jest-diff": "^24.9.0",
+ "jest-get-type": "^24.9.0",
+ "pretty-format": "^24.9.0"
+ }
+ },
+ "jest-message-util": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz",
+ "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/stack-utils": "^1.0.1",
+ "chalk": "^2.0.1",
+ "micromatch": "^3.1.10",
+ "slash": "^2.0.0",
+ "stack-utils": "^1.0.1"
+ },
+ "dependencies": {
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ }
+ }
+ },
+ "jest-mock": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz",
+ "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0"
+ }
+ },
+ "jest-pnp-resolver": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz",
+ "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==",
+ "dev": true
+ },
+ "jest-preset-angular": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-6.0.2.tgz",
+ "integrity": "sha512-uhrllY41tUvkeR41aX9bU5w3/EvvmwZiJ3UitDhRSEJL2Jvq2N/xKlmw7qvlZoGZnciFjOUJ2WDKv5fmCrvnQA==",
+ "dev": true,
+ "requires": {
+ "@types/jest": "^23.3.1",
+ "jest-zone-patch": ">=0.0.9 <1.0.0",
+ "ts-jest": "~23.1.3"
+ },
+ "dependencies": {
+ "@types/jest": {
+ "version": "23.3.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.14.tgz",
+ "integrity": "sha512-Q5hTcfdudEL2yOmluA1zaSyPbzWPmJ3XfSWeP3RyoYvS9hnje1ZyagrZOuQ6+1nQC1Gw+7gap3pLNL3xL6UBug==",
+ "dev": true
+ }
+ }
+ },
+ "jest-regex-util": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz",
+ "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==",
+ "dev": true
+ },
+ "jest-resolve": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz",
+ "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "browser-resolve": "^1.11.3",
+ "chalk": "^2.0.1",
+ "jest-pnp-resolver": "^1.2.1",
+ "realpath-native": "^1.1.0"
+ }
+ },
+ "jest-resolve-dependencies": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz",
+ "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "jest-regex-util": "^24.3.0",
+ "jest-snapshot": "^24.9.0"
+ }
+ },
+ "jest-runner": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz",
+ "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^24.7.1",
+ "@jest/environment": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.4.2",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.1.15",
+ "jest-config": "^24.9.0",
+ "jest-docblock": "^24.3.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-jasmine2": "^24.9.0",
+ "jest-leak-detector": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-resolve": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-worker": "^24.6.0",
+ "source-map-support": "^0.5.6",
+ "throat": "^4.0.0"
+ }
+ },
+ "jest-runtime": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz",
+ "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^24.7.1",
+ "@jest/environment": "^24.9.0",
+ "@jest/source-map": "^24.3.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/yargs": "^13.0.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.1.15",
+ "jest-config": "^24.9.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-mock": "^24.9.0",
+ "jest-regex-util": "^24.3.0",
+ "jest-resolve": "^24.9.0",
+ "jest-snapshot": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-validate": "^24.9.0",
+ "realpath-native": "^1.1.0",
+ "slash": "^2.0.0",
+ "strip-bom": "^3.0.0",
+ "yargs": "^13.3.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
+ "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
+ "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "jest-serializer": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz",
+ "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==",
+ "dev": true
+ },
+ "jest-silent-reporter": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/jest-silent-reporter/-/jest-silent-reporter-0.1.2.tgz",
+ "integrity": "sha512-w/qc9NvWqdX0vZv6TUG4EE15d72+JxQJYh+3hqq8cTi3BnfBOtwNtL3T6TwkZSy/sfc3REW5niz0eSBPTIvWnA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.3.1",
+ "jest-util": "^24.0.0"
+ }
+ },
+ "jest-snapshot": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz",
+ "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "expect": "^24.9.0",
+ "jest-diff": "^24.9.0",
+ "jest-get-type": "^24.9.0",
+ "jest-matcher-utils": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-resolve": "^24.9.0",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^24.9.0",
+ "semver": "^6.2.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "jest-util": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz",
+ "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^24.9.0",
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/source-map": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "callsites": "^3.0.0",
+ "chalk": "^2.0.1",
+ "graceful-fs": "^4.1.15",
+ "is-ci": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "jest-validate": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz",
+ "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "camelcase": "^5.3.1",
+ "chalk": "^2.0.1",
+ "jest-get-type": "^24.9.0",
+ "leven": "^3.1.0",
+ "pretty-format": "^24.9.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ }
+ }
+ },
+ "jest-watcher": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz",
+ "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==",
+ "dev": true,
+ "requires": {
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/yargs": "^13.0.0",
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.1",
+ "jest-util": "^24.9.0",
+ "string-length": "^2.0.0"
+ }
+ },
+ "jest-worker": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz",
+ "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==",
+ "dev": true,
+ "requires": {
+ "merge-stream": "^2.0.0",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "jest-zone-patch": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/jest-zone-patch/-/jest-zone-patch-0.0.10.tgz",
+ "integrity": "sha512-K5uHLHgMgi2Eyj74gbY+xSeGGekb5U48bXsgDwgipRbFdaekyZK+TAcp8auamqU4UjrAt5S4sIUZz/2bBNyTTA==",
+ "dev": true
+ },
+ "js-base64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
+ "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
+ "dev": true,
+ "optional": true
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsdom": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
+ "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
+ "dev": true,
+ "requires": {
+ "abab": "^2.0.0",
+ "acorn": "^5.5.3",
+ "acorn-globals": "^4.1.0",
+ "array-equal": "^1.0.0",
+ "cssom": ">= 0.3.2 < 0.4.0",
+ "cssstyle": "^1.0.0",
+ "data-urls": "^1.0.0",
+ "domexception": "^1.0.1",
+ "escodegen": "^1.9.1",
+ "html-encoding-sniffer": "^1.0.2",
+ "left-pad": "^1.3.0",
+ "nwsapi": "^2.0.7",
+ "parse5": "4.0.0",
+ "pn": "^1.1.0",
+ "request": "^2.87.0",
+ "request-promise-native": "^1.0.5",
+ "sax": "^1.2.4",
+ "symbol-tree": "^3.2.2",
+ "tough-cookie": "^2.3.4",
+ "w3c-hr-time": "^1.0.1",
+ "webidl-conversions": "^4.0.2",
+ "whatwg-encoding": "^1.0.3",
+ "whatwg-mimetype": "^2.1.0",
+ "whatwg-url": "^6.4.1",
+ "ws": "^5.2.0",
+ "xml-name-validator": "^3.0.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ }
+ }
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "json3": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
+ "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "jszip": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz",
+ "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==",
+ "dev": true,
+ "requires": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "set-immediate-shim": "~1.0.1"
+ }
+ },
+ "karma-source-map-support": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz",
+ "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==",
+ "dev": true,
+ "requires": {
+ "source-map-support": "^0.5.5"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "left-pad": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
+ "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==",
+ "dev": true
+ },
+ "less": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz",
+ "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.2",
+ "errno": "^0.1.1",
+ "graceful-fs": "^4.1.2",
+ "image-size": "~0.5.0",
+ "mime": "^1.4.1",
+ "mkdirp": "^0.5.0",
+ "promise": "^7.1.1",
+ "request": "^2.83.0",
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "less-loader": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
+ "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "loader-utils": "^1.1.0",
+ "pify": "^3.0.0"
+ }
+ },
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "license-webpack-plugin": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.0.tgz",
+ "integrity": "sha512-vDiBeMWxjE9n6TabQ9J4FH8urFdsRK0Nvxn1cit9biCiR9aq1zBR0X2BlAkEiIG6qPamLeU0GzvIgLkrFc398A==",
+ "dev": true,
+ "requires": {
+ "@types/webpack-sources": "^0.1.5",
+ "webpack-sources": "^1.2.0"
+ }
+ },
+ "lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "dev": true,
+ "requires": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "linebreak": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.0.2.tgz",
+ "integrity": "sha512-bJwSRsJeAmaZYnkcwl5sCQNfSDAhBuXxb6L27tb+qkBRtUQSSTUa5bcgCPD6hFEkRNlpWHfK7nFMmcANU7ZP1w==",
+ "dev": true,
+ "requires": {
+ "base64-js": "0.0.8",
+ "brfs": "^2.0.2",
+ "unicode-trie": "^1.0.0"
+ },
+ "dependencies": {
+ "base64-js": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
+ "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
+ "dev": true
+ }
+ }
+ },
+ "live-server": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.1.tgz",
+ "integrity": "sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.4",
+ "colors": "^1.4.0",
+ "connect": "^3.6.6",
+ "cors": "^2.8.5",
+ "event-stream": "3.3.4",
+ "faye-websocket": "0.11.x",
+ "http-auth": "3.1.x",
+ "morgan": "^1.9.1",
+ "object-assign": "^4.1.1",
+ "opn": "^6.0.0",
+ "proxy-middleware": "^0.15.0",
+ "send": "^0.17.1",
+ "serve-index": "^1.9.1"
+ },
+ "dependencies": {
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "opn": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz",
+ "integrity": "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ }
+ }
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.14",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
+ "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+ "dev": true
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
+ },
+ "lodash.sortby": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+ "dev": true
+ },
+ "lodash.tail": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
+ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
+ "dev": true
+ },
+ "loglevel": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.4.tgz",
+ "integrity": "sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "lunr": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz",
+ "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==",
+ "dev": true
+ },
+ "macos-release": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz",
+ "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==",
+ "dev": true
+ },
+ "magic-string": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz",
+ "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==",
+ "dev": true,
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+ "dev": true
+ },
+ "make-fetch-happen": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.2.tgz",
+ "integrity": "sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==",
+ "dev": true,
+ "requires": {
+ "agentkeepalive": "^3.4.1",
+ "cacache": "^11.3.3",
+ "http-cache-semantics": "^3.8.1",
+ "http-proxy-agent": "^2.1.0",
+ "https-proxy-agent": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "node-fetch-npm": "^2.0.2",
+ "promise-retry": "^1.1.1",
+ "socks-proxy-agent": "^4.0.0",
+ "ssri": "^6.0.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
+ "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ }
+ }
+ },
+ "makeerror": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
+ "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=",
+ "dev": true,
+ "requires": {
+ "tmpl": "1.0.x"
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true,
+ "optional": true
+ },
+ "map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "marked": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
+ "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
+ "dev": true
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true,
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
+ "dev": true
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "merge-source-map": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz",
+ "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.5.6"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz",
+ "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
+ },
+ "mini-css-extract-plugin": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz",
+ "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^1.0.0",
+ "webpack-sources": "^1.1.0"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+ "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ },
+ "dependencies": {
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ }
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+ "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mixin-object": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
+ "dev": true,
+ "requires": {
+ "for-in": "^0.1.3",
+ "is-extendable": "^0.1.1"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
+ "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=",
+ "dev": true
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ }
+ }
+ },
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ },
+ "morgan": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
+ "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
+ "dev": true,
+ "requires": {
+ "basic-auth": "~2.0.0",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.0.1"
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
+ "multimatch": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
+ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
+ "dev": true,
+ "requires": {
+ "array-differ": "^1.0.0",
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "minimatch": "^3.0.0"
+ }
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+ "dev": true
+ },
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
+ "dev": true
+ },
+ "ng-block-ui": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ng-block-ui/-/ng-block-ui-2.1.1.tgz",
+ "integrity": "sha512-nfSIwcdj0pFkJpYIX7qnmQ5LwFBfYjVJLHCX3nxUCtmOj5mgEMSt3xE6upBt9LrRjYuYt4yHjPS4S7mh9ZOWYQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ng2-charts": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz",
+ "integrity": "sha512-9w0WH69x5/nuqC1og2WaY39NbaBqTGIP1+5gZaH7/KPN6UEPonNg/pYnsIVklLj1DWPWXKa8+XXIJZ1jy5nLxg==",
+ "requires": {
+ "chart.js": "^2.6.0"
+ }
+ },
+ "ng2-tree": {
+ "version": "2.0.0-rc.11",
+ "resolved": "https://registry.npmjs.org/ng2-tree/-/ng2-tree-2.0.0-rc.11.tgz",
+ "integrity": "sha512-COGMatd+YrwJb3LSobagDC+t2PlSh4GkgG75Akh9QbXOSdFFPkbGmZvILg2xO4Hc+xicacvHp+6GINvjIeJwkA=="
+ },
+ "ngx-bootstrap": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-5.1.0.tgz",
+ "integrity": "sha512-gHmIH1dZcZgbgu9Y88iPa8JaMkSM1QrU1zPDSJIw5TUNXVbwhvi5bzh2ttjvL88agyVWmTHM0mgyntPAgULxCQ=="
+ },
+ "ngx-toastr": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-10.0.4.tgz",
+ "integrity": "sha512-iN+zr2Msae5wV334c1dytRhSYNdUz467jwv1NE91lMmllsMkpUzZlu8VdFCeTFt+/R4TWzz19xBRqhpp+OAuVA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node-fetch-npm": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
+ "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.11",
+ "json-parse-better-errors": "^1.0.0",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node-forge": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
+ "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
+ "dev": true
+ },
+ "node-gyp": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+ "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fstream": "^1.0.0",
+ "glob": "^7.0.3",
+ "graceful-fs": "^4.1.2",
+ "mkdirp": "^0.5.0",
+ "nopt": "2 || 3",
+ "npmlog": "0 || 1 || 2 || 3 || 4",
+ "osenv": "0",
+ "request": "^2.87.0",
+ "rimraf": "2",
+ "semver": "~5.3.0",
+ "tar": "^2.0.0",
+ "which": "1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "dev": true
+ },
+ "node-libs-browser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+ "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+ "dev": true,
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.1",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "^1.0.1"
+ }
+ },
+ "node-modules-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
+ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
+ "dev": true
+ },
+ "node-notifier": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz",
+ "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==",
+ "dev": true,
+ "requires": {
+ "growly": "^1.3.0",
+ "is-wsl": "^1.1.0",
+ "semver": "^5.5.0",
+ "shellwords": "^0.1.1",
+ "which": "^1.3.0"
+ }
+ },
+ "node-releases": {
+ "version": "1.1.39",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz",
+ "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "node-sass": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
+ "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "async-foreach": "^0.1.3",
+ "chalk": "^1.1.1",
+ "cross-spawn": "^3.0.0",
+ "gaze": "^1.0.0",
+ "get-stdin": "^4.0.1",
+ "glob": "^7.0.3",
+ "in-publish": "^2.0.0",
+ "lodash": "^4.17.11",
+ "meow": "^3.7.0",
+ "mkdirp": "^0.5.1",
+ "nan": "^2.13.2",
+ "node-gyp": "^3.8.0",
+ "npmlog": "^4.0.0",
+ "request": "^2.88.0",
+ "sass-graph": "^2.2.4",
+ "stdout-stream": "^1.4.0",
+ "true-case-path": "^1.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true,
+ "optional": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+ "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "which": "^1.2.9"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+ "dev": true
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
+ "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
+ "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.6.0",
+ "osenv": "^0.1.5",
+ "semver": "^5.5.0",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "npm-packlist": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz",
+ "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==",
+ "dev": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz",
+ "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "npm-package-arg": "^6.0.0",
+ "semver": "^5.4.1"
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz",
+ "integrity": "sha512-VQCEZlydXw4AwLROAXWUR7QDfe2Y8Id/vpAgp6TI1/H78a4SiQ1kQrKZALm5/zxM5n4HIi+aYb+idUAV/RuY0Q==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.3.4",
+ "bluebird": "^3.5.1",
+ "figgy-pudding": "^3.4.1",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^4.0.2",
+ "npm-package-arg": "^6.1.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ }
+ }
+ },
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "nwsapi": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz",
+ "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz",
+ "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==",
+ "dev": true
+ },
+ "object-is": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
+ "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "open": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-6.0.0.tgz",
+ "integrity": "sha512-/yb5mVZBz7mHLySMiSj2DcLtMBbFPJk5JBKEkHVZFxZAPzeg3L026O0T+lbdz1B2nyDnkClRSwRQJdeVUIF7zw==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "opencollective-postinstall": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz",
+ "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
+ "dev": true
+ },
+ "opn": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
+ "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ }
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.4",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "wordwrap": "~1.0.0"
+ },
+ "dependencies": {
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ }
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "dev": true,
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "os-name": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz",
+ "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==",
+ "dev": true,
+ "requires": {
+ "macos-release": "^2.2.0",
+ "windows-release": "^3.1.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "dev": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-each-series": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz",
+ "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=",
+ "dev": true,
+ "requires": {
+ "p-reduce": "^1.0.0"
+ }
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "dev": true
+ },
+ "p-reduce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz",
+ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=",
+ "dev": true
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ },
+ "pacote": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.4.0.tgz",
+ "integrity": "sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.3",
+ "cacache": "^11.3.2",
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.1.0",
+ "glob": "^7.1.3",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^4.0.1",
+ "minimatch": "^3.0.4",
+ "minipass": "^2.3.5",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-packlist": "^1.1.12",
+ "npm-pick-manifest": "^2.2.3",
+ "npm-registry-fetch": "^3.8.0",
+ "osenv": "^0.1.5",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "protoduck": "^5.0.1",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.2",
+ "semver": "^5.6.0",
+ "ssri": "^6.0.1",
+ "tar": "^4.4.8",
+ "unique-filename": "^1.1.1",
+ "which": "^1.3.1"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
+ "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "tar": {
+ "version": "4.4.13",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+ "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+ "dev": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ }
+ }
+ },
+ "pako": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz",
+ "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==",
+ "dev": true
+ },
+ "parallel-transform": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+ "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+ "dev": true,
+ "requires": {
+ "cyclist": "^1.0.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+ "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "dev": true,
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "parse-node-version": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
+ "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+ "dev": true
+ },
+ "parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "dev": true
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pause-stream": {
+ "version": "0.0.11",
+ "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+ "dev": true,
+ "requires": {
+ "through": "~2.3"
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+ "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "dev": true,
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "pdfkit": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.10.0.tgz",
+ "integrity": "sha512-mRJ6iuDzpIQ4ftKp5GvijLXNVRK86xjnyIPBraYSPrUPubNqWM5/oYmc7FZKUWz3wusRTj3PLR9HJ1X5ooqfsg==",
+ "dev": true,
+ "requires": {
+ "crypto-js": "^3.1.9-1",
+ "fontkit": "^1.0.0",
+ "linebreak": "^0.3.0",
+ "png-js": ">=0.1.0"
+ },
+ "dependencies": {
+ "base64-js": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
+ "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
+ "dev": true
+ },
+ "brfs": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz",
+ "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==",
+ "dev": true,
+ "requires": {
+ "quote-stream": "^1.0.1",
+ "resolve": "^1.1.5",
+ "static-module": "^2.2.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "linebreak": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-0.3.0.tgz",
+ "integrity": "sha1-BSZICmLAW9Z58+nZmDDgnGp9DtY=",
+ "dev": true,
+ "requires": {
+ "base64-js": "0.0.8",
+ "brfs": "^1.3.0",
+ "unicode-trie": "^0.3.0"
+ }
+ },
+ "magic-string": {
+ "version": "0.22.5",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
+ "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
+ "dev": true,
+ "requires": {
+ "vlq": "^0.2.2"
+ }
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ },
+ "static-module": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz",
+ "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "~1.6.0",
+ "convert-source-map": "^1.5.1",
+ "duplexer2": "~0.1.4",
+ "escodegen": "~1.9.0",
+ "falafel": "^2.1.0",
+ "has": "^1.0.1",
+ "magic-string": "^0.22.4",
+ "merge-source-map": "1.0.4",
+ "object-inspect": "~1.4.0",
+ "quote-stream": "~1.0.2",
+ "readable-stream": "~2.3.3",
+ "shallow-copy": "~0.0.1",
+ "static-eval": "^2.0.0",
+ "through2": "~2.0.3"
+ }
+ },
+ "unicode-trie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
+ "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
+ "dev": true,
+ "requires": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ }
+ }
+ },
+ "pdfmake": {
+ "version": "0.1.60",
+ "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.1.60.tgz",
+ "integrity": "sha512-vu+d9xaspGfMB0cNfH+CSet3q+Ip7/CRsx1LJLv2ToMduSTzqE4oTxjZQkPLB9LOL+36zT1SvbNvs0qoxusz1A==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "^0.5.0",
+ "linebreak": "^1.0.2",
+ "pdfkit": "^0.10.0",
+ "svg-to-pdfkit": "^0.1.7"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz",
+ "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz",
+ "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==",
+ "dev": true
+ },
+ "pidtree": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz",
+ "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pirates": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
+ "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==",
+ "dev": true,
+ "requires": {
+ "node-modules-regexp": "^1.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "pn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
+ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
+ "dev": true
+ },
+ "png-js": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/png-js/-/png-js-0.1.1.tgz",
+ "integrity": "sha1-HMfCEjA6yr50Jj7DrHgAlYAkLZM=",
+ "dev": true
+ },
+ "portfinder": {
+ "version": "1.0.25",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
+ "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz",
+ "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-import": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
+ "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.1",
+ "postcss-value-parser": "^3.2.3",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ }
+ },
+ "postcss-load-config": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
+ "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "import-cwd": "^2.0.0"
+ }
+ },
+ "postcss-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^7.0.0",
+ "postcss-load-config": "^2.0.0",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "prettier": {
+ "version": "1.16.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz",
+ "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==",
+ "dev": true
+ },
+ "pretty-format": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz",
+ "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^24.9.0",
+ "ansi-regex": "^4.0.0",
+ "ansi-styles": "^3.2.0",
+ "react-is": "^16.8.4"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ }
+ }
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "promise-retry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
+ "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
+ "dev": true,
+ "requires": {
+ "err-code": "^1.0.0",
+ "retry": "^0.10.0"
+ }
+ },
+ "prompts": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.2.1.tgz",
+ "integrity": "sha512-VObPvJiWPhpZI6C5m60XOzTfnYg/xc/an+r9VYymj9WJW3B/DIH+REzjpAACPf8brwPeP+7vz3bIim3S+AaMjw==",
+ "dev": true,
+ "requires": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.3"
+ }
+ },
+ "protoduck": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
+ "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
+ "dev": true,
+ "requires": {
+ "genfun": "^5.0.0"
+ }
+ },
+ "protractor": {
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz",
+ "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==",
+ "dev": true,
+ "requires": {
+ "@types/q": "^0.0.32",
+ "@types/selenium-webdriver": "^3.0.0",
+ "blocking-proxy": "^1.0.0",
+ "browserstack": "^1.5.1",
+ "chalk": "^1.1.3",
+ "glob": "^7.0.3",
+ "jasmine": "2.8.0",
+ "jasminewd2": "^2.1.0",
+ "optimist": "~0.6.0",
+ "q": "1.4.1",
+ "saucelabs": "^1.5.0",
+ "selenium-webdriver": "3.6.0",
+ "source-map-support": "~0.4.0",
+ "webdriver-js-extender": "2.1.0",
+ "webdriver-manager": "^12.0.6"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "^5.0.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.5.6"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "webdriver-manager": {
+ "version": "12.1.7",
+ "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz",
+ "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==",
+ "dev": true,
+ "requires": {
+ "adm-zip": "^0.4.9",
+ "chalk": "^1.1.1",
+ "del": "^2.2.0",
+ "glob": "^7.0.3",
+ "ini": "^1.3.4",
+ "minimist": "^1.2.0",
+ "q": "^1.4.1",
+ "request": "^2.87.0",
+ "rimraf": "^2.5.2",
+ "semver": "^5.3.0",
+ "xml2js": "^0.4.17"
+ }
+ }
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "dev": true,
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "proxy-middleware": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz",
+ "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=",
+ "dev": true
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "psl": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
+ "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ },
+ "q": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
+ "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+ "dev": true
+ },
+ "quote-stream": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz",
+ "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=",
+ "dev": true,
+ "requires": {
+ "buffer-equal": "0.0.1",
+ "minimist": "^1.1.3",
+ "through2": "^2.0.0"
+ }
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ }
+ }
+ },
+ "raw-loader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz",
+ "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "react-is": {
+ "version": "16.11.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
+ "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==",
+ "dev": true
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+ "dev": true,
+ "requires": {
+ "pify": "^2.3.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "realpath-native": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz",
+ "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==",
+ "dev": true,
+ "requires": {
+ "util.promisify": "^1.0.0"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.1.6"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.18.0",
+ "babel-types": "^6.19.0",
+ "private": "^0.1.6"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
+ "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2"
+ }
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "replace-in-file": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-3.4.3.tgz",
+ "integrity": "sha512-m62vEDCIL1B8uzymh+YKMLb4N4LdX5A5ObxOjap4wyCHzWqblAUYO5vhjWwk7zfR8PkTRIdPZVo/u4h33clnew==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "glob": "^7.1.2",
+ "yargs": "^12.0.5"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "request-promise-core": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz",
+ "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.11"
+ }
+ },
+ "request-promise-native": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz",
+ "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==",
+ "dev": true,
+ "requires": {
+ "request-promise-core": "1.1.2",
+ "stealthy-require": "^1.1.1",
+ "tough-cookie": "^2.3.3"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
+ "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "restructure": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/restructure/-/restructure-0.5.4.tgz",
+ "integrity": "sha1-9U591WNZD7NP1r9Vh2EJrsyyjeg=",
+ "dev": true,
+ "requires": {
+ "browserify-optional": "^1.0.0"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "retry": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+ "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
+ "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "rsvp": {
+ "version": "4.8.5",
+ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
+ "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
+ "dev": true
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "^2.1.0"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rxjs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
+ "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "rxjs-compat": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.5.2.tgz",
+ "integrity": "sha512-TRMkTp4FgSxE2HtGvxmgRukh3JqdFM7ejAj1Ti/VdodbPGfWvZR5+KdLKRV9jVDFyu2SknM8RD+PR54KGnoLjg=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "sane": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz",
+ "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==",
+ "dev": true,
+ "requires": {
+ "@cnakazawa/watch": "^1.0.3",
+ "anymatch": "^2.0.0",
+ "capture-exit": "^2.0.0",
+ "exec-sh": "^0.3.2",
+ "execa": "^1.0.0",
+ "fb-watchman": "^2.0.0",
+ "micromatch": "^3.1.4",
+ "minimist": "^1.1.1",
+ "walker": "~1.0.5"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "sass-graph": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+ "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.0.0",
+ "lodash": "^4.0.0",
+ "scss-tokenizer": "^0.2.3",
+ "yargs": "^7.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true,
+ "optional": true
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "lcid": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+ "dev": true,
+ "optional": true
+ },
+ "yargs": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase": "^3.0.0",
+ "cliui": "^3.2.0",
+ "decamelize": "^1.1.1",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^1.4.0",
+ "read-pkg-up": "^1.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^1.0.2",
+ "which-module": "^1.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^5.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase": "^3.0.0"
+ }
+ }
+ }
+ },
+ "sass-loader": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
+ "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==",
+ "dev": true,
+ "requires": {
+ "clone-deep": "^2.0.1",
+ "loader-utils": "^1.0.1",
+ "lodash.tail": "^4.1.1",
+ "neo-async": "^2.5.0",
+ "pify": "^3.0.0",
+ "semver": "^5.5.0"
+ }
+ },
+ "saucelabs": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
+ "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "scope-analyzer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.0.5.tgz",
+ "integrity": "sha512-+U5H0417mnTEstCD5VwOYO7V4vYuSqwqjFap40ythe67bhMFL5C3UgPwyBv7KDJsqUBIKafOD57xMlh1rN7eaw==",
+ "dev": true,
+ "requires": {
+ "array-from": "^2.1.1",
+ "es6-map": "^0.1.5",
+ "es6-set": "^0.1.5",
+ "es6-symbol": "^3.1.1",
+ "estree-is-function": "^1.0.0",
+ "get-assigned-identifiers": "^1.1.0"
+ }
+ },
+ "scss-tokenizer": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "js-base64": "^2.1.8",
+ "source-map": "^0.4.2"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selenium-webdriver": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
+ "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
+ "dev": true,
+ "requires": {
+ "jszip": "^3.1.3",
+ "rimraf": "^2.5.4",
+ "tmp": "0.0.30",
+ "xml2js": "^0.4.17"
+ },
+ "dependencies": {
+ "tmp": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
+ "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.1"
+ }
+ }
+ }
+ },
+ "selfsigned": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
+ "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.9.0"
+ }
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+ "dev": true
+ },
+ "semver-dsl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
+ "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
+ "semver-intersect": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz",
+ "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.0"
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
+ "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
+ "dev": true
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
+ "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.1",
+ "kind-of": "^5.0.0",
+ "mixin-object": "^2.0.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "shallow-copy": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
+ "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "shell-quote": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
+ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "dev": true
+ },
+ "shelljs": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
+ "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ }
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "sisteransi": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.3.tgz",
+ "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "smart-buffer": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
+ "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "sockjs": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.0.1"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz",
+ "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "socks": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz",
+ "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.5",
+ "smart-buffer": "4.0.2"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz",
+ "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "~4.2.1",
+ "socks": "~2.3.2"
+ },
+ "dependencies": {
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "source-map-loader": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz",
+ "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.5.0",
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz",
+ "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "sourcemap-codec": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
+ "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "spdy": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz",
+ "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+ "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "speed-measure-webpack-plugin": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz",
+ "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "dev": true,
+ "requires": {
+ "through": "2"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "stack-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz",
+ "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==",
+ "dev": true
+ },
+ "static-eval": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
+ "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
+ "dev": true,
+ "requires": {
+ "escodegen": "^1.8.1"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "static-module": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.3.tgz",
+ "integrity": "sha512-RDaMYaI5o/ym0GkCqL/PlD1Pn216omp8fY81okxZ6f6JQxWW5tptOw9reXoZX85yt/scYvbWIt6uoszeyf+/MQ==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.3.0",
+ "concat-stream": "~1.6.0",
+ "convert-source-map": "^1.5.1",
+ "duplexer2": "~0.1.4",
+ "escodegen": "~1.9.0",
+ "has": "^1.0.1",
+ "magic-string": "^0.22.4",
+ "merge-source-map": "1.0.4",
+ "object-inspect": "~1.4.0",
+ "readable-stream": "~2.3.3",
+ "scope-analyzer": "^2.0.1",
+ "shallow-copy": "~0.0.1",
+ "static-eval": "^2.0.2",
+ "through2": "~2.0.3"
+ },
+ "dependencies": {
+ "magic-string": {
+ "version": "0.22.5",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
+ "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
+ "dev": true,
+ "requires": {
+ "vlq": "^0.2.2"
+ }
+ }
+ }
+ },
+ "stats-webpack-plugin": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz",
+ "integrity": "sha512-NT0YGhwuQ0EOX+uPhhUcI6/+1Sq/pMzNuSCBVT4GbFl/ac6I/JZefBcjlECNfAb1t3GOx5dEj1Z7x0cAxeeVLQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.4"
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true
+ },
+ "stdout-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
+ "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "stealthy-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
+ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-combiner": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+ "dev": true,
+ "requires": {
+ "duplexer": "~0.1.1"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "string-length": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
+ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=",
+ "dev": true,
+ "requires": {
+ "astral-regex": "^1.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string.prototype.padend": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz",
+ "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.4.3",
+ "function-bind": "^1.0.2"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
+ "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
+ "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "style-loader": {
+ "version": "0.23.1",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz",
+ "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "stylus": {
+ "version": "0.54.5",
+ "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
+ "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
+ "dev": true,
+ "requires": {
+ "css-parse": "1.7.x",
+ "debug": "*",
+ "glob": "7.0.x",
+ "mkdirp": "0.5.x",
+ "sax": "0.5.x",
+ "source-map": "0.1.x"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "dev": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "stylus-loader": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
+ "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "lodash.clonedeep": "^4.5.0",
+ "when": "~3.6.x"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svg-to-pdfkit": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/svg-to-pdfkit/-/svg-to-pdfkit-0.1.7.tgz",
+ "integrity": "sha1-fbbUfkeziI3OGAYHUajeJBf4V3U=",
+ "dev": true,
+ "requires": {
+ "pdfkit": ">=0.8.1"
+ }
+ },
+ "swagger-ui-dist": {
+ "version": "3.23.10",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.23.10.tgz",
+ "integrity": "sha512-lK9oNNb9HAz2HJIg6+cYZszbYC/0CTm0nWi0XX2AjEbVgu43smbW2/h5zn7yAjYstPJBaYXkt5g6ABRpO/Ncfg=="
+ },
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
+ "dev": true
+ },
+ "symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+ "dev": true
+ },
+ "tar": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+ "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "block-stream": "*",
+ "fstream": "^1.0.12",
+ "inherits": "2"
+ }
+ },
+ "terser": {
+ "version": "3.17.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
+ "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.19.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.10"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.2.tgz",
+ "integrity": "sha512-1DMkTk286BzmfylAvLXwpJrI7dWa5BnFmscV/2dCr8+c56egFcbaeFAl7+sujAjdmpLam21XRdhA4oifLyiWWg==",
+ "dev": true,
+ "requires": {
+ "cacache": "^11.0.2",
+ "find-cache-dir": "^2.0.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^1.4.0",
+ "source-map": "^0.6.1",
+ "terser": "^3.16.1",
+ "webpack-sources": "^1.1.0",
+ "worker-farm": "^1.5.2"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ }
+ }
+ },
+ "test-exclude": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+ "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3",
+ "minimatch": "^3.0.4",
+ "read-pkg-up": "^4.0.0",
+ "require-main-filename": "^2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+ "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0",
+ "read-pkg": "^3.0.0"
+ }
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "throat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
+ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true
+ },
+ "time-stamp": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
+ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+ "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+ "dev": true,
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "tmpl": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
+ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "dev": true
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "tr46": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "transifex-i18ntool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/transifex-i18ntool/-/transifex-i18ntool-1.1.0.tgz",
+ "integrity": "sha512-W1FIGosZJ3cxbYk238QgsJvKPq12dPDIMn3rg37ZHNtoNAGrUAV6wKp+YSFwnMcqk3igZcAEPlLW1jFjBFC95Q==",
+ "dev": true,
+ "requires": {
+ "colors": "^1.0.3",
+ "minimist": "^1.2.0",
+ "prompts": "^2.0.4",
+ "request": "^2.88.0",
+ "request-promise-native": "^1.0.7",
+ "xliff": "^4.2.0"
+ }
+ },
+ "traverse": {
+ "version": "0.6.6",
+ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
+ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
+ "dev": true
+ },
+ "tree-kill": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz",
+ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==",
+ "dev": true
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true,
+ "optional": true
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "true-case-path": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
+ "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.2"
+ }
+ },
+ "ts-jest": {
+ "version": "23.1.4",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.1.4.tgz",
+ "integrity": "sha512-9rCSxbWfoZxxeXnSoEIzRNr9hDIQ8iEJAWmSRsWhDHDT8OeuGfURhJQUE8jtJlkyEygs6rngH8RYtHz9cfjmEA==",
+ "dev": true,
+ "requires": {
+ "closest-file-data": "^0.1.4",
+ "fs-extra": "6.0.1",
+ "json5": "^0.5.0",
+ "lodash": "^4.17.10"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
+ "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ }
+ }
+ },
+ "ts-node": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.2.tgz",
+ "integrity": "sha512-MosTrinKmaAcWgO8tqMjMJB22h+sp3Rd1i4fdoWY4mhBDekOwIAKI/bzmRi7IcbCmjquccYg2gcF6NBkLgr0Tw==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^3.1.0",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^3.0.0"
+ }
+ },
+ "ts-simple-ast": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/ts-simple-ast/-/ts-simple-ast-12.4.0.tgz",
+ "integrity": "sha512-7GJFZlyTZY7uMAEhX62ZLxdwOpGDJzc/nwpi1nRPZ7N2ICcqqrMjDtRnki15IUBv2ZjIGu6KBqk/pUqJFODFsg==",
+ "dev": true,
+ "requires": {
+ "@dsherret/to-absolute-glob": "^2.0.2",
+ "code-block-writer": "^7.2.0",
+ "fs-extra": "^6.0.1",
+ "glob-parent": "^3.1.0",
+ "globby": "^8.0.1",
+ "is-negated-glob": "^1.0.0",
+ "multimatch": "^2.1.0",
+ "object-assign": "^4.1.1",
+ "tslib": "^1.9.0",
+ "typescript": "2.9.1"
+ },
+ "dependencies": {
+ "dir-glob": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
+ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "path-type": "^3.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
+ "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "globby": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz",
+ "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "2.0.0",
+ "fast-glob": "^2.0.2",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz",
+ "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+ },
+ "tslint": {
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz",
+ "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "typescript": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz",
+ "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.0.tgz",
+ "integrity": "sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "commander": "~2.20.3",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "unc-path-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
+ "dev": true
+ },
+ "unicode-properties": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.3.1.tgz",
+ "integrity": "sha512-nIV3Tf3LcUEZttY/2g4ZJtGXhWwSkuLL+rCu0DIAMbjyVPj+8j5gNVz4T/sVbnQybIsd5SFGkPKg/756OY6jlA==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.3.0",
+ "unicode-trie": "^2.0.0"
+ },
+ "dependencies": {
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ },
+ "unicode-trie": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
+ "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
+ "dev": true,
+ "requires": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ }
+ }
+ },
+ "unicode-trie": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-1.0.0.tgz",
+ "integrity": "sha512-v5raLKsobbFbWLMoX9+bChts/VhPPj3XpkNr/HbqkirXR1DPk8eo9IYKyvk0MQZFkaoRsFj2Rmaqgi2rfAZYtA==",
+ "dev": true,
+ "requires": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ },
+ "dependencies": {
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
+ "dev": true
+ }
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "unix-crypt-td-js": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz",
+ "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "url-parse": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+ "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+ "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "util.promisify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz",
+ "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.2",
+ "has-symbols": "^1.0.1",
+ "object.getownpropertydescriptors": "^2.1.0"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.4",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz",
+ "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.1.5",
+ "is-regex": "^1.0.5",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimleft": "^2.1.1",
+ "string.prototype.trimright": "^2.1.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+ "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+ "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "object-inspect": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
+ "dev": true
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
+ "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
+ "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
+ "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ }
+ }
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+ "dev": true,
+ "requires": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "viz.js": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/viz.js/-/viz.js-1.8.2.tgz",
+ "integrity": "sha512-W+1+N/hdzLpQZEcvz79n2IgUE9pfx6JLdHh3Kh8RGvLL8P1LdJVQmi2OsDcLdY4QVID4OUy+FPelyerX0nJxIQ==",
+ "dev": true
+ },
+ "vlq": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
+ "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
+ "dev": true
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+ "dev": true
+ },
+ "w3c-hr-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",
+ "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=",
+ "dev": true,
+ "requires": {
+ "browser-process-hrtime": "^0.1.2"
+ }
+ },
+ "walker": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
+ "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=",
+ "dev": true,
+ "requires": {
+ "makeerror": "1.0.x"
+ }
+ },
+ "watchpack": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
+ "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webdriver-js-extender": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
+ "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==",
+ "dev": true,
+ "requires": {
+ "@types/selenium-webdriver": "^3.0.0",
+ "selenium-webdriver": "^3.0.1"
+ }
+ },
+ "webidl-conversions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+ "dev": true
+ },
+ "webpack": {
+ "version": "4.29.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.0.tgz",
+ "integrity": "sha512-pxdGG0keDBtamE1mNvT5zyBdx+7wkh6mh7uzMOo/uRQ/fhsdj5FXkh/j5mapzs060forql1oXqXN9HJGju+y7w==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/wasm-edit": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "acorn": "^6.0.5",
+ "acorn-dynamic-import": "^4.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chrome-trace-event": "^1.0.0",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "micromatch": "^3.1.8",
+ "mkdirp": "~0.5.0",
+ "neo-async": "^2.5.0",
+ "node-libs-browser": "^2.0.0",
+ "schema-utils": "^0.4.4",
+ "tapable": "^1.1.0",
+ "terser-webpack-plugin": "^1.1.0",
+ "watchpack": "^1.5.0",
+ "webpack-sources": "^1.3.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "webpack-core": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
+ "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
+ "dev": true,
+ "requires": {
+ "source-list-map": "~0.1.7",
+ "source-map": "~0.4.1"
+ },
+ "dependencies": {
+ "source-list-map": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
+ "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.5.1.tgz",
+ "integrity": "sha512-4dwCh/AyMOYAybggUr8fiCkRnjVDp+Cqlr9c+aaNB3GJYgRGYQWJ1YX/WAKUNA9dPNHZ6QSN2lYDKqjKSI8Vqw==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "~0.4.1",
+ "mime": "^2.3.1",
+ "range-parser": "^1.0.3",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.1.14",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz",
+ "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.0.0",
+ "compression": "^1.5.2",
+ "connect-history-api-fallback": "^1.3.0",
+ "debug": "^3.1.0",
+ "del": "^3.0.0",
+ "express": "^4.16.2",
+ "html-entities": "^1.2.0",
+ "http-proxy-middleware": "~0.18.0",
+ "import-local": "^2.0.0",
+ "internal-ip": "^3.0.1",
+ "ip": "^1.1.5",
+ "killable": "^1.0.0",
+ "loglevel": "^1.4.1",
+ "opn": "^5.1.0",
+ "portfinder": "^1.0.9",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.9.1",
+ "semver": "^5.6.0",
+ "serve-index": "^1.7.2",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.3.0",
+ "spdy": "^4.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^5.1.0",
+ "url": "^0.11.0",
+ "webpack-dev-middleware": "3.4.0",
+ "webpack-log": "^2.0.0",
+ "yargs": "12.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz",
+ "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==",
+ "dev": true,
+ "requires": {
+ "xregexp": "4.0.0"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz",
+ "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "~0.4.1",
+ "mime": "^2.3.1",
+ "range-parser": "^1.0.3",
+ "webpack-log": "^2.0.0"
+ }
+ },
+ "yargs": {
+ "version": "12.0.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz",
+ "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^2.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^10.1.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
+ "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "webpack-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz",
+ "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.5"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
+ "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-subresource-integrity": {
+ "version": "1.1.0-rc.6",
+ "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz",
+ "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==",
+ "dev": true,
+ "requires": {
+ "webpack-core": "^0.6.8"
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
+ "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.4.0 <0.4.11",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "dev": true
+ },
+ "whatwg-encoding": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
+ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.24"
+ }
+ },
+ "whatwg-mimetype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
+ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
+ "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "when": {
+ "version": "3.6.4",
+ "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
+ "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "windows-release": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz",
+ "integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "dev": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write-file-atomic": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz",
+ "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ws": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
+ "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "xliff": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/xliff/-/xliff-4.4.0.tgz",
+ "integrity": "sha512-SVzjB3hTHJ/CbsIJtbQg2BAxhvVJqbZ3OluMS7u6JnCbf0/twuj2KASghYHiKHz2sJqZo42dGjydp0URKmWWoA==",
+ "dev": true,
+ "requires": {
+ "xml-js": "1.6.11"
+ }
+ },
+ "xml-js": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
+ "dev": true,
+ "requires": {
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ }
+ }
+ },
+ "xml-name-validator": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true
+ },
+ "xml2js": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+ "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "dev": true,
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ }
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true
+ },
+ "xregexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz",
+ "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "yargs": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz",
+ "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==",
+ "requires": {
+ "cliui": "^3.2.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^8.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
+ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
+ },
+ "zone.js": {
+ "version": "0.8.29",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz",
+ "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ=="
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/package.json b/src/pybind/mgr/dashboard/frontend/package.json
new file mode 100644
index 00000000..7e8ed52f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/package.json
@@ -0,0 +1,139 @@
+{
+ "name": "ceph-dashboard",
+ "version": "0.0.0",
+ "license": "MIT",
+ "config": {
+ "locale": "en-US"
+ },
+ "scripts": {
+ "ng": "ng",
+ "start": "npm run env_build && ng serve --host 0.0.0.0 --ssl",
+ "build": "export _locale=${LOCALE:-$npm_package_config_locale}; if [ ${_locale} = $npm_package_config_locale ]; then export _file=; else export _file=src/locale/messages.${_locale}.xlf; fi; ng build --outputPath=dist/${_locale} --i18nFile=${_file} --i18nLocale=${_locale}",
+ "prebuild": "npm run env_build",
+ "build:en-US": "LOCALE=en-US npm run build",
+ "build:de-DE": "LOCALE=de-DE npm run build",
+ "build:es-ES": "LOCALE=es-ES npm run build",
+ "build:pt-BR": "LOCALE=pt-BR npm run build",
+ "build:it-IT": "LOCALE=it-IT npm run build",
+ "build:cs": "LOCALE=cs npm run build",
+ "build:fr-FR": "LOCALE=fr-FR npm run build",
+ "build:id-ID": "LOCALE=id-ID npm run build",
+ "build:ja-JP": "LOCALE=ja-JP npm run build",
+ "build:pl-PL": "LOCALE=pl-PL npm run build",
+ "build:zh-CN": "LOCALE=zh-CN npm run build",
+ "build:zh-TW": "LOCALE=zh-TW npm run build",
+ "env_build": "cp src/environments/environment.tpl.ts src/environments/environment.prod.ts && cp src/environments/environment.tpl.ts src/environments/environment.ts && node ./environment.build.js",
+ "i18n": "npm run i18n:extract && npm run i18n:push && npm run i18n:pull && npm run i18n:merge",
+ "i18n:extract": "ng xi18n --i18n-format xlf --i18n-locale en-US --output-path locale --progress=false && ngx-extractor -i 'src/**/*.ts' -f xlf -o src/locale/messages.xlf -l en-US",
+ "i18n:push": "npx i18ntool push -c i18n.config.json",
+ "i18n:pull": "npx i18ntool pull -c i18n.config.json",
+ "i18n:merge": "npx i18ntool merge -c i18n.config.json",
+ "i18n:token": "npx i18ntool config token",
+ "test": "npm run test:config && jest --watch",
+ "test:ci": "npm run test:config && JEST_SILENT_REPORTER_DOTS=true jest --coverage --reporters jest-silent-reporter",
+ "test:config": "if [ ! -e 'src/unit-test-configuration.ts' ]; then cp 'src/unit-test-configuration.ts.sample' 'src/unit-test-configuration.ts'; fi",
+ "e2e": "npm run env_build && npm run e2e:update && ng e2e --webdriverUpdate=false",
+ "e2e:dev": "npm run env_build && npm run e2e:update && ng e2e --dev-server-target --webdriverUpdate=false",
+ "e2e:update": "npx webdriver-manager update --ignore_ssl --gecko=false --versions.chrome=$(google-chrome --version | awk '{ print $3 }')",
+ "lint:tslint": "ng lint",
+ "lint:prettier": "prettier --list-different \"{src,e2e}/**/*.{ts,scss}\"",
+ "lint:html": "html-linter --config html-linter.config.json",
+ "lint:tsc": "npm run test:config && tsc -p src/tsconfig.app.json --noEmit --noUnusedLocals --noUnusedParameters && tsc -p src/tsconfig.spec.json --noEmit --noUnusedLocals --noUnusedParameters && tsc -p e2e/tsconfig.e2e.json --noEmit --noUnusedLocals --noUnusedParameters",
+ "lint": "npm run lint:tsc && npm run lint:tslint && npm run lint:prettier && npm run lint:html",
+ "fix:prettier": "prettier --write \"{src,e2e}/**/*.{ts,scss}\"",
+ "fix:tslint": "npm run lint:tslint -- --fix",
+ "fixmod": "prettier --write $(git rev-parse --show-toplevel)/$(git status --porcelain | grep -E '^(\\sM|\\?\\?|A)' | sed -e 's/^...//' | grep -E '^(src|e2e).*\\.(ts|scss)$') 1>/dev/null 2>&1 && echo 'done' || echo 'no changes found'",
+ "fix": "npm run fix:tslint; npm run fix:prettier",
+ "compodoc": "compodoc",
+ "doc-build": "compodoc -p src/tsconfig.app.json",
+ "doc-serve": "compodoc --port 8444 -s src/tsconfig.app.json"
+ },
+ "private": true,
+ "jest": {
+ "preset": "jest-preset-angular",
+ "setupFilesAfterEnv": [
+ "<rootDir>/src/setupJest.ts"
+ ],
+ "transformIgnorePatterns": [
+ "node_modules/(?!@ngrx|ngx-bootstrap|@progress)"
+ ],
+ "transform": {
+ "^.+\\.(ts|html)$": "<rootDir>/node_modules/jest-preset-angular/preprocessor.js",
+ "^.+\\.js$": "babel-jest"
+ },
+ "setupFiles": [
+ "jest-canvas-mock"
+ ],
+ "coverageReporters": [
+ "cobertura",
+ "html"
+ ],
+ "modulePathIgnorePatterns": [
+ "<rootDir>/coverage/"
+ ],
+ "testMatch": [
+ "**/*.spec.ts"
+ ],
+ "testURL": "http://localhost/"
+ },
+ "dependencies": {
+ "@angular/animations": "7.2.6",
+ "@angular/common": "7.2.6",
+ "@angular/compiler": "7.2.6",
+ "@angular/core": "7.2.6",
+ "@angular/forms": "7.2.6",
+ "@angular/http": "7.2.6",
+ "@angular/platform-browser": "7.2.6",
+ "@angular/platform-browser-dynamic": "7.2.6",
+ "@angular/router": "7.2.6",
+ "@ngx-translate/i18n-polyfill": "1.0.0",
+ "@swimlane/ngx-datatable": "14.0.0",
+ "awesome-bootstrap-checkbox": "0.3.7",
+ "bootstrap": "3.4.1",
+ "chart.js": "2.7.3",
+ "core-js": "2.6.5",
+ "detect-browser": "4.1.0",
+ "fork-awesome": "1.1.6",
+ "lodash": "4.17.14",
+ "moment": "2.24.0",
+ "ng-block-ui": "2.1.1",
+ "ng2-charts": "1.6.0",
+ "ng2-tree": "2.0.0-rc.11",
+ "ngx-bootstrap": "5.1.0",
+ "ngx-toastr": "10.0.4",
+ "rxjs": "6.5.2",
+ "rxjs-compat": "6.5.2",
+ "swagger-ui-dist": "3.23.10",
+ "tslib": "1.9.3",
+ "zone.js": "0.8.29"
+ },
+ "devDependencies": {
+ "@angular-devkit/build-angular": "0.13.9",
+ "@angular/cli": "7.3.3",
+ "@angular/compiler-cli": "7.2.6",
+ "@angular/language-service": "7.2.6",
+ "@compodoc/compodoc": "1.1.10",
+ "@types/jasmine": "3.3.9",
+ "@types/jasminewd2": "2.0.6",
+ "@types/jest": "24.0.9",
+ "@types/lodash": "4.14.121",
+ "@types/node": "11.9.5",
+ "babel-preset-env": "1.7.0",
+ "codelyzer": "4.5.0",
+ "html-linter": "1.1.1",
+ "jasmine-core": "3.3.0",
+ "jasmine-spec-reporter": "4.2.1",
+ "jest": "24.8.0",
+ "jest-canvas-mock": "1.1.0",
+ "jest-preset-angular": "6.0.2",
+ "jest-silent-reporter": "0.1.2",
+ "prettier": "1.16.4",
+ "npm-run-all": "^4.1.5",
+ "protractor": "5.4.2",
+ "replace-in-file": "3.4.3",
+ "transifex-i18ntool": "1.1.0",
+ "ts-node": "8.0.2",
+ "tslint": "5.18.0",
+ "typescript": "3.2.4"
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/protractor.conf.js b/src/pybind/mgr/dashboard/frontend/protractor.conf.js
new file mode 100644
index 00000000..f9038245
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/protractor.conf.js
@@ -0,0 +1,58 @@
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+exports.config = {
+ allScriptsTimeout: 11000,
+ specs: [
+ './e2e/**/*.e2e-spec.ts'
+ ],
+ capabilities: {
+ 'browserName': 'chrome',
+ chromeOptions: {
+ args: ['--no-sandbox', '--headless', '--window-size=1920x1080']
+ },
+ acceptInsecureCerts : true
+ },
+ directConnect: true,
+ baseUrl: 'http://localhost:4200/',
+ framework: 'jasmine',
+ jasmineNodeOpts: {
+ showColors: true,
+ defaultTimeoutInterval: 30000,
+ print: function() {}
+ },
+ params: {
+ login: {
+ user: 'admin',
+ password: 'admin'
+ }
+ },
+ onPrepare() {
+ browser.manage().timeouts().implicitlyWait(360000);
+
+ require('ts-node').register({
+ project: 'e2e/tsconfig.e2e.json'
+ });
+ jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+
+ browser.get('/#/login');
+
+ browser.driver.findElement(by.name('username')).clear();
+ browser.driver.findElement(by.name('username')).sendKeys(browser.params.login.user);
+ browser.driver.findElement(by.name('password')).clear();
+ browser.driver.findElement(by.name('password')).sendKeys(browser.params.login.password);
+
+ browser.driver.findElement(by.css('input[type="submit"]')).click();
+
+ // Login takes some time, so wait until it's done.
+ // For the test app's login, we know it's done when it redirects to
+ // dashboard.
+ return browser.driver.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return /dashboard/.test(url);
+ });
+ });
+ }
+};
diff --git a/src/pybind/mgr/dashboard/frontend/proxy.conf.json.sample b/src/pybind/mgr/dashboard/frontend/proxy.conf.json.sample
new file mode 100644
index 00000000..6a71a26b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/proxy.conf.json.sample
@@ -0,0 +1,12 @@
+{
+ "/api/": {
+ "target": "https://localhost:8443",
+ "secure": false,
+ "logLevel": "debug"
+ },
+ "/ui-api/": {
+ "target": "https://localhost:8443",
+ "secure": false,
+ "logLevel": "debug"
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts
new file mode 100644
index 00000000..4553ce8e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts
@@ -0,0 +1,268 @@
+import { NgModule } from '@angular/core';
+import { ActivatedRouteSnapshot, PreloadAllModules, RouterModule, Routes } from '@angular/router';
+
+import * as _ from 'lodash';
+
+import { CephfsListComponent } from './ceph/cephfs/cephfs-list/cephfs-list.component';
+import { ConfigurationFormComponent } from './ceph/cluster/configuration/configuration-form/configuration-form.component';
+import { ConfigurationComponent } from './ceph/cluster/configuration/configuration.component';
+import { CrushmapComponent } from './ceph/cluster/crushmap/crushmap.component';
+import { HostsComponent } from './ceph/cluster/hosts/hosts.component';
+import { LogsComponent } from './ceph/cluster/logs/logs.component';
+import { MgrModuleFormComponent } from './ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component';
+import { MgrModuleListComponent } from './ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component';
+import { MonitorComponent } from './ceph/cluster/monitor/monitor.component';
+import { OsdListComponent } from './ceph/cluster/osd/osd-list/osd-list.component';
+import { MonitoringListComponent } from './ceph/cluster/prometheus/monitoring-list/monitoring-list.component';
+import { SilenceFormComponent } from './ceph/cluster/prometheus/silence-form/silence-form.component';
+import { DashboardComponent } from './ceph/dashboard/dashboard/dashboard.component';
+import { Nfs501Component } from './ceph/nfs/nfs-501/nfs-501.component';
+import { NfsFormComponent } from './ceph/nfs/nfs-form/nfs-form.component';
+import { NfsListComponent } from './ceph/nfs/nfs-list/nfs-list.component';
+import { PerformanceCounterComponent } from './ceph/performance-counter/performance-counter/performance-counter.component';
+import { LoginComponent } from './core/auth/login/login.component';
+import { SsoNotFoundComponent } from './core/auth/sso/sso-not-found/sso-not-found.component';
+import { ForbiddenComponent } from './core/forbidden/forbidden.component';
+import { NotFoundComponent } from './core/not-found/not-found.component';
+import { ActionLabels, URLVerbs } from './shared/constants/app.constants';
+import { BreadcrumbsResolver, IBreadcrumb } from './shared/models/breadcrumbs';
+import { AuthGuardService } from './shared/services/auth-guard.service';
+import { FeatureTogglesGuardService } from './shared/services/feature-toggles-guard.service';
+import { ModuleStatusGuardService } from './shared/services/module-status-guard.service';
+
+export class PerformanceCounterBreadcrumbsResolver extends BreadcrumbsResolver {
+ resolve(route: ActivatedRouteSnapshot) {
+ const result: IBreadcrumb[] = [];
+
+ const fromPath = route.queryParams.fromLink || null;
+ let fromText = '';
+ switch (fromPath) {
+ case '/monitor':
+ fromText = 'Monitors';
+ break;
+ case '/hosts':
+ fromText = 'Hosts';
+ break;
+ }
+ result.push({ text: 'Cluster', path: null });
+ result.push({ text: fromText, path: fromPath });
+ result.push({ text: 'Performance Counters', path: '' });
+
+ return result;
+ }
+}
+
+export class StartCaseBreadcrumbsResolver extends BreadcrumbsResolver {
+ resolve(route: ActivatedRouteSnapshot) {
+ const path = route.params.name;
+ const text = _.startCase(path);
+ return [{ text: text, path: path }];
+ }
+}
+
+const routes: Routes = [
+ // Dashboard
+ { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
+ { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuardService] },
+ // Cluster
+ {
+ path: 'hosts',
+ component: HostsComponent,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/Hosts' }
+ },
+ {
+ path: 'monitor',
+ component: MonitorComponent,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/Monitors' }
+ },
+ {
+ path: 'osd',
+ canActivate: [AuthGuardService],
+ canActivateChild: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/OSDs' },
+ children: [{ path: '', component: OsdListComponent }]
+ },
+ {
+ path: 'configuration',
+ data: { breadcrumbs: 'Cluster/Configuration' },
+ children: [
+ { path: '', component: ConfigurationComponent },
+ {
+ path: 'edit/:name',
+ component: ConfigurationFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ },
+ {
+ path: 'crush-map',
+ component: CrushmapComponent,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/CRUSH map' }
+ },
+ {
+ path: 'logs',
+ component: LogsComponent,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/Logs' }
+ },
+ {
+ path: 'monitoring',
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/Monitoring' },
+ children: [
+ {
+ path: '',
+ component: MonitoringListComponent
+ },
+ {
+ path: 'silence/' + URLVerbs.CREATE,
+ component: SilenceFormComponent,
+ data: { breadcrumbs: `${ActionLabels.CREATE} Silence` }
+ },
+ {
+ path: `silence/${URLVerbs.CREATE}/:id`,
+ component: SilenceFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `silence/${URLVerbs.EDIT}/:id`,
+ component: SilenceFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ },
+ {
+ path: `silence/${URLVerbs.RECREATE}/:id`,
+ component: SilenceFormComponent,
+ data: { breadcrumbs: ActionLabels.RECREATE }
+ }
+ ]
+ },
+ {
+ path: 'perf_counters/:type/:id',
+ component: PerformanceCounterComponent,
+ canActivate: [AuthGuardService],
+ data: {
+ breadcrumbs: PerformanceCounterBreadcrumbsResolver
+ }
+ },
+ // Mgr modules
+ {
+ path: 'mgr-modules',
+ canActivate: [AuthGuardService],
+ canActivateChild: [AuthGuardService],
+ data: { breadcrumbs: 'Cluster/Manager modules' },
+ children: [
+ {
+ path: '',
+ component: MgrModuleListComponent
+ },
+ {
+ path: 'edit/:name',
+ component: MgrModuleFormComponent,
+ data: {
+ breadcrumbs: StartCaseBreadcrumbsResolver
+ }
+ }
+ ]
+ },
+ // Pools
+ {
+ path: 'pool',
+ canActivate: [AuthGuardService],
+ canActivateChild: [AuthGuardService],
+ data: { breadcrumbs: 'Pools' },
+ loadChildren: './ceph/pool/pool.module#RoutedPoolModule'
+ },
+ // Block
+ {
+ path: 'block',
+ canActivateChild: [AuthGuardService],
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: true, text: 'Block', path: null },
+ loadChildren: './ceph/block/block.module#RoutedBlockModule'
+ },
+ // Filesystems
+ {
+ path: 'cephfs',
+ component: CephfsListComponent,
+ canActivate: [FeatureTogglesGuardService, AuthGuardService],
+ data: { breadcrumbs: 'Filesystems' }
+ },
+ // Object Gateway
+ {
+ path: 'rgw',
+ canActivateChild: [FeatureTogglesGuardService, ModuleStatusGuardService, AuthGuardService],
+ data: {
+ moduleStatusGuardConfig: {
+ apiPath: 'rgw',
+ redirectTo: 'rgw/501'
+ },
+ breadcrumbs: true,
+ text: 'Object Gateway',
+ path: null
+ },
+ loadChildren: './ceph/rgw/rgw.module#RoutedRgwModule'
+ },
+ // Dashboard Settings
+ {
+ path: 'user-management',
+ canActivate: [AuthGuardService],
+ canActivateChild: [AuthGuardService],
+ data: { breadcrumbs: 'User management', path: null },
+ loadChildren: './core/auth/auth.module#RoutedAuthModule'
+ },
+ // NFS
+ {
+ path: 'nfs/501/:message',
+ component: Nfs501Component,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'NFS' }
+ },
+ {
+ path: 'nfs',
+ canActivate: [AuthGuardService],
+ canActivateChild: [AuthGuardService, ModuleStatusGuardService],
+ data: {
+ moduleStatusGuardConfig: {
+ apiPath: 'nfs-ganesha',
+ redirectTo: 'nfs/501'
+ },
+ breadcrumbs: 'NFS'
+ },
+ children: [
+ { path: '', component: NfsListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: NfsFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:cluster_id/:export_id`,
+ component: NfsFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ },
+ // Single Sign-On (SSO)
+ { path: 'sso/404', component: SsoNotFoundComponent },
+ // System
+ { path: 'login', component: LoginComponent },
+ { path: 'logout', children: [] },
+ { path: '403', component: ForbiddenComponent },
+ { path: '404', component: NotFoundComponent },
+ { path: '**', redirectTo: '/404' }
+];
+
+@NgModule({
+ imports: [
+ RouterModule.forRoot(routes, {
+ useHash: true,
+ preloadingStrategy: PreloadAllModules
+ })
+ ],
+ exports: [RouterModule],
+ providers: [StartCaseBreadcrumbsResolver, PerformanceCounterBreadcrumbsResolver]
+})
+export class AppRoutingModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.component.html b/src/pybind/mgr/dashboard/frontend/src/app/app.component.html
new file mode 100644
index 00000000..23b65ac2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app.component.html
@@ -0,0 +1,8 @@
+<block-ui>
+ <cd-navigation *ngIf="!isLoginActive()"></cd-navigation>
+ <div class="container-fluid"
+ [ngClass]="{'full-height':isLoginActive(), 'dashboard':isDashboardPage()} ">
+ <cd-breadcrumbs></cd-breadcrumbs>
+ <router-outlet></router-outlet>
+ </div>
+<block-ui>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/app.component.scss
new file mode 100644
index 00000000..93662729
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app.component.scss
@@ -0,0 +1,31 @@
+@import '../defaults';
+
+.dashboard {
+ background-color: $color-whitesmoke-gray;
+ margin: 0;
+ padding: 0;
+}
+
+::ng-deep #toast-container {
+ margin-top: 2vw;
+
+ @media (max-width: 1600px) {
+ margin-top: 2.5vw;
+ }
+
+ @media (max-width: $screen-sm-max) {
+ margin-top: 9vw;
+ }
+
+ @media (max-width: 900px) {
+ margin-top: 10vw;
+ }
+
+ @media (max-width: 319px) {
+ margin-top: 11vw;
+ }
+
+ @media (max-width: 260px) {
+ margin-top: 14vw;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/app.component.spec.ts
new file mode 100644
index 00000000..16fb5adb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app.component.spec.ts
@@ -0,0 +1,29 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../testing/unit-test-helper';
+import { AppComponent } from './app.component';
+import { AuthStorageService } from './shared/services/auth-storage.service';
+
+describe('AppComponent', () => {
+ let component: AppComponent;
+ let fixture: ComponentFixture<AppComponent>;
+
+ configureTestBed({
+ imports: [RouterTestingModule],
+ declarations: [AppComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [AuthStorageService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AppComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/app.component.ts
new file mode 100644
index 00000000..363a213d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app.component.ts
@@ -0,0 +1,34 @@
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+
+import { TooltipConfig } from 'ngx-bootstrap/tooltip';
+
+import { AuthStorageService } from './shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.scss'],
+ providers: [
+ {
+ provide: TooltipConfig,
+ useFactory: (): TooltipConfig =>
+ Object.assign(new TooltipConfig(), {
+ container: 'body'
+ })
+ }
+ ]
+})
+export class AppComponent {
+ title = 'cd';
+
+ constructor(private authStorageService: AuthStorageService, private router: Router) {}
+
+ isLoginActive() {
+ return this.router.url === '/login' || !this.authStorageService.isLoggedIn();
+ }
+
+ isDashboardPage() {
+ return this.router.url === '/dashboard';
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts
new file mode 100644
index 00000000..7b63f06b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts
@@ -0,0 +1,77 @@
+import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
+import {
+ ErrorHandler,
+ LOCALE_ID,
+ NgModule,
+ TRANSLATIONS,
+ TRANSLATIONS_FORMAT
+} from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BlockUIModule } from 'ng-block-ui';
+import { AccordionModule } from 'ngx-bootstrap/accordion';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { CephModule } from './ceph/ceph.module';
+import { CoreModule } from './core/core.module';
+import { ApiInterceptorService } from './shared/services/api-interceptor.service';
+import { JsErrorHandler } from './shared/services/js-error-handler.service';
+import { SharedModule } from './shared/shared.module';
+
+import { environment } from '../environments/environment';
+
+@NgModule({
+ declarations: [AppComponent],
+ imports: [
+ HttpClientModule,
+ BlockUIModule.forRoot(),
+ BrowserModule,
+ BrowserAnimationsModule,
+ ToastrModule.forRoot({
+ positionClass: 'toast-top-right',
+ preventDuplicates: true,
+ enableHtml: true
+ }),
+ AppRoutingModule,
+ CoreModule,
+ SharedModule,
+ CephModule,
+ AccordionModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot()
+ ],
+ exports: [SharedModule],
+ providers: [
+ {
+ provide: ErrorHandler,
+ useClass: JsErrorHandler
+ },
+ {
+ provide: HTTP_INTERCEPTORS,
+ useClass: ApiInterceptorService,
+ multi: true
+ },
+ {
+ provide: TRANSLATIONS,
+ useFactory: (locale) => {
+ locale = locale || environment.default_lang;
+ try {
+ return require(`raw-loader!locale/messages.${locale}.xlf`);
+ } catch (error) {
+ return [];
+ }
+ },
+ deps: [LOCALE_ID]
+ },
+ { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
+ I18n
+ ],
+ bootstrap: [AppComponent]
+})
+export class AppModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts
new file mode 100644
index 00000000..a1e0cc0b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts
@@ -0,0 +1,172 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+
+import { TreeModule } from 'ng2-tree';
+import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { ActionLabels, URLVerbs } from '../../shared/constants/app.constants';
+import { FeatureTogglesGuardService } from '../../shared/services/feature-toggles-guard.service';
+import { SharedModule } from '../../shared/shared.module';
+import { IscsiSettingComponent } from './iscsi-setting/iscsi-setting.component';
+import { IscsiTabsComponent } from './iscsi-tabs/iscsi-tabs.component';
+import { IscsiTargetDetailsComponent } from './iscsi-target-details/iscsi-target-details.component';
+import { IscsiTargetDiscoveryModalComponent } from './iscsi-target-discovery-modal/iscsi-target-discovery-modal.component';
+import { IscsiTargetFormComponent } from './iscsi-target-form/iscsi-target-form.component';
+import { IscsiTargetImageSettingsModalComponent } from './iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component';
+import { IscsiTargetIqnSettingsModalComponent } from './iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component';
+import { IscsiTargetListComponent } from './iscsi-target-list/iscsi-target-list.component';
+import { IscsiComponent } from './iscsi/iscsi.component';
+import { MirroringModule } from './mirroring/mirroring.module';
+import { OverviewComponent as RbdMirroringComponent } from './mirroring/overview/overview.component';
+import { RbdConfigurationFormComponent } from './rbd-configuration-form/rbd-configuration-form.component';
+import { RbdConfigurationListComponent } from './rbd-configuration-list/rbd-configuration-list.component';
+import { RbdDetailsComponent } from './rbd-details/rbd-details.component';
+import { RbdFormComponent } from './rbd-form/rbd-form.component';
+import { RbdImagesComponent } from './rbd-images/rbd-images.component';
+import { RbdListComponent } from './rbd-list/rbd-list.component';
+import { RbdSnapshotFormComponent } from './rbd-snapshot-form/rbd-snapshot-form.component';
+import { RbdSnapshotListComponent } from './rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdTrashListComponent } from './rbd-trash-list/rbd-trash-list.component';
+import { RbdTrashMoveModalComponent } from './rbd-trash-move-modal/rbd-trash-move-modal.component';
+import { RbdTrashPurgeModalComponent } from './rbd-trash-purge-modal/rbd-trash-purge-modal.component';
+import { RbdTrashRestoreModalComponent } from './rbd-trash-restore-modal/rbd-trash-restore-modal.component';
+
+@NgModule({
+ entryComponents: [
+ RbdDetailsComponent,
+ RbdSnapshotFormComponent,
+ RbdTrashMoveModalComponent,
+ RbdTrashRestoreModalComponent,
+ RbdTrashPurgeModalComponent,
+ IscsiTargetDetailsComponent,
+ IscsiTargetImageSettingsModalComponent,
+ IscsiTargetIqnSettingsModalComponent,
+ IscsiTargetDiscoveryModalComponent
+ ],
+ imports: [
+ CommonModule,
+ MirroringModule,
+ FormsModule,
+ ReactiveFormsModule,
+ TabsModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ BsDatepickerModule.forRoot(),
+ TooltipModule.forRoot(),
+ ModalModule.forRoot(),
+ SharedModule,
+ RouterModule,
+ TreeModule
+ ],
+ declarations: [
+ RbdListComponent,
+ IscsiComponent,
+ IscsiSettingComponent,
+ IscsiTabsComponent,
+ IscsiTargetListComponent,
+ RbdDetailsComponent,
+ RbdFormComponent,
+ RbdSnapshotListComponent,
+ RbdSnapshotFormComponent,
+ RbdTrashListComponent,
+ RbdTrashMoveModalComponent,
+ RbdImagesComponent,
+ RbdTrashRestoreModalComponent,
+ RbdTrashPurgeModalComponent,
+ IscsiTargetDetailsComponent,
+ IscsiTargetFormComponent,
+ IscsiTargetImageSettingsModalComponent,
+ IscsiTargetIqnSettingsModalComponent,
+ IscsiTargetDiscoveryModalComponent,
+ RbdConfigurationListComponent,
+ RbdConfigurationFormComponent
+ ],
+ exports: [RbdConfigurationListComponent, RbdConfigurationFormComponent]
+})
+export class BlockModule {}
+
+/* The following breakdown is needed to allow importing block.module without
+ the routes (e.g.: this module is imported by pool.module for RBD QoS
+ components)
+*/
+const routes: Routes = [
+ { path: '', redirectTo: 'rbd', pathMatch: 'full' },
+ {
+ path: 'rbd',
+ canActivate: [FeatureTogglesGuardService],
+ data: { breadcrumbs: 'Images' },
+ children: [
+ { path: '', component: RbdImagesComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: RbdFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:pool/:name`,
+ component: RbdFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ },
+ {
+ path: `${URLVerbs.CLONE}/:pool/:name/:snap`,
+ component: RbdFormComponent,
+ data: { breadcrumbs: ActionLabels.CLONE }
+ },
+ {
+ path: `${URLVerbs.COPY}/:pool/:name`,
+ component: RbdFormComponent,
+ data: { breadcrumbs: ActionLabels.COPY }
+ },
+ {
+ path: `${URLVerbs.COPY}/:pool/:name/:snap`,
+ component: RbdFormComponent,
+ data: { breadcrumbs: ActionLabels.COPY }
+ }
+ ]
+ },
+ {
+ path: 'mirroring',
+ component: RbdMirroringComponent,
+ canActivate: [FeatureTogglesGuardService],
+ data: { breadcrumbs: 'Mirroring' }
+ },
+ // iSCSI
+ {
+ path: 'iscsi',
+ canActivate: [FeatureTogglesGuardService],
+ data: { breadcrumbs: 'iSCSI' },
+ children: [
+ { path: '', redirectTo: 'overview', pathMatch: 'full' },
+ { path: 'overview', component: IscsiComponent, data: { breadcrumbs: 'Overview' } },
+ {
+ path: 'targets',
+ data: { breadcrumbs: 'Targets' },
+ children: [
+ { path: '', component: IscsiTargetListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: IscsiTargetFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:target_iqn`,
+ component: IscsiTargetFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [BlockModule, RouterModule.forChild(routes)]
+})
+export class RoutedBlockModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.html
new file mode 100644
index 00000000..7c65ea85
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.html
@@ -0,0 +1,58 @@
+<div class="form-group"
+ [ngClass]="{'has-error': settingsForm.showError(setting, formDir)}"
+ [formGroup]="settingsForm">
+ <label class="col-form-label"
+ for="{{ setting }}">{{ setting }}</label>
+ <select id="{{ setting }}"
+ name="{{ setting }}"
+ *ngIf="limits['type'] === 'enum'"
+ class="form-control custom-select"
+ [formControlName]="setting">
+ <option [ngValue]="null"></option>
+ <option *ngFor="let opt of limits['values']"
+ [ngValue]="opt">{{ opt }}</option>
+ </select>
+
+ <span *ngIf="limits['type'] !== 'enum'">
+ <input type="number"
+ *ngIf="limits['type'] === 'int'"
+ class="form-control"
+ [formControlName]="setting">
+
+ <input type="text"
+ *ngIf="limits['type'] === 'str'"
+ class="form-control"
+ [formControlName]="setting">
+
+ <ng-container *ngIf="limits['type'] === 'bool'">
+ <br>
+ <div class="radio radio-inline">
+ <input type="radio"
+ [id]="setting + 'True'"
+ [value]="true"
+ [formControlName]="setting"
+ class="custom-control-input">
+ <label class="custom-control-label"
+ [for]="setting + 'True'">Yes</label>
+ </div>
+ <div class="radio radio-inline">
+ <input type="radio"
+ [id]="setting + 'False'"
+ [value]="false"
+ class="custom-control-input"
+ [formControlName]="setting">
+ <label class="custom-control-label"
+ [for]="setting + 'False'">No</label>
+ </div>
+ </ng-container>
+ </span>
+
+ <span class="help-block"
+ *ngIf="settingsForm.showError(setting, formDir, 'min')">
+ <ng-container i18n>Must be greater than or equal to {{ limits['min'] }}.</ng-container>
+ </span>
+ <span class="help-block"
+ *ngIf="settingsForm.showError(setting, formDir, 'max')">
+ <ng-container i18n>Must be less than or equal to {{ limits['max'] }}.</ng-container>
+ </span>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.spec.ts
new file mode 100644
index 00000000..3f272d9b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.spec.ts
@@ -0,0 +1,37 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, NgForm, ReactiveFormsModule } from '@angular/forms';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiSettingComponent } from './iscsi-setting.component';
+
+describe('IscsiSettingComponent', () => {
+ let component: IscsiSettingComponent;
+ let fixture: ComponentFixture<IscsiSettingComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, ReactiveFormsModule],
+ declarations: [IscsiSettingComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiSettingComponent);
+ component = fixture.componentInstance;
+ component.settingsForm = new CdFormGroup({
+ max_data_area_mb: new FormControl()
+ });
+ component.formDir = new NgForm([], []);
+ component.setting = 'max_data_area_mb';
+ component.limits = {
+ type: 'int',
+ min: 1,
+ max: 2048
+ };
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.ts
new file mode 100644
index 00000000..ade8ae4c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-setting/iscsi-setting.component.ts
@@ -0,0 +1,31 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { NgForm, Validators } from '@angular/forms';
+
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+
+@Component({
+ selector: 'cd-iscsi-setting',
+ templateUrl: './iscsi-setting.component.html',
+ styleUrls: ['./iscsi-setting.component.scss']
+})
+export class IscsiSettingComponent implements OnInit {
+ @Input()
+ settingsForm: CdFormGroup;
+ @Input()
+ formDir: NgForm;
+ @Input()
+ setting: string;
+ @Input()
+ limits: object;
+
+ ngOnInit() {
+ const validators = [];
+ if ('min' in this.limits) {
+ validators.push(Validators.min(this.limits['min']));
+ }
+ if ('max' in this.limits) {
+ validators.push(Validators.max(this.limits['max']));
+ }
+ this.settingsForm.get(this.setting).setValidators(validators);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.html
new file mode 100644
index 00000000..e1e43c29
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.html
@@ -0,0 +1,12 @@
+<tabset>
+ <tab heading="Overview"
+ i18n-heading
+ [active]="url === '/block/iscsi/overview'"
+ (selectTab)="navigateTo('/block/iscsi/overview')">
+ </tab>
+ <tab heading="Targets"
+ i18n-heading
+ [active]="url === '/block/iscsi/targets'"
+ (selectTab)="navigateTo('/block/iscsi/targets')">
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.spec.ts
new file mode 100644
index 00000000..e51c9fad
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.spec.ts
@@ -0,0 +1,28 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiTabsComponent } from './iscsi-tabs.component';
+
+describe('IscsiTabsComponent', () => {
+ let component: IscsiTabsComponent;
+ let fixture: ComponentFixture<IscsiTabsComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, TabsModule.forRoot(), RouterTestingModule],
+ declarations: [IscsiTabsComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTabsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.ts
new file mode 100644
index 00000000..b5dc3cff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-tabs/iscsi-tabs.component.ts
@@ -0,0 +1,22 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'cd-iscsi-tabs',
+ templateUrl: './iscsi-tabs.component.html',
+ styleUrls: ['./iscsi-tabs.component.scss']
+})
+export class IscsiTabsComponent implements OnInit {
+ url: string;
+
+ constructor(private router: Router) {}
+
+ ngOnInit() {
+ this.url = this.router.url;
+ }
+
+ navigateTo(url) {
+ this.router.navigate([url]);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.html
new file mode 100644
index 00000000..080f458b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.html
@@ -0,0 +1,35 @@
+<div class="col-sm-6 col-lg-6">
+ <legend i18n>iSCSI Topology</legend>
+ <tree [tree]="tree"
+ (nodeSelected)="onNodeSelected($event)">
+ <ng-template let-node>
+ <span class="node-name"
+ [innerHTML]="node.value"></span>
+ <span>&nbsp;</span>
+
+ <span class="label"
+ [ngClass]="{'label-success': ['logged_in'].includes(node.status), 'label-danger': ['logged_out'].includes(node.status)}">
+ {{ node.status }}
+ </span>
+ </ng-template>
+ </tree>
+</div>
+
+<div class="col-sm-6 col-lg-6 metadata"
+ *ngIf="data">
+ <legend>{{ title }}</legend>
+
+ <cd-table #detailTable
+ [data]="data"
+ columnMode="flex"
+ [columns]="columns"
+ [limit]="0">
+ </cd-table>
+</div>
+
+<ng-template #highlightTpl
+ let-row="row"
+ let-value="value">
+ <span *ngIf="row.default === undefined || row.default === row.current">{{ value }}</span>
+ <strong *ngIf="row.default !== undefined && row.default !== row.current">{{ value }}</strong>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.scss
new file mode 100644
index 00000000..202e7be9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.scss
@@ -0,0 +1,3 @@
+::ng-deep tree .fa {
+ font-weight: unset !important;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.spec.ts
new file mode 100644
index 00000000..f4c5d811
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.spec.ts
@@ -0,0 +1,206 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { NodeEvent, Tree, TreeModule } from 'ng2-tree';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiTargetDetailsComponent } from './iscsi-target-details.component';
+
+describe('IscsiTargetDetailsComponent', () => {
+ let component: IscsiTargetDetailsComponent;
+ let fixture: ComponentFixture<IscsiTargetDetailsComponent>;
+
+ configureTestBed({
+ declarations: [IscsiTargetDetailsComponent],
+ imports: [TreeModule, SharedModule],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetDetailsComponent);
+ component = fixture.componentInstance;
+
+ component.settings = {
+ config: { minimum_gateways: 2 },
+ disk_default_controls: {
+ 'backstore:1': {
+ hw_max_sectors: 1024,
+ max_data_area_mb: 8
+ },
+ 'backstore:2': {
+ hw_max_sectors: 1024,
+ max_data_area_mb: 8
+ }
+ },
+ target_default_controls: {
+ cmdsn_depth: 128,
+ dataout_timeout: 20
+ },
+ backstores: ['backstore:1', 'backstore:2'],
+ default_backstore: 'backstore:1'
+ };
+ component.selection = new CdTableSelection();
+ component.selection.selected = [
+ {
+ target_iqn: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
+ portals: [{ host: 'node1', ip: '192.168.100.201' }],
+ disks: [
+ {
+ pool: 'rbd',
+ image: 'disk_1',
+ backstore: 'backstore:1',
+ controls: { hw_max_sectors: 1 }
+ }
+ ],
+ clients: [
+ {
+ client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
+ luns: [{ pool: 'rbd', image: 'disk_1' }],
+ auth: {
+ user: 'myiscsiusername'
+ },
+ info: {
+ alias: 'myhost',
+ ip_address: ['192.168.200.1'],
+ state: { LOGGED_IN: ['node1'] }
+ }
+ }
+ ],
+ groups: [],
+ target_controls: { dataout_timeout: 2 }
+ }
+ ];
+ component.selection.update();
+
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should empty data and generateTree when ngOnChanges is called', () => {
+ const tempData = [{ current: 'baz', default: 'bar', displayName: 'foo' }];
+ component.data = tempData;
+ fixture.detectChanges();
+
+ expect(component.data).toEqual(tempData);
+ expect(component.metadata).toEqual({});
+ expect(component.tree).toEqual(undefined);
+
+ component.ngOnChanges();
+
+ expect(component.data).toBeUndefined();
+ expect(component.metadata).toEqual({
+ 'client_iqn.1994-05.com.redhat:rh7-client': {
+ user: 'myiscsiusername',
+ alias: 'myhost',
+ ip_address: ['192.168.200.1'],
+ logged_in: ['node1']
+ },
+ disk_rbd_disk_1: { backstore: 'backstore:1', controls: { hw_max_sectors: 1 } },
+ root: { dataout_timeout: 2 }
+ });
+ expect(component.tree).toEqual({
+ children: [
+ {
+ children: [{ id: 'disk_rbd_disk_1', value: 'rbd/disk_1' }],
+ settings: {
+ cssClasses: { expanded: 'fa fa-fw fa-hdd-o fa-lg', leaf: 'fa fa-fw fa-hdd-o' },
+ selectionAllowed: false
+ },
+ value: 'Disks'
+ },
+ {
+ children: [{ value: 'node1:192.168.100.201' }],
+ settings: {
+ cssClasses: { expanded: 'fa fa-fw fa-server fa-lg', leaf: 'fa fa-fw fa-server fa-lg' },
+ selectionAllowed: false
+ },
+ value: 'Portals'
+ },
+ {
+ children: [
+ {
+ children: [
+ {
+ id: 'disk_rbd_disk_1',
+ settings: {
+ cssClasses: { expanded: 'fa fa-fw fa-hdd-o fa-lg', leaf: 'fa fa-fw fa-hdd-o' }
+ },
+ value: 'rbd/disk_1'
+ }
+ ],
+ id: 'client_iqn.1994-05.com.redhat:rh7-client',
+ status: 'logged_in',
+ value: 'iqn.1994-05.com.redhat:rh7-client'
+ }
+ ],
+ settings: {
+ cssClasses: { expanded: 'fa fa-fw fa-user fa-lg', leaf: 'fa fa-fw fa-user' },
+ selectionAllowed: false
+ },
+ value: 'Initiators'
+ },
+ {
+ children: [],
+ settings: {
+ cssClasses: { expanded: 'fa fa-fw fa-users fa-lg', leaf: 'fa fa-fw fa-users' },
+ selectionAllowed: false
+ },
+ value: 'Groups'
+ }
+ ],
+ id: 'root',
+ settings: { cssClasses: { expanded: 'fa fa-fw fa-bullseye fa-lg' }, static: true },
+ value: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw'
+ });
+ });
+
+ describe('should update data when onNodeSelected is called', () => {
+ beforeEach(() => {
+ component.ngOnChanges();
+ });
+
+ it('with target selected', () => {
+ const tree = new Tree(component.tree);
+ const node = new NodeEvent(tree);
+ component.onNodeSelected(node);
+ expect(component.data).toEqual([
+ { current: 128, default: 128, displayName: 'cmdsn_depth' },
+ { current: 2, default: 20, displayName: 'dataout_timeout' }
+ ]);
+ });
+
+ it('with disk selected', () => {
+ const tree = new Tree(component.tree.children[0].children[0]);
+ const node = new NodeEvent(tree);
+ component.onNodeSelected(node);
+ expect(component.data).toEqual([
+ { current: 1, default: 1024, displayName: 'hw_max_sectors' },
+ { current: 8, default: 8, displayName: 'max_data_area_mb' },
+ { current: 'backstore:1', default: 'backstore:1', displayName: 'backstore' }
+ ]);
+ });
+
+ it('with initiator selected', () => {
+ const tree = new Tree(component.tree.children[2].children[0]);
+ const node = new NodeEvent(tree);
+ component.onNodeSelected(node);
+ expect(component.data).toEqual([
+ { current: 'myiscsiusername', default: undefined, displayName: 'user' },
+ { current: 'myhost', default: undefined, displayName: 'alias' },
+ { current: ['192.168.200.1'], default: undefined, displayName: 'ip_address' },
+ { current: ['node1'], default: undefined, displayName: 'logged_in' }
+ ]);
+ });
+
+ it('with any other selected', () => {
+ const tree = new Tree(component.tree.children[1].children[0]);
+ const node = new NodeEvent(tree);
+ component.onNodeSelected(node);
+ expect(component.data).toBeUndefined();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.ts
new file mode 100644
index 00000000..7a03b0ff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-details/iscsi-target-details.component.ts
@@ -0,0 +1,333 @@
+import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { NodeEvent, TreeModel } from 'ng2-tree';
+
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { BooleanTextPipe } from '../../../shared/pipes/boolean-text.pipe';
+import { IscsiBackstorePipe } from '../../../shared/pipes/iscsi-backstore.pipe';
+
+@Component({
+ selector: 'cd-iscsi-target-details',
+ templateUrl: './iscsi-target-details.component.html',
+ styleUrls: ['./iscsi-target-details.component.scss']
+})
+export class IscsiTargetDetailsComponent implements OnChanges, OnInit {
+ @Input()
+ selection: CdTableSelection;
+ @Input()
+ settings: any;
+ @Input()
+ cephIscsiConfigVersion: number;
+
+ @ViewChild('highlightTpl')
+ highlightTpl: TemplateRef<any>;
+
+ private detailTable: TableComponent;
+ @ViewChild('detailTable')
+ set content(content: TableComponent) {
+ this.detailTable = content;
+ if (content) {
+ content.updateColumns();
+ }
+ }
+
+ columns: CdTableColumn[];
+ data: any;
+ metadata: any = {};
+ selectedItem: any;
+ title: string;
+ tree: TreeModel;
+
+ constructor(
+ private i18n: I18n,
+ private iscsiBackstorePipe: IscsiBackstorePipe,
+ private booleanTextPipe: BooleanTextPipe
+ ) {}
+
+ ngOnInit() {
+ this.columns = [
+ {
+ prop: 'displayName',
+ name: this.i18n('Name'),
+ flexGrow: 1,
+ cellTemplate: this.highlightTpl
+ },
+ {
+ prop: 'current',
+ name: this.i18n('Current'),
+ flexGrow: 1,
+ cellTemplate: this.highlightTpl
+ },
+ {
+ prop: 'default',
+ name: this.i18n('Default'),
+ flexGrow: 1,
+ cellTemplate: this.highlightTpl
+ }
+ ];
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+ this.generateTree();
+ }
+
+ this.data = undefined;
+ }
+
+ private generateTree() {
+ const target_meta = _.cloneDeep(this.selectedItem.target_controls);
+ // Target level authentication was introduced in ceph-iscsi config v11
+ if (this.cephIscsiConfigVersion > 10) {
+ _.extend(target_meta, _.cloneDeep(this.selectedItem.auth));
+ }
+ this.metadata = { root: target_meta };
+ const cssClasses = {
+ target: {
+ expanded: this.selectedItem.cdExecuting
+ ? 'fa fa-fw fa-spinner fa-spin fa-lg'
+ : 'fa fa-fw fa-bullseye fa-lg'
+ },
+ initiators: {
+ expanded: 'fa fa-fw fa-user fa-lg',
+ leaf: 'fa fa-fw fa-user'
+ },
+ groups: {
+ expanded: 'fa fa-fw fa-users fa-lg',
+ leaf: 'fa fa-fw fa-users'
+ },
+ disks: {
+ expanded: 'fa fa-fw fa-hdd-o fa-lg',
+ leaf: 'fa fa-fw fa-hdd-o'
+ },
+ portals: {
+ expanded: 'fa fa-fw fa-server fa-lg',
+ leaf: 'fa fa-fw fa-server fa-lg'
+ }
+ };
+
+ const disks = [];
+ _.forEach(this.selectedItem.disks, (disk) => {
+ const id = 'disk_' + disk.pool + '_' + disk.image;
+ this.metadata[id] = {
+ controls: disk.controls,
+ backstore: disk.backstore
+ };
+ ['wwn', 'lun'].forEach((k) => {
+ if (k in disk) {
+ this.metadata[id][k] = disk[k];
+ }
+ });
+ disks.push({
+ value: `${disk.pool}/${disk.image}`,
+ id: id
+ });
+ });
+
+ const portals = [];
+ _.forEach(this.selectedItem.portals, (portal) => {
+ portals.push({ value: `${portal.host}:${portal.ip}` });
+ });
+
+ const clients = [];
+ _.forEach(this.selectedItem.clients, (client) => {
+ const client_metadata = _.cloneDeep(client.auth);
+ if (client.info) {
+ _.extend(client_metadata, client.info);
+ delete client_metadata['state'];
+ _.forEach(Object.keys(client.info.state), (state) => {
+ client_metadata[state.toLowerCase()] = client.info.state[state];
+ });
+ }
+ this.metadata['client_' + client.client_iqn] = client_metadata;
+
+ const luns = [];
+ client.luns.forEach((lun) => {
+ luns.push({
+ value: `${lun.pool}/${lun.image}`,
+ id: 'disk_' + lun.pool + '_' + lun.image,
+ settings: {
+ cssClasses: cssClasses.disks
+ }
+ });
+ });
+
+ let status = '';
+ if (client.info) {
+ status = Object.keys(client.info.state).includes('LOGGED_IN') ? 'logged_in' : 'logged_out';
+ }
+ clients.push({
+ value: client.client_iqn,
+ status: status,
+ id: 'client_' + client.client_iqn,
+ children: luns
+ });
+ });
+
+ const groups = [];
+ _.forEach(this.selectedItem.groups, (group) => {
+ const luns = [];
+ group.disks.forEach((disk) => {
+ luns.push({
+ value: `${disk.pool}/${disk.image}`,
+ id: 'disk_' + disk.pool + '_' + disk.image
+ });
+ });
+
+ const initiators = [];
+ group.members.forEach((member) => {
+ initiators.push({
+ value: member,
+ id: 'client_' + member
+ });
+ });
+
+ groups.push({
+ value: group.group_id,
+ children: [
+ {
+ value: 'Disks',
+ children: luns,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.disks
+ }
+ },
+ {
+ value: 'Initiators',
+ children: initiators,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.initiators
+ }
+ }
+ ]
+ });
+ });
+
+ this.tree = {
+ value: this.selectedItem.target_iqn,
+ id: 'root',
+ settings: {
+ static: true,
+ cssClasses: cssClasses.target
+ },
+ children: [
+ {
+ value: 'Disks',
+ children: disks,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.disks
+ }
+ },
+ {
+ value: 'Portals',
+ children: portals,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.portals
+ }
+ },
+ {
+ value: 'Initiators',
+ children: clients,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.initiators
+ }
+ },
+ {
+ value: 'Groups',
+ children: groups,
+ settings: {
+ selectionAllowed: false,
+ cssClasses: cssClasses.groups
+ }
+ }
+ ]
+ };
+ }
+
+ private format(value) {
+ if (typeof value === 'boolean') {
+ return this.booleanTextPipe.transform(value);
+ }
+ return value;
+ }
+
+ onNodeSelected(e: NodeEvent) {
+ if (e.node.id) {
+ this.title = e.node.value;
+ const tempData = this.metadata[e.node.id] || {};
+
+ if (e.node.id === 'root') {
+ this.columns[2].isHidden = false;
+ this.data = _.map(this.settings.target_default_controls, (value, key) => {
+ value = this.format(value);
+ return {
+ displayName: key,
+ default: value,
+ current: !_.isUndefined(tempData[key]) ? this.format(tempData[key]) : value
+ };
+ });
+ // Target level authentication was introduced in ceph-iscsi config v11
+ if (this.cephIscsiConfigVersion > 10) {
+ ['user', 'password', 'mutual_user', 'mutual_password'].forEach((key) => {
+ this.data.push({
+ displayName: key,
+ default: null,
+ current: tempData[key]
+ });
+ });
+ }
+ } else if (e.node.id.toString().startsWith('disk_')) {
+ this.columns[2].isHidden = false;
+ this.data = _.map(this.settings.disk_default_controls[tempData.backstore], (value, key) => {
+ value = this.format(value);
+ return {
+ displayName: key,
+ default: value,
+ current: !_.isUndefined(tempData.controls[key])
+ ? this.format(tempData.controls[key])
+ : value
+ };
+ });
+ this.data.push({
+ displayName: 'backstore',
+ default: this.iscsiBackstorePipe.transform(this.settings.default_backstore),
+ current: this.iscsiBackstorePipe.transform(tempData.backstore)
+ });
+ ['wwn', 'lun'].forEach((k) => {
+ if (k in tempData) {
+ this.data.push({
+ displayName: k,
+ default: undefined,
+ current: tempData[k]
+ });
+ }
+ });
+ } else {
+ this.columns[2].isHidden = true;
+ this.data = _.map(tempData, (value, key) => {
+ return {
+ displayName: key,
+ default: undefined,
+ current: this.format(value)
+ };
+ });
+ }
+ } else {
+ this.data = undefined;
+ }
+
+ if (this.detailTable) {
+ this.detailTable.updateColumns();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html
new file mode 100644
index 00000000..57f49484
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.html
@@ -0,0 +1,147 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>Discovery Authentication</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="discoveryForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="discoveryForm"
+ novalidate>
+ <div class="modal-body">
+ <!-- User -->
+ <div class="form-group"
+ [ngClass]="{'has-error': discoveryForm.showError('user', formDir)}">
+ <label class="control-label col-sm-4"
+ for="user"
+ i18n>User</label>
+ <div class="col-sm-8">
+ <input id="user"
+ class="form-control"
+ formControlName="user"
+ type="text"
+ autocomplete="off">
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': discoveryForm.showError('password', formDir)}">
+ <label class="control-label col-sm-4"
+ for="password"
+ i18n>Password</label>
+ <div class="col-sm-8">
+ <div class="input-group">
+ <input id="password"
+ class="form-control"
+ formControlName="password"
+ type="password"
+ autocomplete="new-password">
+
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="password">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="password">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+ <!-- mutual_user -->
+ <div class="form-group"
+ [ngClass]="{'has-error': discoveryForm.showError('mutual_user', formDir)}">
+ <label class="control-label col-sm-4"
+ for="mutual_user">
+ <ng-container i18n>Mutual User</ng-container>
+ </label>
+ <div class="col-sm-8">
+ <input id="mutual_user"
+ class="form-control"
+ formControlName="mutual_user"
+ type="text"
+ autocomplete="off">
+
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('mutual_user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('mutual_user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- mutual_password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': discoveryForm.showError('mutual_password', formDir)}">
+ <label class="control-label col-sm-4"
+ for="mutual_password"
+ i18n>Mutual Password</label>
+ <div class="col-sm-8">
+ <div class="input-group">
+ <input id="mutual_password"
+ class="form-control"
+ formControlName="mutual_password"
+ type="password"
+ autocomplete="new-password">
+
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="mutual_password">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="mutual_password">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('mutual_password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="discoveryForm.showError('mutual_password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button (submitAction)="submitAction()"
+ [form]="discoveryForm"
+ *ngIf="hasPermission"
+ i18n>Submit</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.spec.ts
new file mode 100644
index 00000000..e8f42fb2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.spec.ts
@@ -0,0 +1,138 @@
+import {
+ HttpClientTestingModule,
+ HttpTestingController,
+ TestRequest
+} from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ FormHelper,
+ i18nProviders,
+ IscsiHelper
+} from '../../../../testing/unit-test-helper';
+import { Permission } from '../../../shared/models/permissions';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiTargetDiscoveryModalComponent } from './iscsi-target-discovery-modal.component';
+
+describe('IscsiTargetDiscoveryModalComponent', () => {
+ let component: IscsiTargetDiscoveryModalComponent;
+ let fixture: ComponentFixture<IscsiTargetDiscoveryModalComponent>;
+ let httpTesting: HttpTestingController;
+ let req: TestRequest;
+
+ const elem = (css) => fixture.debugElement.query(By.css(css));
+ const elemDisabled = (css) => elem(css).nativeElement.disabled;
+
+ configureTestBed({
+ declarations: [IscsiTargetDiscoveryModalComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ RouterTestingModule
+ ],
+ providers: [i18nProviders, BsModalRef]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetDiscoveryModalComponent);
+ component = fixture.componentInstance;
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ describe('with update permissions', () => {
+ beforeEach(() => {
+ component.permission = new Permission(['update']);
+ fixture.detectChanges();
+ req = httpTesting.expectOne('api/iscsi/discoveryauth');
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should create form', () => {
+ expect(component.discoveryForm.value).toEqual({
+ user: '',
+ password: '',
+ mutual_user: '',
+ mutual_password: ''
+ });
+ });
+
+ it('should patch form', () => {
+ req.flush({
+ user: 'foo',
+ password: 'bar',
+ mutual_user: 'mutual_foo',
+ mutual_password: 'mutual_bar'
+ });
+ expect(component.discoveryForm.value).toEqual({
+ user: 'foo',
+ password: 'bar',
+ mutual_user: 'mutual_foo',
+ mutual_password: 'mutual_bar'
+ });
+ });
+
+ it('should submit new values', () => {
+ component.discoveryForm.patchValue({
+ user: 'new_user',
+ password: 'new_pass',
+ mutual_user: 'mutual_new_user',
+ mutual_password: 'mutual_new_pass'
+ });
+ component.submitAction();
+
+ const submit_req = httpTesting.expectOne('api/iscsi/discoveryauth');
+ expect(submit_req.request.method).toBe('PUT');
+ expect(submit_req.request.body).toEqual({
+ user: 'new_user',
+ password: 'new_pass',
+ mutual_user: 'mutual_new_user',
+ mutual_password: 'mutual_new_pass'
+ });
+ });
+
+ it('should enable form if user has update permission', () => {
+ expect(elemDisabled('input#user')).toBeFalsy();
+ expect(elemDisabled('input#password')).toBeFalsy();
+ expect(elemDisabled('input#mutual_user')).toBeFalsy();
+ expect(elemDisabled('input#mutual_password')).toBeFalsy();
+ expect(elem('cd-submit-button')).toBeDefined();
+ });
+ });
+
+ it('should disabled form if user does not have update permission', () => {
+ component.permission = new Permission(['read', 'create', 'delete']);
+ fixture.detectChanges();
+ req = httpTesting.expectOne('api/iscsi/discoveryauth');
+
+ expect(elemDisabled('input#user')).toBeTruthy();
+ expect(elemDisabled('input#password')).toBeTruthy();
+ expect(elemDisabled('input#mutual_user')).toBeTruthy();
+ expect(elemDisabled('input#mutual_password')).toBeTruthy();
+ expect(elem('cd-submit-button')).toBeNull();
+ });
+
+ it('should validate authentication', () => {
+ component.permission = new Permission(['read', 'create', 'update', 'delete']);
+ fixture.detectChanges();
+ const control = component.discoveryForm;
+ const formHelper = new FormHelper(control);
+ formHelper.expectValid(control);
+
+ IscsiHelper.validateUser(formHelper, 'user');
+ IscsiHelper.validatePassword(formHelper, 'password');
+ IscsiHelper.validateUser(formHelper, 'mutual_user');
+ IscsiHelper.validatePassword(formHelper, 'mutual_password');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.ts
new file mode 100644
index 00000000..fcf9e27c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-discovery-modal/iscsi-target-discovery-modal.component.ts
@@ -0,0 +1,123 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-iscsi-target-discovery-modal',
+ templateUrl: './iscsi-target-discovery-modal.component.html',
+ styleUrls: ['./iscsi-target-discovery-modal.component.scss']
+})
+export class IscsiTargetDiscoveryModalComponent implements OnInit {
+ discoveryForm: CdFormGroup;
+ permission: Permission;
+ hasPermission: boolean;
+
+ USER_REGEX = /^[\w\.:@_-]{8,64}$/;
+ PASSWORD_REGEX = /^[\w@\-_\/]{12,16}$/;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ public bsModalRef: BsModalRef,
+ private iscsiService: IscsiService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().iscsi;
+ }
+
+ ngOnInit() {
+ this.hasPermission = this.permission.update;
+ this.createForm();
+ this.iscsiService.getDiscovery().subscribe((auth) => {
+ this.discoveryForm.patchValue(auth);
+ });
+ }
+
+ createForm() {
+ this.discoveryForm = new CdFormGroup({
+ user: new FormControl({ value: '', disabled: !this.hasPermission }),
+ password: new FormControl({ value: '', disabled: !this.hasPermission }),
+ mutual_user: new FormControl({ value: '', disabled: !this.hasPermission }),
+ mutual_password: new FormControl({ value: '', disabled: !this.hasPermission })
+ });
+
+ CdValidators.validateIf(
+ this.discoveryForm.get('user'),
+ () =>
+ this.discoveryForm.getValue('password') ||
+ this.discoveryForm.getValue('mutual_user') ||
+ this.discoveryForm.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.USER_REGEX)],
+ [
+ this.discoveryForm.get('password'),
+ this.discoveryForm.get('mutual_user'),
+ this.discoveryForm.get('mutual_password')
+ ]
+ );
+
+ CdValidators.validateIf(
+ this.discoveryForm.get('password'),
+ () =>
+ this.discoveryForm.getValue('user') ||
+ this.discoveryForm.getValue('mutual_user') ||
+ this.discoveryForm.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.PASSWORD_REGEX)],
+ [
+ this.discoveryForm.get('user'),
+ this.discoveryForm.get('mutual_user'),
+ this.discoveryForm.get('mutual_password')
+ ]
+ );
+
+ CdValidators.validateIf(
+ this.discoveryForm.get('mutual_user'),
+ () => this.discoveryForm.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.USER_REGEX)],
+ [
+ this.discoveryForm.get('user'),
+ this.discoveryForm.get('password'),
+ this.discoveryForm.get('mutual_password')
+ ]
+ );
+
+ CdValidators.validateIf(
+ this.discoveryForm.get('mutual_password'),
+ () => this.discoveryForm.getValue('mutual_user'),
+ [Validators.required],
+ [Validators.pattern(this.PASSWORD_REGEX)],
+ [
+ this.discoveryForm.get('user'),
+ this.discoveryForm.get('password'),
+ this.discoveryForm.get('mutual_user')
+ ]
+ );
+ }
+
+ submitAction() {
+ this.iscsiService.updateDiscovery(this.discoveryForm.value).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated discovery authentication')
+ );
+ this.bsModalRef.hide();
+ },
+ () => {
+ this.discoveryForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
new file mode 100644
index 00000000..0b0afa1a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
@@ -0,0 +1,721 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="targetForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="targetForm"
+ novalidate
+ *ngIf="targetForm">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+
+ <div class="panel-body">
+ <!-- Target IQN -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('target_iqn', formDir)}">
+ <label class="control-label col-sm-3"
+ for="target_iqn">
+ <ng-container i18n>Target IQN</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input class="form-control"
+ type="text"
+ id="target_iqn"
+ name="target_iqn"
+ formControlName="target_iqn"
+ cdTrim />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ id="ecp-info-button"
+ type="button"
+ (click)="targetSettingsModal()">
+ <i class="fa fa-cogs fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
+ i18n>IQN has wrong pattern.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
+ <ng-container i18n>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
+ <br>
+ <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
+ <br>
+ <a target="_blank"
+ href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
+ i18n>More information</a>
+ </span>
+
+ <span class="help-block"
+ *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
+ i18n>This target has modified advanced settings.</span>
+ <hr />
+ </div>
+ </div>
+
+ <!-- Portals -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('portals', formDir)}">
+ <label class="control-label col-sm-3"
+ for="portals">
+ <ng-container i18n>Portals</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+
+ <ng-container *ngFor="let portal of portals.value; let i = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="portal"
+ disabled />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="removePortal(i, portal)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
+ i18n>At least {{ minimum_gateways }} gateways are required.</span>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="portals.value"
+ [options]="portalsSelections"
+ [messages]="messages.portals"
+ (selection)="onPortalSelection($event)"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add portal</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Images -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('disks', formDir)}">
+ <label class="control-label col-sm-3"
+ for="disks"
+ i18n>Images</label>
+ <div class="col-sm-9">
+ <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="image"
+ disabled />
+ <div class="input-group-addon"
+ *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="imageSettingsModal(image)">
+ <i class="fa fa-cogs fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-default"
+ type="button"
+ (click)="removeImage(i, image)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+
+ </div>
+
+ <span class="help-block">
+ <ng-container *ngIf="backstores.length > 1"
+ i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}.&nbsp;</ng-container>
+
+ <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
+ i18n>This image has modified settings.</ng-container>
+ </span>
+ </ng-container>
+
+ <input class="form-control"
+ type="hidden"
+ id="disks"
+ name="disks"
+ formControlName="disks" />
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
+ i18n>Duplicated LUN numbers.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
+ i18n>Duplicated WWN.</span>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="disks.value"
+ [options]="imagesSelections"
+ [messages]="messages.images"
+ (selection)="onImageSelection($event)"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- acl_enabled -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ formControlName="acl_enabled"
+ name="acl_enabled"
+ id="acl_enabled">
+ <label for="acl_enabled"
+ i18n>ACL authentication</label>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
+ <div formGroupName="auth" *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
+
+ <!-- Target user -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('user', formDir)}">
+ <label class="control-label col-sm-3"
+ for="target_user">
+ <ng-container i18n>User</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ autocomplete="off"
+ id="target_user"
+ name="target_user"
+ formControlName="user" />
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Target password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('password', formDir)}">
+ <label class="control-label col-sm-3"
+ for="target_password">
+ <ng-container i18n>Password</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ autocomplete="new-password"
+ id="target_password"
+ name="target_password"
+ formControlName="password" />
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="target_password">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="target_password">
+ </button>
+ </span>
+ </div>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+ <!-- Target mutual_user -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('mutual_user', formDir)}">
+ <label class="control-label col-sm-3"
+ for="target_mutual_user">
+ <ng-container i18n>Mutual User</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ autocomplete="off"
+ id="target_mutual_user"
+ name="target_mutual_user"
+ formControlName="mutual_user" />
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Target mutual_password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': targetForm.showError('mutual_password', formDir)}">
+ <label class="control-label col-sm-3"
+ for="target_mutual_password">
+ <ng-container i18n>Mutual Password</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ autocomplete="new-password"
+ id="target_mutual_password"
+ name="target_mutual_password"
+ formControlName="mutual_password" />
+
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="target_mutual_password">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="target_mutual_password">
+ </button>
+ </span>
+ </div>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- Initiators -->
+ <div class="form-group"
+ *ngIf="targetForm.getValue('acl_enabled')">
+ <label class="control-label col-sm-3"
+ for="initiators"
+ i18n>Initiators</label>
+ <div class="col-sm-9"
+ formArrayName="initiators">
+ <div class="panel panel-default"
+ *ngFor="let initiator of initiators.controls; let ii = index"
+ [formGroupName]="ii">
+ <div class="panel-heading">
+ <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
+ <button type="button"
+ class="close"
+ (click)="removeInitiator(ii)">
+ <i class="fa fa-remove fa-fw"></i>
+ </button>
+ </div>
+ <div class="panel-body">
+ <!-- Initiator: Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('client_iqn', formDir)}">
+ <label class="control-label col-sm-3"
+ for="client_iqn">
+ <ng-container i18n>Client IQN</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ formControlName="client_iqn"
+ cdTrim
+ (blur)="updatedInitiatorSelector()">
+
+ <span class="help-block"
+ *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
+ i18n>Initiator IQN needs to be unique.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('client_iqn', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
+ i18n>IQN has wrong pattern.</span>
+ </div>
+ </div>
+
+ <ng-container formGroupName="auth">
+ <!-- Initiator: User -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('user', formDir)}">
+ <label class="control-label col-sm-3"
+ for="user"
+ i18n>User</label>
+ <div class="col-sm-9">
+ <input [id]="'user' + ii"
+ class="form-control"
+ formControlName="user"
+ autocomplete="off"
+ type="text">
+ <span class="help-block"
+ *ngIf="initiator.showError('user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Initiator: Password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('password', formDir)}">
+ <label class="control-label col-sm-3"
+ for="password"
+ i18n>Password</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input [id]="'password' + ii"
+ class="form-control"
+ formControlName="password"
+ autocomplete="new-password"
+ type="password">
+
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ [cdPasswordButton]="'password' + ii">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ [cdCopy2ClipboardButton]="'password' + ii">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="initiator.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+
+ <!-- Initiator: mutual_user -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('mutual_user', formDir)}">
+ <label class="control-label col-sm-3"
+ for="mutual_user">
+ <ng-container i18n>Mutual User</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <input [id]="'mutual_user' + ii"
+ class="form-control"
+ formControlName="mutual_user"
+ autocomplete="off"
+ type="text">
+
+ <span class="help-block"
+ *ngIf="initiator.showError('mutual_user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
+ i18n>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Initiator: mutual_password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('mutual_password', formDir)}">
+ <label class="control-label col-sm-3"
+ for="mutual_password"
+ i18n>Mutual Password</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input [id]="'mutual_password' + ii"
+ class="form-control"
+ formControlName="mutual_password"
+ autocomplete="new-password"
+ type="password">
+
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ [cdPasswordButton]="'mutual_password' + ii">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ [cdCopy2ClipboardButton]="'mutual_password' + ii">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="initiator.showError('mutual_password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="help-block"
+ *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+ </ng-container>
+
+ <!-- Initiator: Images -->
+ <div class="form-group"
+ [ngClass]="{'has-error': initiator.showError('luns', formDir)}">
+ <label class="control-label col-sm-3"
+ for="luns"
+ i18n>Images</label>
+ <div class="col-sm-9">
+ <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="image"
+ disabled />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="removeInitiatorImage(initiator, li, ii, image)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <span *ngIf="initiator.getValue('cdIsInGroup')"
+ i18n>Initiator belongs to a group. Images will be configure in the group.</span>
+
+ <div class="row"
+ *ngIf="!initiator.getValue('cdIsInGroup')">
+ <div class="col-md-12">
+ <cd-select [data]="initiator.getValue('luns')"
+ [options]="imagesInitiatorSelections[ii]"
+ [messages]="messages.initiatorImage"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <span class="text-muted"
+ *ngIf="initiators.controls.length === 0"
+ i18n>No items added.</span>
+
+ <button (click)="addInitiator(); false"
+ class="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add initiator</ng-container>
+ </button>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Groups -->
+ <div class="form-group"
+ *ngIf="targetForm.getValue('acl_enabled')"
+ [ngClass]="{'has-error': targetForm.showError('groups', formDir)}">
+ <label class="control-label col-sm-3"
+ for="initiators"
+ i18n>Groups</label>
+ <div class="col-sm-9"
+ formArrayName="groups">
+ <div class="panel panel-default"
+ *ngFor="let group of groups.controls; let gi = index"
+ [formGroupName]="gi">
+ <div class="panel-heading">
+ <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
+ <button type="button"
+ class="close"
+ (click)="groups.removeAt(gi)">
+ <i class="fa fa-remove fa-fw"></i>
+ </button>
+ </div>
+ <div class="panel-body">
+ <!-- Group: group_id -->
+ <div class="form-group">
+ <label class="control-label col-sm-3"
+ for="group_id">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ formControlName="group_id">
+ </div>
+ </div>
+
+ <!-- Group: members -->
+ <div class="form-group"
+ [ngClass]="{'has-error': group.showError('members', formDir)}">
+ <label class="control-label col-sm-3"
+ for="members">
+ <ng-container i18n>Initiators</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <ng-container *ngFor="let member of group.getValue('members'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="member"
+ disabled />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="removeGroupInitiator(group, i, gi)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="group.getValue('members')"
+ [options]="groupMembersSelections[gi]"
+ [messages]="messages.groupInitiator"
+ (selection)="onGroupMemberSelection($event)"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add initiator</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Group: disks -->
+ <div class="form-group"
+ [ngClass]="{'has-error': group.showError('disks', formDir)}">
+ <label class="control-label col-sm-3"
+ for="disks">
+ <ng-container i18n>Images</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="disk"
+ disabled />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="removeGroupDisk(group, i, gi)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="group.getValue('disks')"
+ [options]="groupDiskSelections[gi]"
+ [messages]="messages.initiatorImage"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <span class="text-muted"
+ *ngIf="groups.controls.length === 0"
+ i18n>No items added.</span>
+
+ <button (click)="addGroup(); false"
+ class="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add group</ng-container>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir"
+ (submitAction)="submit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.scss
new file mode 100644
index 00000000..cebcc887
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.scss
@@ -0,0 +1,3 @@
+.cd-mb {
+ margin-bottom: 10px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts
new file mode 100644
index 00000000..a08bad40
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts
@@ -0,0 +1,538 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import { ActivatedRouteStub } from '../../../../testing/activated-route-stub';
+import {
+ configureTestBed,
+ FormHelper,
+ i18nProviders,
+ IscsiHelper
+} from '../../../../testing/unit-test-helper';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiTargetFormComponent } from './iscsi-target-form.component';
+
+describe('IscsiTargetFormComponent', () => {
+ let component: IscsiTargetFormComponent;
+ let fixture: ComponentFixture<IscsiTargetFormComponent>;
+ let httpTesting: HttpTestingController;
+ let activatedRoute: ActivatedRouteStub;
+
+ const SETTINGS = {
+ config: { minimum_gateways: 2 },
+ disk_default_controls: {
+ 'backstore:1': {
+ hw_max_sectors: 1024,
+ osd_op_timeout: 30
+ },
+ 'backstore:2': {
+ qfull_timeout: 5
+ }
+ },
+ target_default_controls: {
+ cmdsn_depth: 128,
+ dataout_timeout: 20,
+ immediate_data: true
+ },
+ required_rbd_features: {
+ 'backstore:1': 0,
+ 'backstore:2': 0
+ },
+ unsupported_rbd_features: {
+ 'backstore:1': 0,
+ 'backstore:2': 0
+ },
+ backstores: ['backstore:1', 'backstore:2'],
+ default_backstore: 'backstore:1',
+ api_version: 1
+ };
+
+ const LIST_TARGET = [
+ {
+ target_iqn: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
+ portals: [{ host: 'node1', ip: '192.168.100.201' }],
+ disks: [
+ {
+ pool: 'rbd',
+ image: 'disk_1',
+ controls: {},
+ backstore: 'backstore:1',
+ wwn: '64af6678-9694-4367-bacc-f8eb0baa'
+ }
+ ],
+ clients: [
+ {
+ client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
+ luns: [{ pool: 'rbd', image: 'disk_1', lun: 0 }],
+ auth: {
+ user: 'myiscsiusername',
+ password: 'myiscsipassword',
+ mutual_user: null,
+ mutual_password: null
+ }
+ }
+ ],
+ groups: [],
+ target_controls: {}
+ }
+ ];
+
+ const PORTALS = [
+ { name: 'node1', ip_addresses: ['192.168.100.201', '10.0.2.15'] },
+ { name: 'node2', ip_addresses: ['192.168.100.202'] }
+ ];
+
+ const VERSION = {
+ ceph_iscsi_config_version: 11
+ };
+
+ const RBD_LIST = [
+ { status: 0, value: [], pool_name: 'ganesha' },
+ {
+ status: 0,
+ value: [
+ {
+ size: 96636764160,
+ obj_size: 4194304,
+ num_objs: 23040,
+ order: 22,
+ block_name_prefix: 'rbd_data.148162fb31a8',
+ name: 'disk_1',
+ id: '148162fb31a8',
+ pool_name: 'rbd',
+ features: 61,
+ features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'],
+ timestamp: '2019-01-18T10:44:26Z',
+ stripe_count: 1,
+ stripe_unit: 4194304,
+ data_pool: null,
+ parent: null,
+ snapshots: [],
+ total_disk_usage: 0,
+ disk_usage: 0
+ },
+ {
+ size: 119185342464,
+ obj_size: 4194304,
+ num_objs: 28416,
+ order: 22,
+ block_name_prefix: 'rbd_data.14b292cee6cb',
+ name: 'disk_2',
+ id: '14b292cee6cb',
+ pool_name: 'rbd',
+ features: 61,
+ features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'],
+ timestamp: '2019-01-18T10:45:56Z',
+ stripe_count: 1,
+ stripe_unit: 4194304,
+ data_pool: null,
+ parent: null,
+ snapshots: [],
+ total_disk_usage: 0,
+ disk_usage: 0
+ }
+ ],
+ pool_name: 'rbd'
+ }
+ ];
+
+ configureTestBed(
+ {
+ declarations: [IscsiTargetFormComponent],
+ imports: [
+ SharedModule,
+ ReactiveFormsModule,
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ToastrModule.forRoot()
+ ],
+ providers: [
+ i18nProviders,
+ {
+ provide: ActivatedRoute,
+ useValue: new ActivatedRouteStub({ target_iqn: undefined })
+ }
+ ]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetFormComponent);
+ component = fixture.componentInstance;
+ httpTesting = TestBed.get(HttpTestingController);
+ activatedRoute = TestBed.get(ActivatedRoute);
+ fixture.detectChanges();
+
+ httpTesting.expectOne('ui-api/iscsi/settings').flush(SETTINGS);
+ httpTesting.expectOne('ui-api/iscsi/portals').flush(PORTALS);
+ httpTesting.expectOne('ui-api/iscsi/version').flush(VERSION);
+ httpTesting.expectOne('api/summary').flush({});
+ httpTesting.expectOne('api/block/image').flush(RBD_LIST);
+ httpTesting.expectOne('api/iscsi/target').flush(LIST_TARGET);
+ httpTesting.verify();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should only show images not used in other targets', () => {
+ expect(component.imagesAll).toEqual([RBD_LIST[1]['value'][1]]);
+ expect(component.imagesSelections).toEqual([
+ { description: '', name: 'rbd/disk_2', selected: false, enabled: true }
+ ]);
+ });
+
+ it('should generate portals selectOptions', () => {
+ expect(component.portalsSelections).toEqual([
+ { description: '', name: 'node1:192.168.100.201', selected: false, enabled: true },
+ { description: '', name: 'node1:10.0.2.15', selected: false, enabled: true },
+ { description: '', name: 'node2:192.168.100.202', selected: false, enabled: true }
+ ]);
+ });
+
+ it('should create the form', () => {
+ expect(component.targetForm.value).toEqual({
+ disks: [],
+ groups: [],
+ initiators: [],
+ acl_enabled: false,
+ auth: {
+ password: '',
+ user: '',
+ mutual_password: '',
+ mutual_user: ''
+ },
+ portals: [],
+ target_controls: {},
+ target_iqn: component.targetForm.value.target_iqn
+ });
+ });
+
+ it('should prepare data when selecting an image', () => {
+ expect(component.imagesSettings).toEqual({});
+ component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
+ expect(component.imagesSettings).toEqual({
+ 'rbd/disk_2': {
+ lun: 0,
+ backstore: 'backstore:1',
+ 'backstore:1': {}
+ }
+ });
+ });
+
+ it('should clean data when removing an image', () => {
+ component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
+ component.addGroup();
+ component.groups.controls[0].patchValue({
+ group_id: 'foo',
+ disks: ['rbd/disk_2']
+ });
+
+ expect(component.groups.controls[0].value).toEqual({
+ disks: ['rbd/disk_2'],
+ group_id: 'foo',
+ members: []
+ });
+
+ component.onImageSelection({ option: { name: 'rbd/disk_2', selected: false } });
+
+ expect(component.groups.controls[0].value).toEqual({ disks: [], group_id: 'foo', members: [] });
+ expect(component.imagesSettings).toEqual({
+ 'rbd/disk_2': {
+ lun: 0,
+ backstore: 'backstore:1',
+ 'backstore:1': {}
+ }
+ });
+ });
+
+ it('should validate authentication', () => {
+ const control = component.targetForm;
+ const formHelper = new FormHelper(control as CdFormGroup);
+ formHelper.expectValid('auth');
+ validateAuth(formHelper);
+ });
+
+ describe('should test initiators', () => {
+ beforeEach(() => {
+ component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
+ component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true });
+ component.addGroup().patchValue({ name: 'group_1' });
+ component.addGroup().patchValue({ name: 'group_2' });
+
+ component.addInitiator();
+ component.initiators.controls[0].patchValue({
+ client_iqn: 'iqn.initiator'
+ });
+ component.updatedInitiatorSelector();
+ });
+
+ it('should prepare data when creating an initiator', () => {
+ expect(component.initiators.controls.length).toBe(1);
+ expect(component.initiators.controls[0].value).toEqual({
+ auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
+ cdIsInGroup: false,
+ client_iqn: 'iqn.initiator',
+ luns: []
+ });
+ expect(component.imagesInitiatorSelections).toEqual([
+ [{ description: '', name: 'rbd/disk_2', selected: false, enabled: true }]
+ ]);
+ expect(component.groupMembersSelections).toEqual([
+ [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }],
+ [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }]
+ ]);
+ });
+
+ it('should update data when changing an initiator name', () => {
+ expect(component.groupMembersSelections).toEqual([
+ [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }],
+ [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }]
+ ]);
+
+ component.initiators.controls[0].patchValue({
+ client_iqn: 'iqn.initiator_new'
+ });
+ component.updatedInitiatorSelector();
+
+ expect(component.groupMembersSelections).toEqual([
+ [{ description: '', name: 'iqn.initiator_new', selected: false, enabled: true }],
+ [{ description: '', name: 'iqn.initiator_new', selected: false, enabled: true }]
+ ]);
+ });
+
+ it('should clean data when removing an initiator', () => {
+ component.groups.controls[0].patchValue({
+ group_id: 'foo',
+ members: ['iqn.initiator']
+ });
+
+ expect(component.groups.controls[0].value).toEqual({
+ disks: [],
+ group_id: 'foo',
+ members: ['iqn.initiator']
+ });
+
+ component.removeInitiator(0);
+
+ expect(component.groups.controls[0].value).toEqual({
+ disks: [],
+ group_id: 'foo',
+ members: []
+ });
+ expect(component.groupMembersSelections).toEqual([[], []]);
+ expect(component.imagesInitiatorSelections).toEqual([]);
+ });
+
+ it('should remove images in the initiator when added in a group', () => {
+ component.initiators.controls[0].patchValue({
+ luns: ['rbd/disk_2']
+ });
+ expect(component.initiators.controls[0].value).toEqual({
+ auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
+ cdIsInGroup: false,
+ client_iqn: 'iqn.initiator',
+ luns: ['rbd/disk_2']
+ });
+
+ component.addGroup();
+ component.groups.controls[0].patchValue({
+ group_id: 'foo',
+ members: ['iqn.initiator']
+ });
+ component.onGroupMemberSelection({
+ option: {
+ name: 'iqn.initiator',
+ selected: true
+ }
+ });
+
+ expect(component.initiators.controls[0].value).toEqual({
+ auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
+ cdIsInGroup: true,
+ client_iqn: 'iqn.initiator',
+ luns: []
+ });
+ });
+
+ it('should disabled the initiator when selected', () => {
+ expect(component.groupMembersSelections).toEqual([
+ [{ description: '', enabled: true, name: 'iqn.initiator', selected: false }],
+ [{ description: '', enabled: true, name: 'iqn.initiator', selected: false }]
+ ]);
+
+ component.groupMembersSelections[0][0].selected = true;
+ component.onGroupMemberSelection({ option: { name: 'iqn.initiator', selected: true } });
+
+ expect(component.groupMembersSelections).toEqual([
+ [{ description: '', enabled: false, name: 'iqn.initiator', selected: true }],
+ [{ description: '', enabled: false, name: 'iqn.initiator', selected: false }]
+ ]);
+ });
+
+ it('should validate authentication', () => {
+ const control = component.initiators.controls[0];
+ const formHelper = new FormHelper(control as CdFormGroup);
+ formHelper.expectValid(control);
+ validateAuth(formHelper);
+ });
+ });
+
+ describe('should submit request', () => {
+ beforeEach(() => {
+ component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
+ component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true });
+ component.portals.setValue(['node1:192.168.100.201', 'node2:192.168.100.202']);
+ component.addInitiator().patchValue({
+ client_iqn: 'iqn.initiator'
+ });
+ component.addGroup().patchValue({
+ group_id: 'foo',
+ members: ['iqn.initiator'],
+ disks: ['rbd/disk_2']
+ });
+ });
+
+ it('should call update', () => {
+ activatedRoute.setParams({ target_iqn: 'iqn.iscsi' });
+ component.isEdit = true;
+ component.target_iqn = 'iqn.iscsi';
+
+ component.submit();
+
+ const req = httpTesting.expectOne('api/iscsi/target/iqn.iscsi');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ clients: [
+ {
+ auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
+ client_iqn: 'iqn.initiator',
+ luns: []
+ }
+ ],
+ disks: [
+ {
+ backstore: 'backstore:1',
+ controls: {},
+ image: 'disk_2',
+ pool: 'rbd',
+ lun: 0,
+ wwn: undefined
+ }
+ ],
+ groups: [
+ { disks: [{ image: 'disk_2', pool: 'rbd' }], group_id: 'foo', members: ['iqn.initiator'] }
+ ],
+ new_target_iqn: component.targetForm.value.target_iqn,
+ portals: [
+ { host: 'node1', ip: '192.168.100.201' },
+ { host: 'node2', ip: '192.168.100.202' }
+ ],
+ target_controls: {},
+ target_iqn: component.target_iqn,
+ acl_enabled: true,
+ auth: {
+ password: '',
+ user: '',
+ mutual_password: '',
+ mutual_user: ''
+ }
+ });
+ });
+
+ it('should call create', () => {
+ component.submit();
+
+ const req = httpTesting.expectOne('api/iscsi/target');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({
+ clients: [
+ {
+ auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
+ client_iqn: 'iqn.initiator',
+ luns: []
+ }
+ ],
+ disks: [
+ {
+ backstore: 'backstore:1',
+ controls: {},
+ image: 'disk_2',
+ pool: 'rbd',
+ lun: 0,
+ wwn: undefined
+ }
+ ],
+ groups: [
+ {
+ disks: [{ image: 'disk_2', pool: 'rbd' }],
+ group_id: 'foo',
+ members: ['iqn.initiator']
+ }
+ ],
+ portals: [
+ { host: 'node1', ip: '192.168.100.201' },
+ { host: 'node2', ip: '192.168.100.202' }
+ ],
+ target_controls: {},
+ target_iqn: component.targetForm.value.target_iqn,
+ acl_enabled: true,
+ auth: {
+ password: '',
+ user: '',
+ mutual_password: '',
+ mutual_user: ''
+ }
+ });
+ });
+
+ it('should call create with acl_enabled disabled', () => {
+ component.targetForm.patchValue({ acl_enabled: false });
+ component.submit();
+
+ const req = httpTesting.expectOne('api/iscsi/target');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({
+ clients: [],
+ disks: [
+ {
+ backstore: 'backstore:1',
+ controls: {},
+ image: 'disk_2',
+ pool: 'rbd',
+ lun: 0,
+ wwn: undefined
+ }
+ ],
+ groups: [],
+ acl_enabled: false,
+ auth: {
+ password: '',
+ user: '',
+ mutual_password: '',
+ mutual_user: ''
+ },
+ portals: [
+ { host: 'node1', ip: '192.168.100.201' },
+ { host: 'node2', ip: '192.168.100.202' }
+ ],
+ target_controls: {},
+ target_iqn: component.targetForm.value.target_iqn
+ });
+ });
+ });
+
+ function validateAuth(formHelper: FormHelper) {
+ IscsiHelper.validateUser(formHelper, 'auth.user');
+ IscsiHelper.validatePassword(formHelper, 'auth.password');
+ IscsiHelper.validateUser(formHelper, 'auth.mutual_user');
+ IscsiHelper.validatePassword(formHelper, 'auth.mutual_password');
+ }
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts
new file mode 100644
index 00000000..24cd6895
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts
@@ -0,0 +1,813 @@
+import { Component, OnInit } from '@angular/core';
+import { FormArray, FormControl, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { forkJoin } from 'rxjs';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { SelectMessages } from '../../../shared/components/select/select-messages.model';
+import { SelectOption } from '../../../shared/components/select/select-option.model';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { IscsiTargetImageSettingsModalComponent } from '../iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component';
+import { IscsiTargetIqnSettingsModalComponent } from '../iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component';
+
+@Component({
+ selector: 'cd-iscsi-target-form',
+ templateUrl: './iscsi-target-form.component.html',
+ styleUrls: ['./iscsi-target-form.component.scss']
+})
+export class IscsiTargetFormComponent implements OnInit {
+ cephIscsiConfigVersion: number;
+ targetForm: CdFormGroup;
+ modalRef: BsModalRef;
+ api_version = 0;
+ minimum_gateways = 1;
+ target_default_controls: any;
+ target_controls_limits: any;
+ disk_default_controls: any;
+ disk_controls_limits: any;
+ backstores: string[];
+ default_backstore: string;
+ unsupported_rbd_features: any;
+ required_rbd_features: any;
+
+ isEdit = false;
+ target_iqn: string;
+
+ imagesAll: any[];
+ imagesSelections: SelectOption[];
+ portalsSelections: SelectOption[] = [];
+
+ imagesInitiatorSelections: SelectOption[][] = [];
+ groupDiskSelections: SelectOption[][] = [];
+ groupMembersSelections: SelectOption[][] = [];
+
+ imagesSettings: any = {};
+ messages = {
+ portals: new SelectMessages(
+ { noOptions: this.i18n('There are no portals available.') },
+ this.i18n
+ ),
+ images: new SelectMessages(
+ { noOptions: this.i18n('There are no images available.') },
+ this.i18n
+ ),
+ initiatorImage: new SelectMessages(
+ {
+ noOptions: this.i18n(
+ 'There are no images available. Please make sure you add an image to the target.'
+ )
+ },
+ this.i18n
+ ),
+ groupInitiator: new SelectMessages(
+ {
+ noOptions: this.i18n(
+ 'There are no initiators available. Please make sure you add an initiator to the target.'
+ )
+ },
+ this.i18n
+ )
+ };
+
+ IQN_REGEX = /^iqn\.(19|20)\d\d-(0[1-9]|1[0-2])\.\D{2,3}(\.[A-Za-z0-9-]+)+(:[A-Za-z0-9-\.]+)*$/;
+ USER_REGEX = /^[\w\.:@_-]{8,64}$/;
+ PASSWORD_REGEX = /^[\w@\-_\/]{12,16}$/;
+ action: string;
+ resource: string;
+
+ constructor(
+ private iscsiService: IscsiService,
+ private modalService: BsModalService,
+ private rbdService: RbdService,
+ private router: Router,
+ private route: ActivatedRoute,
+ private i18n: I18n,
+ private taskWrapper: TaskWrapperService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('target');
+ }
+
+ ngOnInit() {
+ const promises: any[] = [
+ this.iscsiService.listTargets(),
+ this.rbdService.list(),
+ this.iscsiService.portals(),
+ this.iscsiService.settings(),
+ this.iscsiService.version()
+ ];
+
+ if (this.router.url.startsWith('/block/iscsi/targets/edit')) {
+ this.isEdit = true;
+ this.route.params.subscribe((params: { target_iqn: string }) => {
+ this.target_iqn = decodeURIComponent(params.target_iqn);
+ promises.push(this.iscsiService.getTarget(this.target_iqn));
+ });
+ }
+ this.action = this.isEdit ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+
+ forkJoin(promises).subscribe((data: any[]) => {
+ // iscsiService.listTargets
+ const usedImages = _(data[0])
+ .filter((target) => target.target_iqn !== this.target_iqn)
+ .flatMap((target) => target.disks)
+ .map((image) => `${image.pool}/${image.image}`)
+ .value();
+
+ // iscsiService.settings()
+ if ('api_version' in data[3]) {
+ this.api_version = data[3].api_version;
+ }
+ this.minimum_gateways = data[3].config.minimum_gateways;
+ this.target_default_controls = data[3].target_default_controls;
+ this.target_controls_limits = data[3].target_controls_limits;
+ this.disk_default_controls = data[3].disk_default_controls;
+ this.disk_controls_limits = data[3].disk_controls_limits;
+ this.backstores = data[3].backstores;
+ this.default_backstore = data[3].default_backstore;
+ this.unsupported_rbd_features = data[3].unsupported_rbd_features;
+ this.required_rbd_features = data[3].required_rbd_features;
+
+ // rbdService.list()
+ this.imagesAll = _(data[1])
+ .flatMap((pool) => pool.value)
+ .filter((image) => {
+ const imageId = `${image.pool_name}/${image.name}`;
+ if (usedImages.indexOf(imageId) !== -1) {
+ return false;
+ }
+ const validBackstores = this.getValidBackstores(image);
+ if (validBackstores.length === 0) {
+ return false;
+ }
+ return true;
+ })
+ .value();
+
+ this.imagesSelections = this.imagesAll.map(
+ (image) => new SelectOption(false, `${image.pool_name}/${image.name}`, '')
+ );
+
+ // iscsiService.portals()
+ const portals: SelectOption[] = [];
+ data[2].forEach((portal) => {
+ portal.ip_addresses.forEach((ip) => {
+ portals.push(new SelectOption(false, portal.name + ':' + ip, ''));
+ });
+ });
+ this.portalsSelections = [...portals];
+
+ // iscsiService.version()
+ this.cephIscsiConfigVersion = data[4]['ceph_iscsi_config_version'];
+
+ this.createForm();
+
+ // iscsiService.getTarget()
+ if (data[5]) {
+ this.resolveModel(data[5]);
+ }
+ });
+ }
+
+ createForm() {
+ this.targetForm = new CdFormGroup({
+ target_iqn: new FormControl('iqn.2001-07.com.ceph:' + Date.now(), {
+ validators: [Validators.required, Validators.pattern(this.IQN_REGEX)]
+ }),
+ target_controls: new FormControl({}),
+ portals: new FormControl([], {
+ validators: [
+ CdValidators.custom('minGateways', (value) => {
+ const gateways = _.uniq(value.map((elem) => elem.split(':')[0]));
+ return gateways.length < Math.max(1, this.minimum_gateways);
+ })
+ ]
+ }),
+ disks: new FormControl([], {
+ validators: [
+ CdValidators.custom('dupLunId', (value) => {
+ const lunIds = this.getLunIds(value);
+ return lunIds.length !== _.uniq(lunIds).length;
+ }),
+ CdValidators.custom('dupWwn', (value) => {
+ const wwns = this.getWwns(value);
+ return wwns.length !== _.uniq(wwns).length;
+ })
+ ]
+ }),
+ initiators: new FormArray([]),
+ groups: new FormArray([]),
+ acl_enabled: new FormControl(false)
+ });
+ // Target level authentication was introduced in ceph-iscsi config v11
+ if (this.cephIscsiConfigVersion > 10) {
+ const authFormGroup = new CdFormGroup({
+ user: new FormControl(''),
+ password: new FormControl(''),
+ mutual_user: new FormControl(''),
+ mutual_password: new FormControl('')
+ });
+ this.setAuthValidator(authFormGroup);
+ this.targetForm.addControl('auth', authFormGroup);
+ }
+ }
+
+ resolveModel(res) {
+ this.targetForm.patchValue({
+ target_iqn: res.target_iqn,
+ target_controls: res.target_controls,
+ acl_enabled: res.acl_enabled
+ });
+ // Target level authentication was introduced in ceph-iscsi config v11
+ if (this.cephIscsiConfigVersion > 10) {
+ this.targetForm.patchValue({
+ auth: res.auth
+ });
+ }
+ const portals = [];
+ _.forEach(res.portals, (portal) => {
+ const id = `${portal.host}:${portal.ip}`;
+ portals.push(id);
+ });
+ this.targetForm.patchValue({
+ portals: portals
+ });
+
+ const disks = [];
+ _.forEach(res.disks, (disk) => {
+ const id = `${disk.pool}/${disk.image}`;
+ disks.push(id);
+ this.imagesSettings[id] = {
+ backstore: disk.backstore
+ };
+ this.imagesSettings[id][disk.backstore] = disk.controls;
+ if ('lun' in disk) {
+ this.imagesSettings[id]['lun'] = disk.lun;
+ }
+ if ('wwn' in disk) {
+ this.imagesSettings[id]['wwn'] = disk.wwn;
+ }
+
+ this.onImageSelection({ option: { name: id, selected: true } });
+ });
+ this.targetForm.patchValue({
+ disks: disks
+ });
+
+ _.forEach(res.clients, (client) => {
+ const initiator = this.addInitiator();
+ client.luns = _.map(client.luns, (lun) => `${lun.pool}/${lun.image}`);
+ initiator.patchValue(client);
+ // updatedInitiatorSelector()
+ });
+
+ _.forEach(res.groups, (group) => {
+ const fg = this.addGroup();
+ group.disks = _.map(group.disks, (disk) => `${disk.pool}/${disk.image}`);
+ fg.patchValue(group);
+ _.forEach(group.members, (member) => {
+ this.onGroupMemberSelection({ option: new SelectOption(true, member, '') });
+ });
+ });
+ }
+
+ hasAdvancedSettings(settings: any) {
+ return Object.values(settings).length > 0;
+ }
+
+ // Portals
+ get portals() {
+ return this.targetForm.get('portals') as FormControl;
+ }
+
+ onPortalSelection() {
+ this.portals.setValue(this.portals.value);
+ }
+
+ removePortal(index: number, portal: string) {
+ this.portalsSelections.forEach((value) => {
+ if (value.name === portal) {
+ value.selected = false;
+ }
+ });
+
+ this.portals.value.splice(index, 1);
+ this.portals.setValue(this.portals.value);
+ return false;
+ }
+
+ // Images
+ get disks() {
+ return this.targetForm.get('disks') as FormControl;
+ }
+
+ removeImage(index: number, image: string) {
+ this.imagesSelections.forEach((value) => {
+ if (value.name === image) {
+ value.selected = false;
+ }
+ });
+ this.disks.value.splice(index, 1);
+ this.removeImageRefs(image);
+ this.targetForm.get('disks').updateValueAndValidity({ emitEvent: false });
+ return false;
+ }
+
+ removeImageRefs(name) {
+ this.initiators.controls.forEach((element) => {
+ const newImages = element.value.luns.filter((item) => item !== name);
+ element.get('luns').setValue(newImages);
+ });
+
+ this.groups.controls.forEach((element) => {
+ const newDisks = element.value.disks.filter((item) => item !== name);
+ element.get('disks').setValue(newDisks);
+ });
+
+ _.forEach(this.imagesInitiatorSelections, (selections, i) => {
+ this.imagesInitiatorSelections[i] = selections.filter((item: any) => item.name !== name);
+ });
+ _.forEach(this.groupDiskSelections, (selections, i) => {
+ this.groupDiskSelections[i] = selections.filter((item: any) => item.name !== name);
+ });
+ }
+
+ getDefaultBackstore(imageId) {
+ let result = this.default_backstore;
+ const image = this.getImageById(imageId);
+ if (!this.validFeatures(image, this.default_backstore)) {
+ this.backstores.forEach((backstore) => {
+ if (backstore !== this.default_backstore) {
+ if (this.validFeatures(image, backstore)) {
+ result = backstore;
+ }
+ }
+ });
+ }
+ return result;
+ }
+
+ isLunIdInUse(lunId, imageId) {
+ const images = this.disks.value.filter((currentImageId) => currentImageId !== imageId);
+ return this.getLunIds(images).includes(lunId);
+ }
+
+ getLunIds(images) {
+ return _.map(images, (image) => this.imagesSettings[image]['lun']);
+ }
+
+ nextLunId(imageId) {
+ const images = this.disks.value.filter((currentImageId) => currentImageId !== imageId);
+ const lunIdsInUse = this.getLunIds(images);
+ let lunIdCandidate = 0;
+ while (lunIdsInUse.includes(lunIdCandidate)) {
+ lunIdCandidate++;
+ }
+ return lunIdCandidate;
+ }
+
+ getWwns(images) {
+ const wwns = _.map(images, (image) => this.imagesSettings[image]['wwn']);
+ return wwns.filter((wwn) => _.isString(wwn) && wwn !== '');
+ }
+
+ onImageSelection($event) {
+ const option = $event.option;
+
+ if (option.selected) {
+ if (!this.imagesSettings[option.name]) {
+ const defaultBackstore = this.getDefaultBackstore(option.name);
+ this.imagesSettings[option.name] = {
+ backstore: defaultBackstore,
+ lun: this.nextLunId(option.name)
+ };
+ this.imagesSettings[option.name][defaultBackstore] = {};
+ } else if (this.isLunIdInUse(this.imagesSettings[option.name]['lun'], option.name)) {
+ // If the lun id is now in use, we have to generate a new one
+ this.imagesSettings[option.name]['lun'] = this.nextLunId(option.name);
+ }
+
+ _.forEach(this.imagesInitiatorSelections, (selections, i) => {
+ selections.push(new SelectOption(false, option.name, ''));
+ this.imagesInitiatorSelections[i] = [...selections];
+ });
+
+ _.forEach(this.groupDiskSelections, (selections, i) => {
+ selections.push(new SelectOption(false, option.name, ''));
+ this.groupDiskSelections[i] = [...selections];
+ });
+ } else {
+ this.removeImageRefs(option.name);
+ }
+ this.targetForm.get('disks').updateValueAndValidity({ emitEvent: false });
+ }
+
+ // Initiators
+ get initiators() {
+ return this.targetForm.get('initiators') as FormArray;
+ }
+
+ addInitiator() {
+ const fg = new CdFormGroup({
+ client_iqn: new FormControl('', {
+ validators: [
+ Validators.required,
+ CdValidators.custom('notUnique', (client_iqn) => {
+ const flattened = this.initiators.controls.reduce(function(accumulator, currentValue) {
+ return accumulator.concat(currentValue.value.client_iqn);
+ }, []);
+
+ return flattened.indexOf(client_iqn) !== flattened.lastIndexOf(client_iqn);
+ }),
+ Validators.pattern(this.IQN_REGEX)
+ ]
+ }),
+ auth: new CdFormGroup({
+ user: new FormControl(''),
+ password: new FormControl(''),
+ mutual_user: new FormControl(''),
+ mutual_password: new FormControl('')
+ }),
+ luns: new FormControl([]),
+ cdIsInGroup: new FormControl(false)
+ });
+
+ this.setAuthValidator(fg);
+
+ this.initiators.push(fg);
+
+ _.forEach(this.groupMembersSelections, (selections, i) => {
+ selections.push(new SelectOption(false, '', ''));
+ this.groupMembersSelections[i] = [...selections];
+ });
+
+ const disks = _.map(
+ this.targetForm.getValue('disks'),
+ (disk) => new SelectOption(false, disk, '')
+ );
+ this.imagesInitiatorSelections.push(disks);
+
+ return fg;
+ }
+
+ setAuthValidator(fg: CdFormGroup) {
+ CdValidators.validateIf(
+ fg.get('user'),
+ () => fg.getValue('password') || fg.getValue('mutual_user') || fg.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.USER_REGEX)],
+ [fg.get('password'), fg.get('mutual_user'), fg.get('mutual_password')]
+ );
+
+ CdValidators.validateIf(
+ fg.get('password'),
+ () => fg.getValue('user') || fg.getValue('mutual_user') || fg.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.PASSWORD_REGEX)],
+ [fg.get('user'), fg.get('mutual_user'), fg.get('mutual_password')]
+ );
+
+ CdValidators.validateIf(
+ fg.get('mutual_user'),
+ () => fg.getValue('mutual_password'),
+ [Validators.required],
+ [Validators.pattern(this.USER_REGEX)],
+ [fg.get('user'), fg.get('password'), fg.get('mutual_password')]
+ );
+
+ CdValidators.validateIf(
+ fg.get('mutual_password'),
+ () => fg.getValue('mutual_user'),
+ [Validators.required],
+ [Validators.pattern(this.PASSWORD_REGEX)],
+ [fg.get('user'), fg.get('password'), fg.get('mutual_user')]
+ );
+ }
+
+ removeInitiator(index) {
+ const removed = this.initiators.value[index];
+
+ this.initiators.removeAt(index);
+
+ _.forEach(this.groupMembersSelections, (selections, i) => {
+ selections.splice(index, 1);
+ this.groupMembersSelections[i] = [...selections];
+ });
+
+ this.groups.controls.forEach((element) => {
+ const newMembers = element.value.members.filter((item) => item !== removed.client_iqn);
+ element.get('members').setValue(newMembers);
+ });
+
+ this.imagesInitiatorSelections.splice(index, 1);
+ }
+
+ updatedInitiatorSelector() {
+ // Validate all client_iqn
+ this.initiators.controls.forEach((control) => {
+ control.get('client_iqn').updateValueAndValidity({ emitEvent: false });
+ });
+
+ // Update Group Initiator Selector
+ _.forEach(this.groupMembersSelections, (group, group_index) => {
+ _.forEach(group, (elem, index) => {
+ const oldName = elem.name;
+ elem.name = this.initiators.controls[index].value.client_iqn;
+
+ this.groups.controls.forEach((element) => {
+ const members = element.value.members;
+ const i = members.indexOf(oldName);
+
+ if (i !== -1) {
+ members[i] = elem.name;
+ }
+ element.get('members').setValue(members);
+ });
+ });
+ this.groupMembersSelections[group_index] = [...this.groupMembersSelections[group_index]];
+ });
+ }
+
+ removeInitiatorImage(initiator: any, lun_index: number, initiator_index: string, image: string) {
+ const luns = initiator.getValue('luns');
+ luns.splice(lun_index, 1);
+ initiator.patchValue({ luns: luns });
+
+ this.imagesInitiatorSelections[initiator_index].forEach((value) => {
+ if (value.name === image) {
+ value.selected = false;
+ }
+ });
+
+ return false;
+ }
+
+ // Groups
+ get groups() {
+ return this.targetForm.get('groups') as FormArray;
+ }
+
+ addGroup() {
+ const fg = new CdFormGroup({
+ group_id: new FormControl('', { validators: [Validators.required] }),
+ members: new FormControl([]),
+ disks: new FormControl([])
+ });
+
+ this.groups.push(fg);
+
+ const disks = _.map(
+ this.targetForm.getValue('disks'),
+ (disk) => new SelectOption(false, disk, '')
+ );
+ this.groupDiskSelections.push(disks);
+
+ const initiators = _.map(
+ this.initiators.value,
+ (initiator) => new SelectOption(false, initiator.client_iqn, '', !initiator.cdIsInGroup)
+ );
+ this.groupMembersSelections.push(initiators);
+
+ return fg;
+ }
+
+ removeGroup(index) {
+ this.groups.removeAt(index);
+ this.groupDiskSelections.splice(index, 1);
+ }
+
+ onGroupMemberSelection($event) {
+ const option = $event.option;
+
+ let initiator_index: number;
+ this.initiators.controls.forEach((element, index) => {
+ if (element.value.client_iqn === option.name) {
+ element.patchValue({ luns: [] });
+ element.get('cdIsInGroup').setValue(option.selected);
+ initiator_index = index;
+ }
+ });
+
+ // Members can only be at one group at a time, so when a member is selected
+ // in one group we need to disable its selection in other groups
+ _.forEach(this.groupMembersSelections, (group) => {
+ group[initiator_index].enabled = !option.selected;
+ });
+ }
+
+ removeGroupInitiator(group, member_index, group_index) {
+ const name = group.getValue('members')[member_index];
+ group.getValue('members').splice(member_index, 1);
+
+ this.groupMembersSelections[group_index].forEach((value) => {
+ if (value.name === name) {
+ value.selected = false;
+ }
+ });
+ this.groupMembersSelections[group_index] = [...this.groupMembersSelections[group_index]];
+
+ this.onGroupMemberSelection({ option: new SelectOption(false, name, '') });
+ }
+
+ removeGroupDisk(group, disk_index, group_index) {
+ const name = group.getValue('disks')[disk_index];
+ group.getValue('disks').splice(disk_index, 1);
+
+ this.groupDiskSelections[group_index].forEach((value) => {
+ if (value.name === name) {
+ value.selected = false;
+ }
+ });
+ this.groupDiskSelections[group_index] = [...this.groupDiskSelections[group_index]];
+ }
+
+ submit() {
+ const formValue = _.cloneDeep(this.targetForm.value);
+
+ const request = {
+ target_iqn: this.targetForm.getValue('target_iqn'),
+ target_controls: this.targetForm.getValue('target_controls'),
+ acl_enabled: this.targetForm.getValue('acl_enabled'),
+ portals: [],
+ disks: [],
+ clients: [],
+ groups: []
+ };
+
+ // Target level authentication was introduced in ceph-iscsi config v11
+ if (this.cephIscsiConfigVersion > 10) {
+ const targetAuth: CdFormGroup = this.targetForm.get('auth') as CdFormGroup;
+ if (!targetAuth.getValue('user')) {
+ targetAuth.get('user').setValue('');
+ }
+ if (!targetAuth.getValue('password')) {
+ targetAuth.get('password').setValue('');
+ }
+ if (!targetAuth.getValue('mutual_user')) {
+ targetAuth.get('mutual_user').setValue('');
+ }
+ if (!targetAuth.getValue('mutual_password')) {
+ targetAuth.get('mutual_password').setValue('');
+ }
+ const acl_enabled = this.targetForm.getValue('acl_enabled');
+ request['auth'] = {
+ user: acl_enabled ? '' : targetAuth.getValue('user'),
+ password: acl_enabled ? '' : targetAuth.getValue('password'),
+ mutual_user: acl_enabled ? '' : targetAuth.getValue('mutual_user'),
+ mutual_password: acl_enabled ? '' : targetAuth.getValue('mutual_password')
+ };
+ }
+
+ // Disks
+ formValue.disks.forEach((disk) => {
+ const imageSplit = disk.split('/');
+ const backstore = this.imagesSettings[disk].backstore;
+ request.disks.push({
+ pool: imageSplit[0],
+ image: imageSplit[1],
+ backstore: backstore,
+ controls: this.imagesSettings[disk][backstore],
+ lun: this.imagesSettings[disk]['lun'],
+ wwn: this.imagesSettings[disk]['wwn']
+ });
+ });
+
+ // Portals
+ formValue.portals.forEach((portal) => {
+ const index = portal.indexOf(':');
+ request.portals.push({
+ host: portal.substring(0, index),
+ ip: portal.substring(index + 1)
+ });
+ });
+
+ // Clients
+ if (request.acl_enabled) {
+ formValue.initiators.forEach((initiator) => {
+ if (!initiator.auth.user) {
+ initiator.auth.user = '';
+ }
+ if (!initiator.auth.password) {
+ initiator.auth.password = '';
+ }
+ if (!initiator.auth.mutual_user) {
+ initiator.auth.mutual_user = '';
+ }
+ if (!initiator.auth.mutual_password) {
+ initiator.auth.mutual_password = '';
+ }
+ delete initiator.cdIsInGroup;
+
+ const newLuns = [];
+ initiator.luns.forEach((lun) => {
+ const imageSplit = lun.split('/');
+ newLuns.push({
+ pool: imageSplit[0],
+ image: imageSplit[1]
+ });
+ });
+
+ initiator.luns = newLuns;
+ });
+ request.clients = formValue.initiators;
+ }
+
+ // Groups
+ if (request.acl_enabled) {
+ formValue.groups.forEach((group) => {
+ const newDisks = [];
+ group.disks.forEach((disk) => {
+ const imageSplit = disk.split('/');
+ newDisks.push({
+ pool: imageSplit[0],
+ image: imageSplit[1]
+ });
+ });
+
+ group.disks = newDisks;
+ });
+ request.groups = formValue.groups;
+ }
+
+ let wrapTask;
+ if (this.isEdit) {
+ request['new_target_iqn'] = request.target_iqn;
+ request.target_iqn = this.target_iqn;
+ wrapTask = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('iscsi/target/edit', {
+ target_iqn: request.target_iqn
+ }),
+ call: this.iscsiService.updateTarget(this.target_iqn, request)
+ });
+ } else {
+ wrapTask = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('iscsi/target/create', {
+ target_iqn: request.target_iqn
+ }),
+ call: this.iscsiService.createTarget(request)
+ });
+ }
+
+ wrapTask.subscribe(
+ undefined,
+ () => {
+ this.targetForm.setErrors({ cdSubmitButton: true });
+ },
+ () => this.router.navigate(['/block/iscsi/targets'])
+ );
+ }
+
+ targetSettingsModal() {
+ const initialState = {
+ target_controls: this.targetForm.get('target_controls'),
+ target_default_controls: this.target_default_controls,
+ target_controls_limits: this.target_controls_limits
+ };
+
+ this.modalRef = this.modalService.show(IscsiTargetIqnSettingsModalComponent, { initialState });
+ }
+
+ imageSettingsModal(image) {
+ const initialState = {
+ imagesSettings: this.imagesSettings,
+ image: image,
+ api_version: this.api_version,
+ disk_default_controls: this.disk_default_controls,
+ disk_controls_limits: this.disk_controls_limits,
+ backstores: this.getValidBackstores(this.getImageById(image)),
+ control: this.targetForm.get('disks')
+ };
+
+ this.modalRef = this.modalService.show(IscsiTargetImageSettingsModalComponent, {
+ initialState
+ });
+ }
+
+ validFeatures(image, backstore) {
+ const imageFeatures = image.features;
+ const requiredFeatures = this.required_rbd_features[backstore];
+ const unsupportedFeatures = this.unsupported_rbd_features[backstore];
+ // tslint:disable-next-line:no-bitwise
+ const validRequiredFeatures = (imageFeatures & requiredFeatures) === requiredFeatures;
+ // tslint:disable-next-line:no-bitwise
+ const validSupportedFeatures = (imageFeatures & unsupportedFeatures) === 0;
+ return validRequiredFeatures && validSupportedFeatures;
+ }
+
+ getImageById(imageId) {
+ return this.imagesAll.find((image) => imageId === `${image.pool_name}/${image.name}`);
+ }
+
+ getValidBackstores(image) {
+ return this.backstores.filter((backstore) => this.validFeatures(image, backstore));
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html
new file mode 100644
index 00000000..bb14ea06
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.html
@@ -0,0 +1,102 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container class="modal-title">
+ <ng-container i18n>Configure</ng-container>&nbsp;
+ <small>{{ image }}</small>
+ </ng-container>
+
+ <ng-container class="modal-content">
+ <form name="settingsForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="settingsForm"
+ novalidate>
+ <div class="modal-body">
+ <p class="alert-warning"
+ i18n>Changing these parameters from their default values is usually not necessary.</p>
+
+ <span *ngIf="api_version >= 1">
+ <legend class="cd-header"
+ i18n>Identifier</legend>
+ <!-- LUN -->
+ <div class="form-group row">
+ <div class="col-sm-12">
+ <label class="col-form-label"
+ for="lun">
+ <ng-container i18n>lun</ng-container>
+ <span class="required"></span>
+ </label>
+ <input type="number"
+ class="form-control"
+ id="lun"
+ name="lun"
+ formControlName="lun">
+ <span class="invalid-feedback"
+ *ngIf="settingsForm.showError('lun', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+ <!-- WWN -->
+ <div class="form-group row">
+ <div class="col-sm-12">
+ <label class="col-form-label"
+ for="wwn"
+ i18n>wwn</label>
+ <input type="text"
+ class="form-control"
+ id="wwn"
+ name="wwn"
+ formControlName="wwn">
+ </div>
+ </div>
+ </span>
+
+ <legend class="cd-header"
+ i18n>Settings</legend>
+
+ <!-- BACKSTORE -->
+ <div class="form-group row">
+ <div class="col-sm-12">
+ <label class="control-label"
+ i18n>Backstore</label>
+ <select id="backstore"
+ name="backstore"
+ class="form-control"
+ formControlName="backstore">
+ <option *ngFor="let bs of backstores"
+ [value]="bs">{{ bs | iscsiBackstore }}</option>
+ </select>
+ </div>
+ </div>
+
+ <!-- CONTROLS -->
+ <ng-container *ngFor="let bs of backstores">
+ <ng-container *ngIf="settingsForm.value['backstore'] === bs">
+ <div class="form-group row"
+ *ngFor="let setting of disk_default_controls[bs] | keyvalue"
+ [ngClass]="{'has-error': settingsForm.showError(setting.key, formDir)}">
+ <div class="col-sm-12">
+ <cd-iscsi-setting [settingsForm]="settingsForm"
+ [formDir]="formDir"
+ [setting]="setting.key"
+ [limits]="getDiskControlLimits(bs, setting.key)"></cd-iscsi-setting>
+ </div>
+ </div>
+ </ng-container>
+ </ng-container>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button i18n
+ [form]="settingsForm"
+ (submitAction)="save()">Confirm</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.spec.ts
new file mode 100644
index 00000000..921292bc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.spec.ts
@@ -0,0 +1,98 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiSettingComponent } from '../iscsi-setting/iscsi-setting.component';
+import { IscsiTargetImageSettingsModalComponent } from './iscsi-target-image-settings-modal.component';
+
+describe('IscsiTargetImageSettingsModalComponent', () => {
+ let component: IscsiTargetImageSettingsModalComponent;
+ let fixture: ComponentFixture<IscsiTargetImageSettingsModalComponent>;
+
+ configureTestBed({
+ declarations: [IscsiTargetImageSettingsModalComponent, IscsiSettingComponent],
+ imports: [SharedModule, ReactiveFormsModule, HttpClientTestingModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetImageSettingsModalComponent);
+ component = fixture.componentInstance;
+
+ component.imagesSettings = { 'rbd/disk_1': { backstore: 'backstore:1', 'backstore:1': {} } };
+ component.image = 'rbd/disk_1';
+ component.disk_default_controls = {
+ 'backstore:1': {
+ foo: 1,
+ bar: 2
+ },
+ 'backstore:2': {
+ baz: 3
+ }
+ };
+ component.disk_controls_limits = {
+ 'backstore:1': {
+ foo: {
+ min: 1,
+ max: 512,
+ type: 'int'
+ },
+ bar: {
+ min: 1,
+ max: 512,
+ type: 'int'
+ }
+ },
+ 'backstore:2': {
+ baz: {
+ min: 1,
+ max: 512,
+ type: 'int'
+ }
+ }
+ };
+ component.backstores = ['backstore:1', 'backstore:2'];
+ component.control = new FormControl();
+
+ component.ngOnInit();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should fill the form', () => {
+ expect(component.settingsForm.value).toEqual({
+ lun: null,
+ wwn: null,
+ backstore: 'backstore:1',
+ foo: null,
+ bar: null,
+ baz: null
+ });
+ });
+
+ it('should save changes to imagesSettings', () => {
+ component.settingsForm.controls['foo'].setValue(1234);
+ expect(component.imagesSettings).toEqual({
+ 'rbd/disk_1': { backstore: 'backstore:1', 'backstore:1': {} }
+ });
+ component.save();
+ expect(component.imagesSettings).toEqual({
+ 'rbd/disk_1': {
+ lun: null,
+ wwn: null,
+ backstore: 'backstore:1',
+ 'backstore:1': {
+ foo: 1234
+ }
+ }
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.ts
new file mode 100644
index 00000000..b8b52762
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-image-settings-modal/iscsi-target-image-settings-modal.component.ts
@@ -0,0 +1,82 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, FormControl } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+
+@Component({
+ selector: 'cd-iscsi-target-image-settings-modal',
+ templateUrl: './iscsi-target-image-settings-modal.component.html',
+ styleUrls: ['./iscsi-target-image-settings-modal.component.scss']
+})
+export class IscsiTargetImageSettingsModalComponent implements OnInit {
+ image: string;
+ imagesSettings: any;
+ api_version: number;
+ disk_default_controls: any;
+ disk_controls_limits: any;
+ backstores: any;
+ control: AbstractControl;
+
+ settingsForm: CdFormGroup;
+
+ constructor(public modalRef: BsModalRef, public iscsiService: IscsiService) {}
+
+ ngOnInit() {
+ const fg = {
+ backstore: new FormControl(this.imagesSettings[this.image]['backstore']),
+ lun: new FormControl(this.imagesSettings[this.image]['lun']),
+ wwn: new FormControl(this.imagesSettings[this.image]['wwn'])
+ };
+ _.forEach(this.backstores, (backstore) => {
+ const model = this.imagesSettings[this.image][backstore] || {};
+ _.forIn(this.disk_default_controls[backstore], (_value, key) => {
+ fg[key] = new FormControl(model[key]);
+ });
+ });
+
+ this.settingsForm = new CdFormGroup(fg);
+ }
+
+ getDiskControlLimits(backstore, setting) {
+ if (this.disk_controls_limits) {
+ return this.disk_controls_limits[backstore][setting];
+ }
+ // backward compatibility
+ return { type: 'int' };
+ }
+
+ save() {
+ const backstore = this.settingsForm.controls['backstore'].value;
+ const lun = this.settingsForm.controls['lun'].value;
+ const wwn = this.settingsForm.controls['wwn'].value;
+ const settings = {};
+ _.forIn(this.settingsForm.controls, (control, key) => {
+ if (
+ !(control.value === '' || control.value === null) &&
+ key in this.disk_default_controls[this.settingsForm.value['backstore']]
+ ) {
+ settings[key] = control.value;
+ // If one setting belongs to multiple backstores, we have to update it in all backstores
+ _.forEach(this.backstores, (currentBackstore) => {
+ if (currentBackstore !== backstore) {
+ const model = this.imagesSettings[this.image][currentBackstore] || {};
+ if (key in model) {
+ this.imagesSettings[this.image][currentBackstore][key] = control.value;
+ }
+ }
+ });
+ }
+ });
+ this.imagesSettings[this.image]['backstore'] = backstore;
+ this.imagesSettings[this.image]['lun'] = lun;
+ this.imagesSettings[this.image]['wwn'] = wwn;
+ this.imagesSettings[this.image][backstore] = settings;
+ this.imagesSettings = { ...this.imagesSettings };
+ this.control.updateValueAndValidity({ emitEvent: false });
+ this.modalRef.hide();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html
new file mode 100644
index 00000000..89c1e3b8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.html
@@ -0,0 +1,40 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container class="modal-title"
+ i18n>Advanced Settings</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="settingsForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="settingsForm"
+ novalidate>
+ <div class="modal-body">
+ <p class="alert-warning"
+ i18n>Changing these parameters from their default values is usually not necessary.</p>
+
+ <div class="form-group row"
+ *ngFor="let setting of settingsForm.controls | keyvalue"
+ [ngClass]="{'has-error': settingsForm.showError(setting.key, formDir)}">
+ <div class="col-sm-12">
+ <cd-iscsi-setting [settingsForm]="settingsForm"
+ [formDir]="formDir"
+ [setting]="setting.key"
+ [limits]="getTargetControlLimits(setting.key)"></cd-iscsi-setting>
+ </div>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button i18n
+ [form]="settingsForm"
+ (submitAction)="save()">Confirm</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.spec.ts
new file mode 100644
index 00000000..521bcbf2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.spec.ts
@@ -0,0 +1,71 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiSettingComponent } from '../iscsi-setting/iscsi-setting.component';
+import { IscsiTargetIqnSettingsModalComponent } from './iscsi-target-iqn-settings-modal.component';
+
+describe('IscsiTargetIqnSettingsModalComponent', () => {
+ let component: IscsiTargetIqnSettingsModalComponent;
+ let fixture: ComponentFixture<IscsiTargetIqnSettingsModalComponent>;
+
+ configureTestBed({
+ declarations: [IscsiTargetIqnSettingsModalComponent, IscsiSettingComponent],
+ imports: [SharedModule, ReactiveFormsModule, HttpClientTestingModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetIqnSettingsModalComponent);
+ component = fixture.componentInstance;
+ component.target_controls = new FormControl({});
+ component.target_default_controls = {
+ cmdsn_depth: 1,
+ dataout_timeout: 2,
+ first_burst_length: true
+ };
+ component.target_controls_limits = {
+ cmdsn_depth: {
+ min: 1,
+ max: 512,
+ type: 'int'
+ },
+ dataout_timeout: {
+ min: 2,
+ max: 60,
+ type: 'int'
+ },
+ first_burst_length: {
+ max: 16777215,
+ min: 512,
+ type: 'int'
+ }
+ };
+ component.ngOnInit();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should fill the settingsForm', () => {
+ expect(component.settingsForm.value).toEqual({
+ cmdsn_depth: null,
+ dataout_timeout: null,
+ first_burst_length: null
+ });
+ });
+
+ it('should save changes to target_controls', () => {
+ component.settingsForm.patchValue({ dataout_timeout: 1234 });
+ expect(component.target_controls.value).toEqual({});
+ component.save();
+ expect(component.target_controls.value).toEqual({ dataout_timeout: 1234 });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.ts
new file mode 100644
index 00000000..26e3cb0f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-iqn-settings-modal/iscsi-target-iqn-settings-modal.component.ts
@@ -0,0 +1,55 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+
+@Component({
+ selector: 'cd-iscsi-target-iqn-settings-modal',
+ templateUrl: './iscsi-target-iqn-settings-modal.component.html',
+ styleUrls: ['./iscsi-target-iqn-settings-modal.component.scss']
+})
+export class IscsiTargetIqnSettingsModalComponent implements OnInit {
+ target_controls: FormControl;
+ target_default_controls: any;
+ target_controls_limits: any;
+
+ settingsForm: CdFormGroup;
+
+ constructor(public modalRef: BsModalRef, public iscsiService: IscsiService) {}
+
+ ngOnInit() {
+ const fg = {};
+ _.forIn(this.target_default_controls, (_value, key) => {
+ fg[key] = new FormControl(this.target_controls.value[key]);
+ });
+
+ this.settingsForm = new CdFormGroup(fg);
+ }
+
+ save() {
+ const settings = {};
+ _.forIn(this.settingsForm.controls, (control, key) => {
+ if (!(control.value === '' || control.value === null)) {
+ settings[key] = control.value;
+ }
+ });
+
+ this.target_controls.setValue(settings);
+ this.modalRef.hide();
+ }
+
+ getTargetControlLimits(setting) {
+ if (this.target_controls_limits) {
+ return this.target_controls_limits[setting];
+ }
+ // backward compatibility
+ if (['Yes', 'No'].includes(this.target_default_controls[setting])) {
+ return { type: 'bool' };
+ }
+ return { type: 'int' };
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.html
new file mode 100644
index 00000000..bcd841d9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.html
@@ -0,0 +1,48 @@
+<cd-iscsi-tabs></cd-iscsi-tabs>
+
+<cd-info-panel *ngIf="available === false"
+ title="iSCSI Targets not available"
+ i18n-title>
+ <ng-container i18n>Please consult the <a href="{{docsUrl}}"
+ target="_blank">documentation</a>
+ on how to configure and enable the iSCSI Targets management functionality.</ng-container>
+
+ <ng-container *ngIf="status">
+ <br>
+ <span i18n>Available information:</span>
+ <pre>{{ status }}</pre>
+ </ng-container>
+</cd-info-panel>
+
+<cd-table #table
+ *ngIf="available === true"
+ [data]="targets"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="target_iqn"
+ forceIdentifier="true"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <div class="table-actions btn-toolbar">
+ <cd-table-actions class="btn-group"
+ [permission]="permissions.iscsi"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+
+ <button class="btn btn-sm btn-default btn-label"
+ type="button"
+ (click)="configureDiscoveryAuth()">
+ <i class="fa fa-fw fa-key-modern"
+ aria-hidden="true">
+ </i>
+ <ng-container i18n>Discovery authentication</ng-container>
+ </button>
+ </div>
+
+ <cd-iscsi-target-details cdTableDetail
+ *ngIf="selection.hasSingleSelection"
+ [cephIscsiConfigVersion]="cephIscsiConfigVersion"
+ [selection]="selection"
+ [settings]="settings"></cd-iscsi-target-details>
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.scss
new file mode 100644
index 00000000..1335bf2d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.scss
@@ -0,0 +1,9 @@
+::ng-deep tabset.tabset > ul {
+ border-bottom: 1px solid #ddd;
+ float: left;
+ display: block;
+ margin-right: 20px;
+ border-bottom: 0;
+ border-right: 1px solid #ddd;
+ padding-right: 15px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts
new file mode 100644
index 00000000..aa95a4a2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts
@@ -0,0 +1,431 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TreeModule } from 'ng2-tree';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { BehaviorSubject, of } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiTabsComponent } from '../iscsi-tabs/iscsi-tabs.component';
+import { IscsiTargetDetailsComponent } from '../iscsi-target-details/iscsi-target-details.component';
+import { IscsiTargetListComponent } from './iscsi-target-list.component';
+
+describe('IscsiTargetListComponent', () => {
+ let component: IscsiTargetListComponent;
+ let fixture: ComponentFixture<IscsiTargetListComponent>;
+ let summaryService: SummaryService;
+ let iscsiService: IscsiService;
+
+ const refresh = (data) => {
+ summaryService['summaryDataSource'].next(data);
+ };
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule,
+ SharedModule,
+ TabsModule.forRoot(),
+ TreeModule,
+ ToastrModule.forRoot()
+ ],
+ declarations: [IscsiTargetListComponent, IscsiTabsComponent, IscsiTargetDetailsComponent],
+ providers: [TaskListService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiTargetListComponent);
+ component = fixture.componentInstance;
+ summaryService = TestBed.get(SummaryService);
+ iscsiService = TestBed.get(IscsiService);
+
+ // this is needed because summaryService isn't being reset after each test.
+ summaryService['summaryDataSource'] = new BehaviorSubject(null);
+ summaryService['summaryData$'] = summaryService['summaryDataSource'].asObservable();
+
+ spyOn(iscsiService, 'status').and.returnValue(of({ available: true }));
+ spyOn(iscsiService, 'version').and.returnValue(of({ ceph_iscsi_config_version: 11 }));
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('after ngOnInit', () => {
+ beforeEach(() => {
+ spyOn(iscsiService, 'listTargets').and.callThrough();
+ fixture.detectChanges();
+ });
+
+ it('should load targets on init', () => {
+ refresh({});
+ expect(iscsiService.status).toHaveBeenCalled();
+ expect(iscsiService.listTargets).toHaveBeenCalled();
+ });
+
+ it('should not load targets on init because no data', () => {
+ refresh(undefined);
+ expect(iscsiService.listTargets).not.toHaveBeenCalled();
+ });
+
+ it('should call error function on init when summary service fails', () => {
+ spyOn(component.table, 'reset');
+ summaryService['summaryDataSource'].error(undefined);
+ expect(component.table.reset).toHaveBeenCalled();
+ });
+ });
+
+ describe('handling of executing tasks', () => {
+ let targets: any[];
+
+ const addTarget = (name) => {
+ const model: any = {
+ target_iqn: name,
+ portals: [{ host: 'node1', ip: '192.168.100.201' }],
+ disks: [{ pool: 'rbd', image: 'disk_1', controls: {} }],
+ clients: [
+ {
+ client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
+ luns: [{ pool: 'rbd', image: 'disk_1' }],
+ auth: {
+ user: 'myiscsiusername',
+ password: 'myiscsipassword',
+ mutual_user: null,
+ mutual_password: null
+ }
+ }
+ ],
+ groups: [],
+ target_controls: {}
+ };
+ targets.push(model);
+ };
+
+ const addTask = (name: string, target_iqn: string) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ switch (task.name) {
+ case 'iscsi/target/create':
+ task.metadata = {
+ target_iqn: target_iqn
+ };
+ break;
+ case 'iscsi/target/delete':
+ task.metadata = {
+ target_iqn: target_iqn
+ };
+ break;
+ default:
+ task.metadata = {
+ target_iqn: target_iqn
+ };
+ break;
+ }
+ summaryService.addRunningTask(task);
+ };
+
+ beforeEach(() => {
+ targets = [];
+ addTarget('iqn.a');
+ addTarget('iqn.b');
+ addTarget('iqn.c');
+
+ component.targets = targets;
+ refresh({ executing_tasks: [], finished_tasks: [] });
+ spyOn(iscsiService, 'listTargets').and.callFake(() => of(targets));
+ fixture.detectChanges();
+ });
+
+ it('should gets all targets without tasks', () => {
+ expect(component.targets.length).toBe(3);
+ expect(component.targets.every((target) => !target.cdExecuting)).toBeTruthy();
+ });
+
+ it('should add a new target from a task', () => {
+ addTask('iscsi/target/create', 'iqn.d');
+ expect(component.targets.length).toBe(4);
+ expectItemTasks(component.targets[0], undefined);
+ expectItemTasks(component.targets[1], undefined);
+ expectItemTasks(component.targets[2], undefined);
+ expectItemTasks(component.targets[3], 'Creating');
+ });
+
+ it('should show when an existing target is being modified', () => {
+ addTask('iscsi/target/delete', 'iqn.b');
+ expect(component.targets.length).toBe(3);
+ expectItemTasks(component.targets[1], 'Deleting');
+ });
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permissions.iscsi, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Edit',
+ empty: 'Create'
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Create' as main action`, () => {
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ scenario.single = 'Edit';
+ });
+
+ it(`should always show 'Edit'`, () => {
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows all actions except for 'Delete'`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Create' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create' and 'Delete' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows 'Create' for single selection and 'Create' as main action`, () => {
+ scenario.single = 'Create';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and edit', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows no actions`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Delete' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+
+ describe('handling of actions', () => {
+ beforeEach(() => {
+ fixture.detectChanges();
+ });
+
+ let action: CdTableAction;
+
+ const getAction = (name: string): CdTableAction => {
+ return component.tableActions.find((tableAction) => tableAction.name === name);
+ };
+
+ describe('edit', () => {
+ beforeEach(() => {
+ action = getAction('Edit');
+ });
+
+ it('should be disabled if no gateways', () => {
+ component.selection.selected = [
+ {
+ id: '-1'
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeTruthy();
+ expect(action.disableDesc(undefined)).toBe('Unavailable gateway(s)');
+ });
+
+ it('should be enabled if active sessions', () => {
+ component.selection.selected = [
+ {
+ id: '-1',
+ info: {
+ num_sessions: 1
+ }
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeFalsy();
+ expect(action.disableDesc(undefined)).toBeUndefined();
+ });
+
+ it('should be enabled if no active sessions', () => {
+ component.selection.selected = [
+ {
+ id: '-1',
+ info: {
+ num_sessions: 0
+ }
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeFalsy();
+ expect(action.disableDesc(undefined)).toBeUndefined();
+ });
+ });
+
+ describe('delete', () => {
+ beforeEach(() => {
+ action = getAction('Delete');
+ });
+
+ it('should be disabled if no gateways', () => {
+ component.selection.selected = [
+ {
+ id: '-1'
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeTruthy();
+ expect(action.disableDesc(undefined)).toBe('Unavailable gateway(s)');
+ });
+
+ it('should be disabled if active sessions', () => {
+ component.selection.selected = [
+ {
+ id: '-1',
+ info: {
+ num_sessions: 1
+ }
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeTruthy();
+ expect(action.disableDesc(undefined)).toBe('Target has active sessions');
+ });
+
+ it('should be enabled if no active sessions', () => {
+ component.selection.selected = [
+ {
+ id: '-1',
+ info: {
+ num_sessions: 0
+ }
+ }
+ ];
+ component.selection.update();
+ expect(action.disable(undefined)).toBeFalsy();
+ expect(action.disableDesc(undefined)).toBeUndefined();
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.ts
new file mode 100644
index 00000000..ddfc38ca
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.ts
@@ -0,0 +1,231 @@
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { Subscription } from 'rxjs';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permissions } from '../../../shared/models/permissions';
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { ListPipe } from '../../../shared/pipes/list.pipe';
+import { NotAvailablePipe } from '../../../shared/pipes/not-available.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { IscsiTargetDiscoveryModalComponent } from '../iscsi-target-discovery-modal/iscsi-target-discovery-modal.component';
+
+@Component({
+ selector: 'cd-iscsi-target-list',
+ templateUrl: './iscsi-target-list.component.html',
+ styleUrls: ['./iscsi-target-list.component.scss'],
+ providers: [TaskListService]
+})
+export class IscsiTargetListComponent implements OnInit, OnDestroy {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+
+ available: boolean = undefined;
+ columns: CdTableColumn[];
+ docsUrl: string;
+ modalRef: BsModalRef;
+ permissions: Permissions;
+ selection = new CdTableSelection();
+ cephIscsiConfigVersion: number;
+ settings: any;
+ status: string;
+ summaryDataSubscription: Subscription;
+ tableActions: CdTableAction[];
+ targets = [];
+
+ builders = {
+ 'iscsi/target/create': (metadata) => {
+ return {
+ target_iqn: metadata['target_iqn']
+ };
+ }
+ };
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private i18n: I18n,
+ private iscsiService: IscsiService,
+ private listPipe: ListPipe,
+ private taskListService: TaskListService,
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private notAvailablePipe: NotAvailablePipe,
+ private summaryservice: SummaryService,
+ private modalService: BsModalService,
+ private taskWrapper: TaskWrapperService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+
+ this.tableActions = [
+ {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => '/block/iscsi/targets/create',
+ name: this.actionLabels.CREATE
+ },
+ {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => `/block/iscsi/targets/edit/${this.selection.first().target_iqn}`,
+ name: this.actionLabels.EDIT,
+ disable: () => !this.selection.first() || !_.isUndefined(this.getEditDisableDesc()),
+ disableDesc: () => this.getEditDisableDesc()
+ },
+ {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteIscsiTargetModal(),
+ name: this.actionLabels.DELETE,
+ disable: () => !this.selection.first() || !_.isUndefined(this.getDeleteDisableDesc()),
+ disableDesc: () => this.getDeleteDisableDesc()
+ }
+ ];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Target'),
+ prop: 'target_iqn',
+ flexGrow: 2,
+ cellTransformation: CellTemplate.executing
+ },
+ {
+ name: this.i18n('Portals'),
+ prop: 'cdPortals',
+ pipe: this.listPipe,
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Images'),
+ prop: 'cdImages',
+ pipe: this.listPipe,
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('# Sessions'),
+ prop: 'info.num_sessions',
+ pipe: this.notAvailablePipe,
+ flexGrow: 1
+ }
+ ];
+
+ this.iscsiService.status().subscribe((result: any) => {
+ this.available = result.available;
+
+ if (result.available) {
+ this.iscsiService.version().subscribe((res: any) => {
+ this.cephIscsiConfigVersion = res['ceph_iscsi_config_version'];
+ this.taskListService.init(
+ () => this.iscsiService.listTargets(),
+ (resp) => this.prepareResponse(resp),
+ (targets) => (this.targets = targets),
+ () => this.onFetchError(),
+ this.taskFilter,
+ this.itemFilter,
+ this.builders
+ );
+ });
+
+ this.iscsiService.settings().subscribe((settings: any) => {
+ this.settings = settings;
+ });
+ } else {
+ const summary = this.summaryservice.getCurrentSummary();
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/#enabling-iscsi-management`;
+ this.status = result.message;
+ }
+ });
+ }
+
+ ngOnDestroy() {
+ if (this.summaryDataSubscription) {
+ this.summaryDataSubscription.unsubscribe();
+ }
+ }
+
+ getEditDisableDesc(): string | undefined {
+ const first = this.selection.first();
+ if (first && first.cdExecuting) {
+ return first.cdExecuting;
+ }
+ if (first && _.isUndefined(first['info'])) {
+ return this.i18n('Unavailable gateway(s)');
+ }
+ }
+
+ getDeleteDisableDesc(): string | undefined {
+ const first = this.selection.first();
+ if (first && first.cdExecuting) {
+ return first.cdExecuting;
+ }
+ if (first && _.isUndefined(first['info'])) {
+ return this.i18n('Unavailable gateway(s)');
+ }
+ if (first && first['info'] && first['info']['num_sessions']) {
+ return this.i18n('Target has active sessions');
+ }
+ }
+
+ prepareResponse(resp: any): any[] {
+ resp.forEach((element) => {
+ element.cdPortals = element.portals.map((portal) => `${portal.host}:${portal.ip}`);
+ element.cdImages = element.disks.map((disk) => `${disk.pool}/${disk.image}`);
+ });
+
+ return resp;
+ }
+
+ onFetchError() {
+ this.table.reset(); // Disable loading indicator.
+ }
+
+ itemFilter(entry, task) {
+ return entry.target_iqn === task.metadata['target_iqn'];
+ }
+
+ taskFilter(task) {
+ return ['iscsi/target/create', 'iscsi/target/edit', 'iscsi/target/delete'].includes(task.name);
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteIscsiTargetModal() {
+ const target_iqn = this.selection.first().target_iqn;
+
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.i18n('iSCSI target'),
+ itemNames: [target_iqn],
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('iscsi/target/delete', {
+ target_iqn: target_iqn
+ }),
+ call: this.iscsiService.deleteTarget(target_iqn)
+ })
+ }
+ });
+ }
+
+ configureDiscoveryAuth() {
+ this.modalService.show(IscsiTargetDiscoveryModalComponent, {});
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.html
new file mode 100644
index 00000000..59604a24
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.html
@@ -0,0 +1,55 @@
+<cd-iscsi-tabs></cd-iscsi-tabs>
+
+<legend i18n>Gateways</legend>
+<cd-table [data]="gateways"
+ (fetchData)="refresh()"
+ [columns]="gatewaysColumns">
+</cd-table>
+
+<legend i18n>Images</legend>
+<cd-table [data]="images"
+ [columns]="imagesColumns">
+</cd-table>
+
+<ng-template #statusColorTpl
+ let-value="value">
+ <span class="label"
+ [ngClass]="{'label-success': 'up' == value, 'label-danger': 'down' == value}">{{ value }}</span>
+</ng-template>
+
+<ng-template #iscsiSparklineTpl
+ let-row="row"
+ let-value="value">
+ <span *ngIf="row.backstore === 'user:rbd'">
+ <cd-sparkline [data]="value"
+ [isBinary]="row.cdIsBinary"></cd-sparkline>
+ </span>
+ <span *ngIf="row.backstore !== 'user:rbd'"
+ class="text-muted">
+ n/a
+ </span>
+</ng-template>
+
+<ng-template #iscsiPerSecondTpl
+ let-row="row"
+ let-value="value">
+ <span *ngIf="row.backstore === 'user:rbd'">
+ {{ value }} /s
+ </span>
+ <span *ngIf="row.backstore !== 'user:rbd'"
+ class="text-muted">
+ n/a
+ </span>
+</ng-template>
+
+<ng-template #iscsiRelativeDateTpl
+ let-row="row"
+ let-value="value">
+ <span *ngIf="row.backstore === 'user:rbd'">
+ {{ value | relativeDate }}
+ </span>
+ <span *ngIf="row.backstore !== 'user:rbd'"
+ class="text-muted">
+ n/a
+ </span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.spec.ts
new file mode 100644
index 00000000..c7d533c1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.spec.ts
@@ -0,0 +1,79 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { of } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { CephShortVersionPipe } from '../../../shared/pipes/ceph-short-version.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { IscsiBackstorePipe } from '../../../shared/pipes/iscsi-backstore.pipe';
+import { ListPipe } from '../../../shared/pipes/list.pipe';
+import { RelativeDatePipe } from '../../../shared/pipes/relative-date.pipe';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { IscsiComponent } from './iscsi.component';
+
+describe('IscsiComponent', () => {
+ let component: IscsiComponent;
+ let fixture: ComponentFixture<IscsiComponent>;
+ let iscsiService: IscsiService;
+ let tcmuiscsiData;
+
+ const fakeService = {
+ overview: () => {
+ return new Promise(function() {
+ return;
+ });
+ }
+ };
+
+ configureTestBed({
+ imports: [SharedModule],
+ declarations: [IscsiComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ CephShortVersionPipe,
+ DimlessPipe,
+ FormatterService,
+ RelativeDatePipe,
+ IscsiBackstorePipe,
+ ListPipe,
+ { provide: IscsiService, useValue: fakeService },
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IscsiComponent);
+ component = fixture.componentInstance;
+ iscsiService = TestBed.get(IscsiService);
+ fixture.detectChanges();
+ tcmuiscsiData = {
+ images: []
+ };
+ spyOn(iscsiService, 'overview').and.callFake(() => of(tcmuiscsiData));
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should refresh without stats available', () => {
+ tcmuiscsiData.images.push({});
+ component.refresh();
+ expect(component.images[0].cdIsBinary).toBe(true);
+ });
+
+ it('should refresh with stats', () => {
+ tcmuiscsiData.images.push({
+ stats_history: {
+ rd_bytes: [[1540551220, 0.0], [1540551225, 0.0], [1540551230, 0.0]],
+ wr_bytes: [[1540551220, 0.0], [1540551225, 0.0], [1540551230, 0.0]]
+ }
+ });
+ component.refresh();
+ expect(component.images[0].stats_history).toEqual({ rd_bytes: [0, 0, 0], wr_bytes: [0, 0, 0] });
+ expect(component.images[0].cdIsBinary).toBe(true);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.ts
new file mode 100644
index 00000000..9b771dbb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi/iscsi.component.ts
@@ -0,0 +1,114 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { IscsiService } from '../../../shared/api/iscsi.service';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { IscsiBackstorePipe } from '../../../shared/pipes/iscsi-backstore.pipe';
+
+@Component({
+ selector: 'cd-iscsi',
+ templateUrl: './iscsi.component.html',
+ styleUrls: ['./iscsi.component.scss']
+})
+export class IscsiComponent implements OnInit {
+ @ViewChild('statusColorTpl')
+ statusColorTpl: TemplateRef<any>;
+ @ViewChild('iscsiSparklineTpl')
+ iscsiSparklineTpl: TemplateRef<any>;
+ @ViewChild('iscsiPerSecondTpl')
+ iscsiPerSecondTpl: TemplateRef<any>;
+ @ViewChild('iscsiRelativeDateTpl')
+ iscsiRelativeDateTpl: TemplateRef<any>;
+
+ gateways = [];
+ gatewaysColumns: any;
+ images = [];
+ imagesColumns: any;
+
+ constructor(
+ private iscsiService: IscsiService,
+ private dimlessPipe: DimlessPipe,
+ private iscsiBackstorePipe: IscsiBackstorePipe,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.gatewaysColumns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name'
+ },
+ {
+ name: this.i18n('State'),
+ prop: 'state',
+ cellTemplate: this.statusColorTpl
+ },
+ {
+ name: this.i18n('# Targets'),
+ prop: 'num_targets'
+ },
+ {
+ name: this.i18n('# Sessions'),
+ prop: 'num_sessions'
+ }
+ ];
+ this.imagesColumns = [
+ {
+ name: this.i18n('Pool'),
+ prop: 'pool'
+ },
+ {
+ name: this.i18n('Image'),
+ prop: 'image'
+ },
+ {
+ name: this.i18n('Backstore'),
+ prop: 'backstore',
+ pipe: this.iscsiBackstorePipe
+ },
+ {
+ name: this.i18n('Read Bytes'),
+ prop: 'stats_history.rd_bytes',
+ cellTemplate: this.iscsiSparklineTpl
+ },
+ {
+ name: this.i18n('Write Bytes'),
+ prop: 'stats_history.wr_bytes',
+ cellTemplate: this.iscsiSparklineTpl
+ },
+ {
+ name: this.i18n('Read Ops'),
+ prop: 'stats.rd',
+ pipe: this.dimlessPipe,
+ cellTemplate: this.iscsiPerSecondTpl
+ },
+ {
+ name: this.i18n('Write Ops'),
+ prop: 'stats.wr',
+ pipe: this.dimlessPipe,
+ cellTemplate: this.iscsiPerSecondTpl
+ },
+ {
+ name: this.i18n('A/O Since'),
+ prop: 'optimized_since',
+ cellTemplate: this.iscsiRelativeDateTpl
+ }
+ ];
+ }
+
+ refresh() {
+ this.iscsiService.overview().subscribe((overview: Array<any>) => {
+ this.gateways = overview['gateways'];
+ this.images = overview['images'];
+ this.images.map((image) => {
+ if (image.stats_history) {
+ image.stats_history.rd_bytes = image.stats_history.rd_bytes.map((i) => i[1]);
+ image.stats_history.wr_bytes = image.stats_history.wr_bytes.map((i) => i[1]);
+ }
+ image.cdIsBinary = true;
+ return image;
+ });
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.html
new file mode 100644
index 00000000..03739388
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.html
@@ -0,0 +1,12 @@
+<cd-table [data]="data"
+ columnMode="flex"
+ [columns]="columns"
+ [autoReload]="0"
+ (fetchData)="refresh()">
+</cd-table>
+
+<ng-template #healthTmpl
+ let-row="row"
+ let-value="value">
+ <span [ngClass]="row.health_color | mirrorHealthColor">{{ value }}</span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.spec.ts
new file mode 100644
index 00000000..84425710
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MirrorHealthColorPipe } from '../mirror-health-color.pipe';
+import { DaemonListComponent } from './daemon-list.component';
+
+describe('DaemonListComponent', () => {
+ let component: DaemonListComponent;
+ let fixture: ComponentFixture<DaemonListComponent>;
+
+ configureTestBed({
+ declarations: [DaemonListComponent, MirrorHealthColorPipe],
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DaemonListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.ts
new file mode 100644
index 00000000..22156d9b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.ts
@@ -0,0 +1,63 @@
+import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { Subscription } from 'rxjs';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { CephShortVersionPipe } from '../../../../shared/pipes/ceph-short-version.pipe';
+
+@Component({
+ selector: 'cd-mirroring-daemons',
+ templateUrl: './daemon-list.component.html',
+ styleUrls: ['./daemon-list.component.scss']
+})
+export class DaemonListComponent implements OnInit, OnDestroy {
+ @ViewChild('healthTmpl')
+ healthTmpl: TemplateRef<any>;
+
+ subs: Subscription;
+
+ data: [];
+ columns: {};
+
+ constructor(
+ private rbdMirroringService: RbdMirroringService,
+ private cephShortVersionPipe: CephShortVersionPipe,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.columns = [
+ { prop: 'instance_id', name: this.i18n('Instance'), flexGrow: 2 },
+ { prop: 'id', name: this.i18n('ID'), flexGrow: 2 },
+ { prop: 'server_hostname', name: this.i18n('Hostname'), flexGrow: 2 },
+ {
+ prop: 'version',
+ name: this.i18n('Version'),
+ pipe: this.cephShortVersionPipe,
+ flexGrow: 2
+ },
+ {
+ prop: 'health',
+ name: this.i18n('Health'),
+ cellTemplate: this.healthTmpl,
+ flexGrow: 1
+ }
+ ];
+
+ this.subs = this.rbdMirroringService.subscribeSummary((data: any) => {
+ if (!data) {
+ return;
+ }
+ this.data = data.content_data.daemons;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ refresh() {
+ this.rbdMirroringService.refresh();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.html
new file mode 100644
index 00000000..419217b2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.html
@@ -0,0 +1,47 @@
+<tabset>
+ <tab heading="Issues"
+ i18n-heading>
+ <cd-table [data]="image_error.data"
+ columnMode="flex"
+ [columns]="image_error.columns"
+ [autoReload]="0"
+ (fetchData)="refresh()">
+ </cd-table>
+ </tab>
+ <tab heading="Syncing"
+ i18n-heading>
+ <cd-table [data]="image_syncing.data"
+ columnMode="flex"
+ [columns]="image_syncing.columns"
+ [autoReload]="0"
+ (fetchData)="refresh()">
+ </cd-table>
+ </tab>
+ <tab heading="Ready"
+ i18n-heading>
+ <cd-table [data]="image_ready.data"
+ columnMode="flex"
+ [columns]="image_ready.columns"
+ [autoReload]="0"
+ (fetchData)="refresh()">
+ </cd-table>
+ </tab>
+</tabset>
+
+<ng-template #stateTmpl
+ let-row="row"
+ let-value="value">
+ <span [ngClass]="row.state_color | mirrorHealthColor">{{ value }}</span>
+</ng-template>
+
+<ng-template #syncTmpl>
+ <span class="label label-info" i18n>Syncing</span>
+</ng-template>
+
+<ng-template #progressTmpl
+ let-value="value">
+ <progressbar type="info"
+ [value]="value">
+ </progressbar>
+</ng-template>
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.spec.ts
new file mode 100644
index 00000000..25307375
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MirrorHealthColorPipe } from '../mirror-health-color.pipe';
+import { ImageListComponent } from './image-list.component';
+
+describe('ImageListComponent', () => {
+ let component: ImageListComponent;
+ let fixture: ComponentFixture<ImageListComponent>;
+
+ configureTestBed({
+ declarations: [ImageListComponent, MirrorHealthColorPipe],
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ImageListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.ts
new file mode 100644
index 00000000..44810d45
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.ts
@@ -0,0 +1,97 @@
+import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { Subscription } from 'rxjs';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+
+@Component({
+ selector: 'cd-mirroring-images',
+ templateUrl: './image-list.component.html',
+ styleUrls: ['./image-list.component.scss']
+})
+export class ImageListComponent implements OnInit, OnDestroy {
+ @ViewChild('stateTmpl')
+ stateTmpl: TemplateRef<any>;
+ @ViewChild('syncTmpl')
+ syncTmpl: TemplateRef<any>;
+ @ViewChild('progressTmpl')
+ progressTmpl: TemplateRef<any>;
+
+ subs: Subscription;
+
+ image_error = {
+ data: [],
+ columns: {}
+ };
+ image_syncing = {
+ data: [],
+ columns: {}
+ };
+ image_ready = {
+ data: [],
+ columns: {}
+ };
+
+ constructor(private rbdMirroringService: RbdMirroringService, private i18n: I18n) {}
+
+ ngOnInit() {
+ this.image_error.columns = [
+ { prop: 'pool_name', name: this.i18n('Pool'), flexGrow: 2 },
+ { prop: 'name', name: this.i18n('Image'), flexGrow: 2 },
+ { prop: 'description', name: this.i18n('Issue'), flexGrow: 4 },
+ {
+ prop: 'state',
+ name: this.i18n('State'),
+ cellTemplate: this.stateTmpl,
+ flexGrow: 1
+ }
+ ];
+
+ this.image_syncing.columns = [
+ { prop: 'pool_name', name: this.i18n('Pool'), flexGrow: 2 },
+ { prop: 'name', name: this.i18n('Image'), flexGrow: 2 },
+ {
+ prop: 'progress',
+ name: this.i18n('Progress'),
+ cellTemplate: this.progressTmpl,
+ flexGrow: 2
+ },
+ {
+ prop: 'state',
+ name: this.i18n('State'),
+ cellTemplate: this.syncTmpl,
+ flexGrow: 1
+ }
+ ];
+
+ this.image_ready.columns = [
+ { prop: 'pool_name', name: this.i18n('Pool'), flexGrow: 2 },
+ { prop: 'name', name: this.i18n('Image'), flexGrow: 2 },
+ { prop: 'description', name: this.i18n('Description'), flexGrow: 4 },
+ {
+ prop: 'state',
+ name: this.i18n('State'),
+ cellTemplate: this.stateTmpl,
+ flexGrow: 1
+ }
+ ];
+
+ this.subs = this.rbdMirroringService.subscribeSummary((data: any) => {
+ if (!data) {
+ return;
+ }
+ this.image_error.data = data.content_data.image_error;
+ this.image_syncing.data = data.content_data.image_syncing;
+ this.image_ready.data = data.content_data.image_ready;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ refresh() {
+ this.rbdMirroringService.refresh();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.spec.ts
new file mode 100644
index 00000000..2b1738c8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.spec.ts
@@ -0,0 +1,25 @@
+import { MirrorHealthColorPipe } from './mirror-health-color.pipe';
+
+describe('MirrorHealthColorPipe', () => {
+ const pipe = new MirrorHealthColorPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "warning"', () => {
+ expect(pipe.transform('warning')).toBe('label label-warning');
+ });
+
+ it('transforms "error"', () => {
+ expect(pipe.transform('error')).toBe('label label-danger');
+ });
+
+ it('transforms "success"', () => {
+ expect(pipe.transform('success')).toBe('label label-success');
+ });
+
+ it('transforms others', () => {
+ expect(pipe.transform('abc')).toBe('label label-info');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.ts
new file mode 100644
index 00000000..33e0204c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirror-health-color.pipe.ts
@@ -0,0 +1,17 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'mirrorHealthColor'
+})
+export class MirrorHealthColorPipe implements PipeTransform {
+ transform(value: any): any {
+ if (value === 'warning') {
+ return 'label label-warning';
+ } else if (value === 'error') {
+ return 'label label-danger';
+ } else if (value === 'success') {
+ return 'label label-success';
+ }
+ return 'label label-info';
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirroring.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirroring.module.ts
new file mode 100644
index 00000000..932af78c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/mirroring.module.ts
@@ -0,0 +1,51 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+
+import { TreeModule } from 'ng2-tree';
+import { AlertModule } from 'ngx-bootstrap/alert';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { SharedModule } from '../../../shared/shared.module';
+
+import { DaemonListComponent } from './daemon-list/daemon-list.component';
+import { ImageListComponent } from './image-list/image-list.component';
+import { MirrorHealthColorPipe } from './mirror-health-color.pipe';
+import { OverviewComponent } from './overview/overview.component';
+import { PoolEditModeModalComponent } from './pool-edit-mode-modal/pool-edit-mode-modal.component';
+import { PoolEditPeerModalComponent } from './pool-edit-peer-modal/pool-edit-peer-modal.component';
+import { PoolListComponent } from './pool-list/pool-list.component';
+
+@NgModule({
+ entryComponents: [OverviewComponent, PoolEditModeModalComponent, PoolEditPeerModalComponent],
+ imports: [
+ CommonModule,
+ TabsModule.forRoot(),
+ SharedModule,
+ RouterModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ProgressbarModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ ModalModule.forRoot(),
+ AlertModule.forRoot(),
+ TooltipModule.forRoot(),
+ TreeModule
+ ],
+ declarations: [
+ DaemonListComponent,
+ ImageListComponent,
+ OverviewComponent,
+ PoolEditModeModalComponent,
+ PoolEditPeerModalComponent,
+ PoolListComponent,
+ MirrorHealthColorPipe
+ ],
+ exports: [OverviewComponent]
+})
+export class MirroringModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.html
new file mode 100644
index 00000000..6f598e75
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.html
@@ -0,0 +1,25 @@
+<cd-view-cache [status]="status"></cd-view-cache>
+
+<div class="row">
+ <div class="col-sm-6">
+ <legend i18n>Daemons</legend>
+
+ <cd-mirroring-daemons>
+ </cd-mirroring-daemons>
+ </div>
+
+ <div class="col-sm-6">
+ <legend i18n>Pools</legend>
+
+ <cd-mirroring-pools>
+ </cd-mirroring-pools>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col-md-12">
+ <legend i18n>Images</legend>
+ <cd-mirroring-images>
+ </cd-mirroring-images>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.spec.ts
new file mode 100644
index 00000000..a7a0aa4a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.spec.ts
@@ -0,0 +1,51 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { DaemonListComponent } from '../daemon-list/daemon-list.component';
+import { ImageListComponent } from '../image-list/image-list.component';
+import { MirrorHealthColorPipe } from '../mirror-health-color.pipe';
+import { PoolListComponent } from '../pool-list/pool-list.component';
+import { OverviewComponent } from './overview.component';
+
+describe('OverviewComponent', () => {
+ let component: OverviewComponent;
+ let fixture: ComponentFixture<OverviewComponent>;
+
+ configureTestBed({
+ declarations: [
+ DaemonListComponent,
+ ImageListComponent,
+ MirrorHealthColorPipe,
+ OverviewComponent,
+ PoolListComponent
+ ],
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ToastrModule.forRoot()
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OverviewComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.ts
new file mode 100644
index 00000000..1e285339
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.ts
@@ -0,0 +1,32 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+import { Subscription } from 'rxjs';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { ViewCacheStatus } from '../../../../shared/enum/view-cache-status.enum';
+
+@Component({
+ selector: 'cd-mirroring',
+ templateUrl: './overview.component.html',
+ styleUrls: ['./overview.component.scss']
+})
+export class OverviewComponent implements OnInit, OnDestroy {
+ subs: Subscription;
+
+ status: ViewCacheStatus;
+
+ constructor(private rbdMirroringService: RbdMirroringService) {}
+
+ ngOnInit() {
+ this.subs = this.rbdMirroringService.subscribeSummary((data: any) => {
+ if (!data) {
+ return;
+ }
+ this.status = data.content_data.status;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.html
new file mode 100644
index 00000000..78fd2dfb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.html
@@ -0,0 +1,50 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container i18n
+ class="modal-title">Edit pool mirror mode</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="editModeForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="editModeForm"
+ novalidate>
+ <div class="modal-body">
+ <p>
+ <ng-container i18n>To edit the mirror mode for pool&nbsp;
+ <kbd>{{ poolName }}</kbd>, select a new mode from the list and click&nbsp;
+ <kbd>Update</kbd>.</ng-container>
+ </p>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': editModeForm.showError('mirrorMode', formDir)}">
+ <label class="control-label"
+ for="mirrorMode">
+ <span i18n>Mode</span>
+ </label>
+ <select id="mirrorMode"
+ name="mirrorMode"
+ class="form-control"
+ formControlName="mirrorMode">
+ <option *ngFor="let mirrorMode of mirrorModes"
+ [value]="mirrorMode.id">{{ mirrorMode.name }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="editModeForm.showError('mirrorMode', formDir, 'cannotDisable')"
+ i18n>Peer clusters must be removed prior to disabling mirror.</span>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button i18n
+ [form]="editModeForm"
+ (submitAction)="update()">Update</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.spec.ts
new file mode 100644
index 00000000..5d3af10a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.spec.ts
@@ -0,0 +1,83 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ FormHelper,
+ i18nProviders
+} from '../../../../../testing/unit-test-helper';
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { PoolEditModeModalComponent } from './pool-edit-mode-modal.component';
+
+describe('PoolEditModeModalComponent', () => {
+ let component: PoolEditModeModalComponent;
+ let fixture: ComponentFixture<PoolEditModeModalComponent>;
+ let notificationService: NotificationService;
+ let rbdMirroringService: RbdMirroringService;
+ let formHelper: FormHelper;
+
+ configureTestBed({
+ declarations: [PoolEditModeModalComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ providers: [BsModalRef, BsModalService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PoolEditModeModalComponent);
+ component = fixture.componentInstance;
+ component.poolName = 'somePool';
+
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+
+ rbdMirroringService = TestBed.get(RbdMirroringService);
+
+ formHelper = new FormHelper(component.editModeForm);
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('update pool mode', () => {
+ beforeEach(() => {
+ spyOn(component.modalRef, 'hide').and.callThrough();
+ });
+
+ afterEach(() => {
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('should call updatePool', () => {
+ spyOn(rbdMirroringService, 'updatePool').and.callFake(() => of(''));
+
+ component.editModeForm.patchValue({ mirrorMode: 'disabled' });
+ component.update();
+ expect(rbdMirroringService.updatePool).toHaveBeenCalledWith('somePool', {
+ mirror_mode: 'disabled'
+ });
+ });
+ });
+
+ describe('form validation', () => {
+ it('should prevent disabling mirroring if peers exist', () => {
+ component.peerExists = true;
+ formHelper.expectErrorChange('mirrorMode', 'disabled', 'cannotDisable');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.ts
new file mode 100644
index 00000000..443b71f4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-modal.component.ts
@@ -0,0 +1,109 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { AbstractControl, FormControl, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { Subscription } from 'rxjs';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { FinishedTask } from '../../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../../shared/services/task-wrapper.service';
+import { PoolEditModeResponseModel } from './pool-edit-mode-response.model';
+
+@Component({
+ selector: 'cd-pool-edit-mode-modal',
+ templateUrl: './pool-edit-mode-modal.component.html',
+ styleUrls: ['./pool-edit-mode-modal.component.scss']
+})
+export class PoolEditModeModalComponent implements OnInit, OnDestroy {
+ poolName: string;
+
+ subs: Subscription;
+
+ editModeForm: CdFormGroup;
+ bsConfig = {
+ containerClass: 'theme-default'
+ };
+ pattern: string;
+
+ response: PoolEditModeResponseModel;
+ peerExists = false;
+
+ mirrorModes: Array<{ id: string; name: string }> = [
+ { id: 'disabled', name: this.i18n('Disabled') },
+ { id: 'pool', name: this.i18n('Pool') },
+ { id: 'image', name: this.i18n('Image') }
+ ];
+
+ constructor(
+ public modalRef: BsModalRef,
+ private i18n: I18n,
+ private rbdMirroringService: RbdMirroringService,
+ private taskWrapper: TaskWrapperService
+ ) {
+ this.createForm();
+ }
+
+ createForm() {
+ this.editModeForm = new CdFormGroup({
+ mirrorMode: new FormControl('', {
+ validators: [Validators.required, this.validateMode.bind(this)]
+ })
+ });
+ }
+
+ ngOnInit() {
+ this.pattern = `${this.poolName}`;
+ this.rbdMirroringService.getPool(this.poolName).subscribe((resp: PoolEditModeResponseModel) => {
+ this.setResponse(resp);
+ });
+
+ this.subs = this.rbdMirroringService.subscribeSummary((data: any) => {
+ this.peerExists = false;
+ if (!data) {
+ return;
+ }
+
+ const poolData = data.content_data.pools;
+ const pool = poolData.find((o) => this.poolName === o['name']);
+ this.peerExists = pool && pool['peer_uuids'].length;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ validateMode(control: AbstractControl) {
+ if (control.value === 'disabled' && this.peerExists) {
+ return { cannotDisable: { value: control.value } };
+ }
+ return null;
+ }
+
+ setResponse(response: PoolEditModeResponseModel) {
+ this.editModeForm.get('mirrorMode').setValue(response.mirror_mode);
+ }
+
+ update() {
+ const request = new PoolEditModeResponseModel();
+ request.mirror_mode = this.editModeForm.getValue('mirrorMode');
+
+ const action = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/mirroring/pool/edit', {
+ pool_name: this.poolName
+ }),
+ call: this.rbdMirroringService.updatePool(this.poolName, request)
+ });
+
+ action.subscribe(
+ undefined,
+ () => this.editModeForm.setErrors({ cdSubmitButton: true }),
+ () => {
+ this.rbdMirroringService.refresh();
+ this.modalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-response.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-response.model.ts
new file mode 100644
index 00000000..ba8bc677
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-mode-modal/pool-edit-mode-response.model.ts
@@ -0,0 +1,3 @@
+export class PoolEditModeResponseModel {
+ mirror_mode: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.html
new file mode 100644
index 00000000..c1395c39
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.html
@@ -0,0 +1,115 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container class="modal-title"
+ i18n>{mode, select, edit {Edit} other {Add}}
+ pool mirror peer</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="editPeerForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="editPeerForm"
+ novalidate>
+ <div class="modal-body">
+ <p>
+ <ng-container i18n>{mode, select, edit {Edit} other {Add}} the pool
+ mirror peer attributes for pool <kbd>{{ poolName }}</kbd> and click
+ <kbd>Submit</kbd>.</ng-container>
+ </p>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': editPeerForm.showError('clusterName', formDir)}">
+ <label class="control-label"
+ for="clusterName">
+ <span i18n>Cluster Name</span>
+ <span class="required"></span>
+ </label>
+ <input class="form-control"
+ type="text"
+ placeholder="Name..."
+ i18n-placeholder
+ id="clusterName"
+ name="clusterName"
+ formControlName="clusterName"
+ autofocus>
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('clusterName', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('clusterName', formDir, 'invalidClusterName')"
+ i18n>The cluster name is not valid.</span>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': editPeerForm.showError('clientID', formDir)}">
+ <label class="control-label"
+ for="clientID">
+ <span i18n>CephX ID</span>
+ <span class="required"></span>
+ </label>
+ <input class="form-control"
+ type="text"
+ placeholder="CephX ID..."
+ i18n-placeholder
+ id="clientID"
+ name="clientID"
+ formControlName="clientID">
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('clientID', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('clientID', formDir, 'invalidClientID')"
+ i18n>The CephX ID is not valid.</span>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': editPeerForm.showError('monAddr', formDir)}">
+ <label class="control-label"
+ for="monAddr">
+ <span i18n>Monitor Addresses</span>
+ </label>
+ <input class="form-control"
+ type="text"
+ placeholder="Comma-delimited addresses..."
+ i18n-placeholder
+ id="monAddr"
+ name="monAddr"
+ formControlName="monAddr">
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('monAddr', formDir, 'invalidMonAddr')"
+ i18n>The monitory address is not valid.</span>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': editPeerForm.showError('key', formDir)}">
+ <label class="control-label"
+ for="key">
+ <span i18n>CephX Key</span>
+ </label>
+ <input class="form-control"
+ type="text"
+ placeholder="Base64-encoded key..."
+ i18n-placeholder
+ id="key"
+ name="key"
+ formControlName="key">
+ <span class="help-block"
+ *ngIf="editPeerForm.showError('key', formDir, 'invalidKey')"
+ i18n>CephX key must be base64 encoded.</span>
+ </div>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button i18n
+ [form]="editPeerForm"
+ (submitAction)="update()">Submit</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.spec.ts
new file mode 100644
index 00000000..6353ce89
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.spec.ts
@@ -0,0 +1,152 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ FormHelper,
+ i18nProviders
+} from '../../../../../testing/unit-test-helper';
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { PoolEditPeerModalComponent } from './pool-edit-peer-modal.component';
+import { PoolEditPeerResponseModel } from './pool-edit-peer-response.model';
+
+describe('PoolEditPeerModalComponent', () => {
+ let component: PoolEditPeerModalComponent;
+ let fixture: ComponentFixture<PoolEditPeerModalComponent>;
+ let notificationService: NotificationService;
+ let rbdMirroringService: RbdMirroringService;
+ let formHelper: FormHelper;
+
+ configureTestBed({
+ declarations: [PoolEditPeerModalComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ providers: [BsModalRef, BsModalService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PoolEditPeerModalComponent);
+ component = fixture.componentInstance;
+ component.mode = 'add';
+ component.poolName = 'somePool';
+
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+
+ rbdMirroringService = TestBed.get(RbdMirroringService);
+
+ formHelper = new FormHelper(component.editPeerForm);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('add pool peer', () => {
+ beforeEach(() => {
+ component.mode = 'add';
+ component.peerUUID = undefined;
+ spyOn(rbdMirroringService, 'refresh').and.stub();
+ spyOn(component.modalRef, 'hide').and.callThrough();
+ fixture.detectChanges();
+ });
+
+ afterEach(() => {
+ expect(rbdMirroringService.refresh).toHaveBeenCalledTimes(1);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('should call addPeer', () => {
+ spyOn(rbdMirroringService, 'addPeer').and.callFake(() => of(''));
+
+ component.editPeerForm.patchValue({
+ clusterName: 'cluster',
+ clientID: 'id',
+ monAddr: 'mon_host',
+ key: 'dGVzdA=='
+ });
+
+ component.update();
+ expect(rbdMirroringService.addPeer).toHaveBeenCalledWith('somePool', {
+ cluster_name: 'cluster',
+ client_id: 'id',
+ mon_host: 'mon_host',
+ key: 'dGVzdA=='
+ });
+ });
+ });
+
+ describe('edit pool peer', () => {
+ beforeEach(() => {
+ component.mode = 'edit';
+ component.peerUUID = 'somePeer';
+
+ const response = new PoolEditPeerResponseModel();
+ response.uuid = 'somePeer';
+ response.cluster_name = 'cluster';
+ response.client_id = 'id';
+ response.mon_host = '1.2.3.4:1234';
+ response.key = 'dGVzdA==';
+
+ spyOn(rbdMirroringService, 'getPeer').and.callFake(() => of(response));
+ spyOn(rbdMirroringService, 'refresh').and.stub();
+ spyOn(component.modalRef, 'hide').and.callThrough();
+ fixture.detectChanges();
+ });
+
+ afterEach(() => {
+ expect(rbdMirroringService.getPeer).toHaveBeenCalledWith('somePool', 'somePeer');
+ expect(rbdMirroringService.refresh).toHaveBeenCalledTimes(1);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('should call updatePeer', () => {
+ spyOn(rbdMirroringService, 'updatePeer').and.callFake(() => of(''));
+
+ component.update();
+ expect(rbdMirroringService.updatePeer).toHaveBeenCalledWith('somePool', 'somePeer', {
+ cluster_name: 'cluster',
+ client_id: 'id',
+ mon_host: '1.2.3.4:1234',
+ key: 'dGVzdA=='
+ });
+ });
+ });
+
+ describe('form validation', () => {
+ beforeEach(() => {
+ fixture.detectChanges();
+ });
+
+ it('should validate cluster name', () => {
+ formHelper.expectErrorChange('clusterName', '', 'required');
+ formHelper.expectErrorChange('clusterName', ' ', 'invalidClusterName');
+ });
+
+ it('should validate client ID', () => {
+ formHelper.expectErrorChange('clientID', '', 'required');
+ formHelper.expectErrorChange('clientID', 'client.id', 'invalidClientID');
+ });
+
+ it('should validate monitor address', () => {
+ formHelper.expectErrorChange('monAddr', '@', 'invalidMonAddr');
+ });
+
+ it('should validate key', () => {
+ formHelper.expectErrorChange('key', '(', 'invalidKey');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.ts
new file mode 100644
index 00000000..aefbebae
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-modal.component.ts
@@ -0,0 +1,134 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, FormControl, Validators } from '@angular/forms';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { FinishedTask } from '../../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../../shared/services/task-wrapper.service';
+import { PoolEditPeerResponseModel } from './pool-edit-peer-response.model';
+
+@Component({
+ selector: 'cd-pool-edit-peer-modal',
+ templateUrl: './pool-edit-peer-modal.component.html',
+ styleUrls: ['./pool-edit-peer-modal.component.scss']
+})
+export class PoolEditPeerModalComponent implements OnInit {
+ mode: string;
+ poolName: string;
+ peerUUID: string;
+
+ editPeerForm: CdFormGroup;
+ bsConfig = {
+ containerClass: 'theme-default'
+ };
+ pattern: string;
+
+ response: PoolEditPeerResponseModel;
+
+ constructor(
+ public modalRef: BsModalRef,
+ private rbdMirroringService: RbdMirroringService,
+ private taskWrapper: TaskWrapperService
+ ) {
+ this.createForm();
+ }
+
+ createForm() {
+ this.editPeerForm = new CdFormGroup({
+ clusterName: new FormControl('', {
+ validators: [Validators.required, this.validateClusterName]
+ }),
+ clientID: new FormControl('', {
+ validators: [Validators.required, this.validateClientID]
+ }),
+ monAddr: new FormControl('', {
+ validators: [this.validateMonAddr]
+ }),
+ key: new FormControl('', {
+ validators: [this.validateKey]
+ })
+ });
+ }
+
+ ngOnInit() {
+ this.pattern = `${this.poolName}/${this.peerUUID}`;
+ if (this.mode === 'edit') {
+ this.rbdMirroringService
+ .getPeer(this.poolName, this.peerUUID)
+ .subscribe((resp: PoolEditPeerResponseModel) => {
+ this.setResponse(resp);
+ });
+ }
+ }
+
+ validateClusterName(control: AbstractControl) {
+ if (!control.value.match(/^[\w\-_]*$/)) {
+ return { invalidClusterName: { value: control.value } };
+ }
+ }
+
+ validateClientID(control: AbstractControl) {
+ if (!control.value.match(/^(?!client\.)[\w\-_.]*$/)) {
+ return { invalidClientID: { value: control.value } };
+ }
+ }
+
+ validateMonAddr(control: AbstractControl) {
+ if (!control.value.match(/^[,; ]*([\w.\-_\[\]]+(:[\d]+)?[,; ]*)*$/)) {
+ return { invalidMonAddr: { value: control.value } };
+ }
+ }
+
+ validateKey(control: AbstractControl) {
+ try {
+ if (control.value === '' || !!atob(control.value)) {
+ return null;
+ }
+ } catch (error) {}
+ return { invalidKey: { value: control.value } };
+ }
+
+ setResponse(response: PoolEditPeerResponseModel) {
+ this.response = response;
+ this.editPeerForm.get('clusterName').setValue(response.cluster_name);
+ this.editPeerForm.get('clientID').setValue(response.client_id);
+ this.editPeerForm.get('monAddr').setValue(response.mon_host);
+ this.editPeerForm.get('key').setValue(response.key);
+ }
+
+ update() {
+ const request = new PoolEditPeerResponseModel();
+ request.cluster_name = this.editPeerForm.getValue('clusterName');
+ request.client_id = this.editPeerForm.getValue('clientID');
+ request.mon_host = this.editPeerForm.getValue('monAddr');
+ request.key = this.editPeerForm.getValue('key');
+
+ let action;
+ if (this.mode === 'edit') {
+ action = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/mirroring/peer/edit', {
+ pool_name: this.poolName
+ }),
+ call: this.rbdMirroringService.updatePeer(this.poolName, this.peerUUID, request)
+ });
+ } else {
+ action = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/mirroring/peer/add', {
+ pool_name: this.poolName
+ }),
+ call: this.rbdMirroringService.addPeer(this.poolName, request)
+ });
+ }
+
+ action.subscribe(
+ undefined,
+ () => this.editPeerForm.setErrors({ cdSubmitButton: true }),
+ () => {
+ this.rbdMirroringService.refresh();
+ this.modalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-response.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-response.model.ts
new file mode 100644
index 00000000..fb9c67fc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-edit-peer-modal/pool-edit-peer-response.model.ts
@@ -0,0 +1,7 @@
+export class PoolEditPeerResponseModel {
+ cluster_name: string;
+ client_id: string;
+ mon_host: string;
+ key: string;
+ uuid: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.html
new file mode 100644
index 00000000..0b7cf917
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.html
@@ -0,0 +1,21 @@
+<cd-table [data]="data"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="name"
+ forceIdentifier="true"
+ [autoReload]="0"
+ (fetchData)="refresh()"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+</cd-table>
+
+<ng-template #healthTmpl
+ let-row="row"
+ let-value="value">
+ <span [ngClass]="row.health_color | mirrorHealthColor">{{ value }}</span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.spec.ts
new file mode 100644
index 00000000..129dd7c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.spec.ts
@@ -0,0 +1,42 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MirrorHealthColorPipe } from '../mirror-health-color.pipe';
+import { PoolListComponent } from './pool-list.component';
+
+describe('PoolListComponent', () => {
+ let component: PoolListComponent;
+ let fixture: ComponentFixture<PoolListComponent>;
+
+ configureTestBed({
+ declarations: [PoolListComponent, MirrorHealthColorPipe],
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ToastrModule.forRoot()
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.ts
new file mode 100644
index 00000000..98d4f48b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.ts
@@ -0,0 +1,171 @@
+import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { Observable, Subscriber, Subscription } from 'rxjs';
+
+import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { FinishedTask } from '../../../../shared/models/finished-task';
+import { Permission } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { TaskWrapperService } from '../../../../shared/services/task-wrapper.service';
+import { PoolEditModeModalComponent } from '../pool-edit-mode-modal/pool-edit-mode-modal.component';
+import { PoolEditPeerModalComponent } from '../pool-edit-peer-modal/pool-edit-peer-modal.component';
+
+@Component({
+ selector: 'cd-mirroring-pools',
+ templateUrl: './pool-list.component.html',
+ styleUrls: ['./pool-list.component.scss']
+})
+export class PoolListComponent implements OnInit, OnDestroy {
+ @ViewChild('healthTmpl')
+ healthTmpl: TemplateRef<any>;
+
+ subs: Subscription;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ selection = new CdTableSelection();
+
+ modalRef: BsModalRef;
+
+ data: [];
+ columns: {};
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private rbdMirroringService: RbdMirroringService,
+ private modalService: BsModalService,
+ private taskWrapper: TaskWrapperService,
+ private i18n: I18n
+ ) {
+ this.data = [];
+ this.permission = this.authStorageService.getPermissions().rbdMirroring;
+
+ const editModeAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-edit',
+ click: () => this.editModeModal(),
+ name: this.i18n('Edit Mode'),
+ canBePrimary: () => true
+ };
+ const addPeerAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ name: this.i18n('Add Peer'),
+ click: () => this.editPeersModal('add'),
+ disable: () => !this.selection.first() || this.selection.first().mirror_mode === 'disabled',
+ visible: () => !this.getPeerUUID(),
+ canBePrimary: () => false
+ };
+ const editPeerAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-exchange',
+ name: this.i18n('Edit Peer'),
+ click: () => this.editPeersModal('edit'),
+ visible: () => !!this.getPeerUUID()
+ };
+ const deletePeerAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ name: this.i18n('Delete Peer'),
+ click: () => this.deletePeersModal(),
+ visible: () => !!this.getPeerUUID()
+ };
+ this.tableActions = [editModeAction, addPeerAction, editPeerAction, deletePeerAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ { prop: 'name', name: this.i18n('Name'), flexGrow: 2 },
+ { prop: 'mirror_mode', name: this.i18n('Mode'), flexGrow: 2 },
+ { prop: 'leader_id', name: this.i18n('Leader'), flexGrow: 2 },
+ { prop: 'image_local_count', name: this.i18n('# Local'), flexGrow: 2 },
+ { prop: 'image_remote_count', name: this.i18n('# Remote'), flexGrow: 2 },
+ {
+ prop: 'health',
+ name: this.i18n('Health'),
+ cellTemplate: this.healthTmpl,
+ flexGrow: 1
+ }
+ ];
+
+ this.subs = this.rbdMirroringService.subscribeSummary((data: any) => {
+ if (!data) {
+ return;
+ }
+ this.data = data.content_data.pools;
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ refresh() {
+ this.rbdMirroringService.refresh();
+ }
+
+ editModeModal() {
+ const initialState = {
+ poolName: this.selection.first().name
+ };
+ this.modalRef = this.modalService.show(PoolEditModeModalComponent, { initialState });
+ }
+
+ editPeersModal(mode) {
+ const initialState = {
+ poolName: this.selection.first().name,
+ mode: mode
+ };
+ if (mode === 'edit') {
+ initialState['peerUUID'] = this.getPeerUUID();
+ }
+ this.modalRef = this.modalService.show(PoolEditPeerModalComponent, { initialState });
+ }
+
+ deletePeersModal() {
+ const poolName = this.selection.first().name;
+ const peerUUID = this.getPeerUUID();
+
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.i18n('mirror peer'),
+ itemNames: [`${poolName} (${peerUUID})`],
+ submitActionObservable: () =>
+ new Observable((observer: Subscriber<any>) => {
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('rbd/mirroring/peer/delete', {
+ pool_name: poolName
+ }),
+ call: this.rbdMirroringService.deletePeer(poolName, peerUUID)
+ })
+ .subscribe(
+ undefined,
+ (resp) => observer.error(resp),
+ () => {
+ this.rbdMirroringService.refresh();
+ observer.complete();
+ }
+ );
+ })
+ }
+ });
+ }
+
+ getPeerUUID() {
+ const selection = this.selection.first();
+ const pool = this.data.find((o) => selection && selection.name === o['name']);
+ if (pool && pool['peer_uuids']) {
+ return pool['peer_uuids'][0];
+ }
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.html
new file mode 100644
index 00000000..7a1a59b1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.html
@@ -0,0 +1,77 @@
+<fieldset #cfgFormGroup [formGroup]="form.get('configuration')">
+ <legend i18n>RBD Configuration</legend>
+
+ <div *ngFor="let section of rbdConfigurationService.sections">
+ <h3 class="page-header">
+ <span
+ (click)="toggleSectionVisibility(section.class)"
+ class="collapsible">{{ section.heading }} <i [ngClass]="{'fa-plus-circle': !sectionVisibility[section.class], 'fa-minus-circle': sectionVisibility[section.class]}" class="fa" aria-hidden="true"></i></span>
+ </h3>
+ <div class="{{ section.class }}" [hidden]="!sectionVisibility[section.class]">
+ <div
+ class="form-group"
+ *ngFor="let option of section.options"
+ [ngClass]="{'has-error': form.showError('configuration.' + option.name, cfgFormGroup)}">
+ <label
+ class="control-label col-sm-3"
+ [for]="option.name">{{ option.displayName }}<cd-helper>{{ option.description }}</cd-helper></label>
+
+ <div class="col-sm-9 {{ section.heading }}">
+ <div class="input-group">
+ <ng-container [ngSwitch]="option.type">
+ <ng-container *ngSwitchCase="configurationType.milliseconds">
+ <input
+ [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ [ngDataReady]="ngDataReady"
+ cdMilliseconds>
+ </ng-container>
+ <ng-container *ngSwitchCase="configurationType.bps">
+ <input
+ [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ defaultUnit="b"
+ [ngDataReady]="ngDataReady"
+ cdDimlessBinaryPerSecond>
+ </ng-container>
+ <ng-container *ngSwitchCase="configurationType.iops">
+ <input
+ [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ [ngDataReady]="ngDataReady"
+ cdIops>
+ </ng-container>
+ </ng-container>
+ <span class="input-group-btn">
+ <button
+ class="btn btn-default"
+ type="button"
+ data-toggle="button"
+ [ngClass]="{'active': isDisabled(option.name)}"
+ title="Remove the local configuration value. The parent configuration value will be inherited and used instead."
+ i18n-title
+ (click)="reset(option.name)">
+ <i class="fa fa-eraser"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ <span
+ i18n
+ class="help-block"
+ *ngIf="form.showError('configuration.' + option.name, cfgFormGroup, 'min')">The mininum value is 0</span>
+ </div>
+ </div>
+ </div>
+ </div>
+
+</fieldset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.scss
new file mode 100644
index 00000000..ba6460c3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.scss
@@ -0,0 +1,4 @@
+.collapsible {
+ cursor: pointer;
+ user-select: none;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.spec.ts
new file mode 100644
index 00000000..dbce8638
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.spec.ts
@@ -0,0 +1,305 @@
+import { EventEmitter } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+
+import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
+import { PositioningService } from 'ngx-bootstrap/positioning';
+import { TooltipConfig, TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper';
+import { DirectivesModule } from '../../../shared/directives/directives.module';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { RbdConfigurationSourceField } from '../../../shared/models/configuration';
+import { DimlessBinaryPerSecondPipe } from '../../../shared/pipes/dimless-binary-per-second.pipe';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { RbdConfigurationService } from '../../../shared/services/rbd-configuration.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationFormComponent } from './rbd-configuration-form.component';
+
+describe('RbdConfigurationFormComponent', () => {
+ let component: RbdConfigurationFormComponent;
+ let fixture: ComponentFixture<RbdConfigurationFormComponent>;
+ let sections: any[];
+ let fh: FormHelper;
+
+ configureTestBed({
+ imports: [ReactiveFormsModule, TooltipModule, DirectivesModule, SharedModule],
+ declarations: [RbdConfigurationFormComponent],
+ providers: [
+ ComponentLoaderFactory,
+ PositioningService,
+ TooltipConfig,
+ RbdConfigurationService,
+ FormatterService,
+ DimlessBinaryPerSecondPipe,
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdConfigurationFormComponent);
+ component = fixture.componentInstance;
+ component.form = new CdFormGroup({}, null);
+ fh = new FormHelper(component.form);
+ fixture.detectChanges();
+ sections = TestBed.get(RbdConfigurationService).sections;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should create all form fields mentioned in RbdConfiguration::OPTIONS', () => {
+ /* Test form creation on a TypeScript level */
+ const actual = Object.keys((component.form.get('configuration') as CdFormGroup).controls);
+ const expected = sections
+ .map((section) => section.options)
+ .reduce((a, b) => a.concat(b))
+ .map((option) => option.name);
+ expect(actual).toEqual(expected);
+
+ /* Test form creation on a template level */
+ const controlDebugElements = fixture.debugElement.queryAll(By.css('input.form-control'));
+ expect(controlDebugElements.length).toBe(expected.length);
+ controlDebugElements.forEach((element) => expect(element.nativeElement).toBeTruthy());
+ });
+
+ it('should only contain values of changed controls if submitted', () => {
+ let values = {};
+ component.changes.subscribe((getDirtyValues: Function) => {
+ values = getDirtyValues();
+ });
+ fh.setValue('configuration.rbd_qos_bps_limit', 0, true);
+ fixture.detectChanges();
+
+ expect(values).toEqual({ rbd_qos_bps_limit: 0 });
+ });
+
+ describe('test loading of initial data for editing', () => {
+ beforeEach(() => {
+ component.initializeData = new EventEmitter<any>();
+ fixture.detectChanges();
+ component.ngOnInit();
+ });
+
+ it('should return dirty values without any units', () => {
+ let dirtyValues = {};
+ component.changes.subscribe((getDirtyValues) => {
+ dirtyValues = getDirtyValues();
+ });
+
+ fh.setValue('configuration.rbd_qos_bps_limit', 55, true);
+ fh.setValue('configuration.rbd_qos_iops_limit', 22, true);
+
+ expect(dirtyValues['rbd_qos_bps_limit']).toBe(55);
+ expect(dirtyValues['rbd_qos_iops_limit']).toBe(22);
+ });
+
+ it('should load initial data into forms', () => {
+ component.initializeData.emit({
+ initialData: [
+ {
+ name: 'rbd_qos_bps_limit',
+ value: 55,
+ source: 1
+ }
+ ],
+ sourceType: RbdConfigurationSourceField.pool
+ });
+
+ expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('55 B/s');
+ });
+
+ it('should not load initial data if the source is not the pool itself', () => {
+ component.initializeData.emit({
+ initialData: [
+ {
+ name: 'rbd_qos_bps_limit',
+ value: 55,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ value: 22,
+ source: RbdConfigurationSourceField.global
+ }
+ ],
+ sourceType: RbdConfigurationSourceField.pool
+ });
+
+ expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('0 IOPS');
+ expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('0 B/s');
+ });
+
+ it('should not load initial data if the source is not the image itself', () => {
+ component.initializeData.emit({
+ initialData: [
+ {
+ name: 'rbd_qos_bps_limit',
+ value: 55,
+ source: RbdConfigurationSourceField.pool
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ value: 22,
+ source: RbdConfigurationSourceField.global
+ }
+ ],
+ sourceType: RbdConfigurationSourceField.image
+ });
+
+ expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('0 IOPS');
+ expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('0 B/s');
+ });
+
+ it('should always have formatted results', () => {
+ component.initializeData.emit({
+ initialData: [
+ {
+ name: 'rbd_qos_bps_limit',
+ value: 55,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ value: 22,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_read_bps_limit',
+ value: null, // incorrect type
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_read_bps_limit',
+ value: undefined, // incorrect type
+ source: RbdConfigurationSourceField.image
+ }
+ ],
+ sourceType: RbdConfigurationSourceField.image
+ });
+
+ expect(component.form.getValue('configuration.rbd_qos_iops_limit')).toEqual('22 IOPS');
+ expect(component.form.getValue('configuration.rbd_qos_bps_limit')).toEqual('55 B/s');
+ expect(component.form.getValue('configuration.rbd_qos_read_bps_limit')).toEqual('0 B/s');
+ expect(component.form.getValue('configuration.rbd_qos_read_bps_limit')).toEqual('0 B/s');
+ });
+ });
+
+ it('should reset the corresponding form field correctly', () => {
+ const fieldName = 'rbd_qos_bps_limit';
+ const getValue = () => component.form.get(`configuration.${fieldName}`).value;
+
+ // Initialization
+ fh.setValue(`configuration.${fieldName}`, 418, true);
+ expect(getValue()).toBe(418);
+
+ // Reset
+ component.reset(fieldName);
+ expect(getValue()).toBe(null);
+
+ // Restore
+ component.reset(fieldName);
+ expect(getValue()).toBe(418);
+
+ // Reset
+ component.reset(fieldName);
+ expect(getValue()).toBe(null);
+
+ // Restore
+ component.reset(fieldName);
+ expect(getValue()).toBe(418);
+ });
+
+ describe('should verify that getDirtyValues() returns correctly', () => {
+ let data;
+
+ beforeEach(() => {
+ component.initializeData = new EventEmitter<any>();
+ fixture.detectChanges();
+ component.ngOnInit();
+ data = {
+ initialData: [
+ {
+ name: 'rbd_qos_bps_limit',
+ value: 0,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ value: 0,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_read_bps_limit',
+ value: 0,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_read_iops_limit',
+ value: 0,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_read_iops_burst',
+ value: 0,
+ source: RbdConfigurationSourceField.image
+ },
+ {
+ name: 'rbd_qos_write_bps_burst',
+ value: undefined,
+ source: RbdConfigurationSourceField.global
+ },
+ {
+ name: 'rbd_qos_write_iops_burst',
+ value: null,
+ source: RbdConfigurationSourceField.global
+ }
+ ],
+ sourceType: RbdConfigurationSourceField.image
+ };
+ component.initializeData.emit(data);
+ });
+
+ it('should return an empty object', () => {
+ expect(component.getDirtyValues()).toEqual({});
+ expect(component.getDirtyValues(true, RbdConfigurationSourceField.image)).toEqual({});
+ });
+
+ it('should return dirty values', () => {
+ component.form.get('configuration.rbd_qos_write_bps_burst').markAsDirty();
+ expect(component.getDirtyValues()).toEqual({ rbd_qos_write_bps_burst: 0 });
+
+ component.form.get('configuration.rbd_qos_write_iops_burst').markAsDirty();
+ expect(component.getDirtyValues()).toEqual({
+ rbd_qos_write_iops_burst: 0,
+ rbd_qos_write_bps_burst: 0
+ });
+ });
+
+ it('should also return all local values if they do not contain their initial values', () => {
+ // Change value for all options
+ data.initialData = data.initialData.map((o) => {
+ o.value = 22;
+ return o;
+ });
+
+ // Mark some dirty
+ ['rbd_qos_read_iops_limit', 'rbd_qos_write_bps_burst'].forEach((option) => {
+ component.form.get(`configuration.${option}`).markAsDirty();
+ });
+
+ expect(component.getDirtyValues(true, RbdConfigurationSourceField.image)).toEqual({
+ rbd_qos_read_iops_limit: 0,
+ rbd_qos_write_bps_burst: 0
+ });
+ });
+
+ it('should throw an error if used incorrectly', () => {
+ expect(() => component.getDirtyValues(true)).toThrowError(
+ /^ProgrammingError: If local values shall be included/
+ );
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.ts
new file mode 100644
index 00000000..072ab6fe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.ts
@@ -0,0 +1,152 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import {
+ RbdConfigurationEntry,
+ RbdConfigurationSourceField,
+ RbdConfigurationType
+} from '../../../shared/models/configuration';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { RbdConfigurationService } from '../../../shared/services/rbd-configuration.service';
+
+@Component({
+ selector: 'cd-rbd-configuration-form',
+ templateUrl: './rbd-configuration-form.component.html',
+ styleUrls: ['./rbd-configuration-form.component.scss']
+})
+export class RbdConfigurationFormComponent implements OnInit {
+ @Input()
+ form: CdFormGroup;
+ @Input()
+ initializeData: EventEmitter<{
+ initialData: RbdConfigurationEntry[];
+ sourceType: RbdConfigurationSourceField;
+ }>;
+ @Output()
+ changes = new EventEmitter<any>();
+ ngDataReady = new EventEmitter<any>();
+ initialData: RbdConfigurationEntry[];
+ configurationType = RbdConfigurationType;
+ sectionVisibility: { [key: string]: boolean } = {};
+
+ constructor(
+ public formatterService: FormatterService,
+ public rbdConfigurationService: RbdConfigurationService
+ ) {}
+
+ ngOnInit() {
+ const configFormGroup = this.createConfigurationFormGroup();
+ this.form.addControl('configuration', configFormGroup);
+
+ // Listen to changes and emit the values to the parent component
+ configFormGroup.valueChanges.subscribe(() => {
+ this.changes.emit(this.getDirtyValues.bind(this));
+ });
+
+ if (this.initializeData) {
+ this.initializeData.subscribe((data) => {
+ this.initialData = data.initialData;
+ const dataType = data.sourceType;
+
+ this.rbdConfigurationService.getWritableOptionFields().forEach((option) => {
+ const optionData = data.initialData.filter((entry) => entry.name === option.name).pop();
+ if (optionData && optionData['source'] === dataType) {
+ this.form.get(`configuration.${option.name}`).setValue(optionData['value']);
+ }
+ });
+ this.ngDataReady.emit();
+ });
+ }
+
+ this.rbdConfigurationService
+ .getWritableSections()
+ .forEach((section) => (this.sectionVisibility[section.class] = false));
+ }
+
+ getDirtyValues(includeLocalValues = false, localFieldType?: RbdConfigurationSourceField) {
+ if (includeLocalValues && !localFieldType) {
+ const msg =
+ 'ProgrammingError: If local values shall be included, a proper localFieldType argument has to be provided, too';
+ throw new Error(msg);
+ }
+ const result = {};
+
+ this.rbdConfigurationService.getWritableOptionFields().forEach((config) => {
+ const control = this.form.get('configuration').get(config.name);
+ const dirty = control.dirty;
+
+ if (this.initialData && this.initialData[config.name] === control.value) {
+ return; // Skip controls with initial data loaded
+ }
+
+ if (dirty || (includeLocalValues && control['source'] === localFieldType)) {
+ if (control.value === null) {
+ result[config.name] = control.value;
+ } else if (config.type === RbdConfigurationType.bps) {
+ result[config.name] = this.formatterService.toBytes(control.value);
+ } else if (config.type === RbdConfigurationType.milliseconds) {
+ result[config.name] = this.formatterService.toMilliseconds(control.value);
+ } else if (config.type === RbdConfigurationType.iops) {
+ result[config.name] = this.formatterService.toIops(control.value);
+ } else {
+ result[config.name] = control.value;
+ }
+ }
+ });
+
+ return result;
+ }
+
+ /**
+ * Dynamically create form controls.
+ */
+ private createConfigurationFormGroup() {
+ const configFormGroup = new CdFormGroup({});
+
+ this.rbdConfigurationService.getWritableOptionFields().forEach((c) => {
+ let control: FormControl;
+ if (
+ c.type === RbdConfigurationType.milliseconds ||
+ c.type === RbdConfigurationType.iops ||
+ c.type === RbdConfigurationType.bps
+ ) {
+ control = new FormControl(0, Validators.min(0));
+ } else {
+ throw new Error(
+ `Type ${c.type} is unknown, you may need to add it to RbdConfiguration class`
+ );
+ }
+ configFormGroup.addControl(c.name, control);
+ });
+
+ return configFormGroup;
+ }
+
+ /**
+ * Reset the value. The inherited value will be used instead.
+ */
+ reset(optionName: string) {
+ const formControl = this.form.get('configuration').get(optionName);
+ if (formControl.disabled) {
+ formControl.setValue(formControl['previousValue'] || 0);
+ formControl.enable();
+ if (!formControl['previousValue']) {
+ formControl.markAsPristine();
+ }
+ } else {
+ formControl['previousValue'] = formControl.value;
+ formControl.setValue(null);
+ formControl.markAsDirty();
+ formControl.disable();
+ }
+ }
+
+ isDisabled(optionName: string) {
+ return this.form.get('configuration').get(optionName).disabled;
+ }
+
+ toggleSectionVisibility(className) {
+ this.sectionVisibility[className] = !this.sectionVisibility[className];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html
new file mode 100644
index 00000000..d5360932
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.html
@@ -0,0 +1,31 @@
+<cd-table
+ #poolConfTable
+ [data]="data"
+ [columns]="poolConfigurationColumns"
+ identifier="name">
+</cd-table>
+
+<ng-template #configurationSourceTpl
+ let-row="row"
+ let-value="value">
+
+ <div [ngSwitch]="value">
+ <span *ngSwitchCase="'global'"
+ i18n>Global</span>
+ <strong *ngSwitchCase="'image'"
+ i18n>Image</strong>
+ <strong *ngSwitchCase="'pool'"
+ i18n>Pool</strong>
+ </div>
+</ng-template>
+
+<ng-template #configurationValueTpl
+ let-row="row"
+ let-value="value">
+ <div [ngSwitch]="row.type">
+ <span *ngSwitchCase="typeField.bps">{{ value | dimlessBinaryPerSecond }}</span>
+ <span *ngSwitchCase="typeField.milliseconds">{{ value | milliseconds }}</span>
+ <span *ngSwitchCase="typeField.iops">{{ value | iops }}</span>
+ <span *ngSwitchDefault>{{ value }}</span>
+ </div>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts
new file mode 100644
index 00000000..bab2324a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts
@@ -0,0 +1,102 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { ChartsModule } from 'ng2-charts';
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { ErrorPanelComponent } from '../../../shared/components/error-panel/error-panel.component';
+import { SparklineComponent } from '../../../shared/components/sparkline/sparkline.component';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+import { PipesModule } from '../../../shared/pipes/pipes.module';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { RbdConfigurationService } from '../../../shared/services/rbd-configuration.service';
+import { RbdConfigurationListComponent } from './rbd-configuration-list.component';
+
+describe('RbdConfigurationListComponent', () => {
+ let component: RbdConfigurationListComponent;
+ let fixture: ComponentFixture<RbdConfigurationListComponent>;
+
+ configureTestBed({
+ imports: [
+ FormsModule,
+ NgxDatatableModule,
+ RouterTestingModule,
+ AlertModule,
+ ChartsModule,
+ PipesModule
+ ],
+ declarations: [
+ RbdConfigurationListComponent,
+ TableComponent,
+ ErrorPanelComponent,
+ SparklineComponent
+ ],
+ providers: [FormatterService, RbdConfigurationService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdConfigurationListComponent);
+ component = fixture.componentInstance;
+ component.data = [];
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('filters options out which are not defined in RbdConfigurationService', () => {
+ const fakeOption = { name: 'foo', source: 0, value: '50' } as RbdConfigurationEntry;
+ const realOption = {
+ name: 'rbd_qos_read_iops_burst',
+ source: 0,
+ value: '50'
+ } as RbdConfigurationEntry;
+
+ component.data = [fakeOption, realOption];
+ component.ngOnChanges();
+
+ expect(component.data.length).toBe(1);
+ expect(component.data.pop()).toBe(realOption);
+ });
+
+ it('should filter the source column by its piped value', () => {
+ const poolConfTable = component.poolConfTable;
+ poolConfTable.data = [
+ {
+ name: 'rbd_qos_read_iops_burst',
+ source: 0,
+ value: '50'
+ },
+ {
+ name: 'rbd_qos_read_iops_limit',
+ source: 1,
+ value: '50'
+ },
+ {
+ name: 'rbd_qos_write_iops_limit',
+ source: 0,
+ value: '100'
+ },
+ {
+ name: 'rbd_qos_write_iops_burst',
+ source: 2,
+ value: '100'
+ }
+ ];
+ const filter = (keyword) => {
+ poolConfTable.search = keyword;
+ poolConfTable.updateFilter();
+ return poolConfTable.rows;
+ };
+ expect(filter('').length).toBe(4);
+ expect(filter('source:global').length).toBe(2);
+ expect(filter('source:pool').length).toBe(1);
+ expect(filter('source:image').length).toBe(1);
+ expect(filter('source:zero').length).toBe(0);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.ts
new file mode 100644
index 00000000..9dd62177
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.ts
@@ -0,0 +1,67 @@
+import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import {
+ RbdConfigurationEntry,
+ RbdConfigurationSourceField,
+ RbdConfigurationType
+} from '../../../shared/models/configuration';
+import { RbdConfigurationSourcePipe } from '../../../shared/pipes/rbd-configuration-source.pipe';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { RbdConfigurationService } from '../../../shared/services/rbd-configuration.service';
+
+@Component({
+ selector: 'cd-rbd-configuration-table',
+ templateUrl: './rbd-configuration-list.component.html',
+ styleUrls: ['./rbd-configuration-list.component.scss']
+})
+export class RbdConfigurationListComponent implements OnInit, OnChanges {
+ @Input()
+ data: RbdConfigurationEntry[];
+ poolConfigurationColumns: CdTableColumn[];
+ @ViewChild('configurationSourceTpl')
+ configurationSourceTpl: TemplateRef<any>;
+ @ViewChild('configurationValueTpl')
+ configurationValueTpl: TemplateRef<any>;
+ @ViewChild('poolConfTable')
+ poolConfTable: TableComponent;
+
+ readonly sourceField = RbdConfigurationSourceField;
+ readonly typeField = RbdConfigurationType;
+
+ constructor(
+ public formatterService: FormatterService,
+ private rbdConfigurationService: RbdConfigurationService,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.poolConfigurationColumns = [
+ { prop: 'displayName', name: this.i18n('Name') },
+ { prop: 'description', name: this.i18n('Description') },
+ { prop: 'name', name: this.i18n('Key') },
+ {
+ prop: 'source',
+ name: this.i18n('Source'),
+ cellTemplate: this.configurationSourceTpl,
+ pipe: new RbdConfigurationSourcePipe()
+ },
+ { prop: 'value', name: this.i18n('Value'), cellTemplate: this.configurationValueTpl }
+ ];
+ }
+
+ ngOnChanges(): void {
+ if (!this.data) {
+ return;
+ }
+ // Filter settings out which are not listed in RbdConfigurationService
+ this.data = this.data.filter((row) =>
+ this.rbdConfigurationService
+ .getOptionFields()
+ .map((o) => o.name)
+ .includes(row.name)
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.html
new file mode 100644
index 00000000..716539f9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.html
@@ -0,0 +1,144 @@
+<ng-template #usageNotAvailableTooltipTpl>
+ <ng-container i18n>Only available for RBD images with <strong>fast-diff</strong> enabled</ng-container>
+</ng-template>
+
+
+<tabset *ngIf="selection?.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Name</td>
+ <td class="col-sm-3">{{ selectedItem.name }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Pool</td>
+ <td class="col-sm-3">{{ selectedItem.pool_name }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Data Pool</td>
+ <td class="col-sm-3">{{ selectedItem.data_pool | empty }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Created</td>
+ <td class="col-sm-3">{{ selectedItem.timestamp | cdDate }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Size</td>
+ <td class="col-sm-3">{{ selectedItem.size | dimlessBinary }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Objects</td>
+ <td class="col-sm-3">{{ selectedItem.num_objs | dimless }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Object size</td>
+ <td class="col-sm-3">{{ selectedItem.obj_size | dimlessBinary }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Features</td>
+ <td class="col-sm-3">
+ <span *ngFor="let feature of selectedItem.features_name">
+ <span class="badge badge-pill badge-primary margin-right-sm">{{ feature }}</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Provisioned</td>
+ <td class="col-sm-3">
+ <span *ngIf="selectedItem.features_name?.indexOf('fast-diff') === -1">
+ <span class="text-muted"
+ [tooltip]="usageNotAvailableTooltipTpl"
+ placement="top"
+ i18n>N/A</span>
+ </span>
+ <span *ngIf="selectedItem.features_name?.indexOf('fast-diff') !== -1">
+ {{ selectedItem.disk_usage | dimlessBinary }}
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Total provisioned</td>
+ <td class="col-sm-3">
+ <span *ngIf="selectedItem.features_name?.indexOf('fast-diff') === -1">
+ <span class="text-muted"
+ [tooltip]="usageNotAvailableTooltipTpl"
+ placement="top"
+ i18n>N/A</span>
+ </span>
+ <span *ngIf="selectedItem.features_name?.indexOf('fast-diff') !== -1">
+ {{ selectedItem.total_disk_usage | dimlessBinary }}
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Striping unit</td>
+ <td class="col-sm-3">{{ selectedItem.stripe_unit | dimlessBinary }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Striping count</td>
+ <td class="col-sm-3">{{ selectedItem.stripe_count }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Parent</td>
+ <td class="col-sm-3">
+ <span *ngIf="selectedItem.parent">{{ selectedItem.parent.pool_name }}
+ /{{ selectedItem.parent.image_name }}
+ @{{ selectedItem.parent.snap_name }}</span>
+ <span *ngIf="!selectedItem.parent">-</span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Block name prefix</td>
+ <td class="col-sm-3">{{ selectedItem.block_name_prefix }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Order</td>
+ <td class="col-sm-3">{{ selectedItem.order }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">Format Version</td>
+ <td>{{ selection.image_format }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </tab>
+ <tab i18n-heading
+ heading="Snapshots">
+ <cd-rbd-snapshot-list [snapshots]="selectedItem.snapshots"
+ [poolName]="selectedItem.pool_name"
+ [rbdName]="selectedItem.name"></cd-rbd-snapshot-list>
+ </tab>
+ <tab i18n-heading
+ heading="Configuration">
+ <cd-rbd-configuration-table [data]="selectedItem['configuration']"></cd-rbd-configuration-table>
+ </tab>
+</tabset>
+
+<ng-template
+ #poolConfigurationSourceTpl
+ let-row="row"
+ let-value="value">
+ <ng-container *ngIf="+value; else global">
+ <strong i18n i18n-tooltip tooltip="This setting overrides the global value">Image</strong>
+ </ng-container>
+ <ng-template #global><span i18n i18n-tooltip tooltip="This is the global value. No value for this option has been set for this image.">Global</span></ng-template>
+</ng-template>
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.spec.ts
new file mode 100644
index 00000000..44646595
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.spec.ts
@@ -0,0 +1,31 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationListComponent } from '../rbd-configuration-list/rbd-configuration-list.component';
+import { RbdSnapshotListComponent } from '../rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdDetailsComponent } from './rbd-details.component';
+
+describe('RbdDetailsComponent', () => {
+ let component: RbdDetailsComponent;
+ let fixture: ComponentFixture<RbdDetailsComponent>;
+
+ configureTestBed({
+ declarations: [RbdDetailsComponent, RbdSnapshotListComponent, RbdConfigurationListComponent],
+ imports: [SharedModule, TabsModule.forRoot(), TooltipModule.forRoot(), RouterTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdDetailsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.ts
new file mode 100644
index 00000000..a579a1d3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-details/rbd-details.component.ts
@@ -0,0 +1,27 @@
+import { Component, Input, OnChanges, TemplateRef, ViewChild } from '@angular/core';
+
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { RbdFormModel } from '../rbd-form/rbd-form.model';
+
+@Component({
+ selector: 'cd-rbd-details',
+ templateUrl: './rbd-details.component.html',
+ styleUrls: ['./rbd-details.component.scss']
+})
+export class RbdDetailsComponent implements OnChanges {
+ @Input()
+ selection: CdTableSelection;
+ selectedItem: RbdFormModel;
+ @Input()
+ images: any;
+ @ViewChild('poolConfigurationSourceTpl')
+ poolConfigurationSourceTpl: TemplateRef<any>;
+
+ constructor() {}
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-feature.interface.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-feature.interface.ts
new file mode 100644
index 00000000..c12975f0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-feature.interface.ts
@@ -0,0 +1,9 @@
+export interface RbdImageFeature {
+ desc: string;
+ allowEnable: boolean;
+ allowDisable: boolean;
+ requires?: string;
+ interlockedWith?: string;
+ key?: string;
+ initDisabled?: boolean;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-clone-request.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-clone-request.model.ts
new file mode 100644
index 00000000..0c18352d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-clone-request.model.ts
@@ -0,0 +1,12 @@
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+
+export class RbdFormCloneRequestModel {
+ child_pool_name: string;
+ child_image_name: string;
+ obj_size: number;
+ features: Array<string> = [];
+ stripe_unit: number;
+ stripe_count: number;
+ data_pool: string;
+ configuration?: RbdConfigurationEntry[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-copy-request.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-copy-request.model.ts
new file mode 100644
index 00000000..c1b290dc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-copy-request.model.ts
@@ -0,0 +1,13 @@
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+
+export class RbdFormCopyRequestModel {
+ dest_pool_name: string;
+ dest_image_name: string;
+ snapshot_name: string;
+ obj_size: number;
+ features: Array<string> = [];
+ stripe_unit: number;
+ stripe_count: number;
+ data_pool: string;
+ configuration: RbdConfigurationEntry[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-create-request.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-create-request.model.ts
new file mode 100644
index 00000000..2a2366f7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-create-request.model.ts
@@ -0,0 +1,5 @@
+import { RbdFormModel } from './rbd-form.model';
+
+export class RbdFormCreateRequestModel extends RbdFormModel {
+ features: Array<string> = [];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-edit-request.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-edit-request.model.ts
new file mode 100644
index 00000000..37997e22
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-edit-request.model.ts
@@ -0,0 +1,8 @@
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+
+export class RbdFormEditRequestModel {
+ name: string;
+ size: number;
+ features: Array<string> = [];
+ configuration: RbdConfigurationEntry[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-mode.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-mode.enum.ts
new file mode 100644
index 00000000..3db18a1d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-mode.enum.ts
@@ -0,0 +1,5 @@
+export enum RbdFormMode {
+ editing = 'editing',
+ cloning = 'cloning',
+ copying = 'copying'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-response.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-response.model.ts
new file mode 100644
index 00000000..7468e3a2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form-response.model.ts
@@ -0,0 +1,7 @@
+import { RbdFormModel } from './rbd-form.model';
+import { RbdParentModel } from './rbd-parent.model';
+
+export class RbdFormResponseModel extends RbdFormModel {
+ features_name: string[];
+ parent: RbdParentModel;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html
new file mode 100644
index 00000000..2a458b87
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html
@@ -0,0 +1,317 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="rbdForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="rbdForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Parent -->
+ <div class="form-group"
+ *ngIf="rbdForm.getValue('parent')">
+ <label i18n
+ class="control-label col-sm-3"
+ for="name">{{ action | titlecase }} from</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="parent"
+ name="parent"
+ formControlName="parent">
+ <hr>
+ </div>
+ </div>
+
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('name', formDir)}">
+ <label class="control-label col-sm-3"
+ for="name">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Name..."
+ id="name"
+ name="name"
+ formControlName="name"
+ autofocus>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('name', formDir, 'required')">
+ <ng-container i18n>This field is required.</ng-container>
+ </span>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('name', formDir, 'pattern')">
+ <ng-container i18n>'/' and '@' are not allowed.</ng-container>
+ </span>
+ </div>
+ </div>
+
+ <!-- Pool -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('pool', formDir)}"
+ (change)="onPoolChange($event.target.value)">
+ <label class="control-label col-sm-3"
+ for="pool">
+ Pool
+ <span class="required"
+ *ngIf="mode !== 'editing'"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Pool name..."
+ id="pool"
+ name="pool"
+ formControlName="pool"
+ *ngIf="mode === 'editing' || !poolPermission.read">
+ <select id="pool"
+ name="pool"
+ class="form-control"
+ formControlName="pool"
+ *ngIf="mode !== 'editing' && poolPermission.read">
+ <option *ngIf="pools === null"
+ [ngValue]="null"
+ i18n>Loading...</option>
+ <option *ngIf="pools !== null && pools.length === 0"
+ [ngValue]="null"
+ i18n>-- No rbd pools available --</option>
+ <option *ngIf="pools !== null && pools.length > 0"
+ [ngValue]="null"
+ i18n>-- Select a pool --</option>
+ <option *ngFor="let pool of pools"
+ [value]="pool.pool_name">{{ pool.pool_name }}</option>
+ </select>
+ <span *ngIf="rbdForm.showError('pool', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Use a dedicated pool -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ id="useDataPool"
+ name="useDataPool"
+ formControlName="useDataPool"
+ (change)="onUseDataPoolChange()">
+ <label i18n
+ for="useDataPool">Use a dedicated data pool</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Data Pool -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('dataPool', formDir)}"
+ *ngIf="rbdForm.getValue('useDataPool')">
+ <label class="control-label col-sm-3"
+ for="dataPool">
+ <ng-container i18n>Data pool</ng-container>
+ <span class="required"
+ *ngIf="mode !== 'editing'"></span>
+ <cd-helper i18n-html
+ html="Dedicated pool that stores the object-data of the RBD.">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Data pool name..."
+ id="dataPool"
+ name="dataPool"
+ formControlName="dataPool"
+ *ngIf="mode === 'editing' || !poolPermission.read">
+ <select id="dataPool"
+ name="dataPool"
+ class="form-control"
+ formControlName="dataPool"
+ (change)="onDataPoolChange($event.target.value)"
+ *ngIf="mode !== 'editing' && poolPermission.read">
+ <option *ngIf="dataPools === null"
+ [ngValue]="null"
+ i18n>Loading...</option>
+ <option *ngIf="dataPools !== null && dataPools.length === 0"
+ [ngValue]="null"
+ i18n>-- No data pools available --</option>
+ <option *ngIf="dataPools !== null && dataPools.length > 0"
+ [ngValue]="null">-- Select a data pool --
+ </option>
+ <option *ngFor="let dataPool of dataPools"
+ [value]="dataPool.pool_name">{{ dataPool.pool_name }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('dataPool', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('size', formDir)}">
+ <label class="control-label col-sm-3"
+ for="size">
+ <ng-container i18n>Size</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="size"
+ name="size"
+ class="form-control"
+ type="text"
+ formControlName="size"
+ i18n-placeholder
+ placeholder="e.g., 10GiB"
+ defaultUnit="GiB"
+ cdDimlessBinary>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('size', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('size', formDir, 'invalidSizeObject')"
+ i18n>You have to increase the size.</span>
+ </div>
+ </div>
+
+ <!-- Features -->
+ <div class="form-group"
+ [ngClass]="{'has-error': (formDir.submitted || rbdForm.get('features').dirty) && rbdForm.get('features').invalid}"
+ formGroupName="features">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="features">Features</label>
+ <div class="col-sm-9">
+ <div class="checkbox checkbox-primary"
+ *ngFor="let feature of featuresList">
+ <input type="checkbox"
+ id="{{ feature.key }}"
+ name="{{ feature.key }}"
+ formControlName="{{ feature.key }}">
+ <label for="{{ feature.key }}">{{ feature.desc }}</label>
+ <cd-helper *ngIf="feature.helperHtml"
+ html="{{ feature.helperHtml }}">
+ </cd-helper>
+ </div>
+ </div>
+ </div>
+
+ <!-- Advanced -->
+ <div class="row">
+ <div class="col-sm-12">
+ <a class="pull-right margin-right-md"
+ (click)="advancedEnabled = true"
+ *ngIf="!advancedEnabled"
+ i18n>Advanced...</a>
+ </div>
+ </div>
+ <div [hidden]="!advancedEnabled">
+
+ <h2 i18n
+ class="page-header">Advanced</h2>
+
+ <div class="section">
+ <h3 class="page-header" i18n>Striping</h3>
+
+ <!-- Object Size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('obj_size', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="size">Object size</label>
+ <div class="col-sm-9">
+ <select id="obj_size"
+ name="obj_size"
+ class="form-control"
+ formControlName="obj_size">
+ <option *ngFor="let objectSize of objectSizes"
+ [value]="objectSize">{{ objectSize }}</option>
+ </select>
+ </div>
+ </div>
+
+ <!-- Stripe Unit -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('stripingUnit', formDir)}">
+ <label class="control-label col-sm-3"
+ for="stripingUnit">
+ <span i18n>Stripe unit</span>
+ <span class="required"
+ *ngIf="rbdForm.getValue('stripingCount')">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <select id="stripingUnit"
+ name="stripingUnit"
+ class="form-control"
+ formControlName="stripingUnit">
+ <option i18n
+ [ngValue]="null">-- Select stripe unit --</option>
+ <option *ngFor="let objectSize of objectSizes"
+ [value]="objectSize">{{ objectSize }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('stripingUnit', formDir, 'required')"
+ i18n>This field is required because stripe count is defined!</span>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('stripingUnit', formDir, 'invalidStripingUnit')"
+ i18n>Stripe unit is greater than object size.</span>
+ </div>
+ </div>
+
+ <!-- Stripe Count -->
+ <div class="form-group"
+ [ngClass]="{'has-error': rbdForm.showError('stripingCount', formDir)}">
+ <label class="control-label col-sm-3"
+ for="stripingCount">
+ <span i18n>Stripe count</span>
+ <span class="required"
+ *ngIf="rbdForm.getValue('stripingUnit')">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="stripingCount"
+ name="stripingCount"
+ formControlName="stripingCount"
+ class="form-control"
+ type="number">
+ <span class="help-block"
+ *ngIf="rbdForm.showError('stripingCount', formDir, 'required')"
+ i18n>This field is required because stripe unit is defined!</span>
+ <span class="help-block"
+ *ngIf="rbdForm.showError('stripingCount', formDir, 'min')"
+ i18n>Stripe count must be greater than 0.</span>
+ </div>
+ </div>
+ </div>
+
+ <div class="section">
+ <cd-rbd-configuration-form [form]="rbdForm"
+ [initializeData]="initializeConfigData"
+ (changes)="getDirtyConfigurationValues = $event"></cd-rbd-configuration-form>
+ </div>
+
+ </div>
+
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir"
+ (submitAction)="submit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.spec.ts
new file mode 100644
index 00000000..03a2c88a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.spec.ts
@@ -0,0 +1,343 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import { By } from '@angular/platform-browser';
+import { of } from 'rxjs';
+import { delay } from 'rxjs/operators';
+
+import { ActivatedRouteStub } from '../../../../testing/activated-route-stub';
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationFormComponent } from '../rbd-configuration-form/rbd-configuration-form.component';
+import { RbdFormMode } from './rbd-form-mode.enum';
+import { RbdFormComponent } from './rbd-form.component';
+
+describe('RbdFormComponent', () => {
+ let component: RbdFormComponent;
+ let fixture: ComponentFixture<RbdFormComponent>;
+ let activatedRoute: ActivatedRouteStub;
+
+ const queryNativeElement = (cssSelector) =>
+ fixture.debugElement.query(By.css(cssSelector)).nativeElement;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ ToastrModule.forRoot(),
+ SharedModule,
+ TooltipModule
+ ],
+ declarations: [RbdFormComponent, RbdConfigurationFormComponent],
+ providers: [
+ {
+ provide: ActivatedRoute,
+ useValue: new ActivatedRouteStub({ pool: 'foo', name: 'bar', snap: undefined })
+ },
+ i18nProviders,
+ RbdService
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdFormComponent);
+ component = fixture.componentInstance;
+ activatedRoute = TestBed.get(ActivatedRoute);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('create/edit/clone/copy image', () => {
+ let createAction;
+ let editAction;
+ let cloneAction;
+ let copyAction;
+ let rbdServiceGetSpy;
+
+ beforeEach(() => {
+ createAction = spyOn(component, 'createAction').and.stub();
+ editAction = spyOn(component, 'editAction').and.stub();
+ cloneAction = spyOn(component, 'cloneAction').and.stub();
+ copyAction = spyOn(component, 'copyAction').and.stub();
+ spyOn(component, 'setResponse').and.stub();
+ spyOn(TestBed.get(Router), 'navigate').and.stub();
+ rbdServiceGetSpy = spyOn(TestBed.get(RbdService), 'get');
+ rbdServiceGetSpy.and.returnValue(of({ pool_name: 'foo', pool_image: 'bar' }));
+ component.mode = undefined;
+ });
+
+ it('should create image', () => {
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(1);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+ });
+
+ it('should not edit image if no image data is received', fakeAsync(() => {
+ component.mode = RbdFormMode.editing;
+ rbdServiceGetSpy.and.returnValue(
+ of({ pool_name: 'foo', pool_image: 'bar' }).pipe(delay(100))
+ );
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+
+ discardPeriodicTasks();
+ }));
+
+ it('should edit image after image data is received', () => {
+ component.mode = RbdFormMode.editing;
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(1);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+ });
+
+ it('should not clone image if no image data is received', fakeAsync(() => {
+ component.mode = RbdFormMode.cloning;
+ rbdServiceGetSpy.and.returnValue(
+ of({ pool_name: 'foo', pool_image: 'bar' }).pipe(delay(100))
+ );
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+
+ discardPeriodicTasks();
+ }));
+
+ it('should clone image after image data is received', () => {
+ component.mode = RbdFormMode.cloning;
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(1);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+ });
+
+ it('should not copy image if no image data is received', fakeAsync(() => {
+ component.mode = RbdFormMode.copying;
+ rbdServiceGetSpy.and.returnValue(
+ of({ pool_name: 'foo', pool_image: 'bar' }).pipe(delay(100))
+ );
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(0);
+
+ discardPeriodicTasks();
+ }));
+
+ it('should copy image after image data is received', () => {
+ component.mode = RbdFormMode.copying;
+ component.ngOnInit();
+ component.submit();
+
+ expect(createAction).toHaveBeenCalledTimes(0);
+ expect(editAction).toHaveBeenCalledTimes(0);
+ expect(cloneAction).toHaveBeenCalledTimes(0);
+ expect(copyAction).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('should test decodeURIComponent of params', () => {
+ let rbdService: RbdService;
+
+ beforeEach(() => {
+ rbdService = TestBed.get(RbdService);
+ component.mode = RbdFormMode.editing;
+ fixture.detectChanges();
+ spyOn(rbdService, 'get').and.callThrough();
+ });
+
+ it('without snapName', () => {
+ activatedRoute.setParams({ pool: 'foo%2Ffoo', name: 'bar%2Fbar', snap: undefined });
+
+ expect(rbdService.get).toHaveBeenCalledWith('foo/foo', 'bar/bar');
+ expect(component.snapName).toBeUndefined();
+ });
+
+ it('with snapName', () => {
+ activatedRoute.setParams({ pool: 'foo%2Ffoo', name: 'bar%2Fbar', snap: 'baz%2Fbaz' });
+
+ expect(rbdService.get).toHaveBeenCalledWith('foo/foo', 'bar/bar');
+ expect(component.snapName).toBe('baz/baz');
+ });
+ });
+
+ describe('test image configuration component', () => {
+ it('is visible', () => {
+ fixture.detectChanges();
+ expect(queryNativeElement('cd-rbd-configuration-form').parentElement.hidden).toBe(false);
+ });
+ });
+
+ describe('tests for feature flags', () => {
+ let deepFlatten, layering, exclusiveLock, objectMap, journaling, fastDiff;
+ const defaultFeatures = [
+ // Supposed to be enabled by default
+ 'deep-flatten',
+ 'exclusive-lock',
+ 'fast-diff',
+ 'layering',
+ 'object-map'
+ ];
+ const allFeatureNames = [
+ 'deep-flatten',
+ 'layering',
+ 'exclusive-lock',
+ 'object-map',
+ 'journaling',
+ 'fast-diff'
+ ];
+ const setFeatures = (features) => {
+ component.features = features;
+ component.featuresList = component.objToArray(features);
+ component.createForm();
+ };
+ const getFeatureNativeElements = () => allFeatureNames.map((f) => queryNativeElement(`#${f}`));
+
+ it('should convert feature flags correctly in the constructor', () => {
+ setFeatures({
+ one: { desc: 'one', allowEnable: true, allowDisable: true },
+ two: { desc: 'two', allowEnable: true, allowDisable: true },
+ three: { desc: 'three', allowEnable: true, allowDisable: true }
+ });
+ expect(component.featuresList).toEqual([
+ { desc: 'one', key: 'one', allowDisable: true, allowEnable: true },
+ { desc: 'two', key: 'two', allowDisable: true, allowEnable: true },
+ { desc: 'three', key: 'three', allowDisable: true, allowEnable: true }
+ ]);
+ });
+
+ describe('test edit form flags', () => {
+ const prepare = (pool: string, image: string, enabledFeatures: string[]): void => {
+ const rbdService = TestBed.get(RbdService);
+ spyOn(rbdService, 'get').and.returnValue(
+ of({
+ name: image,
+ pool_name: pool,
+ features_name: enabledFeatures
+ })
+ );
+ spyOn(rbdService, 'defaultFeatures').and.returnValue(of(defaultFeatures));
+ component.router = { url: `/block/rbd/edit/${pool}/${image}` } as Router;
+ fixture.detectChanges();
+ [
+ deepFlatten,
+ layering,
+ exclusiveLock,
+ objectMap,
+ journaling,
+ fastDiff
+ ] = getFeatureNativeElements();
+ };
+
+ it('should have the interlock feature for flags disabled, if one feature is not set', () => {
+ prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+ expect(objectMap.disabled).toBe(false);
+ expect(fastDiff.disabled).toBe(false);
+
+ expect(objectMap.checked).toBe(true);
+ expect(fastDiff.checked).toBe(false);
+
+ fastDiff.click();
+ fastDiff.click();
+
+ expect(objectMap.checked).toBe(true); // Shall not be disabled by `fast-diff`!
+ });
+
+ it('should not disable object-map when fast-diff is unchecked', () => {
+ prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+ fastDiff.click();
+ fastDiff.click();
+
+ expect(objectMap.checked).toBe(true); // Shall not be disabled by `fast-diff`!
+ });
+
+ it('should not enable fast-diff when object-map is checked', () => {
+ prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+ objectMap.click();
+ objectMap.click();
+
+ expect(fastDiff.checked).toBe(false); // Shall not be disabled by `fast-diff`!
+ });
+ });
+
+ describe('test create form flags', () => {
+ beforeEach(() => {
+ const rbdService = TestBed.get(RbdService);
+ spyOn(rbdService, 'defaultFeatures').and.returnValue(of(defaultFeatures));
+ component.router = { url: '/block/rbd/create' } as Router;
+ fixture.detectChanges();
+ [
+ deepFlatten,
+ layering,
+ exclusiveLock,
+ objectMap,
+ journaling,
+ fastDiff
+ ] = getFeatureNativeElements();
+ });
+
+ it('should initialize the checkboxes correctly', () => {
+ expect(deepFlatten.disabled).toBe(false);
+ expect(layering.disabled).toBe(false);
+ expect(exclusiveLock.disabled).toBe(false);
+ expect(objectMap.disabled).toBe(false);
+ expect(journaling.disabled).toBe(false);
+ expect(fastDiff.disabled).toBe(false);
+
+ expect(deepFlatten.checked).toBe(true);
+ expect(layering.checked).toBe(true);
+ expect(exclusiveLock.checked).toBe(true);
+ expect(objectMap.checked).toBe(true);
+ expect(journaling.checked).toBe(false);
+ expect(fastDiff.checked).toBe(true);
+ });
+
+ it('should disable features if their requirements are not met (exclusive-lock)', () => {
+ exclusiveLock.click(); // unchecks exclusive-lock
+ expect(objectMap.disabled).toBe(true);
+ expect(journaling.disabled).toBe(true);
+ expect(fastDiff.disabled).toBe(true);
+ });
+
+ it('should disable features if their requirements are not met (object-map)', () => {
+ objectMap.click(); // unchecks object-map
+ expect(fastDiff.disabled).toBe(true);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts
new file mode 100644
index 00000000..ecd158cb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts
@@ -0,0 +1,678 @@
+import { Component, EventEmitter, OnInit } from '@angular/core';
+import { FormControl, ValidatorFn, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { AsyncSubject, Observable } from 'rxjs';
+import { switchMap } from 'rxjs/operators';
+
+import { PoolService } from '../../../shared/api/pool.service';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import {
+ RbdConfigurationEntry,
+ RbdConfigurationSourceField
+} from '../../../shared/models/configuration';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { RBDImageFormat, RbdModel } from '../rbd-list/rbd-model';
+import { RbdImageFeature } from './rbd-feature.interface';
+import { RbdFormCloneRequestModel } from './rbd-form-clone-request.model';
+import { RbdFormCopyRequestModel } from './rbd-form-copy-request.model';
+import { RbdFormCreateRequestModel } from './rbd-form-create-request.model';
+import { RbdFormEditRequestModel } from './rbd-form-edit-request.model';
+import { RbdFormMode } from './rbd-form-mode.enum';
+import { RbdFormResponseModel } from './rbd-form-response.model';
+
+@Component({
+ selector: 'cd-rbd-form',
+ templateUrl: './rbd-form.component.html',
+ styleUrls: ['./rbd-form.component.scss']
+})
+export class RbdFormComponent implements OnInit {
+ poolPermission: Permission;
+ rbdForm: CdFormGroup;
+ getDirtyConfigurationValues: (
+ includeLocalField?: boolean,
+ localField?: RbdConfigurationSourceField
+ ) => RbdConfigurationEntry[];
+
+ pools: Array<string> = null;
+ allPools: Array<string> = null;
+ dataPools: Array<string> = null;
+ allDataPools: Array<string> = null;
+ features: { [key: string]: RbdImageFeature };
+ featuresList: RbdImageFeature[] = [];
+ initializeConfigData = new EventEmitter<{
+ initialData: RbdConfigurationEntry[];
+ sourceType: RbdConfigurationSourceField;
+ }>();
+
+ pool: string;
+
+ advancedEnabled = false;
+
+ public rbdFormMode = RbdFormMode;
+ mode: RbdFormMode;
+
+ response: RbdFormResponseModel;
+ snapName: string;
+
+ defaultObjectSize = '4 MiB';
+
+ objectSizes: Array<string> = [
+ '4 KiB',
+ '8 KiB',
+ '16 KiB',
+ '32 KiB',
+ '64 KiB',
+ '128 KiB',
+ '256 KiB',
+ '512 KiB',
+ '1 MiB',
+ '2 MiB',
+ '4 MiB',
+ '8 MiB',
+ '16 MiB',
+ '32 MiB'
+ ];
+ action: string;
+ resource: string;
+ private rbdImage = new AsyncSubject();
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private route: ActivatedRoute,
+ private poolService: PoolService,
+ private rbdService: RbdService,
+ private formatter: FormatterService,
+ private taskWrapper: TaskWrapperService,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n,
+ public router: Router
+ ) {
+ this.poolPermission = this.authStorageService.getPermissions().pool;
+ this.resource = this.i18n('RBD');
+ this.features = {
+ 'deep-flatten': {
+ desc: this.i18n('Deep flatten'),
+ requires: null,
+ allowEnable: false,
+ allowDisable: true
+ },
+ layering: {
+ desc: this.i18n('Layering'),
+ requires: null,
+ allowEnable: false,
+ allowDisable: false
+ },
+ 'exclusive-lock': {
+ desc: this.i18n('Exclusive lock'),
+ requires: null,
+ allowEnable: true,
+ allowDisable: true
+ },
+ 'object-map': {
+ desc: this.i18n('Object map (requires exclusive-lock)'),
+ requires: 'exclusive-lock',
+ allowEnable: true,
+ allowDisable: true,
+ initDisabled: true
+ },
+ journaling: {
+ desc: this.i18n('Journaling (requires exclusive-lock)'),
+ requires: 'exclusive-lock',
+ allowEnable: true,
+ allowDisable: true,
+ initDisabled: true
+ },
+ 'fast-diff': {
+ desc: this.i18n('Fast diff (interlocked with object-map)'),
+ requires: 'object-map',
+ allowEnable: true,
+ allowDisable: true,
+ interlockedWith: 'object-map',
+ initDisabled: true
+ }
+ };
+ this.featuresList = this.objToArray(this.features);
+ this.createForm();
+ }
+
+ objToArray(obj: { [key: string]: any }) {
+ return _.map(obj, (o, key) => Object.assign(o, { key: key }));
+ }
+
+ createForm() {
+ this.rbdForm = new CdFormGroup(
+ {
+ parent: new FormControl(''),
+ name: new FormControl('', {
+ validators: [Validators.required, Validators.pattern(/^[^@/]+?$/)]
+ }),
+ pool: new FormControl(null, {
+ validators: [Validators.required]
+ }),
+ useDataPool: new FormControl(false),
+ dataPool: new FormControl(null),
+ size: new FormControl(null, {
+ updateOn: 'blur'
+ }),
+ obj_size: new FormControl(this.defaultObjectSize),
+ features: new CdFormGroup(
+ this.featuresList.reduce((acc, e) => {
+ acc[e.key] = new FormControl({ value: false, disabled: !!e.initDisabled });
+ return acc;
+ }, {})
+ ),
+ stripingUnit: new FormControl(null),
+ stripingCount: new FormControl(null, {
+ updateOn: 'blur'
+ })
+ },
+ this.validateRbdForm(this.formatter)
+ );
+ }
+
+ disableForEdit() {
+ this.rbdForm.get('parent').disable();
+ this.rbdForm.get('pool').disable();
+ this.rbdForm.get('useDataPool').disable();
+ this.rbdForm.get('dataPool').disable();
+ this.rbdForm.get('obj_size').disable();
+ this.rbdForm.get('stripingUnit').disable();
+ this.rbdForm.get('stripingCount').disable();
+
+ /* RBD Image Format v1 */
+ this.rbdImage.subscribe((image: RbdModel) => {
+ if (image.image_format === RBDImageFormat.V1) {
+ this.rbdForm.get('deep-flatten').disable();
+ this.rbdForm.get('layering').disable();
+ this.rbdForm.get('exclusive-lock').disable();
+ }
+ });
+ }
+
+ disableForClone() {
+ this.rbdForm.get('parent').disable();
+ this.rbdForm.get('size').disable();
+ }
+
+ disableForCopy() {
+ this.rbdForm.get('parent').disable();
+ this.rbdForm.get('size').disable();
+ }
+
+ ngOnInit() {
+ if (this.router.url.startsWith('/block/rbd/edit')) {
+ this.mode = this.rbdFormMode.editing;
+ this.action = this.actionLabels.EDIT;
+ this.disableForEdit();
+ } else if (this.router.url.startsWith('/block/rbd/clone')) {
+ this.mode = this.rbdFormMode.cloning;
+ this.disableForClone();
+ this.action = this.actionLabels.CLONE;
+ } else if (this.router.url.startsWith('/block/rbd/copy')) {
+ this.mode = this.rbdFormMode.copying;
+ this.action = this.actionLabels.COPY;
+ this.disableForCopy();
+ } else {
+ this.action = this.actionLabels.CREATE;
+ }
+ if (
+ this.mode === this.rbdFormMode.editing ||
+ this.mode === this.rbdFormMode.cloning ||
+ this.mode === this.rbdFormMode.copying
+ ) {
+ this.route.params.subscribe((params: { pool: string; name: string; snap: string }) => {
+ const poolName = decodeURIComponent(params.pool);
+ const rbdName = decodeURIComponent(params.name);
+ if (params.snap) {
+ this.snapName = decodeURIComponent(params.snap);
+ }
+ this.rbdService.get(poolName, rbdName).subscribe((resp: RbdFormResponseModel) => {
+ this.setResponse(resp, this.snapName);
+ this.rbdImage.next(resp);
+ });
+ });
+ } else {
+ // New image
+ this.rbdService.defaultFeatures().subscribe((defaultFeatures: Array<string>) => {
+ this.setFeatures(defaultFeatures);
+ });
+ }
+ if (this.mode !== this.rbdFormMode.editing && this.poolPermission.read) {
+ this.poolService
+ .list(['pool_name', 'type', 'flags_names', 'application_metadata'])
+ .then((resp) => {
+ const pools = [];
+ const dataPools = [];
+ for (const pool of resp) {
+ if (_.indexOf(pool.application_metadata, 'rbd') !== -1) {
+ if (!pool.pool_name.includes('/')) {
+ if (pool.type === 'replicated') {
+ pools.push(pool);
+ dataPools.push(pool);
+ } else if (
+ pool.type === 'erasure' &&
+ pool.flags_names.indexOf('ec_overwrites') !== -1
+ ) {
+ dataPools.push(pool);
+ }
+ }
+ }
+ }
+ this.pools = pools;
+ this.allPools = pools;
+ this.dataPools = dataPools;
+ this.allDataPools = dataPools;
+ if (this.pools.length === 1) {
+ const poolName = this.pools[0]['pool_name'];
+ this.rbdForm.get('pool').setValue(poolName);
+ this.onPoolChange(poolName);
+ }
+ });
+ }
+ _.each(this.features, (feature) => {
+ this.rbdForm
+ .get('features')
+ .get(feature.key)
+ .valueChanges.subscribe((value) => this.featureFormUpdate(feature.key, value));
+ });
+ }
+
+ onPoolChange(selectedPoolName) {
+ const newDataPools = this.allDataPools.filter((dataPool: any) => {
+ return dataPool.pool_name !== selectedPoolName;
+ });
+ if (this.rbdForm.getValue('dataPool') === selectedPoolName) {
+ this.rbdForm.get('dataPool').setValue(null);
+ }
+ this.dataPools = newDataPools;
+ }
+
+ onUseDataPoolChange() {
+ if (!this.rbdForm.getValue('useDataPool')) {
+ this.rbdForm.get('dataPool').setValue(null);
+ this.onDataPoolChange(null);
+ }
+ }
+
+ onDataPoolChange(selectedDataPoolName) {
+ const newPools = this.allPools.filter((pool: any) => {
+ return pool.pool_name !== selectedDataPoolName;
+ });
+ if (this.rbdForm.getValue('pool') === selectedDataPoolName) {
+ this.rbdForm.get('pool').setValue(null);
+ }
+ this.pools = newPools;
+ }
+
+ validateRbdForm(formatter: FormatterService): ValidatorFn {
+ return (formGroup: CdFormGroup) => {
+ // Data Pool
+ const useDataPoolControl = formGroup.get('useDataPool');
+ const dataPoolControl = formGroup.get('dataPool');
+ let dataPoolControlErrors = null;
+ if (useDataPoolControl.value && dataPoolControl.value == null) {
+ dataPoolControlErrors = { required: true };
+ }
+ dataPoolControl.setErrors(dataPoolControlErrors);
+ // Size
+ const sizeControl = formGroup.get('size');
+ const objectSizeControl = formGroup.get('obj_size');
+ const objectSizeInBytes = formatter.toBytes(
+ objectSizeControl.value != null ? objectSizeControl.value : this.defaultObjectSize
+ );
+ const stripingCountControl = formGroup.get('stripingCount');
+ const stripingCount = stripingCountControl.value != null ? stripingCountControl.value : 1;
+ let sizeControlErrors = null;
+ if (sizeControl.value === null) {
+ sizeControlErrors = { required: true };
+ } else {
+ const sizeInBytes = formatter.toBytes(sizeControl.value);
+ if (stripingCount * objectSizeInBytes > sizeInBytes) {
+ sizeControlErrors = { invalidSizeObject: true };
+ }
+ }
+ sizeControl.setErrors(sizeControlErrors);
+ // Striping Unit
+ const stripingUnitControl = formGroup.get('stripingUnit');
+ let stripingUnitControlErrors = null;
+ if (stripingUnitControl.value === null && stripingCountControl.value !== null) {
+ stripingUnitControlErrors = { required: true };
+ } else if (stripingUnitControl.value !== null) {
+ const stripingUnitInBytes = formatter.toBytes(stripingUnitControl.value);
+ if (stripingUnitInBytes > objectSizeInBytes) {
+ stripingUnitControlErrors = { invalidStripingUnit: true };
+ }
+ }
+ stripingUnitControl.setErrors(stripingUnitControlErrors);
+ // Striping Count
+ let stripingCountControlErrors = null;
+ if (stripingCountControl.value === null && stripingUnitControl.value !== null) {
+ stripingCountControlErrors = { required: true };
+ } else if (stripingCount < 1) {
+ stripingCountControlErrors = { min: true };
+ }
+ stripingCountControl.setErrors(stripingCountControlErrors);
+ return null;
+ };
+ }
+
+ protected getDependendChildFeatures(featureKey: string) {
+ return _.filter(this.features, (f) => f.requires === featureKey) || [];
+ }
+
+ deepBoxCheck(key, checked) {
+ const childFeatures = this.getDependendChildFeatures(key);
+ childFeatures.forEach((feature) => {
+ const featureControl = this.rbdForm.get(feature.key);
+ if (checked) {
+ featureControl.enable({ emitEvent: false });
+ } else {
+ featureControl.disable({ emitEvent: false });
+ featureControl.setValue(false, { emitEvent: false });
+ this.deepBoxCheck(feature.key, checked);
+ }
+
+ const featureFormGroup = this.rbdForm.get('features');
+ if (this.mode === this.rbdFormMode.editing && featureFormGroup.get(feature.key).enabled) {
+ if (this.response.features_name.indexOf(feature.key) !== -1 && !feature.allowDisable) {
+ featureFormGroup.get(feature.key).disable();
+ } else if (
+ this.response.features_name.indexOf(feature.key) === -1 &&
+ !feature.allowEnable
+ ) {
+ featureFormGroup.get(feature.key).disable();
+ }
+ }
+ });
+ }
+
+ interlockCheck(key, checked) {
+ // Adds a compatibility layer for Ceph cluster where the feature interlock of features hasn't
+ // been implemented yet. It disables the feature interlock for images which only have one of
+ // both interlocked features (at the time of this writing: object-map and fast-diff) enabled.
+ const feature = this.featuresList.find((f) => f.key === key);
+ if (this.response) {
+ // Ignore `create` page
+ const hasInterlockedFeature = feature.interlockedWith != null;
+ const dependentInterlockedFeature = this.featuresList.find(
+ (f) => f.interlockedWith === feature.key
+ );
+ const isOriginFeatureEnabled = !!this.response.features_name.find((e) => e === feature.key); // in this case: fast-diff
+ if (hasInterlockedFeature) {
+ const isLinkedEnabled = !!this.response.features_name.find(
+ (e) => e === feature.interlockedWith
+ ); // depends: object-map
+ if (isOriginFeatureEnabled !== isLinkedEnabled) {
+ return; // Ignore incompatible setting because it's from a previous cluster version
+ }
+ } else if (dependentInterlockedFeature) {
+ const isOtherInterlockedFeatureEnabled = !!this.response.features_name.find(
+ (e) => e === dependentInterlockedFeature.key
+ );
+ if (isOtherInterlockedFeatureEnabled !== isOriginFeatureEnabled) {
+ return; // Ignore incompatible setting because it's from a previous cluster version
+ }
+ }
+ }
+
+ if (checked) {
+ _.filter(this.features, (f) => f.interlockedWith === key).forEach((f) =>
+ this.rbdForm.get(f.key).setValue(true, { emitEvent: false })
+ );
+ } else {
+ if (feature.interlockedWith) {
+ // Don't skip emitting the event here, as it prevents `fast-diff` from
+ // becoming disabled when manually unchecked. This is because it
+ // triggers an update on `object-map` and if `object-map` doesn't emit,
+ // `fast-diff` will not be automatically disabled.
+ this.rbdForm
+ .get('features')
+ .get(feature.interlockedWith)
+ .setValue(false);
+ }
+ }
+ }
+
+ featureFormUpdate(key, checked) {
+ if (checked) {
+ const required = this.features[key].requires;
+ if (required && !this.rbdForm.getValue(required)) {
+ this.rbdForm.get(`features.${key}`).setValue(false);
+ return;
+ }
+ }
+ this.deepBoxCheck(key, checked);
+ this.interlockCheck(key, checked);
+ }
+
+ setFeatures(features: Array<string>) {
+ const featuresControl = this.rbdForm.get('features');
+ _.forIn(this.features, (feature) => {
+ if (features.indexOf(feature.key) !== -1) {
+ featuresControl.get(feature.key).setValue(true);
+ }
+ this.featureFormUpdate(feature.key, featuresControl.get(feature.key).value);
+ });
+ }
+
+ setResponse(response: RbdFormResponseModel, snapName: string) {
+ this.response = response;
+ if (this.mode === this.rbdFormMode.cloning) {
+ this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}@${snapName}`);
+ } else if (this.mode === this.rbdFormMode.copying) {
+ if (snapName) {
+ this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}@${snapName}`);
+ } else {
+ this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}`);
+ }
+ } else if (response.parent) {
+ const parent = response.parent;
+ this.rbdForm
+ .get('parent')
+ .setValue(`${parent.pool_name}/${parent.image_name}@${parent.snap_name}`);
+ }
+ if (this.mode === this.rbdFormMode.editing) {
+ this.rbdForm.get('name').setValue(response.name);
+ }
+ this.rbdForm.get('pool').setValue(response.pool_name);
+ if (response.data_pool) {
+ this.rbdForm.get('useDataPool').setValue(true);
+ this.rbdForm.get('dataPool').setValue(response.data_pool);
+ }
+ this.rbdForm.get('size').setValue(this.dimlessBinaryPipe.transform(response.size));
+ this.rbdForm.get('obj_size').setValue(this.dimlessBinaryPipe.transform(response.obj_size));
+ this.setFeatures(response.features_name);
+ this.rbdForm
+ .get('stripingUnit')
+ .setValue(this.dimlessBinaryPipe.transform(response.stripe_unit));
+ this.rbdForm.get('stripingCount').setValue(response.stripe_count);
+
+ /* Configuration */
+ this.initializeConfigData.emit({
+ initialData: this.response.configuration,
+ sourceType: RbdConfigurationSourceField.image
+ });
+ }
+
+ createRequest() {
+ const request = new RbdFormCreateRequestModel();
+ request.pool_name = this.rbdForm.getValue('pool');
+ request.name = this.rbdForm.getValue('name');
+ request.size = this.formatter.toBytes(this.rbdForm.getValue('size'));
+ request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size'));
+ _.forIn(this.features, (feature) => {
+ if (this.rbdForm.getValue(feature.key)) {
+ request.features.push(feature.key);
+ }
+ });
+
+ /* Striping */
+ request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit'));
+ request.stripe_count = this.rbdForm.getValue('stripingCount');
+ request.data_pool = this.rbdForm.getValue('dataPool');
+
+ /* Configuration */
+ request.configuration = this.getDirtyConfigurationValues();
+
+ return request;
+ }
+
+ createAction(): Observable<any> {
+ const request = this.createRequest();
+ return this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/create', {
+ pool_name: request.pool_name,
+ image_name: request.name
+ }),
+ call: this.rbdService.create(request)
+ });
+ }
+
+ editRequest() {
+ const request = new RbdFormEditRequestModel();
+ request.name = this.rbdForm.getValue('name');
+ request.size = this.formatter.toBytes(this.rbdForm.getValue('size'));
+ _.forIn(this.features, (feature) => {
+ if (this.rbdForm.getValue(feature.key)) {
+ request.features.push(feature.key);
+ }
+ });
+
+ request.configuration = this.getDirtyConfigurationValues();
+
+ return request;
+ }
+
+ cloneRequest(): RbdFormCloneRequestModel {
+ const request = new RbdFormCloneRequestModel();
+ request.child_pool_name = this.rbdForm.getValue('pool');
+ request.child_image_name = this.rbdForm.getValue('name');
+ request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size'));
+ _.forIn(this.features, (feature) => {
+ if (this.rbdForm.getValue(feature.key)) {
+ request.features.push(feature.key);
+ }
+ });
+
+ /* Striping */
+ request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit'));
+ request.stripe_count = this.rbdForm.getValue('stripingCount');
+ request.data_pool = this.rbdForm.getValue('dataPool');
+
+ /* Configuration */
+ request.configuration = this.getDirtyConfigurationValues(
+ true,
+ RbdConfigurationSourceField.image
+ );
+
+ return request;
+ }
+
+ editAction(): Observable<any> {
+ return this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/edit', {
+ pool_name: this.response.pool_name,
+ image_name: this.response.name
+ }),
+ call: this.rbdService.update(this.response.pool_name, this.response.name, this.editRequest())
+ });
+ }
+
+ cloneAction(): Observable<any> {
+ const request = this.cloneRequest();
+ return this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/clone', {
+ parent_pool_name: this.response.pool_name,
+ parent_image_name: this.response.name,
+ parent_snap_name: this.snapName,
+ child_pool_name: request.child_pool_name,
+ child_image_name: request.child_image_name
+ }),
+ call: this.rbdService.cloneSnapshot(
+ this.response.pool_name,
+ this.response.name,
+ this.snapName,
+ request
+ )
+ });
+ }
+
+ copyRequest(): RbdFormCopyRequestModel {
+ const request = new RbdFormCopyRequestModel();
+ if (this.snapName) {
+ request.snapshot_name = this.snapName;
+ }
+ request.dest_pool_name = this.rbdForm.getValue('pool');
+ request.dest_image_name = this.rbdForm.getValue('name');
+ request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size'));
+ _.forIn(this.features, (feature) => {
+ if (this.rbdForm.getValue(feature.key)) {
+ request.features.push(feature.key);
+ }
+ });
+
+ /* Striping */
+ request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit'));
+ request.stripe_count = this.rbdForm.getValue('stripingCount');
+ request.data_pool = this.rbdForm.getValue('dataPool');
+
+ /* Configuration */
+ request.configuration = this.getDirtyConfigurationValues(
+ true,
+ RbdConfigurationSourceField.image
+ );
+
+ return request;
+ }
+
+ copyAction(): Observable<any> {
+ const request = this.copyRequest();
+
+ return this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/copy', {
+ src_pool_name: this.response.pool_name,
+ src_image_name: this.response.name,
+ dest_pool_name: request.dest_pool_name,
+ dest_image_name: request.dest_image_name
+ }),
+ call: this.rbdService.copy(this.response.pool_name, this.response.name, request)
+ });
+ }
+
+ submit() {
+ if (!this.mode) {
+ this.rbdImage.next('create');
+ }
+ this.rbdImage.complete();
+ this.rbdImage
+ .pipe(
+ switchMap(() => {
+ if (this.mode === this.rbdFormMode.editing) {
+ return this.editAction();
+ } else if (this.mode === this.rbdFormMode.cloning) {
+ return this.cloneAction();
+ } else if (this.mode === this.rbdFormMode.copying) {
+ return this.copyAction();
+ } else {
+ return this.createAction();
+ }
+ })
+ )
+ .subscribe(
+ () => {},
+ () => this.rbdForm.setErrors({ cdSubmitButton: true }),
+ () => this.router.navigate(['/block/rbd'])
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.model.ts
new file mode 100644
index 00000000..9511a00d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.model.ts
@@ -0,0 +1,16 @@
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+
+export class RbdFormModel {
+ name: string;
+ pool_name: string;
+ data_pool: string;
+ size: number;
+
+ /* Striping */
+ obj_size: number;
+ stripe_unit: number;
+ stripe_count: number;
+
+ /* Configuration */
+ configuration: RbdConfigurationEntry[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-parent.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-parent.model.ts
new file mode 100644
index 00000000..a10f8a37
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-parent.model.ts
@@ -0,0 +1,5 @@
+export class RbdParentModel {
+ image_name: string;
+ pool_name: string;
+ snap_name: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html
new file mode 100644
index 00000000..0827a61d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html
@@ -0,0 +1,21 @@
+<div>
+ <tabset>
+ <tab heading="Images"
+ i18n-heading
+ id="tab1">
+ <cd-rbd-list></cd-rbd-list>
+ </tab>
+ <tab heading="Trash"
+ i18n-heading>
+ <cd-rbd-trash-list></cd-rbd-trash-list>
+ </tab>
+ <tab heading="Overall Performance"
+ *ngIf="grafanaPermission.read"
+ i18n-heading>
+ <cd-grafana [grafanaPath]="'rbd-overview?'"
+ uid="41FrpeUiz"
+ grafanaStyle="two">
+ </cd-grafana>
+ </tab>
+ </tabset>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts
new file mode 100644
index 00000000..e1fda888
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts
@@ -0,0 +1,52 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationListComponent } from '../rbd-configuration-list/rbd-configuration-list.component';
+import { RbdDetailsComponent } from '../rbd-details/rbd-details.component';
+import { RbdListComponent } from '../rbd-list/rbd-list.component';
+import { RbdSnapshotListComponent } from '../rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdTrashListComponent } from '../rbd-trash-list/rbd-trash-list.component';
+import { RbdImagesComponent } from './rbd-images.component';
+
+describe('RbdImagesComponent', () => {
+ let component: RbdImagesComponent;
+ let fixture: ComponentFixture<RbdImagesComponent>;
+
+ configureTestBed({
+ declarations: [
+ RbdDetailsComponent,
+ RbdImagesComponent,
+ RbdListComponent,
+ RbdSnapshotListComponent,
+ RbdTrashListComponent,
+ RbdConfigurationListComponent
+ ],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule,
+ SharedModule,
+ TabsModule.forRoot(),
+ ToastrModule.forRoot(),
+ TooltipModule.forRoot()
+ ],
+ providers: [TaskListService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdImagesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts
new file mode 100644
index 00000000..bf99a771
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts
@@ -0,0 +1,19 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-rbd-images',
+ templateUrl: './rbd-images.component.html',
+ styleUrls: ['./rbd-images.component.scss']
+})
+export class RbdImagesComponent implements OnInit {
+ grafanaPermission: Permission;
+
+ constructor(private authStorageService: AuthStorageService) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ }
+
+ ngOnInit() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html
new file mode 100644
index 00000000..4dd424e2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html
@@ -0,0 +1,43 @@
+<cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
+ [status]="viewCacheStatus.status"
+ [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
+
+<cd-table #table
+ [data]="images"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="unique_id"
+ [searchableObjects]="true"
+ forceIdentifier="true"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-rbd-details cdTableDetail
+ [selection]="selection">
+ </cd-rbd-details>
+</cd-table>
+
+<ng-template #usageNotAvailableTooltipTpl>
+ <div i18n
+ [innerHtml]="'Only available for RBD images with <strong>fast-diff</strong> enabled'"></div>
+</ng-template>
+
+<ng-template #parentTpl
+ let-value="value">
+ <span *ngIf="value">{{ value.pool_name }}/{{ value.image_name }}@{{ value.snap_name }}</span>
+ <span *ngIf="!value">-</span>
+</ng-template>
+
+<ng-template #flattenTpl
+ let-value>
+ You are about to flatten
+ <strong>{{ value.child }}</strong>.
+ <br>
+ <br> All blocks will be copied from parent
+ <strong>{{ value.parent }}</strong> to child
+ <strong>{{ value.child }}</strong>.
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts
new file mode 100644
index 00000000..4b80c3b9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts
@@ -0,0 +1,367 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+import { ToastrModule } from 'ngx-toastr';
+import { BehaviorSubject, of } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ActionLabels } from '../../../shared/constants/app.constants';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationListComponent } from '../rbd-configuration-list/rbd-configuration-list.component';
+import { RbdDetailsComponent } from '../rbd-details/rbd-details.component';
+import { RbdSnapshotListComponent } from '../rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdListComponent } from './rbd-list.component';
+import { RbdModel } from './rbd-model';
+
+describe('RbdListComponent', () => {
+ let fixture: ComponentFixture<RbdListComponent>;
+ let component: RbdListComponent;
+ let summaryService: SummaryService;
+ let rbdService: RbdService;
+
+ const refresh = (data) => {
+ summaryService['summaryDataSource'].next(data);
+ };
+
+ configureTestBed({
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ModalModule.forRoot(),
+ TooltipModule.forRoot(),
+ ToastrModule.forRoot(),
+ AlertModule.forRoot(),
+ RouterTestingModule,
+ HttpClientTestingModule
+ ],
+ declarations: [
+ RbdListComponent,
+ RbdDetailsComponent,
+ RbdSnapshotListComponent,
+ RbdConfigurationListComponent
+ ],
+ providers: [TaskListService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdListComponent);
+ component = fixture.componentInstance;
+ summaryService = TestBed.get(SummaryService);
+ rbdService = TestBed.get(RbdService);
+
+ // this is needed because summaryService isn't being reset after each test.
+ summaryService['summaryDataSource'] = new BehaviorSubject(null);
+ summaryService['summaryData$'] = summaryService['summaryDataSource'].asObservable();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('after ngOnInit', () => {
+ beforeEach(() => {
+ fixture.detectChanges();
+ spyOn(rbdService, 'list').and.callThrough();
+ });
+
+ it('should load images on init', () => {
+ refresh({});
+ expect(rbdService.list).toHaveBeenCalled();
+ });
+
+ it('should not load images on init because no data', () => {
+ refresh(undefined);
+ expect(rbdService.list).not.toHaveBeenCalled();
+ });
+
+ it('should call error function on init when summary service fails', () => {
+ spyOn(component.table, 'reset');
+ summaryService['summaryDataSource'].error(undefined);
+ expect(component.table.reset).toHaveBeenCalled();
+ expect(component.viewCacheStatusList).toEqual([{ status: ViewCacheStatus.ValueException }]);
+ });
+ });
+
+ describe('handling of executing tasks', () => {
+ let images: RbdModel[];
+
+ const addImage = (name) => {
+ const model = new RbdModel();
+ model.id = '-1';
+ model.name = name;
+ model.pool_name = 'rbd';
+ images.push(model);
+ };
+
+ const addTask = (name: string, image_name: string) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ switch (task.name) {
+ case 'rbd/copy':
+ task.metadata = {
+ dest_pool_name: 'rbd',
+ dest_image_name: 'd'
+ };
+ break;
+ case 'rbd/clone':
+ task.metadata = {
+ child_pool_name: 'rbd',
+ child_image_name: 'd'
+ };
+ break;
+ default:
+ task.metadata = {
+ pool_name: 'rbd',
+ image_name: image_name
+ };
+ break;
+ }
+ summaryService.addRunningTask(task);
+ };
+
+ beforeEach(() => {
+ images = [];
+ addImage('a');
+ addImage('b');
+ addImage('c');
+ component.images = images;
+ refresh({ executing_tasks: [], finished_tasks: [] });
+ spyOn(rbdService, 'list').and.callFake(() =>
+ of([{ pool_name: 'rbd', status: 1, value: images }])
+ );
+ fixture.detectChanges();
+ });
+
+ it('should gets all images without tasks', () => {
+ expect(component.images.length).toBe(3);
+ expect(component.images.every((image) => !image.cdExecuting)).toBeTruthy();
+ });
+
+ it('should add a new image from a task', () => {
+ addTask('rbd/create', 'd');
+ expect(component.images.length).toBe(4);
+ expectItemTasks(component.images[0], undefined);
+ expectItemTasks(component.images[1], undefined);
+ expectItemTasks(component.images[2], undefined);
+ expectItemTasks(component.images[3], 'Creating');
+ });
+
+ it('should show when a image is being cloned', () => {
+ addTask('rbd/clone', 'd');
+ expect(component.images.length).toBe(4);
+ expectItemTasks(component.images[0], undefined);
+ expectItemTasks(component.images[1], undefined);
+ expectItemTasks(component.images[2], undefined);
+ expectItemTasks(component.images[3], 'Cloning');
+ });
+
+ it('should show when a image is being copied', () => {
+ addTask('rbd/copy', 'd');
+ expect(component.images.length).toBe(4);
+ expectItemTasks(component.images[0], undefined);
+ expectItemTasks(component.images[1], undefined);
+ expectItemTasks(component.images[2], undefined);
+ expectItemTasks(component.images[3], 'Copying');
+ });
+
+ it('should show when an existing image is being modified', () => {
+ addTask('rbd/edit', 'a');
+ addTask('rbd/delete', 'b');
+ addTask('rbd/flatten', 'c');
+ expect(component.images.length).toBe(3);
+ expectItemTasks(component.images[0], 'Updating');
+ expectItemTasks(component.images[1], 'Deleting');
+ expectItemTasks(component.images[2], 'Flattening');
+ });
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: ActionLabels.EDIT,
+ empty: ActionLabels.CREATE
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(6);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows all actions except for 'Delete' and 'Move'`, () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ component.tableActions.pop();
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Copy' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Copy';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Add', 'Copy', 'Delete' and 'Move' action`, () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2],
+ component.tableActions[4],
+ component.tableActions[5]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit', 'Flatten', 'Delete' and 'Move' action`, () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[3],
+ component.tableActions[4],
+ component.tableActions[5]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows 'Copy' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Copy';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Copy' and 'Add' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and edit', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Flatten' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[3]
+ ]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Delete' and 'Move' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[4],
+ component.tableActions[5]
+ ]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
new file mode 100644
index 00000000..59694191
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
@@ -0,0 +1,353 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+import { RbdParentModel } from '../rbd-form/rbd-parent.model';
+import { RbdTrashMoveModalComponent } from '../rbd-trash-move-modal/rbd-trash-move-modal.component';
+import { RBDImageFormat, RbdModel } from './rbd-model';
+
+const BASE_URL = 'block/rbd';
+
+@Component({
+ selector: 'cd-rbd-list',
+ templateUrl: './rbd-list.component.html',
+ styleUrls: ['./rbd-list.component.scss'],
+ providers: [
+ TaskListService,
+ { provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }
+ ]
+})
+export class RbdListComponent implements OnInit {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+ @ViewChild('usageTpl')
+ usageTpl: TemplateRef<any>;
+ @ViewChild('parentTpl')
+ parentTpl: TemplateRef<any>;
+ @ViewChild('nameTpl')
+ nameTpl: TemplateRef<any>;
+ @ViewChild('flattenTpl')
+ flattenTpl: TemplateRef<any>;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ images: any;
+ columns: CdTableColumn[];
+ retries: number;
+ viewCacheStatusList: any[];
+ selection = new CdTableSelection();
+
+ modalRef: BsModalRef;
+
+ builders = {
+ 'rbd/create': (metadata) =>
+ this.createRbdFromTask(metadata['pool_name'], metadata['image_name']),
+ 'rbd/clone': (metadata) =>
+ this.createRbdFromTask(metadata['child_pool_name'], metadata['child_image_name']),
+ 'rbd/copy': (metadata) =>
+ this.createRbdFromTask(metadata['dest_pool_name'], metadata['dest_image_name'])
+ };
+
+ private createRbdFromTask(pool: string, name: string): RbdModel {
+ const model = new RbdModel();
+ model.id = '-1';
+ model.unique_id = '-1';
+ model.name = name;
+ model.pool_name = pool;
+ model.image_format = RBDImageFormat.V2;
+ return model;
+ }
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private rbdService: RbdService,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private dimlessPipe: DimlessPipe,
+ private modalService: BsModalService,
+ private taskWrapper: TaskWrapperService,
+ private taskListService: TaskListService,
+ private i18n: I18n,
+ private urlBuilder: URLBuilderService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().rbdImage;
+ const getImageUri = () =>
+ this.selection.first() &&
+ `${encodeURIComponent(this.selection.first().pool_name)}/${encodeURIComponent(
+ this.selection.first().name
+ )}`;
+ const addAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
+ name: this.actionLabels.CREATE
+ };
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => this.urlBuilder.getEdit(getImageUri()),
+ name: this.actionLabels.EDIT
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteRbdModal(),
+ name: this.actionLabels.DELETE
+ };
+ const copyAction: CdTableAction = {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ icon: 'fa-copy',
+ routerLink: () => `/block/rbd/copy/${getImageUri()}`,
+ name: this.actionLabels.COPY
+ };
+ const flattenAction: CdTableAction = {
+ permission: 'update',
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting || !selection.first().parent,
+ icon: 'fa-chain-broken',
+ click: () => this.flattenRbdModal(),
+ name: this.actionLabels.FLATTEN
+ };
+ const moveAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-trash-o',
+ click: () => this.trashRbdModal(),
+ name: this.actionLabels.TRASH,
+ disable: (selection: CdTableSelection) =>
+ !selection.first() ||
+ !selection.hasSingleSelection ||
+ selection.first().image_format === RBDImageFormat.V1
+ };
+ this.tableActions = [
+ addAction,
+ editAction,
+ copyAction,
+ flattenAction,
+ deleteAction,
+ moveAction
+ ];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 2,
+ cellTransformation: CellTemplate.executing
+ },
+ {
+ name: this.i18n('Pool'),
+ prop: 'pool_name',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Size'),
+ prop: 'size',
+ flexGrow: 1,
+ cellClass: 'text-right',
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Objects'),
+ prop: 'num_objs',
+ flexGrow: 1,
+ cellClass: 'text-right',
+ pipe: this.dimlessPipe
+ },
+ {
+ name: this.i18n('Object size'),
+ prop: 'obj_size',
+ flexGrow: 1,
+ cellClass: 'text-right',
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Provisioned'),
+ prop: 'disk_usage',
+ cellClass: 'text-center',
+ flexGrow: 1,
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Total provisioned'),
+ prop: 'total_disk_usage',
+ cellClass: 'text-center',
+ flexGrow: 1,
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Parent'),
+ prop: 'parent',
+ flexGrow: 2,
+ cellTemplate: this.parentTpl
+ }
+ ];
+
+ this.taskListService.init(
+ () => this.rbdService.list(),
+ (resp) => this.prepareResponse(resp),
+ (images) => (this.images = images),
+ () => this.onFetchError(),
+ this.taskFilter,
+ this.itemFilter,
+ this.builders
+ );
+ }
+
+ onFetchError() {
+ this.table.reset(); // Disable loading indicator.
+ this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+ }
+
+ prepareResponse(resp: any[]): any[] {
+ let images = [];
+ const viewCacheStatusMap = {};
+ resp.forEach((pool) => {
+ if (_.isUndefined(viewCacheStatusMap[pool.status])) {
+ viewCacheStatusMap[pool.status] = [];
+ }
+ viewCacheStatusMap[pool.status].push(pool.pool_name);
+ images = images.concat(pool.value);
+ });
+ const viewCacheStatusList = [];
+ _.forEach(viewCacheStatusMap, (value: any, key) => {
+ viewCacheStatusList.push({
+ status: parseInt(key, 10),
+ statusFor:
+ (value.length > 1 ? 'pools ' : 'pool ') +
+ '<strong>' +
+ value.join('</strong>, <strong>') +
+ '</strong>'
+ });
+ });
+ this.viewCacheStatusList = viewCacheStatusList;
+ return images;
+ }
+
+ itemFilter(entry, task) {
+ let pool_name_k: string;
+ let image_name_k: string;
+ switch (task.name) {
+ case 'rbd/copy':
+ pool_name_k = 'dest_pool_name';
+ image_name_k = 'dest_image_name';
+ break;
+ case 'rbd/clone':
+ pool_name_k = 'child_pool_name';
+ image_name_k = 'child_image_name';
+ break;
+ default:
+ pool_name_k = 'pool_name';
+ image_name_k = 'image_name';
+ break;
+ }
+ return (
+ entry.pool_name === task.metadata[pool_name_k] && entry.name === task.metadata[image_name_k]
+ );
+ }
+
+ taskFilter(task) {
+ return [
+ 'rbd/clone',
+ 'rbd/copy',
+ 'rbd/create',
+ 'rbd/delete',
+ 'rbd/edit',
+ 'rbd/flatten',
+ 'rbd/trash/move'
+ ].includes(task.name);
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteRbdModal() {
+ const poolName = this.selection.first().pool_name;
+ const imageName = this.selection.first().name;
+
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: 'RBD',
+ itemNames: [`${poolName}/${imageName}`],
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/delete', {
+ pool_name: poolName,
+ image_name: imageName
+ }),
+ call: this.rbdService.delete(poolName, imageName)
+ })
+ }
+ });
+ }
+
+ trashRbdModal() {
+ const initialState = {
+ metaType: 'RBD',
+ poolName: this.selection.first().pool_name,
+ imageName: this.selection.first().name
+ };
+ this.modalRef = this.modalService.show(RbdTrashMoveModalComponent, { initialState });
+ }
+
+ flattenRbd(poolName, imageName) {
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('rbd/flatten', {
+ pool_name: poolName,
+ image_name: imageName
+ }),
+ call: this.rbdService.flatten(poolName, imageName)
+ })
+ .subscribe(undefined, undefined, () => {
+ this.modalRef.hide();
+ });
+ }
+
+ flattenRbdModal() {
+ const poolName = this.selection.first().pool_name;
+ const imageName = this.selection.first().name;
+ const parent: RbdParentModel = this.selection.first().parent;
+
+ const initialState = {
+ titleText: 'RBD flatten',
+ buttonText: 'Flatten',
+ bodyTpl: this.flattenTpl,
+ bodyData: {
+ parent: `${parent.pool_name}/${parent.image_name}@${parent.snap_name}`,
+ child: `${poolName}/${imageName}`
+ },
+ onSubmit: () => {
+ this.flattenRbd(poolName, imageName);
+ }
+ };
+
+ this.modalRef = this.modalService.show(ConfirmationModalComponent, { initialState });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-model.ts
new file mode 100644
index 00000000..3920b6ff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-model.ts
@@ -0,0 +1,14 @@
+export class RbdModel {
+ id: string;
+ unique_id: string;
+ name: string;
+ pool_name: string;
+ image_format: RBDImageFormat;
+
+ cdExecuting: string;
+}
+
+export enum RBDImageFormat {
+ V1 = 1,
+ V2 = 2
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.html
new file mode 100644
index 00000000..86a1d9bc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.html
@@ -0,0 +1,53 @@
+<div class="modal-header">
+ <h4 class="modal-title pull-left"
+ i18n="form title|Example: Create rbdSnapshot@@formTitle">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="modalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<form name="snapshotForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="snapshotForm"
+ novalidate>
+ <div class="modal-body">
+
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': snapshotForm.showError('snapshotName', formDir)}">
+ <label class="control-label col-sm-3"
+ for="snapshotName">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Snapshot name..."
+ id="snapshotName"
+ name="snapshotName"
+ formControlName="snapshotName"
+ autofocus>
+ <span class="help-block"
+ *ngIf="snapshotForm.showError('snapshotName', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button [form]="snapshotForm"
+ (submitAction)="submit()"
+ i18n="form action button|Example: Create rbdSnapshot@@formActionButton">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Close"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+</form>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.spec.ts
new file mode 100644
index 00000000..f75cc8fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.spec.ts
@@ -0,0 +1,64 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { ApiModule } from '../../../shared/api/api.module';
+import { ComponentsModule } from '../../../shared/components/components.module';
+import { PipesModule } from '../../../shared/pipes/pipes.module';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { RbdSnapshotFormComponent } from './rbd-snapshot-form.component';
+
+describe('RbdSnapshotFormComponent', () => {
+ let component: RbdSnapshotFormComponent;
+ let fixture: ComponentFixture<RbdSnapshotFormComponent>;
+
+ configureTestBed({
+ imports: [
+ ReactiveFormsModule,
+ ComponentsModule,
+ PipesModule,
+ HttpClientTestingModule,
+ ApiModule,
+ ToastrModule.forRoot(),
+ RouterTestingModule
+ ],
+ declarations: [RbdSnapshotFormComponent],
+ providers: [BsModalRef, BsModalService, AuthStorageService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdSnapshotFormComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should show "Create" text', () => {
+ fixture.detectChanges();
+
+ const header = fixture.debugElement.nativeElement.querySelector('h4');
+ expect(header.textContent).toBe('Create RBD Snapshot');
+
+ const button = fixture.debugElement.nativeElement.querySelector('cd-submit-button');
+ expect(button.textContent).toBe('Create RBD Snapshot');
+ });
+
+ it('should show "Rename" text', () => {
+ component.setEditing();
+
+ fixture.detectChanges();
+
+ const header = fixture.debugElement.nativeElement.querySelector('h4');
+ expect(header.textContent).toBe('Rename RBD Snapshot');
+
+ const button = fixture.debugElement.nativeElement.querySelector('cd-submit-button');
+ expect(button.textContent).toBe('Rename RBD Snapshot');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.ts
new file mode 100644
index 00000000..217a3bbe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-form/rbd-snapshot-form.component.ts
@@ -0,0 +1,136 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { Subject } from 'rxjs';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { TaskManagerService } from '../../../shared/services/task-manager.service';
+
+@Component({
+ selector: 'cd-rbd-snapshot-form',
+ templateUrl: './rbd-snapshot-form.component.html',
+ styleUrls: ['./rbd-snapshot-form.component.scss']
+})
+export class RbdSnapshotFormComponent implements OnInit {
+ poolName: string;
+ imageName: string;
+ snapName: string;
+
+ snapshotForm: CdFormGroup;
+
+ editing = false;
+ action: string;
+ resource: string;
+
+ public onSubmit: Subject<string>;
+
+ constructor(
+ public modalRef: BsModalRef,
+ private rbdService: RbdService,
+ private taskManagerService: TaskManagerService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ private actionLabels: ActionLabelsI18n
+ ) {
+ this.action = this.actionLabels.CREATE;
+ this.resource = this.i18n('RBD Snapshot');
+ this.createForm();
+ }
+
+ createForm() {
+ this.snapshotForm = new CdFormGroup({
+ snapshotName: new FormControl('', {
+ validators: [Validators.required]
+ })
+ });
+ }
+
+ ngOnInit() {
+ this.onSubmit = new Subject();
+ }
+
+ setSnapName(snapName) {
+ this.snapName = snapName;
+ this.snapshotForm.get('snapshotName').setValue(snapName);
+ }
+
+ /**
+ * Set the 'editing' flag. If set to TRUE, the modal dialog is in
+ * 'Edit' mode, otherwise in 'Create' mode.
+ * @param {boolean} editing
+ */
+ setEditing(editing: boolean = true) {
+ this.editing = editing;
+ this.action = this.editing ? this.actionLabels.RENAME : this.actionLabels.CREATE;
+ }
+
+ editAction() {
+ const snapshotName = this.snapshotForm.getValue('snapshotName');
+ const finishedTask = new FinishedTask();
+ finishedTask.name = 'rbd/snap/edit';
+ finishedTask.metadata = {
+ pool_name: this.poolName,
+ image_name: this.imageName,
+ snapshot_name: snapshotName
+ };
+ this.rbdService
+ .renameSnapshot(this.poolName, this.imageName, this.snapName, snapshotName)
+ .toPromise()
+ .then(() => {
+ this.taskManagerService.subscribe(
+ finishedTask.name,
+ finishedTask.metadata,
+ (asyncFinishedTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncFinishedTask);
+ }
+ );
+ this.modalRef.hide();
+ this.onSubmit.next(this.snapName);
+ })
+ .catch(() => {
+ this.snapshotForm.setErrors({ cdSubmitButton: true });
+ });
+ }
+
+ createAction() {
+ const snapshotName = this.snapshotForm.getValue('snapshotName');
+ const finishedTask = new FinishedTask();
+ finishedTask.name = 'rbd/snap/create';
+ finishedTask.metadata = {
+ pool_name: this.poolName,
+ image_name: this.imageName,
+ snapshot_name: snapshotName
+ };
+ this.rbdService
+ .createSnapshot(this.poolName, this.imageName, snapshotName)
+ .toPromise()
+ .then(() => {
+ this.taskManagerService.subscribe(
+ finishedTask.name,
+ finishedTask.metadata,
+ (asyncFinishedTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncFinishedTask);
+ }
+ );
+ this.modalRef.hide();
+ this.onSubmit.next(snapshotName);
+ })
+ .catch(() => {
+ this.snapshotForm.setErrors({ cdSubmitButton: true });
+ });
+ }
+
+ submit() {
+ if (this.editing) {
+ this.editAction();
+ } else {
+ this.createAction();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-actions.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-actions.model.ts
new file mode 100644
index 00000000..b3e3a186
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-actions.model.ts
@@ -0,0 +1,89 @@
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+
+export class RbdSnapshotActionsModel {
+ i18n: I18n;
+
+ create: CdTableAction;
+ rename: CdTableAction;
+ protect: CdTableAction;
+ unprotect: CdTableAction;
+ clone: CdTableAction;
+ copy: CdTableAction;
+ rollback: CdTableAction;
+ deleteSnap: CdTableAction;
+ ordering: CdTableAction[];
+
+ constructor(i18n: I18n, actionLabels: ActionLabelsI18n) {
+ this.i18n = i18n;
+
+ this.create = {
+ permission: 'create',
+ icon: 'fa-plus',
+ name: actionLabels.CREATE
+ };
+ this.rename = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ name: actionLabels.RENAME
+ };
+ this.protect = {
+ permission: 'update',
+ icon: 'fa-lock',
+ visible: (selection: CdTableSelection) =>
+ selection.hasSingleSelection && !selection.first().is_protected,
+ name: actionLabels.PROTECT
+ };
+ this.unprotect = {
+ permission: 'update',
+ icon: 'fa-unlock',
+ visible: (selection: CdTableSelection) =>
+ selection.hasSingleSelection && selection.first().is_protected,
+ name: actionLabels.UNPROTECT
+ };
+ this.clone = {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ icon: 'fa-clone',
+ name: actionLabels.CLONE
+ };
+ this.copy = {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ icon: 'fa-copy',
+ name: actionLabels.COPY
+ };
+ this.rollback = {
+ permission: 'update',
+ icon: 'fa-undo',
+ name: actionLabels.ROLLBACK
+ };
+ this.deleteSnap = {
+ permission: 'delete',
+ icon: 'fa-times',
+ disable: (selection: CdTableSelection) => {
+ const first = selection.first();
+ return !selection.hasSingleSelection || first.cdExecuting || first.is_protected;
+ },
+ name: actionLabels.DELETE
+ };
+
+ this.ordering = [
+ this.create,
+ this.rename,
+ this.protect,
+ this.unprotect,
+ this.clone,
+ this.copy,
+ this.rollback,
+ this.deleteSnap
+ ];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.html
new file mode 100644
index 00000000..a1ae6cd0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.html
@@ -0,0 +1,27 @@
+<cd-table [data]="data"
+ columnMode="flex"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)"
+ [columns]="columns">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+</cd-table>
+
+<ng-template #protectTpl
+ let-value="value">
+ <span *ngIf="value"
+ class="label label-success"
+ i18n>PROTECTED</span>
+ <span *ngIf="!value"
+ class="label label-info"
+ i18n>UNPROTECTED</span>
+</ng-template>
+
+<ng-template #rollbackTpl
+ let-value>
+ <ng-container i18n>You are about to rollback</ng-container>
+ <strong>{{ value.snapName }}</strong>.
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts
new file mode 100644
index 00000000..9007e1a7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts
@@ -0,0 +1,425 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { Subject, throwError as observableThrowError } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { ApiModule } from '../../../shared/api/api.module';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ComponentsModule } from '../../../shared/components/components.module';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { DataTableModule } from '../../../shared/datatable/datatable.module';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { Permissions } from '../../../shared/models/permissions';
+import { PipesModule } from '../../../shared/pipes/pipes.module';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { RbdSnapshotFormComponent } from '../rbd-snapshot-form/rbd-snapshot-form.component';
+import { RbdSnapshotListComponent } from './rbd-snapshot-list.component';
+import { RbdSnapshotModel } from './rbd-snapshot.model';
+
+describe('RbdSnapshotListComponent', () => {
+ let component: RbdSnapshotListComponent;
+ let fixture: ComponentFixture<RbdSnapshotListComponent>;
+ let summaryService: SummaryService;
+
+ const fakeAuthStorageService = {
+ isLoggedIn: () => {
+ return true;
+ },
+ getPermissions: () => {
+ return new Permissions({ 'rbd-image': ['read', 'update', 'create', 'delete'] });
+ }
+ };
+
+ configureTestBed({
+ declarations: [RbdSnapshotListComponent],
+ imports: [
+ DataTableModule,
+ ComponentsModule,
+ ToastrModule.forRoot(),
+ ApiModule,
+ HttpClientTestingModule,
+ RouterTestingModule,
+ PipesModule
+ ],
+ providers: [
+ { provide: AuthStorageService, useValue: fakeAuthStorageService },
+ TaskListService,
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdSnapshotListComponent);
+ component = fixture.componentInstance;
+ summaryService = TestBed.get(SummaryService);
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('api delete request', () => {
+ let called;
+ let rbdService: RbdService;
+ let notificationService: NotificationService;
+ let authStorageService: AuthStorageService;
+
+ beforeEach(() => {
+ fixture.detectChanges();
+ const i18n = TestBed.get(I18n);
+ const actionLabelsI18n = TestBed.get(ActionLabelsI18n);
+ called = false;
+ rbdService = new RbdService(null, null);
+ notificationService = new NotificationService(null, null, null);
+ authStorageService = new AuthStorageService();
+ authStorageService.set('user', { 'rbd-image': ['create', 'read', 'update', 'delete'] });
+ component = new RbdSnapshotListComponent(
+ authStorageService,
+ null,
+ null,
+ null,
+ rbdService,
+ null,
+ notificationService,
+ null,
+ null,
+ i18n,
+ actionLabelsI18n
+ );
+ spyOn(rbdService, 'deleteSnapshot').and.returnValue(observableThrowError({ status: 500 }));
+ spyOn(notificationService, 'notifyTask').and.stub();
+ component.modalRef = new BsModalRef();
+ component.modalRef.content = {
+ stopLoadingSpinner: () => (called = true)
+ };
+ });
+
+ it('should call stopLoadingSpinner if the request fails', <any>fakeAsync(() => {
+ expect(called).toBe(false);
+ component._asyncTask('deleteSnapshot', 'rbd/snap/delete', 'someName');
+ tick(500);
+ expect(called).toBe(true);
+ }));
+ });
+
+ describe('handling of executing tasks', () => {
+ let snapshots: RbdSnapshotModel[];
+
+ const addSnapshot = (name) => {
+ const model = new RbdSnapshotModel();
+ model.id = 1;
+ model.name = name;
+ snapshots.push(model);
+ };
+
+ const addTask = (task_name: string, snapshot_name: string) => {
+ const task = new ExecutingTask();
+ task.name = task_name;
+ task.metadata = {
+ pool_name: 'rbd',
+ image_name: 'foo',
+ snapshot_name: snapshot_name
+ };
+ summaryService.addRunningTask(task);
+ };
+
+ const refresh = (data) => {
+ summaryService['summaryDataSource'].next(data);
+ };
+
+ beforeEach(() => {
+ fixture.detectChanges();
+ snapshots = [];
+ addSnapshot('a');
+ addSnapshot('b');
+ addSnapshot('c');
+ component.snapshots = snapshots;
+ component.poolName = 'rbd';
+ component.rbdName = 'foo';
+ refresh({ executing_tasks: [], finished_tasks: [] });
+ component.ngOnChanges();
+ fixture.detectChanges();
+ });
+
+ it('should gets all snapshots without tasks', () => {
+ expect(component.snapshots.length).toBe(3);
+ expect(component.snapshots.every((image) => !image.cdExecuting)).toBeTruthy();
+ });
+
+ it('should add a new image from a task', () => {
+ addTask('rbd/snap/create', 'd');
+ expect(component.snapshots.length).toBe(4);
+ expectItemTasks(component.snapshots[0], undefined);
+ expectItemTasks(component.snapshots[1], undefined);
+ expectItemTasks(component.snapshots[2], undefined);
+ expectItemTasks(component.snapshots[3], 'Creating');
+ });
+
+ it('should show when an existing image is being modified', () => {
+ addTask('rbd/snap/edit', 'a');
+ addTask('rbd/snap/delete', 'b');
+ addTask('rbd/snap/rollback', 'c');
+ expect(component.snapshots.length).toBe(3);
+ expectItemTasks(component.snapshots[0], 'Updating');
+ expectItemTasks(component.snapshots[1], 'Deleting');
+ expectItemTasks(component.snapshots[2], 'Rolling back');
+ });
+ });
+
+ describe('snapshot modal dialog', () => {
+ beforeEach(() => {
+ component.poolName = 'pool01';
+ component.rbdName = 'image01';
+ spyOn(TestBed.get(BsModalService), 'show').and.callFake(() => {
+ const ref = new BsModalRef();
+ ref.content = new RbdSnapshotFormComponent(
+ null,
+ null,
+ null,
+ null,
+ TestBed.get(I18n),
+ TestBed.get(ActionLabelsI18n)
+ );
+ ref.content.onSubmit = new Subject();
+ return ref;
+ });
+ });
+
+ it('should display old snapshot name', () => {
+ component.selection.selected = [{ name: 'oldname' }];
+ component.selection.update();
+ component.openEditSnapshotModal();
+ expect(component.modalRef.content.snapName).toBe('oldname');
+ expect(component.modalRef.content.editing).toBeTruthy();
+ });
+
+ it('should display suggested snapshot name', () => {
+ component.openCreateSnapshotModal();
+ expect(component.modalRef.content.snapName).toMatch(
+ RegExp(`^${component.rbdName}_[\\d-]+T[\\d.:]+[\\+-][\\d:]+$`)
+ );
+ });
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Rename',
+ empty: 'Create'
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Rename' for single selection else 'Create' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(8);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Rename' for single selection else 'Create' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows all actions except for 'Delete'`, () => {
+ expect(tableActions.tableActions.length).toBe(7);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Clone' for single selection else 'Create' as main action`, () => {
+ scenario.single = 'Clone';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create', 'Clone', 'Copy' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[4],
+ component.tableActions[5],
+ component.tableActions[7]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Rename' as main action`, () => {
+ scenario.empty = 'Rename';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Rename', 'Protect', 'Unprotect', 'Rollback' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(5);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2],
+ component.tableActions[3],
+ component.tableActions[6],
+ component.tableActions[7]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows 'Clone' for single selection else 'Create' as main action`, () => {
+ scenario.single = 'Clone';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create', 'Clone' and 'Copy' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[4],
+ component.tableActions[5]
+ ]);
+ });
+ });
+
+ describe('with read and edit', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Rename' as main action`, () => {
+ scenario.empty = 'Rename';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Rename', 'Protect', 'Unprotect' and 'Rollback' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2],
+ component.tableActions[3],
+ component.tableActions[6]
+ ]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[7]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+
+ describe('test unprotected and protected action cases', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows none of them if nothing is selected`, () => {
+ permissionHelper.setSelection([]);
+ fixture.detectChanges();
+ expect(tableActions.dropDownActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[6]
+ ]);
+ });
+
+ it(`shows 'Protect' of them if nothing is selected`, () => {
+ permissionHelper.setSelection([{ is_protected: false }]);
+ fixture.detectChanges();
+ expect(tableActions.dropDownActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2],
+ component.tableActions[6]
+ ]);
+ });
+
+ it(`shows 'Unprotect' of them if nothing is selected`, () => {
+ permissionHelper.setSelection([{ is_protected: true }]);
+ fixture.detectChanges();
+ expect(tableActions.dropDownActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[3],
+ component.tableActions[6]
+ ]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts
new file mode 100644
index 00000000..45470a0f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts
@@ -0,0 +1,286 @@
+import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as moment from 'moment';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { of } from 'rxjs';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { CdDatePipe } from '../../../shared/pipes/cd-date.pipe';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskManagerService } from '../../../shared/services/task-manager.service';
+import { RbdSnapshotFormComponent } from '../rbd-snapshot-form/rbd-snapshot-form.component';
+import { RbdSnapshotActionsModel } from './rbd-snapshot-actions.model';
+import { RbdSnapshotModel } from './rbd-snapshot.model';
+
+@Component({
+ selector: 'cd-rbd-snapshot-list',
+ templateUrl: './rbd-snapshot-list.component.html',
+ styleUrls: ['./rbd-snapshot-list.component.scss'],
+ providers: [TaskListService]
+})
+export class RbdSnapshotListComponent implements OnInit, OnChanges {
+ @Input()
+ snapshots: RbdSnapshotModel[] = [];
+ @Input()
+ poolName: string;
+ @Input()
+ rbdName: string;
+ @ViewChild('nameTpl')
+ nameTpl: TemplateRef<any>;
+ @ViewChild('protectTpl')
+ protectTpl: TemplateRef<any>;
+ @ViewChild('rollbackTpl')
+ rollbackTpl: TemplateRef<any>;
+
+ permission: Permission;
+ selection = new CdTableSelection();
+ tableActions: CdTableAction[];
+
+ data: RbdSnapshotModel[];
+
+ columns: CdTableColumn[];
+
+ modalRef: BsModalRef;
+
+ builders = {
+ 'rbd/snap/create': (metadata) => {
+ const model = new RbdSnapshotModel();
+ model.name = metadata['snapshot_name'];
+ return model;
+ }
+ };
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private modalService: BsModalService,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private cdDatePipe: CdDatePipe,
+ private rbdService: RbdService,
+ private taskManagerService: TaskManagerService,
+ private notificationService: NotificationService,
+ private summaryService: SummaryService,
+ private taskListService: TaskListService,
+ private i18n: I18n,
+ private actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().rbdImage;
+ const actions = new RbdSnapshotActionsModel(this.i18n, this.actionLabels);
+ actions.create.click = () => this.openCreateSnapshotModal();
+ actions.rename.click = () => this.openEditSnapshotModal();
+ actions.protect.click = () => this.toggleProtection();
+ actions.unprotect.click = () => this.toggleProtection();
+ const getImageUri = () =>
+ this.selection.first() &&
+ `${encodeURIComponent(this.poolName)}/${encodeURIComponent(
+ this.rbdName
+ )}/${encodeURIComponent(this.selection.first().name)}`;
+ actions.clone.routerLink = () => `/block/rbd/clone/${getImageUri()}`;
+ actions.copy.routerLink = () => `/block/rbd/copy/${getImageUri()}`;
+ actions.rollback.click = () => this.rollbackModal();
+ actions.deleteSnap.click = () => this.deleteSnapshotModal();
+ this.tableActions = actions.ordering;
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ cellTransformation: CellTemplate.executing,
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Size'),
+ prop: 'size',
+ flexGrow: 1,
+ cellClass: 'text-right',
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Provisioned'),
+ prop: 'disk_usage',
+ flexGrow: 1,
+ cellClass: 'text-right',
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('State'),
+ prop: 'is_protected',
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTemplate: this.protectTpl
+ },
+ {
+ name: this.i18n('Created'),
+ prop: 'timestamp',
+ flexGrow: 1,
+ pipe: this.cdDatePipe
+ }
+ ];
+ }
+
+ ngOnChanges() {
+ const itemFilter = (entry, task) => {
+ return entry.name === task.metadata['snapshot_name'];
+ };
+
+ const taskFilter = (task) => {
+ return (
+ ['rbd/snap/create', 'rbd/snap/delete', 'rbd/snap/edit', 'rbd/snap/rollback'].includes(
+ task.name
+ ) &&
+ this.poolName === task.metadata['pool_name'] &&
+ this.rbdName === task.metadata['image_name']
+ );
+ };
+
+ this.taskListService.init(
+ () => of(this.snapshots),
+ null,
+ (items) => (this.data = items),
+ () => (this.data = this.snapshots),
+ taskFilter,
+ itemFilter,
+ this.builders
+ );
+ }
+
+ private openSnapshotModal(taskName: string, snapName: string = null) {
+ this.modalRef = this.modalService.show(RbdSnapshotFormComponent);
+ this.modalRef.content.poolName = this.poolName;
+ this.modalRef.content.imageName = this.rbdName;
+ if (snapName) {
+ this.modalRef.content.setEditing();
+ } else {
+ // Auto-create a name for the snapshot: <image_name>_<timestamp_ISO_8601>
+ // https://en.wikipedia.org/wiki/ISO_8601
+ snapName = `${this.rbdName}_${moment().toISOString(true)}`;
+ }
+ this.modalRef.content.setSnapName(snapName);
+ this.modalRef.content.onSubmit.subscribe((snapshotName: string) => {
+ const executingTask = new ExecutingTask();
+ executingTask.name = taskName;
+ executingTask.metadata = {
+ image_name: this.rbdName,
+ pool_name: this.poolName,
+ snapshot_name: snapshotName
+ };
+ this.summaryService.addRunningTask(executingTask);
+ this.ngOnChanges();
+ });
+ }
+
+ openCreateSnapshotModal() {
+ this.openSnapshotModal('rbd/snap/create');
+ }
+
+ openEditSnapshotModal() {
+ this.openSnapshotModal('rbd/snap/edit', this.selection.first().name);
+ }
+
+ toggleProtection() {
+ const snapshotName = this.selection.first().name;
+ const isProtected = this.selection.first().is_protected;
+ const finishedTask = new FinishedTask();
+ finishedTask.name = 'rbd/snap/edit';
+ finishedTask.metadata = {
+ pool_name: this.poolName,
+ image_name: this.rbdName,
+ snapshot_name: snapshotName
+ };
+ this.rbdService
+ .protectSnapshot(this.poolName, this.rbdName, snapshotName, !isProtected)
+ .toPromise()
+ .then(() => {
+ const executingTask = new ExecutingTask();
+ executingTask.name = finishedTask.name;
+ executingTask.metadata = finishedTask.metadata;
+ this.summaryService.addRunningTask(executingTask);
+ this.ngOnChanges();
+ this.taskManagerService.subscribe(
+ finishedTask.name,
+ finishedTask.metadata,
+ (asyncFinishedTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncFinishedTask);
+ }
+ );
+ });
+ }
+
+ _asyncTask(task: string, taskName: string, snapshotName: string) {
+ const finishedTask = new FinishedTask();
+ finishedTask.name = taskName;
+ finishedTask.metadata = {
+ pool_name: this.poolName,
+ image_name: this.rbdName,
+ snapshot_name: snapshotName
+ };
+ this.rbdService[task](this.poolName, this.rbdName, snapshotName)
+ .toPromise()
+ .then(() => {
+ const executingTask = new ExecutingTask();
+ executingTask.name = finishedTask.name;
+ executingTask.metadata = finishedTask.metadata;
+ this.summaryService.addRunningTask(executingTask);
+ this.modalRef.hide();
+ this.ngOnChanges();
+ this.taskManagerService.subscribe(
+ executingTask.name,
+ executingTask.metadata,
+ (asyncFinishedTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncFinishedTask);
+ }
+ );
+ })
+ .catch(() => {
+ this.modalRef.content.stopLoadingSpinner();
+ });
+ }
+
+ rollbackModal() {
+ const snapshotName = this.selection.selected[0].name;
+ const initialState = {
+ titleText: this.i18n('RBD snapshot rollback'),
+ buttonText: this.i18n('Rollback'),
+ bodyTpl: this.rollbackTpl,
+ bodyData: {
+ snapName: `${this.poolName}/${this.rbdName}@${snapshotName}`
+ },
+ onSubmit: () => {
+ this._asyncTask('rollbackSnapshot', 'rbd/snap/rollback', snapshotName);
+ }
+ };
+
+ this.modalRef = this.modalService.show(ConfirmationModalComponent, { initialState });
+ }
+
+ deleteSnapshotModal() {
+ const snapshotName = this.selection.selected[0].name;
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.i18n('RBD snapshot'),
+ itemNames: [snapshotName],
+ submitAction: () => this._asyncTask('deleteSnapshot', 'rbd/snap/delete', snapshotName)
+ }
+ });
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot.model.ts
new file mode 100644
index 00000000..06fd2878
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot.model.ts
@@ -0,0 +1,9 @@
+export class RbdSnapshotModel {
+ id: number;
+ name: string;
+ size: number;
+ timestamp: string;
+ is_protected: boolean;
+
+ cdExecuting: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html
new file mode 100644
index 00000000..6ad31a2c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html
@@ -0,0 +1,51 @@
+<cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
+ [status]="viewCacheStatus.status"
+ [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
+
+<cd-table [data]="images"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="id"
+ forceIdentifier="true"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <div class="table-actions btn-toolbar">
+ <cd-table-actions class="btn-group"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+
+ <button class="btn btn-sm btn-default btn-label"
+ type="button"
+ (click)="purgeModal()"
+ [disabled]="disablePurgeBtn"
+ *ngIf="permission.delete">
+ <i class="fa fa-fw fa-times"
+ aria-hidden="true"></i>
+ <ng-container i18n>Purge Trash</ng-container>
+ </button>
+ </div>
+</cd-table>
+
+<ng-template #expiresTpl
+ let-row="row"
+ let-value="value">
+ <ng-container *ngIf="row.cdIsExpired"
+ i18n>Expired at</ng-container>
+
+ <ng-container *ngIf="!row.cdIsExpired"
+ i18n>Protected until</ng-container>
+
+ {{ value | cdDate }}
+</ng-template>
+
+<ng-template #deleteTpl
+ let-expiresAt>
+ <p class="text-danger"
+ *ngIf="!isExpired(expiresAt)">
+ <strong>
+ <ng-container i18n>This image is protected until {{ expiresAt | cdDate }}.</ng-container>
+ </strong>
+ </p>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts
new file mode 100644
index 00000000..98bf7662
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts
@@ -0,0 +1,163 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import { By } from '@angular/platform-browser';
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders
+} from '../../../../testing/unit-test-helper';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdTrashListComponent } from './rbd-trash-list.component';
+
+describe('RbdTrashListComponent', () => {
+ let component: RbdTrashListComponent;
+ let fixture: ComponentFixture<RbdTrashListComponent>;
+ let summaryService: SummaryService;
+ let rbdService: RbdService;
+
+ configureTestBed({
+ declarations: [RbdTrashListComponent],
+ imports: [SharedModule, HttpClientTestingModule, RouterTestingModule, ToastrModule.forRoot()],
+ providers: [TaskListService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdTrashListComponent);
+ component = fixture.componentInstance;
+ summaryService = TestBed.get(SummaryService);
+ rbdService = TestBed.get(RbdService);
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should load trash images when summary is trigged', () => {
+ spyOn(rbdService, 'listTrash').and.callThrough();
+
+ summaryService['summaryDataSource'].next({ executingTasks: null });
+ expect(rbdService.listTrash).toHaveBeenCalled();
+ });
+
+ it('should call updateSelection', () => {
+ const selection = new CdTableSelection();
+ selection.selected = ['foo'];
+ selection.update();
+
+ expect(component.selection.hasSelection).toBeFalsy();
+ component.updateSelection(selection);
+ expect(component.selection.hasSelection).toBeTruthy();
+ });
+
+ describe('handling of executing tasks', () => {
+ let images: any[];
+
+ const addImage = (id) => {
+ images.push({
+ id: id
+ });
+ };
+
+ const addTask = (name: string, image_id: string) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ task.metadata = {
+ image_id: image_id
+ };
+ summaryService.addRunningTask(task);
+ };
+
+ beforeEach(() => {
+ images = [];
+ addImage('1');
+ addImage('2');
+ component.images = images;
+ summaryService['summaryDataSource'].next({ executingTasks: [] });
+ spyOn(rbdService, 'listTrash').and.callFake(() =>
+ of([{ pool_name: 'rbd', status: 1, value: images }])
+ );
+ fixture.detectChanges();
+ });
+
+ it('should gets all images without tasks', () => {
+ expect(component.images.length).toBe(2);
+ expect(component.images.every((image) => !image.cdExecuting)).toBeTruthy();
+ });
+
+ it('should show when an existing image is being modified', () => {
+ addTask('rbd/trash/remove', '1');
+ addTask('rbd/trash/restore', '2');
+ expect(component.images.length).toBe(2);
+ expectItemTasks(component.images[0], 'Deleting');
+ expectItemTasks(component.images[1], 'Restoring');
+ });
+ });
+
+ describe('display purge button', () => {
+ let images: any[];
+ const addImage = (id: string) => {
+ images.push({
+ id: id,
+ pool_name: 'pl',
+ deferment_end_time: 'abc'
+ });
+ };
+
+ beforeEach(() => {
+ summaryService['summaryDataSource'].next({ executingTasks: [] });
+ spyOn(rbdService, 'listTrash').and.callFake(() => {
+ of([{ pool_name: 'rbd', status: 1, value: images }]);
+ });
+ fixture.detectChanges();
+ });
+
+ it('should show button disabled when no image is in trash', () => {
+ expect(component.disablePurgeBtn).toBeTruthy();
+ });
+
+ it('should show button enabled when an existing image is in trash', () => {
+ images = [];
+ addImage('1');
+ const payload = [{ pool_name: 'rbd', status: 1, value: images }];
+ component.prepareResponse(payload);
+ expect(component.disablePurgeBtn).toBeFalsy();
+ });
+
+ it('should show button with delete permission', () => {
+ component.permission = {
+ read: true,
+ create: true,
+ delete: true,
+ update: true
+ };
+ fixture.detectChanges();
+
+ const purge = fixture.debugElement.query(By.css('.table-actions button .fa-times'));
+ expect(purge).not.toBeNull();
+ });
+
+ it('should remove button without delete permission', () => {
+ component.permission = {
+ read: true,
+ create: true,
+ delete: false,
+ update: true
+ };
+ fixture.detectChanges();
+
+ const purge = fixture.debugElement.query(By.css('.table-actions button .fa-times'));
+ expect(purge).toBeNull();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts
new file mode 100644
index 00000000..85571492
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts
@@ -0,0 +1,212 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import * as moment from 'moment';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { CdDatePipe } from '../../../shared/pipes/cd-date.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { RbdTrashPurgeModalComponent } from '../rbd-trash-purge-modal/rbd-trash-purge-modal.component';
+import { RbdTrashRestoreModalComponent } from '../rbd-trash-restore-modal/rbd-trash-restore-modal.component';
+
+@Component({
+ selector: 'cd-rbd-trash-list',
+ templateUrl: './rbd-trash-list.component.html',
+ styleUrls: ['./rbd-trash-list.component.scss'],
+ providers: [TaskListService]
+})
+export class RbdTrashListComponent implements OnInit {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+ @ViewChild('expiresTpl')
+ expiresTpl: TemplateRef<any>;
+ @ViewChild('deleteTpl')
+ deleteTpl: TemplateRef<any>;
+
+ columns: CdTableColumn[];
+ executingTasks: ExecutingTask[] = [];
+ images: any;
+ modalRef: BsModalRef;
+ permission: Permission;
+ retries: number;
+ selection = new CdTableSelection();
+ tableActions: CdTableAction[];
+ viewCacheStatusList: any[];
+ disablePurgeBtn = true;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private rbdService: RbdService,
+ private modalService: BsModalService,
+ private cdDatePipe: CdDatePipe,
+ private taskListService: TaskListService,
+ private taskWrapper: TaskWrapperService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().rbdImage;
+
+ const restoreAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-undo',
+ click: () => this.restoreModal(),
+ name: this.actionLabels.RESTORE
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteModal(),
+ name: this.actionLabels.DELETE
+ };
+ this.tableActions = [restoreAction, deleteAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('ID'),
+ prop: 'id',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.executing
+ },
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Pool'),
+ prop: 'pool_name',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Status'),
+ prop: 'deferment_end_time',
+ flexGrow: 1,
+ cellTemplate: this.expiresTpl
+ },
+ {
+ name: this.i18n('Deleted At'),
+ prop: 'deletion_time',
+ flexGrow: 1,
+ pipe: this.cdDatePipe
+ }
+ ];
+
+ this.taskListService.init(
+ () => this.rbdService.listTrash(),
+ (resp) => this.prepareResponse(resp),
+ (images) => (this.images = images),
+ () => this.onFetchError(),
+ this.taskFilter,
+ this.itemFilter,
+ undefined
+ );
+ }
+
+ prepareResponse(resp: any[]): any[] {
+ let images = [];
+ const viewCacheStatusMap = {};
+ resp.forEach((pool) => {
+ if (_.isUndefined(viewCacheStatusMap[pool.status])) {
+ viewCacheStatusMap[pool.status] = [];
+ }
+ viewCacheStatusMap[pool.status].push(pool.pool_name);
+ images = images.concat(pool.value);
+ this.disablePurgeBtn = !images.length;
+ });
+
+ const viewCacheStatusList = [];
+ _.forEach(viewCacheStatusMap, (value: any, key) => {
+ viewCacheStatusList.push({
+ status: parseInt(key, 10),
+ statusFor:
+ (value.length > 1 ? 'pools ' : 'pool ') +
+ '<strong>' +
+ value.join('</strong>, <strong>') +
+ '</strong>'
+ });
+ });
+ this.viewCacheStatusList = viewCacheStatusList;
+ images.forEach((image) => {
+ image.cdIsExpired = moment().isAfter(image.deferment_end_time);
+ });
+ return images;
+ }
+
+ onFetchError() {
+ this.table.reset(); // Disable loading indicator.
+ this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+ }
+
+ itemFilter(entry, task) {
+ return entry.id === task.metadata['image_id'];
+ }
+
+ taskFilter(task) {
+ return ['rbd/trash/remove', 'rbd/trash/restore'].includes(task.name);
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ restoreModal() {
+ const initialState = {
+ metaType: 'RBD',
+ poolName: this.selection.first().pool_name,
+ imageName: this.selection.first().name,
+ imageId: this.selection.first().id
+ };
+
+ this.modalRef = this.modalService.show(RbdTrashRestoreModalComponent, { initialState });
+ }
+
+ deleteModal() {
+ const poolName = this.selection.first().pool_name;
+ const imageName = this.selection.first().name;
+ const imageId = this.selection.first().id;
+ const expiresAt = this.selection.first().deferment_end_time;
+
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: 'RBD',
+ itemNames: [`${poolName}/${imageName}`],
+ bodyTemplate: this.deleteTpl,
+ bodyContext: { $implicit: expiresAt },
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('rbd/trash/remove', {
+ pool_name: poolName,
+ image_id: imageId,
+ image_name: imageName
+ }),
+ call: this.rbdService.removeTrash(poolName, imageId, imageName, true)
+ })
+ }
+ });
+ }
+
+ isExpired(expiresAt): boolean {
+ return moment().isAfter(expiresAt);
+ }
+
+ purgeModal() {
+ this.modalService.show(RbdTrashPurgeModalComponent);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.html
new file mode 100644
index 00000000..d05a4b95
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.html
@@ -0,0 +1,49 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container i18n
+ class="modal-title">Move an image to trash</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="moveForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="moveForm"
+ novalidate>
+ <div class="modal-body">
+ <p i18n>To move <kbd>{{ poolName }}/{{ imageName }}</kbd> to trash,
+ click <kbd>Move Image</kbd>. Optionally, you can pick an expiration date.</p>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': moveForm.showError('expiresAt', formDir)}">
+ <label for="expires"
+ i18n>Protection expires at</label>
+ <input type="text"
+ placeholder="NOT PROTECTED"
+ i18n-placeholder
+ class="form-control"
+ [minDate]="minDate"
+ [bsConfig]="bsConfig"
+ formControlName="expiresAt"
+ bsDatepicker>
+ <span class="help-block"
+ *ngIf="moveForm.showError('expiresAt', formDir, 'format')"
+ i18n>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</span>
+ <span class="help-block"
+ *ngIf="moveForm.showError('expiresAt', formDir, 'expired')"
+ i18n>Protection has already expired. Please pick a future date or leave it empty.</span>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button i18n
+ [form]="moveForm"
+ (submitAction)="moveImage()">Move Image</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.scss
new file mode 100644
index 00000000..94a90912
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.scss
@@ -0,0 +1,5 @@
+// Temprary fix until ngx-bootstrap merges: https://github.com/valor-software/ngx-bootstrap/pull/4509
+::ng-deep .bs-datepicker-head bs-datepicker-navigation-view {
+ display: flex;
+ justify-content: space-between;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.spec.ts
new file mode 100644
index 00000000..1c77198e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.spec.ts
@@ -0,0 +1,100 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as moment from 'moment';
+import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdTrashMoveModalComponent } from './rbd-trash-move-modal.component';
+
+describe('RbdTrashMoveModalComponent', () => {
+ let component: RbdTrashMoveModalComponent;
+ let fixture: ComponentFixture<RbdTrashMoveModalComponent>;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [
+ ReactiveFormsModule,
+ HttpClientTestingModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ BsDatepickerModule.forRoot()
+ ],
+ declarations: [RbdTrashMoveModalComponent],
+ providers: [BsModalRef, BsModalService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdTrashMoveModalComponent);
+ component = fixture.componentInstance;
+ httpTesting = TestBed.get(HttpTestingController);
+
+ component.metaType = 'RBD';
+ component.poolName = 'foo';
+ component.imageName = 'bar';
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(component.moveForm).toBeDefined();
+ });
+
+ it('should finish running ngOnInit', () => {
+ fixture.detectChanges();
+ expect(component.pattern).toEqual('foo/bar');
+ });
+
+ describe('should call moveImage', () => {
+ let notificationService;
+
+ beforeEach(() => {
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+ spyOn(component.modalRef, 'hide').and.callThrough();
+ });
+
+ afterEach(() => {
+ expect(notificationService.show).toHaveBeenCalledTimes(1);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('with normal delay', () => {
+ component.moveImage();
+ const req = httpTesting.expectOne('api/block/image/foo/bar/move_trash');
+ req.flush(null);
+ expect(req.request.body).toEqual({ delay: 0 });
+ });
+
+ it('with delay < 0', () => {
+ const oldDate = moment()
+ .subtract(24, 'hour')
+ .toDate();
+ component.moveForm.patchValue({ expiresAt: oldDate });
+
+ component.moveImage();
+ const req = httpTesting.expectOne('api/block/image/foo/bar/move_trash');
+ req.flush(null);
+ expect(req.request.body).toEqual({ delay: 0 });
+ });
+
+ it('with delay < 0', () => {
+ const oldDate = moment()
+ .add(24, 'hour')
+ .toISOString();
+ fixture.detectChanges();
+ component.moveForm.patchValue({ expiresAt: oldDate });
+
+ component.moveImage();
+ const req = httpTesting.expectOne('api/block/image/foo/bar/move_trash');
+ req.flush(null);
+ expect(req.request.body.delay).toBeGreaterThan(86390);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.ts
new file mode 100644
index 00000000..84be13df
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-move-modal/rbd-trash-move-modal.component.ts
@@ -0,0 +1,88 @@
+import { Component, OnInit } from '@angular/core';
+
+import * as moment from 'moment';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+
+@Component({
+ selector: 'cd-rbd-trash-move-modal',
+ templateUrl: './rbd-trash-move-modal.component.html',
+ styleUrls: ['./rbd-trash-move-modal.component.scss']
+})
+export class RbdTrashMoveModalComponent implements OnInit {
+ metaType: string;
+ poolName: string;
+ imageName: string;
+ executingTasks: ExecutingTask[];
+
+ moveForm: CdFormGroup;
+ minDate = new Date();
+ bsConfig = {
+ dateInputFormat: 'YYYY-MM-DD HH:mm:ss',
+ containerClass: 'theme-default'
+ };
+ pattern: string;
+
+ constructor(
+ private rbdService: RbdService,
+ public modalRef: BsModalRef,
+ private fb: CdFormBuilder,
+ private taskWrapper: TaskWrapperService
+ ) {
+ this.createForm();
+ }
+
+ createForm() {
+ this.moveForm = this.fb.group({
+ expiresAt: [
+ '',
+ [
+ CdValidators.custom('format', (expiresAt) => {
+ const result = expiresAt === '' || moment(expiresAt, 'YYYY-MM-DD HH:mm:ss').isValid();
+ return !result;
+ }),
+ CdValidators.custom('expired', (expiresAt) => {
+ const result = moment().isAfter(expiresAt);
+ return result;
+ })
+ ]
+ ]
+ });
+ }
+
+ ngOnInit() {
+ this.pattern = `${this.poolName}/${this.imageName}`;
+ }
+
+ moveImage() {
+ let delay = 0;
+ const expiresAt = this.moveForm.getValue('expiresAt');
+
+ if (expiresAt) {
+ delay = moment(expiresAt).diff(moment(), 'seconds', true);
+ }
+
+ if (delay < 0) {
+ delay = 0;
+ }
+
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('rbd/trash/move', {
+ pool_name: this.poolName,
+ image_name: this.imageName
+ }),
+ call: this.rbdService.moveTrash(this.poolName, this.imageName, delay)
+ })
+ .subscribe(undefined, undefined, () => {
+ this.modalRef.hide();
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.html
new file mode 100644
index 00000000..42a2a460
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.html
@@ -0,0 +1,52 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container i18n
+ class="modal-title">Purge Trash</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="purgeForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="purgeForm"
+ novalidate>
+ <div class="modal-body">
+ <p>
+ <ng-container i18n>To purge, select one or</ng-container>&nbsp;
+ <kbd i18n>All</kbd>&nbsp;
+ <ng-container i18n>pools and click</ng-container>&nbsp;
+ <kbd i18n>Purge Trash</kbd>.&nbsp;
+ </p>
+
+ <div class="form-group">
+ <label class="center-block"
+ i18n>Pool:</label>
+ <input class="form-control"
+ type="text"
+ placeholder="Pool name..."
+ i18n-placeholder
+ formControlName="poolName"
+ *ngIf="!poolPermission.read">
+ <select class="form-control"
+ formControlName="poolName"
+ *ngIf="poolPermission.read">
+ <option value=""
+ i18n>All</option>
+ <option *ngFor="let pool of pools"
+ [value]="pool">{{ pool }}</option>
+ </select>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button [form]="purgeForm"
+ (submitAction)="purge()"
+ i18n>Purge Trash</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.spec.ts
new file mode 100644
index 00000000..32969f10
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.spec.ts
@@ -0,0 +1,102 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { Permission } from '../../../shared/models/permissions';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdTrashPurgeModalComponent } from './rbd-trash-purge-modal.component';
+
+describe('RbdTrashPurgeModalComponent', () => {
+ let component: RbdTrashPurgeModalComponent;
+ let fixture: ComponentFixture<RbdTrashPurgeModalComponent>;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ RouterTestingModule
+ ],
+ declarations: [RbdTrashPurgeModalComponent],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdTrashPurgeModalComponent);
+ httpTesting = TestBed.get(HttpTestingController);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ it('should finish ngOnInit', fakeAsync(() => {
+ component.poolPermission = new Permission(['read', 'create', 'update', 'delete']);
+ fixture.detectChanges();
+ const req = httpTesting.expectOne('api/pool?attrs=pool_name,application_metadata');
+ req.flush([
+ {
+ application_metadata: ['foo'],
+ pool_name: 'bar'
+ },
+ {
+ application_metadata: ['rbd'],
+ pool_name: 'baz'
+ }
+ ]);
+ tick();
+ expect(component.pools).toEqual(['baz']);
+ expect(component.purgeForm).toBeTruthy();
+ }));
+
+ it('should call ngOnInit without pool permissions', () => {
+ component.poolPermission = new Permission([]);
+ component.ngOnInit();
+ httpTesting.expectOne('api/summary');
+ httpTesting.verify();
+ });
+
+ describe('should call purge', () => {
+ let notificationService: NotificationService;
+ let modalRef: BsModalRef;
+ let req;
+
+ beforeEach(() => {
+ fixture.detectChanges();
+ notificationService = TestBed.get(NotificationService);
+ modalRef = TestBed.get(BsModalRef);
+
+ component.purgeForm.patchValue({ poolName: 'foo' });
+
+ spyOn(modalRef, 'hide').and.stub();
+ spyOn(component.purgeForm, 'setErrors').and.stub();
+ spyOn(notificationService, 'show').and.stub();
+
+ component.purge();
+
+ req = httpTesting.expectOne('api/block/image/trash/purge/?pool_name=foo');
+ });
+
+ it('with success', () => {
+ req.flush(null);
+ expect(component.purgeForm.setErrors).toHaveBeenCalledTimes(0);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('with failure', () => {
+ req.flush(null, { status: 500, statusText: 'failure' });
+ expect(component.purgeForm.setErrors).toHaveBeenCalledTimes(1);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(0);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.ts
new file mode 100644
index 00000000..730ee62f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-purge-modal/rbd-trash-purge-modal.component.ts
@@ -0,0 +1,72 @@
+import { Component, OnInit } from '@angular/core';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { PoolService } from '../../../shared/api/pool.service';
+import { RbdService } from '../../../shared/api/rbd.service';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+
+@Component({
+ selector: 'cd-rbd-trash-purge-modal',
+ templateUrl: './rbd-trash-purge-modal.component.html',
+ styleUrls: ['./rbd-trash-purge-modal.component.scss']
+})
+export class RbdTrashPurgeModalComponent implements OnInit {
+ poolPermission: Permission;
+ purgeForm: CdFormGroup;
+ pools: any[];
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private rbdService: RbdService,
+ public modalRef: BsModalRef,
+ private fb: CdFormBuilder,
+ private poolService: PoolService,
+ private taskWrapper: TaskWrapperService
+ ) {
+ this.poolPermission = this.authStorageService.getPermissions().pool;
+ }
+
+ createForm() {
+ this.purgeForm = this.fb.group({
+ poolName: ''
+ });
+ }
+
+ ngOnInit() {
+ if (this.poolPermission.read) {
+ this.poolService.list(['pool_name', 'application_metadata']).then((resp) => {
+ this.pools = resp
+ .filter((pool) => pool.application_metadata.includes('rbd'))
+ .map((pool) => pool.pool_name);
+ });
+ }
+
+ this.createForm();
+ }
+
+ purge() {
+ const poolName = this.purgeForm.getValue('poolName') || '';
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('rbd/trash/purge', {
+ pool_name: poolName
+ }),
+ call: this.rbdService.purgeTrash(poolName)
+ })
+ .subscribe(
+ undefined,
+ () => {
+ this.purgeForm.setErrors({ cdSubmitButton: true });
+ },
+ () => {
+ this.modalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.html
new file mode 100644
index 00000000..f1c1c0c1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.html
@@ -0,0 +1,49 @@
+<cd-modal [modalRef]="modalRef">
+ <ng-container i18n
+ class="modal-title">Restore Image</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="restoreForm"
+ class="form"
+ #formDir="ngForm"
+ [formGroup]="restoreForm"
+ novalidate>
+ <div class="modal-body">
+ <p>
+ <ng-container i18n>To restore</ng-container>&nbsp;
+ <kbd>{{ poolName }}/{{ imageName }}@{{ imageId }}</kbd>,&nbsp;
+ <ng-container i18n>type the image's new name and click</ng-container>&nbsp;
+ <kbd i18n>Restore Image</kbd>.
+ </p>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': restoreForm.showError('name', formDir)}">
+ <label for="name"
+ i18n>New Name</label>
+ <input type="text"
+ class="form-control"
+ name="name"
+ id="name"
+ autocomplete="off"
+ formControlName="name"
+ autofocus>
+ <span class="help-block"
+ *ngIf="restoreForm.showError('name', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button [form]="restoreForm"
+ (submitAction)="restore()"
+ i18n>Restore Image</cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.spec.ts
new file mode 100644
index 00000000..caa6cf94
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.spec.ts
@@ -0,0 +1,75 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdTrashRestoreModalComponent } from './rbd-trash-restore-modal.component';
+
+describe('RbdTrashRestoreModalComponent', () => {
+ let component: RbdTrashRestoreModalComponent;
+ let fixture: ComponentFixture<RbdTrashRestoreModalComponent>;
+
+ configureTestBed({
+ declarations: [RbdTrashRestoreModalComponent],
+ imports: [
+ ReactiveFormsModule,
+ HttpClientTestingModule,
+ ToastrModule.forRoot(),
+ SharedModule,
+ RouterTestingModule
+ ],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RbdTrashRestoreModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('should call restore', () => {
+ let httpTesting: HttpTestingController;
+ let notificationService: NotificationService;
+ let modalRef: BsModalRef;
+ let req;
+
+ beforeEach(() => {
+ httpTesting = TestBed.get(HttpTestingController);
+ notificationService = TestBed.get(NotificationService);
+ modalRef = TestBed.get(BsModalRef);
+
+ component.poolName = 'foo';
+ component.imageId = 'bar';
+
+ spyOn(modalRef, 'hide').and.stub();
+ spyOn(component.restoreForm, 'setErrors').and.stub();
+ spyOn(notificationService, 'show').and.stub();
+
+ component.restore();
+
+ req = httpTesting.expectOne('api/block/image/trash/foo/bar/restore');
+ });
+
+ it('with success', () => {
+ req.flush(null);
+ expect(component.restoreForm.setErrors).toHaveBeenCalledTimes(0);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('with failure', () => {
+ req.flush(null, { status: 500, statusText: 'failure' });
+ expect(component.restoreForm.setErrors).toHaveBeenCalledTimes(1);
+ expect(component.modalRef.hide).toHaveBeenCalledTimes(0);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.ts
new file mode 100644
index 00000000..42794419
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-restore-modal/rbd-trash-restore-modal.component.ts
@@ -0,0 +1,61 @@
+import { Component, OnInit } from '@angular/core';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { RbdService } from '../../../shared/api/rbd.service';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+
+@Component({
+ selector: 'cd-rbd-trash-restore-modal',
+ templateUrl: './rbd-trash-restore-modal.component.html',
+ styleUrls: ['./rbd-trash-restore-modal.component.scss']
+})
+export class RbdTrashRestoreModalComponent implements OnInit {
+ metaType: string;
+ poolName: string;
+ imageName: string;
+ imageId: string;
+ executingTasks: ExecutingTask[];
+
+ restoreForm: CdFormGroup;
+
+ constructor(
+ private rbdService: RbdService,
+ public modalRef: BsModalRef,
+ private fb: CdFormBuilder,
+ private taskWrapper: TaskWrapperService
+ ) {}
+
+ ngOnInit() {
+ this.restoreForm = this.fb.group({
+ name: this.imageName
+ });
+ }
+
+ restore() {
+ const name = this.restoreForm.getValue('name');
+
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('rbd/trash/restore', {
+ pool_name: this.poolName,
+ image_id: this.imageId,
+ new_image_name: name
+ }),
+ call: this.rbdService.restoreTrash(this.poolName, this.imageId, name)
+ })
+ .subscribe(
+ undefined,
+ () => {
+ this.restoreForm.setErrors({ cdSubmitButton: true });
+ },
+ () => {
+ this.modalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts
new file mode 100644
index 00000000..47772304
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/ceph.module.ts
@@ -0,0 +1,23 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { SharedModule } from '../shared/shared.module';
+import { CephfsModule } from './cephfs/cephfs.module';
+import { ClusterModule } from './cluster/cluster.module';
+import { DashboardModule } from './dashboard/dashboard.module';
+import { NfsModule } from './nfs/nfs.module';
+import { PerformanceCounterModule } from './performance-counter/performance-counter.module';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ ClusterModule,
+ DashboardModule,
+ PerformanceCounterModule,
+ CephfsModule,
+ NfsModule,
+ SharedModule
+ ],
+ declarations: []
+})
+export class CephModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.html
new file mode 100644
index 00000000..b81bc20b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.html
@@ -0,0 +1,12 @@
+<div class="chart-container">
+ <canvas baseChart
+ #chartCanvas
+ [datasets]="chart.datasets"
+ [options]="chart.options"
+ [chartType]="chart.chartType">
+ </canvas>
+ <div class="chartjs-tooltip"
+ #chartTooltip>
+ <table></table>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.scss
new file mode 100644
index 00000000..81457a14
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.scss
@@ -0,0 +1,8 @@
+@import '../../../../styles/chart-tooltip.scss';
+
+.chart-container {
+ position: relative;
+ height: 500px;
+ width: 100%;
+ margin-bottom: 20px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts
new file mode 100644
index 00000000..2e4c9c20
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts
@@ -0,0 +1,76 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ChartsModule } from 'ng2-charts/ng2-charts';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { CephfsChartComponent } from './cephfs-chart.component';
+
+describe('CephfsChartComponent', () => {
+ let component: CephfsChartComponent;
+ let fixture: ComponentFixture<CephfsChartComponent>;
+
+ const counter = [[0, 15], [5, 15], [10, 25], [15, 50]];
+
+ configureTestBed({
+ imports: [ChartsModule],
+ declarations: [CephfsChartComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CephfsChartComponent);
+ component = fixture.componentInstance;
+ component.mdsCounter = {
+ 'mds_server.handle_client_request': counter,
+ 'mds_mem.ino': counter,
+ name: 'a'
+ };
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('completed the chart', () => {
+ const lhs = component.chart.datasets[0].data;
+ expect(lhs.length).toBe(3);
+ expect(lhs).toEqual([
+ {
+ x: 5000,
+ y: 15
+ },
+ {
+ x: 10000,
+ y: 25
+ },
+ {
+ x: 15000,
+ y: 50
+ }
+ ]);
+
+ const rhs = component.chart.datasets[1].data;
+ expect(rhs.length).toBe(3);
+ expect(rhs).toEqual([
+ {
+ x: 5000,
+ y: 0
+ },
+ {
+ x: 10000,
+ y: 10
+ },
+ {
+ x: 15000,
+ y: 25
+ }
+ ]);
+ });
+
+ it('should force angular to update the chart datasets array in order to update the graph', () => {
+ const oldDatasets = component.chart.datasets;
+ component.ngOnChanges();
+ expect(oldDatasets).toEqual(component.chart.datasets);
+ expect(oldDatasets).not.toBe(component.chart.datasets);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts
new file mode 100644
index 00000000..8d5a876d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts
@@ -0,0 +1,198 @@
+import { Component, ElementRef, Input, OnChanges, OnInit, ViewChild } from '@angular/core';
+
+import { ChartDataSets, ChartOptions, ChartPoint, ChartType } from 'chart.js';
+import * as _ from 'lodash';
+import * as moment from 'moment';
+
+import { ChartTooltip } from '../../../shared/models/chart-tooltip';
+
+@Component({
+ selector: 'cd-cephfs-chart',
+ templateUrl: './cephfs-chart.component.html',
+ styleUrls: ['./cephfs-chart.component.scss']
+})
+export class CephfsChartComponent implements OnChanges, OnInit {
+ @ViewChild('chartCanvas')
+ chartCanvas: ElementRef;
+ @ViewChild('chartTooltip')
+ chartTooltip: ElementRef;
+
+ @Input()
+ mdsCounter: any;
+
+ lhsCounter = 'mds_mem.ino';
+ rhsCounter = 'mds_server.handle_client_request';
+
+ chart: {
+ datasets: ChartDataSets[];
+ options: ChartOptions;
+ chartType: ChartType;
+ } = {
+ datasets: [
+ {
+ label: this.lhsCounter,
+ yAxisID: 'LHS',
+ data: [],
+ lineTension: 0.1
+ },
+ {
+ label: this.rhsCounter,
+ yAxisID: 'RHS',
+ data: [],
+ lineTension: 0.1
+ }
+ ],
+ options: {
+ title: {
+ text: '',
+ display: true
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ legend: {
+ position: 'top'
+ },
+ scales: {
+ xAxes: [
+ {
+ position: 'top',
+ type: 'time',
+ time: {
+ displayFormats: {
+ quarter: 'MMM YYYY'
+ }
+ },
+ ticks: {
+ maxRotation: 0
+ }
+ }
+ ],
+ yAxes: [
+ {
+ id: 'LHS',
+ type: 'linear',
+ position: 'left'
+ },
+ {
+ id: 'RHS',
+ type: 'linear',
+ position: 'right'
+ }
+ ]
+ },
+ tooltips: {
+ enabled: false,
+ mode: 'index',
+ intersect: false,
+ position: 'nearest',
+ callbacks: {
+ // Pick the Unix timestamp of the first tooltip item.
+ title: (tooltipItems, data): string => {
+ let ts = 0;
+ if (tooltipItems.length > 0) {
+ const item = tooltipItems[0];
+ const point = data.datasets[item.datasetIndex].data[item.index] as ChartPoint;
+ ts = point.x as number;
+ }
+ return ts.toString();
+ }
+ }
+ }
+ },
+ chartType: 'line'
+ };
+
+ constructor() {}
+
+ ngOnInit() {
+ if (_.isUndefined(this.mdsCounter)) {
+ return;
+ }
+ this.setChartTooltip();
+ this.updateChart();
+ }
+
+ ngOnChanges() {
+ if (_.isUndefined(this.mdsCounter)) {
+ return;
+ }
+ this.updateChart();
+ }
+
+ private setChartTooltip() {
+ const chartTooltip = new ChartTooltip(
+ this.chartCanvas,
+ this.chartTooltip,
+ (tooltip) => tooltip.caretX + 'px',
+ (tooltip) => tooltip.caretY - tooltip.height - 23 + 'px'
+ );
+ chartTooltip.getTitle = (ts) => moment(ts, 'x').format('LTS');
+ chartTooltip.checkOffset = true;
+ const chartOptions: ChartOptions = {
+ title: {
+ text: this.mdsCounter.name
+ },
+ tooltips: {
+ custom: (tooltip) => chartTooltip.customTooltips(tooltip)
+ }
+ };
+ _.merge(this.chart, { options: chartOptions });
+ }
+
+ private updateChart() {
+ const chartDataSets: ChartDataSets[] = [
+ {
+ data: this.convertTimeSeries(this.mdsCounter[this.lhsCounter])
+ },
+ {
+ data: this.deltaTimeSeries(this.mdsCounter[this.rhsCounter])
+ }
+ ];
+ _.merge(this.chart, {
+ datasets: chartDataSets
+ });
+ this.chart.datasets = [...this.chart.datasets]; // Force angular to update
+ }
+
+ /**
+ * Convert ceph-mgr's time series format (list of 2-tuples
+ * with seconds-since-epoch timestamps) into what chart.js
+ * can handle (list of objects with millisecs-since-epoch
+ * timestamps)
+ */
+ private convertTimeSeries(sourceSeries) {
+ const data = [];
+ _.each(sourceSeries, (dp) => {
+ data.push({
+ x: dp[0] * 1000,
+ y: dp[1]
+ });
+ });
+
+ /**
+ * MDS performance counters chart is expecting the same number of items
+ * from each data series. Since in deltaTimeSeries we are ignoring the first
+ * element, we will do the same here.
+ */
+ data.shift();
+
+ return data;
+ }
+
+ private deltaTimeSeries(sourceSeries) {
+ let i;
+ let prev = sourceSeries[0];
+ const result = [];
+ for (i = 1; i < sourceSeries.length; i++) {
+ const cur = sourceSeries[i];
+
+ result.push({
+ x: cur[0] * 1000,
+ y: cur[1] - prev[1]
+ });
+
+ prev = cur;
+ }
+ return result;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.html
new file mode 100644
index 00000000..8b84e618
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.html
@@ -0,0 +1,6 @@
+<cd-view-cache [status]="viewCacheStatus"></cd-view-cache>
+
+<cd-table [data]="clients.data"
+ [columns]="clients.columns"
+ (fetchData)="refresh()">
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.spec.ts
new file mode 100644
index 00000000..4b5ab9a1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.spec.ts
@@ -0,0 +1,35 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { CephfsClientsComponent } from './cephfs-clients.component';
+
+describe('CephfsClientsComponent', () => {
+ let component: CephfsClientsComponent;
+ let fixture: ComponentFixture<CephfsClientsComponent>;
+
+ configureTestBed({
+ imports: [
+ RouterTestingModule,
+ BsDropdownModule.forRoot(),
+ SharedModule,
+ HttpClientTestingModule
+ ],
+ declarations: [CephfsClientsComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CephfsClientsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.ts
new file mode 100644
index 00000000..af8181ac
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.ts
@@ -0,0 +1,45 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { CephfsService } from '../../../shared/api/cephfs.service';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+
+@Component({
+ selector: 'cd-cephfs-clients',
+ templateUrl: './cephfs-clients.component.html',
+ styleUrls: ['./cephfs-clients.component.scss']
+})
+export class CephfsClientsComponent implements OnInit {
+ @Input()
+ id: number;
+
+ clients: any;
+ viewCacheStatus: ViewCacheStatus;
+
+ constructor(private cephfsService: CephfsService, private i18n: I18n) {}
+
+ ngOnInit() {
+ this.clients = {
+ columns: [
+ { prop: 'id', name: this.i18n('id') },
+ { prop: 'type', name: this.i18n('type') },
+ { prop: 'state', name: this.i18n('state') },
+ { prop: 'version', name: this.i18n('version') },
+ { prop: 'hostname', name: this.i18n('Host') },
+ { prop: 'root', name: this.i18n('root') }
+ ],
+ data: []
+ };
+
+ this.clients.data = [];
+ this.viewCacheStatus = ViewCacheStatus.ValueNone;
+ }
+
+ refresh() {
+ this.cephfsService.getClients(this.id).subscribe((data: any) => {
+ this.viewCacheStatus = data.status;
+ this.clients.data = data.data;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html
new file mode 100644
index 00000000..f82a0005
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html
@@ -0,0 +1,65 @@
+<tabset *ngIf="selectedItem">
+ <tab i18n-heading
+ heading="Details">
+ <div class="row">
+ <div class="col-sm-6">
+ <legend i18n>Ranks</legend>
+
+ <cd-table [data]="ranks.data"
+ [columns]="ranks.columns"
+ (fetchData)="refresh()"
+ [toolHeader]="false">
+ </cd-table>
+
+ <cd-table-key-value [data]="standbys">
+ </cd-table-key-value>
+ </div>
+
+ <div class="col-sm-6">
+ <legend i18n>Pools</legend>
+
+ <cd-table [data]="pools.data"
+ [columns]="pools.columns"
+ [toolHeader]="false">
+ </cd-table>
+ </div>
+ </div>
+
+ <legend i18n>MDS performance counters</legend>
+ <div class="row"
+ *ngFor="let mdsCounter of objectValues(mdsCounters); trackBy: trackByFn">
+ <div class="col-md-12">
+ <cd-cephfs-chart [mdsCounter]="mdsCounter"></cd-cephfs-chart>
+ </div>
+ </div>
+ </tab>
+ <tab i18n-heading
+ heading="Clients: {{ clientCount }}"
+ (selectTab)="clientsSelect=true"
+ (deselect)="clientsSelect=false">
+ <cd-cephfs-clients [id]="id"
+ *ngIf="clientsSelect">
+ </cd-cephfs-clients>
+ </tab>
+ <tab i18n-heading
+ *ngIf="grafanaPermission.read"
+ heading="Performance Details">
+ <cd-grafana [grafanaPath]="'mds-performance?var-mds_servers=mds.' + grafanaId"
+ uid="tbO9LAiZz"
+ grafanaStyle="one">
+ </cd-grafana>
+ </tab>
+</tabset>
+
+<!-- templates -->
+<ng-template #poolUsageTpl
+ let-row="row">
+ <cd-usage-bar [total]="row.size"
+ [used]="row.used"></cd-usage-bar>
+</ng-template>
+
+<ng-template #activityTmpl
+ let-row="row"
+ let-value="value">
+ {{ row.state === 'standby-replay' ? 'Evts' : 'Reqs' }}: {{ value | dimless }} /s
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.scss
new file mode 100644
index 00000000..d82829af
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.scss
@@ -0,0 +1,3 @@
+.progress {
+ margin-bottom: 0px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.spec.ts
new file mode 100644
index 00000000..256db87f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.spec.ts
@@ -0,0 +1,52 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { Component, Input } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { CephfsDetailComponent } from './cephfs-detail.component';
+
+@Component({ selector: 'cd-cephfs-chart', template: '' })
+class CephfsChartStubComponent {
+ @Input()
+ mdsCounter: any;
+}
+
+@Component({ selector: 'cd-cephfs-clients', template: '' })
+class CephfsClientsStubComponent {
+ @Input()
+ mdsCounter: any;
+}
+
+describe('CephfsDetailComponent', () => {
+ let component: CephfsDetailComponent;
+ let fixture: ComponentFixture<CephfsDetailComponent>;
+
+ configureTestBed({
+ imports: [
+ SharedModule,
+ RouterTestingModule,
+ BsDropdownModule.forRoot(),
+ ProgressbarModule.forRoot(),
+ TabsModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ declarations: [CephfsDetailComponent, CephfsChartStubComponent, CephfsClientsStubComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CephfsDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.ts
new file mode 100644
index 00000000..420e35e7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.ts
@@ -0,0 +1,143 @@
+import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { CephfsService } from '../../../shared/api/cephfs.service';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-cephfs-detail',
+ templateUrl: './cephfs-detail.component.html',
+ styleUrls: ['./cephfs-detail.component.scss']
+})
+export class CephfsDetailComponent implements OnChanges, OnInit {
+ @ViewChild('poolUsageTpl')
+ poolUsageTpl: TemplateRef<any>;
+ @ViewChild('activityTmpl')
+ activityTmpl: TemplateRef<any>;
+
+ @Input()
+ selection: CdTableSelection;
+
+ selectedItem: any;
+
+ id: number;
+ name: string;
+ ranks: any;
+ pools: any;
+ standbys = [];
+ clientCount: number;
+ mdsCounters = {};
+ grafanaId: any;
+ grafanaPermission: Permission;
+
+ objectValues = Object.values;
+ clientsSelect = false;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private cephfsService: CephfsService,
+ private dimlessBinary: DimlessBinaryPipe,
+ private dimless: DimlessPipe,
+ private i18n: I18n
+ ) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+ const mdsInfo: any[] = this.selectedItem.mdsmap.info;
+ this.grafanaId = Object.values(mdsInfo)[0].name;
+
+ if (this.id !== this.selectedItem.id) {
+ this.id = this.selectedItem.id;
+ this.ranks.data = [];
+ this.pools.data = [];
+ this.standbys = [];
+ this.mdsCounters = {};
+ }
+ }
+ }
+
+ ngOnInit() {
+ this.ranks = {
+ columns: [
+ { prop: 'rank', name: this.i18n('Rank') },
+ { prop: 'state', name: this.i18n('State') },
+ { prop: 'mds', name: this.i18n('Daemon') },
+ { prop: 'activity', name: this.i18n('Activity'), cellTemplate: this.activityTmpl },
+ { prop: 'dns', name: this.i18n('Dentries'), pipe: this.dimless },
+ { prop: 'inos', name: this.i18n('Inodes'), pipe: this.dimless }
+ ],
+ data: []
+ };
+
+ this.pools = {
+ columns: [
+ { prop: 'pool', name: this.i18n('Pool') },
+ { prop: 'type', name: this.i18n('Type') },
+ { prop: 'size', name: this.i18n('Size'), pipe: this.dimlessBinary },
+ {
+ name: this.i18n('Usage'),
+ cellTemplate: this.poolUsageTpl,
+ comparator: (_valueA, _valueB, rowA, rowB) => {
+ const valA = rowA.used / rowA.avail;
+ const valB = rowB.used / rowB.avail;
+
+ if (valA === valB) {
+ return 0;
+ }
+
+ if (valA > valB) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ }
+ ],
+ data: []
+ };
+ }
+
+ refresh() {
+ this.cephfsService.getCephfs(this.id).subscribe((data: any) => {
+ this.ranks.data = data.cephfs.ranks;
+ this.pools.data = data.cephfs.pools;
+ this.pools.data.forEach((pool) => {
+ pool.size = pool.used + pool.avail;
+ });
+ this.standbys = [
+ {
+ key: this.i18n('Standby daemons'),
+ value: data.standbys.map((value) => value.name).join(', ')
+ }
+ ];
+ this.name = data.cephfs.name;
+ this.clientCount = data.cephfs.client_count;
+ });
+
+ this.cephfsService.getMdsCounters(this.id).subscribe((data) => {
+ _.each(this.mdsCounters, (_value, key) => {
+ if (data[key] === undefined) {
+ delete this.mdsCounters[key];
+ }
+ });
+
+ _.each(data, (mdsData: any, mdsName) => {
+ mdsData.name = mdsName;
+ this.mdsCounters[mdsName] = mdsData;
+ });
+ });
+ }
+
+ trackByFn(_index, item) {
+ return item.name;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.html
new file mode 100644
index 00000000..5f1b3a3f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.html
@@ -0,0 +1,12 @@
+<cd-table [data]="filesystems"
+ columnMode="flex"
+ [columns]="columns"
+ (fetchData)="loadFilesystems($event)"
+ identifier="id"
+ forceIdentifier="true"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-cephfs-detail cdTableDetail
+ [selection]="selection">
+ </cd-cephfs-detail>
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.spec.ts
new file mode 100644
index 00000000..111a6a46
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.spec.ts
@@ -0,0 +1,35 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { Component, Input } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { CephfsListComponent } from './cephfs-list.component';
+
+@Component({ selector: 'cd-cephfs-detail', template: '' })
+class CephfsDetailStubComponent {
+ @Input()
+ selection: CdTableSelection;
+}
+
+describe('CephfsListComponent', () => {
+ let component: CephfsListComponent;
+ let fixture: ComponentFixture<CephfsListComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, HttpClientTestingModule],
+ declarations: [CephfsListComponent, CephfsDetailStubComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CephfsListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.ts
new file mode 100644
index 00000000..d58357d4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-list/cephfs-list.component.ts
@@ -0,0 +1,56 @@
+import { Component, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { CephfsService } from '../../../shared/api/cephfs.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-cephfs-list',
+ templateUrl: './cephfs-list.component.html',
+ styleUrls: ['./cephfs-list.component.scss']
+})
+export class CephfsListComponent implements OnInit {
+ columns: CdTableColumn[];
+ filesystems: any = [];
+ selection = new CdTableSelection();
+
+ constructor(private cephfsService: CephfsService, private i18n: I18n) {}
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'mdsmap.fs_name',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Created'),
+ prop: 'mdsmap.created',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Enabled'),
+ prop: 'mdsmap.enabled',
+ flexGrow: 1
+ }
+ ];
+ }
+
+ loadFilesystems(context: CdTableFetchDataContext) {
+ this.cephfsService.list().subscribe(
+ (resp: any[]) => {
+ this.filesystems = resp;
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts
new file mode 100644
index 00000000..c44dd6e8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { ChartsModule } from 'ng2-charts/ng2-charts';
+import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { AppRoutingModule } from '../../app-routing.module';
+import { SharedModule } from '../../shared/shared.module';
+import { CephfsChartComponent } from './cephfs-chart/cephfs-chart.component';
+import { CephfsClientsComponent } from './cephfs-clients/cephfs-clients.component';
+import { CephfsDetailComponent } from './cephfs-detail/cephfs-detail.component';
+import { CephfsListComponent } from './cephfs-list/cephfs-list.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ SharedModule,
+ AppRoutingModule,
+ ChartsModule,
+ ProgressbarModule.forRoot(),
+ TabsModule.forRoot()
+ ],
+ declarations: [
+ CephfsDetailComponent,
+ CephfsClientsComponent,
+ CephfsChartComponent,
+ CephfsListComponent
+ ]
+})
+export class CephfsModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts
new file mode 100644
index 00000000..11330561
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts
@@ -0,0 +1,98 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+
+import { TreeModule } from 'ng2-tree';
+import { AlertModule } from 'ngx-bootstrap/alert';
+import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TimepickerModule } from 'ngx-bootstrap/timepicker';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
+
+import { SharedModule } from '../../shared/shared.module';
+import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
+import { ConfigurationDetailsComponent } from './configuration/configuration-details/configuration-details.component';
+import { ConfigurationFormComponent } from './configuration/configuration-form/configuration-form.component';
+import { ConfigurationComponent } from './configuration/configuration.component';
+import { CrushmapComponent } from './crushmap/crushmap.component';
+import { HostDetailsComponent } from './hosts/host-details/host-details.component';
+import { HostsComponent } from './hosts/hosts.component';
+import { LogsComponent } from './logs/logs.component';
+import { MgrModulesModule } from './mgr-modules/mgr-modules.module';
+import { MonitorComponent } from './monitor/monitor.component';
+import { OsdDetailsComponent } from './osd/osd-details/osd-details.component';
+import { OsdFlagsModalComponent } from './osd/osd-flags-modal/osd-flags-modal.component';
+import { OsdListComponent } from './osd/osd-list/osd-list.component';
+import { OsdPerformanceHistogramComponent } from './osd/osd-performance-histogram/osd-performance-histogram.component';
+import { OsdPgScrubModalComponent } from './osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component';
+import { OsdRecvSpeedModalComponent } from './osd/osd-recv-speed-modal/osd-recv-speed-modal.component';
+import { OsdReweightModalComponent } from './osd/osd-reweight-modal/osd-reweight-modal.component';
+import { OsdScrubModalComponent } from './osd/osd-scrub-modal/osd-scrub-modal.component';
+import { ActiveAlertListComponent } from './prometheus/active-alert-list/active-alert-list.component';
+import { MonitoringListComponent } from './prometheus/monitoring-list/monitoring-list.component';
+import { RulesListComponent } from './prometheus/rules-list/rules-list.component';
+import { SilenceFormComponent } from './prometheus/silence-form/silence-form.component';
+import { SilenceListComponent } from './prometheus/silence-list/silence-list.component';
+import { SilenceMatcherModalComponent } from './prometheus/silence-matcher-modal/silence-matcher-modal.component';
+
+@NgModule({
+ entryComponents: [
+ OsdDetailsComponent,
+ OsdScrubModalComponent,
+ OsdFlagsModalComponent,
+ OsdRecvSpeedModalComponent,
+ OsdReweightModalComponent,
+ OsdPgScrubModalComponent,
+ OsdReweightModalComponent,
+ SilenceMatcherModalComponent
+ ],
+ imports: [
+ CommonModule,
+ PerformanceCounterModule,
+ TabsModule.forRoot(),
+ SharedModule,
+ RouterModule,
+ FormsModule,
+ ReactiveFormsModule,
+ BsDropdownModule.forRoot(),
+ BsDatepickerModule.forRoot(),
+ ModalModule.forRoot(),
+ AlertModule.forRoot(),
+ TooltipModule.forRoot(),
+ TreeModule,
+ MgrModulesModule,
+ TypeaheadModule.forRoot(),
+ TimepickerModule.forRoot(),
+ BsDatepickerModule.forRoot()
+ ],
+ declarations: [
+ HostsComponent,
+ MonitorComponent,
+ ConfigurationComponent,
+ OsdListComponent,
+ OsdDetailsComponent,
+ OsdPerformanceHistogramComponent,
+ OsdScrubModalComponent,
+ OsdFlagsModalComponent,
+ HostDetailsComponent,
+ ConfigurationDetailsComponent,
+ ConfigurationFormComponent,
+ OsdReweightModalComponent,
+ CrushmapComponent,
+ LogsComponent,
+ OsdRecvSpeedModalComponent,
+ OsdPgScrubModalComponent,
+ ActiveAlertListComponent,
+ OsdRecvSpeedModalComponent,
+ SilenceFormComponent,
+ SilenceListComponent,
+ SilenceMatcherModalComponent,
+ RulesListComponent,
+ MonitoringListComponent
+ ]
+})
+export class ClusterModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.html
new file mode 100755
index 00000000..b5776a7e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.html
@@ -0,0 +1,108 @@
+<tabset *ngIf="selection?.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Name</td>
+ <td class="col-sm-3">{{ selectedItem.name }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Description</td>
+ <td class="col-sm-3">{{ selectedItem.desc }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Long description</td>
+ <td class="col-sm-3">{{ selectedItem.long_desc }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Current values</td>
+ <td class="col-sm-3">
+ <span *ngFor="let conf of selectedItem.value; last as isLast">
+ {{ conf.section }}: {{ conf.value }}{{ !isLast ? "," : "" }}<br/>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Default</td>
+ <td class="col-sm-3">{{ selectedItem.default }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Daemon default</td>
+ <td class="col-sm-3">{{ selectedItem.daemon_default }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Type</td>
+ <td class="col-sm-3">{{ selectedItem.type }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Min</td>
+ <td class="col-sm-3">{{ selectedItem.min }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Max</td>
+ <td class="col-sm-3">{{ selectedItem.max }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Flags</td>
+ <td class="col-sm-3">
+ <span *ngFor="let flag of selectedItem.flags">
+ <span title="{{ flags[flag] }}">
+ <span class="badge badge-pill badge-primary margin-right-sm">{{ flag | uppercase }}</span>
+ </span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Services</td>
+ <td class="col-sm-3">
+ <span *ngFor="let service of selectedItem.services">
+ <span class="badge badge-pill badge-primary margin-right-sm">{{ service }}</span>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Source</td>
+ <td class="col-sm-3">{{ selectedItem.source }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Level</td>
+ <td class="col-sm-3">{{ selectedItem.level }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Can be updated at runtime (editable)</td>
+ <td class="col-sm-3">{{ selectedItem.can_update_at_runtime | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Tags</td>
+ <td class="col-sm-3">{{ selectedItem.tags }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Enum values</td>
+ <td class="col-sm-3">{{ selectedItem.enum_values }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">See also</td>
+ <td class="col-sm-3">{{ selectedItem.see_also }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.scss
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.spec.ts
new file mode 100755
index 00000000..8c50cb8f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.spec.ts
@@ -0,0 +1,29 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { DataTableModule } from '../../../../shared/datatable/datatable.module';
+import { SharedModule } from '../../../../shared/shared.module';
+import { ConfigurationDetailsComponent } from './configuration-details.component';
+
+describe('ConfigurationDetailsComponent', () => {
+ let component: ConfigurationDetailsComponent;
+ let fixture: ComponentFixture<ConfigurationDetailsComponent>;
+
+ configureTestBed({
+ declarations: [ConfigurationDetailsComponent],
+ imports: [DataTableModule, SharedModule, TabsModule.forRoot()],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfigurationDetailsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.ts
new file mode 100755
index 00000000..25876369
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-details/configuration-details.component.ts
@@ -0,0 +1,36 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-configuration-details',
+ templateUrl: './configuration-details.component.html',
+ styleUrls: ['./configuration-details.component.scss']
+})
+export class ConfigurationDetailsComponent implements OnChanges {
+ @Input()
+ selection: CdTableSelection;
+ selectedItem: any;
+ flags = {
+ runtime: this.i18n('The value can be updated at runtime.'),
+ no_mon_update: this.i18n(`Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.`),
+ startup: this.i18n('Option takes effect only during daemon startup.'),
+ cluster_create: this.i18n('Option only affects cluster creation.'),
+ create: this.i18n('Option only affects daemon creation.')
+ };
+
+ constructor(private i18n: I18n) {}
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+ this.selectedItem.services = _.split(this.selectedItem.services, ',');
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form-create-request.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form-create-request.model.ts
new file mode 100644
index 00000000..bca65a88
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form-create-request.model.ts
@@ -0,0 +1,4 @@
+export class ConfigFormCreateRequestModel {
+ name: string;
+ value: Array<any> = [];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.html
new file mode 100644
index 00000000..30acbc05
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.html
@@ -0,0 +1,168 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="configForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="configForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">
+ <ng-container i18n>Edit</ng-container> {{ configForm.getValue('name') }}
+ </h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Name -->
+ <div class="form-group">
+ <label i18n
+ class="control-label col-sm-3">Name</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="name"
+ formControlName="name"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Description -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('desc')">
+ <label i18n
+ class="control-label col-sm-3">Description</label>
+ <div class="col-sm-9">
+ <textarea class="form-control resize-vertical"
+ id="desc"
+ formControlName="desc"
+ readonly>
+ </textarea>
+ </div>
+ </div>
+
+ <!-- Long description -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('long_desc')">
+ <label i18n
+ class="control-label col-sm-3">Long description</label>
+ <div class="col-sm-9">
+ <textarea class="form-control resize-vertical"
+ id="long_desc"
+ formControlName="long_desc"
+ readonly>
+ </textarea>
+ </div>
+ </div>
+
+ <!-- Default -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('default') !== ''">
+ <label i18n
+ class="control-label col-sm-3">Default</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="default"
+ formControlName="default"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Daemon default -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('daemon_default') !== ''">
+ <label i18n
+ class="control-label col-sm-3">Daemon default</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="daemon_default"
+ formControlName="daemon_default"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Services -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('services').length > 0">
+ <label i18n
+ class="control-label col-sm-3">Services</label>
+ <div class="col-sm-9">
+ <span *ngFor="let service of configForm.getValue('services')"
+ class="form-component-badge">
+ <span class="badge badge-pill badge-primary">{{ service }}</span>
+ </span>
+ </div>
+ </div>
+
+ <!-- Values -->
+ <div class="col-sm-12"
+ formGroupName="values">
+ <h2 i18n
+ class="page-header">Values</h2>
+ <div class="row"
+ *ngFor="let section of availSections">
+ <div class="form-group"
+ *ngIf="type === 'bool'">
+ <label class="control-label col-sm-3"
+ [for]="section">{{ section }}
+ </label>
+ <div class="col-sm-9">
+ <select id="pool"
+ name="pool"
+ class="form-control custom-select"
+ [formControlName]="section">
+ <option [ngValue]="null"
+ i18n>-- Default --</option>
+ <option [ngValue]="true"
+ i18n>true</option>
+ <option [ngValue]="false"
+ i18n>false</option>
+ </select>
+ </div>
+ </div>
+ <div class="form-group"
+ [ngClass]="{'has-error': configForm.showError(section, formDir)}"
+ *ngIf="type !== 'bool'">
+ <label class="control-label col-sm-3"
+ [for]="section">{{ section }}
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ [type]="inputType"
+ [id]="section"
+ [placeholder]="humanReadableType"
+ [formControlName]="section"
+ [step]="getStep(type, this.configForm.getValue(section))">
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'pattern')">
+ {{ patternHelpText }}
+ </span>
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'invalidUuid')">
+ {{ patternHelpText }}
+ </span>
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'max')"
+ i18n>The entered value is too high! It must not be greater than {{ maxValue }}.</span>
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'min')"
+ i18n>The entered value is too low! It must not be lower than {{ minValue }}.</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Footer -->
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button [form]="formDir"
+ type="button"
+ (submitAction)="submit()">
+ <span i18n>Save</span>
+ </cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.scss
new file mode 100644
index 00000000..ae4c6ea4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.scss
@@ -0,0 +1,12 @@
+.form-component-badge {
+ height: 34px;
+ display: block;
+
+ span {
+ margin-top: 7px;
+ }
+}
+
+.resize-vertical {
+ resize: vertical;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts
new file mode 100644
index 00000000..070455fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts
@@ -0,0 +1,107 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { ConfigFormModel } from '../../../../shared/components/config-option/config-option.model';
+import { SharedModule } from '../../../../shared/shared.module';
+import { ConfigurationFormComponent } from './configuration-form.component';
+
+describe('ConfigurationFormComponent', () => {
+ let component: ConfigurationFormComponent;
+ let fixture: ComponentFixture<ConfigurationFormComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ ToastrModule.forRoot(),
+ SharedModule
+ ],
+ declarations: [ConfigurationFormComponent],
+ providers: [
+ {
+ provide: ActivatedRoute
+ },
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfigurationFormComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('getValidators', () => {
+ it('should return a validator for types float, addr and uuid', () => {
+ const types = ['float', 'addr', 'uuid'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(1);
+ });
+ });
+
+ it('should not return a validator for types str and bool', () => {
+ const types = ['str', 'bool'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeUndefined();
+ });
+ });
+
+ it('should return a pattern and a min validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int';
+ configOption.min = 2;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(2);
+ expect(component.minValue).toBe(2);
+ expect(component.maxValue).toBeUndefined();
+ });
+
+ it('should return a pattern and a max validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int';
+ configOption.max = 5;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(2);
+ expect(component.minValue).toBeUndefined();
+ expect(component.maxValue).toBe(5);
+ });
+
+ it('should return multiple validators', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'float';
+ configOption.max = 5.2;
+ configOption.min = 1.5;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(3);
+ expect(component.minValue).toBe(1.5);
+ expect(component.maxValue).toBe(5.2);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts
new file mode 100644
index 00000000..d17888d4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts
@@ -0,0 +1,173 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl, FormGroup, ValidatorFn } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
+import { ConfigFormModel } from '../../../../shared/components/config-option/config-option.model';
+import { ConfigOptionTypes } from '../../../../shared/components/config-option/config-option.types';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { ConfigFormCreateRequestModel } from './configuration-form-create-request.model';
+
+@Component({
+ selector: 'cd-configuration-form',
+ templateUrl: './configuration-form.component.html',
+ styleUrls: ['./configuration-form.component.scss']
+})
+export class ConfigurationFormComponent implements OnInit {
+ configForm: CdFormGroup;
+ response: ConfigFormModel;
+ type: string;
+ inputType: string;
+ humanReadableType: string;
+ minValue: number;
+ maxValue: number;
+ patternHelpText: string;
+ availSections = ['global', 'mon', 'mgr', 'osd', 'mds', 'client'];
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private configService: ConfigurationService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {
+ this.createForm();
+ }
+
+ createForm() {
+ const formControls = {
+ name: new FormControl({ value: null }),
+ desc: new FormControl({ value: null }),
+ long_desc: new FormControl({ value: null }),
+ values: new FormGroup({}),
+ default: new FormControl({ value: null }),
+ daemon_default: new FormControl({ value: null }),
+ services: new FormControl([])
+ };
+
+ this.availSections.forEach((section) => {
+ formControls.values.addControl(section, new FormControl(null));
+ });
+
+ this.configForm = new CdFormGroup(formControls);
+ }
+
+ ngOnInit() {
+ this.route.params.subscribe((params: { name: string }) => {
+ const configName = params.name;
+ this.configService.get(configName).subscribe((resp: ConfigFormModel) => {
+ this.setResponse(resp);
+ });
+ });
+ }
+
+ getValidators(configOption: any): ValidatorFn[] {
+ const typeValidators = ConfigOptionTypes.getTypeValidators(configOption);
+ if (typeValidators) {
+ this.patternHelpText = typeValidators.patternHelpText;
+
+ if ('max' in typeValidators && typeValidators.max !== '') {
+ this.maxValue = typeValidators.max;
+ }
+
+ if ('min' in typeValidators && typeValidators.min !== '') {
+ this.minValue = typeValidators.min;
+ }
+
+ return typeValidators.validators;
+ }
+ }
+
+ getStep(type: string, value: number): number | undefined {
+ return ConfigOptionTypes.getTypeStep(type, value);
+ }
+
+ setResponse(response: ConfigFormModel) {
+ this.response = response;
+ const validators = this.getValidators(response);
+
+ this.configForm.get('name').setValue(response.name);
+ this.configForm.get('desc').setValue(response.desc);
+ this.configForm.get('long_desc').setValue(response.long_desc);
+ this.configForm.get('default').setValue(response.default);
+ this.configForm.get('daemon_default').setValue(response.daemon_default);
+ this.configForm.get('services').setValue(response.services);
+
+ if (this.response.value) {
+ this.response.value.forEach((value) => {
+ // Check value type. If it's a boolean value we need to convert it because otherwise we
+ // would use the string representation. That would cause issues for e.g. checkboxes.
+ let sectionValue = null;
+ if (value.value === 'true') {
+ sectionValue = true;
+ } else if (value.value === 'false') {
+ sectionValue = false;
+ } else {
+ sectionValue = value.value;
+ }
+ this.configForm
+ .get('values')
+ .get(value.section)
+ .setValue(sectionValue);
+ });
+ }
+
+ this.availSections.forEach((section) => {
+ this.configForm
+ .get('values')
+ .get(section)
+ .setValidators(validators);
+ });
+
+ const currentType = ConfigOptionTypes.getType(response.type);
+ this.type = currentType.name;
+ this.inputType = currentType.inputType;
+ this.humanReadableType = currentType.humanReadable;
+ }
+
+ createRequest(): ConfigFormCreateRequestModel | null {
+ const values = [];
+
+ this.availSections.forEach((section) => {
+ const sectionValue = this.configForm.getValue(section);
+ if (sectionValue !== null && sectionValue !== '') {
+ values.push({ section: section, value: sectionValue });
+ }
+ });
+
+ if (!_.isEqual(this.response.value, values)) {
+ const request = new ConfigFormCreateRequestModel();
+ request.name = this.configForm.getValue('name');
+ request.value = values;
+ return request;
+ }
+
+ return null;
+ }
+
+ submit() {
+ const request = this.createRequest();
+
+ if (request) {
+ this.configService.create(request).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated config option {{name}}', { name: request.name })
+ );
+ this.router.navigate(['/configuration']);
+ },
+ () => {
+ this.configForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ this.router.navigate(['/configuration']);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.html
new file mode 100644
index 00000000..36d280ae
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.html
@@ -0,0 +1,39 @@
+<cd-table [data]="data | filter:filters"
+ (fetchData)="getConfigurationList($event)"
+ [columns]="columns"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <div class="table-filters">
+ <div class="form-group filter"
+ *ngFor="let filter of filters">
+ <label>{{ filter.label }}: </label>
+ <select class="form-control input-sm"
+ [(ngModel)]="filter.value"
+ (ngModelChange)="updateFilter()">
+ <option *ngFor="let opt of filter.options">{{ opt }}</option>
+ </select>
+ </div>
+ <a class="fa-stack"
+ title="Reset filters"
+ (click)="resetFilter()">
+ <i class="fa fa-filter fa-stack-2x"></i>
+ <i class="fa fa-times fa-stack-1x" style="margin-left: 8px; margin-top: 5px;"></i>
+ </a>
+ </div>
+ <cd-configuration-details cdTableDetail
+ [selection]="selection">
+ </cd-configuration-details>
+</cd-table>
+
+<ng-template #confValTpl let-value="value">
+ <span *ngIf="value">
+ <span *ngFor="let conf of value; last as isLast">
+ {{ conf.section }}: {{ conf.value }}{{ !isLast ? "," : "" }}<br/>
+ </span>
+ </span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.scss
new file mode 100644
index 00000000..19b14168
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.scss
@@ -0,0 +1,7 @@
+.filter {
+ padding-right: 8px;
+}
+
+::ng-deep datatable-body-cell.wrap {
+ word-break: break-all;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.spec.ts
new file mode 100644
index 00000000..b58ef58c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { ConfigurationDetailsComponent } from './configuration-details/configuration-details.component';
+import { ConfigurationComponent } from './configuration.component';
+
+describe('ConfigurationComponent', () => {
+ let component: ConfigurationComponent;
+ let fixture: ComponentFixture<ConfigurationComponent>;
+
+ configureTestBed({
+ declarations: [ConfigurationComponent, ConfigurationDetailsComponent],
+ imports: [
+ SharedModule,
+ FormsModule,
+ TabsModule.forRoot(),
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfigurationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.ts
new file mode 100644
index 00000000..82ea4b44
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration.component.ts
@@ -0,0 +1,157 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { ConfigurationService } from '../../../shared/api/configuration.service';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-configuration',
+ templateUrl: './configuration.component.html',
+ styleUrls: ['./configuration.component.scss']
+})
+export class ConfigurationComponent implements OnInit {
+ permission: Permission;
+ tableActions: CdTableAction[];
+ data = [];
+ columns: CdTableColumn[];
+ selection = new CdTableSelection();
+ filters = [
+ {
+ label: this.i18n('Level'),
+ prop: 'level',
+ initValue: 'basic',
+ value: 'basic',
+ options: ['basic', 'advanced', 'dev'],
+ applyFilter: (row, value) => {
+ enum Level {
+ basic = 0,
+ advanced = 1,
+ dev = 2
+ }
+
+ const levelVal = Level[value];
+
+ return Level[row.level] <= levelVal;
+ }
+ },
+ {
+ label: this.i18n('Service'),
+ prop: 'services',
+ initValue: 'any',
+ value: 'any',
+ options: ['any', 'mon', 'mgr', 'osd', 'mds', 'common', 'mds_client', 'rgw'],
+ applyFilter: (row, value) => {
+ if (value === 'any') {
+ return true;
+ }
+
+ return row.services.includes(value);
+ }
+ },
+ {
+ label: this.i18n('Source'),
+ prop: 'source',
+ initValue: 'any',
+ value: 'any',
+ options: ['any', 'mon'],
+ applyFilter: (row, value) => {
+ if (value === 'any') {
+ return true;
+ }
+
+ if (!row.hasOwnProperty('source')) {
+ return false;
+ }
+
+ return row.source.includes(value);
+ }
+ }
+ ];
+
+ @ViewChild('confValTpl')
+ public confValTpl: TemplateRef<any>;
+ @ViewChild('confFlagTpl')
+ public confFlagTpl: TemplateRef<any>;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private configurationService: ConfigurationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().configOpt;
+ const getConfigOptUri = () =>
+ this.selection.first() && `${encodeURIComponent(this.selection.first().name)}`;
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => `/configuration/edit/${getConfigOptUri()}`,
+ name: this.actionLabels.EDIT,
+ disable: () => !this.isEditable(this.selection)
+ };
+ this.tableActions = [editAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ { canAutoResize: true, prop: 'name', name: this.i18n('Name') },
+ { prop: 'desc', name: this.i18n('Description'), cellClass: 'wrap' },
+ {
+ prop: 'value',
+ name: this.i18n('Current value'),
+ cellClass: 'wrap',
+ cellTemplate: this.confValTpl
+ },
+ { prop: 'default', name: this.i18n('Default'), cellClass: 'wrap' },
+ {
+ prop: 'can_update_at_runtime',
+ name: this.i18n('Editable'),
+ cellTransformation: CellTemplate.checkIcon,
+ flexGrow: 0.4,
+ cellClass: 'text-center'
+ }
+ ];
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ getConfigurationList(context: CdTableFetchDataContext) {
+ this.configurationService.getConfigData().subscribe(
+ (data: any) => {
+ this.data = data;
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateFilter() {
+ this.data = [...this.data];
+ }
+
+ resetFilter() {
+ this.filters.forEach((item) => {
+ item.value = item.initValue;
+ });
+ this.data = [...this.data];
+ }
+
+ isEditable(selection: CdTableSelection): boolean {
+ if (selection.selected.length !== 1) {
+ return false;
+ }
+
+ return selection.selected[0].can_update_at_runtime;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.html
new file mode 100644
index 00000000..4de89afb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.html
@@ -0,0 +1,29 @@
+<div class="row">
+ <div class="col-sm-12 col-lg-12">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">
+ <span i18n>CRUSH map viewer</span>
+ </h3>
+ </div>
+ <div class="panel-body">
+ <div class="col-sm-6 col-lg-6">
+ <tree [tree]="tree"
+ [settings]="{rootIsVisible: false}"
+ (nodeSelected)="onNodeSelected($event)">
+ <ng-template let-node>
+ <span class="label"
+ [ngClass]="{'label-success': ['in', 'up'].includes(node.status), 'label-danger': ['down', 'out', 'destroyed'].includes(node.status)}">{{ node.status }}</span>
+ <span>&nbsp;</span>
+ <span class="node-name" [innerHTML]="node.value"></span>
+ </ng-template>
+ </tree>
+ </div>
+ <div class="col-sm-6 col-lg-6 metadata" *ngIf="metadata">
+ <legend>{{ metadataTitle }}</legend>
+ <cd-table-key-value [data]="metadata"></cd-table-key-value>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.scss
new file mode 100644
index 00000000..65c94d50
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.scss
@@ -0,0 +1,21 @@
+::ng-deep tree-internal .tree li {
+ cursor: pointer;
+}
+
+::ng-deep tree-internal .tree .node-value {
+ color: #2b99a8;
+ border-radius: 5px;
+}
+
+::ng-deep tree-internal .tree .node-selected {
+ background-color: #d9edf7;
+ color: #212121;
+}
+
+::ng-deep tree-internal .tree .node-value:hover {
+ color: #212121;
+}
+
+::ng-deep tree-internal .tree .node-value:after {
+ height: 0;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.spec.ts
new file mode 100644
index 00000000..2e6e458a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.spec.ts
@@ -0,0 +1,151 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TreeModule } from 'ng2-tree';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { of } from 'rxjs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { HealthService } from '../../../shared/api/health.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { CrushmapComponent } from './crushmap.component';
+
+describe('CrushmapComponent', () => {
+ let component: CrushmapComponent;
+ let fixture: ComponentFixture<CrushmapComponent>;
+ let debugElement: DebugElement;
+ configureTestBed({
+ imports: [HttpClientTestingModule, TreeModule, TabsModule.forRoot(), SharedModule],
+ declarations: [CrushmapComponent],
+ providers: [HealthService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CrushmapComponent);
+ component = fixture.componentInstance;
+ debugElement = fixture.debugElement;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should display right title', () => {
+ fixture.detectChanges();
+ const span = debugElement.nativeElement.querySelector('span');
+ expect(span.textContent).toBe('CRUSH map viewer');
+ });
+
+ describe('test tree', () => {
+ let healthService: HealthService;
+ const prepareGetHealth = (nodes: object[]) => {
+ spyOn(healthService, 'getFullHealth').and.returnValue(
+ of({ osd_map: { tree: { nodes: nodes } } })
+ );
+ fixture.detectChanges();
+ };
+
+ beforeEach(() => {
+ healthService = debugElement.injector.get(HealthService);
+ });
+
+ it('should display "No nodes!" if ceph tree nodes is empty array', () => {
+ prepareGetHealth([]);
+ expect(healthService.getFullHealth).toHaveBeenCalled();
+ expect(component.tree.value).toEqual('No nodes!');
+ });
+
+ describe('nodes not empty', () => {
+ beforeEach(() => {
+ prepareGetHealth([
+ { children: [-2], type: 'root', name: 'default', id: -1 },
+ { children: [1, 0, 2], type: 'host', name: 'my-host', id: -2 },
+ { status: 'up', type: 'osd', name: 'osd.0', id: 0 },
+ { status: 'down', type: 'osd', name: 'osd.1', id: 1 },
+ { status: 'up', type: 'osd', name: 'osd.2', id: 2 },
+ { children: [-4], type: 'root', name: 'default-2', id: -3 },
+ { children: [4], type: 'host', name: 'my-host-2', id: -4 },
+ { status: 'up', type: 'osd', name: 'osd.0-2', id: 4 }
+ ]);
+ });
+
+ it('should have two root nodes', () => {
+ expect(component.tree.children).toEqual([
+ {
+ children: [
+ {
+ children: [
+ {
+ id: 4,
+ settings: {
+ static: true
+ },
+ status: 'up',
+ value: 'osd.0-2 (osd)'
+ }
+ ],
+ id: -4,
+ settings: {
+ static: true
+ },
+ status: undefined,
+ value: 'my-host-2 (host)'
+ }
+ ],
+ id: -3,
+ settings: {
+ static: true
+ },
+ status: undefined,
+ value: 'default-2 (root)'
+ },
+ {
+ children: [
+ {
+ children: [
+ {
+ id: 0,
+ settings: {
+ static: true
+ },
+ status: 'up',
+ value: 'osd.0 (osd)'
+ },
+ {
+ id: 1,
+ settings: {
+ static: true
+ },
+ status: 'down',
+ value: 'osd.1 (osd)'
+ },
+ {
+ id: 2,
+ settings: {
+ static: true
+ },
+ status: 'up',
+ value: 'osd.2 (osd)'
+ }
+ ],
+ id: -2,
+ settings: {
+ static: true
+ },
+ status: undefined,
+ value: 'my-host (host)'
+ }
+ ],
+ id: -1,
+ settings: {
+ static: true
+ },
+ status: undefined,
+ value: 'default (root)'
+ }
+ ]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.ts
new file mode 100644
index 00000000..37b56b52
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/crushmap/crushmap.component.ts
@@ -0,0 +1,80 @@
+import { Component, OnInit } from '@angular/core';
+
+import { NodeEvent, TreeModel } from 'ng2-tree';
+
+import { HealthService } from '../../../shared/api/health.service';
+
+@Component({
+ selector: 'cd-crushmap',
+ templateUrl: './crushmap.component.html',
+ styleUrls: ['./crushmap.component.scss']
+})
+export class CrushmapComponent implements OnInit {
+ tree: TreeModel;
+ metadata: any;
+ metadataTitle: string;
+ metadataKeyMap: { [key: number]: number } = {};
+
+ constructor(private healthService: HealthService) {}
+
+ ngOnInit() {
+ this.healthService.getFullHealth().subscribe((data: any) => {
+ this.tree = this._abstractTreeData(data);
+ });
+ }
+
+ _abstractTreeData(data: any): TreeModel {
+ const nodes = data.osd_map.tree.nodes || [];
+ const treeNodeMap: { [key: number]: any } = {};
+
+ if (0 === nodes.length) {
+ return {
+ value: 'No nodes!',
+ settings: { static: true }
+ };
+ }
+
+ const roots = [];
+ nodes.reverse().forEach((node) => {
+ if (node.type === 'root') {
+ roots.push(node.id);
+ }
+ treeNodeMap[node.id] = this.generateTreeLeaf(node, treeNodeMap);
+ });
+
+ const children = roots.map((id) => {
+ return treeNodeMap[id];
+ });
+
+ return {
+ value: 'CRUSH map',
+ children: children
+ };
+ }
+
+ private generateTreeLeaf(node: any, treeNodeMap) {
+ const id = node.id;
+ this.metadataKeyMap[id] = node;
+ const settings = { static: true };
+
+ const value: string = node.name + ' (' + node.type + ')';
+ const status: string = node.status;
+
+ const children: any[] = [];
+ if (node.children) {
+ node.children.sort().forEach((childId) => {
+ children.push(treeNodeMap[childId]);
+ });
+
+ return { value, status, settings, id, children };
+ }
+
+ return { value, status, settings, id };
+ }
+
+ onNodeSelected(e: NodeEvent) {
+ const { name, type, status, ...remain } = this.metadataKeyMap[e.node.id];
+ this.metadata = remain;
+ this.metadataTitle = name + ' (' + type + ')';
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html
new file mode 100644
index 00000000..005a8749
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html
@@ -0,0 +1,9 @@
+<tabset *ngIf="selection.hasSingleSelection && grafanaPermission.read">
+ <tab i18n-heading
+ heading="Performance Details">
+ <cd-grafana [grafanaPath]="'host-details?var-ceph_hosts=' + host['hostname']"
+ uid="rtOg0AiWz"
+ grafanaStyle="three">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.spec.ts
new file mode 100644
index 00000000..0a37e609
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed } from '../../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../../shared/shared.module';
+import { HostDetailsComponent } from './host-details.component';
+
+describe('HostDetailsComponent', () => {
+ let component: HostDetailsComponent;
+ let fixture: ComponentFixture<HostDetailsComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ SharedModule
+ ],
+ declarations: [HostDetailsComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HostDetailsComponent);
+ component = fixture.componentInstance;
+
+ component.selection = new CdTableSelection();
+
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.ts
new file mode 100644
index 00000000..dfd3c16f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.ts
@@ -0,0 +1,27 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-host-details',
+ templateUrl: './host-details.component.html',
+ styleUrls: ['./host-details.component.scss']
+})
+export class HostDetailsComponent implements OnChanges {
+ grafanaPermission: Permission;
+ @Input()
+ selection: CdTableSelection;
+ host: any;
+
+ constructor(private authStorageService: AuthStorageService) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.host = this.selection.first();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html
new file mode 100644
index 00000000..39dcedb3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html
@@ -0,0 +1,35 @@
+<tabset>
+ <tab i18n-heading
+ heading="Hosts List">
+ <cd-table [data]="hosts"
+ [columns]="columns"
+ columnMode="flex"
+ (fetchData)="getHosts($event)"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <ng-template #servicesTpl let-value="value">
+ <span *ngFor="let service of value; last as isLast">
+ <a [routerLink]="[service.cdLink]"
+ [queryParams]="cdParams"
+ *ngIf="service.canRead">{{ service.type }}.{{ service.id }}
+ </a>
+ <span *ngIf="!service.canRead">
+ {{ service.type }}.{{ service.id }}
+ </span>
+ {{ !isLast ? ", " : "" }}
+ </span>
+ </ng-template>
+ <cd-host-details cdTableDetail
+ [selection]="selection">
+ </cd-host-details>
+ </cd-table>
+ </tab>
+ <tab i18n-heading
+ *ngIf="permissions.grafana.read"
+ heading="Overall Performance">
+ <cd-grafana [grafanaPath]="'host-overview?'"
+ uid="y0KGL0iZz"
+ grafanaStyle="two">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts
new file mode 100644
index 00000000..d1264d52
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts
@@ -0,0 +1,84 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { HostService } from '../../../shared/api/host.service';
+import { Permissions } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { HostDetailsComponent } from './host-details/host-details.component';
+import { HostsComponent } from './hosts.component';
+
+describe('HostsComponent', () => {
+ let component: HostsComponent;
+ let fixture: ComponentFixture<HostsComponent>;
+ let hostListSpy;
+
+ const fakeAuthStorageService = {
+ getPermissions: () => {
+ return new Permissions({ hosts: ['read', 'update', 'create', 'delete'] });
+ }
+ };
+
+ configureTestBed({
+ imports: [
+ SharedModule,
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ RouterTestingModule
+ ],
+ providers: [{ provide: AuthStorageService, useValue: fakeAuthStorageService }, i18nProviders],
+ declarations: [HostsComponent, HostDetailsComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HostsComponent);
+ component = fixture.componentInstance;
+ hostListSpy = spyOn(TestBed.get(HostService), 'list');
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should render hosts list even with not permission mapped services', async(() => {
+ const hostname = 'ceph.dev';
+ const payload = [
+ {
+ services: [
+ {
+ type: 'osd',
+ id: '0'
+ },
+ {
+ type: 'rgw',
+ id: 'rgw'
+ },
+ {
+ type: 'notPermissionMappedService',
+ id: '1'
+ }
+ ],
+ hostname: hostname,
+ ceph_version: 'ceph version Development'
+ }
+ ];
+
+ hostListSpy.and.returnValue(Promise.resolve(payload));
+
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+
+ const spans = fixture.debugElement.nativeElement.querySelectorAll(
+ '.datatable-body-cell-label span'
+ );
+ expect(spans[0].textContent).toBe(hostname);
+ });
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts
new file mode 100644
index 00000000..fa107253
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts
@@ -0,0 +1,98 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { HostService } from '../../../shared/api/host.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../shared/models/permissions';
+import { CephShortVersionPipe } from '../../../shared/pipes/ceph-short-version.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-hosts',
+ templateUrl: './hosts.component.html',
+ styleUrls: ['./hosts.component.scss']
+})
+export class HostsComponent implements OnInit {
+ permissions: Permissions;
+ columns: Array<CdTableColumn> = [];
+ hosts: Array<object> = [];
+ isLoadingHosts = false;
+ cdParams = { fromLink: '/hosts' };
+ selection = new CdTableSelection();
+
+ @ViewChild('servicesTpl')
+ public servicesTpl: TemplateRef<any>;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private hostService: HostService,
+ private cephShortVersionPipe: CephShortVersionPipe,
+ private i18n: I18n
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Hostname'),
+ prop: 'hostname',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Services'),
+ prop: 'services',
+ flexGrow: 3,
+ cellTemplate: this.servicesTpl
+ },
+ {
+ name: this.i18n('Version'),
+ prop: 'ceph_version',
+ flexGrow: 1,
+ pipe: this.cephShortVersionPipe
+ }
+ ];
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ getHosts(context: CdTableFetchDataContext) {
+ if (this.isLoadingHosts) {
+ return;
+ }
+ const typeToPermissionKey = {
+ mds: 'cephfs',
+ mon: 'monitor',
+ osd: 'osd',
+ rgw: 'rgw',
+ 'rbd-mirror': 'rbdMirroring',
+ mgr: 'manager',
+ 'tcmu-runner': 'iscsi'
+ };
+ this.isLoadingHosts = true;
+ this.hostService
+ .list()
+ .then((resp) => {
+ resp.map((host) => {
+ host.services.map((service) => {
+ service.cdLink = `/perf_counters/${service.type}/${encodeURIComponent(service.id)}`;
+ const permission = this.permissions[typeToPermissionKey[service.type]];
+ service.canRead = permission ? permission.read : false;
+ return service;
+ });
+ return host;
+ });
+ this.hosts = resp;
+ this.isLoadingHosts = false;
+ })
+ .catch(() => {
+ this.isLoadingHosts = false;
+ context.error();
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html
new file mode 100644
index 00000000..a2c7d238
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.html
@@ -0,0 +1,107 @@
+<div *ngIf="contentData">
+<ng-container *ngTemplateOutlet="logFiltersTpl"></ng-container>
+<tabset>
+ <tab i18n-heading
+ heading="Cluster Logs">
+ <div class="well">
+ <div *ngIf="clog">
+ <p *ngFor="let line of clog">
+ <span class="timestamp">{{ line.stamp }}</span>
+ <span class="priority {{ line.priority | logPriority }}">{{ line.priority }}</span>
+ <span class="message">{{ line.message }}</span>
+ </p>
+ </div>
+ <div *ngIf="contentData.clog.length === 0">
+ <p i18n>No entries found</p>
+ </div>
+ </div>
+ </tab>
+
+ <tab i18n-heading
+ heading="Audit Logs">
+ <div class="well">
+ <div *ngIf="audit_log">
+ <p *ngFor="let line of audit_log">
+ <span class="timestamp">{{ line.stamp }}</span>
+ <span class="priority {{ line.priority | logPriority }}">{{ line.priority }}</span>
+ <span class="message">{{ line.message }}</span>
+ </p>
+ </div>
+ <div *ngIf="contentData.audit_log.length === 0">
+ <p i18n>No entries found</p>
+ </div>
+ </div>
+ </tab>
+</tabset>
+</div>
+
+<ng-template #logFiltersTpl>
+ <div class="row log-filters">
+ <div class="col-xs-4 col-md-2 cd-col-1 filter-box">
+ <label i18n>Priority:</label>
+ <select class="form-control"
+ [(ngModel)]="priority"
+ (ngModelChange)="filterLogs()">
+ <option class="form-control"
+ *ngFor="let prio of prioritys"
+ [value]="prio.value">{{ prio.name }}</option>
+ </select>
+ </div>
+ <div class="col-xs-4 col-md-3 cd-col-3 filter-box">
+ <label i18n>Keyword:</label>
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="glyphicon glyphicon-search"></i>
+ </span>
+ <input class="form-control"
+ type="text"
+ [(ngModel)]="search"
+ (keyup)="filterLogs()">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default clear-input tc_clearInputBtn"
+ (click)="clearSearchKey()">
+ <i class="icon-prepend fa fa-remove"></i>
+ </button>
+ </span>
+ </div>
+ </div>
+ <div class="col-xs-4 col-md-3 cd-col-2 filter-box">
+ <label i18n>Date:</label>
+ <div class="input-group">
+ <input type="text"
+ class="form-control"
+ i18n-placeholder
+ placeholder="Datepicker"
+ [bsConfig]="bsConfig"
+ bsDatepicker
+ [(ngModel)]="selectedDate"
+ (ngModelChange)="filterLogs()">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default clear-input tc_clearInputBtn"
+ (click)="clearDate()">
+ <i class="icon-prepend fa fa-remove"></i>
+ </button>
+ </span>
+ </div>
+ </div>
+ <div class="clearfix visible-xs-block"></div>
+ <div class="col-xs-8 col-md-4 cd-col-4 filter-box time-box">
+ <label i18n>Time range:</label>
+ <timepicker [showMeridian]="false"
+ [showSpinners]="showSpinners"
+ [minuteStep]="1"
+ [(ngModel)]="startTime"
+ (ngModelChange)="filterLogs()">
+ </timepicker>
+ <span>&nbsp;&mdash;&nbsp;</span>
+ <timepicker [showMeridian]="false"
+ [showSpinners]="showSpinners"
+ [minuteStep]="1"
+ [(ngModel)]="endTime"
+ (ngModelChange)="filterLogs()">
+ </timepicker>
+ </div>
+ </div>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss
new file mode 100644
index 00000000..8c91d4ad
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.scss
@@ -0,0 +1,143 @@
+@import '../../../../defaults';
+
+p {
+ font-family: monospace;
+ color: black;
+}
+
+.well {
+ div p {
+ display: flex;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .timestamp {
+ font-weight: bold;
+ flex-shrink: 0;
+ }
+
+ .priority {
+ margin-left: 0.5rem;
+ }
+
+ .message {
+ margin-left: 1rem;
+ }
+
+ .err {
+ color: $color-pink;
+ }
+
+ .warn {
+ color: $color-bright-yellow;
+ }
+
+ .info {
+ color: $color-brand-teal;
+ }
+}
+
+::ng-deep timepicker table tbody tr td {
+ .bs-timepicker-field {
+ width: 3.5rem;
+ font-size: 1rem;
+ padding: 4px 6px;
+ }
+ .btn {
+ font-size: 1rem;
+ }
+}
+
+.log-filters {
+ margin-bottom: 5px;
+ padding: 0 30px;
+ * {
+ box-sizing: border-box;
+ }
+
+ .filter-box {
+ margin: 0;
+ padding: 0 15px 5px 0;
+ display: -webkit-flex;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ label {
+ padding-top: 5px;
+ padding-right: 5px;
+ }
+ }
+
+ @media (max-width: 991px) {
+ .time-box {
+ margin-top: 20px;
+ }
+ }
+
+ @media (min-width: 1200px) {
+ .cd-col-4 {
+ width: 28vw;
+ }
+
+ .cd-col-3 {
+ width: 20vw;
+ }
+
+ .cd-col-2 {
+ width: 16vw;
+ }
+ .cd-col-1 {
+ width: 14vw;
+ }
+ }
+
+ @media (min-width: 1400px) {
+ .cd-col-4 {
+ width: 24vw;
+ }
+
+ .cd-col-3 {
+ width: 18vw;
+ }
+
+ .cd-col-2 {
+ width: 14vw;
+ }
+ .cd-col-1 {
+ width: 12vw;
+ }
+ }
+
+ @media (min-width: 1600px) {
+ .cd-col-4 {
+ width: 22vw;
+ }
+
+ .cd-col-3 {
+ width: 16vw;
+ }
+
+ .cd-col-2 {
+ width: 12vw;
+ }
+ .cd-col-1 {
+ width: 10vw;
+ }
+ }
+
+ @media (min-width: 1800px) {
+ .cd-col-3 {
+ width: 14vw;
+ }
+
+ .cd-col-2 {
+ width: 11vw;
+ }
+ .cd-col-1 {
+ width: 9vw;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.spec.ts
new file mode 100644
index 00000000..8b4436cc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.spec.ts
@@ -0,0 +1,138 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+
+import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TimepickerModule } from 'ngx-bootstrap/timepicker';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { LogsComponent } from './logs.component';
+
+describe('LogsComponent', () => {
+ let component: LogsComponent;
+ let fixture: ComponentFixture<LogsComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ SharedModule,
+ BsDatepickerModule.forRoot(),
+ TimepickerModule.forRoot(),
+ FormsModule
+ ],
+ declarations: [LogsComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LogsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('abstractfilters', () => {
+ it('after initializaed', () => {
+ const filters = component.abstractfilters();
+ expect(filters.priority).toBe('All');
+ expect(filters.key).toBe('');
+ expect(filters.yearMonthDay).toBe('');
+ expect(filters.sTime).toBe(0);
+ expect(filters.eTime).toBe(1439);
+ });
+ it('change date', () => {
+ component.selectedDate = new Date(2019, 0, 1);
+ component.startTime = new Date(2019, 1, 1, 1, 10);
+ component.endTime = new Date(2019, 1, 1, 12, 10);
+ const filters = component.abstractfilters();
+ expect(filters.yearMonthDay).toBe('2019-01-01');
+ expect(filters.sTime).toBe(70);
+ expect(filters.eTime).toBe(730);
+ });
+ });
+
+ describe('filterLogs', () => {
+ const contentData = {
+ clog: [
+ {
+ name: 'priority',
+ stamp: '2019-02-21 09:39:49.572801',
+ message: 'Manager daemon localhost is now available',
+ priority: '[ERR]'
+ },
+ {
+ name: 'search',
+ stamp: '2019-02-21 09:39:49.572801',
+ message: 'Activating manager daemon localhost',
+ priority: '[INF]'
+ },
+ {
+ name: 'date',
+ stamp: '2019-01-21 09:39:49.572801',
+ message: 'Manager daemon localhost is now available',
+ priority: '[INF]'
+ },
+ {
+ name: 'time',
+ stamp: '2019-02-21 01:39:49.572801',
+ message: 'Manager daemon localhost is now available',
+ priority: '[INF]'
+ }
+ ],
+ audit_log: []
+ };
+ const resetFilter = () => {
+ component.selectedDate = null;
+ component.priority = 'All';
+ component.search = '';
+ component.startTime.setHours(0, 0);
+ component.endTime.setHours(23, 59);
+ };
+ beforeEach(() => {
+ component.contentData = contentData;
+ });
+
+ it('show all log', () => {
+ component.filterLogs();
+ expect(component.clog.length).toBe(4);
+ });
+
+ it('filter by search key', () => {
+ resetFilter();
+ component.search = 'Activating';
+ component.filterLogs();
+ expect(component.clog.length).toBe(1);
+ expect(component.clog[0].name).toBe('search');
+ });
+
+ it('filter by date', () => {
+ resetFilter();
+ component.selectedDate = new Date(2019, 0, 21);
+ component.filterLogs();
+ expect(component.clog.length).toBe(1);
+ expect(component.clog[0].name).toBe('date');
+ });
+
+ it('filter by priority', () => {
+ resetFilter();
+ component.priority = '[ERR]';
+ component.filterLogs();
+ expect(component.clog.length).toBe(1);
+ expect(component.clog[0].name).toBe('priority');
+ });
+
+ it('filter by time range', () => {
+ resetFilter();
+ component.startTime.setHours(1, 0);
+ component.endTime.setHours(2, 0);
+ component.filterLogs();
+ expect(component.clog.length).toBe(1);
+ expect(component.clog[0].name).toBe('time');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts
new file mode 100644
index 00000000..cd20503c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/logs/logs.component.ts
@@ -0,0 +1,115 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+import { LogsService } from '../../../shared/api/logs.service';
+
+@Component({
+ selector: 'cd-logs',
+ templateUrl: './logs.component.html',
+ styleUrls: ['./logs.component.scss']
+})
+export class LogsComponent implements OnInit, OnDestroy {
+ contentData: any;
+ clog: Array<any>;
+ audit_log: Array<any>;
+
+ interval: number;
+ bsConfig = {
+ dateInputFormat: 'YYYY-MM-DD',
+ containerClass: 'theme-default'
+ };
+ prioritys: Array<{ name: string; value: string }> = [
+ { name: 'Info', value: '[INF]' },
+ { name: 'Warning', value: '[WRN]' },
+ { name: 'Error', value: '[ERR]' },
+ { name: 'All', value: 'All' }
+ ];
+ priority = 'All';
+ search = '';
+ selectedDate: Date;
+ startTime: Date = new Date();
+ endTime: Date = new Date();
+ constructor(private logsService: LogsService) {
+ this.startTime.setHours(0, 0);
+ this.endTime.setHours(23, 59);
+ }
+
+ ngOnInit() {
+ this.getInfo();
+ this.interval = window.setInterval(() => {
+ this.getInfo();
+ }, 5000);
+ }
+
+ ngOnDestroy() {
+ clearInterval(this.interval);
+ }
+
+ getInfo() {
+ this.logsService.getLogs().subscribe((data: any) => {
+ this.contentData = data;
+ this.filterLogs();
+ });
+ }
+
+ abstractfilters(): any {
+ const priority = this.priority;
+ const key = this.search.toLowerCase().replace(/,/g, '');
+
+ let yearMonthDay: string;
+ if (this.selectedDate) {
+ const m = this.selectedDate.getMonth() + 1;
+ const d = this.selectedDate.getDate();
+
+ const year = this.selectedDate.getFullYear().toString();
+ const month = m <= 9 ? `0${m}` : `${m}`;
+ const day = d <= 9 ? `0${d}` : `${d}`;
+ yearMonthDay = `${year}-${month}-${day}`;
+ } else {
+ yearMonthDay = '';
+ }
+
+ const sHour = this.startTime ? this.startTime.getHours() : 0;
+ const sMinutes = this.startTime ? this.startTime.getMinutes() : 0;
+ const sTime = sHour * 60 + sMinutes;
+
+ const eHour = this.endTime ? this.endTime.getHours() : 23;
+ const eMinutes = this.endTime ? this.endTime.getMinutes() : 59;
+ const eTime = eHour * 60 + eMinutes;
+
+ return { priority, key, yearMonthDay, sTime, eTime };
+ }
+
+ filterExecutor(logs: Array<any>, filters: any): Array<any> {
+ return logs.filter((line) => {
+ const hour = parseInt(line.stamp.slice(11, 13), 10);
+ const minutes = parseInt(line.stamp.slice(14, 16), 10);
+ let prio: string, y_m_d: string, timeSpan: number;
+
+ prio = filters.priority === 'All' ? line.priority : filters.priority;
+ y_m_d = filters.yearMonthDay ? filters.yearMonthDay : line.stamp;
+ timeSpan = hour * 60 + minutes;
+ return (
+ line.priority === prio &&
+ line.message.toLowerCase().indexOf(filters.key) !== -1 &&
+ line.stamp.indexOf(y_m_d) !== -1 &&
+ timeSpan >= filters.sTime &&
+ timeSpan <= filters.eTime
+ );
+ });
+ }
+
+ filterLogs() {
+ const filters = this.abstractfilters();
+ this.clog = this.filterExecutor(this.contentData.clog, filters);
+ this.audit_log = this.filterExecutor(this.contentData.audit_log, filters);
+ }
+
+ clearSearchKey() {
+ this.search = '';
+ this.filterLogs();
+ }
+ clearDate() {
+ this.selectedDate = null;
+ this.filterLogs();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.html
new file mode 100644
index 00000000..f1a54892
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.html
@@ -0,0 +1,6 @@
+<tabset *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading heading="Details">
+ <cd-table-key-value [data]="module_config">
+ </cd-table-key-value>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.spec.ts
new file mode 100644
index 00000000..23668340
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.spec.ts
@@ -0,0 +1,31 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MgrModuleDetailsComponent } from './mgr-module-details.component';
+
+describe('MgrModuleDetailsComponent', () => {
+ let component: MgrModuleDetailsComponent;
+ let fixture: ComponentFixture<MgrModuleDetailsComponent>;
+
+ configureTestBed({
+ declarations: [MgrModuleDetailsComponent],
+ imports: [HttpClientTestingModule, SharedModule, TabsModule.forRoot()],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MgrModuleDetailsComponent);
+ component = fixture.componentInstance;
+ component.selection = new CdTableSelection();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.ts
new file mode 100644
index 00000000..dd166779
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-details/mgr-module-details.component.ts
@@ -0,0 +1,27 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-mgr-module-details',
+ templateUrl: './mgr-module-details.component.html',
+ styleUrls: ['./mgr-module-details.component.scss']
+})
+export class MgrModuleDetailsComponent implements OnChanges {
+ module_config: any;
+
+ @Input()
+ selection: CdTableSelection;
+
+ constructor(private mgrModuleService: MgrModuleService) {}
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ const selectedItem = this.selection.first();
+ this.mgrModuleService.getConfig(selectedItem.name).subscribe((resp: any) => {
+ this.module_config = resp;
+ });
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.html
new file mode 100644
index 00000000..1854e37f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.html
@@ -0,0 +1,123 @@
+<cd-loading-panel *ngIf="loading && !error"
+ i18n>Loading configuration...</cd-loading-panel>
+<cd-error-panel *ngIf="loading && error"
+ i18n>The configuration could not be loaded.</cd-error-panel>
+
+<div class="col-sm-12 col-lg-6"
+ *ngIf="!loading && !error">
+ <form name="mgrModuleForm"
+ class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="mgrModuleForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title" i18n>Edit Manager module</h3>
+ </div>
+ <div class="panel-body">
+ <div class="form-group"
+ [ngClass]="{'has-error': mgrModuleForm.showError(moduleOption.value.name, frm)}"
+ *ngFor="let moduleOption of moduleOptions | keyvalue">
+
+ <!-- Field label -->
+ <label class="control-label col-sm-3"
+ for="{{ moduleOption.value.name }}">
+ {{ moduleOption.value.name }}
+ <cd-helper *ngIf="moduleOption.value.long_desc || moduleOption.value.desc">
+ {{ moduleOption.value.long_desc || moduleOption.value.desc | upperFirst }}
+ </cd-helper>
+ </label>
+
+ <!-- Field control -->
+ <!-- bool -->
+ <div class="col-sm-7"
+ *ngIf="moduleOption.value.type === 'bool'">
+ <div class="checkbox checkbox-primary">
+ <input id="{{ moduleOption.value.name }}"
+ type="checkbox"
+ formControlName="{{ moduleOption.value.name }}">
+ <label for="{{ moduleOption.value.name }}"></label>
+ </div>
+ </div>
+
+ <!-- addr|str|uuid -->
+ <div class="col-sm-7"
+ *ngIf="['addr', 'str', 'uuid'].includes(moduleOption.value.type)">
+ <input id="{{ moduleOption.value.name }}"
+ class="form-control"
+ type="text"
+ formControlName="{{ moduleOption.value.name }}"
+ *ngIf="moduleOption.value.enum_allowed.length === 0">
+ <select id="{{ moduleOption.value.name }}"
+ class="form-control"
+ formControlName="{{ moduleOption.value.name }}"
+ *ngIf="moduleOption.value.enum_allowed.length > 0">
+ <option *ngFor="let value of moduleOption.value.enum_allowed"
+ [ngValue]="value">
+ {{ value }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'invalidUuid')"
+ i18n>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</span>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
+ i18n>The entered value needs to be a valid IP address.</span>
+ </div>
+
+ <!-- uint|int|size|secs -->
+ <div class="col-sm-7"
+ *ngIf="['uint', 'int', 'size', 'secs'].includes(moduleOption.value.type)">
+ <input id="{{ moduleOption.value.name }}"
+ class="form-control"
+ type="number"
+ formControlName="{{ moduleOption.value.name }}"
+ min="{{ moduleOption.value.min }}"
+ max="{{ moduleOption.value.max }}">
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'max')"
+ i18n>The entered value is too high! It must be lower or equal to {{ moduleOption.value.max }}.</span>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'min')"
+ i18n>The entered value is too low! It must be greater or equal to {{ moduleOption.value.min }}.</span>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
+ i18n>The entered value needs to be a number.</span>
+ </div>
+
+ <!-- float -->
+ <div class="col-sm-7"
+ *ngIf="moduleOption.value.type === 'float'">
+ <input id="{{ moduleOption.value.name }}"
+ class="form-control"
+ type="number"
+ formControlName="{{ moduleOption.value.name }}">
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
+ i18n>The entered value needs to be a number or decimal.</span>
+ </div>
+
+ </div>
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button type="button"
+ (submitAction)="onSubmit()"
+ [form]="mgrModuleForm">
+ <ng-container i18n>Update</ng-container>
+ </cd-submit-button>
+ <button type="button"
+ class="btn btn-sm btn-default"
+ routerLink="/mgr-modules"
+ i18n>Back</button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.spec.ts
new file mode 100644
index 00000000..1832ccd8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.spec.ts
@@ -0,0 +1,93 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MgrModuleFormComponent } from './mgr-module-form.component';
+
+describe('MgrModuleFormComponent', () => {
+ let component: MgrModuleFormComponent;
+ let fixture: ComponentFixture<MgrModuleFormComponent>;
+
+ configureTestBed({
+ declarations: [MgrModuleFormComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MgrModuleFormComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('getValidators', () => {
+ it('should return ip validator for type addr', () => {
+ const result = component.getValidators({ type: 'addr' });
+ expect(result.length).toBe(1);
+ });
+
+ it('should return number, required validators for types uint, int, size, secs', () => {
+ const types = ['uint', 'int', 'size', 'secs'];
+ types.forEach((type) => {
+ const result = component.getValidators({ type: type });
+ expect(result.length).toBe(2);
+ });
+ });
+
+ it('should return number, required, min validators for types uint, int, size, secs', () => {
+ const types = ['uint', 'int', 'size', 'secs'];
+ types.forEach((type) => {
+ const result = component.getValidators({ type: type, min: 2 });
+ expect(result.length).toBe(3);
+ });
+ });
+
+ it('should return number, required, min, max validators for types uint, int, size, secs', () => {
+ const types = ['uint', 'int', 'size', 'secs'];
+ types.forEach((type) => {
+ const result = component.getValidators({ type: type, min: 2, max: 5 });
+ expect(result.length).toBe(4);
+ });
+ });
+
+ it('should return required, decimalNumber validators for type float', () => {
+ const result = component.getValidators({ type: 'float' });
+ expect(result.length).toBe(2);
+ });
+
+ it('should return uuid validator for type uuid', () => {
+ const result = component.getValidators({ type: 'uuid' });
+ expect(result.length).toBe(1);
+ });
+
+ it('should return no validator for type str', () => {
+ const result = component.getValidators({ type: 'str' });
+ expect(result.length).toBe(0);
+ });
+
+ it('should return min validator for type str', () => {
+ const result = component.getValidators({ type: 'str', min: 1 });
+ expect(result.length).toBe(1);
+ });
+
+ it('should return min, max validators for type str', () => {
+ const result = component.getValidators({ type: 'str', min: 1, max: 127 });
+ expect(result.length).toBe(2);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.ts
new file mode 100644
index 00000000..ae525d53
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-form/mgr-module-form.component.ts
@@ -0,0 +1,146 @@
+import { Component, OnInit } from '@angular/core';
+import { ValidatorFn, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { forkJoin as observableForkJoin } from 'rxjs';
+
+import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../../shared/forms/cd-validators';
+import { NotificationService } from '../../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-mgr-module-form',
+ templateUrl: './mgr-module-form.component.html',
+ styleUrls: ['./mgr-module-form.component.scss']
+})
+export class MgrModuleFormComponent implements OnInit {
+ mgrModuleForm: CdFormGroup;
+ error = false;
+ loading = false;
+ moduleName = '';
+ moduleOptions = [];
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private formBuilder: CdFormBuilder,
+ private mgrModuleService: MgrModuleService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.route.params.subscribe(
+ (params: { name: string }) => {
+ this.moduleName = decodeURIComponent(params.name);
+ this.loading = true;
+ const observables = [];
+ observables.push(this.mgrModuleService.getOptions(this.moduleName));
+ observables.push(this.mgrModuleService.getConfig(this.moduleName));
+ observableForkJoin(observables).subscribe(
+ (resp: object) => {
+ this.loading = false;
+ this.moduleOptions = resp[0];
+ // Create the form dynamically.
+ this.createForm();
+ // Set the form field values.
+ this.mgrModuleForm.setValue(resp[1]);
+ },
+ (error) => {
+ this.error = error;
+ }
+ );
+ },
+ (error) => {
+ this.error = error;
+ }
+ );
+ }
+
+ getValidators(moduleOption): ValidatorFn[] {
+ const result = [];
+ switch (moduleOption.type) {
+ case 'addr':
+ result.push(CdValidators.ip());
+ break;
+ case 'uint':
+ case 'int':
+ case 'size':
+ case 'secs':
+ result.push(CdValidators.number());
+ result.push(Validators.required);
+ if (_.isNumber(moduleOption.min)) {
+ result.push(Validators.min(moduleOption.min));
+ }
+ if (_.isNumber(moduleOption.max)) {
+ result.push(Validators.max(moduleOption.max));
+ }
+ break;
+ case 'str':
+ if (_.isNumber(moduleOption.min)) {
+ result.push(Validators.minLength(moduleOption.min));
+ }
+ if (_.isNumber(moduleOption.max)) {
+ result.push(Validators.maxLength(moduleOption.max));
+ }
+ break;
+ case 'float':
+ result.push(Validators.required);
+ result.push(CdValidators.decimalNumber());
+ break;
+ case 'uuid':
+ result.push(CdValidators.uuid());
+ break;
+ }
+ return result;
+ }
+
+ createForm() {
+ const controlsConfig = {};
+ _.forEach(this.moduleOptions, (moduleOption) => {
+ controlsConfig[moduleOption.name] = [
+ moduleOption.default_value,
+ this.getValidators(moduleOption)
+ ];
+ });
+ this.mgrModuleForm = this.formBuilder.group(controlsConfig);
+ }
+
+ goToListView() {
+ this.router.navigate(['/mgr-modules']);
+ }
+
+ onSubmit() {
+ // Exit immediately if the form isn't dirty.
+ if (this.mgrModuleForm.pristine) {
+ this.goToListView();
+ return;
+ }
+ const config = {};
+ _.forEach(this.moduleOptions, (moduleOption) => {
+ const control = this.mgrModuleForm.get(moduleOption.name);
+ // Append the option only if the value has been modified.
+ if (control.dirty && control.valid) {
+ config[moduleOption.name] = control.value;
+ }
+ });
+ this.mgrModuleService.updateConfig(this.moduleName, config).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated options for module "{{name}}".', { name: this.moduleName })
+ );
+ this.goToListView();
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.mgrModuleForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.html
new file mode 100644
index 00000000..967ae661
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.html
@@ -0,0 +1,18 @@
+<cd-table #table
+ [autoReload]="false"
+ [data]="modules"
+ [columns]="columns"
+ columnMode="flex"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)"
+ identifier="module"
+ (fetchData)="getModuleList($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-mgr-module-details cdTableDetail
+ [selection]="selection">
+ </cd-mgr-module-details>
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts
new file mode 100644
index 00000000..88c80134
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts
@@ -0,0 +1,176 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf, throwError as observableThrowError } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { MgrModuleDetailsComponent } from '../mgr-module-details/mgr-module-details.component';
+import { MgrModuleListComponent } from './mgr-module-list.component';
+
+describe('MgrModuleListComponent', () => {
+ let component: MgrModuleListComponent;
+ let fixture: ComponentFixture<MgrModuleListComponent>;
+ let mgrModuleService: MgrModuleService;
+ let notificationService: NotificationService;
+
+ configureTestBed({
+ declarations: [MgrModuleListComponent, MgrModuleDetailsComponent],
+ imports: [
+ RouterTestingModule,
+ SharedModule,
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ ToastrModule.forRoot()
+ ],
+ providers: [MgrModuleService, NotificationService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MgrModuleListComponent);
+ component = fixture.componentInstance;
+ mgrModuleService = TestBed.get(MgrModuleService);
+ notificationService = TestBed.get(NotificationService);
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Edit',
+ empty: 'Edit'
+ };
+ });
+
+ describe('with read and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it('shows action button', () => permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+
+ describe('should update module state', () => {
+ beforeEach(() => {
+ component.selection = new CdTableSelection();
+ spyOn(notificationService, 'suspendToasties');
+ spyOn(component.blockUI, 'start');
+ spyOn(component.blockUI, 'stop');
+ spyOn(component.table, 'refreshBtn');
+ });
+
+ it('should enable module', fakeAsync(() => {
+ spyOn(mgrModuleService, 'enable').and.returnValue(observableThrowError('y'));
+ spyOn(mgrModuleService, 'list').and.returnValues(observableThrowError('z'), observableOf([]));
+ component.selection.selected.push({
+ name: 'foo',
+ enabled: false,
+ always_on: false
+ });
+ component.selection.update();
+ component.updateModuleState();
+ tick(2000);
+ tick(2000);
+ expect(mgrModuleService.enable).toHaveBeenCalledWith('foo');
+ expect(mgrModuleService.list).toHaveBeenCalledTimes(2);
+ expect(notificationService.suspendToasties).toHaveBeenCalledTimes(2);
+ expect(component.blockUI.start).toHaveBeenCalled();
+ expect(component.blockUI.stop).toHaveBeenCalled();
+ expect(component.table.refreshBtn).toHaveBeenCalled();
+ }));
+
+ it('should disable module', fakeAsync(() => {
+ spyOn(mgrModuleService, 'disable').and.returnValue(observableThrowError('x'));
+ spyOn(mgrModuleService, 'list').and.returnValue(observableOf([]));
+ component.selection.selected.push({
+ name: 'bar',
+ enabled: true,
+ always_on: false
+ });
+ component.selection.update();
+ component.updateModuleState();
+ tick(2000);
+ expect(mgrModuleService.disable).toHaveBeenCalledWith('bar');
+ expect(mgrModuleService.list).toHaveBeenCalledTimes(1);
+ expect(notificationService.suspendToasties).toHaveBeenCalledTimes(2);
+ expect(component.blockUI.start).toHaveBeenCalled();
+ expect(component.blockUI.stop).toHaveBeenCalled();
+ expect(component.table.refreshBtn).toHaveBeenCalled();
+ }));
+
+ it('should not disable module (1)', () => {
+ component.selection.selected = [
+ {
+ name: 'dashboard'
+ }
+ ];
+ component.selection.update();
+ expect(component.isTableActionDisabled('enabled')).toBeTruthy();
+ });
+
+ it('should not disable module (2)', () => {
+ component.selection.selected = [
+ {
+ name: 'bar',
+ always_on: true
+ }
+ ];
+ component.selection.update();
+ expect(component.isTableActionDisabled('enabled')).toBeTruthy();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.ts
new file mode 100644
index 00000000..294ba121
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.ts
@@ -0,0 +1,192 @@
+import { Component, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BlockUI, NgBlockUI } from 'ng-block-ui';
+import { timer as observableTimer } from 'rxjs';
+
+import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
+import { TableComponent } from '../../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-mgr-module-list',
+ templateUrl: './mgr-module-list.component.html',
+ styleUrls: ['./mgr-module-list.component.scss']
+})
+export class MgrModuleListComponent {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+ @BlockUI()
+ blockUI: NgBlockUI;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ columns: CdTableColumn[] = [];
+ modules: object[] = [];
+ selection: CdTableSelection = new CdTableSelection();
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private mgrModuleService: MgrModuleService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().configOpt;
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Enabled'),
+ prop: 'enabled',
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ }
+ ];
+ const getModuleUri = () =>
+ this.selection.first() && encodeURIComponent(this.selection.first().name);
+ this.tableActions = [
+ {
+ name: this.i18n('Edit'),
+ permission: 'update',
+ disable: () => {
+ if (!this.selection.hasSelection) {
+ return true;
+ }
+ // Disable the 'edit' button when the module has no options.
+ return Object.values(this.selection.first().options).length === 0;
+ },
+ routerLink: () => `/mgr-modules/edit/${getModuleUri()}`,
+ icon: 'fa-pencil'
+ },
+ {
+ name: this.i18n('Enable'),
+ permission: 'update',
+ click: () => this.updateModuleState(),
+ disable: () => this.isTableActionDisabled('enabled'),
+ icon: 'fa-play'
+ },
+ {
+ name: this.i18n('Disable'),
+ permission: 'update',
+ click: () => this.updateModuleState(),
+ disable: () => this.isTableActionDisabled('disabled'),
+ disableDesc: () => this.getTableActionDisabledDesc(),
+ icon: 'fa-stop'
+ }
+ ];
+ }
+
+ getModuleList(context: CdTableFetchDataContext) {
+ this.mgrModuleService.list().subscribe(
+ (resp: object[]) => {
+ this.modules = resp;
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ /**
+ * Check if the table action is disabled.
+ * @param state The expected module state, e.g. ``enabled`` or ``disabled``.
+ * @returns If the specified state is validated to true or no selection is
+ * done, then ``true`` is returned, otherwise ``false``.
+ */
+ isTableActionDisabled(state: 'enabled' | 'disabled') {
+ if (!this.selection.hasSelection) {
+ return true;
+ }
+ const selected = this.selection.first();
+ // Make sure the user can't modify the run state of the 'Dashboard' module.
+ // This check is only done in the UI because the REST API should still be
+ // able to do so.
+ if (selected.name === 'dashboard') {
+ return true;
+ }
+ // Always-on modules can't be disabled.
+ if (selected.always_on) {
+ return true;
+ }
+ switch (state) {
+ case 'enabled':
+ return selected.enabled;
+ case 'disabled':
+ return !selected.enabled;
+ }
+ }
+
+ getTableActionDisabledDesc(): string | undefined {
+ if (this.selection.hasSelection) {
+ const selected = this.selection.first();
+ if (selected.always_on) {
+ return this.i18n('This Manager module is always on.');
+ }
+ }
+ }
+
+ /**
+ * Update the Ceph Mgr module state to enabled or disabled.
+ */
+ updateModuleState() {
+ if (!this.selection.hasSelection) {
+ return;
+ }
+
+ let $obs;
+ const fnWaitUntilReconnected = () => {
+ observableTimer(2000).subscribe(() => {
+ // Trigger an API request to check if the connection is
+ // re-established.
+ this.mgrModuleService.list().subscribe(
+ () => {
+ // Resume showing the notification toasties.
+ this.notificationService.suspendToasties(false);
+ // Unblock the whole UI.
+ this.blockUI.stop();
+ // Reload the data table content.
+ this.table.refreshBtn();
+ },
+ () => {
+ fnWaitUntilReconnected();
+ }
+ );
+ });
+ };
+
+ // Note, the Ceph Mgr is always restarted when a module
+ // is enabled/disabled.
+ const module = this.selection.first();
+ if (module.enabled) {
+ $obs = this.mgrModuleService.disable(module.name);
+ } else {
+ $obs = this.mgrModuleService.enable(module.name);
+ }
+ $obs.subscribe(
+ () => {},
+ () => {
+ // Suspend showing the notification toasties.
+ this.notificationService.suspendToasties(true);
+ // Block the whole UI to prevent user interactions until
+ // the connection to the backend is reestablished
+ this.blockUI.start(this.i18n('Reconnecting, please wait ...'));
+ fnWaitUntilReconnected();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-modules.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-modules.module.ts
new file mode 100644
index 00000000..1abf09a6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-modules.module.ts
@@ -0,0 +1,23 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { AppRoutingModule } from '../../../app-routing.module';
+import { SharedModule } from '../../../shared/shared.module';
+import { MgrModuleDetailsComponent } from './mgr-module-details/mgr-module-details.component';
+import { MgrModuleFormComponent } from './mgr-module-form/mgr-module-form.component';
+import { MgrModuleListComponent } from './mgr-module-list/mgr-module-list.component';
+
+@NgModule({
+ imports: [
+ AppRoutingModule,
+ CommonModule,
+ ReactiveFormsModule,
+ SharedModule,
+ TabsModule.forRoot()
+ ],
+ declarations: [MgrModuleListComponent, MgrModuleFormComponent, MgrModuleDetailsComponent]
+})
+export class MgrModulesModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.html
new file mode 100644
index 00000000..af863b63
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.html
@@ -0,0 +1,60 @@
+<div class="row">
+ <div class="col-md-4">
+ <fieldset>
+ <legend i18n>Status</legend>
+ <table class="table table-striped"
+ *ngIf="mon_status">
+ <tr>
+ <td i18n
+ class="bold">Cluster ID</td>
+ <td>{{ mon_status.monmap.fsid }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">monmap modified</td>
+ <td>{{ mon_status.monmap.modified }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">monmap epoch</td>
+ <td>{{ mon_status.monmap.epoch }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">quorum con</td>
+ <td>{{ mon_status.features.quorum_con }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">quorum mon</td>
+ <td>{{ mon_status.features.quorum_mon }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">required con</td>
+ <td>{{ mon_status.features.required_con }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold">required mon</td>
+ <td>{{ mon_status.features.required_mon }}</td>
+ </tr>
+ </table>
+ </fieldset>
+ </div>
+
+ <div class="col-md-8">
+ <legend i18n
+ class="in-quorum">In Quorum</legend>
+ <cd-table [data]="inQuorum.data"
+ [columns]="inQuorum.columns">
+ </cd-table>
+
+ <legend i18n
+ class="in-quorum">Not In Quorum</legend>
+ <cd-table [data]="notInQuorum.data"
+ (fetchData)="refresh()"
+ [columns]="notInQuorum.columns">
+ </cd-table>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.spec.ts
new file mode 100644
index 00000000..b3f4ee53
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.spec.ts
@@ -0,0 +1,86 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { of } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { MonitorService } from '../../../shared/api/monitor.service';
+import { MonitorComponent } from './monitor.component';
+
+describe('MonitorComponent', () => {
+ let component: MonitorComponent;
+ let fixture: ComponentFixture<MonitorComponent>;
+ let getMonitorSpy: jasmine.Spy;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ declarations: [MonitorComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [MonitorService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MonitorComponent);
+ component = fixture.componentInstance;
+ const getMonitorPayload = {
+ in_quorum: [
+ {
+ stats: { num_sessions: [[1, 5]] }
+ },
+ {
+ stats: { num_sessions: [[1, 1], [2, 10], [3, 1]] }
+ },
+ {
+ stats: { num_sessions: [[1, 0], [2, 3]] }
+ },
+ {
+ stats: { num_sessions: [[1, 2], [2, 1], [3, 7], [4, 5]] }
+ }
+ ],
+ mon_status: null,
+ out_quorum: []
+ };
+ getMonitorSpy = spyOn(TestBed.get(MonitorService), 'getMonitor').and.returnValue(
+ of(getMonitorPayload)
+ );
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should sort by open sessions column correctly', () => {
+ component.refresh();
+
+ expect(getMonitorSpy).toHaveBeenCalled();
+
+ expect(component.inQuorum.columns[3].comparator(undefined, undefined)).toBe(0);
+ expect(component.inQuorum.columns[3].comparator(null, null)).toBe(0);
+ expect(component.inQuorum.columns[3].comparator([], [])).toBe(0);
+ expect(
+ component.inQuorum.columns[3].comparator(
+ component.inQuorum.data[0].cdOpenSessions,
+ component.inQuorum.data[3].cdOpenSessions
+ )
+ ).toBe(0);
+ expect(
+ component.inQuorum.columns[3].comparator(
+ component.inQuorum.data[0].cdOpenSessions,
+ component.inQuorum.data[1].cdOpenSessions
+ )
+ ).toBe(1);
+ expect(
+ component.inQuorum.columns[3].comparator(
+ component.inQuorum.data[1].cdOpenSessions,
+ component.inQuorum.data[0].cdOpenSessions
+ )
+ ).toBe(-1);
+ expect(
+ component.inQuorum.columns[3].comparator(
+ component.inQuorum.data[2].cdOpenSessions,
+ component.inQuorum.data[1].cdOpenSessions
+ )
+ ).toBe(1);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.ts
new file mode 100644
index 00000000..d53f8626
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/monitor/monitor.component.ts
@@ -0,0 +1,77 @@
+import { Component } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { MonitorService } from '../../../shared/api/monitor.service';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+
+@Component({
+ selector: 'cd-monitor',
+ templateUrl: './monitor.component.html',
+ styleUrls: ['./monitor.component.scss']
+})
+export class MonitorComponent {
+ mon_status: any;
+ inQuorum: any;
+ notInQuorum: any;
+
+ interval: any;
+
+ constructor(private monitorService: MonitorService, private i18n: I18n) {
+ this.inQuorum = {
+ columns: [
+ { prop: 'name', name: this.i18n('Name'), cellTransformation: CellTemplate.routerLink },
+ { prop: 'rank', name: this.i18n('Rank') },
+ { prop: 'public_addr', name: this.i18n('Public Address') },
+ {
+ prop: 'cdOpenSessions',
+ name: this.i18n('Open Sessions'),
+ cellTransformation: CellTemplate.sparkline,
+ comparator: (dataA, dataB) => {
+ // We get the last value of time series to compare:
+ const lastValueA = _.last(dataA);
+ const lastValueB = _.last(dataB);
+
+ if (!lastValueA || !lastValueB || lastValueA === lastValueB) {
+ return 0;
+ }
+
+ return lastValueA > lastValueB ? 1 : -1;
+ }
+ }
+ ],
+ data: []
+ };
+
+ this.notInQuorum = {
+ columns: [
+ { prop: 'name', name: this.i18n('Name'), cellTransformation: CellTemplate.routerLink },
+ { prop: 'rank', name: this.i18n('Rank') },
+ { prop: 'public_addr', name: this.i18n('Public Address') }
+ ],
+ data: []
+ };
+ }
+
+ refresh() {
+ this.monitorService.getMonitor().subscribe((data: any) => {
+ data.in_quorum.map((row) => {
+ row.cdOpenSessions = row.stats.num_sessions.map((i) => i[1]);
+ row.cdLink = '/perf_counters/mon/' + row.name;
+ row.cdParams = { fromLink: '/monitor' };
+ return row;
+ });
+
+ data.out_quorum.map((row) => {
+ row.cdLink = '/perf_counters/mon/' + row.name;
+ row.cdParams = { fromLink: '/monitor' };
+ return row;
+ });
+
+ this.inQuorum.data = [...data.in_quorum];
+ this.notInQuorum.data = [...data.out_quorum];
+ this.mon_status = data.mon_status;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html
new file mode 100644
index 00000000..defec482
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html
@@ -0,0 +1,52 @@
+<tabset *ngIf="selection.hasSingleSelection">
+ <tab heading="Attributes (OSD map)"
+ i18n-heading>
+ <cd-table-key-value *ngIf="osd.loaded"
+ [data]="osd.details.osd_map">
+ </cd-table-key-value>
+ </tab>
+ <tab heading="Metadata"
+ i18n-heading>
+ <cd-table-key-value *ngIf="osd.loaded && osd.details.osd_metadata; else noMetaData"
+ (fetchData)="refresh()"
+ [data]="osd.details.osd_metadata">
+ </cd-table-key-value>
+ <ng-template #noMetaData>
+ <cd-warning-panel i18n>Metadata not available</cd-warning-panel>
+ </ng-template>
+ </tab>
+ <tab heading="Performance counter"
+ i18n-heading>
+ <cd-table-performance-counter *ngIf="osd.loaded"
+ serviceType="osd"
+ [serviceId]="osd.id">
+ </cd-table-performance-counter>
+ </tab>
+ <tab heading="Histogram"
+ i18n-heading>
+ <cd-warning-panel *ngIf="osd.loaded && osd.histogram_failed"
+ i18n>Histogram not available: {{ osd.histogram_failed }}</cd-warning-panel>
+
+ <div class="row"
+ *ngIf="osd.loaded && osd.details.histogram">
+ <div class="col-md-6">
+ <h4 i18n>Writes</h4>
+ <cd-osd-performance-histogram [histogram]="osd.details.histogram.osd.op_w_latency_in_bytes_histogram">
+ </cd-osd-performance-histogram>
+ </div>
+ <div class="col-md-6">
+ <h4 i18n>Reads</h4>
+ <cd-osd-performance-histogram [histogram]="osd.details.histogram.osd.op_r_latency_out_bytes_histogram">
+ </cd-osd-performance-histogram>
+ </div>
+ </div>
+ </tab>
+ <tab i18n-heading
+ *ngIf="grafanaPermission.read"
+ heading="Performance Details">
+ <cd-grafana [grafanaPath]="'osd-device-details?var-osd=osd.' + osd['id']"
+ uid="CrAHE0iZz"
+ grafanaStyle="GrafanaStyles.two">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts
new file mode 100644
index 00000000..1bcecc67
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts
@@ -0,0 +1,77 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { of } from 'rxjs';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../../shared/shared.module';
+import { PerformanceCounterModule } from '../../../performance-counter/performance-counter.module';
+import { OsdPerformanceHistogramComponent } from '../osd-performance-histogram/osd-performance-histogram.component';
+import { OsdDetailsComponent } from './osd-details.component';
+
+describe('OsdDetailsComponent', () => {
+ let component: OsdDetailsComponent;
+ let fixture: ComponentFixture<OsdDetailsComponent>;
+ let debugElement: DebugElement;
+ let osdService: OsdService;
+ let getDetailsSpy;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ PerformanceCounterModule,
+ SharedModule
+ ],
+ declarations: [OsdDetailsComponent, OsdPerformanceHistogramComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdDetailsComponent);
+ component = fixture.componentInstance;
+
+ component.selection = new CdTableSelection();
+ debugElement = fixture.debugElement;
+ osdService = debugElement.injector.get(OsdService);
+
+ getDetailsSpy = spyOn(osdService, 'getDetails');
+
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should fail creating a histogram', () => {
+ const detailDataWithoutHistogram = {
+ osd_map: {},
+ osd_metadata: {},
+ histogram: 'osd down'
+ };
+ getDetailsSpy.and.returnValue(of(detailDataWithoutHistogram));
+ component.osd = { tree: { id: 0 } };
+ component.refresh();
+ expect(getDetailsSpy).toHaveBeenCalled();
+ expect(component.osd.histogram_failed).toBe('osd down');
+ });
+
+ it('should succeed creating a histogram', () => {
+ const detailDataWithHistogram = {
+ osd_map: {},
+ osd_metdata: {},
+ histogram: {}
+ };
+ getDetailsSpy.and.returnValue(of(detailDataWithHistogram));
+ component.osd = { tree: { id: 0 } };
+ component.refresh();
+ expect(getDetailsSpy).toHaveBeenCalled();
+ expect(component.osd.histogram_failed).toBe('');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts
new file mode 100644
index 00000000..766fc2db
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts
@@ -0,0 +1,47 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { OsdService } from '../../../../shared/api/osd.service';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-osd-details',
+ templateUrl: './osd-details.component.html',
+ styleUrls: ['./osd-details.component.scss']
+})
+export class OsdDetailsComponent implements OnChanges {
+ @Input()
+ selection: CdTableSelection;
+
+ osd: any;
+ grafanaPermission: Permission;
+
+ constructor(private osdService: OsdService, private authStorageService: AuthStorageService) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ }
+
+ ngOnChanges() {
+ this.osd = {
+ loaded: false
+ };
+ if (this.selection.hasSelection) {
+ this.osd = this.selection.first();
+ this.refresh();
+ }
+ }
+
+ refresh() {
+ this.osdService.getDetails(this.osd.id).subscribe((data: any) => {
+ this.osd.details = data;
+ this.osd.histogram_failed = '';
+ if (!_.isObject(data.histogram)) {
+ this.osd.histogram_failed = data.histogram;
+ this.osd.details.histogram = undefined;
+ }
+ this.osd.loaded = true;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html
new file mode 100644
index 00000000..3128f820
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html
@@ -0,0 +1,45 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>Cluster-wide OSD Flags</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="osdFlagsForm"
+ #formDir="ngForm"
+ [formGroup]="osdFlagsForm"
+ novalidate
+ cdFormScope="osd">
+ <div class="modal-body osd-modal">
+ <div class="checkbox checkbox-primary"
+ *ngFor="let flag of flags; let last = last">
+ <input type="checkbox"
+ [checked]="flag.value"
+ (change)="flag.value = !flag.value"
+ [name]="flag.code"
+ [id]="flag.code"
+ [disabled]="flag.disabled">
+ <label [for]="flag.code"
+ ng-class="['tc_' + key]">
+ <strong>{{ flag.name }}</strong>
+ <br>
+ <span class="text-muted">{{ flag.description }}</span>
+ </label>
+ <hr class="oa-hr-small"
+ *ngIf="!last">
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button *ngIf="permissions.osd.update"
+ (submitAction)="submitAction()"
+ [form]="osdFlagsForm"
+ i18n>Submit</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.scss
new file mode 100644
index 00000000..df12ae46
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.scss
@@ -0,0 +1,5 @@
+.osd-modal {
+ .oa-hr-small {
+ margin: 5px;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.spec.ts
new file mode 100644
index 00000000..ae4bafec
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.spec.ts
@@ -0,0 +1,100 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as _ from 'lodash';
+import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { OsdFlagsModalComponent } from './osd-flags-modal.component';
+
+function getFlagsArray(component: OsdFlagsModalComponent) {
+ const allFlags = _.cloneDeep(component.allFlags);
+ allFlags['purged_snapdirs'].value = true;
+ allFlags['pause'].value = true;
+ return _.toArray(allFlags);
+}
+
+describe('OsdFlagsModalComponent', () => {
+ let component: OsdFlagsModalComponent;
+ let fixture: ComponentFixture<OsdFlagsModalComponent>;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [
+ ReactiveFormsModule,
+ ModalModule.forRoot(),
+ SharedModule,
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ToastrModule.forRoot()
+ ],
+ declarations: [OsdFlagsModalComponent],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ httpTesting = TestBed.get(HttpTestingController);
+ fixture = TestBed.createComponent(OsdFlagsModalComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should finish running ngOnInit', () => {
+ fixture.detectChanges();
+
+ const flags = getFlagsArray(component);
+
+ const req = httpTesting.expectOne('api/osd/flags');
+ req.flush(['purged_snapdirs', 'pause', 'foo']);
+
+ expect(component.flags).toEqual(flags);
+ expect(component.unknownFlags).toEqual(['foo']);
+ });
+
+ describe('test submitAction', function() {
+ let notificationType: NotificationType;
+ let notificationService: NotificationService;
+ let bsModalRef: BsModalRef;
+
+ beforeEach(() => {
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.callFake((type) => {
+ notificationType = type;
+ });
+
+ bsModalRef = TestBed.get(BsModalRef);
+ spyOn(bsModalRef, 'hide').and.callThrough();
+ component.unknownFlags = ['foo'];
+ });
+
+ it('should run submitAction', () => {
+ component.flags = getFlagsArray(component);
+ component.submitAction();
+ const req = httpTesting.expectOne('api/osd/flags');
+ req.flush(['purged_snapdirs', 'pause', 'foo']);
+ expect(req.request.body).toEqual({ flags: ['pause', 'purged_snapdirs', 'foo'] });
+
+ expect(notificationType).toBe(NotificationType.success);
+ expect(component.bsModalRef.hide).toHaveBeenCalledTimes(1);
+ });
+
+ it('should hide modal if request fails', () => {
+ component.flags = [];
+ component.submitAction();
+ const req = httpTesting.expectOne('api/osd/flags');
+ req.flush([], { status: 500, statusText: 'failure' });
+
+ expect(notificationService.show).toHaveBeenCalledTimes(0);
+ expect(component.bsModalRef.hide).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.ts
new file mode 100644
index 00000000..12520e41
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.ts
@@ -0,0 +1,162 @@
+import { Component, OnInit } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { OsdService } from '../../../../shared/api/osd.service';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { Permissions } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-osd-flags-modal',
+ templateUrl: './osd-flags-modal.component.html',
+ styleUrls: ['./osd-flags-modal.component.scss']
+})
+export class OsdFlagsModalComponent implements OnInit {
+ permissions: Permissions;
+
+ osdFlagsForm = new FormGroup({});
+
+ allFlags = {
+ noin: {
+ code: 'noin',
+ name: this.i18n('No In'),
+ value: false,
+ description: this.i18n(
+ 'OSDs that were previously marked out will not be marked back in when they start'
+ )
+ },
+ noout: {
+ code: 'noout',
+ name: this.i18n('No Out'),
+ value: false,
+ description: this.i18n(
+ 'OSDs will not automatically be marked out after the configured interval'
+ )
+ },
+ noup: {
+ code: 'noup',
+ name: this.i18n('No Up'),
+ value: false,
+ description: this.i18n('OSDs are not allowed to start')
+ },
+ nodown: {
+ code: 'nodown',
+ name: this.i18n('No Down'),
+ value: false,
+ description: this.i18n(
+ 'OSD failure reports are being ignored, such that the monitors will not mark OSDs down'
+ )
+ },
+ pause: {
+ code: 'pause',
+ name: this.i18n('Pause'),
+ value: false,
+ description: this.i18n('Pauses reads and writes')
+ },
+ noscrub: {
+ code: 'noscrub',
+ name: this.i18n('No Scrub'),
+ value: false,
+ description: this.i18n('Scrubbing is disabled')
+ },
+ 'nodeep-scrub': {
+ code: 'nodeep-scrub',
+ name: this.i18n('No Deep Scrub'),
+ value: false,
+ description: this.i18n('Deep Scrubbing is disabled')
+ },
+ nobackfill: {
+ code: 'nobackfill',
+ name: this.i18n('No Backfill'),
+ value: false,
+ description: this.i18n('Backfilling of PGs is suspended')
+ },
+ norebalance: {
+ code: 'norebalance',
+ name: this.i18n('No Rebalance'),
+ value: false,
+ description: this.i18n('OSD will choose not to backfill unless PG is also degraded')
+ },
+ norecover: {
+ code: 'norecover',
+ name: this.i18n('No Recover'),
+ value: false,
+ description: this.i18n('Recovery of PGs is suspended')
+ },
+ sortbitwise: {
+ code: 'sortbitwise',
+ name: this.i18n('Bitwise Sort'),
+ value: false,
+ description: this.i18n('Use bitwise sort'),
+ disabled: true
+ },
+ purged_snapdirs: {
+ code: 'purged_snapdirs',
+ name: this.i18n('Purged Snapdirs'),
+ value: false,
+ description: this.i18n('OSDs have converted snapsets'),
+ disabled: true
+ },
+ recovery_deletes: {
+ code: 'recovery_deletes',
+ name: this.i18n('Recovery Deletes'),
+ value: false,
+ description: this.i18n('Deletes performed during recovery instead of peering'),
+ disabled: true
+ },
+ pglog_hardlimit: {
+ code: 'pglog_hardlimit',
+ name: this.i18n('PG Log Hard Limit'),
+ value: false,
+ description: this.i18n('Puts a hard limit on pg log length'),
+ disabled: true
+ }
+ };
+ flags: any[];
+ unknownFlags: string[] = [];
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private authStorageService: AuthStorageService,
+ private osdService: OsdService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ }
+
+ ngOnInit() {
+ this.osdService.getFlags().subscribe((res: string[]) => {
+ res.forEach((value) => {
+ if (this.allFlags[value]) {
+ this.allFlags[value].value = true;
+ } else {
+ this.unknownFlags.push(value);
+ }
+ });
+ this.flags = _.toArray(this.allFlags);
+ });
+ }
+
+ submitAction() {
+ const newFlags = this.flags
+ .filter((flag) => flag.value)
+ .map((flag) => flag.code)
+ .concat(this.unknownFlags);
+
+ this.osdService.updateFlags(newFlags).subscribe(
+ () => {
+ this.notificationService.show(NotificationType.success, this.i18n('Updated OSD Flags'));
+ this.bsModalRef.hide();
+ },
+ () => {
+ this.bsModalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html
new file mode 100644
index 00000000..dfa9c445
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html
@@ -0,0 +1,95 @@
+<tabset>
+ <tab i18n-heading
+ heading="OSDs List">
+ <cd-table [data]="osds"
+ (fetchData)="getOsdList()"
+ [columns]="columns"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)"
+ [updateSelectionOnRefresh]="'never'">
+ <div class="table-actions btn-toolbar">
+ <cd-table-actions [permission]="permissions.osd"
+ [selection]="selection"
+ class="btn-group"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+
+ <div class="btn-group"
+ dropdown
+ *ngIf="advancedTableActions.length > 0">
+ <button type="button"
+ class="btn btn-sm btn-default btn-label tc_configureCluster"
+ (click)="advancedTableActions[0].click()">
+ <i class="fa fa-fw {{ advancedTableActions[0].icon }}"></i><span>{{ advancedTableActions[0].name }}</span>
+ </button>
+ <button type="button"
+ dropdownToggle
+ class="btn btn-sm btn-default dropdown-toggle dropdown-toggle-split"
+ *ngIf="advancedTableActions.length > 1">
+ <span class="caret caret-black"></span>
+ </button>
+ <ul *dropdownMenu
+ class="dropdown-menu"
+ role="menu">
+ <ng-container *ngFor="let action of advancedTableActions | slice:1">
+ <li role="menuitem">
+ <a class="dropdown-item"
+ (click)="action.click()">
+ <i class="fa fa-fw {{ action.icon }}"
+ aria-hidden="true">
+ </i>
+ <ng-container>{{ action.name }}</ng-container>
+ </a>
+ </li>
+ </ng-container>
+ </ul>
+ </div>
+ </div>
+
+ <cd-osd-details cdTableDetail
+ [selection]="selection">
+ </cd-osd-details>
+ </cd-table>
+
+ <ng-template #statusColor
+ let-value="value">
+ <span *ngFor="let state of value; last as last">
+ <span class="label"
+ [ngClass]="{'label-success': ['in', 'up'].includes(state), 'label-danger': ['down', 'out'].includes(state)}">{{ state }}</span>
+ <span *ngIf="!last">&nbsp;</span>
+ </span>
+ </ng-template>
+
+ <ng-template #osdUsageTpl
+ let-row="row">
+ <cd-usage-bar [total]="row.stats.stat_bytes"
+ [used]="row.stats.stat_bytes_used">
+ </cd-usage-bar>
+ </ng-template>
+ </tab>
+ <tab i18n-heading
+ *ngIf="permissions.grafana.read"
+ heading="Overall Performance">
+ <cd-grafana [grafanaPath]="'osd-overview?'"
+ uid="lo02I1Aiz"
+ grafanaStyle="three">
+ </cd-grafana>
+ </tab>
+</tabset>
+
+<ng-template #markOsdConfirmationTpl
+ let-markActionDescription="markActionDescription">
+ <ng-container i18n><strong>OSD {{ selection.first().id }}</strong> will be marked
+ <strong>{{ markActionDescription }}</strong> if you proceed.</ng-container>
+</ng-template>
+
+<ng-template #criticalConfirmationTpl
+ let-safeToDestroyResult="result"
+ let-actionDescription="actionDescription">
+ <div *ngIf="!safeToDestroyResult['is_safe_to_destroy']"
+ class="danger">
+ <cd-warning-panel i18n>The OSD is not safe to destroy!</cd-warning-panel>
+ </div>
+ <ng-container i18n><strong>OSD {{ selection.first().id }}</strong> will be
+ <strong>{{ actionDescription }}</strong> if you proceed.</ng-container>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.scss
new file mode 100644
index 00000000..d27309cf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.scss
@@ -0,0 +1,3 @@
+.caret.caret-black {
+ color: #000000;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
new file mode 100644
index 00000000..5163bb6b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
@@ -0,0 +1,292 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import _ = require('lodash');
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { EMPTY, of } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { ConfirmationModalComponent } from '../../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { PerformanceCounterModule } from '../../../performance-counter/performance-counter.module';
+import { OsdDetailsComponent } from '../osd-details/osd-details.component';
+import { OsdPerformanceHistogramComponent } from '../osd-performance-histogram/osd-performance-histogram.component';
+import { OsdReweightModalComponent } from '../osd-reweight-modal/osd-reweight-modal.component';
+import { OsdListComponent } from './osd-list.component';
+
+describe('OsdListComponent', () => {
+ let component: OsdListComponent;
+ let fixture: ComponentFixture<OsdListComponent>;
+ let modalServiceShowSpy: jasmine.Spy;
+ let osdService: OsdService;
+
+ const fakeAuthStorageService = {
+ getPermissions: () => {
+ return new Permissions({ osd: ['read', 'update', 'create', 'delete'] });
+ }
+ };
+
+ const getTableAction = (name) => component.tableActions.find((action) => action.name === name);
+
+ const setFakeSelection = () => {
+ // Default data and selection
+ const selection = [{ id: 1 }];
+ const data = [{ id: 1 }];
+
+ // Table data and selection
+ component.selection = new CdTableSelection();
+ component.selection.selected = selection;
+ component.selection.update();
+ component.osds = data;
+ component.permissions = fakeAuthStorageService.getPermissions();
+ };
+
+ const openActionModal = (actionName) => {
+ setFakeSelection();
+ getTableAction(actionName).click();
+ };
+
+ /**
+ * The following modals are called after the information about their
+ * safety to destroy/remove/mark them lost has been retrieved, hence
+ * we will have to fake its request to be able to open those modals.
+ */
+ const mockSafeToDestroy = () => {
+ spyOn(TestBed.get(OsdService), 'safeToDestroy').and.callFake(() =>
+ of({ 'safe-to-destroy': true })
+ );
+ };
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ PerformanceCounterModule,
+ TabsModule.forRoot(),
+ SharedModule,
+ ReactiveFormsModule,
+ RouterTestingModule
+ ],
+ declarations: [OsdListComponent, OsdDetailsComponent, OsdPerformanceHistogramComponent],
+ providers: [
+ { provide: AuthStorageService, useValue: fakeAuthStorageService },
+ TableActionsComponent,
+ BsModalService,
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdListComponent);
+ fixture.detectChanges();
+ component = fixture.componentInstance;
+ osdService = TestBed.get(OsdService);
+ modalServiceShowSpy = spyOn(TestBed.get(BsModalService), 'show').and.stub();
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ it('should have columns that are sortable', () => {
+ expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ });
+
+ describe('getOsdList', () => {
+ let osds;
+
+ const createOsd = (n: number) => ({
+ in: 'in',
+ up: 'up',
+ stats_history: {
+ op_out_bytes: [[n, n], [n * 2, n * 2]],
+ op_in_bytes: [[n * 3, n * 3], [n * 4, n * 4]]
+ },
+ stats: {
+ stat_bytes_used: n * n,
+ stat_bytes: n * n * n
+ }
+ });
+
+ const expectAttributeOnEveryOsd = (attr: string) =>
+ expect(component.osds.every((osd) => Boolean(_.get(osd, attr)))).toBeTruthy();
+
+ beforeEach(() => {
+ spyOn(osdService, 'getList').and.callFake(() => of(osds));
+ osds = [createOsd(1), createOsd(2), createOsd(3)];
+ component.getOsdList();
+ });
+
+ it('should replace "this.osds" with new data', () => {
+ expect(component.osds.length).toBe(3);
+ expect(osdService.getList).toHaveBeenCalledTimes(1);
+
+ osds = [createOsd(4)];
+ component.getOsdList();
+ expect(component.osds.length).toBe(1);
+ expect(osdService.getList).toHaveBeenCalledTimes(2);
+ });
+
+ it('should have custom attribute "collectedStates"', () => {
+ expectAttributeOnEveryOsd('collectedStates');
+ expect(component.osds[0].collectedStates).toEqual(['in', 'up']);
+ });
+
+ it('should have custom attribute "stats_history.out_bytes"', () => {
+ expectAttributeOnEveryOsd('stats_history.out_bytes');
+ expect(component.osds[0].stats_history.out_bytes).toEqual([1, 2]);
+ });
+
+ it('should have custom attribute "stats_history.in_bytes"', () => {
+ expectAttributeOnEveryOsd('stats_history.in_bytes');
+ expect(component.osds[0].stats_history.in_bytes).toEqual([3, 4]);
+ });
+
+ it('should have custom attribute "stats.usage"', () => {
+ expectAttributeOnEveryOsd('stats.usage');
+ expect(component.osds[0].stats.usage).toBe(1);
+ expect(component.osds[1].stats.usage).toBe(0.5);
+ expect(component.osds[2].stats.usage).toBe(3 / 9);
+ });
+
+ it('should have custom attribute "cdIsBinary" to be true', () => {
+ expectAttributeOnEveryOsd('cdIsBinary');
+ expect(component.osds[0].cdIsBinary).toBe(true);
+ });
+ });
+
+ describe('show table actions as defined', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = () => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permissions.osd, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Scrub',
+ empty: 'Scrub'
+ };
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it('shows action button', () => permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(9);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('test table actions in submenu', () => {
+ beforeEach(fakeAsync(() => {
+ // The menu needs a click to render the dropdown!
+ const dropDownToggle = fixture.debugElement.query(By.css('.dropdown-toggle'));
+ dropDownToggle.triggerEventHandler('click', null);
+ tick();
+ fixture.detectChanges();
+ }));
+
+ it('has all menu entries disabled', () => {
+ const tableActionElement = fixture.debugElement.query(By.directive(TableActionsComponent));
+ const toClassName = TestBed.get(TableActionsComponent).toClassName;
+ const getActionClasses = (action: CdTableAction) =>
+ tableActionElement.query(By.css('.' + toClassName(action.name))).classes;
+
+ component.tableActions.forEach((action) => {
+ expect(getActionClasses(action).disabled).toBe(true);
+ });
+ });
+ });
+
+ describe('tests if all modals are opened correctly', () => {
+ /**
+ * Helper function to check if a function opens a modal
+ *
+ * @param modalClass - The expected class of the modal
+ */
+ const expectOpensModal = (actionName: string, modalClass): void => {
+ openActionModal(actionName);
+
+ // @TODO: check why tsc is complaining when passing 'expectationFailOutput' param.
+ expect(modalServiceShowSpy.calls.any()).toBeTruthy();
+ expect(modalServiceShowSpy.calls.first().args[0]).toBe(modalClass);
+
+ modalServiceShowSpy.calls.reset();
+ };
+
+ it('opens the reweight modal', () => {
+ expectOpensModal('Reweight', OsdReweightModalComponent);
+ });
+
+ it('opens all confirmation modals', () => {
+ const modalClass = ConfirmationModalComponent;
+ expectOpensModal('Mark Out', modalClass);
+ expectOpensModal('Mark In', modalClass);
+ expectOpensModal('Mark Down', modalClass);
+ });
+
+ it('opens all critical confirmation modals', () => {
+ const modalClass = CriticalConfirmationModalComponent;
+ mockSafeToDestroy();
+ expectOpensModal('Mark Lost', modalClass);
+ expectOpensModal('Purge', modalClass);
+ expectOpensModal('Destroy', modalClass);
+ });
+ });
+
+ describe('tests if the correct methods are called on confirmation', () => {
+ const expectOsdServiceMethodCalled = (
+ actionName: string,
+ osdServiceMethodName: 'markOut' | 'markIn' | 'markDown' | 'markLost' | 'purge' | 'destroy'
+ ): void => {
+ const osdServiceSpy = spyOn(osdService, osdServiceMethodName).and.callFake(() => EMPTY);
+ openActionModal(actionName);
+ const initialState = modalServiceShowSpy.calls.first().args[1].initialState;
+ const submit = initialState.onSubmit || initialState.submitAction;
+ submit.call(component);
+
+ expect(osdServiceSpy.calls.count()).toBe(1);
+ expect(osdServiceSpy.calls.first().args[0]).toBe(1);
+
+ // Reset spies to be able to recreate them
+ osdServiceSpy.calls.reset();
+ modalServiceShowSpy.calls.reset();
+ };
+
+ it('calls the corresponding service methods in confirmation modals', () => {
+ expectOsdServiceMethodCalled('Mark Out', 'markOut');
+ expectOsdServiceMethodCalled('Mark In', 'markIn');
+ expectOsdServiceMethodCalled('Mark Down', 'markDown');
+ });
+
+ it('calls the corresponding service methods in critical confirmation modals', () => {
+ mockSafeToDestroy();
+ expectOsdServiceMethodCalled('Mark Lost', 'markLost');
+ expectOsdServiceMethodCalled('Purge', 'purge');
+ expectOsdServiceMethodCalled('Destroy', 'destroy');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
new file mode 100644
index 00000000..3099554a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
@@ -0,0 +1,351 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { Observable } from 'rxjs';
+
+import { OsdService } from '../../../../shared/api/osd.service';
+import { ConfirmationModalComponent } from '../../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../../shared/constants/app.constants';
+import { TableComponent } from '../../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { OsdFlagsModalComponent } from '../osd-flags-modal/osd-flags-modal.component';
+import { OsdPgScrubModalComponent } from '../osd-pg-scrub-modal/osd-pg-scrub-modal.component';
+import { OsdRecvSpeedModalComponent } from '../osd-recv-speed-modal/osd-recv-speed-modal.component';
+import { OsdReweightModalComponent } from '../osd-reweight-modal/osd-reweight-modal.component';
+import { OsdScrubModalComponent } from '../osd-scrub-modal/osd-scrub-modal.component';
+
+@Component({
+ selector: 'cd-osd-list',
+ templateUrl: './osd-list.component.html',
+ styleUrls: ['./osd-list.component.scss']
+})
+export class OsdListComponent implements OnInit {
+ @ViewChild('statusColor')
+ statusColor: TemplateRef<any>;
+ @ViewChild('osdUsageTpl')
+ osdUsageTpl: TemplateRef<any>;
+ @ViewChild('markOsdConfirmationTpl')
+ markOsdConfirmationTpl: TemplateRef<any>;
+ @ViewChild('criticalConfirmationTpl')
+ criticalConfirmationTpl: TemplateRef<any>;
+ @ViewChild(TableComponent)
+ tableComponent: TableComponent;
+ @ViewChild('reweightBodyTpl')
+ reweightBodyTpl: TemplateRef<any>;
+ @ViewChild('safeToDestroyBodyTpl')
+ safeToDestroyBodyTpl: TemplateRef<any>;
+
+ permissions: Permissions;
+ tableActions: CdTableAction[];
+ bsModalRef: BsModalRef;
+ columns: CdTableColumn[];
+ advancedTableActions: any[];
+
+ osds = [];
+ selection = new CdTableSelection();
+
+ protected static collectStates(osd) {
+ return [osd['in'] ? 'in' : 'out', osd['up'] ? 'up' : 'down'];
+ }
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private osdService: OsdService,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private modalService: BsModalService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ this.tableActions = [
+ {
+ name: this.actionLabels.SCRUB,
+ permission: 'update',
+ icon: 'fa-stethoscope',
+ click: () => this.scrubAction(false),
+ disable: () => !this.hasOsdSelected
+ },
+ {
+ name: this.actionLabels.DEEP_SCRUB,
+ permission: 'update',
+ icon: 'fa-cog',
+ click: () => this.scrubAction(true),
+ disable: () => !this.hasOsdSelected
+ },
+ {
+ name: this.actionLabels.REWEIGHT,
+ permission: 'update',
+ click: () => this.reweight(),
+ disable: () => !this.hasOsdSelected,
+ icon: 'fa-balance-scale'
+ },
+ {
+ name: this.actionLabels.MARK_OUT,
+ permission: 'update',
+ click: () => this.showConfirmationModal(this.i18n('out'), this.osdService.markOut),
+ disable: () => this.isNotSelectedOrInState('out'),
+ icon: 'fa-arrow-left'
+ },
+ {
+ name: this.actionLabels.MARK_IN,
+ permission: 'update',
+ click: () => this.showConfirmationModal(this.i18n('in'), this.osdService.markIn),
+ disable: () => this.isNotSelectedOrInState('in'),
+ icon: 'fa-arrow-right'
+ },
+ {
+ name: this.actionLabels.MARK_DOWN,
+ permission: 'update',
+ click: () => this.showConfirmationModal(this.i18n('down'), this.osdService.markDown),
+ disable: () => this.isNotSelectedOrInState('down'),
+ icon: 'fa-arrow-down'
+ },
+ {
+ name: this.actionLabels.MARK_LOST,
+ permission: 'delete',
+ click: () =>
+ this.showCriticalConfirmationModal(
+ this.i18n('Mark'),
+ this.i18n('OSD lost'),
+ this.i18n('marked lost'),
+ this.osdService.markLost
+ ),
+ disable: () => this.isNotSelectedOrInState('up'),
+ icon: 'fa-unlink'
+ },
+ {
+ name: this.actionLabels.PURGE,
+ permission: 'delete',
+ click: () =>
+ this.showCriticalConfirmationModal(
+ this.i18n('Purge'),
+ this.i18n('OSD'),
+ this.i18n('purged'),
+ this.osdService.purge
+ ),
+ disable: () => this.isNotSelectedOrInState('up'),
+ icon: 'fa-eraser'
+ },
+ {
+ name: this.actionLabels.DESTROY,
+ permission: 'delete',
+ click: () =>
+ this.showCriticalConfirmationModal(
+ this.i18n('destroy'),
+ this.i18n('OSD'),
+ this.i18n('destroyed'),
+ this.osdService.destroy
+ ),
+ disable: () => this.isNotSelectedOrInState('up'),
+ icon: 'fa-remove'
+ }
+ ];
+ this.advancedTableActions = [
+ {
+ name: this.i18n('Cluster-wide Flags'),
+ icon: 'fa-flag',
+ click: () => this.configureFlagsAction(),
+ permission: this.permissions.osd.read
+ },
+ {
+ name: this.i18n('Cluster-wide Recovery Priority'),
+ icon: 'fa-cog',
+ click: () => this.configureQosParamsAction(),
+ permission: this.permissions.configOpt.read
+ },
+ {
+ name: this.i18n('PG scrub'),
+ icon: 'fa-stethoscope',
+ click: () => this.configurePgScrubAction(),
+ permission: this.permissions.configOpt.read
+ }
+ ];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ { prop: 'host.name', name: this.i18n('Host') },
+ { prop: 'id', name: this.i18n('ID'), cellTransformation: CellTemplate.bold },
+ { prop: 'collectedStates', name: this.i18n('Status'), cellTemplate: this.statusColor },
+ { prop: 'stats.numpg', name: this.i18n('PGs') },
+ { prop: 'stats.stat_bytes', name: this.i18n('Size'), pipe: this.dimlessBinaryPipe },
+ { prop: 'stats.usage', name: this.i18n('Usage'), cellTemplate: this.osdUsageTpl },
+ {
+ prop: 'stats_history.out_bytes',
+ name: this.i18n('Read bytes'),
+ cellTransformation: CellTemplate.sparkline
+ },
+ {
+ prop: 'stats_history.in_bytes',
+ name: this.i18n('Write bytes'),
+ cellTransformation: CellTemplate.sparkline
+ },
+ {
+ prop: 'stats.op_r',
+ name: this.i18n('Read ops'),
+ cellTransformation: CellTemplate.perSecond
+ },
+ {
+ prop: 'stats.op_w',
+ name: this.i18n('Write ops'),
+ cellTransformation: CellTemplate.perSecond
+ }
+ ];
+
+ this.removeActionsWithNoPermissions();
+ }
+
+ get hasOsdSelected() {
+ if (this.selection.hasSelection) {
+ const osdId = this.selection.first().id;
+ const osd = this.osds.filter((o) => o.id === osdId).pop();
+ return !!osd;
+ }
+ return false;
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ /**
+ * Returns true if no row is selected or if the selected row is in the given
+ * state. Useful for deactivating the corresponding menu entry.
+ */
+ isNotSelectedOrInState(state: 'in' | 'up' | 'down' | 'out'): boolean {
+ if (!this.hasOsdSelected) {
+ return true;
+ }
+
+ const osdId = this.selection.first().id;
+ const osd = this.osds.filter((o) => o.id === osdId).pop();
+
+ if (!osd) {
+ // `osd` is undefined if the selected OSD has been removed.
+ return true;
+ }
+
+ switch (state) {
+ case 'in':
+ return osd.in === 1;
+ case 'out':
+ return osd.in !== 1;
+ case 'down':
+ return osd.up !== 1;
+ case 'up':
+ return osd.up === 1;
+ }
+ }
+
+ getOsdList() {
+ this.osdService.getList().subscribe((data: any[]) => {
+ this.osds = data.map((osd) => {
+ osd.collectedStates = OsdListComponent.collectStates(osd);
+ osd.stats_history.out_bytes = osd.stats_history.op_out_bytes.map((i) => i[1]);
+ osd.stats_history.in_bytes = osd.stats_history.op_in_bytes.map((i) => i[1]);
+ osd.stats.usage = osd.stats.stat_bytes_used / osd.stats.stat_bytes;
+ osd.cdIsBinary = true;
+ return osd;
+ });
+ });
+ }
+
+ scrubAction(deep) {
+ if (!this.hasOsdSelected) {
+ return;
+ }
+
+ const initialState = {
+ selected: this.tableComponent.selection.selected,
+ deep: deep
+ };
+
+ this.bsModalRef = this.modalService.show(OsdScrubModalComponent, { initialState });
+ }
+
+ configureFlagsAction() {
+ this.bsModalRef = this.modalService.show(OsdFlagsModalComponent, {});
+ }
+
+ showConfirmationModal(markAction: string, onSubmit: (id: number) => Observable<any>) {
+ this.bsModalRef = this.modalService.show(ConfirmationModalComponent, {
+ initialState: {
+ titleText: this.i18n('Mark OSD {{markAction}}', { markAction: markAction }),
+ buttonText: this.i18n('Mark {{markAction}}', { markAction: markAction }),
+ bodyTpl: this.markOsdConfirmationTpl,
+ bodyContext: {
+ markActionDescription: markAction
+ },
+ onSubmit: () => {
+ onSubmit
+ .call(this.osdService, this.selection.first().id)
+ .subscribe(() => this.bsModalRef.hide());
+ }
+ }
+ });
+ }
+
+ reweight() {
+ const selectedOsd = this.osds.filter((o) => o.id === this.selection.first().id).pop();
+ this.modalService.show(OsdReweightModalComponent, {
+ initialState: {
+ currentWeight: selectedOsd.weight,
+ osdId: selectedOsd.id
+ }
+ });
+ }
+
+ showCriticalConfirmationModal(
+ actionDescription: string,
+ itemDescription: string,
+ templateItemDescription: string,
+ action: (id: number) => Observable<any>
+ ): void {
+ this.osdService.safeToDestroy(this.selection.first().id).subscribe((result) => {
+ const modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ actionDescription: actionDescription,
+ itemDescription: itemDescription,
+ bodyTemplate: this.criticalConfirmationTpl,
+ bodyContext: {
+ result: result,
+ actionDescription: templateItemDescription
+ },
+ submitAction: () => {
+ action
+ .call(this.osdService, this.selection.first().id)
+ .subscribe(() => modalRef.hide());
+ }
+ }
+ });
+ });
+ }
+
+ configureQosParamsAction() {
+ this.bsModalRef = this.modalService.show(OsdRecvSpeedModalComponent, {});
+ }
+
+ configurePgScrubAction() {
+ this.bsModalRef = this.modalService.show(OsdPgScrubModalComponent, { class: 'modal-lg' });
+ }
+
+ /**
+ * Removes all actions from 'advancedTableActions' that need a permission the user doesn't have.
+ */
+ private removeActionsWithNoPermissions() {
+ if (!this.permissions) {
+ this.advancedTableActions = [];
+ return;
+ }
+
+ this.advancedTableActions = this.advancedTableActions.filter((action) => action.permission);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.html
new file mode 100644
index 00000000..080f121f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.html
@@ -0,0 +1,9 @@
+<table>
+ <tr style="height: 10px;"
+ *ngFor="let row of valuesStyle">
+ <td style="width: 10px; height: 10px;"
+ *ngFor="let col of row"
+ [ngStyle]="col">
+ </td>
+ </tr>
+</table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.spec.ts
new file mode 100644
index 00000000..5292f945
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../../testing/unit-test-helper';
+import { OsdPerformanceHistogramComponent } from './osd-performance-histogram.component';
+
+describe('OsdPerformanceHistogramComponent', () => {
+ let component: OsdPerformanceHistogramComponent;
+ let fixture: ComponentFixture<OsdPerformanceHistogramComponent>;
+
+ configureTestBed({
+ declarations: [OsdPerformanceHistogramComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdPerformanceHistogramComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.ts
new file mode 100644
index 00000000..584446f9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-performance-histogram/osd-performance-histogram.component.ts
@@ -0,0 +1,60 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Component({
+ selector: 'cd-osd-performance-histogram',
+ templateUrl: './osd-performance-histogram.component.html',
+ styleUrls: ['./osd-performance-histogram.component.scss']
+})
+export class OsdPerformanceHistogramComponent implements OnChanges {
+ @Input()
+ histogram: any;
+ valuesStyle: any;
+ last = {};
+
+ constructor() {}
+
+ ngOnChanges() {
+ this.render();
+ }
+
+ hexdigits(v): string {
+ const i = Math.floor(v * 255).toString(16);
+ return i.length === 1 ? '0' + i : i;
+ }
+
+ hexcolor(r, g, b) {
+ return '#' + this.hexdigits(r) + this.hexdigits(g) + this.hexdigits(b);
+ }
+
+ render() {
+ if (!this.histogram) {
+ return;
+ }
+ let max = 0;
+
+ _.each(this.histogram.values, (row, i) => {
+ _.each(row, (col, j) => {
+ let val;
+ if (this.last && this.last[i] && this.last[i][j]) {
+ val = col - this.last[i][j];
+ } else {
+ val = col;
+ }
+ max = Math.max(max, val);
+ });
+ });
+
+ this.valuesStyle = this.histogram.values.map((row, i) => {
+ return row.map((col, j) => {
+ const val = this.last && this.last[i] && this.last[i][j] ? col - this.last[i][j] : col;
+ const g = max ? val / max : 0;
+ const r = 1 - g;
+ return { backgroundColor: this.hexcolor(r, g, 0) };
+ });
+ });
+
+ this.last = this.histogram.values;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.html
new file mode 100644
index 00000000..1077fba3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.html
@@ -0,0 +1,50 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title">{{ action | titlecase }} {{ resource | upperFirst }}</ng-container>
+
+ <ng-container class="modal-content">
+ <form class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="osdPgScrubForm"
+ novalidate
+ cdFormScope="osd">
+ <div class="modal-body osd-modal">
+ <!-- Basic -->
+ <cd-config-option [optionNames]="basicOptions"
+ [optionsForm]="osdPgScrubForm"
+ [optionsFormDir]="formDir"
+ [optionsFormGroupName]="'basicFormGroup'"
+ #basicOptionsValues></cd-config-option>
+ <!-- Advanced -->
+ <div class="row">
+ <div class="col-sm-12">
+ <a class="pull-right margin-right-md"
+ (click)="advancedEnabled = true"
+ *ngIf="!advancedEnabled"
+ i18n>Advanced...</a>
+ </div>
+ </div>
+ <div *ngIf="advancedEnabled">
+ <h2 class="page-header"
+ i18n>Advanced configuration options</h2>
+ <cd-config-option [optionNames]="advancedOptions"
+ [optionsForm]="osdPgScrubForm"
+ [optionsFormDir]="formDir"
+ [optionsFormGroupName]="'advancedFormGroup'"
+ #advancedOptionsValues></cd-config-option>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button *ngIf="permissions.configOpt.update"
+ (submitAction)="submitAction()"
+ [form]="osdPgScrubForm"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide">
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.spec.ts
new file mode 100644
index 00000000..3fb4ee79
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.spec.ts
@@ -0,0 +1,65 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { OsdPgScrubModalComponent } from './osd-pg-scrub-modal.component';
+
+describe('OsdPgScrubModalComponent', () => {
+ let component: OsdPgScrubModalComponent;
+ let fixture: ComponentFixture<OsdPgScrubModalComponent>;
+ let configurationService: ConfigurationService;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ ModalModule.forRoot(),
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ declarations: [OsdPgScrubModalComponent],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdPgScrubModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ configurationService = TestBed.get(ConfigurationService);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('submitAction', () => {
+ let notificationService: NotificationService;
+
+ beforeEach(() => {
+ spyOn(TestBed.get(Router), 'navigate').and.stub();
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show');
+ });
+
+ it('test create success notification', () => {
+ spyOn(configurationService, 'bulkCreate').and.returnValue(observableOf([]));
+ component.submitAction();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Updated PG scrub options'
+ );
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.ts
new file mode 100644
index 00000000..b21136be
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.component.ts
@@ -0,0 +1,70 @@
+import { Component, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { forkJoin as observableForkJoin } from 'rxjs';
+
+import { ConfigOptionComponent } from '../../../../shared/components/config-option/config-option.component';
+import { ActionLabelsI18n } from '../../../../shared/constants/app.constants';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { Permissions } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { OsdPgScrubModalOptions } from './osd-pg-scrub-modal.options';
+
+@Component({
+ selector: 'cd-osd-pg-scrub-modal',
+ templateUrl: './osd-pg-scrub-modal.component.html',
+ styleUrls: ['./osd-pg-scrub-modal.component.scss']
+})
+export class OsdPgScrubModalComponent {
+ osdPgScrubForm: CdFormGroup;
+ action: string;
+ resource: string;
+ permissions: Permissions;
+
+ @ViewChild('basicOptionsValues')
+ basicOptionsValues: ConfigOptionComponent;
+ basicOptions: Array<string> = OsdPgScrubModalOptions.basicOptions;
+
+ @ViewChild('advancedOptionsValues')
+ advancedOptionsValues: ConfigOptionComponent;
+ advancedOptions: Array<string> = OsdPgScrubModalOptions.advancedOptions;
+
+ advancedEnabled = false;
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private authStorageService: AuthStorageService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.osdPgScrubForm = new CdFormGroup({});
+ this.resource = this.i18n('PG scrub options');
+ this.action = this.actionLabels.EDIT;
+ this.permissions = this.authStorageService.getPermissions();
+ }
+
+ submitAction() {
+ const observables = [this.basicOptionsValues.saveValues()];
+
+ if (this.advancedOptionsValues) {
+ observables.push(this.advancedOptionsValues.saveValues());
+ }
+
+ observableForkJoin(observables).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated PG scrub options')
+ );
+ this.bsModalRef.hide();
+ },
+ () => {
+ this.bsModalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.options.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.options.ts
new file mode 100644
index 00000000..b7c07d18
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-pg-scrub-modal/osd-pg-scrub-modal.options.ts
@@ -0,0 +1,39 @@
+export class OsdPgScrubModalOptions {
+ public static basicOptions: Array<string> = [
+ 'osd_scrub_during_recovery',
+ 'osd_scrub_begin_hour',
+ 'osd_scrub_end_hour',
+ 'osd_scrub_begin_week_day',
+ 'osd_scrub_end_week_day',
+ 'osd_scrub_min_interval',
+ 'osd_scrub_max_interval',
+ 'osd_deep_scrub_interval',
+ 'osd_scrub_auto_repair',
+ 'osd_max_scrubs',
+ 'osd_scrub_priority',
+ 'osd_scrub_sleep'
+ ];
+
+ public static advancedOptions: Array<string> = [
+ 'osd_scrub_auto_repair_num_errors',
+ 'osd_debug_deep_scrub_sleep',
+ 'osd_deep_scrub_keys',
+ 'osd_deep_scrub_large_omap_object_key_threshold',
+ 'osd_deep_scrub_large_omap_object_value_sum_threshold',
+ 'osd_deep_scrub_randomize_ratio',
+ 'osd_deep_scrub_stride',
+ 'osd_deep_scrub_update_digest_min_age',
+ 'osd_op_queue_mclock_scrub_lim',
+ 'osd_op_queue_mclock_scrub_res',
+ 'osd_op_queue_mclock_scrub_wgt',
+ 'osd_requested_scrub_priority',
+ 'osd_scrub_backoff_ratio',
+ 'osd_scrub_chunk_max',
+ 'osd_scrub_chunk_min',
+ 'osd_scrub_cost',
+ 'osd_scrub_interval_randomize_ratio',
+ 'osd_scrub_invalid_stats',
+ 'osd_scrub_load_threshold',
+ 'osd_scrub_max_preemptions'
+ ];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html
new file mode 100755
index 00000000..91d7da00
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html
@@ -0,0 +1,98 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>OSD Recovery Priority</ng-container>
+
+ <ng-container class="modal-content">
+ <form class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="osdRecvSpeedForm"
+ novalidate
+ cdFormScope="osd">
+ <div class="modal-body">
+ <!-- Priority -->
+ <div class="form-group"
+ [ngClass]="{'has-error': osdRecvSpeedForm.showError('priority', formDir)}">
+ <label class="control-label col-sm-6"
+ for="priority">
+ <ng-container i18n>Priority</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-6">
+ <select class="form-control"
+ formControlName="priority"
+ id="priority"
+ (change)="onPriorityChange($event.target.value)">
+ <option *ngFor="let priority of priorities"
+ [value]="priority.name">
+ {{ priority.text }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.showError('priority', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Customize priority -->
+ <div class="form-group">
+ <div class="col-sm-offset-6 col-sm-6">
+ <div class="checkbox checkbox-primary">
+ <input formControlName="customizePriority"
+ id="customizePriority"
+ type="checkbox"
+ (change)="onCustomizePriorityChange()">
+ <label i18n
+ for="customizePriority">Customize priority values</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Priority values -->
+ <div class="form-group" *ngFor="let attr of priorityAttrs | keyvalue"
+ [ngClass]="{'has-error': osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir)}">
+ <label class="control-label col-sm-6"
+ [for]="attr.key">{{ attr.value.text }}
+ <cd-helper *ngIf="attr.value.desc">{{ attr.value.desc }}</cd-helper>
+ <span class="required" *ngIf="osdRecvSpeedForm.getValue('customizePriority')"></span>
+ </label>
+ <div class="col-sm-6">
+ <input class="form-control"
+ type="number"
+ [id]="attr.key"
+ [formControlName]="attr.key"
+ [readonly]="!osdRecvSpeedForm.getValue('customizePriority')">
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'pattern')"
+ i18n>{{ attr.value.patternHelpText }}</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'max')"
+ i18n>The entered value is too high! It must not be greater than {{ attr.value.maxValue }}.</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'min')"
+ i18n>The entered value is too low! It must not be lower than {{ attr.value.minValue }}.</span>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button *ngIf="permissions.configOpt.update"
+ (submitAction)="submitAction()"
+ [form]="osdRecvSpeedForm"
+ i18n>Submit</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts
new file mode 100755
index 00000000..57855adb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts
@@ -0,0 +1,318 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as _ from 'lodash';
+import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { OsdRecvSpeedModalComponent } from './osd-recv-speed-modal.component';
+
+describe('OsdRecvSpeedModalComponent', () => {
+ let component: OsdRecvSpeedModalComponent;
+ let fixture: ComponentFixture<OsdRecvSpeedModalComponent>;
+ let configurationService: ConfigurationService;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ ModalModule.forRoot(),
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ declarations: [OsdRecvSpeedModalComponent],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ let configOptions = [];
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdRecvSpeedModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ configurationService = TestBed.get(ConfigurationService);
+ configOptions = [
+ {
+ name: 'osd_max_backfills',
+ desc: '',
+ type: 'uint',
+ default: 1
+ },
+ {
+ name: 'osd_recovery_max_active',
+ desc: '',
+ type: 'uint',
+ default: 3
+ },
+ {
+ name: 'osd_recovery_max_single_start',
+ desc: '',
+ type: 'uint',
+ default: 1
+ },
+ {
+ name: 'osd_recovery_sleep',
+ desc: 'Time in seconds to sleep before next recovery or backfill op',
+ type: 'float',
+ default: 0
+ }
+ ];
+ spyOn(configurationService, 'filter').and.returnValue(observableOf(configOptions));
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('ngOnInit', () => {
+ let setPriority;
+ let setValidators;
+
+ beforeEach(() => {
+ setPriority = spyOn(component, 'setPriority').and.callThrough();
+ setValidators = spyOn(component, 'setValidators').and.callThrough();
+ component.ngOnInit();
+ });
+
+ it('should call setValidators', () => {
+ expect(setValidators).toHaveBeenCalled();
+ });
+
+ it('should get and set priority correctly', () => {
+ const defaultPriority = _.find(component.priorities, (p) => {
+ return _.isEqual(p.name, 'default');
+ });
+ expect(setPriority).toHaveBeenCalledWith(defaultPriority);
+ });
+
+ it('should set descriptions correctly', () => {
+ expect(component.priorityAttrs['osd_max_backfills'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_max_active'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_max_single_start'].desc).toBe('');
+ expect(component.priorityAttrs['osd_recovery_sleep'].desc).toBe(
+ 'Time in seconds to sleep before next recovery or backfill op'
+ );
+ });
+ });
+
+ describe('setPriority', () => {
+ it('should prepare the form for a custom priority', () => {
+ const customPriority = {
+ name: 'custom',
+ text: 'Custom',
+ values: {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 4,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 1
+ }
+ };
+
+ component.setPriority(customPriority);
+
+ const customInPriorities = _.find(component.priorities, (p) => {
+ return p.name === 'custom';
+ });
+
+ expect(customInPriorities).not.toBeNull();
+ expect(component.osdRecvSpeedForm.getValue('priority')).toBe('custom');
+ expect(component.osdRecvSpeedForm.getValue('osd_max_backfills')).toBe(1);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_active')).toBe(4);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_single_start')).toBe(1);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_sleep')).toBe(1);
+ });
+
+ it('should prepare the form for a none custom priority', () => {
+ const lowPriority = {
+ name: 'low',
+ text: 'Low',
+ values: {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 1,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0.5
+ }
+ };
+
+ component.setPriority(lowPriority);
+
+ const customInPriorities = _.find(component.priorities, (p) => {
+ return p.name === 'custom';
+ });
+
+ expect(customInPriorities).toBeUndefined();
+ expect(component.osdRecvSpeedForm.getValue('priority')).toBe('low');
+ expect(component.osdRecvSpeedForm.getValue('osd_max_backfills')).toBe(1);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_active')).toBe(1);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_single_start')).toBe(1);
+ expect(component.osdRecvSpeedForm.getValue('osd_recovery_sleep')).toBe(0.5);
+ });
+ });
+
+ describe('detectPriority', () => {
+ const configOptionsLow = {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 1,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0.5
+ };
+
+ const configOptionsDefault = {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 3,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0
+ };
+
+ const configOptionsHigh = {
+ osd_max_backfills: 4,
+ osd_recovery_max_active: 4,
+ osd_recovery_max_single_start: 4,
+ osd_recovery_sleep: 0
+ };
+
+ const configOptionsCustom = {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 2,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0
+ };
+
+ const configOptionsIncomplete = {
+ osd_max_backfills: 1,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0
+ };
+
+ it('should return priority "low" if the config option values have been set accordingly', () => {
+ component.detectPriority(configOptionsLow, (priority) => {
+ expect(priority.name).toBe('low');
+ });
+ expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy();
+ });
+
+ it('should return priority "default" if the config option values have been set accordingly', () => {
+ component.detectPriority(configOptionsDefault, (priority) => {
+ expect(priority.name).toBe('default');
+ });
+ expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy();
+ });
+
+ it('should return priority "high" if the config option values have been set accordingly', () => {
+ component.detectPriority(configOptionsHigh, (priority) => {
+ expect(priority.name).toBe('high');
+ });
+ expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy();
+ });
+
+ it('should return priority "custom" if the config option values do not match any priority', () => {
+ component.detectPriority(configOptionsCustom, (priority) => {
+ expect(priority.name).toBe('custom');
+ });
+ expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeTruthy();
+ });
+
+ it('should return no priority if the config option values are incomplete', () => {
+ component.detectPriority(configOptionsIncomplete, (priority) => {
+ expect(priority.name).toBeNull();
+ });
+ expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy();
+ });
+ });
+
+ describe('getCurrentValues', () => {
+ it('should return default values if no value has been set by the user', () => {
+ const currentValues = component.getCurrentValues(configOptions);
+ configOptions.forEach((configOption) => {
+ const configOptionValue = currentValues.values[configOption.name];
+ expect(configOptionValue).toBe(configOption.default);
+ });
+ });
+
+ it('should return the values set by the user if they exist', () => {
+ configOptions.forEach((configOption) => {
+ configOption['value'] = [{ section: 'osd', value: 7 }];
+ });
+
+ const currentValues = component.getCurrentValues(configOptions);
+ Object.values(currentValues.values).forEach((configValue) => {
+ expect(configValue).toBe(7);
+ });
+ });
+
+ it('should return the default value if one is missing', () => {
+ for (let i = 1; i < configOptions.length; i++) {
+ configOptions[i]['value'] = [{ section: 'osd', value: 7 }];
+ }
+
+ const currentValues = component.getCurrentValues(configOptions);
+ Object.entries(currentValues.values).forEach(([configName, configValue]) => {
+ if (configName === 'osd_max_backfills') {
+ expect(configValue).toBe(1);
+ } else {
+ expect(configValue).toBe(7);
+ }
+ });
+ });
+
+ it('should return nothing if neither value nor default value is given', () => {
+ configOptions[0].default = null;
+ const currentValues = component.getCurrentValues(configOptions);
+ expect(currentValues.values).not.toContain('osd_max_backfills');
+ });
+ });
+
+ describe('setDescription', () => {
+ it('should set the description if one is given', () => {
+ component.setDescription(configOptions);
+ Object.keys(component.priorityAttrs).forEach((configOptionName) => {
+ if (configOptionName === 'osd_recovery_sleep') {
+ expect(component.priorityAttrs[configOptionName].desc).toBe(
+ 'Time in seconds to sleep before next recovery or backfill op'
+ );
+ } else {
+ expect(component.priorityAttrs[configOptionName].desc).toBe('');
+ }
+ });
+ });
+ });
+
+ describe('setValidators', () => {
+ it('should set needed validators for config option', () => {
+ component.setValidators(configOptions);
+ configOptions.forEach((configOption) => {
+ const control = component.osdRecvSpeedForm.controls[configOption.name];
+
+ if (configOption.type === 'float') {
+ expect(component.priorityAttrs[configOption.name].patternHelpText).toBe(
+ 'The entered value needs to be a number or decimal.'
+ );
+ } else {
+ expect(component.priorityAttrs[configOption.name].minValue).toBe(0);
+ expect(component.priorityAttrs[configOption.name].patternHelpText).toBe(
+ 'The entered value needs to be an unsigned number.'
+ );
+
+ control.setValue(-1);
+ expect(control.hasError('min')).toBeTruthy();
+ }
+
+ control.setValue(null);
+ expect(control.hasError('required')).toBeTruthy();
+ control.setValue('E');
+ expect(control.hasError('pattern')).toBeTruthy();
+ control.setValue(3);
+ expect(control.hasError('required')).toBeFalsy();
+ expect(control.hasError('min')).toBeFalsy();
+ expect(control.hasError('pattern')).toBeFalsy();
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts
new file mode 100755
index 00000000..d98ea39a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts
@@ -0,0 +1,238 @@
+import { Component, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { ConfigOptionTypes } from '../../../../shared/components/config-option/config-option.types';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { Permissions } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-osd-recv-speed-modal',
+ templateUrl: './osd-recv-speed-modal.component.html',
+ styleUrls: ['./osd-recv-speed-modal.component.scss']
+})
+export class OsdRecvSpeedModalComponent implements OnInit {
+ osdRecvSpeedForm: CdFormGroup;
+ permissions: Permissions;
+
+ priorities = [];
+ priorityAttrs = {};
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private authStorageService: AuthStorageService,
+ private configService: ConfigurationService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ private osdService: OsdService
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ this.priorities = this.osdService.osdRecvSpeedModalPriorities.KNOWN_PRIORITIES;
+ this.osdRecvSpeedForm = new CdFormGroup({
+ priority: new FormControl(null, { validators: [Validators.required] }),
+ customizePriority: new FormControl(false)
+ });
+ this.priorityAttrs = {
+ osd_max_backfills: {
+ text: this.i18n('Max Backfills'),
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
+ },
+ osd_recovery_max_active: {
+ text: this.i18n('Recovery Max Active'),
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
+ },
+ osd_recovery_max_single_start: {
+ text: this.i18n('Recovery Max Single Start'),
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
+ },
+ osd_recovery_sleep: {
+ text: this.i18n('Recovery Sleep'),
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
+ }
+ };
+
+ Object.keys(this.priorityAttrs).forEach((configOptionName) => {
+ this.osdRecvSpeedForm.addControl(
+ configOptionName,
+ new FormControl(null, { validators: [Validators.required] })
+ );
+ });
+ }
+
+ ngOnInit() {
+ this.configService.filter(Object.keys(this.priorityAttrs)).subscribe((data: any) => {
+ const config_option_values = this.getCurrentValues(data);
+ this.detectPriority(config_option_values.values, (priority) => {
+ this.setPriority(priority);
+ });
+ this.setDescription(config_option_values.configOptions);
+ this.setValidators(config_option_values.configOptions);
+ });
+ }
+
+ detectPriority(configOptionValues: any, callbackFn: Function) {
+ const priority = _.find(this.priorities, (p) => {
+ return _.isEqual(p.values, configOptionValues);
+ });
+
+ this.osdRecvSpeedForm.controls.customizePriority.setValue(false);
+
+ if (priority) {
+ return callbackFn(priority);
+ }
+
+ if (Object.entries(configOptionValues).length === 4) {
+ this.osdRecvSpeedForm.controls.customizePriority.setValue(true);
+ return callbackFn(
+ Object({ name: 'custom', text: this.i18n('Custom'), values: configOptionValues })
+ );
+ }
+
+ return callbackFn(this.priorities[0]);
+ }
+
+ getCurrentValues(configOptions: any) {
+ const currentValues = { values: {}, configOptions: [] };
+ configOptions.forEach((configOption) => {
+ currentValues.configOptions.push(configOption);
+
+ if ('value' in configOption) {
+ configOption.value.forEach((value) => {
+ if (value.section === 'osd') {
+ currentValues.values[configOption.name] = Number(value.value);
+ }
+ });
+ } else if ('default' in configOption && configOption.default !== null) {
+ currentValues.values[configOption.name] = Number(configOption.default);
+ }
+ });
+ return currentValues;
+ }
+
+ setDescription(configOptions: Array<any>) {
+ configOptions.forEach((configOption) => {
+ if (configOption.desc !== '') {
+ this.priorityAttrs[configOption.name].desc = configOption.desc;
+ }
+ });
+ }
+
+ setPriority(priority: any) {
+ const customPriority = _.find(this.priorities, (p) => {
+ return p.name === 'custom';
+ });
+
+ if (priority.name === 'custom') {
+ if (!customPriority) {
+ this.priorities.push(priority);
+ }
+ } else {
+ if (customPriority) {
+ this.priorities.splice(this.priorities.indexOf(customPriority), 1);
+ }
+ }
+
+ this.osdRecvSpeedForm.controls.priority.setValue(priority.name);
+ Object.entries(priority.values).forEach(([name, value]) => {
+ this.osdRecvSpeedForm.controls[name].setValue(value);
+ });
+ }
+
+ setValidators(configOptions: Array<any>) {
+ configOptions.forEach((configOption) => {
+ const typeValidators = ConfigOptionTypes.getTypeValidators(configOption);
+ if (typeValidators) {
+ typeValidators.validators.push(Validators.required);
+
+ if ('max' in typeValidators && typeValidators.max !== '') {
+ this.priorityAttrs[configOption.name].maxValue = typeValidators.max;
+ }
+
+ if ('min' in typeValidators && typeValidators.min !== '') {
+ this.priorityAttrs[configOption.name].minValue = typeValidators.min;
+ }
+
+ this.priorityAttrs[configOption.name].patternHelpText = typeValidators.patternHelpText;
+ this.osdRecvSpeedForm.controls[configOption.name].setValidators(typeValidators.validators);
+ } else {
+ this.osdRecvSpeedForm.controls[configOption.name].setValidators(Validators.required);
+ }
+ });
+ }
+
+ onCustomizePriorityChange() {
+ const values = {};
+ Object.keys(this.priorityAttrs).forEach((configOptionName) => {
+ values[configOptionName] = this.osdRecvSpeedForm.getValue(configOptionName);
+ });
+
+ if (this.osdRecvSpeedForm.getValue('customizePriority')) {
+ const customPriority = {
+ name: 'custom',
+ text: this.i18n('Custom'),
+ values: values
+ };
+ this.setPriority(customPriority);
+ } else {
+ this.detectPriority(values, (priority) => {
+ this.setPriority(priority);
+ });
+ }
+ }
+
+ onPriorityChange(selectedPriorityName) {
+ const selectedPriority =
+ _.find(this.priorities, (p) => {
+ return p.name === selectedPriorityName;
+ }) || this.priorities[0];
+ // Uncheck the 'Customize priority values' checkbox.
+ this.osdRecvSpeedForm.get('customizePriority').setValue(false);
+ // Set the priority profile values.
+ this.setPriority(selectedPriority);
+ }
+
+ submitAction() {
+ const options = {};
+ Object.keys(this.priorityAttrs).forEach((configOptionName) => {
+ options[configOptionName] = {
+ section: 'osd',
+ value: this.osdRecvSpeedForm.getValue(configOptionName)
+ };
+ });
+
+ this.configService.bulkCreate({ options: options }).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated OSD recovery speed priority "{{value}}"', {
+ value: this.osdRecvSpeedForm.getValue('priority')
+ })
+ );
+ this.bsModalRef.hide();
+ },
+ () => {
+ this.bsModalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html
new file mode 100644
index 00000000..7d9e28eb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html
@@ -0,0 +1,38 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>Reweight OSD</ng-container>
+
+ <ng-container class="modal-content">
+ <form class="form-horizontal"
+ [formGroup]="reweightForm">
+ <div class="modal-body" [ngClass]="{'has-error': weight.errors}">
+ <div class="row">
+ <label for="weight" class="col-sm-2 control-label">Weight</label>
+ <div class="col-sm-10">
+ <input id="weight" class="form-control" type="number"
+ step="0.1" formControlName="weight" min="0" max="1"
+ [value]="currentWeight">
+ <span class="help-block"
+ *ngIf="weight.errors">
+ <span *ngIf="weight.errors?.required"
+ i18n>This field is required.</span>
+ <span *ngIf="weight.errors?.max || weight.errors?.min"
+ i18n>The value needs to be between 0 and 1.</span>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <cd-submit-button (submitAction)="reweight()"
+ [form]="reweightForm"
+ [disabled]="reweightForm.invalid"
+ i18n>Reweight</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.spec.ts
new file mode 100644
index 00000000..78c3860c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.spec.ts
@@ -0,0 +1,52 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { of } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { BackButtonComponent } from '../../../../shared/components/back-button/back-button.component';
+import { ModalComponent } from '../../../../shared/components/modal/modal.component';
+import { SubmitButtonComponent } from '../../../../shared/components/submit-button/submit-button.component';
+import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
+import { OsdReweightModalComponent } from './osd-reweight-modal.component';
+
+describe('OsdReweightModalComponent', () => {
+ let component: OsdReweightModalComponent;
+ let fixture: ComponentFixture<OsdReweightModalComponent>;
+
+ configureTestBed({
+ imports: [ReactiveFormsModule, HttpClientTestingModule, RouterTestingModule],
+ declarations: [
+ OsdReweightModalComponent,
+ ModalComponent,
+ SubmitButtonComponent,
+ BackButtonComponent
+ ],
+ providers: [OsdService, BsModalRef, CdFormBuilder, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdReweightModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should call OsdService::reweight() on submit', () => {
+ component.osdId = 1;
+ component.reweightForm.get('weight').setValue(0.5);
+
+ const osdServiceSpy = spyOn(TestBed.get(OsdService), 'reweight').and.callFake(() => of(true));
+ component.reweight();
+
+ expect(osdServiceSpy.calls.count()).toBe(1);
+ expect(osdServiceSpy.calls.first().args).toEqual([1, 0.5]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.ts
new file mode 100644
index 00000000..4f884d1b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit } from '@angular/core';
+import { Validators } from '@angular/forms';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { OsdService } from '../../../../shared/api/osd.service';
+import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+
+@Component({
+ selector: 'cd-osd-reweight-modal',
+ templateUrl: './osd-reweight-modal.component.html',
+ styleUrls: ['./osd-reweight-modal.component.scss']
+})
+export class OsdReweightModalComponent implements OnInit {
+ currentWeight = 1;
+ osdId: number;
+ reweightForm: CdFormGroup;
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private osdService: OsdService,
+ private fb: CdFormBuilder
+ ) {}
+
+ get weight() {
+ return this.reweightForm.get('weight');
+ }
+
+ ngOnInit() {
+ this.reweightForm = this.fb.group({
+ weight: this.fb.control(this.currentWeight, [
+ Validators.required,
+ Validators.max(1),
+ Validators.min(0)
+ ])
+ });
+ }
+
+ reweight() {
+ this.osdService
+ .reweight(this.osdId, this.reweightForm.value.weight)
+ .subscribe(() => this.bsModalRef.hide());
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html
new file mode 100644
index 00000000..ba05c975
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html
@@ -0,0 +1,29 @@
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>OSDs {deep, select, 1 {Deep }}Scrub</ng-container>
+
+ <ng-container class="modal-content">
+ <form name="scrubForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="scrubForm"
+ novalidate>
+ <div class="modal-body">
+ <div *ngIf="selected.length === 1">
+ <p i18n>You are about to apply a {deep, select, 1 {deep }}scrub to
+ the OSD <strong>{{ selected[0].id }}</strong>.</p>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <cd-submit-button (submitAction)="scrub()"
+ [form]="scrubForm"
+ i18n>Submit</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.spec.ts
new file mode 100644
index 00000000..cf08843c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.spec.ts
@@ -0,0 +1,49 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { OsdScrubModalComponent } from './osd-scrub-modal.component';
+
+describe('OsdScrubModalComponent', () => {
+ let component: OsdScrubModalComponent;
+ let fixture: ComponentFixture<OsdScrubModalComponent>;
+
+ const fakeService = {
+ list: () => {
+ return new Promise(() => {});
+ },
+ scrub: () => {
+ return new Promise(() => {});
+ },
+ scrub_many: () => {
+ return new Promise(() => {});
+ }
+ };
+
+ configureTestBed({
+ imports: [ReactiveFormsModule],
+ declarations: [OsdScrubModalComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ BsModalRef,
+ { provide: OsdService, useValue: fakeService },
+ { provide: NotificationService, useValue: fakeService },
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OsdScrubModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.ts
new file mode 100644
index 00000000..18b03254
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.ts
@@ -0,0 +1,54 @@
+import { Component, OnInit } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { OsdService } from '../../../../shared/api/osd.service';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-osd-scrub-modal',
+ templateUrl: './osd-scrub-modal.component.html',
+ styleUrls: ['./osd-scrub-modal.component.scss']
+})
+export class OsdScrubModalComponent implements OnInit {
+ deep: boolean;
+ selected = [];
+ scrubForm: FormGroup;
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private osdService: OsdService,
+ private notificationService: NotificationService,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.scrubForm = new FormGroup({});
+ }
+
+ scrub() {
+ const id = this.selected[0].id;
+
+ this.osdService.scrub(id, this.deep).subscribe(
+ () => {
+ const operation = this.deep ? 'Deep scrub' : 'Scrub';
+
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('{{operation}} was initialized in the following OSD: {{id}}', {
+ operation: operation,
+ id: id
+ })
+ );
+
+ this.bsModalRef.hide();
+ },
+ () => {
+ this.bsModalRef.hide();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html
new file mode 100644
index 00000000..a5b11ee7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.html
@@ -0,0 +1,32 @@
+<cd-table [data]="prometheusAlertService.alerts"
+ [columns]="columns"
+ identifier="fingerprint"
+ [forceIdentifier]="true"
+ [customCss]="customCss"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <tabset cdTableDetail *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <cd-table-key-value [renderObjects]="true"
+ [hideEmpty]="true"
+ [appendParentKey]="false"
+ [data]="selection.first()"
+ [customCss]="customCss"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ </tabset>
+</cd-table>
+
+<ng-template #externalLinkTpl
+ let-row="row"
+ let-value="value">
+ <a [href]="value" target="_blank"><i class="fa fa-line-chart"></i> Source</a>
+</ng-template>
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.spec.ts
new file mode 100644
index 00000000..85eb89f6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.spec.ts
@@ -0,0 +1,132 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { CoreModule } from '../../../../core/core.module';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../../shared/shared.module';
+import { CephModule } from '../../../ceph.module';
+import { DashboardModule } from '../../../dashboard/dashboard.module';
+import { ClusterModule } from '../../cluster.module';
+import { ActiveAlertListComponent } from './active-alert-list.component';
+
+describe('ActiveAlertListComponent', () => {
+ let component: ActiveAlertListComponent;
+ let fixture: ComponentFixture<ActiveAlertListComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ RouterTestingModule,
+ ToastrModule.forRoot(),
+ SharedModule,
+ ClusterModule,
+ DashboardModule,
+ CephModule,
+ CoreModule
+ ],
+ declarations: [],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ActiveAlertListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+ let combinations: number[][];
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Create Silence',
+ empty: 'Create Silence'
+ };
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ const permissionSwitch = (combination) => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(
+ combination[0],
+ combination[1],
+ combination[2]
+ );
+ tableActions.tableActions = component.tableActions;
+ tableActions.ngOnInit();
+ };
+
+ const testCombinations = (test: Function) => {
+ combinations.forEach((combination) => {
+ permissionSwitch(combination);
+ test();
+ });
+ };
+
+ describe('with every permission combination that includes create', () => {
+ beforeEach(() => {
+ combinations = [[1, 1, 1], [1, 1, 0], [1, 0, 1], [1, 0, 0]];
+ });
+
+ it(`always shows 'Create silence' as main action`, () => {
+ testCombinations(() => permissionHelper.testScenarios(scenario));
+ });
+
+ it('shows all actions', () => {
+ testCombinations(() => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+ });
+
+ describe('with every permission combination that does not include create', () => {
+ beforeEach(() => {
+ combinations = [[0, 1, 1], [0, 1, 0], [0, 0, 1], [0, 0, 0]];
+ });
+
+ it(`won't show any action`, () => {
+ testCombinations(() => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+ });
+
+ it('shows no actions', () => {
+ testCombinations(() => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts
new file mode 100644
index 00000000..a61dae42
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts
@@ -0,0 +1,97 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
+import { Icons } from '../../../../shared/enum/icons.enum';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { CdDatePipe } from '../../../../shared/pipes/cd-date.pipe';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { PrometheusAlertService } from '../../../../shared/services/prometheus-alert.service';
+import { URLBuilderService } from '../../../../shared/services/url-builder.service';
+
+const BASE_URL = 'silence'; // as only silence actions can be used
+
+@Component({
+ selector: 'cd-active-alert-list',
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }],
+ templateUrl: './active-alert-list.component.html',
+ styleUrls: ['./active-alert-list.component.scss']
+})
+export class ActiveAlertListComponent implements OnInit {
+ @ViewChild('externalLinkTpl')
+ externalLinkTpl: TemplateRef<any>;
+ columns: CdTableColumn[];
+ tableActions: CdTableAction[];
+ permission: Permission;
+ selection = new CdTableSelection();
+ icons = Icons;
+ customCss = {
+ 'label label-danger': 'active',
+ 'label label-warning': 'unprocessed',
+ 'label label-info': 'suppressed'
+ };
+
+ constructor(
+ // NotificationsComponent will refresh all alerts every 5s (No need to do it here as well)
+ private authStorageService: AuthStorageService,
+ public prometheusAlertService: PrometheusAlertService,
+ private urlBuilder: URLBuilderService,
+ private i18n: I18n,
+ private cdDatePipe: CdDatePipe
+ ) {
+ this.permission = this.authStorageService.getPermissions().prometheus;
+ this.tableActions = [
+ {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ icon: Icons.add,
+ routerLink: () =>
+ '/monitoring' + this.urlBuilder.getCreateFrom(this.selection.first().fingerprint),
+ name: this.i18n('Create Silence')
+ }
+ ];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'labels.alertname',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Job'),
+ prop: 'labels.job',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Severity'),
+ prop: 'labels.severity'
+ },
+ {
+ name: this.i18n('State'),
+ prop: 'status.state',
+ cellTransformation: CellTemplate.classAdding
+ },
+ {
+ name: this.i18n('Started'),
+ prop: 'startsAt',
+ pipe: this.cdDatePipe
+ },
+ {
+ name: this.i18n('URL'),
+ prop: 'generatorURL',
+ sortable: false,
+ cellTemplate: this.externalLinkTpl
+ }
+ ];
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html
new file mode 100644
index 00000000..3b9aef25
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.html
@@ -0,0 +1,35 @@
+<tabset #tabs>
+ <tab id="active-alerts"
+ heading="Active Alerts"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-active-alert-list *ngIf="isAlertmanagerConfigured"></cd-active-alert-list>
+ <cd-info-panel i18n
+ *ngIf="!isAlertmanagerConfigured">To see all active Prometheus alerts, please
+ provide the URL to the API of Prometheus' Alertmanager as described in the
+ <a href="{{docsUrl}}"
+ target="_blank">documentation</a>.</cd-info-panel>
+ </tab>
+ <tab id="all-alerts"
+ heading="All Alerts"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-rules-list *ngIf="isPrometheusConfigured"
+ [data]="prometheusAlertService.rules"></cd-rules-list>
+ <cd-info-panel *ngIf="!isPrometheusConfigured">To see all configured Prometheus alerts, please provide the URL to
+ the API of Prometheus as described in the
+ <a href="{{docsUrl}}"
+ target="_blank">documentation</a>.</cd-info-panel>
+ </tab>
+ <tab id="silences"
+ heading="Silences"
+ (selectTab)="setFragment($event)"
+ i18n-heading>
+ <cd-silences-list *ngIf="isAlertmanagerConfigured"></cd-silences-list>
+ <cd-info-panel *ngIf="!isAlertmanagerConfigured"
+ i18n>To enable Silences, please provide the URL to the API of the Prometheus' Alertmanager as
+ described in the
+ <a href="{{docsUrl}}"
+ target="_blank">documentation</a>.</cd-info-panel>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts
new file mode 100644
index 00000000..bf0bf6c0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.spec.ts
@@ -0,0 +1,46 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import { i18nProviders } from '../../../../../testing/unit-test-helper';
+import { AuthModule } from '../../../../core/auth/auth.module';
+import { CoreModule } from '../../../../core/core.module';
+import { CephfsModule } from '../../../cephfs/cephfs.module';
+import { DashboardModule } from '../../../dashboard/dashboard.module';
+import { NfsModule } from '../../../nfs/nfs.module';
+import { ClusterModule } from '../../cluster.module';
+import { MonitoringListComponent } from './monitoring-list.component';
+
+describe('MonitoringListComponent', () => {
+ let component: MonitoringListComponent;
+ let fixture: ComponentFixture<MonitoringListComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ ClusterModule,
+ DashboardModule,
+ CephfsModule,
+ AuthModule,
+ NfsModule,
+ CoreModule,
+ ToastrModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ declarations: [],
+ providers: [i18nProviders]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MonitoringListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts
new file mode 100644
index 00000000..2b85d386
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/monitoring-list/monitoring-list.component.ts
@@ -0,0 +1,70 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { TabDirective, TabsetComponent } from 'ngx-bootstrap/tabs';
+
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import { CephReleaseNamePipe } from '../../../../shared/pipes/ceph-release-name.pipe';
+import { PrometheusAlertService } from '../../../../shared/services/prometheus-alert.service';
+import { SummaryService } from '../../../../shared/services/summary.service';
+
+@Component({
+ selector: 'cd-monitoring-list',
+ templateUrl: './monitoring-list.component.html',
+ styleUrls: ['./monitoring-list.component.scss']
+})
+export class MonitoringListComponent implements OnInit {
+ constructor(
+ public prometheusAlertService: PrometheusAlertService,
+ private prometheusService: PrometheusService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private summaryService: SummaryService,
+ private cephReleaseNamePipe: CephReleaseNamePipe
+ ) {}
+ @ViewChild('tabs')
+ tabs: TabsetComponent;
+
+ isPrometheusConfigured = false;
+ isAlertmanagerConfigured = false;
+
+ docsUrl = '';
+
+ ngOnInit() {
+ this.prometheusService.ifAlertmanagerConfigured(() => {
+ this.isAlertmanagerConfigured = true;
+ });
+ this.prometheusService.ifPrometheusConfigured(() => {
+ this.isPrometheusConfigured = true;
+ });
+
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl = `https://docs.ceph.com/docs/${releaseName}/mgr/dashboard/#enabling-prometheus-alerting`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+
+ // Activate tab according to given fragment
+ if (this.route.snapshot.fragment) {
+ const tab = this.tabs.tabs.find(
+ (t) => t.elementRef.nativeElement.id === this.route.snapshot.fragment
+ );
+ if (tab) {
+ tab.active = true;
+ }
+ // Ensure fragment is not removed, so page can always be reloaded with the same tab open.
+ this.router.navigate([], { fragment: this.route.snapshot.fragment });
+ }
+ }
+
+ setFragment(element: TabDirective) {
+ this.router.navigate([], { fragment: element.id });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.html
new file mode 100644
index 00000000..e5d311f5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.html
@@ -0,0 +1,9 @@
+<cd-table [data]="data"
+ [columns]="columns"
+ (updateSelection)="selectionUpdated($event)"
+ [selectionType]="'single'"></cd-table>
+
+<cd-table-key-value *ngIf="selectedRule"
+ [data]="selectedRule"
+ [renderObjects]="true"
+ [hideKeys]="hideKeys"></cd-table-key-value>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.spec.ts
new file mode 100644
index 00000000..f09bd49d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.spec.ts
@@ -0,0 +1,29 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import { SettingsService } from '../../../../shared/api/settings.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { RulesListComponent } from './rules-list.component';
+
+describe('RulesListComponent', () => {
+ let component: RulesListComponent;
+ let fixture: ComponentFixture<RulesListComponent>;
+
+ configureTestBed({
+ declarations: [RulesListComponent],
+ imports: [HttpClientTestingModule, SharedModule],
+ providers: [PrometheusService, SettingsService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RulesListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts
new file mode 100644
index 00000000..41577da9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts
@@ -0,0 +1,44 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { PrometheusRule } from '../../../../shared/models/prometheus-alerts';
+import { DurationPipe } from '../../../../shared/pipes/duration.pipe';
+
+@Component({
+ selector: 'cd-rules-list',
+ templateUrl: './rules-list.component.html',
+ styleUrls: ['./rules-list.component.scss']
+})
+export class RulesListComponent implements OnInit {
+ @Input()
+ data: any;
+ columns: CdTableColumn[];
+ selectedRule: PrometheusRule;
+
+ /**
+ * Hide active alerts in details of alerting rules as they are already shown
+ * in the 'active alerts' table. Also hide the 'type' column as the type is
+ * always supposed to be 'alerting'.
+ */
+ hideKeys = ['alerts', 'type'];
+
+ constructor(private i18n: I18n) {}
+
+ ngOnInit() {
+ this.columns = [
+ { prop: 'name', name: this.i18n('Name') },
+ { prop: 'labels.severity', name: this.i18n('Severity') },
+ { prop: 'group', name: this.i18n('Group') },
+ { prop: 'duration', name: this.i18n('Duration'), pipe: new DurationPipe() },
+ { prop: 'query', name: this.i18n('Query'), isHidden: true },
+ { prop: 'annotations.description', name: this.i18n('Description') }
+ ];
+ }
+
+ selectionUpdated(selection: CdTableSelection) {
+ this.selectedRule = selection.first();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.html
new file mode 100644
index 00000000..0050c87e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.html
@@ -0,0 +1,219 @@
+<ng-template #matcherTpl let-matcher="matcher" let-index="index">
+ <div class="input-group">
+ <ng-container *ngFor="let config of matcherConfig">
+ <span class="input-group-addon"
+ [tooltip]=config.tooltip>
+ <i class="icon-prepend" [ngClass]="[config.icon]"></i>
+ </span>
+ <ng-container *ngIf="config.attribute !== 'isRegex'">
+ <input type="text"
+ id="matcher-{{config.attribute}}-{{index}}"
+ class="form-control"
+ [value]="matcher[config.attribute]"
+ disabled
+ readonly>
+ </ng-container>
+ <ng-container *ngIf="config.attribute === 'isRegex'">
+ <span class="input-group-addon">
+ <input type="checkbox"
+ id="matcher-{{config.attribute}}-{{index}}"
+ [checked]="matcher[config.attribute]"
+ disabled
+ readonly>
+ </span>
+ </ng-container>
+ </ng-container>
+ <!-- Matcher actions -->
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ id="matcher-edit-{{index}}"
+ i18n-tooltip
+ tooltip="Edit"
+ (click)="showMatcherModal(index)">
+ <i [ngClass]="[icons.edit]"></i>
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ id="matcher-delete-{{index}}"
+ i18n-tooltip
+ tooltip="Delete"
+ (click)="deleteMatcher(index)">
+ <i [ngClass]="[icons.trash]"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"></span>
+</ng-template>
+
+<div class="col-sm-12 col-lg-6">
+ <form #formDir="ngForm"
+ [formGroup]="form"
+ class="form-horizontal"
+ name="form"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">
+ <span i18n="@@formTitle">
+ {{ action | titlecase }} {{ resource | upperFirst }}
+ </span>
+ <cd-helper *ngIf="edit"
+ i18n>Editing a silence will expire the old silence and recreate it as a new silence</cd-helper>
+ </h3>
+ </div>
+
+ <!-- Creator -->
+ <div class="panel-body">
+ <div [ngClass]="{'has-error': form.showError('createdBy', formDir)}"
+ class="form-group">
+ <label class="control-label col-sm-3"
+ for="created-by">
+ <ng-container i18n>Creator</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ formControlName="createdBy"
+ id="created-by"
+ name="created-by"
+ type="text">
+ <span *ngIf="form.showError('createdBy', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- Comment -->
+ <div [ngClass]="{'has-error': form.showError('comment', formDir)}"
+ class="form-group">
+ <label class="control-label col-sm-3"
+ for="comment">
+ <ng-container i18n>Comment</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <textarea class="form-control"
+ formControlName="comment"
+ id="comment"
+ name="comment"
+ type="text">
+ </textarea>
+ <span *ngIf="form.showError('comment', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- Start time -->
+ <div [ngClass]="{'has-error': form.showError('startsAt', formDir)}"
+ class="form-group">
+ <label class="control-label col-sm-3"
+ for="starts-at">
+ <ng-container i18n>Start time</ng-container>
+ <cd-helper i18n>If the start time lies in the past the creation time will be used</cd-helper>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input [bsConfig]="bsConfig"
+ bsDatepicker
+ class="form-control"
+ formControlName="startsAt"
+ id="starts-at"
+ name="starts-at">
+ <span *ngIf="form.showError('startsAt', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- Duration -->
+ <div [ngClass]="{'has-error': form.showError('duration', formDir)}"
+ class="form-group">
+ <label class="control-label col-sm-3"
+ for="duration">
+ <ng-container i18n>Duration</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ formControlName="duration"
+ id="duration"
+ name="duration"
+ type="text">
+ <span *ngIf="form.showError('duration', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- End time -->
+ <div [ngClass]="{'has-error': form.showError('endsAt', formDir)}"
+ class="form-group">
+ <label class="control-label col-sm-3"
+ for="ends-at">
+ <ng-container i18n>End time</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input [bsConfig]="bsConfig"
+ bsDatepicker
+ class="form-control"
+ formControlName="endsAt"
+ id="ends-at"
+ name="ends-at">
+ <span *ngIf="form.showError('endsAt', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- Matchers -->
+ <fieldset>
+ <legend i18n>Matchers<span class="required">*</span></legend>
+ <div class="col-sm-offset-3 col-sm-9">
+ <h5 *ngIf="matchers.length === 0"
+ [ngClass]="{'text-warning': !formDir.submitted, 'text-danger': formDir.submitted}">
+ <strong i18n>A silence requires at least one matcher</strong>
+ </h5>
+
+ <span *ngFor="let matcher of matchers; let i=index;">
+ <ng-container *ngTemplateOutlet="matcherTpl; context:{index: i, matcher: matcher}"></ng-container>
+ </span>
+
+ <span class="form-control no-border">
+ <button type="button"
+ id="add-matcher"
+ class="btn btn-sm btn-default btn-label pull-right"
+ [ngClass]="{'btn-warning': formDir.submitted && matchers.length === 0 }"
+ (click)="showMatcherModal()">
+ <i [ngClass]="[icons.width, icons.add]"></i>
+ <ng-container i18n>Add matcher</ng-container>
+ </button>
+ </span>
+ </div>
+ <div *ngIf="matchers.length && matcherMatch"
+ class="col-sm-offset-3 col-sm-9 {{matcherMatch.cssClass}}"
+ id="match-state">
+ <span class="help-block {{matcherMatch.cssClass}}">
+ {{ matcherMatch.status }}
+ </span>
+ </div>
+ </fieldset>
+ </div>
+
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button (submitAction)="submit()"
+ [form]="formDir"
+ id="submit"
+ i18n="@@formTitle"
+ type="button">
+ {{ action | titlecase }} {{ resource | upperFirst }}
+ </cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.scss
new file mode 100644
index 00000000..fb52450d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.scss
@@ -0,0 +1,3 @@
+textarea {
+ resize: vertical;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts
new file mode 100644
index 00000000..73d5fd8a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts
@@ -0,0 +1,606 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { ActivatedRoute, Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as _ from 'lodash';
+import { BsDatepickerDirective, BsDatepickerModule } from 'ngx-bootstrap/datepicker';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+import { ToastrModule } from 'ngx-toastr';
+import { of, throwError } from 'rxjs';
+
+import {
+ configureTestBed,
+ FixtureHelper,
+ FormHelper,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../../../testing/unit-test-helper';
+import { NotFoundComponent } from '../../../../core/not-found/not-found.component';
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { AlertmanagerSilence } from '../../../../shared/models/alertmanager-silence';
+import { Permission } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { SilenceFormComponent } from './silence-form.component';
+
+describe('SilenceFormComponent', () => {
+ // SilenceFormComponent specific
+ let component: SilenceFormComponent;
+ let fixture: ComponentFixture<SilenceFormComponent>;
+ let form: CdFormGroup;
+ // Spied on
+ let prometheusService: PrometheusService;
+ let authStorageService: AuthStorageService;
+ let notificationService: NotificationService;
+ let router: Router;
+ // Spies
+ let rulesSpy;
+ let ifPrometheusSpy;
+ // Helper
+ let prometheus: PrometheusHelper;
+ let formHelper: FormHelper;
+ let fixtureH: FixtureHelper;
+ let params;
+ // Date mocking related
+ let originalDate;
+ const baseTime = new Date('2022-02-22T00:00:00');
+ const beginningDate = new Date('2022-02-22T00:00:12.35');
+
+ const routes: Routes = [{ path: '404', component: NotFoundComponent }];
+ configureTestBed({
+ declarations: [NotFoundComponent, SilenceFormComponent],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule.withRoutes(routes),
+ BsDatepickerModule.forRoot(),
+ SharedModule,
+ ToastrModule.forRoot(),
+ TooltipModule.forRoot(),
+ ReactiveFormsModule
+ ],
+ providers: [
+ i18nProviders,
+ {
+ provide: ActivatedRoute,
+ useValue: { params: { subscribe: (fn) => fn(params) } }
+ }
+ ]
+ });
+
+ const createMatcher = (name, value, isRegex) => ({ name, value, isRegex });
+
+ const addMatcher = (name, value, isRegex) =>
+ component['setMatcher'](createMatcher(name, value, isRegex));
+
+ const callInit = () =>
+ fixture.ngZone.run(() => {
+ component['init']();
+ });
+
+ const changeAction = (action: string) => {
+ const modes = {
+ add: '/monitoring/silence/add',
+ alertAdd: '/monitoring/silence/add/someAlert',
+ recreate: '/monitoring/silence/recreate/someExpiredId',
+ edit: '/monitoring/silence/edit/someNotExpiredId'
+ };
+ Object.defineProperty(router, 'url', { value: modes[action] });
+ callInit();
+ };
+
+ beforeEach(() => {
+ params = {};
+
+ originalDate = Date;
+ spyOn(global, 'Date').and.callFake((arg) => (arg ? new originalDate(arg) : beginningDate));
+
+ prometheus = new PrometheusHelper();
+ prometheusService = TestBed.get(PrometheusService);
+ spyOn(prometheusService, 'getAlerts').and.callFake(() =>
+ of([prometheus.createAlert('alert0')])
+ );
+ ifPrometheusSpy = spyOn(prometheusService, 'ifPrometheusConfigured').and.callFake((fn) => fn());
+ rulesSpy = spyOn(prometheusService, 'getRules').and.callFake(() =>
+ of({
+ groups: [
+ {
+ file: '',
+ interval: 0,
+ name: '',
+ rules: [
+ prometheus.createRule('alert0', 'someSeverity', [prometheus.createAlert('alert0')]),
+ prometheus.createRule('alert1', 'someSeverity', []),
+ prometheus.createRule('alert2', 'someOtherSeverity', [
+ prometheus.createAlert('alert2')
+ ])
+ ]
+ }
+ ]
+ })
+ );
+
+ router = TestBed.get(Router);
+
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+
+ authStorageService = TestBed.get(AuthStorageService);
+ spyOn(authStorageService, 'getUsername').and.returnValue('someUser');
+
+ fixture = TestBed.createComponent(SilenceFormComponent);
+ fixtureH = new FixtureHelper(fixture);
+ component = fixture.componentInstance;
+ form = component.form;
+ formHelper = new FormHelper(form);
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(_.isArray(component.rules)).toBeTruthy();
+ });
+
+ it('should have set the logged in user name as creator', () => {
+ expect(component.form.getValue('createdBy')).toBe('someUser');
+ });
+
+ it('should call disablePrometheusConfig on error calling getRules', () => {
+ spyOn(prometheusService, 'disablePrometheusConfig');
+ rulesSpy.and.callFake(() => throwError({}));
+ callInit();
+ expect(component.rules).toEqual([]);
+ expect(prometheusService.disablePrometheusConfig).toHaveBeenCalled();
+ });
+
+ it('should remind user if prometheus is not set when it is not configured', () => {
+ ifPrometheusSpy.and.callFake((_x, fn) => fn());
+ callInit();
+ expect(component.rules).toEqual([]);
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.info,
+ 'Please add your Prometheus host to the dashboard configuration and refresh the page',
+ undefined,
+ undefined,
+ 'Prometheus'
+ );
+ });
+
+ describe('redirect not allowed users', () => {
+ let prometheusPermissions: Permission;
+ let navigateSpy;
+
+ const expectRedirect = (action: string, redirected: boolean) => {
+ changeAction(action);
+ expect(router.navigate).toHaveBeenCalledTimes(redirected ? 1 : 0);
+ if (redirected) {
+ expect(router.navigate).toHaveBeenCalledWith(['/404']);
+ }
+ navigateSpy.calls.reset();
+ };
+
+ beforeEach(() => {
+ navigateSpy = spyOn(router, 'navigate').and.stub();
+ spyOn(authStorageService, 'getPermissions').and.callFake(() => ({
+ prometheus: prometheusPermissions
+ }));
+ });
+
+ it('redirects to 404 if not allowed', () => {
+ prometheusPermissions = new Permission(['delete', 'read']);
+ expectRedirect('add', true);
+ expectRedirect('alertAdd', true);
+ });
+
+ it('redirects if user does not have minimum permissions to create silences', () => {
+ prometheusPermissions = new Permission(['update', 'delete', 'read']);
+ expectRedirect('add', true);
+ prometheusPermissions = new Permission(['update', 'delete', 'create']);
+ expectRedirect('recreate', true);
+ });
+
+ it('redirects if user does not have minimum permissions to update silences', () => {
+ prometheusPermissions = new Permission(['create', 'delete', 'read']);
+ expectRedirect('edit', true);
+ prometheusPermissions = new Permission(['create', 'delete', 'update']);
+ expectRedirect('edit', true);
+ });
+
+ it('does not redirect if user has minimum permissions to create silences', () => {
+ prometheusPermissions = new Permission(['create', 'read']);
+ expectRedirect('add', false);
+ expectRedirect('alertAdd', false);
+ expectRedirect('recreate', false);
+ });
+
+ it('does not redirect if user has minimum permissions to update silences', () => {
+ prometheusPermissions = new Permission(['update', 'read']);
+ expectRedirect('edit', false);
+ });
+ });
+
+ describe('choose the right action', () => {
+ const expectMode = (routerMode: string, edit: boolean, recreate: boolean, action: string) => {
+ changeAction(routerMode);
+ expect(component.recreate).toBe(recreate);
+ expect(component.edit).toBe(edit);
+ expect(component.action).toBe(action);
+ };
+
+ beforeEach(() => {
+ spyOn(prometheusService, 'getSilences').and.callFake((p) =>
+ of([prometheus.createSilence(p.id)])
+ );
+ });
+
+ it('should have no special action activate by default', () => {
+ expectMode('add', false, false, 'Create');
+ expect(prometheusService.getSilences).not.toHaveBeenCalled();
+ expect(component.form.value).toEqual({
+ comment: null,
+ createdBy: 'someUser',
+ duration: '2h',
+ startsAt: baseTime,
+ endsAt: new Date('2022-02-22T02:00:00')
+ });
+ });
+
+ it('should be in edit action if route includes edit', () => {
+ params = { id: 'someNotExpiredId' };
+ expectMode('edit', true, false, 'Edit');
+ expect(prometheusService.getSilences).toHaveBeenCalledWith(params);
+ expect(component.form.value).toEqual({
+ comment: `A comment for ${params.id}`,
+ createdBy: `Creator of ${params.id}`,
+ duration: '1d',
+ startsAt: new Date('2022-02-22T22:22:00'),
+ endsAt: new Date('2022-02-23T22:22:00')
+ });
+ expect(component.matchers).toEqual([createMatcher('job', 'someJob', true)]);
+ });
+
+ it('should be in recreation action if route includes recreate', () => {
+ params = { id: 'someExpiredId' };
+ expectMode('recreate', false, true, 'Recreate');
+ expect(prometheusService.getSilences).toHaveBeenCalledWith(params);
+ expect(component.form.value).toEqual({
+ comment: `A comment for ${params.id}`,
+ createdBy: `Creator of ${params.id}`,
+ duration: '2h',
+ startsAt: baseTime,
+ endsAt: new Date('2022-02-22T02:00:00')
+ });
+ expect(component.matchers).toEqual([createMatcher('job', 'someJob', true)]);
+ });
+
+ it('adds matchers based on the label object of the alert with the given id', () => {
+ params = { id: 'someAlert' };
+ expectMode('alertAdd', false, false, 'Create');
+ expect(prometheusService.getSilences).not.toHaveBeenCalled();
+ expect(prometheusService.getAlerts).toHaveBeenCalled();
+ expect(component.matchers).toEqual([
+ createMatcher('alertname', 'alert0', false),
+ createMatcher('instance', 'someInstance', false),
+ createMatcher('job', 'someJob', false),
+ createMatcher('severity', 'someSeverity', false)
+ ]);
+ expect(component.matcherMatch).toEqual({
+ cssClass: 'has-success',
+ status: 'Matches 1 rule with 1 active alert.'
+ });
+ });
+ });
+
+ describe('time', () => {
+ // Can't be used to set accurate UTC dates in unit tests as Date uses timezones,
+ // this means the UTC time changes depending on the timezone you are in.
+ const changeDatePicker = (el, text) => {
+ el.triggerEventHandler('change', { target: { value: text } });
+ };
+ const getDatePicker = (i) =>
+ fixture.debugElement.queryAll(By.directive(BsDatepickerDirective))[i];
+ const changeEndDate = (text) => changeDatePicker(getDatePicker(1), text);
+ const changeStartDate = (text) => changeDatePicker(getDatePicker(0), text);
+
+ it('have all dates set at beginning', () => {
+ expect(form.getValue('startsAt')).toEqual(baseTime);
+ expect(form.getValue('duration')).toBe('2h');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T02:00:00'));
+ });
+
+ describe('on start date change', () => {
+ it('changes end date on start date change if it exceeds it', fakeAsync(() => {
+ changeStartDate('2022-02-28T 04:05');
+ expect(form.getValue('duration')).toEqual('2h');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-28T06:05:00'));
+
+ changeStartDate('2022-12-31T 22:00');
+ expect(form.getValue('duration')).toEqual('2h');
+ expect(form.getValue('endsAt')).toEqual(new Date('2023-01-01T00:00:00'));
+ }));
+
+ it('changes duration if start date does not exceed end date ', fakeAsync(() => {
+ changeStartDate('2022-02-22T 00:45');
+ expect(form.getValue('duration')).toEqual('1h 15m');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T02:00:00'));
+ }));
+
+ it('should raise invalid start date error', fakeAsync(() => {
+ changeStartDate('No valid date');
+ formHelper.expectError('startsAt', 'bsDate');
+ expect(form.getValue('startsAt').toString()).toBe('Invalid Date');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T02:00:00'));
+ }));
+ });
+
+ describe('on duration change', () => {
+ it('changes end date if duration is changed', () => {
+ formHelper.setValue('duration', '15m');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-22T00:15'));
+ formHelper.setValue('duration', '5d 23h');
+ expect(form.getValue('endsAt')).toEqual(new Date('2022-02-27T23:00'));
+ });
+ });
+
+ describe('on end date change', () => {
+ it('changes duration on end date change if it exceeds start date', fakeAsync(() => {
+ changeEndDate('2022-02-28T 04:05');
+ expect(form.getValue('duration')).toEqual('6d 4h 5m');
+ expect(form.getValue('startsAt')).toEqual(baseTime);
+ }));
+
+ it('changes start date if end date happens before it', fakeAsync(() => {
+ changeEndDate('2022-02-21T 02:00');
+ expect(form.getValue('duration')).toEqual('2h');
+ expect(form.getValue('startsAt')).toEqual(new Date('2022-02-21T00:00:00'));
+ }));
+
+ it('should raise invalid end date error', fakeAsync(() => {
+ changeEndDate('No valid date');
+ formHelper.expectError('endsAt', 'bsDate');
+ expect(form.getValue('endsAt').toString()).toBe('Invalid Date');
+ expect(form.getValue('startsAt')).toEqual(baseTime);
+ }));
+ });
+ });
+
+ it('should have a creator field', () => {
+ formHelper.expectValid('createdBy');
+ formHelper.expectErrorChange('createdBy', '', 'required');
+ formHelper.expectValidChange('createdBy', 'Mighty FSM');
+ });
+
+ it('should have a comment field', () => {
+ formHelper.expectError('comment', 'required');
+ formHelper.expectValidChange('comment', 'A pretty long comment');
+ });
+
+ it('should be a valid form if all inputs are filled and at least one matcher was added', () => {
+ expect(form.valid).toBeFalsy();
+ formHelper.expectValidChange('createdBy', 'Mighty FSM');
+ formHelper.expectValidChange('comment', 'A pretty long comment');
+ addMatcher('job', 'someJob', false);
+ expect(form.valid).toBeTruthy();
+ });
+
+ describe('matchers', () => {
+ const expectMatch = (helpText) => {
+ expect(fixtureH.getText('#match-state')).toBe(helpText);
+ };
+
+ it('should show the add matcher button', () => {
+ fixtureH.expectElementVisible('#add-matcher', true);
+ fixtureH.expectIdElementsVisible(
+ [
+ 'matcher-name-0',
+ 'matcher-value-0',
+ 'matcher-isRegex-0',
+ 'matcher-edit-0',
+ 'matcher-delete-0'
+ ],
+ false
+ );
+ expectMatch(null);
+ });
+
+ it('should show added matcher', () => {
+ addMatcher('job', 'someJob', true);
+ fixtureH.expectIdElementsVisible(
+ [
+ 'matcher-name-0',
+ 'matcher-value-0',
+ 'matcher-isRegex-0',
+ 'matcher-edit-0',
+ 'matcher-delete-0'
+ ],
+ true
+ );
+ expectMatch(null);
+ });
+
+ it('should show multiple matchers', () => {
+ addMatcher('severity', 'someSeverity', false);
+ addMatcher('alertname', 'alert0', false);
+ fixtureH.expectIdElementsVisible(
+ [
+ 'matcher-name-0',
+ 'matcher-value-0',
+ 'matcher-isRegex-0',
+ 'matcher-edit-0',
+ 'matcher-delete-0',
+ 'matcher-name-1',
+ 'matcher-value-1',
+ 'matcher-isRegex-1',
+ 'matcher-edit-1',
+ 'matcher-delete-1'
+ ],
+ true
+ );
+ expectMatch('Matches 1 rule with 1 active alert.');
+ });
+
+ it('should show the right matcher values', () => {
+ addMatcher('alertname', 'alert.*', true);
+ addMatcher('job', 'someJob', false);
+ fixture.detectChanges();
+ fixtureH.expectFormFieldToBe('#matcher-name-0', 'alertname');
+ fixtureH.expectFormFieldToBe('#matcher-value-0', 'alert.*');
+ fixtureH.expectFormFieldToBe('#matcher-isRegex-0', 'true');
+ fixtureH.expectFormFieldToBe('#matcher-isRegex-1', 'false');
+ expectMatch(null);
+ });
+
+ it('should be able to edit a matcher', () => {
+ addMatcher('alertname', 'alert.*', true);
+ expectMatch(null);
+
+ const modalService = TestBed.get(BsModalService);
+ spyOn(modalService, 'show').and.callFake(() => {
+ return {
+ content: {
+ preFillControls: (matcher) => {
+ expect(matcher).toBe(component.matchers[0]);
+ },
+ submitAction: of({ name: 'alertname', value: 'alert0', isRegex: false })
+ }
+ };
+ });
+ fixtureH.clickElement('#matcher-edit-0');
+
+ fixtureH.expectFormFieldToBe('#matcher-name-0', 'alertname');
+ fixtureH.expectFormFieldToBe('#matcher-value-0', 'alert0');
+ fixtureH.expectFormFieldToBe('#matcher-isRegex-0', 'false');
+ expectMatch('Matches 1 rule with 1 active alert.');
+ });
+
+ it('should be able to remove a matcher', () => {
+ addMatcher('alertname', 'alert0', false);
+ expectMatch('Matches 1 rule with 1 active alert.');
+ fixtureH.clickElement('#matcher-delete-0');
+ expect(component.matchers).toEqual([]);
+ fixtureH.expectIdElementsVisible(
+ ['matcher-name-0', 'matcher-value-0', 'matcher-isRegex-0'],
+ false
+ );
+ expectMatch(null);
+ });
+
+ it('should be able to remove a matcher and update the matcher text', () => {
+ addMatcher('alertname', 'alert0', false);
+ addMatcher('alertname', 'alert1', false);
+ expectMatch('Your matcher seems to match no currently defined rule or active alert.');
+ fixtureH.clickElement('#matcher-delete-1');
+ expectMatch('Matches 1 rule with 1 active alert.');
+ });
+
+ it('should show form as invalid if no matcher is set', () => {
+ expect(form.errors).toEqual({ matcherRequired: true });
+ });
+
+ it('should show form as valid if matcher was added', () => {
+ addMatcher('some name', 'some value', true);
+ expect(form.errors).toEqual(null);
+ });
+ });
+
+ describe('submit tests', () => {
+ const endsAt = new Date('2022-02-22T02:00:00');
+ let silence: AlertmanagerSilence;
+ const silenceId = '50M3-10N6-1D';
+
+ const expectSuccessNotification = (titleStartsWith) =>
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ `${titleStartsWith} silence ${silenceId}`,
+ undefined,
+ undefined,
+ 'Prometheus'
+ );
+
+ const fillAndSubmit = () => {
+ ['createdBy', 'comment'].forEach((attr) => {
+ formHelper.setValue(attr, silence[attr]);
+ });
+ silence.matchers.forEach((matcher) =>
+ addMatcher(matcher.name, matcher.value, matcher.isRegex)
+ );
+ component.submit();
+ };
+
+ beforeEach(() => {
+ spyOn(prometheusService, 'setSilence').and.callFake(() => of({ body: { silenceId } }));
+ spyOn(router, 'navigate').and.stub();
+ silence = {
+ createdBy: 'some creator',
+ comment: 'some comment',
+ startsAt: baseTime.toISOString(),
+ endsAt: endsAt.toISOString(),
+ matchers: [
+ {
+ name: 'some attribute name',
+ value: 'some value',
+ isRegex: false
+ },
+ {
+ name: 'job',
+ value: 'node-exporter',
+ isRegex: false
+ },
+ {
+ name: 'instance',
+ value: 'localhost:9100',
+ isRegex: false
+ },
+ {
+ name: 'alertname',
+ value: 'load_0',
+ isRegex: false
+ }
+ ]
+ };
+ });
+
+ it('should not create a silence if the form is invalid', () => {
+ component.submit();
+ expect(notificationService.show).not.toHaveBeenCalled();
+ expect(form.valid).toBeFalsy();
+ expect(prometheusService.setSilence).not.toHaveBeenCalledWith(silence);
+ expect(router.navigate).not.toHaveBeenCalled();
+ });
+
+ it('should route back to previous tab on success', () => {
+ fillAndSubmit();
+ expect(form.valid).toBeTruthy();
+ expect(router.navigate).toHaveBeenCalledWith(['/monitoring'], { fragment: 'silences' });
+ });
+
+ it('should create a silence', () => {
+ fillAndSubmit();
+ expect(prometheusService.setSilence).toHaveBeenCalledWith(silence);
+ expectSuccessNotification('Created');
+ });
+
+ it('should recreate a silence', () => {
+ component.recreate = true;
+ component.id = 'recreateId';
+ fillAndSubmit();
+ expect(prometheusService.setSilence).toHaveBeenCalledWith(silence);
+ expectSuccessNotification('Recreated');
+ });
+
+ it('should edit a silence', () => {
+ component.edit = true;
+ component.id = 'editId';
+ silence.id = component.id;
+ fillAndSubmit();
+ expect(prometheusService.setSilence).toHaveBeenCalledWith(silence);
+ expectSuccessNotification('Edited');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts
new file mode 100644
index 00000000..d5ef6b35
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts
@@ -0,0 +1,333 @@
+import { Component } from '@angular/core';
+import { Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import {
+ ActionLabelsI18n,
+ SucceededActionLabelsI18n
+} from '../../../../shared/constants/app.constants';
+import { Icons } from '../../../../shared/enum/icons.enum';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../../shared/forms/cd-validators';
+import {
+ AlertmanagerSilence,
+ AlertmanagerSilenceMatcher,
+ AlertmanagerSilenceMatcherMatch
+} from '../../../../shared/models/alertmanager-silence';
+import { Permission } from '../../../../shared/models/permissions';
+import { AlertmanagerAlert, PrometheusRule } from '../../../../shared/models/prometheus-alerts';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { PrometheusSilenceMatcherService } from '../../../../shared/services/prometheus-silence-matcher.service';
+import { TimeDiffService } from '../../../../shared/services/time-diff.service';
+import { SilenceMatcherModalComponent } from '../silence-matcher-modal/silence-matcher-modal.component';
+
+@Component({
+ selector: 'cd-prometheus-form',
+ templateUrl: './silence-form.component.html',
+ styleUrls: ['./silence-form.component.scss']
+})
+export class SilenceFormComponent {
+ icons = Icons;
+ permission: Permission;
+ form: CdFormGroup;
+ rules: PrometheusRule[];
+
+ // Date formatting rules can be found here: https://momentjs.com/docs/#/displaying/format/
+ bsConfig = { dateInputFormat: 'YYYY-MM-DDT HH:mm' };
+
+ recreate = false;
+ edit = false;
+ id: string;
+
+ action: string;
+ resource = this.i18n('silence');
+
+ matchers: AlertmanagerSilenceMatcher[] = [];
+ matcherMatch: AlertmanagerSilenceMatcherMatch = undefined;
+ matcherConfig = [
+ {
+ tooltip: this.i18n('Attribute name'),
+ icon: this.icons.paragraph,
+ attribute: 'name'
+ },
+ {
+ tooltip: this.i18n('Value'),
+ icon: this.icons.terminal,
+ attribute: 'value'
+ },
+ {
+ tooltip: this.i18n('Regular expression'),
+ icon: this.icons.magic,
+ attribute: 'isRegex'
+ }
+ ];
+
+ constructor(
+ private i18n: I18n,
+ private router: Router,
+ private authStorageService: AuthStorageService,
+ private formBuilder: CdFormBuilder,
+ private prometheusService: PrometheusService,
+ private notificationService: NotificationService,
+ private route: ActivatedRoute,
+ private timeDiff: TimeDiffService,
+ private bsModalService: BsModalService,
+ private silenceMatcher: PrometheusSilenceMatcherService,
+ private actionLabels: ActionLabelsI18n,
+ private succeededLabels: SucceededActionLabelsI18n
+ ) {
+ this.init();
+ }
+
+ private init() {
+ this.chooseMode();
+ this.authenticate();
+ this.createForm();
+ this.setupDates();
+ this.getData();
+ }
+
+ private chooseMode() {
+ this.edit = this.router.url.startsWith('/monitoring/silence/edit');
+ this.recreate = this.router.url.startsWith('/monitoring/silence/recreate');
+ if (this.edit) {
+ this.action = this.actionLabels.EDIT;
+ } else if (this.recreate) {
+ this.action = this.actionLabels.RECREATE;
+ } else {
+ this.action = this.actionLabels.CREATE;
+ }
+ }
+
+ private authenticate() {
+ this.permission = this.authStorageService.getPermissions().prometheus;
+ const allowed =
+ this.permission.read && (this.edit ? this.permission.update : this.permission.create);
+ if (!allowed) {
+ this.router.navigate(['/404']);
+ }
+ }
+
+ private createForm() {
+ this.form = this.formBuilder.group(
+ {
+ startsAt: [null, [Validators.required]],
+ duration: ['2h', [Validators.min(1)]],
+ endsAt: [null, [Validators.required]],
+ createdBy: [this.authStorageService.getUsername(), [Validators.required]],
+ comment: [null, [Validators.required]]
+ },
+ {
+ validators: CdValidators.custom('matcherRequired', () => this.matchers.length === 0)
+ }
+ );
+ }
+
+ private setupDates() {
+ const now = new Date();
+ now.setSeconds(0, 0); // Normalizes start date
+ this.form.silentSet('startsAt', now);
+ this.updateDate();
+ this.subscribeDateChanges();
+ }
+
+ private updateDate(updateStartDate?: boolean) {
+ const next = this.timeDiff.calculateDate(
+ this.form.getValue(updateStartDate ? 'endsAt' : 'startsAt'),
+ this.form.getValue('duration'),
+ updateStartDate
+ );
+ if (next) {
+ this.form.silentSet(updateStartDate ? 'startsAt' : 'endsAt', next);
+ }
+ }
+
+ private subscribeDateChanges() {
+ this.form.get('startsAt').valueChanges.subscribe(() => {
+ this.onDateChange();
+ });
+ this.form.get('duration').valueChanges.subscribe(() => {
+ this.updateDate();
+ });
+ this.form.get('endsAt').valueChanges.subscribe(() => {
+ this.onDateChange(true);
+ });
+ }
+
+ private onDateChange(updateStartDate?: boolean) {
+ if (this.form.getValue('startsAt') < this.form.getValue('endsAt')) {
+ this.updateDuration();
+ } else {
+ this.updateDate(updateStartDate);
+ }
+ }
+
+ private updateDuration() {
+ this.form.silentSet(
+ 'duration',
+ this.timeDiff.calculateDuration(this.form.getValue('startsAt'), this.form.getValue('endsAt'))
+ );
+ }
+
+ private getData() {
+ this.getRules();
+ this.getModeSpecificData();
+ }
+
+ private getRules() {
+ this.prometheusService.ifPrometheusConfigured(
+ () =>
+ this.prometheusService.getRules().subscribe(
+ (groups) => {
+ this.rules = groups['groups'].reduce(
+ (acc, group) => _.concat<PrometheusRule>(acc, group.rules),
+ []
+ );
+ },
+ () => {
+ this.prometheusService.disablePrometheusConfig();
+ this.rules = [];
+ }
+ ),
+ () => {
+ this.rules = [];
+ this.notificationService.show(
+ NotificationType.info,
+ this.i18n(
+ 'Please add your Prometheus host to the dashboard configuration and refresh the page'
+ ),
+ undefined,
+ undefined,
+ 'Prometheus'
+ );
+ }
+ );
+ }
+
+ private getModeSpecificData() {
+ this.route.params.subscribe((params: { id: string }) => {
+ if (!params.id) {
+ return;
+ }
+ if (this.edit || this.recreate) {
+ this.prometheusService.getSilences(params).subscribe((silences) => {
+ this.fillFormWithSilence(silences[0]);
+ });
+ } else {
+ this.prometheusService.getAlerts(params).subscribe((alerts) => {
+ this.fillFormByAlert(alerts[0]);
+ });
+ }
+ });
+ }
+
+ private fillFormWithSilence(silence: AlertmanagerSilence) {
+ this.id = silence.id;
+ if (this.edit) {
+ ['startsAt', 'endsAt'].forEach((attr) => this.form.silentSet(attr, new Date(silence[attr])));
+ this.updateDuration();
+ }
+ ['createdBy', 'comment'].forEach((attr) => this.form.silentSet(attr, silence[attr]));
+ this.matchers = silence.matchers;
+ this.validateMatchers();
+ }
+
+ private validateMatchers() {
+ if (!this.rules) {
+ window.setTimeout(() => this.validateMatchers(), 100);
+ return;
+ }
+ this.matcherMatch = this.silenceMatcher.multiMatch(this.matchers, this.rules);
+ this.form.markAsDirty();
+ this.form.updateValueAndValidity();
+ }
+
+ private fillFormByAlert(alert: AlertmanagerAlert) {
+ const labels = alert.labels;
+ Object.keys(labels).forEach((key) =>
+ this.setMatcher({
+ name: key,
+ value: labels[key],
+ isRegex: false
+ })
+ );
+ }
+
+ private setMatcher(matcher: AlertmanagerSilenceMatcher, index?: number) {
+ if (_.isNumber(index)) {
+ this.matchers[index] = matcher;
+ } else {
+ this.matchers.push(matcher);
+ }
+ this.validateMatchers();
+ }
+
+ showMatcherModal(index?: number) {
+ const modalRef = this.bsModalService.show(SilenceMatcherModalComponent);
+ const modal = modalRef.content as SilenceMatcherModalComponent;
+ modal.rules = this.rules;
+ if (_.isNumber(index)) {
+ modal.editMode = true;
+ modal.preFillControls(this.matchers[index]);
+ }
+ modalRef.content.submitAction.subscribe((matcher: AlertmanagerSilenceMatcher) => {
+ this.setMatcher(matcher, index);
+ });
+ }
+
+ deleteMatcher(index: number) {
+ this.matchers.splice(index, 1);
+ this.validateMatchers();
+ }
+
+ submit() {
+ if (this.form.invalid) {
+ return;
+ }
+ this.prometheusService.setSilence(this.getSubmitData()).subscribe(
+ (resp) => {
+ this.router.navigate(['/monitoring'], { fragment: 'silences' });
+ this.notificationService.show(
+ NotificationType.success,
+ this.getNotificationTile(resp.body['silenceId']),
+ undefined,
+ undefined,
+ 'Prometheus'
+ );
+ },
+ () => this.form.setErrors({ cdSubmitButton: true })
+ );
+ }
+
+ private getSubmitData(): AlertmanagerSilence {
+ const payload = this.form.value;
+ delete payload.duration;
+ payload.startsAt = payload.startsAt.toISOString();
+ payload.endsAt = payload.endsAt.toISOString();
+ payload.matchers = this.matchers;
+ if (this.edit) {
+ payload.id = this.id;
+ }
+ return payload;
+ }
+
+ private getNotificationTile(id: string) {
+ let action;
+ if (this.edit) {
+ action = this.succeededLabels.EDITED;
+ } else if (this.recreate) {
+ action = this.succeededLabels.RECREATED;
+ } else {
+ action = this.succeededLabels.CREATED;
+ }
+ return `${action} ${this.resource} ${id}`;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html
new file mode 100644
index 00000000..fef517d8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.html
@@ -0,0 +1,27 @@
+<cd-table [data]="silences"
+ [columns]="columns"
+ [forceIdentifier]="true"
+ [customCss]="customCss"
+ [sorts]="sorts"
+ selectionType="single"
+ (fetchData)="refresh()"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <tabset cdTableDetail *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <cd-table-key-value [renderObjects]="true"
+ [hideEmpty]="true"
+ [appendParentKey]="false"
+ [data]="selection.first()"
+ [customCss]="customCss"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ </tabset>
+</cd-table>
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.spec.ts
new file mode 100644
index 00000000..9b69f579
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.spec.ts
@@ -0,0 +1,319 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { SilenceListComponent } from './silence-list.component';
+
+describe('SilenceListComponent', () => {
+ let component: SilenceListComponent;
+ let fixture: ComponentFixture<SilenceListComponent>;
+ let prometheusService: PrometheusService;
+
+ configureTestBed({
+ imports: [
+ SharedModule,
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ ModalModule.forRoot(),
+ ToastrModule.forRoot(),
+ RouterTestingModule,
+ HttpClientTestingModule
+ ],
+ declarations: [SilenceListComponent],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SilenceListComponent);
+ component = fixture.componentInstance;
+ prometheusService = TestBed.get(PrometheusService);
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+ let silenceState: string;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ const setSilenceState = (state) => {
+ silenceState = state;
+ };
+
+ const testNonExpiredSilenceScenario = () => {
+ setSilenceState('active');
+ permissionHelper.testScenarios(scenario);
+ setSilenceState('pending');
+ permissionHelper.testScenarios(scenario);
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ permissionHelper.createSelection = () => ({ status: { state: silenceState } });
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Edit',
+ empty: 'Create'
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Edit';
+ testNonExpiredSilenceScenario();
+ });
+
+ it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Recreate';
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('can use all actions', () => {
+ expect(tableActions.tableActions.length).toBe(4);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single non expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Edit';
+ testNonExpiredSilenceScenario();
+ });
+
+ it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Recreate';
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use all actions except for 'Expire'`, () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Expire' for single non expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Expire';
+ testNonExpiredSilenceScenario();
+ });
+
+ it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Recreate';
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use 'Create' and 'Expire' action`, () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[1],
+ component.tableActions[3]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action for any state`, () => {
+ scenario.single = 'Edit';
+ scenario.empty = 'Edit';
+ testNonExpiredSilenceScenario();
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use 'Edit' and 'Expire' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[2],
+ component.tableActions[3]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows always 'Create' as main action for single non expired silences`, () => {
+ scenario.single = 'Create';
+ testNonExpiredSilenceScenario();
+ });
+
+ it(`shows 'Recreate' for single expired silence else 'Create' as main action`, () => {
+ scenario.single = 'Recreate';
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use 'Create' and 'Recreate' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[1]
+ ]);
+ });
+ });
+
+ describe('with read and edit', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action for any state`, () => {
+ scenario.single = 'Edit';
+ scenario.empty = 'Edit';
+ testNonExpiredSilenceScenario();
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Expire' as main action for any state`, () => {
+ scenario.single = 'Expire';
+ scenario.empty = 'Expire';
+ testNonExpiredSilenceScenario();
+ setSilenceState('expired');
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`can use 'Expire' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[3]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('can use no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+
+ describe('expire silence', () => {
+ const setSelectedSilence = (silenceName: string) => {
+ component.selection.selected = [{ id: silenceName }];
+ component.selection.update();
+ };
+
+ const expireSilence = () => {
+ component.expireSilence();
+ const deletion: CriticalConfirmationModalComponent = component.modalRef.content;
+ deletion.modalRef = new BsModalRef();
+ deletion.ngOnInit();
+ deletion.callSubmitAction();
+ };
+
+ const expectSilenceToExpire = (silenceId) => {
+ setSelectedSilence(silenceId);
+ expireSilence();
+ expect(prometheusService.expireSilence).toHaveBeenCalledWith(silenceId);
+ };
+
+ beforeEach(() => {
+ const mockObservable = () => of([]);
+ spyOn(component, 'refresh').and.callFake(mockObservable);
+ spyOn(prometheusService, 'expireSilence').and.callFake(mockObservable);
+ spyOn(TestBed.get(BsModalService), 'show').and.callFake((deletionClass, config) => {
+ return {
+ content: Object.assign(new deletionClass(), config.initialState)
+ };
+ });
+ });
+
+ it('should expire a silence', () => {
+ const notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+ expectSilenceToExpire('someSilenceId');
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Expired Silence someSilenceId',
+ undefined,
+ undefined,
+ 'Prometheus'
+ );
+ });
+
+ it('should refresh after expiring a silence', () => {
+ expectSilenceToExpire('someId');
+ expect(component.refresh).toHaveBeenCalledTimes(1);
+ expectSilenceToExpire('someOtherId');
+ expect(component.refresh).toHaveBeenCalledTimes(2);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts
new file mode 100644
index 00000000..c423b001
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts
@@ -0,0 +1,201 @@
+import { Component, OnInit } from '@angular/core';
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { SortDirection, SortPropDir } from '@swimlane/ngx-datatable';
+
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { Observable, Subscriber } from 'rxjs';
+
+import { PrometheusService } from '../../../../shared/api/prometheus.service';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import {
+ ActionLabelsI18n,
+ SucceededActionLabelsI18n
+} from '../../../../shared/constants/app.constants';
+import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
+import { Icons } from '../../../../shared/enum/icons.enum';
+import { NotificationType } from '../../../../shared/enum/notification-type.enum';
+import { AlertmanagerSilence } from '../../../../shared/models/alertmanager-silence';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permission } from '../../../../shared/models/permissions';
+import { CdDatePipe } from '../../../../shared/pipes/cd-date.pipe';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../../shared/services/notification.service';
+import { URLBuilderService } from '../../../../shared/services/url-builder.service';
+
+const BASE_URL = 'monitoring/silence';
+
+@Component({
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }],
+ selector: 'cd-silences-list',
+ templateUrl: './silence-list.component.html',
+ styleUrls: ['./silence-list.component.scss']
+})
+export class SilenceListComponent implements OnInit {
+ silences: AlertmanagerSilence[] = [];
+ columns: CdTableColumn[];
+ tableActions: CdTableAction[];
+ permission: Permission;
+ selection = new CdTableSelection();
+ modalRef: BsModalRef;
+ customCss = {
+ 'label label-danger': 'active',
+ 'label label-warning': 'pending',
+ 'label label-default': 'expired'
+ };
+ sorts: SortPropDir[] = [{ prop: 'endsAt', dir: SortDirection.desc }];
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private i18n: I18n,
+ private cdDatePipe: CdDatePipe,
+ private prometheusService: PrometheusService,
+ private modalService: BsModalService,
+ private notificationService: NotificationService,
+ private urlBuilder: URLBuilderService,
+ private actionLabels: ActionLabelsI18n,
+ private succeededLabels: SucceededActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().prometheus;
+ }
+
+ ngOnInit() {
+ const selectionExpired = (selection: CdTableSelection) =>
+ selection.first() && selection.first().status.state === 'expired';
+ this.tableActions = [
+ {
+ permission: 'create',
+ icon: Icons.add,
+ routerLink: () => this.urlBuilder.getCreate(),
+ preserveFragment: true,
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
+ name: this.actionLabels.CREATE
+ },
+ {
+ permission: 'create',
+ canBePrimary: (selection: CdTableSelection) =>
+ selection.hasSingleSelection && selectionExpired(selection),
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection ||
+ selection.first().cdExecuting ||
+ (selection.first().cdExecuting && selectionExpired(selection)) ||
+ !selectionExpired(selection),
+ icon: Icons.copy,
+ routerLink: () => this.urlBuilder.getRecreate(this.selection.first().id),
+ preserveFragment: true,
+ name: this.actionLabels.RECREATE
+ },
+ {
+ permission: 'update',
+ icon: Icons.edit,
+ canBePrimary: (selection: CdTableSelection) =>
+ selection.hasSingleSelection && !selectionExpired(selection),
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection ||
+ selection.first().cdExecuting ||
+ (selection.first().cdExecuting && !selectionExpired(selection)) ||
+ selectionExpired(selection),
+ routerLink: () => this.urlBuilder.getEdit(this.selection.first().id),
+ preserveFragment: true,
+ name: this.actionLabels.EDIT
+ },
+ {
+ permission: 'delete',
+ icon: Icons.trash,
+ canBePrimary: (selection: CdTableSelection) =>
+ selection.hasSingleSelection && !selectionExpired(selection),
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection ||
+ selection.first().cdExecuting ||
+ selectionExpired(selection),
+ click: () => this.expireSilence(),
+ name: this.actionLabels.EXPIRE
+ }
+ ];
+ this.columns = [
+ {
+ name: this.i18n('ID'),
+ prop: 'id',
+ flexGrow: 3
+ },
+ {
+ name: this.i18n('Created by'),
+ prop: 'createdBy',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Started'),
+ prop: 'startsAt',
+ pipe: this.cdDatePipe
+ },
+ {
+ name: this.i18n('Updated'),
+ prop: 'updatedAt',
+ pipe: this.cdDatePipe
+ },
+ {
+ name: this.i18n('Ends'),
+ prop: 'endsAt',
+ pipe: this.cdDatePipe
+ },
+ {
+ name: this.i18n('Status'),
+ prop: 'status.state',
+ cellTransformation: CellTemplate.classAdding
+ }
+ ];
+ }
+
+ refresh() {
+ this.prometheusService.ifAlertmanagerConfigured(() => {
+ this.prometheusService.getSilences().subscribe(
+ (silences) => {
+ this.silences = silences;
+ },
+ () => {
+ this.prometheusService.disableAlertmanagerConfig();
+ }
+ );
+ });
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ expireSilence() {
+ const id = this.selection.first().id;
+ const i18nSilence = this.i18n('Silence');
+ const applicationName = 'Prometheus';
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: i18nSilence,
+ itemNames: [id],
+ actionDescription: this.actionLabels.EXPIRE,
+ submitActionObservable: () =>
+ new Observable((observer: Subscriber<any>) => {
+ this.prometheusService.expireSilence(id).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ `${this.succeededLabels.EXPIRED} ${i18nSilence} ${id}`,
+ undefined,
+ undefined,
+ applicationName
+ );
+ },
+ (resp) => {
+ resp['application'] = applicationName;
+ observer.error(resp);
+ },
+ () => {
+ observer.complete();
+ this.refresh();
+ }
+ );
+ })
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.html
new file mode 100644
index 00000000..c0ad6ac6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.html
@@ -0,0 +1,98 @@
+<div class="modal-header">
+ <h4 class="modal-title pull-left"
+ i18n>Matcher</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+
+<form class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="form"
+ novalidate>
+ <div class="modal-body">
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('name', formDir)}">
+ <label class="control-label col-sm-3"
+ for="name">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="name"
+ formControlName="name"
+ name="name">
+ <option [ngValue]="null"
+ i18n>-- Select an attribute to match against --</option>
+ <option *ngFor="let attribute of nameAttributes"
+ [value]="attribute">
+ {{ attribute }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="form.showError('name', formDir, 'required')"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <!-- Value -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('value', formDir)}">
+ <label class="control-label col-sm-3"
+ for="value">
+ <ng-container i18n>Value</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="value"
+ class="form-control"
+ type="text"
+ [typeahead]="possibleValues"
+ [typeaheadMinLength]="0"
+ formControlName="value">
+ <span *ngIf="form.showError('value', formDir, 'required')"
+ class="help-block"
+ i18n>This field is required!</span>
+ </div>
+ <div *ngIf="form.getValue('value') && !form.getValue('isRegex') && matcherMatch"
+ class="col-sm-offset-3 col-sm-9 {{matcherMatch.cssClass}}"
+ id="match-state">
+ <span class="help-block {{matcherMatch.cssClass}}">
+ {{matcherMatch.status}}
+ </span>
+ </div>
+ </div>
+
+ <!-- isRegex -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="input-group">
+ <div class="checkbox checkbox-primary">
+ <input id="is-regex"
+ type="checkbox"
+ formControlName="isRegex">
+ <label for="is-regex"
+ i18n>Use regular expression</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <cd-submit-button (submitAction)="onSubmit()"
+ [form]="form">
+ <ng-container i18n>{editMode, select, 1 {Update} other {Add}}</ng-container>
+ </cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Close"
+ i18n-name>
+ </cd-back-button>
+ </div>
+</form>
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.spec.ts
new file mode 100644
index 00000000..cd8fa280
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.spec.ts
@@ -0,0 +1,163 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
+
+import {
+ configureTestBed,
+ FixtureHelper,
+ FormHelper,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { SilenceMatcherModalComponent } from './silence-matcher-modal.component';
+
+describe('SilenceMatcherModalComponent', () => {
+ let component: SilenceMatcherModalComponent;
+ let fixture: ComponentFixture<SilenceMatcherModalComponent>;
+
+ let formH: FormHelper;
+ let fixtureH: FixtureHelper;
+ let prometheus: PrometheusHelper;
+
+ configureTestBed({
+ declarations: [SilenceMatcherModalComponent],
+ imports: [
+ HttpClientTestingModule,
+ SharedModule,
+ TypeaheadModule.forRoot(),
+ RouterTestingModule,
+ ReactiveFormsModule
+ ],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SilenceMatcherModalComponent);
+ component = fixture.componentInstance;
+
+ fixtureH = new FixtureHelper(fixture);
+ formH = new FormHelper(component.form);
+ prometheus = new PrometheusHelper();
+
+ component.rules = [
+ prometheus.createRule('alert0', 'someSeverity', [prometheus.createAlert('alert0')]),
+ prometheus.createRule('alert1', 'someSeverity', [])
+ ];
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should have a name field', () => {
+ formH.expectError('name', 'required');
+ formH.expectValidChange('name', 'alertname');
+ });
+
+ it('should only allow a specific set of name attributes', () => {
+ expect(component.nameAttributes).toEqual(['alertname', 'instance', 'job', 'severity']);
+ });
+
+ it('should autocomplete a list based on the set name', () => {
+ const expectations = {
+ alertname: ['alert0', 'alert1'],
+ instance: ['someInstance'],
+ job: ['someJob'],
+ severity: ['someSeverity']
+ };
+ Object.keys(expectations).forEach((key) => {
+ formH.setValue('name', key);
+ expect(component.possibleValues).toEqual(expectations[key]);
+ });
+ });
+
+ describe('test rule matching', () => {
+ const expectMatch = (name, value, helpText) => {
+ component.preFillControls({
+ name: name,
+ value: value,
+ isRegex: false
+ });
+ expect(fixtureH.getText('#match-state')).toBe(helpText);
+ };
+
+ it('should match no rule and no alert', () => {
+ expectMatch(
+ 'alertname',
+ 'alert',
+ 'Your matcher seems to match no currently defined rule or active alert.'
+ );
+ });
+
+ it('should match a rule with no alert', () => {
+ expectMatch('alertname', 'alert1', 'Matches 1 rule with no active alerts.');
+ });
+
+ it('should match a rule and an alert', () => {
+ expectMatch('alertname', 'alert0', 'Matches 1 rule with 1 active alert.');
+ });
+
+ it('should match multiple rules and an alert', () => {
+ expectMatch('severity', 'someSeverity', 'Matches 2 rules with 1 active alert.');
+ });
+
+ it('should match multiple rules and multiple alerts', () => {
+ component.rules[1].alerts.push(null);
+ expectMatch('severity', 'someSeverity', 'Matches 2 rules with 2 active alerts.');
+ });
+
+ it('should not show match-state if regex is checked', () => {
+ fixtureH.expectElementVisible('#match-state', false);
+ formH.setValue('name', 'severity');
+ formH.setValue('value', 'someSeverity');
+ fixtureH.expectElementVisible('#match-state', true);
+ formH.setValue('isRegex', true);
+ fixtureH.expectElementVisible('#match-state', false);
+ });
+ });
+
+ it('should only enable value field if name was set', () => {
+ const value = component.form.get('value');
+ expect(value.disabled).toBeTruthy();
+ formH.setValue('name', component.nameAttributes[0]);
+ expect(value.enabled).toBeTruthy();
+ formH.setValue('name', null);
+ expect(value.disabled).toBeTruthy();
+ });
+
+ it('should have a value field', () => {
+ formH.setValue('name', component.nameAttributes[0]);
+ formH.expectError('value', 'required');
+ formH.expectValidChange('value', 'alert0');
+ });
+
+ it('should test preFillControls', () => {
+ const controlValues = {
+ name: 'alertname',
+ value: 'alert0',
+ isRegex: false
+ };
+ component.preFillControls(controlValues);
+ expect(component.form.value).toEqual(controlValues);
+ });
+
+ it('should test submit', (done) => {
+ const controlValues = {
+ name: 'alertname',
+ value: 'alert0',
+ isRegex: false
+ };
+ component.preFillControls(controlValues);
+ component.submitAction.subscribe((resp) => {
+ expect(resp).toEqual(controlValues);
+ done();
+ });
+ component.onSubmit();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.ts
new file mode 100644
index 00000000..d04537fc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-matcher-modal/silence-matcher-modal.component.ts
@@ -0,0 +1,79 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import {
+ AlertmanagerSilenceMatcher,
+ AlertmanagerSilenceMatcherMatch
+} from '../../../../shared/models/alertmanager-silence';
+import { PrometheusRule } from '../../../../shared/models/prometheus-alerts';
+import { PrometheusSilenceMatcherService } from '../../../../shared/services/prometheus-silence-matcher.service';
+
+@Component({
+ selector: 'cd-silence-matcher-modal',
+ templateUrl: './silence-matcher-modal.component.html',
+ styleUrls: ['./silence-matcher-modal.component.scss']
+})
+export class SilenceMatcherModalComponent {
+ @Output()
+ submitAction = new EventEmitter();
+
+ form: CdFormGroup;
+ editMode = false;
+ rules: PrometheusRule[];
+ nameAttributes = ['alertname', 'instance', 'job', 'severity'];
+ possibleValues: string[] = [];
+ matcherMatch: AlertmanagerSilenceMatcherMatch = undefined;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ private silenceMatcher: PrometheusSilenceMatcherService,
+ public bsModalRef: BsModalRef
+ ) {
+ this.createForm();
+ this.subscribeToChanges();
+ }
+
+ private createForm() {
+ this.form = this.formBuilder.group({
+ name: [null, [Validators.required]],
+ value: [{ value: null, disabled: true }, [Validators.required]],
+ isRegex: new FormControl(false)
+ });
+ }
+
+ private subscribeToChanges() {
+ this.form.get('name').valueChanges.subscribe((name) => {
+ if (name === null) {
+ this.form.get('value').disable();
+ return;
+ }
+ this.setPossibleValues(name);
+ this.form.get('value').enable();
+ });
+ this.form.get('value').valueChanges.subscribe((value) => {
+ const values = this.form.value;
+ values.value = value; // Isn't the current value at this stage
+ this.matcherMatch = this.silenceMatcher.singleMatch(values, this.rules);
+ });
+ }
+
+ private setPossibleValues(name) {
+ this.possibleValues = _.sortedUniq(
+ this.rules.map((r) => _.get(r, this.silenceMatcher.getAttributePath(name))).filter((x) => x)
+ );
+ }
+
+ preFillControls(matcher: AlertmanagerSilenceMatcher) {
+ this.form.setValue(matcher);
+ }
+
+ onSubmit() {
+ this.submitAction.emit(this.form.value);
+ this.bsModalRef.hide();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts
new file mode 100644
index 00000000..49630da4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts
@@ -0,0 +1,44 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { ChartsModule } from 'ng2-charts';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { SharedModule } from '../../shared/shared.module';
+import { CephSharedModule } from '../shared/ceph-shared.module';
+import { DashboardComponent } from './dashboard/dashboard.component';
+import { HealthPieComponent } from './health-pie/health-pie.component';
+import { HealthComponent } from './health/health.component';
+import { InfoCardComponent } from './info-card/info-card.component';
+import { InfoGroupComponent } from './info-group/info-group.component';
+import { MdsSummaryPipe } from './mds-summary.pipe';
+import { MgrSummaryPipe } from './mgr-summary.pipe';
+import { MonSummaryPipe } from './mon-summary.pipe';
+import { OsdSummaryPipe } from './osd-summary.pipe';
+
+@NgModule({
+ imports: [
+ CephSharedModule,
+ CommonModule,
+ TabsModule.forRoot(),
+ SharedModule,
+ ChartsModule,
+ RouterModule,
+ PopoverModule.forRoot()
+ ],
+
+ declarations: [
+ HealthComponent,
+ DashboardComponent,
+ MonSummaryPipe,
+ OsdSummaryPipe,
+ MgrSummaryPipe,
+ MdsSummaryPipe,
+ HealthPieComponent,
+ InfoCardComponent,
+ InfoGroupComponent
+ ]
+})
+export class DashboardModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.html
new file mode 100644
index 00000000..c59717c5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.html
@@ -0,0 +1,13 @@
+<div>
+ <cd-refresh-selector></cd-refresh-selector>
+ <tabset *ngIf="hasGrafana">
+ <tab i18n-heading
+ heading="Health">
+ <cd-health></cd-health>
+ </tab>
+ <tab i18n-heading
+ heading="Statistics">
+ </tab>
+ </tabset>
+ <cd-health *ngIf="!hasGrafana"></cd-health>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.scss
new file mode 100644
index 00000000..04eee2d6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.scss
@@ -0,0 +1,3 @@
+div {
+ padding-top: 20px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts
new file mode 100644
index 00000000..079ae3e1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.spec.ts
@@ -0,0 +1,25 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { DashboardComponent } from './dashboard.component';
+
+describe('DashboardComponent', () => {
+ let component: DashboardComponent;
+ let fixture: ComponentFixture<DashboardComponent>;
+
+ configureTestBed({
+ declarations: [DashboardComponent],
+ schemas: [NO_ERRORS_SCHEMA]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DashboardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.ts
new file mode 100644
index 00000000..7d0b4244
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard/dashboard.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'cd-dashboard',
+ templateUrl: './dashboard.component.html',
+ styleUrls: ['./dashboard.component.scss']
+})
+export class DashboardComponent implements OnInit {
+ hasGrafana = false; // TODO: Temporary var, remove when grafana is implemented
+
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie-color.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie-color.enum.ts
new file mode 100644
index 00000000..fbeadcc2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie-color.enum.ts
@@ -0,0 +1,7 @@
+export enum HealthPieColor {
+ DEFAULT_RED = '#ff7592',
+ DEFAULT_BLUE = '#1d699d',
+ DEFAULT_ORANGE = '#ffa500',
+ DEFAULT_MAGENTA = '#564d65',
+ DEFAULT_GREEN = '#00bb00'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.html
new file mode 100644
index 00000000..02b72b25
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.html
@@ -0,0 +1,15 @@
+<div class="chart-container">
+ <canvas baseChart
+ #chartCanvas
+ [datasets]="chartConfig.dataset"
+ [chartType]="chartConfig.chartType"
+ [options]="chartConfig.options"
+ [labels]="chartConfig.labels"
+ [colors]="chartConfig.colors"
+ class="chart-canvas">
+ </canvas>
+ <div class="chartjs-tooltip"
+ #chartTooltip>
+ <table></table>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.scss
new file mode 100644
index 00000000..e2d23cd4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.scss
@@ -0,0 +1,22 @@
+@import '../../../../styles/chart-tooltip.scss';
+
+$canvas-width: 100%;
+$canvas-height: 100%;
+
+.chart-container {
+ position: unset;
+ width: $canvas-width;
+ height: $canvas-height;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.chart-canvas {
+ position: unset;
+ width: $canvas-width;
+ height: $canvas-height;
+ margin-left: auto;
+ margin-right: auto;
+ max-width: $canvas-width;
+ max-height: $canvas-height;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.spec.ts
new file mode 100644
index 00000000..25782502
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.spec.ts
@@ -0,0 +1,74 @@
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { HealthPieComponent } from './health-pie.component';
+
+describe('HealthPieComponent', () => {
+ let component: HealthPieComponent;
+ let fixture: ComponentFixture<HealthPieComponent>;
+
+ configureTestBed({
+ schemas: [NO_ERRORS_SCHEMA],
+ declarations: [HealthPieComponent],
+ providers: [DimlessBinaryPipe, DimlessPipe, FormatterService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HealthPieComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('Add slice border if there is more than one slice with numeric non zero value', () => {
+ component.chartConfig.dataset[0].data = [48, 0, 1, 0];
+ component.ngOnChanges();
+
+ expect(component.chartConfig.dataset[0].borderWidth).toEqual(1);
+ });
+
+ it('Remove slice border if there is only one slice with numeric non zero value', () => {
+ component.chartConfig.dataset[0].data = [48, 0, undefined, 0];
+ component.ngOnChanges();
+
+ expect(component.chartConfig.dataset[0].borderWidth).toEqual(0);
+ });
+
+ it('Remove slice border if there is no slice with numeric non zero value', () => {
+ component.chartConfig.dataset[0].data = [undefined, 0];
+ component.ngOnChanges();
+
+ expect(component.chartConfig.dataset[0].borderWidth).toEqual(0);
+ });
+
+ it('should not hide any slice if there is no user click on legend item', () => {
+ const initialData = [8, 15];
+ component.chartConfig.dataset[0].data = initialData;
+ component.ngOnChanges();
+
+ expect(component.chartConfig.dataset[0].data).toEqual(initialData);
+ });
+
+ describe('tooltip body', () => {
+ const tooltipBody = ['text: 10000'];
+
+ it('should return amount converted to appropriate units', () => {
+ component.isBytesData = false;
+ expect(component['getChartTooltipBody'](tooltipBody)).toEqual('text: 10 k');
+
+ component.isBytesData = true;
+ expect(component['getChartTooltipBody'](tooltipBody)).toEqual('text: 9.8 KiB');
+ });
+
+ it('should not return amount when showing label as tooltip', () => {
+ component.showLabelAsTooltip = true;
+ expect(component['getChartTooltipBody'](tooltipBody)).toEqual('text');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.ts
new file mode 100644
index 00000000..f4baefb4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health-pie/health-pie.component.ts
@@ -0,0 +1,187 @@
+import {
+ Component,
+ ElementRef,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnInit,
+ Output,
+ ViewChild
+} from '@angular/core';
+
+import * as Chart from 'chart.js';
+import * as _ from 'lodash';
+
+import { ChartTooltip } from '../../../shared/models/chart-tooltip';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { HealthPieColor } from './health-pie-color.enum';
+
+@Component({
+ selector: 'cd-health-pie',
+ templateUrl: './health-pie.component.html',
+ styleUrls: ['./health-pie.component.scss']
+})
+export class HealthPieComponent implements OnChanges, OnInit {
+ @ViewChild('chartCanvas')
+ chartCanvasRef: ElementRef;
+ @ViewChild('chartTooltip')
+ chartTooltipRef: ElementRef;
+
+ @Input()
+ data: any;
+ @Input()
+ config = {};
+ @Input()
+ isBytesData = false;
+ @Input()
+ tooltipFn: any;
+ @Input()
+ showLabelAsTooltip = false;
+ @Output()
+ prepareFn = new EventEmitter();
+
+ chartConfig: any = {
+ chartType: 'pie',
+ dataset: [
+ {
+ label: null,
+ borderWidth: 0
+ }
+ ],
+ options: {
+ legend: {
+ display: true,
+ position: 'right',
+ labels: { usePointStyle: true },
+ onClick: (event, legendItem) => {
+ this.onLegendClick(event, legendItem);
+ }
+ },
+ animation: { duration: 0 },
+ tooltips: {
+ enabled: false
+ },
+ title: {
+ display: false
+ }
+ }
+ };
+ private hiddenSlices = [];
+
+ constructor(private dimlessBinary: DimlessBinaryPipe, private dimless: DimlessPipe) {}
+
+ ngOnInit() {
+ // An extension to Chart.js to enable rendering some
+ // text in the middle of a doughnut
+ Chart.pluginService.register({
+ beforeDraw: function(chart) {
+ if (!chart.options.center_text) {
+ return;
+ }
+
+ const width = chart.chart.width,
+ height = chart.chart.height,
+ ctx = chart.chart.ctx;
+
+ ctx.restore();
+ const fontSize = (height / 114).toFixed(2);
+ ctx.font = fontSize + 'em sans-serif';
+ ctx.textBaseline = 'middle';
+
+ const text = chart.options.center_text,
+ textX = Math.round((width - ctx.measureText(text).width) / 2),
+ textY = height / 2;
+
+ ctx.fillText(text, textX, textY);
+ ctx.save();
+ }
+ });
+
+ const getStyleTop = (tooltip, positionY) => {
+ return positionY + tooltip.caretY - tooltip.height - 10 + 'px';
+ };
+
+ const getStyleLeft = (tooltip, positionX) => {
+ return positionX + tooltip.caretX + 'px';
+ };
+
+ const chartTooltip = new ChartTooltip(
+ this.chartCanvasRef,
+ this.chartTooltipRef,
+ getStyleLeft,
+ getStyleTop
+ );
+
+ const getBody = (body) => {
+ return this.getChartTooltipBody(body);
+ };
+
+ chartTooltip.getBody = getBody;
+
+ this.chartConfig.options.tooltips.custom = (tooltip) => {
+ chartTooltip.customTooltips(tooltip);
+ };
+
+ this.chartConfig.colors = [
+ {
+ backgroundColor: [
+ HealthPieColor.DEFAULT_RED,
+ HealthPieColor.DEFAULT_BLUE,
+ HealthPieColor.DEFAULT_ORANGE,
+ HealthPieColor.DEFAULT_GREEN,
+ HealthPieColor.DEFAULT_MAGENTA
+ ]
+ }
+ ];
+
+ _.merge(this.chartConfig, this.config);
+
+ this.prepareFn.emit([this.chartConfig, this.data]);
+ }
+
+ ngOnChanges() {
+ this.prepareFn.emit([this.chartConfig, this.data]);
+ this.hideSlices();
+ this.setChartSliceBorderWidth();
+ }
+
+ private getChartTooltipBody(body) {
+ const bodySplit = body[0].split(': ');
+
+ if (this.showLabelAsTooltip) {
+ return bodySplit[0];
+ }
+
+ bodySplit[1] = this.isBytesData
+ ? this.dimlessBinary.transform(bodySplit[1])
+ : this.dimless.transform(bodySplit[1]);
+
+ return bodySplit.join(': ');
+ }
+
+ private setChartSliceBorderWidth() {
+ let nonZeroValueSlices = 0;
+ _.forEach(this.chartConfig.dataset[0].data, function(slice) {
+ if (slice > 0) {
+ nonZeroValueSlices += 1;
+ }
+ });
+
+ this.chartConfig.dataset[0].borderWidth = nonZeroValueSlices > 1 ? 1 : 0;
+ }
+
+ private onLegendClick(event, legendItem) {
+ event.stopPropagation();
+ this.hiddenSlices[legendItem.index] = !legendItem.hidden;
+ this.ngOnChanges();
+ }
+
+ private hideSlices() {
+ _.forEach(this.chartConfig.dataset[0].data, (_slice, sliceIndex) => {
+ if (this.hiddenSlices[sliceIndex]) {
+ this.chartConfig.dataset[0].data[sliceIndex] = undefined;
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html
new file mode 100644
index 00000000..75d2b94f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html
@@ -0,0 +1,267 @@
+<div *ngIf="healthData && enabledFeature$ | async as enabledFeature"
+ class="container-fluid">
+ <cd-info-group groupTitle="Status"
+ i18n-groupTitle
+ class="row info-group"
+ *ngIf="healthData.health?.status
+ || healthData.mon_status
+ || healthData.osd_map
+ || healthData.mgr_map
+ || healthData.hosts != null
+ || healthData.rgw != null
+ || healthData.fs_map
+ || healthData.iscsi_daemons != null">
+
+ <cd-info-card cardTitle="Cluster Status"
+ i18n-cardTitle
+ class="col-sm-6 col-md-4 col-lg-3"
+ [contentClass]="healthData.health?.checks?.length > 0 ? 'content-highlight text-area-size-2' : 'content-highlight'"
+ *ngIf="healthData.health?.status">
+ <ng-container *ngIf="healthData.health?.checks?.length > 0">
+ <ng-template #healthChecks>
+ <ng-container *ngTemplateOutlet="logsLink"></ng-container>
+ <ul>
+ <li *ngFor="let check of healthData.health.checks">
+ <span [ngStyle]="check.severity | healthColor">{{ check.type }}</span>: {{ check.summary.message }}
+ </li>
+ </ul>
+ </ng-template>
+ <div class="info-card-content-clickable"
+ [ngStyle]="healthData.health.status | healthColor"
+ [popover]="healthChecks"
+ triggers=""
+ #healthChecksTarget="bs-popover"
+ placement="bottom"
+ container="body"
+ containerClass="info-card-popover-cluster-status"
+ (click)="healthChecksTarget.toggle()">
+ {{ healthData.health.status }}
+ </div>
+ </ng-container>
+ <ng-container *ngIf="!healthData.health?.checks?.length">
+ <div [ngStyle]="healthData.health.status | healthColor">
+ {{ healthData.health.status }}
+ </div>
+ </ng-container>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Monitors"
+ i18n-cardTitle
+ link="/monitor"
+ class="col-sm-6 col-md-4 col-lg-3"
+ contentClass="content-highlight"
+ *ngIf="healthData.mon_status">
+ {{ healthData.mon_status | monSummary }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="OSDs"
+ i18n-cardTitle
+ link="/osd"
+ class="col-sm-6 col-md-4 col-lg-3"
+ *ngIf="(healthData.osd_map | osdSummary) as transformedResult"
+ [contentClass]="(transformedResult.length == 5 ? 'text-area-size-3' : 'text-area-size-2') + ' content-highlight'">
+ <span *ngFor="let result of transformedResult"
+ [ngClass]="result.class">
+ {{ result.content }}
+ </span>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Manager Daemons"
+ i18n-cardTitle
+ class="col-sm-6 col-md-4 col-lg-3"
+ contentClass="content-highlight text-area-size-2"
+ *ngIf="healthData.mgr_map">
+ <span *ngFor="let result of (healthData.mgr_map | mgrSummary)"
+ [ngClass]="result.class"
+ [title]="result.titleText != null ? result.titleText : ''">
+ {{ result.content }}
+ </span>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Hosts"
+ i18n-cardTitle
+ link="/hosts"
+ class="col-sm-6 col-md-4 col-lg-3"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.hosts != null">
+ {{ healthData.hosts }} total
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Object Gateways"
+ i18n-cardTitle
+ link="/rgw/daemon"
+ class="col-sm-6 col-md-4 col-lg-3"
+ contentClass="content-medium content-highlight"
+ *ngIf="enabledFeature.rgw && healthData.rgw != null">
+ {{ healthData.rgw }} total
+ </cd-info-card>
+ <cd-info-card cardTitle="Metadata Servers"
+ i18n-cardTitle
+ class="col-sm-6 col-md-4 col-lg-3"
+ *ngIf="((enabledFeature.cephfs && healthData.fs_map) | mdsSummary) as transformedResult"
+ [contentClass]="(transformedResult.length > 1 ? 'text-area-size-2' : '') + ' content-highlight'">
+ <span *ngFor="let result of transformedResult"
+ [ngClass]="result.class"
+ [title]="result.titleText != null ? result.titleText : ''">
+ {{ result.content }}
+ </span>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="iSCSI Gateways"
+ i18n-cardTitle
+ link="/block/iscsi"
+ class="col-sm-6 col-md-4 col-lg-3"
+ contentClass="content-medium content-highlight"
+ *ngIf="enabledFeature.iscsi && healthData.iscsi_daemons != null">
+ {{ healthData.iscsi_daemons }} total
+ </cd-info-card>
+ </cd-info-group>
+
+ <cd-info-group groupTitle="Performance"
+ i18n-groupTitle
+ class="row info-group"
+ *ngIf="healthData.client_perf || healthData.scrub_status">
+
+ <div class="cd-container-flex">
+ <cd-info-card cardTitle="Client IOPS"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.client_perf">
+ {{ (healthData.client_perf.read_op_per_sec + healthData.client_perf.write_op_per_sec) | round:1 }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Client Throughput"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.client_perf">
+ {{ ((healthData.client_perf.read_bytes_sec + healthData.client_perf.write_bytes_sec) | dimlessBinary) + '/s' }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Client Read/Write"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ [contentClass]="isClientReadWriteChartShowable() ? 'content-chart': 'content-medium content-highlight'"
+ *ngIf="healthData.client_perf">
+ <cd-health-pie *ngIf="isClientReadWriteChartShowable()"
+ [data]="healthData"
+ (prepareFn)="prepareReadWriteRatio($event[0], $event[1])">
+ </cd-health-pie>
+ <span *ngIf="!isClientReadWriteChartShowable()">
+ N/A
+ </span>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Recovery Throughput"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.client_perf">
+ {{ (healthData.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Scrub"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.scrub_status">
+ {{ healthData.scrub_status }}
+ </cd-info-card>
+ </div>
+ </cd-info-group>
+
+ <cd-info-group groupTitle="Capacity"
+ i18n-groupTitle
+ class="row info-group"
+ *ngIf="healthData.pools
+ || healthData.df
+ || healthData.pg_info">
+
+ <div class="cd-container-flex">
+ <cd-info-card cardTitle="Pools"
+ i18n-cardTitle
+ link="/pool"
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.pools">
+ {{ healthData.pools.length }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Raw Capacity"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-chart"
+ *ngIf="healthData.df">
+ <cd-health-pie [data]="healthData"
+ [config]="rawCapacityChartConfig"
+ [showLabelAsTooltip]="true"
+ (prepareFn)="prepareRawUsage($event[0], $event[1])">
+ </cd-health-pie>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="Objects"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-chart"
+ *ngIf="healthData.pg_info?.object_stats?.num_objects != null">
+ <cd-health-pie [data]="healthData"
+ [config]="objectsChartConfig"
+ (prepareFn)="prepareObjects($event[0], $event[1])">
+ </cd-health-pie>
+ </cd-info-card>
+
+ <cd-info-card cardTitle="PGs per OSD"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-medium content-highlight"
+ *ngIf="healthData.pg_info">
+ {{ healthData.pg_info.pgs_per_osd | dimless }}
+ </cd-info-card>
+
+ <cd-info-card cardTitle="PG Status"
+ i18n-cardTitle
+ class="cd-col-5"
+ cardClass="card-medium"
+ contentClass="content-chart"
+ (click)="pgStatusTarget.toggle()"
+ *ngIf="healthData.pg_info">
+ <ng-template #pgStatus>
+ <ng-container *ngTemplateOutlet="logsLink"></ng-container>
+ <ul>
+ <li *ngFor="let pgStatesText of healthData.pg_info.statuses | keyvalue">
+ {{ pgStatesText.key }}: {{ pgStatesText.value }}
+ </li>
+ </ul>
+ </ng-template>
+ <div class="pg-status-popover-wrapper">
+ <div [popover]="pgStatus"
+ triggers=""
+ #pgStatusTarget="bs-popover"
+ placement="bottom">
+ <cd-health-pie [data]="healthData"
+ [config]="pgStatusChartConfig"
+ (prepareFn)="preparePgStatus($event[0], $event[1])">
+ </cd-health-pie>
+ </div>
+ </div>
+ </cd-info-card>
+ </div>
+ </cd-info-group>
+
+ <ng-template #logsLink>
+ <ng-container *ngIf="permissions.log.read">
+ <p class="logs-link"
+ i18n><i class="fa fa-info-circle"></i> See <a routerLink="/logs">Logs</a> for more details.</p>
+ </ng-container>
+ </ng-template>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.scss
new file mode 100644
index 00000000..ae1505ce
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.scss
@@ -0,0 +1,89 @@
+@import '../../../../defaults';
+
+cd-info-card {
+ padding: 0 0.5vw 0 0.5vw;
+}
+
+.cd-container-flex {
+ margin: 0;
+ padding: 0;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-between;
+}
+
+.cd-col-5 {
+ width: 20%;
+}
+
+@media (max-width: 1599px) {
+ .cd-col-5 {
+ width: 25%;
+ }
+}
+
+@media (max-width: $screen-md-max) {
+ .cd-col-5 {
+ width: 33%;
+ }
+}
+
+@media (max-width: $screen-sm-max) {
+ .cd-col-5 {
+ width: 50%;
+ }
+}
+
+@media (max-width: $screen-xs-max) {
+ cd-info-card {
+ padding: 0;
+ }
+
+ .cd-col-5 {
+ width: 100%;
+ }
+}
+
+.info-group {
+ margin: 0;
+ padding: 0;
+}
+
+::ng-deep .pg-status-popover-wrapper {
+ position: relative;
+
+ .popover {
+ position: absolute;
+ width: 116%;
+ max-height: 20vh;
+ min-width: unset !important;
+ max-width: unset !important;
+
+ .popover-body {
+ max-width: 100%;
+ max-height: 19vh;
+ font-size: 12px;
+ }
+ }
+}
+
+.logs-link {
+ text-align: center;
+}
+
+.card-text-error {
+ display: inline;
+ color: $color-solid-red;
+}
+
+.card-text-line-break:after {
+ content: '\A';
+ white-space: pre;
+}
+
+.popover-info:hover {
+ cursor: pointer;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts
new file mode 100644
index 00000000..eb849ae8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts
@@ -0,0 +1,338 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+
+import * as _ from 'lodash';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { of } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { HealthService } from '../../../shared/api/health.service';
+import { Permissions } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { FeatureTogglesService } from '../../../shared/services/feature-toggles.service';
+import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { PgCategoryService } from '../../shared/pg-category.service';
+import { HealthPieComponent } from '../health-pie/health-pie.component';
+import { MdsSummaryPipe } from '../mds-summary.pipe';
+import { MgrSummaryPipe } from '../mgr-summary.pipe';
+import { MonSummaryPipe } from '../mon-summary.pipe';
+import { OsdSummaryPipe } from '../osd-summary.pipe';
+import { HealthComponent } from './health.component';
+
+describe('HealthComponent', () => {
+ let component: HealthComponent;
+ let fixture: ComponentFixture<HealthComponent>;
+ let getHealthSpy;
+ const healthPayload = {
+ health: { status: 'HEALTH_OK' },
+ mon_status: { monmap: { mons: [] }, quorum: [] },
+ osd_map: { osds: [] },
+ mgr_map: { standbys: [] },
+ hosts: 0,
+ rgw: 0,
+ fs_map: { filesystems: [], standbys: [] },
+ iscsi_daemons: 0,
+ client_perf: {},
+ scrub_status: 'Inactive',
+ pools: [],
+ df: { stats: {} },
+ pg_info: { object_stats: { num_objects: 0 } }
+ };
+ const fakeAuthStorageService = {
+ getPermissions: () => {
+ return new Permissions({ log: ['read'] });
+ }
+ };
+ let fakeFeatureTogglesService;
+
+ configureTestBed({
+ imports: [SharedModule, HttpClientTestingModule, PopoverModule.forRoot()],
+ declarations: [
+ HealthComponent,
+ HealthPieComponent,
+ MonSummaryPipe,
+ OsdSummaryPipe,
+ MdsSummaryPipe,
+ MgrSummaryPipe
+ ],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ i18nProviders,
+ { provide: AuthStorageService, useValue: fakeAuthStorageService },
+ PgCategoryService,
+ RefreshIntervalService
+ ]
+ });
+
+ beforeEach(() => {
+ fakeFeatureTogglesService = spyOn(TestBed.get(FeatureTogglesService), 'get').and.returnValue(
+ of({
+ rbd: true,
+ mirroring: true,
+ iscsi: true,
+ cephfs: true,
+ rgw: true
+ })
+ );
+ fixture = TestBed.createComponent(HealthComponent);
+ component = fixture.componentInstance;
+ getHealthSpy = spyOn(TestBed.get(HealthService), 'getMinimalHealth');
+ getHealthSpy.and.returnValue(of(healthPayload));
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should render all info groups and all info cards', () => {
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(3);
+
+ const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card');
+ expect(infoCards.length).toBe(18);
+ });
+
+ describe('features disabled', () => {
+ beforeEach(() => {
+ fakeFeatureTogglesService.and.returnValue(
+ of({
+ rbd: false,
+ mirroring: false,
+ iscsi: false,
+ cephfs: false,
+ rgw: false
+ })
+ );
+ fixture = TestBed.createComponent(HealthComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should not render cards related to disabled features', () => {
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(3);
+
+ const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card');
+ expect(infoCards.length).toBe(15);
+ });
+ });
+
+ it('should render all except "Status" group and cards', () => {
+ const payload = _.cloneDeep(healthPayload);
+ payload.health.status = '';
+ payload.mon_status = null;
+ payload.osd_map = null;
+ payload.mgr_map = null;
+ payload.hosts = null;
+ payload.rgw = null;
+ payload.fs_map = null;
+ payload.iscsi_daemons = null;
+
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(2);
+
+ const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card');
+ expect(infoCards.length).toBe(10);
+ });
+
+ it('should render all except "Performance" group and cards', () => {
+ const payload = _.cloneDeep(healthPayload);
+ payload.scrub_status = '';
+ payload.client_perf = null;
+
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(2);
+
+ const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card');
+ expect(infoCards.length).toBe(13);
+ });
+
+ it('should render all except "Capacity" group and cards', () => {
+ const payload = _.cloneDeep(healthPayload);
+ payload.pools = null;
+ payload.df = null;
+ payload.pg_info = null;
+
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(2);
+
+ const infoCards = fixture.debugElement.nativeElement.querySelectorAll('cd-info-card');
+ expect(infoCards.length).toBe(13);
+ });
+
+ it('should render all groups and 1 card per group', () => {
+ const payload = { hosts: 0, scrub_status: 'Inactive', pools: [] };
+
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ const infoGroups = fixture.debugElement.nativeElement.querySelectorAll('cd-info-group');
+ expect(infoGroups.length).toBe(3);
+
+ _.each(infoGroups, (infoGroup) => {
+ expect(infoGroup.querySelectorAll('cd-info-card').length).toBe(1);
+ });
+ });
+
+ it('should render "Cluster Status" card text that is not clickable', () => {
+ fixture.detectChanges();
+
+ const clusterStatusCard = fixture.debugElement.query(
+ By.css('cd-info-card[cardTitle="Cluster Status"]')
+ );
+ const clickableContent = clusterStatusCard.query(By.css('.info-card-content-clickable'));
+ expect(clickableContent).toBeNull();
+ expect(clusterStatusCard.nativeElement.textContent).toEqual(` ${healthPayload.health.status} `);
+ });
+
+ it('should render "Cluster Status" card text that is clickable (popover)', () => {
+ const payload = _.cloneDeep(healthPayload);
+ payload.health['status'] = 'HEALTH_WARN';
+ payload.health['checks'] = [
+ { severity: 'HEALTH_WARN', type: 'WRN', summary: { message: 'fake warning' } }
+ ];
+
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ expect(component.permissions.log.read).toBeTruthy();
+
+ const clusterStatusCard = fixture.debugElement.query(
+ By.css('cd-info-card[cardTitle="Cluster Status"]')
+ );
+ const clickableContent = clusterStatusCard.query(By.css('.info-card-content-clickable'));
+ expect(clickableContent.nativeElement.textContent).toEqual(` ${payload.health.status} `);
+ });
+
+ it('event binding "prepareReadWriteRatio" is called', () => {
+ const prepareReadWriteRatio = spyOn(component, 'prepareReadWriteRatio');
+
+ const payload = _.cloneDeep(healthPayload);
+ payload.client_perf['read_op_per_sec'] = 1;
+ payload.client_perf['write_op_per_sec'] = 1;
+ getHealthSpy.and.returnValue(of(payload));
+ fixture.detectChanges();
+
+ expect(prepareReadWriteRatio).toHaveBeenCalled();
+ });
+
+ it('event binding "prepareRawUsage" is called', () => {
+ const prepareRawUsage = spyOn(component, 'prepareRawUsage');
+
+ fixture.detectChanges();
+
+ expect(prepareRawUsage).toHaveBeenCalled();
+ });
+
+ it('event binding "preparePgStatus" is called', () => {
+ const preparePgStatus = spyOn(component, 'preparePgStatus');
+
+ fixture.detectChanges();
+
+ expect(preparePgStatus).toHaveBeenCalled();
+ });
+
+ it('event binding "prepareObjects" is called', () => {
+ const prepareObjects = spyOn(component, 'prepareObjects');
+
+ fixture.detectChanges();
+
+ expect(prepareObjects).toHaveBeenCalled();
+ });
+
+ describe('preparePgStatus', () => {
+ const calcPercentage = (data) => Math.round((data / 10) * 100) || 0;
+
+ const expectedChart = (data: number[]) => ({
+ labels: [
+ `Clean (${calcPercentage(data[0])}%)`,
+ `Working (${calcPercentage(data[1])}%)`,
+ `Warning (${calcPercentage(data[2])}%)`,
+ `Unknown (${calcPercentage(data[3])}%)`
+ ],
+ options: {},
+ dataset: [{ data: data }]
+ });
+
+ it('gets no data', () => {
+ const chart = { dataset: [{}], options: {} };
+ component.preparePgStatus(chart, {
+ pg_info: {}
+ });
+ expect(chart).toEqual(expectedChart([undefined, undefined, undefined, undefined]));
+ });
+
+ it('gets data from all categories', () => {
+ const chart = { dataset: [{}], options: {} };
+ component.preparePgStatus(chart, {
+ pg_info: {
+ statuses: {
+ 'clean+active+scrubbing+nonMappedState': 4,
+ 'clean+active+scrubbing': 2,
+ 'clean+active': 1,
+ 'clean+active+scrubbing+down': 3
+ }
+ }
+ });
+ expect(chart).toEqual(expectedChart([1, 2, 3, 4]));
+ });
+ });
+
+ describe('isClientReadWriteChartShowable', () => {
+ beforeEach(() => {
+ component.healthData = healthPayload;
+ });
+
+ it('returns false', () => {
+ component.healthData['client_perf'] = {};
+
+ expect(component.isClientReadWriteChartShowable()).toBeFalsy();
+ });
+
+ it('returns false', () => {
+ component.healthData['client_perf'] = { read_op_per_sec: undefined, write_op_per_sec: 0 };
+
+ expect(component.isClientReadWriteChartShowable()).toBeFalsy();
+ });
+
+ it('returns true', () => {
+ component.healthData['client_perf'] = { read_op_per_sec: 1, write_op_per_sec: undefined };
+
+ expect(component.isClientReadWriteChartShowable()).toBeTruthy();
+ });
+
+ it('returns true', () => {
+ component.healthData['client_perf'] = { read_op_per_sec: 2, write_op_per_sec: 3 };
+
+ expect(component.isClientReadWriteChartShowable()).toBeTruthy();
+ });
+ });
+
+ describe('calcPercentage', () => {
+ it('returns correct value', () => {
+ expect(component['calcPercentage'](1, undefined)).toEqual(0);
+ expect(component['calcPercentage'](1, null)).toEqual(0);
+ expect(component['calcPercentage'](1, 0)).toEqual(0);
+ expect(component['calcPercentage'](undefined, 1)).toEqual(0);
+ expect(component['calcPercentage'](null, 1)).toEqual(0);
+ expect(component['calcPercentage'](0, 1)).toEqual(0);
+ expect(component['calcPercentage'](2.346, 10)).toEqual(23);
+ expect(component['calcPercentage'](2.35, 10)).toEqual(24);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.ts
new file mode 100644
index 00000000..3bc78c70
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.ts
@@ -0,0 +1,225 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { Subscription } from 'rxjs/Subscription';
+
+import { HealthService } from '../../../shared/api/health.service';
+import { Permissions } from '../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import {
+ FeatureTogglesMap$,
+ FeatureTogglesService
+} from '../../../shared/services/feature-toggles.service';
+import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service';
+import { PgCategoryService } from '../../shared/pg-category.service';
+import { HealthPieColor } from '../health-pie/health-pie-color.enum';
+
+@Component({
+ selector: 'cd-health',
+ templateUrl: './health.component.html',
+ styleUrls: ['./health.component.scss']
+})
+export class HealthComponent implements OnInit, OnDestroy {
+ healthData: any;
+ interval = new Subscription();
+ permissions: Permissions;
+ enabledFeature$: FeatureTogglesMap$;
+
+ rawCapacityChartConfig = {
+ options: {
+ title: { display: true, position: 'bottom' }
+ }
+ };
+ objectsChartConfig = {
+ options: {
+ title: { display: true, position: 'bottom' }
+ },
+ colors: [
+ {
+ backgroundColor: [
+ HealthPieColor.DEFAULT_GREEN,
+ HealthPieColor.DEFAULT_MAGENTA,
+ HealthPieColor.DEFAULT_ORANGE,
+ HealthPieColor.DEFAULT_RED
+ ]
+ }
+ ]
+ };
+ pgStatusChartConfig = {
+ colors: [
+ {
+ backgroundColor: [
+ HealthPieColor.DEFAULT_GREEN,
+ HealthPieColor.DEFAULT_BLUE,
+ HealthPieColor.DEFAULT_ORANGE,
+ HealthPieColor.DEFAULT_RED
+ ]
+ }
+ ]
+ };
+
+ constructor(
+ private healthService: HealthService,
+ private i18n: I18n,
+ private authStorageService: AuthStorageService,
+ private pgCategoryService: PgCategoryService,
+ private featureToggles: FeatureTogglesService,
+ private refreshIntervalService: RefreshIntervalService,
+ private dimlessBinary: DimlessBinaryPipe,
+ private dimless: DimlessPipe
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ this.enabledFeature$ = this.featureToggles.get();
+ }
+
+ ngOnInit() {
+ this.getHealth();
+ this.interval = this.refreshIntervalService.intervalData$.subscribe(() => {
+ this.getHealth();
+ });
+ }
+
+ ngOnDestroy() {
+ this.interval.unsubscribe();
+ }
+
+ getHealth() {
+ this.healthService.getMinimalHealth().subscribe((data: any) => {
+ this.healthData = data;
+ });
+ }
+
+ prepareReadWriteRatio(chart) {
+ const ratioLabels = [];
+ const ratioData = [];
+
+ const total =
+ this.healthData.client_perf.write_op_per_sec + this.healthData.client_perf.read_op_per_sec;
+
+ ratioLabels.push(
+ `${this.i18n('Writes')} (${this.calcPercentage(
+ this.healthData.client_perf.write_op_per_sec,
+ total
+ )}%)`
+ );
+ ratioData.push(this.healthData.client_perf.write_op_per_sec);
+ ratioLabels.push(
+ `${this.i18n('Reads')} (${this.calcPercentage(
+ this.healthData.client_perf.read_op_per_sec,
+ total
+ )}%)`
+ );
+ ratioData.push(this.healthData.client_perf.read_op_per_sec);
+
+ chart.dataset[0].data = ratioData;
+ chart.labels = ratioLabels;
+ }
+
+ prepareRawUsage(chart, data) {
+ const percentAvailable = this.calcPercentage(
+ data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes,
+ data.df.stats.total_bytes
+ );
+ const percentUsed = this.calcPercentage(
+ data.df.stats.total_used_raw_bytes,
+ data.df.stats.total_bytes
+ );
+
+ chart.dataset[0].data = [data.df.stats.total_used_raw_bytes, data.df.stats.total_avail_bytes];
+
+ chart.labels = [
+ `${this.dimlessBinary.transform(data.df.stats.total_used_raw_bytes)} ${this.i18n(
+ 'Used'
+ )} (${percentUsed}%)`,
+ `${this.dimlessBinary.transform(
+ data.df.stats.total_bytes - data.df.stats.total_used_raw_bytes
+ )} ${this.i18n('Avail.')} (${percentAvailable}%)`
+ ];
+
+ chart.options.title.text = `${this.dimlessBinary.transform(
+ data.df.stats.total_bytes
+ )} ${this.i18n('total')}`;
+ }
+
+ preparePgStatus(chart, data) {
+ const categoryPgAmount = {};
+ let totalPgs = 0;
+
+ _.forEach(data.pg_info.statuses, (pgAmount, pgStatesText) => {
+ const categoryType = this.pgCategoryService.getTypeByStates(pgStatesText);
+
+ if (_.isUndefined(categoryPgAmount[categoryType])) {
+ categoryPgAmount[categoryType] = 0;
+ }
+ categoryPgAmount[categoryType] += pgAmount;
+ totalPgs += pgAmount;
+ });
+
+ chart.dataset[0].data = this.pgCategoryService
+ .getAllTypes()
+ .map((categoryType) => categoryPgAmount[categoryType]);
+
+ chart.labels = [
+ `${this.i18n('Clean')} (${this.calcPercentage(categoryPgAmount['clean'], totalPgs)}%)`,
+ `${this.i18n('Working')} (${this.calcPercentage(categoryPgAmount['working'], totalPgs)}%)`,
+ `${this.i18n('Warning')} (${this.calcPercentage(categoryPgAmount['warning'], totalPgs)}%)`,
+ `${this.i18n('Unknown')} (${this.calcPercentage(categoryPgAmount['unknown'], totalPgs)}%)`
+ ];
+ }
+
+ prepareObjects(chart, data) {
+ const totalReplicas = data.pg_info.object_stats.num_object_copies;
+ const healthy =
+ totalReplicas -
+ data.pg_info.object_stats.num_objects_misplaced -
+ data.pg_info.object_stats.num_objects_degraded -
+ data.pg_info.object_stats.num_objects_unfound;
+
+ chart.labels = [
+ `${this.i18n('Healthy')} (${this.calcPercentage(healthy, totalReplicas)}%)`,
+ `${this.i18n('Misplaced')} (${this.calcPercentage(
+ data.pg_info.object_stats.num_objects_misplaced,
+ totalReplicas
+ )}%)`,
+ `${this.i18n('Degraded')} (${this.calcPercentage(
+ data.pg_info.object_stats.num_objects_degraded,
+ totalReplicas
+ )}%)`,
+ `${this.i18n('Unfound')} (${this.calcPercentage(
+ data.pg_info.object_stats.num_objects_unfound,
+ totalReplicas
+ )}%)`
+ ];
+
+ chart.dataset[0].data = [
+ healthy,
+ data.pg_info.object_stats.num_objects_misplaced,
+ data.pg_info.object_stats.num_objects_degraded,
+ data.pg_info.object_stats.num_objects_unfound
+ ];
+
+ chart.options.title.text = `${this.dimless.transform(
+ data.pg_info.object_stats.num_objects
+ )} ${this.i18n('total')} (${this.dimless.transform(totalReplicas)} ${this.i18n('replicas')})`;
+
+ chart.options.maintainAspectRatio = window.innerWidth >= 375;
+ }
+
+ isClientReadWriteChartShowable() {
+ const readOps = this.healthData.client_perf.read_op_per_sec || 0;
+ const writeOps = this.healthData.client_perf.write_op_per_sec || 0;
+
+ return readOps + writeOps > 0;
+ }
+
+ private calcPercentage(dividend: number, divisor: number) {
+ if (!_.isNumber(dividend) || !_.isNumber(divisor) || divisor === 0) {
+ return 0;
+ }
+
+ return Math.round((dividend / divisor) * 100);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card-popover.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card-popover.scss
new file mode 100644
index 00000000..1ec12366
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card-popover.scss
@@ -0,0 +1,42 @@
+@import '../../../../defaults';
+
+.info-card-popover-cluster-status {
+ max-width: 23vw;
+ max-height: 20vh;
+
+ .popover-body {
+ max-width: 100%;
+ max-height: 19vh;
+ font-size: 12px;
+ }
+}
+
+@media (max-width: $screen-md-max) {
+ .info-card-popover-cluster-status {
+ max-width: 31vw;
+ }
+}
+
+@media (max-width: $screen-sm-max) {
+ .info-card-popover-cluster-status {
+ max-width: 46vw;
+ }
+}
+@media (max-width: $screen-xs-max) {
+ .info-card-popover-cluster-status {
+ max-width: 83vw;
+ }
+}
+
+.info-card-content-clickable {
+ cursor: pointer;
+ padding: 7px;
+ border: 1px solid;
+ border-radius: 3px;
+ border-color: $color-shade-gray;
+}
+
+.info-card-content-clickable:hover {
+ border-color: $color-light-gray;
+ background-color: $color-light-shade-gray;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.html
new file mode 100644
index 00000000..ae672510
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.html
@@ -0,0 +1,14 @@
+<div class="card"
+ [ngClass]="cardClass">
+ <div class="card-title">
+ <a *ngIf="link; else noLinkTitle"
+ [routerLink]="link">{{ cardTitle }}</a>
+ <ng-template #noLinkTitle>
+ {{ cardTitle }}
+ </ng-template>
+ </div>
+ <div class="card-body"
+ [ngClass]="contentClass">
+ <ng-content></ng-content>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.scss
new file mode 100644
index 00000000..dd0ce775
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.scss
@@ -0,0 +1,135 @@
+@import '../../../../defaults';
+
+$card-height: 6vw;
+$card-medium-height: 12vw;
+$card-font-min-width: 320px;
+$card-font-max-width: 2048px;
+$card-font-min-size: 12px;
+$card-font-max-size: 21px;
+$logs-text-font-size: $card-font-min-size;
+
+.card {
+ border: 0.5px solid $color-info-card-border;
+ border-radius: 3px;
+ background-color: $color-solid-white;
+ box-shadow: 0 1px 1px $color-shadow-gray;
+ margin: 0 -10px 20px;
+ padding: 0 20px;
+ width: auto;
+ height: auto;
+ margin-left: auto;
+ margin-right: auto;
+ min-height: $card-height;
+ @include fluid-font-size(
+ $card-font-min-width,
+ $card-font-max-width,
+ $card-font-min-size,
+ $card-font-max-size
+ );
+ position: relative;
+}
+
+.card-title {
+ margin: 1.1vw 0;
+ padding: 0;
+}
+
+.card-body {
+ text-align: center;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%);
+}
+
+.content-chart {
+ margin-top: -0.7vw;
+ position: unset;
+ top: unset;
+ left: unset;
+ transform: unset;
+}
+
+.no-center {
+ position: unset;
+ top: unset;
+ left: unset;
+ transform: unset;
+}
+
+.text-area-size-2 {
+ margin-right: -50%;
+ transform: translate(-50%, -20%);
+}
+
+.text-area-size-3 {
+ margin-right: -50%;
+ transform: translate(-50%, -40%);
+}
+
+.content-highlight {
+ font-weight: bold;
+}
+
+.card-medium {
+ min-height: $card-medium-height;
+}
+
+.scroll {
+ max-height: ($card-medium-height * 1.5);
+ overflow-y: auto;
+}
+
+.text-monospace {
+ font-size: $logs-text-font-size;
+ font-family: monospace;
+ text-align: left;
+}
+
+@media (max-width: 1599px) {
+ .card {
+ min-height: $card-height * 1.3;
+ }
+
+ .card-medium {
+ min-height: $card-medium-height * 1.2;
+ }
+}
+
+@media (max-width: $screen-md-max) {
+ .card-medium {
+ min-height: $card-medium-height * 1.5;
+ }
+
+ .content-chart {
+ margin-top: -0.6vw;
+ }
+}
+
+@media (max-width: $screen-sm-max) {
+ .card {
+ min-height: $card-height * 2;
+ }
+
+ .content-chart {
+ margin-top: -0.3vw;
+ }
+}
+
+@media (max-width: $screen-sm-max) and (min-width: $screen-sm-min) {
+ .card-medium {
+ min-height: $card-medium-height * 2.2;
+ }
+}
+
+@media (max-width: 599px) {
+ .card {
+ min-height: $card-height * 3;
+ }
+}
+
+@media (max-width: 319px) {
+ .card {
+ min-height: $card-height * 4;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.spec.ts
new file mode 100644
index 00000000..b7082b3a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.spec.ts
@@ -0,0 +1,65 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { InfoCardComponent } from './info-card.component';
+
+describe('InfoCardComponent', () => {
+ let component: InfoCardComponent;
+ let fixture: ComponentFixture<InfoCardComponent>;
+
+ configureTestBed({
+ imports: [RouterTestingModule],
+ declarations: [InfoCardComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(InfoCardComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('Setting cardTitle makes title visible', () => {
+ const cardTitle = 'Card Title';
+ component.cardTitle = cardTitle;
+ fixture.detectChanges();
+ const titleDiv = fixture.debugElement.nativeElement.querySelector('.card-title');
+
+ expect(titleDiv.textContent).toContain(cardTitle);
+ });
+
+ it('Setting link makes anchor visible', () => {
+ const cardTitle = 'Card Title';
+ const link = '/dashboard';
+ component.cardTitle = cardTitle;
+ component.link = link;
+ fixture.detectChanges();
+ const anchor = fixture.debugElement.nativeElement
+ .querySelector('.card-title')
+ .querySelector('a');
+
+ expect(anchor.textContent).toContain(cardTitle);
+ expect(anchor.href).toBe(`http://localhost${link}`);
+ });
+
+ it('Setting cardClass makes class set', () => {
+ const cardClass = 'my-css-card-class';
+ component.cardClass = cardClass;
+ fixture.detectChanges();
+ const card = fixture.debugElement.nativeElement.querySelector(`.card.${cardClass}`);
+
+ expect(card).toBeTruthy();
+ });
+
+ it('Setting contentClass makes class set', () => {
+ const contentClass = 'my-css-content-class';
+ component.contentClass = contentClass;
+ fixture.detectChanges();
+ const card = fixture.debugElement.nativeElement.querySelector(`.card-body.${contentClass}`);
+
+ expect(card).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.ts
new file mode 100644
index 00000000..fdcbe2ec
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-card/info-card.component.ts
@@ -0,0 +1,17 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'cd-info-card',
+ templateUrl: './info-card.component.html',
+ styleUrls: ['./info-card.component.scss']
+})
+export class InfoCardComponent {
+ @Input()
+ cardTitle: string;
+ @Input()
+ link: string;
+ @Input()
+ cardClass = '';
+ @Input()
+ contentClass: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.html
new file mode 100644
index 00000000..48e516ba
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.html
@@ -0,0 +1,4 @@
+<div class="info-group-title">
+ {{ groupTitle }}
+</div>
+<ng-content></ng-content>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.scss
new file mode 100644
index 00000000..3f2efa99
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.scss
@@ -0,0 +1,7 @@
+@import '../../../../defaults';
+
+.info-group-title {
+ margin: 0 0 0.5vw 0.5vw;
+ padding: 0;
+ font-size: 21px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.spec.ts
new file mode 100644
index 00000000..c0f476b7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.spec.ts
@@ -0,0 +1,31 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { InfoGroupComponent } from './info-group.component';
+
+describe('InfoGroupComponent', () => {
+ let component: InfoGroupComponent;
+ let fixture: ComponentFixture<InfoGroupComponent>;
+
+ configureTestBed({
+ declarations: [InfoGroupComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(InfoGroupComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('Setting groupTitle makes title visible', () => {
+ const groupTitle = 'Group Title';
+ component.groupTitle = groupTitle;
+ fixture.detectChanges();
+ const titleDiv = fixture.debugElement.nativeElement.querySelector('.info-group-title');
+
+ expect(titleDiv.textContent).toContain(groupTitle);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.ts
new file mode 100644
index 00000000..662d585b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/info-group/info-group.component.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'cd-info-group',
+ templateUrl: './info-group.component.html',
+ styleUrls: ['./info-group.component.scss']
+})
+export class InfoGroupComponent {
+ @Input()
+ groupTitle: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts
new file mode 100644
index 00000000..f93d484a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts
@@ -0,0 +1,72 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { MdsSummaryPipe } from './mds-summary.pipe';
+
+describe('MdsSummaryPipe', () => {
+ let pipe: MdsSummaryPipe;
+
+ configureTestBed({
+ providers: [MdsSummaryPipe, i18nProviders]
+ });
+
+ beforeEach(() => {
+ pipe = TestBed.get(MdsSummaryPipe);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms with 0 active and 2 standy', () => {
+ const payload = {
+ standbys: [{ name: 'a' }],
+ filesystems: [{ mdsmap: { info: [{ state: 'up:standby-replay' }] } }]
+ };
+ const expected = [
+ { class: 'popover-info', content: '0 active', titleText: '1 standbyReplay' },
+ { class: 'card-text-line-break', content: '', titleText: '' },
+ { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: a' }
+ ];
+
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+
+ it('transforms with 1 active and 1 standy', () => {
+ const payload = {
+ standbys: [{ name: 'b' }],
+ filesystems: [{ mdsmap: { info: [{ state: 'up:active', name: 'a' }] } }]
+ };
+ const expected = [
+ { class: 'popover-info', content: '1 active', titleText: 'active daemon: a' },
+ { class: 'card-text-line-break', content: '', titleText: '' },
+ { class: 'popover-info', content: '1 standby', titleText: 'standby daemons: b' }
+ ];
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+
+ it('transforms with 0 filesystems', () => {
+ const payload = {
+ standbys: [0],
+ filesystems: []
+ };
+ const expected = [{ class: 'popover-info', content: 'no filesystems', titleText: '' }];
+
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+
+ it('transforms without filesystem', () => {
+ const payload = { standbys: [{ name: 'a' }] };
+ const expected = [
+ { class: 'popover-info', content: '1 up', titleText: '' },
+ { class: 'card-text-line-break', content: '', titleText: '' },
+ { class: 'popover-info', content: 'no filesystems', titleText: 'standby daemons: a' }
+ ];
+
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+
+ it('transforms without value', () => {
+ expect(pipe.transform(undefined)).toBe('');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts
new file mode 100644
index 00000000..7bd1014d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts
@@ -0,0 +1,83 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'mdsSummary'
+})
+export class MdsSummaryPipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+
+ transform(value: any): any {
+ if (!value) {
+ return '';
+ }
+
+ let contentLine1 = '';
+ let contentLine2 = '';
+ let standbys = 0;
+ let active = 0;
+ let standbyReplay = 0;
+ _.each(value.standbys, () => {
+ standbys += 1;
+ });
+
+ if (value.standbys && !value.filesystems) {
+ contentLine1 = `${standbys} ${this.i18n('up')}`;
+ contentLine2 = this.i18n('no filesystems');
+ } else if (value.filesystems.length === 0) {
+ contentLine1 = this.i18n('no filesystems');
+ } else {
+ _.each(value.filesystems, (fs) => {
+ _.each(fs.mdsmap.info, (mds) => {
+ if (mds.state === 'up:standby-replay') {
+ standbyReplay += 1;
+ } else {
+ active += 1;
+ }
+ });
+ });
+
+ contentLine1 = `${active} ${this.i18n('active')}`;
+ contentLine2 = `${standbys + standbyReplay} ${this.i18n('standby')}`;
+ }
+ const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', ');
+ const standbyTitleText = !standbyHoverText
+ ? ''
+ : `${this.i18n('standby daemons')}: ${standbyHoverText}`;
+ const fsLength = value.filesystems ? value.filesystems.length : 0;
+ const infoObject = fsLength > 0 ? value.filesystems[0].mdsmap.info : {};
+ const activeHoverText = Object.values(infoObject)
+ .map((info: any): string => info.name)
+ .join(', ');
+ let activeTitleText = !activeHoverText
+ ? ''
+ : `${this.i18n('active daemon')}: ${activeHoverText}`;
+ // There is always one standbyreplay to replace active daemon, if active one is down
+ if (!active && fsLength > 0) {
+ activeTitleText = `${standbyReplay} ${this.i18n('standbyReplay')}`;
+ }
+ const mgrSummary = [
+ {
+ content: contentLine1,
+ class: 'popover-info',
+ titleText: activeTitleText
+ }
+ ];
+ if (contentLine2) {
+ mgrSummary.push({
+ content: '',
+ class: 'card-text-line-break',
+ titleText: ''
+ });
+ mgrSummary.push({
+ content: contentLine2,
+ class: 'popover-info',
+ titleText: standbyTitleText
+ });
+ }
+
+ return mgrSummary;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts
new file mode 100644
index 00000000..73f6d9b3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts
@@ -0,0 +1,53 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+
+import { MgrSummaryPipe } from './mgr-summary.pipe';
+
+describe('MgrSummaryPipe', () => {
+ let pipe: MgrSummaryPipe;
+
+ configureTestBed({
+ providers: [MgrSummaryPipe, i18nProviders]
+ });
+
+ beforeEach(() => {
+ pipe = TestBed.get(MgrSummaryPipe);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms without value', () => {
+ expect(pipe.transform(undefined)).toBe('');
+ });
+
+ it('transforms with active_name undefined', () => {
+ const payload = {
+ active_name: undefined,
+ standbys: []
+ };
+ const expected = [
+ { class: 'popover-info', content: 'n/a active', titleText: '' },
+ { class: 'card-text-line-break', content: '', titleText: '' },
+ { class: 'popover-info', content: '0 standby', titleText: '' }
+ ];
+
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+
+ it('transforms with 1 active and 2 standbys', () => {
+ const payload = {
+ active_name: 'x',
+ standbys: [{ name: 'y' }, { name: 'z' }]
+ };
+ const expected = [
+ { class: 'popover-info', content: '1 active', titleText: 'active daemon: x' },
+ { class: 'card-text-line-break', content: '', titleText: '' },
+ { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: y, z' }
+ ];
+
+ expect(pipe.transform(payload)).toEqual(expected);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts
new file mode 100644
index 00000000..c99cd864
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts
@@ -0,0 +1,51 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'mgrSummary'
+})
+export class MgrSummaryPipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+
+ transform(value: any): any {
+ if (!value) {
+ return '';
+ }
+
+ let activeCount = this.i18n('n/a');
+ const activeTitleText = _.isUndefined(value.active_name)
+ ? ''
+ : `${this.i18n('active daemon')}: ${value.active_name}`;
+ // There is always one standbyreplay to replace active daemon, if active one is down
+ if (activeTitleText.length > 0) {
+ activeCount = '1';
+ }
+ const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', ');
+ const standbyTitleText = !standbyHoverText
+ ? ''
+ : `${this.i18n('standby daemons')}: ${standbyHoverText}`;
+ const standbyCount = value.standbys.length;
+ const mgrSummary = [
+ {
+ content: `${activeCount} ${this.i18n('active')}`,
+ class: 'popover-info',
+ titleText: activeTitleText
+ }
+ ];
+
+ mgrSummary.push({
+ content: '',
+ class: 'card-text-line-break',
+ titleText: ''
+ });
+ mgrSummary.push({
+ content: `${standbyCount} ${this.i18n('standby')}`,
+ class: 'popover-info',
+ titleText: standbyTitleText
+ });
+
+ return mgrSummary;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.spec.ts
new file mode 100644
index 00000000..9d193a5e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.spec.ts
@@ -0,0 +1,40 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { MonSummaryPipe } from './mon-summary.pipe';
+
+describe('MonSummaryPipe', () => {
+ let pipe: MonSummaryPipe;
+
+ configureTestBed({
+ providers: [MonSummaryPipe, i18nProviders]
+ });
+
+ beforeEach(() => {
+ pipe = TestBed.get(MonSummaryPipe);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms without value', () => {
+ expect(pipe.transform(undefined)).toBe('');
+ });
+
+ it('transforms with 3 mons in quorum', () => {
+ const value = {
+ monmap: { mons: [0, 1, 2] },
+ quorum: [0, 1, 2]
+ };
+ expect(pipe.transform(value)).toBe('3 (quorum 0, 1, 2)');
+ });
+
+ it('transforms with 2/3 mons in quorum', () => {
+ const value = {
+ monmap: { mons: [0, 1, 2] },
+ quorum: [0, 1]
+ };
+ expect(pipe.transform(value)).toBe('3 (quorum 0, 1)');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.ts
new file mode 100644
index 00000000..31339f52
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mon-summary.pipe.ts
@@ -0,0 +1,22 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+@Pipe({
+ name: 'monSummary'
+})
+export class MonSummaryPipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+
+ transform(value: any): any {
+ if (!value) {
+ return '';
+ }
+
+ const result = `${value.monmap.mons.length.toString()} (${this.i18n(
+ 'quorum'
+ )} ${value.quorum.join(', ')})`;
+
+ return result;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts
new file mode 100644
index 00000000..6332017d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts
@@ -0,0 +1,127 @@
+import { TestBed } from '@angular/core/testing';
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { OsdSummaryPipe } from './osd-summary.pipe';
+
+describe('OsdSummaryPipe', () => {
+ let pipe: OsdSummaryPipe;
+
+ configureTestBed({
+ providers: [OsdSummaryPipe, i18nProviders]
+ });
+
+ beforeEach(() => {
+ pipe = TestBed.get(OsdSummaryPipe);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms without value', () => {
+ expect(pipe.transform(undefined)).toBe('');
+ });
+
+ it('transforms having 3 osd with 3 up, 3 in, 0 down, 0 out', () => {
+ const value = {
+ osds: [{ up: 1, in: 1 }, { up: 1, in: 1 }, { up: 1, in: 1 }]
+ };
+ expect(pipe.transform(value)).toEqual([
+ {
+ content: '3 total',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '3 up, 3 in',
+ class: ''
+ }
+ ]);
+ });
+
+ it('transforms having 3 osd with 2 up, 1 in, 1 down, 1 out', () => {
+ const value = {
+ osds: [{ up: 1, in: 1 }, { up: 1, in: 0 }, { up: 0, in: 0 }]
+ };
+ expect(pipe.transform(value)).toEqual([
+ {
+ content: '3 total',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '2 up, 1 in',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '1 down, 1 out',
+ class: 'card-text-error'
+ }
+ ]);
+ });
+
+ it('transforms having 3 osd with 2 up, 2 in, 1 down, 0 out', () => {
+ const value = {
+ osds: [{ up: 1, in: 1 }, { up: 1, in: 1 }, { up: 0, in: 0 }]
+ };
+ expect(pipe.transform(value)).toEqual([
+ {
+ content: '3 total',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '2 up, 2 in',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '1 down',
+ class: 'card-text-error'
+ }
+ ]);
+ });
+
+ it('transforms having 3 osd with 3 up, 2 in, 0 down, 1 out', () => {
+ const value = {
+ osds: [{ up: 1, in: 1 }, { up: 1, in: 1 }, { up: 1, in: 0 }]
+ };
+ expect(pipe.transform(value)).toEqual([
+ {
+ content: '3 total',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '3 up, 2 in',
+ class: ''
+ },
+ {
+ content: '',
+ class: 'card-text-line-break'
+ },
+ {
+ content: '1 out',
+ class: 'card-text-error'
+ }
+ ]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts
new file mode 100644
index 00000000..c007c313
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts
@@ -0,0 +1,62 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'osdSummary'
+})
+export class OsdSummaryPipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+
+ transform(value: any): any {
+ if (!value) {
+ return '';
+ }
+
+ let inCount = 0;
+ let upCount = 0;
+ _.each(value.osds, (osd) => {
+ if (osd.in) {
+ inCount++;
+ }
+ if (osd.up) {
+ upCount++;
+ }
+ });
+
+ const osdSummary = [
+ {
+ content: `${value.osds.length} ${this.i18n('total')}`,
+ class: ''
+ }
+ ];
+ osdSummary.push({
+ content: '',
+ class: 'card-text-line-break'
+ });
+ osdSummary.push({
+ content: `${upCount} ${this.i18n('up')}, ${inCount} ${this.i18n('in')}`,
+ class: ''
+ });
+
+ const downCount = value.osds.length - upCount;
+ const outCount = upCount - inCount;
+ if (downCount > 0 || outCount > 0) {
+ osdSummary.push({
+ content: '',
+ class: 'card-text-line-break'
+ });
+
+ const downText = downCount > 0 ? `${downCount} ${this.i18n('down')}` : '';
+ const separator = downCount > 0 && outCount > 0 ? ', ' : '';
+ const outText = outCount > 0 ? `${outCount} ${this.i18n('out')}` : '';
+ osdSummary.push({
+ content: `${downText}${separator}${outText}`,
+ class: 'card-text-error'
+ });
+ }
+
+ return osdSummary;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.html
new file mode 100644
index 00000000..e3db036f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.html
@@ -0,0 +1,5 @@
+<cd-info-panel>
+ {{ message }}<br>
+ <ng-container i18n>Please consult the <a href="{{docsUrl}}" target="_blank">documentation</a>
+ on how to configure and enable the NFS Ganesha management functionality.</ng-container>
+</cd-info-panel>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.spec.ts
new file mode 100644
index 00000000..bde06ba8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.spec.ts
@@ -0,0 +1,28 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { Nfs501Component } from './nfs-501.component';
+
+describe('Nfs501Component', () => {
+ let component: Nfs501Component;
+ let fixture: ComponentFixture<Nfs501Component>;
+
+ configureTestBed({
+ declarations: [Nfs501Component],
+ imports: [HttpClientTestingModule, RouterTestingModule, SharedModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(Nfs501Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.ts
new file mode 100644
index 00000000..77b3b649
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-501/nfs-501.component.ts
@@ -0,0 +1,50 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../../shared/services/summary.service';
+
+@Component({
+ selector: 'cd-nfs-501',
+ templateUrl: './nfs-501.component.html',
+ styleUrls: ['./nfs-501.component.scss']
+})
+export class Nfs501Component implements OnInit, OnDestroy {
+ docsUrl: string;
+ message = this.i18n('The NFS Ganesha service is not configured.');
+ routeParamsSubscribe: any;
+
+ constructor(
+ private route: ActivatedRoute,
+ private summaryService: SummaryService,
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl =
+ `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/` +
+ `#configuring-nfs-ganesha-in-the-dashboard`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+
+ this.routeParamsSubscribe = this.route.params.subscribe((params: { message: string }) => {
+ this.message = params.message;
+ });
+ }
+
+ ngOnDestroy() {
+ this.routeParamsSubscribe.unsubscribe();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.html
new file mode 100644
index 00000000..b8f10391
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.html
@@ -0,0 +1,19 @@
+<tabset *ngIf="selection?.hasSingleSelection">
+ <tab heading="Details"
+ i18n-heading>
+ <cd-table-key-value [data]="data">
+ </cd-table-key-value>
+ </tab>
+
+ <tab heading="Clients ({{ clients.length }})"
+ i18n-heading>
+ <cd-table #table
+ [data]="clients"
+ columnMode="flex"
+ [columns]="clientsColumns"
+ identifier="addresses"
+ forceIdentifier="true"
+ selectionType="">
+ </cd-table>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.spec.ts
new file mode 100644
index 00000000..2e2cb52c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.spec.ts
@@ -0,0 +1,114 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+
+import * as _ from 'lodash';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { NfsDetailsComponent } from './nfs-details.component';
+
+describe('NfsDetailsComponent', () => {
+ let component: NfsDetailsComponent;
+ let fixture: ComponentFixture<NfsDetailsComponent>;
+
+ const elem = (css) => fixture.debugElement.query(By.css(css));
+
+ configureTestBed({
+ declarations: [NfsDetailsComponent],
+ imports: [SharedModule, TabsModule.forRoot(), HttpClientTestingModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NfsDetailsComponent);
+ component = fixture.componentInstance;
+
+ component.selection = new CdTableSelection();
+ component.selection.selected = [
+ {
+ export_id: 1,
+ path: '/qwe',
+ fsal: { name: 'CEPH', user_id: 'fs', fs_name: 1 },
+ cluster_id: 'cluster1',
+ daemons: ['node1', 'node2'],
+ pseudo: '/qwe',
+ tag: 'asd',
+ access_type: 'RW',
+ squash: 'no_root_squash',
+ protocols: [3, 4],
+ transports: ['TCP', 'UDP'],
+ clients: [
+ {
+ addresses: ['192.168.0.10', '192.168.1.0/8'],
+ access_type: 'RW',
+ squash: 'root_id_squash'
+ }
+ ],
+ id: 'cluster1:1',
+ state: 'LOADING'
+ }
+ ];
+ component.selection.update();
+ component.ngOnChanges();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component.data).toBeTruthy();
+ });
+
+ it('should prepare data', () => {
+ expect(component.data).toEqual({
+ 'Access Type': 'RW',
+ 'CephFS Filesystem': 1,
+ 'CephFS User': 'fs',
+ Cluster: 'cluster1',
+ Daemons: ['node1', 'node2'],
+ 'NFS Protocol': ['NFSv3', 'NFSv4'],
+ Path: '/qwe',
+ Pseudo: '/qwe',
+ 'Security Label': undefined,
+ Squash: 'no_root_squash',
+ 'Storage Backend': 'CephFS',
+ Transport: ['TCP', 'UDP']
+ });
+ });
+
+ it('should prepare data if RGW', () => {
+ const newData = _.assignIn(component.selection.first(), {
+ fsal: {
+ name: 'RGW',
+ rgw_user_id: 'rgw_user_id'
+ }
+ });
+ component.selection.selected = [newData];
+ component.selection.update();
+ component.ngOnChanges();
+ expect(component.data).toEqual({
+ 'Access Type': 'RW',
+ Cluster: 'cluster1',
+ Daemons: ['node1', 'node2'],
+ 'NFS Protocol': ['NFSv3', 'NFSv4'],
+ 'Object Gateway User': 'rgw_user_id',
+ Path: '/qwe',
+ Pseudo: '/qwe',
+ Squash: 'no_root_squash',
+ 'Storage Backend': 'Object Gateway',
+ Transport: ['TCP', 'UDP']
+ });
+ });
+
+ it('should have 1 client', () => {
+ expect(elem('li.nav-item:nth-of-type(2) span').nativeElement.textContent).toBe('Clients (1)');
+ expect(component.clients).toEqual([
+ {
+ access_type: 'RW',
+ addresses: ['192.168.0.10', '192.168.1.0/8'],
+ squash: 'root_id_squash'
+ }
+ ]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.ts
new file mode 100644
index 00000000..0219585c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-details/nfs-details.component.ts
@@ -0,0 +1,73 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-nfs-details',
+ templateUrl: './nfs-details.component.html',
+ styleUrls: ['./nfs-details.component.scss']
+})
+export class NfsDetailsComponent implements OnChanges {
+ @Input()
+ selection: CdTableSelection;
+
+ selectedItem: any;
+ data: any;
+
+ clientsColumns: CdTableColumn[];
+ clients = [];
+
+ constructor(private i18n: I18n) {
+ this.clientsColumns = [
+ {
+ name: this.i18n('Addresses'),
+ prop: 'addresses',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Access Type'),
+ prop: 'access_type',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Squash'),
+ prop: 'squash',
+ flexGrow: 1
+ }
+ ];
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+
+ this.clients = this.selectedItem.clients;
+
+ this.data = {};
+ this.data[this.i18n('Cluster')] = this.selectedItem.cluster_id;
+ this.data[this.i18n('Daemons')] = this.selectedItem.daemons;
+ this.data[this.i18n('NFS Protocol')] = this.selectedItem.protocols.map(
+ (protocol) => 'NFSv' + protocol
+ );
+ this.data[this.i18n('Pseudo')] = this.selectedItem.pseudo;
+ this.data[this.i18n('Access Type')] = this.selectedItem.access_type;
+ this.data[this.i18n('Squash')] = this.selectedItem.squash;
+ this.data[this.i18n('Transport')] = this.selectedItem.transports;
+ this.data[this.i18n('Path')] = this.selectedItem.path;
+
+ if (this.selectedItem.fsal.name === 'CEPH') {
+ this.data[this.i18n('Storage Backend')] = this.i18n('CephFS');
+ this.data[this.i18n('CephFS User')] = this.selectedItem.fsal.user_id;
+ this.data[this.i18n('CephFS Filesystem')] = this.selectedItem.fsal.fs_name;
+ this.data[this.i18n('Security Label')] = this.selectedItem.fsal.sec_label_xattr;
+ } else {
+ this.data[this.i18n('Storage Backend')] = this.i18n('Object Gateway');
+ this.data[this.i18n('Object Gateway User')] = this.selectedItem.fsal.rgw_user_id;
+ }
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.html
new file mode 100644
index 00000000..b5a05c75
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.html
@@ -0,0 +1,104 @@
+<div class="form-group">
+ <label class="col-sm-3 control-label"
+ i18n>Clients</label>
+
+ <div class="col-sm-9"
+ [formGroup]="form"
+ #formDir="ngForm">
+ <span *ngIf="form.get('clients').value.length === 0"
+ class="form-control no-border text-muted">
+ <span class="text-muted"
+ i18n>Any client can access</span>
+ </span>
+
+ <ng-container formArrayName="clients">
+ <div *ngFor="let item of form.get('clients').value; let index = index; trackBy: trackByFn">
+ <div class="panel panel-default"
+ [formGroupName]="index">
+ <div class="panel-heading">
+ <h3 class="panel-title">{{ (index + 1) | ordinal }}
+ <span class="pull-right clickable"
+ (click)="removeClient(index)"
+ tooltip="Remove">&times;</span>
+ </h3>
+ </div>
+
+ <div class="panel-body">
+ <!-- Addresses -->
+ <div class="form-group"
+ [ngClass]="{ 'has-error': showError(index, 'addresses', formDir) }">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="addresses">Addresses</label>
+ <div class="col-sm-9">
+ <input type="text"
+ class="form-control"
+ name="addresses"
+ id="addresses"
+ formControlName="addresses"
+ placeholder="192.168.0.10, 192.168.1.0/8">
+ <span class="help-block">
+ <span *ngIf="showError(index, 'addresses', formDir, 'required')"
+ i18n>Required field</span>
+
+ <span *ngIf="showError(index, 'addresses', formDir, 'pattern')">
+ <ng-container i18n>Must contain one or more comma-separated values</ng-container>
+ <br>
+ <ng-container i18n>For example:</ng-container> 192.168.0.10, 192.168.1.0/8
+ </span>
+ </span>
+ </div>
+ </div>
+
+ <!-- Access Type-->
+ <div class="form-group">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="access_type">Access Type</label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ name="access_type"
+ id="access_type"
+ formControlName="access_type">
+ <option value="">{{ getNoAccessTypeDescr() }}</option>
+ <option *ngFor="let item of nfsAccessType"
+ [value]="item.value">{{ item.value }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="getValue(index, 'access_type')">
+ {{ getAccessTypeHelp(index) }}
+ </span>
+ </div>
+ </div>
+
+ <!-- Squash -->
+ <div class="form-group">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="squash">Squash</label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ name="squash"
+ id="squash"
+ formControlName="squash">
+ <option value="">{{ getNoSquashDescr() }}</option>
+ <option *ngFor="let squash of nfsSquash"
+ [value]="squash">{{ squash }}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-container>
+
+ <span class="form-control no-border">
+ <button class="btn btn-default btn-label pull-right"
+ (click)="addClient()">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add clients</ng-container>
+ </button>
+ </span>
+ <hr>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.spec.ts
new file mode 100644
index 00000000..3c8e0bb5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.spec.ts
@@ -0,0 +1,72 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { SharedModule } from '../../../shared/shared.module';
+import { NfsFormClientComponent } from './nfs-form-client.component';
+
+describe('NfsFormClientComponent', () => {
+ let component: NfsFormClientComponent;
+ let fixture: ComponentFixture<NfsFormClientComponent>;
+
+ configureTestBed({
+ declarations: [NfsFormClientComponent],
+ imports: [ReactiveFormsModule, SharedModule, HttpClientTestingModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NfsFormClientComponent);
+ const formBuilder = TestBed.get(CdFormBuilder);
+ component = fixture.componentInstance;
+
+ component.form = this.nfsForm = new CdFormGroup({
+ access_type: new FormControl(''),
+ clients: formBuilder.array([]),
+ squash: new FormControl('')
+ });
+
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should add a client', () => {
+ expect(component.form.getValue('clients')).toEqual([]);
+ component.addClient();
+ expect(component.form.getValue('clients')).toEqual([
+ { access_type: '', addresses: '', squash: '' }
+ ]);
+ });
+
+ it('should return form access_type', () => {
+ expect(component.getNoAccessTypeDescr()).toBe('-- Select the access type --');
+
+ component.form.patchValue({ access_type: 'RW' });
+ expect(component.getNoAccessTypeDescr()).toBe('RW (inherited from global config)');
+ });
+
+ it('should return form squash', () => {
+ expect(component.getNoSquashDescr()).toBe(
+ '-- Select what kind of user id squashing is performed --'
+ );
+
+ component.form.patchValue({ squash: 'root_id_squash' });
+ expect(component.getNoSquashDescr()).toBe('root_id_squash (inherited from global config)');
+ });
+
+ it('should remove client', () => {
+ component.addClient();
+ expect(component.form.getValue('clients')).toEqual([
+ { access_type: '', addresses: '', squash: '' }
+ ]);
+
+ component.removeClient(0);
+ expect(component.form.getValue('clients')).toEqual([]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.ts
new file mode 100644
index 00000000..a549deb0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form-client/nfs-form-client.component.ts
@@ -0,0 +1,88 @@
+import { Component, Input } from '@angular/core';
+import { FormArray, FormControl, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { NfsService } from '../../../shared/api/nfs.service';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+
+@Component({
+ selector: 'cd-nfs-form-client',
+ templateUrl: './nfs-form-client.component.html',
+ styleUrls: ['./nfs-form-client.component.scss']
+})
+export class NfsFormClientComponent {
+ @Input()
+ form: CdFormGroup;
+
+ nfsSquash: any[] = this.nfsService.nfsSquash;
+ nfsAccessType: any[] = this.nfsService.nfsAccessType;
+
+ constructor(private nfsService: NfsService, private i18n: I18n) {}
+
+ getNoAccessTypeDescr() {
+ if (this.form.getValue('access_type')) {
+ return `${this.form.getValue('access_type')} ${this.i18n('(inherited from global config)')}`;
+ }
+ return this.i18n('-- Select the access type --');
+ }
+
+ getAccessTypeHelp(index) {
+ const accessTypeItem = this.nfsAccessType.find((currentAccessTypeItem) => {
+ return this.getValue(index, 'access_type') === currentAccessTypeItem.value;
+ });
+ return _.isObjectLike(accessTypeItem) ? accessTypeItem.help : '';
+ }
+
+ getNoSquashDescr() {
+ if (this.form.getValue('squash')) {
+ return `${this.form.getValue('squash')} (${this.i18n('inherited from global config')})`;
+ }
+ return this.i18n('-- Select what kind of user id squashing is performed --');
+ }
+
+ addClient() {
+ const clients = this.form.get('clients') as FormArray;
+
+ const REGEX_IP = `(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\.([0-9]{1,3})([/](\\d|[1-2]\\d|3[0-2]))?)`;
+ const REGEX_LIST_IP = `${REGEX_IP}([ ,]{1,2}${REGEX_IP})*`;
+
+ const fg = new CdFormGroup({
+ addresses: new FormControl('', {
+ validators: [Validators.required, Validators.pattern(REGEX_LIST_IP)]
+ }),
+ access_type: new FormControl(''),
+ squash: new FormControl('')
+ });
+
+ clients.push(fg);
+ return fg;
+ }
+
+ removeClient(index) {
+ const clients = this.form.get('clients') as FormArray;
+ clients.removeAt(index);
+ }
+
+ showError(index, control, formDir, x) {
+ return (<any>this.form.controls.clients).controls[index].showError(control, formDir, x);
+ }
+
+ getValue(index, control) {
+ const clients = this.form.get('clients') as FormArray;
+ const client = clients.at(index) as CdFormGroup;
+ return client.getValue(control);
+ }
+
+ resolveModel(clients: any[]) {
+ _.forEach(clients, (client) => {
+ const fg = this.addClient();
+ fg.patchValue(client);
+ });
+ }
+
+ trackByFn(index) {
+ return index;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html
new file mode 100644
index 00000000..dea05634
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html
@@ -0,0 +1,530 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="nfsForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="nfsForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+
+ <div class="panel-body">
+
+ <!-- cluster_id -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('cluster_id', formDir)}"
+ *ngIf="!isDefaultCluster">
+ <label class="col-sm-3 control-label"
+ for="cluster_id">
+ <ng-container i18n>Cluster</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="cluster_id"
+ name="cluster_id"
+ id="cluster_id"
+ (change)="onClusterChange()">
+ <option *ngIf="allClusters === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allClusters !== null && allClusters.length === 0"
+ value=""
+ i18n>-- No cluster available --</option>
+ <option *ngIf="allClusters !== null && allClusters.length > 0"
+ value=""
+ i18n>-- Select the cluster --</option>
+ <option *ngFor="let cluster of allClusters"
+ [value]="cluster">{{ cluster }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('cluster_id', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- daemons -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('daemons', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="daemons">
+ <ng-container i18n>Daemons</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <ng-container *ngFor="let daemon of nfsForm.getValue('daemons'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="form-control"
+ type="text"
+ [value]="daemon"
+ disabled />
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ type="button"
+ (click)="removeDaemon(i, daemon)">
+ <i class="fa fa-remove fa-fw"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="nfsForm.get('daemons').value"
+ [options]="daemonsSelections"
+ [messages]="daemonsMessages"
+ (selection)="onDaemonSelection()"
+ elemClass="btn btn-default pull-right">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>Add daemon</ng-container>
+ </cd-select>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- FSAL -->
+ <div formGroupName="fsal">
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('name', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="name">
+ <ng-container i18n>Storage Backend</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="name"
+ name="name"
+ id="name"
+ (change)="fsalChangeHandler()">
+ <option *ngIf="allFsals === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allFsals !== null && allFsals.length === 0"
+ value=""
+ i18n>-- No data pools available --</option>
+ <option *ngIf="allFsals !== null && allFsals.length > 0"
+ value=""
+ i18n>-- Select the storage backend --</option>
+ <option *ngFor="let fsal of allFsals"
+ [value]="fsal.value">{{ fsal.descr }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('name', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- RGW user -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('rgw_user_id', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'RGW'">
+ <label class="col-sm-3 control-label"
+ for="rgw_user_id">
+ <ng-container i18n>Object Gateway User</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="rgw_user_id"
+ name="rgw_user_id"
+ id="rgw_user_id"
+ (change)="rgwUserIdChangeHandler()">
+ <option *ngIf="allRgwUsers === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allRgwUsers !== null && allRgwUsers.length === 0"
+ value=""
+ i18n>-- No users available --</option>
+ <option *ngIf="allRgwUsers !== null && allRgwUsers.length > 0"
+ value=""
+ i18n>-- Select the object gateway user --</option>
+ <option *ngFor="let rgwUserId of allRgwUsers"
+ [value]="rgwUserId">{{ rgwUserId }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('rgw_user_id', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- CephFS user_id -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('user_id', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'CEPH'">
+ <label class="col-sm-3 control-label"
+ for="user_id">
+ <ng-container i18n>CephFS User ID</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="user_id"
+ name="user_id"
+ id="user_id">
+ <option *ngIf="allCephxClients === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allCephxClients !== null && allCephxClients.length === 0"
+ value=""
+ i18n>-- No clients available --</option>
+ <option *ngIf="allCephxClients !== null && allCephxClients.length > 0"
+ value=""
+ i18n>-- Select the cephx client --</option>
+ <option *ngFor="let client of allCephxClients"
+ [value]="client">{{ client }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('user_id', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- CephFS fs_name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('fs_name', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'CEPH'">
+ <label class="col-sm-3 control-label"
+ for="fs_name">
+ <ng-container i18n>CephFS Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="fs_name"
+ name="fs_name"
+ id="fs_name"
+ (change)="rgwUserIdChangeHandler()">
+ <option *ngIf="allFsNames === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allFsNames !== null && allFsNames.length === 0"
+ value=""
+ i18n>-- No CephFS filesystem available --</option>
+ <option *ngIf="allFsNames !== null && allFsNames.length > 0"
+ value=""
+ i18n>-- Select the CephFS filesystem --</option>
+ <option *ngFor="let filesystem of allFsNames"
+ [value]="filesystem.name">{{ filesystem.name }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('fs_name', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- Secutiry Label -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('security_label', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'CEPH'">
+ <label class="col-sm-3 control-label"
+ for="security_label">
+ <ng-container i18n>Security Label</ng-container>
+ <span class="required"
+ *ngIf="nfsForm.getValue('security_label')"></span>
+ </label>
+
+ <div class="col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ formControlName="security_label"
+ name="security_label"
+ id="security_label">
+ <label for="security_label"
+ i18n>Enable security label</label>
+ </div>
+
+ <br>
+
+ <input type="text"
+ *ngIf="nfsForm.getValue('security_label')"
+ class="form-control"
+ name="sec_label_xattr"
+ id="sec_label_xattr"
+ formControlName="sec_label_xattr">
+
+ <span class="help-block"
+ *ngIf="nfsForm.showError('sec_label_xattr', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- Path -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('path', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'CEPH'">
+ <label class="col-sm-3 control-label"
+ for="path">
+ <ng-container i18n>CephFS Path</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ class="form-control"
+ name="path"
+ id="path"
+ formControlName="path"
+ [typeahead]="pathDataSource"
+ (typeaheadOnSelect)="pathChangeHandler()"
+ (blur)="pathChangeHandler()">
+ <span class="help-block"
+ *ngIf="nfsForm.showError('path', formDir, 'required')"
+ i18n>Required field</span>
+
+ <span class="help-block"
+ *ngIf="nfsForm.showError('path', formDir, 'pattern')"
+ i18n>Path need to start with a '/' and can be followed by a word</span>
+ <span class="help-block"
+ *ngIf="isNewDirectory && !nfsForm.showError('path', formDir)"
+ i18n>New directory will be created</span>
+ </div>
+ </div>
+
+ <!-- Bucket -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('path', formDir)}"
+ *ngIf="nfsForm.getValue('name') === 'RGW'">
+ <label class="col-sm-3 control-label"
+ for="path">
+ <ng-container i18n>Path</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ class="form-control"
+ name="path"
+ id="path"
+ formControlName="path"
+ [typeahead]="bucketDataSource"
+ (typeaheadOnSelect)="bucketChangeHandler()"
+ (blur)="bucketChangeHandler()">
+
+ <span class="help-block"
+ *ngIf="nfsForm.showError('path', formDir, 'required')"
+ i18n>Required field</span>
+
+ <span class="help-block"
+ *ngIf="nfsForm.showError('path', formDir, 'pattern')"
+ i18n>Path can only be a single '/' or a word</span>
+
+ <span class="help-block"
+ *ngIf="isNewBucket && !nfsForm.showError('path', formDir)"
+ i18n>New bucket will be created</span>
+ </div>
+ </div>
+
+ <!-- NFS Protocol -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('protocolNfsv3', formDir) || nfsForm.showError('protocolNfsv4', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="protocols">
+ <ng-container i18n>NFS Protocol</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ id="protocolNfsv3"
+ name="protocolNfsv3"
+ formControlName="protocolNfsv3">
+ <label i18n
+ for="protocolNfsv3">NFSv3</label>
+ </div>
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ formControlName="protocolNfsv4"
+ name="protocolNfsv4"
+ id="protocolNfsv4">
+ <label i18n
+ for="protocolNfsv4">NFSv4</label>
+ </div>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('protocolNfsv3', formDir, 'required') ||
+ nfsForm.showError('protocolNfsv4', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- Tag -->
+ <div class="form-group"
+ *ngIf="nfsForm.getValue('protocolNfsv3')">
+ <label class="col-sm-3 control-label"
+ for="tag">
+ <ng-container i18n>NFS Tag</ng-container>
+ <cd-helper>
+ <p i18n>Alternative access for <strong>NFS v3</strong> mounts (it must not have a leading /).</p>
+ <p i18n>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</p>
+ <p i18n>By using different Tag options, the same Path may be exported multiple times.</p>
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ class="form-control"
+ name="tag"
+ id="tag"
+ formControlName="tag">
+ </div>
+ </div>
+
+ <!-- Pseudo -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('pseudo', formDir)}"
+ *ngIf="nfsForm.getValue('protocolNfsv4')">
+ <label class="col-sm-3 control-label"
+ for="pseudo">
+ <ng-container i18n>Pseudo</ng-container>
+ <span class="required"></span>
+ <cd-helper>
+ <p i18n>The position that this <strong>NFS v4</strong> export occupies
+ in the <strong>Pseudo FS</strong> (it must be unique).</p>
+ <p i18n>By using different Pseudo options, the same Path may be exported multiple times.</p>
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ class="form-control"
+ name="pseudo"
+ id="pseudo"
+ formControlName="pseudo">
+ <span class="help-block"
+ *ngIf="nfsForm.showError('pseudo', formDir, 'required')"
+ i18n>Required field</span>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('pseudo', formDir, 'pattern')"
+ i18n>Pseudo needs to start with a '/' and can't contain any of the following: >, <, |, &, ( or ).</span>
+ </div>
+ </div>
+
+ <!-- Access Type -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('access_type', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="access_type">
+ <ng-container i18n>Access Type</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="access_type"
+ name="access_type"
+ id="access_type"
+ (change)="accessTypeChangeHandler()">
+ <option *ngIf="nfsAccessType === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="nfsAccessType !== null && nfsAccessType.length === 0"
+ value=""
+ i18n>-- No access type available --</option>
+ <option *ngIf="nfsAccessType !== null && nfsAccessType.length > 0"
+ value=""
+ i18n>-- Select the access type --</option>
+ <option *ngFor="let accessType of nfsAccessType"
+ [value]="accessType.value">{{ accessType.value }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.getValue('access_type')">
+ {{ getAccessTypeHelp(nfsForm.getValue('access_type')) }}
+ </span>
+ <span class="text-warning"
+ *ngIf="nfsForm.getValue('access_type') === 'RW' && nfsForm.getValue('name') === 'RGW'"
+ i18n>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <a href="{{docsUrl}}"
+ target="_blank"> documentation</a> for details before enabling write access.</span>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('access_type', formDir, 'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- Squash -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('squash', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="squash">
+ <ng-container i18n>Squash</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ name="squash"
+ formControlName="squash"
+ id="squash">
+ <option *ngIf="nfsSquash === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="nfsSquash !== null && nfsSquash.length === 0"
+ value=""
+ i18n>-- No squash available --</option>
+ <option *ngIf="nfsSquash !== null && nfsSquash.length > 0"
+ value=""
+ i18n>--Select what kind of user id squashing is performed --</option>
+ <option *ngFor="let squash of nfsSquash"
+ [value]="squash">{{ squash }}</option>
+
+ </select>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('squash', formDir,'required')"
+ i18n>Required field</span>
+ </div>
+ </div>
+
+ <!-- Transport Protocol -->
+ <div class="form-group"
+ [ngClass]="{'has-error': nfsForm.showError('transportUDP', formDir) || nfsForm.showError('transportTCP', formDir)}">
+ <label class="col-sm-3 control-label"
+ for="transports">
+ <ng-container i18n>Transport Protocol</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ formControlName="transportUDP"
+ name="transportUDP"
+ id="transportUDP">
+ <label for="transportUDP"
+ i18n>UDP</label>
+ </div>
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ formControlName="transportTCP"
+ name="transportTCP"
+ id="transportTCP">
+ <label for="transportTCP"
+ i18n>TCP</label>
+ </div>
+ <span class="help-block"
+ *ngIf="nfsForm.showError('transportUDP', formDir, 'required') ||
+ nfsForm.showError('transportTCP', formDir, 'required')"
+ i18n>Required field</span>
+ <hr>
+ </div>
+ </div>
+
+ <!-- Clients -->
+ <cd-nfs-form-client [form]="nfsForm"
+ #nfsClients>
+ </cd-nfs-form-client>
+
+ </div>
+
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir"
+ (submitAction)="submitAction()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.scss
new file mode 100644
index 00000000..cebcc887
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.scss
@@ -0,0 +1,3 @@
+.cd-mb {
+ margin-bottom: 10px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts
new file mode 100644
index 00000000..4d1c0c7a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts
@@ -0,0 +1,229 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
+import { ToastrModule } from 'ngx-toastr';
+
+import { ActivatedRouteStub } from '../../../../testing/activated-route-stub';
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { NfsFormClientComponent } from '../nfs-form-client/nfs-form-client.component';
+import { NfsFormComponent } from './nfs-form.component';
+
+describe('NfsFormComponent', () => {
+ let component: NfsFormComponent;
+ let fixture: ComponentFixture<NfsFormComponent>;
+ let httpTesting: HttpTestingController;
+ let activatedRoute: ActivatedRouteStub;
+
+ configureTestBed(
+ {
+ declarations: [NfsFormComponent, NfsFormClientComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ TypeaheadModule.forRoot()
+ ],
+ providers: [
+ {
+ provide: ActivatedRoute,
+ useValue: new ActivatedRouteStub({ cluster_id: undefined, export_id: undefined })
+ },
+ i18nProviders,
+ SummaryService,
+ CephReleaseNamePipe
+ ]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ const summaryService = TestBed.get(SummaryService);
+ spyOn(summaryService, 'refresh').and.callFake(() => true);
+ spyOn(summaryService, 'getCurrentSummary').and.callFake(() => {
+ return {
+ version: 'master'
+ };
+ });
+
+ fixture = TestBed.createComponent(NfsFormComponent);
+ component = fixture.componentInstance;
+ httpTesting = TestBed.get(HttpTestingController);
+ activatedRoute = TestBed.get(ActivatedRoute);
+ fixture.detectChanges();
+
+ httpTesting.expectOne('api/summary').flush([]);
+ httpTesting
+ .expectOne('api/nfs-ganesha/daemon')
+ .flush([
+ { daemon_id: 'node1', cluster_id: 'cluster1' },
+ { daemon_id: 'node2', cluster_id: 'cluster1' },
+ { daemon_id: 'node5', cluster_id: 'cluster2' }
+ ]);
+ httpTesting.expectOne('ui-api/nfs-ganesha/fsals').flush(['CEPH', 'RGW']);
+ httpTesting.expectOne('ui-api/nfs-ganesha/cephx/clients').flush(['admin', 'fs', 'rgw']);
+ httpTesting.expectOne('ui-api/nfs-ganesha/cephfs/filesystems').flush([{ id: 1, name: 'a' }]);
+ httpTesting.expectOne('api/rgw/user').flush(['test', 'dev']);
+ httpTesting.expectOne('api/rgw/user/dev').flush({ suspended: 0, user_id: 'dev', keys: ['a'] });
+ httpTesting
+ .expectOne('api/rgw/user/test')
+ .flush({ suspended: 1, user_id: 'test', keys: ['a'] });
+ httpTesting.verify();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should process all data', () => {
+ expect(component.allDaemons).toEqual({ cluster1: ['node1', 'node2'], cluster2: ['node5'] });
+ expect(component.isDefaultCluster).toEqual(false);
+ expect(component.allFsals).toEqual([
+ { descr: 'CephFS', value: 'CEPH' },
+ { descr: 'Object Gateway', value: 'RGW' }
+ ]);
+ expect(component.allCephxClients).toEqual(['admin', 'fs', 'rgw']);
+ expect(component.allFsNames).toEqual([{ id: 1, name: 'a' }]);
+ expect(component.allRgwUsers).toEqual(['dev']);
+ });
+
+ it('should create the form', () => {
+ expect(component.nfsForm.value).toEqual({
+ access_type: 'RW',
+ clients: [],
+ cluster_id: '',
+ daemons: [],
+ fsal: { fs_name: 'a', name: '', rgw_user_id: '', user_id: '' },
+ path: '',
+ protocolNfsv3: true,
+ protocolNfsv4: true,
+ pseudo: '',
+ sec_label_xattr: 'security.selinux',
+ security_label: false,
+ squash: '',
+ tag: '',
+ transportTCP: true,
+ transportUDP: true
+ });
+ expect(component.nfsForm.get('cluster_id').disabled).toBeFalsy();
+ });
+
+ it('should prepare data when selecting an cluster', () => {
+ expect(component.allDaemons).toEqual({ cluster1: ['node1', 'node2'], cluster2: ['node5'] });
+ expect(component.daemonsSelections).toEqual([]);
+
+ component.nfsForm.patchValue({ cluster_id: 'cluster1' });
+ component.onClusterChange();
+
+ expect(component.daemonsSelections).toEqual([
+ { description: '', name: 'node1', selected: false, enabled: true },
+ { description: '', name: 'node2', selected: false, enabled: true }
+ ]);
+ });
+
+ it('should clean data when changing cluster', () => {
+ component.nfsForm.patchValue({ cluster_id: 'cluster1', daemons: ['node1'] });
+ component.nfsForm.patchValue({ cluster_id: 'node2' });
+ component.onClusterChange();
+
+ expect(component.nfsForm.getValue('daemons')).toEqual([]);
+ });
+
+ it('should not allow changing cluster in edit mode', () => {
+ component.isEdit = true;
+ component.ngOnInit();
+ expect(component.nfsForm.get('cluster_id').disabled).toBeTruthy();
+ });
+
+ describe('should submit request', () => {
+ beforeEach(() => {
+ component.nfsForm.patchValue({
+ access_type: 'RW',
+ clients: [],
+ cluster_id: 'cluster1',
+ daemons: ['node2'],
+ fsal: { name: 'CEPH', user_id: 'fs', fs_name: 1, rgw_user_id: '' },
+ path: '/foo',
+ protocolNfsv3: true,
+ protocolNfsv4: true,
+ pseudo: '/baz',
+ squash: 'no_root_squash',
+ tag: 'bar',
+ transportTCP: true,
+ transportUDP: true
+ });
+ });
+
+ it('should remove "pseudo" requirement when NFS v4 disabled', () => {
+ component.nfsForm.patchValue({
+ protocolNfsv4: false,
+ pseudo: ''
+ });
+
+ component.nfsForm.updateValueAndValidity({ emitEvent: false });
+ expect(component.nfsForm.valid).toBeTruthy();
+ });
+
+ it('should call update', () => {
+ activatedRoute.setParams({ cluster_id: 'cluster1', export_id: '1' });
+ component.isEdit = true;
+ component.cluster_id = 'cluster1';
+ component.export_id = '1';
+ component.nfsForm.patchValue({ export_id: 1 });
+ component.submitAction();
+
+ const req = httpTesting.expectOne('api/nfs-ganesha/export/cluster1/1');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ access_type: 'RW',
+ clients: [],
+ cluster_id: 'cluster1',
+ daemons: ['node2'],
+ export_id: '1',
+ fsal: { fs_name: 1, name: 'CEPH', sec_label_xattr: null, user_id: 'fs' },
+ path: '/foo',
+ protocols: [3, 4],
+ pseudo: '/baz',
+ security_label: false,
+ squash: 'no_root_squash',
+ tag: 'bar',
+ transports: ['TCP', 'UDP']
+ });
+ });
+
+ it('should call create', () => {
+ activatedRoute.setParams({ cluster_id: undefined, export_id: undefined });
+ component.submitAction();
+
+ const req = httpTesting.expectOne('api/nfs-ganesha/export');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({
+ access_type: 'RW',
+ clients: [],
+ cluster_id: 'cluster1',
+ daemons: ['node2'],
+ fsal: {
+ fs_name: 1,
+ name: 'CEPH',
+ sec_label_xattr: null,
+ user_id: 'fs'
+ },
+ path: '/foo',
+ protocols: [3, 4],
+ pseudo: '/baz',
+ security_label: false,
+ squash: 'no_root_squash',
+ tag: 'bar',
+ transports: ['TCP', 'UDP']
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts
new file mode 100644
index 00000000..b32f7b8d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts
@@ -0,0 +1,597 @@
+import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { forkJoin, Observable, of } from 'rxjs';
+import { map, mergeMap } from 'rxjs/operators';
+
+import { NfsService } from '../../../shared/api/nfs.service';
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { SelectMessages } from '../../../shared/components/select/select-messages.model';
+import { SelectOption } from '../../../shared/components/select/select-option.model';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { NfsFormClientComponent } from '../nfs-form-client/nfs-form-client.component';
+
+@Component({
+ selector: 'cd-nfs-form',
+ templateUrl: './nfs-form.component.html',
+ styleUrls: ['./nfs-form.component.scss']
+})
+export class NfsFormComponent implements OnInit {
+ @ViewChild('nfsClients')
+ nfsClients: NfsFormClientComponent;
+
+ permission: Permission;
+ nfsForm: CdFormGroup;
+ isEdit = false;
+
+ cluster_id = null;
+ export_id = null;
+
+ isNewDirectory = false;
+ isNewBucket = false;
+ isDefaultCluster = false;
+
+ allClusters: string[] = null;
+ allDaemons = {};
+
+ allFsals: any[] = [];
+ allRgwUsers: any[] = [];
+ allCephxClients: any[] = null;
+ allFsNames: any[] = null;
+
+ defaultAccessType = { RGW: 'RO' };
+ nfsAccessType: any[] = this.nfsService.nfsAccessType;
+ nfsSquash: any[] = this.nfsService.nfsSquash;
+
+ action: string;
+ resource: string;
+ docsUrl: string;
+
+ daemonsSelections: SelectOption[] = [];
+ daemonsMessages = new SelectMessages(
+ { noOptions: this.i18n('There are no daemons available.') },
+ this.i18n
+ );
+
+ pathDataSource: Observable<any> = Observable.create((observer: any) => {
+ observer.next(this.nfsForm.getValue('path'));
+ }).pipe(
+ mergeMap((token: string) => this.getPathTypeahead(token)),
+ map((val: any) => val.paths)
+ );
+
+ bucketDataSource: Observable<any> = Observable.create((observer: any) => {
+ observer.next(this.nfsForm.getValue('path'));
+ }).pipe(mergeMap((token: string) => this.getBucketTypeahead(token)));
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private nfsService: NfsService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private rgwUserService: RgwUserService,
+ private formBuilder: CdFormBuilder,
+ private summaryservice: SummaryService,
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private taskWrapper: TaskWrapperService,
+ private cdRef: ChangeDetectorRef,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().pool;
+ this.resource = this.i18n('NFS export');
+ this.createForm();
+ }
+
+ ngOnInit() {
+ const promises: any[] = [
+ this.nfsService.daemon(),
+ this.nfsService.fsals(),
+ this.nfsService.clients(),
+ this.nfsService.filesystems()
+ ];
+
+ if (this.router.url.startsWith('/nfs/edit')) {
+ this.isEdit = true;
+ }
+
+ if (this.isEdit) {
+ this.action = this.actionLabels.EDIT;
+ this.route.params.subscribe((params: { cluster_id: string; export_id: string }) => {
+ this.cluster_id = decodeURIComponent(params.cluster_id);
+ this.export_id = decodeURIComponent(params.export_id);
+ promises.push(this.nfsService.get(this.cluster_id, this.export_id));
+
+ this.getData(promises);
+ });
+ this.nfsForm.get('cluster_id').disable();
+ } else {
+ this.action = this.actionLabels.CREATE;
+ this.getData(promises);
+ }
+
+ const summary = this.summaryservice.getCurrentSummary();
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/radosgw/nfs/`;
+ }
+
+ getData(promises) {
+ forkJoin(promises).subscribe((data: any[]) => {
+ this.resolveDaemons(data[0]);
+ this.resolvefsals(data[1]);
+ this.resolveClients(data[2]);
+ this.resolveFilesystems(data[3]);
+ if (data[4]) {
+ this.resolveModel(data[4]);
+ }
+ });
+ }
+
+ createForm() {
+ this.nfsForm = new CdFormGroup({
+ cluster_id: new FormControl('', {
+ validators: [Validators.required]
+ }),
+ daemons: new FormControl([]),
+ fsal: new CdFormGroup({
+ name: new FormControl('', {
+ validators: [Validators.required]
+ }),
+ user_id: new FormControl('', {
+ validators: [
+ CdValidators.requiredIf({
+ name: 'CEPH'
+ })
+ ]
+ }),
+ fs_name: new FormControl('', {
+ validators: [
+ CdValidators.requiredIf({
+ name: 'CEPH'
+ })
+ ]
+ }),
+ rgw_user_id: new FormControl('', {
+ validators: [
+ CdValidators.requiredIf({
+ name: 'RGW'
+ })
+ ]
+ })
+ }),
+ path: new FormControl(''),
+ protocolNfsv3: new FormControl(true, {
+ validators: [
+ CdValidators.requiredIf({ protocolNfsv4: false }, (value) => {
+ return !value;
+ })
+ ]
+ }),
+ protocolNfsv4: new FormControl(true, {
+ validators: [
+ CdValidators.requiredIf({ protocolNfsv3: false }, (value) => {
+ return !value;
+ })
+ ]
+ }),
+ tag: new FormControl(''),
+ pseudo: new FormControl('', {
+ validators: [
+ CdValidators.requiredIf({ protocolNfsv4: true }),
+ Validators.pattern('^/[^><|&()]*$')
+ ]
+ }),
+ access_type: new FormControl('RW', {
+ validators: [Validators.required]
+ }),
+ squash: new FormControl('', {
+ validators: [Validators.required]
+ }),
+ transportUDP: new FormControl(true, {
+ validators: [
+ CdValidators.requiredIf({ transportTCP: false }, (value) => {
+ return !value;
+ })
+ ]
+ }),
+ transportTCP: new FormControl(true, {
+ validators: [
+ CdValidators.requiredIf({ transportUDP: false }, (value) => {
+ return !value;
+ })
+ ]
+ }),
+ clients: this.formBuilder.array([]),
+ security_label: new FormControl(false),
+ sec_label_xattr: new FormControl(
+ 'security.selinux',
+ CdValidators.requiredIf({ security_label: true, 'fsal.name': 'CEPH' })
+ )
+ });
+ }
+
+ resolveModel(res) {
+ if (res.fsal.name === 'CEPH') {
+ res.sec_label_xattr = res.fsal.sec_label_xattr;
+ }
+
+ this.daemonsSelections = _.map(
+ this.allDaemons[res.cluster_id],
+ (daemon) => new SelectOption(res.daemons.indexOf(daemon) !== -1, daemon, '')
+ );
+ this.daemonsSelections = [...this.daemonsSelections];
+
+ res.protocolNfsv3 = res.protocols.indexOf(3) !== -1;
+ res.protocolNfsv4 = res.protocols.indexOf(4) !== -1;
+ delete res.protocols;
+
+ res.transportTCP = res.transports.indexOf('TCP') !== -1;
+ res.transportUDP = res.transports.indexOf('UDP') !== -1;
+ delete res.transports;
+
+ res.clients.forEach((client) => {
+ let addressStr = '';
+ client.addresses.forEach((address) => {
+ addressStr += address + ', ';
+ });
+ if (addressStr.length >= 2) {
+ addressStr = addressStr.substring(0, addressStr.length - 2);
+ }
+ client.addresses = addressStr;
+ });
+
+ this.nfsForm.patchValue(res);
+ this.setPathValidation();
+ this.nfsClients.resolveModel(res.clients);
+ }
+
+ resolveDaemons(daemons) {
+ daemons = _.sortBy(daemons, ['daemon_id']);
+
+ this.allClusters = _(daemons)
+ .map((daemon) => daemon.cluster_id)
+ .sortedUniq()
+ .value();
+
+ _.forEach(this.allClusters, (cluster) => {
+ this.allDaemons[cluster] = [];
+ });
+
+ _.forEach(daemons, (daemon) => {
+ this.allDaemons[daemon.cluster_id].push(daemon.daemon_id);
+ });
+
+ const hasOneCluster = _.isArray(this.allClusters) && this.allClusters.length === 1;
+ this.isDefaultCluster = hasOneCluster && this.allClusters[0] === '_default_';
+ if (hasOneCluster) {
+ this.nfsForm.patchValue({
+ cluster_id: this.allClusters[0]
+ });
+ this.onClusterChange();
+ }
+ }
+
+ resolvefsals(res: string[]) {
+ res.forEach((fsal) => {
+ const fsalItem = this.nfsService.nfsFsal.find((currentFsalItem) => {
+ return fsal === currentFsalItem.value;
+ });
+
+ if (_.isObjectLike(fsalItem)) {
+ this.allFsals.push(fsalItem);
+ if (fsalItem.value === 'RGW') {
+ this.rgwUserService.list().subscribe((result: any) => {
+ result.forEach((user) => {
+ if (user.suspended === 0 && user.keys.length > 0) {
+ this.allRgwUsers.push(user.user_id);
+ }
+ });
+ });
+ }
+ }
+ });
+
+ if (this.allFsals.length === 1 && _.isUndefined(this.nfsForm.getValue('fsal'))) {
+ this.nfsForm.patchValue({
+ fsal: this.allFsals[0]
+ });
+ }
+ }
+
+ resolveClients(clients) {
+ this.allCephxClients = clients;
+ }
+
+ resolveFilesystems(filesystems) {
+ this.allFsNames = filesystems;
+ if (filesystems.length === 1) {
+ this.nfsForm.patchValue({
+ fsal: {
+ fs_name: filesystems[0].name
+ }
+ });
+ }
+ }
+
+ fsalChangeHandler() {
+ this.nfsForm.patchValue({
+ tag: this._generateTag(),
+ pseudo: this._generatePseudo(),
+ access_type: this._updateAccessType()
+ });
+
+ this.setPathValidation();
+
+ this.cdRef.detectChanges();
+ }
+
+ accessTypeChangeHandler() {
+ const name = this.nfsForm.getValue('name');
+ const accessType = this.nfsForm.getValue('access_type');
+ this.defaultAccessType[name] = accessType;
+ }
+
+ setPathValidation() {
+ if (this.nfsForm.getValue('name') === 'RGW') {
+ this.nfsForm
+ .get('path')
+ .setValidators([Validators.required, Validators.pattern('^(/|[^/><|&()#?]+)$')]);
+ } else {
+ this.nfsForm
+ .get('path')
+ .setValidators([Validators.required, Validators.pattern('^/[^><|&()?]*$')]);
+ }
+ }
+
+ rgwUserIdChangeHandler() {
+ this.nfsForm.patchValue({
+ pseudo: this._generatePseudo()
+ });
+ }
+
+ getAccessTypeHelp(accessType) {
+ const accessTypeItem = this.nfsAccessType.find((currentAccessTypeItem) => {
+ if (accessType === currentAccessTypeItem.value) {
+ return currentAccessTypeItem;
+ }
+ });
+ return _.isObjectLike(accessTypeItem) ? accessTypeItem.help : '';
+ }
+
+ getId() {
+ if (
+ _.isString(this.nfsForm.getValue('cluster_id')) &&
+ _.isString(this.nfsForm.getValue('path'))
+ ) {
+ return this.nfsForm.getValue('cluster_id') + ':' + this.nfsForm.getValue('path');
+ }
+ return '';
+ }
+
+ getPathTypeahead(path) {
+ if (!_.isString(path) || path === '/') {
+ return of([]);
+ }
+
+ return this.nfsService.lsDir(path);
+ }
+
+ pathChangeHandler() {
+ this.nfsForm.patchValue({
+ pseudo: this._generatePseudo()
+ });
+
+ const path = this.nfsForm.getValue('path');
+ this.getPathTypeahead(path).subscribe((res: any) => {
+ this.isNewDirectory = path !== '/' && res.paths.indexOf(path) === -1;
+ });
+ }
+
+ bucketChangeHandler() {
+ this.nfsForm.patchValue({
+ tag: this._generateTag(),
+ pseudo: this._generatePseudo()
+ });
+
+ const bucket = this.nfsForm.getValue('path');
+ this.getBucketTypeahead(bucket).subscribe((res: any) => {
+ this.isNewBucket = bucket !== '' && res.indexOf(bucket) === -1;
+ });
+ }
+
+ getBucketTypeahead(path: string): Observable<any> {
+ const rgwUserId = this.nfsForm.getValue('rgw_user_id');
+
+ if (_.isString(rgwUserId) && _.isString(path) && path !== '/' && path !== '') {
+ return this.nfsService.buckets(rgwUserId);
+ } else {
+ return of([]);
+ }
+ }
+
+ _generateTag() {
+ let newTag = this.nfsForm.getValue('tag');
+ if (!this.nfsForm.get('tag').dirty) {
+ newTag = undefined;
+ if (this.nfsForm.getValue('fsal') === 'RGW') {
+ newTag = this.nfsForm.getValue('path');
+ }
+ }
+ return newTag;
+ }
+
+ _generatePseudo() {
+ let newPseudo = this.nfsForm.getValue('pseudo');
+ if (this.nfsForm.get('pseudo') && !this.nfsForm.get('pseudo').dirty) {
+ newPseudo = undefined;
+ if (this.nfsForm.getValue('fsal') === 'CEPH') {
+ newPseudo = '/cephfs';
+ if (_.isString(this.nfsForm.getValue('path'))) {
+ newPseudo += this.nfsForm.getValue('path');
+ }
+ } else if (this.nfsForm.getValue('fsal') === 'RGW') {
+ if (_.isString(this.nfsForm.getValue('rgw_user_id'))) {
+ newPseudo = '/' + this.nfsForm.getValue('rgw_user_id');
+ if (_.isString(this.nfsForm.getValue('path'))) {
+ newPseudo += '/' + this.nfsForm.getValue('path');
+ }
+ }
+ }
+ }
+ return newPseudo;
+ }
+
+ _updateAccessType() {
+ const name = this.nfsForm.getValue('name');
+ let accessType = this.defaultAccessType[name];
+
+ if (!accessType) {
+ accessType = 'RW';
+ }
+
+ return accessType;
+ }
+
+ onClusterChange() {
+ const cluster_id = this.nfsForm.getValue('cluster_id');
+ this.daemonsSelections = _.map(
+ this.allDaemons[cluster_id],
+ (daemon) => new SelectOption(false, daemon, '')
+ );
+ this.daemonsSelections = [...this.daemonsSelections];
+ this.nfsForm.patchValue({ daemons: [] });
+ }
+
+ removeDaemon(index, daemon) {
+ this.daemonsSelections.forEach((value) => {
+ if (value.name === daemon) {
+ value.selected = false;
+ }
+ });
+
+ const daemons = this.nfsForm.get('daemons');
+ daemons.value.splice(index, 1);
+ daemons.setValue(daemons.value);
+
+ return false;
+ }
+
+ onDaemonSelection() {
+ this.nfsForm.get('daemons').setValue(this.nfsForm.getValue('daemons'));
+ }
+
+ submitAction() {
+ let action: Observable<any>;
+ const requestModel = this._buildRequest();
+
+ if (this.isEdit) {
+ action = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('nfs/edit', {
+ cluster_id: this.cluster_id,
+ export_id: this.export_id
+ }),
+ call: this.nfsService.update(this.cluster_id, this.export_id, requestModel)
+ });
+ } else {
+ // Create
+ action = this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('nfs/create', {
+ path: requestModel.path,
+ fsal: requestModel.fsal,
+ cluster_id: requestModel.cluster_id
+ }),
+ call: this.nfsService.create(requestModel)
+ });
+ }
+
+ action.subscribe(
+ undefined,
+ () => this.nfsForm.setErrors({ cdSubmitButton: true }),
+ () => this.router.navigate(['/nfs'])
+ );
+ }
+
+ _buildRequest() {
+ const requestModel: any = _.cloneDeep(this.nfsForm.value);
+
+ if (_.isUndefined(requestModel.tag) || requestModel.tag === '') {
+ requestModel.tag = null;
+ }
+
+ if (this.isEdit) {
+ requestModel.export_id = this.export_id;
+ }
+
+ if (requestModel.fsal.name === 'CEPH') {
+ delete requestModel.fsal.rgw_user_id;
+ } else {
+ delete requestModel.fsal.fs_name;
+ delete requestModel.fsal.user_id;
+ }
+
+ requestModel.protocols = [];
+ if (requestModel.protocolNfsv3) {
+ requestModel.protocols.push(3);
+ } else {
+ requestModel.tag = null;
+ }
+ delete requestModel.protocolNfsv3;
+ if (requestModel.protocolNfsv4) {
+ requestModel.protocols.push(4);
+ } else {
+ requestModel.pseudo = null;
+ }
+ delete requestModel.protocolNfsv4;
+
+ requestModel.transports = [];
+ if (requestModel.transportTCP) {
+ requestModel.transports.push('TCP');
+ }
+ delete requestModel.transportTCP;
+ if (requestModel.transportUDP) {
+ requestModel.transports.push('UDP');
+ }
+ delete requestModel.transportUDP;
+
+ requestModel.clients.forEach((client) => {
+ if (_.isString(client.addresses)) {
+ client.addresses = _(client.addresses)
+ .split(/[ ,]+/)
+ .uniq()
+ .filter((address) => address !== '')
+ .value();
+ } else {
+ client.addresses = [];
+ }
+
+ if (!client.squash) {
+ client.squash = requestModel.squash;
+ }
+
+ if (!client.access_type) {
+ client.access_type = requestModel.access_type;
+ }
+ });
+
+ if (requestModel.security_label === false || requestModel.fsal.name === 'RGW') {
+ requestModel.fsal.sec_label_xattr = null;
+ } else {
+ requestModel.fsal.sec_label_xattr = requestModel.sec_label_xattr;
+ }
+ delete requestModel.sec_label_xattr;
+
+ return requestModel;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.html
new file mode 100644
index 00000000..ef42aa29
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.html
@@ -0,0 +1,28 @@
+<cd-table #table
+ [data]="exports"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="id"
+ forceIdentifier="true"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <div class="table-actions btn-toolbar">
+ <cd-table-actions class="btn-group"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ </div>
+
+ <cd-nfs-details cdTableDetail
+ [selection]="selection">
+ </cd-nfs-details>
+</cd-table>
+
+<ng-template #nfsFsal
+ let-value="value">
+ <ng-container *ngIf="value.name==='CEPH'"
+ i18n>CephFS</ng-container>
+ <ng-container *ngIf="value.name==='RGW'"
+ i18n>Object Gateway</ng-container>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.spec.ts
new file mode 100644
index 00000000..5e44726b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.spec.ts
@@ -0,0 +1,325 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { BehaviorSubject, of } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { NfsService } from '../../../shared/api/nfs.service';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { NfsDetailsComponent } from '../nfs-details/nfs-details.component';
+import { NfsListComponent } from './nfs-list.component';
+
+describe('NfsListComponent', () => {
+ let component: NfsListComponent;
+ let fixture: ComponentFixture<NfsListComponent>;
+ let summaryService: SummaryService;
+ let nfsService: NfsService;
+ let httpTesting: HttpTestingController;
+
+ const refresh = (data) => {
+ summaryService['summaryDataSource'].next(data);
+ };
+
+ configureTestBed(
+ {
+ declarations: [NfsListComponent, NfsDetailsComponent],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ TabsModule.forRoot()
+ ],
+ providers: [TaskListService, i18nProviders]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NfsListComponent);
+ component = fixture.componentInstance;
+ summaryService = TestBed.get(SummaryService);
+ nfsService = TestBed.get(NfsService);
+ httpTesting = TestBed.get(HttpTestingController);
+
+ // this is needed because summaryService isn't being reset after each test.
+ summaryService['summaryDataSource'] = new BehaviorSubject(null);
+ summaryService['summaryData$'] = summaryService['summaryDataSource'].asObservable();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('after ngOnInit', () => {
+ beforeEach(() => {
+ fixture.detectChanges();
+ spyOn(nfsService, 'list').and.callThrough();
+ httpTesting.expectOne('api/nfs-ganesha/daemon').flush([]);
+ httpTesting.expectOne('api/summary');
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should load exports on init', () => {
+ refresh({});
+ httpTesting.expectOne('api/nfs-ganesha/export');
+ expect(nfsService.list).toHaveBeenCalled();
+ });
+
+ it('should not load images on init because no data', () => {
+ refresh(undefined);
+ expect(nfsService.list).not.toHaveBeenCalled();
+ });
+
+ it('should call error function on init when summary service fails', () => {
+ spyOn(component.table, 'reset');
+ summaryService['summaryDataSource'].error(undefined);
+ expect(component.table.reset).toHaveBeenCalled();
+ });
+ });
+
+ describe('handling of executing tasks', () => {
+ let exports: any[];
+
+ const addExport = (export_id) => {
+ const model = {
+ export_id: export_id,
+ path: 'path_' + export_id,
+ fsal: 'fsal_' + export_id,
+ cluster_id: 'cluster_' + export_id
+ };
+ exports.push(model);
+ };
+
+ const addTask = (name: string, export_id: string) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ switch (task.name) {
+ case 'nfs/create':
+ task.metadata = {
+ path: 'path_' + export_id,
+ fsal: 'fsal_' + export_id,
+ cluster_id: 'cluster_' + export_id
+ };
+ break;
+ default:
+ task.metadata = {
+ cluster_id: 'cluster_' + export_id,
+ export_id: export_id
+ };
+ break;
+ }
+ summaryService.addRunningTask(task);
+ };
+
+ beforeEach(() => {
+ exports = [];
+ addExport('a');
+ addExport('b');
+ addExport('c');
+ component.exports = exports;
+ refresh({ executing_tasks: [], finished_tasks: [] });
+ spyOn(nfsService, 'list').and.callFake(() => of(exports));
+ fixture.detectChanges();
+
+ const req = httpTesting.expectOne('api/nfs-ganesha/daemon');
+ req.flush([]);
+ });
+
+ it('should gets all exports without tasks', () => {
+ expect(component.exports.length).toBe(3);
+ expect(component.exports.every((expo) => !expo.cdExecuting)).toBeTruthy();
+ });
+
+ it('should add a new export from a task', fakeAsync(() => {
+ addTask('nfs/create', 'd');
+ tick();
+ expect(component.exports.length).toBe(4);
+ expectItemTasks(component.exports[0], undefined);
+ expectItemTasks(component.exports[1], undefined);
+ expectItemTasks(component.exports[2], undefined);
+ expectItemTasks(component.exports[3], 'Creating');
+ }));
+
+ it('should show when an existing export is being modified', () => {
+ addTask('nfs/edit', 'a');
+ addTask('nfs/delete', 'b');
+ expect(component.exports.length).toBe(3);
+ expectItemTasks(component.exports[0], 'Updating');
+ expectItemTasks(component.exports[1], 'Deleting');
+ });
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: 'Edit',
+ empty: 'Create'
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Create' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Create' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows all actions except for 'Delete'`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Create' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create', and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' actions`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`always shows 'Create' as main action`, () => {
+ scenario.single = 'Create';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Create' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and edit', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts
new file mode 100644
index 00000000..3b819a14
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts
@@ -0,0 +1,221 @@
+import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { Subscription } from 'rxjs';
+
+import { NfsService } from '../../../shared/api/nfs.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+
+@Component({
+ selector: 'cd-nfs-list',
+ templateUrl: './nfs-list.component.html',
+ styleUrls: ['./nfs-list.component.scss'],
+ providers: [TaskListService]
+})
+export class NfsListComponent implements OnInit, OnDestroy {
+ @ViewChild('nfsState')
+ nfsState: TemplateRef<any>;
+ @ViewChild('nfsFsal')
+ nfsFsal: TemplateRef<any>;
+
+ @ViewChild('table')
+ table: TableComponent;
+
+ columns: CdTableColumn[];
+ permission: Permission;
+ selection = new CdTableSelection();
+ summaryDataSubscription: Subscription;
+ viewCacheStatus: any;
+ exports: any[];
+ tableActions: CdTableAction[];
+ isDefaultCluster = false;
+
+ modalRef: BsModalRef;
+
+ builders = {
+ 'nfs/create': (metadata) => {
+ return {
+ path: metadata['path'],
+ cluster_id: metadata['cluster_id'],
+ fsal: metadata['fsal']
+ };
+ }
+ };
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private i18n: I18n,
+ private modalService: BsModalService,
+ private nfsService: NfsService,
+ private taskListService: TaskListService,
+ private taskWrapper: TaskWrapperService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().nfs;
+ const getNfsUri = () =>
+ this.selection.first() &&
+ `${encodeURI(this.selection.first().cluster_id)}/${encodeURI(
+ this.selection.first().export_id
+ )}`;
+
+ const createAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => '/nfs/create',
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
+ name: this.actionLabels.CREATE
+ };
+
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => `/nfs/edit/${getNfsUri()}`,
+ name: this.actionLabels.EDIT
+ };
+
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteNfsModal(),
+ name: this.actionLabels.DELETE
+ };
+
+ this.tableActions = [createAction, editAction, deleteAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Path'),
+ prop: 'path',
+ flexGrow: 2,
+ cellTransformation: CellTemplate.executing
+ },
+ {
+ name: this.i18n('Pseudo'),
+ prop: 'pseudo',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Cluster'),
+ prop: 'cluster_id',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Daemons'),
+ prop: 'daemons',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Storage Backend'),
+ prop: 'fsal',
+ flexGrow: 2,
+ cellTemplate: this.nfsFsal
+ },
+ {
+ name: this.i18n('Access Type'),
+ prop: 'access_type',
+ flexGrow: 2
+ }
+ ];
+
+ this.nfsService.daemon().subscribe(
+ (daemons: any) => {
+ const clusters = _(daemons)
+ .map((daemon) => daemon.cluster_id)
+ .uniq()
+ .value();
+
+ this.isDefaultCluster = clusters.length === 1 && clusters[0] === '_default_';
+ this.columns[2].isHidden = this.isDefaultCluster;
+ if (this.table) {
+ this.table.updateColumns();
+ }
+
+ this.taskListService.init(
+ () => this.nfsService.list(),
+ (resp) => this.prepareResponse(resp),
+ (exports) => (this.exports = exports),
+ () => this.onFetchError(),
+ this.taskFilter,
+ this.itemFilter,
+ this.builders
+ );
+ },
+ () => {
+ this.onFetchError();
+ }
+ );
+ }
+
+ ngOnDestroy() {
+ if (this.summaryDataSubscription) {
+ this.summaryDataSubscription.unsubscribe();
+ }
+ }
+
+ prepareResponse(resp: any): any[] {
+ let result = [];
+ resp.forEach((nfs) => {
+ nfs.id = `${nfs.cluster_id}:${nfs.export_id}`;
+ nfs.state = 'LOADING';
+ result = result.concat(nfs);
+ });
+
+ return result;
+ }
+
+ onFetchError() {
+ this.table.reset(); // Disable loading indicator.
+ this.viewCacheStatus = { status: ViewCacheStatus.ValueException };
+ }
+
+ itemFilter(entry, task) {
+ return (
+ entry.cluster_id === task.metadata['cluster_id'] &&
+ entry.export_id === task.metadata['export_id']
+ );
+ }
+
+ taskFilter(task) {
+ return ['nfs/create', 'nfs/delete', 'nfs/edit'].includes(task.name);
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteNfsModal() {
+ const cluster_id = this.selection.first().cluster_id;
+ const export_id = this.selection.first().export_id;
+
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.i18n('NFS export'),
+ itemNames: [`${cluster_id}:${export_id}`],
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('nfs/delete', {
+ cluster_id: cluster_id,
+ export_id: export_id
+ }),
+ call: this.nfsService.delete(cluster_id, export_id)
+ })
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs.module.ts
new file mode 100644
index 00000000..e61227ac
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs.module.ts
@@ -0,0 +1,34 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
+
+import { SharedModule } from '../../shared/shared.module';
+import { Nfs501Component } from './nfs-501/nfs-501.component';
+import { NfsDetailsComponent } from './nfs-details/nfs-details.component';
+import { NfsFormClientComponent } from './nfs-form-client/nfs-form-client.component';
+import { NfsFormComponent } from './nfs-form/nfs-form.component';
+import { NfsListComponent } from './nfs-list/nfs-list.component';
+
+@NgModule({
+ imports: [
+ ReactiveFormsModule,
+ RouterModule,
+ SharedModule,
+ TabsModule.forRoot(),
+ CommonModule,
+ TypeaheadModule.forRoot()
+ ],
+ declarations: [
+ NfsListComponent,
+ NfsDetailsComponent,
+ NfsFormComponent,
+ NfsFormClientComponent,
+ Nfs501Component
+ ],
+ exports: [Nfs501Component]
+})
+export class NfsModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter.module.ts
new file mode 100644
index 00000000..6e0967a4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter.module.ts
@@ -0,0 +1,14 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { SharedModule } from '../../shared/shared.module';
+import { PerformanceCounterComponent } from './performance-counter/performance-counter.component';
+import { TablePerformanceCounterComponent } from './table-performance-counter/table-performance-counter.component';
+
+@NgModule({
+ imports: [CommonModule, SharedModule, RouterModule],
+ declarations: [TablePerformanceCounterComponent, PerformanceCounterComponent],
+ exports: [TablePerformanceCounterComponent]
+})
+export class PerformanceCounterModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.html
new file mode 100644
index 00000000..988a8a25
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.html
@@ -0,0 +1,4 @@
+<legend>{{ serviceType }}.{{ serviceId }}</legend>
+<cd-table-performance-counter [serviceType]="serviceType"
+ [serviceId]="serviceId">
+</cd-table-performance-counter>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.spec.ts
new file mode 100644
index 00000000..233599be
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.spec.ts
@@ -0,0 +1,29 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { TablePerformanceCounterComponent } from '../table-performance-counter/table-performance-counter.component';
+import { PerformanceCounterComponent } from './performance-counter.component';
+
+describe('PerformanceCounterComponent', () => {
+ let component: PerformanceCounterComponent;
+ let fixture: ComponentFixture<PerformanceCounterComponent>;
+
+ configureTestBed({
+ declarations: [PerformanceCounterComponent, TablePerformanceCounterComponent],
+ imports: [RouterTestingModule, SharedModule, HttpClientTestingModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PerformanceCounterComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.ts
new file mode 100644
index 00000000..9321e0e9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/performance-counter/performance-counter.component.ts
@@ -0,0 +1,25 @@
+import { Component } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+@Component({
+ selector: 'cd-performance-counter',
+ templateUrl: './performance-counter.component.html',
+ styleUrls: ['./performance-counter.component.scss']
+})
+export class PerformanceCounterComponent {
+ static defaultFromLink = '/hosts';
+
+ serviceId: string;
+ serviceType: string;
+ fromLink: string;
+
+ constructor(private route: ActivatedRoute) {
+ this.route.queryParams.subscribe((params: { fromLink: string }) => {
+ this.fromLink = params.fromLink || PerformanceCounterComponent.defaultFromLink;
+ });
+ this.route.params.subscribe((params: { type: string; id: string }) => {
+ this.serviceId = decodeURIComponent(params.id);
+ this.serviceType = params.type;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.html
new file mode 100644
index 00000000..097ea48c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.html
@@ -0,0 +1,13 @@
+<cd-table *ngIf="counters; else warning"
+ [data]="counters"
+ [columns]="columns"
+ columnMode="flex"
+ [autoSave]="false"
+ (fetchData)="getCounters($event)">
+ <ng-template #valueTpl let-row="row">
+ {{ row.value | dimless }} {{ row.unit }}
+ </ng-template>
+</cd-table>
+<ng-template #warning>
+ <cd-warning-panel i18n>Performance counters not available</cd-warning-panel>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.spec.ts
new file mode 100644
index 00000000..769dde58
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.spec.ts
@@ -0,0 +1,63 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { AppModule } from '../../../app.module';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { TablePerformanceCounterComponent } from './table-performance-counter.component';
+
+describe('TablePerformanceCounterComponent', () => {
+ let component: TablePerformanceCounterComponent;
+ let fixture: ComponentFixture<TablePerformanceCounterComponent>;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [AppModule, HttpClientTestingModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TablePerformanceCounterComponent);
+ component = fixture.componentInstance;
+ httpTesting = TestBed.get(HttpTestingController);
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(component.counters).toEqual([]);
+ });
+
+ it('should have columns that are sortable', () => {
+ expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ });
+
+ describe('Error handling', () => {
+ const context = new CdTableFetchDataContext(() => {});
+
+ beforeEach(() => {
+ spyOn(context, 'error');
+ component.serviceType = 'osd';
+ component.serviceId = '3';
+ component.getCounters(context);
+ });
+
+ it('should display 404 warning', () => {
+ httpTesting
+ .expectOne('api/perf_counters/osd/3')
+ .error(new ErrorEvent('osd.3 not found'), { status: 404 });
+ httpTesting.verify();
+ expect(component.counters).toBeNull();
+ expect(context.error).not.toHaveBeenCalled();
+ });
+
+ it('should call error function of context', () => {
+ httpTesting
+ .expectOne('api/perf_counters/osd/3')
+ .error(new ErrorEvent('Unknown error'), { status: 500 });
+ httpTesting.verify();
+ expect(component.counters).toEqual([]);
+ expect(context.error).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.ts
new file mode 100644
index 00000000..ac6ea523
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/performance-counter/table-performance-counter/table-performance-counter.component.ts
@@ -0,0 +1,74 @@
+import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { PerformanceCounterService } from '../../../shared/api/performance-counter.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+
+/**
+ * Display the specified performance counters in a datatable.
+ */
+@Component({
+ selector: 'cd-table-performance-counter',
+ templateUrl: './table-performance-counter.component.html',
+ styleUrls: ['./table-performance-counter.component.scss']
+})
+export class TablePerformanceCounterComponent implements OnInit {
+ columns: Array<CdTableColumn> = [];
+ counters: Array<object> = [];
+
+ @ViewChild('valueTpl')
+ public valueTpl: TemplateRef<any>;
+
+ /**
+ * The service type, e.g. 'rgw', 'mds', 'mon', 'osd', ...
+ */
+ @Input()
+ serviceType: string;
+
+ /**
+ * The service identifier.
+ */
+ @Input()
+ serviceId: string;
+
+ constructor(private performanceCounterService: PerformanceCounterService, private i18n: I18n) {}
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Description'),
+ prop: 'description',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Value'),
+ prop: 'value',
+ cellTemplate: this.valueTpl,
+ flexGrow: 1
+ }
+ ];
+ }
+
+ getCounters(context: CdTableFetchDataContext) {
+ this.performanceCounterService.get(this.serviceType, this.serviceId).subscribe(
+ (resp: object[]) => {
+ this.counters = resp;
+ },
+ (error) => {
+ if (error.status === 404) {
+ error.preventDefault();
+ this.counters = null;
+ } else {
+ context.error();
+ }
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html
new file mode 100644
index 00000000..4806bf21
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html
@@ -0,0 +1,330 @@
+<div class="modal-header">
+ <h4 i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title pull-left">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+
+<form class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="form"
+ novalidate>
+ <div class="modal-body">
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('name', frm)}">
+ <label for="name"
+ class="control-label col-sm-3">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ id="name"
+ name="name"
+ class="form-control"
+ placeholder="Name..."
+ formControlName="name"
+ autofocus>
+ <span class="help-block"
+ *ngIf="form.showError('name', frm, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('name', frm, 'pattern')"
+ i18n>The name can only consist of alphanumeric characters, dashes and underscores.</span>
+ <span class="help-block"
+ *ngIf="form.showError('name', frm, 'uniqueName')"
+ i18n>The chosen erasure code profile name is already in use.</span>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="plugin"
+ class="control-label col-sm-3">
+ <ng-container i18n>Plugin</ng-container>
+ <span class="required"></span>
+ <cd-helper [html]="tooltips.plugins[plugin].description">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="plugin"
+ name="plugin"
+ formControlName="plugin">
+ <option *ngIf="!plugins"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngFor="let plugin of plugins"
+ [ngValue]="plugin">
+ {{ plugin }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="form.showError('name', frm, 'required')"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('k', frm)}">
+ <label for="k"
+ class="control-label col-sm-3">
+ <ng-container i18n>Data chunks (k)</ng-container>
+ <span class="required"
+ *ngIf="requiredControls.includes('k')"></span>
+ <cd-helper [html]="tooltips.k">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="number"
+ id="k"
+ name="k"
+ class="form-control"
+ ng-model="$ctrl.erasureCodeProfile.k"
+ placeholder="Data chunks..."
+ formControlName="k">
+ <span class="help-block"
+ *ngIf="form.showError('k', frm, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('k', frm, 'min')"
+ i18n>Must be equal to or greater than 2.</span>
+ </div>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('m', frm)}">
+ <label for="m"
+ class="control-label col-sm-3">
+ <ng-container i18n>Coding chunks (m)</ng-container>
+ <span class="required"
+ *ngIf="requiredControls.includes('m')"></span>
+ <cd-helper [html]="tooltips.m">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="number"
+ id="m"
+ name="m"
+ class="form-control"
+ placeholder="Coding chunks..."
+ formControlName="m">
+ <span class="help-block"
+ *ngIf="form.showError('m', frm, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('m', frm, 'min')"
+ i18n>Must be equal to or greater than 1.</span>
+ </div>
+ </div>
+
+ <div class="form-group"
+ *ngIf="plugin === 'shec'"
+ [ngClass]="{'has-error': form.showError('c', frm)}">
+ <label for="c"
+ class="control-label col-sm-3">
+ <ng-container i18n>Durability estimator (c)</ng-container>
+ <cd-helper [html]="tooltips.plugins.shec.c">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="number"
+ id="c"
+ name="c"
+ class="form-control"
+ placeholder="Coding chunks..."
+ formControlName="c">
+ <span class="help-block"
+ *ngIf="form.showError('c', frm, 'min')"
+ i18n>Must be equal to or greater than 1.</span>
+ </div>
+ </div>
+
+ <div class="form-group"
+ *ngIf="plugin === PLUGIN.LRC"
+ [ngClass]="{'has-error': form.showError('l', frm)}">
+ <label for="l"
+ class="control-label col-sm-3">
+ <ng-container i18n>Locality (l)</ng-container>
+ <span class="required"></span>
+ <cd-helper [html]="tooltips.plugins.lrc.l">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="number"
+ id="l"
+ name="l"
+ class="form-control"
+ placeholder="Coding chunks..."
+ formControlName="l">
+ <span class="help-block"
+ *ngIf="form.showError('l', frm, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('l', frm, 'min')"
+ i18n>Must be equal to or greater than 1.</span>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="crushFailureDomain"
+ class="control-label col-sm-3">
+ <ng-container i18n>Crush failure domain</ng-container>
+ <cd-helper [html]="tooltips.crushFailureDomain">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="crushFailureDomain"
+ name="crushFailureDomain"
+ formControlName="crushFailureDomain">
+ <option *ngIf="!failureDomains"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngFor="let domain of failureDomains"
+ [ngValue]="domain">
+ {{ domain }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <div class="form-group"
+ *ngIf="plugin === PLUGIN.LRC">
+ <label for="crushLocality"
+ class="control-label col-sm-3">
+ <ng-container i18n>Crush Locality</ng-container>
+ <cd-helper [html]="tooltips.plugins.lrc.crushLocality">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="crushLocality"
+ name="crushLocality"
+ formControlName="crushLocality">
+ <option *ngIf="!failureDomains"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngIf="failureDomains && failureDomains.length > 0"
+ ngValue=""
+ i18n>None</option>
+ <option *ngFor="let domain of failureDomains"
+ [ngValue]="domain">
+ {{ domain }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <div class="form-group"
+ *ngIf="[PLUGIN.JERASURE, PLUGIN.ISA].includes(plugin)">
+ <label for="technique"
+ class="control-label col-sm-3">
+ <ng-container i18n>Technique</ng-container>
+ <cd-helper [html]="tooltips.plugins[plugin].technique">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="technique"
+ name="technique"
+ formControlName="technique">
+ <option *ngFor="let technique of techniques"
+ [ngValue]="technique">
+ {{ technique }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <div class="form-group"
+ *ngIf="plugin === PLUGIN.JERASURE"
+ [ngClass]="{'has-error': form.showError('packetSize', frm)}">
+ <label for="packetSize"
+ class="control-label col-sm-3">
+ <ng-container i18n>Packetsize</ng-container>
+ <cd-helper [html]="tooltips.plugins.jerasure.packetSize">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="number"
+ id="packetSize"
+ name="packetSize"
+ class="form-control"
+ placeholder="Packetsize..."
+ formControlName="packetSize">
+ <span class="help-block"
+ *ngIf="form.showError('packetSize', frm, 'min')"
+ i18n>Must be equal to or greater than 1.</span>
+ </div>
+ </div>
+
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('crushRoot', frm)}">
+ <label for="crushRoot"
+ class="control-label col-sm-3">
+ <ng-container i18n>Crush root</ng-container>
+ <cd-helper [html]="tooltips.crushRoot">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ id="crushRoot"
+ name="crushRoot"
+ class="form-control"
+ placeholder="root..."
+ formControlName="crushRoot">
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="crushDeviceClass"
+ class="control-label col-sm-3">
+ <ng-container i18n>Crush device class</ng-container>
+ <cd-helper [html]="tooltips.crushDeviceClass">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="crushDeviceClass"
+ name="crushDeviceClass"
+ formControlName="crushDeviceClass">
+ <option ngValue=""
+ i18n>any</option>
+ <option *ngFor="let deviceClass of devices"
+ [ngValue]="deviceClass">
+ {{ deviceClass }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="directory"
+ class="control-label col-sm-3">
+ <ng-container i18n>Directory</ng-container>
+ <cd-helper [html]="tooltips.directory">
+ </cd-helper>
+ </label>
+ <div class="col-sm-9">
+ <input type="text"
+ id="directory"
+ name="directory"
+ class="form-control"
+ placeholder="Path..."
+ formControlName="directory">
+ </div>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <cd-submit-button
+ (submitAction)="onSubmit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ [form]="frm">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"></cd-back-button>
+ </div>
+</form>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.spec.ts
new file mode 100644
index 00000000..9db51d4d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.spec.ts
@@ -0,0 +1,325 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ FixtureHelper,
+ FormHelper,
+ i18nProviders
+} from '../../../../testing/unit-test-helper';
+import { ErasureCodeProfileService } from '../../../shared/api/erasure-code-profile.service';
+import { ErasureCodeProfile } from '../../../shared/models/erasure-code-profile';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { PoolModule } from '../pool.module';
+import { ErasureCodeProfileFormComponent } from './erasure-code-profile-form.component';
+
+describe('ErasureCodeProfileFormComponent', () => {
+ let component: ErasureCodeProfileFormComponent;
+ let ecpService: ErasureCodeProfileService;
+ let fixture: ComponentFixture<ErasureCodeProfileFormComponent>;
+ let formHelper: FormHelper;
+ let fixtureHelper: FixtureHelper;
+ let data: {};
+
+ configureTestBed({
+ imports: [HttpClientTestingModule, RouterTestingModule, ToastrModule.forRoot(), PoolModule],
+ providers: [ErasureCodeProfileService, BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ErasureCodeProfileFormComponent);
+ fixtureHelper = new FixtureHelper(fixture);
+ component = fixture.componentInstance;
+ formHelper = new FormHelper(component.form);
+ ecpService = TestBed.get(ErasureCodeProfileService);
+ data = {
+ failure_domains: ['host', 'osd'],
+ plugins: ['isa', 'jerasure', 'shec', 'lrc'],
+ names: ['ecp1', 'ecp2'],
+ devices: ['ssd', 'hdd']
+ };
+ spyOn(ecpService, 'getInfo').and.callFake(() => of(data));
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('calls listing to get ecps on ngInit', () => {
+ expect(ecpService.getInfo).toHaveBeenCalled();
+ expect(component.names.length).toBe(2);
+ });
+
+ describe('form validation', () => {
+ it(`isn't valid if name is not set`, () => {
+ expect(component.form.invalid).toBeTruthy();
+ formHelper.setValue('name', 'someProfileName');
+ expect(component.form.valid).toBeTruthy();
+ });
+
+ it('sets name invalid', () => {
+ component.names = ['awesomeProfileName'];
+ formHelper.expectErrorChange('name', 'awesomeProfileName', 'uniqueName');
+ formHelper.expectErrorChange('name', 'some invalid text', 'pattern');
+ formHelper.expectErrorChange('name', null, 'required');
+ });
+
+ it('sets k to min error', () => {
+ formHelper.expectErrorChange('k', 0, 'min');
+ });
+
+ it('sets m to min error', () => {
+ formHelper.expectErrorChange('m', 0, 'min');
+ });
+
+ it(`should show all default form controls`, () => {
+ const showDefaults = (plugin) => {
+ formHelper.setValue('plugin', plugin);
+ fixtureHelper.expectIdElementsVisible(
+ [
+ 'name',
+ 'plugin',
+ 'k',
+ 'm',
+ 'crushFailureDomain',
+ 'crushRoot',
+ 'crushDeviceClass',
+ 'directory'
+ ],
+ true
+ );
+ };
+ showDefaults('jerasure');
+ showDefaults('shec');
+ showDefaults('lrc');
+ showDefaults('isa');
+ });
+
+ describe(`for 'jerasure' plugin (default)`, () => {
+ it(`requires 'm' and 'k'`, () => {
+ formHelper.expectErrorChange('k', null, 'required');
+ formHelper.expectErrorChange('m', null, 'required');
+ });
+
+ it(`should show 'packetSize' and 'technique'`, () => {
+ fixtureHelper.expectIdElementsVisible(['packetSize', 'technique'], true);
+ });
+
+ it(`should not show any other plugin specific form control`, () => {
+ fixtureHelper.expectIdElementsVisible(['c', 'l', 'crushLocality'], false);
+ });
+ });
+
+ describe(`for 'isa' plugin`, () => {
+ beforeEach(() => {
+ formHelper.setValue('plugin', 'isa');
+ });
+
+ it(`does not require 'm' and 'k'`, () => {
+ formHelper.setValue('k', null);
+ formHelper.expectValidChange('k', null);
+ formHelper.expectValidChange('m', null);
+ });
+
+ it(`should show 'technique'`, () => {
+ fixtureHelper.expectIdElementsVisible(['technique'], true);
+ expect(fixture.debugElement.query(By.css('#technique'))).toBeTruthy();
+ });
+
+ it(`should not show any other plugin specific form control`, () => {
+ fixtureHelper.expectIdElementsVisible(['c', 'l', 'crushLocality', 'packetSize'], false);
+ });
+ });
+
+ describe(`for 'lrc' plugin`, () => {
+ beforeEach(() => {
+ formHelper.setValue('plugin', 'lrc');
+ });
+
+ it(`requires 'm', 'l' and 'k'`, () => {
+ formHelper.expectErrorChange('k', null, 'required');
+ formHelper.expectErrorChange('m', null, 'required');
+ });
+
+ it(`should show 'l' and 'crushLocality'`, () => {
+ fixtureHelper.expectIdElementsVisible(['l', 'crushLocality'], true);
+ });
+
+ it(`should not show any other plugin specific form control`, () => {
+ fixtureHelper.expectIdElementsVisible(['c', 'packetSize', 'technique'], false);
+ });
+ });
+
+ describe(`for 'shec' plugin`, () => {
+ beforeEach(() => {
+ formHelper.setValue('plugin', 'shec');
+ });
+
+ it(`does not require 'm' and 'k'`, () => {
+ formHelper.expectValidChange('k', null);
+ formHelper.expectValidChange('m', null);
+ });
+
+ it(`should show 'c'`, () => {
+ fixtureHelper.expectIdElementsVisible(['c'], true);
+ });
+
+ it(`should not show any other plugin specific form control`, () => {
+ fixtureHelper.expectIdElementsVisible(
+ ['l', 'crushLocality', 'packetSize', 'technique'],
+ false
+ );
+ });
+ });
+ });
+
+ describe('submission', () => {
+ let ecp: ErasureCodeProfile;
+
+ const testCreation = () => {
+ fixture.detectChanges();
+ component.onSubmit();
+ expect(ecpService.create).toHaveBeenCalledWith(ecp);
+ };
+
+ beforeEach(() => {
+ ecp = new ErasureCodeProfile();
+ const taskWrapper = TestBed.get(TaskWrapperService);
+ spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough();
+ spyOn(ecpService, 'create').and.stub();
+ });
+
+ describe(`'jerasure' usage`, () => {
+ beforeEach(() => {
+ ecp.name = 'jerasureProfile';
+ });
+
+ it('should be able to create a profile with only required fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ ecp.m = 2;
+ testCreation();
+ });
+
+ it(`does not create with missing 'k' or invalid form`, () => {
+ ecp.k = 0;
+ formHelper.setMultipleValues(ecp, true);
+ component.onSubmit();
+ expect(ecpService.create).not.toHaveBeenCalled();
+ });
+
+ it('should be able to create a profile with m, k, name, directory and packetSize', () => {
+ ecp.m = 3;
+ ecp.directory = '/different/ecp/path';
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ formHelper.setValue('packetSize', 8192, true);
+ ecp.packetsize = 8192;
+ testCreation();
+ });
+
+ it('should not send the profile with unsupported fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ ecp.m = 2;
+ formHelper.setValue('crushLocality', 'osd', true);
+ testCreation();
+ });
+ });
+
+ describe(`'isa' usage`, () => {
+ beforeEach(() => {
+ ecp.name = 'isaProfile';
+ ecp.plugin = 'isa';
+ });
+
+ it('should be able to create a profile with only plugin and name', () => {
+ formHelper.setMultipleValues(ecp, true);
+ testCreation();
+ });
+
+ it('should send profile with plugin, name, failure domain and technique only', () => {
+ ecp.technique = 'cauchy';
+ formHelper.setMultipleValues(ecp, true);
+ formHelper.setValue('crushFailureDomain', 'osd', true);
+ ecp['crush-failure-domain'] = 'osd';
+ testCreation();
+ });
+
+ it('should not send the profile with unsupported fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ formHelper.setValue('packetSize', 'osd', true);
+ testCreation();
+ });
+ });
+
+ describe(`'lrc' usage`, () => {
+ beforeEach(() => {
+ ecp.name = 'lreProfile';
+ ecp.plugin = 'lrc';
+ });
+
+ it('should be able to create a profile with only required fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ ecp.m = 2;
+ ecp.l = 3;
+ testCreation();
+ });
+
+ it('should send profile with all required fields and crush root and locality', () => {
+ ecp.l = 8;
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ ecp.m = 2;
+ formHelper.setValue('crushLocality', 'osd', true);
+ formHelper.setValue('crushRoot', 'rack', true);
+ ecp['crush-locality'] = 'osd';
+ ecp['crush-root'] = 'rack';
+ testCreation();
+ });
+
+ it('should not send the profile with unsupported fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ ecp.k = 4;
+ ecp.m = 2;
+ ecp.l = 3;
+ formHelper.setValue('c', 4, true);
+ testCreation();
+ });
+ });
+
+ describe(`'shec' usage`, () => {
+ beforeEach(() => {
+ ecp.name = 'shecProfile';
+ ecp.plugin = 'shec';
+ });
+
+ it('should be able to create a profile with only plugin and name', () => {
+ formHelper.setMultipleValues(ecp, true);
+ testCreation();
+ });
+
+ it('should send profile with plugin, name, c and crush device class only', () => {
+ ecp.c = 4;
+ formHelper.setMultipleValues(ecp, true);
+ formHelper.setValue('crushDeviceClass', 'ssd', true);
+ ecp['crush-device-class'] = 'ssd';
+ testCreation();
+ });
+
+ it('should not send the profile with unsupported fields', () => {
+ formHelper.setMultipleValues(ecp, true);
+ formHelper.setValue('l', 8, true);
+ testCreation();
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.ts
new file mode 100644
index 00000000..d707bf90
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.ts
@@ -0,0 +1,259 @@
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { ErasureCodeProfileService } from '../../../shared/api/erasure-code-profile.service';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { ErasureCodeProfile } from '../../../shared/models/erasure-code-profile';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+
+@Component({
+ selector: 'cd-erasure-code-profile-form',
+ templateUrl: './erasure-code-profile-form.component.html',
+ styleUrls: ['./erasure-code-profile-form.component.scss']
+})
+export class ErasureCodeProfileFormComponent implements OnInit {
+ @Output()
+ submitAction = new EventEmitter();
+
+ form: CdFormGroup;
+ failureDomains: string[];
+ plugins: string[];
+ names: string[];
+ techniques: string[];
+ requiredControls: string[] = [];
+ devices: string[] = [];
+ tooltips = this.ecpService.formTooltips;
+
+ PLUGIN = {
+ LRC: 'lrc', // Locally Repairable Erasure Code
+ SHEC: 'shec', // Shingled Erasure Code
+ JERASURE: 'jerasure', // default
+ ISA: 'isa' // Intel Storage Acceleration
+ };
+ plugin = this.PLUGIN.JERASURE;
+ action: string;
+ resource: string;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ public bsModalRef: BsModalRef,
+ private taskWrapper: TaskWrapperService,
+ private ecpService: ErasureCodeProfileService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.action = this.actionLabels.CREATE;
+ this.resource = this.i18n('EC Profile');
+ this.createForm();
+ this.setJerasureDefaults();
+ }
+
+ createForm() {
+ this.form = this.formBuilder.group({
+ name: [
+ null,
+ [
+ Validators.required,
+ Validators.pattern('[A-Za-z0-9_-]+'),
+ CdValidators.custom(
+ 'uniqueName',
+ (value) => this.names && this.names.indexOf(value) !== -1
+ )
+ ]
+ ],
+ plugin: [this.PLUGIN.JERASURE, [Validators.required]],
+ k: [1], // Will be replaced by plugin defaults
+ m: [1], // Will be replaced by plugin defaults
+ crushFailureDomain: ['host'],
+ crushRoot: ['default'], // default for all - is a list possible???
+ crushDeviceClass: [''], // set none to empty at submit - get list from configs?
+ directory: [''],
+ // Only for 'jerasure' and 'isa' use
+ technique: ['reed_sol_van'],
+ // Only for 'jerasure' use
+ packetSize: [2048, [Validators.min(1)]],
+ // Only for 'lrc' use
+ l: [1, [Validators.required, Validators.min(1)]],
+ crushLocality: [''], // set to none at the end (same list as for failure domains)
+ // Only for 'shec' use
+ c: [1, [Validators.required, Validators.min(1)]]
+ });
+ this.form.get('plugin').valueChanges.subscribe((plugin) => this.onPluginChange(plugin));
+ }
+
+ onPluginChange(plugin) {
+ this.plugin = plugin;
+ if (plugin === this.PLUGIN.JERASURE) {
+ this.setJerasureDefaults();
+ } else if (plugin === this.PLUGIN.LRC) {
+ this.setLrcDefaults();
+ } else if (plugin === this.PLUGIN.ISA) {
+ this.setIsaDefaults();
+ } else if (plugin === this.PLUGIN.SHEC) {
+ this.setShecDefaults();
+ }
+ }
+
+ private setNumberValidators(name: string, required: boolean) {
+ const validators = [Validators.min(1)];
+ if (required) {
+ validators.push(Validators.required);
+ }
+ this.form.get(name).setValidators(validators);
+ }
+
+ private setKMValidators(required: boolean) {
+ ['k', 'm'].forEach((name) => this.setNumberValidators(name, required));
+ }
+
+ private setJerasureDefaults() {
+ this.requiredControls = ['k', 'm'];
+ this.setDefaults({
+ k: 4,
+ m: 2
+ });
+ this.setKMValidators(true);
+ this.techniques = [
+ 'reed_sol_van',
+ 'reed_sol_r6_op',
+ 'cauchy_orig',
+ 'cauchy_good',
+ 'liberation',
+ 'blaum_roth',
+ 'liber8tion'
+ ];
+ }
+
+ private setLrcDefaults() {
+ this.requiredControls = ['k', 'm', 'l'];
+ this.setKMValidators(true);
+ this.setNumberValidators('l', true);
+ this.setDefaults({
+ k: 4,
+ m: 2,
+ l: 3
+ });
+ }
+
+ private setIsaDefaults() {
+ this.requiredControls = [];
+ this.setKMValidators(false);
+ this.setDefaults({
+ k: 7,
+ m: 3
+ });
+ this.techniques = ['reed_sol_van', 'cauchy'];
+ }
+
+ private setShecDefaults() {
+ this.requiredControls = [];
+ this.setKMValidators(false);
+ this.setDefaults({
+ k: 4,
+ m: 3,
+ c: 2
+ });
+ }
+
+ private setDefaults(defaults: object) {
+ Object.keys(defaults).forEach((controlName) => {
+ if (this.form.get(controlName).pristine) {
+ this.form.silentSet(controlName, defaults[controlName]);
+ }
+ });
+ }
+
+ ngOnInit() {
+ this.ecpService
+ .getInfo()
+ .subscribe(
+ ({
+ failure_domains,
+ plugins,
+ names,
+ directory,
+ devices
+ }: {
+ failure_domains: string[];
+ plugins: string[];
+ names: string[];
+ directory: string;
+ devices: string[];
+ }) => {
+ this.failureDomains = failure_domains;
+ this.plugins = plugins;
+ this.names = names;
+ this.devices = devices;
+ this.form.silentSet('directory', directory);
+ }
+ );
+ }
+
+ private createJson() {
+ const pluginControls = {
+ technique: [this.PLUGIN.ISA, this.PLUGIN.JERASURE],
+ packetSize: [this.PLUGIN.JERASURE],
+ l: [this.PLUGIN.LRC],
+ crushLocality: [this.PLUGIN.LRC],
+ c: [this.PLUGIN.SHEC]
+ };
+ const ecp = new ErasureCodeProfile();
+ const plugin = this.form.getValue('plugin');
+ Object.keys(this.form.controls)
+ .filter((name) => {
+ const pluginControl = pluginControls[name];
+ const control = this.form.get(name);
+ const usable = (pluginControl && pluginControl.includes(plugin)) || !pluginControl;
+ return (
+ usable &&
+ (control.dirty || this.requiredControls.includes(name)) &&
+ this.form.getValue(name)
+ );
+ })
+ .forEach((name) => {
+ this.extendJson(name, ecp);
+ });
+ return ecp;
+ }
+
+ private extendJson(name: string, ecp: ErasureCodeProfile) {
+ const differentApiAttributes = {
+ crushFailureDomain: 'crush-failure-domain',
+ crushRoot: 'crush-root',
+ crushDeviceClass: 'crush-device-class',
+ packetSize: 'packetsize',
+ crushLocality: 'crush-locality'
+ };
+ ecp[differentApiAttributes[name] || name] = this.form.getValue(name);
+ }
+
+ onSubmit() {
+ if (this.form.invalid) {
+ this.form.setErrors({ cdSubmitButton: true });
+ return;
+ }
+ const profile = this.createJson();
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('ecp/create', { name: profile.name }),
+ call: this.ecpService.create(profile)
+ })
+ .subscribe(
+ undefined,
+ () => {
+ this.form.setErrors({ cdSubmitButton: true });
+ },
+ () => {
+ this.bsModalRef.hide();
+ this.submitAction.emit(profile);
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.html
new file mode 100644
index 00000000..db33fad7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.html
@@ -0,0 +1,34 @@
+<tabset #tabsetChild
+ cdTableDetail
+ *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <cd-table-key-value [renderObjects]="true"
+ [data]="filterNonPoolData(selection.first())"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ <tab i18n-heading
+ *ngIf="permissions.grafana.read"
+ heading="Performance Details">
+ <cd-grafana [grafanaPath]="'ceph-pool-detail?var-pool_name='
+ + selection.first()['pool_name']"
+ uid="-xyV8KCiz"
+ grafanaStyle="one">
+ </cd-grafana>
+ </tab>
+ <tab *ngIf="selection.first().type === 'replicated'"
+ i18n-heading
+ heading="Configuration">
+ <cd-rbd-configuration-table [data]="selectedPoolConfiguration"></cd-rbd-configuration-table>
+ </tab>
+ <tab i18n-heading
+ *ngIf="selection.first()['tiers'].length > 0"
+ heading="Cache Tiers Details">
+ <cd-table [data]="cacheTiers"
+ [columns]="cacheTierColumns"
+ [autoSave]="false"
+ columnMode="flex">
+ </cd-table>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.spec.ts
new file mode 100644
index 00000000..4bf43944
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.spec.ts
@@ -0,0 +1,102 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabsetComponent, TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { AppModule } from '../../../app.module';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../shared/models/permissions';
+import { RbdConfigurationListComponent } from '../../block/rbd-configuration-list/rbd-configuration-list.component';
+import { PoolDetailsComponent } from './pool-details.component';
+
+describe('PoolDetailsComponent', () => {
+ let poolDetailsComponent: PoolDetailsComponent;
+ let fixture: ComponentFixture<PoolDetailsComponent>;
+
+ configureTestBed({
+ imports: [TabsModule.forRoot(), AppModule],
+ declarations: [PoolDetailsComponent, RbdConfigurationListComponent],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PoolDetailsComponent);
+ poolDetailsComponent = fixture.componentInstance;
+ poolDetailsComponent.selection = new CdTableSelection();
+ poolDetailsComponent.permissions = new Permissions({
+ grafana: ['read']
+ });
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(poolDetailsComponent).toBeTruthy();
+ });
+
+ describe('Pool details tabset', () => {
+ beforeEach(() => {
+ poolDetailsComponent.selection.selected = [
+ {
+ tiers: [0],
+ pool: 0
+ }
+ ];
+ poolDetailsComponent.selection.update();
+ });
+
+ it('should recognize a tabset child', () => {
+ fixture.detectChanges();
+ const tabsetChild: TabsetComponent = poolDetailsComponent.tabsetChild;
+ expect(tabsetChild).toBeDefined();
+ });
+
+ it('should show "Cache Tiers Details" tab if selected pool has "tiers"', () => {
+ fixture.detectChanges();
+ const tabs = poolDetailsComponent.tabsetChild.tabs;
+ expect(tabs.length).toBe(3);
+ expect(tabs[2].heading).toBe('Cache Tiers Details');
+ expect(tabs[0].active).toBeTruthy();
+ });
+
+ it('should not show "Cache Tiers Details" tab if selected pool has no "tiers"', () => {
+ poolDetailsComponent.selection.selected = [
+ {
+ tiers: []
+ }
+ ];
+ poolDetailsComponent.selection.update();
+ fixture.detectChanges();
+ const tabs = poolDetailsComponent.tabsetChild.tabs;
+ expect(tabs.length).toEqual(2);
+ expect(tabs[0].active).toBeTruthy();
+ });
+
+ it('current active status of tabs should not change when selection is the same as previous selection', () => {
+ fixture.detectChanges();
+ const tabs = poolDetailsComponent.tabsetChild.tabs;
+ expect(tabs[0].active).toBeTruthy();
+
+ tabs[1].active = true;
+ fixture.detectChanges();
+ expect(tabs[1].active).toBeTruthy();
+ });
+
+ it('returns pool details correctly', () => {
+ const pool = { prop1: 1, cdIsBinary: true, prop2: 2, cdExecuting: true, prop3: 3 };
+ const expectedPool = { prop1: 1, prop2: 2, prop3: 3 };
+
+ expect(poolDetailsComponent.filterNonPoolData(pool)).toEqual(expectedPool);
+ });
+
+ it('pool data filtering is called', () => {
+ const filterNonPoolDataSpy = spyOn(
+ poolDetailsComponent,
+ 'filterNonPoolData'
+ ).and.callThrough();
+
+ fixture.detectChanges();
+
+ expect(filterNonPoolDataSpy).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.ts
new file mode 100644
index 00000000..fed286e6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-details/pool-details.component.ts
@@ -0,0 +1,77 @@
+import { Component, Input, OnChanges, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { TabsetComponent } from 'ngx-bootstrap/tabs';
+
+import { PoolService } from '../../../shared/api/pool.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { RbdConfigurationEntry } from '../../../shared/models/configuration';
+import { Permissions } from '../../../shared/models/permissions';
+
+@Component({
+ selector: 'cd-pool-details',
+ templateUrl: './pool-details.component.html',
+ styleUrls: ['./pool-details.component.scss']
+})
+export class PoolDetailsComponent implements OnChanges {
+ cacheTierColumns: Array<CdTableColumn> = [];
+
+ @Input()
+ selection: CdTableSelection;
+ @Input()
+ permissions: Permissions;
+ @Input()
+ cacheTiers: any[];
+ @ViewChild(TabsetComponent)
+ tabsetChild: TabsetComponent;
+ selectedPoolConfiguration: RbdConfigurationEntry[];
+
+ constructor(private i18n: I18n, private poolService: PoolService) {
+ this.cacheTierColumns = [
+ {
+ prop: 'pool_name',
+ name: this.i18n('Name'),
+ flexGrow: 3
+ },
+ {
+ prop: 'cache_mode',
+ name: this.i18n('Cache Mode'),
+ flexGrow: 2
+ },
+ {
+ prop: 'cache_min_evict_age',
+ name: this.i18n('Min Evict Age'),
+ flexGrow: 2
+ },
+ {
+ prop: 'cache_min_flush_age',
+ name: this.i18n('Min Flush Age'),
+ flexGrow: 2
+ },
+ {
+ prop: 'target_max_bytes',
+ name: this.i18n('Target Max Bytes'),
+ flexGrow: 2
+ },
+ {
+ prop: 'target_max_objects',
+ name: this.i18n('Target Max Objects'),
+ flexGrow: 2
+ }
+ ];
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSingleSelection) {
+ this.poolService.getConfiguration(this.selection.first().pool_name).subscribe((poolConf) => {
+ this.selectedPoolConfiguration = poolConf;
+ });
+ }
+ }
+
+ filterNonPoolData(pool: object): object {
+ return _.omit(pool, ['cdExecuting', 'cdIsBinary']);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form-data.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form-data.ts
new file mode 100644
index 00000000..f6036b6f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form-data.ts
@@ -0,0 +1,46 @@
+import { Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { SelectMessages } from '../../../shared/components/select/select-messages.model';
+import { SelectOption } from '../../../shared/components/select/select-option.model';
+import { Pool } from '../pool';
+
+export class PoolFormData {
+ poolTypes: string[];
+ erasureInfo = false;
+ crushInfo = false;
+ applications: any;
+
+ constructor(i18n: I18n) {
+ this.poolTypes = ['erasure', 'replicated'];
+ this.applications = {
+ selected: [],
+ available: [
+ new SelectOption(false, 'cephfs', ''),
+ new SelectOption(false, 'rbd', ''),
+ new SelectOption(false, 'rgw', '')
+ ],
+ validators: [Validators.pattern('[A-Za-z0-9_]+'), Validators.maxLength(128)],
+ messages: new SelectMessages(
+ {
+ empty: i18n('No applications added'),
+ selectionLimit: {
+ text: i18n('Applications limit reached'),
+ tooltip: i18n('A pool can only have up to four applications definitions.')
+ },
+ customValidations: {
+ pattern: i18n(`Allowed characters '_a-zA-Z0-9'`),
+ maxlength: i18n('Maximum length is 128 characters')
+ },
+ filter: i18n('Filter or add applications'),
+ add: i18n('Add application')
+ },
+ i18n
+ )
+ };
+ }
+
+ pgs = 1;
+ pool: Pool; // Only available during edit mode
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html
new file mode 100644
index 00000000..ad9dca78
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html
@@ -0,0 +1,459 @@
+<div class="col-sm-12 col-lg-6">
+ <h1 *ngIf="!(info && ecProfiles)"
+ class="jumbotron">
+ <i class="fa fa-lg fa-pulse fa-spinner text-primary"></i>
+ <ng-container i18n>Loading...</ng-container>
+ </h1>
+ <form name="form"
+ *ngIf="info && ecProfiles"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="form"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+
+ <div class="panel-body">
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('name', formDir)}">
+ <label class="control-label col-sm-3"
+ for="name">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="name"
+ name="name"
+ type="text"
+ class="form-control"
+ placeholder="Name..."
+ i18n-placeholder
+ formControlName="name"
+ autofocus>
+ <span class="help-block"
+ *ngIf="form.showError('name', formDir, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('name', formDir, 'uniqueName')"
+ i18n>The chosen Ceph pool name is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Pool type selection -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('poolType', formDir)}">
+ <label class="control-label col-sm-3"
+ for="poolType">
+ <ng-container i18n>Pool type</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="poolType"
+ formControlName="poolType"
+ name="poolType">
+ <option ngValue=""
+ i18n>-- Select a pool type --</option>
+ <option *ngFor="let poolType of data.poolTypes"
+ [value]="poolType">
+ {{ poolType }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="form.showError('poolType', formDir, 'required')"
+ i18n>This field is required!</span>
+ </div>
+ </div>
+
+ <div *ngIf="form.getValue('poolType')">
+ <!-- Pg number -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('pgNum', formDir)}">
+ <label class="control-label col-sm-3"
+ for="pgNum">
+ <ng-container i18n>Placement groups</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ id="pgNum"
+ name="pgNum"
+ formControlName="pgNum"
+ min="1"
+ type="number"
+ (focus)="externalPgChange = false"
+ (blur)="alignPgs()"
+ required>
+ <span class="help-block"
+ *ngIf="form.showError('pgNum', formDir, 'required')"
+ i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="form.showError('pgNum', formDir, 'min')"
+ i18n>At least one placement group is needed!</span>
+ <span class="help-block"
+ *ngIf="form.showError('pgNum', formDir, '34')"
+ i18n>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</span>
+ <span class="help-block">
+ <a i18n
+ target="_blank"
+ href="http://ceph.com/pgcalc">Calculation help</a>
+ </span>
+ <span class="help-block"
+ *ngIf="externalPgChange"
+ i18n>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</span>
+ </div>
+ </div>
+
+ <!-- Crush ruleset selection -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('crushRule', formDir)}"
+ *ngIf="form.getValue('poolType') && current.rules.length > 0">
+ <label class="control-label col-sm-3"
+ for="crushRule"
+ i18n>Crush ruleset</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <select class="form-control"
+ id="crushRule"
+ formControlName="crushRule"
+ name="crushSet">
+ <option [ngValue]="null"
+ i18n>-- Select a crush rule --</option>
+ <option *ngFor="let rule of current.rules"
+ [ngValue]="rule">
+ {{ rule.rule_name }}
+ </option>
+ </select>
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ [ngClass]="{'active': data.crushInfo}"
+ id="crush-info-button"
+ type="button"
+ (click)="data.crushInfo = !data.crushInfo">
+ <i class="fa fa-question-circle"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ id="crush-info-block"
+ *ngIf="data.crushInfo && form.getValue('crushRule')">
+ <tabset>
+ <tab i18n-heading heading="Crush rule" class="crush-rule-info">
+ <cd-table-key-value [renderObjects]="true"
+ [data]="form.getValue('crushRule')"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ <tab i18n-heading heading="Crush steps" class="crush-rule-steps">
+ <ol>
+ <li *ngFor="let step of form.get('crushRule').value.steps">
+ {{ describeCrushStep(step) }}
+ </li>
+ </ol>
+ </tab>
+ </tabset>
+ </span>
+ <span class="help-block"
+ *ngIf="form.showError('crushRule', formDir, 'tooFewOsds')"
+ i18n>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</span>
+ </div>
+ </div>
+
+ <!-- Replica Size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('size', formDir)}"
+ *ngIf="form.getValue('poolType') === 'replicated'">
+ <label class="control-label col-sm-3"
+ for="size">
+ <ng-container i18n>Replicated size</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ id="size"
+ [max]="getMaxSize()"
+ [min]="getMinSize()"
+ name="size"
+ type="number"
+ formControlName="size">
+ <span class="help-block"
+ *ngIf="form.showError('size', formDir)">
+ <ul class="list-inline">
+ <li i18n>Minimum: {{ getMinSize() }}</li>
+ <li i18n>Maximum: {{ getMaxSize() }}</li>
+ </ul>
+ </span>
+ <span class="help-block"
+ *ngIf="form.showError('size', formDir)"
+ i18n>The size specified is out of range. A value from
+ {{ getMinSize() }} to {{ getMaxSize() }} is valid.</span>
+ </div>
+ </div>
+
+ <!-- Erasure Profile select -->
+ <div class="form-group"
+ *ngIf="form.getValue('poolType') === 'erasure'">
+ <label i18n
+ class="control-label col-sm-3"
+ for="erasureProfile">Erasure code profile</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <select class="form-control"
+ id="erasureProfile"
+ name="erasureProfile"
+ formControlName="erasureProfile">
+ <option *ngIf="!ecProfiles"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngIf="ecProfiles && ecProfiles.length === 0"
+ [ngValue]="null"
+ i18n>-- No erasure code profile available --</option>
+ <option *ngIf="ecProfiles && ecProfiles.length > 0"
+ [ngValue]="null"
+ i18n>-- Select an erasure code profile --</option>
+ <option *ngFor="let ecp of ecProfiles"
+ [ngValue]="ecp">
+ {{ ecp.name }}
+ </option>
+ </select>
+ <span class="input-group-btn">
+ <button class="btn btn-default"
+ [ngClass]="{'active': data.erasureInfo}"
+ id="ecp-info-button"
+ type="button"
+ (click)="data.erasureInfo = !data.erasureInfo">
+ <i class="fa fa-question-circle"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-default"
+ type="button"
+ [disabled]="editing"
+ (click)="addErasureCodeProfile()">
+ <i class="fa fa-plus"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-default"
+ type="button"
+ (click)="deleteErasureCodeProfile()"
+ [disabled]="editing || ecProfiles.length < 1">
+ <i class="fa fa-trash-o"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ id="ecp-info-block"
+ *ngIf="data.erasureInfo && form.getValue('erasureProfile')">
+ <cd-table-key-value [renderObjects]="true"
+ [data]="form.getValue('erasureProfile')"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </span>
+ </div>
+ </div>
+
+ <!-- Flags -->
+ <div class="form-group"
+ *ngIf="info.is_all_bluestore && form.getValue('poolType') === 'erasure'">
+ <label i18n
+ class="control-label col-sm-3">Flags</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <div class="checkbox checkbox-primary">
+ <input id="ec-overwrites"
+ type="checkbox"
+ formControlName="ecOverwrites">
+ <label for="ec-overwrites"
+ i18n>EC Overwrites</label>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <!-- Applications -->
+ <div class="form-group">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="applications">Applications</label>
+ <div class="col-sm-9">
+ <span class="form-control no-border full-height">
+ <cd-select-badges id="applications"
+ [customBadges]="true"
+ [customBadgeValidators]="data.applications.validators"
+ [messages]="data.applications.messages"
+ [data]="data.applications.selected"
+ [options]="data.applications.available"
+ [selectionLimit]="4"
+ (selection)="appSelection()">
+ </cd-select-badges>
+ </span>
+ </div>
+ </div>
+
+ <!-- Compression -->
+ <div *ngIf="info.is_all_bluestore"
+ formGroupName="compression">
+ <legend i18n>Compression</legend>
+
+ <!-- Compression Mode -->
+ <div class="form-group">
+ <label i18n
+ class="control-label col-sm-3"
+ for="mode">Mode</label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="mode"
+ name="mode"
+ formControlName="mode">
+ <option *ngFor="let mode of info.compression_modes"
+ [value]="mode">
+ {{ mode }}
+ </option>
+ </select>
+ </div>
+ </div>
+ <div *ngIf="hasCompressionEnabled()">
+ <!-- Compression algorithm selection -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('algorithm', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="algorithm">Algorithm</label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ id="algorithm"
+ name="algorithm"
+ formControlName="algorithm">
+ <option *ngIf="!info.compression_algorithms"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngIf="info.compression_algorithms && info.compression_algorithms.length === 0"
+ i18n
+ ngValue="">-- No erasure compression algorithm available --</option>
+ <option *ngFor="let algorithm of info.compression_algorithms"
+ [value]="algorithm">
+ {{ algorithm }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <!-- Compression min blob size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('minBlobSize', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="minBlobSize">Minimum blob size</label>
+ <div class="col-sm-9">
+ <input id="minBlobSize"
+ name="minBlobSize"
+ formControlName="minBlobSize"
+ type="text"
+ min="0"
+ class="form-control"
+ i18n-placeholder
+ placeholder="e.g., 128KiB"
+ defaultUnit="KiB"
+ cdDimlessBinary>
+ <span class="help-block"
+ *ngIf="form.showError('minBlobSize', formDir, 'min')"
+ i18n>Value should be greater than 0</span>
+ <span class="help-block"
+ *ngIf="form.showError('minBlobSize', formDir, 'maximum')"
+ i18n>Value should be less than the maximum blob size</span>
+ </div>
+ </div>
+
+ <!-- Compression max blob size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('maxBlobSize', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="maxBlobSize">Maximum blob size</label>
+ <div class="col-sm-9">
+ <input id="maxBlobSize"
+ type="text"
+ min="0"
+ formControlName="maxBlobSize"
+ class="form-control"
+ i18n-placeholder
+ placeholder="e.g., 512KiB"
+ defaultUnit="KiB"
+ cdDimlessBinary>
+ <span class="help-block"
+ *ngIf="form.showError('maxBlobSize', formDir, 'min')"
+ i18n>Value should be greater than 0</span>
+ <span class="help-block"
+ *ngIf="form.showError('maxBlobSize', formDir, 'minimum')"
+ i18n>Value should be greater than the minimum blob size</span>
+ </div>
+ </div>
+
+ <!-- Compression ratio -->
+ <div class="form-group"
+ [ngClass]="{'has-error': form.showError('ratio', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="ratio">Ratio</label>
+ <div class="col-sm-9">
+ <input id="ratio"
+ name="ratio"
+ formControlName="ratio"
+ type="number"
+ min="0"
+ max="1"
+ step="0.1"
+ class="form-control"
+ i18n-placeholder
+ placeholder="Compression ratio">
+ <span class="help-block"
+ *ngIf="form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
+ i18n>Value should be between 0.0 and 1.0</span>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+ <!-- Pool configuration -->
+ <div [hidden]="form.get('poolType').value !== 'replicated' || data.applications.selected.indexOf('rbd') === -1">
+ <cd-rbd-configuration-form [form]="form"
+ [initializeData]="initializeConfigData"
+ (changes)="currentConfigurationValues = $event()">
+ </cd-rbd-configuration-form>
+ </div>
+
+ <div class="form-group has-error">
+ <div class="col-sm-offset-3 col-sm-9"
+ *ngIf="form.hasError('rbdPool')">
+ <br>
+ <span class="help-block"
+ i18n>It's not possible to create an RBD pool with '/' in the name.</span>
+ <span class="help-block"
+ i18n>Please change the name or remove 'rbd' from the applications list.</span>
+ </div>
+ </div>
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir"
+ type="button"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ (submitAction)="submit()">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+
+ </div>
+
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.scss
new file mode 100644
index 00000000..29a4cf72
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.scss
@@ -0,0 +1,3 @@
+.crush-rule-steps {
+ margin-top: 10px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts
new file mode 100644
index 00000000..95ee1eb3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts
@@ -0,0 +1,1140 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AbstractControl } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { ActivatedRoute, Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ FixtureHelper,
+ FormHelper,
+ i18nProviders
+} from '../../../../testing/unit-test-helper';
+import { NotFoundComponent } from '../../../core/not-found/not-found.component';
+import { ErasureCodeProfileService } from '../../../shared/api/erasure-code-profile.service';
+import { PoolService } from '../../../shared/api/pool.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { SelectBadgesComponent } from '../../../shared/components/select-badges/select-badges.component';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CrushRule } from '../../../shared/models/crush-rule';
+import { ErasureCodeProfile } from '../../../shared/models/erasure-code-profile';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { Pool } from '../pool';
+import { PoolModule } from '../pool.module';
+import { PoolFormComponent } from './pool-form.component';
+
+describe('PoolFormComponent', () => {
+ const OSDS = 8;
+ let formHelper: FormHelper;
+ let fixtureHelper: FixtureHelper;
+ let component: PoolFormComponent;
+ let fixture: ComponentFixture<PoolFormComponent>;
+ let poolService: PoolService;
+ let form: CdFormGroup;
+ let router: Router;
+ let ecpService: ErasureCodeProfileService;
+
+ const setPgNum = (pgs): AbstractControl => {
+ const control = formHelper.setValue('pgNum', pgs);
+ fixture.debugElement.query(By.css('#pgNum')).nativeElement.dispatchEvent(new Event('blur'));
+ return control;
+ };
+
+ const testPgUpdate = (pgs, jump, returnValue) => {
+ if (pgs) {
+ setPgNum(pgs);
+ }
+ if (jump) {
+ setPgNum(form.getValue('pgNum') + jump);
+ }
+ expect(form.getValue('pgNum')).toBe(returnValue);
+ };
+
+ const createCrushRule = ({
+ id = 0,
+ name = 'somePoolName',
+ min = 1,
+ max = 10,
+ type = 'replicated'
+ }: {
+ max?: number;
+ min?: number;
+ id?: number;
+ name?: string;
+ type?: string;
+ }) => {
+ const typeNumber = type === 'erasure' ? 3 : 1;
+ const rule = new CrushRule();
+ rule.max_size = max;
+ rule.min_size = min;
+ rule.rule_id = id;
+ rule.ruleset = typeNumber;
+ rule.rule_name = name;
+ rule.steps = [
+ {
+ item_name: 'default',
+ item: -1,
+ op: 'take'
+ },
+ {
+ num: 0,
+ type: 'osd',
+ op: 'choose_firstn'
+ },
+ {
+ op: 'emit'
+ }
+ ];
+ component.info['crush_rules_' + type].push(rule);
+ return rule;
+ };
+
+ const expectValidSubmit = (
+ pool: any,
+ taskName: string,
+ poolServiceMethod: 'create' | 'update'
+ ) => {
+ spyOn(poolService, poolServiceMethod).and.stub();
+ const taskWrapper = TestBed.get(TaskWrapperService);
+ spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough();
+ component.submit();
+ expect(poolService[poolServiceMethod]).toHaveBeenCalledWith(pool);
+ expect(taskWrapper.wrapTaskAroundCall).toHaveBeenCalledWith({
+ task: {
+ name: taskName,
+ metadata: {
+ pool_name: pool.pool
+ }
+ },
+ call: undefined // because of stub
+ });
+ };
+
+ const setUpPoolComponent = () => {
+ fixture = TestBed.createComponent(PoolFormComponent);
+ fixtureHelper = new FixtureHelper(fixture);
+ component = fixture.componentInstance;
+ component.info = {
+ pool_names: [],
+ osd_count: OSDS,
+ is_all_bluestore: true,
+ bluestore_compression_algorithm: 'snappy',
+ compression_algorithms: ['snappy'],
+ compression_modes: ['none', 'passive'],
+ crush_rules_replicated: [],
+ crush_rules_erasure: [],
+ pg_autoscale_default_mode: 'off',
+ pg_autoscale_modes: ['off', 'warn', 'on']
+ };
+ const ecp1 = new ErasureCodeProfile();
+ ecp1.name = 'ecp1';
+ component.ecProfiles = [ecp1];
+ form = component.form;
+ formHelper = new FormHelper(form);
+ };
+
+ const routes: Routes = [{ path: '404', component: NotFoundComponent }];
+
+ configureTestBed({
+ declarations: [NotFoundComponent],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule.withRoutes(routes),
+ ToastrModule.forRoot(),
+ TabsModule.forRoot(),
+ PoolModule
+ ],
+ providers: [
+ ErasureCodeProfileService,
+ SelectBadgesComponent,
+ { provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } },
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ setUpPoolComponent();
+ poolService = TestBed.get(PoolService);
+ spyOn(poolService, 'getInfo').and.callFake(() => [component.info]);
+ ecpService = TestBed.get(ErasureCodeProfileService);
+ spyOn(ecpService, 'list').and.callFake(() => [component.ecProfiles]);
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate').and.stub();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('redirect not allowed users', () => {
+ let poolPermissions: Permission;
+ let authStorageService: AuthStorageService;
+
+ const testForRedirect = (times: number) => {
+ component.authenticate();
+ expect(router.navigate).toHaveBeenCalledTimes(times);
+ };
+
+ beforeEach(() => {
+ poolPermissions = {
+ create: false,
+ update: false,
+ read: false,
+ delete: false
+ };
+ authStorageService = TestBed.get(AuthStorageService);
+ spyOn(authStorageService, 'getPermissions').and.callFake(() => ({
+ pool: poolPermissions
+ }));
+ });
+
+ it('navigates to 404 if not allowed', () => {
+ component.authenticate();
+ expect(router.navigate).toHaveBeenCalledWith(['/404']);
+ });
+
+ it('navigates if user is not allowed', () => {
+ testForRedirect(1);
+ poolPermissions.read = true;
+ testForRedirect(2);
+ poolPermissions.delete = true;
+ testForRedirect(3);
+ poolPermissions.update = true;
+ testForRedirect(4);
+ component.editing = true;
+ poolPermissions.update = false;
+ poolPermissions.create = true;
+ testForRedirect(5);
+ });
+
+ it('does not navigate users with right permissions', () => {
+ poolPermissions.read = true;
+ poolPermissions.create = true;
+ testForRedirect(0);
+ component.editing = true;
+ poolPermissions.update = true;
+ testForRedirect(0);
+ poolPermissions.create = false;
+ testForRedirect(0);
+ });
+ });
+
+ describe('pool form validation', () => {
+ beforeEach(() => {
+ fixture.detectChanges();
+ });
+
+ it('is invalid at the beginning all sub forms are valid', () => {
+ expect(form.valid).toBeFalsy();
+ ['name', 'poolType', 'pgNum'].forEach((name) => formHelper.expectError(name, 'required'));
+ ['crushRule', 'size', 'erasureProfile', 'ecOverwrites'].forEach((name) =>
+ formHelper.expectValid(name)
+ );
+ expect(component.form.get('compression').valid).toBeTruthy();
+ });
+
+ it('validates name', () => {
+ expect(component.editing).toBeFalsy();
+ formHelper.expectError('name', 'required');
+ formHelper.expectValidChange('name', 'some-name');
+ formHelper.expectValidChange('name', 'name/with/slash');
+ component.info.pool_names.push('someExistingPoolName');
+ formHelper.expectErrorChange('name', 'someExistingPoolName', 'uniqueName');
+ formHelper.expectErrorChange('name', 'wrong format with spaces', 'pattern');
+ });
+
+ it('should validate with dots in pool name', () => {
+ formHelper.expectValidChange('name', 'pool.default.bar', true);
+ });
+
+ it('validates poolType', () => {
+ formHelper.expectError('poolType', 'required');
+ formHelper.expectValidChange('poolType', 'erasure');
+ formHelper.expectValidChange('poolType', 'replicated');
+ });
+
+ it('validates that pgNum is required creation mode', () => {
+ formHelper.expectError(form.get('pgNum'), 'required');
+ });
+
+ it('validates pgNum in edit mode', () => {
+ component.data.pool = new Pool('test');
+ component.data.pool.pg_num = 16;
+ component.editing = true;
+ component.ngOnInit(); // Switches form into edit mode
+ formHelper.setValue('poolType', 'erasure');
+ fixture.detectChanges();
+ formHelper.expectValid(setPgNum('8'));
+ });
+
+ it('is valid if pgNum, poolType and name are valid', () => {
+ formHelper.setValue('name', 'some-name');
+ formHelper.setValue('poolType', 'erasure');
+ fixture.detectChanges();
+ setPgNum(1);
+ expect(form.valid).toBeTruthy();
+ });
+
+ it('validates crushRule', () => {
+ formHelper.expectValid('crushRule');
+ formHelper.expectErrorChange('crushRule', { min_size: 20 }, 'tooFewOsds');
+ });
+
+ it('validates size', () => {
+ formHelper.setValue('poolType', 'replicated');
+ formHelper.expectValid('size');
+ formHelper.setValue('crushRule', {
+ min_size: 2,
+ max_size: 6
+ });
+ formHelper.expectErrorChange('size', 1, 'min');
+ formHelper.expectErrorChange('size', 8, 'max');
+ formHelper.expectValidChange('size', 6);
+ });
+
+ it('validates compression mode default value', () => {
+ expect(form.getValue('mode')).toBe('none');
+ });
+
+ describe('compression form', () => {
+ beforeEach(() => {
+ formHelper.setValue('poolType', 'replicated');
+ formHelper.setValue('mode', 'passive');
+ });
+
+ it('is valid', () => {
+ expect(component.form.get('compression').valid).toBeTruthy();
+ });
+
+ it('validates minBlobSize to be only valid between 0 and maxBlobSize', () => {
+ formHelper.expectErrorChange('minBlobSize', -1, 'min');
+ formHelper.expectValidChange('minBlobSize', 0);
+ formHelper.setValue('maxBlobSize', '2 KiB');
+ formHelper.expectErrorChange('minBlobSize', '3 KiB', 'maximum');
+ formHelper.expectValidChange('minBlobSize', '1.9 KiB');
+ });
+
+ it('validates minBlobSize converts numbers', () => {
+ const control = formHelper.setValue('minBlobSize', '1');
+ fixture.detectChanges();
+ formHelper.expectValid(control);
+ expect(control.value).toBe('1 KiB');
+ });
+
+ it('validates maxBlobSize to be only valid bigger than minBlobSize', () => {
+ formHelper.expectErrorChange('maxBlobSize', -1, 'min');
+ formHelper.setValue('minBlobSize', '1 KiB');
+ formHelper.expectErrorChange('maxBlobSize', '0.5 KiB', 'minimum');
+ formHelper.expectValidChange('maxBlobSize', '1.5 KiB');
+ });
+
+ it('s valid to only use one blob size', () => {
+ formHelper.expectValid(formHelper.setValue('minBlobSize', '1 KiB'));
+ formHelper.expectValid(formHelper.setValue('maxBlobSize', ''));
+ formHelper.expectValid(formHelper.setValue('minBlobSize', ''));
+ formHelper.expectValid(formHelper.setValue('maxBlobSize', '1 KiB'));
+ });
+
+ it('dismisses any size error if one of the blob sizes is changed into a valid state', () => {
+ const min = formHelper.setValue('minBlobSize', '10 KiB');
+ const max = formHelper.setValue('maxBlobSize', '1 KiB');
+ fixture.detectChanges();
+ max.setValue('');
+ formHelper.expectValid(min);
+ formHelper.expectValid(max);
+ max.setValue('1 KiB');
+ fixture.detectChanges();
+ min.setValue('0.5 KiB');
+ formHelper.expectValid(min);
+ formHelper.expectValid(max);
+ });
+
+ it('validates maxBlobSize converts numbers', () => {
+ const control = formHelper.setValue('maxBlobSize', '2');
+ fixture.detectChanges();
+ expect(control.value).toBe('2 KiB');
+ });
+
+ it('validates that odd size validator works as expected', () => {
+ const odd = (min, max) => component['oddBlobSize'](min, max);
+ expect(odd('10', '8')).toBe(true);
+ expect(odd('8', '-')).toBe(false);
+ expect(odd('8', '10')).toBe(false);
+ expect(odd(null, '8')).toBe(false);
+ expect(odd('10', '')).toBe(false);
+ expect(odd('10', null)).toBe(false);
+ expect(odd(null, null)).toBe(false);
+ });
+
+ it('validates ratio to be only valid between 0 and 1', () => {
+ formHelper.expectValid('ratio');
+ formHelper.expectErrorChange('ratio', -0.1, 'min');
+ formHelper.expectValidChange('ratio', 0);
+ formHelper.expectValidChange('ratio', 1);
+ formHelper.expectErrorChange('ratio', 1.1, 'max');
+ });
+ });
+
+ it('validates application metadata name', () => {
+ formHelper.setValue('poolType', 'replicated');
+ fixture.detectChanges();
+ const selectBadges = fixture.debugElement.query(By.directive(SelectBadgesComponent))
+ .componentInstance;
+ const control = selectBadges.cdSelect.filter;
+ formHelper.expectValid(control);
+ control.setValue('?');
+ formHelper.expectError(control, 'pattern');
+ control.setValue('Ab3_');
+ formHelper.expectValid(control);
+ control.setValue('a'.repeat(129));
+ formHelper.expectError(control, 'maxlength');
+ });
+ });
+
+ describe('pool type changes', () => {
+ beforeEach(() => {
+ component.ngOnInit();
+ createCrushRule({ id: 3, min: 1, max: 1, name: 'ep1', type: 'erasure' });
+ createCrushRule({ id: 0, min: 2, max: 4, name: 'rep1', type: 'replicated' });
+ createCrushRule({ id: 1, min: 3, max: 18, name: 'rep2', type: 'replicated' });
+ });
+
+ it('should have a default replicated size of 3', () => {
+ formHelper.setValue('poolType', 'replicated');
+ expect(form.getValue('size')).toBe(3);
+ });
+
+ describe('replicatedRuleChange', () => {
+ beforeEach(() => {
+ formHelper.setValue('poolType', 'replicated');
+ formHelper.setValue('size', 99);
+ });
+
+ it('should not set size if a replicated pool is not set', () => {
+ formHelper.setValue('poolType', 'erasure');
+ expect(form.getValue('size')).toBe(99);
+ formHelper.setValue('crushRule', component.info.crush_rules_replicated[1]);
+ expect(form.getValue('size')).toBe(99);
+ });
+
+ it('should set size to maximum if size exceeds maximum', () => {
+ formHelper.setValue('crushRule', component.info.crush_rules_replicated[0]);
+ expect(form.getValue('size')).toBe(4);
+ });
+
+ it('should set size to minimum if size is lower than minimum', () => {
+ formHelper.setValue('size', -1);
+ formHelper.setValue('crushRule', component.info.crush_rules_replicated[0]);
+ expect(form.getValue('size')).toBe(2);
+ });
+ });
+
+ describe('rulesChange', () => {
+ it('has no effect if info is not there', () => {
+ delete component.info;
+ formHelper.setValue('poolType', 'replicated');
+ expect(component.current.rules).toEqual([]);
+ });
+
+ it('has no effect if pool type is not set', () => {
+ component['rulesChange']();
+ expect(component.current.rules).toEqual([]);
+ });
+
+ it('shows all replicated rules when pool type is "replicated"', () => {
+ formHelper.setValue('poolType', 'replicated');
+ expect(component.current.rules).toEqual(component.info.crush_rules_replicated);
+ expect(component.current.rules.length).toBe(2);
+ });
+
+ it('shows all erasure code rules when pool type is "erasure"', () => {
+ formHelper.setValue('poolType', 'erasure');
+ expect(component.current.rules).toEqual(component.info.crush_rules_erasure);
+ expect(component.current.rules.length).toBe(1);
+ });
+
+ it('disables rule field if only one rule exists which is used in the disabled field', () => {
+ formHelper.setValue('poolType', 'erasure');
+ const control = form.get('crushRule');
+ expect(control.value).toEqual(component.info.crush_rules_erasure[0]);
+ expect(control.disabled).toBe(true);
+ });
+
+ it('does not select the first rule if more than one exist', () => {
+ formHelper.setValue('poolType', 'replicated');
+ const control = form.get('crushRule');
+ expect(control.value).toEqual(null);
+ expect(control.disabled).toBe(false);
+ });
+
+ it('changing between both types will not leave crushRule in a bad state', () => {
+ formHelper.setValue('poolType', 'erasure');
+ formHelper.setValue('poolType', 'replicated');
+ const control = form.get('crushRule');
+ expect(control.value).toEqual(null);
+ expect(control.disabled).toBe(false);
+ formHelper.setValue('poolType', 'erasure');
+ expect(control.value).toEqual(component.info.crush_rules_erasure[0]);
+ expect(control.disabled).toBe(true);
+ });
+ });
+ });
+
+ describe('getMaxSize and getMinSize', () => {
+ const setCrushRule = ({ min, max }: { min?: number; max?: number }) => {
+ formHelper.setValue('crushRule', {
+ min_size: min,
+ max_size: max
+ });
+ };
+
+ it('returns nothing if osd count is 0', () => {
+ component.info.osd_count = 0;
+ expect(component.getMinSize()).toBe(undefined);
+ expect(component.getMaxSize()).toBe(undefined);
+ });
+
+ it('returns nothing if info is not there', () => {
+ delete component.info;
+ expect(component.getMinSize()).toBe(undefined);
+ expect(component.getMaxSize()).toBe(undefined);
+ });
+
+ it('returns minimum and maximum of rule', () => {
+ setCrushRule({ min: 2, max: 6 });
+ expect(component.getMinSize()).toBe(2);
+ expect(component.getMaxSize()).toBe(6);
+ });
+
+ it('returns 1 as minimum and the osd count as maximum if no crush rule is available', () => {
+ expect(component.getMinSize()).toBe(1);
+ expect(component.getMaxSize()).toBe(OSDS);
+ });
+
+ it('returns the osd count as maximum if the rule maximum exceeds it', () => {
+ setCrushRule({ max: 100 });
+ expect(component.getMaxSize()).toBe(OSDS);
+ });
+
+ it('should return the osd count as minimum if its lower the the rule minimum', () => {
+ setCrushRule({ min: 10 });
+ expect(component.getMinSize()).toBe(10);
+ const control = form.get('crushRule');
+ expect(control.invalid).toBe(true);
+ formHelper.expectError(control, 'tooFewOsds');
+ });
+ });
+
+ describe('application metadata', () => {
+ let selectBadges: SelectBadgesComponent;
+
+ const testAddApp = (app?: string, result?: string[]) => {
+ selectBadges.cdSelect.filter.setValue(app);
+ selectBadges.cdSelect.updateFilter();
+ selectBadges.cdSelect.selectOption();
+ expect(component.data.applications.selected).toEqual(result);
+ };
+
+ const testRemoveApp = (app: string, result: string[]) => {
+ selectBadges.cdSelect.removeItem(app);
+ expect(component.data.applications.selected).toEqual(result);
+ };
+
+ const setCurrentApps = (apps: string[]) => {
+ component.data.applications.selected = apps;
+ fixture.detectChanges();
+ selectBadges.cdSelect.ngOnInit();
+ return apps;
+ };
+
+ beforeEach(() => {
+ formHelper.setValue('poolType', 'replicated');
+ fixture.detectChanges();
+ selectBadges = fixture.debugElement.query(By.directive(SelectBadgesComponent))
+ .componentInstance;
+ });
+
+ it('adds all predefined and a custom applications to the application metadata array', () => {
+ testAddApp('g', ['rgw']);
+ testAddApp('b', ['rbd', 'rgw']);
+ testAddApp('c', ['cephfs', 'rbd', 'rgw']);
+ testAddApp('something', ['cephfs', 'rbd', 'rgw', 'something']);
+ });
+
+ it('only allows 4 apps to be added to the array', () => {
+ const apps = setCurrentApps(['d', 'c', 'b', 'a']);
+ testAddApp('e', apps);
+ });
+
+ it('can remove apps', () => {
+ setCurrentApps(['a', 'b', 'c', 'd']);
+ testRemoveApp('c', ['a', 'b', 'd']);
+ testRemoveApp('a', ['b', 'd']);
+ testRemoveApp('d', ['b']);
+ testRemoveApp('b', []);
+ });
+
+ it('does not remove any app that is not in the array', () => {
+ const apps = ['a', 'b', 'c', 'd'];
+ setCurrentApps(apps);
+ testRemoveApp('e', apps);
+ testRemoveApp('0', apps);
+ });
+ });
+
+ describe('pg number changes', () => {
+ beforeEach(() => {
+ formHelper.setValue('crushRule', {
+ min_size: 1,
+ max_size: 20
+ });
+ formHelper.setValue('poolType', 'erasure');
+ fixture.detectChanges();
+ setPgNum(256);
+ });
+
+ it('updates by value', () => {
+ testPgUpdate(10, undefined, 8);
+ testPgUpdate(22, undefined, 16);
+ testPgUpdate(26, undefined, 32);
+ testPgUpdate(200, undefined, 256);
+ testPgUpdate(300, undefined, 256);
+ testPgUpdate(350, undefined, 256);
+ });
+
+ it('updates by jump -> a magnitude of the power of 2', () => {
+ testPgUpdate(undefined, 1, 512);
+ testPgUpdate(undefined, -1, 256);
+ });
+
+ it('returns 1 as minimum for false numbers', () => {
+ testPgUpdate(-26, undefined, 1);
+ testPgUpdate(0, undefined, 1);
+ testPgUpdate(0, -1, 1);
+ testPgUpdate(undefined, -20, 1);
+ });
+
+ it('changes the value and than jumps', () => {
+ testPgUpdate(230, 1, 512);
+ testPgUpdate(3500, -1, 2048);
+ });
+
+ describe('pg power jump', () => {
+ it('should jump correctly at the beginning', () => {
+ testPgUpdate(1, -1, 1);
+ testPgUpdate(1, 1, 2);
+ testPgUpdate(2, -1, 1);
+ testPgUpdate(2, 1, 4);
+ testPgUpdate(4, -1, 2);
+ testPgUpdate(4, 1, 8);
+ testPgUpdate(4, 1, 8);
+ });
+
+ it('increments pg power if difference to the current number is 1', () => {
+ testPgUpdate(undefined, 1, 512);
+ testPgUpdate(undefined, 1, 1024);
+ testPgUpdate(undefined, 1, 2048);
+ testPgUpdate(undefined, 1, 4096);
+ });
+
+ it('decrements pg power if difference to the current number is -1', () => {
+ testPgUpdate(undefined, -1, 128);
+ testPgUpdate(undefined, -1, 64);
+ testPgUpdate(undefined, -1, 32);
+ testPgUpdate(undefined, -1, 16);
+ testPgUpdate(undefined, -1, 8);
+ });
+ });
+
+ describe('pgCalc', () => {
+ const PGS = 1;
+
+ const getValidCase = () => ({
+ type: 'replicated',
+ osds: OSDS,
+ size: 4,
+ ecp: {
+ k: 2,
+ m: 2
+ },
+ expected: 256
+ });
+
+ const testPgCalc = ({ type, osds, size, ecp, expected }) => {
+ component.info.osd_count = osds;
+ formHelper.setValue('poolType', type);
+ if (type === 'replicated') {
+ formHelper.setValue('size', size);
+ } else {
+ formHelper.setValue('erasureProfile', ecp);
+ }
+ expect(form.getValue('pgNum')).toBe(expected);
+ expect(component.externalPgChange).toBe(PGS !== expected);
+ };
+
+ beforeEach(() => {
+ setPgNum(PGS);
+ });
+
+ it('does not change anything if type is not valid', () => {
+ const test = getValidCase();
+ test.type = '';
+ test.expected = PGS;
+ testPgCalc(test);
+ });
+
+ it('does not change anything if ecp is not valid', () => {
+ const test = getValidCase();
+ test.expected = PGS;
+ test.type = 'erasure';
+ test.ecp = null;
+ testPgCalc(test);
+ });
+
+ it('calculates some replicated values', () => {
+ const test = getValidCase();
+ testPgCalc(test);
+ test.osds = 16;
+ test.expected = 512;
+ testPgCalc(test);
+ test.osds = 8;
+ test.size = 8;
+ test.expected = 128;
+ testPgCalc(test);
+ });
+
+ it('calculates erasure code values even if selection is disabled', () => {
+ component['initEcp']([{ k: 2, m: 2, name: 'bla', plugin: '', technique: '' }]);
+ const test = getValidCase();
+ test.type = 'erasure';
+ testPgCalc(test);
+ expect(form.get('erasureProfile').disabled).toBeTruthy();
+ });
+
+ it('calculates some erasure code values', () => {
+ const test = getValidCase();
+ test.type = 'erasure';
+ testPgCalc(test);
+ test.osds = 16;
+ test.ecp.m = 5;
+ test.expected = 256;
+ testPgCalc(test);
+ test.ecp.k = 5;
+ test.expected = 128;
+ testPgCalc(test);
+ });
+
+ it('should not change a manual set pg number', () => {
+ form.get('pgNum').markAsDirty();
+ const test = getValidCase();
+ test.expected = PGS;
+ testPgCalc(test);
+ });
+ });
+ });
+
+ describe('crushRule', () => {
+ beforeEach(() => {
+ createCrushRule({ name: 'replicatedRule' });
+ fixture.detectChanges();
+ formHelper.setValue('poolType', 'replicated');
+ fixture.detectChanges();
+ });
+
+ it('should not show info per default', () => {
+ fixtureHelper.expectElementVisible('#crushRule', true);
+ fixtureHelper.expectElementVisible('#crush-info-block', false);
+ });
+
+ it('should show info if the info button is clicked', () => {
+ fixture.detectChanges();
+ const infoButton = fixture.debugElement.query(By.css('#crush-info-button'));
+ infoButton.triggerEventHandler('click', null);
+ expect(component.data.crushInfo).toBeTruthy();
+ fixture.detectChanges();
+ expect(infoButton.classes['active']).toBeTruthy();
+ fixtureHelper.expectIdElementsVisible(['crushRule', 'crush-info-block'], true);
+ });
+ });
+
+ describe('erasure code profile', () => {
+ const setSelectedEcp = (name: string) => {
+ formHelper.setValue('erasureProfile', { name: name });
+ };
+
+ beforeEach(() => {
+ formHelper.setValue('poolType', 'erasure');
+ fixture.detectChanges();
+ });
+
+ it('should not show info per default', () => {
+ fixtureHelper.expectElementVisible('#erasureProfile', true);
+ fixtureHelper.expectElementVisible('#ecp-info-block', false);
+ });
+
+ it('should show info if the info button is clicked', () => {
+ const infoButton = fixture.debugElement.query(By.css('#ecp-info-button'));
+ infoButton.triggerEventHandler('click', null);
+ expect(component.data.erasureInfo).toBeTruthy();
+ fixture.detectChanges();
+ expect(infoButton.classes['active']).toBeTruthy();
+ fixtureHelper.expectIdElementsVisible(['erasureProfile', 'ecp-info-block'], true);
+ });
+
+ describe('ecp deletion', () => {
+ let taskWrapper: TaskWrapperService;
+ let deletion: CriticalConfirmationModalComponent;
+
+ const callDeletion = () => {
+ component.deleteErasureCodeProfile();
+ deletion.submitActionObservable();
+ };
+
+ const testPoolDeletion = (name) => {
+ setSelectedEcp(name);
+ callDeletion();
+ expect(ecpService.delete).toHaveBeenCalledWith(name);
+ expect(taskWrapper.wrapTaskAroundCall).toHaveBeenCalledWith({
+ task: {
+ name: 'ecp/delete',
+ metadata: {
+ name: name
+ }
+ },
+ call: undefined // because of stub
+ });
+ };
+
+ beforeEach(() => {
+ spyOn(TestBed.get(BsModalService), 'show').and.callFake((deletionClass, config) => {
+ deletion = Object.assign(new deletionClass(), config.initialState);
+ return {
+ content: deletion
+ };
+ });
+ spyOn(ecpService, 'delete').and.stub();
+ taskWrapper = TestBed.get(TaskWrapperService);
+ spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough();
+ });
+
+ it('should delete two different erasure code profiles', () => {
+ testPoolDeletion('someEcpName');
+ testPoolDeletion('aDifferentEcpName');
+ });
+ });
+ });
+
+ describe('submit - create', () => {
+ const setMultipleValues = (settings: {}) => {
+ Object.keys(settings).forEach((name) => {
+ formHelper.setValue(name, settings[name]);
+ });
+ };
+ const testCreate = (pool) => {
+ expectValidSubmit(pool, 'pool/create', 'create');
+ };
+
+ beforeEach(() => {
+ createCrushRule({ name: 'replicatedRule' });
+ createCrushRule({ name: 'erasureRule', type: 'erasure', id: 1 });
+ });
+
+ describe('erasure coded pool', () => {
+ it('minimum requirements', () => {
+ setMultipleValues({
+ name: 'minECPool',
+ poolType: 'erasure',
+ pgNum: 4
+ });
+ testCreate({
+ pool: 'minECPool',
+ pool_type: 'erasure',
+ pg_num: 4
+ });
+ });
+
+ it('with erasure coded profile', () => {
+ const ecp = { name: 'ecpMinimalMock' };
+ setMultipleValues({
+ name: 'ecpPool',
+ poolType: 'erasure',
+ pgNum: 16,
+ size: 2, // Will be ignored
+ erasureProfile: ecp
+ });
+ testCreate({
+ pool: 'ecpPool',
+ pool_type: 'erasure',
+ pg_num: 16,
+ erasure_code_profile: ecp.name
+ });
+ });
+
+ it('with ec_overwrite flag', () => {
+ setMultipleValues({
+ name: 'ecOverwrites',
+ poolType: 'erasure',
+ pgNum: 32,
+ ecOverwrites: true
+ });
+ testCreate({
+ pool: 'ecOverwrites',
+ pool_type: 'erasure',
+ pg_num: 32,
+ flags: ['ec_overwrites']
+ });
+ });
+
+ it('with rbd qos settings', () => {
+ setMultipleValues({
+ name: 'replicatedRbdQos',
+ poolType: 'replicated',
+ size: 2,
+ pgNum: 32
+ });
+ component.currentConfigurationValues = {
+ rbd_qos_bps_limit: 55
+ };
+ testCreate({
+ pool: 'replicatedRbdQos',
+ pool_type: 'replicated',
+ size: 2,
+ pg_num: 32,
+ configuration: {
+ rbd_qos_bps_limit: 55
+ }
+ });
+ });
+ });
+
+ describe('replicated coded pool', () => {
+ it('minimum requirements', () => {
+ const ecp = { name: 'ecpMinimalMock' };
+ setMultipleValues({
+ name: 'minRepPool',
+ poolType: 'replicated',
+ size: 2,
+ erasureProfile: ecp, // Will be ignored
+ pgNum: 8
+ });
+ testCreate({
+ pool: 'minRepPool',
+ pool_type: 'replicated',
+ pg_num: 8,
+ size: 2
+ });
+ });
+ });
+
+ it('pool with compression', () => {
+ setMultipleValues({
+ name: 'compression',
+ poolType: 'erasure',
+ pgNum: 64,
+ mode: 'passive',
+ algorithm: 'lz4',
+ minBlobSize: '4 K',
+ maxBlobSize: '4 M',
+ ratio: 0.7
+ });
+ testCreate({
+ pool: 'compression',
+ pool_type: 'erasure',
+ pg_num: 64,
+ compression_mode: 'passive',
+ compression_algorithm: 'lz4',
+ compression_min_blob_size: 4096,
+ compression_max_blob_size: 4194304,
+ compression_required_ratio: 0.7
+ });
+ });
+
+ it('pool with application metadata', () => {
+ setMultipleValues({
+ name: 'apps',
+ poolType: 'erasure',
+ pgNum: 128
+ });
+ component.data.applications.selected = ['cephfs', 'rgw'];
+ testCreate({
+ pool: 'apps',
+ pool_type: 'erasure',
+ pg_num: 128,
+ application_metadata: ['cephfs', 'rgw']
+ });
+ });
+ });
+
+ describe('edit mode', () => {
+ const setUrl = (url) => {
+ Object.defineProperty(router, 'url', { value: url });
+ setUpPoolComponent(); // Renew of component needed because the constructor has to be called
+ };
+
+ let pool: Pool;
+ beforeEach(() => {
+ pool = new Pool('somePoolName');
+ pool.type = 'replicated';
+ pool.size = 3;
+ pool.crush_rule = 'someRule';
+ pool.pg_num = 32;
+ pool.options = {};
+ pool.options.compression_mode = 'passive';
+ pool.options.compression_algorithm = 'lz4';
+ pool.options.compression_min_blob_size = 1024 * 512;
+ pool.options.compression_max_blob_size = 1024 * 1024;
+ pool.options.compression_required_ratio = 0.8;
+ pool.flags_names = 'someFlag1,someFlag2';
+ pool.application_metadata = ['rbd', 'rgw'];
+
+ createCrushRule({ name: 'someRule' });
+ spyOn(poolService, 'get').and.callFake(() => of(pool));
+ });
+
+ it('is not in edit mode if edit is not included in url', () => {
+ setUrl('/pool/add');
+ expect(component.editing).toBeFalsy();
+ });
+
+ it('is in edit mode if edit is included in url', () => {
+ setUrl('/pool/edit/somePoolName');
+ expect(component.editing).toBeTruthy();
+ });
+
+ describe('after ngOnInit', () => {
+ beforeEach(() => {
+ component.editing = true;
+ fixture.detectChanges();
+ });
+
+ it('disabled inputs', () => {
+ const disabled = ['poolType', 'crushRule', 'size', 'erasureProfile', 'ecOverwrites'];
+ disabled.forEach((controlName) => {
+ return expect(form.get(controlName).disabled).toBeTruthy();
+ });
+ const enabled = [
+ 'name',
+ 'pgNum',
+ 'mode',
+ 'algorithm',
+ 'minBlobSize',
+ 'maxBlobSize',
+ 'ratio'
+ ];
+ enabled.forEach((controlName) => {
+ return expect(form.get(controlName).enabled).toBeTruthy();
+ });
+ });
+
+ it('set all control values to the given pool', () => {
+ expect(form.getValue('name')).toBe(pool.pool_name);
+ expect(form.getValue('poolType')).toBe(pool.type);
+ expect(form.getValue('crushRule')).toEqual(component.info.crush_rules_replicated[0]);
+ expect(form.getValue('size')).toBe(pool.size);
+ expect(form.getValue('pgNum')).toBe(pool.pg_num);
+ expect(form.getValue('mode')).toBe(pool.options.compression_mode);
+ expect(form.getValue('algorithm')).toBe(pool.options.compression_algorithm);
+ expect(form.getValue('minBlobSize')).toBe('512 KiB');
+ expect(form.getValue('maxBlobSize')).toBe('1 MiB');
+ expect(form.getValue('ratio')).toBe(pool.options.compression_required_ratio);
+ });
+
+ it('updates pgs on every change', () => {
+ testPgUpdate(undefined, -1, 16);
+ testPgUpdate(undefined, -1, 8);
+ });
+
+ it('is possible to use less or more pgs than before', () => {
+ formHelper.expectValid(setPgNum(64));
+ formHelper.expectValid(setPgNum(4));
+ });
+
+ describe('submit', () => {
+ const markControlAsPreviouslySet = (controlName) => form.get(controlName).markAsPristine();
+
+ beforeEach(() => {
+ ['algorithm', 'maxBlobSize', 'minBlobSize', 'mode', 'pgNum', 'ratio', 'name'].forEach(
+ (name) => markControlAsPreviouslySet(name)
+ );
+ fixture.detectChanges();
+ });
+
+ it(`always provides the application metadata array with submit even if it's empty`, () => {
+ expect(form.get('mode').dirty).toBe(false);
+ component.data.applications.selected = [];
+ expectValidSubmit(
+ {
+ application_metadata: [],
+ pool: 'somePoolName'
+ },
+ 'pool/edit',
+ 'update'
+ );
+ });
+
+ it(`will always provide reset value for compression options`, () => {
+ formHelper.setValue('minBlobSize', '').markAsDirty();
+ formHelper.setValue('maxBlobSize', '').markAsDirty();
+ formHelper.setValue('ratio', '').markAsDirty();
+ expectValidSubmit(
+ {
+ application_metadata: ['rbd', 'rgw'],
+ compression_max_blob_size: 0,
+ compression_min_blob_size: 0,
+ compression_required_ratio: 0,
+ pool: 'somePoolName'
+ },
+ 'pool/edit',
+ 'update'
+ );
+ });
+
+ it(`will unset mode not used anymore`, () => {
+ formHelper.setValue('mode', 'none').markAsDirty();
+ expectValidSubmit(
+ {
+ application_metadata: ['rbd', 'rgw'],
+ compression_mode: 'unset',
+ pool: 'somePoolName'
+ },
+ 'pool/edit',
+ 'update'
+ );
+ });
+ });
+ });
+ });
+
+ describe('test pool configuration component', () => {
+ it('is visible for replicated pools with rbd application', () => {
+ const poolType = component.form.get('poolType');
+ poolType.markAsDirty();
+ poolType.setValue('replicated');
+ component.data.applications.selected = ['rbd'];
+ fixture.detectChanges();
+ expect(
+ fixture.debugElement.query(By.css('cd-rbd-configuration-form')).nativeElement.parentElement
+ .hidden
+ ).toBe(false);
+ });
+
+ it('is invisible for erasure coded pools', () => {
+ const poolType = component.form.get('poolType');
+ poolType.markAsDirty();
+ poolType.setValue('erasure');
+ fixture.detectChanges();
+ expect(
+ fixture.debugElement.query(By.css('cd-rbd-configuration-form')).nativeElement.parentElement
+ .hidden
+ ).toBe(true);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
new file mode 100644
index 00000000..c0cdecd4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts
@@ -0,0 +1,674 @@
+import { Component, EventEmitter, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { forkJoin, Subscription } from 'rxjs';
+
+import { ErasureCodeProfileService } from '../../../shared/api/erasure-code-profile.service';
+import { PoolService } from '../../../shared/api/pool.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import {
+ RbdConfigurationEntry,
+ RbdConfigurationSourceField
+} from '../../../shared/models/configuration';
+import { CrushRule } from '../../../shared/models/crush-rule';
+import { CrushStep } from '../../../shared/models/crush-step';
+import { ErasureCodeProfile } from '../../../shared/models/erasure-code-profile';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permission } from '../../../shared/models/permissions';
+import { PoolFormInfo } from '../../../shared/models/pool-form-info';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { ErasureCodeProfileFormComponent } from '../erasure-code-profile-form/erasure-code-profile-form.component';
+import { Pool } from '../pool';
+import { PoolFormData } from './pool-form-data';
+
+interface FormFieldDescription {
+ externalFieldName: string;
+ formControlName: string;
+ attr?: string;
+ replaceFn?: Function;
+ editable?: boolean;
+ resetValue?: any;
+}
+
+@Component({
+ selector: 'cd-pool-form',
+ templateUrl: './pool-form.component.html',
+ styleUrls: ['./pool-form.component.scss']
+})
+export class PoolFormComponent implements OnInit {
+ permission: Permission;
+ form: CdFormGroup;
+ ecProfiles: ErasureCodeProfile[];
+ info: PoolFormInfo;
+ routeParamsSubscribe: any;
+ editing = false;
+ data = new PoolFormData(this.i18n);
+ externalPgChange = false;
+ private modalSubscription: Subscription;
+ current = {
+ rules: []
+ };
+ initializeConfigData = new EventEmitter<{
+ initialData: RbdConfigurationEntry[];
+ sourceType: RbdConfigurationSourceField;
+ }>();
+ currentConfigurationValues: { [configKey: string]: any } = {};
+ action: string;
+ resource: string;
+
+ constructor(
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private route: ActivatedRoute,
+ private router: Router,
+ private modalService: BsModalService,
+ private poolService: PoolService,
+ private authStorageService: AuthStorageService,
+ private formatter: FormatterService,
+ private bsModalService: BsModalService,
+ private taskWrapper: TaskWrapperService,
+ private ecpService: ErasureCodeProfileService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.editing = this.router.url.startsWith(`/pool/${URLVerbs.EDIT}`);
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+ this.resource = this.i18n('pool');
+ this.authenticate();
+ this.createForm();
+ }
+
+ authenticate() {
+ this.permission = this.authStorageService.getPermissions().pool;
+ if (
+ !this.permission.read ||
+ ((!this.permission.update && this.editing) || (!this.permission.create && !this.editing))
+ ) {
+ this.router.navigate(['/404']);
+ }
+ }
+
+ private createForm() {
+ const compressionForm = new CdFormGroup({
+ mode: new FormControl('none'),
+ algorithm: new FormControl(''),
+ minBlobSize: new FormControl('', {
+ updateOn: 'blur'
+ }),
+ maxBlobSize: new FormControl('', {
+ updateOn: 'blur'
+ }),
+ ratio: new FormControl('', {
+ updateOn: 'blur'
+ })
+ });
+
+ this.form = new CdFormGroup(
+ {
+ name: new FormControl('', {
+ validators: [Validators.pattern(/^[.A-Za-z0-9_/-]+$/), Validators.required]
+ }),
+ poolType: new FormControl('', {
+ validators: [Validators.required]
+ }),
+ crushRule: new FormControl(null, {
+ validators: [
+ CdValidators.custom(
+ 'tooFewOsds',
+ (rule) => this.info && rule && this.info.osd_count < rule.min_size
+ )
+ ]
+ }),
+ size: new FormControl('', {
+ updateOn: 'blur'
+ }),
+ erasureProfile: new FormControl(null),
+ pgNum: new FormControl('', {
+ validators: [Validators.required, Validators.min(1)]
+ }),
+ ecOverwrites: new FormControl(false),
+ compression: compressionForm
+ },
+ [
+ CdValidators.custom('form', () => null),
+ CdValidators.custom('rbdPool', () => {
+ return (
+ this.form &&
+ this.form.getValue('name').includes('/') &&
+ this.data &&
+ this.data.applications.selected.indexOf('rbd') !== -1
+ );
+ })
+ ]
+ );
+ }
+
+ ngOnInit() {
+ forkJoin(this.poolService.getInfo(), this.ecpService.list()).subscribe(
+ (data: [PoolFormInfo, ErasureCodeProfile[]]) => {
+ this.initInfo(data[0]);
+ this.initEcp(data[1]);
+ if (this.editing) {
+ this.initEditMode();
+ }
+ this.listenToChanges();
+ this.setComplexValidators();
+ }
+ );
+ }
+
+ private initInfo(info: PoolFormInfo) {
+ this.form.silentSet('algorithm', info.bluestore_compression_algorithm);
+ this.info = info;
+ }
+
+ private initEcp(ecProfiles: ErasureCodeProfile[]) {
+ const control = this.form.get('erasureProfile');
+ if (ecProfiles.length <= 1) {
+ control.disable();
+ }
+ if (ecProfiles.length === 1) {
+ control.setValue(ecProfiles[0]);
+ } else if (ecProfiles.length > 1 && control.disabled) {
+ control.enable();
+ }
+ this.ecProfiles = ecProfiles;
+ }
+
+ private initEditMode() {
+ this.disableForEdit();
+ this.routeParamsSubscribe = this.route.params.subscribe((param: { name: string }) =>
+ this.poolService.get(param.name).subscribe((pool: Pool) => {
+ this.data.pool = pool;
+ this.initEditFormData(pool);
+ })
+ );
+ }
+
+ private disableForEdit() {
+ ['poolType', 'crushRule', 'size', 'erasureProfile', 'ecOverwrites'].forEach((controlName) =>
+ this.form.get(controlName).disable()
+ );
+ }
+
+ private initEditFormData(pool: Pool) {
+ this.initializeConfigData.emit({
+ initialData: pool.configuration,
+ sourceType: RbdConfigurationSourceField.pool
+ });
+
+ const dataMap = {
+ name: pool.pool_name,
+ poolType: pool.type,
+ crushRule: this.info['crush_rules_' + pool.type].find(
+ (rule: CrushRule) => rule.rule_name === pool.crush_rule
+ ),
+ size: pool.size,
+ erasureProfile: this.ecProfiles.find((ecp) => ecp.name === pool.erasure_code_profile),
+ pgNum: pool.pg_num,
+ ecOverwrites: pool.flags_names.includes('ec_overwrites'),
+ mode: pool.options.compression_mode,
+ algorithm: pool.options.compression_algorithm,
+ minBlobSize: this.dimlessBinaryPipe.transform(pool.options.compression_min_blob_size),
+ maxBlobSize: this.dimlessBinaryPipe.transform(pool.options.compression_max_blob_size),
+ ratio: pool.options.compression_required_ratio
+ };
+
+ Object.keys(dataMap).forEach((controlName: string) => {
+ const value = dataMap[controlName];
+ if (!_.isUndefined(value) && value !== '') {
+ this.form.silentSet(controlName, value);
+ }
+ });
+ this.data.pgs = this.form.getValue('pgNum');
+ this.data.applications.selected = pool.application_metadata;
+ }
+
+ private listenToChanges() {
+ this.listenToChangesDuringAddEdit();
+ if (!this.editing) {
+ this.listenToChangesDuringAdd();
+ }
+ }
+
+ private listenToChangesDuringAddEdit() {
+ this.form.get('pgNum').valueChanges.subscribe((pgs) => {
+ const change = pgs - this.data.pgs;
+ if (Math.abs(change) !== 1 || pgs === 2) {
+ this.data.pgs = pgs;
+ return;
+ }
+ this.doPgPowerJump(change as 1 | -1);
+ });
+ }
+
+ private doPgPowerJump(jump: 1 | -1) {
+ const power = this.calculatePgPower() + jump;
+ this.setPgs(jump === -1 ? Math.round(power) : Math.floor(power));
+ }
+
+ private calculatePgPower(pgs = this.form.getValue('pgNum')): number {
+ return Math.log(pgs) / Math.log(2);
+ }
+
+ private setPgs(power: number) {
+ const pgs = Math.pow(2, power < 0 ? 0 : power); // Set size the nearest accurate size.
+ this.data.pgs = pgs;
+ this.form.silentSet('pgNum', pgs);
+ }
+
+ private listenToChangesDuringAdd() {
+ this.form.get('poolType').valueChanges.subscribe((poolType) => {
+ this.form.get('size').updateValueAndValidity();
+ this.rulesChange();
+ if (poolType === 'replicated') {
+ this.replicatedRuleChange();
+ }
+ this.pgCalc();
+ });
+ this.form.get('crushRule').valueChanges.subscribe(() => {
+ if (this.form.getValue('poolType') === 'replicated') {
+ this.replicatedRuleChange();
+ }
+ this.pgCalc();
+ });
+ this.form.get('size').valueChanges.subscribe(() => {
+ this.pgCalc();
+ });
+ this.form.get('erasureProfile').valueChanges.subscribe(() => {
+ this.pgCalc();
+ });
+ this.form.get('mode').valueChanges.subscribe(() => {
+ ['minBlobSize', 'maxBlobSize', 'ratio'].forEach((name) => {
+ this.form.get(name).updateValueAndValidity({ emitEvent: false });
+ });
+ });
+ this.form.get('minBlobSize').valueChanges.subscribe(() => {
+ this.form.get('maxBlobSize').updateValueAndValidity({ emitEvent: false });
+ });
+ this.form.get('maxBlobSize').valueChanges.subscribe(() => {
+ this.form.get('minBlobSize').updateValueAndValidity({ emitEvent: false });
+ });
+ }
+
+ private rulesChange() {
+ const poolType = this.form.getValue('poolType');
+ if (!poolType || !this.info) {
+ this.current.rules = [];
+ return;
+ }
+ const rules = this.info['crush_rules_' + poolType] || [];
+ const control = this.form.get('crushRule');
+ if (rules.length === 1) {
+ control.setValue(rules[0]);
+ control.disable();
+ } else {
+ control.setValue(null);
+ control.enable();
+ }
+ this.current.rules = rules;
+ }
+
+ private replicatedRuleChange() {
+ if (this.form.getValue('poolType') !== 'replicated') {
+ return;
+ }
+ const control = this.form.get('size');
+ let size = this.form.getValue('size') || 3;
+ const min = this.getMinSize();
+ const max = this.getMaxSize();
+ if (size < min) {
+ size = min;
+ } else if (size > max) {
+ size = max;
+ }
+ if (size !== control.value) {
+ this.form.silentSet('size', size);
+ }
+ }
+
+ getMinSize(): number {
+ if (!this.info || this.info.osd_count < 1) {
+ return;
+ }
+ const rule = this.form.getValue('crushRule');
+ if (rule) {
+ return rule.min_size;
+ }
+ return 1;
+ }
+
+ getMaxSize(): number {
+ if (!this.info || this.info.osd_count < 1) {
+ return;
+ }
+ const osds: number = this.info.osd_count;
+ if (this.form.getValue('crushRule')) {
+ const max: number = this.form.get('crushRule').value.max_size;
+ if (max < osds) {
+ return max;
+ }
+ }
+ return osds;
+ }
+
+ private pgCalc() {
+ const poolType = this.form.getValue('poolType');
+ if (!this.info || this.form.get('pgNum').dirty || !poolType) {
+ return;
+ }
+ const pgMax = this.info.osd_count * 100;
+ const pgs =
+ poolType === 'replicated' ? this.replicatedPgCalc(pgMax) : this.erasurePgCalc(pgMax);
+ if (!pgs) {
+ return;
+ }
+ const oldValue = this.data.pgs;
+ this.alignPgs(pgs);
+ const newValue = this.data.pgs;
+ if (!this.externalPgChange) {
+ this.externalPgChange = oldValue !== newValue;
+ }
+ }
+
+ private replicatedPgCalc(pgs): number {
+ const sizeControl = this.form.get('size');
+ const size = sizeControl.value;
+ if (sizeControl.valid && size > 0) {
+ return pgs / size;
+ }
+ }
+
+ private erasurePgCalc(pgs): number {
+ const ecpControl = this.form.get('erasureProfile');
+ const ecp = ecpControl.value;
+ if ((ecpControl.valid || ecpControl.disabled) && ecp) {
+ return pgs / (ecp.k + ecp.m);
+ }
+ }
+
+ private alignPgs(pgs = this.form.getValue('pgNum')) {
+ this.setPgs(Math.round(this.calculatePgPower(pgs < 1 ? 1 : pgs)));
+ }
+
+ private setComplexValidators() {
+ if (this.editing) {
+ this.form
+ .get('name')
+ .setValidators([
+ this.form.get('name').validator,
+ CdValidators.custom(
+ 'uniqueName',
+ (name) =>
+ this.data.pool &&
+ this.info &&
+ this.info.pool_names.indexOf(name) !== -1 &&
+ this.info.pool_names.indexOf(name) !==
+ this.info.pool_names.indexOf(this.data.pool.pool_name)
+ )
+ ]);
+ } else {
+ CdValidators.validateIf(
+ this.form.get('size'),
+ () => this.form.get('poolType').value === 'replicated',
+ [
+ CdValidators.custom(
+ 'min',
+ (value) => this.form.getValue('size') && value < this.getMinSize()
+ ),
+ CdValidators.custom(
+ 'max',
+ (value) => this.form.getValue('size') && this.getMaxSize() < value
+ )
+ ]
+ );
+ this.form
+ .get('name')
+ .setValidators([
+ this.form.get('name').validator,
+ CdValidators.custom(
+ 'uniqueName',
+ (name) => this.info && this.info.pool_names.indexOf(name) !== -1
+ )
+ ]);
+ }
+ this.setCompressionValidators();
+ }
+
+ private setCompressionValidators() {
+ CdValidators.validateIf(this.form.get('minBlobSize'), () => this.hasCompressionEnabled(), [
+ Validators.min(0),
+ CdValidators.custom('maximum', (size) =>
+ this.oddBlobSize(size, this.form.getValue('maxBlobSize'))
+ )
+ ]);
+ CdValidators.validateIf(this.form.get('maxBlobSize'), () => this.hasCompressionEnabled(), [
+ Validators.min(0),
+ CdValidators.custom('minimum', (size) =>
+ this.oddBlobSize(this.form.getValue('minBlobSize'), size)
+ )
+ ]);
+ CdValidators.validateIf(this.form.get('ratio'), () => this.hasCompressionEnabled(), [
+ Validators.min(0),
+ Validators.max(1)
+ ]);
+ }
+
+ private oddBlobSize(minimum, maximum) {
+ minimum = this.formatter.toBytes(minimum);
+ maximum = this.formatter.toBytes(maximum);
+ return Boolean(minimum && maximum && minimum >= maximum);
+ }
+
+ hasCompressionEnabled() {
+ return this.form.getValue('mode') && this.form.get('mode').value.toLowerCase() !== 'none';
+ }
+
+ describeCrushStep(step: CrushStep) {
+ return [
+ step.op.replace('_', ' '),
+ step.item_name || '',
+ step.type ? step.num + ' type ' + step.type : ''
+ ].join(' ');
+ }
+
+ addErasureCodeProfile() {
+ this.modalSubscription = this.modalService.onHide.subscribe(() => this.reloadECPs());
+ this.bsModalService.show(ErasureCodeProfileFormComponent);
+ }
+
+ private reloadECPs() {
+ this.ecpService.list().subscribe((profiles: ErasureCodeProfile[]) => this.initEcp(profiles));
+ this.modalSubscription.unsubscribe();
+ }
+
+ deleteErasureCodeProfile() {
+ const ecp = this.form.getValue('erasureProfile');
+ if (!ecp) {
+ return;
+ }
+ const name = ecp.name;
+ this.modalSubscription = this.modalService.onHide.subscribe(() => this.reloadECPs());
+ this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.i18n('erasure code profile'),
+ itemNames: [name],
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask('ecp/delete', { name: name }),
+ call: this.ecpService.delete(name)
+ })
+ }
+ });
+ }
+
+ submit() {
+ if (this.form.invalid) {
+ this.form.setErrors({ cdSubmitButton: true });
+ return;
+ }
+
+ const pool = { pool: this.form.getValue('name') };
+
+ this.assignFormFields(pool, [
+ { externalFieldName: 'pool_type', formControlName: 'poolType' },
+ { externalFieldName: 'pg_num', formControlName: 'pgNum', editable: true },
+ this.form.getValue('poolType') === 'replicated'
+ ? { externalFieldName: 'size', formControlName: 'size' }
+ : {
+ externalFieldName: 'erasure_code_profile',
+ formControlName: 'erasureProfile',
+ attr: 'name'
+ },
+ { externalFieldName: 'rule_name', formControlName: 'crushRule', attr: 'rule_name' }
+ ]);
+
+ if (this.info.is_all_bluestore) {
+ this.assignFormField(pool, {
+ externalFieldName: 'flags',
+ formControlName: 'ecOverwrites',
+ replaceFn: () => ['ec_overwrites']
+ });
+
+ if (this.form.getValue('mode') !== 'none') {
+ this.assignFormFields(pool, [
+ {
+ externalFieldName: 'compression_mode',
+ formControlName: 'mode',
+ editable: true,
+ replaceFn: (value) => this.hasCompressionEnabled() && value
+ },
+ {
+ externalFieldName: 'compression_algorithm',
+ formControlName: 'algorithm',
+ editable: true
+ },
+ {
+ externalFieldName: 'compression_min_blob_size',
+ formControlName: 'minBlobSize',
+ replaceFn: this.formatter.toBytes,
+ editable: true,
+ resetValue: 0
+ },
+ {
+ externalFieldName: 'compression_max_blob_size',
+ formControlName: 'maxBlobSize',
+ replaceFn: this.formatter.toBytes,
+ editable: true,
+ resetValue: 0
+ },
+ {
+ externalFieldName: 'compression_required_ratio',
+ formControlName: 'ratio',
+ editable: true,
+ resetValue: 0
+ }
+ ]);
+ } else if (this.editing) {
+ this.assignFormFields(pool, [
+ {
+ externalFieldName: 'compression_mode',
+ formControlName: 'mode',
+ editable: true,
+ replaceFn: () => 'unset' // Is used if no compression is set
+ },
+ {
+ externalFieldName: 'srcpool',
+ formControlName: 'name',
+ editable: true,
+ replaceFn: () => this.data.pool.pool_name
+ }
+ ]);
+ }
+ }
+
+ const apps = this.data.applications.selected;
+ if (apps.length > 0 || this.editing) {
+ pool['application_metadata'] = apps;
+ }
+
+ // Only collect configuration data for replicated pools, as QoS cannot be configured on EC
+ // pools. EC data pools inherit their settings from the corresponding replicated metadata pool.
+ if (
+ this.form.get('poolType').value === 'replicated' &&
+ !_.isEmpty(this.currentConfigurationValues)
+ ) {
+ pool['configuration'] = this.currentConfigurationValues;
+ }
+
+ this.triggerApiTask(pool);
+ }
+
+ /**
+ * Retrieves the values for the given form field descriptions and assigns the values to the given
+ * object. This method differentiates between `add` and `edit` mode and acts differently on one or
+ * the other.
+ */
+ private assignFormFields(pool: object, formFieldDescription: FormFieldDescription[]): void {
+ formFieldDescription.forEach((item) => this.assignFormField(pool, item));
+ }
+
+ /**
+ * Retrieves the value for the given form field description and assigns the values to the given
+ * object. This method differentiates between `add` and `edit` mode and acts differently on one or
+ * the other.
+ */
+ private assignFormField(
+ pool: object,
+ {
+ externalFieldName,
+ formControlName,
+ attr,
+ replaceFn,
+ editable,
+ resetValue
+ }: FormFieldDescription
+ ): void {
+ if (this.editing && (!editable || this.form.get(formControlName).pristine)) {
+ return;
+ }
+ const value = this.form.getValue(formControlName);
+ let apiValue = replaceFn ? replaceFn(value) : attr ? _.get(value, attr) : value;
+ if (!value || !apiValue) {
+ if (editable && !_.isUndefined(resetValue)) {
+ apiValue = resetValue;
+ } else {
+ return;
+ }
+ }
+ pool[externalFieldName] = apiValue;
+ }
+
+ private triggerApiTask(pool) {
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('pool/' + (this.editing ? URLVerbs.EDIT : URLVerbs.CREATE), {
+ pool_name: pool.hasOwnProperty('srcpool') ? pool.srcpool : pool.pool
+ }),
+ call: this.poolService[this.editing ? URLVerbs.UPDATE : URLVerbs.CREATE](pool)
+ })
+ .subscribe(
+ undefined,
+ (resp) => {
+ if (_.isObject(resp.error) && resp.error.code === '34') {
+ this.form.get('pgNum').setErrors({ '34': true });
+ }
+ this.form.setErrors({ cdSubmitButton: true });
+ },
+ () => this.router.navigate(['/pool'])
+ );
+ }
+
+ appSelection() {
+ this.form.updateValueAndValidity({ emitEvent: false, onlySelf: true });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html
new file mode 100644
index 00000000..560cfba0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html
@@ -0,0 +1,42 @@
+<tabset>
+ <tab i18n-heading heading="Pools List">
+ <cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
+ [status]="viewCacheStatus.status"
+ [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
+
+ <cd-table #table
+ [data]="pools"
+ [columns]="columns"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permissions.pool"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-pool-details cdTableDetail
+ [selection]="selection"
+ [permissions]="permissions"
+ [cacheTiers]="selectionCacheTiers">
+ </cd-pool-details>
+ </cd-table>
+
+ <ng-template #poolUsageTpl
+ let-row="row">
+ <cd-usage-bar *ngIf="row.stats?.avail_raw?.latest"
+ [total]="row.stats.bytes_used.latest + row.stats.avail_raw.latest"
+ [used]="row.stats.bytes_used.latest"
+ decimals="2">
+ </cd-usage-bar>
+ </ng-template>
+ </tab>
+
+ <tab i18n-heading
+ *ngIf="permissions.grafana.read"
+ heading="Overall Performance">
+ <cd-grafana [grafanaPath]="'ceph-pools-overview?'"
+ uid="z99hzWtmk"
+ grafanaStyle="two">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.scss
new file mode 100644
index 00000000..40a8a256
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.scss
@@ -0,0 +1,17 @@
+@import '../../../../defaults';
+
+::ng-deep .pg-clean {
+ color: $color-bright-green;
+}
+
+::ng-deep .pg-working {
+ color: $color-primary;
+}
+
+::ng-deep .pg-warning {
+ color: $color-bright-yellow;
+}
+
+::ng-deep .pg-unknown {
+ color: $color-solid-red;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.spec.ts
new file mode 100644
index 00000000..3f917e20
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.spec.ts
@@ -0,0 +1,489 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders
+} from '../../../../testing/unit-test-helper';
+import { ConfigurationService } from '../../../shared/api/configuration.service';
+import { PoolService } from '../../../shared/api/pool.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdConfigurationListComponent } from '../../block/rbd-configuration-list/rbd-configuration-list.component';
+import { PgCategoryService } from '../../shared/pg-category.service';
+import { Pool } from '../pool';
+import { PoolDetailsComponent } from '../pool-details/pool-details.component';
+import { PoolListComponent } from './pool-list.component';
+
+describe('PoolListComponent', () => {
+ let component: PoolListComponent;
+ let fixture: ComponentFixture<PoolListComponent>;
+ let poolService: PoolService;
+
+ const createPool = (name, id): Pool => {
+ return _.merge(new Pool(name), {
+ pool: id,
+ pg_num: 256,
+ pg_placement_num: 256,
+ pg_num_target: 256,
+ pg_placement_num_target: 256
+ });
+ };
+
+ const getPoolList = (): Pool[] => {
+ return [createPool('a', 0), createPool('b', 1), createPool('c', 2)];
+ };
+
+ configureTestBed({
+ declarations: [PoolListComponent, PoolDetailsComponent, RbdConfigurationListComponent],
+ imports: [
+ SharedModule,
+ ToastrModule.forRoot(),
+ RouterTestingModule,
+ TabsModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ providers: [i18nProviders, PgCategoryService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ component.permissions.pool.read = true;
+ poolService = TestBed.get(PoolService);
+ spyOn(poolService, 'getList').and.callFake(() => of(getPoolList()));
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should have columns that are sortable', () => {
+ expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ });
+
+ describe('monAllowPoolDelete', () => {
+ let configOptRead: boolean;
+ let configurationService: ConfigurationService;
+
+ beforeEach(() => {
+ configOptRead = true;
+ spyOn(TestBed.get(AuthStorageService), 'getPermissions').and.callFake(() => ({
+ configOpt: { read: configOptRead }
+ }));
+ configurationService = TestBed.get(ConfigurationService);
+ });
+
+ it('should set value correctly if mon_allow_pool_delete flag is set to true', () => {
+ const configOption = {
+ name: 'mon_allow_pool_delete',
+ value: [
+ {
+ section: 'mon',
+ value: 'true'
+ }
+ ]
+ };
+ spyOn(configurationService, 'get').and.returnValue(of(configOption));
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ expect(component.monAllowPoolDelete).toBe(true);
+ });
+
+ it('should set value correctly if mon_allow_pool_delete flag is set to false', () => {
+ const configOption = {
+ name: 'mon_allow_pool_delete',
+ value: [
+ {
+ section: 'mon',
+ value: 'false'
+ }
+ ]
+ };
+ spyOn(configurationService, 'get').and.returnValue(of(configOption));
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ expect(component.monAllowPoolDelete).toBe(false);
+ });
+
+ it('should set value correctly if mon_allow_pool_delete flag is not set', () => {
+ const configOption = {
+ name: 'mon_allow_pool_delete'
+ };
+ spyOn(configurationService, 'get').and.returnValue(of(configOption));
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ expect(component.monAllowPoolDelete).toBe(false);
+ });
+
+ it('should set value correctly w/o config-opt read privileges', () => {
+ configOptRead = false;
+ fixture = TestBed.createComponent(PoolListComponent);
+ component = fixture.componentInstance;
+ expect(component.monAllowPoolDelete).toBe(false);
+ });
+ });
+
+ describe('pool deletion', () => {
+ let taskWrapper: TaskWrapperService;
+
+ const setSelectedPool = (poolName: string) => {
+ component.selection.selected = [{ pool_name: poolName }];
+ component.selection.update();
+ };
+
+ const callDeletion = () => {
+ component.deletePoolModal();
+ const deletion: CriticalConfirmationModalComponent = component.modalRef.content;
+ deletion.submitActionObservable();
+ };
+
+ const testPoolDeletion = (poolName) => {
+ setSelectedPool(poolName);
+ callDeletion();
+ expect(poolService.delete).toHaveBeenCalledWith(poolName);
+ expect(taskWrapper.wrapTaskAroundCall).toHaveBeenCalledWith({
+ task: {
+ name: 'pool/delete',
+ metadata: {
+ pool_name: poolName
+ }
+ },
+ call: undefined // because of stub
+ });
+ };
+
+ beforeEach(() => {
+ spyOn(TestBed.get(BsModalService), 'show').and.callFake((deletionClass, config) => {
+ return {
+ content: Object.assign(new deletionClass(), config.initialState)
+ };
+ });
+ spyOn(poolService, 'delete').and.stub();
+ taskWrapper = TestBed.get(TaskWrapperService);
+ spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough();
+ });
+
+ it('should pool deletion with two different pools', () => {
+ testPoolDeletion('somePoolName');
+ testPoolDeletion('aDifferentPoolName');
+ });
+ });
+
+ describe('handling of executing tasks', () => {
+ let summaryService: SummaryService;
+
+ const addTask = (name: string, pool: string) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ task.metadata = { pool_name: pool };
+ summaryService.addRunningTask(task);
+ };
+
+ beforeEach(() => {
+ summaryService = TestBed.get(SummaryService);
+ summaryService['summaryDataSource'].next({ executing_tasks: [], finished_tasks: [] });
+ });
+
+ it('gets all pools without executing pools', () => {
+ expect(component.pools.length).toBe(3);
+ expect(component.pools.every((pool) => !pool.executingTasks)).toBeTruthy();
+ });
+
+ it('gets a pool from a task during creation', () => {
+ addTask('pool/create', 'd');
+ expect(component.pools.length).toBe(4);
+ expectItemTasks(component.pools[3], 'Creating');
+ });
+
+ it('gets all pools with one executing pools', () => {
+ addTask('pool/create', 'a');
+ expect(component.pools.length).toBe(3);
+ expectItemTasks(component.pools[0], 'Creating');
+ expect(component.pools[1].cdExecuting).toBeFalsy();
+ expect(component.pools[2].cdExecuting).toBeFalsy();
+ });
+
+ it('gets all pools with multiple executing pools', () => {
+ addTask('pool/create', 'a');
+ addTask('pool/edit', 'a');
+ addTask('pool/delete', 'a');
+ addTask('pool/edit', 'b');
+ addTask('pool/delete', 'b');
+ addTask('pool/delete', 'c');
+ expect(component.pools.length).toBe(3);
+ expectItemTasks(component.pools[0], 'Creating..., Updating..., Deleting');
+ expectItemTasks(component.pools[1], 'Updating..., Deleting');
+ expectItemTasks(component.pools[2], 'Deleting');
+ });
+
+ it('gets all pools with multiple executing tasks (not only pool tasks)', () => {
+ addTask('rbd/create', 'a');
+ addTask('rbd/edit', 'a');
+ addTask('pool/delete', 'a');
+ addTask('pool/edit', 'b');
+ addTask('rbd/delete', 'b');
+ addTask('rbd/delete', 'c');
+ expect(component.pools.length).toBe(3);
+ expectItemTasks(component.pools[0], 'Deleting');
+ expectItemTasks(component.pools[1], 'Updating');
+ expect(component.pools[2].cdExecuting).toBeFalsy();
+ });
+ });
+
+ describe('getPgStatusCellClass', () => {
+ const testMethod = (value, expected) =>
+ expect(component.getPgStatusCellClass('', '', value)).toEqual({
+ 'text-right': true,
+ [expected]: true
+ });
+
+ it('pg-clean', () => {
+ testMethod('8 active+clean', 'pg-clean');
+ });
+
+ it('pg-working', () => {
+ testMethod(' 8 active+clean+scrubbing+deep, 255 active+clean ', 'pg-working');
+ });
+
+ it('pg-warning', () => {
+ testMethod('8 active+clean+scrubbing+down', 'pg-warning');
+ testMethod('8 active+clean+scrubbing+down+nonMappedState', 'pg-warning');
+ });
+
+ it('pg-unknown', () => {
+ testMethod('8 active+clean+scrubbing+nonMappedState', 'pg-unknown');
+ testMethod('8 ', 'pg-unknown');
+ testMethod('', 'pg-unknown');
+ });
+ });
+
+ describe('custom row comparators', () => {
+ const expectCorrectComparator = (statsAttribute: string) => {
+ const mockPool = (v) => ({ stats: { [statsAttribute]: { latest: v } } });
+ const columnDefinition = _.find(
+ component.columns,
+ (column) => column.prop === `stats.${statsAttribute}.rates`
+ );
+ expect(columnDefinition.comparator(undefined, undefined, mockPool(2), mockPool(1))).toBe(1);
+ expect(columnDefinition.comparator(undefined, undefined, mockPool(1), mockPool(2))).toBe(-1);
+ };
+
+ it('compares read bytes correctly', () => {
+ expectCorrectComparator('rd_bytes');
+ });
+
+ it('compares write bytes correctly', () => {
+ expectCorrectComparator('wr_bytes');
+ });
+ });
+
+ describe('transformPoolsData', () => {
+ let pool: Pool;
+
+ const getPoolData = (o) => [
+ _.merge(
+ _.merge(createPool('a', 0), {
+ cdIsBinary: true,
+ pg_status: '',
+ stats: {
+ bytes_used: { latest: 0, rate: 0, rates: [] },
+ max_avail: { latest: 0, rate: 0, rates: [] },
+ avail_raw: { latest: 0, rate: 0, rates: [] },
+ percent_used: { latest: 0, rate: 0, rates: [] },
+ rd: { latest: 0, rate: 0, rates: [] },
+ rd_bytes: { latest: 0, rate: 0, rates: [] },
+ wr: { latest: 0, rate: 0, rates: [] },
+ wr_bytes: { latest: 0, rate: 0, rates: [] }
+ },
+ usage: 0
+ }),
+ o
+ )
+ ];
+
+ beforeEach(() => {
+ pool = createPool('a', 0);
+ });
+
+ it('transforms pools data correctly', () => {
+ pool = _.merge(pool, {
+ stats: {
+ bytes_used: { latest: 5, rate: 0, rates: [] },
+ avail_raw: { latest: 15, rate: 0, rates: [] },
+ percent_used: { latest: 0.25, rate: 0, rates: [] },
+ rd_bytes: {
+ latest: 6,
+ rate: 4,
+ rates: [[0, 2], [1, 6]]
+ }
+ },
+ pg_status: { 'active+clean': 8, down: 2 }
+ });
+ expect(component.transformPoolsData([pool])).toEqual(
+ getPoolData({
+ pg_status: '8 active+clean, 2 down',
+ stats: {
+ bytes_used: { latest: 5, rate: 0, rates: [] },
+ avail_raw: { latest: 15, rate: 0, rates: [] },
+ percent_used: { latest: 0.25, rate: 0, rates: [] },
+ rd_bytes: { latest: 6, rate: 4, rates: [2, 6] }
+ },
+ usage: 0.25
+ })
+ );
+ });
+
+ it('transforms pools data correctly if stats are missing', () => {
+ expect(component.transformPoolsData([pool])).toEqual(getPoolData({}));
+ });
+
+ it('transforms empty pools data correctly', () => {
+ expect(component.transformPoolsData(undefined)).toEqual(undefined);
+ expect(component.transformPoolsData([])).toEqual([]);
+ });
+
+ it('shows not marked pools in progress if pg_num does not match pg_num_target', () => {
+ const pools = [
+ _.merge(pool, {
+ pg_num: 32,
+ pg_num_target: 16,
+ pg_placement_num: 32,
+ pg_placement_num_target: 16
+ })
+ ];
+ expect(component.transformPoolsData(pools)).toEqual(
+ getPoolData({
+ cdExecuting: 'Updating',
+ pg_num: 32,
+ pg_num_target: 16,
+ pg_placement_num: 32,
+ pg_placement_num_target: 16
+ })
+ );
+ });
+
+ it('shows marked pools in progress as defined by task', () => {
+ const pools = [
+ _.merge(pool, {
+ pg_num: 32,
+ pg_num_target: 16,
+ pg_placement_num: 32,
+ pg_placement_num_target: 16,
+ cdExecuting: 'Updating... 50%'
+ })
+ ];
+ expect(component.transformPoolsData(pools)).toEqual(
+ getPoolData({
+ cdExecuting: 'Updating... 50%',
+ pg_num: 32,
+ pg_num_target: 16,
+ pg_placement_num: 32,
+ pg_placement_num_target: 16
+ })
+ );
+ });
+ });
+
+ describe('transformPgStatus', () => {
+ it('returns status groups correctly', () => {
+ const pgStatus = { 'active+clean': 8 };
+ const expected = '8 active+clean';
+
+ expect(component.transformPgStatus(pgStatus)).toEqual(expected);
+ });
+
+ it('returns separated status groups', () => {
+ const pgStatus = { 'active+clean': 8, down: 2 };
+ const expected = '8 active+clean, 2 down';
+
+ expect(component.transformPgStatus(pgStatus)).toEqual(expected);
+ });
+
+ it('returns separated statuses correctly', () => {
+ const pgStatus = { active: 8, down: 2 };
+ const expected = '8 active, 2 down';
+
+ expect(component.transformPgStatus(pgStatus)).toEqual(expected);
+ });
+
+ it('returns empty string', () => {
+ const pgStatus = undefined;
+ const expected = '';
+
+ expect(component.transformPgStatus(pgStatus)).toEqual(expected);
+ });
+ });
+
+ describe('getSelectionTiers', () => {
+ const setSelectionTiers = (tiers: number[]) => {
+ component.selection.selected = [
+ {
+ tiers
+ }
+ ];
+ component.selection.update();
+ component.getSelectionTiers();
+ };
+
+ beforeEach(() => {
+ component.pools = getPoolList();
+ });
+
+ it('should select multiple existing cache tiers', () => {
+ setSelectionTiers([0, 1, 2]);
+ expect(component.selectionCacheTiers).toEqual(getPoolList());
+ });
+
+ it('should select correct existing cache tier', () => {
+ setSelectionTiers([0]);
+ expect(component.selectionCacheTiers).toEqual([createPool('a', 0)]);
+ });
+
+ it('should not select cache tier if id is invalid', () => {
+ setSelectionTiers([-1]);
+ expect(component.selectionCacheTiers).toEqual([]);
+ });
+
+ it('should not select cache tier if empty', () => {
+ setSelectionTiers([]);
+ expect(component.selectionCacheTiers).toEqual([]);
+ });
+
+ it('should be able to selected one pool with multiple tiers, than with a single tier, than with no tiers', () => {
+ setSelectionTiers([0, 1, 2]);
+ expect(component.selectionCacheTiers).toEqual(getPoolList());
+ setSelectionTiers([0]);
+ expect(component.selectionCacheTiers).toEqual([createPool('a', 0)]);
+ setSelectionTiers([]);
+ expect(component.selectionCacheTiers).toEqual([]);
+ });
+ });
+
+ describe('getDisableDesc', () => {
+ it('should return message if mon_allow_pool_delete flag is set to false', () => {
+ component.monAllowPoolDelete = false;
+ expect(component.getDisableDesc()).toBe(
+ 'Pool deletion is disabled by the mon_allow_pool_delete configuration setting.'
+ );
+ });
+
+ it('should return undefined if mon_allow_pool_delete flag is set to true', () => {
+ component.monAllowPoolDelete = true;
+ expect(component.getDisableDesc()).toBeUndefined();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.ts
new file mode 100644
index 00000000..4b2940dc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.ts
@@ -0,0 +1,300 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { ConfigurationService } from '../../../shared/api/configuration.service';
+import { PoolService } from '../../../shared/api/pool.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { Permissions } from '../../../shared/models/permissions';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { TaskListService } from '../../../shared/services/task-list.service';
+import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+import { PgCategoryService } from '../../shared/pg-category.service';
+import { Pool } from '../pool';
+import { PoolStats } from '../pool-stat';
+
+const BASE_URL = 'pool';
+
+@Component({
+ selector: 'cd-pool-list',
+ templateUrl: './pool-list.component.html',
+ providers: [
+ TaskListService,
+ { provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }
+ ],
+ styleUrls: ['./pool-list.component.scss']
+})
+export class PoolListComponent implements OnInit {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+ @ViewChild('poolUsageTpl')
+ poolUsageTpl: TemplateRef<any>;
+
+ @ViewChild('poolConfigurationSourceTpl')
+ poolConfigurationSourceTpl: TemplateRef<any>;
+
+ pools: Pool[] = [];
+ columns: CdTableColumn[];
+ selection = new CdTableSelection();
+ modalRef: BsModalRef;
+ executingTasks: ExecutingTask[] = [];
+ permissions: Permissions;
+ tableActions: CdTableAction[];
+ viewCacheStatusList: any[];
+ selectionCacheTiers: any[] = [];
+ monAllowPoolDelete = false;
+
+ constructor(
+ private poolService: PoolService,
+ private taskWrapper: TaskWrapperService,
+ private authStorageService: AuthStorageService,
+ private taskListService: TaskListService,
+ private modalService: BsModalService,
+ private i18n: I18n,
+ private pgCategoryService: PgCategoryService,
+ private dimlessPipe: DimlessPipe,
+ private urlBuilder: URLBuilderService,
+ private configurationService: ConfigurationService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ this.tableActions = [
+ {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ name: this.actionLabels.CREATE
+ },
+ {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () =>
+ this.urlBuilder.getEdit(encodeURIComponent(this.selection.first().pool_name)),
+ name: this.actionLabels.EDIT
+ },
+ {
+ permission: 'delete',
+ icon: 'fa-trash-o',
+ click: () => this.deletePoolModal(),
+ name: this.actionLabels.DELETE,
+ disable: () => !this.selection.first() || !this.monAllowPoolDelete,
+ disableDesc: () => this.getDisableDesc()
+ }
+ ];
+
+ // Note, we need read permissions to get the 'mon_allow_pool_delete'
+ // configuration option.
+ if (this.permissions.configOpt.read) {
+ this.configurationService.get('mon_allow_pool_delete').subscribe((data: any) => {
+ if (_.has(data, 'value')) {
+ const monSection = _.find(data.value, (v) => {
+ return v.section === 'mon';
+ }) || { value: false };
+ this.monAllowPoolDelete = monSection.value === 'true' ? true : false;
+ }
+ });
+ }
+ }
+
+ ngOnInit() {
+ const compare = (prop: string, pool1: Pool, pool2: Pool) =>
+ _.get(pool1, prop) > _.get(pool2, prop) ? 1 : -1;
+ this.columns = [
+ {
+ prop: 'pool_name',
+ name: this.i18n('Name'),
+ flexGrow: 4,
+ cellTransformation: CellTemplate.executing
+ },
+ {
+ prop: 'type',
+ name: this.i18n('Type'),
+ flexGrow: 2
+ },
+ {
+ prop: 'application_metadata',
+ name: this.i18n('Applications'),
+ flexGrow: 3
+ },
+ {
+ prop: 'pg_status',
+ name: this.i18n('PG Status'),
+ flexGrow: 3,
+ cellClass: ({ row, column, value }): any => {
+ return this.getPgStatusCellClass(row, column, value);
+ }
+ },
+ {
+ prop: 'size',
+ name: this.i18n('Replica Size'),
+ flexGrow: 2,
+ cellClass: 'text-right'
+ },
+ {
+ prop: 'last_change',
+ name: this.i18n('Last Change'),
+ flexGrow: 2,
+ cellClass: 'text-right'
+ },
+ {
+ prop: 'erasure_code_profile',
+ name: this.i18n('Erasure Coded Profile'),
+ flexGrow: 2
+ },
+ {
+ prop: 'crush_rule',
+ name: this.i18n('Crush Ruleset'),
+ flexGrow: 3
+ },
+ {
+ name: this.i18n('Usage'),
+ prop: 'usage',
+ cellTemplate: this.poolUsageTpl,
+ flexGrow: 3
+ },
+ {
+ prop: 'stats.rd_bytes.rates',
+ name: this.i18n('Read bytes'),
+ comparator: (_valueA, _valueB, rowA: Pool, rowB: Pool) =>
+ compare('stats.rd_bytes.latest', rowA, rowB),
+ cellTransformation: CellTemplate.sparkline,
+ flexGrow: 3
+ },
+ {
+ prop: 'stats.wr_bytes.rates',
+ name: this.i18n('Write bytes'),
+ comparator: (_valueA, _valueB, rowA: Pool, rowB: Pool) =>
+ compare('stats.wr_bytes.latest', rowA, rowB),
+ cellTransformation: CellTemplate.sparkline,
+ flexGrow: 3
+ },
+ {
+ prop: 'stats.rd.rate',
+ name: this.i18n('Read ops'),
+ flexGrow: 1,
+ pipe: this.dimlessPipe,
+ cellTransformation: CellTemplate.perSecond
+ },
+ {
+ prop: 'stats.wr.rate',
+ name: this.i18n('Write ops'),
+ flexGrow: 1,
+ pipe: this.dimlessPipe,
+ cellTransformation: CellTemplate.perSecond
+ }
+ ];
+
+ this.taskListService.init(
+ () => this.poolService.getList(),
+ undefined,
+ (pools) => (this.pools = this.transformPoolsData(pools)),
+ () => {
+ this.table.reset(); // Disable loading indicator.
+ this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+ },
+ (task) => task.name.startsWith(`${BASE_URL}/`),
+ (pool, task) => task.metadata['pool_name'] === pool.pool_name,
+ { default: (task: ExecutingTask) => new Pool(task.metadata['pool_name']) }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ this.getSelectionTiers();
+ }
+
+ deletePoolModal() {
+ const name = this.selection.first().pool_name;
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: 'Pool',
+ itemNames: [name],
+ submitActionObservable: () =>
+ this.taskWrapper.wrapTaskAroundCall({
+ task: new FinishedTask(`${BASE_URL}/${URLVerbs.DELETE}`, { pool_name: name }),
+ call: this.poolService.delete(name)
+ })
+ }
+ });
+ }
+
+ getPgStatusCellClass(_row, _column, value): object {
+ return {
+ 'text-right': true,
+ [`pg-${this.pgCategoryService.getTypeByStates(value)}`]: true
+ };
+ }
+
+ transformPoolsData(pools: any) {
+ const requiredStats = [
+ 'bytes_used',
+ 'max_avail',
+ 'avail_raw',
+ 'percent_used',
+ 'rd_bytes',
+ 'wr_bytes',
+ 'rd',
+ 'wr'
+ ];
+ const emptyStat = { latest: 0, rate: 0, rates: [] };
+
+ _.forEach(pools, (pool: Pool) => {
+ pool['pg_status'] = this.transformPgStatus(pool['pg_status']);
+ const stats: PoolStats = {};
+ _.forEach(requiredStats, (stat) => {
+ stats[stat] = pool.stats && pool.stats[stat] ? pool.stats[stat] : emptyStat;
+ });
+ pool['stats'] = stats;
+ pool['usage'] = stats.percent_used.latest;
+
+ if (
+ !pool.cdExecuting &&
+ pool.pg_num + pool.pg_placement_num !== pool.pg_num_target + pool.pg_placement_num_target
+ ) {
+ pool['cdExecuting'] = 'Updating';
+ }
+
+ ['rd_bytes', 'wr_bytes'].forEach((stat) => {
+ pool.stats[stat].rates = pool.stats[stat].rates.map((point) => point[1]);
+ });
+ pool.cdIsBinary = true;
+ });
+
+ return pools;
+ }
+
+ transformPgStatus(pgStatus: any): string {
+ const strings = [];
+ _.forEach(pgStatus, (count, state) => {
+ strings.push(`${count} ${state}`);
+ });
+
+ return strings.join(', ');
+ }
+
+ getSelectionTiers() {
+ const cacheTierIds = this.selection.hasSingleSelection ? this.selection.first()['tiers'] : [];
+ this.selectionCacheTiers = this.pools.filter((pool) => cacheTierIds.includes(pool.pool));
+ }
+
+ getDisableDesc(): string | undefined {
+ if (!this.monAllowPoolDelete) {
+ return this.i18n(
+ 'Pool deletion is disabled by the mon_allow_pool_delete configuration setting.'
+ );
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-stat.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-stat.ts
new file mode 100644
index 00000000..9820be94
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-stat.ts
@@ -0,0 +1,16 @@
+export class PoolStat {
+ latest: number;
+ rate: number;
+ rates: number[];
+}
+
+export class PoolStats {
+ bytes_used?: PoolStat;
+ max_avail?: PoolStat;
+ avail_raw?: PoolStat;
+ percent_used?: PoolStat;
+ rd_bytes?: PoolStat;
+ wr_bytes?: PoolStat;
+ rd?: PoolStat;
+ wr?: PoolStat;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.module.ts
new file mode 100644
index 00000000..0d3f6c56
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.module.ts
@@ -0,0 +1,61 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { ActionLabels, URLVerbs } from '../../shared/constants/app.constants';
+import { SharedModule } from '../../shared/shared.module';
+import { BlockModule } from '../block/block.module';
+import { CephSharedModule } from '../shared/ceph-shared.module';
+import { ErasureCodeProfileFormComponent } from './erasure-code-profile-form/erasure-code-profile-form.component';
+import { PoolDetailsComponent } from './pool-details/pool-details.component';
+import { PoolFormComponent } from './pool-form/pool-form.component';
+import { PoolListComponent } from './pool-list/pool-list.component';
+
+@NgModule({
+ imports: [
+ CephSharedModule,
+ CommonModule,
+ TabsModule,
+ PopoverModule.forRoot(),
+ SharedModule,
+ RouterModule,
+ ReactiveFormsModule,
+ BsDropdownModule,
+ TooltipModule.forRoot(),
+ BlockModule
+ ],
+ exports: [PoolListComponent, PoolFormComponent],
+ declarations: [
+ PoolListComponent,
+ PoolFormComponent,
+ ErasureCodeProfileFormComponent,
+ PoolDetailsComponent
+ ],
+ entryComponents: [ErasureCodeProfileFormComponent]
+})
+export class PoolModule {}
+
+const routes: Routes = [
+ { path: '', component: PoolListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: PoolFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:name`,
+ component: PoolFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+];
+
+@NgModule({
+ imports: [PoolModule, RouterModule.forChild(routes)]
+})
+export class RoutedPoolModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.ts
new file mode 100644
index 00000000..0808a89d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool.ts
@@ -0,0 +1,73 @@
+import { ExecutingTask } from '../../shared/models/executing-task';
+import { PoolStats } from './pool-stat';
+
+export class Pool {
+ cache_target_full_ratio_micro: number;
+ fast_read: boolean;
+ stripe_width: number;
+ flags_names: string;
+ tier_of: number;
+ hit_set_grade_decay_rate: number;
+ use_gmt_hitset: boolean;
+ last_force_op_resend_preluminous: string;
+ quota_max_bytes: number;
+ erasure_code_profile: string;
+ expected_num_objects: number;
+ size: number;
+ snap_seq: number;
+ auid: number;
+ cache_min_flush_age: number;
+ hit_set_period: number;
+ min_read_recency_for_promote: number;
+ target_max_objects: number;
+ pg_num: number;
+ pg_num_target: number;
+ pg_num_pending: number;
+ pg_placement_num: number;
+ pg_placement_num_target: number;
+ pg_autoscale_mode: string;
+ pg_status: string;
+ type: string;
+ pool_name: string;
+ cache_min_evict_age: number;
+ cache_mode: string;
+ min_size: number;
+ cache_target_dirty_high_ratio_micro: number;
+ object_hash: number;
+ application_metadata: string[];
+ write_tier: number;
+ cache_target_dirty_ratio_micro: number;
+ pool: number;
+ removed_snaps: string;
+ cdExecuting?: string;
+ executingTasks?: ExecutingTask[];
+ crush_rule: string;
+ tiers: any[];
+ hit_set_params: {
+ type: string;
+ };
+ last_force_op_resend: string;
+ pool_snaps: any[];
+ quota_max_objects: number;
+ options: {
+ compression_algorithm?: string;
+ compression_max_blob_size?: number;
+ compression_min_blob_size?: number;
+ compression_mode?: string;
+ compression_required_ratio?: number;
+ };
+ hit_set_count: number;
+ flags: number;
+ target_max_bytes: number;
+ hit_set_search_last_n: number;
+ last_change: string;
+ min_write_recency_for_promote: number;
+ read_tier: number;
+ stats?: PoolStats;
+ cdIsBinary?: boolean;
+ configuration: { source: number; name: string; value: string }[];
+
+ constructor(name) {
+ this.pool_name = name;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capabilities.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capabilities.ts
new file mode 100644
index 00000000..dac6986c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capabilities.ts
@@ -0,0 +1,15 @@
+export enum RgwUserAvailableCapability {
+ USERS = 'users',
+ BUCKETS = 'buckets',
+ METADATA = 'metadata',
+ USAGE = 'usage',
+ ZONE = 'zone'
+}
+
+export class RgwUserCapabilities {
+ static readonly capabilities = RgwUserAvailableCapability;
+
+ static getAll(): string[] {
+ return Object.values(RgwUserCapabilities.capabilities);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capability.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capability.ts
new file mode 100644
index 00000000..ee10088c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-capability.ts
@@ -0,0 +1,4 @@
+export class RgwUserCapability {
+ type: string;
+ perm: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-s3-key.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-s3-key.ts
new file mode 100644
index 00000000..bcb95310
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-s3-key.ts
@@ -0,0 +1,6 @@
+export class RgwUserS3Key {
+ user: string;
+ generate_key?: boolean;
+ access_key: string;
+ secret_key: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-subuser.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-subuser.ts
new file mode 100644
index 00000000..788b6a29
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-subuser.ts
@@ -0,0 +1,6 @@
+export class RgwUserSubuser {
+ id: string;
+ permissions: string;
+ generate_secret?: boolean;
+ secret_key?: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-swift-key.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-swift-key.ts
new file mode 100644
index 00000000..26abd2a9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-user-swift-key.ts
@@ -0,0 +1,4 @@
+export class RgwUserSwiftKey {
+ user: string;
+ secret_key: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.html
new file mode 100644
index 00000000..b9984b5c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.html
@@ -0,0 +1,5 @@
+<cd-info-panel>
+ {{ message }}<br>
+ <ng-container i18n>Please consult the <a href="{{docsUrl}}" target="_blank">documentation</a>
+ on how to configure and enable the Object Gateway management functionality.</ng-container>
+</cd-info-panel>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.spec.ts
new file mode 100644
index 00000000..565caab1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.spec.ts
@@ -0,0 +1,28 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { Rgw501Component } from './rgw-501.component';
+
+describe('Rgw501Component', () => {
+ let component: Rgw501Component;
+ let fixture: ComponentFixture<Rgw501Component>;
+
+ configureTestBed({
+ declarations: [Rgw501Component],
+ imports: [HttpClientTestingModule, RouterTestingModule, SharedModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(Rgw501Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts
new file mode 100644
index 00000000..67fb868a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-501/rgw-501.component.ts
@@ -0,0 +1,47 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../../shared/services/summary.service';
+
+@Component({
+ selector: 'cd-rgw-501',
+ templateUrl: './rgw-501.component.html',
+ styleUrls: ['./rgw-501.component.scss']
+})
+export class Rgw501Component implements OnInit, OnDestroy {
+ docsUrl: string;
+ message = 'The Object Gateway service is not configured.';
+ routeParamsSubscribe: any;
+
+ constructor(
+ private route: ActivatedRoute,
+ private summaryService: SummaryService,
+ private cephReleaseNamePipe: CephReleaseNamePipe
+ ) {}
+
+ ngOnInit() {
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl =
+ `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/` +
+ `#enabling-the-object-gateway-management-frontend`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+
+ this.routeParamsSubscribe = this.route.params.subscribe((params: { message: string }) => {
+ this.message = params.message;
+ });
+ }
+
+ ngOnDestroy() {
+ this.routeParamsSubscribe.unsubscribe();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html
new file mode 100644
index 00000000..d6d2068a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html
@@ -0,0 +1,101 @@
+<tabset *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading heading="Details">
+ <div *ngIf="bucket">
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Name</td>
+ <td class="col-sm-3">{{ bucket.bid }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">ID</td>
+ <td>{{ bucket.id }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Owner</td>
+ <td>{{ bucket.owner }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Index type</td>
+ <td>{{ bucket.index_type }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Placement rule</td>
+ <td>{{ bucket.placement_rule }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Marker</td>
+ <td>{{ bucket.marker }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum marker</td>
+ <td>{{ bucket.max_marker }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Version</td>
+ <td>{{ bucket.ver }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Master version</td>
+ <td>{{ bucket.master_ver }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Modification time</td>
+ <td>{{ bucket.mtime | cdDate }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Zonegroup</td>
+ <td>{{ bucket.zonegroup }}</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- Bucket quota -->
+ <div *ngIf="bucket.bucket_quota">
+ <legend i18n>Bucket quota</legend>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Enabled</td>
+ <td class="col-sm-3">{{ bucket.bucket_quota.enabled | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum size</td>
+ <td *ngIf="bucket.bucket_quota.max_size <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="bucket.bucket_quota.max_size > -1"
+ class="col-sm-3">
+ {{ bucket.bucket_quota.max_size | dimless }}
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum objects</td>
+ <td *ngIf="bucket.bucket_quota.max_objects <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="bucket.bucket_quota.max_objects > -1"
+ class="col-sm-3">
+ {{ bucket.bucket_quota.max_objects }}
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss
new file mode 100644
index 00000000..d293c9d9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss
@@ -0,0 +1,7 @@
+table {
+ table-layout: fixed;
+}
+
+table td {
+ word-wrap: break-word;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts
new file mode 100644
index 00000000..a2ede8d3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts
@@ -0,0 +1,30 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwBucketDetailsComponent } from './rgw-bucket-details.component';
+
+describe('RgwBucketDetailsComponent', () => {
+ let component: RgwBucketDetailsComponent;
+ let fixture: ComponentFixture<RgwBucketDetailsComponent>;
+
+ configureTestBed({
+ declarations: [RgwBucketDetailsComponent],
+ imports: [SharedModule, TabsModule.forRoot()],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwBucketDetailsComponent);
+ component = fixture.componentInstance;
+ component.selection = new CdTableSelection();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts
new file mode 100644
index 00000000..0b4fa506
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts
@@ -0,0 +1,23 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-rgw-bucket-details',
+ templateUrl: './rgw-bucket-details.component.html',
+ styleUrls: ['./rgw-bucket-details.component.scss']
+})
+export class RgwBucketDetailsComponent implements OnChanges {
+ bucket: any;
+
+ @Input()
+ selection: CdTableSelection;
+
+ constructor() {}
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.bucket = this.selection.first();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html
new file mode 100644
index 00000000..1be3e0f9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html
@@ -0,0 +1,108 @@
+<cd-loading-panel *ngIf="editing && loading && !error"
+ i18n>Loading bucket data...</cd-loading-panel>
+<cd-error-panel *ngIf="editing && error"
+ (backAction)="goToListView()"
+ i18n>The bucket data could not be loaded.</cd-error-panel>
+
+<div class="col-sm-12 col-lg-6"
+ *ngIf="!loading && !error">
+ <form name="bucketForm"
+ class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="bucketForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Id -->
+ <div class="form-group"
+ *ngIf="editing">
+ <label i18n
+ class="col-sm-3 control-label"
+ for="id">Id</label>
+ <div class="col-sm-9">
+ <input id="id"
+ name="id"
+ class="form-control"
+ type="text"
+ formControlName="id"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': bucketForm.showError('bid', frm)}">
+ <label class="control-label col-sm-3"
+ for="bid">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"
+ *ngIf="!editing"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="bid"
+ name="bid"
+ class="form-control"
+ type="text"
+ i18n-placeholder
+ placeholder="Name..."
+ formControlName="bid"
+ [readonly]="editing"
+ autofocus>
+ <span class="help-block"
+ *ngIf="bucketForm.showError('bid', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="bucketForm.showError('bid', frm, 'bucketNameInvalid')"
+ i18n>The value is not valid.</span>
+ <span class="help-block"
+ *ngIf="bucketForm.showError('bid', frm, 'bucketNameExists')"
+ i18n>The chosen name is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Owner -->
+ <div class="form-group"
+ [ngClass]="{'has-error': bucketForm.showError('owner', frm)}">
+ <label class="control-label col-sm-3"
+ for="owner">
+ <ng-container i18n>Owner</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select id="owner"
+ name="owner"
+ class="form-control"
+ formControlName="owner">
+ <option i18n
+ *ngIf="owners === null"
+ [ngValue]="null">Loading...</option>
+ <option i18n
+ *ngIf="owners !== null"
+ [ngValue]="null">-- Select a user --</option>
+ <option *ngFor="let owner of owners"
+ [value]="owner">{{ owner }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="bucketForm.showError('owner', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ (submitAction)="submit()" [form]="bucketForm"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts
new file mode 100644
index 00000000..dfebff4b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts
@@ -0,0 +1,131 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { RgwBucketService } from '../../../shared/api/rgw-bucket.service';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwBucketFormComponent } from './rgw-bucket-form.component';
+
+describe('RgwBucketFormComponent', () => {
+ let component: RgwBucketFormComponent;
+ let fixture: ComponentFixture<RgwBucketFormComponent>;
+ let rwgBucketService: RgwBucketService;
+
+ configureTestBed({
+ declarations: [RgwBucketFormComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwBucketFormComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ rwgBucketService = TestBed.get(RgwBucketService);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('bucketNameValidator', () => {
+ it('should validate name (1/4)', () => {
+ const validatorFn = component.bucketNameValidator();
+ const ctrl = new FormControl('');
+ const validatorPromise = validatorFn(ctrl);
+ expect(validatorPromise instanceof Promise).toBeTruthy();
+ if (validatorPromise instanceof Promise) {
+ validatorPromise.then((resp) => {
+ expect(resp).toBe(null);
+ });
+ }
+ });
+
+ it('should validate name (2/4)', () => {
+ const validatorFn = component.bucketNameValidator();
+ const ctrl = new FormControl('ab');
+ ctrl.markAsDirty();
+ const validatorPromise = validatorFn(ctrl);
+ expect(validatorPromise instanceof Promise).toBeTruthy();
+ if (validatorPromise instanceof Promise) {
+ validatorPromise.then((resp) => {
+ expect(resp.bucketNameInvalid).toBeTruthy();
+ });
+ }
+ });
+
+ it('should validate name (3/4)', () => {
+ const validatorFn = component.bucketNameValidator();
+ const ctrl = new FormControl('abc');
+ ctrl.markAsDirty();
+ const validatorPromise = validatorFn(ctrl);
+ expect(validatorPromise instanceof Promise).toBeTruthy();
+ if (validatorPromise instanceof Promise) {
+ validatorPromise.then((resp) => {
+ expect(resp).toBe(null);
+ });
+ }
+ });
+
+ it('should validate name (4/4)', () => {
+ spyOn(rwgBucketService, 'enumerate').and.returnValue(observableOf(['abcd']));
+ const validatorFn = component.bucketNameValidator();
+ const ctrl = new FormControl('abcd');
+ ctrl.markAsDirty();
+ const validatorPromise = validatorFn(ctrl);
+ expect(validatorPromise instanceof Promise).toBeTruthy();
+ if (validatorPromise instanceof Promise) {
+ validatorPromise.then((resp) => {
+ expect(resp instanceof Object).toBeTruthy();
+ expect(resp.bucketNameExists).toBeTruthy();
+ });
+ }
+ });
+ });
+
+ describe('submit form', () => {
+ let notificationService: NotificationService;
+
+ beforeEach(() => {
+ spyOn(TestBed.get(Router), 'navigate').and.stub();
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show');
+ });
+
+ it('tests create success notification', () => {
+ spyOn(rwgBucketService, 'create').and.returnValue(observableOf([]));
+ component.editing = false;
+ component.bucketForm.markAsDirty();
+ component.submit();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Created Object Gateway bucket ""'
+ );
+ });
+
+ it('tests update success notification', () => {
+ spyOn(rwgBucketService, 'update').and.returnValue(observableOf([]));
+ component.editing = true;
+ component.bucketForm.markAsDirty();
+ component.submit();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Updated Object Gateway bucket ""'
+ );
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
new file mode 100644
index 00000000..8a3391f8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
@@ -0,0 +1,160 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, AsyncValidatorFn, ValidationErrors, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { RgwBucketService } from '../../../shared/api/rgw-bucket.service';
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { NotificationService } from '../../../shared/services/notification.service';
+
+@Component({
+ selector: 'cd-rgw-bucket-form',
+ templateUrl: './rgw-bucket-form.component.html',
+ styleUrls: ['./rgw-bucket-form.component.scss']
+})
+export class RgwBucketFormComponent implements OnInit {
+ bucketForm: CdFormGroup;
+ editing = false;
+ error = false;
+ loading = false;
+ owners = null;
+ action: string;
+ resource: string;
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private formBuilder: CdFormBuilder,
+ private rgwBucketService: RgwBucketService,
+ private rgwUserService: RgwUserService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.editing = this.router.url.startsWith(`/rgw/bucket/${URLVerbs.EDIT}`);
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+ this.resource = this.i18n('bucket');
+ this.createForm();
+ }
+
+ createForm() {
+ this.bucketForm = this.formBuilder.group({
+ id: [null],
+ bid: [null, [Validators.required], [this.bucketNameValidator()]],
+ owner: [null, [Validators.required]]
+ });
+ }
+
+ ngOnInit() {
+ // Get the list of possible owners.
+ this.rgwUserService.enumerate().subscribe((resp: string[]) => {
+ this.owners = resp.sort();
+ });
+
+ // Process route parameters.
+ this.route.params.subscribe(
+ (params: { bid: string }) => {
+ if (!params.hasOwnProperty('bid')) {
+ return;
+ }
+ const bid = decodeURIComponent(params.bid);
+ this.loading = true;
+
+ this.rgwBucketService.get(bid).subscribe((resp: object) => {
+ this.loading = false;
+ // Get the default values.
+ const defaults = _.clone(this.bucketForm.value);
+ // Extract the values displayed in the form.
+ let value = _.pick(resp, _.keys(this.bucketForm.value));
+ // Append default values.
+ value = _.merge(defaults, value);
+ // Update the form.
+ this.bucketForm.setValue(value);
+ });
+ },
+ (error) => {
+ this.error = error;
+ }
+ );
+ }
+
+ goToListView() {
+ this.router.navigate(['/rgw/bucket']);
+ }
+
+ submit() {
+ // Exit immediately if the form isn't dirty.
+ if (this.bucketForm.pristine) {
+ this.goToListView();
+ return;
+ }
+ const bidCtl = this.bucketForm.get('bid');
+ const ownerCtl = this.bucketForm.get('owner');
+ if (this.editing) {
+ // Edit
+ const idCtl = this.bucketForm.get('id');
+ this.rgwBucketService.update(bidCtl.value, idCtl.value, ownerCtl.value).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated Object Gateway bucket "{{bid}}"', { bid: bidCtl.value })
+ );
+ this.goToListView();
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.bucketForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ } else {
+ // Add
+ this.rgwBucketService.create(bidCtl.value, ownerCtl.value).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Created Object Gateway bucket "{{bid}}"', { bid: bidCtl.value })
+ );
+ this.goToListView();
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.bucketForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+ }
+
+ bucketNameValidator(): AsyncValidatorFn {
+ const rgwBucketService = this.rgwBucketService;
+ return (control: AbstractControl): Promise<ValidationErrors | null> => {
+ return new Promise((resolve) => {
+ // Exit immediately if user has not interacted with the control yet
+ // or the control value is empty.
+ if (control.pristine || control.value === '') {
+ resolve(null);
+ return;
+ }
+ // Validate the bucket name.
+ const nameRe = /^[0-9A-Za-z][\w-\.]{2,254}$/;
+ if (!nameRe.test(control.value)) {
+ resolve({ bucketNameInvalid: true });
+ return;
+ }
+ // Does any bucket with the given name already exist?
+ rgwBucketService.exists(control.value).subscribe((resp: boolean) => {
+ if (!resp) {
+ resolve(null);
+ } else {
+ resolve({ bucketNameExists: true });
+ }
+ });
+ });
+ };
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.html
new file mode 100644
index 00000000..aa487bf9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.html
@@ -0,0 +1,39 @@
+<cd-table #table
+ [autoReload]="false"
+ [data]="buckets"
+ [columns]="columns"
+ columnMode="flex"
+ selectionType="multi"
+ (updateSelection)="updateSelection($event)"
+ identifier="bid"
+ (fetchData)="getBucketList($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-rgw-bucket-details cdTableDetail
+ [selection]="selection">
+ </cd-rgw-bucket-details>
+</cd-table>
+
+<ng-template #bucketSizeTpl
+ let-row="row">
+ <cd-usage-bar *ngIf="row.bucket_quota.max_size > 0 && row.bucket_quota.enabled; else noSizeQuota"
+ [total]="row.bucket_quota.max_size"
+ [used]="row.bucket_size">
+ </cd-usage-bar>
+
+ <ng-template #noSizeQuota>No Limit</ng-template>
+</ng-template>
+
+<ng-template #bucketObjectTpl
+ let-row="row">
+ <cd-usage-bar *ngIf="row.bucket_quota.max_objects > 0 && row.bucket_quota.enabled; else noObjectQuota"
+ [total]="row.bucket_quota.max_objects"
+ [used]="row.num_objects"
+ [isBinary]="false">
+ </cd-usage-bar>
+
+ <ng-template #noObjectQuota>No Limit</ng-template>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts
new file mode 100644
index 00000000..4ecb6ae1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts
@@ -0,0 +1,291 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { RgwBucketService } from '../../../shared/api/rgw-bucket.service';
+import { ActionLabels } from '../../../shared/constants/app.constants';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwBucketDetailsComponent } from '../rgw-bucket-details/rgw-bucket-details.component';
+import { RgwBucketListComponent } from './rgw-bucket-list.component';
+
+describe('RgwBucketListComponent', () => {
+ let component: RgwBucketListComponent;
+ let fixture: ComponentFixture<RgwBucketListComponent>;
+ let rgwBucketService: RgwBucketService;
+ let rgwBucketServiceListSpy: jasmine.Spy;
+
+ configureTestBed({
+ declarations: [RgwBucketListComponent, RgwBucketDetailsComponent],
+ imports: [
+ RouterTestingModule,
+ ModalModule.forRoot(),
+ SharedModule,
+ TabsModule.forRoot(),
+ HttpClientTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ rgwBucketService = TestBed.get(RgwBucketService);
+ rgwBucketServiceListSpy = spyOn(rgwBucketService, 'list');
+ rgwBucketServiceListSpy.and.returnValue(of(null));
+ fixture = TestBed.createComponent(RgwBucketListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: ActionLabels.EDIT,
+ empty: ActionLabels.CREATE
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows 'Add' and 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Add' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows always 'Add' as main action`, () => {
+ scenario.single = ActionLabels.CREATE;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Add' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+
+ it('should test if bucket data is tranformed correctly', () => {
+ rgwBucketServiceListSpy.and.returnValue(
+ of([
+ {
+ bucket: 'bucket',
+ owner: 'testid',
+ usage: {
+ 'rgw.main': {
+ size_actual: 4,
+ num_objects: 2
+ },
+ 'rgw.another': {
+ size_actual: 6,
+ num_objects: 6
+ }
+ },
+ bucket_quota: {
+ max_size: 20,
+ max_objects: 10,
+ enabled: true
+ }
+ }
+ ])
+ );
+ fixture.detectChanges();
+ expect(component.buckets).toEqual([
+ {
+ bucket: 'bucket',
+ owner: 'testid',
+ usage: {
+ 'rgw.main': { size_actual: 4, num_objects: 2 },
+ 'rgw.another': { size_actual: 6, num_objects: 6 }
+ },
+ bucket_quota: {
+ max_size: 20,
+ max_objects: 10,
+ enabled: true
+ },
+ bucket_size: 10,
+ num_objects: 8,
+ size_usage: 0.5,
+ object_usage: 0.8
+ }
+ ]);
+ });
+ it('should usage bars only if quota enabled', () => {
+ rgwBucketServiceListSpy.and.returnValue(
+ of([
+ {
+ bucket: 'bucket',
+ owner: 'testid',
+ bucket_quota: {
+ max_size: 1024,
+ max_objects: 10,
+ enabled: true
+ }
+ }
+ ])
+ );
+ fixture.detectChanges();
+ const usageBars = fixture.debugElement.nativeElement.querySelectorAll('cd-usage-bar');
+ expect(usageBars.length).toBe(2);
+ });
+ it('should not show any usage bars if quota disabled', () => {
+ rgwBucketServiceListSpy.and.returnValue(
+ of([
+ {
+ bucket: 'bucket',
+ owner: 'testid',
+ bucket_quota: {
+ max_size: 1024,
+ max_objects: 10,
+ enabled: false
+ }
+ }
+ ])
+ );
+ fixture.detectChanges();
+ const usageBars = fixture.debugElement.nativeElement.querySelectorAll('cd-usage-bar');
+ expect(usageBars.length).toBe(0);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts
new file mode 100644
index 00000000..f16a98b4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts
@@ -0,0 +1,189 @@
+import { ChangeDetectorRef, Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
+
+import { RgwBucketService } from '../../../shared/api/rgw-bucket.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+
+const BASE_URL = 'rgw/bucket';
+
+@Component({
+ selector: 'cd-rgw-bucket-list',
+ templateUrl: './rgw-bucket-list.component.html',
+ styleUrls: ['./rgw-bucket-list.component.scss'],
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }]
+})
+export class RgwBucketListComponent implements OnInit {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+ @ViewChild('bucketSizeTpl')
+ bucketSizeTpl: TemplateRef<any>;
+ @ViewChild('bucketObjectTpl')
+ bucketObjectTpl: TemplateRef<any>;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ columns: CdTableColumn[] = [];
+ buckets: object[] = [];
+ selection: CdTableSelection = new CdTableSelection();
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private dimlessPipe: DimlessPipe,
+ private rgwBucketService: RgwBucketService,
+ private bsModalService: BsModalService,
+ private i18n: I18n,
+ private urlBuilder: URLBuilderService,
+ public actionLabels: ActionLabelsI18n,
+ private changeDetectorRef: ChangeDetectorRef
+ ) {
+ this.permission = this.authStorageService.getPermissions().rgw;
+ const getBucketUri = () =>
+ this.selection.first() && `${encodeURIComponent(this.selection.first().bid)}`;
+ const addAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ name: this.actionLabels.CREATE
+ };
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => this.urlBuilder.getEdit(getBucketUri()),
+ name: this.actionLabels.EDIT
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteAction(),
+ name: this.actionLabels.DELETE
+ };
+ this.tableActions = [addAction, editAction, deleteAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'bid',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Owner'),
+ prop: 'owner',
+ flexGrow: 3
+ },
+ {
+ name: this.i18n('Used Capacity'),
+ prop: 'bucket_size',
+ flexGrow: 0.5,
+ pipe: this.dimlessBinaryPipe
+ },
+ {
+ name: this.i18n('Capacity Limit %'),
+ prop: 'size_usage',
+ cellTemplate: this.bucketSizeTpl,
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Objects'),
+ prop: 'num_objects',
+ flexGrow: 0.5,
+ pipe: this.dimlessPipe
+ },
+ {
+ name: this.i18n('Object Limit %'),
+ prop: 'object_usage',
+ cellTemplate: this.bucketObjectTpl,
+ flexGrow: 1
+ }
+ ];
+ }
+
+ transformBucketData() {
+ _.forEach(this.buckets, (bucketKey) => {
+ const usageList = bucketKey['usage'];
+ const maxBucketSize = bucketKey['bucket_quota']['max_size'];
+ const maxBucketObjects = bucketKey['bucket_quota']['max_objects'];
+ let totalBucketSize = 0;
+ let numOfObjects = 0;
+ _.forEach(usageList, (usageKey) => {
+ totalBucketSize = totalBucketSize + usageKey.size_actual;
+ numOfObjects = numOfObjects + usageKey.num_objects;
+ });
+ bucketKey['bucket_size'] = totalBucketSize;
+ bucketKey['num_objects'] = numOfObjects;
+ bucketKey['size_usage'] = maxBucketSize > 0 ? totalBucketSize / maxBucketSize : undefined;
+ bucketKey['object_usage'] =
+ maxBucketObjects > 0 ? numOfObjects / maxBucketObjects : undefined;
+ });
+ }
+
+ getBucketList(context: CdTableFetchDataContext) {
+ this.rgwBucketService.list().subscribe(
+ (resp: object[]) => {
+ this.buckets = resp;
+ this.transformBucketData();
+ this.changeDetectorRef.detectChanges();
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteAction() {
+ this.bsModalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.selection.hasSingleSelection
+ ? this.i18n('bucket')
+ : this.i18n('buckets'),
+ itemNames: this.selection.selected.map((bucket: any) => bucket['bid']),
+ submitActionObservable: () => {
+ return new Observable((observer: Subscriber<any>) => {
+ // Delete all selected data table rows.
+ observableForkJoin(
+ this.selection.selected.map((bucket: any) => {
+ return this.rgwBucketService.delete(bucket.bid);
+ })
+ ).subscribe(
+ null,
+ (error) => {
+ // Forward the error to the observer.
+ observer.error(error);
+ // Reload the data table content because some deletions might
+ // have been executed successfully in the meanwhile.
+ this.table.refreshBtn();
+ },
+ () => {
+ // Notify the observer that we are done.
+ observer.complete();
+ // Reload the data table content.
+ this.table.refreshBtn();
+ }
+ );
+ });
+ }
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html
new file mode 100644
index 00000000..d46bbb8c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html
@@ -0,0 +1,22 @@
+<tabset *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <cd-table-key-value [data]="metadata"
+ (fetchData)="getMetaData()">
+ </cd-table-key-value>
+ </tab>
+ <tab i18n-heading
+ heading="Performance Counters">
+ <cd-table-performance-counter serviceType="rgw"
+ [serviceId]="serviceId">
+ </cd-table-performance-counter>
+ </tab>
+ <tab i18n-heading
+ *ngIf="grafanaPermission.read"
+ heading="Performance Details">
+ <cd-grafana [grafanaPath]="'rgw-instance-detail?var-rgw_servers=rgw.' + this.selection.first().id"
+ uid="x5ARzZtmk"
+ grafanaStyle="one">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.spec.ts
new file mode 100644
index 00000000..96b6d81a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.spec.ts
@@ -0,0 +1,31 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { PerformanceCounterModule } from '../../performance-counter/performance-counter.module';
+import { RgwDaemonDetailsComponent } from './rgw-daemon-details.component';
+
+describe('RgwDaemonDetailsComponent', () => {
+ let component: RgwDaemonDetailsComponent;
+ let fixture: ComponentFixture<RgwDaemonDetailsComponent>;
+
+ configureTestBed({
+ declarations: [RgwDaemonDetailsComponent],
+ imports: [SharedModule, PerformanceCounterModule, TabsModule.forRoot(), HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwDaemonDetailsComponent);
+ component = fixture.componentInstance;
+ component.selection = new CdTableSelection();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts
new file mode 100644
index 00000000..ff9badf3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts
@@ -0,0 +1,45 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { RgwDaemonService } from '../../../shared/api/rgw-daemon.service';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-rgw-daemon-details',
+ templateUrl: './rgw-daemon-details.component.html',
+ styleUrls: ['./rgw-daemon-details.component.scss']
+})
+export class RgwDaemonDetailsComponent implements OnChanges {
+ metadata: any;
+ serviceId = '';
+ grafanaPermission: Permission;
+
+ @Input()
+ selection: CdTableSelection;
+
+ constructor(
+ private rgwDaemonService: RgwDaemonService,
+ private authStorageService: AuthStorageService
+ ) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ }
+
+ ngOnChanges() {
+ // Get the service id of the first selected row.
+ if (this.selection.hasSelection) {
+ this.serviceId = this.selection.first().id;
+ }
+ }
+
+ getMetaData() {
+ if (_.isEmpty(this.serviceId)) {
+ return;
+ }
+ this.rgwDaemonService.get(this.serviceId).subscribe((resp) => {
+ this.metadata = resp['rgw_metadata'];
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html
new file mode 100644
index 00000000..7efc3c11
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html
@@ -0,0 +1,22 @@
+<tabset>
+ <tab i18n-heading heading="Daemons List">
+ <cd-table [data]="daemons"
+ [columns]="columns"
+ columnMode="flex"
+ selectionType="single"
+ (updateSelection)="updateSelection($event)"
+ (fetchData)="getDaemonList($event)">
+ <cd-rgw-daemon-details cdTableDetail [selection]="selection">
+ </cd-rgw-daemon-details>
+ </cd-table>
+ </tab>
+
+ <tab i18n-heading
+ *ngIf="grafanaPermission.read"
+ heading="Overall Performance">
+ <cd-grafana [grafanaPath]="'rgw-overview?'"
+ uid="WAkugZpiz"
+ grafanaStyle="two">
+ </cd-grafana>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts
new file mode 100644
index 00000000..65b7102c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { PerformanceCounterModule } from '../../performance-counter/performance-counter.module';
+import { RgwDaemonDetailsComponent } from '../rgw-daemon-details/rgw-daemon-details.component';
+import { RgwDaemonListComponent } from './rgw-daemon-list.component';
+
+describe('RgwDaemonListComponent', () => {
+ let component: RgwDaemonListComponent;
+ let fixture: ComponentFixture<RgwDaemonListComponent>;
+
+ configureTestBed({
+ declarations: [RgwDaemonListComponent, RgwDaemonDetailsComponent],
+ imports: [
+ HttpClientTestingModule,
+ TabsModule.forRoot(),
+ PerformanceCounterModule,
+ SharedModule,
+ RouterTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwDaemonListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts
new file mode 100644
index 00000000..7f689615
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts
@@ -0,0 +1,65 @@
+import { Component } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { RgwDaemonService } from '../../../shared/api/rgw-daemon.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { CephShortVersionPipe } from '../../../shared/pipes/ceph-short-version.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-rgw-daemon-list',
+ templateUrl: './rgw-daemon-list.component.html',
+ styleUrls: ['./rgw-daemon-list.component.scss']
+})
+export class RgwDaemonListComponent {
+ columns: CdTableColumn[] = [];
+ daemons: object[] = [];
+ selection: CdTableSelection = new CdTableSelection();
+ grafanaPermission: Permission;
+
+ constructor(
+ private rgwDaemonService: RgwDaemonService,
+ private authStorageService: AuthStorageService,
+ cephShortVersionPipe: CephShortVersionPipe,
+ private i18n: I18n
+ ) {
+ this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+ this.columns = [
+ {
+ name: this.i18n('ID'),
+ prop: 'id',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Hostname'),
+ prop: 'server_hostname',
+ flexGrow: 2
+ },
+ {
+ name: this.i18n('Version'),
+ prop: 'version',
+ flexGrow: 1,
+ pipe: cephShortVersionPipe
+ }
+ ];
+ }
+
+ getDaemonList(context: CdTableFetchDataContext) {
+ this.rgwDaemonService.list().subscribe(
+ (resp: object[]) => {
+ this.daemons = resp;
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.html
new file mode 100644
index 00000000..5dc0cfbb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.html
@@ -0,0 +1,84 @@
+<div class="modal-header">
+ <h4 i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title pull-left">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<form class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="formGroup"
+ novalidate>
+ <div class="modal-body">
+
+ <!-- Type -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('type', frm)}">
+ <label class="control-label col-sm-3"
+ for="type">
+ <ng-container i18n>Type</ng-container>
+ <span class="required"
+ *ngIf="!editing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="type"
+ class="form-control"
+ type="text"
+ *ngIf="editing"
+ [readonly]="true"
+ formControlName="type">
+ <select id="type"
+ class="form-control"
+ formControlName="type"
+ *ngIf="!editing"
+ autofocus>
+ <option i18n
+ *ngIf="types !== null"
+ [ngValue]="null">-- Select a type --</option>
+ <option *ngFor="let type of types"
+ [value]="type">{{ type }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="formGroup.showError('type', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Permission -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('perm', frm)}">
+ <label class="control-label col-sm-3"
+ for="perm">
+ <ng-container i18n>Permission</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select id="perm"
+ class="form-control"
+ formControlName="perm">
+ <option i18n
+ [ngValue]="null">-- Select a permission --</option>
+ <option *ngFor="let perm of ['read', 'write', '*']"
+ [value]="perm">
+ {{ perm }}
+ </option>
+ </select>
+ <span class="help-block"
+ *ngIf="formGroup.showError('perm', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <cd-submit-button
+ (submitAction)="onSubmit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ [form]="formGroup">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"></cd-back-button>
+ </div>
+</form>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.spec.ts
new file mode 100644
index 00000000..c2b53d26
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.spec.ts
@@ -0,0 +1,30 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserCapabilityModalComponent } from './rgw-user-capability-modal.component';
+
+describe('RgwUserCapabilityModalComponent', () => {
+ let component: RgwUserCapabilityModalComponent;
+ let fixture: ComponentFixture<RgwUserCapabilityModalComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserCapabilityModalComponent],
+ imports: [ReactiveFormsModule, SharedModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserCapabilityModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.ts
new file mode 100644
index 00000000..d890aa90
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-capability-modal/rgw-user-capability-modal.component.ts
@@ -0,0 +1,94 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { Validators } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { RgwUserCapabilities } from '../models/rgw-user-capabilities';
+import { RgwUserCapability } from '../models/rgw-user-capability';
+
+@Component({
+ selector: 'cd-rgw-user-capability-modal',
+ templateUrl: './rgw-user-capability-modal.component.html',
+ styleUrls: ['./rgw-user-capability-modal.component.scss']
+})
+export class RgwUserCapabilityModalComponent {
+ /**
+ * The event that is triggered when the 'Add' or 'Update' button
+ * has been pressed.
+ */
+ @Output()
+ submitAction = new EventEmitter();
+
+ formGroup: CdFormGroup;
+ editing = true;
+ types: string[] = [];
+ resource: string;
+ action: string;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ public bsModalRef: BsModalRef,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('capability');
+ this.createForm();
+ }
+
+ createForm() {
+ this.formGroup = this.formBuilder.group({
+ type: [null, [Validators.required]],
+ perm: [null, [Validators.required]]
+ });
+ }
+
+ /**
+ * Set the 'editing' flag. If set to TRUE, the modal dialog is in 'Edit' mode,
+ * otherwise in 'Add' mode. According to the mode the dialog and its controls
+ * behave different.
+ * @param {boolean} viewing
+ */
+ setEditing(editing: boolean = true) {
+ this.editing = editing;
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.ADD;
+ }
+
+ /**
+ * Set the values displayed in the dialog.
+ */
+ setValues(type: string, perm: string) {
+ this.formGroup.setValue({
+ type: type,
+ perm: perm
+ });
+ }
+
+ /**
+ * Set the current capabilities of the user.
+ */
+ setCapabilities(capabilities: RgwUserCapability[]) {
+ // Parse the configured capabilities to get a list of types that
+ // should be displayed.
+ const usedTypes = [];
+ capabilities.forEach((capability) => {
+ usedTypes.push(capability.type);
+ });
+ this.types = [];
+ RgwUserCapabilities.getAll().forEach((type) => {
+ if (_.indexOf(usedTypes, type) === -1) {
+ this.types.push(type);
+ }
+ });
+ }
+
+ onSubmit() {
+ const capability: RgwUserCapability = this.formGroup.value;
+ this.submitAction.emit(capability);
+ this.bsModalRef.hide();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.html
new file mode 100644
index 00000000..7ae1c088
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.html
@@ -0,0 +1,155 @@
+<tabset *ngIf="selection.hasSingleSelection">
+ <tab i18n-heading
+ heading="Details">
+ <div *ngIf="user">
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Username</td>
+ <td class="col-sm-3">{{ user.uid }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Full name</td>
+ <td class="col-sm-3">{{ user.display_name }}</td>
+ </tr>
+ <tr *ngIf="user.email?.length">
+ <td i18n
+ class="bold col-sm-1">Email address</td>
+ <td class="col-sm-3">{{ user.email }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Suspended</td>
+ <td class="col-sm-3">{{ user.suspended | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">System</td>
+ <td class="col-sm-3">{{ user.system === 'true' | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum buckets</td>
+ <td class="col-sm-3">{{ user.max_buckets| map:maxBucketsMap }}</td>
+ </tr>
+ <tr *ngIf="user.subusers && user.subusers.length">
+ <td i18n
+ class="bold col-sm-1">Subusers</td>
+ <td class="col-sm-3">
+ <div *ngFor="let subuser of user.subusers">
+ {{ subuser.id }} ({{ subuser.permissions }})
+ </div>
+ </td>
+ </tr>
+ <tr *ngIf="user.caps && user.caps.length">
+ <td i18n
+ class="bold col-sm-1">Capabilities</td>
+ <td class="col-sm-3">
+ <div *ngFor="let cap of user.caps">
+ {{ cap.type }} ({{ cap.perm }})
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <!-- User quota -->
+ <div *ngIf="user.user_quota">
+ <legend i18n>User quota</legend>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Enabled</td>
+ <td class="col-sm-3">{{ user.user_quota.enabled | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum size</td>
+ <td *ngIf="user.user_quota.max_size <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="user.user_quota.max_size > -1"
+ class="col-sm-3">
+ {{ user.user_quota.max_size | dimlessBinary }}
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum objects</td>
+ <td *ngIf="user.user_quota.max_objects <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="user.user_quota.max_objects > -1"
+ class="col-sm-3">
+ {{ user.user_quota.max_objects }}
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <!-- Bucket quota -->
+ <div *ngIf="user.bucket_quota">
+ <legend i18n>Bucket quota</legend>
+ <table class="table table-striped table-bordered">
+ <tbody>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Enabled</td>
+ <td class="col-sm-3">{{ user.bucket_quota.enabled | booleanText }}</td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum size</td>
+ <td *ngIf="user.bucket_quota.max_size <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="user.bucket_quota.max_size > -1"
+ class="col-sm-3">
+ {{ user.bucket_quota.max_size | dimlessBinary }}
+ </td>
+ </tr>
+ <tr>
+ <td i18n
+ class="bold col-sm-1">Maximum objects</td>
+ <td *ngIf="user.bucket_quota.max_objects <= -1"
+ i18n
+ class="col-sm-3">Unlimited</td>
+ <td *ngIf="user.bucket_quota.max_objects > -1"
+ class="col-sm-3">
+ {{ user.bucket_quota.max_objects }}
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </tab>
+
+ <tab *ngIf="keys.length"
+ i18n-heading
+ heading="Keys">
+ <cd-table [data]="keys"
+ [columns]="keysColumns"
+ columnMode="flex"
+ selectionType="multi"
+ forceIdentifier="true"
+ (updateSelection)="updateKeysSelection($event)">
+ <div class="table-actions">
+ <div class="btn-group"
+ dropdown>
+ <button type="button"
+ class="btn btn-sm btn-primary"
+ [disabled]="!keysSelection.hasSingleSelection"
+ (click)="showKeyModal()">
+ <i class="fa fa-eye"></i>
+ <ng-container i18n>Show</ng-container>
+ </button>
+ </div>
+ </div>
+ </cd-table>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.spec.ts
new file mode 100644
index 00000000..dc5aa35a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.spec.ts
@@ -0,0 +1,85 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserS3Key } from '../models/rgw-user-s3-key';
+import { RgwUserDetailsComponent } from './rgw-user-details.component';
+
+describe('RgwUserDetailsComponent', () => {
+ let component: RgwUserDetailsComponent;
+ let fixture: ComponentFixture<RgwUserDetailsComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserDetailsComponent],
+ imports: [HttpClientTestingModule, SharedModule, TabsModule.forRoot()],
+ providers: [BsModalService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserDetailsComponent);
+ component = fixture.componentInstance;
+ component.selection = new CdTableSelection();
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+
+ const detailsTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Details"]');
+ expect(detailsTab).toBeFalsy();
+ const keysTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Keys"]');
+ expect(keysTab).toBeFalsy();
+ });
+
+ it('should show "Details" tab', () => {
+ component.selection.selected = [{ uid: 'myUsername' }];
+ component.selection.hasSingleSelection = true;
+ fixture.detectChanges();
+
+ const detailsTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Details"]');
+ expect(detailsTab).toBeTruthy();
+ const keysTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Keys"]');
+ expect(keysTab).toBeFalsy();
+ });
+
+ it('should show "Keys" tab', () => {
+ const s3Key = new RgwUserS3Key();
+ component.selection.selected = [{ keys: [s3Key] }];
+ component.selection.hasSingleSelection = true;
+ component.selection.hasSelection = true;
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const detailsTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Details"]');
+ expect(detailsTab).toBeTruthy();
+ const keysTab = fixture.debugElement.nativeElement.querySelector('tab[heading="Keys"]');
+ expect(keysTab).toBeTruthy();
+ });
+
+ it('should show correct "System" info', () => {
+ component.selection.selected = [
+ { uid: '', email: '', system: 'true', keys: [], swift_keys: [] }
+ ];
+ component.selection.hasSelection = true;
+ component.selection.hasSingleSelection = true;
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const detailsTab = fixture.debugElement.nativeElement.querySelectorAll(
+ '.table.table-striped.table-bordered tr td'
+ );
+ expect(detailsTab[6].textContent).toEqual('System');
+ expect(detailsTab[7].textContent).toEqual('Yes');
+
+ component.selection.selected[0].system = 'false';
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ expect(detailsTab[7].textContent).toEqual('No');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.ts
new file mode 100644
index 00000000..b7ff6119
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-details/rgw-user-details.component.ts
@@ -0,0 +1,122 @@
+import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { RgwUserS3Key } from '../models/rgw-user-s3-key';
+import { RgwUserSwiftKey } from '../models/rgw-user-swift-key';
+import { RgwUserS3KeyModalComponent } from '../rgw-user-s3-key-modal/rgw-user-s3-key-modal.component';
+import { RgwUserSwiftKeyModalComponent } from '../rgw-user-swift-key-modal/rgw-user-swift-key-modal.component';
+
+@Component({
+ selector: 'cd-rgw-user-details',
+ templateUrl: './rgw-user-details.component.html',
+ styleUrls: ['./rgw-user-details.component.scss']
+})
+export class RgwUserDetailsComponent implements OnChanges, OnInit {
+ @ViewChild('accessKeyTpl')
+ public accessKeyTpl: TemplateRef<any>;
+ @ViewChild('secretKeyTpl')
+ public secretKeyTpl: TemplateRef<any>;
+
+ @Input()
+ selection: CdTableSelection;
+
+ // Details tab
+ user: any;
+ maxBucketsMap: {};
+
+ // Keys tab
+ keys: any = [];
+ keysColumns: CdTableColumn[] = [];
+ keysSelection: CdTableSelection = new CdTableSelection();
+
+ constructor(
+ private rgwUserService: RgwUserService,
+ private bsModalService: BsModalService,
+ private i18n: I18n
+ ) {}
+
+ ngOnInit() {
+ this.keysColumns = [
+ {
+ name: this.i18n('Username'),
+ prop: 'username',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Type'),
+ prop: 'type',
+ flexGrow: 1
+ }
+ ];
+ this.maxBucketsMap = {
+ '-1': this.i18n('Disabled'),
+ 0: this.i18n('Unlimited')
+ };
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.user = this.selection.first();
+
+ // Sort subusers and capabilities.
+ this.user.subusers = _.sortBy(this.user.subusers, 'id');
+ this.user.caps = _.sortBy(this.user.caps, 'type');
+
+ // Load the user/bucket quota of the selected user.
+ this.rgwUserService.getQuota(this.user.uid).subscribe((resp: object) => {
+ _.extend(this.user, resp);
+ });
+
+ // Process the keys.
+ this.keys = [];
+ if (this.user.keys) {
+ this.user.keys.forEach((key: RgwUserS3Key) => {
+ this.keys.push({
+ id: this.keys.length + 1, // Create an unique identifier
+ type: 'S3',
+ username: key.user,
+ ref: key
+ });
+ });
+ }
+ if (this.user.swift_keys) {
+ this.user.swift_keys.forEach((key: RgwUserSwiftKey) => {
+ this.keys.push({
+ id: this.keys.length + 1, // Create an unique identifier
+ type: 'Swift',
+ username: key.user,
+ ref: key
+ });
+ });
+ }
+
+ this.keys = _.sortBy(this.keys, 'user');
+ }
+ }
+
+ updateKeysSelection(selection: CdTableSelection) {
+ this.keysSelection = selection;
+ }
+
+ showKeyModal() {
+ const key = this.keysSelection.first();
+ const modalRef = this.bsModalService.show(
+ key.type === 'S3' ? RgwUserS3KeyModalComponent : RgwUserSwiftKeyModalComponent
+ );
+ switch (key.type) {
+ case 'S3':
+ modalRef.content.setViewing();
+ modalRef.content.setValues(key.ref.user, key.ref.access_key, key.ref.secret_key);
+ break;
+ case 'Swift':
+ modalRef.content.setValues(key.ref.user, key.ref.secret_key);
+ break;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html
new file mode 100644
index 00000000..75abab51
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.html
@@ -0,0 +1,623 @@
+<cd-loading-panel *ngIf="editing && loading && !error"
+ i18n>Loading user data...</cd-loading-panel>
+<cd-error-panel *ngIf="editing && error"
+ (backAction)="goToListView()"
+ i18n>The user data could not be loaded.</cd-error-panel>
+
+<div class="col-sm-12 col-lg-6"
+ *ngIf="!loading && !error">
+ <form class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="userForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Username -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('uid', frm)}">
+ <label class="control-label col-sm-3"
+ for="uid">
+ <ng-container i18n>Username</ng-container>
+ <span class="required"
+ *ngIf="!editing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="uid"
+ class="form-control"
+ type="text"
+ formControlName="uid"
+ [readonly]="editing"
+ autofocus>
+ <span class="help-block"
+ *ngIf="userForm.showError('uid', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('uid', frm, 'notUnique')"
+ i18n>The chosen user ID is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Full name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('display_name', frm)}">
+ <label class="control-label col-sm-3"
+ for="display_name">
+ <ng-container i18n>Full name</ng-container>
+ <span class="required"
+ *ngIf="!editing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="display_name"
+ class="form-control"
+ type="text"
+ formControlName="display_name">
+ <span class="help-block"
+ *ngIf="userForm.showError('display_name', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Email address -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('email', frm)}">
+ <label class="control-label col-sm-3"
+ for="email"
+ i18n>Email address</label>
+ <div class="col-sm-9">
+ <input id="email"
+ class="form-control"
+ type="text"
+ formControlName="email">
+ <span class="help-block"
+ *ngIf="userForm.showError('email', frm, 'email')"
+ i18n>This is not a valid email address.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('email', frm, 'notUnique')"
+ i18n>The chosen email address is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Max. buckets -->
+ <div class="form-group">
+ <label class="control-label col-sm-3"
+ for="max_buckets_mode"
+ i18n>Max. buckets</label>
+ <div class="col-sm-9">
+ <select class="form-control"
+ formControlName="max_buckets_mode"
+ name="max_buckets_mode"
+ id="max_buckets_mode"
+ (change)="onMaxBucketsModeChange($event.target.value)">
+ <option i18n
+ value="-1">Disabled</option>
+ <option i18n
+ value="0">Unlimited</option>
+ <option i18n
+ value="1">Custom</option>
+ </select>
+ </div>
+ </div>
+ <div *ngIf="1 == userForm.get('max_buckets_mode').value"
+ class="form-group"
+ [ngClass]="{'has-error': userForm.showError('max_buckets', frm)}">
+ <label class="control-label col-sm-3"></label>
+ <div class="col-sm-9">
+ <input id="max_buckets"
+ class="form-control"
+ type="number"
+ formControlName="max_buckets"
+ min="1">
+ <span class="help-block"
+ *ngIf="userForm.showError('max_buckets', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('max_buckets', frm, 'min')"
+ i18n>The entered value must be >= 1.</span>
+ </div>
+ </div>
+
+ <!-- Suspended -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="suspended"
+ type="checkbox"
+ formControlName="suspended">
+ <label for="suspended"
+ i18n>Suspended</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- S3 key -->
+ <fieldset *ngIf="!editing">
+ <legend i18n>S3 key</legend>
+
+ <!-- Auto-generate key -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="generate_key"
+ type="checkbox"
+ formControlName="generate_key">
+ <label for="generate_key"
+ i18n>Auto-generate key</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Access key -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('access_key', frm)}"
+ *ngIf="!editing && !userForm.getValue('generate_key')">
+ <label class="control-label col-sm-3"
+ for="access_key">
+ <ng-container i18n>Access key</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="access_key"
+ class="form-control"
+ type="password"
+ formControlName="access_key">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="access_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="access_key">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="userForm.showError('access_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Secret key -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('secret_key', frm)}"
+ *ngIf="!editing && !userForm.getValue('generate_key')">
+ <label class="control-label col-sm-3"
+ for="secret_key">
+ <ng-container i18n>Secret key</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="secret_key"
+ class="form-control"
+ type="password"
+ formControlName="secret_key">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="secret_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="secret_key">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="userForm.showError('secret_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+ </fieldset>
+
+ <!-- Subusers -->
+ <fieldset *ngIf="editing">
+ <legend i18n>Subusers</legend>
+
+ <div class="col-sm-offset-3 col-sm-9">
+ <span *ngIf="subusers.length === 0"
+ class="form-control no-border">
+ <span class="text-muted"
+ i18n>There are no subusers.</span>
+ </span>
+
+ <span *ngFor="let subuser of subusers; let i=index;">
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="icon-prepend fa fa-user"></i>
+ </span>
+ <input type="text"
+ class="form-control"
+ value="{{ subuser.id }}"
+ readonly>
+ <span class="input-group-addon"
+ style="border-left: 0; border-right: 0;">
+ <i class="icon-prepend fa fa-share-alt"></i>
+ </span>
+ <input type="text"
+ class="form-control"
+ value="{{ ('full-control' === subuser.permissions) ? 'full' : subuser.permissions }}"
+ readonly>
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default tc_showSubuserButton"
+ i18n-tooltip
+ tooltip="Edit"
+ (click)="showSubuserModal(i)">
+ <i class="fa fa-cogs"></i>
+ </button>
+ <button type="button"
+ class="btn btn-default tc_deleteSubuserButton"
+ i18n-tooltip
+ tooltip="Delete"
+ (click)="deleteSubuser(i)">
+ <i class="fa fa-times"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"></span>
+ </span>
+
+ <span class="form-control no-border">
+ <button type="button"
+ class="btn btn-sm btn-default btn-label pull-right tc_addSubuserButton"
+ (click)="showSubuserModal()">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>{{ actionLabels.CREATE | titlecase }} {{ subuserLabel | upperFirst }}</ng-container>
+ </button>
+ </span>
+ </div>
+ </fieldset>
+
+ <!-- Keys -->
+ <fieldset *ngIf="editing">
+ <legend i18n>Keys</legend>
+
+ <!-- S3 keys -->
+ <label class="col-sm-3 control-label"
+ i18n>S3</label>
+ <div class="col-sm-9">
+ <span *ngIf="s3Keys.length === 0"
+ class="form-control no-border">
+ <span class="text-muted"
+ i18n>There are no keys.</span>
+ </span>
+
+ <span *ngFor="let key of s3Keys; let i=index;">
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="icon-prepend fa fa-key"></i>
+ </span>
+ <input type="text"
+ class="form-control"
+ value="{{ key.user }}"
+ readonly>
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default tc_showS3KeyButton"
+ i18n-tooltip
+ tooltip="Show"
+ (click)="showS3KeyModal(i)">
+ <i class="fa fa-eye"></i>
+ </button>
+ <button type="button"
+ class="btn btn-default tc_deleteS3KeyButton"
+ i18n-tooltip
+ tooltip="Delete"
+ (click)="deleteS3Key(i)">
+ <i class="fa fa-times"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"></span>
+ </span>
+
+ <span class="form-control no-border">
+ <button type="button"
+ class="btn btn-sm btn-default btn-label pull-right tc_addS3KeyButton"
+ (click)="showS3KeyModal()">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>{{ actionLabels.CREATE | titlecase }} {{ s3keyLabel | upperFirst }}</ng-container>
+ </button>
+ </span>
+ <hr>
+ </div>
+
+ <!-- Swift keys -->
+ <label class="col-sm-3 control-label"
+ i18n>Swift</label>
+ <div class="col-sm-9">
+ <span *ngIf="swiftKeys.length === 0"
+ class="form-control no-border">
+ <span class="text-muted"
+ i18n>There are no keys.</span>
+ </span>
+
+ <span *ngFor="let key of swiftKeys; let i=index;">
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="icon-prepend fa fa-key"></i>
+ </span>
+ <input type="text"
+ class="form-control"
+ value="{{ key.user }}"
+ readonly>
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default tc_showSwiftKeyButton"
+ i18n-tooltip
+ tooltip="Show"
+ (click)="showSwiftKeyModal(i)">
+ <i class="fa fa-eye"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"></span>
+ </span>
+ </div>
+ </fieldset>
+
+ <!-- Capabilities -->
+ <fieldset *ngIf="editing">
+ <legend i18n>Capabilities</legend>
+
+ <div class="col-sm-offset-3 col-sm-9">
+ <span *ngIf="capabilities.length === 0"
+ class="form-control no-border">
+ <span class="text-muted"
+ i18n>There are no capabilities.</span>
+ </span>
+
+ <span *ngFor="let cap of capabilities; let i=index;">
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="icon-prepend fa fa-share-alt"></i>
+ </span>
+ <input type="text"
+ class="form-control"
+ value="{{ cap.type }}:{{ cap.perm }}"
+ readonly>
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default tc_editCapButton"
+ i18n-tooltip
+ tooltip="Edit"
+ (click)="showCapabilityModal(i)">
+ <i class="fa fa-cogs"></i>
+ </button>
+ <button type="button"
+ class="btn btn-default tc_deleteCapButton"
+ i18n-tooltip
+ tooltip="Delete"
+ (click)="deleteCapability(i)">
+ <i class="fa fa-times"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"></span>
+ </span>
+
+ <span class="form-control no-border">
+ <button type="button"
+ class="btn btn-sm btn-default btn-label pull-right tc_addCapButton"
+ [disabled]="hasAllCapabilities()"
+ i18n-tooltip
+ tooltip="All capabilities are already added."
+ [isDisabled]="!hasAllCapabilities()"
+ triggers="pointerenter pointerleave"
+ (click)="showCapabilityModal()">
+ <i class="fa fa-fw fa-plus"></i>
+ <ng-container i18n>{{ actionLabels.ADD | titlecase }} {{ capabilityLabel | upperFirst }}</ng-container>
+ </button>
+ </span>
+ </div>
+ </fieldset>
+
+ <!-- User quota -->
+ <fieldset>
+ <legend i18n>User quota</legend>
+
+ <!-- Enabled -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="user_quota_enabled"
+ type="checkbox"
+ formControlName="user_quota_enabled">
+ <label for="user_quota_enabled"
+ i18n>Enabled</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Unlimited size -->
+ <div class="form-group"
+ *ngIf="userForm.controls.user_quota_enabled.value">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="user_quota_max_size_unlimited"
+ type="checkbox"
+ formControlName="user_quota_max_size_unlimited">
+ <label for="user_quota_max_size_unlimited"
+ i18n>Unlimited size</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Maximum size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('user_quota_max_size', frm)}"
+ *ngIf="!userForm.getValue('user_quota_max_size_unlimited')">
+ <label class="control-label col-sm-3"
+ for="user_quota_max_size">
+ <ng-container i18n>Max. size</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="user_quota_max_size"
+ class="form-control"
+ type="text"
+ formControlName="user_quota_max_size"
+ cdDimlessBinary>
+ <span class="help-block"
+ *ngIf="userForm.showError('user_quota_max_size', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('user_quota_max_size', frm, 'quotaMaxSize')"
+ i18n>The value is not valid.</span>
+ </div>
+ </div>
+
+ <!-- Unlimited objects -->
+ <div class="form-group"
+ *ngIf="userForm.controls.user_quota_enabled.value">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="user_quota_max_objects_unlimited"
+ type="checkbox"
+ formControlName="user_quota_max_objects_unlimited">
+ <label for="user_quota_max_objects_unlimited"
+ i18n>Unlimited objects</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Maximum objects -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('user_quota_max_objects', frm)}"
+ *ngIf="!userForm.getValue('user_quota_max_objects_unlimited')">
+ <label class="control-label col-sm-3"
+ for="user_quota_max_objects">
+ <ng-container i18n>Max. objects</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="user_quota_max_objects"
+ class="form-control"
+ type="number"
+ formControlName="user_quota_max_objects">
+ <span class="help-block"
+ *ngIf="userForm.showError('user_quota_max_objects', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('user_quota_max_objects', frm, 'min')"
+ i18n>The entered value must be >= 0.</span>
+ </div>
+ </div>
+ </fieldset>
+
+ <!-- Bucket quota -->
+ <fieldset>
+ <legend i18n>Bucket quota</legend>
+
+ <!-- Enabled -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="bucket_quota_enabled"
+ type="checkbox"
+ formControlName="bucket_quota_enabled">
+ <label for="bucket_quota_enabled"
+ i18n>Enabled</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Unlimited size -->
+ <div class="form-group"
+ *ngIf="userForm.controls.bucket_quota_enabled.value">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="bucket_quota_max_size_unlimited"
+ type="checkbox"
+ formControlName="bucket_quota_max_size_unlimited">
+ <label for="bucket_quota_max_size_unlimited"
+ i18n>Unlimited size</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Maximum size -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('bucket_quota_max_size', frm)}"
+ *ngIf="!userForm.getValue('bucket_quota_max_size_unlimited')">
+ <label class="control-label col-sm-3"
+ for="bucket_quota_max_size">
+ <ng-container i18n>Max. size</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="bucket_quota_max_size"
+ class="form-control"
+ type="text"
+ formControlName="bucket_quota_max_size"
+ cdDimlessBinary>
+ <span class="help-block"
+ *ngIf="userForm.showError('bucket_quota_max_size', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('bucket_quota_max_size', frm, 'quotaMaxSize')"
+ i18n>The value is not valid.</span>
+ </div>
+ </div>
+
+ <!-- Unlimited objects -->
+ <div class="form-group"
+ *ngIf="userForm.controls.bucket_quota_enabled.value">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="bucket_quota_max_objects_unlimited"
+ type="checkbox"
+ formControlName="bucket_quota_max_objects_unlimited">
+ <label for="bucket_quota_max_objects_unlimited"
+ i18n>Unlimited objects</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Maximum objects -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('bucket_quota_max_objects', frm)}"
+ *ngIf="!userForm.getValue('bucket_quota_max_objects_unlimited')">
+ <label class="control-label col-sm-3"
+ for="bucket_quota_max_objects">
+ <ng-container i18n>Max. objects</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <input id="bucket_quota_max_objects"
+ class="form-control"
+ type="number"
+ formControlName="bucket_quota_max_objects">
+ <span class="help-block"
+ *ngIf="userForm.showError('bucket_quota_max_objects', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('bucket_quota_max_objects', frm, 'min')"
+ i18n>The entered value must be >= 0.</span>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ (submitAction)="onSubmit()"
+ [form]="userForm"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.scss
new file mode 100644
index 00000000..7ac12c1f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.scss
@@ -0,0 +1,6 @@
+@import '../../../../defaults';
+
+form .input-group-addon {
+ color: $color-rgw-icon !important;
+ background-color: transparent;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts
new file mode 100644
index 00000000..4eb8c278
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts
@@ -0,0 +1,339 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf, throwError } from 'rxjs';
+
+import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper';
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserCapabilities } from '../models/rgw-user-capabilities';
+import { RgwUserCapability } from '../models/rgw-user-capability';
+import { RgwUserS3Key } from '../models/rgw-user-s3-key';
+import { RgwUserFormComponent } from './rgw-user-form.component';
+
+describe('RgwUserFormComponent', () => {
+ let component: RgwUserFormComponent;
+ let fixture: ComponentFixture<RgwUserFormComponent>;
+ let rgwUserService: RgwUserService;
+ let formHelper: FormHelper;
+
+ configureTestBed({
+ declarations: [RgwUserFormComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot(),
+ TooltipModule.forRoot()
+ ],
+ providers: [BsModalService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserFormComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ rgwUserService = TestBed.get(RgwUserService);
+ formHelper = new FormHelper(component.userForm);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('s3 key management', () => {
+ beforeEach(() => {
+ spyOn(rgwUserService, 'addS3Key').and.stub();
+ });
+
+ it('should not update key', () => {
+ component.setS3Key(new RgwUserS3Key(), 3);
+ expect(component.s3Keys.length).toBe(0);
+ expect(rgwUserService.addS3Key).not.toHaveBeenCalled();
+ });
+
+ it('should set user defined key', () => {
+ const key = new RgwUserS3Key();
+ key.user = 'test1:subuser2';
+ key.access_key = 'my-access-key';
+ key.secret_key = 'my-secret-key';
+ component.setS3Key(key);
+ expect(component.s3Keys.length).toBe(1);
+ expect(component.s3Keys[0].user).toBe('test1:subuser2');
+ expect(rgwUserService.addS3Key).toHaveBeenCalledWith('test1', {
+ subuser: 'subuser2',
+ generate_key: 'false',
+ access_key: 'my-access-key',
+ secret_key: 'my-secret-key'
+ });
+ });
+
+ it('should set params for auto-generating key', () => {
+ const key = new RgwUserS3Key();
+ key.user = 'test1:subuser2';
+ key.generate_key = true;
+ key.access_key = 'my-access-key';
+ key.secret_key = 'my-secret-key';
+ component.setS3Key(key);
+ expect(component.s3Keys.length).toBe(1);
+ expect(component.s3Keys[0].user).toBe('test1:subuser2');
+ expect(rgwUserService.addS3Key).toHaveBeenCalledWith('test1', {
+ subuser: 'subuser2',
+ generate_key: 'true'
+ });
+ });
+
+ it('should set key w/o subuser', () => {
+ const key = new RgwUserS3Key();
+ key.user = 'test1';
+ component.setS3Key(key);
+ expect(component.s3Keys.length).toBe(1);
+ expect(component.s3Keys[0].user).toBe('test1');
+ expect(rgwUserService.addS3Key).toHaveBeenCalledWith('test1', {
+ subuser: '',
+ generate_key: 'false',
+ access_key: undefined,
+ secret_key: undefined
+ });
+ });
+ });
+
+ describe('quotaMaxSizeValidator', () => {
+ it('should validate max size (1)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl(''));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate max size (2)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('xxxx'));
+ expect(resp.quotaMaxSize).toBeTruthy();
+ });
+
+ it('should validate max size (3)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1023'));
+ expect(resp.quotaMaxSize).toBeTruthy();
+ });
+
+ it('should validate max size (4)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1024'));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate max size (5)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1M'));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate max size (6)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1024 gib'));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate max size (7)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('10 X'));
+ expect(resp.quotaMaxSize).toBeTruthy();
+ });
+
+ it('should validate max size (8)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1.085 GiB'));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate max size (9)', () => {
+ const resp = component.quotaMaxSizeValidator(new FormControl('1,085 GiB'));
+ expect(resp.quotaMaxSize).toBeTruthy();
+ });
+ });
+
+ describe('username validation', () => {
+ it('should validate that username is required', () => {
+ formHelper.expectErrorChange('uid', '', 'required', true);
+ });
+
+ it('should validate that username is valid', fakeAsync(() => {
+ spyOn(rgwUserService, 'get').and.returnValue(throwError('foo'));
+ formHelper.setValue('uid', 'ab', true);
+ tick(500);
+ formHelper.expectValid('uid');
+ }));
+
+ it('should validate that username is invalid', fakeAsync(() => {
+ spyOn(rgwUserService, 'get').and.returnValue(observableOf({}));
+ formHelper.setValue('uid', 'abc', true);
+ tick(500);
+ formHelper.expectError('uid', 'notUnique');
+ }));
+ });
+
+ describe('max buckets', () => {
+ it('disable creation (create)', () => {
+ spyOn(rgwUserService, 'create');
+ formHelper.setValue('max_buckets_mode', -1, true);
+ component.onSubmit();
+ expect(rgwUserService.create).toHaveBeenCalledWith({
+ access_key: '',
+ display_name: null,
+ email: '',
+ generate_key: true,
+ max_buckets: -1,
+ secret_key: '',
+ suspended: false,
+ uid: null
+ });
+ });
+
+ it('disable creation (edit)', () => {
+ spyOn(rgwUserService, 'update');
+ component.editing = true;
+ formHelper.setValue('max_buckets_mode', -1, true);
+ component.onSubmit();
+ expect(rgwUserService.update).toHaveBeenCalledWith(null, {
+ display_name: null,
+ email: null,
+ max_buckets: -1,
+ suspended: false
+ });
+ });
+
+ it('unlimited buckets (create)', () => {
+ spyOn(rgwUserService, 'create');
+ formHelper.setValue('max_buckets_mode', 0, true);
+ component.onSubmit();
+ expect(rgwUserService.create).toHaveBeenCalledWith({
+ access_key: '',
+ display_name: null,
+ email: '',
+ generate_key: true,
+ max_buckets: 0,
+ secret_key: '',
+ suspended: false,
+ uid: null
+ });
+ });
+
+ it('unlimited buckets (edit)', () => {
+ spyOn(rgwUserService, 'update');
+ component.editing = true;
+ formHelper.setValue('max_buckets_mode', 0, true);
+ component.onSubmit();
+ expect(rgwUserService.update).toHaveBeenCalledWith(null, {
+ display_name: null,
+ email: null,
+ max_buckets: 0,
+ suspended: false
+ });
+ });
+
+ it('custom (create)', () => {
+ spyOn(rgwUserService, 'create');
+ formHelper.setValue('max_buckets_mode', 1, true);
+ formHelper.setValue('max_buckets', 100, true);
+ component.onSubmit();
+ expect(rgwUserService.create).toHaveBeenCalledWith({
+ access_key: '',
+ display_name: null,
+ email: '',
+ generate_key: true,
+ max_buckets: 100,
+ secret_key: '',
+ suspended: false,
+ uid: null
+ });
+ });
+
+ it('custom (edit)', () => {
+ spyOn(rgwUserService, 'update');
+ component.editing = true;
+ formHelper.setValue('max_buckets_mode', 1, true);
+ formHelper.setValue('max_buckets', 100, true);
+ component.onSubmit();
+ expect(rgwUserService.update).toHaveBeenCalledWith(null, {
+ display_name: null,
+ email: null,
+ max_buckets: 100,
+ suspended: false
+ });
+ });
+ });
+
+ describe('submit form', () => {
+ let notificationService: NotificationService;
+
+ beforeEach(() => {
+ spyOn(TestBed.get(Router), 'navigate').and.stub();
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show');
+ });
+
+ it('should be able to clear the mail field on update', () => {
+ spyOn(rgwUserService, 'update');
+ component.editing = true;
+ formHelper.setValue('email', '', true);
+ component.onSubmit();
+ expect(rgwUserService.update).toHaveBeenCalledWith(null, {
+ display_name: null,
+ email: '',
+ max_buckets: 1000,
+ suspended: false
+ });
+ });
+
+ it('tests create success notification', () => {
+ spyOn(rgwUserService, 'create').and.returnValue(observableOf([]));
+ component.editing = false;
+ formHelper.setValue('suspended', true, true);
+ component.onSubmit();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Created Object Gateway user ""'
+ );
+ });
+
+ it('tests update success notification', () => {
+ spyOn(rgwUserService, 'update').and.returnValue(observableOf([]));
+ component.editing = true;
+ formHelper.setValue('suspended', true, true);
+ component.onSubmit();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ NotificationType.success,
+ 'Updated Object Gateway user ""'
+ );
+ });
+ });
+
+ describe('RgwUserCapabilities', () => {
+ it('capability button disabled when all capabilities are added', () => {
+ component.editing = true;
+ for (const capabilityType of RgwUserCapabilities.getAll()) {
+ const capability = new RgwUserCapability();
+ capability.type = capabilityType;
+ capability.perm = 'read';
+ component.setCapability(capability);
+ }
+
+ fixture.detectChanges();
+
+ expect(component.hasAllCapabilities()).toBeTruthy();
+ const capabilityButton = fixture.debugElement.nativeElement.querySelector('.tc_addCapButton');
+ expect(capabilityButton.disabled).toBeTruthy();
+ });
+
+ it('capability button not disabled when not all capabilities are added', () => {
+ component.editing = true;
+
+ fixture.detectChanges();
+
+ const capabilityButton = fixture.debugElement.nativeElement.querySelector('.tc_addCapButton');
+ expect(capabilityButton.disabled).toBeFalsy();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts
new file mode 100644
index 00000000..6e517864
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts
@@ -0,0 +1,713 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, ValidationErrors, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { concat as observableConcat, forkJoin as observableForkJoin, Observable } from 'rxjs';
+
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators, isEmptyInputValue } from '../../../shared/forms/cd-validators';
+import { FormatterService } from '../../../shared/services/formatter.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { RgwUserCapabilities } from '../models/rgw-user-capabilities';
+import { RgwUserCapability } from '../models/rgw-user-capability';
+import { RgwUserS3Key } from '../models/rgw-user-s3-key';
+import { RgwUserSubuser } from '../models/rgw-user-subuser';
+import { RgwUserSwiftKey } from '../models/rgw-user-swift-key';
+import { RgwUserCapabilityModalComponent } from '../rgw-user-capability-modal/rgw-user-capability-modal.component';
+import { RgwUserS3KeyModalComponent } from '../rgw-user-s3-key-modal/rgw-user-s3-key-modal.component';
+import { RgwUserSubuserModalComponent } from '../rgw-user-subuser-modal/rgw-user-subuser-modal.component';
+import { RgwUserSwiftKeyModalComponent } from '../rgw-user-swift-key-modal/rgw-user-swift-key-modal.component';
+
+@Component({
+ selector: 'cd-rgw-user-form',
+ templateUrl: './rgw-user-form.component.html',
+ styleUrls: ['./rgw-user-form.component.scss']
+})
+export class RgwUserFormComponent implements OnInit {
+ userForm: CdFormGroup;
+ editing = false;
+ error = false;
+ loading = false;
+ submitObservables: Observable<Object>[] = [];
+
+ subusers: RgwUserSubuser[] = [];
+ s3Keys: RgwUserS3Key[] = [];
+ swiftKeys: RgwUserSwiftKey[] = [];
+ capabilities: RgwUserCapability[] = [];
+
+ action: string;
+ resource: string;
+ subuserLabel: string;
+ s3keyLabel: string;
+ capabilityLabel: string;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ private route: ActivatedRoute,
+ private router: Router,
+ private rgwUserService: RgwUserService,
+ private bsModalService: BsModalService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('user');
+ this.subuserLabel = this.i18n('subuser');
+ this.s3keyLabel = this.i18n('S3 Key');
+ this.capabilityLabel = this.i18n('capability');
+ this.editing = this.router.url.startsWith(`/rgw/user/${URLVerbs.EDIT}`);
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+ this.createForm();
+ }
+
+ createForm() {
+ this.userForm = this.formBuilder.group({
+ // General
+ uid: [
+ null,
+ [Validators.required],
+ this.editing ? [] : [CdValidators.unique(this.rgwUserService.exists, this.rgwUserService)]
+ ],
+ display_name: [null, [Validators.required]],
+ email: [
+ null,
+ [CdValidators.email],
+ [CdValidators.unique(this.rgwUserService.emailExists, this.rgwUserService)]
+ ],
+ max_buckets_mode: ['1'],
+ max_buckets: [
+ 1000,
+ [
+ CdValidators.requiredIf({ max_buckets_mode: '1' }),
+ CdValidators.number(false),
+ Validators.min(1)
+ ]
+ ],
+ suspended: [false],
+ // S3 key
+ generate_key: [true],
+ access_key: [null, [CdValidators.requiredIf({ generate_key: false })]],
+ secret_key: [null, [CdValidators.requiredIf({ generate_key: false })]],
+ // User quota
+ user_quota_enabled: [false],
+ user_quota_max_size_unlimited: [true],
+ user_quota_max_size: [
+ null,
+ [
+ CdValidators.requiredIf({
+ user_quota_enabled: true,
+ user_quota_max_size_unlimited: false
+ }),
+ this.quotaMaxSizeValidator
+ ]
+ ],
+ user_quota_max_objects_unlimited: [true],
+ user_quota_max_objects: [
+ null,
+ [
+ Validators.min(0),
+ CdValidators.requiredIf({
+ user_quota_enabled: true,
+ user_quota_max_objects_unlimited: false
+ })
+ ]
+ ],
+ // Bucket quota
+ bucket_quota_enabled: [false],
+ bucket_quota_max_size_unlimited: [true],
+ bucket_quota_max_size: [
+ null,
+ [
+ CdValidators.requiredIf({
+ bucket_quota_enabled: true,
+ bucket_quota_max_size_unlimited: false
+ }),
+ this.quotaMaxSizeValidator
+ ]
+ ],
+ bucket_quota_max_objects_unlimited: [true],
+ bucket_quota_max_objects: [
+ null,
+ [
+ Validators.min(0),
+ CdValidators.requiredIf({
+ bucket_quota_enabled: true,
+ bucket_quota_max_objects_unlimited: false
+ })
+ ]
+ ]
+ });
+ }
+
+ ngOnInit() {
+ // Process route parameters.
+ this.route.params.subscribe((params: { uid: string }) => {
+ if (!params.hasOwnProperty('uid')) {
+ return;
+ }
+ const uid = decodeURIComponent(params.uid);
+ this.loading = true;
+ // Load the user and quota information.
+ const observables = [];
+ observables.push(this.rgwUserService.get(uid));
+ observables.push(this.rgwUserService.getQuota(uid));
+ observableForkJoin(observables).subscribe(
+ (resp: any[]) => {
+ this.loading = false;
+ // Get the default values.
+ const defaults = _.clone(this.userForm.value);
+ // Extract the values displayed in the form.
+ let value = _.pick(resp[0], _.keys(this.userForm.value));
+ // Map the max. buckets values.
+ switch (value['max_buckets']) {
+ case -1:
+ value['max_buckets_mode'] = '-1';
+ value['max_buckets'] = '';
+ break;
+ case 0:
+ value['max_buckets_mode'] = '0';
+ value['max_buckets'] = '';
+ break;
+ default:
+ value['max_buckets_mode'] = '1';
+ break;
+ }
+ // Map the quota values.
+ ['user', 'bucket'].forEach((type) => {
+ const quota = resp[1][type + '_quota'];
+ value[type + '_quota_enabled'] = quota.enabled;
+ if (quota.max_size < 0) {
+ value[type + '_quota_max_size_unlimited'] = true;
+ value[type + '_quota_max_size'] = null;
+ } else {
+ value[type + '_quota_max_size_unlimited'] = false;
+ value[type + '_quota_max_size'] = `${quota.max_size} B`;
+ }
+ if (quota.max_objects < 0) {
+ value[type + '_quota_max_objects_unlimited'] = true;
+ value[type + '_quota_max_objects'] = null;
+ } else {
+ value[type + '_quota_max_objects_unlimited'] = false;
+ value[type + '_quota_max_objects'] = quota.max_objects;
+ }
+ });
+ // Merge with default values.
+ value = _.merge(defaults, value);
+ // Update the form.
+ this.userForm.setValue(value);
+
+ // Get the sub users.
+ this.subusers = resp[0].subusers;
+
+ // Get the keys.
+ this.s3Keys = resp[0].keys;
+ this.swiftKeys = resp[0].swift_keys;
+
+ // Process the capabilities.
+ const mapPerm = { 'read, write': '*' };
+ resp[0].caps.forEach((cap) => {
+ if (cap.perm in mapPerm) {
+ cap.perm = mapPerm[cap.perm];
+ }
+ });
+ this.capabilities = resp[0].caps;
+ },
+ (error) => {
+ this.error = error;
+ }
+ );
+ });
+ }
+
+ goToListView() {
+ this.router.navigate(['/rgw/user']);
+ }
+
+ onSubmit() {
+ let notificationTitle: string;
+ // Exit immediately if the form isn't dirty.
+ if (this.userForm.pristine) {
+ this.goToListView();
+ return;
+ }
+ const uid = this.userForm.getValue('uid');
+ if (this.editing) {
+ // Edit
+ if (this._isGeneralDirty()) {
+ const args = this._getUpdateArgs();
+ this.submitObservables.push(this.rgwUserService.update(uid, args));
+ }
+ notificationTitle = this.i18n('Updated Object Gateway user "{{uid}}"', { uid: uid });
+ } else {
+ // Add
+ const args = this._getCreateArgs();
+ this.submitObservables.push(this.rgwUserService.create(args));
+ notificationTitle = this.i18n('Created Object Gateway user "{{uid}}"', { uid: uid });
+ }
+ // Check if user quota has been modified.
+ if (this._isUserQuotaDirty()) {
+ const userQuotaArgs = this._getUserQuotaArgs();
+ this.submitObservables.push(this.rgwUserService.updateQuota(uid, userQuotaArgs));
+ }
+ // Check if bucket quota has been modified.
+ if (this._isBucketQuotaDirty()) {
+ const bucketQuotaArgs = this._getBucketQuotaArgs();
+ this.submitObservables.push(this.rgwUserService.updateQuota(uid, bucketQuotaArgs));
+ }
+ // Finally execute all observables one by one in serial.
+ observableConcat(...this.submitObservables).subscribe({
+ error: () => {
+ // Reset the 'Submit' button.
+ this.userForm.setErrors({ cdSubmitButton: true });
+ },
+ complete: () => {
+ this.notificationService.show(NotificationType.success, notificationTitle);
+ this.goToListView();
+ }
+ });
+ }
+
+ /**
+ * Validate the quota maximum size, e.g. 1096, 1K, 30M or 1.9MiB.
+ */
+ quotaMaxSizeValidator(control: AbstractControl): ValidationErrors | null {
+ if (isEmptyInputValue(control.value)) {
+ return null;
+ }
+ const m = RegExp('^(\\d+(\\.\\d+)?)\\s*(B|K(B|iB)?|M(B|iB)?|G(B|iB)?|T(B|iB)?)?$', 'i').exec(
+ control.value
+ );
+ if (m === null) {
+ return { quotaMaxSize: true };
+ }
+ const bytes = new FormatterService().toBytes(control.value);
+ return bytes < 1024 ? { quotaMaxSize: true } : null;
+ }
+
+ /**
+ * Add/Update a subuser.
+ */
+ setSubuser(subuser: RgwUserSubuser, index?: number) {
+ const mapPermissions = {
+ 'full-control': 'full',
+ 'read-write': 'readwrite'
+ };
+ const uid = this.userForm.getValue('uid');
+ const args = {
+ subuser: subuser.id,
+ access:
+ subuser.permissions in mapPermissions
+ ? mapPermissions[subuser.permissions]
+ : subuser.permissions,
+ key_type: 'swift',
+ secret_key: subuser.secret_key,
+ generate_secret: subuser.generate_secret ? 'true' : 'false'
+ };
+ this.submitObservables.push(this.rgwUserService.createSubuser(uid, args));
+ if (_.isNumber(index)) {
+ // Modify
+ // Create an observable to modify the subuser when the form is submitted.
+ this.subusers[index] = subuser;
+ } else {
+ // Add
+ // Create an observable to add the subuser when the form is submitted.
+ this.subusers.push(subuser);
+ // Add a Swift key. If the secret key is auto-generated, then visualize
+ // this to the user by displaying a notification instead of the key.
+ this.swiftKeys.push({
+ user: subuser.id,
+ secret_key: subuser.generate_secret ? 'Apply your changes first...' : subuser.secret_key
+ });
+ }
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ /**
+ * Delete a subuser.
+ * @param {number} index The subuser to delete.
+ */
+ deleteSubuser(index: number) {
+ const subuser = this.subusers[index];
+ // Create an observable to delete the subuser when the form is submitted.
+ this.submitObservables.push(
+ this.rgwUserService.deleteSubuser(this.userForm.getValue('uid'), subuser.id)
+ );
+ // Remove the associated S3 keys.
+ this.s3Keys = this.s3Keys.filter((key) => {
+ return key.user !== subuser.id;
+ });
+ // Remove the associated Swift keys.
+ this.swiftKeys = this.swiftKeys.filter((key) => {
+ return key.user !== subuser.id;
+ });
+ // Remove the subuser to update the UI.
+ this.subusers.splice(index, 1);
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ /**
+ * Add/Update a capability.
+ */
+ setCapability(cap: RgwUserCapability, index?: number) {
+ const uid = this.userForm.getValue('uid');
+ if (_.isNumber(index)) {
+ // Modify
+ const oldCap = this.capabilities[index];
+ // Note, the RadosGW Admin OPS API does not support the modification of
+ // user capabilities. Because of that it is necessary to delete it and
+ // then to re-add the capability with its new value/permission.
+ this.submitObservables.push(
+ this.rgwUserService.deleteCapability(uid, oldCap.type, oldCap.perm)
+ );
+ this.submitObservables.push(this.rgwUserService.addCapability(uid, cap.type, cap.perm));
+ this.capabilities[index] = cap;
+ } else {
+ // Add
+ // Create an observable to add the capability when the form is submitted.
+ this.submitObservables.push(this.rgwUserService.addCapability(uid, cap.type, cap.perm));
+ this.capabilities.push(cap);
+ }
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ /**
+ * Delete the given capability:
+ * - Delete it from the local array to update the UI
+ * - Create an observable that will be executed on form submit
+ * @param {number} index The capability to delete.
+ */
+ deleteCapability(index: number) {
+ const cap = this.capabilities[index];
+ // Create an observable to delete the capability when the form is submitted.
+ this.submitObservables.push(
+ this.rgwUserService.deleteCapability(this.userForm.getValue('uid'), cap.type, cap.perm)
+ );
+ // Remove the capability to update the UI.
+ this.capabilities.splice(index, 1);
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ hasAllCapabilities() {
+ return !_.difference(RgwUserCapabilities.getAll(), _.map(this.capabilities, 'type')).length;
+ }
+
+ /**
+ * Add/Update a S3 key.
+ */
+ setS3Key(key: RgwUserS3Key, index?: number) {
+ if (_.isNumber(index)) {
+ // Modify
+ // Nothing to do here at the moment.
+ } else {
+ // Add
+ // Split the key's user name into its user and subuser parts.
+ const userMatches = key.user.match(/([^:]+)(:(.+))?/);
+ // Create an observable to add the S3 key when the form is submitted.
+ const uid = userMatches[1];
+ const args = {
+ subuser: userMatches[2] ? userMatches[3] : '',
+ generate_key: key.generate_key ? 'true' : 'false'
+ };
+ if (args['generate_key'] === 'false') {
+ if (!_.isNil(key.access_key)) {
+ args['access_key'] = key.access_key;
+ }
+ if (!_.isNil(key.secret_key)) {
+ args['secret_key'] = key.secret_key;
+ }
+ }
+ this.submitObservables.push(this.rgwUserService.addS3Key(uid, args));
+ // If the access and the secret key are auto-generated, then visualize
+ // this to the user by displaying a notification instead of the key.
+ this.s3Keys.push({
+ user: key.user,
+ access_key: key.generate_key ? 'Apply your changes first...' : key.access_key,
+ secret_key: key.generate_key ? 'Apply your changes first...' : key.secret_key
+ });
+ }
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ /**
+ * Delete a S3 key.
+ * @param {number} index The S3 key to delete.
+ */
+ deleteS3Key(index: number) {
+ const key = this.s3Keys[index];
+ // Create an observable to delete the S3 key when the form is submitted.
+ this.submitObservables.push(
+ this.rgwUserService.deleteS3Key(this.userForm.getValue('uid'), key.access_key)
+ );
+ // Remove the S3 key to update the UI.
+ this.s3Keys.splice(index, 1);
+ // Mark the form as dirty to be able to submit it.
+ this.userForm.markAsDirty();
+ }
+
+ /**
+ * Show the specified subuser in a modal dialog.
+ * @param {number | undefined} index The subuser to show.
+ */
+ showSubuserModal(index?: number) {
+ const uid = this.userForm.getValue('uid');
+ const modalRef = this.bsModalService.show(RgwUserSubuserModalComponent);
+ if (_.isNumber(index)) {
+ // Edit
+ const subuser = this.subusers[index];
+ modalRef.content.setEditing();
+ modalRef.content.setValues(uid, subuser.id, subuser.permissions);
+ } else {
+ // Add
+ modalRef.content.setEditing(false);
+ modalRef.content.setValues(uid);
+ modalRef.content.setSubusers(this.subusers);
+ }
+ modalRef.content.submitAction.subscribe((subuser: RgwUserSubuser) => {
+ this.setSubuser(subuser, index);
+ });
+ }
+
+ /**
+ * Show the specified S3 key in a modal dialog.
+ * @param {number | undefined} index The S3 key to show.
+ */
+ showS3KeyModal(index?: number) {
+ const modalRef = this.bsModalService.show(RgwUserS3KeyModalComponent);
+ if (_.isNumber(index)) {
+ // View
+ const key = this.s3Keys[index];
+ modalRef.content.setViewing();
+ modalRef.content.setValues(key.user, key.access_key, key.secret_key);
+ } else {
+ // Add
+ const candidates = this._getS3KeyUserCandidates();
+ modalRef.content.setViewing(false);
+ modalRef.content.setUserCandidates(candidates);
+ modalRef.content.submitAction.subscribe((key: RgwUserS3Key) => {
+ this.setS3Key(key);
+ });
+ }
+ }
+
+ /**
+ * Show the specified Swift key in a modal dialog.
+ * @param {number} index The Swift key to show.
+ */
+ showSwiftKeyModal(index: number) {
+ const modalRef = this.bsModalService.show(RgwUserSwiftKeyModalComponent);
+ const key = this.swiftKeys[index];
+ modalRef.content.setValues(key.user, key.secret_key);
+ }
+
+ /**
+ * Show the specified capability in a modal dialog.
+ * @param {number | undefined} index The S3 key to show.
+ */
+ showCapabilityModal(index?: number) {
+ const modalRef = this.bsModalService.show(RgwUserCapabilityModalComponent);
+ if (_.isNumber(index)) {
+ // Edit
+ const cap = this.capabilities[index];
+ modalRef.content.setEditing();
+ modalRef.content.setValues(cap.type, cap.perm);
+ } else {
+ // Add
+ modalRef.content.setEditing(false);
+ modalRef.content.setCapabilities(this.capabilities);
+ }
+ modalRef.content.submitAction.subscribe((cap: RgwUserCapability) => {
+ this.setCapability(cap, index);
+ });
+ }
+
+ /**
+ * Check if the general user settings (display name, email, ...) have been modified.
+ * @return {Boolean} Returns TRUE if the general user settings have been modified.
+ */
+ private _isGeneralDirty(): boolean {
+ return ['display_name', 'email', 'max_buckets_mode', 'max_buckets', 'suspended'].some(
+ (path) => {
+ return this.userForm.get(path).dirty;
+ }
+ );
+ }
+
+ /**
+ * Check if the user quota has been modified.
+ * @return {Boolean} Returns TRUE if the user quota has been modified.
+ */
+ private _isUserQuotaDirty(): boolean {
+ return [
+ 'user_quota_enabled',
+ 'user_quota_max_size_unlimited',
+ 'user_quota_max_size',
+ 'user_quota_max_objects_unlimited',
+ 'user_quota_max_objects'
+ ].some((path) => {
+ return this.userForm.get(path).dirty;
+ });
+ }
+
+ /**
+ * Check if the bucket quota has been modified.
+ * @return {Boolean} Returns TRUE if the bucket quota has been modified.
+ */
+ private _isBucketQuotaDirty(): boolean {
+ return [
+ 'bucket_quota_enabled',
+ 'bucket_quota_max_size_unlimited',
+ 'bucket_quota_max_size',
+ 'bucket_quota_max_objects_unlimited',
+ 'bucket_quota_max_objects'
+ ].some((path) => {
+ return this.userForm.get(path).dirty;
+ });
+ }
+
+ /**
+ * Helper function to get the arguments of the API request when a new
+ * user is created.
+ */
+ private _getCreateArgs() {
+ const result = {
+ uid: this.userForm.getValue('uid'),
+ display_name: this.userForm.getValue('display_name'),
+ suspended: this.userForm.getValue('suspended'),
+ email: '',
+ max_buckets: this.userForm.getValue('max_buckets'),
+ generate_key: this.userForm.getValue('generate_key'),
+ access_key: '',
+ secret_key: ''
+ };
+ const email = this.userForm.getValue('email');
+ if (_.isString(email) && email.length > 0) {
+ _.merge(result, { email: email });
+ }
+ const generateKey = this.userForm.getValue('generate_key');
+ if (!generateKey) {
+ _.merge(result, {
+ generate_key: false,
+ access_key: this.userForm.getValue('access_key'),
+ secret_key: this.userForm.getValue('secret_key')
+ });
+ }
+ const maxBucketsMode = parseInt(this.userForm.getValue('max_buckets_mode'), 10);
+ if (_.includes([-1, 0], maxBucketsMode)) {
+ // -1 => Disable bucket creation.
+ // 0 => Unlimited bucket creation.
+ _.merge(result, { max_buckets: maxBucketsMode });
+ }
+ return result;
+ }
+
+ /**
+ * Helper function to get the arguments for the API request when the user
+ * configuration has been modified.
+ */
+ private _getUpdateArgs() {
+ const result: Record<string, any> = {};
+ const keys = ['display_name', 'email', 'max_buckets', 'suspended'];
+ for (const key of keys) {
+ result[key] = this.userForm.getValue(key);
+ }
+ const maxBucketsMode = parseInt(this.userForm.getValue('max_buckets_mode'), 10);
+ if (_.includes([-1, 0], maxBucketsMode)) {
+ // -1 => Disable bucket creation.
+ // 0 => Unlimited bucket creation.
+ result['max_buckets'] = maxBucketsMode;
+ }
+ return result;
+ }
+
+ /**
+ * Helper function to get the arguments for the API request when the user
+ * quota configuration has been modified.
+ */
+ private _getUserQuotaArgs(): object {
+ const result = {
+ quota_type: 'user',
+ enabled: this.userForm.getValue('user_quota_enabled'),
+ max_size_kb: -1,
+ max_objects: -1
+ };
+ if (!this.userForm.getValue('user_quota_max_size_unlimited')) {
+ // Convert the given value to bytes.
+ const bytes = new FormatterService().toBytes(this.userForm.getValue('user_quota_max_size'));
+ // Finally convert the value to KiB.
+ result['max_size_kb'] = (bytes / 1024).toFixed(0) as any;
+ }
+ if (!this.userForm.getValue('user_quota_max_objects_unlimited')) {
+ result['max_objects'] = this.userForm.getValue('user_quota_max_objects');
+ }
+ return result;
+ }
+
+ /**
+ * Helper function to get the arguments for the API request when the bucket
+ * quota configuration has been modified.
+ */
+ private _getBucketQuotaArgs(): object {
+ const result = {
+ quota_type: 'bucket',
+ enabled: this.userForm.getValue('bucket_quota_enabled'),
+ max_size_kb: -1,
+ max_objects: -1
+ };
+ if (!this.userForm.getValue('bucket_quota_max_size_unlimited')) {
+ // Convert the given value to bytes.
+ const bytes = new FormatterService().toBytes(this.userForm.getValue('bucket_quota_max_size'));
+ // Finally convert the value to KiB.
+ result['max_size_kb'] = (bytes / 1024).toFixed(0) as any;
+ }
+ if (!this.userForm.getValue('bucket_quota_max_objects_unlimited')) {
+ result['max_objects'] = this.userForm.getValue('bucket_quota_max_objects');
+ }
+ return result;
+ }
+
+ /**
+ * Helper method to get the user candidates for S3 keys.
+ * @returns {Array} Returns a list of user identifiers.
+ */
+ private _getS3KeyUserCandidates() {
+ let result = [];
+ // Add the current user id.
+ const uid = this.userForm.getValue('uid');
+ if (_.isString(uid) && !_.isEmpty(uid)) {
+ result.push(uid);
+ }
+ // Append the subusers.
+ this.subusers.forEach((subUser) => {
+ result.push(subUser.id);
+ });
+ // Note that it's possible to create multiple S3 key pairs for a user,
+ // thus we append already configured users, too.
+ this.s3Keys.forEach((key) => {
+ result.push(key.user);
+ });
+ result = _.uniq(result);
+ return result;
+ }
+
+ onMaxBucketsModeChange(mode: string) {
+ if (mode === '1') {
+ // If 'Custom' mode is selected, then ensure that the form field
+ // 'Max. buckets' contains a valid value. Set it to default if
+ // necessary.
+ const maxBuckets = this.userForm.getValue('max_buckets');
+ this.userForm.patchValue({ max_buckets: _.isEmpty(maxBuckets) ? 1000 : maxBuckets });
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.html
new file mode 100644
index 00000000..8bb40fc9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.html
@@ -0,0 +1,18 @@
+<cd-table #table
+ [autoReload]="false"
+ [data]="users"
+ [columns]="columns"
+ columnMode="flex"
+ selectionType="multi"
+ (updateSelection)="updateSelection($event)"
+ identifier="uid"
+ (fetchData)="getUserList($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-rgw-user-details cdTableDetail
+ [selection]="selection">
+ </cd-rgw-user-details>
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.spec.ts
new file mode 100644
index 00000000..46c3ee99
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.spec.ts
@@ -0,0 +1,196 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ModalModule } from 'ngx-bootstrap/modal';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { ActionLabels } from '../../../shared/constants/app.constants';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserListComponent } from './rgw-user-list.component';
+
+describe('RgwUserListComponent', () => {
+ let component: RgwUserListComponent;
+ let fixture: ComponentFixture<RgwUserListComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserListComponent],
+ imports: [RouterTestingModule, HttpClientTestingModule, ModalModule.forRoot(), SharedModule],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: ActionLabels.EDIT,
+ empty: ActionLabels.CREATE
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows 'Add' and 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Add' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows always 'Add' as main action`, () => {
+ scenario.single = ActionLabels.CREATE;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Add' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.ts
new file mode 100644
index 00000000..6808fc78
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.ts
@@ -0,0 +1,152 @@
+import { Component, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
+
+import { RgwUserService } from '../../../shared/api/rgw-user.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { TableComponent } from '../../../shared/datatable/table/table.component';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+
+const BASE_URL = 'rgw/user';
+
+@Component({
+ selector: 'cd-rgw-user-list',
+ templateUrl: './rgw-user-list.component.html',
+ styleUrls: ['./rgw-user-list.component.scss'],
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }]
+})
+export class RgwUserListComponent {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ columns: CdTableColumn[] = [];
+ users: object[] = [];
+ selection: CdTableSelection = new CdTableSelection();
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private rgwUserService: RgwUserService,
+ private bsModalService: BsModalService,
+ private i18n: I18n,
+ private urlBuilder: URLBuilderService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().rgw;
+ this.columns = [
+ {
+ name: this.i18n('Username'),
+ prop: 'uid',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Full name'),
+ prop: 'display_name',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Email address'),
+ prop: 'email',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Suspended'),
+ prop: 'suspended',
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ },
+ {
+ name: this.i18n('Max. buckets'),
+ prop: 'max_buckets',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.map,
+ customTemplateConfig: {
+ '-1': this.i18n('Disabled'),
+ 0: this.i18n('Unlimited')
+ }
+ }
+ ];
+ const getUserUri = () =>
+ this.selection.first() && `${encodeURIComponent(this.selection.first().uid)}`;
+ const addAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ name: this.actionLabels.CREATE
+ };
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => this.urlBuilder.getEdit(getUserUri()),
+ name: this.actionLabels.EDIT
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteAction(),
+ name: this.actionLabels.DELETE
+ };
+ this.tableActions = [addAction, editAction, deleteAction];
+ }
+
+ getUserList(context: CdTableFetchDataContext) {
+ this.rgwUserService.list().subscribe(
+ (resp: object[]) => {
+ this.users = resp;
+ },
+ () => {
+ context.error();
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteAction() {
+ this.bsModalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: this.selection.hasSingleSelection ? this.i18n('user') : this.i18n('users'),
+ itemNames: this.selection.selected.map((user: any) => user['uid']),
+ submitActionObservable: (): Observable<any> => {
+ return new Observable((observer: Subscriber<any>) => {
+ // Delete all selected data table rows.
+ observableForkJoin(
+ this.selection.selected.map((user: any) => {
+ return this.rgwUserService.delete(user.uid);
+ })
+ ).subscribe(
+ null,
+ (error) => {
+ // Forward the error to the observer.
+ observer.error(error);
+ // Reload the data table content because some deletions might
+ // have been executed successfully in the meanwhile.
+ this.table.refreshBtn();
+ },
+ () => {
+ // Notify the observer that we are done.
+ observer.complete();
+ // Reload the data table content.
+ this.table.refreshBtn();
+ }
+ );
+ });
+ }
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.html
new file mode 100644
index 00000000..0805c5e8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.html
@@ -0,0 +1,144 @@
+<div class="modal-header">
+ <h4 i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title pull-left">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<form class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="formGroup"
+ novalidate>
+ <div class="modal-body">
+
+ <!-- Username -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('user', frm)}">
+ <label class="control-label col-sm-3"
+ for="user">
+ <ng-container i18n>Username</ng-container>
+ <span class="required"
+ *ngIf="!viewing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="user"
+ class="form-control"
+ type="text"
+ *ngIf="viewing"
+ [readonly]="true"
+ formControlName="user">
+ <select id="user"
+ class="form-control"
+ formControlName="user"
+ *ngIf="!viewing"
+ autofocus>
+ <option i18n
+ *ngIf="userCandidates !== null"
+ [ngValue]="null">-- Select a username --</option>
+ <option *ngFor="let userCandidate of userCandidates"
+ [value]="userCandidate">{{ userCandidate }}</option>
+ </select>
+ <span class="help-block"
+ *ngIf="formGroup.showError('user', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Auto-generate key -->
+ <div class="form-group"
+ *ngIf="!viewing">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="generate_key"
+ type="checkbox"
+ formControlName="generate_key">
+ <label for="generate_key"
+ i18n>Auto-generate key</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Access key -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('access_key', frm)}"
+ *ngIf="!formGroup.getValue('generate_key')">
+ <label class="control-label col-sm-3"
+ for="access_key">
+ <ng-container i18n>Access key</ng-container>
+ <span class="required"
+ *ngIf="!viewing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="access_key"
+ class="form-control"
+ type="password"
+ [readonly]="viewing"
+ formControlName="access_key">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="access_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="access_key">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="formGroup.showError('access_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Secret key -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('secret_key', frm)}"
+ *ngIf="!formGroup.getValue('generate_key')">
+ <label class="control-label col-sm-3"
+ for="secret_key">
+ <ng-container i18n>Secret key</ng-container>
+ <span class="required"
+ *ngIf="!viewing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="secret_key"
+ class="form-control"
+ type="password"
+ [readonly]="viewing"
+ formControlName="secret_key">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="secret_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="secret_key">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="formGroup.showError('secret_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <cd-submit-button
+ *ngIf="!viewing"
+ (submitAction)="onSubmit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ [form]="formGroup">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"></cd-back-button>
+ </div>
+</form>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.spec.ts
new file mode 100644
index 00000000..bf8dcdce
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.spec.ts
@@ -0,0 +1,30 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserS3KeyModalComponent } from './rgw-user-s3-key-modal.component';
+
+describe('RgwUserS3KeyModalComponent', () => {
+ let component: RgwUserS3KeyModalComponent;
+ let fixture: ComponentFixture<RgwUserS3KeyModalComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserS3KeyModalComponent],
+ imports: [ReactiveFormsModule, SharedModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserS3KeyModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts
new file mode 100644
index 00000000..a3cd2f11
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts
@@ -0,0 +1,86 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { RgwUserS3Key } from '../models/rgw-user-s3-key';
+
+@Component({
+ selector: 'cd-rgw-user-s3-key-modal',
+ templateUrl: './rgw-user-s3-key-modal.component.html',
+ styleUrls: ['./rgw-user-s3-key-modal.component.scss']
+})
+export class RgwUserS3KeyModalComponent {
+ /**
+ * The event that is triggered when the 'Add' button as been pressed.
+ */
+ @Output()
+ submitAction = new EventEmitter();
+
+ formGroup: CdFormGroup;
+ viewing = true;
+ userCandidates: string[] = [];
+ resource: string;
+ action: string;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ public bsModalRef: BsModalRef,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('S3 Key');
+ this.createForm();
+ }
+
+ createForm() {
+ this.formGroup = this.formBuilder.group({
+ user: [null, [Validators.required]],
+ generate_key: [true],
+ access_key: [null, [CdValidators.requiredIf({ generate_key: false })]],
+ secret_key: [null, [CdValidators.requiredIf({ generate_key: false })]]
+ });
+ }
+
+ /**
+ * Set the 'viewing' flag. If set to TRUE, the modal dialog is in 'View' mode,
+ * otherwise in 'Add' mode. According to the mode the dialog and its controls
+ * behave different.
+ * @param {boolean} viewing
+ */
+ setViewing(viewing: boolean = true) {
+ this.viewing = viewing;
+ this.action = this.viewing ? this.actionLabels.SHOW : this.actionLabels.CREATE;
+ }
+
+ /**
+ * Set the values displayed in the dialog.
+ */
+ setValues(user: string, access_key: string, secret_key: string) {
+ this.formGroup.setValue({
+ user: user,
+ generate_key: _.isEmpty(access_key),
+ access_key: access_key,
+ secret_key: secret_key
+ });
+ }
+
+ /**
+ * Set the user candidates displayed in the 'Username' dropdown box.
+ */
+ setUserCandidates(candidates: string[]) {
+ this.userCandidates = candidates;
+ }
+
+ onSubmit() {
+ const key: RgwUserS3Key = this.formGroup.value;
+ this.submitAction.emit(key);
+ this.bsModalRef.hide();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.html
new file mode 100644
index 00000000..2f9a7d69
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.html
@@ -0,0 +1,146 @@
+<div class="modal-header">
+ <h4 i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title pull-left">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<form class="form-horizontal"
+ #frm="ngForm"
+ [formGroup]="formGroup"
+ novalidate>
+ <div class="modal-body">
+
+ <!-- Username -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('uid', frm)}">
+ <label class="control-label col-sm-3"
+ for="uid"
+ i18n>Username</label>
+ <div class="col-sm-9">
+ <input id="uid"
+ class="form-control"
+ type="text"
+ formControlName="uid"
+ [readonly]="true">
+ </div>
+ </div>
+
+ <!-- Subuser -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('subuid', frm)}">
+ <label class="control-label col-sm-3"
+ for="subuid">
+ <ng-container i18n>Subuser</ng-container>
+ <span class="required"
+ *ngIf="!editing">
+ </span>
+ </label>
+ <div class="col-sm-9">
+ <input id="subuid"
+ class="form-control"
+ type="text"
+ formControlName="subuid"
+ [readonly]="editing"
+ autofocus>
+ <span class="help-block"
+ *ngIf="formGroup.showError('subuid', frm, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="formGroup.showError('subuid', frm, 'subuserIdExists')"
+ i18n>The chosen subuser ID is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Permission -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('perm', frm)}">
+ <label class="control-label col-sm-3"
+ for="perm">
+ <ng-container i18n>Permission</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <select id="perm"
+ class="form-control"
+ formControlName="perm">
+ <option i18n
+ [ngValue]="null">-- Select a permission --</option>
+ <option *ngFor="let perm of ['read', 'write']"
+ [value]="perm">
+ {{ perm }}
+ </option>
+ <option i18n
+ value="read-write">read, write</option>
+ <option i18n
+ value="full-control">full</option>
+ </select>
+ <span class="help-block"
+ *ngIf="formGroup.showError('perm', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Swift key -->
+ <fieldset *ngIf="!editing">
+ <legend i18n>Swift key</legend>
+
+ <!-- Auto-generate key -->
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input id="generate_secret"
+ type="checkbox"
+ formControlName="generate_secret">
+ <label for="generate_secret"
+ i18n>Auto-generate secret</label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Secret key -->
+ <div class="form-group"
+ [ngClass]="{'has-error': formGroup.showError('secret_key', frm)}"
+ *ngIf="!editing && !formGroup.getValue('generate_secret')">
+ <label class="control-label col-sm-3"
+ for="secret_key">
+ <ng-container i18n>Secret key</ng-container>
+ <span class="required"></span>
+ </label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="secret_key"
+ class="form-control"
+ type="password"
+ formControlName="secret_key">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="secret_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="secret_key">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="formGroup.showError('secret_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ </fieldset>
+
+ </div>
+ <div class="modal-footer">
+ <cd-submit-button
+ (submitAction)="onSubmit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ [form]="formGroup">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button [back]="bsModalRef.hide"></cd-back-button>
+ </div>
+</form>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.spec.ts
new file mode 100644
index 00000000..a828c3d5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.spec.ts
@@ -0,0 +1,71 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserSubuserModalComponent } from './rgw-user-subuser-modal.component';
+
+describe('RgwUserSubuserModalComponent', () => {
+ let component: RgwUserSubuserModalComponent;
+ let fixture: ComponentFixture<RgwUserSubuserModalComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserSubuserModalComponent],
+ imports: [ReactiveFormsModule, SharedModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserSubuserModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('subuserValidator', () => {
+ beforeEach(() => {
+ component.editing = false;
+ component.subusers = [
+ { id: 'Edith', permissions: 'full-control' },
+ { id: 'Edith:images', permissions: 'read-write' }
+ ];
+ });
+
+ it('should validate subuser (1/5)', () => {
+ component.editing = true;
+ const validatorFn = component.subuserValidator();
+ const resp = validatorFn(new FormControl());
+ expect(resp).toBe(null);
+ });
+
+ it('should validate subuser (2/5)', () => {
+ const validatorFn = component.subuserValidator();
+ const resp = validatorFn(new FormControl(''));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate subuser (3/5)', () => {
+ const validatorFn = component.subuserValidator();
+ const resp = validatorFn(new FormControl('Melissa'));
+ expect(resp).toBe(null);
+ });
+
+ it('should validate subuser (4/5)', () => {
+ const validatorFn = component.subuserValidator();
+ const resp = validatorFn(new FormControl('Edith'));
+ expect(resp.subuserIdExists).toBeTruthy();
+ });
+
+ it('should validate subuser (5/5)', () => {
+ const validatorFn = component.subuserValidator();
+ const resp = validatorFn(new FormControl('images'));
+ expect(resp.subuserIdExists).toBeTruthy();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts
new file mode 100644
index 00000000..03a4b95e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts
@@ -0,0 +1,132 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators, isEmptyInputValue } from '../../../shared/forms/cd-validators';
+import { RgwUserSubuser } from '../models/rgw-user-subuser';
+
+@Component({
+ selector: 'cd-rgw-user-subuser-modal',
+ templateUrl: './rgw-user-subuser-modal.component.html',
+ styleUrls: ['./rgw-user-subuser-modal.component.scss']
+})
+export class RgwUserSubuserModalComponent {
+ /**
+ * The event that is triggered when the 'Add' or 'Update' button
+ * has been pressed.
+ */
+ @Output()
+ submitAction = new EventEmitter();
+
+ formGroup: CdFormGroup;
+ editing = true;
+ subusers: RgwUserSubuser[] = [];
+ resource: string;
+ action: string;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ public bsModalRef: BsModalRef,
+ private i18n: I18n,
+ private actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('Subuser');
+ this.createForm();
+ }
+
+ createForm() {
+ this.formGroup = this.formBuilder.group({
+ uid: [null],
+ subuid: [null, [Validators.required, this.subuserValidator()]],
+ perm: [null, [Validators.required]],
+ // Swift key
+ generate_secret: [true],
+ secret_key: [null, [CdValidators.requiredIf({ generate_secret: false })]]
+ });
+ }
+
+ /**
+ * Validates whether the subuser already exists.
+ */
+ subuserValidator(): ValidatorFn {
+ const self = this;
+ return (control: AbstractControl): ValidationErrors | null => {
+ if (self.editing) {
+ return null;
+ }
+ if (isEmptyInputValue(control.value)) {
+ return null;
+ }
+ const found = self.subusers.some((subuser) => {
+ return _.isEqual(self.getSubuserName(subuser.id), control.value);
+ });
+ return found ? { subuserIdExists: true } : null;
+ };
+ }
+
+ /**
+ * Get the subuser name.
+ * Examples:
+ * 'johndoe' => 'johndoe'
+ * 'janedoe:xyz' => 'xyz'
+ * @param {string} value The value to process.
+ * @returns {string} Returns the user ID.
+ */
+ private getSubuserName(value: string) {
+ if (_.isEmpty(value)) {
+ return value;
+ }
+ const matches = value.match(/([^:]+)(:(.+))?/);
+ return _.isUndefined(matches[3]) ? matches[1] : matches[3];
+ }
+
+ /**
+ * Set the 'editing' flag. If set to TRUE, the modal dialog is in 'Edit' mode,
+ * otherwise in 'Add' mode. According to the mode the dialog and its controls
+ * behave different.
+ * @param {boolean} viewing
+ */
+ setEditing(editing: boolean = true) {
+ this.editing = editing;
+ this.action = this.editing ? this.actionLabels.EDIT : this.actionLabels.CREATE;
+ }
+
+ /**
+ * Set the values displayed in the dialog.
+ */
+ setValues(uid: string, subuser: string = '', permissions: string = '') {
+ this.formGroup.setValue({
+ uid: uid,
+ subuid: this.getSubuserName(subuser),
+ perm: permissions,
+ generate_secret: true,
+ secret_key: null
+ });
+ }
+
+ /**
+ * Set the current capabilities of the user.
+ */
+ setSubusers(subusers: RgwUserSubuser[]) {
+ this.subusers = subusers;
+ }
+
+ onSubmit() {
+ // Get the values from the form and create an object that is sent
+ // by the triggered submit action event.
+ const values = this.formGroup.value;
+ const subuser = new RgwUserSubuser();
+ subuser.id = `${values.uid}:${values.subuid}`;
+ subuser.permissions = values.perm;
+ subuser.generate_secret = values.generate_secret;
+ subuser.secret_key = values.secret_key;
+ this.submitAction.emit(subuser);
+ this.bsModalRef.hide();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.html
new file mode 100644
index 00000000..ce973cbd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.html
@@ -0,0 +1,61 @@
+<div class="modal-header">
+ <h4 i18n="form title|Example: Create Pool@@formTitle"
+ class="modal-title pull-left">{{ action | titlecase }} {{ resource | upperFirst }}</h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="bsModalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<div class="modal-body">
+ <form class="form-horizontal"
+ novalidate>
+
+ <!-- Username -->
+ <div class="form-group">
+ <label class="control-label col-sm-3"
+ for="user"
+ i18n>Username</label>
+ <div class="col-sm-9">
+ <input id="user"
+ name="user"
+ class="form-control"
+ type="text"
+ [readonly]="true"
+ [(ngModel)]="user">
+ </div>
+ </div>
+
+ <!-- Secret key -->
+ <div class="form-group">
+ <label class="control-label col-sm-3"
+ for="secret_key"
+ i18n>Secret key</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input id="secret_key"
+ name="secret_key"
+ class="form-control"
+ type="password"
+ [(ngModel)]="secret_key"
+ [readonly]="true">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="secret_key">
+ </button>
+ <button type="button"
+ class="btn btn-default"
+ cdCopy2ClipboardButton="secret_key">
+ </button>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ </form>
+</div>
+<div class="modal-footer">
+ <cd-back-button [back]="bsModalRef.hide"></cd-back-button>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.spec.ts
new file mode 100644
index 00000000..38d9bde3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.spec.ts
@@ -0,0 +1,31 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RgwUserSwiftKeyModalComponent } from './rgw-user-swift-key-modal.component';
+
+describe('RgwUserSwiftKeyModalComponent', () => {
+ let component: RgwUserSwiftKeyModalComponent;
+ let fixture: ComponentFixture<RgwUserSwiftKeyModalComponent>;
+
+ configureTestBed({
+ declarations: [RgwUserSwiftKeyModalComponent],
+ imports: [ToastrModule.forRoot(), FormsModule, SharedModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RgwUserSwiftKeyModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.ts
new file mode 100644
index 00000000..ad10e070
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-swift-key-modal/rgw-user-swift-key-modal.component.ts
@@ -0,0 +1,35 @@
+import { Component } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+
+@Component({
+ selector: 'cd-rgw-user-swift-key-modal',
+ templateUrl: './rgw-user-swift-key-modal.component.html',
+ styleUrls: ['./rgw-user-swift-key-modal.component.scss']
+})
+export class RgwUserSwiftKeyModalComponent {
+ user: string;
+ secret_key: string;
+ resource: string;
+ action: string;
+
+ constructor(
+ public bsModalRef: BsModalRef,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('Swift Key');
+ this.action = this.actionLabels.SHOW;
+ }
+
+ /**
+ * Set the values displayed in the dialog.
+ */
+ setValues(user: string, secret_key: string) {
+ this.user = user;
+ this.secret_key = secret_key;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts
new file mode 100644
index 00000000..25ce79a3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts
@@ -0,0 +1,134 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { ActionLabels, URLVerbs } from '../../shared/constants/app.constants';
+import { AuthGuardService } from '../../shared/services/auth-guard.service';
+import { SharedModule } from '../../shared/shared.module';
+import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
+import { Rgw501Component } from './rgw-501/rgw-501.component';
+import { RgwBucketDetailsComponent } from './rgw-bucket-details/rgw-bucket-details.component';
+import { RgwBucketFormComponent } from './rgw-bucket-form/rgw-bucket-form.component';
+import { RgwBucketListComponent } from './rgw-bucket-list/rgw-bucket-list.component';
+import { RgwDaemonDetailsComponent } from './rgw-daemon-details/rgw-daemon-details.component';
+import { RgwDaemonListComponent } from './rgw-daemon-list/rgw-daemon-list.component';
+import { RgwUserCapabilityModalComponent } from './rgw-user-capability-modal/rgw-user-capability-modal.component';
+import { RgwUserDetailsComponent } from './rgw-user-details/rgw-user-details.component';
+import { RgwUserFormComponent } from './rgw-user-form/rgw-user-form.component';
+import { RgwUserListComponent } from './rgw-user-list/rgw-user-list.component';
+import { RgwUserS3KeyModalComponent } from './rgw-user-s3-key-modal/rgw-user-s3-key-modal.component';
+import { RgwUserSubuserModalComponent } from './rgw-user-subuser-modal/rgw-user-subuser-modal.component';
+import { RgwUserSwiftKeyModalComponent } from './rgw-user-swift-key-modal/rgw-user-swift-key-modal.component';
+
+@NgModule({
+ entryComponents: [
+ RgwDaemonDetailsComponent,
+ RgwBucketDetailsComponent,
+ RgwUserDetailsComponent,
+ RgwUserSwiftKeyModalComponent,
+ RgwUserS3KeyModalComponent,
+ RgwUserCapabilityModalComponent,
+ RgwUserSubuserModalComponent
+ ],
+ imports: [
+ CommonModule,
+ SharedModule,
+ FormsModule,
+ ReactiveFormsModule,
+ PerformanceCounterModule,
+ AlertModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ TabsModule.forRoot(),
+ TooltipModule.forRoot(),
+ ModalModule.forRoot(),
+ RouterModule
+ ],
+ exports: [
+ Rgw501Component,
+ RgwDaemonListComponent,
+ RgwDaemonDetailsComponent,
+ RgwBucketFormComponent,
+ RgwBucketListComponent,
+ RgwBucketDetailsComponent,
+ RgwUserListComponent,
+ RgwUserDetailsComponent
+ ],
+ declarations: [
+ Rgw501Component,
+ RgwDaemonListComponent,
+ RgwDaemonDetailsComponent,
+ RgwBucketFormComponent,
+ RgwBucketListComponent,
+ RgwBucketDetailsComponent,
+ RgwUserListComponent,
+ RgwUserDetailsComponent,
+ RgwBucketFormComponent,
+ RgwUserFormComponent,
+ RgwUserSwiftKeyModalComponent,
+ RgwUserS3KeyModalComponent,
+ RgwUserCapabilityModalComponent,
+ RgwUserSubuserModalComponent
+ ]
+})
+export class RgwModule {}
+
+const routes: Routes = [
+ {
+ path: '',
+ redirectTo: 'daemon',
+ pathMatch: 'full'
+ },
+ { path: 'daemon', component: RgwDaemonListComponent, data: { breadcrumbs: 'Daemons' } },
+ {
+ path: 'user',
+ data: { breadcrumbs: 'Users' },
+ children: [
+ { path: '', component: RgwUserListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: RgwUserFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:uid`,
+ component: RgwUserFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ },
+ {
+ path: 'bucket',
+ data: { breadcrumbs: 'Buckets' },
+ children: [
+ { path: '', component: RgwBucketListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: RgwBucketFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:bid`,
+ component: RgwBucketFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ },
+ {
+ path: '501/:message',
+ component: Rgw501Component,
+ canActivate: [AuthGuardService],
+ data: { breadcrumbs: 'Object Gateway' }
+ }
+];
+
+@NgModule({
+ imports: [RgwModule, RouterModule.forChild(routes)]
+})
+export class RoutedRgwModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/ceph-shared.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/ceph-shared.module.ts
new file mode 100644
index 00000000..aaf0ddcf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/ceph-shared.module.ts
@@ -0,0 +1,7 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+@NgModule({
+ imports: [CommonModule]
+})
+export class CephSharedModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.model.ts
new file mode 100644
index 00000000..12fda778
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.model.ts
@@ -0,0 +1,71 @@
+export class PgCategory {
+ static readonly CATEGORY_CLEAN = 'clean';
+ static readonly CATEGORY_WORKING = 'working';
+ static readonly CATEGORY_WARNING = 'warning';
+ static readonly CATEGORY_UNKNOWN = 'unknown';
+ static readonly VALID_CATEGORIES = [
+ PgCategory.CATEGORY_CLEAN,
+ PgCategory.CATEGORY_WORKING,
+ PgCategory.CATEGORY_WARNING,
+ PgCategory.CATEGORY_UNKNOWN
+ ];
+
+ states: string[];
+
+ constructor(public type: string) {
+ if (!this.isValidType()) {
+ throw new Error('Wrong placement group category type');
+ }
+
+ this.setTypeStates();
+ }
+
+ private isValidType() {
+ return PgCategory.VALID_CATEGORIES.includes(this.type);
+ }
+
+ private setTypeStates() {
+ switch (this.type) {
+ case PgCategory.CATEGORY_CLEAN:
+ this.states = ['active', 'clean'];
+ break;
+ case PgCategory.CATEGORY_WORKING:
+ this.states = [
+ 'activating',
+ 'backfill_wait',
+ 'backfilling',
+ 'creating',
+ 'deep',
+ 'degraded',
+ 'forced_backfill',
+ 'forced_recovery',
+ 'peering',
+ 'peered',
+ 'recovering',
+ 'recovery_wait',
+ 'repair',
+ 'scrubbing',
+ 'snaptrim',
+ 'snaptrim_wait'
+ ];
+ break;
+ case PgCategory.CATEGORY_WARNING:
+ this.states = [
+ 'backfill_toofull',
+ 'backfill_unfound',
+ 'down',
+ 'incomplete',
+ 'inconsistent',
+ 'recovery_toofull',
+ 'recovery_unfound',
+ 'remapped',
+ 'snaptrim_error',
+ 'stale',
+ 'undersized'
+ ];
+ break;
+ default:
+ this.states = [];
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.spec.ts
new file mode 100644
index 00000000..5a71c208
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.spec.ts
@@ -0,0 +1,55 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { PgCategory } from './pg-category.model';
+import { PgCategoryService } from './pg-category.service';
+
+describe('PgCategoryService', () => {
+ let service: PgCategoryService;
+
+ configureTestBed({
+ providers: [PgCategoryService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(PgCategoryService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('returns all category types', () => {
+ const categoryTypes = service.getAllTypes();
+
+ expect(categoryTypes).toEqual(PgCategory.VALID_CATEGORIES);
+ });
+
+ describe('getTypeByStates', () => {
+ const testMethod = (value, expected) =>
+ expect(service.getTypeByStates(value)).toEqual(expected);
+
+ it(PgCategory.CATEGORY_CLEAN, () => {
+ testMethod('clean', PgCategory.CATEGORY_CLEAN);
+ });
+
+ it(PgCategory.CATEGORY_WORKING, () => {
+ testMethod('clean+scrubbing', PgCategory.CATEGORY_WORKING);
+ testMethod(
+ ' 8 active+clean+scrubbing+deep, 255 active+clean ',
+ PgCategory.CATEGORY_WORKING
+ );
+ });
+
+ it(PgCategory.CATEGORY_WARNING, () => {
+ testMethod('clean+scrubbing+down', PgCategory.CATEGORY_WARNING);
+ testMethod('clean+scrubbing+down+nonMappedState', PgCategory.CATEGORY_WARNING);
+ });
+
+ it(PgCategory.CATEGORY_UNKNOWN, () => {
+ testMethod('clean+scrubbing+nonMappedState', PgCategory.CATEGORY_UNKNOWN);
+ testMethod('nonMappedState', PgCategory.CATEGORY_UNKNOWN);
+ testMethod('', PgCategory.CATEGORY_UNKNOWN);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.ts
new file mode 100644
index 00000000..79c2bcc9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/pg-category.service.ts
@@ -0,0 +1,63 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { CephSharedModule } from './ceph-shared.module';
+import { PgCategory } from './pg-category.model';
+
+@Injectable({
+ providedIn: CephSharedModule
+})
+export class PgCategoryService {
+ private categories: object;
+
+ constructor() {
+ this.categories = this.createCategories();
+ }
+
+ getAllTypes() {
+ return PgCategory.VALID_CATEGORIES;
+ }
+
+ getTypeByStates(pgStatesText: string): string {
+ const pgStates = this.getPgStatesFromText(pgStatesText);
+
+ if (pgStates.length === 0) {
+ return PgCategory.CATEGORY_UNKNOWN;
+ }
+
+ const intersections = _.zipObject(
+ PgCategory.VALID_CATEGORIES,
+ PgCategory.VALID_CATEGORIES.map(
+ (category) => _.intersection(this.categories[category].states, pgStates).length
+ )
+ );
+
+ if (intersections[PgCategory.CATEGORY_WARNING] > 0) {
+ return PgCategory.CATEGORY_WARNING;
+ }
+
+ const pgWorkingStates = intersections[PgCategory.CATEGORY_WORKING];
+ if (pgStates.length > intersections[PgCategory.CATEGORY_CLEAN] + pgWorkingStates) {
+ return PgCategory.CATEGORY_UNKNOWN;
+ }
+
+ return pgWorkingStates ? PgCategory.CATEGORY_WORKING : PgCategory.CATEGORY_CLEAN;
+ }
+
+ private createCategories() {
+ return _.zipObject(
+ PgCategory.VALID_CATEGORIES,
+ PgCategory.VALID_CATEGORIES.map((category) => new PgCategory(category))
+ );
+ }
+
+ private getPgStatesFromText(pgStatesText) {
+ const pgStates = pgStatesText
+ .replace(/[^a-z]+/g, ' ')
+ .trim()
+ .split(' ');
+
+ return _.uniq(pgStates);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/auth.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/auth.module.ts
new file mode 100644
index 00000000..cdba46c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/auth.module.ts
@@ -0,0 +1,86 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { ActionLabels, URLVerbs } from '../../shared/constants/app.constants';
+import { SharedModule } from '../../shared/shared.module';
+import { LoginComponent } from './login/login.component';
+import { RoleDetailsComponent } from './role-details/role-details.component';
+import { RoleFormComponent } from './role-form/role-form.component';
+import { RoleListComponent } from './role-list/role-list.component';
+import { SsoNotFoundComponent } from './sso/sso-not-found/sso-not-found.component';
+import { UserFormComponent } from './user-form/user-form.component';
+import { UserListComponent } from './user-list/user-list.component';
+import { UserTabsComponent } from './user-tabs/user-tabs.component';
+
+@NgModule({
+ imports: [
+ BsDropdownModule.forRoot(),
+ CommonModule,
+ FormsModule,
+ PopoverModule.forRoot(),
+ ReactiveFormsModule,
+ SharedModule,
+ TabsModule.forRoot(),
+ RouterModule
+ ],
+ declarations: [
+ LoginComponent,
+ RoleDetailsComponent,
+ RoleFormComponent,
+ RoleListComponent,
+ SsoNotFoundComponent,
+ UserTabsComponent,
+ UserListComponent,
+ UserFormComponent
+ ]
+})
+export class AuthModule {}
+
+const routes: Routes = [
+ { path: '', redirectTo: 'users', pathMatch: 'full' },
+ {
+ path: 'users',
+ data: { breadcrumbs: 'Users' },
+ children: [
+ { path: '', component: UserListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: UserFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:username`,
+ component: UserFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ },
+ {
+ path: 'roles',
+ data: { breadcrumbs: 'Roles' },
+ children: [
+ { path: '', component: RoleListComponent },
+ {
+ path: URLVerbs.CREATE,
+ component: RoleFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
+ },
+ {
+ path: `${URLVerbs.EDIT}/:name`,
+ component: RoleFormComponent,
+ data: { breadcrumbs: ActionLabels.EDIT }
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [AuthModule, RouterModule.forChild(routes)]
+})
+export class RoutedAuthModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.html
new file mode 100644
index 00000000..d0b91960
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.html
@@ -0,0 +1,69 @@
+<div class="login"
+ *ngIf="isLoginActive">
+ <div class="row full-height vertical-align">
+ <div class="col-sm-6 hidden-xs">
+ <img src="assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png"
+ alt="Ceph"
+ class="pull-right">
+ </div>
+ <div class="col-xs-10 col-sm-4 col-lg-3 col-xs-offset-1 col-sm-offset-0 col-md-offset-0 col-lg-offset-0">
+ <h1 i18n="The welcome message on the login page">Welcome to Ceph!</h1>
+ <form name="loginForm"
+ (ngSubmit)="login()"
+ #loginForm="ngForm"
+ novalidate>
+
+ <!-- I18N -->
+ <div class="form-group has-feedback">
+ <cd-language-selector [isDropdown]="false"></cd-language-selector>
+ </div>
+
+ <!-- Username -->
+ <div class="form-group has-feedback"
+ [ngClass]="{'has-error': (loginForm.submitted || username.dirty) && username.invalid}">
+ <input name="username"
+ [(ngModel)]="model.username"
+ #username="ngModel"
+ type="text"
+ placeholder="Enter your username..."
+ class="form-control"
+ required
+ autofocus>
+ <div class="help-block"
+ *ngIf="(loginForm.submitted || username.dirty) && username.invalid"
+ i18n>Username is required</div>
+ </div>
+
+ <!-- Password -->
+ <div class="form-group has-feedback"
+ [ngClass]="{'has-error': (loginForm.submitted || password.dirty) && password.invalid}">
+ <div class="input-group">
+ <input id="password"
+ name="password"
+ [(ngModel)]="model.password"
+ #password="ngModel"
+ type="password"
+ placeholder="Enter your password..."
+ class="form-control"
+ required>
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default btn-password"
+ cdPasswordButton="password">
+ </button>
+ </span>
+ </div>
+ <div class="help-block"
+ *ngIf="(loginForm.submitted || password.dirty) && password.invalid"
+ i18n>Password is required</div>
+ </div>
+
+ <input type="submit"
+ class="btn btn-primary btn-block"
+ [disabled]="loginForm.invalid"
+ value="Login"
+ i18n-value>
+ </form>
+ </div>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.scss
new file mode 100644
index 00000000..24224973
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.scss
@@ -0,0 +1,31 @@
+@import '../../../../defaults';
+
+::ng-deep .login {
+ height: 100%;
+
+ .row {
+ color: $color-login-row-text;
+ background-color: $color-login-row-bg;
+ }
+
+ h1 {
+ margin-top: 0;
+ margin-bottom: 30px;
+ }
+
+ .btn-password,
+ .form-control {
+ color: $color-password-toggle-text;
+ background-color: $color-password-toggle-bg;
+ }
+
+ .btn-password:focus {
+ outline-color: $color-password-toggle-focus;
+ }
+
+ .checkbox-primary input[type='checkbox']:checked + label::before,
+ .checkbox-primary input[type='radio']:checked + label::before {
+ background-color: $color-login-checkbox-bg;
+ border-color: $color-login-checkbox-border;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.spec.ts
new file mode 100644
index 00000000..daa96f34
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.spec.ts
@@ -0,0 +1,32 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { AuthModule } from '../auth.module';
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture<LoginComponent>;
+
+ configureTestBed({
+ imports: [RouterTestingModule, HttpClientTestingModule, AuthModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should ensure no modal dialogs are opened', () => {
+ component['bsModalService']['modalsCount'] = 2;
+ component.ngOnInit();
+ expect(component['bsModalService'].getModalsCount()).toBe(0);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.ts
new file mode 100644
index 00000000..05609f1c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/login/login.component.ts
@@ -0,0 +1,68 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import * as _ from 'lodash';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+
+import { AuthService } from '../../../shared/api/auth.service';
+import { Credentials } from '../../../shared/models/credentials';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.scss']
+})
+export class LoginComponent implements OnInit {
+ model = new Credentials();
+ isLoginActive = false;
+ returnUrl: string;
+
+ constructor(
+ private authService: AuthService,
+ private authStorageService: AuthStorageService,
+ private bsModalService: BsModalService,
+ private route: ActivatedRoute,
+ private router: Router
+ ) {}
+
+ ngOnInit() {
+ if (this.authStorageService.isLoggedIn()) {
+ this.router.navigate(['']);
+ } else {
+ // Make sure all open modal dialogs are closed. This might be
+ // necessary when the logged in user is redirected to the login
+ // page after a 401.
+ const modalsCount = this.bsModalService.getModalsCount();
+ for (let i = 1; i <= modalsCount; i++) {
+ this.bsModalService.hide(i);
+ }
+ let token = null;
+ if (window.location.hash.indexOf('access_token=') !== -1) {
+ token = window.location.hash.split('access_token=')[1];
+ const uri = window.location.toString();
+ window.history.replaceState({}, document.title, uri.split('?')[0]);
+ }
+ this.authService.check(token).subscribe((login: any) => {
+ if (login.login_url) {
+ if (login.login_url === '#/login') {
+ this.isLoginActive = true;
+ } else {
+ window.location.replace(login.login_url);
+ }
+ } else {
+ this.authStorageService.set(login.username, login.permissions);
+ this.router.navigate(['']);
+ }
+ });
+ }
+ }
+
+ login() {
+ this.authService.login(this.model).then(() => {
+ const url = _.get(this.route.snapshot.queryParams, 'returnUrl', '/');
+ this.router.navigate([url]);
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.html
new file mode 100644
index 00000000..7389a48f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.html
@@ -0,0 +1,13 @@
+<tabset *ngIf="selection?.hasSingleSelection">
+ <tab heading="Details" i18n-heading>
+ <cd-table [data]="scopes_permissions"
+ [columns]="columns"
+ columnMode="flex"
+ [toolHeader]="false"
+ [autoReload]="false"
+ [autoSave]="false"
+ [footer]="false"
+ [limit]="0">
+ </cd-table>
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.scss
new file mode 100644
index 00000000..f9c5b875
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.scss
@@ -0,0 +1,12 @@
+@import '../../../../defaults';
+
+thead {
+ background-color: $color-table-header-bg;
+}
+
+.fa {
+ font-size: large;
+ &.fa-square-o {
+ color: $color-light-gray;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.spec.ts
new file mode 100644
index 00000000..e14cbb63
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.spec.ts
@@ -0,0 +1,77 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { SharedModule } from '../../../shared/shared.module';
+import { RoleDetailsComponent } from './role-details.component';
+
+describe('RoleDetailsComponent', () => {
+ let component: RoleDetailsComponent;
+ let fixture: ComponentFixture<RoleDetailsComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, TabsModule.forRoot(), RouterTestingModule, HttpClientTestingModule],
+ declarations: [RoleDetailsComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RoleDetailsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should create scopes permissions [1/2]', () => {
+ component.scopes = ['log', 'rgw'];
+ component.selection = new CdTableSelection();
+ component.selection.selected = [
+ {
+ description: 'RGW Manager',
+ name: 'rgw-manager',
+ scopes_permissions: {
+ rgw: ['read', 'create', 'update', 'delete']
+ },
+ system: true
+ }
+ ];
+ component.selection.update();
+ expect(component.scopes_permissions.length).toBe(0);
+ component.ngOnChanges();
+ expect(component.scopes_permissions).toEqual([
+ { scope: 'log', read: false, create: false, update: false, delete: false },
+ { scope: 'rgw', read: true, create: true, update: true, delete: true }
+ ]);
+ });
+
+ it('should create scopes permissions [2/2]', () => {
+ component.scopes = ['cephfs', 'log', 'rgw'];
+ component.selection = new CdTableSelection();
+ component.selection.selected = [
+ {
+ description: 'Test',
+ name: 'test',
+ scopes_permissions: {
+ log: ['read', 'update'],
+ rgw: ['read', 'create', 'update']
+ },
+ system: false
+ }
+ ];
+ component.selection.update();
+ expect(component.scopes_permissions.length).toBe(0);
+ component.ngOnChanges();
+ expect(component.scopes_permissions).toEqual([
+ { scope: 'cephfs', read: false, create: false, update: false, delete: false },
+ { scope: 'log', read: true, create: false, update: true, delete: false },
+ { scope: 'rgw', read: true, create: true, update: true, delete: false }
+ ]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.ts
new file mode 100644
index 00000000..4a8e0268
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-details/role-details.component.ts
@@ -0,0 +1,83 @@
+import { Component, Input, OnChanges, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+
+@Component({
+ selector: 'cd-role-details',
+ templateUrl: './role-details.component.html',
+ styleUrls: ['./role-details.component.scss']
+})
+export class RoleDetailsComponent implements OnChanges, OnInit {
+ @Input()
+ selection: CdTableSelection;
+ @Input()
+ scopes: Array<string>;
+ selectedItem: any;
+
+ columns: CdTableColumn[];
+ scopes_permissions: Array<any> = [];
+
+ constructor(private i18n: I18n) {}
+
+ ngOnInit() {
+ this.columns = [
+ {
+ prop: 'scope',
+ name: this.i18n('Scope'),
+ flexGrow: 2
+ },
+ {
+ prop: 'read',
+ name: this.i18n('Read'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ },
+ {
+ prop: 'create',
+ name: this.i18n('Create'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ },
+ {
+ prop: 'update',
+ name: this.i18n('Update'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ },
+ {
+ prop: 'delete',
+ name: this.i18n('Delete'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTransformation: CellTemplate.checkIcon
+ }
+ ];
+ }
+
+ ngOnChanges() {
+ if (this.selection.hasSelection) {
+ this.selectedItem = this.selection.first();
+ // Build the scopes/permissions data used by the data table.
+ const scopes_permissions = [];
+ _.each(this.scopes, (scope) => {
+ const scope_permission = { read: false, create: false, update: false, delete: false };
+ scope_permission['scope'] = scope;
+ if (scope in this.selectedItem['scopes_permissions']) {
+ _.each(this.selectedItem['scopes_permissions'][scope], (permission) => {
+ scope_permission[permission] = true;
+ });
+ }
+ scopes_permissions.push(scope_permission);
+ });
+ this.scopes_permissions = scopes_permissions;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form-mode.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form-mode.enum.ts
new file mode 100644
index 00000000..4f0a6f11
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form-mode.enum.ts
@@ -0,0 +1,3 @@
+export enum RoleFormMode {
+ editing = 'editing'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html
new file mode 100644
index 00000000..2f9eefa9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html
@@ -0,0 +1,125 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="roleForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="roleForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Name -->
+ <div class="form-group"
+ [ngClass]="{'has-error': roleForm.showError('name', formDir)}">
+ <label class="control-label col-sm-3"
+ for="name">
+ <ng-container i18n>Name</ng-container>
+ <span class="required"
+ *ngIf="mode !== roleFormMode.editing"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ i18n-placeholder
+ placeholder="Name..."
+ id="name"
+ name="name"
+ formControlName="name"
+ autofocus>
+ <span class="help-block"
+ *ngIf="roleForm.showError('name', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="roleForm.showError('name', formDir, 'notUnique')"
+ i18n>The chosen name is already in use.</span>
+ </div>
+ </div>
+
+ <!-- Description -->
+ <div class="form-group"
+ [ngClass]="{'has-error': roleForm.showError('description', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="description">Description</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ i18n-placeholder
+ placeholder="Description..."
+ id="description"
+ name="description"
+ formControlName="description">
+ </div>
+ </div>
+
+ <!-- Permissions -->
+ <div class="form-group">
+ <label i18n
+ class="control-label col-sm-3">Permissions</label>
+ <div class="col-sm-9">
+ <cd-table [data]="scopes_permissions"
+ [columns]="columns"
+ columnMode="flex"
+ [toolHeader]="false"
+ [autoReload]="false"
+ [autoSave]="false"
+ [footer]="false"
+ [limit]="0">
+ </cd-table>
+ </div>
+ </div>
+
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir" (submitAction)="submit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
+
+<ng-template #cellScopeCheckboxTpl
+ let-column="column"
+ let-row="row"
+ let-value="value">
+ <div class="checkbox checkbox-primary">
+ <input id="scope_{{ row.scope }}"
+ type="checkbox"
+ [checked]="isRowChecked(row.scope)"
+ (change)="onClickCellCheckbox(row.scope, column.prop, $event)">
+ <label class="datatable-permissions-scope-cell-label"
+ for="scope_{{ row.scope }}">{{ value }}</label>
+ </div>
+</ng-template>
+
+<ng-template #cellPermissionCheckboxTpl
+ let-column="column"
+ let-row="row"
+ let-value="value">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ [checked]="value"
+ (change)="onClickCellCheckbox(row.scope, column.prop, $event)">
+ <label></label>
+ </div>
+</ng-template>
+
+<ng-template #headerPermissionCheckboxTpl
+ let-column="column">
+ <div class="checkbox checkbox-primary">
+ <input id="header_{{ column.prop }}"
+ type="checkbox"
+ [checked]="isHeaderChecked(column.prop)"
+ (change)="onClickHeaderCheckbox(column.prop, $event)">
+ <label class="datatable-permissions-header-cell-label"
+ for="header_{{ column.prop }}">{{ column.name }}</label>
+ </div>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.scss
new file mode 100644
index 00000000..3caafa2e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.scss
@@ -0,0 +1,4 @@
+.datatable-permissions-header-cell-label,
+.datatable-permissions-scope-cell-label {
+ font-weight: bold;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts
new file mode 100644
index 00000000..b5d36b58
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts
@@ -0,0 +1,222 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper';
+import { RoleService } from '../../../shared/api/role.service';
+import { ScopeService } from '../../../shared/api/scope.service';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { RoleFormComponent } from './role-form.component';
+import { RoleFormModel } from './role-form.model';
+
+describe('RoleFormComponent', () => {
+ let component: RoleFormComponent;
+ let form: CdFormGroup;
+ let fixture: ComponentFixture<RoleFormComponent>;
+ let httpTesting: HttpTestingController;
+ let roleService: RoleService;
+ let router: Router;
+ const setUrl = (url) => Object.defineProperty(router, 'url', { value: url });
+
+ @Component({ selector: 'cd-fake', template: '' })
+ class FakeComponent {}
+
+ const routes: Routes = [{ path: 'roles', component: FakeComponent }];
+
+ configureTestBed(
+ {
+ imports: [
+ RouterTestingModule.withRoutes(routes),
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ ToastrModule.forRoot(),
+ SharedModule
+ ],
+ declarations: [RoleFormComponent, FakeComponent],
+ providers: i18nProviders
+ },
+ true
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RoleFormComponent);
+ component = fixture.componentInstance;
+ form = component.roleForm;
+ httpTesting = TestBed.get(HttpTestingController);
+ roleService = TestBed.get(RoleService);
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate');
+ fixture.detectChanges();
+ const notify = TestBed.get(NotificationService);
+ spyOn(notify, 'show');
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(form).toBeTruthy();
+ });
+
+ describe('create mode', () => {
+ let formHelper: FormHelper;
+
+ beforeEach(() => {
+ setUrl('/user-management/roles/add');
+ component.ngOnInit();
+ formHelper = new FormHelper(form);
+ });
+
+ it('should not disable fields', () => {
+ ['name', 'description', 'scopes_permissions'].forEach((key) =>
+ expect(form.get(key).disabled).toBeFalsy()
+ );
+ });
+
+ it('should validate name required', () => {
+ formHelper.expectErrorChange('name', '', 'required');
+ });
+
+ it('should set mode', () => {
+ expect(component.mode).toBeUndefined();
+ });
+
+ it('should submit', () => {
+ const role: RoleFormModel = {
+ name: 'role1',
+ description: 'Role 1',
+ scopes_permissions: { osd: ['read'] }
+ };
+ formHelper.setMultipleValues(role);
+ component.submit();
+ const roleReq = httpTesting.expectOne('api/role');
+ expect(roleReq.request.method).toBe('POST');
+ expect(roleReq.request.body).toEqual(role);
+ roleReq.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['/user-management/roles']);
+ });
+
+ it('should check all perms for a scope', () => {
+ formHelper.setValue('scopes_permissions', { cephfs: ['read'] });
+ component.onClickCellCheckbox('grafana', 'scope');
+ const scopes_permissions = form.getValue('scopes_permissions');
+ expect(Object.keys(scopes_permissions)).toContain('grafana');
+ expect(scopes_permissions['grafana']).toEqual(['create', 'delete', 'read', 'update']);
+ });
+
+ it('should uncheck all perms for a scope', () => {
+ formHelper.setValue('scopes_permissions', { cephfs: ['read', 'create', 'update', 'delete'] });
+ component.onClickCellCheckbox('cephfs', 'scope');
+ const scopes_permissions = form.getValue('scopes_permissions');
+ expect(Object.keys(scopes_permissions)).not.toContain('cephfs');
+ });
+
+ it('should uncheck all scopes and perms', () => {
+ component.scopes = ['cephfs', 'grafana'];
+ formHelper.setValue('scopes_permissions', {
+ cephfs: ['read', 'delete'],
+ grafana: ['update']
+ });
+ component.onClickHeaderCheckbox('scope', ({
+ target: { checked: false }
+ } as unknown) as Event);
+ const scopes_permissions = form.getValue('scopes_permissions');
+ expect(scopes_permissions).toEqual({});
+ });
+
+ it('should check all scopes and perms', () => {
+ component.scopes = ['cephfs', 'grafana'];
+ formHelper.setValue('scopes_permissions', {
+ cephfs: ['create', 'update'],
+ grafana: ['delete']
+ });
+ component.onClickHeaderCheckbox('scope', ({ target: { checked: true } } as unknown) as Event);
+ const scopes_permissions = form.getValue('scopes_permissions');
+ const keys = Object.keys(scopes_permissions);
+ expect(keys).toEqual(['cephfs', 'grafana']);
+ keys.forEach((key) => {
+ expect(scopes_permissions[key].sort()).toEqual(['create', 'delete', 'read', 'update']);
+ });
+ });
+
+ it('should check if column is checked', () => {
+ component.scopes_permissions = [
+ { scope: 'a', read: true, create: true, update: true, delete: true },
+ { scope: 'b', read: false, create: true, update: false, delete: true }
+ ];
+ expect(component.isRowChecked('a')).toBeTruthy();
+ expect(component.isRowChecked('b')).toBeFalsy();
+ expect(component.isRowChecked('c')).toBeFalsy();
+ });
+
+ it('should check if header is checked', () => {
+ component.scopes_permissions = [
+ { scope: 'a', read: true, create: true, update: false, delete: true },
+ { scope: 'b', read: false, create: true, update: false, delete: true }
+ ];
+ expect(component.isHeaderChecked('read')).toBeFalsy();
+ expect(component.isHeaderChecked('create')).toBeTruthy();
+ expect(component.isHeaderChecked('update')).toBeFalsy();
+ });
+ });
+
+ describe('edit mode', () => {
+ const role: RoleFormModel = {
+ name: 'role1',
+ description: 'Role 1',
+ scopes_permissions: { osd: ['read', 'create'] }
+ };
+ const scopes = ['osd', 'user'];
+ beforeEach(() => {
+ spyOn(roleService, 'get').and.callFake(() => of(role));
+ spyOn(TestBed.get(ScopeService), 'list').and.callFake(() => of(scopes));
+ setUrl('/user-management/roles/edit/role1');
+ component.ngOnInit();
+ const reqScopes = httpTesting.expectOne('ui-api/scope');
+ expect(reqScopes.request.method).toBe('GET');
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should disable fields if editing', () => {
+ expect(form.get('name').disabled).toBeTruthy();
+ ['description', 'scopes_permissions'].forEach((key) =>
+ expect(form.get(key).disabled).toBeFalsy()
+ );
+ });
+
+ it('should set control values', () => {
+ ['name', 'description', 'scopes_permissions'].forEach((key) =>
+ expect(form.getValue(key)).toBe(role[key])
+ );
+ });
+
+ it('should set mode', () => {
+ expect(component.mode).toBe('editing');
+ });
+
+ it('should submit', () => {
+ component.onClickCellCheckbox('osd', 'update');
+ component.onClickCellCheckbox('osd', 'create');
+ component.onClickCellCheckbox('user', 'read');
+ component.submit();
+ const roleReq = httpTesting.expectOne(`api/role/${role.name}`);
+ expect(roleReq.request.method).toBe('PUT');
+ expect(roleReq.request.body).toEqual({
+ name: 'role1',
+ description: 'Role 1',
+ scopes_permissions: { osd: ['read', 'update'], user: ['read'] }
+ });
+ roleReq.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['/user-management/roles']);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts
new file mode 100644
index 00000000..29efb82c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts
@@ -0,0 +1,314 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { forkJoin as observableForkJoin } from 'rxjs';
+
+import { RoleService } from '../../../shared/api/role.service';
+import { ScopeService } from '../../../shared/api/scope.service';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { RoleFormMode } from './role-form-mode.enum';
+import { RoleFormModel } from './role-form.model';
+
+@Component({
+ selector: 'cd-role-form',
+ templateUrl: './role-form.component.html',
+ styleUrls: ['./role-form.component.scss']
+})
+export class RoleFormComponent implements OnInit {
+ @ViewChild('headerPermissionCheckboxTpl')
+ headerPermissionCheckboxTpl: TemplateRef<any>;
+ @ViewChild('cellScopeCheckboxTpl')
+ cellScopeCheckboxTpl: TemplateRef<any>;
+ @ViewChild('cellPermissionCheckboxTpl')
+ cellPermissionCheckboxTpl: TemplateRef<any>;
+
+ modalRef: BsModalRef;
+
+ roleForm: CdFormGroup;
+ response: RoleFormModel;
+
+ columns: CdTableColumn[];
+ scopes: Array<string> = [];
+ scopes_permissions: Array<any> = [];
+
+ roleFormMode = RoleFormMode;
+ mode: RoleFormMode;
+
+ action: string;
+ resource: string;
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private roleService: RoleService,
+ private scopeService: ScopeService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('role');
+ this.createForm();
+ this.listenToChanges();
+ }
+
+ createForm() {
+ this.roleForm = new CdFormGroup({
+ name: new FormControl('', {
+ validators: [Validators.required],
+ asyncValidators: [CdValidators.unique(this.roleService.exists, this.roleService)]
+ }),
+ description: new FormControl(''),
+ scopes_permissions: new FormControl({})
+ });
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ prop: 'scope',
+ name: this.i18n('All'),
+ flexGrow: 2,
+ cellTemplate: this.cellScopeCheckboxTpl,
+ headerTemplate: this.headerPermissionCheckboxTpl
+ },
+ {
+ prop: 'read',
+ name: this.i18n('Read'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTemplate: this.cellPermissionCheckboxTpl,
+ headerTemplate: this.headerPermissionCheckboxTpl
+ },
+ {
+ prop: 'create',
+ name: this.i18n('Create'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTemplate: this.cellPermissionCheckboxTpl,
+ headerTemplate: this.headerPermissionCheckboxTpl
+ },
+ {
+ prop: 'update',
+ name: this.i18n('Update'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTemplate: this.cellPermissionCheckboxTpl,
+ headerTemplate: this.headerPermissionCheckboxTpl
+ },
+ {
+ prop: 'delete',
+ name: this.i18n('Delete'),
+ flexGrow: 1,
+ cellClass: 'text-center',
+ cellTemplate: this.cellPermissionCheckboxTpl,
+ headerTemplate: this.headerPermissionCheckboxTpl
+ }
+ ];
+ if (this.router.url.startsWith('/user-management/roles/edit')) {
+ this.mode = this.roleFormMode.editing;
+ this.action = this.actionLabels.EDIT;
+ } else {
+ this.action = this.actionLabels.CREATE;
+ }
+ if (this.mode === this.roleFormMode.editing) {
+ this.initEdit();
+ } else {
+ this.initCreate();
+ }
+ }
+
+ initCreate() {
+ // Load the scopes and initialize the default scopes/permissions data.
+ this.scopeService.list().subscribe((scopes: Array<string>) => {
+ this.scopes = scopes;
+ this.roleForm.get('scopes_permissions').setValue({});
+ });
+ }
+
+ initEdit() {
+ // Disable the 'Name' input field.
+ this.roleForm.get('name').disable();
+ // Load the scopes and the role data.
+ this.route.params.subscribe((params: { name: string }) => {
+ const observables = [];
+ observables.push(this.scopeService.list());
+ observables.push(this.roleService.get(params.name));
+ observableForkJoin(observables).subscribe((resp: any[]) => {
+ this.scopes = resp[0];
+ ['name', 'description', 'scopes_permissions'].forEach((key) =>
+ this.roleForm.get(key).setValue(resp[1][key])
+ );
+ });
+ });
+ }
+
+ listenToChanges() {
+ // Create/Update the data which is used by the data table to display the
+ // scopes/permissions every time the form field value has been changed.
+ this.roleForm.get('scopes_permissions').valueChanges.subscribe((value) => {
+ const scopes_permissions = [];
+ _.each(this.scopes, (scope) => {
+ // Set the defaults values.
+ const scope_permission = { read: false, create: false, update: false, delete: false };
+ scope_permission['scope'] = scope;
+ // Apply settings from the given value if they exist.
+ if (scope in value) {
+ _.each(value[scope], (permission) => {
+ scope_permission[permission] = true;
+ });
+ }
+ scopes_permissions.push(scope_permission);
+ });
+ this.scopes_permissions = scopes_permissions;
+ });
+ }
+
+ /**
+ * Checks if the specified row checkbox needs to be rendered as checked.
+ * @param {string} scope The scope to be checked, e.g. 'cephfs', 'grafana',
+ * 'osd', 'pool' ...
+ * @return Returns true if all permissions (read, create, update, delete)
+ * are checked for the specified scope, otherwise false.
+ */
+ isRowChecked(scope: string) {
+ const scope_permission = _.find(this.scopes_permissions, (o) => {
+ return o['scope'] === scope;
+ });
+ if (_.isUndefined(scope_permission)) {
+ return false;
+ }
+ return (
+ scope_permission['read'] &&
+ scope_permission['create'] &&
+ scope_permission['update'] &&
+ scope_permission['delete']
+ );
+ }
+
+ /**
+ * Checks if the specified header checkbox needs to be rendered as checked.
+ * @param {string} property The property/permission (read, create,
+ * update, delete) to be checked. If 'scope' is given, all permissions
+ * are checked.
+ * @return Returns true if specified property/permission is selected
+ * for all scopes, otherwise false.
+ */
+ isHeaderChecked(property: string) {
+ let permissions = [property];
+ if ('scope' === property) {
+ permissions = ['read', 'create', 'update', 'delete'];
+ }
+ return permissions.every((permission) => {
+ return this.scopes_permissions.every((scope_permission) => {
+ return scope_permission[permission];
+ });
+ });
+ }
+
+ onClickCellCheckbox(scope: string, property: string, event: Event = null) {
+ // Use a copy of the form field data to do not trigger the redrawing of the
+ // data table with every change.
+ const scopes_permissions = _.cloneDeep(this.roleForm.getValue('scopes_permissions'));
+ let permissions = [property];
+ if ('scope' === property) {
+ permissions = ['read', 'create', 'update', 'delete'];
+ }
+ if (!(scope in scopes_permissions)) {
+ scopes_permissions[scope] = [];
+ }
+ // Add or remove the given permission(s) depending on the click event or if no
+ // click event is given then add/remove them if they are absent/exist.
+ if (
+ (event && event.target['checked']) ||
+ !_.isEqual(permissions.sort(), _.intersection(scopes_permissions[scope], permissions).sort())
+ ) {
+ scopes_permissions[scope] = _.union(scopes_permissions[scope], permissions);
+ } else {
+ scopes_permissions[scope] = _.difference(scopes_permissions[scope], permissions);
+ if (_.isEmpty(scopes_permissions[scope])) {
+ _.unset(scopes_permissions, scope);
+ }
+ }
+ this.roleForm.get('scopes_permissions').setValue(scopes_permissions);
+ }
+
+ onClickHeaderCheckbox(property: 'scope' | 'read' | 'create' | 'update' | 'delete', event: Event) {
+ // Use a copy of the form field data to do not trigger the redrawing of the
+ // data table with every change.
+ const scopes_permissions = _.cloneDeep(this.roleForm.getValue('scopes_permissions'));
+ let permissions = [property];
+ if ('scope' === property) {
+ permissions = ['read', 'create', 'update', 'delete'];
+ }
+ _.each(permissions, (permission) => {
+ _.each(this.scopes, (scope) => {
+ if (event.target['checked']) {
+ scopes_permissions[scope] = _.union(scopes_permissions[scope], [permission]);
+ } else {
+ scopes_permissions[scope] = _.difference(scopes_permissions[scope], [permission]);
+ if (_.isEmpty(scopes_permissions[scope])) {
+ _.unset(scopes_permissions, scope);
+ }
+ }
+ });
+ });
+ this.roleForm.get('scopes_permissions').setValue(scopes_permissions);
+ }
+
+ getRequest(): RoleFormModel {
+ const roleFormModel = new RoleFormModel();
+ ['name', 'description', 'scopes_permissions'].forEach(
+ (key) => (roleFormModel[key] = this.roleForm.get(key).value)
+ );
+ return roleFormModel;
+ }
+
+ createAction() {
+ const roleFormModel = this.getRequest();
+ this.roleService.create(roleFormModel).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n(`Created role '{{role_name}}'`, { role_name: roleFormModel.name })
+ );
+ this.router.navigate(['/user-management/roles']);
+ },
+ () => {
+ this.roleForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ editAction() {
+ const roleFormModel = this.getRequest();
+ this.roleService.update(roleFormModel).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n(`Updated role '{{role_name}}'`, { role_name: roleFormModel.name })
+ );
+ this.router.navigate(['/user-management/roles']);
+ },
+ () => {
+ this.roleForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ submit() {
+ if (this.mode === this.roleFormMode.editing) {
+ this.editAction();
+ } else {
+ this.createAction();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.model.ts
new file mode 100644
index 00000000..74a7323b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.model.ts
@@ -0,0 +1,5 @@
+export class RoleFormModel {
+ name: string;
+ description: string;
+ scopes_permissions: any;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.html
new file mode 100644
index 00000000..75331794
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.html
@@ -0,0 +1,19 @@
+<cd-user-tabs></cd-user-tabs>
+
+<cd-table [data]="roles"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="name"
+ selectionType="single"
+ (fetchData)="getRoles()"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <cd-role-details cdTableDetail
+ [selection]="selection"
+ [scopes]="scopes">
+ </cd-role-details>
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.spec.ts
new file mode 100644
index 00000000..7274125f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.spec.ts
@@ -0,0 +1,203 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { ActionLabels } from '../../../shared/constants/app.constants';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../shared/shared.module';
+import { RoleDetailsComponent } from '../role-details/role-details.component';
+import { UserTabsComponent } from '../user-tabs/user-tabs.component';
+import { RoleListComponent } from './role-list.component';
+
+describe('RoleListComponent', () => {
+ let component: RoleListComponent;
+ let fixture: ComponentFixture<RoleListComponent>;
+
+ configureTestBed({
+ declarations: [RoleListComponent, RoleDetailsComponent, UserTabsComponent],
+ imports: [
+ SharedModule,
+ ToastrModule.forRoot(),
+ TabsModule.forRoot(),
+ RouterTestingModule,
+ HttpClientTestingModule
+ ],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RoleListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: ActionLabels.EDIT,
+ empty: ActionLabels.CREATE
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows 'Add' and 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Add' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows always 'Add' as main action`, () => {
+ scenario.single = ActionLabels.CREATE;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Add' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.ts
new file mode 100644
index 00000000..569e1fdd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-list/role-list.component.ts
@@ -0,0 +1,138 @@
+import { Component, OnInit } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { forkJoin } from 'rxjs';
+
+import { RoleService } from '../../../shared/api/role.service';
+import { ScopeService } from '../../../shared/api/scope.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { CellTemplate } from '../../../shared/enum/cell-template.enum';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { EmptyPipe } from '../../../shared/pipes/empty.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+
+const BASE_URL = 'user-management/roles';
+
+@Component({
+ selector: 'cd-role-list',
+ templateUrl: './role-list.component.html',
+ styleUrls: ['./role-list.component.scss'],
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }]
+})
+export class RoleListComponent implements OnInit {
+ permission: Permission;
+ tableActions: CdTableAction[];
+ columns: CdTableColumn[];
+ roles: Array<any>;
+ scopes: Array<string>;
+ selection = new CdTableSelection();
+
+ modalRef: BsModalRef;
+
+ constructor(
+ private roleService: RoleService,
+ private scopeService: ScopeService,
+ private emptyPipe: EmptyPipe,
+ private authStorageService: AuthStorageService,
+ private modalService: BsModalService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ private urlBuilder: URLBuilderService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().user;
+ const addAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ name: this.actionLabels.CREATE
+ };
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ disable: () => !this.selection.hasSingleSelection || this.selection.first().system,
+ routerLink: () =>
+ this.selection.first() && this.urlBuilder.getEdit(this.selection.first().name),
+ name: this.actionLabels.EDIT
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ disable: () => !this.selection.hasSingleSelection || this.selection.first().system,
+ click: () => this.deleteRoleModal(),
+ name: this.actionLabels.DELETE
+ };
+ this.tableActions = [addAction, editAction, deleteAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 3
+ },
+ {
+ name: this.i18n('Description'),
+ prop: 'description',
+ flexGrow: 5,
+ pipe: this.emptyPipe
+ },
+ {
+ name: this.i18n('System Role'),
+ prop: 'system',
+ cellClass: 'text-center',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.checkIcon
+ }
+ ];
+ }
+
+ getRoles() {
+ forkJoin([this.roleService.list(), this.scopeService.list()]).subscribe(
+ (data: [Array<any>, Array<string>]) => {
+ this.roles = data[0];
+ this.scopes = data[1];
+ }
+ );
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteRole(role: string) {
+ this.roleService.delete(role).subscribe(
+ () => {
+ this.getRoles();
+ this.modalRef.hide();
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n(`Deleted role '{{role_name}}'`, { role_name: role })
+ );
+ },
+ () => {
+ this.modalRef.content.stopLoadingSpinner();
+ }
+ );
+ }
+
+ deleteRoleModal() {
+ const name = this.selection.first().name;
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: 'Role',
+ itemNames: [name],
+ submitAction: () => this.deleteRole(name)
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.html
new file mode 100644
index 00000000..6187a09b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.html
@@ -0,0 +1,15 @@
+<div class="row">
+ <div class="col-md-12 text-center">
+ <h1 i18n>Sorry, the user does not exist in Ceph.</h1>
+ <h4 i18n>Return to <a class="sso-logout" [href]="logoutUrl">Login Page</a>. You'll be logged out from the Identity Provider when you retry logging in.</h4>
+
+ <img class="img-responsive center-block img-rounded"
+ src="assets/1280px-Nautilus_Octopus.jpg">
+ <span>
+ "<a href="https://www.flickr.com/photos/146401137@N06/40335060661">Nautilus Octopus</a>" by Jin Kemoole is licensed under
+ <a rel="nofollow"
+ class="external text"
+ href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>
+ </span>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.scss
new file mode 100644
index 00000000..fdf2e710
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.scss
@@ -0,0 +1,11 @@
+h1 {
+ font-size: -webkit-xxx-large;
+}
+
+* {
+ font-family: monospace;
+}
+
+img {
+ width: 50vw;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.spec.ts
new file mode 100644
index 00000000..528c7b1b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.spec.ts
@@ -0,0 +1,30 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../../testing/unit-test-helper';
+import { SsoNotFoundComponent } from './sso-not-found.component';
+
+describe('SsoNotFoundComponent', () => {
+ let component: SsoNotFoundComponent;
+ let fixture: ComponentFixture<SsoNotFoundComponent>;
+
+ configureTestBed({
+ declarations: [SsoNotFoundComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SsoNotFoundComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should render the correct logout url', () => {
+ const expectedUrl = `http://localhost/auth/saml2/slo`;
+ const logoutAnchor = fixture.debugElement.nativeElement.querySelector('.sso-logout');
+
+ expect(logoutAnchor.href).toEqual(expectedUrl);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.ts
new file mode 100644
index 00000000..24bfcd94
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/sso/sso-not-found/sso-not-found.component.ts
@@ -0,0 +1,14 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'cd-sso-not-found',
+ templateUrl: './sso-not-found.component.html',
+ styleUrls: ['./sso-not-found.component.scss']
+})
+export class SsoNotFoundComponent {
+ logoutUrl: string;
+
+ constructor() {
+ this.logoutUrl = `${window.location.origin}/auth/saml2/slo`;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-mode.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-mode.enum.ts
new file mode 100644
index 00000000..8cae7d15
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-mode.enum.ts
@@ -0,0 +1,3 @@
+export enum UserFormMode {
+ editing = 'editing'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-role.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-role.model.ts
new file mode 100644
index 00000000..ea32b634
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form-role.model.ts
@@ -0,0 +1,14 @@
+import { SelectOption } from '../../../shared/components/select/select-option.model';
+
+export class UserFormRoleModel implements SelectOption {
+ name: string;
+ description: string;
+ selected = false;
+ scopes_permissions: object;
+ enabled = true;
+
+ constructor(name, description) {
+ this.name = name;
+ this.description = description;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html
new file mode 100644
index 00000000..902e5f35
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html
@@ -0,0 +1,163 @@
+<div class="col-sm-12 col-lg-6">
+ <form name="userForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="userForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 i18n="form title|Example: Create Pool@@formTitle"
+ class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Username -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('username', formDir)}">
+ <label class="control-label col-sm-3"
+ for="name">
+ <ng-container i18n>Username</ng-container>
+ <span class="required"
+ *ngIf="mode !== userFormMode.editing"></span>
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Username..."
+ id="username"
+ name="username"
+ formControlName="username"
+ autofocus>
+ <span class="help-block"
+ *ngIf="userForm.showError('username', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('password', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="name">Password</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ placeholder="Password..."
+ id="password"
+ name="password"
+ autocomplete="new-password"
+ formControlName="password">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="password">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="userForm.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- Confirm password -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('confirmpassword', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="name">Confirm password</label>
+ <div class="col-sm-9">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ placeholder="Confirm password..."
+ id="confirmpassword"
+ name="confirmpassword"
+ formControlName="confirmpassword">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default"
+ cdPasswordButton="confirmpassword">
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="userForm.showError('confirmpassword', formDir, 'required')"
+ i18n>This field is required.</span>
+ <span class="help-block"
+ *ngIf="userForm.showError('confirmpassword', formDir, 'match')"
+ i18n>Password confirmation doesn't match the password.</span>
+ </div>
+ </div>
+
+ <!-- Name -->
+ <div class="form-group">
+ <label i18n
+ class="control-label col-sm-3"
+ for="name">Full name</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ placeholder="Full name..."
+ id="name"
+ name="name"
+ formControlName="name">
+ </div>
+ </div>
+
+ <!-- Email -->
+ <div class="form-group"
+ [ngClass]="{'has-error': userForm.showError('email', formDir)}">
+ <label i18n
+ class="control-label col-sm-3"
+ for="email">Email</label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="email"
+ placeholder="Email..."
+ id="email"
+ name="email"
+ formControlName="email">
+
+ <span class="help-block"
+ *ngIf="userForm.showError('email', formDir, 'email')"
+ i18n>Invalid email.</span>
+ </div>
+ </div>
+
+ <!-- Roles -->
+ <label class="col-sm-3 control-label"
+ i18n>Roles</label>
+ <div class="col-sm-9">
+ <span class="form-control no-border full-height"
+ *ngIf="allRoles">
+ <cd-select-badges [data]="userForm.controls.roles.value"
+ [options]="allRoles"
+ [messages]="messages"></cd-select-badges>
+ </span>
+ </div>
+
+ </div>
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <cd-submit-button
+ [form]="formDir"
+ (submitAction)="submit()"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-back-button></cd-back-button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
+
+<ng-template #removeSelfUserReadUpdatePermissionTpl>
+ <p><strong i18n>You are about to remove "user read / update" permissions from your own user.</strong></p>
+ <br>
+ <p i18n>If you continue, you will no longer be able to add or remove roles from any user.</p>
+
+ <ng-container i18n>Are you sure you want to continue?</ng-container>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts
new file mode 100644
index 00000000..b91a71fd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts
@@ -0,0 +1,231 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { ToastrModule } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper';
+import { RoleService } from '../../../shared/api/role.service';
+import { UserService } from '../../../shared/api/user.service';
+import { ComponentsModule } from '../../../shared/components/components.module';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { UserFormComponent } from './user-form.component';
+import { UserFormModel } from './user-form.model';
+
+describe('UserFormComponent', () => {
+ let component: UserFormComponent;
+ let form: CdFormGroup;
+ let fixture: ComponentFixture<UserFormComponent>;
+ let httpTesting: HttpTestingController;
+ let userService: UserService;
+ let modalService: BsModalService;
+ let router: Router;
+ let formHelper: FormHelper;
+
+ const setUrl = (url) => Object.defineProperty(router, 'url', { value: url });
+
+ @Component({ selector: 'cd-fake', template: '' })
+ class FakeComponent {}
+
+ const routes: Routes = [
+ { path: 'login', component: FakeComponent },
+ { path: 'users', component: FakeComponent }
+ ];
+
+ configureTestBed(
+ {
+ imports: [
+ RouterTestingModule.withRoutes(routes),
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ ComponentsModule,
+ ToastrModule.forRoot(),
+ SharedModule
+ ],
+ declarations: [UserFormComponent, FakeComponent],
+ providers: i18nProviders
+ },
+ true
+ );
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserFormComponent);
+ component = fixture.componentInstance;
+ form = component.userForm;
+ httpTesting = TestBed.get(HttpTestingController);
+ userService = TestBed.get(UserService);
+ modalService = TestBed.get(BsModalService);
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate');
+ fixture.detectChanges();
+ const notify = TestBed.get(NotificationService);
+ spyOn(notify, 'show');
+ formHelper = new FormHelper(form);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(form).toBeTruthy();
+ });
+
+ describe('create mode', () => {
+ beforeEach(() => {
+ setUrl('/user-management/users/add');
+ component.ngOnInit();
+ });
+
+ it('should not disable fields', () => {
+ ['username', 'name', 'password', 'confirmpassword', 'email', 'roles'].forEach((key) =>
+ expect(form.get(key).disabled).toBeFalsy()
+ );
+ });
+
+ it('should validate username required', () => {
+ formHelper.expectErrorChange('username', '', 'required');
+ formHelper.expectValidChange('username', 'user1');
+ });
+
+ it('should validate password match', () => {
+ formHelper.setValue('password', 'aaa');
+ formHelper.expectErrorChange('confirmpassword', 'bbb', 'match');
+ formHelper.expectValidChange('confirmpassword', 'aaa');
+ });
+
+ it('should validate email', () => {
+ formHelper.expectErrorChange('email', 'aaa', 'email');
+ });
+
+ it('should set mode', () => {
+ expect(component.mode).toBeUndefined();
+ });
+
+ it('should submit', () => {
+ const user: UserFormModel = {
+ username: 'user0',
+ password: 'pass0',
+ name: 'User 0',
+ email: 'user0@email.com',
+ roles: ['administrator']
+ };
+ formHelper.setMultipleValues(user);
+ formHelper.setValue('confirmpassword', user.password);
+ component.submit();
+ const userReq = httpTesting.expectOne('api/user');
+ expect(userReq.request.method).toBe('POST');
+ expect(userReq.request.body).toEqual(user);
+ userReq.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['/user-management/users']);
+ });
+ });
+
+ describe('edit mode', () => {
+ const user: UserFormModel = {
+ username: 'user1',
+ password: undefined,
+ name: 'User 1',
+ email: 'user1@email.com',
+ roles: ['administrator']
+ };
+ const roles = [
+ {
+ name: 'administrator',
+ description: 'Administrator',
+ scopes_permissions: {
+ user: ['create', 'delete', 'read', 'update']
+ }
+ },
+ {
+ name: 'read-only',
+ description: 'Read-Only',
+ scopes_permissions: {
+ user: ['read']
+ }
+ },
+ {
+ name: 'user-manager',
+ description: 'User Manager',
+ scopes_permissions: {
+ user: ['create', 'delete', 'read', 'update']
+ }
+ }
+ ];
+
+ beforeEach(() => {
+ spyOn(userService, 'get').and.callFake(() => of(user));
+ spyOn(TestBed.get(RoleService), 'list').and.callFake(() => of(roles));
+ setUrl('/user-management/users/edit/user1');
+ component.ngOnInit();
+ const req = httpTesting.expectOne('api/role');
+ expect(req.request.method).toBe('GET');
+ req.flush(roles);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should disable fields if editing', () => {
+ expect(form.get('username').disabled).toBeTruthy();
+ ['name', 'password', 'confirmpassword', 'email', 'roles'].forEach((key) =>
+ expect(form.get(key).disabled).toBeFalsy()
+ );
+ });
+
+ it('should set control values', () => {
+ ['username', 'name', 'email', 'roles'].forEach((key) =>
+ expect(form.getValue(key)).toBe(user[key])
+ );
+ ['password', 'confirmpassword'].forEach((key) => expect(form.getValue(key)).toBeFalsy());
+ });
+
+ it('should set mode', () => {
+ expect(component.mode).toBe('editing');
+ });
+
+ it('should alert if user is removing needed role permission', () => {
+ spyOn(TestBed.get(AuthStorageService), 'getUsername').and.callFake(() => user.username);
+ let modalBodyTpl = null;
+ spyOn(modalService, 'show').and.callFake((_content, config) => {
+ modalBodyTpl = config.initialState.bodyTpl;
+ });
+ formHelper.setValue('roles', ['read-only']);
+ component.submit();
+ expect(modalBodyTpl).toEqual(component.removeSelfUserReadUpdatePermissionTpl);
+ });
+
+ it('should logout if current user roles have been changed', () => {
+ spyOn(TestBed.get(AuthStorageService), 'getUsername').and.callFake(() => user.username);
+ formHelper.setValue('roles', ['user-manager']);
+ component.submit();
+ const userReq = httpTesting.expectOne(`api/user/${user.username}`);
+ expect(userReq.request.method).toBe('PUT');
+ userReq.flush({});
+ const authReq = httpTesting.expectOne('api/auth/logout');
+ expect(authReq.request.method).toBe('POST');
+ });
+
+ it('should submit', () => {
+ spyOn(TestBed.get(AuthStorageService), 'getUsername').and.callFake(() => user.username);
+ component.submit();
+ const userReq = httpTesting.expectOne(`api/user/${user.username}`);
+ expect(userReq.request.method).toBe('PUT');
+ expect(userReq.request.body).toEqual({
+ username: 'user1',
+ password: '',
+ name: 'User 1',
+ email: 'user1@email.com',
+ roles: ['administrator']
+ });
+ userReq.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['/user-management/users']);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts
new file mode 100644
index 00000000..77a8e75c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts
@@ -0,0 +1,234 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { AuthService } from '../../../shared/api/auth.service';
+import { RoleService } from '../../../shared/api/role.service';
+import { UserService } from '../../../shared/api/user.service';
+import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { SelectMessages } from '../../../shared/components/select/select-messages.model';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { UserFormMode } from './user-form-mode.enum';
+import { UserFormRoleModel } from './user-form-role.model';
+import { UserFormModel } from './user-form.model';
+
+@Component({
+ selector: 'cd-user-form',
+ templateUrl: './user-form.component.html',
+ styleUrls: ['./user-form.component.scss']
+})
+export class UserFormComponent implements OnInit {
+ @ViewChild('removeSelfUserReadUpdatePermissionTpl')
+ removeSelfUserReadUpdatePermissionTpl: TemplateRef<any>;
+
+ modalRef: BsModalRef;
+
+ userForm: CdFormGroup;
+ response: UserFormModel;
+
+ userFormMode = UserFormMode;
+ mode: UserFormMode;
+ allRoles: Array<UserFormRoleModel>;
+ messages = new SelectMessages({ empty: 'There are no roles.' }, this.i18n);
+ action: string;
+ resource: string;
+
+ constructor(
+ private authService: AuthService,
+ private authStorageService: AuthStorageService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private modalService: BsModalService,
+ private roleService: RoleService,
+ private userService: UserService,
+ private notificationService: NotificationService,
+ private i18n: I18n,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.resource = this.i18n('user');
+ this.createForm();
+ this.messages = new SelectMessages({ empty: 'There are no roles.' }, this.i18n);
+ }
+
+ createForm() {
+ this.userForm = new CdFormGroup(
+ {
+ username: new FormControl('', {
+ validators: [Validators.required]
+ }),
+ name: new FormControl(''),
+ password: new FormControl('', {
+ validators: []
+ }),
+ confirmpassword: new FormControl('', {
+ updateOn: 'blur',
+ validators: []
+ }),
+ email: new FormControl('', {
+ validators: [Validators.email]
+ }),
+ roles: new FormControl([])
+ },
+ {
+ validators: [CdValidators.match('password', 'confirmpassword')]
+ }
+ );
+ }
+
+ ngOnInit() {
+ if (this.router.url.startsWith('/user-management/users/edit')) {
+ this.mode = this.userFormMode.editing;
+ this.action = this.actionLabels.EDIT;
+ } else {
+ this.action = this.actionLabels.CREATE;
+ }
+
+ this.roleService.list().subscribe((roles: Array<UserFormRoleModel>) => {
+ this.allRoles = _.map(roles, (role) => {
+ role.enabled = true;
+ return role;
+ });
+ });
+ if (this.mode === this.userFormMode.editing) {
+ this.initEdit();
+ }
+ }
+
+ initEdit() {
+ this.disableForEdit();
+ this.route.params.subscribe((params: { username: string }) => {
+ const username = params.username;
+ this.userService.get(username).subscribe((userFormModel: UserFormModel) => {
+ this.response = _.cloneDeep(userFormModel);
+ this.setResponse(userFormModel);
+ });
+ });
+ }
+
+ disableForEdit() {
+ this.userForm.get('username').disable();
+ }
+
+ setResponse(response: UserFormModel) {
+ ['username', 'name', 'email', 'roles'].forEach((key) =>
+ this.userForm.get(key).setValue(response[key])
+ );
+ }
+
+ getRequest(): UserFormModel {
+ const userFormModel = new UserFormModel();
+ ['username', 'password', 'name', 'email', 'roles'].forEach(
+ (key) => (userFormModel[key] = this.userForm.get(key).value)
+ );
+ return userFormModel;
+ }
+
+ createAction() {
+ const userFormModel = this.getRequest();
+ this.userService.create(userFormModel).subscribe(
+ () => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Created user "{{username}}"', { username: userFormModel.username })
+ );
+ this.router.navigate(['/user-management/users']);
+ },
+ () => {
+ this.userForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ editAction() {
+ if (this.isUserRemovingNeededRolePermissions()) {
+ const initialState = {
+ titleText: this.i18n('Update user'),
+ buttonText: this.i18n('Continue'),
+ bodyTpl: this.removeSelfUserReadUpdatePermissionTpl,
+ onSubmit: () => {
+ this.modalRef.hide();
+ this.doEditAction();
+ },
+ onCancel: () => {
+ this.userForm.setErrors({ cdSubmitButton: true });
+ this.userForm.get('roles').reset(this.userForm.get('roles').value);
+ }
+ };
+ this.modalRef = this.modalService.show(ConfirmationModalComponent, { initialState });
+ } else {
+ this.doEditAction();
+ }
+ }
+
+ private isCurrentUser(): boolean {
+ return this.authStorageService.getUsername() === this.userForm.getValue('username');
+ }
+
+ private isUserChangingRoles(): boolean {
+ const isCurrentUser = this.isCurrentUser();
+ return (
+ isCurrentUser &&
+ this.response &&
+ !_.isEqual(this.response.roles, this.userForm.getValue('roles'))
+ );
+ }
+
+ private isUserRemovingNeededRolePermissions(): boolean {
+ const isCurrentUser = this.isCurrentUser();
+ return isCurrentUser && !this.hasUserReadUpdatePermissions(this.userForm.getValue('roles'));
+ }
+
+ private hasUserReadUpdatePermissions(roles: Array<string> = []) {
+ for (const role of this.allRoles) {
+ if (roles.indexOf(role.name) !== -1 && role.scopes_permissions['user']) {
+ const userPermissions = role.scopes_permissions['user'];
+ return ['read', 'update'].every((permission) => {
+ return userPermissions.indexOf(permission) !== -1;
+ });
+ }
+ }
+ return false;
+ }
+
+ private doEditAction() {
+ const userFormModel = this.getRequest();
+ this.userService.update(userFormModel).subscribe(
+ () => {
+ if (this.isUserChangingRoles()) {
+ this.authService.logout(() => {
+ this.notificationService.show(
+ NotificationType.info,
+ this.i18n('You were automatically logged out because your roles have been changed.')
+ );
+ });
+ } else {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Updated user "{{username}}"', { username: userFormModel.username })
+ );
+ this.router.navigate(['/user-management/users']);
+ }
+ },
+ () => {
+ this.userForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ submit() {
+ if (this.mode === this.userFormMode.editing) {
+ this.editAction();
+ } else {
+ this.createAction();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.model.ts
new file mode 100644
index 00000000..cd3b188a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.model.ts
@@ -0,0 +1,7 @@
+export class UserFormModel {
+ username: string;
+ password: string;
+ name: string;
+ email: string;
+ roles: Array<string>;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.html
new file mode 100644
index 00000000..89ed21be
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.html
@@ -0,0 +1,22 @@
+<cd-user-tabs></cd-user-tabs>
+
+<cd-table [data]="users"
+ columnMode="flex"
+ [columns]="columns"
+ identifier="username"
+ selectionType="single"
+ (fetchData)="getUsers()"
+ (updateSelection)="updateSelection($event)">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+</cd-table>
+
+<ng-template #userRolesTpl
+ let-value="value">
+ <span *ngFor="let role of value; last as isLast">
+ {{ role }}{{ !isLast ? ", " : "" }}
+ </span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.spec.ts
new file mode 100644
index 00000000..1a34a2f6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.spec.ts
@@ -0,0 +1,202 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PermissionHelper
+} from '../../../../testing/unit-test-helper';
+import { ActionLabels } from '../../../shared/constants/app.constants';
+import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
+import { SharedModule } from '../../../shared/shared.module';
+import { UserTabsComponent } from '../user-tabs/user-tabs.component';
+import { UserListComponent } from './user-list.component';
+
+describe('UserListComponent', () => {
+ let component: UserListComponent;
+ let fixture: ComponentFixture<UserListComponent>;
+
+ configureTestBed({
+ imports: [
+ SharedModule,
+ ToastrModule.forRoot(),
+ TabsModule.forRoot(),
+ RouterTestingModule,
+ HttpClientTestingModule
+ ],
+ declarations: [UserListComponent, UserTabsComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserListComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('show action buttons and drop down actions depending on permissions', () => {
+ let tableActions: TableActionsComponent;
+ let scenario: { fn; empty; single };
+ let permissionHelper: PermissionHelper;
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ fixture.detectChanges();
+ return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+ };
+
+ beforeEach(() => {
+ permissionHelper = new PermissionHelper(component.permission, () =>
+ getTableActionComponent()
+ );
+ scenario = {
+ fn: () => tableActions.getCurrentButton().name,
+ single: ActionLabels.EDIT,
+ empty: ActionLabels.CREATE
+ };
+ });
+
+ describe('with all', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it('shows all actions', () => {
+ expect(tableActions.tableActions.length).toBe(3);
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ });
+
+ it(`shows 'Edit' for single selection else 'Add' as main action`, () =>
+ permissionHelper.testScenarios(scenario));
+
+ it(`shows 'Add' and 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ component.tableActions.pop();
+ expect(tableActions.tableActions).toEqual(component.tableActions);
+ });
+ });
+
+ describe('with read, create and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ });
+
+ it(`shows 'Delete' for single selection else 'Add' as main action`, () => {
+ scenario.single = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Add' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[0],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read, edit and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = ActionLabels.EDIT;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows 'Edit' and 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(2);
+ expect(tableActions.tableActions).toEqual([
+ component.tableActions[1],
+ component.tableActions[2]
+ ]);
+ });
+ });
+
+ describe('with read and create', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ });
+
+ it(`shows always 'Add' as main action`, () => {
+ scenario.single = ActionLabels.CREATE;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Add' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[0]]);
+ });
+ });
+
+ describe('with read and update', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ });
+
+ it(`shows always 'Edit' as main action`, () => {
+ scenario.empty = 'Edit';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Edit' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[1]]);
+ });
+ });
+
+ describe('with read and delete', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ });
+
+ it(`shows always 'Delete' as main action`, () => {
+ scenario.single = 'Delete';
+ scenario.empty = 'Delete';
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it(`shows only 'Delete' action`, () => {
+ expect(tableActions.tableActions.length).toBe(1);
+ expect(tableActions.tableActions).toEqual([component.tableActions[2]]);
+ });
+ });
+
+ describe('with only read', () => {
+ beforeEach(() => {
+ tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ });
+
+ it('shows no main action', () => {
+ permissionHelper.testScenarios({
+ fn: () => tableActions.getCurrentButton(),
+ single: undefined,
+ empty: undefined
+ });
+ });
+
+ it('shows no actions', () => {
+ expect(tableActions.tableActions.length).toBe(0);
+ expect(tableActions.tableActions).toEqual([]);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.ts
new file mode 100644
index 00000000..77962d42
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-list/user-list.component.ts
@@ -0,0 +1,145 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { UserService } from '../../../shared/api/user.service';
+import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
+import { CdTableColumn } from '../../../shared/models/cd-table-column';
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { EmptyPipe } from '../../../shared/pipes/empty.pipe';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { URLBuilderService } from '../../../shared/services/url-builder.service';
+
+const BASE_URL = 'user-management/users';
+
+@Component({
+ selector: 'cd-user-list',
+ templateUrl: './user-list.component.html',
+ styleUrls: ['./user-list.component.scss'],
+ providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }]
+})
+export class UserListComponent implements OnInit {
+ @ViewChild('userRolesTpl')
+ userRolesTpl: TemplateRef<any>;
+
+ permission: Permission;
+ tableActions: CdTableAction[];
+ columns: CdTableColumn[];
+ users: Array<any>;
+ selection = new CdTableSelection();
+
+ modalRef: BsModalRef;
+
+ constructor(
+ private userService: UserService,
+ private emptyPipe: EmptyPipe,
+ private modalService: BsModalService,
+ private notificationService: NotificationService,
+ private authStorageService: AuthStorageService,
+ private i18n: I18n,
+ private urlBuilder: URLBuilderService,
+ public actionLabels: ActionLabelsI18n
+ ) {
+ this.permission = this.authStorageService.getPermissions().user;
+ const addAction: CdTableAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ routerLink: () => this.urlBuilder.getCreate(),
+ name: this.actionLabels.CREATE
+ };
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () =>
+ this.selection.first() && this.urlBuilder.getEdit(this.selection.first().username),
+ name: this.actionLabels.EDIT
+ };
+ const deleteAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ click: () => this.deleteUserModal(),
+ name: this.actionLabels.DELETE
+ };
+ this.tableActions = [addAction, editAction, deleteAction];
+ }
+
+ ngOnInit() {
+ this.columns = [
+ {
+ name: this.i18n('Username'),
+ prop: 'username',
+ flexGrow: 1
+ },
+ {
+ name: this.i18n('Name'),
+ prop: 'name',
+ flexGrow: 1,
+ pipe: this.emptyPipe
+ },
+ {
+ name: this.i18n('Email'),
+ prop: 'email',
+ flexGrow: 1,
+ pipe: this.emptyPipe
+ },
+ {
+ name: this.i18n('Roles'),
+ prop: 'roles',
+ flexGrow: 1,
+ cellTemplate: this.userRolesTpl
+ }
+ ];
+ }
+
+ getUsers() {
+ this.userService.list().subscribe((users: Array<any>) => {
+ this.users = users;
+ });
+ }
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
+
+ deleteUser(username: string) {
+ this.userService.delete(username).subscribe(
+ () => {
+ this.getUsers();
+ this.modalRef.hide();
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('Deleted user "{{username}}"', { username: username })
+ );
+ },
+ () => {
+ this.modalRef.content.stopLoadingSpinner();
+ }
+ );
+ }
+
+ deleteUserModal() {
+ const sessionUsername = this.authStorageService.getUsername();
+ const username = this.selection.first().username;
+ if (sessionUsername === username) {
+ this.notificationService.show(
+ NotificationType.error,
+ this.i18n('Failed to delete user "{{username}}"', { username: username }),
+ this.i18n('You are currently logged in as "{{username}}".', { username: username })
+ );
+ return;
+ }
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ itemDescription: 'User',
+ itemNames: [username],
+ submitAction: () => this.deleteUser(username)
+ }
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.html
new file mode 100644
index 00000000..b707992a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.html
@@ -0,0 +1,12 @@
+<tabset>
+ <tab heading="Users"
+ i18n-heading
+ [active]="url === '/user-management/users'"
+ (selectTab)="navigateTo('/user-management/users')">
+ </tab>
+ <tab heading="Roles"
+ i18n-heading
+ [active]="url === '/user-management/roles'"
+ (selectTab)="navigateTo('/user-management/roles')">
+ </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.spec.ts
new file mode 100644
index 00000000..d7339514
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.spec.ts
@@ -0,0 +1,29 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { UserTabsComponent } from './user-tabs.component';
+
+describe('UserTabsComponent', () => {
+ let component: UserTabsComponent;
+ let fixture: ComponentFixture<UserTabsComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, TabsModule.forRoot(), RouterTestingModule, HttpClientTestingModule],
+ declarations: [UserTabsComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserTabsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.ts
new file mode 100644
index 00000000..16a3094d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-tabs/user-tabs.component.ts
@@ -0,0 +1,22 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'cd-user-tabs',
+ templateUrl: './user-tabs.component.html',
+ styleUrls: ['./user-tabs.component.scss']
+})
+export class UserTabsComponent implements OnInit {
+ url: string;
+
+ constructor(private router: Router) {}
+
+ ngOnInit() {
+ this.url = this.router.url;
+ }
+
+ navigateTo(url) {
+ this.router.navigate([url]);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/core.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/core.module.ts
new file mode 100644
index 00000000..8d3d67c6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/core.module.ts
@@ -0,0 +1,13 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { ForbiddenComponent } from './forbidden/forbidden.component';
+import { NavigationModule } from './navigation/navigation.module';
+import { NotFoundComponent } from './not-found/not-found.component';
+
+@NgModule({
+ imports: [CommonModule, NavigationModule],
+ exports: [NavigationModule],
+ declarations: [NotFoundComponent, ForbiddenComponent]
+})
+export class CoreModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.html
new file mode 100644
index 00000000..ba06ebe9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.html
@@ -0,0 +1,10 @@
+<div class="row">
+ <div class="col-md-12 text-center">
+ <h1 i18n>Forbidden</h1>
+
+ <i class="fa fa-lock text-danger"></i>
+
+ <h2 i18n>Sorry, you are not allowed to see what you were looking for.</h2>
+
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.scss
new file mode 100644
index 00000000..47a92861
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.scss
@@ -0,0 +1,13 @@
+h1 {
+ font-size: -webkit-xxx-large;
+ font-family: monospace;
+}
+
+h2 {
+ font-size: xx-large;
+ font-family: monospace;
+}
+
+i {
+ font-size: 200px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.spec.ts
new file mode 100644
index 00000000..3ed7d32d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { ForbiddenComponent } from './forbidden.component';
+
+describe('ForbiddenComponent', () => {
+ let component: ForbiddenComponent;
+ let fixture: ComponentFixture<ForbiddenComponent>;
+
+ configureTestBed({
+ declarations: [ForbiddenComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ForbiddenComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.ts
new file mode 100644
index 00000000..8b70d3ee
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/forbidden/forbidden.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'cd-forbidden',
+ templateUrl: './forbidden.component.html',
+ styleUrls: ['./forbidden.component.scss']
+})
+export class ForbiddenComponent {
+ constructor() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.html
new file mode 100644
index 00000000..d76ca939
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.html
@@ -0,0 +1,60 @@
+<div class="modal-header">
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="modalRef.hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+<div class="modal-body">
+ <h2>
+ <img src="assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png"
+ class="ceph-logo"
+ alt="{{ projectConstants.organization }}">
+ {{ projectConstants.organization }}
+ </h2>
+ <h3>
+ <strong>{{ projectConstants.projectName }}</strong>
+ </h3>
+ <div class="product-versions">
+ <strong>Version</strong>
+ <br>
+ {{ versionNumber }}
+ {{ versionHash }}
+ <br>
+ {{ versionName }}
+ </div>
+ <br>
+ <ul class="list-unstyled">
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">Ceph Manager</strong>
+ <span class="col-xs-4 col-sm-4">{{ hostAddr }}</span>
+ </li>
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">User</strong>
+ <span class="col-xs-4 col-sm-4">{{ modalVariables.user }}</span>
+ </li>
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">User Role</strong>
+ <span class="col-xs-4 col-sm-4">{{ modalVariables.role }}</span>
+ </li>
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">Browser</strong>
+ <span class="col-xs-4 col-sm-4">{{ modalVariables.browserName }}</span>
+ </li>
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">Browser Version</strong>
+ <span class="col-xs-4 col-sm-4">{{ modalVariables.browserVersion }}</span>
+ </li>
+ <li class="row">
+ <strong class="col-xs-6 col-sm-4">Browser OS</strong>
+ <span class="col-xs-4 col-sm-4">{{ modalVariables.browserOS }}</span>
+ </li>
+ </ul>
+</div>
+<div class="modal-footer">
+ <div class="text-left">
+ {{ copyright }}
+ {{ projectConstants.license }}
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.scss
new file mode 100644
index 00000000..86f72b55
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.scss
@@ -0,0 +1,36 @@
+.product-versions {
+ margin-top: 30px;
+}
+.product-versions strong {
+ margin-right: 10px;
+}
+.modal-header {
+ border-bottom: none;
+}
+.modal-body {
+ padding-left: 80px;
+ padding-right: 80px;
+}
+.modal-footer {
+ border-top: none;
+}
+h2 {
+ font-size: 3em;
+}
+.ceph-logo {
+ width: 10%;
+}
+.list-unstyled li {
+ margin-top: 5px;
+}
+.modal-footer {
+ padding: 15px 80px 35px 80px;
+}
+.modal-body {
+ margin-top: 0;
+ padding-top: 0;
+
+ h2 {
+ margin-top: 0;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.spec.ts
new file mode 100644
index 00000000..ccb92d13
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.spec.ts
@@ -0,0 +1,55 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { BehaviorSubject } from 'rxjs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { AboutComponent } from './about.component';
+
+export class SummaryServiceMock {
+ summaryDataSource = new BehaviorSubject({
+ version:
+ 'ceph version 14.0.0-855-gb8193bb4cd ' +
+ '(b8193bb4cda16ccc5b028c3e1df62bc72350a15d) nautilus (dev)',
+ mgr_host: 'http://localhost:11000/'
+ });
+ summaryData$ = this.summaryDataSource.asObservable();
+
+ subscribe(call) {
+ return this.summaryData$.subscribe(call);
+ }
+}
+
+describe('AboutComponent', () => {
+ let component: AboutComponent;
+ let fixture: ComponentFixture<AboutComponent>;
+
+ configureTestBed({
+ imports: [SharedModule, HttpClientTestingModule],
+ declarations: [AboutComponent],
+ providers: [BsModalRef, { provide: SummaryService, useClass: SummaryServiceMock }]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AboutComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should parse version', () => {
+ expect(component.versionNumber).toBe('14.0.0-855-gb8193bb4cd');
+ expect(component.versionHash).toBe('(b8193bb4cda16ccc5b028c3e1df62bc72350a15d)');
+ expect(component.versionName).toBe('nautilus (dev)');
+ });
+
+ it('should get host', () => {
+ expect(component.hostAddr).toBe('localhost:11000');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.ts
new file mode 100644
index 00000000..c22507ee
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/about/about.component.ts
@@ -0,0 +1,74 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+
+import { detect } from 'detect-browser';
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { Subscription } from 'rxjs';
+import { environment } from '../../../../environments/environment';
+import { UserService } from '../../../shared/api/user.service';
+import { AppConstants } from '../../../shared/constants/app.constants';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+
+@Component({
+ selector: 'cd-about',
+ templateUrl: './about.component.html',
+ styleUrls: ['./about.component.scss']
+})
+export class AboutComponent implements OnInit, OnDestroy {
+ modalVariables: any;
+ versionNumber: string;
+ versionHash: string;
+ versionName: string;
+ subs: Subscription;
+ userPermission: Permission;
+ projectConstants: typeof AppConstants;
+ hostAddr: string;
+ copyright: string;
+
+ constructor(
+ public modalRef: BsModalRef,
+ private summaryService: SummaryService,
+ private userService: UserService,
+ private authStorageService: AuthStorageService
+ ) {
+ this.userPermission = this.authStorageService.getPermissions().user;
+ }
+
+ ngOnInit() {
+ this.copyright = 'Copyright(c) ' + environment.year + ' Ceph contributors.';
+ this.projectConstants = AppConstants;
+ this.hostAddr = window.location.hostname;
+ this.modalVariables = this.setVariables();
+ this.subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+ const version = summary.version.replace('ceph version ', '').split(' ');
+ this.hostAddr = summary.mgr_host.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, '');
+ this.versionNumber = version[0];
+ this.versionHash = version[1];
+ this.versionName = version.slice(2, version.length).join(' ');
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ setVariables() {
+ const project = {} as any;
+ project.user = localStorage.getItem('dashboard_username');
+ project.role = 'user';
+ if (this.userPermission.read) {
+ this.userService.get(project.user).subscribe((data: any) => {
+ project.role = data.roles;
+ });
+ }
+ const browser = detect();
+ project.browserName = browser && browser.name ? browser.name : 'Not detected';
+ project.browserVersion = browser && browser.version ? browser.version : 'Not detected';
+ project.browserOS = browser && browser.os ? browser.os : 'Not detected';
+ return project;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.html
new file mode 100644
index 00000000..1dd55556
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.html
@@ -0,0 +1,21 @@
+<div dropdown
+ *ngIf="userPermission.read">
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown"
+ i18n-title
+ title="Dashboard Settings">
+ <i class="fa fa-fw fa-cog"></i>
+ <span i18n
+ class="visible-xs-inline-block">Dashboard Settings</span>
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu dropdown-menu-right">
+ <li *ngIf="userPermission.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/user-management">User management</a>
+ </li>
+ </ul>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.spec.ts
new file mode 100644
index 00000000..ae695068
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { AdministrationComponent } from './administration.component';
+
+describe('AdministrationComponent', () => {
+ let component: AdministrationComponent;
+ let fixture: ComponentFixture<AdministrationComponent>;
+
+ configureTestBed({
+ imports: [SharedModule],
+ declarations: [AdministrationComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AdministrationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.ts
new file mode 100644
index 00000000..eacef898
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/administration/administration.component.ts
@@ -0,0 +1,19 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-administration',
+ templateUrl: './administration.component.html',
+ styleUrls: ['./administration.component.scss']
+})
+export class AdministrationComponent implements OnInit {
+ userPermission: Permission;
+
+ constructor(private authStorageService: AuthStorageService) {
+ this.userPermission = this.authStorageService.getPermissions().user;
+ }
+
+ ngOnInit() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html
new file mode 100644
index 00000000..cca56a32
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.html
@@ -0,0 +1,11 @@
+<ol *ngIf="crumbs.length"
+ class="breadcrumb">
+ <li *ngFor="let crumb of crumbs; let last = last"
+ [ngClass]="{ 'active': last }"
+ class="breadcrumb-item">
+ <a *ngIf="!last && crumb.path !== null"
+ [routerLink]="crumb.path"
+ preserveFragment>{{ crumb.text }}</a>
+ <span *ngIf="last || crumb.path === null">{{ crumb.text }}</span>
+ </li>
+</ol>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.scss
new file mode 100644
index 00000000..a8dbf5ef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.scss
@@ -0,0 +1,18 @@
+@import '../../../../defaults';
+
+.breadcrumb {
+ padding: 8px 0;
+ background-color: transparent;
+ border-radius: 0;
+}
+
+.breadcrumb > li + li:before {
+ padding: 0 5px 0 7px;
+ color: $color-breadcrumb;
+ font-family: 'ForkAwesome';
+ content: '\f101';
+}
+
+.breadcrumb > li > span {
+ color: $color-breadcrumb;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.spec.ts
new file mode 100644
index 00000000..f593d268
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.spec.ts
@@ -0,0 +1,131 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { PerformanceCounterBreadcrumbsResolver } from '../../../app-routing.module';
+import { BreadcrumbsComponent } from './breadcrumbs.component';
+
+describe('BreadcrumbsComponent', () => {
+ let component: BreadcrumbsComponent;
+ let fixture: ComponentFixture<BreadcrumbsComponent>;
+ let router: Router;
+
+ @Component({ selector: 'cd-fake', template: '' })
+ class FakeComponent {}
+
+ const routes: Routes = [
+ {
+ path: 'hosts',
+ component: FakeComponent,
+ data: { breadcrumbs: 'Cluster/Hosts' }
+ },
+ {
+ path: 'perf_counters',
+ component: FakeComponent,
+ data: {
+ breadcrumbs: PerformanceCounterBreadcrumbsResolver
+ }
+ },
+ {
+ path: 'block',
+ data: { breadcrumbs: true, text: 'Block', path: null },
+ children: [
+ {
+ path: 'rbd',
+ data: { breadcrumbs: 'Images' },
+ children: [
+ { path: '', component: FakeComponent },
+ { path: 'add', component: FakeComponent, data: { breadcrumbs: 'Add' } }
+ ]
+ }
+ ]
+ }
+ ];
+
+ configureTestBed({
+ declarations: [BreadcrumbsComponent, FakeComponent],
+ imports: [CommonModule, RouterTestingModule.withRoutes(routes)],
+ providers: [PerformanceCounterBreadcrumbsResolver]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BreadcrumbsComponent);
+ router = TestBed.get(Router);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ expect(component.crumbs).toEqual([]);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(component.subscription).toBeDefined();
+ });
+
+ it('should run postProcess and split the breadcrumbs when navigating to hosts', fakeAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigateByUrl('/hosts');
+ });
+ tick();
+ expect(component.crumbs).toEqual([
+ { path: null, text: 'Cluster' },
+ { path: '/hosts', text: 'Hosts' }
+ ]);
+ }));
+
+ it('should display empty breadcrumb when navigating to perf_counters from unknown path', fakeAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigateByUrl('/perf_counters');
+ });
+ tick();
+ expect(component.crumbs).toEqual([
+ { path: null, text: 'Cluster' },
+ { path: null, text: '' },
+ { path: '', text: 'Performance Counters' }
+ ]);
+ }));
+
+ it('should display Monitor breadcrumb when navigating to perf_counters from Monitors', fakeAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigate(['/perf_counters'], { queryParams: { fromLink: '/monitor' } });
+ });
+ tick();
+ expect(component.crumbs).toEqual([
+ { path: null, text: 'Cluster' },
+ { path: '/monitor', text: 'Monitors' },
+ { path: '', text: 'Performance Counters' }
+ ]);
+ }));
+
+ it('should display Hosts breadcrumb when navigating to perf_counters from Hosts', fakeAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigate(['/perf_counters'], { queryParams: { fromLink: '/hosts' } });
+ });
+ tick();
+ expect(component.crumbs).toEqual([
+ { path: null, text: 'Cluster' },
+ { path: '/hosts', text: 'Hosts' },
+ { path: '', text: 'Performance Counters' }
+ ]);
+ }));
+
+ it('should show all 3 breadcrumbs when navigating to RBD Add', fakeAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigateByUrl('/block/rbd/add');
+ });
+ tick();
+ expect(component.crumbs).toEqual([
+ { path: null, text: 'Block' },
+ { path: '/block/rbd', text: 'Images' },
+ { path: '/block/rbd/add', text: 'Add' }
+ ]);
+ }));
+
+ it('should unsubscribe on ngOnDestroy', () => {
+ expect(component.subscription.closed).toBeFalsy();
+ component.ngOnDestroy();
+ expect(component.subscription.closed).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.ts
new file mode 100644
index 00000000..f7b9d8af
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/breadcrumbs/breadcrumbs.component.ts
@@ -0,0 +1,126 @@
+/*
+The MIT License
+
+Copyright (c) 2017 (null) McNull https://github.com/McNull
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+import { Component, Injector, OnDestroy } from '@angular/core';
+import { ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router';
+
+import { from, Observable, of, Subscription } from 'rxjs';
+import { concat, distinct, filter, first, flatMap, toArray } from 'rxjs/operators';
+
+import { BreadcrumbsResolver, IBreadcrumb } from '../../../shared/models/breadcrumbs';
+
+@Component({
+ selector: 'cd-breadcrumbs',
+ templateUrl: './breadcrumbs.component.html',
+ styleUrls: ['./breadcrumbs.component.scss']
+})
+export class BreadcrumbsComponent implements OnDestroy {
+ crumbs: IBreadcrumb[] = [];
+ subscription: Subscription;
+ private defaultResolver = new BreadcrumbsResolver();
+
+ constructor(private router: Router, private injector: Injector) {
+ this.subscription = this.router.events
+ .pipe(filter((x) => x instanceof NavigationEnd))
+ .subscribe(() => {
+ const currentRoot = router.routerState.snapshot.root;
+
+ this._resolveCrumbs(currentRoot)
+ .pipe(
+ flatMap((x) => x),
+ distinct((x) => x.text),
+ toArray(),
+ flatMap((x) => {
+ const y = this.postProcess(x);
+ return this.wrapIntoObservable<IBreadcrumb[]>(y).pipe(first());
+ })
+ )
+ .subscribe((x) => {
+ this.crumbs = x;
+ });
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.subscription.unsubscribe();
+ }
+
+ private _resolveCrumbs(route: ActivatedRouteSnapshot): Observable<IBreadcrumb[]> {
+ let crumbs$: Observable<IBreadcrumb[]>;
+
+ const data = route.routeConfig && route.routeConfig.data;
+
+ if (data && data.breadcrumbs) {
+ let resolver: BreadcrumbsResolver;
+
+ if (data.breadcrumbs.prototype instanceof BreadcrumbsResolver) {
+ resolver = this.injector.get(data.breadcrumbs);
+ } else {
+ resolver = this.defaultResolver;
+ }
+
+ const result = resolver.resolve(route);
+ crumbs$ = this.wrapIntoObservable<IBreadcrumb[]>(result).pipe(first());
+ } else {
+ crumbs$ = of([]);
+ }
+
+ if (route.firstChild) {
+ crumbs$ = crumbs$.pipe(concat(this._resolveCrumbs(route.firstChild)));
+ }
+
+ return crumbs$;
+ }
+
+ postProcess(breadcrumbs: IBreadcrumb[]) {
+ const result = [];
+ breadcrumbs.forEach((element) => {
+ const split = element.text.split('/');
+ if (split.length > 1) {
+ element.text = split[split.length - 1];
+ for (let i = 0; i < split.length - 1; i++) {
+ result.push({ text: split[i], path: null });
+ }
+ }
+ result.push(element);
+ });
+ return result;
+ }
+
+ isPromise(value: any): boolean {
+ return value && typeof value.then === 'function';
+ }
+
+ wrapIntoObservable<T>(value: T | Promise<T> | Observable<T>): Observable<T> {
+ if (value instanceof Observable) {
+ return value;
+ }
+
+ if (this.isPromise(value)) {
+ return from(Promise.resolve(value));
+ }
+
+ return of(value as T);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.html
new file mode 100644
index 00000000..02c7ad9c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.html
@@ -0,0 +1,36 @@
+<form #docsForm action="/docs" target="_blank" method="post">
+ <input type="hidden" name="token"/>
+</form>
+
+<div dropdown>
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown"
+ i18n-title
+ title="Help">
+ <i class="fa fa-fw fa-question-circle-o"></i>
+ <span i18n
+ class="visible-xs-inline-block">Help</span>
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu dropdown-menu-right">
+ <li>
+ <a i18n
+ class="dropdown-item"
+ [ngClass]="{'disabled': !docsUrl}"
+ href="{{ docsUrl }}"
+ target="_blank">Documentation</a>
+ </li>
+ <li>
+ <a i18n
+ class="dropdown-item"
+ (click)="goToApiDocs()">API</a>
+ </li>
+ <li>
+ <a i18n
+ class="dropdown-item"
+ (click)="openAboutModal()">About</a>
+ </li>
+ </ul>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.spec.ts
new file mode 100644
index 00000000..e6a61bba
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.spec.ts
@@ -0,0 +1,27 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { DashboardHelpComponent } from './dashboard-help.component';
+
+describe('DashboardHelpComponent', () => {
+ let component: DashboardHelpComponent;
+ let fixture: ComponentFixture<DashboardHelpComponent>;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule, SharedModule, RouterTestingModule],
+ declarations: [DashboardHelpComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DashboardHelpComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.ts
new file mode 100644
index 00000000..366522c3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/dashboard-help/dashboard-help.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+
+import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { AboutComponent } from '../about/about.component';
+
+@Component({
+ selector: 'cd-dashboard-help',
+ templateUrl: './dashboard-help.component.html',
+ styleUrls: ['./dashboard-help.component.scss']
+})
+export class DashboardHelpComponent implements OnInit {
+ @ViewChild('docsForm')
+ docsFormElement;
+ docsUrl: string;
+ modalRef: BsModalRef;
+
+ constructor(
+ private summaryService: SummaryService,
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private modalService: BsModalService
+ ) {}
+
+ ngOnInit() {
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+ }
+
+ openAboutModal() {
+ this.modalRef = this.modalService.show(AboutComponent);
+ }
+
+ goToApiDocs() {
+ this.docsFormElement.nativeElement.submit();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.html
new file mode 100644
index 00000000..ad62aaf3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.html
@@ -0,0 +1,31 @@
+<div dropdown>
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown"
+ i18n-title
+ title="Logged in user">
+ <i class="fa fa-fw fa-user"></i>
+ <span i18n
+ class="visible-xs-inline-block">Logged in user</span>
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu dropdown-menu-right"
+ role="menu">
+ <li class="disabled"
+ role="menuitem">
+ <a i18n
+ class="dropdown-item disabled"
+ href="#">Signed in as
+ <strong>{{ username }}</strong></a>
+ </li>
+ <li class="divider dropdown-divider"></li>
+ <li role="menuitem">
+ <a class="dropdown-item"
+ (click)="logout()">
+ <i class="fa fa-sign-out fa-fw"></i>
+ <span i18n>Sign out</span>
+ </a>
+ </li>
+ </ul>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.spec.ts
new file mode 100644
index 00000000..17f0ac0b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.spec.ts
@@ -0,0 +1,27 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { IdentityComponent } from './identity.component';
+
+describe('IdentityComponent', () => {
+ let component: IdentityComponent;
+ let fixture: ComponentFixture<IdentityComponent>;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule, SharedModule, RouterTestingModule],
+ declarations: [IdentityComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IdentityComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.ts
new file mode 100644
index 00000000..ccc31cd2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/identity/identity.component.ts
@@ -0,0 +1,23 @@
+import { Component, OnInit } from '@angular/core';
+
+import { AuthService } from '../../../shared/api/auth.service';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+ selector: 'cd-identity',
+ templateUrl: './identity.component.html',
+ styleUrls: ['./identity.component.scss']
+})
+export class IdentityComponent implements OnInit {
+ username: string;
+
+ constructor(private authStorageService: AuthStorageService, private authService: AuthService) {}
+
+ ngOnInit() {
+ this.username = this.authStorageService.getUsername();
+ }
+
+ logout() {
+ this.authService.logout();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation.module.ts
new file mode 100644
index 00000000..08a5148d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation.module.ts
@@ -0,0 +1,47 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+import { CollapseModule } from 'ngx-bootstrap/collapse';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { AppRoutingModule } from '../../app-routing.module';
+import { SharedModule } from '../../shared/shared.module';
+import { AuthModule } from '../auth/auth.module';
+import { AboutComponent } from './about/about.component';
+import { AdministrationComponent } from './administration/administration.component';
+import { BreadcrumbsComponent } from './breadcrumbs/breadcrumbs.component';
+import { DashboardHelpComponent } from './dashboard-help/dashboard-help.component';
+import { IdentityComponent } from './identity/identity.component';
+import { NavigationComponent } from './navigation/navigation.component';
+import { NotificationsComponent } from './notifications/notifications.component';
+import { TaskManagerComponent } from './task-manager/task-manager.component';
+
+@NgModule({
+ entryComponents: [AboutComponent],
+ imports: [
+ CommonModule,
+ AuthModule,
+ CollapseModule.forRoot(),
+ BsDropdownModule.forRoot(),
+ PopoverModule.forRoot(),
+ TooltipModule.forRoot(),
+ AppRoutingModule,
+ SharedModule,
+ RouterModule
+ ],
+ declarations: [
+ AboutComponent,
+ BreadcrumbsComponent,
+ NavigationComponent,
+ NotificationsComponent,
+ TaskManagerComponent,
+ DashboardHelpComponent,
+ AdministrationComponent,
+ IdentityComponent
+ ],
+ exports: [NavigationComponent, BreadcrumbsComponent]
+})
+export class NavigationModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html
new file mode 100644
index 00000000..62331bb9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html
@@ -0,0 +1,241 @@
+<nav class="navbar navbar-default navbar-main">
+ <!-- Brand and toggle get grouped for better mobile display -->
+
+ <div class="navbar-header tc_logo_component">
+ <a class="navbar-brand"
+ href="#">
+ <img src="assets/Ceph_Logo_Standard_RGB_White_120411_fa.png"
+ alt="Ceph">
+ </a>
+
+ <button type="button"
+ class="navbar-toggle collapsed"
+ (click)="isCollapsed = !isCollapsed">
+ <span i18n
+ class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div *ngIf="enabledFeature$ | async as enabledFeature"
+ class="collapse navbar-collapse"
+ id="bs-example-navbar-collapse-1"
+ [collapse]="isCollapsed">
+ <ul class="nav navbar-nav navbar-primary">
+
+ <!-- Dashboard -->
+ <li routerLinkActive="active"
+ class="tc_menuitem tc_menuitem_dashboard">
+ <a routerLink="/dashboard">
+ <i class="fa fa-heartbeat fa-fw"
+ [ngStyle]="summaryData?.health_status | healthColor"></i>
+ <span i18n>Dashboard</span>
+ </a>
+ </li>
+
+ <!-- Cluster -->
+ <li dropdown
+ routerLinkActive="active"
+ class="dropdown tc_menuitem tc_menuitem_cluster"
+ *ngIf="permissions.hosts.read || permissions.monitor.read || permissions.osd.read || permissions.configOpt.read">
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown">
+ <ng-container i18n>Cluster</ng-container>
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu">
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_hosts"
+ *ngIf="permissions.hosts.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/hosts">Hosts</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_cluster_monitor"
+ *ngIf="permissions.monitor.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/monitor/">Monitors</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_hosts"
+ *ngIf="permissions.osd.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/osd">OSDs</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_configuration"
+ *ngIf="permissions.configOpt.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/configuration">Configuration</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_crush"
+ *ngIf="permissions.hosts.read && permissions.osd.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/crush-map">CRUSH map</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_modules"
+ *ngIf="permissions.configOpt.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/mgr-modules">Manager modules</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_log"
+ *ngIf="permissions.log.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/logs">Logs</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_monitoring"
+ *ngIf="(isAlertmanagerConfigured || isPrometheusConfigured) && permissions.prometheus.read">
+ <a routerLink="/monitoring">
+ <ng-container i18n>Monitoring</ng-container>
+ <small *ngIf="prometheusAlertService.alerts.length > 0"
+ class="badge badge-danger">{{ prometheusAlertService.alerts.length }}</small>
+ </a>
+ </li>
+ </ul>
+ </li>
+
+ <!-- Pools -->
+ <li routerLinkActive="active"
+ class="tc_menuitem tc_menuitem_pool"
+ *ngIf="permissions.pool.read">
+ <a i18n
+ routerLink="/pool">Pools</a>
+ </li>
+
+ <!-- Block -->
+ <li dropdown
+ routerLinkActive="active"
+ class="dropdown tc_menuitem tc_menuitem_block"
+ *ngIf="
+ (enabledFeature.rbd || enabledFeature.mirroring || enabledFeature.iscsi) &&
+ (permissions.rbdImage.read || permissions.rbdMirroring.read || permissions.iscsi.read)">
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown"
+ [ngStyle]="blockHealthColor()">
+ <ng-container i18n>Block</ng-container>
+ <span class="caret"></span>
+ </a>
+
+ <ul class="dropdown-menu">
+ <li routerLinkActive="active"
+ *ngIf="enabledFeature.rbd && permissions.rbdImage.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/block/rbd">Images</a>
+ </li>
+
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_block_mirroring"
+ *ngIf="enabledFeature.mirroring && permissions.rbdMirroring.read">
+ <a class="dropdown-item"
+ routerLink="/block/mirroring">
+ <ng-container i18n>Mirroring</ng-container>
+ <small *ngIf="summaryData?.rbd_mirroring?.warnings !== 0"
+ class="label label-warning">{{ summaryData?.rbd_mirroring?.warnings }}</small>
+ <small *ngIf="summaryData?.rbd_mirroring?.errors !== 0"
+ class="label label-danger">{{ summaryData?.rbd_mirroring?.errors }}</small>
+ </a>
+ </li>
+
+ <li routerLinkActive="active"
+ *ngIf="enabledFeature.iscsi && permissions.iscsi.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/block/iscsi">iSCSI</a>
+ </li>
+ </ul>
+ </li>
+
+ <!-- NFS -->
+ <li routerLinkActive="active"
+ class="tc_menuitem tc_menuitem_nfs"
+ *ngIf="permissions?.nfs?.read">
+ <a i18n
+ routerLink="/nfs">NFS</a>
+ </li>
+
+ <!-- Filesystem -->
+ <li routerLinkActive="active"
+ class="tc_menuitem tc_menuitem_cephs"
+ *ngIf="enabledFeature.cephfs && permissions.cephfs.read">
+ <a i18n
+ routerLink="/cephfs">Filesystems</a>
+ </li>
+
+ <!-- Object Gateway -->
+ <li dropdown
+ routerLinkActive="active"
+ class="dropdown tc_menuitem tc_menuitem_rgw"
+ *ngIf="enabledFeature.rgw && permissions.rgw.read">
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown">
+ <ng-container i18n>Object Gateway</ng-container>
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu">
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_rgw_daemons">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/rgw/daemon">Daemons</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_rgw_users">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/rgw/user">Users</a>
+ </li>
+ <li routerLinkActive="active"
+ class="tc_submenuitem tc_submenuitem_rgw_buckets">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/rgw/bucket">Buckets</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ <!-- /.navbar-primary -->
+
+ <ul class="nav navbar-nav navbar-utility">
+ <li>
+ <cd-language-selector class="oa-navbar"></cd-language-selector>
+ </li>
+ <li>
+ <cd-task-manager class="oa-navbar"></cd-task-manager>
+ </li>
+ <li>
+ <cd-notifications class="oa-navbar"></cd-notifications>
+ </li>
+ <li>
+ <cd-dashboard-help class="oa-navbar"></cd-dashboard-help>
+ </li>
+ <li>
+ <cd-administration class="oa-navbar"></cd-administration>
+ </li>
+ <li>
+ <cd-identity class="oa-navbar"></cd-identity>
+ </li>
+ </ul>
+ <!-- /.navbar-utility -->
+ </div>
+ <!-- /.navbar-collapse -->
+</nav>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss
new file mode 100644
index 00000000..fcb4b0b5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss
@@ -0,0 +1,210 @@
+@import '../../../../defaults';
+
+/* Navbar */
+::ng-deep .navbar-main {
+ margin-bottom: 0;
+ background: $color-navbar-bg;
+ border: 0;
+ border-radius: 0;
+ border-top: 4px solid $color-nav-top-bar;
+ font-size: 1.2em;
+
+ .navbar-header {
+ display: flex;
+ float: none;
+ }
+
+ .navbar-brand,
+ .navbar-brand:hover {
+ color: $color-navbar-brand;
+ height: auto;
+ margin: 15px 0 15px 20px;
+ padding: 0;
+ -webkit-align-self: flex-start;
+ align-self: flex-start;
+ }
+
+ .navbar-brand > img {
+ height: 25px;
+ }
+
+ .navbar-toggle {
+ margin-left: auto;
+ border: 0;
+ }
+
+ .navbar-toggle:focus,
+ .navbar-toggle:hover {
+ background-color: transparent;
+ outline: 0;
+ }
+
+ .navbar-toggle .icon-bar {
+ background-color: $color-nav-toggle-bar;
+ }
+
+ .navbar-toggle:focus .icon-bar,
+ .navbar-toggle:hover .icon-bar {
+ -webkit-box-shadow: 0 0 3px $color-nav-toggle-shadow;
+ box-shadow: 0 0 3px $color-nav-toggle-shadow;
+ }
+
+ .navbar-collapse {
+ padding: 0;
+ }
+
+ .navbar-nav > li > .oa-navbar > [dropdown] > ul > li > .dropdown-item {
+ font-size: 12px;
+ }
+
+ .navbar-nav > li > .oa-navbar > [dropdown] > a,
+ .navbar-nav > li > .oa-navbar > a,
+ .navbar-nav > li > a {
+ color: $color-nav-links;
+ line-height: 1;
+ padding: 10px 18px;
+ position: relative;
+ display: block;
+ text-decoration: none;
+ }
+
+ .navbar-nav > li > .oa-navbar > [dropdown] > a:focus,
+ .navbar-nav > li > .oa-navbar > [dropdown] > a:hover,
+ .navbar-nav > li > .oa-navbar > a:focus,
+ .navbar-nav > li > .oa-navbar > a:hover,
+ .navbar-nav > li > a:focus,
+ .navbar-nav > li > a:hover {
+ color: $color-nav-links;
+ }
+
+ .navbar-nav > li > .oa-navbar > [dropdown] > a:hover,
+ .navbar-nav > li > .oa-navbar > [dropdown].open > a,
+ .navbar-nav > li > .oa-navbar > a:hover,
+ .navbar-nav > li > a:hover {
+ background-color: $color-nav-links-hover;
+ }
+
+ .navbar-nav > li a.dropdown-toggle span.caret {
+ margin-left: 5px;
+ }
+
+ .navbar-nav > .open > .oa-navbar > [dropdown] > a,
+ .navbar-nav > .open > .oa-navbar > [dropdown] > a:hover,
+ .navbar-nav > .open > .oa-navbar > a,
+ .navbar-nav > .open > .oa-navbar > a:focus,
+ .navbar-nav > .open > .oa-navbar > a:hover,
+ .navbar-nav > .open > .oa-navbar > li > a:focus,
+ .navbar-nav > .open > a,
+ .navbar-nav > .open > a:focus,
+ .navbar-nav > .open > a:hover {
+ color: $color-nav-links;
+ border-color: transparent;
+ background-color: transparent;
+ }
+
+ .navbar-primary > li > a {
+ border: 0;
+ }
+
+ .navbar-primary > .active > a,
+ .navbar-primary > .active > a:focus,
+ .navbar-primary > .active > a:hover {
+ color: $color-nav-links;
+ background-color: $color-nav-links-hover;
+ border: 0;
+ }
+
+ .navbar-utility .fa,
+ .navbar-utility a {
+ font-size: 1.1em;
+ }
+
+ .navbar-utility > .active > a {
+ color: $color-nav-links;
+ background-color: $color-nav-links-hover;
+ }
+
+ .navbar-utility > li > .open > a,
+ .navbar-utility > li > .open > a:focus,
+ .navbar-utility > li > .open > a:hover {
+ color: $color-nav-links;
+ border-color: transparent;
+ background-color: transparent;
+ }
+ @media (min-width: $screen-sm-min) {
+ .navbar-primary > li > a {
+ border-bottom: 4px solid transparent;
+ }
+
+ .navbar-primary > .active > a,
+ .navbar-primary > .active > a:focus,
+ .navbar-primary > .active > a:hover {
+ background-color: transparent;
+ border-bottom: 4px solid $color-nav-bottom-bar;
+ }
+
+ .navbar-utility {
+ border-bottom: 0;
+ font-size: 11px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
+ @media (max-width: $screen-xs-max) {
+ .navbar-nav {
+ margin: 0;
+
+ .fa {
+ margin-right: 0.5em;
+ }
+ }
+
+ .navbar-collapse,
+ .navbar-form {
+ border-color: $color-nav-collapse-border;
+ }
+
+ .navbar-collapse {
+ padding: 0;
+ }
+
+ .navbar-nav .open .dropdown-menu {
+ padding-top: 0;
+ padding-bottom: 0;
+ background-color: $color-nav-open-bg;
+ }
+
+ .navbar-nav .open .dropdown-menu .dropdown-header,
+ .navbar-nav .open .dropdown-menu > li > a {
+ padding: 5px 15px 5px 35px;
+ }
+
+ .navbar-nav .open .dropdown-menu > li > a {
+ color: $color-nav-links;
+ }
+
+ .navbar-nav .open .dropdown-menu > .active > a {
+ color: $color-nav-links;
+ background-color: $color-nav-active-link-bg;
+ }
+
+ .navbar-nav > li > a:hover {
+ background-color: $color-nav-active-link-bg;
+ }
+
+ .navbar-utility {
+ border-top: 1px solid $color-nav-border-top-collapse;
+
+ a {
+ font-size: 1em;
+ }
+ }
+
+ .navbar-primary > .active > a,
+ .navbar-primary > .active > a:focus,
+ .navbar-primary > .active > a:hover {
+ background-color: $color-nav-active-link-bg;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts
new file mode 100644
index 00000000..8e1662f4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts
@@ -0,0 +1,47 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { AppModule } from '../../../app.module';
+import { PrometheusService } from '../../../shared/api/prometheus.service';
+import { Permissions } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NavigationComponent } from './navigation.component';
+
+describe('NavigationComponent', () => {
+ let component: NavigationComponent;
+ let fixture: ComponentFixture<NavigationComponent>;
+ let ifAlertmanagerConfiguredSpy: jasmine.Spy;
+
+ configureTestBed({
+ imports: [AppModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ ifAlertmanagerConfiguredSpy = spyOn(
+ TestBed.get(PrometheusService),
+ 'ifAlertmanagerConfigured'
+ ).and.stub();
+ fixture = TestBed.createComponent(NavigationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create and PrometheusService methods should not have been called', () => {
+ expect(component).toBeTruthy();
+ expect(ifAlertmanagerConfiguredSpy).toHaveBeenCalledTimes(0);
+ });
+
+ it('PrometheusService methods should have been called', () => {
+ const authStorageServiceSpy = spyOn(
+ TestBed.get(AuthStorageService),
+ 'getPermissions'
+ ).and.returnValue(new Permissions({ 'config-opt': ['read'] }));
+ TestBed.overrideProvider(AuthStorageService, { useValue: authStorageServiceSpy });
+ fixture = TestBed.createComponent(NavigationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+
+ expect(ifAlertmanagerConfiguredSpy).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts
new file mode 100644
index 00000000..efd87da1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts
@@ -0,0 +1,64 @@
+import { Component, OnInit } from '@angular/core';
+
+import { PrometheusService } from '../../../shared/api/prometheus.service';
+import { Permissions } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import {
+ FeatureTogglesMap$,
+ FeatureTogglesService
+} from '../../../shared/services/feature-toggles.service';
+import { PrometheusAlertService } from '../../../shared/services/prometheus-alert.service';
+import { SummaryService } from '../../../shared/services/summary.service';
+
+@Component({
+ selector: 'cd-navigation',
+ templateUrl: './navigation.component.html',
+ styleUrls: ['./navigation.component.scss']
+})
+export class NavigationComponent implements OnInit {
+ permissions: Permissions;
+ summaryData: any;
+
+ isCollapsed = true;
+ isAlertmanagerConfigured = false;
+ isPrometheusConfigured = false;
+ enabledFeature$: FeatureTogglesMap$;
+
+ constructor(
+ private authStorageService: AuthStorageService,
+ private prometheusService: PrometheusService,
+ private summaryService: SummaryService,
+ private featureToggles: FeatureTogglesService,
+ public prometheusAlertService: PrometheusAlertService
+ ) {
+ this.permissions = this.authStorageService.getPermissions();
+ this.enabledFeature$ = this.featureToggles.get();
+ }
+
+ ngOnInit() {
+ this.summaryService.subscribe((data: any) => {
+ if (!data) {
+ return;
+ }
+ this.summaryData = data;
+ });
+ if (this.permissions.configOpt.read) {
+ this.prometheusService.ifAlertmanagerConfigured(() => {
+ this.isAlertmanagerConfigured = true;
+ });
+ this.prometheusService.ifPrometheusConfigured(() => {
+ this.isPrometheusConfigured = true;
+ });
+ }
+ }
+
+ blockHealthColor() {
+ if (this.summaryData && this.summaryData.rbd_mirroring) {
+ if (this.summaryData.rbd_mirroring.errors > 0) {
+ return { color: '#d9534f' };
+ } else if (this.summaryData.rbd_mirroring.warnings > 0) {
+ return { color: '#f0ad4e' };
+ }
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.html
new file mode 100644
index 00000000..9e73409d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.html
@@ -0,0 +1,57 @@
+<ng-template #notificationsTpl>
+ <div *ngIf="notifications.length > 0">
+ <button type="button" class="btn btn-default btn-sm btn-block" (click)="removeAll()">
+ <i class="fa fa-trash-o" aria-hidden="true"></i>
+ &nbsp;
+ <ng-container i18n>Remove all</ng-container>
+ </button>
+ <hr>
+ <div *ngFor="let notification of notifications">
+ <table>
+ <tr>
+ <td rowspan="3" class="icon-col text-center">
+ <span [ngClass]="['fa-stack fa-2x', notification.textClass]">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i [ngClass]="['fa fa-stack-1x fa-inverse', notification.iconClass]"></i>
+ </span>
+ </td>
+ <td>
+ <strong>{{ notification.title }}</strong>
+ </td>
+ </tr>
+ <tr>
+ <td [innerHtml]="notification.message">
+ </td>
+ </tr>
+ <tr>
+ <td [innerHtml]="notificationService.renderTimeAndApplicationHtml(notification)"></td>
+ </tr>
+ </table>
+ <hr>
+ </div>
+ </div>
+</ng-template>
+
+<ng-template #emptyTpl>
+ <div *ngIf="notifications.length === 0">
+ <div class="message">
+ There are no notifications.
+ </div>
+ </div>
+</ng-template>
+
+<ng-template #popTpl>
+ <ng-container *ngTemplateOutlet="notificationsTpl"></ng-container>
+ <ng-container *ngTemplateOutlet="emptyTpl"></ng-container>
+</ng-template>
+
+<a [popover]="popTpl"
+ placement="bottom"
+ container="body"
+ outsideClick="true"
+ i18n-title
+ title="Recent Notifications">
+ <i class="fa fa-fw fa-bell"></i>
+ <span i18n
+ class="visible-xs-inline-block">Recent Notifications</span>
+</a>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.scss
new file mode 100644
index 00000000..70cfd4a6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.scss
@@ -0,0 +1 @@
+@import '../../../../styles/popover.scss';
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.spec.ts
new file mode 100644
index 00000000..6ce6241f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.spec.ts
@@ -0,0 +1,89 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { ToastrModule } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { PrometheusService } from '../../../shared/api/prometheus.service';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { PrometheusAlertService } from '../../../shared/services/prometheus-alert.service';
+import { PrometheusNotificationService } from '../../../shared/services/prometheus-notification.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { NotificationsComponent } from './notifications.component';
+
+describe('NotificationsComponent', () => {
+ let component: NotificationsComponent;
+ let fixture: ComponentFixture<NotificationsComponent>;
+
+ configureTestBed({
+ imports: [
+ HttpClientTestingModule,
+ PopoverModule.forRoot(),
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ declarations: [NotificationsComponent],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NotificationsComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ describe('prometheus alert handling', () => {
+ let prometheusAlertService: PrometheusAlertService;
+ let prometheusNotificationService: PrometheusNotificationService;
+ let prometheusAccessAllowed: boolean;
+
+ const expectPrometheusServicesToBeCalledTimes = (n: number) => {
+ expect(prometheusNotificationService.refresh).toHaveBeenCalledTimes(n);
+ expect(prometheusAlertService.refresh).toHaveBeenCalledTimes(n);
+ };
+
+ beforeEach(() => {
+ prometheusAccessAllowed = true;
+ spyOn(TestBed.get(AuthStorageService), 'getPermissions').and.callFake(() => ({
+ prometheus: { read: prometheusAccessAllowed }
+ }));
+
+ spyOn(TestBed.get(PrometheusService), 'ifAlertmanagerConfigured').and.callFake((fn) => fn());
+
+ prometheusAlertService = TestBed.get(PrometheusAlertService);
+ spyOn(prometheusAlertService, 'refresh').and.stub();
+
+ prometheusNotificationService = TestBed.get(PrometheusNotificationService);
+ spyOn(prometheusNotificationService, 'refresh').and.stub();
+ });
+
+ it('should not refresh prometheus services if not allowed', () => {
+ prometheusAccessAllowed = false;
+ fixture.detectChanges();
+
+ expectPrometheusServicesToBeCalledTimes(0);
+ });
+ it('should first refresh prometheus notifications and alerts during init', () => {
+ fixture.detectChanges();
+
+ expect(prometheusAlertService.refresh).toHaveBeenCalledTimes(1);
+ expectPrometheusServicesToBeCalledTimes(1);
+ });
+
+ it('should refresh prometheus services every 5s', fakeAsync(() => {
+ fixture.detectChanges();
+
+ expectPrometheusServicesToBeCalledTimes(1);
+ tick(5000);
+ expectPrometheusServicesToBeCalledTimes(2);
+ tick(15000);
+ expectPrometheusServicesToBeCalledTimes(5);
+ component.ngOnDestroy();
+ }));
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.ts
new file mode 100644
index 00000000..d3dd47a1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.ts
@@ -0,0 +1,58 @@
+import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { CdNotification } from '../../../shared/models/cd-notification';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { PrometheusAlertService } from '../../../shared/services/prometheus-alert.service';
+import { PrometheusNotificationService } from '../../../shared/services/prometheus-notification.service';
+
+@Component({
+ selector: 'cd-notifications',
+ templateUrl: './notifications.component.html',
+ styleUrls: ['./notifications.component.scss']
+})
+export class NotificationsComponent implements OnInit, OnDestroy {
+ notifications: CdNotification[];
+ private interval: number;
+
+ constructor(
+ public notificationService: NotificationService,
+ private prometheusNotificationService: PrometheusNotificationService,
+ private authStorageService: AuthStorageService,
+ private prometheusAlertService: PrometheusAlertService,
+ private ngZone: NgZone
+ ) {
+ this.notifications = [];
+ }
+
+ ngOnDestroy() {
+ window.clearInterval(this.interval);
+ }
+
+ ngOnInit() {
+ if (this.authStorageService.getPermissions().prometheus.read) {
+ this.triggerPrometheusAlerts();
+ this.ngZone.runOutsideAngular(() => {
+ this.interval = window.setInterval(() => {
+ this.ngZone.run(() => {
+ this.triggerPrometheusAlerts();
+ });
+ }, 5000);
+ });
+ }
+ this.notificationService.data$.subscribe((notifications: CdNotification[]) => {
+ this.notifications = _.orderBy(notifications, ['timestamp'], ['desc']);
+ });
+ }
+
+ private triggerPrometheusAlerts() {
+ this.prometheusAlertService.refresh();
+ this.prometheusNotificationService.refresh();
+ }
+
+ removeAll() {
+ this.notificationService.removeAll();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.html
new file mode 100644
index 00000000..dae57580
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.html
@@ -0,0 +1,85 @@
+<ng-template #popTemplate>
+ <!-- Executing -->
+ <div *ngIf="executingTasks.length > 0">
+ <div class="separator">EXECUTING</div>
+ <hr>
+ <div *ngFor="let executingTask of executingTasks">
+ <table>
+ <tr>
+ <td rowspan="3" class="icon-col text-center">
+ <span class="fa-stack fa-2x text-info">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i class="fa fa-stack-1x fa-inverse fa-spinner fa-spin"></i>
+ </span>
+ </td>
+ <td colspan="3"><strong>{{ executingTask.description }}</strong></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <small class="date">{{ executingTask.begin_time | cdDate }}</small>
+ </td>
+ <td class="text-right italic" nowrap *ngIf="executingTask.progress"><span>{{ executingTask.progress }} %</span></td>
+ </tr>
+ </table>
+ <hr>
+ </div>
+ </div>
+ <!-- Finished -->
+ <div *ngIf="finishedTasks.length > 0">
+ <div class="separator">FINISHED</div>
+ <hr>
+ <div *ngFor="let finishedTask of finishedTasks">
+ <table>
+ <tr>
+ <td rowspan="3" class="icon-col text-center">
+ <span *ngIf="!finishedTask.errorMessage">
+ <span class="fa-stack fa-2x text-success">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i class="fa fa-stack-1x fa-inverse fa-check"></i>
+ </span>
+ </span>
+ <span *ngIf="finishedTask.errorMessage">
+ <span class="fa-stack fa-2x text-danger">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i class="fa fa-stack-1x fa-inverse fa-exclamation-triangle"></i>
+ </span>
+ </span>
+ </td>
+ <td colspan="2">
+ <strong>{{ finishedTask.description }}</strong>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <span *ngIf="finishedTask.errorMessage" class="text-danger">
+ {{ finishedTask.errorMessage }}
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <small class="date">{{ finishedTask.end_time | cdDate }}</small>
+ </td>
+ </tr>
+ </table>
+ <hr>
+ </div>
+ </div>
+ <!-- Empty -->
+ <div *ngIf="executingTasks.length === 0 && finishedTasks.length === 0">
+ <div class="message" i18n>There are no background tasks.</div>
+ </div>
+</ng-template>
+<a [popover]="popTemplate"
+ placement="bottom"
+ container="body"
+ outsideClick="true"
+ i18n-title
+ title="Background Tasks">
+ <i class="fa fa-fw"
+ [ngClass]="icon"></i>
+ <span i18n
+ class="visible-xs-inline-block">Background Tasks</span>
+ <span *ngIf="executingTasks.length > 0"> ({{ executingTasks.length }})</span>
+</a>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.scss
new file mode 100644
index 00000000..70cfd4a6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.scss
@@ -0,0 +1 @@
+@import '../../../../styles/popover.scss';
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.spec.ts
new file mode 100644
index 00000000..e1839d52
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.spec.ts
@@ -0,0 +1,86 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { PopoverModule } from 'ngx-bootstrap/popover';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { SharedModule } from '../../../shared/shared.module';
+import { TaskManagerComponent } from './task-manager.component';
+
+describe('TaskManagerComponent', () => {
+ let component: TaskManagerComponent;
+ let fixture: ComponentFixture<TaskManagerComponent>;
+ const tasks = {
+ executing: [],
+ finished: []
+ };
+
+ configureTestBed({
+ imports: [SharedModule, PopoverModule.forRoot(), HttpClientTestingModule, RouterTestingModule],
+ declarations: [TaskManagerComponent],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TaskManagerComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ tasks.executing = [
+ new ExecutingTask('rbd/delete', {
+ pool_name: 'somePool',
+ image_name: 'someImage'
+ })
+ ];
+ tasks.finished = [
+ new FinishedTask('rbd/copy', {
+ dest_pool_name: 'somePool',
+ dest_image_name: 'someImage'
+ }),
+ new FinishedTask('rbd/clone', {
+ child_pool_name: 'somePool',
+ child_image_name: 'someImage'
+ })
+ ];
+ tasks.finished[1].success = false;
+ tasks.finished[1].exception = { code: 17 };
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should get executing message for task', () => {
+ component._handleTasks(tasks.executing, []);
+ expect(component.executingTasks.length).toBe(1);
+ expect(component.executingTasks[0].description).toBe(`Deleting RBD 'somePool/someImage'`);
+ });
+
+ it('should get finished message for successful task', () => {
+ component._handleTasks([], tasks.finished);
+ expect(component.finishedTasks.length).toBe(2);
+ expect(component.finishedTasks[0].description).toBe(`Copied RBD 'somePool/someImage'`);
+ expect(component.finishedTasks[0].errorMessage).toBe(undefined);
+ });
+
+ it('should get failed message for finished task', () => {
+ component._handleTasks([], tasks.finished);
+ expect(component.finishedTasks.length).toBe(2);
+ expect(component.finishedTasks[1].description).toBe(`Failed to clone RBD 'somePool/someImage'`);
+ expect(component.finishedTasks[1].errorMessage).toBe(
+ `Name is already used by RBD 'somePool/someImage'.`
+ );
+ });
+
+ it('should get an empty hour glass with only finished tasks', () => {
+ component._setIcon(0);
+ expect(component.icon).toBe('fa-hourglass-o');
+ });
+
+ it('should get a nearly empty hour glass with executing tasks', () => {
+ component._setIcon(10);
+ expect(component.icon).toBe('fa-hourglass-start');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.ts
new file mode 100644
index 00000000..3eb58985
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.ts
@@ -0,0 +1,55 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ExecutingTask } from '../../../shared/models/executing-task';
+import { FinishedTask } from '../../../shared/models/finished-task';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { TaskMessageService } from '../../../shared/services/task-message.service';
+
+@Component({
+ selector: 'cd-task-manager',
+ templateUrl: './task-manager.component.html',
+ styleUrls: ['./task-manager.component.scss']
+})
+export class TaskManagerComponent implements OnInit {
+ executingTasks: ExecutingTask[] = [];
+ finishedTasks: FinishedTask[] = [];
+
+ icon = 'fa-hourglass-o';
+
+ constructor(
+ private summaryService: SummaryService,
+ private taskMessageService: TaskMessageService
+ ) {}
+
+ ngOnInit() {
+ this.summaryService.subscribe((data: any) => {
+ if (!data) {
+ return;
+ }
+ this._handleTasks(data.executing_tasks, data.finished_tasks);
+ this._setIcon(data.executing_tasks.length);
+ });
+ }
+
+ _handleTasks(executingTasks: ExecutingTask[], finishedTasks: FinishedTask[]) {
+ for (const excutingTask of executingTasks) {
+ excutingTask.description = this.taskMessageService.getRunningTitle(excutingTask);
+ }
+ for (const finishedTask of finishedTasks) {
+ if (finishedTask.success === false) {
+ finishedTask.description = this.taskMessageService.getErrorTitle(finishedTask);
+ finishedTask.errorMessage = this.taskMessageService.getErrorMessage(finishedTask);
+ } else {
+ finishedTask.description = this.taskMessageService.getSuccessTitle(finishedTask);
+ }
+ }
+ this.executingTasks = executingTasks;
+ this.finishedTasks = finishedTasks;
+ }
+
+ _setIcon(executingTasks: number) {
+ const iconSuffix = ['o', 'start', 'half', 'end']; // TODO: Use all suffixes
+ const iconIndex = executingTasks > 0 ? 1 : 0;
+ this.icon = 'fa-hourglass-' + iconSuffix[iconIndex];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.html
new file mode 100644
index 00000000..b50478af
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.html
@@ -0,0 +1,14 @@
+<div class="row">
+ <div class="col-md-12 text-center">
+ <h1 i18n>Sorry, we could not find what you were looking for</h1>
+
+ <img class="img-responsive center-block img-rounded"
+ src="assets/1280px-Nautilus_Octopus.jpg">
+ <span>
+ "<a href="https://www.flickr.com/photos/146401137@N06/40335060661">Nautilus Octopus</a>" by Jin Kemoole is licensed under
+ <a rel="nofollow"
+ class="external text"
+ href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>
+ </span>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.scss
new file mode 100644
index 00000000..fdf2e710
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.scss
@@ -0,0 +1,11 @@
+h1 {
+ font-size: -webkit-xxx-large;
+}
+
+* {
+ font-family: monospace;
+}
+
+img {
+ width: 50vw;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.spec.ts
new file mode 100644
index 00000000..b75232c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { NotFoundComponent } from './not-found.component';
+
+describe('NotFoundComponent', () => {
+ let component: NotFoundComponent;
+ let fixture: ComponentFixture<NotFoundComponent>;
+
+ configureTestBed({
+ declarations: [NotFoundComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NotFoundComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.ts
new file mode 100644
index 00000000..d12bc321
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/core/not-found/not-found.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'cd-not-found',
+ templateUrl: './not-found.component.html',
+ styleUrls: ['./not-found.component.scss']
+})
+export class NotFoundComponent {
+ constructor() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/api.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/api.module.ts
new file mode 100644
index 00000000..4066a304
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/api.module.ts
@@ -0,0 +1,7 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+@NgModule({
+ imports: [CommonModule]
+})
+export class ApiModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.spec.ts
new file mode 100644
index 00000000..b535547f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.spec.ts
@@ -0,0 +1,54 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { AuthStorageService } from '../services/auth-storage.service';
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+ let service: AuthService;
+ let httpTesting: HttpTestingController;
+
+ const routes: Routes = [{ path: 'logout', children: [] }];
+
+ configureTestBed({
+ providers: [AuthService, AuthStorageService],
+ imports: [HttpClientTestingModule, RouterTestingModule.withRoutes(routes)]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(AuthService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should login and save the user', fakeAsync(() => {
+ const fakeCredentials = { username: 'foo', password: 'bar' };
+ const fakeResponse = { username: 'foo' };
+ service.login(<any>fakeCredentials);
+ const req = httpTesting.expectOne('api/auth');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(fakeCredentials);
+ req.flush(fakeResponse);
+ tick();
+ expect(localStorage.getItem('dashboard_username')).toBe('foo');
+ }));
+
+ it('should logout and remove the user', fakeAsync(() => {
+ service.logout();
+ const req = httpTesting.expectOne('api/auth/logout');
+ expect(req.request.method).toBe('POST');
+ req.flush({ redirect_url: '#/login' });
+ tick();
+ expect(localStorage.getItem('dashboard_username')).toBe(null);
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.ts
new file mode 100644
index 00000000..fbee7b20
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/auth.service.ts
@@ -0,0 +1,43 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Router } from '@angular/router';
+
+import { Credentials } from '../models/credentials';
+import { LoginResponse } from '../models/login-response';
+import { AuthStorageService } from '../services/auth-storage.service';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class AuthService {
+ constructor(
+ private authStorageService: AuthStorageService,
+ private http: HttpClient,
+ private router: Router
+ ) {}
+
+ check(token: string) {
+ return this.http.post('api/auth/check', { token: token });
+ }
+
+ login(credentials: Credentials) {
+ return this.http
+ .post('api/auth', credentials)
+ .toPromise()
+ .then((resp: LoginResponse) => {
+ this.authStorageService.set(resp.username, resp.permissions);
+ });
+ }
+
+ logout(callback: Function = null) {
+ return this.http.post('api/auth/logout', null).subscribe((resp: any) => {
+ this.authStorageService.remove();
+ this.router.navigate(['/logout'], { skipLocationChange: true });
+ if (callback) {
+ callback();
+ }
+ window.location.replace(resp.redirect_url);
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.spec.ts
new file mode 100644
index 00000000..882f7c58
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.spec.ts
@@ -0,0 +1,52 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { CephfsService } from './cephfs.service';
+
+describe('CephfsService', () => {
+ let service: CephfsService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ providers: [CephfsService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(CephfsService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/cephfs');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getCephfs', () => {
+ service.getCephfs(1).subscribe();
+ const req = httpTesting.expectOne('api/cephfs/1');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getClients', () => {
+ service.getClients(1).subscribe();
+ const req = httpTesting.expectOne('api/cephfs/1/clients');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getMdsCounters', () => {
+ service.getMdsCounters(1).subscribe();
+ const req = httpTesting.expectOne('api/cephfs/1/mds_counters');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.ts
new file mode 100644
index 00000000..745f2589
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.ts
@@ -0,0 +1,29 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class CephfsService {
+ baseURL = 'api/cephfs';
+
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get(`${this.baseURL}`);
+ }
+
+ getCephfs(id) {
+ return this.http.get(`${this.baseURL}/${id}`);
+ }
+
+ getClients(id) {
+ return this.http.get(`${this.baseURL}/${id}/clients`);
+ }
+
+ getMdsCounters(id) {
+ return this.http.get(`${this.baseURL}/${id}/mds_counters`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.spec.ts
new file mode 100644
index 00000000..9add3a5b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.spec.ts
@@ -0,0 +1,80 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { ConfigFormCreateRequestModel } from '../../ceph/cluster/configuration/configuration-form/configuration-form-create-request.model';
+import { ConfigurationService } from './configuration.service';
+
+describe('ConfigurationService', () => {
+ let service: ConfigurationService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [ConfigurationService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(ConfigurationService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getConfigData', () => {
+ service.getConfigData().subscribe();
+ const req = httpTesting.expectOne('api/cluster_conf/');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ service.get('configOption').subscribe();
+ const req = httpTesting.expectOne('api/cluster_conf/configOption');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call create', () => {
+ const configOption = new ConfigFormCreateRequestModel();
+ configOption.name = 'Test option';
+ configOption.value = [
+ { section: 'section1', value: 'value1' },
+ { section: 'section2', value: 'value2' }
+ ];
+ service.create(configOption).subscribe();
+ const req = httpTesting.expectOne('api/cluster_conf/');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(configOption);
+ });
+
+ it('should call bulkCreate', () => {
+ const configOptions = {
+ configOption1: { section: 'section', value: 'value' },
+ configOption2: { section: 'section', value: 'value' }
+ };
+ service.bulkCreate(configOptions).subscribe();
+ const req = httpTesting.expectOne('api/cluster_conf/');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual(configOptions);
+ });
+
+ it('should call filter', () => {
+ const configOptions = ['configOption1', 'configOption2', 'configOption3'];
+ service.filter(configOptions).subscribe();
+ const req = httpTesting.expectOne(
+ 'api/cluster_conf/filter?names=configOption1,configOption2,configOption3'
+ );
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call delete', () => {
+ service.delete('testOption', 'testSection').subscribe();
+ const reg = httpTesting.expectOne('api/cluster_conf/testOption?section=testSection');
+ expect(reg.request.method).toBe('DELETE');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts
new file mode 100644
index 00000000..3355b8fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts
@@ -0,0 +1,36 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ConfigFormCreateRequestModel } from '../../ceph/cluster/configuration/configuration-form/configuration-form-create-request.model';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class ConfigurationService {
+ constructor(private http: HttpClient) {}
+
+ getConfigData() {
+ return this.http.get('api/cluster_conf/');
+ }
+
+ get(configOption: string) {
+ return this.http.get(`api/cluster_conf/${configOption}`);
+ }
+
+ filter(configOptionNames: Array<string>) {
+ return this.http.get(`api/cluster_conf/filter?names=${configOptionNames.join(',')}`);
+ }
+
+ create(configOption: ConfigFormCreateRequestModel) {
+ return this.http.post('api/cluster_conf/', configOption);
+ }
+
+ delete(configOption: string, section: string) {
+ return this.http.delete(`api/cluster_conf/${configOption}?section=${section}`);
+ }
+
+ bulkCreate(configOptions: Object) {
+ return this.http.put('api/cluster_conf/', configOptions);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.spec.ts
new file mode 100644
index 00000000..227af54c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.spec.ts
@@ -0,0 +1,67 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { ErasureCodeProfile } from '../models/erasure-code-profile';
+import { ErasureCodeProfileService } from './erasure-code-profile.service';
+
+describe('ErasureCodeProfileService', () => {
+ let service: ErasureCodeProfileService;
+ let httpTesting: HttpTestingController;
+ const apiPath = 'api/erasure_code_profile';
+ const testProfile: ErasureCodeProfile = { name: 'test', plugin: 'jerasure', k: 2, m: 1 };
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ providers: [ErasureCodeProfileService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(ErasureCodeProfileService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne(apiPath);
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call create', () => {
+ service.create(testProfile).subscribe();
+ const req = httpTesting.expectOne(apiPath);
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call update', () => {
+ service.update(testProfile).subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/test`);
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call delete', () => {
+ service.delete('test').subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/test`);
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call get', () => {
+ service.get('test').subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/test`);
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getInfo', () => {
+ service.getInfo().subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/_info`);
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.ts
new file mode 100644
index 00000000..df752772
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/erasure-code-profile.service.ts
@@ -0,0 +1,107 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { ErasureCodeProfile } from '../models/erasure-code-profile';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class ErasureCodeProfileService {
+ apiPath = 'api/erasure_code_profile';
+
+ formTooltips = {
+ // Copied from /srv/cephmgr/ceph-dev/doc/rados/operations/erasure-code.*.rst
+ k: this.i18n(`Each object is split in data-chunks parts, each stored on a different OSD.`),
+
+ m: this.i18n(`Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.`),
+
+ plugins: {
+ jerasure: {
+ description: this.i18n(`The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.`),
+ technique: this.i18n(`The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.`),
+ packetSize: this.i18n(`The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.`)
+ },
+ lrc: {
+ description: this.i18n(`With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.`),
+ l: this.i18n(`Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.`),
+ crushLocality: this.i18n(`The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.`)
+ },
+ isa: {
+ description: this.i18n(
+ `The isa plugin encapsulates the ISA library. It only runs on Intel processors.`
+ ),
+ technique: this.i18n(`The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.`)
+ },
+ shec: {
+ description: this.i18n(`The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.`),
+ c: this.i18n(`The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.`)
+ }
+ },
+
+ crushRoot: this.i18n(`The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.`),
+
+ crushFailureDomain: this.i18n(`Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.`),
+
+ crushDeviceClass: this.i18n(`Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.`),
+
+ directory: this.i18n(`Set the directory name from which the erasure code plugin is loaded.`)
+ };
+
+ constructor(private http: HttpClient, private i18n: I18n) {}
+
+ list(): Observable<ErasureCodeProfile[]> {
+ return this.http.get<ErasureCodeProfile[]>(this.apiPath);
+ }
+
+ create(ecp: ErasureCodeProfile) {
+ return this.http.post(this.apiPath, ecp, { observe: 'response' });
+ }
+
+ update(ecp: ErasureCodeProfile) {
+ return this.http.put(`${this.apiPath}/${ecp.name}`, ecp, { observe: 'response' });
+ }
+
+ delete(name: string) {
+ return this.http.delete(`${this.apiPath}/${name}`, { observe: 'response' });
+ }
+
+ get(name: string) {
+ return this.http.get(`${this.apiPath}/${name}`);
+ }
+
+ getInfo() {
+ return this.http.get(`${this.apiPath}/_info`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.spec.ts
new file mode 100644
index 00000000..82736401
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.spec.ts
@@ -0,0 +1,40 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { HealthService } from './health.service';
+
+describe('HealthService', () => {
+ let service: HealthService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [HealthService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(HealthService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getFullHealth', () => {
+ service.getFullHealth().subscribe();
+ const req = httpTesting.expectOne('api/health/full');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getMinimalHealth', () => {
+ service.getMinimalHealth().subscribe();
+ const req = httpTesting.expectOne('api/health/minimal');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.ts
new file mode 100644
index 00000000..e3ac3934
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/health.service.ts
@@ -0,0 +1,19 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class HealthService {
+ constructor(private http: HttpClient) {}
+
+ getFullHealth() {
+ return this.http.get('api/health/full');
+ }
+
+ getMinimalHealth() {
+ return this.http.get('api/health/minimal');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.spec.ts
new file mode 100644
index 00000000..a9354ce5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.spec.ts
@@ -0,0 +1,38 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { HostService } from './host.service';
+
+describe('HostService', () => {
+ let service: HostService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [HostService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(HostService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', fakeAsync(() => {
+ let result;
+ service.list().then((resp) => (result = resp));
+ const req = httpTesting.expectOne('api/host');
+ expect(req.request.method).toBe('GET');
+ req.flush(['foo', 'bar']);
+ tick();
+ expect(result).toEqual(['foo', 'bar']);
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts
new file mode 100644
index 00000000..e0338609
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts
@@ -0,0 +1,20 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class HostService {
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http
+ .get('api/host')
+ .toPromise()
+ .then((resp: any) => {
+ return resp;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.spec.ts
new file mode 100644
index 00000000..7eb21db9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.spec.ts
@@ -0,0 +1,97 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { IscsiService } from './iscsi.service';
+
+describe('IscsiService', () => {
+ let service: IscsiService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [IscsiService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(IscsiService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call listTargets', () => {
+ service.listTargets().subscribe();
+ const req = httpTesting.expectOne('api/iscsi/target');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getTarget', () => {
+ service.getTarget('iqn.foo').subscribe();
+ const req = httpTesting.expectOne('api/iscsi/target/iqn.foo');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call status', () => {
+ service.status().subscribe();
+ const req = httpTesting.expectOne('ui-api/iscsi/status');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call settings', () => {
+ service.settings().subscribe();
+ const req = httpTesting.expectOne('ui-api/iscsi/settings');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call portals', () => {
+ service.portals().subscribe();
+ const req = httpTesting.expectOne('ui-api/iscsi/portals');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call createTarget', () => {
+ service.createTarget({ target_iqn: 'foo' }).subscribe();
+ const req = httpTesting.expectOne('api/iscsi/target');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({ target_iqn: 'foo' });
+ });
+
+ it('should call updateTarget', () => {
+ service.updateTarget('iqn.foo', { target_iqn: 'foo' }).subscribe();
+ const req = httpTesting.expectOne('api/iscsi/target/iqn.foo');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({ target_iqn: 'foo' });
+ });
+
+ it('should call deleteTarget', () => {
+ service.deleteTarget('target_iqn').subscribe();
+ const req = httpTesting.expectOne('api/iscsi/target/target_iqn');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call getDiscovery', () => {
+ service.getDiscovery().subscribe();
+ const req = httpTesting.expectOne('api/iscsi/discoveryauth');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call updateDiscovery', () => {
+ service
+ .updateDiscovery({
+ user: 'foo',
+ password: 'bar',
+ mutual_user: 'mutual_foo',
+ mutual_password: 'mutual_bar'
+ })
+ .subscribe();
+ const req = httpTesting.expectOne('api/iscsi/discoveryauth');
+ expect(req.request.method).toBe('PUT');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.ts
new file mode 100644
index 00000000..6b31eaad
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/iscsi.service.ts
@@ -0,0 +1,61 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class IscsiService {
+ constructor(private http: HttpClient) {}
+
+ listTargets() {
+ return this.http.get(`api/iscsi/target`);
+ }
+
+ getTarget(target_iqn) {
+ return this.http.get(`api/iscsi/target/${target_iqn}`);
+ }
+
+ updateTarget(target_iqn, target) {
+ return this.http.put(`api/iscsi/target/${target_iqn}`, target, { observe: 'response' });
+ }
+
+ status() {
+ return this.http.get(`ui-api/iscsi/status`);
+ }
+
+ settings() {
+ return this.http.get(`ui-api/iscsi/settings`);
+ }
+
+ version() {
+ return this.http.get(`ui-api/iscsi/version`);
+ }
+
+ portals() {
+ return this.http.get(`ui-api/iscsi/portals`);
+ }
+
+ createTarget(target) {
+ return this.http.post(`api/iscsi/target`, target, { observe: 'response' });
+ }
+
+ deleteTarget(target_iqn) {
+ return this.http.delete(`api/iscsi/target/${target_iqn}`, { observe: 'response' });
+ }
+
+ getDiscovery() {
+ return this.http.get(`api/iscsi/discoveryauth`);
+ }
+
+ updateDiscovery(auth) {
+ return this.http.put(`api/iscsi/discoveryauth`, auth);
+ }
+
+ overview() {
+ return this.http.get(`ui-api/iscsi/overview`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.spec.ts
new file mode 100644
index 00000000..cc855f2a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.spec.ts
@@ -0,0 +1,39 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { LoggingService } from './logging.service';
+
+describe('LoggingService', () => {
+ let service: LoggingService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [LoggingService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(LoggingService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call jsError', () => {
+ service.jsError('foo', 'bar', 'baz').subscribe();
+ const req = httpTesting.expectOne('ui-api/logging/js-error');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({
+ url: 'foo',
+ message: 'bar',
+ stack: 'baz'
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.ts
new file mode 100644
index 00000000..3ed2a172
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logging.service.ts
@@ -0,0 +1,20 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class LoggingService {
+ constructor(private http: HttpClient) {}
+
+ jsError(url, message, stack) {
+ const request = {
+ url: url,
+ message: message,
+ stack: stack
+ };
+ return this.http.post('ui-api/logging/js-error', request);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.spec.ts
new file mode 100644
index 00000000..8e7777a6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.spec.ts
@@ -0,0 +1,34 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { LogsService } from './logs.service';
+
+describe('LogsService', () => {
+ let service: LogsService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [LogsService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(LogsService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getLogs', () => {
+ service.getLogs().subscribe();
+ const req = httpTesting.expectOne('api/logs/all');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts
new file mode 100644
index 00000000..04dfa82a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts
@@ -0,0 +1,19 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class LogsService {
+ constructor(private http: HttpClient) {}
+
+ getLogs() {
+ return this.http.get('api/logs/all');
+ }
+
+ validateDashboardUrl(uid) {
+ return this.http.get(`api/grafana/validation/${uid}`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.spec.ts
new file mode 100644
index 00000000..d996c565
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.spec.ts
@@ -0,0 +1,66 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { MgrModuleService } from './mgr-module.service';
+
+describe('MgrModuleService', () => {
+ let service: MgrModuleService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ providers: [MgrModuleService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(MgrModuleService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/mgr/module');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getConfig', () => {
+ service.getConfig('foo').subscribe();
+ const req = httpTesting.expectOne('api/mgr/module/foo');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call updateConfig', () => {
+ const config = { foo: 'bar' };
+ service.updateConfig('xyz', config).subscribe();
+ const req = httpTesting.expectOne('api/mgr/module/xyz');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body.config).toEqual(config);
+ });
+
+ it('should call enable', () => {
+ service.enable('foo').subscribe();
+ const req = httpTesting.expectOne('api/mgr/module/foo/enable');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call disable', () => {
+ service.disable('bar').subscribe();
+ const req = httpTesting.expectOne('api/mgr/module/bar/disable');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call getOptions', () => {
+ service.getOptions('foo').subscribe();
+ const req = httpTesting.expectOne('api/mgr/module/foo/options');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.ts
new file mode 100644
index 00000000..782ee737
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/mgr-module.service.ts
@@ -0,0 +1,67 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class MgrModuleService {
+ private url = 'api/mgr/module';
+
+ constructor(private http: HttpClient) {}
+
+ /**
+ * Get the list of Ceph Mgr modules and their state (enabled/disabled).
+ * @return {Observable<Object[]>}
+ */
+ list(): Observable<Object[]> {
+ return this.http.get<Object[]>(`${this.url}`);
+ }
+
+ /**
+ * Get the Ceph Mgr module configuration.
+ * @param {string} module The name of the mgr module.
+ * @return {Observable<Object>}
+ */
+ getConfig(module: string): Observable<Object> {
+ return this.http.get(`${this.url}/${module}`);
+ }
+
+ /**
+ * Update the Ceph Mgr module configuration.
+ * @param {string} module The name of the mgr module.
+ * @param {object} config The configuration.
+ * @return {Observable<Object>}
+ */
+ updateConfig(module: string, config: Object): Observable<Object> {
+ return this.http.put(`${this.url}/${module}`, { config: config });
+ }
+
+ /**
+ * Enable the Ceph Mgr module.
+ * @param {string} module The name of the mgr module.
+ */
+ enable(module: string) {
+ return this.http.post(`${this.url}/${module}/enable`, null);
+ }
+
+ /**
+ * Disable the Ceph Mgr module.
+ * @param {string} module The name of the mgr module.
+ */
+ disable(module: string) {
+ return this.http.post(`${this.url}/${module}/disable`, null);
+ }
+
+ /**
+ * Get the Ceph Mgr module options.
+ * @param {string} module The name of the mgr module.
+ * @return {Observable<Object>}
+ */
+ getOptions(module: string): Observable<Object> {
+ return this.http.get(`${this.url}/${module}/options`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.spec.ts
new file mode 100644
index 00000000..0eca853a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.spec.ts
@@ -0,0 +1,34 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { MonitorService } from './monitor.service';
+
+describe('MonitorService', () => {
+ let service: MonitorService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [MonitorService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(MonitorService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getMonitor', () => {
+ service.getMonitor().subscribe();
+ const req = httpTesting.expectOne('api/monitor');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.ts
new file mode 100644
index 00000000..115d1ca3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/monitor.service.ts
@@ -0,0 +1,15 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class MonitorService {
+ constructor(private http: HttpClient) {}
+
+ getMonitor() {
+ return this.http.get('api/monitor');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.spec.ts
new file mode 100644
index 00000000..e5f039ff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.spec.ts
@@ -0,0 +1,90 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { NfsService } from './nfs.service';
+
+describe('NfsService', () => {
+ let service: NfsService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [NfsService, i18nProviders],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(NfsService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/export');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ service.get('cluster_id', 'export_id').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/export/cluster_id/export_id');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call create', () => {
+ service.create('foo').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/export');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual('foo');
+ });
+
+ it('should call update', () => {
+ service.update('cluster_id', 'export_id', 'foo').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/export/cluster_id/export_id');
+ expect(req.request.body).toEqual('foo');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call delete', () => {
+ service.delete('hostName', 'exportId').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/export/hostName/exportId');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call lsDir', () => {
+ service.lsDir('foo_dir').subscribe();
+ const req = httpTesting.expectOne('ui-api/nfs-ganesha/lsdir?root_dir=foo_dir');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call buckets', () => {
+ service.buckets('user_foo').subscribe();
+ const req = httpTesting.expectOne('ui-api/nfs-ganesha/rgw/buckets?user_id=user_foo');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call daemon', () => {
+ service.daemon().subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/daemon');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call start', () => {
+ service.start('host_name').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/service/host_name/start');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call stop', () => {
+ service.stop('host_name').subscribe();
+ const req = httpTesting.expectOne('api/nfs-ganesha/service/host_name/stop');
+ expect(req.request.method).toBe('PUT');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.ts
new file mode 100644
index 00000000..3ad1aadc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/nfs.service.ts
@@ -0,0 +1,113 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class NfsService {
+ apiPath = 'api/nfs-ganesha';
+ uiApiPath = 'ui-api/nfs-ganesha';
+
+ nfsAccessType = [
+ {
+ value: 'RW',
+ help: this.i18n('Allows all operations')
+ },
+ {
+ value: 'RO',
+ help: this.i18n('Allows only operations that do not modify the server')
+ },
+ {
+ value: 'MDONLY',
+ help: this.i18n('Does not allow read or write operations, but allows any other operation')
+ },
+ {
+ value: 'MDONLY_RO',
+ help: this.i18n(
+ 'Does not allow read, write, or any operation that modifies file \
+ attributes or directory content'
+ )
+ },
+ {
+ value: 'NONE',
+ help: this.i18n('Allows no access at all')
+ }
+ ];
+
+ nfsFsal = [
+ {
+ value: 'CEPH',
+ descr: this.i18n('CephFS')
+ },
+ {
+ value: 'RGW',
+ descr: this.i18n('Object Gateway')
+ }
+ ];
+
+ nfsSquash = ['no_root_squash', 'root_id_squash', 'root_squash', 'all_squash'];
+
+ constructor(private http: HttpClient, private i18n: I18n) {}
+
+ list() {
+ return this.http.get(`${this.apiPath}/export`);
+ }
+
+ get(clusterId, exportId) {
+ return this.http.get(`${this.apiPath}/export/${clusterId}/${exportId}`);
+ }
+
+ create(nfs) {
+ return this.http.post(`${this.apiPath}/export`, nfs, { observe: 'response' });
+ }
+
+ update(clusterId, id, nfs) {
+ return this.http.put(`${this.apiPath}/export/${clusterId}/${id}`, nfs, { observe: 'response' });
+ }
+
+ delete(clusterId, exportId) {
+ return this.http.delete(`${this.apiPath}/export/${clusterId}/${exportId}`, {
+ observe: 'response'
+ });
+ }
+
+ lsDir(root_dir) {
+ return this.http.get(`${this.uiApiPath}/lsdir?root_dir=${root_dir}`);
+ }
+
+ buckets(user_id) {
+ return this.http.get(`${this.uiApiPath}/rgw/buckets?user_id=${user_id}`);
+ }
+
+ clients() {
+ return this.http.get(`${this.uiApiPath}/cephx/clients`);
+ }
+
+ fsals() {
+ return this.http.get(`${this.uiApiPath}/fsals`);
+ }
+
+ filesystems() {
+ return this.http.get(`${this.uiApiPath}/cephfs/filesystems`);
+ }
+
+ daemon() {
+ return this.http.get(`${this.apiPath}/daemon`);
+ }
+
+ start(host_name: string) {
+ return this.http.put(`${this.apiPath}/service/${host_name}/start`, null, {
+ observe: 'response'
+ });
+ }
+
+ stop(host_name: string) {
+ return this.http.put(`${this.apiPath}/service/${host_name}/stop`, null, {
+ observe: 'response'
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.spec.ts
new file mode 100644
index 00000000..e9225ef1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.spec.ts
@@ -0,0 +1,114 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { OsdService } from './osd.service';
+
+describe('OsdService', () => {
+ let service: OsdService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [OsdService, i18nProviders],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(OsdService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getList', () => {
+ service.getList().subscribe();
+ const req = httpTesting.expectOne('api/osd');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getDetails', () => {
+ service.getDetails(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call scrub, with deep=true', () => {
+ service.scrub('foo', true).subscribe();
+ const req = httpTesting.expectOne('api/osd/foo/scrub?deep=true');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call scrub, with deep=false', () => {
+ service.scrub('foo', false).subscribe();
+ const req = httpTesting.expectOne('api/osd/foo/scrub?deep=false');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call getFlags', () => {
+ service.getFlags().subscribe();
+ const req = httpTesting.expectOne('api/osd/flags');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call updateFlags', () => {
+ service.updateFlags(['foo']).subscribe();
+ const req = httpTesting.expectOne('api/osd/flags');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({ flags: ['foo'] });
+ });
+
+ it('should mark the OSD out', () => {
+ service.markOut(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/mark_out');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should mark the OSD in', () => {
+ service.markIn(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/mark_in');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should mark the OSD down', () => {
+ service.markDown(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/mark_down');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should reweight an OSD', () => {
+ service.reweight(1, 0.5).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/reweight');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({ weight: 0.5 });
+ });
+
+ it('should mark an OSD lost', () => {
+ service.markLost(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/mark_lost');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should purge an OSD', () => {
+ service.purge(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/purge');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should destroy an OSD', () => {
+ service.destroy(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/destroy');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should return if it is safe to destroy an OSD', () => {
+ service.safeToDestroy(1).subscribe();
+ const req = httpTesting.expectOne('api/osd/1/safe_to_destroy');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.ts
new file mode 100644
index 00000000..06c63bf8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/osd.service.ts
@@ -0,0 +1,116 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class OsdService {
+ private path = 'api/osd';
+
+ osdRecvSpeedModalPriorities = {
+ KNOWN_PRIORITIES: [
+ {
+ name: null,
+ text: this.i18n('-- Select the priority --'),
+ values: {
+ osd_max_backfills: null,
+ osd_recovery_max_active: null,
+ osd_recovery_max_single_start: null,
+ osd_recovery_sleep: null
+ }
+ },
+ {
+ name: 'low',
+ text: this.i18n('Low'),
+ values: {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 1,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0.5
+ }
+ },
+ {
+ name: 'default',
+ text: this.i18n('Default'),
+ values: {
+ osd_max_backfills: 1,
+ osd_recovery_max_active: 3,
+ osd_recovery_max_single_start: 1,
+ osd_recovery_sleep: 0
+ }
+ },
+ {
+ name: 'high',
+ text: this.i18n('High'),
+ values: {
+ osd_max_backfills: 4,
+ osd_recovery_max_active: 4,
+ osd_recovery_max_single_start: 4,
+ osd_recovery_sleep: 0
+ }
+ }
+ ]
+ };
+
+ constructor(private http: HttpClient, private i18n: I18n) {}
+
+ getList() {
+ return this.http.get(`${this.path}`);
+ }
+
+ getDetails(id: number) {
+ return this.http.get(`${this.path}/${id}`);
+ }
+
+ scrub(id, deep) {
+ return this.http.post(`${this.path}/${id}/scrub?deep=${deep}`, null);
+ }
+
+ getFlags() {
+ return this.http.get(`${this.path}/flags`);
+ }
+
+ updateFlags(flags: string[]) {
+ return this.http.put(`${this.path}/flags`, { flags: flags });
+ }
+
+ markOut(id: number) {
+ return this.http.post(`${this.path}/${id}/mark_out`, null);
+ }
+
+ markIn(id: number) {
+ return this.http.post(`${this.path}/${id}/mark_in`, null);
+ }
+
+ markDown(id: number) {
+ return this.http.post(`${this.path}/${id}/mark_down`, null);
+ }
+
+ reweight(id: number, weight: number) {
+ return this.http.post(`${this.path}/${id}/reweight`, { weight: weight });
+ }
+
+ markLost(id: number) {
+ return this.http.post(`${this.path}/${id}/mark_lost`, null);
+ }
+
+ purge(id: number) {
+ return this.http.post(`${this.path}/${id}/purge`, null);
+ }
+
+ destroy(id: number) {
+ return this.http.post(`${this.path}/${id}/destroy`, null);
+ }
+
+ safeToDestroy(id: number) {
+ interface SafeToDestroyResponse {
+ 'safe-to-destroy': boolean;
+ message?: string;
+ }
+ return this.http.get<SafeToDestroyResponse>(`${this.path}/${id}/safe_to_destroy`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.spec.ts
new file mode 100644
index 00000000..5cb79a6d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.spec.ts
@@ -0,0 +1,45 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { PerformanceCounterService } from './performance-counter.service';
+
+describe('PerformanceCounterService', () => {
+ let service: PerformanceCounterService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [PerformanceCounterService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(PerformanceCounterService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/perf_counters');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ let result;
+ service.get('foo', '1').subscribe((resp) => {
+ result = resp;
+ });
+ const req = httpTesting.expectOne('api/perf_counters/foo/1');
+ expect(req.request.method).toBe('GET');
+ req.flush({ counters: [{ foo: 'bar' }] });
+ expect(result).toEqual([{ foo: 'bar' }]);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.ts
new file mode 100644
index 00000000..5cf4207a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/performance-counter.service.ts
@@ -0,0 +1,30 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { of as observableOf } from 'rxjs';
+import { mergeMap } from 'rxjs/operators';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class PerformanceCounterService {
+ private url = 'api/perf_counters';
+
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get(this.url);
+ }
+
+ get(service_type: string, service_id: string) {
+ return this.http.get(`${this.url}/${service_type}/${service_id}`).pipe(
+ mergeMap((resp) => {
+ return observableOf(resp['counters']);
+ })
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.spec.ts
new file mode 100644
index 00000000..20ff612d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.spec.ts
@@ -0,0 +1,123 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { RbdConfigurationSourceField } from '../models/configuration';
+import { RbdConfigurationService } from '../services/rbd-configuration.service';
+import { PoolService } from './pool.service';
+
+describe('PoolService', () => {
+ let service: PoolService;
+ let httpTesting: HttpTestingController;
+ const apiPath = 'api/pool';
+
+ configureTestBed({
+ providers: [PoolService, RbdConfigurationService, i18nProviders],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(PoolService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getList', () => {
+ service.getList().subscribe();
+ const req = httpTesting.expectOne(`${apiPath}?stats=true`);
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getInfo', () => {
+ service.getInfo().subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/_info`);
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call create', () => {
+ const pool = { pool: 'somePool' };
+ service.create(pool).subscribe();
+ const req = httpTesting.expectOne(apiPath);
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(pool);
+ });
+
+ it('should call update', () => {
+ service.update({ pool: 'somePool', application_metadata: [] }).subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/somePool`);
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({ application_metadata: [] });
+ });
+
+ it('should call delete', () => {
+ service.delete('somePool').subscribe();
+ const req = httpTesting.expectOne(`${apiPath}/somePool`);
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call list without parameter', fakeAsync(() => {
+ let result;
+ service.list().then((resp) => (result = resp));
+ const req = httpTesting.expectOne(`${apiPath}?attrs=`);
+ expect(req.request.method).toBe('GET');
+ req.flush(['foo', 'bar']);
+ tick();
+ expect(result).toEqual(['foo', 'bar']);
+ }));
+
+ it('should call list with a list', fakeAsync(() => {
+ let result;
+ service.list(['foo']).then((resp) => (result = resp));
+ const req = httpTesting.expectOne(`${apiPath}?attrs=foo`);
+ expect(req.request.method).toBe('GET');
+ req.flush(['foo', 'bar']);
+ tick();
+ expect(result).toEqual(['foo', 'bar']);
+ }));
+
+ it('should test injection of data from getConfiguration()', fakeAsync(() => {
+ const pool = 'foo';
+ let value;
+ service.getConfiguration(pool).subscribe((next) => (value = next));
+ const req = httpTesting.expectOne(`${apiPath}/${pool}/configuration`);
+ expect(req.request.method).toBe('GET');
+ req.flush([
+ {
+ name: 'rbd_qos_bps_limit',
+ value: '60',
+ source: RbdConfigurationSourceField.global
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ value: '0',
+ source: RbdConfigurationSourceField.global
+ }
+ ]);
+ tick();
+ expect(value).toEqual([
+ {
+ description: 'The desired limit of IO bytes per second.',
+ displayName: 'BPS Limit',
+ name: 'rbd_qos_bps_limit',
+ source: RbdConfigurationSourceField.global,
+ type: 0,
+ value: '60'
+ },
+ {
+ description: 'The desired limit of IO operations per second.',
+ displayName: 'IOPS Limit',
+ name: 'rbd_qos_iops_limit',
+ source: RbdConfigurationSourceField.global,
+ type: 1,
+ value: '0'
+ }
+ ]);
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts
new file mode 100644
index 00000000..8d81b316
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts
@@ -0,0 +1,75 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { RbdConfigurationEntry } from '../models/configuration';
+import { RbdConfigurationService } from '../services/rbd-configuration.service';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class PoolService {
+ apiPath = 'api/pool';
+
+ constructor(private http: HttpClient, private rbdConfigurationService: RbdConfigurationService) {}
+
+ create(pool) {
+ return this.http.post(this.apiPath, pool, { observe: 'response' });
+ }
+
+ update(pool) {
+ let name: string;
+ if (pool.hasOwnProperty('srcpool')) {
+ name = pool.srcpool;
+ delete pool.srcpool;
+ } else {
+ name = pool.pool;
+ delete pool.pool;
+ }
+ return this.http.put(`${this.apiPath}/${encodeURIComponent(name)}`, pool, {
+ observe: 'response'
+ });
+ }
+
+ delete(name) {
+ return this.http.delete(`${this.apiPath}/${name}`, { observe: 'response' });
+ }
+
+ get(poolName) {
+ return this.http.get(`${this.apiPath}/${poolName}`);
+ }
+
+ getList() {
+ return this.http.get(`${this.apiPath}?stats=true`);
+ }
+
+ getConfiguration(poolName: string): Observable<RbdConfigurationEntry[]> {
+ return this.http.get<RbdConfigurationEntry[]>(`${this.apiPath}/${poolName}/configuration`).pipe(
+ // Add static data maintained in RbdConfigurationService
+ map((values) =>
+ values.map((entry) =>
+ Object.assign(entry, this.rbdConfigurationService.getOptionByName(entry.name))
+ )
+ )
+ );
+ }
+
+ getInfo(pool_name?: string) {
+ return this.http.get(`${this.apiPath}/_info` + (pool_name ? `?pool_name=${pool_name}` : ''));
+ }
+
+ list(attrs = []) {
+ const attrsStr = attrs.join(',');
+ return this.http
+ .get(`${this.apiPath}?attrs=${attrsStr}`)
+ .toPromise()
+ .then((resp: any) => {
+ return resp;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.spec.ts
new file mode 100644
index 00000000..93e3c43c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.spec.ts
@@ -0,0 +1,238 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { AlertmanagerNotification } from '../models/prometheus-alerts';
+import { PrometheusService } from './prometheus.service';
+import { SettingsService } from './settings.service';
+
+describe('PrometheusService', () => {
+ let service: PrometheusService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [PrometheusService, SettingsService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(PrometheusService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should get alerts', () => {
+ service.getAlerts().subscribe();
+ const req = httpTesting.expectOne('api/prometheus');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should get silences', () => {
+ service.getSilences().subscribe();
+ const req = httpTesting.expectOne('api/prometheus/silences');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should set a silence', () => {
+ const silence = {
+ id: 'someId',
+ matchers: [
+ {
+ name: 'getZero',
+ value: 0,
+ isRegex: false
+ }
+ ],
+ startsAt: '2019-01-25T14:32:46.646300974Z',
+ endsAt: '2019-01-25T18:32:46.646300974Z',
+ createdBy: 'someCreator',
+ comment: 'for testing purpose'
+ };
+ service.setSilence(silence).subscribe();
+ const req = httpTesting.expectOne('api/prometheus/silence');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(silence);
+ });
+
+ it('should expire a silence', () => {
+ service.expireSilence('someId').subscribe();
+ const req = httpTesting.expectOne('api/prometheus/silence/someId');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call getNotificationSince without a notification', () => {
+ service.getNotifications().subscribe();
+ const req = httpTesting.expectOne('api/prometheus/notifications?from=last');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getNotificationSince with notification', () => {
+ service.getNotifications({ id: '42' } as AlertmanagerNotification).subscribe();
+ const req = httpTesting.expectOne('api/prometheus/notifications?from=42');
+ expect(req.request.method).toBe('GET');
+ });
+
+ describe('test getRules()', () => {
+ let data: {}; // Subset of PrometheusRuleGroup to keep the tests concise.
+
+ beforeEach(() => {
+ data = {
+ groups: [
+ {
+ name: 'test',
+ rules: [
+ {
+ name: 'load_0',
+ type: 'alerting'
+ },
+ {
+ name: 'load_1',
+ type: 'alerting'
+ },
+ {
+ name: 'load_2',
+ type: 'alerting'
+ }
+ ]
+ },
+ {
+ name: 'recording_rule',
+ rules: [
+ {
+ name: 'node_memory_MemUsed_percent',
+ type: 'recording'
+ }
+ ]
+ }
+ ]
+ };
+ });
+
+ it('should get rules without applying filters', () => {
+ service.getRules().subscribe((rules) => {
+ expect(rules).toEqual(data);
+ });
+
+ const req = httpTesting.expectOne('api/prometheus/rules');
+ expect(req.request.method).toBe('GET');
+ req.flush(data);
+ });
+
+ it('should get rewrite rules only', () => {
+ service.getRules('rewrites').subscribe((rules) => {
+ expect(rules).toEqual({
+ groups: [{ name: 'test', rules: [] }, { name: 'recording_rule', rules: [] }]
+ });
+ });
+
+ const req = httpTesting.expectOne('api/prometheus/rules');
+ expect(req.request.method).toBe('GET');
+ req.flush(data);
+ });
+
+ it('should get alerting rules only', () => {
+ service.getRules('alerting').subscribe((rules) => {
+ expect(rules).toEqual({
+ groups: [
+ {
+ name: 'test',
+ rules: [
+ { name: 'load_0', type: 'alerting' },
+ { name: 'load_1', type: 'alerting' },
+ { name: 'load_2', type: 'alerting' }
+ ]
+ },
+ { name: 'recording_rule', rules: [] }
+ ]
+ });
+ });
+
+ const req = httpTesting.expectOne('api/prometheus/rules');
+ expect(req.request.method).toBe('GET');
+ req.flush(data);
+ });
+ });
+
+ describe('ifAlertmanagerConfigured', () => {
+ let x: any;
+ let host;
+
+ const receiveConfig = () => {
+ const req = httpTesting.expectOne('api/settings/alertmanager-api-host');
+ expect(req.request.method).toBe('GET');
+ req.flush({ value: host });
+ };
+
+ beforeEach(() => {
+ x = false;
+ TestBed.get(SettingsService)['settings'] = {};
+ service.ifAlertmanagerConfigured((v) => (x = v), () => (x = []));
+ host = 'http://localhost:9093';
+ });
+
+ it('changes x in a valid case', () => {
+ expect(x).toBe(false);
+ receiveConfig();
+ expect(x).toBe(host);
+ });
+
+ it('does changes x an empty array in a invalid case', () => {
+ host = '';
+ receiveConfig();
+ expect(x).toEqual([]);
+ });
+
+ it('disables the set setting', () => {
+ receiveConfig();
+ service.disableAlertmanagerConfig();
+ x = false;
+ service.ifAlertmanagerConfigured((v) => (x = v));
+ expect(x).toBe(false);
+ });
+ });
+
+ describe('ifPrometheusConfigured', () => {
+ let x: any;
+ let host;
+
+ const receiveConfig = () => {
+ const req = httpTesting.expectOne('api/settings/prometheus-api-host');
+ expect(req.request.method).toBe('GET');
+ req.flush({ value: host });
+ };
+
+ beforeEach(() => {
+ x = false;
+ TestBed.get(SettingsService)['settings'] = {};
+ service.ifPrometheusConfigured((v) => (x = v), () => (x = []));
+ host = 'http://localhost:9090';
+ });
+
+ it('changes x in a valid case', () => {
+ expect(x).toBe(false);
+ receiveConfig();
+ expect(x).toBe(host);
+ });
+
+ it('does changes x an empty array in a invalid case', () => {
+ host = '';
+ receiveConfig();
+ expect(x).toEqual([]);
+ });
+
+ it('disables the set setting', () => {
+ receiveConfig();
+ service.disablePrometheusConfig();
+ x = false;
+ service.ifPrometheusConfigured((v) => (x = v));
+ expect(x).toBe(false);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.ts
new file mode 100644
index 00000000..0c8f2ff0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/prometheus.service.ts
@@ -0,0 +1,92 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+import { AlertmanagerSilence } from '../models/alertmanager-silence';
+import {
+ AlertmanagerAlert,
+ AlertmanagerNotification,
+ PrometheusRuleGroup
+} from '../models/prometheus-alerts';
+import { ApiModule } from './api.module';
+import { SettingsService } from './settings.service';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class PrometheusService {
+ private baseURL = 'api/prometheus';
+ private settingsKey = {
+ alertmanager: 'api/settings/alertmanager-api-host',
+ prometheus: 'api/settings/prometheus-api-host'
+ };
+
+ constructor(private http: HttpClient, private settingsService: SettingsService) {}
+
+ ifAlertmanagerConfigured(fn, elseFn?): void {
+ this.settingsService.ifSettingConfigured(this.settingsKey.alertmanager, fn, elseFn);
+ }
+
+ disableAlertmanagerConfig(): void {
+ this.settingsService.disableSetting(this.settingsKey.alertmanager);
+ }
+
+ ifPrometheusConfigured(fn, elseFn?): void {
+ this.settingsService.ifSettingConfigured(this.settingsKey.prometheus, fn, elseFn);
+ }
+
+ disablePrometheusConfig(): void {
+ this.settingsService.disableSetting(this.settingsKey.prometheus);
+ }
+
+ getAlerts(params = {}): Observable<AlertmanagerAlert[]> {
+ return this.http.get<AlertmanagerAlert[]>(this.baseURL, { params });
+ }
+
+ getSilences(params = {}): Observable<AlertmanagerSilence[]> {
+ return this.http.get<AlertmanagerSilence[]>(`${this.baseURL}/silences`, { params });
+ }
+
+ getRules(
+ type: 'all' | 'alerting' | 'rewrites' = 'all'
+ ): Observable<{ groups: PrometheusRuleGroup[] }> {
+ let rules = this.http.get<{ groups: PrometheusRuleGroup[] }>(`${this.baseURL}/rules`);
+ const filterByType = (_type: 'alerting' | 'rewrites') => {
+ return rules.pipe(
+ map((_rules) => {
+ _rules.groups = _rules.groups.map((group) => {
+ group.rules = group.rules.filter((rule) => rule.type === _type);
+ return group;
+ });
+ return _rules;
+ })
+ );
+ };
+ switch (type) {
+ case 'alerting':
+ case 'rewrites':
+ rules = filterByType(type);
+ break;
+ }
+ return rules;
+ }
+
+ setSilence(silence: AlertmanagerSilence) {
+ return this.http.post(`${this.baseURL}/silence`, silence, { observe: 'response' });
+ }
+
+ expireSilence(silenceId: string) {
+ return this.http.delete(`${this.baseURL}/silence/${silenceId}`, { observe: 'response' });
+ }
+
+ getNotifications(
+ notification?: AlertmanagerNotification
+ ): Observable<AlertmanagerNotification[]> {
+ const url = `${this.baseURL}/notifications?from=${
+ notification && notification.id ? notification.id : 'last'
+ }`;
+ return this.http.get<AlertmanagerNotification[]>(url);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.spec.ts
new file mode 100644
index 00000000..cc4b7d31
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.spec.ts
@@ -0,0 +1,130 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { RbdMirroringService } from './rbd-mirroring.service';
+
+describe('RbdMirroringService', () => {
+ let service: RbdMirroringService;
+ let httpTesting: HttpTestingController;
+
+ const summary = {
+ status: 0,
+ content_data: {
+ daemons: [],
+ pools: [],
+ image_error: [],
+ image_syncing: [],
+ image_ready: []
+ },
+ executing_tasks: [{}]
+ };
+
+ configureTestBed(
+ {
+ providers: [RbdMirroringService],
+ imports: [HttpClientTestingModule]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ service = TestBed.get(RbdMirroringService);
+ httpTesting = TestBed.get(HttpTestingController);
+
+ const req = httpTesting.expectOne('api/block/mirroring/summary');
+ expect(req.request.method).toBe('GET');
+ req.flush(summary);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should periodically poll summary', fakeAsync(() => {
+ const calledWith = [];
+ service.subscribeSummary((data) => {
+ calledWith.push(data);
+ });
+ service.refreshAndSchedule();
+ tick(30000);
+ // In order to not trigger setTimeout again,
+ // which would raise 'Error: 1 timer(s) still in the queue.'
+ spyOn(service, 'refreshAndSchedule').and.callFake(() => true);
+ tick(30000);
+
+ const calls = httpTesting.match((request) => {
+ return request.url.match(/api\/block\/mirroring\/summary/) && request.method === 'GET';
+ });
+
+ expect(calls.length).toEqual(2);
+ calls.forEach((call) => call.flush(summary));
+
+ expect(calledWith).toEqual([summary, summary, summary]);
+ }));
+
+ it('should get current summary', () => {
+ expect(service.getCurrentSummary()).toEqual(summary);
+ });
+
+ it('should get pool config', () => {
+ service.getPool('poolName').subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should update pool config', () => {
+ const request = {
+ mirror_mode: 'pool'
+ };
+ service.updatePool('poolName', request).subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual(request);
+ });
+
+ it('should get peer config', () => {
+ service.getPeer('poolName', 'peerUUID').subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName/peer/peerUUID');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should add peer config', () => {
+ const request = {
+ cluster_name: 'remote',
+ client_id: 'admin',
+ mon_host: 'localhost',
+ key: '1234'
+ };
+ service.addPeer('poolName', request).subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName/peer');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(request);
+ });
+
+ it('should update peer config', () => {
+ const request = {
+ cluster_name: 'remote'
+ };
+ service.updatePeer('poolName', 'peerUUID', request).subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName/peer/peerUUID');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual(request);
+ });
+
+ it('should delete peer config', () => {
+ service.deletePeer('poolName', 'peerUUID').subscribe();
+
+ const req = httpTesting.expectOne('api/block/mirroring/pool/poolName/peer/peerUUID');
+ expect(req.request.method).toBe('DELETE');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.ts
new file mode 100644
index 00000000..2f3626c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd-mirroring.service.ts
@@ -0,0 +1,84 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable, NgZone } from '@angular/core';
+
+import { BehaviorSubject, Subscription } from 'rxjs';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class RbdMirroringService {
+ // Observable sources
+ private summaryDataSource = new BehaviorSubject(null);
+
+ // Observable streams
+ summaryData$ = this.summaryDataSource.asObservable();
+
+ constructor(private http: HttpClient, private ngZone: NgZone) {
+ this.refreshAndSchedule();
+ }
+
+ refresh() {
+ this.http.get('api/block/mirroring/summary').subscribe((data) => {
+ this.summaryDataSource.next(data);
+ });
+ }
+
+ refreshAndSchedule() {
+ this.refresh();
+
+ this.ngZone.runOutsideAngular(() => {
+ setTimeout(() => {
+ this.ngZone.run(() => {
+ this.refreshAndSchedule();
+ });
+ }, 30000);
+ });
+ }
+
+ /**
+ * Returns the current value of summaryData
+ */
+ getCurrentSummary(): { [key: string]: any; executing_tasks: object[] } {
+ return this.summaryDataSource.getValue();
+ }
+
+ /**
+ * Subscribes to the summaryData,
+ * which is updated once every 30 seconds or when a new task is created.
+ */
+ subscribeSummary(next: (summary: any) => void, error?: (error: any) => void): Subscription {
+ return this.summaryData$.subscribe(next, error);
+ }
+
+ getPool(poolName) {
+ return this.http.get(`api/block/mirroring/pool/${poolName}`);
+ }
+
+ updatePool(poolName, request) {
+ return this.http.put(`api/block/mirroring/pool/${poolName}`, request, { observe: 'response' });
+ }
+
+ getPeer(poolName, peerUUID) {
+ return this.http.get(`api/block/mirroring/pool/${poolName}/peer/${peerUUID}`);
+ }
+
+ addPeer(poolName, request) {
+ return this.http.post(`api/block/mirroring/pool/${poolName}/peer`, request, {
+ observe: 'response'
+ });
+ }
+
+ updatePeer(poolName, peerUUID, request) {
+ return this.http.put(`api/block/mirroring/pool/${poolName}/peer/${peerUUID}`, request, {
+ observe: 'response'
+ });
+ }
+
+ deletePeer(poolName, peerUUID) {
+ return this.http.delete(`api/block/mirroring/pool/${poolName}/peer/${peerUUID}`, {
+ observe: 'response'
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.model.ts
new file mode 100644
index 00000000..af646d8a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.model.ts
@@ -0,0 +1,29 @@
+import { RbdConfigurationEntry } from '../models/configuration';
+
+export interface RbdPool {
+ pool_name: string;
+ status: number;
+ value: RbdImage[];
+}
+
+export interface RbdImage {
+ disk_usage: number;
+ stripe_unit: number;
+ name: string;
+ parent: any;
+ pool_name: string;
+ num_objs: number;
+ block_name_prefix: string;
+ snapshots: any[];
+ obj_size: number;
+ data_pool: string;
+ total_disk_usage: number;
+ features: number;
+ configuration: RbdConfigurationEntry[];
+ timestamp: string;
+ id: string;
+ features_name: string[];
+ stripe_count: number;
+ order: number;
+ size: number;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.spec.ts
new file mode 100644
index 00000000..b09fec66
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.spec.ts
@@ -0,0 +1,137 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { RbdConfigurationService } from '../services/rbd-configuration.service';
+import { RbdService } from './rbd.service';
+
+describe('RbdService', () => {
+ let service: RbdService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [RbdService, RbdConfigurationService, i18nProviders],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RbdService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call create', () => {
+ service.create('foo').subscribe();
+ const req = httpTesting.expectOne('api/block/image');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual('foo');
+ });
+
+ it('should call delete', () => {
+ service.delete('poolName', 'rbdName').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call update', () => {
+ service.update('poolName', 'rbdName', 'foo').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName');
+ expect(req.request.body).toEqual('foo');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call get', () => {
+ service.get('poolName', 'rbdName').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/block/image');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call copy', () => {
+ service.copy('poolName', 'rbdName', 'foo').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/copy');
+ expect(req.request.body).toEqual('foo');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call flatten', () => {
+ service.flatten('poolName', 'rbdName').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/flatten');
+ expect(req.request.body).toEqual(null);
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call defaultFeatures', () => {
+ service.defaultFeatures().subscribe();
+ const req = httpTesting.expectOne('api/block/image/default_features');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call createSnapshot', () => {
+ service.createSnapshot('poolName', 'rbdName', 'snapshotName').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap');
+ expect(req.request.body).toEqual({
+ snapshot_name: 'snapshotName'
+ });
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call renameSnapshot', () => {
+ service.renameSnapshot('poolName', 'rbdName', 'snapshotName', 'foo').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap/snapshotName');
+ expect(req.request.body).toEqual({
+ new_snap_name: 'foo'
+ });
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call protectSnapshot', () => {
+ service.protectSnapshot('poolName', 'rbdName', 'snapshotName', true).subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap/snapshotName');
+ expect(req.request.body).toEqual({
+ is_protected: true
+ });
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call rollbackSnapshot', () => {
+ service.rollbackSnapshot('poolName', 'rbdName', 'snapshotName').subscribe();
+ const req = httpTesting.expectOne(
+ 'api/block/image/poolName/rbdName/snap/snapshotName/rollback'
+ );
+ expect(req.request.body).toEqual(null);
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call cloneSnapshot', () => {
+ service.cloneSnapshot('poolName', 'rbdName', 'snapshotName', null).subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap/snapshotName/clone');
+ expect(req.request.body).toEqual(null);
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call deleteSnapshot', () => {
+ service.deleteSnapshot('poolName', 'rbdName', 'snapshotName').subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/snap/snapshotName');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call moveTrash', () => {
+ service.moveTrash('poolName', 'rbdName', 1).subscribe();
+ const req = httpTesting.expectOne('api/block/image/poolName/rbdName/move_trash');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual({ delay: 1 });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.ts
new file mode 100644
index 00000000..110d7ff2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rbd.service.ts
@@ -0,0 +1,150 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { map } from 'rxjs/operators';
+
+import { cdEncode, cdEncodeNot } from '../decorators/cd-encode';
+import { RbdConfigurationService } from '../services/rbd-configuration.service';
+import { ApiModule } from './api.module';
+import { RbdPool } from './rbd.model';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class RbdService {
+ constructor(private http: HttpClient, private rbdConfigurationService: RbdConfigurationService) {}
+
+ create(rbd) {
+ return this.http.post('api/block/image', rbd, { observe: 'response' });
+ }
+
+ delete(poolName, rbdName) {
+ return this.http.delete(`api/block/image/${poolName}/${rbdName}`, { observe: 'response' });
+ }
+
+ update(poolName, rbdName, rbd) {
+ return this.http.put(`api/block/image/${poolName}/${rbdName}`, rbd, { observe: 'response' });
+ }
+
+ get(poolName, rbdName) {
+ return this.http.get(`api/block/image/${poolName}/${rbdName}`);
+ }
+
+ list() {
+ return this.http.get<RbdPool[]>('api/block/image').pipe(
+ map((pools) =>
+ pools.map((pool) => {
+ pool.value.map((image) => {
+ if (!image.configuration) {
+ return image;
+ }
+ image.configuration.map((option) =>
+ Object.assign(option, this.rbdConfigurationService.getOptionByName(option.name))
+ );
+ return image;
+ });
+ return pool;
+ })
+ )
+ );
+ }
+
+ copy(poolName, rbdName, rbd) {
+ return this.http.post(`api/block/image/${poolName}/${rbdName}/copy`, rbd, {
+ observe: 'response'
+ });
+ }
+
+ flatten(poolName, rbdName) {
+ return this.http.post(`api/block/image/${poolName}/${rbdName}/flatten`, null, {
+ observe: 'response'
+ });
+ }
+
+ defaultFeatures() {
+ return this.http.get('api/block/image/default_features');
+ }
+
+ createSnapshot(poolName, rbdName, @cdEncodeNot snapshotName) {
+ const request = {
+ snapshot_name: snapshotName
+ };
+ return this.http.post(`api/block/image/${poolName}/${rbdName}/snap`, request, {
+ observe: 'response'
+ });
+ }
+
+ renameSnapshot(poolName, rbdName, snapshotName, @cdEncodeNot newSnapshotName) {
+ const request = {
+ new_snap_name: newSnapshotName
+ };
+ return this.http.put(`api/block/image/${poolName}/${rbdName}/snap/${snapshotName}`, request, {
+ observe: 'response'
+ });
+ }
+
+ protectSnapshot(poolName, rbdName, snapshotName, @cdEncodeNot isProtected) {
+ const request = {
+ is_protected: isProtected
+ };
+ return this.http.put(`api/block/image/${poolName}/${rbdName}/snap/${snapshotName}`, request, {
+ observe: 'response'
+ });
+ }
+
+ rollbackSnapshot(poolName, rbdName, snapshotName) {
+ return this.http.post(
+ `api/block/image/${poolName}/${rbdName}/snap/${snapshotName}/rollback`,
+ null,
+ { observe: 'response' }
+ );
+ }
+
+ cloneSnapshot(poolName, rbdName, snapshotName, request) {
+ return this.http.post(
+ `api/block/image/${poolName}/${rbdName}/snap/${snapshotName}/clone`,
+ request,
+ { observe: 'response' }
+ );
+ }
+
+ deleteSnapshot(poolName, rbdName, snapshotName) {
+ return this.http.delete(`api/block/image/${poolName}/${rbdName}/snap/${snapshotName}`, {
+ observe: 'response'
+ });
+ }
+
+ listTrash() {
+ return this.http.get(`api/block/image/trash/`);
+ }
+
+ moveTrash(poolName, rbdName, delay) {
+ return this.http.post(
+ `api/block/image/${poolName}/${rbdName}/move_trash`,
+ { delay: delay },
+ { observe: 'response' }
+ );
+ }
+
+ purgeTrash(poolName) {
+ return this.http.post(`api/block/image/trash/purge/?pool_name=${poolName}`, null, {
+ observe: 'response'
+ });
+ }
+
+ restoreTrash(poolName, imageId, @cdEncodeNot newImageName) {
+ return this.http.post(
+ `api/block/image/trash/${poolName}/${imageId}/restore`,
+ { new_image_name: newImageName },
+ { observe: 'response' }
+ );
+ }
+
+ removeTrash(poolName, imageId, imageName, force = false) {
+ return this.http.delete(
+ `api/block/image/trash/${poolName}/${imageId}/?image_name=${imageName}&force=${force}`,
+ { observe: 'response' }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts
new file mode 100644
index 00000000..9951dfeb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts
@@ -0,0 +1,75 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { RgwBucketService } from './rgw-bucket.service';
+
+describe('RgwBucketService', () => {
+ let service: RgwBucketService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [RgwBucketService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RgwBucketService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket?stats=true');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ service.get('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket/foo');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call create', () => {
+ service.create('foo', 'bar').subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket?bucket=foo&uid=bar');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call update', () => {
+ service.update('foo', 'bar', 'baz').subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket/foo?bucket_id=bar&uid=baz');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call delete, with purgeObjects = true', () => {
+ service.delete('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket/foo?purge_objects=true');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call delete, with purgeObjects = false', () => {
+ service.delete('foo', false).subscribe();
+ const req = httpTesting.expectOne('api/rgw/bucket/foo?purge_objects=false');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call exists', () => {
+ let result;
+ service.exists('foo').subscribe((resp) => {
+ result = resp;
+ });
+ const req = httpTesting.expectOne('api/rgw/bucket');
+ expect(req.request.method).toBe('GET');
+ req.flush(['foo', 'bar']);
+ expect(result).toBe(true);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts
new file mode 100644
index 00000000..b23b1999
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts
@@ -0,0 +1,75 @@
+import { HttpClient, HttpParams } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+import { of as observableOf } from 'rxjs';
+import { mergeMap } from 'rxjs/operators';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class RgwBucketService {
+ private url = 'api/rgw/bucket';
+
+ constructor(private http: HttpClient) {}
+
+ /**
+ * Get the list of buckets.
+ * @return {Observable<Object[]>}
+ */
+ list() {
+ let params = new HttpParams();
+ params = params.append('stats', 'true');
+ return this.http.get(this.url, { params: params });
+ }
+
+ /**
+ * Get the list of bucket names.
+ * @return {Observable<string[]>}
+ */
+ enumerate() {
+ return this.http.get(this.url);
+ }
+
+ get(bucket: string) {
+ return this.http.get(`${this.url}/${bucket}`);
+ }
+
+ create(bucket: string, uid: string) {
+ let params = new HttpParams();
+ params = params.append('bucket', bucket);
+ params = params.append('uid', uid);
+ return this.http.post(this.url, null, { params: params });
+ }
+
+ update(bucket: string, bucketId: string, uid: string) {
+ let params = new HttpParams();
+ params = params.append('bucket_id', bucketId);
+ params = params.append('uid', uid);
+ return this.http.put(`${this.url}/${bucket}`, null, { params: params });
+ }
+
+ delete(bucket: string, purgeObjects = true) {
+ let params = new HttpParams();
+ params = params.append('purge_objects', purgeObjects ? 'true' : 'false');
+ return this.http.delete(`${this.url}/${bucket}`, { params: params });
+ }
+
+ /**
+ * Check if the specified bucket exists.
+ * @param {string} uid The bucket name to check.
+ * @return {Observable<boolean>}
+ */
+ exists(bucket: string) {
+ return this.enumerate().pipe(
+ mergeMap((resp: string[]) => {
+ const index = _.indexOf(resp, bucket);
+ return observableOf(-1 !== index);
+ })
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.spec.ts
new file mode 100644
index 00000000..b866333f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.spec.ts
@@ -0,0 +1,40 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { RgwDaemonService } from './rgw-daemon.service';
+
+describe('RgwDaemonService', () => {
+ let service: RgwDaemonService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [RgwDaemonService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RgwDaemonService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/rgw/daemon');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ service.get('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/daemon/foo');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.ts
new file mode 100644
index 00000000..9dde8ea7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-daemon.service.ts
@@ -0,0 +1,23 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class RgwDaemonService {
+ private url = 'api/rgw/daemon';
+
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get(this.url);
+ }
+
+ get(id: string) {
+ return this.http.get(`${this.url}/${id}`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.spec.ts
new file mode 100644
index 00000000..b33c2011
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.spec.ts
@@ -0,0 +1,156 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { of as observableOf, throwError } from 'rxjs';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { RgwUserService } from './rgw-user.service';
+
+describe('RgwUserService', () => {
+ let service: RgwUserService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ providers: [RgwUserService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RgwUserService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list with empty result', () => {
+ let result;
+ service.list().subscribe((resp) => {
+ result = resp;
+ });
+ const req = httpTesting.expectOne('api/rgw/user');
+ expect(req.request.method).toBe('GET');
+ req.flush([]);
+ expect(result).toEqual([]);
+ });
+
+ it('should call list with result', () => {
+ let result;
+ service.list().subscribe((resp) => {
+ result = resp;
+ });
+
+ let req = httpTesting.expectOne('api/rgw/user');
+ expect(req.request.method).toBe('GET');
+ req.flush(['foo', 'bar']);
+
+ req = httpTesting.expectOne('api/rgw/user/foo');
+ expect(req.request.method).toBe('GET');
+ req.flush({ name: 'foo' });
+
+ req = httpTesting.expectOne('api/rgw/user/bar');
+ expect(req.request.method).toBe('GET');
+ req.flush({ name: 'bar' });
+
+ expect(result).toEqual([{ name: 'foo' }, { name: 'bar' }]);
+ });
+
+ it('should call enumerate', () => {
+ service.enumerate().subscribe();
+ const req = httpTesting.expectOne('api/rgw/user');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call get', () => {
+ service.get('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call getQuota', () => {
+ service.getQuota('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/quota');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call update', () => {
+ service.update('foo', { xxx: 'yyy' }).subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo?xxx=yyy');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call updateQuota', () => {
+ service.updateQuota('foo', { xxx: 'yyy' }).subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/quota?xxx=yyy');
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call create', () => {
+ service.create({ foo: 'bar' }).subscribe();
+ const req = httpTesting.expectOne('api/rgw/user?foo=bar');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call delete', () => {
+ service.delete('foo').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call createSubuser', () => {
+ service.createSubuser('foo', { xxx: 'yyy' }).subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/subuser?xxx=yyy');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call deleteSubuser', () => {
+ service.deleteSubuser('foo', 'bar').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/subuser/bar');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call addCapability', () => {
+ service.addCapability('foo', 'bar', 'baz').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/capability?type=bar&perm=baz');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call deleteCapability', () => {
+ service.deleteCapability('foo', 'bar', 'baz').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/capability?type=bar&perm=baz');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call addS3Key', () => {
+ service.addS3Key('foo', { xxx: 'yyy' }).subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/key?key_type=s3&xxx=yyy');
+ expect(req.request.method).toBe('POST');
+ });
+
+ it('should call deleteS3Key', () => {
+ service.deleteS3Key('foo', 'bar').subscribe();
+ const req = httpTesting.expectOne('api/rgw/user/foo/key?key_type=s3&access_key=bar');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call exists with an existent uid', (done) => {
+ spyOn(service, 'get').and.returnValue(observableOf({}));
+ service.exists('foo').subscribe((res) => {
+ expect(res).toBe(true);
+ done();
+ });
+ });
+
+ it('should call exists with a non existent uid', (done) => {
+ spyOn(service, 'get').and.returnValue(throwError('bar'));
+ service.exists('baz').subscribe((res) => {
+ expect(res).toBe(false);
+ done();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.ts
new file mode 100644
index 00000000..322aa503
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-user.service.ts
@@ -0,0 +1,159 @@
+import { HttpClient, HttpParams } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+import { forkJoin as observableForkJoin, Observable, of as observableOf } from 'rxjs';
+import { catchError, mapTo, mergeMap } from 'rxjs/operators';
+
+import { cdEncode } from '../decorators/cd-encode';
+import { ApiModule } from './api.module';
+
+@cdEncode
+@Injectable({
+ providedIn: ApiModule
+})
+export class RgwUserService {
+ private url = 'api/rgw/user';
+
+ constructor(private http: HttpClient) {}
+
+ /**
+ * Get the list of users.
+ * @return {Observable<Object[]>}
+ */
+ list() {
+ return this.enumerate().pipe(
+ mergeMap((uids: string[]) => {
+ if (uids.length > 0) {
+ return observableForkJoin(
+ uids.map((uid: string) => {
+ return this.get(uid);
+ })
+ );
+ }
+ return observableOf([]);
+ })
+ );
+ }
+
+ /**
+ * Get the list of usernames.
+ * @return {Observable<string[]>}
+ */
+ enumerate() {
+ return this.http.get(this.url);
+ }
+
+ enumerateEmail() {
+ return this.http.get(`${this.url}/get_emails`);
+ }
+
+ get(uid: string) {
+ return this.http.get(`${this.url}/${uid}`);
+ }
+
+ getQuota(uid: string) {
+ return this.http.get(`${this.url}/${uid}/quota`);
+ }
+
+ create(args: Record<string, any>) {
+ let params = new HttpParams();
+ _.keys(args).forEach((key) => {
+ params = params.append(key, args[key]);
+ });
+ return this.http.post(this.url, null, { params: params });
+ }
+
+ update(uid: string, args: Record<string, any>) {
+ let params = new HttpParams();
+ _.keys(args).forEach((key) => {
+ params = params.append(key, args[key]);
+ });
+ return this.http.put(`${this.url}/${uid}`, null, { params: params });
+ }
+
+ updateQuota(uid: string, args: object) {
+ let params = new HttpParams();
+ _.keys(args).forEach((key) => {
+ params = params.append(key, args[key]);
+ });
+ return this.http.put(`${this.url}/${uid}/quota`, null, { params: params });
+ }
+
+ delete(uid: string) {
+ return this.http.delete(`${this.url}/${uid}`);
+ }
+
+ createSubuser(uid: string, args: object) {
+ let params = new HttpParams();
+ _.keys(args).forEach((key) => {
+ params = params.append(key, args[key]);
+ });
+ return this.http.post(`${this.url}/${uid}/subuser`, null, { params: params });
+ }
+
+ deleteSubuser(uid: string, subuser: string) {
+ return this.http.delete(`${this.url}/${uid}/subuser/${subuser}`);
+ }
+
+ addCapability(uid: string, type: string, perm: string) {
+ let params = new HttpParams();
+ params = params.append('type', type);
+ params = params.append('perm', perm);
+ return this.http.post(`${this.url}/${uid}/capability`, null, { params: params });
+ }
+
+ deleteCapability(uid: string, type: string, perm: string) {
+ let params = new HttpParams();
+ params = params.append('type', type);
+ params = params.append('perm', perm);
+ return this.http.delete(`${this.url}/${uid}/capability`, { params: params });
+ }
+
+ addS3Key(uid: string, args: object) {
+ let params = new HttpParams();
+ params = params.append('key_type', 's3');
+ _.keys(args).forEach((key) => {
+ params = params.append(key, args[key]);
+ });
+ return this.http.post(`${this.url}/${uid}/key`, null, { params: params });
+ }
+
+ deleteS3Key(uid: string, accessKey: string) {
+ let params = new HttpParams();
+ params = params.append('key_type', 's3');
+ params = params.append('access_key', accessKey);
+ return this.http.delete(`${this.url}/${uid}/key`, { params: params });
+ }
+
+ /**
+ * Check if the specified user ID exists.
+ * @param {string} uid The user ID to check.
+ * @return {Observable<boolean>}
+ */
+ exists(uid: string): Observable<boolean> {
+ return this.get(uid).pipe(
+ mapTo(true),
+ catchError((error: Event) => {
+ if (_.isFunction(error.preventDefault)) {
+ error.preventDefault();
+ }
+ return observableOf(false);
+ })
+ );
+ }
+
+ // Using @cdEncodeNot would be the preferred way here, but this
+ // causes an error: https://tracker.ceph.com/issues/37505
+ // Use decodeURIComponent as workaround.
+ // emailExists(@cdEncodeNot email: string): Observable<boolean> {
+ emailExists(email: string): Observable<boolean> {
+ email = decodeURIComponent(email);
+ return this.enumerateEmail().pipe(
+ mergeMap((resp: any[]) => {
+ const index = _.indexOf(resp, email);
+ return observableOf(-1 !== index);
+ })
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.spec.ts
new file mode 100644
index 00000000..d3290157
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.spec.ts
@@ -0,0 +1,68 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { RoleService } from './role.service';
+
+describe('RoleService', () => {
+ let service: RoleService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [RoleService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RoleService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/role');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call delete', () => {
+ service.delete('role1').subscribe();
+ const req = httpTesting.expectOne('api/role/role1');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call get', () => {
+ service.get('role1').subscribe();
+ const req = httpTesting.expectOne('api/role/role1');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should check if role name exists', () => {
+ let exists: boolean;
+ service.exists('role1').subscribe((res: boolean) => {
+ exists = res;
+ });
+ const req = httpTesting.expectOne('api/role');
+ expect(req.request.method).toBe('GET');
+ req.flush([{ name: 'role0' }, { name: 'role1' }]);
+ expect(exists).toBeTruthy();
+ });
+
+ it('should check if role name does not exist', () => {
+ let exists: boolean;
+ service.exists('role2').subscribe((res: boolean) => {
+ exists = res;
+ });
+ const req = httpTesting.expectOne('api/role');
+ expect(req.request.method).toBe('GET');
+ req.flush([{ name: 'role0' }, { name: 'role1' }]);
+ expect(exists).toBeFalsy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.ts
new file mode 100644
index 00000000..974ee5af
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/role.service.ts
@@ -0,0 +1,46 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable, of as observableOf } from 'rxjs';
+import { mergeMap } from 'rxjs/operators';
+
+import { RoleFormModel } from '../../core/auth/role-form/role-form.model';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class RoleService {
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get('api/role');
+ }
+
+ delete(role: string) {
+ return this.http.delete(`api/role/${role}`);
+ }
+
+ get(name) {
+ return this.http.get(`api/role/${name}`);
+ }
+
+ create(role: RoleFormModel) {
+ return this.http.post(`api/role`, role);
+ }
+
+ update(role: RoleFormModel) {
+ return this.http.put(`api/role/${role.name}`, role);
+ }
+
+ exists(name: string): Observable<boolean> {
+ return this.list().pipe(
+ mergeMap((roles: Array<RoleFormModel>) => {
+ const exists = roles.some((currentRole: RoleFormModel) => {
+ return currentRole.name === name;
+ });
+ return observableOf(exists);
+ })
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.spec.ts
new file mode 100644
index 00000000..2016ff50
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.spec.ts
@@ -0,0 +1,34 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { ScopeService } from './scope.service';
+
+describe('ScopeService', () => {
+ let service: ScopeService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [ScopeService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(ScopeService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('ui-api/scope');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.ts
new file mode 100644
index 00000000..8808f212
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/scope.service.ts
@@ -0,0 +1,15 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class ScopeService {
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get('ui-api/scope');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts
new file mode 100644
index 00000000..122f2691
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts
@@ -0,0 +1,128 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { SettingsService } from './settings.service';
+
+describe('SettingsService', () => {
+ let service: SettingsService;
+ let httpTesting: HttpTestingController;
+
+ const exampleUrl = 'api/settings/something';
+ const exampleValue = 'http://localhost:3000';
+
+ configureTestBed(
+ {
+ providers: [SettingsService],
+ imports: [HttpClientTestingModule]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ service = TestBed.get(SettingsService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call validateGrafanaDashboardUrl', () => {
+ service.validateGrafanaDashboardUrl('s').subscribe();
+ const req = httpTesting.expectOne('api/grafana/validation/s');
+ expect(req.request.method).toBe('GET');
+ });
+
+ describe('getSettingsValue', () => {
+ const testMethod = (data, expected: string) => {
+ expect(service['getSettingsValue'](data)).toBe(expected);
+ };
+
+ it('should explain the logic of the method', () => {
+ expect('' || undefined).toBe(undefined);
+ expect(undefined || '').toBe('');
+ expect('test' || undefined || '').toBe('test');
+ });
+
+ it('should test the method for empty string values', () => {
+ testMethod({}, '');
+ testMethod({ wrongAttribute: 'test' }, '');
+ testMethod({ value: '' }, '');
+ testMethod({ instance: '' }, '');
+ });
+
+ it('should test the method for non empty string values', () => {
+ testMethod({ value: 'test' }, 'test');
+ testMethod({ instance: 'test' }, 'test');
+ });
+ });
+
+ describe('isSettingConfigured', () => {
+ let increment: number;
+
+ const testConfig = (url, value) => {
+ service.ifSettingConfigured(
+ url,
+ (setValue) => {
+ expect(setValue).toBe(value);
+ increment++;
+ },
+ () => {
+ increment--;
+ }
+ );
+ };
+
+ const expectSettingsApiCall = (url: string, value: object, isSet: string) => {
+ testConfig(url, isSet);
+ const req = httpTesting.expectOne(url);
+ expect(req.request.method).toBe('GET');
+ req.flush(value);
+ tick();
+ expect(increment).toBe(isSet !== '' ? 1 : -1);
+ expect(service['settings'][url]).toBe(isSet);
+ };
+
+ beforeEach(() => {
+ increment = 0;
+ });
+
+ it(`should return true if 'value' does not contain an empty string`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, { value: exampleValue }, exampleValue);
+ }));
+
+ it(`should return false if 'value' does contain an empty string`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, { value: '' }, '');
+ }));
+
+ it(`should return true if 'instance' does not contain an empty string`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, { value: exampleValue }, exampleValue);
+ }));
+
+ it(`should return false if 'instance' does contain an empty string`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, { instance: '' }, '');
+ }));
+
+ it(`should return false if the api object is empty`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, {}, '');
+ }));
+
+ it(`should call the API once even if it is called multiple times`, fakeAsync(() => {
+ expectSettingsApiCall(exampleUrl, { value: exampleValue }, exampleValue);
+ testConfig(exampleUrl, exampleValue);
+ httpTesting.expectNone(exampleUrl);
+ expect(increment).toBe(2);
+ }));
+ });
+
+ it('should disable a set setting', () => {
+ service['settings'] = { [exampleUrl]: exampleValue };
+ service.disableSetting(exampleUrl);
+ expect(service['settings']).toEqual({ [exampleUrl]: '' });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts
new file mode 100644
index 00000000..9403b576
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts
@@ -0,0 +1,50 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class SettingsService {
+ constructor(private http: HttpClient) {}
+
+ private settings: { [url: string]: string } = {};
+
+ ifSettingConfigured(url: string, fn: (value?: string) => void, elseFn?: () => void): void {
+ const setting = this.settings[url];
+ if (setting === undefined) {
+ this.http.get(url).subscribe(
+ (data: any) => {
+ this.settings[url] = this.getSettingsValue(data);
+ this.ifSettingConfigured(url, fn, elseFn);
+ },
+ (resp) => {
+ if (resp.status !== 401) {
+ this.settings[url] = '';
+ }
+ }
+ );
+ } else if (setting !== '') {
+ fn(setting);
+ } else {
+ if (elseFn) {
+ elseFn();
+ }
+ }
+ }
+
+ // Easiest way to stop reloading external content that can't be reached
+ disableSetting(url) {
+ this.settings[url] = '';
+ }
+
+ private getSettingsValue(data: any): string {
+ return data.value || data.instance || '';
+ }
+
+ validateGrafanaDashboardUrl(uid) {
+ return this.http.get(`api/grafana/validation/${uid}`);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.spec.ts
new file mode 100644
index 00000000..e7a15b8a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.spec.ts
@@ -0,0 +1,73 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { UserFormModel } from '../../core/auth/user-form/user-form.model';
+import { UserService } from './user.service';
+
+describe('UserService', () => {
+ let service: UserService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [UserService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(UserService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call create', () => {
+ const user = new UserFormModel();
+ user.username = 'user0';
+ user.password = 'pass0';
+ user.name = 'User 0';
+ user.email = 'user0@email.com';
+ user.roles = ['administrator'];
+ service.create(user).subscribe();
+ const req = httpTesting.expectOne('api/user');
+ expect(req.request.method).toBe('POST');
+ expect(req.request.body).toEqual(user);
+ });
+
+ it('should call delete', () => {
+ service.delete('user0').subscribe();
+ const req = httpTesting.expectOne('api/user/user0');
+ expect(req.request.method).toBe('DELETE');
+ });
+
+ it('should call update', () => {
+ const user = new UserFormModel();
+ user.username = 'user0';
+ user.password = 'pass0';
+ user.name = 'User 0';
+ user.email = 'user0@email.com';
+ user.roles = ['administrator'];
+ service.update(user).subscribe();
+ const req = httpTesting.expectOne('api/user/user0');
+ expect(req.request.body).toEqual(user);
+ expect(req.request.method).toBe('PUT');
+ });
+
+ it('should call get', () => {
+ service.get('user0').subscribe();
+ const req = httpTesting.expectOne('api/user/user0');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call list', () => {
+ service.list().subscribe();
+ const req = httpTesting.expectOne('api/user');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.ts
new file mode 100644
index 00000000..2643c7c3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/user.service.ts
@@ -0,0 +1,32 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { UserFormModel } from '../../core/auth/user-form/user-form.model';
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class UserService {
+ constructor(private http: HttpClient) {}
+
+ list() {
+ return this.http.get('api/user');
+ }
+
+ delete(username: string) {
+ return this.http.delete(`api/user/${username}`);
+ }
+
+ get(username: string) {
+ return this.http.get(`api/user/${username}`);
+ }
+
+ create(user: UserFormModel) {
+ return this.http.post(`api/user`, user);
+ }
+
+ update(user: UserFormModel) {
+ return this.http.put(`api/user/${user.username}`, user);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.html
new file mode 100644
index 00000000..0d5e50fd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.html
@@ -0,0 +1,6 @@
+&nbsp;
+<button class="btn btn-sm btn-default tc_backButton"
+ (click)="back()"
+ type="button">
+ {{ name }}
+</button>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.spec.ts
new file mode 100644
index 00000000..150e0567
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { BackButtonComponent } from './back-button.component';
+
+describe('BackButtonComponent', () => {
+ let component: BackButtonComponent;
+ let fixture: ComponentFixture<BackButtonComponent>;
+
+ configureTestBed({
+ imports: [RouterTestingModule],
+ declarations: [BackButtonComponent],
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BackButtonComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.ts
new file mode 100644
index 00000000..374099ea
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.ts
@@ -0,0 +1,16 @@
+import { Location } from '@angular/common';
+import { Component, Input } from '@angular/core';
+
+import { ActionLabelsI18n } from '../../constants/app.constants';
+
+@Component({
+ selector: 'cd-back-button',
+ templateUrl: './back-button.component.html',
+ styleUrls: ['./back-button.component.scss']
+})
+export class BackButtonComponent {
+ constructor(private location: Location, private actionLabels: ActionLabelsI18n) {}
+
+ @Input() name: string = this.actionLabels.CANCEL;
+ @Input() back: Function = () => this.location.back();
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts
new file mode 100644
index 00000000..e2ad026e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts
@@ -0,0 +1,92 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
+import { ChartsModule } from 'ng2-charts/ng2-charts';
+import { AlertModule } from 'ngx-bootstrap/alert';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+import { ModalModule } from 'ngx-bootstrap/modal';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { DirectivesModule } from '../directives/directives.module';
+import { PipesModule } from '../pipes/pipes.module';
+import { BackButtonComponent } from './back-button/back-button.component';
+import { ConfigOptionComponent } from './config-option/config-option.component';
+import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from './critical-confirmation-modal/critical-confirmation-modal.component';
+import { ErrorPanelComponent } from './error-panel/error-panel.component';
+import { GrafanaComponent } from './grafana/grafana.component';
+import { HelperComponent } from './helper/helper.component';
+import { InfoPanelComponent } from './info-panel/info-panel.component';
+import { LanguageSelectorComponent } from './language-selector/language-selector.component';
+import { LoadingPanelComponent } from './loading-panel/loading-panel.component';
+import { ModalComponent } from './modal/modal.component';
+import { RefreshSelectorComponent } from './refresh-selector/refresh-selector.component';
+import { SelectBadgesComponent } from './select-badges/select-badges.component';
+import { SelectComponent } from './select/select.component';
+import { SparklineComponent } from './sparkline/sparkline.component';
+import { SubmitButtonComponent } from './submit-button/submit-button.component';
+import { UsageBarComponent } from './usage-bar/usage-bar.component';
+import { ViewCacheComponent } from './view-cache/view-cache.component';
+import { WarningPanelComponent } from './warning-panel/warning-panel.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ ReactiveFormsModule,
+ AlertModule.forRoot(),
+ PopoverModule.forRoot(),
+ TooltipModule.forRoot(),
+ ChartsModule,
+ ReactiveFormsModule,
+ PipesModule,
+ ModalModule.forRoot(),
+ DirectivesModule,
+ BsDropdownModule
+ ],
+ declarations: [
+ ViewCacheComponent,
+ SparklineComponent,
+ HelperComponent,
+ SelectBadgesComponent,
+ SubmitButtonComponent,
+ UsageBarComponent,
+ ErrorPanelComponent,
+ LoadingPanelComponent,
+ InfoPanelComponent,
+ ModalComponent,
+ CriticalConfirmationModalComponent,
+ ConfirmationModalComponent,
+ WarningPanelComponent,
+ LanguageSelectorComponent,
+ GrafanaComponent,
+ SelectComponent,
+ BackButtonComponent,
+ RefreshSelectorComponent,
+ ConfigOptionComponent
+ ],
+ providers: [],
+ exports: [
+ ViewCacheComponent,
+ SparklineComponent,
+ HelperComponent,
+ SelectBadgesComponent,
+ SubmitButtonComponent,
+ BackButtonComponent,
+ ErrorPanelComponent,
+ LoadingPanelComponent,
+ InfoPanelComponent,
+ UsageBarComponent,
+ ModalComponent,
+ WarningPanelComponent,
+ LanguageSelectorComponent,
+ GrafanaComponent,
+ SelectComponent,
+ RefreshSelectorComponent,
+ ConfigOptionComponent
+ ],
+ entryComponents: [ModalComponent, CriticalConfirmationModalComponent, ConfirmationModalComponent]
+})
+export class ComponentsModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.html
new file mode 100644
index 00000000..0db04413
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.html
@@ -0,0 +1,72 @@
+<div [formGroup]="optionsFormGroup">
+ <div *ngFor="let option of options; let last = last">
+ <div class="form-group"
+ [ngClass]="{'has-error': optionsForm.showError(option.name, optionsFormDir)}"
+ *ngIf="option.type === 'bool'">
+ <label class="col-sm-6 control-label"
+ [for]="option.name">
+ {{ option.text }}
+ <br>
+ <span class="text-muted">
+ {{ option.desc }}
+ <cd-helper *ngIf="option.long_desc">
+ {{ option.long_desc }}</cd-helper>
+ </span>
+ </label>
+ <div class="col-sm-6 checkbox-primary checkbox">
+ <input type="checkbox"
+ [id]="option.name"
+ [formControlName]="option.name">
+ <label></label>
+ </div>
+ </div>
+ <div class="form-group"
+ [ngClass]="{'has-error': optionsForm.showError(option.name, optionsFormDir)}"
+ *ngIf="option.type !== 'bool'">
+ <label class="col-sm-6 control-label"
+ [for]="option.name">{{ option.text }}
+ <br>
+ <span class="text-muted">
+ {{ option.desc }}
+ <cd-helper *ngIf="option.long_desc">
+ {{ option.long_desc }}</cd-helper>
+ </span>
+ </label>
+ <div class="col-sm-6">
+ <div class="input-group">
+ <input class="form-control"
+ [type]="option.additionalTypeInfo.inputType"
+ [id]="option.name"
+ [placeholder]="option.additionalTypeInfo.humanReadable"
+ [formControlName]="option.name"
+ [step]="getStep(option.type, optionsForm.getValue(option.name))">
+ <span class="input-group-btn"
+ *ngIf="optionsFormShowReset">
+ <button class="btn btn-default"
+ type="button"
+ data-toggle="button"
+ title="Remove the custom configuration value. The default configuration will be inherited and used instead."
+ (click)="resetValue(option.name)"
+ i18n-title>
+ <i class="fa fa-eraser"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ <span class="help-block"
+ *ngIf="optionsForm.showError(option.name, optionsFormDir, 'pattern')">
+ {{ option.additionalTypeInfo.patternHelpText }}</span>
+ <span class="help-block"
+ *ngIf="optionsForm.showError(option.name, optionsFormDir, 'invalidUuid')">
+ {{ option.additionalTypeInfo.patternHelpText }}</span>
+ <span class="help-block"
+ *ngIf="optionsForm.showError(option.name, optionsFormDir, 'max')"
+ i18n>The entered value is too high! It must not be greater than {{ option.maxValue }}.</span>
+ <span class="help-block"
+ *ngIf="optionsForm.showError(option.name, optionsFormDir, 'min')"
+ i18n>The entered value is too low! It must not be lower than {{ option.minValue }}.</span>
+ </div>
+ </div>
+ <hr *ngIf="!last">
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.scss
new file mode 100644
index 00000000..7c1347ef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.scss
@@ -0,0 +1,30 @@
+hr {
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+.control-label {
+ text-align: left;
+}
+
+.checkbox-primary {
+ input {
+ width: 23px;
+ height: 15px;
+ margin-left: 0;
+ cursor: pointer;
+ }
+ label {
+ &:before,
+ &:after {
+ margin-left: 0;
+ }
+ cursor: auto;
+ }
+}
+
+.form-group {
+ .col-sm-6 {
+ padding-top: 7px;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.spec.ts
new file mode 100644
index 00000000..bc2d1ce3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.spec.ts
@@ -0,0 +1,295 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+
+import * as _ from 'lodash';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ConfigurationService } from '../../api/configuration.service';
+import { CdFormGroup } from '../../forms/cd-form-group';
+import { HelperComponent } from '../helper/helper.component';
+import { ConfigOptionComponent } from './config-option.component';
+
+describe('ConfigOptionComponent', () => {
+ let component: ConfigOptionComponent;
+ let fixture: ComponentFixture<ConfigOptionComponent>;
+ let configurationService: ConfigurationService;
+ let oNames: Array<string>;
+
+ configureTestBed({
+ declarations: [ConfigOptionComponent, HelperComponent],
+ imports: [PopoverModule.forRoot(), ReactiveFormsModule, HttpClientTestingModule],
+ providers: [ConfigurationService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfigOptionComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ configurationService = TestBed.get(ConfigurationService);
+
+ const configOptions = [
+ {
+ name: 'osd_scrub_auto_repair_num_errors',
+ type: 'uint',
+ level: 'advanced',
+ desc: 'Maximum number of detected errors to automatically repair',
+ long_desc: '',
+ default: 5,
+ daemon_default: '',
+ tags: [],
+ services: [],
+ see_also: ['osd_scrub_auto_repair'],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: []
+ },
+ {
+ name: 'osd_debug_deep_scrub_sleep',
+ type: 'float',
+ level: 'dev',
+ desc:
+ 'Inject an expensive sleep during deep scrub IO to make it easier to induce preemption',
+ long_desc: '',
+ default: 0,
+ daemon_default: '',
+ tags: [],
+ services: [],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: []
+ },
+ {
+ name: 'osd_heartbeat_interval',
+ type: 'int',
+ level: 'advanced',
+ desc: 'Interval (in seconds) between peer pings',
+ long_desc: '',
+ default: 6,
+ daemon_default: '',
+ tags: [],
+ services: [],
+ see_also: [],
+ min: 1,
+ max: 86400,
+ can_update_at_runtime: true,
+ flags: [],
+ value: [
+ {
+ section: 'osd',
+ value: 6
+ }
+ ]
+ },
+ {
+ name: 'bluestore_compression_algorithm',
+ type: 'str',
+ level: 'advanced',
+ desc: 'Default compression algorithm to use when writing object data',
+ long_desc:
+ 'This controls the default compressor to use (if any) if the ' +
+ 'per-pool property is not set. Note that zstd is *not* recommended for ' +
+ 'bluestore due to high CPU overhead when compressing small amounts of data.',
+ default: 'snappy',
+ daemon_default: '',
+ tags: [],
+ services: [],
+ see_also: [],
+ enum_values: ['', 'snappy', 'zlib', 'zstd', 'lz4'],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: ['runtime']
+ },
+ {
+ name: 'rbd_discard_on_zeroed_write_same',
+ type: 'bool',
+ level: 'advanced',
+ desc: 'discard data on zeroed write same instead of writing zero',
+ long_desc: '',
+ default: true,
+ daemon_default: '',
+ tags: [],
+ services: ['rbd'],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: []
+ },
+ {
+ name: 'rbd_journal_max_payload_bytes',
+ type: 'size',
+ level: 'advanced',
+ desc: 'maximum journal payload size before splitting',
+ long_desc: '',
+ daemon_default: '',
+ tags: [],
+ services: ['rbd'],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: [],
+ default: '16384'
+ },
+ {
+ name: 'cluster_addr',
+ type: 'addr',
+ level: 'basic',
+ desc: 'cluster-facing address to bind to',
+ long_desc: '',
+ daemon_default: '',
+ tags: ['network'],
+ services: ['osd'],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: false,
+ flags: [],
+ default: '-'
+ },
+ {
+ name: 'fsid',
+ type: 'uuid',
+ level: 'basic',
+ desc: 'cluster fsid (uuid)',
+ long_desc: '',
+ daemon_default: '',
+ tags: ['service'],
+ services: ['common'],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: false,
+ flags: ['no_mon_update'],
+ default: '00000000-0000-0000-0000-000000000000'
+ },
+ {
+ name: 'mgr_tick_period',
+ type: 'secs',
+ level: 'advanced',
+ desc: 'Period in seconds of beacon messages to monitor',
+ long_desc: '',
+ daemon_default: '',
+ tags: [],
+ services: ['mgr'],
+ see_also: [],
+ min: '',
+ max: '',
+ can_update_at_runtime: true,
+ flags: [],
+ default: '2'
+ }
+ ];
+
+ spyOn(configurationService, 'filter').and.returnValue(observableOf(configOptions));
+ oNames = _.map(configOptions, 'name');
+ component.optionNames = oNames;
+ component.optionsForm = new CdFormGroup({});
+ component.optionsFormGroupName = 'testFormGroupName';
+ component.ngOnInit();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('optionNameToText', () => {
+ it('should format config option names correctly', () => {
+ const configOptionNames = {
+ osd_scrub_auto_repair_num_errors: 'Scrub Auto Repair Num Errors',
+ osd_debug_deep_scrub_sleep: 'Debug Deep Scrub Sleep',
+ osd_heartbeat_interval: 'Heartbeat Interval',
+ bluestore_compression_algorithm: 'Bluestore Compression Algorithm',
+ rbd_discard_on_zeroed_write_same: 'Rbd Discard On Zeroed Write Same',
+ rbd_journal_max_payload_bytes: 'Rbd Journal Max Payload Bytes',
+ cluster_addr: 'Cluster Addr',
+ fsid: 'Fsid',
+ mgr_tick_period: 'Tick Period'
+ };
+
+ component.options.forEach((option) => {
+ expect(option.text).toEqual(configOptionNames[option.name]);
+ });
+ });
+ });
+
+ describe('createForm', () => {
+ it('should set the optionsFormGroupName correctly', () => {
+ expect(component.optionsFormGroupName).toEqual('testFormGroupName');
+ });
+
+ it('should create a FormControl for every config option', () => {
+ component.options.forEach((option) => {
+ expect(Object.keys(component.optionsFormGroup.controls)).toContain(option.name);
+ });
+ });
+ });
+
+ describe('loadStorageData', () => {
+ it('should create a list of config options by names', () => {
+ expect(component.options.length).toEqual(9);
+
+ component.options.forEach((option) => {
+ expect(oNames).toContain(option.name);
+ });
+ });
+
+ it('should add all needed attributes to every config option', () => {
+ component.options.forEach((option) => {
+ const optionKeys = Object.keys(option);
+ expect(optionKeys).toContain('text');
+ expect(optionKeys).toContain('additionalTypeInfo');
+ expect(optionKeys).toContain('value');
+
+ if (option.type !== 'bool' && option.type !== 'str') {
+ expect(optionKeys).toContain('patternHelpText');
+ }
+
+ if (option.name === 'osd_heartbeat_interval') {
+ expect(optionKeys).toContain('maxValue');
+ expect(optionKeys).toContain('minValue');
+ }
+ });
+ });
+
+ it('should set minValue and maxValue correctly', () => {
+ component.options.forEach((option) => {
+ if (option.name === 'osd_heartbeat_interval') {
+ expect(option.minValue).toEqual(1);
+ expect(option.maxValue).toEqual(86400);
+ }
+ });
+ });
+
+ it('should set the value attribute correctly', () => {
+ component.options.forEach((option) => {
+ if (option.name === 'osd_heartbeat_interval') {
+ const value = option.value;
+ expect(value).toBeDefined();
+ expect(value).toEqual({ section: 'osd', value: 6 });
+ } else {
+ expect(option.value).toBeUndefined();
+ }
+ });
+ });
+
+ it('should set the FormControl value correctly', () => {
+ component.options.forEach((option) => {
+ const value = component.optionsFormGroup.getValue(option.name);
+ if (option.name === 'osd_heartbeat_interval') {
+ expect(value).toBeDefined();
+ expect(value).toEqual(6);
+ } else {
+ expect(value).toBeNull();
+ }
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.ts
new file mode 100644
index 00000000..e9d6a116
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.component.ts
@@ -0,0 +1,118 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { FormControl, NgForm } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+import { ConfigurationService } from '../../api/configuration.service';
+import { CdFormGroup } from '../../forms/cd-form-group';
+import { ConfigOptionTypes } from './config-option.types';
+
+@Component({
+ selector: 'cd-config-option',
+ templateUrl: './config-option.component.html',
+ styleUrls: ['./config-option.component.scss']
+})
+export class ConfigOptionComponent implements OnInit {
+ @Input()
+ optionNames: Array<string> = [];
+ @Input()
+ optionsForm: CdFormGroup = new CdFormGroup({});
+ @Input()
+ optionsFormDir: NgForm = new NgForm([], []);
+ @Input()
+ optionsFormGroupName = '';
+ @Input()
+ optionsFormShowReset = true;
+
+ options: Array<any> = [];
+ optionsFormGroup: CdFormGroup = new CdFormGroup({});
+
+ constructor(private configService: ConfigurationService) {}
+
+ private static optionNameToText(optionName: string): string {
+ const sections = ['mon', 'mgr', 'osd', 'mds', 'client'];
+ return optionName
+ .split('_')
+ .filter((c, index) => index !== 0 || !sections.includes(c))
+ .map((c) => c.charAt(0).toUpperCase() + c.substring(1))
+ .join(' ');
+ }
+
+ ngOnInit() {
+ this.createForm();
+ this.loadStoredData();
+ }
+
+ private createForm() {
+ this.optionsForm.addControl(this.optionsFormGroupName, this.optionsFormGroup);
+ this.optionNames.forEach((optionName) => {
+ this.optionsFormGroup.addControl(optionName, new FormControl(null));
+ });
+ }
+
+ getStep(type: string, value: any): number | undefined {
+ return ConfigOptionTypes.getTypeStep(type, value);
+ }
+
+ private loadStoredData() {
+ this.configService.filter(this.optionNames).subscribe((data: any) => {
+ this.options = data.map((configOption) => {
+ const formControl = this.optionsForm.get(configOption.name);
+ const typeValidators = ConfigOptionTypes.getTypeValidators(configOption);
+ configOption.additionalTypeInfo = ConfigOptionTypes.getType(configOption.type);
+
+ // Set general information and value
+ configOption.text = ConfigOptionComponent.optionNameToText(configOption.name);
+ configOption.value = _.find(configOption.value, (p) => {
+ return p.section === 'osd'; // TODO: Can handle any other section
+ });
+ if (configOption.value) {
+ if (configOption.additionalTypeInfo.name === 'bool') {
+ formControl.setValue(configOption.value.value === 'true');
+ } else {
+ formControl.setValue(configOption.value.value);
+ }
+ }
+
+ // Set type information and validators
+ if (typeValidators) {
+ configOption.patternHelpText = typeValidators.patternHelpText;
+ if ('max' in typeValidators && typeValidators.max !== '') {
+ configOption.maxValue = typeValidators.max;
+ }
+ if ('min' in typeValidators && typeValidators.min !== '') {
+ configOption.minValue = typeValidators.min;
+ }
+ formControl.setValidators(typeValidators.validators);
+ }
+
+ return configOption;
+ });
+ });
+ }
+
+ saveValues() {
+ const options = {};
+ this.optionNames.forEach((optionName) => {
+ const optionValue = this.optionsForm.getValue(optionName);
+ if (optionValue !== null && optionValue !== '') {
+ options[optionName] = {
+ section: 'osd', // TODO: Can handle any other section
+ value: optionValue
+ };
+ }
+ });
+
+ return this.configService.bulkCreate({ options: options });
+ }
+
+ resetValue(optionName: string) {
+ this.configService.delete(optionName, 'osd').subscribe(
+ // TODO: Can handle any other section
+ () => {
+ const formControl = this.optionsForm.get(optionName);
+ formControl.reset();
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.model.ts
new file mode 100644
index 00000000..d3ebc5f3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.model.ts
@@ -0,0 +1,12 @@
+export class ConfigFormModel {
+ name: string;
+ desc: string;
+ long_desc: string;
+ type: string;
+ value: Array<any>;
+ default: any;
+ daemon_default: any;
+ min: any;
+ max: any;
+ services: Array<string>;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.spec.ts
new file mode 100644
index 00000000..8c34111b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.spec.ts
@@ -0,0 +1,272 @@
+import { ConfigFormModel } from './config-option.model';
+import { ConfigOptionTypes } from './config-option.types';
+
+describe('ConfigOptionTypes', () => {
+ describe('getType', () => {
+ it('should return uint type', () => {
+ const ret = ConfigOptionTypes.getType('uint');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('uint');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Unsigned integer value');
+ expect(ret.defaultMin).toBe(0);
+ expect(ret.patternHelpText).toBe('The entered value needs to be an unsigned number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return int type', () => {
+ const ret = ConfigOptionTypes.getType('int');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('int');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Integer value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(true);
+ });
+
+ it('should return size type', () => {
+ const ret = ConfigOptionTypes.getType('size');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('size');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Unsigned integer value (>=16bit)');
+ expect(ret.defaultMin).toBe(0);
+ expect(ret.patternHelpText).toBe('The entered value needs to be a unsigned number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return secs type', () => {
+ const ret = ConfigOptionTypes.getType('secs');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('secs');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Number of seconds');
+ expect(ret.defaultMin).toBe(1);
+ expect(ret.patternHelpText).toBe('The entered value needs to be a number >= 1.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return float type', () => {
+ const ret = ConfigOptionTypes.getType('float');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('float');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Double value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a number or decimal.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(true);
+ });
+
+ it('should return str type', () => {
+ const ret = ConfigOptionTypes.getType('str');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('str');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('Text');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBeUndefined();
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return addr type', () => {
+ const ret = ConfigOptionTypes.getType('addr');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('addr');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('IPv4 or IPv6 address');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a valid IP address.');
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return uuid type', () => {
+ const ret = ConfigOptionTypes.getType('uuid');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('uuid');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('UUID');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe(
+ 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8'
+ );
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return bool type', () => {
+ const ret = ConfigOptionTypes.getType('bool');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('bool');
+ expect(ret.inputType).toBe('checkbox');
+ expect(ret.humanReadable).toBe('Boolean value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBeUndefined();
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should throw an error for unknown type', () => {
+ expect(() => ConfigOptionTypes.getType('unknown')).toThrowError(
+ 'Found unknown type "unknown" for config option.'
+ );
+ });
+ });
+
+ describe('getTypeValidators', () => {
+ it('should return two validators for type uint, secs and size', () => {
+ const types = ['uint', 'size', 'secs'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.validators.length).toBe(2);
+ });
+ });
+
+ it('should return a validator for types float, int, addr and uuid', () => {
+ const types = ['float', 'int', 'addr', 'uuid'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.validators.length).toBe(1);
+ });
+ });
+
+ it('should return undefined for type bool and str', () => {
+ const types = ['str', 'bool'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeUndefined();
+ });
+ });
+
+ it('should return a pattern and a min validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int';
+ configOption.min = 2;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.validators.length).toBe(2);
+ expect(ret.min).toBe(2);
+ expect(ret.max).toBeUndefined();
+ });
+
+ it('should return a pattern and a max validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int';
+ configOption.max = 5;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.validators.length).toBe(2);
+ expect(ret.min).toBeUndefined();
+ expect(ret.max).toBe(5);
+ });
+
+ it('should return multiple validators', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'float';
+ configOption.max = 5.2;
+ configOption.min = 1.5;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.validators.length).toBe(3);
+ expect(ret.min).toBe(1.5);
+ expect(ret.max).toBe(5.2);
+ });
+
+ it(
+ 'should return a pattern help text for type uint, int, size, secs, ' + 'float, addr and uuid',
+ () => {
+ const types = ['uint', 'int', 'size', 'secs', 'float', 'addr', 'uuid'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = ConfigOptionTypes.getTypeValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.patternHelpText).toBeDefined();
+ });
+ }
+ );
+ });
+
+ describe('getTypeStep', () => {
+ it('should return the correct step for type uint and value 0', () => {
+ const ret = ConfigOptionTypes.getTypeStep('uint', 0);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type int and value 1', () => {
+ const ret = ConfigOptionTypes.getTypeStep('int', 1);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type int and value null', () => {
+ const ret = ConfigOptionTypes.getTypeStep('int', null);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type size and value 2', () => {
+ const ret = ConfigOptionTypes.getTypeStep('size', 2);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type secs and value 3', () => {
+ const ret = ConfigOptionTypes.getTypeStep('secs', 3);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type float and value 1', () => {
+ const ret = ConfigOptionTypes.getTypeStep('float', 1);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return the correct step for type float and value 0.1', () => {
+ const ret = ConfigOptionTypes.getTypeStep('float', 0.1);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return the correct step for type float and value 0.02', () => {
+ const ret = ConfigOptionTypes.getTypeStep('float', 0.02);
+ expect(ret).toBe(0.01);
+ });
+
+ it('should return the correct step for type float and value 0.003', () => {
+ const ret = ConfigOptionTypes.getTypeStep('float', 0.003);
+ expect(ret).toBe(0.001);
+ });
+
+ it('should return the correct step for type float and value null', () => {
+ const ret = ConfigOptionTypes.getTypeStep('float', null);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return undefined for unknown type', () => {
+ const ret = ConfigOptionTypes.getTypeStep('unknown', 1);
+ expect(ret).toBeUndefined();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.ts
new file mode 100644
index 00000000..cfe1b474
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/config-option/config-option.types.ts
@@ -0,0 +1,144 @@
+import { Validators } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+import { CdValidators } from '../../forms/cd-validators';
+import { ConfigFormModel } from './config-option.model';
+
+export class ConfigOptionTypes {
+ // TODO: I18N
+ private static knownTypes: Array<any> = [
+ {
+ name: 'uint',
+ inputType: 'number',
+ humanReadable: 'Unsigned integer value',
+ defaultMin: 0,
+ patternHelpText: 'The entered value needs to be an unsigned number.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'int',
+ inputType: 'number',
+ humanReadable: 'Integer value',
+ patternHelpText: 'The entered value needs to be a number.',
+ isNumberType: true,
+ allowsNegative: true
+ },
+ {
+ name: 'size',
+ inputType: 'number',
+ humanReadable: 'Unsigned integer value (>=16bit)',
+ defaultMin: 0,
+ patternHelpText: 'The entered value needs to be a unsigned number.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'secs',
+ inputType: 'number',
+ humanReadable: 'Number of seconds',
+ defaultMin: 1,
+ patternHelpText: 'The entered value needs to be a number >= 1.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'float',
+ inputType: 'number',
+ humanReadable: 'Double value',
+ patternHelpText: 'The entered value needs to be a number or decimal.',
+ isNumberType: true,
+ allowsNegative: true
+ },
+ { name: 'str', inputType: 'text', humanReadable: 'Text', isNumberType: false },
+ {
+ name: 'addr',
+ inputType: 'text',
+ humanReadable: 'IPv4 or IPv6 address',
+ patternHelpText: 'The entered value needs to be a valid IP address.',
+ isNumberType: false
+ },
+ {
+ name: 'uuid',
+ inputType: 'text',
+ humanReadable: 'UUID',
+ patternHelpText:
+ 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8',
+ isNumberType: false
+ },
+ { name: 'bool', inputType: 'checkbox', humanReadable: 'Boolean value', isNumberType: false }
+ ];
+
+ public static getType(type: string): any {
+ const currentType = _.find(this.knownTypes, (t) => {
+ return t.name === type;
+ });
+
+ if (currentType !== undefined) {
+ return currentType;
+ }
+
+ throw new Error('Found unknown type "' + type + '" for config option.');
+ }
+
+ public static getTypeValidators(configOption: ConfigFormModel): any {
+ const typeParams = ConfigOptionTypes.getType(configOption.type);
+
+ if (typeParams.name === 'bool' || typeParams.name === 'str') {
+ return;
+ }
+
+ const typeValidators = { validators: [], patternHelpText: typeParams.patternHelpText };
+
+ if (typeParams.isNumberType) {
+ if (configOption.max && configOption.max !== '') {
+ typeValidators['max'] = configOption.max;
+ typeValidators.validators.push(Validators.max(configOption.max));
+ }
+
+ if (configOption.min && configOption.min !== '') {
+ typeValidators['min'] = configOption.min;
+ typeValidators.validators.push(Validators.min(configOption.min));
+ } else if ('defaultMin' in typeParams) {
+ typeValidators['min'] = typeParams.defaultMin;
+ typeValidators.validators.push(Validators.min(typeParams.defaultMin));
+ }
+
+ if (configOption.type === 'float') {
+ typeValidators.validators.push(CdValidators.decimalNumber());
+ } else {
+ typeValidators.validators.push(CdValidators.number(typeParams.allowsNegative));
+ }
+ } else if (configOption.type === 'addr') {
+ typeValidators.validators = [CdValidators.ip()];
+ } else if (configOption.type === 'uuid') {
+ typeValidators.validators = [CdValidators.uuid()];
+ }
+
+ return typeValidators;
+ }
+
+ public static getTypeStep(type: string, value: number): number | undefined {
+ const numberTypes = ['uint', 'int', 'size', 'secs'];
+
+ if (numberTypes.includes(type)) {
+ return 1;
+ }
+
+ if (type === 'float') {
+ if (value !== null) {
+ const stringVal = value.toString();
+ if (stringVal.indexOf('.') !== -1) {
+ // Value type float and contains decimal characters
+ const decimal = value.toString().split('.');
+ return Math.pow(10, -decimal[1].length);
+ }
+ }
+
+ return 0.1;
+ }
+
+ return undefined;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.html
new file mode 100644
index 00000000..707e24e8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.html
@@ -0,0 +1,26 @@
+<cd-modal (hide)="cancel()">
+ <ng-container class="modal-title">{{ titleText }}</ng-container>
+ <ng-container class="modal-content">
+ <form name="confirmationForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="confirmationForm"
+ novalidate>
+ <div class="modal-body">
+ <ng-container *ngTemplateOutlet="bodyTpl; context: bodyContext"></ng-container>
+ </div>
+ <div class="modal-footer">
+ <div class="button-group text-right">
+ <cd-submit-button [form]="confirmationForm"
+ (submitAction)="onSubmit(confirmationForm.value)">
+ {{ buttonText }}
+ </cd-submit-button>
+ <cd-back-button [back]="boundCancel"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.spec.ts
new file mode 100644
index 00000000..2c1f76a1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.spec.ts
@@ -0,0 +1,37 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { BackButtonComponent } from '../back-button/back-button.component';
+import { ModalComponent } from '../modal/modal.component';
+import { SubmitButtonComponent } from '../submit-button/submit-button.component';
+import { ConfirmationModalComponent } from './confirmation-modal.component';
+
+describe('ConfirmationModalComponent', () => {
+ let component: ConfirmationModalComponent;
+ let fixture: ComponentFixture<ConfirmationModalComponent>;
+
+ configureTestBed({
+ declarations: [
+ ConfirmationModalComponent,
+ BackButtonComponent,
+ SubmitButtonComponent,
+ ModalComponent
+ ],
+ imports: [ReactiveFormsModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfirmationModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.ts
new file mode 100644
index 00000000..9765fed8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/confirmation-modal/confirmation-modal.component.ts
@@ -0,0 +1,43 @@
+import { Component, OnInit, TemplateRef } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+@Component({
+ selector: 'cd-confirmation-modal',
+ templateUrl: './confirmation-modal.component.html',
+ styleUrls: ['./confirmation-modal.component.scss']
+})
+export class ConfirmationModalComponent implements OnInit {
+ bodyData: object;
+ bodyTpl: TemplateRef<any>;
+ buttonText: string;
+ onSubmit: Function;
+ onCancel: Function;
+ titleText: string;
+
+ bodyContext: object;
+ confirmationForm: FormGroup;
+
+ boundCancel = this.cancel.bind(this);
+
+ constructor(public modalRef: BsModalRef) {
+ this.confirmationForm = new FormGroup({});
+ }
+
+ ngOnInit() {
+ this.bodyContext = this.bodyContext || {};
+ this.bodyContext['$implicit'] = this.bodyData;
+ }
+
+ cancel() {
+ this.modalRef.hide();
+ if (this.onCancel) {
+ this.onCancel();
+ }
+ }
+
+ stopLoadingSpinner() {
+ this.confirmationForm.setErrors({ cdSubmitButton: true });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.html
new file mode 100644
index 00000000..c6c93045
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.html
@@ -0,0 +1,59 @@
+<cd-modal #modal
+ [modalRef]="modalRef">
+ <ng-container class="modal-title">
+ <ng-container *ngTemplateOutlet="deletionHeading"></ng-container>
+ </ng-container>
+
+ <ng-container class="modal-content">
+ <form name="deletionForm"
+ #formDir="ngForm"
+ [formGroup]="deletionForm"
+ novalidate>
+ <div class="modal-body">
+ <ng-container *ngTemplateOutlet="bodyTemplate; context: bodyContext"></ng-container>
+ <div class="question">
+ <span *ngIf="itemNames; else noNames">
+ <p *ngIf="itemNames.length === 1; else manyNames"
+ i18n>Are you sure that you want to {{ actionDescription | lowercase }} <strong>{{ itemNames[0] }}</strong>?</p>
+ <ng-template #manyNames>
+ <p i18n>Are you sure that you want to {{ actionDescription | lowercase }} the selected items?</p>
+ <ul>
+ <li *ngFor="let itemName of itemNames"><strong>{{ itemName }}</strong></li>
+ </ul>
+ </ng-template >
+ </span>
+ <ng-template #noNames>
+ <p i18n>Are you sure that you want to {{ actionDescription | lowercase }} the selected {{ itemDescription }}?</p>
+ </ng-template>
+ <div class="form-group"
+ [ngClass]="{'has-error': deletionForm.showError('confirmation', formDir)}">
+ <div class="checkbox checkbox-primary">
+ <input type="checkbox"
+ name="confirmation"
+ id="confirmation"
+ formControlName="confirmation"
+ autofocus>
+ <label i18n
+ for="confirmation">Yes, I am sure.</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <cd-submit-button #submitButton
+ [form]="deletionForm"
+ (submitAction)="callSubmitAction()">
+ <ng-container *ngTemplateOutlet="deletionHeading"></ng-container>
+ </cd-submit-button>
+ <cd-back-button [back]="modalRef.hide"
+ name="Cancel"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </form>
+ </ng-container>
+</cd-modal>
+
+<ng-template #deletionHeading>
+ {{ actionDescription | titlecase }} {{ itemDescription }}
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.scss
new file mode 100644
index 00000000..d136c24b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.scss
@@ -0,0 +1,9 @@
+.modal-body .question {
+ margin-top: 1em;
+}
+.modal-body label {
+ font-weight: bold;
+}
+.modal-body .question .checkbox {
+ padding-top: 7px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
new file mode 100644
index 00000000..9602ad78
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
@@ -0,0 +1,250 @@
+import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { NgForm, ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+
+import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap/modal';
+import { Observable, Subscriber, timer as observableTimer } from 'rxjs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { DirectivesModule } from '../../directives/directives.module';
+import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
+
+@NgModule({
+ entryComponents: [CriticalConfirmationModalComponent]
+})
+export class MockModule {}
+
+@Component({
+ template: `
+ <button type="button" class="btn btn-sm btn-primary" (click)="openCtrlDriven()">
+ <i class="fa fa-fw fa-times"></i>Deletion Ctrl-Test
+ <ng-template #ctrlDescription>
+ The spinner is handled by the controller if you have use the modal as ViewChild in order to
+ use it's functions to stop the spinner or close the dialog.
+ </ng-template>
+ </button>
+
+ <button type="button" class="btn btn-sm btn-primary" (click)="openModalDriven()">
+ <i class="fa fa-fw fa-times"></i>Deletion Modal-Test
+ <ng-template #modalDescription>
+ The spinner is handled by the modal if your given deletion function returns a Observable.
+ </ng-template>
+ </button>
+ `
+})
+class MockComponent {
+ @ViewChild('ctrlDescription')
+ ctrlDescription: TemplateRef<any>;
+ @ViewChild('modalDescription')
+ modalDescription: TemplateRef<any>;
+ someData = [1, 2, 3, 4, 5];
+ finished: number[];
+ ctrlRef: BsModalRef;
+ modalRef: BsModalRef;
+
+ // Normally private - public was needed for the tests
+ constructor(public modalService: BsModalService) {}
+
+ openCtrlDriven() {
+ this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ submitAction: this.fakeDeleteController.bind(this),
+ bodyTemplate: this.ctrlDescription
+ }
+ });
+ }
+
+ openModalDriven() {
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ initialState: {
+ submitActionObservable: this.fakeDelete(),
+ bodyTemplate: this.modalDescription
+ }
+ });
+ }
+
+ finish() {
+ this.finished = [6, 7, 8, 9];
+ }
+
+ fakeDelete() {
+ return (): Observable<any> => {
+ return new Observable((observer: Subscriber<any>) => {
+ observableTimer(100).subscribe(() => {
+ observer.next(this.finish());
+ observer.complete();
+ });
+ });
+ };
+ }
+
+ fakeDeleteController() {
+ observableTimer(100).subscribe(() => {
+ this.finish();
+ this.ctrlRef.hide();
+ });
+ }
+}
+
+describe('CriticalConfirmationModalComponent', () => {
+ let mockComponent: MockComponent;
+ let component: CriticalConfirmationModalComponent;
+ let mockFixture: ComponentFixture<MockComponent>;
+ let fixture: ComponentFixture<CriticalConfirmationModalComponent>;
+
+ configureTestBed({
+ declarations: [MockComponent, CriticalConfirmationModalComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ imports: [ModalModule.forRoot(), ReactiveFormsModule, MockModule, DirectivesModule],
+ providers: [BsModalRef]
+ });
+
+ beforeEach(() => {
+ mockFixture = TestBed.createComponent(MockComponent);
+ mockComponent = mockFixture.componentInstance;
+ // Mocking the modals as a lot would be left over
+ spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
+ const ref = new BsModalRef();
+ fixture = TestBed.createComponent(CriticalConfirmationModalComponent);
+ component = fixture.componentInstance;
+ if (config.initialState) {
+ component = Object.assign(component, config.initialState);
+ }
+ fixture.detectChanges();
+ ref.content = component;
+ return ref;
+ });
+ mockComponent.openCtrlDriven();
+ mockFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should focus the checkbox form field', () => {
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ const focused = fixture.debugElement.query(By.css(':focus'));
+ expect(focused.attributes.id).toBe('confirmation');
+ expect(focused.attributes.type).toBe('checkbox');
+ const element = document.getElementById('confirmation');
+ expect(element === document.activeElement).toBeTruthy();
+ });
+ });
+
+ it('should throw an error if no action is defined', () => {
+ component = Object.assign(component, {
+ submitAction: null,
+ submitActionObservable: null
+ });
+ expect(() => component.ngOnInit()).toThrowError('No submit action defined');
+ });
+
+ it('should test if the ctrl driven mock is set correctly through mock component', () => {
+ expect(component.bodyTemplate).toBeTruthy();
+ expect(component.submitAction).toBeTruthy();
+ expect(component.submitActionObservable).not.toBeTruthy();
+ });
+
+ it('should test if the modal driven mock is set correctly through mock component', () => {
+ mockComponent.openModalDriven();
+ expect(component.bodyTemplate).toBeTruthy();
+ expect(component.submitActionObservable).toBeTruthy();
+ expect(component.submitAction).not.toBeTruthy();
+ });
+
+ describe('component functions', () => {
+ const changeValue = (value) => {
+ const ctrl = component.deletionForm.get('confirmation');
+ ctrl.setValue(value);
+ ctrl.markAsDirty();
+ ctrl.updateValueAndValidity();
+ fixture.detectChanges();
+ };
+
+ it('should test hideModal', () => {
+ expect(component.modalRef).toBeTruthy();
+ expect(component.hideModal).toBeTruthy();
+ spyOn(component.modalRef, 'hide').and.callThrough();
+ expect(component.modalRef.hide).not.toHaveBeenCalled();
+ component.hideModal();
+ expect(component.modalRef.hide).toHaveBeenCalled();
+ });
+
+ describe('validate confirmation', () => {
+ const testValidation = (submitted: boolean, error: string, expected: boolean) => {
+ expect(
+ component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
+ ).toBe(expected);
+ };
+
+ beforeEach(() => {
+ component.deletionForm.reset();
+ });
+
+ it('should test empty values', () => {
+ component.deletionForm.reset();
+ testValidation(false, undefined, false);
+ testValidation(true, 'required', true);
+ component.deletionForm.reset();
+ changeValue(true);
+ changeValue(false);
+ testValidation(true, 'required', true);
+ });
+ });
+
+ describe('deletion call', () => {
+ beforeEach(() => {
+ spyOn(component, 'stopLoadingSpinner').and.callThrough();
+ spyOn(component, 'hideModal').and.callThrough();
+ });
+
+ describe('Controller driven', () => {
+ beforeEach(() => {
+ spyOn(component, 'submitAction').and.callThrough();
+ spyOn(mockComponent.ctrlRef, 'hide').and.callThrough();
+ });
+
+ it('should test fake deletion that closes modal', <any>fakeAsync(() => {
+ // Before deletionCall
+ expect(component.submitAction).not.toHaveBeenCalled();
+ // During deletionCall
+ component.callSubmitAction();
+ expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
+ expect(component.hideModal).not.toHaveBeenCalled();
+ expect(mockComponent.ctrlRef.hide).not.toHaveBeenCalled();
+ expect(component.submitAction).toHaveBeenCalled();
+ expect(mockComponent.finished).toBe(undefined);
+ // After deletionCall
+ tick(2000);
+ expect(component.hideModal).not.toHaveBeenCalled();
+ expect(mockComponent.ctrlRef.hide).toHaveBeenCalled();
+ expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
+ }));
+ });
+
+ describe('Modal driven', () => {
+ beforeEach(() => {
+ mockComponent.openModalDriven();
+ spyOn(component, 'stopLoadingSpinner').and.callThrough();
+ spyOn(component, 'hideModal').and.callThrough();
+ spyOn(mockComponent, 'fakeDelete').and.callThrough();
+ });
+
+ it('should delete and close modal', <any>fakeAsync(() => {
+ // During deletionCall
+ component.callSubmitAction();
+ expect(mockComponent.finished).toBe(undefined);
+ expect(component.hideModal).not.toHaveBeenCalled();
+ // After deletionCall
+ tick(2000);
+ expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
+ expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
+ expect(component.hideModal).toHaveBeenCalled();
+ }));
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.ts
new file mode 100644
index 00000000..5c1f1405
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.ts
@@ -0,0 +1,58 @@
+import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+import { Observable } from 'rxjs';
+
+import { CdFormGroup } from '../../forms/cd-form-group';
+import { SubmitButtonComponent } from '../submit-button/submit-button.component';
+
+@Component({
+ selector: 'cd-deletion-modal',
+ templateUrl: './critical-confirmation-modal.component.html',
+ styleUrls: ['./critical-confirmation-modal.component.scss']
+})
+export class CriticalConfirmationModalComponent implements OnInit {
+ @ViewChild(SubmitButtonComponent)
+ submitButton: SubmitButtonComponent;
+ bodyTemplate: TemplateRef<any>;
+ bodyContext: object;
+ submitActionObservable: () => Observable<any>;
+ submitAction: Function;
+ deletionForm: CdFormGroup;
+ itemDescription: 'entry';
+ itemNames: string[];
+ actionDescription = 'delete';
+
+ constructor(public modalRef: BsModalRef) {}
+
+ ngOnInit() {
+ this.deletionForm = new CdFormGroup({
+ confirmation: new FormControl(false, [Validators.requiredTrue])
+ });
+
+ if (!(this.submitAction || this.submitActionObservable)) {
+ throw new Error('No submit action defined');
+ }
+ }
+
+ callSubmitAction() {
+ if (this.submitActionObservable) {
+ this.submitActionObservable().subscribe(
+ null,
+ this.stopLoadingSpinner.bind(this),
+ this.hideModal.bind(this)
+ );
+ } else {
+ this.submitAction();
+ }
+ }
+
+ hideModal() {
+ this.modalRef.hide();
+ }
+
+ stopLoadingSpinner() {
+ this.deletionForm.setErrors({ cdSubmitButton: true });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.html
new file mode 100644
index 00000000..962a0ca2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.html
@@ -0,0 +1,28 @@
+<alert type="danger">
+ <table>
+ <tr>
+ <td rowspan="2"
+ class="error-panel-alert-icon">
+ <i class="fa fa-3x fa-times-circle alert-danger"
+ aria-hidden="true"></i>
+ </td>
+ <td class="error-panel-alert-title">
+ {{ title }}
+ </td>
+ </tr>
+ <tr>
+ <td class="error-panel-alert-text">
+ <ng-content></ng-content>
+ </td>
+ </tr>
+ </table>
+</alert>
+
+<div class="button-group text-right"
+ *ngIf="backAction.observers.length > 0">
+ <button class="btn btn-sm btn-default tc_backButton"
+ type="button"
+ (click)="backAction.emit()"
+ autofocus
+ i18n>Back</button>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.scss
new file mode 100644
index 00000000..945fd6f8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.scss
@@ -0,0 +1,7 @@
+.error-panel-alert-icon {
+ vertical-align: top;
+ padding-right: 15px; // See @alert-padding in bootstrap/less/variables.less
+}
+.error-panel-alert-title {
+ font-weight: bold;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.spec.ts
new file mode 100644
index 00000000..f9355833
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ErrorPanelComponent } from './error-panel.component';
+
+describe('ErrorPanelComponent', () => {
+ let component: ErrorPanelComponent;
+ let fixture: ComponentFixture<ErrorPanelComponent>;
+
+ configureTestBed({
+ declarations: [ErrorPanelComponent],
+ imports: [AlertModule.forRoot()]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ErrorPanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.ts
new file mode 100644
index 00000000..85ccef2c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/error-panel/error-panel.component.ts
@@ -0,0 +1,22 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+ selector: 'cd-error-panel',
+ templateUrl: './error-panel.component.html',
+ styleUrls: ['./error-panel.component.scss']
+})
+export class ErrorPanelComponent {
+ /**
+ * The title to be displayed. Defaults to 'Error'.
+ * @type {string}
+ */
+ @Input()
+ title = 'Error';
+
+ /**
+ * The event that is triggered when the 'Back' button is pressed.
+ * @type {EventEmitter<any>}
+ */
+ @Output()
+ backAction = new EventEmitter();
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html
new file mode 100644
index 00000000..61fccbc6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html
@@ -0,0 +1,53 @@
+<!-- Embed dashboard -->
+<cd-loading-panel *ngIf="loading && grafanaExist"
+ i18n>Loading panel data...</cd-loading-panel>
+
+<cd-info-panel *ngIf="!grafanaExist"
+ i18n>Please consult the
+ <a href="{{ docsUrl }}" target="_blank">documentation</a> on how to
+ configure and enable the monitoring functionality.</cd-info-panel>
+
+<cd-info-panel *ngIf="!dashboardExist"
+ i18n>Grafana Dashboard doesn't exist. Please refer to
+ <a href="{{ docsUrl }}" target="_blank">documentation</a> on how to
+ add dashboards to Grafana.</cd-info-panel>
+
+<div class="row"
+ *ngIf="grafanaExist && dashboardExist">
+ <div class="col-md-12 timepicker">
+ <label class="control-label col-sm-1"
+ for="timepicker-control">
+ <ng-container i18n>Grafana Time Picker</ng-container>
+ </label>
+ <div class="col-sm-9">
+ <select id="timepicker"
+ name="timepicker-control"
+ class="form-control "
+ [(ngModel)]="time"
+ (ngModelChange)="onTimepickerChange($event)">
+ <option *ngFor="let key of grafanaTimes"
+ [ngValue]="key.value">{{ key.name }}
+ </option>
+ </select>
+ </div>
+ <button class="btn btn-sm"
+ i18n-title
+ title="Reset Settings"
+ (click)="reset()">
+ <i class="fa fa-undo"></i>
+ </button>
+ <br>
+ </div>
+ <div class="col-md-12">
+ <div class="grafana-container">
+ <iframe #iframe
+ id="iframe"
+ [src]="grafanaSrc"
+ class="grafana"
+ [ngClass]="panelStyle"
+ frameborder="0"
+ scrolling="no">
+ </iframe>
+ </div>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.scss
new file mode 100644
index 00000000..fe30025c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.scss
@@ -0,0 +1,44 @@
+.grafana {
+ width: 100%;
+ height: 600px;
+ z-index: 0;
+}
+
+.grafana_one {
+ height: 400px;
+}
+
+.grafana_two {
+ height: 750px;
+}
+
+.grafana_three {
+ height: 900px;
+}
+
+.timepicker {
+ select {
+ display: inline-block;
+ }
+
+ label {
+ font-size: 1.05em;
+ padding: 5px !important;
+ }
+}
+
+button {
+ margin-bottom: 10px;
+ margin-left: 10px;
+ float: right;
+ i {
+ font-size: 14px;
+ padding: 2px;
+ }
+}
+
+.dropdown-menu {
+ top: 20px;
+ right: 20px;
+ left: auto;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.spec.ts
new file mode 100644
index 00000000..d063cd6b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.spec.ts
@@ -0,0 +1,83 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { SettingsService } from '../../api/settings.service';
+import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
+import { InfoPanelComponent } from '../info-panel/info-panel.component';
+import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
+import { GrafanaComponent } from './grafana.component';
+
+describe('GrafanaComponent', () => {
+ let component: GrafanaComponent;
+ let fixture: ComponentFixture<GrafanaComponent>;
+
+ configureTestBed({
+ declarations: [GrafanaComponent, InfoPanelComponent, LoadingPanelComponent],
+ imports: [AlertModule.forRoot(), HttpClientTestingModule, RouterTestingModule, FormsModule],
+ providers: [CephReleaseNamePipe, SettingsService, SummaryService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GrafanaComponent);
+ component = fixture.componentInstance;
+ component.grafanaPath = 'somePath';
+ component.uid = 'foo';
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should have found out that grafana does not exist', () => {
+ fixture.detectChanges();
+ expect(component.grafanaExist).toBe(false);
+ expect(component.baseUrl).toBe(undefined);
+ expect(component.loading).toBe(true);
+ expect(component.url).toBe(undefined);
+ expect(component.grafanaSrc).toEqual(undefined);
+ });
+
+ describe('with grafana initialized', () => {
+ beforeEach(() => {
+ TestBed.get(SettingsService).settings = { 'api/grafana/url': 'http:localhost:3000' };
+ fixture.detectChanges();
+ });
+
+ it('should have found out that grafana exists and dashboard exists', () => {
+ expect(component.time).toBe('from=now-1h&to=now');
+ expect(component.grafanaExist).toBe(true);
+ expect(component.baseUrl).toBe('http:localhost:3000/d/');
+ expect(component.loading).toBe(false);
+ expect(component.url).toBe(
+ 'http:localhost:3000/d/foo/somePath&refresh=2s&kiosk&from=now-1h&to=now'
+ );
+ expect(component.grafanaSrc).toEqual({
+ changingThisBreaksApplicationSecurity:
+ 'http:localhost:3000/d/foo/somePath&refresh=2s&kiosk&from=now-1h&to=now'
+ });
+ });
+
+ it('should reset the values', () => {
+ component.reset();
+ expect(component.time).toBe('from=now-1h&to=now');
+ expect(component.url).toBe(
+ 'http:localhost:3000/d/foo/somePath&refresh=2s&kiosk&from=now-1h&to=now'
+ );
+ expect(component.grafanaSrc).toEqual({
+ changingThisBreaksApplicationSecurity:
+ 'http:localhost:3000/d/foo/somePath&refresh=2s&kiosk&from=now-1h&to=now'
+ });
+ });
+
+ it('should have Dashboard', () => {
+ TestBed.get(SettingsService).validateGrafanaDashboardUrl = { uid: 200 };
+ expect(component.dashboardExist).toBe(true);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts
new file mode 100644
index 00000000..af7158c3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.ts
@@ -0,0 +1,221 @@
+import { Component, Input, OnChanges, OnInit } from '@angular/core';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../../shared/services/summary.service';
+import { SettingsService } from '../../api/settings.service';
+
+@Component({
+ selector: 'cd-grafana',
+ templateUrl: './grafana.component.html',
+ styleUrls: ['./grafana.component.scss']
+})
+export class GrafanaComponent implements OnInit, OnChanges {
+ grafanaSrc: SafeUrl;
+ url: string;
+ protocol: string;
+ host: string;
+ port: number;
+ baseUrl: any;
+ panelStyle: any;
+ grafanaExist = false;
+ mode = '&kiosk';
+ loading = true;
+ styles = {};
+ dashboardExist = true;
+ time: string;
+ grafanaTimes: any;
+ readonly DEFAULT_TIME: string = 'from=now-1h&to=now';
+
+ @Input()
+ grafanaPath: string;
+ @Input()
+ grafanaStyle: string;
+ @Input()
+ uid: string;
+
+ docsUrl: string;
+
+ constructor(
+ private summaryService: SummaryService,
+ private sanitizer: DomSanitizer,
+ private settingsService: SettingsService,
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private i18n: I18n
+ ) {
+ this.grafanaTimes = [
+ {
+ name: this.i18n('Last 5 minutes'),
+ value: 'from=now-5m&to=now'
+ },
+ {
+ name: this.i18n('Last 15 minutes'),
+ value: 'from=now-15m&to=now'
+ },
+ {
+ name: this.i18n('Last 30 minutes'),
+ value: 'from=now-30m&to=now'
+ },
+ {
+ name: this.i18n('Last 1 hour (Default)'),
+ value: 'from=now-1h&to=now'
+ },
+ {
+ name: this.i18n('Last 3 hours'),
+ value: 'from=now-3h&to=now'
+ },
+ {
+ name: this.i18n('Last 6 hours'),
+ value: 'from=now-6h&to=now'
+ },
+ {
+ name: this.i18n('Last 12 hours'),
+ value: 'from=now-12h&to=now'
+ },
+ {
+ name: this.i18n('Last 24 hours'),
+ value: 'from=now-24h&to=now'
+ },
+ {
+ name: this.i18n('Yesterday'),
+ value: 'from=now-1d%2Fd&to=now-1d%2Fd'
+ },
+ {
+ name: this.i18n('Today so far'),
+ value: 'from=now%2Fd&to=now'
+ },
+ {
+ name: this.i18n('Day before yesterday'),
+ value: 'from=now-2d%2Fd&to=now-2d%2Fd'
+ },
+ {
+ name: this.i18n('Last 2 days'),
+ value: 'from=now-2d&to=now'
+ },
+ {
+ name: this.i18n('This day last week'),
+ value: 'from=now-7d%2Fd&to=now-7d%2Fd'
+ },
+ {
+ name: this.i18n('Previous week'),
+ value: 'from=now-1w%2Fw&to=now-1w%2Fw'
+ },
+ {
+ name: this.i18n('This week so far'),
+ value: 'from=now%2Fw&to=now'
+ },
+ {
+ name: this.i18n('Last 7 days'),
+ value: 'from=now-7d&to=now'
+ },
+ {
+ name: this.i18n('Previous month'),
+ value: 'from=now-1M%2FM&to=now-1M%2FM'
+ },
+ {
+ name: this.i18n('This month so far'),
+ value: 'from=now%2FM&to=now'
+ },
+ {
+ name: this.i18n('Last 30 days'),
+ value: 'from=now-30d&to=now'
+ },
+ {
+ name: this.i18n('Last 90 days'),
+ value: 'from=now-90d&to=now'
+ },
+ {
+ name: this.i18n('Last 6 months'),
+ value: 'from=now-6M&to=now'
+ },
+ {
+ name: this.i18n('Last 1 year'),
+ value: 'from=now-1y&to=now'
+ },
+ {
+ name: this.i18n('Previous year'),
+ value: 'from=now-1y%2Fy&to=now-1y%2Fy'
+ },
+ {
+ name: this.i18n('This year so far'),
+ value: 'from=now%2Fy&to=now'
+ },
+ {
+ name: this.i18n('Last 2 years'),
+ value: 'from=now-2y&to=now'
+ },
+ {
+ name: this.i18n('Last 5 years'),
+ value: 'from=now-5y&to=now'
+ }
+ ];
+ }
+
+ ngOnInit() {
+ this.time = this.DEFAULT_TIME;
+ this.styles = {
+ one: 'grafana_one',
+ two: 'grafana_two',
+ three: 'grafana_three'
+ };
+
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl =
+ `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/` +
+ `#enabling-the-embedding-of-grafana-dashboards`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+ this.settingsService.ifSettingConfigured('api/grafana/url', (url) => {
+ this.grafanaExist = true;
+ this.loading = false;
+ this.baseUrl = url + '/d/';
+ this.getFrame();
+ });
+ this.panelStyle = this.styles[this.grafanaStyle];
+ }
+
+ getFrame() {
+ this.settingsService
+ .validateGrafanaDashboardUrl(this.uid)
+ .subscribe((data: any) => (this.dashboardExist = data === 200));
+ this.url =
+ this.baseUrl +
+ this.uid +
+ '/' +
+ this.grafanaPath +
+ '&refresh=2s' +
+ this.mode +
+ '&' +
+ this.time;
+ this.grafanaSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
+ }
+
+ onTimepickerChange() {
+ if (this.grafanaExist) {
+ this.getFrame();
+ }
+ }
+
+ reset() {
+ this.time = this.DEFAULT_TIME;
+ if (this.grafanaExist) {
+ this.getFrame();
+ }
+ }
+
+ ngOnChanges() {
+ if (this.grafanaExist) {
+ this.getFrame();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.html
new file mode 100644
index 00000000..18ca71e4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.html
@@ -0,0 +1,12 @@
+<ng-template #popoverTpl>
+ <div [innerHtml]="html"></div>
+ <ng-content></ng-content>
+</ng-template>
+<i class="fa fa-question-circle"
+ aria-hidden="true"
+ [popover]="popoverTpl"
+ placement="bottom"
+ container="body"
+ (click)="$event.preventDefault();"
+ [outsideClick]="true">
+</i>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.scss
new file mode 100644
index 00000000..d6637810
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.scss
@@ -0,0 +1,7 @@
+@import '../../../../defaults';
+
+i {
+ color: $color-helper-bg;
+ cursor: pointer;
+ padding-left: 4px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.spec.ts
new file mode 100644
index 00000000..c0506ce0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PopoverModule } from 'ngx-bootstrap/popover';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { HelperComponent } from './helper.component';
+
+describe('HelperComponent', () => {
+ let component: HelperComponent;
+ let fixture: ComponentFixture<HelperComponent>;
+
+ configureTestBed({
+ imports: [PopoverModule.forRoot()],
+ declarations: [HelperComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HelperComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.ts
new file mode 100644
index 00000000..7430411b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/helper/helper.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'cd-helper',
+ templateUrl: './helper.component.html',
+ styleUrls: ['./helper.component.scss']
+})
+export class HelperComponent {
+ @Input()
+ html: any;
+
+ constructor() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.html
new file mode 100644
index 00000000..27b5fd67
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.html
@@ -0,0 +1,18 @@
+<alert type="info">
+ <table>
+ <tr>
+ <td rowspan="2" class="info-panel-alert-icon">
+ <i class="fa fa-3x fa-info-circle alert-info"
+ aria-hidden="true"></i>
+ </td>
+ <td class="info-panel-alert-title">
+ {{ title }}
+ </td>
+ </tr>
+ <tr>
+ <td class="info-panel-alert-text">
+ <ng-content></ng-content>
+ </td>
+ </tr>
+ </table>
+</alert>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.scss
new file mode 100644
index 00000000..27c0e321
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.scss
@@ -0,0 +1,7 @@
+.info-panel-alert-icon {
+ vertical-align: top;
+ padding-right: 15px; // See @alert-padding in bootstrap/less/variables.less
+}
+.info-panel-alert-title {
+ font-weight: bold;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.spec.ts
new file mode 100644
index 00000000..6a28aecb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.spec.ts
@@ -0,0 +1,27 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { InfoPanelComponent } from './info-panel.component';
+
+describe('InfoPanelComponent', () => {
+ let component: InfoPanelComponent;
+ let fixture: ComponentFixture<InfoPanelComponent>;
+
+ configureTestBed({
+ declarations: [InfoPanelComponent],
+ imports: [AlertModule.forRoot()],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(InfoPanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.ts
new file mode 100644
index 00000000..ce0ef7ff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/info-panel/info-panel.component.ts
@@ -0,0 +1,19 @@
+import { Component, Input } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+@Component({
+ selector: 'cd-info-panel',
+ templateUrl: './info-panel.component.html',
+ styleUrls: ['./info-panel.component.scss']
+})
+export class InfoPanelComponent {
+ /**
+ * The title to be displayed. Defaults to 'Information'.
+ * @type {string}
+ */
+ @Input()
+ title = this.i18n('Information');
+
+ constructor(private i18n: I18n) {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.html
new file mode 100644
index 00000000..4fca0b72
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.html
@@ -0,0 +1,26 @@
+<div dropdown
+ *ngIf="isDropdown">
+ <a dropdownToggle
+ class="dropdown-toggle"
+ data-toggle="dropdown"
+ i18n-title
+ title="Select a Language">
+ {{ supportedLanguages[selectedLanguage] }}
+ <span class="caret"></span>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu dropdown-menu-right">
+ <li *ngFor="let lang of supportedLanguages | keyvalue">
+ <a class="dropdown-item"
+ (click)="changeLanguage(lang.key)">{{ lang.value }}</a>
+ </li>
+ </ul>
+</div>
+
+<select *ngIf="!isDropdown"
+ (change)="changeLanguage($event.target.value)"
+ [(ngModel)]="selectedLanguage"
+ class="form-control">
+ <option *ngFor="let lang of supportedLanguages | keyvalue"
+ [value]="lang.key">{{ lang.value }}</option>
+</select>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.spec.ts
new file mode 100644
index 00000000..3b3f2b7e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.spec.ts
@@ -0,0 +1,90 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+
+import { listLocales } from 'ngx-bootstrap/chronos';
+import { BsLocaleService } from 'ngx-bootstrap/datepicker';
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { LanguageSelectorComponent } from './language-selector.component';
+
+describe('LanguageSelectorComponent', () => {
+ let component: LanguageSelectorComponent;
+ let fixture: ComponentFixture<LanguageSelectorComponent>;
+
+ configureTestBed({
+ declarations: [LanguageSelectorComponent],
+ providers: [BsLocaleService],
+ imports: [FormsModule, HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LanguageSelectorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ spyOn(window.location, 'reload').and.callFake(() => component.ngOnInit());
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should read current language', () => {
+ expect(component.selectedLanguage).toBe('en-US');
+ expect(listLocales()).toEqual([]);
+ });
+
+ const expectLanguageChange = (lang) => {
+ component.changeLanguage(lang);
+ const cookie = document.cookie.split(';').filter((item) => item.includes(`cd-lang=${lang}`));
+ expect(cookie.length).toBe(1);
+ };
+
+ it('should change to cs', () => {
+ expectLanguageChange('cs');
+ });
+
+ it('should change to de-DE', () => {
+ expectLanguageChange('de-DE');
+ });
+
+ it('should change to es-ES', () => {
+ expectLanguageChange('es-ES');
+ });
+
+ it('should change to fr-FR', () => {
+ expectLanguageChange('fr-FR');
+ });
+
+ it('should change to id-ID', () => {
+ expectLanguageChange('id-ID');
+ });
+
+ it('should change to it-IT', () => {
+ expectLanguageChange('it-IT');
+ });
+
+ it('should change to ja-JP', () => {
+ expectLanguageChange('ja-JP');
+ });
+
+ it('should change to ko-KR', () => {
+ expectLanguageChange('ko-KR');
+ });
+
+ it('should change to pl-PL', () => {
+ expectLanguageChange('pl-PL');
+ });
+
+ it('should change to pt-BR', () => {
+ expectLanguageChange('pt-BR');
+ });
+
+ it('should change to zh-CN', () => {
+ expectLanguageChange('zh-CN');
+ });
+
+ it('should change to zh-TW', () => {
+ expectLanguageChange('zh-TW');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.ts
new file mode 100644
index 00000000..032ae420
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/language-selector.component.ts
@@ -0,0 +1,59 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import * as _ from 'lodash';
+import { defineLocale } from 'ngx-bootstrap/chronos';
+import { BsLocaleService } from 'ngx-bootstrap/datepicker';
+
+import { LanguageService } from '../../services/language.service';
+import { languageBootstrapMapping, SupportedLanguages } from './supported-languages.enum';
+
+@Component({
+ selector: 'cd-language-selector',
+ templateUrl: './language-selector.component.html',
+ styleUrls: ['./language-selector.component.scss']
+})
+export class LanguageSelectorComponent implements OnInit {
+ @Input()
+ isDropdown = true;
+
+ supportedLanguages: Object = SupportedLanguages;
+ selectedLanguage: string;
+
+ constructor(private localeService: BsLocaleService, private languageService: LanguageService) {}
+
+ ngOnInit() {
+ this.selectedLanguage = this.languageService.getLocale();
+ this.defineUsedLanguage();
+
+ this.languageService.getLanguages().subscribe((langs) => {
+ this.supportedLanguages = _.pick(this.supportedLanguages, langs) as Object;
+ });
+ }
+
+ /**
+ * Sets ngx-bootstrap local based on the current language selection
+ *
+ * ngx-bootstrap locals documentation:
+ * https://valor-software.com/ngx-bootstrap/#/datepicker#locales
+ */
+ private defineUsedLanguage() {
+ const lang = this.selectedLanguage.slice(0, 2);
+ if (lang in languageBootstrapMapping) {
+ defineLocale(lang, languageBootstrapMapping[lang]);
+ this.localeService.use(lang);
+ }
+ }
+
+ /**
+ * Jest is being more restricted regarding spying on the reload method.
+ * This will allow us to spyOn this method instead.
+ */
+ reloadWindow() {
+ window.location.reload();
+ }
+
+ changeLanguage(lang: string) {
+ this.languageService.setLocale(lang);
+ this.reloadWindow();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/supported-languages.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/supported-languages.enum.ts
new file mode 100644
index 00000000..4a771d59
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/language-selector/supported-languages.enum.ts
@@ -0,0 +1,47 @@
+import {
+ csLocale,
+ deLocale,
+ esLocale,
+ frLocale,
+ idLocale,
+ itLocale,
+ jaLocale,
+ koLocale,
+ plLocale,
+ ptBrLocale,
+ zhCnLocale
+} from 'ngx-bootstrap/chronos';
+
+// When adding a new supported language make sure to add a test for it in:
+// language-selector.component.spec.ts
+export enum SupportedLanguages {
+ 'cs' = 'Čeština',
+ 'de-DE' = 'Deutsch',
+ 'en-US' = 'English',
+ 'es-ES' = 'Español',
+ 'fr-FR' = 'Français',
+ 'id-ID' = 'Bahasa Indonesia',
+ 'it-IT' = 'Italiano',
+ 'ja-JP' = '日本語',
+ 'ko-KR' = '한국어',
+ 'pl-PL' = 'Polski',
+ 'pt-BR' = 'Português',
+ 'zh-CN' = '中文 (简体)',
+ 'zh-TW' = '中文 (繁體)'
+}
+
+// Supported languages:
+// https://github.com/valor-software/ngx-bootstrap/tree/development/src/chronos/i18n
+export let languageBootstrapMapping = {
+ cs: csLocale,
+ de: deLocale,
+ es: esLocale,
+ fr: frLocale,
+ id: idLocale,
+ it: itLocale,
+ ja: jaLocale,
+ ko: koLocale,
+ pl: plLocale,
+ pt: ptBrLocale,
+ zh: zhCnLocale
+};
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.html
new file mode 100644
index 00000000..4aca2357
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.html
@@ -0,0 +1,7 @@
+<alert type="info">
+ <strong>
+ <i class="fa fa-spinner fa-spin fa-fw"
+ aria-hidden="true"></i>
+ </strong>
+ <ng-content></ng-content>
+</alert>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.spec.ts
new file mode 100644
index 00000000..3bdb0799
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { LoadingPanelComponent } from './loading-panel.component';
+
+describe('LoadingPanelComponent', () => {
+ let component: LoadingPanelComponent;
+ let fixture: ComponentFixture<LoadingPanelComponent>;
+
+ configureTestBed({
+ declarations: [LoadingPanelComponent],
+ imports: [AlertModule.forRoot()]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoadingPanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.ts
new file mode 100644
index 00000000..17d02a76
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/loading-panel/loading-panel.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'cd-loading-panel',
+ templateUrl: './loading-panel.component.html',
+ styleUrls: ['./loading-panel.component.scss']
+})
+export class LoadingPanelComponent {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.html
new file mode 100644
index 00000000..9f56f9ef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.html
@@ -0,0 +1,13 @@
+<div class="modal-header">
+ <h4 class="modal-title pull-left">
+ <ng-content select=".modal-title"></ng-content>
+ </h4>
+ <button type="button"
+ class="close pull-right"
+ aria-label="Close"
+ (click)="close()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+</div>
+
+<ng-content select=".modal-content"></ng-content>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.scss
new file mode 100644
index 00000000..4b3e4e26
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.scss
@@ -0,0 +1,17 @@
+@import '../../../../defaults';
+
+.modal-header {
+ @include hf;
+ border-radius: 5px 5px 0 0;
+}
+
+::ng-deep .modal-footer {
+ @include hf;
+ border-radius: 0 0 5px 5px;
+}
+
+::ng-deep .modal-body {
+ max-height: 70vh;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.spec.ts
new file mode 100644
index 00000000..a43ece29
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.spec.ts
@@ -0,0 +1,42 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ModalComponent } from './modal.component';
+
+describe('ModalComponent', () => {
+ let component: ModalComponent;
+ let fixture: ComponentFixture<ModalComponent>;
+
+ configureTestBed({
+ imports: [ModalModule.forRoot()],
+ declarations: [ModalComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should call the hide callback function', () => {
+ spyOn(component.hide, 'emit');
+ const nativeElement = fixture.nativeElement;
+ const button = nativeElement.querySelector('button');
+ button.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ expect(component.hide.emit).toHaveBeenCalled();
+ });
+
+ it('should hide the modal', () => {
+ component.modalRef = new BsModalRef();
+ spyOn(component.modalRef, 'hide');
+ component.close();
+ expect(component.modalRef.hide).toHaveBeenCalled();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.ts
new file mode 100644
index 00000000..656e234c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/modal/modal.component.ts
@@ -0,0 +1,28 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+@Component({
+ selector: 'cd-modal',
+ templateUrl: './modal.component.html',
+ styleUrls: ['./modal.component.scss']
+})
+export class ModalComponent {
+ @Input()
+ modalRef: BsModalRef;
+
+ /**
+ * Should be a function that is triggered when the modal is hidden.
+ */
+ @Output()
+ hide = new EventEmitter();
+
+ constructor() {}
+
+ close() {
+ if (this.modalRef) {
+ this.modalRef.hide();
+ }
+ this.hide.emit();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.html
new file mode 100644
index 00000000..ce904653
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.html
@@ -0,0 +1,18 @@
+<div class="row">
+ <div class="col-xs-5 col-sm-2 refresh-selector">
+ <label class="control-label col-xs-5 col-sm-5"
+ for="refreshInterval">
+ <span i18n>Refresh</span>
+ </label>
+ <div class="col-xs-7 col-sm-7">
+ <select id="refreshInterval"
+ name="refreshInterval"
+ class="form-control"
+ (change)="changeRefreshInterval($event.target.value)"
+ [(ngModel)]="selectedInterval">
+ <option *ngFor="let key of intervalKeys"
+ [value]="intervalList[key]">{{ key }}</option>
+ </select>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.scss
new file mode 100644
index 00000000..3440b874
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.scss
@@ -0,0 +1,26 @@
+.refresh-selector {
+ padding: 0;
+ float: right;
+ margin-right: 60px;
+
+ * {
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ label {
+ padding: 10px 10px 0 0;
+ text-align: right;
+ margin: 0;
+ }
+
+ @media (min-width: 500px) and (max-width: 767px) {
+ width: 24vw;
+ }
+ @media (min-width: 1200px) {
+ width: 12vw;
+ }
+ @media (min-width: 1400px) {
+ width: 10vw;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.spec.ts
new file mode 100644
index 00000000..87389fcc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.spec.ts
@@ -0,0 +1,28 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+
+import { RefreshIntervalService } from '../../services/refresh-interval.service';
+import { RefreshSelectorComponent } from './refresh-selector.component';
+
+describe('RefreshSelectorComponent', () => {
+ let component: RefreshSelectorComponent;
+ let fixture: ComponentFixture<RefreshSelectorComponent>;
+
+ configureTestBed({
+ imports: [FormsModule],
+ declarations: [RefreshSelectorComponent],
+ providers: [RefreshIntervalService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RefreshSelectorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.ts
new file mode 100644
index 00000000..632ddf6f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/refresh-selector/refresh-selector.component.ts
@@ -0,0 +1,32 @@
+import { Component, OnInit } from '@angular/core';
+
+import { RefreshIntervalService } from '../../services/refresh-interval.service';
+
+@Component({
+ selector: 'cd-refresh-selector',
+ templateUrl: './refresh-selector.component.html',
+ styleUrls: ['./refresh-selector.component.scss']
+})
+export class RefreshSelectorComponent implements OnInit {
+ selectedInterval: number;
+ intervalList: { [key: string]: number } = {
+ '5 s': 5000,
+ '10 s': 10000,
+ '15 s': 15000,
+ '30 s': 30000,
+ '1 min': 60000,
+ '3 min': 180000,
+ '5 min': 300000
+ };
+ intervalKeys = Object.keys(this.intervalList);
+
+ constructor(private refreshIntervalService: RefreshIntervalService) {}
+
+ ngOnInit() {
+ this.selectedInterval = this.refreshIntervalService.getRefreshInterval() || 5000;
+ }
+
+ changeRefreshInterval(interval: number) {
+ this.refreshIntervalService.setRefreshInterval(interval);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.html
new file mode 100644
index 00000000..d7f55179
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.html
@@ -0,0 +1,22 @@
+<cd-select #cdSelect
+ [data]="data"
+ [options]="options"
+ [messages]="messages"
+ [selectionLimit]="selectionLimit"
+ [customBadges]="customBadges"
+ [customBadgeValidators]="customBadgeValidators"
+ elemClass="margin-right-sm select-menu-edit"
+ (selection)="selection.emit($event)">
+ <i class="fa fa-fw fa-pencil"></i>
+</cd-select>
+
+<span *ngFor="let dataItem of data">
+ <span class="badge badge-pill badge-primary margin-right-sm">
+ <span class="margin-right-sm">{{ dataItem }}</span>
+ <a class="badge-remove"
+ (click)="cdSelect.removeItem(dataItem)">
+ <i class="fa fa-times"
+ aria-hidden="true"></i>
+ </a>
+ </span>
+</span>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.scss
new file mode 100644
index 00000000..d5f2a30d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.scss
@@ -0,0 +1,8 @@
+@import '../../../../defaults';
+
+::ng-deep .select-menu-edit {
+ margin-left: -20px;
+}
+.badge-remove {
+ color: $color-solid-white;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.spec.ts
new file mode 100644
index 00000000..bd4cc250
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.spec.ts
@@ -0,0 +1,61 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule, Validators } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SelectMessages } from '../select/select-messages.model';
+import { SelectComponent } from '../select/select.component';
+import { SelectBadgesComponent } from './select-badges.component';
+
+describe('SelectBadgesComponent', () => {
+ let component: SelectBadgesComponent;
+ let fixture: ComponentFixture<SelectBadgesComponent>;
+
+ configureTestBed({
+ declarations: [SelectBadgesComponent, SelectComponent],
+ imports: [PopoverModule.forRoot(), TooltipModule, ReactiveFormsModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SelectBadgesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should reflect the attributes into CdSelect', () => {
+ const data = ['a', 'b'];
+ const options = [
+ { name: 'option1', description: '', selected: false, enabled: true },
+ { name: 'option2', description: '', selected: false, enabled: true }
+ ];
+ const i18n = TestBed.get(I18n);
+ const messages = new SelectMessages({ empty: 'foo bar' }, i18n);
+ const selectionLimit = 2;
+ const customBadges = true;
+ const customBadgeValidators = [Validators.required];
+
+ component.data = data;
+ component.options = options;
+ component.messages = messages;
+ component.selectionLimit = selectionLimit;
+ component.customBadges = customBadges;
+ component.customBadgeValidators = customBadgeValidators;
+
+ fixture.detectChanges();
+
+ expect(component.cdSelect.data).toEqual(data);
+ expect(component.cdSelect.options).toEqual(options);
+ expect(component.cdSelect.messages).toEqual(messages);
+ expect(component.cdSelect.selectionLimit).toEqual(selectionLimit);
+ expect(component.cdSelect.customBadges).toEqual(customBadges);
+ expect(component.cdSelect.customBadgeValidators).toEqual(customBadgeValidators);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.ts
new file mode 100644
index 00000000..c275095e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select-badges/select-badges.component.ts
@@ -0,0 +1,36 @@
+import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import { ValidatorFn } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { SelectMessages } from '../select/select-messages.model';
+import { SelectOption } from '../select/select-option.model';
+
+@Component({
+ selector: 'cd-select-badges',
+ templateUrl: './select-badges.component.html',
+ styleUrls: ['./select-badges.component.scss']
+})
+export class SelectBadgesComponent {
+ @Input()
+ data: Array<string> = [];
+ @Input()
+ options: Array<SelectOption> = [];
+ @Input()
+ messages = new SelectMessages({}, this.i18n);
+ @Input()
+ selectionLimit: number;
+ @Input()
+ customBadges = false;
+ @Input()
+ customBadgeValidators: ValidatorFn[] = [];
+
+ @Output()
+ selection = new EventEmitter();
+
+ @ViewChild('cdSelect')
+ cdSelect;
+
+ constructor(private i18n: I18n) {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-messages.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-messages.model.ts
new file mode 100644
index 00000000..94f8c997
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-messages.model.ts
@@ -0,0 +1,29 @@
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import * as _ from 'lodash';
+
+export class SelectMessages {
+ i18n: I18n;
+
+ empty: string;
+ selectionLimit: any;
+ customValidations = {};
+ filter: string;
+ add: string;
+ noOptions: string;
+
+ constructor(messages: {}, i18n: I18n) {
+ this.i18n = i18n;
+
+ this.empty = this.i18n('No items selected.');
+ this.selectionLimit = {
+ tooltip: this.i18n('Deselect item to select again'),
+ text: this.i18n('Selection limit reached')
+ };
+ this.filter = this.i18n('Filter tags');
+ this.add = this.i18n('Add badge'); // followed by " '{{filter.value}}'"
+ this.noOptions = this.i18n('There are no items available.');
+
+ _.merge(this, messages);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-option.model.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-option.model.ts
new file mode 100644
index 00000000..bbd970c6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select-option.model.ts
@@ -0,0 +1,13 @@
+export class SelectOption {
+ selected: boolean;
+ name: string;
+ description: string;
+ enabled: boolean;
+
+ constructor(selected: boolean, name: string, description: string, enabled = true) {
+ this.selected = selected;
+ this.name = name;
+ this.description = description;
+ this.enabled = enabled;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.html
new file mode 100644
index 00000000..72682dbd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.html
@@ -0,0 +1,79 @@
+<ng-template #popTemplate>
+ <form name="form"
+ #formDir="ngForm"
+ [formGroup]="form"
+ novalidate>
+ <div [ngClass]="{'has-error': form.showError('filter', formDir)}">
+ <input type="text"
+ formControlName="filter"
+ i18n-placeholder
+ [placeholder]="messages.filter"
+ (keyup)="$event.keyCode == 13 ? selectOption() : updateFilter()"
+ class="form-control text-center" />
+ <ng-container *ngFor="let error of Object.keys(messages.customValidations)">
+ <span class="help-block text-center"
+ *ngIf="form.showError('filter', formDir) && filter.hasError(error)">
+ {{ messages.customValidations[error] }}
+ </span>
+ </ng-container>
+ </div>
+ </form>
+ <div *ngFor="let option of filteredOptions"
+ class="select-menu-item"
+ [ngClass]="{'help-block disabled': (data.length === selectionLimit || !option.enabled) && !option.selected}"
+ (click)="triggerSelection(option)">
+ <div class="select-menu-item-icon">
+ <i class="fa fa-check"
+ aria-hidden="true"
+ *ngIf="option.selected"></i>
+ &nbsp;
+ </div>
+ <div class="select-menu-item-content">
+ {{ option.name }}
+ <ng-container *ngIf="option.description">
+ <br>
+ <small class="text-muted">
+ {{ option.description }}&nbsp;
+ </small>
+ </ng-container>
+ </div>
+ </div>
+ <div *ngIf="isCreatable()"
+ class="select-menu-item"
+ (click)="addCustomOption(filter.value)">
+ <div class="select-menu-item-icon">
+ <i class="fa fa-tag"
+ aria-hidden="true"></i>
+ &nbsp;
+ </div>
+ <div class="select-menu-item-content">
+ {{ messages.add }} '{{ filter.value }}'
+ </div>
+ </div>
+ <div class="has-warning"
+ *ngIf="data.length === selectionLimit">
+ <span class="help-block text-center text-warning"
+ [tooltip]="messages.selectionLimit.tooltip"
+ *ngIf="data.length === selectionLimit">
+ {{ messages.selectionLimit.text }}
+ </span>
+ </div>
+</ng-template>
+
+<a class="select-menu-edit"
+ [ngClass]="elemClass"
+ [popover]="popTemplate"
+ placement="bottom"
+ container="body"
+ outsideClick="true"
+ *ngIf="options.length > 0">
+ <ng-content></ng-content>
+</a>
+<span class="text-muted"
+ *ngIf="data.length === 0 && options.length > 0">
+ {{ messages.empty }}
+</span>
+<span class="text-muted"
+ *ngIf="options.length === 0">
+ {{ messages.noOptions }}
+</span>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.scss
new file mode 100644
index 00000000..59f633f7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.scss
@@ -0,0 +1,19 @@
+@import '../../../../defaults';
+
+.select-menu-item {
+ display: block;
+ cursor: pointer;
+ border-bottom: 1px solid $color-transparent;
+ font-size: 12px;
+ &:hover {
+ background-color: $color-whitesmoke-gray;
+ }
+}
+.select-menu-item-icon {
+ float: left;
+ padding: 0.5em;
+ width: 3em;
+}
+.select-menu-item-content {
+ padding: 0.5em;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.spec.ts
new file mode 100644
index 00000000..45e82673
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.spec.ts
@@ -0,0 +1,278 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule, Validators } from '@angular/forms';
+
+import { PopoverModule } from 'ngx-bootstrap/popover';
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SelectOption } from './select-option.model';
+import { SelectComponent } from './select.component';
+
+describe('SelectComponent', () => {
+ let component: SelectComponent;
+ let fixture: ComponentFixture<SelectComponent>;
+
+ const selectOption = (filter: string) => {
+ component.filter.setValue(filter);
+ component.updateFilter();
+ component.selectOption();
+ };
+
+ configureTestBed({
+ declarations: [SelectComponent],
+ imports: [PopoverModule.forRoot(), TooltipModule, ReactiveFormsModule],
+ providers: i18nProviders
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SelectComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ component.options = [
+ { name: 'option1', description: '', selected: false, enabled: true },
+ { name: 'option2', description: '', selected: false, enabled: true },
+ { name: 'option3', description: '', selected: false, enabled: true }
+ ];
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should add item', () => {
+ component.data = [];
+ component.triggerSelection(component.options[1]);
+ expect(component.data).toEqual(['option2']);
+ });
+
+ it('should update selected', () => {
+ component.data = ['option2'];
+ component.ngOnChanges();
+ expect(component.options[0].selected).toBe(false);
+ expect(component.options[1].selected).toBe(true);
+ });
+
+ it('should remove item', () => {
+ component.options.map((option) => {
+ option.selected = true;
+ return option;
+ });
+ component.data = ['option1', 'option2', 'option3'];
+ component.removeItem('option1');
+ expect(component.data).toEqual(['option2', 'option3']);
+ });
+
+ it('should not remove item that is not selected', () => {
+ component.options[0].selected = true;
+ component.data = ['option1'];
+ component.removeItem('option2');
+ expect(component.data).toEqual(['option1']);
+ });
+
+ describe('filter values', () => {
+ beforeEach(() => {
+ component.ngOnInit();
+ });
+
+ it('shows all options with no value set', () => {
+ expect(component.filteredOptions).toEqual(component.options);
+ });
+
+ it('shows one option that it filtered for', () => {
+ component.filter.setValue('2');
+ component.updateFilter();
+ expect(component.filteredOptions).toEqual([component.options[1]]);
+ });
+
+ it('shows all options after selecting something', () => {
+ component.filter.setValue('2');
+ component.updateFilter();
+ component.selectOption();
+ expect(component.filteredOptions).toEqual(component.options);
+ });
+
+ it('is not able to create by default with no value set', () => {
+ component.updateFilter();
+ expect(component.isCreatable()).toBeFalsy();
+ });
+
+ it('is not able to create by default with a value set', () => {
+ component.filter.setValue('2');
+ component.updateFilter();
+ expect(component.isCreatable()).toBeFalsy();
+ });
+ });
+
+ describe('automatically add selected options if not in options array', () => {
+ beforeEach(() => {
+ component.data = ['option1', 'option4'];
+ expect(component.options.length).toBe(3);
+ });
+
+ const expectedResult = () => {
+ expect(component.options.length).toBe(4);
+ expect(component.options[3]).toEqual(new SelectOption(true, 'option4', ''));
+ };
+
+ it('with no extra settings', () => {
+ component.ngOnInit();
+ expectedResult();
+ });
+
+ it('with custom badges', () => {
+ component.customBadges = true;
+ component.ngOnInit();
+ expectedResult();
+ });
+
+ it('with limit higher than selected', () => {
+ component.selectionLimit = 3;
+ component.ngOnInit();
+ expectedResult();
+ });
+
+ it('with limit equal to selected', () => {
+ component.selectionLimit = 2;
+ component.ngOnInit();
+ expectedResult();
+ });
+
+ it('with limit lower than selected', () => {
+ component.selectionLimit = 1;
+ component.ngOnInit();
+ expectedResult();
+ });
+ });
+
+ describe('sorted array and options', () => {
+ beforeEach(() => {
+ component.customBadges = true;
+ component.customBadgeValidators = [Validators.pattern('[A-Za-z0-9_]+')];
+ component.data = ['c', 'b'];
+ component.options = [new SelectOption(true, 'd', ''), new SelectOption(true, 'a', '')];
+ component.ngOnInit();
+ });
+
+ it('has a sorted selection', () => {
+ expect(component.data).toEqual(['a', 'b', 'c', 'd']);
+ });
+
+ it('has a sorted options', () => {
+ const sortedOptions = [
+ new SelectOption(true, 'a', ''),
+ new SelectOption(true, 'b', ''),
+ new SelectOption(true, 'c', ''),
+ new SelectOption(true, 'd', '')
+ ];
+ expect(component.options).toEqual(sortedOptions);
+ });
+
+ it('has a sorted selection after adding an item', () => {
+ selectOption('block');
+ expect(component.data).toEqual(['a', 'b', 'block', 'c', 'd']);
+ });
+
+ it('has a sorted options after adding an item', () => {
+ selectOption('block');
+ const sortedOptions = [
+ new SelectOption(true, 'a', ''),
+ new SelectOption(true, 'b', ''),
+ new SelectOption(true, 'block', ''),
+ new SelectOption(true, 'c', ''),
+ new SelectOption(true, 'd', '')
+ ];
+ expect(component.options).toEqual(sortedOptions);
+ });
+ });
+
+ describe('with custom options', () => {
+ beforeEach(() => {
+ component.customBadges = true;
+ component.customBadgeValidators = [Validators.pattern('[A-Za-z0-9_]+')];
+ component.ngOnInit();
+ });
+
+ it('is not able to create with no value set', () => {
+ component.updateFilter();
+ expect(component.isCreatable()).toBeFalsy();
+ });
+
+ it('is able to create with a valid value set', () => {
+ component.filter.setValue('2');
+ component.updateFilter();
+ expect(component.isCreatable()).toBeTruthy();
+ });
+
+ it('is not able to create with a value set that already exist', () => {
+ component.filter.setValue('option2');
+ component.updateFilter();
+ expect(component.isCreatable()).toBeFalsy();
+ });
+
+ it('adds custom option', () => {
+ selectOption('customOption');
+ expect(component.options[0]).toEqual({
+ name: 'customOption',
+ description: '',
+ selected: true,
+ enabled: true
+ });
+ expect(component.options.length).toBe(4);
+ expect(component.data).toEqual(['customOption']);
+ });
+
+ it('will not add an option that did not pass the validation', () => {
+ selectOption(' this does not pass ');
+ expect(component.options.length).toBe(3);
+ expect(component.data).toEqual([]);
+ expect(component.filter.invalid).toBeTruthy();
+ });
+
+ it('removes custom item selection by name', () => {
+ selectOption('customOption');
+ component.removeItem('customOption');
+ expect(component.data).toEqual([]);
+ expect(component.options.length).toBe(4);
+ expect(component.options[0]).toEqual({
+ name: 'customOption',
+ description: '',
+ selected: false,
+ enabled: true
+ });
+ });
+
+ it('will not add an option that is already there', () => {
+ selectOption('option2');
+ expect(component.options.length).toBe(3);
+ expect(component.data).toEqual(['option2']);
+ });
+
+ it('will not add an option twice after each other', () => {
+ selectOption('onlyOnce');
+ expect(component.data).toEqual(['onlyOnce']);
+ selectOption('onlyOnce');
+ expect(component.data).toEqual([]);
+ selectOption('onlyOnce');
+ expect(component.data).toEqual(['onlyOnce']);
+ expect(component.options.length).toBe(4);
+ });
+ });
+
+ describe('if the selection limit is reached', function() {
+ beforeEach(() => {
+ component.selectionLimit = 2;
+ component.triggerSelection(component.options[0]);
+ component.triggerSelection(component.options[1]);
+ });
+
+ it('will not select more options', () => {
+ component.triggerSelection(component.options[2]);
+ expect(component.data).toEqual(['option1', 'option2']);
+ });
+
+ it('will unselect options that are selected', () => {
+ component.triggerSelection(component.options[1]);
+ expect(component.data).toEqual(['option1']);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.ts
new file mode 100644
index 00000000..1728acb5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/select/select.component.ts
@@ -0,0 +1,150 @@
+import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
+import { FormControl, ValidatorFn } from '@angular/forms';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { CdFormGroup } from '../../forms/cd-form-group';
+import { SelectMessages } from './select-messages.model';
+import { SelectOption } from './select-option.model';
+
+@Component({
+ selector: 'cd-select',
+ templateUrl: './select.component.html',
+ styleUrls: ['./select.component.scss']
+})
+export class SelectComponent implements OnInit, OnChanges {
+ @Input()
+ elemClass: string;
+ @Input()
+ data: Array<string> = [];
+ @Input()
+ options: Array<SelectOption> = [];
+ @Input()
+ messages = new SelectMessages({}, this.i18n);
+ @Input()
+ selectionLimit: number;
+ @Input()
+ customBadges = false;
+ @Input()
+ customBadgeValidators: ValidatorFn[] = [];
+
+ @Output()
+ selection = new EventEmitter();
+
+ form: CdFormGroup;
+ filter: FormControl;
+ Object = Object;
+ filteredOptions: Array<SelectOption> = [];
+
+ constructor(private i18n: I18n) {}
+
+ ngOnInit() {
+ this.initFilter();
+ if (this.data.length > 0) {
+ this.initMissingOptions();
+ }
+ this.options = _.sortBy(this.options, ['name']);
+ this.updateOptions();
+ }
+
+ private initFilter() {
+ this.filter = new FormControl('', { validators: this.customBadgeValidators });
+ this.form = new CdFormGroup({ filter: this.filter });
+ this.filteredOptions = [...(this.options || [])];
+ }
+
+ private initMissingOptions() {
+ const options = this.options.map((option) => option.name);
+ const needToCreate = this.data.filter((option) => options.indexOf(option) === -1);
+ needToCreate.forEach((option) => this.addOption(option));
+ this.forceOptionsToReflectData();
+ }
+
+ private addOption(name: string) {
+ this.options.push(new SelectOption(false, name, ''));
+ this.options = _.sortBy(this.options, ['name']);
+ this.triggerSelection(this.options.find((option) => option.name === name));
+ }
+
+ triggerSelection(option: SelectOption) {
+ if (
+ !option ||
+ (this.selectionLimit && !option.selected && this.data.length >= this.selectionLimit)
+ ) {
+ return;
+ }
+ option.selected = !option.selected;
+ this.updateOptions();
+ this.selection.emit({ option: option });
+ }
+
+ private updateOptions() {
+ this.data.splice(0, this.data.length);
+ this.options.forEach((option: SelectOption) => {
+ if (option.selected) {
+ this.data.push(option.name);
+ }
+ });
+ this.updateFilter();
+ }
+
+ updateFilter() {
+ this.filteredOptions = this.options.filter((option) => option.name.includes(this.filter.value));
+ }
+
+ private forceOptionsToReflectData() {
+ this.options.forEach((option) => {
+ if (this.data.indexOf(option.name) !== -1) {
+ option.selected = true;
+ }
+ });
+ }
+
+ ngOnChanges() {
+ if (this.filter) {
+ this.updateFilter();
+ }
+ if (!this.options || !this.data || this.data.length === 0) {
+ return;
+ }
+ this.forceOptionsToReflectData();
+ }
+
+ selectOption() {
+ if (this.filteredOptions.length === 0) {
+ this.addCustomOption();
+ } else {
+ this.triggerSelection(this.filteredOptions[0]);
+ this.resetFilter();
+ }
+ }
+
+ addCustomOption() {
+ if (!this.isCreatable()) {
+ return;
+ }
+ this.addOption(this.filter.value);
+ this.resetFilter();
+ }
+
+ isCreatable() {
+ return (
+ this.customBadges &&
+ this.filter.valid &&
+ this.filter.value.length > 0 &&
+ this.filteredOptions.every((option) => option.name !== this.filter.value)
+ );
+ }
+
+ private resetFilter() {
+ this.filter.setValue('');
+ this.updateFilter();
+ }
+
+ removeItem(item: string) {
+ this.triggerSelection(
+ this.options.find((option: SelectOption) => option.name === item && option.selected)
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.html
new file mode 100644
index 00000000..4b7a1b87
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.html
@@ -0,0 +1,13 @@
+<div class="chart-container"
+ [ngStyle]="style">
+ <canvas baseChart #sparkCanvas
+ [labels]="labels"
+ [datasets]="datasets"
+ [options]="options"
+ [colors]="colors"
+ [chartType]="'line'">
+ </canvas>
+ <div class="chartjs-tooltip" #sparkTooltip>
+ <table></table>
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.scss
new file mode 100644
index 00000000..ec7d9829
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.scss
@@ -0,0 +1,5 @@
+@import '../../../../styles/chart-tooltip.scss';
+
+.chart-container {
+ position: static !important;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.spec.ts
new file mode 100644
index 00000000..2aac8532
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.spec.ts
@@ -0,0 +1,53 @@
+import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { DimlessBinaryPipe } from '../../pipes/dimless-binary.pipe';
+import { FormatterService } from '../../services/formatter.service';
+import { SparklineComponent } from './sparkline.component';
+
+describe('SparklineComponent', () => {
+ let component: SparklineComponent;
+ let fixture: ComponentFixture<SparklineComponent>;
+
+ configureTestBed({
+ declarations: [SparklineComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ imports: [],
+ providers: [DimlessBinaryPipe, FormatterService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SparklineComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ expect(component.options.tooltips.custom).toBeDefined();
+ });
+
+ it('should update', () => {
+ expect(component.datasets).toEqual([{ data: [] }]);
+ expect(component.labels.length).toBe(0);
+
+ component.data = [11, 22, 33];
+ component.ngOnChanges({ data: new SimpleChange(null, component.data, false) });
+
+ expect(component.datasets).toEqual([{ data: [11, 22, 33] }]);
+ expect(component.labels.length).toBe(3);
+ });
+
+ it('should not transform the label, if not isBinary', () => {
+ component.isBinary = false;
+ const result = component.options.tooltips.callbacks.label({ yLabel: 1024 });
+ expect(result).toBe(1024);
+ });
+
+ it('should transform the label, if isBinary', () => {
+ component.isBinary = true;
+ const result = component.options.tooltips.callbacks.label({ yLabel: 1024 });
+ expect(result).toBe('1 KiB');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.ts
new file mode 100644
index 00000000..856eabf7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/sparkline/sparkline.component.ts
@@ -0,0 +1,123 @@
+import { Component, ElementRef, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
+import { Input } from '@angular/core';
+
+import { ChartTooltip } from '../../models/chart-tooltip';
+import { DimlessBinaryPipe } from '../../pipes/dimless-binary.pipe';
+
+@Component({
+ selector: 'cd-sparkline',
+ templateUrl: './sparkline.component.html',
+ styleUrls: ['./sparkline.component.scss']
+})
+export class SparklineComponent implements OnInit, OnChanges {
+ @ViewChild('sparkCanvas')
+ chartCanvasRef: ElementRef;
+ @ViewChild('sparkTooltip')
+ chartTooltipRef: ElementRef;
+
+ @Input()
+ data: any;
+ @Input()
+ style = {
+ height: '30px',
+ width: '100px'
+ };
+ @Input()
+ isBinary: boolean;
+
+ public colors: Array<any> = [
+ {
+ backgroundColor: 'rgba(40,140,234,0.2)',
+ borderColor: 'rgba(40,140,234,1)',
+ pointBackgroundColor: 'rgba(40,140,234,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(40,140,234,0.8)'
+ }
+ ];
+
+ options = {
+ animation: {
+ duration: 0
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ legend: {
+ display: false
+ },
+ elements: {
+ line: {
+ borderWidth: 1
+ }
+ },
+ tooltips: {
+ enabled: false,
+ mode: 'index',
+ intersect: false,
+ custom: undefined,
+ callbacks: {
+ label: (tooltipItem) => {
+ if (this.isBinary) {
+ return this.dimlessBinaryPipe.transform(tooltipItem.yLabel);
+ } else {
+ return tooltipItem.yLabel;
+ }
+ },
+ title: () => ''
+ }
+ },
+ scales: {
+ yAxes: [
+ {
+ display: false
+ }
+ ],
+ xAxes: [
+ {
+ display: false
+ }
+ ]
+ }
+ };
+
+ public datasets: Array<any> = [
+ {
+ data: []
+ }
+ ];
+
+ public labels: Array<any> = [];
+
+ constructor(private dimlessBinaryPipe: DimlessBinaryPipe) {}
+
+ ngOnInit() {
+ const getStyleTop = (tooltip) => {
+ return tooltip.caretY - tooltip.height - tooltip.yPadding - 5 + 'px';
+ };
+
+ const getStyleLeft = (tooltip, positionX) => {
+ return positionX + tooltip.caretX + 'px';
+ };
+
+ const chartTooltip = new ChartTooltip(
+ this.chartCanvasRef,
+ this.chartTooltipRef,
+ getStyleLeft,
+ getStyleTop
+ );
+
+ chartTooltip.customColors = {
+ backgroundColor: this.colors[0].pointBackgroundColor,
+ borderColor: this.colors[0].pointBorderColor
+ };
+
+ this.options.tooltips.custom = (tooltip) => {
+ chartTooltip.customTooltips(tooltip);
+ };
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ this.datasets[0].data = changes['data'].currentValue;
+ this.labels = [...Array(changes['data'].currentValue.length)];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.html
new file mode 100644
index 00000000..c5750e72
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.html
@@ -0,0 +1,9 @@
+<button [type]="type"
+ class="btn btn-sm btn-primary tc_submitButton"
+ [disabled]="loading || disabled"
+ (click)="submit($event)">
+ <ng-content></ng-content>
+ <span *ngIf="loading">
+ <i class="fa fa-spinner fa-spin fa-fw"></i>
+ </span>
+</button>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.spec.ts
new file mode 100644
index 00000000..795637a5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.spec.ts
@@ -0,0 +1,27 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormGroup } from '@angular/forms';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SubmitButtonComponent } from './submit-button.component';
+
+describe('SubmitButtonComponent', () => {
+ let component: SubmitButtonComponent;
+ let fixture: ComponentFixture<SubmitButtonComponent>;
+
+ configureTestBed({
+ declarations: [SubmitButtonComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubmitButtonComponent);
+ component = fixture.componentInstance;
+
+ component.form = new FormGroup({}, {});
+
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.ts
new file mode 100644
index 00000000..1b98d67e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/submit-button/submit-button.component.ts
@@ -0,0 +1,86 @@
+import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { AbstractControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+/**
+ * This component will render a submit button with the given label.
+ *
+ * The button will disabled itself and show a loading icon when the user clicks
+ * it, usually initiating a request to the server, and it will stay in that
+ * state until the request is finished.
+ *
+ * To indicate that the request failed, returning the button to the enable
+ * state, you need to insert an error in the form with the 'cdSubmitButton' key.
+ * p.e.: this.rbdForm.setErrors({'cdSubmitButton': true});
+ *
+ * It will also check if the form is valid, when clicking the button, and will
+ * focus on the first invalid input.
+ *
+ * @export
+ * @class SubmitButtonComponent
+ * @implements {OnInit}
+ */
+@Component({
+ selector: 'cd-submit-button',
+ templateUrl: './submit-button.component.html',
+ styleUrls: ['./submit-button.component.scss']
+})
+export class SubmitButtonComponent implements OnInit {
+ @Input()
+ form: FormGroup | NgForm;
+ @Input()
+ type = 'submit';
+ @Output()
+ submitAction = new EventEmitter();
+ @Input()
+ disabled = false;
+
+ loading = false;
+
+ constructor(private elRef: ElementRef) {}
+
+ ngOnInit() {
+ this.form.statusChanges.subscribe(() => {
+ if (_.has(this.form.errors, 'cdSubmitButton')) {
+ this.loading = false;
+ _.unset(this.form.errors, 'cdSubmitButton');
+ // Handle Reactive forms.
+ if (this.form instanceof AbstractControl) {
+ (<AbstractControl>this.form).updateValueAndValidity();
+ }
+ }
+ });
+ }
+
+ submit($event) {
+ this.focusButton();
+
+ // Special handling for Template driven forms.
+ if (this.form instanceof FormGroupDirective) {
+ (<FormGroupDirective>this.form).onSubmit($event);
+ }
+
+ if (this.form.invalid) {
+ this.focusInvalid();
+ return;
+ }
+
+ this.loading = true;
+ this.submitAction.emit();
+ }
+
+ focusButton() {
+ this.elRef.nativeElement.offsetParent.querySelector(`button[type="${this.type}"]`).focus();
+ }
+
+ focusInvalid() {
+ const target = this.elRef.nativeElement.offsetParent.querySelector(
+ 'input.ng-invalid, select.ng-invalid'
+ );
+
+ if (target) {
+ target.focus();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.html
new file mode 100644
index 00000000..c31a2eb4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.html
@@ -0,0 +1,26 @@
+<ng-template #usageTooltipTpl>
+ <table>
+ <tr>
+ <td class="text-left">Used:&nbsp;</td>
+ <td class="text-right"><strong> {{ isBinary ? (used | dimlessBinary) : (used | dimless) }}</strong></td>
+ </tr>
+ <tr>
+ <td class="text-left">Free:&nbsp;</td>
+ <td class="'text-right"><strong>{{ isBinary ? (total - used | dimlessBinary) : (total - used | dimless) }}</strong></td>
+ </tr>
+ </table>
+</ng-template>
+
+<div class="progress oaprogress"
+ data-placement="left"
+ [tooltip]="usageTooltipTpl">
+ <div class="progress-bar progress-bar-info"
+ role="progressbar"
+ [style.width]="usedPercentage + '%'">
+ <span>{{ usedPercentage | number: '1.0-' + decimals }}%</span>
+ </div>
+ <div class="progress-bar progress-bar-freespace"
+ role="progressbar"
+ [style.width]="freePercentage + '%'">
+ </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.spec.ts
new file mode 100644
index 00000000..334e601f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.spec.ts
@@ -0,0 +1,27 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TooltipModule } from 'ngx-bootstrap/tooltip';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { PipesModule } from '../../pipes/pipes.module';
+import { UsageBarComponent } from './usage-bar.component';
+
+describe('UsageBarComponent', () => {
+ let component: UsageBarComponent;
+ let fixture: ComponentFixture<UsageBarComponent>;
+
+ configureTestBed({
+ imports: [PipesModule, TooltipModule.forRoot()],
+ declarations: [UsageBarComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UsageBarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.ts
new file mode 100644
index 00000000..0d4256d8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/usage-bar/usage-bar.component.ts
@@ -0,0 +1,27 @@
+import { Component, Input, OnChanges } from '@angular/core';
+
+@Component({
+ selector: 'cd-usage-bar',
+ templateUrl: './usage-bar.component.html',
+ styleUrls: ['./usage-bar.component.scss']
+})
+export class UsageBarComponent implements OnChanges {
+ @Input()
+ total: number;
+ @Input()
+ used: number;
+ @Input()
+ decimals = 0;
+ @Input()
+ isBinary = true;
+
+ usedPercentage: number;
+ freePercentage: number;
+
+ constructor() {}
+
+ ngOnChanges() {
+ this.usedPercentage = this.total > 0 ? (this.used / this.total) * 100 : 0;
+ this.freePercentage = 100 - this.usedPercentage;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html
new file mode 100644
index 00000000..73e9ea6a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html
@@ -0,0 +1,15 @@
+<cd-info-panel *ngIf="status === vcs.ValueNone">
+ <ng-container i18n>Retrieving data<span *ngIf="statusFor"> for
+ <span [innerHtml]="statusFor"></span></span>. Please wait...</ng-container>
+</cd-info-panel>
+
+<cd-warning-panel *ngIf="status === vcs.ValueStale">
+ <ng-container i18n>Displaying previously cached data<span *ngIf="statusFor">
+ for <span [innerHtml]="statusFor"></span></span>.</ng-container>
+</cd-warning-panel>
+
+<cd-error-panel *ngIf="status === vcs.ValueException">
+ <ng-container i18n>Could not load data<span *ngIf="statusFor"> for
+ <span [innerHtml]="statusFor"></span></span>.
+ Please check the cluster health.</ng-container>
+</cd-error-panel>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts
new file mode 100644
index 00000000..f55b8a62
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts
@@ -0,0 +1,34 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ErrorPanelComponent } from '../error-panel/error-panel.component';
+import { InfoPanelComponent } from '../info-panel/info-panel.component';
+import { WarningPanelComponent } from '../warning-panel/warning-panel.component';
+import { ViewCacheComponent } from './view-cache.component';
+
+describe('ViewCacheComponent', () => {
+ let component: ViewCacheComponent;
+ let fixture: ComponentFixture<ViewCacheComponent>;
+
+ configureTestBed({
+ declarations: [
+ ErrorPanelComponent,
+ InfoPanelComponent,
+ ViewCacheComponent,
+ WarningPanelComponent
+ ],
+ imports: [AlertModule.forRoot()]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ViewCacheComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts
new file mode 100644
index 00000000..b0a806d0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts
@@ -0,0 +1,20 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
+
+@Component({
+ selector: 'cd-view-cache',
+ templateUrl: './view-cache.component.html',
+ styleUrls: ['./view-cache.component.scss']
+})
+export class ViewCacheComponent implements OnInit {
+ @Input()
+ status: ViewCacheStatus;
+ @Input()
+ statusFor: string;
+ vcs = ViewCacheStatus;
+
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.html
new file mode 100644
index 00000000..cf9bc8cb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.html
@@ -0,0 +1,18 @@
+<alert type="warning">
+ <table>
+ <tr>
+ <td rowspan="2" class="warning-panel-alert-icon">
+ <i class="fa fa-3x fa-warning alert-warning"
+ aria-hidden="true"></i>
+ </td>
+ <td class="warning-panel-alert-title">
+ {{ title }}
+ </td>
+ </tr>
+ <tr>
+ <td class="warning-panel-alert-text">
+ <ng-content></ng-content>
+ </td>
+ </tr>
+ </table>
+</alert>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.scss
new file mode 100644
index 00000000..b47e386f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.scss
@@ -0,0 +1,9 @@
+.warning-panel-alert-icon {
+ vertical-align: top;
+ padding-right: 15px; // See @alert-padding in bootstrap/less/variables.less
+}
+.warning-panel-alert-title {
+ font-weight: bold;
+}
+.warning-panel-alert-text {
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.spec.ts
new file mode 100644
index 00000000..834aebe6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap/alert';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { WarningPanelComponent } from './warning-panel.component';
+
+describe('WarningPanelComponent', () => {
+ let component: WarningPanelComponent;
+ let fixture: ComponentFixture<WarningPanelComponent>;
+
+ configureTestBed({
+ declarations: [WarningPanelComponent],
+ imports: [AlertModule.forRoot()]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(WarningPanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.ts
new file mode 100644
index 00000000..cdbf71f3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/warning-panel/warning-panel.component.ts
@@ -0,0 +1,15 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'cd-warning-panel',
+ templateUrl: './warning-panel.component.html',
+ styleUrls: ['./warning-panel.component.scss']
+})
+export class WarningPanelComponent {
+ /**
+ * The title to be displayed. Defaults to 'Warning'.
+ * @type {string}
+ */
+ @Input()
+ title = 'Warning';
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts
new file mode 100644
index 00000000..6c148fde
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/constants/app.constants.ts
@@ -0,0 +1,198 @@
+import { Injectable } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+export class AppConstants {
+ public static readonly organization = 'ceph';
+ public static readonly projectName = 'Ceph Manager Dashboard';
+ public static readonly license = 'Free software (LGPL 2.1).';
+}
+
+export enum URLVerbs {
+ /* Create a new item */
+ CREATE = 'create',
+
+ /* Make changes to an existing item */
+ EDIT = 'edit',
+
+ /* Make changes to an existing item */
+ UPDATE = 'update',
+
+ /* Remove an item from a container WITHOUT deleting it */
+ REMOVE = 'remove',
+
+ /* Destroy an existing item */
+ DELETE = 'delete',
+
+ /* Add an existing item to a container */
+ ADD = 'add',
+
+ /* Non-standard verbs */
+ COPY = 'copy',
+ CLONE = 'clone',
+
+ /* Prometheus wording */
+ RECREATE = 'recreate',
+ EXPIRE = 'expire'
+}
+
+export enum ActionLabels {
+ /* Create a new item */
+ CREATE = 'Create',
+
+ /* Destroy an existing item */
+ DELETE = 'Delete',
+
+ /* Add an existing item to a container */
+ ADD = 'Add',
+
+ /* Remove an item from a container WITHOUT deleting it */
+ REMOVE = 'Remove',
+
+ /* Make changes to an existing item */
+ EDIT = 'Edit',
+
+ /* */
+ CANCEL = 'Cancel',
+
+ /* Non-standard actions */
+ COPY = 'Copy',
+ CLONE = 'Clone',
+
+ /* Read-only */
+ SHOW = 'Show',
+
+ /* Prometheus wording */
+ RECREATE = 'Recreate',
+ EXPIRE = 'Expire'
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ActionLabelsI18n {
+ /* This service is required as the i18n polyfill does not provide static
+ translation
+ */
+ CREATE: string;
+ DELETE: string;
+ ADD: string;
+ REMOVE: string;
+ EDIT: string;
+ CANCEL: string;
+ COPY: string;
+ CLONE: string;
+ DEEP_SCRUB: string;
+ DESTROY: string;
+ FLATTEN: string;
+ MARK_DOWN: string;
+ MARK_IN: string;
+ MARK_LOST: string;
+ MARK_OUT: string;
+ PROTECT: string;
+ PURGE: string;
+ RENAME: string;
+ RESTORE: string;
+ REWEIGHT: string;
+ ROLLBACK: string;
+ SCRUB: string;
+ SHOW: string;
+ TRASH: string;
+ UNPROTECT: string;
+ RECREATE: string;
+ EXPIRE: string;
+
+ constructor(private i18n: I18n) {
+ /* Create a new item */
+ this.CREATE = this.i18n('Create');
+
+ /* Destroy an existing item */
+ this.DELETE = this.i18n('Delete');
+
+ /* Add an existing item to a container */
+ this.ADD = this.i18n('Add');
+
+ /* Remove an item from a container WITHOUT deleting it */
+ this.REMOVE = this.i18n('Remove');
+
+ /* Make changes to an existing item */
+ this.EDIT = this.i18n('Edit');
+ this.CANCEL = this.i18n('Cancel');
+
+ /* Non-standard actions */
+ this.CLONE = this.i18n('Clone');
+ this.COPY = this.i18n('Copy');
+ this.DEEP_SCRUB = this.i18n('Deep Scrub');
+ this.DESTROY = this.i18n('Destroy');
+ this.FLATTEN = this.i18n('Flatten');
+ this.MARK_DOWN = this.i18n('Mark Down');
+ this.MARK_IN = this.i18n('Mark In');
+ this.MARK_LOST = this.i18n('Mark Lost');
+ this.MARK_OUT = this.i18n('Mark Out');
+ this.PROTECT = this.i18n('Protect');
+ this.PURGE = this.i18n('Purge');
+ this.RENAME = this.i18n('Rename');
+ this.RESTORE = this.i18n('Restore');
+ this.REWEIGHT = this.i18n('Reweight');
+ this.ROLLBACK = this.i18n('Rollback');
+ this.SCRUB = this.i18n('Scrub');
+ this.SHOW = this.i18n('Show');
+ this.TRASH = this.i18n('Move to Trash');
+ this.UNPROTECT = this.i18n('Unprotect');
+
+ /* Prometheus wording */
+ this.RECREATE = this.i18n('Recreate');
+ this.EXPIRE = this.i18n('Expire');
+ }
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SucceededActionLabelsI18n {
+ /* This service is required as the i18n polyfill does not provide static
+ translation
+ */
+ CREATED: string;
+ DELETED: string;
+ ADDED: string;
+ REMOVED: string;
+ EDITED: string;
+ CANCELED: string;
+ COPIED: string;
+ CLONED: string;
+ SHOWED: string;
+ TRASHED: string;
+ UNPROTECTED: string;
+ RECREATED: string;
+ EXPIRED: string;
+
+ constructor(private i18n: I18n) {
+ /* Create a new item */
+ this.CREATED = this.i18n('Created');
+
+ /* Destroy an existing item */
+ this.DELETED = this.i18n('Deleted');
+
+ /* Add an existing item to a container */
+ this.ADDED = this.i18n('Added');
+
+ /* Remove an item from a container WITHOUT deleting it */
+ this.REMOVED = this.i18n('Removed');
+
+ /* Make changes to an existing item */
+ this.EDITED = this.i18n('Edited');
+ this.CANCELED = this.i18n('Canceled');
+
+ /* Non-standard actions */
+ this.CLONED = this.i18n('Cloned');
+ this.COPIED = this.i18n('Copied');
+ this.SHOWED = this.i18n('Showed');
+ this.TRASHED = this.i18n('Moved to Trash');
+ this.UNPROTECTED = this.i18n('Unprotected');
+
+ /* Prometheus wording */
+ this.RECREATED = this.i18n('Recreated');
+ this.EXPIRED = this.i18n('Expired');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts
new file mode 100644
index 00000000..479f6cab
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts
@@ -0,0 +1,28 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
+
+import { ComponentsModule } from '../components/components.module';
+import { PipesModule } from '../pipes/pipes.module';
+import { TableActionsComponent } from './table-actions/table-actions.component';
+import { TableKeyValueComponent } from './table-key-value/table-key-value.component';
+import { TableComponent } from './table/table.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ NgxDatatableModule,
+ FormsModule,
+ BsDropdownModule.forRoot(),
+ PipesModule,
+ ComponentsModule,
+ RouterModule
+ ],
+ declarations: [TableComponent, TableKeyValueComponent, TableActionsComponent],
+ exports: [TableComponent, NgxDatatableModule, TableKeyValueComponent, TableActionsComponent]
+})
+export class DataTableModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html
new file mode 100644
index 00000000..65ad67de
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html
@@ -0,0 +1,39 @@
+<div class="btn-group"
+ dropdown>
+ <ng-container *ngIf="getCurrentButton() as action">
+ <button type="button"
+ class="btn btn-sm btn-primary"
+ [ngClass]="{'disabled': disableSelectionAction(action)}"
+ (click)="useClickAction(action)"
+ [routerLink]="useRouterLink(action)"
+ [preserveFragment]="action.preserveFragment ? '' : null">
+ <i class="fa fa-fw {{ action.icon }}"></i><span>{{ action.name }}</span>
+ </button>
+ </ng-container>
+ <button type="button"
+ dropdownToggle
+ *ngIf="showDropDownActions()"
+ class="btn btn-sm btn-primary dropdown-toggle dropdown-toggle-split">
+ <ng-container *ngIf="onlyDropDown">{{ onlyDropDown }}</ng-container>
+ <span class="caret"></span>
+ <span *ngIf="!onlyDropDown"
+ class="sr-only"></span>
+ </button>
+ <ul *dropdownMenu
+ class="dropdown-menu"
+ role="menu">
+ <ng-container *ngFor="let action of dropDownActions">
+ <li role="menuitem"
+ class="{{ toClassName(action['name']) }}"
+ [ngClass]="{'disabled': disableSelectionAction(action)}"
+ data-toggle="tooltip" title="{{ useDisableDesc(action) }}">
+ <a class="dropdown-item"
+ (click)="useClickAction(action)"
+ [routerLink]="useRouterLink(action)"
+ [preserveFragment]="action.preserveFragment ? '' : null">
+ <i class="fa fa-fw {{ action.icon }}"></i><span>{{ action.name }}</span>
+ </a>
+ </li>
+ </ng-container>
+ </ul>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.scss
new file mode 100644
index 00000000..e3c3492a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.scss
@@ -0,0 +1,4 @@
+.dropdown-menu > .disabled > a {
+ pointer-events: auto;
+ cursor: default !important;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.spec.ts
new file mode 100644
index 00000000..45fcf511
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.spec.ts
@@ -0,0 +1,334 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, PermissionHelper } from '../../../../testing/unit-test-helper';
+import { ComponentsModule } from '../../components/components.module';
+import { CdTableAction } from '../../models/cd-table-action';
+import { CdTableSelection } from '../../models/cd-table-selection';
+import { Permission } from '../../models/permissions';
+import { TableActionsComponent } from './table-actions.component';
+
+describe('TableActionsComponent', () => {
+ let component: TableActionsComponent;
+ let fixture: ComponentFixture<TableActionsComponent>;
+ let addAction: CdTableAction;
+ let editAction: CdTableAction;
+ let protectAction: CdTableAction;
+ let unprotectAction: CdTableAction;
+ let deleteAction: CdTableAction;
+ let copyAction: CdTableAction;
+ let scenario;
+ let permissionHelper: PermissionHelper;
+
+ const setUpTableActions = () => {
+ component.tableActions = [
+ addAction,
+ editAction,
+ protectAction,
+ unprotectAction,
+ copyAction,
+ deleteAction
+ ];
+ };
+
+ const getTableActionComponent = (): TableActionsComponent => {
+ setUpTableActions();
+ component.ngOnInit();
+ return component;
+ };
+
+ configureTestBed({
+ declarations: [TableActionsComponent],
+ imports: [ComponentsModule, RouterTestingModule]
+ });
+
+ beforeEach(() => {
+ addAction = {
+ permission: 'create',
+ icon: 'fa-plus',
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSelection,
+ name: 'Add'
+ };
+ editAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ name: 'Edit'
+ };
+ copyAction = {
+ permission: 'create',
+ icon: 'fa-copy',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSingleSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSingleSelection || selection.first().cdExecuting,
+ name: 'Copy'
+ };
+ deleteAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSelection,
+ disable: (selection: CdTableSelection) =>
+ !selection.hasSelection || selection.first().cdExecuting,
+ name: 'Delete'
+ };
+ protectAction = {
+ permission: 'update',
+ icon: 'fa-lock',
+ canBePrimary: () => false,
+ visible: (selection: CdTableSelection) => selection.hasSingleSelection,
+ name: 'Protect'
+ };
+ unprotectAction = {
+ permission: 'update',
+ icon: 'fa-unlock',
+ canBePrimary: () => false,
+ visible: (selection: CdTableSelection) => !selection.hasSingleSelection,
+ name: 'Unprotect'
+ };
+ fixture = TestBed.createComponent(TableActionsComponent);
+ component = fixture.componentInstance;
+ component.selection = new CdTableSelection();
+ component.permission = new Permission();
+ component.permission.read = true;
+ permissionHelper = new PermissionHelper(component.permission, () => getTableActionComponent());
+ permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should ngInit should be called with no permissions', () => {
+ component.permission = undefined;
+ component.ngOnInit();
+ expect(component.tableActions).toEqual([]);
+ expect(component.dropDownActions).toEqual([]);
+ });
+
+ describe('useRouterLink', () => {
+ const testLink = '/api/some/link';
+ it('should use a link generated from a function', () => {
+ addAction.routerLink = () => testLink;
+ expect(component.useRouterLink(addAction)).toBe(testLink);
+ });
+
+ it('should use the link as it is because it is a string', () => {
+ addAction.routerLink = testLink;
+ expect(component.useRouterLink(addAction)).toBe(testLink);
+ });
+
+ it('should not return anything because no link is defined', () => {
+ expect(component.useRouterLink(addAction)).toBe(undefined);
+ });
+
+ it('should not return anything because the action is disabled', () => {
+ editAction.routerLink = testLink;
+ expect(component.useRouterLink(editAction)).toBe(undefined);
+ });
+ });
+
+ describe('disableSelectionAction', () => {
+ beforeEach(() => {
+ scenario = {
+ fn: () => null,
+ multiple: false,
+ singleExecuting: false,
+ single: false,
+ empty: false
+ };
+ });
+
+ it('tests disabling addAction', () => {
+ scenario.fn = () => component.disableSelectionAction(addAction);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('tests disabling editAction', () => {
+ scenario.fn = () => component.disableSelectionAction(editAction);
+ scenario.multiple = true;
+ scenario.empty = true;
+ scenario.singleExecuting = true;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('tests disabling deleteAction', () => {
+ scenario.fn = () => component.disableSelectionAction(deleteAction);
+ scenario.multiple = false;
+ scenario.empty = true;
+ scenario.singleExecuting = true;
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('tests disabling copyAction', () => {
+ scenario.fn = () => component.disableSelectionAction(copyAction);
+ scenario.multiple = true;
+ scenario.empty = true;
+ scenario.singleExecuting = true;
+ permissionHelper.testScenarios(scenario);
+ });
+ });
+
+ describe('get current button', () => {
+ const hiddenScenario = () => {
+ scenario.multiple = undefined;
+ scenario.empty = undefined;
+ scenario.singleExecuting = undefined;
+ scenario.single = undefined;
+ };
+
+ const setScenario = (defaultAction, selectionAction) => {
+ scenario.single = selectionAction;
+ scenario.singleExecuting = selectionAction;
+ scenario.multiple = defaultAction;
+ scenario.empty = defaultAction;
+ };
+
+ beforeEach(() => {
+ scenario = {
+ fn: () => component.getCurrentButton(),
+ singleExecuting: copyAction,
+ single: copyAction,
+ empty: addAction
+ };
+ });
+
+ it('gets add for no, edit for single and delete for multiple selections', () => {
+ setScenario(addAction, editAction);
+ scenario.multiple = deleteAction;
+ permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('gets add action except for selections where it shows edit action', () => {
+ setScenario(addAction, editAction);
+ permissionHelper.setPermissionsAndGetActions(1, 1, 0);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('gets add for no, copy for single and delete for multiple selections', () => {
+ setScenario(addAction, copyAction);
+ scenario.multiple = deleteAction;
+ permissionHelper.setPermissionsAndGetActions(1, 0, 1);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('gets add action except for selections where it shows copy action', () => {
+ setScenario(addAction, copyAction);
+ permissionHelper.setPermissionsAndGetActions(1, 0, 0);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('should always get edit action except delete for multiple items', () => {
+ setScenario(editAction, editAction);
+ scenario.multiple = deleteAction;
+ permissionHelper.setPermissionsAndGetActions(0, 1, 1);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('should always get edit action', () => {
+ setScenario(editAction, editAction);
+ permissionHelper.setPermissionsAndGetActions(0, 1, 0);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('should always get delete action', () => {
+ setScenario(deleteAction, deleteAction);
+ permissionHelper.setPermissionsAndGetActions(0, 0, 1);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('should not get any button with no permissions', () => {
+ hiddenScenario();
+ permissionHelper.setPermissionsAndGetActions(0, 0, 0);
+ permissionHelper.testScenarios(scenario);
+ });
+
+ it('should not get any button if only a drop down should be shown', () => {
+ hiddenScenario();
+ component.onlyDropDown = 'Drop down label';
+ permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+ permissionHelper.testScenarios(scenario);
+ });
+ });
+
+ describe('show drop down', () => {
+ const testShowDropDownActions = (perms, expected) => {
+ permissionHelper.setPermissionsAndGetActions(perms[0], perms[1], perms[2]);
+ expect(`${perms} ${component.showDropDownActions()}`).toBe(`${perms} ${expected}`);
+ };
+
+ it('is shown if multiple items are found depending on the permissions', () => {
+ [[1, 0, 0], [1, 1, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1], [0, 1, 0]].forEach((perms) => {
+ testShowDropDownActions(perms, true);
+ });
+ });
+
+ it('is not shown if only 1 or less items are found depending on the permissions', () => {
+ [[0, 0, 1], [0, 0, 0]].forEach((perms) => {
+ testShowDropDownActions(perms, false);
+ });
+ });
+ });
+
+ describe('with drop down only', () => {
+ beforeEach(() => {
+ component.onlyDropDown = 'displayMe';
+ });
+
+ it('should not return any button with getCurrentButton', () => {
+ expect(component.getCurrentButton()).toBeFalsy();
+ });
+ });
+
+ it('should convert any name to a proper CSS class', () => {
+ expect(component.toClassName('Create')).toBe('create');
+ expect(component.toClassName('Mark x down')).toBe('mark-x-down');
+ expect(component.toClassName('?Su*per!')).toBe('super');
+ });
+
+ describe('useDisableDesc', () => {
+ it('should return a description if disableDesc is set for action', () => {
+ const deleteWithDescAction: CdTableAction = {
+ permission: 'delete',
+ icon: 'fa-times',
+ canBePrimary: (selection: CdTableSelection) => selection.hasSelection,
+ disableDesc: () => {
+ return 'Delete action disabled description';
+ },
+ name: 'DeleteDesc'
+ };
+
+ expect(component.useDisableDesc(deleteWithDescAction)).toBe(
+ 'Delete action disabled description'
+ );
+ });
+
+ it('should return no description if disableDesc is not set for action', () => {
+ expect(component.useDisableDesc(deleteAction)).toBeUndefined();
+ });
+ });
+
+ describe('useClickAction', () => {
+ const editClickAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ name: 'Edit',
+ click: () => {
+ return 'Edit action click';
+ }
+ };
+
+ it('should call click action if action is not disabled', () => {
+ editClickAction.disable = () => {
+ return false;
+ };
+ expect(component.useClickAction(editClickAction)).toBe('Edit action click');
+ });
+
+ it('should not call click action if action is disabled', () => {
+ editClickAction.disable = () => {
+ return true;
+ };
+ expect(component.useClickAction(editClickAction)).toBeFalsy();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts
new file mode 100644
index 00000000..62f33aca
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts
@@ -0,0 +1,148 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { CdTableAction } from '../../models/cd-table-action';
+import { CdTableSelection } from '../../models/cd-table-selection';
+import { Permission } from '../../models/permissions';
+
+@Component({
+ selector: 'cd-table-actions',
+ templateUrl: './table-actions.component.html',
+ styleUrls: ['./table-actions.component.scss']
+})
+export class TableActionsComponent implements OnInit {
+ @Input()
+ permission: Permission;
+ @Input()
+ selection: CdTableSelection;
+ @Input()
+ tableActions: CdTableAction[];
+
+ // Use this if you just want to display a drop down button,
+ // labeled with the given text, with all actions in it.
+ // This disables the main action button.
+ @Input()
+ onlyDropDown?: string;
+
+ // Array with all visible actions
+ dropDownActions: CdTableAction[] = [];
+
+ constructor() {}
+
+ ngOnInit() {
+ this.removeActionsWithNoPermissions();
+ this.updateDropDownActions();
+ }
+
+ toClassName(name: string): string {
+ return name
+ .replace(/ /g, '-')
+ .replace(/[^a-z-]/gi, '')
+ .toLowerCase();
+ }
+
+ /**
+ * Removes all actions from 'tableActions' that need a permission the user doesn't have.
+ */
+ private removeActionsWithNoPermissions() {
+ if (!this.permission) {
+ this.tableActions = [];
+ return;
+ }
+ const permissions = Object.keys(this.permission).filter((key) => this.permission[key]);
+ this.tableActions = this.tableActions.filter((action) =>
+ permissions.includes(action.permission)
+ );
+ }
+
+ private updateDropDownActions() {
+ this.dropDownActions = this.tableActions.filter((action) =>
+ action.visible ? action.visible(this.selection) : action
+ );
+ }
+
+ /**
+ * Finds the next action that is used as main action for the button
+ *
+ * The order of the list is crucial to get the right main action.
+ *
+ * Default button conditions of actions:
+ * - 'create' actions can be used with no or multiple selections
+ * - 'update' and 'delete' actions can be used with one selection
+ *
+ * @returns {CdTableAction}
+ */
+ getCurrentButton(): CdTableAction {
+ if (this.onlyDropDown) {
+ return;
+ }
+ let buttonAction = this.dropDownActions.find((tableAction) => this.showableAction(tableAction));
+ if (!buttonAction && this.dropDownActions.length > 0) {
+ buttonAction = this.dropDownActions[0];
+ }
+ return buttonAction;
+ }
+
+ /**
+ * Determines if action can be used for the button
+ *
+ * @param {CdTableAction} action
+ * @returns {boolean}
+ */
+ private showableAction(action: CdTableAction): boolean {
+ const condition = action.canBePrimary;
+ const singleSelection = this.selection.hasSingleSelection;
+ const defaultCase = action.permission === 'create' ? !singleSelection : singleSelection;
+ return (condition && condition(this.selection)) || (!condition && defaultCase);
+ }
+
+ useRouterLink(action: CdTableAction): string {
+ if (!action.routerLink || this.disableSelectionAction(action)) {
+ return;
+ }
+ return _.isString(action.routerLink) ? action.routerLink : action.routerLink();
+ }
+
+ /**
+ * Determines if an action should be disabled
+ *
+ * Default disable conditions of 'update' and 'delete' actions:
+ * - If no or multiple selections are made
+ * - If one selection is made, but a task is executed on that item
+ *
+ * @param {CdTableAction} action
+ * @returns {Boolean}
+ */
+ disableSelectionAction(action: CdTableAction): Boolean {
+ const permission = action.permission;
+ const disable = action.disable;
+ if (disable) {
+ return Boolean(disable(this.selection));
+ }
+ const selected = this.selection.hasSingleSelection && this.selection.first();
+ return Boolean(
+ ['update', 'delete'].includes(permission) && (!selected || selected.cdExecuting)
+ );
+ }
+
+ showDropDownActions() {
+ this.updateDropDownActions();
+ return this.dropDownActions.length > 1;
+ }
+
+ useClickAction(action: CdTableAction) {
+ /**
+ * In order to show tooltips for deactivated menu items, the class
+ * 'pointer-events: auto;' has been added to the .scss file which also
+ * re-activates the click-event.
+ * To prevent calling the click-event on deactivated elements we also have
+ * to check here if it's disabled.
+ */
+ return !this.disableSelectionAction(action) && action.click && action.click();
+ }
+
+ useDisableDesc(action: CdTableAction) {
+ return action.disableDesc && action.disableDesc();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html
new file mode 100644
index 00000000..2e2dda4e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html
@@ -0,0 +1,12 @@
+<cd-table #table
+ [data]="tableData"
+ [columns]="columns"
+ columnMode="flex"
+ [toolHeader]="false"
+ [autoReload]="autoReload"
+ [customCss]="customCss"
+ [autoSave]="false"
+ [header]="false"
+ [footer]="false"
+ [limit]="0">
+</cd-table>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.scss
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.scss
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts
new file mode 100644
index 00000000..0ae953c3
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts
@@ -0,0 +1,317 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ComponentsModule } from '../../components/components.module';
+import { CellTemplate } from '../../enum/cell-template.enum';
+import { CdTableColumn } from '../../models/cd-table-column';
+import { CdDatePipe } from '../../pipes/cd-date.pipe';
+import { PipesModule } from '../../pipes/pipes.module';
+import { TableComponent } from '../table/table.component';
+import { TableKeyValueComponent } from './table-key-value.component';
+
+describe('TableKeyValueComponent', () => {
+ let component: TableKeyValueComponent;
+ let fixture: ComponentFixture<TableKeyValueComponent>;
+
+ configureTestBed({
+ declarations: [TableComponent, TableKeyValueComponent],
+ imports: [FormsModule, NgxDatatableModule, ComponentsModule, PipesModule, RouterTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TableKeyValueComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ fixture.detectChanges();
+ expect(component).toBeTruthy();
+ });
+
+ it('should make key value object pairs out of arrays with length two', () => {
+ component.data = [['someKey', 0], ['arrayKey', [1, 2, 3]], [3, 'something']];
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: 'arrayKey', value: '1, 2, 3' },
+ { key: 'someKey', value: 0 },
+ { key: 3, value: 'something' }
+ ]);
+ });
+
+ it('should not show data supposed to be have hidden by key', () => {
+ component.data = [['a', 1], ['b', 2]];
+ component.hideKeys = ['a'];
+ component.ngOnInit();
+ expect(component.tableData).toEqual([{ key: 'b', value: 2 }]);
+ });
+
+ it('should remove items with objects as values', () => {
+ component.data = [[3, 'something'], ['will be removed', { a: 3, b: 4, c: 5 }]];
+ component.ngOnInit();
+ expect(component.tableData).toEqual([{ key: 3, value: 'something' }]);
+ });
+
+ it('makes key value object pairs out of an object', () => {
+ component.data = { 3: 'something', someKey: 0 };
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: '3', value: 'something' },
+ { key: 'someKey', value: 0 }
+ ]);
+ });
+
+ it('does nothing if data does not need to be converted', () => {
+ component.data = [{ key: 3, value: 'something' }, { key: 'someKey', value: 0 }];
+ component.ngOnInit();
+ expect(component.tableData).toEqual(component.data);
+ });
+
+ it('throws errors if data cannot be converted', () => {
+ component.data = 38;
+ expect(() => component.ngOnInit()).toThrowError('Wrong data format');
+ component.data = [['someKey', 0, 3]];
+ expect(() => component.ngOnInit()).toThrowError(
+ 'Array contains too many elements (3). Needs to be of type [string, any][]'
+ );
+ });
+
+ it('tests makePairs()', () => {
+ const makePairs = (data) => component['makePairs'](data);
+ expect(makePairs([['dash', 'board']])).toEqual([{ key: 'dash', value: 'board' }]);
+ const pair = [{ key: 'dash', value: 'board' }, { key: 'ceph', value: 'mimic' }];
+ const pairInverse = [{ key: 'ceph', value: 'mimic' }, { key: 'dash', value: 'board' }];
+ expect(makePairs(pair)).toEqual(pairInverse);
+ expect(makePairs({ dash: 'board' })).toEqual([{ key: 'dash', value: 'board' }]);
+ expect(makePairs({ dash: 'board', ceph: 'mimic' })).toEqual(pairInverse);
+ });
+
+ it('tests makePairsFromArray()', () => {
+ const makePairsFromArray = (data) => component['makePairsFromArray'](data);
+ expect(makePairsFromArray([['dash', 'board']])).toEqual([{ key: 'dash', value: 'board' }]);
+ const pair = [{ key: 'dash', value: 'board' }, { key: 'ceph', value: 'mimic' }];
+ expect(makePairsFromArray(pair)).toEqual(pair);
+ });
+
+ it('tests makePairsFromObject()', () => {
+ const makePairsFromObject = (data) => component['makePairsFromObject'](data);
+ expect(makePairsFromObject({ dash: 'board' })).toEqual([{ key: 'dash', value: 'board' }]);
+ expect(makePairsFromObject({ dash: 'board', ceph: 'mimic' })).toEqual([
+ { key: 'dash', value: 'board' },
+ { key: 'ceph', value: 'mimic' }
+ ]);
+ });
+
+ describe('tests convertValue()', () => {
+ const convertValue = (data) => component['convertValue'](data);
+ const expectConvertValue = (value, expectation) =>
+ expect(convertValue(value)).toBe(expectation);
+
+ it('should not convert strings', () => {
+ expectConvertValue('something', 'something');
+ });
+
+ it('should not convert integers', () => {
+ expectConvertValue(29, 29);
+ });
+
+ it('should convert arrays with any type to strings', () => {
+ expectConvertValue([1, 2, 3], '1, 2, 3');
+ expectConvertValue([{ sth: 'something' }], '{"sth":"something"}');
+ expectConvertValue([1, 'two', { 3: 'three' }], '1, two, {"3":"three"}');
+ });
+
+ it('should only convert objects if renderObjects is set to true', () => {
+ expect(convertValue({ sth: 'something' })).toBe(null);
+ component.renderObjects = true;
+ expect(convertValue({ sth: 'something' })).toEqual({ sth: 'something' });
+ });
+ });
+
+ describe('automatically pipe UTC dates through cdDate', () => {
+ let datePipe: CdDatePipe;
+
+ beforeEach(() => {
+ datePipe = TestBed.get(CdDatePipe);
+ spyOn(datePipe, 'transform').and.callThrough();
+ });
+
+ const expectTimeConversion = (date: string) => {
+ component.data = { dateKey: date };
+ component.ngOnInit();
+ expect(datePipe.transform).toHaveBeenCalledWith(date);
+ expect(component.tableData[0].key).not.toBe(date);
+ };
+
+ it('converts some date', () => {
+ expectTimeConversion('2019-04-15 12:26:52.305285');
+ });
+
+ it('converts UTC date', () => {
+ expectTimeConversion('2019-04-16T12:35:46.646300974Z');
+ });
+ });
+
+ describe('render objects', () => {
+ beforeEach(() => {
+ component.data = {
+ options: {
+ numberKey: 38,
+ stringKey: 'somethingElse',
+ objectKey: {
+ sub1: 12,
+ sub2: 34,
+ sub3: 56
+ }
+ },
+ otherOptions: {
+ sub1: {
+ x: 42
+ },
+ sub2: {
+ y: 555
+ }
+ },
+ additionalKeyContainingObject: { type: 'none' },
+ keyWithEmptyObject: {}
+ };
+ component.renderObjects = true;
+ });
+
+ it('with parent key', () => {
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: 'additionalKeyContainingObject type', value: 'none' },
+ { key: 'keyWithEmptyObject', value: '' },
+ { key: 'options numberKey', value: 38 },
+ { key: 'options objectKey sub1', value: 12 },
+ { key: 'options objectKey sub2', value: 34 },
+ { key: 'options objectKey sub3', value: 56 },
+ { key: 'options stringKey', value: 'somethingElse' },
+ { key: 'otherOptions sub1 x', value: 42 },
+ { key: 'otherOptions sub2 y', value: 555 }
+ ]);
+ });
+
+ it('without parent key', () => {
+ component.appendParentKey = false;
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: 'keyWithEmptyObject', value: '' },
+ { key: 'numberKey', value: 38 },
+ { key: 'stringKey', value: 'somethingElse' },
+ { key: 'sub1', value: 12 },
+ { key: 'sub2', value: 34 },
+ { key: 'sub3', value: 56 },
+ { key: 'type', value: 'none' },
+ { key: 'x', value: 42 },
+ { key: 'y', value: 555 }
+ ]);
+ });
+ });
+
+ describe('subscribe fetchData', () => {
+ it('should not subscribe fetchData of table', () => {
+ component.ngOnInit();
+ expect(component.table.fetchData.observers.length).toBe(0);
+ });
+
+ it('should call fetchData', () => {
+ let called = false;
+ component.fetchData.subscribe(() => {
+ called = true;
+ });
+ component.ngOnInit();
+ expect(component.table.fetchData.observers.length).toBe(1);
+ component.table.fetchData.emit();
+ expect(called).toBeTruthy();
+ });
+ });
+
+ describe('hide empty items', () => {
+ beforeEach(() => {
+ component.data = {
+ booleanFalse: false,
+ booleanTrue: true,
+ string: '',
+ array: [],
+ object: {},
+ emptyObject: {
+ string: '',
+ array: [],
+ object: {}
+ },
+ someNumber: 0,
+ someDifferentNumber: 1,
+ someArray: [0, 1],
+ someString: '0',
+ someObject: {
+ empty: {},
+ something: 0.1
+ }
+ };
+ component.renderObjects = true;
+ });
+
+ it('should show all items as default', () => {
+ expect(component.hideEmpty).toBe(false);
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: 'array', value: '' },
+ { key: 'booleanFalse', value: false },
+ { key: 'booleanTrue', value: true },
+ { key: 'emptyObject array', value: '' },
+ { key: 'emptyObject object', value: '' },
+ { key: 'emptyObject string', value: '' },
+ { key: 'object', value: '' },
+ { key: 'someArray', value: '0, 1' },
+ { key: 'someDifferentNumber', value: 1 },
+ { key: 'someNumber', value: 0 },
+ { key: 'someObject empty', value: '' },
+ { key: 'someObject something', value: 0.1 },
+ { key: 'someString', value: '0' },
+ { key: 'string', value: '' }
+ ]);
+ });
+
+ it('should hide all empty items', () => {
+ component.hideEmpty = true;
+ component.ngOnInit();
+ expect(component.tableData).toEqual([
+ { key: 'booleanFalse', value: false },
+ { key: 'booleanTrue', value: true },
+ { key: 'someArray', value: '0, 1' },
+ { key: 'someDifferentNumber', value: 1 },
+ { key: 'someNumber', value: 0 },
+ { key: 'someObject something', value: 0.1 },
+ { key: 'someString', value: '0' }
+ ]);
+ });
+ });
+
+ describe('columns set up', () => {
+ let columns: CdTableColumn[];
+
+ beforeEach(() => {
+ columns = [
+ { prop: 'key', flexGrow: 1, cellTransformation: CellTemplate.bold },
+ { prop: 'value', flexGrow: 3 }
+ ];
+ });
+
+ it('should have the following default column set up', () => {
+ component.ngOnInit();
+ expect(component.columns).toEqual(columns);
+ });
+
+ it('should have the following column set up if customCss is defined', () => {
+ component.customCss = { 'class-name': 42 };
+ component.ngOnInit();
+ columns[1].cellTransformation = CellTemplate.classAdding;
+ expect(component.columns).toEqual(columns);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts
new file mode 100644
index 00000000..fb762d6d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts
@@ -0,0 +1,224 @@
+import {
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnInit,
+ Output,
+ ViewChild
+} from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { CellTemplate } from '../../enum/cell-template.enum';
+import { CdTableColumn } from '../../models/cd-table-column';
+import { CdDatePipe } from '../../pipes/cd-date.pipe';
+import { TableComponent } from '../table/table.component';
+
+interface KeyValueItem {
+ key: string;
+ value: any;
+}
+
+/**
+ * Display the given data in a 2 column data table. The left column
+ * shows the 'key' attribute, the right column the 'value' attribute.
+ * The data table has the following characteristics:
+ * - No header and footer is displayed
+ * - The relation of the width for the columns 'key' and 'value' is 1:3
+ * - The 'key' column is displayed in bold text
+ */
+@Component({
+ selector: 'cd-table-key-value',
+ templateUrl: './table-key-value.component.html',
+ styleUrls: ['./table-key-value.component.scss']
+})
+export class TableKeyValueComponent implements OnInit, OnChanges {
+ @ViewChild(TableComponent)
+ table: TableComponent;
+
+ @Input()
+ data: any;
+ @Input()
+ autoReload: any = 5000;
+ @Input()
+ renderObjects = false;
+ // Only used if objects are rendered
+ @Input()
+ appendParentKey = true;
+ @Input()
+ hideEmpty = false;
+ @Input()
+ hideKeys = []; // Keys of pairs not to be displayed
+
+ // If set, the classAddingTpl is used to enable different css for different values
+ @Input()
+ customCss?: { [css: string]: number | string | ((any) => boolean) };
+
+ columns: Array<CdTableColumn> = [];
+ tableData: KeyValueItem[];
+
+ /**
+ * The function that will be called to update the input data.
+ */
+ @Output()
+ fetchData = new EventEmitter();
+
+ constructor(private datePipe: CdDatePipe) {}
+
+ ngOnInit() {
+ this.columns = [
+ {
+ prop: 'key',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.bold
+ },
+ {
+ prop: 'value',
+ flexGrow: 3
+ }
+ ];
+ if (this.customCss) {
+ this.columns[1].cellTransformation = CellTemplate.classAdding;
+ }
+ // We need to subscribe the 'fetchData' event here and not in the
+ // HTML template, otherwise the data table will display the loading
+ // indicator infinitely if data is only bound via '[data]="xyz"'.
+ // See for 'loadingIndicator' in 'TableComponent::ngOnInit()'.
+ if (this.fetchData.observers.length > 0) {
+ this.table.fetchData.subscribe(() => {
+ // Forward event triggered by the 'cd-table' data table.
+ this.fetchData.emit();
+ });
+ }
+ this.useData();
+ }
+
+ ngOnChanges() {
+ this.useData();
+ }
+
+ useData() {
+ if (!this.data) {
+ return; // Wait for data
+ }
+ let pairs = this.makePairs(this.data);
+ if (this.hideKeys) {
+ pairs = pairs.filter((pair) => !this.hideKeys.includes(pair.key));
+ }
+ this.tableData = pairs;
+ }
+
+ private makePairs(data: any): KeyValueItem[] {
+ let result: KeyValueItem[] = [];
+ if (!data) {
+ return; // Wait for data
+ } else if (_.isArray(data)) {
+ result = this.makePairsFromArray(data);
+ } else if (_.isObject(data)) {
+ result = this.makePairsFromObject(data);
+ } else {
+ throw new Error('Wrong data format');
+ }
+ result = result
+ .map((item) => {
+ item.value = this.convertValue(item.value);
+ return item;
+ })
+ .filter((i) => i.value !== null);
+ return _.sortBy(this.renderObjects ? this.insertFlattenObjects(result) : result, 'key');
+ }
+
+ private makePairsFromArray(data: any[]): KeyValueItem[] {
+ let temp = [];
+ const first = data[0];
+ if (_.isArray(first)) {
+ if (first.length === 2) {
+ temp = data.map((a) => ({
+ key: a[0],
+ value: a[1]
+ }));
+ } else {
+ throw new Error(
+ `Array contains too many elements (${first.length}). ` +
+ `Needs to be of type [string, any][]`
+ );
+ }
+ } else if (_.isObject(first)) {
+ if (_.has(first, 'key') && _.has(first, 'value')) {
+ temp = [...data];
+ } else {
+ temp = data.reduce(
+ (previous: any[], item) => previous.concat(this.makePairsFromObject(item)),
+ temp
+ );
+ }
+ }
+ return temp;
+ }
+
+ private makePairsFromObject(data: object): KeyValueItem[] {
+ return Object.keys(data).map((k) => ({
+ key: k,
+ value: data[k]
+ }));
+ }
+
+ private insertFlattenObjects(data: KeyValueItem[]): any[] {
+ return _.flattenDeep(
+ data.map((item) => {
+ const value = item.value;
+ const isObject = _.isObject(value);
+ if (!isObject || _.isEmpty(value)) {
+ if (isObject) {
+ item.value = '';
+ }
+ return item;
+ }
+ return this.splitItemIntoItems(item);
+ })
+ );
+ }
+
+ /**
+ * Split item into items will call _makePairs inside _makePairs (recursion), in oder to split
+ * the object item up into items as planned.
+ */
+ private splitItemIntoItems(data: { key: string; value: object }): KeyValueItem[] {
+ return this.makePairs(data.value).map((item) => {
+ if (this.appendParentKey) {
+ item.key = data.key + ' ' + item.key;
+ }
+ return item;
+ });
+ }
+
+ private convertValue(value: any): KeyValueItem {
+ if (_.isArray(value)) {
+ if (_.isEmpty(value) && this.hideEmpty) {
+ return null;
+ }
+ value = value.map((item) => (_.isObject(item) ? JSON.stringify(item) : item)).join(', ');
+ } else if (_.isObject(value)) {
+ if ((this.hideEmpty && _.isEmpty(value)) || !this.renderObjects) {
+ return null;
+ }
+ } else if (_.isString(value)) {
+ if (value === '' && this.hideEmpty) {
+ return null;
+ }
+ if (this.isDate(value)) {
+ value = this.datePipe.transform(value) || value;
+ }
+ }
+
+ return value;
+ }
+
+ private isDate(s) {
+ const sep = '[ -:.TZ]';
+ const n = '\\d{2}' + sep;
+ // year - m - d - h : m : s . someRest Z (if UTC)
+ return s.match(new RegExp('^\\d{4}' + sep + n + n + n + n + n + '\\d*' + 'Z?$'));
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html
new file mode 100644
index 00000000..616ba250
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html
@@ -0,0 +1,191 @@
+<cd-error-panel *ngIf="loadingError"
+ i18n>Failed to load data.</cd-error-panel>
+
+<div class="dataTables_wrapper">
+ <div class="dataTables_header clearfix form-inline"
+ *ngIf="toolHeader">
+ <!-- actions -->
+ <div class="oadatatableactions">
+ <ng-content select=".table-actions"></ng-content>
+ </div>
+ <!-- end actions -->
+
+ <!-- filters -->
+ <ng-content select=".table-filters"></ng-content>
+ <!-- end filters -->
+
+ <!-- search -->
+ <div class="input-group">
+ <span class="input-group-addon">
+ <i class="glyphicon glyphicon-search"></i>
+ </span>
+ <input class="form-control"
+ type="text"
+ [(ngModel)]="search"
+ (keyup)="updateFilter()">
+ <span class="input-group-btn">
+ <button type="button"
+ class="btn btn-default clear-input tc_clearInputBtn"
+ (click)="updateFilter(true)">
+ <i class="icon-prepend fa fa-remove"></i>
+ </button>
+ </span>
+ </div>
+ <!-- end search -->
+
+ <!-- pagination limit -->
+ <div class="input-group dataTables_paginate"
+ *ngIf="limit">
+ <input class="form-control"
+ type="number"
+ min="1"
+ max="9999"
+ [value]="userConfig.limit"
+ (click)="setLimit($event)"
+ (keyup)="setLimit($event)"
+ (blur)="setLimit($event)">
+ </div>
+ <!-- end pagination limit-->
+
+ <!-- show hide columns -->
+ <div class="widget-toolbar">
+ <div dropdown
+ class="dropdown tc_menuitem tc_menuitem_cluster">
+ <a dropdownToggle
+ class="btn btn-sm btn-default dropdown-toggle tc_columnBtn"
+ data-toggle="dropdown">
+ <i class="fa fa-lg fa-table"></i>
+ </a>
+ <ul *dropdownMenu
+ class="dropdown-menu">
+ <li *ngFor="let column of columns">
+ <label>
+ <input type="checkbox"
+ (change)="toggleColumn($event)"
+ [name]="column.prop"
+ [checked]="!column.isHidden">
+ <span>{{ column.name }}</span>
+ </label>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <!-- end show hide columns -->
+
+ <!-- refresh button -->
+ <div class="widget-toolbar tc_refreshBtn"
+ *ngIf="fetchData.observers.length > 0">
+ <a (click)="refreshBtn()">
+ <i class="fa fa-lg fa-refresh"
+ [class.fa-spin]="updating || loadingIndicator"></i>
+ </a>
+ </div>
+ <!-- end refresh button -->
+ </div>
+ <ngx-datatable #table
+ class="bootstrap oadatatable"
+ [cssClasses]="paginationClasses"
+ [selectionType]="selectionType"
+ [selected]="selection.selected"
+ (select)="onSelect($event)"
+ [sorts]="userConfig.sorts"
+ (sort)="changeSorting($event)"
+ [columns]="tableColumns"
+ [columnMode]="columnMode"
+ [rows]="rows"
+ [rowClass]="getRowClass()"
+ [headerHeight]="header ? 'auto' : 0"
+ [footerHeight]="footer ? 'auto' : 0"
+ [limit]="userConfig.limit > 0 ? userConfig.limit : undefined"
+ [loadingIndicator]="loadingIndicator"
+ [rowIdentity]="rowIdentity()"
+ [rowHeight]="'auto'">
+ <ngx-datatable-footer>
+ <ng-template ngx-datatable-footer-template
+ let-rowCount="rowCount"
+ let-pageSize="pageSize"
+ let-selectedCount="selectedCount"
+ let-curPage="curPage"
+ let-offset="offset"
+ let-isVisible="isVisible">
+ <div class="page-count">
+ <span *ngIf="selectionType">
+ {{ selectedCount }} <ng-container i18n="X selected">selected</ng-container> /
+ </span>
+ <span *ngIf="rowCount != data?.length">
+ {{ rowCount }} <ng-container i18n="X found">found</ng-container> /
+ </span>
+ <span>
+ {{ data?.length || 0 }} <ng-container i18n="X total">total</ng-container>
+ </span>
+ </div>
+ <datatable-pager [pagerLeftArrowIcon]="paginationClasses.pagerLeftArrow"
+ [pagerRightArrowIcon]="paginationClasses.pagerRightArrow"
+ [pagerPreviousIcon]="paginationClasses.pagerPrevious"
+ [pagerNextIcon]="paginationClasses.pagerNext"
+ [page]="curPage"
+ [size]="pageSize"
+ [count]="rowCount"
+ [hidden]="!((rowCount / pageSize) > 1)"
+ (change)="table.onFooterPage($event)">
+ </datatable-pager>
+ </ng-template>
+ </ngx-datatable-footer>
+ </ngx-datatable>
+</div>
+
+<!-- Table Details -->
+<ng-content select="[cdTableDetail]"></ng-content>
+
+<!-- cell templates that can be accessed from outside -->
+<ng-template #tableCellBoldTpl
+ let-value="value">
+ <strong>{{ value }}</strong>
+</ng-template>
+
+<ng-template #sparklineTpl
+ let-row="row"
+ let-value="value">
+ <cd-sparkline [data]="value"
+ [isBinary]="row.cdIsBinary"></cd-sparkline>
+</ng-template>
+
+<ng-template #routerLinkTpl
+ let-row="row"
+ let-value="value">
+ <a [routerLink]="[row.cdLink]"
+ [queryParams]="row.cdParams">{{ value }}</a>
+</ng-template>
+
+<ng-template #checkIconTpl
+ let-value="value">
+ <i class="fa fa-check fa-fw"
+ [hidden]="!value"></i>
+</ng-template>
+
+<ng-template #perSecondTpl
+ let-row="row"
+ let-value="value">
+ {{ value | dimless }} /s
+</ng-template>
+
+<ng-template #executingTpl
+ let-row="row"
+ let-value="value">
+ <i class="fa fa-spinner fa-spin fa-fw"
+ *ngIf="row.cdExecuting"></i>
+ {{ value }}
+ <span *ngIf="row.cdExecuting"
+ class="text-muted italic">({{ row.cdExecuting }})</span>
+</ng-template>
+
+<ng-template #classAddingTpl
+ let-value="value">
+ <span class="{{useCustomClass(value)}}">{{ value }}</span>
+</ng-template>
+
+<ng-template #mapTpl
+ let-column="column"
+ let-value="value">
+ <span>{{ value | map:column?.customTemplateConfig }}</span>
+</ng-template>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.scss
new file mode 100644
index 00000000..a2259c82
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.scss
@@ -0,0 +1,282 @@
+@import '../../../../defaults';
+
+.dataTables_wrapper {
+ margin-bottom: 25px;
+ .separator {
+ height: 30px;
+ border-left: 1px solid $color-table-seperator-border;
+ padding-left: 5px;
+ margin-left: 5px;
+ display: inline-block;
+ vertical-align: middle;
+ }
+ .widget-toolbar {
+ display: inline-block;
+ float: right;
+ width: auto;
+ height: 30px;
+ line-height: 28px;
+ position: relative;
+ border-left: 1px solid $color-table-seperator-border;
+ cursor: pointer;
+ padding: 0 8px;
+ text-align: center;
+ }
+ .dropdown-menu {
+ white-space: nowrap;
+ & > li {
+ cursor: pointer;
+ & > label {
+ width: 100%;
+ margin-bottom: 0;
+ padding-left: 20px;
+ padding-right: 20px;
+ cursor: pointer;
+ &:hover {
+ background-color: $color-table-dropdown-bg;
+ }
+ & > input {
+ cursor: pointer;
+ }
+ }
+ }
+ }
+ th.oadatatablecheckbox {
+ width: 16px;
+ }
+ .dataTables_length > input {
+ line-height: 25px;
+ text-align: right;
+ }
+}
+.dataTables_header {
+ background-color: $color-table-header-bg;
+ border: 1px solid $color-table-header-border;
+ border-bottom: none;
+ padding: 5px;
+ position: relative;
+ .oadatatableactions {
+ float: left;
+ }
+ ::ng-deep .table-filters {
+ float: right;
+ border-left: 1px solid $color-table-seperator-border;
+ padding-left: 8px;
+ }
+ ::ng-deep .table-filters label {
+ margin-right: 4px;
+ }
+ .form-group {
+ padding-left: 8px;
+ }
+ .input-group {
+ float: right;
+ border-left: 1px solid $color-table-input-border;
+ padding-left: 8px;
+ padding-right: 8px;
+ width: 40%;
+ max-width: 250px;
+ .form-control {
+ height: 30px;
+ }
+ .clear-input {
+ height: 30px;
+ i {
+ vertical-align: text-top;
+ }
+ }
+ }
+ .input-group.dataTables_paginate {
+ width: 8%;
+ min-width: 85px;
+ padding-right: 8px;
+ }
+}
+
+::ng-deep .oadatatable {
+ border: 1px solid $color-table-header-border;
+ margin-bottom: 0;
+ max-width: none !important;
+ .progress-linear {
+ display: block;
+ position: relative;
+ width: 100%;
+ height: 5px;
+ padding: 0;
+ margin: 0;
+ .container {
+ background-color: $color-table-active-row;
+ .bar {
+ left: 0;
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ overflow: hidden;
+ background-color: $color-table-active-row;
+ }
+ .bar:before {
+ display: block;
+ position: absolute;
+ content: '';
+ left: -200px;
+ width: 200px;
+ height: 100%;
+ background-color: $color-table-progress-bar-active;
+ animation: progress-loading 3s linear infinite;
+ }
+ }
+ }
+ .datatable-header {
+ background-clip: padding-box;
+ background-color: $color-table-datatable-header;
+ background-image: -webkit-linear-gradient(
+ top,
+ $color-table-gradient-1 0,
+ $color-table-gradient-2 100%
+ );
+ background-image: -o-linear-gradient(
+ top,
+ $color-table-gradient-1 0,
+ $color-table-gradient-2 100%
+ );
+ background-image: linear-gradient(
+ to bottom,
+ $color-table-gradient-1 0,
+ $color-table-gradient-2 100%
+ );
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);
+ .sort-asc,
+ .sort-desc {
+ color: $color-table-sort;
+ }
+ .datatable-header-cell {
+ @include table-cell;
+ text-align: left;
+ font-weight: bold;
+ .datatable-header-cell-label {
+ &:after {
+ font-family: ForkAwesome;
+ font-weight: 400;
+ height: 9px;
+ left: 10px;
+ line-height: 12px;
+ position: relative;
+ vertical-align: baseline;
+ width: 12px;
+ }
+ }
+ &.sortable {
+ .datatable-header-cell-label:after {
+ content: ' \f0dc';
+ }
+ &.sort-active {
+ &.sort-asc .datatable-header-cell-label:after {
+ content: ' \f160';
+ }
+ &.sort-desc .datatable-header-cell-label:after {
+ content: ' \f161';
+ }
+ }
+ }
+ &:first-child {
+ border-left: none;
+ }
+ }
+ }
+ .datatable-body {
+ .empty-row {
+ background-color: $color-table-empty-row;
+ text-align: center;
+ font-weight: bold;
+ font-style: italic;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ }
+ .datatable-body-row {
+ .label {
+ font-size: 0.9em;
+ }
+ &.clickable:hover .datatable-row-group {
+ background-color: $color-table-hover-row;
+ transition-property: background;
+ transition-duration: 0.3s;
+ transition-timing-function: linear;
+ }
+ &.datatable-row-even {
+ background-color: $color-table-even-row-bg;
+ }
+ &.datatable-row-odd {
+ background-color: $color-table-odd-row-bg;
+ }
+ &.active,
+ &.active:hover {
+ background-color: $color-table-active-row-hover;
+ }
+ .datatable-body-cell {
+ @include table-cell;
+ &:first-child {
+ border-left: none;
+ }
+ .datatable-body-cell-label {
+ display: block;
+ }
+ }
+ }
+ }
+ .datatable-footer {
+ .selected-count,
+ .page-count {
+ font-style: italic;
+ padding-left: 5px;
+ }
+ .datatable-pager .pager {
+ margin-right: 5px !important;
+ & li:not(:first-child) {
+ /** Add space between buttons */
+ margin-left: 3px;
+ }
+ & li > a,
+ & li > span {
+ border-radius: 3px;
+ }
+ .pages {
+ & > a,
+ & > span {
+ display: inline-block;
+ padding: 5px 10px;
+ margin-bottom: 5px;
+ border: none;
+ }
+ a:hover {
+ background-color: $color-table-active-row;
+ }
+ &.active > a {
+ background-color: $color-table-active-row-hover;
+ }
+ }
+ }
+ }
+}
+
+@keyframes progress-loading {
+ from {
+ left: -200px;
+ width: 15%;
+ }
+ 50% {
+ width: 30%;
+ }
+ 70% {
+ width: 70%;
+ }
+ 80% {
+ left: 50%;
+ }
+ 95% {
+ left: 120%;
+ }
+ to {
+ left: 100%;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts
new file mode 100644
index 00000000..682a9386
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts
@@ -0,0 +1,431 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import * as _ from 'lodash';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { ComponentsModule } from '../../components/components.module';
+import { CdTableFetchDataContext } from '../../models/cd-table-fetch-data-context';
+import { PipesModule } from '../../pipes/pipes.module';
+import { TableComponent } from './table.component';
+
+describe('TableComponent', () => {
+ let component: TableComponent;
+ let fixture: ComponentFixture<TableComponent>;
+
+ const createFakeData = (n) => {
+ const data = [];
+ for (let i = 0; i < n; i++) {
+ data.push({
+ a: i,
+ b: i * i,
+ c: [-(i % 10), 'score' + ((i % 16) + 6)],
+ d: !(i % 2)
+ });
+ }
+ return data;
+ };
+
+ const clearLocalStorage = () => {
+ component.localStorage.clear();
+ };
+
+ configureTestBed({
+ declarations: [TableComponent],
+ imports: [NgxDatatableModule, FormsModule, ComponentsModule, PipesModule, RouterTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TableComponent);
+ component = fixture.componentInstance;
+ });
+
+ beforeEach(() => {
+ component.data = createFakeData(100);
+ component.columns = [
+ { prop: 'a', name: 'Index' },
+ { prop: 'b', name: 'Power ofA' },
+ { prop: 'c', name: 'Poker array' },
+ { prop: 'd', name: 'Boolean value' }
+ ];
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('after useData', () => {
+ beforeEach(() => {
+ component.useData();
+ });
+
+ it('should force an identifier', () => {
+ component.identifier = 'x';
+ component.forceIdentifier = true;
+ component.ngOnInit();
+ expect(component.identifier).toBe('x');
+ expect(component.sorts[0].prop).toBe('a');
+ expect(component.sorts).toEqual(component.createSortingDefinition('a'));
+ });
+
+ it('should have rows', () => {
+ expect(component.data.length).toBe(100);
+ expect(component.rows.length).toBe(component.data.length);
+ });
+
+ it('should have an int in setLimit parsing a string', () => {
+ expect(component.limit).toBe(10);
+ expect(component.limit).toEqual(jasmine.any(Number));
+ });
+
+ it('should prevent propagation of mouseenter event', (done) => {
+ let wasCalled = false;
+ const mouseEvent = new MouseEvent('mouseenter');
+ mouseEvent.stopPropagation = () => {
+ wasCalled = true;
+ };
+ spyOn(window, 'addEventListener').and.callFake((eventName, fn) => {
+ fn(mouseEvent);
+ expect(eventName).toBe('mouseenter');
+ expect(wasCalled).toBe(true);
+ done();
+ });
+ component.ngOnInit();
+ });
+
+ it('should force an identifier', () => {
+ clearLocalStorage();
+ component.identifier = 'x';
+ component.forceIdentifier = true;
+ component.ngOnInit();
+ expect(component.identifier).toBe('x');
+ expect(component.sorts[0].prop).toBe('a');
+ expect(component.sorts).toEqual(component.createSortingDefinition('a'));
+ });
+ });
+
+ describe('test search', () => {
+ const doSearch = (search: string, expectedLength: number, firstObject?: object) => {
+ component.search = search;
+ component.updateFilter();
+ expect(component.rows.length).toBe(expectedLength);
+ if (firstObject) {
+ expect(component.rows[0]).toEqual(firstObject);
+ }
+ };
+
+ describe('searchableObjects', () => {
+ const testObject = {
+ obj: {
+ min: 8,
+ max: 123
+ }
+ };
+
+ beforeEach(() => {
+ component.data = [testObject];
+ component.columns = [{ prop: 'obj', name: 'Object' }];
+ });
+
+ it('should not search through objects as default case', () => {
+ expect(component.searchableObjects).toBe(false);
+ doSearch('8', 0);
+ });
+
+ it('should search through objects if searchableObjects is set to true', () => {
+ component.searchableObjects = true;
+ doSearch('28', 0);
+ doSearch('8', 1, testObject);
+ doSearch('123', 1, testObject);
+ doSearch('max', 1, testObject);
+ });
+ });
+
+ it('should find a particular number', () => {
+ doSearch('5', 37, { a: 5, b: 25, c: [-5, 'score11'], d: false });
+ // { a: 3, b: 9, c: [ -3, 'score9' ], d: false },
+ // { a: 7, b: 49, c: [ -7, 'score13' ], d: false },
+ // { a: 9, b: 81, c: [ -9, 'score15' ], d: false },
+
+ doSearch('9', 50, { a: 3, b: 9, c: [-3, 'score9'], d: false });
+ });
+
+ it('should search for 13', () => {
+ doSearch('13', 9, { a: 7, b: 49, c: [-7, 'score13'], d: false });
+ expect(component.rows[1].a).toBe(13);
+ expect(component.rows[8].a).toBe(87);
+ });
+
+ it('should search for true', () => {
+ doSearch('true', 50, { a: 0, b: 0, c: [-0, 'score6'], d: true });
+ expect(component.rows[0].d).toBe(true);
+ expect(component.rows[1].d).toBe(true);
+ });
+
+ it('should search for false', () => {
+ doSearch('false', 50, { a: 1, b: 1, c: [-1, 'score7'], d: false });
+ expect(component.rows[0].d).toBe(false);
+ expect(component.rows[1].d).toBe(false);
+ });
+
+ it('should test search manipulation', () => {
+ let searchTerms = [];
+ spyOn(component, 'subSearch').and.callFake((_d, search) => {
+ expect(search).toEqual(searchTerms);
+ });
+ const searchTest = (s: string, st: string[]) => {
+ component.search = s;
+ searchTerms = st;
+ component.updateFilter();
+ };
+ searchTest('a b c', ['a', 'b', 'c']);
+ searchTest('a+b c', ['a+b', 'c']);
+ searchTest('a,,,, b,,, c', ['a', 'b', 'c']);
+ searchTest('a,,,+++b,,, c', ['a+++b', 'c']);
+ searchTest('"a b c" "d e f", "g, h i"', ['a+b+c', 'd+e++f', 'g+h+i']);
+ });
+
+ it('should search for multiple values', () => {
+ doSearch('7 5 3', 5, { a: 57, b: 3249, c: [-7, 'score15'], d: false });
+ });
+
+ it('should search with column filter', () => {
+ doSearch('power:1369', 1, { a: 37, b: 1369, c: [-7, 'score11'], d: false });
+ doSearch('ndex:7 ofa:5 poker:3', 3, { a: 71, b: 5041, c: [-1, 'score13'], d: false });
+ });
+
+ it('should search with through array', () => {
+ doSearch('array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+ });
+
+ it('should search with spaces', () => {
+ doSearch(`'poker array':score21`, 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+ doSearch('"poker array":score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+ doSearch('poker+array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+ });
+
+ it('should search if column name is incomplete', () => {
+ doSearch(`'poker array'`, 0);
+ doSearch('pok', 0);
+ doSearch('pok:', 100);
+ });
+
+ it('should restore full table after search', () => {
+ component.updateFilter();
+ expect(component.rows.length).toBe(100);
+ component.search = '13';
+ component.updateFilter();
+ expect(component.rows.length).toBe(9);
+ component.updateFilter(true);
+ expect(component.rows.length).toBe(100);
+ });
+ });
+
+ describe('after ngInit', () => {
+ const toggleColumn = (prop, checked) => {
+ component.toggleColumn({
+ target: {
+ name: prop,
+ checked: checked
+ }
+ });
+ };
+
+ const equalStorageConfig = () => {
+ expect(JSON.stringify(component.userConfig)).toBe(
+ component.localStorage.getItem(component.tableName)
+ );
+ };
+
+ beforeEach(() => {
+ component.ngOnInit();
+ });
+
+ it('should have updated the column definitions', () => {
+ expect(component.columns[0].flexGrow).toBe(1);
+ expect(component.columns[1].flexGrow).toBe(2);
+ expect(component.columns[2].flexGrow).toBe(2);
+ expect(component.columns[2].resizeable).toBe(false);
+ });
+
+ it('should have table columns', () => {
+ expect(component.tableColumns.length).toBe(4);
+ expect(component.tableColumns).toEqual(component.columns);
+ });
+
+ it('should have a unique identifier which it searches for', () => {
+ expect(component.identifier).toBe('a');
+ expect(component.userConfig.sorts[0].prop).toBe('a');
+ expect(component.userConfig.sorts).toEqual(component.createSortingDefinition('a'));
+ equalStorageConfig();
+ });
+
+ it('should remove column "a"', () => {
+ expect(component.userConfig.sorts[0].prop).toBe('a');
+ toggleColumn('a', false);
+ expect(component.userConfig.sorts[0].prop).toBe('b');
+ expect(component.tableColumns.length).toBe(3);
+ equalStorageConfig();
+ });
+
+ it('should not be able to remove all columns', () => {
+ expect(component.userConfig.sorts[0].prop).toBe('a');
+ toggleColumn('a', false);
+ toggleColumn('b', false);
+ toggleColumn('c', false);
+ toggleColumn('d', false);
+ expect(component.userConfig.sorts[0].prop).toBe('d');
+ expect(component.tableColumns.length).toBe(1);
+ equalStorageConfig();
+ });
+
+ it('should enable column "a" again', () => {
+ expect(component.userConfig.sorts[0].prop).toBe('a');
+ toggleColumn('a', false);
+ toggleColumn('a', true);
+ expect(component.userConfig.sorts[0].prop).toBe('b');
+ expect(component.tableColumns.length).toBe(4);
+ equalStorageConfig();
+ });
+
+ afterEach(() => {
+ clearLocalStorage();
+ });
+ });
+
+ describe('select row', () => {
+ beforeEach(() => {
+ component.ngOnInit();
+ component.data = [];
+ });
+
+ it('should select the row item', () => {
+ spyOn(component, 'onSelect').and.callThrough();
+ component.data = createFakeData(3);
+ component.selection.selected = [_.clone(component.data[1])];
+ component.onSelect(new Event('click'));
+ expect(component.selection.hasSelection).toBeTruthy();
+ });
+ });
+
+ describe('reload data', () => {
+ beforeEach(() => {
+ component.ngOnInit();
+ component.data = [];
+ component['updating'] = false;
+ });
+
+ it('should call fetchData callback function', () => {
+ component.fetchData.subscribe((context) => {
+ expect(context instanceof CdTableFetchDataContext).toBeTruthy();
+ });
+ component.reloadData();
+ });
+
+ it('should call error function', () => {
+ component.data = createFakeData(5);
+ component.fetchData.subscribe((context) => {
+ context.error();
+ expect(component.loadingError).toBeTruthy();
+ expect(component.data.length).toBe(0);
+ expect(component.loadingIndicator).toBeFalsy();
+ expect(component['updating']).toBeFalsy();
+ });
+ component.reloadData();
+ });
+
+ it('should call error function with custom config', () => {
+ component.data = createFakeData(10);
+ component.fetchData.subscribe((context) => {
+ context.errorConfig.resetData = false;
+ context.errorConfig.displayError = false;
+ context.error();
+ expect(component.loadingError).toBeFalsy();
+ expect(component.data.length).toBe(10);
+ expect(component.loadingIndicator).toBeFalsy();
+ expect(component['updating']).toBeFalsy();
+ });
+ component.reloadData();
+ });
+
+ it('should update selection on refresh - "onChange"', () => {
+ spyOn(component, 'onSelect').and.callThrough();
+ component.data = createFakeData(10);
+ component.selection.selected = [_.clone(component.data[1])];
+ component.updateSelectionOnRefresh = 'onChange';
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalledTimes(0);
+ component.data[1].d = !component.data[1].d;
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalled();
+ });
+
+ it('should update selection on refresh - "always"', () => {
+ spyOn(component, 'onSelect').and.callThrough();
+ component.data = createFakeData(10);
+ component.selection.selected = [_.clone(component.data[1])];
+ component.updateSelectionOnRefresh = 'always';
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalled();
+ component.data[1].d = !component.data[1].d;
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalled();
+ });
+
+ it('should update selection on refresh - "never"', () => {
+ spyOn(component, 'onSelect').and.callThrough();
+ component.data = createFakeData(10);
+ component.selection.selected = [_.clone(component.data[1])];
+ component.updateSelectionOnRefresh = 'never';
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalledTimes(0);
+ component.data[1].d = !component.data[1].d;
+ component.updateSelected();
+ expect(component.onSelect).toHaveBeenCalledTimes(0);
+ });
+
+ afterEach(() => {
+ clearLocalStorage();
+ });
+ });
+
+ describe('useCustomClass', () => {
+ beforeEach(() => {
+ component.customCss = {
+ 'label label-danger': 'active',
+ 'secret secret-number': 123.456,
+ 'btn btn-sm': (v) => _.isString(v) && v.startsWith('http'),
+ secure: (v) => _.isString(v) && v.startsWith('https')
+ };
+ });
+
+ it('should throw an error if custom classes are not set', () => {
+ component.customCss = undefined;
+ expect(() => component.useCustomClass('active')).toThrowError('Custom classes are not set!');
+ });
+
+ it('should not return any class', () => {
+ ['', 'something', 123, { complex: 1 }, [1, 2, 3]].forEach((value) =>
+ expect(component.useCustomClass(value)).toBe(undefined)
+ );
+ });
+
+ it('should match a string and return the corresponding class', () => {
+ expect(component.useCustomClass('active')).toBe('label label-danger');
+ });
+
+ it('should match a number and return the corresponding class', () => {
+ expect(component.useCustomClass(123.456)).toBe('secret secret-number');
+ });
+
+ it('should match against a function and return the corresponding class', () => {
+ expect(component.useCustomClass('http://no.ssl')).toBe('btn btn-sm');
+ });
+
+ it('should match against multiple functions and return the corresponding classes', () => {
+ expect(component.useCustomClass('https://secure.it')).toBe('btn btn-sm secure');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts
new file mode 100644
index 00000000..b3e5eb41
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts
@@ -0,0 +1,582 @@
+import {
+ AfterContentChecked,
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ EventEmitter,
+ Input,
+ NgZone,
+ OnChanges,
+ OnDestroy,
+ OnInit,
+ Output,
+ TemplateRef,
+ ViewChild
+} from '@angular/core';
+
+import {
+ DatatableComponent,
+ SortDirection,
+ SortPropDir,
+ TableColumnProp
+} from '@swimlane/ngx-datatable';
+import * as _ from 'lodash';
+import { Observable, timer as observableTimer } from 'rxjs';
+
+import { CellTemplate } from '../../enum/cell-template.enum';
+import { CdTableColumn } from '../../models/cd-table-column';
+import { CdTableFetchDataContext } from '../../models/cd-table-fetch-data-context';
+import { CdTableSelection } from '../../models/cd-table-selection';
+import { CdUserConfig } from '../../models/cd-user-config';
+
+@Component({
+ selector: 'cd-table',
+ templateUrl: './table.component.html',
+ styleUrls: ['./table.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class TableComponent implements AfterContentChecked, OnInit, OnChanges, OnDestroy {
+ @ViewChild(DatatableComponent)
+ table: DatatableComponent;
+ @ViewChild('tableCellBoldTpl')
+ tableCellBoldTpl: TemplateRef<any>;
+ @ViewChild('sparklineTpl')
+ sparklineTpl: TemplateRef<any>;
+ @ViewChild('routerLinkTpl')
+ routerLinkTpl: TemplateRef<any>;
+ @ViewChild('checkIconTpl')
+ checkIconTpl: TemplateRef<any>;
+ @ViewChild('perSecondTpl')
+ perSecondTpl: TemplateRef<any>;
+ @ViewChild('executingTpl')
+ executingTpl: TemplateRef<any>;
+ @ViewChild('classAddingTpl')
+ classAddingTpl: TemplateRef<any>;
+ @ViewChild('mapTpl')
+ mapTpl: TemplateRef<any>;
+
+ // This is the array with the items to be shown.
+ @Input()
+ data: any[];
+ // Each item -> { prop: 'attribute name', name: 'display name' }
+ @Input()
+ columns: CdTableColumn[];
+ // Each item -> { prop: 'attribute name', dir: 'asc'||'desc'}
+ @Input()
+ sorts?: SortPropDir[];
+ // Method used for setting column widths.
+ @Input()
+ columnMode? = 'flex';
+ // Display the tool header, including reload button, pagination and search fields?
+ @Input()
+ toolHeader? = true;
+ // Display the table header?
+ @Input()
+ header? = true;
+ // Display the table footer?
+ @Input()
+ footer? = true;
+ // Page size to show. Set to 0 to show unlimited number of rows.
+ @Input()
+ limit? = 10;
+
+ /**
+ * Auto reload time in ms - per default every 5s
+ * You can set it to 0, undefined or false to disable the auto reload feature in order to
+ * trigger 'fetchData' if the reload button is clicked.
+ */
+ @Input()
+ autoReload: any = 5000;
+
+ // Which row property is unique for a row. If the identifier is not specified in any
+ // column, then the property name of the first column is used. Defaults to 'id'.
+ @Input()
+ identifier = 'id';
+ // If 'true', then the specified identifier is used anyway, although it is not specified
+ // in any column. Defaults to 'false'.
+ @Input()
+ forceIdentifier = false;
+ // Allows other components to specify which type of selection they want,
+ // e.g. 'single' or 'multi'.
+ @Input()
+ selectionType: string = undefined;
+ // By default selected item details will be updated on table refresh, if data has changed
+ @Input()
+ updateSelectionOnRefresh: 'always' | 'never' | 'onChange' = 'onChange';
+
+ @Input()
+ autoSave = true;
+
+ // Enable this in order to search through the JSON of any used object.
+ @Input()
+ searchableObjects = false;
+
+ // Only needed to set if the classAddingTpl is used
+ @Input()
+ customCss?: { [css: string]: number | string | ((any) => boolean) };
+
+ /**
+ * Should be a function to update the input data if undefined nothing will be triggered
+ *
+ * Sometimes it's useful to only define fetchData once.
+ * Example:
+ * Usage of multiple tables with data which is updated by the same function
+ * What happens:
+ * The function is triggered through one table and all tables will update
+ */
+ @Output()
+ fetchData = new EventEmitter();
+
+ /**
+ * This should be defined if you need access to the selection object.
+ *
+ * Each time the table selection changes, this will be triggered and
+ * the new selection object will be sent.
+ *
+ * @memberof TableComponent
+ */
+ @Output()
+ updateSelection = new EventEmitter();
+
+ /**
+ * Use this variable to access the selected row(s).
+ */
+ selection = new CdTableSelection();
+
+ tableColumns: CdTableColumn[];
+ cellTemplates: {
+ [key: string]: TemplateRef<any>;
+ } = {};
+ search = '';
+ rows = [];
+ loadingIndicator = true;
+ loadingError = false;
+ paginationClasses = {
+ pagerLeftArrow: 'i fa fa-angle-double-left',
+ pagerRightArrow: 'i fa fa-angle-double-right',
+ pagerPrevious: 'i fa fa-angle-left',
+ pagerNext: 'i fa fa-angle-right'
+ };
+ userConfig: CdUserConfig = {};
+ tableName: string;
+ localStorage = window.localStorage;
+ private saveSubscriber;
+ private reloadSubscriber;
+ private updating = false;
+
+ // Internal variable to check if it is necessary to recalculate the
+ // table columns after the browser window has been resized.
+ private currentWidth: number;
+
+ constructor(private ngZone: NgZone, private cdRef: ChangeDetectorRef) {}
+
+ ngOnInit() {
+ // ngx-datatable triggers calculations each time mouse enters a row,
+ // this will prevent that.
+ window.addEventListener(
+ 'mouseenter',
+ function(event) {
+ event.stopPropagation();
+ },
+ true
+ );
+
+ this._addTemplates();
+ if (!this.sorts) {
+ // Check whether the specified identifier exists.
+ const exists = _.findIndex(this.columns, ['prop', this.identifier]) !== -1;
+ // Auto-build the sorting configuration. If the specified identifier doesn't exist,
+ // then use the property of the first column.
+ this.sorts = this.createSortingDefinition(
+ exists ? this.identifier : this.columns[0].prop + ''
+ );
+ // If the specified identifier doesn't exist and it is not forced to use it anyway,
+ // then use the property of the first column.
+ if (!exists && !this.forceIdentifier) {
+ this.identifier = this.columns[0].prop + '';
+ }
+ }
+ this.initUserConfig();
+ this.columns.forEach((c) => {
+ if (c.cellTransformation) {
+ c.cellTemplate = this.cellTemplates[c.cellTransformation];
+ }
+ if (!c.flexGrow) {
+ c.flexGrow = c.prop + '' === this.identifier ? 1 : 2;
+ }
+ if (!c.resizeable) {
+ c.resizeable = false;
+ }
+ });
+ this.filterHiddenColumns();
+ // Load the data table content every N ms or at least once.
+ // Force showing the loading indicator if there are subscribers to the fetchData
+ // event. This is necessary because it has been set to False in useData() when
+ // this method was triggered by ngOnChanges().
+ if (this.fetchData.observers.length > 0) {
+ this.loadingIndicator = true;
+ }
+ if (_.isInteger(this.autoReload) && this.autoReload > 0) {
+ this.ngZone.runOutsideAngular(() => {
+ this.reloadSubscriber = observableTimer(0, this.autoReload).subscribe(() => {
+ this.ngZone.run(() => {
+ return this.reloadData();
+ });
+ });
+ });
+ } else {
+ this.reloadData();
+ }
+ }
+
+ initUserConfig() {
+ if (this.autoSave) {
+ this.tableName = this._calculateUniqueTableName(this.columns);
+ this._loadUserConfig();
+ this._initUserConfigAutoSave();
+ }
+ if (!this.userConfig.limit) {
+ this.userConfig.limit = this.limit;
+ }
+ if (!this.userConfig.sorts) {
+ this.userConfig.sorts = this.sorts;
+ }
+ if (!this.userConfig.columns) {
+ this.updateUserColumns();
+ } else {
+ this.columns.forEach((c, i) => {
+ c.isHidden = this.userConfig.columns[i].isHidden;
+ });
+ }
+ }
+
+ _calculateUniqueTableName(columns) {
+ const stringToNumber = (s) => {
+ if (!_.isString(s)) {
+ return 0;
+ }
+ let result = 0;
+ for (let i = 0; i < s.length; i++) {
+ result += s.charCodeAt(i) * i;
+ }
+ return result;
+ };
+ return columns
+ .reduce(
+ (result, value, index) =>
+ (stringToNumber(value.prop) + stringToNumber(value.name)) * (index + 1) + result,
+ 0
+ )
+ .toString();
+ }
+
+ _loadUserConfig() {
+ const loaded = this.localStorage.getItem(this.tableName);
+ if (loaded) {
+ this.userConfig = JSON.parse(loaded);
+ }
+ }
+
+ _initUserConfigAutoSave() {
+ const source = Observable.create(this._initUserConfigProxy.bind(this));
+ this.saveSubscriber = source.subscribe(this._saveUserConfig.bind(this));
+ }
+
+ _initUserConfigProxy(observer) {
+ this.userConfig = new Proxy(this.userConfig, {
+ set(config, prop, value) {
+ config[prop] = value;
+ observer.next(config);
+ return true;
+ }
+ });
+ }
+
+ _saveUserConfig(config) {
+ this.localStorage.setItem(this.tableName, JSON.stringify(config));
+ }
+
+ updateUserColumns() {
+ this.userConfig.columns = this.columns.map((c) => ({
+ prop: c.prop,
+ name: c.name,
+ isHidden: !!c.isHidden
+ }));
+ }
+
+ filterHiddenColumns() {
+ this.tableColumns = this.columns.filter((c) => !c.isHidden);
+ }
+
+ ngOnDestroy() {
+ if (this.reloadSubscriber) {
+ this.reloadSubscriber.unsubscribe();
+ }
+ if (this.saveSubscriber) {
+ this.saveSubscriber.unsubscribe();
+ }
+ }
+
+ ngAfterContentChecked() {
+ // If the data table is not visible, e.g. another tab is active, and the
+ // browser window gets resized, the table and its columns won't get resized
+ // automatically if the tab gets visible again.
+ // https://github.com/swimlane/ngx-datatable/issues/193
+ // https://github.com/swimlane/ngx-datatable/issues/193#issuecomment-329144543
+ if (this.table && this.table.element.clientWidth !== this.currentWidth) {
+ this.currentWidth = this.table.element.clientWidth;
+ // Recalculate the sizes of the grid.
+ this.table.recalculate();
+ // Mark the datatable as changed, Angular's change-detection will
+ // do the rest for us => the grid will be redrawn.
+ // Note, the ChangeDetectorRef variable is private, so we need to
+ // use this workaround to access it and make TypeScript happy.
+ const cdRef = _.get(this.table, 'cd');
+ cdRef.markForCheck();
+ }
+ }
+
+ _addTemplates() {
+ this.cellTemplates.bold = this.tableCellBoldTpl;
+ this.cellTemplates.checkIcon = this.checkIconTpl;
+ this.cellTemplates.sparkline = this.sparklineTpl;
+ this.cellTemplates.routerLink = this.routerLinkTpl;
+ this.cellTemplates.perSecond = this.perSecondTpl;
+ this.cellTemplates.executing = this.executingTpl;
+ this.cellTemplates.classAdding = this.classAddingTpl;
+ this.cellTemplates.map = this.mapTpl;
+ }
+
+ useCustomClass(value: any): string {
+ if (!this.customCss) {
+ throw new Error('Custom classes are not set!');
+ }
+ const classes = Object.keys(this.customCss);
+ const css = Object.values(this.customCss)
+ .map((v, i) => ((_.isFunction(v) && v(value)) || v === value) && classes[i])
+ .filter((x) => x)
+ .join(' ');
+ return _.isEmpty(css) ? undefined : css;
+ }
+
+ ngOnChanges() {
+ this.useData();
+ }
+
+ setLimit(e) {
+ const value = parseInt(e.target.value, 10);
+ if (value > 0) {
+ this.userConfig.limit = value;
+ }
+ }
+
+ reloadData() {
+ if (!this.updating) {
+ this.loadingError = false;
+ const context = new CdTableFetchDataContext(() => {
+ // Do we have to display the error panel?
+ this.loadingError = context.errorConfig.displayError;
+ // Force data table to show no data?
+ if (context.errorConfig.resetData) {
+ this.data = [];
+ }
+ // Stop the loading indicator and reset the data table
+ // to the correct state.
+ this.useData();
+ });
+ this.fetchData.emit(context);
+ this.updating = true;
+ }
+ }
+
+ refreshBtn() {
+ this.loadingIndicator = true;
+ this.reloadData();
+ }
+
+ rowIdentity() {
+ return (row) => {
+ const id = row[this.identifier];
+ if (_.isUndefined(id)) {
+ throw new Error(`Wrong identifier "${this.identifier}" -> "${id}"`);
+ }
+ return id;
+ };
+ }
+
+ useData() {
+ if (!this.data) {
+ return; // Wait for data
+ }
+ if (this.search.length > 0) {
+ this.updateFilter();
+ } else {
+ this.rows = [...this.data];
+ }
+ this.reset();
+ this.updateSelected();
+ }
+
+ /**
+ * Reset the data table to correct state. This includes:
+ * - Disable loading indicator
+ * - Reset 'Updating' flag
+ */
+ reset() {
+ this.loadingIndicator = false;
+ this.updating = false;
+ }
+
+ /**
+ * After updating the data, we have to update the selected items
+ * because details may have changed,
+ * or some selected items may have been removed.
+ */
+ updateSelected() {
+ if (this.updateSelectionOnRefresh === 'never') {
+ return;
+ }
+ const newSelected = [];
+ this.selection.selected.forEach((selectedItem) => {
+ for (const row of this.data) {
+ if (selectedItem[this.identifier] === row[this.identifier]) {
+ newSelected.push(row);
+ }
+ }
+ });
+ if (
+ this.updateSelectionOnRefresh === 'onChange' &&
+ _.isEqual(this.selection.selected, newSelected)
+ ) {
+ return;
+ }
+ this.selection.selected = newSelected;
+ this.onSelect(this.selection);
+ }
+
+ onSelect($event: any) {
+ // Ensure we do not process DOM 'select' events.
+ // https://github.com/swimlane/ngx-datatable/issues/899
+ if (_.has($event, 'selected')) {
+ this.selection.selected = $event['selected'];
+ }
+ this.selection.update();
+ this.updateSelection.emit(_.clone(this.selection));
+ }
+
+ toggleColumn($event: any) {
+ const prop: TableColumnProp = $event.target.name;
+ const hide = !$event.target.checked;
+ if (hide && this.tableColumns.length === 1) {
+ $event.target.checked = true;
+ return;
+ }
+ _.find(this.columns, (c: CdTableColumn) => c.prop === prop).isHidden = hide;
+ this.updateColumns();
+ }
+
+ updateColumns() {
+ this.updateUserColumns();
+ this.filterHiddenColumns();
+ const sortProp = this.userConfig.sorts[0].prop;
+ if (!_.find(this.tableColumns, (c: CdTableColumn) => c.prop === sortProp)) {
+ this.userConfig.sorts = this.createSortingDefinition(this.tableColumns[0].prop);
+ this.table.onColumnSort({ sorts: this.userConfig.sorts });
+ }
+ this.table.recalculate();
+ this.cdRef.detectChanges();
+ }
+
+ createSortingDefinition(prop: TableColumnProp): SortPropDir[] {
+ return [
+ {
+ prop: prop,
+ dir: SortDirection.asc
+ }
+ ];
+ }
+
+ changeSorting({ sorts }) {
+ this.userConfig.sorts = sorts;
+ }
+
+ updateFilter(clearSearch = false) {
+ if (clearSearch) {
+ this.search = '';
+ }
+ // prepare search strings
+ let search = this.search.toLowerCase().replace(/,/g, '');
+ const columns = this.columns.filter((c) => c.cellTransformation !== CellTemplate.sparkline);
+ if (search.match(/['"][^'"]+['"]/)) {
+ search = search.replace(/['"][^'"]+['"]/g, (match: string) => {
+ return match.replace(/(['"])([^'"]+)(['"])/g, '$2').replace(/ /g, '+');
+ });
+ }
+ // update the rows
+ this.rows = this.subSearch(this.data, search.split(' ').filter((s) => s.length > 0), columns);
+ // Whenever the filter changes, always go back to the first page
+ this.table.offset = 0;
+ }
+
+ subSearch(data: any[], currentSearch: string[], columns: CdTableColumn[]) {
+ if (currentSearch.length === 0 || data.length === 0) {
+ return data;
+ }
+ const searchTerms: string[] = currentSearch
+ .pop()
+ .replace('+', ' ')
+ .split(':');
+ const columnsClone = [...columns];
+ if (searchTerms.length === 2) {
+ columns = columnsClone.filter((c) => c.name.toLowerCase().indexOf(searchTerms[0]) !== -1);
+ }
+ data = this.basicDataSearch(_.last(searchTerms), data, columns);
+ // Checks if user searches for column but he is still typing
+ return this.subSearch(data, currentSearch, columnsClone);
+ }
+
+ basicDataSearch(searchTerm: string, rows: any[], columns: CdTableColumn[]) {
+ if (searchTerm.length === 0) {
+ return rows;
+ }
+ return rows.filter((row) => {
+ return (
+ columns.filter((col) => {
+ let cellValue: any = _.get(row, col.prop);
+
+ if (!_.isUndefined(col.pipe)) {
+ cellValue = col.pipe.transform(cellValue);
+ }
+ if (_.isUndefined(cellValue) || _.isNull(cellValue)) {
+ return false;
+ }
+
+ if (_.isArray(cellValue)) {
+ cellValue = cellValue.join(' ');
+ } else if (_.isNumber(cellValue) || _.isBoolean(cellValue)) {
+ cellValue = cellValue.toString();
+ }
+
+ if (_.isObjectLike(cellValue)) {
+ if (this.searchableObjects) {
+ cellValue = JSON.stringify(cellValue);
+ } else {
+ return false;
+ }
+ }
+
+ return cellValue.toLowerCase().indexOf(searchTerm) !== -1;
+ }).length > 0
+ );
+ });
+ }
+
+ getRowClass() {
+ // Return the function used to populate a row's CSS classes.
+ return () => {
+ return {
+ clickable: !_.isUndefined(this.selectionType)
+ };
+ };
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.spec.ts
new file mode 100644
index 00000000..49b504fd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.spec.ts
@@ -0,0 +1,41 @@
+import { cdEncode, cdEncodeNot } from './cd-encode';
+
+describe('cdEncode', () => {
+ @cdEncode
+ class ClassA {
+ x2: string;
+ y2: string;
+
+ methodA(x1: string, @cdEncodeNot y1: string) {
+ this.x2 = x1;
+ this.y2 = y1;
+ }
+ }
+
+ class ClassB {
+ x2: string;
+ y2: string;
+
+ @cdEncode
+ methodB(x1: string, @cdEncodeNot y1: string) {
+ this.x2 = x1;
+ this.y2 = y1;
+ }
+ }
+
+ const word = 'a+b/c-d';
+
+ it('should encode all params of ClassA, with exception of y1', () => {
+ const a = new ClassA();
+ a.methodA(word, word);
+ expect(a.x2).toBe('a%2Bb%2Fc-d');
+ expect(a.y2).toBe(word);
+ });
+
+ it('should encode all params of methodB, with exception of y1', () => {
+ const b = new ClassB();
+ b.methodB(word, word);
+ expect(b.x2).toBe('a%2Bb%2Fc-d');
+ expect(b.y2).toBe(word);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts
new file mode 100644
index 00000000..c77be120
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/decorators/cd-encode.ts
@@ -0,0 +1,79 @@
+import * as _ from 'lodash';
+
+/**
+ * This decorator can be used in a class or method.
+ * It will encode all the string parameters of all the methods of a class
+ * or, if applied on a method, the specified method.
+ *
+ * @export
+ * @param {Function} [target=null]
+ * @returns {*}
+ */
+export function cdEncode(...args: any[]): any {
+ switch (args.length) {
+ case 1:
+ return encodeClass.apply(this, args);
+ case 3:
+ return encodeMethod.apply(this, args);
+ default:
+ throw new Error();
+ }
+}
+
+/**
+ * This decorator can be used in parameters only.
+ * It will exclude the parameter from being encode.
+ * This should be used in parameters that are going
+ * to be sent in the request's body.
+ *
+ * @export
+ * @param {Object} target
+ * @param {string} propertyKey
+ * @param {number} index
+ */
+export function cdEncodeNot(target: Object, propertyKey: string, index: number) {
+ const metadataKey = `__ignore_${propertyKey}`;
+ if (Array.isArray(target[metadataKey])) {
+ target[metadataKey].push(index);
+ } else {
+ target[metadataKey] = [index];
+ }
+}
+
+function encodeClass(target: Function) {
+ for (const propertyName of Object.keys(target.prototype)) {
+ const descriptor = Object.getOwnPropertyDescriptor(target.prototype, propertyName);
+
+ const isMethod = descriptor.value instanceof Function;
+ if (!isMethod) {
+ continue;
+ }
+
+ encodeMethod(target.prototype, propertyName, descriptor);
+ Object.defineProperty(target.prototype, propertyName, descriptor);
+ }
+}
+
+function encodeMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
+ if (descriptor === undefined) {
+ descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
+ }
+ const originalMethod = descriptor.value;
+
+ descriptor.value = function() {
+ const metadataKey = `__ignore_${propertyKey}`;
+ const indices: number[] = target[metadataKey] || [];
+ const args = [];
+
+ for (let i = 0; i < arguments.length; i++) {
+ if (_.isString(arguments[i]) && indices.indexOf(i) === -1) {
+ args[i] = encodeURIComponent(arguments[i]);
+ } else {
+ args[i] = arguments[i];
+ }
+ }
+
+ const result = originalMethod.apply(this, args);
+ return result;
+ };
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.spec.ts
new file mode 100644
index 00000000..afbc3539
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.spec.ts
@@ -0,0 +1,61 @@
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { AutofocusDirective } from './autofocus.directive';
+
+@Component({
+ template: `
+ <form>
+ <input id="x" type="text" />
+ <input id="y" type="password" autofocus />
+ </form>
+ `
+})
+export class PasswordFormComponent {}
+
+@Component({
+ template: `
+ <form>
+ <input id="x" type="checkbox" autofocus />
+ <input id="y" type="text" />
+ </form>
+ `
+})
+export class CheckboxFormComponent {}
+
+describe('AutofocusDirective', () => {
+ configureTestBed({
+ declarations: [AutofocusDirective, CheckboxFormComponent, PasswordFormComponent]
+ });
+
+ it('should create an instance', () => {
+ const directive = new AutofocusDirective(null);
+ expect(directive).toBeTruthy();
+ });
+
+ it('should focus the password form field', () => {
+ const fixture: ComponentFixture<PasswordFormComponent> = TestBed.createComponent(
+ PasswordFormComponent
+ );
+ fixture.detectChanges();
+ const focused = fixture.debugElement.query(By.css(':focus'));
+ expect(focused.attributes.id).toBe('y');
+ expect(focused.attributes.type).toBe('password');
+ const element = document.getElementById('y');
+ expect(element === document.activeElement).toBeTruthy();
+ });
+
+ it('should focus the checkbox form field', () => {
+ const fixture: ComponentFixture<CheckboxFormComponent> = TestBed.createComponent(
+ CheckboxFormComponent
+ );
+ fixture.detectChanges();
+ const focused = fixture.debugElement.query(By.css(':focus'));
+ expect(focused.attributes.id).toBe('x');
+ expect(focused.attributes.type).toBe('checkbox');
+ const element = document.getElementById('x');
+ expect(element === document.activeElement).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.ts
new file mode 100644
index 00000000..809d8b76
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/autofocus.directive.ts
@@ -0,0 +1,17 @@
+import { AfterViewInit, Directive, ElementRef } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Directive({
+ selector: '[autofocus]' // tslint:disable-line
+})
+export class AutofocusDirective implements AfterViewInit {
+ constructor(private elementRef: ElementRef) {}
+
+ ngAfterViewInit() {
+ const el: HTMLInputElement = this.elementRef.nativeElement;
+ if (_.isFunction(el.focus)) {
+ el.focus();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.spec.ts
new file mode 100644
index 00000000..e50fd863
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.spec.ts
@@ -0,0 +1,8 @@
+import { Copy2ClipboardButtonDirective } from './copy2clipboard-button.directive';
+
+describe('Copy2clipboardButtonDirective', () => {
+ it('should create an instance', () => {
+ const directive = new Copy2ClipboardButtonDirective(null, null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts
new file mode 100644
index 00000000..55efbaab
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts
@@ -0,0 +1,48 @@
+import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2 } from '@angular/core';
+
+import { ToastrService } from 'ngx-toastr';
+
+@Directive({
+ selector: '[cdCopy2ClipboardButton]'
+})
+export class Copy2ClipboardButtonDirective implements OnInit {
+ @Input()
+ private cdCopy2ClipboardButton: string;
+
+ constructor(
+ private elementRef: ElementRef,
+ private renderer: Renderer2,
+ private toastr: ToastrService
+ ) {}
+
+ ngOnInit() {
+ const iElement = this.renderer.createElement('i');
+ this.renderer.addClass(iElement, 'icon-prepend');
+ this.renderer.addClass(iElement, 'fa');
+ this.renderer.addClass(iElement, 'fa-clipboard');
+ this.renderer.appendChild(this.elementRef.nativeElement, iElement);
+ }
+
+ private getInputElement() {
+ return document.getElementById(this.cdCopy2ClipboardButton) as HTMLInputElement;
+ }
+
+ @HostListener('click')
+ onClick() {
+ try {
+ // Create the input to hold our text.
+ const tmpInputElement = document.createElement('input');
+ tmpInputElement.value = this.getInputElement().value;
+ document.body.appendChild(tmpInputElement);
+ // Copy text to clipboard.
+ tmpInputElement.select();
+ document.execCommand('copy');
+ // Finally remove the element.
+ document.body.removeChild(tmpInputElement);
+
+ this.toastr.success('Copied text to the clipboard successfully.');
+ } catch (err) {
+ this.toastr.error('Failed to copy text to the clipboard.');
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.spec.ts
new file mode 100644
index 00000000..858becc4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.spec.ts
@@ -0,0 +1,12 @@
+import { DimlessBinaryPerSecondDirective } from './dimless-binary-per-second.directive';
+
+export class MockElementRef {
+ nativeElement: {};
+}
+
+describe('DimlessBinaryPerSecondDirective', () => {
+ it('should create an instance', () => {
+ const directive = new DimlessBinaryPerSecondDirective(new MockElementRef(), null, null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts
new file mode 100644
index 00000000..6355fd74
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts
@@ -0,0 +1,132 @@
+import {
+ Directive,
+ ElementRef,
+ EventEmitter,
+ HostListener,
+ Input,
+ OnInit,
+ Output
+} from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+import { DimlessBinaryPerSecondPipe } from '../pipes/dimless-binary-per-second.pipe';
+import { FormatterService } from '../services/formatter.service';
+
+@Directive({
+ selector: '[cdDimlessBinaryPerSecond]'
+})
+export class DimlessBinaryPerSecondDirective implements OnInit {
+ @Output()
+ ngModelChange: EventEmitter<any> = new EventEmitter();
+
+ /**
+ * Event emitter for letting this directive know that the data has (asynchronously) been loaded
+ * and the value needs to be adapted by this directive.
+ */
+ @Input()
+ ngDataReady: EventEmitter<any>;
+
+ /**
+ * Minimum size in bytes.
+ * If user enter a value lower than <minBytes>,
+ * the model will automatically be update to <minBytes>.
+ *
+ * If <roundPower> is used, this value should be a power of <roundPower>.
+ *
+ * Example:
+ * Given minBytes=4096 (4KiB), if user type 1KiB, then model will be updated to 4KiB
+ */
+ @Input()
+ minBytes: number;
+
+ /**
+ * Maximum size in bytes.
+ * If user enter a value greater than <maxBytes>,
+ * the model will automatically be update to <maxBytes>.
+ *
+ * If <roundPower> is used, this value should be a power of <roundPower>.
+ *
+ * Example:
+ * Given maxBytes=3145728 (3MiB), if user type 4MiB, then model will be updated to 3MiB
+ */
+ @Input()
+ maxBytes: number;
+
+ /**
+ * Value will be rounded up the nearest power of <roundPower>
+ *
+ * Example:
+ * Given roundPower=2, if user type 7KiB, then model will be updated to 8KiB
+ * Given roundPower=2, if user type 5KiB, then model will be updated to 4KiB
+ */
+ @Input()
+ roundPower: number;
+
+ /**
+ * Default unit that should be used when user do not type a unit.
+ * By default, "MiB" will be used.
+ *
+ * Example:
+ * Given defaultUnit=null, if user type 7, then model will be updated to 7MiB
+ * Given defaultUnit=k, if user type 7, then model will be updated to 7KiB
+ */
+ @Input()
+ defaultUnit: string;
+
+ private el: HTMLInputElement;
+
+ constructor(
+ private elementRef: ElementRef,
+ private control: NgControl,
+ private dimlessBinaryPerSecondPipe: DimlessBinaryPerSecondPipe,
+ private formatter: FormatterService
+ ) {
+ this.el = this.elementRef.nativeElement;
+ }
+
+ ngOnInit() {
+ this.setValue(this.el.value);
+ if (this.ngDataReady) {
+ this.ngDataReady.subscribe(() => this.setValue(this.el.value));
+ }
+ }
+
+ setValue(value) {
+ if (/^[\d.]+$/.test(value)) {
+ value += this.defaultUnit || 'm';
+ }
+ const size = this.formatter.toBytes(value, 0);
+ const roundedSize = this.round(size);
+ this.el.value = this.dimlessBinaryPerSecondPipe.transform(roundedSize);
+ if (size !== null) {
+ this.ngModelChange.emit(this.el.value);
+ this.control.control.setValue(this.el.value);
+ } else {
+ this.ngModelChange.emit(null);
+ this.control.control.setValue(null);
+ }
+ }
+
+ round(size) {
+ if (size !== null && size !== 0) {
+ if (!_.isUndefined(this.minBytes) && size < this.minBytes) {
+ return this.minBytes;
+ }
+ if (!_.isUndefined(this.maxBytes) && size > this.maxBytes) {
+ return this.maxBytes;
+ }
+ if (!_.isUndefined(this.roundPower)) {
+ const power = Math.round(Math.log(size) / Math.log(this.roundPower));
+ return Math.pow(this.roundPower, power);
+ }
+ }
+ return size;
+ }
+
+ @HostListener('blur', ['$event.target.value'])
+ onBlur(value) {
+ this.setValue(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.spec.ts
new file mode 100644
index 00000000..5822e7d9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.spec.ts
@@ -0,0 +1,12 @@
+import { DimlessBinaryDirective } from './dimless-binary.directive';
+
+export class MockElementRef {
+ nativeElement: {};
+}
+
+describe('DimlessBinaryDirective', () => {
+ it('should create an instance', () => {
+ const directive = new DimlessBinaryDirective(new MockElementRef(), null, null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.ts
new file mode 100644
index 00000000..efe7e8da
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.ts
@@ -0,0 +1,122 @@
+import {
+ Directive,
+ ElementRef,
+ EventEmitter,
+ HostListener,
+ Input,
+ OnInit,
+ Output
+} from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+import { DimlessBinaryPipe } from '../pipes/dimless-binary.pipe';
+import { FormatterService } from '../services/formatter.service';
+
+@Directive({
+ selector: '[cdDimlessBinary]'
+})
+export class DimlessBinaryDirective implements OnInit {
+ @Output()
+ ngModelChange: EventEmitter<any> = new EventEmitter();
+
+ /**
+ * Minimum size in bytes.
+ * If user enter a value lower than <minBytes>,
+ * the model will automatically be update to <minBytes>.
+ *
+ * If <roundPower> is used, this value should be a power of <roundPower>.
+ *
+ * Example:
+ * Given minBytes=4096 (4KiB), if user type 1KiB, then model will be updated to 4KiB
+ */
+ @Input()
+ minBytes: number;
+
+ /**
+ * Maximum size in bytes.
+ * If user enter a value greater than <maxBytes>,
+ * the model will automatically be update to <maxBytes>.
+ *
+ * If <roundPower> is used, this value should be a power of <roundPower>.
+ *
+ * Example:
+ * Given maxBytes=3145728 (3MiB), if user type 4MiB, then model will be updated to 3MiB
+ */
+ @Input()
+ maxBytes: number;
+
+ /**
+ * Value will be rounded up the nearest power of <roundPower>
+ *
+ * Example:
+ * Given roundPower=2, if user type 7KiB, then model will be updated to 8KiB
+ * Given roundPower=2, if user type 5KiB, then model will be updated to 4KiB
+ */
+ @Input()
+ roundPower: number;
+
+ /**
+ * Default unit that should be used when user do not type a unit.
+ * By default, "MiB" will be used.
+ *
+ * Example:
+ * Given defaultUnit=null, if user type 7, then model will be updated to 7MiB
+ * Given defaultUnit=k, if user type 7, then model will be updated to 7KiB
+ */
+ @Input()
+ defaultUnit: string;
+
+ private el: HTMLInputElement;
+
+ constructor(
+ private elementRef: ElementRef,
+ private control: NgControl,
+ private dimlessBinaryPipe: DimlessBinaryPipe,
+ private formatter: FormatterService
+ ) {
+ this.el = this.elementRef.nativeElement;
+ }
+
+ ngOnInit() {
+ this.setValue(this.el.value);
+ }
+
+ setValue(value) {
+ if (/^[\d.]+$/.test(value)) {
+ value += this.defaultUnit || 'm';
+ }
+ const size = this.formatter.toBytes(value);
+ const roundedSize = this.round(size);
+ this.el.value = this.dimlessBinaryPipe.transform(roundedSize);
+ if (size !== null) {
+ this.ngModelChange.emit(this.el.value);
+ this.control.control.setValue(this.el.value);
+ } else {
+ this.ngModelChange.emit(null);
+ this.control.control.setValue(null);
+ }
+ }
+
+ round(size) {
+ if (size !== null && size !== 0) {
+ if (!_.isUndefined(this.minBytes) && size < this.minBytes) {
+ return this.minBytes;
+ }
+ if (!_.isUndefined(this.maxBytes) && size > this.maxBytes) {
+ return this.maxBytes;
+ }
+ if (!_.isUndefined(this.roundPower)) {
+ const power = Math.round(Math.log(size) / Math.log(this.roundPower));
+ return Math.pow(this.roundPower, power);
+ }
+ }
+ return size;
+ }
+
+ @HostListener('blur', ['$event.target.value'])
+ onBlur(value) {
+ this.setValue(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/directives.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/directives.module.ts
new file mode 100644
index 00000000..8724ce47
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/directives.module.ts
@@ -0,0 +1,41 @@
+import { NgModule } from '@angular/core';
+
+import { AutofocusDirective } from './autofocus.directive';
+import { Copy2ClipboardButtonDirective } from './copy2clipboard-button.directive';
+import { DimlessBinaryPerSecondDirective } from './dimless-binary-per-second.directive';
+import { DimlessBinaryDirective } from './dimless-binary.directive';
+import { FormInputDisableDirective } from './form-input-disable.directive';
+import { FormScopeDirective } from './form-scope.directive';
+import { IopsDirective } from './iops.directive';
+import { MillisecondsDirective } from './milliseconds.directive';
+import { PasswordButtonDirective } from './password-button.directive';
+import { TrimDirective } from './trim.directive';
+
+@NgModule({
+ imports: [],
+ declarations: [
+ AutofocusDirective,
+ Copy2ClipboardButtonDirective,
+ DimlessBinaryDirective,
+ DimlessBinaryPerSecondDirective,
+ PasswordButtonDirective,
+ TrimDirective,
+ MillisecondsDirective,
+ IopsDirective,
+ FormInputDisableDirective,
+ FormScopeDirective
+ ],
+ exports: [
+ AutofocusDirective,
+ Copy2ClipboardButtonDirective,
+ DimlessBinaryDirective,
+ DimlessBinaryPerSecondDirective,
+ PasswordButtonDirective,
+ TrimDirective,
+ MillisecondsDirective,
+ IopsDirective,
+ FormInputDisableDirective,
+ FormScopeDirective
+ ]
+})
+export class DirectivesModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.spec.ts
new file mode 100644
index 00000000..c5263533
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.spec.ts
@@ -0,0 +1,75 @@
+import { Component, DebugElement, Input } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { Permission } from '../models/permissions';
+import { AuthStorageService } from '../services/auth-storage.service';
+import { FormInputDisableDirective } from './form-input-disable.directive';
+import { FormScopeDirective } from './form-scope.directive';
+
+@Component({
+ template: `
+ <form cdFormScope="osd">
+ <input type="checkbox" />
+ </form>
+ `
+})
+export class FormDisableComponent {}
+
+class MockFormScopeDirective {
+ @Input() cdFormScope = 'osd';
+}
+
+describe('FormInputDisableDirective', () => {
+ let fakePermissions: Permission;
+ let authStorageService: AuthStorageService;
+ let directive: FormInputDisableDirective;
+ let fixture: ComponentFixture<FormDisableComponent>;
+ let inputElement: DebugElement;
+ configureTestBed({
+ declarations: [FormScopeDirective, FormInputDisableDirective, FormDisableComponent]
+ });
+
+ beforeEach(() => {
+ directive = new FormInputDisableDirective(
+ new MockFormScopeDirective(),
+ new AuthStorageService(),
+ null
+ );
+
+ fakePermissions = {
+ create: false,
+ update: false,
+ read: false,
+ delete: false
+ };
+ authStorageService = TestBed.get(AuthStorageService);
+ spyOn(authStorageService, 'getPermissions').and.callFake(() => ({
+ osd: fakePermissions
+ }));
+
+ fixture = TestBed.createComponent(FormDisableComponent);
+ inputElement = fixture.debugElement.query(By.css('input'));
+ });
+
+ afterEach(() => {
+ directive = null;
+ });
+
+ it('should create an instance', () => {
+ expect(directive).toBeTruthy();
+ });
+
+ it('should disable the input if update permission is false', () => {
+ fixture.detectChanges();
+ expect(inputElement.nativeElement.disabled).toBeTruthy();
+ });
+
+ it('should not disable the input if update permission is true', () => {
+ fakePermissions.update = true;
+ fakePermissions.read = false;
+ fixture.detectChanges();
+ expect(inputElement.nativeElement.disabled).toBeFalsy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.ts
new file mode 100644
index 00000000..4fcfe65e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-input-disable.directive.ts
@@ -0,0 +1,30 @@
+import { AfterViewInit, Directive, ElementRef, Optional } from '@angular/core';
+
+import { Permissions } from '../models/permissions';
+import { AuthStorageService } from '../services/auth-storage.service';
+import { FormScopeDirective } from './form-scope.directive';
+
+@Directive({
+ selector:
+ 'input:not([cdNoFormInputDisable]), select:not([cdNoFormInputDisable]), [cdFormInputDisable]'
+})
+export class FormInputDisableDirective implements AfterViewInit {
+ permissions: Permissions;
+ service_name: keyof Permissions;
+
+ constructor(
+ @Optional() private formScope: FormScopeDirective,
+ private authStorageService: AuthStorageService,
+ private elementRef: ElementRef
+ ) {}
+
+ ngAfterViewInit() {
+ this.permissions = this.authStorageService.getPermissions();
+ if (this.formScope !== null) {
+ this.service_name = this.formScope.cdFormScope;
+ }
+ if (this.service_name && !this.permissions[this.service_name].update) {
+ this.elementRef.nativeElement.disabled = true;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.spec.ts
new file mode 100644
index 00000000..2cf882ec
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.spec.ts
@@ -0,0 +1,8 @@
+import { FormScopeDirective } from './form-scope.directive';
+
+describe('UpdateOnlyDirective', () => {
+ it('should create an instance', () => {
+ const directive = new FormScopeDirective();
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.ts
new file mode 100644
index 00000000..8ae3f848
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-scope.directive.ts
@@ -0,0 +1,8 @@
+import { Directive, Input } from '@angular/core';
+
+@Directive({
+ selector: '[cdFormScope]'
+})
+export class FormScopeDirective {
+ @Input() cdFormScope: any;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.spec.ts
new file mode 100644
index 00000000..9c1641de
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.spec.ts
@@ -0,0 +1,8 @@
+import { IopsDirective } from './iops.directive';
+
+describe('IopsDirective', () => {
+ it('should create an instance', () => {
+ const directive = new IopsDirective(null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.ts
new file mode 100644
index 00000000..5d5d22db
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/iops.directive.ts
@@ -0,0 +1,31 @@
+import { Directive, EventEmitter, HostListener, Input, OnInit } from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+import { FormatterService } from '../services/formatter.service';
+
+@Directive({
+ selector: '[cdIops]'
+})
+export class IopsDirective implements OnInit {
+ @Input()
+ ngDataReady: EventEmitter<any>;
+
+ constructor(private formatter: FormatterService, private ngControl: NgControl) {}
+
+ setValue(value: string): void {
+ const iops = this.formatter.toIops(value);
+ this.ngControl.control.setValue(`${iops} IOPS`);
+ }
+
+ ngOnInit(): void {
+ this.setValue(this.ngControl.value);
+ if (this.ngDataReady) {
+ this.ngDataReady.subscribe(() => this.setValue(this.ngControl.value));
+ }
+ }
+
+ @HostListener('blur', ['$event.target.value'])
+ onUpdate(value) {
+ this.setValue(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.spec.ts
new file mode 100644
index 00000000..50380205
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.spec.ts
@@ -0,0 +1,8 @@
+import { MillisecondsDirective } from './milliseconds.directive';
+
+describe('MillisecondsDirective', () => {
+ it('should create an instance', () => {
+ const directive = new MillisecondsDirective(null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.ts
new file mode 100644
index 00000000..4d84499b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/milliseconds.directive.ts
@@ -0,0 +1,31 @@
+import { Directive, EventEmitter, HostListener, Input, OnInit } from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+import { FormatterService } from '../services/formatter.service';
+
+@Directive({
+ selector: '[cdMilliseconds]'
+})
+export class MillisecondsDirective implements OnInit {
+ @Input()
+ ngDataReady: EventEmitter<any>;
+
+ constructor(private control: NgControl, private formatter: FormatterService) {}
+
+ setValue(value: string): void {
+ const ms = this.formatter.toMilliseconds(value);
+ this.control.control.setValue(`${ms} ms`);
+ }
+
+ ngOnInit(): void {
+ this.setValue(this.control.value);
+ if (this.ngDataReady) {
+ this.ngDataReady.subscribe(() => this.setValue(this.control.value));
+ }
+ }
+
+ @HostListener('blur', ['$event.target.value'])
+ onUpdate(value) {
+ this.setValue(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.spec.ts
new file mode 100644
index 00000000..1fc8f9c7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.spec.ts
@@ -0,0 +1,8 @@
+import { PasswordButtonDirective } from './password-button.directive';
+
+describe('PasswordButtonDirective', () => {
+ it('should create an instance', () => {
+ const directive = new PasswordButtonDirective(null, null);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.ts
new file mode 100644
index 00000000..1a17b9f0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/password-button.directive.ts
@@ -0,0 +1,46 @@
+import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2 } from '@angular/core';
+
+@Directive({
+ selector: '[cdPasswordButton]'
+})
+export class PasswordButtonDirective implements OnInit {
+ private iElement: HTMLElement;
+
+ @Input()
+ private cdPasswordButton: string;
+
+ constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
+
+ ngOnInit() {
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'tabindex', '-1');
+ this.iElement = this.renderer.createElement('i');
+ this.renderer.addClass(this.iElement, 'icon-prepend');
+ this.renderer.addClass(this.iElement, 'fa');
+ this.renderer.appendChild(this.elementRef.nativeElement, this.iElement);
+ this.update();
+ }
+
+ private getInputElement() {
+ return document.getElementById(this.cdPasswordButton) as HTMLInputElement;
+ }
+
+ private update() {
+ const inputElement = this.getInputElement();
+ if (inputElement && inputElement.type === 'text') {
+ this.renderer.removeClass(this.iElement, 'fa-eye');
+ this.renderer.addClass(this.iElement, 'fa-eye-slash');
+ } else {
+ this.renderer.removeClass(this.iElement, 'fa-eye-slash');
+ this.renderer.addClass(this.iElement, 'fa-eye');
+ }
+ }
+
+ @HostListener('click')
+ onClick() {
+ const inputElement = this.getInputElement();
+ // Modify the type of the input field.
+ inputElement.type = inputElement.type === 'password' ? 'text' : 'password';
+ // Update the button icon/tooltip.
+ this.update();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.spec.ts
new file mode 100644
index 00000000..db5e3940
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.spec.ts
@@ -0,0 +1,50 @@
+import { Component } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { CdFormGroup } from '../forms/cd-form-group';
+import { TrimDirective } from './trim.directive';
+
+@Component({
+ template: `
+ <form [formGroup]="trimForm">
+ <input type="text" formControlName="trimInput" cdTrim />
+ </form>
+ `
+})
+export class TrimComponent {
+ trimForm: CdFormGroup;
+ constructor() {
+ this.trimForm = new CdFormGroup({
+ trimInput: new FormControl()
+ });
+ }
+}
+
+describe('TrimDirective', () => {
+ configureTestBed({
+ imports: [FormsModule, ReactiveFormsModule],
+ declarations: [TrimDirective, TrimComponent]
+ });
+
+ it('should create an instance', () => {
+ const directive = new TrimDirective(null);
+ expect(directive).toBeTruthy();
+ });
+
+ it('should trim', () => {
+ const fixture: ComponentFixture<TrimComponent> = TestBed.createComponent(TrimComponent);
+ const component: TrimComponent = fixture.componentInstance;
+ const inputElement: HTMLInputElement = fixture.debugElement.query(By.css('input'))
+ .nativeElement;
+ fixture.detectChanges();
+
+ inputElement.value = ' a b ';
+ inputElement.dispatchEvent(new Event('input'));
+ const expectedValue = 'a b';
+ expect(inputElement.value).toBe(expectedValue);
+ expect(component.trimForm.getValue('trimInput')).toBe(expectedValue);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.ts
new file mode 100644
index 00000000..eadac251
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/trim.directive.ts
@@ -0,0 +1,21 @@
+import { Directive, HostListener } from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+@Directive({
+ selector: '[cdTrim]'
+})
+export class TrimDirective {
+ constructor(private ngControl: NgControl) {}
+
+ @HostListener('input', ['$event.target.value'])
+ onInput(value) {
+ this.setValue(value);
+ }
+
+ setValue(value: string): void {
+ value = _.isString(value) ? value.trim() : value;
+ this.ngControl.control.setValue(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/cell-template.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/cell-template.enum.ts
new file mode 100644
index 00000000..9b5a1bfa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/cell-template.enum.ts
@@ -0,0 +1,18 @@
+export enum CellTemplate {
+ bold = 'bold',
+ sparkline = 'sparkline',
+ perSecond = 'perSecond',
+ checkIcon = 'checkIcon',
+ routerLink = 'routerLink',
+ executing = 'executing',
+ classAdding = 'classAdding',
+ // Maps the value using the given dictionary.
+ // {
+ // ...
+ // cellTransformation: CellTemplate.map,
+ // customTemplateConfig: {
+ // [key: any]: any
+ // }
+ // }
+ map = 'map'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/components.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/components.enum.ts
new file mode 100644
index 00000000..bf8daafc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/components.enum.ts
@@ -0,0 +1,9 @@
+export enum Components {
+ auth = 'Login',
+ cephfs = 'CephFS',
+ rbd = 'RBD',
+ pool = 'Pool',
+ osd = 'OSD',
+ role = 'Role',
+ user = 'User'
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts
new file mode 100644
index 00000000..50578b8d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts
@@ -0,0 +1,72 @@
+export enum Icons {
+ /* Icons for Symbol */
+ add = 'fa fa-plus', // Create, Add
+ addCircle = 'fa fa-plus-circle', // Plus with Circle
+ minusCircle = 'fa fa-minus-circle', // Minus with Circle
+ edit = 'fa fa-pencil', // Edit, Edit Mode, Rename
+ destroy = 'fa fa-times', // Destroy, Remove, Delete
+ destroyCircle = 'fa fa-times-circle', // Destroy, Remove, Delete
+ exchange = 'fa fa-exchange', // Edit-Peer
+ copy = 'fa fa-copy', // Copy
+ clipboard = 'fa fa-clipboard', // Clipboard
+ flatten = 'fa-chain-broken', // Flatten, Link broken, Mark Lost
+ trash = 'fa fa-trash-o', // Move to trash
+ lock = 'fa fa-lock', // Protect
+ unlock = 'fa fa-unlock', // Unprotect
+ clone = 'fa fa-clone', // clone
+ undo = 'fa fa-undo', // Rollback, Restore
+ search = 'fa fa-search', // Search
+ start = 'fa fa-play', // Enable
+ stop = 'fa fa-stop', // Disable
+ analyse = 'fa fa-stethoscope', // Scrub
+ deepCheck = 'fa fa-cog', // Deep Scrub, Setting, Configuration
+ reweight = 'fa-balance-scale', // Reweight
+ left = 'fa fa-arrow-left', // Mark out
+ right = 'fa fa-arrow-right', // Mark in
+ down = 'fa fa-arrow-down', // Mark Down
+ erase = 'fa fa-eraser', // Purge
+ user = 'fa fa-user', // User, Initiators
+ share = 'fa fa-share-alt', // share
+ key = 'fa fa-key-modern', // S3 Keys, Swift Keys, Authentication
+ warning = 'fa fa-exclamation-triangle', // Notification warning
+ info = 'fa fa-info', // Notification information
+ infoCircle = 'fa fa-info-circle', // Info on landing page
+ questionCircle = 'fa fa-question-circle-o',
+ check = 'fa fa-check', // Notification check
+ show = 'fa fa-eye', // Show
+ paragraph = 'fa fa-paragraph', // Silence Matcher - Attribute name
+ terminal = 'fa fa-terminal', // Silence Matcher - Value
+ magic = 'fa fa-magic', // Silence Matcher - Regex checkbox
+ hourglass = 'fa fa-hourglass-o', // Task
+ filledHourglass = 'fa fa-hourglass', // Task
+ table = 'fa fa-table', // Table,
+ spinner = 'fa spinner', // spinner, Load
+ refresh = 'fa fa-refresh', // Refresh
+ bullseye = 'fa fa-bullseye', // Target
+ disk = 'fa fa-hdd-o', // Hard disk, disks
+ server = 'fa fa-server', // Server, Portal
+ filter = 'fa fa-filter', // Filter
+ lineChart = 'fa fa-line-chart', // Line chart
+ signOut = 'fa fa-sign-out', // Sign Out
+ health = 'fa fa-heartbeat', // Health
+ circle = 'fa fa-circle', // Circle
+ bell = 'fa fa-bell', // Notification
+ tag = 'fa fa-tag', // Tag, Badge
+ leftArrow = 'fa fa-angle-left', // Left facing angle
+ rightArrow = 'fa fa-angle-right', // Right facing angle
+ leftArrowDouble = 'fa fa-angle-double-left', // Left facing Double angle
+ rightArrowDouble = 'fa fa-angle-double-right', // Left facing Double angle
+ flag = 'fa fa-flag', // OSD configuration
+
+ /* Icons for special effect */
+ width = 'fa fa-fw', // set one or more icons to the same fixed width
+ large = 'fa fa-lg', // icon becomes 33% larger
+ large2x = 'fa fa-2x', // icon becomes 50% larger
+ large3x = 'fa fa-3x', // icon becomes 3 times larger
+ stack = 'fa fa-stack', // To stack multiple icons
+ stack1x = 'fa fa-stack-1x', // To stack regularly sized icon
+ stack2x = 'fa fa-stack-2x', // To stack regularly sized icon
+ pulse = 'fa fa-pulse', // To have spinner rotate with 8 steps
+ spin = 'fa fa-spin', // To get any icon to rotate
+ inverse = 'fa fa-inverse' // To get an alternative icon color
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts
new file mode 100644
index 00000000..c82929fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/notification-type.enum.ts
@@ -0,0 +1,5 @@
+export enum NotificationType {
+ error,
+ info,
+ success
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/unix_errno.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/unix_errno.enum.ts
new file mode 100644
index 00000000..98bcb689
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/unix_errno.enum.ts
@@ -0,0 +1,4 @@
+// http://www.virtsync.com/c-error-codes-include-errno
+export enum UnixErrno {
+ EEXIST = 17 // File exists
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/view-cache-status.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/view-cache-status.enum.ts
new file mode 100644
index 00000000..169059c4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/view-cache-status.enum.ts
@@ -0,0 +1,6 @@
+export enum ViewCacheStatus {
+ ValueOk = 0,
+ ValueStale = 1,
+ ValueNone = 2,
+ ValueException = 3
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.spec.ts
new file mode 100644
index 00000000..07e7f00d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.spec.ts
@@ -0,0 +1,32 @@
+import { Validators } from '@angular/forms';
+import { CdFormBuilder } from './cd-form-builder';
+import { CdFormGroup } from './cd-form-group';
+
+describe('cd-form-builder', () => {
+ let service: CdFormBuilder;
+
+ beforeEach(() => {
+ service = new CdFormBuilder();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should create a nested CdFormGroup', () => {
+ const form = service.group({
+ nested: service.group({
+ a: [null],
+ b: ['sth'],
+ c: [2, [Validators.min(3)]]
+ }),
+ d: [{ e: 3 }],
+ f: [true]
+ });
+ expect(form.constructor).toBe(CdFormGroup);
+ expect(form instanceof CdFormGroup).toBeTruthy();
+ expect(form.getValue('b')).toBe('sth');
+ expect(form.getValue('d')).toEqual({ e: 3 });
+ expect(form.get('c').valid).toBeFalsy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.ts
new file mode 100644
index 00000000..307407a2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-builder.ts
@@ -0,0 +1,20 @@
+import { Injectable } from '@angular/core';
+import { FormBuilder } from '@angular/forms';
+
+import { CdFormGroup } from './cd-form-group';
+
+/**
+ * CdFormBuilder extends FormBuilder to create an CdFormGroup based form.
+ */
+@Injectable({
+ providedIn: 'root'
+})
+export class CdFormBuilder extends FormBuilder {
+ group(
+ controlsConfig: { [key: string]: any },
+ extra: { [key: string]: any } | null = null
+ ): CdFormGroup {
+ const form = super.group(controlsConfig, extra);
+ return new CdFormGroup(form.controls, form.validator, form.asyncValidator);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.spec.ts
new file mode 100644
index 00000000..e9d4b204
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.spec.ts
@@ -0,0 +1,184 @@
+import { AbstractControl, FormControl, FormGroup, NgForm } from '@angular/forms';
+
+import { CdFormGroup } from './cd-form-group';
+
+describe('CdFormGroup', () => {
+ let form: CdFormGroup;
+
+ const createTestForm = (controlName: string, value: any): FormGroup =>
+ new FormGroup({
+ [controlName]: new FormControl(value)
+ });
+
+ describe('test get and getValue in nested forms', () => {
+ let formA: FormGroup;
+ let formB: FormGroup;
+ let formC: FormGroup;
+
+ beforeEach(() => {
+ formA = createTestForm('a', 'a');
+ formB = createTestForm('b', 'b');
+ formC = createTestForm('c', 'c');
+ form = new CdFormGroup({
+ formA: formA,
+ formB: formB,
+ formC: formC
+ });
+ });
+
+ it('should find controls out of every form', () => {
+ expect(form.get('a')).toBe(formA.get('a'));
+ expect(form.get('b')).toBe(formB.get('b'));
+ expect(form.get('c')).toBe(formC.get('c'));
+ });
+
+ it('should throw an error if element could be found', () => {
+ expect(() => form.get('d')).toThrowError(`Control 'd' could not be found!`);
+ expect(() => form.get('sth')).toThrowError(`Control 'sth' could not be found!`);
+ });
+ });
+
+ describe('CdFormGroup tests', () => {
+ let x, nested, a, c;
+
+ beforeEach(() => {
+ a = new FormControl('a');
+ x = new CdFormGroup({
+ a: a
+ });
+ nested = new CdFormGroup({
+ lev1: new CdFormGroup({
+ lev2: new FormControl('lev2')
+ })
+ });
+ c = createTestForm('c', 'c');
+ form = new CdFormGroup({
+ nested: nested,
+ cdform: x,
+ b: new FormControl('b'),
+ formC: c
+ });
+ });
+
+ it('should return single value from "a" control in not nested form "x"', () => {
+ expect(x.get('a')).toBe(a);
+ expect(x.getValue('a')).toBe('a');
+ });
+
+ it('should return control "a" out of form "x" in nested form', () => {
+ expect(form.get('a')).toBe(a);
+ expect(form.getValue('a')).toBe('a');
+ });
+
+ it('should return value "b" that is not nested in nested form', () => {
+ expect(form.getValue('b')).toBe('b');
+ });
+
+ it('return value "c" out of normal form group "c" in nested form', () => {
+ expect(form.getValue('c')).toBe('c');
+ });
+
+ it('should return "lev2" value', () => {
+ expect(form.getValue('lev2')).toBe('lev2');
+ });
+
+ it('should nested throw an error if control could not be found', () => {
+ expect(() => form.get('d')).toThrowError(`Control 'd' could not be found!`);
+ expect(() => form.getValue('sth')).toThrowError(`Control 'sth' could not be found!`);
+ });
+ });
+
+ describe('test different values for getValue', () => {
+ beforeEach(() => {
+ form = new CdFormGroup({
+ form_undefined: createTestForm('undefined', undefined),
+ form_null: createTestForm('null', null),
+ form_emptyObject: createTestForm('emptyObject', {}),
+ form_filledObject: createTestForm('filledObject', { notEmpty: 1 }),
+ form_number0: createTestForm('number0', 0),
+ form_number1: createTestForm('number1', 1),
+ form_emptyString: createTestForm('emptyString', ''),
+ form_someString1: createTestForm('someString1', 's'),
+ form_someString2: createTestForm('someString2', 'sth'),
+ form_floating: createTestForm('floating', 0.1),
+ form_false: createTestForm('false', false),
+ form_true: createTestForm('true', true)
+ });
+ });
+
+ it('returns objects', () => {
+ expect(form.getValue('null')).toBe(null);
+ expect(form.getValue('emptyObject')).toEqual({});
+ expect(form.getValue('filledObject')).toEqual({ notEmpty: 1 });
+ });
+
+ it('returns set numbers', () => {
+ expect(form.getValue('number0')).toBe(0);
+ expect(form.getValue('number1')).toBe(1);
+ expect(form.getValue('floating')).toBe(0.1);
+ });
+
+ it('returns strings', () => {
+ expect(form.getValue('emptyString')).toBe('');
+ expect(form.getValue('someString1')).toBe('s');
+ expect(form.getValue('someString2')).toBe('sth');
+ });
+
+ it('returns booleans', () => {
+ expect(form.getValue('true')).toBe(true);
+ expect(form.getValue('false')).toBe(false);
+ });
+
+ it('returns null if control was set as undefined', () => {
+ expect(form.getValue('undefined')).toBe(null);
+ });
+
+ it('returns a falsy value for null, undefined, false and 0', () => {
+ expect(form.getValue('false')).toBeFalsy();
+ expect(form.getValue('null')).toBeFalsy();
+ expect(form.getValue('number0')).toBeFalsy();
+ });
+ });
+
+ describe('should test showError', () => {
+ let formDir: NgForm;
+ let test: AbstractControl;
+
+ beforeEach(() => {
+ formDir = new NgForm([], []);
+ form = new CdFormGroup({
+ test_form: createTestForm('test', '')
+ });
+ test = form.get('test');
+ test.setErrors({ someError: 'failed' });
+ });
+
+ it('should not show an error if not dirty and not submitted', () => {
+ expect(form.showError('test', formDir)).toBe(false);
+ });
+
+ it('should show an error if dirty', () => {
+ test.markAsDirty();
+ expect(form.showError('test', formDir)).toBe(true);
+ });
+
+ it('should show an error if submitted', () => {
+ expect(form.showError('test', <NgForm>{ submitted: true })).toBe(true);
+ });
+
+ it('should not show an error if no error exits', () => {
+ test.setErrors(null);
+ expect(form.showError('test', <NgForm>{ submitted: true })).toBe(false);
+ test.markAsDirty();
+ expect(form.showError('test', formDir)).toBe(false);
+ });
+
+ it('should not show error if the given error is not there', () => {
+ expect(form.showError('test', <NgForm>{ submitted: true }, 'someOtherError')).toBe(false);
+ });
+
+ it('should show error if the given error is there', () => {
+ expect(form.showError('test', <NgForm>{ submitted: true }, 'someError')).toBe(true);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.ts
new file mode 100644
index 00000000..9f2c1e63
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-form-group.ts
@@ -0,0 +1,75 @@
+import {
+ AbstractControl,
+ AbstractControlOptions,
+ AsyncValidatorFn,
+ FormGroup,
+ NgForm,
+ ValidatorFn
+} from '@angular/forms';
+
+/**
+ * CdFormGroup extends FormGroup with a few new methods that will help form development.
+ */
+export class CdFormGroup extends FormGroup {
+ constructor(
+ public controls: { [key: string]: AbstractControl },
+ validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
+ asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null
+ ) {
+ super(controls, validatorOrOpts, asyncValidator);
+ }
+
+ /**
+ * Get a control out of any control even if its nested in other CdFormGroups or a FormGroup
+ */
+ get(controlName: string): AbstractControl {
+ const control = this._get(controlName);
+ if (!control) {
+ throw new Error(`Control '${controlName}' could not be found!`);
+ }
+ return control;
+ }
+
+ _get(controlName): AbstractControl {
+ return (
+ super.get(controlName) ||
+ Object.values(this.controls)
+ .filter((c) => c.get)
+ .map((form) => {
+ if (form instanceof CdFormGroup) {
+ return form._get(controlName);
+ }
+ return form.get(controlName);
+ })
+ .find((c) => Boolean(c))
+ );
+ }
+
+ /**
+ * Get the value of a control
+ */
+ getValue(controlName: string): any {
+ return this.get(controlName).value;
+ }
+
+ /**
+ * Sets a control without triggering a value changes event
+ *
+ * Very useful if a function is called through a value changes event but the value
+ * should be changed within the call.
+ */
+ silentSet(controlName: string, value: any) {
+ this.get(controlName).setValue(value, { emitEvent: false });
+ }
+
+ /**
+ * Indicates errors of the control in templates
+ */
+ showError(controlName: string, form: NgForm, errorName?: string): boolean {
+ const control = this.get(controlName);
+ return (
+ (form.submitted || control.dirty) &&
+ (errorName ? control.hasError(errorName) : control.invalid)
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts
new file mode 100644
index 00000000..e2fe10e2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts
@@ -0,0 +1,478 @@
+import { fakeAsync, tick } from '@angular/core/testing';
+import { FormControl, Validators } from '@angular/forms';
+
+import { of as observableOf } from 'rxjs';
+
+import { FormHelper } from '../../../testing/unit-test-helper';
+import { CdFormGroup } from './cd-form-group';
+import { CdValidators } from './cd-validators';
+
+describe('CdValidators', () => {
+ let formHelper: FormHelper;
+ let form: CdFormGroup;
+
+ const expectValid = (value) => formHelper.expectValidChange('x', value);
+ const expectPatternError = (value) => formHelper.expectErrorChange('x', value, 'pattern');
+ const updateValidity = (controlName) => form.get(controlName).updateValueAndValidity();
+
+ beforeEach(() => {
+ form = new CdFormGroup({
+ x: new FormControl()
+ });
+ formHelper = new FormHelper(form);
+ });
+
+ describe('email', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.email);
+ });
+
+ it('should not error on an empty email address', () => {
+ expectValid('');
+ });
+
+ it('should not error on valid email address', () => {
+ expectValid('dashboard@ceph.com');
+ });
+
+ it('should error on invalid email address', () => {
+ formHelper.expectErrorChange('x', 'xyz', 'email');
+ });
+ });
+
+ describe('ip validator', () => {
+ describe('IPv4', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.ip(4));
+ });
+
+ it('should not error on empty addresses', () => {
+ expectValid('');
+ });
+
+ it('should accept valid address', () => {
+ expectValid('19.117.23.141');
+ });
+
+ it('should error containing whitespace', () => {
+ expectPatternError('155.144.133.122 ');
+ expectPatternError('155. 144.133 .122');
+ expectPatternError(' 155.144.133.122');
+ });
+
+ it('should error containing invalid char', () => {
+ expectPatternError('155.144.eee.122 ');
+ expectPatternError('155.1?.133 .1&2');
+ });
+
+ it('should error containing blocks higher than 255', () => {
+ expectPatternError('155.270.133.122');
+ expectPatternError('155.144.133.290');
+ });
+ });
+
+ describe('IPv4', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.ip(6));
+ });
+
+ it('should not error on empty IPv6 addresses', () => {
+ expectValid('');
+ });
+
+ it('should accept valid IPv6 address', () => {
+ expectValid('c4dc:1475:cb0b:24ed:3c80:468b:70cd:1a95');
+ });
+
+ it('should error on IPv6 address containing too many blocks', () => {
+ formHelper.expectErrorChange(
+ 'x',
+ 'c4dc:14753:cb0b:24ed:3c80:468b:70cd:1a95:a3f3',
+ 'pattern'
+ );
+ });
+
+ it('should error on IPv6 address containing more than 4 digits per block', () => {
+ expectPatternError('c4dc:14753:cb0b:24ed:3c80:468b:70cd:1a95');
+ });
+
+ it('should error on IPv6 address containing whitespace', () => {
+ expectPatternError('c4dc:14753:cb0b:24ed:3c80:468b:70cd:1a95 ');
+ expectPatternError('c4dc:14753 :cb0b:24ed:3c80 :468b:70cd :1a95');
+ expectPatternError(' c4dc:14753:cb0b:24ed:3c80:468b:70cd:1a95');
+ });
+
+ it('should error on IPv6 address containing invalid char', () => {
+ expectPatternError('c4dx:14753:cb0b:24ed:3c80:468b:70cd:1a95');
+ expectPatternError('c4da:14753:cb0b:24ed:3$80:468b:70cd:1a95');
+ });
+ });
+
+ it('should accept valid IPv4/6 addresses if not protocol version is given', () => {
+ const x = form.get('x');
+ x.setValidators(CdValidators.ip());
+ expectValid('19.117.23.141');
+ expectValid('c4dc:1475:cb0b:24ed:3c80:468b:70cd:1a95');
+ });
+ });
+
+ describe('uuid validator', () => {
+ const expectUuidError = (value) =>
+ formHelper.expectErrorChange('x', value, 'invalidUuid', true);
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.uuid());
+ });
+
+ it('should accept empty value', () => {
+ expectValid('');
+ });
+
+ it('should accept valid version 1 uuid', () => {
+ expectValid('171af0b2-c305-11e8-a355-529269fb1459');
+ });
+
+ it('should accept valid version 4 uuid', () => {
+ expectValid('e33bbcb6-fcc3-40b1-ae81-3f81706a35d5');
+ });
+
+ it('should error on uuid containing too many blocks', () => {
+ expectUuidError('e33bbcb6-fcc3-40b1-ae81-3f81706a35d5-23d3');
+ });
+
+ it('should error on uuid containing too many chars in block', () => {
+ expectUuidError('aae33bbcb6-fcc3-40b1-ae81-3f81706a35d5');
+ });
+
+ it('should error on uuid containing invalid char', () => {
+ expectUuidError('x33bbcb6-fcc3-40b1-ae81-3f81706a35d5');
+ expectUuidError('$33bbcb6-fcc3-40b1-ae81-3f81706a35d5');
+ });
+ });
+
+ describe('number validator', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.number());
+ });
+
+ it('should accept empty value', () => {
+ expectValid('');
+ });
+
+ it('should accept numbers', () => {
+ expectValid(42);
+ expectValid(-42);
+ expectValid('42');
+ });
+
+ it('should error on decimal numbers', () => {
+ expectPatternError(42.3);
+ expectPatternError(-42.3);
+ expectPatternError('42.3');
+ });
+
+ it('should error on chars', () => {
+ expectPatternError('char');
+ expectPatternError('42char');
+ });
+
+ it('should error on whitespaces', () => {
+ expectPatternError('42 ');
+ expectPatternError('4 2');
+ });
+ });
+
+ describe('number validator (without negative values)', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.number(false));
+ });
+
+ it('should accept positive numbers', () => {
+ expectValid(42);
+ expectValid('42');
+ });
+
+ it('should error on negative numbers', () => {
+ expectPatternError(-42);
+ expectPatternError('-42');
+ });
+ });
+
+ describe('decimal number validator', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.decimalNumber());
+ });
+
+ it('should accept empty value', () => {
+ expectValid('');
+ });
+
+ it('should accept numbers and decimal numbers', () => {
+ expectValid(42);
+ expectValid(-42);
+ expectValid(42.3);
+ expectValid(-42.3);
+ expectValid('42');
+ expectValid('42.3');
+ });
+
+ it('should error on chars', () => {
+ expectPatternError('42e');
+ expectPatternError('e42.3');
+ });
+
+ it('should error on whitespaces', () => {
+ expectPatternError('42.3 ');
+ expectPatternError('42 .3');
+ });
+ });
+
+ describe('decimal number validator (without negative values)', () => {
+ beforeEach(() => {
+ form.get('x').setValidators(CdValidators.decimalNumber(false));
+ });
+
+ it('should accept positive numbers and decimals', () => {
+ expectValid(42);
+ expectValid(42.3);
+ expectValid('42');
+ expectValid('42.3');
+ });
+
+ it('should error on negative numbers and decimals', () => {
+ expectPatternError(-42);
+ expectPatternError('-42');
+ expectPatternError(-42.3);
+ expectPatternError('-42.3');
+ });
+ });
+
+ describe('requiredIf', () => {
+ beforeEach(() => {
+ form = new CdFormGroup({
+ x: new FormControl(true),
+ y: new FormControl('abc'),
+ z: new FormControl('')
+ });
+ formHelper = new FormHelper(form);
+ });
+
+ it('should not error because all conditions are fulfilled', () => {
+ formHelper.setValue('z', 'zyx');
+ const validatorFn = CdValidators.requiredIf({
+ x: true,
+ y: 'abc'
+ });
+ expect(validatorFn(form.get('z'))).toBeNull();
+ });
+
+ it('should not error because of unmet prerequisites', () => {
+ // Define prereqs that do not match the current values of the form fields.
+ const validatorFn = CdValidators.requiredIf({
+ x: false,
+ y: 'xyz'
+ });
+ // The validator must succeed because the prereqs do not match, so the
+ // validation of the 'z' control will be skipped.
+ expect(validatorFn(form.get('z'))).toBeNull();
+ });
+
+ it('should error because of an empty value', () => {
+ // Define prereqs that force the validator to validate the value of
+ // the 'z' control.
+ const validatorFn = CdValidators.requiredIf({
+ x: true,
+ y: 'abc'
+ });
+ // The validator must fail because the value of control 'z' is empty.
+ expect(validatorFn(form.get('z'))).toEqual({ required: true });
+ });
+
+ it('should not error because of unsuccessful condition', () => {
+ formHelper.setValue('z', 'zyx');
+ // Define prereqs that force the validator to validate the value of
+ // the 'z' control.
+ const validatorFn = CdValidators.requiredIf(
+ {
+ x: true,
+ z: 'zyx'
+ },
+ () => false
+ );
+ expect(validatorFn(form.get('z'))).toBeNull();
+ });
+
+ it('should error because of successful condition', () => {
+ const conditionFn = (value) => {
+ return value === 'abc';
+ };
+ // Define prereqs that force the validator to validate the value of
+ // the 'y' control.
+ const validatorFn = CdValidators.requiredIf(
+ {
+ x: true,
+ z: ''
+ },
+ conditionFn
+ );
+ expect(validatorFn(form.get('y'))).toEqual({ required: true });
+ });
+ });
+
+ describe('custom validation', () => {
+ beforeEach(() => {
+ form = new CdFormGroup({
+ x: new FormControl(3, CdValidators.custom('odd', (x) => x % 2 === 1)),
+ y: new FormControl(
+ 5,
+ CdValidators.custom('not-dividable-by-x', (y) => {
+ const x = (form && form.get('x').value) || 1;
+ return y % x !== 0;
+ })
+ )
+ });
+ formHelper = new FormHelper(form);
+ });
+
+ it('should test error and valid condition for odd x', () => {
+ formHelper.expectError('x', 'odd');
+ expectValid(4);
+ });
+
+ it('should test error and valid condition for y if its dividable by x', () => {
+ updateValidity('y');
+ formHelper.expectError('y', 'not-dividable-by-x');
+ formHelper.expectValidChange('y', 6);
+ });
+ });
+
+ describe('validate if condition', () => {
+ beforeEach(() => {
+ form = new CdFormGroup({
+ x: new FormControl(3),
+ y: new FormControl(5)
+ });
+ CdValidators.validateIf(form.get('x'), () => ((form && form.get('y').value) || 0) > 10, [
+ CdValidators.custom('min', (x) => x < 7),
+ CdValidators.custom('max', (x) => x > 12)
+ ]);
+ formHelper = new FormHelper(form);
+ });
+
+ it('should test min error', () => {
+ formHelper.setValue('y', 11);
+ updateValidity('x');
+ formHelper.expectError('x', 'min');
+ });
+
+ it('should test max error', () => {
+ formHelper.setValue('y', 11);
+ formHelper.setValue('x', 13);
+ formHelper.expectError('x', 'max');
+ });
+
+ it('should test valid number with validation', () => {
+ formHelper.setValue('y', 11);
+ formHelper.setValue('x', 12);
+ formHelper.expectValid('x');
+ });
+
+ it('should validate automatically if dependency controls are defined', () => {
+ CdValidators.validateIf(
+ form.get('x'),
+ () => ((form && form.getValue('y')) || 0) > 10,
+ [Validators.min(7), Validators.max(12)],
+ undefined,
+ [form.get('y')]
+ );
+
+ formHelper.expectValid('x');
+ formHelper.setValue('y', 13);
+ formHelper.expectError('x', 'min');
+ });
+
+ it('should always validate the permanentValidators', () => {
+ CdValidators.validateIf(
+ form.get('x'),
+ () => ((form && form.getValue('y')) || 0) > 10,
+ [Validators.min(7), Validators.max(12)],
+ [Validators.required],
+ [form.get('y')]
+ );
+
+ formHelper.expectValid('x');
+ formHelper.setValue('x', '');
+ formHelper.expectError('x', 'required');
+ });
+ });
+
+ describe('match', () => {
+ let y: FormControl;
+
+ beforeEach(() => {
+ y = new FormControl('aaa');
+ form = new CdFormGroup({
+ x: new FormControl('aaa'),
+ y: y
+ });
+ formHelper = new FormHelper(form);
+ });
+
+ it('should error when values are different', () => {
+ formHelper.setValue('y', 'aab');
+ CdValidators.match('x', 'y')(form);
+ formHelper.expectValid('x');
+ formHelper.expectError('y', 'match');
+ });
+
+ it('should not error when values are equal', () => {
+ CdValidators.match('x', 'y')(form);
+ formHelper.expectValid('x');
+ formHelper.expectValid('y');
+ });
+
+ it('should unset error when values are equal', () => {
+ y.setErrors({ match: true });
+ CdValidators.match('x', 'y')(form);
+ formHelper.expectValid('x');
+ formHelper.expectValid('y');
+ });
+
+ it('should keep other existing errors', () => {
+ y.setErrors({ match: true, notUnique: true });
+ CdValidators.match('x', 'y')(form);
+ formHelper.expectValid('x');
+ formHelper.expectError('y', 'notUnique');
+ });
+ });
+
+ describe('unique', () => {
+ beforeEach(() => {
+ form = new CdFormGroup({
+ x: new FormControl(
+ '',
+ null,
+ CdValidators.unique((value) => {
+ return observableOf('xyz' === value);
+ })
+ )
+ });
+ formHelper = new FormHelper(form);
+ });
+
+ it('should not error because of empty input', () => {
+ expectValid('');
+ });
+
+ it('should not error because of not existing input', fakeAsync(() => {
+ formHelper.setValue('x', 'abc', true);
+ tick(500);
+ formHelper.expectValid('x');
+ }));
+
+ it('should error because of already existing input', fakeAsync(() => {
+ formHelper.setValue('x', 'xyz', true);
+ tick(500);
+ formHelper.expectError('x', 'notUnique');
+ }));
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts
new file mode 100644
index 00000000..dff17050
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts
@@ -0,0 +1,284 @@
+import {
+ AbstractControl,
+ AsyncValidatorFn,
+ ValidationErrors,
+ ValidatorFn,
+ Validators
+} from '@angular/forms';
+
+import * as _ from 'lodash';
+import { Observable, of as observableOf, timer as observableTimer } from 'rxjs';
+import { map, switchMapTo, take } from 'rxjs/operators';
+
+export function isEmptyInputValue(value: any): boolean {
+ return value == null || value.length === 0;
+}
+
+export type existsServiceFn = (value: any) => Observable<boolean>;
+
+export class CdValidators {
+ /**
+ * Validator that performs email validation. In contrast to the Angular
+ * email validator an empty email will not be handled as invalid.
+ */
+ static email(control: AbstractControl): ValidationErrors | null {
+ // Exit immediately if value is empty.
+ if (isEmptyInputValue(control.value)) {
+ return null;
+ }
+ return Validators.email(control);
+ }
+
+ /**
+ * Validator function in order to validate IP addresses.
+ * @param {number} version determines the protocol version. It needs to be set to 4 for IPv4 and
+ * to 6 for IPv6 validation. For any other number (it's also the default case) it will return a
+ * function to validate the input string against IPv4 OR IPv6.
+ * @returns {ValidatorFn} A validator function that returns an error map containing `pattern`
+ * if the validation failed, otherwise `null`.
+ */
+ static ip(version: number = 0): ValidatorFn {
+ // prettier-ignore
+ const ipv4Rgx =
+ /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
+ const ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
+
+ if (version === 4) {
+ return Validators.pattern(ipv4Rgx);
+ } else if (version === 6) {
+ return Validators.pattern(ipv6Rgx);
+ } else {
+ return Validators.pattern(new RegExp(ipv4Rgx.source + '|' + ipv6Rgx.source));
+ }
+ }
+
+ /**
+ * Validator function in order to validate numbers.
+ * @returns {ValidatorFn} A validator function that returns an error map containing `pattern`
+ * if the validation failed, otherwise `null`.
+ */
+ static number(allowsNegative: boolean = true): ValidatorFn {
+ if (allowsNegative) {
+ return Validators.pattern(/^-?[0-9]+$/i);
+ } else {
+ return Validators.pattern(/^[0-9]+$/i);
+ }
+ }
+
+ /**
+ * Validator function in order to validate decimal numbers.
+ * @returns {ValidatorFn} A validator function that returns an error map containing `pattern`
+ * if the validation failed, otherwise `null`.
+ */
+ static decimalNumber(allowsNegative: boolean = true): ValidatorFn {
+ if (allowsNegative) {
+ return Validators.pattern(/^-?[0-9]+(.[0-9]+)?$/i);
+ } else {
+ return Validators.pattern(/^[0-9]+(.[0-9]+)?$/i);
+ }
+ }
+
+ /**
+ * Validator that requires controls to fulfill the specified condition if
+ * the specified prerequisites matches. If the prerequisites are fulfilled,
+ * then the given function is executed and if it succeeds, the 'required'
+ * validation error will be returned, otherwise null.
+ * @param {Object} prerequisites An object containing the prerequisites.
+ * ### Example
+ * ```typescript
+ * {
+ * 'generate_key': true,
+ * 'username': 'Max Mustermann'
+ * }
+ * ```
+ * Only if all prerequisites are fulfilled, then the validation of the
+ * control will be triggered.
+ * @param {Function | undefined} condition The function to be executed when all
+ * prerequisites are fulfilled. If not set, then the {@link isEmptyInputValue}
+ * function will be used by default. The control's value is used as function
+ * argument. The function must return true to set the validation error.
+ * @return {ValidatorFn} Returns the validator function.
+ */
+ static requiredIf(prerequisites: Object, condition?: Function | undefined): ValidatorFn {
+ let isWatched = false;
+
+ return (control: AbstractControl): ValidationErrors | null => {
+ if (!isWatched && control.parent) {
+ Object.keys(prerequisites).forEach((key) => {
+ control.parent.get(key).valueChanges.subscribe(() => {
+ control.updateValueAndValidity({ emitEvent: false });
+ });
+ });
+
+ isWatched = true;
+ }
+
+ // Check if all prerequisites matches.
+ if (
+ !Object.keys(prerequisites).every((key) => {
+ return control.parent && control.parent.get(key).value === prerequisites[key];
+ })
+ ) {
+ return null;
+ }
+ const success = _.isFunction(condition)
+ ? condition.call(condition, control.value)
+ : isEmptyInputValue(control.value);
+ return success ? { required: true } : null;
+ };
+ }
+
+ /**
+ * Custom validation by passing a name for the error and a function as error condition.
+ *
+ * @param {string} error
+ * @param {Function} condition - a truthy return value will trigger the error
+ * @returns {ValidatorFn}
+ */
+ static custom(error: string, condition: Function): ValidatorFn {
+ return (control: AbstractControl): { [key: string]: any } => {
+ const value = condition.call(this, control.value);
+ if (value) {
+ return { [error]: value };
+ }
+ return null;
+ };
+ }
+
+ /**
+ * Validate form control if condition is true with validators.
+ *
+ * @param {AbstractControl} formControl
+ * @param {Function} condition
+ * @param {ValidatorFn[]} conditionalValidators List of validators that should only be tested
+ * when the condition is met
+ * @param {ValidatorFn[]} permanentValidators List of validators that should always be tested
+ * @param {AbstractControl[]} watchControls List of controls that the condition depend on.
+ * Every time one of this controls value is updated, the validation will be triggered
+ */
+ static validateIf(
+ formControl: AbstractControl,
+ condition: Function,
+ conditionalValidators: ValidatorFn[],
+ permanentValidators: ValidatorFn[] = [],
+ watchControls: AbstractControl[] = []
+ ) {
+ conditionalValidators = conditionalValidators.concat(permanentValidators);
+
+ formControl.setValidators(
+ (
+ control: AbstractControl
+ ): {
+ [key: string]: any;
+ } => {
+ const value = condition.call(this);
+ if (value) {
+ return Validators.compose(conditionalValidators)(control);
+ }
+ if (permanentValidators.length > 0) {
+ return Validators.compose(permanentValidators)(control);
+ }
+ return null;
+ }
+ );
+
+ watchControls.forEach((control: AbstractControl) => {
+ control.valueChanges.subscribe(() => {
+ formControl.updateValueAndValidity({ emitEvent: false });
+ });
+ });
+ }
+
+ /**
+ * Validator that requires that both specified controls have the same value.
+ * Error will be added to the `path2` control.
+ * @param {string} path1 A dot-delimited string that define the path to the control.
+ * @param {string} path2 A dot-delimited string that define the path to the control.
+ * @return {ValidatorFn} Returns a validator function that always returns `null`.
+ * If the validation fails an error map with the `match` property will be set
+ * on the `path2` control.
+ */
+ static match(path1: string, path2: string): ValidatorFn {
+ return (control: AbstractControl): { [key: string]: any } => {
+ const ctrl1 = control.get(path1);
+ const ctrl2 = control.get(path2);
+ if (ctrl1.value !== ctrl2.value) {
+ ctrl2.setErrors({ match: true });
+ } else {
+ const hasError = ctrl2.hasError('match');
+ if (hasError) {
+ // Remove the 'match' error. If no more errors exists, then set
+ // the error value to 'null', otherwise the field is still marked
+ // as invalid.
+ const errors = ctrl2.errors;
+ _.unset(errors, 'match');
+ ctrl2.setErrors(_.isEmpty(_.keys(errors)) ? null : errors);
+ }
+ }
+ return null;
+ };
+ }
+
+ /**
+ * Asynchronous validator that requires the control's value to be unique.
+ * The validation is only executed after the specified delay. Every
+ * keystroke during this delay will restart the timer.
+ * @param serviceFn {existsServiceFn} The service function that is
+ * called to check whether the given value exists. It must return
+ * boolean 'true' if the given value exists, otherwise 'false'.
+ * @param serviceFnThis {any} The object to be used as the 'this' object
+ * when calling the serviceFn function. Defaults to null.
+ * @param {number|Date} dueTime The delay time to wait before the
+ * serviceFn call is executed. This is useful to prevent calls on
+ * every keystroke. Defaults to 500.
+ * @return {AsyncValidatorFn} Returns an asynchronous validator function
+ * that returns an error map with the `notUnique` property if the
+ * validation check succeeds, otherwise `null`.
+ */
+ static unique(
+ serviceFn: existsServiceFn,
+ serviceFnThis: any = null,
+ dueTime = 500
+ ): AsyncValidatorFn {
+ return (control: AbstractControl): Observable<ValidationErrors | null> => {
+ // Exit immediately if user has not interacted with the control yet
+ // or the control value is empty.
+ if (control.pristine || isEmptyInputValue(control.value)) {
+ return observableOf(null);
+ }
+ // Forgot previous requests if a new one arrives within the specified
+ // delay time.
+ return observableTimer(dueTime).pipe(
+ switchMapTo(serviceFn.call(serviceFnThis, control.value)),
+ map((resp: boolean) => {
+ if (!resp) {
+ return null;
+ } else {
+ return { notUnique: true };
+ }
+ }),
+ take(1)
+ );
+ };
+ }
+
+ /**
+ * Validator function for UUIDs.
+ * @param required - Defines if it is mandatory to fill in the UUID
+ * @return Validator function that returns an error object containing `invalidUuid` if the
+ * validation failed, `null` otherwise.
+ */
+ static uuid(required = false): ValidatorFn {
+ const uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+ return (control: AbstractControl): { [key: string]: any } | null => {
+ if (control.pristine && control.untouched) {
+ return null;
+ } else if (!required && !control.value) {
+ return null;
+ } else if (uuidRe.test(control.value)) {
+ return null;
+ }
+ return { invalidUuid: 'This is not a valid UUID' };
+ };
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/alertmanager-silence.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/alertmanager-silence.ts
new file mode 100644
index 00000000..b7b88629
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/alertmanager-silence.ts
@@ -0,0 +1,23 @@
+export class AlertmanagerSilenceMatcher {
+ name: string;
+ value: any;
+ isRegex: boolean;
+}
+
+export class AlertmanagerSilenceMatcherMatch {
+ status: string;
+ cssClass: string;
+}
+
+export class AlertmanagerSilence {
+ id?: string;
+ matchers: AlertmanagerSilenceMatcher[];
+ startsAt: string; // DateStr
+ endsAt: string; // DateStr
+ updatedAt?: string; // DateStr
+ createdBy: string;
+ comment: string;
+ status?: {
+ state: 'expired' | 'active' | 'pending';
+ };
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts
new file mode 100644
index 00000000..10e79992
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts
@@ -0,0 +1,59 @@
+/*
+The MIT License
+
+Copyright (c) 2017 (null) McNull https://github.com/McNull
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+import { ActivatedRouteSnapshot, Resolve, UrlSegment } from '@angular/router';
+
+import { Observable, of } from 'rxjs';
+
+export class BreadcrumbsResolver implements Resolve<IBreadcrumb[]> {
+ public resolve(
+ route: ActivatedRouteSnapshot
+ ): Observable<IBreadcrumb[]> | Promise<IBreadcrumb[]> | IBreadcrumb[] {
+ const data = route.routeConfig.data;
+ const path = data.path === null ? null : this.getFullPath(route);
+
+ const text =
+ typeof data.breadcrumbs === 'string'
+ ? data.breadcrumbs
+ : data.breadcrumbs.text || data.text || path;
+
+ const crumbs: IBreadcrumb[] = [{ text: text, path: path }];
+
+ return of(crumbs);
+ }
+
+ public getFullPath(route: ActivatedRouteSnapshot): string {
+ const relativePath = (segments: UrlSegment[]) =>
+ segments.reduce((a, v) => (a += '/' + v.path), '');
+ const fullPath = (routes: ActivatedRouteSnapshot[]) =>
+ routes.reduce((a, v) => (a += relativePath(v.url)), '');
+
+ return fullPath(route.pathFromRoot);
+ }
+}
+
+export interface IBreadcrumb {
+ text: string;
+ path: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.spec.ts
new file mode 100644
index 00000000..e0f65b9a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.spec.ts
@@ -0,0 +1,95 @@
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotification, CdNotificationConfig } from './cd-notification';
+
+describe('cd-notification classes', () => {
+ const expectObject = (something: object, expected: object) => {
+ Object.keys(expected).forEach((key) => expect(something[key]).toBe(expected[key]));
+ };
+
+ // As these Models have a view methods they need to be tested
+ describe('CdNotificationConfig', () => {
+ it('should create a new config without any parameters', () => {
+ expectObject(new CdNotificationConfig(), {
+ application: 'Ceph',
+ applicationClass: 'ceph-icon',
+ message: undefined,
+ options: undefined,
+ title: undefined,
+ type: 1
+ });
+ });
+
+ it('should create a new config with parameters', () => {
+ expectObject(
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'Some Alert',
+ 'Something failed',
+ undefined,
+ 'Prometheus'
+ ),
+ {
+ application: 'Prometheus',
+ applicationClass: 'prometheus-icon',
+ message: 'Something failed',
+ options: undefined,
+ title: 'Some Alert',
+ type: 0
+ }
+ );
+ });
+ });
+
+ describe('CdNotification', () => {
+ beforeEach(() => {
+ const baseTime = new Date('2022-02-22');
+ spyOn(global, 'Date').and.returnValue(baseTime);
+ });
+
+ it('should create a new config without any parameters', () => {
+ expectObject(new CdNotification(), {
+ application: 'Ceph',
+ applicationClass: 'ceph-icon',
+ iconClass: 'fa-info',
+ message: undefined,
+ options: undefined,
+ textClass: 'text-info',
+ timestamp: '2022-02-22T00:00:00.000Z',
+ title: undefined,
+ type: 1
+ });
+ });
+
+ it('should create a new config with parameters', () => {
+ expectObject(
+ new CdNotification(
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'Some Alert',
+ 'Something failed',
+ undefined,
+ 'Prometheus'
+ )
+ ),
+ {
+ application: 'Prometheus',
+ applicationClass: 'prometheus-icon',
+ iconClass: 'fa-exclamation-triangle',
+ message: 'Something failed',
+ options: undefined,
+ textClass: 'text-danger',
+ timestamp: '2022-02-22T00:00:00.000Z',
+ title: 'Some Alert',
+ type: 0
+ }
+ );
+ });
+
+ it('should expect the right success classes', () => {
+ expectObject(new CdNotification(new CdNotificationConfig(NotificationType.success)), {
+ iconClass: 'fa-check',
+ textClass: 'text-success'
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts
new file mode 100644
index 00000000..1acbba1a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-notification.ts
@@ -0,0 +1,40 @@
+import { IndividualConfig } from 'ngx-toastr';
+import { NotificationType } from '../enum/notification-type.enum';
+
+export class CdNotificationConfig {
+ applicationClass: string;
+
+ private classes = {
+ Ceph: 'ceph-icon',
+ Prometheus: 'prometheus-icon'
+ };
+
+ constructor(
+ public type: NotificationType = NotificationType.info,
+ public title?: string,
+ public message?: string, // Use this for additional information only
+ public options?: any | IndividualConfig,
+ public application: string = 'Ceph'
+ ) {
+ this.applicationClass = this.classes[this.application];
+ }
+}
+
+export class CdNotification extends CdNotificationConfig {
+ timestamp: string;
+ textClass: string;
+ iconClass: string;
+
+ private textClasses = ['text-danger', 'text-info', 'text-success'];
+ private iconClasses = ['fa-exclamation-triangle', 'fa-info', 'fa-check'];
+
+ constructor(private config: CdNotificationConfig = new CdNotificationConfig()) {
+ super(config.type, config.title, config.message, config.options, config.application);
+ delete this.config;
+ /* string representation of the Date object so it can be directly compared
+ with the timestamps parsed from localStorage */
+ this.timestamp = new Date().toJSON();
+ this.iconClass = this.iconClasses[this.type];
+ this.textClass = this.textClasses[this.type];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts
new file mode 100644
index 00000000..ac8dcb61
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts
@@ -0,0 +1,46 @@
+import { CdTableSelection } from './cd-table-selection';
+
+export class CdTableAction {
+ // It's possible to assign a string
+ // or a function that returns the link if it has to be dynamic
+ // or none if it's not needed
+ routerLink?: string | Function;
+
+ preserveFragment? = false;
+
+ // This is the function that will be triggered on a click event if defined
+ click?: Function;
+
+ permission: 'create' | 'update' | 'delete' | 'read';
+
+ // The name of the action
+ name: string;
+
+ // The font awesome icon that will be used
+ icon: string;
+
+ // You can define the condition to disable the action.
+ // By default all 'update' and 'delete' actions will only be enabled
+ // if one selection is made and no task is running on the selected item.
+ disable?: (_: CdTableSelection) => boolean;
+
+ /**
+ * In some cases you might want to give the user a hint why a button is
+ * disabled. The specified message will be shown to the user as a button
+ * tooltip.
+ */
+ disableDesc?: Function;
+
+ /**
+ * Defines if the button can become 'primary' (displayed as button and not
+ * 'hidden' in the menu). Only one button can be primary at a time. By
+ * default all 'create' actions can be the action button if no or multiple
+ * items are selected. Also, all 'update' and 'delete' actions can be the
+ * action button by default, provided only one item is selected.
+ */
+ canBePrimary?: (_: CdTableSelection) => boolean;
+
+ // In some rare cases you want to hide a action that can be used by the user for example
+ // if one action can lock the item and another action unlocks it
+ visible?: (_: CdTableSelection) => boolean;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-column.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-column.ts
new file mode 100644
index 00000000..64cd7db4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-column.ts
@@ -0,0 +1,10 @@
+import { TableColumn, TableColumnProp } from '@swimlane/ngx-datatable';
+
+import { CellTemplate } from '../enum/cell-template.enum';
+
+export interface CdTableColumn extends TableColumn {
+ cellTransformation?: CellTemplate;
+ isHidden?: boolean;
+ prop: TableColumnProp; // Enforces properties to get sortable columns
+ customTemplateConfig?: any; // Custom configuration used by cell templates.
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-fetch-data-context.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-fetch-data-context.ts
new file mode 100644
index 00000000..b7c6e672
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-fetch-data-context.ts
@@ -0,0 +1,17 @@
+export class CdTableFetchDataContext {
+ errorConfig = {
+ resetData: true, // Force data table to show no data
+ displayError: true // Show an error panel above the data table
+ };
+
+ /**
+ * The function that should be called from within the error handler
+ * of the 'fetchData' function to display the error panel and to
+ * reset the data table to the correct state.
+ */
+ error: Function;
+
+ constructor(error: () => void) {
+ this.error = error;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-selection.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-selection.ts
new file mode 100644
index 00000000..9732abc5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-selection.ts
@@ -0,0 +1,28 @@
+export class CdTableSelection {
+ selected: any[] = [];
+ hasMultiSelection: boolean;
+ hasSingleSelection: boolean;
+ hasSelection: boolean;
+
+ constructor() {
+ this.update();
+ }
+
+ /**
+ * Recalculate the variables based on the current number
+ * of selected rows.
+ */
+ update() {
+ this.hasSelection = this.selected.length > 0;
+ this.hasSingleSelection = this.selected.length === 1;
+ this.hasMultiSelection = this.selected.length > 1;
+ }
+
+ /**
+ * Get the first selected row.
+ * @return {any | null}
+ */
+ first() {
+ return this.hasSelection ? this.selected[0] : null;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-user-config.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-user-config.ts
new file mode 100644
index 00000000..2e1a9e19
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-user-config.ts
@@ -0,0 +1,9 @@
+import { SortPropDir } from '@swimlane/ngx-datatable';
+
+import { CdTableColumn } from './cd-table-column';
+
+export interface CdUserConfig {
+ limit?: number;
+ sorts?: SortPropDir[];
+ columns?: CdTableColumn[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/chart-tooltip.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/chart-tooltip.ts
new file mode 100644
index 00000000..9b6552dd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/chart-tooltip.ts
@@ -0,0 +1,115 @@
+import { ElementRef } from '@angular/core';
+
+export class ChartTooltip {
+ tooltipEl: any;
+ chartEl: any;
+ getStyleLeft: Function;
+ getStyleTop: Function;
+ customColors = {
+ backgroundColor: undefined,
+ borderColor: undefined
+ };
+ checkOffset = false;
+
+ /**
+ * Creates an instance of ChartTooltip.
+ * @param {ElementRef} chartCanvas Canvas Element
+ * @param {ElementRef} chartTooltip Tooltip Element
+ * @param {Function} getStyleLeft Function that calculates the value of Left
+ * @param {Function} getStyleTop Function that calculates the value of Top
+ * @memberof ChartTooltip
+ */
+ constructor(
+ chartCanvas: ElementRef,
+ chartTooltip: ElementRef,
+ getStyleLeft: Function,
+ getStyleTop: Function
+ ) {
+ this.chartEl = chartCanvas.nativeElement;
+ this.getStyleLeft = getStyleLeft;
+ this.getStyleTop = getStyleTop;
+ this.tooltipEl = chartTooltip.nativeElement;
+ }
+
+ /**
+ * Implementation of a ChartJS custom tooltip function.
+ *
+ * @param {any} tooltip
+ * @memberof ChartTooltip
+ */
+ customTooltips(tooltip) {
+ // Hide if no tooltip
+ if (tooltip.opacity === 0) {
+ this.tooltipEl.style.opacity = 0;
+ return;
+ }
+
+ // Set caret Position
+ this.tooltipEl.classList.remove('above', 'below', 'no-transform');
+ if (tooltip.yAlign) {
+ this.tooltipEl.classList.add(tooltip.yAlign);
+ } else {
+ this.tooltipEl.classList.add('no-transform');
+ }
+
+ // Set Text
+ if (tooltip.body) {
+ const titleLines = tooltip.title || [];
+ const bodyLines = tooltip.body.map((bodyItem) => {
+ return bodyItem.lines;
+ });
+
+ let innerHtml = '<thead>';
+
+ titleLines.forEach((title) => {
+ innerHtml += '<tr><th>' + this.getTitle(title) + '</th></tr>';
+ });
+ innerHtml += '</thead><tbody>';
+
+ bodyLines.forEach((body, i) => {
+ const colors = tooltip.labelColors[i];
+ let style = 'background:' + (this.customColors.backgroundColor || colors.backgroundColor);
+ style += '; border-color:' + (this.customColors.borderColor || colors.borderColor);
+ style += '; border-width: 2px';
+ const span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';
+ innerHtml += '<tr><td nowrap>' + span + this.getBody(body) + '</td></tr>';
+ });
+ innerHtml += '</tbody>';
+
+ const tableRoot = this.tooltipEl.querySelector('table');
+ tableRoot.innerHTML = innerHtml;
+ }
+
+ const positionY = this.chartEl.offsetTop;
+ const positionX = this.chartEl.offsetLeft;
+
+ // Display, position, and set styles for font
+ if (this.checkOffset) {
+ const halfWidth = tooltip.width / 2;
+ this.tooltipEl.classList.remove('transform-left');
+ this.tooltipEl.classList.remove('transform-right');
+ if (tooltip.caretX - halfWidth < 0) {
+ this.tooltipEl.classList.add('transform-left');
+ } else if (tooltip.caretX + halfWidth > this.chartEl.width) {
+ this.tooltipEl.classList.add('transform-right');
+ }
+ }
+
+ this.tooltipEl.style.left = this.getStyleLeft(tooltip, positionX);
+ this.tooltipEl.style.top = this.getStyleTop(tooltip, positionY);
+
+ this.tooltipEl.style.opacity = 1;
+ this.tooltipEl.style.fontFamily = tooltip._fontFamily;
+ this.tooltipEl.style.fontSize = tooltip.fontSize;
+ this.tooltipEl.style.fontStyle = tooltip._fontStyle;
+ this.tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
+ }
+
+ getBody(body) {
+ return body;
+ }
+
+ getTitle(title) {
+ return title;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/configuration.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/configuration.ts
new file mode 100644
index 00000000..0a8e403d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/configuration.ts
@@ -0,0 +1,43 @@
+export enum RbdConfigurationSourceField {
+ global = 0,
+ pool = 1,
+ image = 2
+}
+
+export enum RbdConfigurationType {
+ bps,
+ iops,
+ milliseconds
+}
+
+/**
+ * This configuration can also be set on a pool level.
+ */
+export interface RbdConfigurationEntry {
+ name: string;
+ source: RbdConfigurationSourceField;
+ value: any;
+ type?: RbdConfigurationType; // Non-external field.
+ description?: string; // Non-external field.
+ displayName?: string; // Non-external field. Nice name for the UI which is added in the UI.
+}
+
+/**
+ * This object contains additional information injected into the elements retrieved by the service.
+ */
+export interface RbdConfigurationExtraField {
+ name: string;
+ displayName: string;
+ description: string;
+ type: RbdConfigurationType;
+ readOnly?: boolean;
+}
+
+/**
+ * Represents a set of data to be used for editing or creating configuration options
+ */
+export interface RbdConfigurationSection {
+ heading: string;
+ class: string;
+ options: RbdConfigurationExtraField[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/credentials.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/credentials.ts
new file mode 100644
index 00000000..2c2b7d76
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/credentials.ts
@@ -0,0 +1,4 @@
+export class Credentials {
+ username: string;
+ password: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-rule.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-rule.ts
new file mode 100644
index 00000000..ef050850
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-rule.ts
@@ -0,0 +1,10 @@
+import { CrushStep } from './crush-step';
+
+export class CrushRule {
+ max_size: number;
+ min_size: number;
+ rule_id: number;
+ rule_name: string;
+ ruleset: number;
+ steps: CrushStep[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-step.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-step.ts
new file mode 100644
index 00000000..3c46a7cd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/crush-step.ts
@@ -0,0 +1,7 @@
+export class CrushStep {
+ op: string;
+ item_name?: string;
+ item?: number;
+ type?: string;
+ num?: number;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/erasure-code-profile.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/erasure-code-profile.ts
new file mode 100644
index 00000000..17f48acd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/erasure-code-profile.ts
@@ -0,0 +1,15 @@
+export class ErasureCodeProfile {
+ name: string;
+ plugin: string;
+ k?: number;
+ m?: number;
+ c?: number;
+ l?: number;
+ packetsize?: number;
+ technique?: string;
+ 'crush-root'?: string;
+ 'crush-locality'?: string;
+ 'crush-failure-domain'?: string;
+ 'crush-device-class'?: string;
+ 'directory'?: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/executing-task.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/executing-task.ts
new file mode 100644
index 00000000..27dc5968
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/executing-task.ts
@@ -0,0 +1,6 @@
+import { Task } from './task';
+
+export class ExecutingTask extends Task {
+ begin_time: number;
+ progress: number;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/finished-task.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/finished-task.ts
new file mode 100644
index 00000000..3749fafa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/finished-task.ts
@@ -0,0 +1,14 @@
+import { Task } from './task';
+import { TaskException } from './task-exception';
+
+export class FinishedTask extends Task {
+ begin_time: number;
+ end_time: number;
+ exception: TaskException;
+ latency: number;
+ progress: number;
+ ret_value: any;
+ success: boolean;
+
+ errorMessage: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/login-response.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/login-response.ts
new file mode 100644
index 00000000..15d3197c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/login-response.ts
@@ -0,0 +1,4 @@
+export class LoginResponse {
+ username: string;
+ permissions: object;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts
new file mode 100644
index 00000000..fb2c9046
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permission.spec.ts
@@ -0,0 +1,62 @@
+import { Permissions } from './permissions';
+
+describe('cd-notification classes', () => {
+ it('should show empty permissions', () => {
+ expect(new Permissions({})).toEqual({
+ cephfs: { create: false, delete: false, read: false, update: false },
+ configOpt: { create: false, delete: false, read: false, update: false },
+ grafana: { create: false, delete: false, read: false, update: false },
+ hosts: { create: false, delete: false, read: false, update: false },
+ iscsi: { create: false, delete: false, read: false, update: false },
+ log: { create: false, delete: false, read: false, update: false },
+ manager: { create: false, delete: false, read: false, update: false },
+ monitor: { create: false, delete: false, read: false, update: false },
+ nfs: { create: false, delete: false, read: false, update: false },
+ osd: { create: false, delete: false, read: false, update: false },
+ pool: { create: false, delete: false, read: false, update: false },
+ prometheus: { create: false, delete: false, read: false, update: false },
+ rbdImage: { create: false, delete: false, read: false, update: false },
+ rbdMirroring: { create: false, delete: false, read: false, update: false },
+ rgw: { create: false, delete: false, read: false, update: false },
+ user: { create: false, delete: false, read: false, update: false }
+ });
+ });
+
+ it('should show full permissions', () => {
+ const fullyGranted = {
+ cephfs: ['create', 'read', 'update', 'delete'],
+ 'config-opt': ['create', 'read', 'update', 'delete'],
+ grafana: ['create', 'read', 'update', 'delete'],
+ hosts: ['create', 'read', 'update', 'delete'],
+ iscsi: ['create', 'read', 'update', 'delete'],
+ log: ['create', 'read', 'update', 'delete'],
+ manager: ['create', 'read', 'update', 'delete'],
+ monitor: ['create', 'read', 'update', 'delete'],
+ osd: ['create', 'read', 'update', 'delete'],
+ pool: ['create', 'read', 'update', 'delete'],
+ prometheus: ['create', 'read', 'update', 'delete'],
+ 'rbd-image': ['create', 'read', 'update', 'delete'],
+ 'rbd-mirroring': ['create', 'read', 'update', 'delete'],
+ rgw: ['create', 'read', 'update', 'delete'],
+ user: ['create', 'read', 'update', 'delete']
+ };
+ expect(new Permissions(fullyGranted)).toEqual({
+ cephfs: { create: true, delete: true, read: true, update: true },
+ configOpt: { create: true, delete: true, read: true, update: true },
+ grafana: { create: true, delete: true, read: true, update: true },
+ hosts: { create: true, delete: true, read: true, update: true },
+ iscsi: { create: true, delete: true, read: true, update: true },
+ log: { create: true, delete: true, read: true, update: true },
+ manager: { create: true, delete: true, read: true, update: true },
+ monitor: { create: true, delete: true, read: true, update: true },
+ nfs: { create: false, delete: false, read: false, update: false },
+ osd: { create: true, delete: true, read: true, update: true },
+ pool: { create: true, delete: true, read: true, update: true },
+ prometheus: { create: true, delete: true, read: true, update: true },
+ rbdImage: { create: true, delete: true, read: true, update: true },
+ rbdMirroring: { create: true, delete: true, read: true, update: true },
+ rgw: { create: true, delete: true, read: true, update: true },
+ user: { create: true, delete: true, read: true, update: true }
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts
new file mode 100644
index 00000000..3f2c87ed
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/permissions.ts
@@ -0,0 +1,50 @@
+export class Permission {
+ read: boolean;
+ create: boolean;
+ update: boolean;
+ delete: boolean;
+
+ constructor(serverPermission: Array<string> = []) {
+ ['read', 'create', 'update', 'delete'].forEach(
+ (permission) => (this[permission] = serverPermission.includes(permission))
+ );
+ }
+}
+
+export class Permissions {
+ hosts: Permission;
+ configOpt: Permission;
+ pool: Permission;
+ osd: Permission;
+ monitor: Permission;
+ rbdImage: Permission;
+ iscsi: Permission;
+ rbdMirroring: Permission;
+ rgw: Permission;
+ cephfs: Permission;
+ manager: Permission;
+ log: Permission;
+ user: Permission;
+ grafana: Permission;
+ prometheus: Permission;
+ nfs: Permission;
+
+ constructor(serverPermissions: any) {
+ this.hosts = new Permission(serverPermissions['hosts']);
+ this.configOpt = new Permission(serverPermissions['config-opt']);
+ this.pool = new Permission(serverPermissions['pool']);
+ this.osd = new Permission(serverPermissions['osd']);
+ this.monitor = new Permission(serverPermissions['monitor']);
+ this.rbdImage = new Permission(serverPermissions['rbd-image']);
+ this.iscsi = new Permission(serverPermissions['iscsi']);
+ this.rbdMirroring = new Permission(serverPermissions['rbd-mirroring']);
+ this.rgw = new Permission(serverPermissions['rgw']);
+ this.cephfs = new Permission(serverPermissions['cephfs']);
+ this.manager = new Permission(serverPermissions['manager']);
+ this.log = new Permission(serverPermissions['log']);
+ this.user = new Permission(serverPermissions['user']);
+ this.grafana = new Permission(serverPermissions['grafana']);
+ this.prometheus = new Permission(serverPermissions['prometheus']);
+ this.nfs = new Permission(serverPermissions['nfs-ganesha']);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/pool-form-info.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/pool-form-info.ts
new file mode 100644
index 00000000..4f5b653d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/pool-form-info.ts
@@ -0,0 +1,14 @@
+import { CrushRule } from './crush-rule';
+
+export class PoolFormInfo {
+ pool_names: string[];
+ osd_count: number;
+ is_all_bluestore: boolean;
+ bluestore_compression_algorithm: string;
+ compression_algorithms: string[];
+ compression_modes: string[];
+ crush_rules_replicated: CrushRule[];
+ crush_rules_erasure: CrushRule[];
+ pg_autoscale_default_mode: string;
+ pg_autoscale_modes: string[];
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/prometheus-alerts.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/prometheus-alerts.ts
new file mode 100644
index 00000000..f5e8f850
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/prometheus-alerts.ts
@@ -0,0 +1,85 @@
+export class PrometheusAlertLabels {
+ alertname: string;
+ instance: string;
+ job: string;
+ severity: string;
+}
+
+class Annotations {
+ description: string;
+ summary: string;
+}
+
+class CommonAlertmanagerAlert {
+ labels: PrometheusAlertLabels;
+ annotations: Annotations;
+ startsAt: string; // Date string
+ endsAt: string; // Date string
+ generatorURL: string;
+}
+
+class PrometheusAlert {
+ labels: PrometheusAlertLabels;
+ annotations: Annotations;
+ state: 'pending' | 'firing';
+ activeAt: string; // Date string
+ value: number;
+}
+
+export interface PrometheusRuleGroup {
+ name: string;
+ file: string;
+ rules: PrometheusRule[];
+}
+
+export class PrometheusRule {
+ name: string; // => PrometheusAlertLabels.alertname
+ query: string;
+ duration: 10;
+ labels: {
+ severity: string; // => PrometheusAlertLabels.severity
+ };
+ annotations: Annotations;
+ alerts: PrometheusAlert[]; // Shows only active alerts
+ health: string;
+ type: string;
+ group?: string; // Added field for flattened list
+}
+
+export class AlertmanagerAlert extends CommonAlertmanagerAlert {
+ status: {
+ state: 'unprocessed' | 'active' | 'suppressed';
+ silencedBy: null | string[];
+ inhibitedBy: null | string[];
+ };
+ receivers: string[];
+ fingerprint: string;
+}
+
+export class AlertmanagerNotificationAlert extends CommonAlertmanagerAlert {
+ status: 'firing' | 'resolved';
+}
+
+export class AlertmanagerNotification {
+ status: 'firing' | 'resolved';
+ groupLabels: object;
+ commonAnnotations: object;
+ groupKey: string;
+ notified: string;
+ id: string;
+ alerts: AlertmanagerNotificationAlert[];
+ version: string;
+ receiver: string;
+ externalURL: string;
+ commonLabels: {
+ severity: string;
+ };
+}
+
+export class PrometheusCustomAlert {
+ status: 'resolved' | 'unprocessed' | 'active' | 'suppressed';
+ name: string;
+ url: string;
+ summary: string;
+ fingerprint?: string | boolean;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task-exception.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task-exception.ts
new file mode 100644
index 00000000..ba38e4aa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task-exception.ts
@@ -0,0 +1,9 @@
+import { Task } from './task';
+
+export class TaskException {
+ status: number;
+ code: number;
+ component: string;
+ detail: string;
+ task: Task;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task.ts
new file mode 100644
index 00000000..fab76717
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/task.ts
@@ -0,0 +1,10 @@
+export class Task {
+ constructor(name?, metadata?) {
+ this.name = name;
+ this.metadata = metadata;
+ }
+ name: string;
+ metadata: object;
+
+ description: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.spec.ts
new file mode 100644
index 00000000..a5d4667a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.spec.ts
@@ -0,0 +1,47 @@
+import { TestBed } from '@angular/core/testing';
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { BooleanTextPipe } from './boolean-text.pipe';
+
+describe('BooleanTextPipe', () => {
+ let pipe: BooleanTextPipe;
+
+ configureTestBed({
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ const i18n = TestBed.get(I18n);
+ pipe = new BooleanTextPipe(i18n);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms true', () => {
+ expect(pipe.transform(true)).toEqual('Yes');
+ });
+
+ it('transforms true, alternative text', () => {
+ expect(pipe.transform(true, 'foo')).toEqual('foo');
+ });
+
+ it('transforms 1', () => {
+ expect(pipe.transform(1)).toEqual('Yes');
+ });
+
+ it('transforms false', () => {
+ expect(pipe.transform(false)).toEqual('No');
+ });
+
+ it('transforms false, alternative text', () => {
+ expect(pipe.transform(false, 'foo', 'bar')).toEqual('bar');
+ });
+
+ it('transforms 0', () => {
+ expect(pipe.transform(0)).toEqual('No');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.ts
new file mode 100644
index 00000000..dba4e8bc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/boolean-text.pipe.ts
@@ -0,0 +1,18 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+@Pipe({
+ name: 'booleanText'
+})
+export class BooleanTextPipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+
+ transform(
+ value: any,
+ truthyText: string = this.i18n('Yes'),
+ falsyText: string = this.i18n('No')
+ ): string {
+ return Boolean(value) ? truthyText : falsyText;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.spec.ts
new file mode 100644
index 00000000..08212b26
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.spec.ts
@@ -0,0 +1,24 @@
+import { DatePipe } from '@angular/common';
+
+import * as moment from 'moment';
+
+import { CdDatePipe } from './cd-date.pipe';
+
+describe('CdDatePipe', () => {
+ const datePipe = new DatePipe('en-US');
+ let pipe = new CdDatePipe(datePipe);
+
+ it('create an instance', () => {
+ pipe = new CdDatePipe(datePipe);
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms without value', () => {
+ expect(pipe.transform('')).toBe('');
+ });
+
+ it('transforms with some date', () => {
+ const result = moment(1527085564486).format('M/D/YY LTS');
+ expect(pipe.transform(1527085564486)).toBe(result);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.ts
new file mode 100644
index 00000000..911f3204
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/cd-date.pipe.ts
@@ -0,0 +1,20 @@
+import { DatePipe } from '@angular/common';
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'cdDate'
+})
+export class CdDatePipe implements PipeTransform {
+ constructor(private datePipe: DatePipe) {}
+
+ transform(value: any): any {
+ if (value === null || value === '') {
+ return '';
+ }
+ return (
+ this.datePipe.transform(value, 'shortDate') +
+ ' ' +
+ this.datePipe.transform(value, 'mediumTime')
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.spec.ts
new file mode 100644
index 00000000..7b7c5e05
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.spec.ts
@@ -0,0 +1,28 @@
+import { CephReleaseNamePipe } from './ceph-release-name.pipe';
+
+describe('CephReleaseNamePipe', () => {
+ const pipe = new CephReleaseNamePipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('recognizes a stable release', () => {
+ const value =
+ 'ceph version 13.2.1 \
+ (5533ecdc0fda920179d7ad84e0aa65a127b20d77) mimic (stable)';
+ expect(pipe.transform(value)).toBe('mimic');
+ });
+
+ it('recognizes a development release as the master branch', () => {
+ const value =
+ 'ceph version 13.1.0-534-g23d3751b89 \
+ (23d3751b897b31d2bda57aeaf01acb5ff3c4a9cd) nautilus (dev)';
+ expect(pipe.transform(value)).toBe('master');
+ });
+
+ it('transforms with wrong version format', () => {
+ const value = 'foo';
+ expect(pipe.transform(value)).toBe('foo');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.ts
new file mode 100644
index 00000000..c7c1e1d7
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-release-name.pipe.ts
@@ -0,0 +1,24 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'cephReleaseName'
+})
+export class CephReleaseNamePipe implements PipeTransform {
+ transform(value: any): any {
+ // Expect "ceph version 13.1.0-419-g251e2515b5
+ // (251e2515b563856349498c6caf34e7a282f62937) nautilus (dev)"
+ const result = /ceph version\s+[^ ]+\s+\(.+\)\s+(.+)\s+\((.+)\)/.exec(value);
+ if (result) {
+ if (result[2] === 'dev') {
+ // Assume this is actually master
+ return 'master';
+ } else {
+ // Return the "nautilus" part
+ return result[1];
+ }
+ } else {
+ // Unexpected format, pass it through
+ return value;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts
new file mode 100644
index 00000000..0242839d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts
@@ -0,0 +1,21 @@
+import { CephShortVersionPipe } from './ceph-short-version.pipe';
+
+describe('CephShortVersionPipe', () => {
+ const pipe = new CephShortVersionPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms with correct version format', () => {
+ const value =
+ 'ceph version 13.1.0-534-g23d3751b89 \
+ (23d3751b897b31d2bda57aeaf01acb5ff3c4a9cd) nautilus (dev)';
+ expect(pipe.transform(value)).toBe('13.1.0-534-g23d3751b89');
+ });
+
+ it('transforms with wrong version format', () => {
+ const value = 'foo';
+ expect(pipe.transform(value)).toBe('foo');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts
new file mode 100644
index 00000000..03e75dfb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts
@@ -0,0 +1,18 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'cephShortVersion'
+})
+export class CephShortVersionPipe implements PipeTransform {
+ transform(value: any): any {
+ // Expect "ceph version 1.2.3-g9asdasd (as98d7a0s8d7)"
+ const result = /ceph version\s+([^ ]+)\s+\(.+\)/.exec(value);
+ if (result) {
+ // Return the "1.2.3-g9asdasd" part
+ return result[1];
+ } else {
+ // Unexpected format, pass it through
+ return value;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts
new file mode 100644
index 00000000..67faad2b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts
@@ -0,0 +1,23 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { FormatterService } from '../services/formatter.service';
+
+@Pipe({
+ name: 'dimlessBinaryPerSecond'
+})
+export class DimlessBinaryPerSecondPipe implements PipeTransform {
+ constructor(private formatter: FormatterService) {}
+
+ transform(value: any): any {
+ return this.formatter.format_number(value, 1024, [
+ 'B/s',
+ 'kB/s',
+ 'MB/s',
+ 'GB/s',
+ 'TB/s',
+ 'PB/s',
+ 'EB/s',
+ 'ZB/s',
+ 'YB/s'
+ ]);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.spec.ts
new file mode 100644
index 00000000..caf51f57
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.spec.ts
@@ -0,0 +1,56 @@
+import { FormatterService } from '../services/formatter.service';
+import { DimlessBinaryPipe } from './dimless-binary.pipe';
+
+describe('DimlessBinaryPipe', () => {
+ const formatterService = new FormatterService();
+ const pipe = new DimlessBinaryPipe(formatterService);
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms 1024^0', () => {
+ const value = Math.pow(1024, 0);
+ expect(pipe.transform(value)).toBe('1 B');
+ });
+
+ it('transforms 1024^1', () => {
+ const value = Math.pow(1024, 1);
+ expect(pipe.transform(value)).toBe('1 KiB');
+ });
+
+ it('transforms 1024^2', () => {
+ const value = Math.pow(1024, 2);
+ expect(pipe.transform(value)).toBe('1 MiB');
+ });
+
+ it('transforms 1024^3', () => {
+ const value = Math.pow(1024, 3);
+ expect(pipe.transform(value)).toBe('1 GiB');
+ });
+
+ it('transforms 1024^4', () => {
+ const value = Math.pow(1024, 4);
+ expect(pipe.transform(value)).toBe('1 TiB');
+ });
+
+ it('transforms 1024^5', () => {
+ const value = Math.pow(1024, 5);
+ expect(pipe.transform(value)).toBe('1 PiB');
+ });
+
+ it('transforms 1024^6', () => {
+ const value = Math.pow(1024, 6);
+ expect(pipe.transform(value)).toBe('1 EiB');
+ });
+
+ it('transforms 1024^7', () => {
+ const value = Math.pow(1024, 7);
+ expect(pipe.transform(value)).toBe('1 ZiB');
+ });
+
+ it('transforms 1024^8', () => {
+ const value = Math.pow(1024, 8);
+ expect(pipe.transform(value)).toBe('1 YiB');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts
new file mode 100644
index 00000000..493696ef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts
@@ -0,0 +1,23 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { FormatterService } from '../services/formatter.service';
+
+@Pipe({
+ name: 'dimlessBinary'
+})
+export class DimlessBinaryPipe implements PipeTransform {
+ constructor(private formatter: FormatterService) {}
+
+ transform(value: any): any {
+ return this.formatter.format_number(value, 1024, [
+ 'B',
+ 'KiB',
+ 'MiB',
+ 'GiB',
+ 'TiB',
+ 'PiB',
+ 'EiB',
+ 'ZiB',
+ 'YiB'
+ ]);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.spec.ts
new file mode 100644
index 00000000..8d01678f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.spec.ts
@@ -0,0 +1,56 @@
+import { FormatterService } from '../services/formatter.service';
+import { DimlessPipe } from './dimless.pipe';
+
+describe('DimlessPipe', () => {
+ const formatterService = new FormatterService();
+ const pipe = new DimlessPipe(formatterService);
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms 1000^0', () => {
+ const value = Math.pow(1000, 0);
+ expect(pipe.transform(value)).toBe('1');
+ });
+
+ it('transforms 1000^1', () => {
+ const value = Math.pow(1000, 1);
+ expect(pipe.transform(value)).toBe('1 k');
+ });
+
+ it('transforms 1000^2', () => {
+ const value = Math.pow(1000, 2);
+ expect(pipe.transform(value)).toBe('1 M');
+ });
+
+ it('transforms 1000^3', () => {
+ const value = Math.pow(1000, 3);
+ expect(pipe.transform(value)).toBe('1 G');
+ });
+
+ it('transforms 1000^4', () => {
+ const value = Math.pow(1000, 4);
+ expect(pipe.transform(value)).toBe('1 T');
+ });
+
+ it('transforms 1000^5', () => {
+ const value = Math.pow(1000, 5);
+ expect(pipe.transform(value)).toBe('1 P');
+ });
+
+ it('transforms 1000^6', () => {
+ const value = Math.pow(1000, 6);
+ expect(pipe.transform(value)).toBe('1 E');
+ });
+
+ it('transforms 1000^7', () => {
+ const value = Math.pow(1000, 7);
+ expect(pipe.transform(value)).toBe('1 Z');
+ });
+
+ it('transforms 1000^8', () => {
+ const value = Math.pow(1000, 8);
+ expect(pipe.transform(value)).toBe('1 Y');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts
new file mode 100644
index 00000000..18994bd1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts
@@ -0,0 +1,13 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { FormatterService } from '../services/formatter.service';
+
+@Pipe({
+ name: 'dimless'
+})
+export class DimlessPipe implements PipeTransform {
+ constructor(private formatter: FormatterService) {}
+
+ transform(value: any): any {
+ return this.formatter.format_number(value, 1000, ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts
new file mode 100644
index 00000000..7241812e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts
@@ -0,0 +1,24 @@
+import * as moment from 'moment';
+
+import { DurationPipe } from './duration.pipe';
+
+describe('DurationPipe', () => {
+ const pipe = new DurationPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms seconds into a human readable duration', () => {
+ expect(pipe.transform(0)).toBe('1 second');
+ expect(pipe.transform(6)).toBe('6 seconds');
+ expect(pipe.transform(60)).toBe('1 minute');
+ expect(pipe.transform(600)).toBe('10 minutes');
+ expect(pipe.transform(6000)).toBe('1 hour 40 minutes');
+ });
+
+ it('transforms date into a human readable relative duration', () => {
+ const date = moment().subtract(130, 'seconds');
+ expect(pipe.transform(date, true)).toBe('2 minutes ago');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts
new file mode 100644
index 00000000..c2b874ac
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts
@@ -0,0 +1,47 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as moment from 'moment';
+
+@Pipe({
+ name: 'duration',
+ pure: false
+})
+export class DurationPipe implements PipeTransform {
+ transform(date: any, isRelative = false): string {
+ if (isRelative) {
+ return moment(date).fromNow();
+ } else {
+ return this._forHumans(date);
+ }
+ }
+
+ /**
+ * Translates seconds into human readable format of seconds, minutes, hours, days, and years
+ * source: https://stackoverflow.com/a/34270811
+ *
+ * @param {number} seconds The number of seconds to be processed
+ * @return {string} The phrase describing the the amount of time
+ */
+ _forHumans(seconds: number): string {
+ const levels = [
+ [`${Math.floor(seconds / 31536000)}`, 'years'],
+ [`${Math.floor((seconds % 31536000) / 86400)}`, 'days'],
+ [`${Math.floor((seconds % 86400) / 3600)}`, 'hours'],
+ [`${Math.floor((seconds % 3600) / 60)}`, 'minutes'],
+ [`${Math.floor(seconds % 60)}`, 'seconds']
+ ];
+ let returntext = '';
+
+ for (let i = 0, max = levels.length; i < max; i++) {
+ if (levels[i][0] === '0') {
+ continue;
+ }
+ returntext +=
+ ' ' +
+ levels[i][0] +
+ ' ' +
+ (levels[i][0] === '1' ? levels[i][1].substr(0, levels[i][1].length - 1) : levels[i][1]);
+ }
+ return returntext.trim() || '1 second';
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.spec.ts
new file mode 100644
index 00000000..46290790
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.spec.ts
@@ -0,0 +1,19 @@
+import { EmptyPipe } from './empty.pipe';
+
+describe('EmptyPipe', () => {
+ const pipe = new EmptyPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms with empty value', () => {
+ const value = undefined;
+ expect(pipe.transform(value)).toBe('-');
+ });
+
+ it('transforms with some value', () => {
+ const value = 'foo';
+ expect(pipe.transform(value)).toBe('foo');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.ts
new file mode 100644
index 00000000..7ee51b63
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/empty.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'empty'
+})
+export class EmptyPipe implements PipeTransform {
+ transform(value: any): any {
+ return _.isUndefined(value) || _.isNull(value) ? '-' : value;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.spec.ts
new file mode 100644
index 00000000..a4367409
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.spec.ts
@@ -0,0 +1,13 @@
+import { EncodeUriPipe } from './encode-uri.pipe';
+
+describe('EncodeUriPipe', () => {
+ it('create an instance', () => {
+ const pipe = new EncodeUriPipe();
+ expect(pipe).toBeTruthy();
+ });
+
+ it('should transforms the value', () => {
+ const pipe = new EncodeUriPipe();
+ expect(pipe.transform('rbd/name')).toBe('rbd%2Fname');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.ts
new file mode 100644
index 00000000..48fbf166
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/encode-uri.pipe.ts
@@ -0,0 +1,10 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'encodeUri'
+})
+export class EncodeUriPipe implements PipeTransform {
+ transform(value: any): any {
+ return encodeURIComponent(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.spec.ts
new file mode 100644
index 00000000..94e5f8bd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.spec.ts
@@ -0,0 +1,54 @@
+import { FilterPipe } from './filter.pipe';
+
+describe('FilterPipe', () => {
+ const pipe = new FilterPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('filter words with "foo"', () => {
+ const value = ['foo', 'bar', 'foobar'];
+ const filters = [
+ {
+ value: 'foo',
+ applyFilter: (row, val) => {
+ return row.indexOf(val) !== -1;
+ }
+ }
+ ];
+ expect(pipe.transform(value, filters)).toEqual(['foo', 'foobar']);
+ });
+
+ it('filter words with "foo" and "bar"', () => {
+ const value = ['foo', 'bar', 'foobar'];
+ const filters = [
+ {
+ value: 'foo',
+ applyFilter: (row, val) => {
+ return row.indexOf(val) !== -1;
+ }
+ },
+ {
+ value: 'bar',
+ applyFilter: (row, val) => {
+ return row.indexOf(val) !== -1;
+ }
+ }
+ ];
+ expect(pipe.transform(value, filters)).toEqual(['foobar']);
+ });
+
+ it('filter with no value', () => {
+ const value = ['foo', 'bar', 'foobar'];
+ const filters = [
+ {
+ value: '',
+ applyFilter: () => {
+ return false;
+ }
+ }
+ ];
+ expect(pipe.transform(value, filters)).toEqual(['foo', 'bar', 'foobar']);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.ts
new file mode 100644
index 00000000..7425183f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/filter.pipe.ts
@@ -0,0 +1,25 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'filter'
+})
+export class FilterPipe implements PipeTransform {
+ transform(value: any, args?: any): any {
+ return value.filter((row) => {
+ let result = true;
+
+ args.forEach((filter) => {
+ if (!filter.value) {
+ return;
+ }
+
+ result = result && filter.applyFilter(row, filter.value);
+ if (!result) {
+ return result;
+ }
+ });
+
+ return result;
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.spec.ts
new file mode 100644
index 00000000..2293dd9a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.spec.ts
@@ -0,0 +1,25 @@
+import { HealthColorPipe } from './health-color.pipe';
+
+describe('HealthColorPipe', () => {
+ const pipe = new HealthColorPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "HEALTH_OK"', () => {
+ expect(pipe.transform('HEALTH_OK')).toEqual({ color: '#00bb00' });
+ });
+
+ it('transforms "HEALTH_WARN"', () => {
+ expect(pipe.transform('HEALTH_WARN')).toEqual({ color: '#ffa500' });
+ });
+
+ it('transforms "HEALTH_ERR"', () => {
+ expect(pipe.transform('HEALTH_ERR')).toEqual({ color: '#ff0000' });
+ });
+
+ it('transforms others', () => {
+ expect(pipe.transform('abc')).toBe(null);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.ts
new file mode 100644
index 00000000..4b950226
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/health-color.pipe.ts
@@ -0,0 +1,18 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'healthColor'
+})
+export class HealthColorPipe implements PipeTransform {
+ transform(value: any): any {
+ if (value === 'HEALTH_OK') {
+ return { color: '#00bb00' };
+ } else if (value === 'HEALTH_WARN') {
+ return { color: '#ffa500' };
+ } else if (value === 'HEALTH_ERR') {
+ return { color: '#ff0000' };
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.spec.ts
new file mode 100644
index 00000000..dac353dd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { IopsPipe } from './iops.pipe';
+
+describe('IopsPipe', () => {
+ it('create an instance', () => {
+ const pipe = new IopsPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.ts
new file mode 100644
index 00000000..9644801f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iops.pipe.ts
@@ -0,0 +1,10 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'iops'
+})
+export class IopsPipe implements PipeTransform {
+ transform(value: any): any {
+ return `${value} IOPS`;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.spec.ts
new file mode 100644
index 00000000..c82e3755
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.spec.ts
@@ -0,0 +1,17 @@
+import { IscsiBackstorePipe } from './iscsi-backstore.pipe';
+
+describe('IscsiBackstorePipe', () => {
+ const pipe = new IscsiBackstorePipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "user:rbd"', () => {
+ expect(pipe.transform('user:rbd')).toBe('user:rbd (tcmu-runner)');
+ });
+
+ it('transforms "other"', () => {
+ expect(pipe.transform('other')).toBe('other');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.ts
new file mode 100644
index 00000000..ae347b6f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/iscsi-backstore.pipe.ts
@@ -0,0 +1,17 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'iscsiBackstore'
+})
+export class IscsiBackstorePipe implements PipeTransform {
+ constructor() {}
+
+ transform(value: any): any {
+ switch (value) {
+ case 'user:rbd':
+ return 'user:rbd (tcmu-runner)';
+ default:
+ return value;
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.spec.ts
new file mode 100644
index 00000000..d26fd65e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.spec.ts
@@ -0,0 +1,13 @@
+import { ListPipe } from './list.pipe';
+
+describe('ListPipe', () => {
+ const pipe = new ListPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "[1,2,3]"', () => {
+ expect(pipe.transform([1, 2, 3])).toBe('1, 2, 3');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.ts
new file mode 100644
index 00000000..9a044c1b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/list.pipe.ts
@@ -0,0 +1,10 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'list'
+})
+export class ListPipe implements PipeTransform {
+ transform(value: any): any {
+ return value.join(', ');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.spec.ts
new file mode 100644
index 00000000..45d677c2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.spec.ts
@@ -0,0 +1,32 @@
+import { LogPriorityPipe } from './log-priority.pipe';
+
+describe('LogPriorityPipe', () => {
+ const pipe = new LogPriorityPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "INF"', () => {
+ const value = '[INF]';
+ const result = 'info';
+ expect(pipe.transform(value)).toEqual(result);
+ });
+
+ it('transforms "WRN"', () => {
+ const value = '[WRN]';
+ const result = 'warn';
+ expect(pipe.transform(value)).toEqual(result);
+ });
+
+ it('transforms "ERR"', () => {
+ const value = '[ERR]';
+ const result = 'err';
+ expect(pipe.transform(value)).toEqual(result);
+ });
+
+ it('transforms others', () => {
+ const value = '[foo]';
+ expect(pipe.transform(value)).toBe('');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.ts
new file mode 100644
index 00000000..c7f5e50b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/log-priority.pipe.ts
@@ -0,0 +1,18 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'logPriority'
+})
+export class LogPriorityPipe implements PipeTransform {
+ transform(value: any): any {
+ if (value === '[INF]') {
+ return 'info';
+ } else if (value === '[WRN]') {
+ return 'warn';
+ } else if (value === '[ERR]') {
+ return 'err';
+ } else {
+ return ''; // Inherit
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.spec.ts
new file mode 100644
index 00000000..337d5c37
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.spec.ts
@@ -0,0 +1,25 @@
+import { MapPipe } from './map.pipe';
+
+describe('MapPipe', () => {
+ const pipe = new MapPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('map value [1]', () => {
+ expect(pipe.transform('foo')).toBe('foo');
+ });
+
+ it('map value [2]', () => {
+ expect(pipe.transform('foo', { '-1': 'disabled', 0: 'unlimited' })).toBe('foo');
+ });
+
+ it('map value [3]', () => {
+ expect(pipe.transform(-1, { '-1': 'disabled', 0: 'unlimited' })).toBe('disabled');
+ });
+
+ it('map value [4]', () => {
+ expect(pipe.transform(0, { '-1': 'disabled', 0: 'unlimited' })).toBe('unlimited');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.ts
new file mode 100644
index 00000000..9242bb4e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/map.pipe.ts
@@ -0,0 +1,15 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'map'
+})
+export class MapPipe implements PipeTransform {
+ transform(value: string | number, map?: object): any {
+ if (!_.isPlainObject(map)) {
+ return value;
+ }
+ return _.get(map, value, value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.spec.ts
new file mode 100644
index 00000000..cea4bb13
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { MillisecondsPipe } from './milliseconds.pipe';
+
+describe('MillisecondsPipe', () => {
+ it('create an instance', () => {
+ const pipe = new MillisecondsPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.ts
new file mode 100644
index 00000000..b0dc6860
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/milliseconds.pipe.ts
@@ -0,0 +1,10 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'milliseconds'
+})
+export class MillisecondsPipe implements PipeTransform {
+ transform(value: any): any {
+ return `${value} ms`;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.spec.ts
new file mode 100644
index 00000000..14a6fd06
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.spec.ts
@@ -0,0 +1,32 @@
+import { TestBed } from '@angular/core/testing';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { NotAvailablePipe } from './not-available.pipe';
+
+describe('NotAvailablePipe', () => {
+ let pipe: NotAvailablePipe;
+
+ configureTestBed({
+ providers: [i18nProviders]
+ });
+
+ beforeEach(() => {
+ const i18n = TestBed.get(I18n);
+ pipe = new NotAvailablePipe(i18n);
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms not available', () => {
+ expect(pipe.transform('')).toBe('n/a');
+ });
+
+ it('transforms number', () => {
+ expect(pipe.transform(0)).toBe(0);
+ expect(pipe.transform(1)).toBe(1);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.ts
new file mode 100644
index 00000000..75cb8a5c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/not-available.pipe.ts
@@ -0,0 +1,16 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+@Pipe({
+ name: 'notAvailable'
+})
+export class NotAvailablePipe implements PipeTransform {
+ constructor(private i18n: I18n) {}
+ transform(value: any): any {
+ if (value === '') {
+ return this.i18n('n/a');
+ }
+ return value;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.spec.ts
new file mode 100644
index 00000000..7e1cdbc8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { OrdinalPipe } from './ordinal.pipe';
+
+describe('OrdinalPipe', () => {
+ it('create an instance', () => {
+ const pipe = new OrdinalPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.ts
new file mode 100644
index 00000000..da89a024
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/ordinal.pipe.ts
@@ -0,0 +1,25 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'ordinal'
+})
+export class OrdinalPipe implements PipeTransform {
+ transform(value: any): any {
+ const num = parseInt(value, 10);
+ if (isNaN(num)) {
+ return value;
+ }
+ return (
+ value +
+ (Math.floor(num / 10) === 1
+ ? 'th'
+ : num % 10 === 1
+ ? 'st'
+ : num % 10 === 2
+ ? 'nd'
+ : num % 10 === 3
+ ? 'rd'
+ : 'th')
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts
new file mode 100644
index 00000000..2076cc80
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts
@@ -0,0 +1,106 @@
+import { CommonModule, DatePipe } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { BooleanTextPipe } from './boolean-text.pipe';
+import { CdDatePipe } from './cd-date.pipe';
+import { CephReleaseNamePipe } from './ceph-release-name.pipe';
+import { CephShortVersionPipe } from './ceph-short-version.pipe';
+import { DimlessBinaryPerSecondPipe } from './dimless-binary-per-second.pipe';
+import { DimlessBinaryPipe } from './dimless-binary.pipe';
+import { DimlessPipe } from './dimless.pipe';
+import { DurationPipe } from './duration.pipe';
+import { EmptyPipe } from './empty.pipe';
+import { EncodeUriPipe } from './encode-uri.pipe';
+import { FilterPipe } from './filter.pipe';
+import { HealthColorPipe } from './health-color.pipe';
+import { IopsPipe } from './iops.pipe';
+import { IscsiBackstorePipe } from './iscsi-backstore.pipe';
+import { ListPipe } from './list.pipe';
+import { LogPriorityPipe } from './log-priority.pipe';
+import { MapPipe } from './map.pipe';
+import { MillisecondsPipe } from './milliseconds.pipe';
+import { NotAvailablePipe } from './not-available.pipe';
+import { OrdinalPipe } from './ordinal.pipe';
+import { RbdConfigurationSourcePipe } from './rbd-configuration-source.pipe';
+import { RelativeDatePipe } from './relative-date.pipe';
+import { RoundPipe } from './round.pipe';
+import { UpperFirstPipe } from './upper-first.pipe';
+
+@NgModule({
+ imports: [CommonModule],
+ declarations: [
+ BooleanTextPipe,
+ DimlessBinaryPipe,
+ DimlessBinaryPerSecondPipe,
+ HealthColorPipe,
+ DimlessPipe,
+ CephShortVersionPipe,
+ CephReleaseNamePipe,
+ RelativeDatePipe,
+ IscsiBackstorePipe,
+ ListPipe,
+ LogPriorityPipe,
+ FilterPipe,
+ CdDatePipe,
+ EmptyPipe,
+ EncodeUriPipe,
+ RoundPipe,
+ OrdinalPipe,
+ MillisecondsPipe,
+ NotAvailablePipe,
+ IopsPipe,
+ UpperFirstPipe,
+ RbdConfigurationSourcePipe,
+ DurationPipe,
+ MapPipe
+ ],
+ exports: [
+ BooleanTextPipe,
+ DimlessBinaryPipe,
+ DimlessBinaryPerSecondPipe,
+ HealthColorPipe,
+ DimlessPipe,
+ CephShortVersionPipe,
+ CephReleaseNamePipe,
+ RelativeDatePipe,
+ IscsiBackstorePipe,
+ ListPipe,
+ LogPriorityPipe,
+ FilterPipe,
+ CdDatePipe,
+ EmptyPipe,
+ EncodeUriPipe,
+ RoundPipe,
+ OrdinalPipe,
+ MillisecondsPipe,
+ NotAvailablePipe,
+ IopsPipe,
+ UpperFirstPipe,
+ RbdConfigurationSourcePipe,
+ DurationPipe,
+ MapPipe
+ ],
+ providers: [
+ BooleanTextPipe,
+ DatePipe,
+ CephShortVersionPipe,
+ CephReleaseNamePipe,
+ DimlessBinaryPipe,
+ DimlessBinaryPerSecondPipe,
+ DimlessPipe,
+ RelativeDatePipe,
+ IscsiBackstorePipe,
+ ListPipe,
+ LogPriorityPipe,
+ CdDatePipe,
+ EmptyPipe,
+ EncodeUriPipe,
+ OrdinalPipe,
+ IopsPipe,
+ MillisecondsPipe,
+ NotAvailablePipe,
+ UpperFirstPipe,
+ MapPipe
+ ]
+})
+export class PipesModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.spec.ts
new file mode 100644
index 00000000..9c0346bd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.spec.ts
@@ -0,0 +1,22 @@
+import { RbdConfigurationSourcePipe } from './rbd-configuration-source.pipe';
+
+describe('RbdConfigurationSourcePipePipe', () => {
+ let pipe: RbdConfigurationSourcePipe;
+
+ beforeEach(() => {
+ pipe = new RbdConfigurationSourcePipe();
+ });
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('should transform correctly', () => {
+ expect(pipe.transform('foo')).not.toBeDefined();
+ expect(pipe.transform(-1)).not.toBeDefined();
+ expect(pipe.transform(0)).toBe('global');
+ expect(pipe.transform(1)).toBe('pool');
+ expect(pipe.transform(2)).toBe('image');
+ expect(pipe.transform(-3)).not.toBeDefined();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.ts
new file mode 100644
index 00000000..bb42d3f1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/rbd-configuration-source.pipe.ts
@@ -0,0 +1,15 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'rbdConfigurationSource'
+})
+export class RbdConfigurationSourcePipe implements PipeTransform {
+ transform(value: any): any {
+ const sourceMap = {
+ 0: 'global',
+ 1: 'pool',
+ 2: 'image'
+ };
+ return sourceMap[value];
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.spec.ts
new file mode 100644
index 00000000..a05657dd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.spec.ts
@@ -0,0 +1,30 @@
+import * as moment from 'moment';
+
+import { RelativeDatePipe } from './relative-date.pipe';
+
+describe('RelativeDatePipe', () => {
+ const pipe = new RelativeDatePipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms without value', () => {
+ const value = undefined;
+ expect(pipe.transform(value)).toBe('unknown');
+ });
+
+ it('transforms "in 7 days"', () => {
+ const value = moment()
+ .add(7, 'days')
+ .unix();
+ expect(pipe.transform(value)).toBe('in 7 days');
+ });
+
+ it('transforms "7 days ago"', () => {
+ const value = moment()
+ .subtract(7, 'days')
+ .unix();
+ expect(pipe.transform(value)).toBe('7 days ago');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.ts
new file mode 100644
index 00000000..3ebc389e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/relative-date.pipe.ts
@@ -0,0 +1,17 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as moment from 'moment';
+
+@Pipe({
+ name: 'relativeDate'
+})
+export class RelativeDatePipe implements PipeTransform {
+ constructor() {}
+
+ transform(value: any): any {
+ if (!value) {
+ return 'unknown';
+ }
+ return moment(value * 1000).fromNow();
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.spec.ts
new file mode 100644
index 00000000..60204526
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.spec.ts
@@ -0,0 +1,13 @@
+import { RoundPipe } from './round.pipe';
+
+describe('RoundPipe', () => {
+ const pipe = new RoundPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "1500"', () => {
+ expect(pipe.transform(1.52, 1)).toEqual(1.5);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.ts
new file mode 100644
index 00000000..1365ddef
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/round.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'round'
+})
+export class RoundPipe implements PipeTransform {
+ transform(value: any, precision: number): any {
+ return _.round(value, precision);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.spec.ts
new file mode 100644
index 00000000..072baa04
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.spec.ts
@@ -0,0 +1,17 @@
+import { UpperFirstPipe } from './upper-first.pipe';
+
+describe('UpperFirstPipe', () => {
+ const pipe = new UpperFirstPipe();
+
+ it('create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('transforms "foo"', () => {
+ expect(pipe.transform('foo')).toEqual('Foo');
+ });
+
+ it('transforms "BAR"', () => {
+ expect(pipe.transform('BAR')).toEqual('BAR');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.ts
new file mode 100644
index 00000000..11d7fc97
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/upper-first.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Pipe({
+ name: 'upperFirst'
+})
+export class UpperFirstPipe implements PipeTransform {
+ transform(value: string): string {
+ return _.upperFirst(value);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.spec.ts
new file mode 100644
index 00000000..744f2137
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.spec.ts
@@ -0,0 +1,217 @@
+import { HttpClient, HttpErrorResponse } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { Router } from '@angular/router';
+
+import { ToastrService } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { AppModule } from '../../app.module';
+import { CdNotification, CdNotificationConfig } from '../models/cd-notification';
+import { ApiInterceptorService } from './api-interceptor.service';
+import { NotificationService } from './notification.service';
+
+describe('ApiInterceptorService', () => {
+ let notificationService: NotificationService;
+ let httpTesting: HttpTestingController;
+ let httpClient: HttpClient;
+ let router: Router;
+ const url = 'api/xyz';
+
+ const httpError = (error, errorOpts, done = (_resp) => {}) => {
+ httpClient.get(url).subscribe(
+ () => {},
+ (resp) => {
+ // Error must have been forwarded by the interceptor.
+ expect(resp instanceof HttpErrorResponse).toBeTruthy();
+ done(resp);
+ }
+ );
+ httpTesting.expectOne(url).error(error, errorOpts);
+ };
+
+ const runRouterTest = (errorOpts, expectedCallParams) => {
+ httpError(new ErrorEvent('abc'), errorOpts);
+ httpTesting.verify();
+ expect(router.navigate).toHaveBeenCalledWith(...expectedCallParams);
+ };
+
+ const runNotificationTest = (error, errorOpts, expectedCallParams) => {
+ httpError(error, errorOpts);
+ httpTesting.verify();
+ expect(notificationService.show).toHaveBeenCalled();
+ expect(notificationService.save).toHaveBeenCalledWith(expectedCallParams);
+ };
+
+ const createCdNotification = (type, title?, message?, options?, application?) => {
+ return new CdNotification(new CdNotificationConfig(type, title, message, options, application));
+ };
+
+ configureTestBed({
+ imports: [AppModule, HttpClientTestingModule],
+ providers: [
+ NotificationService,
+ i18nProviders,
+ {
+ provide: ToastrService,
+ useValue: {
+ error: () => true
+ }
+ }
+ ]
+ });
+
+ beforeEach(() => {
+ const baseTime = new Date('2022-02-22');
+ spyOn(global, 'Date').and.returnValue(baseTime);
+
+ httpClient = TestBed.get(HttpClient);
+ httpTesting = TestBed.get(HttpTestingController);
+
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.callThrough();
+ spyOn(notificationService, 'save');
+
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate');
+ });
+
+ it('should be created', () => {
+ const service = TestBed.get(ApiInterceptorService);
+ expect(service).toBeTruthy();
+ });
+
+ describe('test different error behaviours', () => {
+ beforeEach(() => {
+ spyOn(window, 'setTimeout').and.callFake((fn) => fn());
+ });
+
+ it('should redirect 401', () => {
+ runRouterTest(
+ {
+ status: 401
+ },
+ [['/login']]
+ );
+ });
+
+ it('should redirect 403', () => {
+ runRouterTest(
+ {
+ status: 403
+ },
+ [['/403']]
+ );
+ });
+
+ it('should show notification (error string)', () => {
+ runNotificationTest(
+ 'foobar',
+ {
+ status: 500,
+ statusText: 'Foo Bar'
+ },
+ createCdNotification(0, '500 - Foo Bar', 'foobar')
+ );
+ });
+
+ it('should show notification (error object, triggered from backend)', () => {
+ runNotificationTest(
+ { detail: 'abc' },
+ {
+ status: 504,
+ statusText: 'AAA bbb CCC'
+ },
+ createCdNotification(0, '504 - AAA bbb CCC', 'abc')
+ );
+ });
+
+ it('should show notification (error object with unknown keys)', () => {
+ runNotificationTest(
+ { type: 'error' },
+ {
+ status: 0,
+ statusText: 'Unknown Error',
+ message: 'Http failure response for (unknown url): 0 Unknown Error',
+ name: 'HttpErrorResponse',
+ ok: false,
+ url: null
+ },
+ createCdNotification(
+ 0,
+ '0 - Unknown Error',
+ 'Http failure response for api/xyz: 0 Unknown Error'
+ )
+ );
+ });
+
+ it('should show notification (undefined error)', () => {
+ runNotificationTest(
+ undefined,
+ {
+ status: 502
+ },
+ createCdNotification(0, '502 - Unknown Error', 'Http failure response for api/xyz: 502 ')
+ );
+ });
+
+ it('should show 400 notification', () => {
+ spyOn(notificationService, 'notifyTask');
+ httpError({ task: { name: 'mytask', metadata: { component: 'foobar' } } }, { status: 400 });
+ httpTesting.verify();
+ expect(notificationService.show).toHaveBeenCalledTimes(0);
+ expect(notificationService.notifyTask).toHaveBeenCalledWith({
+ exception: { task: { metadata: { component: 'foobar' }, name: 'mytask' } },
+ metadata: { component: 'foobar' },
+ name: 'mytask',
+ success: false
+ });
+ });
+ });
+
+ describe('interceptor error handling', () => {
+ const expectSaveToHaveBeenCalled = (called) => {
+ tick(510);
+ if (called) {
+ expect(notificationService.save).toHaveBeenCalled();
+ } else {
+ expect(notificationService.save).not.toHaveBeenCalled();
+ }
+ };
+
+ it('should show default behaviour', fakeAsync(() => {
+ httpError(undefined, { status: 500 });
+ expectSaveToHaveBeenCalled(true);
+ }));
+
+ it('should prevent the default behaviour with preventDefault', fakeAsync(() => {
+ httpError(undefined, { status: 500 }, (resp) => resp.preventDefault());
+ expectSaveToHaveBeenCalled(false);
+ }));
+
+ it('should be able to use preventDefault with 400 errors', fakeAsync(() => {
+ httpError(
+ { task: { name: 'someName', metadata: { component: 'someComponent' } } },
+ { status: 400 },
+ (resp) => resp.preventDefault()
+ );
+ expectSaveToHaveBeenCalled(false);
+ }));
+
+ it('should prevent the default behaviour by status code', fakeAsync(() => {
+ httpError(undefined, { status: 500 }, (resp) => resp.ignoreStatusCode(500));
+ expectSaveToHaveBeenCalled(false);
+ }));
+
+ it('should use different application icon (default Ceph) in error message', fakeAsync(() => {
+ const msg = 'Cannot connect to Alertmanager';
+ httpError(undefined, { status: 500 }, (resp) => {
+ (resp.application = 'Prometheus'), (resp.message = msg);
+ });
+ expectSaveToHaveBeenCalled(true);
+ expect(notificationService.save).toHaveBeenCalledWith(
+ createCdNotification(0, '500 - Unknown Error', msg, undefined, 'Prometheus')
+ );
+ }));
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts
new file mode 100644
index 00000000..374f8637
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts
@@ -0,0 +1,109 @@
+import {
+ HttpErrorResponse,
+ HttpEvent,
+ HttpHandler,
+ HttpInterceptor,
+ HttpRequest
+} from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Router } from '@angular/router';
+
+import * as _ from 'lodash';
+import { Observable, throwError as observableThrowError } from 'rxjs';
+import { catchError } from 'rxjs/operators';
+
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { FinishedTask } from '../models/finished-task';
+import { AuthStorageService } from './auth-storage.service';
+import { NotificationService } from './notification.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ApiInterceptorService implements HttpInterceptor {
+ constructor(
+ private router: Router,
+ private authStorageService: AuthStorageService,
+ public notificationService: NotificationService
+ ) {}
+
+ intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
+ return next.handle(request).pipe(
+ catchError((resp) => {
+ if (resp instanceof HttpErrorResponse) {
+ let timeoutId: number;
+ switch (resp.status) {
+ case 400:
+ const finishedTask = new FinishedTask();
+
+ const task = resp.error.task;
+ if (_.isPlainObject(task)) {
+ task.metadata.component = task.metadata.component || resp.error.component;
+
+ finishedTask.name = task.name;
+ finishedTask.metadata = task.metadata;
+ } else {
+ finishedTask.metadata = resp.error;
+ }
+
+ finishedTask.success = false;
+ finishedTask.exception = resp.error;
+ timeoutId = this.notificationService.notifyTask(finishedTask);
+ break;
+ case 401:
+ this.authStorageService.remove();
+ this.router.navigate(['/login']);
+ break;
+ case 403:
+ this.router.navigate(['/403']);
+ break;
+ default:
+ timeoutId = this.prepareNotification(resp);
+ }
+
+ /**
+ * Decorated preventDefault method (in case error previously had
+ * preventDefault method defined). If called, it will prevent a
+ * notification to be shown.
+ */
+ resp['preventDefault'] = () => {
+ this.notificationService.cancel(timeoutId);
+ };
+
+ /**
+ * If called, it will prevent a notification for the specific status code.
+ * @param {number} status The status code to be ignored.
+ */
+ resp['ignoreStatusCode'] = function(status: number) {
+ if (this.status === status) {
+ this.preventDefault();
+ }
+ };
+ }
+ // Return the error to the method that called it.
+ return observableThrowError(resp);
+ })
+ );
+ }
+
+ private prepareNotification(resp): number {
+ return this.notificationService.show(() => {
+ let message = '';
+ if (_.isPlainObject(resp.error) && _.isString(resp.error.detail)) {
+ message = resp.error.detail; // Error was triggered by the backend.
+ } else if (_.isString(resp.error)) {
+ message = resp.error;
+ } else if (_.isString(resp.message)) {
+ message = resp.message;
+ }
+ return new CdNotificationConfig(
+ NotificationType.error,
+ `${resp.status} - ${resp.statusText}`,
+ message,
+ undefined,
+ resp['application']
+ );
+ });
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.spec.ts
new file mode 100644
index 00000000..796b42b4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.spec.ts
@@ -0,0 +1,54 @@
+import { Component, NgZone } from '@angular/core';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { AuthGuardService } from './auth-guard.service';
+import { AuthStorageService } from './auth-storage.service';
+
+describe('AuthGuardService', () => {
+ let service: AuthGuardService;
+ let authStorageService: AuthStorageService;
+ let ngZone: NgZone;
+ let route: ActivatedRouteSnapshot;
+ let state: RouterStateSnapshot;
+
+ @Component({ selector: 'cd-login', template: '' })
+ class LoginComponent {}
+
+ const routes: Routes = [{ path: 'login', component: LoginComponent }];
+
+ configureTestBed({
+ imports: [RouterTestingModule.withRoutes(routes)],
+ providers: [AuthGuardService, AuthStorageService],
+ declarations: [LoginComponent]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(AuthGuardService);
+ authStorageService = TestBed.get(AuthStorageService);
+ ngZone = TestBed.get(NgZone);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should allow the user if loggedIn', () => {
+ route = null;
+ state = { url: '/', root: null };
+ spyOn(authStorageService, 'isLoggedIn').and.returnValue(true);
+ expect(service.canActivate(route, state)).toBe(true);
+ });
+
+ it('should prevent user if not loggedIn and redirect to login page', fakeAsync(() => {
+ const router = TestBed.get(Router);
+ state = { url: '/pool', root: null };
+ ngZone.run(() => {
+ expect(service.canActivate(route, state)).toBe(false);
+ });
+ tick();
+ expect(router.url).toBe('/login?returnUrl=%2Fpool');
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts
new file mode 100644
index 00000000..61c06c81
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts
@@ -0,0 +1,29 @@
+import { Injectable } from '@angular/core';
+import {
+ ActivatedRouteSnapshot,
+ CanActivate,
+ CanActivateChild,
+ Router,
+ RouterStateSnapshot
+} from '@angular/router';
+
+import { AuthStorageService } from './auth-storage.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthGuardService implements CanActivate, CanActivateChild {
+ constructor(private router: Router, private authStorageService: AuthStorageService) {}
+
+ canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
+ if (this.authStorageService.isLoggedIn()) {
+ return true;
+ }
+ this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
+ return false;
+ }
+
+ canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
+ return this.canActivate(childRoute, state);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.spec.ts
new file mode 100644
index 00000000..068a1e1d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.spec.ts
@@ -0,0 +1,35 @@
+import { AuthStorageService } from './auth-storage.service';
+
+describe('AuthStorageService', () => {
+ let service: AuthStorageService;
+ const username = 'foobar';
+
+ beforeEach(() => {
+ service = new AuthStorageService();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should store username', () => {
+ service.set(username);
+ expect(localStorage.getItem('dashboard_username')).toBe(username);
+ });
+
+ it('should remove username', () => {
+ service.set(username);
+ service.remove();
+ expect(localStorage.getItem('dashboard_username')).toBe(null);
+ });
+
+ it('should be loggedIn', () => {
+ service.set(username);
+ expect(service.isLoggedIn()).toBe(true);
+ });
+
+ it('should not be loggedIn', () => {
+ service.remove();
+ expect(service.isLoggedIn()).toBe(false);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.ts
new file mode 100644
index 00000000..1f34eeed
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-storage.service.ts
@@ -0,0 +1,33 @@
+import { Injectable } from '@angular/core';
+
+import { Permissions } from '../models/permissions';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthStorageService {
+ constructor() {}
+
+ set(username: string, permissions: object = {}) {
+ localStorage.setItem('dashboard_username', username);
+ localStorage.setItem('dashboard_permissions', JSON.stringify(new Permissions(permissions)));
+ }
+
+ remove() {
+ localStorage.removeItem('dashboard_username');
+ }
+
+ isLoggedIn() {
+ return localStorage.getItem('dashboard_username') !== null;
+ }
+
+ getUsername() {
+ return localStorage.getItem('dashboard_username');
+ }
+
+ getPermissions(): Permissions {
+ return JSON.parse(
+ localStorage.getItem('dashboard_permissions') || JSON.stringify(new Permissions({}))
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.spec.ts
new file mode 100644
index 00000000..6665647b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.spec.ts
@@ -0,0 +1,72 @@
+import { Component, NgZone } from '@angular/core';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ActivatedRouteSnapshot, Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { FeatureTogglesGuardService } from './feature-toggles-guard.service';
+import { FeatureTogglesService } from './feature-toggles.service';
+
+describe('FeatureTogglesGuardService', () => {
+ let service: FeatureTogglesGuardService;
+ let fakeFeatureTogglesService: FeatureTogglesService;
+ let router: Router;
+ let ngZone: NgZone;
+
+ @Component({ selector: 'cd-cephfs', template: '' })
+ class CephfsComponent {}
+
+ @Component({ selector: 'cd-404', template: '' })
+ class NotFoundComponent {}
+
+ const routes: Routes = [
+ { path: 'cephfs', component: CephfsComponent },
+ { path: '404', component: NotFoundComponent }
+ ];
+
+ configureTestBed({
+ imports: [RouterTestingModule.withRoutes(routes)],
+ providers: [
+ { provide: FeatureTogglesService, useValue: { get: null } },
+ FeatureTogglesGuardService
+ ],
+ declarations: [CephfsComponent, NotFoundComponent]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(FeatureTogglesGuardService);
+ fakeFeatureTogglesService = TestBed.get(FeatureTogglesService);
+ ngZone = TestBed.get(NgZone);
+ router = TestBed.get(Router);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ function testCanActivate(path, feature_toggles_map) {
+ let result: boolean;
+ spyOn(fakeFeatureTogglesService, 'get').and.returnValue(observableOf(feature_toggles_map));
+
+ ngZone.run(() => {
+ service
+ .canActivate(<ActivatedRouteSnapshot>{ routeConfig: { path: path } })
+ .subscribe((val) => (result = val));
+ });
+ tick();
+
+ return result;
+ }
+
+ it('should allow the feature if enabled', fakeAsync(() => {
+ expect(testCanActivate('cephfs', { cephfs: true })).toBe(true);
+ expect(router.url).toBe('/');
+ }));
+
+ it('should redirect to 404 if disable', fakeAsync(() => {
+ expect(testCanActivate('cephfs', { cephfs: false })).toBe(false);
+ expect(router.url).toBe('/404');
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts
new file mode 100644
index 00000000..3cad644d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts
@@ -0,0 +1,29 @@
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router } from '@angular/router';
+
+import { map } from 'rxjs/operators';
+
+import { FeatureTogglesMap, FeatureTogglesService } from './feature-toggles.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FeatureTogglesGuardService implements CanActivate, CanActivateChild {
+ constructor(private router: Router, private featureToggles: FeatureTogglesService) {}
+
+ canActivate(route: ActivatedRouteSnapshot) {
+ return this.featureToggles.get().pipe(
+ map((enabledFeatures: FeatureTogglesMap) => {
+ if (enabledFeatures[route.routeConfig.path] === false) {
+ this.router.navigate(['404']);
+ return false;
+ }
+ return true;
+ })
+ );
+ }
+
+ canActivateChild(route: ActivatedRouteSnapshot) {
+ return this.canActivate(route.parent);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.spec.ts
new file mode 100644
index 00000000..8ad0a15e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.spec.ts
@@ -0,0 +1,54 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { FeatureTogglesService } from './feature-toggles.service';
+
+describe('FeatureTogglesService', () => {
+ let httpTesting: HttpTestingController;
+ let service: FeatureTogglesService;
+
+ configureTestBed({
+ providers: [FeatureTogglesService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(FeatureTogglesService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should fetch HTTP endpoint once and only once', fakeAsync(() => {
+ const mockFeatureTogglesMap = [
+ {
+ rbd: true,
+ mirroring: true,
+ iscsi: true,
+ cephfs: true,
+ rgw: true
+ }
+ ];
+
+ service
+ .get()
+ .subscribe((featureTogglesMap) => expect(featureTogglesMap).toEqual(mockFeatureTogglesMap));
+ tick();
+
+ // Second subscription shouldn't trigger a new HTTP request
+ service
+ .get()
+ .subscribe((featureTogglesMap) => expect(featureTogglesMap).toEqual(mockFeatureTogglesMap));
+
+ const req = httpTesting.expectOne(service.API_URL);
+ req.flush(mockFeatureTogglesMap);
+ discardPeriodicTasks();
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts
new file mode 100644
index 00000000..9104e0b4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles.service.ts
@@ -0,0 +1,28 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Observable, timer } from 'rxjs';
+import { flatMap, shareReplay } from 'rxjs/operators';
+
+export type FeatureTogglesMap = Map<string, boolean>;
+export type FeatureTogglesMap$ = Observable<FeatureTogglesMap>;
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FeatureTogglesService {
+ readonly API_URL: string = 'api/feature_toggles';
+ readonly REFRESH_INTERVAL: number = 20000;
+ private featureToggleMap$: FeatureTogglesMap$;
+
+ constructor(private http: HttpClient) {
+ this.featureToggleMap$ = timer(0, this.REFRESH_INTERVAL).pipe(
+ flatMap(() => this.http.get<FeatureTogglesMap>(this.API_URL)),
+ shareReplay(1)
+ );
+ }
+
+ get(): FeatureTogglesMap$ {
+ return this.featureToggleMap$;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.spec.ts
new file mode 100644
index 00000000..b0c1860d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.spec.ts
@@ -0,0 +1,90 @@
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { DimlessBinaryPipe } from '../pipes/dimless-binary.pipe';
+import { DimlessPipe } from '../pipes/dimless.pipe';
+import { FormatterService } from './formatter.service';
+
+describe('FormatterService', () => {
+ let service: FormatterService;
+ let dimlessBinaryPipe: DimlessBinaryPipe;
+ let dimlessPipe: DimlessPipe;
+
+ const convertToBytesAndBack = (value: string, newValue?: string) => {
+ expect(dimlessBinaryPipe.transform(service.toBytes(value))).toBe(newValue || value);
+ };
+
+ configureTestBed({
+ providers: [FormatterService, DimlessBinaryPipe]
+ });
+
+ beforeEach(() => {
+ service = new FormatterService();
+ dimlessBinaryPipe = new DimlessBinaryPipe(service);
+ dimlessPipe = new DimlessPipe(service);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('format_number', () => {
+ const formats = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
+
+ it('should return minus for unsupported values', () => {
+ expect(service.format_number(service, 1024, formats)).toBe('-');
+ expect(service.format_number(undefined, 1024, formats)).toBe('-');
+ expect(service.format_number(null, 1024, formats)).toBe('-');
+ });
+
+ it('should test some values', () => {
+ expect(service.format_number('0', 1024, formats)).toBe('0 B');
+ expect(service.format_number('0.1', 1024, formats)).toBe('0.1 B');
+ expect(service.format_number('1.2', 1024, formats)).toBe('1.2 B');
+ expect(service.format_number('1', 1024, formats)).toBe('1 B');
+ expect(service.format_number('1024', 1024, formats)).toBe('1 KiB');
+ expect(service.format_number(23.45678 * Math.pow(1024, 3), 1024, formats)).toBe('23.5 GiB');
+ expect(service.format_number(23.45678 * Math.pow(1024, 3), 1024, formats, 2)).toBe(
+ '23.46 GiB'
+ );
+ });
+
+ it('should test some dimless values', () => {
+ expect(dimlessPipe.transform(0.6)).toBe('0.6');
+ expect(dimlessPipe.transform(1000.608)).toBe('1 k');
+ expect(dimlessPipe.transform(1e10)).toBe('10 G');
+ expect(dimlessPipe.transform(2.37e16)).toBe('23.7 P');
+ });
+ });
+
+ describe('toBytes', () => {
+ it('should not convert wrong values', () => {
+ expect(service.toBytes('10xyz')).toBeNull();
+ expect(service.toBytes('1.1.1KiB')).toBeNull();
+ expect(service.toBytes('1.1 KiloByte')).toBeNull();
+ expect(service.toBytes('1.1 kib')).toBeNull();
+ expect(service.toBytes('1.kib')).toBeNull();
+ expect(service.toBytes('1 ki')).toBeNull();
+ expect(service.toBytes(undefined)).toBeNull();
+ expect(service.toBytes('')).toBeNull();
+ expect(service.toBytes('-')).toBeNull();
+ expect(service.toBytes(null)).toBeNull();
+ });
+
+ it('should convert values to bytes', () => {
+ expect(service.toBytes('4815162342')).toBe(4815162342);
+ expect(service.toBytes('100M')).toBe(104857600);
+ expect(service.toBytes('100 M')).toBe(104857600);
+ expect(service.toBytes('100 mIb')).toBe(104857600);
+ expect(service.toBytes('100 mb')).toBe(104857600);
+ expect(service.toBytes('100MIB')).toBe(104857600);
+ expect(service.toBytes('1.532KiB')).toBe(Math.round(1.532 * 1024));
+ expect(service.toBytes('0.000000000001TiB')).toBe(1);
+ });
+
+ it('should convert values to human readable again', () => {
+ convertToBytesAndBack('1.1 MiB');
+ convertToBytesAndBack('1.0MiB', '1 MiB');
+ convertToBytesAndBack('8.9 GiB');
+ convertToBytesAndBack('123.5 EiB');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.ts
new file mode 100644
index 00000000..6c9ce12b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/formatter.service.ts
@@ -0,0 +1,79 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FormatterService {
+ constructor() {}
+
+ format_number(n: any, divisor: number, units: string[], decimals: number = 1): string {
+ if (_.isString(n)) {
+ n = Number(n);
+ }
+ if (!_.isNumber(n)) {
+ return '-';
+ }
+ let unit = n < 1 ? 0 : Math.floor(Math.log(n) / Math.log(divisor));
+ unit = unit >= units.length ? units.length - 1 : unit;
+ let result = _.round(n / Math.pow(divisor, unit), decimals).toString();
+ if (result === '') {
+ return '-';
+ }
+ if (units[unit] !== '') {
+ result = `${result} ${units[unit]}`;
+ }
+ return result;
+ }
+
+ /**
+ * Convert the given value into bytes.
+ * @param {string} value The value to be converted, e.g. 1024B, 10M, 300KiB or 1ZB.
+ * @param error_value The value returned in case the regular expression did not match. Defaults to
+ * null.
+ * @returns Returns the given value in bytes without any unit appended or the defined error value
+ * in case xof an error.
+ */
+ toBytes(value: string, error_value = null): number | null {
+ const base = 1024;
+ const units = ['b', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y'];
+ const m = RegExp('^(\\d+(.\\d+)?) ?([' + units.join('') + ']?(b|ib|B/s)?)?$', 'i').exec(value);
+ if (m === null) {
+ return error_value;
+ }
+ let bytes = parseFloat(m[1]);
+ if (_.isString(m[3])) {
+ bytes = bytes * Math.pow(base, units.indexOf(m[3].toLowerCase()[0]));
+ }
+ return Math.round(bytes);
+ }
+
+ /**
+ * Converts `x ms` to `x` (currently) or `0` if the conversion fails
+ */
+ toMilliseconds(value: string): number {
+ const pattern = /^\s*(\d+)\s*(ms)?\s*$/i;
+ const testResult = pattern.exec(value);
+
+ if (testResult !== null) {
+ return +testResult[1];
+ }
+
+ return 0;
+ }
+
+ /**
+ * Converts `x IOPS` to `x` (currently) or `0` if the conversion fails
+ */
+ toIops(value: string): number {
+ const pattern = /^\s*(\d+)\s*(IOPS)?\s*$/i;
+ const testResult = pattern.exec(value);
+
+ if (testResult !== null) {
+ return +testResult[1];
+ }
+
+ return 0;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/js-error-handler.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/js-error-handler.service.ts
new file mode 100644
index 00000000..87e95bf6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/js-error-handler.service.ts
@@ -0,0 +1,16 @@
+import { ErrorHandler, Injectable, Injector } from '@angular/core';
+import { LoggingService } from '../api/logging.service';
+
+@Injectable()
+export class JsErrorHandler implements ErrorHandler {
+ constructor(private injector: Injector) {}
+
+ handleError(error) {
+ const loggingService = this.injector.get(LoggingService);
+ const url = window.location.href;
+ const message = error && error.message;
+ const stack = error && error.stack;
+ loggingService.jsError(url, message, stack).subscribe();
+ throw error;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.spec.ts
new file mode 100644
index 00000000..5c4ad820
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.spec.ts
@@ -0,0 +1,34 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { LanguageService } from './language.service';
+
+describe('LanguageService', () => {
+ let service: LanguageService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [LanguageService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(LanguageService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call create', () => {
+ service.getLanguages().subscribe();
+ const req = httpTesting.expectOne('ui-api/langs');
+ expect(req.request.method).toBe('GET');
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.ts
new file mode 100644
index 00000000..43881710
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/language.service.ts
@@ -0,0 +1,24 @@
+import { HttpClient } from '@angular/common/http';
+import { Inject, LOCALE_ID } from '@angular/core';
+import { Injectable } from '@angular/core';
+
+import { environment } from '../../../environments/environment';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class LanguageService {
+ constructor(private http: HttpClient, @Inject(LOCALE_ID) protected localeId: string) {}
+
+ getLocale(): string {
+ return this.localeId || environment.default_lang;
+ }
+
+ setLocale(lang: string) {
+ document.cookie = `cd-lang=${lang}`;
+ }
+
+ getLanguages() {
+ return this.http.get<string[]>('ui-api/langs');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.spec.ts
new file mode 100644
index 00000000..9912d67b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.spec.ts
@@ -0,0 +1,82 @@
+import { HttpClient } from '@angular/common/http';
+import { Component, NgZone } from '@angular/core';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ActivatedRouteSnapshot, Router, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { ModuleStatusGuardService } from './module-status-guard.service';
+
+describe('ModuleStatusGuardService', () => {
+ let service: ModuleStatusGuardService;
+ let httpClient: HttpClient;
+ let router: Router;
+ let route: ActivatedRouteSnapshot;
+ let ngZone: NgZone;
+
+ @Component({ selector: 'cd-foo', template: '' })
+ class FooComponent {}
+
+ const fakeService = {
+ get: () => true
+ };
+
+ const routes: Routes = [{ path: '**', component: FooComponent }];
+
+ const testCanActivate = (getResult: {}, activateResult: boolean, urlResult: string) => {
+ let result: boolean;
+ spyOn(httpClient, 'get').and.returnValue(observableOf(getResult));
+ ngZone.run(() => {
+ service.canActivateChild(route).subscribe((resp) => {
+ result = resp;
+ });
+ });
+
+ tick();
+ expect(result).toBe(activateResult);
+ expect(router.url).toBe(urlResult);
+ };
+
+ configureTestBed(
+ {
+ imports: [RouterTestingModule.withRoutes(routes)],
+ providers: [ModuleStatusGuardService, { provide: HttpClient, useValue: fakeService }],
+ declarations: [FooComponent]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ service = TestBed.get(ModuleStatusGuardService);
+ httpClient = TestBed.get(HttpClient);
+ router = TestBed.get(Router);
+ route = new ActivatedRouteSnapshot();
+ route.url = [];
+ route.data = {
+ moduleStatusGuardConfig: {
+ apiPath: 'bar',
+ redirectTo: '/foo'
+ }
+ };
+ ngZone = TestBed.get(NgZone);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should test canActivate with status available', fakeAsync(() => {
+ route.data.moduleStatusGuardConfig.redirectTo = 'foo';
+ testCanActivate({ available: true, message: 'foo' }, true, '/');
+ }));
+
+ it('should test canActivateChild with status unavailable', fakeAsync(() => {
+ testCanActivate({ available: false, message: null }, false, '/foo/');
+ }));
+
+ it('should test canActivateChild with status unavailable', fakeAsync(() => {
+ testCanActivate(null, false, '/foo');
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts
new file mode 100644
index 00000000..46f3c840
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts
@@ -0,0 +1,68 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router } from '@angular/router';
+
+import { of as observableOf } from 'rxjs';
+import { catchError, map } from 'rxjs/operators';
+
+/**
+ * This service checks if a route can be activated by executing a
+ * REST API call to '/api/<apiPath>/status'. If the returned response
+ * states that the module is not available, then the user is redirected
+ * to the specified <redirectTo> URL path.
+ *
+ * A controller implementing this endpoint should return an object of
+ * the following form:
+ * {'available': true|false, 'message': null|string}.
+ *
+ * The configuration of this guard should look like this:
+ * const routes: Routes = [
+ * {
+ * path: 'rgw/bucket',
+ * component: RgwBucketListComponent,
+ * canActivate: [AuthGuardService, ModuleStatusGuardService],
+ * data: {
+ * moduleStatusGuardConfig: {
+ * apiPath: 'rgw',
+ * redirectTo: 'rgw/501'
+ * }
+ * }
+ * },
+ * ...
+ */
+@Injectable({
+ providedIn: 'root'
+})
+export class ModuleStatusGuardService implements CanActivate, CanActivateChild {
+ // TODO: Hotfix - remove WHITELIST'ing when a generic ErrorComponent is implemented
+ static readonly WHITELIST: string[] = ['501'];
+
+ constructor(private http: HttpClient, private router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot) {
+ return this.doCheck(route);
+ }
+
+ canActivateChild(childRoute: ActivatedRouteSnapshot) {
+ return this.doCheck(childRoute);
+ }
+
+ private doCheck(route: ActivatedRouteSnapshot) {
+ if (route.url.length > 0 && ModuleStatusGuardService.WHITELIST.includes(route.url[0].path)) {
+ return observableOf(true);
+ }
+ const config = route.data['moduleStatusGuardConfig'];
+ return this.http.get(`api/${config.apiPath}/status`).pipe(
+ map((resp: any) => {
+ if (!resp.available) {
+ this.router.navigate([config.redirectTo, resp.message || '']);
+ }
+ return resp.available;
+ }),
+ catchError(() => {
+ this.router.navigate([config.redirectTo]);
+ return observableOf(false);
+ })
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts
new file mode 100644
index 00000000..09578f42
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.spec.ts
@@ -0,0 +1,262 @@
+import { DatePipe } from '@angular/common';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import * as _ from 'lodash';
+import { ToastrService } from 'ngx-toastr';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { FinishedTask } from '../models/finished-task';
+import { CdDatePipe } from '../pipes/cd-date.pipe';
+import { NotificationService } from './notification.service';
+import { TaskMessageService } from './task-message.service';
+
+describe('NotificationService', () => {
+ let service: NotificationService;
+ const toastFakeService = {
+ error: () => true,
+ info: () => true,
+ success: () => true
+ };
+
+ configureTestBed({
+ providers: [
+ CdDatePipe,
+ DatePipe,
+ NotificationService,
+ TaskMessageService,
+ { provide: ToastrService, useValue: toastFakeService },
+ { provide: CdDatePipe, useValue: { transform: (d) => d } },
+ i18nProviders
+ ]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(NotificationService);
+ service.removeAll();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should read empty notification list', () => {
+ localStorage.setItem('cdNotifications', '[]');
+ expect(service['dataSource'].getValue()).toEqual([]);
+ });
+
+ it('should read old notifications', fakeAsync(() => {
+ localStorage.setItem(
+ 'cdNotifications',
+ '[{"type":2,"message":"foobar","timestamp":"2018-05-24T09:41:32.726Z"}]'
+ );
+ service = new NotificationService(null, null, null);
+ expect(service['dataSource'].getValue().length).toBe(1);
+ }));
+
+ it('should cancel a notification', fakeAsync(() => {
+ const timeoutId = service.show(NotificationType.error, 'Simple test');
+ service.cancel(timeoutId);
+ tick(5000);
+ expect(service['dataSource'].getValue().length).toBe(0);
+ }));
+
+ describe('Saved notifications', () => {
+ const expectSavedNotificationToHave = (expected: {}) => {
+ tick(510);
+ expect(service['dataSource'].getValue().length).toBe(1);
+ const notification = service['dataSource'].getValue()[0];
+ Object.keys(expected).forEach((key) => {
+ expect(notification[key]).toBe(expected[key]);
+ });
+ };
+
+ beforeEach(() => {
+ service.cancel(service['justShownTimeoutId']);
+ });
+
+ it('should create a success notification and save it', fakeAsync(() => {
+ service.show(new CdNotificationConfig(NotificationType.success, 'Simple test'));
+ expectSavedNotificationToHave({ type: NotificationType.success });
+ }));
+
+ it('should create an error notification and save it', fakeAsync(() => {
+ service.show(NotificationType.error, 'Simple test');
+ expectSavedNotificationToHave({ type: NotificationType.error });
+ }));
+
+ it('should create an info notification and save it', fakeAsync(() => {
+ service.show(new CdNotificationConfig(NotificationType.info, 'Simple test'));
+ expectSavedNotificationToHave({
+ type: NotificationType.info,
+ title: 'Simple test',
+ message: undefined
+ });
+ }));
+
+ it('should never have more then 10 notifications', fakeAsync(() => {
+ for (let index = 0; index < 15; index++) {
+ service.show(NotificationType.info, 'Simple test');
+ tick(510);
+ }
+ expect(service['dataSource'].getValue().length).toBe(10);
+ }));
+
+ it('should show a success task notification', fakeAsync(() => {
+ const task = _.assign(new FinishedTask(), {
+ success: true
+ });
+ service.notifyTask(task, true);
+ expectSavedNotificationToHave({
+ type: NotificationType.success,
+ title: 'Executed unknown task',
+ message: undefined
+ });
+ }));
+
+ it('should be able to stop notifyTask from notifying', fakeAsync(() => {
+ const task = _.assign(new FinishedTask(), {
+ success: true
+ });
+ const timeoutId = service.notifyTask(task, true);
+ service.cancel(timeoutId);
+ tick(100);
+ expect(service['dataSource'].getValue().length).toBe(0);
+ }));
+
+ it('should show a error task notification', fakeAsync(() => {
+ const task = _.assign(
+ new FinishedTask('rbd/create', {
+ pool_name: 'somePool',
+ image_name: 'someImage'
+ }),
+ {
+ success: false,
+ exception: {
+ code: 17
+ }
+ }
+ );
+ service.notifyTask(task);
+ expectSavedNotificationToHave({
+ type: NotificationType.error,
+ title: `Failed to create RBD 'somePool/someImage'`,
+ message: `Name is already used by RBD 'somePool/someImage'.`
+ });
+ }));
+
+ it('combines different notifications with the same title', fakeAsync(() => {
+ service.show(NotificationType.error, '502 - Bad Gateway', 'Error occurred in path a');
+ tick(60);
+ service.show(NotificationType.error, '502 - Bad Gateway', 'Error occurred in path b');
+ expectSavedNotificationToHave({
+ type: NotificationType.error,
+ title: '502 - Bad Gateway',
+ message: '<ul><li>Error occurred in path a</li><li>Error occurred in path b</li></ul>'
+ });
+ }));
+ });
+
+ describe('notification queue', () => {
+ const n1 = new CdNotificationConfig(NotificationType.success, 'Some success');
+ const n2 = new CdNotificationConfig(NotificationType.info, 'Some info');
+
+ const showArray = (arr) => arr.forEach((n) => service.show(n));
+
+ beforeEach(() => {
+ spyOn(service, 'save').and.stub();
+ });
+
+ it('filters out duplicated notifications on single call', fakeAsync(() => {
+ showArray([n1, n1, n2, n2]);
+ tick(510);
+ expect(service.save).toHaveBeenCalledTimes(2);
+ }));
+
+ it('filters out duplicated notifications presented in different calls', fakeAsync(() => {
+ showArray([n1, n2]);
+ showArray([n1, n2]);
+ tick(1000);
+ expect(service.save).toHaveBeenCalledTimes(2);
+ }));
+
+ it('will reset the timeout on every call', fakeAsync(() => {
+ showArray([n1, n2]);
+ tick(490);
+ showArray([n1, n2]);
+ tick(450);
+ expect(service.save).toHaveBeenCalledTimes(0);
+ tick(60);
+ expect(service.save).toHaveBeenCalledTimes(2);
+ }));
+
+ it('wont filter out duplicated notifications if timeout was reached before', fakeAsync(() => {
+ showArray([n1, n2]);
+ tick(510);
+ showArray([n1, n2]);
+ tick(510);
+ expect(service.save).toHaveBeenCalledTimes(4);
+ }));
+ });
+
+ describe('showToasty', () => {
+ let toastr: ToastrService;
+ const time = '2022-02-22T00:00:00.000Z';
+
+ beforeEach(() => {
+ const baseTime = new Date(time);
+ spyOn(global, 'Date').and.returnValue(baseTime);
+ spyOn(window, 'setTimeout').and.callFake((fn) => fn());
+
+ toastr = TestBed.get(ToastrService);
+ // spyOn needs to know the methods before spying and can't read the array for clarification
+ ['error', 'info', 'success'].forEach((method: 'error' | 'info' | 'success') =>
+ spyOn(toastr, method).and.stub()
+ );
+ });
+
+ it('should show with only title defined', () => {
+ service.show(NotificationType.info, 'Some info');
+ expect(toastr.info).toHaveBeenCalledWith(
+ `<small class="date">${time}</small>` +
+ '<i class="pull-right custom-icon ceph-icon" title="Ceph"></i>',
+ 'Some info',
+ undefined
+ );
+ });
+
+ it('should show with title and message defined', () => {
+ service.show(
+ () =>
+ new CdNotificationConfig(NotificationType.error, 'Some error', 'Some operation failed')
+ );
+ expect(toastr.error).toHaveBeenCalledWith(
+ 'Some operation failed<br>' +
+ `<small class="date">${time}</small>` +
+ '<i class="pull-right custom-icon ceph-icon" title="Ceph"></i>',
+ 'Some error',
+ undefined
+ );
+ });
+
+ it('should show with title, message and application defined', () => {
+ service.show(
+ new CdNotificationConfig(
+ NotificationType.success,
+ 'Alert resolved',
+ 'Some alert resolved',
+ undefined,
+ 'Prometheus'
+ )
+ );
+ expect(toastr.success).toHaveBeenCalledWith(
+ 'Some alert resolved<br>' +
+ `<small class="date">${time}</small>` +
+ '<i class="pull-right custom-icon prometheus-icon" title="Prometheus"></i>',
+ 'Alert resolved',
+ undefined
+ );
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts
new file mode 100644
index 00000000..217acf26
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/notification.service.ts
@@ -0,0 +1,207 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+import { IndividualConfig, ToastrService } from 'ngx-toastr';
+import { BehaviorSubject } from 'rxjs';
+
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotification, CdNotificationConfig } from '../models/cd-notification';
+import { FinishedTask } from '../models/finished-task';
+import { CdDatePipe } from '../pipes/cd-date.pipe';
+import { TaskMessageService } from './task-message.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class NotificationService {
+ private hideToasties = false;
+
+ // Observable sources
+ private dataSource = new BehaviorSubject<CdNotification[]>([]);
+
+ // Observable streams
+ data$ = this.dataSource.asObservable();
+
+ private queued: CdNotificationConfig[] = [];
+ private queuedTimeoutId: number;
+ KEY = 'cdNotifications';
+
+ constructor(
+ public toastr: ToastrService,
+ private taskMessageService: TaskMessageService,
+ private cdDatePipe: CdDatePipe
+ ) {
+ const stringNotifications = localStorage.getItem(this.KEY);
+ let notifications: CdNotification[] = [];
+
+ if (_.isString(stringNotifications)) {
+ notifications = JSON.parse(stringNotifications, (_key, value) => {
+ if (_.isPlainObject(value)) {
+ return _.assign(new CdNotification(), value);
+ }
+ return value;
+ });
+ }
+
+ this.dataSource.next(notifications);
+ }
+
+ /**
+ * Removes all current saved notifications
+ */
+ removeAll() {
+ localStorage.removeItem(this.KEY);
+ this.dataSource.next([]);
+ }
+
+ /**
+ * Method used for saving a shown notification (check show() method).
+ */
+ save(notification: CdNotification) {
+ const recent = this.dataSource.getValue();
+ recent.push(notification);
+ while (recent.length > 10) {
+ recent.shift();
+ }
+ this.dataSource.next(recent);
+ localStorage.setItem(this.KEY, JSON.stringify(recent));
+ }
+
+ /**
+ * Method for showing a notification.
+ * @param {NotificationType} type toastr type
+ * @param {string} title
+ * @param {string} [message] The message to be displayed. Note, use this field
+ * for error notifications only.
+ * @param {*} [options] toastr compatible options, used when creating a toastr
+ * @param {string} [application] Only needed if notification comes from an external application
+ * @returns The timeout ID that is set to be able to cancel the notification.
+ */
+ show(
+ type: NotificationType,
+ title: string,
+ message?: string,
+ options?: any | IndividualConfig,
+ application?: string
+ ): number;
+ show(config: CdNotificationConfig | (() => CdNotificationConfig)): number;
+ show(
+ arg: NotificationType | CdNotificationConfig | (() => CdNotificationConfig),
+ title?: string,
+ message?: string,
+ options?: any | IndividualConfig,
+ application?: string
+ ): number {
+ return window.setTimeout(() => {
+ let config: CdNotificationConfig;
+ if (_.isFunction(arg)) {
+ config = arg() as CdNotificationConfig;
+ } else if (_.isObject(arg)) {
+ config = arg as CdNotificationConfig;
+ } else {
+ config = new CdNotificationConfig(
+ arg as NotificationType,
+ title,
+ message,
+ options,
+ application
+ );
+ }
+ this.queueToShow(config);
+ }, 10);
+ }
+
+ private queueToShow(config: CdNotificationConfig) {
+ this.cancel(this.queuedTimeoutId);
+ if (!this.queued.find((c) => _.isEqual(c, config))) {
+ this.queued.push(config);
+ }
+ this.queuedTimeoutId = window.setTimeout(() => {
+ this.showQueued();
+ }, 500);
+ }
+
+ private showQueued() {
+ this.getUnifiedTitleQueue().forEach((config) => {
+ const notification = new CdNotification(config);
+ this.save(notification);
+ this.showToasty(notification);
+ });
+ }
+
+ private getUnifiedTitleQueue(): CdNotificationConfig[] {
+ return Object.values(this.queueShiftByTitle()).map((configs) => {
+ const config = configs[0];
+ if (configs.length > 1) {
+ config.message = '<ul>' + configs.map((c) => `<li>${c.message}</li>`).join('') + '</ul>';
+ }
+ return config;
+ });
+ }
+
+ private queueShiftByTitle(): { [key: string]: CdNotificationConfig[] } {
+ const byTitle: { [key: string]: CdNotificationConfig[] } = {};
+ let config: CdNotificationConfig;
+ while ((config = this.queued.shift())) {
+ if (!byTitle[config.title]) {
+ byTitle[config.title] = [];
+ }
+ byTitle[config.title].push(config);
+ }
+ return byTitle;
+ }
+
+ private showToasty(notification: CdNotification) {
+ // Exit immediately if no toasty should be displayed.
+ if (this.hideToasties) {
+ return;
+ }
+ this.toastr[['error', 'info', 'success'][notification.type]](
+ (notification.message ? notification.message + '<br>' : '') +
+ this.renderTimeAndApplicationHtml(notification),
+ notification.title,
+ notification.options
+ );
+ }
+
+ renderTimeAndApplicationHtml(notification: CdNotification): string {
+ return `<small class="date">${this.cdDatePipe.transform(
+ notification.timestamp
+ )}</small><i class="pull-right custom-icon ${notification.applicationClass}" title="${
+ notification.application
+ }"></i>`;
+ }
+
+ notifyTask(finishedTask: FinishedTask, success: boolean = true): number {
+ let notification: CdNotificationConfig;
+ if (finishedTask.success && success) {
+ notification = new CdNotificationConfig(
+ NotificationType.success,
+ this.taskMessageService.getSuccessTitle(finishedTask)
+ );
+ } else {
+ notification = new CdNotificationConfig(
+ NotificationType.error,
+ this.taskMessageService.getErrorTitle(finishedTask),
+ this.taskMessageService.getErrorMessage(finishedTask)
+ );
+ }
+ return this.show(notification);
+ }
+
+ /**
+ * Prevent the notification from being shown.
+ * @param {number} timeoutId A number representing the ID of the timeout to be canceled.
+ */
+ cancel(timeoutId) {
+ window.clearTimeout(timeoutId);
+ }
+
+ /**
+ * Suspend showing the notification toasties.
+ * @param {boolean} suspend Set to ``true`` to disable/hide toasties.
+ */
+ suspendToasties(suspend: boolean) {
+ this.hideToasties = suspend;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.spec.ts
new file mode 100644
index 00000000..0b019055
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.spec.ts
@@ -0,0 +1,98 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../testing/unit-test-helper';
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { PrometheusCustomAlert } from '../models/prometheus-alerts';
+import { SharedModule } from '../shared.module';
+import { NotificationService } from './notification.service';
+import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
+
+describe('PrometheusAlertFormatter', () => {
+ let service: PrometheusAlertFormatter;
+ let notificationService: NotificationService;
+ let prometheus: PrometheusHelper;
+
+ configureTestBed({
+ imports: [ToastrModule.forRoot(), SharedModule],
+ providers: [PrometheusAlertFormatter, i18nProviders]
+ });
+
+ beforeEach(() => {
+ prometheus = new PrometheusHelper();
+ service = TestBed.get(PrometheusAlertFormatter);
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+ });
+
+ it('should create', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('sendNotifications', () => {
+ it('should not call queue notifications with no notification', () => {
+ service.sendNotifications([]);
+ expect(notificationService.show).not.toHaveBeenCalled();
+ });
+
+ it('should call queue notifications with notifications', () => {
+ const notifications = [new CdNotificationConfig(NotificationType.success, 'test')];
+ service.sendNotifications(notifications);
+ expect(notificationService.show).toHaveBeenCalledWith(notifications[0]);
+ });
+ });
+
+ describe('convertToCustomAlert', () => {
+ it('converts PrometheusAlert', () => {
+ expect(service.convertToCustomAlerts([prometheus.createAlert('Something')])).toEqual([
+ {
+ status: 'active',
+ name: 'Something',
+ summary: 'Something is active',
+ url: 'http://Something',
+ fingerprint: 'Something'
+ } as PrometheusCustomAlert
+ ]);
+ });
+
+ it('converts PrometheusNotificationAlert', () => {
+ expect(
+ service.convertToCustomAlerts([prometheus.createNotificationAlert('Something')])
+ ).toEqual([
+ {
+ fingerprint: false,
+ status: 'active',
+ name: 'Something',
+ summary: 'Something is firing',
+ url: 'http://Something'
+ } as PrometheusCustomAlert
+ ]);
+ });
+ });
+
+ it('converts custom alert into notification', () => {
+ const alert: PrometheusCustomAlert = {
+ status: 'active',
+ name: 'Some alert',
+ summary: 'Some alert is active',
+ url: 'http://some-alert',
+ fingerprint: '42'
+ };
+ expect(service.convertAlertToNotification(alert)).toEqual(
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'Some alert (active)',
+ 'Some alert is active <a href="http://some-alert" target="_blank">' +
+ '<i class="fa fa-line-chart"></i></a>',
+ undefined,
+ 'Prometheus'
+ )
+ );
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.ts
new file mode 100644
index 00000000..47cb0307
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert-formatter.ts
@@ -0,0 +1,73 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import {
+ AlertmanagerAlert,
+ AlertmanagerNotificationAlert,
+ PrometheusCustomAlert
+} from '../models/prometheus-alerts';
+import { NotificationService } from './notification.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PrometheusAlertFormatter {
+ constructor(private notificationService: NotificationService) {}
+
+ sendNotifications(notifications: CdNotificationConfig[]) {
+ notifications.forEach((n) => this.notificationService.show(n));
+ }
+
+ convertToCustomAlerts(
+ alerts: (AlertmanagerNotificationAlert | AlertmanagerAlert)[]
+ ): PrometheusCustomAlert[] {
+ return _.uniqWith(
+ alerts.map((alert) => {
+ return {
+ status: _.isObject(alert.status)
+ ? (alert as AlertmanagerAlert).status.state
+ : this.getPrometheusNotificationStatus(alert as AlertmanagerNotificationAlert),
+ name: alert.labels.alertname,
+ url: alert.generatorURL,
+ summary: alert.annotations.summary,
+ fingerprint: _.isObject(alert.status) && (alert as AlertmanagerAlert).fingerprint
+ };
+ }),
+ _.isEqual
+ ) as PrometheusCustomAlert[];
+ }
+
+ /*
+ * This is needed because NotificationAlerts don't use 'active'
+ */
+ private getPrometheusNotificationStatus(alert: AlertmanagerNotificationAlert): string {
+ const state = alert.status;
+ return state === 'firing' ? 'active' : state;
+ }
+
+ convertAlertToNotification(alert: PrometheusCustomAlert): CdNotificationConfig {
+ return new CdNotificationConfig(
+ this.formatType(alert.status),
+ `${alert.name} (${alert.status})`,
+ this.appendSourceLink(alert, alert.summary),
+ undefined,
+ 'Prometheus'
+ );
+ }
+
+ private formatType(status: string): NotificationType {
+ const types = {
+ error: ['firing', 'active'],
+ info: ['suppressed', 'unprocessed'],
+ success: ['resolved']
+ };
+ return NotificationType[_.findKey(types, (type) => type.includes(status))];
+ }
+
+ private appendSourceLink(alert: PrometheusCustomAlert, message: string): string {
+ return `${message} <a href="${alert.url}" target="_blank"><i class="fa fa-line-chart"></i></a>`;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.spec.ts
new file mode 100644
index 00000000..100c8299
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.spec.ts
@@ -0,0 +1,190 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+import { Observable, of } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../testing/unit-test-helper';
+import { PrometheusService } from '../api/prometheus.service';
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { AlertmanagerAlert } from '../models/prometheus-alerts';
+import { SharedModule } from '../shared.module';
+import { NotificationService } from './notification.service';
+import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
+import { PrometheusAlertService } from './prometheus-alert.service';
+
+describe('PrometheusAlertService', () => {
+ let service: PrometheusAlertService;
+ let notificationService: NotificationService;
+ let alerts: AlertmanagerAlert[];
+ let prometheusService: PrometheusService;
+ let prometheus: PrometheusHelper;
+
+ configureTestBed({
+ imports: [ToastrModule.forRoot(), SharedModule, HttpClientTestingModule],
+ providers: [PrometheusAlertService, PrometheusAlertFormatter, i18nProviders]
+ });
+
+ beforeEach(() => {
+ prometheus = new PrometheusHelper();
+ });
+
+ it('should create', () => {
+ expect(TestBed.get(PrometheusAlertService)).toBeTruthy();
+ });
+
+ describe('test failing status codes and verify disabling of the alertmanager', () => {
+ const isDisabledByStatusCode = (statusCode: number, expectedStatus: boolean, done) => {
+ service = TestBed.get(PrometheusAlertService);
+ prometheusService = TestBed.get(PrometheusService);
+ spyOn(prometheusService, 'ifAlertmanagerConfigured').and.callFake((fn) => fn());
+ spyOn(prometheusService, 'getAlerts').and.returnValue(
+ Observable.create((observer) => observer.error({ status: statusCode, error: {} }))
+ );
+ const disableFn = spyOn(prometheusService, 'disableAlertmanagerConfig').and.callFake(() => {
+ expect(expectedStatus).toBe(true);
+ done();
+ });
+
+ if (!expectedStatus) {
+ expect(disableFn).not.toHaveBeenCalled();
+ done();
+ }
+
+ service.getAlerts();
+ };
+
+ it('disables on 504 error which is thrown if the mgr failed', (done) => {
+ isDisabledByStatusCode(504, true, done);
+ });
+
+ it('disables on 404 error which is thrown if the external api cannot be reached', (done) => {
+ isDisabledByStatusCode(404, true, done);
+ });
+
+ it('does not disable on 400 error which is thrown if the external api receives unexpected data', (done) => {
+ isDisabledByStatusCode(400, false, done);
+ });
+ });
+
+ it('should flatten the response of getRules()', () => {
+ service = TestBed.get(PrometheusAlertService);
+ prometheusService = TestBed.get(PrometheusService);
+
+ spyOn(service['prometheusService'], 'ifPrometheusConfigured').and.callFake((fn) => fn());
+ spyOn(prometheusService, 'getRules').and.returnValue(
+ of({
+ groups: [
+ {
+ name: 'group1',
+ rules: [{ name: 'nearly_full', type: 'alerting' }]
+ },
+ {
+ name: 'test',
+ rules: [
+ { name: 'load_0', type: 'alerting' },
+ { name: 'load_1', type: 'alerting' },
+ { name: 'load_2', type: 'alerting' }
+ ]
+ }
+ ]
+ })
+ );
+
+ service.getRules();
+
+ expect(service.rules as any).toEqual([
+ { name: 'nearly_full', type: 'alerting', group: 'group1' },
+ { name: 'load_0', type: 'alerting', group: 'test' },
+ { name: 'load_1', type: 'alerting', group: 'test' },
+ { name: 'load_2', type: 'alerting', group: 'test' }
+ ]);
+ });
+
+ describe('refresh', () => {
+ beforeEach(() => {
+ service = TestBed.get(PrometheusAlertService);
+ service['alerts'] = [];
+ service['canAlertsBeNotified'] = false;
+
+ spyOn(window, 'setTimeout').and.callFake((fn: Function) => fn());
+
+ notificationService = TestBed.get(NotificationService);
+ spyOn(notificationService, 'show').and.stub();
+
+ prometheusService = TestBed.get(PrometheusService);
+ spyOn(prometheusService, 'ifAlertmanagerConfigured').and.callFake((fn) => fn());
+ spyOn(prometheusService, 'getAlerts').and.callFake(() => of(alerts));
+
+ alerts = [prometheus.createAlert('alert0')];
+ service.refresh();
+ });
+
+ it('should not notify on first call', () => {
+ expect(notificationService.show).not.toHaveBeenCalled();
+ });
+
+ it('should not notify with no change', () => {
+ service.refresh();
+ expect(notificationService.show).not.toHaveBeenCalled();
+ });
+
+ it('should notify on alert change', () => {
+ alerts = [prometheus.createAlert('alert0', 'suppressed')];
+ service.refresh();
+ expect(notificationService.show).toHaveBeenCalledWith(
+ new CdNotificationConfig(
+ NotificationType.info,
+ 'alert0 (suppressed)',
+ 'alert0 is suppressed ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ )
+ );
+ });
+
+ it('should notify on a new alert', () => {
+ alerts = [prometheus.createAlert('alert1'), prometheus.createAlert('alert0')];
+ service.refresh();
+ expect(notificationService.show).toHaveBeenCalledTimes(1);
+ expect(notificationService.show).toHaveBeenCalledWith(
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert1 (active)',
+ 'alert1 is active ' + prometheus.createLink('http://alert1'),
+ undefined,
+ 'Prometheus'
+ )
+ );
+ });
+
+ it('should notify a resolved alert if it is not there anymore', () => {
+ alerts = [];
+ service.refresh();
+ expect(notificationService.show).toHaveBeenCalledTimes(1);
+ expect(notificationService.show).toHaveBeenCalledWith(
+ new CdNotificationConfig(
+ NotificationType.success,
+ 'alert0 (resolved)',
+ 'alert0 is active ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ )
+ );
+ });
+
+ it('should call multiple times for multiple changes', () => {
+ const alert1 = prometheus.createAlert('alert1');
+ alerts.push(alert1);
+ service.refresh();
+ alerts = [alert1, prometheus.createAlert('alert2')];
+ service.refresh();
+ expect(notificationService.show).toHaveBeenCalledTimes(2);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts
new file mode 100644
index 00000000..dc1731b9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts
@@ -0,0 +1,91 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { PrometheusService } from '../api/prometheus.service';
+import {
+ AlertmanagerAlert,
+ PrometheusCustomAlert,
+ PrometheusRule
+} from '../models/prometheus-alerts';
+import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PrometheusAlertService {
+ private canAlertsBeNotified = false;
+ alerts: AlertmanagerAlert[] = [];
+ rules: PrometheusRule[] = [];
+
+ constructor(
+ private alertFormatter: PrometheusAlertFormatter,
+ private prometheusService: PrometheusService
+ ) {}
+
+ getAlerts() {
+ this.prometheusService.ifAlertmanagerConfigured(() => {
+ this.prometheusService.getAlerts().subscribe(
+ (alerts) => this.handleAlerts(alerts),
+ (resp) => {
+ if ([404, 504].includes(resp.status)) {
+ this.prometheusService.disableAlertmanagerConfig();
+ }
+ }
+ );
+ });
+ }
+
+ getRules() {
+ this.prometheusService.ifPrometheusConfigured(() => {
+ this.prometheusService.getRules('alerting').subscribe((groups) => {
+ this.rules = groups['groups'].reduce((acc, group) => {
+ return acc.concat(
+ group.rules.map((rule) => {
+ rule.group = group.name;
+ return rule;
+ })
+ );
+ }, []);
+ });
+ });
+ }
+
+ refresh() {
+ this.getAlerts();
+ this.getRules();
+ }
+
+ private handleAlerts(alerts: AlertmanagerAlert[]) {
+ if (this.canAlertsBeNotified) {
+ this.notifyOnAlertChanges(alerts, this.alerts);
+ }
+ this.alerts = alerts;
+ this.canAlertsBeNotified = true;
+ }
+
+ private notifyOnAlertChanges(alerts: AlertmanagerAlert[], oldAlerts: AlertmanagerAlert[]) {
+ const changedAlerts = this.getChangedAlerts(
+ this.alertFormatter.convertToCustomAlerts(alerts),
+ this.alertFormatter.convertToCustomAlerts(oldAlerts)
+ );
+ const notifications = changedAlerts.map((alert) =>
+ this.alertFormatter.convertAlertToNotification(alert)
+ );
+ this.alertFormatter.sendNotifications(notifications);
+ }
+
+ private getChangedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
+ const updatedAndNew = _.differenceWith(alerts, oldAlerts, _.isEqual);
+ return updatedAndNew.concat(this.getVanishedAlerts(alerts, oldAlerts));
+ }
+
+ private getVanishedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
+ return _.differenceWith(oldAlerts, alerts, (a, b) => a.fingerprint === b.fingerprint).map(
+ (alert) => {
+ alert.status = 'resolved';
+ return alert;
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.spec.ts
new file mode 100644
index 00000000..f8d70d1d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.spec.ts
@@ -0,0 +1,232 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import { ToastrModule, ToastrService } from 'ngx-toastr';
+import { of, throwError } from 'rxjs';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../testing/unit-test-helper';
+import { PrometheusService } from '../api/prometheus.service';
+import { NotificationType } from '../enum/notification-type.enum';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { AlertmanagerNotification } from '../models/prometheus-alerts';
+import { SharedModule } from '../shared.module';
+import { NotificationService } from './notification.service';
+import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
+import { PrometheusNotificationService } from './prometheus-notification.service';
+
+describe('PrometheusNotificationService', () => {
+ let service: PrometheusNotificationService;
+ let notificationService: NotificationService;
+ let notifications: AlertmanagerNotification[];
+ let prometheusService: PrometheusService;
+ let prometheus: PrometheusHelper;
+ let shown: CdNotificationConfig[];
+ let getNotificationSinceMock: Function;
+
+ const toastFakeService = {
+ error: () => true,
+ info: () => true,
+ success: () => true
+ };
+
+ configureTestBed({
+ imports: [ToastrModule.forRoot(), SharedModule, HttpClientTestingModule],
+ providers: [
+ PrometheusNotificationService,
+ PrometheusAlertFormatter,
+ i18nProviders,
+ { provide: ToastrService, useValue: toastFakeService }
+ ]
+ });
+
+ beforeEach(() => {
+ prometheus = new PrometheusHelper();
+
+ service = TestBed.get(PrometheusNotificationService);
+ service['notifications'] = [];
+
+ notificationService = TestBed.get(NotificationService);
+ shown = [];
+ spyOn(notificationService, 'show').and.callThrough();
+ spyOn(notificationService, 'save').and.callFake((n) => shown.push(n));
+
+ spyOn(window, 'setTimeout').and.callFake((fn: Function) => fn());
+
+ prometheusService = TestBed.get(PrometheusService);
+ getNotificationSinceMock = () => of(notifications);
+ spyOn(prometheusService, 'getNotifications').and.callFake(() => getNotificationSinceMock());
+
+ notifications = [prometheus.createNotification()];
+ });
+
+ it('should create', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('getLastNotification', () => {
+ it('returns an empty object on the first call', () => {
+ service.refresh();
+ expect(prometheusService.getNotifications).toHaveBeenCalledWith(undefined);
+ expect(service['notifications'].length).toBe(1);
+ });
+
+ it('returns last notification on any other call', () => {
+ service.refresh();
+ notifications = [prometheus.createNotification(1, 'resolved')];
+ service.refresh();
+ expect(prometheusService.getNotifications).toHaveBeenCalledWith(service['notifications'][0]);
+ expect(service['notifications'].length).toBe(2);
+
+ notifications = [prometheus.createNotification(2)];
+ service.refresh();
+ notifications = [prometheus.createNotification(3, 'resolved')];
+ service.refresh();
+ expect(prometheusService.getNotifications).toHaveBeenCalledWith(service['notifications'][2]);
+ expect(service['notifications'].length).toBe(4);
+ });
+ });
+
+ it('notifies not on the first call', () => {
+ service.refresh();
+ expect(notificationService.save).not.toHaveBeenCalled();
+ });
+
+ it('notifies should not call the api again if it failed once', () => {
+ getNotificationSinceMock = () => throwError(new Error('Test error'));
+ service.refresh();
+ expect(prometheusService.getNotifications).toHaveBeenCalledTimes(1);
+ expect(service['backendFailure']).toBe(true);
+ service.refresh();
+ expect(prometheusService.getNotifications).toHaveBeenCalledTimes(1);
+ service['backendFailure'] = false;
+ });
+
+ describe('looks of fired notifications', () => {
+ const asyncRefresh = () => {
+ service.refresh();
+ tick(20);
+ };
+
+ const expectShown = (expected: {}[]) => {
+ tick(500);
+ expect(shown.length).toBe(expected.length);
+ expected.forEach((e, i) =>
+ Object.keys(e).forEach((key) => expect(shown[i][key]).toEqual(expected[i][key]))
+ );
+ };
+
+ beforeEach(() => {
+ service.refresh();
+ });
+
+ it('notifies on the second call', () => {
+ service.refresh();
+ expect(notificationService.show).toHaveBeenCalledTimes(1);
+ });
+
+ it('notify looks on single notification with single alert like', fakeAsync(() => {
+ asyncRefresh();
+ expectShown([
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert0 (active)',
+ 'alert0 is firing ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ )
+ ]);
+ }));
+
+ it('raises multiple pop overs for a single notification with multiple alerts', fakeAsync(() => {
+ asyncRefresh();
+ notifications[0].alerts.push(prometheus.createNotificationAlert('alert1', 'resolved'));
+ asyncRefresh();
+ expectShown([
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert0 (active)',
+ 'alert0 is firing ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ ),
+ new CdNotificationConfig(
+ NotificationType.success,
+ 'alert1 (resolved)',
+ 'alert1 is resolved ' + prometheus.createLink('http://alert1'),
+ undefined,
+ 'Prometheus'
+ )
+ ]);
+ }));
+
+ it('should raise multiple notifications if they do not look like each other', fakeAsync(() => {
+ notifications[0].alerts.push(prometheus.createNotificationAlert('alert1'));
+ notifications.push(prometheus.createNotification());
+ notifications[1].alerts.push(prometheus.createNotificationAlert('alert2'));
+ asyncRefresh();
+ expectShown([
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert0 (active)',
+ 'alert0 is firing ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ ),
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert1 (active)',
+ 'alert1 is firing ' + prometheus.createLink('http://alert1'),
+ undefined,
+ 'Prometheus'
+ ),
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert2 (active)',
+ 'alert2 is firing ' + prometheus.createLink('http://alert2'),
+ undefined,
+ 'Prometheus'
+ )
+ ]);
+ }));
+
+ it('only shows toasties if it got new data', () => {
+ service.refresh();
+ expect(notificationService.save).toHaveBeenCalledTimes(1);
+ notifications = [];
+ service.refresh();
+ service.refresh();
+ expect(notificationService.save).toHaveBeenCalledTimes(1);
+ notifications = [prometheus.createNotification()];
+ service.refresh();
+ expect(notificationService.save).toHaveBeenCalledTimes(2);
+ service.refresh();
+ expect(notificationService.save).toHaveBeenCalledTimes(3);
+ });
+
+ it('filters out duplicated and non user visible changes in notifications', fakeAsync(() => {
+ asyncRefresh();
+ // Return 2 notifications with 3 duplicated alerts and 1 non visible changed alert
+ const secondAlert = prometheus.createNotificationAlert('alert0');
+ secondAlert.endsAt = new Date().toString(); // Should be ignored as it's not visible
+ notifications[0].alerts.push(secondAlert);
+ notifications.push(prometheus.createNotification());
+ notifications[1].alerts.push(prometheus.createNotificationAlert('alert0'));
+ notifications[1].notified = 'by somebody else';
+ asyncRefresh();
+
+ expectShown([
+ new CdNotificationConfig(
+ NotificationType.error,
+ 'alert0 (active)',
+ 'alert0 is firing ' + prometheus.createLink('http://alert0'),
+ undefined,
+ 'Prometheus'
+ )
+ ]);
+ }));
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.ts
new file mode 100644
index 00000000..d2b35b25
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-notification.service.ts
@@ -0,0 +1,53 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { PrometheusService } from '../api/prometheus.service';
+import { CdNotificationConfig } from '../models/cd-notification';
+import { AlertmanagerNotification } from '../models/prometheus-alerts';
+import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PrometheusNotificationService {
+ private notifications: AlertmanagerNotification[];
+ private backendFailure = false;
+
+ constructor(
+ private alertFormatter: PrometheusAlertFormatter,
+ private prometheusService: PrometheusService
+ ) {
+ this.notifications = [];
+ }
+
+ refresh() {
+ if (this.backendFailure) {
+ return;
+ }
+ this.prometheusService
+ .getNotifications(_.last(this.notifications))
+ .subscribe(
+ (notifications) => this.handleNotifications(notifications),
+ () => (this.backendFailure = true)
+ );
+ }
+
+ private handleNotifications(notifications: AlertmanagerNotification[]) {
+ if (notifications.length === 0) {
+ return;
+ }
+ if (this.notifications.length > 0) {
+ this.alertFormatter.sendNotifications(
+ _.flatten(notifications.map((notification) => this.formatNotification(notification)))
+ );
+ }
+ this.notifications = this.notifications.concat(notifications);
+ }
+
+ private formatNotification(notification: AlertmanagerNotification): CdNotificationConfig[] {
+ return this.alertFormatter
+ .convertToCustomAlerts(notification.alerts)
+ .map((alert) => this.alertFormatter.convertAlertToNotification(alert));
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.spec.ts
new file mode 100644
index 00000000..684a7daa
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.spec.ts
@@ -0,0 +1,133 @@
+import { TestBed } from '@angular/core/testing';
+
+import {
+ configureTestBed,
+ i18nProviders,
+ PrometheusHelper
+} from '../../../testing/unit-test-helper';
+import { PrometheusRule } from '../models/prometheus-alerts';
+import { SharedModule } from '../shared.module';
+import { PrometheusSilenceMatcherService } from './prometheus-silence-matcher.service';
+
+describe('PrometheusSilenceMatcherService', () => {
+ let service: PrometheusSilenceMatcherService;
+ let prometheus: PrometheusHelper;
+ let rules: PrometheusRule[];
+
+ configureTestBed({
+ imports: [SharedModule],
+ providers: [i18nProviders]
+ });
+
+ const addMatcher = (name, value) => ({
+ name: name,
+ value: value,
+ isRegex: false
+ });
+
+ beforeEach(() => {
+ prometheus = new PrometheusHelper();
+ service = TestBed.get(PrometheusSilenceMatcherService);
+ rules = [
+ prometheus.createRule('alert0', 'someSeverity', [prometheus.createAlert('alert0')]),
+ prometheus.createRule('alert1', 'someSeverity', []),
+ prometheus.createRule('alert2', 'someOtherSeverity', [prometheus.createAlert('alert2')])
+ ];
+ });
+
+ it('should create', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('test rule matching with one matcher', () => {
+ const expectSingleMatch = (name, value, helpText, successClass: boolean) => {
+ const match = service.singleMatch(addMatcher(name, value), rules);
+ expect(match.status).toBe(helpText);
+ expect(match.cssClass).toBe(successClass ? 'has-success' : 'has-warning');
+ };
+
+ it('should match no rule and no alert', () => {
+ expectSingleMatch(
+ 'alertname',
+ 'alert',
+ 'Your matcher seems to match no currently defined rule or active alert.',
+ false
+ );
+ });
+
+ it('should match a rule with no alert', () => {
+ expectSingleMatch('alertname', 'alert1', 'Matches 1 rule with no active alerts.', false);
+ });
+
+ it('should match a rule and an alert', () => {
+ expectSingleMatch('alertname', 'alert0', 'Matches 1 rule with 1 active alert.', true);
+ });
+
+ it('should match multiple rules and an alert', () => {
+ expectSingleMatch('severity', 'someSeverity', 'Matches 2 rules with 1 active alert.', true);
+ });
+
+ it('should match multiple rules and multiple alerts', () => {
+ expectSingleMatch('job', 'someJob', 'Matches 2 rules with 2 active alerts.', true);
+ });
+
+ it('should return any match if regex is checked', () => {
+ const match = service.singleMatch(
+ {
+ name: 'severity',
+ value: 'someSeverity',
+ isRegex: true
+ },
+ rules
+ );
+ expect(match).toBeFalsy();
+ });
+ });
+
+ describe('test rule matching with multiple matcher', () => {
+ const expectMultiMatch = (matchers, helpText, successClass: boolean) => {
+ const match = service.multiMatch(matchers, rules);
+ expect(match.status).toBe(helpText);
+ expect(match.cssClass).toBe(successClass ? 'has-success' : 'has-warning');
+ };
+
+ it('should match no rule and no alert', () => {
+ expectMultiMatch(
+ [addMatcher('alertname', 'alert0'), addMatcher('job', 'ceph')],
+ 'Your matcher seems to match no currently defined rule or active alert.',
+ false
+ );
+ });
+
+ it('should match a rule with no alert', () => {
+ expectMultiMatch(
+ [addMatcher('severity', 'someSeverity'), addMatcher('alertname', 'alert1')],
+ 'Matches 1 rule with no active alerts.',
+ false
+ );
+ });
+
+ it('should match a rule and an alert', () => {
+ expectMultiMatch(
+ [addMatcher('instance', 'someInstance'), addMatcher('alertname', 'alert0')],
+ 'Matches 1 rule with 1 active alert.',
+ true
+ );
+ });
+
+ it('should return any match if regex is checked', () => {
+ const match = service.multiMatch(
+ [
+ addMatcher('instance', 'someInstance'),
+ {
+ name: 'severity',
+ value: 'someSeverity',
+ isRegex: true
+ }
+ ],
+ rules
+ );
+ expect(match).toBeFalsy();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.ts
new file mode 100644
index 00000000..c9bb9729
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-silence-matcher.service.ts
@@ -0,0 +1,82 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import {
+ AlertmanagerSilenceMatcher,
+ AlertmanagerSilenceMatcherMatch
+} from '../models/alertmanager-silence';
+import { PrometheusRule } from '../models/prometheus-alerts';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PrometheusSilenceMatcherService {
+ private valueAttributePath = {
+ alertname: 'name',
+ instance: 'alerts.0.labels.instance',
+ job: 'alerts.0.labels.job',
+ severity: 'labels.severity'
+ };
+
+ constructor(private i18n: I18n) {}
+
+ singleMatch(
+ matcher: AlertmanagerSilenceMatcher,
+ rules: PrometheusRule[]
+ ): AlertmanagerSilenceMatcherMatch {
+ return this.multiMatch([matcher], rules);
+ }
+
+ multiMatch(
+ matchers: AlertmanagerSilenceMatcher[],
+ rules: PrometheusRule[]
+ ): AlertmanagerSilenceMatcherMatch {
+ if (matchers.some((matcher) => matcher.isRegex)) {
+ return;
+ }
+ matchers.forEach((matcher) => {
+ rules = this.getMatchedRules(matcher, rules);
+ });
+ return this.describeMatch(rules);
+ }
+
+ private getMatchedRules(
+ matcher: AlertmanagerSilenceMatcher,
+ rules: PrometheusRule[]
+ ): PrometheusRule[] {
+ const attributePath = this.getAttributePath(matcher.name);
+ return rules.filter((r) => _.get(r, attributePath) === matcher.value);
+ }
+
+ private describeMatch(rules: PrometheusRule[]): AlertmanagerSilenceMatcherMatch {
+ let alerts = 0;
+ rules.forEach((r) => (alerts += r.alerts.length));
+ return {
+ status: this.getMatchText(rules.length, alerts),
+ cssClass: alerts ? 'has-success' : 'has-warning'
+ };
+ }
+
+ getAttributePath(name: string): string {
+ return this.valueAttributePath[name];
+ }
+
+ private getMatchText(rules: number, alerts: number): string {
+ const msg = {
+ noRule: this.i18n('Your matcher seems to match no currently defined rule or active alert.'),
+ noAlerts: this.i18n('no active alerts'),
+ alert: this.i18n('1 active alert'),
+ alerts: this.i18n('{{n}} active alerts', { n: alerts }),
+ rule: this.i18n('Matches 1 rule'),
+ rules: this.i18n('Matches {{n}} rules', { n: rules })
+ };
+ return rules
+ ? this.i18n('{{rules}} with {{alerts}}.', {
+ rules: rules > 1 ? msg.rules : msg.rule,
+ alerts: alerts ? (alerts > 1 ? msg.alerts : msg.alert) : msg.noAlerts
+ })
+ : msg.noRule;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.spec.ts
new file mode 100644
index 00000000..3b9c0437
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.spec.ts
@@ -0,0 +1,45 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { RbdConfigurationType } from '../models/configuration';
+import { RbdConfigurationService } from './rbd-configuration.service';
+
+describe('RbdConfigurationService', () => {
+ let service: RbdConfigurationService;
+
+ configureTestBed({
+ providers: [RbdConfigurationService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(RbdConfigurationService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should filter config options', () => {
+ const result = service.getOptionByName('rbd_qos_write_iops_burst');
+ expect(result).toEqual({
+ name: 'rbd_qos_write_iops_burst',
+ displayName: 'Write IOPS Burst',
+ description: 'The desired burst limit of write operations.',
+ type: RbdConfigurationType.iops
+ });
+ });
+
+ it('should return the display name', () => {
+ const displayName = service.getDisplayName('rbd_qos_write_iops_burst');
+ expect(displayName).toBe('Write IOPS Burst');
+ });
+
+ it('should return the description', () => {
+ const description = service.getDescription('rbd_qos_write_iops_burst');
+ expect(description).toBe('The desired burst limit of write operations.');
+ });
+
+ it('should have a class for each section', () => {
+ service.sections.forEach((section) => expect(section.class).toBeTruthy());
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.ts
new file mode 100644
index 00000000..10a0ac70
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/rbd-configuration.service.ts
@@ -0,0 +1,146 @@
+import { Injectable } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import {
+ RbdConfigurationExtraField,
+ RbdConfigurationSection,
+ RbdConfigurationType
+} from '../models/configuration';
+
+/**
+ * Define here which options should be made available under which section heading.
+ * The display name and description needs to be added manually as long as Ceph does not provide
+ * this information.
+ */
+@Injectable({
+ providedIn: 'root'
+})
+export class RbdConfigurationService {
+ readonly sections: RbdConfigurationSection[];
+
+ constructor(private i18n: I18n) {
+ this.sections = [
+ {
+ heading: this.i18n('Quality of Service'),
+ class: 'quality-of-service',
+ options: [
+ {
+ name: 'rbd_qos_bps_limit',
+ displayName: this.i18n('BPS Limit'),
+ description: this.i18n('The desired limit of IO bytes per second.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_iops_limit',
+ displayName: this.i18n('IOPS Limit'),
+ description: this.i18n('The desired limit of IO operations per second.'),
+ type: RbdConfigurationType.iops
+ },
+ {
+ name: 'rbd_qos_read_bps_limit',
+ displayName: this.i18n('Read BPS Limit'),
+ description: this.i18n('The desired limit of read bytes per second.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_read_iops_limit',
+ displayName: this.i18n('Read IOPS Limit'),
+ description: this.i18n('The desired limit of read operations per second.'),
+ type: RbdConfigurationType.iops
+ },
+ {
+ name: 'rbd_qos_write_bps_limit',
+ displayName: this.i18n('Write BPS Limit'),
+ description: this.i18n('The desired limit of write bytes per second.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_write_iops_limit',
+ displayName: this.i18n('Write IOPS Limit'),
+ description: this.i18n('The desired limit of write operations per second.'),
+ type: RbdConfigurationType.iops
+ },
+ {
+ name: 'rbd_qos_bps_burst',
+ displayName: this.i18n('BPS Burst'),
+ description: this.i18n('The desired burst limit of IO bytes.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_iops_burst',
+ displayName: this.i18n('IOPS Burst'),
+ description: this.i18n('The desired burst limit of IO operations.'),
+ type: RbdConfigurationType.iops
+ },
+ {
+ name: 'rbd_qos_read_bps_burst',
+ displayName: this.i18n('Read BPS Burst'),
+ description: this.i18n('The desired burst limit of read bytes.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_read_iops_burst',
+ displayName: this.i18n('Read IOPS Burst'),
+ description: this.i18n('The desired burst limit of read operations.'),
+ type: RbdConfigurationType.iops
+ },
+ {
+ name: 'rbd_qos_write_bps_burst',
+ displayName: this.i18n('Write BPS Burst'),
+ description: this.i18n('The desired burst limit of write bytes.'),
+ type: RbdConfigurationType.bps
+ },
+ {
+ name: 'rbd_qos_write_iops_burst',
+ displayName: this.i18n('Write IOPS Burst'),
+ description: this.i18n('The desired burst limit of write operations.'),
+ type: RbdConfigurationType.iops
+ }
+ ] as RbdConfigurationExtraField[]
+ }
+ ];
+ }
+
+ private static getOptionsFromSections(sections: RbdConfigurationSection[]) {
+ return sections.map((section) => section.options).reduce((a, b) => a.concat(b));
+ }
+
+ private filterConfigOptionsByName(configName: string) {
+ return RbdConfigurationService.getOptionsFromSections(this.sections).filter(
+ (option) => option.name === configName
+ );
+ }
+
+ private getOptionValueByName(configName: string, fieldName: string, defaultValue = '') {
+ const configOptions = this.filterConfigOptionsByName(configName);
+ return configOptions.length === 1 ? configOptions.pop()[fieldName] : defaultValue;
+ }
+
+ getWritableSections() {
+ return this.sections.map((section) => {
+ section.options = section.options.filter((o) => !o.readOnly);
+ return section;
+ });
+ }
+
+ getOptionFields() {
+ return RbdConfigurationService.getOptionsFromSections(this.sections);
+ }
+
+ getWritableOptionFields() {
+ return RbdConfigurationService.getOptionsFromSections(this.getWritableSections());
+ }
+
+ getOptionByName(optionName: string): RbdConfigurationExtraField {
+ return this.filterConfigOptionsByName(optionName).pop();
+ }
+
+ getDisplayName(configName: string): string {
+ return this.getOptionValueByName(configName, 'displayName');
+ }
+
+ getDescription(configName: string): string {
+ return this.getOptionValueByName(configName, 'description');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.spec.ts
new file mode 100644
index 00000000..da55b44f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.spec.ts
@@ -0,0 +1,45 @@
+import { fakeAsync, tick } from '@angular/core/testing';
+
+import { RefreshIntervalService } from './refresh-interval.service';
+
+describe('RefreshIntervalService', () => {
+ let service: RefreshIntervalService;
+
+ beforeEach(() => {
+ service = new RefreshIntervalService();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should initial private interval time right', () => {
+ sessionStorage.setItem('dashboard_interval', '10000');
+ service = new RefreshIntervalService();
+ expect(service.getRefreshInterval()).toBe(10000);
+ });
+
+ describe('setRefreshInterval', () => {
+ let notifyCount: number;
+
+ it('should send notification to component at correct interval time when interval changed', fakeAsync(() => {
+ service.intervalData$.subscribe(() => {
+ notifyCount++;
+ });
+
+ notifyCount = 0;
+ service.setRefreshInterval(10000);
+ tick(10000);
+ expect(service.getRefreshInterval()).toBe(10000);
+ expect(notifyCount).toBe(1);
+
+ notifyCount = 0;
+ service.setRefreshInterval(30000);
+ tick(30000);
+ expect(service.getRefreshInterval()).toBe(30000);
+ expect(notifyCount).toBe(1);
+
+ service.ngOnDestroy();
+ }));
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.ts
new file mode 100644
index 00000000..0627d78e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/refresh-interval.service.ts
@@ -0,0 +1,42 @@
+import { Injectable, OnDestroy } from '@angular/core';
+
+import { BehaviorSubject, interval, Subscription } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class RefreshIntervalService implements OnDestroy {
+ private intervalTime: number;
+ // Observable sources
+ private intervalDataSource = new BehaviorSubject(null);
+ private intervalSubscription: Subscription;
+ // Observable streams
+ intervalData$ = this.intervalDataSource.asObservable();
+
+ constructor() {
+ const initialInterval = parseInt(sessionStorage.getItem('dashboard_interval'), 10) || 5000;
+ this.setRefreshInterval(initialInterval);
+ }
+
+ setRefreshInterval(newInterval: number) {
+ this.intervalTime = newInterval;
+ sessionStorage.setItem('dashboard_interval', newInterval.toString());
+
+ if (this.intervalSubscription) {
+ this.intervalSubscription.unsubscribe();
+ }
+ this.intervalSubscription = interval(this.intervalTime).subscribe(() =>
+ this.intervalDataSource.next(this.intervalTime)
+ );
+ }
+
+ getRefreshInterval() {
+ return this.intervalTime;
+ }
+
+ ngOnDestroy() {
+ if (this.intervalSubscription) {
+ this.intervalSubscription.unsubscribe();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.spec.ts
new file mode 100644
index 00000000..76a0a0f8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.spec.ts
@@ -0,0 +1,117 @@
+import { HttpClient } from '@angular/common/http';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { of as observableOf, Subscriber } from 'rxjs';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { ExecutingTask } from '../models/executing-task';
+import { AuthStorageService } from './auth-storage.service';
+import { SummaryService } from './summary.service';
+
+describe('SummaryService', () => {
+ let summaryService: SummaryService;
+ let authStorageService: AuthStorageService;
+
+ const summary = {
+ executing_tasks: [],
+ health_status: 'HEALTH_OK',
+ mgr_id: 'x',
+ rbd_mirroring: { errors: 0, warnings: 0 },
+ rbd_pools: [],
+ have_mon_connection: true,
+ finished_tasks: [],
+ filesystems: [{ id: 1, name: 'cephfs_a' }]
+ };
+
+ const httpClientSpy = {
+ get: () => observableOf(summary)
+ };
+
+ configureTestBed({
+ imports: [RouterTestingModule],
+ providers: [
+ SummaryService,
+ AuthStorageService,
+ { provide: HttpClient, useValue: httpClientSpy }
+ ]
+ });
+
+ beforeEach(() => {
+ summaryService = TestBed.get(SummaryService);
+ authStorageService = TestBed.get(AuthStorageService);
+ });
+
+ it('should be created', () => {
+ expect(summaryService).toBeTruthy();
+ });
+
+ it('should call refresh', fakeAsync(() => {
+ summaryService.enablePolling();
+ authStorageService.set('foobar', undefined);
+ const calledWith = [];
+ summaryService.subscribe((data) => {
+ calledWith.push(data);
+ });
+ expect(calledWith).toEqual([summary]);
+ summaryService.refresh();
+ expect(calledWith).toEqual([summary, summary]);
+ tick(10000);
+ expect(calledWith.length).toEqual(4);
+ // In order to not trigger setInterval again,
+ // which would raise 'Error: 1 timer(s) still in the queue.'
+ window.clearInterval(summaryService.polling);
+ }));
+
+ describe('Should test methods after first refresh', () => {
+ beforeEach(() => {
+ authStorageService.set('foobar', undefined);
+ summaryService.refresh();
+ });
+
+ it('should call getCurrentSummary', () => {
+ expect(summaryService.getCurrentSummary()).toEqual(summary);
+ });
+
+ it('should call subscribe', () => {
+ let result;
+ const subscriber = summaryService.subscribe((data) => {
+ result = data;
+ });
+ expect(subscriber).toEqual(jasmine.any(Subscriber));
+ expect(result).toEqual(summary);
+ });
+
+ it('should call addRunningTask', () => {
+ summaryService.addRunningTask(
+ new ExecutingTask('rbd/delete', {
+ pool_name: 'somePool',
+ image_name: 'someImage'
+ })
+ );
+ const result = summaryService.getCurrentSummary();
+ expect(result.executing_tasks.length).toBe(1);
+ expect(result.executing_tasks[0]).toEqual({
+ metadata: { image_name: 'someImage', pool_name: 'somePool' },
+ name: 'rbd/delete'
+ });
+ });
+
+ it('should call addRunningTask with duplicate task', () => {
+ let result = summaryService.getCurrentSummary();
+ const exec_task = new ExecutingTask('rbd/delete', {
+ pool_name: 'somePool',
+ image_name: 'someImage'
+ });
+
+ result.executing_tasks = [exec_task];
+ summaryService['summaryDataSource'].next(result);
+ result = summaryService.getCurrentSummary();
+ expect(result.executing_tasks.length).toBe(1);
+
+ summaryService.addRunningTask(exec_task);
+ result = summaryService.getCurrentSummary();
+ expect(result.executing_tasks.length).toBe(1);
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.ts
new file mode 100644
index 00000000..8124ecc8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/summary.service.ts
@@ -0,0 +1,85 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable, NgZone } from '@angular/core';
+import { Router } from '@angular/router';
+
+import * as _ from 'lodash';
+import { BehaviorSubject, Subscription } from 'rxjs';
+
+import { ExecutingTask } from '../models/executing-task';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SummaryService {
+ // Observable sources
+ private summaryDataSource = new BehaviorSubject(null);
+
+ // Observable streams
+ summaryData$ = this.summaryDataSource.asObservable();
+
+ polling: number;
+
+ constructor(private http: HttpClient, private router: Router, private ngZone: NgZone) {
+ this.enablePolling();
+ }
+
+ enablePolling() {
+ this.refresh();
+
+ this.ngZone.runOutsideAngular(() => {
+ this.polling = window.setInterval(() => {
+ this.ngZone.run(() => {
+ this.refresh();
+ });
+ }, 5000);
+ });
+ }
+
+ refresh() {
+ if (this.router.url !== '/login') {
+ this.http.get('api/summary').subscribe((data) => {
+ this.summaryDataSource.next(data);
+ });
+ }
+ }
+
+ /**
+ * Returns the current value of summaryData
+ */
+ getCurrentSummary(): { [key: string]: any; executing_tasks: object[] } {
+ return this.summaryDataSource.getValue();
+ }
+
+ /**
+ * Subscribes to the summaryData,
+ * which is updated once every 5 seconds or when a new task is created.
+ */
+ subscribe(next: (summary: any) => void, error?: (error: any) => void): Subscription {
+ return this.summaryData$.subscribe(next, error);
+ }
+
+ /**
+ * Inserts a newly created task to the local list of executing tasks.
+ * After that, it will automatically push that new information
+ * to all subscribers.
+ */
+ addRunningTask(task: ExecutingTask) {
+ const current = this.summaryDataSource.getValue();
+ if (!current) {
+ return;
+ }
+
+ if (_.isArray(current.executing_tasks)) {
+ const exists = current.executing_tasks.find((element) => {
+ return element.name === task.name && _.isEqual(element.metadata, task.metadata);
+ });
+ if (!exists) {
+ current.executing_tasks.push(task);
+ }
+ } else {
+ current.executing_tasks = [task];
+ }
+
+ this.summaryDataSource.next(current);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.spec.ts
new file mode 100644
index 00000000..0abee40c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.spec.ts
@@ -0,0 +1,136 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { of } from 'rxjs';
+
+import {
+ configureTestBed,
+ expectItemTasks,
+ i18nProviders
+} from '../../../testing/unit-test-helper';
+import { ExecutingTask } from '../models/executing-task';
+import { SummaryService } from './summary.service';
+import { TaskListService } from './task-list.service';
+import { TaskMessageService } from './task-message.service';
+
+describe('TaskListService', () => {
+ let service: TaskListService;
+ let summaryService: SummaryService;
+ let taskMessageService: TaskMessageService;
+
+ let list: any[];
+ let apiResp: any;
+ let tasks: any[];
+
+ const addItem = (name) => {
+ apiResp.push({ name: name });
+ };
+
+ configureTestBed({
+ providers: [TaskListService, TaskMessageService, SummaryService, i18nProviders],
+ imports: [HttpClientTestingModule, RouterTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(TaskListService);
+ summaryService = TestBed.get(SummaryService);
+ taskMessageService = TestBed.get(TaskMessageService);
+ summaryService['summaryDataSource'].next({ executing_tasks: [] });
+
+ taskMessageService.messages['test/create'] = taskMessageService.messages['rbd/create'];
+ taskMessageService.messages['test/edit'] = taskMessageService.messages['rbd/edit'];
+ taskMessageService.messages['test/delete'] = taskMessageService.messages['rbd/delete'];
+
+ tasks = [];
+ apiResp = [];
+ list = [];
+ addItem('a');
+ addItem('b');
+ addItem('c');
+
+ service.init(
+ () => of(apiResp),
+ undefined,
+ (updatedList) => (list = updatedList),
+ () => true,
+ (task) => task.name.startsWith('test'),
+ (item, task) => item.name === task.metadata['name'],
+ {
+ default: (task) => ({ name: task.metadata['name'] })
+ }
+ );
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ const addTask = (name: string, itemName: string, progress?: number) => {
+ const task = new ExecutingTask();
+ task.name = name;
+ task.progress = progress;
+ task.metadata = { name: itemName };
+ tasks.push(task);
+ summaryService.addRunningTask(task);
+ };
+
+ it('gets all items without any executing items', () => {
+ expect(list.length).toBe(3);
+ expect(list.every((item) => !item.cdExecuting)).toBeTruthy();
+ });
+
+ it('gets an item from a task during creation', () => {
+ addTask('test/create', 'd');
+ expect(list.length).toBe(4);
+ expectItemTasks(list[3], 'Creating');
+ });
+
+ it('shows progress of current task if any above 0', () => {
+ addTask('test/edit', 'd', 97);
+ addTask('test/edit', 'e', 0);
+ expect(list.length).toBe(5);
+ expectItemTasks(list[3], 'Updating', 97);
+ expectItemTasks(list[4], 'Updating');
+ });
+
+ it('gets all items with one executing items', () => {
+ addTask('test/create', 'a');
+ expect(list.length).toBe(3);
+ expectItemTasks(list[0], 'Creating');
+ expectItemTasks(list[1], undefined);
+ expectItemTasks(list[2], undefined);
+ });
+
+ it('gets all items with multiple executing items', () => {
+ addTask('test/create', 'a');
+ addTask('test/edit', 'a');
+ addTask('test/delete', 'a');
+ addTask('test/edit', 'b');
+ addTask('test/delete', 'b');
+ addTask('test/delete', 'c');
+ expect(list.length).toBe(3);
+ expectItemTasks(list[0], 'Creating..., Updating..., Deleting');
+ expectItemTasks(list[1], 'Updating..., Deleting');
+ expectItemTasks(list[2], 'Deleting');
+ });
+
+ it('gets all items with multiple executing tasks (not only item tasks', () => {
+ addTask('rbd/create', 'a');
+ addTask('rbd/edit', 'a');
+ addTask('test/delete', 'a');
+ addTask('test/edit', 'b');
+ addTask('rbd/delete', 'b');
+ addTask('rbd/delete', 'c');
+ expect(list.length).toBe(3);
+ expectItemTasks(list[0], 'Deleting');
+ expectItemTasks(list[1], 'Updating');
+ expectItemTasks(list[2], undefined);
+ });
+
+ it('should call ngOnDestroy', () => {
+ expect(service.summaryDataSubscription.closed).toBeFalsy();
+ service.ngOnDestroy();
+ expect(service.summaryDataSubscription.closed).toBeTruthy();
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts
new file mode 100644
index 00000000..28024827
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts
@@ -0,0 +1,106 @@
+import { Injectable, OnDestroy } from '@angular/core';
+
+import { Observable, Subscription } from 'rxjs';
+
+import { ExecutingTask } from '../models/executing-task';
+import { SummaryService } from './summary.service';
+import { TaskMessageService } from './task-message.service';
+
+@Injectable()
+export class TaskListService implements OnDestroy {
+ summaryDataSubscription: Subscription;
+
+ getUpdate: () => Observable<object>;
+ preProcessing: (_: any) => any[];
+ setList: (_: any[]) => void;
+ onFetchError: (error: any) => void;
+ taskFilter: (task: ExecutingTask) => boolean;
+ itemFilter: (item, task: ExecutingTask) => boolean;
+ builders: object;
+
+ constructor(
+ private taskMessageService: TaskMessageService,
+ private summaryService: SummaryService
+ ) {}
+
+ /**
+ * @param {() => Observable<object>} getUpdate Method that calls the api and
+ * returns that without subscribing.
+ * @param {(_: any) => any[]} preProcessing Method executed before merging
+ * Tasks with Items
+ * @param {(_: any[]) => void} setList Method used to update array of item in the component.
+ * @param {(error: any) => void} onFetchError Method called when there were
+ * problems while fetching data.
+ * @param {(task: ExecutingTask) => boolean} taskFilter callback used in tasks_array.filter()
+ * @param {(item, task: ExecutingTask) => boolean} itemFilter callback used in
+ * items_array.filter()
+ * @param {object} builders
+ * object with builders for each type of task.
+ * You can also use a 'default' one.
+ * @memberof TaskListService
+ */
+ init(
+ getUpdate: () => Observable<object>,
+ preProcessing: (_: any) => any[],
+ setList: (_: any[]) => void,
+ onFetchError: (error: any) => void,
+ taskFilter: (task: ExecutingTask) => boolean,
+ itemFilter: (item, task: ExecutingTask) => boolean,
+ builders: object
+ ) {
+ this.getUpdate = getUpdate;
+ this.preProcessing = preProcessing;
+ this.setList = setList;
+ this.onFetchError = onFetchError;
+ this.taskFilter = taskFilter;
+ this.itemFilter = itemFilter;
+ this.builders = builders || {};
+
+ this.summaryDataSubscription = this.summaryService.subscribe((tasks: any) => {
+ if (tasks) {
+ this.getUpdate().subscribe((resp: any) => {
+ this.updateData(resp, tasks.executing_tasks.filter(this.taskFilter));
+ }, this.onFetchError);
+ }
+ }, this.onFetchError);
+ }
+
+ private updateData(resp: any, tasks: ExecutingTask[]) {
+ const data: any[] = this.preProcessing ? this.preProcessing(resp) : resp;
+ this.addMissing(data, tasks);
+ data.forEach((item) => {
+ const executingTasks = tasks.filter((task) => this.itemFilter(item, task));
+ item.cdExecuting = this.getTaskAction(executingTasks);
+ });
+ this.setList(data);
+ }
+
+ private addMissing(data: any[], tasks: ExecutingTask[]) {
+ const defaultBuilder = this.builders['default'] || {};
+ tasks.forEach((task) => {
+ const existing = data.find((item) => this.itemFilter(item, task));
+ const builder = this.builders[task.name];
+ if (!existing && (builder || defaultBuilder)) {
+ data.push(builder ? builder(task.metadata) : defaultBuilder(task));
+ }
+ });
+ }
+
+ private getTaskAction(tasks: ExecutingTask[]): string {
+ if (tasks.length === 0) {
+ return;
+ }
+ return tasks
+ .map((task) => {
+ const progress = task.progress ? ` ${task.progress}%` : '';
+ return this.taskMessageService.getRunningText(task) + '...' + progress;
+ })
+ .join(', ');
+ }
+
+ ngOnDestroy() {
+ if (this.summaryDataSubscription) {
+ this.summaryDataSubscription.unsubscribe();
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.spec.ts
new file mode 100644
index 00000000..1fab5d39
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.spec.ts
@@ -0,0 +1,74 @@
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+
+import * as _ from 'lodash';
+import { BehaviorSubject } from 'rxjs';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { SummaryService } from './summary.service';
+import { TaskManagerService } from './task-manager.service';
+
+const summary = {
+ executing_tasks: [],
+ health_status: 'HEALTH_OK',
+ mgr_id: 'x',
+ rbd_mirroring: { errors: 0, warnings: 0 },
+ rbd_pools: [],
+ have_mon_connection: true,
+ finished_tasks: [{ name: 'foo', metadata: {} }],
+ filesystems: [{ id: 1, name: 'cephfs_a' }]
+};
+
+export class SummaryServiceMock {
+ summaryDataSource = new BehaviorSubject(summary);
+ summaryData$ = this.summaryDataSource.asObservable();
+
+ refresh() {
+ this.summaryDataSource.next(summary);
+ }
+ subscribe(call) {
+ return this.summaryData$.subscribe(call);
+ }
+}
+
+describe('TaskManagerService', () => {
+ let taskManagerService: TaskManagerService;
+ let summaryService: any;
+ let called: boolean;
+
+ configureTestBed(
+ {
+ providers: [TaskManagerService, { provide: SummaryService, useClass: SummaryServiceMock }]
+ },
+ true
+ );
+
+ beforeEach(() => {
+ taskManagerService = TestBed.get(TaskManagerService);
+ summaryService = TestBed.get(SummaryService);
+ called = false;
+ taskManagerService.subscribe('foo', {}, () => (called = true));
+ });
+
+ it('should be created', () => {
+ expect(taskManagerService).toBeTruthy();
+ });
+
+ it('should subscribe and be notified when task is finished', fakeAsync(() => {
+ expect(taskManagerService.subscriptions.length).toBe(1);
+ summaryService.refresh();
+ tick();
+ expect(called).toEqual(true);
+ expect(taskManagerService.subscriptions).toEqual([]);
+ }));
+
+ it('should subscribe and process executing taks', fakeAsync(() => {
+ const original_subscriptions = _.cloneDeep(taskManagerService.subscriptions);
+ _.assign(summary, {
+ executing_tasks: [{ name: 'foo', metadata: {} }],
+ finished_tasks: []
+ });
+ summaryService.refresh();
+ tick();
+ expect(taskManagerService.subscriptions).toEqual(original_subscriptions);
+ }));
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.ts
new file mode 100644
index 00000000..20ecd9d9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-manager.service.ts
@@ -0,0 +1,62 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+import { ExecutingTask } from '../models/executing-task';
+import { FinishedTask } from '../models/finished-task';
+import { Task } from '../models/task';
+import { SummaryService } from './summary.service';
+
+class TaskSubscription {
+ name: string;
+ metadata: object;
+ onTaskFinished: (finishedTask: FinishedTask) => any;
+
+ constructor(name, metadata, onTaskFinished) {
+ this.name = name;
+ this.metadata = metadata;
+ this.onTaskFinished = onTaskFinished;
+ }
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TaskManagerService {
+ subscriptions: Array<TaskSubscription> = [];
+
+ constructor(summaryService: SummaryService) {
+ summaryService.subscribe((data: any) => {
+ if (!data) {
+ return;
+ }
+ const executingTasks = data.executing_tasks;
+ const finishedTasks = data.finished_tasks;
+ const newSubscriptions: Array<TaskSubscription> = [];
+ for (const subscription of this.subscriptions) {
+ const finishedTask = <FinishedTask>this._getTask(subscription, finishedTasks);
+ const executingTask = <ExecutingTask>this._getTask(subscription, executingTasks);
+ if (finishedTask !== null && executingTask === null) {
+ subscription.onTaskFinished(finishedTask);
+ }
+ if (executingTask !== null) {
+ newSubscriptions.push(subscription);
+ }
+ this.subscriptions = newSubscriptions;
+ }
+ });
+ }
+
+ subscribe(name, metadata, onTaskFinished: (finishedTask: FinishedTask) => any) {
+ this.subscriptions.push(new TaskSubscription(name, metadata, onTaskFinished));
+ }
+
+ _getTask(subscription: TaskSubscription, tasks: Array<Task>): Task {
+ for (const task of tasks) {
+ if (task.name === subscription.name && _.isEqual(task.metadata, subscription.metadata)) {
+ return task;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.spec.ts
new file mode 100644
index 00000000..a5c22bc8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.spec.ts
@@ -0,0 +1,274 @@
+import { TestBed } from '@angular/core/testing';
+
+import * as _ from 'lodash';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { FinishedTask } from '../models/finished-task';
+import { TaskException } from '../models/task-exception';
+import { TaskMessageOperation, TaskMessageService } from './task-message.service';
+
+describe('TaskManagerMessageService', () => {
+ let service: TaskMessageService;
+ let finishedTask: FinishedTask;
+
+ configureTestBed({
+ providers: [TaskMessageService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(TaskMessageService);
+ finishedTask = new FinishedTask();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should get default description', () => {
+ expect(service.getErrorTitle(finishedTask)).toBe('Failed to execute unknown task');
+ });
+
+ it('should get default running message', () => {
+ expect(service.getRunningTitle(finishedTask)).toBe('Executing unknown task');
+ });
+
+ it('should get default running message with a set component', () => {
+ finishedTask.metadata = { component: 'rbd' };
+ expect(service.getRunningTitle(finishedTask)).toBe('Executing RBD');
+ });
+
+ it('should getSuccessMessage', () => {
+ expect(service.getSuccessTitle(finishedTask)).toBe('Executed unknown task');
+ });
+
+ describe('defined tasks messages', () => {
+ let defaultMsg: string;
+ const testMessages = (operation: TaskMessageOperation, involves: string) => {
+ expect(service.getRunningTitle(finishedTask)).toBe(operation.running + ' ' + involves);
+ expect(service.getErrorTitle(finishedTask)).toBe(
+ 'Failed to ' + operation.failure + ' ' + involves
+ );
+ expect(service.getSuccessTitle(finishedTask)).toBe(operation.success + ' ' + involves);
+ };
+
+ const testCreate = (involves: string) => {
+ testMessages(new TaskMessageOperation('Creating', 'create', 'Created'), involves);
+ };
+
+ const testUpdate = (involves: string) => {
+ testMessages(new TaskMessageOperation('Updating', 'update', 'Updated'), involves);
+ };
+
+ const testDelete = (involves: string) => {
+ testMessages(new TaskMessageOperation('Deleting', 'delete', 'Deleted'), involves);
+ };
+
+ const testErrorCode = (code: number, msg: string) => {
+ finishedTask.exception = _.assign(new TaskException(), {
+ code: code
+ });
+ expect(service.getErrorMessage(finishedTask)).toBe(msg);
+ };
+
+ describe('pool tasks', () => {
+ beforeEach(() => {
+ const metadata = {
+ pool_name: 'somePool'
+ };
+ defaultMsg = `pool '${metadata.pool_name}'`;
+ finishedTask.metadata = metadata;
+ });
+
+ it('tests pool/create messages', () => {
+ finishedTask.name = 'pool/create';
+ testCreate(defaultMsg);
+ testErrorCode(17, `Name is already used by ${defaultMsg}.`);
+ });
+
+ it('tests pool/edit messages', () => {
+ finishedTask.name = 'pool/edit';
+ testUpdate(defaultMsg);
+ testErrorCode(17, `Name is already used by ${defaultMsg}.`);
+ });
+
+ it('tests pool/delete messages', () => {
+ finishedTask.name = 'pool/delete';
+ testDelete(defaultMsg);
+ });
+ });
+
+ describe('erasure code profile tasks', () => {
+ beforeEach(() => {
+ const metadata = {
+ name: 'someEcpName'
+ };
+ defaultMsg = `erasure code profile '${metadata.name}'`;
+ finishedTask.metadata = metadata;
+ });
+
+ it('tests ecp/create messages', () => {
+ finishedTask.name = 'ecp/create';
+ testCreate(defaultMsg);
+ testErrorCode(17, `Name is already used by ${defaultMsg}.`);
+ });
+
+ it('tests ecp/delete messages', () => {
+ finishedTask.name = 'ecp/delete';
+ testDelete(defaultMsg);
+ });
+ });
+
+ describe('rbd tasks', () => {
+ let metadata;
+ let childMsg: string;
+ let destinationMsg: string;
+ let snapMsg: string;
+
+ beforeEach(() => {
+ metadata = {
+ pool_name: 'somePool',
+ image_name: 'someImage',
+ snapshot_name: 'someSnapShot',
+ dest_pool_name: 'someDestinationPool',
+ dest_image_name: 'someDestinationImage',
+ child_pool_name: 'someChildPool',
+ child_image_name: 'someChildImage',
+ new_image_name: 'newImage',
+ image_id: '12345'
+ };
+ defaultMsg = `RBD '${metadata.pool_name}/${metadata.image_name}'`;
+ childMsg = `RBD '${metadata.child_pool_name}/${metadata.child_image_name}'`;
+ destinationMsg = `RBD '${metadata.dest_pool_name}/${metadata.dest_image_name}'`;
+ snapMsg = `RBD snapshot '${metadata.pool_name}/${metadata.image_name}@${
+ metadata.snapshot_name
+ }'`;
+ finishedTask.metadata = metadata;
+ });
+
+ it('tests rbd/create messages', () => {
+ finishedTask.name = 'rbd/create';
+ testCreate(defaultMsg);
+ testErrorCode(17, `Name is already used by ${defaultMsg}.`);
+ });
+
+ it('tests rbd/edit messages', () => {
+ finishedTask.name = 'rbd/edit';
+ testUpdate(defaultMsg);
+ testErrorCode(17, `Name is already used by ${defaultMsg}.`);
+ });
+
+ it('tests rbd/delete messages', () => {
+ finishedTask.name = 'rbd/delete';
+ testDelete(defaultMsg);
+ testErrorCode(39, `${defaultMsg} contains snapshots.`);
+ });
+
+ it('tests rbd/clone messages', () => {
+ finishedTask.name = 'rbd/clone';
+ testMessages(new TaskMessageOperation('Cloning', 'clone', 'Cloned'), childMsg);
+ testErrorCode(17, `Name is already used by ${childMsg}.`);
+ testErrorCode(22, `Snapshot of ${childMsg} must be protected.`);
+ });
+
+ it('tests rbd/copy messages', () => {
+ finishedTask.name = 'rbd/copy';
+ testMessages(new TaskMessageOperation('Copying', 'copy', 'Copied'), destinationMsg);
+ testErrorCode(17, `Name is already used by ${destinationMsg}.`);
+ });
+
+ it('tests rbd/flatten messages', () => {
+ finishedTask.name = 'rbd/flatten';
+ testMessages(new TaskMessageOperation('Flattening', 'flatten', 'Flattened'), defaultMsg);
+ });
+
+ it('tests rbd/snap/create messages', () => {
+ finishedTask.name = 'rbd/snap/create';
+ testCreate(snapMsg);
+ testErrorCode(17, `Name is already used by ${snapMsg}.`);
+ });
+
+ it('tests rbd/snap/edit messages', () => {
+ finishedTask.name = 'rbd/snap/edit';
+ testUpdate(snapMsg);
+ testErrorCode(16, `Cannot unprotect ${snapMsg} because it contains child images.`);
+ });
+
+ it('tests rbd/snap/delete messages', () => {
+ finishedTask.name = 'rbd/snap/delete';
+ testDelete(snapMsg);
+ testErrorCode(16, `Cannot delete ${snapMsg} because it's protected.`);
+ });
+
+ it('tests rbd/snap/rollback messages', () => {
+ finishedTask.name = 'rbd/snap/rollback';
+ testMessages(new TaskMessageOperation('Rolling back', 'rollback', 'Rolled back'), snapMsg);
+ });
+
+ it('tests rbd/trash/move messages', () => {
+ finishedTask.name = 'rbd/trash/move';
+ testMessages(
+ new TaskMessageOperation('Moving', 'move', 'Moved'),
+ `image '${metadata.pool_name}/${metadata.image_name}' to trash`
+ );
+ testErrorCode(2, `Could not find image.`);
+ });
+
+ it('tests rbd/trash/restore messages', () => {
+ finishedTask.name = 'rbd/trash/restore';
+ testMessages(
+ new TaskMessageOperation('Restoring', 'restore', 'Restored'),
+ `image '${metadata.pool_name}@${metadata.image_id}' ` +
+ `into '${metadata.pool_name}/${metadata.new_image_name}'`
+ );
+ testErrorCode(
+ 17,
+ `Image name '${metadata.pool_name}/${metadata.new_image_name}' is already in use.`
+ );
+ });
+
+ it('tests rbd/trash/remove messages', () => {
+ finishedTask.name = 'rbd/trash/remove';
+ testDelete(`image '${metadata.pool_name}/${metadata.image_name}@${metadata.image_id}'`);
+ });
+
+ it('tests rbd/trash/purge messages', () => {
+ finishedTask.name = 'rbd/trash/purge';
+ testMessages(
+ new TaskMessageOperation('Purging', 'purge', 'Purged'),
+ `images from '${metadata.pool_name}'`
+ );
+ });
+ });
+ describe('rbd tasks', () => {
+ let metadata;
+ let modeMsg: string;
+ let peerMsg: string;
+
+ beforeEach(() => {
+ metadata = {
+ pool_name: 'somePool'
+ };
+ modeMsg = `mirror mode for pool '${metadata.pool_name}'`;
+ peerMsg = `mirror peer for pool '${metadata.pool_name}'`;
+ finishedTask.metadata = metadata;
+ });
+ it('tests rbd/mirroring/pool/edit messages', () => {
+ finishedTask.name = 'rbd/mirroring/pool/edit';
+ testUpdate(modeMsg);
+ testErrorCode(16, 'Cannot disable mirroring because it contains a peer.');
+ });
+ it('tests rbd/mirroring/peer/edit messages', () => {
+ finishedTask.name = 'rbd/mirroring/peer/edit';
+ testUpdate(peerMsg);
+ });
+ it('tests rbd/mirroring/peer/add messages', () => {
+ finishedTask.name = 'rbd/mirroring/peer/add';
+ testCreate(peerMsg);
+ });
+ it('tests rbd/mirroring/peer/delete messages', () => {
+ finishedTask.name = 'rbd/mirroring/peer/delete';
+ testDelete(peerMsg);
+ });
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts
new file mode 100644
index 00000000..9af1a50a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts
@@ -0,0 +1,396 @@
+import { Injectable } from '@angular/core';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+
+import { Components } from '../enum/components.enum';
+import { FinishedTask } from '../models/finished-task';
+import { Task } from '../models/task';
+
+export class TaskMessageOperation {
+ running: string;
+ failure: string;
+ success: string;
+
+ constructor(running: string, failure: string, success: string) {
+ this.running = running;
+ this.failure = failure;
+ this.success = success;
+ }
+}
+
+class TaskMessage {
+ i18n: I18n;
+
+ operation: TaskMessageOperation;
+ involves: (object) => string;
+ errors: (metadata) => object;
+
+ failure(metadata): string {
+ return this.i18n('Failed to {{failure}} {{metadata}}', {
+ failure: this.operation.failure,
+ metadata: this.involves(metadata)
+ });
+ }
+
+ running(metadata): string {
+ return `${this.operation.running} ${this.involves(metadata)}`;
+ }
+
+ success(metadata): string {
+ return `${this.operation.success} ${this.involves(metadata)}`;
+ }
+
+ constructor(
+ i18n: I18n,
+ operation: TaskMessageOperation,
+ involves: (metadata) => string,
+ errors?: (metadata) => object
+ ) {
+ this.i18n = i18n;
+ this.operation = operation;
+ this.involves = involves;
+ this.errors = errors || (() => ({}));
+ }
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TaskMessageService {
+ constructor(private i18n: I18n) {}
+
+ defaultMessage = this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Executing'), this.i18n('execute'), this.i18n('Executed')),
+ (metadata) => {
+ return (
+ (metadata && (Components[metadata.component] || metadata.component)) ||
+ this.i18n('unknown task')
+ );
+ },
+ () => {
+ return {};
+ }
+ );
+
+ commonOperations = {
+ create: new TaskMessageOperation(
+ this.i18n('Creating'),
+ this.i18n('create'),
+ this.i18n('Created')
+ ),
+ update: new TaskMessageOperation(
+ this.i18n('Updating'),
+ this.i18n('update'),
+ this.i18n('Updated')
+ ),
+ delete: new TaskMessageOperation(
+ this.i18n('Deleting'),
+ this.i18n('delete'),
+ this.i18n('Deleted')
+ )
+ };
+
+ rbd = {
+ default: (metadata) =>
+ this.i18n(`RBD '{{id}}'`, {
+ id: `${metadata.pool_name}/${metadata.image_name}`
+ }),
+ child: (metadata) =>
+ this.i18n(`RBD '{{id}}'`, {
+ id: `${metadata.child_pool_name}/${metadata.child_image_name}`
+ }),
+ destination: (metadata) =>
+ this.i18n(`RBD '{{id}}'`, {
+ id: `${metadata.dest_pool_name}/${metadata.dest_image_name}`
+ }),
+ snapshot: (metadata) =>
+ this.i18n(`RBD snapshot '{{id}}'`, {
+ id: `${metadata.pool_name}/${metadata.image_name}@${metadata.snapshot_name}`
+ })
+ };
+
+ rbd_mirroring = {
+ pool: (metadata) =>
+ this.i18n(`mirror mode for pool '{{id}}'`, {
+ id: `${metadata.pool_name}`
+ }),
+ pool_peer: (metadata) =>
+ this.i18n(`mirror peer for pool '{{id}}'`, {
+ id: `${metadata.pool_name}`
+ })
+ };
+
+ grafana = {
+ update_dashboards: () => this.i18n('all dashboards')
+ };
+
+ messages = {
+ // Pool tasks
+ 'pool/create': this.newTaskMessage(
+ this.commonOperations.create,
+ (metadata) => this.pool(metadata),
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{pool_name}}.', {
+ pool_name: this.pool(metadata)
+ })
+ })
+ ),
+ 'pool/edit': this.newTaskMessage(
+ this.commonOperations.update,
+ (metadata) => this.pool(metadata),
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{pool_name}}.', {
+ pool_name: this.pool(metadata)
+ })
+ })
+ ),
+ 'pool/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
+ this.pool(metadata)
+ ),
+ // Erasure code profile tasks
+ 'ecp/create': this.newTaskMessage(
+ this.commonOperations.create,
+ (metadata) => this.ecp(metadata),
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{name}}.', {
+ name: this.ecp(metadata)
+ })
+ })
+ ),
+ 'ecp/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
+ this.ecp(metadata)
+ ),
+ // RBD tasks
+ 'rbd/create': this.newTaskMessage(
+ this.commonOperations.create,
+ this.rbd.default,
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{rbd_name}}.', {
+ rbd_name: this.rbd.default(metadata)
+ })
+ })
+ ),
+ 'rbd/edit': this.newTaskMessage(this.commonOperations.update, this.rbd.default, (metadata) => ({
+ '17': this.i18n('Name is already used by {{rbd_name}}.', {
+ rbd_name: this.rbd.default(metadata)
+ })
+ })),
+ 'rbd/delete': this.newTaskMessage(
+ this.commonOperations.delete,
+ this.rbd.default,
+ (metadata) => ({
+ '39': this.i18n('{{rbd_name}} contains snapshots.', {
+ rbd_name: this.rbd.default(metadata)
+ })
+ })
+ ),
+ 'rbd/clone': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Cloning'), this.i18n('clone'), this.i18n('Cloned')),
+ this.rbd.child,
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{rbd_name}}.', {
+ rbd_name: this.rbd.child(metadata)
+ }),
+ '22': this.i18n('Snapshot of {{rbd_name}} must be protected.', {
+ rbd_name: this.rbd.child(metadata)
+ })
+ })
+ ),
+ 'rbd/copy': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Copying'), this.i18n('copy'), this.i18n('Copied')),
+ this.rbd.destination,
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{rbd_name}}.', {
+ rbd_name: this.rbd.destination(metadata)
+ })
+ })
+ ),
+ 'rbd/flatten': this.newTaskMessage(
+ new TaskMessageOperation(
+ this.i18n('Flattening'),
+ this.i18n('flatten'),
+ this.i18n('Flattened')
+ ),
+ this.rbd.default
+ ),
+ // RBD snapshot tasks
+ 'rbd/snap/create': this.newTaskMessage(
+ this.commonOperations.create,
+ this.rbd.snapshot,
+ (metadata) => ({
+ '17': this.i18n('Name is already used by {{snap_name}}.', {
+ snap_name: this.rbd.snapshot(metadata)
+ })
+ })
+ ),
+ 'rbd/snap/edit': this.newTaskMessage(
+ this.commonOperations.update,
+ this.rbd.snapshot,
+ (metadata) => ({
+ '16': this.i18n('Cannot unprotect {{snap_name}} because it contains child images.', {
+ snap_name: this.rbd.snapshot(metadata)
+ })
+ })
+ ),
+ 'rbd/snap/delete': this.newTaskMessage(
+ this.commonOperations.delete,
+ this.rbd.snapshot,
+ (metadata) => ({
+ '16': this.i18n(`Cannot delete {{snap_name}} because it's protected.`, {
+ snap_name: this.rbd.snapshot(metadata)
+ })
+ })
+ ),
+ 'rbd/snap/rollback': this.newTaskMessage(
+ new TaskMessageOperation(
+ this.i18n('Rolling back'),
+ this.i18n('rollback'),
+ this.i18n('Rolled back')
+ ),
+ this.rbd.snapshot
+ ),
+ // RBD trash tasks
+ 'rbd/trash/move': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Moving'), this.i18n('move'), this.i18n('Moved')),
+ (metadata) =>
+ this.i18n(`image '{{id}}' to trash`, {
+ id: `${metadata.pool_name}/${metadata.image_name}`
+ }),
+ () => ({
+ 2: this.i18n('Could not find image.')
+ })
+ ),
+ 'rbd/trash/restore': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Restoring'), this.i18n('restore'), this.i18n('Restored')),
+ (metadata) =>
+ this.i18n(`image '{{id}}' into '{{new_id}}'`, {
+ id: `${metadata.pool_name}@${metadata.image_id}`,
+ new_id: `${metadata.pool_name}/${metadata.new_image_name}`
+ }),
+ (metadata) => ({
+ 17: this.i18n(`Image name '{{id}}' is already in use.`, {
+ id: `${metadata.pool_name}/${metadata.new_image_name}`
+ })
+ })
+ ),
+ 'rbd/trash/remove': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Deleting'), this.i18n('delete'), this.i18n('Deleted')),
+ (metadata) =>
+ this.i18n(`image '{{id}}'`, {
+ id: `${metadata.pool_name}/${metadata.image_name}@${metadata.image_id}`
+ })
+ ),
+ 'rbd/trash/purge': this.newTaskMessage(
+ new TaskMessageOperation(this.i18n('Purging'), this.i18n('purge'), this.i18n('Purged')),
+ (metadata) => {
+ let message = this.i18n('all pools');
+ if (metadata.pool_name) {
+ message = `'${metadata.pool_name}'`;
+ }
+ return this.i18n('images from {{message}}', {
+ message: message
+ });
+ }
+ ),
+ // RBD mirroring tasks
+ 'rbd/mirroring/pool/edit': this.newTaskMessage(
+ this.commonOperations.update,
+ this.rbd_mirroring.pool,
+ () => ({
+ 16: this.i18n('Cannot disable mirroring because it contains a peer.')
+ })
+ ),
+ 'rbd/mirroring/peer/add': this.newTaskMessage(
+ this.commonOperations.create,
+ this.rbd_mirroring.pool_peer,
+ () => ({})
+ ),
+ 'rbd/mirroring/peer/edit': this.newTaskMessage(
+ this.commonOperations.update,
+ this.rbd_mirroring.pool_peer,
+ () => ({})
+ ),
+ 'rbd/mirroring/peer/delete': this.newTaskMessage(
+ this.commonOperations.delete,
+ this.rbd_mirroring.pool_peer,
+ () => ({})
+ ),
+ // iSCSI target tasks
+ 'iscsi/target/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
+ this.iscsiTarget(metadata)
+ ),
+ 'iscsi/target/edit': this.newTaskMessage(this.commonOperations.update, (metadata) =>
+ this.iscsiTarget(metadata)
+ ),
+ 'iscsi/target/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
+ this.iscsiTarget(metadata)
+ ),
+ 'nfs/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
+ this.nfs(metadata)
+ ),
+ 'nfs/edit': this.newTaskMessage(this.commonOperations.update, (metadata) => this.nfs(metadata)),
+ 'nfs/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
+ this.nfs(metadata)
+ ),
+ // Grafana tasks
+ 'grafana/dashboards/update': this.newTaskMessage(
+ this.commonOperations.update,
+ this.grafana.update_dashboards,
+ () => ({})
+ )
+ };
+
+ newTaskMessage(
+ operation: TaskMessageOperation,
+ involves: (metadata) => string,
+ errors?: (metadata) => object
+ ) {
+ return new TaskMessage(this.i18n, operation, involves, errors);
+ }
+
+ pool(metadata) {
+ return this.i18n(`pool '{{pool_name}}'`, {
+ pool_name: metadata.pool_name
+ });
+ }
+
+ ecp(metadata) {
+ return this.i18n(`erasure code profile '{{name}}'`, { name: metadata.name });
+ }
+
+ iscsiTarget(metadata) {
+ return this.i18n(`target '{{target_iqn}}'`, { target_iqn: metadata.target_iqn });
+ }
+
+ nfs(metadata) {
+ return this.i18n(`NFS {{nfs_id}}`, {
+ nfs_id: `'${metadata.cluster_id}:${metadata.export_id ? metadata.export_id : metadata.path}'`
+ });
+ }
+
+ _getTaskTitle(task: Task) {
+ return this.messages[task.name] || this.defaultMessage;
+ }
+
+ getSuccessTitle(task: FinishedTask) {
+ return this._getTaskTitle(task).success(task.metadata);
+ }
+
+ getErrorMessage(task: FinishedTask) {
+ return (
+ this._getTaskTitle(task).errors(task.metadata)[task.exception.code] || task.exception.detail
+ );
+ }
+
+ getErrorTitle(task: Task) {
+ return this._getTaskTitle(task).failure(task.metadata);
+ }
+
+ getRunningTitle(task: Task) {
+ return this._getTaskTitle(task).running(task.metadata);
+ }
+
+ getRunningText(task: Task) {
+ return this._getTaskTitle(task).operation.running;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.spec.ts
new file mode 100644
index 00000000..747964e1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.spec.ts
@@ -0,0 +1,98 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { inject, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { ToastrModule } from 'ngx-toastr';
+import { Observable } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
+import { FinishedTask } from '../models/finished-task';
+import { SharedModule } from '../shared.module';
+import { NotificationService } from './notification.service';
+import { SummaryService } from './summary.service';
+import { TaskManagerService } from './task-manager.service';
+import { TaskWrapperService } from './task-wrapper.service';
+
+describe('TaskWrapperService', () => {
+ let service: TaskWrapperService;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule, ToastrModule.forRoot(), SharedModule, RouterTestingModule],
+ providers: [TaskWrapperService, i18nProviders]
+ });
+
+ beforeEach(inject([TaskWrapperService], (wrapper: TaskWrapperService) => {
+ service = wrapper;
+ }));
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ describe('wrapTaskAroundCall', () => {
+ let notify: NotificationService;
+ let passed: boolean;
+ let summaryService: SummaryService;
+
+ const fakeCall = (status?) =>
+ new Observable((observer) => {
+ if (!status) {
+ observer.error({ error: 'failed' });
+ }
+ observer.next({ status: status });
+ observer.complete();
+ });
+
+ const callWrapTaskAroundCall = (status, name) => {
+ return service.wrapTaskAroundCall({
+ task: new FinishedTask(name, { sth: 'else' }),
+ call: fakeCall(status)
+ });
+ };
+
+ beforeEach(() => {
+ passed = false;
+ notify = TestBed.get(NotificationService);
+ summaryService = TestBed.get(SummaryService);
+ spyOn(notify, 'show');
+ spyOn(notify, 'notifyTask').and.stub();
+ spyOn(service, '_handleExecutingTasks').and.callThrough();
+ spyOn(summaryService, 'addRunningTask').and.callThrough();
+ });
+
+ it('should simulate a synchronous task', () => {
+ callWrapTaskAroundCall(200, 'sync').subscribe(null, null, () => (passed = true));
+ expect(service._handleExecutingTasks).not.toHaveBeenCalled();
+ expect(passed).toBeTruthy();
+ expect(summaryService.addRunningTask).not.toHaveBeenCalled();
+ });
+
+ it('should simulate a asynchronous task', () => {
+ callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
+ expect(service._handleExecutingTasks).toHaveBeenCalled();
+ expect(passed).toBeTruthy();
+ expect(summaryService.addRunningTask).toHaveBeenCalledTimes(1);
+ });
+
+ it('should call notifyTask if asynchronous task would have been finished', () => {
+ const taskManager = TestBed.get(TaskManagerService);
+ spyOn(taskManager, 'subscribe').and.callFake((_name, _metadata, onTaskFinished) => {
+ onTaskFinished();
+ });
+ callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
+ expect(notify.notifyTask).toHaveBeenCalled();
+ });
+
+ it('should simulate a task failure', () => {
+ callWrapTaskAroundCall(null, 'async').subscribe(null, () => (passed = true), null);
+ expect(service._handleExecutingTasks).not.toHaveBeenCalled();
+ expect(passed).toBeTruthy();
+ expect(summaryService.addRunningTask).not.toHaveBeenCalled();
+ /**
+ * A notification will be raised by the API interceptor.
+ * This resolves this bug https://tracker.ceph.com/issues/25139
+ */
+ expect(notify.notifyTask).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.ts
new file mode 100644
index 00000000..66668ec6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-wrapper.service.ts
@@ -0,0 +1,65 @@
+import { Injectable } from '@angular/core';
+
+import { Observable, Subscriber } from 'rxjs';
+
+import { NotificationType } from '../enum/notification-type.enum';
+import { ExecutingTask } from '../models/executing-task';
+import { FinishedTask } from '../models/finished-task';
+import { NotificationService } from './notification.service';
+import { SummaryService } from './summary.service';
+import { TaskManagerService } from './task-manager.service';
+import { TaskMessageService } from './task-message.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TaskWrapperService {
+ constructor(
+ private notificationService: NotificationService,
+ private summaryService: SummaryService,
+ private taskMessageService: TaskMessageService,
+ private taskManagerService: TaskManagerService
+ ) {}
+
+ wrapTaskAroundCall({ task, call }: { task: FinishedTask; call: Observable<any> }) {
+ return new Observable((observer: Subscriber<any>) => {
+ call.subscribe(
+ (resp) => {
+ if (resp.status === 202) {
+ this._handleExecutingTasks(task);
+ } else {
+ this.summaryService.refresh();
+ task.success = true;
+ this.notificationService.notifyTask(task);
+ }
+ },
+ (resp) => {
+ task.success = false;
+ task.exception = resp.error;
+ observer.error(resp);
+ },
+ () => {
+ observer.complete();
+ }
+ );
+ });
+ }
+
+ _handleExecutingTasks(task: FinishedTask) {
+ this.notificationService.show(
+ NotificationType.info,
+ this.taskMessageService.getRunningTitle(task)
+ );
+
+ const executingTask = new ExecutingTask(task.name, task.metadata);
+ this.summaryService.addRunningTask(executingTask);
+
+ this.taskManagerService.subscribe(
+ executingTask.name,
+ executingTask.metadata,
+ (asyncTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncTask);
+ }
+ );
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts
new file mode 100644
index 00000000..59b52ae6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.spec.ts
@@ -0,0 +1,66 @@
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { TimeDiffService } from './time-diff.service';
+
+describe('TimeDiffService', () => {
+ let service: TimeDiffService;
+ const baseTime = new Date('2022-02-22T00:00:00');
+
+ configureTestBed({
+ providers: [TimeDiffService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(TimeDiffService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('calculates a new date that happens after the given date', () => {
+ expect(service.calculateDate(new Date('2022-02-28T04:05:00'), '2h')).toEqual(
+ new Date('2022-02-28T06:05:00')
+ );
+ expect(service.calculateDate(baseTime, '15m')).toEqual(new Date('2022-02-22T00:15'));
+ expect(service.calculateDate(baseTime, '5d 23h')).toEqual(new Date('2022-02-27T23:00'));
+ });
+
+ it('calculates a new date that happens before the given date', () => {
+ expect(service.calculateDate(new Date('2022-02-22T02:00:00'), '2h', true)).toEqual(baseTime);
+ });
+
+ it('calculates the difference of two dates', () => {
+ expect(
+ service.calculateDuration(new Date('2022-02-22T00:45:00'), new Date('2022-02-22T02:00:00'))
+ ).toBe('1h 15m');
+ expect(service.calculateDuration(baseTime, new Date('2022-02-28T04:05:00'))).toBe('6d 4h 5m');
+ });
+
+ describe('testing duration calculation in detail', () => {
+ const minutes = 60 * 1000;
+ const hours = 60 * minutes;
+ const days = 24 * hours;
+
+ it('should allow different writings', () => {
+ const expectDurationToBeMs = (duration, ms) =>
+ expect(service['getDurationMs'](duration)).toBe(ms);
+ expectDurationToBeMs('2h', 2 * hours);
+ expectDurationToBeMs('4 Days', 4 * days);
+ expectDurationToBeMs('3 minutes', 3 * minutes);
+ expectDurationToBeMs('4 Days 2h 3 minutes', 4 * days + 2 * hours + 3 * minutes);
+ expectDurationToBeMs('5d3h120m', 5 * days + 5 * hours);
+ });
+
+ it('should create duration string from ms', () => {
+ const expectMsToBeDuration = (ms, duration) =>
+ expect(service['getDuration'](ms)).toBe(duration);
+ expectMsToBeDuration(2 * hours, '2h');
+ expectMsToBeDuration(4 * days, '4d');
+ expectMsToBeDuration(3 * minutes, '3m');
+ expectMsToBeDuration(4 * days + 2 * hours + 3 * minutes, '4d 2h 3m');
+ expectMsToBeDuration(service['getDurationMs']('5d3h120m'), '5d 5h');
+ });
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts
new file mode 100644
index 00000000..051d1049
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/time-diff.service.ts
@@ -0,0 +1,51 @@
+import { Injectable } from '@angular/core';
+
+import * as _ from 'lodash';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TimeDiffService {
+ constructor() {}
+
+ calculateDuration(startDate: Date, endDate: Date): string {
+ const startTime = +startDate;
+ const endTime = +endDate;
+ const duration = this.getDuration(Math.abs(startTime - endTime));
+ if (startTime > endTime) {
+ return '-' + duration;
+ }
+ return duration;
+ }
+
+ private getDuration(ms: number): string {
+ const date = new Date(ms);
+ const h = date.getUTCHours();
+ const m = date.getUTCMinutes();
+ const d = Math.floor(ms / (24 * 3600 * 1000));
+
+ const format = (n, s) => (n ? n + s : n);
+ return [format(d, 'd'), format(h, 'h'), format(m, 'm')].filter((x) => x).join(' ');
+ }
+
+ calculateDate(date: Date, duration: string, reverse?: boolean): Date {
+ const time = +date;
+ if (_.isNaN(time)) {
+ return;
+ }
+ const diff = this.getDurationMs(duration) * (reverse ? -1 : 1);
+ return new Date(time + diff);
+ }
+
+ private getDurationMs(duration: string): number {
+ const d = this.getNumbersFromString(duration, 'd');
+ const h = this.getNumbersFromString(duration, 'h');
+ const m = this.getNumbersFromString(duration, 'm');
+ return ((d * 24 + h) * 60 + m) * 60000;
+ }
+
+ private getNumbersFromString(duration, prefix): number {
+ const match = duration.match(new RegExp(`[0-9 ]+${prefix}`, 'i'));
+ return match ? parseInt(match, 10) : 0;
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.spec.ts
new file mode 100644
index 00000000..bc8b54ca
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.spec.ts
@@ -0,0 +1,37 @@
+import { URLVerbs } from '../constants/app.constants';
+import { URLBuilderService } from './url-builder.service';
+
+describe('URLBuilderService', () => {
+ const BASE = 'pool';
+ const urlBuilder = new URLBuilderService(BASE);
+
+ it('get base', () => {
+ expect(urlBuilder.base).toBe(BASE);
+ });
+
+ it('build absolute URL', () => {
+ expect(URLBuilderService.buildURL(true, urlBuilder.base, URLVerbs.CREATE)).toBe(
+ `/${urlBuilder.base}/${URLVerbs.CREATE}`
+ );
+ });
+
+ it('build relative URL', () => {
+ expect(URLBuilderService.buildURL(false, urlBuilder.base, URLVerbs.CREATE)).toBe(
+ `${urlBuilder.base}/${URLVerbs.CREATE}`
+ );
+ });
+
+ it('get Create URL', () => {
+ expect(urlBuilder.getCreate()).toBe(`/${urlBuilder.base}/${URLVerbs.CREATE}`);
+ });
+
+ it('get Create From URL', () => {
+ const id = 'someId';
+ expect(urlBuilder.getCreateFrom(id)).toBe(`/${urlBuilder.base}/${URLVerbs.CREATE}/${id}`);
+ });
+
+ it('get Edit URL with item', () => {
+ const item = 'test_pool';
+ expect(urlBuilder.getEdit(item)).toBe(`/${urlBuilder.base}/${URLVerbs.EDIT}/${item}`);
+ });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.ts
new file mode 100644
index 00000000..b06f307a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/url-builder.service.ts
@@ -0,0 +1,50 @@
+import { Location } from '@angular/common';
+
+import { URLVerbs } from '../constants/app.constants';
+
+export class URLBuilderService {
+ constructor(readonly base: string) {}
+
+ private static concatURLSegments(segments: string[]): string {
+ return segments.reduce(Location.joinWithSlash);
+ }
+
+ static buildURL(absolute: boolean, ...segments: string[]): string {
+ return URLBuilderService.concatURLSegments([...(absolute ? ['/'] : []), ...segments]);
+ }
+
+ private getURL(verb: URLVerbs, absolute = true, ...segments: string[]): string {
+ return URLBuilderService.buildURL(absolute, this.base, verb, ...segments);
+ }
+
+ getCreate(absolute = true): string {
+ return this.getURL(URLVerbs.CREATE, absolute);
+ }
+
+ getCreateFrom(item: string, absolute = true): string {
+ return this.getURL(URLVerbs.CREATE, absolute, item);
+ }
+
+ getDelete(absolute = true): string {
+ return this.getURL(URLVerbs.DELETE, absolute);
+ }
+
+ getEdit(item: string, absolute = true): string {
+ return this.getURL(URLVerbs.EDIT, absolute, item);
+ }
+ getUpdate(item: string, absolute = true): string {
+ return this.getURL(URLVerbs.UPDATE, absolute, item);
+ }
+
+ getAdd(absolute = true): string {
+ return this.getURL(URLVerbs.ADD, absolute);
+ }
+ getRemove(absolute = true): string {
+ return this.getURL(URLVerbs.REMOVE, absolute);
+ }
+
+ // Prometheus wording
+ getRecreate(item: string, absolute = true): string {
+ return this.getURL(URLVerbs.RECREATE, absolute, item);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/shared.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/shared.module.ts
new file mode 100644
index 00000000..ae3a1c08
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/shared.module.ts
@@ -0,0 +1,26 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { ApiModule } from './api/api.module';
+import { ComponentsModule } from './components/components.module';
+import { DataTableModule } from './datatable/datatable.module';
+import { DirectivesModule } from './directives/directives.module';
+import { PipesModule } from './pipes/pipes.module';
+import { AuthGuardService } from './services/auth-guard.service';
+import { AuthStorageService } from './services/auth-storage.service';
+import { FormatterService } from './services/formatter.service';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ PipesModule,
+ ComponentsModule,
+ DataTableModule,
+ ApiModule,
+ DirectivesModule
+ ],
+ declarations: [],
+ exports: [ComponentsModule, PipesModule, DataTableModule, ApiModule, DirectivesModule],
+ providers: [AuthStorageService, AuthGuardService, FormatterService]
+})
+export class SharedModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/.gitkeep b/src/pybind/mgr/dashboard/frontend/src/assets/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/.gitkeep
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Mimic_Octopus2.jpg b/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Mimic_Octopus2.jpg
new file mode 100644
index 00000000..f8cf2a8d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Mimic_Octopus2.jpg
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Nautilus_Octopus.jpg b/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Nautilus_Octopus.jpg
new file mode 100644
index 00000000..1f0776fb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/1280px-Nautilus_Octopus.jpg
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png
new file mode 100644
index 00000000..79064dc0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png
new file mode 100644
index 00000000..d46bd73f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png
new file mode 100644
index 00000000..26d602be
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Stacked_RGB_White_120411_fa_256x256.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png
new file mode 100644
index 00000000..0f07b83e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/Ceph_Logo_Standard_RGB_White_120411_fa.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/loading.gif b/src/pybind/mgr/dashboard/frontend/src/assets/loading.gif
new file mode 100755
index 00000000..8fb88dea
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/loading.gif
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/logo-mini.png b/src/pybind/mgr/dashboard/frontend/src/assets/logo-mini.png
new file mode 100644
index 00000000..b3446a89
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/logo-mini.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/notification-icons.png b/src/pybind/mgr/dashboard/frontend/src/assets/notification-icons.png
new file mode 100644
index 00000000..d609a7c8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/notification-icons.png
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/assets/prometheus_logo.svg b/src/pybind/mgr/dashboard/frontend/src/assets/prometheus_logo.svg
new file mode 100644
index 00000000..5c51f66d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/assets/prometheus_logo.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="115.333px"
+ height="114px"
+ viewBox="0 0 115.333 114"
+ enable-background="new 0 0 115.333 114"
+ xml:space="preserve"
+ sodipodi:docname="prometheus_logo_orange.svg"
+ inkscape:version="0.92.1 r15371"><metadata
+ id="metadata4495"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs4493" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1484"
+ inkscape:window-height="886"
+ id="namedview4491"
+ showgrid="false"
+ inkscape:zoom="5.2784901"
+ inkscape:cx="60.603667"
+ inkscape:cy="60.329656"
+ inkscape:window-x="54"
+ inkscape:window-y="7"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" /><g
+ id="Layer_2" /><path
+ style="fill:#e6522c;fill-opacity:1"
+ inkscape:connector-curvature="0"
+ id="path4486"
+ d="M 56.667,0.667 C 25.372,0.667 0,26.036 0,57.332 c 0,31.295 25.372,56.666 56.667,56.666 31.295,0 56.666,-25.371 56.666,-56.666 0,-31.296 -25.372,-56.665 -56.666,-56.665 z m 0,106.055 c -8.904,0 -16.123,-5.948 -16.123,-13.283 H 72.79 c 0,7.334 -7.219,13.283 -16.123,13.283 z M 83.297,89.04 H 30.034 V 79.382 H 83.298 V 89.04 Z M 83.106,74.411 H 30.186 C 30.01,74.208 29.83,74.008 29.66,73.802 24.208,67.182 22.924,63.726 21.677,60.204 c -0.021,-0.116 6.611,1.355 11.314,2.413 0,0 2.42,0.56 5.958,1.205 -3.397,-3.982 -5.414,-9.044 -5.414,-14.218 0,-11.359 8.712,-21.285 5.569,-29.308 3.059,0.249 6.331,6.456 6.552,16.161 3.252,-4.494 4.613,-12.701 4.613,-17.733 0,-5.21 3.433,-11.262 6.867,-11.469 -3.061,5.045 0.793,9.37 4.219,20.099 1.285,4.03 1.121,10.812 2.113,15.113 C 63.797,33.534 65.333,20.5 71,16 c -2.5,5.667 0.37,12.758 2.333,16.167 3.167,5.5 5.087,9.667 5.087,17.548 0,5.284 -1.951,10.259 -5.242,14.148 3.742,-0.702 6.326,-1.335 6.326,-1.335 l 12.152,-2.371 c 10e-4,-10e-4 -1.765,7.261 -8.55,14.254 z" /></svg> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/defaults.scss b/src/pybind/mgr/dashboard/frontend/src/defaults.scss
new file mode 100644
index 00000000..9cf30b39
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/defaults.scss
@@ -0,0 +1,188 @@
+/*The file suppose to contain all variables, mixins and extends*/
+
+@import 'vendor.variables';
+
+$screen-sm-min: 768px !default;
+$screen-md-min: 992px !default;
+$screen-lg-min: 1200px !default;
+
+$screen-xs-max: calc(#{$screen-sm-min} - 1px);
+$screen-sm-max: calc(#{$screen-md-min} - 1px);
+$screen-md-max: calc(#{$screen-lg-min} - 1px);
+
+$color-solid-red: #ff0000 !default;
+$color-pink: #a94442 !default;
+$color-light-red: #f2dede !default;
+
+$color-orange: #ff6600 !default;
+
+$color-bright-yellow: #ffc200 !default;
+$color-light-yellow: #fff3cd !default;
+
+$color-bright-green: #00bb00 !default;
+$color-green: #71843f !default;
+
+$color-blue: #288cea !default;
+$color-light-blue: #d9edf7 !default;
+$color-sky-blue: #afd9ee !default;
+
+$color-black: #000 !default;
+$color-transparent-black: rgba(0, 0, 0, 0.7) !default;
+$color-solid-gray: #555555 !default;
+$color-dark-gray: #474544 !default;
+$color-gray: #505050 !default;
+$color-mild-gray: #777777 !default;
+$color-blue-gray: #90949c !default;
+$color-grad-gray: #ededed !default;
+$color-shadow-gray: rgba(3, 3, 3, 0.175) !default;
+$color-light-gray: #d1d1d1 !default;
+$color-soft-gray: #ddd !default;
+$color-white-gray: #eee !default;
+$color-shade-gray: #efefef !default;
+$color-light-shade-gray: #f3f3f3 !default;
+$color-whitesmoke-gray: #f5f5f5 !default;
+$color-solid-white: #ffffff !default;
+$color-transparent: rgba(0, 0, 0, 0.09) !default;
+$color-brand-teal: #2b99a8 !default;
+$color-brand-gray: #374249 !default;
+
+$color-primary: $color-brand-teal !default;
+$color-secondary: $color-brand-gray !default;
+$color-accent: #ef5c55 !default;
+
+$color-app-bg: $color-solid-white !default;
+$color-bg-darken: $color-dark-gray !default;
+$color-links: $color-primary !default;
+$color-links-focus: $color-dark-gray !default;
+$color-breadcrumb: $color-dark-gray !default;
+$color-button-text: $color-white-gray !default;
+$color-button: $color-primary !default;
+$color-button-hover: darken($color-primary, 3) !default;
+$color-button-border: darken($color-primary, 6) !default;
+$color-button-badge: $color-white-gray !default;
+$color-button-caret: $color-white-gray !default;
+$color-dropdown-menu: $color-dark-gray !default;
+$color-dropdown-active-text: $color-white-gray !default;
+$color-dropdown-active-bg: $color-primary !default;
+$color-caret-text: $color-solid-white !default;
+$color-progress-bar-info-bg: $color-primary !default;
+$color-progress-bar-freespace-bg: $color-light-gray !default;
+$color-oaprogress-text: $color-black !default;
+$color-tags-border: $color-light-gray !default;
+$color-tags-box-shadow: $color-transparent !default;
+$color-error-btn-bg: $color-light-red !default;
+$color-error-btn-border: $color-pink !default;
+$color-noscript-text: $color-mild-gray !default;
+$color-required-text: $color-pink !default;
+
+/*Button*/
+$button-radius: 1.875rem !default;
+
+/*Login*/
+$color-login-row-text: $color-solid-white !default;
+$color-login-row-bg: $color-secondary !default;
+$color-password-toggle-text: $color-solid-white !default;
+$color-password-toggle-bg: $color-solid-gray !default;
+$color-password-toggle-focus: $color-primary !default;
+$color-login-checkbox-bg: $color-primary !default;
+$color-login-checkbox-border: $color-primary !default;
+$color-login-active-row-bg: $color-light-yellow !default;
+$color-login-active-row-text: $color-black !default;
+
+/*Landing Page*/
+
+/*InfoGroup*/
+$color-info-group-underline: $color-whitesmoke-gray !default;
+
+/*InfoCard*/
+$color-info-card-background: $color-whitesmoke-gray !default;
+$color-info-card-border: $color-soft-gray !default;
+
+/*Navigation*/
+$color-navbar-bg: $color-secondary !default;
+$color-navbar-brand: $color-white-gray !default;
+$color-nav-top-bar: $color-primary !default;
+$color-nav-bottom-bar: $color-primary !default;
+$color-nav-toggle-bar: $color-white-gray !default;
+$color-nav-toggle-shadow: $color-solid-white !default;
+$color-nav-collapse-border: $color-white-gray !default;
+$color-nav-open-bg: $color-primary !default;
+$color-nav-links: $color-white-gray !default;
+$color-nav-links-hover: $color-primary !default;
+$color-nav-active-link-bg: $color-primary !default;
+$color-nav-border-top-collapse: $color-white-gray !default;
+
+/*Helper*/
+$color-helper-bg: $color-primary !default;
+
+/*Table*/
+$color-table-seperator-border: $color-transparent !default;
+$color-table-input-border: $color-transparent !default;
+$color-table-dropdown-bg: $color-whitesmoke-gray !default;
+$color-table-header-bg: $color-whitesmoke-gray !default;
+$color-table-header-border: $color-light-gray !default;
+$color-table-active-row: $color-sky-blue !default;
+$color-table-active-row-hover: $color-light-blue !default;
+$color-table-progress-bar-bg: $color-sky-blue !default;
+$color-table-progress-bar-active: $color-primary !default;
+$color-table-gradient-1: $color-whitesmoke-gray !default;
+$color-table-gradient-2: $color-grad-gray !default;
+$color-table-sort: $color-primary !default;
+$color-table-empty-row: $color-light-yellow !default;
+$color-table-hover-row: $color-white-gray !default;
+$color-table-even-row-bg: $color-solid-white !default;
+$color-table-odd-row-bg: $color-whitesmoke-gray !default;
+$color-table-datatable-header: $color-whitesmoke-gray !default;
+
+/*Chart tooltip*/
+$color-chart-tooltip-bg: $color-transparent-black !default;
+$color-chat-tooltip-text: $color-solid-white !default;
+$color-chart-tooltip-border: $color-black !default;
+
+/*Popover*/
+$color-popover-seperator-text: $color-blue-gray !default;
+$color-popover-seperator-bg: $color-white-gray !default;
+$color-popover-message-text: $color-dark-gray !default;
+$color-popover-table-text: $color-dark-gray !default;
+$color-popover-date: $color-solid-gray !default;
+
+/*RGW user form*/
+$color-rgw-icon: $color-blue-gray !default;
+
+@mixin table-cell {
+ padding: 5px;
+ border: none;
+ border-left: 1px solid $color-light-gray;
+ border-bottom: 1px solid $color-light-gray;
+}
+
+@mixin hf {
+ border-bottom: 1px solid $color-light-gray;
+ background-color: $color-whitesmoke-gray;
+}
+
+@function strip-unit($value) {
+ @return $value / ($value * 0 + 1);
+}
+
+@mixin fluid-font-size($min-vw, $max-vw, $min-font-size, $max-font-size) {
+ $u1: unit($min-vw);
+ $u2: unit($max-vw);
+ $u3: unit($min-font-size);
+ $u4: unit($max-font-size);
+
+ @if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
+ & {
+ font-size: $min-font-size;
+ @media screen and (min-width: $min-vw) {
+ font-size: calc(
+ #{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)} *
+ ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)})
+ );
+ }
+ @media screen and (min-width: $max-vw) {
+ font-size: $max-font-size;
+ }
+ }
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/environments/environment.tpl.ts b/src/pybind/mgr/dashboard/frontend/src/environments/environment.tpl.ts
new file mode 100644
index 00000000..421ae5e5
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/environments/environment.tpl.ts
@@ -0,0 +1,10 @@
+// The file contents for the current environment will overwrite these during build.
+// The build system defaults to the dev environment which uses `environment.ts`, but if you do
+// `ng build --env=prod` then `environment.prod.ts` will be used instead.
+// The list of which env maps to which file can be found in `.angular-cli.json`.
+
+export const environment = {
+ default_lang: '{DEFAULT_LANG}',
+ production: '{PRODUCTION}',
+ year: '{COPYRIGHT_YEAR}'
+};
diff --git a/src/pybind/mgr/dashboard/frontend/src/favicon.ico b/src/pybind/mgr/dashboard/frontend/src/favicon.ico
new file mode 100644
index 00000000..90e538ba
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/favicon.ico
Binary files differ
diff --git a/src/pybind/mgr/dashboard/frontend/src/index.html b/src/pybind/mgr/dashboard/frontend/src/index.html
new file mode 100644
index 00000000..05a8f709
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/index.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Ceph</title>
+
+ <script>
+ document.write('<base href="' + document.location+ '" />');
+ </script>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
+</head>
+<body>
+ <noscript>
+ <div class="noscript container"
+ ng-if="false">
+ <div class="jumbotron alert alert-danger">
+ <h2 i18n>JavaScript required!</h2>
+ <p i18n>A browser with JavaScript enabled is required in order to use this service.</p>
+ <p i18n>When using Internet Explorer, please check your security settings and add this address to your trusted sites.</p>
+ </div>
+ </div>
+ </noscript>
+
+ <cd-root></cd-root>
+</body>
+</html>
diff --git a/src/pybind/mgr/dashboard/frontend/src/jestGlobalMocks.ts b/src/pybind/mgr/dashboard/frontend/src/jestGlobalMocks.ts
new file mode 100644
index 00000000..6c6750ad
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/jestGlobalMocks.ts
@@ -0,0 +1,19 @@
+const mock = () => {
+ let storage = {};
+ return {
+ getItem: (key) => (key in storage ? storage[key] : null),
+ setItem: (key, value) => (storage[key] = value || ''),
+ removeItem: (key) => delete storage[key],
+ clear: () => (storage = {})
+ };
+};
+
+Object.defineProperty(window, 'localStorage', { value: mock() });
+Object.defineProperty(window, 'sessionStorage', { value: mock() });
+Object.defineProperty(window, 'getComputedStyle', {
+ value: () => ({
+ getPropertyValue: () => {
+ return '';
+ }
+ })
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.cs.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.cs.xlf
new file mode 100644
index 00000000..28d2665b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.cs.xlf
@@ -0,0 +1,4365 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="cs">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Zobraz./skrýt navigaci</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Přehled</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Klastr</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Stroje</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitory</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Nastavení</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSH mapa</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Moduly správy</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Záznamy událostí</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Výstrahy</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Fondy</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Blok</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Obrazy</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Zrcadlení</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Souborové systémy</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Objektová brána</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Procesy služeb</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Uživatelé</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Nádoby</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Získávají se data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pro
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Čekejte…
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Zobrazují se data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>z mezipaměti
+ pro
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Nedaří se načíst dat
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pro
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Zkontrolujte zdraví klastru.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Zpět</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Vyberte jazyk</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Načítání údajů panelu…</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Nahlédněte do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>, kde naleznete jak
+ nastavit a zapnout funkci monitorování.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Grafana přehled neexistuje. Podívejte se do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> jak
+ přidat přehledy do Grafany.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Grafana Time Picker</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Resetovat nastavení</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Data se nepodařilo načíst</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>vybráno</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>nalezeno</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>celkem</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Upravit</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Název</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Popis</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Podrobnější popis</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Výchozí</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Výchozí pro proces služby</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Služby</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Hodnoty</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>Zadaná hodnota je příliš vysoká! Nemůže být vyšší než
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>Zadaná hodnota je příliš nízká! Nemůže být nižší než
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Uložit</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>prohlížeč CRUSH mapy</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Seznam strojů</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Celková výkonnost</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Nenalezeny žádné položky</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Záznamy událostí v klastra</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Auditní záznamy událostí</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Načítání nastavení…</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Toto nastavení se nepodařilo načíst.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Upravit modul správy</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>Zadaná hodnota není platné UUID, např.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>Je třeba, aby zadaná hodnota byla platnou IP adresou.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Tuto kolonku je třeba vyplnit.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>Je třeba, aby zadaná hodnota byla číslo.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>Je třeba, aby zadaná hodnota byla číslo nebo desítkové.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Aktualizovat</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Stav</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>Identif. kastru</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>mapa monitorů změněna</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmap epocha</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>kvórum spojení</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>kvórum monitor</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>vyžadováno spojení</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>vyžadováno monitorů</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>V kvóru</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Není v kvóru</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Storno</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Opravdu chcete označené
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Ano, opravdu to chci.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Příznaky OSD pro celý klastr</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Odeslat</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Pokročilé…</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Priorita obnovení OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Priorita</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Přizpůsobit hodnoty priority</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Tuto kolonku je třeba vyplnit!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>Zadaná hodnota je příliš vysoká, je třeba, aby nebyla vyšší než
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>Zadaná hodnota je příliš nízká! Je třeba, aby byla nižší než
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Znovu vyvážit OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>Je třeba, aby hodnota byla mezi 0 a 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Znovu vyvážit</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>kontrola
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, vybrat, 1 {Deep } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Chystáte se použít kontrolu na
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, vybrat, 1 {deep } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Seznam OSD</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Pokud budete pokračovat,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> bude označeno
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>OSD není možné bezpečně zlikvidovat!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Pokud budete pokračovat,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> bude
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Podrobnosti</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Hodnota</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Zavřít</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Smazat</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Zdraví</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statistiky</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Ohledně nastavení a zapnutí funkce správy NFS Ganesha nahlédněte do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Klienti</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Přistupovat může libovolný klient</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Adresy</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Vyžadovaná kolonka</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Je třeba, aby obsahovalo jednu nebo více čárkou oddělovaných hodnot</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Například:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Typ přístupu</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Přidat klienty</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Načítání…</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Žádný klastr k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Vyberte klastr --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Přidat proces služby</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Podpůrná vrstva úložiště</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Žádné fondy k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Vyberte podpůrnou vrstvu úložiště --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Uživatel objektové brány</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Žádní uživatelé k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Vyberte uživatele brány objektů --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>Identif. uživatele CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Žádní klienti k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Vyberte cephx klienta --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Název CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Security Label</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Enable security label</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Popis umístění CephFS</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Je třeba, aby popis umístění začínal na „/“, za kterým následuje slovo</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Bude vytvořena nová složka</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Popis umístění</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Popis umístění může být pouze jediné „/“ nebo slovo</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Bude vytvořena nová nádoba</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFS protokol</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFS štítek</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Alternativní přístup pro
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> připojení (nemůže začínat na /).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>By using different Tag options, the same Path may be exported multiple times.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>By using different Pseudo options, the same Path may be exported multiple times.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Žádný typ přístupu k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Vyberte typ přístupu --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- No squash available --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>--Select what kind of user id squashing is performed --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Transportní protokol</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Vítejte v Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Je třeba vyplnit uživatelské jméno</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Je třeba vyplnit heslo</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Přihlásit</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Je nám líto, uživatel v Ceph neexistuje.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Vrátit se na
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Přihlašovací stránku
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Budete odhlášeni od poskytovatele identity když se pokusíte znovu přihlásit.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Odepřeno</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Omlouváme se, ale nemáte oprávnění zobrazit to, po čem se poohlížíte.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Omlouváme se, nepodařilo se najít to, po čem se poohlížíte</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Odebrat vše</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Nedávná oznámení</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Nejsou zde žádné úlohy na pozadí.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Úlohy na pozadí</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Nápověda</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Dokumentace</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>Aplikační program. rozhraní</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>O aplikaci</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Nastavení přehledu</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Správa uživatelů</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Přihlášený uživatel</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Přihlášeni jako
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Odhlásit</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Název…</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Zvolený název už je používán.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Popis…</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Oprávnění</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Role</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Uživatelské jméno</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Heslo</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Potvrzení zadání hesla</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Zadání hesla se neshodují.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Celé jméno</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>E-mail</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>Neplatný e-mail.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Chystáte se odebrat oprávnění „uživatel číst/aktualizovat“ svému vlastnímu účtu.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Pokud budete pokračovat, nebudete nadále schopní přidávat nebo nebo odebírat role žádnému z uživatelů.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Opravdu chcete pokračovat?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Výkonnostní čítače nejsou k dispozici</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Atributy (OSD mapa)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Metadata nejsou k dispozici</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadata</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Výkonnostní čítač</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histogram není k dispozici:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Zápisy</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Čtení</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histogram</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Podrobnosti o výkonnosti</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Stávající hodnoty</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Typ</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Min</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Max</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Příznaky</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Zdroj</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Úroveň</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Je možné aktualizovat za provozu (upravitelné)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Štítky</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Vyčíslit hodnoty</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Viz také</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Stav klastru</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Procesy služby správy</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Objektové brány</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Metadata servery</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI brány</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>vst/výst. klienta</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Propustnost klienta</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Čtení/zápis klienta</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Propustnost zotavení</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Kontrola</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Výkonnost</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Holá kapacita</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objekty</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>Skupin umístění na OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Stav skupiny umístění</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Kapacita</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>Další podrobnosti
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> naleznete v
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>záznamech událostí
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Hodnocení</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Klienti:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Přesunout obraz do koše</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Pro přesunutí
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> do koše,
+ klikněte na
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Přesunout obraz
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Volitelně je možné zvolit datum skončení platnosti.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>Platnost ochrany skončí v</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NECHRÁNĚNO</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Chybný formát data. Použijte „RRRR-MM-DD HH:mm:ss“.</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>Platnost ochrany už skončila. Zvolte budoucí datum nebo nevyplňujte.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Přesunout obraz</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Přehled</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Cíle</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Ověřování pro objevování</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Uživatele</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Uživatel pro vzájemné ověření</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Heslo pro vzájemné ověření</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Podívejte se do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ jak nastavit a zapnout funkci správy iSCSI cílů.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Informace k dispozici:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>iSCSI cíl není k dispozici</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>K dispozici pouze pro RBD obrazy se zapnutým
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Fond</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Datový fond</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Vytvořeno</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Velikost</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Velikost objektu</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Funkce</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Poskytováno</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/A</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Celkem poskytováno</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Proužkovací jednotka</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Počet proužkování</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Nadřazené</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Předpona názvu bloku</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Pořadí</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Zachycené stavy</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Obraz</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Toto nastavení přebije globální hodnotu</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Globální</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Toto je globální hodnota. Pro tento obraz nebyla u této volby nastavena žádná hodnota.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>„/“ a „@“ nejsou dovoleny.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Žádné rbd fondy k dispozici --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Vybrat fond --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Použít vyhrazený datový fond</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Datový fond</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Vyhrazený fond který uchovává objektová data RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>např. 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Je třeba zvětšit.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Pokročilé</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Proužkování</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Jednotka proužku</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Vybrat jednotku proužku --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Tuto kolonku je třeba vyplnit, protože je definován počet proužků!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>Jednotka proužku je vyšší než velikost objektu.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Počet proužků</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Tuto kolonku je třeba vyplnit, protože je definována jednotka proužku!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Je třeba, aby počet proužků byl větší než nula.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD zachycený stav
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, vybrat, skutečné {Rename} ostatní {Create} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> zachycený stav
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>CHRÁNĚNO</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NECHRÁNĚNO</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Chystáte se vrátit zpět</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Vysypat koš</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Pro vyčištění, vyberte jeden nebo všechny obrazy a klikněte na</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Fond:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Název fondu…</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Vše</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Obnovit obraz</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Pro obnovení</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>zadejte nový název pro obraz a klikněte na</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nový název</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Platnost skončila v</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Chráněno do</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Tento obraz je chráněn do
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Koš</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologie iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Měnit tyto parametry z jejich výchozích hodnot obvykle není potřeba.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Nastavení</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Potvrdit</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Pokročilá nastavení</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>IQN cíle</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN nemá správný formát.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQN má následující formu zápisu „iqn.$rok-$měsíc.$adresaObráceně:$určenýNázev'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Například: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Další informace</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Tento cíl má změněná pokročilá nastavení.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portály</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Je třeba alespoň
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> bran.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Přidat portál</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Tento obraz má změněná nastavení.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Přidat obraz</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL ověřování</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Iniciátory</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Iniciátor</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>IQN klienta</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>Je třeba, aby se IQN iniciátoru neopakovalo.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Je třeba, aby uživatelská jména měla délku 8 až 64 znaků a
+ mohou obsahovat pouze písmena a znaky „.“, „@“, „-“, „_“ nebo „:“.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>Iniciátor spadá do skupiny. Obrazy budou nastaveny ve skupině.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Nepřidány žádné položky.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Přidat iniciátor</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Skupiny</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Skupina</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Přidat skupinu</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Nastavení RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Odebrat hodnotu místnímu nastavení. Namísto ní bude použita hodnota nadřazeného nastavení.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>Minimální hodnota je 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>problémy</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Synchronizuje se</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Připraveno</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Upravit režim zrcadlení fondu</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Pro úpravu režimu zrcadlení pro fond 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, vyberte ze seznamu nový režim a klikněte na 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aktualizovat
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Režim</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Před vypnutím zrcadlení je třeba odebrat klastry-protějšky.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ protějšek zrcadlení fondu
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> atributy
+ protějšku zrcadlení pro fond
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> a klikněte na
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Odeslat
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Název klastru</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Název klastru není platný</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX identif.</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX identif. …</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>CephX identif. není platný.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Adresy monitorů</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Čárkou oddělované adresy…</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>Adresa monitoru není platná.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX klíč</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Klíč v base64 kódování…</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>Je třeba, aby CephX klíč byl v kódování base64.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Seznam fondů</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Název může být tvořen pouze písmeny a číslicemi, dále ještě spojovníky a podtržítky.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Zvolený název pro profil mazacího kódu je už používán.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Zásuvný modul</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Shluky dat (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Je třeba, aby bylo 2 a více.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Shluky kódování (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Je třeba, aby bylo 1 a více.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Odhadování odolnosti (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Umístění (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Doména selhání crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Lokalita crush</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Žádné</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Technika</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Velikostpaketu</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Kořen crush</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Třída crush zařízení</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>libovolné</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Složka</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Zvolený název pro Ceph fond je už používán.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Typ fondul</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Vybrat typ fondu --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Skupiny umístění</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Je třeba alespoň jedné skupiny umístění!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Váš klastr nemůže obsloužit tolik skupin umístění. Přepočítejte potřebné množství skupin umístění.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Nápověda k výpočtu</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Sada pravidel crush</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Vybrat crush pravidlo --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Crush pravidlo</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Crush kroky</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Pravidlo nemůže být uplatněno na stávající klastr protože má
+ příliš málo OSD aby splnil minimum OSD vyžadovaných tímto pravidlem.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Replikovaná velikost</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Nejméně:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Nejvíce:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>Zadaná velikost je mimo rozsah. Platné hodnoty jsou od
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> do
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Profil mazacího kódu</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Žádný profil mazacího kódu --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Vyberte profil mazacího kódu --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC přebití</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Aplikace</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Komprese</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algoritmus</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Žádný algoritmus komprese mazání --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Minimální velikost blobu</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>např. 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>Hodnota by měla být vyšší než nula</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Nejvyšší velikost blobu</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>např. 512 KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>Hodnota by měla být vyšší než nejnižší velikost blobu</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Poměr</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Kompresní poměr</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>Hodnota by měla být z rozmezí 0.0 až 1.0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Není možné vytvořit RBD fond, který má v názvu „/“.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Změňte název nebo ze seznamu použití odeberte „rbd“</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Podrobnosti o stupních mezipaměti</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Podívejte se do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentace
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ jak nastavit a zapnout funkci správy brány objektů.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Seznam procesů služeb</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Výkonnostní čítače</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Načítání dat nádoby…</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Data nádoby se nepodařilo načíst.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>Identif.</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>Hodnota není platná.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Vlastník</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Vybrat uživatele --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>Identif.</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Typ rejstříku</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Pravidlo umístění</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Označovač</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Nejvyšší označovač</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Verze</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Hlavní verze</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Okamžik úpravy</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Skupinazóny</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Kvóta nádoby</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Zapnuto</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Nejvyšší velikost</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Neomezeno</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Nejvýše objektů</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Vybrat uživatelské jméno --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Automaticky vytvořit klíč</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Přístupový klíč</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Tajný klíč</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>E-mailová adresa</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Pozastaveno</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Systém</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Nejvýše nádob</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Dílčí uživatelé</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Schopnosti</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Kvóta uživatele</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Zobrazit</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Klíče</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Vybrat typ --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Oprávnění</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Vybrat oprávnění --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Dílčí uživatel</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>Zvolený identifikátor dílčího uživatele už je používán.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>číst, zapisovat</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>plné</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Swift klíč</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Automaticky vytvořit tajemství</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Načítání údajů uživatele…</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Údaje uživatele se nepodařilo načíst.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>Zvolený identif. uživatele už je používán.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Toto není platná e-mailová adresa.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>Zvolená e-mailová adresa už je používána.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Nejvýše nádob</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>Je třeba, aby zadaná hodnota byla 0 a vyšší.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3 klíč</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Nejsou zde žádní dílčí uživatelé.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Nejsou zde žádné klíče.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Nejsou zde žádné schopnosti.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Neomezená velikost</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Nejvyšší velikost</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Neomezené objekty</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Nejvýše objektů</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Stávající</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Aktualizováno ověřování pro objevování</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Nejsou k dispozici žádné portály.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Nejsou k dispozici žádné obrazy.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Nejsou k dispozici žádné obrazy. Ověřte, že jste cíli přidali obraz.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Nejsou k dispozici žádné iniciátory. Ověřte, že jste cíli přidali iniciátor.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Cíl</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Stav</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Bajtů čtení</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Bajtů zápis</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Operací/s čtení</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Operací/s zápis</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O od</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instance</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Název stroje</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problém</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Ukazatel postupu</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Vypnuto</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Upravit režim</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Přidat protějšek</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Upravit protějšek</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Smazat protějšek</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Vedoucí</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>Počet místních</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>Počet vzdálených</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>zrcadlit protějšek</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Klíč</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Hluboké zploštění</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Vrstvení</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Výhradní zámek</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Mapa objektů (vyžaduje výhradní zámek)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Žurnálování (vyžaduje výhradní zámek)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Vrácení zachyceného stavu RBD zpět</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Vrácení zpět</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Zachycený stav RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Smazáno v</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>identif.</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>typ</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>stav</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>verze</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Stroj</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>kořen</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Hodnocení</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Proces služby</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Aktivita</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Struktury složek</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>I-uzlů</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Využití</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Procesy služeb v pohotovosti</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>Hodnotu je možné aktualizovat za chodu.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Procesy služeb / klienti nezískávají tuto hodnotu
+ z databáze nastavení monitoru. Není umožněno nastavit tuto volbu
+ prostřednictvím „ceph config set …'. Tato volba by měla být nastavena
+ z příkazového řádku.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>Volba se uplatní pouze při spouštění procesu služby.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>Volba ovlivní pouze vytváření klastru.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>Volba ovlivní pouze vytvoření procesu služby.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Aktualizována volba nastavení
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Služba</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Stávající hodnota</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Upravitelné</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Aktualizována volba pro modul „
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Zapnout</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Vypnout</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Opětovné připojování, čekejte…</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Veřejná adresa</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Otevřené relace</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Počet do</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>OSD které byly dříve odznačeny nebudou označeny nazpět když spustí</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Počet ven</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSD nebudou automaticky odznačeny po nastaveném intervalu</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Počet aktivních</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSD není dovoleno spuštění</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Počet neaktivních</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Hlášení o selhání OSD jsou ignorovány, jako například že monitory OSD neoznačí jako nedostupné</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pozastavit</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Pozastavit čtení a zápisy</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Žádná kontrola</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Kontrola je vypnutá</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Žádná hloubková kontrola</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Hloubková kontrola je vypnutá</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Žádné zasypávání</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Zasypávání skupin umístění je pozastaveno</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Žádné obnovení</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Obnovování skupin umístění je pozastaveno</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Bitové třídění</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Třídit podle bitů</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Vyčištěné složky zachycených stavů</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD mají převedené sady zachycených stavů</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Smazáno při zotavování</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Mazání provedená při obnovování namísto peeringu</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Nepřekročitelný limit záznamu událostí PG</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Zapne nepřekročitelný limit na délku záznamu událostí v pg</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Aktualizovány OSD příznaky</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>ven</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>dovnitř</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>nedostupné</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Značka</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD ztraceno</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>označeno jako ztracené</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Vyčistit</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>vyčištěno</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>zlikvidovat</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>zlikvidováno</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>skupiny umístění</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Přečteno bajtů</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Zapsáno bajtů</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Operací/s čtení</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Operací/s zápis</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Označit OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Označit
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Max Backfills</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Recovery Max Active</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Recovery Max Single Start</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Recovery Sleep</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Uživatelsky určené</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Aktualizována rychlost zotavení OSD „
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> bylo inicializováno v následujícím OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Úloha</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Závažnost</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Zahájeno</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL adresa</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Aktualizováno</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Použito</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>K dispozici</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Čisté</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>Pracující</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Varování</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Neznámé</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>aktivní</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>žádné souborové systémy</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>aktivní</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>v pohotovosti</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/a</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>aktivní proces služby</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>kvórum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Služba NFS Ganesha není nastavena.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transport</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFS uživatel</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>Souborový systém CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(převzato z globálního nastavení)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>převzato z globálního nastavení</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Select what kind of user id squashing is performed --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Nejsou k dispozici žádné procesy služeb.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Režim mezipaměti</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Min Evict Age</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Min Flush Age</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Nejvýše bajtů cíle</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Nejvýše objektů cíle</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Nebyla přidána žádná aplikace</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Dosažen limit aplikací</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Fond může mít nejvýše čtyři definice aplikací.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Použitelné znaky „_a-zA-Z0-9“</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>Nejvyšší délka je 128 znaků</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtrovat nebo přidat aplikace</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Přidat aplikaci</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>profil mazacího kódu</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Velikost repliky</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Nejnovější změna</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Mazáním kódovaný profil</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Sada crush pravidel</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Zapsáno bajtů</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>nádoba</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Aktualizována nádoba objektové brány „
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Vytvořena nádoba objektové brány „
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>nádoby</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>uživatel</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Aktualizován uživatel objektové brány „
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Vytvořen uživatel objektové brány „
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>uživatelé</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Rozsah</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Čtení</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Vytvořit</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Vytvořena role „
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Aktualizována role „
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Systémová role</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Smazána role „
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Vytvořen uživatel „
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Aktualizovat uživatele</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Pokračovat</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Byli jste automaticky odhlášeni protože vaše role byly změněny.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Aktualizován uživatel „
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Smazán uživatel „
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Nepodařilo se smazat uživatele „
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Nyní jste přihlášení jako „
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>“.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Každý objekt je rozdělen v částech shluků dat, každé uložené na jiném OSD.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Počítat kódovací shluky pro každý objekt a ukládat je na různých OSD.
+ Počet kódovacích shluků je také počet OSD, které mohou vypadnou, aniž dojde ke ztrátě dat.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Zásuvný modul jerasure je nejobecnější a nejpřizpůsobivější,
+ je také výchozí pro Ceph fondy kódované mazáním.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Zásuvný modul isa obaluje knihovnu ISA. Funguje pouze na procesorech Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Název crush nádoby sloužící jako první krok CRUSH pravidla.
+ Například krok vzít výchozí.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Omezit umístění na zařízení určité třídy
+ (např., ssd nebo hdd), pomocí názvu crush třídy zařízení v CRUSH mapě.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Nastavit složku ze které načítat zásuvný modul mazacího kódu.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Umožnit všechny operace</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Umožnit pouze operace které neupraví server</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Neumožňuje operace čtení či zápisu, ale umožňuje ostatní</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Neumožňuje čtení, zápis nebo jinou operaci která upravuje atributy souboru nebo obsah složky</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Neumožnit vůbec žádný přístup</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Vyberte prioritu --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Nízká</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Vysoká</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Uplynulých 5 minut</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Uplynulých 15 minut</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Uplynulých 30 minut</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Uplynulá 1 hodina (výchozí)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Uplynulé 3 hodiny</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Uplynulých 6 hodin</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Uplynulých 12 hodin</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Uplynulých 24 hodin</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Včera</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Dnes</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Dnes doposud</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Včerejšek</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Uplynulé 2 dny</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Tento den minulý týden</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Předchozí týden</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Tento týden</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Tento týden doposud</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Uplynulých 7 dnů</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Předchozí měsíc</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Tento měsíc</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Tento měsíc doposud</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Uplynulých 30 dnů</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Uplynulých 90 dnů</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Uplynulých 6 měsíců</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>Uplynulý 1 rok</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Předchozí rok</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Tento rok</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Tento rok doposud</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Uplynulé 2 roky</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Uplynulých 5 let</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informace</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Nevybrány žádné položky.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Aby položku bylo možné znovu vybrat, je třeba nejprve zrušit její výběr</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Dosažen limit výběru</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Filtrovat štítky</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Přidat odznak</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Nejsou k dispozici žádné položky.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Přidat</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Klonovat</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Kopírovat</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Hloubková kontrola</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Zlikvidovat</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Zploštit</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Označit</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Označit</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Označit ztracené</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Odznačit</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Ochránit</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Přejmenovat</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Obnovit</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Přesunout do koše</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Zrušit ochranu</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Smazáno</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Naklonováno</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Zkopírováno</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Ano</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Ne</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Kvalita služby</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS Limit</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Požadovaný limit vst./výstup. bajtů za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS Limit</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Požadovaný limit vst./výstup. operací za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Read BPS Limit</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Požadovaný limit čtení bajtů za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Read IOPS Limit</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Požadovaný limit operací čtení za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Write BPS Limit</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Požadovaný limit zápisu bajtů za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Write IOPS Limit</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Požadovaný limit operací čtení za sekundu.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPS dávka</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>The desired burst limit of IO bytes.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPS Burst</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Požadovaný limit dávky vst./výstup. operací.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Read BPS Burst</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Požadovaný limit dávky bajtů čtení.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Read IOPS Burst</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>Požadovaný limit dávky čtení bajtů.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Write BPS Burst</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Požadovaný limit bajtů dávky zápisu.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Write IOPS Burst</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Požadovaný limit dávky operace zápisu.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Nepodařilo se
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Vykonává se</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>vykonat</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Vykonáno</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>neznámý úkol</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Vytváří se</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>vytvořit</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Aktualizuje se</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>aktualizovat</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Maže se</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>smazat</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD zachycený stav „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>režim zrcadlení pro fond „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>protějšek zrcadlení pro fond „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Název už je používán
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Název už je používán
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Název už je používán
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> obsahuje zachycené stavy.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Klonuje se</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>klonovat</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>Je třeba, aby zachycený stav
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> byl chráněný.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Kopíruje se</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>zkopírovat</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Zploštění</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>zploštit</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Zploštěno</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Název už je používán pro
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Není možné zrušit ochranu
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, protože obsahuje podřízené obrazy.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> není možné smazat, protože je chráněné.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Bere se zpět</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>vzít zpět</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Vzato zpět</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Přesouvá se</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>přesunout</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Přesunuto</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>obraz „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“ do koše
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Obraz se nedaří najít.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Obnovuje se</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>obnovit</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Obnoveno</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>obraz „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“ do „
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Název „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“ už je používán pro jiný obraz.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>obraz „
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Čistí se</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>vyčistit</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Vyčištěno</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>všechny fondy</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>obrazy z
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Zrcadlení nelze vypnout protože obsahuje protějšek.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>fond „
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>profil mazacího kódu „
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>cíl „
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>“
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.de-DE.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.de-DE.xlf
new file mode 100644
index 00000000..4761eb83
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.de-DE.xlf
@@ -0,0 +1,4365 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="de-DE">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Navigation umschalten</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Dashboard</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Cluster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Hosts</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitore</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSDs</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Konfiguration</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSH-Zuordnung</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Manager-Module</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Protokolle</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Warnungen</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Pools</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Block</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Images</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Spiegelung</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Dateisysteme</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Objektgateway</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemons</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Benutzer</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Buckets</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Daten
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> für
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> werden abgerufen. Bitte warten...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Zuvor zwischengespeicherte Daten
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ für
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> werden angezeigt.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Daten
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> für
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/> konnten nicht geladen werden.
+ Prüfen Sie die Clusterintegrität.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Zurück</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Sprache auswählen</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Bereichsdaten werden geladen...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Lesen Sie die
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum
+ Konfigurieren und Aktivieren der Überwachungsfunktion.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Das Grafana-Dashboard ist nicht vorhanden. In der
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> wird beschrieben,
+ wie Grafana Dashboards hinzugefügt werden.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Grafana-Zeitauswahl</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Einstellungen für Zurücksetzungen</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Daten konnten nicht geladen werden.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>ausgewählt</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>gefunden</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>insgesamt</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Bearbeiten</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Name</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Beschreibung</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Lange Beschreibung</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Standard</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Daemon-Standard</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Services</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Werte</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu groß! Er darf nicht größer als
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/> sein.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu klein! Er darf nicht kleiner als
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/> sein.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Speichern</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>CRUSH-Zuordnungsanzeige</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Liste mit Hosts</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Gesamtleistung</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Keine Einträge gefunden</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Clusterprotokolle</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Revisionsprotokoll</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Konfiguration wird geladen...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Die Konfiguration konnte nicht geladen werden.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Manager-Modul bearbeiten</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>Der eingegebene Wert ist kein gültiger UUID, z. B.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>Der eingegebene Wert muss eine gültige IP-Adresse sein.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Dies ist ein Pflichtfeld.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu groß! Er muss kleiner als
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/> sein oder diesem Wert entsprechen.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu klein! Er muss größer als
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/> sein oder diesem Wert entsprechen.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>Der eingegebene Wert muss eine Zahl sein.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>Der eingegebene Wert muss eine Zahl oder Dezimalzahl sein.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Aktualisieren</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Status</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>Cluster-ID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>Monmap geändert</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>Monmap-Epoche</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>erforderliche Verbindung</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>erforderliche Überwachung</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>In Quorum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Nicht in Quorum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Abbrechen</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Sind Sie sicher dass Sie die ausgewählten
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> möchten?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Ja, ich bin sicher.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Clusterweite OSD-Flags</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Absenden</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Erweitert...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>OSD-Wiederherstellungspriorität</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Priorität</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Prioritätswerte anpassen</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Dies ist ein Pflichtfeld!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu groß! Er darf nicht größer als
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/> sein.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>Der eingegebene Wert ist zu klein! Er darf nicht kleiner als
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/> sein.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>OSD neu gewichten</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>Der Wert muss zwischen 0 und 1 liegen.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Neu gewichten</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Tief } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Sie sind dabei, einen
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub auf
+ das OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> anzuwenden.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {tief } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>OSD-Liste</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> wird markiert als
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>, wenn Sie den Vorgang fortsetzen.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>Es ist nicht sicher, das OSD zu vernichten!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> wird
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> , wenn Sie den Vorgang fortsetzen.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Details</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Wert</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Schließen</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Löschen</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Integrität</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statistiken</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Lesen Sie die
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum
+ Konfigurieren und Aktivieren der Verwaltungsfunktion für NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Clients</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Jeder Client hat Zugriff</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Adressen</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Pflichtfeld</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Muss mindestens einen kommagetrennten Wert enthalten</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Beispielsweise:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Zugriffstyp</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Clients hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Laden...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Kein Cluster verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Cluster auswählen --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Daemon hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Speicher-Back-End</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Keine Datenpools verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Speicher-Back-End auswählen --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Objektgatewaybenutzer</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Keine Benutzer verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Objektgatewaybenutzer auswählen --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFS-Benutzer-ID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- keine Clients verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- cephx-Client auswählen --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>CephFS-Name</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Sicherheitsbezeichnung</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Sicherheitsbezeichnung aktivieren</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFS-Pfad</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Pfad muss mit einem '/' beginnen und kann von einem Wort gefolgt werden</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Neues Verzeichnis wird erstellt</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Pfad</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Pfad darf nur ein einzelner '/' oder ein Wort sein</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Neuer Bucket wird erstellt</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFS-Protokoll</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFS-Tag</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Alternativer Zugriff für
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>-Mountpunkte (dürfen keinen führenden / enthalten)
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Clients können Unterverzeichnisse möglicherweise nicht mounten (d. h. wenn das Tag = foo, kann der Client foo/baz möglicherweise nicht mounten).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Wenn unterschiedliche Tagoptionen verwendet werden, wird derselbe Pfad möglicherweise mehrfach exportiert.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>Die Position dieses
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>-Exports
+ auf dem
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo-Dateisystem
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (muss eindeutig sein).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Wenn unterschiedliche Pseudo-Optionen verwendet werden, wird derselbe Pfad möglicherweise mehrfach exportiert.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Kein Zugriffstyp verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Zugriffstyp auswählen --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- Kein Squash verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- Durchzuführende Benutzer-ID-Squashing-Art auswählen --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Transportprotokoll</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Willkommen bei Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Benutzername ist erforderlich</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Passwort ist erforderlich</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Anmeldung</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Der Benutzer ist in Ceph leider nicht enthalten.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Kehren Sie zur
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Anmeldeseite
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zurück. Sie werden vom Identitätsanbieter abgemeldet, wenn Sie versuchen, sich erneut anzumelden.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Verboten</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Leider sind Sie nicht berechtigt, den gewünschten Inhalt anzuzeigen.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Leider konnte der gewünschte Inhalt nicht gefunden werden.</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Alle löschen</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Neue Benachrichtigungen</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Keine Hintergrundaufgaben vorhanden.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Hintergrundaufgaben</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Hilfe</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Dokumentation</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>Über</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Dashboard-Einstellungen</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Benutzerverwaltung</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Angemeldeter Benutzer</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Angemeldet als
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Abmelden</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Name...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Der ausgewählte Name wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Beschreibung...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Berechtigungen</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Rollen</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Benutzername</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Passwort</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Passwort bestätigen</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Passwortbestätigung stimmt nicht mit dem Passwort überein.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Vollständiger Name</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>E-Mail-Adresse</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>Ungültige E-Mail-Adresse.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Sie sind dabei, die Lese-/Aktualisierungsberechtigungen für Benutzer von Ihrem eigenen Benutzer zu entfernen.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Wenn Sie den Vorgang fortsetzen, können Sie Benutzerrollen nicht mehr hinzufügen oder entfernen.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Möchten Sie den Vorgang wirklich fortsetzen?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Leistungsindikatoren nicht verfügbar</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Attribute (OSD-Zuordnung)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Metadaten nicht verfügbar</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadaten</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Leistungsindikator</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histogramm nicht verfügbar:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histogramm</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Leistungsdetails</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Aktuelle Werte</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Typ</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Min.</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Max.</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Flags</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Quelle</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Ebene</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Kann zur Laufzeit aktualisiert werden (bearbeitbar)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Tags</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Auflistungswerte</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Siehe auch</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Clusterstatus</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Manager-Daemons</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Objektgateways</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Metadatenserver</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI-Gateways</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>Client-IOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Clientdurchsatz</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Client-Lese-/Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Wiederherstellungsdurchsatz</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Scrub</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Leistung</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Rohkapazität</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objekte</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>Platzierungsgruppen pro OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Platzierungsgruppenstatus</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Kapazität</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Weitere Details finden Sie in den
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Protokollen
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Ränge</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Image in Papierkorb verschieben</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Um
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> in den Papierkorb zu verschieben,
+ klicken Sie auf
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Image verschieben
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optional können Sie ein Ablaufdatum auswählen.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>Schutz läuft ab am</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NICHT GESCHÜTZT</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Falsches Datumsformat. Verwenden Sie "TT.MM.JJJJ HH:mm:ss".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>Schutz ist bereits abgelaufen. Wählen Sie ein künftiges Datum aus oder lassen Sie es leer.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Image verschieben</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Übersicht</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Ziele</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Ermittlungsauthentifizierung</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Benutzer</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Benutzernamen müssen zwischen 8 und 64 Zeichen lang sein und
+ dürfen nur Buchstaben, '.', '@', '-', '_' oder ':' enthalten.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Gemeinsamer Benutzer</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Gemeinsames Passwort</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Lesen Sie die
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum
+ Konfigurieren und Aktivieren der Verwaltungsfunktion für iSCSI-Ziele.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Verfügbare Informationen:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>iSCSI-Ziele nicht verfügbar</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Nur für RBD-Images verfügbar, bei denen
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> aktiviert ist
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Datenpool</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Erstellt</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Größe</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Objektgröße</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Funktionen</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Bereitgestellt</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>n. v.</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Bereitgestellt gesamt</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Striping-Einheit</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Striping-Anzahl</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Übergeordnet</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Präfix für Blockname</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Reihenfolge</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Snapshots</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Image</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Diese Einstellung überschreibt den globalen Wert</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Global</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Dies ist der globale Wert. Kein Wert für diese Option wurde für dieses Image festgelegt.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' und '@' sind nicht zulässig.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Keine rbd-Pools verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Pool auswählen --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Dedizierten Datenpool verwenden</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Datenpool</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Dedizierter Pool zur Speicherung von RBD-Objektdaten.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>z. B. 10GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Sie müssen die Größe erhöhen.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Erweitert</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Striping</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Stripe-Einheit</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Stripe-Einheit auswählen --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Dies ist ein Pflichtfeld, da eine Stripe-Anzahl definiert wurde!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>Die Stripe-Einheit ist größer als die Objektgröße.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Stripe-Anzahl</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Dies ist ein Pflichtfeld, da eine Stripe-Einheit definiert wurde!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Die Stripe-Anzahl muss größer als 0 sein.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD-Snapshot
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Umbenennen} other {Erstellen} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>GESCHÜTZT</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NICHT GESCHÜTZT</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Sie sind dabei, ein Rollback durchzuführen</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Papierkorb bereinigen</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Zum Bereinigen ein oder alle Images auswählen und klicken</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Pool:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Poolname...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Alle</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Image wiederherstellen</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Zum Wiederherstellen</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>Neuen Namen des Images eingeben und klicken</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Neuer Name</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Abgelaufen am</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Geschützt bis</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Dieses Image ist geschützt bis
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Papierkorb</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>iSCSI-Topologie</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Eine Änderung dieser Parameter von ihren Standardwerten ist in der Regel nicht erforderlich.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Einstellungen</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Bestätigen</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Erweiterte Einstellungen</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>Ziel-IQN</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN hat ein fehlerhaftes Muster.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Eine IQN hat die folgende Notation 'iqn.$jahr-$monat.$umkehradresse:$definierterName'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Zum Beispiel: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Weitere Informationen</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Erweiterte Einstellungen bei diesem Ziel wurden geändert.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portale</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Es sind mindestens
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> Gateways erforderlich.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Portal hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Einstellungen bei diesem Image wurden geändert.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Image hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL-Authentifizierung</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Initiatoren</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Initiator</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>Client-IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>Initiator-IQN muss eindeutig sein.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Benutzernamen müssen zwischen 8 und 64 Zeichen lang sein und
+ dürfen nur Buchstaben, '.', '@', '-', '_' oder ':' enthalten.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>Der Initiator gehört zu einer Gruppe. Images werden in der Gruppe konfiguriert.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Keine Elemente hinzugefügt.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Initiator hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Gruppen</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Gruppe</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Gruppe hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>RBD-Konfiguration</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Entfernen Sie den lokalen Konfigurationswert. Stattdessen wird der übergeordnete Konfigurationswert übernommen und verwendet.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>Der Mindestwert lautet 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Probleme</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Wird synchronisiert</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Fertig</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Spiegelungsmodus für Pool bearbeiten</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Wählen Sie zum Bearbeiten des Spiegelungsmodus für den Pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> einen neuen Modus aus der Liste aus und klicken Sie auf 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aktualisieren
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Modus</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Vor dem Deaktivieren der Spiegelung müssen Peer-Cluster entfernt werden.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ Peer für Poolspiegelung
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Bearbeiten} other {Hinzufügen} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> Der Pool
+ Spiegeln Sie Peer-Attribute für Pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> und klicken Sie auf
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Absenden
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Clustername</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Der Clustername ist ungültig.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX-ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX-ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>Die CephX ID ist ungültig.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Adressen der Monitore</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Kommagetrennte Adressen...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>Die Anrede ist ungültig.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX-Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64-codierter Schlüssel...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>CephX-Schlüssel muss base64-codiert sein.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Pool-Liste</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Der Name darf nur alphanumerische Zeichen, Bindestriche und Unterstriche enthalten.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Der ausgewählte Löschcode-Profilname wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Plugin</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Datenblöcke (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Muss größer oder gleich 2 sein.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Datenblöcke für die Codierung (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Muss größer oder gleich 1 sein.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Dauerhaftigkeitsschätzung (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Standort (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Crush-Ausfalldomäne</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Crush-Standort</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Keine</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Technik</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Paketgröße</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Crush-Stamm</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Crush-Geräteklasse</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>beliebig</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Verzeichnis</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Der ausgewählte Poolname wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Pooltyp</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Pooltyp auswählen --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Platzierungsgruppen</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Es wird mindestens eine Platzierungsgruppe benötigt.</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Ihr Cluster kann nicht so viele Platzierungsgruppen verarbeiten. Berechnen Sie die benötigte Anzahl an Platzierungsgruppen.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Hilfe zur Berechnung</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>Die aktuellen Einstellungen für die Platzierungsgruppen wurden für Sie berechnet.
+ Stellen Sie vor dem Senden sicher, dass die Werte Ihren Anforderungen entsprechen.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Crush-Regelsatz</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Crush-Regel auswählen --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Crush-Regel</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Crush-Schritte</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Die Regel kann im aktuellen Cluster nicht verwendet werden,
+ da es zu wenige OSDs enthält, um das von dieser Regel geforderte OSD-Minimum zu erfüllen.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Reproduzierte Größe</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>Die angegebene Größe liegt außerhalb des Bereichs. Gültige Werte liegen zwischen
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> und
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Löschcode-Profil</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Kein Löschcode-Profil verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Löschcode-Profil auswählen --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC-Überschreibungen</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Anwendungen</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Komprimierung</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algorithmus</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Kein Löschkomprimierungsalgorithmus verfügbar --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Minimale Blobgröße</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>z. B. 128KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>Wert sollte größer als 0 sein</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Maximale Blobgröße</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>z. B. 512KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>Wert sollte größer als die minimale Blobgröße sein</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Verhältnis</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Komprimierungsverhältnis</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>Wert sollte zwischen 0,0 und 1,0 liegen</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Es ist nicht möglich, einen RBD-Pool mit '/' im Namen zu erstellen.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Ändern Sie den Namen oder entfernen Sie 'rbd' aus der Anwendungsliste.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Details zu den Cache-Ebenen</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Lesen Sie die
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Dokumentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> zum
+ Konfigurieren und Aktivieren der Verwaltungsfunktion für das Objektgateway.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Liste der Daemons</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Leistungsindikatoren</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Bucket-Daten werden geladen...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Die Bucket-Daten konnten nicht geladen werden.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>Der Wert ist ungültig.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Inhaber</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Benutzer auswählen --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Indextyp</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Platzierungsregel</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Marker</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Maximum für Marker</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Version</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Masterversion</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Änderungszeit</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Zonengruppe</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Bucket-Quote</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Aktiviert</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Maximale Größe</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Unbegrenzt</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Maximale Objekte</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Benutzername auswählen --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Schlüssel automatisch generieren</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Zugriffsschlüssel</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Geheimer Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>E-Mail-Adresse</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Angehalten</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>System</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {Nein} 1 {Ja} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Maximale Buckets</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Unterbenutzer</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Befähigungen</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Benutzerquote</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Anzeigen</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Typ auswählen --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Berechtigung</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Berechtigung auswählen --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Unterbenutzer</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>Die ausgewählte Unterbenutzer-ID wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>lesen, schreiben</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>voll</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Swift-Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Geheimnis automatisch generieren</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Benutzerdaten werden geladen...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Die Benutzerdaten konnten nicht geladen werden.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>Die ausgewählte Benutzer-ID wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Dies ist keine gültige E-Mail-Adresse.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>Die ausgewählte E-Mail-Adresse wird bereits verwendet.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Max. Buckets</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>Der eingegebene Wert muss &gt;=0 sein.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3-Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Keine Unterbenutzer vorhanden.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Keine Schlüssel vorhanden.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Keine Befähigungen vorhanden.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Unbegrenzte Größe</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Max. Größe</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Unbegrenzte Objekte</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Max. Objekte</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Aktuell</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target> Ermittlungsauthentifizierung aktualisiert</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Keine Portale verfügbar.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Keine Images verfügbar.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Keine Images verfügbar. Fügen Sie dem Ziel ein Image hinzu.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Keine Initiatoren verfügen. Fügen Sie dem Ziel einen Initiator hinzu.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Ziel</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Zustand</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Bytes für Lesevorgang</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Bytes für Schreibvorgang</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O seit</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instanz</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Hostname</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problem</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Fortschritt</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Deaktiviert</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Bearbeitungsmodus</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Peer hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Peer bearbeiten</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Peer löschen</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Leader</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># lokal</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># remote</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>Peer spiegeln</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Schlüssel</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Umfassende Vereinfachung</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Schichtung</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Exklusive Sperre</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Objektzuordnung (erfordert exklusive Sperre)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Journaling (erfordert exklusive Sperre)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Rollback für RBD-Snapshot</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Rollback</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>RBD-Snapshot</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Gelöscht am</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>Typ</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>Zustand</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>Version</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>Stamm</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Rang</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Aktivität</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inodes</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Nutzung</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Standby-Daemons</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>Der Wert kann zur Laufzeit aktualisiert werden.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Daemons/Clients rufen diesen Wert nicht aus der
+ Datenbank 'monitor config' ab. Es ist nicht zulässig, diese Option über 'ceph config
+ set ...' festzulegen. Diese Option sollte über 'ceph.conf' oder an der
+ Befehlszeile konfiguriert werden.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>Die Option wird nur während des Daemon-Starts wirksam.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>Die Option wirkt sich nur auf die Cluster-Erstellung aus.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>Die Option wirkt sich nur auf die Daemon-Erstellung aus.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Aktualisierte config-Option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Service</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Aktueller Wert</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Bearbeitbar</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Aktualisierte Optionen für Modul &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Aktivieren</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Deaktivieren</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Verbindung wird erneut hergestellt, bitte warten...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Öffentliche Adresse</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Offene Sitzungen</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Kein In-Vorgang</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>OSDs, die zuvor als 'out' markiert wurden, werden beim Start nicht wieder markiert</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Kein Out-Vorgang</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSDs werden nach dem konfigurierten Intervall nicht automatisch als 'out' markiert</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Kein Up-Vorgang</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSDs dürfen nicht gestartet werden</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Kein Down-Vorgang</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>OSD-Fehlerberichte werden ignoriert, sodass die Monitore die OSDs nicht als ausgefallen markieren</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pause</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Hält Lese- und Schreibvorgänge an</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Kein Scrub</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Scrubbing ist deaktiviert</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Kein umfassender Scrub</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Umfassendes Scrubbing ist deaktiviert</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Kein Abgleich</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Abgleich der Platzierungsgruppen ist ausgesetzt</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Keine Wiederherstellung</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Wiederherstellung der Platzierungsgruppen ist ausgesetzt</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Bitweise Sortierung</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Bitweise Sortierung verwenden</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Bereinigte Snapdirs</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSDs besitzen konvertierte Snapsets</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Löschvorgänge bei Wiederherstellungen</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Bei der Wiederherstellung anstelle des Peerings durchgeführte Löschvorgänge</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Hardlimit für Platzierungsgruppen-Protokoll</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Legt ein Hardlimit für die Platzierungsgruppen-Protokolllänge fest</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Aktualisierte OSD-Flags</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>aus</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>ein</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>ausgefallen</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Markieren</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD verloren</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>markierter Verlust</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Bereinigen</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>bereinigt</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>vernichten</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>vernichtet</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>Platzierungsgruppen</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Bytes für Lesevorgang</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Bytes für Schreibvorgang</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/> markieren
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/> markieren
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Max. Abgleiche</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Wiederherstellung, max. aktiv</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Wiederherstellung, max. - einzelner Start</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Wiederherstellung - Inaktivität</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Benutzerdefiniert</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Aktualisierte OSD-Wiederherstellungsgeschwindigkeits-Priorität &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> wurde im folgenden OSD initialisiert:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Auftrag</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Schweregrad</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Gestartet</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Aktualisiert</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Verwendet</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Verf.</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Bereinigen</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>In Bearbeitung</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Warnung</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Unbekannt</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>aktiv</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>keine Dateisysteme</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>aktiv</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>Standby</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n. v.</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>aktiver Daemon</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>Quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Der NFS Ganesha-Dienst ist nicht konfiguriert.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transport</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFS-Benutzer</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>CephFS-Dateisystem</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(aus globaler Konfiguration übernommen)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>aus globaler Konfiguration übernommen</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Durchzuführende Benutzer-ID-Squashing-Art auswählen --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Keine Daemons verfügbar.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Cache-Modus</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Min. Alter für Vertreibung</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Min. Alter für Leerung</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Max. Bytes für Ziel</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Max. Objekte für Ziel</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Keine Anwendungen hinzugefügt</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Anwendungslimit erreicht</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Ein Pool kann nur bis zu vier Anwendungsdefinitionen aufweisen.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Zulässige Zeichen '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>Maximale Länge beträgt 128 Zeichen</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Anwendungen filtern oder hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Anwendung hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>Löschcode-Profil</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Größe des Replikats</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Letzte Änderung</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Profil mit Löschcodierung</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Crush-Regelsatz</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Bytes für Schreibvorgang</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>Bucket</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Aktualisierter Objektgateway-Bucket &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Erstellter Objektgateway-Bucket &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>Buckets</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>Benutzer</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Aktualisierter Objektgatewaybenutzer &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Erstellter Objektgatewaybenutzer &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>Benutzer</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Bereich</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Lesen</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Erstellen</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Erstellte Rolle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Aktualisierte Rolle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Systemrolle</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Gelöschte Rolle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Erstellter Benutzer &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Benutzer aktualisieren</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Fortfahren</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Sie wurden automatisch abgemeldet, da Ihre Rollen geändert wurden.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Aktualisierter Benutzer &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Gelöschter Benutzer &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Fehler beim Löschen des Benutzers &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Sie sind derzeit angemeldet als &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Jedes Objekt wird in Datenblöcke aufgeteilt und jeweils auf einem anderen OSD gespeichert.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Berechnen Sie Codierungsdatenblöcke für jedes Objekt und speichern Sie sie auf unterschiedlichen OSDs.
+ Die Anzahl der Codierungsdatenblöcke entspricht auch der Anzahl der OSDs, die ausfallen können, ohne dass Daten verloren gehen.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Das jerasure-Modul ist das allgemeinste und flexibelste Modul
+ und fungiert auch als der Standard für Ceph-Pools mit Löschcodierung.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>Die flexiblere Technik ist 'reed_sol_van :', wobei es ausreicht, k
+ und m festzulegen. Die Technik 'cauchy_good' kann schneller sein. Sie müssen jedoch die Paketgröße sorgfältig
+ auswählen. Sämtliche 'reed_sol_r6_op'-, 'liberation'-, 'blaum_roth'- und 'liber8tion'-Vorgänge sind dahingehend RAID6-Entsprechungen,
+ dass sie nur mit 'm=2' konfiguriert werden können.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>Die Codierung wird jeweils für Pakete auf Bytes-Größe vorgenommen.
+ Die Auswahl der richtigen Paketgröße ist schwierig.
+ In der Jerasure-Dokumentation sind ausführliche Informationen zu diesem Thema enthalten.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Bei Verwendung des Jerasure-Moduls, wenn ein Objekt mit Löschcodierung auf mehreren OSDs gespeichert ist,
+ müssen alle anderen OSDs gelesen werden, um die verloren gegangenen Daten eines OSDs wiederherzustellen.
+ Wenn jerasure beispielsweise mit 'k=8' und 'm=4' konfiguriert ist,
+ müssen bei Verlust eines OSDs zum Reparieren die elf anderen gelesen werden.
+
+ Das lrc-Löschcode-Modul erstellt lokale Paritätsdatenblöcke, um die Wiederherstellung mit weniger OSDs auszuführen.
+ Wenn lrc beispielsweise mit 'k=8', 'm=4' und 'l=4' konfiguriert ist, wird ein zusätzlicher Paritätsdatenblock für jeweils vier OSDs erstellt.
+ Geht ein einzelnes OSD verloren, kann es mit nur vier OSDs anstelle
+ von elf wiederhergestellt werden.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Gruppieren Sie die Codierungs- und Datenblöcke in Sätze entsprechend dem Speicherort.
+ Beispielsweise werden für 'k=4' und 'm=2', wenn der Speicherort '3' entspricht, zwei Dreiergruppen erstellt.
+ Jeder Satz kann wiederhergestellt werden, ohne dass Datenblöcke aus einem anderen Satz gelesen werden.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>Der Typ des Crush-Buckets, in dem jeder durch l definierte Satz von Datenblöcken gespeichert wird.
+ Wenn er beispielsweise auf 'rack' festgelegt ist, wird jede Gruppe an l-Datenblöcken in einem anderen Rack platziert.
+ Er wird zum Erstellen eines CRUSH-Regelschritts verwendet, beispielsweise für einen Schritt zum Auswählen des Racks.
+ Wenn er nicht festgelegt ist, wird keine solche Gruppierung vorgenommen.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Das isa-Modul kapselt die ISA-Bibliothek und wird nur auf Intel-Prozessoren ausgeführt.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>Das ISA-Modul wird in zwei Reed Solomon-Formularen bereitgestellt.
+ Wenn 'reed_sol_van' festgelegt ist, entspricht dies Vandermonde. Ist 'cauchy' festgelegt, entspricht dies 'Cauchy'.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>Das shec-Modul kapselt die SHEC-Mehrfachbibliothek.
+ Dadurch kann ceph Daten effizienter wiederherstellen als Reed Solomon-Codes.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>Die Anzahl der Paritätsdatenblöcke, von denen jeder jeden Datenblock in seinem Berechnungsbereich enthält.
+ Die Anzahl wird als eine Dauerhaftigkeitsschätzung verwendet. Wenn beispielsweise 'c=2' vorliegt,
+ können 2 OSDs ausfallen, ohne dass Daten verloren gehen.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Der Name des für den ersten Schritt der CRUSH-Regel verwendeten Crush-Buckets.
+ Beispielsweise 'step take default'.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Stellen Sie sicher, dass sich keine zwei Datenblöcke in einem Bucket mit derselben Ausfalldomäne befinden.
+ Wenn die Ausfalldomäne beispielsweise als Host fungiert, werden keine zwei Datenblöcke auf demselben Host gespeichert.
+ Er wird zum Erstellen eines CRUSH-Regelschritts verwendet, beispielsweise 'step chooseleaf host'.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Schränken Sie mithilfe der Klassennamen für Crush-Geräte in der CRUSH-Zuordnung die Platzierung
+ auf Geräte einer bestimmten Klasse (z. B. SSD oder HDD) ein.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Legen Sie den Verzeichnisnamen fest, über den das Löschcode-Modul geladen wird.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Lässt alle Vorgänge zu</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Lässt nur Vorgänge zu, die den Server nicht ändern</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Lässt weder Lese- noch Schreibvorgänge zu, jedoch alle anderen Vorgänge</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Lässt Lese-/Schreibvorgänge und andere Vorgänge nicht zu, die Dateiattribute oder Verzeichnisinhalte ändern</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Lässt überhaupt keinen Zugriff zu</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Priorität auswählen --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Niedrig</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Hoch</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Letzte 5 Minuten</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Letzte 15 Minuten</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Letzte 30 Minuten</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Letzte Stunde (Standard)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Letzte 3 Stunden</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Letzte 6 Stunden</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Letzte 12 Stunden</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Letzte 24 Stunden</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Gestern</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Heute</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Heute bisher</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Vorgestern</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Letzte 2 Tage</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Dieser Tag letzte Woche</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Vorwoche</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Diese Woche</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Diese Woche bisher</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Letzte 7 Tage</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Vormonat</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Dieser Monat</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Dieser Monat bisher</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Letzte 30 Tage</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Letzte 90 Tage</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Letzte 6 Monate</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>Letztes Jahr</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Vorjahr</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Dieses Jahr</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Dieses Jahr bisher</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Letzte 2 Jahre</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Letzte 5 Jahre</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informationen</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Keine Elemente ausgewählt.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Elementauswahl zum erneuten Auswählen aufheben</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Auswahllimit erreicht</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Tags filtern</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Badge hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Keine Elemente verfügbar.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Hinzufügen</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Klonen</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Kopieren</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Umfassender Scrub</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Vernichten</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Vereinfachen</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Als ausgefallen markieren</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Mit Befehl 'In' markieren</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Als verloren markieren</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Mit Befehl 'Out' markieren</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Schützen</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Umbenennen</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Wiederherstellen</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>In Papierkorb verschieben</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Schutz aufheben</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Gelöscht</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Geklont</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Kopiert</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Ja</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Nein</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Quality of Service</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS-Limit</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Das gewünschte Limit der E/A-Bytes pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS-Limit</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Das gewünschte Limit der E/A-Vorgänge pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>BPS-Limit für Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Das gewünschte Limit der gelesenen Bytes pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>IOPS-Limit für Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Das gewünschte Limit für Lesevorgänge pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>BPS-Limit für Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Das gewünschte Limit der geschriebenen Bytes pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>IOPS-Limit für Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Das gewünschte Limit für Schreibvorgänge pro Sekunde.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPS-Block</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>Das gewünschte Blocklimit der E/A-Bytes.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPS-Block</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Das gewünschte Blocklimit der E/A-Vorgänge.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>BPS-Block für Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Das gewünschte Blocklimit der gelesenen Bytes.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>IOPS-Block für Lesevorgänge</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>Das gewünschte Blocklimit der Lesevorgänge.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>BPS-Block für Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Das gewünschte Blocklimit der geschriebenen Bytes.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>IOPS-Block für Schreibvorgänge</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Das gewünschte Blocklimit der Schreibvorgänge.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Fehler bei
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Wird ausgeführt</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>ausführen</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Ausgeführt</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>Unbekannte Aufgabe</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Wird erstellt</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>erstellen</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Wird aktualisiert</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>aktualisieren</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Wird gelöscht</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>löschen</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD-Snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Spiegelungsmodus für Pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Peer für Pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' spiegeln
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Name wird bereits von
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> verwendet.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Name wird bereits von
+ <x id="INTERPOLATION" equiv-text="{{name}}"/> verwendet.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Name wird bereits von
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> verwendet.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> enthält Snapshots.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Wird geklont</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>klonen</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>Snapshot von
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> muss geschützt sein.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Wird kopiert</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>kopieren</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Wird vereinfacht</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>vereinfachen</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Vereinfacht</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Name wird bereits von
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> verwendet.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Der Schutz von
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> kann aufgrund enthaltener untergeordneter Images nicht aufgehoben werden.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Kann
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> nicht löschen, da es geschützt ist.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Rollback wird ausgeführt</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>Rollback</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Rollback wurde ausgeführt</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Wird verschoben</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>verschieben</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Verschoben</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>Image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' in Papierkorb verschieben
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Image konnte nicht gefunden werden.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Wird wiederhergestellt</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>wiederherstellen</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Wiederhergestellt</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>Image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' in '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>' verschieben
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Image-Name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' wird bereits verwendet.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Wird bereinigt</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>bereinigen</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Bereinigt</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>alle Pools</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>Images von
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Spiegelung kann nicht deaktiviert werden, da sie einen Peer enthält.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>Pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>Löschcode-Profil '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>Ziel '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.es-ES.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.es-ES.xlf
new file mode 100644
index 00000000..b3a8eb5f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.es-ES.xlf
@@ -0,0 +1,4371 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="es-ES">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Alternar navegación</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Consola</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Clúster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Hosts</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitores</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSDs</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Configuración</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>Mapa de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Módulos de gestor</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Registros</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Alertas</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Repositorios</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Bloque</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Imágenes</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Duplicación</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Sistemas de archivos</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemons</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Usuarios</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Papeleras</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Obteniendo datos
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+para
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Espere.
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Mostrando datos guardados previamente en caché
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+para
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>No se han podido cargar los datos
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> para
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+Consulte el estado del clúster.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Atrás</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Seleccione un idioma</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Cargando datos del panel...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Consulte la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentación
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre cómo
+configurar y habilitar la supervisión.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>No existe la consola de Grafana. Consulte la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentación
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre cómo
+ añadir consolas a Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Selector de hora de Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Restablecer ajustes</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Error al cargar los datos.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>seleccionados</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>encontrados</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>total</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Editar</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nombre</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Descripción</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Descripción larga</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Opción por defecto</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Daemon por defecto</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Servicios</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Valores</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>El valor introducido es demasiado alto. No debe ser mayor que
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>El valor introducido es demasiado bajo. No debe ser menor que
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Guardar</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>Visor del mapa de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Lista de hosts</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Rendimiento general</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>No se encuentra ninguna entrada</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Registros del clúster</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Registros de auditoría</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Cargando configuración...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>No es posible cargar la configuración.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Módulo del gestor de edición</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>El valor introducido no es un UUID válido, por ejemplo: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>El valor introducido debe ser una dirección IP válida.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Este campo es obligatorio.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>El valor introducido es demasiado alto. Debe ser menor o igual que
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>El valor introducido es demasiado bajo. Debe ser mayor o igual que
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>El valor introducido debe ser un número.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>El valor introducido debe ser un número o un decimal.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Actualizar</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Estado</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>ID de clúster</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>Mapa de supervisión modificado</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>Época de mapa de supervisión</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quórum de con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quórum de mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>con requerido</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>mon requerido</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>Con quórum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Sin quórum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Cancelar</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>¿Seguro que quiere
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> el elemento
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> seleccionado?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Sí, seguro.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Indicadores OSD de todo el clúster</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Enviar</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Avanzado...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Prioridad de recuperación de OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Prioridad</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Personalizar valores de prioridad</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Este campo es obligatorio.</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>El valor introducido es demasiado alto. No debe ser mayor que
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>El valor introducido es demasiado bajo. No debe ser menor que
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Reequilibrar peso de OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>El valor debe estar entre 0 y 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Reequilibrar peso</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Depuración de OSDs
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Profundo} }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Se dispone a aplicar una
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>depuración
+ al OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {profundo} }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Lista de OSD</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Si continúa, el
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ se marcará
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>No es seguro destruir el OSD.</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Si continúa, el
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ se
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Detalles</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Valor</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Cerrar</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Suprimir</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Estado</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Estadísticas</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Consulte la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentación
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre cómo configurar y habilitar la función de gestión de NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Clientes</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Cualquier cliente puede acceder</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Destinatarios</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Campo requerido</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Debe contener uno o varios valores separados por comas</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Por ejemplo:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Tipo de acceso</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Reducir privilegios</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Añadir clientes</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Cargando...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- No hay ningún clúster disponible --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Seleccione el clúster --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Añadir daemon</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Motor de almacenamiento</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- No hay ningún repositorio de datos disponible --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Seleccione el motor de almacenamiento --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Usuario de Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- No hay ningún usuario disponible --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Seleccione el usuario de Object Gateway --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>ID de usuario de CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- No hay ningún cliente disponible --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Seleccione el cliente de CephX --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nombre de CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Etiqueta de seguridad</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Habilitar etiqueta de seguridad</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Ruta de CephFS</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>La ruta debe empezar por "/" y puede ir seguida de una palabra</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Se creará un directorio nuevo</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Ruta</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>La ruta solo puede ser una "/" o una palabra</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Se creará una papelera nueva</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protocolo NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Etiqueta NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Acceso alternativo para montajes
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (no debe empezar con /).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Puede que los clientes no monten subdirectorios (es decir, si Etiqueta = foo, el cliente puede que no monte foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Al usar distintas opciones de Etiqueta, la misma Ruta se puede exportar varias veces.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>La posición que ocupa esta exportación
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ en
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (debe ser exclusiva).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Al usar distintas opciones de Pseudo, la misma Ruta se puede exportar varias veces.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- No hay ningún tipo de acceso disponible --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Seleccione el tipo de acceso --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- No hay ninguna reducción de privilegios disponible --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- Seleccione el tipo de reducción de privilegios de ID de usuario que se va a realizar --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protocolo de transporte</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>¡Bienvenidos a Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>El nombre de usuario es obligatorio</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>La contraseña es obligatoria</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Entrada</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Lo sentimos. El usuario no existe en Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Vuelva a la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Página de entrada
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Saldrá del proveedor de identidad cuando vuelva a intentar entrar a la sesión.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Prohibido</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Lo sentimos. No tiene permiso para ver lo que busca.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Lo sentimos. No se encuentra lo que busca</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Eliminar todo</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Notificaciones recientes</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>No hay tareas en segundo plano.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Tareas en segundo plano</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Ayuda</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Documentación</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>Acerca de</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Ajustes de la consola</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Gestión del usuario</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Usuario que ha entrado</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Ha entrado como
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Salir</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nombre...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>El nombre que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Descripción...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Permisos</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Funciones</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nombre de usuario</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Contraseña</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Confirmar contraseña</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Las contraseñas no coinciden.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Nombre completo</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>Correo electrónico</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>Correo electrónico no válido.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Se dispone a eliminar los permisos "lectura/actualización de usuario" de su propio usuario.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Si continúa, no podrá añadir ni eliminar funciones en ningún usuario.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>¿Seguro que desea continuar?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Los contadores de rendimiento no están disponibles</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Atributos (mapa de OSD)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Los metadatos no están disponibles</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadatos</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Contandor de rendimiento</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>El histograma no está disponible:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Escrituras</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Lecturas</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histograma</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Detalles de rendimiento</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Valores actuales</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Tipo</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Mín.</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Máx.</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Indicadores</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Origen</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Nivel</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Se puede actualizar en el tiempo de ejecución (editable)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Etiquetas</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Valores Enum</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Véase también</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Estado del clúster</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Daemons de gestor</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Instancias de Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Servidores de metadatos</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>Puertas de enlace iSCSI</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>IOPS de cliente</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Rendimiento del cliente</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Lectura/escritura de cliente</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Rendimiento de recuperación</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Depuración</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Rendimiento</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Capacidad en bruto</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objetos</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>Grupos de colocación por OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Estado del grupo de colocación</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Capacidad</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consulte la sección
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Registros
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> para obtener más datos.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Clasificaciones</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Clientes:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Mover una imagen a la papelera</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Para mover
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> a la papelera,
+ haga clic en
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mover imagen
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Opcionalmente, puede seleccionar una fecha de caducidad.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>La protección caduca a las</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>SIN PROTECCIÓN</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Formato de fecha erróneo. Use el formato "AAAA-MM-DD HH:mm:ss".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>La protección ya ha caducado. Seleccione una fecha del futuro o deje el campo vacío.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Mover imagen</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Resumen</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Destinos</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Autenticación de descubrimiento</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Usuario</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Los nombres de usuario deben tener entre 8 y 64 caracteres y
+ solo pueden incluir letras y estos caracteres: ".", "@", "-", "_" o ":".</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Usuario mutuo</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Contraseña mutua</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Consulte la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentación
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre cómo configurar y habilitar la función de gestión de destinos iSCSI.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Información disponible:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>Destinos iSCSI no disponibles</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Solo disponible para imágenes RBD con
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> habilitado
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Repositorio</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Repositorio de datos</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Creados</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Tamaño</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Tamaño del objeto</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Características</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Aprovisionados</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/D</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Total aprovisionado</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Unidad de repartición</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Recuento de repartición</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Padre</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Prefijo de nombre de bloque</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Orden</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Instantáneas</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Imagen</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Este ajuste sustituye al valor global</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Global</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Este es el valor global. No se ha definido ningún valor para esta opción para esta imagen.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>No se permiten los caracteres "/" ni "@".</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- No hay ningún repositorio RBD disponible --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Seleccione un repositorio --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Usar un repositorio dedicado para datos</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Repositorio de datos</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Repositorio dedicado para almacenar los datos de objeto de RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>ej.: 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Debe aumentar el tamaño.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Avanzado</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Repartición</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Unidad de repartición</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Seleccione la unidad de repartición --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Este campo es obligatorio porque se ha definido el recuento de repartición.</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>La unidad de repartición es mayor que el tamaño del objeto.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Recuento de repartición</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Este campo es obligatorio porque se ha definido la unidad de repartición.</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>El recuento de repartición debe ser mayor que 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantánea RBD
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Renombrar} other {Crear} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantánea
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>CON PROTECCIÓN</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>SIN PROTECCIÓN</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Se dispone a revertir</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Vaciar papelera</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Para limpiar, seleccione una imagen, o todas las imágenes, y haga clic en</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Repositorio:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nombre del repositorio...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Todas</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Restaurar imágenes</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Para restaurar</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>escriba el nombre nuevo de la imagen y haga clic en</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nombre nuevo</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Caducó a las</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Protección hasta</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Esta imagen está protegida hasta el
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Papelera</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topología iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Normalmente no es necesario cambiar los valores por defecto de estos parámetros.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Ajustes</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Almacén</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Confirmar</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Ajustes avanzados</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>IQN de destino</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>El IQN tiene un patrón erróneo.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Los IQN tienen esta notación: iqn.$year-$month.$reversedAddress:$definedName</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Por ejemplo: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Más información</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Este destino tiene ajustes avanzados modificados.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portales</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Se requieren al menos
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> puertas de enlace.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Añadir portal</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Esta imagen tiene ajustes modificados.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Añadir imagen</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Autenticación de ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Iniciadores</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Iniciador</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>IQN del cliente</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>El IQN del iniciador debe ser exclusivo.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Los nombres de usuario deben tener entre 8 y 64 caracteres y
+ solo pueden incluir letras y estos caracteres: ".", "@", "-", "_" o ":".</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>El iniciador pertenece a un grupo. Las imágenes se configurarán en el grupo.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>No se ha añadido ningún elemento.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Añadir iniciador</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Grupos</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Grupo</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Añadir grupo</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Configuración de RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Elimina el valor de configuración local. Se heredará y usará en su lugar el valor de configuración padre.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>El valor mínimo es 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Problemas</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Sincronizando</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Listo</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Editar modo de duplicación de repositorio</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Para editar el modo de duplicación del repositorio 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, seleccione un modo nuevo en la lista y haga clic 
+ en
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Actualizar
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Modo</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Los clústeres de par deben eliminarse antes de inhabilitar la duplicación.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+duplicar par de repositorio
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Editar} other {Añadir} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> los atributos del par
+ de duplicación del respositorio
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> y haga clic en
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Enviar
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nombre del clúster</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>El nombre del clúster no es válido.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>ID de CephX</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>ID de CephX...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>El ID de CephX no es válido.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Direcciones de monitores</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Direcciones delimitadas por comas...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>La dirección del monitor no es válida.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>Clave de CephX</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Clave con cifrado base64...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>La clave de CephX debe tener cifrado base64</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Lista de repositorios</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>El nombre solo puede tener caracteres alfanuméricos, guiones y guiones bajos.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>El nombre del perfil de código de borrado que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Complemento</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Porciones de datos (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Debe ser igual o mayor que 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Porciones de código (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Debe ser igual o mayor que 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Estimador de durabilidad (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Localización (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Dominio de error de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Localización de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Ninguna</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Técnica</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Tamaño del paquete</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Raíz de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Clase de dispositivo de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>cualquiera</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Directorio</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>El nombre del repositorio de Ceph que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Tipo de repositorio</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Seleccione un tipo de repositorio --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Grupos de colocación</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Se necesita al menos un grupo de colocación.</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>El clúster no puede gestionar tantos grupos de colocación. Vuelva a calcular la cantidad que necesita.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Ayuda para el cálculo</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>El número grupos de colocación actual se ha calculado
+  automáticamente. Debe asegurarse de que sirve para sus necesidades antes de enviar.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Conjunto de reglas de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Seleccione una regla de CRUSH --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Regla de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Pasos de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>La regla no se puede usar en el clúster actual, ya que
+ no tiene suficientes OSD que cumplan el mínimo requerido.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Tamaño replicado</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Mínimo:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Máximo:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>El tamaño especificado está fuera del intervalo. Los valores válidos
+ son del
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> al
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Perfil de código de borrado</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- No hay ningún perfil de código de borrado disponible --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Seleccione un perfil de código de borrado --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>Sustituciones de códigos de borrado</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Aplicaciones</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Compresión</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algoritmo</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- No hay ningún algoritmo de compresión de borrado disponible --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Tamaño de Blob mínimo</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>p. ej. 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>El valor debe ser mayor que 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Tamaño de Blob máximo</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>p. ej. 512 KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>El valor debe ser mayor que el tamaño de Blob mínimo</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Relación</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Relación de compresión</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>El valor debe estar entre 0,0 y 1,0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>No es posible crear un repositorio RBD con el nombre "/".</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Cambie el nombre o elimine "rbd" de la lista de aplicaciones.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Detalles de niveles de caché</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Consulte la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentación
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre cómo configurar y habilitar la función de gestión de Object Gateway.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Lista de daemons</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Contadores de rendimiento</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Cargando datos de la papelera...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>No es posible cargar los datos de la papelera.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>El valor no es válido.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Propietario</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Seleccione un usuario --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Tipo de índice</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Regla de colocación</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Marcador</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Marcador máximo</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Versión</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Versión maestra</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Hora de modificación</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Grupo de zona</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Cuota de papelera</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Habilitado</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Tamaño máximo</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Sin límite</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Número máximo de objetos</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Seleccione un nombre de usuario --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Autogenerar clave</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Clave de acceso</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Clave secreta</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Dirección de correo electrónico</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Suspendido</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Sistema</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {No} 1 {Sí} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Número máximo de papeleras</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Subusuarios</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Capacidades</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Cuota de usuario</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Mostrar</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Claves</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Seleccione un tipo --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Permiso</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Seleccione un permiso --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Subusuario</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>El ID de subusuario que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>lectura, escritura</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>todos</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Clave Swift</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Autogenerar secreto</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Cargando datos del usuario...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>No es posible cargar los datos del usuario.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>El ID de usuario que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Esta dirección no es válida.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>La dirección de correo electrónico que ha elegido ya está en uso.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Máx. papeleras</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>El valor introducido debe ser mayor o igual que 0.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>Clave S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>No hay ningún subusuario.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>No hay ninguna clave.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>No hay ninguna capacidad</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Tamaño ilimitado</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Tamaño máx.</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Objetos ilimitados</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Objetos máx.</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Actual</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Autenticación de descubrimiento actualizada</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>No hay ningún portal disponible.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>No hay ninguna imagen disponible.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>No hay ninguna imagen disponible. Asegúrese de añadir una imagen al destino.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>No hay ningún iniciador disponible. Asegúrese de añadir un iniciador al destino.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Destino</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Estado</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Bytes de lectura</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Bytes de escritura</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Operaciones de lectura</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Operaciones de escritura</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O desde</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instancia</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nombre de host</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problema</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Progreso</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Inhabilitado</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Editar modo</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Añadir par</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Editar par</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Suprimir par</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Líder</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>N.º locales</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>N.º remotos</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>duplicar par</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Clave</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Aplanamiento profundo</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>En capas</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Bloqueo exclusivo</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Mapa de objetos (requiere bloqueo exclusivo)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>En diario (requiere bloqueo exclusivo)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Reversión de instantánea RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Revertir</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Instantánea RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Suprimido a las</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>tipo</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>estado</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>versión</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>raíz</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Clasificación</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Actividad</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inodos</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Uso</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Daemons de reserva</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>El valor se puede actualizar en el tiempo de ejecución.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Los daemons/clientes no extraen este valor de la
+ base de datos de configuración del monitor. No se recomienda definir esta opción con "ceph config
+ set ...". Esta opción se debe configurar mediante ceph.conf o a través
+ de la línea de comandos.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>La opción solo surte efecto durante el inicio del daemon.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>La opción solo afecta a la creación del clúster.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>La opción solo afecta a la creación del daemon.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Opción de configuración actualizada
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Servicio</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Valor actual</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Editable</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Opciones actualizadas para el módulo
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Habilitar</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Inhabilitar</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Conectando de nuevo. Espere...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Dirección pública</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Sesiones abiertas</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>No incluir</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>Los OSD que se excluyeron anteriormente no se volverán a incluir cuando se inicien</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>No excluir</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>Los OSD no se excluirán automáticamente después del intervalo configurado</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>No activar</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>No se permite que los OSD se inicien</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>No desactivar</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Se ignoran los informes de error de OSD, de forma que los monitores no desactivarán los OSD</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pausa</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Pone en pausa las lecturas y escrituras</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>No depurar</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>La depuración está inhabilitada</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>No depuración profunda</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>La depuración profunda está inhabilitada</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>No reponer</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>La reposición de grupos de colocación se suspende</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>No recuperar</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>La recuperación de los grupos de colocación se suspende</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Orden bit a bit</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Usar orden bit a bit</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Snapdir limpiados</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>Los OSD tienen snapset convertidos</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Supresiones de recuperación</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Supresiones realizadas durante la recuperación, en lugar de emparejamientos</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Límite estricto de registro del grupo de colocación</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Establece un límite estricto para la longitud del registro del grupo de colocación</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Indicadores de OSD actualizados</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>excluir</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>Incluir</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>desactivar</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Marcar</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD perdido</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>marcado como perdido</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Limpiar</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>limpiado</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>destruir</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>destruido</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>Grupos de colocación</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Bytes de lectura</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Bytes de escritura</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Operaciones de lectura</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Operaciones de escritura</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marcar OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marcar
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Número máximo de reposiciones</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Máximo de recuperaciones activas</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Máximo de recuperaciones de inicio único</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Reposo de recuperación</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Personalizar</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Prioridad de velocidad de recuperación de OSD actualizada
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> se ha inicializado en el siguiente OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Trabajo</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Gravedad</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Iniciado</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Actualizado</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Usado</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Dispon.</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Limpio</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>En curso</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Advertencia</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Desconocido</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>activo</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>sin sistemas de archivos</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>activo</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>reserva</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/d</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>daemon activo</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>quórum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>El servicio NFS Ganesha no está configurado.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transportar</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Usuario de CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>Sistemas de archivos CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(se hereda de la configuración global)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>se hereda de la configuración global</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Seleccione el tipo de reducción de privilegios de ID de usuario que se va a realizar --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>No hay ningún daemon disponible.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Modo de caché</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Antigüedad mínima de expulsión</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Antigüedad mínima de vaciado</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Número máximo de bytes de destino</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Número máximo de objetos de destino</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>No se ha añadido ninguna aplicación</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Se ha alcanzado el límite de aplicaciones</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Un repositorio solo puede tener hasta cuatro definiciones de aplicaciones.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Caracteres permitidos: _, a-z, A-Z y 0-9</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>La longitud máxima es 128 caracteres</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtrar o añadir aplicaciones</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Añadir aplicación</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>perfil de código de borrado</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Tamaño de réplica</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Último cambio</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Perfil de código de borrado</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Conjunto de reglas de CRUSH</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Bytes de escritura</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>papelera</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Papelera de Object Gateway actualizada "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Papelera de Object Gateway creada "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>papeleras</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>usuario</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Usuario de Object Gateway actualizado "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Usuario de Object Gateway creado "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>usuarios</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Ámbito</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Lectura</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Crear</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Se ha creado la función
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Se ha actualizado la función
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Función del sistema</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Se ha suprimido la función
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Se ha creado el usuario
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Actualizar usuario</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Continuar</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>La sesión se ha cerrado automáticamente porque sus funciones han cambiado.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Se ha actualizado el usuario
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Se ha suprimido el usuario
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Error al suprimir el usuario
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Ha entrado a la sesión como
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Cada objeto se divide en porciones de datos, cada una almacenada en un OSD distinto.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Calcula las porciones de código para cada objeto y las almacena en distintos OSD.
+ El número de porciones de código es también el número de OSD que pueden estar inactivos sin que se pierdan datos.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>El complemento jerasure es el más genérico y flexible,
+ y también el complemento por defecto para los repositorios de código de borrado de Ceph.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>La técnica más flexible es reed_sol_van: basta con definir k y m.
+ La técnica cauchy_good puede ser más rápida, pero hay que elegir con cuidado el tamaño
+ del paquete. reed_sol_r6_op, liberation, blaum_roth y liber8tion son todas equivalentes a RAID6
+ en el sentido de que solo se pueden configurar con m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>La codificación se realizará según el tamaño de los paquetes de bytes de uno en uno.
+ Elegir el tamaño correcto es difícil.
+ La documentación de jerasure incluye información completa sobre el tema.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Con el complemento jerasure, cuando un objeto de código de borrado se almacena
+ en varios OSD, para recuperarse de la pérdida de un OSD es necesario leer de todos los demás.
+ Por ejemplo, si jerasure está configurado con k=8 y m=4, cuando se pierde un OSD es necesario leer
+ de los otros once para repararlo.
+
+ El complemento de código de borrado lrc crea porciones de paridad local para poder realizar la recuperación con
+ menos OSDs. Por ejemplo, is lrc está configurado con k=8, m=4 y l=4, creará
+ una porción de paridad adicional para cada cuatro OSDs. Si se pierde un solo OSD, se puede recuperar
+ solo con cuatro OSD, en lugar de con once.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Agrupa las porciones de código y de datos en localizaciones de conjuntos de tamaño. Por ejemplo,
+ para k=4 y m=2, si locality=3, se crean dos grupos de tres. Cada conjunto
+ se puede recuperar sin leer porciones de otro conjunto.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>El tipo de papelera de CRUSH en el que se almacenará cada
+ conjunto de porciones definido por l. Por ejemplo, si se define como bastidor, cada grupo de l porciones
+ se colocará en un bastidor distinto. Se usa para crear un paso de regla de CRUSH, por ejemplo, "step choose
+ rack". Si no se define, no se realiza este tipo de agrupamiento.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>El complemento isa encapsula la biblioteca ISA. Solo funciona en procesadores Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>El complemento ISA viene en dos formatos de Reed Solomon.
+ Si se define reed_sol_van, se trata de Vandermonde; si se define cauchy, se trata de Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>El complemento shec encapsula las distintas bibliotecas SHEC.
+ Permite a Ceph recuperar datos de forma más eficiente que los códigos de Reed Solomon.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>El número de porciones de paridad. Cada uno de ellas incluye cada porción de datos
+ en su intervalo de cálculo. El número se usa como estimador de durabilidad. Por ejemplo, si c=2,
+ 2 OSD pueden estar inactivos sin que se pierdan datos.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>El nombre de la papelera de CRUSH usado para el primer paso de la regla de CRUSH.
+ Por ejemplo, "step take default".</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Asegúrese de que no hay dos porciones en una papelera con el mismo
+ dominio de error. Por ejemplo, si el dominio de error es host, no debe haber dos porciones almacenadas en el mismo
+ host. Se usa para crear un paso de regla de CRUSH, por ejemplo, "step chooseleaf host".</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Restringe la colocación a dispositivos de una clase concreta
+ (p.ej., ssd o hdd) usando los nombre de clase de dispositivo CRUSH en el mapa de CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Define el nombre de directorio del que se cargará el complemento de código de borrado.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Permite todas las operaciones</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Permite solo las operaciones que no modifican el servidor</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>No permite operaciones de lectura o escritura, pero sí cualquier otra</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>No permite operaciones de lectura o escritura, ni ninguna otra que modifique los atributos del archivo o el contenido del directorio</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>No permite ningún tipo de acceso</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Seleccione la prioridad --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Baja</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Alta</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Últimos 5 minutos</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Últimos 15 minutos</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Últimos 30 minutos</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Última hora (opción por defecto)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Últimas 3 horas</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Últimas 6 horas</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Últimas 12 horas</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Últimas 24 horas</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Ayer</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Hoy</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Hoy hasta ahora</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Anteayer</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Los últimos 2 días</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Este día la semana pasada</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>La semana pasada</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Esta semana</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Esta semana hasta ahora</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Los últimos 7 días</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>El mes pasado</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Este mes</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Este mes hasta ahora</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Los últimos 30 días</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Los últimos 90 días</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Los últimos 6 meses</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>El último año</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>El año pasado</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Este año</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Este año hasta ahora</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Los últimos 2 años</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Los últimos 5 años</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Información</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>No se ha seleccionado ningún elemento.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Deseleccione el elemento para volver a seleccionarlo</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Se ha alcanzado el límite de selección</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Filtrar etiquetas</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Añadir insignia</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>No hay ningún elemento disponible.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Añadir</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Clonar</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Copiar</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Depuración profunda</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Destruir</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Aplanar</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Marcar para desactivar</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Marcar para incluir</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Marcar como perdido</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Marcar para excluir</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Proteger</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Renombrar</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Restaurar</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Mover a la papelera</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Desproteger</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Suprimido</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Clonado</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Copiado</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Sí</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>No</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Calidad del servicio</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Límite de BPS</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>El límite deseado de bytes de E/S por segundo.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Límite de IOPS</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>El límite deseado de operaciones de E/S por segundo.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Límite de BPS de lectura</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>El límite deseado de bytes de lectura por segundo.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Límite de IOPS de lectura</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>El límite deseado de operaciones de lectura por segundo.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Límite de BPS de escritura</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>El límite deseado de bytes de escritura por segundo.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Límite de IOPS de escritura</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>El límite deseado de operaciones de escritura por segundo.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Ráfaga de BPS</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>El límite deseado de ráfaga de bytes de E/S.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Ráfaga de IOPS</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>El límite deseado de ráfaga de operaciones de E/S.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Ráfaga de BPS de lectura</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>El límite deseado de ráfaga de bytes de lectura.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Ráfaga de IOPS de lectura</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>El límite deseado de ráfaga de operaciones de lectura.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Ráfaga de BPS de escritura</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>El límite deseado de ráfaga de bytes de escritura.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Ráfaga de IOPS de escritura</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>El límite deseado de ráfaga de operaciones de escritura.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Error al
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Ejecutando</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>ejecutar</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Ejecutado</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>tarea desconocida</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Creando</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>crear</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Actualizando</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>actualizar</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Suprimiendo</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>suprimir</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Instantánea RBD
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>modo de duplicación para repositorio
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>par de duplicación para repositorio
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> ya está usando el nombre.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{name}}"/> ya está usando el nombre.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> ya está usando el nombre.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contiene instantáneas.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Clonando</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>clonar</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>La instantánea de
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> debe estar protegida.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Copiando</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>copiar</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Aplanando</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>aplanar</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Aplanado</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> ya está usando el nombre.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>No es posible desproteger
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque contiene imágenes hijas.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>No es posible suprimir
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque está protegido.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Revirtiendo</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>revertir</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Revertido</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Moviendo</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>mover</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Movido</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>la imagen
+ <x id="INTERPOLATION" equiv-text="{{id}}"/> a la papelera
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>No se encuentra la imagen.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Restaurando</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>restaurar</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Restaurado</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>la imagen
+ <x id="INTERPOLATION" equiv-text="{{id}}"/> en
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>El nombre de imagen
+ <x id="INTERPOLATION" equiv-text="{{id}}"/> ya está en uso.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>la imagen
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Limpiando</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>limpiar</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Limpiado</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>todos los repositorios</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>imágenes de
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>No es posible inhabilitar la duplicación porque contiene un par</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>repositorio
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>perfil de código de borrado
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>destino
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.fr-FR.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.fr-FR.xlf
new file mode 100644
index 00000000..e94b1423
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.fr-FR.xlf
@@ -0,0 +1,4367 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="fr-FR">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Activer/Désactiver la navigation</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Tableau de bord</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Grappe</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Serveurs</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Moniteurs</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Configuration</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>Carte CRUSH</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Modules Manager</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Journaux</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Alertes</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Réserves</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Bloc</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Images</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Mise en miroir</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Systèmes de fichiers</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemons</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Utilisateurs</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Compartiments</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Récupération des données
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pour
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Veuillez patienter...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Affichage des données
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> précédemment mises en cache
+ pour
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Impossible de charger les données
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> pour
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Veuillez vérifier l'état de santé de la grappe.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Retour</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Sélectionner une langue</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Chargement des données du panneau...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Veuillez consulter la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> relative à
+ la configuration et à l'activation de la fonctionnalité de surveillance.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Le tableau de bord Grafana n'existe pas. Veuillez consulter
+ la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> relative à
+ l'ajout de tableaux de bord à Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Sélecteur d'heure Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Réinitialiser les paramètres</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Échec du chargement des données.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>sélectionné(e)(s)</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>trouvé(e)(s)</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>total</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Modifier</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nom</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Description</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Description longue</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Valeur par défaut</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Valeur par défaut du daemon</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Services</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Valeurs</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>La valeur entrée est trop élevée ! Elle ne peut pas être supérieure à
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>La valeur entrée est trop faible ! Elle ne peut pas être inférieure à
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Sauvegarder</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>Visionneuse de carte CRUSH</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Liste d'hôtes</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Performance globale</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Aucune entrée trouvée</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Journaux de grappes</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Journaux d'audit</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Chargement de la configuration...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>La configuration n'a pas pu être chargée.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Modifier le module Manager</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>La valeur entrée n'est pas un UUID valide, par exemple : 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>La valeur entrée doit être une adresse IP valide.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Ce champs est requis.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>La valeur entrée est trop élevée ! Elle doit être inférieure ou égale à
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>La valeur entrée est trop faible ! Elle doit être supérieure ou égale à
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>La valeur entrée doit être un nombre.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>La valeur entrée doit être un nombre ou une valeur décimale.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Mise à jour</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Statut</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>ID de grappe</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmap modifié</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmap epoch</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>required con</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>required mon</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>Dans le quorum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Hors quorum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Annuler</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Voulez-vous vraiment
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> l'élément sélectionné
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> ?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Oui.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Drapeaux OSD à l'échelle de la grappe</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Soumettre</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Avancé...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Priorité de récupération des OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Priorité</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Personnaliser les valeurs de priorité</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Ce champ est obligatoire !</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>La valeur entrée est trop élevée ! Elle ne peut pas être supérieure à
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>La valeur entrée est trop faible ! Elle ne peut pas être inférieure à
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Réévaluer l'OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>La valeur doit être comprise entre 0 et 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Réévaluer</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>Nettoyage des
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>OSD
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Profondeur } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Vous êtes sur le point d'appliquer un nettoyage
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>
+ à l'OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {profondeur } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Liste des OSD</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>L'
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> sera marqué
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> si vous continuez.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>L'OSD ne peut pas être détruit de façon sécurisée !</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L'OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> sera
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> si vous continuez.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Détails</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Valeur</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Fermer</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Supprimer</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Santé</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statistiques</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Veuillez consulter la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ relative à la configuration et à l'activation de la fonctionnalité de gestion du NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Clients</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Accès possible par tous les clients</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Adresses</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Champ obligatoire</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Doit contenir une ou plusieurs valeurs séparées par une virgule</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Par exemple :</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Type d'accès</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Ajouter des clients</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Chargement...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Aucune grappe disponible --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Sélectionner la grappe --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Ajouter un daemon</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Backend de stockage</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Aucune réserve de données disponible --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Sélectionner le backend de stockage --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Utilisateur Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Aucun utilisateur disponible --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Sélectionner l'utilisateur Object Gateway --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>ID utilisateur CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Aucun client disponible --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Sélectionner le client cephx --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nom CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Libellé de sécurité</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Activer le libellé de sécurité</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Chemin CephFS</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Le chemin doit commencer par '/' et peut être suivi d'un mot</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Un nouveau répertoire sera créé</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Chemin</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Le chemin peut être constitué d'un seul '/' ou d'un seul mot</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Un compartiment sera créé</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protocole NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Balise NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Autre chemin d'accès aux montages
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (doit commencer par /).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Les clients ne peuvent pas monter de sous-répertoires (si la balise = foo, le client ne peut pas monter foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>En utilisant différentes options de balise, il est possible d'exporter plusieurs fois le même chemin.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>Position occupée par cet export
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ dans le
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>système de fichiers Pseudo
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (doit être unique).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>En utilisant différentes options de pseudo, il est possible d'exporter exporter plusieurs fois le même chemin.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Aucun type d'accès disponible --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Sélectionner le type d'accès --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- Aucun squash disponible --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- Sélectionnez le type de squash d'ID utilisateur qui est effectué --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protocole de transport</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Bienvenue dans Ceph !</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Nom d'utilisateur requis</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Mot de passe requis</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Connexion</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Désolé, l'utilisateur n'existe pas dans Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Retournez à la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>page de connexion
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Vous serez déconnecté du fournisseur d'identité lorsque vous tenterez de vous reconnecter.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Interdit</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Désolé, vous n'êtes pas autorisé à voir ce que vous cherchez.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Désolés, nous ne parvenons pas à trouver ce que vous cherchez.</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Tout supprimer</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Notifications récentes</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Il n'y a aucune tâche en arrière-plan.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Tâches en arrière-plan</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Aide</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Documentation</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>À propos de</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Paramètres du tableau de bord</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Gestion des utilisateurs</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Utilisateur connecté</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Connecté en tant que
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Se déconnecter</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nom...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Le nom sélectionné est déjà en cours d'utilisation.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Description...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Autorisations</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Rôles</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nom d'utilisateur</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Mot de passe</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Confirmer le mot de passe</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Le mot de passe de confirmation ne correspond pas au mot de passe.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Nom complet</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>Adresse électronique</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>L'adresse électronique n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Vous êtes sur le point de supprimer les autorisations "lecture/mise à jour utilisateur" de votre propre utilisateur.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Si vous continuez, vous ne serez plus en mesure d'ajouter ni de supprimer des rôles pour n'importe quel utilisateur.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Voulez-vous vraiment continuer ?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Compteurs de performance non disponibles</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Attributs (carte OSD)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Métadonnées non disponibles</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Métadonnées</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Compteur de performance</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histogramme non disponible :
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Écritures</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Lectures</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histogramme</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Détails des performances</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Valeurs actuelles</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Type</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Minimum</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Maximum</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Drapeaux</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Source</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Niveau</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Mise à jour possible lors de l'exécution (modifiable)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Balises</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Valeurs d'énuménation</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Voir aussi</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Statut de la grappe</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Daemons du gestionnaire</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Passerelles d'objet</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Serveurs de métadonnées</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>Passerelles iSCSI</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>IOPS client</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Débit client</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Lectures/Écritures client</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Débit de récupération</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Nettoyer</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Performance</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Capacité brute</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objets</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>Groupes de placements par OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Statut du groupe de placements</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Capacité</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consultez les
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>journaux
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> pour plus d'informations.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Rangs</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Clients :
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Déplacer une image vers la corbeille.</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Pour déplacer
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> vers la corbeille,
+ cliquez sur
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Déplacer une image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Vous pouvez également sélectionner une date d'expiration.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>La protection expire le </target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NON PROTÉGÉ</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Format de date incorrect. Veuillez utiliser "AAAA-MM-JJ HH:mm:ss"</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>La protection a déjà expiré. Veuillez sélectionner une date ultérieure ou laisser le champ vide.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Déplacer une image</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Présentation</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Cibles</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Authentification de la découverte</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Utilisateur</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Les noms d'utilisateur doivent comporter entre 8 et 64 caractères et
+ ne peuvent contenir que des lettres et les caractères '.', '@', '-', '_' ou ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Utilisateur commun</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Mot de passe commun</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Veuillez consulter la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+relative à la configuration et à l'activation de la fonctionnalité de gestion des cibles iSCSI.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Informations disponibles :</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>Cibles iSCSI non disponibles</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Disponible uniquement pour les images RBD pour lesquelles
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> est activé
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Réserve</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Réserve de données</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Créé</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Taille</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Taille de l'objet</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Fonctionnalités</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Provisionné</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/A</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Provisionnement total</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Unité de segmentation</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Nombre de segmentations</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Parent</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Préfixe du nom de bloc</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Tri</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Instantanés</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Image</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Ce paramètre remplace la valeur globale</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Global</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Il s'agit de la valeur globale. Aucune valeur de cette option n'a été définie pour cette image.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>Les caractères '/' et '@' ne sont pas autorisés.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Aucune réserve RBD disponible --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Sélectionner une réserve --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Utiliser une réserve de données dédiée</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Réserve de données</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Réserve dédiée qui stocke les données objet du RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>par exemple, 10 Gio</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Vous devez augmenter la taille.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Avancé</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Segmentation</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Unité de segmentation</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Sélectionner une unité de segmentation --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Ce champ est obligatoire, car le nombre de segments est défini.</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>L'unité de segmentation est supérieure à la taille de l'objet.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Nombre de segments</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Ce champ est obligatoire, car l'unité de segmentation est définie.</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Le nombre de segments doit être supérieur à 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantané RDB
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Renommer} other {Créer} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> instantané
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>PROTÉGÉ</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NON PROTÉGÉ</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Vous êtes sur le point de revenir à l'état initial</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Vider la corbeille</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Pour purger, sélectionner une image ou toutes, puis cliquez sur</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Réserve :</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nom de la réserve...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Tout</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Restaurer l'image</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Pour restaurer</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>saisissez le nouveau nom de l'image, puis cliquez sur</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nouveau nom</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Expiration le </target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Protection jusqu'au</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Cette image est protégée jusqu'au
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Corbeille</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologie iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Il n'est généralement pas nécessaire de modifier ces paramètres par défaut.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Paramètres</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Confirmer</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Paramètres avancés</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>IQN cible</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>Modèle IQN incorrect.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Un IQN est associé à la notation 'iqn.$year-$month.$reversedAddress:$definedName'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Par exemple : iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Plus d'informations</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Des paramètres avancés de cette cible ont été modifiés.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portails</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Au moins
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> passerelles sont nécessaires.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Ajouter un portail</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Des paramètres avancés de cette image ont été modifiés.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Ajouter une image</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Authentification ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Initiateurs</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Initiateur</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>IQN client</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>L'IQN de l'initiateur doit être unique.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Les noms d'utilisateur doivent comporter entre 8 et 64 caractères et
+ ne peuvent contenir que des lettres et les caractères '.', '@', '-', '_' ou ':'.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>L'initiateur appartient à un groupe dans lequel les images seront configurées.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Aucun élément ajouté.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Ajouter un initiateur</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Groupes</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Groupe</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Ajouter un groupe</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Configuration RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Supprimez la valeur de configuration locale. La valeur de configuration parent sera héritée et utilisée à la place.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>La valeur minimale est 0.</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Problèmes</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Synchronisation en cours</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Prêt</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Modifier le mode de mise en miroir de la réserve</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Pour modifier le mode de mise en miroir de la réserve 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, sélectionnez un nouveau mode dans la liste, puis cliquez sur
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mettre à jour
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Mode</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Les grappes d'homologues doivent être supprimées avant de désactiver la mise en miroir.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ homologue de mise en miroir de la réserve
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Modifier} other {Ajouter} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> les attributs
+ de mise en miroir de la réserve
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> et cliquez sur
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Soumettre
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nom de grappe</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Le nom de grappe n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>ID CephX</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>ID CephX</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>L'ID CephX n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Adresses du moniteur</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Adresses séparées par une virgule...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>L'adresse du moniteur n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>Clef CephX</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Clef Base64...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>La clef CephX doit être codée en base64.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Liste des réserves</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Le nom doit être exclusivement composé de caractères alphanumériques, de tirets et de traits de soulignement.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Le nom de profil du code d'effacement sélectionné est déjà utilisé.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Plug-in</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Blocs de données (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Doit être égal ou supérieur à 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Blocs de codage (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Doit être égal ou supérieur à 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Estimateur de durabilité (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Localité (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Domaine de défaillance Crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Localité Crush</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Aucun</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Technique</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Taille de paquet</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Racine Crush</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Classe de périphérique Crush</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>tout</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Répertoire</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Le nom de réserve Ceph sélectionné est déjà utilisé.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Type de réserve</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Sélectionner un type de réserve --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Groupes de placements</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Au moins un groupe de placements est nécessaire.</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Votre grappe ne peut pas gérer autant de groupes de placements. Veuillez recalculer le nombre de groupes de placements nécessaires.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Aide au calcul</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>Les paramètres actuels des groupes de placements ont été calculés pour vous.
+Vérifiez que les valeurs correspondent à vos besoins avant de les soumettre.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Jeu de règles Crush</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Sélectionner une règle crush --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Règle Crush</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Étapes Crush</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>La règle ne peut pas être utilisée dans la grappe active, car celle-ci
+ comporte un nombre d'OSD inférieur au nombre d'OSD minimum requis par cette règle.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Taille de réplication</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Minimum :
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Maximum :
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>La taille spécifiée est en dehors de la plage. Une valeur comprise entre
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> et
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> est valide.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Profil de code d'effacement</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Aucun profil de code d'effacement n'est disponible --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Sélectionner un profil de code d'effacement --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>Écrasements EC</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Applications</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Compression</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algorithme</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Aucun algorithme de compression d'effacement n'est disponible --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Taille de blob minimale</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>par ex. 128 Kio</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>La valeur doit être supérieure à 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Taille de blob maximale</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>par ex., 512 Kio</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>La valeur doit être supérieure à la taille de blob minimale.</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Rapport</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Rapport de compression</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>La valeur doit se situer entre 0.0 et 1.0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Il n'est pas possible de créer une réserve RBD dont le nom contient '/'.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Modifiez le nom ou supprimez 'rbd' de la liste des applications.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Détails des niveaux de mise en cache</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Veuillez consulter la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ relative à la configuration et à l'activation de la fonctionnalité de gestion Object Gateway.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Liste de daemons</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Compteurs de performance</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Chargement des données de compartiment...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Les données du compartiment n'ont pas pu être chargées.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>La valeur n'est pas valide.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Propriétaire</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Sélectionner un utilisateur --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Type d'index</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Règle de placement</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Marqueur</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Marqueur maximum</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Version</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Version principale</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Date de modification</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Groupe de zones</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Quota de compartiments</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Activé</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Taille maximale</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Illimité</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Nombre maximal d'objets</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Sélectionner un nom d'utilisateur --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Générer automatiquement la clef</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Clef d'accès</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Clef secrète</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Adresse électronique</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Suspendu</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Système</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {Non} 1 {Oui} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Nombre maximal de compartiments</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Utilisateurs secondaires</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Fonctionnalités</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Quota utilisateur</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Afficher</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Clefs</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Sélectionner un type --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Autorisation</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Sélectionner une autorisation --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Utilisateur secondaire</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>L'ID d'utilisateur secondaire sélectionné est déjà utilisé.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>lire, écrire</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>complet</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Clé Swift</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Générer automatiquement le secret</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Chargement des donnés utilisateur…</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Les donnés utilisateur n'ont pas pu être chargées.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>L'ID utilisateur spécifié est déjà utilisé.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Ceci n'est pas une adresse électronique valide.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>L'adresse électronique spécifiée est déjà utilisée.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Nombre max. de compartiments</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>La valeur saisie doit être &gt;= 0.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>Clef S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Il n'y a aucun utilisateur secondaire.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Il n'y a pas de clefs.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Il n'y a aucune fonctionnalité.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Taille illimitée</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Taille max.</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Objets illimités</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Nombre max. d'objets</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Actuel</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Authentification de la découverte mise à jour</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Il n'y a aucun portail disponible.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Il n'y a aucune image disponible.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Il n'y a aucune image disponible. Veillez à ajouter une image à la cible.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Il n'y a aucun initiateur disponible. Veillez à ajouter un initiateur à la cible.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Cible</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>État</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Octets de lecture</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Octets d'écriture</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Opérations de lecture</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Opérations d'écriture</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O depuis</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instance</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nom d'hôte</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problème</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Avancement</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Désactivé</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Mode d'édition</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Ajouter un homologue</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Modifier un homologue</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Supprimer un homologue</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Leader</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>nb en local</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>nb à distance</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>mettre en miroir l'homologue</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Clef</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Aplatissement en profondeur</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Superposition</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Verrou exclusif</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Assignation d'objet (nécessite exclusive-lock)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Journalisation (nécessite exclusive-lock)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Retour à l'état initial de l'instantané RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Revenir à l'état initial</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Intantané RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Supprimé le</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>type</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>état</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>version</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Hôte</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>racine</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Rang</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Activité</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inodes</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Utilisation</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Daemons en veille</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>La valeur peut être mise à jour au moment de l'exécution.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Les daemons/clients ne tirent pas cette valeur de
+  la base de données de configuration de Monitor. Nous n'autorisons pas le réglage de cette option via 'ceph config
+  set ...'. Cette option doit être configurée via ceph.conf ou via
+  la ligne de commande.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>L'option ne prend effet qu'au démarrage du daemon.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>L'option n'affecte que la création des grappes.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>L'option n'affecte que la création des daemons.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Option de configuration mise à jour
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Service</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Valeur actuelle</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Modifiable</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Options mises à jour pour le module &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Activer</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Désactiver</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Reconnexion en cours… Veuillez patienter.</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Adresse publique</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Sessions ouvertes</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Pas rentrés</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>Les OSD qui ont été marqués comme sortis ne seront pas marqués comme rentrés à leur démarrage.</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Pas sortis</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>Les OSD ne seront pas marqués automatiquement comme sortis après l'intervalle configuré.</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Pas démarrés</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>Les OSD ne sont pas autorisés à démarrer.</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Pas arrêtés</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Les rapports de défaillance des OSD sont ignorés, de sorte que les moniteurs ne marquent pas les OSD comme étant arrêtés.</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pause</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Met en pause les lectures et écritures</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Pas de nettoyage</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Nettoyage désactivé</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Pas de nettoyage en profondeur</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Le nettoyage en profondeur est désactivé</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Pas de renvoi</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Le renvoi des groupes de placements est suspendu</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Pas de récupération</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>La récupération des groupes de placements est suspendue</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Tri au niveau du bit</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Utiliser le tri au niveau du bit</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Variables snapdir purgées</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>Les OSD ont converti les variables snapset</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Suppressions des récupérations</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Suppressions effectuées pendant la restauration et non l'homologation</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Limite stricte de journalisation des groupes de placements</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Impose une limite stricte à la longueur du journal des groupes de placements</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Drapeaux OSD mis à jour</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>sorti</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>rentré</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>arrêté</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Marquer</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD perdu</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>marqué comme perdu</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Purger</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>purgé</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>détruire</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>détruit</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>Groupes de placements</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Octets de lecture</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Octets d'écriture</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Opérations de lecture</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Opérations d'écriture</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marquer l'OSD comme
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marquer comme
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Nbre max. de renvois</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Nombre maximum de récupérations actives</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Nombre maximum de démarrages uniques de récupérations</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Mise en veille de la récupération</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Personnalisé</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Priorité de la vitesse de récupération des OSD&amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot; mise à jour
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> a été initialisé(e) sur l'OSD suivant :
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Travail</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Gravité</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Démarré</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Mis à jour</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Utilisé</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Dispo.</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Nettoyé</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>En cours</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Avertissement</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Inconnu</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>opérationnel</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>aucun système de fichiers</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>actif</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>veille</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/a</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>daemon actif</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Le service NFS Ganesha n'est pas configuré.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transport</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Utilisateur CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>Système de fichiers CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(hérité de la configuration globale)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>hérité de la configuration globale</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Sélectionner le type de squashing d'ID utilisateur effectué --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Aucun daemon n'est disponible.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Mode cache</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Âge évict min.</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Âge vidage min.</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Nombre max d'octets cibles</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Nombre max. d'objets cibles</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Aucune application ajoutée</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Limite d'applications atteinte</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Une réserve peut avoir quatre définitions d'application maximum.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Caractère autorisés '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>La longueur maximale est de 128 caractères.</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtrer ou ajouter des applications</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Ajouter une application</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>profil de code d'effacement</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Taille de la réplique</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Dernier changement</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Profil de code d'effacement</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Jeu de règles Crush</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Octets d'écriture</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>compartiment</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Compartiment Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; mis à jour
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Compartiment Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; créé
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>compartiments</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>utilisateur</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Utilisateur Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; mis à jour
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Utilisateur Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; créé
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>utilisateurs</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Périmètre</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Lecture</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Créer</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Rôle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' créé
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Rôle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' mis à jour
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Rôle système</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Rôle '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' supprimé
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Utilisateur &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; créé
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Mettre à jour l'utilisateur</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Continuer</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Vous avez été automatiquement déconnecté, car vos rôles ont changé.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Utilisateur &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; mis à jour
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Utilisateur &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; supprimé
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Échec de la suppression de l'utilisateur &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Vous êtes connecté en tant que &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Chaque objet est divisé en parties de blocs de données, chacune étant stockée sur un OSD différent.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Calculez des blocs de codage pour chaque objet et stockez-les sur différents OSD.
+ Le nombre de blocs de codage correspond également au nombre d'OSD qui peuvent être arrêtés sans perdre de données.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Le plugin jerasure est le plugin le plus générique et le plus flexible,
+  c'est aussi la valeur par défaut des réserves codées à effacement Ceph.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>La technique la plus flexible est reed_sol_van_van : il suffit de définir k
+ et m. La technique cauchy_good peut être plus rapide, mais vous devez choisir la taille du paquet
+ avec précaution. reed_sol_r6_op, liberation, blaum_roth et liber8tion sont des équivalents RAID6
+ en ce sens qu'ils ne peuvent être configurés qu'avec m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>L'encodage se fera sur des paquets de taille d'octets.
+  Choisir la bonne taille de paquet est difficile.
+  La documentation de jerasure contient de nombreuses informations à ce sujet.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Avec le plugin jerasure, lorsqu'un objet codé à effacement est stocké sur
+ plusieurs OSD, la récupération à la suite de la perte d'un OSD nécessite la lecture de tous les autres.
+ Par exemple, si jerasure est configuré avec k=8 et m=4, la perte d'un OSD nécessite de lire
+ les onze autres pour pouvoir effectuer une réparation.
+
+ Le plugin de code d'effacement lrc crée des blocs de parité locale pour permettre la récupération avec
+ moins d'OSD. Par exemple, si lrc est configuré avec k=8, m=4 et l=4,
+ un bloc de parité supplémentaire est créé pour chaque groupe de quatre OSD. Lorsqu'un seul OSD est perdu, il peut être
+ récupéré avec seulement quatre OSD au lieu de onze.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Regroupez les blocs de données et de codage en ensembles de localité de taille. Par exemple,
+ pour k=4 et m=2, lorsque locality=3, deux groupes de trois sont créés. Chaque ensemble peut
+ être récupéré sans lire les blocs d'un autre jeu.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>Type de compartiment Crush dans lequel chaque ensemble de blocs défini
+ par I sera stocké. Par exemple, s'il est réglé sur rack, chaque groupe de blocs I sera
+ placé dans un rack différent. Il est utilisé pour créer une étape de la règle CRUSH telle que l'étape de choix
+ d'un rack. S'il n'est pas défini, aucun regroupement de ce type n'est effectué.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Le plug-in isa encapsule la bibliothèque ISA. Il ne fonctionne qu'avec des processeurs Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>Le plugin ISA se présente sous deux formes Reed Solomon.
+ Si reed_sol_van est défini, il équivaut à Vandermonde. Si cauchy est configuré, il équivaut à Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>Le plug-in shec encapsule la bibliothèque SHEC multiple.
+ Il permet à Ceph de récupérer les données plus efficacement qu'avec les codes Reed Solomon.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>Nombre de blocs de parité, chacun incluant chaque bloc de données dans sa
+ plage de calcul. Ce nombre est utilisé comme estimateur de durabilité. Par exemple, si c=2,
+ 2 OSD peuvent être arrêtés sans perte de données.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Nom du compartiment crush utilisé pour la première étape de la règle CRUSH.
+ Par exemple, l'étape de définition des valeurs par défaut.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Vérifiez qu'il n'existe pas deux blocs dans un compartiment avec le même domaine de
+ défaillance. Par exemple, si le domaine de défaillance est un hôte, deux blocs ne seront pas stockés sur le même
+ hôte. Cette option est utilisée pour créer une étape de la règle CRUSH telle que chooseleaf host.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Restreindre le placement aux périphériques d'une classe spécifique
+ (par exemple, ssd ou hdd), en utilisant les noms des classes de périphériques crush dans la carte CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Définissez le nom du répertoire à partir duquel le plug-in de code d'effacement est chargé.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Autoriser toutes les opérations</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Autorise uniquement les opérations qui ne modifient pas le serveur</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>N'autorise pas les opérations de lecture ou d'écriture, mais toutes les autres.</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>N'autorise pas la lecture, l'écriture ni aucune autre opération modifiant les attributs d'un fichier ou le contenu d'un répertoire.</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>N'autorise aucun accès</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Sélectionner la priorité --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Faible</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Élevée</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Les 5 dernières minutes</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Les 15 dernières minutes</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Les 30 dernières minutes</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>La dernière heure (par défaut)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Les 3 dernières heures</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Les 6 dernières heures</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Les 12 dernières heures</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Les 24 dernières heures</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Hier</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Aujourd'hui</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Depuis le début de la journée</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Avant-hier</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Les 2 derniers jours</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Il y a huit jours</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>La semaine dernière</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Cette semaine</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Depuis le début de la semaine</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Les 7 derniers jours</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Le mois dernier</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Ce mois</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Depuis le début du mois</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Les 30 derniers jours</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Les 90 derniers jours</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Les 6 derniers mois</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>L'année écoulée</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>L'année dernière</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Cette année</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Depuis le début de l'année</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Les 2 dernières années</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Les 5 dernières années</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informations</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Aucun élément sélectionné.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Désélectionnez l'élément pour le sélectionner à nouveau.</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Limite de sélection atteinte</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Balises de filtre</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Ajouter un badge</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Aucun élément disponible.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Ajouter</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Cloner</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Copier</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Nettoyage en profondeur</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Détruire</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Aplatir</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Marquer comme arrêté</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Marquer comme rentré</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Marquer comme perdu</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Marquer comme sorti</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Protéger</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Renommer</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Restaurer</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Déplacer vers la corbeille</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Annuler la protection</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Supprimé</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Cloné</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Copié</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Oui</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Non</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Qualité de service</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Limite de bits/s</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Limite souhaitée d'octets E/S par seconde.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Limite E/S par seconde</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Limite souhaitée d'opérations E/S par seconde.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Limite de bits/s en lecture</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Limite souhaitée de lecture d'octets par seconde.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Limite E/S par seconde en lecture</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Limite souhaitée d'opérations de lecture par seconde.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Limite de bits/s en écriture</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Limite souhaitée d'écriture d'octets par seconde.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Limite E/S par seconde en écriture</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Limite souhaitée d'opérations d'écriture par seconde.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Rafale de bits/s</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>Limite de rafale d'octets en E/S souhaitée.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Rafale E/S par seconde</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Limite de rafale d'opérations E/S souhaitée.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Rafale E/S par seconde en lecture</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Limite de rafale d'octets lus par seconde.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Rafale E/S par seconde en lecture</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>Limite de rafale d'opérations de lecture</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Rafale E/S par seconde en écriture</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Limite de rafale de lectures d'octets souhaitée.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Rafale d'E/S par seconde en écriture</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Limite de rafale d'opérations d'écriture souhaitée.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Impossible de
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>En cours d'exécution</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>exécuter</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Exécuté</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>tâche inconnue</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>En cours de création</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>créer</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>En cours de mise à jour</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>mettre à jour</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>En cours de suppression</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>supprimer</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Instantané RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>mode miroir pour la réserve '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>mettre en miroir l'homologue pour la réserve '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Le nom est déjà utilisé par
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Le nom est déjà utilisé par
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Le nom est déjà utilisé par
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contient des instantanés.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Clonage en cours</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>cloner</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>L'instantané de
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> doit être protégé.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>En cours de copie</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>copie</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Aplatissement</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>aplatir</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Applati</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Nom déjà utilisé par
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Impossible d'annuler la protection de
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> , car cet élément contient des images enfants.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Impossible de supprimer
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, car cet élément est protégé.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Retour à l'état initial</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>rétablir l'état initial</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Rétabli à l'état initial</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>En cours de déplacement</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>déplacer</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Déplacé</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' déplacée vers la corbeille
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Impossible de trouver l'image.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>En cours de restauration.</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>restaurer</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Restauré</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' vers '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Le nom d'image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' est déjà utilisé.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>En cours de purge</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>purger</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Purgé</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>toutes les réserves</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>images de
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Impossible de désactiver la mise en miroir, car l'élément contient un homologue.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>réserve '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>profil de code d'effacement '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>cible '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.id-ID.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.id-ID.xlf
new file mode 100644
index 00000000..b66f0391
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.id-ID.xlf
@@ -0,0 +1,4363 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="id-ID">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Pengalih navigasi</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Dasbor</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Klaster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Hos</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitor</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Konfigurasi</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>peta CRUSH</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Modul Ceph Manajer</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Log</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Peringatan</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Blok</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Image</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Pencerminan</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Sistemfile</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Gerbang Objek</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Pengguna</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Buket</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Menerima data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> untuk
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Mohon tunggu...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Menampilkan data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> sebelumnya
+untuk
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Gagal memuat data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> untuk
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+Mohon periksa kesehatan klaster.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Kembali</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Pilih bahasa</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Memuat data panel...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Silakan merujuk ke
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentasi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> tentang
+cara mengonfigurasi dan mengaktifkan fungsi pemantauan.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Dasbor Grafana tidak ada. Mohon merujuk ke
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> tentang cara
+menambahkan dasbor ke Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Pemilih Waktu Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Reset Pengaturan</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Gagal memuat data.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>dipilih</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>ditemukan</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>total</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Edit</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nama</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Deskripsi</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Deskripsi lengkap</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Bawaan</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Daemon bawaan</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Layanan</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Nilai</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu tinggi! Tidak boleh lebih besar dari
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu rendah! Tidak boleh lebih rendah dari
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Simpan</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>Penampil peta CRUSH</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Daftar Hos</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Performa Keseluruhan</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Entri tidak ditemukan</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Log Klaster</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Log Audit</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Memuat konfigurasi...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Konfigurasi tidak dapat dimuat.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Edit modul Ceph Manajer</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>Nilai yang dimasukkan bukan UUID yang valid, cth: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>Nilai yang dimasukkan harus alamat IP yang valid.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Isian ini tidak boleh kosong.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu tinggi! Harus lebih kecil atau sama dengan
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu rendah! Harus lebih besar atau sama dengan
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>Nilai yang dimasukkan harus berupa angka.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>Nilai yang dimasukkan harus berupa angka atau desimal.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Perbarui</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Status</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>ID Klaster</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmap diubah</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmap epoch</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>kuorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>kuorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>con yang dibutuhkan</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>mon yang dibutuhkan</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>Memenuhi Kuorum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Tidak dalam Kuorum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Batal</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Anda yakin ingin
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> dari
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Ya, saya yakin.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Flag OSD Klaster</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Kirim</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Tingkat lanjut...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Prioritas pemulihan OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Prioritas</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Ubah nilai prioritas</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Isian ini harus diisi!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu tinggi! Tidak boleh lebih tinggi dari
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>Nilai yang dimasukkan terlalu rendah! Tidak boleh lebih rendah dari
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Ubah bobot OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>Nilai harus antara 0 dan 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Ubah bobot</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Dalam } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Anda akan menerapkan
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> scrub pada
+OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {dalam } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Daftar OSD</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> akan ditandai
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> jika ingin melanjutkan.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>OSD tidak aman untuk dihancurkan!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> akan
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> jika ingin melanjutkan.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Detail</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Nilai</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Tutup</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Hapus</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Kesehatan</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statistik </target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Mohon periksa
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+tentang cara mengonfigurasi dan aktfikan fungsi manajemen NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Klien</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Semua klien dapat mengakses</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Alamat</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Wajib diisi</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Harus mengandung satu atau lebih nilai yang dipisahkan koma</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Contoh:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Tipe Akses</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Tambah klien</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Memuat...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Klaster tidak tersedia --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Pilih klaster --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Tambah daemon</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Backend Penyimpanan</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Tidak ada pool data tersedia --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Pilih backend penyimpanan --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Pengguna Gerbang Objek</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Pengguna tidak tersedia --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Pilih pengguna gerbang objek --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>ID Pengguna CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Klien tidak tersedia --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Pilih klien cephx --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nama CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Label Keamanan</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Aktifkan label keamanan</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFS Path</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Lintasan atau path harus dimulai dengan '/' dan diikuti dengan kata</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Direktori baru akan dibuat</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Path</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Path hanya boleh berupa '/' atau kata</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Buket baru akan dibuat</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protokol NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Tag NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Alternatif akses untuk mount
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFSv3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (tidak boleh diawali /).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Klien mungkin tidak dapat mount subdirektori (cth. jika Tag = foo, klien mungkin tidak bisa mount foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Dengan menggunakan opsi Tag yang berbeda, Path yang sama akan diekspor beberapa kali.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>Posisi dari
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> yang diekspor ini menempati
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (ini harus unik).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Dengan menggunakan opsi Pseudo yang berbeda, Path yang sama akan diekspor beberapa kali.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Tipe akses tidak tersedia --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Pilih tipe akses --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- Squash tidak tersedia --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- Pilih jenis squashing id pengguna yang akan dilakukan --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protokol Transport</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Selamat datang di Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Nama pengguna harus diisi</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Kata sandi harus diisi</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Masuk</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Maaf, pengguna tidak terdaftar di Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Kembali ke Halaman Masuk
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Anda akan dikeluarkan dari Penyedia Identitas saat Anda mencoba masuk.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Terlarang</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Maaf, Anda tidak dizinkan melihat hal yang Anda inginkan.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Maaf, kami tidak dapat menemukan yang Anda cari</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Hapus semua</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Notifikasi terkini</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Tidak ada tugas latar belakang.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Tugas Latar Belakang</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Bantuan</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Dokumentasi </target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>Tentang</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Pengaturan Dasbor</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Manajemen Pengguna</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Pengguna masuk</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Masuk sebagai
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Keluar</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nama...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Nama yang dipilih sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Deskripsi...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Izin</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Peran</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nama pengguna</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Kata sandi</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Konfirmasi kata sandi</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Konfirmasi kata sandi tidak sesuai dengan kata sandi.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Nama lengkap</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>Email</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>Email tidak valid.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Anda akan menghapus izin "pengguna baca / perbarui" dari diri Anda sendiri.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Jika melanjutkan, Anda tidak akan lagi dapat menambahkan atau menghapus peran dari pengguna manapun.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Anda yakin ingin melanjutkan?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Penghitung kinerja tidak tersedia</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Atribut (peta OSD)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Metadata tidak tersedia</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadata</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Penghitung kinerja</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histogram tidak tersedia:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Tulis</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Baca</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histogram</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Detail Performa</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Nilai saat ini</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Tipe</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Min</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Maks</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Flag</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Sumber</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Level</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Boleh diperbarui saat dijalankan (bisa diedit)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Tag</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Nilai Enum</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Lihat juga</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Status Klaster</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Manajer Daemon</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Gerbang Objek</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Server Metadata</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>Gateway iSCSI</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>IOPS klien</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Throughput Pengguna</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Baca/Tulis Klien</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Throughput Pemulihan</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Scrub</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Kinerja</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Kapasitas mentah</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objek</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>PG per OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Status PG</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Kapasitas</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Lihat
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> Log untuk detil lainnya.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Peringkat</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Klien:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Pindahkan image ke tempat sampah</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Untuk pindahkan
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> ke tempat sampah,
+tekan
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Pindah Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Anda juga dapat memilih tanggal kedaluwarsa.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>Proteksi berakhir pada</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>TIDAK DIPROTEKSI</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Format tanggal salah. Mohon gunakan "TTTT-BB-HH JJ:mm:dd".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>Proteksi telah kedaluarsa. Mohon pilih tanggal masa mendatang atau kosongkan.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Pindahkan Image</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Ikhtisar</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Target</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Otentikasi Discovery</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Pengguna</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Nama pengguna harus terdiri dari 8 hingga 64 karakter dan
+hanya boleh mengandung huruf, '.', '@', '-', '_' atau ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Pengguna Bersama</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Kata sandi bersama</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Mohon cek ke
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+tentang cara mengonfigurasi dan mengaktifkan fungsi manajemen iSCSI Target.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Informasi tersedia:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>iSCSI Target tidak tersedia</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Hanya tersedia untuk image RBD dengan
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> yang diaktifkan.
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Pool Data</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Dibuat</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Ukuran</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Ukuran objek</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Fitur</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Disiapkan</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/A</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Total disiapkan</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Unit setrip</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Jumlah setrip</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Induk</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Awalan nama blok</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Urutan</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Snapshot</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Image</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Pengaturan ini akan membatalkan nilai global</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Global</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Ini adalah nilai global. Tidak ada nilai yang diset untuk image ini.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' dan '@' tidak diperbolehkan.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Tidak ada pool rbd tersedia --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Pilih pool --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Gunakan pool data terdedikasi</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Pool data</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Pool terdedikasi yang menyimpan data-objek dari RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>cth. 10GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Anda harus menaikkan ukuran.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Tingkat lanjut</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Setrip</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Unit setrip</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Pilih ukuran setrip --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Isian ini harus diisi karena jumlah setrip telah ditentukan!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>Unit setrip lebih besar dari ukuran objek.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Jumlah setrip</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Isian wajib diisi karena unit setrip didefinisikan!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Jumlah setrip harus lebih besar dari 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot RBD
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Ganti nama} other {Buat} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>DIPROTEKSI</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>TIDAK DIPROTEKSI</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Anda akan mengembalikan semula</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Kosongkan Tempah Sampah</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Untuk menghapus, pilih satu atau Semua image dan pilih</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Pool:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nama Pool...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Semua</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Pulihkan Image</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Untuk memulihkan</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>ketik nama baru image dan pilih</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nama Baru</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Kedaluwarsa pada</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Diproteksi hingga</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Image ini diproteksi hingga
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Tempat sampah</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologi iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Mengganti parameter ini dari nilai bawaan biasanya tidak diperlukan.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Pengaturan</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Konfirmasi</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Pengaturan Lanjut</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>Target IQN</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>Pola IQN salah.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Suatu IQN memiliki notasi seperti ini 'iqn.$tahun-$bulan.$reversedAddress:$definedName'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Contoh: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Informasi lainnya</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Pengaturan lanjutan target ini telah dimodifikasi.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portal</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Dibutuhkan min
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gerbang/gateway.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Tambahkan portal</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Pengaturan Image ini telah dimodifikasi.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Tambahkan image</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Otentikasi ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Inisiator</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Inisiator</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>Klien IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>Inisiator IQN harus unik.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Nama pengguna harus terdiri atas 8 hingga 64 karakter dan
+hanya boleh mengandung huruf, '.', '@', '-', '_' atau ':'.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>Inisiator termasuk ke dalam grup. Image akan dikonfigurasi di dalam grup.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Tidak ada yang ditambahkan.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Tambahkan inisiator</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Grup</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Grup</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Tambahkan grup</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Konfigurasi RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Menghapus nilai konfigurasi lokal. Nilai konfigurasi induk akan diturun dan digunakan.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>Nilai minimum adalah 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Masalah</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Menyinkronkan</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Siap</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Edit mode pencerminan pool</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Untuk mengubah mode pencerminan pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, pilih mode baru dari daftar dan klik 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Perbarui
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Mode</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Klaster mitra harus dihapus sebelum menonaktfikan pencerminan.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+mitra pencerminan pool
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Edit} other {Tambah} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> pool
+atribut mitra pencerminan untuk pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> dan klik
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Kirim
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nama Klaster</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Nama klaster tidak valid.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>CephX ID tidak valid.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Alamat Monitor</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Alamat dengan pemisah-koma...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>Alamat monitor tidak valid.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX Key</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64-encoded key...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>Kunci CephX harus base64 encoded.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Daftar pool</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Nama hanya boleh terdiri dari alfanumerik, tanda hubung, dan garis bawah.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Nama profil erasure code sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Plugin</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Pecahan data (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Harus sama dengan atau lebih dari 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Pecahan Coding (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Harus sama dengan atau lebih dari 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Penduga daya tahan (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Lokalitas (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Domain kegagalan Crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Lokalitas Crush</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Tidak ada</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Teknik</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Ukuran paket</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Crush root</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Kelas perangkat Crush</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>apa saja</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Direktori</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Nama pool Ceph yang dipilih sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Jenis pool</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Pilih jenis pool --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Grup penempatan</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Dibutuhkan setidaknya satu grup penempatan!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Klaster Anda tidak dapat menangani PG sebanyak ini. Mohon hitung ulang jumlah PG yang dibutuhkan.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Bantuan penghitungan</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>Pengaturan PG saat ini telah dihitung untuk Anda, Anda
+harus memastikan nilai tersebut sesuai kebutuhan sebelum mengajukan.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Aturan CRUSH</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Pilih aturan crush --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Aturan crush</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Crush steps</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Aturan crush tidak dapat digunakan di klaster ini karena
+jumlah OSD terlalu sedikit untuk memenuhi syarat minimal OSD untuk aturan ini.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Jumlah replikasi</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Maksimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>Ukuran yang dimasukkan di luar jangkauan. Nilai yang valid
+dari
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> hingga
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Profil erasure code</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Tidak ada profil erasure code --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Pilih profil erasure code --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC Overwrites</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Aplikasi</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Kompresi</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algoritma</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Tidak ada algoritma pengompresian erasure --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Ukuran blob minimum</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>cth. 128KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>Nilai harus lebih besar dari 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Ukuran maksimum blob</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>cth. 512KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>Nilai harus lebih besar dari ukuran minimum blob</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Rasio</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Rasio kompresi</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>Nilai harus antara 0.0 dan 1.0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Tidak boleh membuat pool RBD dengan nama yang mengandung '/'.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Mohon ganti atau hapus 'rbd' dari daftar aplikasi.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Detil Cache Bertingkat</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Silakan cek kembali
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentasi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+tentang cara mengonfigurasi dan mengaktifkan fungsi manajemen Gerbang Objek.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Daftar Daemon</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Penghitung Performa</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Memuat data buket...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Buket data tidak dapat dimuat.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>Id</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>Nilai tidak valid.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Pemilik</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Pilih pengguna --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Jenis indeks</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Aturan penempatan</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Penanda</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Penanda maksimum</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Versi</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Versi Master</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Modifikasi waktu</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Zona grup</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Kuota Buket</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Diaktifkan</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Ukuran maksimum</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Tak terbatas</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Objek maksimum</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Pilih nama pengguna --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Kunci otomatis-dibuat</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Kunci akses</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Kunci rahasia</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Alamat email</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Dihentikan</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Sistem</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {Tidak} 1 {Ya} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Buket maksimum</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Subpengguna</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Kemampuan</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Kuota pengguna</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Tampilkan</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Kunci</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Pilih tipe --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Izin</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Pilih izin --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Subpengguna</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>ID subpengguna sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>baca, tulis</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>penuh</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Kunci Swift</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Sandi otomatis-dibuat</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Memuat data pengguna...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Data pengguna tidak dapat dimuat.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>ID pengguna yang dipilih sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Ini bukan alamat email yang valid.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>Alamat email yang dipilih sudah digunakan.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Maks. buket</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>Nilai yang dimasukkan harus &gt;= 0.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>Kunci S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Tidak ada sub-pengguna.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Kunci tidak ditemukan.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Kemampuan tidak ada.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Ukuran tak terbatas</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Ukuran maks.</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Objek tak terbatas</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Objek maks.</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Terkini</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Otentikasi penemuan telah diperbarui</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Tidak ada portal yang tersedia.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Tidak ada image yang tersedia.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Tidak ada image yang tersedia. Mohon pastikan Anda telah menambahkan image ke target.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Tidak ada inisiator tersedia. Mohon pastikan Anda telah menambahkan inisiator ke target.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Target</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Keadaan</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Baca Bytes</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Tulis Bytes</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Ops Baca</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Ops Tulis</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O Sejak</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instance</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nama hos</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Isu</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Kemajuan</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Dimatikan</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Mode Edit</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Tambahkan Mitra</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Edit Mitra</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Hapus Mitra</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Pemimpin</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># Lokal</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># Jauh</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>mitra pencerminan</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Kunci</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Perataan mendalam</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Lapisan</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Kunci eksklusif</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Peta objek (butuh kunci-eksklusif)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Penjurnalan (membutuhkan kunci-eksklusif)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Kembalikan snapshot RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Kembalikan</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Snapshot RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Dihapus pada</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>id</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>tipe</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>keadaan</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>versi</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Hos</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>induk</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Peringkat</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Aktivitas</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inode</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Penggunaan</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Daemon siaga</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>Nilai dapat diperbarui saat runtime.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Daemon/klien tidak dapat mengambil nilai dari
+basis data konfigurasi monitor. Kami tidak mengizinkan mengubah ini dari 'ceph config
+set ...'. Pilihan ini harus dikonfigurasi melalui ceph.conf atau CLI.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>Pilihan hanya dapat bekerja selama daemon dimulai.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>Pilihan hanya berpengaruh pada pembuatan klaster.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>Pilihan hanya berpengaruh pada pembuatan daemon.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Perbarui opsi konfigurasi
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Layanan</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Nilai saat ini</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Dapat diedit</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Opsi diperbarui untuk modul &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Aktifkan</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Nonaktifkan</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Menghubungkan kembali, mohon tunggu...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Alamat Publik</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Buka Sesi</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Tidak boleh Masuk</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>OSD yang telah ditandai keluar tidak akan ditandai masuk saat mereka menyala</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Tidak boleh Keluar</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSD tidak akan otomatis ditandai keluar setelah interval dikonfigurasi</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Tidak Nyala</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSD tidak diizinkan menyala</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Tidak Mati</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Laporan kegagalan OSD sedang diabaikan sehingga monitor tidak akan menandai OSD mati</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Jeda</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Jeda baca dan tulis</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Nonaktifkan Scrub</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Scrubbing dinonaktifkan</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Nonaktifkan Deep Scrub</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Deep Scrubing dinonaktifkan</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Tidak ada Penambalan</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Penambalan PG dihentikan</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Tidak ada Pemulihan</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Pemulihan PG dihentikan</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Urutan Bitwise</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Gunakan urutan bitwise</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Buang Snapdirs</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD memiliki snapset yang dikonversi</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Pulihkan yang telah dihapus</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Penghapusan dilakukan saat pemulihan bukan saat bermitra</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Batas Maks Log PG</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Taruh batas maks pada panjang log pg</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Flag OSD diperbarui</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>keluar</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>masuk</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>gugur</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Tandai</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD hilang</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>ditandai hilang</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Buang</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>dibuang</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>hancurkan</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>dihancurkan</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>PG</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Bita baca</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Bita tulis</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Ops baca</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Ops tulis</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Tandai OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Tandai
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Maks Penambalan</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Maks Pemulihan Aktif</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Maks Menjalankan Pemulihan Tunggal</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Jeda Pemulihan</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Ubahsuai</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Piroritas &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot; kecepatan pemulihan OSD diperbarui.
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> telah diinisialisasi pada OSD berikut:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Tugas</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Keparahan</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Dimulai</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Diperbarui</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Terpakai</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Tersedia</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Bersih</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>Bekerja</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Peringatan</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Tidak diketahui</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>nyala</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>tidak ada filesistem</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>aktif</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>siaga</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/a</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>daemon aktif</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>kuorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Layanan NFS Ganesha belum dikonfigurasi.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transport</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Pengguna CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>Filesistem CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(diturunkan dari konfig global)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>diturunkan dari konfig global</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Pilih jenis squashing id pengguna yang akan dilakukan --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Tidak ada daemon tersedia.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Mode Cache</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Min Waktu Usir</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Min Waktu Buang</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Target Maks Bita</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Target Maks Objek</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Tidak ada aplikasi ditambahkan</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Batas aplikasi tercapai</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Sebuah pool hanya dapat memiliki empat definisi aplikasi.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Karakter diperbolehkan '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>Panjang maksimum 128 karakter</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Saring atau tambah aplikasi</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Tambah aplikasi</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>profil erasure code</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Ukuran Replikasi</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Perubahan Terakhir</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Profil Erasure Code</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Aturan Crush</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Bita tulis</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>buket</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Buket Gerbang Objek &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; diperbarui
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Buat buket Gerbang Objek &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>buket</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>pengguna</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Perbarui pengguna Gerbang Objek &amp;quot
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>;&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Buat pengguna Gerbang Objek &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>pengguna</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Cakupan</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Baca</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Buat</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Peran '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' dibuat
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Peran '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' diperbarui
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Peran Sistem</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Peran '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' dihapus
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Pengguna &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; dibuat
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Perbarui pengguna</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Lanjutkan</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Anda dikeluarkan otomatis karena peran Anda telah berubah.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Perbarui pengguna &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Hapus pengguna &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Gagal menghapus pengguna &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Saat ini Anda masuk sebagai &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Tiap objek dipecah dalam pecahan-data, masing-masing disimpan pada OSD yang berbeda.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Hitung pecahan coding untuk tiap objek dan simpan pada OSD yang berbeda.
+Jumlah pecahan data juga menjadi jumlah OSD yang diperbolehkan mati tanpa kehilangan data.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Plugin jerasure merupakan plugin paling umum dan fleksibel,
+serta merupakan plugin bawaan Ceph untuk pool erasure code.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>Teknik yang lebih fleksibel yaitu reed_sol_van : cukup mengeset k
+dan m. Teknik cauchy_good bisa lebih cepat, namun Anda harus memilih ukuran paket
+dengan seksama. Semua reed_sol_r6_op, liberation, blaum_roth, liber8tion setara dengan RAID6
+dalam hal mereka hanya bisa diatur dengan m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>Penyandian dilakukan setiap saat pada ukuran bita paket.
+Sulit untuk menentukan ukuran paket yang tepat.
+Silakan cek dokumentasi jerasure untuk informasi lebih mendalam.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Pada plugin jerasure, saat objek dengan erasure code disimpan pada
+banyak OSD, pemulihan dari OSD yang hilang membutuhkan akses dari OSD lainnya.
+Contoh, saat jerasure dikonfigurasi dengan k=8 dan m=4, saat satu OSD mati, maka pemulihan akan membutuhkan pembacaan dari tujuh OSD lainnya.
+
+Plugin lrc erasure code membuat pecahan paritas lokal agar dapat memulihkan
+dengan OSD yang lebih sedikit. Contoh, jika lrc dikonfigurasi dengan k=8, m=4, dan l=4, maka lrc akan
+membuat pecahan paritas tambahan tiap empat OSD. Saat satu OSD mati, maka pemulihan dapat dilakukan hanya dengan 4 OSD, alih-alih 7 OSD.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Kelompokkan pecahan data dan coding ke dalam ukuran lokalitas. Controh
+untuk k=4 dan m=2, saat lokalitas=3 dua grup dari tiga akan dibuat. Setiap set akan
+dipulihkan tanpa membaca pecahan dari set lainnya.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>Tipe buket crush setiap set pecahan yang didefinisikan oleh l
+akan disimpan. Contoh, jika diset pada rak, tiap grup pecahan l akan
+ditempatkan pada rak berbeda. Ini akan digunakan pada aturan step CRUSH yaitu
+memilih tiap rak. Jika tidak diset, tidak akan ada pengelompokkan.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Plugin isa menghimpun perpustakaan ISA. Hanya dapat berjalan pada prosesor Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>Plugin ISA memiliki dua jenis Reed Solomon.
+Jika reed_sol_van diset, maka menjadi Vandermonde, jika cauchy diset, maka menjadi Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>Plugin shec mengenkapsulasi banyak pustaka SHEC.
+Hal ini agar ceph dapat dipulihkan dengan lebih efisien dari kode Reed Solomon.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>Jumlah potongan paritas yang masing-masing mencakup setiap potongan data
+dalam rentang perhitungannya. Nilai ini digunakan untuk perkiraan daya tahan. Contoh, jika c=2,
+2 OSD dapat mati tanpa kehilangan data.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Nama buket crush digunakan sebagai langkah pertama dari aturan CRUSH.
+Contoh diambil langkah bawaan.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Memastikan tidak ada pecahan data berada pada buket dengan domain kegagalan
+yang sama. Contoh, saat domain gagal adalah hos, maka tidak ada pecahan data yang akan disimpan
+pada hos yang sama. Aturan CRUSH seperti step chooseleaf hos akan digunakan untuk hal tersebut.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Batasi penempatan ke perangkat dengan kelas tertentu
+(cth. ssd atau hdd), menggunakan nama kelas perangkat crush pada peta CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Set nama direktori empat plugin erasure code akan dimuat.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Izinkan semua operasi</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Izinkan hanya untuk operasi yang tidak mengubah server</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Tidak diizinkan untuk operasi baca dan tulis, namun izinkan operasi lainnya</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Tidak diizinkan untuk baca, tulis, atau operasi lainnya yang mengubah atribut berkas atau konten direktori</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Tidak diizinkan untuk semua hal</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Pilih prioritas --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Rendah</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Tinggi</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>5 menit terakhir</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>15 menit terakhir</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>30 menit terakhir</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>1 Jam Terakhir (Bawaan)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>3 jam terakhir</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>6 jam terakhir</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>12 jam terakhir</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>24 jam terakhir</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Kemarin</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Hari ini</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Sejauh hari ini</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Kemarin dulu</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>2 hari terakhir</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Hari ini minggu lalu</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Minggu lalu</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Minggu ini</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Sejauh minggu ini</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>7 hari terakhir</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Bulan lalu</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Bulan ini</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Sejauh bulan ini</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>30 hari terakhir</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>90 hari terakhir</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>6 bulan terakhir</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>1 tahun terakhir</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Tahun lalu</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Tahun ini</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Sejauh tahun ini</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>2 tahun terakhir</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>5 tahun terakhir</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informasi</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Tidak ada yang dipilih.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Batalkan memilih untuk memilih ulang</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Batas pemilihan tercapai</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Tanda penyaringan</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Tambahkan lencana</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Tidak ada yang tersedia.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Tambah</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Klon</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Salin</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Deep Scrub</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Hancurkan</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Ratakan</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Tandai Gugur</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Tandai Masuk</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Tandai Hilang</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Tandai Keluar</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Proteksi</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Ubah nama</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Pulihkan</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Pindahkan ke Tempat Sampah</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Tidak diproteksi</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Dihapus</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Diklon</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Disalin</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Ya</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Tidak</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Kualitas Layanan atau QoS</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Limit BPS</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Limit IO bytes per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Limit IOPS</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Limit operasi IO per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Limit Baca BPS </target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Limit byte baca per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Limit IOPS Baca</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Limit operasi baca per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Limit Tulis BPS</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Limit tulis byte per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Limit IOPS Tulis</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Limit operasi tulis per detik yang diinginkan.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Letupan BPS</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst dari IO byte.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Letupan IOPS</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst operasi IO.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Letupan Baca BPS</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst dari baca byte.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Letupan IOPS Baca</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst operasi baca.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Letupan BPS Tulis</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst dari tulis byte.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Letupan IOPS Tulis</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Limit yang diinginkan untuk letupan atau burst dari operasi baca.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Gagal untuk
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Mengeksekusi</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>eksekusi</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Dieksekusi</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>tugas tak diketahui</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Membuat</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>buat</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Memperbarui</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>perbarui</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Menghapus</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>hapus</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Snapshot RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>mode pencerminan untuk pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>mitra pencerminan untuk pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Nama telah digunakan oleh
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Nama telah digunakan oleh
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Nama telah digunakan oleh
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> berisi snapshot.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Pengklonan</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>klon</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>Snapshot
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> harus diproteksi.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Menyalin</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>salin</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Meratakan</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>ratakan</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Diratakan</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Nama telah digunakan oleh
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Tidak dapat menghapus proteksi
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> karena mengandung child image.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Tidak dapat menghapus
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> karena diproteksi.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Mengembalikan</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>kembalikan</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Dikembalikan</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Memindahkan</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>pindah</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>dipindahkan</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' ke tempat sampah
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Tidak dapat menemukan image.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Memulihkan</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>pulihkan</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Dipulihkan</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' ke '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Nama image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' sudah digunakan.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Membuang</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>buang</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Dibuang</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>semua pool</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>image dari
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Gagal menonaktifkan pencerminan karena sedang bermitra.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>profil erasure code '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.it-IT.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.it-IT.xlf
new file mode 100644
index 00000000..f8214f73
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.it-IT.xlf
@@ -0,0 +1,4367 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="it-IT">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Attiva/Disattiva barra di navigazione</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Dashboard</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Cluster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitor</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Configurazione</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>Mappa CRUSH</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Moduli Manager</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Log</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Avvisi</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Blocco</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Immagini</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Esecuzione della copia speculare</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI </target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>File system</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Utenti</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Compartimenti</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Recupero dati
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> per
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Attendere...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Visualizzazione dei dati memorizzati in precedenza nella cache
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ per
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Impossibile caricare i dati
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> per
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Verificare lo stato del cluster.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Indietro</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Selezionare una lingua</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Caricamento pannello dati in corso...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Consultare la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> su come
+ configurare e abilitare la funzionalità di monitoraggio.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Il dashboard di Grafana non esiste. Consultare la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> su come
+ aggiungere dashboard a Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Selezione ora di Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Impostazioni di ripristino</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Non è stato possibile caricare i dati.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>selezionato</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>trovato</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>totale</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Modifica</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nome</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Descrizione</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Descrizione lunga</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Default</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Default del daemon</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Servizi</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Valori</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>Il valore immesso è troppo alto. Non deve essere maggiore di
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>Il valore immesso è troppo basso. Non deve essere minore di
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Salva</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>Visualizzatore mappa CRUSH</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Elenco degli host</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Prestazioni complessive</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Nessuna voce trovata</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Log dei cluster</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Log delle revisioni</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Caricamento della configurazione in corso...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Impossibile caricare la configurazione.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Modifica modulo Manager</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>Il valore immesso non è un UUID valido, ad es.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>Il valore immesso deve essere un indirizzo IP valido.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Questo campo è obbligatorio.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>Il valore immesso è troppo alto. Deve essere minore o uguale a
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>Il valore immesso è troppo basso. Deve essere maggiore o uguale a
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>Il valore immesso deve essere un numero.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>Il valore immesso deve essere un numero o un decimale.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Aggiorna</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Stato</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>ID cluster</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>mappa mon modificata</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>epoca mappa mon</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>con richiesta</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>mon richiesto</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>Nel quorum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Non nel quorum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Annulla</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Si è sicuri di voler
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> l'elemento
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> selezionato?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Sì.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Flag OSD in tutto il cluster</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Invia</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Avanzate...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Priorità di recupero OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Priorità</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Personalizza valori di priorità</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Questo campo è obbligatorio.</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>Il valore immesso è troppo alto. Non deve essere maggiore di
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>Il valore immesso è troppo basso. Non deve essere minore di
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Ripesa OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>Il valore deve essere compreso tra 0 e 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Ripesa</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>Pulitura degli
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>OSD
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Deep } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Si sta per eseguire una
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>pulitura
+ dell'OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {deep } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Elenco degli OSD</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L'OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> viene contrassegnato
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se si procede.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>Non è sicuro eliminare definitivamente l'OSD.</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>L'OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> viene
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se si procede.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Dettagli</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Valore</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Chiudi</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Elimina</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Stato</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statistiche</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Consultare la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ su come configurare e abilitare la funzionalità di gestione di NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Client</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Può accedere qualsiasi client</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Indirizzi</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Campo obbligatorio</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Deve contenere uno o più valori delimitati da virgole</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Ad esempio:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Tipo di accesso</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Esegui squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Aggiungi client</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Caricamento in corso...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Nessun cluster disponibile --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Selezionare il cluster --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Aggiungi daemon</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Backend di storage</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Nessun pool di dati disponibile --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Selezionare il backend di storage --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Utente Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Nessun utente disponibile --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Selezionare l'utente Object Gateway --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>ID utente CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Nessun client disponibile --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Selezionare il client Cephx --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nome CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Etichetta di sicurezza</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Abilita etichetta di sicurezza</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Percorso CephFS</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Il percorso deve iniziare con una barra '/' e può essere seguito da una parola</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Viene creata la nuova directory</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Percorso</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Il percorso può essere solo una singola barra '/' o parola</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Viene creato il nuovo compartimento</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protocollo NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Tag NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Accesso alternativo per montaggi
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (non deve contenere una / iniziale).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>I client non possono montare le sottodirectory (ad es. se Tag = foo, il client non può montare foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Utilizzando diverse opzioni Tag, è possibile esportare più volte lo stesso percorso.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>La posizione che occupa l'esportazione
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ nello
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (deve essere univoca).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Utilizzando diverse opzioni Pseudo, è possibile esportare più volte lo stesso percorso.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Nessun tipo di accesso disponibile --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Selezionare il tipo di accesso --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- Nessuno squash disponibile --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>--Selezionare il tipo di squash dell'ID utente da eseguire --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protocollo di trasporto</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Benvenuto in Ceph.</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Nome utente necessario</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Password richiesta</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Login</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Spiacenti, l'utente non esiste in Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Tornale alla
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Pagina di login
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Si viene disconnessi dal Provider di identità
+ quando si riprova a eseguire il login.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Non consentito</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Spiacenti, non è consentito visualizzare ciò che si stava cercando.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Spiacenti, impossibile trovare ciò che si stava cercando</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Rimuovi tutto</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Notifiche recenti</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Non esistono task in background.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Task in background</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Guida</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Documentazione</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>Informazioni su</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Impostazioni del dashboard</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Gestione utenti</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Utente connesso</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Connesso come
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Disconnetti</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nome...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Il nome scelto è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Descrizione...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Autorizzazioni</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Ruoli</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nome utente</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Password</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Conferma password</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>La password di conferma non corrisponde alla password.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Nome completo</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>E-mail</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>E-mail non valida.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Si stanno per rimuovere le autorizzazioni di "lettura/aggiornamento utente" dal proprio utente.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Se si continua, non è più possibile aggiungere o rimuovere ruoli da qualsiasi utente.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Continuare?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Contatori delle prestazioni non disponibili</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Attributi (mappa OSD)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Metadati non disponibili</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadati</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Contatore delle prestazioni</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Istogramma non disponibile:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Scritture</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Letture</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Istogramma</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Dettagli sulle prestazioni</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Valori attuali</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Tipo</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Min</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Max</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Flag</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Origine</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Livello</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Può essere aggiornato al runtime (modificabile)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Tag</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Valori di enumerazione</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Vedere anche</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Stato del cluster</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Manager Daemon</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Object Gateway</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Server di metadati</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI Gateway</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>IOPS client</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Velocità effettiva client</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Lettura/scrittura client</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Velocità effettiva di recupero</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Pulitura</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Prestazioni</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Capacità di base</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Oggetti</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>Gruppi di posizionamento per OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Stato gruppo di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Capacità</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Vedere
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Log
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> per ulteriori informazioni.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Classificazioni</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Client:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Sposta un'immagine nel cestino</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Per spostare
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> nel cestino,
+ fare clic su
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Sposta immagine
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Facoltativamente, è possibile selezionare una data di scadenza.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>La protezione scade alle</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NON PROTETTO</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Formato data errato. Utilizzare "AAAA-MM-GG HH:mm:ss".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>La protezione è già scaduta. Selezionare una data futura o lasciarla vuota.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Sposta immagine</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Panoramica</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Destinazioni</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Autenticazione rilevazione</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Utente</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>I nomi utente devono avere una lunghezza compresa tra 8 e 64 caratteri e
+ possono contenere solo lettere, '.', '@', '-', '_' o ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Utente reciproco</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Password reciproca</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Consultare la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ su come configurare e abilitare la funzionalità di gestione delle destinazioni iSCSI.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Informazioni disponibili:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>Destinazioni iSCSI non disponibili</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Disponibile solo per le immagini RDB con
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> abilitata
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Pool di dati</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Creato</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Dimensioni</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Dimensioni oggetto</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Funzioni</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Soggetto al provisioning</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/D</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Totale soggetto al provisioning</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Unità di striping</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Conteggio di striping</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Superiore</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Prefisso nome blocco</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Ordine</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Snapshot</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Immagine</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Questa impostazione sostituisce il valore globale</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Globale</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Questo è il valore globale. Nessun valore di opzione è stato impostato per questa immagine.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' e '@' non sono consentiti.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Nessun pool rbd disponibile --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Selezionare un pool --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Utilizza un pool di dati dedicato</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Pool di dati</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Pool dedicato che archivia i dati oggetto dell'RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>ad es. 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>È necessario aumentare le dimensioni.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Avanzate</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Striping</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Unità di striping</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Selezionare l'unità di striping --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Questo campo è obbligatorio perché è specificato il numero di striping.</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>L'unità di striping è maggiore delle dimensioni dell'oggetto.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Numero di striping</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Questo campo è obbligatorio perché è specificata l'unità di striping.</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Il numero di striping deve essere maggiore di 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot RBD
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>PROTETTO</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NON PROTETTO</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Si sta per eseguire il rollback</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Elimina definitivamente contenuto del cestino</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Per eliminare definitivamente, selezionare una o tutte le immagini e fare clic su</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Pool:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nome pool...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Tutto</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Ripristina immagine</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Per ripristinare,</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>digitare il nuovo nome dell'immagine e fare clic su</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nuovo nome</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Scaduto alle</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Protetto fino alle</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Questa immagine è protetta fino alle
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Cestino</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologia iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Di solito non è necessario modificare questi parametri rispetto ai valori di default.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Impostazioni</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Conferma</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Impostazioni avanzate</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>IQN di destinazione</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN contiene un modello errato.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Un IQN contiene la notazione seguente 'iqn.$year-$month.$reversedAddress:$definedName'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Ad esempio: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Ulteriori informazioni</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Questa destinazione contiene impostazioni avanzate modificate.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portali</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Gateway richiesti: almeno
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Aggiungi portale</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Questa immagine contiene impostazioni modificate.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Aggiungi immagine</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Autenticazione ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Iniziatori</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Iniziatore</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>IQN client</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>L'IQN dell'iniziatore deve essere univoco.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>I nomi utente devono avere una lunghezza compresa tra 8 e 64 caratteri e
+ possono contenere solo lettere, '.', '@', '-', '_' o ':'.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>L'iniziatore appartiene a un gruppo. Le immagini verranno configurate nel gruppo.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Nessun elemento aggiunto.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Aggiungi iniziatore</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Gruppi</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Gruppo</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Aggiungi gruppo</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Configurazione RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Rimuovere il valore della configurazione locale. Al suo posto verrà ereditato e utilizzato il valore della configurazione superiore.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>Il valore minimo è 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Problemi</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Sincronizzazione in corso</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Pronto</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Modifica modalità speculare per il pool</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Per modificare la modalità speculare per il pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, selezionare una nuova modalità dall'elenco e fare clic su 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Aggiorna
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Modalità</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>È necessario rimuovere i cluster peer prima di disabilitare la copia speculare.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ peer copia speculare del pool
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> gli attributi peer della
+ copia speculare per il pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> e fare clic su
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Invia
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nome cluster</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Il nome del cluster non è valido.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>ID CephX</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>ID CephX...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>L'ID CephX non è valido.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Indirizzi dei monitor</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Indirizzi con valori delimitati da virgole...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>L'indirizzo del monitor non è valido.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>Chiave CephX</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Chiave con codifica Base64...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>La chiave CephX deve essere con codifica Base64.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Elenco dei pool</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Il nome può contenere solo caratteri alfanumerici, trattini e caratteri di sottolineatura.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Il nome del profilo del codice di cancellazione selezionato è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Plugin</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Porzioni di dati (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Deve essere uguale o maggiore di 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Porzioni di codice (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Deve essere uguale o maggiore di 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Stima durata (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Località (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Dominio di errore Crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Località Crush</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Nessuno</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Tecnica</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Dimensione del pacchetto</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Radice Crush</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Classe dispositivo Crush</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>qualsiasi</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Directory</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Il nome del pool Ceph scelto è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Tipo di pool</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Selezionare un tipo di pool --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Gruppi di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>È necessario almeno un gruppo di posizionamento.</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Il cluster non può gestire questo numero eccessivo di gruppi di posizionamento. Ricalcolare il numero di gruppi di posizionamento necessari.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Guida per il calcolo</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>Sono state calcolate le impostazioni dei gruppi di posizionamento attuali;
+ prima di inviare, assicurarsi che i valori soddisfino le proprie esigenze.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Set di regole Crush</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Selezionare una regola Crush --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Regola Crush</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Passaggi Crush</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Non è possibile utilizzare la regola nel cluster attuale perché il numero degli
+ OSD che contiene è troppo basso e non soddisfa il numero minimo di OSD richiesto da questa regola.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Dimensioni replicate</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Minime:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Massime:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>Le dimensioni specificate non sono comprese nell'intervallo. L'intervallo valido è da
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> a
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Profilo del codice di cancellazione</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Nessun profilo del codice di cancellazione disponibile --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Selezionare un profilo del codice di cancellazione --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>Sovrascritture EC</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Applicazioni</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Compressione</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algoritmo</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Nessun algoritmo di compressione della cancellazione disponibile --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Dimensioni minime del blob</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>ad es. 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>Il valore deve essere maggiore di 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Dimensioni massime del blob</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>ad es. 512 KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>Il valore deve essere maggiore delle dimensioni minime del blob</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Rapporto</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Rapporto di compressione</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>Il valore deve essere compreso tra 0,0 e 1,0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Non è possibile creare un pool RBD con una '/' nel nome.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Modificare il nome o rimuovere 'rbd' dall'elenco delle applicazioni.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Dettagli livelli cache</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Consultare la
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentazione
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ su come configurare e abilitare la funzionalità di gestione di Object Gateway.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Elenco dei daemon</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Contatori delle prestazioni</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Caricamento dati compartimento in corso...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Impossibile caricare i dati del compartimento.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>Il valore non è valido.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Proprietario</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Selezionare un utente --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Tipo di indice</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Regola di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Contrassegno</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Contrassegno massimo</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Versione</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Versione master</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Ora di modifica</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Gruppo di zone</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Quota compartimenti</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Abilitato</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Dimensioni massime</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Illimitato</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Numero massimo di oggetti</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Selezionare un nome utente --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Generazione automatica chiave</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Chiave di accesso</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Chiave segreta</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Indirizzo e-mail</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Sospeso</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Sistema</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Numero massimo di compartimenti</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Sottoutenti</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Capacità</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Quota utenti</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Mostra</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Chiavi</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Selezionare un tipo --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Autorizzazione</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Selezionare un'autorizzazione --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Sottoutente</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>L'ID del sottoutente scelto è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>lettura, scrittura</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>pieno</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Chiave Swift</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Generazione automatica segreto</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Caricamento dati utente in corso...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Impossibile caricare i dati utente.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>L'ID utente scelto è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Non è un indirizzo e-mail valido.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>L'indirizzo e-mail scelto è già in uso.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Numero max. di compartimenti</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>Il valore immesso deve essere &gt;= a 0.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>Chiave S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Non esistono sottoutenti.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Non esistono chiavi.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Non esistono capacità.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Dimensioni illimitate</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Dimensione max.</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Oggetti illimitati</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Numero max. di oggetti</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Attuale</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Autenticazione rilevazione aggiornata</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Non sono disponibili pool.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Non sono disponibili immagini.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Non sono disponibili immagini. Assicurarsi di aggiungere un'immagine alla destinazione.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Non sono disponibili iniziatori. Assicurarsi di aggiungere un iniziatore alla destinazione.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Destinazione</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Stato</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Byte letti</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Byte scritti</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Operazioni di lettura</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Operazioni di scrittura</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O da</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Istanza</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nome host</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problema</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Avanzamento</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Disabilitato</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Modalità di modifica</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Aggiungi peer</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Modifica peer</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Elimina peer</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Sequenza iniziale</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># Locale</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># Remoto</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>peer copia speculare</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Chiave</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Appiattimento profondo</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Su strati</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Blocco esclusivo</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Mappa oggetti (richiede il blocco escluso)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Journaling (richiede il blocco esclusivo)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Rollback snapshot RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Esegui rollback</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Snapshot RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Eliminato alle</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>tipo</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>stato</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>versione</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>root</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Classificazione</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Task</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentry</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inode</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Utilizzo</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Daemon in standby</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>È possibile aggiornare il valore al runtime.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>I daemon/client non estraggono questo valore dal
+ database della configurazione di monitoraggio. Non è consentito impostare questa opzione tramite 'ceph config
+ set ...'. È necessario configurare questa opzione tramite ceph.conf o dalla
+ riga di comando.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>L'opzione diventa attiva solo all'avvio del daemon.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>L'opzione interessa solo la creazione del cluster.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>L'opzione interessa solo la creazione del daemon.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Aggiornata opzione di configurazione
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Servizio</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Valore attuale</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Modificabile</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Opzioni aggiornate per il modulo &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Abilita</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Disabilita</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Riconnessione in corso. Attendere.</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Indirizzo pubblico</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Sessioni aperte</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Nessuno in entrata</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>Gli OSD che sono stati contrassegnati come disattivi in precedenza non verranno contrassegnati nuovamente come attivi all'avvio</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Nessuno in uscita</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>Gli OSD non verranno disattivati automaticamente dopo l'intervallo configurato</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Nessuno attivo</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>Non è consentito l'avvio degli OSD</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Nessuno disattivo</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>I rapporti di errore degli OSD vengono ignorati in modo che i monitor non disattivino gli OSD</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Sospendi</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Sospende le operazioni di lettura e scrittura</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Nessuna pulitura</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Pulitura disabilitata</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Nessun pulitura approfondita</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Pulitura approfondita disabilitata</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Nessuna operazione di recupero</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Recupero dei gruppi di posizionamento sospeso</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Nessun recupero</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Recupero dei gruppi di posizionamento sospeso</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Ordinamento bitwise</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Usa ordinamento bitwise</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Snapdir eliminate definitivamente</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>Gli OSD contengono set di snap convertiti</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Eliminazioni recuperi</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Eliminazioni eseguite durante il recupero invece del peering</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Limite rigido log gruppo di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Inserisce un limite rigido alla lunghezza del log del gruppo di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Flag OSD aggiornati</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>esterno</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>interno</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>in basso</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Contrassegna</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD perso</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>contrassegnato come perso</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Elimina definitivamente</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>eliminato definitivamente</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>elimina definitivamente</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>eliminato definitivamente</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>Gruppi di posizionamento</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Byte letti</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Byte scritti</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Operazioni di lettura</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Operazioni di scrittura</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Contrassegna OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Contrassegna
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Numero max di recuperi informazioni</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Numero max di recuperi attivi</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Avvio singolo numero max di recuperi</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Sospensione recupero</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Personalizzato</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Aggiornata la priorità della velocità di recupero dell'OSD &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> è stato inizializzato dall'OSD seguente:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Lavoro</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Gravità</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Avviato</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Aggiornato</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Utilizzato</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Dispon.</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Pulisci</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>In funzione</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Avviso</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Sconosciuto</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>su</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>nessun file system</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>attivo</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>standby</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/d</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>daemon attivo</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target> quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Il servizio NFS Ganesha non è configurato.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Trasporto</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Utente CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>File system CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(ereditato dalla configurazione globale)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>importato dalla configurazione globale</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Selezionare il tipo di squash dell'ID utente che viene eseguito --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Non vi sono daemon disponibili.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Modalità cache</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Numero minimo di giorni per la rimozione</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Numero minimo di giorni per la cancellazione</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Numero max di byte di destinazione</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Numero max di oggetti di destinazione</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Non sono state aggiunte applicazioni.</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Raggiunto il limite di applicazioni</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Un pool può contenere solo fino a quattro definizioni delle applicazioni.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Caratteri consentiti '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>La lunghezza massima è di 128 caratteri</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtra o aggiungi applicazioni</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Aggiungi applicazione</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>profilo del codice di cancellazione</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Dimensioni della replica</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Ultima modifica</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Profilo con codice di cancellazione</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Set di regole Crush</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Byte scritti</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>compartimento</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Aggiornato compartimento Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Creato compartimento Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>compartimenti</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>utente</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Aggiornato utente Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Creato utente Object Gateway &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>utenti</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Ambito</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Lettura</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Crea</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Creato ruolo '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Aggiornato ruolo '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Ruolo di sistema</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Eliminato ruolo '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Creato utente &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Aggiorna utente</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Continua</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Si è stati automaticamente disconnessi perché i ruoli sono stati modificati.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Aggiornato utente &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Eliminato utente &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Impossibile eliminare l'utente &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Si è attualmente connessi come &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Ogni oggetto è suddiviso in porzioni di dati, ciascuna delle quali è memorizzata su un diverso OSD.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Calcola le porzioni di codice relative a ciascun oggetto e le memorizza su diversi OSD.
+ Il numero di porzioni di codice è anche il numero degli OSD che è possibile disattivare senza perdere i dati.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Il plugin jerasure è il plugin più generico e flessibile,
+ ed è anche il plugin di default dei pool con codice di cancellazione di Ceph.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>La tecnica più flessibile è reed_sol_van: è sufficiente impostare k
+ ed m. La tecnica cauchy_good può essere più rapida ma occorre selezionare attentamente la dimensione del
+ pacchetto. reed_sol_r6_op, liberation, blaum_roth, liber8tion sono tutti equivalenti a RAID6,
+ nel senso che è possibile configurarli solo con m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>La codifica viene eseguita su pacchetti di dimensioni in byte, uno alla volta.
+ È difficile scegliere la dimensione del pacchetto corretta.
+ La documentazione su jerasure fornisce informazioni esaustive su questo argomento.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Con il plugin di jerasure, quando un oggetto con codice di cancellazione viene memorizzato su
+ più OSD, il recupero della perdita di un OSD richiede la lettura di tutti gli altri.
+ Ad esempio, se jerasure è configurato con k=8 e m=4, la perdita di un OSD richiede la lettura
+ degli altri undici per il ripristino.
+
+ Il plugin del codice di cancellazione lrc crea porzioni di parità locali che è possibile recuperare utilizzando un
+ minor numero di OSD. Ad esempio, se lrc è configurato con k=8, m=4 e l=4, crea
+ una porzione di parità aggiuntiva ogni quattro OSD. Quando si perde un singolo OSD, è possibile
+ recuperarlo solo con quattro OSD invece che con undici.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Raggruppa le porzioni di codice e dati in set di località dimensione. Ad esempio,
+ per k=4 e m=2, se località=3 vengono creati due gruppi su tre. È possibile recuperare ciascun set
+ senza leggere le porzioni di un altro set.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>Il tipo di compartimento Crush in cui viene memorizzato ciascun set di porzioni definito
+ dall'utente. Ad esempio, se è impostato su rack, ciascun gruppo di porzioni viene
+ posizionato in un diverso rack. Viene utilizzato per creare un passaggio della regola CRUSH come il passaggio choose
+ rack. Se non è impostato, il raggruppamento non viene eseguito.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Il plugin ISA incapsula la libreria ISA. Viene eseguito solo su processori Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>Il plugin ISA è disponibile in due formati Reed Solomon.
+ Se è impostato reed_sol_van, il formato è Vandermonde, se è impostato cauchy, il formato è Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>Il plugin shec incapsula la libreria SHEC multipla.
+ Consente a Ceph di recuperare i dati in modo più efficiente rispetto ai codici Reed Solomon.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>Il numero di compartimenti di parità, ciascuno dei quali include i singoli compartimenti di dati
+ nell'intervallo di calcolo. Il numero viene utilizzato come strumento di stima della durabilità. Ad esempio, se c=2,
+ è possibile disattivare 2 OSD senza perdere i dati.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Il nome del compartimento Crush utilizzato per il primo passaggio della regola CRUSH.
+ Ad esempio il passaggio take default.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Assicurarsi che non esistano due porzioni in un compartimento con lo stesso dominio
+ di errore. Ad esempio, se il dominio di errore è l'host, non verranno memorizzate due porzioni sullo stesso
+ host. Viene utilizzato per creare un passaggio della regola CRUSH come passaggio chooseleaf host.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Limitare il posizionamento ai dispositivi di una classe specifica
+ (ad es. ssd o hdd) usando i nomi delle classi di dispositivi Crush nella mappa CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Impostare il nome della directory da cui viene caricato il plugin del codice di cancellazione.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Consente tutte le operazioni</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Consente solo le operazioni che non modificano il server</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Non consente operazioni di lettura o scrittura, ma consente qualsiasi altra operazione</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Non consente operazioni di lettura o scrittura o qualsiasi operazione che modifichi gli attributi dei file o il contenuto della directory</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Non consente alcun accesso</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Selezionare la priorità --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Bassa</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Alta</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Ultimi 5 minuti</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Ultimi 15 minuti</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Ultimi 30 minuti</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Ultima ora (Default)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Ultime 3 ore</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Ultime 6 ore</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Ultime 12 ore</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Ultime 24 ore</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Ieri</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Oggi</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Fino a oggi</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Giorno prima di ieri</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Ultimi 2 giorni</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Questo giorno della scorsa settimana</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Settimana precedente</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Questa settimana</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Fino a questa settimana</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Ultimi 7 giorni</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Mese precedente</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Questo mese</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Fino a questo mese</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Ultimi 30 giorni</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Ultimi 90 giorni</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Ultimi 6 mesi</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>Ultimo anno</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Anno precedente</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Quest'anno</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Fino a quest'anno</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Ultimi 2 anni</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Ultimi 5 anni</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informazioni</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Nessun elemento selezionato.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Deselezionare l'elemento per selezionare di nuovo</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target> Raggiunto il limite per la selezione</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Filtra tag</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Aggiungi badge</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Non vi sono elementi disponibili.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Aggiungi</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Clona</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Copia</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Pulitura approfondita</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Eliminazione definitiva</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Appiattisci</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Declassa</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Attiva</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Contrassegna come perso</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Disattiva</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Proteggi</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Rinomina</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Ripristina</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Sposta nel cestino</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Rimuovi protezione</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Eliminato</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Clonato</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Copiato</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Sì</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>No</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Qualità di servizio</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Limite di BPS</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Il limite desiderato di byte I/O al secondo.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Limite di IOPS</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Il limite desiderato di operazioni I/O al secondo.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Limite BPS in lettura</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Il limite desiderato dei byte letti al secondo.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Limite di IOPS in lettura</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Il limite desiderato di operazioni di lettura al secondo.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Limite di BPS in scrittura</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Il limite desiderato di byte scritti al secondo.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Limite di IOPS in scrittura</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Il limite desiderato di operazioni di scrittura al secondo.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Burst BPS</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>Il limite di burst desiderato dei byte di I/O.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Burst IOPS</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Il limite di burst desiderato delle operazioni di I/O.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Burst BPS in lettura</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Il limite di burst desiderato dei byte letti.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Burst IOPS in lettura</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>Il limite di burst desiderato delle operazioni di lettura.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Burst BPS in scrittura</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Il limite di burst desiderato dei byte scritti.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Burst di IOPS in scrittura</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Il limite di burst desiderato delle operazioni di scrittura.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Non è stato possibile
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>In esecuzione</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>esegui</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Eseguito</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>task sconosciuto</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Creazione in corso</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>crea</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Aggiornamento in corso</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>aggiorna</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Eliminazione in corso</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>elimina</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Snapshot RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>modalità speculare per il pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>peer della copia speculare per il pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Il nome è già utilizzato da
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Il nome è già utilizzato da
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Il nome è già utilizzato da
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contiene snapshot.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Clonazione in corso</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>clona</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>La snapshot di
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> deve essere protetta.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Copia in corso</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>copia</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Appiattimento</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>appiattisci</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Appiattito</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Il nome è già utilizzato da
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Impossibile rimuovere la protezione da
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> perché contiene immagini figlio.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Impossibile eliminare
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> perché è protetto.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Rollback in corso</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>rollback</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Rollback eseguito</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Spostamento in corso</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>sposta</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Spostato</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>immagine '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' nel cestino
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Impossibile trovare l'immagine.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Ripristino in corso</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>ripristina</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Ripristinato</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>immagine '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' in '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Il nome dell'immagine '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' è già in uso.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>immagine '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Eliminazione in corso</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>elimina definitivamente</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Eliminato definitivamente</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>tutti i pool</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>Immagini da
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Impossibile disabilitare l'esecuzione della copia speculare perché contiene un peer.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>profilo del codice di cancellazione '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>destinazione '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.ja-JP.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.ja-JP.xlf
new file mode 100644
index 00000000..dc39c6cd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.ja-JP.xlf
@@ -0,0 +1,4368 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="ja-JP">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>ナビゲーションの切り替え</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>ダッシュボード</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>クラスタ</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>ホスト</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>モニター</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>設定</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSHマップ</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>マネージャモジュール</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>ログ</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>アラート</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>プール</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>ブロック</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>イメージ</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>ミラーリング</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>ファイルシステム</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>オブジェクトゲートウェイ</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>デーモン</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>ユーザ</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>バケット</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>戻る</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>言語の選択</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>パネルデータを読み込んでいます...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>監視機能を設定および有効化
+する方法に関する
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ドキュメント
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>を
+参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Grafanaダッシュボードが存在していません。
+Grafanaにダッシュボードを追加する方法に関する
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ドキュメント
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>を参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Grafana Time Picker</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>設定のリセット</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>データを読み込めませんでした。</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>選択済み</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>検出済み</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>合計</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>編集</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>名前</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>説明</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>長い説明</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>デフォルト</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>デーモンのデフォルト</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>サービス</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>値</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>入力された値は大きすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>より大きい値を入力することはできません。
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>入力された値は小さすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>より小さい値を入力することはできません。
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>保存</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>CRUSHマップビューア</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>ホストリスト</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>全体的なパフォーマンス</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>エントリが見つかりません</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>クラスタログ</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>監査ログ</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>設定を読み込んでいます...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>設定を読み込めませんでした。</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>マネージャモジュールの編集</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>入力された値は有効なUUIDではありません(有効なUUIDの例: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8)。</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>有効なIPアドレスを入力する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>このフィールドは必須です。</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>入力された値は大きすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>以下の値を入力する必要があります。
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>入力された値は小さすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>以上の値を入力する必要があります。
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>数字を入力する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>数字または小数を入力する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>ステータス</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>クラスタID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmapが変更されました</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmapエポック</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>定数con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>定数mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>必須のcon</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>必須のmon</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>定数内</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>非定数内</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>キャンセル</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>選択された
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>を
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>してもよろしいですか?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>はい。</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>クラスタ全体のOSDフラグ</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>送信</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>詳細...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>OSD回復優先度</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>優先度</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>優先度値のカスタマイズ</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>このフィールドは必須です。</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>入力された値は大きすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>より大きい値を入力することはできません。
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>入力された値は小さすぎます。
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>より小さい値を入力することはできません。
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>再重みづけOSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>値は0と1の間である必要があります。</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>再重みづけ</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>スクラブ
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Deep } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>スクラブをOSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>に
+適用しようとしています。
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {deep } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>OSDリスト</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>続行した場合は、
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>は
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>とマークされます。
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>このOSDを安全に破棄することはできません。</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>続行した場合は、
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>は
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>されます。
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>詳細</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>値</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>閉じる</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>削除</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>ヘルス</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>統計情報</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>NFS Ganeshaの管理機能を設定および有効化
+する方法に関する
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ドキュメント
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>を参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>クライアント</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>任意のクライアントからアクセスできます</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>アドレス</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>必須フィールド</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>1つ以上のカンマ区切り値を含んでいる必要があります</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>例:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>アクセスタイプ</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>スカッシュ</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>クライアントの追加</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>読み込んでいます...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- 使用可能なクラスタがありません --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- クラスタを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>デーモンの追加</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>ストレージバックエンド</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- 使用可能なデータプールがありません --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- ストレージバックエンドを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>オブジェクトゲートウェイユーザ</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- 使用可能なユーザがありません --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- オブジェクトゲートウェイユーザを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFSユーザID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- 使用可能なクライアントがありません --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- cephxクライアントを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>CephFS名</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>セキュリティラベル</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>セキュリティラベルの有効化</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFSパス</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>パスは「/」で始まる必要があり、その後ろに1つの単語を配置できます</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>新しいディレクトリが作成されます</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>パス</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>パスは単一の「/」または1つの単語である必要があります</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>新しいバケットが作成されます</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFSプロトコル</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFSタグ</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>マウントの代替アクセス(先頭に「/」があってはいけません)。
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>クライアントはサブディレクトリをマウントできません(たとえば、[タグ] = fooの場合は、クライアントはfoo/bazをマウントできません)。</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>異なる[タグ]オプションを使用することで、同じパスを複数回エクスポートできます。</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>疑似</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>この
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>エクスポートが
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>疑似FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>内で
+占有する位置(この位置は一意である必要があります)。
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>異なる[疑似]オプションを使用することで、同じパスを複数回エクスポートできます。</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- 使用可能なアクセスタイプがありません --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- アクセスタイプを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- 使用可能なスカッシュがありません --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- 実行されるユーザIDスカッシュ操作の種類を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>トランスポートプロトコル</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Cephにようこそ!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>ユーザ名は必須です</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>パスワードは必須です</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>ログイン</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>このユーザはCephに存在しません。</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>[ログイン]ページ
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>に戻ります。ログインを再試行すると、Identity Providerからログアウトされます。
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>禁止</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>検索していた内容を表示することは許可されていません。</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>検索していた内容が見つかりませんでした</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>すべて削除</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>最近の通知</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>バックグラウンドタスクがありません。</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>バックグラウンドタスク</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>ヘルプ</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>ドキュメント</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>バージョン情報</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>ダッシュボード設定</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>ユーザ管理</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>ログイン済みユーザ</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+としてサインイン済み
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>サインアウト</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>名前...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>選択された名前はすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>説明...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>許可</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>役割</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>ユーザ名</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>パスワード</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>パスワードの確認入力</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>確認入力されたパスワードがパスワードと一致しません。</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>氏名</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>電子メール</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>無効な電子メールです。</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>自身のユーザから「user read / update」という許可を削除しようとしています。</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>続行した場合は、どのユーザの役割も追加および削除できなくなります。</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>続行してもよろしいですか?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>パフォーマンスカウンタを使用できません</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>属性(OSDマップ)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>メタデータを使用できません</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>メタデータ</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>パフォーマンスカウンタ</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>ヒストグラムを使用できません:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>書き込み回数</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>読み取り回数</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>ヒストグラム</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>パフォーマンスの詳細</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>現行値</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>タイプ</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>最小</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>最大</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>フラグ</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>ソース</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>レベル</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>実行時に更新できます(編集可能)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>タグ</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>列挙値</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>関連項目</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>クラスタのステータス</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>マネージャデーモン</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>オブジェクトゲートウェイ</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>メタデータサーバ</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSIゲートウェイ</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>クライアントのIOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>クライアントのスループット</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>クライアントの読み取り/書き込み</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>回復スループット</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>スクラブ</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>パフォーマンス</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>未フォーマット時の容量</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>オブジェクト数</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>OSDあたりの配置グループ数</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>配置グループのステータス</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>容量</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>詳細については、「
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ログ
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>」を参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>ランク</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>クライアント数:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>イメージをごみ箱に移動する</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>をごみ箱に移動するには、
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>[イメージの移動]
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>をクリックします。希望に応じて、失効日を選択できます。
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>保護の失効日</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>保護されていません</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>日付の形式が正しくありません。「YYYY-MM-DD HH:mm:ss」という形式を使用してください。</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>保護はすでに失効しています。将来の日付を選択するか、日付を空白のままにしてください。</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>イメージの移動</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>概要</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>ターゲット</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>検出認証</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>ユーザ</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>ユーザ名は8~64文字の長さである必要があり、
+英字、「.」、「@」、「-」、「_」、または「:」のみで構成される必要があります。</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>相互ユーザ</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>相互パスワード</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>iSCSIターゲットの管理機能を設定および有効化
+する方法に関する
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ドキュメント
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>を参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>取得可能な情報:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>使用可能なiSCSIターゲットがありません</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>が有効になっているRBDイメージのみに使用できます
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>プール</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>データプール</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>作成済み</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>サイズ</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>オブジェクトサイズ</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>機能</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>プロビジョニング済み</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>なし</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>プロビジョニング済み合計</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>ストライピング単位</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>ストライピング数</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>親</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>ブロック名のプレフィックス</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>順番</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>スナップショット</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>イメージ</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>この設定はグローバル値よりも優先されます</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>グローバル</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>これはグローバル値です。このイメージについて、このオプションの値は設定されていません。</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>「/」と「@」は使用できません。</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- 使用可能なrbdプールがありません --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- プールを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>専用のデータプールを使用してください</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>データプール</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>RBDのオブジェクトデータを保管するための専用プール</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>例: 10GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>サイズを大きくする必要があります。</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>詳細</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>ストライピング</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>ストライプ単位</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- ストライプ単位を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>ストライプ数が定義されているため、このフィールドは必須です。</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>ストライプ単位がオブジェクトサイズより大きいです。</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>ストライプ数</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>ストライプ単位が定義されているため、このフィールドは必須です。</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>ストライプ数は0より大きい必要があります。</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBDスナップショット
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>スナップショット
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>保護済み</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>未保護</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>ロールバックしようとしています</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>ごみ箱を空にする</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>空にするには、1つまたはすべてのイメージを選択してクリックします</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>プール:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>プール名...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>すべて</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>イメージの復元</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>復元するには</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>イメージの新しい名前を入力してクリックします</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>新しい名前</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>失効日</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>保護の終了日</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>このイメージは
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>まで保護されます。
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>ごみ箱</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>iSCSIトポロジ</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>通常はこれらのパラメータをデフォルト値から変更する必要はありません。</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>設定</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>バックストア</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>確認</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>詳細設定</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>ターゲットIQN</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQNのパターンが正しくありません。</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQNは「iqn.$year-$month.$reversedAddress:$definedName」という形式で表記されます。</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>例: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>詳細情報</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>このターゲットの詳細設定は変更されています。</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>ポータル</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>少なくとも
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/>台のゲートウェイが必要です。
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>ポータルの追加</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>このイメージの設定は変更されています。</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>イメージの追加</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL認証</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>イニシエータ</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>イニシエータ</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>クライアントIQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>イニシエータIQNは一意である必要があります。</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>ユーザ名は8~64文字の長さである必要があり、
+英字、「.」、「@」、「-」、「_」、または「:」のみで構成される必要があります。</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>イニシエータはいずれかのグループに属します。イメージはそのグループ内で設定されます。</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>アイテムが追加されていません。</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>イニシエータの追加</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>グループ</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>グループ</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>グループの追加</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>RBD設定</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>ローカル設定値を削除します。親設定値が継承されて代わりに使用されます。</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>最小値は0です</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>問題</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>同期中</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>準備完了</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>プールのミラーモードの編集</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>プール
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>のミラーモードを編集するには、
+リストから新しいモードを選択して、
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>[更新]
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>をクリックします。
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>モード</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>ミラーを無効にする前に、ピアクラスタを削除する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+プールのミラーピア
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>プール
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>
+のプールミラーピア属性、および
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>[送信]
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>をクリックします。
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>クラスタ名</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>このクラスタ名は無効です。</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>このCephX IDは無効です。</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>モニターアドレス</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>カンマ区切りアドレス...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>この警告アドレスは無効です。</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephXキー</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64エンコード化済みキー...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>CephXキーはbase64でエンコードされている必要があります。</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>プールリスト</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>名前は英数字、ダッシュ、および下線のみで構成される必要があります。</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>選択されたイレイジャコードプロファイル名はすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>プラグイン</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>データチャンク(k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>2以上である必要があります。</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>コーディングチャンク(m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>1以上である必要があります。</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>耐久性推定子(c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>地域(l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Crush障害ドメイン</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Crush地域</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>なし</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>技法</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>パケットサイズ</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Crushルート</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Crushデバイスクラス</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>任意</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>ディレクトリ</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>選択されたCephプール名はすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>プールタイプ</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- プールタイプを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>配置グループ</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>少なくとも1つの配置グループが必要です。</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>ご使用のクラスタはこれだけ多数の配置グループを処理できません。必要な配置グループの数を再計算してください。</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>計算のヘルプ</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>現在の配置グループ設定は自動的に計算されたため、
+送信前に、これらの値がニーズに合っていることを確認してください。</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Crushルールセット</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Crushルールを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Crushルール</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Crushステップ</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>現在のクラスタ内のOSD数はこのルールで要求される最小OSD数を下回っているため、
+このルールを現在のクラスタで使用することはできません。</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>複製されたサイズ</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>最小:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>最大:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>指定されたサイズは範囲外です。
+有効な値の範囲は
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>~
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/>です。
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>イレイジャコードプロファイル</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- 使用可能なイレイジャコードプロファイルがありません --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- イレイジャコードプロファイルを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>ECの上書き</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>アプリケーション</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>圧縮</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>アルゴリズム</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- 使用可能なイレイジャ圧縮アルゴリズムがありません --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>最小blobサイズ</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>例: 128KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>値は0より大きい必要があります</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>最大blobサイズ</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>例: 512KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>値は最小blobサイズより大きい必要があります</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>率</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>圧縮率</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>値は0.0~1.0の間である必要があります</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>名前に「/」が含まれたRBDプールを作成することはできません。</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>名前を変更するか、アプリケーションリストから「rbd」を削除してください。</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>キャッシュ層の詳細</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>オブジェクトゲートウェイの管理機能を設定および有効化
+する方法に関する
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>ドキュメント
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>を参照してください。
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>デーモンリスト</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>パフォーマンスカウンタ</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>バケットデータを読み込んでいます...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>バケットデータを読み込めませんでした。</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>Id</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>この値は無効です。</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>所有者</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- ユーザを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>インデックスタイプ</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>配置ルール</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>マーカー</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>最大マーカー</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>バージョン</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>マスタバージョン</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>変更時間</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>ゾーングループ</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>バケットクォータ</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>有効化済み</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>最大サイズ</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>無制限</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>最大オブジェクト数</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- ユーザ名を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>キーの自動生成</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>アクセスキー</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>秘密キー</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>電子メールアドレス</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>中断済み</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>システム</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {No} 1 {Yes} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>最大バケット数</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>サブユーザ</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>機能</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>ユーザクォータ</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>表示</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>キー</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- タイプを選択してください --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>許可</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- 許可を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>サブユーザ</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>選択されたサブユーザIDはすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>読み取り、書き込み</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>フル</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>スウィフトキー</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>秘密の自動生成</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>ユーザデータを読み込んでいます...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>ユーザデータを読み込めませんでした。</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>選択されたユーザIDはすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>これは有効な電子メールアドレスではありません。</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>選択された電子メールアドレスはすでに使用されています。</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>最大バケット数</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>0以上の値を入力する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3キー</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>サブユーザがいません。</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>キーがありません。</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>スウィフト</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>機能がありません。</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>無制限のサイズ</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>最大サイズ</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>無制限のオブジェクト数</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>最大オブジェクト数</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>現在</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>検出認証を更新しました</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>使用可能なポータルはありません。</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>使用可能なイメージはありません。</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>使用可能なイメージはありません。ターゲットにイメージを追加したことを確認してください。</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>使用可能なイニシエータはありません。ターゲットにイニシエータを追加したことを確認してください。</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>ターゲット</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>状態</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>読み取りバイト数</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>書き込みバイト数</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>読み取り操作数</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>書き込み操作数</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>次の日付以降のA/O</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>インスタンス</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>ホスト名</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>問題</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>進捗</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>無効化済み</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>モードの編集</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>ピアの追加</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>ピアの編集</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>ピアの削除</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>リーダー</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>#ローカル</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>#リモート</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>ミラーピア</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>キー</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>ディープフラット化</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>階層化</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>排他ロック</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>オブジェクトマップ(排他ロックが必要)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>ジャーナリング(排他ロックが必要)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>RBDスナップショットのロールバック</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>ロールバック</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>RBDスナップショット</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>削除日時</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>id</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>タイプ</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>状態</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>バージョン</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>ホスト</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>ルート</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>ランク</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>デーモン</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>アクティビティ</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>dエントリ</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>iノード</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>使用量</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>スタンバイデーモン</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>この値は実行時に更新できます。</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>デーモン/クライアントはこの値をモニター設定データベースから取得しません。
+このオプションを「ceph config set ...」を通じて設定することは禁止されています。
+このオプションは、ceph.confまたはコマンドラインを通じて
+設定する必要があります。</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>オプションはデーモン始動時のみに有効になります。</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>オプションはクラスタの作成のみに適用されます。</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>オプションはデーモンの作成のみに適用されます。</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>設定オプション
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>サービス</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>現行値</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>編集可能</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>モジュール「
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>」のオプションを更新しました。
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>有効化</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>無効化</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>再接続していますので、しばらくお待ちください...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>パブリックアドレス</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>セッションの開始</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>インなし</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>以前にアウトとしてマークされたOSDは、それらの始動時にインとしてマークされることはありません</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>アウトなし</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSDは、設定済みの間隔が経過した後に自動的にアウトとしてマークされます</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>アップなし</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSDを始動することは許可されていません</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>ダウンなし</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>OSDの障害レポートは無視されているため、OSDはモニターによってダウンとしてマークされません</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>一時停止</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>読み取りと書き込みを一時停止します</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>スクラブなし</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>スクラブ処理は無効化されています</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>ディープスクラブなし</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>ディープスクラブ処理は無効化されています</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>バックフィルなし</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>配置グループのバックフィルは中断されています</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>回復なし</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>配置グループの回復は中断されています</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>ビット単位のソート</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>ビット単位のソートを使用する</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>消去されたスナップディレクトリ</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSDによってスナップセットが変換されました</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>回復の削除</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>ピアリングの代わりに回復時に削除が実行されました</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>配置グループログのハード制限</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>配置グループログ長のハード制限を適用します</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>OSDフラグを更新しました</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>アウト</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>イン</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>ダウン</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>マーク</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>喪失したOSD</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>喪失としてマーク済み</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>消去</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>消去済み</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>破棄</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>破棄済み</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>配置グループ数</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>読み取りバイト数</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>書き込みバイト数</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>読み取り操作数</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>書き込み操作数</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>をマーク
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>をマーク
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>最大バックフィル数</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>回復最大アクティブ</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>回復最大単一始動</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>回復スリープ</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>カスタム</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>OSDの回復速度優先度「
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>」を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/>は次のOSDで初期化されました:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>ジョブ</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>重大度</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>始動済み</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>更新済み</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>使用済み</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>使用可能</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>クリーン</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>動作中</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>警告</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>不明</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>アップ</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>ファイルシステムがありません</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>アクティブ</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>スタンバイ</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>なし</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>アクティブデーモン</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>定数</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>NFS Ganeshaサービスが設定されていません。</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>トランスポート</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFSユーザ</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>CephFSファイルシステム</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(グローバル設定から継承)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>グローバル設定から継承されました</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- 実行されるユーザIDスカッシュ操作を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>使用可能なデーモンがありません。</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>キャッシュモード</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>退去までの最小経過時間</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>消去までの最小経過時間</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>ターゲットの最大バイト数</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>ターゲットの最大オブジェクト数</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>アプリケーションは追加されていません</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>アプリケーション数の上限に達しました</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>1つのプールは最大で4つのアプリケーション定義しか保有できません。</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>使用可能な文字「_a-zA-Z0-9」</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>最大長は128文字です</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>アプリケーションのフィルタリングまたは追加</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>アプリケーションの追加</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>イレイジャコードプロファイル</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>レプリカサイズ</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>最後の変更</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>イレイジャコード化済みプロファイル</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Crushルールセット</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>書き込みバイト数</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>バケット</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>オブジェクトゲートウェイバケット「
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>」を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>オブジェクトゲートウェイバケット「
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>」を作成しました
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>バケット数</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>ユーザ</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>オブジェクトゲートウェイユーザ「
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>」を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>オブジェクトゲートウェイユーザ「
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>」を作成しました
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>ユーザ数</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>範囲</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>読み取り</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>作成</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>役割「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」を作成しました
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>役割「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>システム役割</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>役割「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」を削除しました
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>ユーザ「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」を作成しました
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>ユーザの更新</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>続行</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>このユーザの役割が変更されたため、このユーザは自動的にログアウトされました。</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>ユーザ「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」を更新しました
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>ユーザ「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」を削除しました
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>ユーザ「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」を削除できませんでした
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>現在このユーザは「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」としてログインしています。
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>各オブジェクトは複数のデータチャンクパートに分割されており、それぞれのパートは異なるOSDに保管されています。</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>各オブジェクトのコーディングチャンクを計算して、これらのチャンクを別々のOSDに保管します。
+コーディングチャンクの数は、データを失うことなくダウン状態になることができるOSDの数でもあります。</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>jerasureプラグインは最も汎用的で柔軟性の高いプラグインです。
+このプラグインは、Cephイレイジャコード化済みプール用のデフォルトでもあります。</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>さらに柔軟性の高い技法はreed_sol_vanです。kとmを
+設定するだけで十分です。
+cauchy_good技法はより高速となり得ますが、パケットサイズを慎重に選択する必要があります。
+reed_sol_r6_op、liberation、blaum_roth、liber8tionはすべて、
+m=2を使用した設定のみが可能という意味でRAID6と同等です。</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>エンコードはバイトサイズのパケット群に対して同時に実行されます。
+適切なパケットサイズを選択することは困難です。
+jerasureのドキュメントにはこのトピックに関する詳細な情報が記載されています。</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>jerasureプラグインを使用すると、イレイジャコード化済みオブジェクトが複数のOSDに保管されている場合は、
+1つのOSDの喪失から回復するには、他のすべてのOSDからの読み取りが必要になります。
+たとえば、k=8およびm=4を使用してjerasureが設定されている場合は、1つのOSDが失われた場合、
+修復のためには他の11個のOSDからの読み取りが必要になります。
+
+lrcイレイジャコードプラグインは、これより少ないOSDを使用した回復を可能にするために、
+ローカルパリティチャンクを作成します。たとえば、lrcがk=8、m=4、およびl=4を使用して設定されている場合は、
+lrcは、4つのOSDごとに1つの追加パリティチャンクを作成します。1つのOSDが失われた場合は、
+11個の代わりに4つのOSDのみを使用してそのOSDを回復できます。</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>コーディングチャンクとデータチャンクをサイズ地域の複数セットにグループ分けします。
+たとえば、k=4およびm=2の場合に、[地域]=3の場合は、3つのチャンクからなるグループが2つ作成されます。
+各セットは、別のセットからチャンクを読み取ることなく回復できます。</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>1によって定義されたチャンクの各セットが保管されるCrushバケットのタイプ。
+たとえば、このバケットタイプがラックに設定されている場合は、1のチャンクの各グループは異なるラックに配置されます。
+このバケットタイプを使用して、「ラックの選択」ステップなどのCRUSHルールステップが作成されます。
+このバケットタイプが設定されていない場合は、このようなグループ分けは行われません。</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>isaプラグインはISAライブラリをカプセル化します。このプラグインはIntelプロセッサ上のみで動作します。</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>ISAプラグインは2つのリードソロモン形式で提供されています。reed_sol_vanが設定されている場合は、Vandermondeであり、cauchyが設定されている場合は、Cauchyです。</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>shecプラグインは複数のSHECライブラリをカプセル化します。
+このプラグインを使用すると、cephはリードソロモンコードより効率的にデータを回復できます。</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>それぞれが各データチャンクを各自の計算範囲内に含んでいるパリティチャンクの数。
+この数は、耐久性推定子として使用されます。
+たとえば、c=2の場合は、データを失うことなく2つのOSDがダウン状態になることができます。</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>CRUSHルールの最初のステップ(「デフォルトの使用」ステップなど)用に
+使用されるCrushバケットの名前。</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>同じ障害ドメインの単一バケット内に2つのチャンクが配置されることを防止します。
+たとえば、障害ドメインがホストである場合は、2つのチャンクが同じホストに保管されることはありません。
+これを使用して、「リーフホストの選択」ステップなどのCRUSHルールステップが作成されます。</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>CRUSHマップ内でCrushデバイスクラス名を使用して、配置先を特定クラス(ssdやhddなど)のデバイスのみに制限します。</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>イレイジャコードプラグインの読み込み元となるディレクトリ名を設定します。</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>すべての操作を許可します</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>サーバに変更を加えない操作のみを許可します</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>読み取り/書き込み操作を許可しませんが、他のすべての操作を許可します</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>読み取り/書き込み操作、およびファイル属性やディレクトリ内容を変更するどの操作も許可しません</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>アクセスを一切許可しません</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- 優先度を選択してください --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>低</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>高</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>直前の5分間</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>直前の15分間</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>直前の30分間</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>直前の1時間(デフォルト)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>直前の3時間</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>直前の6時間</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>直前の12時間</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>直前の24時間</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>昨日</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>本日</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>本日の現時点まで</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>一昨日</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>過去2日間</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>先週の同じ曜日</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>前週</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>今週</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>今週の現時点まで</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>過去7日間</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>前月</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>今月</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>今月の現時点まで</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>過去30日間</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>過去90日間</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>過去6カ月</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>過去1年間</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>前年</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>今年</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>今年の現時点まで</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>過去2年間</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>過去5年間</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>情報</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>アイテムが選択されていません。</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>アイテムを選択解除して再選択してください</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>選択の上限に達しました</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>タグのフィルタリング</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>バッジの追加</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>使用可能なアイテムはありません。</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>追加</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>複製</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>コピー</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>ディープスクラブ</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>破棄</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>フラット化</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>ダウンとしてマーク</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>インとしてマーク</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>喪失としてマーク</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>アウトとしてマーク</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>保護</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>名前の変更</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>復元</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>ごみ箱に移動する</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>保護解除</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>削除済み</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>複製済み</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>コピー済み</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>はい</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>いいえ</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>サービス品質</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS制限</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>希望する秒あたり入出力バイト数の上限。</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS制限</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>希望する秒あたり入出力操作数の上限。</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>読み取りBPS制限</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>希望する秒あたり読み取りバイト数の上限。</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>読み取りIOPS制限</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>希望する秒あたり読み取り操作数の上限。</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>書き込みBPS制限</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>希望する秒あたり書き込みバイト数の上限。</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>書き込みIOPS制限</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>希望する秒あたり書き込み操作数の上限。</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPSバースト</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>希望する入出力バイト数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPSバースト</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>希望する入出力操作数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>読み取りBPSバースト</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>希望する読み取りバイト数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>読み取りIOPSバースト</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>希望する読み取り操作数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>書き込みBPSバースト</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>希望する書き込みバイト数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>書き込みIOPSバースト</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>希望する書き込み操作数のバースト上限。</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>を実行できませんでした
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>実行中</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>実行</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>実行済み</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>不明なタスク</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>作成中</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>作成</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>更新中</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>削除中</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>削除</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBDスナップショット「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>プール「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」のミラーモード
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>プール「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」のミラーピア
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>この名前は
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>によってすでに使用されています。
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>この名前は
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>によってすでに使用されています。
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>この名前は
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>によってすでに使用されています。
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>にはスナップショットが含まれています。
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>複製中</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>複製</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>のスナップショットは保護される必要があります。
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>コピー中</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>コピー</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>フラット化中</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>フラット化</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>フラット化済み</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>この名前は
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>によってすでに使用されています。
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>は子イメージを含んでいるため保護解除できません。
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>は保護されているため削除できません。
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>ロールバック中</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>ロールバック</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>ロールバック済み</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>移動中</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>移動</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>移動済み</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>イメージ「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」をごみ箱に
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>イメージが見つかりませんでした。</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>復元中</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>復元</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>復元済み</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>イメージ「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」を「
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>」に
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>イメージ名「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」はすでに使用されています。
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>イメージ「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>消去中</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>消去</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>消去済み</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>すべてのプール</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>からのイメージ
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>ピアを含んでいるためミラーリングを無効化できません。</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>プール「
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>イレイジャコードプロファイル「
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>ターゲット「
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.ko-KR.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.ko-KR.xlf
new file mode 100644
index 00000000..0c3f0d85
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.ko-KR.xlf
@@ -0,0 +1,4340 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="ko-KR">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>네비게이션 전환</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>현황판</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>클러스터</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>호스트들</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>모니터들</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD들</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>설정</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>크러쉬맵</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>메니저 모듈들</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>로그들</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>경고들</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>풀들</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>블럭</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>이미지들</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>미러링</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>파일시스템들</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>오브젝트게이트웨이</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>데몬들</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>사용자</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>버킷들</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>뒤로</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>언어선택</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>패널 데이타 로딩 중...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>그라파나 타임 픽커</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>설정 초기화</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>데이타 로딩 실폐</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>선택된</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>발견된</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>전체</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>편집</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>이름</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>설명</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>자세한 설명</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>기본값</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>데모 기본값</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>서비스들</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>값들</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>입력값이 너무 큽니다! 그것은
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/> 보다 커야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>입력된 값이 너무 작습니다.! 그것은
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/> 작아야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>저장하기</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>크러쉬맵 보기</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>호스트 목록들</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>통합 성능치</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>항목들을 찾을 수 없음</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>클러스터 로그들</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>감사 로그들</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>설정 로딩 중</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>설정을 로드할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>관리모듈 편집하기</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>입력된 값이 유효한 UUID가 아닙니다, 예.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>입력된 값은 유효한 IP주소 여야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>이 필드는 필수적입니다.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>입력값이 너무 큽니다! 그것은 반드시
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/> 작거나 같아야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>입력된 값이 너무 작습니다! 그것은
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>보다 크거나 같아야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>입력된 값은 적어도 하나의 숫자를 필요로 합니다.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>입력 된 값은 숫자 또는 십진수여야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>갱신</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>상태</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>클러스터 ID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>몬맵 변경시간</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>몬맵 변경번호</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>정족수 일치번호</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>정족수 모니터상태</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>요구되는 일치번호</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>요구되는 모니터상태</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>정족수에 포함</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>정족수 미포함</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>취소</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>선택된
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>로
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> 을 하는 것이 확실합니까?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>예, 확실합니다.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>클러스터-수준의 OSD 플레그들</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>제출</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>자세한 옵션...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>OSD 복구 우선순위</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>우선순위</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>우선 순위 값 맞춤 설정</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>이 필드는 요구됩니다!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>입력된 값이 너무 큽니다! 그것은
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>보다 크지 않아야 합니다..
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>입력된 값이 너무 작습니다! 그것은
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>보다 작아야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>OSD 재-조정</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>값은 0과 1사이어야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>재-조정</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD들
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> 청소하기
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, 선택, 1 {깊이 } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>을 청소하기 위해, 당신은
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>을 적용하려고 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, 선택, 1 {깊이 } }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>OSD 목록들</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>계속진행하면
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 는
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 로 표시됩니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>OSD는 파괴하기에 안전하지 않습니다!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>계속진행하면
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 는
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 가 될 것입니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>세부설명</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>값</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>닫기</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>삭제</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>건강상태</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>통계들</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>클라이언트들</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>모든 클라이언트 접근가능</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>주소들</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>필수 입력란</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>반드시 하나 이상의 쉼표로 구분 된 값을 포함해야 함</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>예를들면:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>접근형태</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>클라이언트들 추가</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>로딩중...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- 사용가능 클러스터 없음 --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- 클러스터 선택 --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>데몬 추가하기</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>스토리지 백엔드</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- 이용가능한 데이타풀 없음 --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- 스토리지 백엔드 선택 --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>객체 게이트웨이 사용자</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- 사용가능한 사용자들 없음 --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- 객체 게이트웨이 사용자 선택 --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFS 사용자 ID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- 사용가능한 클라이언트 없음 --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- cephx 클라이언트 선택 --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>CephFS 이름</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>보안 레이블</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>보안 레이블 사용</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFS 경로</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>경로는 '/'로 시작해야하며 그 뒤에 단어가 올 수 있습니다</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>새로운 디렉토리가 만들어 질 것입니다</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>경로</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>경로는 하나의 '/' 또는 하나의 단어 일 수 있습니다</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>새로운 버킷이 만들어 질 것입니다</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFS 프로토콜</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFS 태크</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 마운트들을 위한 대체 접근 (/가 앞에 와야 함).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>클라이언트는 하위 디렉토리를 마운트 할 수 없습니다 (즉, Tag = foo 인 경우 클라이언트가 foo / baz를 마운트하지 못할 수 있습니다).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>다른 태그 옵션을 사용하면 같은 경로를 여러 번 내보낼 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>다른 Pseudo 옵션을 사용하면 동일한 경로를 여러 번 내보낼 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- 사용가능한 접근형태 없음 --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- 접근형태 선택 --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- 사용가능한 squash 없음 --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- 어떤 종류의 사용자 ID 스쿼시가 수행되는지 선택하세요 --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>전송프로토콜</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Ceph 사용을 환영합니다.</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>사용자이름이 필요합니다</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>암호가 필요합니다</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>로그인</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>미안합니다. 사용자가 Ceph내에 존재하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>금지됨</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>미안합니다. 당신이 요청할 것을 열람하는 것이 허락되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>미안합니다. 당신이 요청할 것을 찾을 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>모든 것 제거</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>최근 알림들</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>백그라운드 작업이 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>백그라운드 작업들</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>도움말</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>문서</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>대하여</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>대쉬보드 설정</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>사용자 관리</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>로그인된 사용자</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+로써 승인됨
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>로그아웃</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>이름...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>선택한 이름이 이미 사용중입니다.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>세부설명...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>권한들</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>역할들</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>사용자명</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>암호</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>암호 확인</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>암호 확인이 암호와 일치하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>전체 이름</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>전자우편</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>유효하지않는 전자우편.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>당신의 사용자로부터 "사용자 읽기 / 업데이트"권한을 제거하려고합니다.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>계속하면 모든 사용자에게 역할을 추가하거나 제거 할 수 없게됩니다.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>계속 진행하기를 원하십니까?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>성능 카운터들을 사용 할 수 없음</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>속성들 (OSD 맵)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>메타데이타 사용할 수 없음</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>메타데이타</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>성능 카운터</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>히스토그램을 사용할 수 없음:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>쓰기</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>읽기</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>히스토그램</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>성능 세부정보들</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>현재 값들</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>형태</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>최소</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>최대</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>플레그들</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>소스</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>수준</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>수행시간에 갱신가능함(편집가능)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>테크들</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>열거형 값들</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>추가로 더보기</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>클러스터 상태</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>관리자 데몬들</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>오브젝트 게이트웨이들</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>메타데이타 서버들</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI 게이트웨이들</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>클라이언트 IOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>클라이언트 처리량</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>클라이언트 읽기/쓰기</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>복구 처리량</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>세정작업</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>성능</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>원시용량</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>오브젝트들</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>OSD당 PG들</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>PG 상태들</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>용량</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> 더 자세한 내용을 위해
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>로그
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 보십시오.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>순위</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>클라이언트들:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>이미지를 휴지통에 이동</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>휴지통으로
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 옮기기 위해,
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>선택,
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 이미지 옮기세요. 선택적으로, 폐기날짜를 지정할 수 있습니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>보호가 만료되는 </target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>보호되지 않음</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>날짜 형식 오류. "YYYY-MM-DD HH:mm:ss" 형식으로 지정하세요.</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>보호기간이 이미 만료되었습니다. 더 미래의 날짜를 선택하거나 공란으로 남겨두세요.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>이미지 옮기기</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>개관</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>타겟들</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>인증 탐색</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>사용자</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>사용자이름은 8~64자까지 길이의 문자들을 가져야 하며 그리고, 오직 , '.', '@', '-', '_', ':' 등의 특수 문자들만을 포함가능합니다.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>공동 사용자</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>공통 암호</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>iSCSI 타겟들 관리 기능들을 설정하고 켜기위해서
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>문서
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 부분을 참조하시기 바랍니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>이용가능한 정보:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>iSCSI 타겟이 이용 불가능합니다.</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>오직
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 설정된 RBD 이미지들과 함께 사용가능합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>풀</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>데이타 풀</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>생성된</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>크기</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>객체크기</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>특징들</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>준비된</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>이용불가</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>준비된 총계</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>스트라이핑 단위</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>스트라이핑 횟수</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>상위</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>블록 이름 접두사</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>순서</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>스냅삿</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>이미지</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>이 설정은 전역 값을 덮어씁니다.</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>글로벌</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>이것은 전역 값입니다. 이 이미지에 대해 이 옵션의 값이 설정되지 않았습니다.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' 와 '@' 문자는 사용불가입니다.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- 이용가능한 rbd풀 없음 --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- 풀 선택 --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>전용 데이타 풀들을 사용하세요</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>데이타 풀</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>RBD의 객체-데이타를 저장하고 있는 전용 풀</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>예., 100 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>사이즈를 증가시켜야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>자세한</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>분산저장</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>분산저장단위</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- 분산저장단위 선택 --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>분산저장 개수가 정의되어 있으므로 이 필드는 필수입니다!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>분산저장단위는 객체크기보다 커야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>분산저장 갯수</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>분산저장 단위가 정의되어 있으므로 이 필드는 필수입니다!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>분산저장 갯수는 반드시 0보다 커야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD 스냅샷
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Rename} other {Create} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> 스냅샷
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>보호됨</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>보호안됨</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>롤백하려고 합니다.</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>휴지통 비우기</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>비우기 위해, 하나 또는 모든 이미지들을 선택하고 클릭하세요.</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>풀:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>풀 이름:</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>모든</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>이미지 복구하기</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>복구를 위해</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>이미지들의 새로운 이름을 입력하고 클릭하세요</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>새로운 이름</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>폐기될</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>까지 보호됨</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>이 이미지는
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>까지 보호됩니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>휴지통</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>iSCSI 토폴로지</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>기본설정 값들로 부터 인자를 변경하는 것은 일반적으로 필요하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>설정들</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>백스토어</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>확인</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>고급설정들</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>타겟 IQN</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN이 잘못된 패턴을 가지고 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQN은 다음과 같은 지정규칙이 있습니다.
+'iqn.$년-$달.$뒤집어진주소:$정의된이름'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Key
+예를들면: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>추가 정보</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>이 타겟은 고급설정들을 수정했습니다.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>포털</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>적어도
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> 게이트웨이들을 필요로 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>포털 추가</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>이 이미지는 설정들을 수정했습니다. </target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>이미지 추가</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL 인증</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>개시자들</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>개시자들</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>클라이언트 IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>개시자 IQN은 유일해야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>사용자이름은 8~64자까지 길이의 문자들을 가져야 하며 그리고, 오직 , '.', '@', '-', '_', ':' 등의 특수 문자들만 포함이 가능합니다.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>개시자는 하나의 그룹에 속해야 하고, 이미지는 그룹안에서 설정합니다.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>추가된 아이템들이 없음</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>게시자 추가</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>그룹들</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>그룹</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>그룹추가</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>RBD 설정들</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>로컬 구성 값을 제거하십시오. 상위 구성 값은 계승되고 대신 사용됩니다.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>최소값은 0입니다.</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>이슈들</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>동기화중</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>준비됨</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>풀 미러모드를 편집하기</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>풀을 위한 미러모드를 편집하기 위해 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, 그 목록으로 부터 새로운 모드를 선택하고, 클릭
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>갱신
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>양식</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>상대방 클러스터들은 미러를 단절하기 전에 반드시 제거되어야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ 풀 미러 상대방
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Edit} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> 풀
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 풀을 위하여 상대방 속성 미러하고,
+ 선택
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/> 제출
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> .
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>클러스터 이름</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>클러스터 이름이 유효하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX 아이디</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX 아이디...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>CephX 아이디가 유효하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>모니터 주소들</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>콤마로 분리된 주소들...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>모니터 주소가 유효하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX 키</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64로 인코딩 된 키 ...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>CephX 키는 반드시 base64로 인코드 되어야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>풀 목록들</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>이름은 영숫자, 대시 및 밑줄로만 구성 될 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>선택한 Erasure Code 프로파일 이름이 이미 사용 중입니다.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>플러그인</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>데이터 덩어리들 (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>반드시 2보다 크거나 같아야합니다.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>코딩 덩어리들 (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>반드시 1보다 크거나 같아야합니다.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>내구성 평가(c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>지역 (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>크러쉬 실패 도메인</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>크러쉬 지역</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>없음</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>기술</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>패킷크기</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>크러쉬루트</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>크러쉬 장치 클래스</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>모든</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>디렉토리</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>선택한 Ceph 풀이름이 이미 사용중입니다.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>풀 형태</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- 풀 형태 선택 --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>게재위치 그룹</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>적어도 하나의 게재위치 그룹이 필요함!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>클러스터는 이 많은 PG들를 처리 할 수 없습니다. 필요한 PG 양을 다시 계산하십시오.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>계산 도움말</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>현재의 PG들 설정들이 당신을 위해 계산되었습니다.
+당신은 제출하기 전에 당신의 요구에 적합한 값인지를 확인해야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>크러쉬 룰셋</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- 크러쉬 룰 선택 --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>크러쉬 룰</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>크러쉬 단계들</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>이 룰에 의하여 최소로 필요로 하는 OSD보다 적은 OSD를 가지고 있기때문에 이 룰은 현재의 클러스터에서는 사용할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>복제되는 크기</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>최소:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>최대:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>지정된 크기는 범위를 벗어났습니다.
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> 에서
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> 사이의 값이 유효합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Erasure Code 프로파일</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- 사용가능한 Erasure Code 프로파일 없음 --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- 한개의 Erasure Code 프로파일 선택 --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC 덮어쓰기</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>응용프로그램들</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>압축</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>알고리즘</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- 이용가능한 Erasure 압축알고리즘 없음 --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>최소 blob 크기</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>예) 128KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>값은 0보다 커야합니다</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>최대 blob 크기</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>예) 512KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>값은 최소 blob 크기보다 커야 합니다</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>비율</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>압축율</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>값은 0.0과 1.0 사이 여야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>이름에 '/'가 포함 된 RBD 풀을 생성 할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>이름을 변경하거나 응용 프로그램 목록에서 'rbd'를 제거하십시오.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>케쉬 계층들 상세설명들</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target> 오브젝트 게이트웨이 관리기능들을 어떻게 설정하고 켜는지에 대해
+문서
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>상의
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> 부분을 참조하기 바랍니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>데몬 목록들</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>성능 카운터</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>버킷데이타 적재 중</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>버킷 데이타를 적재할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>아이디</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>값이 유효하지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>소유자</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- 사용자 선택 --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>아이디</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>색인형식</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>위치규칙</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>표시</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>최대 마커</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>버젼</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>마스터 버젼</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>수정된 시간</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>제로그룹</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>버킷 할당량</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>이용가능</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>최대 크기</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>무제한</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>최대 객체들</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- 사용자명 선택 --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>자동생성된 키</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>접근 키</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>비밀 키</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>전자우편 주소</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>유예되다.</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>시스템</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, 선택, 0 {아니오} 1 {예} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>최대 버킷들</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>보조사용자들</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>능력치들</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>사용자 할당량</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>보기</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>키들</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- 형태 선택 --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>권한</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- 권한 선택 --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>보조사용자</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>선택한 보조사용자 아이디가 이미 사용중입니다.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>읽기, 쓰기</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>가득찬</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>스위프트 키</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>자동생선된 비밀</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>사용자 데이타 적재 중...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>사용자 데이타를 적재할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>선택된 사용자 아이디가 이미 사용 중입니다.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>이것은 유효한 전자우편 주소가 아닙니다.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>선택한 전자우편 주소가 이미 사용 중입니다.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>최대 버킷들</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>입력된 값은 반드시 0보다 커야 합니다.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3 키</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>보조사용자가 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>키가 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>스위프트</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>능력치가 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>무제한 크기</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>최대 크기</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>무제한 객체들</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>최대 객체들</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>현재</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>업데이트된 검색 인증</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>사용가능한 포탈들이 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>사용가능한 이미지들이 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>사용할 수있는 이미지가 없습니다. 대상에 이미지를 추가했는지 확인하십시오.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>사용할 수있는 개시자가 없습니다. 대상에 개시자를 추가했는지 확인하십시오.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>타겟</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>상태</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>읽은 바이트들</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>쓰기 바이트들</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>읽기 Ops</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>쓰기 Ops</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O 이래로</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>인스탄스</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>호스트이름</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>이슈</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>진행중</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>설정해제됨</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>편집모드</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>상대방 추가</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>상대방 편집</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>상대방 삭제</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>리더</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># 로컬</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># 원격</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>상대방 미러</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>키</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>딥 패턴</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>계층화</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>배타적인 락</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>오프젝트-맵(배타적인-락을 요구한다)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>저널링(배탁적인-락을 요구합니다.)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>RBD 스냅샷 롤백</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>롤백</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>RBD 스냅샷</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>삭제될 </target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>아이디</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>형태</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>상태</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>버젼</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>호스트</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>루트</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>순위</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>데몬</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>활동</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>덴트리들</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>아이노드들</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>사용량</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>대기 데몬들</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>이 값은 런타임에 업데이트 할 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>데몬들 / 클라이언트들은 모니터 구성 데이터베이스에서이 값을 가져 오지 않습니다. 'ceph config set ...'을 통해이 옵션을 설정하는 것은 허락되지 않습니다. 이 옵션은 ceph.conf 또는 명령 줄을 통해 구성해야합니다.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>옵션은 데몬 시작 중에 만 적용됩니다.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>옵션은 클러스터 생성할 때 만 영향을 줍니다.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>옵션은 데몬 생성할 때만 영향을줍니다.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>갱신된 설정 옵션
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>서비스</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>현재값</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>편집가능</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>모듈을 위해 갱신된 옵션들 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>사용가능</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>사용불가</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>재-접속 중, 기다려 주세요...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>공개 주소</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>열린 세션들</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>들어올 수 없는</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>이전에 마크 아웃 된 OSD는 시작시 다시 표시되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>나갈 수 없는</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSD들은 구성된 간격 후에는 자동으로 표시되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>살아나지 않는</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSD는 시작할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>죽일 수 없는</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>모니터가 OSD들의 다운을 표시하지 않도록 OSD 장애 보고서가 무시되고 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>멈출</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>읽기와 쓰기를 멈춤</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>스크러빙 않됨</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>스크러빙이 비활성화되었습니다.</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>딥 스크럽 안됨</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>딥 스크러빙이 비활성되었습니다.</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>백필 없음</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>PG들의 백필이 일시중지 되었습니다.</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>복구 않됨</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>PG들의 복구가 일시중지 되었습니다.</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>비트단위 정렬</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>비트단위 정렬을 사용하세요</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>완전삭제된 스냅디렉토리들</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD들이 변화된 스냅셋을 가지고 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>삭제된 복구들</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>피어링 대신 복구 중에 수행된 삭제물들</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>PG 로그 하드 한계</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>pg 로그 길이에 하드 한계를 넣으세요</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>갱신된 OSD 플래그들</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>아웃</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>인</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>다운</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>표시</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD 손실</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>손실 표시</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>완전제거</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>완전제거된</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>파괴됨</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>파괴된</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>파괴됨</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>읽은 바이트들</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>쓰기된 바이트들</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>읽기 ops</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>쓰기 ops</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>표시된 OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>표시된
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>최대 백필들</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>최대 활성화를 복구하기</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>최대 단일 시작을 복구하기</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>잠자기를 복구하기</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>커스텀</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>갱신된 OSD 복구 속도 우선순위 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> 은 다음의 OSD들 안에 초기화됨:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>일</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>심각도</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>시작된</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>갱신된</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>사용된</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>이용가능:</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>깨끗한</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>정상동작중</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>경고</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>알려지지 않은</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>정상</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>파일시스템들 없음</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>활성화된</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>대기중인</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>이용불가</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>활성화된 데몬들</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>정족수</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>NFS Ganesha 서비스가 설정되지 않음</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>전송</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFS 사용자</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>CephFS 파일시스템</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(전역 구성에서 상속)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>전역 구성에서 상속</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>- 어떤 종류의 사용자 ID 스쿼시가 수행되는지 선택 -</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>사용가능한 데몬이 없읍니다.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>캐쉬모드</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>최소 퇴거 연령</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>최소 플러시 연령</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>목표 최대 바이트들</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>목표 최대 오브젝트들</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>추가된 응용프로그램 없음</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>응용프로그램 한계에 도달함</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>하나의 풀은 오직 네개의 응용프로그램 정의들을 가질 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target> '_a-zA-Z0-9' 문자들만 허락됨</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>최대 길이는 128글자이다.</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>필터 또는 추가된 응용프로그램들</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>응용프로그램 추가</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>Erasure 코드 프로파일</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>복제 크기</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>마지막 변경</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Erasure 코드화된 프로파일</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>크러쉬 룰셋</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>쓰여진 바이트들</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>버킷</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>갱신된 오브젝트 게이트웨어 버킷 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>생성된 오브젝트 게이트웨이 버킷 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>버킷들</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>사용자</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>갱신된 오브젝트 게이트웨이 사용자 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>생성된 오브젝트 게이트웨이 사용자 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>사용자들</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>범위</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>읽기</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>만들기</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>생성된 롤 '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>갱신된 롤 '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>시스템 롤</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>삭제된 롤 '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>생성된 사용자 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>갱신된 사용자</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>계속</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>당신의 롤들이 변경되어 당신은 자동적으로 로그아웃되었습니다.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>갱신된 사용자 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>삭제된 사용자 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>사용자 삭제가 실폐된 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>당신은 현재 &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; 로 로그인되었습니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>각각의 오브젝트들은 데이타-청크 부분들로 분리되어, 각기 다른 OSD에 보관됩니다.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>각 오브젝트들에 대한 코딩 청크를 계산하고 서로 다른 OSD에 저장합니다.
+코딩된 청크의 수는 데이터 손실없이 작동중지 되어 질 수있는 OSD의 숫자이기도합니다.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Jerasure 플러그인은 가장 일반적이고 유연한 플러그인으로,
+또한 Ceph erasure 코드 풀의 기본값이기도합니다.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>보다 유연한 기술은 reed_sol_van입니다 : k와 m을 설정하면 충분합니다.
+cauchy_good 기술은 빠를 수 있지만 패킷크기를 주의깊게 선택해야합니다.
+reed_sol_r6_op, liberation, blaum_roth, liber8tion은 모두 m = 2로만 구성 할 수 있다는 점에서 RAID-6에 해당합니다.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>인코딩은 한번에 바이트들 크기의 패킷에 대해 수행됩니다. 올바른 패킷 크기를 선택하는 것은 어렵습니다. jerasure 문서에는이 주제에 대한 광범위한 정보가 들어 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>jerasure 플러그인을 사용하면 삭제 된 코딩 된 객체가 여러 OSD에 저장 될 때 하나의 OSD가 손실되는 것을 복구하려면 다른 모든 OSD를 읽어야합니다. 예를 들어 jerasure가 k = 8 및 m = 4로 구성되어있는 경우 하나의 OSD를 잃어 버리면 11 명의 다른 사람들이 수리해야합니다.
+lrc erasure code plugin은 적은 양의 OSD를 사용하여 복구 할 수 있도록 로컬 패리티 청크를 만듭니다. 예를 들어, lrc가 k = 8, m = 4 및 l = 4로 구성된 경우 4 개의 OSD마다 추가 패리티 덩어리가 생성됩니다. 단일 OSD가 손실되면 11 개 대신 4 개의 OSD만으로 복구 할 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>코딩 및 데이터 청크를 크기 지역 집합으로 그룹화합니다. 예를 들어, k = 4 및 m = 2에 대해, 지역성 = 3 일 때 두 개의 세 그룹이 생성됩니다. 각 세트는 다른 세트의 청크를 읽지 않고도 복구 될 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>l로 정의 된 각 청크 집합이 저장되는 크러시 버킷의 유형입니다. 예를 들어 랙으로 설정하면 l 개의 청크 그룹이 각각 다른 랙에 배치됩니다.
+랙 선택 단계와 같은 CRUSH 규칙 단계를 만드는 데 사용됩니다. 설정되어 있지 않으면, 그러한 그룹화가 수행되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>isa 플러그인은 ISA 라이브러리를 캡슐화합니다. 인텔 프로세서에서만 실행됩니다.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>ISA 플러그인은 두 개의 리드 솔로몬 형식으로 제공됩니다.
+reed_sol_van이 설정되면 Vandermonde, cauchy가 설정되면 Cauchy입니다.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>shec plugin은 다중 SHEC 라이브러리를 캡슐화합니다.
+           ceph가 리드 솔로몬 코드보다 더 효율적으로 데이터를 복구 할 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>각 데이터 청크가 계산 범위에 포함되는 패리티 청크의 수입니다. 이 수치는 내구성 측정기로 사용됩니다. 예를 들어, c = 2 인 경우 2 개의 OSD가 데이터 손실없이 중단 될 수 있습니다.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>CRUSH 규칙의 첫 번째 단계에 사용 된 크러시 버킷의 이름입니다. 예를 들어 step은 기본값을 취합니다.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>동일한 실패 도메인을 가진 양동이에 두 개의 청크가 없는지 확인하십시오. 예를 들어 실패 도메인이 호스트 인 경우 두 개의 청크가 동일한 호스트에 저장되지 않습니다. 이 단계는 리프 호스트를 선택하는 단계와 같은 CRUSH 규칙 단계를 만드는 데 사용됩니다.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>CRUSH지도에서 크래시 장치 클래스 이름을 사용하여 특정 클래스 (예 : ssd 또는 hdd)의 장치로 배치를 제한합니다.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>삭제 코드 플러그인이로드되는 디렉토리 이름을 설정하십시오.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>모든 작업들 허용</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>오직 서버를 수정하지 않는 작업들만 가능합니다.</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>읽기와 쓰기 작업은 허용되지 않지만, 그외 모든 작업이 가능합니다.</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>파일의 속성과 디렉토리 내용을 변경하는 읽기, 쓰기 또는 어떠한 작업은 허용되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>전혀 어떠한 접근도 허용되지 않습니다.</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- 우선순위 선택 --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>낮음</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>높음</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>마지막 5분</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>지난 15분</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>지난 30분</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>지난 1시간(기본)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>지난 3시간</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>지난 6시간</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>지난 12시간</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>지난 24시간</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>어제</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>오늘</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>오늘 지금까지</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>그저께</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>지난 2일</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>이번 주 마지막날</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>전주</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>이번주</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>이번주 지금까지</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>지난 7일</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>지난 달</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>이번 달</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>이번 달 지금까지</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>지난 30일</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>지난 90일</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>지난 6개월</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>지난 1년</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>전년도</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>금년도</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>금년 지금까지</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>지난 2년</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>지난 5년</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>정보</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>선택된 아이템 없음</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>다시 선택하기 위해 아이템 선택을 취소</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>선택 한계에 도달함</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>필터 테그들</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>베찌 추가</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>사용가능한 아이템 없음</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>추가</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>복제</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>복사</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>딥 스크럽</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>파괴됨</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>단조로움</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>다운 표시</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>인 표시</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>손실 표시</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>아웃 표시</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>보호</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>이름변경</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>복구</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>휴지통으로 옮기기</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>보호않됨</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>삭제돔</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>복제된</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>복사된</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>예</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>아니오</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>서비스 량</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS 한계</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>원하는 초당 IO 바이트 수 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS 제한</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>원하는 초당 IO 작업 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>읽기 BPS 제한</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>원하는 초당 읽기 바이스 수 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>읽기 IOPS 한도</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>원하는 초당 읽기 작업 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>쓰기 BPS 한도</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>원하는 초당 쓰기 바이트 수 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>쓰기 IOPS 제한</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>원하는 초당 쓰기 작업 제한입니다.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>원하는 버스트 IO 바이트 한도 입니다.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>원하는 IO 작업의 버스트 한계입니다.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>읽기 BPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>원하는 읽기 버스트 한계입니다.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>읽기 IOPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>원하는 읽기 작업의 버스트 한도입니다.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>쓰기 BPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>쓰기 바이트의 원하는 버스트 한도.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>쓰기 IOPS 버스트</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>쓰기 바이트의 원하는 버스트 한도.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/> 의 실폐
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>수행중</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>수행</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>수행된</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>알려지지 않는 작업</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>생성하는 중</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>생성</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>갱신 중</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>갱신</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>삭제 중</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>삭제</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD 스냅삿 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>풀 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 을 위한 미러모드
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>풀 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 미러 상대방
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>이름은
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>에 의하여 이미 사용되었습니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>이름은
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>에 의하여 이미 사용중입니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>이름이
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>에 의하여 이미 사용중입니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> 이 포함된 스냅삿들.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>복제중</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>복제</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>반드시
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>의 스냅삿은 보호되어야 합니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>복사중</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>복사</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>평평하게 하는 중</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>평평함</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>평평하게 됨</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>이름이
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>에 의하여 이미 사용 중.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>을 보호할 수 없습니다. 왜냐하면 그것은 자식 이미지들을 포함하고 있습니다,
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> 을 삭제할 수 없습니다. 왜냐하면 그것은 보호되어 있습니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>롤백 중</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>롤백</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>롤백됨</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>옮기는 중</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>옮기기</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>옮겨짐</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>이미지 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 버리기
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>이미지를 찾을 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>복구중</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>복구</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>복구됨</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>이미지 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 을 '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>' 로
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>이미지 이름 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 이 이미 사용중입니다.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>이미지 '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>완전삭제 중</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>완전삭제</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>완전삭제됨</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>모든 풀들</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>로 부터의 이미지들
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>피어가 포함되어 있기 때문에 미러링을 비활성화 할 수 없습니다.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>풀 '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>Erasure 코드 프로파일 '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>타깃 '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.pl-PL.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.pl-PL.xlf
new file mode 100644
index 00000000..b7d88262
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.pl-PL.xlf
@@ -0,0 +1,4360 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="pl-PL">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Rozwiń</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Pulpit</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Klaster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Hosty</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitory</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD-ki</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Konfiguracja</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSH mapa</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Zarządca modułów</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Logi</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Powiadomienia</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Pule</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Dostęp blokowy</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Obrazy</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Kopia lustrzana</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>Sieciowy system plików NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Systemy plików</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Dostęp obiektowy</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Demony</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Użytkownicy</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Wiadra</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Trwa pobieranie danych
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> dla
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Czekaj...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Wyświetlanie wcześniej buforowanych danych
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+dla
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Nie można załadować danych
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> dla
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Sprawdź proszę zdrowie klastra.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Wstecz</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Wybierz język</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Trwa ładowanie danych...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Sprawdź proszę
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentację
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>jak
+skonfigurować i uruchomić funkcje monitoringu.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Pulpit Grafany nie istnieje. Sprawdź proszę
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentację
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> jak
+dodaj pulpity do Grafany.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Wybór czasu Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Zresetuj ustawienia</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Błąd wczytywania danych.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>Wybrane</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>Znaleziono</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>Razem</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Edytuj</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nazwa</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Opis</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Długi opis</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Domyślna</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Domyślny demon</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Usługi</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Wartości</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>Podana wartość jest za wysoka. Nie może być większa niż
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>Podana wartość jest za mała. Nie może być mniejsza od
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Zapisz</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>widok CRUSH mapy</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Lista hostów</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Całkowita wydajność</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Nie znaleziono wejść</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Logi z klastra </target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Audyt logów</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Ładowanie konfiguracji.</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Nie można załadować konfiguracji</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Edytuj moduł zarządzania</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>Wpisana wartość nie jest poprawnym UUID, np. 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>Wpisana wartość musi być poprawnym adresem IP</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Pole jest wymagane.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>Podana wartość jest za wysoka! Musi być mniejsza bądź równa
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>Podana wartość jest za niska! Musi być większa bądź równa
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>Podana wartość musi być liczbą</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>Podana wartość musi być liczbą albo dziesiętną.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Zaktualizuj</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Status</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>Klaster ID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>Zmodyfikowana monmapa</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>epoka monmap</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>kworum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>kworum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>wymagany con</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>Wymagane mon </target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>W kworum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Nie w kworum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Anuluj</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Jesteś pewny, że chcesz
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>  wybrany
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Tak, jestem pewny.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Flagi OSD w całym klastrze</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Zatwierdź</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Zaawansowane...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Priorytet odzyskiwania OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Priorytet</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Dostosuj wartości priorytetowe</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>To pole jest wymagane.</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>Podana wartość jest za wysoka. Nie może być większa niż
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>Podana wartość jest za mała! Nie może być mniejsza od
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Ponowne ważenie OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>Wartość powinna być pomiędzy 0 a 1. </target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Ponowne ważenie</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>Szoruj
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> OSD-ki
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, wybierz, 1 {Głębokość} }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Zamierzasz zaaplikować
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> szorowanie na OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, wybierz, 1 {głębokość} }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Lista OSD-ków </target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Jeśli kontynuujesz
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> będzie zaznaczony
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> .
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>Nie można bezpiecznie zniszczyć tego OSD.</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>Jeśli kontyuujesz
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> będzie
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Szczegóły</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Wartość</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Zamknij</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Usuń</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Zdrowie</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Statystyki</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Sprawdź proszę
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentację
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 
+jak należy skonfigurować i uruchomić zarządzanie funkcjami NFS Ganeshy
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Klienci</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Każdy klient ma dostęp</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Adresy</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Obowiązkowe pole</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Musi zawierać jedną albo więcej ,rozdzielonych przecinkiem, wartości </target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Na przykład: </target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Typ dostępu</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Dodaj klientów </target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Ładowanie...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Brak dostępnego klastra -- </target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Wybierz klaster --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Dodaj demona</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Pamięć Podręczna</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Brak danych puli -- </target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Wybierz pamięć podręczną -- </target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Użytkownik dostępu obiektowego</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Brak dostępnych użytkowników -- </target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Wybierz użytkownika dostępu obiektowego -- </target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFS Użytkownik ID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Brak dostępnych klientów -- </target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Wybierz klienta cephx -- </target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nazwa CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Etykieta bezpieczeństwa</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Uruchom etykietę bezpieczeństwa</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Ścieżka CephFS </target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>Ścieżka powinna zaczynać się z '/' i następne może być słowo</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Nowy katalog będzie stworzony. </target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Ścieżka</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>Ścieżką może być tylko '/' albo słowo</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Nowe wiadro będzie stworzone </target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protokół NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Tag NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Alternatywny dostęp do
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> montuje ( nie musi mieć poprzedzającego '/' )
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Klient może nie montować podkatalogów ( np. jeśli Tag = foo, klient może nie montować foo/baz) </target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Używając różnych opcji Tagu, ta sama Ścieżka może być wyeksportowana kilka razy.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>Pozycja, którą
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> eksport zajmuje
+w
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (musi być unikatowa).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Używając różnych opcji Pseudo, ta sama Ścieżka może być wyeksportowana kilka razy.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Brak dostępnych typów dostępu --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Wybierz typ dostępu --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>- Brak squasha -</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- Wybierz, jakiego rodzaju identyfikacja użytkownika ma być przeprowadzana --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protokół Transportu </target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Witamy w Cephie! </target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Nazwa użytkownika jest wymagana</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Hasło jest wymagane.</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Zaloguj</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>Przepraszam, użytkownik nie istnieje w Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Powrót do
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Strony Logowania
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Zostaniesz wylogowany z Dostastcy Tożsamości , kiedy spróbujesz się zalgować.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Zakazany</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Przepraszam, nie masz dostępu do tego czego szukasz. </target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Przepraszam, nie możemy znaleźć tego czego szukasz.</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Usuń wszystko</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Ostatnie powiadomienia</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Brak zadań w tle.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Zagadnienia w tle </target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Pomoc</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Dokumentacja</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>Interfejs API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>O</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Ustawienia Pulpitu</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Zarządzanie użytkownikami</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Zalogowany użytkownik</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Zalogowany jako
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Wyloguj</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nazwa...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>Wybrana nazwa już jest użyta.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Opis...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Pozwolenia</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Role</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nazwa użytkownika</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Hasło</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Potwierdź hasło</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>Potwierdzające hasło nie pokrywa się z hasłem.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Pełne imię </target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>Email</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>Niepoprawny email.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Zamierzasz usunąć uprawnienia „odczytu / aktualizacji użytkownika” od własnego użytkownika.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Jeśli kontynuujesz, nie będziesz mógł dodawać albo usuwać role od użytkowników.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Jesteś pewny, że chcesz kontynuować? </target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Liczniki wydajności nie są dostępne</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Atrybuty (mapa OSD-ków)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Niedostępne metadane</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadane</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Licznik wydajności</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histogram niedostępny:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Pisze</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Czyta</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histogram</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Szczegóły wydajności</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Obecne wartości </target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Typ</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Min</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Max</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Flagi</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Źródło </target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Poziom</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Może być aktualizowany w czasie wykonywania (edytowalny)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Tagi</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Wartości enumerowane </target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Zobacz także </target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Status klastra</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Zarządzanie demonami</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Obiekty bram </target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Serwery metadanych</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>Bramy iSCSI</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>Klient IOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Przepustowość klienta</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Odczyt/Zapis klienta</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Przepustowość odzyskiwania</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Szoruj</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Wydajność</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Pojemność rzędu</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Obiekty</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>PG-y na OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Status PG</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Pojemność</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> zobacz
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>logi
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> , żeby mieć więcej szczegółów.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Szeregi</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Klienci:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Przenieś obraz do kosza</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Żeby przenieść
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> do kosza, kliknij
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Przenieś obraz
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Opcjonalnie, możesz wybrać datę ważności.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>Zabezpieczenie wygasa w </target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NIEZABEZPIECZONY </target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Zły format daty. Proszę używać "RRRR-MM-DD GG:mm:ss".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>Ochrona już wygasła. Proszę wybrać przyszłą datę lub zostawić pustą.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Przenieś obraz</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Przegląd</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Obiekty docelowe</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Uwierzytelnianie wykrywania</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Użytkownik</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Nazwy użytkowników muszą mieć długość od 8 do 64 znaków i
+mogą zawierać jedynie litery, '.', '@', '-', '_' lub ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Wspólny użytkownik </target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Wspólne hasło</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Sprawdź proszę
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> dokumentację
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 
+jak skonfigurować i uruchomić zarządzanie funkcjonalnościami obiektami docelowymi iSCSI
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Dostępne informacje: </target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>obiekty docelowe iSCSI niedostępne </target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Dostępne tylko dla obrazów RBD z
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/> szybką różnicą
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> włączone
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Pul</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Dane pula</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Utworzony</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Rozmiar</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Rozmiar obiektu</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Funkcje</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Zaopatrzony</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>Niedostępny</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Całkowite rezerwy</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Jednostka maskowana</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Licznik maskowania</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Rodzic</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Prefiks nazwy bloku</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Zamówienie</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Migawki</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Obraz</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>To ustawienie zastępuję wartość globalną.</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Globalne</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>To jest globalna wartość. Dla tego obrazu nie ustawiono żadnej wartości dla tej opcji.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' and '@' nie są dozwolone.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Brak dostępnych rbd puli -- </target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Wybierz pul --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Użyj dedykowanych danych pul </target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Dane pul</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Dedykowany pul, który przechowuje dane obiektowe z RBD</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>np. 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Musisz zwiększyć rozmiar.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Zaawansowane</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Maskowanie</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Jednostka pasków</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Wybierz jednostkę pasków -- </target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Pole jest wymagane, ponieważ licznik pasków jest zdefiniowany. </target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>Jednostka pasków jest większa niż rozmiar obiektu.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Licznik pasków </target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Pole jest wymagane, ponieważ jednostka pasków jest zdefiniowana! </target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>Licznik pasków musi być większy od 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> migawka RBD
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, wybierz, prawda {Zmień nazwe} inaczej{Utwórz} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Migawka
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>ZABEZPIECZONE</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NIEZABEZPIECZONY </target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Zaraz się wycofasz. </target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Usuń Śmieci</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Aby usunąć, wybierz jeden albo wszystkie obrazy i kliknij </target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Pul:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nazwa pula</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Wszystkie</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Przywróć obraz</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Przywróć</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>Wpisz nazwe nowego obrazu i kliknij. </target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Nowa Nazwa</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Wygasły w</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Zabezpieczony do</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Ten obraz jest chroniony do
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Kosz</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologia iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Zmiana tych parametrów z domyślnych wartości przeważnie nie jest potrzebna.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Ustawienia</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Tylny koniec przechowywania</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Potwierdź</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Ustawienia zaawansowane</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>Nazwa IQN obiektu docelowego iSCSI</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>Błędna składnia nazwy IQN.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQN ma następującą notację „iqn. $ Rok-$ miesiąc. $ odwróconyAdres: $ zdefiniowanaNazwa”</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Na przykład: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Więcej informacji</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Ten obiekt docelowy zmodyfikował zaawansowane ustawienia.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portale</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Wymagane są przynajmniej
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> bramy.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Dodaj portal</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Ten obraz zmodyfikował ustawienia. </target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Dodaj obraz.</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Uwierzytelnianie ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Inicjatory iSCSI</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Inicjator iSCSI</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>Klient IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>Inicjator IQN powinien być unikalny.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Nazwy użytkowników muszą mieć długość od 8 do 64 znaków i mogą zawierać jedynie litery, '.', '@', '-', '_' lub ':'.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>Inicjator iSCSI należą do grupy. Obrazy będą skonfigurowane w grupie. </target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Brak dodanych pozycji.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Dodaj inicjator iSCSI</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Grupy</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Grupa</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Dodaj grupę</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Konfiguracja RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Usuń wartość konfiguracji lokalnej. Wartość konfiguracji rodzica będzie odziedziczona i zostanie użyta zamiast tej.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>Minimalna wartość wynosi 0.</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Zagadnienia</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Synchronizacja</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Gotowy</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Tryb edycji lustrzanego pula</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Aby edytować tryb lustrzanydla pula
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, wybierz tryb z listy i kliknij
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Zaktualizuj
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Tryb</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Sparowany klaster musi być usunięty przed wyłączeniem lustra. </target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> sparowany pul lustrzany
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, wybierz, edytuj{Edytuj} inaczej {Dodaj} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> pul
+lustra sparowanych atrybutów dla pula
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> i kliknij
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Zatwierdź
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nazwa Klastra</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>Nazwa klastra jest niepoprawna </target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>ID CephX nie jest poprawne.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Adres monitora </target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Adresy rozdzielane przecinkami... </target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>Adres monitora nie jest poprawny.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>Klucz CephX</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Klucz zakodowany w Base64...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>Klucz CephX musi być zakodowany w Base64/</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Lista puli</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>Nazwa może składać się z alfanumerycznych znaków, kresek i podkreśleń.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>Wybrana nazwa profilu kodu kasowania jest już używana.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Wtyczka</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Ramka danych (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Musi być większa bądź równa 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Kodowanie kawałka (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Musi być większa bądź równa 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Estymator trwałości (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Lokalność (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Domena niepowodzenia Crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Lokalność Crusha</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Nic</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Technika</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Rozmiar pakietu</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>korzeń Crusha</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>urządzenie klasy Crush</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>którykolwiek</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Katalog</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>Wybrana nazwa Ceph pula jest już użyta.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Typ pula</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Wybierz typ pula --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Grupa umieszczenia</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Przynajmniej jedna grupa umieszczenia jest wymagana</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Twój klaster nie obsługuje tylu PG. Skalkuluj proszę potrzebną ilość PG.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Pomoc obliczeniowa</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>Obecne ustawienia PG zostały policzone dla Ciebie,
+powinieneś upewnić się czy te wartości Ci odpowiadają przed zatwierdzeniem.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>zbiór zasad Crush</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Wybierz zasadę Crush --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>zasada Crush</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Kroki Crush</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Zasada nie może być użyta w obecnym klastrze, gdyż ma
+zbyt mało OSD-ków, żeby spełnić minimum OSD-ków wymaganych przez tę zasadę.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Replikowany rozmiar</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>Sprecyzowany rozmiar jest poza zakresem. Wartość od
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> do
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> jest poprawna.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Skasuj profil kodu.</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Brak profilu kasowania --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Wybierz profil kodu wymazywania --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC Nadpisuje</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Zastosowania</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Kompresja</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algorytm</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Brak algorytmu kompresji wymazywania --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Minimalny rozmiar blob</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>np. 128 KB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>Wartość powinna być większa niż 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Maksymalny rozmiar blob</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>np. 512 KB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>Wartość powinna być większa niż minimalny rozmiar blob</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Stosunek</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Skompresowany stosunek</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>Wartość powinna być pomiędzy 0.0, a 1.0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Nie można stworzyć pula RBD z '/' w nazwie.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Proszę zmienić nazwę albo usunąć 'rbd' z listy zastosowań.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Szczegóły poziomów pamięci podręcznej</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Sprawdź proszę
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>dokumentację
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 
+jak skonfigurować i i uruchomić zarządzanie funkcjami Dostępu obiektowego
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Lista demonów</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Liczniki wydajności</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Ładowanie wiadra danych</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Nie można załadować wiadra danych.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>Number ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>Wartość nie jest poprawna.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Właściciel</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Wybierz użytkownika -- </target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Typ indeksu</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Zasada umieszczania</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Znacznik</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Maksymalny znacznik</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Wersja</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Główna wersja</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Czas modyfikacji</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Strefa </target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>kontyngent wiadra</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Uaktywniony</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Maksymalny rozmiar</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Nielimitowany</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Maksimum obiektów</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Wybierz nazwę użytkownika -- </target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Auto-generowany klucz</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Klucz dostępu</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Tajny klucz </target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Adres email</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Zawieszony</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>System</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, wybierz, 0 {Nie} 1{Tak} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Maksimum wiader</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>pod-użytkownicy</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Zdolności</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Limit użytkownika</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Pokaż</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Klucze</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- wybierz typ --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Pozwolenie </target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Wybierz pozwolenie --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>pod-użytkownik</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>Wybrane ID pod-użytkownika jest już użyte.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>odczyt, zapis</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>pełny</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Szybki klucz</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Auto-generowany sekret</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Ładowanie danych użytkownika...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Nie można załadować danych użytkownika.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>Wybrane ID użytkownika jest już użyte.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Ten adres email nie jest poprawny.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>Wybrany adres email jest już użyty.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Max. wiader </target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>Podana wartość musi być &gt;= 0</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>klucz S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Nie ma pod-użytkowników.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3 (prosty serwis przechowywania) </target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Nie ma kluczy.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Szybki</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Nie ma zdolności. </target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Nielimitowany rozmiar</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Max. rozmiar</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Nielimitowane obiekty</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Max. obiektów</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Obecny</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Zaktualizowane uwierzytelnianie wykrywania</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Brak dostępnych portali.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Nie ma dostępnych obrazów. </target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Nie ma dostępnych obrazów. Proszę się upewnić, że dodajesz obraz do obiektu docelowego. </target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Nie ma dostępnych inicjatorów iSCSI. Proszę upewnić się, że dodajesz inicjator iSCSI do obiektu docelowego.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>obiekt docelowy iSCSI</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Stan</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Odczyt bajtów </target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Zapis bajtów</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Odczyt Ops</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Zapis Ops</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O Od</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instancja</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nazwa hosta</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Zagadnienie </target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Progres</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Wyłączony</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Tryb Edycji</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Dodaj parowanie </target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Edytuj parowanie</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Usuń parowanie</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Lider</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># Lokalny</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># Zdalny</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>lustrzane parowanie</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Klucz</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Głębokie spłaszczenie</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Warstwowanie </target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Wyłączna blokada</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Mapa obiektów (wymaga wyłącznej blokady)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Kronikowanie (wymaga wyłącznej blokady)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Wycofywanie migawek RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Wycofanie</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>migawka RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Usunięty o </target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>id</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>typ</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>stan</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>wersja</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>administrator</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Ranga</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Demon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Aktywność</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>centrale</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>i-węzły</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Użycie</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Czuwanie demona </target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>Wartość może być zaktualizowana w czasie wykonywania . </target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Demony/klienci nie pobierają tej wartości z
+bazy danych skonfigurowanego monitora. Nie zezwalamy na ustawienie tej opcji przez 'konfiguracje ceph
+ustaw.. '. Ta opcja powinna być skonfigurowana przez ceph.conf albo przez
+terminal.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>Opcja działa tylko podczas startu demona.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>Opcja dotyczy tylko tworzenia klastra.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>Opcja tylko wpływa na tworzenie demona.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Zaktualizowana opcja konfiguracji
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Usługa</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Obecna wartość</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Edytowalny</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Zaktualizowane opcje dla modułu &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Włączyć</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Wyłączyć</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Ponowne łączenie, proszę czekać</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Adres publiczny</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Otwarte sesje</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Nie w </target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>OSD-ki, które zostały oznaczone jako poza, nie będą oznaczone ponownie jako w gdy zostaną uruchomion</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Nie poza</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSD-ki nie będą automatycznie oznaczone jako poza po konfiguracji interwału</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Nie powstały </target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>OSD-ki nie mogą startować</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Nie upadły</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Raport z niepowodzenia OSD jest ignorowany, także monitory nie oznaczą OSD jako upadłego. </target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pauza </target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Pauzuje czytanie i zapisywanie</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Nie szoruj</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Szorowanie jest wyłączone</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Nie ma głębokiego szorowania</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Głębokie szorowanie jest wyłączone</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Brak zasypywania</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Zasypywanie PG jest zawieszone</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Nie przywrócono</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Przywrócenie PGy jest zawieszone </target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Sortuj bitowo</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Użyj sortowania bitowego</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Usuń snap katalogi</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD-ki zmieniły snapsety</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Odzyskaj usunięte</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Podczas zdrowienia zastosowano usunięcie zamiast parowania</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Twardy limit logów PG</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Ustawia twardy limit na długość logów PG</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Zaktualizowane flagi OSD-ków</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>poza</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>w</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>upadły</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Zaznacz</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>Stracony OSD</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>Zaznaczony jako stracony</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Czyść</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD-ik</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>Oczyszczony</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>Zniszcz</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>Zniszczony</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>PG-y</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Czytanie bajtów</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Zapis bajtów</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Czytanie ops</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Zapis ops</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Zaznacz OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Zaznacz
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Max zasypywanie</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Max aktywność wyzdrowienia</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Max pojedynczy start wyzdrowienia</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Uśpienie wyzdrowienia</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Zwyczaj</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Zaktualizowano prędkość wyzdrowienia OSD priorytet &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> został zainicjalizowany w następującym OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Praca</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>surowość</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Wystartowany</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Zaktualizowany</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Użyty</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Dostępny</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Czyść</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>Działający</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Ostrzeżenie </target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Nieznany</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>Podniesiony</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>brak systemów plików</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>aktywny</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>Rezerwa</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>niedostępny</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>aktywny demon</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>kworum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>Usługa NFS Ganesha nie jest skonfigurowana</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transport</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Użytkownik CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>system plików CephFS </target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(Odziedziczyło z globalnej konfiguracji)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>Odziedziczyło z globalnej konfiguracji</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Wybierz, jakiego rodzaju identyfikacja użytkownika ma być przeprowadzana -- </target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Brak dostępnym demonów</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Tryb pamięci podręcznej</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Min wiek eksmisji</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Min wiek wyrównania </target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Max bajtów obiektu docelowego </target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Max obiektów docelowych</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Nie dodano żadnego zastosowania</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Osiągnięto limit zastosowań </target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Pul może mieć maksymalnie 4 definicje aplikacji. </target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Dozwolone znaki '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>Maksymalna długość wynosi 128 znaków</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtruj lub dodaj zastosowanie</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Dodaj zastosowanie</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>skasuj profil kodu</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Rozmiar repliki</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Ostatnia zmiana</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Skasuj profil zakodowany</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Zbiór zasad Crush</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Zapis bajtów </target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>wiadro</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Zaktualizowano wiadro dostępu obiektowego &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Stworzono wiadro dostępu obiektowego &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>Wiadra</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>użytkownik</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Zaktualizowano użytkownika dostępu obiektowego &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Stworzono użytkownika dostępu obiektowego&amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>użytkownicy</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Zakres</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Czytaj</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Stwórz</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Utwórz rolę '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Zaktualizuj rolę '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>System roli </target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Usuń rolę '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Stwórz użytkownika &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Zaktualizuj użytkownika</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Kontynuuj </target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Zostałeś automatycznie wylogowany, ponieważ zostały zmienione twoje role.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Zaktualizowano użytkownika &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Usunięto użytkownika &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Nie udało się usunąć użytkownika &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>Jesteś obecnie zalogowany jako&amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Każdy obiekt jest podzielony na części fragmentów danych, każdy jest przechowywany na innym OSD.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Oblicz porcje kodu dla każdego obiektu i przechowuj je na różnych OSD.
+ Liczba fragmentów kodujących to również liczba OSD, które mogą zostać wyłączone bez utraty danych.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Wtyczka jerasure jest najbardziej uniwersalną i elastyczną wtyczką,
+ jest to również domyślne ustawienie dla pui kodowanych przez Ceph.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>Bardziej elastyczną techniką jest reed_sol_van: wystarczy ustawić k
+ oraz m. Technika cauchy_good może być szybsza, ale musisz wybrać rozmiar pakietu
+ ostrożnie. Wszystkie reed_sol_r6_op, liberation, blaum_roth, liber8tion są odpowiednikami RAID6
+ w tym sensie, że mogą być skonfigurowane tylko z m = 2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>Kodowanie będzie wykonywane na pakietach o rozmiarze bajtów naraz.
+ Wybór odpowiedniego rozmiaru pakietu jest trudny.
+ Dokumentacja jerasure zawiera obszerne informacje na ten temat.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Z wtyczką jerasure, gdy obiekt zakodowany przy użyciu skasowania jest przechowywany na
+ wielu OSD-kach, odzyskiwanie po utracie jednego OSD wymaga odczytu ze wszystkich pozostałych.
+ Na przykład, jeśli konfiguracja skryptu ma wartość k = 8 ,m = 4 i l=4, utrata jednego OSD wymaga odczytu
+ od jedenastu innych do naprawy.
+
+ Wtyczka kodu wymazywania lrc tworzy fragmenty o parzystości lokalnej, aby móc je odzyskać
+ mniej OSD. Na przykład, jeśli lrc jest skonfigurowane z k = 8, m = 4 i l = 4, zostanie utworzony
+ dodatkowy fragment parzystości na każde cztery OSD. Gdy jeden OSD zostanie utracone, może to być
+ odzyskane tylko z czterema OSD zamiast jedenastu.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Grupuj fragmenty kodu i danych w zestawy lokalizacji wielkości. Na przykład,
+ dla k = 4 i m = 2, gdy lokalność = 3 tworzone są dwie grupy po trzy. Każdy zestaw może
+ odzyskać bez czytania kawałków z innego zestawu.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>Typ wiadra CRUSH, w którym zdefiniowano każdy zestaw porcji
+ przez l zostaną zapisane. Na przykład, jeśli jest ustawiony na rack, każda grupa l porcji będzie
+ umieszczona w innym raku. Służy do utworzenia kroku reguły CRUSH, takiego jak krok wyboru
+ racka. Jeśli nie jest ustawiony, nie ma takiego grupowania.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>Wtyczka isa zawiera bibliotekę ISA. Działa tylko na procesorach Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>Wtyczka ISA jest dostępna w dwóch formach Reed Solomon.
+ Jeśli ustawiono reed_sol_van, jest to Vandermonde, jeśli ustawiono cauchy, to jest to Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>Wtyczka shec zawiera wiele bibliotek SHEC.
+ Pozwala ceph odzyskać dane bardziej efektywnie niż kody Reeda Solomona.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>Liczba kawałków parzystości, z których każdy zawiera każdą porcję danych w swoim zakresie obliczeń. Liczba jest używana jako estymator trwałości. Na przykład, jeśli c = 2,
+ 2 OSD można wyłączyć bez utraty danych.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>Nazwa wiadra crush jest użyte do pierwszego kroku reguły CRUSH.
+Na przykład krok jest domyślny.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Upewnij się, że żadne dwie porcje nie znajdują się w wiadrze z tą samą awarią
+ domeny. Na przykład, jeśli domena awarii jest hostem, nie zostaną na niej zapisane dwie porcje
+ hosta. Służy do utworzenia kroku reguły CRUSH, takiego jak krok wyboru hosta.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Ogranicz umieszczanie do urządzeń określonej klasy
+ (np. ssd lub hdd), używając nazw klas urządzeń zgniatających na mapie CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Ustaw nazwę katalogu, z którego ładowana jest wtyczka kodu kasowania.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Dozwolone są wszystkie operacje</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Dozwolone są operacje, które nie modyfikują serweru</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Operacje odczytu i zapisu są zakazane, wszystkie inne dozwolone</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Operacje odczytu i zapisu, oraz wszystkie operacje modyfikujące atrybuty albo katalogi są zakazane </target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Brak dostępu w ogóle</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- wybierz priorytet -- </target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Niski</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Wysoki</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Ostatnie 5 minut</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Ostatnie 15 minut</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Ostatnie 30 minut</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Ostatnia 1 godzina (domyślnie)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Ostatnie 3 godziny</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Ostatnie 6 godzin</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Ostatnie 12 godzin</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Ostatnie 24 godziny</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Wczoraj</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Dzisiaj</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Do tej pory dzisiaj</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Przedwczoraj</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Ostatnie 2 dni</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Tego dnia tydzień temu</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Poprzedni tydzień</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Ten tydzień </target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Do tej pory w tym tygodniu</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Ostatnie 7 dni</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Poprzedniego miesiąca</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>ten miesiąc</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Do tej pory w tym miesiącu</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Ostatnie 30 dni</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Ostatnie 90 dni</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Ostatnie 6 miesięcy</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>Ostatni 1 rok</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Poprzedniego roku</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Bieżącego roku</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Do tej pory bieżącego roku</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Ostatnie 2 lata</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Ostatnie 5 lat</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informacja</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Nie wybrano żadnej pozycji</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Odznacz pozycję, żeby wybrać ponownie</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Osiągnięto limit wyboru. </target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Filtr tagów.</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Dodaj odznakę</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Brak dostępnych pozycji.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Dodaj</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Sklonuj</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Kopia</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Szoruj głęboko</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Zniszcz</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Spłaszcz</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>zaznacz jako upadły</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Zaznacz jako w </target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Zaznacz jako stracony</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Zaznacz jako poza</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Zabezpiecz</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Zmień nazwę</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Przywróć</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Przenieś do kosza</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Odbezpiecz </target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Usunięty</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Sklonowano</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Skopiowano </target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Tak</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Nie</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Jakość serwisu</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Limit BPS</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>Pożądany limit IO bajtów na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Limit IOPS</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>Pożądany limit operacji IO na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>limit odczytu BPS</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>Pożądany limit odczytu bajtów na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>limit odczytu IOPS</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>Pożądany limit operacji odczytu na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Limit zapisu BPS</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>Pożądany limit zapisu bajtów na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Limit zapisu IOPS</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>Pożądany limit operacji zapisu na sekundę.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Wiązka BPS</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>Żądana granica serii IO bajtów.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Wiązka IOPS</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>Żądana granica serii operacji IO.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Odczyt wiązki BPS</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>Żądana granica serii odczytanych bajtów.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Odczyt wiązki IOPS</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target> Żądana granica serii operacji odczytu.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Zapis wiązki BPS</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>Żądana granica serii bajtów zapisu.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Zapis wiązki IOPS</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>Żądana granica serii operacji zapisu.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Nie powiodło się
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Wykonywanie </target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>Wykonaj</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Wykonany</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>Nieznane zadanie</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Tworzenie</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>Utwórz</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Aktualizowanie </target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>Zaktualizuj</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Usuwanie</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>Usuń</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>urządzenie blokowe Rados '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>migawka RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>tryb lustrzany dla pula '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Lustrzane parowanie dla pula '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Nazwa jest już użyta przez
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Nazwa jest już używana przez
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Nazwa jest już używana przez
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> zawiera migawkę.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Klonowanie</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>Sklonuj </target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>Migawka
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>  musi być zabezpieczona.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Kopiowanie </target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>Kopiuj</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Spłaszczanie</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>Spłaszcz</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Spłaszczony</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Nazwa już jest używana przez
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Nie można zdjąć zabezpieczenia
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> , ponieważ zawiera pokrewne obrazy.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Nie można usunąć
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>, ponieważ jest zabezpieczony.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Wycofywanie </target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>Wycofanie</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Wycofaj</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Przenoszenie</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>Przenieś</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Przeniesiono</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>Obraz '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' przenieś do kosza
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Nie znaleziono obrazu.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Przywracanie</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>Przywróć </target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Przywrócony</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target> Obraz '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' w '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Nazwa obrazu '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' jest już używana.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Obraz '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' 
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>oczyszczać</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>oczyść</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Oczyszczony</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>Wszystkie pule</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>Obraz z
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Nie można wyłączyć lustrzenia ponieważ zawiera parowanie.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>pul '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>skasuj profil kodu '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>docelowy '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.pt-BR.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.pt-BR.xlf
new file mode 100644
index 00000000..816a0976
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.pt-BR.xlf
@@ -0,0 +1,4366 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="pt-BR">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>Alternar navegação</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>Painel de controle</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>Cluster</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>Hosts</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitores</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSDs</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>Configuração</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>Mapa CRUSH</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Módulos do gerenciador</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>Registros</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>Alertas</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>Pools</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>Bloco</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>Imagens</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>Espelhamento</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>Sistemas de arquivos</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>Gateway de Objetos</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>Daemons</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>Usuários</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>Compartimentos</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Recuperando dados
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> de
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Aguarde...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Exibindo dados armazenados em cache anteriormente
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ para
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Não foi possível carregar os dados
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> de
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Verifique a saúde do cluster.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>Voltar</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>Selecionar Idioma</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>Carregando dados do painel...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>Consulte a
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentação
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre como
+ configurar e habilitar a funcionalidade de monitoramento.
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>O Painel de Controle do Grafana não existe. Consulte a
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentação
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> sobre como
+ adicionar painéis de controle ao Grafana.
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Seletor de Horário do Grafana</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>Redefinir Configurações</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>Falha ao carregar dados.</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>selecionado(s)</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>encontrado(s)</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>total</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>Editar</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>Nome</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>Descrição</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>Descrição extensa</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>Padrão</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>Padrão do daemon</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>Serviços</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>Valores</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>O valor inserido é muito alto! Ele não pode ser maior do que
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>O valor inserido é muito baixo! Ele não deve ser menor do que
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>Salvar</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>Visualizador de mapa CRUSH</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>Lista de Hosts</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>Desempenho Geral</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>Nenhuma entrada encontrada</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>Registros do Cluster</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>Registros de Auditoria</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>Carregando configuração...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>Não foi possível carregar a configuração.</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>Editar módulo do gerenciador</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>O valor inserido não é um UUID válido. Ex.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>O valor inserido precisa ser um endereço IP válido.</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>Este campo é obrigatório.</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>O valor inserido é muito alto! Ele deve ser menor ou igual a
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>O valor inserido é muito baixo! Ele deve ser maior ou igual a
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>O valor inserido precisa ser um número.</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>O valor inserido precisa ser um número ou decimal.</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>Atualizar</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>Status</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>ID do Cluster</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmap modificado</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>época de monmap</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>con obrigatório</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>mon obrigatório</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>No Quorum</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>Não está no Quorum</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>Cancelar</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>Deseja realmente
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> o(a)
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/> selecionado(a)?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>Sim, desejo.</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>Flags OSD de todo o Cluster</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>Enviar</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>Avançado...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>Prioridade de Recuperação de OSD</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>Prioridade</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>Personalizar valores de prioridade</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>Este campo é obrigatório!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>O valor inserido é muito alto! Ele não pode ser maior do que
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>O valor inserido é muito baixo! Ele não deve ser menor do que
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>Reponderar OSD</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>O valor precisa ser entre 0 e 1.</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>Reponderar</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>Remoção de OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {Profundo } }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>Você está prestes a aplicar uma
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>remoção ao
+ OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {profundo} }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>Lista de OSDs</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> será marcado como
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se você continuar.
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>Não é seguro destruir o OSD!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> será
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> se você continuar.
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>Detalhes</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>Valor</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>Fechar</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>Excluir</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>Saúde</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>Estatísticas</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>Consulte a
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentação
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre como configurar e habilitar a funcionalidade de gerenciamento do NFS Ganesha.
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>Clientes</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>Qualquer cliente pode acessar</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>Endereços</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>Campo obrigatório</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>Deve conter um ou mais valores separados por vírgula</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>Por exemplo:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>Tipo de Acesso</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Executar Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>Adicionar clientes</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>Carregando...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- Não há clusters disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- Selecionar cluster --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>Adicionar daemon</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>Backend de Armazenamento</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- Não há pools de dados disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- Selecionar backend de armazenamento --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>Usuário do Gateway de Objetos</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- Não há usuários disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- Selecionar usuário do gateway de objetos --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>ID de Usuário do CephFS</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- Não há clientes disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- Selecionar cliente do cephx --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>Nome do CephFS</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>Rótulo de Segurança</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>Habilitar rótulo de segurança</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>Caminho do CephFS</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>O caminho precisa começar com '/' e pode ser seguido de uma palavra</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>Novo diretório será criado</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>Caminho</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>O caminho pode ser apenas uma '/' ou uma palavra</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>Novo compartimento será criado</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>Protocolo NFS</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>Tag NFS</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>Acesso alternativo às montagens do
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (não deve ter / à esquerda).
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>Clientes não podem montar subdiretórios (ou seja, se Tag = foo, o cliente não poderá montar foo/baz).</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>Ao usar opções diferentes de Tag, o mesmo Caminho pode ser exportado várias vezes.</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>Pseudo</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>A posição que esta exportação de
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> ocupa
+ no
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (deve ser exclusiva).
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>Ao usar opções diferentes de Pseudo, o mesmo Caminho pode ser exportado várias vezes.</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- Não há tipos de acesso disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- Selecionar tipo de acesso --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- Não há squashes disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>--Selecionar que tipo de squash de ID de usuário será executado --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>Protocolo de Transporte</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>Bem-vindo ao Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>Nome de usuário é obrigatório</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>Senha é obrigatória</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>Login</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>O usuário não existe no Ceph.</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>Retorne à
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Página de Login
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. Seu logout será efetuado do Provedor de Identidade quando você repetir o login.
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>Proibido</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>Você não tem permissão para ver o que está procurando.</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>Não foi possível localizar o que você está procurando</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>Remover tudo</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>Notificações Recentes</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>Não há tarefas em segundo plano.</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>Tarefas em Segundo Plano</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>Ajuda</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>Documentação</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>Sobre</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>Configurações do Painel de Controle</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>Gerenciamento de usuários</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>Usuário que efetuou login</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>Efetuar login como
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>Efetuar logout</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>Nome...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>O nome escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>Descrição...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>Permissões</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>Funções</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>Nome de usuário</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>Senha</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>Confirmar senha</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>A confirmação de senha não corresponde à senha.</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>Nome completo</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>E-mail</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>E-mail inválido.</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>Você está prestes a remover as permissões de "leitura/atualização de usuário" do seu próprio usuário.</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>Se você continuar, não poderá mais adicionar ou remover funções de nenhum usuário.</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>Deseja realmente continuar?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>Contadores de desempenho não disponíveis</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>Atributos (mapa OSD)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>Metadados não disponíveis</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>Metadados</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>Contador de desempenho</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>Histograma não disponível:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>Gravações</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>Leituras</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>Histograma</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>Detalhes de Desempenho</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>Valores atuais</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>Tipo</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>Mín.</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>Máx.</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>Flags</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>Origem</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>Nível</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>Pode ser atualizado em tempo de execução (editável)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>Tags</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>Valores de enum</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>Consulte também</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>Status do Cluster</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>Daemons do Gerenciador</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>Gateways de Objetos</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>Servidores de Metadados</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>Gateways iSCSI</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>IOPS do Cliente</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>Throughput do Cliente</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>Leitura/Gravação do Cliente</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>Throughput de Recuperação</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>Remoção</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>Desempenho</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>Capacidade Bruta</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>Objetos</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>PGs por OSD</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>Status do PG</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>Capacidade</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> Consulte os
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Registros
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> para obter mais detalhes.
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>Posições</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>Clientes:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>Mover imagem para o lixo</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>Para mover
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> para o lixo,
+ clique em
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Mover Imagem
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Se preferir, escolha uma data de vencimento.
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>Vencimento da proteção em</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>NÃO PROTEGIDO</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>Formato de data incorreto. Use "AAAA-MM-DD HH:mm:ss".</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>A proteção já venceu. Escolha uma data no futuro ou deixe-a vazia.</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>Mover Imagem</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>Visão geral</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>Destinos</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>Autenticação de Descoberta</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>Usuário</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Os nomes de usuário devem ter entre 8 e 64 caracteres e
+ apenas podem conter letras, '.', '@', '-', '_' ou ':'.</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>Usuário Mútuo</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>Senha Mútua</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>Consulte a
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentação
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre como configurar e habilitar a funcionalidade de gerenciamento de Destinos iSCSI.
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>Informações disponíveis:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>Destinos iSCSI não disponíveis</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>Disponível apenas para imagens RBD com
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>diff rápido
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> habilitado
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>Pool</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>Pool de Dados</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>Criado</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>Tamanho</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>Tamanho do objeto</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>Recursos</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>Aprovisionado</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/A</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>Total aprovisionado</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>Unidade de distribuição</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>Total de distribuições</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>Pai</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>Prefixo do nome do bloco</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>Ordem</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>Instantâneos</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>Imagem</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>Esta configuração substitui o valor global</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>Global</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>Este é o valor global. Nenhum valor para esta opção foi definido para esta imagem.</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>'/' e '@' não são permitidos.</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- Não há pools de RBD disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- Selecionar pool --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>Usar pool de dados dedicado</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>Pool de dados</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>Pool dedicado que armazena os dados de objetos do RBD.</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>ex. 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>Você precisa aumentar o tamanho.</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>Avançado</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>Distribuição</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>Unidade de distribuição</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- Selecionar unidade de distribuição --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>Este campo é obrigatório porque o total de distribuições foi definido!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>A unidade de distribuição é maior do que o tamanho do objeto.</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>Total de distribuições</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>Este campo é obrigatório porque a unidade de distribuição foi definida!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>O total de distribuições deve ser maior do que 0.</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Instantâneo do RBD
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {Renomear} other {Criar} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Instantâneo
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>PROTEGIDO</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>NÃO PROTEGIDO</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>Você está prestes a fazer rollback</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>Purgar Lixo</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>Para purgar, selecione uma ou Todas as imagens e clique em</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>Pool:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>Nome do pool...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>Tudo</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>Restaurar Imagem</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>Para restaurar</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>digite o novo nome da imagem e clique em</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>Novo Nome</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>Venceu em</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>Protegido até</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>Esta imagem está protegida até
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>Lixo</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>Topologia iSCSI</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>Não costuma ser necessário mudar o valor padrão destes parâmetros.</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>Configurações</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>Backstore</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>Confirmar</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>Configurações Avançadas</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>IQN de Destino</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN tem padrão incorreto.</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>Um IQN tem a seguinte notação 'iqn.$year-$month.$reversedAddress:$definedName'</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>Por exemplo: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>Mais informações</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>Este destino tem configurações avançadas modificadas.</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>Portais</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>Pelo menos
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways são necessários.
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>Adicionar portal</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>Esta imagem tem configurações modificadas.</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>Adicionar imagem</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>Autenticação ACL</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>Iniciadores</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>Iniciador</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>IQN do Cliente</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>O IQN do Iniciador precisa ser exclusivo.</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Os nomes de usuário devem ter entre 8 e 64 caracteres e
+ apenas podem conter letras, '.', '@', '-', '_' ou ':'.</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>O iniciador pertence a um grupo. As imagens serão configuradas no grupo.</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>Nenhum item adicionado.</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>Adicionar iniciador</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>Grupos</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>Grupo</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>Adicionar grupo</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>Configuração de RBD</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>Remova o valor de configuração local. No lugar dele, o valor de configuração pai será herdado e usado.</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>O valor mínimo é 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>Problemas</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>Sincronizando</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>Pronto</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>Editar modo de espelho do pool</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>Para editar o modo de espelho do pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, selecione o novo modo na lista e clique em 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Atualizar
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>Modo</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>Clusters de peer devem ser removidos antes de desabilitar o espelho.</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ peer de espelho do pool
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {Editar} other {Adicionar} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> os atributos
+ de peer de espelho do pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> e clique em
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Enviar
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>Nome do Cluster</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>O nome do cluster não é válido.</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>ID do CephX</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>ID do CephX...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>O ID do CephX não é válido.</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Endereços do Monitor</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>Endereços delimitados por vírgula...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>O endereço de monitoria não é válido.</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>Chave do CephX</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Chave codificada com base64...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>A chave do CephX deve ser codificada com base64.</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>Lista de Pools</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>O nome pode conter apenas caracteres alfanuméricos, traços e sublinhados.</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>O nome do perfil de código de eliminação escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>Plug-in</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>Pacotes de dados (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>Deve ser igual ou maior do que 2.</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>Pacotes de codificação (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>Deve ser igual ou maior do que 1.</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>Estimador de durabilidade (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>Localidade (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>Domínio de falha do Crush</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>Localidade do Crush</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>Nenhum</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>Técnica</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>Tamanho do pacote</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>Raiz do Crush</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>Classe do dispositivo do Crush</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>qualquer</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>Diretório</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>O nome do pool do Ceph escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>Tipo de pool</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- Selecionar tipo de pool --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>Grupos de posicionamento</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>Pelo menos um grupo de posicionamento é necessário!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>Seu cluster não pode processar tantos PGs. Recalcule a quantidade de PG necessária.</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>Ajuda no cálculo</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>As configurações de PGs atuais foram calculadas para você. Verifique
+ se os valores atendem às suas necessidades antes de enviar.</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>Conjunto de regras do Crush</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- Selecionar regra de crush --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>Regra de Crush</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>Etapas do Crush</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>Impossível usar a regra no cluster atual porque ela tem
+ poucos OSDs para atender ao OSD mínimo necessário para esta regra.</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>Tamanho replicado</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>Mínimo:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>Máximo:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>O tamanho especificado está fora da faixa. Um valor de
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> a
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> é válido.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>Perfil do código de eliminação</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- Não há perfis de código de eliminação disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- Selecionar perfil do código de eliminação --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>Sobregravações de EC</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>Aplicativos</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>Compactação</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>Algoritmo</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- Não há algoritmos de compactação de eliminação disponíveis --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Tamanho mínimo do blob</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>ex. 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>O valor deve ser maior do que 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Tamanho máximo do blob</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>ex. 512 KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>O valor deve ser maior do que o tamanho mínimo do blob</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>Taxa</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>Taxa de compactação</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>O valor deve ser entre 0.0 e 1.0</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>Impossível criar um pool de RBD com '/' no nome.</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>Altere o nome ou remova o 'rbd' da lista de aplicativos.</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>Detalhes das Camadas do Cache</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>Consulte a
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentação
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ sobre como configurar e habilitar a funcionalidade de gerenciamento do Gateway de Objetos.
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>Lista de Daemons</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>Contadores de Desempenho</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>Carregando dados do compartimento...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>Não foi possível carregar os dados do compartimento.</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>O valor não é válido.</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>Proprietário</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- Selecionar usuário --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>Tipo de índice</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>Regra de posicionamento</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>Marcador</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>Marcador máximo</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>Versão</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>Versão master</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>Horário da modificação</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>Grupo de zonas</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>Cota do compartimento</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>Habilitado</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>Tamanho máximo</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>Ilimitado</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>Máximo de objetos</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- Selecionar nome de usuário --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>Gerar chave automaticamente</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>Chave de acesso</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>Chave secreta</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>Endereço de e-mail</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>Suspenso</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>Sistema</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {Não} 1 {Sim} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>Máximo de compartimentos</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>Subusuários</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>Recursos</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>Cota do usuário</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>Mostrar</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>Chaves</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- Selecionar tipo --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>Permissão</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- Selecionar permissão --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>Subusuário</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>O ID de subusuário escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>leitura, gravação</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>completo</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Chave Swift</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>Gerar segredo automaticamente</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>Carregando dados do usuário...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>Não foi possível carregar os dados do usuário.</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>O ID de usuário escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>Este não é um endereço de e-mail válido.</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>O endereço de e-mail escolhido já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>Máx. de compartimentos</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>O valor inserido deve ser &gt;= 0.</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>Chave S3</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>Não há subusuários.</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>Não há chaves.</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>Não há recursos.</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>Tamanho ilimitado</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>Tamanho máx.</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>Objetos ilimitados</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>Máx. de objetos</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>Atual</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>Autenticação de descoberta atualizada</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>Não há portais disponíveis.</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>Não há imagens disponíveis.</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>Não há imagens disponíveis. Adicione uma imagem ao destino.</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>Não há iniciadores disponíveis. Adicione um iniciador ao destino.</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>Destino</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>Estado</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>Bytes de Leitura</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>Bytes de Gravação</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>Op. de Leitura</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>Op. de Gravação</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>A/O Desde</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>Instância</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>Nome de host</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>Problema</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>Andamento</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>Desabilitado</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>Modo de Edição</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>Adicionar Peer</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>Editar Peer</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>Excluir Peer</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Leader</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>Nº Local</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>Nº Remoto</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>espelhar peer</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>Chave</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>Nivelamento profundo</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>Disposição em camadas</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>Bloqueio exclusivo</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>Mapa de objetos (requer bloqueio exclusivo)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>Registro em diário (requer bloqueio exclusivo)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>Rollback de instantâneo do RBD</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>Fazer Rollback</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>Instantâneo do RBD</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>Excluído à(s)</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>tipo</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>estado</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>versão</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>Host</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>raiz</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>Posição</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>Daemon</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>Atividade</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inodes</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>Uso</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>Daemons de standby</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>É possível atualizar o valor em temo de execução.</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>Daemons/clientes não extraem este valor do
+ banco de dados de configuração do monitor. A configuração desta opção não é permitida por meio de 'ceph config
+ set ...'. Essa opção deve ser configurada por meio do ceph.conf ou da
+ linha de comando.</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>A opção entra em vigor apenas durante a inicialização do daemon.</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>A opção afeta apenas a criação do cluster.</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>A opção afeta apenas a criação do daemon.</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>Opção de configuração
+ <x id="INTERPOLATION" equiv-text="{{name}}"/> atualizada
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>Serviço</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>Valor atual</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>Editável</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>Opções atualizadas para o módulo &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>Habilitar</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>Desabilitar</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>Reconectando, aguarde...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>Endereço Público</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>Sessões Abertas</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>Não Entrada</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>Os OSDs que já foram marcados como saída não serão remarcados como entrada ao serem iniciados</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>Não Saída</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>Os OSDs não serão automaticamente marcados como saída após o intervalo configurado</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>Não Ativo</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>Os OSDs não podem ser iniciados</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>Não Inativo</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>Os relatórios de falha de OSD estão sendo ignorados, portanto, os monitores não marcarão os OSDs como inativos</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>Pausar</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>Pausa leituras e gravações</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>Sem Remoção</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>Remoção desabilitada</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>Sem Remoção Profunda</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>Remoção Profunda desabilitada</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>Sem Provisionamento</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>Provisionamento de PGs suspenso</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>Sem Recuperação</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>Recuperação de PGs suspensa</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>Classificação Bit a Bit</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>Usar classificação bit a bit</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>Snapdirs Purgados</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSDs converteram snapsets</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>Exclusões de Recuperação</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>Exclusões realizadas durante a recuperação, e não o emparelhamento</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>Limite Físico do Registro de PG</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>Atribui um limite físico ao tamanho do registro de PG</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>Flags OSD Atualizadas</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>saída</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>entrada</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>inativo</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>Marcar</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD perdido</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>marcado como perdido</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>Purgar</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>purgado</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>destruir</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>destruído</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>PGs</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>Bytes de leitura</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>Bytes de gravação</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>Op. de leitura</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>Op. de gravação</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marcar OSD como
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>Marcar como
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>Máx. de Provisionamentos</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>Máx. Recuperação Ativo</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>Máx. Recuperação Inicialização Única</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>Suspensão de Recuperação</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>Personalizado</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>Prioridade de velocidade de recuperação de OSD &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>&amp;quot atualizada;
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> foi inicializado no seguinte OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>Tarefa</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>Gravidade</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>Iniciado</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>Atualizado</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>Usado</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>Disp.</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>Limpar</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>Em funcionamento</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>Aviso</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>Desconhecido</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>ativo</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>sem sistemas de arquivos</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>ativo</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>standby</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/a</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>daemon ativo</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>O serviço NFS Ganesha não está configurado.</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>Transporte</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>Usuário do CephFS</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>Sistema de Arquivos do CephFS</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(herdado da configuração global)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>herdado da configuração global</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- Selecionar que tipo de squash de ID de usuário será executado --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>Não há daemons disponíveis.</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>Modo de Cache</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>Tempo Mín. Expulsão</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>Tempo Mín. Descarregamento</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>Máx. de Bytes de Destino</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>Máx. de Objetos de Destino</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>Nenhum aplicativo adicionado</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>Limite de aplicativos atingido</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>Um pool apenas pode ter até quatro definições de aplicativos.</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>Caracteres permitidos: '_a-zA-Z0-9'</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>Tamanho máximo de 128 caracteres</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>Filtrar ou adicionar aplicativos</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>Adicionar aplicativo</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>perfil de código de eliminação</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>Tamanho da Réplica</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>Última Alteração</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>Perfil Codificado para Eliminação</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>Conjunto de Regras do Crush</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>Bytes de gravação</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>compartimento</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Compartimento do Gateway de Objetos &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; atualizado
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>Compartimento do Gateway de Objetos &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>&amp;quot; criado
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>compartimentos</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>usuário</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Usuário do Gateway de Objetos &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot; atualizado
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>Usuário do Gateway de Objetos &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>&amp;quot; criado
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>usuários</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>Escopo</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>Leitura</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>Criar</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Função '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' criada
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Função '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' atualizada
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>Função do Sistema</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>Função '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>' excluída
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Usuário &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; criado
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>Atualizar usuário</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>Continuar</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>Você foi automaticamente desconectado porque suas funções foram alteradas.</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Usuário &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; atualizado
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Usuário &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot; excluído
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>Falha ao excluir o usuário &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>No momento, você está conectado como &amp;quot;
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>&amp;quot;.
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>Cada objeto é dividido em partes de pacotes de dados, cada uma armazenada em um OSD diferente.</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>Calcule os pacotes de codificação de cada objeto e armazene-os em diferentes OSDs.
+ O número de pacotes de codificação é também o número de OSDs que podem ficar inativos sem perda de dados.</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>O plug-in jerasure é o mais genérico e flexível,
+ além de ser o padrão para pools codificados para eliminação do Ceph.</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>A técnica mais flexível é reed_sol_van: ela é suficiente para definir k
+ e m. A técnica cauchy_good pode ser mais rápida, mas você precisa escolher o tamanho do pacote
+ com cuidado. Todos os reed_sol_r6_op, liberation, blaum_roth e liber8tion são equivalentes ao RAID6
+ no sentido de que só podem ser configurados com m=2.</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>A codificação será feita em pacotes de tamanho de bytes um de cada vez.
+ A escolha do tamanho do pacote certo é difícil.
+ A documentação do jerasure contém informações completas sobre este tópico.</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>Com o plug-in jerasure, quando um objeto codificado para eliminação é armazenado em
+ vários OSDs, a recuperação após a perda de um OSD requer a leitura de todos os outros.
+ Por exemplo, se o jerasure for configurado com k=8 e m=4, a perda de um OSD exigirá a leitura
+ dos outros onze para fazer o reparo.
+
+ O plug-in de código de eliminação lrc cria pacotes locais de paridade para conseguir recuperar usando
+ menos OSDs. Por exemplo, se o lrc for configurado com k=8, m=4 e l=4, ele criará
+ um pacote de paridade adicional para cada quatro OSDs. Quando um único OSD é perdido, ele pode ser
+ recuperado apenas com quatro OSDs, em vez de onze.</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>Agrupe os pacotes de codificação e dados em conjuntos de localidades com tamanho. Por exemplo,
+ no caso de k=4 e m=2, quando locality=3, dois grupos de três são criados. Cada conjunto pode
+ ser recuperado sem a leitura dos pacotes do outro conjunto.</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>O tipo do compartimento de crush em que cada conjunto de pacotes definido
+ por l será armazenado. Por exemplo, se isso for definido como rack, cada grupo de pacotes l será
+ colocado em um rack diferente. Isso é usado para criar uma etapa da regra CRUSH, como a etapa de escolha do
+ rack. Se isso não for definido, esse tipo de agrupamento não será feito.</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>O plug-in isa encapsula a biblioteca ISA. Ele apenas é executado em processadores Intel.</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>O plug-in ISA vem em dois formatos de Reed Solomon.
+ Se reed_sol_van for definido, ele será Vandermonde, se cauchy for definido, ele será Cauchy.</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>O plug-in shec encapsula a biblioteca múltipla SHEC.
+ Ele permite ao ceph recuperar dados com mais eficiência do que os códigos de Reed Solomon.</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>O número de pacotes de paridade, em que cada um inclui cada pacote de dados em sua
+ faixa de cálculo. O número é usado como estimador de durabilidade. Por exemplo, se c=2,
+ 2 OSDs podem ficar inativos sem perda de dados.</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>O nome do compartimento de crush usado para a primeira etapa da regra CRUSH.
+ Por exemplo, a etapa assumir o padrão.</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>Verifique se não há dois pacotes em um compartimento com o mesmo domínio de
+ falha. Por exemplo, se o domínio de falha for um host, não armazene dois pacotes no mesmo
+ host. Isso é usado para criar uma etapa da regra CRUSH, como a etapa de escolha do host folha.</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>Restrinja o posicionamento a dispositivos de uma classe específica
+ (ex. ssd ou hdd), usando nomes de classe de dispositivo crush no mapa CRUSH.</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>Defina o nome do diretório do qual o plug-in de código de eliminação é carregado.</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>Permite todas as operações</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>Permite apenas as operações que não modificam o servidor</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>Não permite operações de leitura ou gravação, mas permite qualquer outra operação</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>Não permite leitura, gravação ou qualquer operação que modifica os atributos do arquivo ou o conteúdo do diretório</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>Não permite nenhum tipo de acesso</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- Selecionar prioridade --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>Baixa</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>Alta</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>Últimos 5 minutos</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>Últimos 15 minutos</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>Últimos 30 minutos</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>Última 1 hora (Padrão)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>Últimas 3 horas</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>Últimas 6 horas</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>Últimas 12 horas</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>Últimas 24 horas</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>Ontem</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>Hoje</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>Até agora hoje</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>Antes de ontem</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>Últimos 2 dias</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>Este dia na semana passada</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>Semana anterior</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>Esta semana</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>Até agora nesta semana</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>Últimos 7 dias</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>Mês anterior</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>Este mês</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>Até agora neste mês</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>Últimos 30 dias</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>Últimos 90 dias</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>Últimos 6 meses</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>Último ano</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>Ano anterior</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>Este ano</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>Até agora neste ano</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>Últimos 2 anos</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>Últimos 5 anos</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>Informações</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>Nenhum item selecionado.</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>Desmarcar item para selecionar novamente</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>Limite de seleção atingido</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>Tags de filtro</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>Adicionar selo</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>Não há itens disponíveis.</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>Adicionar</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>Clonar</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>Copiar</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>Remoção Profunda</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>Destruir</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>Nivelar</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>Marcar como Inativo</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>Marcar como Entrada</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>Marcar como Perdido</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>Marcar como Saída</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>Proteger</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>Renomear</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>Restaurar</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>Mover para Lixo</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>Cancelar proteção</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>Excluído</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>Clonado</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>Copiado</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>Sim</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>Não</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>Qualidade do Serviço</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>Limite de BPS</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>O limite de bytes por segundo de E/S desejado.</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>Limite de IOPS</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>O limite de operações por segundo de E/S desejado.</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>Limite de BPS de Leitura</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>O limite de bytes por segundo de leitura desejado.</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>Limite de IOPS de Leitura</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>O limite de operações por segundo de leitura desejado.</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>Limite de BPS de Gravação</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>O limite de bytes por segundo de gravação desejado.</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>Limite de IOPS de Gravação</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>O limite de operações por segundo de gravação desejado.</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>Intermitência de BPS</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>O limite de bytes de E/S de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>Intermitência de IOPS</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>O limite de operações de E/S de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>Intermitência de BPS de Leitura</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>O limite de bytes de leitura de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>Intermitência de IOPS de Leitura</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>O limite de operações de leitura de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>Intermitência de BPS de Gravação</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>O limite de bytes de gravação de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>Intermitência de IOPS de Gravação</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>O limite de operações de gravação de intermitência desejado.</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>Falha ao
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>Executando</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>executar</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>Executado</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>tarefa desconhecida</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>Criando</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>criar</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>Atualizando</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>atualizar</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>Excluindo</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>excluir</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>Instantâneo do RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>modo de espelho para o pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>espelhar peer para o pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>Nome já foi usado por
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>Nome já foi usado por
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>Nome já foi usado por
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contém instantâneos.
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>Clonando</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>clonar</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>O instantâneo de
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> deve ser protegido.
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>Copiando</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>copiar</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>Nivelando</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>nivelar</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>Nivelado</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>Nome já foi usado por
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>Impossível cancelar a proteção de
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque há imagens filho.
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>Impossível excluir
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> porque está protegido.
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>Fazendo rollback</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>rollback</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>Rollback feito</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>Movendo</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>mover</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>Movido</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>imagem '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' para jogar no lixo
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>Imagem não encontrada.</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>Restaurando</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>restaurar</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>Restaurado</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>imagem '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' para '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>Nome da imagem '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' já está em uso.
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>imagem '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>Purgando</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>purgar</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>Purgado</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>todos os pools</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>imagens de
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>Impossível desabilitar espelhamento porque ele contém um peer.</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>perfil de código de eliminação '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>destino '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-CN.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-CN.xlf
new file mode 100644
index 00000000..1184122b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-CN.xlf
@@ -0,0 +1,4365 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="zh-CN">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>切换导航</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>仪表盘</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>集群</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>主机</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>Monitor</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>配置项</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSH 索引</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>Manager 扩展模块</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>日志</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>警告</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>存储池</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>块设备</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>映像</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>镜像</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>文件系统</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>对象网关</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>守护进程</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>用户</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>存储桶</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>关于
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> 的数据,正为
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>获取中,请稍候...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>关于之前缓存的数据
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>,正为
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>显示。
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>关于数据
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> ,无法为
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>加载。
+ 请检查集群的健康状况。
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>返回</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>请选择语言</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>正在加载面板的相关数据…</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>关于如何配置以及打开监控功能,
+请参阅
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文档
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>无 Grafana 仪表盘。关于如何为 Grafana 添加
+仪表盘,请参考
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文档
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 。
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Grafana 时间选择工具</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>重新设置</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>无法加载数据。</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>选中个数</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>命中个数</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>总数</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>编辑</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>名称</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>解释</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>更详尽的解释</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>缺省值</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>守护进程的缺省值</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>对应的服务</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>可选值</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>设置的值太大了!应低于
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>设置的值太小了!不能低于
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>保存</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>检查 CRUSH 索引图</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>主机列表</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>总体性能</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>无法找到相关条目</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>集群日志</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>审计日志</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>正在加载相关配置信息...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>配置信息无法加载。</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>编辑 Manager 扩展模块</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>输入值不是有效的 UUID,如:67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>输入的应该是个有效的 IP 地址。</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>请填写此栏目!</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>输入值过大!必须小于或等于
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>输入值过小!必须大于或等于
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>输入须为数字。</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>输入的应该是一个浮点数或者十进制整数。</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>状态</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>集群 ID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmap 修改时间</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmap epoch</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con </target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>required con</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>required mon</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>仲裁成员</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>非仲裁成员</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>取消</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>您确定要
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>选中的
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>吗?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>是的,我确定。</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>集群范围的 OSD 标志</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>提交</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>高级设置…</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>OSD 恢复优先级</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>优先级</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>自定义优先级</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>这个字段是必填的!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>输入值过大!不能大于
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>输入值过小!不能小于
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>重新设置 OSD 的权重</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>权重值必须在 0 和 1 之间</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>重设权重</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>洗刷
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {深度}}</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>即将对 OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>执行
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/> 洗刷。
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {深度} }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>OSD 列表</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>如果继续,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+将被标记为
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>OSD 不安全,无法销毁!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>如果继续,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+将被
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>详情</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>值</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>关闭</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>删除</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>健康状况</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>统计数据</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>关于如何配置和启用 NFS Ganesha 管理功能,
+请参考
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文档
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>客户端</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>任何客户端均可访问</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>地址</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>必填项</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>必须包含一个或多个逗号分隔值</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>例如:</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>访问类型</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>添加客户端</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>正在加载…</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- 无可用集群 --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- 请选择一个集群 --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>添加守护进程</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>存储后端</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- 没有可用的数据存储池 --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- 请选择存储后端 --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>对象网关用户</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- 无可选用户 --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- 请选择对象网关用户 --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFS 用户 ID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- 无可用客户端 --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- 请选择 cephx 客户端 --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>CephFS 名称</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>安全标签</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>启用安全标签</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFS 路径</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>路径需以“/”开头,后面可跟单词</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>将创建新文件夹</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>路径</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>路径只能是单个“/”或单词</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>将创建新的桶</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFS 协议</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFS 标签</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 装入的备用访问(不得包含前置 /)。
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>客户端不能装入子目录(即如果标记为 foo,则客户端无法装入 foo/baz)。</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>通过使用不同标记选项,可将同一路径导出多次。</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>伪</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>此
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 导出在
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>伪文件系统
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>中
+ 所占用的位置(必须唯一)。
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>通过使用不同伪选项,可将同一路径导出多次。</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- 没有可用的访问类型 --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- 选择访问类型 --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- 没有可用的 squash --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- 选择执行哪种类型的用户 ID 匿名访问 --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>传输协议</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>欢迎使用 Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>请输入用户名</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>请输入密码</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>登录</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>抱歉,此用户不存在。</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>返回
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>登录页
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。您将在重新登录时从身份提供程序注销。
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>禁止访问</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>抱歉,您无权访问这个页面。</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>抱歉,我们找不到您要看的东西。</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>全部已读</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>最新的通知</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>没有后台任务正在执行。</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>后台任务</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>帮助</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>文档</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>关于</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>仪表盘设置</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>用户管理</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>登录的用户</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>以用户名
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+进行登录
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>登出</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>名称…</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>所选名称已经被使用。</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>描述…</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>权限</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>角色</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>用户名</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>密码</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>确认密码</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>密码和之前的输入不匹配。</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>全名</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>邮箱</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>邮箱地址无效。</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>您即将取消您自己用户的 "user read / update" 权限。</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>如果您继续的话,您以后就没办法为其他用户添加或者删除角色了。</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>您确实要继续吗?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>无法读取性能计数器</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>OSD map</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>元数据不可用</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>相关元数据</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>性能计数器</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>直方图不可用:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>写入请求</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>读取请求</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>直方图</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>性能详情</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>当前值</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>类型</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>下限</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>上限</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>标志</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>来源</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>级别</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>可在运行时更新(可编辑)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>标记</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>可选项</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>参见</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>集群状态</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>manager 守护进程</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>对象网关</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>metadata 服务器</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI 网关</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>客户端 IOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>客户端吞吐量</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>客户端读/写</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>恢复吞吐量</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>洗刷</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>性能</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>基本容量</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>对象数</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>每个 OSD 的 PG 数</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>PG 状态</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>容量</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>查看
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>日志
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>以获得更多细节。
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>排位</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>客户端:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>将映像移至回收站</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>要将
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>移至回收站,
+ 请点击
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>移动映像
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。此外,可选择设置一个过期时间。
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>保护期一直到</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>无保护</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>日期格式有问题。请使用“YYYY-MM-DD HH:mm:ss”。</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>保护期限已经过了。请设置一个将来的日期,或者清空不填。</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>移动映像</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>概览</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>目标</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>发现身份验证</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>用户</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>用户名长度必须在 8 到 64 个字符之间,且只能包含
+以下字符:英文字母、“.”、“@”、“-”、“_”或“:”。</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>互认证用户</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>互认证密码</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>关于如何配置和启用 iSCSI 目标管理功能,
+请参考
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文档
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>可用信息:</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>无可用 iSCSI 目标</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>只对启动了
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 功能的 RBD 映像可用
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>存储池</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>数据存储池</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>创建</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>容量</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>对象大小</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>特性</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>供给容量</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>N/A</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>总供给容量</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>条带单元</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>条带个数</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>父节点</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>块存储名字前缀</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>order</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>快照</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>映像</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>此设置会覆盖全局值</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>全局</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>该值为全局值。没有为此映像设置此选项的值。</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>不允许使用“/”和“@”。</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- 没有可用的 RBD 存储池 --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- 请选择存储池 --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>使用一个专用的数据池</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>数据池</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>为保存 RBD 的对象数据单独分配的存储池。</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>如 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>您需要设置大一些的容量。</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>高级设置</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>条带</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>条带单元大小</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- 选择条带单元大小 --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>因为设置了条带个数,所以这个字段是必选的!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>条带单元大小超过了对象大小。</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>条带个数</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>因为设置了条带单元大小,所以这个字段是必选的!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>条带的个数必须大于 0。</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>RBD 快照
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {改名} other {创建} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>快照
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>受保护的</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>无保护的</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>您即将进行回滚操作</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>清空回收站</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>要彻底清空的话,请选择单个或所有的映像,然后点击</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>存储池:</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>存储池名称…</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>全选</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>恢复映像</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>要恢复</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>输入映像的新名称,并点击</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>新名称</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>过期时间</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>保护期限</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>一直到
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>,该映像都会受保护。
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>回收站</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>iSCSI 结构图</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>通常无须改变这些默认参数值。</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>设置</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>后备存储</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>确认</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>高级设置</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>目标限定名</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN 格式错误。</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQN 应由以下格式构成:“iqn.$year-$month.$reversedAddress:$definedName”</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>例如:iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>更多信息</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>此目标的高级设置项存在修改。</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>端口</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>至少需要
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> 个网关。
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>添加端口</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>此映像的设置项存在修改。</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>添加映像</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL 身份验证</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>授权人</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>授权人</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>客户端 IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>授权人 IQN 必须唯一。</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>用户名长度必须在 8 到 64 个字符之间,且只能包含
+以下字符:英文字母、“.”、“@”、“-”、“_”或“:”。</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>授权人属于群组。映像须在群组中进行设置。</target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>无项目添加。</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>添加授权人</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>群组</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>群组</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>添加群组</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>RBD 配置</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>删除本地的配置项,改用更高作用域的配置值。</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>最小值为 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>问题</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>正在同步</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>已就绪</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>编辑存储池镜像模式</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>要编辑存储池
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 
+ 的镜像模式,请从列表中选择一项,并点击 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>更新
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>模式</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>在禁用镜像功能前必须先移除同伴集群。</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+存储池镜像同伴
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {编辑} other {添加} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>存储池
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>
+ 的存储池镜像同伴属性,并点击
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>提交
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>集群名称</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>集群名称无效。</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>CephX ID 无效。</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>Monitor 地址</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>逗号分割的地址...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>Monitor 地址无效。</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX 密钥</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64 编码的密钥...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>CephX 密钥必须是 base64 编码的。</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>存储池列表</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>名称只能由字母、数字、短划线和下划线组成。</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>此纠删码配置名称已被使用。</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>纠删码算法</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>数据块 (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>必须大于等于 2</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>校验块 (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>必须大于等于 1</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>持久因子 (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>局部性因子 (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>CRUSH 故障域</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>CRUSH 局部性</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>无</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>算法</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>packetsize</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>CRUSH 根</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>CRUSH 设备类型</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>任意</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>目录</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>此 Ceph 存储池名称已被使用。</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>存储池类型</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- 请选择存储池的类型 --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>归置组 (PG)</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>至少需要一个归置组!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>您的集群没法支持这么多的 PG。请重新计算需要的 PG 个数。</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>在线 PG 计算器</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>已根据当前情况为您推算出了 PG 的设置,您
+最好在提交之前确认这些设置是合适的。</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>CRUSH 算法规则组</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- 选择 CRUSH 规则 --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>CRUSH 规则</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>CRUSH 步骤</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>当前的集群无法使用该规则,因为集群的 OSD 个数过少,
+ 无法满足规则所需的最低 OSD 数量。</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>副本个数</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>最低:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>最高:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>设置的超过了限制。设置值应该在
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> 和
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> 中间为宜.
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>纠删码配置</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- 无纠删码配置可选 --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- 请选择一个纠删码配置 --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC 重写 (overwrite)</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>应用类型</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>压缩</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>算法</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- 无可用的纠删码压缩算法 --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>blob 大小下限</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>比如 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>取值必须大于 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>blob 大小上限</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>如 512KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>取值必须大于 blob 大小下限</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>比例</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>压缩率</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>取值必须在 0.0 和 1.0 之间</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>无法新建名字中有“/”的 RBD 存储池。</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>请重新命名,或者把存储池的“rbd”应用标记去掉。</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>缓存层详细信息</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>关于如何配置和启用对象网关的功能,
+ 请参考
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文档
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> 。
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>守护进程列表</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>性能计数器</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>正在加载存储桶数据…</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>存储桶数据无法加载。</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>输入值无效。</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>所有者</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- 请选择一个用户 --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>索引类型</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>归置规则</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>标识</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>max marker</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>版本</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>主版本</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>修改时间</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>zonegroup</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>存储桶配额</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>开启</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>最大数目</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>无限制</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>最大对象数目</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- 请选择用户名 --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>自动生成密钥</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>访问密钥</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>秘密密钥</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>邮箱</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>冻结</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>系统</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {否} 1 {是} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>最大存储桶数目</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>子用户</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>用户权限</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>用户配额</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>显示</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>密钥</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- 请选择一个类型 --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>权限</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- 请选择权限类型 --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>子用户</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>所选的子用户 ID 已被使用。</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>读、写</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>全部</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Swift 密钥</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>自动生成密钥</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>正在加载用户数据…</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>用户数据无法加载。 </target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>所选的用户 ID 已被使用。</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>无效的邮箱地址。</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>此邮箱地址已被使用。</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>存储桶个数的上限</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>设置的值必须 &gt;= 0。</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3 密钥</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>没有子用户。</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>没有任何密钥。</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>权限为空。</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>空间无限制</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>空间上限</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>对象个数无限制</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>对象个数上限</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>当前</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>已更新发现身份验证</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>无可用端口。</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>无可用映像。</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>无可用映像。请确保为目标添加一个映像。</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>无可用授权人。请确保为目标添加一个授权人。</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>目标</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>状态</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>读字节数</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>写字节数</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>读请求数</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>写请求数</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>活动/优化自</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>实例</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>主机名</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>问题</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>进度</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>禁用</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>编辑模式</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>添加 peer</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>编辑 peer</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>删除 peer</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Leader</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target># 本地</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target># 远程</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>镜像 peer</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>密钥</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>完全展开</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>分层</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>互斥锁</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>object map(要求互斥锁支持)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>日志(要求互斥锁支持)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>RBD 快照回滚</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>回滚</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>RBD 快照</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>定点删除</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>类型</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>状态</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>版本</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>主机</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>根</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>排位</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>守护进程</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>活跃度</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>dentries</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>inodes</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>使用率</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>备用服务</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>该值可在运行时更新。</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>服务器或客户端不会主动从 monitor 的配置数据库读取这个配置。
+ 所以不能用“ceph config set ...”设置它。但是可以通过
+ ceph.conf 或者用命令行进行配置。</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>该配置只有在服务启动的时候才会生效。</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>该配置只在创建集群的时候才会生效。</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>该配置只在服务创建的时候才会生效。</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>已更新配置选项
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>服务</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>当前值</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>可编辑</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>已更新扩展模块“
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>”的选项。
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>启用</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>禁用</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>正在重新连接,请稍候…</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>外部地址</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>活动会话</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>禁止加入</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>之前被除名的 OSD 在启动之后,不会被加入集群</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>禁止除名</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>在发现 OSD 没有响应之后一段时间,该 OSD 会被踢出集群。该标志会禁止这个功能。</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>禁止启用</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>不允许 OSD 启动</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>禁止停用</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>当前不受理对 OSD 的失效报告,因而 monitor 不会停用 OSD</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>暂停</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>暂停读写</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>禁止洗刷</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>洗刷已禁止</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>禁止深层洗刷</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>深层洗刷已禁止</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>禁止回填</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>PG 回填已推迟</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>禁止恢复</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>PG 恢复已推迟</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>逐位排序</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>使用逐位排序</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>老版本的快照已全部升级</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD 上的快照已全部转换完毕</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>在恢复时进行删除操作</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>在恢复时,而非对齐阶段进行删除</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>PG 日志硬限制</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>为 pg 日志长度添加硬限制</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>已更新 OSD 标志</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>除名</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>加入</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>停用</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>标记</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD 丢失</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>已标记丢失</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>清除</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>已清除</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>销毁</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>已销毁</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>PG</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>读字节数</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>写字节数</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>读请求数</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>写请求数</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>标记 OSD 为
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>标记为
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>最大回填量</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>最大活跃恢复请求数</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>最大单次恢复操作数</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>恢复/回填操作间隔睡眠时间</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>自定义</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>已更新 OSD 恢复速度优先级“
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>如下 OSD 已经启动了
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> 操作:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>任务</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>严重程度</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>已启动</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>更新完成</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>已使用</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>空闲</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>正常</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>运行中</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>警报</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>未知</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>启用中</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>无文件系统</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>工作</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>待机</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>n/a</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>工作的守护进程</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>NFS Ganesha 服务的配置还没有完成。</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>传输</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFS 用户</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>CephFS 文件系统</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(继承自全局配置)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>继承自全局配置</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- 选择执行哪种类型的用户 ID 匿名访问 --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>没有可用的守护进程。</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>缓存模式</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>最少延迟赶出时间</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>最少延迟刷回时间</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>目标器最大字节数</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>目标器最大对象数</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>还没有任何应用标记</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>应用标记到了上限</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>一个存储池最多能有四个应用标记。</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>可用的字符为“_a-zA-Z0-9”</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>长度限制为 128 个字符</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>添加应用标记或根据其进行筛选</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>添加应用标记</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>纠删码配置</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>副本个数</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>最后修改时间</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>纠删码配置</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>CRUSH 规则集</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>写字节数</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>存储桶</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>已更新对象网关存储桶“
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>已创建对象网关存储桶“
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>存储桶</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>用户</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>已更新对象网关用户“
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>已创建对象网关用户“
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>用户</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>作用范围</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>读权限</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>新建</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>新建角色“
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>更新角色“
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>系统角色</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>已删除角色“
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已新建用户“
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>更新用户</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>继续</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>您被自动登出,因为您的角色有了变动。</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已更新用户“
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已删除用户“
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>删除用户“
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>”失败
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>您当前在用“
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>”的身份登录。
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target> 各对象都被分割为数据块,分别存储于不同 OSD 。</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>计算各对象的编码块、并存储于不同 OSD 。
+编码块的数量等同于在不丢数据的前提下允许同时失效的 OSD 数量。</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>jerasure 插件是最通用、最灵活的插件,
+也是 Ceph 纠删码存储池的默认插件。</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>reed_sol_van 技术更灵活:它足以设置 k 和 m 值。
+cauchy_good 技术更快,但你得谨慎地选择 packetsize 值。
+reed_sol_r6_op 、 liberation 、 blaum_roth 、 liber8tion 都是与 RAID6 等价的技术,
+它们只能配置为 m=2 。</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target> 以 bytes 大小的包为单位进行编码。
+确定合适的包尺寸很难,
+jerasure 文档对此有很详细的描述。</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>用 jerasure 插件时,纠删码编码的对象存储在多个 OSD 上,
+丢失一个 OSD 的恢复过程需读取所有其他的 OSD 。
+比如 jerasure 的配置为 k=8 且 m=4 ,丢失一个 OSD 后需读取其他 11 个 OSD 才能恢复。
+
+lrc 纠删码插件创建的是局部校验块,这样只需较少的 OSD 即可恢复。
+比如 lrc 的配置为 k=8 、 m=4 且 l=4 ,它将为每四个 OSD 创建额外的校验块,
+当一个 OSD 丢失时,它只需四个 OSD 即可恢复,而不需要十一个。</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>把编码块和数据块分组为大小为 locality 的集合。
+比如, k=4 且 m=2 时,若设置 locality=3 ,将会分组为大小为三的两组,
+这样各组都能自行恢复,无需从另一组读数据块。</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>由 l 定义的块集合将按哪种 crush 桶类型存储。
+比如,若设置为 rack ,大小为 l 块的各组将被存入不同的机架,
+此值会被用于创建类似 step choose rack 的规则集。
+如果没设置,就不会这样分组。</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>isa 插件封装了 ISA 库。它只能运行在 Intel 处理器上。</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>ISA 插件包含两种 Reed Solomon 编码形式。
+设置为 reed_sol_van 表示用 Vandermonde 算法,设置为 cauchy 表示用 Cauchy 算法。</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>shec 插件封装了 multiple SHEC 库。
+与 Reed Solomon 编码相比,它能使 Ceph 更高效地恢复数据。</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target> 奇偶校验块数量,它们在各自的计算范围内包含了各数据块。
+此数值被用作持久性估值。
+例如,假设 c=2 ,就是说不丟数据的情况下可损失 2 个 OSD 。</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>规则集第一步所指向的 CRUSH 桶之名,
+如 step take default 。</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>确保两个编码块不会存在于同一故障域的桶里面。
+比如,假设故障域是 host ,就不会有两个编码块存储到同一主机;
+此值用于在规则集中创建类似 step chooseleaf host 的步骤。</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>使用 CRUSH 索引中的 crush 设备类名,
+将归置限制于特定类的设备(例如,ssd 或 hdd)。</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>设置纠删码插件所在目录。</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>允许所有操作</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>只允许不修改服务器端数据的操作</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>禁止读写,但是允许其他的操作</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>禁止读、写以及任何可能修改文件内容的操作</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>完全禁止访问</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- 选择优先级 --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>低</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>高</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>过去 5 分钟</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>过去 15 分钟</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>过去 30 分钟</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>过去 1 小时(默认)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>过去 3 小时</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>过去 6 小时</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>过去 12 小时</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>过去 24 小时</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>昨天</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>今天</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>今天到现在为止</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>前天</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>过去 2 天</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>上周的今天</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>上个星期</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>本周</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>本周以来</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>过去 7 天</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>上个月</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>当月</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>本月以来</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>过去 30 天</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>过去 90 天</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>过去 6 个月</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>过去 1 年</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>去年</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>今年</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>今年以来</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>过去 2 年</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>过去 5 年</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>信息</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>无选中项目。</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>取消选择</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>达到选择项数上限。</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>过滤标签</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>添加 badge</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>无可选项目。</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>添加</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>克隆</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>复制</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>深层洗刷</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>销毁</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>展开</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>标记为停用</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>标记为加入</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>标记为丢失</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>标记为已除名</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>保护</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>重命名</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>恢复</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>移至回收站</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>解除保护</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>删除完成</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>克隆完成</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>复制完成</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>是</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>否</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>服务质量 (QoS)</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>指定的每秒 IO 字节数上限。</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>指定的每秒 IO 操作次数上限。</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>读 BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>指定的每秒内读取的字节数上限。</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>读 IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>指定的每秒读操作次数上限。</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>写 BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>指定的每秒内写入的字节数上限。</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>写 IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>指定的每秒写操作次数上限。</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPS 突发</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>指定的 IO 字节数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPS 突发</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>指定的 IO 操作次数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>读 BPS 突发</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>指定的读取的字节数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>读 IOPS 突发</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>指定的读操作次数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>写 BPS 突发</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>指定的写入的字节数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>写 IOPS 突发</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>指定的写操作次数突发上限。</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>失败
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>正在执行</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>执行</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>执行完毕</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>未知任务</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>正在创建</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>创建</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>正在更新</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>正在删除</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>删除</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD 快照“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>存储池“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”的镜像模式
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>存储池“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”的镜像同伴
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>该名称已被
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>该名称已被
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>该名称已被
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>包含有快照。
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>正在克隆</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>克隆</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>的快照必须处于受保护状态。
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>正在复制</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>复制</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>正在展开</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>展开</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>展开完成</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>该名称已被
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>无法去掉
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>的保护状态,因为它有子映像。
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>无法删除
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>,因为它处于受保护状态。
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>正在回滚</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>回滚</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>回滚完成</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>正在把</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>把</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>已经把</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>映像“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”移至回收站
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>无法找到映像。</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>正在把</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>把</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>已经把</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>映像从“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”恢复到“
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>映像名称“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”已被使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>映像“
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>正在清除</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>清除</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>已清除</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>所有存储池</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>里的映像
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>因为包含同伴集群,无法禁用镜像功能</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>存储池“
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>纠删码配置“
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>目标器“
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>”
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-TW.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-TW.xlf
new file mode 100644
index 00000000..0134f8bc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.zh-TW.xlf
@@ -0,0 +1,4371 @@
+<xliff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd" xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
+ <file original="ng2.template" datatype="plaintext" source-language="en-US" target-language="zh-TW">
+ <body>
+ <trans-unit id="319e0745bcbc132451569294fa2fa21bf10f555a" datatype="html">
+ <source>Toggle navigation</source>
+ <target>切換導覽</target>
+ </trans-unit>
+ <trans-unit id="f65253954b66e929a8b4d5ecaf61f9129f8cec64" datatype="html">
+ <source>Dashboard</source>
+ <target>儀表板</target>
+ </trans-unit>
+ <trans-unit id="f4d1dd59b039ad818d9da7e29a773e10e41d9821" datatype="html">
+ <source>Cluster</source>
+ <target>叢集</target>
+ </trans-unit>
+ <trans-unit id="099b441d49333b3c6d30b36dc0a4763e64c78920" datatype="html">
+ <source>Hosts</source>
+ <target>主機</target>
+ </trans-unit>
+ <trans-unit id="624f596cc3320f5e0a0d7c7346c364e5af9bdd8c" datatype="html">
+ <source>Monitors</source>
+ <target>監控程式</target>
+ </trans-unit>
+ <trans-unit id="1a9183778f2c6473d7ccb080f651caa01faaf70c" datatype="html">
+ <source>OSDs</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4a41f824a35ba01d5bd7be61aa06b3e8145209d0" datatype="html">
+ <source>Configuration</source>
+ <target>組態</target>
+ </trans-unit>
+ <trans-unit id="8c95898abff46bfac3ed6eb2afef74597e60b15c" datatype="html">
+ <source>CRUSH map</source>
+ <target>CRUSH 地圖</target>
+ </trans-unit>
+ <trans-unit id="33da4dbeb076159510801ea764a218fd341269d2" datatype="html">
+ <source>Manager modules</source>
+ <target>管理員模組</target>
+ </trans-unit>
+ <trans-unit id="eb3d5aefff38a814b76da74371cbf02c0789a1ef" datatype="html">
+ <source>Logs</source>
+ <target>記錄</target>
+ </trans-unit>
+ <trans-unit id="9fe218829514884cdd0ca2300573a4e0428c324f" datatype="html">
+ <source>Alerts</source>
+ <target>警示</target>
+ </trans-unit>
+ <trans-unit id="aa0c44aa1e5727061baa91e954f77e2f5f9a37c9" datatype="html">
+ <source>Silences</source>
+ <target>Silences</target>
+ </trans-unit>
+ <trans-unit id="92899fa68e8ca108912163ff58edc8540e453787" datatype="html">
+ <source>Pools</source>
+ <target>池</target>
+ </trans-unit>
+ <trans-unit id="7f5d0c10614e8a34f0e2dad33a0568277c50cf69" datatype="html">
+ <source>Block</source>
+ <target>區塊</target>
+ </trans-unit>
+ <trans-unit id="b73f7f5060fb22a1e9ec462b1bb02493fa3ab866" datatype="html">
+ <source>Images</source>
+ <target>影像</target>
+ </trans-unit>
+ <trans-unit id="3c2562ba992127203dcfd014010b03cb7b8113c6" datatype="html">
+ <source>Mirroring</source>
+ <target>鏡像</target>
+ </trans-unit>
+ <trans-unit id="811c241d56601b91ef26735b770e64428089b950" datatype="html">
+ <source>iSCSI</source>
+ <target>iSCSI</target>
+ </trans-unit>
+ <trans-unit id="a24eabd99ea5af20f5f94c4484649cd30370042b" datatype="html">
+ <source>NFS</source>
+ <target>NFS</target>
+ </trans-unit>
+ <trans-unit id="a4eff72d97b7ced051398d581f10968218057ddc" datatype="html">
+ <source>Filesystems</source>
+ <target>檔案系統</target>
+ </trans-unit>
+ <trans-unit id="2190548d236ca5f7bc7ab2bca334b860c5ff2ad4" datatype="html">
+ <source>Object Gateway</source>
+ <target>物件閘道</target>
+ </trans-unit>
+ <trans-unit id="9e24f9e2d42104ffc01599db4d566d1cc518f9e6" datatype="html">
+ <source>Daemons</source>
+ <target>精靈</target>
+ </trans-unit>
+ <trans-unit id="4d13a9cd5ed3dcee0eab22cb25198d43886942be" datatype="html">
+ <source>Users</source>
+ <target>使用者</target>
+ </trans-unit>
+ <trans-unit id="9515520496da83179d8b08132f00f575512a1f40" datatype="html">
+ <source>Buckets</source>
+ <target>桶</target>
+ </trans-unit>
+ <trans-unit id="797f8214e8148f4bf0d244baaa7341706b419549" datatype="html">
+ <source>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </source>
+ <target>Retrieving data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>. Please wait...
+ </target>
+ </trans-unit>
+ <trans-unit id="5a870dc77b9f6f33ee671ea2d856021276933339" datatype="html">
+ <source>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </source>
+ <target>Displaying previously cached data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/>
+ for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="ae580202919844531361ba2308287226ff74a584" datatype="html">
+ <source>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </source>
+ <target>Could not load data
+ <x id="START_TAG_SPAN_1" ctype="x-span" equiv-text="<span>"/> for
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>.
+ Please check the cluster health.
+ </target>
+ </trans-unit>
+ <trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
+ <source>Back</source>
+ <target>返回</target>
+ </trans-unit>
+ <trans-unit id="3fb5709e10166cbc85970cbff103db227dbeb813" datatype="html">
+ <source>Select a Language</source>
+ <target>選取語言</target>
+ </trans-unit>
+ <trans-unit id="c5109325fb160b543f71a51e7511c00575057431" datatype="html">
+ <source>Loading panel data...</source>
+ <target>正在載入面板資料...</target>
+ </trans-unit>
+ <trans-unit id="8ca12411f890ab8b0a9216418e2b8f5ea7d2441a" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ configure and enable the monitoring functionality.
+ </source>
+ <target>如需了解如何設定和啟用監控功能,
+ 請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文件
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="160a9e80dc089792df42e2400b1e81b9e7025aa7" datatype="html">
+ <source>Grafana Dashboard doesn't exist. Please refer to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> on how to
+ add dashboards to Grafana.
+ </source>
+ <target>Grafana 儀表板不存在。如需了解
+ 如何向 Grafana 新增儀表板,
+ 請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文件
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="4e11830040bd64804a0555de76f291d5832772d4" datatype="html">
+ <source>Grafana Time Picker</source>
+ <target>Grafana 時間選擇器</target>
+ </trans-unit>
+ <trans-unit id="238c1ba845dd7330e8088165275919a1debf1ca3" datatype="html">
+ <source>Reset Settings</source>
+ <target>重設設定</target>
+ </trans-unit>
+ <trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <target>Refresh</target>
+ </trans-unit>
+ <trans-unit id="6c947210e2d162b6225083d18820ab602f58cd2d" datatype="html">
+ <source>Remove the custom configuration value. The default configuration will be inherited and used instead.</source>
+ <target>Remove the custom configuration value. The default configuration will be inherited and used instead.</target>
+ </trans-unit>
+ <trans-unit id="454ee9cb60b00446a8fb147fd2cc5eb836320586" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </source>
+ <target>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ option.maxValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="7fc8a22825131e028336f60ef909ccbd96059703" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </source>
+ <target>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ option.minValue }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
+ <source>Failed to load data.</source>
+ <target>無法載入資料。</target>
+ </trans-unit>
+ <trans-unit id="80cc9a12d4bf6fe454ed94b379eeaf915f920bb7" datatype="html">
+ <source>selected</source>
+ <target>選取的數目</target>
+ <note>X selected</note>
+ </trans-unit>
+ <trans-unit id="0cb77511a9a148e05b9adf36cc07269956fbb29d" datatype="html">
+ <source>found</source>
+ <target>找到的數目</target>
+ <note>X found</note>
+ </trans-unit>
+ <trans-unit id="79347388740c50b7ac97e144c2494bb62912f312" datatype="html">
+ <source>total</source>
+ <target>總計</target>
+ <note>X total</note>
+ </trans-unit>
+ <trans-unit id="28f86ffd419b869711aa13f5e5ff54be6d70731c" datatype="html">
+ <source>Edit</source>
+ <target>編輯</target>
+ </trans-unit>
+ <trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
+ <source>Name</source>
+ <target>名稱</target>
+ </trans-unit>
+ <trans-unit id="eec715de352a6b114713b30b640d319fa78207a0" datatype="html">
+ <source>Description</source>
+ <target>描述</target>
+ </trans-unit>
+ <trans-unit id="4ad112ce9bcd55dfd137792a86afe1b5a5b13cf8" datatype="html">
+ <source>Long description</source>
+ <target>詳細描述</target>
+ </trans-unit>
+ <trans-unit id="ff7cee38a2259526c519f878e71b964f41db4348" datatype="html">
+ <source>Default</source>
+ <target>預設值</target>
+ </trans-unit>
+ <trans-unit id="33e1c1d9fc05ca3f62fcc8a1170fc31ebae4229c" datatype="html">
+ <source>Daemon default</source>
+ <target>精靈預設值</target>
+ </trans-unit>
+ <trans-unit id="419d940613972cc3fae9c8ea0a4306dbf80616e5" datatype="html">
+ <source>Services</source>
+ <target>服務</target>
+ </trans-unit>
+ <trans-unit id="809b0c848932a41318f77a2aace904ef429c13f4" datatype="html">
+ <source>Values</source>
+ <target>值</target>
+ </trans-unit>
+ <trans-unit id="82029b6db704c56a2aa3e82ac555b8655356b077" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>.
+ </source>
+ <target>輸入的值太高!該值不得大於
+ <x id="INTERPOLATION" equiv-text="{{ maxValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="8ed8b3967a7326b81b191c9f490006e6a6777a9a" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>.
+ </source>
+ <target>輸入的值太低!該值不得小於
+ <x id="INTERPOLATION" equiv-text="{{ minValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="52c9a103b812f258bcddc3d90a6e3f46871d25fe" datatype="html">
+ <source>Save</source>
+ <target>儲存</target>
+ </trans-unit>
+ <trans-unit id="738de688b22fba5d0dc7a5e549996838dddad0ee" datatype="html">
+ <source>CRUSH map viewer</source>
+ <target>CRUSH 地圖檢視器</target>
+ </trans-unit>
+ <trans-unit id="40661476cb24c89d8b06614998e31d5fbe84eeb6" datatype="html">
+ <source>Hosts List</source>
+ <target>主機清單</target>
+ </trans-unit>
+ <trans-unit id="5e7f4b1ca49e8d217bd0e12c6f7d6b6a2ade2c18" datatype="html">
+ <source>Overall Performance</source>
+ <target>整體效能</target>
+ </trans-unit>
+ <trans-unit id="e6d57f36aa2bad303c8a8ee944b9bd7fae3c8c26" datatype="html">
+ <source>No entries found</source>
+ <target>找不到項目</target>
+ </trans-unit>
+ <trans-unit id="d556ab48a65722b400e497f61737f553ee0f89e2" datatype="html">
+ <source>Cluster Logs</source>
+ <target>叢集記錄</target>
+ </trans-unit>
+ <trans-unit id="5f966baffd188be0e8adc2d7067b86e55fc9b9de" datatype="html">
+ <source>Audit Logs</source>
+ <target>稽核記錄</target>
+ </trans-unit>
+ <trans-unit id="4193c9eb868aeec119b78a14795241e0aa5e8b60" datatype="html">
+ <source>Priority:</source>
+ <target>Priority:</target>
+ </trans-unit>
+ <trans-unit id="1d78ca51eab260ce3fd917d39190d64df5229b6e" datatype="html">
+ <source>Keyword:</source>
+ <target>Keyword:</target>
+ </trans-unit>
+ <trans-unit id="05fa0bded36de6e73a1fa44838b627349dace044" datatype="html">
+ <source>Date:</source>
+ <target>Date:</target>
+ </trans-unit>
+ <trans-unit id="31dadb362bf7f7c2afa10e5f96474ccd3977f91f" datatype="html">
+ <source>Datepicker</source>
+ <target>Datepicker</target>
+ </trans-unit>
+ <trans-unit id="85a400388de1899b1917138cf7e5286376f72847" datatype="html">
+ <source>Time range:</source>
+ <target>Time range:</target>
+ </trans-unit>
+ <trans-unit id="2447796ddbda942f4e2c46619cb84d69f066e568" datatype="html">
+ <source>Loading configuration...</source>
+ <target>正在載入組態...</target>
+ </trans-unit>
+ <trans-unit id="b42c0b347a841bed8859ee83de05080ee28c803b" datatype="html">
+ <source>The configuration could not be loaded.</source>
+ <target>無法載入組態。</target>
+ </trans-unit>
+ <trans-unit id="31a9c2870a934b594d1390146c489f76440859ea" datatype="html">
+ <source>Edit Manager module</source>
+ <target>編輯管理員模組</target>
+ </trans-unit>
+ <trans-unit id="46e09b8290d3d0afdb6baa2021395b0570606a31" datatype="html">
+ <source>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</source>
+ <target>輸入的值不是有效的 UUID,例如 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</target>
+ </trans-unit>
+ <trans-unit id="7aacd038b39cfd347107d01d1dc27f5cb3e0951c" datatype="html">
+ <source>The entered value needs to be a valid IP address.</source>
+ <target>輸入的值必須是有效的 IP 位址。</target>
+ </trans-unit>
+ <trans-unit id="7cbdabcece469fab89cfa687ab152bca18b97498" datatype="html">
+ <source>This field is required.</source>
+ <target>此欄位為必填欄位。</target>
+ </trans-unit>
+ <trans-unit id="f19106149f4b07a0d721f9d317afed393cb7bd93" datatype="html">
+ <source>The entered value is too high! It must be lower or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>.
+ </source>
+ <target>輸入的值太高!該值必須小於或等於
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.max }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="6d33c40ef9a6c3bf0888df831b25e41e65f9d15b" datatype="html">
+ <source>The entered value is too low! It must be greater or equal to
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>.
+ </source>
+ <target>輸入的值太低!該值必須大於或等於
+ <x id="INTERPOLATION" equiv-text="{{ moduleOption.value.min }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="eae7086660cf1e38c7194a2c49ff52cc656f90f5" datatype="html">
+ <source>The entered value needs to be a number.</source>
+ <target>輸入的值必須為數字。</target>
+ </trans-unit>
+ <trans-unit id="a73376e04b4fb3a20734c8c39743fba32e6676ce" datatype="html">
+ <source>The entered value needs to be a number or decimal.</source>
+ <target>輸入的值必須為數字或小數。</target>
+ </trans-unit>
+ <trans-unit id="047f50bc5b5d17b5bec0196355953e1a5c590ddb" datatype="html">
+ <source>Update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="81b97b8ea996ad1e4f9fca8415021850214884b1" datatype="html">
+ <source>Status</source>
+ <target>狀態</target>
+ </trans-unit>
+ <trans-unit id="57ec6032f5618d4a9f16eb950ad23d2ce7c24b54" datatype="html">
+ <source>Cluster ID</source>
+ <target>叢集 ID</target>
+ </trans-unit>
+ <trans-unit id="67d7facc3fec5f8a49ab9ba0a245872184264ce5" datatype="html">
+ <source>monmap modified</source>
+ <target>monmap 修改時間</target>
+ </trans-unit>
+ <trans-unit id="d4906731aaf2b94b4f547646c9bfe58bb77951b6" datatype="html">
+ <source>monmap epoch</source>
+ <target>monmap 版本編號</target>
+ </trans-unit>
+ <trans-unit id="bd4ee06ffdc46d9dfbd0c0c4f81399021c680056" datatype="html">
+ <source>quorum con</source>
+ <target>quorum con</target>
+ </trans-unit>
+ <trans-unit id="1176c7db8a8276ccb44cc3d42e2c28d9fa6c6596" datatype="html">
+ <source>quorum mon</source>
+ <target>quorum mon</target>
+ </trans-unit>
+ <trans-unit id="530ef677a09d681b3ab68cb0760494b3ae72a77c" datatype="html">
+ <source>required con</source>
+ <target>required con</target>
+ </trans-unit>
+ <trans-unit id="a91558e0d506c32021c31843f8f168899fc65cbf" datatype="html">
+ <source>required mon</source>
+ <target>required mon</target>
+ </trans-unit>
+ <trans-unit id="b3abe9eac5bcd94a54c8da93b312e085ec512e74" datatype="html">
+ <source>In Quorum</source>
+ <target>仲裁成員</target>
+ </trans-unit>
+ <trans-unit id="ba4b748a676e1f217ce1e736fb7ec1215e677bae" datatype="html">
+ <source>Not In Quorum</source>
+ <target>非仲裁成員</target>
+ </trans-unit>
+ <trans-unit id="d7b35c384aecd25a516200d6921836374613dfe7" datatype="html">
+ <source>Cancel</source>
+ <target>取消</target>
+ </trans-unit>
+ <trans-unit id="6110699a3562eeb15371063c0cf7f6bfd88a0209" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ itemNames[0] }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>?
+ </target>
+ </trans-unit>
+ <trans-unit id="549859e511ba5af0ea03fcaa620c472f08038969" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </source>
+ <target>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected items?
+ </target>
+ </trans-unit>
+ <trans-unit id="54839ebc827b73c9dc4e1df731c6d36a85036af7" datatype="html">
+ <source>Are you sure that you want to
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/> the selected
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>?
+ </source>
+ <target>確定要
+ <x id="INTERPOLATION" equiv-text="{{ actionDescription | lowercase }}"/>選取的
+ <x id="INTERPOLATION_1" equiv-text="{{ itemDescription }}"/>嗎?
+ </target>
+ </trans-unit>
+ <trans-unit id="2be8b7f04f0104d3fad90d079d8202b74f758b9a" datatype="html">
+ <source>Yes, I am sure.</source>
+ <target>是的,我確定。</target>
+ </trans-unit>
+ <trans-unit id="5ef50ba2514414f799d4c8fc36067a251904ba81" datatype="html">
+ <source>Cluster-wide OSD Flags</source>
+ <target>叢集範圍的 OSD 旗標</target>
+ </trans-unit>
+ <trans-unit id="71c77bb8cecdf11ec3eead24dd1ba506573fa9cd" datatype="html">
+ <source>Submit</source>
+ <target>提交</target>
+ </trans-unit>
+ <trans-unit id="formTitle" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form title</note>
+ </trans-unit>
+ <trans-unit id="1cfe07dac5b4ee1c464eb24225ddeb4f1d24076a" datatype="html">
+ <source>Advanced...</source>
+ <target>進階...</target>
+ </trans-unit>
+ <trans-unit id="b1ef1c12ddcee305353623919ef02778569f5454" datatype="html">
+ <source>Advanced configuration options</source>
+ <target>Advanced configuration options</target>
+ </trans-unit>
+ <trans-unit id="formActionButton" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ resource | upperFirst }}"/>
+ </target>
+ <note>form action button</note>
+ </trans-unit>
+ <trans-unit id="c35f9c5f268a514b970cc55e9a5dc4bed0988e7f" datatype="html">
+ <source>OSD Recovery Priority</source>
+ <target>OSD 復原優先程度</target>
+ </trans-unit>
+ <trans-unit id="b74af38005e8a8914e45af2ec412e11ceafef8b6" datatype="html">
+ <source>Priority</source>
+ <target>優先程度</target>
+ </trans-unit>
+ <trans-unit id="c2f48f04b379bfba133825747adfd238d511412e" datatype="html">
+ <source>Customize priority values</source>
+ <target>自訂優先程度值</target>
+ </trans-unit>
+ <trans-unit id="4aa19de2a2b54cbda39e9c62917b23044c087776" datatype="html">
+ <source>This field is required!</source>
+ <target>此欄位為必填欄位!</target>
+ </trans-unit>
+ <trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.
+ </source>
+ <target>輸入的值太高!該值不得大於
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.
+ </source>
+ <target>輸入的值太低!該值不得小於
+ <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
+ <source>Reweight OSD</source>
+ <target>重新設定 OSD 的權數</target>
+ </trans-unit>
+ <trans-unit id="67650b2998db48201b2c6176cbfef51e7211ccaa" datatype="html">
+ <source>The value needs to be between 0 and 1.</source>
+ <target>該值必須介於 0 至 1 之間。</target>
+ </trans-unit>
+ <trans-unit id="bc11f92113d678a90e334fdf3d7b3fddbe34c579" datatype="html">
+ <source>Reweight</source>
+ <target>重新設定權數</target>
+ </trans-unit>
+ <trans-unit id="d5ca5daf742023fc4f0919fb3c1c6a51991cda4f" datatype="html">
+ <source>OSDs
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>Scrub
+ </source>
+ <target>OSD
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>整理
+ </target>
+ </trans-unit>
+ <trans-unit id="4c17d67c7c5799eb920030e9a399961e90f55dd8" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Deep } }</source>
+ <target>{VAR_SELECT, select, 1 {深層} }</target>
+ </trans-unit>
+ <trans-unit id="6a92b12d76f3cb0ea9d4f6c3cdc57cb1e1235977" datatype="html">
+ <source>You are about to apply a
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>scrub to
+ the OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>.
+ </source>
+ <target>即將對 OSD
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ selected[0].id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ 套用
+ <x id="ICU" equiv-text="{deep, select, 1 {...}}"/>整理。
+ </target>
+ </trans-unit>
+ <trans-unit id="dc6705f342a036b332c3fd3443201c3613e5524d" datatype="html">
+ <source>{VAR_SELECT, select, 1 {deep } }</source>
+ <target>{VAR_SELECT, select, 1 {深層} }</target>
+ </trans-unit>
+ <trans-unit id="b49d7877d24112d4bdfce9256edf61a007fae888" datatype="html">
+ <source>OSDs List</source>
+ <target>OSD 清單</target>
+ </trans-unit>
+ <trans-unit id="f777d9b30d757508cec8e0348e8696e1c64eab8a" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be marked
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>若繼續,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ 將被標示為
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ markActionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="2d3a73f6440a7d896d74356fe0a725d731e71cbb" datatype="html">
+ <source>The OSD is not safe to destroy!</source>
+ <target>OSD 不安全,無法損毀!</target>
+ </trans-unit>
+ <trans-unit id="9d08116242443953ebbfe10bc2092e0a694b4adf" datatype="html">
+ <source>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> will be
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> if you proceed.
+ </source>
+ <target>若繼續,
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>OSD
+ <x id="INTERPOLATION" equiv-text="{{ selection.first().id }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ 將被
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ actionDescription }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="4f8b2bb476981727ab34ed40fde1218361f92c45" datatype="html">
+ <source>Details</source>
+ <target>詳細資料</target>
+ </trans-unit>
+ <trans-unit id="8501055865d7031b5521a0c5467532648009a61d" datatype="html">
+ <source>Matcher</source>
+ <target>Matcher</target>
+ </trans-unit>
+ <trans-unit id="9c25e04f554875dc2625a78ba0fc56c6010cd0d3" datatype="html">
+ <source>-- Select an attribute to match against --</source>
+ <target>-- Select an attribute to match against --</target>
+ </trans-unit>
+ <trans-unit id="5049e204c14c648691ac775a64fb504467aeb549" datatype="html">
+ <source>Value</source>
+ <target>值</target>
+ </trans-unit>
+ <trans-unit id="77fc5c63497fc031ddc97645484e3d94ad27766c" datatype="html">
+ <source>Use regular expression</source>
+ <target>Use regular expression</target>
+ </trans-unit>
+ <trans-unit id="7bbec1a797283712c0adf9e71d77fb5a8cd720db" datatype="html">
+ <source>{VAR_SELECT, select, 1 {Update} other {Add} }</source>
+ <target>{VAR_SELECT, select, 1 {Update} other {Add} }</target>
+ </trans-unit>
+ <trans-unit id="f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8" datatype="html">
+ <source>Close</source>
+ <target>關閉</target>
+ </trans-unit>
+ <trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
+ <source>Delete</source>
+ <target>刪除</target>
+ </trans-unit>
+ <trans-unit id="a3ba06aba047605af8ea1718ec1ba153b7db12a2" datatype="html">
+ <source>Editing a silence will expire the old silence and recreate it as a new silence</source>
+ <target>Editing a silence will expire the old silence and recreate it as a new silence</target>
+ </trans-unit>
+ <trans-unit id="a20424156b8816671f61879f0574a4f27d7b16b9" datatype="html">
+ <source>Creator</source>
+ <target>Creator</target>
+ </trans-unit>
+ <trans-unit id="5a5d7ee2acbfa9c91ab7f41d26bda9ff0cafe42f" datatype="html">
+ <source>Comment</source>
+ <target>Comment</target>
+ </trans-unit>
+ <trans-unit id="4c11aad490b2d53fdae30b3807beabf79306752c" datatype="html">
+ <source>Start time</source>
+ <target>Start time</target>
+ </trans-unit>
+ <trans-unit id="32856b1e8e339b747b21e313e2fe65a51fd450bb" datatype="html">
+ <source>If the start time lies in the past the creation time will be used</source>
+ <target>If the start time lies in the past the creation time will be used</target>
+ </trans-unit>
+ <trans-unit id="a02ea1d4e7424ca989929da5e598f379940fdbf2" datatype="html">
+ <source>Duration</source>
+ <target>Duration</target>
+ </trans-unit>
+ <trans-unit id="2f4e35e36f4d3c62e2c17df41730b6dee4afc4b9" datatype="html">
+ <source>End time</source>
+ <target>End time</target>
+ </trans-unit>
+ <trans-unit id="dbe739ec8c99a0132e326067ffec9c0ee06b2655" datatype="html">
+ <source>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </source>
+ <target>Matchers
+ <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span>"/>*
+ <x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="3e023166c55833d5a13f4143e3dbe372befe1b4e" datatype="html">
+ <source>A silence requires at least one matcher</source>
+ <target>A silence requires at least one matcher</target>
+ </trans-unit>
+ <trans-unit id="ef765bd80c4806c51c891908c07a24bc76f019eb" datatype="html">
+ <source>Add matcher</source>
+ <target>Add matcher</target>
+ </trans-unit>
+ <trans-unit id="d2bcd3296d2850de762fb943060b7e086a893181" datatype="html">
+ <source>Health</source>
+ <target>狀態</target>
+ </trans-unit>
+ <trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
+ <source>Statistics</source>
+ <target>統計資料</target>
+ </trans-unit>
+ <trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the NFS Ganesha management functionality.
+ </source>
+ <target>如需了解如何設定和啟用 NFS Ganesha 管理功能,
+ 請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文件
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="7ffe39df9d88c972792bd8688b215392deb8313d" datatype="html">
+ <source>Clients</source>
+ <target>用戶端</target>
+ </trans-unit>
+ <trans-unit id="f2dae0bda66f6a349444951c0379c28cda47d6d1" datatype="html">
+ <source>Any client can access</source>
+ <target>任何用戶端均可存取</target>
+ </trans-unit>
+ <trans-unit id="7882f2edb1d4139800b276b6b0bbf5ae0b2234ef" datatype="html">
+ <source>Addresses</source>
+ <target>位址</target>
+ </trans-unit>
+ <trans-unit id="9bd96fcf50863e685c74d0490392f46689ffbdb6" datatype="html">
+ <source>Required field</source>
+ <target>必填欄位</target>
+ </trans-unit>
+ <trans-unit id="a5f3f74c0f6925826cb2188576391c0da01a23f0" datatype="html">
+ <source>Must contain one or more comma-separated values</source>
+ <target>必須包含一或多個逗號分隔值</target>
+ </trans-unit>
+ <trans-unit id="8bb5b2073697f3f4378c44a49b7524934c9268f4" datatype="html">
+ <source>For example:</source>
+ <target>例如︰</target>
+ </trans-unit>
+ <trans-unit id="8f969c655b3fbe4fba7e277caf4cd2c459f9fca5" datatype="html">
+ <source>Access Type</source>
+ <target>存取類型</target>
+ </trans-unit>
+ <trans-unit id="28952831a284cfe2b4fc39ca610e80b52598905a" datatype="html">
+ <source>Squash</source>
+ <target>Squash</target>
+ </trans-unit>
+ <trans-unit id="0660ae339068979854ade34a96546980723dede3" datatype="html">
+ <source>Add clients</source>
+ <target>新增用戶端</target>
+ </trans-unit>
+ <trans-unit id="94516fa213706c67ce5a5b5765681d7fb032033a" datatype="html">
+ <source>Loading...</source>
+ <target>正在載入...</target>
+ </trans-unit>
+ <trans-unit id="135b91a2d908d5814b782695470a6a786c99d9d2" datatype="html">
+ <source>-- No cluster available --</source>
+ <target>-- 沒有可用的叢集 --</target>
+ </trans-unit>
+ <trans-unit id="c501dba379f566885919240ea277b5bc10c14d18" datatype="html">
+ <source>-- Select the cluster --</source>
+ <target>-- 選取叢集 --</target>
+ </trans-unit>
+ <trans-unit id="cf85b1ee58326aa9da63da41b2629c9db7c9a5b9" datatype="html">
+ <source>Add daemon</source>
+ <target>新增精靈</target>
+ </trans-unit>
+ <trans-unit id="b3f6ba7fe84d6508705cdfe234f0fcc8ff85c9cf" datatype="html">
+ <source>Storage Backend</source>
+ <target>儲存後端</target>
+ </trans-unit>
+ <trans-unit id="151c80ea931037cd92e854442927f8a0f6ae7795" datatype="html">
+ <source>-- No data pools available --</source>
+ <target>-- 沒有可用的資料池 --</target>
+ </trans-unit>
+ <trans-unit id="b6fee356d1db954255a56d8169405a89595246b9" datatype="html">
+ <source>-- Select the storage backend --</source>
+ <target>-- 選取儲存後端 --</target>
+ </trans-unit>
+ <trans-unit id="76d67035c3ab3d8e56f725859f820f03fda41cfc" datatype="html">
+ <source>Object Gateway User</source>
+ <target>物件閘道使用者</target>
+ </trans-unit>
+ <trans-unit id="fade7788bace74337f306ae209f10fc187ef4671" datatype="html">
+ <source>-- No users available --</source>
+ <target>-- 沒有可用的使用者 --</target>
+ </trans-unit>
+ <trans-unit id="6d30b7b36cf8f6364167321bdb4ba35d4cefce7b" datatype="html">
+ <source>-- Select the object gateway user --</source>
+ <target>-- 選取物件閘道使用者 --</target>
+ </trans-unit>
+ <trans-unit id="589ce20d3ba3e3ac44f75decfaadc4ea8f0aec2d" datatype="html">
+ <source>CephFS User ID</source>
+ <target>CephFS 使用者 ID</target>
+ </trans-unit>
+ <trans-unit id="c4b88a53ac3b0ece46ba9b3ad72355a3c190cce7" datatype="html">
+ <source>-- No clients available --</source>
+ <target>-- 沒有可用的用戶端 --</target>
+ </trans-unit>
+ <trans-unit id="da52835b80497a0002d24414b057dc46ae44ce38" datatype="html">
+ <source>-- Select the cephx client --</source>
+ <target>-- 選取 cephx 用戶端 --</target>
+ </trans-unit>
+ <trans-unit id="fd3419e8957d928d7f7ba19c93356a0dbff02871" datatype="html">
+ <source>CephFS Name</source>
+ <target>CephFS 名稱</target>
+ </trans-unit>
+ <trans-unit id="ee3ba0ab5f0ccd597b3e44021c71e9aaad14df0a" datatype="html">
+ <source>-- No CephFS filesystem available --</source>
+ <target>-- No CephFS filesystem available --</target>
+ </trans-unit>
+ <trans-unit id="764c57812558b1ae66c5eec95d7efd2b1bf761e3" datatype="html">
+ <source>-- Select the CephFS filesystem --</source>
+ <target>-- Select the CephFS filesystem --</target>
+ </trans-unit>
+ <trans-unit id="957512d0321f73e9f115bce1bd823fa635170c41" datatype="html">
+ <source>Security Label</source>
+ <target>安全標籤</target>
+ </trans-unit>
+ <trans-unit id="65ce0fa4da1ed55e658aeb31d1644a29f06bb342" datatype="html">
+ <source>Enable security label</source>
+ <target>啟用安全標籤</target>
+ </trans-unit>
+ <trans-unit id="7e808f804130c7b6ff719509cbc06ebb27393a48" datatype="html">
+ <source>CephFS Path</source>
+ <target>CephFS 路徑</target>
+ </trans-unit>
+ <trans-unit id="5ecc0107badb6625466aaa3f975b5c05276f432f" datatype="html">
+ <source>Path need to start with a '/' and can be followed by a word</source>
+ <target>路徑必須以「/」開頭,後面可接單詞</target>
+ </trans-unit>
+ <trans-unit id="2d02916f44fc63e13ab16d1cbe72aa6cb51feab3" datatype="html">
+ <source>New directory will be created</source>
+ <target>將建立新目錄</target>
+ </trans-unit>
+ <trans-unit id="766c66ad5cc981c531aaf3fe3a2a7a346ddc8d83" datatype="html">
+ <source>Path</source>
+ <target>路徑</target>
+ </trans-unit>
+ <trans-unit id="7ec35c722a50b976620f22612f7be619c12ceb90" datatype="html">
+ <source>Path can only be a single '/' or a word</source>
+ <target>路徑只能以單一「/」或單詞開頭</target>
+ </trans-unit>
+ <trans-unit id="aebb6a5090c24511de4530195694bb3f3dcf0342" datatype="html">
+ <source>New bucket will be created</source>
+ <target>將建立新桶</target>
+ </trans-unit>
+ <trans-unit id="bee6900143996c0e908a10564532eba3da0b30fb" datatype="html">
+ <source>NFS Protocol</source>
+ <target>NFS 通訊協定</target>
+ </trans-unit>
+ <trans-unit id="2f534178c01ebf1307da2eaeef04bc6801ebc729" datatype="html">
+ <source>NFSv3</source>
+ <target>NFSv3</target>
+ </trans-unit>
+ <trans-unit id="f5043c0921e709935ab026bb3253ffe1f159fca1" datatype="html">
+ <source>NFSv4</source>
+ <target>NFSv4</target>
+ </trans-unit>
+ <trans-unit id="92488963d23095985a47c0d6e62304e11d333f19" datatype="html">
+ <source>NFS Tag</source>
+ <target>NFS 標記</target>
+ </trans-unit>
+ <trans-unit id="aae93362720aea94623682996dd3fcd0f906f056" datatype="html">
+ <source>Alternative access for
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> mounts (it must not have a leading /).
+ </source>
+ <target>
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v3
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 掛接的備用存取 (不得包含前置 /)。
+ </target>
+ </trans-unit>
+ <trans-unit id="45d6db77dcf1a3eeb921033abc7882e517a541cc" datatype="html">
+ <source>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</source>
+ <target>用戶端不能掛接子目錄 (即如果標記為 foo,則用戶端無法掛接 foo/baz)。</target>
+ </trans-unit>
+ <trans-unit id="a1c7a8676b55e882a97c6a6fb205204f9c761afa" datatype="html">
+ <source>By using different Tag options, the same Path may be exported multiple times.</source>
+ <target>透過使用不同標記選項,可將同一路徑輸出多次。</target>
+ </trans-unit>
+ <trans-unit id="6d2c39708a32910f89701dd7e1cfb9ec1c195768" datatype="html">
+ <source>Pseudo</source>
+ <target>虛擬</target>
+ </trans-unit>
+ <trans-unit id="1f8be2ae25947bec0b84c2338201580ea053f34e" datatype="html">
+ <source>The position that this
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> export occupies
+ in the
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>Pseudo FS
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> (it must be unique).
+ </source>
+ <target>此
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>NFS v4
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 輸出在
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>虛擬檔案系統
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>中
+ 所佔用的位置 (必須唯一)。
+ </target>
+ </trans-unit>
+ <trans-unit id="f3af55f7fd5b1d9e5a53e030c80116dc635bfb9f" datatype="html">
+ <source>By using different Pseudo options, the same Path may be exported multiple times.</source>
+ <target>透過使用不同虛擬選項,可將同一路徑輸出多次。</target>
+ </trans-unit>
+ <trans-unit id="ddf98fcdeeb17643db020d54f42b5e56b5f9a52a" datatype="html">
+ <source>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</source>
+ <target>Pseudo needs to start with a '/' and can't contain any of the following: &gt;, &lt;, |, &amp;, ( or ).</target>
+ </trans-unit>
+ <trans-unit id="27eb35c4b4ac08781a7253a2ab40f8f7d957ba51" datatype="html">
+ <source>-- No access type available --</source>
+ <target>-- 沒有可用的存取類型 --</target>
+ </trans-unit>
+ <trans-unit id="509ce016c9110a54028dafd741f15ceacbe74b5a" datatype="html">
+ <source>-- Select the access type --</source>
+ <target>-- 選取存取類型 --</target>
+ </trans-unit>
+ <trans-unit id="49850390a653cd05dc5843d74ef073a9122b54c9" datatype="html">
+ <source>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </source>
+ <target>The Object Gateway NFS backend has a number of
+ limitations which will seriously affect applications writing to
+ the share. Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/> documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for details before enabling write access.
+ </target>
+ </trans-unit>
+ <trans-unit id="4deda03573eaaff77e63f6a238a1f0ca7816950a" datatype="html">
+ <source>-- No squash available --</source>
+ <target>-- 沒有可用的 squash --</target>
+ </trans-unit>
+ <trans-unit id="a0e82a4da88e7fdf270444f838d45849676e9d4b" datatype="html">
+ <source>--Select what kind of user id squashing is performed --</source>
+ <target>-- 選取執行哪種類型的使用者 ID 匿名存取 --</target>
+ </trans-unit>
+ <trans-unit id="d01b7c3f7f06712c53d054cfbe4f53d446b038e8" datatype="html">
+ <source>Transport Protocol</source>
+ <target>傳輸通訊協定</target>
+ </trans-unit>
+ <trans-unit id="d2a6ad6e8bc315f07911722c05767ac79c136d99" datatype="html">
+ <source>UDP</source>
+ <target>UDP</target>
+ </trans-unit>
+ <trans-unit id="9c030f11e0aae9b24d2c048c57f29f590be621df" datatype="html">
+ <source>TCP</source>
+ <target>TCP</target>
+ </trans-unit>
+ <trans-unit id="734c9905951a774870497c5aaae8e3ee833b6196" datatype="html">
+ <source>CephFS</source>
+ <target>CephFS</target>
+ </trans-unit>
+ <trans-unit id="449dca3d3a93ead418b0541ea81b0dda7e6483c2" datatype="html">
+ <source>Welcome to Ceph!</source>
+ <target>歡迎使用 Ceph!</target>
+ <note>The welcome message on the login page</note>
+ </trans-unit>
+ <trans-unit id="0070e83d11da39d6f4bb95065c2675db1610b419" datatype="html">
+ <source>Username is required</source>
+ <target>需要指定使用者名稱</target>
+ </trans-unit>
+ <trans-unit id="1e20f8b8a4706526c9024cc2f39d568345d100dc" datatype="html">
+ <source>Password is required</source>
+ <target>需要指定密碼</target>
+ </trans-unit>
+ <trans-unit id="6765b4c916060f6bc42d9bb69e80377dbcb5e4e9" datatype="html">
+ <source>Login</source>
+ <target>登入</target>
+ </trans-unit>
+ <trans-unit id="58fc1b5c79a75370eb52644fd83fb2e7096b6649" datatype="html">
+ <source>Sorry, the user does not exist in Ceph.</source>
+ <target>抱歉,該使用者不存在於 Ceph 中。</target>
+ </trans-unit>
+ <trans-unit id="d9deb94f78e7c41b35c6622b874f06657d7604c1" datatype="html">
+ <source>Return to
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Login Page
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>. You'll be logged out from the Identity Provider when you retry logging in.
+ </source>
+ <target>返回
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>登入頁面
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。 當您重試登入時,您將從身分提供者登出。
+ </target>
+ </trans-unit>
+ <trans-unit id="471e78026c258073ba687478dc54c35d9041ea42" datatype="html">
+ <source>Forbidden</source>
+ <target>已禁止</target>
+ </trans-unit>
+ <trans-unit id="02ea8ad57677e3c63f3d7814ca5e6c7b74e360b4" datatype="html">
+ <source>Sorry, you are not allowed to see what you were looking for.</source>
+ <target>抱歉,您無權查看您要尋找的內容。</target>
+ </trans-unit>
+ <trans-unit id="e3c028c58f92453d46f09b5adf95b2f013ee0300" datatype="html">
+ <source>Sorry, we could not find what you were looking for</source>
+ <target>抱歉,我們找不到您要尋找的內容。</target>
+ </trans-unit>
+ <trans-unit id="16568619015cfb2352e3b2596ba04fc1c82e44ef" datatype="html">
+ <source>Remove all</source>
+ <target>全部移除</target>
+ </trans-unit>
+ <trans-unit id="1d65cc22d5842c06d33b244fc67de9db4003537e" datatype="html">
+ <source>Recent Notifications</source>
+ <target>最近的通知</target>
+ </trans-unit>
+ <trans-unit id="495ab70870b5b4a30f2bc5f55052fdc518d954a9" datatype="html">
+ <source>There are no background tasks.</source>
+ <target>沒有背景任務。</target>
+ </trans-unit>
+ <trans-unit id="ea94e7754983d80af8acb958a5d49d93bacd721c" datatype="html">
+ <source>Background Tasks</source>
+ <target>背景任務</target>
+ </trans-unit>
+ <trans-unit id="85b79c9064aed1ead31ace985f31aa1363f6bdaf" datatype="html">
+ <source>Help</source>
+ <target>說明</target>
+ </trans-unit>
+ <trans-unit id="fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7" datatype="html">
+ <source>Documentation</source>
+ <target>文件</target>
+ </trans-unit>
+ <trans-unit id="e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4" datatype="html">
+ <source>API</source>
+ <target>API</target>
+ </trans-unit>
+ <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
+ <source>About</source>
+ <target>關於</target>
+ </trans-unit>
+ <trans-unit id="1481ecd21e760ac919a24e26cf790acd82e40199" datatype="html">
+ <source>Dashboard Settings</source>
+ <target>儀表板設定</target>
+ </trans-unit>
+ <trans-unit id="a79aab4ef674bf3f6532292107c0054302236e0f" datatype="html">
+ <source>User management</source>
+ <target>使用者管理</target>
+ </trans-unit>
+ <trans-unit id="049dfd9fe6c78914ad58cf89ac6a631fca28ec74" datatype="html">
+ <source>Logged in user</source>
+ <target>登入的使用者</target>
+ </trans-unit>
+ <trans-unit id="cd38a58e73f306d838e621959d47d5e7a2f06d1f" datatype="html">
+ <source>Signed in as
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ </source>
+ <target>以
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>
+ <x id="INTERPOLATION" equiv-text="{{ username }}"/>
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/>
+ 身分登入
+ </target>
+ </trans-unit>
+ <trans-unit id="5d22c795daf43877a5f708dca2bccd549eb0471d" datatype="html">
+ <source>Sign out</source>
+ <target>登出</target>
+ </trans-unit>
+ <trans-unit id="2fecea01ce1d44114ee45144eff6d47a5016a74f" datatype="html">
+ <source>Name...</source>
+ <target>名稱...</target>
+ </trans-unit>
+ <trans-unit id="eabb4db920d9f9b2480cf438468b86e1bea02a9b" datatype="html">
+ <source>The chosen name is already in use.</source>
+ <target>所選的名稱已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="1ea5c4d8942c00752dcc72e72949c5d9832f6399" datatype="html">
+ <source>Description...</source>
+ <target>描述...</target>
+ </trans-unit>
+ <trans-unit id="70f45880fce6ac5d8e468e25e82aefbba8098cfe" datatype="html">
+ <source>Permissions</source>
+ <target>許可權</target>
+ </trans-unit>
+ <trans-unit id="9610487cbeb5796d34d8601b5ac0c0a65f9e1d19" datatype="html">
+ <source>Roles</source>
+ <target>角色</target>
+ </trans-unit>
+ <trans-unit id="08c74dc9762957593b91f6eb5d65efdfc975bf48" datatype="html">
+ <source>Username</source>
+ <target>使用者名稱</target>
+ </trans-unit>
+ <trans-unit id="c32ef07f8803a223a83ed17024b38e8d82292407" datatype="html">
+ <source>Password</source>
+ <target>密碼</target>
+ </trans-unit>
+ <trans-unit id="7f3bdcce4b2e8c37cd7f0f6c92ef8cff34b039b8" datatype="html">
+ <source>Confirm password</source>
+ <target>確認密碼</target>
+ </trans-unit>
+ <trans-unit id="cbb979e63ba50e0ca3adfa09cbdcaefd0853fca1" datatype="html">
+ <source>Password confirmation doesn't match the password.</source>
+ <target>確認的密碼與之前輸入的密碼不符。</target>
+ </trans-unit>
+ <trans-unit id="b760f123248930122fc7e7b6b6bf94e376e959c8" datatype="html">
+ <source>Full name</source>
+ <target>全名</target>
+ </trans-unit>
+ <trans-unit id="244aae9346da82b0922506c2d2581373a15641cc" datatype="html">
+ <source>Email</source>
+ <target>電子郵件</target>
+ </trans-unit>
+ <trans-unit id="d0ec081dd61eb4f43aea269077bbe38eae87b7f9" datatype="html">
+ <source>Invalid email.</source>
+ <target>電子郵件無效。</target>
+ </trans-unit>
+ <trans-unit id="0051a3479d3ba79135c16dc8cc017950a2cce821" datatype="html">
+ <source>You are about to remove "user read / update" permissions from your own user.</source>
+ <target>您正要為您自己的使用者移除「使用者讀取/寫入」許可權。</target>
+ </trans-unit>
+ <trans-unit id="af4bf9fcb256853f14cf947eb1deb8d7f176d3f9" datatype="html">
+ <source>If you continue, you will no longer be able to add or remove roles from any user.</source>
+ <target>若繼續,您將再也無法為任何使用者新增或移除角色。</target>
+ </trans-unit>
+ <trans-unit id="7d1dcf2a9146caac0581329acf94806ec69a89a5" datatype="html">
+ <source>Are you sure you want to continue?</source>
+ <target>確定要繼續嗎?</target>
+ </trans-unit>
+ <trans-unit id="ca53d681a9892d6fdbb57ee9676582186515e961" datatype="html">
+ <source>Performance counters not available</source>
+ <target>沒有可用的效能計數器</target>
+ </trans-unit>
+ <trans-unit id="91853167141c37b58868f3b0421383dd72fa8a01" datatype="html">
+ <source>Attributes (OSD map)</source>
+ <target>屬性 (OSD 地圖)</target>
+ </trans-unit>
+ <trans-unit id="97842f379e1d4157ac3ab0661b90c352e7cb72d5" datatype="html">
+ <source>Metadata not available</source>
+ <target>無法使用中繼資料</target>
+ </trans-unit>
+ <trans-unit id="f721a500a68c357e8f2a01e60510f6a01e4ba529" datatype="html">
+ <source>Metadata</source>
+ <target>中繼資料</target>
+ </trans-unit>
+ <trans-unit id="d24e28e19c5703d7c6be44f4eb595a6a43b618ed" datatype="html">
+ <source>Performance counter</source>
+ <target>效能計數器</target>
+ </trans-unit>
+ <trans-unit id="d1f7c81ed9c5034af4abcdf119b1c1e86cd019dd" datatype="html">
+ <source>Histogram not available:
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </source>
+ <target>無法使用長條圖︰
+ <x id="INTERPOLATION" equiv-text="{{ osd.histogram_failed }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="868abfff914873d1c65df798d8432ed04b8ae2a9" datatype="html">
+ <source>Writes</source>
+ <target>寫入</target>
+ </trans-unit>
+ <trans-unit id="996ebb9a653b5067f97bf3891ea9d2108e969492" datatype="html">
+ <source>Reads</source>
+ <target>讀取</target>
+ </trans-unit>
+ <trans-unit id="65ac79790aa477a97b1cc579e18a115a8df8918f" datatype="html">
+ <source>Histogram</source>
+ <target>長條圖</target>
+ </trans-unit>
+ <trans-unit id="fbbaf5cb02ed419e79a27072478f716a4666a99d" datatype="html">
+ <source>Performance Details</source>
+ <target>效能詳細資料</target>
+ </trans-unit>
+ <trans-unit id="26fb5f81b3581f06b9210defb0e71dc69a67e819" datatype="html">
+ <source>Current values</source>
+ <target>目前的值</target>
+ </trans-unit>
+ <trans-unit id="f61c6867295f3b53d23557021f2f4e0aa1d0b8fc" datatype="html">
+ <source>Type</source>
+ <target>類型</target>
+ </trans-unit>
+ <trans-unit id="9abcd7c82643d60c22733470463f74e4a54bc069" datatype="html">
+ <source>Min</source>
+ <target>最小值</target>
+ </trans-unit>
+ <trans-unit id="c3ced4d162a0a55ee233a187ce7208ba5e922418" datatype="html">
+ <source>Max</source>
+ <target>最大值</target>
+ </trans-unit>
+ <trans-unit id="920617c6a1a4805e53bcb5af6a9c76f8387e89c6" datatype="html">
+ <source>Flags</source>
+ <target>旗標</target>
+ </trans-unit>
+ <trans-unit id="6834fa6b43d1ecbdf147c48dd9c4d72f1484571d" datatype="html">
+ <source>Source</source>
+ <target>來源</target>
+ </trans-unit>
+ <trans-unit id="a446fb0eb11fbffcac805ece5a2d306d24e733d8" datatype="html">
+ <source>Level</source>
+ <target>層級</target>
+ </trans-unit>
+ <trans-unit id="39f2fb094e9b2eda13163fa3f3a31594cf9c1307" datatype="html">
+ <source>Can be updated at runtime (editable)</source>
+ <target>可在執行時期更新 (可編輯)</target>
+ </trans-unit>
+ <trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
+ <source>Tags</source>
+ <target>標記</target>
+ </trans-unit>
+ <trans-unit id="ab0089ef47af61ca1d137bc908b96c290dfd9287" datatype="html">
+ <source>Enum values</source>
+ <target>列舉值</target>
+ </trans-unit>
+ <trans-unit id="819476f1264f1659f38e86f6abb542141b184832" datatype="html">
+ <source>See also</source>
+ <target>另請參閱</target>
+ </trans-unit>
+ <trans-unit id="73caac4265ea7314ff061e5a1d78a6361a6dd3b8" datatype="html">
+ <source>Cluster Status</source>
+ <target>叢集狀態</target>
+ </trans-unit>
+ <trans-unit id="1d4bc612bbf19aa9553853266b9e92c9d75f4464" datatype="html">
+ <source>Manager Daemons</source>
+ <target>管理員精靈</target>
+ </trans-unit>
+ <trans-unit id="946ac5dea9921dc09d7b0a63b89535371f283b19" datatype="html">
+ <source>Object Gateways</source>
+ <target>物件閘道</target>
+ </trans-unit>
+ <trans-unit id="ff03fa5bcf37c4da46ad736c1f7d03f959e8ba9a" datatype="html">
+ <source>Metadata Servers</source>
+ <target>中繼資料伺服器</target>
+ </trans-unit>
+ <trans-unit id="d817609ba4993eba859409ab71e566168f4d5f5a" datatype="html">
+ <source>iSCSI Gateways</source>
+ <target>iSCSI 閘道</target>
+ </trans-unit>
+ <trans-unit id="42c13e50391250ea9379bdf55d5d6c0228c0c8bc" datatype="html">
+ <source>Client IOPS</source>
+ <target>用戶端 IOPS</target>
+ </trans-unit>
+ <trans-unit id="52213660b2454d139ada3079a42ec6caf3c3c01e" datatype="html">
+ <source>Client Throughput</source>
+ <target>用戶端輸送量</target>
+ </trans-unit>
+ <trans-unit id="32efd1c3f70e3c5244239de97a2cc95d98534a14" datatype="html">
+ <source>Client Read/Write</source>
+ <target>用戶端讀取/寫入</target>
+ </trans-unit>
+ <trans-unit id="275485415092cbae3a9f3cbb786ebe283cacfdd5" datatype="html">
+ <source>Recovery Throughput</source>
+ <target>復原輸送量</target>
+ </trans-unit>
+ <trans-unit id="6d9a9f55046891733ef71170e7652063765eb542" datatype="html">
+ <source>Scrub</source>
+ <target>整理</target>
+ </trans-unit>
+ <trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
+ <source>Performance</source>
+ <target>效能</target>
+ </trans-unit>
+ <trans-unit id="88f383269db2d32cccee9e936fe549dccb9fdbf4" datatype="html">
+ <source>Raw Capacity</source>
+ <target>原始容量</target>
+ </trans-unit>
+ <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+ <source>Objects</source>
+ <target>物件</target>
+ </trans-unit>
+ <trans-unit id="c5f8a813f91a11af99132e4beafc136cfc13d73b" datatype="html">
+ <source>PGs per OSD</source>
+ <target>每個 OSD 的 PG 數</target>
+ </trans-unit>
+ <trans-unit id="498a109c6e9e94f1966de01aa0326f7f0ac6fb52" datatype="html">
+ <source>PG Status</source>
+ <target>PG 狀態</target>
+ </trans-unit>
+ <trans-unit id="ce9dfdc6dccb28dc75a78c704e09dc18fb02dcfa" datatype="html">
+ <source>Capacity</source>
+ <target>容量</target>
+ </trans-unit>
+ <trans-unit id="44ecac93d67c6a671198091c2270354f80322327" datatype="html">
+ <source>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/> See
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>Logs
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/> for more details.
+ </source>
+ <target>
+ <x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>
+ <x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/>如需詳細資料,請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>記錄
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="0c1e17956453ad772dbe82d6946f62748c692f3e" datatype="html">
+ <source>Ranks</source>
+ <target>階層</target>
+ </trans-unit>
+ <trans-unit id="50df62325726db950523a5be1c78b8905fcc25d4" datatype="html">
+ <source>MDS performance counters</source>
+ <target>MDS performance counters</target>
+ </trans-unit>
+ <trans-unit id="95c96d55690c0c685deebe52a1da94dc36f5e99d" datatype="html">
+ <source>Clients:
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </source>
+ <target>用戶端︰
+ <x id="INTERPOLATION" equiv-text="{{ clientCount }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="47116253e36f4e38a97ba41b2d3122c6c15ab904" datatype="html">
+ <source>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </source>
+ <target>Clients (
+ <x id="INTERPOLATION" equiv-text="{{ clients.length }}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="f0b5d789d42c0e69348e5fe0037fcbf5b5fbbdcc" datatype="html">
+ <source>Move an image to trash</source>
+ <target>將影像移至垃圾桶</target>
+ </trans-unit>
+ <trans-unit id="86301cf2044b1eda218483365f6b9de8dde5040b" datatype="html">
+ <source>To move
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> to trash,
+ click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Move Image
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>. Optionally, you can pick an expiration date.
+ </source>
+ <target>若要將
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>/
+ <x id="INTERPOLATION_1" equiv-text="{{ imageName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 移至垃圾桶,
+ 請按一下
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>移動影像
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。或者,您可以選取一個過期日。
+ </target>
+ </trans-unit>
+ <trans-unit id="88f27d390844aad53b4240360e928156c5f0d326" datatype="html">
+ <source>Protection expires at</source>
+ <target>保護的過期日為</target>
+ </trans-unit>
+ <trans-unit id="da166e9a0d27322f6ba8916d71ecc0f9905bb4b1" datatype="html">
+ <source>NOT PROTECTED</source>
+ <target>無保護</target>
+ </trans-unit>
+ <trans-unit id="a1506e5f2ca22cad14502ec7a20fb6113ace145d" datatype="html">
+ <source>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</source>
+ <target>日期格式錯誤。請使用「YYYY-MM-DD HH:mm:ss」。</target>
+ </trans-unit>
+ <trans-unit id="aa7ea0bb7495281e0b3258467ac7d90a1e44a1a1" datatype="html">
+ <source>Protection has already expired. Please pick a future date or leave it empty.</source>
+ <target>保護已過期。請選取一個未來的日期或保留空白。</target>
+ </trans-unit>
+ <trans-unit id="536b3205c0c0d4d21685ec06feccfcf2fe14deb1" datatype="html">
+ <source>Move Image</source>
+ <target>移動影像</target>
+ </trans-unit>
+ <trans-unit id="8a9910cd114c1deb9af74f6f99b4173403965bf2" datatype="html">
+ <source>Gateways</source>
+ <target>Gateways</target>
+ </trans-unit>
+ <trans-unit id="8835b9e49a3348b0a2f2162c21118af1f4bee45a" datatype="html">
+ <source>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </source>
+ <target>Must be greater than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['min'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="bbddac59563c8c126e3fe28691e4e247614fcbd1" datatype="html">
+ <source>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </source>
+ <target>Must be less than or equal to
+ <x id="INTERPOLATION" equiv-text="{{ limits['max'] }}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="e95ae009d0bdb45fcc656e8b65248cf7396080d5" datatype="html">
+ <source>Overview</source>
+ <target>綜覽</target>
+ </trans-unit>
+ <trans-unit id="bbd2045d5c37e4bb39a3c0fb62ea1ddf70a12838" datatype="html">
+ <source>Targets</source>
+ <target>目標</target>
+ </trans-unit>
+ <trans-unit id="6803e31b7395d94934e091a49a9524026b59b018" datatype="html">
+ <source>Discovery Authentication</source>
+ <target>探查驗證</target>
+ </trans-unit>
+ <trans-unit id="e08a77594f3d89311cdf6da5090044270909c194" datatype="html">
+ <source>User</source>
+ <target>使用者</target>
+ </trans-unit>
+ <trans-unit id="0214f773f8e394f50f953f39962e352d7863e959" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>使用者名稱的長度必須介於 8 至 64 個字元之間,並且只能包含以下
+ 字元︰字母、「.」、「@」、「-」、「_」或「:」。</target>
+ </trans-unit>
+ <trans-unit id="6682d1c00263bee204583a5d589b308b6be88b0f" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="ff40391de7a1944ea95091e4045cc34c4979b736" datatype="html">
+ <source>Mutual User</source>
+ <target>雙向驗證使用者</target>
+ </trans-unit>
+ <trans-unit id="0cf73dbebe99b737c4d288788182fc356e3c93d3" datatype="html">
+ <source>Mutual Password</source>
+ <target>雙向驗證密碼</target>
+ </trans-unit>
+ <trans-unit id="8800276925157c666b103c36ff7fe8ffe11980b4" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="53a583cd5f15059cc958b7d547f72cc78f68e123" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the iSCSI Targets management functionality.
+ </source>
+ <target>如需了解如何設定和啟用 iSCSI 目標管理功能,
+ 請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文件
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="3b301d0044f62c92af0da53d7aaca52a436a547d" datatype="html">
+ <source>Available information:</source>
+ <target>可用資訊︰</target>
+ </trans-unit>
+ <trans-unit id="332227f088a4877b3c11f5fb3ae8bc812c470fae" datatype="html">
+ <source>iSCSI Targets not available</source>
+ <target>無法使用 iSCSI 目標</target>
+ </trans-unit>
+ <trans-unit id="8414a5cb9d71cc1b21b10e4a9d1f2dad558f3361" datatype="html">
+ <source>Discovery authentication</source>
+ <target>Discovery authentication</target>
+ </trans-unit>
+ <trans-unit id="0f6e8f6094b180eaf1f11bc0ffe383f1cdcd059e" datatype="html">
+ <source>Only available for RBD images with
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> enabled
+ </source>
+ <target>僅適用於已啟用
+ <x id="START_TAG_STRONG" ctype="x-strong" equiv-text="<strong>"/>fast-diff
+ <x id="CLOSE_TAG_STRONG" ctype="x-strong" equiv-text="</strong>"/> 的 RBD 影像
+ </target>
+ </trans-unit>
+ <trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
+ <source>Pool</source>
+ <target>池</target>
+ </trans-unit>
+ <trans-unit id="03cc5b14b0a20d075e9009ff021f4f1660ba348a" datatype="html">
+ <source>Data Pool</source>
+ <target>資料池</target>
+ </trans-unit>
+ <trans-unit id="1b051734b0ee9021991c91b3ed4e81c244322462" datatype="html">
+ <source>Created</source>
+ <target>已建立</target>
+ </trans-unit>
+ <trans-unit id="7faaaa08f56427999f3be41df1093ce4089bbd75" datatype="html">
+ <source>Size</source>
+ <target>大小</target>
+ </trans-unit>
+ <trans-unit id="ceac8e132384322ec778ba760875a6c6897d3e42" datatype="html">
+ <source>Object size</source>
+ <target>物件大小</target>
+ </trans-unit>
+ <trans-unit id="6cdb1fea93d77c07950c0c76c6e0ad79ebbef084" datatype="html">
+ <source>Features</source>
+ <target>功能</target>
+ </trans-unit>
+ <trans-unit id="0a65771c9a73b9aa609d592fc96a64801a8f40bd" datatype="html">
+ <source>Provisioned</source>
+ <target>已佈建</target>
+ </trans-unit>
+ <trans-unit id="84a36cb75660b736773fe36ffa3d54f0f0fe363e" datatype="html">
+ <source>N/A</source>
+ <target>無</target>
+ </trans-unit>
+ <trans-unit id="e5c009342a4e8381f64341d0bb61c2e4685f5a4b" datatype="html">
+ <source>Total provisioned</source>
+ <target>總佈建數</target>
+ </trans-unit>
+ <trans-unit id="7f6bf8a43ae415f527ac961ea62471b983aaa97b" datatype="html">
+ <source>Striping unit</source>
+ <target>分割單位</target>
+ </trans-unit>
+ <trans-unit id="db710e8a8f011923f2d15d713fbae49c38b02b26" datatype="html">
+ <source>Striping count</source>
+ <target>分割計數</target>
+ </trans-unit>
+ <trans-unit id="3a4c2a9e76634ff14a60d52a718296f722d47c67" datatype="html">
+ <source>Parent</source>
+ <target>父</target>
+ </trans-unit>
+ <trans-unit id="6a209e68d78ffc2cc9c53d2e76158624efab71ad" datatype="html">
+ <source>Block name prefix</source>
+ <target>區塊名稱字首</target>
+ </trans-unit>
+ <trans-unit id="5704ec2049d007c5f5fb495a5d8b607e68d58081" datatype="html">
+ <source>Order</source>
+ <target>順序</target>
+ </trans-unit>
+ <trans-unit id="f21b1d17b6c5042bb5805516eee37fde33739dd8" datatype="html">
+ <source>Snapshots</source>
+ <target>快照</target>
+ </trans-unit>
+ <trans-unit id="a5f9ba9bb9faa8284bcadb1cdbc6aaf969e9c4bb" datatype="html">
+ <source>Image</source>
+ <target>影像</target>
+ </trans-unit>
+ <trans-unit id="58e58f1a8786da9031a05e6770c5dafce82badf5" datatype="html">
+ <source>This setting overrides the global value</source>
+ <target>此設定會覆寫全域值</target>
+ </trans-unit>
+ <trans-unit id="5decb3917d46a9ac6e5813699801becb7c3c1455" datatype="html">
+ <source>Global</source>
+ <target>全域</target>
+ </trans-unit>
+ <trans-unit id="36b46714164964c6258b08ed0a25f57d8a950f92" datatype="html">
+ <source>This is the global value. No value for this option has been set for this image.</source>
+ <target>此值為全域值。未為此影像設定此選項的值。</target>
+ </trans-unit>
+ <trans-unit id="6547c9c4d5f62942ac4b1fe459cf9a03d4dbf5a0" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ action | titlecase }}"/> from
+ </target>
+ </trans-unit>
+ <trans-unit id="0e9ecf29a4fa5b057bd8052e0d801b3fde6a30bf" datatype="html">
+ <source>'/' and '@' are not allowed.</source>
+ <target>不允許使用「/」和「@」。</target>
+ </trans-unit>
+ <trans-unit id="b99417c4dd46286ffd37c8d2e987c8b512ec7052" datatype="html">
+ <source>-- No rbd pools available --</source>
+ <target>-- 沒有可用的 RBD 池 --</target>
+ </trans-unit>
+ <trans-unit id="ef83ec9c304a89d45650e580dcdc2978c37b3a83" datatype="html">
+ <source>-- Select a pool --</source>
+ <target>-- 選取池 --</target>
+ </trans-unit>
+ <trans-unit id="49449943d8cbf59d8c401c8bd2e76f92e207cc5f" datatype="html">
+ <source>Use a dedicated data pool</source>
+ <target>使用專屬的資料池</target>
+ </trans-unit>
+ <trans-unit id="870aee0dd31a9643bf62007beb8f1ae1deb34d42" datatype="html">
+ <source>Data pool</source>
+ <target>資料池</target>
+ </trans-unit>
+ <trans-unit id="3792ca829d9b9f687e1f5d7733d30e9bb0bfec47" datatype="html">
+ <source>Dedicated pool that stores the object-data of the RBD.</source>
+ <target>專用於儲存 RBD 的物件資料的池</target>
+ </trans-unit>
+ <trans-unit id="f0016bd458baa88284a658ce9eeda42d8ad88d2c" datatype="html">
+ <source>e.g., 10GiB</source>
+ <target>例如 10 GiB</target>
+ </trans-unit>
+ <trans-unit id="0a88bbee20570aaf9615332fb27020627044874d" datatype="html">
+ <source>You have to increase the size.</source>
+ <target>您必須增加大小。</target>
+ </trans-unit>
+ <trans-unit id="bc2e854e111ecf2bd7db170da5e3c2ed08181d88" datatype="html">
+ <source>Advanced</source>
+ <target>進階</target>
+ </trans-unit>
+ <trans-unit id="3562a3778695a5f9c0445660e35301f0a39aaf73" datatype="html">
+ <source>Striping</source>
+ <target>分割</target>
+ </trans-unit>
+ <trans-unit id="ef3c3f3b5f562a5cdbe0ee2874287db1534b5958" datatype="html">
+ <source>Stripe unit</source>
+ <target>分割單位</target>
+ </trans-unit>
+ <trans-unit id="84471be1049006edecbcaef1a32ae0893c229c50" datatype="html">
+ <source>-- Select stripe unit --</source>
+ <target>-- 選取分割單位 --</target>
+ </trans-unit>
+ <trans-unit id="8d32c5c54c8581c774a7f467fbd4e329b15a74fa" datatype="html">
+ <source>This field is required because stripe count is defined!</source>
+ <target>由於已定義分割計數,因此必須填寫此欄位!</target>
+ </trans-unit>
+ <trans-unit id="6bbf9040be7c5491d4a03f2185708f43a6582a3b" datatype="html">
+ <source>Stripe unit is greater than object size.</source>
+ <target>分割單位大於物件大小。</target>
+ </trans-unit>
+ <trans-unit id="a682f49f9b761591661276d7c6f550e641a130a4" datatype="html">
+ <source>Stripe count</source>
+ <target>分割計數</target>
+ </trans-unit>
+ <trans-unit id="baa74031990c5370008ba622d0a250f0929097f4" datatype="html">
+ <source>This field is required because stripe unit is defined!</source>
+ <target>由於已定義分割單位,因此必須填寫此欄位!</target>
+ </trans-unit>
+ <trans-unit id="cd2ada6d5ecbd5cbf89eae0a1f5326efedac0dbc" datatype="html">
+ <source>Stripe count must be greater than 0.</source>
+ <target>分割計數必須大於 0。</target>
+ </trans-unit>
+ <trans-unit id="3f67f30568e9ae47507d46e28e1e82a7dca772e2" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> RBD 快照
+ </target>
+ </trans-unit>
+ <trans-unit id="1628d19a4490817c18be2afab410ca4adfa62ea7" datatype="html">
+ <source>{VAR_SELECT, select, true {Rename} other {Create} }</source>
+ <target>{VAR_SELECT, select, true {重新命名} other {建立} }</target>
+ </trans-unit>
+ <trans-unit id="73a287b41afe6b28f90edbeb98957a341a0276b4" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/> Snapshot
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{ editing, select, true {...} other {...}}"/>快照
+ </target>
+ </trans-unit>
+ <trans-unit id="cb60c1cd3655234756b5b92d4d597d92d520ee30" datatype="html">
+ <source>PROTECTED</source>
+ <target>受保護</target>
+ </trans-unit>
+ <trans-unit id="deffb86b8fb0541254ad5a43862d82bff6b6a6c4" datatype="html">
+ <source>UNPROTECTED</source>
+ <target>未受保護</target>
+ </trans-unit>
+ <trans-unit id="5c5331983af566d4ac6a1024d15a3511786a4aa6" datatype="html">
+ <source>You are about to rollback</source>
+ <target>您正要復原</target>
+ </trans-unit>
+ <trans-unit id="49c0408946a6d67185947f455f15cc201d0d78e6" datatype="html">
+ <source>Purge Trash</source>
+ <target>清除垃圾桶</target>
+ </trans-unit>
+ <trans-unit id="af728625d769b61acf291442644b89edb88faec3" datatype="html">
+ <source>To purge, select one or All images and click</source>
+ <target>若要清除,請選取一個或全部影像,然後按一下</target>
+ </trans-unit>
+ <trans-unit id="55a4f598a4894b7fd5cb88f0ffd3c37ad009dd70" datatype="html">
+ <source>Pool:</source>
+ <target>池︰</target>
+ </trans-unit>
+ <trans-unit id="d43dd2b9f7797e4cf3a604695bb33e4479108516" datatype="html">
+ <source>Pool name...</source>
+ <target>池名稱...</target>
+ </trans-unit>
+ <trans-unit id="dfc3c34e182ea73c5d784ff7c8135f087992dac1" datatype="html">
+ <source>All</source>
+ <target>全部</target>
+ </trans-unit>
+ <trans-unit id="b0e7c7ed1d51a0c205c815048bc9f79e24ee6db2" datatype="html">
+ <source>Restore Image</source>
+ <target>回存影像</target>
+ </trans-unit>
+ <trans-unit id="7369384817e0ad61ce871c9afdfbb538df2f97c1" datatype="html">
+ <source>To restore</source>
+ <target>若要回存</target>
+ </trans-unit>
+ <trans-unit id="e7f0abefc608f7fb452c2dc9b1cdc3dec432160e" datatype="html">
+ <source>type the image's new name and click</source>
+ <target>鍵入影像的新名稱并按一下</target>
+ </trans-unit>
+ <trans-unit id="41307dd56fea669eed72e12a6c23af275f6bfd82" datatype="html">
+ <source>New Name</source>
+ <target>新名稱</target>
+ </trans-unit>
+ <trans-unit id="5c96a761dc55a21882c132c929583a424c9b8cf4" datatype="html">
+ <source>Expired at</source>
+ <target>過期日為</target>
+ </trans-unit>
+ <trans-unit id="661041e3fcff4d3e75c561e038ca2504cf2cc643" datatype="html">
+ <source>Protected until</source>
+ <target>保護過期日為</target>
+ </trans-unit>
+ <trans-unit id="0ee3b2322a1d3277f7e3fdb8a5141ac42bcf350b" datatype="html">
+ <source>This image is protected until
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>.
+ </source>
+ <target>此影像的保護過期日為
+ <x id="INTERPOLATION" equiv-text="{{ expiresAt | cdDate }}"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="aba82bfd8e177d35b76cad7cd43941f8e5e5acac" datatype="html">
+ <source>Trash</source>
+ <target>垃圾桶</target>
+ </trans-unit>
+ <trans-unit id="a674ab267d1934bf395f87ca1503fd474296893f" datatype="html">
+ <source>iSCSI Topology</source>
+ <target>iSCSI 拓撲</target>
+ </trans-unit>
+ <trans-unit id="051dcc342cfa5c1eaf187a2001aaa162379a160c" datatype="html">
+ <source>Configure</source>
+ <target>Configure</target>
+ </trans-unit>
+ <trans-unit id="9e515f954730279c31d5301f02479666d6264e8b" datatype="html">
+ <source>Changing these parameters from their default values is usually not necessary.</source>
+ <target>通常不需要變更這些參數的預設值。</target>
+ </trans-unit>
+ <trans-unit id="4e2591df099ddac796cda401c5f282da779d45f2" datatype="html">
+ <source>Identifier</source>
+ <target>Identifier</target>
+ </trans-unit>
+ <trans-unit id="62480a4859976427cf18fc8ef41d3a438eda0412" datatype="html">
+ <source>lun</source>
+ <target>lun</target>
+ </trans-unit>
+ <trans-unit id="8afc9eb4405e0aa554b2ba14140ef790cdecc040" datatype="html">
+ <source>wwn</source>
+ <target>wwn</target>
+ </trans-unit>
+ <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
+ <source>Settings</source>
+ <target>設定</target>
+ </trans-unit>
+ <trans-unit id="69a47cbabcc51ca942606e1d8da0ec11f98a2690" datatype="html">
+ <source>Backstore</source>
+ <target>支援儲存</target>
+ </trans-unit>
+ <trans-unit id="68e710782ccb5398b3acb8844caf0b199da2c3da" datatype="html">
+ <source>Confirm</source>
+ <target>確認</target>
+ </trans-unit>
+ <trans-unit id="339878da255ab55447c43afef8d9b2f9753bf5f6" datatype="html">
+ <source>Advanced Settings</source>
+ <target>進階設定</target>
+ </trans-unit>
+ <trans-unit id="1406c2fb12a20c1528b19bcc5e24a6a2386167f3" datatype="html">
+ <source>Target IQN</source>
+ <target>目標 IQN</target>
+ </trans-unit>
+ <trans-unit id="5fe42339be910372fa689f559155631862d218e8" datatype="html">
+ <source>IQN has wrong pattern.</source>
+ <target>IQN 模式錯誤。</target>
+ </trans-unit>
+ <trans-unit id="47d1bfe4f5b3f292e1202dfe691195b10cb99500" datatype="html">
+ <source>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</source>
+ <target>IQN 模式應如下所示︰「iqn.$year-$month.$reversedAddress:$definedName」</target>
+ </trans-unit>
+ <trans-unit id="c8ada4b53396d8366db00a435acc61d53d857047" datatype="html">
+ <source>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</source>
+ <target>例如:iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</target>
+ </trans-unit>
+ <trans-unit id="e60c11e1b1dfbbeda577364b8de39ded2d796c5e" datatype="html">
+ <source>More information</source>
+ <target>更多資訊</target>
+ </trans-unit>
+ <trans-unit id="9b1aa85dfc6849196e64060db02c5410de69b7a1" datatype="html">
+ <source>This target has modified advanced settings.</source>
+ <target>此目標的進階設定存在修改。</target>
+ </trans-unit>
+ <trans-unit id="6990ad8d6182662e864495ac31c3758cda1c7a28" datatype="html">
+ <source>Portals</source>
+ <target>入口網站</target>
+ </trans-unit>
+ <trans-unit id="c3638c01b6c34066438909713ec96087c813fc7e" datatype="html">
+ <source>At least
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> gateways are required.
+ </source>
+ <target>至少需要
+ <x id="INTERPOLATION" equiv-text="{{ minimum_gateways }}"/> 個物件閘道。
+ </target>
+ </trans-unit>
+ <trans-unit id="6a3ac2b4137d723fd9878cd357c2012ff6c07973" datatype="html">
+ <source>Add portal</source>
+ <target>新增入口網站</target>
+ </trans-unit>
+ <trans-unit id="9aff25be088f0efe3eaaf62edf2bff41cc41a617" datatype="html">
+ <source>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </source>
+ <target>Backstore:
+ <x id="INTERPOLATION" equiv-text="{{ imagesSettings[image].backstore | iscsiBackstore }}"/>. 
+ </target>
+ </trans-unit>
+ <trans-unit id="e3484cae8b118c576ca2815bf9c9406c2eb2cae3" datatype="html">
+ <source>This image has modified settings.</source>
+ <target>此影像的設定存在修改。</target>
+ </trans-unit>
+ <trans-unit id="1dff11e0820b6722ab240169f1232d70a54beaaa" datatype="html">
+ <source>Duplicated LUN numbers.</source>
+ <target>Duplicated LUN numbers.</target>
+ </trans-unit>
+ <trans-unit id="bf2dccf92ccff6e3b091792bf4205595406e1bfb" datatype="html">
+ <source>Duplicated WWN.</source>
+ <target>Duplicated WWN.</target>
+ </trans-unit>
+ <trans-unit id="808038f912fdc7f0e03f82d4afd3bf9178527fc8" datatype="html">
+ <source>Add image</source>
+ <target>新增影像</target>
+ </trans-unit>
+ <trans-unit id="66c5fb27f52e75b70ca4b670b9b15a2a51cf9543" datatype="html">
+ <source>ACL authentication</source>
+ <target>ACL 驗證</target>
+ </trans-unit>
+ <trans-unit id="419c8b402609dcf49ae4932a5a4647dc8d79bbaf" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</target>
+ </trans-unit>
+ <trans-unit id="938050960d6653fddfcfd42425e18fb35a308262" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="f494bd31f095f6dcc656ce87ec2dcf07a2e9b30c" datatype="html">
+ <source>Initiators</source>
+ <target>啟動器</target>
+ </trans-unit>
+ <trans-unit id="e98239d8a6be1100119ff4b5630c822b82786740" datatype="html">
+ <source>Initiator</source>
+ <target>啟動器</target>
+ </trans-unit>
+ <trans-unit id="f2c5059d8cda15d8d03e2cce30f2d139623d9a91" datatype="html">
+ <source>Client IQN</source>
+ <target>用戶端 IQN</target>
+ </trans-unit>
+ <trans-unit id="107d5aabce23d900f0a80e6ddc1c10e29aa0bed8" datatype="html">
+ <source>Initiator IQN needs to be unique.</source>
+ <target>啟動器 IQN 必須唯一。</target>
+ </trans-unit>
+ <trans-unit id="bbf0b34a3fcc80800fcb44b9e1e86931a530dfe3" datatype="html">
+ <source>Usernames must have a length of 8 to 64 characters and
+ can only contain letters, '.', '@', '-', '_' or ':'.</source>
+ <target>使用者名稱的長度必須介於 8 至 64 個字元之間,並且只能包含以下
+ 字元︰字母、「.」、「@」、「-」、「_」或「:」。</target>
+ </trans-unit>
+ <trans-unit id="fdfee5d7a27e1bdd97a176097277bee078de6aaf" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters
+ and can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="8406eb7415ee40e54d9ecb209abb056f06e3d666" datatype="html">
+ <source>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</source>
+ <target>Passwords must have a length of 12 to 16 characters and
+ can only contain letters, '@', '-', '_' or '/'.</target>
+ </trans-unit>
+ <trans-unit id="5d1878d5fc761cbe9614bfd87047a740c82a6951" datatype="html">
+ <source>Initiator belongs to a group. Images will be configure in the group.</source>
+ <target>啟動器屬於群組。影像須在群組中進行設定。 </target>
+ </trans-unit>
+ <trans-unit id="c0de67b9d97fafbf200f9451e8388ee8128a56ac" datatype="html">
+ <source>No items added.</source>
+ <target>未新增項目。</target>
+ </trans-unit>
+ <trans-unit id="d565e47726158e428ecdc952fc9233b9b7d7f049" datatype="html">
+ <source>Add initiator</source>
+ <target>新增啟動器</target>
+ </trans-unit>
+ <trans-unit id="c22ba03540aa3217da059f45e7eab138b51a96e2" datatype="html">
+ <source>Groups</source>
+ <target>群組</target>
+ </trans-unit>
+ <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+ <source>Group</source>
+ <target>群組</target>
+ </trans-unit>
+ <trans-unit id="3084948274cff4f56d0f431af47240e9cf02fcc7" datatype="html">
+ <source>Add group</source>
+ <target>新增群組</target>
+ </trans-unit>
+ <trans-unit id="a949d7e577902d0e5dc5d0971bb0170a21be7728" datatype="html">
+ <source>[object Object]</source>
+ <target>[object Object]</target>
+ </trans-unit>
+ <trans-unit id="ff92fbdec9fdd5054493eeda0d7ee8b450f83e72" datatype="html">
+ <source>RBD Configuration</source>
+ <target>RBD 組態</target>
+ </trans-unit>
+ <trans-unit id="b62d9efc8eb3b589904f6cb96a0406bbda55673a" datatype="html">
+ <source>Remove the local configuration value. The parent configuration value will be inherited and used instead.</source>
+ <target>移除本地組態值。將繼承並使用父組態值。</target>
+ </trans-unit>
+ <trans-unit id="963488a1010d46067b238c4ae917fab3907c0a3a" datatype="html">
+ <source>The mininum value is 0</source>
+ <target>最小值為 0</target>
+ </trans-unit>
+ <trans-unit id="66db799d67958d4b0765181d072df62e2d1c16f5" datatype="html">
+ <source>Issues</source>
+ <target>問題</target>
+ </trans-unit>
+ <trans-unit id="ef06d69259e587e28d52372455f44c7153cda7e7" datatype="html">
+ <source>Syncing</source>
+ <target>正在同步</target>
+ </trans-unit>
+ <trans-unit id="0b0901877d837d3fda16ba161eb74368d1c75b7a" datatype="html">
+ <source>Ready</source>
+ <target>準備就緒</target>
+ </trans-unit>
+ <trans-unit id="4057c56d63a7e9b140b1d01871a9229a5f30eb27" datatype="html">
+ <source>Edit pool mirror mode</source>
+ <target>編輯池鏡像模式</target>
+ </trans-unit>
+ <trans-unit id="e1f367f5feaab38f6637dd1f967c848b447dea2d" datatype="html">
+ <source>To edit the mirror mode for pool 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>, select a new mode from the list and click 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Update
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>若要編輯池
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> 
+ 的鏡像模式,請從清單中選取一個新模式,然後按一下 
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>更新
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="37e10df2d9c0c25ef04ac112c9c9a7723e8efae0" datatype="html">
+ <source>Mode</source>
+ <target>模式</target>
+ </trans-unit>
+ <trans-unit id="32ca348ef926b0a6a7a780b8b64c3a8239895cec" datatype="html">
+ <source>Peer clusters must be removed prior to disabling mirror.</source>
+ <target>在停用鏡像之前,必須先移除對等叢集。</target>
+ </trans-unit>
+ <trans-unit id="fa61522d482349707fd7dd03b90dc5781611b17f" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ pool mirror peer
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>
+ 池鏡像對等
+ </target>
+ </trans-unit>
+ <trans-unit id="4ddcb416c1c0aa1f54acf5beef1de81813e76fa6" datatype="html">
+ <source>{VAR_SELECT, select, edit {Edit} other {Add} }</source>
+ <target>{VAR_SELECT, select, edit {編輯} other {新增} }</target>
+ </trans-unit>
+ <trans-unit id="f7a13e4807afa6a9eda3db57a0a2a110dbae8ad7" datatype="html">
+ <source>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/> the pool
+ mirror peer attributes for pool
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/> and click
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>Submit
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>.
+ </source>
+ <target>
+ <x id="ICU" equiv-text="{mode, select, edit {...} other {...}}"/>池
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>
+ <x id="INTERPOLATION" equiv-text="{{ poolName }}"/>
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>的
+ 鏡像對等屬性,然後按一下
+ <x id="START_TAG_KBD" ctype="x-kbd" equiv-text="<kbd>"/>提交
+ <x id="CLOSE_TAG_KBD" ctype="x-kbd" equiv-text="</kbd>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="d3cc964811f852a168f4a2d5daa59068abc5cf53" datatype="html">
+ <source>Cluster Name</source>
+ <target>叢集名稱</target>
+ </trans-unit>
+ <trans-unit id="b631721fc56cb7fb1cbd07b802a487c5753f6a2d" datatype="html">
+ <source>The cluster name is not valid.</source>
+ <target>叢集名稱無效。</target>
+ </trans-unit>
+ <trans-unit id="ca6deafa31bf421f85094807982aee4bcb20a3ae" datatype="html">
+ <source>CephX ID</source>
+ <target>CephX ID</target>
+ </trans-unit>
+ <trans-unit id="7539188a568c3d553cbde1bacaf32310c4264e24" datatype="html">
+ <source>CephX ID...</source>
+ <target>CephX ID...</target>
+ </trans-unit>
+ <trans-unit id="a1c45b594b0fba22fc64e80c793a7ffe005fdb0e" datatype="html">
+ <source>The CephX ID is not valid.</source>
+ <target>CephX ID 無效。</target>
+ </trans-unit>
+ <trans-unit id="20861576fcfce773c918c782cd4f5adf32382921" datatype="html">
+ <source>Monitor Addresses</source>
+ <target>監控程式位址</target>
+ </trans-unit>
+ <trans-unit id="fa28eeed2b4bd4ccbe6e9349a1c2b3cb1c5de70a" datatype="html">
+ <source>Comma-delimited addresses...</source>
+ <target>逗號分隔的位址...</target>
+ </trans-unit>
+ <trans-unit id="dc016c82fd85848d5c1b2fd0e8469ee2027d9c16" datatype="html">
+ <source>The monitory address is not valid.</source>
+ <target>監控程式位址無效。</target>
+ </trans-unit>
+ <trans-unit id="e0ac55b83dc6739e62bc655cfe375b67c93e7f4a" datatype="html">
+ <source>CephX Key</source>
+ <target>CephX 金鑰</target>
+ </trans-unit>
+ <trans-unit id="f53434bcb95bd86f1df9c8e22966f757614fc4ad" datatype="html">
+ <source>Base64-encoded key...</source>
+ <target>Base64 編碼的金鑰...</target>
+ </trans-unit>
+ <trans-unit id="4cd83164cd4f66b4abc2863f9ce6f599d789e4ca" datatype="html">
+ <source>CephX key must be base64 encoded.</source>
+ <target>CephX 金鑰必須為 Base64 編碼的金鑰。</target>
+ </trans-unit>
+ <trans-unit id="1d8a7c8aea58294a3c57c23af0468ddf0ba0c9c7" datatype="html">
+ <source>Pools List</source>
+ <target>池清單</target>
+ </trans-unit>
+ <trans-unit id="490e15ecc922965b6d8194754c87c5583aa071f3" datatype="html">
+ <source>The name can only consist of alphanumeric characters, dashes and underscores.</source>
+ <target>名稱只能由英數字元、破折號和底線組成。</target>
+ </trans-unit>
+ <trans-unit id="9edc2b494e660618af3e5225f68d40b7ca67629c" datatype="html">
+ <source>The chosen erasure code profile name is already in use.</source>
+ <target>所選的糾刪碼設定檔名稱已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="ef9ff0e6227947b48dfab4ac39ade04af758913b" datatype="html">
+ <source>Plugin</source>
+ <target>外掛程式</target>
+ </trans-unit>
+ <trans-unit id="dd69b31bce8f630eac1d4762b0bbcf72ce19d193" datatype="html">
+ <source>Data chunks (k)</source>
+ <target>資料區塊 (k)</target>
+ </trans-unit>
+ <trans-unit id="b0d26a6172d32cb81218fe2103c54a818cbc1189" datatype="html">
+ <source>Must be equal to or greater than 2.</source>
+ <target>必須大於或等於 2。</target>
+ </trans-unit>
+ <trans-unit id="dab3a299ead121169b8e08ed618c3b6a2f66691b" datatype="html">
+ <source>Coding chunks (m)</source>
+ <target>編碼區塊 (m)</target>
+ </trans-unit>
+ <trans-unit id="1e2773e5bd4948193f18f2361d663ecc3988c656" datatype="html">
+ <source>Must be equal to or greater than 1.</source>
+ <target>必須大於或等於 1。</target>
+ </trans-unit>
+ <trans-unit id="6cde4c945a49a260c0a47bcc7cd956846930a5f7" datatype="html">
+ <source>Durability estimator (c)</source>
+ <target>持久性估值 (c)</target>
+ </trans-unit>
+ <trans-unit id="af668c2a095a979ea2b4e43cd82c2120ab56c21c" datatype="html">
+ <source>Locality (l)</source>
+ <target>本地性 (l)</target>
+ </trans-unit>
+ <trans-unit id="d455a110bf6d2235e314e295ce1dfeee93d3dff2" datatype="html">
+ <source>Crush failure domain</source>
+ <target>CRUSH 故障網域</target>
+ </trans-unit>
+ <trans-unit id="b74a495f041f7dd102eee5c0bbc9e03083b538ae" datatype="html">
+ <source>Crush Locality</source>
+ <target>CRUSH 本地性</target>
+ </trans-unit>
+ <trans-unit id="a2f14a73f7a6e94479f67423cc51102da8d6f524" datatype="html">
+ <source>None</source>
+ <target>無</target>
+ </trans-unit>
+ <trans-unit id="2981733b912b693a9dd9d915d6d34f4692cc874a" datatype="html">
+ <source>Technique</source>
+ <target>技術</target>
+ </trans-unit>
+ <trans-unit id="e0098b6e47b04ec817361f384ce81d454ba5c0bb" datatype="html">
+ <source>Packetsize</source>
+ <target>封包大小</target>
+ </trans-unit>
+ <trans-unit id="c0252cd81ca54d0a2f69ec9ccf4248e73df5aa4a" datatype="html">
+ <source>Crush root</source>
+ <target>CRUSH 根</target>
+ </trans-unit>
+ <trans-unit id="1548d5c76f0406ddd1ba3c557e1e6db22e95b340" datatype="html">
+ <source>Crush device class</source>
+ <target>CRUSH 裝置類別</target>
+ </trans-unit>
+ <trans-unit id="5e85feb6f9f0334366e46ee09ca6b8df52397432" datatype="html">
+ <source>any</source>
+ <target>任何</target>
+ </trans-unit>
+ <trans-unit id="03d84645f6e019c5a43909bbf2ea1696ee88332c" datatype="html">
+ <source>Directory</source>
+ <target>目錄</target>
+ </trans-unit>
+ <trans-unit id="16e113230b6b0d3165e076300880542bac7c8138" datatype="html">
+ <source>The chosen Ceph pool name is already in use.</source>
+ <target>所選的 Ceph 池名稱已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="b85c657469e5ec8231c3de99b22f437bc01ffde5" datatype="html">
+ <source>Pool type</source>
+ <target>池類型</target>
+ </trans-unit>
+ <trans-unit id="526c5443254c3b126eedb264840ffe827727bfd3" datatype="html">
+ <source>-- Select a pool type --</source>
+ <target>-- 選取池類型 --</target>
+ </trans-unit>
+ <trans-unit id="0aa21053410a94aa61d16985a4e95fd65523430d" datatype="html">
+ <source>Placement groups</source>
+ <target>放置群組</target>
+ </trans-unit>
+ <trans-unit id="6301f1391d726f8f450bb358058534db19541ca9" datatype="html">
+ <source>At least one placement group is needed!</source>
+ <target>至少需要一個放置群組!</target>
+ </trans-unit>
+ <trans-unit id="ba9469a1ce6ed36e039c1f67247c8c81a5c71449" datatype="html">
+ <source>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</source>
+ <target>您的叢集無法處理這麼多的 PG。請重新計算所需的 PG 數量。</target>
+ </trans-unit>
+ <trans-unit id="80ac68cd883369dac20688bc32b4cb33291b5e50" datatype="html">
+ <source>Calculation help</source>
+ <target>計算說明</target>
+ </trans-unit>
+ <trans-unit id="37dd747f97e873d4280500da71b0076805f530a1" datatype="html">
+ <source>The current PGs settings were calculated for you, you
+ should make sure the values suit your needs before submit.</source>
+ <target>已為您計算目前的 PG 設定,您
+ 應在提交前確定這些值符合您的需求。</target>
+ </trans-unit>
+ <trans-unit id="33150f22ce5348aa6c499bd092c3f4f3695d62cc" datatype="html">
+ <source>Crush ruleset</source>
+ <target>CRUSH 規則集</target>
+ </trans-unit>
+ <trans-unit id="73a6b31116b3cc322af951daa0bafdc169e6c42e" datatype="html">
+ <source>-- Select a crush rule --</source>
+ <target>-- 選取 CRUSH 規則 --</target>
+ </trans-unit>
+ <trans-unit id="92da80699921e89fb19372e25b8d0f3b9fa427fc" datatype="html">
+ <source>Crush rule</source>
+ <target>CRUSH 規則</target>
+ </trans-unit>
+ <trans-unit id="5489e9f96835f469f6f728a00d8efa88ea5bc940" datatype="html">
+ <source>Crush steps</source>
+ <target>CRUSH 步驟</target>
+ </trans-unit>
+ <trans-unit id="54a53b1b402aafff5b992ee9b64e409fbfe9074f" datatype="html">
+ <source>The rule can't be used in the current cluster as it has
+ to few OSDs to meet the minimum required OSD by this rule.</source>
+ <target>無法在目前的叢集中使用此規則,因為叢集的
+ OSD 數量過少,無法滿足規則所需的最低 OSD 數量。</target>
+ </trans-unit>
+ <trans-unit id="a43b2695131b48b76cebba676aba98a2bee17515" datatype="html">
+ <source>Replicated size</source>
+ <target>複製大小</target>
+ </trans-unit>
+ <trans-unit id="7bff144a4c4dc63b0e18fff2617d61a7ebdf2b6c" datatype="html">
+ <source>Minimum:
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </source>
+ <target>最低︰
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1a9c54b41f6d58a74e5d0aa3429ed0c87a482551" datatype="html">
+ <source>Maximum:
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </source>
+ <target>最高︰
+ <x id="INTERPOLATION" equiv-text="{{ getMaxSize() }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="43c6dd9233d6a8242cec2b025d25c273244d8d61" datatype="html">
+ <source>The size specified is out of range. A value from
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> to
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> is valid.
+ </source>
+ <target>指定的大小超出了範圍。介於
+ <x id="INTERPOLATION" equiv-text="{{ getMinSize() }}"/> 至
+ <x id="INTERPOLATION_1" equiv-text="{{ getMaxSize() }}"/> 之間的值才有效。
+ </target>
+ </trans-unit>
+ <trans-unit id="9de7dde00e2139cc4bd03b1837afbe72ad15a1ff" datatype="html">
+ <source>Erasure code profile</source>
+ <target>糾刪碼設定檔</target>
+ </trans-unit>
+ <trans-unit id="39b4620e6bd444e0a57a0a5c03fa8c96d7fe5235" datatype="html">
+ <source>-- No erasure code profile available --</source>
+ <target>-- 沒有可用的糾刪碼設定檔 --</target>
+ </trans-unit>
+ <trans-unit id="498561757390d5528b263ce450d5f38efb00266d" datatype="html">
+ <source>-- Select an erasure code profile --</source>
+ <target>-- 選取糾刪碼設定檔 --</target>
+ </trans-unit>
+ <trans-unit id="1c870fb00256b8a5b9cb9cd1a124e6390b9bc639" datatype="html">
+ <source>EC Overwrites</source>
+ <target>EC 覆寫</target>
+ </trans-unit>
+ <trans-unit id="f1abafaeb40ce52355ddcc24686e3cd17b64e08a" datatype="html">
+ <source>Applications</source>
+ <target>應用程式</target>
+ </trans-unit>
+ <trans-unit id="2208d63d5940ce656006a220102b1eb2b5e553da" datatype="html">
+ <source>Compression</source>
+ <target>壓縮</target>
+ </trans-unit>
+ <trans-unit id="6c6f25c47da62ec597c6057a36ddfc3209811ec5" datatype="html">
+ <source>Algorithm</source>
+ <target>演算法</target>
+ </trans-unit>
+ <trans-unit id="4903231d42089325a28892c0fde1aed46b733ae6" datatype="html">
+ <source>-- No erasure compression algorithm available --</source>
+ <target>-- 沒有可用的糾刪壓縮演算法 --</target>
+ </trans-unit>
+ <trans-unit id="5d68ddb254275f8f44221e9ad6d8ceeb59ca46a6" datatype="html">
+ <source>Minimum blob size</source>
+ <target>Blob 最小大小</target>
+ </trans-unit>
+ <trans-unit id="fb2f176df80647137cbb02bbeb29e5dec707a400" datatype="html">
+ <source>e.g., 128KiB</source>
+ <target>例如 128 KiB</target>
+ </trans-unit>
+ <trans-unit id="1b7f6e53a4521c6eb3ced4c007fdd4cf80bb7707" datatype="html">
+ <source>Value should be greater than 0</source>
+ <target>值應大於 0</target>
+ </trans-unit>
+ <trans-unit id="8db98ab14b4e207ec763dfdefbc2dae367aab1cc" datatype="html">
+ <source>Value should be less than the maximum blob size</source>
+ <target>Value should be less than the maximum blob size</target>
+ </trans-unit>
+ <trans-unit id="151efb127a9a4dd25259a0b2055442318a141f5b" datatype="html">
+ <source>Maximum blob size</source>
+ <target>Blob 最大大小</target>
+ </trans-unit>
+ <trans-unit id="0c656f0e346bbadf46eb1a5d20d0307a3bd20ba8" datatype="html">
+ <source>e.g., 512KiB</source>
+ <target>例如 512 KiB</target>
+ </trans-unit>
+ <trans-unit id="0a65a24eee8a026f3b1113fe9e157e9a0dd69486" datatype="html">
+ <source>Value should be greater than the minimum blob size</source>
+ <target>值應大於 blob 最小大小</target>
+ </trans-unit>
+ <trans-unit id="261ba09c4a59de83f48f52a23fd328da37e61ff4" datatype="html">
+ <source>Ratio</source>
+ <target>比率</target>
+ </trans-unit>
+ <trans-unit id="c1430457a9c3c66366e51d76bf10396014c576be" datatype="html">
+ <source>Compression ratio</source>
+ <target>壓縮率</target>
+ </trans-unit>
+ <trans-unit id="ae5ce6de352cde949998fb10754459c3a4eb183b" datatype="html">
+ <source>Value should be between 0.0 and 1.0</source>
+ <target>值應介於 0.0 至 1.0 之間</target>
+ </trans-unit>
+ <trans-unit id="4b673e771a3f6b056837b22ef19a825386046095" datatype="html">
+ <source>It's not possible to create an RBD pool with '/' in the name.</source>
+ <target>無法建立名稱中包含「/」的 RBD 池。</target>
+ </trans-unit>
+ <trans-unit id="a9c02674c6e4936562d1146e1ecf0c4240dfcf96" datatype="html">
+ <source>Please change the name or remove 'rbd' from the applications list.</source>
+ <target>請變更名稱或將「rbd」從應用程式清單中移除。</target>
+ </trans-unit>
+ <trans-unit id="3938a411d76796f8ae73b72ea4c77661207453bd" datatype="html">
+ <source>Cache Tiers Details</source>
+ <target>快取層詳細資料</target>
+ </trans-unit>
+ <trans-unit id="9424badb7e0c6ac792d020d7830645b529a80aad" datatype="html">
+ <source>Please consult the
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>
+ on how to configure and enable the Object Gateway management functionality.
+ </source>
+ <target>如需了解如何設定和啟用物件閘道管理功能,
+ 請參閱
+ <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>文件
+ <x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>。
+ </target>
+ </trans-unit>
+ <trans-unit id="479488ab6e91ecb375484edc78bee3d13467f33f" datatype="html">
+ <source>Daemons List</source>
+ <target>精靈清單</target>
+ </trans-unit>
+ <trans-unit id="eeba399c4dae8d4890c27b7a2cd2dc28fcf8b5f9" datatype="html">
+ <source>Performance Counters</source>
+ <target>效能計數器</target>
+ </trans-unit>
+ <trans-unit id="5f67f2247b9c6bbaf24a0f2d37f4ac0537c6fa53" datatype="html">
+ <source>Loading bucket data...</source>
+ <target>正在載入桶資料...</target>
+ </trans-unit>
+ <trans-unit id="8508c0ab851ad91fd0410da1266c02b0ef9d3ff9" datatype="html">
+ <source>The bucket data could not be loaded.</source>
+ <target>無法載入桶資料。</target>
+ </trans-unit>
+ <trans-unit id="2798cc1e152b1ec07fd8daf94a2a073d1ba1ebcc" datatype="html">
+ <source>Id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="db4e1a734518691b128ef40b939cc673f01d03a6" datatype="html">
+ <source>The value is not valid.</source>
+ <target>該值無效。</target>
+ </trans-unit>
+ <trans-unit id="0ee5132a8da30e0b7f9f5c70dbc91928d17dd909" datatype="html">
+ <source>Owner</source>
+ <target>擁有者</target>
+ </trans-unit>
+ <trans-unit id="8e4c918357c7445fbf19a203e5f0f0ece1960b3b" datatype="html">
+ <source>-- Select a user --</source>
+ <target>-- 選取使用者 --</target>
+ </trans-unit>
+ <trans-unit id="45cc8ca94b5a50842a9a8ef804a5ab089a38ae5c" datatype="html">
+ <source>ID</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="e5c51963a9c553b29427ef783bbb69fa6634fa8c" datatype="html">
+ <source>Index type</source>
+ <target>索引類型</target>
+ </trans-unit>
+ <trans-unit id="8e6f950a32eaea32ec7e192f9ca3d3dfe469d4ba" datatype="html">
+ <source>Placement rule</source>
+ <target>放置規則</target>
+ </trans-unit>
+ <trans-unit id="6972d213e31c4ea4f887e60db99d9881bc8fcd3e" datatype="html">
+ <source>Marker</source>
+ <target>標記</target>
+ </trans-unit>
+ <trans-unit id="47b02acd2d3254d1ace1926f840523f154ebef71" datatype="html">
+ <source>Maximum marker</source>
+ <target>最大標記數</target>
+ </trans-unit>
+ <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+ <source>Version</source>
+ <target>版本</target>
+ </trans-unit>
+ <trans-unit id="092fa3a7df9168b14d3f83a77a4035e92b92ce15" datatype="html">
+ <source>Master version</source>
+ <target>主版本</target>
+ </trans-unit>
+ <trans-unit id="97434cc5001d407f90c7447a12d9e8e6848a2aa3" datatype="html">
+ <source>Modification time</source>
+ <target>修改時間</target>
+ </trans-unit>
+ <trans-unit id="90fe2e41e7fde38453ce4e619efeea9bc6adea9c" datatype="html">
+ <source>Zonegroup</source>
+ <target>區域群組</target>
+ </trans-unit>
+ <trans-unit id="649a410bd0ace333d067d8fa22f12bdbdb43533b" datatype="html">
+ <source>Bucket quota</source>
+ <target>桶定額</target>
+ </trans-unit>
+ <trans-unit id="f50a33d3c339f8f4a465141f8caa5d2d8c005251" datatype="html">
+ <source>Enabled</source>
+ <target>已啟用</target>
+ </trans-unit>
+ <trans-unit id="cef1595d040e77cbb4466e60382028d4c2040cac" datatype="html">
+ <source>Maximum size</source>
+ <target>最大大小</target>
+ </trans-unit>
+ <trans-unit id="aa6fb95c355f172bda303de1ce2f38c251a149cf" datatype="html">
+ <source>Unlimited</source>
+ <target>無限制</target>
+ </trans-unit>
+ <trans-unit id="ee862a800364b4d11f9b8cb9955a28a60f840a45" datatype="html">
+ <source>Maximum objects</source>
+ <target>最大物件數</target>
+ </trans-unit>
+ <trans-unit id="49c614babd1950adb2be75df4e2c9747286d6adc" datatype="html">
+ <source>-- Select a username --</source>
+ <target>-- 選取使用者名稱 --</target>
+ </trans-unit>
+ <trans-unit id="c217ee914725a37e9dd2336c721c8e63e9666bdc" datatype="html">
+ <source>Auto-generate key</source>
+ <target>自動產生金鑰</target>
+ </trans-unit>
+ <trans-unit id="2f1c1c0f2bce4c9f92d1a2061e8161cb0006c31a" datatype="html">
+ <source>Access key</source>
+ <target>存取金鑰</target>
+ </trans-unit>
+ <trans-unit id="b864acb67296a9819c1db0069c4c47d8b5ce8f44" datatype="html">
+ <source>Secret key</source>
+ <target>機密金鑰</target>
+ </trans-unit>
+ <trans-unit id="69b6ac577a19acc39fc0c22342092f327fff2529" datatype="html">
+ <source>Email address</source>
+ <target>電子郵件地址</target>
+ </trans-unit>
+ <trans-unit id="92f3f203270a29b3001871153f02c063484a1574" datatype="html">
+ <source>Suspended</source>
+ <target>已暫停</target>
+ </trans-unit>
+ <trans-unit id="8011e20c5bbe51602d459a860fbf29b599b55edd" datatype="html">
+ <source>System</source>
+ <target>系統</target>
+ </trans-unit>
+ <trans-unit id="f120423a48cf96636bc415daf5ac041ea8c6503e" datatype="html">
+ <source>{VAR_SELECT, select, 0 {No} 1 {Yes} }</source>
+ <target>{VAR_SELECT, select, 0 {否} 1 {是} }</target>
+ </trans-unit>
+ <trans-unit id="db18a2772988415466a7f75dc42663ce78c9c1d3" datatype="html">
+ <source>Maximum buckets</source>
+ <target>最大桶數</target>
+ </trans-unit>
+ <trans-unit id="2c4c62e8ba24601be5cfe7dc5d32c24bbbd4b53c" datatype="html">
+ <source>Subusers</source>
+ <target>子使用者</target>
+ </trans-unit>
+ <trans-unit id="17bb3082e6fe5003203ef992a3714172334631a1" datatype="html">
+ <source>Capabilities</source>
+ <target>功能</target>
+ </trans-unit>
+ <trans-unit id="36ad38f9c1a1485e09b67778a28af84553290ffb" datatype="html">
+ <source>User quota</source>
+ <target>使用者定額</target>
+ </trans-unit>
+ <trans-unit id="2aba1e87039819aca3b70faa9aa848c12bf139ca" datatype="html">
+ <source>Show</source>
+ <target>顯示</target>
+ </trans-unit>
+ <trans-unit id="0bcd5ef19af0f1b814141ca8c57df623d8270088" datatype="html">
+ <source>Keys</source>
+ <target>金鑰</target>
+ </trans-unit>
+ <trans-unit id="1221ca97d19eaa9a7bc0c5243d5fc5befe1d2314" datatype="html">
+ <source>-- Select a type --</source>
+ <target>-- 選取類型 --</target>
+ </trans-unit>
+ <trans-unit id="d1b8990332af18f1c5159a6061ca889bcbb28432" datatype="html">
+ <source>Permission</source>
+ <target>許可權</target>
+ </trans-unit>
+ <trans-unit id="a08c589f82f69d892307288da14190ae1dd583d5" datatype="html">
+ <source>-- Select a permission --</source>
+ <target>-- 選取許可權 --</target>
+ </trans-unit>
+ <trans-unit id="b2841767821d6b66238c34d07e413b0af67aee92" datatype="html">
+ <source>Subuser</source>
+ <target>子使用者</target>
+ </trans-unit>
+ <trans-unit id="bd59fc25a7bd98cff3e75117c09697c8a007a514" datatype="html">
+ <source>The chosen subuser ID is already in use.</source>
+ <target>所選的子使用者 ID 已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="3d386c357ebcbc04ed05c4babd5a03626f9b1674" datatype="html">
+ <source>read, write</source>
+ <target>讀取、寫入</target>
+ </trans-unit>
+ <trans-unit id="84e3e3f9a4f31a039b648c97debf95fcb20f4c4a" datatype="html">
+ <source>full</source>
+ <target>完整</target>
+ </trans-unit>
+ <trans-unit id="b6bf81d032a2316464f9df2f0d2f3d753f89f0d3" datatype="html">
+ <source>Swift key</source>
+ <target>Swift 金鑰</target>
+ </trans-unit>
+ <trans-unit id="1e0c12685d50d47448ceed9423977ef39775c037" datatype="html">
+ <source>Auto-generate secret</source>
+ <target>自動產生機密金鑰</target>
+ </trans-unit>
+ <trans-unit id="3d1c7a6004bd5d86a7fa096ae24209e8aa7a53e3" datatype="html">
+ <source>Loading user data...</source>
+ <target>正在載入使用者資料...</target>
+ </trans-unit>
+ <trans-unit id="faa5d834ab28571423d794d32b57998920efb65f" datatype="html">
+ <source>The user data could not be loaded.</source>
+ <target>無法載入使用者資料。</target>
+ </trans-unit>
+ <trans-unit id="6aaf5d2a304167272ac73e3b1d1c162e16c77858" datatype="html">
+ <source>The chosen user ID is already in use.</source>
+ <target>所選的使用者 ID 已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="df441e80db2157f9d272b75de724ba4a82b96b57" datatype="html">
+ <source>This is not a valid email address.</source>
+ <target>電子郵件地址無效。</target>
+ </trans-unit>
+ <trans-unit id="ca271adf154956b8fcb28f4f50a37acb3057ff7c" datatype="html">
+ <source>The chosen email address is already in use.</source>
+ <target>所選的電子郵件地址已在使用中。</target>
+ </trans-unit>
+ <trans-unit id="030197cebe938edf35422e92fe14183d06eb670b" datatype="html">
+ <source>Max. buckets</source>
+ <target>最大桶數</target>
+ </trans-unit>
+ <trans-unit id="623ac50f37a26caec6fd7cd519b653e3315cba25" datatype="html">
+ <source>The entered value must be &gt;= 0.</source>
+ <target>輸入的值必須大於或等於 0。</target>
+ </trans-unit>
+ <trans-unit id="583a219c524155c2314eb06ee29162bb315272a3" datatype="html">
+ <source>S3 key</source>
+ <target>S3 金鑰</target>
+ </trans-unit>
+ <trans-unit id="128d6efb51d9ddc7c0cc695a2deeca5b9523f6e4" datatype="html">
+ <source>There are no subusers.</source>
+ <target>沒有子使用者。</target>
+ </trans-unit>
+ <trans-unit id="8c49635e3672c82d9cf3b416a0d1a03460191699" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ subuserLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="67c746c1ba9dab4351fedc4c7cba4e6d6b0dbc47" datatype="html">
+ <source>S3</source>
+ <target>S3</target>
+ </trans-unit>
+ <trans-unit id="d6819038d608623503918fb2553f53d68231ec3a" datatype="html">
+ <source>There are no keys.</source>
+ <target>沒有金鑰。</target>
+ </trans-unit>
+ <trans-unit id="8b1d0beb2246fd01d9b25400bf9c67cbd532baee" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.CREATE | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ s3keyLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6ddb5e991a3ecd2659fb520bc5acc81b67e08ddd" datatype="html">
+ <source>Swift</source>
+ <target>Swift</target>
+ </trans-unit>
+ <trans-unit id="1d01eccdda47fc907c5be35bcb16d2dcd02b0270" datatype="html">
+ <source>There are no capabilities.</source>
+ <target>沒有功能。</target>
+ </trans-unit>
+ <trans-unit id="af26a69a40b3a5477a7d062756a44c8d91f988a4" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{ actionLabels.ADD | titlecase }}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{ capabilityLabel | upperFirst }}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="6146e13ceca5fa5cc17b771b282fe5955f3d19fa" datatype="html">
+ <source>Unlimited size</source>
+ <target>大小不限</target>
+ </trans-unit>
+ <trans-unit id="f6db8aa7c99fdce18edb33dde57729acede2b308" datatype="html">
+ <source>Max. size</source>
+ <target>最大大小</target>
+ </trans-unit>
+ <trans-unit id="fc630b2093e880fffa19df99d5cd8b87605037f8" datatype="html">
+ <source>Unlimited objects</source>
+ <target>物件數不限</target>
+ </trans-unit>
+ <trans-unit id="6cda5a993d06f0bb10048be9d3aba6555aa9f356" datatype="html">
+ <source>Max. objects</source>
+ <target>最大物件數</target>
+ </trans-unit>
+ <trans-unit id="bd5a3b1c5a3c185c7bbb0e09a061d4cdc88ce5ad" datatype="html">
+ <source>Current</source>
+ <target>目前</target>
+ </trans-unit>
+ <trans-unit id="e5e7d62e942083a59b0b31f54e17cd7958186052" datatype="html">
+ <source>Updated discovery authentication</source>
+ <target>已更新探查驗證</target>
+ </trans-unit>
+ <trans-unit id="dd4ab758afd5fd5a6c6a25b2b30ff99d0c00e9ad" datatype="html">
+ <source>There are no portals available.</source>
+ <target>沒有可用的入口網站。</target>
+ </trans-unit>
+ <trans-unit id="83021e45778a4a230a14ca0c6d6ccdf05500ad93" datatype="html">
+ <source>There are no images available.</source>
+ <target>沒有可用的影像。</target>
+ </trans-unit>
+ <trans-unit id="86684eb21f8a768e1dbc659e3d5da6861db544a0" datatype="html">
+ <source>There are no images available. Please make sure you add an image to the target.</source>
+ <target>沒有可用的影像。請確定為目標新增一個影像。</target>
+ </trans-unit>
+ <trans-unit id="fffda6e440078f57eba93944ce051c593cc6ed7f" datatype="html">
+ <source>There are no initiators available. Please make sure you add an initiator to the target.</source>
+ <target>沒有可用的啟動器。請確定為目標新增一個啟動器。</target>
+ </trans-unit>
+ <trans-unit id="cea3c6fe490385eef1584cbc4983fda7ece24bb6" datatype="html">
+ <source>target</source>
+ <target>target</target>
+ </trans-unit>
+ <trans-unit id="38baeb215c17af9d9e295e371a57f4a48ab4c191" datatype="html">
+ <source>Target</source>
+ <target>目標</target>
+ </trans-unit>
+ <trans-unit id="99e094878070eebc1b972bac02aaa33b2bf83b35" datatype="html">
+ <source># Sessions</source>
+ <target># Sessions</target>
+ </trans-unit>
+ <trans-unit id="a87acd72dfb68b45175270695209550a85adf50c" datatype="html">
+ <source>iSCSI target</source>
+ <target>iSCSI target</target>
+ </trans-unit>
+ <trans-unit id="873b72903b1858a9cd6c8967521030b4d7d1435b" datatype="html">
+ <source>State</source>
+ <target>狀態</target>
+ </trans-unit>
+ <trans-unit id="02b75464c0dc0cf49ea0208211b6fbcad3bf728a" datatype="html">
+ <source># Targets</source>
+ <target># Targets</target>
+ </trans-unit>
+ <trans-unit id="13415637c325ceefee29111b31cb48701490adf7" datatype="html">
+ <source>Read Bytes</source>
+ <target>讀取位元組數</target>
+ </trans-unit>
+ <trans-unit id="e2ed82b7bbf4a006e60e6208c597b05d5b5556e9" datatype="html">
+ <source>Write Bytes</source>
+ <target>寫入位元組數</target>
+ </trans-unit>
+ <trans-unit id="6a32a5f58845ca840185ea9564682094e77a1d80" datatype="html">
+ <source>Read Ops</source>
+ <target>讀取操作數</target>
+ </trans-unit>
+ <trans-unit id="7c36cb8032af123d3550ffab2e1fa1e957c87fae" datatype="html">
+ <source>Write Ops</source>
+ <target>寫入操作數</target>
+ </trans-unit>
+ <trans-unit id="458c33846a8c7e2feb9404bcf06723784e756cdc" datatype="html">
+ <source>A/O Since</source>
+ <target>使用中/最佳化開始時間</target>
+ </trans-unit>
+ <trans-unit id="ff78f059449d44322f627d0f66df07abe476962b" datatype="html">
+ <source>Instance</source>
+ <target>例項</target>
+ </trans-unit>
+ <trans-unit id="9a541ec1a4319fffc16ad3b3ab2c2b6d251a829d" datatype="html">
+ <source>Hostname</source>
+ <target>主機名稱</target>
+ </trans-unit>
+ <trans-unit id="36fad7995cadfb3a6f0d43ef2db280146b3ca022" datatype="html">
+ <source>Issue</source>
+ <target>問題</target>
+ </trans-unit>
+ <trans-unit id="15793f4cbc261bedbc60f7105533dde536a3f42b" datatype="html">
+ <source>Progress</source>
+ <target>進度</target>
+ </trans-unit>
+ <trans-unit id="f39256070bfc0714020dfee08895421fc1527014" datatype="html">
+ <source>Disabled</source>
+ <target>已停用</target>
+ </trans-unit>
+ <trans-unit id="8c375764db42f5d736fb56d01b8052c006ccc8e2" datatype="html">
+ <source>Edit Mode</source>
+ <target>編輯模式</target>
+ </trans-unit>
+ <trans-unit id="45932f2a0ea524b3425f4320ee46a6d1c68977bc" datatype="html">
+ <source>Add Peer</source>
+ <target>新增對等</target>
+ </trans-unit>
+ <trans-unit id="d3dc34662e3cda0dad646221651cebd26f731485" datatype="html">
+ <source>Edit Peer</source>
+ <target>編輯對等</target>
+ </trans-unit>
+ <trans-unit id="e8a0ec0b6ee72db0f27c186e09640d1ed41964bd" datatype="html">
+ <source>Delete Peer</source>
+ <target>刪除對等</target>
+ </trans-unit>
+ <trans-unit id="314de06d6f64d39149e78e6d796585c0246fec0b" datatype="html">
+ <source>Leader</source>
+ <target>Leader</target>
+ </trans-unit>
+ <trans-unit id="7acaab450312114059ced9e3737798ee9aa738b1" datatype="html">
+ <source># Local</source>
+ <target>本地數量</target>
+ </trans-unit>
+ <trans-unit id="7a3ffd88868135c44be3994263bb8e49d8358884" datatype="html">
+ <source># Remote</source>
+ <target>遠端數量</target>
+ </trans-unit>
+ <trans-unit id="85ca0fd6a6ddd211023c70a25753122c5b978787" datatype="html">
+ <source>mirror peer</source>
+ <target>鏡像對等</target>
+ </trans-unit>
+ <trans-unit id="a6493c6ca346cd052da40423eda9c132de2b2002" datatype="html">
+ <source>Key</source>
+ <target>金鑰</target>
+ </trans-unit>
+ <trans-unit id="e9cac80fb5d9de66f0006d0bec530fd1fc69a674" datatype="html">
+ <source>RBD</source>
+ <target>RBD</target>
+ </trans-unit>
+ <trans-unit id="4130b1a836f2000cfe9a11fb62493dc42d444de7" datatype="html">
+ <source>Deep flatten</source>
+ <target>深層壓平</target>
+ </trans-unit>
+ <trans-unit id="7b17694d7cb8ecb7c8440bc999dac21b44455b33" datatype="html">
+ <source>Layering</source>
+ <target>分層</target>
+ </trans-unit>
+ <trans-unit id="6a072ce577c2079d0e0c31071a16824f6d22b84d" datatype="html">
+ <source>Exclusive lock</source>
+ <target>獨佔鎖定</target>
+ </trans-unit>
+ <trans-unit id="7354f01320bf936a7f85577c9f71402635c3a362" datatype="html">
+ <source>Object map (requires exclusive-lock)</source>
+ <target>物件對應 (需要獨佔鎖定)</target>
+ </trans-unit>
+ <trans-unit id="fb7e625c1152f1c102cd16460955d124edff1770" datatype="html">
+ <source>Journaling (requires exclusive-lock)</source>
+ <target>記錄 (需要獨佔鎖定)</target>
+ </trans-unit>
+ <trans-unit id="df4044632bfc211dd96544fc8f007dabbeeb506c" datatype="html">
+ <source>Fast diff (interlocked with object-map)</source>
+ <target>Fast diff (interlocked with object-map)</target>
+ </trans-unit>
+ <trans-unit id="7eb984588f4835f6d0187b33769b4b0f62821640" datatype="html">
+ <source>RBD snapshot rollback</source>
+ <target>RBD 快照復原</target>
+ </trans-unit>
+ <trans-unit id="4be22bf20ef82614ed53bcd3b912a85590aa71c9" datatype="html">
+ <source>Rollback</source>
+ <target>復原</target>
+ </trans-unit>
+ <trans-unit id="2a04c483708d261751d62082d6f03a50d4577b1e" datatype="html">
+ <source>RBD snapshot</source>
+ <target>RBD 快照</target>
+ </trans-unit>
+ <trans-unit id="fa96769d1ea86741297cb9b9769b0dcfde58c8b4" datatype="html">
+ <source>Deleted At</source>
+ <target>刪除位置</target>
+ </trans-unit>
+ <trans-unit id="e928864038ca70ee7d67bbf1fd71a01c3938a127" datatype="html">
+ <source>id</source>
+ <target>ID</target>
+ </trans-unit>
+ <trans-unit id="240c9c1e96dc38814922a83ad041dc815b084f32" datatype="html">
+ <source>type</source>
+ <target>類型</target>
+ </trans-unit>
+ <trans-unit id="c9d7ec7ee5b4e282f2228fa996651ec4ef5195a9" datatype="html">
+ <source>state</source>
+ <target>狀態</target>
+ </trans-unit>
+ <trans-unit id="5780e5c3b4fc2ae07836bb5221cec4f8d597630d" datatype="html">
+ <source>version</source>
+ <target>版本</target>
+ </trans-unit>
+ <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
+ <source>Host</source>
+ <target>主機</target>
+ </trans-unit>
+ <trans-unit id="fb69299354312c8954ecf324997ccafcd9f6b14b" datatype="html">
+ <source>root</source>
+ <target>根</target>
+ </trans-unit>
+ <trans-unit id="3c3a423d91e36ac6624e909fcd2669a25685f847" datatype="html">
+ <source>Rank</source>
+ <target>階層</target>
+ </trans-unit>
+ <trans-unit id="9596ecae8956e96921acef47aec787f6bdc37454" datatype="html">
+ <source>Daemon</source>
+ <target>精靈</target>
+ </trans-unit>
+ <trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
+ <source>Activity</source>
+ <target>活動</target>
+ </trans-unit>
+ <trans-unit id="e3a986984ae0c3b43af648c3fa638649d1c00348" datatype="html">
+ <source>Dentries</source>
+ <target>Dentry</target>
+ </trans-unit>
+ <trans-unit id="7c692ab865066967d73c6d64ec0691cc6ce91b93" datatype="html">
+ <source>Inodes</source>
+ <target>Inode</target>
+ </trans-unit>
+ <trans-unit id="45f210b96a2a6e91f52f153a4f8dc30662629f8e" datatype="html">
+ <source>Usage</source>
+ <target>使用率</target>
+ </trans-unit>
+ <trans-unit id="7db875ff4cc626d394f37fba95c075b2e4bfeb00" datatype="html">
+ <source>Standby daemons</source>
+ <target>待命精靈</target>
+ </trans-unit>
+ <trans-unit id="22e4e574b7f8abf58254f328792445b42e2a924a" datatype="html">
+ <source>The value can be updated at runtime.</source>
+ <target>該值可在執行時期更新。</target>
+ </trans-unit>
+ <trans-unit id="d7770de7b2343c9deeaa7ebf37ba3e35ca5c5988" datatype="html">
+ <source>Daemons/clients do not pull this value from the
+ monitor config database. We disallow setting this option via 'ceph config
+ set ...'. This option should be configured via ceph.conf or via the
+ command line.</source>
+ <target>精靈/用戶端不會從監控程式組態資料庫
+ 提取此值。我們不允許透過「ceph config set ...」
+ 設定此選項。應透過 ceph.conf 或使用指令行
+ 進行設定。</target>
+ </trans-unit>
+ <trans-unit id="83f11fd1dc503c37931ea6c1c5c1e8c2b4b597b6" datatype="html">
+ <source>Option takes effect only during daemon startup.</source>
+ <target>該選項僅在精靈啟動期間生效。</target>
+ </trans-unit>
+ <trans-unit id="837a07cd6a971038b8b1aa190c43440c9fdb5d8b" datatype="html">
+ <source>Option only affects cluster creation.</source>
+ <target>該選項僅影響叢集建立。</target>
+ </trans-unit>
+ <trans-unit id="2566a88eb247c918b71cfe5b354c31de0d4b01e5" datatype="html">
+ <source>Option only affects daemon creation.</source>
+ <target>該選項僅影響精靈建立。</target>
+ </trans-unit>
+ <trans-unit id="1cdc60cfc09c257625768f3d2082816cdef27279" datatype="html">
+ <source>Updated config option
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </source>
+ <target>已更新組態選項
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="d473e0f684a60db45d6f31e993f693f74290e056" datatype="html">
+ <source>Service</source>
+ <target>服務</target>
+ </trans-unit>
+ <trans-unit id="9951bb3983c7dba6fde013e05c922e4fe1a44367" datatype="html">
+ <source>Current value</source>
+ <target>目前的值</target>
+ </trans-unit>
+ <trans-unit id="4a01c175f90dd92b432f4a4a199d2c7bb9d997ff" datatype="html">
+ <source>Editable</source>
+ <target>可編輯</target>
+ </trans-unit>
+ <trans-unit id="1a6e6ad05508130b7a99ce5b15daf3227c2a930c" datatype="html">
+ <source>Updated options for module "
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>".
+ </source>
+ <target>已更新模組「
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>」的選項。
+ </target>
+ </trans-unit>
+ <trans-unit id="ac6c9212896d39b23811ed2dadab7d07336ec559" datatype="html">
+ <source>Enable</source>
+ <target>啟用</target>
+ </trans-unit>
+ <trans-unit id="6766a926d80bb7763785621098dae459d6226429" datatype="html">
+ <source>Disable</source>
+ <target>停用</target>
+ </trans-unit>
+ <trans-unit id="6a0b3657745dd7a2f2162f1cc790bf9004d0845d" datatype="html">
+ <source>Reconnecting, please wait ...</source>
+ <target>正在重新連接,請稍候...</target>
+ </trans-unit>
+ <trans-unit id="7099a8878af7a0a26fe5663c4f46cfe87142b75d" datatype="html">
+ <source>Public Address</source>
+ <target>公用位址</target>
+ </trans-unit>
+ <trans-unit id="cbdd1cdc0c7a87f55dd177bc44212f0fc4b80852" datatype="html">
+ <source>Open Sessions</source>
+ <target>開啟的工作階段</target>
+ </trans-unit>
+ <trans-unit id="37e58d1cbdf8212b380efa51422e42821d4f08e6" datatype="html">
+ <source>No In</source>
+ <target>禁止標示為 In</target>
+ </trans-unit>
+ <trans-unit id="12706eb5af17ff5ad77b3de21af368d24678e00b" datatype="html">
+ <source>OSDs that were previously marked out will not be marked back in when they start</source>
+ <target>之前標示為 out 的 OSD 在啟動時將不會重新標示為 in</target>
+ </trans-unit>
+ <trans-unit id="96114d7624d11dc90ca46cfa96145fe22118df76" datatype="html">
+ <source>No Out</source>
+ <target>禁止標示為 Out</target>
+ </trans-unit>
+ <trans-unit id="a2ef636fe1ddd56b63e4aaf3d292f33dbf735ef3" datatype="html">
+ <source>OSDs will not automatically be marked out after the configured interval</source>
+ <target>OSD 在設定的間隔過後將不會自動標示為 out</target>
+ </trans-unit>
+ <trans-unit id="ee50aefa9b8bde1e5429b48709a23abfe08358e0" datatype="html">
+ <source>No Up</source>
+ <target>禁止標示為 Up</target>
+ </trans-unit>
+ <trans-unit id="608929b939307e397586a98cea52ae38997c7273" datatype="html">
+ <source>OSDs are not allowed to start</source>
+ <target>不允許 OSD 啟動</target>
+ </trans-unit>
+ <trans-unit id="1751ab69c1e7f62927afedbf7116e0116316c551" datatype="html">
+ <source>No Down</source>
+ <target>禁止標示為 Down</target>
+ </trans-unit>
+ <trans-unit id="41fac86dfb65c1db690f3e87f6497cb73b281084" datatype="html">
+ <source>OSD failure reports are being ignored, such that the monitors will not mark OSDs down</source>
+ <target>將會忽略 OSD 故障報告,如此監控程式便不會將 OSD 標示為 down</target>
+ </trans-unit>
+ <trans-unit id="b2838c6165a9672a17db188f4dd9676574353dd8" datatype="html">
+ <source>Pause</source>
+ <target>暫停</target>
+ </trans-unit>
+ <trans-unit id="191d71dadcc8790573d46706a0b48211de4b8334" datatype="html">
+ <source>Pauses reads and writes</source>
+ <target>暫停讀取和寫入</target>
+ </trans-unit>
+ <trans-unit id="471d5ba75836f38c19992cf83d8822632d99e473" datatype="html">
+ <source>No Scrub</source>
+ <target>禁止整理</target>
+ </trans-unit>
+ <trans-unit id="5b8caa61814121bc36dac0c34a9e9de3cae74990" datatype="html">
+ <source>Scrubbing is disabled</source>
+ <target>整理已停用</target>
+ </trans-unit>
+ <trans-unit id="7f29a0ac1c797bdc0347dd5d0734ba83e96e7ce6" datatype="html">
+ <source>No Deep Scrub</source>
+ <target>禁止深層整理</target>
+ </trans-unit>
+ <trans-unit id="01da61ab216541a8d31259cebd16b10c7e5fc124" datatype="html">
+ <source>Deep Scrubbing is disabled</source>
+ <target>深層整理已停用</target>
+ </trans-unit>
+ <trans-unit id="0b86c7f18ac725de62c7e192dcfccd02c0dc40ab" datatype="html">
+ <source>No Backfill</source>
+ <target>禁止回填</target>
+ </trans-unit>
+ <trans-unit id="bd33a2bdc8fbed3b7469f3717c16d9aaa2851fdd" datatype="html">
+ <source>Backfilling of PGs is suspended</source>
+ <target>PG 回填已暫停</target>
+ </trans-unit>
+ <trans-unit id="7fbbd036394cfa623add40299757bc87df8eaa7e" datatype="html">
+ <source>No Recover</source>
+ <target>禁止復原</target>
+ </trans-unit>
+ <trans-unit id="f3ee9b451a64dca47299c9b4ae1091c2008068ad" datatype="html">
+ <source>Recovery of PGs is suspended</source>
+ <target>PG 復原已暫停</target>
+ </trans-unit>
+ <trans-unit id="de904148fe7e8d812218f50333ffe247900617c5" datatype="html">
+ <source>Bitwise Sort</source>
+ <target>按位元排序</target>
+ </trans-unit>
+ <trans-unit id="2613c9fde29785bcd75f0abeccb653d14d7527b3" datatype="html">
+ <source>Use bitwise sort</source>
+ <target>使用按位元排序</target>
+ </trans-unit>
+ <trans-unit id="2fe10d84250aeee365db244251d40934c70ff1e9" datatype="html">
+ <source>Purged Snapdirs</source>
+ <target>已清除 Snapdir</target>
+ </trans-unit>
+ <trans-unit id="6b22a5b780eda3c5d500cdac9c6d4f96978c38f1" datatype="html">
+ <source>OSDs have converted snapsets</source>
+ <target>OSD 已轉換 snapset</target>
+ </trans-unit>
+ <trans-unit id="c42f0ba60564dc5b977a8c7f3fdcde9efbb39c60" datatype="html">
+ <source>Recovery Deletes</source>
+ <target>復原刪除</target>
+ </trans-unit>
+ <trans-unit id="72fe39979198ea2ed6db6274b5029025cb316d90" datatype="html">
+ <source>Deletes performed during recovery instead of peering</source>
+ <target>在復原期間,而非在建立互聯時執行刪除</target>
+ </trans-unit>
+ <trans-unit id="1bb4a1f9127cefe624c173557a716d0ebb6d647c" datatype="html">
+ <source>PG Log Hard Limit</source>
+ <target>PG 記錄硬限制</target>
+ </trans-unit>
+ <trans-unit id="e03c0321397fdf7a9c22e8d6b5015424943c0a57" datatype="html">
+ <source>Puts a hard limit on pg log length</source>
+ <target>為 pg 記錄長度設定硬限制</target>
+ </trans-unit>
+ <trans-unit id="3c384e2e80c6b5eb24861fbf4225b69486cff4a3" datatype="html">
+ <source>Updated OSD Flags</source>
+ <target>已更新 OSD 旗標</target>
+ </trans-unit>
+ <trans-unit id="688578fcc739d6f0c5fb6c366dbb19d21c6d9e36" datatype="html">
+ <source>out</source>
+ <target>out</target>
+ </trans-unit>
+ <trans-unit id="cb0f69bdd4dea41d7d45c74b6e07f98de8a2ab26" datatype="html">
+ <source>in</source>
+ <target>in</target>
+ </trans-unit>
+ <trans-unit id="b5fbc7c7f007dd53b2318525bb7ff8b0376c9e37" datatype="html">
+ <source>down</source>
+ <target>down</target>
+ </trans-unit>
+ <trans-unit id="b58719bcb9184e1a7884d00d22d10899d59bf295" datatype="html">
+ <source>Mark</source>
+ <target>標示</target>
+ </trans-unit>
+ <trans-unit id="31a1c1aa03f1e5084750bedb4e3fdc04ce2cb6ca" datatype="html">
+ <source>OSD lost</source>
+ <target>OSD 遺失</target>
+ </trans-unit>
+ <trans-unit id="f3fc4c85c5b8f1dedea0496b72d0af9da7b9e0d9" datatype="html">
+ <source>marked lost</source>
+ <target>已標示為遺失</target>
+ </trans-unit>
+ <trans-unit id="40fedc157ad899a18ec40573f770d18b040959d2" datatype="html">
+ <source>Purge</source>
+ <target>清除</target>
+ </trans-unit>
+ <trans-unit id="c8b1475105463088593de1022ff6dceb523eae0e" datatype="html">
+ <source>OSD</source>
+ <target>OSD</target>
+ </trans-unit>
+ <trans-unit id="4f3cff08c7033b63bbccfe66006b1bcaea48ddd8" datatype="html">
+ <source>purged</source>
+ <target>已清除</target>
+ </trans-unit>
+ <trans-unit id="8e5d1b01eca6dce26a4751f0b19bda7a6ab8db5b" datatype="html">
+ <source>destroy</source>
+ <target>損毀</target>
+ </trans-unit>
+ <trans-unit id="495a06b78bf165a7b545fa002137f0846b094a3d" datatype="html">
+ <source>destroyed</source>
+ <target>已損毀</target>
+ </trans-unit>
+ <trans-unit id="43be3b1a806ff6b7eda5f9530b0595c081d2ad0f" datatype="html">
+ <source>Cluster-wide Flags</source>
+ <target>Cluster-wide Flags</target>
+ </trans-unit>
+ <trans-unit id="a1334f5ad3090d59be02f4add0f3e98c8697c504" datatype="html">
+ <source>Cluster-wide Recovery Priority</source>
+ <target>Cluster-wide Recovery Priority</target>
+ </trans-unit>
+ <trans-unit id="359dad5a3a912ef9dece3194035020856805aa96" datatype="html">
+ <source>PG scrub</source>
+ <target>PG scrub</target>
+ </trans-unit>
+ <trans-unit id="953144c420c2e5abd02e6a687433eac60fa852bd" datatype="html">
+ <source>PGs</source>
+ <target>PG</target>
+ </trans-unit>
+ <trans-unit id="7d3523ea9d35c274cef84043de8a2fdde540a9a1" datatype="html">
+ <source>Read bytes</source>
+ <target>讀取位元組數</target>
+ </trans-unit>
+ <trans-unit id="ecbe2fdca919499125bc42c2c67cedae8563db1c" datatype="html">
+ <source>Writes bytes</source>
+ <target>寫入位元組數</target>
+ </trans-unit>
+ <trans-unit id="f3c33322823c846b13f59ba2c8f234405bba99e1" datatype="html">
+ <source>Read ops</source>
+ <target>讀取操作數</target>
+ </trans-unit>
+ <trans-unit id="7e0b24a17546cbfab48b03dc874461d1ca68bc9a" datatype="html">
+ <source>Write ops</source>
+ <target>寫入操作數</target>
+ </trans-unit>
+ <trans-unit id="d45455406092f58e6b089cb440b5b7934b801a01" datatype="html">
+ <source>Mark OSD
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>將 OSD 標示為
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="de0b7806e451b3b3dbd564decba59981fe781c18" datatype="html">
+ <source>Mark
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </source>
+ <target>標示為
+ <x id="INTERPOLATION" equiv-text="{{markAction}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="bba1d3bb4f8a47aa2b3068e242562196eadb1e83" datatype="html">
+ <source>PG scrub options</source>
+ <target>PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="b0b7748ebc9b7a6942a8cac4a89d4b215b365878" datatype="html">
+ <source>Updated PG scrub options</source>
+ <target>Updated PG scrub options</target>
+ </trans-unit>
+ <trans-unit id="4edc2162af0bd6cd941eaf730d20a7e3b5a83ba7" datatype="html">
+ <source>Max Backfills</source>
+ <target>最大回填數</target>
+ </trans-unit>
+ <trans-unit id="eb5e6c24a48a1dfe23e0a772b762be5e949c0c8a" datatype="html">
+ <source>Recovery Max Active</source>
+ <target>處於使用中狀態的最大復原操作數</target>
+ </trans-unit>
+ <trans-unit id="4a23c6d3859e03184118620d2baeb736ac765fbf" datatype="html">
+ <source>Recovery Max Single Start</source>
+ <target>單次啟動的最大復原操作數</target>
+ </trans-unit>
+ <trans-unit id="97049169ef5228fd1724de2fcdad1fec2858eaf8" datatype="html">
+ <source>Recovery Sleep</source>
+ <target>復原操作間隔睡眠時間</target>
+ </trans-unit>
+ <trans-unit id="a5c05002b0ac2040f1aede5e727e0ffd06eda819" datatype="html">
+ <source>Custom</source>
+ <target>自訂</target>
+ </trans-unit>
+ <trans-unit id="89553524f4e7db5c437b07dcfdc7b831d56ded1a" datatype="html">
+ <source>Updated OSD recovery speed priority "
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>"
+ </source>
+ <target>已更新 OSD 復原速度優先程度「
+ <x id="INTERPOLATION" equiv-text="{{value}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="442db228d78b94d704b22bb0ffeb712af183f19a" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/> was initialized in the following OSD:
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </source>
+ <target>以下 OSD 已啟始化
+ <x id="INTERPOLATION" equiv-text="{{operation}}"/>操作︰
+ <x id="INTERPOLATION_1" equiv-text="{{id}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="1edb8e46b0fac57c5feb3d7d3585afc0122d5481" datatype="html">
+ <source>Create silence</source>
+ <target>Create silence</target>
+ </trans-unit>
+ <trans-unit id="78917e8031aaf913ac3fa63295325ce8879703ce" datatype="html">
+ <source>Job</source>
+ <target>工作</target>
+ </trans-unit>
+ <trans-unit id="94287619205068b591c18493c64781424864c259" datatype="html">
+ <source>Severity</source>
+ <target>嚴重性</target>
+ </trans-unit>
+ <trans-unit id="e6cfbe0c5e0302ba2cec22315f6a28f8ac46b651" datatype="html">
+ <source>Started</source>
+ <target>已啟動</target>
+ </trans-unit>
+ <trans-unit id="801b98c6f02fe3b32f6afa3ee854c99ed83474e6" datatype="html">
+ <source>URL</source>
+ <target>URL</target>
+ </trans-unit>
+ <trans-unit id="a5cd682a8a33bdc72e093d059429e3cc3a50ec1d" datatype="html">
+ <source>silence</source>
+ <target>silence</target>
+ </trans-unit>
+ <trans-unit id="f557e117e059e7036c6eecacd325a6ae35d866e0" datatype="html">
+ <source>Attribute name</source>
+ <target>Attribute name</target>
+ </trans-unit>
+ <trans-unit id="50f7f517ad8158667f7d4e2bd6f3256e05156e75" datatype="html">
+ <source>Regular expression</source>
+ <target>Regular expression</target>
+ </trans-unit>
+ <trans-unit id="81b1eab399c47110d50f45e3ccb4c009de7cb581" datatype="html">
+ <source>Please add your Prometheus host to the dashboard configuration and refresh the page</source>
+ <target>Please add your Prometheus host to the dashboard configuration and refresh the page</target>
+ </trans-unit>
+ <trans-unit id="29b4ae3296e239446fa0dea88a5112de15cffa54" datatype="html">
+ <source>Created by</source>
+ <target>Created by</target>
+ </trans-unit>
+ <trans-unit id="9da0107a35751e722c8b4bca7636fc7645dbdbdc" datatype="html">
+ <source>Updated</source>
+ <target>已更新</target>
+ </trans-unit>
+ <trans-unit id="8d833cceee0ba4c5161b130365e02bc1e129b57e" datatype="html">
+ <source>Ends</source>
+ <target>Ends</target>
+ </trans-unit>
+ <trans-unit id="46a11ff4289e8c88b1b7a935f8d8ee704055f11a" datatype="html">
+ <source>Silence</source>
+ <target>Silence</target>
+ </trans-unit>
+ <trans-unit id="fb2e1bed329dc5b84197808c778abb9edcbdb335" datatype="html">
+ <source>Used</source>
+ <target>已使用</target>
+ </trans-unit>
+ <trans-unit id="4f1ab04d9100fb0df0e62b921ec46ae052ae29fc" datatype="html">
+ <source>Avail.</source>
+ <target>可用</target>
+ </trans-unit>
+ <trans-unit id="a1c9b3d4fa67450fe9afd1d726f8a1bd91d990ea" datatype="html">
+ <source>Clean</source>
+ <target>乾淨</target>
+ </trans-unit>
+ <trans-unit id="0054f5460090d6dde385e8f099d598df5d28cf54" datatype="html">
+ <source>Working</source>
+ <target>工作中</target>
+ </trans-unit>
+ <trans-unit id="a8059e31694578c1b0344a76a345357dd60e8f01" datatype="html">
+ <source>Warning</source>
+ <target>警告</target>
+ </trans-unit>
+ <trans-unit id="e5d8bb389c702588877f039d72178f219453a72d" datatype="html">
+ <source>Unknown</source>
+ <target>未知</target>
+ </trans-unit>
+ <trans-unit id="88155be1b9b9c6140d6e8f93bac4a775cfdc6671" datatype="html">
+ <source>Healthy</source>
+ <target>Healthy</target>
+ </trans-unit>
+ <trans-unit id="8a3aec4dc1a6e2d4c612ae85e0537acbb20a0f85" datatype="html">
+ <source>Misplaced</source>
+ <target>Misplaced</target>
+ </trans-unit>
+ <trans-unit id="ee81f9bf7ceac69712e0b83e8adc268739f9673e" datatype="html">
+ <source>Degraded</source>
+ <target>Degraded</target>
+ </trans-unit>
+ <trans-unit id="14625bc4025daef1969777a67a3cca27e0cd9167" datatype="html">
+ <source>Unfound</source>
+ <target>Unfound</target>
+ </trans-unit>
+ <trans-unit id="8f23ea509d081c2f747d083d44608dbf125b2ea2" datatype="html">
+ <source>replicas</source>
+ <target>replicas</target>
+ </trans-unit>
+ <trans-unit id="129a2224e1f9d19eb5e11e2a07fe10a785556484" datatype="html">
+ <source>up</source>
+ <target>啟用中</target>
+ </trans-unit>
+ <trans-unit id="d5f29cf0af691726483262d647eb6622be002512" datatype="html">
+ <source>no filesystems</source>
+ <target>無檔案系統</target>
+ </trans-unit>
+ <trans-unit id="b1c4387ffab06f3fa9fdb4411aea955595538d44" datatype="html">
+ <source>active</source>
+ <target>使用中</target>
+ </trans-unit>
+ <trans-unit id="1aaf7054d826f2cb05ec3e88a5a4b8116861e1f5" datatype="html">
+ <source>standby</source>
+ <target>待命</target>
+ </trans-unit>
+ <trans-unit id="c9a1080024dca344a48acdb77fa2d54e059f7254" datatype="html">
+ <source>n/a</source>
+ <target>無</target>
+ </trans-unit>
+ <trans-unit id="84a1787b6df375847c70f782861d7e7f8f43bff4" datatype="html">
+ <source>active daemon</source>
+ <target>使用中的精靈</target>
+ </trans-unit>
+ <trans-unit id="24407dc2ebfafaf6b131ee978683b893c3f1d763" datatype="html">
+ <source>quorum</source>
+ <target>quorum</target>
+ </trans-unit>
+ <trans-unit id="2fa50bc07995c6ea660412294298ded39fcb08d9" datatype="html">
+ <source>The NFS Ganesha service is not configured.</source>
+ <target>未設定 NFS Ganesha 服務。</target>
+ </trans-unit>
+ <trans-unit id="af1396bdc49f45ea6c4a1e414769f5e2a382c834" datatype="html">
+ <source>Transport</source>
+ <target>傳輸</target>
+ </trans-unit>
+ <trans-unit id="b6a0e176d96c4feed2e975a039c044fcf822e152" datatype="html">
+ <source>CephFS User</source>
+ <target>CephFS 使用者</target>
+ </trans-unit>
+ <trans-unit id="44dc610cf201a163e8c38da810acec9596930bb3" datatype="html">
+ <source>CephFS Filesystem</source>
+ <target>CephFS 檔案系統</target>
+ </trans-unit>
+ <trans-unit id="db6dc7124be83c7055cb0f2719e31f2f9d46fd3d" datatype="html">
+ <source>(inherited from global config)</source>
+ <target>(繼承自全域組態)</target>
+ </trans-unit>
+ <trans-unit id="e1f97bb86f991553ec7b535cb39e7eaa99dfcfe2" datatype="html">
+ <source>inherited from global config</source>
+ <target>繼承自全域組態</target>
+ </trans-unit>
+ <trans-unit id="e751800766277e7c2edd652cec7a7a1a68a37852" datatype="html">
+ <source>-- Select what kind of user id squashing is performed --</source>
+ <target>-- 選取執行哪種類型的使用者 ID 匿名存取 --</target>
+ </trans-unit>
+ <trans-unit id="4b58387f911e8a7b135a0c4d76c70335c65bbb32" datatype="html">
+ <source>There are no daemons available.</source>
+ <target>沒有可用的精靈。</target>
+ </trans-unit>
+ <trans-unit id="18ae8dc1264f06df7ea251175ada2ac1b8401018" datatype="html">
+ <source>NFS export</source>
+ <target>NFS export</target>
+ </trans-unit>
+ <trans-unit id="ae128527ec18892f812a62a1fd15dc50a38060c0" datatype="html">
+ <source>EC Profile</source>
+ <target>EC Profile</target>
+ </trans-unit>
+ <trans-unit id="60fb10c145f9c7ede2b9ddf9b2b0b0f6191d0ebd" datatype="html">
+ <source>Cache Mode</source>
+ <target>快取模式</target>
+ </trans-unit>
+ <trans-unit id="fa5bfad31d4139f6871443bb74324ffda5cad3e6" datatype="html">
+ <source>Min Evict Age</source>
+ <target>逐出前至少可留存的時間</target>
+ </trans-unit>
+ <trans-unit id="fd0eb851666df45c34c76fabcda79b0d77bc910b" datatype="html">
+ <source>Min Flush Age</source>
+ <target>衝洗前至少可留存的時間</target>
+ </trans-unit>
+ <trans-unit id="cb54d2c420a534cee0c308ea5589f8c394ef8d67" datatype="html">
+ <source>Target Max Bytes</source>
+ <target>目標最大位元組數</target>
+ </trans-unit>
+ <trans-unit id="07f4ebe6615dca466818ffdae2a69ee217d265fb" datatype="html">
+ <source>Target Max Objects</source>
+ <target>目標最大物件數</target>
+ </trans-unit>
+ <trans-unit id="eaa8f4df53cf7fa78d078e20a701d10f3dccd77d" datatype="html">
+ <source>No applications added</source>
+ <target>未新增應用程式</target>
+ </trans-unit>
+ <trans-unit id="321c2a7640f11177ea49b0857b94c4b70830c0e6" datatype="html">
+ <source>Applications limit reached</source>
+ <target>已達到應用程式上限</target>
+ </trans-unit>
+ <trans-unit id="519d27742b74fadc8336777452f78891e98aa1dc" datatype="html">
+ <source>A pool can only have up to four applications definitions.</source>
+ <target>一個池最多只能四個應用程式定義。</target>
+ </trans-unit>
+ <trans-unit id="b5bec3813f0d45daa7eb9471272969e1bc3e734e" datatype="html">
+ <source>Allowed characters '_a-zA-Z0-9'</source>
+ <target>允許的字元為「_a-zA-Z0-9」</target>
+ </trans-unit>
+ <trans-unit id="807472d29602a0085bce62e534bd66208982c2e2" datatype="html">
+ <source>Maximum length is 128 characters</source>
+ <target>最大長度為 128 個字元</target>
+ </trans-unit>
+ <trans-unit id="37785748b9ac9ad1d3e4b111ac502c3284afe84b" datatype="html">
+ <source>Filter or add applications</source>
+ <target>過濾或新增應用程式</target>
+ </trans-unit>
+ <trans-unit id="38c7b8610ca87835e13eeee6a09ba1c414cd5cb9" datatype="html">
+ <source>Add application</source>
+ <target>新增應用程式</target>
+ </trans-unit>
+ <trans-unit id="db8c42f077700d8a94619fad9f4c94b7361d5f1d" datatype="html">
+ <source>pool</source>
+ <target>pool</target>
+ </trans-unit>
+ <trans-unit id="65bb2be83261bc4798853bbccdedc110c43feea7" datatype="html">
+ <source>erasure code profile</source>
+ <target>糾刪碼設定檔</target>
+ </trans-unit>
+ <trans-unit id="112d356ad6846959ca4aa5ec9a1f0d9d473b24ec" datatype="html">
+ <source>Replica Size</source>
+ <target>複本大小</target>
+ </trans-unit>
+ <trans-unit id="ec50492db341fa752b023d8c924601286b6c9c0c" datatype="html">
+ <source>Last Change</source>
+ <target>上次變更時間</target>
+ </trans-unit>
+ <trans-unit id="563a8c136a9d423bc7ae1269a404d6da5fd83dad" datatype="html">
+ <source>Erasure Coded Profile</source>
+ <target>糾刪碼設定檔</target>
+ </trans-unit>
+ <trans-unit id="0ad7f0662956cff61ac1208f92b1a0305b1b2e58" datatype="html">
+ <source>Crush Ruleset</source>
+ <target>CRUSH 規則集</target>
+ </trans-unit>
+ <trans-unit id="f15bf7f588f09ca79795b17bc244e8d336f28171" datatype="html">
+ <source>Write bytes</source>
+ <target>寫入位元組數</target>
+ </trans-unit>
+ <trans-unit id="bcc365a084b6145b941b371bd4c2b6c3d2c79234" datatype="html">
+ <source>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</source>
+ <target>Pool deletion is disabled by the mon_allow_pool_delete configuration setting.</target>
+ </trans-unit>
+ <trans-unit id="44939fd05cedfd077db886528b755e77d5fa3885" datatype="html">
+ <source>bucket</source>
+ <target>桶</target>
+ </trans-unit>
+ <trans-unit id="364cc3f92837b6000e686aab6d03bd2ad8007b50" datatype="html">
+ <source>Updated Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>已更新物件閘道桶「
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="2d7a43674f0bbc131c9e555ec16ac37fa0445d76" datatype="html">
+ <source>Created Object Gateway bucket "
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>"
+ </source>
+ <target>已建立物件閘道桶「
+ <x id="INTERPOLATION" equiv-text="{{bid}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="ec40d74ecfb1d6d60455af6805c9a714a3f5750a" datatype="html">
+ <source>buckets</source>
+ <target>桶</target>
+ </trans-unit>
+ <trans-unit id="764585d5595bac113582ee14a6fd07006770ceb1" datatype="html">
+ <source>capability</source>
+ <target>capability</target>
+ </trans-unit>
+ <trans-unit id="0914cbe18bae204217e1851be6d2d24d86e74605" datatype="html">
+ <source>user</source>
+ <target>使用者</target>
+ </trans-unit>
+ <trans-unit id="d8c86dc5e48a63590d9c94e19f90b5f8325cbd49" datatype="html">
+ <source>subuser</source>
+ <target>subuser</target>
+ </trans-unit>
+ <trans-unit id="f45a3de8a8b40d161cc36a55d77548a27107ca04" datatype="html">
+ <source>S3 Key</source>
+ <target>S3 Key</target>
+ </trans-unit>
+ <trans-unit id="854a763265e92f91ba3ccee1a0e8d823be584f7c" datatype="html">
+ <source>Updated Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>已更新物件閘道使用者「
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="84ab3fd641e65e39cffee0ec722a059ed284229e" datatype="html">
+ <source>Created Object Gateway user "
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>"
+ </source>
+ <target>已建立物件閘道使用者「
+ <x id="INTERPOLATION" equiv-text="{{uid}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="7c7f4be7b726e61c577e63842a58d9e435f7c597" datatype="html">
+ <source>users</source>
+ <target>使用者</target>
+ </trans-unit>
+ <trans-unit id="9f7760223efd77806f1bbaf963e6993bb4bc6a0a" datatype="html">
+ <source>Swift Key</source>
+ <target>Swift Key</target>
+ </trans-unit>
+ <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+ <source>Scope</source>
+ <target>範圍</target>
+ </trans-unit>
+ <trans-unit id="9b1d5e95f6bdcfb4b737413f5fa157e0dcb103d5" datatype="html">
+ <source>Read</source>
+ <target>讀取</target>
+ </trans-unit>
+ <trans-unit id="70a67e04629f6d412db0a12d51820b480788d795" datatype="html">
+ <source>Create</source>
+ <target>建立</target>
+ </trans-unit>
+ <trans-unit id="dc4fba275819619ee78e8eae14d357ea69ba7477" datatype="html">
+ <source>role</source>
+ <target>role</target>
+ </trans-unit>
+ <trans-unit id="fe6ee93173884201ec62d62ba173c3de85ae177e" datatype="html">
+ <source>Created role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>已建立角色「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="41c032df0732f4318f8213fabd0719ac347d4b6c" datatype="html">
+ <source>Updated role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>已更新角色「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="50e22b5289f79f1417369403345c9fa9911a4557" datatype="html">
+ <source>System Role</source>
+ <target>系統角色</target>
+ </trans-unit>
+ <trans-unit id="7f132668e2dbfcf616381d2daf59d1a6f2698102" datatype="html">
+ <source>Deleted role '
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>'
+ </source>
+ <target>已刪除角色「
+ <x id="INTERPOLATION" equiv-text="{{role_name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="d2362a49d2434ce137bf19dab004251b7fd9c7b3" datatype="html">
+ <source>Created user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已建立使用者「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="9910122dfedd2eaa544a990f1430e5b82a76d99f" datatype="html">
+ <source>Update user</source>
+ <target>更新使用者</target>
+ </trans-unit>
+ <trans-unit id="ac10a3d9b59575640797c1a8e6aea642cf5d5e77" datatype="html">
+ <source>Continue</source>
+ <target>繼續</target>
+ </trans-unit>
+ <trans-unit id="cf4bcf4ce3d551e6099ccdc3546ae418fe5f8038" datatype="html">
+ <source>You were automatically logged out because your roles have been changed.</source>
+ <target>您已被自動登出,因為您的角色發生了變更。</target>
+ </trans-unit>
+ <trans-unit id="0f6003fb0c1cc73b89d225801cc1b870945cd259" datatype="html">
+ <source>Updated user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已更新使用者「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="fe516c6d820018fdc971113935e22ec1e852965f" datatype="html">
+ <source>Deleted user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>已刪除使用者「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="01a7e11502ff80421ef3615e533ea14ef57e1d5c" datatype="html">
+ <source>Failed to delete user "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>"
+ </source>
+ <target>無法刪除使用者「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="63316a3861dbcb035147efc1b9fb6bc708242e94" datatype="html">
+ <source>You are currently logged in as "
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>".
+ </source>
+ <target>您目前正以「
+ <x id="INTERPOLATION" equiv-text="{{username}}"/>」身分登入。
+ </target>
+ </trans-unit>
+ <trans-unit id="1d7fbcc3d5efc946ffbcf86fed04c4e20dda20fb" datatype="html">
+ <source>Each object is split in data-chunks parts, each stored on a different OSD.</source>
+ <target>各物件都被分割成資料區塊部分,分別儲存於不同的 OSD。</target>
+ </trans-unit>
+ <trans-unit id="b1f8ed4e216585f1f9134740002ef3c8501debd8" datatype="html">
+ <source>Compute coding chunks for each object and store them on different OSDs.
+ The number of coding chunks is also the number of OSDs that can be down without losing data.</source>
+ <target>運算各物件的編碼區塊并將它們儲存到不同的 OSD。
+ 編碼區塊的數量等同於在不遺失資料的前提下,可停機的 OSD 數量。</target>
+ </trans-unit>
+ <trans-unit id="c437ee74a9a8e781e1380153f742a685e3b8cc5e" datatype="html">
+ <source>The jerasure plugin is the most generic and flexible plugin,
+ it is also the default for Ceph erasure coded pools.</source>
+ <target>Jerasure 外掛程式是最一般、最靈活的外掛程式,
+ 也是 Ceph 糾刪碼池的預設外掛程式。</target>
+ </trans-unit>
+ <trans-unit id="8c7e19322851402afa67e41f4f1d4e531caf1bf5" datatype="html">
+ <source>The more flexible technique is reed_sol_van : it is enough to set k
+ and m. The cauchy_good technique can be faster but you need to chose the packetsize
+ carefully. All of reed_sol_r6_op, liberation, blaum_roth, liber8tion are RAID6 equivalents
+ in the sense that they can only be configured with m=2.</source>
+ <target>Reed_sol_van 方法更靈活︰它足以設定 k
+ 和 m。Cauchy_good 方法更快,但您需要小心選取封包大小。
+ 所有 reed_sol_r6_op、liberation、blaum_roth、liber8tion 都
+ 等同於 RAID6,它們只能設定為 m=2。</target>
+ </trans-unit>
+ <trans-unit id="b1b11f49281b4e79219b4eecfbcb033cb15bd880" datatype="html">
+ <source>The encoding will be done on packets of bytes size at a time.
+ Chosing the right packet size is difficult.
+ The jerasure documentation contains extensive information on this topic.</source>
+ <target>將以位元組大小的封包為單位進行編碼。
+ 選取合適的封包大小很難。
+ Jerasure 文件包含有關此主題的詳細資訊。</target>
+ </trans-unit>
+ <trans-unit id="d9cb3bc07a25b26fbea457e0a7b543340bc13c49" datatype="html">
+ <source>With the jerasure plugin, when an erasure coded object is stored on
+ multiple OSDs, recovering from the loss of one OSD requires reading from all the others.
+ For instance if jerasure is configured with k=8 and m=4, losing one OSD requires reading
+ from the eleven others to repair.
+
+ The lrc erasure code plugin creates local parity chunks to be able to recover using
+ less OSDs. For instance if lrc is configured with k=8, m=4 and l=4, it will create
+ an additional parity chunk for every four OSDs. When a single OSD is lost, it can be
+ recovered with only four OSDs instead of eleven.</source>
+ <target>使用 jerasure 外掛程式時,若糾刪碼物件儲存於
+ 多個 OSD 上,則復原一個遺失的 OSD 時需要讀取所有其他 OSD。
+ 例如,若 jerasure 設定為 k=8 且 m=4,則遺失一個 OSD 後需讀取
+ 其他十一個 OSD 才能修復。
+
+ lrc 糾刪碼外掛程式會建立本地同位區塊,因此只需較少的 OSD 即
+ 可復原。例如,若 lrc 設定為 k=8、m=4 且 l=4,它將為每四個 OSD
+ 建立額外的同位區塊。這樣,當一個 OSD 遺失時,它只需四個 OSD
+ 即可復原,而不需要十一個。</target>
+ </trans-unit>
+ <trans-unit id="813959d46e63a29bbd266b3af2ff9414c2ef553c" datatype="html">
+ <source>Group the coding and data chunks into sets of size locality. For instance,
+ for k=4 and m=2, when locality=3 two groups of three are created. Each set can
+ be recovered without reading chunks from another set.</source>
+ <target>將編碼區塊和資料區塊分組為大小為 locality 的集合。例如,
+ k=4 且 m=2 時,若 locality=3,則會建立 2 個大小為 3 的組。這樣,各組都能
+ 自行復原,而無需從另一組讀取區塊。</target>
+ </trans-unit>
+ <trans-unit id="f0ff63d92e0a1b4d4b51e31b9133802d160a5f4c" datatype="html">
+ <source>The type of the crush bucket in which each set of chunks defined
+ by l will be stored. For instance, if it is set to rack, each group of l chunks will be
+ placed in a different rack. It is used to create a CRUSH rule step such as step choose
+ rack. If it is not set, no such grouping is done.</source>
+ <target>由 l 定義的區塊集將按哪種 CRUSH 桶類型儲存。
+ 例如,若設定為機架,則各組 l 區塊將會被放置到不同的
+ 機架中。該值用於建立類似 step choose rack 的 CRUSH
+ 規則步驟。若未設定,則不會進行此類分組。</target>
+ </trans-unit>
+ <trans-unit id="3ece48df9d1e9a98f98bf3c5cc66e8b637020a4d" datatype="html">
+ <source>The isa plugin encapsulates the ISA library. It only runs on Intel processors.</source>
+ <target>isa 外掛程式封包了 ISA 程式庫。它只能在 Intel 處理器上執行。</target>
+ </trans-unit>
+ <trans-unit id="4472c9e31bfc7d96a83dc4afce0a6e885c99e839" datatype="html">
+ <source>The ISA plugin comes in two Reed Solomon forms.
+ If reed_sol_van is set, it is Vandermonde, if cauchy is set, it is Cauchy.</source>
+ <target>ISA 外掛程式包含兩種 Reed Solomon 格式。
+ 若設定為 reed_sol_van,則為 Vandermonde。若設定為 cauchy,則為 Cauchy。</target>
+ </trans-unit>
+ <trans-unit id="fa385f5ecf63083ec848dca8dc5e52bdc72ac6f6" datatype="html">
+ <source>The shec plugin encapsulates the multiple SHEC library.
+ It allows ceph to recover data more efficiently than Reed Solomon codes.</source>
+ <target>shec 外掛程式封包了多個 SHEC 程式庫。
+ 與 Reed Solomon 代碼相比,它能更有效地復原資料。</target>
+ </trans-unit>
+ <trans-unit id="687b3cd94b3475c24ff4481d64d4739f902a377c" datatype="html">
+ <source>The number of parity chunks each of which includes each data chunk in its
+ calculation range. The number is used as a durability estimator. For instance, if c=2,
+ 2 OSDs can be down without losing data.</source>
+ <target>同位區塊的數量,它們在各自的計算範圍內包含了
+ 各資料區塊。該數值被用做持久性估值。例如,若 c=2,
+ 則在不遺失資料的前提下,可有 2 個 OSD 停機。</target>
+ </trans-unit>
+ <trans-unit id="f3c4af6df91bdaabdb715f8f0b61a24faf73a3bc" datatype="html">
+ <source>The name of the crush bucket used for the first step of the CRUSH rule.
+ For instance step take default.</source>
+ <target>CRUSH 規則的第一步所指向的 CRUSH 桶名稱。
+ 例如 step take default。</target>
+ </trans-unit>
+ <trans-unit id="e1059955a5ce65cdabf0c0a8207377e1f9bae57e" datatype="html">
+ <source>Ensure that no two chunks are in a bucket with the same failure
+ domain. For instance, if the failure domain is host no two chunks will be stored on the same
+ host. It is used to create a CRUSH rule step such as step chooseleaf host.</source>
+ <target>確定兩個區塊不會存在於同一故障網域的桶中。
+ 例如,若故障網域為主機,則不會有兩個區塊儲存於同一主機中。
+ 該值用於建立類似 step chooseleaf host 的 CRUSH 規則步驟。</target>
+ </trans-unit>
+ <trans-unit id="ac392ac9c6da5fde6da80fc57b9c09402fb6e73d" datatype="html">
+ <source>Restrict placement to devices of a specific class
+ (e.g., ssd or hdd), using the crush device class names in the CRUSH map.</source>
+ <target>使用 CRUSH 地圖中的 crush 裝置類別名稱,
+ 將放置限制於特定類別的裝置 (例如 ssd 或 hdd)。</target>
+ </trans-unit>
+ <trans-unit id="62bcb9ae5583a088649b1adf5787a86ca3334f89" datatype="html">
+ <source>Set the directory name from which the erasure code plugin is loaded.</source>
+ <target>設定糾刪碼外掛程式所在目錄。</target>
+ </trans-unit>
+ <trans-unit id="c8f10184a8433d132ede0a2c0c1aa96f291cacfa" datatype="html">
+ <source>Allows all operations</source>
+ <target>允許所有操作</target>
+ </trans-unit>
+ <trans-unit id="82077ee97c11ee76efc3adf253b7b26654544317" datatype="html">
+ <source>Allows only operations that do not modify the server</source>
+ <target>僅允許不修改伺服器的操作</target>
+ </trans-unit>
+ <trans-unit id="22b5212ec10449dbf0a0af0ad34122eac51b5f2a" datatype="html">
+ <source>Does not allow read or write operations, but allows any other operation</source>
+ <target>不允許讀取或寫入操作,但是允許任何其他操作</target>
+ </trans-unit>
+ <trans-unit id="9799d0f8c4b7727ae239fedfe3c0ce127feb7a50" datatype="html">
+ <source>Does not allow read, write, or any operation that modifies file attributes or directory content</source>
+ <target>不允許讀取、寫入或任何可能修改檔案屬性或目錄內容的操作</target>
+ </trans-unit>
+ <trans-unit id="aeddefe0af87025d8f00699aa94bed8216a99a58" datatype="html">
+ <source>Allows no access at all</source>
+ <target>完全禁止存取</target>
+ </trans-unit>
+ <trans-unit id="a436c6a4025a749198e93cac239de8deede72211" datatype="html">
+ <source>-- Select the priority --</source>
+ <target>-- 選取優先程度 --</target>
+ </trans-unit>
+ <trans-unit id="9556266f0a2b1762a44b686f2bb21dbfefb01c12" datatype="html">
+ <source>Low</source>
+ <target>低</target>
+ </trans-unit>
+ <trans-unit id="72279141a67cc042d9864102b703216cc8a428a3" datatype="html">
+ <source>High</source>
+ <target>高</target>
+ </trans-unit>
+ <trans-unit id="e6ca3c0efaf51e6d45a7f92f58bac37140c3fda4" datatype="html">
+ <source>Last 5 minutes</source>
+ <target>過去 5 分鐘</target>
+ </trans-unit>
+ <trans-unit id="b0ecb2bbc548cc9bd95050fd8f0c84586d083fe2" datatype="html">
+ <source>Last 15 minutes</source>
+ <target>過去 15 分鐘</target>
+ </trans-unit>
+ <trans-unit id="857ae67deb51353120b203b0f2a06b0c48ef49fa" datatype="html">
+ <source>Last 30 minutes</source>
+ <target>過去 30 分鐘</target>
+ </trans-unit>
+ <trans-unit id="7b1738fad314e936dc14b94db8f43da736942308" datatype="html">
+ <source>Last 1 hour (Default)</source>
+ <target>過去 1 小時 (預設值)</target>
+ </trans-unit>
+ <trans-unit id="a428288224389726cef9d9bd8d1d7808cccd7ffd" datatype="html">
+ <source>Last 3 hours</source>
+ <target>過去 3 小時</target>
+ </trans-unit>
+ <trans-unit id="7cbabecc8d80cf183ac199cfaeb7619d56e5d43f" datatype="html">
+ <source>Last 6 hours</source>
+ <target>過去 6 小時</target>
+ </trans-unit>
+ <trans-unit id="1a389cdf64187d34cf99eec30a290e3fa7d4744f" datatype="html">
+ <source>Last 12 hours</source>
+ <target>過去 12 小時</target>
+ </trans-unit>
+ <trans-unit id="9e0ba5f591380a94d594a76288f0c41aa97eb9c2" datatype="html">
+ <source>Last 24 hours</source>
+ <target>過去 24 小時</target>
+ </trans-unit>
+ <trans-unit id="e430eda9c785cd43465b7cbb400ee914f1057247" datatype="html">
+ <source>Yesterday</source>
+ <target>昨天</target>
+ </trans-unit>
+ <trans-unit id="7fb1099e29660162f9154d5b2feee7743a423df6" datatype="html">
+ <source>Today</source>
+ <target>今天</target>
+ </trans-unit>
+ <trans-unit id="33904058a97a64bd189bed84038b1ffe719769c7" datatype="html">
+ <source>Today so far</source>
+ <target>今天到目前為止</target>
+ </trans-unit>
+ <trans-unit id="3b0b849be007510021d3d383df75bec95ef9c97b" datatype="html">
+ <source>Day before yesterday</source>
+ <target>前天</target>
+ </trans-unit>
+ <trans-unit id="6b430c2c394c4d32ebd7d46c8c46ab60e1b29ccb" datatype="html">
+ <source>Last 2 days</source>
+ <target>過去 2 天</target>
+ </trans-unit>
+ <trans-unit id="d5e812a87a5d57a94200a2013027cab76a7c4863" datatype="html">
+ <source>This day last week</source>
+ <target>上週的今天</target>
+ </trans-unit>
+ <trans-unit id="d00edc936eeab6b5577401f115ca86ca2c87dc9a" datatype="html">
+ <source>Previous week</source>
+ <target>上週</target>
+ </trans-unit>
+ <trans-unit id="b036e40577baa6b918b2267d319d4b3aeaa88a5a" datatype="html">
+ <source>This week</source>
+ <target>本週</target>
+ </trans-unit>
+ <trans-unit id="99ad5a6096b3fcb3f021f3779bae710cdfeb8934" datatype="html">
+ <source>This week so far</source>
+ <target>本週目前為止</target>
+ </trans-unit>
+ <trans-unit id="02e0243b60007368f87dc01e083f232dd025096d" datatype="html">
+ <source>Last 7 days</source>
+ <target>過去 7 天</target>
+ </trans-unit>
+ <trans-unit id="c3b08b07b5ab98e7cdcf18df39355690ab7d3884" datatype="html">
+ <source>Previous month</source>
+ <target>上個月</target>
+ </trans-unit>
+ <trans-unit id="1b2562c6d5aa90644e7dc91feee82e2005fceb33" datatype="html">
+ <source>This month</source>
+ <target>本月</target>
+ </trans-unit>
+ <trans-unit id="26b4b18c5917934abb169ba9aa490e57f7bf10b8" datatype="html">
+ <source>This month so far</source>
+ <target>本月目前為止</target>
+ </trans-unit>
+ <trans-unit id="7668986b9f753fcd72ad4a00b1a0c4861d1f7fb8" datatype="html">
+ <source>Last 30 days</source>
+ <target>過去 30 天</target>
+ </trans-unit>
+ <trans-unit id="ba1e822408d90c6fbd2989100fa648bfd5e8ee84" datatype="html">
+ <source>Last 90 days</source>
+ <target>過去 90 天</target>
+ </trans-unit>
+ <trans-unit id="c3df03f899a914c4181adcdc8a3f077424f7b6e8" datatype="html">
+ <source>Last 6 months</source>
+ <target>過去 6 個月</target>
+ </trans-unit>
+ <trans-unit id="7f9a92757580c9f31c309c0a3812ea429274eadf" datatype="html">
+ <source>Last 1 year</source>
+ <target>過去 1 年</target>
+ </trans-unit>
+ <trans-unit id="5a9fede30ff65cb4b4426f6b1ed31afb67ecd7b0" datatype="html">
+ <source>Previous year</source>
+ <target>去年</target>
+ </trans-unit>
+ <trans-unit id="65cefcc53d1f6445df7568e8a40c49165f1090ee" datatype="html">
+ <source>This year</source>
+ <target>今年</target>
+ </trans-unit>
+ <trans-unit id="1f68b766944dc3865bddab765fe952b0c1c43f92" datatype="html">
+ <source>This year so far</source>
+ <target>今年目前為止</target>
+ </trans-unit>
+ <trans-unit id="4d4b77e614f8043fdadef5d6d235655bb48eb311" datatype="html">
+ <source>Last 2 years</source>
+ <target>過去 2 年</target>
+ </trans-unit>
+ <trans-unit id="138afa339ea6e75d25a474affe1edbcb90e00ec0" datatype="html">
+ <source>Last 5 years</source>
+ <target>過去 5 年</target>
+ </trans-unit>
+ <trans-unit id="c43dc1967a603fefb886149ac35863a06d5b4ce5" datatype="html">
+ <source>Information</source>
+ <target>資訊</target>
+ </trans-unit>
+ <trans-unit id="37391297bb077a6f84484930261b01a3ce38327b" datatype="html">
+ <source>No items selected.</source>
+ <target>未選取項目。</target>
+ </trans-unit>
+ <trans-unit id="2c1e52ee832661b4a0f570877d24661736b16af1" datatype="html">
+ <source>Deselect item to select again</source>
+ <target>取消選取項目以再次選取</target>
+ </trans-unit>
+ <trans-unit id="c8c9c6e5918659336824bbdda3501c66eaa79a4c" datatype="html">
+ <source>Selection limit reached</source>
+ <target>已達到選取上限</target>
+ </trans-unit>
+ <trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
+ <source>Filter tags</source>
+ <target>過濾標記</target>
+ </trans-unit>
+ <trans-unit id="aa00748e49c269956837d6f3acdd8d218796a8d8" datatype="html">
+ <source>Add badge</source>
+ <target>新增徽章</target>
+ </trans-unit>
+ <trans-unit id="4078a92d8121abdce7d8f346a88914923ec835fc" datatype="html">
+ <source>There are no items available.</source>
+ <target>沒有可用的項目。</target>
+ </trans-unit>
+ <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
+ <source>Add</source>
+ <target>新增</target>
+ </trans-unit>
+ <trans-unit id="019d4bd6a5690f0cfa0ecf346a4e6bf7f0d8debb" datatype="html">
+ <source>Remove</source>
+ <target>Remove</target>
+ </trans-unit>
+ <trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
+ <source>Clone</source>
+ <target>克隆</target>
+ </trans-unit>
+ <trans-unit id="1979da7460819153e11d2078244645d94291b69c" datatype="html">
+ <source>Copy</source>
+ <target>複製</target>
+ </trans-unit>
+ <trans-unit id="2e5e77dbaadd6588d8bbf737139fd9806294ae28" datatype="html">
+ <source>Deep Scrub</source>
+ <target>深層整理</target>
+ </trans-unit>
+ <trans-unit id="bf463b189696c19769ea263227e6c22aefafb918" datatype="html">
+ <source>Destroy</source>
+ <target>損毀</target>
+ </trans-unit>
+ <trans-unit id="3747fff7faf52b436ecff5fb8555091736d92c70" datatype="html">
+ <source>Flatten</source>
+ <target>壓平</target>
+ </trans-unit>
+ <trans-unit id="66fdbf32e5449cc54a3d1e19c7b8f4ea238facfb" datatype="html">
+ <source>Mark Down</source>
+ <target>標示為 Down</target>
+ </trans-unit>
+ <trans-unit id="0cda3e824fb2f9c731e5a60b859dedc1fe03127e" datatype="html">
+ <source>Mark In</source>
+ <target>標示為 In</target>
+ </trans-unit>
+ <trans-unit id="f833354f43cb38c5716faa8759a9bbdd1ab8f199" datatype="html">
+ <source>Mark Lost</source>
+ <target>標示為遺失</target>
+ </trans-unit>
+ <trans-unit id="75fb9f970ba365398c45e57bbb1019c009f6b832" datatype="html">
+ <source>Mark Out</source>
+ <target>標示為 Out</target>
+ </trans-unit>
+ <trans-unit id="45480c03b0a3a37ff8f6a5600a6a034b40fbaea4" datatype="html">
+ <source>Protect</source>
+ <target>保護</target>
+ </trans-unit>
+ <trans-unit id="e26f9cf3666aace4e524b1505c9795d76d87738d" datatype="html">
+ <source>Rename</source>
+ <target>重新命名</target>
+ </trans-unit>
+ <trans-unit id="d5cec7468241d72cafd86ad1af6d55b09a6e3ae5" datatype="html">
+ <source>Restore</source>
+ <target>還原</target>
+ </trans-unit>
+ <trans-unit id="ba073985cfd2528c77a746ed596b2f2052b973c5" datatype="html">
+ <source>Move to Trash</source>
+ <target>移至垃圾桶</target>
+ </trans-unit>
+ <trans-unit id="3ea9b96a21a499d296a7f25407da0f3df6c2d5ed" datatype="html">
+ <source>Unprotect</source>
+ <target>取消保護</target>
+ </trans-unit>
+ <trans-unit id="011f3e2bfc1fd8407eb5f599352665bfeb145664" datatype="html">
+ <source>Recreate</source>
+ <target>Recreate</target>
+ </trans-unit>
+ <trans-unit id="6df2dfa48bef5510c82fb43f4e71a7f9557f3d71" datatype="html">
+ <source>Expire</source>
+ <target>Expire</target>
+ </trans-unit>
+ <trans-unit id="28df1b02fd88d2deb0212bc5d7ff34cf9492fa54" datatype="html">
+ <source>Deleted</source>
+ <target>已刪除</target>
+ </trans-unit>
+ <trans-unit id="80e3b490720757978c99a7b5af3885faf202b955" datatype="html">
+ <source>Added</source>
+ <target>Added</target>
+ </trans-unit>
+ <trans-unit id="1aa4883bc4f1352f7a0bdd94810a9bf6dc22bd02" datatype="html">
+ <source>Removed</source>
+ <target>Removed</target>
+ </trans-unit>
+ <trans-unit id="402f3ee47f98fbbc68530239b1ddcbb9e96a460c" datatype="html">
+ <source>Edited</source>
+ <target>Edited</target>
+ </trans-unit>
+ <trans-unit id="96d56ec71c6e78cb4d6204c4a9359a3d38fcdb59" datatype="html">
+ <source>Canceled</source>
+ <target>Canceled</target>
+ </trans-unit>
+ <trans-unit id="a3318a2ee2bd0064b6b9ff72a4018b679ec63125" datatype="html">
+ <source>Cloned</source>
+ <target>已克隆</target>
+ </trans-unit>
+ <trans-unit id="ef90545bc832876c0d7f9a10363c75137472bbb5" datatype="html">
+ <source>Copied</source>
+ <target>已複製</target>
+ </trans-unit>
+ <trans-unit id="8dc560ded67482f109a98e0638851ad1d37188b3" datatype="html">
+ <source>Showed</source>
+ <target>Showed</target>
+ </trans-unit>
+ <trans-unit id="197259b7ea76f15c6d0a64b075a673fd4112ada7" datatype="html">
+ <source>Moved to Trash</source>
+ <target>Moved to Trash</target>
+ </trans-unit>
+ <trans-unit id="8fb15cb102cd75b562680290b7e04c44d80018f2" datatype="html">
+ <source>Unprotected</source>
+ <target>Unprotected</target>
+ </trans-unit>
+ <trans-unit id="8588eafa498262a1cbb5043ad68cf0ff669c4f10" datatype="html">
+ <source>Recreated</source>
+ <target>Recreated</target>
+ </trans-unit>
+ <trans-unit id="ffde7468d7b5cad6990095ed68ddee3d67cd02f8" datatype="html">
+ <source>Expired</source>
+ <target>Expired</target>
+ </trans-unit>
+ <trans-unit id="4f20f2d5a6882190892e58b85f6ccbedfa737952" datatype="html">
+ <source>Yes</source>
+ <target>是</target>
+ </trans-unit>
+ <trans-unit id="3d3ae7deebc5949b0c1c78b9847886a94321d9fd" datatype="html">
+ <source>No</source>
+ <target>否</target>
+ </trans-unit>
+ <trans-unit id="99fa0b67376d40142bd4d3ace3344abf4f98b6a5" datatype="html">
+ <source>Your matcher seems to match no currently defined rule or active alert.</source>
+ <target>Your matcher seems to match no currently defined rule or active alert.</target>
+ </trans-unit>
+ <trans-unit id="7e284852732c303eb1f47de9aca2569e41aeffed" datatype="html">
+ <source>no active alerts</source>
+ <target>no active alerts</target>
+ </trans-unit>
+ <trans-unit id="b8042829e4fbe7b09fd9bac9fa0ecf5cc1802fee" datatype="html">
+ <source>1 active alert</source>
+ <target>1 active alert</target>
+ </trans-unit>
+ <trans-unit id="e24adce97669cb0fc74cc13fdc14179b6f78ea5e" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> active alerts
+ </target>
+ </trans-unit>
+ <trans-unit id="d8fb058ff5883731d38a132da4ca45cfe8d719a3" datatype="html">
+ <source>Matches 1 rule</source>
+ <target>Matches 1 rule</target>
+ </trans-unit>
+ <trans-unit id="90aaef24d192e67c3fbc2ec6f8bfaff211cea128" datatype="html">
+ <source>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </source>
+ <target>Matches
+ <x id="INTERPOLATION" equiv-text="{{n}}"/> rules
+ </target>
+ </trans-unit>
+ <trans-unit id="f4685dc581e18244cd410f1057a8c56a9dbfe8df" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rules}}"/> with
+ <x id="INTERPOLATION_1" equiv-text="{{alerts}}"/>.
+ </target>
+ </trans-unit>
+ <trans-unit id="8fd98fb2a0f24ba72cde0787dd3f02cfc17de469" datatype="html">
+ <source>Quality of Service</source>
+ <target>服務品質</target>
+ </trans-unit>
+ <trans-unit id="2c53f3ce2c6fff9025a7b41cc334521725da6e7b" datatype="html">
+ <source>BPS Limit</source>
+ <target>BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="e897624a392419386b035bcd8529337e262fc41d" datatype="html">
+ <source>The desired limit of IO bytes per second.</source>
+ <target>指定的每秒 IO 位元組數上限。</target>
+ </trans-unit>
+ <trans-unit id="dc56f77e4507da7e86a3accd0a2a7099a838d539" datatype="html">
+ <source>IOPS Limit</source>
+ <target>IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="141c3f6eadbb35b0e17b2f847e4cac23240a6ea9" datatype="html">
+ <source>The desired limit of IO operations per second.</source>
+ <target>指定的每秒 IO 操作次數上限。</target>
+ </trans-unit>
+ <trans-unit id="3b3b101f16c38806e984b157e0cf22cd21451122" datatype="html">
+ <source>Read BPS Limit</source>
+ <target>讀取 BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="87835fabb6a645873f3829a450ca1d58f97754f2" datatype="html">
+ <source>The desired limit of read bytes per second.</source>
+ <target>指定的每秒內讀取的位元組數上限。</target>
+ </trans-unit>
+ <trans-unit id="28b485e700df46d70b96666099f714e3ae9e5c2e" datatype="html">
+ <source>Read IOPS Limit</source>
+ <target>讀取 IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="5907bd1a5cf3e20e740bca676cb1538372e1f9ff" datatype="html">
+ <source>The desired limit of read operations per second.</source>
+ <target>指定的每秒讀取操作次數上限。</target>
+ </trans-unit>
+ <trans-unit id="07317121f0b194987d4dee8b322f521ac17bf124" datatype="html">
+ <source>Write BPS Limit</source>
+ <target>寫入 BPS 上限</target>
+ </trans-unit>
+ <trans-unit id="4022c78bd9132ca2ec67927f8484c437d1d9b6fd" datatype="html">
+ <source>The desired limit of write bytes per second.</source>
+ <target>指定的每秒內寫入的位元組數上限。</target>
+ </trans-unit>
+ <trans-unit id="52c22c19f98ff3a09bd811292954a889b93d28b7" datatype="html">
+ <source>Write IOPS Limit</source>
+ <target>寫入 IOPS 上限</target>
+ </trans-unit>
+ <trans-unit id="0ed62e3fd8654b3191fc7fa959ad3f10f1ea773a" datatype="html">
+ <source>The desired limit of write operations per second.</source>
+ <target>指定的每秒寫入操作次數上限。</target>
+ </trans-unit>
+ <trans-unit id="d90c99d77864f21f932ee1369019f400c4ad0e2d" datatype="html">
+ <source>BPS Burst</source>
+ <target>BPS 高載</target>
+ </trans-unit>
+ <trans-unit id="29c32192f4d185139aaaf6d3a766a3411dfeabbe" datatype="html">
+ <source>The desired burst limit of IO bytes.</source>
+ <target>指定的 IO 位元組數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="b988b90489e899941e196c3dd0ecc22e37540224" datatype="html">
+ <source>IOPS Burst</source>
+ <target>IOPS 高載</target>
+ </trans-unit>
+ <trans-unit id="02c5de8ff11870f1b3896f2b45637ce0dba1ed4b" datatype="html">
+ <source>The desired burst limit of IO operations.</source>
+ <target>指定的 IO 操作次數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="7a160538129b37cf595f1651f28b5fac62fbc0f8" datatype="html">
+ <source>Read BPS Burst</source>
+ <target>讀取 BPS 高載</target>
+ </trans-unit>
+ <trans-unit id="b573a5df16a53b9947288461bc24e6a0eb4341d6" datatype="html">
+ <source>The desired burst limit of read bytes.</source>
+ <target>指定的讀取的位元組數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="1d5b8c2a0c653651cc4ca4b8fed9456f449220d1" datatype="html">
+ <source>Read IOPS Burst</source>
+ <target>讀取 IOPS 高載</target>
+ </trans-unit>
+ <trans-unit id="20b199f9d4a8d08ffefec66040e27639ec221512" datatype="html">
+ <source>The desired burst limit of read operations.</source>
+ <target>指定的讀取操作次數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="824525ae57992aee629ddffcd500a8b77087ddec" datatype="html">
+ <source>Write BPS Burst</source>
+ <target>寫入 BPS 高載</target>
+ </trans-unit>
+ <trans-unit id="a90aac4050a5d79765da5e1186909f6d4d7f981d" datatype="html">
+ <source>The desired burst limit of write bytes.</source>
+ <target>指定的寫入的位元組數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="35a8c6e6c249c7d16e26aa7c4ef97c06db405070" datatype="html">
+ <source>Write IOPS Burst</source>
+ <target>寫入 IOPS 高載</target>
+ </trans-unit>
+ <trans-unit id="b356abd41d7e9eea4d20c03d2e6892b6d435ecbd" datatype="html">
+ <source>The desired burst limit of write operations.</source>
+ <target>指定的寫入操作次數高載上限。</target>
+ </trans-unit>
+ <trans-unit id="24c4d50fe8567de381a20a1745f1b6d37eacaa90" datatype="html">
+ <source>Failed to
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </source>
+ <target>無法
+ <x id="INTERPOLATION" equiv-text="{{failure}}"/>
+ <x id="INTERPOLATION_1" equiv-text="{{metadata}}"/>
+ </target>
+ </trans-unit>
+ <trans-unit id="f54b6f09b390d5ade0e354f6c7d4743c10a315cc" datatype="html">
+ <source>Executing</source>
+ <target>正在執行</target>
+ </trans-unit>
+ <trans-unit id="5cdfe3e3330ea42bfd29c540dbd268bee97d364d" datatype="html">
+ <source>execute</source>
+ <target>執行</target>
+ </trans-unit>
+ <trans-unit id="6e98e243518daa88be30330fcdbd2d10f8eae4d7" datatype="html">
+ <source>Executed</source>
+ <target>已執行</target>
+ </trans-unit>
+ <trans-unit id="24b09aa5bd909273a023d2d788a2673325c77e31" datatype="html">
+ <source>unknown task</source>
+ <target>未知任務</target>
+ </trans-unit>
+ <trans-unit id="114b5f92b9192b229ffc9a450319a97ccca2aa5c" datatype="html">
+ <source>Creating</source>
+ <target>正在建立</target>
+ </trans-unit>
+ <trans-unit id="56695b69d27437ada580a187958407e7c856d46e" datatype="html">
+ <source>create</source>
+ <target>建立</target>
+ </trans-unit>
+ <trans-unit id="9db60170ef3b3b41a863e7d5ee7cec10919b9141" datatype="html">
+ <source>Updating</source>
+ <target>正在更新</target>
+ </trans-unit>
+ <trans-unit id="64412640835b7d25247cb254d4f911366c0e6862" datatype="html">
+ <source>update</source>
+ <target>更新</target>
+ </trans-unit>
+ <trans-unit id="416193bb373d59477458b00e5922d755e2e2cacd" datatype="html">
+ <source>Deleting</source>
+ <target>正在刪除</target>
+ </trans-unit>
+ <trans-unit id="70ef158c584bafe788e319a0bffa11b02ee9abf1" datatype="html">
+ <source>delete</source>
+ <target>刪除</target>
+ </trans-unit>
+ <trans-unit id="3f757cfc3749ebb5d4462017cb60138ca082f15f" datatype="html">
+ <source>RBD '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="a6c681e6130fe440ae40de99a405fcf5c7eefee1" datatype="html">
+ <source>RBD snapshot '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>RBD 快照「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="4fb54a0291f49583c317d4a3690239141b5a8f68" datatype="html">
+ <source>mirror mode for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>池「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」的鏡像模式
+ </target>
+ </trans-unit>
+ <trans-unit id="6621ab6e122a149326a1e48e9051a41e7f203cf6" datatype="html">
+ <source>mirror peer for pool '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>池「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」的鏡像對等
+ </target>
+ </trans-unit>
+ <trans-unit id="db15adc778317d551232fe712eb03a2c1eac4a43" datatype="html">
+ <source>all dashboards</source>
+ <target>all dashboards</target>
+ </trans-unit>
+ <trans-unit id="1b559dbd9cc9664fd788c2da9a10d3abafe066cb" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>.
+ </source>
+ <target>名稱已被
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/> 使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="8fc28e1103d9f2ef47b9fff9a4f74e8365c7cf19" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>.
+ </source>
+ <target>名稱已被
+ <x id="INTERPOLATION" equiv-text="{{name}}"/> 使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="1cdc7ea44fcb85d0cfcf6e7379d625d8674a8fbe" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/>.
+ </source>
+ <target>名稱已被
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> 使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="1ff7676ad1e991102224540a32dd44ad1ab88aa8" datatype="html">
+ <source>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> contains snapshots.
+ </source>
+ <target>
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> 包含快照。
+ </target>
+ </trans-unit>
+ <trans-unit id="c3a1dcca2b2ba20fbe39e2441e7bb1cf9c20cdf3" datatype="html">
+ <source>Cloning</source>
+ <target>正在克隆</target>
+ </trans-unit>
+ <trans-unit id="b5fa4e0a3a279dee5b6bf7b823e54387f7c79994" datatype="html">
+ <source>clone</source>
+ <target>克隆</target>
+ </trans-unit>
+ <trans-unit id="29b7452e8367af9aa8fa828f16ff94c3530e7a1a" datatype="html">
+ <source>Snapshot of
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> must be protected.
+ </source>
+ <target>必須保護
+ <x id="INTERPOLATION" equiv-text="{{rbd_name}}"/> 的快照。
+ </target>
+ </trans-unit>
+ <trans-unit id="369f93b9a07a9465f7a261e9f0021b6cfa7180c5" datatype="html">
+ <source>Copying</source>
+ <target>正在複製</target>
+ </trans-unit>
+ <trans-unit id="37584f889855d153a106f5dffe23d21f9453c8ff" datatype="html">
+ <source>copy</source>
+ <target>複製</target>
+ </trans-unit>
+ <trans-unit id="6ea9e313a04ef59222feaadfe84e97b4c69d7e9e" datatype="html">
+ <source>Flattening</source>
+ <target>正在壓平</target>
+ </trans-unit>
+ <trans-unit id="1f57593581b64d2d4c70eab1736bd9bccc66a7dc" datatype="html">
+ <source>flatten</source>
+ <target>壓平</target>
+ </trans-unit>
+ <trans-unit id="647059bf3ea098fffedf92ddfad792bb3daa3c95" datatype="html">
+ <source>Flattened</source>
+ <target>已壓平</target>
+ </trans-unit>
+ <trans-unit id="d990ef9680cd23bbe652c37eb46bf038cfee80ad" datatype="html">
+ <source>Name is already used by
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>.
+ </source>
+ <target>名稱已被
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> 使用。
+ </target>
+ </trans-unit>
+ <trans-unit id="a101745d080ef65c09bd5fafc796f94ddb9f9d60" datatype="html">
+ <source>Cannot unprotect
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it contains child images.
+ </source>
+ <target>無法保護
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>,因為其包含子影像。
+ </target>
+ </trans-unit>
+ <trans-unit id="647968f4cde7786cd53ec8e6aa9802ac6824a262" datatype="html">
+ <source>Cannot delete
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/> because it's protected.
+ </source>
+ <target>無法刪除
+ <x id="INTERPOLATION" equiv-text="{{snap_name}}"/>,因為其處於保護狀態。
+ </target>
+ </trans-unit>
+ <trans-unit id="57ddd3e15cf0ce974356b757451f50116a27272b" datatype="html">
+ <source>Rolling back</source>
+ <target>正在復原</target>
+ </trans-unit>
+ <trans-unit id="a8913a3a5ee61f2598b5f0432cb9b20cdd60548e" datatype="html">
+ <source>rollback</source>
+ <target>復原</target>
+ </trans-unit>
+ <trans-unit id="dc21fd6547f2325c67f6deff925f29eb07a2db3e" datatype="html">
+ <source>Rolled back</source>
+ <target>已復原</target>
+ </trans-unit>
+ <trans-unit id="de8676f0017c9db6c49388cd7d63cd0a83a0c1dc" datatype="html">
+ <source>Moving</source>
+ <target>正在移動</target>
+ </trans-unit>
+ <trans-unit id="2d810712308ae63cb795d809687a3254ef7a2f05" datatype="html">
+ <source>move</source>
+ <target>移動</target>
+ </trans-unit>
+ <trans-unit id="f3ba995236e5c1cc77686108980c099a90aec754" datatype="html">
+ <source>Moved</source>
+ <target>已移動</target>
+ </trans-unit>
+ <trans-unit id="d0422169252d132624a20f267b5c29f28cb53ebe" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' to trash
+ </source>
+ <target>影像「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」到垃圾桶
+ </target>
+ </trans-unit>
+ <trans-unit id="b603e2dfed9808222fbcb5a7c5f4da2cc6ae2aae" datatype="html">
+ <source>Could not find image.</source>
+ <target>找不到影像。</target>
+ </trans-unit>
+ <trans-unit id="398debe73006b1fe5177ed81d2e7b0cc852f61ec" datatype="html">
+ <source>Restoring</source>
+ <target>正在還原</target>
+ </trans-unit>
+ <trans-unit id="c252806fb400e79bac194696632c9362742b1538" datatype="html">
+ <source>restore</source>
+ <target>還原</target>
+ </trans-unit>
+ <trans-unit id="86fc6cae82c095f14105eb8a61d7b3fa948304b7" datatype="html">
+ <source>Restored</source>
+ <target>已還原</target>
+ </trans-unit>
+ <trans-unit id="30b8bcf69b3f1754b7abba173fd806cfcea4cb04" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' into '
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>'
+ </source>
+ <target>影像「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」(到「
+ <x id="INTERPOLATION_1" equiv-text="{{new_id}}"/>」)
+ </target>
+ </trans-unit>
+ <trans-unit id="13b7b241cef989fe0932ddd180e757658e1817e7" datatype="html">
+ <source>Image name '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>' is already in use.
+ </source>
+ <target>影像名稱「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」已在使用中。
+ </target>
+ </trans-unit>
+ <trans-unit id="cc1cee12c833e8fbbef28a2a7c449dc530da912d" datatype="html">
+ <source>image '
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>'
+ </source>
+ <target>影像「
+ <x id="INTERPOLATION" equiv-text="{{id}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="38e5f47f8bef505652f3e87f46efb00ead1350a3" datatype="html">
+ <source>Purging</source>
+ <target>正在清除</target>
+ </trans-unit>
+ <trans-unit id="e4e57747f123f0fe6fe3a0ecf608f8bc287dec0c" datatype="html">
+ <source>purge</source>
+ <target>清除</target>
+ </trans-unit>
+ <trans-unit id="69b0446c6c2411c4fe01e411b8ceec72d4044fb4" datatype="html">
+ <source>Purged</source>
+ <target>已清除</target>
+ </trans-unit>
+ <trans-unit id="1560d58fdf39663929653250d45f5b1dfe078fea" datatype="html">
+ <source>all pools</source>
+ <target>所有池</target>
+ </trans-unit>
+ <trans-unit id="1ac3dc50c2c3d86e98bc0967ee1e696810a2d3aa" datatype="html">
+ <source>images from
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>
+ </source>
+ <target>影像 (從
+ <x id="INTERPOLATION" equiv-text="{{message}}"/>)
+ </target>
+ </trans-unit>
+ <trans-unit id="02278abbb044ece04ab6bd80bd2060198d31d83b" datatype="html">
+ <source>Cannot disable mirroring because it contains a peer.</source>
+ <target>無法停用鏡像,因為其包含對等。</target>
+ </trans-unit>
+ <trans-unit id="dfe70001dc590a9e12512cbb206aa29fb36fd00b" datatype="html">
+ <source>pool '
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>'
+ </source>
+ <target>池「
+ <x id="INTERPOLATION" equiv-text="{{pool_name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="59630daf2f4786690fae0cdad55da8887236eabe" datatype="html">
+ <source>erasure code profile '
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>'
+ </source>
+ <target>糾刪碼設定檔「
+ <x id="INTERPOLATION" equiv-text="{{name}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="369462e5e018360e0600bb570866201ad5c3c8a8" datatype="html">
+ <source>target '
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>'
+ </source>
+ <target>目標「
+ <x id="INTERPOLATION" equiv-text="{{target_iqn}}"/>」
+ </target>
+ </trans-unit>
+ <trans-unit id="cf41310917cb19b335e5a950972bbff2346f7a47" datatype="html">
+ <source>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </source>
+ <target>NFS
+ <x id="INTERPOLATION" equiv-text="{{nfs_id}}"/>
+ </target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff> \ No newline at end of file
diff --git a/src/pybind/mgr/dashboard/frontend/src/main.ts b/src/pybind/mgr/dashboard/frontend/src/main.ts
new file mode 100644
index 00000000..741c9eb8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/main.ts
@@ -0,0 +1,13 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic()
+ .bootstrapModule(AppModule)
+ .catch((err) => console.log(err));
diff --git a/src/pybind/mgr/dashboard/frontend/src/polyfills.ts b/src/pybind/mgr/dashboard/frontend/src/polyfills.ts
new file mode 100644
index 00000000..6eb2cc38
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/polyfills.ts
@@ -0,0 +1,67 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+import 'core-js/es6/array';
+import 'core-js/es6/date';
+import 'core-js/es6/function';
+import 'core-js/es6/map';
+import 'core-js/es6/math';
+import 'core-js/es6/number';
+import 'core-js/es6/object';
+import 'core-js/es6/parse-float';
+import 'core-js/es6/parse-int';
+import 'core-js/es6/regexp';
+import 'core-js/es6/set';
+import 'core-js/es6/string';
+import 'core-js/es6/symbol';
+import 'core-js/es6/weak-map';
+import 'core-js/es7/object';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+// import 'core-js/es6/reflect';
+
+/**
+ * Required to support Web Animations `@angular/platform-browser/animations`.
+ * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
+ **/
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/***************************************************************************************************
+ * Zone JS is required by Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
+
+/**
+ * Date, currency, decimal and percent pipes.
+ * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
+ */
+// import 'intl'; // Run `npm install --save intl`.
+/**
+ * Need to import at least one locale-data with intl.
+ */
+// import 'intl/locale-data/jsonp/en';
diff --git a/src/pybind/mgr/dashboard/frontend/src/setupJest.ts b/src/pybind/mgr/dashboard/frontend/src/setupJest.ts
new file mode 100644
index 00000000..f695767e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/setupJest.ts
@@ -0,0 +1,4 @@
+import 'jest-preset-angular';
+import 'jest-zone-patch';
+
+import './jestGlobalMocks';
diff --git a/src/pybind/mgr/dashboard/frontend/src/styles.scss b/src/pybind/mgr/dashboard/frontend/src/styles.scss
new file mode 100644
index 00000000..ad06737c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/styles.scss
@@ -0,0 +1,392 @@
+/* You can add global styles to this file, and also import other style files */
+
+@import 'defaults';
+$fa-font-path: '../node_modules/fork-awesome/fonts';
+@import '../node_modules/fork-awesome/scss/fork-awesome';
+$font_family_1: 'ForkAwesome';
+@import 'app/ceph/dashboard/info-card/info-card-popover.scss';
+
+/* Basics */
+html {
+ background-color: $color-app-bg;
+}
+html,
+body {
+ width: 100%;
+ height: 100%;
+ font-size: 12px;
+}
+a {
+ color: $color-links;
+ cursor: pointer;
+}
+a:hover,
+a:focus {
+ color: $color-links-focus;
+}
+h1 {
+ letter-spacing: -1px;
+ font-size: 2em;
+}
+h2 {
+ letter-spacing: -1px;
+ font-size: 1.833em;
+}
+h3 {
+ display: block;
+ font-size: 1.583em;
+ font-weight: 400;
+}
+h4 {
+ font-size: 1.5em;
+ line-height: normal;
+}
+option {
+ font-weight: normal;
+ font-style: normal;
+}
+/* For awesome-bootstrap-checkbox */
+.checkbox input[type='checkbox']:checked + label:after {
+ font-family: $font_family_1;
+}
+/*******/
+.full-height {
+ height: 100%;
+}
+.vertical-align {
+ display: flex;
+ align-items: center;
+}
+.loading {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+}
+.margin-right-md {
+ margin-right: 15px;
+}
+.no-border {
+ border: 0px;
+ box-shadow: 0px 0px 0px !important;
+}
+.italic {
+ font-style: italic;
+}
+.bold {
+ font-weight: bold;
+}
+.text-right {
+ text-align: right;
+}
+.text-monospace {
+ font-family: monospace;
+}
+
+/* Buttons */
+.btn {
+ &,
+ &:active,
+ &.active {
+ &:focus,
+ &.focus {
+ outline: 0;
+ }
+ }
+}
+.btn-primary {
+ color: $color-button-text;
+ background-color: $color-accent;
+ border-color: $color-accent;
+ border-radius: $button-radius;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.open .dropdown-toggle.btn-primary {
+ color: $color-button-text;
+ background-color: lighten($color-accent, 10);
+ border-color: lighten($color-accent, 10);
+}
+.btn-primary:active,
+.btn-primary.active,
+.open .dropdown-toggle.btn-primary {
+ background-image: none;
+
+ &:hover,
+ &:focus {
+ background-color: lighten($color-accent, 10);
+ border-color: lighten($color-accent, 10);
+ }
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: $color-accent;
+ border-color: $color-accent;
+}
+.btn-primary .badge {
+ color: $color-primary;
+ background-color: $color-button-badge;
+}
+.btn-primary .caret {
+ color: $color-button-caret;
+}
+.btn-default {
+ border-radius: $button-radius;
+}
+.form-group .btn-default {
+ border-radius: 4px;
+}
+.btn-group > .btn > i.fa,
+button.btn.btn-label > i.fa {
+ /** Add space between icon and text */
+ padding-right: 5px;
+}
+
+/* Dropdown */
+.dropdown-menu {
+ min-width: 50px;
+ z-index: 999999;
+}
+.dropdown-menu > li > a {
+ color: $color-dropdown-menu;
+ cursor: pointer;
+}
+.dropdown-menu > li > a > i.fa {
+ /** Add space between icon and text */
+ padding-right: 5px;
+}
+.dropdown-menu > .active > a {
+ color: $color-dropdown-active-text;
+ background-color: $color-dropdown-active-bg;
+
+ &,
+ &:hover,
+ &:focus {
+ background-color: darken($color-dropdown-active-bg, 10);
+ }
+}
+.dataTables_wrapper .dropdown-menu > li.divider {
+ cursor: auto;
+}
+
+/* Grid */
+.container,
+.container-fluid {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+.row {
+ margin-left: -30px;
+ margin-right: -30px;
+}
+.col-lg-1,
+.col-lg-10,
+.col-lg-11,
+.col-lg-12,
+.col-lg-2,
+.col-lg-3,
+.col-lg-4,
+.col-lg-5,
+.col-lg-6,
+.col-lg-7,
+.col-lg-8,
+.col-lg-9,
+.col-md-1,
+.col-md-10,
+.col-md-11,
+.col-md-12,
+.col-md-2,
+.col-md-3,
+.col-md-4,
+.col-md-5,
+.col-md-6,
+.col-md-7,
+.col-md-8,
+.col-md-9,
+.col-sm-1,
+.col-sm-10,
+.col-sm-11,
+.col-sm-12,
+.col-sm-2,
+.col-sm-3,
+.col-sm-4,
+.col-sm-5,
+.col-sm-6,
+.col-sm-7,
+.col-sm-8,
+.col-sm-9,
+.col-xs-1,
+.col-xs-10,
+.col-xs-11,
+.col-xs-12,
+.col-xs-2,
+.col-xs-3,
+.col-xs-4,
+.col-xs-5,
+.col-xs-6,
+.col-xs-7,
+.col-xs-8,
+.col-xs-9 {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+/* Caret */
+.caret {
+ color: $color-caret-text;
+}
+/* Progressbar */
+.progress-bar {
+ background-image: none !important;
+}
+.progress-bar-info {
+ background-color: $color-progress-bar-info-bg;
+}
+.progress-bar-freespace {
+ background-color: $color-progress-bar-freespace-bg;
+}
+.oaprogress {
+ position: relative;
+ margin-bottom: 0;
+}
+.oaprogress div.progress-bar {
+ position: static;
+}
+.oaprogress span {
+ position: absolute;
+ display: block;
+ width: 100%;
+ color: $color-oaprogress-text;
+ font-weight: normal;
+}
+tags-input .tags {
+ border-radius: 4px;
+ border: 1px solid $color-tags-border;
+ box-shadow: inset 0 1px 1px $color-tags-box-shadow;
+}
+uib-accordion .panel-title,
+.panel .accordion-title {
+ font-size: 14px !important;
+}
+.panel-body h2:first-child {
+ margin-top: 0;
+}
+.pull-left {
+ float: left;
+}
+.disabled {
+ pointer-events: none;
+}
+.clickable {
+ cursor: pointer;
+}
+.has-error .has-error-btn,
+.has-error .has-error-btn:disabled:hover {
+ background-color: $color-error-btn-bg;
+ border-color: $color-error-btn-border;
+}
+/* If javascript is disabled. */
+.noscript {
+ padding-top: 5em;
+}
+.noscript p {
+ color: $color-noscript-text;
+}
+.required {
+ color: $color-required-text;
+}
+/* Forms */
+.form-group > .control-label > span.required,
+.form-group > .col-sm-12 > .control-label > span.required {
+ @extend .fa;
+ @extend .fa-asterisk;
+ @extend .required;
+ font-size: 6px;
+ padding-left: 4px;
+ vertical-align: text-top;
+}
+.form-control {
+ display: table-cell;
+
+ &:focus {
+ border-color: rgba($color-primary, 0.8);
+ outline: 0;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px 2px rgba($color-primary, 0.5);
+ }
+}
+/* Panel */
+.panel-footer button.btn:not(:first-child) {
+ margin-left: 5px;
+}
+/* Modal dialog */
+.modal-footer button.btn:not(:first-child) {
+ margin-left: 5px;
+}
+.margin-right-sm {
+ margin-right: 10px;
+}
+.nav-tabs {
+ margin-bottom: 15px;
+}
+/* Icons */
+.ceph-icon {
+ background: url('assets/Ceph_Logo_Stacked_RGB_120411_fa_228x228.png');
+}
+.prometheus-icon {
+ background: url('assets/prometheus_logo.svg');
+}
+.custom-icon {
+ padding: 10px;
+ margin-right: 1em;
+ background-clip: padding-box;
+ background-size: contain;
+ background-repeat: no-repeat;
+}
+/* Notification icons */
+.toast-message .custom-icon {
+ /* Display icons in white, regardless of their origin color. */
+ filter: brightness(0) invert(1);
+ -webkit-filter: brightness(0) invert(1);
+ -moz-filter: brightness(0) invert(1);
+ -o-filter: brightness(0) invert(1);
+ -ms-filter: brightness(0) invert(1);
+}
+/* Block UI */
+.block-ui-wrapper {
+ background: $color-transparent-black !important;
+}
+
+h3.page-header {
+ margin-left: 1em;
+ margin-top: 1em;
+ border-color: #f0f0f0;
+}
+
+.tooltip-wide .tooltip-inner {
+ width: 400px;
+}
+
+.tooltip-inner {
+ background-color: white;
+ border: 1px solid grey;
+ color: #333;
+ font-size: 1.1em;
+}
+
+.toast-message > ul {
+ padding-left: 1em;
+ margin: 0;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/styles/chart-tooltip.scss b/src/pybind/mgr/dashboard/frontend/src/styles/chart-tooltip.scss
new file mode 100644
index 00000000..b37e5fcc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/styles/chart-tooltip.scss
@@ -0,0 +1,64 @@
+@import '../defaults';
+
+.chart-container {
+ position: absolute;
+ margin: auto;
+ cursor: pointer;
+ overflow: visible;
+}
+
+canvas {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.chartjs-tooltip {
+ opacity: 0;
+ position: absolute;
+ background: $color-chart-tooltip-bg;
+ color: $color-chat-tooltip-text;
+ border-radius: 3px;
+ -webkit-transition: all 0.1s ease;
+ transition: all 0.1s ease;
+ pointer-events: none;
+ font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif !important;
+
+ -webkit-transform: translate(-50%, 0);
+ transform: translate(-50%, 0);
+
+ &.transform-left {
+ transform: translate(-10%, 0);
+
+ &::after {
+ left: 10%;
+ }
+ }
+
+ &.transform-right {
+ transform: translate(-90%, 0);
+
+ &::after {
+ left: 90%;
+ }
+ }
+}
+
+.chartjs-tooltip::after {
+ content: ' ';
+ position: absolute;
+ top: 100%; /* At the bottom of the tooltip */
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: $color-chart-tooltip-border transparent transparent transparent;
+}
+
+::ng-deep .chartjs-tooltip-key {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin-right: 10px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/styles/popover.scss b/src/pybind/mgr/dashboard/frontend/src/styles/popover.scss
new file mode 100644
index 00000000..ab747bf6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/styles/popover.scss
@@ -0,0 +1,46 @@
+@import '../defaults';
+
+::ng-deep .popover-content {
+ padding: 0.5em;
+ height: auto;
+ max-height: 70vh;
+ overflow-x: hidden;
+}
+
+::ng-deep .popover {
+ min-width: 276px !important;
+}
+
+.separator {
+ padding: 5px 12px;
+ color: $color-popover-seperator-text;
+ background-color: $color-popover-seperator-bg;
+ font-size: 12px;
+}
+
+.message {
+ padding: 10px 16px;
+ color: $color-popover-message-text;
+ font-size: 12px;
+}
+
+table {
+ width: 252px;
+ margin: 5px 12px 5px 5px;
+ font-size: 12px;
+ color: $color-popover-table-text;
+}
+
+.icon-col {
+ width: 50px;
+ font-size: 10px;
+}
+
+.date {
+ color: $color-popover-date;
+}
+
+hr {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/testing/activated-route-stub.ts b/src/pybind/mgr/dashboard/frontend/src/testing/activated-route-stub.ts
new file mode 100644
index 00000000..fafbf60b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/testing/activated-route-stub.ts
@@ -0,0 +1,23 @@
+import { ReplaySubject } from 'rxjs';
+
+/**
+ * An ActivateRoute test double with a `params` observable.
+ * Use the `setParams()` method to add the next `params` value.
+ */
+export class ActivatedRouteStub {
+ // Use a ReplaySubject to share previous values with subscribers
+ // and pump new values into the `params` observable
+ private subject = new ReplaySubject<object>();
+
+ constructor(initialParams?: object) {
+ this.setParams(initialParams);
+ }
+
+ /** The mock params observable */
+ readonly params = this.subject.asObservable();
+
+ /** Set the params observables's next value */
+ setParams(params?: object) {
+ this.subject.next(params);
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts b/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts
new file mode 100644
index 00000000..a22c76ec
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts
@@ -0,0 +1,344 @@
+import { LOCALE_ID, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { AbstractControl } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+
+import { TableActionsComponent } from '../app/shared/datatable/table-actions/table-actions.component';
+import { CdFormGroup } from '../app/shared/forms/cd-form-group';
+import { Permission } from '../app/shared/models/permissions';
+import {
+ AlertmanagerAlert,
+ AlertmanagerNotification,
+ AlertmanagerNotificationAlert,
+ PrometheusRule
+} from '../app/shared/models/prometheus-alerts';
+import { _DEV_ } from '../unit-test-configuration';
+
+export function configureTestBed(configuration, useOldMethod?) {
+ if (_DEV_ && !useOldMethod) {
+ const resetTestingModule = TestBed.resetTestingModule;
+ beforeAll((done) =>
+ (async () => {
+ TestBed.resetTestingModule();
+ TestBed.configureTestingModule(configuration);
+ // prevent Angular from resetting testing module
+ TestBed.resetTestingModule = () => TestBed;
+ })()
+ .then(done)
+ .catch(done.fail)
+ );
+ afterAll(() => {
+ TestBed.resetTestingModule = resetTestingModule;
+ });
+ } else {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule(configuration);
+ }));
+ }
+}
+
+export class PermissionHelper {
+ tableActions: TableActionsComponent;
+ permission: Permission;
+ getTableActionComponent: () => TableActionsComponent;
+
+ constructor(permission: Permission, getTableActionComponent: () => TableActionsComponent) {
+ this.permission = permission;
+ this.getTableActionComponent = getTableActionComponent;
+ }
+
+ setPermissionsAndGetActions(
+ createPerm: number | boolean,
+ updatePerm: number | boolean,
+ deletePerm: number | boolean
+ ): TableActionsComponent {
+ this.permission.create = Boolean(createPerm);
+ this.permission.update = Boolean(updatePerm);
+ this.permission.delete = Boolean(deletePerm);
+ this.tableActions = this.getTableActionComponent();
+ return this.tableActions;
+ }
+
+ // Overwrite if needed
+ createSelection(): object {
+ return {};
+ }
+
+ testScenarios({
+ fn,
+ empty,
+ single,
+ singleExecuting,
+ multiple
+ }: {
+ fn: () => any;
+ empty: any;
+ single: any;
+ singleExecuting?: any; // uses 'single' if not defined
+ multiple?: any; // uses 'empty' if not defined
+ }) {
+ this.testScenario(
+ // 'multiple selections'
+ [this.createSelection(), this.createSelection()],
+ fn,
+ _.isUndefined(multiple) ? empty : multiple
+ );
+ const executing = this.createSelection();
+ executing['cdExecuting'] = 'someAction';
+ this.testScenario(
+ // 'select executing item'
+ [executing],
+ fn,
+ _.isUndefined(singleExecuting) ? single : singleExecuting
+ );
+ this.testScenario([this.createSelection()], fn, single); // 'select non-executing item'
+ this.testScenario([], fn, empty); // 'no selection'
+ }
+
+ private testScenario(selection: object[], fn: () => any, expected: any) {
+ this.setSelection(selection);
+ expect(fn()).toBe(expected);
+ }
+
+ setSelection(selection: object[]) {
+ this.tableActions.selection.selected = selection;
+ this.tableActions.selection.update();
+ }
+}
+
+export class FormHelper {
+ form: CdFormGroup;
+
+ constructor(form: CdFormGroup) {
+ this.form = form;
+ }
+
+ /**
+ * Changes multiple values in multiple controls
+ */
+ setMultipleValues(values: { [controlName: string]: any }, markAsDirty?: boolean) {
+ Object.keys(values).forEach((key) => {
+ this.setValue(key, values[key], markAsDirty);
+ });
+ }
+
+ /**
+ * Changes the value of a control
+ */
+ setValue(control: AbstractControl | string, value: any, markAsDirty?: boolean): AbstractControl {
+ control = this.getControl(control);
+ if (markAsDirty) {
+ control.markAsDirty();
+ }
+ control.setValue(value);
+ return control;
+ }
+
+ private getControl(control: AbstractControl | string): AbstractControl {
+ if (typeof control === 'string') {
+ return this.form.get(control);
+ }
+ return control;
+ }
+
+ /**
+ * Change the value of the control and expect the control to be valid afterwards.
+ */
+ expectValidChange(control: AbstractControl | string, value: any, markAsDirty?: boolean) {
+ this.expectValid(this.setValue(control, value, markAsDirty));
+ }
+
+ /**
+ * Expect that the given control is valid.
+ */
+ expectValid(control: AbstractControl | string) {
+ // 'isValid' would be false for disabled controls
+ expect(this.getControl(control).errors).toBe(null);
+ }
+
+ /**
+ * Change the value of the control and expect a specific error.
+ */
+ expectErrorChange(
+ control: AbstractControl | string,
+ value: any,
+ error: string,
+ markAsDirty?: boolean
+ ) {
+ this.expectError(this.setValue(control, value, markAsDirty), error);
+ }
+
+ /**
+ * Expect a specific error for the given control.
+ */
+ expectError(control: AbstractControl | string, error: string) {
+ expect(this.getControl(control).hasError(error)).toBeTruthy();
+ }
+}
+
+export class FixtureHelper {
+ fixture: ComponentFixture<any>;
+
+ constructor(fixture: ComponentFixture<any>) {
+ this.fixture = fixture;
+ }
+
+ /**
+ * Expect a list of id elements to be visible or not.
+ */
+ expectIdElementsVisible(ids: string[], visibility: boolean) {
+ ids.forEach((css) => {
+ this.expectElementVisible(`#${css}`, visibility);
+ });
+ }
+
+ /**
+ * Expect a specific element to be visible or not.
+ */
+ expectElementVisible(css: string, visibility: boolean) {
+ expect(Boolean(this.getElementByCss(css))).toBe(visibility);
+ }
+
+ expectFormFieldToBe(css: string, value: string) {
+ const props = this.getElementByCss(css).properties;
+ expect(props['value'] || props['checked'].toString()).toBe(value);
+ }
+
+ clickElement(css: string) {
+ this.getElementByCss(css).triggerEventHandler('click', null);
+ this.fixture.detectChanges();
+ }
+
+ getText(css: string) {
+ const e = this.getElementByCss(css);
+ return e ? e.nativeElement.textContent.trim() : null;
+ }
+
+ getElementByCss(css: string) {
+ this.fixture.detectChanges();
+ return this.fixture.debugElement.query(By.css(css));
+ }
+}
+
+export class PrometheusHelper {
+ createSilence(id) {
+ return {
+ id: id,
+ createdBy: `Creator of ${id}`,
+ comment: `A comment for ${id}`,
+ startsAt: new Date('2022-02-22T22:22:00').toISOString(),
+ endsAt: new Date('2022-02-23T22:22:00').toISOString(),
+ matchers: [
+ {
+ name: 'job',
+ value: 'someJob',
+ isRegex: true
+ }
+ ]
+ };
+ }
+
+ createRule(name, severity, alerts: any[]): PrometheusRule {
+ return {
+ name: name,
+ labels: {
+ severity: severity
+ },
+ alerts: alerts
+ } as PrometheusRule;
+ }
+
+ createAlert(name, state = 'active', timeMultiplier = 1): AlertmanagerAlert {
+ return {
+ fingerprint: name,
+ status: { state },
+ labels: {
+ alertname: name,
+ instance: 'someInstance',
+ job: 'someJob',
+ severity: 'someSeverity'
+ },
+ annotations: {
+ summary: `${name} is ${state}`
+ },
+ generatorURL: `http://${name}`,
+ startsAt: new Date(new Date('2022-02-22').getTime() * timeMultiplier).toString()
+ } as AlertmanagerAlert;
+ }
+
+ createNotificationAlert(name, status = 'firing'): AlertmanagerNotificationAlert {
+ return {
+ status: status,
+ labels: {
+ alertname: name
+ },
+ annotations: {
+ summary: `${name} is ${status}`
+ },
+ generatorURL: `http://${name}`
+ } as AlertmanagerNotificationAlert;
+ }
+
+ createNotification(alertNumber = 1, status = 'firing'): AlertmanagerNotification {
+ const alerts = [];
+ for (let i = 0; i < alertNumber; i++) {
+ alerts.push(this.createNotificationAlert('alert' + i, status));
+ }
+ return { alerts, status } as AlertmanagerNotification;
+ }
+
+ createLink(url) {
+ return `<a href="${url}" target="_blank"><i class="fa fa-line-chart"></i></a>`;
+ }
+}
+
+const XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="ng2.template">
+ <body>
+ </body>
+ </file>
+</xliff>
+`;
+
+const i18nProviders = [
+ { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
+ { provide: TRANSLATIONS, useValue: XLIFF },
+ { provide: LOCALE_ID, useValue: 'en' },
+ I18n
+];
+
+export { i18nProviders };
+
+export function expectItemTasks(item: any, executing: string, percentage?: number) {
+ if (executing) {
+ executing = executing + '...';
+ if (percentage) {
+ executing = `${executing} ${percentage}%`;
+ }
+ }
+ expect(item.cdExecuting).toBe(executing);
+}
+
+export class IscsiHelper {
+ static validateUser(formHelper: FormHelper, fieldName: string) {
+ formHelper.expectErrorChange(fieldName, 'short', 'pattern');
+ formHelper.expectValidChange(fieldName, 'thisIsCorrect');
+ formHelper.expectErrorChange(fieldName, '##?badChars?##', 'pattern');
+ formHelper.expectErrorChange(
+ fieldName,
+ 'thisUsernameIsWayyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyTooBig',
+ 'pattern'
+ );
+ }
+
+ static validatePassword(formHelper: FormHelper, fieldName: string) {
+ formHelper.expectErrorChange(fieldName, 'short', 'pattern');
+ formHelper.expectValidChange(fieldName, 'thisIsCorrect');
+ formHelper.expectErrorChange(fieldName, '##?badChars?##', 'pattern');
+ formHelper.expectErrorChange(fieldName, 'thisPasswordIsWayTooBig', 'pattern');
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/tsconfig.app.json b/src/pybind/mgr/dashboard/frontend/src/tsconfig.app.json
new file mode 100644
index 00000000..05a9aad1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/tsconfig.app.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/app",
+ "baseUrl": "./",
+ "module": "es2015",
+ "types": []
+ },
+ "exclude": [
+ "**/*.spec.ts",
+ "testing/*.ts"
+ ]
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/tsconfig.spec.json b/src/pybind/mgr/dashboard/frontend/src/tsconfig.spec.json
new file mode 100644
index 00000000..0533feab
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/tsconfig.spec.json
@@ -0,0 +1,22 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/spec",
+ "baseUrl": "./",
+ "module": "commonjs",
+ "target": "es5",
+ "types": [
+ "jest",
+ "node"
+ ],
+ "noEmit": true
+ },
+ "files": [
+ "polyfills.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts",
+ "testing/*.ts"
+ ]
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/typings.d.ts b/src/pybind/mgr/dashboard/frontend/src/typings.d.ts
new file mode 100644
index 00000000..ef5c7bd6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/typings.d.ts
@@ -0,0 +1,5 @@
+/* SystemJS module definition */
+declare var module: NodeModule;
+interface NodeModule {
+ id: string;
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/unit-test-configuration.ts.sample b/src/pybind/mgr/dashboard/frontend/src/unit-test-configuration.ts.sample
new file mode 100644
index 00000000..74dbf2c0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/unit-test-configuration.ts.sample
@@ -0,0 +1 @@
+export const _DEV_ = false;
diff --git a/src/pybind/mgr/dashboard/frontend/src/vendor.overrides.scss b/src/pybind/mgr/dashboard/frontend/src/vendor.overrides.scss
new file mode 100644
index 00000000..0cca9de8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/vendor.overrides.scss
@@ -0,0 +1,3 @@
+/* Vendor specific scss */
+
+@import 'defaults';
diff --git a/src/pybind/mgr/dashboard/frontend/src/vendor.variables.scss b/src/pybind/mgr/dashboard/frontend/src/vendor.variables.scss
new file mode 100644
index 00000000..e35fef11
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/vendor.variables.scss
@@ -0,0 +1 @@
+/* Vendor specific variables */
diff --git a/src/pybind/mgr/dashboard/frontend/tsconfig.json b/src/pybind/mgr/dashboard/frontend/tsconfig.json
new file mode 100644
index 00000000..557f4b43
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "importHelpers": true,
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "target": "es5",
+ "typeRoots": ["node_modules/@types"],
+ "lib": ["es2017", "dom"],
+ "allowJs": true
+ }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/tslint.json b/src/pybind/mgr/dashboard/frontend/tslint.json
new file mode 100644
index 00000000..f0ce66cf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/tslint.json
@@ -0,0 +1,90 @@
+{
+ "rulesDirectory": ["node_modules/codelyzer"],
+ "rules": {
+ "no-consecutive-blank-lines": true,
+ "arrow-return-shorthand": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": [true, "check-space"],
+ "curly": true,
+ "eofline": true,
+ "forin": true,
+ "import-blacklist": [true, "rxjs/Rx", "ngx-bootstrap"],
+ "import-spacing": true,
+ "indent": [true, "spaces"],
+ "interface-over-type-literal": true,
+ "label-position": true,
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": ["static-field", "instance-field", "static-method", "instance-method"]
+ }
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-empty": false,
+ "no-empty-interface": true,
+ "no-eval": true,
+ "no-inferrable-types": [true, "ignore-params"],
+ "no-misused-new": true,
+ "no-non-null-assertion": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-string-throw": true,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-initializer": true,
+ "no-unused-expression": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"],
+ "prefer-const": true,
+ "quotemark": [true, "single"],
+ "radix": true,
+ "semicolon": [true, "always"],
+ "triple-equals": [true, "allow-null-check"],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "unified-signatures": true,
+ "variable-name": [true, "check-format", "allow-snake-case", "allow-leading-underscore"],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-operator",
+ "check-separator",
+ "check-type",
+ "check-module"
+ ],
+ "directive-selector": [true, "attribute", "cd", "camelCase"],
+ "component-selector": [true, "element", "cd", "kebab-case"],
+ "angular-whitespace": [true, "check-interpolation", "check-semicolon"],
+ "no-output-on-prefix": true,
+ "use-input-property-decorator": true,
+ "use-output-property-decorator": true,
+ "use-host-property-decorator": true,
+ "no-attribute-parameter-decorator": true,
+ "no-input-rename": true,
+ "no-output-rename": true,
+ "use-life-cycle-interface": true,
+ "use-pipe-transform-interface": true,
+ "component-class-suffix": true,
+ "directive-class-suffix": true,
+ "no-forward-ref": true,
+ "no-output-named-after-standard-event": true,
+ "ordered-imports": true
+ }
+}
diff --git a/src/pybind/mgr/dashboard/grafana.py b/src/pybind/mgr/dashboard/grafana.py
new file mode 100644
index 00000000..e1157553
--- /dev/null
+++ b/src/pybind/mgr/dashboard/grafana.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+import os
+import time
+import requests
+
+from . import logger
+from .exceptions import GrafanaError
+from .settings import Settings
+
+
+class GrafanaRestClient(object):
+
+ @staticmethod
+ def url_validation(method, path):
+ response = requests.request(
+ method,
+ path,
+ verify=Settings.GRAFANA_API_SSL_VERIFY)
+ return response.status_code
+
+ @staticmethod
+ def push_dashboard(dashboard_obj):
+ if not Settings.GRAFANA_API_URL:
+ raise GrafanaError("The Grafana API URL is not set")
+ if not Settings.GRAFANA_API_URL.startswith('http'):
+ raise GrafanaError("The Grafana API URL is invalid")
+ if not Settings.GRAFANA_API_USERNAME:
+ raise GrafanaError("The Grafana API username is not set")
+ if not Settings.GRAFANA_API_PASSWORD:
+ raise GrafanaError("The Grafana API password is not set")
+ url = Settings.GRAFANA_API_URL.rstrip('/') + \
+ '/api/dashboards/db'
+ headers = {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ }
+ payload = {
+ 'dashboard': dashboard_obj,
+ 'overwrite': True,
+ }
+ try:
+ response = requests.post(
+ url,
+ headers=headers,
+ data=json.dumps(payload),
+ auth=(Settings.GRAFANA_API_USERNAME,
+ Settings.GRAFANA_API_PASSWORD),
+ verify=Settings.GRAFANA_API_SSL_VERIFY
+ )
+ except requests.ConnectionError:
+ raise GrafanaError("Could not connect to Grafana server")
+ response.raise_for_status()
+ return response.status_code, response.json()
+
+
+class Retrier(object):
+ def __init__(self, tries, sleep, func, *args, **kwargs):
+ """
+ Wraps a function. An instance of this class may be called to call that
+ function, retrying if it raises an exception. Sleeps between retries,
+ eventually reraising the original exception when retries are exhausted.
+ Once the function returns a value, that value is returned.
+
+ :param tries: How many times to try, before reraising the exception
+ :type tries: int
+ :param sleep: How many seconds to wait between tries
+ :type sleep: int|float
+ :param func: The function to execute
+ :type func: function
+ :param args: Any arguments to pass to the function
+ :type args: list
+ :param kwargs: Any keyword arguments to pass to the function
+ :type kwargs: dict
+ """
+ assert tries >= 1
+ self.tries = int(tries)
+ self.tried = 0
+ self.sleep = sleep
+ self.func = func
+ self.args = args
+ self.kwargs = kwargs
+
+ def __call__(self):
+ result = None
+ while self.tried < self.tries:
+ try:
+ result = self.func(*self.args, **self.kwargs)
+ except Exception: # pylint: disable=broad-except
+ if self.tried == self.tries - 1:
+ raise
+ else:
+ self.tried += 1
+ time.sleep(self.sleep)
+ else:
+ return result
+
+
+def load_local_dashboards():
+ if os.environ.get('CEPH_DEV') == '1' or 'UNITTEST' in os.environ:
+ path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__),
+ '../../../../monitoring/grafana/dashboards/'
+ ))
+ else:
+ path = '/etc/grafana/dashboards/ceph-dashboard'
+ dashboards = dict()
+ for item in [p for p in os.listdir(path) if p.endswith('.json')]:
+ db_path = os.path.join(path, item)
+ with open(db_path) as f:
+ dashboards[item] = json.loads(f.read())
+ return dashboards
+
+
+def push_local_dashboards(tries=1, sleep=0):
+ try:
+ dashboards = load_local_dashboards()
+ except (EnvironmentError, ValueError):
+ logger.exception("Failed to load local dashboard files")
+ raise
+
+ def push():
+ try:
+ grafana = GrafanaRestClient()
+ for body in dashboards.values():
+ grafana.push_dashboard(body)
+ except Exception:
+ logger.exception("Failed to push dashboards to Grafana")
+ raise
+ retry = Retrier(tries, sleep, push)
+ retry()
+ return True
diff --git a/src/pybind/mgr/dashboard/module.py b/src/pybind/mgr/dashboard/module.py
new file mode 100644
index 00000000..9770bd85
--- /dev/null
+++ b/src/pybind/mgr/dashboard/module.py
@@ -0,0 +1,517 @@
+# -*- coding: utf-8 -*-
+"""
+ceph dashboard mgr plugin (based on CherryPy)
+"""
+from __future__ import absolute_import
+
+import collections
+from distutils.version import StrictVersion
+import errno
+import os
+import socket
+import ssl
+import sys
+import tempfile
+import threading
+import time
+from uuid import uuid4
+from OpenSSL import crypto
+import _strptime # pylint: disable=unused-import
+from mgr_module import MgrModule, MgrStandbyModule, Option, CLIWriteCommand
+from mgr_util import get_default_addr, ServerConfigException, verify_tls_files
+
+try:
+ import cherrypy
+ from cherrypy._cptools import HandlerWrapperTool
+except ImportError:
+ # To be picked up and reported by .can_run()
+ cherrypy = None
+
+from .services.sso import load_sso_db
+
+if cherrypy is not None:
+ from .cherrypy_backports import patch_cherrypy
+ patch_cherrypy(cherrypy.__version__)
+
+if 'COVERAGE_ENABLED' in os.environ:
+ import coverage
+ __cov = coverage.Coverage(config_file="{}/.coveragerc".format(os.path.dirname(__file__)),
+ data_suffix=True)
+
+ cherrypy.engine.subscribe('start', __cov.start)
+ cherrypy.engine.subscribe('after_request', __cov.save)
+ cherrypy.engine.subscribe('stop', __cov.stop)
+
+# pylint: disable=wrong-import-position
+from . import logger, mgr
+from .controllers import generate_routes, json_error_page
+from .grafana import push_local_dashboards
+from .tools import NotificationQueue, RequestLoggingTool, TaskManager, \
+ prepare_url_prefix, str_to_bool
+from .services.auth import AuthManager, AuthManagerTool, JwtManager
+from .services.sso import SSO_COMMANDS, \
+ handle_sso_command
+from .services.exception import dashboard_exception_handler
+from .settings import options_command_list, options_schema_list, \
+ handle_option_command
+
+from .plugins import PLUGIN_MANAGER
+from .plugins import feature_toggles, debug # noqa # pylint: disable=unused-import
+
+
+PLUGIN_MANAGER.hook.init()
+
+
+# cherrypy likes to sys.exit on error. don't let it take us down too!
+# pylint: disable=W0613
+def os_exit_noop(*args):
+ pass
+
+
+# pylint: disable=W0212
+os._exit = os_exit_noop
+
+
+class CherryPyConfig(object):
+ """
+ Class for common server configuration done by both active and
+ standby module, especially setting up SSL.
+ """
+
+ def __init__(self):
+ self._stopping = threading.Event()
+ self._url_prefix = ""
+
+ self.cert_tmp = None
+ self.pkey_tmp = None
+
+ def shutdown(self):
+ self._stopping.set()
+
+ @property
+ def url_prefix(self):
+ return self._url_prefix
+
+ @staticmethod
+ def update_cherrypy_config(config):
+ PLUGIN_MANAGER.hook.configure_cherrypy(config=config)
+ cherrypy.config.update(config)
+
+ # pylint: disable=too-many-branches
+ def _configure(self):
+ """
+ Configure CherryPy and initialize self.url_prefix
+
+ :returns our URI
+ """
+ server_addr = self.get_localized_module_option(
+ 'server_addr', get_default_addr())
+ use_ssl = self.get_localized_module_option('ssl', True)
+ if not use_ssl:
+ server_port = self.get_localized_module_option('server_port', 8080)
+ else:
+ server_port = self.get_localized_module_option('ssl_server_port', 8443)
+
+ if server_addr is None:
+ raise ServerConfigException(
+ 'no server_addr configured; '
+ 'try "ceph config set mgr mgr/{}/{}/server_addr <ip>"'
+ .format(self.module_name, self.get_mgr_id()))
+ self.log.info('server: ssl=%s host=%s port=%d', 'yes' if use_ssl else 'no',
+ server_addr, server_port)
+
+ # Initialize custom handlers.
+ cherrypy.tools.authenticate = AuthManagerTool()
+ cherrypy.tools.plugin_hooks_filter_request = cherrypy.Tool(
+ 'before_handler',
+ lambda: PLUGIN_MANAGER.hook.filter_request_before_handler(request=cherrypy.request),
+ priority=1)
+ cherrypy.tools.request_logging = RequestLoggingTool()
+ cherrypy.tools.dashboard_exception_handler = HandlerWrapperTool(dashboard_exception_handler,
+ priority=31)
+
+ # Apply the 'global' CherryPy configuration.
+ config = {
+ 'engine.autoreload.on': False,
+ 'server.socket_host': server_addr,
+ 'server.socket_port': int(server_port),
+ 'error_page.default': json_error_page,
+ 'tools.request_logging.on': True,
+ 'tools.gzip.on': True,
+ 'tools.gzip.mime_types': [
+ # text/html and text/plain are the default types to compress
+ 'text/html', 'text/plain',
+ # We also want JSON and JavaScript to be compressed
+ 'application/json',
+ 'application/javascript',
+ ],
+ 'tools.json_in.on': True,
+ 'tools.json_in.force': True,
+ 'tools.plugin_hooks_filter_request.on': True,
+ }
+
+ if use_ssl:
+ # SSL initialization
+ cert = self.get_store("crt")
+ if cert is not None:
+ self.cert_tmp = tempfile.NamedTemporaryFile()
+ self.cert_tmp.write(cert.encode('utf-8'))
+ self.cert_tmp.flush() # cert_tmp must not be gc'ed
+ cert_fname = self.cert_tmp.name
+ else:
+ cert_fname = self.get_localized_module_option('crt_file')
+
+ pkey = self.get_store("key")
+ if pkey is not None:
+ self.pkey_tmp = tempfile.NamedTemporaryFile()
+ self.pkey_tmp.write(pkey.encode('utf-8'))
+ self.pkey_tmp.flush() # pkey_tmp must not be gc'ed
+ pkey_fname = self.pkey_tmp.name
+ else:
+ pkey_fname = self.get_localized_module_option('key_file')
+
+ verify_tls_files(cert_fname, pkey_fname)
+
+ # Create custom SSL context to disable TLS 1.0 and 1.1.
+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+ context.load_cert_chain(cert_fname, pkey_fname)
+ if sys.version_info >= (3, 7):
+ context.minimum_version = ssl.TLSVersion.TLSv1_2
+ else:
+ # Based on tests limiting TLS to specific versions
+ # starts working with CherryPy >= 8.9.1 (Ubuntu 18.04
+ # or SUSE Leap 15.1).
+ if StrictVersion(cherrypy.__version__) >= StrictVersion('8.9.1'):
+ context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
+
+ config['server.ssl_module'] = 'builtin'
+ config['server.ssl_certificate'] = cert_fname
+ config['server.ssl_private_key'] = pkey_fname
+ config['server.ssl_context'] = context
+
+ self.update_cherrypy_config(config)
+
+ self._url_prefix = prepare_url_prefix(self.get_module_option('url_prefix',
+ default=''))
+
+ uri = "{0}://{1}:{2}{3}/".format(
+ 'https' if use_ssl else 'http',
+ socket.getfqdn(server_addr if server_addr != '::' else ''),
+ server_port,
+ self.url_prefix
+ )
+
+ return uri
+
+ def await_configuration(self):
+ """
+ Block until configuration is ready (i.e. all needed keys are set)
+ or self._stopping is set.
+
+ :returns URI of configured webserver
+ """
+ while not self._stopping.is_set():
+ try:
+ uri = self._configure()
+ except ServerConfigException as e:
+ self.log.info("Config not ready to serve, waiting: {0}".format(
+ e
+ ))
+ # Poll until a non-errored config is present
+ self._stopping.wait(5)
+ else:
+ self.log.info("Configured CherryPy, starting engine...")
+ return uri
+
+
+class Module(MgrModule, CherryPyConfig):
+ """
+ dashboard module entrypoint
+ """
+
+ COMMANDS = [
+ {
+ 'cmd': 'dashboard set-jwt-token-ttl '
+ 'name=seconds,type=CephInt',
+ 'desc': 'Set the JWT token TTL in seconds',
+ 'perm': 'w'
+ },
+ {
+ 'cmd': 'dashboard get-jwt-token-ttl',
+ 'desc': 'Get the JWT token TTL in seconds',
+ 'perm': 'r'
+ },
+ {
+ "cmd": "dashboard create-self-signed-cert",
+ "desc": "Create self signed certificate",
+ "perm": "w"
+ },
+ {
+ "cmd": "dashboard grafana dashboards update",
+ "desc": "Push dashboards to Grafana",
+ "perm": "w",
+ },
+ ]
+ COMMANDS.extend(options_command_list())
+ COMMANDS.extend(SSO_COMMANDS)
+ PLUGIN_MANAGER.hook.register_commands()
+
+ MODULE_OPTIONS = [
+ Option(name='server_addr', type='str', default=get_default_addr()),
+ Option(name='server_port', type='int', default=8080),
+ Option(name='ssl_server_port', type='int', default=8443),
+ Option(name='jwt_token_ttl', type='int', default=28800),
+ Option(name='password', type='str', default=''),
+ Option(name='url_prefix', type='str', default=''),
+ Option(name='username', type='str', default=''),
+ Option(name='key_file', type='str', default=''),
+ Option(name='crt_file', type='str', default=''),
+ Option(name='ssl', type='bool', default=True),
+ Option(name='standby_behaviour', type='str', default='redirect',
+ enum_allowed=['redirect', 'error']),
+ Option(name='standby_error_status_code', type='int', default=500,
+ min=400, max=599)
+ ]
+ MODULE_OPTIONS.extend(options_schema_list())
+ for options in PLUGIN_MANAGER.hook.get_options() or []:
+ MODULE_OPTIONS.extend(options)
+
+ __pool_stats = collections.defaultdict(lambda: collections.defaultdict(
+ lambda: collections.deque(maxlen=10)))
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ CherryPyConfig.__init__(self)
+
+ mgr.init(self)
+
+ self._stopping = threading.Event()
+ self.shutdown_event = threading.Event()
+ self.ACCESS_CTRL_DB = None
+ self.SSO_DB = None
+ self.health_checks = {}
+
+ @classmethod
+ def can_run(cls):
+ if cherrypy is None:
+ return False, "Missing dependency: cherrypy"
+
+ if not os.path.exists(cls.get_frontend_path()):
+ return False, "Frontend assets not found: incomplete build?"
+
+ return True, ""
+
+ @classmethod
+ def get_frontend_path(cls):
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ return os.path.join(current_dir, 'frontend/dist')
+
+ def serve(self):
+ AuthManager.initialize()
+ load_sso_db()
+
+ uri = self.await_configuration()
+ if uri is None:
+ # We were shut down while waiting
+ return
+
+ # Publish the URI that others may use to access the service we're
+ # about to start serving
+ self.set_uri(uri)
+
+ mapper, parent_urls = generate_routes(self.url_prefix)
+
+ config = {}
+ for purl in parent_urls:
+ config[purl] = {
+ 'request.dispatch': mapper
+ }
+
+ cherrypy.tree.mount(None, config=config)
+
+ PLUGIN_MANAGER.hook.setup()
+
+ cherrypy.engine.start()
+ NotificationQueue.start_queue()
+ TaskManager.init()
+ logger.info('Engine started.')
+ update_dashboards = str_to_bool(
+ self.get_module_option('GRAFANA_UPDATE_DASHBOARDS', 'False'))
+ if update_dashboards:
+ logger.info('Starting Grafana dashboard task')
+ TaskManager.run(
+ 'grafana/dashboards/update',
+ {},
+ push_local_dashboards,
+ kwargs=dict(tries=10, sleep=60),
+ )
+ # wait for the shutdown event
+ self.shutdown_event.wait()
+ self.shutdown_event.clear()
+ NotificationQueue.stop()
+ cherrypy.engine.stop()
+ logger.info('Engine stopped')
+
+ def shutdown(self):
+ super(Module, self).shutdown()
+ CherryPyConfig.shutdown(self)
+ logger.info('Stopping engine...')
+ self.shutdown_event.set()
+
+ @CLIWriteCommand("dashboard set-ssl-certificate",
+ "name=mgr_id,type=CephString,req=false")
+ def set_ssl_certificate(self, mgr_id=None, inbuf=None):
+ if inbuf is None:
+ return -errno.EINVAL, '',\
+ 'Please specify the certificate file with "-i" option'
+ if mgr_id is not None:
+ self.set_store('{}/crt'.format(mgr_id), inbuf)
+ else:
+ self.set_store('crt', inbuf)
+ return 0, 'SSL certificate updated', ''
+
+ @CLIWriteCommand("dashboard set-ssl-certificate-key",
+ "name=mgr_id,type=CephString,req=false")
+ def set_ssl_certificate_key(self, mgr_id=None, inbuf=None):
+ if inbuf is None:
+ return -errno.EINVAL, '',\
+ 'Please specify the certificate key file with "-i" option'
+ if mgr_id is not None:
+ self.set_store('{}/key'.format(mgr_id), inbuf)
+ else:
+ self.set_store('key', inbuf)
+ return 0, 'SSL certificate key updated', ''
+
+ def handle_command(self, inbuf, cmd):
+ # pylint: disable=too-many-return-statements
+ res = handle_option_command(cmd, inbuf)
+ if res[0] != -errno.ENOSYS:
+ return res
+ res = handle_sso_command(cmd)
+ if res[0] != -errno.ENOSYS:
+ return res
+ if cmd['prefix'] == 'dashboard set-jwt-token-ttl':
+ self.set_module_option('jwt_token_ttl', str(cmd['seconds']))
+ return 0, 'JWT token TTL updated', ''
+ if cmd['prefix'] == 'dashboard get-jwt-token-ttl':
+ ttl = self.get_module_option('jwt_token_ttl', JwtManager.JWT_TOKEN_TTL)
+ return 0, str(ttl), ''
+ if cmd['prefix'] == 'dashboard create-self-signed-cert':
+ self.create_self_signed_cert()
+ return 0, 'Self-signed certificate created', ''
+ if cmd['prefix'] == 'dashboard grafana dashboards update':
+ push_local_dashboards()
+ return 0, 'Grafana dashboards updated', ''
+
+ return (-errno.EINVAL, '', 'Command not found \'{0}\''
+ .format(cmd['prefix']))
+
+ def create_self_signed_cert(self):
+ # create a key pair
+ pkey = crypto.PKey()
+ pkey.generate_key(crypto.TYPE_RSA, 2048)
+
+ # create a self-signed cert
+ cert = crypto.X509()
+ cert.get_subject().O = "IT"
+ cert.get_subject().CN = "ceph-dashboard"
+ cert.set_serial_number(int(uuid4()))
+ cert.gmtime_adj_notBefore(0)
+ cert.gmtime_adj_notAfter(10*365*24*60*60)
+ cert.set_issuer(cert.get_subject())
+ cert.set_pubkey(pkey)
+ cert.sign(pkey, 'sha512')
+
+ cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
+ self.set_store('crt', cert.decode('utf-8'))
+
+ pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
+ self.set_store('key', pkey.decode('utf-8'))
+
+ def notify(self, notify_type, notify_id):
+ NotificationQueue.new_notification(notify_type, notify_id)
+
+ def get_updated_pool_stats(self):
+ df = self.get('df')
+ pool_stats = {p['id']: p['stats'] for p in df['pools']}
+ now = time.time()
+ for pool_id, stats in pool_stats.items():
+ for stat_name, stat_val in stats.items():
+ self.__pool_stats[pool_id][stat_name].append((now, stat_val))
+
+ return self.__pool_stats
+
+ def config_notify(self):
+ """
+ This method is called whenever one of our config options is changed.
+ """
+ PLUGIN_MANAGER.hook.config_notify()
+
+ def refresh_health_checks(self):
+ self.set_health_checks(self.health_checks)
+
+
+class StandbyModule(MgrStandbyModule, CherryPyConfig):
+ def __init__(self, *args, **kwargs):
+ super(StandbyModule, self).__init__(*args, **kwargs)
+ CherryPyConfig.__init__(self)
+ self.shutdown_event = threading.Event()
+
+ # We can set the global mgr instance to ourselves even though
+ # we're just a standby, because it's enough for logging.
+ mgr.init(self)
+
+ def serve(self):
+ uri = self.await_configuration()
+ if uri is None:
+ # We were shut down while waiting
+ return
+
+ module = self
+
+ class Root(object):
+ @cherrypy.expose
+ def default(self, *args, **kwargs):
+ if module.get_module_option('standby_behaviour', 'redirect') == 'redirect':
+ active_uri = module.get_active_uri()
+ if active_uri:
+ module.log.info("Redirecting to active '%s'", active_uri)
+ raise cherrypy.HTTPRedirect(active_uri)
+ else:
+ template = """
+ <html>
+ <!-- Note: this is only displayed when the standby
+ does not know an active URI to redirect to, otherwise
+ a simple redirect is returned instead -->
+ <head>
+ <title>Ceph</title>
+ <meta http-equiv="refresh" content="{delay}">
+ </head>
+ <body>
+ No active ceph-mgr instance is currently running
+ the dashboard. A failover may be in progress.
+ Retrying in {delay} seconds...
+ </body>
+ </html>
+ """
+ return template.format(delay=5)
+ else:
+ status = module.get_module_option('standby_error_status_code', 500)
+ raise cherrypy.HTTPError(status, message="Keep on looking")
+
+ cherrypy.tree.mount(Root(), "{}/".format(self.url_prefix), {})
+ self.log.info("Starting engine...")
+ cherrypy.engine.start()
+ self.log.info("Engine started...")
+ # Wait for shutdown event
+ self.shutdown_event.wait()
+ self.shutdown_event.clear()
+ cherrypy.engine.stop()
+ self.log.info("Engine stopped.")
+
+ def shutdown(self):
+ CherryPyConfig.shutdown(self)
+
+ self.log.info("Stopping engine...")
+ self.shutdown_event.set()
+ self.log.info("Stopped engine...")
diff --git a/src/pybind/mgr/dashboard/plugins/__init__.py b/src/pybind/mgr/dashboard/plugins/__init__.py
new file mode 100644
index 00000000..43d71fde
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/__init__.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import abc
+import six
+
+from .pluggy import HookspecMarker, HookimplMarker, PluginManager
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Interface(object):
+ pass
+
+
+class Mixin(object):
+ pass
+
+
+class DashboardPluginManager(object):
+ def __init__(self, project_name):
+ self.__pm = PluginManager(project_name)
+ self.__add_spec = HookspecMarker(project_name)
+ self.__add_abcspec = lambda *args, **kwargs: abc.abstractmethod(
+ self.__add_spec(*args, **kwargs))
+ self.__add_hook = HookimplMarker(project_name)
+
+ pm = property(lambda self: self.__pm)
+ hook = property(lambda self: self.pm.hook)
+
+ add_spec = property(lambda self: self.__add_spec)
+ add_abcspec = property(lambda self: self.__add_abcspec)
+ add_hook = property(lambda self: self.__add_hook)
+
+ def add_interface(self, cls):
+ assert issubclass(cls, Interface)
+ self.pm.add_hookspecs(cls)
+ return cls
+
+ @staticmethod
+ def final(func):
+ setattr(func, '__final__', True)
+ return func
+
+ def add_plugin(self, plugin):
+ """ Provides decorator interface for PluginManager.register():
+ @PLUGIN_MANAGER.add_plugin
+ class Plugin(...):
+ ...
+ Additionally it checks whether the Plugin instance has all Interface
+ methods implemented and marked with add_hook decorator.
+ As a con of this approach, plugins cannot call super() from __init__()
+ """
+ assert issubclass(plugin, Interface)
+ from inspect import getmembers, ismethod
+ for interface in plugin.__bases__:
+ for method_name, _ in getmembers(interface, predicate=ismethod):
+ if hasattr(getattr(interface, method_name), '__final__'):
+ continue
+
+ if self.pm.parse_hookimpl_opts(plugin, method_name) is None:
+ raise NotImplementedError(
+ "Plugin '{}' implements interface '{}' but existing"
+ " method '{}' is not declared added as hook".format(
+ plugin.__name__,
+ interface.__name__,
+ method_name))
+ self.pm.register(plugin())
+ return plugin
+
+
+PLUGIN_MANAGER = DashboardPluginManager("ceph-mgr.dashboard")
+
+# Load all interfaces and their hooks
+from . import interfaces
diff --git a/src/pybind/mgr/dashboard/plugins/debug.py b/src/pybind/mgr/dashboard/plugins/debug.py
new file mode 100644
index 00000000..5f4cdbea
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/debug.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from enum import Enum
+import json
+
+from . import PLUGIN_MANAGER as PM
+from . import interfaces as I # noqa: E741,N812
+from .plugin import SimplePlugin as SP
+
+
+class Actions(Enum):
+ ENABLE = 'enable'
+ DISABLE = 'disable'
+ STATUS = 'status'
+
+
+@PM.add_plugin # pylint: disable=too-many-ancestors
+class Debug(SP, I.CanCherrypy, I.ConfiguresCherryPy, # pylint: disable=too-many-ancestors
+ I.Setupable, I.ConfigNotify):
+ NAME = 'debug'
+
+ OPTIONS = [
+ SP.Option(
+ name=NAME,
+ default=False,
+ type='bool',
+ desc="Enable/disable debug options"
+ )
+ ]
+
+ def _refresh_health_checks(self):
+ debug = self.get_option(self.NAME)
+ if debug:
+ self.mgr.health_checks.update({'DASHBOARD_DEBUG': {
+ 'severity': 'warning',
+ 'summary': 'Dashboard debug mode is enabled',
+ 'detail': [
+ 'Please disable debug mode in production environments using '
+ '"ceph dashboard {} {}"'.format(self.NAME, Actions.DISABLE.value)
+ ]
+ }})
+ else:
+ self.mgr.health_checks.pop('DASHBOARD_DEBUG', None)
+ self.mgr.refresh_health_checks()
+
+ @PM.add_hook
+ def setup(self):
+ self._refresh_health_checks()
+
+ def handler(self, action):
+ ret = 0
+ msg = ''
+ if action in [Actions.ENABLE.value, Actions.DISABLE.value]:
+ self.set_option(self.NAME, action == Actions.ENABLE.value)
+ self.mgr.update_cherrypy_config({})
+ self._refresh_health_checks()
+ else:
+ debug = self.get_option(self.NAME)
+ msg = "Debug: '{}'".format('enabled' if debug else 'disabled')
+ return ret, msg, None
+
+ COMMANDS = [
+ SP.Command(
+ prefix="dashboard {name}".format(name=NAME),
+ args="name=action,type=CephChoices,strings={states}".format(
+ states="|".join(a.value for a in Actions)),
+ desc="Control and report debug status in Ceph-Dashboard",
+ handler=handler
+ )
+ ]
+
+ def custom_error_response(self, status, message, traceback, version):
+ self.response.headers['Content-Type'] = 'application/json'
+ error_response = dict(status=status, detail=message, request_id=str(self.request.unique_id))
+
+ if self.get_option(self.NAME):
+ error_response.update(dict(traceback=traceback, version=version))
+
+ return json.dumps(error_response)
+
+ @PM.add_hook
+ def configure_cherrypy(self, config):
+ config.update({
+ 'environment': 'test_suite' if self.get_option(self.NAME) else 'production',
+ 'error_page.default': self.custom_error_response,
+ })
+
+ @PM.add_hook
+ def config_notify(self):
+ self._refresh_health_checks()
diff --git a/src/pybind/mgr/dashboard/plugins/feature_toggles.py b/src/pybind/mgr/dashboard/plugins/feature_toggles.py
new file mode 100644
index 00000000..7edbfa8f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/feature_toggles.py
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from enum import Enum
+import cherrypy
+from mgr_module import CLICommand, Option
+
+from . import PLUGIN_MANAGER as PM
+from . import interfaces as I
+from .ttl_cache import ttl_cache
+
+from ..controllers.rbd import Rbd, RbdSnapshot, RbdTrash
+from ..controllers.rbd_mirroring import (
+ RbdMirroringSummary, RbdMirroringPoolMode, RbdMirroringPoolPeer)
+from ..controllers.iscsi import Iscsi, IscsiTarget
+from ..controllers.cephfs import CephFS
+from ..controllers.rgw import Rgw, RgwDaemon, RgwBucket, RgwUser
+
+
+class Features(Enum):
+ RBD = 'rbd'
+ MIRRORING = 'mirroring'
+ ISCSI = 'iscsi'
+ CEPHFS = 'cephfs'
+ RGW = 'rgw'
+
+
+PREDISABLED_FEATURES = set()
+
+
+Feature2Controller = {
+ Features.RBD: [Rbd, RbdSnapshot, RbdTrash],
+ Features.MIRRORING: [
+ RbdMirroringSummary, RbdMirroringPoolMode, RbdMirroringPoolPeer],
+ Features.ISCSI: [Iscsi, IscsiTarget],
+ Features.CEPHFS: [CephFS],
+ Features.RGW: [Rgw, RgwDaemon, RgwBucket, RgwUser],
+}
+
+
+class Actions(Enum):
+ ENABLE = 'enable'
+ DISABLE = 'disable'
+ STATUS = 'status'
+
+
+@PM.add_plugin
+class FeatureToggles(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions,
+ I.HasCommands, I.FilterRequest.BeforeHandler,
+ I.HasControllers):
+ OPTION_FMT = 'FEATURE_TOGGLE_{}'
+ CACHE_MAX_SIZE = 128 # Optimum performance with 2^N sizes
+ CACHE_TTL = 10 # seconds
+
+ @PM.add_hook
+ def setup(self):
+ self.Controller2Feature = {
+ controller: feature
+ for feature, controllers in Feature2Controller.items()
+ for controller in controllers}
+
+ @PM.add_hook
+ def get_options(self):
+ return [Option(
+ name=self.OPTION_FMT.format(feature.value),
+ default=(feature not in PREDISABLED_FEATURES),
+ type='bool',) for feature in Features]
+
+ @PM.add_hook
+ def register_commands(self):
+ @CLICommand(
+ "dashboard feature",
+ "name=action,type=CephChoices,strings={} ".format(
+ "|".join(a.value for a in Actions))
+ + "name=features,type=CephChoices,strings={},req=false,n=N".format(
+ "|".join(f.value for f in Features)),
+ "Enable or disable features in Ceph-Mgr Dashboard")
+ def cmd(mgr, action, features=None):
+ ret = 0
+ msg = []
+ if action in [Actions.ENABLE.value, Actions.DISABLE.value]:
+ if features is None:
+ ret = 1
+ msg = ["At least one feature must be specified"]
+ else:
+ for feature in features:
+ mgr.set_module_option(
+ self.OPTION_FMT.format(feature),
+ action == Actions.ENABLE.value)
+ msg += ["Feature '{}': {}".format(
+ feature,
+ 'enabled' if action == Actions.ENABLE.value else
+ 'disabled')]
+ else:
+ for feature in features or [f.value for f in Features]:
+ enabled = mgr.get_module_option(self.OPTION_FMT.format(feature))
+ msg += ["Feature '{}': '{}'".format(
+ feature,
+ 'enabled' if enabled else 'disabled')]
+ return ret, '\n'.join(msg), ''
+ return {'handle_command': cmd}
+
+ def _get_feature_from_request(self, request):
+ try:
+ return self.Controller2Feature[
+ request.handler.callable.__self__]
+ except (AttributeError, KeyError):
+ return None
+
+ @ttl_cache(ttl=CACHE_TTL, maxsize=CACHE_MAX_SIZE)
+ def _is_feature_enabled(self, feature):
+ return self.mgr.get_module_option(self.OPTION_FMT.format(feature.value))
+
+ @PM.add_hook
+ def filter_request_before_handler(self, request):
+ feature = self._get_feature_from_request(request)
+ if feature is None:
+ return
+
+ if not self._is_feature_enabled(feature):
+ raise cherrypy.HTTPError(
+ 404, "Feature='{}' disabled by option '{}'".format(
+ feature.value,
+ self.OPTION_FMT.format(feature.value),
+ )
+ )
+
+ @PM.add_hook
+ def get_controllers(self):
+ from ..controllers import ApiController, RESTController
+
+ @ApiController('/feature_toggles')
+ class FeatureTogglesEndpoint(RESTController):
+
+ def list(_):
+ return {
+ feature.value: self._is_feature_enabled(feature)
+ for feature in Features
+ }
+ return [FeatureTogglesEndpoint]
diff --git a/src/pybind/mgr/dashboard/plugins/interfaces.py b/src/pybind/mgr/dashboard/plugins/interfaces.py
new file mode 100644
index 00000000..dbcd60a0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/interfaces.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import PLUGIN_MANAGER as PM, Interface, Mixin # pylint: disable=cyclic-import
+
+
+class CanMgr(Mixin):
+ from .. import mgr
+ mgr = mgr
+
+
+class CanLog(Mixin):
+ from .. import logger
+ log = logger
+
+
+class CanCherrypy(Mixin):
+ import cherrypy
+ request = cherrypy.request
+ response = cherrypy.response
+
+
+@PM.add_interface
+class Initializable(Interface):
+ @PM.add_abcspec
+ def init(self):
+ """
+ Placeholder for module scope initialization
+ """
+
+
+@PM.add_interface
+class Setupable(Interface):
+ @PM.add_abcspec
+ def setup(self):
+ """
+ Placeholder for plugin setup, right after server start.
+ CanMgr.mgr and CanLog.log are initialized by then.
+ """
+ pass
+
+
+@PM.add_interface
+class HasOptions(Interface):
+ @PM.add_abcspec
+ def get_options(self): pass
+
+
+@PM.add_interface
+class HasCommands(Interface):
+ @PM.add_abcspec
+ def register_commands(self): pass
+
+
+@PM.add_interface
+class HasControllers(Interface):
+ @PM.add_abcspec
+ def get_controllers(self): pass
+
+
+@PM.add_interface
+class ConfiguresCherryPy(Interface):
+ @PM.add_abcspec
+ def configure_cherrypy(self, config):
+ pass
+
+
+class FilterRequest(object):
+ @PM.add_interface
+ class BeforeHandler(Interface):
+ @PM.add_abcspec
+ def filter_request_before_handler(self, request): pass
+
+
+@PM.add_interface
+class ConfigNotify(Interface):
+ @PM.add_abcspec
+ def config_notify(self):
+ """
+ This method is called whenever a option of this mgr module has
+ been modified.
+ """
diff --git a/src/pybind/mgr/dashboard/plugins/lru_cache.py b/src/pybind/mgr/dashboard/plugins/lru_cache.py
new file mode 100644
index 00000000..19ad1b85
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/lru_cache.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+"""
+This is a minimal implementation of lru_cache function.
+
+Based on Python 3 functools and backports.functools_lru_cache.
+"""
+from __future__ import absolute_import
+
+from functools import wraps
+from collections import OrderedDict
+from threading import RLock
+
+
+def lru_cache(maxsize=128, typed=False):
+ if typed is not False:
+ raise NotImplementedError("typed caching not supported")
+
+ def decorating_function(function):
+ cache = OrderedDict()
+ stats = [0, 0]
+ rlock = RLock()
+ setattr(
+ function,
+ 'cache_info',
+ lambda:
+ "hits={}, misses={}, maxsize={}, currsize={}".format(
+ stats[0], stats[1], maxsize, len(cache)))
+
+ @wraps(function)
+ def wrapper(*args, **kwargs):
+ key = args + tuple(kwargs.items())
+ with rlock:
+ if key in cache:
+ ret = cache[key]
+ del cache[key]
+ cache[key] = ret
+ stats[0] += 1
+ else:
+ ret = function(*args, **kwargs)
+ if len(cache) == maxsize:
+ cache.popitem(last=False)
+ cache[key] = ret
+ stats[1] += 1
+ return ret
+
+ return wrapper
+ return decorating_function
diff --git a/src/pybind/mgr/dashboard/plugins/pluggy.py b/src/pybind/mgr/dashboard/plugins/pluggy.py
new file mode 100644
index 00000000..7517e6d6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/pluggy.py
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+"""
+CAVEAT:
+This is a minimal implementation of python-pluggy (based on 0.8.0 interface:
+https://github.com/pytest-dev/pluggy/releases/tag/0.8.0).
+
+
+Despite being a widely available Python library, it does not reach all the
+distros and releases currently targeted for Ceph Nautilus:
+- CentOS/RHEL 7.5 [ ]
+- CentOS/RHEL 8 [ ]
+- Debian 8.0 [ ]
+- Debian 9.0 [ ]
+- Ubuntu 14.05 [ ]
+- Ubuntu 16.04 [X]
+
+TODO: Once this becomes available in the above distros, this file should be
+REMOVED, and the fully featured python-pluggy should be used instead.
+"""
+
+
+class HookspecMarker(object):
+ """ Dummy implementation. No spec validation. """
+ def __init__(self, project_name):
+ self.project_name = project_name
+
+ def __call__(self, function, *args, **kwargs):
+ """ No options supported. """
+ if any(args) or any(kwargs):
+ raise NotImplementedError(
+ "This is a minimal implementation of pluggy")
+ return function
+
+
+class HookimplMarker(object):
+ def __init__(self, project_name):
+ self.project_name = project_name
+
+ def __call__(self, function, *args, **kwargs):
+ """ No options supported."""
+ if any(args) or any(kwargs):
+ raise NotImplementedError(
+ "This is a minimal implementation of pluggy")
+ setattr(function, self.project_name + "_impl", {})
+ return function
+
+
+class _HookRelay(object):
+ """
+ Provides the PluginManager.hook.<method_name>() syntax and
+ functionality.
+ """
+ def __init__(self):
+ from collections import defaultdict
+ self._registry = defaultdict(list)
+
+ def __getattr__(self, hook_name):
+ return lambda *args, **kwargs: [
+ hook(*args, **kwargs) for hook in self._registry[hook_name]]
+
+ def _add_hookimpl(self, hook_name, hook_method):
+ self._registry[hook_name].append(hook_method)
+
+
+class PluginManager(object):
+ def __init__(self, project_name):
+ self.project_name = project_name
+ self.__hook = _HookRelay()
+
+ @property
+ def hook(self):
+ return self.__hook
+
+ def parse_hookimpl_opts(self, plugin, name):
+ return getattr(
+ getattr(plugin, name),
+ self.project_name + "_impl",
+ None)
+
+ def add_hookspecs(self, module_or_class):
+ """ Dummy method"""
+ pass
+
+ def register(self, plugin, name=None):
+ for attr in dir(plugin):
+ if self.parse_hookimpl_opts(plugin, attr) is not None:
+ self.hook._add_hookimpl(attr, getattr(plugin, attr))
diff --git a/src/pybind/mgr/dashboard/plugins/plugin.py b/src/pybind/mgr/dashboard/plugins/plugin.py
new file mode 100644
index 00000000..0f52aefb
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/plugin.py
@@ -0,0 +1,33 @@
+from mgr_module import Option, Command
+
+from . import PLUGIN_MANAGER as PM
+from . import interfaces as I # noqa: E741,N812
+
+
+class SimplePlugin(I.CanMgr, I.CanLog, I.HasOptions, I.HasCommands):
+ """
+ Helper class that provides simplified creation of plugins:
+ - Default Mixins/Interfaces: CanMgr, CanLog, HasOptions & HasCommands
+ - Options are defined by OPTIONS class variable, instead from get_options hook
+ - Commands are created with by COMMANDS list of Commands() and handlers
+ (less compact than CLICommand, but allows using method instances)
+ """
+ Option = Option
+ Command = Command
+
+ @PM.add_hook
+ def get_options(self):
+ return self.OPTIONS
+
+ @PM.final
+ def get_option(self, option):
+ return self.mgr.get_module_option(option)
+
+ @PM.final
+ def set_option(self, option, value):
+ self.mgr.set_module_option(option, value)
+
+ @PM.add_hook
+ def register_commands(self):
+ for cmd in self.COMMANDS:
+ cmd.register(instance=self)
diff --git a/src/pybind/mgr/dashboard/plugins/ttl_cache.py b/src/pybind/mgr/dashboard/plugins/ttl_cache.py
new file mode 100644
index 00000000..a0698542
--- /dev/null
+++ b/src/pybind/mgr/dashboard/plugins/ttl_cache.py
@@ -0,0 +1,55 @@
+"""
+This is a minimal implementation of TTL-ed lru_cache function.
+
+Based on Python 3 functools and backports.functools_lru_cache.
+"""
+from __future__ import absolute_import
+
+from functools import wraps
+from collections import OrderedDict
+from threading import RLock
+from time import time
+
+
+def ttl_cache(ttl, maxsize=128, typed=False):
+ if typed is not False:
+ raise NotImplementedError("typed caching not supported")
+
+ def decorating_function(function):
+ cache = OrderedDict()
+ stats = [0, 0, 0]
+ rlock = RLock()
+ setattr(
+ function,
+ 'cache_info',
+ lambda:
+ "hits={}, misses={}, expired={}, maxsize={}, currsize={}".format(
+ stats[0], stats[1], stats[2], maxsize, len(cache)))
+
+ @wraps(function)
+ def wrapper(*args, **kwargs):
+ key = args + tuple(kwargs.items())
+ with rlock:
+ refresh = True
+ if key in cache:
+ (ret, ts) = cache[key]
+ del cache[key]
+ if time() - ts < ttl:
+ refresh = False
+ stats[0] += 1
+ else:
+ stats[2] += 1
+
+ if refresh:
+ ret = function(*args, **kwargs)
+ ts = time()
+ if len(cache) == maxsize:
+ cache.popitem(last=False)
+ stats[1] += 1
+
+ cache[key] = (ret, ts)
+
+ return ret
+
+ return wrapper
+ return decorating_function
diff --git a/src/pybind/mgr/dashboard/requirements-py27.txt b/src/pybind/mgr/dashboard/requirements-py27.txt
new file mode 100644
index 00000000..d8fb6f6a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/requirements-py27.txt
@@ -0,0 +1,3 @@
+astroid==1.6.1
+pylint==1.8.2
+python-saml==2.4.2
diff --git a/src/pybind/mgr/dashboard/requirements-py3.txt b/src/pybind/mgr/dashboard/requirements-py3.txt
new file mode 100644
index 00000000..364ce283
--- /dev/null
+++ b/src/pybind/mgr/dashboard/requirements-py3.txt
@@ -0,0 +1,3 @@
+astroid==2.1.0
+pylint==2.2.2
+python3-saml==1.4.1
diff --git a/src/pybind/mgr/dashboard/requirements.txt b/src/pybind/mgr/dashboard/requirements.txt
new file mode 100644
index 00000000..9a7c71f1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/requirements.txt
@@ -0,0 +1,36 @@
+attrs==17.4.0
+backports.functools-lru-cache==1.4
+bcrypt==3.1.4
+cheroot==6.0.0
+CherryPy==13.1.0
+configparser==3.5.0
+coverage==4.5.2
+enum34; python_version<'3.4'
+funcsigs==1.0.2
+isort==4.2.15
+lazy-object-proxy==1.3.1
+mccabe==0.6.1
+mock==2.0.0
+more-itertools==4.1.0
+pbr==3.1.1
+pluggy==0.6.0
+portend==2.2
+py==1.5.2
+pycodestyle==2.4.0
+pycparser==2.18
+PyJWT
+pyopenssl
+pytest==3.3.2
+pytest-cov==2.5.1
+pytest-faulthandler==1.0.1
+pytz==2017.3
+requests==2.20.0
+Routes==2.4.1
+singledispatch==3.4.0.3
+six==1.14.0
+tempora==1.10
+tox==2.9.1
+virtualenv==15.1.0
+werkzeug==0.14.1
+wrapt==1.10.11
+pyfakefs
diff --git a/src/pybind/mgr/dashboard/rest_client.py b/src/pybind/mgr/dashboard/rest_client.py
new file mode 100644
index 00000000..b287086f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/rest_client.py
@@ -0,0 +1,531 @@
+# -*- coding: utf-8 -*-
+"""
+ * Copyright (c) 2017 SUSE LLC
+ *
+ * openATTIC is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+"""
+from __future__ import absolute_import
+
+from .settings import Settings
+from .tools import build_url
+import inspect
+import re
+import requests
+from requests.exceptions import ConnectionError, InvalidURL, Timeout
+from . import logger
+
+try:
+ from requests.packages.urllib3.exceptions import SSLError
+except ImportError:
+ from urllib3.exceptions import SSLError
+
+
+class TimeoutRequestsSession(requests.Session):
+ """
+ Set timeout argument for all requests if this is not already done.
+ """
+ def request(self, *args, **kwargs):
+ if ((args[8] if len(args) > 8 else None) is None) \
+ and kwargs.get('timeout') is None:
+ if Settings.REST_REQUESTS_TIMEOUT > 0:
+ kwargs['timeout'] = Settings.REST_REQUESTS_TIMEOUT
+ return super(TimeoutRequestsSession, self).request(*args, **kwargs)
+
+
+class RequestException(Exception):
+ def __init__(self,
+ message,
+ status_code=None,
+ content=None,
+ conn_errno=None,
+ conn_strerror=None):
+ super(RequestException, self).__init__(message)
+ self.status_code = status_code
+ self.content = content
+ self.conn_errno = conn_errno
+ self.conn_strerror = conn_strerror
+
+
+class BadResponseFormatException(RequestException):
+ def __init__(self, message):
+ super(BadResponseFormatException, self).__init__(
+ "Bad response format" if message is None else message, None)
+
+
+class _ResponseValidator(object):
+ """Simple JSON schema validator
+
+ This class implements a very simple validator for the JSON formatted
+ messages received by request responses from a RestClient instance.
+
+ The validator validates the JSON response against a "structure" string that
+ specifies the structure that the JSON response must comply. The validation
+ procedure raises a BadResponseFormatException in case of a validation
+ failure.
+
+ The structure syntax is given by the following grammar:
+
+ Structure ::= Level
+ Level ::= Path | Path '&' Level
+ Path ::= Step | Step '>'+ Path
+ Step ::= Key | '?' Key | '*' | '(' Level ')'
+ Key ::= <string> | Array+
+ Array ::= '[' <int> ']' | '[' '*' ']' | '[' '+' ']'
+
+ The symbols enclosed in ' ' are tokens of the language, and the + symbol
+ denotes repetition of of the preceding token at least once.
+
+ Examples of usage:
+
+ Example 1:
+ Validator args:
+ structure = "return > *"
+ response = { 'return': { ... } }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary and its value is also a dictionary.
+
+ Example 2:
+ Validator args:
+ structure = "[*]"
+ response = [...]
+
+ In the above example the structure will validate against any response
+ that is an array of any size.
+
+ Example 3:
+ Validator args:
+ structure = "return[*]"
+ response = { 'return': [....] }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary and its value is an array.
+
+ Example 4:
+ Validator args:
+ structure = "return[0] > token"
+ response = { 'return': [ { 'token': .... } ] }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary and its value is an array, and the first element of the
+ array is a dictionary that contains the key 'token'.
+
+ Example 5:
+ Validator args:
+ structure = "return[0][*] > key1"
+ response = { 'return': [ [ { 'key1': ... } ], ...] }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary where its value is an array, and the first value of this
+ array is also an array where all it's values must be a dictionary
+ containing a key named "key1".
+
+ Example 6:
+ Validator args:
+ structure = "return > (key1[*] & key2 & ?key3 > subkey)"
+ response = { 'return': { 'key1': [...], 'key2: .... } ] }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary and its value is a dictionary that must contain a key named
+ "key1" that is an array, a key named "key2", and optionally a key named
+ "key3" that is a dictionary that contains a key named "subkey".
+
+ Example 7:
+ Validator args:
+ structure = "return >> roles[*]"
+ response = { 'return': { 'key1': { 'roles': [...] }, 'key2': { 'roles': [...] } } }
+
+ In the above example the structure will validate against any response
+ that contains a key named "return" in the root of the response
+ dictionary, and its value is a dictionary that for any key present in
+ the dictionary their value is also a dictionary that must contain a key
+ named 'roles' that is an array. Please note that you can use any
+ number of successive '>' to denote the level in the JSON tree that you
+ want to match next step in the path.
+
+ """
+
+ @staticmethod
+ def validate(structure, response):
+ if structure is None:
+ return
+
+ _ResponseValidator._validate_level(structure, response)
+
+ @staticmethod
+ def _validate_level(level, resp):
+ if not isinstance(resp, dict) and not isinstance(resp, list):
+ raise BadResponseFormatException(
+ "{} is neither a dict nor a list".format(resp))
+
+ paths = _ResponseValidator._parse_level_paths(level)
+ for path in paths:
+ path_sep = path.find('>')
+ if path_sep != -1:
+ level_next = path[path_sep + 1:].strip()
+ else:
+ path_sep = len(path)
+ level_next = None
+ key = path[:path_sep].strip()
+
+ if key == '*':
+ continue
+ elif key == '': # check all keys
+ for k in resp.keys():
+ _ResponseValidator._validate_key(k, level_next, resp)
+ else:
+ _ResponseValidator._validate_key(key, level_next, resp)
+
+ @staticmethod
+ def _validate_array(array_seq, level_next, resp):
+ if array_seq:
+ if not isinstance(resp, list):
+ raise BadResponseFormatException(
+ "{} is not an array".format(resp))
+ if array_seq[0].isdigit():
+ idx = int(array_seq[0])
+ if len(resp) <= idx:
+ raise BadResponseFormatException(
+ "length of array {} is lower than the index {}".format(
+ resp, idx))
+ _ResponseValidator._validate_array(array_seq[1:], level_next,
+ resp[idx])
+ elif array_seq[0] == '*':
+ for r in resp:
+ _ResponseValidator._validate_array(array_seq[1:],
+ level_next, r)
+ elif array_seq[0] == '+':
+ if len(resp) < 1:
+ raise BadResponseFormatException(
+ "array should not be empty")
+ for r in resp:
+ _ResponseValidator._validate_array(array_seq[1:],
+ level_next, r)
+ else:
+ raise Exception(
+ "Response structure is invalid: only <int> | '*' are "
+ "allowed as array index arguments")
+ else:
+ if level_next:
+ _ResponseValidator._validate_level(level_next, resp)
+
+ @staticmethod
+ def _validate_key(key, level_next, resp):
+ array_access = [a.strip() for a in key.split("[")]
+ key = array_access[0]
+ if key:
+ optional = key[0] == '?'
+ if optional:
+ key = key[1:]
+ if key not in resp:
+ if optional:
+ return
+ raise BadResponseFormatException(
+ "key {} is not in dict {}".format(key, resp))
+ resp_next = resp[key]
+ else:
+ resp_next = resp
+ if len(array_access) > 1:
+ _ResponseValidator._validate_array(
+ [a[0:-1] for a in array_access[1:]], level_next, resp_next)
+ else:
+ if level_next:
+ _ResponseValidator._validate_level(level_next, resp_next)
+
+ @staticmethod
+ def _parse_level_paths(level):
+ level = level.strip()
+ if level[0] == '(':
+ level = level[1:]
+ if level[-1] == ')':
+ level = level[:-1]
+
+ paths = []
+ lp = 0
+ nested = 0
+ for i, c in enumerate(level):
+ if c == '&' and nested == 0:
+ paths.append(level[lp:i].strip())
+ lp = i + 1
+ elif c == '(':
+ nested += 1
+ elif c == ')':
+ nested -= 1
+ paths.append(level[lp:].strip())
+ return paths
+
+
+class _Request(object):
+ def __init__(self, method, path, path_params, rest_client, resp_structure):
+ self.method = method
+ self.path = path
+ self.path_params = path_params
+ self.rest_client = rest_client
+ self.resp_structure = resp_structure
+
+ def _gen_path(self):
+ new_path = self.path
+ matches = re.finditer(r'\{(\w+?)\}', self.path)
+ for match in matches:
+ if match:
+ param_key = match.group(1)
+ if param_key in self.path_params:
+ new_path = new_path.replace(
+ match.group(0), self.path_params[param_key])
+ else:
+ raise RequestException(
+ 'Invalid path. Param "{}" was not specified'
+ .format(param_key), None)
+ return new_path
+
+ def __call__(self,
+ req_data=None,
+ method=None,
+ params=None,
+ data=None,
+ raw_content=False):
+ method = method if method else self.method
+ if not method:
+ raise Exception('No HTTP request method specified')
+ if req_data:
+ if method == 'get':
+ if params:
+ raise Exception('Ambiguous source of GET params')
+ params = req_data
+ else:
+ if data:
+ raise Exception('Ambiguous source of {} data'.format(
+ method.upper()))
+ data = req_data
+ resp = self.rest_client.do_request(method, self._gen_path(), params,
+ data, raw_content)
+ if raw_content and self.resp_structure:
+ raise Exception("Cannot validate response in raw format")
+ _ResponseValidator.validate(self.resp_structure, resp)
+ return resp
+
+
+class RestClient(object):
+ def __init__(self, host, port, client_name=None, ssl=False, auth=None, ssl_verify=True):
+ super(RestClient, self).__init__()
+ self.client_name = client_name if client_name else ''
+ self.host = host
+ self.port = port
+ self.base_url = build_url(
+ scheme='https' if ssl else 'http', host=host, port=port)
+ logger.debug("REST service base URL: %s", self.base_url)
+ self.headers = {'Accept': 'application/json'}
+ self.auth = auth
+ self.session = TimeoutRequestsSession()
+ self.session.verify = ssl_verify
+
+ def _login(self, request=None):
+ pass
+
+ def _is_logged_in(self):
+ pass
+
+ def _reset_login(self):
+ pass
+
+ def is_service_online(self, request=None):
+ pass
+
+ @staticmethod
+ def requires_login(func):
+ def func_wrapper(self, *args, **kwargs):
+ retries = 2
+ while True:
+ try:
+ if not self._is_logged_in():
+ self._login()
+ resp = func(self, *args, **kwargs)
+ return resp
+ except RequestException as e:
+ if isinstance(e, BadResponseFormatException):
+ raise e
+ retries -= 1
+ if e.status_code not in [401, 403] or retries == 0:
+ raise e
+ self._reset_login()
+
+ return func_wrapper
+
+ def do_request(self,
+ method,
+ path,
+ params=None,
+ data=None,
+ raw_content=False):
+ url = '{}{}'.format(self.base_url, path)
+ logger.debug('%s REST API %s req: %s data: %s', self.client_name,
+ method.upper(), path, data)
+ try:
+ if method.lower() == 'get':
+ resp = self.session.get(
+ url, headers=self.headers, params=params, auth=self.auth)
+ elif method.lower() == 'post':
+ resp = self.session.post(
+ url,
+ headers=self.headers,
+ params=params,
+ data=data,
+ auth=self.auth)
+ elif method.lower() == 'put':
+ resp = self.session.put(
+ url,
+ headers=self.headers,
+ params=params,
+ data=data,
+ auth=self.auth)
+ elif method.lower() == 'delete':
+ resp = self.session.delete(
+ url,
+ headers=self.headers,
+ params=params,
+ data=data,
+ auth=self.auth)
+ else:
+ raise RequestException('Method "{}" not supported'.format(
+ method.upper()), None)
+ if resp.ok:
+ logger.debug("%s REST API %s res status: %s content: %s",
+ self.client_name, method.upper(),
+ resp.status_code, resp.text)
+ if raw_content:
+ return resp.content
+ try:
+ return resp.json() if resp.text else None
+ except ValueError:
+ logger.error(
+ "%s REST API failed %s req while decoding JSON "
+ "response : %s",
+ self.client_name, method.upper(), resp.text)
+ raise RequestException(
+ "{} REST API failed request while decoding JSON "
+ "response: {}".format(self.client_name, resp.text),
+ resp.status_code, resp.text)
+ else:
+ logger.error(
+ "%s REST API failed %s req status: %s", self.client_name,
+ method.upper(), resp.status_code)
+ from pprint import pprint as pp
+ from pprint import pformat as pf
+
+ raise RequestException(
+ "{} REST API failed request with status code {}\n"
+ "{}" # TODO remove
+ .format(self.client_name, resp.status_code, pf(
+ resp.content)),
+ resp.status_code,
+ resp.content)
+ except ConnectionError as ex:
+ if ex.args:
+ if isinstance(ex.args[0], SSLError):
+ errno = "n/a"
+ strerror = "SSL error. Probably trying to access a non " \
+ "SSL connection."
+ logger.error("%s REST API failed %s, SSL error.",
+ self.client_name, method.upper())
+ else:
+ try:
+ match = re.match(r'.*: \[Errno (-?\d+)\] (.+)',
+ ex.args[0].reason.args[0])
+ except AttributeError:
+ match = False
+ if match:
+ errno = match.group(1)
+ strerror = match.group(2)
+ logger.error(
+ "%s REST API failed %s, connection error: "
+ "[errno: %s] %s",
+ self.client_name, method.upper(), errno, strerror)
+ else:
+ errno = "n/a"
+ strerror = "n/a"
+ logger.error(
+ "%s REST API failed %s, connection error.",
+ self.client_name, method.upper())
+ else:
+ errno = "n/a"
+ strerror = "n/a"
+ logger.error("%s REST API failed %s, connection error.",
+ self.client_name, method.upper())
+
+ if errno != "n/a":
+ ex_msg = (
+ "{} REST API cannot be reached: {} [errno {}]. "
+ "Please check your configuration and that the API endpoint"
+ " is accessible"
+ .format(self.client_name, strerror, errno))
+ else:
+ ex_msg = (
+ "{} REST API cannot be reached. Please check "
+ "your configuration and that the API endpoint is"
+ " accessible"
+ .format(self.client_name))
+ raise RequestException(
+ ex_msg, conn_errno=errno, conn_strerror=strerror)
+ except InvalidURL as ex:
+ logger.exception("%s REST API failed %s: %s", self.client_name,
+ method.upper(), str(ex))
+ raise RequestException(str(ex))
+ except Timeout as ex:
+ msg = "{} REST API {} timed out after {} seconds (url={}).".format(
+ self.client_name, ex.request.method, Settings.REST_REQUESTS_TIMEOUT,
+ ex.request.url)
+ logger.exception(msg)
+ raise RequestException(msg)
+
+ @staticmethod
+ def api(path, **api_kwargs):
+ def call_decorator(func):
+ def func_wrapper(self, *args, **kwargs):
+ method = api_kwargs.get('method', None)
+ resp_structure = api_kwargs.get('resp_structure', None)
+ args_name = inspect.getargspec(func).args
+ args_dict = dict(zip(args_name[1:], args))
+ for key, val in kwargs:
+ args_dict[key] = val
+ return func(
+ self,
+ *args,
+ request=_Request(method, path, args_dict, self,
+ resp_structure),
+ **kwargs)
+
+ return func_wrapper
+
+ return call_decorator
+
+ @staticmethod
+ def api_get(path, resp_structure=None):
+ return RestClient.api(
+ path, method='get', resp_structure=resp_structure)
+
+ @staticmethod
+ def api_post(path, resp_structure=None):
+ return RestClient.api(
+ path, method='post', resp_structure=resp_structure)
+
+ @staticmethod
+ def api_put(path, resp_structure=None):
+ return RestClient.api(
+ path, method='put', resp_structure=resp_structure)
+
+ @staticmethod
+ def api_delete(path, resp_structure=None):
+ return RestClient.api(
+ path, method='delete', resp_structure=resp_structure)
diff --git a/src/pybind/mgr/dashboard/run-backend-api-request.sh b/src/pybind/mgr/dashboard/run-backend-api-request.sh
new file mode 100755
index 00000000..5c4c1559
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-backend-api-request.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+CURR_DIR=`pwd`
+cd ../../../../build
+API_URL=`./bin/ceph mgr services 2>/dev/null | jq .dashboard | sed -e 's/"//g' -e 's!/$!!g'`
+if [ "$API_URL" = "null" ]; then
+ echo "Couldn't retrieve API URL, exiting..." >&2
+ exit 1
+fi
+cd $CURR_DIR
+
+TOKEN=`curl --insecure -s -H "Content-Type: application/json" -X POST \
+ -d '{"username":"admin","password":"admin"}' $API_URL/api/auth \
+ | jq .token | sed -e 's/"//g'`
+
+echo "METHOD: $1"
+echo "URL: ${API_URL}${2}"
+echo "DATA: $3"
+echo ""
+
+curl --insecure -s -b /tmp/cd-cookie.txt -H "Authorization: Bearer $TOKEN " \
+ -H "Content-Type: application/json" -X $1 -d "$3" ${API_URL}$2 | jq
+
diff --git a/src/pybind/mgr/dashboard/run-backend-api-tests.sh b/src/pybind/mgr/dashboard/run-backend-api-tests.sh
new file mode 100755
index 00000000..66831399
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-backend-api-tests.sh
@@ -0,0 +1,166 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+if [[ "$1" = "-h" || "$1" = "--help" ]]; then
+ echo "Usage (run from ./):"
+ echo -e "\t./run-backend-api-tests.sh"
+ echo -e "\t./run-backend-api-tests.sh [tests]..."
+ echo
+ echo "Example:"
+ echo -e "\t./run-backend-api-tests.sh tasks.mgr.dashboard.test_pool.DashboardTest"
+ echo
+ echo "Or source this script. This allows to re-run tests faster:"
+ echo -e "\tsource run-backend-api-tests.sh"
+ echo -e "\trun_teuthology_tests [tests]..."
+ echo -e "\tcleanup_teuthology"
+ echo
+
+ exit 0
+fi
+
+get_cmake_variable() {
+ local variable=$1
+ grep "$variable" CMakeCache.txt | cut -d "=" -f 2
+}
+
+get_build_py_version() {
+ CURR_DIR=`pwd`
+ BUILD_DIR="$CURR_DIR/../../../../build"
+ cd $BUILD_DIR
+
+ CEPH_MGR_PY_VERSION_MAJOR=$(get_cmake_variable MGR_PYTHON_VERSION | cut -d '.' -f1)
+ if [ -n "$CEPH_MGR_PY_VERSION_MAJOR" ]; then
+ CEPH_PY_VERSION_MAJOR=${CEPH_MGR_PY_VERSION_MAJOR}
+ else
+ if [ $(get_cmake_variable WITH_PYTHON2) = ON ]; then
+ CEPH_PY_VERSION_MAJOR=2
+ else
+ CEPH_PY_VERSION_MAJOR=3
+ fi
+ fi
+}
+
+setup_teuthology() {
+ TEMP_DIR=`mktemp -d`
+ cd $TEMP_DIR
+ virtualenv --python=${TEUTHOLOGY_PYTHON_BIN:-/usr/bin/python3} venv
+ source venv/bin/activate
+ pip install 'setuptools >= 12'
+ pip install git+https://github.com/ceph/teuthology#egg=teuthology[test]
+ pushd $CURR_DIR
+ pip install -r requirements.txt -c constraints.txt
+ popd
+
+ deactivate
+}
+
+setup_coverage() {
+ # In CI environment we cannot install coverage in system, so we install it in a dedicated venv
+ # so only coverage is available when adding this path.
+ cd $TEMP_DIR
+ virtualenv --python=${TEUTHOLOGY_PYTHON_BIN:-/usr/bin/python} coverage-venv
+ source coverage-venv/bin/activate
+ cd $CURR_DIR
+ pip install coverage==4.5.2
+ COVERAGE_PATH=$(python -c "import sysconfig; print(sysconfig.get_paths()['platlib'])")
+ deactivate
+}
+
+on_tests_error() {
+ if [[ -n "$JENKINS_HOME" ]]; then
+ CEPH_OUT_DIR=${CEPH_OUT_DIR:-"$BUILD_DIR"/out}
+ MGR_LOG_FILES=$(find "$CEPH_OUT_DIR" -iname "mgr.*.log" | tr '\n' ' ')
+ MGR_LOG_FILE_LAST_LINES=1000
+ for mgr_log_file in ${MGR_LOG_FILES[@]}; do
+ printf "\n\nDisplaying last ${MGR_LOG_FILE_LAST_LINES} lines of: $mgr_log_file\n\n"
+ tail -n ${MGR_LOG_FILE_LAST_LINES} $mgr_log_file
+ printf "\n\nEnd of: $mgr_log_file\n\n"
+ done
+ printf "\n\nTEST FAILED.\n\n"
+ fi
+}
+
+run_teuthology_tests() {
+ trap on_tests_error ERR
+
+ cd "$BUILD_DIR"
+ find ../src/pybind/mgr/dashboard/ -name '*.pyc' -exec rm -f {} \;
+
+ OPTIONS=''
+ TEST_CASES=''
+ if [[ "$@" == '' || "$@" == '--create-cluster-only' ]]; then
+ TEST_CASES=`for i in \`ls $BUILD_DIR/../qa/tasks/mgr/dashboard/test_*\`; do F=$(basename $i); M="${F%.*}"; echo -n " tasks.mgr.dashboard.$M"; done`
+ # Mgr selftest module tests have to be run at the end as they stress the mgr daemon.
+ TEST_CASES="tasks.mgr.test_dashboard $TEST_CASES tasks.mgr.test_module_selftest"
+ if [[ "$@" == '--create-cluster-only' ]]; then
+ OPTIONS="$@"
+ fi
+ else
+ for t in "$@"; do
+ TEST_CASES="$TEST_CASES $t"
+ done
+ fi
+
+ export PATH=$BUILD_DIR/bin:$PATH
+ source $TEMP_DIR/venv/bin/activate # Run after setting PATH as it does the last PATH export.
+ export LD_LIBRARY_PATH=$BUILD_DIR/lib/cython_modules/lib.${CEPH_PY_VERSION_MAJOR}/:$BUILD_DIR/lib
+ local source_dir=$(dirname "$BUILD_DIR")
+ local pybind_dir=$source_dir/src/pybind
+ local python_common_dir=$source_dir/src/python-common
+ # In CI environment we set python paths inside build (where you find the required frontend build: "dist" dir).
+ if [[ -n "$JENKINS_HOME" ]]; then
+ export PYBIND=$BUILD_DIR/src/pybind
+ pybind_dir=$PYBIND
+ fi
+ export PYTHONPATH=$source_dir/qa:$BUILD_DIR/lib/cython_modules/lib.${CEPH_PY_VERSION_MAJOR}/:$pybind_dir:$python_common_dir:${COVERAGE_PATH}
+ export RGW=${RGW:-1}
+
+ export COVERAGE_ENABLED=true
+ export COVERAGE_FILE=.coverage.mgr.dashboard
+ find . -iname "*${COVERAGE_FILE}*" -type f -delete
+
+ python ../qa/tasks/vstart_runner.py --ignore-missing-binaries --no-verbose $OPTIONS $TEST_CASES
+
+ deactivate
+ cd $CURR_DIR
+}
+
+cleanup_teuthology() {
+ cd "$BUILD_DIR"
+ killall ceph-mgr
+ sleep 10
+ if [[ "$COVERAGE_ENABLED" == 'true' ]]; then
+ source $TEMP_DIR/coverage-venv/bin/activate
+ (coverage combine && coverage report) || true
+ deactivate
+ fi
+ ../src/stop.sh
+ sleep 5
+
+ cd $CURR_DIR
+ rm -rf $TEMP_DIR
+
+ unset TEMP_DIR
+ unset CURR_DIR
+ unset BUILD_DIR
+ unset COVERAGE_PATH
+ unset get_build_py_version
+ unset setup_teuthology
+ unset setup_coverage
+ unset on_tests_error
+ unset run_teuthology_tests
+ unset cleanup_teuthology
+}
+
+get_build_py_version
+setup_teuthology
+setup_coverage
+run_teuthology_tests --create-cluster-only
+
+# End sourced section. Do not exit shell when the script has been sourced.
+set +e
+return 2>/dev/null || set -eo pipefail
+
+run_teuthology_tests "$@"
+cleanup_teuthology
diff --git a/src/pybind/mgr/dashboard/run-backend-rook-api-request.sh b/src/pybind/mgr/dashboard/run-backend-rook-api-request.sh
new file mode 100755
index 00000000..ef221dcf
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-backend-rook-api-request.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+#
+# Query k8s to determine where the mgr is running and how to reach the
+# dashboard from the local machine. This assumes that the dashboard is being
+# exposed via a nodePort service
+CURR_DIR=`pwd`
+K8S_NAMESPACE='rook-ceph'
+
+HOST=$(kubectl get pods -n $K8S_NAMESPACE -l "app=rook-ceph-mgr" -o json | jq .items[0].spec.nodeName | sed s/\"//g)
+if [ "$HOST" = "minikube" ]; then
+ HOST=$(minikube ip)
+fi
+PORT=$(kubectl get service -n $K8S_NAMESPACE rook-ceph-mgr-dashboard -o yaml | grep nodePort: | awk '{print $2}')
+API_URL="https://${HOST}:${PORT}"
+
+#
+# Rook automagically sets up an "admin" account with a random PW and stuffs
+# that into a k8s secret. This fetches it.
+#
+PASSWD=$(kubectl -n $K8S_NAMESPACE get secret rook-ceph-dashboard-password -o yaml | grep "password:" | awk '{print $2}' | base64 --decode)
+
+if [ "$API_URL" = "null" ]; then
+ echo "Couldn't retrieve API URL, exiting..." >&2
+ exit 1
+fi
+cd $CURR_DIR
+
+TOKEN=`curl --insecure -s -H "Content-Type: application/json" -X POST \
+ -d "{\"username\":\"admin\",\"password\":\"${PASSWD}\"}" $API_URL/api/auth \
+ | jq .token | sed -e 's/"//g'`
+
+echo "METHOD: $1"
+echo "URL: ${API_URL}${2}"
+echo "DATA: $3"
+echo ""
+
+curl --insecure -s -b /tmp/cd-cookie.txt -H "Authorization: Bearer $TOKEN " \
+ -H "Content-Type: application/json" -X $1 -d "$3" ${API_URL}$2 | jq
+
diff --git a/src/pybind/mgr/dashboard/run-frontend-e2e-tests.sh b/src/pybind/mgr/dashboard/run-frontend-e2e-tests.sh
new file mode 100755
index 00000000..280debdc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-frontend-e2e-tests.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+set -e
+
+stop() {
+ if [ "$REMOTE" == "false" ]; then
+ cd $BUILD_DIR
+ ../src/stop.sh
+ fi
+ exit $1
+}
+
+BASE_URL=''
+DEVICE=''
+REMOTE='false'
+
+while getopts 'd:r:' flag; do
+ case "${flag}" in
+ d) DEVICE=$OPTARG;;
+ r) REMOTE='true'
+ # jq is expecting a string literal, otherwise it will fail on the url ':'.
+ # We need to ensure that jq gets a json string for assignment; we achieve
+ # that by introducing literal double quotes (i.e., '"').
+ BASE_URL='"'$OPTARG'"';;
+ esac
+done
+
+if [ "$DEVICE" == "" ]; then
+ if [ -x "$(command -v google-chrome)" ] || [ -x "$(command -v google-chrome-stable)" ]; then
+ DEVICE="chrome"
+ elif [ -x "$(command -v docker)" ]; then
+ DEVICE="docker"
+ else
+ echo "ERROR: Chrome and Docker not found. You need to install one of \
+them to run the e2e frontend tests."
+ stop 1
+ fi
+fi
+
+DASH_DIR=`pwd`
+
+cd ../../../../build
+BUILD_DIR=`pwd`
+
+if [ "$BASE_URL" == "" ]; then
+ MGR=2 RGW=1 ../src/vstart.sh -n -d
+ sleep 10
+
+ # Create an Object Gateway User
+ ./bin/radosgw-admin user create --uid=dev --display-name=Developer --system
+ # Set the user-id
+ ./bin/ceph dashboard set-rgw-api-user-id dev
+ # Obtain and set access and secret key for the previously created user
+ RGW_ACCESS_KEY_FILE="/tmp/rgw-user-access-key.txt"
+ printf "$(./bin/radosgw-admin user info --uid=dev | jq -r .keys[0].access_key)" > "${RGW_ACCESS_KEY_FILE}"
+ ./bin/ceph dashboard set-rgw-api-access-key -i "${RGW_ACCESS_KEY_FILE}"
+ RGW_SECRET_KEY_FILE="/tmp/rgw-user-secret-key.txt"
+ printf "$(./bin/radosgw-admin user info --uid=dev | jq -r .keys[0].secret_key)" > "${RGW_SECRET_KEY_FILE}"
+ ./bin/ceph dashboard set-rgw-api-secret-key -i "${RGW_SECRET_KEY_FILE}"
+ # Set SSL verify to False
+ ./bin/ceph dashboard set-rgw-api-ssl-verify False
+
+ BASE_URL=`./bin/ceph mgr services | jq .dashboard`
+fi
+
+cd $DASH_DIR/frontend
+jq .[].target=$BASE_URL proxy.conf.json.sample > proxy.conf.json
+
+[ -z $(command -v npm) ] && . $BUILD_DIR/src/pybind/mgr/dashboard/node-env/bin/activate
+npm ci
+
+if [ $DEVICE == "chrome" ]; then
+ npm run e2e -- --dev-server-target --baseUrl=$(echo $BASE_URL | tr -d '"') || stop 1
+ stop 0
+elif [ $DEVICE == "docker" ]; then
+ failed=0
+ docker run -d -v $(pwd):/workdir --net=host --name angular-e2e-container rogargon/angular-e2e || failed=1
+ docker exec angular-e2e-container npm run e2e || failed=1
+ docker stop angular-e2e-container
+ docker rm angular-e2e-container
+ stop $failed
+else
+ echo "ERROR: Device not recognized. Valid devices are 'chrome' and 'docker'."
+ stop 1
+fi
diff --git a/src/pybind/mgr/dashboard/run-frontend-unittests.sh b/src/pybind/mgr/dashboard/run-frontend-unittests.sh
new file mode 100755
index 00000000..dd8bac59
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-frontend-unittests.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+failed=false
+: ${CEPH_ROOT:=$PWD/../../../../}
+cd $CEPH_ROOT/src/pybind/mgr/dashboard/frontend
+if [ `uname` != "FreeBSD" ]; then
+ . $CEPH_ROOT/build/src/pybind/mgr/dashboard/node-env/bin/activate
+fi
+
+# Build
+npm run build -- --prod --progress=false || failed=true
+
+# Unit Tests
+config='src/unit-test-configuration.ts'
+if [ -e $config ]; then
+ mv $config ${config}_old
+fi
+cp ${config}.sample $config
+
+npm run test:ci || failed=true
+
+rm $config
+if [ -e ${config}_old ]; then
+ mv ${config}_old $config
+fi
+
+# Linting
+npm run lint --silent
+if [ $? -gt 0 ]; then
+ failed=true
+ echo -e "\nTry running 'npm run fix' to fix some linting errors. \
+Some errors might need a manual fix."
+fi
+
+# I18N
+npm run i18n:extract
+if [ $? -gt 0 ]; then
+ failed=true
+ echo -e "\nTranslations extraction has failed."
+else
+ i18n_lint=`awk '/<source> |<source>$| <\/source>/,/<\/context-group>/ {printf "%-4s ", NR; print}' src/locale/messages.xlf`
+ if [ "$i18n_lint" ]; then
+ echo -e "The following source translations in 'messages.xlf' need to be \
+ fixed, please check the I18N suggestions in 'HACKING.rst':\n"
+ echo "${i18n_lint}"
+ failed=true
+ fi
+fi
+
+if [ `uname` != "FreeBSD" ]; then
+ deactivate
+fi
+
+if [ "$failed" = "true" ]; then
+ exit 1
+fi
diff --git a/src/pybind/mgr/dashboard/run-tox.sh b/src/pybind/mgr/dashboard/run-tox.sh
new file mode 100755
index 00000000..8086bb4e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/run-tox.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+function dump_envvars {
+ echo "WITH_PYTHON2: ->$WITH_PYTHON2<-"
+ echo "WITH_PYTHON3: ->$WITH_PYTHON3<-"
+ echo "TOX_PATH: ->$TOX_PATH<-"
+ echo "ENV_LIST: ->$ENV_LIST<-"
+}
+
+# run from ./ or from ../
+: ${CEPH_BUILD_DIR:=$PWD/.tox}
+: ${MGR_DASHBOARD_VIRTUALENV:=$CEPH_BUILD_DIR/mgr-dashboard-virtualenv}
+: ${WITH_PYTHON2:=ON}
+: ${WITH_PYTHON3:=3}
+test -d dashboard && cd dashboard
+
+if [ -e tox.ini ]; then
+ TOX_PATH=$(readlink -f tox.ini)
+else
+ TOX_PATH=$(readlink -f $(dirname $0)/tox.ini)
+fi
+
+# tox.ini will take care of this.
+unset PYTHONPATH
+export CEPH_BUILD_DIR=$CEPH_BUILD_DIR
+
+source ${MGR_DASHBOARD_VIRTUALENV}/bin/activate
+
+if [ "$WITH_PYTHON2" = "ON" ]; then
+ if [[ -n "$@" ]]; then
+ ENV_LIST+="py27-run,"
+ else
+ ENV_LIST+="py27-cov,py27-lint,py27-check,"
+ fi
+fi
+# WITH_PYTHON3 might be set to "ON" or to the python3 RPM version number
+# prevailing on the system - e.g. "3", "36"
+if [[ "$WITH_PYTHON3" =~ (^3|^ON) ]]; then
+ if [[ -n "$@" ]]; then
+ ENV_LIST+="py3-run,"
+ else
+ ENV_LIST+="py3-cov,py3-lint,py3-check,"
+ fi
+fi
+# use bash string manipulation to strip off any trailing comma
+ENV_LIST=${ENV_LIST%,}
+
+tox -c "${TOX_PATH}" -e "${ENV_LIST}" "$@"
+TOX_STATUS="$?"
+test "$TOX_STATUS" -ne "0" && dump_envvars
+exit $TOX_STATUS
diff --git a/src/pybind/mgr/dashboard/security.py b/src/pybind/mgr/dashboard/security.py
new file mode 100644
index 00000000..cbeda6da
--- /dev/null
+++ b/src/pybind/mgr/dashboard/security.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import inspect
+
+
+class Scope(object):
+ """
+ List of Dashboard Security Scopes.
+ If you need another security scope, please add it here.
+ """
+
+ HOSTS = "hosts"
+ CONFIG_OPT = "config-opt"
+ POOL = "pool"
+ OSD = "osd"
+ MONITOR = "monitor"
+ RBD_IMAGE = "rbd-image"
+ ISCSI = "iscsi"
+ RBD_MIRRORING = "rbd-mirroring"
+ RGW = "rgw"
+ CEPHFS = "cephfs"
+ MANAGER = "manager"
+ LOG = "log"
+ GRAFANA = "grafana"
+ PROMETHEUS = "prometheus"
+ USER = "user"
+ DASHBOARD_SETTINGS = "dashboard-settings"
+ NFS_GANESHA = "nfs-ganesha"
+
+ @classmethod
+ def all_scopes(cls):
+ return [val for scope, val in
+ inspect.getmembers(cls,
+ lambda memb: not inspect.isroutine(memb))
+ if not scope.startswith('_')]
+
+ @classmethod
+ def valid_scope(cls, scope_name):
+ return scope_name in cls.all_scopes()
+
+
+class Permission(object):
+ """
+ Scope permissions types
+ """
+ READ = "read"
+ CREATE = "create"
+ UPDATE = "update"
+ DELETE = "delete"
+
+ @classmethod
+ def all_permissions(cls):
+ return [val for perm, val in
+ inspect.getmembers(cls,
+ lambda memb: not inspect.isroutine(memb))
+ if not perm.startswith('_')]
+
+ @classmethod
+ def valid_permission(cls, perm_name):
+ return perm_name in cls.all_permissions()
diff --git a/src/pybind/mgr/dashboard/services/__init__.py b/src/pybind/mgr/dashboard/services/__init__.py
new file mode 100644
index 00000000..139759b6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
diff --git a/src/pybind/mgr/dashboard/services/access_control.py b/src/pybind/mgr/dashboard/services/access_control.py
new file mode 100644
index 00000000..9ea7a01c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/access_control.py
@@ -0,0 +1,670 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-arguments,too-many-return-statements
+# pylint: disable=too-many-branches, too-many-locals, too-many-statements
+from __future__ import absolute_import
+
+import errno
+import json
+import threading
+import time
+import six
+
+import bcrypt
+
+from mgr_module import CLICheckNonemptyFileInput, CLIReadCommand, CLIWriteCommand
+
+from .. import mgr, logger
+from ..security import Scope, Permission
+from ..exceptions import RoleAlreadyExists, RoleDoesNotExist, ScopeNotValid, \
+ PermissionNotValid, RoleIsAssociatedWithUser, \
+ UserAlreadyExists, UserDoesNotExist, ScopeNotInRole, \
+ RoleNotInUser
+
+
+# password hashing algorithm
+def password_hash(password, salt_password=None):
+ if not password:
+ return None
+ if six.PY2:
+ password = unicode(password, 'utf-8') if isinstance(password, str) else password
+ if not salt_password:
+ salt_password = bcrypt.gensalt()
+ else:
+ salt_password = salt_password.encode('utf8')
+ return bcrypt.hashpw(password.encode('utf8'), salt_password).decode('utf8')
+
+
+_P = Permission # short alias
+
+
+class Role(object):
+ def __init__(self, name, description=None, scope_permissions=None):
+ self.name = name
+ self.description = description
+ if scope_permissions is None:
+ self.scopes_permissions = {}
+ else:
+ self.scopes_permissions = scope_permissions
+
+ def __hash__(self):
+ return hash(self.name)
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def set_scope_permissions(self, scope, permissions):
+ if not Scope.valid_scope(scope):
+ raise ScopeNotValid(scope)
+ for perm in permissions:
+ if not Permission.valid_permission(perm):
+ raise PermissionNotValid(perm)
+
+ permissions.sort()
+ self.scopes_permissions[scope] = permissions
+
+ def del_scope_permissions(self, scope):
+ if scope not in self.scopes_permissions:
+ raise ScopeNotInRole(scope, self.name)
+ del self.scopes_permissions[scope]
+
+ def reset_scope_permissions(self):
+ self.scopes_permissions = {}
+
+ def authorize(self, scope, permissions):
+ if scope in self.scopes_permissions:
+ role_perms = self.scopes_permissions[scope]
+ for perm in permissions:
+ if perm not in role_perms:
+ return False
+ return True
+ return False
+
+ def to_dict(self):
+ return {
+ 'name': self.name,
+ 'description': self.description,
+ 'scopes_permissions': self.scopes_permissions
+ }
+
+ @classmethod
+ def from_dict(cls, r_dict):
+ return Role(r_dict['name'], r_dict['description'],
+ r_dict['scopes_permissions'])
+
+
+# static pre-defined system roles
+# this roles cannot be deleted nor updated
+
+# admin role provides all permissions for all scopes
+ADMIN_ROLE = Role('administrator', 'Administrator', {
+ scope_name: Permission.all_permissions()
+ for scope_name in Scope.all_scopes()
+})
+
+
+# read-only role provides read-only permission for all scopes
+READ_ONLY_ROLE = Role('read-only', 'Read-Only', {
+ scope_name: [_P.READ] for scope_name in Scope.all_scopes()
+ if scope_name != Scope.DASHBOARD_SETTINGS
+})
+
+
+# block manager role provides all permission for block related scopes
+BLOCK_MGR_ROLE = Role('block-manager', 'Block Manager', {
+ Scope.RBD_IMAGE: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.POOL: [_P.READ],
+ Scope.ISCSI: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.RBD_MIRRORING: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+
+# RadosGW manager role provides all permissions for block related scopes
+RGW_MGR_ROLE = Role('rgw-manager', 'RGW Manager', {
+ Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+
+# Cluster manager role provides all permission for OSDs, Monitors, and
+# Config options
+CLUSTER_MGR_ROLE = Role('cluster-manager', 'Cluster Manager', {
+ Scope.HOSTS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.OSD: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.MONITOR: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.MANAGER: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.CONFIG_OPT: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.LOG: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+
+# Pool manager role provides all permissions for pool related scopes
+POOL_MGR_ROLE = Role('pool-manager', 'Pool Manager', {
+ Scope.POOL: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+# CephFS manager role provides all permissions for CephFS related scopes
+CEPHFS_MGR_ROLE = Role('cephfs-manager', 'CephFS Manager', {
+ Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+GANESHA_MGR_ROLE = Role('ganesha-manager', 'NFS Ganesha Manager', {
+ Scope.NFS_GANESHA: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.GRAFANA: [_P.READ],
+})
+
+
+SYSTEM_ROLES = {
+ ADMIN_ROLE.name: ADMIN_ROLE,
+ READ_ONLY_ROLE.name: READ_ONLY_ROLE,
+ BLOCK_MGR_ROLE.name: BLOCK_MGR_ROLE,
+ RGW_MGR_ROLE.name: RGW_MGR_ROLE,
+ CLUSTER_MGR_ROLE.name: CLUSTER_MGR_ROLE,
+ POOL_MGR_ROLE.name: POOL_MGR_ROLE,
+ CEPHFS_MGR_ROLE.name: CEPHFS_MGR_ROLE,
+ GANESHA_MGR_ROLE.name: GANESHA_MGR_ROLE,
+}
+
+
+class User(object):
+ def __init__(self, username, password, name=None, email=None, roles=None,
+ lastUpdate=None):
+ self.username = username
+ self.password = password
+ self.name = name
+ self.email = email
+ if roles is None:
+ self.roles = set()
+ else:
+ self.roles = roles
+ if lastUpdate is None:
+ self.refreshLastUpdate()
+ else:
+ self.lastUpdate = lastUpdate
+
+ def refreshLastUpdate(self):
+ self.lastUpdate = int(time.time())
+
+ def set_password(self, password):
+ self.password = password_hash(password)
+ self.refreshLastUpdate()
+
+ def set_roles(self, roles):
+ self.roles = set(roles)
+ self.refreshLastUpdate()
+
+ def add_roles(self, roles):
+ self.roles = self.roles.union(set(roles))
+ self.refreshLastUpdate()
+
+ def del_roles(self, roles):
+ for role in roles:
+ if role not in self.roles:
+ raise RoleNotInUser(role.name, self.username)
+ self.roles.difference_update(set(roles))
+ self.refreshLastUpdate()
+
+ def authorize(self, scope, permissions):
+ for role in self.roles:
+ if role.authorize(scope, permissions):
+ return True
+ return False
+
+ def permissions_dict(self):
+ perms = {}
+ for role in self.roles:
+ for scope, perms_list in role.scopes_permissions.items():
+ if scope in perms:
+ perms_tmp = set(perms[scope]).union(set(perms_list))
+ perms[scope] = list(perms_tmp)
+ else:
+ perms[scope] = perms_list
+
+ return perms
+
+ def to_dict(self):
+ return {
+ 'username': self.username,
+ 'password': self.password,
+ 'roles': sorted([r.name for r in self.roles]),
+ 'name': self.name,
+ 'email': self.email,
+ 'lastUpdate': self.lastUpdate
+ }
+
+ @classmethod
+ def from_dict(cls, u_dict, roles):
+ return User(u_dict['username'], u_dict['password'], u_dict['name'],
+ u_dict['email'], {roles[r] for r in u_dict['roles']},
+ u_dict['lastUpdate'])
+
+
+class AccessControlDB(object):
+ VERSION = 1
+ ACDB_CONFIG_KEY = "accessdb_v"
+
+ def __init__(self, version, users, roles):
+ self.users = users
+ self.version = version
+ self.roles = roles
+ self.lock = threading.RLock()
+
+ def create_role(self, name, description=None):
+ with self.lock:
+ if name in SYSTEM_ROLES or name in self.roles:
+ raise RoleAlreadyExists(name)
+ role = Role(name, description)
+ self.roles[name] = role
+ return role
+
+ def get_role(self, name):
+ with self.lock:
+ if name not in self.roles:
+ raise RoleDoesNotExist(name)
+ return self.roles[name]
+
+ def delete_role(self, name):
+ with self.lock:
+ if name not in self.roles:
+ raise RoleDoesNotExist(name)
+ role = self.roles[name]
+
+ # check if role is not associated with a user
+ for username, user in self.users.items():
+ if role in user.roles:
+ raise RoleIsAssociatedWithUser(name, username)
+
+ del self.roles[name]
+
+ def create_user(self, username, password, name, email):
+ logger.debug("AC: creating user: username=%s", username)
+ with self.lock:
+ if username in self.users:
+ raise UserAlreadyExists(username)
+ user = User(username, password_hash(password), name, email)
+ self.users[username] = user
+ return user
+
+ def get_user(self, username):
+ with self.lock:
+ if username not in self.users:
+ raise UserDoesNotExist(username)
+ return self.users[username]
+
+ def delete_user(self, username):
+ with self.lock:
+ if username not in self.users:
+ raise UserDoesNotExist(username)
+ del self.users[username]
+
+ def update_users_with_roles(self, role):
+ with self.lock:
+ if not role:
+ return
+ for _, user in self.users.items():
+ if role in user.roles:
+ user.refreshLastUpdate()
+
+ def save(self):
+ with self.lock:
+ db = {
+ 'users': {un: u.to_dict() for un, u in self.users.items()},
+ 'roles': {rn: r.to_dict() for rn, r in self.roles.items()},
+ 'version': self.version
+ }
+ mgr.set_store(self.accessdb_config_key(), json.dumps(db))
+
+ @classmethod
+ def accessdb_config_key(cls, version=None):
+ if version is None:
+ version = cls.VERSION
+ return "{}{}".format(cls.ACDB_CONFIG_KEY, version)
+
+ def check_and_update_db(self):
+ logger.debug("AC: Checking for previews DB versions")
+ if self.VERSION == 1: # current version
+ # check if there is username/password from previous version
+ username = mgr.get_module_option('username', None)
+ password = mgr.get_module_option('password', None)
+ if username and password:
+ logger.debug("AC: Found single user credentials: user=%s",
+ username)
+ # found user credentials
+ user = self.create_user(username, "", None, None)
+ # password is already hashed, so setting manually
+ user.password = password
+ user.add_roles([ADMIN_ROLE])
+ self.save()
+ else:
+ raise NotImplementedError()
+
+ @classmethod
+ def load(cls):
+ logger.info("AC: Loading user roles DB version=%s", cls.VERSION)
+
+ json_db = mgr.get_store(cls.accessdb_config_key())
+ if json_db is None:
+ logger.debug("AC: No DB v%s found, creating new...", cls.VERSION)
+ db = cls(cls.VERSION, {}, {})
+ # check if we can update from a previous version database
+ db.check_and_update_db()
+ return db
+
+ db = json.loads(json_db)
+ roles = {rn: Role.from_dict(r)
+ for rn, r in db.get('roles', {}).items()}
+ users = {un: User.from_dict(u, dict(roles, **SYSTEM_ROLES))
+ for un, u in db.get('users', {}).items()}
+ return cls(db['version'], users, roles)
+
+
+def load_access_control_db():
+ mgr.ACCESS_CTRL_DB = AccessControlDB.load()
+
+
+# CLI dashboard access control scope commands
+
+@CLIWriteCommand('dashboard set-login-credentials',
+ 'name=username,type=CephString',
+ 'Set the login credentials. Password read from -i <file>')
+@CLICheckNonemptyFileInput
+def set_login_credentials_cmd(_, username, inbuf):
+ password = inbuf
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ user.set_password(password)
+ except UserDoesNotExist:
+ user = mgr.ACCESS_CTRL_DB.create_user(username, password, None, None)
+ user.set_roles([ADMIN_ROLE])
+
+ mgr.ACCESS_CTRL_DB.save()
+
+ return 0, '''\
+******************************************************************
+*** WARNING: this command is deprecated. ***
+*** Please use the ac-user-* related commands to manage users. ***
+******************************************************************
+Username and password updated''', ''
+
+
+@CLIReadCommand('dashboard ac-role-show',
+ 'name=rolename,type=CephString,req=false',
+ 'Show role info')
+def ac_role_show_cmd(_, rolename=None):
+ if not rolename:
+ roles = dict(mgr.ACCESS_CTRL_DB.roles)
+ roles.update(SYSTEM_ROLES)
+ roles_list = [name for name, _ in roles.items()]
+ return 0, json.dumps(roles_list), ''
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(rolename)
+ except RoleDoesNotExist as ex:
+ if rolename not in SYSTEM_ROLES:
+ return -errno.ENOENT, '', str(ex)
+ role = SYSTEM_ROLES[rolename]
+ return 0, json.dumps(role.to_dict()), ''
+
+
+@CLIWriteCommand('dashboard ac-role-create',
+ 'name=rolename,type=CephString '
+ 'name=description,type=CephString,req=false',
+ 'Create a new access control role')
+def ac_role_create_cmd(_, rolename, description=None):
+ try:
+ role = mgr.ACCESS_CTRL_DB.create_role(rolename, description)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(role.to_dict()), ''
+ except RoleAlreadyExists as ex:
+ return -errno.EEXIST, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-role-delete',
+ 'name=rolename,type=CephString',
+ 'Delete an access control role')
+def ac_role_delete_cmd(_, rolename):
+ try:
+ mgr.ACCESS_CTRL_DB.delete_role(rolename)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, "Role '{}' deleted".format(rolename), ""
+ except RoleDoesNotExist as ex:
+ if rolename in SYSTEM_ROLES:
+ return -errno.EPERM, '', "Cannot delete system role '{}'" \
+ .format(rolename)
+ return -errno.ENOENT, '', str(ex)
+ except RoleIsAssociatedWithUser as ex:
+ return -errno.EPERM, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-role-add-scope-perms',
+ 'name=rolename,type=CephString '
+ 'name=scopename,type=CephString '
+ 'name=permissions,type=CephString,n=N',
+ 'Add the scope permissions for a role')
+def ac_role_add_scope_perms_cmd(_, rolename, scopename, permissions):
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(rolename)
+ perms_array = [perm.strip() for perm in permissions]
+ role.set_scope_permissions(scopename, perms_array)
+ mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(role.to_dict()), ''
+ except RoleDoesNotExist as ex:
+ if rolename in SYSTEM_ROLES:
+ return -errno.EPERM, '', "Cannot update system role '{}'" \
+ .format(rolename)
+ return -errno.ENOENT, '', str(ex)
+ except ScopeNotValid as ex:
+ return -errno.EINVAL, '', str(ex) + "\n Possible values: {}" \
+ .format(Scope.all_scopes())
+ except PermissionNotValid as ex:
+ return -errno.EINVAL, '', str(ex) + \
+ "\n Possible values: {}" \
+ .format(Permission.all_permissions())
+
+
+@CLIWriteCommand('dashboard ac-role-del-scope-perms',
+ 'name=rolename,type=CephString '
+ 'name=scopename,type=CephString',
+ 'Delete the scope permissions for a role')
+def ac_role_del_scope_perms_cmd(_, rolename, scopename):
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(rolename)
+ role.del_scope_permissions(scopename)
+ mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(role.to_dict()), ''
+ except RoleDoesNotExist as ex:
+ if rolename in SYSTEM_ROLES:
+ return -errno.EPERM, '', "Cannot update system role '{}'" \
+ .format(rolename)
+ return -errno.ENOENT, '', str(ex)
+ except ScopeNotInRole as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIReadCommand('dashboard ac-user-show',
+ 'name=username,type=CephString,req=false',
+ 'Show user info')
+def ac_user_show_cmd(_, username=None):
+ if not username:
+ users = mgr.ACCESS_CTRL_DB.users
+ users_list = [name for name, _ in users.items()]
+ return 0, json.dumps(users_list), ''
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-create',
+ 'name=username,type=CephString '
+ 'name=rolename,type=CephString,req=false '
+ 'name=name,type=CephString,req=false '
+ 'name=email,type=CephString,req=false',
+ 'Create a user. Password read from -i <file>')
+@CLICheckNonemptyFileInput
+def ac_user_create_cmd(_, username, inbuf, rolename=None, name=None,
+ email=None):
+ password = inbuf
+ try:
+ role = mgr.ACCESS_CTRL_DB.get_role(rolename) if rolename else None
+ except RoleDoesNotExist as ex:
+ if rolename not in SYSTEM_ROLES:
+ return -errno.ENOENT, '', str(ex)
+ role = SYSTEM_ROLES[rolename]
+
+ try:
+ user = mgr.ACCESS_CTRL_DB.create_user(username, password, name, email)
+ except UserAlreadyExists as ex:
+ return -errno.EEXIST, '', str(ex)
+
+ if role:
+ user.set_roles([role])
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+
+
+@CLIWriteCommand('dashboard ac-user-delete',
+ 'name=username,type=CephString',
+ 'Delete user')
+def ac_user_delete_cmd(_, username):
+ try:
+ mgr.ACCESS_CTRL_DB.delete_user(username)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, "User '{}' deleted".format(username), ""
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-set-roles',
+ 'name=username,type=CephString '
+ 'name=roles,type=CephString,n=N',
+ 'Set user roles')
+def ac_user_set_roles_cmd(_, username, roles):
+ rolesname = roles
+ roles = []
+ for rolename in rolesname:
+ try:
+ roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
+ except RoleDoesNotExist as ex:
+ if rolename not in SYSTEM_ROLES:
+ return -errno.ENOENT, '', str(ex)
+ roles.append(SYSTEM_ROLES[rolename])
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ user.set_roles(roles)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-add-roles',
+ 'name=username,type=CephString '
+ 'name=roles,type=CephString,n=N',
+ 'Add roles to user')
+def ac_user_add_roles_cmd(_, username, roles):
+ rolesname = roles
+ roles = []
+ for rolename in rolesname:
+ try:
+ roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
+ except RoleDoesNotExist as ex:
+ if rolename not in SYSTEM_ROLES:
+ return -errno.ENOENT, '', str(ex)
+ roles.append(SYSTEM_ROLES[rolename])
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ user.add_roles(roles)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-del-roles',
+ 'name=username,type=CephString '
+ 'name=roles,type=CephString,n=N',
+ 'Delete roles from user')
+def ac_user_del_roles_cmd(_, username, roles):
+ rolesname = roles
+ roles = []
+ for rolename in rolesname:
+ try:
+ roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
+ except RoleDoesNotExist as ex:
+ if rolename not in SYSTEM_ROLES:
+ return -errno.ENOENT, '', str(ex)
+ roles.append(SYSTEM_ROLES[rolename])
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ user.del_roles(roles)
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+ except RoleNotInUser as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-set-password',
+ 'name=username,type=CephString',
+ 'Set user password from -i <file>')
+@CLICheckNonemptyFileInput
+def ac_user_set_password(_, username, inbuf):
+ password = inbuf
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ user.set_password(password)
+
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+@CLIWriteCommand('dashboard ac-user-set-info',
+ 'name=username,type=CephString '
+ 'name=name,type=CephString '
+ 'name=email,type=CephString',
+ 'Set user info')
+def ac_user_set_info(_, username, name, email):
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ if name:
+ user.name = name
+ if email:
+ user.email = email
+ mgr.ACCESS_CTRL_DB.save()
+ return 0, json.dumps(user.to_dict()), ''
+ except UserDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+
+
+class LocalAuthenticator(object):
+ def __init__(self):
+ load_access_control_db()
+
+ def get_user(self, username):
+ return mgr.ACCESS_CTRL_DB.get_user(username)
+
+ def authenticate(self, username, password):
+ try:
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ if user.password:
+ pass_hash = password_hash(password, user.password)
+ if pass_hash == user.password:
+ return user.permissions_dict()
+ except UserDoesNotExist:
+ logger.debug("User '%s' does not exist", username)
+ return None
+
+ def authorize(self, username, scope, permissions):
+ user = mgr.ACCESS_CTRL_DB.get_user(username)
+ return user.authorize(scope, permissions)
diff --git a/src/pybind/mgr/dashboard/services/auth.py b/src/pybind/mgr/dashboard/services/auth.py
new file mode 100644
index 00000000..239efae8
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/auth.py
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from base64 import b64encode
+import json
+import os
+import threading
+import time
+import uuid
+
+import cherrypy
+import jwt
+
+from .access_control import LocalAuthenticator, UserDoesNotExist
+from .. import mgr, logger
+
+cherrypy.config.update({
+ 'response.headers.server': 'Ceph-Dashboard',
+ 'response.headers.content-security-policy': "frame-ancestors 'self';",
+ 'response.headers.x-content-type-options': 'nosniff',
+ 'response.headers.strict-transport-security': 'max-age=63072000; includeSubDomains; preload'
+})
+
+
+class JwtManager(object):
+ JWT_TOKEN_BLACKLIST_KEY = "jwt_token_black_list"
+ JWT_TOKEN_TTL = 28800 # default 8 hours
+ JWT_ALGORITHM = 'HS256'
+ _secret = None
+
+ LOCAL_USER = threading.local()
+
+ @staticmethod
+ def _gen_secret():
+ secret = os.urandom(16)
+ return b64encode(secret).decode('utf-8')
+
+ @classmethod
+ def init(cls):
+ # generate a new secret if it does not exist
+ secret = mgr.get_store('jwt_secret')
+ if secret is None:
+ secret = cls._gen_secret()
+ mgr.set_store('jwt_secret', secret)
+ cls._secret = secret
+
+ @classmethod
+ def gen_token(cls, username):
+ if not cls._secret:
+ cls.init()
+ ttl = mgr.get_module_option('jwt_token_ttl', cls.JWT_TOKEN_TTL)
+ ttl = int(ttl)
+ now = int(time.time())
+ payload = {
+ 'iss': 'ceph-dashboard',
+ 'jti': str(uuid.uuid4()),
+ 'exp': now + ttl,
+ 'iat': now,
+ 'username': username
+ }
+ return jwt.encode(payload, cls._secret, algorithm=cls.JWT_ALGORITHM)
+
+ @classmethod
+ def decode_token(cls, token):
+ if not cls._secret:
+ cls.init()
+ return jwt.decode(token, cls._secret, algorithms=cls.JWT_ALGORITHM)
+
+ @classmethod
+ def get_token_from_header(cls):
+ auth_cookie_name = 'token'
+ try:
+ # use cookie
+ return cherrypy.request.cookie[auth_cookie_name].value
+ except KeyError:
+ try:
+ # fall-back: use Authorization header
+ auth_header = cherrypy.request.headers.get('authorization')
+ if auth_header is not None:
+ scheme, params = auth_header.split(' ', 1)
+ if scheme.lower() == 'bearer':
+ return params
+ except IndexError:
+ return None
+
+ @classmethod
+ def set_user(cls, token):
+ cls.LOCAL_USER.username = token['username']
+
+ @classmethod
+ def reset_user(cls):
+ cls.set_user({'username': None, 'permissions': None})
+
+ @classmethod
+ def get_username(cls):
+ return getattr(cls.LOCAL_USER, 'username', None)
+
+ @classmethod
+ def blacklist_token(cls, token):
+ token = cls.decode_token(token)
+ blacklist_json = mgr.get_store(cls.JWT_TOKEN_BLACKLIST_KEY)
+ if not blacklist_json:
+ blacklist_json = "{}"
+ bl_dict = json.loads(blacklist_json)
+ now = time.time()
+
+ # remove expired tokens
+ to_delete = []
+ for jti, exp in bl_dict.items():
+ if exp < now:
+ to_delete.append(jti)
+ for jti in to_delete:
+ del bl_dict[jti]
+
+ bl_dict[token['jti']] = token['exp']
+ mgr.set_store(cls.JWT_TOKEN_BLACKLIST_KEY, json.dumps(bl_dict))
+
+ @classmethod
+ def is_blacklisted(cls, jti):
+ blacklist_json = mgr.get_store(cls.JWT_TOKEN_BLACKLIST_KEY)
+ if not blacklist_json:
+ blacklist_json = "{}"
+ bl_dict = json.loads(blacklist_json)
+ return jti in bl_dict
+
+
+class AuthManager(object):
+ AUTH_PROVIDER = None
+
+ @classmethod
+ def initialize(cls):
+ cls.AUTH_PROVIDER = LocalAuthenticator()
+
+ @classmethod
+ def get_user(cls, username):
+ return cls.AUTH_PROVIDER.get_user(username)
+
+ @classmethod
+ def authenticate(cls, username, password):
+ return cls.AUTH_PROVIDER.authenticate(username, password)
+
+ @classmethod
+ def authorize(cls, username, scope, permissions):
+ return cls.AUTH_PROVIDER.authorize(username, scope, permissions)
+
+
+class AuthManagerTool(cherrypy.Tool):
+ def __init__(self):
+ super(AuthManagerTool, self).__init__(
+ 'before_handler', self._check_authentication, priority=20)
+
+ def _check_authentication(self):
+ JwtManager.reset_user()
+ token = JwtManager.get_token_from_header()
+ logger.debug("AMT: token: %s", token)
+ if token:
+ try:
+ token = JwtManager.decode_token(token)
+ if not JwtManager.is_blacklisted(token['jti']):
+ user = AuthManager.get_user(token['username'])
+ if user.lastUpdate <= token['iat']:
+ self._check_authorization(token)
+ return
+
+ logger.debug("AMT: user info changed after token was"
+ " issued, iat=%s lastUpdate=%s",
+ token['iat'], user.lastUpdate)
+ else:
+ logger.debug('AMT: Token is black-listed')
+ except jwt.exceptions.ExpiredSignatureError:
+ logger.debug("AMT: Token has expired")
+ except jwt.exceptions.InvalidTokenError:
+ logger.debug("AMT: Failed to decode token")
+ except UserDoesNotExist:
+ logger.debug("AMT: Invalid token: user %s does not exist",
+ token['username'])
+
+ logger.debug('AMT: Unauthorized access to %s',
+ cherrypy.url(relative='server'))
+ raise cherrypy.HTTPError(401, 'You are not authorized to access '
+ 'that resource')
+
+ def _check_authorization(self, token):
+ logger.debug("AMT: checking authorization...")
+ username = token['username']
+ handler = cherrypy.request.handler.callable
+ controller = handler.__self__
+ sec_scope = getattr(controller, '_security_scope', None)
+ sec_perms = getattr(handler, '_security_permissions', None)
+ JwtManager.set_user(token)
+
+ if not sec_scope:
+ # controller does not define any authorization restrictions
+ return
+
+ logger.debug("AMT: checking '%s' access to '%s' scope", sec_perms,
+ sec_scope)
+
+ if not sec_perms:
+ logger.debug("Fail to check permission on: %s:%s", controller,
+ handler)
+ raise cherrypy.HTTPError(403, "You don't have permissions to "
+ "access that resource")
+
+ if not AuthManager.authorize(username, sec_scope, sec_perms):
+ raise cherrypy.HTTPError(403, "You don't have permissions to "
+ "access that resource")
diff --git a/src/pybind/mgr/dashboard/services/ceph_service.py b/src/pybind/mgr/dashboard/services/ceph_service.py
new file mode 100644
index 00000000..6d38fa41
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/ceph_service.py
@@ -0,0 +1,254 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+import rados
+
+from mgr_module import CommandResult
+from mgr_util import get_time_series_rates, get_most_recent_rate
+
+from .. import logger, mgr
+
+try:
+ from typing import Dict, Any, Union # pylint: disable=unused-import
+except ImportError:
+ pass # For typing only
+
+
+class SendCommandError(rados.Error):
+ def __init__(self, err, prefix, argdict, errno):
+ self.prefix = prefix
+ self.argdict = argdict
+ super(SendCommandError, self).__init__(err, errno)
+
+
+class CephService(object):
+
+ OSD_FLAG_NO_SCRUB = 'noscrub'
+ OSD_FLAG_NO_DEEP_SCRUB = 'nodeep-scrub'
+
+ PG_STATUS_SCRUBBING = 'scrubbing'
+ PG_STATUS_DEEP_SCRUBBING = 'deep'
+
+ SCRUB_STATUS_DISABLED = 'Disabled'
+ SCRUB_STATUS_ACTIVE = 'Active'
+ SCRUB_STATUS_INACTIVE = 'Inactive'
+
+ @classmethod
+ def get_service_map(cls, service_name):
+ service_map = {} # type: Dict[str, Dict[str, Any]]
+ for server in mgr.list_servers():
+ for service in server['services']:
+ if service['type'] == service_name:
+ if server['hostname'] not in service_map:
+ service_map[server['hostname']] = {
+ 'server': server,
+ 'services': []
+ }
+ inst_id = service['id']
+ metadata = mgr.get_metadata(service_name, inst_id)
+ status = mgr.get_daemon_status(service_name, inst_id)
+ service_map[server['hostname']]['services'].append({
+ 'id': inst_id,
+ 'type': service_name,
+ 'hostname': server['hostname'],
+ 'metadata': metadata,
+ 'status': status
+ })
+ return service_map
+
+ @classmethod
+ def get_service_list(cls, service_name):
+ service_map = cls.get_service_map(service_name)
+ return [svc for _, svcs in service_map.items() for svc in svcs['services']]
+
+ @classmethod
+ def get_service(cls, service_name, service_id):
+ for server in mgr.list_servers():
+ for service in server['services']:
+ if service['type'] == service_name:
+ inst_id = service['id']
+ if inst_id == service_id:
+ metadata = mgr.get_metadata(service_name, inst_id)
+ status = mgr.get_daemon_status(service_name, inst_id)
+ return {
+ 'id': inst_id,
+ 'type': service_name,
+ 'hostname': server['hostname'],
+ 'metadata': metadata,
+ 'status': status
+ }
+ return None
+
+ @classmethod
+ def get_pool_list(cls, application=None):
+ osd_map = mgr.get('osd_map')
+ if not application:
+ return osd_map['pools']
+ return [pool for pool in osd_map['pools']
+ if application in pool.get('application_metadata', {})]
+
+ @classmethod
+ def get_pool_list_with_stats(cls, application=None):
+ # pylint: disable=too-many-locals
+ pools = cls.get_pool_list(application)
+
+ pools_w_stats = []
+
+ pg_summary = mgr.get("pg_summary")
+ pool_stats = mgr.get_updated_pool_stats()
+
+ for pool in pools:
+ pool['pg_status'] = pg_summary['by_pool'][pool['pool'].__str__()]
+ stats = pool_stats[pool['pool']]
+ s = {}
+
+ for stat_name, stat_series in stats.items():
+ rates = get_time_series_rates(stat_series)
+ s[stat_name] = {
+ 'latest': stat_series[0][1],
+ 'rate': get_most_recent_rate(rates),
+ 'rates': rates
+ }
+ pool['stats'] = s
+ pools_w_stats.append(pool)
+ return pools_w_stats
+
+ @classmethod
+ def get_pool_name_from_id(cls, pool_id):
+ # type: (int) -> Union[str, None]
+ return mgr.rados.pool_reverse_lookup(pool_id)
+
+ @classmethod
+ def get_pool_by_attribute(cls, attribute, value):
+ # type: (str, Any) -> Union[dict, None]
+ pool_list = cls.get_pool_list()
+ for pool in pool_list:
+ if attribute in pool and pool[attribute] == value:
+ return pool
+ return None
+
+ @classmethod
+ def get_pool_pg_status(cls, pool_name):
+ # type: (str) -> dict
+ pool = cls.get_pool_by_attribute('pool_name', pool_name)
+ if pool is None:
+ return {}
+ return mgr.get("pg_summary")['by_pool'][pool['pool'].__str__()]
+
+ @classmethod
+ def send_command(cls, srv_type, prefix, srv_spec='', **kwargs):
+ """
+ :type prefix: str
+ :param srv_type: mon |
+ :param kwargs: will be added to argdict
+ :param srv_spec: typically empty. or something like "<fs_id>:0"
+
+ :raises PermissionError: See rados.make_ex
+ :raises ObjectNotFound: See rados.make_ex
+ :raises IOError: See rados.make_ex
+ :raises NoSpace: See rados.make_ex
+ :raises ObjectExists: See rados.make_ex
+ :raises ObjectBusy: See rados.make_ex
+ :raises NoData: See rados.make_ex
+ :raises InterruptedOrTimeoutError: See rados.make_ex
+ :raises TimedOut: See rados.make_ex
+ :raises ValueError: return code != 0
+ """
+ argdict = {
+ "prefix": prefix,
+ "format": "json",
+ }
+ argdict.update({k: v for k, v in kwargs.items() if v is not None})
+ result = CommandResult("")
+ mgr.send_command(result, srv_type, srv_spec, json.dumps(argdict), "")
+ r, outb, outs = result.wait()
+ if r != 0:
+ msg = "send_command '{}' failed. (r={}, outs=\"{}\", kwargs={})".format(prefix, r, outs,
+ kwargs)
+ logger.error(msg)
+ raise SendCommandError(outs, prefix, argdict, r)
+ else:
+ try:
+ return json.loads(outb)
+ except Exception: # pylint: disable=broad-except
+ return outb
+
+ @classmethod
+ def get_rates(cls, svc_type, svc_name, path):
+ """
+ :return: the derivative of mgr.get_counter()
+ :rtype: list[tuple[int, float]]"""
+ data = mgr.get_counter(svc_type, svc_name, path)[path]
+ return get_time_series_rates(data)
+
+ @classmethod
+ def get_rate(cls, svc_type, svc_name, path):
+ """returns most recent rate"""
+ return get_most_recent_rate(cls.get_rates(svc_type, svc_name, path))
+
+ @classmethod
+ def get_client_perf(cls):
+ pools_stats = mgr.get('osd_pool_stats')['pool_stats']
+
+ io_stats = {
+ 'read_bytes_sec': 0,
+ 'read_op_per_sec': 0,
+ 'write_bytes_sec': 0,
+ 'write_op_per_sec': 0,
+ }
+ recovery_stats = {'recovering_bytes_per_sec': 0}
+
+ for pool_stats in pools_stats:
+ client_io = pool_stats['client_io_rate']
+ for stat in list(io_stats.keys()):
+ if stat in client_io:
+ io_stats[stat] += client_io[stat]
+
+ client_recovery = pool_stats['recovery_rate']
+ for stat in list(recovery_stats.keys()):
+ if stat in client_recovery:
+ recovery_stats[stat] += client_recovery[stat]
+
+ client_perf = io_stats.copy()
+ client_perf.update(recovery_stats)
+
+ return client_perf
+
+ @classmethod
+ def get_scrub_status(cls):
+ enabled_flags = mgr.get('osd_map')['flags_set']
+ if cls.OSD_FLAG_NO_SCRUB in enabled_flags or cls.OSD_FLAG_NO_DEEP_SCRUB in enabled_flags:
+ return cls.SCRUB_STATUS_DISABLED
+
+ grouped_pg_statuses = mgr.get('pg_summary')['all']
+ for grouped_pg_status in grouped_pg_statuses.keys():
+ if len(grouped_pg_status.split(cls.PG_STATUS_SCRUBBING)) > 1 \
+ or len(grouped_pg_status.split(cls.PG_STATUS_DEEP_SCRUBBING)) > 1:
+ return cls.SCRUB_STATUS_ACTIVE
+
+ return cls.SCRUB_STATUS_INACTIVE
+
+ @classmethod
+ def get_pg_info(cls):
+ pg_summary = mgr.get('pg_summary')
+ object_stats = {stat: pg_summary['pg_stats_sum']['stat_sum'][stat] for stat in [
+ 'num_objects', 'num_object_copies', 'num_objects_degraded',
+ 'num_objects_misplaced', 'num_objects_unfound']}
+
+ pgs_per_osd = 0.0
+ total_osds = len(pg_summary['by_osd'])
+ if total_osds > 0:
+ total_pgs = 0.0
+ for _, osd_pg_statuses in pg_summary['by_osd'].items():
+ for _, pg_amount in osd_pg_statuses.items():
+ total_pgs += pg_amount
+
+ pgs_per_osd = total_pgs / total_osds
+
+ return {
+ 'object_stats': object_stats,
+ 'statuses': pg_summary['all'],
+ 'pgs_per_osd': pgs_per_osd,
+ }
diff --git a/src/pybind/mgr/dashboard/services/cephfs.py b/src/pybind/mgr/dashboard/services/cephfs.py
new file mode 100644
index 00000000..bb75b4e2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/cephfs.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from contextlib import contextmanager
+
+import cephfs
+
+from .. import mgr, logger
+
+
+class CephFS(object):
+ @classmethod
+ def list_filesystems(cls):
+ fsmap = mgr.get("fs_map")
+ return [{'id': fs['id'], 'name': fs['mdsmap']['fs_name']}
+ for fs in fsmap['filesystems']]
+
+ def __init__(self, fs_name=None):
+ logger.debug("[CephFS] initializing cephfs connection")
+ self.cfs = cephfs.LibCephFS(rados_inst=mgr.rados)
+ logger.debug("[CephFS] mounting cephfs filesystem: %s", fs_name)
+ if fs_name:
+ self.cfs.mount(filesystem_name=fs_name)
+ else:
+ self.cfs.mount()
+ logger.debug("[CephFS] mounted cephfs filesystem")
+
+ def __del__(self):
+ logger.debug("[CephFS] shutting down cephfs filesystem")
+ self.cfs.shutdown()
+
+ @contextmanager
+ def opendir(self, dirpath):
+ d = None
+ try:
+ d = self.cfs.opendir(dirpath)
+ yield d
+ finally:
+ if d:
+ self.cfs.closedir(d)
+
+ def get_dir_list(self, dirpath, level):
+ logger.debug("[CephFS] get_dir_list dirpath=%s level=%s", dirpath,
+ level)
+ if level == 0:
+ return [dirpath]
+ logger.debug("[CephFS] opening dirpath=%s", dirpath)
+ with self.opendir(dirpath) as d:
+ dent = self.cfs.readdir(d)
+ paths = [dirpath]
+ while dent:
+ logger.debug("[CephFS] found entry=%s", dent.d_name)
+ if dent.d_name in ['.', '..']:
+ dent = self.cfs.readdir(d)
+ continue
+ if dent.is_dir():
+ logger.debug("[CephFS] found dir=%s", dent.d_name)
+ subdirpath = '{}{}/'.format(dirpath, dent.d_name)
+ paths.extend(self.get_dir_list(subdirpath, level-1))
+ dent = self.cfs.readdir(d)
+ return paths
+
+ def dir_exists(self, dirpath):
+ try:
+ with self.opendir(dirpath):
+ return True
+ except cephfs.ObjectNotFound:
+ return False
+
+ def mkdirs(self, dirpath):
+ if dirpath == '/':
+ raise Exception('Cannot create root directory "/"')
+ if self.dir_exists(dirpath):
+ return
+
+ logger.info("[CephFS] Creating directory: %s", dirpath)
+ self.cfs.mkdirs("{}".format(dirpath).encode('utf-8'), 0o755)
diff --git a/src/pybind/mgr/dashboard/services/cephx.py b/src/pybind/mgr/dashboard/services/cephx.py
new file mode 100644
index 00000000..ccda3879
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/cephx.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from .ceph_service import CephService
+
+
+class CephX(object):
+ @classmethod
+ def _entities_map(cls, entity_type=None):
+ auth_dump = CephService.send_command("mon", "auth list")
+ result = {}
+ for auth_entry in auth_dump['auth_dump']:
+ entity = auth_entry['entity']
+ if not entity_type or entity.startswith('{}.'.format(entity_type)):
+ entity_id = entity[entity.find('.')+1:]
+ result[entity_id] = auth_entry
+ return result
+
+ @classmethod
+ def _clients_map(cls):
+ return cls._entities_map("client")
+
+ @classmethod
+ def list_clients(cls):
+ return [client for client in cls._clients_map()]
+
+ @classmethod
+ def get_client_key(cls, client_id):
+ return cls._clients_map()[client_id]['key']
diff --git a/src/pybind/mgr/dashboard/services/exception.py b/src/pybind/mgr/dashboard/services/exception.py
new file mode 100644
index 00000000..b5c0bd58
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/exception.py
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+import sys
+from contextlib import contextmanager
+
+import cherrypy
+
+import rbd
+import rados
+
+from .. import logger
+from ..services.ceph_service import SendCommandError
+from ..exceptions import ViewCacheNoDataException, DashboardException
+from ..tools import wraps
+
+if sys.version_info < (3, 0):
+ # Monkey-patch a __call__ method into @contextmanager to make
+ # it compatible to Python 3
+
+ from contextlib import GeneratorContextManager # pylint: disable=no-name-in-module
+
+ def init(self, *args):
+ if len(args) == 1:
+ self.gen = args[0]
+ elif len(args) == 3:
+ self.func, self.args, self.kwargs = args
+ else:
+ raise TypeError()
+
+ def enter(self):
+ if hasattr(self, 'func'):
+ self.gen = self.func(*self.args, **self.kwargs)
+ try:
+ return self.gen.next()
+ except StopIteration:
+ raise RuntimeError("generator didn't yield")
+
+ def call(self, f):
+ @wraps(f)
+ def wrapper(*args, **kwargs):
+ with self:
+ return f(*args, **kwargs)
+
+ return wrapper
+
+ GeneratorContextManager.__init__ = init
+ GeneratorContextManager.__enter__ = enter
+ GeneratorContextManager.__call__ = call
+
+ # pylint: disable=function-redefined
+ def contextmanager(func):
+
+ @wraps(func)
+ def helper(*args, **kwds):
+ return GeneratorContextManager(func, args, kwds)
+
+ return helper
+
+
+def serialize_dashboard_exception(e, include_http_status=False, task=None):
+ """
+ :type e: Exception
+ :param include_http_status: Used for Tasks, where the HTTP status code is not available.
+ """
+ from ..tools import ViewCache
+ if isinstance(e, ViewCacheNoDataException):
+ return {'status': ViewCache.VALUE_NONE, 'value': None}
+
+ out = dict(detail=str(e))
+ try:
+ out['code'] = e.code
+ except AttributeError:
+ pass
+ component = getattr(e, 'component', None)
+ out['component'] = component if component else None
+ if include_http_status:
+ out['status'] = getattr(e, 'status', 500)
+ if task:
+ out['task'] = dict(name=task.name, metadata=task.metadata)
+ return out
+
+
+def dashboard_exception_handler(handler, *args, **kwargs):
+ try:
+ with handle_rados_error(component=None): # make the None controller the fallback.
+ return handler(*args, **kwargs)
+ # Don't catch cherrypy.* Exceptions.
+ except (ViewCacheNoDataException, DashboardException) as e:
+ logger.exception('dashboard_exception_handler')
+ cherrypy.response.headers['Content-Type'] = 'application/json'
+ cherrypy.response.status = getattr(e, 'status', 400)
+ return json.dumps(serialize_dashboard_exception(e)).encode('utf-8')
+
+
+@contextmanager
+def handle_rbd_error():
+ try:
+ yield
+ except rbd.OSError as e:
+ raise DashboardException(e, component='rbd')
+ except rbd.Error as e:
+ raise DashboardException(e, component='rbd', code=e.__class__.__name__)
+
+
+@contextmanager
+def handle_rados_error(component):
+ try:
+ yield
+ except rados.OSError as e:
+ raise DashboardException(e, component=component)
+ except rados.Error as e:
+ raise DashboardException(e, component=component, code=e.__class__.__name__)
+
+
+@contextmanager
+def handle_send_command_error(component):
+ try:
+ yield
+ except SendCommandError as e:
+ raise DashboardException(e, component=component)
diff --git a/src/pybind/mgr/dashboard/services/ganesha.py b/src/pybind/mgr/dashboard/services/ganesha.py
new file mode 100644
index 00000000..4053d20c
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/ganesha.py
@@ -0,0 +1,998 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import re
+
+from orchestrator import OrchestratorError
+from .cephfs import CephFS
+from .cephx import CephX
+from .orchestrator import OrchClient
+from .rgw_client import RgwClient, RequestException, NoCredentialsException
+from .. import mgr, logger
+from ..settings import Settings
+from ..exceptions import DashboardException
+
+
+class NFSException(DashboardException):
+ def __init__(self, msg):
+ super(NFSException, self).__init__(component="nfs", msg=msg)
+
+
+class Ganesha(object):
+ @classmethod
+ def _get_clusters_locations(cls):
+ result = {}
+ location_list_str = Settings.GANESHA_CLUSTERS_RADOS_POOL_NAMESPACE
+ if not location_list_str:
+ raise NFSException("Ganesha config location is not configured. "
+ "Please set the GANESHA_RADOS_POOL_NAMESPACE "
+ "setting.")
+ location_list = [l.strip() for l in location_list_str.split(",")]
+ for location in location_list:
+ cluster = None
+ pool = None
+ namespace = None
+ if not location:
+ raise NFSException("Invalid Ganesha cluster RADOS "
+ "[cluster_id:]pool/namespace setting: {}"
+ .format(location))
+ if location.count(':') < 1:
+ # default cluster_id
+ if location.count('/') > 1:
+ raise NFSException("Invalid Ganesha RADOS pool/namespace "
+ "setting: {}".format(location))
+ # in this case accept pool/namespace only
+ cluster = "_default_"
+ if location.count('/') == 0:
+ pool, namespace = location, None
+ else:
+ pool, namespace = location.split('/', 1)
+ else:
+ cluster = location[:location.find(':')]
+ pool_nm = location[location.find(':')+1:]
+ if pool_nm.count('/') == 0:
+ pool, namespace = pool_nm, None
+ else:
+ pool, namespace = pool_nm.split('/', 1)
+
+ if cluster in result:
+ raise NFSException("Duplicate Ganesha cluster definition in "
+ "the setting: {}".format(location_list_str))
+ result[cluster] = (pool, namespace)
+
+ return result
+
+ @classmethod
+ def get_ganesha_clusters(cls):
+ return [cluster_id for cluster_id in cls._get_clusters_locations()]
+
+ @staticmethod
+ def _get_orch_nfs_instances():
+ try:
+ return OrchClient().list_service_info("nfs")
+ except (RuntimeError, OrchestratorError, ImportError):
+ return []
+
+ @classmethod
+ def get_daemons_status(cls):
+ instances = cls._get_orch_nfs_instances()
+ if not instances:
+ return None
+
+ result = {}
+ for instance in instances:
+ if instance.service is None:
+ instance.service = "_default_"
+ if instance.service not in result:
+ result[instance.service] = {}
+ result[instance.service][instance.nodename] = {
+ 'status': instance.status,
+ 'desc': instance.status_desc,
+ }
+ return result
+
+ @classmethod
+ def parse_rados_url(cls, rados_url):
+ if not rados_url.startswith("rados://"):
+ raise NFSException("Invalid NFS Ganesha RADOS configuration URL: {}"
+ .format(rados_url))
+ rados_url = rados_url[8:]
+ url_comps = rados_url.split("/")
+ if len(url_comps) < 2 or len(url_comps) > 3:
+ raise NFSException("Invalid NFS Ganesha RADOS configuration URL: "
+ "rados://{}".format(rados_url))
+ if len(url_comps) == 2:
+ return url_comps[0], None, url_comps[1]
+ return url_comps
+
+ @classmethod
+ def make_rados_url(cls, pool, namespace, obj):
+ if namespace:
+ return "rados://{}/{}/{}".format(pool, namespace, obj)
+ return "rados://{}/{}".format(pool, obj)
+
+ @classmethod
+ def get_pool_and_namespace(cls, cluster_id):
+ instances = cls._get_orch_nfs_instances()
+ # we assume that every instance stores there configuration in the
+ # same RADOS pool/namespace
+ if instances:
+ location = instances[0].rados_config_location
+ pool, ns, _ = cls.parse_rados_url(location)
+ return pool, ns
+ locations = cls._get_clusters_locations()
+ if cluster_id not in locations:
+ raise NFSException("Cluster not found: cluster_id={}"
+ .format(cluster_id))
+ return locations[cluster_id]
+
+ @classmethod
+ def reload_daemons(cls, cluster_id, daemons_id):
+ logger.debug("[NFS] issued reload of daemons: %s", daemons_id)
+ if not OrchClient().available():
+ logger.debug("[NFS] orchestrator not available")
+ return
+ reload_list = []
+ daemons = cls.get_daemons_status()
+ if cluster_id not in daemons:
+ raise NFSException("Cluster not found: cluster_id={}"
+ .format(cluster_id))
+ for daemon_id in daemons_id:
+ if daemon_id not in daemons[cluster_id]:
+ continue
+ if daemons[cluster_id][daemon_id] == 1:
+ reload_list.append((cluster_id, daemon_id))
+ OrchClient().reload_service("nfs", reload_list)
+
+ @classmethod
+ def fsals_available(cls):
+ result = []
+ if CephFS.list_filesystems():
+ result.append("CEPH")
+ try:
+ if RgwClient.admin_instance().is_service_online() and \
+ RgwClient.admin_instance().is_system_user():
+ result.append("RGW")
+ except (NoCredentialsException, RequestException, LookupError):
+ pass
+ return result
+
+
+class GaneshaConfParser(object):
+ def __init__(self, raw_config):
+ self.pos = 0
+ self.text = ""
+ self.clean_config(raw_config)
+
+ def clean_config(self, raw_config):
+ for line in raw_config.split("\n"):
+ cardinal_idx = line.find('#')
+ if cardinal_idx == -1:
+ self.text += line
+ else:
+ # remove comments
+ self.text += line[:cardinal_idx]
+ if line.startswith("%"):
+ self.text += "\n"
+
+ def remove_all_whitespaces(self):
+ new_text = ""
+ in_string = False
+ in_section = False
+ for i, cha in enumerate(self.text):
+ if in_section:
+ if cha != '"' and self.text[i-1] != '\\':
+ new_text += cha
+ elif cha == '\n':
+ new_text += cha
+ in_section = False
+ elif i == (len(self.text)-1):
+ if cha != '"' and self.text[i-1] != '\\':
+ new_text += cha
+ in_section = False
+ elif not in_section and (i == 0 or self.text[i-1] == '\n') and cha == '%':
+ in_section = True
+ new_text += cha
+ elif in_string or cha not in [' ', '\n', '\t']:
+ new_text += cha
+ elif cha == '"' and self.text[i-1] != '\\':
+ in_string = not in_string
+ self.text = new_text
+
+ def stream(self):
+ return self.text[self.pos:]
+
+ def parse_block_name(self):
+ idx = self.stream().find('{')
+ if idx == -1:
+ raise Exception("Cannot find block name")
+ block_name = self.stream()[:idx]
+ self.pos += idx+1
+ return block_name
+
+ def parse_block_or_section(self):
+ if self.stream().startswith("%url "):
+ # section line
+ self.pos += 5
+ idx = self.stream().find('\n')
+ if idx == -1:
+ value = self.stream()
+ self.pos += len(self.stream())
+ else:
+ value = self.stream()[:idx]
+ self.pos += idx+1
+ block_dict = {'block_name': '%url', 'value': value}
+ return block_dict
+
+ block_name = self.parse_block_name().upper()
+ block_dict = {'block_name': block_name}
+ self.parse_block_body(block_dict)
+ if self.stream()[0] != '}':
+ raise Exception("No closing bracket '}' found at the end of block")
+ self.pos += 1
+ return block_dict
+
+ def parse_parameter_value(self, raw_value):
+ colon_idx = raw_value.find(',')
+
+ if colon_idx == -1:
+ try:
+ return int(raw_value)
+ except ValueError:
+ if raw_value == "true":
+ return True
+ if raw_value == "false":
+ return False
+ if raw_value.find('"') == 0:
+ return raw_value[1:-1]
+ return raw_value
+ else:
+ return [self.parse_parameter_value(v.strip())
+ for v in raw_value.split(',')]
+
+ def parse_stanza(self, block_dict):
+ equal_idx = self.stream().find('=')
+ semicolon_idx = self.stream().find(';')
+ if equal_idx == -1:
+ raise Exception("Malformed stanza: no equal symbol found.")
+ parameter_name = self.stream()[:equal_idx].lower()
+ parameter_value = self.stream()[equal_idx+1:semicolon_idx]
+ block_dict[parameter_name] = self.parse_parameter_value(
+ parameter_value)
+ self.pos += semicolon_idx+1
+
+ def parse_block_body(self, block_dict):
+ last_pos = self.pos
+ while True:
+ semicolon_idx = self.stream().find(';')
+ lbracket_idx = self.stream().find('{')
+ rbracket_idx = self.stream().find('}')
+
+ if rbracket_idx == 0:
+ # block end
+ return
+
+ if (semicolon_idx != -1 and lbracket_idx != -1
+ and semicolon_idx < lbracket_idx) \
+ or (semicolon_idx != -1 and lbracket_idx == -1):
+ self.parse_stanza(block_dict)
+ elif (semicolon_idx != -1 and lbracket_idx != -1
+ and semicolon_idx > lbracket_idx) or (
+ semicolon_idx == -1 and lbracket_idx != -1):
+ if '_blocks_' not in block_dict:
+ block_dict['_blocks_'] = []
+ block_dict['_blocks_'].append(self.parse_block_or_section())
+ else:
+ raise Exception("Malformed stanza: no semicolon found.")
+
+ if last_pos == self.pos:
+ raise Exception("Infinite loop while parsing block content")
+ last_pos = self.pos
+
+ def parse(self):
+ self.remove_all_whitespaces()
+ blocks = []
+ while self.stream():
+ block_dict = self.parse_block_or_section()
+ blocks.append(block_dict)
+ return blocks
+
+ @staticmethod
+ def _indentation(depth, size=4):
+ conf_str = ""
+ for _ in range(0, depth*size):
+ conf_str += " "
+ return conf_str
+
+ @staticmethod
+ def write_block_body(block, depth=0):
+ def format_val(key, val):
+ if isinstance(val, list):
+ return ', '.join([format_val(key, v) for v in val])
+ if isinstance(val, bool):
+ return str(val).lower()
+ if isinstance(val, int) or (block['block_name'] == 'CLIENT'
+ and key == 'clients'):
+ return '{}'.format(val)
+ return '"{}"'.format(val)
+
+ conf_str = ""
+ for key, val in block.items():
+ if key == 'block_name':
+ continue
+ elif key == '_blocks_':
+ for blo in val:
+ conf_str += GaneshaConfParser.write_block(blo, depth)
+ elif val:
+ conf_str += GaneshaConfParser._indentation(depth)
+ conf_str += '{} = {};\n'.format(key, format_val(key, val))
+ return conf_str
+
+ @staticmethod
+ def write_block(block, depth):
+ if block['block_name'] == "%url":
+ return '%url "{}"\n\n'.format(block['value'])
+
+ conf_str = ""
+ conf_str += GaneshaConfParser._indentation(depth)
+ conf_str += format(block['block_name'])
+ conf_str += " {\n"
+ conf_str += GaneshaConfParser.write_block_body(block, depth+1)
+ conf_str += GaneshaConfParser._indentation(depth)
+ conf_str += "}\n\n"
+ return conf_str
+
+ @staticmethod
+ def write_conf(blocks):
+ if not isinstance(blocks, list):
+ blocks = [blocks]
+ conf_str = ""
+ for block in blocks:
+ conf_str += GaneshaConfParser.write_block(block, 0)
+ return conf_str
+
+
+class FSal(object):
+ def __init__(self, name):
+ self.name = name
+
+ @classmethod
+ def validate_path(cls, _):
+ raise NotImplementedError()
+
+ def validate(self):
+ raise NotImplementedError()
+
+ def fill_keys(self):
+ raise NotImplementedError()
+
+ def create_path(self, path):
+ raise NotImplementedError()
+
+ @staticmethod
+ def from_fsal_block(fsal_block):
+ if fsal_block['name'] == "CEPH":
+ return CephFSFSal.from_fsal_block(fsal_block)
+ if fsal_block['name'] == 'RGW':
+ return RGWFSal.from_fsal_block(fsal_block)
+ return None
+
+ def to_fsal_block(self):
+ raise NotImplementedError()
+
+ @staticmethod
+ def from_dict(fsal_dict):
+ if fsal_dict['name'] == "CEPH":
+ return CephFSFSal.from_dict(fsal_dict)
+ if fsal_dict['name'] == 'RGW':
+ return RGWFSal.from_dict(fsal_dict)
+ return None
+
+ def to_dict(self):
+ raise NotImplementedError()
+
+
+class RGWFSal(FSal):
+ def __init__(self, name, rgw_user_id, access_key, secret_key):
+ super(RGWFSal, self).__init__(name)
+ self.rgw_user_id = rgw_user_id
+ self.access_key = access_key
+ self.secret_key = secret_key
+
+ @classmethod
+ def validate_path(cls, path):
+ return path == "/" or re.match(r'^[^/><|&()#?]+$', path)
+
+ def validate(self):
+ if not self.rgw_user_id:
+ raise NFSException('RGW user must be specified')
+
+ if not RgwClient.admin_instance().user_exists(self.rgw_user_id):
+ raise NFSException("RGW user '{}' does not exist"
+ .format(self.rgw_user_id))
+
+ def fill_keys(self):
+ keys = RgwClient.admin_instance().get_user_keys(self.rgw_user_id)
+ self.access_key = keys['access_key']
+ self.secret_key = keys['secret_key']
+
+ def create_path(self, path):
+ if path == '/': # nothing to do
+ return
+ rgw = RgwClient.instance(self.rgw_user_id)
+ try:
+ exists = rgw.bucket_exists(path, self.rgw_user_id)
+ logger.debug('Checking existence of RGW bucket "%s" for user "%s": %s',
+ path, self.rgw_user_id, exists)
+ except RequestException as exp:
+ if exp.status_code == 403:
+ raise NFSException('Cannot create bucket "{}" as it already '
+ 'exists, and belongs to other user.'
+ .format(path))
+ else:
+ raise exp
+ if not exists:
+ logger.info('Creating new RGW bucket "%s" for user "%s"', path,
+ self.rgw_user_id)
+ rgw.create_bucket(path)
+
+ @classmethod
+ def from_fsal_block(cls, fsal_block):
+ return cls(fsal_block['name'],
+ fsal_block['user_id'],
+ fsal_block['access_key_id'],
+ fsal_block['secret_access_key'])
+
+ def to_fsal_block(self):
+ return {
+ 'block_name': 'FSAL',
+ 'name': self.name,
+ 'user_id': self.rgw_user_id,
+ 'access_key_id': self.access_key,
+ 'secret_access_key': self.secret_key
+ }
+
+ @classmethod
+ def from_dict(cls, fsal_dict):
+ return cls(fsal_dict['name'], fsal_dict['rgw_user_id'], None, None)
+
+ def to_dict(self):
+ return {
+ 'name': self.name,
+ 'rgw_user_id': self.rgw_user_id
+ }
+
+
+class CephFSFSal(FSal):
+ def __init__(self, name, user_id=None, fs_name=None, sec_label_xattr=None,
+ cephx_key=None):
+ super(CephFSFSal, self).__init__(name)
+ self.fs_name = fs_name
+ self.user_id = user_id
+ self.sec_label_xattr = sec_label_xattr
+ self.cephx_key = cephx_key
+
+ @classmethod
+ def validate_path(cls, path):
+ return re.match(r'^/[^><|&()?]*$', path)
+
+ def validate(self):
+ if self.user_id and self.user_id not in CephX.list_clients():
+ raise NFSException("cephx user '{}' does not exist"
+ .format(self.user_id))
+
+ def fill_keys(self):
+ if self.user_id:
+ self.cephx_key = CephX.get_client_key(self.user_id)
+
+ def create_path(self, path):
+ cfs = CephFS()
+ if not cfs.dir_exists(path):
+ cfs.mkdirs(path)
+
+ @classmethod
+ def from_fsal_block(cls, fsal_block):
+ return cls(fsal_block['name'],
+ fsal_block.get('user_id', None),
+ fsal_block.get('filesystem', None),
+ fsal_block.get('sec_label_xattr', None),
+ fsal_block.get('secret_access_key', None))
+
+ def to_fsal_block(self):
+ result = {
+ 'block_name': 'FSAL',
+ 'name': self.name,
+ }
+ if self.user_id:
+ result['user_id'] = self.user_id
+ if self.fs_name:
+ result['filesystem'] = self.fs_name
+ if self.sec_label_xattr:
+ result['sec_label_xattr'] = self.sec_label_xattr
+ if self.cephx_key:
+ result['secret_access_key'] = self.cephx_key
+ return result
+
+ @classmethod
+ def from_dict(cls, fsal_dict):
+ return cls(fsal_dict['name'], fsal_dict['user_id'],
+ fsal_dict['fs_name'], fsal_dict['sec_label_xattr'], None)
+
+ def to_dict(self):
+ return {
+ 'name': self.name,
+ 'user_id': self.user_id,
+ 'fs_name': self.fs_name,
+ 'sec_label_xattr': self.sec_label_xattr
+ }
+
+
+class Client(object):
+ def __init__(self, addresses, access_type=None, squash=None):
+ self.addresses = addresses
+ self.access_type = access_type
+ self.squash = GaneshaConf.format_squash(squash)
+
+ @classmethod
+ def from_client_block(cls, client_block):
+ addresses = client_block['clients']
+ if not isinstance(addresses, list):
+ addresses = [addresses]
+ return cls(addresses,
+ client_block.get('access_type', None),
+ client_block.get('squash', None))
+
+ def to_client_block(self):
+ result = {
+ 'block_name': 'CLIENT',
+ 'clients': self.addresses,
+ }
+ if self.access_type:
+ result['access_type'] = self.access_type
+ if self.squash:
+ result['squash'] = self.squash
+ return result
+
+ @classmethod
+ def from_dict(cls, client_dict):
+ return cls(client_dict['addresses'], client_dict['access_type'],
+ client_dict['squash'])
+
+ def to_dict(self):
+ return {
+ 'addresses': self.addresses,
+ 'access_type': self.access_type,
+ 'squash': self.squash
+ }
+
+
+class Export(object):
+ # pylint: disable=R0902
+ def __init__(self, export_id, path, fsal, cluster_id, daemons, pseudo=None,
+ tag=None, access_type=None, squash=None,
+ attr_expiration_time=None, security_label=False,
+ protocols=None, transports=None, clients=None):
+ self.export_id = export_id
+ self.path = GaneshaConf.format_path(path)
+ self.fsal = fsal
+ self.cluster_id = cluster_id
+ self.daemons = set(daemons)
+ self.pseudo = GaneshaConf.format_path(pseudo)
+ self.tag = tag
+ self.access_type = access_type
+ self.squash = GaneshaConf.format_squash(squash)
+ if attr_expiration_time is None:
+ self.attr_expiration_time = 0
+ else:
+ self.attr_expiration_time = attr_expiration_time
+ self.security_label = security_label
+ self.protocols = {GaneshaConf.format_protocol(p) for p in protocols}
+ self.transports = set(transports)
+ self.clients = clients
+
+ def validate(self, daemons_list):
+ # pylint: disable=R0912
+ for daemon_id in self.daemons:
+ if daemon_id not in daemons_list:
+ raise NFSException("Daemon '{}' does not exist"
+ .format(daemon_id))
+
+ if not self.fsal.validate_path(self.path):
+ raise NFSException("Export path ({}) is invalid.".format(self.path))
+
+ if not self.protocols:
+ raise NFSException(
+ "No NFS protocol version specified for the export.")
+
+ if not self.transports:
+ raise NFSException(
+ "No network transport type specified for the export.")
+
+ for t in self.transports:
+ match = re.match(r'^TCP$|^UDP$', t)
+ if not match:
+ raise NFSException(
+ "'{}' is an invalid network transport type identifier"
+ .format(t))
+
+ self.fsal.validate()
+
+ if 4 in self.protocols:
+ if not self.pseudo:
+ raise NFSException(
+ "Pseudo path is required when NFSv4 protocol is used")
+ match = re.match(r'^/[^><|&()]*$', self.pseudo)
+ if not match:
+ raise NFSException(
+ "Export pseudo path ({}) is invalid".format(self.pseudo))
+
+ if self.tag:
+ match = re.match(r'^[^/><|:&()]+$', self.tag)
+ if not match:
+ raise NFSException(
+ "Export tag ({}) is invalid".format(self.tag))
+
+ if self.fsal.name == 'RGW' and 4 not in self.protocols and not self.tag:
+ raise NFSException(
+ "Tag is mandatory for RGW export when using only NFSv3")
+
+ @classmethod
+ def from_export_block(cls, export_block, cluster_id, defaults):
+ logger.debug("[NFS] parsing export block: %s", export_block)
+
+ fsal_block = [b for b in export_block['_blocks_']
+ if b['block_name'] == "FSAL"]
+
+ protocols = export_block.get('protocols', defaults['protocols'])
+ if not isinstance(protocols, list):
+ protocols = [protocols]
+
+ transports = export_block.get('transports', defaults['transports'])
+ if not isinstance(transports, list):
+ transports = [transports]
+
+ client_blocks = [b for b in export_block['_blocks_']
+ if b['block_name'] == "CLIENT"]
+
+ return cls(export_block['export_id'],
+ export_block['path'],
+ FSal.from_fsal_block(fsal_block[0]),
+ cluster_id,
+ [],
+ export_block.get('pseudo', None),
+ export_block.get('tag', None),
+ export_block.get('access_type', defaults['access_type']),
+ export_block.get('squash', defaults['squash']),
+ export_block.get('attr_expiration_time', None),
+ export_block.get('security_label', False),
+ protocols,
+ transports,
+ [Client.from_client_block(client)
+ for client in client_blocks])
+
+ def to_export_block(self, defaults):
+ # pylint: disable=too-many-branches
+ result = {
+ 'block_name': 'EXPORT',
+ 'export_id': self.export_id,
+ 'path': self.path
+ }
+ if self.pseudo:
+ result['pseudo'] = self.pseudo
+ if self.tag:
+ result['tag'] = self.tag
+ if 'access_type' not in defaults \
+ or self.access_type != defaults['access_type']:
+ result['access_type'] = self.access_type
+ if 'squash' not in defaults or self.squash != defaults['squash']:
+ result['squash'] = self.squash
+ if self.fsal.name == 'CEPH':
+ result['attr_expiration_time'] = self.attr_expiration_time
+ result['security_label'] = self.security_label
+ if 'protocols' not in defaults:
+ result['protocols'] = [p for p in self.protocols]
+ else:
+ def_proto = defaults['protocols']
+ if not isinstance(def_proto, list):
+ def_proto = set([def_proto])
+ if self.protocols != def_proto:
+ result['protocols'] = [p for p in self.protocols]
+ if 'transports' not in defaults:
+ result['transports'] = [t for t in self.transports]
+ else:
+ def_transp = defaults['transports']
+ if not isinstance(def_transp, list):
+ def_transp = set([def_transp])
+ if self.transports != def_transp:
+ result['transports'] = [t for t in self.transports]
+
+ result['_blocks_'] = [self.fsal.to_fsal_block()]
+ result['_blocks_'].extend([client.to_client_block()
+ for client in self.clients])
+ return result
+
+ @classmethod
+ def from_dict(cls, export_id, ex_dict, old_export=None):
+ return cls(export_id,
+ ex_dict['path'],
+ FSal.from_dict(ex_dict['fsal']),
+ ex_dict['cluster_id'],
+ ex_dict['daemons'],
+ ex_dict['pseudo'],
+ ex_dict['tag'],
+ ex_dict['access_type'],
+ ex_dict['squash'],
+ old_export.attr_expiration_time if old_export else None,
+ ex_dict['security_label'],
+ ex_dict['protocols'],
+ ex_dict['transports'],
+ [Client.from_dict(client) for client in ex_dict['clients']])
+
+ def to_dict(self):
+ return {
+ 'export_id': self.export_id,
+ 'path': self.path,
+ 'fsal': self.fsal.to_dict(),
+ 'cluster_id': self.cluster_id,
+ 'daemons': sorted([d for d in self.daemons]),
+ 'pseudo': self.pseudo,
+ 'tag': self.tag,
+ 'access_type': self.access_type,
+ 'squash': self.squash,
+ 'security_label': self.security_label,
+ 'protocols': sorted([p for p in self.protocols]),
+ 'transports': sorted([t for t in self.transports]),
+ 'clients': [client.to_dict() for client in self.clients]
+ }
+
+
+class GaneshaConf(object):
+ # pylint: disable=R0902
+
+ def __init__(self, cluster_id, rados_pool, rados_namespace):
+ self.cluster_id = cluster_id
+ self.rados_pool = rados_pool
+ self.rados_namespace = rados_namespace
+ self.export_conf_blocks = []
+ self.daemons_conf_blocks = {}
+ self._defaults = {}
+ self.exports = {}
+
+ self._read_raw_config()
+
+ # load defaults
+ def_block = [b for b in self.export_conf_blocks
+ if b['block_name'] == "EXPORT_DEFAULTS"]
+ self.export_defaults = def_block[0] if def_block else {}
+ self._defaults = self.ganesha_defaults(self.export_defaults)
+
+ for export_block in [block for block in self.export_conf_blocks
+ if block['block_name'] == "EXPORT"]:
+ export = Export.from_export_block(export_block, cluster_id,
+ self._defaults)
+ self.exports[export.export_id] = export
+
+ # link daemons to exports
+ for daemon_id, daemon_blocks in self.daemons_conf_blocks.items():
+ for block in daemon_blocks:
+ if block['block_name'] == "%url":
+ rados_url = block['value']
+ _, _, obj = Ganesha.parse_rados_url(rados_url)
+ if obj.startswith("export-"):
+ export_id = int(obj[obj.find('-')+1:])
+ self.exports[export_id].daemons.add(daemon_id)
+
+ @classmethod
+ def instance(cls, cluster_id):
+ pool, ns = Ganesha.get_pool_and_namespace(cluster_id)
+ return cls(cluster_id, pool, ns)
+
+ def _read_raw_config(self):
+ with mgr.rados.open_ioctx(self.rados_pool) as ioctx:
+ if self.rados_namespace:
+ ioctx.set_namespace(self.rados_namespace)
+ objs = ioctx.list_objects()
+ for obj in objs:
+ if obj.key.startswith("export-"):
+ size, _ = obj.stat()
+ raw_config = obj.read(size)
+ raw_config = raw_config.decode("utf-8")
+ logger.debug("[NFS] read export configuration from rados "
+ "object %s/%s/%s:\n%s", self.rados_pool,
+ self.rados_namespace, obj.key, raw_config)
+ self.export_conf_blocks.extend(
+ GaneshaConfParser(raw_config).parse())
+ elif obj.key.startswith("conf-"):
+ size, _ = obj.stat()
+ raw_config = obj.read(size)
+ raw_config = raw_config.decode("utf-8")
+ logger.debug("[NFS] read daemon configuration from rados "
+ "object %s/%s/%s:\n%s", self.rados_pool,
+ self.rados_namespace, obj.key, raw_config)
+ idx = obj.key.find('-')
+ self.daemons_conf_blocks[obj.key[idx+1:]] = \
+ GaneshaConfParser(raw_config).parse()
+
+ def _write_raw_config(self, conf_block, obj):
+ raw_config = GaneshaConfParser.write_conf(conf_block)
+ with mgr.rados.open_ioctx(self.rados_pool) as ioctx:
+ if self.rados_namespace:
+ ioctx.set_namespace(self.rados_namespace)
+ ioctx.write_full(obj, raw_config.encode('utf-8'))
+ logger.debug(
+ "[NFS] write configuration into rados object %s/%s/%s:\n%s",
+ self.rados_pool, self.rados_namespace, obj, raw_config)
+
+ @classmethod
+ def ganesha_defaults(cls, export_defaults):
+ """
+ According to
+ https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/config_samples/export.txt
+ """
+ return {
+ 'access_type': export_defaults.get('access_type', 'NONE'),
+ 'protocols': export_defaults.get('protocols', [3, 4]),
+ 'transports': export_defaults.get('transports', ['TCP', 'UDP']),
+ 'squash': export_defaults.get('squash', 'root_squash')
+ }
+
+ @classmethod
+ def format_squash(cls, squash):
+ if squash is None:
+ return None
+ if squash.lower() in ["no_root_squash", "noidsquash", "none"]:
+ return "no_root_squash"
+ if squash.lower() in ["rootid", "root_id_squash", "rootidsquash"]:
+ return "root_id_squash"
+ if squash.lower() in ["root", "root_squash", "rootsquash"]:
+ return "root_squash"
+ if squash.lower() in ["all", "all_squash", "allsquash",
+ "all_anonymous", "allanonymous"]:
+ return "all_squash"
+ logger.error("[NFS] could not parse squash value: %s", squash)
+ raise NFSException("'{}' is an invalid squash option".format(squash))
+
+ @classmethod
+ def format_protocol(cls, protocol):
+ if str(protocol) in ["NFSV3", "3", "V3", "NFS3"]:
+ return 3
+ if str(protocol) in ["NFSV4", "4", "V4", "NFS4"]:
+ return 4
+ logger.error("[NFS] could not parse protocol value: %s", protocol)
+ raise NFSException("'{}' is an invalid NFS protocol version identifier"
+ .format(protocol))
+
+ @classmethod
+ def format_path(cls, path):
+ if path is not None:
+ path = path.strip()
+ if len(path) > 1 and path[-1] == '/':
+ path = path[:-1]
+ return path
+
+ def validate(self, export):
+ export.validate(self.list_daemons())
+
+ if 4 in export.protocols: # NFSv4 protocol
+ len_prefix = 1
+ parent_export = None
+ for ex in self.list_exports():
+ if export.tag and ex.tag == export.tag:
+ raise NFSException(
+ "Another export exists with the same tag: {}"
+ .format(export.tag))
+
+ if export.pseudo and ex.pseudo == export.pseudo:
+ raise NFSException(
+ "Another export exists with the same pseudo path: {}"
+ .format(export.pseudo))
+
+ if not ex.pseudo:
+ continue
+
+ if export.pseudo[:export.pseudo.rfind('/')+1].startswith(ex.pseudo):
+ if export.pseudo[len(ex.pseudo)] == '/':
+ if len(ex.pseudo) > len_prefix:
+ len_prefix = len(ex.pseudo)
+ parent_export = ex
+
+ if len_prefix > 1:
+ # validate pseudo path
+ idx = len(parent_export.pseudo)
+ idx = idx + 1 if idx > 1 else idx
+ real_path = "{}/{}".format(parent_export.path
+ if len(parent_export.path) > 1 else "",
+ export.pseudo[idx:])
+ if export.fsal.name == 'CEPH':
+ cfs = CephFS()
+ if export.path != real_path and not cfs.dir_exists(real_path):
+ raise NFSException(
+ "Pseudo path ({}) invalid, path {} does not exist."
+ .format(export.pseudo, real_path))
+
+ def _gen_export_id(self):
+ exports = sorted(self.exports)
+ nid = 1
+ for e_id in exports:
+ if e_id == nid:
+ nid += 1
+ else:
+ break
+ return nid
+
+ def _persist_daemon_configuration(self):
+ daemon_map = {}
+ for daemon_id in self.list_daemons():
+ daemon_map[daemon_id] = []
+
+ for _, ex in self.exports.items():
+ for daemon in ex.daemons:
+ daemon_map[daemon].append({
+ 'block_name': "%url",
+ 'value': Ganesha.make_rados_url(
+ self.rados_pool, self.rados_namespace,
+ "export-{}".format(ex.export_id))
+ })
+ for daemon_id, conf_blocks in daemon_map.items():
+ self._write_raw_config(conf_blocks, "conf-{}".format(daemon_id))
+
+ def _save_export(self, export):
+ self.validate(export)
+ export.fsal.create_path(export.path)
+ export.fsal.fill_keys()
+ self.exports[export.export_id] = export
+ conf_block = export.to_export_block(self.export_defaults)
+ self._write_raw_config(conf_block, "export-{}".format(export.export_id))
+ self._persist_daemon_configuration()
+
+ def _delete_export(self, export_id):
+ self._persist_daemon_configuration()
+ with mgr.rados.open_ioctx(self.rados_pool) as ioctx:
+ if self.rados_namespace:
+ ioctx.set_namespace(self.rados_namespace)
+ ioctx.remove_object("export-{}".format(export_id))
+
+ def list_exports(self):
+ return [ex for _, ex in self.exports.items()]
+
+ def create_export(self, ex_dict):
+ ex_id = self._gen_export_id()
+ export = Export.from_dict(ex_id, ex_dict)
+ self._save_export(export)
+ return ex_id
+
+ def has_export(self, export_id):
+ return export_id in self.exports
+
+ def update_export(self, ex_dict):
+ if ex_dict['export_id'] not in self.exports:
+ return None
+ old_export = self.exports[ex_dict['export_id']]
+ del self.exports[ex_dict['export_id']]
+ export = Export.from_dict(ex_dict['export_id'], ex_dict, old_export)
+ self._save_export(export)
+ self.exports[export.export_id] = export
+ return old_export
+
+ def remove_export(self, export_id):
+ if export_id not in self.exports:
+ return None
+ export = self.exports[export_id]
+ del self.exports[export_id]
+ self._delete_export(export_id)
+ return export
+
+ def get_export(self, export_id):
+ if export_id in self.exports:
+ return self.exports[export_id]
+ return None
+
+ def list_daemons(self):
+ return [daemon_id for daemon_id in self.daemons_conf_blocks]
+
+ def reload_daemons(self, daemons):
+ with mgr.rados.open_ioctx(self.rados_pool) as ioctx:
+ if self.rados_namespace:
+ ioctx.set_namespace(self.rados_namespace)
+ for daemon_id in daemons:
+ ioctx.notify("conf-{}".format(daemon_id))
diff --git a/src/pybind/mgr/dashboard/services/iscsi_cli.py b/src/pybind/mgr/dashboard/services/iscsi_cli.py
new file mode 100644
index 00000000..f962de59
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/iscsi_cli.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import errno
+import json
+
+from mgr_module import CLICheckNonemptyFileInput, CLIReadCommand, CLIWriteCommand
+
+from .iscsi_client import IscsiClient
+from .iscsi_config import IscsiGatewaysConfig, IscsiGatewayAlreadyExists, InvalidServiceUrl, \
+ ManagedByOrchestratorException, IscsiGatewayDoesNotExist
+from ..rest_client import RequestException
+
+
+@CLIReadCommand('dashboard iscsi-gateway-list', desc='List iSCSI gateways')
+def list_iscsi_gateways(_):
+ return 0, json.dumps(IscsiGatewaysConfig.get_gateways_config()), ''
+
+
+@CLIWriteCommand('dashboard iscsi-gateway-add',
+ desc='Add iSCSI gateway configuration. Gateway URL read from -i <file>')
+@CLICheckNonemptyFileInput
+def add_iscsi_gateway(_, inbuf):
+ service_url = inbuf
+ try:
+ IscsiGatewaysConfig.validate_service_url(service_url)
+ name = IscsiClient.instance(service_url=service_url).get_hostname()['data']
+ IscsiGatewaysConfig.add_gateway(name, service_url)
+ return 0, 'Success', ''
+ except IscsiGatewayAlreadyExists as ex:
+ return -errno.EEXIST, '', str(ex)
+ except InvalidServiceUrl as ex:
+ return -errno.EINVAL, '', str(ex)
+ except ManagedByOrchestratorException as ex:
+ return -errno.EINVAL, '', str(ex)
+ except RequestException as ex:
+ return -errno.EINVAL, '', str(ex)
+
+
+@CLIWriteCommand('dashboard iscsi-gateway-rm',
+ 'name=name,type=CephString',
+ 'Remove iSCSI gateway configuration')
+def remove_iscsi_gateway(_, name):
+ try:
+ IscsiGatewaysConfig.remove_gateway(name)
+ return 0, 'Success', ''
+ except IscsiGatewayDoesNotExist as ex:
+ return -errno.ENOENT, '', str(ex)
+ except ManagedByOrchestratorException as ex:
+ return -errno.EINVAL, '', str(ex)
diff --git a/src/pybind/mgr/dashboard/services/iscsi_client.py b/src/pybind/mgr/dashboard/services/iscsi_client.py
new file mode 100644
index 00000000..e66bd3cc
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/iscsi_client.py
@@ -0,0 +1,257 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-public-methods
+from __future__ import absolute_import
+
+import json
+
+from requests.auth import HTTPBasicAuth
+
+try:
+ from urlparse import urlparse
+except ImportError:
+ from urllib.parse import urlparse
+
+from .iscsi_config import IscsiGatewaysConfig
+from .. import logger
+from ..settings import Settings
+from ..rest_client import RestClient
+
+
+class IscsiClient(RestClient):
+ _CLIENT_NAME = 'iscsi'
+ _instances = {}
+
+ service_url = None
+ gateway_name = None
+
+ @classmethod
+ def instance(cls, gateway_name=None, service_url=None):
+ if not service_url:
+ if not gateway_name:
+ gateway_name = list(IscsiGatewaysConfig.get_gateways_config()['gateways'].keys())[0]
+ gateways_config = IscsiGatewaysConfig.get_gateway_config(gateway_name)
+ service_url = gateways_config['service_url']
+
+ instance = cls._instances.get(gateway_name)
+ if not instance or service_url != instance.service_url or \
+ instance.session.verify != Settings.ISCSI_API_SSL_VERIFICATION:
+ url = urlparse(service_url)
+ ssl = url.scheme == 'https'
+ host = url.hostname
+ port = url.port
+ username = url.username
+ password = url.password
+ if not port:
+ port = 443 if ssl else 80
+
+ auth = HTTPBasicAuth(username, password)
+ instance = IscsiClient(host, port, IscsiClient._CLIENT_NAME, ssl,
+ auth, Settings.ISCSI_API_SSL_VERIFICATION)
+ instance.service_url = service_url
+ instance.gateway_name = gateway_name
+ if gateway_name:
+ cls._instances[gateway_name] = instance
+
+ return instance
+
+ @RestClient.api_get('/api/_ping')
+ def ping(self, request=None):
+ return request()
+
+ @RestClient.api_get('/api/settings')
+ def get_settings(self, request=None):
+ return request()
+
+ @RestClient.api_get('/api/sysinfo/ip_addresses')
+ def get_ip_addresses(self, request=None):
+ return request()
+
+ @RestClient.api_get('/api/sysinfo/hostname')
+ def get_hostname(self, request=None):
+ return request()
+
+ @RestClient.api_get('/api/config')
+ def get_config(self, request=None):
+ return request({
+ 'decrypt_passwords': True
+ })
+
+ @RestClient.api_put('/api/target/{target_iqn}')
+ def create_target(self, target_iqn, target_controls, request=None):
+ logger.debug("iSCSI[%s] Creating target: %s", self.gateway_name, target_iqn)
+ return request({
+ 'controls': json.dumps(target_controls)
+ })
+
+ @RestClient.api_delete('/api/target/{target_iqn}')
+ def delete_target(self, target_iqn, request=None):
+ logger.debug("iSCSI[%s] Deleting target: %s", self.gateway_name, target_iqn)
+ return request()
+
+ @RestClient.api_put('/api/target/{target_iqn}')
+ def reconfigure_target(self, target_iqn, target_controls, request=None):
+ logger.debug("iSCSI[%s] Reconfiguring target: %s", self.gateway_name, target_iqn)
+ return request({
+ 'mode': 'reconfigure',
+ 'controls': json.dumps(target_controls)
+ })
+
+ @RestClient.api_put('/api/gateway/{target_iqn}/{gateway_name}')
+ def create_gateway(self, target_iqn, gateway_name, ip_address, request=None):
+ logger.debug("iSCSI[%s] Creating gateway: %s/%s", self.gateway_name, target_iqn,
+ gateway_name)
+ return request({
+ 'ip_address': ','.join(ip_address),
+ 'skipchecks': 'true'
+ })
+
+ @RestClient.api_get('/api/gatewayinfo')
+ def get_gatewayinfo(self, request=None):
+ return request()
+
+ @RestClient.api_delete('/api/gateway/{target_iqn}/{gateway_name}')
+ def delete_gateway(self, target_iqn, gateway_name, request=None):
+ logger.debug("iSCSI: Deleting gateway: %s/%s", target_iqn, gateway_name)
+ return request()
+
+ @RestClient.api_put('/api/disk/{pool}/{image}')
+ def create_disk(self, pool, image, backstore, wwn, request=None):
+ logger.debug("iSCSI[%s] Creating disk: %s/%s", self.gateway_name, pool, image)
+ return request({
+ 'mode': 'create',
+ 'backstore': backstore,
+ 'wwn': wwn
+ })
+
+ @RestClient.api_delete('/api/disk/{pool}/{image}')
+ def delete_disk(self, pool, image, request=None):
+ logger.debug("iSCSI[%s] Deleting disk: %s/%s", self.gateway_name, pool, image)
+ return request({
+ 'preserve_image': 'true'
+ })
+
+ @RestClient.api_put('/api/disk/{pool}/{image}')
+ def reconfigure_disk(self, pool, image, controls, request=None):
+ logger.debug("iSCSI[%s] Reconfiguring disk: %s/%s", self.gateway_name, pool, image)
+ return request({
+ 'controls': json.dumps(controls),
+ 'mode': 'reconfigure'
+ })
+
+ @RestClient.api_put('/api/targetlun/{target_iqn}')
+ def create_target_lun(self, target_iqn, image_id, lun, request=None):
+ logger.debug("iSCSI[%s] Creating target lun: %s/%s", self.gateway_name, target_iqn,
+ image_id)
+ return request({
+ 'disk': image_id,
+ 'lun_id': lun
+ })
+
+ @RestClient.api_delete('/api/targetlun/{target_iqn}')
+ def delete_target_lun(self, target_iqn, image_id, request=None):
+ logger.debug("iSCSI[%s] Deleting target lun: %s/%s", self.gateway_name, target_iqn,
+ image_id)
+ return request({
+ 'disk': image_id
+ })
+
+ @RestClient.api_put('/api/client/{target_iqn}/{client_iqn}')
+ def create_client(self, target_iqn, client_iqn, request=None):
+ logger.debug("iSCSI[%s] Creating client: %s/%s", self.gateway_name, target_iqn, client_iqn)
+ return request()
+
+ @RestClient.api_delete('/api/client/{target_iqn}/{client_iqn}')
+ def delete_client(self, target_iqn, client_iqn, request=None):
+ logger.debug("iSCSI[%s] Deleting client: %s/%s", self.gateway_name, target_iqn, client_iqn)
+ return request()
+
+ @RestClient.api_put('/api/clientlun/{target_iqn}/{client_iqn}')
+ def create_client_lun(self, target_iqn, client_iqn, image_id, request=None):
+ logger.debug("iSCSI[%s] Creating client lun: %s/%s", self.gateway_name, target_iqn,
+ client_iqn)
+ return request({
+ 'disk': image_id
+ })
+
+ @RestClient.api_delete('/api/clientlun/{target_iqn}/{client_iqn}')
+ def delete_client_lun(self, target_iqn, client_iqn, image_id, request=None):
+ logger.debug("iSCSI[%s] Deleting client lun: %s/%s", self.gateway_name, target_iqn,
+ client_iqn)
+ return request({
+ 'disk': image_id
+ })
+
+ @RestClient.api_put('/api/clientauth/{target_iqn}/{client_iqn}')
+ def create_client_auth(self, target_iqn, client_iqn, username, password, mutual_username,
+ mutual_password, request=None):
+ logger.debug("iSCSI[%s] Creating client auth: %s/%s/%s/%s/%s/%s",
+ self.gateway_name, target_iqn, client_iqn, username, password, mutual_username,
+ mutual_password)
+ return request({
+ 'username': username,
+ 'password': password,
+ 'mutual_username': mutual_username,
+ 'mutual_password': mutual_password
+ })
+
+ @RestClient.api_put('/api/hostgroup/{target_iqn}/{group_name}')
+ def create_group(self, target_iqn, group_name, members, image_ids, request=None):
+ logger.debug("iSCSI[%s] Creating group: %s/%s", self.gateway_name, target_iqn, group_name)
+ return request({
+ 'members': ','.join(members),
+ 'disks': ','.join(image_ids)
+ })
+
+ @RestClient.api_put('/api/hostgroup/{target_iqn}/{group_name}')
+ def update_group(self, target_iqn, group_name, members, image_ids, request=None):
+ logger.debug("iSCSI[%s] Updating group: %s/%s", self.gateway_name, target_iqn, group_name)
+ return request({
+ 'action': 'remove',
+ 'members': ','.join(members),
+ 'disks': ','.join(image_ids)
+ })
+
+ @RestClient.api_delete('/api/hostgroup/{target_iqn}/{group_name}')
+ def delete_group(self, target_iqn, group_name, request=None):
+ logger.debug("iSCSI[%s] Deleting group: %s/%s", self.gateway_name, target_iqn, group_name)
+ return request()
+
+ @RestClient.api_put('/api/discoveryauth')
+ def update_discoveryauth(self, user, password, mutual_user, mutual_password, request=None):
+ logger.debug("iSCSI[%s] Updating discoveryauth: %s/%s/%s/%s", self.gateway_name, user,
+ password, mutual_user, mutual_password)
+ return request({
+ 'username': user,
+ 'password': password,
+ 'mutual_username': mutual_user,
+ 'mutual_password': mutual_password
+ })
+
+ @RestClient.api_put('/api/targetauth/{target_iqn}')
+ def update_targetacl(self, target_iqn, action, request=None):
+ logger.debug("iSCSI[%s] Updating targetacl: %s/%s", self.gateway_name, target_iqn, action)
+ return request({
+ 'action': action
+ })
+
+ @RestClient.api_put('/api/targetauth/{target_iqn}')
+ def update_targetauth(self, target_iqn, user, password, mutual_user, mutual_password,
+ request=None):
+ logger.debug("iSCSI[%s] Updating targetauth: %s/%s/%s/%s/%s", self.gateway_name,
+ target_iqn, user, password, mutual_user, mutual_password)
+ return request({
+ 'username': user,
+ 'password': password,
+ 'mutual_username': mutual_user,
+ 'mutual_password': mutual_password
+ })
+
+ @RestClient.api_get('/api/targetinfo/{target_iqn}')
+ def get_targetinfo(self, target_iqn, request=None):
+ # pylint: disable=unused-argument
+ return request()
+
+ @RestClient.api_get('/api/clientinfo/{target_iqn}/{client_iqn}')
+ def get_clientinfo(self, target_iqn, client_iqn, request=None):
+ # pylint: disable=unused-argument
+ return request()
diff --git a/src/pybind/mgr/dashboard/services/iscsi_config.py b/src/pybind/mgr/dashboard/services/iscsi_config.py
new file mode 100644
index 00000000..2f119136
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/iscsi_config.py
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+
+from orchestrator import OrchestratorError
+
+try:
+ from urlparse import urlparse
+except ImportError:
+ from urllib.parse import urlparse
+
+from mgr_util import merge_dicts
+from .orchestrator import OrchClient
+from .. import mgr
+
+
+class IscsiGatewayAlreadyExists(Exception):
+ def __init__(self, gateway_name):
+ super(IscsiGatewayAlreadyExists, self).__init__(
+ "iSCSI gateway '{}' already exists".format(gateway_name))
+
+
+class IscsiGatewayDoesNotExist(Exception):
+ def __init__(self, hostname):
+ super(IscsiGatewayDoesNotExist, self).__init__(
+ "iSCSI gateway '{}' does not exist".format(hostname))
+
+
+class InvalidServiceUrl(Exception):
+ def __init__(self, service_url):
+ super(InvalidServiceUrl, self).__init__(
+ "Invalid service URL '{}'. "
+ "Valid format: '<scheme>://<username>:<password>@<host>[:port]'.".format(service_url))
+
+
+class ManagedByOrchestratorException(Exception):
+ def __init__(self):
+ super(ManagedByOrchestratorException, self).__init__(
+ "iSCSI configuration is managed by the orchestrator")
+
+
+_ISCSI_STORE_KEY = "_iscsi_config"
+
+
+class IscsiGatewaysConfig(object):
+ @classmethod
+ def _load_config_from_store(cls):
+ json_db = mgr.get_store(_ISCSI_STORE_KEY,
+ '{"gateways": {}}')
+ config = json.loads(json_db)
+ cls.update_iscsi_config(config)
+ return config
+
+ @classmethod
+ def update_iscsi_config(cls, config):
+ """
+ Since `ceph-iscsi` config v10, gateway names were renamed from host short name to FQDN.
+ If Ceph Dashboard were configured before v10, we try to update our internal gateways
+ database automatically.
+ """
+ for gateway_name, gateway_config in config['gateways'].items():
+ if '.' not in gateway_name:
+ from .iscsi_client import IscsiClient
+ from ..rest_client import RequestException
+ try:
+ service_url = gateway_config['service_url']
+ new_gateway_name = IscsiClient.instance(
+ service_url=service_url).get_hostname()['data']
+ if gateway_name != new_gateway_name:
+ config['gateways'][new_gateway_name] = gateway_config
+ del config['gateways'][gateway_name]
+ cls._save_config(config)
+ except RequestException:
+ # If gateway is not acessible, it should be removed manually
+ # or we will try to update automatically next time
+ continue
+
+ @staticmethod
+ def _load_config_from_orchestrator():
+ config = {'gateways': {}}
+ try:
+ instances = OrchClient().list_service_info("iscsi")
+ for instance in instances:
+ config['gateways'][instance.nodename] = {
+ 'service_url': instance.service_url
+ }
+ except (RuntimeError, OrchestratorError, ImportError):
+ pass
+ return config
+
+ @classmethod
+ def _save_config(cls, config):
+ mgr.set_store(_ISCSI_STORE_KEY, json.dumps(config))
+
+ @classmethod
+ def validate_service_url(cls, service_url):
+ url = urlparse(service_url)
+ if not url.scheme or not url.hostname or not url.username or not url.password:
+ raise InvalidServiceUrl(service_url)
+
+ @classmethod
+ def add_gateway(cls, name, service_url):
+ config = cls.get_gateways_config()
+ if name in config:
+ raise IscsiGatewayAlreadyExists(name)
+ IscsiGatewaysConfig.validate_service_url(service_url)
+ config['gateways'][name] = {'service_url': service_url}
+ cls._save_config(config)
+
+ @classmethod
+ def remove_gateway(cls, name):
+ if name in cls._load_config_from_orchestrator()['gateways']:
+ raise ManagedByOrchestratorException()
+
+ config = cls._load_config_from_store()
+ if name not in config['gateways']:
+ raise IscsiGatewayDoesNotExist(name)
+
+ del config['gateways'][name]
+ cls._save_config(config)
+
+ @classmethod
+ def get_gateways_config(cls):
+ orch_config = cls._load_config_from_orchestrator()
+ local_config = cls._load_config_from_store()
+
+ return {'gateways': merge_dicts(orch_config['gateways'], local_config['gateways'])}
+
+ @classmethod
+ def get_gateway_config(cls, name):
+ config = IscsiGatewaysConfig.get_gateways_config()
+ if name not in config['gateways']:
+ raise IscsiGatewayDoesNotExist(name)
+ return config['gateways'][name]
diff --git a/src/pybind/mgr/dashboard/services/orchestrator.py b/src/pybind/mgr/dashboard/services/orchestrator.py
new file mode 100644
index 00000000..366ff7de
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/orchestrator.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from orchestrator import OrchestratorClientMixin, raise_if_exception, OrchestratorError
+from .. import mgr, logger
+
+
+# pylint: disable=abstract-method
+class OrchClient(OrchestratorClientMixin):
+ def __init__(self):
+ super(OrchClient, self).__init__()
+ self.set_mgr(mgr)
+
+ def list_service_info(self, service_type):
+ # type: (str) -> list
+ completion = self.describe_service(service_type, None, None)
+ self._orchestrator_wait([completion])
+ raise_if_exception(completion)
+ return completion.result
+
+ def available(self):
+ try:
+ status, desc = super(OrchClient, self).available()
+ logger.info("[ORCH] is orchestrator available: %s, %s", status, desc)
+ return status
+ except (RuntimeError, OrchestratorError, ImportError):
+ return False
+
+ def reload_service(self, service_type, service_ids):
+ if not isinstance(service_ids, list):
+ service_ids = [service_ids]
+
+ completion_list = [self.service_action('reload', service_type,
+ service_name, service_id)
+ for service_name, service_id in service_ids]
+ self._orchestrator_wait(completion_list)
+ for c in completion_list:
+ raise_if_exception(c)
diff --git a/src/pybind/mgr/dashboard/services/rbd.py b/src/pybind/mgr/dashboard/services/rbd.py
new file mode 100644
index 00000000..55c6f542
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/rbd.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import six
+
+import rbd
+
+from .. import mgr
+from .ceph_service import CephService
+
+
+RBD_FEATURES_NAME_MAPPING = {
+ rbd.RBD_FEATURE_LAYERING: "layering",
+ rbd.RBD_FEATURE_STRIPINGV2: "striping",
+ rbd.RBD_FEATURE_EXCLUSIVE_LOCK: "exclusive-lock",
+ rbd.RBD_FEATURE_OBJECT_MAP: "object-map",
+ rbd.RBD_FEATURE_FAST_DIFF: "fast-diff",
+ rbd.RBD_FEATURE_DEEP_FLATTEN: "deep-flatten",
+ rbd.RBD_FEATURE_JOURNALING: "journaling",
+ rbd.RBD_FEATURE_DATA_POOL: "data-pool",
+ rbd.RBD_FEATURE_OPERATIONS: "operations",
+}
+
+
+def format_bitmask(features):
+ """
+ Formats the bitmask:
+
+ >>> format_bitmask(45)
+ ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
+ """
+ names = [val for key, val in RBD_FEATURES_NAME_MAPPING.items()
+ if key & features == key]
+ return sorted(names)
+
+
+def format_features(features):
+ """
+ Converts the features list to bitmask:
+
+ >>> format_features(['deep-flatten', 'exclusive-lock', 'layering', 'object-map'])
+ 45
+
+ >>> format_features(None) is None
+ True
+
+ >>> format_features('deep-flatten, exclusive-lock')
+ 32
+ """
+ if isinstance(features, six.string_types):
+ features = features.split(',')
+
+ if not isinstance(features, list):
+ return None
+
+ res = 0
+ for key, value in RBD_FEATURES_NAME_MAPPING.items():
+ if value in features:
+ res = key | res
+ return res
+
+
+class RbdConfiguration(object):
+ _rbd = rbd.RBD()
+
+ def __init__(self, pool_name='', image_name='', pool_ioctx=None, image_ioctx=None):
+ # type: (str, str, object, object) -> None
+ assert bool(pool_name) != bool(pool_ioctx) # xor
+ self._pool_name = pool_name
+ self._image_name = image_name
+ self._pool_ioctx = pool_ioctx
+ self._image_ioctx = image_ioctx
+
+ @staticmethod
+ def _ensure_prefix(option):
+ # type: (str) -> str
+ return option if option.startswith('conf_') else 'conf_' + option
+
+ def list(self):
+ # type: () -> [dict]
+ def _list(ioctx):
+ if self._image_name: # image config
+ try:
+ with rbd.Image(ioctx, self._image_name) as image:
+ result = image.config_list()
+ except rbd.ImageNotFound:
+ result = []
+ else: # pool config
+ pg_status = list(CephService.get_pool_pg_status(self._pool_name).keys())
+ if len(pg_status) == 1 and 'incomplete' in pg_status[0]:
+ # If config_list would be called with ioctx if it's a bad pool,
+ # the dashboard would stop working, waiting for the response
+ # that would not happen.
+ #
+ # This is only a workaround for https://tracker.ceph.com/issues/43771 which
+ # already got rejected as not worth the effort.
+ #
+ # Are more complete workaround for the dashboard will be implemented with
+ # https://tracker.ceph.com/issues/44224
+ #
+ # @TODO: If #44224 is addressed remove this workaround
+ return []
+ result = self._rbd.config_list(ioctx)
+ return list(result)
+
+ if self._pool_name:
+ ioctx = mgr.rados.open_ioctx(self._pool_name)
+ else:
+ ioctx = self._pool_ioctx
+
+ return _list(ioctx)
+
+ def get(self, option_name):
+ # type: (str) -> str
+ option_name = self._ensure_prefix(option_name)
+ with mgr.rados.open_ioctx(self._pool_name) as pool_ioctx:
+ if self._image_name:
+ with rbd.Image(pool_ioctx, self._image_name) as image:
+ return image.metadata_get(option_name)
+ return self._rbd.pool_metadata_get(pool_ioctx, option_name)
+
+ def set(self, option_name, option_value):
+ # type: (str, str) -> None
+
+ option_value = str(option_value)
+ option_name = self._ensure_prefix(option_name)
+
+ pool_ioctx = self._pool_ioctx
+ if self._pool_name: # open ioctx
+ pool_ioctx = mgr.rados.open_ioctx(self._pool_name)
+ pool_ioctx.__enter__()
+
+ image_ioctx = self._image_ioctx
+ if self._image_name:
+ image_ioctx = rbd.Image(pool_ioctx, self._image_name)
+ image_ioctx.__enter__()
+
+ if image_ioctx:
+ image_ioctx.metadata_set(option_name, option_value)
+ else:
+ self._rbd.pool_metadata_set(pool_ioctx, option_name, option_value)
+
+ if self._image_name: # Name provided, so we opened it and now have to close it
+ image_ioctx.__exit__(None, None, None)
+ if self._pool_name:
+ pool_ioctx.__exit__(None, None, None)
+
+ def remove(self, option_name):
+ """
+ Removes an option by name. Will not raise an error, if the option hasn't been found.
+ :type option_name str
+ """
+ def _remove(ioctx):
+ try:
+ if self._image_name:
+ with rbd.Image(ioctx, self._image_name) as image:
+ image.metadata_remove(option_name)
+ else:
+ self._rbd.pool_metadata_remove(ioctx, option_name)
+ except KeyError:
+ pass
+
+ option_name = self._ensure_prefix(option_name)
+
+ if self._pool_name:
+ with mgr.rados.open_ioctx(self._pool_name) as pool_ioctx:
+ _remove(pool_ioctx)
+ else:
+ _remove(self._pool_ioctx)
+
+ def set_configuration(self, configuration):
+ if configuration:
+ for option_name, option_value in configuration.items():
+ if option_value is not None:
+ self.set(option_name, option_value)
+ else:
+ self.remove(option_name)
diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py
new file mode 100644
index 00000000..eef11794
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/rgw_client.py
@@ -0,0 +1,437 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import re
+from distutils.util import strtobool
+from ..awsauth import S3Auth
+from ..settings import Settings, Options
+from ..rest_client import RestClient, RequestException
+from ..tools import build_url, dict_contains_path, is_valid_ip_address
+from .. import mgr, logger
+
+
+class NoCredentialsException(RequestException):
+ def __init__(self):
+ super(NoCredentialsException, self).__init__(
+ 'No RGW credentials found, '
+ 'please consult the documentation on how to enable RGW for '
+ 'the dashboard.')
+
+
+def _determine_rgw_addr():
+ """
+ Get a RGW daemon to determine the configured host (IP address) and port.
+ Note, the service id of the RGW daemons may differ depending on the setup.
+ Example 1:
+ {
+ ...
+ 'services': {
+ 'rgw': {
+ 'daemons': {
+ 'summary': '',
+ '0': {
+ ...
+ 'addr': '[2001:db8:85a3::8a2e:370:7334]:49774/1534999298',
+ 'metadata': {
+ 'frontend_config#0': 'civetweb port=7280',
+ }
+ ...
+ }
+ }
+ }
+ }
+ }
+ Example 2:
+ {
+ ...
+ 'services': {
+ 'rgw': {
+ 'daemons': {
+ 'summary': '',
+ 'rgw': {
+ ...
+ 'addr': '192.168.178.3:49774/1534999298',
+ 'metadata': {
+ 'frontend_config#0': 'civetweb port=8000',
+ }
+ ...
+ }
+ }
+ }
+ }
+ }
+ """
+ service_map = mgr.get('service_map')
+ if not dict_contains_path(service_map, ['services', 'rgw', 'daemons']):
+ raise LookupError('No RGW found')
+ daemon = None
+ daemons = service_map['services']['rgw']['daemons']
+ for key in daemons.keys():
+ if dict_contains_path(daemons[key], ['metadata', 'frontend_config#0']):
+ daemon = daemons[key]
+ break
+ if daemon is None:
+ raise LookupError('No RGW daemon found')
+
+ addr = _parse_addr(daemon['addr'])
+ port, ssl = _parse_frontend_config(daemon['metadata']['frontend_config#0'])
+
+ logger.info('Auto-detected RGW configuration: addr=%s, port=%d, ssl=%s',
+ addr, port, str(ssl))
+
+ return addr, port, ssl
+
+
+def _parse_addr(value):
+ """
+ Get the IP address the RGW is running on.
+
+ >>> _parse_addr('192.168.178.3:49774/1534999298')
+ '192.168.178.3'
+
+ >>> _parse_addr('[2001:db8:85a3::8a2e:370:7334]:49774/1534999298')
+ '2001:db8:85a3::8a2e:370:7334'
+
+ >>> _parse_addr('xyz')
+ Traceback (most recent call last):
+ ...
+ LookupError: Failed to determine RGW address
+
+ >>> _parse_addr('192.168.178.a:8080/123456789')
+ Traceback (most recent call last):
+ ...
+ LookupError: Invalid RGW address '192.168.178.a' found
+
+ >>> _parse_addr('[2001:0db8:1234]:443/123456789')
+ Traceback (most recent call last):
+ ...
+ LookupError: Invalid RGW address '2001:0db8:1234' found
+
+ >>> _parse_addr('2001:0db8::1234:49774/1534999298')
+ Traceback (most recent call last):
+ ...
+ LookupError: Failed to determine RGW address
+
+ :param value: The string to process. The syntax is '<HOST>:<PORT>/<NONCE>'.
+ :type: str
+ :raises LookupError if parsing fails to determine the IP address.
+ :return: The IP address.
+ :rtype: str
+ """
+ match = re.search(r'^(\[)?(?(1)([^\]]+)\]|([^:]+)):\d+/\d+?', value)
+ if match:
+ # IPv4:
+ # Group 0: 192.168.178.3:49774/1534999298
+ # Group 3: 192.168.178.3
+ # IPv6:
+ # Group 0: [2001:db8:85a3::8a2e:370:7334]:49774/1534999298
+ # Group 1: [
+ # Group 2: 2001:db8:85a3::8a2e:370:7334
+ addr = match.group(3) if match.group(3) else match.group(2)
+ if not is_valid_ip_address(addr):
+ raise LookupError('Invalid RGW address \'{}\' found'.format(addr))
+ return addr
+ raise LookupError('Failed to determine RGW address')
+
+
+def _parse_frontend_config(config):
+ """
+ Get the port the RGW is running on. Due the complexity of the
+ syntax not all variations are supported.
+
+ If there are multiple (ssl_)ports/(ssl_)endpoints options, then
+ the first found option will be returned.
+
+ Get more details about the configuration syntax here:
+ http://docs.ceph.com/docs/master/radosgw/frontends/
+ https://civetweb.github.io/civetweb/UserManual.html
+
+ :param config: The configuration string to parse.
+ :type config: str
+ :raises LookupError if parsing fails to determine the port.
+ :return: A tuple containing the port number and the information
+ whether SSL is used.
+ :rtype: (int, boolean)
+ """
+ match = re.search(r'^(beast|civetweb)\s+.+$', config)
+ if match:
+ if match.group(1) == 'beast':
+ match = re.search(r'(port|ssl_port|endpoint|ssl_endpoint)=(.+)',
+ config)
+ if match:
+ option_name = match.group(1)
+ if option_name in ['port', 'ssl_port']:
+ match = re.search(r'(\d+)', match.group(2))
+ if match:
+ port = int(match.group(1))
+ ssl = option_name == 'ssl_port'
+ return port, ssl
+ if option_name in ['endpoint', 'ssl_endpoint']:
+ match = re.search(r'([\d.]+|\[.+\])(:(\d+))?',
+ match.group(2))
+ if match:
+ port = int(match.group(3)) if \
+ match.group(2) is not None else 443 if \
+ option_name == 'ssl_endpoint' else \
+ 80
+ ssl = option_name == 'ssl_endpoint'
+ return port, ssl
+ if match.group(1) == 'civetweb':
+ match = re.search(r'port=(.*:)?(\d+)(s)?', config)
+ if match:
+ port = int(match.group(2))
+ ssl = match.group(3) == 's'
+ return port, ssl
+ raise LookupError('Failed to determine RGW port from "{}"'.format(config))
+
+
+class RgwClient(RestClient):
+ _SYSTEM_USERID = None
+ _ADMIN_PATH = None
+ _host = None
+ _port = None
+ _ssl = None
+ _user_instances = {}
+ _rgw_settings_snapshot = None
+
+ @staticmethod
+ def _load_settings():
+ # The API access key and secret key are mandatory for a minimal configuration.
+ if not (Settings.RGW_API_ACCESS_KEY and Settings.RGW_API_SECRET_KEY):
+ logger.warning('No credentials found, please consult the '
+ 'documentation about how to enable RGW for the '
+ 'dashboard.')
+ raise NoCredentialsException()
+
+ if Options.has_default_value('RGW_API_HOST') and \
+ Options.has_default_value('RGW_API_PORT') and \
+ Options.has_default_value('RGW_API_SCHEME'):
+ host, port, ssl = _determine_rgw_addr()
+ else:
+ host = Settings.RGW_API_HOST
+ port = Settings.RGW_API_PORT
+ ssl = Settings.RGW_API_SCHEME == 'https'
+
+ RgwClient._host = host
+ RgwClient._port = port
+ RgwClient._ssl = ssl
+ RgwClient._ADMIN_PATH = Settings.RGW_API_ADMIN_RESOURCE
+
+ # Create an instance using the configured settings.
+ instance = RgwClient(Settings.RGW_API_USER_ID,
+ Settings.RGW_API_ACCESS_KEY,
+ Settings.RGW_API_SECRET_KEY)
+
+ RgwClient._SYSTEM_USERID = instance.userid
+
+ # Append the instance to the internal map.
+ RgwClient._user_instances[RgwClient._SYSTEM_USERID] = instance
+
+ @staticmethod
+ def _rgw_settings():
+ return (Settings.RGW_API_HOST,
+ Settings.RGW_API_PORT,
+ Settings.RGW_API_ACCESS_KEY,
+ Settings.RGW_API_SECRET_KEY,
+ Settings.RGW_API_ADMIN_RESOURCE,
+ Settings.RGW_API_SCHEME,
+ Settings.RGW_API_USER_ID,
+ Settings.RGW_API_SSL_VERIFY)
+
+ @staticmethod
+ def instance(userid):
+ # Discard all cached instances if any rgw setting has changed
+ if RgwClient._rgw_settings_snapshot != RgwClient._rgw_settings():
+ RgwClient._rgw_settings_snapshot = RgwClient._rgw_settings()
+ RgwClient.drop_instance()
+
+ if not RgwClient._user_instances:
+ RgwClient._load_settings()
+
+ if not userid:
+ userid = RgwClient._SYSTEM_USERID
+
+ if userid not in RgwClient._user_instances:
+ # Get the access and secret keys for the specified user.
+ keys = RgwClient.admin_instance().get_user_keys(userid)
+ if not keys:
+ raise RequestException(
+ "User '{}' does not have any keys configured.".format(
+ userid))
+
+ # Create an instance and append it to the internal map.
+ RgwClient._user_instances[userid] = RgwClient(userid,
+ keys['access_key'],
+ keys['secret_key'])
+
+ return RgwClient._user_instances[userid]
+
+ @staticmethod
+ def admin_instance():
+ return RgwClient.instance(RgwClient._SYSTEM_USERID)
+
+ @staticmethod
+ def drop_instance(userid=None):
+ """
+ Drop a cached instance by name or all.
+ """
+ if userid:
+ RgwClient._user_instances.pop(userid, None)
+ else:
+ RgwClient._user_instances.clear()
+
+ def _reset_login(self):
+ if self.userid != RgwClient._SYSTEM_USERID:
+ logger.info("Fetching new keys for user: %s", self.userid)
+ keys = RgwClient.admin_instance().get_user_keys(self.userid)
+ self.auth = S3Auth(keys['access_key'], keys['secret_key'],
+ service_url=self.service_url)
+ else:
+ raise RequestException('Authentication failed for the "{}" user: wrong credentials'
+ .format(self.userid), status_code=401)
+
+ def __init__(self, # pylint: disable-msg=R0913
+ userid,
+ access_key,
+ secret_key,
+ host=None,
+ port=None,
+ admin_path=None,
+ ssl=False):
+
+ if not host and not RgwClient._host:
+ RgwClient._load_settings()
+ host = host if host else RgwClient._host
+ port = port if port else RgwClient._port
+ admin_path = admin_path if admin_path else RgwClient._ADMIN_PATH
+ ssl = ssl if ssl else RgwClient._ssl
+ ssl_verify = Settings.RGW_API_SSL_VERIFY
+
+ self.service_url = build_url(host=host, port=port)
+ self.admin_path = admin_path
+
+ s3auth = S3Auth(access_key, secret_key, service_url=self.service_url)
+ super(RgwClient, self).__init__(host, port, 'RGW', ssl, s3auth, ssl_verify=ssl_verify)
+
+ # If user ID is not set, then try to get it via the RGW Admin Ops API.
+ self.userid = userid if userid else self._get_user_id(self.admin_path)
+
+ logger.info("Created new connection: user=%s, host=%s, port=%s, ssl=%d, sslverify=%d",
+ self.userid, host, port, ssl, ssl_verify)
+
+ @RestClient.api_get('/', resp_structure='[0] > (ID & DisplayName)')
+ def is_service_online(self, request=None):
+ """
+ Consider the service as online if the response contains the
+ specified keys. Nothing more is checked here.
+ """
+ _ = request({'format': 'json'})
+ return True
+
+ @RestClient.api_get('/{admin_path}/metadata/user?myself',
+ resp_structure='data > user_id')
+ def _get_user_id(self, admin_path, request=None):
+ # pylint: disable=unused-argument
+ """
+ Get the user ID of the user that is used to communicate with the
+ RGW Admin Ops API.
+ :rtype: str
+ :return: The user ID of the user that is used to sign the
+ RGW Admin Ops API calls.
+ """
+ response = request()
+ return response['data']['user_id']
+
+ @RestClient.api_get('/{admin_path}/metadata/user', resp_structure='[+]')
+ def _user_exists(self, admin_path, user_id, request=None):
+ # pylint: disable=unused-argument
+ response = request()
+ if user_id:
+ return user_id in response
+ return self.userid in response
+
+ def user_exists(self, user_id=None):
+ return self._user_exists(self.admin_path, user_id)
+
+ @RestClient.api_get('/{admin_path}/metadata/user?key={userid}',
+ resp_structure='data > system')
+ def _is_system_user(self, admin_path, userid, request=None):
+ # pylint: disable=unused-argument
+ response = request()
+ return strtobool(response['data']['system'])
+
+ def is_system_user(self):
+ return self._is_system_user(self.admin_path, self.userid)
+
+ @RestClient.api_get(
+ '/{admin_path}/user',
+ resp_structure='tenant & user_id & email & keys[*] > '
+ ' (user & access_key & secret_key)')
+ def _admin_get_user_keys(self, admin_path, userid, request=None):
+ # pylint: disable=unused-argument
+ colon_idx = userid.find(':')
+ user = userid if colon_idx == -1 else userid[:colon_idx]
+ response = request({'uid': user})
+ for key in response['keys']:
+ if key['user'] == userid:
+ return {
+ 'access_key': key['access_key'],
+ 'secret_key': key['secret_key']
+ }
+ return None
+
+ def get_user_keys(self, userid):
+ return self._admin_get_user_keys(self.admin_path, userid)
+
+ @RestClient.api('/{admin_path}/{path}')
+ def _proxy_request(self, # pylint: disable=too-many-arguments
+ admin_path,
+ path,
+ method,
+ params,
+ data,
+ request=None):
+ # pylint: disable=unused-argument
+ return request(
+ method=method, params=params, data=data, raw_content=True)
+
+ def proxy(self, method, path, params, data):
+ logger.debug("proxying method=%s path=%s params=%s data=%s", method,
+ path, params, data)
+ return self._proxy_request(self.admin_path, path, method, params, data)
+
+ @RestClient.api_get('/', resp_structure='[1][*] > Name')
+ def get_buckets(self, request=None):
+ """
+ Get a list of names from all existing buckets of this user.
+ :return: Returns a list of bucket names.
+ """
+ response = request({'format': 'json'})
+ return [bucket['Name'] for bucket in response[1]]
+
+ @RestClient.api_get('/{bucket_name}')
+ def bucket_exists(self, bucket_name, userid, request=None):
+ """
+ Check if the specified bucket exists for this user.
+ :param bucket_name: The name of the bucket.
+ :return: Returns True if the bucket exists, otherwise False.
+ """
+ # pylint: disable=unused-argument
+ try:
+ request()
+ my_buckets = self.get_buckets()
+ if bucket_name not in my_buckets:
+ raise RequestException(
+ 'Bucket "{}" belongs to other user'.format(bucket_name),
+ 403)
+ return True
+ except RequestException as e:
+ if e.status_code == 404:
+ return False
+
+ raise e
+
+ @RestClient.api_put('/{bucket_name}')
+ def create_bucket(self, bucket_name, request=None):
+ logger.info("Creating bucket: %s", bucket_name)
+ return request()
diff --git a/src/pybind/mgr/dashboard/services/sso.py b/src/pybind/mgr/dashboard/services/sso.py
new file mode 100644
index 00000000..007a5307
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/sso.py
@@ -0,0 +1,268 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-return-statements,too-many-branches
+from __future__ import absolute_import
+
+import errno
+import json
+import sys
+import threading
+import six
+
+try:
+ from onelogin.saml2.settings import OneLogin_Saml2_Settings
+ from onelogin.saml2.errors import OneLogin_Saml2_Error
+ from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
+
+ python_saml_imported = True
+except ImportError:
+ python_saml_imported = False
+
+
+from .. import mgr, logger
+from ..tools import prepare_url_prefix
+
+
+class Saml2(object):
+ def __init__(self, onelogin_settings):
+ self.onelogin_settings = onelogin_settings
+
+ def get_username_attribute(self):
+ return self.onelogin_settings['sp']['attributeConsumingService']['requestedAttributes'][0][
+ 'name']
+
+ def to_dict(self):
+ return {
+ 'onelogin_settings': self.onelogin_settings
+ }
+
+ @classmethod
+ def from_dict(cls, s_dict):
+ return Saml2(s_dict['onelogin_settings'])
+
+
+class SsoDB(object):
+ VERSION = 1
+ SSODB_CONFIG_KEY = "ssodb_v"
+
+ def __init__(self, version, protocol, saml2):
+ self.version = version
+ self.protocol = protocol
+ self.saml2 = saml2
+ self.lock = threading.RLock()
+
+ def save(self):
+ with self.lock:
+ db = {
+ 'protocol': self.protocol,
+ 'saml2': self.saml2.to_dict(),
+ 'version': self.version
+ }
+ mgr.set_store(self.ssodb_config_key(), json.dumps(db))
+
+ @classmethod
+ def ssodb_config_key(cls, version=None):
+ if version is None:
+ version = cls.VERSION
+ return "{}{}".format(cls.SSODB_CONFIG_KEY, version)
+
+ def check_and_update_db(self):
+ logger.debug("SSO: Checking for previews DB versions")
+ if self.VERSION != 1:
+ raise NotImplementedError()
+
+ @classmethod
+ def load(cls):
+ logger.info("SSO: Loading SSO DB version=%s", cls.VERSION)
+
+ json_db = mgr.get_store(cls.ssodb_config_key(), None)
+ if json_db is None:
+ logger.debug("SSO: No DB v%s found, creating new...", cls.VERSION)
+ db = cls(cls.VERSION, '', Saml2({}))
+ # check if we can update from a previous version database
+ db.check_and_update_db()
+ return db
+
+ db = json.loads(json_db)
+ return cls(db['version'], db.get('protocol'), Saml2.from_dict(db.get('saml2')))
+
+
+def load_sso_db():
+ mgr.SSO_DB = SsoDB.load()
+
+
+SSO_COMMANDS = [
+ {
+ 'cmd': 'dashboard sso enable saml2',
+ 'desc': 'Enable SAML2 Single Sign-On',
+ 'perm': 'w'
+ },
+ {
+ 'cmd': 'dashboard sso disable',
+ 'desc': 'Disable Single Sign-On',
+ 'perm': 'w'
+ },
+ {
+ 'cmd': 'dashboard sso status',
+ 'desc': 'Get Single Sign-On status',
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'dashboard sso show saml2',
+ 'desc': 'Show SAML2 configuration',
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'dashboard sso setup saml2 '
+ 'name=ceph_dashboard_base_url,type=CephString '
+ 'name=idp_metadata,type=CephString '
+ 'name=idp_username_attribute,type=CephString,req=false '
+ 'name=idp_entity_id,type=CephString,req=false '
+ 'name=sp_x_509_cert,type=CephString,req=false '
+ 'name=sp_private_key,type=CephString,req=false',
+ 'desc': 'Setup SAML2 Single Sign-On',
+ 'perm': 'w'
+ }
+]
+
+
+def _get_optional_attr(cmd, attr, default):
+ if attr in cmd:
+ if cmd[attr] != '':
+ return cmd[attr]
+ return default
+
+
+def handle_sso_command(cmd):
+ if cmd['prefix'] not in ['dashboard sso enable saml2',
+ 'dashboard sso disable',
+ 'dashboard sso status',
+ 'dashboard sso show saml2',
+ 'dashboard sso setup saml2']:
+ return -errno.ENOSYS, '', ''
+
+ if cmd['prefix'] == 'dashboard sso disable':
+ mgr.SSO_DB.protocol = ''
+ mgr.SSO_DB.save()
+ return 0, 'SSO is "disabled".', ''
+
+ if not python_saml_imported:
+ python_saml_name = 'python3-saml' if sys.version_info >= (3, 0) else 'python-saml'
+ return -errno.EPERM, '', 'Required library not found: `{}`'.format(python_saml_name)
+
+ if cmd['prefix'] == 'dashboard sso enable saml2':
+ try:
+ OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings)
+ except OneLogin_Saml2_Error:
+ return -errno.EPERM, '', 'Single Sign-On is not configured: ' \
+ 'use `ceph dashboard sso setup saml2`'
+ mgr.SSO_DB.protocol = 'saml2'
+ mgr.SSO_DB.save()
+ return 0, 'SSO is "enabled" with "SAML2" protocol.', ''
+
+ if cmd['prefix'] == 'dashboard sso status':
+ if mgr.SSO_DB.protocol == 'saml2':
+ return 0, 'SSO is "enabled" with "SAML2" protocol.', ''
+
+ return 0, 'SSO is "disabled".', ''
+
+ if cmd['prefix'] == 'dashboard sso show saml2':
+ return 0, json.dumps(mgr.SSO_DB.saml2.to_dict()), ''
+
+ if cmd['prefix'] == 'dashboard sso setup saml2':
+ ceph_dashboard_base_url = cmd['ceph_dashboard_base_url']
+ idp_metadata = cmd['idp_metadata']
+ idp_username_attribute = _get_optional_attr(cmd, 'idp_username_attribute', 'uid')
+ idp_entity_id = _get_optional_attr(cmd, 'idp_entity_id', None)
+ sp_x_509_cert = _get_optional_attr(cmd, 'sp_x_509_cert', '')
+ sp_private_key = _get_optional_attr(cmd, 'sp_private_key', '')
+ if sp_x_509_cert and not sp_private_key:
+ return -errno.EINVAL, '', 'Missing parameter `sp_private_key`.'
+ if not sp_x_509_cert and sp_private_key:
+ return -errno.EINVAL, '', 'Missing parameter `sp_x_509_cert`.'
+ has_sp_cert = sp_x_509_cert != "" and sp_private_key != ""
+ try:
+ # pylint: disable=undefined-variable
+ FileNotFoundError
+ except NameError:
+ # pylint: disable=redefined-builtin
+ FileNotFoundError = IOError
+ try:
+ f = open(sp_x_509_cert, 'r', encoding='utf-8') if six.PY3 else \
+ open(sp_x_509_cert, 'rb')
+ sp_x_509_cert = f.read()
+ f.close()
+ except FileNotFoundError:
+ pass
+ try:
+ f = open(sp_private_key, 'r', encoding='utf-8') if six.PY3 else \
+ open(sp_private_key, 'rb')
+ sp_private_key = f.read()
+ f.close()
+ except FileNotFoundError:
+ pass
+ try:
+ idp_settings = OneLogin_Saml2_IdPMetadataParser.parse_remote(idp_metadata,
+ validate_cert=False,
+ entity_id=idp_entity_id)
+ # pylint: disable=broad-except
+ except Exception:
+ try:
+ f = open(idp_metadata, 'r', encoding='utf-8') if six.PY3 else \
+ open(idp_metadata, 'rb')
+ idp_metadata = f.read()
+ f.close()
+ except FileNotFoundError:
+ pass
+ try:
+ idp_settings = OneLogin_Saml2_IdPMetadataParser.parse(idp_metadata,
+ entity_id=idp_entity_id)
+ # pylint: disable=broad-except
+ except Exception:
+ return -errno.EINVAL, '', 'Invalid parameter `idp_metadata`.'
+
+ url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default=''))
+ settings = {
+ 'sp': {
+ 'entityId': '{}{}/auth/saml2/metadata'.format(ceph_dashboard_base_url, url_prefix),
+ 'assertionConsumerService': {
+ 'url': '{}{}/auth/saml2'.format(ceph_dashboard_base_url, url_prefix),
+ 'binding': "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ },
+ 'attributeConsumingService': {
+ 'serviceName': "Ceph Dashboard",
+ "serviceDescription": "Ceph Dashboard Service",
+ "requestedAttributes": [
+ {
+ "name": idp_username_attribute,
+ "isRequired": True
+ }
+ ]
+ },
+ 'singleLogoutService': {
+ 'url': '{}{}/auth/saml2/logout'.format(ceph_dashboard_base_url, url_prefix),
+ 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
+ },
+ "x509cert": sp_x_509_cert,
+ "privateKey": sp_private_key
+ },
+ 'security': {
+ "nameIdEncrypted": has_sp_cert,
+ "authnRequestsSigned": has_sp_cert,
+ "logoutRequestSigned": has_sp_cert,
+ "logoutResponseSigned": has_sp_cert,
+ "signMetadata": has_sp_cert,
+ "wantMessagesSigned": has_sp_cert,
+ "wantAssertionsSigned": has_sp_cert,
+ "wantAssertionsEncrypted": has_sp_cert,
+ "wantNameIdEncrypted": False, # Not all Identity Providers support this.
+ "metadataValidUntil": '',
+ "wantAttributeStatement": False
+ }
+ }
+ settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, idp_settings)
+ mgr.SSO_DB.saml2.onelogin_settings = settings
+ mgr.SSO_DB.protocol = 'saml2'
+ mgr.SSO_DB.save()
+ return 0, json.dumps(mgr.SSO_DB.saml2.onelogin_settings), ''
+
+ return -errno.ENOSYS, '', ''
diff --git a/src/pybind/mgr/dashboard/services/tcmu_service.py b/src/pybind/mgr/dashboard/services/tcmu_service.py
new file mode 100644
index 00000000..1f3e4d8d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/tcmu_service.py
@@ -0,0 +1,96 @@
+from mgr_util import get_most_recent_rate
+
+from dashboard.services.ceph_service import CephService
+from .. import mgr
+
+SERVICE_TYPE = 'tcmu-runner'
+
+
+class TcmuService(object):
+ # pylint: disable=too-many-nested-blocks
+ @staticmethod
+ def get_iscsi_info():
+ daemons = {}
+ images = {}
+ for service in CephService.get_service_list(SERVICE_TYPE):
+ metadata = service['metadata']
+ if metadata is None:
+ continue
+ status = service['status']
+ hostname = service['hostname']
+
+ daemon = daemons.get(hostname, None)
+ if daemon is None:
+ daemon = {
+ 'server_hostname': hostname,
+ 'version': metadata['ceph_version'],
+ 'optimized_paths': 0,
+ 'non_optimized_paths': 0
+ }
+ daemons[hostname] = daemon
+
+ service_id = service['id']
+ device_id = service_id.split(':')[-1]
+ image = images.get(device_id)
+ if image is None:
+ image = {
+ 'device_id': device_id,
+ 'pool_name': metadata['pool_name'],
+ 'name': metadata['image_name'],
+ 'id': metadata.get('image_id', None),
+ 'optimized_paths': [],
+ 'non_optimized_paths': []
+ }
+ images[device_id] = image
+
+ if status.get('lock_owner', 'false') == 'true':
+ daemon['optimized_paths'] += 1
+ image['optimized_paths'].append(hostname)
+
+ perf_key_prefix = "librbd-{id}-{pool}-{name}.".format(
+ id=metadata.get('image_id', ''),
+ pool=metadata['pool_name'],
+ name=metadata['image_name'])
+ perf_key = "{}lock_acquired_time".format(perf_key_prefix)
+ lock_acquired_time = (mgr.get_counter(
+ 'tcmu-runner', service_id, perf_key)[perf_key]
+ or [[0, 0]])[-1][1] / 1000000000
+ if lock_acquired_time > image.get('optimized_since', 0):
+ image['optimized_daemon'] = hostname
+ image['optimized_since'] = lock_acquired_time
+ image['stats'] = {}
+ image['stats_history'] = {}
+ for s in ['rd', 'wr', 'rd_bytes', 'wr_bytes']:
+ perf_key = "{}{}".format(perf_key_prefix, s)
+ rates = CephService.get_rates('tcmu-runner', service_id, perf_key)
+ image['stats'][s] = get_most_recent_rate(rates)
+ image['stats_history'][s] = rates
+ else:
+ daemon['non_optimized_paths'] += 1
+ image['non_optimized_paths'].append(hostname)
+
+ # clear up races w/ tcmu-runner clients that haven't detected
+ # loss of optimized path
+ for image in images.values():
+ optimized_daemon = image.get('optimized_daemon', None)
+ if optimized_daemon:
+ for daemon_name in image['optimized_paths']:
+ if daemon_name != optimized_daemon:
+ daemon = daemons[daemon_name]
+ daemon['optimized_paths'] -= 1
+ daemon['non_optimized_paths'] += 1
+ image['non_optimized_paths'].append(daemon_name)
+ image['optimized_paths'] = [optimized_daemon]
+
+ return {
+ 'daemons': sorted(daemons.values(),
+ key=lambda d: d['server_hostname']),
+ 'images': sorted(images.values(), key=lambda i: ['id']),
+ }
+
+ @staticmethod
+ def get_image_info(pool_name, image_name, get_iscsi_info):
+ for image in get_iscsi_info['images']:
+ if image['pool_name'] == pool_name and image['name'] == image_name:
+ return image
+ return None
diff --git a/src/pybind/mgr/dashboard/settings.py b/src/pybind/mgr/dashboard/settings.py
new file mode 100644
index 00000000..95b1cdf4
--- /dev/null
+++ b/src/pybind/mgr/dashboard/settings.py
@@ -0,0 +1,201 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import errno
+import inspect
+from six import add_metaclass
+
+from mgr_module import CLICheckNonemptyFileInput
+
+from . import mgr
+
+
+class Options(object):
+ """
+ If you need to store some configuration value please add the config option
+ name as a class attribute to this class.
+
+ Example::
+
+ GRAFANA_API_HOST = ('localhost', str)
+ GRAFANA_API_PORT = (3000, int)
+ """
+ ENABLE_BROWSABLE_API = (True, bool)
+ REST_REQUESTS_TIMEOUT = (45, int)
+
+ # API auditing
+ AUDIT_API_ENABLED = (False, bool)
+ AUDIT_API_LOG_PAYLOAD = (True, bool)
+
+ # RGW settings
+ RGW_API_HOST = ('', str)
+ RGW_API_PORT = (80, int)
+ RGW_API_ACCESS_KEY = ('', str)
+ RGW_API_SECRET_KEY = ('', str)
+ RGW_API_ADMIN_RESOURCE = ('admin', str)
+ RGW_API_SCHEME = ('http', str)
+ RGW_API_USER_ID = ('', str)
+ RGW_API_SSL_VERIFY = (True, bool)
+
+ # Grafana settings
+ GRAFANA_API_URL = ('', str)
+ GRAFANA_FRONTEND_API_URL = ('', str)
+ GRAFANA_API_USERNAME = ('admin', str)
+ GRAFANA_API_PASSWORD = ('admin', str)
+ GRAFANA_API_SSL_VERIFY = (True, bool)
+ GRAFANA_UPDATE_DASHBOARDS = (False, bool)
+
+ # NFS Ganesha settings
+ GANESHA_CLUSTERS_RADOS_POOL_NAMESPACE = ('', str)
+
+ # Prometheus settings
+ PROMETHEUS_API_HOST = ('', str)
+ ALERTMANAGER_API_HOST = ('', str)
+
+ # iSCSI management settings
+ ISCSI_API_SSL_VERIFICATION = (True, bool)
+
+ @staticmethod
+ def has_default_value(name):
+ return getattr(Settings, name, None) is None or \
+ getattr(Settings, name) == getattr(Options, name)[0]
+
+
+class SettingsMeta(type):
+ def __getattr__(cls, attr):
+ default, stype = getattr(Options, attr)
+ if stype == bool and str(mgr.get_module_option(
+ attr,
+ default)).lower() == 'false':
+ value = False
+ else:
+ value = stype(mgr.get_module_option(attr, default))
+ return value
+
+ def __setattr__(cls, attr, value):
+ if not attr.startswith('_') and hasattr(Options, attr):
+ mgr.set_module_option(attr, str(value))
+ else:
+ setattr(SettingsMeta, attr, value)
+
+ def __delattr__(cls, attr):
+ if not attr.startswith('_') and hasattr(Options, attr):
+ mgr.set_module_option(attr, None)
+
+
+# pylint: disable=no-init
+@add_metaclass(SettingsMeta)
+class Settings(object):
+ pass
+
+
+def _options_command_map():
+ def filter_attr(member):
+ return not inspect.isroutine(member)
+
+ cmd_map = {}
+ for option, value in inspect.getmembers(Options, filter_attr):
+ if option.startswith('_'):
+ continue
+ key_get = 'dashboard get-{}'.format(option.lower().replace('_', '-'))
+ key_set = 'dashboard set-{}'.format(option.lower().replace('_', '-'))
+ key_reset = 'dashboard reset-{}'.format(option.lower().replace('_', '-'))
+ cmd_map[key_get] = {'name': option, 'type': None}
+ cmd_map[key_set] = {'name': option, 'type': value[1]}
+ cmd_map[key_reset] = {'name': option, 'type': None}
+ return cmd_map
+
+
+_OPTIONS_COMMAND_MAP = _options_command_map()
+
+
+def options_command_list():
+ """
+ This function generates a list of ``get`` and ``set`` commands
+ for each declared configuration option in class ``Options``.
+ """
+ def py2ceph(pytype):
+ if pytype == str:
+ return 'CephString'
+ elif pytype == int:
+ return 'CephInt'
+ return 'CephString'
+
+ cmd_list = []
+ for cmd, opt in _OPTIONS_COMMAND_MAP.items():
+ if cmd.startswith('dashboard get'):
+ cmd_list.append({
+ 'cmd': '{}'.format(cmd),
+ 'desc': 'Get the {} option value'.format(opt['name']),
+ 'perm': 'r'
+ })
+ elif cmd.startswith('dashboard set'):
+ cmd_entry = {
+ 'cmd': '{} name=value,type={}'
+ .format(cmd, py2ceph(opt['type'])),
+ 'desc': 'Set the {} option value'.format(opt['name']),
+ 'perm': 'w'
+ }
+ if handles_secret(cmd):
+ cmd_entry['cmd'] = cmd
+ cmd_entry['desc'] = '{} read from -i <file>'.format(cmd_entry['desc'])
+ cmd_list.append(cmd_entry)
+ elif cmd.startswith('dashboard reset'):
+ desc = 'Reset the {} option to its default value'.format(
+ opt['name'])
+ cmd_list.append({
+ 'cmd': '{}'.format(cmd),
+ 'desc': desc,
+ 'perm': 'w'
+ })
+
+ return cmd_list
+
+
+def options_schema_list():
+ def filter_attr(member):
+ return not inspect.isroutine(member)
+
+ result = []
+ for option, value in inspect.getmembers(Options, filter_attr):
+ if option.startswith('_'):
+ continue
+ result.append({'name': option, 'default': value[0],
+ 'type': value[1].__name__})
+
+ return result
+
+
+def handle_option_command(cmd, inbuf):
+ if cmd['prefix'] not in _OPTIONS_COMMAND_MAP:
+ return -errno.ENOSYS, '', "Command not found '{}'".format(cmd['prefix'])
+
+ opt = _OPTIONS_COMMAND_MAP[cmd['prefix']]
+
+ if cmd['prefix'].startswith('dashboard reset'):
+ delattr(Settings, opt['name'])
+ return 0, 'Option {} reset to default value "{}"'.format(
+ opt['name'], getattr(Settings, opt['name'])), ''
+ elif cmd['prefix'].startswith('dashboard get'):
+ return 0, str(getattr(Settings, opt['name'])), ''
+ elif cmd['prefix'].startswith('dashboard set'):
+ if handles_secret(cmd['prefix']):
+ value, stdout, stderr = get_secret(inbuf=inbuf)
+ if stderr:
+ return value, stdout, stderr
+ else:
+ value = cmd['value']
+ value = opt['type'](value)
+ if opt['type'] == bool and cmd['value'].lower() == 'false':
+ value = False
+ setattr(Settings, opt['name'], value)
+ return 0, 'Option {} updated'.format(opt['name']), ''
+
+
+def handles_secret(cmd):
+ return bool([cmd for secret_word in ['password', 'key'] if (secret_word in cmd)])
+
+
+@CLICheckNonemptyFileInput
+def get_secret(inbuf=None):
+ return inbuf, None, None
diff --git a/src/pybind/mgr/dashboard/tests/__init__.py b/src/pybind/mgr/dashboard/tests/__init__.py
new file mode 100644
index 00000000..58998690
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/__init__.py
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-arguments
+from __future__ import absolute_import
+
+import json
+import threading
+import sys
+import time
+
+import cherrypy
+from cherrypy._cptools import HandlerWrapperTool
+from cherrypy.test import helper
+from pyfakefs import fake_filesystem
+
+from mgr_module import CLICommand, MgrModule
+
+from .. import logger, mgr
+from ..controllers import json_error_page, generate_controller_routes
+from ..services.auth import AuthManagerTool
+from ..services.exception import dashboard_exception_handler
+
+from ..plugins import PLUGIN_MANAGER
+from ..plugins import feature_toggles, debug # noqa # pylint: disable=unused-import
+
+
+PLUGIN_MANAGER.hook.init()
+PLUGIN_MANAGER.hook.register_commands()
+
+
+class CmdException(Exception):
+ def __init__(self, retcode, message):
+ super(CmdException, self).__init__(message)
+ self.retcode = retcode
+
+
+def exec_dashboard_cmd(command_handler, cmd, **kwargs):
+ inbuf = kwargs['inbuf'] if 'inbuf' in kwargs else None
+ cmd_dict = {'prefix': 'dashboard {}'.format(cmd)}
+ cmd_dict.update(kwargs)
+ if cmd_dict['prefix'] not in CLICommand.COMMANDS:
+ ret, out, err = command_handler(cmd_dict)
+ if ret < 0:
+ raise CmdException(ret, err)
+ try:
+ return json.loads(out)
+ except ValueError:
+ return out
+
+ ret, out, err = CLICommand.COMMANDS[cmd_dict['prefix']].call(mgr, cmd_dict, inbuf)
+ if ret < 0:
+ raise CmdException(ret, err)
+ try:
+ return json.loads(out)
+ except ValueError:
+ return out
+
+
+class KVStoreMockMixin(object):
+ CONFIG_KEY_DICT = {}
+
+ @classmethod
+ def mock_set_module_option(cls, attr, val):
+ cls.CONFIG_KEY_DICT[attr] = val
+
+ @classmethod
+ def mock_get_module_option(cls, attr, default=None):
+ return cls.CONFIG_KEY_DICT.get(attr, default)
+
+ @classmethod
+ def mock_kv_store(cls):
+ cls.CONFIG_KEY_DICT.clear()
+ mgr.set_module_option.side_effect = cls.mock_set_module_option
+ mgr.get_module_option.side_effect = cls.mock_get_module_option
+ # kludge below
+ mgr.set_store.side_effect = cls.mock_set_module_option
+ mgr.get_store.side_effect = cls.mock_get_module_option
+
+ @classmethod
+ def get_key(cls, key):
+ return cls.CONFIG_KEY_DICT.get(key, None)
+
+
+class CLICommandTestMixin(KVStoreMockMixin):
+ @classmethod
+ def exec_cmd(cls, cmd, **kwargs):
+ return exec_dashboard_cmd(None, cmd, **kwargs)
+
+
+class FakeFsMixin(object):
+ fs = fake_filesystem.FakeFilesystem()
+ f_open = fake_filesystem.FakeFileOpen(fs)
+ f_os = fake_filesystem.FakeOsModule(fs)
+
+ if sys.version_info > (3, 0):
+ builtins_open = 'builtins.open'
+ else:
+ builtins_open = '__builtin__.open'
+
+
+class ControllerTestCase(helper.CPWebCase):
+ _endpoints_cache = {}
+
+ @classmethod
+ def setup_controllers(cls, ctrl_classes, base_url=''):
+ if not isinstance(ctrl_classes, list):
+ ctrl_classes = [ctrl_classes]
+ mapper = cherrypy.dispatch.RoutesDispatcher()
+ endpoint_list = []
+ for ctrl in ctrl_classes:
+ inst = ctrl()
+
+ # We need to cache the controller endpoints because
+ # BaseController#endpoints method is not idempontent
+ # and a controller might be needed by more than one
+ # unit test.
+ if ctrl not in cls._endpoints_cache:
+ ctrl_endpoints = ctrl.endpoints()
+ cls._endpoints_cache[ctrl] = ctrl_endpoints
+
+ ctrl_endpoints = cls._endpoints_cache[ctrl]
+ for endpoint in ctrl_endpoints:
+ endpoint.inst = inst
+ endpoint_list.append(endpoint)
+ endpoint_list = sorted(endpoint_list, key=lambda e: e.url)
+ for endpoint in endpoint_list:
+ generate_controller_routes(endpoint, mapper, base_url)
+ if base_url == '':
+ base_url = '/'
+ cherrypy.tree.mount(None, config={
+ base_url: {'request.dispatch': mapper}})
+
+ def __init__(self, *args, **kwargs):
+ cherrypy.tools.authenticate = AuthManagerTool()
+ cherrypy.tools.dashboard_exception_handler = HandlerWrapperTool(dashboard_exception_handler,
+ priority=31)
+ cherrypy.config.update({
+ 'error_page.default': json_error_page,
+ 'tools.json_in.on': True,
+ 'tools.json_in.force': False
+ })
+ PLUGIN_MANAGER.hook.configure_cherrypy(config=cherrypy.config)
+ super(ControllerTestCase, self).__init__(*args, **kwargs)
+
+ def _request(self, url, method, data=None, headers=None):
+ if not data:
+ b = None
+ h = None
+ else:
+ b = json.dumps(data)
+ h = [('Content-Type', 'application/json'),
+ ('Content-Length', str(len(b)))]
+ if headers:
+ h = headers
+ self.getPage(url, method=method, body=b, headers=h)
+
+ def _get(self, url, headers=None):
+ self._request(url, 'GET', headers=headers)
+
+ def _post(self, url, data=None):
+ self._request(url, 'POST', data)
+
+ def _delete(self, url, data=None):
+ self._request(url, 'DELETE', data)
+
+ def _put(self, url, data=None):
+ self._request(url, 'PUT', data)
+
+ def _task_request(self, method, url, data, timeout):
+ self._request(url, method, data)
+ if self.status != '202 Accepted':
+ logger.info("task finished immediately")
+ return
+
+ res = self.jsonBody()
+ self.assertIsInstance(res, dict)
+ self.assertIn('name', res)
+ self.assertIn('metadata', res)
+
+ task_name = res['name']
+ task_metadata = res['metadata']
+
+ # pylint: disable=protected-access
+ class Waiter(threading.Thread):
+ def __init__(self, task_name, task_metadata, tc):
+ super(Waiter, self).__init__()
+ self.task_name = task_name
+ self.task_metadata = task_metadata
+ self.ev = threading.Event()
+ self.abort = False
+ self.res_task = None
+ self.tc = tc
+
+ def run(self):
+ running = True
+ while running and not self.abort:
+ logger.info("task (%s, %s) is still executing", self.task_name,
+ self.task_metadata)
+ time.sleep(1)
+ self.tc._get('/api/task?name={}'.format(self.task_name))
+ res = self.tc.jsonBody()
+ for task in res['finished_tasks']:
+ if task['metadata'] == self.task_metadata:
+ # task finished
+ running = False
+ self.res_task = task
+ self.ev.set()
+
+ thread = Waiter(task_name, task_metadata, self)
+ thread.start()
+ status = thread.ev.wait(timeout)
+ if not status:
+ # timeout expired
+ thread.abort = True
+ thread.join()
+ raise Exception("Waiting for task ({}, {}) to finish timed out"
+ .format(task_name, task_metadata))
+ logger.info("task (%s, %s) finished", task_name, task_metadata)
+ if thread.res_task['success']:
+ self.body = json.dumps(thread.res_task['ret_value'])
+ if method == 'POST':
+ self.status = '201 Created'
+ elif method == 'PUT':
+ self.status = '200 OK'
+ elif method == 'DELETE':
+ self.status = '204 No Content'
+ return
+ else:
+ if 'status' in thread.res_task['exception']:
+ self.status = thread.res_task['exception']['status']
+ else:
+ self.status = 500
+ self.body = json.dumps(thread.res_task['exception'])
+ return
+
+ def _task_post(self, url, data=None, timeout=60):
+ self._task_request('POST', url, data, timeout)
+
+ def _task_delete(self, url, timeout=60):
+ self._task_request('DELETE', url, None, timeout)
+
+ def _task_put(self, url, data=None, timeout=60):
+ self._task_request('PUT', url, data, timeout)
+
+ def jsonBody(self):
+ body_str = self.body.decode('utf-8') if isinstance(self.body, bytes) else self.body
+ return json.loads(body_str)
+
+ def assertJsonBody(self, data, msg=None):
+ """Fail if value != self.body."""
+ json_body = self.jsonBody()
+ if data != json_body:
+ if msg is None:
+ msg = 'expected body:\n%r\n\nactual body:\n%r' % (
+ data, json_body)
+ self._handlewebError(msg)
+
+ def assertInJsonBody(self, data, msg=None):
+ json_body = self.jsonBody()
+ if data not in json_body:
+ if msg is None:
+ msg = 'expected %r to be in %r' % (data, json_body)
+ self._handlewebError(msg)
diff --git a/src/pybind/mgr/dashboard/tests/helper.py b/src/pybind/mgr/dashboard/tests/helper.py
new file mode 100644
index 00000000..9ec043d6
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/helper.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+try:
+ from typing import Dict, Any # pylint: disable=unused-import
+except ImportError:
+ pass
+
+
+def update_dict(data, update_data):
+ # type: (Dict[Any, Any], Dict[Any, Any]) -> Dict[Any]
+ """ Update a dictionary recursively.
+
+ Eases doing so by providing the option to separate the key to be updated by dot characters. If
+ a key provided does not exist, it will raise an KeyError instead of just updating the
+ dictionary.
+
+ Limitations
+
+ Please note that the functionality provided by this method can only be used if the dictionary to
+ be updated (`data`) does not contain dot characters in its keys.
+
+ :raises KeyError:
+
+ >>> update_dict({'foo': {'bar': 5}}, {'foo.bar': 10})
+ {'foo': {'bar': 10}}
+
+ >>> update_dict({'foo': {'bar': 5}}, {'xyz': 10})
+ Traceback (most recent call last):
+ ...
+ KeyError: 'xyz'
+
+ >>> update_dict({'foo': {'bar': 5}}, {'foo.xyz': 10})
+ Traceback (most recent call last):
+ ...
+ KeyError: 'xyz'
+ """
+ for k, v in update_data.items():
+ keys = k.split('.')
+ element = None
+ for i, key in enumerate(keys):
+ last = False
+ if len(keys) == i + 1:
+ last = True
+
+ if not element:
+ element = data[key]
+ elif not last:
+ element = element[key] # pylint: disable=unsubscriptable-object
+
+ if last:
+ if key not in element:
+ raise KeyError(key)
+
+ element[key] = v
+ return data
diff --git a/src/pybind/mgr/dashboard/tests/test_access_control.py b/src/pybind/mgr/dashboard/tests/test_access_control.py
new file mode 100644
index 00000000..34452267
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_access_control.py
@@ -0,0 +1,695 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=dangerous-default-value,too-many-public-methods
+from __future__ import absolute_import
+
+import errno
+import json
+import tempfile
+import time
+import unittest
+
+from mgr_module import ERROR_MSG_EMPTY_INPUT_FILE
+
+from . import CmdException, CLICommandTestMixin
+from .. import mgr
+from ..security import Scope, Permission
+from ..services.access_control import load_access_control_db, \
+ password_hash, AccessControlDB, \
+ SYSTEM_ROLES
+
+
+class AccessControlTest(unittest.TestCase, CLICommandTestMixin):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.mock_kv_store()
+ mgr.ACCESS_CONTROL_DB = None
+
+ def setUp(self):
+ self.CONFIG_KEY_DICT.clear()
+ load_access_control_db()
+
+ def load_persistent_db(self):
+ config_key = AccessControlDB.accessdb_config_key()
+ self.assertIn(config_key, self.CONFIG_KEY_DICT)
+ db_json = self.CONFIG_KEY_DICT[config_key]
+ db = json.loads(db_json)
+ return db
+
+ # The DB is written to persistent storage the first time it is saved.
+ # However, should an operation fail due to <reasons>, we may end up in
+ # a state where we have a completely empty CONFIG_KEY_DICT (our mock
+ # equivalent to the persistent state). While this works for most of the
+ # tests in this class, that would prevent us from testing things like
+ # "run a command that is expected to fail, and then ensure nothing
+ # happened", because we'd be asserting in `load_persistent_db()` due to
+ # the map being empty.
+ #
+ # This function will therefore force state to be written to our mock
+ # persistent state. We could have added this extra step to
+ # `load_persistent_db()` directly, but that would conflict with the
+ # upgrade tests. This way, we can selectively enforce this requirement
+ # where we believe it to be necessary; generically speaking, this should
+ # not be needed unless we're testing very specific behaviors.
+ #
+ def setup_and_load_persistent_db(self):
+ mgr.ACCESS_CTRL_DB.save()
+ self.load_persistent_db()
+
+ def validate_persistent_role(self, rolename, scopes_permissions,
+ description=None):
+ db = self.load_persistent_db()
+ self.assertIn('roles', db)
+ self.assertIn(rolename, db['roles'])
+ self.assertEqual(db['roles'][rolename]['name'], rolename)
+ self.assertEqual(db['roles'][rolename]['description'], description)
+ self.assertDictEqual(db['roles'][rolename]['scopes_permissions'],
+ scopes_permissions)
+
+ def validate_persistent_no_role(self, rolename):
+ db = self.load_persistent_db()
+ self.assertIn('roles', db)
+ self.assertNotIn(rolename, db['roles'])
+
+ def validate_persistent_user(self, username, roles, password=None,
+ name=None, email=None, lastUpdate=None):
+ db = self.load_persistent_db()
+ self.assertIn('users', db)
+ self.assertIn(username, db['users'])
+ self.assertEqual(db['users'][username]['username'], username)
+ self.assertListEqual(db['users'][username]['roles'], roles)
+ if password:
+ self.assertEqual(db['users'][username]['password'], password)
+ if name:
+ self.assertEqual(db['users'][username]['name'], name)
+ if email:
+ self.assertEqual(db['users'][username]['email'], email)
+ if lastUpdate:
+ self.assertEqual(db['users'][username]['lastUpdate'], lastUpdate)
+
+ def validate_persistent_no_user(self, username):
+ db = self.load_persistent_db()
+ self.assertIn('users', db)
+ self.assertNotIn(username, db['users'])
+
+ def test_create_role(self):
+ role = self.exec_cmd('ac-role-create', rolename='test_role')
+ self.assertDictEqual(role, {'name': 'test_role', 'description': None,
+ 'scopes_permissions': {}})
+ self.validate_persistent_role('test_role', {})
+
+ def test_create_role_with_desc(self):
+ role = self.exec_cmd('ac-role-create', rolename='test_role',
+ description='Test Role')
+ self.assertDictEqual(role, {'name': 'test_role',
+ 'description': 'Test Role',
+ 'scopes_permissions': {}})
+ self.validate_persistent_role('test_role', {}, 'Test Role')
+
+ def test_create_duplicate_role(self):
+ self.test_create_role()
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-create', rolename='test_role')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EEXIST)
+ self.assertEqual(str(ctx.exception), "Role 'test_role' already exists")
+
+ def test_delete_role(self):
+ self.test_create_role()
+ out = self.exec_cmd('ac-role-delete', rolename='test_role')
+ self.assertEqual(out, "Role 'test_role' deleted")
+ self.validate_persistent_no_role('test_role')
+
+ def test_delete_nonexistent_role(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-delete', rolename='test_role')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "Role 'test_role' does not exist")
+
+ def test_show_single_role(self):
+ self.test_create_role()
+ role = self.exec_cmd('ac-role-show', rolename='test_role')
+ self.assertDictEqual(role, {'name': 'test_role', 'description': None,
+ 'scopes_permissions': {}})
+
+ def test_show_nonexistent_role(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-show', rolename='test_role')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "Role 'test_role' does not exist")
+
+ def test_show_system_roles(self):
+ roles = self.exec_cmd('ac-role-show')
+ self.assertEqual(len(roles), len(SYSTEM_ROLES))
+ for role in roles:
+ self.assertIn(role, SYSTEM_ROLES)
+
+ def test_show_system_role(self):
+ role = self.exec_cmd('ac-role-show', rolename="read-only")
+ self.assertEqual(role['name'], 'read-only')
+ self.assertEqual(role['description'], 'Read-Only')
+
+ def test_delete_system_role(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-delete', rolename='administrator')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EPERM)
+ self.assertEqual(str(ctx.exception),
+ "Cannot delete system role 'administrator'")
+
+ def test_add_role_scope_perms(self):
+ self.test_create_role()
+ self.exec_cmd('ac-role-add-scope-perms', rolename='test_role',
+ scopename=Scope.POOL,
+ permissions=[Permission.READ, Permission.DELETE])
+ role = self.exec_cmd('ac-role-show', rolename='test_role')
+ self.assertDictEqual(role, {'name': 'test_role',
+ 'description': None,
+ 'scopes_permissions': {
+ Scope.POOL: [Permission.DELETE,
+ Permission.READ]
+ }})
+ self.validate_persistent_role('test_role', {
+ Scope.POOL: [Permission.DELETE, Permission.READ]
+ })
+
+ def test_del_role_scope_perms(self):
+ self.test_add_role_scope_perms()
+ self.exec_cmd('ac-role-add-scope-perms', rolename='test_role',
+ scopename=Scope.MONITOR,
+ permissions=[Permission.READ, Permission.CREATE])
+ self.validate_persistent_role('test_role', {
+ Scope.POOL: [Permission.DELETE, Permission.READ],
+ Scope.MONITOR: [Permission.CREATE, Permission.READ]
+ })
+ self.exec_cmd('ac-role-del-scope-perms', rolename='test_role',
+ scopename=Scope.POOL)
+ role = self.exec_cmd('ac-role-show', rolename='test_role')
+ self.assertDictEqual(role, {'name': 'test_role',
+ 'description': None,
+ 'scopes_permissions': {
+ Scope.MONITOR: [Permission.CREATE,
+ Permission.READ]
+ }})
+ self.validate_persistent_role('test_role', {
+ Scope.MONITOR: [Permission.CREATE, Permission.READ]
+ })
+
+ def test_add_role_scope_perms_nonexistent_role(self):
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-add-scope-perms', rolename='test_role',
+ scopename='pool',
+ permissions=['read', 'delete'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "Role 'test_role' does not exist")
+
+ def test_add_role_invalid_scope_perms(self):
+ self.test_create_role()
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-add-scope-perms', rolename='test_role',
+ scopename='invalidscope',
+ permissions=['read', 'delete'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+ self.assertEqual(str(ctx.exception),
+ "Scope 'invalidscope' is not valid\n Possible values: "
+ "{}".format(Scope.all_scopes()))
+
+ def test_add_role_scope_invalid_perms(self):
+ self.test_create_role()
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-add-scope-perms', rolename='test_role',
+ scopename='pool', permissions=['invalidperm'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+ self.assertEqual(str(ctx.exception),
+ "Permission 'invalidperm' is not valid\n Possible "
+ "values: {}".format(Permission.all_permissions()))
+
+ def test_del_role_scope_perms_nonexistent_role(self):
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-del-scope-perms', rolename='test_role',
+ scopename='pool')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "Role 'test_role' does not exist")
+
+ def test_del_role_nonexistent_scope_perms(self):
+ self.test_add_role_scope_perms()
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-del-scope-perms', rolename='test_role',
+ scopename='nonexistentscope')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception),
+ "There are no permissions for scope 'nonexistentscope' "
+ "in role 'test_role'")
+
+ def test_not_permitted_add_role_scope_perms(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-add-scope-perms', rolename='read-only',
+ scopename='pool', permissions=['read', 'delete'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.EPERM)
+ self.assertEqual(str(ctx.exception),
+ "Cannot update system role 'read-only'")
+
+ def test_not_permitted_del_role_scope_perms(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-del-scope-perms', rolename='read-only',
+ scopename='pool')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EPERM)
+ self.assertEqual(str(ctx.exception),
+ "Cannot update system role 'read-only'")
+
+ def test_create_user(self, username='admin', rolename=None):
+ user = self.exec_cmd('ac-user-create', username=username,
+ rolename=rolename, inbuf='admin',
+ name='{} User'.format(username),
+ email='{}@user.com'.format(username))
+
+ pass_hash = password_hash('admin', user['password'])
+ self.assertDictEqual(user, {
+ 'username': username,
+ 'password': pass_hash,
+ 'lastUpdate': user['lastUpdate'],
+ 'name': '{} User'.format(username),
+ 'email': '{}@user.com'.format(username),
+ 'roles': [rolename] if rolename else []
+ })
+ self.validate_persistent_user(username, [rolename] if rolename else [],
+ pass_hash, '{} User'.format(username),
+ '{}@user.com'.format(username),
+ user['lastUpdate'])
+ return user
+
+ def test_create_user_with_role(self):
+ self.test_add_role_scope_perms()
+ self.test_create_user(rolename='test_role')
+
+ def test_create_user_with_system_role(self):
+ self.test_create_user(rolename='administrator')
+
+ def test_delete_user(self):
+ self.test_create_user()
+ out = self.exec_cmd('ac-user-delete', username='admin')
+ self.assertEqual(out, "User 'admin' deleted")
+ users = self.exec_cmd('ac-user-show')
+ self.assertEqual(len(users), 0)
+ self.validate_persistent_no_user('admin')
+
+ def test_create_duplicate_user(self):
+ self.test_create_user()
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-create', username='admin', inbuf='admin')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EEXIST)
+ self.assertEqual(str(ctx.exception), "User 'admin' already exists")
+
+ def test_create_users_with_dne_role(self):
+ # one time call to setup our persistent db
+ self.setup_and_load_persistent_db()
+
+ # create a user with a role that does not exist; expect a failure
+ try:
+ self.exec_cmd('ac-user-create', username='foo',
+ rolename='dne_role', inbuf='foopass',
+ name='foo User', email='foo@user.com')
+ except CmdException as e:
+ self.assertEqual(e.retcode, -errno.ENOENT)
+
+ db = self.load_persistent_db()
+ if 'users' in db:
+ self.assertNotIn('foo', db['users'])
+
+ # We could just finish our test here, given we ensured that the user
+ # with a non-existent role is not in persistent storage. However,
+ # we're going to test the database's consistency, making sure that
+ # side-effects are not written to persistent storage once we commit
+ # an unrelated operation. To ensure this, we'll issue another
+ # operation that is sharing the same code path, and will check whether
+ # the next operation commits dirty state.
+
+ # create a role (this will be 'test_role')
+ self.test_create_role()
+ self.exec_cmd('ac-user-create', username='bar',
+ rolename='test_role', inbuf='barpass',
+ name='bar User', email='bar@user.com')
+
+ # validate db:
+ # user 'foo' should not exist
+ # user 'bar' should exist and have role 'test_role'
+ self.validate_persistent_user('bar', ['test_role'])
+
+ db = self.load_persistent_db()
+ self.assertIn('users', db)
+ self.assertNotIn('foo', db['users'])
+
+ def test_delete_nonexistent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-delete', username='admin')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_add_user_roles(self, username='admin',
+ roles=['pool-manager', 'block-manager']):
+ user_orig = self.test_create_user(username)
+ uroles = []
+ for role in roles:
+ uroles.append(role)
+ uroles.sort()
+ user = self.exec_cmd('ac-user-add-roles', username=username,
+ roles=[role])
+ self.assertDictContainsSubset({'roles': uroles}, user)
+ self.validate_persistent_user(username, uroles)
+ self.assertGreaterEqual(user['lastUpdate'], user_orig['lastUpdate'])
+
+ def test_add_user_roles2(self):
+ user_orig = self.test_create_user()
+ user = self.exec_cmd('ac-user-add-roles', username="admin",
+ roles=['pool-manager', 'block-manager'])
+ self.assertDictContainsSubset(
+ {'roles': ['block-manager', 'pool-manager']}, user)
+ self.validate_persistent_user('admin', ['block-manager',
+ 'pool-manager'])
+ self.assertGreaterEqual(user['lastUpdate'], user_orig['lastUpdate'])
+
+ def test_add_user_roles_not_existent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-add-roles', username="admin",
+ roles=['pool-manager', 'block-manager'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_add_user_roles_not_existent_role(self):
+ self.test_create_user()
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-add-roles', username="admin",
+ roles=['Invalid Role'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception),
+ "Role 'Invalid Role' does not exist")
+
+ def test_set_user_roles(self):
+ user_orig = self.test_create_user()
+ user = self.exec_cmd('ac-user-add-roles', username="admin",
+ roles=['pool-manager'])
+ self.assertDictContainsSubset(
+ {'roles': ['pool-manager']}, user)
+ self.validate_persistent_user('admin', ['pool-manager'])
+ self.assertGreaterEqual(user['lastUpdate'], user_orig['lastUpdate'])
+ user2 = self.exec_cmd('ac-user-set-roles', username="admin",
+ roles=['rgw-manager', 'block-manager'])
+ self.assertDictContainsSubset(
+ {'roles': ['block-manager', 'rgw-manager']}, user2)
+ self.validate_persistent_user('admin', ['block-manager',
+ 'rgw-manager'])
+ self.assertGreaterEqual(user2['lastUpdate'], user['lastUpdate'])
+
+ def test_set_user_roles_not_existent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-set-roles', username="admin",
+ roles=['pool-manager', 'block-manager'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_set_user_roles_not_existent_role(self):
+ self.test_create_user()
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-set-roles', username="admin",
+ roles=['Invalid Role'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception),
+ "Role 'Invalid Role' does not exist")
+
+ def test_del_user_roles(self):
+ self.test_add_user_roles()
+ user = self.exec_cmd('ac-user-del-roles', username="admin",
+ roles=['pool-manager'])
+ self.assertDictContainsSubset(
+ {'roles': ['block-manager']}, user)
+ self.validate_persistent_user('admin', ['block-manager'])
+
+ def test_del_user_roles_not_existent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-del-roles', username="admin",
+ roles=['pool-manager', 'block-manager'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_del_user_roles_not_existent_role(self):
+ self.test_create_user()
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-del-roles', username="admin",
+ roles=['Invalid Role'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception),
+ "Role 'Invalid Role' does not exist")
+
+ def test_del_user_roles_not_associated_role(self):
+ self.test_create_user()
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-del-roles', username="admin",
+ roles=['rgw-manager'])
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception),
+ "Role 'rgw-manager' is not associated with user "
+ "'admin'")
+
+ def test_show_user(self):
+ self.test_add_user_roles()
+ user = self.exec_cmd('ac-user-show', username='admin')
+ pass_hash = password_hash('admin', user['password'])
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'lastUpdate': user['lastUpdate'],
+ 'password': pass_hash,
+ 'name': 'admin User',
+ 'email': 'admin@user.com',
+ 'roles': ['block-manager', 'pool-manager']
+ })
+
+ def test_show_nonexistent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-show', username='admin')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_show_all_users(self):
+ self.test_add_user_roles('admin', ['administrator'])
+ self.test_add_user_roles('guest', ['read-only'])
+ users = self.exec_cmd('ac-user-show')
+ self.assertEqual(len(users), 2)
+ for user in users:
+ self.assertIn(user, ['admin', 'guest'])
+
+ def test_del_role_associated_with_user(self):
+ self.test_create_role()
+ self.test_add_user_roles('guest', ['test_role'])
+
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-role-delete', rolename='test_role')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EPERM)
+ self.assertEqual(str(ctx.exception),
+ "Role 'test_role' is still associated with user "
+ "'guest'")
+
+ def test_set_user_info(self):
+ user_orig = self.test_create_user()
+ user = self.exec_cmd('ac-user-set-info', username='admin',
+ name='Admin Name', email='admin@admin.com')
+ pass_hash = password_hash('admin', user['password'])
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'password': pass_hash,
+ 'name': 'Admin Name',
+ 'email': 'admin@admin.com',
+ 'lastUpdate': user['lastUpdate'],
+ 'roles': []
+ })
+ self.validate_persistent_user('admin', [], pass_hash, 'Admin Name',
+ 'admin@admin.com')
+ self.assertEqual(user['lastUpdate'], user_orig['lastUpdate'])
+
+ def test_set_user_info_nonexistent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-set-info', username='admin',
+ name='Admin Name', email='admin@admin.com')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_set_user_password(self):
+ user_orig = self.test_create_user()
+ user = self.exec_cmd('ac-user-set-password', username='admin',
+ inbuf='newpass')
+ pass_hash = password_hash('newpass', user['password'])
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'password': pass_hash,
+ 'name': 'admin User',
+ 'email': 'admin@user.com',
+ 'lastUpdate': user['lastUpdate'],
+ 'roles': []
+ })
+ self.validate_persistent_user('admin', [], pass_hash, 'admin User',
+ 'admin@user.com')
+ self.assertGreaterEqual(user['lastUpdate'], user_orig['lastUpdate'])
+
+ def test_sanitize_password(self):
+ self.test_create_user()
+ password = 'myPass\\n\\r\\n'
+ with tempfile.TemporaryFile(mode='w+') as pwd_file:
+ # Add new line separators (like some text editors when a file is saved).
+ pwd_file.write('{}{}'.format(password, '\n\r\n\n'))
+ pwd_file.seek(0)
+ user = self.exec_cmd('ac-user-set-password', username='admin',
+ inbuf=pwd_file.read(), force_password=True)
+ pass_hash = password_hash(password, user['password'])
+ self.assertEqual(user['password'], pass_hash)
+
+ def test_unicode_password(self):
+ self.test_create_user()
+ password = '章鱼不是密码'
+ with tempfile.TemporaryFile(mode='w+') as pwd_file:
+ pwd_file.write(password)
+ pwd_file.seek(0)
+ user = self.exec_cmd('ac-user-set-password', username='admin',
+ inbuf=pwd_file.read(), force_password=True)
+ pass_hash = password_hash(password, user['password'])
+ self.assertEqual(user['password'], pass_hash)
+
+ def test_set_user_password_nonexistent_user(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-set-password', username='admin',
+ inbuf='newpass')
+
+ self.assertEqual(ctx.exception.retcode, -errno.ENOENT)
+ self.assertEqual(str(ctx.exception), "User 'admin' does not exist")
+
+ def test_set_user_password_empty(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('ac-user-set-password', username='admin', inbuf='\n')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+ self.assertEqual(str(ctx.exception), ERROR_MSG_EMPTY_INPUT_FILE)
+
+ def test_set_login_credentials(self):
+ self.exec_cmd('set-login-credentials', username='admin',
+ inbuf='admin')
+ user = self.exec_cmd('ac-user-show', username='admin')
+ pass_hash = password_hash('admin', user['password'])
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'password': pass_hash,
+ 'name': None,
+ 'email': None,
+ 'lastUpdate': user['lastUpdate'],
+ 'roles': ['administrator']
+ })
+ self.validate_persistent_user('admin', ['administrator'], pass_hash,
+ None, None)
+
+ def test_set_login_credentials_for_existing_user(self):
+ self.test_add_user_roles('admin', ['read-only'])
+ self.exec_cmd('set-login-credentials', username='admin',
+ inbuf='admin2')
+ user = self.exec_cmd('ac-user-show', username='admin')
+ pass_hash = password_hash('admin2', user['password'])
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'password': pass_hash,
+ 'name': 'admin User',
+ 'email': 'admin@user.com',
+ 'lastUpdate': user['lastUpdate'],
+ 'roles': ['read-only']
+ })
+ self.validate_persistent_user('admin', ['read-only'], pass_hash,
+ 'admin User', 'admin@user.com')
+
+ def test_load_v1(self):
+ self.CONFIG_KEY_DICT['accessdb_v1'] = '''
+ {{
+ "users": {{
+ "admin": {{
+ "username": "admin",
+ "password":
+ "$2b$12$sd0Az7mm3FaJl8kN3b/xwOuztaN0sWUwC1SJqjM4wcDw/s5cmGbLK",
+ "roles": ["block-manager", "test_role"],
+ "name": "admin User",
+ "email": "admin@user.com",
+ "lastUpdate": {}
+ }}
+ }},
+ "roles": {{
+ "test_role": {{
+ "name": "test_role",
+ "description": "Test Role",
+ "scopes_permissions": {{
+ "{}": ["{}", "{}"],
+ "{}": ["{}"]
+ }}
+ }}
+ }},
+ "version": 1
+ }}
+ '''.format(int(round(time.time())), Scope.ISCSI, Permission.READ,
+ Permission.UPDATE, Scope.POOL, Permission.CREATE)
+
+ load_access_control_db()
+ role = self.exec_cmd('ac-role-show', rolename="test_role")
+ self.assertDictEqual(role, {
+ 'name': 'test_role',
+ 'description': "Test Role",
+ 'scopes_permissions': {
+ Scope.ISCSI: [Permission.READ, Permission.UPDATE],
+ Scope.POOL: [Permission.CREATE]
+ }
+ })
+ user = self.exec_cmd('ac-user-show', username="admin")
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'lastUpdate': user['lastUpdate'],
+ 'password':
+ "$2b$12$sd0Az7mm3FaJl8kN3b/xwOuztaN0sWUwC1SJqjM4wcDw/s5cmGbLK",
+ 'name': 'admin User',
+ 'email': 'admin@user.com',
+ 'roles': ['block-manager', 'test_role']
+ })
+
+ def test_update_from_previous_version_v1(self):
+ self.CONFIG_KEY_DICT['username'] = 'admin'
+ self.CONFIG_KEY_DICT['password'] = \
+ '$2b$12$sd0Az7mm3FaJl8kN3b/xwOuztaN0sWUwC1SJqjM4wcDw/s5cmGbLK'
+ load_access_control_db()
+ user = self.exec_cmd('ac-user-show', username="admin")
+ self.assertDictEqual(user, {
+ 'username': 'admin',
+ 'lastUpdate': user['lastUpdate'],
+ 'password':
+ "$2b$12$sd0Az7mm3FaJl8kN3b/xwOuztaN0sWUwC1SJqjM4wcDw/s5cmGbLK",
+ 'name': None,
+ 'email': None,
+ 'roles': ['administrator']
+ })
diff --git a/src/pybind/mgr/dashboard/tests/test_api_auditing.py b/src/pybind/mgr/dashboard/tests/test_api_auditing.py
new file mode 100644
index 00000000..ae95e340
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_api_auditing.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import re
+import json
+import cherrypy
+import mock
+
+from . import ControllerTestCase, KVStoreMockMixin
+from ..controllers import RESTController, Controller
+from ..tools import RequestLoggingTool
+from .. import mgr
+
+
+# pylint: disable=W0613
+@Controller('/foo', secure=False)
+class FooResource(RESTController):
+ def create(self, password):
+ pass
+
+ def get(self, key):
+ pass
+
+ def delete(self, key):
+ pass
+
+ def set(self, key, password, secret_key=None):
+ pass
+
+
+class ApiAuditingTest(ControllerTestCase, KVStoreMockMixin):
+
+ def __init__(self, *args, **kwargs):
+ cherrypy.tools.request_logging = RequestLoggingTool()
+ cherrypy.config.update({'tools.request_logging.on': True})
+ super(ApiAuditingTest, self).__init__(*args, **kwargs)
+
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([FooResource])
+
+ def setUp(self):
+ self.mock_kv_store()
+ mgr.cluster_log = mock.Mock()
+ mgr.set_module_option('AUDIT_API_ENABLED', True)
+ mgr.set_module_option('AUDIT_API_LOG_PAYLOAD', True)
+
+ def _validate_cluster_log_msg(self, path, method, user, params):
+ channel, _, msg = mgr.cluster_log.call_args_list[0][0]
+ self.assertEqual(channel, 'audit')
+ pattern = r'^\[DASHBOARD\] from=\'(.+)\' path=\'(.+)\' ' \
+ 'method=\'(.+)\' user=\'(.+)\' params=\'(.+)\'$'
+ m = re.match(pattern, msg)
+ self.assertEqual(m.group(2), path)
+ self.assertEqual(m.group(3), method)
+ self.assertEqual(m.group(4), user)
+ self.assertDictEqual(json.loads(m.group(5)), params)
+
+ def test_no_audit(self):
+ mgr.set_module_option('AUDIT_API_ENABLED', False)
+ self._delete('/foo/test1')
+ mgr.cluster_log.assert_not_called()
+
+ def test_no_payload(self):
+ mgr.set_module_option('AUDIT_API_LOG_PAYLOAD', False)
+ self._delete('/foo/test1')
+ _, _, msg = mgr.cluster_log.call_args_list[0][0]
+ self.assertNotIn('params=', msg)
+
+ def test_no_audit_get(self):
+ self._get('/foo/test1')
+ mgr.cluster_log.assert_not_called()
+
+ def test_audit_put(self):
+ self._put('/foo/test1', {'password': 'y', 'secret_key': 1234})
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo/test1', 'PUT', 'None',
+ {'key': 'test1',
+ 'password': '***',
+ 'secret_key': '***'})
+
+ def test_audit_post(self):
+ with mock.patch('dashboard.services.auth.JwtManager.get_username',
+ return_value='hugo'):
+ self._post('/foo?password=1234')
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo', 'POST', 'hugo',
+ {'password': '***'})
+
+ def test_audit_delete(self):
+ self._delete('/foo/test1')
+ mgr.cluster_log.assert_called_once()
+ self._validate_cluster_log_msg('/foo/test1', 'DELETE',
+ 'None', {'key': 'test1'})
diff --git a/src/pybind/mgr/dashboard/tests/test_auth.py b/src/pybind/mgr/dashboard/tests/test_auth.py
new file mode 100644
index 00000000..6f1d2a08
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_auth.py
@@ -0,0 +1,20 @@
+import unittest
+
+from .. import mgr
+from ..services.auth import JwtManager
+
+
+class JwtManagerTest(unittest.TestCase):
+
+ def test_generate_token_and_decode(self):
+ mgr.get_module_option.return_value = JwtManager.JWT_TOKEN_TTL
+ mgr.get_store.return_value = 'jwt_secret'
+
+ token = JwtManager.gen_token('my-username')
+ self.assertIsInstance(token, str)
+ self.assertTrue(token)
+
+ decoded_token = JwtManager.decode_token(token)
+ self.assertIsInstance(decoded_token, dict)
+ self.assertEqual(decoded_token['iss'], 'ceph-dashboard')
+ self.assertEqual(decoded_token['username'], 'my-username')
diff --git a/src/pybind/mgr/dashboard/tests/test_ceph_service.py b/src/pybind/mgr/dashboard/tests/test_ceph_service.py
new file mode 100644
index 00000000..5111e68d
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_ceph_service.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=dangerous-default-value,too-many-public-methods
+from __future__ import absolute_import
+
+import unittest
+try:
+ import mock
+except ImportError:
+ import unittest.mock as mock
+
+from ..services.ceph_service import CephService
+
+
+class CephServiceTest(unittest.TestCase):
+ pools = [{
+ 'pool_name': 'good_pool',
+ 'pool': 1,
+ }, {
+ 'pool_name': 'bad_pool',
+ 'pool': 2,
+ 'flaky': 'option_x'
+ }]
+
+ def setUp(self):
+ # Mock get_pool_list
+ self.list_patch = mock.patch('dashboard.services.ceph_service.CephService.get_pool_list')
+ self.list = self.list_patch.start()
+ self.list.return_value = self.pools
+ # Mock mgr.get
+ self.mgr_patch = mock.patch('dashboard.mgr.get')
+ self.mgr = self.mgr_patch.start()
+ self.mgr.return_value = {
+ 'by_pool': {
+ '1': {'active+clean': 16},
+ '2': {'creating+incomplete': 16},
+ }
+ }
+ self.service = CephService()
+
+ def tearDown(self):
+ self.list_patch.stop()
+ self.mgr_patch.stop()
+
+ def test_get_pool_by_attribute_with_match(self):
+ self.assertEqual(self.service.get_pool_by_attribute('pool', 1), self.pools[0])
+ self.assertEqual(self.service.get_pool_by_attribute('pool_name', 'bad_pool'), self.pools[1])
+
+ def test_get_pool_by_attribute_without_a_match(self):
+ self.assertEqual(self.service.get_pool_by_attribute('pool', 3), None)
+ self.assertEqual(self.service.get_pool_by_attribute('not_there', 'sth'), None)
+
+ def test_get_pool_by_attribute_matching_a_not_always_set_attribute(self):
+ self.assertEqual(self.service.get_pool_by_attribute('flaky', 'option_x'), self.pools[1])
+
+ @mock.patch('dashboard.mgr.rados.pool_reverse_lookup', return_value='good_pool')
+ def test_get_pool_name_from_id_with_match(self, _mock):
+ self.assertEqual(self.service.get_pool_name_from_id(1), 'good_pool')
+
+ @mock.patch('dashboard.mgr.rados.pool_reverse_lookup', return_value=None)
+ def test_get_pool_name_from_id_without_match(self, _mock):
+ self.assertEqual(self.service.get_pool_name_from_id(3), None)
+
+ def test_get_pool_pg_status(self):
+ self.assertEqual(self.service.get_pool_pg_status('good_pool'), {'active+clean': 16})
+
+ def test_get_pg_status_without_match(self):
+ self.assertEqual(self.service.get_pool_pg_status('no-pool'), {})
diff --git a/src/pybind/mgr/dashboard/tests/test_cephfs.py b/src/pybind/mgr/dashboard/tests/test_cephfs.py
new file mode 100644
index 00000000..e9abda53
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_cephfs.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+from collections import defaultdict
+try:
+ from mock import Mock
+except ImportError:
+ from unittest.mock import Mock
+
+from .. import mgr
+from . import ControllerTestCase
+from ..controllers.cephfs import CephFS
+
+
+class MetaDataMock(object):
+ def get(self, _x, _y):
+ return 'bar'
+
+
+def get_metadata_mock(key, meta_key):
+ return {
+ 'mds': {
+ None: None, # Unknown key
+ 'foo': MetaDataMock()
+ }[meta_key]
+ }[key]
+
+
+class CephFsTest(ControllerTestCase):
+ cephFs = CephFS()
+
+ @classmethod
+ def setup_server(cls):
+ mgr.get_metadata = Mock(side_effect=get_metadata_mock)
+
+ def tearDown(self):
+ mgr.get_metadata.stop()
+
+ def test_append_of_mds_metadata_if_key_is_not_found(self):
+ mds_versions = defaultdict(list)
+ # pylint: disable=protected-access
+ self.cephFs._append_mds_metadata(mds_versions, None)
+ self.assertEqual(len(mds_versions), 0)
+
+ def test_append_of_mds_metadata_with_existing_metadata(self):
+ mds_versions = defaultdict(list)
+ # pylint: disable=protected-access
+ self.cephFs._append_mds_metadata(mds_versions, 'foo')
+ self.assertEqual(len(mds_versions), 1)
+ self.assertEqual(mds_versions['bar'], ['foo'])
diff --git a/src/pybind/mgr/dashboard/tests/test_controllers.py b/src/pybind/mgr/dashboard/tests/test_controllers.py
new file mode 100644
index 00000000..0e880470
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_controllers.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ControllerTestCase
+from ..controllers import BaseController, RESTController, Controller, \
+ ApiController, Endpoint
+
+
+@Controller("/btest/{key}", base_url="/ui", secure=False)
+class BTest(BaseController):
+ @Endpoint()
+ def test1(self, key, opt=1):
+ return {'key': key, 'opt': opt}
+
+ @Endpoint()
+ def test2(self, key, skey, opt=1):
+ return {'key': key, 'skey': skey, 'opt': opt}
+
+ @Endpoint(path="/foo/{skey}/test-3")
+ def test3(self, key, skey, opt=1):
+ return {'key': key, 'skey': skey, 'opt': opt}
+
+ @Endpoint('POST', path="/foo/{skey}/test-3", query_params=['opt'])
+ def test4(self, key, skey, data, opt=1):
+ return {'key': key, 'skey': skey, 'data': data, 'opt': opt}
+
+ @Endpoint('PUT', path_params=['skey'], query_params=['opt'])
+ def test5(self, key, skey, data1, data2=None, opt=1):
+ return {'key': key, 'skey': skey, 'data1': data1, 'data2': data2,
+ 'opt': opt}
+
+ @Endpoint('GET', json_response=False)
+ def test6(self, key, opt=1):
+ return "My Formatted string key={} opt={}".format(key, opt)
+
+ @Endpoint()
+ def __call__(self, key, opt=1):
+ return {'key': key, 'opt': opt}
+
+
+@ApiController("/rtest/{key}", secure=False)
+class RTest(RESTController):
+ RESOURCE_ID = 'skey/ekey'
+
+ def list(self, key, opt=1):
+ return {'key': key, 'opt': opt}
+
+ def create(self, key, data1, data2=None):
+ return {'key': key, 'data1': data1, 'data2': data2}
+
+ def get(self, key, skey, ekey, opt=1):
+ return {'key': key, 'skey': skey, 'ekey': ekey, 'opt': opt}
+
+ def set(self, key, skey, ekey, data):
+ return {'key': key, 'skey': skey, 'ekey': ekey, 'data': data}
+
+ def delete(self, key, skey, ekey, opt=1):
+ pass
+
+ def bulk_set(self, key, data1, data2=None):
+ return {'key': key, 'data1': data1, 'data2': data2}
+
+ def bulk_delete(self, key, opt=1):
+ pass
+
+ @RESTController.Collection('POST')
+ def cmethod(self, key, data):
+ return {'key': key, 'data': data}
+
+ @RESTController.Resource('GET')
+ def rmethod(self, key, skey, ekey, opt=1):
+ return {'key': key, 'skey': skey, 'ekey': ekey, 'opt': opt}
+
+
+@Controller("/", secure=False)
+class Root(BaseController):
+ @Endpoint(json_response=False)
+ def __call__(self):
+ return "<html></html>"
+
+
+class ControllersTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([BTest, RTest], "/test")
+
+ def test_1(self):
+ self._get('/test/ui/btest/{}/test1?opt=3'.format(100))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'opt': '3'})
+
+ def test_2(self):
+ self._get('/test/ui/btest/{}/test2/{}?opt=3'.format(100, 200))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'skey': '200', 'opt': '3'})
+
+ def test_3(self):
+ self._get('/test/ui/btest/{}/foo/{}/test-3?opt=3'.format(100, 200))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'skey': '200', 'opt': '3'})
+
+ def test_4(self):
+ self._post('/test/ui/btest/{}/foo/{}/test-3?opt=3'.format(100, 200),
+ {'data': 30})
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'skey': '200', 'data': 30,
+ 'opt': '3'})
+
+ def test_5(self):
+ self._put('/test/ui/btest/{}/test5/{}?opt=3'.format(100, 200),
+ {'data1': 40, 'data2': "hello"})
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'skey': '200', 'data1': 40,
+ 'data2': "hello", 'opt': '3'})
+
+ def test_6(self):
+ self._get('/test/ui/btest/{}/test6'.format(100))
+ self.assertStatus(200)
+ self.assertBody("My Formatted string key=100 opt=1")
+
+ def test_7(self):
+ self._get('/test/ui/btest/{}?opt=3'.format(100))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '100', 'opt': '3'})
+
+ def test_rest_list(self):
+ self._get('/test/api/rtest/{}?opt=2'.format(300))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'opt': '2'})
+
+ def test_rest_create(self):
+ self._post('/test/api/rtest/{}'.format(300),
+ {'data1': 20, 'data2': True})
+ self.assertStatus(201)
+ self.assertJsonBody({'key': '300', 'data1': 20, 'data2': True})
+
+ def test_rest_get(self):
+ self._get('/test/api/rtest/{}/{}/{}?opt=3'.format(300, 1, 2))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'skey': '1', 'ekey': '2',
+ 'opt': '3'})
+
+ def test_rest_set(self):
+ self._put('/test/api/rtest/{}/{}/{}'.format(300, 1, 2),
+ {'data': 40})
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'skey': '1', 'ekey': '2',
+ 'data': 40})
+
+ def test_rest_delete(self):
+ self._delete('/test/api/rtest/{}/{}/{}?opt=3'.format(300, 1, 2))
+ self.assertStatus(204)
+
+ def test_rest_bulk_set(self):
+ self._put('/test/api/rtest/{}'.format(300),
+ {'data1': 20, 'data2': True})
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'data1': 20, 'data2': True})
+
+ self._put('/test/api/rtest/{}'.format(400),
+ {'data1': 20, 'data2': ['one', 'two', 'three']})
+ self.assertStatus(200)
+ self.assertJsonBody({
+ 'key': '400',
+ 'data1': 20,
+ 'data2': ['one', 'two', 'three'],
+ })
+
+ def test_rest_bulk_delete(self):
+ self._delete('/test/api/rtest/{}?opt=2'.format(300))
+ self.assertStatus(204)
+
+ def test_rest_collection(self):
+ self._post('/test/api/rtest/{}/cmethod'.format(300), {'data': 30})
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'data': 30})
+
+ def test_rest_resource(self):
+ self._get('/test/api/rtest/{}/{}/{}/rmethod?opt=4'.format(300, 2, 3))
+ self.assertStatus(200)
+ self.assertJsonBody({'key': '300', 'skey': '2', 'ekey': '3',
+ 'opt': '4'})
+
+
+class RootControllerTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([Root])
+
+ def test_index(self):
+ self._get("/")
+ self.assertBody("<html></html>")
diff --git a/src/pybind/mgr/dashboard/tests/test_docs.py b/src/pybind/mgr/dashboard/tests/test_docs.py
new file mode 100644
index 00000000..4d6c2576
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_docs.py
@@ -0,0 +1,71 @@
+# # -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ControllerTestCase
+from ..controllers import RESTController, ApiController, Endpoint, EndpointDoc, ControllerDoc
+from ..controllers.docs import Docs
+
+
+# Dummy controller and endpoint that can be assigned with @EndpointDoc and @GroupDoc
+@ControllerDoc("Group description", group="FooGroup")
+@ApiController("/doctest/", secure=False)
+class DecoratedController(RESTController):
+ @EndpointDoc(
+ description="Endpoint description",
+ group="BarGroup",
+ parameters={
+ 'parameter': (int, "Description of parameter"),
+ },
+ responses={
+ 200: {
+ 'resp': (str, 'Description of response')
+ },
+ },
+ )
+ @Endpoint(json_response=False)
+ def decorated_func(self, parameter):
+ pass
+
+
+# To assure functionality of @EndpointDoc, @GroupDoc
+class DocDecoratorsTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([DecoratedController, Docs], "/test")
+
+ def test_group_info_attr(self):
+ test_ctrl = DecoratedController()
+ self.assertTrue(hasattr(test_ctrl, 'doc_info'))
+ self.assertIn('tag_descr', test_ctrl.doc_info)
+ self.assertIn('tag', test_ctrl.doc_info)
+
+ def test_endpoint_info_attr(self):
+ test_ctrl = DecoratedController()
+ test_endpoint = test_ctrl.decorated_func
+ self.assertTrue(hasattr(test_endpoint, 'doc_info'))
+ self.assertIn('summary', test_endpoint.doc_info)
+ self.assertIn('tag', test_endpoint.doc_info)
+ self.assertIn('parameters', test_endpoint.doc_info)
+ self.assertIn('response', test_endpoint.doc_info)
+
+
+# To assure functionality of Docs.py
+# pylint: disable=protected-access
+class DocsTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([Docs], "/test")
+
+ def test_type_to_str(self):
+ self.assertEqual(Docs()._type_to_str(str), "string")
+
+ def test_gen_paths(self):
+ outcome = Docs()._gen_paths(False, "")['/api/doctest//decorated_func/{parameter}']['get']
+ self.assertIn('tags', outcome)
+ self.assertIn('summary', outcome)
+ self.assertIn('parameters', outcome)
+ self.assertIn('responses', outcome)
+
+ def test_gen_tags(self):
+ outcome = Docs()._gen_tags(False)[0]
+ self.assertEqual({'description': 'Group description', 'name': 'FooGroup'}, outcome)
diff --git a/src/pybind/mgr/dashboard/tests/test_erasure_code_profile.py b/src/pybind/mgr/dashboard/tests/test_erasure_code_profile.py
new file mode 100644
index 00000000..88575c0a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_erasure_code_profile.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+from .. import mgr
+from . import ControllerTestCase
+from ..controllers.erasure_code_profile import ErasureCodeProfile
+
+
+class ErasureCodeProfileTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ mgr.get.side_effect = lambda key: {
+ 'osd_map': {
+ 'erasure_code_profiles': {
+ 'test': {
+ 'k': '2',
+ 'm': '1'
+ }
+ }
+ },
+ 'health': {'json': '{"status": 1}'},
+ 'fs_map': {'filesystems': []},
+
+ }[key]
+ # pylint: disable=protected-access
+ ErasureCodeProfile._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([ErasureCodeProfile])
+
+ def test_list(self):
+ self._get('/api/erasure_code_profile')
+ self.assertStatus(200)
+ self.assertJsonBody([{'k': 2, 'm': 1, 'name': 'test'}])
+
+ def test_get(self):
+ self._get('/api/erasure_code_profile/test')
+ self.assertStatus(200)
+ self.assertJsonBody({'k': 2, 'm': 1, 'name': 'test'})
diff --git a/src/pybind/mgr/dashboard/tests/test_exceptions.py b/src/pybind/mgr/dashboard/tests/test_exceptions.py
new file mode 100644
index 00000000..5607f1dd
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_exceptions.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import time
+
+import rados
+
+from . import ControllerTestCase
+from ..services.ceph_service import SendCommandError
+from ..controllers import RESTController, Controller, Task, Endpoint
+from ..services.exception import handle_rados_error, handle_send_command_error, \
+ serialize_dashboard_exception
+from ..tools import ViewCache, TaskManager, NotificationQueue
+
+
+# pylint: disable=W0613
+@Controller('foo', secure=False)
+class FooResource(RESTController):
+
+ @Endpoint()
+ @handle_rados_error('foo')
+ def no_exception(self, param1, param2):
+ return [param1, param2]
+
+ @Endpoint()
+ @handle_rados_error('foo')
+ def error_foo_controller(self):
+ raise rados.OSError('hi', errno=-42)
+
+ @Endpoint()
+ @handle_send_command_error('foo')
+ def error_send_command(self):
+ raise SendCommandError('hi', 'prefix', {}, -42)
+
+ @Endpoint()
+ def error_generic(self):
+ raise rados.Error('hi')
+
+ @Endpoint()
+ def vc_no_data(self):
+ @ViewCache(timeout=0)
+ def _no_data():
+ time.sleep(0.2)
+
+ _no_data()
+ assert False
+
+ @handle_rados_error('foo')
+ @Endpoint()
+ def vc_exception(self):
+ @ViewCache(timeout=10)
+ def _raise():
+ raise rados.OSError('hi', errno=-42)
+
+ _raise()
+ assert False
+
+ @Endpoint()
+ def internal_server_error(self):
+ return 1/0
+
+ @handle_send_command_error('foo')
+ def list(self):
+ raise SendCommandError('list', 'prefix', {}, -42)
+
+ @Endpoint()
+ @Task('task_exceptions/task_exception', {1: 2}, 1.0,
+ exception_handler=serialize_dashboard_exception)
+ @handle_rados_error('foo')
+ def task_exception(self):
+ raise rados.OSError('hi', errno=-42)
+
+ @Endpoint()
+ def wait_task_exception(self):
+ ex, _ = TaskManager.list('task_exceptions/task_exception')
+ return bool(len(ex))
+
+
+# pylint: disable=C0102
+class Root(object):
+ foo = FooResource()
+
+
+class RESTControllerTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ NotificationQueue.start_queue()
+ TaskManager.init()
+ cls.setup_controllers([FooResource])
+
+ def test_no_exception(self):
+ self._get('/foo/no_exception/a/b')
+ self.assertStatus(200)
+ self.assertJsonBody(
+ ['a', 'b']
+ )
+
+ def test_error_foo_controller(self):
+ self._get('/foo/error_foo_controller')
+ self.assertStatus(400)
+ self.assertJsonBody(
+ {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo'}
+ )
+
+ def test_error_send_command(self):
+ self._get('/foo/error_send_command')
+ self.assertStatus(400)
+ self.assertJsonBody(
+ {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo'}
+ )
+
+ def test_error_send_command_list(self):
+ self._get('/foo/')
+ self.assertStatus(400)
+ self.assertJsonBody(
+ {'detail': '[errno -42] list', 'code': "42", 'component': 'foo'}
+ )
+
+ def test_error_foo_generic(self):
+ self._get('/foo/error_generic')
+ self.assertJsonBody({'detail': 'hi', 'code': 'Error', 'component': None})
+ self.assertStatus(400)
+
+ def test_viewcache_no_data(self):
+ self._get('/foo/vc_no_data')
+ self.assertStatus(200)
+ self.assertJsonBody({'status': ViewCache.VALUE_NONE, 'value': None})
+
+ def test_viewcache_exception(self):
+ self._get('/foo/vc_exception')
+ self.assertStatus(400)
+ self.assertJsonBody(
+ {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo'}
+ )
+
+ def test_task_exception(self):
+ self._get('/foo/task_exception')
+ self.assertStatus(400)
+ self.assertJsonBody(
+ {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo',
+ 'task': {'name': 'task_exceptions/task_exception', 'metadata': {'1': 2}}}
+ )
+
+ self._get('/foo/wait_task_exception')
+ while self.jsonBody():
+ time.sleep(0.5)
+ self._get('/foo/wait_task_exception')
+
+ def test_internal_server_error(self):
+ self._get('/foo/internal_server_error')
+ self.assertStatus(500)
+ self.assertIn('unexpected condition', self.jsonBody()['detail'])
+
+ def test_404(self):
+ self._get('/foonot_found')
+ self.assertStatus(404)
+ self.assertIn('detail', self.jsonBody())
diff --git a/src/pybind/mgr/dashboard/tests/test_feature_toggles.py b/src/pybind/mgr/dashboard/tests/test_feature_toggles.py
new file mode 100644
index 00000000..5c70c88a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_feature_toggles.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import unittest
+from mock import Mock, patch
+
+from . import KVStoreMockMixin
+from ..plugins.feature_toggles import FeatureToggles, Features
+
+
+class SettingsTest(unittest.TestCase, KVStoreMockMixin):
+ @classmethod
+ def setUpClass(cls):
+ cls.mock_kv_store()
+ cls.CONFIG_KEY_DICT['url_prefix'] = ''
+
+ # Mock MODULE_OPTIONS
+ from .. import mgr
+ cls.mgr = mgr
+
+ # Populate real endpoint map
+ from ..controllers import load_controllers
+ cls.controllers = load_controllers()
+
+ # Initialize FeatureToggles plugin
+ cls.plugin = FeatureToggles()
+ cls.CONFIG_KEY_DICT.update(
+ {k['name']: k['default'] for k in cls.plugin.get_options()})
+ cls.plugin.setup()
+
+ def test_filter_request_when_all_features_enabled(self):
+ """
+ This test iterates over all the registered endpoints to ensure that, with default
+ feature toggles, none is disabled.
+ """
+ import cherrypy
+
+ request = Mock()
+ for controller in self.controllers:
+ request.path_info = controller.get_path()
+ try:
+ self.plugin.filter_request_before_handler(request)
+ except cherrypy.HTTPError:
+ self.fail("Request filtered {} and it shouldn't".format(
+ request.path_info))
+
+ def test_filter_request_when_some_feature_enabled(self):
+ """
+ This test focuses on a single feature and checks whether it's actually
+ disabled
+ """
+ import cherrypy
+
+ self.plugin.register_commands()['handle_command'](
+ self.mgr, 'disable', ['cephfs'])
+
+ with patch.object(self.plugin, '_get_feature_from_request',
+ return_value=Features.CEPHFS):
+ with self.assertRaises(cherrypy.HTTPError):
+ request = Mock()
+ self.plugin.filter_request_before_handler(request)
diff --git a/src/pybind/mgr/dashboard/tests/test_ganesha.py b/src/pybind/mgr/dashboard/tests/test_ganesha.py
new file mode 100644
index 00000000..5dced126
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_ganesha.py
@@ -0,0 +1,642 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import unittest
+
+from mock import MagicMock, Mock
+
+import orchestrator
+from . import KVStoreMockMixin
+from .. import mgr
+from ..settings import Settings
+from ..services import ganesha
+from ..services.ganesha import GaneshaConf, Export, GaneshaConfParser
+
+
+class GaneshaConfTest(unittest.TestCase, KVStoreMockMixin):
+ export_1 = """
+EXPORT {
+ Export_ID=1;
+ Protocols = 4;
+ Path = /;
+ Pseudo = /cephfs_a/;
+ Access_Type = RW;
+ Protocols = 4;
+ Attr_Expiration_Time = 0;
+ # Delegations = R;
+ # Squash = root;
+
+ FSAL {
+ Name = CEPH;
+ Filesystem = "a";
+ User_Id = "ganesha";
+ # Secret_Access_Key = "YOUR SECRET KEY HERE";
+ }
+
+ CLIENT
+ {
+ Clients = 192.168.0.10, 192.168.1.0/8;
+ Squash = None;
+ }
+
+ CLIENT
+ {
+ Clients = 192.168.0.0/16;
+ Squash = All;
+ Access_Type = RO;
+ }
+}
+"""
+
+ export_2 = """
+EXPORT
+{
+ Export_ID=2;
+
+ Path = "/";
+
+ Pseudo = "/rgw";
+
+ Access_Type = RW;
+
+ squash = AllAnonymous;
+
+ Protocols = 4, 3;
+
+ Transports = TCP, UDP;
+
+ FSAL {
+ Name = RGW;
+ User_Id = "testuser";
+ Access_Key_Id ="access_key";
+ Secret_Access_Key = "secret_key";
+ }
+}
+"""
+
+ conf_nodea = '''
+%url rados://ganesha/ns/export-2
+
+%url "rados://ganesha/ns/export-1"'''
+
+ conf_nodeb = '%url "rados://ganesha/ns/export-1"'
+
+ class RObject(object):
+ def __init__(self, key, raw):
+ self.key = key
+ self.raw = raw
+
+ def read(self, _):
+ return self.raw.encode('utf-8')
+
+ def stat(self):
+ return len(self.raw), None
+
+ def _ioctx_write_full_mock(self, key, content):
+ if key not in self.temp_store:
+ self.temp_store[key] = GaneshaConfTest.RObject(key,
+ content.decode('utf-8'))
+ else:
+ self.temp_store[key].raw = content.decode('utf-8')
+
+ def _ioctx_remove_mock(self, key):
+ del self.temp_store[key]
+
+ def _ioctx_list_objects_mock(self):
+ return [obj for _, obj in self.temp_store.items()]
+
+ def setUp(self):
+ self.mock_kv_store()
+
+ Settings.GANESHA_CLUSTERS_RADOS_POOL_NAMESPACE = "ganesha/ns"
+
+ self.temp_store = {
+ 'export-1': GaneshaConfTest.RObject("export-1", self.export_1),
+ 'conf-nodea': GaneshaConfTest.RObject("conf-nodea", self.conf_nodea),
+ 'export-2': GaneshaConfTest.RObject("export-2", self.export_2),
+ 'conf-nodeb': GaneshaConfTest.RObject("conf-nodeb", self.conf_nodeb)
+ }
+
+ self.io_mock = MagicMock()
+ self.io_mock.list_objects.side_effect = self._ioctx_list_objects_mock
+ self.io_mock.write_full.side_effect = self._ioctx_write_full_mock
+ self.io_mock.remove_object.side_effect = self._ioctx_remove_mock
+
+ ioctx_mock = MagicMock()
+ ioctx_mock.__enter__ = Mock(return_value=(self.io_mock))
+ ioctx_mock.__exit__ = Mock(return_value=None)
+
+ mgr.rados = MagicMock()
+ mgr.rados.open_ioctx.return_value = ioctx_mock
+
+ # pylint: disable=protected-access
+ mgr._select_orchestrator.side_effect = orchestrator.NoOrchestrator()
+
+ ganesha.CephX = MagicMock()
+ ganesha.CephX.list_clients.return_value = ['ganesha']
+ ganesha.CephX.get_client_key.return_value = 'ganesha'
+
+ ganesha.CephFS = MagicMock()
+
+ def test_export_parser_1(self):
+ blocks = GaneshaConfParser(self.export_1).parse()
+ self.assertIsInstance(blocks, list)
+ self.assertEqual(len(blocks), 1)
+ export = Export.from_export_block(blocks[0], '_default_',
+ GaneshaConf.ganesha_defaults({}))
+
+ self.assertEqual(export.export_id, 1)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/cephfs_a")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "root_squash")
+ self.assertEqual(export.protocols, {4})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "CEPH")
+ self.assertEqual(export.fsal.user_id, "ganesha")
+ self.assertEqual(export.fsal.fs_name, "a")
+ self.assertEqual(export.fsal.sec_label_xattr, None)
+ self.assertEqual(len(export.clients), 2)
+ self.assertEqual(export.clients[0].addresses,
+ ["192.168.0.10", "192.168.1.0/8"])
+ self.assertEqual(export.clients[0].squash, "no_root_squash")
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.clients[1].addresses, ["192.168.0.0/16"])
+ self.assertEqual(export.clients[1].squash, "all_squash")
+ self.assertEqual(export.clients[1].access_type, "RO")
+ self.assertEqual(export.cluster_id, '_default_')
+ self.assertEqual(export.attr_expiration_time, 0)
+ self.assertEqual(export.security_label, False)
+
+ def test_export_parser_2(self):
+ blocks = GaneshaConfParser(self.export_2).parse()
+ self.assertIsInstance(blocks, list)
+ self.assertEqual(len(blocks), 1)
+ export = Export.from_export_block(blocks[0], '_default_',
+ GaneshaConf.ganesha_defaults({}))
+
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/rgw")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key")
+ self.assertEqual(export.fsal.secret_key, "secret_key")
+ self.assertEqual(len(export.clients), 0)
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_daemon_conf_parser_a(self):
+ blocks = GaneshaConfParser(self.conf_nodea).parse()
+ self.assertIsInstance(blocks, list)
+ self.assertEqual(len(blocks), 2)
+ self.assertEqual(blocks[0]['block_name'], "%url")
+ self.assertEqual(blocks[0]['value'], "rados://ganesha/ns/export-2")
+ self.assertEqual(blocks[1]['block_name'], "%url")
+ self.assertEqual(blocks[1]['value'], "rados://ganesha/ns/export-1")
+
+ def test_daemon_conf_parser_b(self):
+ blocks = GaneshaConfParser(self.conf_nodeb).parse()
+ self.assertIsInstance(blocks, list)
+ self.assertEqual(len(blocks), 1)
+ self.assertEqual(blocks[0]['block_name'], "%url")
+ self.assertEqual(blocks[0]['value'], "rados://ganesha/ns/export-1")
+
+ def test_ganesha_conf(self):
+ ganesha_conf = GaneshaConf.instance('_default_')
+ exports = ganesha_conf.exports
+
+ self.assertEqual(len(exports.items()), 2)
+ self.assertIn(1, exports)
+ self.assertIn(2, exports)
+
+ # export_id = 1 asserts
+ export = exports[1]
+ self.assertEqual(export.export_id, 1)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/cephfs_a")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "root_squash")
+ self.assertEqual(export.protocols, {4})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "CEPH")
+ self.assertEqual(export.fsal.user_id, "ganesha")
+ self.assertEqual(export.fsal.fs_name, "a")
+ self.assertEqual(export.fsal.sec_label_xattr, None)
+ self.assertEqual(len(export.clients), 2)
+ self.assertEqual(export.clients[0].addresses,
+ ["192.168.0.10", "192.168.1.0/8"])
+ self.assertEqual(export.clients[0].squash, "no_root_squash")
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.clients[1].addresses, ["192.168.0.0/16"])
+ self.assertEqual(export.clients[1].squash, "all_squash")
+ self.assertEqual(export.clients[1].access_type, "RO")
+ self.assertEqual(export.attr_expiration_time, 0)
+ self.assertEqual(export.security_label, False)
+
+ # export_id = 2 asserts
+ export = exports[2]
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/rgw")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key")
+ self.assertEqual(export.fsal.secret_key, "secret_key")
+ self.assertEqual(len(export.clients), 0)
+
+ def test_config_dict(self):
+ conf = GaneshaConf.instance('_default_')
+ export = conf.exports[1]
+ ex_dict = export.to_dict()
+ self.assertDictEqual(ex_dict, {
+ 'daemons': ['nodea', 'nodeb'],
+ 'export_id': 1,
+ 'path': '/',
+ 'pseudo': '/cephfs_a',
+ 'cluster_id': '_default_',
+ 'tag': None,
+ 'access_type': 'RW',
+ 'squash': 'root_squash',
+ 'security_label': False,
+ 'protocols': [4],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [{
+ 'addresses': ["192.168.0.10", "192.168.1.0/8"],
+ 'access_type': None,
+ 'squash': 'no_root_squash'
+ }, {
+ 'addresses': ["192.168.0.0/16"],
+ 'access_type': 'RO',
+ 'squash': 'all_squash'
+ }],
+ 'fsal': {
+ 'name': 'CEPH',
+ 'user_id': 'ganesha',
+ 'fs_name': 'a',
+ 'sec_label_xattr': None
+ }
+ })
+
+ export = conf.exports[2]
+ ex_dict = export.to_dict()
+ self.assertDictEqual(ex_dict, {
+ 'daemons': ['nodea'],
+ 'export_id': 2,
+ 'path': '/',
+ 'pseudo': '/rgw',
+ 'cluster_id': '_default_',
+ 'tag': None,
+ 'access_type': 'RW',
+ 'squash': 'all_squash',
+ 'security_label': False,
+ 'protocols': [3, 4],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [],
+ 'fsal': {
+ 'name': 'RGW',
+ 'rgw_user_id': 'testuser'
+ }
+ })
+
+ def test_config_from_dict(self):
+ export = Export.from_dict(1, {
+ 'daemons': ['nodea', 'nodeb'],
+ 'export_id': 1,
+ 'path': '/',
+ 'cluster_id': '_default_',
+ 'pseudo': '/cephfs_a',
+ 'tag': None,
+ 'access_type': 'RW',
+ 'squash': 'root_squash',
+ 'security_label': True,
+ 'protocols': [4],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [{
+ 'addresses': ["192.168.0.10", "192.168.1.0/8"],
+ 'access_type': None,
+ 'squash': 'no_root_squash'
+ }, {
+ 'addresses': ["192.168.0.0/16"],
+ 'access_type': 'RO',
+ 'squash': 'all_squash'
+ }],
+ 'fsal': {
+ 'name': 'CEPH',
+ 'user_id': 'ganesha',
+ 'fs_name': 'a',
+ 'sec_label_xattr': 'security.selinux'
+ }
+ })
+
+ self.assertEqual(export.export_id, 1)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/cephfs_a")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "root_squash")
+ self.assertEqual(export.protocols, {4})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "CEPH")
+ self.assertEqual(export.fsal.user_id, "ganesha")
+ self.assertEqual(export.fsal.fs_name, "a")
+ self.assertEqual(export.fsal.sec_label_xattr, 'security.selinux')
+ self.assertEqual(len(export.clients), 2)
+ self.assertEqual(export.clients[0].addresses,
+ ["192.168.0.10", "192.168.1.0/8"])
+ self.assertEqual(export.clients[0].squash, "no_root_squash")
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.clients[1].addresses, ["192.168.0.0/16"])
+ self.assertEqual(export.clients[1].squash, "all_squash")
+ self.assertEqual(export.clients[1].access_type, "RO")
+ self.assertEqual(export.daemons, {"nodeb", "nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+ self.assertEqual(export.attr_expiration_time, 0)
+ self.assertEqual(export.security_label, True)
+
+ export = Export.from_dict(2, {
+ 'daemons': ['nodea'],
+ 'export_id': 2,
+ 'path': '/',
+ 'pseudo': '/rgw',
+ 'cluster_id': '_default_',
+ 'tag': None,
+ 'access_type': 'RW',
+ 'squash': 'all_squash',
+ 'security_label': False,
+ 'protocols': [4, 3],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [],
+ 'fsal': {
+ 'name': 'RGW',
+ 'rgw_user_id': 'testuser'
+ }
+ })
+
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/rgw")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertIsNone(export.fsal.access_key)
+ self.assertIsNone(export.fsal.secret_key)
+ self.assertEqual(len(export.clients), 0)
+ self.assertEqual(export.daemons, {"nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_gen_raw_config(self):
+ conf = GaneshaConf.instance('_default_')
+ # pylint: disable=W0212
+ export = conf.exports[1]
+ del conf.exports[1]
+ conf._save_export(export)
+ conf = GaneshaConf.instance('_default_')
+ exports = conf.exports
+ self.assertEqual(len(exports.items()), 2)
+ self.assertIn(1, exports)
+ self.assertIn(2, exports)
+
+ # export_id = 1 asserts
+ export = exports[1]
+ self.assertEqual(export.export_id, 1)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/cephfs_a")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "root_squash")
+ self.assertEqual(export.protocols, {4})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "CEPH")
+ self.assertEqual(export.fsal.user_id, "ganesha")
+ self.assertEqual(export.fsal.fs_name, "a")
+ self.assertEqual(export.fsal.sec_label_xattr, None)
+ self.assertEqual(len(export.clients), 2)
+ self.assertEqual(export.clients[0].addresses,
+ ["192.168.0.10", "192.168.1.0/8"])
+ self.assertEqual(export.clients[0].squash, "no_root_squash")
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.clients[1].addresses, ["192.168.0.0/16"])
+ self.assertEqual(export.clients[1].squash, "all_squash")
+ self.assertEqual(export.clients[1].access_type, "RO")
+ self.assertEqual(export.daemons, {"nodeb", "nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+ self.assertEqual(export.attr_expiration_time, 0)
+ self.assertEqual(export.security_label, False)
+
+ # export_id = 2 asserts
+ export = exports[2]
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/rgw")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key")
+ self.assertEqual(export.fsal.secret_key, "secret_key")
+ self.assertEqual(len(export.clients), 0)
+ self.assertEqual(export.daemons, {"nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_update_export(self):
+ ganesha.RgwClient = MagicMock()
+ admin_inst_mock = MagicMock()
+ admin_inst_mock.get_user_keys.return_value = {
+ 'access_key': 'access_key',
+ 'secret_key': 'secret_key'
+ }
+ ganesha.RgwClient.admin_instance.return_value = admin_inst_mock
+
+ conf = GaneshaConf.instance('_default_')
+ conf.update_export({
+ 'export_id': 2,
+ 'daemons': ["nodeb"],
+ 'path': 'bucket',
+ 'pseudo': '/rgw/bucket',
+ 'cluster_id': '_default_',
+ 'tag': 'bucket_tag',
+ 'access_type': 'RW',
+ 'squash': 'all_squash',
+ 'security_label': False,
+ 'protocols': [4, 3],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [{
+ 'addresses': ["192.168.0.0/16"],
+ 'access_type': None,
+ 'squash': None
+ }],
+ 'fsal': {
+ 'name': 'RGW',
+ 'rgw_user_id': 'testuser'
+ }
+ })
+
+ conf = GaneshaConf.instance('_default_')
+ export = conf.get_export(2)
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "bucket")
+ self.assertEqual(export.pseudo, "/rgw/bucket")
+ self.assertEqual(export.tag, "bucket_tag")
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key")
+ self.assertEqual(export.fsal.secret_key, "secret_key")
+ self.assertEqual(len(export.clients), 1)
+ self.assertEqual(export.clients[0].addresses, ["192.168.0.0/16"])
+ self.assertIsNone(export.clients[0].squash)
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.daemons, {"nodeb"})
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_remove_export(self):
+ conf = GaneshaConf.instance('_default_')
+ conf.remove_export(1)
+ exports = conf.list_exports()
+ self.assertEqual(len(exports), 1)
+ self.assertEqual(2, exports[0].export_id)
+ export = conf.get_export(2)
+ self.assertEqual(export.export_id, 2)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/rgw")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key")
+ self.assertEqual(export.fsal.secret_key, "secret_key")
+ self.assertEqual(len(export.clients), 0)
+ self.assertEqual(export.daemons, {"nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_create_export_rgw(self):
+ ganesha.RgwClient = MagicMock()
+ admin_inst_mock = MagicMock()
+ admin_inst_mock.get_user_keys.return_value = {
+ 'access_key': 'access_key2',
+ 'secret_key': 'secret_key2'
+ }
+ ganesha.RgwClient.admin_instance.return_value = admin_inst_mock
+
+ conf = GaneshaConf.instance('_default_')
+ ex_id = conf.create_export({
+ 'daemons': ["nodeb"],
+ 'path': 'bucket',
+ 'pseudo': '/rgw/bucket',
+ 'tag': 'bucket_tag',
+ 'cluster_id': '_default_',
+ 'access_type': 'RW',
+ 'squash': 'all_squash',
+ 'security_label': False,
+ 'protocols': [4, 3],
+ 'transports': ['TCP', 'UDP'],
+ 'clients': [{
+ 'addresses': ["192.168.0.0/16"],
+ 'access_type': None,
+ 'squash': None
+ }],
+ 'fsal': {
+ 'name': 'RGW',
+ 'rgw_user_id': 'testuser'
+ }
+ })
+
+ conf = GaneshaConf.instance('_default_')
+ exports = conf.list_exports()
+ self.assertEqual(len(exports), 3)
+ export = conf.get_export(ex_id)
+ self.assertEqual(export.export_id, ex_id)
+ self.assertEqual(export.path, "bucket")
+ self.assertEqual(export.pseudo, "/rgw/bucket")
+ self.assertEqual(export.tag, "bucket_tag")
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4, 3})
+ self.assertEqual(export.transports, {"TCP", "UDP"})
+ self.assertEqual(export.fsal.name, "RGW")
+ self.assertEqual(export.fsal.rgw_user_id, "testuser")
+ self.assertEqual(export.fsal.access_key, "access_key2")
+ self.assertEqual(export.fsal.secret_key, "secret_key2")
+ self.assertEqual(len(export.clients), 1)
+ self.assertEqual(export.clients[0].addresses, ["192.168.0.0/16"])
+ self.assertIsNone(export.clients[0].squash)
+ self.assertIsNone(export.clients[0].access_type)
+ self.assertEqual(export.daemons, {"nodeb"})
+ self.assertEqual(export.cluster_id, '_default_')
+
+ def test_create_export_cephfs(self):
+ ganesha.CephX = MagicMock()
+ ganesha.CephX.list_clients.return_value = ["fs"]
+ ganesha.CephX.get_client_key.return_value = "fs_key"
+
+ ganesha.CephFS = MagicMock()
+ ganesha.CephFS.dir_exists.return_value = True
+
+ conf = GaneshaConf.instance('_default_')
+ ex_id = conf.create_export({
+ 'daemons': ['nodea', 'nodeb'],
+ 'path': '/',
+ 'pseudo': '/cephfs2',
+ 'cluster_id': '_default_',
+ 'tag': None,
+ 'access_type': 'RW',
+ 'squash': 'all_squash',
+ 'security_label': True,
+ 'protocols': [4],
+ 'transports': ['TCP'],
+ 'clients': [],
+ 'fsal': {
+ 'name': 'CEPH',
+ 'user_id': 'fs',
+ 'fs_name': None,
+ 'sec_label_xattr': 'security.selinux'
+ }
+ })
+
+ conf = GaneshaConf.instance('_default_')
+ exports = conf.list_exports()
+ self.assertEqual(len(exports), 3)
+ export = conf.get_export(ex_id)
+ self.assertEqual(export.export_id, ex_id)
+ self.assertEqual(export.path, "/")
+ self.assertEqual(export.pseudo, "/cephfs2")
+ self.assertIsNone(export.tag)
+ self.assertEqual(export.access_type, "RW")
+ self.assertEqual(export.squash, "all_squash")
+ self.assertEqual(export.protocols, {4})
+ self.assertEqual(export.transports, {"TCP"})
+ self.assertEqual(export.fsal.name, "CEPH")
+ self.assertEqual(export.fsal.user_id, "fs")
+ self.assertEqual(export.fsal.cephx_key, "fs_key")
+ self.assertEqual(export.fsal.sec_label_xattr, "security.selinux")
+ self.assertIsNone(export.fsal.fs_name)
+ self.assertEqual(len(export.clients), 0)
+ self.assertEqual(export.daemons, {"nodeb", "nodea"})
+ self.assertEqual(export.cluster_id, '_default_')
+ self.assertEqual(export.attr_expiration_time, 0)
+ self.assertEqual(export.security_label, True)
diff --git a/src/pybind/mgr/dashboard/tests/test_grafana.py b/src/pybind/mgr/dashboard/tests/test_grafana.py
new file mode 100644
index 00000000..02597dfe
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_grafana.py
@@ -0,0 +1,116 @@
+import json
+import unittest
+
+try:
+ from mock import patch
+except ImportError:
+ from unittest.mock import patch
+
+from . import ControllerTestCase, KVStoreMockMixin
+from ..controllers.grafana import Grafana
+from ..grafana import GrafanaRestClient
+from ..settings import Settings
+
+
+class GrafanaTest(ControllerTestCase, KVStoreMockMixin):
+ @classmethod
+ def setup_server(cls):
+ # pylint: disable=protected-access
+ Grafana._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([Grafana])
+
+ def setUp(self):
+ self.mock_kv_store()
+
+ @staticmethod
+ def server_settings(
+ url='http://localhost:3000',
+ user='admin',
+ password='admin',
+ ):
+ if url is not None:
+ Settings.GRAFANA_API_URL = url
+ if user is not None:
+ Settings.GRAFANA_API_USERNAME = user
+ if password is not None:
+ Settings.GRAFANA_API_PASSWORD = password
+
+ def test_url(self):
+ self.server_settings()
+ self._get('/api/grafana/url')
+ self.assertStatus(200)
+ self.assertJsonBody({'instance': 'http://localhost:3000'})
+
+ def test_validation(self):
+ self.server_settings()
+ self._get('/api/grafana/validation/foo')
+ self.assertStatus(500)
+
+ def test_dashboards_unavailable_no_url(self):
+ self.server_settings(url=None)
+ self._post('/api/grafana/dashboards')
+ self.assertStatus(500)
+
+ def test_dashboards_unavailable_no_user(self):
+ self.server_settings(user=None)
+ self._post('/api/grafana/dashboards')
+ self.assertStatus(500)
+
+ def test_dashboards_unavailable_no_password(self):
+ self.server_settings(password=None)
+ self._post('/api/grafana/dashboards')
+ self.assertStatus(500)
+
+
+class GrafanaRestClientTest(unittest.TestCase, KVStoreMockMixin):
+ headers = {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ }
+ payload = json.dumps({
+ 'dashboard': 'foo',
+ 'overwrite': True
+ })
+
+ def setUp(self):
+ self.mock_kv_store()
+ Settings.GRAFANA_API_URL = 'https://foo/bar'
+ Settings.GRAFANA_API_USERNAME = 'xyz'
+ Settings.GRAFANA_API_PASSWORD = 'abc'
+ Settings.GRAFANA_API_SSL_VERIFY = True
+
+ def test_ssl_verify_url_validation(self):
+ with patch('requests.request') as mock_request:
+ rest_client = GrafanaRestClient()
+ rest_client.url_validation('FOO', Settings.GRAFANA_API_URL)
+ mock_request.assert_called_with('FOO', Settings.GRAFANA_API_URL,
+ verify=True)
+
+ def test_no_ssl_verify_url_validation(self):
+ Settings.GRAFANA_API_SSL_VERIFY = False
+ with patch('requests.request') as mock_request:
+ rest_client = GrafanaRestClient()
+ rest_client.url_validation('BAR', Settings.GRAFANA_API_URL)
+ mock_request.assert_called_with('BAR', Settings.GRAFANA_API_URL,
+ verify=False)
+
+ def test_ssl_verify_push_dashboard(self):
+ with patch('requests.post') as mock_request:
+ rest_client = GrafanaRestClient()
+ rest_client.push_dashboard('foo')
+ mock_request.assert_called_with(
+ Settings.GRAFANA_API_URL + '/api/dashboards/db',
+ auth=(Settings.GRAFANA_API_USERNAME,
+ Settings.GRAFANA_API_PASSWORD),
+ data=self.payload, headers=self.headers, verify=True)
+
+ def test_no_ssl_verify_push_dashboard(self):
+ Settings.GRAFANA_API_SSL_VERIFY = False
+ with patch('requests.post') as mock_request:
+ rest_client = GrafanaRestClient()
+ rest_client.push_dashboard('foo')
+ mock_request.assert_called_with(
+ Settings.GRAFANA_API_URL + '/api/dashboards/db',
+ auth=(Settings.GRAFANA_API_USERNAME,
+ Settings.GRAFANA_API_PASSWORD),
+ data=self.payload, headers=self.headers, verify=False)
diff --git a/src/pybind/mgr/dashboard/tests/test_home.py b/src/pybind/mgr/dashboard/tests/test_home.py
new file mode 100644
index 00000000..c3088b7a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_home.py
@@ -0,0 +1,68 @@
+from __future__ import absolute_import
+
+import logging
+import os
+
+try:
+ import mock
+except ImportError:
+ import unittest.mock as mock
+
+from . import ControllerTestCase, FakeFsMixin
+from .. import mgr
+
+from ..controllers.home import HomeController, LanguageMixin
+
+logger = logging.getLogger()
+
+
+class HomeTest(ControllerTestCase, FakeFsMixin):
+ @classmethod
+ def setup_server(cls):
+ frontend_path = mgr.get_frontend_path()
+ cls.fs.reset()
+ cls.fs.create_dir(frontend_path)
+ cls.fs.create_file(
+ os.path.join(frontend_path, '..', 'package.json'),
+ contents='{"config":{"locale": "en-US"}}')
+ with mock.patch(cls.builtins_open, new=cls.f_open),\
+ mock.patch('os.listdir', new=cls.f_os.listdir):
+ lang = LanguageMixin()
+ cls.fs.create_file(
+ os.path.join(lang.DEFAULT_LANGUAGE_PATH, 'index.html'),
+ contents='<!doctype html><html lang="en"><body></body></html>')
+ cls.setup_controllers([HomeController])
+
+ @mock.patch(FakeFsMixin.builtins_open, new=FakeFsMixin.f_open)
+ @mock.patch('os.stat', new=FakeFsMixin.f_os.stat)
+ @mock.patch('os.listdir', new=FakeFsMixin.f_os.listdir)
+ def test_home_default_lang(self):
+ self._get('/')
+ self.assertStatus(200)
+ logger.info(self.body)
+ self.assertIn('<html lang="en">', self.body.decode('utf-8'))
+
+ @mock.patch(FakeFsMixin.builtins_open, new=FakeFsMixin.f_open)
+ @mock.patch('os.stat', new=FakeFsMixin.f_os.stat)
+ @mock.patch('os.listdir', new=FakeFsMixin.f_os.listdir)
+ def test_home_uplevel_check(self):
+ self._get('/../../../../../../etc/shadow')
+ self.assertStatus(403)
+
+ @mock.patch(FakeFsMixin.builtins_open, new=FakeFsMixin.f_open)
+ @mock.patch('os.stat', new=FakeFsMixin.f_os.stat)
+ @mock.patch('os.listdir', new=FakeFsMixin.f_os.listdir)
+ def test_home_en_us(self):
+ self._get('/', headers=[('Accept-Language', 'en-US')])
+ self.assertStatus(200)
+ logger.info(self.body)
+ self.assertIn('<html lang="en">', self.body.decode('utf-8'))
+
+ @mock.patch(FakeFsMixin.builtins_open, new=FakeFsMixin.f_open)
+ @mock.patch('os.stat', new=FakeFsMixin.f_os.stat)
+ @mock.patch('os.listdir', new=FakeFsMixin.f_os.listdir)
+ def test_home_non_supported_lang(self):
+ self._get('/', headers=[('Accept-Language', 'NO-NO')])
+ self.assertStatus(200)
+ logger.info(self.body)
+ self.assertIn('<html lang="en">', self.body.decode('utf-8'))
diff --git a/src/pybind/mgr/dashboard/tests/test_iscsi.py b/src/pybind/mgr/dashboard/tests/test_iscsi.py
new file mode 100644
index 00000000..34d2f014
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_iscsi.py
@@ -0,0 +1,998 @@
+# pylint: disable=too-many-public-methods, too-many-lines
+
+import copy
+import errno
+import json
+import unittest
+
+try:
+ import mock
+except ImportError:
+ import unittest.mock as mock
+
+from mgr_module import ERROR_MSG_NO_INPUT_FILE
+
+from . import CmdException, ControllerTestCase, CLICommandTestMixin, KVStoreMockMixin
+from .. import mgr
+from ..controllers.iscsi import Iscsi, IscsiTarget
+from ..services.iscsi_client import IscsiClient
+from ..services.orchestrator import OrchClient
+from ..rest_client import RequestException
+
+
+class IscsiTestCli(unittest.TestCase, CLICommandTestMixin):
+
+ def setUp(self):
+ self.mock_kv_store()
+ # pylint: disable=protected-access
+ IscsiClientMock._instance = IscsiClientMock()
+ IscsiClient.instance = IscsiClientMock.instance
+
+ def test_cli_add_gateway_invalid_url(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('iscsi-gateway-add', inbuf='http:/hello.com')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+ self.assertEqual(str(ctx.exception),
+ "Invalid service URL 'http:/hello.com'. Valid format: "
+ "'<scheme>://<username>:<password>@<host>[:port]'.")
+
+ def test_cli_add_gateway_empty_url(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('iscsi-gateway-add', inbuf='')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
+ self.assertEqual(str(ctx.exception), ERROR_MSG_NO_INPUT_FILE)
+
+ def test_cli_add_gateway(self):
+ self.exec_cmd('iscsi-gateway-add', inbuf='https://admin:admin@10.17.5.1:5001')
+ self.exec_cmd('iscsi-gateway-add', inbuf='https://admin:admin@10.17.5.2:5001')
+ iscsi_config = json.loads(self.get_key("_iscsi_config"))
+ self.assertEqual(iscsi_config['gateways'], {
+ 'node1': {
+ 'service_url': 'https://admin:admin@10.17.5.1:5001'
+ },
+ 'node2': {
+ 'service_url': 'https://admin:admin@10.17.5.2:5001'
+ }
+ })
+
+ def test_cli_remove_gateway(self):
+ self.test_cli_add_gateway()
+ self.exec_cmd('iscsi-gateway-rm', name='node1')
+ iscsi_config = json.loads(self.get_key("_iscsi_config"))
+ self.assertEqual(iscsi_config['gateways'], {
+ 'node2': {
+ 'service_url': 'https://admin:admin@10.17.5.2:5001'
+ }
+ })
+
+
+class IscsiTestController(ControllerTestCase, KVStoreMockMixin):
+
+ @classmethod
+ def setup_server(cls):
+ OrchClient().available = lambda: False
+ mgr.rados.side_effect = None
+ # pylint: disable=protected-access
+ Iscsi._cp_config['tools.authenticate.on'] = False
+ IscsiTarget._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([Iscsi, IscsiTarget])
+
+ def setUp(self):
+ self.mock_kv_store()
+ self.CONFIG_KEY_DICT['_iscsi_config'] = '''
+ {
+ "gateways": {
+ "node1": {
+ "service_url": "https://admin:admin@10.17.5.1:5001"
+ },
+ "node2": {
+ "service_url": "https://admin:admin@10.17.5.2:5001"
+ }
+ }
+ }
+ '''
+ # pylint: disable=protected-access
+ IscsiClientMock._instance = IscsiClientMock()
+ IscsiClient.instance = IscsiClientMock.instance
+
+ def test_enable_discoveryauth(self):
+ discoveryauth = {
+ 'user': 'myiscsiusername',
+ 'password': 'myiscsipassword',
+ 'mutual_user': 'myiscsiusername2',
+ 'mutual_password': 'myiscsipassword2'
+ }
+ self._put('/api/iscsi/discoveryauth', discoveryauth)
+ self.assertStatus(200)
+ self.assertJsonBody(discoveryauth)
+ self._get('/api/iscsi/discoveryauth')
+ self.assertStatus(200)
+ self.assertJsonBody(discoveryauth)
+
+ def test_bad_discoveryauth(self):
+ discoveryauth = {
+ 'user': 'myiscsiusername',
+ 'password': 'myiscsipasswordmyiscsipasswordmyiscsipassword',
+ 'mutual_user': '',
+ 'mutual_password': ''
+ }
+ put_response = {
+ 'detail': 'Bad authentication',
+ 'code': 'target_bad_auth',
+ 'component': 'iscsi'
+ }
+ get_response = {
+ 'user': '',
+ 'password': '',
+ 'mutual_user': '',
+ 'mutual_password': ''
+ }
+ self._put('/api/iscsi/discoveryauth', discoveryauth)
+ self.assertStatus(400)
+ self.assertJsonBody(put_response)
+ self._get('/api/iscsi/discoveryauth')
+ self.assertStatus(200)
+ self.assertJsonBody(get_response)
+
+ def test_disable_discoveryauth(self):
+ discoveryauth = {
+ 'user': '',
+ 'password': '',
+ 'mutual_user': '',
+ 'mutual_password': ''
+ }
+ self._put('/api/iscsi/discoveryauth', discoveryauth)
+ self.assertStatus(200)
+ self.assertJsonBody(discoveryauth)
+ self._get('/api/iscsi/discoveryauth')
+ self.assertStatus(200)
+ self.assertJsonBody(discoveryauth)
+
+ def test_list_empty(self):
+ self._get('/api/iscsi/target')
+ self.assertStatus(200)
+ self.assertJsonBody([])
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_list(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw1"
+ request = copy.deepcopy(iscsi_target_request)
+ request['target_iqn'] = target_iqn
+ self._task_post('/api/iscsi/target', request)
+ self.assertStatus(201)
+ self._get('/api/iscsi/target')
+ self.assertStatus(200)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ self.assertJsonBody([response])
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_create(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw2"
+ request = copy.deepcopy(iscsi_target_request)
+ request['target_iqn'] = target_iqn
+ self._task_post('/api/iscsi/target', request)
+ self.assertStatus(201)
+ self._get('/api/iscsi/target/{}'.format(request['target_iqn']))
+ self.assertStatus(200)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ self.assertJsonBody(response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_delete(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw3"
+ request = copy.deepcopy(iscsi_target_request)
+ request['target_iqn'] = target_iqn
+ self._task_post('/api/iscsi/target', request)
+ self.assertStatus(201)
+ self._task_delete('/api/iscsi/target/{}'.format(request['target_iqn']))
+ self.assertStatus(204)
+ self._get('/api/iscsi/target')
+ self.assertStatus(200)
+ self.assertJsonBody([])
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_client(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw4"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'].append(
+ {
+ "luns": [{"image": "lun1", "pool": "rbd"}],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
+ "auth": {
+ "password": "myiscsipassword5",
+ "user": "myiscsiusername5",
+ "mutual_password": "myiscsipassword6",
+ "mutual_user": "myiscsiusername6"}
+ })
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'].append(
+ {
+ "luns": [{"image": "lun1", "pool": "rbd"}],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
+ "auth": {
+ "password": "myiscsipassword5",
+ "user": "myiscsiusername5",
+ "mutual_password": "myiscsipassword6",
+ "mutual_user": "myiscsiusername6"},
+ "info": {
+ "alias": "",
+ "ip_address": [],
+ "state": {}
+ }
+ })
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_bad_client(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw4"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'].append(
+ {
+ "luns": [{"image": "lun1", "pool": "rbd"}],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client4",
+ "auth": {
+ "password": "myiscsipassword7myiscsipassword7myiscsipasswo",
+ "user": "myiscsiusername7",
+ "mutual_password": "myiscsipassword8",
+ "mutual_user": "myiscsiusername8"}
+ })
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+
+ self._task_post('/api/iscsi/target', create_request)
+ self.assertStatus(201)
+ self._task_put('/api/iscsi/target/{}'.format(create_request['target_iqn']), update_request)
+ self.assertStatus(400)
+ self._get('/api/iscsi/target/{}'.format(update_request['new_target_iqn']))
+ self.assertStatus(200)
+ self.assertJsonBody(response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_change_client_password(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw5"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'][0]['auth']['password'] = 'MyNewPassword'
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'][0]['auth']['password'] = 'MyNewPassword'
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_rename_client(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw6"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'][0]['client_iqn'] = 'iqn.1994-05.com.redhat:rh7-client0'
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'][0]['client_iqn'] = 'iqn.1994-05.com.redhat:rh7-client0'
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_disk(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw7"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['disks'].append(
+ {
+ "image": "lun3",
+ "pool": "rbd",
+ "controls": {},
+ "backstore": "user:rbd"
+ })
+ update_request['clients'][0]['luns'].append({"image": "lun3", "pool": "rbd"})
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['disks'].append(
+ {
+ "image": "lun3",
+ "pool": "rbd",
+ "controls": {},
+ "backstore": "user:rbd",
+ "wwn": "64af6678-9694-4367-bacc-f8eb0baa2",
+ "lun": 2
+
+ })
+ response['clients'][0]['luns'].append({"image": "lun3", "pool": "rbd"})
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_change_disk_image(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw8"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['disks'][0]['image'] = 'lun0'
+ update_request['clients'][0]['luns'][0]['image'] = 'lun0'
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['disks'][0]['image'] = 'lun0'
+ response['clients'][0]['luns'][0]['image'] = 'lun0'
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_change_disk_controls(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw9"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['disks'][0]['controls'] = {"qfull_timeout": 15}
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['disks'][0]['controls'] = {"qfull_timeout": 15}
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_rename_target(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw10"
+ new_target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw11"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = new_target_iqn
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = new_target_iqn
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_rename_group(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw12"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['groups'][0]['group_id'] = 'mygroup0'
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['groups'][0]['group_id'] = 'mygroup0'
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_client_to_group(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw13"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'].append(
+ {
+ "luns": [],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
+ "auth": {
+ "password": None,
+ "user": None,
+ "mutual_password": None,
+ "mutual_user": None}
+ })
+ update_request['groups'][0]['members'].append('iqn.1994-05.com.redhat:rh7-client3')
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'].append(
+ {
+ "luns": [],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
+ "auth": {
+ "password": None,
+ "user": None,
+ "mutual_password": None,
+ "mutual_user": None},
+ "info": {
+ "alias": "",
+ "ip_address": [],
+ "state": {}
+ }
+ })
+ response['groups'][0]['members'].append('iqn.1994-05.com.redhat:rh7-client3')
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_client_from_group(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw14"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['groups'][0]['members'].remove('iqn.1994-05.com.redhat:rh7-client2')
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['groups'][0]['members'].remove('iqn.1994-05.com.redhat:rh7-client2')
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_groups(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw15"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['groups'] = []
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['groups'] = []
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_client_to_multiple_groups(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw16"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ create_request['groups'].append(copy.deepcopy(create_request['groups'][0]))
+ create_request['groups'][1]['group_id'] = 'mygroup2'
+ self._task_post('/api/iscsi/target', create_request)
+ self.assertStatus(400)
+ self.assertJsonBody({
+ 'detail': 'Each initiator can only be part of 1 group at a time',
+ 'code': 'initiator_in_multiple_groups',
+ 'component': 'iscsi'
+ })
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_client_lun(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw17"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ create_request['clients'][0]['luns'] = [
+ {"image": "lun1", "pool": "rbd"},
+ {"image": "lun2", "pool": "rbd"},
+ {"image": "lun3", "pool": "rbd"}
+ ]
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'][0]['luns'] = [
+ {"image": "lun1", "pool": "rbd"},
+ {"image": "lun3", "pool": "rbd"}
+ ]
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'][0]['luns'] = [
+ {"image": "lun1", "pool": "rbd"},
+ {"image": "lun3", "pool": "rbd"}
+ ]
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_change_client_auth(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw18"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'][0]['auth']['password'] = 'myiscsipasswordX'
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'][0]['auth']['password'] = 'myiscsipasswordX'
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_client_logged_in(self, _validate_image_mock):
+ client_info = {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {'LOGGED_IN': ['node1']}
+ }
+ # pylint: disable=protected-access
+ IscsiClientMock._instance.clientinfo = client_info
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw19"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'].pop(0)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ for client in response['clients']:
+ client['info'] = client_info
+ update_response = {
+ 'detail': "Client 'iqn.1994-05.com.redhat:rh7-client' cannot be deleted until it's "
+ "logged out",
+ 'code': 'client_logged_in',
+ 'component': 'iscsi'
+ }
+ self._update_iscsi_target(create_request, update_request, 400, update_response, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_client(self, _validate_image_mock):
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw20"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'].pop(0)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'].pop(0)
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_image_to_group_with_client_logged_in(self, _validate_image_mock):
+ client_info = {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {'LOGGED_IN': ['node1']}
+ }
+ new_disk = {"pool": "rbd", "image": "lun1"}
+ # pylint: disable=protected-access
+ IscsiClientMock._instance.clientinfo = client_info
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw21"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['groups'][0]['disks'].append(new_disk)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['groups'][0]['disks'].insert(0, new_disk)
+ for client in response['clients']:
+ client['info'] = client_info
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_add_image_to_initiator_with_client_logged_in(self, _validate_image_mock):
+ client_info = {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {'LOGGED_IN': ['node1']}
+ }
+ new_disk = {"pool": "rbd", "image": "lun2"}
+ # pylint: disable=protected-access
+ IscsiClientMock._instance.clientinfo = client_info
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw22"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['clients'][0]['luns'].append(new_disk)
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['clients'][0]['luns'].append(new_disk)
+ for client in response['clients']:
+ client['info'] = client_info
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
+ def test_remove_image_from_group_with_client_logged_in(self, _validate_image_mock):
+ client_info = {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {'LOGGED_IN': ['node1']}
+ }
+ # pylint: disable=protected-access
+ IscsiClientMock._instance.clientinfo = client_info
+ target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw23"
+ create_request = copy.deepcopy(iscsi_target_request)
+ create_request['target_iqn'] = target_iqn
+ update_request = copy.deepcopy(create_request)
+ update_request['new_target_iqn'] = target_iqn
+ update_request['groups'][0]['disks'] = []
+ response = copy.deepcopy(iscsi_target_response)
+ response['target_iqn'] = target_iqn
+ response['groups'][0]['disks'] = []
+ for client in response['clients']:
+ client['info'] = client_info
+ self._update_iscsi_target(create_request, update_request, 200, None, response)
+
+ def _update_iscsi_target(self, create_request, update_request, update_response_code,
+ update_response, response):
+ self._task_post('/api/iscsi/target', create_request)
+ self.assertStatus(201)
+ self._task_put('/api/iscsi/target/{}'.format(create_request['target_iqn']), update_request)
+ self.assertStatus(update_response_code)
+ self.assertJsonBody(update_response)
+ self._get('/api/iscsi/target/{}'.format(update_request['new_target_iqn']))
+ self.assertStatus(200)
+ self.assertJsonBody(response)
+
+
+iscsi_target_request = {
+ "target_iqn": "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw",
+ "portals": [
+ {"ip": "192.168.100.202", "host": "node2"},
+ {"ip": "10.0.2.15", "host": "node2"},
+ {"ip": "192.168.100.203", "host": "node3"}
+ ],
+ "disks": [
+ {"image": "lun1", "pool": "rbd", "backstore": "user:rbd",
+ "controls": {"max_data_area_mb": 128}},
+ {"image": "lun2", "pool": "rbd", "backstore": "user:rbd",
+ "controls": {"max_data_area_mb": 128}}
+ ],
+ "clients": [
+ {
+ "luns": [{"image": "lun1", "pool": "rbd"}],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client",
+ "auth": {
+ "password": "myiscsipassword1",
+ "user": "myiscsiusername1",
+ "mutual_password": "myiscsipassword2",
+ "mutual_user": "myiscsiusername2"}
+ },
+ {
+ "luns": [],
+ "client_iqn": "iqn.1994-05.com.redhat:rh7-client2",
+ "auth": {
+ "password": "myiscsipassword3",
+ "user": "myiscsiusername3",
+ "mutual_password": "myiscsipassword4",
+ "mutual_user": "myiscsiusername4"
+ }
+ }
+ ],
+ "acl_enabled": True,
+ "auth": {
+ "password": "",
+ "user": "",
+ "mutual_password": "",
+ "mutual_user": ""},
+ "target_controls": {},
+ "groups": [
+ {
+ "group_id": "mygroup",
+ "disks": [{"pool": "rbd", "image": "lun2"}],
+ "members": ["iqn.1994-05.com.redhat:rh7-client2"]
+ }
+ ]
+}
+
+iscsi_target_response = {
+ 'target_iqn': 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
+ 'portals': [
+ {'host': 'node2', 'ip': '10.0.2.15'},
+ {'host': 'node2', 'ip': '192.168.100.202'},
+ {'host': 'node3', 'ip': '192.168.100.203'}
+ ],
+ 'disks': [
+ {'pool': 'rbd', 'image': 'lun1', 'backstore': 'user:rbd',
+ 'wwn': '64af6678-9694-4367-bacc-f8eb0baa0', 'lun': 0,
+ 'controls': {'max_data_area_mb': 128}},
+ {'pool': 'rbd', 'image': 'lun2', 'backstore': 'user:rbd',
+ 'wwn': '64af6678-9694-4367-bacc-f8eb0baa1', 'lun': 1,
+ 'controls': {'max_data_area_mb': 128}}
+ ],
+ 'clients': [
+ {
+ 'client_iqn': 'iqn.1994-05.com.redhat:rh7-client',
+ 'luns': [{'pool': 'rbd', 'image': 'lun1'}],
+ 'auth': {
+ 'user': 'myiscsiusername1',
+ 'password': 'myiscsipassword1',
+ 'mutual_password': 'myiscsipassword2',
+ 'mutual_user': 'myiscsiusername2'
+ },
+ 'info': {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {}
+ }
+ },
+ {
+ 'client_iqn': 'iqn.1994-05.com.redhat:rh7-client2',
+ 'luns': [],
+ 'auth': {
+ 'user': 'myiscsiusername3',
+ 'password': 'myiscsipassword3',
+ 'mutual_password': 'myiscsipassword4',
+ 'mutual_user': 'myiscsiusername4'
+ },
+ 'info': {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {}
+ }
+ }
+ ],
+ "acl_enabled": True,
+ "auth": {
+ "password": "",
+ "user": "",
+ "mutual_password": "",
+ "mutual_user": ""},
+ 'groups': [
+ {
+ 'group_id': 'mygroup',
+ 'disks': [{'pool': 'rbd', 'image': 'lun2'}],
+ 'members': ['iqn.1994-05.com.redhat:rh7-client2']
+ }
+ ],
+ 'target_controls': {},
+ 'info': {
+ 'num_sessions': 0
+ }
+}
+
+
+class IscsiClientMock(object):
+
+ _instance = None
+
+ def __init__(self):
+ self.gateway_name = None
+ self.service_url = None
+ self.config = {
+ "created": "2019/01/17 08:57:16",
+ "discovery_auth": {
+ "username": "",
+ "password": "",
+ "password_encryption_enabled": False,
+ "mutual_username": "",
+ "mutual_password": "",
+ "mutual_password_encryption_enabled": False
+ },
+ "disks": {},
+ "epoch": 0,
+ "gateways": {},
+ "targets": {},
+ "updated": "",
+ "version": 11
+ }
+ self.clientinfo = {
+ 'alias': '',
+ 'ip_address': [],
+ 'state': {}
+ }
+
+ @classmethod
+ def instance(cls, gateway_name=None, service_url=None):
+ cls._instance.gateway_name = gateway_name
+ cls._instance.service_url = service_url
+ # pylint: disable=unused-argument
+ return cls._instance
+
+ def ping(self):
+ return {
+ "message": "pong"
+ }
+
+ def get_settings(self):
+ return {
+ "api_version": 2,
+ "backstores": [
+ "user:rbd"
+ ],
+ "config": {
+ "minimum_gateways": 2
+ },
+ "default_backstore": "user:rbd",
+ "required_rbd_features": {
+ "rbd": 0,
+ "user:rbd": 4,
+ },
+ "unsupported_rbd_features": {
+ "rbd": 88,
+ "user:rbd": 0,
+ },
+ "disk_default_controls": {
+ "user:rbd": {
+ "hw_max_sectors": 1024,
+ "max_data_area_mb": 8,
+ "osd_op_timeout": 30,
+ "qfull_timeout": 5
+ }
+ },
+ "target_default_controls": {
+ "cmdsn_depth": 128,
+ "dataout_timeout": 20,
+ "first_burst_length": 262144,
+ "immediate_data": "Yes",
+ "initial_r2t": "Yes",
+ "max_burst_length": 524288,
+ "max_outstanding_r2t": 1,
+ "max_recv_data_segment_length": 262144,
+ "max_xmit_data_segment_length": 262144,
+ "nopin_response_timeout": 5,
+ "nopin_timeout": 5
+ }
+ }
+
+ def get_config(self):
+ return copy.deepcopy(self.config)
+
+ def create_target(self, target_iqn, target_controls):
+ self.config['targets'][target_iqn] = {
+ "clients": {},
+ "acl_enabled": True,
+ "auth": {
+ "username": "",
+ "password": "",
+ "password_encryption_enabled": False,
+ "mutual_username": "",
+ "mutual_password": "",
+ "mutual_password_encryption_enabled": False
+ },
+ "controls": target_controls,
+ "created": "2019/01/17 09:22:34",
+ "disks": {},
+ "groups": {},
+ "portals": {}
+ }
+
+ def create_gateway(self, target_iqn, gateway_name, ip_addresses):
+ target_config = self.config['targets'][target_iqn]
+ if 'ip_list' not in target_config:
+ target_config['ip_list'] = []
+ target_config['ip_list'] += ip_addresses
+ target_config['portals'][gateway_name] = {
+ "portal_ip_addresses": ip_addresses
+ }
+
+ def delete_gateway(self, target_iqn, gateway_name):
+ target_config = self.config['targets'][target_iqn]
+ portal_config = target_config['portals'][gateway_name]
+ for ip in portal_config['portal_ip_addresses']:
+ target_config['ip_list'].remove(ip)
+ target_config['portals'].pop(gateway_name)
+
+ def create_disk(self, pool, image, backstore, wwn):
+ if wwn is None:
+ wwn = '64af6678-9694-4367-bacc-f8eb0baa' + str(len(self.config['disks']))
+ image_id = '{}/{}'.format(pool, image)
+ self.config['disks'][image_id] = {
+ "pool": pool,
+ "image": image,
+ "backstore": backstore,
+ "controls": {},
+ "wwn": wwn
+ }
+
+ def create_target_lun(self, target_iqn, image_id, lun):
+ target_config = self.config['targets'][target_iqn]
+ if lun is None:
+ lun = len(target_config['disks'])
+ target_config['disks'][image_id] = {
+ "lun_id": lun
+ }
+ self.config['disks'][image_id]['owner'] = list(target_config['portals'].keys())[0]
+
+ def reconfigure_disk(self, pool, image, controls):
+ image_id = '{}/{}'.format(pool, image)
+ settings = self.get_settings()
+ backstore = self.config['disks'][image_id]['backstore']
+ disk_default_controls = settings['disk_default_controls'][backstore]
+ new_controls = {}
+ for control_k, control_v in controls.items():
+ if control_v != disk_default_controls[control_k]:
+ new_controls[control_k] = control_v
+ self.config['disks'][image_id]['controls'] = new_controls
+
+ def create_client(self, target_iqn, client_iqn):
+ target_config = self.config['targets'][target_iqn]
+ target_config['clients'][client_iqn] = {
+ "auth": {
+ "username": "",
+ "password": "",
+ "password_encryption_enabled": False,
+ "mutual_username": "",
+ "mutual_password": "",
+ "mutual_password_encryption_enabled": False
+ },
+ "group_name": "",
+ "luns": {}
+ }
+
+ def create_client_lun(self, target_iqn, client_iqn, image_id):
+ target_config = self.config['targets'][target_iqn]
+ target_config['clients'][client_iqn]['luns'][image_id] = {}
+
+ def delete_client_lun(self, target_iqn, client_iqn, image_id):
+ target_config = self.config['targets'][target_iqn]
+ del target_config['clients'][client_iqn]['luns'][image_id]
+
+ def create_client_auth(self, target_iqn, client_iqn, user, password, m_user, m_password):
+ target_config = self.config['targets'][target_iqn]
+ target_config['clients'][client_iqn]['auth']['username'] = user
+ target_config['clients'][client_iqn]['auth']['password'] = password
+ target_config['clients'][client_iqn]['auth']['mutual_username'] = m_user
+ target_config['clients'][client_iqn]['auth']['mutual_password'] = m_password
+
+ def create_group(self, target_iqn, group_name, members, image_ids):
+ target_config = self.config['targets'][target_iqn]
+ target_config['groups'][group_name] = {
+ "disks": {},
+ "members": []
+ }
+ for image_id in image_ids:
+ target_config['groups'][group_name]['disks'][image_id] = {}
+ target_config['groups'][group_name]['members'] = members
+
+ def update_group(self, target_iqn, group_name, members, image_ids):
+ target_config = self.config['targets'][target_iqn]
+ group = target_config['groups'][group_name]
+ old_members = group['members']
+ disks = group['disks']
+ target_config['groups'][group_name] = {
+ "disks": {},
+ "members": []
+ }
+
+ for image_id in disks.keys():
+ if image_id not in image_ids:
+ target_config['groups'][group_name]['disks'][image_id] = {}
+
+ new_members = []
+ for member_iqn in old_members:
+ if member_iqn not in members:
+ new_members.append(member_iqn)
+ target_config['groups'][group_name]['members'] = new_members
+
+ def delete_group(self, target_iqn, group_name):
+ target_config = self.config['targets'][target_iqn]
+ del target_config['groups'][group_name]
+
+ def delete_client(self, target_iqn, client_iqn):
+ target_config = self.config['targets'][target_iqn]
+ del target_config['clients'][client_iqn]
+
+ def delete_target_lun(self, target_iqn, image_id):
+ target_config = self.config['targets'][target_iqn]
+ target_config['disks'].pop(image_id)
+ del self.config['disks'][image_id]['owner']
+
+ def delete_disk(self, pool, image):
+ image_id = '{}/{}'.format(pool, image)
+ del self.config['disks'][image_id]
+
+ def delete_target(self, target_iqn):
+ del self.config['targets'][target_iqn]
+
+ def get_ip_addresses(self):
+ ips = {
+ 'node1': ['192.168.100.201'],
+ 'node2': ['192.168.100.202', '10.0.2.15'],
+ 'node3': ['192.168.100.203']
+ }
+ return {'data': ips[self.gateway_name]}
+
+ def get_hostname(self):
+ hostnames = {
+ 'https://admin:admin@10.17.5.1:5001': 'node1',
+ 'https://admin:admin@10.17.5.2:5001': 'node2',
+ 'https://admin:admin@10.17.5.3:5001': 'node3'
+ }
+ if self.service_url not in hostnames:
+ raise RequestException('No route to host')
+ return {'data': hostnames[self.service_url]}
+
+ def update_discoveryauth(self, user, password, mutual_user, mutual_password):
+ self.config['discovery_auth']['username'] = user
+ self.config['discovery_auth']['password'] = password
+ self.config['discovery_auth']['mutual_username'] = mutual_user
+ self.config['discovery_auth']['mutual_password'] = mutual_password
+
+ def update_targetacl(self, target_iqn, action):
+ self.config['targets'][target_iqn]['acl_enabled'] = (action == 'enable_acl')
+
+ def update_targetauth(self, target_iqn, user, password, mutual_user, mutual_password):
+ target_config = self.config['targets'][target_iqn]
+ target_config['auth']['username'] = user
+ target_config['auth']['password'] = password
+ target_config['auth']['mutual_username'] = mutual_user
+ target_config['auth']['mutual_password'] = mutual_password
+
+ def get_targetinfo(self, target_iqn):
+ # pylint: disable=unused-argument
+ return {
+ 'num_sessions': 0
+ }
+
+ def get_clientinfo(self, target_iqn, client_iqn):
+ # pylint: disable=unused-argument
+ return self.clientinfo
diff --git a/src/pybind/mgr/dashboard/tests/test_notification.py b/src/pybind/mgr/dashboard/tests/test_notification.py
new file mode 100644
index 00000000..185ddc12
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_notification.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import random
+import time
+import unittest
+
+
+from ..tools import NotificationQueue
+
+
+class Listener(object):
+ # pylint: disable=too-many-instance-attributes
+ def __init__(self):
+ self.type1 = []
+ self.type1_ts = []
+ self.type2 = []
+ self.type2_ts = []
+ self.type1_3 = []
+ self.type1_3_ts = []
+ self.all = []
+ self.all_ts = []
+
+ def register(self):
+ NotificationQueue.register(self.log_type1, 'type1', priority=90)
+ NotificationQueue.register(self.log_type2, 'type2')
+ NotificationQueue.register(self.log_type1_3, ['type1', 'type3'])
+ NotificationQueue.register(self.log_all, priority=50)
+
+ # these should be ignored by the queue
+ NotificationQueue.register(self.log_type1, 'type1')
+ NotificationQueue.register(self.log_type1_3, ['type1', 'type3'])
+ NotificationQueue.register(self.log_all)
+
+ def log_type1(self, val):
+ self.type1_ts.append(time.time())
+ self.type1.append(val)
+
+ def log_type2(self, val):
+ self.type2_ts.append(time.time())
+ self.type2.append(val)
+
+ def log_type1_3(self, val):
+ self.type1_3_ts.append(time.time())
+ self.type1_3.append(val)
+
+ def log_all(self, val):
+ self.all_ts.append(time.time())
+ self.all.append(val)
+
+ def clear(self):
+ self.type1 = []
+ self.type1_ts = []
+ self.type2 = []
+ self.type2_ts = []
+ self.type1_3 = []
+ self.type1_3_ts = []
+ self.all = []
+ self.all_ts = []
+ NotificationQueue.deregister(self.log_type1, 'type1')
+ NotificationQueue.deregister(self.log_type2, 'type2')
+ NotificationQueue.deregister(self.log_type1_3, ['type1', 'type3'])
+ NotificationQueue.deregister(self.log_all)
+
+
+class NotificationQueueTest(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.listener = Listener()
+
+ def setUp(self):
+ self.listener.register()
+
+ def tearDown(self):
+ self.listener.clear()
+
+ def test_invalid_register(self):
+ with self.assertRaises(Exception) as ctx:
+ NotificationQueue.register(None, 1)
+ self.assertEqual(str(ctx.exception),
+ "n_types param is neither a string nor a list")
+
+ def test_notifications(self):
+ NotificationQueue.start_queue()
+ NotificationQueue.new_notification('type1', 1)
+ NotificationQueue.new_notification('type2', 2)
+ NotificationQueue.new_notification('type3', 3)
+ NotificationQueue.stop()
+ self.assertEqual(self.listener.type1, [1])
+ self.assertEqual(self.listener.type2, [2])
+ self.assertEqual(self.listener.type1_3, [1, 3])
+ self.assertEqual(self.listener.all, [1, 2, 3])
+
+ # validate priorities
+ self.assertLessEqual(self.listener.type1_3_ts[0], self.listener.all_ts[0])
+ self.assertLessEqual(self.listener.all_ts[0], self.listener.type1_ts[0])
+ self.assertLessEqual(self.listener.type2_ts[0], self.listener.all_ts[1])
+ self.assertLessEqual(self.listener.type1_3_ts[1], self.listener.all_ts[2])
+
+ def test_notifications2(self):
+ NotificationQueue.start_queue()
+ for i in range(0, 600):
+ typ = "type{}".format(i % 3 + 1)
+ if random.random() < 0.5:
+ time.sleep(0.002)
+ NotificationQueue.new_notification(typ, i)
+ NotificationQueue.stop()
+ for i in range(0, 600):
+ typ = i % 3 + 1
+ if typ == 1:
+ self.assertIn(i, self.listener.type1)
+ self.assertIn(i, self.listener.type1_3)
+ elif typ == 2:
+ self.assertIn(i, self.listener.type2)
+ elif typ == 3:
+ self.assertIn(i, self.listener.type1_3)
+ self.assertIn(i, self.listener.all)
+
+ self.assertEqual(len(self.listener.type1), 200)
+ self.assertEqual(len(self.listener.type2), 200)
+ self.assertEqual(len(self.listener.type1_3), 400)
+ self.assertEqual(len(self.listener.all), 600)
+
+ def test_deregister(self):
+ NotificationQueue.start_queue()
+ NotificationQueue.new_notification('type1', 1)
+ NotificationQueue.new_notification('type3', 3)
+ NotificationQueue.stop()
+ self.assertEqual(self.listener.type1, [1])
+ self.assertEqual(self.listener.type1_3, [1, 3])
+
+ NotificationQueue.start_queue()
+ NotificationQueue.deregister(self.listener.log_type1_3, ['type1'])
+ NotificationQueue.new_notification('type1', 4)
+ NotificationQueue.new_notification('type3', 5)
+ NotificationQueue.stop()
+ self.assertEqual(self.listener.type1, [1, 4])
+ self.assertEqual(self.listener.type1_3, [1, 3, 5])
diff --git a/src/pybind/mgr/dashboard/tests/test_osd.py b/src/pybind/mgr/dashboard/tests/test_osd.py
new file mode 100644
index 00000000..0f24d25e
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_osd.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import uuid
+from contextlib import contextmanager
+
+from mock import patch
+
+from . import ControllerTestCase
+from ..controllers.osd import Osd
+from .. import mgr
+from .helper import update_dict
+
+try:
+ from typing import List, Dict, Any # pylint: disable=unused-import
+except ImportError:
+ pass # Only requried for type hints
+
+
+class OsdHelper(object):
+ DEFAULT_OSD_IDS = [0, 1, 2]
+
+ @staticmethod
+ def _gen_osdmap_tree_node(node_id, node_type, children=None, update_data=None):
+ # type: (int, str, List[int], Dict[str, Any]) -> Dict[str, Any]
+ assert node_type in ['root', 'host', 'osd']
+ if node_type in ['root', 'host']:
+ assert children is not None
+
+ node_types = {
+ 'root': {
+ 'id': node_id,
+ 'name': 'default',
+ 'type': 'root',
+ 'type_id': 10,
+ 'children': children,
+ },
+ 'host': {
+ 'id': node_id,
+ 'name': 'ceph-1',
+ 'type': 'host',
+ 'type_id': 1,
+ 'pool_weights': {},
+ 'children': children,
+ },
+ 'osd': {
+ 'id': node_id,
+ 'device_class': 'hdd',
+ 'type': 'osd',
+ 'type_id': 0,
+ 'crush_weight': 0.009796142578125,
+ 'depth': 2,
+ 'pool_weights': {},
+ 'exists': 1,
+ 'status': 'up',
+ 'reweight': 1.0,
+ 'primary_affinity': 1.0,
+ 'name': 'osd.{}'.format(node_id),
+ }
+ }
+ node = node_types[node_type]
+
+ return update_dict(node, update_data) if update_data else node
+
+ @staticmethod
+ def _gen_osd_stats(osd_id, update_data=None):
+ # type: (int, Dict[str, Any]) -> Dict[str, Any]
+ stats = {
+ 'osd': osd_id,
+ 'up_from': 11,
+ 'seq': 47244640581,
+ 'num_pgs': 50,
+ 'kb': 10551288,
+ 'kb_used': 1119736,
+ 'kb_used_data': 5504,
+ 'kb_used_omap': 0,
+ 'kb_used_meta': 1048576,
+ 'kb_avail': 9431552,
+ 'statfs': {
+ 'total': 10804518912,
+ 'available': 9657909248,
+ 'internally_reserved': 1073741824,
+ 'allocated': 5636096,
+ 'data_stored': 102508,
+ 'data_compressed': 0,
+ 'data_compressed_allocated': 0,
+ 'data_compressed_original': 0,
+ 'omap_allocated': 0,
+ 'internal_metadata': 1073741824
+ },
+ 'hb_peers': [0, 1],
+ 'snap_trim_queue_len': 0,
+ 'num_snap_trimming': 0,
+ 'op_queue_age_hist': {
+ 'histogram': [],
+ 'upper_bound': 1
+ },
+ 'perf_stat': {
+ 'commit_latency_ms': 0.0,
+ 'apply_latency_ms': 0.0,
+ 'commit_latency_ns': 0,
+ 'apply_latency_ns': 0
+ },
+ 'alerts': [],
+ }
+ return stats if not update_data else update_dict(stats, update_data)
+
+ @staticmethod
+ def _gen_osd_map_osd(osd_id):
+ # type: (int) -> Dict[str, Any]
+ return {
+ 'osd': osd_id,
+ 'up': 1,
+ 'in': 1,
+ 'weight': 1.0,
+ 'primary_affinity': 1.0,
+ 'last_clean_begin': 0,
+ 'last_clean_end': 0,
+ 'up_from': 5,
+ 'up_thru': 21,
+ 'down_at': 0,
+ 'lost_at': 0,
+ 'public_addrs': {
+ 'addrvec': [{
+ 'type': 'v2',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6802'
+ }, {
+ 'type': 'v1',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6803'
+ }]
+ },
+ 'cluster_addrs': {
+ 'addrvec': [{
+ 'type': 'v2',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6804'
+ }, {
+ 'type': 'v1',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6805'
+ }]
+ },
+ 'heartbeat_back_addrs': {
+ 'addrvec': [{
+ 'type': 'v2',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6808'
+ }, {
+ 'type': 'v1',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6809'
+ }]
+ },
+ 'heartbeat_front_addrs': {
+ 'addrvec': [{
+ 'type': 'v2',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6806'
+ }, {
+ 'type': 'v1',
+ 'nonce': 1302,
+ 'addr': '172.23.0.2:6807'
+ }]
+ },
+ 'state': ['exists', 'up'],
+ 'uuid': str(uuid.uuid4()),
+ 'public_addr': '172.23.0.2:6803/1302',
+ 'cluster_addr': '172.23.0.2:6805/1302',
+ 'heartbeat_back_addr': '172.23.0.2:6809/1302',
+ 'heartbeat_front_addr': '172.23.0.2:6807/1302',
+ 'id': osd_id,
+ }
+
+ @classmethod
+ def gen_osdmap(cls, ids=None):
+ # type: (List[int]) -> Dict[str, Any]
+ return {str(i): cls._gen_osd_map_osd(i) for i in ids or cls.DEFAULT_OSD_IDS}
+
+ @classmethod
+ def gen_osd_stats(cls, ids=None):
+ # type: (List[int]) -> List[Dict[str, Any]]
+ return [cls._gen_osd_stats(i) for i in ids or cls.DEFAULT_OSD_IDS]
+
+ @classmethod
+ def gen_osdmap_tree_nodes(cls, ids=None):
+ # type: (List[int]) -> List[Dict[str, Any]]
+ return [
+ cls._gen_osdmap_tree_node(-1, 'root', [-3]),
+ cls._gen_osdmap_tree_node(-3, 'host', ids or cls.DEFAULT_OSD_IDS),
+ ] + [cls._gen_osdmap_tree_node(node_id, 'osd') for node_id in ids or cls.DEFAULT_OSD_IDS]
+
+ @classmethod
+ def gen_mgr_get_counter(cls):
+ # type: () -> List[List[int]]
+ return [[1551973855, 35], [1551973860, 35], [1551973865, 35], [1551973870, 35]]
+
+
+class OsdTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ Osd._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
+ cls.setup_controllers([Osd])
+
+ @contextmanager
+ def _mock_osd_list(self, osd_stat_ids, osdmap_tree_node_ids, osdmap_ids):
+ def mgr_get_replacement(*args, **kwargs):
+ method = args[0] or kwargs['method']
+ if method == 'osd_stats':
+ return {'osd_stats': OsdHelper.gen_osd_stats(osd_stat_ids)}
+ if method == 'osd_map_tree':
+ return {'nodes': OsdHelper.gen_osdmap_tree_nodes(osdmap_tree_node_ids)}
+ raise NotImplementedError()
+
+ def mgr_get_counter_replacement(svc_type, _, path):
+ if svc_type == 'osd':
+ return {path: OsdHelper.gen_mgr_get_counter()}
+ raise NotImplementedError()
+
+ with patch.object(Osd, 'get_osd_map', return_value=OsdHelper.gen_osdmap(osdmap_ids)):
+ with patch.object(mgr, 'get', side_effect=mgr_get_replacement):
+ with patch.object(mgr, 'get_counter', side_effect=mgr_get_counter_replacement):
+ with patch.object(mgr, 'get_latest', return_value=1146609664):
+ yield
+
+ def test_osd_list_aggregation(self):
+ """
+ This test emulates the state of a cluster where an OSD has only been
+ removed (with e.g. `ceph osd rm`), but it hasn't been removed from the
+ CRUSH map. Ceph reports a health warning alongside a `1 osds exist in
+ the crush map but not in the osdmap` warning in such a case.
+ """
+ osds_actual = [0, 1]
+ osds_leftover = [0, 1, 2]
+ with self._mock_osd_list(osd_stat_ids=osds_actual, osdmap_tree_node_ids=osds_leftover,
+ osdmap_ids=osds_actual):
+ self._get('/api/osd')
+ self.assertEqual(len(self.jsonBody()), 2, 'It should display two OSDs without failure')
+ self.assertStatus(200)
diff --git a/src/pybind/mgr/dashboard/tests/test_plugin_debug.py b/src/pybind/mgr/dashboard/tests/test_plugin_debug.py
new file mode 100644
index 00000000..e6999782
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_plugin_debug.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import CLICommandTestMixin, ControllerTestCase
+
+
+class TestPluginDebug(ControllerTestCase, CLICommandTestMixin):
+ @classmethod
+ def setup_server(cls):
+ # pylint: disable=protected-access
+ cls.setup_controllers([])
+
+ def setUp(self):
+ self.mock_kv_store()
+
+ def test_debug_disabled(self):
+ self.exec_cmd('debug', action='disable')
+
+ self._get('/api/unexisting_controller')
+ self.assertStatus(404)
+
+ data = self.jsonBody()
+ self.assertGreater(len(data), 0)
+ self.assertNotIn('traceback', data)
+ self.assertNotIn('version', data)
+ self.assertIn('request_id', data)
+
+ def test_debug_enabled(self):
+ self.exec_cmd('debug', action='enable')
+
+ self._get('/api/unexisting_controller')
+ self.assertStatus(404)
+
+ data = self.jsonBody()
+ self.assertGreater(len(data), 0)
+ self.assertIn('traceback', data)
+ self.assertIn('version', data)
+ self.assertIn('request_id', data)
diff --git a/src/pybind/mgr/dashboard/tests/test_pool.py b/src/pybind/mgr/dashboard/tests/test_pool.py
new file mode 100644
index 00000000..16d7d7b1
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_pool.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=protected-access
+import time
+import mock
+
+from . import ControllerTestCase
+from ..controllers.pool import Pool
+from ..controllers.task import Task
+from ..tools import NotificationQueue, TaskManager
+
+
+class MockTask(object):
+ percentages = []
+
+ def set_progress(self, percentage):
+ self.percentages.append(percentage)
+
+
+class PoolControllerTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ Task._cp_config['tools.authenticate.on'] = False
+ Pool._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([Pool, Task])
+
+ @mock.patch('dashboard.controllers.pool.Pool._get')
+ @mock.patch('dashboard.services.ceph_service.CephService.send_command')
+ def test_creation(self, send_command, _get):
+ _get.side_effect = [{
+ 'pool_name': 'test-pool',
+ 'pg_num': 64,
+ 'pg_num_target': 63,
+ 'pg_placement_num': 64,
+ 'pg_placement_num_target': 63
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 64,
+ 'pg_num_target': 64,
+ 'pg_placement_num': 64,
+ 'pg_placement_num_target': 64
+ }]
+ NotificationQueue.start_queue()
+ TaskManager.init()
+
+ def _send_cmd(*args, **kwargs): # pylint: disable=unused-argument
+ time.sleep(3)
+
+ send_command.side_effect = _send_cmd
+
+ self._task_post('/api/pool', {
+ 'pool': 'test-pool',
+ 'pool_type': 1,
+ 'pg_num': 64
+ }, 10)
+ self.assertStatus(201)
+ self.assertEqual(_get.call_count, 2)
+ NotificationQueue.stop()
+
+ @mock.patch('dashboard.controllers.pool.Pool._get')
+ def test_wait_for_pgs_without_waiting(self, _get):
+ _get.side_effect = [{
+ 'pool_name': 'test-pool',
+ 'pg_num': 32,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 32,
+ 'pg_placement_num_target': 32
+ }]
+ Pool._wait_for_pgs('test-pool')
+ self.assertEqual(_get.call_count, 1)
+
+ @mock.patch('dashboard.controllers.pool.Pool._get')
+ def test_wait_for_pgs_with_waiting(self, _get):
+ task = MockTask()
+ orig_method = TaskManager.current_task
+ TaskManager.current_task = mock.MagicMock()
+ TaskManager.current_task.return_value = task
+ _get.side_effect = [{
+ 'pool_name': 'test-pool',
+ 'pg_num': 64,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 64,
+ 'pg_placement_num_target': 64
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 63,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 62,
+ 'pg_placement_num_target': 32
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 48,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 48,
+ 'pg_placement_num_target': 32
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 48,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 33,
+ 'pg_placement_num_target': 32
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 33,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 32,
+ 'pg_placement_num_target': 32
+ }, {
+ 'pool_name': 'test-pool',
+ 'pg_num': 32,
+ 'pg_num_target': 32,
+ 'pg_placement_num': 32,
+ 'pg_placement_num_target': 32
+ }]
+ Pool._wait_for_pgs('test-pool')
+ self.assertEqual(_get.call_count, 6)
+ self.assertEqual(task.percentages, [0, 5, 50, 73, 98])
+ TaskManager.current_task = orig_method
diff --git a/src/pybind/mgr/dashboard/tests/test_prometheus.py b/src/pybind/mgr/dashboard/tests/test_prometheus.py
new file mode 100644
index 00000000..73dedbab
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_prometheus.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=protected-access
+from mock import patch
+
+from . import ControllerTestCase
+from .. import mgr
+from ..controllers.prometheus import Prometheus, PrometheusReceiver, PrometheusNotifications
+
+
+class PrometheusControllerTest(ControllerTestCase):
+ alert_host = 'http://alertmanager:9093/mock'
+ alert_host_api = alert_host + '/api/v1'
+
+ prometheus_host = 'http://prometheus:9090/mock'
+ prometheus_host_api = prometheus_host + '/api/v1'
+
+ @classmethod
+ def setup_server(cls):
+ settings = {
+ 'ALERTMANAGER_API_HOST': cls.alert_host,
+ 'PROMETHEUS_API_HOST': cls.prometheus_host
+ }
+ mgr.get_module_option.side_effect = settings.get
+ Prometheus._cp_config['tools.authenticate.on'] = False
+ PrometheusNotifications._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([Prometheus, PrometheusNotifications, PrometheusReceiver])
+
+ def test_rules(self):
+ with patch('requests.request') as mock_request:
+ self._get('/api/prometheus/rules')
+ mock_request.assert_called_with('GET', self.prometheus_host_api + '/rules',
+ json=None, params={})
+
+ def test_list(self):
+ with patch('requests.request') as mock_request:
+ self._get('/api/prometheus')
+ mock_request.assert_called_with('GET', self.alert_host_api + '/alerts',
+ json=None, params={})
+
+ def test_get_silences(self):
+ with patch('requests.request') as mock_request:
+ self._get('/api/prometheus/silences')
+ mock_request.assert_called_with('GET', self.alert_host_api + '/silences',
+ json=None, params={})
+
+ def test_add_silence(self):
+ with patch('requests.request') as mock_request:
+ self._post('/api/prometheus/silence', {'id': 'new-silence'})
+ mock_request.assert_called_with('POST', self.alert_host_api + '/silences',
+ params=None, json={'id': 'new-silence'})
+
+ def test_update_silence(self):
+ with patch('requests.request') as mock_request:
+ self._post('/api/prometheus/silence', {'id': 'update-silence'})
+ mock_request.assert_called_with('POST', self.alert_host_api + '/silences',
+ params=None, json={'id': 'update-silence'})
+
+ def test_expire_silence(self):
+ with patch('requests.request') as mock_request:
+ self._delete('/api/prometheus/silence/0')
+ mock_request.assert_called_with('DELETE', self.alert_host_api + '/silence/0',
+ json=None, params=None)
+
+ def test_silences_empty_delete(self):
+ with patch('requests.request') as mock_request:
+ self._delete('/api/prometheus/silence')
+ mock_request.assert_not_called()
+
+ def test_post_on_receiver(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ self.assertEqual(len(PrometheusReceiver.notifications), 1)
+ notification = PrometheusReceiver.notifications[0]
+ self.assertEqual(notification['name'], 'foo')
+ self.assertTrue(len(notification['notified']) > 20)
+
+ def test_get_empty_list_with_no_notifications(self):
+ PrometheusReceiver.notifications = []
+ self._get('/api/prometheus/notifications')
+ self.assertStatus(200)
+ self.assertJsonBody([])
+ self._get('/api/prometheus/notifications?from=last')
+ self.assertStatus(200)
+ self.assertJsonBody([])
+
+ def test_get_all_notification(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ self._post('/api/prometheus_receiver', {'name': 'bar'})
+ self._get('/api/prometheus/notifications')
+ self.assertStatus(200)
+ self.assertJsonBody(PrometheusReceiver.notifications)
+
+ def test_get_last_notification_with_use_of_last_keyword(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ self._post('/api/prometheus_receiver', {'name': 'bar'})
+ self._get('/api/prometheus/notifications?from=last')
+ self.assertStatus(200)
+ last = PrometheusReceiver.notifications[1]
+ self.assertJsonBody([last])
+
+ def test_get_no_notification_with_unknown_id(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ self._post('/api/prometheus_receiver', {'name': 'bar'})
+ self._get('/api/prometheus/notifications?from=42')
+ self.assertStatus(200)
+ self.assertJsonBody([])
+
+ def test_get_no_notification_since_with_last_notification(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ notification = PrometheusReceiver.notifications[0]
+ self._get('/api/prometheus/notifications?from=' + notification['id'])
+ self.assertStatus(200)
+ self.assertJsonBody([])
+
+ def test_get_notifications_since_last_notification(self):
+ PrometheusReceiver.notifications = []
+ self._post('/api/prometheus_receiver', {'name': 'foobar'})
+ next_to_last = PrometheusReceiver.notifications[0]
+ self._post('/api/prometheus_receiver', {'name': 'foo'})
+ self._post('/api/prometheus_receiver', {'name': 'bar'})
+ self._get('/api/prometheus/notifications?from=' + next_to_last['id'])
+ forelast = PrometheusReceiver.notifications[1]
+ last = PrometheusReceiver.notifications[2]
+ self.assertEqual(self.jsonBody(), [forelast, last])
diff --git a/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py
new file mode 100644
index 00000000..b307c209
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py
@@ -0,0 +1,95 @@
+from __future__ import absolute_import
+
+import json
+import mock
+
+from . import ControllerTestCase
+from .. import mgr
+from ..controllers.summary import Summary
+from ..controllers.rbd_mirroring import RbdMirroringSummary
+
+
+mock_list_servers = [{
+ 'hostname': 'ceph-host',
+ 'services': [{'id': 3, 'type': 'rbd-mirror'}]
+}]
+
+mock_get_metadata = {
+ 'id': 1,
+ 'instance_id': 3,
+ 'ceph_version': 'ceph version 13.0.0-5719 mimic (dev)'
+}
+
+_status = {
+ 1: {
+ 'callouts': {},
+ 'image_local_count': 5,
+ 'image_remote_count': 6,
+ 'image_error_count': 7,
+ 'image_warning_count': 8,
+ 'name': 'pool_name'
+ }
+}
+
+mock_get_daemon_status = {
+ 'json': json.dumps(_status)
+}
+
+mock_osd_map = {
+ 'pools': [{
+ 'pool_name': 'rbd',
+ 'application_metadata': {'rbd'}
+ }]
+}
+
+
+class RbdMirroringSummaryControllerTest(ControllerTestCase):
+
+ @classmethod
+ def setup_server(cls):
+ mgr.list_servers.return_value = mock_list_servers
+ mgr.get_metadata = mock.Mock(return_value=mock_get_metadata)
+ mgr.get_daemon_status.return_value = mock_get_daemon_status
+ mgr.get.side_effect = lambda key: {
+ 'osd_map': mock_osd_map,
+ 'health': {'json': '{"status": 1}'},
+ 'fs_map': {'filesystems': []},
+ 'mgr_map': {
+ 'services': {
+ 'dashboard': 'https://ceph.dev:11000/'
+ },
+ }
+ }[key]
+ mgr.url_prefix = ''
+ mgr.get_mgr_id.return_value = 0
+ mgr.have_mon_connection.return_value = True
+ mgr.version = 'ceph version 13.1.0-534-g23d3751b89 ' \
+ '(23d3751b897b31d2bda57aeaf01acb5ff3c4a9cd) ' \
+ 'nautilus (dev)'
+
+ # pylint: disable=protected-access
+ RbdMirroringSummary._cp_config['tools.authenticate.on'] = False
+ Summary._cp_config['tools.authenticate.on'] = False
+ # pylint: enable=protected-access
+
+ cls.setup_controllers([RbdMirroringSummary, Summary], '/test')
+
+ @mock.patch('dashboard.controllers.rbd_mirroring.rbd')
+ def test_default(self, rbd_mock): # pylint: disable=W0613
+ self._get('/test/api/block/mirroring/summary')
+ result = self.jsonBody()
+ self.assertStatus(200)
+ self.assertEqual(result['status'], 0)
+ for k in ['daemons', 'pools', 'image_error', 'image_syncing', 'image_ready']:
+ self.assertIn(k, result['content_data'])
+
+ @mock.patch('dashboard.controllers.BaseController._has_permissions')
+ @mock.patch('dashboard.controllers.rbd_mirroring.rbd')
+ def test_summary(self, rbd_mock, has_perms_mock): # pylint: disable=W0613
+ """We're also testing `summary`, as it also uses code from `rbd_mirroring.py`"""
+ has_perms_mock.return_value = True
+ self._get('/test/api/summary')
+ self.assertStatus(200)
+
+ summary = self.jsonBody()['rbd_mirroring']
+ self.assertEqual(summary, {'errors': 0, 'warnings': 1})
diff --git a/src/pybind/mgr/dashboard/tests/test_rbd_service.py b/src/pybind/mgr/dashboard/tests/test_rbd_service.py
new file mode 100644
index 00000000..a4511fa9
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rbd_service.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=dangerous-default-value,too-many-public-methods
+from __future__ import absolute_import
+
+import unittest
+try:
+ import mock
+except ImportError:
+ import unittest.mock as mock
+
+from ..services.rbd import RbdConfiguration
+
+
+class RbdServiceTest(unittest.TestCase):
+
+ @mock.patch('dashboard.services.rbd.RbdConfiguration._rbd.config_list')
+ @mock.patch('dashboard.mgr.get')
+ @mock.patch('dashboard.services.ceph_service.CephService.get_pool_list')
+ def test_pool_rbd_configuration_with_different_pg_states(self, get_pool_list, get, config_list):
+ get_pool_list.return_value = [{
+ 'pool_name': 'good-pool',
+ 'pool': 1,
+ }, {
+ 'pool_name': 'bad-pool',
+ 'pool': 2,
+ }]
+ get.return_value = {
+ 'by_pool': {
+ '1': {'active+clean': 32},
+ '2': {'creating+incomplete': 32},
+ }
+ }
+ config_list.return_value = [1, 2, 3]
+ config = RbdConfiguration('bad-pool')
+ self.assertEqual(config.list(), [])
+ config = RbdConfiguration('good-pool')
+ self.assertEqual(config.list(), [1, 2, 3])
diff --git a/src/pybind/mgr/dashboard/tests/test_rest_client.py b/src/pybind/mgr/dashboard/tests/test_rest_client.py
new file mode 100644
index 00000000..36ecd51a
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rest_client.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+import unittest
+import requests.exceptions
+
+from mock import patch
+from urllib3.exceptions import MaxRetryError, ProtocolError
+from .. import mgr
+from ..rest_client import RequestException, RestClient
+
+
+class RestClientTest(unittest.TestCase):
+ def setUp(self):
+ settings = {'REST_REQUESTS_TIMEOUT': 45}
+ mgr.get_module_option.side_effect = settings.get
+
+ def test_timeout_auto_set(self):
+ with patch('requests.Session.request') as mock_request:
+ rest_client = RestClient('localhost', 8000)
+ rest_client.session.request('GET', '/test')
+ mock_request.assert_called_with('GET', '/test', timeout=45)
+
+ def test_timeout_auto_set_arg(self):
+ with patch('requests.Session.request') as mock_request:
+ rest_client = RestClient('localhost', 8000)
+ rest_client.session.request(
+ 'GET', '/test', None, None, None, None,
+ None, None, None)
+ mock_request.assert_called_with(
+ 'GET', '/test', None, None, None, None,
+ None, None, None, timeout=45)
+
+ def test_timeout_no_auto_set_kwarg(self):
+ with patch('requests.Session.request') as mock_request:
+ rest_client = RestClient('localhost', 8000)
+ rest_client.session.request('GET', '/test', timeout=20)
+ mock_request.assert_called_with('GET', '/test', timeout=20)
+
+ def test_timeout_no_auto_set_arg(self):
+ with patch('requests.Session.request') as mock_request:
+ rest_client = RestClient('localhost', 8000)
+ rest_client.session.request(
+ 'GET', '/test', None, None, None, None,
+ None, None, 40)
+ mock_request.assert_called_with(
+ 'GET', '/test', None, None, None, None,
+ None, None, 40)
+
+
+class RestClientDoRequestTest(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.mock_requests = patch('requests.Session').start()
+ cls.rest_client = RestClient('localhost', 8000, 'UnitTest')
+
+ def test_do_request_exception_no_args(self):
+ self.mock_requests().get.side_effect = requests.exceptions.ConnectionError()
+ with self.assertRaises(RequestException) as context:
+ self.rest_client.do_request('GET', '/test')
+ self.assertEqual('UnitTest REST API cannot be reached. Please '
+ 'check your configuration and that the API '
+ 'endpoint is accessible',
+ context.exception.message)
+
+ def test_do_request_exception_args_1(self):
+ self.mock_requests().post.side_effect = requests.exceptions.ConnectionError(
+ MaxRetryError('Abc', 'http://xxx.yyy', 'too many redirects'))
+ with self.assertRaises(RequestException) as context:
+ self.rest_client.do_request('POST', '/test')
+ self.assertEqual('UnitTest REST API cannot be reached. Please '
+ 'check your configuration and that the API '
+ 'endpoint is accessible',
+ context.exception.message)
+
+ def test_do_request_exception_args_2(self):
+ self.mock_requests().put.side_effect = requests.exceptions.ConnectionError(
+ ProtocolError('Connection broken: xyz'))
+ with self.assertRaises(RequestException) as context:
+ self.rest_client.do_request('PUT', '/test')
+ self.assertEqual('UnitTest REST API cannot be reached. Please '
+ 'check your configuration and that the API '
+ 'endpoint is accessible',
+ context.exception.message)
+
+ def test_do_request_exception_nested_args(self):
+ self.mock_requests().delete.side_effect = requests.exceptions.ConnectionError(
+ MaxRetryError('Xyz', 'https://foo.bar',
+ Exception('Foo: [Errno -42] bla bla bla')))
+ with self.assertRaises(RequestException) as context:
+ self.rest_client.do_request('DELETE', '/test')
+ self.assertEqual('UnitTest REST API cannot be reached: bla '
+ 'bla bla [errno -42]. Please check your '
+ 'configuration and that the API endpoint '
+ 'is accessible',
+ context.exception.message)
diff --git a/src/pybind/mgr/dashboard/tests/test_rest_tasks.py b/src/pybind/mgr/dashboard/tests/test_rest_tasks.py
new file mode 100644
index 00000000..191ef812
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rest_tasks.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=blacklisted-name
+
+import time
+
+from . import ControllerTestCase
+from ..controllers import Controller, RESTController, Task
+from ..controllers.task import Task as TaskController
+from ..tools import NotificationQueue, TaskManager
+
+
+@Controller('/test/task', secure=False)
+class TaskTest(RESTController):
+ sleep_time = 0.0
+
+ @Task('task/create', {'param': '{param}'}, wait_for=1.0)
+ def create(self, param):
+ time.sleep(TaskTest.sleep_time)
+ return {'my_param': param}
+
+ @Task('task/set', {'param': '{2}'}, wait_for=1.0)
+ def set(self, key, param=None):
+ time.sleep(TaskTest.sleep_time)
+ return {'key': key, 'my_param': param}
+
+ @Task('task/delete', ['{key}'], wait_for=1.0)
+ def delete(self, key):
+ # pylint: disable=unused-argument
+ time.sleep(TaskTest.sleep_time)
+
+ @Task('task/foo', ['{param}'])
+ @RESTController.Collection('POST')
+ def foo(self, param):
+ return {'my_param': param}
+
+ @Task('task/bar', ['{key}', '{param}'])
+ @RESTController.Resource('PUT')
+ def bar(self, key, param=None):
+ return {'my_param': param, 'key': key}
+
+ @Task('task/query', ['{param}'])
+ @RESTController.Collection('POST', query_params=['param'])
+ def query(self, param=None):
+ return {'my_param': param}
+
+
+class TaskControllerTest(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ # pylint: disable=protected-access
+ NotificationQueue.start_queue()
+ TaskManager.init()
+ TaskTest._cp_config['tools.authenticate.on'] = False
+ TaskController._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([TaskTest, TaskController])
+
+ @classmethod
+ def tearDownClass(cls):
+ NotificationQueue.stop()
+
+ def setUp(self):
+ TaskTest.sleep_time = 0.0
+
+ def test_create_task(self):
+ self._task_post('/test/task', {'param': 'hello'})
+ self.assertJsonBody({'my_param': 'hello'})
+
+ def test_long_set_task(self):
+ TaskTest.sleep_time = 2.0
+ self._task_put('/test/task/2', {'param': 'hello'})
+ self.assertJsonBody({'key': '2', 'my_param': 'hello'})
+
+ def test_delete_task(self):
+ self._task_delete('/test/task/hello')
+
+ def test_foo_task(self):
+ self._task_post('/test/task/foo', {'param': 'hello'})
+ self.assertJsonBody({'my_param': 'hello'})
+
+ def test_bar_task(self):
+ self._task_put('/test/task/3/bar', {'param': 'hello'})
+ self.assertJsonBody({'my_param': 'hello', 'key': '3'})
+
+ def test_query_param(self):
+ self._task_post('/test/task/query')
+ self.assertJsonBody({'my_param': None})
diff --git a/src/pybind/mgr/dashboard/tests/test_rgw.py b/src/pybind/mgr/dashboard/tests/test_rgw.py
new file mode 100644
index 00000000..9f586be2
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rgw.py
@@ -0,0 +1,129 @@
+import mock
+
+from .. import mgr
+from ..controllers.rgw import Rgw, RgwUser
+from . import ControllerTestCase # pylint: disable=no-name-in-module
+
+
+class RgwControllerTestCase(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ Rgw._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
+ cls.setup_controllers([Rgw], '/test')
+
+ def test_status_no_service(self):
+ mgr.list_servers.return_value = []
+ self._get('/test/api/rgw/status')
+ self.assertStatus(200)
+ self.assertJsonBody({'available': False, 'message': 'No RGW service is running.'})
+
+
+class RgwUserControllerTestCase(ControllerTestCase):
+ @classmethod
+ def setup_server(cls):
+ RgwUser._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
+ cls.setup_controllers([RgwUser], '/test')
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ def test_user_list(self, mock_proxy):
+ mock_proxy.side_effect = [{
+ 'count': 3,
+ 'keys': ['test1', 'test2', 'test3'],
+ 'truncated': False
+ }]
+ self._get('/test/api/rgw/user')
+ self.assertStatus(200)
+ mock_proxy.assert_has_calls([
+ mock.call('GET', 'user?list', {})
+ ])
+ self.assertJsonBody(['test1', 'test2', 'test3'])
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ def test_user_list_marker(self, mock_proxy):
+ mock_proxy.side_effect = [{
+ 'count': 3,
+ 'keys': ['test1', 'test2', 'test3'],
+ 'marker': 'foo:bar',
+ 'truncated': True
+ }, {
+ 'count': 1,
+ 'keys': ['admin'],
+ 'truncated': False
+ }]
+ self._get('/test/api/rgw/user')
+ self.assertStatus(200)
+ mock_proxy.assert_has_calls([
+ mock.call('GET', 'user?list', {}),
+ mock.call('GET', 'user?list', {'marker': 'foo:bar'})
+ ])
+ self.assertJsonBody(['test1', 'test2', 'test3', 'admin'])
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ def test_user_list_duplicate_marker(self, mock_proxy):
+ mock_proxy.side_effect = [{
+ 'count': 3,
+ 'keys': ['test1', 'test2', 'test3'],
+ 'marker': 'foo:bar',
+ 'truncated': True
+ }, {
+ 'count': 3,
+ 'keys': ['test4', 'test5', 'test6'],
+ 'marker': 'foo:bar',
+ 'truncated': True
+ }, {
+ 'count': 1,
+ 'keys': ['admin'],
+ 'truncated': False
+ }]
+ self._get('/test/api/rgw/user')
+ self.assertStatus(500)
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ def test_user_list_invalid_marker(self, mock_proxy):
+ mock_proxy.side_effect = [{
+ 'count': 3,
+ 'keys': ['test1', 'test2', 'test3'],
+ 'marker': 'foo:bar',
+ 'truncated': True
+ }, {
+ 'count': 3,
+ 'keys': ['test4', 'test5', 'test6'],
+ 'marker': '',
+ 'truncated': True
+ }, {
+ 'count': 1,
+ 'keys': ['admin'],
+ 'truncated': False
+ }]
+ self._get('/test/api/rgw/user')
+ self.assertStatus(500)
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ @mock.patch.object(RgwUser, '_keys_allowed')
+ def test_user_get_with_keys(self, keys_allowed, mock_proxy):
+ keys_allowed.return_value = True
+ mock_proxy.return_value = {
+ 'tenant': '',
+ 'user_id': 'my_user_id',
+ 'keys': [],
+ 'swift_keys': []
+ }
+ self._get('/test/api/rgw/user/testuser')
+ self.assertStatus(200)
+ self.assertInJsonBody('keys')
+ self.assertInJsonBody('swift_keys')
+
+ @mock.patch('dashboard.controllers.rgw.RgwRESTController.proxy')
+ @mock.patch.object(RgwUser, '_keys_allowed')
+ def test_user_get_without_keys(self, keys_allowed, mock_proxy):
+ keys_allowed.return_value = False
+ mock_proxy.return_value = {
+ 'tenant': '',
+ 'user_id': 'my_user_id',
+ 'keys': [],
+ 'swift_keys': []
+ }
+ self._get('/test/api/rgw/user/testuser')
+ self.assertStatus(200)
+ self.assertNotIn('keys', self.jsonBody())
+ self.assertNotIn('swift_keys', self.jsonBody())
diff --git a/src/pybind/mgr/dashboard/tests/test_rgw_client.py b/src/pybind/mgr/dashboard/tests/test_rgw_client.py
new file mode 100644
index 00000000..0824665f
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_rgw_client.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=too-many-public-methods
+import unittest
+
+from ..services.rgw_client import RgwClient, _parse_frontend_config
+from ..settings import Settings
+from . import KVStoreMockMixin
+
+
+class RgwClientTest(unittest.TestCase, KVStoreMockMixin):
+ def setUp(self):
+ RgwClient._user_instances.clear() # pylint: disable=protected-access
+ self.mock_kv_store()
+ self.CONFIG_KEY_DICT.update({
+ 'RGW_API_ACCESS_KEY': 'klausmustermann',
+ 'RGW_API_SECRET_KEY': 'supergeheim',
+ 'RGW_API_HOST': 'localhost',
+ 'RGW_API_USER_ID': 'rgwadmin'
+ })
+
+ def test_ssl_verify(self):
+ Settings.RGW_API_SSL_VERIFY = True
+ instance = RgwClient.admin_instance()
+ self.assertTrue(instance.session.verify)
+
+ def test_no_ssl_verify(self):
+ Settings.RGW_API_SSL_VERIFY = False
+ instance = RgwClient.admin_instance()
+ self.assertFalse(instance.session.verify)
+
+
+class RgwClientHelperTest(unittest.TestCase):
+ def test_parse_frontend_config_1(self):
+ self.assertEqual(_parse_frontend_config('beast port=8000'), (8000, False))
+
+ def test_parse_frontend_config_2(self):
+ self.assertEqual(_parse_frontend_config('beast port=80 port=8000'), (80, False))
+
+ def test_parse_frontend_config_3(self):
+ self.assertEqual(_parse_frontend_config('beast ssl_port=443 port=8000'), (443, True))
+
+ def test_parse_frontend_config_4(self):
+ self.assertEqual(_parse_frontend_config('beast endpoint=192.168.0.100:8000'), (8000, False))
+
+ def test_parse_frontend_config_5(self):
+ self.assertEqual(_parse_frontend_config('beast endpoint=[::1]'), (80, False))
+
+ def test_parse_frontend_config_6(self):
+ self.assertEqual(_parse_frontend_config(
+ 'beast ssl_endpoint=192.168.0.100:8443'), (8443, True))
+
+ def test_parse_frontend_config_7(self):
+ self.assertEqual(_parse_frontend_config('beast ssl_endpoint=192.168.0.100'), (443, True))
+
+ def test_parse_frontend_config_8(self):
+ self.assertEqual(_parse_frontend_config(
+ 'beast ssl_endpoint=[::1]:8443 endpoint=192.0.2.3:80'), (8443, True))
+
+ def test_parse_frontend_config_9(self):
+ self.assertEqual(_parse_frontend_config(
+ 'beast port=8080 endpoint=192.0.2.3:80'), (8080, False))
+
+ def test_parse_frontend_config_10(self):
+ self.assertEqual(_parse_frontend_config(
+ 'beast ssl_endpoint=192.0.2.3:8443 port=8080'), (8443, True))
+
+ def test_parse_frontend_config_11(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=8000s'), (8000, True))
+
+ def test_parse_frontend_config_12(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=443s port=8000'), (443, True))
+
+ def test_parse_frontend_config_13(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=192.0.2.3:80'), (80, False))
+
+ def test_parse_frontend_config_14(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=172.5.2.51:8080s'), (8080, True))
+
+ def test_parse_frontend_config_15(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=[::]:8080'), (8080, False))
+
+ def test_parse_frontend_config_16(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=ip6-localhost:80s'), (80, True))
+
+ def test_parse_frontend_config_17(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=[2001:0db8::1234]:80'), (80, False))
+
+ def test_parse_frontend_config_18(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=[::1]:8443s'), (8443, True))
+
+ def test_parse_frontend_config_19(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8443s+8000'), (8443, True))
+
+ def test_parse_frontend_config_20(self):
+ self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8080+443s'), (8080, False))
+
+ def test_parse_frontend_config_21(self):
+ with self.assertRaises(LookupError) as ctx:
+ _parse_frontend_config('civetweb port=xyz')
+ self.assertEqual(str(ctx.exception),
+ 'Failed to determine RGW port from "civetweb port=xyz"')
+
+ def test_parse_frontend_config_22(self):
+ with self.assertRaises(LookupError) as ctx:
+ _parse_frontend_config('civetweb')
+ self.assertEqual(str(ctx.exception), 'Failed to determine RGW port from "civetweb"')
+
+ def test_parse_frontend_config_23(self):
+ with self.assertRaises(LookupError) as ctx:
+ _parse_frontend_config('mongoose port=8080')
+ self.assertEqual(str(ctx.exception),
+ 'Failed to determine RGW port from "mongoose port=8080"')
diff --git a/src/pybind/mgr/dashboard/tests/test_settings.py b/src/pybind/mgr/dashboard/tests/test_settings.py
new file mode 100644
index 00000000..2d050429
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_settings.py
@@ -0,0 +1,191 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import errno
+import unittest
+
+from mgr_module import ERROR_MSG_EMPTY_INPUT_FILE
+
+from . import KVStoreMockMixin, ControllerTestCase
+from .. import settings
+from ..controllers.settings import Settings as SettingsController
+from ..settings import Settings, handle_option_command
+
+
+class SettingsTest(unittest.TestCase, KVStoreMockMixin):
+ @classmethod
+ def setUpClass(cls):
+ # pylint: disable=protected-access
+ settings.Options.GRAFANA_API_HOST = ('localhost', str)
+ settings.Options.GRAFANA_API_PORT = (3000, int)
+ settings.Options.GRAFANA_ENABLED = (False, bool)
+ settings._OPTIONS_COMMAND_MAP = settings._options_command_map()
+
+ def setUp(self):
+ self.mock_kv_store()
+ if Settings.GRAFANA_API_HOST != 'localhost':
+ Settings.GRAFANA_API_HOST = 'localhost'
+ if Settings.GRAFANA_API_PORT != 3000:
+ Settings.GRAFANA_API_PORT = 3000
+
+ def test_get_setting(self):
+ self.assertEqual(Settings.GRAFANA_API_HOST, 'localhost')
+ self.assertEqual(Settings.GRAFANA_API_PORT, 3000)
+ self.assertEqual(Settings.GRAFANA_ENABLED, False)
+
+ def test_set_setting(self):
+ Settings.GRAFANA_API_HOST = 'grafanahost'
+ self.assertEqual(Settings.GRAFANA_API_HOST, 'grafanahost')
+
+ Settings.GRAFANA_API_PORT = 50
+ self.assertEqual(Settings.GRAFANA_API_PORT, 50)
+
+ Settings.GRAFANA_ENABLED = True
+ self.assertEqual(Settings.GRAFANA_ENABLED, True)
+
+ def test_get_cmd(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard get-grafana-api-port'},
+ None
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, '3000')
+ self.assertEqual(err, '')
+
+ def test_set_cmd(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard set-grafana-api-port',
+ 'value': '4000'},
+ None
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, 'Option GRAFANA_API_PORT updated')
+ self.assertEqual(err, '')
+
+ def test_set_secret_empty(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard set-rgw-api-secret-key'},
+ None
+ )
+ self.assertEqual(r, -errno.EINVAL)
+ self.assertEqual(out, '')
+ self.assertEqual(err, ERROR_MSG_EMPTY_INPUT_FILE)
+
+ def test_set_secret(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard set-rgw-api-secret-key'},
+ 'my-secret'
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, 'Option RGW_API_SECRET_KEY updated')
+ self.assertEqual(err, '')
+
+ def test_reset_cmd(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard reset-grafana-enabled'},
+ None
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, 'Option {} reset to default value "{}"'.format(
+ 'GRAFANA_ENABLED', Settings.GRAFANA_ENABLED))
+ self.assertEqual(err, '')
+
+ def test_inv_cmd(self):
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard get-non-existent-option'},
+ None
+ )
+ self.assertEqual(r, -errno.ENOSYS)
+ self.assertEqual(out, '')
+ self.assertEqual(err, "Command not found "
+ "'dashboard get-non-existent-option'")
+
+ def test_sync(self):
+ Settings.GRAFANA_API_PORT = 5000
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard get-grafana-api-port'},
+ None
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, '5000')
+ self.assertEqual(err, '')
+ r, out, err = handle_option_command(
+ {'prefix': 'dashboard set-grafana-api-host',
+ 'value': 'new-local-host'},
+ None
+ )
+ self.assertEqual(r, 0)
+ self.assertEqual(out, 'Option GRAFANA_API_HOST updated')
+ self.assertEqual(err, '')
+ self.assertEqual(Settings.GRAFANA_API_HOST, 'new-local-host')
+
+ def test_attribute_error(self):
+ with self.assertRaises(AttributeError) as ctx:
+ _ = Settings.NON_EXISTENT_OPTION
+
+ self.assertEqual(str(ctx.exception),
+ "type object 'Options' has no attribute 'NON_EXISTENT_OPTION'")
+
+
+class SettingsControllerTest(ControllerTestCase, KVStoreMockMixin):
+ @classmethod
+ def setup_server(cls):
+ # pylint: disable=protected-access
+
+ SettingsController._cp_config['tools.authenticate.on'] = False
+ cls.setup_controllers([SettingsController])
+
+ def setUp(self):
+ self.mock_kv_store()
+
+ def test_settings_list(self):
+ self._get('/api/settings')
+ data = self.jsonBody()
+ self.assertTrue(len(data) > 0)
+ self.assertStatus(200)
+ self.assertIn('default', data[0].keys())
+ self.assertIn('type', data[0].keys())
+ self.assertIn('name', data[0].keys())
+ self.assertIn('value', data[0].keys())
+
+ def test_rgw_daemon_get(self):
+ self._get('/api/settings/grafana-api-username')
+ self.assertStatus(200)
+ self.assertJsonBody({
+ u'default': u'admin',
+ u'type': u'str',
+ u'name': u'GRAFANA_API_USERNAME',
+ u'value': u'admin',
+ })
+
+ def test_set(self):
+ self._put('/api/settings/GRAFANA_API_USERNAME', {'value': 'foo'},)
+ self.assertStatus(200)
+
+ self._get('/api/settings/GRAFANA_API_USERNAME')
+ self.assertStatus(200)
+ self.assertInJsonBody('default')
+ self.assertInJsonBody('type')
+ self.assertInJsonBody('name')
+ self.assertInJsonBody('value')
+ self.assertEqual(self.jsonBody()['value'], 'foo')
+
+ def test_bulk_set(self):
+ self._put('/api/settings', {
+ 'GRAFANA_API_USERNAME': 'foo',
+ 'GRAFANA_API_HOST': 'somehost',
+ })
+ self.assertStatus(200)
+
+ self._get('/api/settings/grafana-api-username')
+ self.assertStatus(200)
+ body = self.jsonBody()
+ self.assertEqual(body['value'], 'foo')
+
+ self._get('/api/settings/grafana-api-username')
+ self.assertStatus(200)
+ self.assertEqual(self.jsonBody()['value'], 'foo')
+
+ self._get('/api/settings/grafana-api-host')
+ self.assertStatus(200)
+ self.assertEqual(self.jsonBody()['value'], 'somehost')
diff --git a/src/pybind/mgr/dashboard/tests/test_sso.py b/src/pybind/mgr/dashboard/tests/test_sso.py
new file mode 100644
index 00000000..f8681b89
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_sso.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+# pylint: disable=dangerous-default-value,too-many-public-methods
+from __future__ import absolute_import
+
+import errno
+import unittest
+
+from . import CmdException, exec_dashboard_cmd, KVStoreMockMixin
+from ..services.sso import handle_sso_command, load_sso_db
+
+
+class AccessControlTest(unittest.TestCase, KVStoreMockMixin):
+ IDP_METADATA = '''<?xml version="1.0"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ entityID="https://testidp.ceph.com/simplesamlphp/saml2/idp/metadata.php"
+ ID="pfx8ca6fbd7-6062-d4a9-7995-0730aeb8114f">
+ <ds:Signature>
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#pfx8ca6fbd7-6062-d4a9-7995-0730aeb8114f">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>v6V8fooEUeq/LO/59JCfJF69Tw3ohN52OGAY6X3jX8w=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>IDP_SIGNATURE_VALUE</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>IDP_X509_CERTIFICATE</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>IDP_X509_CERTIFICATE</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>IDP_X509_CERTIFICATE</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://testidp.ceph.com/simplesamlphp/saml2/idp/SingleLogoutService.php"/>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://testidp.ceph.com/simplesamlphp/saml2/idp/SSOService.php"/>
+ </md:IDPSSODescriptor>
+</md:EntityDescriptor>'''
+
+ def setUp(self):
+ self.mock_kv_store()
+ load_sso_db()
+
+ @classmethod
+ def exec_cmd(cls, cmd, **kwargs):
+ return exec_dashboard_cmd(handle_sso_command, cmd, **kwargs)
+
+ def validate_onelogin_settings(self, onelogin_settings, ceph_dashboard_base_url, uid,
+ sp_x509cert, sp_private_key, signature_enabled):
+ self.assertIn('sp', onelogin_settings)
+ self.assertIn('entityId', onelogin_settings['sp'])
+ self.assertEqual(onelogin_settings['sp']['entityId'],
+ '{}/auth/saml2/metadata'.format(ceph_dashboard_base_url))
+
+ self.assertIn('assertionConsumerService', onelogin_settings['sp'])
+ self.assertIn('url', onelogin_settings['sp']['assertionConsumerService'])
+ self.assertEqual(onelogin_settings['sp']['assertionConsumerService']['url'],
+ '{}/auth/saml2'.format(ceph_dashboard_base_url))
+
+ self.assertIn('attributeConsumingService', onelogin_settings['sp'])
+ attribute_consuming_service = onelogin_settings['sp']['attributeConsumingService']
+ self.assertIn('requestedAttributes', attribute_consuming_service)
+ requested_attributes = attribute_consuming_service['requestedAttributes']
+ self.assertEqual(len(requested_attributes), 1)
+ self.assertIn('name', requested_attributes[0])
+ self.assertEqual(requested_attributes[0]['name'], uid)
+
+ self.assertIn('singleLogoutService', onelogin_settings['sp'])
+ self.assertIn('url', onelogin_settings['sp']['singleLogoutService'])
+ self.assertEqual(onelogin_settings['sp']['singleLogoutService']['url'],
+ '{}/auth/saml2/logout'.format(ceph_dashboard_base_url))
+
+ self.assertIn('x509cert', onelogin_settings['sp'])
+ self.assertEqual(onelogin_settings['sp']['x509cert'], sp_x509cert)
+
+ self.assertIn('privateKey', onelogin_settings['sp'])
+ self.assertEqual(onelogin_settings['sp']['privateKey'], sp_private_key)
+
+ self.assertIn('security', onelogin_settings)
+ self.assertIn('authnRequestsSigned', onelogin_settings['security'])
+ self.assertEqual(onelogin_settings['security']['authnRequestsSigned'], signature_enabled)
+
+ self.assertIn('logoutRequestSigned', onelogin_settings['security'])
+ self.assertEqual(onelogin_settings['security']['logoutRequestSigned'], signature_enabled)
+
+ self.assertIn('logoutResponseSigned', onelogin_settings['security'])
+ self.assertEqual(onelogin_settings['security']['logoutResponseSigned'], signature_enabled)
+
+ self.assertIn('wantMessagesSigned', onelogin_settings['security'])
+ self.assertEqual(onelogin_settings['security']['wantMessagesSigned'], signature_enabled)
+
+ self.assertIn('wantAssertionsSigned', onelogin_settings['security'])
+ self.assertEqual(onelogin_settings['security']['wantAssertionsSigned'], signature_enabled)
+
+ def test_sso_saml2_setup(self):
+ result = self.exec_cmd('sso setup saml2',
+ ceph_dashboard_base_url='https://cephdashboard.local',
+ idp_metadata=self.IDP_METADATA)
+ self.validate_onelogin_settings(result, 'https://cephdashboard.local', 'uid', '', '',
+ False)
+
+ def test_sso_enable_saml2(self):
+ with self.assertRaises(CmdException) as ctx:
+ self.exec_cmd('sso enable saml2')
+
+ self.assertEqual(ctx.exception.retcode, -errno.EPERM)
+ self.assertEqual(str(ctx.exception), 'Single Sign-On is not configured: '
+ 'use `ceph dashboard sso setup saml2`')
+
+ self.exec_cmd('sso setup saml2',
+ ceph_dashboard_base_url='https://cephdashboard.local',
+ idp_metadata=self.IDP_METADATA)
+
+ result = self.exec_cmd('sso enable saml2')
+ self.assertEqual(result, 'SSO is "enabled" with "SAML2" protocol.')
+
+ def test_sso_disable(self):
+ result = self.exec_cmd('sso disable')
+ self.assertEqual(result, 'SSO is "disabled".')
+
+ def test_sso_status(self):
+ result = self.exec_cmd('sso status')
+ self.assertEqual(result, 'SSO is "disabled".')
+
+ self.exec_cmd('sso setup saml2',
+ ceph_dashboard_base_url='https://cephdashboard.local',
+ idp_metadata=self.IDP_METADATA)
+
+ result = self.exec_cmd('sso status')
+ self.assertEqual(result, 'SSO is "enabled" with "SAML2" protocol.')
+
+ def test_sso_show_saml2(self):
+ result = self.exec_cmd('sso show saml2')
+ self.assertEqual(result, {
+ 'onelogin_settings': {}
+ })
diff --git a/src/pybind/mgr/dashboard/tests/test_task.py b/src/pybind/mgr/dashboard/tests/test_task.py
new file mode 100644
index 00000000..c10af640
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_task.py
@@ -0,0 +1,433 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import json
+import unittest
+import threading
+import time
+from collections import defaultdict
+from functools import partial
+
+from ..services.exception import serialize_dashboard_exception
+from ..tools import NotificationQueue, TaskManager, TaskExecutor
+
+
+class MyTask(object):
+ class CallbackExecutor(TaskExecutor):
+ def __init__(self, fail, progress):
+ super(MyTask.CallbackExecutor, self).__init__()
+ self.fail = fail
+ self.progress = progress
+
+ def init(self, task):
+ super(MyTask.CallbackExecutor, self).init(task)
+ args = [self.callback]
+ args.extend(self.task.fn_args)
+ self.task.fn_args = args
+
+ def callback(self, result):
+ self.task.set_progress(self.progress)
+ if self.fail:
+ self.finish(None, Exception("Task Unexpected Exception"))
+ else:
+ self.finish(result, None)
+
+ # pylint: disable=too-many-arguments
+ def __init__(self, op_seconds, wait=False, fail=False, progress=50,
+ is_async=False, handle_ex=False):
+ self.op_seconds = op_seconds
+ self.wait = wait
+ self.fail = fail
+ self.progress = progress
+ self.is_async = is_async
+ self.handle_ex = handle_ex
+ self._event = threading.Event()
+
+ def run(self, ns, timeout=None):
+ args = ['dummy arg']
+ kwargs = {'dummy': 'arg'}
+ h_ex = partial(serialize_dashboard_exception,
+ include_http_status=True) if self.handle_ex else None
+ if not self.is_async:
+ task = TaskManager.run(
+ ns, self.metadata(), self.task_op, args, kwargs,
+ exception_handler=h_ex)
+ else:
+ task = TaskManager.run(
+ ns, self.metadata(), self.task_async_op, args, kwargs,
+ executor=MyTask.CallbackExecutor(self.fail, self.progress),
+ exception_handler=h_ex)
+ return task.wait(timeout)
+
+ def task_op(self, *args, **kwargs):
+ time.sleep(self.op_seconds)
+ TaskManager.current_task().set_progress(self.progress)
+ if self.fail:
+ raise Exception("Task Unexpected Exception")
+ if self.wait:
+ self._event.wait()
+ return {'args': list(args), 'kwargs': kwargs}
+
+ def task_async_op(self, callback, *args, **kwargs):
+ if self.fail == "premature":
+ raise Exception("Task Unexpected Exception")
+
+ def _run_bg():
+ time.sleep(self.op_seconds)
+ if self.wait:
+ self._event.wait()
+ callback({'args': list(args), 'kwargs': kwargs})
+
+ worker = threading.Thread(target=_run_bg)
+ worker.start()
+
+ def resume(self):
+ self._event.set()
+
+ def metadata(self):
+ return {
+ 'op_seconds': self.op_seconds,
+ 'wait': self.wait,
+ 'fail': self.fail,
+ 'progress': self.progress,
+ 'is_async': self.is_async,
+ 'handle_ex': self.handle_ex
+ }
+
+
+class TaskTest(unittest.TestCase):
+
+ TASK_FINISHED_MAP = defaultdict(threading.Event)
+
+ @classmethod
+ def _handle_task(cls, task):
+ cls.TASK_FINISHED_MAP[task.name].set()
+
+ @classmethod
+ def wait_for_task(cls, name):
+ cls.TASK_FINISHED_MAP[name].wait()
+
+ @classmethod
+ def setUpClass(cls):
+ NotificationQueue.start_queue()
+ TaskManager.init()
+ NotificationQueue.register(cls._handle_task, 'cd_task_finished',
+ priority=100)
+
+ @classmethod
+ def tearDownClass(cls):
+ NotificationQueue.deregister(cls._handle_task, 'cd_task_finished')
+ NotificationQueue.stop()
+
+ def setUp(self):
+ TaskManager.FINISHED_TASK_SIZE = 10
+ TaskManager.FINISHED_TASK_TTL = 60.0
+
+ def assertTaskResult(self, result):
+ self.assertEqual(result,
+ {'args': ['dummy arg'], 'kwargs': {'dummy': 'arg'}})
+
+ def test_fast_task(self):
+ task1 = MyTask(1)
+ state, result = task1.run('test1/task1')
+ self.assertEqual(state, TaskManager.VALUE_DONE)
+ self.assertTaskResult(result)
+ self.wait_for_task('test1/task1')
+ _, fn_t = TaskManager.list('test1/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].exception)
+ self.assertTaskResult(fn_t[0].ret_value)
+ self.assertEqual(fn_t[0].progress, 100)
+
+ def test_slow_task(self):
+ task1 = MyTask(1)
+ state, result = task1.run('test2/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ self.wait_for_task('test2/task1')
+ _, fn_t = TaskManager.list('test2/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].exception)
+ self.assertTaskResult(fn_t[0].ret_value)
+ self.assertEqual(fn_t[0].progress, 100)
+
+ def test_fast_task_with_failure(self):
+ task1 = MyTask(1, fail=True, progress=40)
+
+ with self.assertRaises(Exception) as ctx:
+ task1.run('test3/task1')
+
+ self.assertEqual(str(ctx.exception), "Task Unexpected Exception")
+ self.wait_for_task('test3/task1')
+ _, fn_t = TaskManager.list('test3/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].ret_value)
+ self.assertEqual(str(fn_t[0].exception), "Task Unexpected Exception")
+ self.assertEqual(fn_t[0].progress, 40)
+
+ def test_slow_task_with_failure(self):
+ task1 = MyTask(1, fail=True, progress=70)
+ state, result = task1.run('test4/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ self.wait_for_task('test4/task1')
+ _, fn_t = TaskManager.list('test4/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].ret_value)
+ self.assertEqual(str(fn_t[0].exception), "Task Unexpected Exception")
+ self.assertEqual(fn_t[0].progress, 70)
+
+ def test_executing_tasks_list(self):
+ task1 = MyTask(0, wait=True, progress=30)
+ task2 = MyTask(0, wait=True, progress=60)
+ state, result = task1.run('test5/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ ex_t, _ = TaskManager.list('test5/*')
+ self.assertEqual(len(ex_t), 1)
+ self.assertEqual(ex_t[0].name, 'test5/task1')
+ self.assertEqual(ex_t[0].progress, 30)
+ state, result = task2.run('test5/task2', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ ex_t, _ = TaskManager.list('test5/*')
+ self.assertEqual(len(ex_t), 2)
+ for task in ex_t:
+ if task.name == 'test5/task1':
+ self.assertEqual(task.progress, 30)
+ elif task.name == 'test5/task2':
+ self.assertEqual(task.progress, 60)
+ task2.resume()
+ self.wait_for_task('test5/task2')
+ ex_t, _ = TaskManager.list('test5/*')
+ self.assertEqual(len(ex_t), 1)
+ self.assertEqual(ex_t[0].name, 'test5/task1')
+ task1.resume()
+ self.wait_for_task('test5/task1')
+ ex_t, _ = TaskManager.list('test5/*')
+ self.assertEqual(len(ex_t), 0)
+
+ def test_task_idempotent(self):
+ task1 = MyTask(0, wait=True)
+ task1_clone = MyTask(0, wait=True)
+ state, result = task1.run('test6/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ ex_t, _ = TaskManager.list('test6/*')
+ self.assertEqual(len(ex_t), 1)
+ self.assertEqual(ex_t[0].name, 'test6/task1')
+ state, result = task1_clone.run('test6/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ ex_t, _ = TaskManager.list('test6/*')
+ self.assertEqual(len(ex_t), 1)
+ self.assertEqual(ex_t[0].name, 'test6/task1')
+ task1.resume()
+ self.wait_for_task('test6/task1')
+ ex_t, fn_t = TaskManager.list('test6/*')
+ self.assertEqual(len(ex_t), 0)
+ self.assertEqual(len(fn_t), 1)
+
+ def test_finished_cleanup(self):
+ TaskManager.FINISHED_TASK_SIZE = 2
+ TaskManager.FINISHED_TASK_TTL = 0.5
+ task1 = MyTask(0)
+ task2 = MyTask(0)
+ state, result = task1.run('test7/task1')
+ self.assertEqual(state, TaskManager.VALUE_DONE)
+ self.assertTaskResult(result)
+ self.wait_for_task('test7/task1')
+ state, result = task2.run('test7/task2')
+ self.assertEqual(state, TaskManager.VALUE_DONE)
+ self.assertTaskResult(result)
+ self.wait_for_task('test7/task2')
+ time.sleep(1)
+ _, fn_t = TaskManager.list('test7/*')
+ self.assertEqual(len(fn_t), 2)
+ for idx, task in enumerate(fn_t):
+ self.assertEqual(task.name,
+ "test7/task{}".format(len(fn_t)-idx))
+ task3 = MyTask(0)
+ state, result = task3.run('test7/task3')
+ self.assertEqual(state, TaskManager.VALUE_DONE)
+ self.assertTaskResult(result)
+ self.wait_for_task('test7/task3')
+ time.sleep(1)
+ _, fn_t = TaskManager.list('test7/*')
+ self.assertEqual(len(fn_t), 3)
+ for idx, task in enumerate(fn_t):
+ self.assertEqual(task.name,
+ "test7/task{}".format(len(fn_t)-idx))
+ _, fn_t = TaskManager.list('test7/*')
+ self.assertEqual(len(fn_t), 2)
+ for idx, task in enumerate(fn_t):
+ self.assertEqual(task.name,
+ "test7/task{}".format(len(fn_t)-idx+1))
+
+ def test_task_serialization_format(self):
+ task1 = MyTask(0, wait=True, progress=20)
+ task2 = MyTask(1)
+ task1.run('test8/task1', 0.5)
+ task2.run('test8/task2', 0.5)
+ self.wait_for_task('test8/task2')
+ ex_t, fn_t = TaskManager.list_serializable('test8/*')
+ self.assertEqual(len(ex_t), 1)
+ self.assertEqual(len(fn_t), 1)
+
+ try:
+ json.dumps(ex_t)
+ except ValueError as ex:
+ self.fail("Failed to serialize executing tasks: {}".format(str(ex)))
+
+ try:
+ json.dumps(fn_t)
+ except ValueError as ex:
+ self.fail("Failed to serialize finished tasks: {}".format(str(ex)))
+
+ # validate executing tasks attributes
+ self.assertEqual(len(ex_t[0].keys()), 4)
+ self.assertEqual(ex_t[0]['name'], 'test8/task1')
+ self.assertEqual(ex_t[0]['metadata'], task1.metadata())
+ self.assertIsNotNone(ex_t[0]['begin_time'])
+ self.assertEqual(ex_t[0]['progress'], 20)
+ # validate finished tasks attributes
+ self.assertEqual(len(fn_t[0].keys()), 9)
+ self.assertEqual(fn_t[0]['name'], 'test8/task2')
+ self.assertEqual(fn_t[0]['metadata'], task2.metadata())
+ self.assertIsNotNone(fn_t[0]['begin_time'])
+ self.assertIsNotNone(fn_t[0]['end_time'])
+ self.assertGreaterEqual(fn_t[0]['duration'], 1.0)
+ self.assertEqual(fn_t[0]['progress'], 100)
+ self.assertTrue(fn_t[0]['success'])
+ self.assertTaskResult(fn_t[0]['ret_value'])
+ self.assertIsNone(fn_t[0]['exception'])
+ task1.resume()
+ self.wait_for_task('test8/task1')
+
+ def test_fast_async_task(self):
+ task1 = MyTask(1, is_async=True)
+ state, result = task1.run('test9/task1')
+ self.assertEqual(state, TaskManager.VALUE_DONE)
+ self.assertTaskResult(result)
+ self.wait_for_task('test9/task1')
+ _, fn_t = TaskManager.list('test9/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].exception)
+ self.assertTaskResult(fn_t[0].ret_value)
+ self.assertEqual(fn_t[0].progress, 100)
+
+ def test_slow_async_task(self):
+ task1 = MyTask(1, is_async=True)
+ state, result = task1.run('test10/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ self.wait_for_task('test10/task1')
+ _, fn_t = TaskManager.list('test10/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].exception)
+ self.assertTaskResult(fn_t[0].ret_value)
+ self.assertEqual(fn_t[0].progress, 100)
+
+ def test_fast_async_task_with_failure(self):
+ task1 = MyTask(1, fail=True, progress=40, is_async=True)
+
+ with self.assertRaises(Exception) as ctx:
+ task1.run('test11/task1')
+
+ self.assertEqual(str(ctx.exception), "Task Unexpected Exception")
+ self.wait_for_task('test11/task1')
+ _, fn_t = TaskManager.list('test11/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].ret_value)
+ self.assertEqual(str(fn_t[0].exception), "Task Unexpected Exception")
+ self.assertEqual(fn_t[0].progress, 40)
+
+ def test_slow_async_task_with_failure(self):
+ task1 = MyTask(1, fail=True, progress=70, is_async=True)
+ state, result = task1.run('test12/task1', 0.5)
+ self.assertEqual(state, TaskManager.VALUE_EXECUTING)
+ self.assertIsNone(result)
+ self.wait_for_task('test12/task1')
+ _, fn_t = TaskManager.list('test12/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].ret_value)
+ self.assertEqual(str(fn_t[0].exception), "Task Unexpected Exception")
+ self.assertEqual(fn_t[0].progress, 70)
+
+ def test_fast_async_task_with_premature_failure(self):
+ task1 = MyTask(1, fail="premature", progress=40, is_async=True)
+
+ with self.assertRaises(Exception) as ctx:
+ task1.run('test13/task1')
+
+ self.assertEqual(str(ctx.exception), "Task Unexpected Exception")
+ self.wait_for_task('test13/task1')
+ _, fn_t = TaskManager.list('test13/*')
+ self.assertEqual(len(fn_t), 1)
+ self.assertIsNone(fn_t[0].ret_value)
+ self.assertEqual(str(fn_t[0].exception), "Task Unexpected Exception")
+
+ def test_task_serialization_format_on_failure(self):
+ task1 = MyTask(1, fail=True)
+ task1.run('test14/task1', 0.5)
+ self.wait_for_task('test14/task1')
+ ex_t, fn_t = TaskManager.list_serializable('test14/*')
+ self.assertEqual(len(ex_t), 0)
+ self.assertEqual(len(fn_t), 1)
+ # validate finished tasks attributes
+
+ try:
+ json.dumps(fn_t)
+ except TypeError as ex:
+ self.fail("Failed to serialize finished tasks: {}".format(str(ex)))
+
+ self.assertEqual(len(fn_t[0].keys()), 9)
+ self.assertEqual(fn_t[0]['name'], 'test14/task1')
+ self.assertEqual(fn_t[0]['metadata'], task1.metadata())
+ self.assertIsNotNone(fn_t[0]['begin_time'])
+ self.assertIsNotNone(fn_t[0]['end_time'])
+ self.assertGreaterEqual(fn_t[0]['duration'], 1.0)
+ self.assertEqual(fn_t[0]['progress'], 50)
+ self.assertFalse(fn_t[0]['success'])
+ self.assertIsNotNone(fn_t[0]['exception'])
+ self.assertEqual(fn_t[0]['exception'],
+ {"detail": "Task Unexpected Exception"})
+
+ def test_task_serialization_format_on_failure_with_handler(self):
+ task1 = MyTask(1, fail=True, handle_ex=True)
+ task1.run('test15/task1', 0.5)
+ self.wait_for_task('test15/task1')
+ ex_t, fn_t = TaskManager.list_serializable('test15/*')
+ self.assertEqual(len(ex_t), 0)
+ self.assertEqual(len(fn_t), 1)
+ # validate finished tasks attributes
+
+ try:
+ json.dumps(fn_t)
+ except TypeError as ex:
+ self.fail("Failed to serialize finished tasks: {}".format(str(ex)))
+
+ self.assertEqual(len(fn_t[0].keys()), 9)
+ self.assertEqual(fn_t[0]['name'], 'test15/task1')
+ self.assertEqual(fn_t[0]['metadata'], task1.metadata())
+ self.assertIsNotNone(fn_t[0]['begin_time'])
+ self.assertIsNotNone(fn_t[0]['end_time'])
+ self.assertGreaterEqual(fn_t[0]['duration'], 1.0)
+ self.assertEqual(fn_t[0]['progress'], 50)
+ self.assertFalse(fn_t[0]['success'])
+ self.assertIsNotNone(fn_t[0]['exception'])
+ self.assertEqual(fn_t[0]['exception'], {
+ 'component': None,
+ 'detail': 'Task Unexpected Exception',
+ 'status': 500,
+ 'task': {
+ 'metadata': {
+ 'fail': True,
+ 'handle_ex': True,
+ 'is_async': False,
+ 'op_seconds': 1,
+ 'progress': 50,
+ 'wait': False},
+ 'name': 'test15/task1'
+ }
+ })
diff --git a/src/pybind/mgr/dashboard/tests/test_tools.py b/src/pybind/mgr/dashboard/tests/test_tools.py
new file mode 100644
index 00000000..1c2c2e5b
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tests/test_tools.py
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import unittest
+
+import cherrypy
+from cherrypy.lib.sessions import RamSession
+from mock import patch
+
+from . import ControllerTestCase
+from ..services.exception import handle_rados_error
+from ..controllers import RESTController, ApiController, Controller, \
+ BaseController, Proxy
+from ..tools import is_valid_ipv6_address, dict_contains_path, \
+ RequestLoggingTool
+
+
+# pylint: disable=W0613
+@Controller('/foo', secure=False)
+class FooResource(RESTController):
+ elems = []
+
+ def list(self):
+ return FooResource.elems
+
+ def create(self, a):
+ FooResource.elems.append({'a': a})
+ return {'a': a}
+
+ def get(self, key):
+ return {'detail': (key, [])}
+
+ def delete(self, key):
+ del FooResource.elems[int(key)]
+
+ def bulk_delete(self):
+ FooResource.elems = []
+
+ def set(self, key, newdata):
+ FooResource.elems[int(key)] = {'newdata': newdata}
+ return dict(key=key, newdata=newdata)
+
+
+@Controller('/foo/:key/:method', secure=False)
+class FooResourceDetail(RESTController):
+ def list(self, key, method):
+ return {'detail': (key, [method])}
+
+
+@ApiController('/rgw/proxy', secure=False)
+class GenerateControllerRoutesController(BaseController):
+ @Proxy()
+ def __call__(self, path, **params):
+ pass
+
+
+@ApiController('/fooargs', secure=False)
+class FooArgs(RESTController):
+ def set(self, code, name=None, opt1=None, opt2=None):
+ return {'code': code, 'name': name, 'opt1': opt1, 'opt2': opt2}
+
+ @handle_rados_error('foo')
+ def create(self, my_arg_name):
+ return my_arg_name
+
+ def list(self):
+ raise cherrypy.NotFound()
+
+
+# pylint: disable=blacklisted-name
+class Root(object):
+ foo = FooResource()
+ fooargs = FooArgs()
+
+
+class RESTControllerTest(ControllerTestCase):
+
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers(
+ [FooResource, FooResourceDetail, FooArgs, GenerateControllerRoutesController])
+
+ def test_empty(self):
+ self._delete("/foo")
+ self.assertStatus(204)
+ self._get("/foo")
+ self.assertStatus('200 OK')
+ self.assertHeader('Content-Type', 'application/json')
+ self.assertBody('[]')
+
+ def test_fill(self):
+ sess_mock = RamSession()
+ with patch('cherrypy.session', sess_mock, create=True):
+ data = {'a': 'b'}
+ for _ in range(5):
+ self._post("/foo", data)
+ self.assertJsonBody(data)
+ self.assertStatus(201)
+ self.assertHeader('Content-Type', 'application/json')
+
+ self._get("/foo")
+ self.assertStatus('200 OK')
+ self.assertHeader('Content-Type', 'application/json')
+ self.assertJsonBody([data] * 5)
+
+ self._put('/foo/0', {'newdata': 'newdata'})
+ self.assertStatus('200 OK')
+ self.assertHeader('Content-Type', 'application/json')
+ self.assertJsonBody({'newdata': 'newdata', 'key': '0'})
+
+ def test_not_implemented(self):
+ self._put("/foo")
+ self.assertStatus(404)
+ body = self.jsonBody()
+ self.assertIsInstance(body, dict)
+ assert body['detail'] == "The path '/foo' was not found."
+ assert '404' in body['status']
+
+ def test_args_from_json(self):
+ self._put("/api/fooargs/hello", {'name': 'world'})
+ self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': None})
+
+ self._put("/api/fooargs/hello", {'name': 'world', 'opt1': 'opt1'})
+ self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': 'opt1', 'opt2': None})
+
+ self._put("/api/fooargs/hello", {'name': 'world', 'opt2': 'opt2'})
+ self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': 'opt2'})
+
+ def test_detail_route(self):
+ self._get('/foo/default')
+ self.assertJsonBody({'detail': ['default', []]})
+
+ self._get('/foo/default/default')
+ self.assertJsonBody({'detail': ['default', ['default']]})
+
+ self._get('/foo/1/detail')
+ self.assertJsonBody({'detail': ['1', ['detail']]})
+
+ self._post('/foo/1/detail', 'post-data')
+ self.assertStatus(404)
+
+ def test_generate_controller_routes(self):
+ # We just need to add this controller in setup_server():
+ # noinspection PyStatementEffect
+ # pylint: disable=pointless-statement
+ GenerateControllerRoutesController
+
+
+class RequestLoggingToolTest(ControllerTestCase):
+
+ def __init__(self, *args, **kwargs):
+ cherrypy.tools.request_logging = RequestLoggingTool()
+ cherrypy.config.update({'tools.request_logging.on': True})
+ super(RequestLoggingToolTest, self).__init__(*args, **kwargs)
+
+ @classmethod
+ def setup_server(cls):
+ cls.setup_controllers([FooResource])
+
+ def test_is_logged(self):
+ with patch('logging.Logger.debug') as mock_logger_debug:
+ self._put('/foo/0', {'newdata': 'xyz'})
+ self.assertStatus(200)
+ call_args_list = mock_logger_debug.call_args_list
+ _, host, _, method, user, path = call_args_list[0][0]
+ self.assertEqual(host, '127.0.0.1')
+ self.assertEqual(method, 'PUT')
+ self.assertIsNone(user)
+ self.assertEqual(path, '/foo/0')
+
+
+class TestFunctions(unittest.TestCase):
+
+ def test_is_valid_ipv6_address(self):
+ self.assertTrue(is_valid_ipv6_address('::'))
+ self.assertTrue(is_valid_ipv6_address('::1'))
+ self.assertFalse(is_valid_ipv6_address('127.0.0.1'))
+ self.assertFalse(is_valid_ipv6_address('localhost'))
+ self.assertTrue(is_valid_ipv6_address('1200:0000:AB00:1234:0000:2552:7777:1313'))
+ self.assertFalse(is_valid_ipv6_address('1200::AB00:1234::2552:7777:1313'))
+
+ def test_dict_contains_path(self):
+ x = {'a': {'b': {'c': 'foo'}}}
+ self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
+ self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
+ self.assertTrue(dict_contains_path(x, ['a']))
+ self.assertFalse(dict_contains_path(x, ['a', 'c']))
+ self.assertTrue(dict_contains_path(x, []))
diff --git a/src/pybind/mgr/dashboard/tools.py b/src/pybind/mgr/dashboard/tools.py
new file mode 100644
index 00000000..82a82194
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tools.py
@@ -0,0 +1,932 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+import sys
+import inspect
+import json
+import functools
+
+import collections
+from datetime import datetime, timedelta
+from distutils.util import strtobool
+import fnmatch
+import time
+import threading
+import socket
+import six
+from six.moves import urllib
+import cherrypy
+
+try:
+ from urlparse import urljoin
+except ImportError:
+ from urllib.parse import urljoin
+
+from . import logger, mgr
+from .exceptions import ViewCacheNoDataException
+from .settings import Settings
+from .services.auth import JwtManager
+
+
+def ensure_str(s, encoding='utf-8', errors='strict'):
+ """Ported from six."""
+ if not isinstance(s, (six.text_type, six.binary_type)):
+ raise TypeError("not expecting type '%s'" % type(s))
+ if six.PY2 and isinstance(s, six.text_type):
+ s = s.encode(encoding, errors)
+ elif six.PY3 and isinstance(s, six.binary_type):
+ s = s.decode(encoding, errors)
+ return s
+
+
+class RequestLoggingTool(cherrypy.Tool):
+ def __init__(self):
+ cherrypy.Tool.__init__(self, 'before_handler', self.request_begin,
+ priority=10)
+
+ def _setup(self):
+ cherrypy.Tool._setup(self)
+ cherrypy.request.hooks.attach('on_end_request', self.request_end,
+ priority=5)
+ cherrypy.request.hooks.attach('after_error_response', self.request_error,
+ priority=5)
+
+ def request_begin(self):
+ req = cherrypy.request
+ user = JwtManager.get_username()
+ if user is not None:
+ # PY2: Encode user to str to prevent further implicit decoding
+ user = ensure_str(user)
+ # Log the request.
+ logger.debug('[%s:%s] [%s] [%s] %s', req.remote.ip, req.remote.port,
+ req.method, user, req.path_info)
+ # Audit the request.
+ if Settings.AUDIT_API_ENABLED and req.method not in ['GET']:
+ url = build_url(req.remote.ip, scheme=req.scheme,
+ port=req.remote.port)
+ msg = '[DASHBOARD] from=\'{}\' path=\'{}\' method=\'{}\' ' \
+ 'user=\'{}\''.format(url, req.path_info, req.method, user)
+ if Settings.AUDIT_API_LOG_PAYLOAD:
+ params = dict(req.params or {}, **get_request_body_params(req))
+ # Hide sensitive data like passwords, secret keys, ...
+ # Extend the list of patterns to search for if necessary.
+ # Currently parameters like this are processed:
+ # - secret_key
+ # - user_password
+ # - new_passwd_to_login
+ keys = []
+ for key in ['password', 'passwd', 'secret']:
+ keys.extend([x for x in params.keys() if key in x])
+ for key in keys:
+ params[key] = '***'
+ msg = '{} params=\'{}\''.format(msg, json.dumps(params))
+ mgr.cluster_log('audit', mgr.CLUSTER_LOG_PRIO_INFO, msg)
+
+ def request_error(self):
+ self._request_log(logger.error)
+ logger.error(cherrypy.response.body)
+
+ def request_end(self):
+ status = cherrypy.response.status[:3]
+ if status in ["401"]:
+ # log unauthorized accesses
+ self._request_log(logger.warning)
+ else:
+ self._request_log(logger.info)
+
+ def _format_bytes(self, num):
+ units = ['B', 'K', 'M', 'G']
+
+ if isinstance(num, str):
+ try:
+ num = int(num)
+ except ValueError:
+ return "n/a"
+
+ format_str = "{:.0f}{}"
+ for i, unit in enumerate(units):
+ div = 2**(10*i)
+ if num < 2**(10*(i+1)):
+ if num % div == 0:
+ format_str = "{}{}"
+ else:
+ div = float(div)
+ format_str = "{:.1f}{}"
+ return format_str.format(num/div, unit[0])
+
+ # content-length bigger than 1T!! return value in bytes
+ return "{}B".format(num)
+
+ def _request_log(self, logger_fn):
+ req = cherrypy.request
+ res = cherrypy.response
+ lat = time.time() - res.time
+ user = JwtManager.get_username()
+ status = res.status[:3] if isinstance(res.status, str) else res.status
+ if 'Content-Length' in res.headers:
+ length = self._format_bytes(res.headers['Content-Length'])
+ else:
+ length = self._format_bytes(0)
+ if user:
+ logger_fn("[%s:%s] [%s] [%s] [%s] [%s] [%s] %s", req.remote.ip,
+ req.remote.port, req.method, status,
+ "{0:.3f}s".format(lat), ensure_str(user), length, req.path_info)
+ else:
+ logger_fn("[%s:%s] [%s] [%s] [%s] [%s] %s", req.remote.ip,
+ req.remote.port, req.method, status,
+ "{0:.3f}s".format(lat), length, req.path_info)
+
+
+# pylint: disable=too-many-instance-attributes
+class ViewCache(object):
+ VALUE_OK = 0
+ VALUE_STALE = 1
+ VALUE_NONE = 2
+
+ class GetterThread(threading.Thread):
+ def __init__(self, view, fn, args, kwargs):
+ super(ViewCache.GetterThread, self).__init__()
+ self._view = view
+ self.event = threading.Event()
+ self.fn = fn
+ self.args = args
+ self.kwargs = kwargs
+
+ # pylint: disable=broad-except
+ def run(self):
+ t0 = 0.0
+ t1 = 0.0
+ try:
+ t0 = time.time()
+ logger.debug("VC: starting execution of %s", self.fn)
+ val = self.fn(*self.args, **self.kwargs)
+ t1 = time.time()
+ except Exception as ex:
+ with self._view.lock:
+ logger.exception("Error while calling fn=%s ex=%s", self.fn,
+ str(ex))
+ self._view.value = None
+ self._view.value_when = None
+ self._view.getter_thread = None
+ self._view.exception = ex
+ else:
+ with self._view.lock:
+ self._view.latency = t1 - t0
+ self._view.value = val
+ self._view.value_when = datetime.now()
+ self._view.getter_thread = None
+ self._view.exception = None
+
+ logger.debug("VC: execution of %s finished in: %s", self.fn,
+ t1 - t0)
+ self.event.set()
+
+ class RemoteViewCache(object):
+ # Return stale data if
+ STALE_PERIOD = 1.0
+
+ def __init__(self, timeout):
+ self.getter_thread = None
+ # Consider data within 1s old to be sufficiently fresh
+ self.timeout = timeout
+ self.event = threading.Event()
+ self.value_when = None
+ self.value = None
+ self.latency = 0
+ self.exception = None
+ self.lock = threading.Lock()
+
+ def reset(self):
+ with self.lock:
+ self.value_when = None
+ self.value = None
+
+ def run(self, fn, args, kwargs):
+ """
+ If data less than `stale_period` old is available, return it
+ immediately.
+ If an attempt to fetch data does not complete within `timeout`, then
+ return the most recent data available, with a status to indicate that
+ it is stale.
+
+ Initialization does not count towards the timeout, so the first call
+ on one of these objects during the process lifetime may be slower
+ than subsequent calls.
+
+ :return: 2-tuple of value status code, value
+ """
+ with self.lock:
+ now = datetime.now()
+ if self.value_when and now - self.value_when < timedelta(
+ seconds=self.STALE_PERIOD):
+ return ViewCache.VALUE_OK, self.value
+
+ if self.getter_thread is None:
+ self.getter_thread = ViewCache.GetterThread(self, fn, args,
+ kwargs)
+ self.getter_thread.start()
+ else:
+ logger.debug("VC: getter_thread still alive for: %s", fn)
+
+ ev = self.getter_thread.event
+
+ success = ev.wait(timeout=self.timeout)
+
+ with self.lock:
+ if success:
+ # We fetched the data within the timeout
+ if self.exception:
+ # execution raised an exception
+ # pylint: disable=raising-bad-type
+ raise self.exception
+ return ViewCache.VALUE_OK, self.value
+ if self.value_when is not None:
+ # We have some data, but it doesn't meet freshness requirements
+ return ViewCache.VALUE_STALE, self.value
+ # We have no data, not even stale data
+ raise ViewCacheNoDataException()
+
+ def __init__(self, timeout=5):
+ self.timeout = timeout
+ self.cache_by_args = {}
+
+ def __call__(self, fn):
+ def wrapper(*args, **kwargs):
+ rvc = self.cache_by_args.get(args, None)
+ if not rvc:
+ rvc = ViewCache.RemoteViewCache(self.timeout)
+ self.cache_by_args[args] = rvc
+ return rvc.run(fn, args, kwargs)
+ wrapper.reset = self.reset
+ return wrapper
+
+ def reset(self):
+ for _, rvc in self.cache_by_args.items():
+ rvc.reset()
+
+
+class NotificationQueue(threading.Thread):
+ _ALL_TYPES_ = '__ALL__'
+ _listeners = collections.defaultdict(set)
+ _lock = threading.Lock()
+ _cond = threading.Condition()
+ _queue = collections.deque()
+ _running = False
+ _instance = None
+
+ def __init__(self):
+ super(NotificationQueue, self).__init__()
+
+ @classmethod
+ def start_queue(cls):
+ with cls._lock:
+ if cls._instance:
+ # the queue thread is already running
+ return
+ cls._running = True
+ cls._instance = NotificationQueue()
+ logger.debug("starting notification queue")
+ cls._instance.start()
+
+ @classmethod
+ def stop(cls):
+ with cls._lock:
+ if not cls._instance:
+ # the queue thread was not started
+ return
+ instance = cls._instance
+ cls._instance = None
+ cls._running = False
+ with cls._cond:
+ cls._cond.notify()
+ logger.debug("waiting for notification queue to finish")
+ instance.join()
+ logger.debug("notification queue stopped")
+
+ @classmethod
+ def _registered_handler(cls, func, n_types):
+ for _, reg_func in cls._listeners[n_types]:
+ if reg_func == func:
+ return True
+ return False
+
+ @classmethod
+ def register(cls, func, n_types=None, priority=1):
+ """Registers function to listen for notifications
+
+ If the second parameter `n_types` is omitted, the function in `func`
+ parameter will be called for any type of notifications.
+
+ Args:
+ func (function): python function ex: def foo(val)
+ n_types (str|list): the single type to listen, or a list of types
+ priority (int): the priority level (1=max, +inf=min)
+ """
+ with cls._lock:
+ if not n_types:
+ n_types = [cls._ALL_TYPES_]
+ elif isinstance(n_types, str):
+ n_types = [n_types]
+ elif not isinstance(n_types, list):
+ raise Exception("n_types param is neither a string nor a list")
+ for ev_type in n_types:
+ if not cls._registered_handler(func, ev_type):
+ cls._listeners[ev_type].add((priority, func))
+ logger.debug("NQ: function %s was registered for events of"
+ " type %s", func, ev_type)
+
+ @classmethod
+ def deregister(cls, func, n_types=None):
+ """Removes the listener function from this notification queue
+
+ If the second parameter `n_types` is omitted, the function is removed
+ from all event types, otherwise the function is removed only for the
+ specified event types.
+
+ Args:
+ func (function): python function
+ n_types (str|list): the single event type, or a list of event types
+ """
+ with cls._lock:
+ if not n_types:
+ n_types = list(cls._listeners.keys())
+ elif isinstance(n_types, str):
+ n_types = [n_types]
+ elif not isinstance(n_types, list):
+ raise Exception("n_types param is neither a string nor a list")
+ for ev_type in n_types:
+ listeners = cls._listeners[ev_type]
+ toRemove = None
+ for pr, fn in listeners:
+ if fn == func:
+ toRemove = (pr, fn)
+ break
+ if toRemove:
+ listeners.discard(toRemove)
+ logger.debug("NQ: function %s was deregistered for events "
+ "of type %s", func, ev_type)
+
+ @classmethod
+ def new_notification(cls, notify_type, notify_value):
+ with cls._cond:
+ cls._queue.append((notify_type, notify_value))
+ cls._cond.notify()
+
+ @classmethod
+ def _notify_listeners(cls, events):
+ for ev in events:
+ notify_type, notify_value = ev
+ with cls._lock:
+ listeners = list(cls._listeners[notify_type])
+ listeners.extend(cls._listeners[cls._ALL_TYPES_])
+ listeners.sort(key=lambda lis: lis[0])
+ for listener in listeners:
+ listener[1](notify_value)
+
+ def run(self):
+ logger.debug("notification queue started")
+ while self._running:
+ private_buffer = []
+ logger.debug("NQ: processing queue: %s", len(self._queue))
+ try:
+ while True:
+ private_buffer.append(self._queue.popleft())
+ except IndexError:
+ pass
+ self._notify_listeners(private_buffer)
+ with self._cond:
+ while self._running and not self._queue:
+ self._cond.wait()
+ # flush remaining events
+ logger.debug("NQ: flush remaining events: %s", len(self._queue))
+ self._notify_listeners(self._queue)
+ self._queue.clear()
+ logger.debug("notification queue finished")
+
+
+# pylint: disable=too-many-arguments, protected-access
+class TaskManager(object):
+ FINISHED_TASK_SIZE = 10
+ FINISHED_TASK_TTL = 60.0
+
+ VALUE_DONE = "done"
+ VALUE_EXECUTING = "executing"
+
+ _executing_tasks = set()
+ _finished_tasks = []
+ _lock = threading.Lock()
+
+ _task_local_data = threading.local()
+
+ @classmethod
+ def init(cls):
+ NotificationQueue.register(cls._handle_finished_task, 'cd_task_finished')
+
+ @classmethod
+ def _handle_finished_task(cls, task):
+ logger.info("TM: finished %s", task)
+ with cls._lock:
+ cls._executing_tasks.remove(task)
+ cls._finished_tasks.append(task)
+
+ @classmethod
+ def run(cls, name, metadata, fn, args=None, kwargs=None, executor=None,
+ exception_handler=None):
+ if not args:
+ args = []
+ if not kwargs:
+ kwargs = {}
+ if not executor:
+ executor = ThreadedExecutor()
+ task = Task(name, metadata, fn, args, kwargs, executor,
+ exception_handler)
+ with cls._lock:
+ if task in cls._executing_tasks:
+ logger.debug("TM: task already executing: %s", task)
+ for t in cls._executing_tasks:
+ if t == task:
+ return t
+ logger.debug("TM: created %s", task)
+ cls._executing_tasks.add(task)
+ logger.info("TM: running %s", task)
+ task._run()
+ return task
+
+ @classmethod
+ def current_task(cls):
+ """
+ Returns the current task object.
+ This method should only be called from a threaded task operation code.
+ """
+ return cls._task_local_data.task
+
+ @classmethod
+ def _cleanup_old_tasks(cls, task_list):
+ """
+ The cleanup rule is: maintain the FINISHED_TASK_SIZE more recent
+ finished tasks, and the rest is maintained up to the FINISHED_TASK_TTL
+ value.
+ """
+ now = datetime.now()
+ for idx, t in enumerate(task_list):
+ if idx < cls.FINISHED_TASK_SIZE:
+ continue
+ if now - datetime.fromtimestamp(t[1].end_time) > \
+ timedelta(seconds=cls.FINISHED_TASK_TTL):
+ del cls._finished_tasks[t[0]]
+
+ @classmethod
+ def list(cls, name_glob=None):
+ executing_tasks = []
+ finished_tasks = []
+ with cls._lock:
+ for task in cls._executing_tasks:
+ if not name_glob or fnmatch.fnmatch(task.name, name_glob):
+ executing_tasks.append(task)
+ for idx, task in enumerate(cls._finished_tasks):
+ if not name_glob or fnmatch.fnmatch(task.name, name_glob):
+ finished_tasks.append((idx, task))
+ finished_tasks.sort(key=lambda t: t[1].end_time, reverse=True)
+ cls._cleanup_old_tasks(finished_tasks)
+ executing_tasks.sort(key=lambda t: t.begin_time, reverse=True)
+ return executing_tasks, [t[1] for t in finished_tasks]
+
+ @classmethod
+ def list_serializable(cls, ns_glob=None):
+ ex_t, fn_t = cls.list(ns_glob)
+ return [{
+ 'name': t.name,
+ 'metadata': t.metadata,
+ 'begin_time': "{}Z".format(datetime.fromtimestamp(t.begin_time).isoformat()),
+ 'progress': t.progress
+ } for t in ex_t if t.begin_time], [{
+ 'name': t.name,
+ 'metadata': t.metadata,
+ 'begin_time': "{}Z".format(datetime.fromtimestamp(t.begin_time).isoformat()),
+ 'end_time': "{}Z".format(datetime.fromtimestamp(t.end_time).isoformat()),
+ 'duration': t.duration,
+ 'progress': t.progress,
+ 'success': not t.exception,
+ 'ret_value': t.ret_value if not t.exception else None,
+ 'exception': t.ret_value if t.exception and t.ret_value else (
+ {'detail': str(t.exception)} if t.exception else None)
+ } for t in fn_t]
+
+
+# pylint: disable=protected-access
+class TaskExecutor(object):
+ def __init__(self):
+ self.task = None
+
+ def init(self, task):
+ self.task = task
+
+ # pylint: disable=broad-except
+ def start(self):
+ logger.debug("EX: executing task %s", self.task)
+ try:
+ self.task.fn(*self.task.fn_args, **self.task.fn_kwargs)
+ except Exception as ex:
+ logger.exception("Error while calling %s", self.task)
+ self.finish(None, ex)
+
+ def finish(self, ret_value, exception):
+ if not exception:
+ logger.debug("EX: successfully finished task: %s", self.task)
+ else:
+ logger.debug("EX: task finished with exception: %s", self.task)
+ self.task._complete(ret_value, exception)
+
+
+# pylint: disable=protected-access
+class ThreadedExecutor(TaskExecutor):
+ def __init__(self):
+ super(ThreadedExecutor, self).__init__()
+ self._thread = threading.Thread(target=self._run)
+
+ def start(self):
+ self._thread.start()
+
+ # pylint: disable=broad-except
+ def _run(self):
+ TaskManager._task_local_data.task = self.task
+ try:
+ logger.debug("TEX: executing task %s", self.task)
+ val = self.task.fn(*self.task.fn_args, **self.task.fn_kwargs)
+ except Exception as ex:
+ logger.exception("Error while calling %s", self.task)
+ self.finish(None, ex)
+ else:
+ self.finish(val, None)
+
+
+class Task(object):
+ def __init__(self, name, metadata, fn, args, kwargs, executor,
+ exception_handler=None):
+ self.name = name
+ self.metadata = metadata
+ self.fn = fn
+ self.fn_args = args
+ self.fn_kwargs = kwargs
+ self.executor = executor
+ self.ex_handler = exception_handler
+ self.running = False
+ self.event = threading.Event()
+ self.progress = None
+ self.ret_value = None
+ self.begin_time = None
+ self.end_time = None
+ self.duration = 0
+ self.exception = None
+ self.lock = threading.Lock()
+
+ def __hash__(self):
+ return hash((self.name, tuple(sorted(self.metadata.items()))))
+
+ def __eq__(self, other):
+ return self.name == other.name and self.metadata == other.metadata
+
+ def __str__(self):
+ return "Task(ns={}, md={})" \
+ .format(self.name, self.metadata)
+
+ def __repr__(self):
+ return str(self)
+
+ def _run(self):
+ NotificationQueue.register(self._handle_task_finished, 'cd_task_finished', 100)
+ with self.lock:
+ assert not self.running
+ self.executor.init(self)
+ self.set_progress(0, in_lock=True)
+ self.begin_time = time.time()
+ self.running = True
+ self.executor.start()
+
+ def _complete(self, ret_value, exception=None):
+ now = time.time()
+ if exception and self.ex_handler:
+ # pylint: disable=broad-except
+ try:
+ ret_value = self.ex_handler(exception, task=self)
+ except Exception as ex:
+ exception = ex
+ with self.lock:
+ assert self.running, "_complete cannot be called before _run"
+ self.end_time = now
+ self.ret_value = ret_value
+ self.exception = exception
+ self.duration = now - self.begin_time
+ if not self.exception:
+ self.set_progress(100, True)
+ NotificationQueue.new_notification('cd_task_finished', self)
+ logger.debug("TK: execution of %s finished in: %s s", self,
+ self.duration)
+
+ def _handle_task_finished(self, task):
+ if self == task:
+ NotificationQueue.deregister(self._handle_task_finished)
+ self.event.set()
+
+ def wait(self, timeout=None):
+ with self.lock:
+ assert self.running, "wait cannot be called before _run"
+ ev = self.event
+
+ success = ev.wait(timeout=timeout)
+ with self.lock:
+ if success:
+ # the action executed within the timeout
+ if self.exception:
+ # pylint: disable=raising-bad-type
+ # execution raised an exception
+ raise self.exception
+ return TaskManager.VALUE_DONE, self.ret_value
+ # the action is still executing
+ return TaskManager.VALUE_EXECUTING, None
+
+ def inc_progress(self, delta, in_lock=False):
+ if not isinstance(delta, int) or delta < 0:
+ raise Exception("Progress delta value must be a positive integer")
+ if not in_lock:
+ self.lock.acquire()
+ prog = self.progress + delta
+ self.progress = prog if prog <= 100 else 100
+ if not in_lock:
+ self.lock.release()
+
+ def set_progress(self, percentage, in_lock=False):
+ if not isinstance(percentage, int) or percentage < 0 or percentage > 100:
+ raise Exception("Progress value must be in percentage "
+ "(0 <= percentage <= 100)")
+ if not in_lock:
+ self.lock.acquire()
+ self.progress = percentage
+ if not in_lock:
+ self.lock.release()
+
+
+def is_valid_ip_address(addr):
+ """
+ Validate the given IPv4 or IPv6 address.
+
+ >>> is_valid_ip_address('2001:0db8::1234')
+ True
+
+ >>> is_valid_ip_address('192.168.121.1')
+ True
+
+ >>> is_valid_ip_address('1:::1')
+ False
+
+ >>> is_valid_ip_address('8.1.0')
+ False
+
+ >>> is_valid_ip_address('260.1.0.1')
+ False
+
+ :param addr:
+ :type addr: str
+ :return: Returns ``True`` if the IP address is valid,
+ otherwise ``False``.
+ :rtype: bool
+ """
+ return is_valid_ipv4_address(addr) or is_valid_ipv6_address(addr)
+
+
+def is_valid_ipv4_address(addr):
+ """
+ Validate the given IPv4 address.
+
+ >>> is_valid_ipv4_address('0.0.0.0')
+ True
+
+ >>> is_valid_ipv4_address('192.168.121.1')
+ True
+
+ >>> is_valid_ipv4_address('a.b.c.d')
+ False
+
+ >>> is_valid_ipv4_address('172.1.0.a')
+ False
+
+ >>> is_valid_ipv4_address('2001:0db8::1234')
+ False
+
+ >>> is_valid_ipv4_address(None)
+ False
+
+ >>> is_valid_ipv4_address(123456)
+ False
+
+ :param addr:
+ :type addr: str
+ :return: Returns ``True`` if the IPv4 address is valid,
+ otherwise ``False``.
+ :rtype: bool
+ """
+ try:
+ socket.inet_pton(socket.AF_INET, addr)
+ return True
+ except (socket.error, TypeError):
+ return False
+
+
+def is_valid_ipv6_address(addr):
+ """
+ Validate the given IPv6 address.
+
+ >>> is_valid_ipv6_address('2001:0db8::1234')
+ True
+
+ >>> is_valid_ipv6_address('fe80::bc6c:66b0:5af8:f44')
+ True
+
+ >>> is_valid_ipv6_address('192.168.121.1')
+ False
+
+ >>> is_valid_ipv6_address('a:x::1')
+ False
+
+ >>> is_valid_ipv6_address('1200:0000:AB00:1234:O000:2552:7777:1313')
+ False
+
+ >>> is_valid_ipv6_address(None)
+ False
+
+ >>> is_valid_ipv6_address(123456)
+ False
+
+ :param addr:
+ :type addr: str
+ :return: Returns ``True`` if the IPv6 address is valid,
+ otherwise ``False``.
+ :rtype: bool
+ """
+ try:
+ socket.inet_pton(socket.AF_INET6, addr)
+ return True
+ except (socket.error, TypeError):
+ return False
+
+
+def build_url(host, scheme=None, port=None):
+ """
+ Build a valid URL. IPv6 addresses specified in host will be enclosed in brackets
+ automatically.
+
+ >>> build_url('example.com', 'https', 443)
+ 'https://example.com:443'
+
+ >>> build_url(host='example.com', port=443)
+ '//example.com:443'
+
+ >>> build_url('fce:9af7:a667:7286:4917:b8d3:34df:8373', port=80, scheme='http')
+ 'http://[fce:9af7:a667:7286:4917:b8d3:34df:8373]:80'
+
+ :param scheme: The scheme, e.g. http, https or ftp.
+ :type scheme: str
+ :param host: Consisting of either a registered name (including but not limited to
+ a hostname) or an IP address.
+ :type host: str
+ :type port: int
+ :rtype: str
+ """
+ netloc = host if not is_valid_ipv6_address(host) else '[{}]'.format(host)
+ if port:
+ netloc += ':{}'.format(port)
+ pr = urllib.parse.ParseResult(
+ scheme=scheme if scheme else '',
+ netloc=netloc,
+ path='',
+ params='',
+ query='',
+ fragment='')
+ return pr.geturl()
+
+
+def prepare_url_prefix(url_prefix):
+ """
+ return '' if no prefix, or '/prefix' without slash in the end.
+ """
+ url_prefix = urljoin('/', url_prefix)
+ return url_prefix.rstrip('/')
+
+
+def dict_contains_path(dct, keys):
+ """
+ Tests whether the keys exist recursively in `dictionary`.
+
+ :type dct: dict
+ :type keys: list
+ :rtype: bool
+ """
+ if keys:
+ if not isinstance(dct, dict):
+ return False
+ key = keys.pop(0)
+ if key in dct:
+ dct = dct[key]
+ return dict_contains_path(dct, keys)
+ return False
+ return True
+
+
+if sys.version_info > (3, 0):
+ wraps = functools.wraps
+ _getargspec = inspect.getfullargspec
+else:
+ def wraps(func):
+ def decorator(wrapper):
+ new_wrapper = functools.wraps(func)(wrapper)
+ new_wrapper.__wrapped__ = func # set __wrapped__ even for Python 2
+ return new_wrapper
+ return decorator
+
+ _getargspec = inspect.getargspec
+
+
+def getargspec(func):
+ try:
+ while True:
+ func = func.__wrapped__
+ except AttributeError:
+ pass
+ # pylint: disable=deprecated-method
+ return _getargspec(func)
+
+
+def str_to_bool(val):
+ """
+ Convert a string representation of truth to True or False.
+
+ >>> str_to_bool('true') and str_to_bool('yes') and str_to_bool('1') and str_to_bool(True)
+ True
+
+ >>> str_to_bool('false') and str_to_bool('no') and str_to_bool('0') and str_to_bool(False)
+ False
+
+ >>> str_to_bool('xyz')
+ Traceback (most recent call last):
+ ...
+ ValueError: invalid truth value 'xyz'
+
+ :param val: The value to convert.
+ :type val: str|bool
+ :rtype: bool
+ """
+ if isinstance(val, bool):
+ return val
+ return bool(strtobool(val))
+
+
+def get_request_body_params(request):
+ """
+ Helper function to get parameters from the request body.
+ :param request The CherryPy request object.
+ :type request: cherrypy.Request
+ :return: A dictionary containing the parameters.
+ :rtype: dict
+ """
+ params = {}
+ if request.method not in request.methods_with_bodies:
+ return params
+
+ content_type = request.headers.get('Content-Type', '')
+ if content_type in ['application/json', 'text/javascript']:
+ if not hasattr(request, 'json'):
+ raise cherrypy.HTTPError(400, 'Expected JSON body')
+ if isinstance(request.json, str):
+ params.update(json.loads(request.json))
+ else:
+ params.update(request.json)
+
+ return params
+
+
+def find_object_in_list(key, value, iterable):
+ """
+ Get the first occurrence of an object within a list with
+ the specified key/value.
+
+ >>> find_object_in_list('name', 'bar', [{'name': 'foo'}, {'name': 'bar'}])
+ {'name': 'bar'}
+
+ >>> find_object_in_list('name', 'xyz', [{'name': 'foo'}, {'name': 'bar'}]) is None
+ True
+
+ >>> find_object_in_list('foo', 'bar', [{'xyz': 4815162342}]) is None
+ True
+
+ >>> find_object_in_list('foo', 'bar', []) is None
+ True
+
+ :param key: The name of the key.
+ :param value: The value to search for.
+ :param iterable: The list to process.
+ :return: Returns the found object or None.
+ """
+ for obj in iterable:
+ if key in obj and obj[key] == value:
+ return obj
+ return None
diff --git a/src/pybind/mgr/dashboard/tox.ini b/src/pybind/mgr/dashboard/tox.ini
new file mode 100644
index 00000000..e9614a50
--- /dev/null
+++ b/src/pybind/mgr/dashboard/tox.ini
@@ -0,0 +1,30 @@
+[tox]
+envlist = py27-{cov,lint,run,check},py3-{cov,lint,run,check}
+skipsdist = true
+toxworkdir = {env:CEPH_BUILD_DIR}/dashboard
+minversion = 2.8.1
+
+[testenv]
+setenv=
+ CFLAGS = -DXMLSEC_NO_SIZE_T
+ UNITTEST = true
+ WEBTEST_INTERACTIVE = false
+ LD_LIBRARY_PATH = {toxinidir}/../../../../build/lib
+ PATH = {toxinidir}/../../../../build/bin:{env:PATH}
+ py27: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.2
+ py3: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.3
+ cov: UNITTEST = true
+ cov: COVERAGE_FILE = .coverage.{envname}
+commands=
+ pip install -r {toxinidir}/requirements.txt
+ py27: pip install -r {toxinidir}/requirements-py27.txt
+ py3: pip install -r {toxinidir}/requirements-py3.txt
+ cov: coverage erase
+ cov: {envbindir}/py.test --cov=. --cov-report= --junitxml=junit.{envname}.xml --doctest-modules controllers services/ tests/ tools.py
+ cov: coverage combine {toxinidir}/{env:COVERAGE_FILE}
+ cov: coverage report
+ cov: coverage xml
+ lint: pylint --rcfile=.pylintrc --jobs=5 . module.py tools.py controllers tests services exceptions.py grafana.py ci/check_grafana_uids.py
+ lint: pycodestyle --max-line-length=100 --exclude=.tox,venv,frontend,.vscode --ignore=E402,E121,E123,E126,E226,E24,E704,W503,E741 .
+ check: python ci/check_grafana_uids.py frontend/src/app ../../../../monitoring/grafana/dashboards
+ run: {posargs}
diff --git a/src/pybind/mgr/deepsea/__init__.py b/src/pybind/mgr/deepsea/__init__.py
new file mode 100644
index 00000000..99bad018
--- /dev/null
+++ b/src/pybind/mgr/deepsea/__init__.py
@@ -0,0 +1 @@
+from .module import DeepSeaOrchestrator
diff --git a/src/pybind/mgr/deepsea/module.py b/src/pybind/mgr/deepsea/module.py
new file mode 100644
index 00000000..734a457d
--- /dev/null
+++ b/src/pybind/mgr/deepsea/module.py
@@ -0,0 +1,527 @@
+# vim: ts=8 et sw=4 sts=4
+"""
+ceph-mgr DeepSea orchestrator module
+"""
+
+# We want orchestrator methods in this to be 1:1 mappings to DeepSea runners,
+# we don't want to aggregate multiple salt invocations here, because that means
+# this module would need to know too much about how DeepSea works internally.
+# Better to expose new runners from DeepSea to match what the orchestrator needs.
+
+import json
+import errno
+import requests
+
+from threading import Event, Thread, Lock
+
+from mgr_module import MgrModule
+import orchestrator
+
+
+class RequestException(Exception):
+ def __init__(self, message, status_code=None):
+ super(RequestException, self).__init__(message)
+ self.status_code = status_code
+
+
+class DeepSeaReadCompletion(orchestrator.ReadCompletion):
+ def __init__(self, process_result_callback):
+ super(DeepSeaReadCompletion, self).__init__()
+ self._complete = False
+ self._cb = process_result_callback
+
+ def _process_result(self, data):
+ self._result = self._cb(data)
+ self._complete = True
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_complete(self):
+ return self._complete
+
+
+class DeepSeaOrchestrator(MgrModule, orchestrator.Orchestrator):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'salt_api_url',
+ 'default': ''
+ },
+ {
+ 'name': 'salt_api_eauth',
+ 'default': 'sharedsecret'
+ },
+ {
+ 'name': 'salt_api_username',
+ 'default': ''
+ },
+ {
+ 'name': 'salt_api_password',
+ 'default': ''
+ }
+ ]
+
+
+ COMMANDS = [
+ {
+ "cmd": "deepsea config-set name=key,type=CephString "
+ "name=value,type=CephString",
+ "desc": "Set a configuration value",
+ "perm": "rw"
+ },
+ {
+ "cmd": "deepsea config-show",
+ "desc": "Show current configuration",
+ "perm": "r"
+ }
+ ]
+
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None)) for o in self.MODULE_OPTIONS)
+
+
+ def get_module_option(self, key, default=None):
+ """
+ Overrides the default MgrModule get_module_option() method to pull in defaults
+ specific to this module
+ """
+ return super(DeepSeaOrchestrator, self).get_module_option(key, default=self.config_keys[key])
+
+
+ def _config_valid(self):
+ for key in self.config_keys.keys():
+ if not self.get_module_option(key, self.config_keys[key]):
+ return False
+ return True
+
+
+ def __init__(self, *args, **kwargs):
+ super(DeepSeaOrchestrator, self).__init__(*args, **kwargs)
+ self._event = Event()
+ self._token = None
+ self._event_reader = None
+ self._reading_events = False
+ self._last_failure_msg = None
+ self._all_completions = dict()
+ self._completion_lock = Lock()
+ self.inventory_cache = orchestrator.OutdatableDict()
+ self.service_cache = orchestrator.OutdatableDict()
+
+ def available(self):
+ if not self._config_valid():
+ return False, "Configuration invalid; try `ceph deepsea config-set [...]`"
+
+ if not self._reading_events and self._last_failure_msg:
+ return False, self._last_failure_msg
+
+ return True, ""
+
+ def get_inventory(self, node_filter=None, refresh=False):
+ """
+ Note that this will raise an exception (e.g. if the salt-api is down,
+ or the username/password is incorret). Same for other methods.
+ Callers should expect this and react appropriately. The orchestrator
+ cli, for example, just prints the traceback in the console, so the
+ user at least sees the error.
+ """
+ self.inventory_cache.remove_outdated()
+ if not self.inventory_cache.any_outdated() and not refresh:
+ if node_filter is None:
+ return orchestrator.TrivialReadCompletion(
+ orchestrator.InventoryNode.from_nested_items(self.inventory_cache.items()))
+ elif node_filter.labels is None:
+ try:
+ return orchestrator.TrivialReadCompletion(
+ orchestrator.InventoryNode.from_nested_items(
+ self.inventory_cache.items_filtered(node_filter.nodes)))
+ except KeyError:
+ # items_filtered() will raise KeyError if passed a node name that doesn't exist
+ return orchestrator.TrivialReadCompletion([])
+
+ def process_result(event_data):
+ result = []
+ if event_data['success']:
+ for node_name, node_devs in event_data["return"].items():
+ if node_filter is None:
+ # The cache will only be populated when this function is invoked
+ # without a node filter, i.e. if you run it once for the whole
+ # cluster, you can then call it for individual nodes and return
+ # cached data. However, if you only *ever* call it for individual
+ # nodes, the cache will never be populated, and you'll always have
+ # the full round trip to DeepSea.
+ self.inventory_cache[node_name] = orchestrator.OutdatableData(node_devs)
+ devs = orchestrator.InventoryDevice.from_ceph_volume_inventory_list(node_devs)
+ result.append(orchestrator.InventoryNode(node_name, devs))
+ else:
+ self.log.error(event_data['return'])
+ return result
+
+ with self._completion_lock:
+ c = DeepSeaReadCompletion(process_result)
+
+ nodes = []
+ roles = []
+ if node_filter:
+ nodes = node_filter.nodes
+ roles = node_filter.labels
+
+ resp = self._do_request_with_login("POST", data = {
+ "client": "runner_async",
+ "fun": "mgr_orch.get_inventory",
+ "nodes": nodes,
+ "roles": roles
+ })
+
+ # ['return'][0]['tag'] in the resonse JSON is what we need to match
+ # on when looking for the result event (e.g.: "salt/run/20181018074024331230")
+ self._all_completions["{}/ret".format(resp.json()['return'][0]['tag'])] = c
+
+ return c
+
+ def describe_service(self, service_type=None, service_id=None, node_name=None, refresh=False):
+
+ # Note: describe_service() does *not* support OSDs. This is because
+ # DeepSea doesn't really record what OSDs are deployed where; Ceph is
+ # considered the canonical source of this information, so having this
+ # function query OSD information from DeepSea doesn't make a lot of
+ # sense (DeepSea would have to call back into Ceph).
+
+ assert service_type in ("mon", "mgr", "mds", "rgw", "nfs", "iscsi", None), service_type + " unsupported"
+
+ def _deepsea_to_ceph(service):
+ if service == "ganesha":
+ return "nfs"
+ elif service == "igw":
+ return "iscsi"
+ else:
+ return service
+
+ # presently unused
+ def _ceph_to_deepsea(service):
+ if service == "nfs":
+ return "ganesha"
+ elif service == "iscsi":
+ return "igw"
+ else:
+ return service
+
+ self.service_cache.remove_outdated()
+ if not self.service_cache.any_outdated() and not refresh:
+ # Let's hope the services are complete.
+ try:
+ node_filter = [node_name] if node_name else None
+ services_by_node = [d[1].data for d in self.service_cache.items_filtered(node_filter)]
+ services = [orchestrator.ServiceDescription.from_json(s) for services in services_by_node for s in services]
+ services = [s for s in services if
+ (True if service_type is None else s.service_type == service_type) and
+ (True if service_id is None else s.service_instance == service_id)]
+ return orchestrator.TrivialReadCompletion(services)
+ except KeyError:
+ # items_filtered() will raise KeyError if passed a node name that doesn't exist
+ return orchestrator.TrivialReadCompletion([])
+
+ def process_result(event_data):
+ result = []
+ if event_data['success']:
+ for service_node, service_info in event_data["return"].items():
+ node_service_cache = []
+ for this_service_type, service_dict in service_info.items():
+ if isinstance(service_dict, str):
+ # map old form where deepsea only returned service IDs
+ # to new form where it retuns a dict
+ service_dict = { 'service_instance': service_dict }
+ desc = orchestrator.ServiceDescription(nodename=service_node,
+ service_instance=service_dict['service_instance'],
+ service_type=_deepsea_to_ceph(this_service_type),
+ # the following may or may not be present
+ container_id=service_dict.get('container_id', None),
+ service=service_dict.get('service', None),
+ version=service_dict.get('version', None),
+ rados_config_location=service_dict.get('rados_config_location', None),
+ service_url = service_dict.get('service_url', None),
+ status=service_dict.get('status', None),
+ status_desc=service_dict.get('status_desc', None)
+ )
+ # Always add every service to the cache...
+ node_service_cache.append(desc.to_json())
+ # ...but only return the ones the caller asked for
+ if ((service_type is None or desc.service_type == service_type) and
+ (service_id is None or desc.service_instance == service_id) and
+ (node_name is None or desc.nodename == node_name)):
+ result.append(desc)
+
+ self.service_cache[service_node] = orchestrator.OutdatableData(node_service_cache)
+ else:
+ self.log.error(event_data['return'])
+ return result
+
+ with self._completion_lock:
+ c = DeepSeaReadCompletion(process_result)
+
+ # Always request all services, so we always have all services cached.
+ resp = self._do_request_with_login("POST", data = {
+ "client": "runner_async",
+ "fun": "mgr_orch.describe_service"
+ })
+ self._all_completions["{}/ret".format(resp.json()['return'][0]['tag'])] = c
+
+ return c
+
+ def wait(self, completions):
+ incomplete = False
+
+ with self._completion_lock:
+ for c in completions:
+ if c.is_complete:
+ continue
+ if not c.is_complete:
+ # TODO: the job is in the bus, it should reach us eventually
+ # unless something has gone wrong (e.g. salt-api died, etc.),
+ # in which case it's possible the job finished but we never
+ # noticed the salt/run/$id/ret event. Need to add the job ID
+ # (or possibly the full event tag) to the completion object.
+ # That way, if we want to double check on a job that hasn't
+ # been completed yet, we can make a synchronous request to
+ # salt-api to invoke jobs.lookup_jid, and if it's complete we
+ # should be able to pass its return value to _process_result()
+ # Question: do we do this automatically after some timeout?
+ # Or do we add a function so the admin can check and "unstick"
+ # a stuck completion?
+ incomplete = True
+
+ return not incomplete
+
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == 'deepsea config-show':
+ return 0, json.dumps(dict([(key, self.get_module_option(key)) for key in self.config_keys.keys()])), ''
+
+ elif cmd['prefix'] == 'deepsea config-set':
+ if cmd['key'] not in self.config_keys.keys():
+ return (-errno.EINVAL, '',
+ "Unknown configuration option '{0}'".format(cmd['key']))
+
+ self.set_module_option(cmd['key'], cmd['value'])
+ self._event.set()
+ return 0, "Configuration option '{0}' updated".format(cmd['key']), ''
+
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(cmd['prefix']))
+
+
+ def serve(self):
+ self.log.info('DeepSea module starting up')
+ self.run = True
+ while self.run:
+ if not self._config_valid():
+ # This will spin until the config is valid, spitting a warning
+ # that the config is invalid every 60 seconds. The one oddity
+ # is that while setting the various parameters, this log warning
+ # will print once for each parameter set until the config is valid.
+ self.log.warn("Configuration invalid; try `ceph deepsea config-set [...]`")
+ self._event.wait(60)
+ self._event.clear()
+ continue
+
+ if self._event_reader and not self._reading_events:
+ self._event_reader = None
+
+ if not self._event_reader:
+ self._last_failure_msg = None
+ try:
+ # This spawns a separate thread to read the salt event bus
+ # stream. We can't do it in the serve thead, because reading
+ # from the response blocks, which would prevent the serve
+ # thread from handling anything else.
+ #
+ # TODO: figure out how to restart the _event_reader thread if
+ # config changes, e.g.: a new username or password is set.
+ # This will be difficult, because _read_sse() just blocks waiting
+ # for response lines. The closest I got was setting a read timeout
+ # on the request, but in the general case (where not much is
+ # happening most of the time), this will result in continual
+ # timeouts and reconnects. We really need an asynchronous read
+ # to support this.
+ self._event_response = self._do_request_with_login("GET", "events", stream=True)
+ self._event_reader = Thread(target=self._read_sse)
+ self._reading_events = True
+ self._event_reader.start()
+ except Exception as ex:
+ self._set_last_failure_msg("Failure setting up event reader: " + str(ex))
+ # gives an (arbitrary) 60 second retry if we can't attach to
+ # the salt-api event bus for some reason (e.g.: invalid username,
+ # or password, which will be logged as "Request failed with status
+ # code 401"). Note that this 60 second retry will also happen if
+ # salt-api dies.
+ self._event.wait(60)
+ self._event.clear()
+ continue
+
+ # Wait indefinitely for something interesting to happen (e.g.
+ # config-set, or shutdown), or the event reader to fail, which
+ # will happen if the salt-api server dies or restarts).
+ self._event.wait()
+ self._event.clear()
+
+
+ def shutdown(self):
+ self.log.info('DeepSea module shutting down')
+ self.run = False
+ self._event.set()
+
+
+ def _set_last_failure_msg(self, msg):
+ self._last_failure_msg = msg
+ self.log.warn(msg)
+
+
+ # Reader/parser of SSE events, see:
+ # - https://docs.saltstack.com/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html#events)
+ # - https://www.w3.org/TR/2009/WD-eventsource-20090421/
+ # Note: this is pretty braindead and doesn't implement the full eventsource
+ # spec, but it *does* implement enough for us to listen to events from salt
+ # and potentially do something with them.
+ def _read_sse(self):
+ event = {}
+ try:
+ # Just starting the event reader; if we've made it here, we know we're
+ # talking to salt-api (_do_request would have raised an exception if the
+ # response wasn't ok), so check if there's any completions inflight that
+ # need to be dealt with. This handles the case where some command was
+ # invoked, then salt-api died somehow, and we reconneced, but missed the
+ # completion at the time it actually happened.
+ for tag in list(self._all_completions):
+ self.log.info("Found event {} inflight".format(tag))
+ try:
+ resp = self._do_request_with_login("POST", data = {
+ "client": "runner",
+ "fun": "jobs.lookup_jid",
+ "jid": tag.split('/')[2]
+ })
+ # jobs.lookup_jid returns a dict keyed by hostname.
+ return_dict = resp.json()['return'][0]
+ if return_dict:
+ # If the job is complete, there'll be one item in the dict.
+ self.log.info("Event {} complete".format(tag))
+ # The key is the salt master hostname, but we don't care
+ # about that, so just grab the data.
+ data = next(iter(return_dict.items()))[1]
+ self._all_completions[tag]._process_result(data)
+ # TODO: decide whether it's bad to delete the completion
+ # here -- would we ever need to resurrect it?
+ del self._all_completions[tag]
+ else:
+ # if the job is not complete, there'll be nothing in the dict
+ self.log.info("Event {} still pending".format(tag))
+ except Exception as ex:
+ # Logging a warning if the request failed, so we can continue
+ # checking any other completions, then get onto reading events
+ self.log.warn("Error looking up inflight event {}: {}".format(tag, str(ex)))
+
+ for line in self._event_response.iter_lines():
+ with self._completion_lock:
+ if line:
+ line = line.decode('utf-8')
+ colon = line.find(':')
+ if colon > 0:
+ k = line[:colon]
+ v = line[colon+2:]
+ if k == "retry":
+ # TODO: find out if we need to obey this reconnection time
+ self.log.warn("Server requested retry {}, ignored".format(v))
+ else:
+ event[k] = v
+ else:
+ # Empty line, terminates an event. Note that event['tag']
+ # is a salt-api extension to SSE to avoid having to decode
+ # json data if you don't care about it. To get to the
+ # interesting stuff, you want event['data'], which is json.
+ # If you want to have some fun, try
+ # `ceph daemon mgr.$(hostname) config set debug_mgr 20`
+ # then `salt '*' test.ping` on the master
+ self.log.debug("Got event '{}'".format(str(event)))
+
+ # If we're actually interested in this event (i.e. it's
+ # in our completion dict), fire off that completion's
+ # _process_result() callback and remove it from our list.
+ if event['tag'] in self._all_completions:
+ self.log.info("Event {} complete".format(event['tag']))
+ self._all_completions[event['tag']]._process_result(json.loads(event['data'])['data'])
+ # TODO: decide whether it's bad to delete the completion
+ # here -- would we ever need to resurrect it?
+ del self._all_completions[event['tag']]
+
+ event = {}
+ self._set_last_failure_msg("SSE read terminated")
+ except Exception as ex:
+ self.log.exception(ex)
+ self._set_last_failure_msg("SSE read failed: {}".format(str(ex)))
+
+ self._reading_events = False
+ self._event.set()
+
+
+ # _do_request(), _login() and _do_request_with_login() are an extremely
+ # minimalist form of the following, with notably terse error handling:
+ # https://bitbucket.org/openattic/openattic/src/ce4543d4cbedadc21b484a098102a16efec234f9/backend/rest_client.py?at=master&fileviewer=file-view-default
+ # https://bitbucket.org/openattic/openattic/src/ce4543d4cbedadc21b484a098102a16efec234f9/backend/deepsea.py?at=master&fileviewer=file-view-default
+ # rationale:
+ # - I needed slightly different behaviour than in openATTIC (I want the
+ # caller to read the response, to allow streaming the salt-api event bus)
+ # - I didn't want to pull in 400+ lines more code into this presently
+ # experimental module, to save everyone having to review it ;-)
+
+ def _do_request(self, method, path="", data=None, stream=False):
+ """
+ returns the response, which the caller then has to read
+ """
+ url = "{0}/{1}".format(self.get_module_option('salt_api_url'), path)
+ try:
+ if method.lower() == 'get':
+ resp = requests.get(url, headers = { "X-Auth-Token": self._token },
+ data=data, stream=stream)
+ elif method.lower() == 'post':
+ resp = requests.post(url, headers = { "X-Auth-Token": self._token },
+ data=data)
+
+ else:
+ raise RequestException("Method '{}' not supported".format(method.upper()))
+ if resp.ok:
+ return resp
+ else:
+ msg = "Request failed with status code {}".format(resp.status_code)
+ raise RequestException(msg, resp.status_code)
+ except requests.exceptions.ConnectionError as ex:
+ self.log.exception(str(ex))
+ raise RequestException(str(ex))
+ except requests.exceptions.InvalidURL as ex:
+ self.log.exception(str(ex))
+ raise RequestException(str(ex))
+
+
+ def _login(self):
+ resp = self._do_request('POST', 'login', data = {
+ "eauth": self.get_module_option('salt_api_eauth'),
+ "password": self.get_module_option('salt_api_password'),
+ "username": self.get_module_option('salt_api_username')
+ })
+ self._token = resp.json()['return'][0]['token']
+ self.log.info("Salt API login successful")
+
+
+ def _do_request_with_login(self, method, path="", data=None, stream=False):
+ retries = 2
+ while True:
+ try:
+ if not self._token:
+ self._login()
+ return self._do_request(method, path, data, stream)
+ except RequestException as ex:
+ retries -= 1
+ if ex.status_code not in [401, 403] or retries == 0:
+ raise ex
+ self._token = None
diff --git a/src/pybind/mgr/devicehealth/__init__.py b/src/pybind/mgr/devicehealth/__init__.py
new file mode 100644
index 00000000..4c5b97ce
--- /dev/null
+++ b/src/pybind/mgr/devicehealth/__init__.py
@@ -0,0 +1,2 @@
+
+from .module import Module
diff --git a/src/pybind/mgr/devicehealth/module.py b/src/pybind/mgr/devicehealth/module.py
new file mode 100644
index 00000000..9bddc66f
--- /dev/null
+++ b/src/pybind/mgr/devicehealth/module.py
@@ -0,0 +1,651 @@
+"""
+Device health monitoring
+"""
+
+import errno
+import json
+from mgr_module import MgrModule, CommandResult
+import operator
+import rados
+from threading import Event
+from datetime import datetime, timedelta, date, time
+import _strptime
+from six import iteritems
+
+TIME_FORMAT = '%Y%m%d-%H%M%S'
+
+DEVICE_HEALTH = 'DEVICE_HEALTH'
+DEVICE_HEALTH_IN_USE = 'DEVICE_HEALTH_IN_USE'
+DEVICE_HEALTH_TOOMANY = 'DEVICE_HEALTH_TOOMANY'
+HEALTH_MESSAGES = {
+ DEVICE_HEALTH: '%d device(s) expected to fail soon',
+ DEVICE_HEALTH_IN_USE: '%d daemons(s) expected to fail soon and still contain data',
+ DEVICE_HEALTH_TOOMANY: 'Too many daemons are expected to fail soon',
+}
+
+MAX_SAMPLES=500
+
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'enable_monitoring',
+ 'default': False,
+ 'type': 'bool',
+ 'desc': 'monitor device health metrics',
+ 'runtime': True,
+ },
+ {
+ 'name': 'scrape_frequency',
+ 'default': 86400,
+ 'type': 'secs',
+ 'desc': 'how frequently to scrape device health metrics',
+ 'runtime': True,
+ },
+ {
+ 'name': 'pool_name',
+ 'default': 'device_health_metrics',
+ 'type': 'str',
+ 'desc': 'name of pool in which to store device health metrics',
+ 'runtime': True,
+ },
+ {
+ 'name': 'retention_period',
+ 'default': (86400 * 180),
+ 'type': 'secs',
+ 'desc': 'how long to retain device health metrics',
+ 'runtime': True,
+ },
+ {
+ 'name': 'mark_out_threshold',
+ 'default': (86400 * 14 * 2),
+ 'type': 'secs',
+ 'desc': 'automatically mark OSD if it may fail before this long',
+ 'runtime': True,
+ },
+ {
+ 'name': 'warn_threshold',
+ 'default': (86400 * 14 * 6),
+ 'type': 'secs',
+ 'desc': 'raise health warning if OSD may fail before this long',
+ 'runtime': True,
+ },
+ {
+ 'name': 'self_heal',
+ 'default': True,
+ 'type': 'bool',
+ 'desc': 'preemptively heal cluster around devices that may fail',
+ 'runtime': True,
+ },
+ {
+ 'name': 'sleep_interval',
+ 'default': 600,
+ 'type': 'secs',
+ 'desc': 'how frequently to wake up and check device health',
+ 'runtime': True,
+ },
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "device query-daemon-health-metrics "
+ "name=who,type=CephString",
+ "desc": "Get device health metrics for a given daemon",
+ "perm": "r"
+ },
+ {
+ "cmd": "device scrape-daemon-health-metrics "
+ "name=who,type=CephString",
+ "desc": "Scrape and store device health metrics "
+ "for a given daemon",
+ "perm": "r"
+ },
+ {
+ "cmd": "device scrape-health-metrics "
+ "name=devid,type=CephString,req=False",
+ "desc": "Scrape and store health metrics",
+ "perm": "r"
+ },
+ {
+ "cmd": "device get-health-metrics "
+ "name=devid,type=CephString "
+ "name=sample,type=CephString,req=False",
+ "desc": "Show stored device metrics for the device",
+ "perm": "r"
+ },
+ {
+ "cmd": "device check-health",
+ "desc": "Check life expectancy of devices",
+ "perm": "rw",
+ },
+ {
+ "cmd": "device monitoring on",
+ "desc": "Enable device health monitoring",
+ "perm": "rw",
+ },
+ {
+ "cmd": "device monitoring off",
+ "desc": "Disable device health monitoring",
+ "perm": "rw",
+ },
+ {
+ 'cmd': 'device predict-life-expectancy '
+ 'name=devid,type=CephString,req=true',
+ 'desc': 'Predict life expectancy with local predictor',
+ 'perm': 'r'
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+
+ # populate options (just until serve() runs)
+ for opt in self.MODULE_OPTIONS:
+ setattr(self, opt['name'], opt['default'])
+
+ # other
+ self.run = True
+ self.event = Event()
+
+ def is_valid_daemon_name(self, who):
+ l = who.split('.')
+ if len(l) != 2:
+ return False
+ if l[0] not in ('osd', 'mon'):
+ return False;
+ return True;
+
+ def handle_command(self, _, cmd):
+ self.log.error("handle_command")
+
+ if cmd['prefix'] == 'device query-daemon-health-metrics':
+ who = cmd.get('who', '')
+ if not self.is_valid_daemon_name(who):
+ return -errno.EINVAL, '', 'not a valid mon or osd daemon name'
+ (daemon_type, daemon_id) = cmd.get('who', '').split('.')
+ result = CommandResult('')
+ self.send_command(result, daemon_type, daemon_id, json.dumps({
+ 'prefix': 'smart',
+ 'format': 'json',
+ }), '')
+ r, outb, outs = result.wait()
+ return r, outb, outs
+ elif cmd['prefix'] == 'device scrape-daemon-health-metrics':
+ who = cmd.get('who', '')
+ if not self.is_valid_daemon_name(who):
+ return -errno.EINVAL, '', 'not a valid mon or osd daemon name'
+ (daemon_type, daemon_id) = cmd.get('who', '').split('.')
+ return self.scrape_daemon(daemon_type, daemon_id)
+ elif cmd['prefix'] == 'device scrape-health-metrics':
+ if 'devid' in cmd:
+ return self.scrape_device(cmd['devid'])
+ return self.scrape_all()
+ elif cmd['prefix'] == 'device get-health-metrics':
+ return self.show_device_metrics(cmd['devid'], cmd.get('sample'))
+ elif cmd['prefix'] == 'device check-health':
+ return self.check_health()
+ elif cmd['prefix'] == 'device monitoring on':
+ self.set_module_option('enable_monitoring', True)
+ self.event.set()
+ return 0, '', ''
+ elif cmd['prefix'] == 'device monitoring off':
+ self.set_module_option('enable_monitoring', False)
+ self.set_health_checks({}) # avoid stuck health alerts
+ return 0, '', ''
+ elif cmd['prefix'] == 'device predict-life-expectancy':
+ return self.predict_lift_expectancy(cmd['devid'])
+ else:
+ # mgr should respect our self.COMMANDS and not call us for
+ # any prefix we don't advertise
+ raise NotImplementedError(cmd['prefix'])
+
+ def self_test(self):
+ self.config_notify()
+ osdmap = self.get('osd_map')
+ osd_id = osdmap['osds'][0]['osd']
+ osdmeta = self.get('osd_metadata')
+ devs = osdmeta.get(str(osd_id), {}).get('device_ids')
+ if devs:
+ devid = devs.split()[0].split('=')[1]
+ (r, before, err) = self.show_device_metrics(devid, '')
+ assert r == 0
+ (r, out, err) = self.scrape_device(devid)
+ assert r == 0
+ (r, after, err) = self.show_device_metrics(devid, '')
+ assert r == 0
+ assert before != after
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+
+ def serve(self):
+ self.log.info("Starting")
+ self.config_notify()
+
+ last_scrape = None
+ ls = self.get_store('last_scrape')
+ if ls:
+ try:
+ last_scrape = datetime.strptime(ls, TIME_FORMAT)
+ except ValueError as e:
+ pass
+ self.log.debug('Last scrape %s', last_scrape)
+
+ while self.run:
+ if self.enable_monitoring:
+ self.log.debug('Running')
+ self.check_health()
+
+ now = datetime.utcnow()
+ if not last_scrape:
+ next_scrape = now
+ else:
+ # align to scrape interval
+ scrape_frequency = int(self.scrape_frequency) or 86400
+ seconds = (last_scrape - datetime.utcfromtimestamp(0)).total_seconds()
+ seconds -= seconds % scrape_frequency
+ seconds += scrape_frequency
+ next_scrape = datetime.utcfromtimestamp(seconds)
+ if last_scrape:
+ self.log.debug('Last scrape %s, next scrape due %s',
+ last_scrape.strftime(TIME_FORMAT),
+ next_scrape.strftime(TIME_FORMAT))
+ else:
+ self.log.debug('Last scrape never, next scrape due %s',
+ next_scrape.strftime(TIME_FORMAT))
+ if now >= next_scrape:
+ self.scrape_all()
+ self.predict_all_devices()
+ last_scrape = now
+ self.set_store('last_scrape', last_scrape.strftime(TIME_FORMAT))
+
+ # sleep
+ sleep_interval = int(self.sleep_interval) or 60
+ self.log.debug('Sleeping for %d seconds', sleep_interval)
+ ret = self.event.wait(sleep_interval)
+ self.event.clear()
+
+ def shutdown(self):
+ self.log.info('Stopping')
+ self.run = False
+ self.event.set()
+
+ def open_connection(self, create_if_missing=True):
+ pools = self.rados.list_pools()
+ is_pool = False
+ for pool in pools:
+ if pool == self.pool_name:
+ is_pool = True
+ break
+ if not is_pool:
+ if not create_if_missing:
+ return None
+ self.log.debug('create %s pool' % self.pool_name)
+ # create pool
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd pool create',
+ 'format': 'json',
+ 'pool': self.pool_name,
+ 'pg_num': 1,
+ 'pg_num_min': 1,
+ }), '')
+ r, outb, outs = result.wait()
+ assert r == 0
+
+ # set pool application
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd pool application enable',
+ 'format': 'json',
+ 'pool': self.pool_name,
+ 'app': 'mgr_devicehealth',
+ }), '')
+ r, outb, outs = result.wait()
+ assert r == 0
+
+ ioctx = self.rados.open_ioctx(self.pool_name)
+ return ioctx
+
+ def scrape_daemon(self, daemon_type, daemon_id):
+ ioctx = self.open_connection()
+ if daemon_type != 'osd':
+ return -errno.EINVAL, '', 'scraping non-OSDs not currently supported'
+ raw_smart_data = self.do_scrape_daemon(daemon_type, daemon_id)
+ if raw_smart_data:
+ for device, raw_data in raw_smart_data.items():
+ data = self.extract_smart_features(raw_data)
+ if device and data:
+ self.put_device_metrics(ioctx, device, data)
+ ioctx.close()
+ return 0, "", ""
+
+ def scrape_all(self):
+ osdmap = self.get("osd_map")
+ assert osdmap is not None
+ ioctx = self.open_connection()
+ did_device = {}
+ ids = []
+ for osd in osdmap['osds']:
+ ids.append(('osd', str(osd['osd'])))
+ for daemon_type, daemon_id in ids:
+ raw_smart_data = self.do_scrape_daemon(daemon_type, daemon_id)
+ if not raw_smart_data:
+ continue
+ for device, raw_data in raw_smart_data.items():
+ if device in did_device:
+ self.log.debug('skipping duplicate %s' % device)
+ continue
+ did_device[device] = 1
+ data = self.extract_smart_features(raw_data)
+ if device and data:
+ self.put_device_metrics(ioctx, device, data)
+ ioctx.close()
+ return 0, "", ""
+
+ def scrape_device(self, devid):
+ r = self.get("device " + devid)
+ if not r or 'device' not in r.keys():
+ return -errno.ENOENT, '', 'device ' + devid + ' not found'
+ daemons = [d for d in r['device'].get('daemons', []) if d.startswith('osd.')]
+ if not daemons:
+ return (-errno.EAGAIN, '',
+ 'device ' + devid + ' not claimed by any active OSD daemons')
+ (daemon_type, daemon_id) = daemons[0].split('.')
+ ioctx = self.open_connection()
+ raw_smart_data = self.do_scrape_daemon(daemon_type, daemon_id,
+ devid=devid)
+ if raw_smart_data:
+ for device, raw_data in raw_smart_data.items():
+ data = self.extract_smart_features(raw_data)
+ if device and data:
+ self.put_device_metrics(ioctx, device, data)
+ ioctx.close()
+ return 0, "", ""
+
+ def do_scrape_daemon(self, daemon_type, daemon_id, devid=''):
+ """
+ :return: a dict, or None if the scrape failed.
+ """
+ self.log.debug('do_scrape_daemon %s.%s' % (daemon_type, daemon_id))
+ result = CommandResult('')
+ self.send_command(result, daemon_type, daemon_id, json.dumps({
+ 'prefix': 'smart',
+ 'format': 'json',
+ 'devid': devid,
+ }), '')
+ r, outb, outs = result.wait()
+
+ try:
+ return json.loads(outb)
+ except (IndexError, ValueError):
+ self.log.error(
+ "Fail to parse JSON result from daemon {0}.{1} ({2})".format(
+ daemon_type, daemon_id, outb))
+
+ def put_device_metrics(self, ioctx, devid, data):
+ assert devid
+ old_key = datetime.utcnow() - timedelta(
+ seconds=int(self.retention_period))
+ prune = old_key.strftime(TIME_FORMAT)
+ self.log.debug('put_device_metrics device %s prune %s' %
+ (devid, prune))
+ erase = []
+ try:
+ with rados.ReadOpCtx() as op:
+ omap_iter, ret = ioctx.get_omap_keys(op, "", MAX_SAMPLES) # fixme
+ assert ret == 0
+ ioctx.operate_read_op(op, devid)
+ for key, _ in list(omap_iter):
+ if key >= prune:
+ break
+ erase.append(key)
+ except rados.ObjectNotFound:
+ # The object doesn't already exist, no problem.
+ pass
+ except rados.Error as e:
+ # Do not proceed with writes if something unexpected
+ # went wrong with the reads.
+ self.log.exception("Error reading OMAP: {0}".format(e))
+ return
+
+ key = datetime.utcnow().strftime(TIME_FORMAT)
+ self.log.debug('put_device_metrics device %s key %s = %s, erase %s' %
+ (devid, key, data, erase))
+ with rados.WriteOpCtx() as op:
+ ioctx.set_omap(op, (key,), (str(json.dumps(data)),))
+ if len(erase):
+ ioctx.remove_omap_keys(op, tuple(erase))
+ ioctx.operate_write_op(op, devid)
+
+ def _get_device_metrics(self, devid, sample=None, min_sample=None):
+ res = {}
+ ioctx = self.open_connection(create_if_missing=False)
+ if not ioctx:
+ return {}
+ with ioctx:
+ with rados.ReadOpCtx() as op:
+ omap_iter, ret = ioctx.get_omap_vals(op, min_sample or '', sample or '',
+ MAX_SAMPLES) # fixme
+ assert ret == 0
+ try:
+ ioctx.operate_read_op(op, devid)
+ for key, value in list(omap_iter):
+ if sample and key != sample:
+ break
+ if min_sample and key < min_sample:
+ break
+ try:
+ v = json.loads(value)
+ except (ValueError, IndexError):
+ self.log.debug('unable to parse value for %s: "%s"' %
+ (key, value))
+ pass
+ res[key] = v
+ except rados.ObjectNotFound:
+ pass
+ except rados.Error as e:
+ self.log.exception("RADOS error reading omap: {0}".format(e))
+ raise
+ return res
+
+ def show_device_metrics(self, devid, sample):
+ # verify device exists
+ r = self.get("device " + devid)
+ if not r or 'device' not in r.keys():
+ return -errno.ENOENT, '', 'device ' + devid + ' not found'
+ # fetch metrics
+ res = self._get_device_metrics(devid, sample=sample)
+ return 0, json.dumps(res, indent=4, sort_keys=True), ''
+
+ def check_health(self):
+ self.log.info('Check health')
+ config = self.get('config')
+ min_in_ratio = float(config.get('mon_osd_min_in_ratio'))
+ mark_out_threshold_td = timedelta(seconds=int(self.mark_out_threshold))
+ warn_threshold_td = timedelta(seconds=int(self.warn_threshold))
+ checks = {}
+ health_warnings = {
+ DEVICE_HEALTH: [],
+ DEVICE_HEALTH_IN_USE: [],
+ }
+ devs = self.get("devices")
+ osds_in = {}
+ osds_out = {}
+ now = datetime.utcnow()
+ osdmap = self.get("osd_map")
+ assert osdmap is not None
+ for dev in devs['devices']:
+ devid = dev['devid']
+ if 'life_expectancy_max' not in dev:
+ continue
+ # ignore devices that are not consumed by any daemons
+ if not dev['daemons']:
+ continue
+ if not dev['life_expectancy_max'] or \
+ dev['life_expectancy_max'] == '0.000000':
+ continue
+ # life_expectancy_(min/max) is in the format of:
+ # '%Y-%m-%d %H:%M:%S.%f', e.g.:
+ # '2019-01-20 21:12:12.000000'
+ life_expectancy_max = datetime.strptime(
+ dev['life_expectancy_max'],
+ '%Y-%m-%d %H:%M:%S.%f')
+ self.log.debug('device %s expectancy max %s', dev,
+ life_expectancy_max)
+
+ if life_expectancy_max - now <= mark_out_threshold_td:
+ if self.self_heal:
+ # dev['daemons'] == ["osd.0","osd.1","osd.2"]
+ if dev['daemons']:
+ osds = [x for x in dev['daemons']
+ if x.startswith('osd.')]
+ osd_ids = map(lambda x: x[4:], osds)
+ for _id in osd_ids:
+ if self.is_osd_in(osdmap, _id):
+ osds_in[_id] = life_expectancy_max
+ else:
+ osds_out[_id] = 1
+
+ if life_expectancy_max - now <= warn_threshold_td:
+ # device can appear in more than one location in case
+ # of SCSI multipath
+ device_locations = map(lambda x: x['host'] + ':' + x['dev'],
+ dev['location'])
+ health_warnings[DEVICE_HEALTH].append(
+ '%s (%s); daemons %s; life expectancy between %s and %s'
+ % (dev['devid'],
+ ','.join(device_locations),
+ ','.join(dev.get('daemons', ['none'])),
+ dev['life_expectancy_max'],
+ dev.get('life_expectancy_max', 'unknown')))
+
+ # OSD might be marked 'out' (which means it has no
+ # data), however PGs are still attached to it.
+ for _id in osds_out:
+ num_pgs = self.get_osd_num_pgs(_id)
+ if num_pgs > 0:
+ health_warnings[DEVICE_HEALTH_IN_USE].append(
+ 'osd.%s is marked out '
+ 'but still has %s PG(s)' %
+ (_id, num_pgs))
+ if osds_in:
+ self.log.debug('osds_in %s' % osds_in)
+ # calculate target in ratio
+ num_osds = len(osdmap['osds'])
+ num_in = len([x for x in osdmap['osds'] if x['in']])
+ num_bad = len(osds_in)
+ # sort with next-to-fail first
+ bad_osds = sorted(osds_in.items(), key=operator.itemgetter(1))
+ did = 0
+ to_mark_out = []
+ for osd_id, when in bad_osds:
+ ratio = float(num_in - did - 1) / float(num_osds)
+ if ratio < min_in_ratio:
+ final_ratio = float(num_in - num_bad) / float(num_osds)
+ checks[DEVICE_HEALTH_TOOMANY] = {
+ 'severity': 'warning',
+ 'summary': HEALTH_MESSAGES[DEVICE_HEALTH_TOOMANY],
+ 'detail': [
+ '%d OSDs with failing device(s) would bring "in" ratio to %f < mon_osd_min_in_ratio %f' % (num_bad - did, final_ratio, min_in_ratio)
+ ]
+ }
+ break
+ to_mark_out.append(osd_id)
+ did += 1
+ if to_mark_out:
+ self.mark_out_etc(to_mark_out)
+ for warning, ls in iteritems(health_warnings):
+ n = len(ls)
+ if n:
+ checks[warning] = {
+ 'severity': 'warning',
+ 'summary': HEALTH_MESSAGES[warning] % n,
+ 'detail': ls,
+ }
+ self.set_health_checks(checks)
+ return 0, "", ""
+
+ def is_osd_in(self, osdmap, osd_id):
+ for osd in osdmap['osds']:
+ if str(osd_id) == str(osd['osd']):
+ return bool(osd['in'])
+ return False
+
+ def get_osd_num_pgs(self, osd_id):
+ stats = self.get('osd_stats')
+ assert stats is not None
+ for stat in stats['osd_stats']:
+ if str(osd_id) == str(stat['osd']):
+ return stat['num_pgs']
+ return -1
+
+ def mark_out_etc(self, osd_ids):
+ self.log.info('Marking out OSDs: %s' % osd_ids)
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd out',
+ 'format': 'json',
+ 'ids': osd_ids,
+ }), '')
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.warn('Could not mark OSD %s out. r: [%s], outb: [%s], outs: [%s]' % (osd_ids, r, outb, outs))
+ for osd_id in osd_ids:
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd primary-affinity',
+ 'format': 'json',
+ 'id': int(osd_id),
+ 'weight': 0.0,
+ }), '')
+ r, outb, outs = result.wait()
+ if r != 0:
+ self.log.warn('Could not set osd.%s primary-affinity, r: [%s], outs: [%s]' % (osd_id, r, outb, outs))
+
+ def extract_smart_features(self, raw):
+ # FIXME: extract and normalize raw smartctl --json output and
+ # generate a dict of the fields we care about.
+ return raw
+
+ def predict_lift_expectancy(self, devid):
+ plugin_name = ''
+ model = self.get_ceph_option('device_failure_prediction_mode')
+ if model and model.lower() == 'cloud':
+ plugin_name = 'diskprediction_cloud'
+ elif model and model.lower() == 'local':
+ plugin_name = 'diskprediction_local'
+ else:
+ return -1, '', 'unable to enable any disk prediction model[local/cloud]'
+ try:
+ can_run, _ = self.remote(plugin_name, 'can_run')
+ if can_run:
+ return self.remote(plugin_name, 'predict_life_expectancy', devid=devid)
+ except:
+ return -1, '', 'unable to invoke diskprediction local or remote plugin'
+
+ def predict_all_devices(self):
+ plugin_name = ''
+ model = self.get_ceph_option('device_failure_prediction_mode')
+ if model and model.lower() == 'cloud':
+ plugin_name = 'diskprediction_cloud'
+ elif model and model.lower() == 'local':
+ plugin_name = 'diskprediction_local'
+ else:
+ return -1, '', 'unable to enable any disk prediction model[local/cloud]'
+ try:
+ can_run, _ = self.remote(plugin_name, 'can_run')
+ if can_run:
+ return self.remote(plugin_name, 'predict_all_devices')
+ except:
+ return -1, '', 'unable to invoke diskprediction local or remote plugin'
+
+ def get_recent_device_metrics(self, devid, min_sample):
+ return self._get_device_metrics(devid, min_sample=min_sample)
+
+ def get_time_format(self):
+ return TIME_FORMAT
diff --git a/src/pybind/mgr/diskprediction_cloud/__init__.py b/src/pybind/mgr/diskprediction_cloud/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/__init__.py b/src/pybind/mgr/diskprediction_cloud/agent/__init__.py
new file mode 100644
index 00000000..c7702e52
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/__init__.py
@@ -0,0 +1,38 @@
+from __future__ import absolute_import
+
+from ..common import timeout, TimeoutError
+
+
+class BaseAgent(object):
+
+ measurement = ''
+
+ def __init__(self, mgr_module, obj_sender, timeout=30):
+ self.data = []
+ self._client = None
+ self._client = obj_sender
+ self._logger = mgr_module.log
+ self._module_inst = mgr_module
+ self._timeout = timeout
+
+ def run(self):
+ try:
+ self._collect_data()
+ self._run()
+ except TimeoutError:
+ self._logger.error('{} failed to execute {} task'.format(
+ __name__, self.measurement))
+
+ def __nonzero__(self):
+ if not self._module_inst:
+ return False
+ else:
+ return True
+
+ @timeout()
+ def _run(self):
+ pass
+
+ @timeout()
+ def _collect_data(self):
+ pass
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/__init__.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/__init__.py
new file mode 100644
index 00000000..9e7e5b0b
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/__init__.py
@@ -0,0 +1,61 @@
+from __future__ import absolute_import
+
+from .. import BaseAgent
+from ...common import DP_MGR_STAT_FAILED, DP_MGR_STAT_WARNING, DP_MGR_STAT_OK
+
+AGENT_VERSION = '1.0.0'
+
+
+class MetricsField(object):
+ def __init__(self):
+ self.tags = {}
+ self.fields = {}
+ self.timestamp = None
+
+ def __str__(self):
+ return str({
+ 'tags': self.tags,
+ 'fields': self.fields,
+ 'timestamp': self.timestamp
+ })
+
+
+class MetricsAgent(BaseAgent):
+
+ def log_summary(self, status_info):
+ try:
+ if status_info:
+ measurement = status_info['measurement']
+ success_count = status_info['success_count']
+ failure_count = status_info['failure_count']
+ total_count = success_count + failure_count
+ display_string = \
+ '%s agent stats in total count: %s, success count: %s, failure count: %s.'
+ self._logger.info(
+ display_string % (measurement, total_count, success_count, failure_count)
+ )
+ except Exception as e:
+ self._logger.error(str(e))
+
+ def _run(self):
+ collect_data = self.data
+ result = {}
+ if collect_data and self._client:
+ status_info = self._client.send_info(collect_data, self.measurement)
+ # show summary info
+ self.log_summary(status_info)
+ # write sub_agent buffer
+ total_count = status_info['success_count'] + status_info['failure_count']
+ if total_count:
+ if status_info['success_count'] == 0:
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_FAILED,
+ 'reason': 'failed to send metrics data to the server'}
+ elif status_info['failure_count'] == 0:
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_OK}
+ else:
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_WARNING,
+ 'reason': 'failed to send partial metrics data to the server'}
+ return result
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_cluster.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_cluster.py
new file mode 100644
index 00000000..2491644a
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_cluster.py
@@ -0,0 +1,145 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class CephCluster(MetricsField):
+ """ Ceph cluster structure """
+ measurement = 'ceph_cluster'
+
+ def __init__(self):
+ super(CephCluster, self).__init__()
+ self.tags['cluster_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.fields['cluster_health'] = ''
+ self.fields['num_mon'] = None
+ self.fields['num_mon_quorum'] = None
+ self.fields['num_osd'] = None
+ self.fields['num_osd_up'] = None
+ self.fields['num_osd_in'] = None
+ self.fields['osd_epoch'] = None
+ self.fields['osd_bytes'] = None
+ self.fields['osd_bytes_used'] = None
+ self.fields['osd_bytes_avail'] = None
+ self.fields['num_pool'] = None
+ self.fields['num_pg'] = None
+ self.fields['num_pg_active_clean'] = None
+ self.fields['num_pg_active'] = None
+ self.fields['num_pg_peering'] = None
+ self.fields['num_object'] = None
+ self.fields['num_object_degraded'] = None
+ self.fields['num_object_misplaced'] = None
+ self.fields['num_object_unfound'] = None
+ self.fields['num_bytes'] = None
+ self.fields['num_mds_up'] = None
+ self.fields['num_mds_in'] = None
+ self.fields['num_mds_failed'] = None
+ self.fields['mds_epoch'] = None
+
+
+class CephClusterAgent(MetricsAgent):
+ measurement = 'ceph_cluster'
+
+ def _collect_data(self):
+ # process data and save to 'self.data'
+ obj_api = ClusterAPI(self._module_inst)
+ cluster_id = obj_api.get_cluster_id()
+
+ c_data = CephCluster()
+ cluster_state = obj_api.get_health_status()
+ c_data.tags['cluster_id'] = cluster_id
+ c_data.fields['cluster_health'] = str(cluster_state)
+ c_data.fields['agenthost'] = socket.gethostname()
+ c_data.tags['agenthost_domain_id'] = cluster_id
+ c_data.fields['osd_epoch'] = obj_api.get_osd_epoch()
+ c_data.fields['num_mon'] = len(obj_api.get_mons())
+ c_data.fields['num_mon_quorum'] = \
+ len(obj_api.get_mon_status().get('quorum', []))
+
+ osds = obj_api.get_osds()
+ num_osd_up = 0
+ num_osd_in = 0
+ for osd_data in osds:
+ if osd_data.get('up'):
+ num_osd_up = num_osd_up + 1
+ if osd_data.get('in'):
+ num_osd_in = num_osd_in + 1
+ if osds:
+ c_data.fields['num_osd'] = len(osds)
+ else:
+ c_data.fields['num_osd'] = 0
+ c_data.fields['num_osd_up'] = num_osd_up
+ c_data.fields['num_osd_in'] = num_osd_in
+ c_data.fields['num_pool'] = len(obj_api.get_osd_pools())
+
+ df_stats = obj_api.module.get('df').get('stats', {})
+ total_bytes = df_stats.get('total_bytes', 0)
+ total_used_bytes = df_stats.get('total_used_bytes', 0)
+ total_avail_bytes = df_stats.get('total_avail_bytes', 0)
+ c_data.fields['osd_bytes'] = total_bytes
+ c_data.fields['osd_bytes_used'] = total_used_bytes
+ c_data.fields['osd_bytes_avail'] = total_avail_bytes
+ if total_bytes and total_avail_bytes:
+ c_data.fields['osd_bytes_used_percentage'] = \
+ round((float(total_used_bytes) / float(total_bytes)) * 100, 4)
+ else:
+ c_data.fields['osd_bytes_used_percentage'] = 0.0000
+
+ pg_stats = obj_api.module.get('pg_stats').get('pg_stats', [])
+ num_bytes = 0
+ num_object = 0
+ num_object_degraded = 0
+ num_object_misplaced = 0
+ num_object_unfound = 0
+ num_pg_active = 0
+ num_pg_active_clean = 0
+ num_pg_peering = 0
+ for pg_data in pg_stats:
+ num_pg_active = num_pg_active + len(pg_data.get('acting'))
+ if 'active+clean' in pg_data.get('state'):
+ num_pg_active_clean = num_pg_active_clean + 1
+ if 'peering' in pg_data.get('state'):
+ num_pg_peering = num_pg_peering + 1
+
+ stat_sum = pg_data.get('stat_sum', {})
+ num_object = num_object + stat_sum.get('num_objects', 0)
+ num_object_degraded = \
+ num_object_degraded + stat_sum.get('num_objects_degraded', 0)
+ num_object_misplaced = \
+ num_object_misplaced + stat_sum.get('num_objects_misplaced', 0)
+ num_object_unfound = \
+ num_object_unfound + stat_sum.get('num_objects_unfound', 0)
+ num_bytes = num_bytes + stat_sum.get('num_bytes', 0)
+
+ c_data.fields['num_pg'] = len(pg_stats)
+ c_data.fields['num_object'] = num_object
+ c_data.fields['num_object_degraded'] = num_object_degraded
+ c_data.fields['num_object_misplaced'] = num_object_misplaced
+ c_data.fields['num_object_unfound'] = num_object_unfound
+ c_data.fields['num_bytes'] = num_bytes
+ c_data.fields['num_pg_active'] = num_pg_active
+ c_data.fields['num_pg_active_clean'] = num_pg_active_clean
+ c_data.fields['num_pg_peering'] = num_pg_active_clean
+
+ filesystems = obj_api.get_file_systems()
+ num_mds_in = 0
+ num_mds_up = 0
+ num_mds_failed = 0
+ mds_epoch = 0
+ for fs_data in filesystems:
+ num_mds_in = \
+ num_mds_in + len(fs_data.get('mdsmap', {}).get('in', []))
+ num_mds_up = \
+ num_mds_up + len(fs_data.get('mdsmap', {}).get('up', {}))
+ num_mds_failed = \
+ num_mds_failed + len(fs_data.get('mdsmap', {}).get('failed', []))
+ mds_epoch = mds_epoch + fs_data.get('mdsmap', {}).get('epoch', 0)
+ c_data.fields['num_mds_in'] = num_mds_in
+ c_data.fields['num_mds_up'] = num_mds_up
+ c_data.fields['num_mds_failed'] = num_mds_failed
+ c_data.fields['mds_epoch'] = mds_epoch
+ self.data.append(c_data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_mon_osd.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_mon_osd.py
new file mode 100644
index 00000000..4b4d8fa8
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_mon_osd.py
@@ -0,0 +1,222 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class CephMON(MetricsField):
+ """ Ceph monitor structure """
+ measurement = 'ceph_mon'
+
+ def __init__(self):
+ super(CephMON, self).__init__()
+ self.tags['cluster_id'] = None
+ self.tags['mon_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.fields['num_sessions'] = None
+ self.fields['session_add'] = None
+ self.fields['session_rm'] = None
+ self.fields['session_trim'] = None
+ self.fields['num_elections'] = None
+ self.fields['election_call'] = None
+ self.fields['election_win'] = None
+ self.fields['election_lose'] = None
+
+
+class CephErasureProfile(MetricsField):
+ """ Ceph osd erasure profile """
+ measurement = 'ceph_erasure_profile'
+
+ def __init__(self):
+ super(CephErasureProfile, self).__init__()
+ self.tags['cluster_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['host_domain_id'] = None
+ self.fields['name'] = None
+
+
+class CephOsdTree(MetricsField):
+ """ Ceph osd tree map """
+ measurement = 'ceph_osd_tree'
+
+ def __init__(self):
+ super(CephOsdTree, self).__init__()
+ self.tags['cluster_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['host_domain_id'] = None
+ self.fields['name'] = None
+
+
+class CephOSD(MetricsField):
+ """ Ceph osd structure """
+ measurement = 'ceph_osd'
+
+ def __init__(self):
+ super(CephOSD, self).__init__()
+ self.tags['cluster_id'] = None
+ self.tags['osd_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['host_domain_id'] = None
+ self.fields['op_w'] = None
+ self.fields['op_in_bytes'] = None
+ self.fields['op_r'] = None
+ self.fields['op_out_bytes'] = None
+ self.fields['op_wip'] = None
+ self.fields['op_latency'] = None
+ self.fields['op_process_latency'] = None
+ self.fields['op_r_latency'] = None
+ self.fields['op_r_process_latency'] = None
+ self.fields['op_w_in_bytes'] = None
+ self.fields['op_w_latency'] = None
+ self.fields['op_w_process_latency'] = None
+ self.fields['op_w_prepare_latency'] = None
+ self.fields['op_rw'] = None
+ self.fields['op_rw_in_bytes'] = None
+ self.fields['op_rw_out_bytes'] = None
+ self.fields['op_rw_latency'] = None
+ self.fields['op_rw_process_latency'] = None
+ self.fields['op_rw_prepare_latency'] = None
+ self.fields['op_before_queue_op_lat'] = None
+ self.fields['op_before_dequeue_op_lat'] = None
+
+
+class CephMonOsdAgent(MetricsAgent):
+ measurement = 'ceph_mon_osd'
+
+ # counter types
+ PERFCOUNTER_LONGRUNAVG = 4
+ PERFCOUNTER_COUNTER = 8
+ PERFCOUNTER_HISTOGRAM = 0x10
+ PERFCOUNTER_TYPE_MASK = ~3
+
+ def _stattype_to_str(self, stattype):
+ typeonly = stattype & self.PERFCOUNTER_TYPE_MASK
+ if typeonly == 0:
+ return 'gauge'
+ if typeonly == self.PERFCOUNTER_LONGRUNAVG:
+ # this lie matches the DaemonState decoding: only val, no counts
+ return 'counter'
+ if typeonly == self.PERFCOUNTER_COUNTER:
+ return 'counter'
+ if typeonly == self.PERFCOUNTER_HISTOGRAM:
+ return 'histogram'
+ return ''
+
+ def _generage_osd_erasure_profile(self, cluster_id):
+ obj_api = ClusterAPI(self._module_inst)
+ osd_map = obj_api.module.get('osd_map')
+ if osd_map:
+ for n, n_value in osd_map.get('erasure_code_profiles', {}).items():
+ e_osd = CephErasureProfile()
+ e_osd.fields['name'] = n
+ e_osd.tags['cluster_id'] = cluster_id
+ e_osd.fields['agenthost'] = socket.gethostname()
+ e_osd.tags['agenthost_domain_id'] = cluster_id
+ e_osd.tags['host_domain_id'] = '%s_%s' % (cluster_id, socket.gethostname())
+ for k in n_value.keys():
+ e_osd.fields[k] = str(n_value[k])
+ self.data.append(e_osd)
+
+ def _generate_osd_tree(self, cluster_id):
+ obj_api = ClusterAPI(self._module_inst)
+ osd_tree = obj_api.module.get('osd_map_tree')
+ if osd_tree:
+ for node in osd_tree.get('nodes', []):
+ n_node = CephOsdTree()
+ n_node.tags['cluster_id'] = cluster_id
+ n_node.fields['agenthost'] = socket.gethostname()
+ n_node.tags['agenthost_domain_id'] = cluster_id
+ n_node.tags['host_domain_id'] = '%s_%s' % (cluster_id, socket.gethostname())
+ n_node.fields['children'] = ','.join(str(x) for x in node.get('children', []))
+ n_node.fields['type_id'] = str(node.get('type_id', ''))
+ n_node.fields['id'] = str(node.get('id', ''))
+ n_node.fields['name'] = str(node.get('name', ''))
+ n_node.fields['type'] = str(node.get('type', ''))
+ n_node.fields['reweight'] = float(node.get('reweight', 0.0))
+ n_node.fields['crush_weight'] = float(node.get('crush_weight', 0.0))
+ n_node.fields['primary_affinity'] = float(node.get('primary_affinity', 0.0))
+ n_node.fields['device_class'] = str(node.get('device_class', ''))
+ self.data.append(n_node)
+
+ def _generate_osd(self, cluster_id, service_name, perf_counts):
+ obj_api = ClusterAPI(self._module_inst)
+ service_id = service_name[4:]
+ d_osd = CephOSD()
+ stat_bytes = 0
+ stat_bytes_used = 0
+ d_osd.tags['cluster_id'] = cluster_id
+ d_osd.tags['osd_id'] = service_name[4:]
+ d_osd.fields['agenthost'] = socket.gethostname()
+ d_osd.tags['agenthost_domain_id'] = cluster_id
+ d_osd.tags['host_domain_id'] = \
+ '%s_%s' % (cluster_id,
+ obj_api.get_osd_hostname(d_osd.tags['osd_id']))
+
+ for i_key, i_val in perf_counts.items():
+ if i_key[:4] == 'osd.':
+ key_name = i_key[4:]
+ else:
+ key_name = i_key
+ if self._stattype_to_str(i_val['type']) == 'counter':
+ value = obj_api.get_rate('osd', service_id, i_key)
+ else:
+ value = obj_api.get_latest('osd', service_id, i_key)
+ if key_name == 'stat_bytes':
+ stat_bytes = value
+ elif key_name == 'stat_bytes_used':
+ stat_bytes_used = value
+ else:
+ d_osd.fields[key_name] = float(value)
+
+ if stat_bytes and stat_bytes_used:
+ d_osd.fields['stat_bytes_used_percentage'] = \
+ round((float(stat_bytes_used) / float(stat_bytes)) * 100, 4)
+ else:
+ d_osd.fields['stat_bytes_used_percentage'] = 0.0000
+ self.data.append(d_osd)
+
+ def _generate_mon(self, cluster_id, service_name, perf_counts):
+ d_mon = CephMON()
+ d_mon.tags['cluster_id'] = cluster_id
+ d_mon.tags['mon_id'] = service_name[4:]
+ d_mon.fields['agenthost'] = socket.gethostname()
+ d_mon.tags['agenthost_domain_id'] = cluster_id
+ d_mon.fields['num_sessions'] = \
+ perf_counts.get('mon.num_sessions', {}).get('value', 0)
+ d_mon.fields['session_add'] = \
+ perf_counts.get('mon.session_add', {}).get('value', 0)
+ d_mon.fields['session_rm'] = \
+ perf_counts.get('mon.session_rm', {}).get('value', 0)
+ d_mon.fields['session_trim'] = \
+ perf_counts.get('mon.session_trim', {}).get('value', 0)
+ d_mon.fields['num_elections'] = \
+ perf_counts.get('mon.num_elections', {}).get('value', 0)
+ d_mon.fields['election_call'] = \
+ perf_counts.get('mon.election_call', {}).get('value', 0)
+ d_mon.fields['election_win'] = \
+ perf_counts.get('mon.election_win', {}).get('value', 0)
+ d_mon.fields['election_lose'] = \
+ perf_counts.get('election_lose', {}).get('value', 0)
+ self.data.append(d_mon)
+
+ def _collect_data(self):
+ # process data and save to 'self.data'
+ obj_api = ClusterAPI(self._module_inst)
+ perf_data = obj_api.module.get_all_perf_counters(services=('mon', 'osd'))
+ if not perf_data and not isinstance(perf_data, dict):
+ self._logger.error('unable to get all perf counters')
+ return
+ cluster_id = obj_api.get_cluster_id()
+ for n_name, i_perf in perf_data.items():
+ if n_name[0:3].lower() == 'mon':
+ self._generate_mon(cluster_id, n_name, i_perf)
+ elif n_name[0:3].lower() == 'osd':
+ self._generate_osd(cluster_id, n_name, i_perf)
+ self._generage_osd_erasure_profile(cluster_id)
+ self._generate_osd_tree(cluster_id)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_pool.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_pool.py
new file mode 100644
index 00000000..e8b39566
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/ceph_pool.py
@@ -0,0 +1,57 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class CephPool(MetricsField):
+ """ Ceph pool structure """
+ measurement = 'ceph_pool'
+
+ def __init__(self):
+ super(CephPool, self).__init__()
+ self.tags['cluster_id'] = None
+ self.tags['pool_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.fields['bytes_used'] = None
+ self.fields['max_avail'] = None
+ self.fields['objects'] = None
+ self.fields['wr_bytes'] = None
+ self.fields['dirty'] = None
+ self.fields['rd_bytes'] = None
+ self.fields['stored_raw'] = None
+
+
+class CephPoolAgent(MetricsAgent):
+ measurement = 'ceph_pool'
+
+ def _collect_data(self):
+ # process data and save to 'self.data'
+ obj_api = ClusterAPI(self._module_inst)
+ df_data = obj_api.module.get('df')
+ cluster_id = obj_api.get_cluster_id()
+ for pool in df_data.get('pools', []):
+ d_pool = CephPool()
+ p_id = pool.get('id')
+ d_pool.tags['cluster_id'] = cluster_id
+ d_pool.tags['pool_id'] = p_id
+ d_pool.fields['agenthost'] = socket.gethostname()
+ d_pool.tags['agenthost_domain_id'] = cluster_id
+ d_pool.fields['bytes_used'] = \
+ pool.get('stats', {}).get('bytes_used', 0)
+ d_pool.fields['max_avail'] = \
+ pool.get('stats', {}).get('max_avail', 0)
+ d_pool.fields['objects'] = \
+ pool.get('stats', {}).get('objects', 0)
+ d_pool.fields['wr_bytes'] = \
+ pool.get('stats', {}).get('wr_bytes', 0)
+ d_pool.fields['dirty'] = \
+ pool.get('stats', {}).get('dirty', 0)
+ d_pool.fields['rd_bytes'] = \
+ pool.get('stats', {}).get('rd_bytes', 0)
+ d_pool.fields['stored_raw'] = \
+ pool.get('stats', {}).get('stored_raw', 0)
+ self.data.append(d_pool)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/db_relay.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/db_relay.py
new file mode 100644
index 00000000..2f5d60db
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/db_relay.py
@@ -0,0 +1,703 @@
+from __future__ import absolute_import
+
+import re
+import socket
+
+from . import MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+from ...common.cypher import CypherOP, NodeInfo
+
+
+class BaseDP(object):
+ """ basic diskprediction structure """
+ _fields = []
+
+ def __init__(self, *args, **kwargs):
+ if len(args) > len(self._fields):
+ raise TypeError('Expected {} arguments'.format(len(self._fields)))
+
+ for name, value in zip(self._fields, args):
+ setattr(self, name, value)
+
+ for name in self._fields[len(args):]:
+ setattr(self, name, kwargs.pop(name))
+
+ if kwargs:
+ raise TypeError('Invalid argument(s): {}'.format(','.join(kwargs)))
+
+
+class MGRDpCeph(BaseDP):
+ _fields = [
+ 'fsid', 'health', 'max_osd', 'size',
+ 'avail_size', 'raw_used', 'raw_used_percent'
+ ]
+
+
+class MGRDpHost(BaseDP):
+ _fields = ['fsid', 'host', 'ipaddr']
+
+
+class MGRDpMon(BaseDP):
+ _fields = ['fsid', 'host', 'ipaddr']
+
+
+class MGRDpOsd(BaseDP):
+ _fields = [
+ 'fsid', 'host', '_id', 'uuid', 'up', '_in', 'weight', 'public_addr',
+ 'cluster_addr', 'state', 'ceph_release', 'osd_devices', 'rotational'
+ ]
+
+
+class MGRDpMds(BaseDP):
+ _fields = ['fsid', 'host', 'ipaddr']
+
+
+class MGRDpPool(BaseDP):
+ _fields = [
+ 'fsid', 'size', 'pool_name', 'pool_id', 'type', 'min_size',
+ 'pg_num', 'pgp_num', 'created_time', 'pgids', 'osd_ids', 'tiers', 'cache_mode',
+ 'erasure_code_profile', 'tier_of'
+ ]
+
+
+class MGRDpRBD(BaseDP):
+ _fields = ['fsid', '_id', 'name', 'pool_name', 'pool_id']
+
+
+class MGRDpFS(BaseDP):
+ _fields = ['fsid', '_id', 'name', 'metadata_pool', 'data_pools', 'mds_nodes']
+
+
+class MGRDpPG(BaseDP):
+ _fields = [
+ 'fsid', 'pgid', 'up_osds', 'acting_osds', 'state',
+ 'objects', 'degraded', 'misplaced', 'unfound'
+ ]
+
+
+class MGRDpDisk(BaseDP):
+ _fields = ['host_domain_id', 'host', 'fs_journal_osd', 'bs_db_osd', 'bs_wal_osd', 'data_osd', 'osd_ids']
+
+
+class DBRelay(MetricsField):
+ """ DB Relay structure """
+ measurement = 'db_relay'
+
+ def __init__(self):
+ super(DBRelay, self).__init__()
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['dc_tag'] = 'na'
+ self.tags['host'] = None
+ self.fields['cmd'] = None
+
+
+class DBRelayAgent(MetricsAgent):
+ measurement = 'db_relay'
+
+ def __init__(self, *args, **kwargs):
+ super(DBRelayAgent, self).__init__(*args, **kwargs)
+ self._cluster_node = None
+ self._cluster_id = None
+ self._ceph = ClusterAPI(self._module_inst)
+ self._osd_maps = self._ceph.module.get('osd_map')
+ self._mon_maps = self._ceph.module.get('mon_map')
+ self._fs_maps = self._ceph.module.get('fs_map')
+ self._osd_metadata = self._ceph.module.get('osd_metadata')
+ self._host_nodes = dict()
+ self._osd_nodes = dict()
+ self._mon_nodes = dict()
+ self._mds_nodes = dict()
+ self._dev_nodes = dict()
+ self._pool_nodes = dict()
+ self._rbd_nodes = dict()
+ self._fs_nodes = dict()
+ # initial ceph all node states
+ self._init_cluster_node()
+ self._init_hosts()
+ self._init_mons()
+ self._init_mds()
+ self._init_osds()
+ self._init_devices()
+ self._init_pools()
+ self._init_rbds()
+ self._init_fs()
+
+ def _init_hosts(self):
+ hosts = set()
+ # Add host from osd
+ osd_data = self._osd_maps.get('osds', [])
+ for _data in osd_data:
+ osd_id = _data['osd']
+ if not _data.get('in'):
+ continue
+ osd_addr = _data['public_addr'].split(':')[0]
+ osd_metadata = self._ceph.get_osd_metadata(osd_id)
+ if osd_metadata:
+ osd_host = osd_metadata['hostname']
+ hosts.add((osd_host, osd_addr))
+
+ # Add host from mon
+ mons = self._mon_maps.get('mons', [])
+ for _data in mons:
+ mon_host = _data['name']
+ mon_addr = _data['public_addr'].split(':')[0]
+ if mon_host:
+ hosts.add((mon_host, mon_addr))
+
+ # Add host from mds
+ file_systems = self._fs_maps.get('filesystems', [])
+ for _data in file_systems:
+ mds_info = _data.get('mdsmap').get('info')
+ for _gid in mds_info:
+ mds_data = mds_info[_gid]
+ mds_addr = mds_data.get('addr').split(':')[0]
+ mds_host = mds_data.get('name')
+ if mds_host:
+ hosts.add((mds_host, mds_addr))
+ for tp in hosts:
+ host = tp[0]
+ self._host_nodes[host] = None
+
+ host_node = NodeInfo(
+ label='VMHost',
+ domain_id='{}_{}'.format(self._cluster_id, host),
+ name=host,
+ meta={}
+ )
+ self._host_nodes[host] = host_node
+
+ def _init_mons(self):
+ cluster_id = self._cluster_id
+ mons = self._mon_maps.get('mons')
+ for mon in mons:
+ mon_name = mon.get('name', '')
+ mon_addr = mon.get('addr', '').split(':')[0]
+ if mon_name not in self._host_nodes.keys():
+ continue
+
+ dp_mon = MGRDpMon(
+ fsid=cluster_id,
+ host=mon_name,
+ ipaddr=mon_addr
+ )
+
+ # create mon node
+ mon_node = NodeInfo(
+ label='CephMon',
+ domain_id='{}.mon.{}'.format(cluster_id, mon_name),
+ name=mon_name,
+ meta=dp_mon.__dict__
+ )
+ self._mon_nodes[mon_name] = mon_node
+
+ def _init_mds(self):
+ cluster_id = self._cluster_id
+ file_systems = self._fs_maps.get('filesystems', [])
+ for _data in file_systems:
+ mds_info = _data.get('mdsmap').get('info')
+ for _gid in mds_info:
+ mds_data = mds_info[_gid]
+ mds_addr = mds_data.get('addr').split(':')[0]
+ mds_host = mds_data.get('name')
+ mds_gid = mds_data.get('gid')
+
+ if mds_host not in self._host_nodes:
+ continue
+
+ dp_mds = MGRDpMds(
+ fsid=cluster_id,
+ host=mds_host,
+ ipaddr=mds_addr
+ )
+
+ # create osd node
+ mds_node = NodeInfo(
+ label='CephMds',
+ domain_id='{}.mds.{}'.format(cluster_id, mds_gid),
+ name='MDS.{}'.format(mds_gid),
+ meta=dp_mds.__dict__
+ )
+ self._mds_nodes[mds_host] = mds_node
+
+ def _init_osds(self):
+ for osd in self._osd_maps.get('osds', []):
+ osd_id = osd.get('osd', -1)
+ meta = self._osd_metadata.get(str(osd_id), {})
+ osd_host = meta['hostname']
+ osd_ceph_version = meta['ceph_version']
+ osd_rotational = meta['rotational']
+ osd_devices = meta['devices'].split(',')
+
+ # filter 'dm' device.
+ devices = []
+ for devname in osd_devices:
+ if 'dm' in devname:
+ continue
+ devices.append(devname)
+
+ if osd_host not in self._host_nodes.keys():
+ continue
+ self._osd_nodes[str(osd_id)] = None
+ public_addr = []
+ cluster_addr = []
+ for addr in osd.get('public_addrs', {}).get('addrvec', []):
+ public_addr.append(addr.get('addr'))
+ for addr in osd.get('cluster_addrs', {}).get('addrvec', []):
+ cluster_addr.append(addr.get('addr'))
+ dp_osd = MGRDpOsd(
+ fsid=self._cluster_id,
+ host=osd_host,
+ _id=osd_id,
+ uuid=osd.get('uuid'),
+ up=osd.get('up'),
+ _in=osd.get('in'),
+ weight=osd.get('weight'),
+ public_addr=','.join(public_addr),
+ cluster_addr=','.join(cluster_addr),
+ state=','.join(osd.get('state', [])),
+ ceph_release=osd_ceph_version,
+ osd_devices=','.join(devices),
+ rotational=osd_rotational)
+ for k, v in meta.items():
+ setattr(dp_osd, k, v)
+
+ # create osd node
+ osd_node = NodeInfo(
+ label='CephOsd',
+ domain_id='{}.osd.{}'.format(self._cluster_id, osd_id),
+ name='OSD.{}'.format(osd_id),
+ meta=dp_osd.__dict__
+ )
+ self._osd_nodes[str(osd_id)] = osd_node
+
+ def _init_devices(self):
+ r = re.compile('[^/dev]\D+')
+ for osdid, o_val in self._osd_nodes.items():
+ o_devs = o_val.meta.get('device_ids', '').split(',')
+ # fs_store
+ journal_devs = o_val.meta.get('backend_filestore_journal_dev_node', '').split(',')
+ # bs_store
+ bs_db_devs = o_val.meta.get('bluefs_db_dev_node', '').split(',')
+ bs_wal_devs = o_val.meta.get('bluefs_wal_dev_node', '').split(',')
+
+ for dev in o_devs:
+ fs_journal = []
+ bs_db = []
+ bs_wal = []
+ data = []
+ if len(dev.split('=')) != 2:
+ continue
+ dev_name = dev.split('=')[0]
+ dev_id = dev.split('=')[1]
+ if not dev_id:
+ continue
+
+ for j_dev in journal_devs:
+ if dev_name == ''.join(r.findall(j_dev)):
+ fs_journal.append(osdid)
+ for db_dev in bs_db_devs:
+ if dev_name == ''.join(r.findall(db_dev)):
+ bs_db.append(osdid)
+ for wal_dev in bs_wal_devs:
+ if dev_name == ''.join(r.findall(wal_dev)):
+ bs_wal.append(osdid)
+
+ if not fs_journal and not bs_db and not bs_wal:
+ data.append(osdid)
+
+ disk_domain_id = dev_id
+ if disk_domain_id not in self._dev_nodes.keys():
+ dp_disk = MGRDpDisk(
+ host_domain_id='{}_{}'.format(self._cluster_id, o_val.meta.get('host')),
+ host=o_val.meta.get('host'),
+ osd_ids=osdid,
+ fs_journal_osd=','.join(str(x) for x in fs_journal) if fs_journal else '',
+ bs_db_osd=','.join(str(x) for x in bs_db) if bs_db else '',
+ bs_wal_osd=','.join(str(x) for x in bs_wal) if bs_wal else '',
+ data_osd=','.join(str(x) for x in data) if data else ''
+ )
+ # create disk node
+ disk_node = NodeInfo(
+ label='VMDisk',
+ domain_id=disk_domain_id,
+ name=dev_name,
+ meta=dp_disk.__dict__
+ )
+ self._dev_nodes[disk_domain_id] = disk_node
+ else:
+ dev_node = self._dev_nodes[disk_domain_id]
+ osd_ids = dev_node.meta.get('osd_ids', '')
+ if osdid not in osd_ids.split(','):
+ arr_value = osd_ids.split(',')
+ arr_value.append(str(osdid))
+ dev_node.meta['osd_ids'] = ','.join(arr_value)
+ if fs_journal:
+ arr_value = None
+ for t in fs_journal:
+ value = dev_node.meta.get('fs_journal_osd', '')
+ if value:
+ arr_value = value.split(',')
+ else:
+ arr_value = []
+ if t not in arr_value:
+ arr_value.append(t)
+ if arr_value:
+ dev_node.meta['fs_journal_osd'] = ','.join(str(x) for x in arr_value)
+ if bs_db:
+ arr_value = None
+ for t in bs_db:
+ value = dev_node.meta.get('bs_db_osd', '')
+ if value:
+ arr_value = value.split(',')
+ else:
+ arr_value = []
+ if t not in arr_value:
+ arr_value.append(t)
+ if arr_value:
+ dev_node.meta['bs_db_osd'] = ','.join(str(x) for x in arr_value)
+ if bs_wal:
+ arr_value = None
+ for t in bs_wal:
+ value = dev_node.meta.get('bs_wal_osd', '')
+ if value:
+ arr_value = value.split(',')
+ else:
+ arr_value = []
+ if t not in arr_value:
+ arr_value.append(t)
+ if arr_value:
+ dev_node.meta['bs_wal_osd'] = ','.join(str(x) for x in arr_value)
+ if data:
+ arr_value = None
+ for t in data:
+ value = dev_node.meta.get('data_osd', '')
+ if value:
+ arr_value = value.split(',')
+ else:
+ arr_value = []
+ if t not in arr_value:
+ arr_value.append(t)
+ if arr_value:
+ dev_node.meta['data_osd'] = ','.join(str(x) for x in arr_value)
+
+ def _init_cluster_node(self):
+ cluster_id = self._ceph.get_cluster_id()
+ ceph_df_stat = self._ceph.get_ceph_df_state()
+ dp_cluster = MGRDpCeph(
+ fsid=cluster_id,
+ health=self._ceph.get_health_status(),
+ max_osd=len(self._ceph.get_osds()),
+ size=ceph_df_stat.get('total_size'),
+ avail_size=ceph_df_stat.get('avail_size'),
+ raw_used=ceph_df_stat.get('raw_used_size'),
+ raw_used_percent=ceph_df_stat.get('used_percent')
+ )
+ cluster_name = cluster_id[-12:]
+ cluster_node = NodeInfo(
+ label='CephCluster',
+ domain_id=cluster_id,
+ name='cluster-{}'.format(cluster_name),
+ meta=dp_cluster.__dict__
+ )
+ self._cluster_id = cluster_id
+ self._cluster_node = cluster_node
+
+ def _init_pools(self):
+ pools = self._osd_maps.get('pools', [])
+ cluster_id = self._cluster_id
+ for pool in pools:
+ osds = []
+ pgs = self._ceph.get_pgs_up_by_poolid(int(pool.get('pool', -1)))
+ for pg_id, osd_id in pgs.items():
+ for o_id in osd_id:
+ if o_id not in osds:
+ osds.append(str(o_id))
+ dp_pool = MGRDpPool(
+ fsid=cluster_id,
+ size=pool.get('size'),
+ pool_name=pool.get('pool_name'),
+ pool_id=pool.get('pool'),
+ type=pool.get('type'),
+ min_size=pool.get('min_szie'),
+ pg_num=pool.get('pg_num'),
+ pgp_num=pool.get('pg_placement_num'),
+ created_time=pool.get('create_time'),
+ pgids=','.join(pgs.keys()),
+ osd_ids=','.join(osds),
+ tiers=','.join(str(x) for x in pool.get('tiers', [])),
+ cache_mode=pool.get('cache_mode', ''),
+ erasure_code_profile=str(pool.get('erasure_code_profile', '')),
+ tier_of=str(pool.get('tier_of', -1)))
+ # create pool node
+ pool_node = NodeInfo(
+ label='CephPool',
+ domain_id='{}_pool_{}'.format(cluster_id, pool.get('pool')),
+ name=pool.get('pool_name'),
+ meta=dp_pool.__dict__
+ )
+ self._pool_nodes[str(pool.get('pool'))] = pool_node
+
+ def _init_rbds(self):
+ cluster_id = self._cluster_id
+ for p_id, p_node in self._pool_nodes.items():
+ rbds = self._ceph.get_rbd_list(p_node.name)
+ self._rbd_nodes[str(p_id)] = []
+ for rbd in rbds:
+ dp_rbd = MGRDpRBD(
+ fsid=cluster_id,
+ _id=rbd['id'],
+ name=rbd['name'],
+ pool_name=rbd['pool_name'],
+ pool_id=p_id,
+ )
+ # create pool node
+ rbd_node = NodeInfo(
+ label='CephRBD',
+ domain_id='{}_rbd_{}'.format(cluster_id, rbd['id']),
+ name=rbd['name'],
+ meta=dp_rbd.__dict__,
+ )
+ self._rbd_nodes[str(p_id)].append(rbd_node)
+
+ def _init_fs(self):
+ # _fields = ['fsid', '_id', 'name', 'metadata_pool', 'data_pool', 'mds_nodes']
+ cluster_id = self._cluster_id
+ file_systems = self._fs_maps.get('filesystems', [])
+ for fs in file_systems:
+ mdsmap = fs.get('mdsmap', {})
+ mds_hostnames = []
+ for m, md in mdsmap.get('info', {}).items():
+ if md.get('name') not in mds_hostnames:
+ mds_hostnames.append(md.get('name'))
+ dp_fs = MGRDpFS(
+ fsid=cluster_id,
+ _id=fs.get('id'),
+ name=mdsmap.get('fs_name'),
+ metadata_pool=str(mdsmap.get('metadata_pool', -1)),
+ data_pools=','.join(str(i) for i in mdsmap.get('data_pools', [])),
+ mds_nodes=','.join(mds_hostnames),
+ )
+ fs_node = NodeInfo(
+ label='CephFS',
+ domain_id='{}_fs_{}'.format(cluster_id, fs.get('id')),
+ name=mdsmap.get('fs_name'),
+ meta=dp_fs.__dict__,
+ )
+ self._fs_nodes[str(fs.get('id'))] = fs_node
+
+ def _cluster_contains_host(self):
+ cluster_id = self._cluster_id
+ cluster_node = self._cluster_node
+
+ # create node relation
+ for h_id, h_node in self._host_nodes.items():
+ data = DBRelay()
+ # add osd node relationship
+ cypher_cmd = CypherOP.add_link(
+ cluster_node,
+ h_node,
+ 'CephClusterContainsHost'
+ )
+ cluster_host = socket.gethostname()
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _host_contains_mon(self):
+ for m_name, m_node in self._mon_nodes.items():
+ host_node = self._host_nodes.get(m_name)
+ if not host_node:
+ continue
+ data = DBRelay()
+ # add mon node relationship
+ cypher_cmd = CypherOP.add_link(
+ host_node,
+ m_node,
+ 'HostContainsMon'
+ )
+ cluster_host = socket.gethostname()
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = self._cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _host_contains_osd(self):
+ cluster_id = self._cluster_id
+ for o_id, o_node in self._osd_nodes.items():
+ host_node = self._host_nodes.get(o_node.meta.get('host'))
+ if not host_node:
+ continue
+ data = DBRelay()
+ # add osd node relationship
+ cypher_cmd = CypherOP.add_link(
+ host_node,
+ o_node,
+ 'HostContainsOsd'
+ )
+ cluster_host = socket.gethostname()
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id, data
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _host_contains_mds(self):
+ cluster_id = self._cluster_id
+ for m_name, mds_node in self._mds_nodes.items():
+ data = DBRelay()
+ host_node = self._host_nodes.get(mds_node.meta.get('host'))
+ if not host_node:
+ continue
+ # add osd node relationship
+ cypher_cmd = CypherOP.add_link(
+ host_node,
+ mds_node,
+ 'HostContainsMds'
+ )
+ cluster_host = socket.gethostname()
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _osd_contains_disk(self):
+ cluster_id = self._cluster_id
+ cluster_host = socket.gethostname()
+ for d_name, d_node in self._dev_nodes.items():
+ keys = {'data_osd': 'DataDiskOfOSD',
+ 'fs_journal_osd': 'FsJournalDiskOfOSD',
+ 'bs_db_osd': 'BsDBDiskOfOSD',
+ 'bs_wal_osd': 'BsWalDiskOfOSD'}
+ for k, v in keys.items():
+ if not d_node.meta.get(k):
+ continue
+ for osdid in d_node.meta.get(k, '').split(','):
+ data = DBRelay()
+ osd_node = self._osd_nodes.get(str(osdid))
+ if not osd_node:
+ continue
+ # add disk node relationship
+ cypher_cmd = CypherOP.add_link(
+ osd_node,
+ d_node,
+ v)
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ hostname = d_node.meta.get('host', '')
+ if not hostname:
+ continue
+ host_node = self._host_nodes.get(hostname)
+ if not host_node:
+ continue
+ # add osd node relationship
+ data = DBRelay()
+ cypher_cmd = CypherOP.add_link(
+ host_node,
+ d_node,
+ 'VmHostContainsVmDisk'
+ )
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _pool_contains_osd(self):
+ cluster_id = self._cluster_id
+ cluster_host = socket.gethostname()
+ for p_id, p_node in self._pool_nodes.items():
+ for o_id in p_node.meta.get('osd_ids', '').split(','):
+ osd_node = self._osd_nodes.get(str(o_id))
+ if not osd_node:
+ continue
+ data = DBRelay()
+ cypher_cmd = CypherOP.add_link(
+ osd_node,
+ p_node,
+ 'OsdContainsPool'
+ )
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _pool_contains_rbd(self):
+ cluster_id = self._cluster_id
+ cluster_host = socket.gethostname()
+ for p_id, p_node in self._pool_nodes.items():
+ for rbd_node in self._rbd_nodes.get(str(p_id), []):
+ if not rbd_node:
+ continue
+ data = DBRelay()
+ cypher_cmd = CypherOP.add_link(
+ p_node,
+ rbd_node,
+ 'PoolContainsRBD'
+ )
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _pool_contains_fs(self):
+ cluster_id = self._cluster_id
+ cluster_host = socket.gethostname()
+ for fs_id, fs_node in self._fs_nodes.items():
+ pool_attrs = ['metadata_pool', 'data_pools']
+ for p_attr in pool_attrs:
+ pools_id = fs_node.meta.get(p_attr).split(',')
+ for p_id in pools_id:
+ p_node = self._pool_nodes.get(str(p_id))
+ if p_node:
+ data = DBRelay()
+ cypher_cmd = CypherOP.add_link(
+ p_node,
+ fs_node,
+ 'MetadataPoolContainsFS' if p_attr == 'metadata_pool' else 'DataPoolContainsFS'
+ )
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+ for mds_name in fs_node.meta.get('mds_nodes', '').split(','):
+ mds_node = self._mds_nodes.get(mds_name)
+ if not mds_node:
+ continue
+ data = DBRelay()
+ cypher_cmd = CypherOP.add_link(
+ mds_node,
+ fs_node,
+ 'MDSContainsFS'
+ )
+ data.fields['agenthost'] = cluster_host
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['host'] = cluster_host
+ data.fields['cmd'] = str(cypher_cmd)
+ self.data.append(data)
+
+ def _collect_data(self):
+ if not self._module_inst:
+ return
+ job_name = ['cluster_contains_host', 'host_contains_mon', 'host_contains_mds', 'host_contains_osd', 'osd_contains_disk',
+ 'pool_contains_osd', 'pool_contains_rbd', 'pool_contains_fs']
+ for job in job_name:
+ fn = getattr(self, '_%s' % job)
+ if not fn:
+ continue
+ try:
+ fn()
+ except Exception as e:
+ self._module_inst.log.error('dbrelay - execute function {} fail, due to {}'.format(job, str(e)))
+ continue
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_agent.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_agent.py
new file mode 100644
index 00000000..81fbdf96
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_agent.py
@@ -0,0 +1,70 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+from __future__ import absolute_import
+
+import socket
+import time
+
+from . import AGENT_VERSION, MetricsAgent, MetricsField
+from ...common import DP_MGR_STAT_FAILED, DP_MGR_STAT_WARNING
+from ...common.clusterdata import ClusterAPI
+
+
+class SAIAgentFields(MetricsField):
+ """ SAI DiskSmart structure """
+ measurement = 'sai_agent'
+
+ def __init__(self):
+ super(SAIAgentFields, self).__init__()
+ self.tags['agenthost_domain_id'] = None
+ self.fields['agent_type'] = str('ceph')
+ self.fields['agent_version'] = str(AGENT_VERSION)
+ self.fields['agenthost'] = ''
+ self.fields['cluster_domain_id'] = ''
+ self.fields['heartbeat_interval'] = ''
+ self.fields['host_ip'] = ''
+ self.fields['host_name'] = ''
+ self.fields['is_error'] = False
+ self.fields['is_ceph_error'] = False
+ self.fields['needs_warning'] = False
+ self.fields['send'] = None
+
+
+class SAIAgent(MetricsAgent):
+ measurement = 'sai_agent'
+
+ def _collect_data(self):
+ mgr_id = []
+ c_data = SAIAgentFields()
+ obj_api = ClusterAPI(self._module_inst)
+ svc_data = obj_api.get_server(socket.gethostname())
+ cluster_state = obj_api.get_health_status()
+ if not svc_data:
+ raise Exception('unable to get %s service info' % socket.gethostname())
+ # Filter mgr id
+ for s in svc_data.get('services', []):
+ if s.get('type', '') == 'mgr':
+ mgr_id.append(s.get('id'))
+
+ for _id in mgr_id:
+ mgr_meta = obj_api.get_mgr_metadata(_id)
+ cluster_id = obj_api.get_cluster_id()
+ c_data.fields['cluster_domain_id'] = str(cluster_id)
+ c_data.fields['agenthost'] = str(socket.gethostname())
+ c_data.tags['agenthost_domain_id'] = cluster_id
+ c_data.fields['heartbeat_interval'] = \
+ int(obj_api.get_configuration('diskprediction_upload_metrics_interval'))
+ c_data.fields['host_ip'] = str(mgr_meta.get('addr', '127.0.0.1'))
+ c_data.fields['host_name'] = str(socket.gethostname())
+ if obj_api.module.status.get('status', '') in [DP_MGR_STAT_WARNING, DP_MGR_STAT_FAILED]:
+ c_data.fields['is_error'] = bool(True)
+ else:
+ c_data.fields['is_error'] = bool(False)
+ if cluster_state in ['HEALTH_ERR', 'HEALTH_WARN']:
+ c_data.fields['is_ceph_error'] = bool(True)
+ c_data.fields['needs_warning'] = bool(True)
+ c_data.fields['is_error'] = bool(True)
+ c_data.fields['problems'] = str(obj_api.get_health_checks())
+ else:
+ c_data.fields['is_ceph_error'] = bool(False)
+ c_data.fields['send'] = int(time.time() * 1000)
+ self.data.append(c_data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_cluster.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_cluster.py
new file mode 100644
index 00000000..d444f9a2
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_cluster.py
@@ -0,0 +1,35 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import AGENT_VERSION, MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class SAIClusterFields(MetricsField):
+ """ SAI Host structure """
+ measurement = 'sai_cluster'
+
+ def __init__(self):
+ super(SAIClusterFields, self).__init__()
+ self.tags['domain_id'] = None
+ self.fields['agenthost'] = None
+ self.fields['agenthost_domain_id'] = None
+ self.fields['name'] = None
+ self.fields['agent_version'] = str(AGENT_VERSION)
+
+
+class SAICluserAgent(MetricsAgent):
+ measurement = 'sai_cluster'
+
+ def _collect_data(self):
+ c_data = SAIClusterFields()
+ obj_api = ClusterAPI(self._module_inst)
+ cluster_id = obj_api.get_cluster_id()
+
+ c_data.tags['domain_id'] = str(cluster_id)
+ c_data.tags['host_domain_id'] = '%s_%s' % (str(cluster_id), str(socket.gethostname()))
+ c_data.fields['agenthost'] = str(socket.gethostname())
+ c_data.tags['agenthost_domain_id'] = cluster_id
+ c_data.fields['name'] = 'Ceph mgr plugin'
+ self.data.append(c_data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk.py
new file mode 100644
index 00000000..3b177e69
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk.py
@@ -0,0 +1,175 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import AGENT_VERSION, MetricsAgent, MetricsField
+from ...common import get_human_readable
+from ...common.clusterdata import ClusterAPI
+
+
+class SAIDiskFields(MetricsField):
+ """ SAI Disk structure """
+ measurement = 'sai_disk'
+
+ def __init__(self):
+ super(SAIDiskFields, self).__init__()
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['disk_domain_id'] = None
+ self.tags['disk_name'] = None
+ self.tags['disk_wwn'] = None
+ self.tags['primary_key'] = None
+ self.fields['cluster_domain_id'] = None
+ self.fields['host_domain_id'] = None
+ self.fields['model'] = None
+ self.fields['serial_number'] = None
+ self.fields['size'] = None
+ self.fields['vendor'] = None
+ self.fields['agent_version'] = str(AGENT_VERSION)
+
+ """disk_status
+ 0: unknown 1: good 2: failure
+ """
+ self.fields['disk_status'] = 0
+
+ """disk_type
+ 0: unknown 1: HDD 2: SSD 3: SSD NVME
+ 4: SSD SAS 5: SSD SATA 6: HDD SAS 7: HDD SATA
+ """
+ self.fields['disk_type'] = 0
+
+
+class SAIDiskAgent(MetricsAgent):
+ measurement = 'sai_disk'
+
+ @staticmethod
+ def _convert_disk_type(is_ssd, sata_version, protocol):
+ """ return type:
+ 0: "Unknown', 1: 'HDD',
+ 2: 'SSD", 3: "SSD NVME",
+ 4: "SSD SAS", 5: "SSD SATA",
+ 6: "HDD SAS", 7: "HDD SATA"
+ """
+ if is_ssd:
+ if sata_version and not protocol:
+ disk_type = 5
+ elif 'SCSI'.lower() in protocol.lower():
+ disk_type = 4
+ elif 'NVMe'.lower() in protocol.lower():
+ disk_type = 3
+ else:
+ disk_type = 2
+ else:
+ if sata_version and not protocol:
+ disk_type = 7
+ elif 'SCSI'.lower() in protocol.lower():
+ disk_type = 6
+ else:
+ disk_type = 1
+ return disk_type
+
+ def _collect_data(self):
+ # process data and save to 'self.data'
+ obj_api = ClusterAPI(self._module_inst)
+ cluster_id = obj_api.get_cluster_id()
+ osds = obj_api.get_osds()
+ for osd in osds:
+ if osd.get('osd') is None:
+ continue
+ if not osd.get('in'):
+ continue
+ osds_meta = obj_api.get_osd_metadata(osd.get('osd'))
+ if not osds_meta:
+ continue
+ osds_smart = obj_api.get_osd_smart(osd.get('osd'))
+ if not osds_smart:
+ continue
+ for dev_name, s_val in osds_smart.items():
+ d_data = SAIDiskFields()
+ d_data.tags['disk_name'] = str(dev_name)
+ d_data.fields['cluster_domain_id'] = str(cluster_id)
+ d_data.tags['host_domain_id'] = \
+ str('%s_%s'
+ % (cluster_id, osds_meta.get('hostname', 'None')))
+ d_data.fields['agenthost'] = str(socket.gethostname())
+ d_data.tags['agenthost_domain_id'] = cluster_id
+ serial_number = s_val.get('serial_number')
+ wwn = s_val.get('wwn', {})
+ wwpn = ''
+ if wwn:
+ wwpn = '%06X%X' % (wwn.get('oui', 0), wwn.get('id', 0))
+ for k in wwn.keys():
+ if k in ['naa', 't10', 'eui', 'iqn']:
+ wwpn = ('%X%s' % (wwn[k], wwpn)).lower()
+ break
+
+ if wwpn:
+ d_data.tags['disk_domain_id'] = str(dev_name)
+ d_data.tags['disk_wwn'] = str(wwpn)
+ if serial_number:
+ d_data.fields['serial_number'] = str(serial_number)
+ else:
+ d_data.fields['serial_number'] = str(wwpn)
+ elif serial_number:
+ d_data.tags['disk_domain_id'] = str(dev_name)
+ d_data.fields['serial_number'] = str(serial_number)
+ if wwpn:
+ d_data.tags['disk_wwn'] = str(wwpn)
+ else:
+ d_data.tags['disk_wwn'] = str(serial_number)
+ else:
+ d_data.tags['disk_domain_id'] = str(dev_name)
+ d_data.tags['disk_wwn'] = str(dev_name)
+ d_data.fields['serial_number'] = str(dev_name)
+ d_data.tags['primary_key'] = \
+ str('%s%s%s'
+ % (cluster_id, d_data.tags['host_domain_id'],
+ d_data.tags['disk_domain_id']))
+ d_data.fields['disk_status'] = int(1)
+ is_ssd = True if s_val.get('rotation_rate') == 0 else False
+ vendor = s_val.get('vendor', None)
+ model = s_val.get('model_name', None)
+ if s_val.get('sata_version', {}).get('string'):
+ sata_version = s_val['sata_version']['string']
+ else:
+ sata_version = ''
+ if s_val.get('device', {}).get('protocol'):
+ protocol = s_val['device']['protocol']
+ else:
+ protocol = ''
+ d_data.fields['disk_type'] = \
+ self._convert_disk_type(is_ssd, sata_version, protocol)
+ d_data.fields['firmware_version'] = \
+ str(s_val.get('firmware_version'))
+ if model:
+ d_data.fields['model'] = str(model)
+ if vendor:
+ d_data.fields['vendor'] = str(vendor)
+ if sata_version:
+ d_data.fields['sata_version'] = str(sata_version)
+ if s_val.get('logical_block_size'):
+ d_data.fields['sector_size'] = \
+ str(str(s_val['logical_block_size']))
+ d_data.fields['transport_protocol'] = str('')
+ d_data.fields['vendor'] = \
+ str(s_val.get('model_family', '')).replace('\"', '\'')
+ try:
+ if isinstance(s_val.get('user_capacity'), dict):
+ if isinstance(s_val['user_capacity'].get('bytes'), dict):
+ user_capacity = \
+ s_val['user_capacity'].get('bytes', {}).get('n', 0)
+ else:
+ user_capacity = s_val['user_capacity'].get('bytes')
+ else:
+ user_capacity = s_val.get('user_capacity', 0)
+ except ValueError:
+ user_capacity = 0
+ if str(user_capacity).isdigit():
+ d_data.fields['size'] = get_human_readable(int(user_capacity), 0)
+ else:
+ d_data.fields['size'] = str(user_capacity)
+ if s_val.get('smart_status', {}).get('passed'):
+ d_data.fields['smart_health_status'] = 'PASSED'
+ else:
+ d_data.fields['smart_health_status'] = 'FAILED'
+ self.data.append(d_data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk_smart.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk_smart.py
new file mode 100644
index 00000000..1ad34784
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_disk_smart.py
@@ -0,0 +1,182 @@
+from __future__ import absolute_import
+
+import datetime
+import json
+import _strptime
+import socket
+import time
+
+from . import AGENT_VERSION, MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class SAIDiskSmartFields(MetricsField):
+ """ SAI DiskSmart structure """
+ measurement = 'sai_disk_smart'
+
+ def __init__(self):
+ super(SAIDiskSmartFields, self).__init__()
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.tags['disk_domain_id'] = None
+ self.tags['disk_name'] = None
+ self.tags['disk_wwn'] = None
+ self.tags['primary_key'] = None
+ self.fields['cluster_domain_id'] = None
+ self.fields['host_domain_id'] = None
+ self.fields['agent_version'] = str(AGENT_VERSION)
+
+
+class SAIDiskSmartAgent(MetricsAgent):
+ measurement = 'sai_disk_smart'
+
+ def _collect_data(self):
+ # process data and save to 'self.data'
+ obj_api = ClusterAPI(self._module_inst)
+ cluster_id = obj_api.get_cluster_id()
+ osds = obj_api.get_osds()
+ for osd in osds:
+ if osd.get('osd') is None:
+ continue
+ if not osd.get('in'):
+ continue
+ osds_meta = obj_api.get_osd_metadata(osd.get('osd'))
+ if not osds_meta:
+ continue
+ devs_info = obj_api.get_osd_device_id(osd.get('osd'))
+ if devs_info:
+ for dev_name, dev_info in devs_info.items():
+ osds_smart = obj_api.get_device_health(dev_info['dev_id'])
+ if not osds_smart:
+ continue
+ # Always pass through last smart data record
+ o_key = sorted(osds_smart.keys(), reverse=True)[0]
+ if o_key:
+ s_date = o_key
+ s_val = osds_smart[s_date]
+ smart_data = SAIDiskSmartFields()
+ smart_data.tags['disk_name'] = str(dev_name)
+ smart_data.fields['cluster_domain_id'] = str(cluster_id)
+ smart_data.tags['host_domain_id'] = \
+ str('%s_%s'
+ % (cluster_id, osds_meta.get('hostname', 'None')))
+ smart_data.fields['agenthost'] = str(socket.gethostname())
+ smart_data.tags['agenthost_domain_id'] = cluster_id
+ # parse attributes
+ protocol = s_val.get('device', {}).get('protocol', '')
+ if str(protocol).lower() == 'nvme':
+ nvme_info = s_val.get('nvme_smart_health_information_log', {})
+ smart_data['CriticalWarniing_raw'] = int(nvme_info.get('critical_warning', 0))
+ smart_data['CurrentDriveTemperature_raw'] = int(nvme_info.get('temperature', 0))
+ smart_data['AvailableSpare_raw'] = int(nvme_info.get('available_spare', 0))
+ smart_data['AvailableSpareThreshold_raw'] = int(nvme_info.get('available_spare_threshold', 0))
+ smart_data['PercentageUsed_raw'] = int(nvme_info.get('percentage_used', 0))
+ smart_data['DataUnitsRead_raw'] = int(nvme_info.get('data_units_read', 0))
+ smart_data['DataUnitsRead'] = int(nvme_info.get('data_units_written', 0))
+ smart_data['HostReadCommands_raw'] = int(nvme_info.get('host_reads', 0))
+ smart_data['HostWriteCommands_raw'] = int(nvme_info.get('host_writes', 0))
+ smart_data['ControllerBusyTime_raw'] = int(nvme_info.get('controller_busy_time', 0))
+ smart_data['PowerCycles_raw'] = int(nvme_info.get('power_cycles', 0))
+ smart_data['PowerOnHours_raw'] = int(nvme_info.get('power_on_hours', 0))
+ smart_data['UnsafeShutdowns_raw'] = int(nvme_info.get('unsafe_shutdowns', 0))
+ smart_data['MediaandDataIntegrityErrors_raw'] = int(nvme_info.get('media_errors', 0))
+ smart_data['ErrorInformationLogEntries'] = int(nvme_info.get('num_err_log_entries'))
+ nvme_addition = s_val.get('nvme_smart_health_information_add_log', {})
+ for k, v in nvme_addition.get("Device stats", {}).items():
+ if v.get('raw') is None:
+ continue
+ if isinstance(v.get('raw'), int):
+ smart_data[k] = int(v['raw'])
+ else:
+ smart_data[k] = str(v.get('raw'))
+ else:
+ ata_smart = s_val.get('ata_smart_attributes', {})
+ for attr in ata_smart.get('table', []):
+ if attr.get('raw', {}).get('string'):
+ if str(attr.get('raw', {}).get('string', '0')).isdigit():
+ smart_data.fields['%s_raw' % attr.get('id')] = \
+ int(attr.get('raw', {}).get('string', '0'))
+ else:
+ if str(attr.get('raw', {}).get('string', '0')).split(' ')[0].isdigit():
+ smart_data.fields['%s_raw' % attr.get('id')] = \
+ int(attr.get('raw', {}).get('string', '0').split(' ')[0])
+ else:
+ smart_data.fields['%s_raw' % attr.get('id')] = \
+ attr.get('raw', {}).get('value', 0)
+ smart_data.fields['raw_data'] = str(json.dumps(osds_smart[s_date]).replace("\"", "\'"))
+ if s_val.get('temperature', {}).get('current') is not None:
+ smart_data.fields['CurrentDriveTemperature_raw'] = \
+ int(s_val['temperature']['current'])
+ if s_val.get('temperature', {}).get('drive_trip') is not None:
+ smart_data.fields['DriveTripTemperature_raw'] = \
+ int(s_val['temperature']['drive_trip'])
+ if s_val.get('elements_grown_list') is not None:
+ smart_data.fields['ElementsInGrownDefectList_raw'] = int(s_val['elements_grown_list'])
+ if s_val.get('power_on_time', {}).get('hours') is not None:
+ smart_data.fields['9_raw'] = int(s_val['power_on_time']['hours'])
+ if s_val.get('scsi_percentage_used_endurance_indicator') is not None:
+ smart_data.fields['PercentageUsedEnduranceIndicator_raw'] = \
+ int(s_val['scsi_percentage_used_endurance_indicator'])
+ if s_val.get('scsi_error_counter_log') is not None:
+ s_err_counter = s_val['scsi_error_counter_log']
+ for s_key in s_err_counter.keys():
+ if s_key.lower() in ['read', 'write']:
+ for s1_key in s_err_counter[s_key].keys():
+ if s1_key.lower() == 'errors_corrected_by_eccfast':
+ smart_data.fields['ErrorsCorrectedbyECCFast%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['errors_corrected_by_eccfast'])
+ elif s1_key.lower() == 'errors_corrected_by_eccdelayed':
+ smart_data.fields['ErrorsCorrectedbyECCDelayed%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['errors_corrected_by_eccdelayed'])
+ elif s1_key.lower() == 'errors_corrected_by_rereads_rewrites':
+ smart_data.fields['ErrorCorrectedByRereadsRewrites%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['errors_corrected_by_rereads_rewrites'])
+ elif s1_key.lower() == 'total_errors_corrected':
+ smart_data.fields['TotalErrorsCorrected%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['total_errors_corrected'])
+ elif s1_key.lower() == 'correction_algorithm_invocations':
+ smart_data.fields['CorrectionAlgorithmInvocations%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['correction_algorithm_invocations'])
+ elif s1_key.lower() == 'gigabytes_processed':
+ smart_data.fields['GigaBytesProcessed%s_raw' % s_key.capitalize()] = \
+ float(s_err_counter[s_key]['gigabytes_processed'])
+ elif s1_key.lower() == 'total_uncorrected_errors':
+ smart_data.fields['TotalUncorrectedErrors%s_raw' % s_key.capitalize()] = \
+ int(s_err_counter[s_key]['total_uncorrected_errors'])
+
+ serial_number = s_val.get('serial_number')
+ wwn = s_val.get('wwn', {})
+ wwpn = ''
+ if wwn:
+ wwpn = '%06X%X' % (wwn.get('oui', 0), wwn.get('id', 0))
+ for k in wwn.keys():
+ if k in ['naa', 't10', 'eui', 'iqn']:
+ wwpn = ('%X%s' % (wwn[k], wwpn)).lower()
+ break
+ if wwpn:
+ smart_data.tags['disk_domain_id'] = str(dev_info['dev_id'])
+ smart_data.tags['disk_wwn'] = str(wwpn)
+ if serial_number:
+ smart_data.fields['serial_number'] = str(serial_number)
+ else:
+ smart_data.fields['serial_number'] = str(wwpn)
+ elif serial_number:
+ smart_data.tags['disk_domain_id'] = str(dev_info['dev_id'])
+ smart_data.fields['serial_number'] = str(serial_number)
+ if wwpn:
+ smart_data.tags['disk_wwn'] = str(wwpn)
+ else:
+ smart_data.tags['disk_wwn'] = str(serial_number)
+ else:
+ smart_data.tags['disk_domain_id'] = str(dev_info['dev_id'])
+ smart_data.tags['disk_wwn'] = str(dev_name)
+ smart_data.fields['serial_number'] = str(dev_name)
+ smart_data.tags['primary_key'] = \
+ str('%s%s%s'
+ % (cluster_id,
+ smart_data.tags['host_domain_id'],
+ smart_data.tags['disk_domain_id']))
+ smart_data.timestamp = \
+ time.mktime(datetime.datetime.strptime(
+ s_date, '%Y%m%d-%H%M%S').timetuple())
+ self.data.append(smart_data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_host.py b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_host.py
new file mode 100644
index 00000000..0f3698ad
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/metrics/sai_host.py
@@ -0,0 +1,105 @@
+from __future__ import absolute_import
+
+import socket
+
+from . import AGENT_VERSION, MetricsAgent, MetricsField
+from ...common.clusterdata import ClusterAPI
+
+
+class SAIHostFields(MetricsField):
+ """ SAI Host structure """
+ measurement = 'sai_host'
+
+ def __init__(self):
+ super(SAIHostFields, self).__init__()
+ self.tags['domain_id'] = None
+ self.fields['agenthost'] = None
+ self.tags['agenthost_domain_id'] = None
+ self.fields['cluster_domain_id'] = None
+ self.fields['name'] = None
+ self.fields['host_ip'] = None
+ self.fields['host_ipv6'] = None
+ self.fields['host_uuid'] = None
+ self.fields['os_type'] = str('ceph')
+ self.fields['os_name'] = None
+ self.fields['os_version'] = None
+ self.fields['agent_version'] = str(AGENT_VERSION)
+
+
+class SAIHostAgent(MetricsAgent):
+ measurement = 'sai_host'
+
+ def _collect_data(self):
+ db = ClusterAPI(self._module_inst)
+ cluster_id = db.get_cluster_id()
+
+ hosts = set()
+
+ # Parse osd's host
+ osd_data = db.get_osds()
+ for _data in osd_data:
+ osd_id = _data['osd']
+ if not _data.get('in'):
+ continue
+ osd_addr = _data['public_addr'].split(':')[0]
+ osd_metadata = db.get_osd_metadata(osd_id)
+ if osd_metadata:
+ osd_host = osd_metadata.get('hostname', 'None')
+ if osd_host not in hosts:
+ data = SAIHostFields()
+ data.fields['agenthost'] = str(socket.gethostname())
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['domain_id'] = \
+ str('%s_%s' % (cluster_id, osd_host))
+ data.fields['cluster_domain_id'] = str(cluster_id)
+ data.fields['host_ip'] = osd_addr
+ data.fields['host_uuid'] = \
+ str('%s_%s' % (cluster_id, osd_host))
+ data.fields['os_name'] = \
+ osd_metadata.get('ceph_release', '')
+ data.fields['os_version'] = \
+ osd_metadata.get('ceph_version_short', '')
+ data.fields['name'] = 'osd_{}'.format(osd_host)
+ hosts.add(osd_host)
+ self.data.append(data)
+
+ # Parse mon node host
+ mons = db.get_mons()
+ for _data in mons:
+ mon_host = _data['name']
+ mon_addr = _data['public_addr'].split(':')[0]
+ if mon_host not in hosts:
+ data = SAIHostFields()
+ data.fields['agenthost'] = str(socket.gethostname())
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['domain_id'] = \
+ str('%s_%s' % (cluster_id, mon_host))
+ data.fields['cluster_domain_id'] = str(cluster_id)
+ data.fields['host_ip'] = mon_addr
+ data.fields['host_uuid'] = \
+ str('%s_%s' % (cluster_id, mon_host))
+ data.fields['name'] = 'mon_{}'.format(mon_host)
+ hosts.add((mon_host, mon_addr))
+ self.data.append(data)
+
+ # Parse fs host
+ file_systems = db.get_file_systems()
+ for _data in file_systems:
+ mds_info = _data.get('mdsmap').get('info')
+ for _gid in mds_info:
+ mds_data = mds_info[_gid]
+ mds_addr = mds_data.get('addr').split(':')[0]
+ mds_host = mds_data.get('name')
+ if mds_host not in hosts:
+ data = SAIHostFields()
+ data.fields['agenthost'] = str(socket.gethostname())
+ data.tags['agenthost_domain_id'] = cluster_id
+ data.tags['domain_id'] = \
+ str('%s_%s' % (cluster_id, mds_host))
+ data.fields['cluster_domain_id'] = str(cluster_id)
+ data.fields['host_ip'] = mds_addr
+ data.fields['host_uuid'] = \
+ str('%s_%s' % (cluster_id, mds_host))
+ data.fields['name'] = 'mds_{}'.format(mds_host)
+ hosts.add((mds_host, mds_addr))
+ self.data.append(data)
diff --git a/src/pybind/mgr/diskprediction_cloud/agent/predictor.py b/src/pybind/mgr/diskprediction_cloud/agent/predictor.py
new file mode 100644
index 00000000..1fdea46d
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/agent/predictor.py
@@ -0,0 +1,48 @@
+from __future__ import absolute_import
+
+
+class PredictAgent(object):
+
+ measurement = 'predictor'
+
+ def __init__(self, mgr_module, obj_sender, timeout=30):
+ self.data = []
+ self._client = None
+ self._client = obj_sender
+ self._logger = mgr_module.log
+ self._module_inst = mgr_module
+ self._timeout = timeout
+
+ def __nonzero__(self):
+ if not self._module_inst:
+ return False
+ else:
+ return True
+
+ def run(self):
+ result = self._module_inst.get('devices')
+ cluster_id = self._module_inst.get('mon_map').get('fsid')
+ if not result:
+ return -1, '', 'unable to get all devices for prediction'
+ for dev in result.get('devices', []):
+ for location in dev.get('location', []):
+ host = location.get('host')
+ host_domain_id = '{}_{}'.format(cluster_id, host)
+ prediction_data = self._get_cloud_prediction_result(host_domain_id, dev.get('devid'))
+ if prediction_data:
+ self._module_inst.prediction_result[dev.get('devid')] = prediction_data
+
+ def _get_cloud_prediction_result(self, host_domain_id, disk_domain_id):
+ result = {}
+ try:
+ query_info = self._client.query_info(host_domain_id, disk_domain_id, 'sai_disk_prediction')
+ status_code = query_info.status_code
+ if status_code == 200:
+ result = query_info.json()
+ else:
+ resp = query_info.json()
+ if resp.get('error'):
+ self._logger.error(str(resp['error']))
+ except Exception as e:
+ self._logger.error('failed to get %s prediction result %s' % (disk_domain_id, str(e)))
+ return result
diff --git a/src/pybind/mgr/diskprediction_cloud/common/__init__.py b/src/pybind/mgr/diskprediction_cloud/common/__init__.py
new file mode 100644
index 00000000..ce5131b8
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/__init__.py
@@ -0,0 +1,61 @@
+from __future__ import absolute_import
+import errno
+from functools import wraps
+import os
+import signal
+
+
+DP_MGR_STAT_OK = 'OK'
+DP_MGR_STAT_WARNING = 'WARNING'
+DP_MGR_STAT_FAILED = 'FAILED'
+DP_MGR_STAT_DISABLED = 'DISABLED'
+DP_MGR_STAT_ENABLED = 'ENABLED'
+
+
+class DummyResonse:
+ def __init__(self):
+ self.resp_json = dict()
+ self.content = 'DummyResponse'
+ self.status_code = 404
+
+ def json(self):
+ return self.resp_json
+
+ def __str__(self):
+ return '{}'.format({'resp': self.resp_json, 'content': self.content, 'status_code': self.status_code})
+
+
+class TimeoutError(Exception):
+ pass
+
+
+def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
+ def decorator(func):
+ def _handle_timeout(signum, frame):
+ raise TimeoutError(error_message)
+
+ def wrapper(*args, **kwargs):
+ if hasattr(args[0], '_timeout') is not None:
+ seconds = args[0]._timeout
+ signal.signal(signal.SIGALRM, _handle_timeout)
+ signal.alarm(seconds)
+ try:
+ result = func(*args, **kwargs)
+ finally:
+ signal.alarm(0)
+ return result
+
+ return wraps(func)(wrapper)
+
+ return decorator
+
+
+def get_human_readable(size, precision=2):
+ suffixes = ['B', 'KB', 'MB', 'GB', 'TB']
+ suffix_index = 0
+ while size > 1000 and suffix_index < 4:
+ # increment the index of the suffix
+ suffix_index += 1
+ # apply the division
+ size = size/1000.0
+ return '%.*d %s' % (precision, size, suffixes[suffix_index])
diff --git a/src/pybind/mgr/diskprediction_cloud/common/client_pb2.py b/src/pybind/mgr/diskprediction_cloud/common/client_pb2.py
new file mode 100644
index 00000000..9f65c731
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/client_pb2.py
@@ -0,0 +1,1775 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: mainServer.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf import descriptor_pb2
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='mainServer.proto',
+ package='proto',
+ syntax='proto3',
+ serialized_pb=_b('\n\x10mainServer.proto\x12\x05proto\x1a\x1cgoogle/api/annotations.proto\"\x07\n\x05\x45mpty\"#\n\x10GeneralMsgOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\")\n\x16GeneralHeartbeatOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\"\x1d\n\nPingOutout\x12\x0f\n\x07message\x18\x01 \x01(\t\"*\n\tTestInput\x12\x1d\n\x06people\x18\x01 \x03(\x0b\x32\r.proto.Person\"\xbe\x01\n\nTestOutput\x12\x10\n\x08strArray\x18\x01 \x03(\t\x12\x31\n\x08mapValue\x18\x02 \x03(\x0b\x32\x1f.proto.TestOutput.MapValueEntry\x12\x19\n\x02pn\x18\x04 \x01(\x0b\x32\r.proto.Person\x12\x1f\n\x07profile\x18\x03 \x03(\x0b\x32\x0e.proto.Profile\x1a/\n\rMapValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xcf\x01\n\x06Person\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\x03\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12)\n\x06phones\x18\x04 \x03(\x0b\x32\x19.proto.Person.PhoneNumber\x1a\x44\n\x0bPhoneNumber\x12\x0e\n\x06number\x18\x01 \x01(\t\x12%\n\x04type\x18\x02 \x01(\x0e\x32\x17.proto.Person.PhoneType\"+\n\tPhoneType\x12\n\n\x06MOBILE\x10\x00\x12\x08\n\x04HOME\x10\x01\x12\x08\n\x04WORK\x10\x02\"\xa9\x01\n\x07Profile\x12%\n\x08\x66ileInfo\x18\x01 \x01(\x0b\x32\x13.proto.Profile.File\x1aw\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\ttypeInt32\x18\x02 \x01(\x05\x12\x11\n\ttypeInt64\x18\x03 \x01(\x03\x12\x11\n\ttypeFloat\x18\x04 \x01(\x02\x12\x12\n\ntypeDouble\x18\x05 \x01(\x01\x12\x14\n\x0c\x62ooleanValue\x18\x06 \x01(\x08\"4\n\x15GetUsersByStatusInput\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\":\n\x16GetUsersByStatusOutput\x12 \n\x05users\x18\x01 \x03(\x0b\x32\x11.proto.UserOutput\")\n\x16\x41\x63\x63ountHeartbeatOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\"-\n\nLoginInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\"\xf2\x01\n\nUserOutput\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\x12\r\n\x05phone\x18\x04 \x01(\t\x12\x11\n\tfirstName\x18\x05 \x01(\t\x12\x10\n\x08lastName\x18\x06 \x01(\t\x12\x13\n\x0b\x63reatedTime\x18\x07 \x01(\t\x12\x11\n\tnamespace\x18\x08 \x01(\t\x12\x12\n\ndomainName\x18\t \x01(\t\x12\x0f\n\x07\x63ompany\x18\n \x01(\t\x12\x0b\n\x03url\x18\x0b \x01(\t\x12\x14\n\x0c\x61gentAccount\x18\x0c \x01(\t\x12\x15\n\ragentPassword\x18\r \x01(\t\"s\n\x0bSingupInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\r\n\x05phone\x18\x02 \x01(\t\x12\x11\n\tfirstName\x18\x03 \x01(\t\x12\x10\n\x08lastName\x18\x04 \x01(\t\x12\x10\n\x08password\x18\x05 \x01(\t\x12\x0f\n\x07\x63ompany\x18\x06 \x01(\t\"\x1f\n\x0cSingupOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\"-\n\x0f\x44\x65leteUserInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\"C\n\x15UpdateUserStatusInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\"\'\n\x16ResendConfirmCodeInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\"+\n\x0c\x43onfirmInput\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\"$\n\x11\x44PHeartbeatOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\"n\n\x17\x44PGetPhysicalDisksInput\x12\x0f\n\x07hostIds\x18\x01 \x01(\t\x12\x0b\n\x03ids\x18\x02 \x01(\t\x12\r\n\x05limit\x18\x03 \x01(\x03\x12\x0c\n\x04page\x18\x04 \x01(\x03\x12\x0c\n\x04\x66rom\x18\x05 \x01(\t\x12\n\n\x02to\x18\x06 \x01(\t\"{\n\x19\x44PGetDisksPredictionInput\x12\x17\n\x0fphysicalDiskIds\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\t\x12\r\n\x05limit\x18\x03 \x01(\x03\x12\x0c\n\x04page\x18\x04 \x01(\x03\x12\x0c\n\x04\x66rom\x18\x05 \x01(\t\x12\n\n\x02to\x18\x06 \x01(\t\"\x1e\n\x0e\x44PBinaryOutput\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\",\n\x19\x43ollectionHeartbeatOutput\x12\x0f\n\x07message\x18\x01 \x01(\t\"\"\n\x10PostMetricsInput\x12\x0e\n\x06points\x18\x01 \x03(\t\" \n\x10PostDBRelayInput\x12\x0c\n\x04\x63mds\x18\x01 \x03(\t\":\n\x17\x43ollectionMessageOutput\x12\x0e\n\x06status\x18\x01 \x01(\x03\x12\x0f\n\x07message\x18\x02 \x01(\t2\x85\x02\n\x07General\x12\x63\n\x10GeneralHeartbeat\x12\x0c.proto.Empty\x1a\x1d.proto.GeneralHeartbeatOutput\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/apis/v2/general/heartbeat\x12\x46\n\x04Ping\x12\x0c.proto.Empty\x1a\x11.proto.PingOutout\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/apis/v2/general/ping\x12M\n\x04Test\x12\x10.proto.TestInput\x1a\x11.proto.TestOutput\" \x82\xd3\xe4\x93\x02\x1a\"\x15/apis/v2/general/test:\x01*2\xa4\x06\n\x07\x41\x63\x63ount\x12\x63\n\x10\x41\x63\x63ountHeartbeat\x12\x0c.proto.Empty\x1a\x1d.proto.AccountHeartbeatOutput\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/apis/v2/account/heartbeat\x12N\n\x05Login\x12\x11.proto.LoginInput\x1a\x11.proto.UserOutput\"\x1f\x82\xd3\xe4\x93\x02\x19\"\x14/apis/v2/users/login:\x01*\x12S\n\x06Signup\x12\x12.proto.SingupInput\x1a\x13.proto.SingupOutput\" \x82\xd3\xe4\x93\x02\x1a\"\x15/apis/v2/users/signup:\x01*\x12r\n\x11ResendConfirmCode\x12\x1d.proto.ResendConfirmCodeInput\x1a\x17.proto.GeneralMsgOutput\"%\x82\xd3\xe4\x93\x02\x1f\"\x1a/apis/v2/users/confirmcode:\x01*\x12_\n\x07\x43onfirm\x12\x13.proto.ConfirmInput\x1a\x17.proto.GeneralMsgOutput\"&\x82\xd3\xe4\x93\x02 \"\x1b/apis/v2/users/confirmation:\x01*\x12g\n\x10GetUsersByStatus\x12\x1c.proto.GetUsersByStatusInput\x1a\x1d.proto.GetUsersByStatusOutput\"\x16\x82\xd3\xe4\x93\x02\x10\x12\x0e/apis/v2/users\x12\x63\n\nDeleteUser\x12\x16.proto.DeleteUserInput\x1a\x17.proto.GeneralMsgOutput\"$\x82\xd3\xe4\x93\x02\x1e*\x1c/apis/v2/users/{email}/{key}\x12l\n\x10UpdateUserStatus\x12\x1c.proto.UpdateUserStatusInput\x1a\x17.proto.GeneralMsgOutput\"!\x82\xd3\xe4\x93\x02\x1b\x1a\x16/apis/v2/users/{email}:\x01*2\xcf\x02\n\x0b\x44iskprophet\x12T\n\x0b\x44PHeartbeat\x12\x0c.proto.Empty\x1a\x18.proto.DPHeartbeatOutput\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/apis/v2/dp/heartbeat\x12l\n\x12\x44PGetPhysicalDisks\x12\x1e.proto.DPGetPhysicalDisksInput\x1a\x15.proto.DPBinaryOutput\"\x1f\x82\xd3\xe4\x93\x02\x19\x12\x17/apis/v2/physical-disks\x12|\n\x14\x44PGetDisksPrediction\x12 .proto.DPGetDisksPredictionInput\x1a\x15.proto.DPBinaryOutput\"+\x82\xd3\xe4\x93\x02%\x12#/apis/v2/physical-disks/predictions2\xdb\x02\n\nCollection\x12l\n\x13\x43ollectionHeartbeat\x12\x0c.proto.Empty\x1a .proto.CollectionHeartbeatOutput\"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/apis/v2/collection/heartbeat\x12o\n\x0bPostDBRelay\x12\x17.proto.PostDBRelayInput\x1a\x1e.proto.CollectionMessageOutput\"\'\x82\xd3\xe4\x93\x02!\"\x1c/apis/v2/collection/relation:\x01*\x12n\n\x0bPostMetrics\x12\x17.proto.PostMetricsInput\x1a\x1e.proto.CollectionMessageOutput\"&\x82\xd3\xe4\x93\x02 \"\x1b/apis/v2/collection/metrics:\x01*b\x06proto3')
+ ,
+ dependencies=[google_dot_api_dot_annotations__pb2.DESCRIPTOR,])
+
+
+
+_PERSON_PHONETYPE = _descriptor.EnumDescriptor(
+ name='PhoneType',
+ full_name='proto.Person.PhoneType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='MOBILE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HOME', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='WORK', index=2, number=2,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=579,
+ serialized_end=622,
+)
+_sym_db.RegisterEnumDescriptor(_PERSON_PHONETYPE)
+
+
+_EMPTY = _descriptor.Descriptor(
+ name='Empty',
+ full_name='proto.Empty',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=57,
+ serialized_end=64,
+)
+
+
+_GENERALMSGOUTPUT = _descriptor.Descriptor(
+ name='GeneralMsgOutput',
+ full_name='proto.GeneralMsgOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.GeneralMsgOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=66,
+ serialized_end=101,
+)
+
+
+_GENERALHEARTBEATOUTPUT = _descriptor.Descriptor(
+ name='GeneralHeartbeatOutput',
+ full_name='proto.GeneralHeartbeatOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.GeneralHeartbeatOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=103,
+ serialized_end=144,
+)
+
+
+_PINGOUTOUT = _descriptor.Descriptor(
+ name='PingOutout',
+ full_name='proto.PingOutout',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.PingOutout.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=146,
+ serialized_end=175,
+)
+
+
+_TESTINPUT = _descriptor.Descriptor(
+ name='TestInput',
+ full_name='proto.TestInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='people', full_name='proto.TestInput.people', index=0,
+ number=1, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=177,
+ serialized_end=219,
+)
+
+
+_TESTOUTPUT_MAPVALUEENTRY = _descriptor.Descriptor(
+ name='MapValueEntry',
+ full_name='proto.TestOutput.MapValueEntry',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='key', full_name='proto.TestOutput.MapValueEntry.key', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='value', full_name='proto.TestOutput.MapValueEntry.value', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=365,
+ serialized_end=412,
+)
+
+_TESTOUTPUT = _descriptor.Descriptor(
+ name='TestOutput',
+ full_name='proto.TestOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='strArray', full_name='proto.TestOutput.strArray', index=0,
+ number=1, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='mapValue', full_name='proto.TestOutput.mapValue', index=1,
+ number=2, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='pn', full_name='proto.TestOutput.pn', index=2,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='profile', full_name='proto.TestOutput.profile', index=3,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[_TESTOUTPUT_MAPVALUEENTRY, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=222,
+ serialized_end=412,
+)
+
+
+_PERSON_PHONENUMBER = _descriptor.Descriptor(
+ name='PhoneNumber',
+ full_name='proto.Person.PhoneNumber',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='number', full_name='proto.Person.PhoneNumber.number', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='type', full_name='proto.Person.PhoneNumber.type', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=509,
+ serialized_end=577,
+)
+
+_PERSON = _descriptor.Descriptor(
+ name='Person',
+ full_name='proto.Person',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='name', full_name='proto.Person.name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='id', full_name='proto.Person.id', index=1,
+ number=2, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.Person.email', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='phones', full_name='proto.Person.phones', index=3,
+ number=4, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[_PERSON_PHONENUMBER, ],
+ enum_types=[
+ _PERSON_PHONETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=415,
+ serialized_end=622,
+)
+
+
+_PROFILE_FILE = _descriptor.Descriptor(
+ name='File',
+ full_name='proto.Profile.File',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='name', full_name='proto.Profile.File.name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='typeInt32', full_name='proto.Profile.File.typeInt32', index=1,
+ number=2, type=5, cpp_type=1, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='typeInt64', full_name='proto.Profile.File.typeInt64', index=2,
+ number=3, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='typeFloat', full_name='proto.Profile.File.typeFloat', index=3,
+ number=4, type=2, cpp_type=6, label=1,
+ has_default_value=False, default_value=float(0),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='typeDouble', full_name='proto.Profile.File.typeDouble', index=4,
+ number=5, type=1, cpp_type=5, label=1,
+ has_default_value=False, default_value=float(0),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='booleanValue', full_name='proto.Profile.File.booleanValue', index=5,
+ number=6, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=675,
+ serialized_end=794,
+)
+
+_PROFILE = _descriptor.Descriptor(
+ name='Profile',
+ full_name='proto.Profile',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='fileInfo', full_name='proto.Profile.fileInfo', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[_PROFILE_FILE, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=625,
+ serialized_end=794,
+)
+
+
+_GETUSERSBYSTATUSINPUT = _descriptor.Descriptor(
+ name='GetUsersByStatusInput',
+ full_name='proto.GetUsersByStatusInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='status', full_name='proto.GetUsersByStatusInput.status', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='key', full_name='proto.GetUsersByStatusInput.key', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=796,
+ serialized_end=848,
+)
+
+
+_GETUSERSBYSTATUSOUTPUT = _descriptor.Descriptor(
+ name='GetUsersByStatusOutput',
+ full_name='proto.GetUsersByStatusOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='users', full_name='proto.GetUsersByStatusOutput.users', index=0,
+ number=1, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=850,
+ serialized_end=908,
+)
+
+
+_ACCOUNTHEARTBEATOUTPUT = _descriptor.Descriptor(
+ name='AccountHeartbeatOutput',
+ full_name='proto.AccountHeartbeatOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.AccountHeartbeatOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=910,
+ serialized_end=951,
+)
+
+
+_LOGININPUT = _descriptor.Descriptor(
+ name='LoginInput',
+ full_name='proto.LoginInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.LoginInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='password', full_name='proto.LoginInput.password', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=953,
+ serialized_end=998,
+)
+
+
+_USEROUTPUT = _descriptor.Descriptor(
+ name='UserOutput',
+ full_name='proto.UserOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='id', full_name='proto.UserOutput.id', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.UserOutput.email', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='status', full_name='proto.UserOutput.status', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='phone', full_name='proto.UserOutput.phone', index=3,
+ number=4, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='firstName', full_name='proto.UserOutput.firstName', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='lastName', full_name='proto.UserOutput.lastName', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='createdTime', full_name='proto.UserOutput.createdTime', index=6,
+ number=7, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='namespace', full_name='proto.UserOutput.namespace', index=7,
+ number=8, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='domainName', full_name='proto.UserOutput.domainName', index=8,
+ number=9, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='company', full_name='proto.UserOutput.company', index=9,
+ number=10, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='url', full_name='proto.UserOutput.url', index=10,
+ number=11, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='agentAccount', full_name='proto.UserOutput.agentAccount', index=11,
+ number=12, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='agentPassword', full_name='proto.UserOutput.agentPassword', index=12,
+ number=13, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1001,
+ serialized_end=1243,
+)
+
+
+_SINGUPINPUT = _descriptor.Descriptor(
+ name='SingupInput',
+ full_name='proto.SingupInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.SingupInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='phone', full_name='proto.SingupInput.phone', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='firstName', full_name='proto.SingupInput.firstName', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='lastName', full_name='proto.SingupInput.lastName', index=3,
+ number=4, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='password', full_name='proto.SingupInput.password', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='company', full_name='proto.SingupInput.company', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1245,
+ serialized_end=1360,
+)
+
+
+_SINGUPOUTPUT = _descriptor.Descriptor(
+ name='SingupOutput',
+ full_name='proto.SingupOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.SingupOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1362,
+ serialized_end=1393,
+)
+
+
+_DELETEUSERINPUT = _descriptor.Descriptor(
+ name='DeleteUserInput',
+ full_name='proto.DeleteUserInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.DeleteUserInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='key', full_name='proto.DeleteUserInput.key', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1395,
+ serialized_end=1440,
+)
+
+
+_UPDATEUSERSTATUSINPUT = _descriptor.Descriptor(
+ name='UpdateUserStatusInput',
+ full_name='proto.UpdateUserStatusInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.UpdateUserStatusInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='key', full_name='proto.UpdateUserStatusInput.key', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='status', full_name='proto.UpdateUserStatusInput.status', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1442,
+ serialized_end=1509,
+)
+
+
+_RESENDCONFIRMCODEINPUT = _descriptor.Descriptor(
+ name='ResendConfirmCodeInput',
+ full_name='proto.ResendConfirmCodeInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.ResendConfirmCodeInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1511,
+ serialized_end=1550,
+)
+
+
+_CONFIRMINPUT = _descriptor.Descriptor(
+ name='ConfirmInput',
+ full_name='proto.ConfirmInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='email', full_name='proto.ConfirmInput.email', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='code', full_name='proto.ConfirmInput.code', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1552,
+ serialized_end=1595,
+)
+
+
+_DPHEARTBEATOUTPUT = _descriptor.Descriptor(
+ name='DPHeartbeatOutput',
+ full_name='proto.DPHeartbeatOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.DPHeartbeatOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1597,
+ serialized_end=1633,
+)
+
+
+_DPGETPHYSICALDISKSINPUT = _descriptor.Descriptor(
+ name='DPGetPhysicalDisksInput',
+ full_name='proto.DPGetPhysicalDisksInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='hostIds', full_name='proto.DPGetPhysicalDisksInput.hostIds', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='ids', full_name='proto.DPGetPhysicalDisksInput.ids', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='limit', full_name='proto.DPGetPhysicalDisksInput.limit', index=2,
+ number=3, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='page', full_name='proto.DPGetPhysicalDisksInput.page', index=3,
+ number=4, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='from', full_name='proto.DPGetPhysicalDisksInput.from', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='to', full_name='proto.DPGetPhysicalDisksInput.to', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1635,
+ serialized_end=1745,
+)
+
+
+_DPGETDISKSPREDICTIONINPUT = _descriptor.Descriptor(
+ name='DPGetDisksPredictionInput',
+ full_name='proto.DPGetDisksPredictionInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='physicalDiskIds', full_name='proto.DPGetDisksPredictionInput.physicalDiskIds', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='status', full_name='proto.DPGetDisksPredictionInput.status', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='limit', full_name='proto.DPGetDisksPredictionInput.limit', index=2,
+ number=3, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='page', full_name='proto.DPGetDisksPredictionInput.page', index=3,
+ number=4, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='from', full_name='proto.DPGetDisksPredictionInput.from', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='to', full_name='proto.DPGetDisksPredictionInput.to', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1747,
+ serialized_end=1870,
+)
+
+
+_DPBINARYOUTPUT = _descriptor.Descriptor(
+ name='DPBinaryOutput',
+ full_name='proto.DPBinaryOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='data', full_name='proto.DPBinaryOutput.data', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1872,
+ serialized_end=1902,
+)
+
+
+_COLLECTIONHEARTBEATOUTPUT = _descriptor.Descriptor(
+ name='CollectionHeartbeatOutput',
+ full_name='proto.CollectionHeartbeatOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.CollectionHeartbeatOutput.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1904,
+ serialized_end=1948,
+)
+
+
+_POSTMETRICSINPUT = _descriptor.Descriptor(
+ name='PostMetricsInput',
+ full_name='proto.PostMetricsInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='points', full_name='proto.PostMetricsInput.points', index=0,
+ number=1, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1950,
+ serialized_end=1984,
+)
+
+
+_POSTDBRELAYINPUT = _descriptor.Descriptor(
+ name='PostDBRelayInput',
+ full_name='proto.PostDBRelayInput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='cmds', full_name='proto.PostDBRelayInput.cmds', index=0,
+ number=1, type=9, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1986,
+ serialized_end=2018,
+)
+
+
+_COLLECTIONMESSAGEOUTPUT = _descriptor.Descriptor(
+ name='CollectionMessageOutput',
+ full_name='proto.CollectionMessageOutput',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='status', full_name='proto.CollectionMessageOutput.status', index=0,
+ number=1, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='message', full_name='proto.CollectionMessageOutput.message', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2020,
+ serialized_end=2078,
+)
+
+_TESTINPUT.fields_by_name['people'].message_type = _PERSON
+_TESTOUTPUT_MAPVALUEENTRY.containing_type = _TESTOUTPUT
+_TESTOUTPUT.fields_by_name['mapValue'].message_type = _TESTOUTPUT_MAPVALUEENTRY
+_TESTOUTPUT.fields_by_name['pn'].message_type = _PERSON
+_TESTOUTPUT.fields_by_name['profile'].message_type = _PROFILE
+_PERSON_PHONENUMBER.fields_by_name['type'].enum_type = _PERSON_PHONETYPE
+_PERSON_PHONENUMBER.containing_type = _PERSON
+_PERSON.fields_by_name['phones'].message_type = _PERSON_PHONENUMBER
+_PERSON_PHONETYPE.containing_type = _PERSON
+_PROFILE_FILE.containing_type = _PROFILE
+_PROFILE.fields_by_name['fileInfo'].message_type = _PROFILE_FILE
+_GETUSERSBYSTATUSOUTPUT.fields_by_name['users'].message_type = _USEROUTPUT
+DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY
+DESCRIPTOR.message_types_by_name['GeneralMsgOutput'] = _GENERALMSGOUTPUT
+DESCRIPTOR.message_types_by_name['GeneralHeartbeatOutput'] = _GENERALHEARTBEATOUTPUT
+DESCRIPTOR.message_types_by_name['PingOutout'] = _PINGOUTOUT
+DESCRIPTOR.message_types_by_name['TestInput'] = _TESTINPUT
+DESCRIPTOR.message_types_by_name['TestOutput'] = _TESTOUTPUT
+DESCRIPTOR.message_types_by_name['Person'] = _PERSON
+DESCRIPTOR.message_types_by_name['Profile'] = _PROFILE
+DESCRIPTOR.message_types_by_name['GetUsersByStatusInput'] = _GETUSERSBYSTATUSINPUT
+DESCRIPTOR.message_types_by_name['GetUsersByStatusOutput'] = _GETUSERSBYSTATUSOUTPUT
+DESCRIPTOR.message_types_by_name['AccountHeartbeatOutput'] = _ACCOUNTHEARTBEATOUTPUT
+DESCRIPTOR.message_types_by_name['LoginInput'] = _LOGININPUT
+DESCRIPTOR.message_types_by_name['UserOutput'] = _USEROUTPUT
+DESCRIPTOR.message_types_by_name['SingupInput'] = _SINGUPINPUT
+DESCRIPTOR.message_types_by_name['SingupOutput'] = _SINGUPOUTPUT
+DESCRIPTOR.message_types_by_name['DeleteUserInput'] = _DELETEUSERINPUT
+DESCRIPTOR.message_types_by_name['UpdateUserStatusInput'] = _UPDATEUSERSTATUSINPUT
+DESCRIPTOR.message_types_by_name['ResendConfirmCodeInput'] = _RESENDCONFIRMCODEINPUT
+DESCRIPTOR.message_types_by_name['ConfirmInput'] = _CONFIRMINPUT
+DESCRIPTOR.message_types_by_name['DPHeartbeatOutput'] = _DPHEARTBEATOUTPUT
+DESCRIPTOR.message_types_by_name['DPGetPhysicalDisksInput'] = _DPGETPHYSICALDISKSINPUT
+DESCRIPTOR.message_types_by_name['DPGetDisksPredictionInput'] = _DPGETDISKSPREDICTIONINPUT
+DESCRIPTOR.message_types_by_name['DPBinaryOutput'] = _DPBINARYOUTPUT
+DESCRIPTOR.message_types_by_name['CollectionHeartbeatOutput'] = _COLLECTIONHEARTBEATOUTPUT
+DESCRIPTOR.message_types_by_name['PostMetricsInput'] = _POSTMETRICSINPUT
+DESCRIPTOR.message_types_by_name['PostDBRelayInput'] = _POSTDBRELAYINPUT
+DESCRIPTOR.message_types_by_name['CollectionMessageOutput'] = _COLLECTIONMESSAGEOUTPUT
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), dict(
+ DESCRIPTOR = _EMPTY,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.Empty)
+ ))
+_sym_db.RegisterMessage(Empty)
+
+GeneralMsgOutput = _reflection.GeneratedProtocolMessageType('GeneralMsgOutput', (_message.Message,), dict(
+ DESCRIPTOR = _GENERALMSGOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.GeneralMsgOutput)
+ ))
+_sym_db.RegisterMessage(GeneralMsgOutput)
+
+GeneralHeartbeatOutput = _reflection.GeneratedProtocolMessageType('GeneralHeartbeatOutput', (_message.Message,), dict(
+ DESCRIPTOR = _GENERALHEARTBEATOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.GeneralHeartbeatOutput)
+ ))
+_sym_db.RegisterMessage(GeneralHeartbeatOutput)
+
+PingOutout = _reflection.GeneratedProtocolMessageType('PingOutout', (_message.Message,), dict(
+ DESCRIPTOR = _PINGOUTOUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.PingOutout)
+ ))
+_sym_db.RegisterMessage(PingOutout)
+
+TestInput = _reflection.GeneratedProtocolMessageType('TestInput', (_message.Message,), dict(
+ DESCRIPTOR = _TESTINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.TestInput)
+ ))
+_sym_db.RegisterMessage(TestInput)
+
+TestOutput = _reflection.GeneratedProtocolMessageType('TestOutput', (_message.Message,), dict(
+
+ MapValueEntry = _reflection.GeneratedProtocolMessageType('MapValueEntry', (_message.Message,), dict(
+ DESCRIPTOR = _TESTOUTPUT_MAPVALUEENTRY,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.TestOutput.MapValueEntry)
+ ))
+ ,
+ DESCRIPTOR = _TESTOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.TestOutput)
+ ))
+_sym_db.RegisterMessage(TestOutput)
+_sym_db.RegisterMessage(TestOutput.MapValueEntry)
+
+Person = _reflection.GeneratedProtocolMessageType('Person', (_message.Message,), dict(
+
+ PhoneNumber = _reflection.GeneratedProtocolMessageType('PhoneNumber', (_message.Message,), dict(
+ DESCRIPTOR = _PERSON_PHONENUMBER,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.Person.PhoneNumber)
+ ))
+ ,
+ DESCRIPTOR = _PERSON,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.Person)
+ ))
+_sym_db.RegisterMessage(Person)
+_sym_db.RegisterMessage(Person.PhoneNumber)
+
+Profile = _reflection.GeneratedProtocolMessageType('Profile', (_message.Message,), dict(
+
+ File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict(
+ DESCRIPTOR = _PROFILE_FILE,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.Profile.File)
+ ))
+ ,
+ DESCRIPTOR = _PROFILE,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.Profile)
+ ))
+_sym_db.RegisterMessage(Profile)
+_sym_db.RegisterMessage(Profile.File)
+
+GetUsersByStatusInput = _reflection.GeneratedProtocolMessageType('GetUsersByStatusInput', (_message.Message,), dict(
+ DESCRIPTOR = _GETUSERSBYSTATUSINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.GetUsersByStatusInput)
+ ))
+_sym_db.RegisterMessage(GetUsersByStatusInput)
+
+GetUsersByStatusOutput = _reflection.GeneratedProtocolMessageType('GetUsersByStatusOutput', (_message.Message,), dict(
+ DESCRIPTOR = _GETUSERSBYSTATUSOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.GetUsersByStatusOutput)
+ ))
+_sym_db.RegisterMessage(GetUsersByStatusOutput)
+
+AccountHeartbeatOutput = _reflection.GeneratedProtocolMessageType('AccountHeartbeatOutput', (_message.Message,), dict(
+ DESCRIPTOR = _ACCOUNTHEARTBEATOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.AccountHeartbeatOutput)
+ ))
+_sym_db.RegisterMessage(AccountHeartbeatOutput)
+
+LoginInput = _reflection.GeneratedProtocolMessageType('LoginInput', (_message.Message,), dict(
+ DESCRIPTOR = _LOGININPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.LoginInput)
+ ))
+_sym_db.RegisterMessage(LoginInput)
+
+UserOutput = _reflection.GeneratedProtocolMessageType('UserOutput', (_message.Message,), dict(
+ DESCRIPTOR = _USEROUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.UserOutput)
+ ))
+_sym_db.RegisterMessage(UserOutput)
+
+SingupInput = _reflection.GeneratedProtocolMessageType('SingupInput', (_message.Message,), dict(
+ DESCRIPTOR = _SINGUPINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.SingupInput)
+ ))
+_sym_db.RegisterMessage(SingupInput)
+
+SingupOutput = _reflection.GeneratedProtocolMessageType('SingupOutput', (_message.Message,), dict(
+ DESCRIPTOR = _SINGUPOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.SingupOutput)
+ ))
+_sym_db.RegisterMessage(SingupOutput)
+
+DeleteUserInput = _reflection.GeneratedProtocolMessageType('DeleteUserInput', (_message.Message,), dict(
+ DESCRIPTOR = _DELETEUSERINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.DeleteUserInput)
+ ))
+_sym_db.RegisterMessage(DeleteUserInput)
+
+UpdateUserStatusInput = _reflection.GeneratedProtocolMessageType('UpdateUserStatusInput', (_message.Message,), dict(
+ DESCRIPTOR = _UPDATEUSERSTATUSINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.UpdateUserStatusInput)
+ ))
+_sym_db.RegisterMessage(UpdateUserStatusInput)
+
+ResendConfirmCodeInput = _reflection.GeneratedProtocolMessageType('ResendConfirmCodeInput', (_message.Message,), dict(
+ DESCRIPTOR = _RESENDCONFIRMCODEINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.ResendConfirmCodeInput)
+ ))
+_sym_db.RegisterMessage(ResendConfirmCodeInput)
+
+ConfirmInput = _reflection.GeneratedProtocolMessageType('ConfirmInput', (_message.Message,), dict(
+ DESCRIPTOR = _CONFIRMINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.ConfirmInput)
+ ))
+_sym_db.RegisterMessage(ConfirmInput)
+
+DPHeartbeatOutput = _reflection.GeneratedProtocolMessageType('DPHeartbeatOutput', (_message.Message,), dict(
+ DESCRIPTOR = _DPHEARTBEATOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.DPHeartbeatOutput)
+ ))
+_sym_db.RegisterMessage(DPHeartbeatOutput)
+
+DPGetPhysicalDisksInput = _reflection.GeneratedProtocolMessageType('DPGetPhysicalDisksInput', (_message.Message,), dict(
+ DESCRIPTOR = _DPGETPHYSICALDISKSINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.DPGetPhysicalDisksInput)
+ ))
+_sym_db.RegisterMessage(DPGetPhysicalDisksInput)
+
+DPGetDisksPredictionInput = _reflection.GeneratedProtocolMessageType('DPGetDisksPredictionInput', (_message.Message,), dict(
+ DESCRIPTOR = _DPGETDISKSPREDICTIONINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.DPGetDisksPredictionInput)
+ ))
+_sym_db.RegisterMessage(DPGetDisksPredictionInput)
+
+DPBinaryOutput = _reflection.GeneratedProtocolMessageType('DPBinaryOutput', (_message.Message,), dict(
+ DESCRIPTOR = _DPBINARYOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.DPBinaryOutput)
+ ))
+_sym_db.RegisterMessage(DPBinaryOutput)
+
+CollectionHeartbeatOutput = _reflection.GeneratedProtocolMessageType('CollectionHeartbeatOutput', (_message.Message,), dict(
+ DESCRIPTOR = _COLLECTIONHEARTBEATOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.CollectionHeartbeatOutput)
+ ))
+_sym_db.RegisterMessage(CollectionHeartbeatOutput)
+
+PostMetricsInput = _reflection.GeneratedProtocolMessageType('PostMetricsInput', (_message.Message,), dict(
+ DESCRIPTOR = _POSTMETRICSINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.PostMetricsInput)
+ ))
+_sym_db.RegisterMessage(PostMetricsInput)
+
+PostDBRelayInput = _reflection.GeneratedProtocolMessageType('PostDBRelayInput', (_message.Message,), dict(
+ DESCRIPTOR = _POSTDBRELAYINPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.PostDBRelayInput)
+ ))
+_sym_db.RegisterMessage(PostDBRelayInput)
+
+CollectionMessageOutput = _reflection.GeneratedProtocolMessageType('CollectionMessageOutput', (_message.Message,), dict(
+ DESCRIPTOR = _COLLECTIONMESSAGEOUTPUT,
+ __module__ = 'mainServer_pb2'
+ # @@protoc_insertion_point(class_scope:proto.CollectionMessageOutput)
+ ))
+_sym_db.RegisterMessage(CollectionMessageOutput)
+
+
+_TESTOUTPUT_MAPVALUEENTRY.has_options = True
+_TESTOUTPUT_MAPVALUEENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
+
+_GENERAL = _descriptor.ServiceDescriptor(
+ name='General',
+ full_name='proto.General',
+ file=DESCRIPTOR,
+ index=0,
+ options=None,
+ serialized_start=2081,
+ serialized_end=2342,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='GeneralHeartbeat',
+ full_name='proto.General.GeneralHeartbeat',
+ index=0,
+ containing_service=None,
+ input_type=_EMPTY,
+ output_type=_GENERALHEARTBEATOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\034\022\032/apis/v2/general/heartbeat')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='Ping',
+ full_name='proto.General.Ping',
+ index=1,
+ containing_service=None,
+ input_type=_EMPTY,
+ output_type=_PINGOUTOUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\027\022\025/apis/v2/general/ping')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='Test',
+ full_name='proto.General.Test',
+ index=2,
+ containing_service=None,
+ input_type=_TESTINPUT,
+ output_type=_TESTOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\032\"\025/apis/v2/general/test:\001*')),
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_GENERAL)
+
+DESCRIPTOR.services_by_name['General'] = _GENERAL
+
+
+_ACCOUNT = _descriptor.ServiceDescriptor(
+ name='Account',
+ full_name='proto.Account',
+ file=DESCRIPTOR,
+ index=1,
+ options=None,
+ serialized_start=2345,
+ serialized_end=3149,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='AccountHeartbeat',
+ full_name='proto.Account.AccountHeartbeat',
+ index=0,
+ containing_service=None,
+ input_type=_EMPTY,
+ output_type=_ACCOUNTHEARTBEATOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\034\022\032/apis/v2/account/heartbeat')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='Login',
+ full_name='proto.Account.Login',
+ index=1,
+ containing_service=None,
+ input_type=_LOGININPUT,
+ output_type=_USEROUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\031\"\024/apis/v2/users/login:\001*')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='Signup',
+ full_name='proto.Account.Signup',
+ index=2,
+ containing_service=None,
+ input_type=_SINGUPINPUT,
+ output_type=_SINGUPOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\032\"\025/apis/v2/users/signup:\001*')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='ResendConfirmCode',
+ full_name='proto.Account.ResendConfirmCode',
+ index=3,
+ containing_service=None,
+ input_type=_RESENDCONFIRMCODEINPUT,
+ output_type=_GENERALMSGOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\037\"\032/apis/v2/users/confirmcode:\001*')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='Confirm',
+ full_name='proto.Account.Confirm',
+ index=4,
+ containing_service=None,
+ input_type=_CONFIRMINPUT,
+ output_type=_GENERALMSGOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002 \"\033/apis/v2/users/confirmation:\001*')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='GetUsersByStatus',
+ full_name='proto.Account.GetUsersByStatus',
+ index=5,
+ containing_service=None,
+ input_type=_GETUSERSBYSTATUSINPUT,
+ output_type=_GETUSERSBYSTATUSOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\020\022\016/apis/v2/users')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='DeleteUser',
+ full_name='proto.Account.DeleteUser',
+ index=6,
+ containing_service=None,
+ input_type=_DELETEUSERINPUT,
+ output_type=_GENERALMSGOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\036*\034/apis/v2/users/{email}/{key}')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='UpdateUserStatus',
+ full_name='proto.Account.UpdateUserStatus',
+ index=7,
+ containing_service=None,
+ input_type=_UPDATEUSERSTATUSINPUT,
+ output_type=_GENERALMSGOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\033\032\026/apis/v2/users/{email}:\001*')),
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_ACCOUNT)
+
+DESCRIPTOR.services_by_name['Account'] = _ACCOUNT
+
+
+_DISKPROPHET = _descriptor.ServiceDescriptor(
+ name='Diskprophet',
+ full_name='proto.Diskprophet',
+ file=DESCRIPTOR,
+ index=2,
+ options=None,
+ serialized_start=3152,
+ serialized_end=3487,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='DPHeartbeat',
+ full_name='proto.Diskprophet.DPHeartbeat',
+ index=0,
+ containing_service=None,
+ input_type=_EMPTY,
+ output_type=_DPHEARTBEATOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\027\022\025/apis/v2/dp/heartbeat')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='DPGetPhysicalDisks',
+ full_name='proto.Diskprophet.DPGetPhysicalDisks',
+ index=1,
+ containing_service=None,
+ input_type=_DPGETPHYSICALDISKSINPUT,
+ output_type=_DPBINARYOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\031\022\027/apis/v2/physical-disks')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='DPGetDisksPrediction',
+ full_name='proto.Diskprophet.DPGetDisksPrediction',
+ index=2,
+ containing_service=None,
+ input_type=_DPGETDISKSPREDICTIONINPUT,
+ output_type=_DPBINARYOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002%\022#/apis/v2/physical-disks/predictions')),
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_DISKPROPHET)
+
+DESCRIPTOR.services_by_name['Diskprophet'] = _DISKPROPHET
+
+
+_COLLECTION = _descriptor.ServiceDescriptor(
+ name='Collection',
+ full_name='proto.Collection',
+ file=DESCRIPTOR,
+ index=3,
+ options=None,
+ serialized_start=3490,
+ serialized_end=3837,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='CollectionHeartbeat',
+ full_name='proto.Collection.CollectionHeartbeat',
+ index=0,
+ containing_service=None,
+ input_type=_EMPTY,
+ output_type=_COLLECTIONHEARTBEATOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002\037\022\035/apis/v2/collection/heartbeat')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='PostDBRelay',
+ full_name='proto.Collection.PostDBRelay',
+ index=1,
+ containing_service=None,
+ input_type=_POSTDBRELAYINPUT,
+ output_type=_COLLECTIONMESSAGEOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002!\"\034/apis/v2/collection/relation:\001*')),
+ ),
+ _descriptor.MethodDescriptor(
+ name='PostMetrics',
+ full_name='proto.Collection.PostMetrics',
+ index=2,
+ containing_service=None,
+ input_type=_POSTMETRICSINPUT,
+ output_type=_COLLECTIONMESSAGEOUTPUT,
+ options=_descriptor._ParseOptions(descriptor_pb2.MethodOptions(), _b('\202\323\344\223\002 \"\033/apis/v2/collection/metrics:\001*')),
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_COLLECTION)
+
+DESCRIPTOR.services_by_name['Collection'] = _COLLECTION
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/pybind/mgr/diskprediction_cloud/common/client_pb2_grpc.py b/src/pybind/mgr/diskprediction_cloud/common/client_pb2_grpc.py
new file mode 100644
index 00000000..c1c32178
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/client_pb2_grpc.py
@@ -0,0 +1,395 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+import grpc
+
+import client_pb2 as mainServer__pb2
+
+
+class GeneralStub(object):
+ """-------------------------- General -------------------------------------
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.GeneralHeartbeat = channel.unary_unary(
+ '/proto.General/GeneralHeartbeat',
+ request_serializer=mainServer__pb2.Empty.SerializeToString,
+ response_deserializer=mainServer__pb2.GeneralHeartbeatOutput.FromString,
+ )
+ self.Ping = channel.unary_unary(
+ '/proto.General/Ping',
+ request_serializer=mainServer__pb2.Empty.SerializeToString,
+ response_deserializer=mainServer__pb2.PingOutout.FromString,
+ )
+ self.Test = channel.unary_unary(
+ '/proto.General/Test',
+ request_serializer=mainServer__pb2.TestInput.SerializeToString,
+ response_deserializer=mainServer__pb2.TestOutput.FromString,
+ )
+
+
+class GeneralServicer(object):
+ """-------------------------- General -------------------------------------
+ """
+
+ def GeneralHeartbeat(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Ping(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Test(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GeneralServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'GeneralHeartbeat': grpc.unary_unary_rpc_method_handler(
+ servicer.GeneralHeartbeat,
+ request_deserializer=mainServer__pb2.Empty.FromString,
+ response_serializer=mainServer__pb2.GeneralHeartbeatOutput.SerializeToString,
+ ),
+ 'Ping': grpc.unary_unary_rpc_method_handler(
+ servicer.Ping,
+ request_deserializer=mainServer__pb2.Empty.FromString,
+ response_serializer=mainServer__pb2.PingOutout.SerializeToString,
+ ),
+ 'Test': grpc.unary_unary_rpc_method_handler(
+ servicer.Test,
+ request_deserializer=mainServer__pb2.TestInput.FromString,
+ response_serializer=mainServer__pb2.TestOutput.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'proto.General', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class AccountStub(object):
+ """-------------------------- SERVER ACCOUNT ------------------------------
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.AccountHeartbeat = channel.unary_unary(
+ '/proto.Account/AccountHeartbeat',
+ request_serializer=mainServer__pb2.Empty.SerializeToString,
+ response_deserializer=mainServer__pb2.AccountHeartbeatOutput.FromString,
+ )
+ self.Login = channel.unary_unary(
+ '/proto.Account/Login',
+ request_serializer=mainServer__pb2.LoginInput.SerializeToString,
+ response_deserializer=mainServer__pb2.UserOutput.FromString,
+ )
+ self.Signup = channel.unary_unary(
+ '/proto.Account/Signup',
+ request_serializer=mainServer__pb2.SingupInput.SerializeToString,
+ response_deserializer=mainServer__pb2.SingupOutput.FromString,
+ )
+ self.ResendConfirmCode = channel.unary_unary(
+ '/proto.Account/ResendConfirmCode',
+ request_serializer=mainServer__pb2.ResendConfirmCodeInput.SerializeToString,
+ response_deserializer=mainServer__pb2.GeneralMsgOutput.FromString,
+ )
+ self.Confirm = channel.unary_unary(
+ '/proto.Account/Confirm',
+ request_serializer=mainServer__pb2.ConfirmInput.SerializeToString,
+ response_deserializer=mainServer__pb2.GeneralMsgOutput.FromString,
+ )
+ self.GetUsersByStatus = channel.unary_unary(
+ '/proto.Account/GetUsersByStatus',
+ request_serializer=mainServer__pb2.GetUsersByStatusInput.SerializeToString,
+ response_deserializer=mainServer__pb2.GetUsersByStatusOutput.FromString,
+ )
+ self.DeleteUser = channel.unary_unary(
+ '/proto.Account/DeleteUser',
+ request_serializer=mainServer__pb2.DeleteUserInput.SerializeToString,
+ response_deserializer=mainServer__pb2.GeneralMsgOutput.FromString,
+ )
+ self.UpdateUserStatus = channel.unary_unary(
+ '/proto.Account/UpdateUserStatus',
+ request_serializer=mainServer__pb2.UpdateUserStatusInput.SerializeToString,
+ response_deserializer=mainServer__pb2.GeneralMsgOutput.FromString,
+ )
+
+
+class AccountServicer(object):
+ """-------------------------- SERVER ACCOUNT ------------------------------
+ """
+
+ def AccountHeartbeat(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Login(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Signup(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def ResendConfirmCode(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Confirm(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetUsersByStatus(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def DeleteUser(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def UpdateUserStatus(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_AccountServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'AccountHeartbeat': grpc.unary_unary_rpc_method_handler(
+ servicer.AccountHeartbeat,
+ request_deserializer=mainServer__pb2.Empty.FromString,
+ response_serializer=mainServer__pb2.AccountHeartbeatOutput.SerializeToString,
+ ),
+ 'Login': grpc.unary_unary_rpc_method_handler(
+ servicer.Login,
+ request_deserializer=mainServer__pb2.LoginInput.FromString,
+ response_serializer=mainServer__pb2.UserOutput.SerializeToString,
+ ),
+ 'Signup': grpc.unary_unary_rpc_method_handler(
+ servicer.Signup,
+ request_deserializer=mainServer__pb2.SingupInput.FromString,
+ response_serializer=mainServer__pb2.SingupOutput.SerializeToString,
+ ),
+ 'ResendConfirmCode': grpc.unary_unary_rpc_method_handler(
+ servicer.ResendConfirmCode,
+ request_deserializer=mainServer__pb2.ResendConfirmCodeInput.FromString,
+ response_serializer=mainServer__pb2.GeneralMsgOutput.SerializeToString,
+ ),
+ 'Confirm': grpc.unary_unary_rpc_method_handler(
+ servicer.Confirm,
+ request_deserializer=mainServer__pb2.ConfirmInput.FromString,
+ response_serializer=mainServer__pb2.GeneralMsgOutput.SerializeToString,
+ ),
+ 'GetUsersByStatus': grpc.unary_unary_rpc_method_handler(
+ servicer.GetUsersByStatus,
+ request_deserializer=mainServer__pb2.GetUsersByStatusInput.FromString,
+ response_serializer=mainServer__pb2.GetUsersByStatusOutput.SerializeToString,
+ ),
+ 'DeleteUser': grpc.unary_unary_rpc_method_handler(
+ servicer.DeleteUser,
+ request_deserializer=mainServer__pb2.DeleteUserInput.FromString,
+ response_serializer=mainServer__pb2.GeneralMsgOutput.SerializeToString,
+ ),
+ 'UpdateUserStatus': grpc.unary_unary_rpc_method_handler(
+ servicer.UpdateUserStatus,
+ request_deserializer=mainServer__pb2.UpdateUserStatusInput.FromString,
+ response_serializer=mainServer__pb2.GeneralMsgOutput.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'proto.Account', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class DiskprophetStub(object):
+ """------------------------ SERVER DISKPROPHET ---------------------------
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.DPHeartbeat = channel.unary_unary(
+ '/proto.Diskprophet/DPHeartbeat',
+ request_serializer=mainServer__pb2.Empty.SerializeToString,
+ response_deserializer=mainServer__pb2.DPHeartbeatOutput.FromString,
+ )
+ self.DPGetPhysicalDisks = channel.unary_unary(
+ '/proto.Diskprophet/DPGetPhysicalDisks',
+ request_serializer=mainServer__pb2.DPGetPhysicalDisksInput.SerializeToString,
+ response_deserializer=mainServer__pb2.DPBinaryOutput.FromString,
+ )
+ self.DPGetDisksPrediction = channel.unary_unary(
+ '/proto.Diskprophet/DPGetDisksPrediction',
+ request_serializer=mainServer__pb2.DPGetDisksPredictionInput.SerializeToString,
+ response_deserializer=mainServer__pb2.DPBinaryOutput.FromString,
+ )
+
+
+class DiskprophetServicer(object):
+ """------------------------ SERVER DISKPROPHET ---------------------------
+ """
+
+ def DPHeartbeat(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def DPGetPhysicalDisks(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def DPGetDisksPrediction(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_DiskprophetServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'DPHeartbeat': grpc.unary_unary_rpc_method_handler(
+ servicer.DPHeartbeat,
+ request_deserializer=mainServer__pb2.Empty.FromString,
+ response_serializer=mainServer__pb2.DPHeartbeatOutput.SerializeToString,
+ ),
+ 'DPGetPhysicalDisks': grpc.unary_unary_rpc_method_handler(
+ servicer.DPGetPhysicalDisks,
+ request_deserializer=mainServer__pb2.DPGetPhysicalDisksInput.FromString,
+ response_serializer=mainServer__pb2.DPBinaryOutput.SerializeToString,
+ ),
+ 'DPGetDisksPrediction': grpc.unary_unary_rpc_method_handler(
+ servicer.DPGetDisksPrediction,
+ request_deserializer=mainServer__pb2.DPGetDisksPredictionInput.FromString,
+ response_serializer=mainServer__pb2.DPBinaryOutput.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'proto.Diskprophet', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class CollectionStub(object):
+ """------------------------ SERVER Collection ---------------------------
+
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.CollectionHeartbeat = channel.unary_unary(
+ '/proto.Collection/CollectionHeartbeat',
+ request_serializer=mainServer__pb2.Empty.SerializeToString,
+ response_deserializer=mainServer__pb2.CollectionHeartbeatOutput.FromString,
+ )
+ self.PostDBRelay = channel.unary_unary(
+ '/proto.Collection/PostDBRelay',
+ request_serializer=mainServer__pb2.PostDBRelayInput.SerializeToString,
+ response_deserializer=mainServer__pb2.CollectionMessageOutput.FromString,
+ )
+ self.PostMetrics = channel.unary_unary(
+ '/proto.Collection/PostMetrics',
+ request_serializer=mainServer__pb2.PostMetricsInput.SerializeToString,
+ response_deserializer=mainServer__pb2.CollectionMessageOutput.FromString,
+ )
+
+
+class CollectionServicer(object):
+ """------------------------ SERVER Collection ---------------------------
+
+ """
+
+ def CollectionHeartbeat(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def PostDBRelay(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def PostMetrics(self, request, context):
+ # missing associated documentation comment in .proto file
+ pass
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_CollectionServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'CollectionHeartbeat': grpc.unary_unary_rpc_method_handler(
+ servicer.CollectionHeartbeat,
+ request_deserializer=mainServer__pb2.Empty.FromString,
+ response_serializer=mainServer__pb2.CollectionHeartbeatOutput.SerializeToString,
+ ),
+ 'PostDBRelay': grpc.unary_unary_rpc_method_handler(
+ servicer.PostDBRelay,
+ request_deserializer=mainServer__pb2.PostDBRelayInput.FromString,
+ response_serializer=mainServer__pb2.CollectionMessageOutput.SerializeToString,
+ ),
+ 'PostMetrics': grpc.unary_unary_rpc_method_handler(
+ servicer.PostMetrics,
+ request_deserializer=mainServer__pb2.PostMetricsInput.FromString,
+ response_serializer=mainServer__pb2.CollectionMessageOutput.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'proto.Collection', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
diff --git a/src/pybind/mgr/diskprediction_cloud/common/clusterdata.py b/src/pybind/mgr/diskprediction_cloud/common/clusterdata.py
new file mode 100644
index 00000000..45add693
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/clusterdata.py
@@ -0,0 +1,464 @@
+"""
+Ceph database API
+
+"""
+from __future__ import absolute_import
+
+import json
+import rbd
+from mgr_module import CommandResult
+
+GB = 1024 * 1024 * 1024
+
+
+RBD_FEATURES_NAME_MAPPING = {
+ rbd.RBD_FEATURE_LAYERING: 'layering',
+ rbd.RBD_FEATURE_STRIPINGV2: 'striping',
+ rbd.RBD_FEATURE_EXCLUSIVE_LOCK: 'exclusive-lock',
+ rbd.RBD_FEATURE_OBJECT_MAP: 'object-map',
+ rbd.RBD_FEATURE_FAST_DIFF: 'fast-diff',
+ rbd.RBD_FEATURE_DEEP_FLATTEN: 'deep-flatten',
+ rbd.RBD_FEATURE_JOURNALING: 'journaling',
+ rbd.RBD_FEATURE_DATA_POOL: 'data-pool',
+ rbd.RBD_FEATURE_OPERATIONS: 'operations',
+}
+
+
+def differentiate(data1, data2):
+ """
+ # >>> times = [0, 2]
+ # >>> values = [100, 101]
+ # >>> differentiate(*zip(times, values))
+ 0.5
+ """
+ return (data2[1] - data1[1]) / float(data2[0] - data1[0])
+
+
+class ClusterAPI(object):
+
+ def __init__(self, module_obj):
+ self.module = module_obj
+
+ @staticmethod
+ def format_bitmask(features):
+ """
+ Formats the bitmask:
+ # >>> format_bitmask(45)
+ ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']
+ """
+ names = [val for key, val in RBD_FEATURES_NAME_MAPPING.items()
+ if key & features == key]
+ return sorted(names)
+
+ def _open_connection(self, pool_name='device_health_metrics'):
+ pools = self.module.rados.list_pools()
+ is_pool = False
+ for pool in pools:
+ if pool == pool_name:
+ is_pool = True
+ break
+ if not is_pool:
+ self.module.log.debug('create %s pool' % pool_name)
+ # create pool
+ result = CommandResult('')
+ self.module.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd pool create',
+ 'format': 'json',
+ 'pool': pool_name,
+ 'pg_num': 1,
+ }), '')
+ r, outb, outs = result.wait()
+ assert r == 0
+
+ # set pool application
+ result = CommandResult('')
+ self.module.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd pool application enable',
+ 'format': 'json',
+ 'pool': pool_name,
+ 'app': 'mgr_devicehealth',
+ }), '')
+ r, outb, outs = result.wait()
+ assert r == 0
+
+ ioctx = self.module.rados.open_ioctx(pool_name)
+ return ioctx
+
+ @classmethod
+ def _rbd_disk_usage(cls, image, snaps, whole_object=True):
+ class DUCallback(object):
+ def __init__(self):
+ self.used_size = 0
+
+ def __call__(self, offset, length, exists):
+ if exists:
+ self.used_size += length
+ snap_map = {}
+ prev_snap = None
+ total_used_size = 0
+ for _, size, name in snaps:
+ image.set_snap(name)
+ du_callb = DUCallback()
+ image.diff_iterate(0, size, prev_snap, du_callb,
+ whole_object=whole_object)
+ snap_map[name] = du_callb.used_size
+ total_used_size += du_callb.used_size
+ prev_snap = name
+ return total_used_size, snap_map
+
+ def _rbd_image(self, ioctx, pool_name, image_name):
+ with rbd.Image(ioctx, image_name) as img:
+ stat = img.stat()
+ stat['name'] = image_name
+ stat['id'] = img.id()
+ stat['pool_name'] = pool_name
+ features = img.features()
+ stat['features'] = features
+ stat['features_name'] = self.format_bitmask(features)
+
+ # the following keys are deprecated
+ del stat['parent_pool']
+ del stat['parent_name']
+ stat['timestamp'] = '{}Z'.format(img.create_timestamp()
+ .isoformat())
+ stat['stripe_count'] = img.stripe_count()
+ stat['stripe_unit'] = img.stripe_unit()
+ stat['data_pool'] = None
+ try:
+ parent_info = img.parent_info()
+ stat['parent'] = {
+ 'pool_name': parent_info[0],
+ 'image_name': parent_info[1],
+ 'snap_name': parent_info[2]
+ }
+ except rbd.ImageNotFound:
+ # no parent image
+ stat['parent'] = None
+ # snapshots
+ stat['snapshots'] = []
+ for snap in img.list_snaps():
+ snap['timestamp'] = '{}Z'.format(
+ img.get_snap_timestamp(snap['id']).isoformat())
+ snap['is_protected'] = img.is_protected_snap(snap['name'])
+ snap['used_bytes'] = None
+ snap['children'] = []
+ img.set_snap(snap['name'])
+ for child_pool_name, child_image_name in img.list_children():
+ snap['children'].append({
+ 'pool_name': child_pool_name,
+ 'image_name': child_image_name
+ })
+ stat['snapshots'].append(snap)
+ # disk usage
+ if 'fast-diff' in stat['features_name']:
+ snaps = [(s['id'], s['size'], s['name'])
+ for s in stat['snapshots']]
+ snaps.sort(key=lambda s: s[0])
+ snaps += [(snaps[-1][0]+1 if snaps else 0, stat['size'], None)]
+ total_prov_bytes, snaps_prov_bytes = self._rbd_disk_usage(
+ img, snaps, True)
+ stat['total_disk_usage'] = total_prov_bytes
+ for snap, prov_bytes in snaps_prov_bytes.items():
+ if snap is None:
+ stat['disk_usage'] = prov_bytes
+ continue
+ for ss in stat['snapshots']:
+ if ss['name'] == snap:
+ ss['disk_usage'] = prov_bytes
+ break
+ else:
+ stat['total_disk_usage'] = None
+ stat['disk_usage'] = None
+ return stat
+
+ def get_rbd_list(self, pool_name=None):
+ if pool_name:
+ pools = [pool_name]
+ else:
+ pools = []
+ for data in self.get_osd_pools():
+ pools.append(data['pool_name'])
+ result = []
+ for pool in pools:
+ rbd_inst = rbd.RBD()
+ with self._open_connection(str(pool)) as ioctx:
+ names = rbd_inst.list(ioctx)
+ for name in names:
+ try:
+ stat = self._rbd_image(ioctx, pool_name, name)
+ except rbd.ImageNotFound:
+ continue
+ result.append(stat)
+ return result
+
+ def get_object_pg_info(self, pool_name, object_name):
+ result = CommandResult('')
+ data_jaon = {}
+ self.module.send_command(
+ result, 'mon', '', json.dumps({
+ 'prefix': 'osd map',
+ 'format': 'json',
+ 'pool': pool_name,
+ 'object': object_name,
+ }), '')
+ ret, outb, outs = result.wait()
+ try:
+ if outb:
+ data_jaon = json.loads(outb)
+ else:
+ self.module.log.error('unable to get %s pg info' % pool_name)
+ except Exception as e:
+ self.module.log.error(
+ 'unable to get %s pg, error: %s' % (pool_name, str(e)))
+ return data_jaon
+
+ @staticmethod
+ def _list_objects(ioctx, image_id):
+ objects = []
+ object_iterator = ioctx.list_objects()
+ while True:
+ try:
+ rados_object = object_iterator.next()
+ if image_id is None:
+ objects.append(str(rados_object.key))
+ else:
+ v = str(rados_object.key).split('.')
+ if len(v) >= 2 and v[1] == image_id:
+ objects.append(str(rados_object.key))
+ except StopIteration:
+ break
+ return objects
+
+ def get_rbd_info(self, pool_name, image_name):
+ with self._open_connection(pool_name) as ioctx:
+ try:
+ stat = self._rbd_image(ioctx, pool_name, image_name)
+ if stat.get('id'):
+ objects = self._list_objects(ioctx, stat.get('id'))
+ if objects:
+ stat['objects'] = objects
+ stat['pgs'] = list()
+ for obj_name in objects:
+ pgs_data = self.get_object_pg_info(pool_name, obj_name)
+ stat['pgs'].extend([pgs_data])
+ except rbd.ImageNotFound:
+ stat = {}
+ return stat
+
+ def get_pool_objects(self, pool_name, image_id=None):
+ # list_objects
+ try:
+ with self._open_connection(pool_name) as ioctx:
+ objects = self._list_objects(ioctx, image_id)
+ except:
+ objects = []
+ return objects
+
+ def get_ceph_df_state(self):
+ ceph_stats = self.module.get('df').get('stats', {})
+ if not ceph_stats:
+ return {'total_size': 0, 'avail_size': 0, 'raw_used_size': 0, 'raw_used_percent': 0}
+ total_size = round(float(ceph_stats.get('total_bytes', 0)) / GB)
+ avail_size = round(float(ceph_stats.get('total_avail_bytes', 0)) / GB, 2)
+ raw_used_size = round(float(ceph_stats.get('total_used_bytes', 0)) / GB, 2)
+ if total_size != 0:
+ raw_used_percent = round(float(raw_used_size) / float(total_size) * 100, 2)
+ else:
+ raw_used_percent = 0
+ return {'total_size': total_size, 'avail_size': avail_size, 'raw_used_size': raw_used_size,
+ 'used_percent': raw_used_percent}
+
+ def get_osd_metadata(self, osd_id=None):
+ if osd_id is not None:
+ return self.module.get('osd_metadata')[str(osd_id)]
+ return self.module.get('osd_metadata')
+
+ def get_mgr_metadata(self, mgr_id):
+ return self.module.get_metadata('mgr', mgr_id)
+
+ def get_osd_epoch(self):
+ return self.module.get('osd_map').get('epoch', 0)
+
+ def get_osds(self):
+ return self.module.get('osd_map').get('osds', [])
+
+ def get_max_osd(self):
+ return self.module.get('osd_map').get('max_osd', '')
+
+ def get_osd_pools(self):
+ return self.module.get('osd_map').get('pools', [])
+
+ def get_pool_bytes_used(self, pool_id):
+ bytes_used = None
+ pools = self.module.get('df').get('pools', [])
+ for pool in pools:
+ if pool_id == pool['id']:
+ bytes_used = pool['stats']['bytes_used']
+ return bytes_used
+
+ def get_cluster_id(self):
+ return self.module.get('mon_map').get('fsid')
+
+ def get_health_status(self):
+ health = json.loads(self.module.get('health')['json'])
+ return health.get('status')
+
+ def get_health_checks(self):
+ health = json.loads(self.module.get('health')['json'])
+ if health.get('checks'):
+ message = ''
+ checks = health['checks']
+ for key in checks.keys():
+ if message:
+ message += ';'
+ if checks[key].get('summary', {}).get('message', ''):
+ message += checks[key]['summary']['message']
+ return message
+ else:
+ return ''
+
+ def get_mons(self):
+ return self.module.get('mon_map').get('mons', [])
+
+ def get_mon_status(self):
+ mon_status = json.loads(self.module.get('mon_status')['json'])
+ return mon_status
+
+ def get_osd_smart(self, osd_id, device_id=None):
+ osd_devices = []
+ osd_smart = {}
+ devices = self.module.get('devices')
+ for dev in devices.get('devices', []):
+ osd = ''
+ daemons = dev.get('daemons', [])
+ for daemon in daemons:
+ if daemon[4:] != str(osd_id):
+ continue
+ osd = daemon
+ if not osd:
+ continue
+ if dev.get('devid') and dev.get('devid') not in osd_devices:
+ osd_devices.append(dev.get('devid'))
+ for dev_id in osd_devices:
+ o_key = ''
+ if device_id and dev_id != device_id:
+ continue
+ smart_data = self.get_device_health(dev_id)
+ if smart_data:
+ o_key = sorted(smart_data.keys(), reverse=True)[0]
+ if o_key and smart_data and smart_data.values():
+ dev_smart = smart_data[o_key]
+ if dev_smart:
+ osd_smart[dev_id] = dev_smart
+ return osd_smart
+
+ def get_device_health(self, devid):
+ health_data = {}
+ try:
+ r, outb, outs = self.module.remote('devicehealth', 'show_device_metrics', devid=devid, sample='')
+ if r != 0:
+ self.module.log.error('failed to get device %s health', devid)
+ health_data = {}
+ else:
+ health_data = json.loads(outb)
+ except Exception as e:
+ self.module.log.error('failed to get device %s health data due to %s', devid, str(e))
+ return health_data
+
+ def get_osd_hostname(self, osd_id):
+ result = ''
+ osd_metadata = self.get_osd_metadata(osd_id)
+ if osd_metadata:
+ osd_host = osd_metadata.get('hostname', 'None')
+ result = osd_host
+ return result
+
+ def get_osd_device_id(self, osd_id):
+ result = {}
+ if not str(osd_id).isdigit():
+ if str(osd_id)[0:4] == 'osd.':
+ osdid = osd_id[4:]
+ else:
+ raise Exception('not a valid <osd.NNN> id or number')
+ else:
+ osdid = osd_id
+ osd_metadata = self.get_osd_metadata(osdid)
+ if osd_metadata:
+ osd_device_ids = osd_metadata.get('device_ids', '')
+ if osd_device_ids:
+ result = {}
+ for osd_device_id in osd_device_ids.split(','):
+ dev_name = ''
+ if len(str(osd_device_id).split('=')) >= 2:
+ dev_name = osd_device_id.split('=')[0]
+ dev_id = osd_device_id.split('=')[1]
+ else:
+ dev_id = osd_device_id
+ if dev_name:
+ result[dev_name] = {'dev_id': dev_id}
+ return result
+
+ def get_file_systems(self):
+ return self.module.get('fs_map').get('filesystems', [])
+
+ def set_device_life_expectancy(self, device_id, from_date, to_date=None):
+ result = CommandResult('')
+
+ if to_date is None:
+ self.module.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device set-life-expectancy',
+ 'devid': device_id,
+ 'from': from_date
+ }), '')
+ else:
+ self.module.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device set-life-expectancy',
+ 'devid': device_id,
+ 'from': from_date,
+ 'to': to_date
+ }), '')
+ ret, outb, outs = result.wait()
+ if ret != 0:
+ self.module.log.error(
+ 'failed to set device life expectancy, %s' % outs)
+ return ret
+
+ def reset_device_life_expectancy(self, device_id):
+ result = CommandResult('')
+ self.module.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device rm-life-expectancy',
+ 'devid': device_id
+ }), '')
+ ret, outb, outs = result.wait()
+ if ret != 0:
+ self.module.log.error(
+ 'failed to reset device life expectancy, %s' % outs)
+ return ret
+
+ def get_server(self, hostname):
+ return self.module.get_server(hostname)
+
+ def get_configuration(self, key):
+ return self.module.get_configuration(key)
+
+ def get_rate(self, svc_type, svc_name, path):
+ """returns most recent rate"""
+ data = self.module.get_counter(svc_type, svc_name, path)[path]
+
+ if data and len(data) > 1:
+ return differentiate(*data[-2:])
+ return 0.0
+
+ def get_latest(self, daemon_type, daemon_name, counter):
+ return self.module.get_latest(daemon_type, daemon_name, counter)
+
+ def get_pgs_up_by_poolid(self, poolid):
+ pgs = {}
+ try:
+ osd_map = self.module.get_osdmap()
+ if not osd_map:
+ return {}
+ pgs = osd_map.map_pool_pgs_up(int(poolid))
+ return pgs
+ except:
+ return {}
diff --git a/src/pybind/mgr/diskprediction_cloud/common/cypher.py b/src/pybind/mgr/diskprediction_cloud/common/cypher.py
new file mode 100644
index 00000000..7b7b60e5
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/cypher.py
@@ -0,0 +1,71 @@
+from __future__ import absolute_import
+
+import time
+
+
+class NodeInfo(object):
+ """ Neo4j Node information """
+ def __init__(self, label, domain_id, name, meta):
+ self.label = label
+ self.domain_id = domain_id
+ self.name = name
+ self.meta = meta
+
+
+class CypherOP(object):
+ """ Cypher Operation """
+
+ @staticmethod
+ def update(node, key, value, timestamp=int(time.time()*(1000**3))):
+ result = ''
+ if isinstance(node, NodeInfo):
+ if key != 'time':
+ cy_value = '\'%s\'' % value
+ else:
+ cy_value = value
+ result = \
+ 'set %s.%s=case when %s.time >= %s then %s.%s ELSE %s end' % (
+ node.label, key, node.label, timestamp, node.label, key,
+ cy_value)
+ return result
+
+ @staticmethod
+ def create_or_merge(node, timestamp=int(time.time()*(1000**3))):
+ result = ''
+ if isinstance(node, NodeInfo):
+ meta_list = []
+ if isinstance(node.meta, dict):
+ for key, value in node.meta.items():
+ meta_list.append(CypherOP.update(node, key, value, timestamp))
+ domain_id = '{domainId:\'%s\'}' % node.domain_id
+ if meta_list:
+ result = 'merge (%s:%s %s) %s %s %s' % (
+ node.label, node.label,
+ domain_id,
+ CypherOP.update(node, 'name', node.name, timestamp),
+ ' '.join(meta_list),
+ CypherOP.update(node, 'time', timestamp, timestamp))
+ else:
+ result = 'merge (%s:%s %s) %s %s' % (
+ node.label, node.label,
+ domain_id,
+ CypherOP.update(node, 'name', node.name, timestamp),
+ CypherOP.update(node, 'time', timestamp, timestamp))
+ return result
+
+ @staticmethod
+ def add_link(snode, dnode, relationship, timestamp=None):
+ result = ''
+ if timestamp is None:
+ timestamp = int(time.time()*(1000**3))
+ if isinstance(snode, NodeInfo) and isinstance(dnode, NodeInfo):
+ cy_snode = CypherOP.create_or_merge(snode, timestamp)
+ cy_dnode = CypherOP.create_or_merge(dnode, timestamp)
+ target = snode.label + dnode.label
+ link = 'merge (%s)-[%s:%s]->(%s) set %s.time=case when %s.time >= %s then %s.time ELSE %s end' % (
+ snode.label, target, relationship,
+ dnode.label, target,
+ target, timestamp,
+ target, timestamp)
+ result = '%s %s %s' % (cy_snode, cy_dnode, link)
+ return result
diff --git a/src/pybind/mgr/diskprediction_cloud/common/grpcclient.py b/src/pybind/mgr/diskprediction_cloud/common/grpcclient.py
new file mode 100644
index 00000000..5a1d5e7e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/grpcclient.py
@@ -0,0 +1,242 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+import grpc
+import json
+from logging import getLogger
+import time
+
+from . import DummyResonse
+from . import client_pb2
+from . import client_pb2_grpc
+
+
+def gen_configuration(**kwargs):
+ configuration = {
+ 'host': kwargs.get('host', 'api.diskprophet.com'),
+ 'user': kwargs.get('user'),
+ 'password': kwargs.get('password'),
+ 'port': kwargs.get('port', 31400),
+ 'mgr_inst': kwargs.get('mgr_inst', None),
+ 'cert_context': kwargs.get('cert_context'),
+ 'ssl_target_name': kwargs.get('ssl_target_name', 'api.diskprophet.com'),
+ 'default_authority': kwargs.get('default_authority', 'api.diskprophet.com')}
+ return configuration
+
+
+class GRPcClient(object):
+
+ def __init__(self, configuration):
+ self.auth = None
+ self.host = configuration.get('host')
+ self.port = configuration.get('port')
+ if configuration.get('user') and configuration.get('password'):
+ self.auth = (
+ ('account', configuration.get('user')),
+ ('password', configuration.get('password')))
+ self.cert_context = configuration.get('cert_context')
+ self.ssl_target_name = configuration.get('ssl_target_name')
+ self.default_authority = configuration.get('default_authority')
+ self.mgr_inst = configuration.get('mgr_inst')
+ if self.mgr_inst:
+ self._logger = self.mgr_inst.log
+ else:
+ self._logger = getLogger()
+ self._client = self._get_channel()
+
+ def close(self):
+ if self._client:
+ self._client.close()
+
+ @staticmethod
+ def connectivity_update(connectivity):
+ pass
+
+ def _get_channel(self):
+ try:
+ creds = grpc.ssl_channel_credentials(
+ root_certificates=self.cert_context)
+ channel = \
+ grpc.secure_channel('{}:{}'.format(
+ self.host, self.port), creds,
+ options=(('grpc.ssl_target_name_override', self.ssl_target_name,),
+ ('grpc.default_authority', self.default_authority),))
+ channel.subscribe(self.connectivity_update, try_to_connect=True)
+ return channel
+ except Exception as e:
+ self._logger.error(
+ 'failed to create connection exception: {}'.format(
+ ';'.join(str(e).split('\n\t'))))
+ return None
+
+ def test_connection(self):
+ try:
+ stub_accout = client_pb2_grpc.AccountStub(self._client)
+ result = stub_accout.AccountHeartbeat(client_pb2.Empty())
+ self._logger.debug('text connection result: {}'.format(str(result)))
+ if result and "is alive" in str(result.message):
+ return True
+ else:
+ return False
+ except Exception as e:
+ self._logger.error(
+ 'failed to test connection exception: {}'.format(
+ ';'.join(str(e).split('\n\t'))))
+ return False
+
+ def _send_metrics(self, data, measurement):
+ status_info = dict()
+ status_info['measurement'] = None
+ status_info['success_count'] = 0
+ status_info['failure_count'] = 0
+ for dp_data in data:
+ d_measurement = dp_data.measurement
+ if not d_measurement:
+ status_info['measurement'] = measurement
+ else:
+ status_info['measurement'] = d_measurement
+ tag_list = []
+ field_list = []
+ for name in dp_data.tags:
+ tag = '{}={}'.format(name, dp_data.tags[name])
+ tag_list.append(tag)
+ for name in dp_data.fields:
+ if dp_data.fields[name] is None:
+ continue
+ if isinstance(dp_data.fields[name], str):
+ field = '{}=\"{}\"'.format(name, dp_data.fields[name])
+ elif isinstance(dp_data.fields[name], bool):
+ field = '{}={}'.format(name,
+ str(dp_data.fields[name]).lower())
+ elif (isinstance(dp_data.fields[name], int) or
+ isinstance(dp_data.fields[name], long)):
+ field = '{}={}i'.format(name, dp_data.fields[name])
+ else:
+ field = '{}={}'.format(name, dp_data.fields[name])
+ field_list.append(field)
+ data = '{},{} {} {}'.format(
+ status_info['measurement'],
+ ','.join(tag_list),
+ ','.join(field_list),
+ int(time.time() * 1000 * 1000 * 1000))
+ try:
+ resp = self._send_info(data=[data], measurement=status_info['measurement'])
+ status_code = resp.status_code
+ if 200 <= status_code < 300:
+ self._logger.debug(
+ '{} send diskprediction api success(ret: {})'.format(
+ status_info['measurement'], status_code))
+ status_info['success_count'] += 1
+ else:
+ self._logger.error(
+ 'return code: {}, content: {}'.format(
+ status_code, resp.content))
+ status_info['failure_count'] += 1
+ except Exception as e:
+ status_info['failure_count'] += 1
+ self._logger.error(str(e))
+ return status_info
+
+ def _send_db_relay(self, data, measurement):
+ status_info = dict()
+ status_info['measurement'] = measurement
+ status_info['success_count'] = 0
+ status_info['failure_count'] = 0
+ for dp_data in data:
+ try:
+ resp = self._send_info(
+ data=[dp_data.fields['cmd']], measurement=measurement)
+ status_code = resp.status_code
+ if 200 <= status_code < 300:
+ self._logger.debug(
+ '{} send diskprediction api success(ret: {})'.format(
+ measurement, status_code))
+ status_info['success_count'] += 1
+ else:
+ self._logger.error(
+ 'return code: {}, content: {}'.format(
+ status_code, resp.content))
+ status_info['failure_count'] += 1
+ except Exception as e:
+ status_info['failure_count'] += 1
+ self._logger.error(str(e))
+ return status_info
+
+ def send_info(self, data, measurement):
+ """
+ :param data: data structure
+ :param measurement: data measurement class name
+ :return:
+ status_info = {
+ 'success_count': <count>,
+ 'failure_count': <count>
+ }
+ """
+ if measurement == 'db_relay':
+ return self._send_db_relay(data, measurement)
+ else:
+ return self._send_metrics(data, measurement)
+
+ def _send_info(self, data, measurement):
+ resp = DummyResonse()
+ try:
+ stub_collection = client_pb2_grpc.CollectionStub(self._client)
+ if measurement == 'db_relay':
+ result = stub_collection.PostDBRelay(
+ client_pb2.PostDBRelayInput(cmds=data), metadata=self.auth)
+ else:
+ result = stub_collection.PostMetrics(
+ client_pb2.PostMetricsInput(points=data), metadata=self.auth)
+ if result and 'success' in str(result.message).lower():
+ resp.status_code = 200
+ resp.content = ''
+ else:
+ resp.status_code = 400
+ resp.content = ';'.join(str(result).split('\n\t'))
+ self._logger.error(
+ 'failed to send info: {}'.format(resp.content))
+ except Exception as e:
+ resp.status_code = 400
+ resp.content = ';'.join(str(e).split('\n\t'))
+ self._logger.error(
+ 'failed to send info exception: {}'.format(resp.content))
+ return resp
+
+ def query_info(self, host_domain_id, disk_domain_id, measurement):
+ resp = DummyResonse()
+ try:
+ stub_dp = client_pb2_grpc.DiskprophetStub(self._client)
+ predicted = stub_dp.DPGetDisksPrediction(
+ client_pb2.DPGetDisksPredictionInput(
+ physicalDiskIds=disk_domain_id),
+ metadata=self.auth)
+ if predicted and hasattr(predicted, 'data'):
+ resp.status_code = 200
+ resp.content = ''
+ resp_json = json.loads(predicted.data)
+ rc = resp_json.get('results', [])
+ if rc:
+ series = rc[0].get('series', [])
+ if series:
+ values = series[0].get('values', [])
+ if not values:
+ resp.resp_json = {}
+ else:
+ columns = series[0].get('columns', [])
+ for item in values:
+ # get prediction key and value from server.
+ for name, value in zip(columns, item):
+ # process prediction data
+ resp.resp_json[name] = value
+ self._logger.debug("query {}:{} result:{}".format(host_domain_id, disk_domain_id, resp))
+ return resp
+ else:
+ resp.status_code = 400
+ resp.content = ''
+ resp.resp_json = {'error': ';'.join(str(predicted).split('\n\t'))}
+ self._logger.debug("query {}:{} result:{}".format(host_domain_id, disk_domain_id, resp))
+ return resp
+ except Exception as e:
+ resp.status_code = 400
+ resp.content = ';'.join(str(e).split('\n\t'))
+ resp.resp_json = {'error': resp.content}
+ self._logger.debug("query {}:{} result:{}".format(host_domain_id, disk_domain_id, resp))
+ return resp
diff --git a/src/pybind/mgr/diskprediction_cloud/common/server.crt b/src/pybind/mgr/diskprediction_cloud/common/server.crt
new file mode 100644
index 00000000..d72c9d2f
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/common/server.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICsjCCAZoCCQCKLjrHOzCTrDANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBh
+cGkuZmVkZXJhdG9yLmFpMB4XDTE4MDgwMjA2NDg0N1oXDTI4MDczMDA2NDg0N1ow
+GzEZMBcGA1UEAwwQYXBpLmZlZGVyYXRvci5haTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAJkDL/VoLbI+Rc1GXkZwpN8n4e7HhIk1iK98yhXegoH8g6ZZ
+uVVlUW/zNO0V5W9IgiSBqEWOEf9heWj7mIbbxl437W1LpR4V0LKR2dbY7ZMwlB3L
+ZJYxtziZYu1g4Fn9hDnVJIXVmXFpF62wHd2ZSY7FyUF/OGetxLSfoOMkTHY8A8HB
+92vQfoFjgx1e23lLgTO2VpucmU/qXiF+xI/K6kkrMnGJi4xBL29i3aKRRNktVUHf
+Zs6JhBKl4sbvkW5m5AECW4c0XxVJotTLoPUjx4rxp0k5S1aQSYSS+0z96eVY0w8J
+ungiWEj7lLqwEGKjOzfjDLsczZIcZZcQSQwb3qcCAwEAATANBgkqhkiG9w0BAQsF
+AAOCAQEADwfBrHsvPmUD8CTx8lpVcqrOlHc7ftW3hb11vWwwfJw4fBiJ8DoB496x
+SAP2CJyDnSLdyvVueKLjiRFBm96W76nbMeP9+CkktGRUbLjkByv/v+7WSxRrukDC
+yR6IXqQJe4ADcYkVYoUMx3frBQzFtS7hni0FPvl3AN55TvTXqed61CdN9zdw9Ezn
+yn0oy3BbT5h/zNHefTQBzgQhW62C5YdTRtS6VVWV/k1kLz0GVG1eMtAqueUCxFeM
+g1mXYz2/Cm5C8pszZfiP+a/QV1z/3QgRUp0i0yVLiteqNDCPv6bc767VQEuXok9p
+NDuKElVxdA0WD9cbnBXiyfeMOQnjQw==
+-----END CERTIFICATE-----
diff --git a/src/pybind/mgr/diskprediction_cloud/module.py b/src/pybind/mgr/diskprediction_cloud/module.py
new file mode 100644
index 00000000..5052d55e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/module.py
@@ -0,0 +1,454 @@
+"""
+diskprediction with cloud predictor
+"""
+from __future__ import absolute_import
+
+import base64
+from datetime import datetime
+import errno
+import json
+from mgr_module import MgrModule
+import os
+from threading import Event
+
+try:
+ from string import maketrans
+except ImportError:
+ maketrans = str.maketrans
+
+from .common import DP_MGR_STAT_ENABLED, DP_MGR_STAT_DISABLED
+from .task import MetricsRunner, SmartRunner, PredictRunner, TestRunner
+
+TIME_DAYS = 24*60*60
+TIME_WEEK = TIME_DAYS * 7
+DP_AGENTS = [MetricsRunner, SmartRunner, PredictRunner]
+CUSTOMER_ALPHABET = "ABCDEFG&HIJKLMN@OQRS.TUV(WXYZabcd)efghijlmn-opqrstu*vwxyz0123=45"
+ORIGIN_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+
+
+def get_transtable():
+ transtable = maketrans(ORIGIN_ALPHABET, CUSTOMER_ALPHABET)
+ return transtable
+
+
+def get_reverse_transtable():
+ transtable = maketrans(CUSTOMER_ALPHABET, ORIGIN_ALPHABET)
+ return transtable
+
+
+def encode_string(value):
+ if len(value) == 0:
+ return ""
+ transtable = get_transtable()
+ e = str((base64.b64encode(str(value).encode())).decode("utf-8"))
+ e = e.rstrip("=")
+ return e.translate(transtable)
+
+
+class Module(MgrModule):
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'diskprediction_server',
+ 'default': ''
+ },
+ {
+ 'name': 'diskprediction_port',
+ 'default': '31400'
+ },
+ {
+ 'name': 'diskprediction_user',
+ 'default': ''
+ },
+ {
+ 'name': 'diskprediction_password',
+ 'default': ''
+ },
+ {
+ 'name': 'diskprediction_upload_metrics_interval',
+ 'default': '600'
+ },
+ {
+ 'name': 'diskprediction_upload_smart_interval',
+ 'default': '43200'
+ },
+ {
+ 'name': 'diskprediction_retrieve_prediction_interval',
+ 'default': '43200'
+ },
+ {
+ 'name': 'diskprediction_cert_context',
+ 'default': ''
+ },
+ {
+ 'name': 'diskprediction_ssl_target_name_override',
+ 'default': 'localhost'
+ },
+ {
+ 'name': 'diskprediction_default_authority',
+ 'default': 'localhost'
+ },
+ {
+ 'name': 'sleep_interval',
+ 'default': str(600),
+ }
+ ]
+
+ COMMANDS = [
+ {
+ 'cmd': 'device show-prediction-config',
+ 'desc': 'Prints diskprediction configuration',
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'device set-cloud-prediction-config '
+ 'name=server,type=CephString,req=true '
+ 'name=user,type=CephString,req=true '
+ 'name=password,type=CephString,req=true '
+ 'name=certfile,type=CephString,req=true '
+ 'name=port,type=CephString,req=false ',
+ 'desc': 'Configure Disk Prediction service',
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'device debug metrics-forced',
+ 'desc': 'Run metrics agent forced',
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'device debug smart-forced',
+ 'desc': 'Run smart agent forced',
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'diskprediction_cloud status',
+ 'desc': 'Check diskprediction_cloud status',
+ 'perm': 'r'
+ }
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.status = {'status': DP_MGR_STAT_DISABLED}
+ self._event = Event()
+ self._predict_event = Event()
+ self._agents = []
+ self._activated_cloud = False
+ self.prediction_result = {}
+ self.config = dict()
+ self._run = True
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+ if not self._activated_cloud and self.get_ceph_option('device_failure_prediction_mode') == 'cloud':
+ self._event.set()
+ if self._activated_cloud and self.get_ceph_option('device_failure_prediction_mode') != 'cloud':
+ self._event.set()
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None)) for o in self.MODULE_OPTIONS)
+
+ def set_config_option(self, option, value):
+ if option not in self.config_keys.keys():
+ raise RuntimeError('{0} is a unknown configuration '
+ 'option'.format(option))
+
+ if option in ['diskprediction_port',
+ 'diskprediction_upload_metrics_interval',
+ 'diskprediction_upload_smart_interval',
+ 'diskprediction_retrieve_prediction_interval']:
+ if not str(value).isdigit():
+ raise RuntimeError('invalid {} configured. Please specify '
+ 'a valid integer {}'.format(option, value))
+
+ self.log.debug('Setting in-memory config option %s to: %s', option,
+ value)
+ self.set_module_option(option, value)
+ self.config[option] = value
+
+ return True
+
+ def get_configuration(self, key):
+ return self.get_module_option(key, self.config_keys[key])
+
+ @staticmethod
+ def _convert_timestamp(predicted_timestamp, life_expectancy_day):
+ """
+ :param predicted_timestamp: unit is nanoseconds
+ :param life_expectancy_day: unit is seconds
+ :return:
+ date format '%Y-%m-%d' ex. 2018-01-01
+ """
+ return datetime.fromtimestamp(
+ predicted_timestamp / (1000 ** 3) + life_expectancy_day).strftime('%Y-%m-%d')
+
+ def _show_prediction_config(self, cmd):
+ self.show_module_config()
+ return 0, json.dumps(self.config, indent=4), ''
+
+ def _set_ssl_target_name(self, cmd):
+ str_ssl_target = cmd.get('ssl_target_name', '')
+ try:
+ self.set_module_option('diskprediction_ssl_target_name_override', str_ssl_target)
+ return (0,
+ 'success to config ssl target name', 0)
+ except Exception as e:
+ return -errno.EINVAL, '', str(e)
+
+ def _set_ssl_default_authority(self, cmd):
+ str_ssl_authority = cmd.get('ssl_authority', '')
+ try:
+ self.set_module_option('diskprediction_default_authority', str_ssl_authority)
+ return 0, 'success to config ssl default authority', 0
+ except Exception as e:
+ return -errno.EINVAL, '', str(e)
+
+ def _set_cloud_prediction_config(self, cmd):
+ str_cert_path = cmd.get('certfile', '')
+ if os.path.exists(str_cert_path):
+ with open(str_cert_path, 'rb') as f:
+ trusted_certs = f.read()
+ self.set_config_option(
+ 'diskprediction_cert_context', trusted_certs)
+ for _agent in self._agents:
+ _agent.event.set()
+ self.set_module_option('diskprediction_server', cmd['server'])
+ self.set_module_option('diskprediction_user', cmd['user'])
+ self.set_module_option('diskprediction_password', encode_string(cmd['password']))
+ if cmd.get('port'):
+ self.set_module_option('diskprediction_port', cmd['port'])
+ return 0, 'succeed to config cloud mode connection', ''
+ else:
+ return -errno.EINVAL, '', 'certification file not existed'
+
+ def _debug_metrics_forced(self, cmd):
+ msg = ''
+ for _agent in self._agents:
+ if isinstance(_agent, MetricsRunner):
+ msg = 'run metrics agent successfully'
+ _agent.event.set()
+ return 0, msg, ''
+
+ def _debug_smart_forced(self, cmd):
+ msg = ' '
+ for _agent in self._agents:
+ if isinstance(_agent, SmartRunner):
+ msg = 'run smart agent successfully'
+ _agent.event.set()
+ return 0, msg, ''
+
+ def refresh_config(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+
+ def _status(self, cmd):
+ return 0, json.dumps(self.status), ''
+
+ def _refresh_cloud_prediction_result(self):
+ for _agent in self._agents:
+ if isinstance(_agent, PredictRunner):
+ self._predict_event.clear()
+ _agent.event.set()
+ self._predict_event.wait(300)
+ if self._predict_event.is_set():
+ self._predict_event.clear()
+ break
+
+ def predict_life_expectancy(self, devid):
+ assert devid
+ result = self.get('device {}'.format(devid))
+ if not result:
+ return -1, '', 'device {} not found'.format(devid)
+ dev_info = result.get('device', {})
+ if not dev_info:
+ return -1, '', 'device {} not found'.format(devid)
+ self._refresh_cloud_prediction_result()
+ prediction_data = self.prediction_result.get(devid)
+ if not prediction_data:
+ return -1, '', 'device {} prediction data not ready'.format(devid)
+ elif prediction_data.get('near_failure', '').lower() == 'good':
+ return 0, '>6w', ''
+ elif prediction_data.get('near_failure', '').lower() == 'warning':
+ return 0, '>=2w and <=6w', ''
+ elif prediction_data.get('near_failure', '').lower() == 'bad':
+ return 0, '<2w', ''
+ else:
+ return 0, 'unknown', ''
+
+ def _update_device_life_expectancy_day(self, devid, prediction):
+ # Update osd life-expectancy
+ from .common.clusterdata import ClusterAPI
+ predicted = None
+ life_expectancy_day_min = None
+ life_expectancy_day_max = None
+ if prediction.get('predicted'):
+ predicted = int(prediction['predicted'])
+ if prediction.get('near_failure'):
+ if prediction['near_failure'].lower() == 'good':
+ life_expectancy_day_min = (TIME_WEEK * 6) + TIME_DAYS
+ life_expectancy_day_max = None
+ elif prediction['near_failure'].lower() == 'warning':
+ life_expectancy_day_min = (TIME_WEEK * 2)
+ life_expectancy_day_max = (TIME_WEEK * 6)
+ elif prediction['near_failure'].lower() == 'bad':
+ life_expectancy_day_min = 0
+ life_expectancy_day_max = (TIME_WEEK * 2) - TIME_DAYS
+ else:
+ # Near failure state is unknown.
+ predicted = None
+ life_expectancy_day_min = None
+ life_expectancy_day_max = None
+
+ obj_api = ClusterAPI(self)
+ if predicted and devid and life_expectancy_day_min is not None:
+ from_date = None
+ to_date = None
+ try:
+ if life_expectancy_day_min is not None:
+ from_date = self._convert_timestamp(predicted, life_expectancy_day_min)
+
+ if life_expectancy_day_max is not None:
+ to_date = self._convert_timestamp(predicted, life_expectancy_day_max)
+
+ obj_api.set_device_life_expectancy(devid, from_date, to_date)
+ self.log.info(
+ 'succeed to set device {} life expectancy from: {}, to: {}'.format(
+ devid, from_date, to_date))
+ except Exception as e:
+ self.log.error(
+ 'failed to set device {} life expectancy from: {}, to: {}, {}'.format(
+ devid, from_date, to_date, str(e)))
+ else:
+ obj_api.reset_device_life_expectancy(devid)
+
+ def predict_all_devices(self):
+ if not self._activated_cloud:
+ return -1, '', 'diskprecition_cloud not ready'
+ self.refresh_config()
+ result = self.get('devices')
+ if not result:
+ return -1, '', 'unable to get all devices for prediction'
+ self._refresh_cloud_prediction_result()
+ for dev in result.get('devices', []):
+ devid = dev.get('devid')
+ if not devid:
+ continue
+ prediction_data = self.prediction_result.get(devid)
+ if prediction_data:
+ break
+ if not prediction_data:
+ return -1, '', 'device {} prediction data not ready'.format(dev.get('devid'))
+ else:
+ self._update_device_life_expectancy_day(dev.get('devid'), prediction_data)
+ return 0, '', ''
+
+ def handle_command(self, _, cmd):
+ for o_cmd in self.COMMANDS:
+ if cmd['prefix'] == o_cmd['cmd'][:len(cmd['prefix'])]:
+ fun_name = ''
+ avgs = o_cmd['cmd'].split(' ')
+ for avg in avgs:
+ if avg.lower() == 'diskprediction_cloud':
+ continue
+ if avg.lower() == 'device':
+ continue
+ if '=' in avg or ',' in avg or not avg:
+ continue
+ fun_name += '_%s' % avg.replace('-', '_')
+ if fun_name:
+ fun = getattr(
+ self, fun_name)
+ if fun:
+ return fun(cmd)
+ return -errno.EINVAL, '', 'cmd not found'
+
+ def show_module_config(self):
+ for key, default in self.config_keys.items():
+ self.set_config_option(key, self.get_module_option(key, default))
+
+ def serve(self):
+ self.log.info('Starting diskprediction module')
+ self.config_notify()
+ self.status = {'status': DP_MGR_STAT_ENABLED}
+
+ while self._run:
+ self.refresh_config()
+ mode = self.get_ceph_option('device_failure_prediction_mode')
+ if mode == 'cloud':
+ if not self._activated_cloud:
+ self.start_cloud_disk_prediction()
+ else:
+ if self._activated_cloud:
+ self.stop_disk_prediction()
+
+ # Check agent hang is?
+ restart_agent = False
+ try:
+ for dp_agent in self._agents:
+ if dp_agent.is_timeout():
+ self.log.error('agent name: {] timeout'.format(dp_agent.task_name))
+ restart_agent = True
+ break
+ except Exception as IOError:
+ self.log.error('disk prediction plugin failed to started and try to restart')
+ restart_agent = True
+
+ if restart_agent:
+ self.stop_disk_prediction()
+ else:
+ sleep_interval = int(self.sleep_interval) or 60
+ self._event.wait(sleep_interval)
+ self._event.clear()
+ self.stop_disk_prediction()
+
+ def _agent_call_back(self):
+ self.log.debug('notify refresh devices prediction result')
+ self._predict_event.set()
+
+ def start_cloud_disk_prediction(self):
+ assert not self._activated_cloud
+ for dp_agent in DP_AGENTS:
+ if dp_agent == PredictRunner:
+ obj_agent = dp_agent(self, 300, self._agent_call_back)
+ else:
+ obj_agent = dp_agent(self, 300)
+ if obj_agent:
+ obj_agent.start()
+ else:
+ raise Exception('failed to start task %s' % obj_agent.task_name)
+ self._agents.append(obj_agent)
+ self._activated_cloud = True
+ self.log.info('start cloud disk prediction')
+
+ def stop_disk_prediction(self):
+ assert self._activated_cloud
+ try:
+ self.status = {'status': DP_MGR_STAT_DISABLED}
+ while self._agents:
+ dp_agent = self._agents.pop()
+ self.log.info('agent name: {}'.format(dp_agent.task_name))
+ dp_agent.terminate()
+ dp_agent.join(5)
+ del dp_agent
+ self._activated_cloud = False
+ self.log.info('stop disk prediction')
+ except Exception as IOError:
+ self.log.error('failed to stop disk prediction clould plugin')
+
+ def shutdown(self):
+ self._run = False
+ self._event.set()
+ super(Module, self).shutdown()
+
+ def self_test(self):
+ obj_test = TestRunner(self)
+ obj_test.run()
+ self.log.info('self test completed')
diff --git a/src/pybind/mgr/diskprediction_cloud/requirements.txt b/src/pybind/mgr/diskprediction_cloud/requirements.txt
new file mode 100644
index 00000000..4abc346a
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/requirements.txt
@@ -0,0 +1,12 @@
+google-api-python-client==1.7.3
+google-auth==1.5.0
+google-auth-httplib2==0.0.3
+googleapis-common-protos==1.5.3
+grpc==0.3.post19
+grpc-google-logging-v2==0.8.1
+grpc-google-pubsub-v1==0.8.1
+grpcio==1.14.1
+mock==2.0.0
+numpy==1.15.1
+scikit-learn==0.19.2
+scipy==1.1.0
diff --git a/src/pybind/mgr/diskprediction_cloud/task.py b/src/pybind/mgr/diskprediction_cloud/task.py
new file mode 100644
index 00000000..6ed04e60
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_cloud/task.py
@@ -0,0 +1,181 @@
+from __future__ import absolute_import
+
+import time
+from threading import Event, Thread
+
+from .agent.predictor import PredictAgent
+from .agent.metrics.ceph_cluster import CephClusterAgent
+from .agent.metrics.ceph_mon_osd import CephMonOsdAgent
+from .agent.metrics.ceph_pool import CephPoolAgent
+from .agent.metrics.db_relay import DBRelayAgent
+from .agent.metrics.sai_agent import SAIAgent
+from .agent.metrics.sai_cluster import SAICluserAgent
+from .agent.metrics.sai_disk import SAIDiskAgent
+from .agent.metrics.sai_disk_smart import SAIDiskSmartAgent
+from .agent.metrics.sai_host import SAIHostAgent
+from .common import DP_MGR_STAT_FAILED, DP_MGR_STAT_OK, DP_MGR_STAT_WARNING
+
+
+class AgentRunner(Thread):
+
+ task_name = ''
+ interval_key = ''
+ agents = []
+
+ def __init__(self, mgr_module, agent_timeout=60, call_back=None):
+ """
+
+ :param mgr_module: parent ceph mgr module
+ :param agent_timeout: (unit seconds) agent execute timeout value, default: 60 secs
+ """
+ Thread.__init__(self)
+ self._agent_timeout = agent_timeout
+ self._module_inst = mgr_module
+ self._log = mgr_module.log
+ self._start_time = time.time()
+ self._th = None
+ self._call_back = call_back
+ self.exit = False
+ self.event = Event()
+ self.task_interval = \
+ int(self._module_inst.get_configuration(self.interval_key))
+
+ def terminate(self):
+ self.exit = True
+ self.event.set()
+ self._log.info('PDS terminate %s complete' % self.task_name)
+
+ def run(self):
+ self._start_time = time.time()
+ self._log.info(
+ 'start %s, interval: %s'
+ % (self.task_name, self.task_interval))
+ while not self.exit:
+ self.run_agents()
+ if self._call_back:
+ self._call_back()
+ if self.event:
+ self.event.wait(int(self.task_interval))
+ self.event.clear()
+ self._log.info(
+ 'completed %s(%s)' % (self.task_name, time.time()-self._start_time))
+
+ def run_agents(self):
+ obj_sender = None
+ try:
+ self._log.debug('run_agents %s' % self.task_name)
+ from .common.grpcclient import GRPcClient, gen_configuration
+ conf = gen_configuration(
+ host=self._module_inst.get_configuration('diskprediction_server'),
+ user=self._module_inst.get_configuration('diskprediction_user'),
+ password=self._module_inst.get_configuration(
+ 'diskprediction_password'),
+ port=self._module_inst.get_configuration('diskprediction_port'),
+ cert_context=self._module_inst.get_configuration('diskprediction_cert_context'),
+ mgr_inst=self._module_inst,
+ ssl_target_name=self._module_inst.get_configuration('diskprediction_ssl_target_name_override'),
+ default_authority=self._module_inst.get_configuration('diskprediction_default_authority'))
+ obj_sender = GRPcClient(conf)
+ if not obj_sender:
+ self._log.error('invalid diskprediction sender')
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_FAILED,
+ 'reason': 'invalid diskprediction sender'}
+ raise Exception('invalid diskprediction sender')
+ if obj_sender.test_connection():
+ self._module_inst.status = {'status': DP_MGR_STAT_OK}
+ self._log.debug('succeed to test connection')
+ self._run(self._module_inst, obj_sender)
+ else:
+ self._log.error('failed to test connection')
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_FAILED,
+ 'reason': 'failed to test connection'}
+ raise Exception('failed to test connection')
+ except Exception as e:
+ self._module_inst.status = \
+ {'status': DP_MGR_STAT_FAILED,
+ 'reason': 'failed to start %s agents, %s'
+ % (self.task_name, str(e))}
+ self._log.error(
+ 'failed to start %s agents, %s' % (self.task_name, str(e)))
+ raise
+ finally:
+ if obj_sender:
+ obj_sender.close()
+
+ def is_timeout(self):
+ now = time.time()
+ if (now - self._start_time) > self._agent_timeout:
+ return True
+ else:
+ return False
+
+ def _run(self, module_inst, sender):
+ self._log.debug('%s run' % self.task_name)
+ for agent in self.agents:
+ self._start_time = time.time()
+ retry_count = 3
+ while retry_count:
+ retry_count -= 1
+ try:
+ obj_agent = agent(module_inst, sender, self._agent_timeout)
+ obj_agent.run()
+ del obj_agent
+ break
+ except Exception as e:
+ if str(e).find('configuring') >= 0:
+ self._log.debug(
+ 'failed to execute {}, {}, retry again.'.format(
+ agent.measurement, str(e)))
+ time.sleep(1)
+ continue
+ else:
+ module_inst.status = \
+ {'status': DP_MGR_STAT_WARNING,
+ 'reason': 'failed to execute {}, {}'.format(
+ agent.measurement, ';'.join(str(e).split('\n\t')))}
+ self._log.warning(
+ 'failed to execute {}, {}'.format(
+ agent.measurement, ';'.join(str(e).split('\n\t'))))
+ break
+
+
+class MetricsRunner(AgentRunner):
+
+ task_name = 'Metrics Agent'
+ interval_key = 'diskprediction_upload_metrics_interval'
+ agents = [CephClusterAgent, CephMonOsdAgent, CephPoolAgent,
+ SAICluserAgent, SAIDiskAgent, SAIHostAgent, DBRelayAgent,
+ SAIAgent]
+
+
+class PredictRunner(AgentRunner):
+
+ task_name = 'Predictor Agent'
+ interval_key = 'diskprediction_retrieve_prediction_interval'
+ agents = [PredictAgent]
+
+
+class SmartRunner(AgentRunner):
+
+ task_name = 'Smart data Agent'
+ interval_key = 'diskprediction_upload_smart_interval'
+ agents = [SAIDiskSmartAgent]
+
+
+class TestRunner(object):
+ task_name = 'Test Agent'
+ interval_key = 'diskprediction_upload_metrics_interval'
+ agents = [CephClusterAgent, CephMonOsdAgent, CephPoolAgent,
+ SAICluserAgent, SAIDiskAgent, SAIHostAgent, DBRelayAgent,
+ SAIAgent, SAIDiskSmartAgent]
+
+ def __init__(self, mgr_module):
+ self._module_inst = mgr_module
+
+ def run(self):
+ for agent in self.agents:
+ obj_agent = agent(self._module_inst, None)
+ obj_agent.run()
+ del obj_agent
diff --git a/src/pybind/mgr/diskprediction_local/__init__.py b/src/pybind/mgr/diskprediction_local/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/diskprediction_local/models/config.json b/src/pybind/mgr/diskprediction_local/models/config.json
new file mode 100644
index 00000000..9a1485ca
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/config.json
@@ -0,0 +1,77 @@
+{
+"svm_123.pkl": ["smart_197_raw", "smart_183_raw", "smart_200_raw", "smart_194_raw", "smart_254_raw", "smart_252_raw", "smart_4_raw", "smart_222_raw", "smart_187_raw", "smart_184_raw"],
+"svm_105.pkl": ["smart_197_raw", "smart_4_raw", "smart_5_raw", "smart_252_raw", "smart_184_raw", "smart_223_raw", "smart_198_raw", "smart_10_raw", "smart_189_raw", "smart_222_raw"],
+"svm_82.pkl":["smart_184_raw", "smart_2_raw", "smart_187_raw", "smart_225_raw", "smart_198_raw", "smart_197_raw", "smart_4_raw", "smart_13_raw", "smart_188_raw", "smart_251_raw"],
+"svm_186.pkl":["smart_3_raw", "smart_11_raw", "smart_198_raw", "smart_250_raw", "smart_13_raw", "smart_200_raw", "smart_224_raw", "smart_187_raw", "smart_22_raw", "smart_4_raw", "smart_220_raw"],
+"svm_14.pkl":["smart_12_raw", "smart_226_raw", "smart_187_raw", "smart_196_raw", "smart_5_raw", "smart_183_raw", "smart_255_raw", "smart_250_raw", "smart_201_raw", "smart_8_raw"],
+"svm_10.pkl":["smart_251_raw", "smart_4_raw", "smart_223_raw", "smart_13_raw", "smart_255_raw", "smart_188_raw", "smart_197_raw", "smart_201_raw", "smart_250_raw", "smart_15_raw"],
+"svm_235.pkl":["smart_15_raw", "smart_255_raw", "smart_252_raw", "smart_197_raw", "smart_250_raw", "smart_254_raw", "smart_13_raw", "smart_251_raw", "smart_198_raw", "smart_189_raw", "smart_191_raw"],
+"svm_234.pkl":["smart_187_raw", "smart_183_raw", "smart_3_raw", "smart_4_raw", "smart_222_raw", "smart_184_raw", "smart_5_raw", "smart_198_raw", "smart_200_raw", "smart_8_raw", "smart_10_raw"],
+"svm_119.pkl":["smart_254_raw", "smart_8_raw", "smart_183_raw", "smart_184_raw", "smart_195_raw", "smart_252_raw", "smart_191_raw", "smart_10_raw", "smart_200_raw", "smart_197_raw"],
+"svm_227.pkl":["smart_254_raw", "smart_189_raw", "smart_225_raw", "smart_224_raw", "smart_197_raw", "smart_223_raw", "smart_4_raw", "smart_183_raw", "smart_11_raw", "smart_184_raw", "smart_13_raw"],
+"svm_18.pkl":["smart_197_raw", "smart_3_raw", "smart_220_raw", "smart_193_raw", "smart_10_raw", "smart_187_raw", "smart_188_raw", "smart_225_raw", "smart_194_raw", "smart_13_raw"],
+"svm_78.pkl":["smart_10_raw", "smart_183_raw", "smart_191_raw", "smart_13_raw", "smart_198_raw", "smart_22_raw", "smart_195_raw", "smart_12_raw", "smart_224_raw", "smart_200_raw"],
+"svm_239.pkl":["smart_3_raw", "smart_254_raw", "smart_199_raw", "smart_225_raw", "smart_187_raw", "smart_195_raw", "smart_197_raw", "smart_2_raw", "smart_193_raw", "smart_220_raw", "smart_183_raw"],
+"svm_174.pkl":["smart_183_raw", "smart_196_raw", "smart_225_raw", "smart_189_raw", "smart_4_raw", "smart_3_raw", "smart_9_raw", "smart_198_raw", "smart_15_raw", "smart_5_raw", "smart_194_raw"],
+"svm_104.pkl":["smart_12_raw", "smart_198_raw", "smart_197_raw", "smart_4_raw", "smart_240_raw", "smart_187_raw", "smart_225_raw", "smart_8_raw", "smart_3_raw", "smart_2_raw"],
+"svm_12.pkl":["smart_222_raw", "smart_251_raw", "smart_194_raw", "smart_9_raw", "smart_184_raw", "smart_191_raw", "smart_187_raw", "smart_255_raw", "smart_4_raw", "smart_11_raw"],
+"svm_97.pkl":["smart_15_raw", "smart_197_raw", "smart_190_raw", "smart_199_raw", "smart_200_raw", "smart_12_raw", "smart_191_raw", "smart_254_raw", "smart_194_raw", "smart_201_raw"],
+"svm_118.pkl":["smart_11_raw", "smart_225_raw", "smart_196_raw", "smart_197_raw", "smart_198_raw", "smart_200_raw", "smart_3_raw", "smart_10_raw", "smart_191_raw", "smart_22_raw"],
+"svm_185.pkl":["smart_191_raw", "smart_254_raw", "smart_3_raw", "smart_190_raw", "smart_15_raw", "smart_22_raw", "smart_2_raw", "smart_198_raw", "smart_13_raw", "smart_226_raw", "smart_225_raw"],
+"svm_206.pkl":["smart_183_raw", "smart_192_raw", "smart_197_raw", "smart_255_raw", "smart_187_raw", "smart_254_raw", "smart_198_raw", "smart_13_raw", "smart_226_raw", "smart_240_raw", "smart_8_raw"],
+"svm_225.pkl":["smart_224_raw", "smart_11_raw", "smart_5_raw", "smart_4_raw", "smart_225_raw", "smart_197_raw", "smart_15_raw", "smart_183_raw", "smart_193_raw", "smart_190_raw", "smart_187_raw"],
+"svm_169.pkl":["smart_252_raw", "smart_183_raw", "smart_254_raw", "smart_11_raw", "smart_193_raw", "smart_22_raw", "smart_226_raw", "smart_189_raw", "smart_225_raw", "smart_198_raw", "smart_200_raw"],
+"svm_79.pkl":["smart_184_raw", "smart_196_raw", "smart_4_raw", "smart_226_raw", "smart_199_raw", "smart_187_raw", "smart_193_raw", "smart_188_raw", "smart_12_raw", "smart_250_raw"],
+"svm_69.pkl":["smart_187_raw", "smart_9_raw", "smart_200_raw", "smart_11_raw", "smart_252_raw", "smart_189_raw", "smart_4_raw", "smart_188_raw", "smart_255_raw", "smart_201_raw"],
+"svm_201.pkl":["smart_224_raw", "smart_8_raw", "smart_250_raw", "smart_2_raw", "smart_198_raw", "smart_15_raw", "smart_193_raw", "smart_223_raw", "smart_3_raw", "smart_11_raw", "smart_191_raw"],
+"svm_114.pkl":["smart_226_raw", "smart_188_raw", "smart_2_raw", "smart_11_raw", "smart_4_raw", "smart_193_raw", "smart_184_raw", "smart_194_raw", "smart_198_raw", "smart_13_raw"],
+"svm_219.pkl":["smart_12_raw", "smart_22_raw", "smart_8_raw", "smart_191_raw", "smart_197_raw", "smart_254_raw", "smart_15_raw", "smart_193_raw", "smart_199_raw", "smart_225_raw", "smart_192_raw"],
+"svm_168.pkl":["smart_255_raw", "smart_191_raw", "smart_193_raw", "smart_220_raw", "smart_5_raw", "smart_3_raw", "smart_222_raw", "smart_223_raw", "smart_197_raw", "smart_196_raw", "smart_22_raw"],
+"svm_243.pkl":["smart_11_raw", "smart_255_raw", "smart_10_raw", "smart_189_raw", "smart_225_raw", "smart_240_raw", "smart_222_raw", "smart_197_raw", "smart_183_raw", "smart_198_raw", "smart_12_raw"],
+"svm_195.pkl":["smart_183_raw", "smart_5_raw", "smart_11_raw", "smart_197_raw", "smart_15_raw", "smart_9_raw", "smart_4_raw", "smart_220_raw", "smart_12_raw", "smart_192_raw", "smart_240_raw"],
+"svm_222.pkl":["smart_10_raw", "smart_13_raw", "smart_188_raw", "smart_15_raw", "smart_192_raw", "smart_224_raw", "smart_225_raw", "smart_187_raw", "smart_222_raw", "smart_220_raw", "smart_252_raw"],
+"svm_62.pkl":["smart_196_raw", "smart_251_raw", "smart_187_raw", "smart_224_raw", "smart_11_raw", "smart_12_raw", "smart_8_raw", "smart_199_raw", "smart_220_raw", "smart_195_raw"],
+"svm_151.pkl":["smart_187_raw", "smart_223_raw", "smart_200_raw", "smart_189_raw", "smart_251_raw", "smart_255_raw", "smart_222_raw", "smart_192_raw", "smart_12_raw", "smart_183_raw", "smart_22_raw"],
+"svm_125.pkl":["smart_9_raw", "smart_252_raw", "smart_197_raw", "smart_251_raw", "smart_11_raw", "smart_12_raw", "smart_188_raw", "smart_240_raw", "smart_10_raw", "smart_223_raw"],
+"svm_124.pkl":["smart_193_raw", "smart_187_raw", "smart_183_raw", "smart_11_raw", "smart_10_raw", "smart_8_raw", "smart_194_raw", "smart_189_raw", "smart_222_raw", "smart_191_raw"],
+"svm_67.pkl":["smart_2_raw", "smart_8_raw", "smart_225_raw", "smart_240_raw", "smart_13_raw", "smart_5_raw", "smart_187_raw", "smart_198_raw", "smart_199_raw", "smart_3_raw"],
+"svm_115.pkl":["smart_222_raw", "smart_193_raw", "smart_223_raw", "smart_195_raw", "smart_252_raw", "smart_189_raw", "smart_199_raw", "smart_187_raw", "smart_15_raw", "smart_184_raw"],
+"svm_1.pkl":["smart_201_raw", "smart_8_raw", "smart_200_raw", "smart_252_raw", "smart_251_raw", "smart_187_raw", "smart_9_raw", "smart_188_raw", "smart_15_raw", "smart_184_raw"],
+"svm_112.pkl":["smart_220_raw", "smart_197_raw", "smart_10_raw", "smart_188_raw", "smart_12_raw", "smart_4_raw", "smart_196_raw", "smart_3_raw", "smart_240_raw", "smart_225_raw"],
+"svm_138.pkl":["smart_183_raw", "smart_10_raw", "smart_191_raw", "smart_195_raw", "smart_223_raw", "smart_189_raw", "smart_187_raw", "smart_255_raw", "smart_226_raw", "smart_8_raw"],
+"svm_229.pkl":["smart_224_raw", "smart_8_raw", "smart_192_raw", "smart_220_raw", "smart_195_raw", "smart_183_raw", "smart_250_raw", "smart_187_raw", "smart_225_raw", "smart_4_raw", "smart_252_raw"],
+"svm_145.pkl":["smart_190_raw", "smart_8_raw", "smart_226_raw", "smart_184_raw", "smart_225_raw", "smart_220_raw", "smart_193_raw", "smart_183_raw", "smart_201_raw", "smart_187_raw", "smart_2_raw"],
+"svm_59.pkl":["smart_188_raw", "smart_11_raw", "smart_184_raw", "smart_2_raw", "smart_220_raw", "smart_198_raw", "smart_225_raw", "smart_240_raw", "smart_197_raw", "smart_251_raw"],
+"svm_204.pkl":["smart_15_raw", "smart_240_raw", "smart_225_raw", "smart_223_raw", "smart_252_raw", "smart_22_raw", "smart_200_raw", "smart_13_raw", "smart_220_raw", "smart_198_raw", "smart_191_raw"],
+"svm_88.pkl":["smart_198_raw", "smart_3_raw", "smart_8_raw", "smart_225_raw", "smart_251_raw", "smart_222_raw", "smart_188_raw", "smart_10_raw", "smart_240_raw", "smart_189_raw"],
+"svm_182.pkl":["smart_10_raw", "smart_190_raw", "smart_250_raw", "smart_15_raw", "smart_193_raw", "smart_22_raw", "smart_200_raw", "smart_8_raw", "smart_4_raw", "smart_187_raw", "smart_9_raw"],
+"svm_61.pkl":["smart_5_raw", "smart_12_raw", "smart_9_raw", "smart_198_raw", "smart_195_raw", "smart_252_raw", "smart_15_raw", "smart_240_raw", "smart_255_raw", "smart_224_raw"],
+"svm_50.pkl":["smart_220_raw", "smart_5_raw", "smart_194_raw", "smart_250_raw", "smart_15_raw", "smart_240_raw", "smart_8_raw", "smart_198_raw", "smart_224_raw", "smart_191_raw"],
+"svm_210.pkl":["smart_8_raw", "smart_15_raw", "smart_195_raw", "smart_224_raw", "smart_5_raw", "smart_191_raw", "smart_198_raw", "smart_225_raw", "smart_200_raw", "smart_251_raw", "smart_240_raw"],
+"svm_16.pkl":["smart_222_raw", "smart_10_raw", "smart_250_raw", "smart_189_raw", "smart_191_raw", "smart_2_raw", "smart_5_raw", "smart_193_raw", "smart_9_raw", "smart_187_raw"],
+"svm_85.pkl":["smart_252_raw", "smart_184_raw", "smart_9_raw", "smart_5_raw", "smart_254_raw", "smart_3_raw", "smart_195_raw", "smart_10_raw", "smart_12_raw", "smart_222_raw"],
+"svm_36.pkl":["smart_201_raw", "smart_251_raw", "smart_184_raw", "smart_3_raw", "smart_5_raw", "smart_183_raw", "smart_194_raw", "smart_195_raw", "smart_224_raw", "smart_2_raw"],
+"svm_33.pkl":["smart_223_raw", "smart_254_raw", "smart_225_raw", "smart_9_raw", "smart_199_raw", "smart_5_raw", "smart_189_raw", "smart_194_raw", "smart_240_raw", "smart_4_raw"],
+"svm_3.pkl":["smart_225_raw", "smart_194_raw", "smart_3_raw", "smart_189_raw", "smart_9_raw", "smart_254_raw", "smart_240_raw", "smart_5_raw", "smart_255_raw", "smart_223_raw"],
+"svm_93.pkl":["smart_8_raw", "smart_188_raw", "smart_5_raw", "smart_10_raw", "smart_222_raw", "smart_2_raw", "smart_254_raw", "smart_12_raw", "smart_193_raw", "smart_224_raw"],
+"svm_120.pkl":["smart_189_raw", "smart_224_raw", "smart_222_raw", "smart_193_raw", "smart_5_raw", "smart_201_raw", "smart_8_raw", "smart_254_raw", "smart_194_raw", "smart_22_raw"],
+"svm_128.pkl":["smart_195_raw", "smart_184_raw", "smart_251_raw", "smart_8_raw", "smart_5_raw", "smart_196_raw", "smart_10_raw", "smart_4_raw", "smart_225_raw", "smart_191_raw"],
+"svm_212.pkl":["smart_225_raw", "smart_192_raw", "smart_10_raw", "smart_12_raw", "smart_222_raw", "smart_184_raw", "smart_13_raw", "smart_226_raw", "smart_5_raw", "smart_201_raw", "smart_22_raw"],
+"svm_221.pkl":["smart_255_raw", "smart_2_raw", "smart_224_raw", "smart_192_raw", "smart_252_raw", "smart_13_raw", "smart_183_raw", "smart_193_raw", "smart_15_raw", "smart_199_raw", "smart_200_raw"],
+"svm_223.pkl":["smart_4_raw", "smart_194_raw", "smart_9_raw", "smart_255_raw", "smart_188_raw", "smart_201_raw", "smart_3_raw", "smart_226_raw", "smart_192_raw", "smart_251_raw", "smart_191_raw"],
+"svm_44.pkl":["smart_255_raw", "smart_11_raw", "smart_200_raw", "smart_3_raw", "smart_195_raw", "smart_201_raw", "smart_4_raw", "smart_5_raw", "smart_10_raw", "smart_191_raw"],
+"svm_213.pkl":["smart_22_raw", "smart_191_raw", "smart_183_raw", "smart_4_raw", "smart_194_raw", "smart_255_raw", "smart_254_raw", "smart_193_raw", "smart_11_raw", "smart_10_raw", "smart_220_raw"],
+"svm_131.pkl":["smart_22_raw", "smart_194_raw", "smart_184_raw", "smart_250_raw", "smart_10_raw", "smart_189_raw", "smart_183_raw", "smart_240_raw", "smart_12_raw", "smart_252_raw"],
+"svm_6.pkl":["smart_194_raw", "smart_250_raw", "smart_223_raw", "smart_224_raw", "smart_184_raw", "smart_191_raw", "smart_201_raw", "smart_9_raw", "smart_252_raw", "smart_3_raw"],
+"svm_161.pkl":["smart_255_raw", "smart_222_raw", "smart_226_raw", "smart_254_raw", "smart_183_raw", "smart_22_raw", "smart_12_raw", "smart_190_raw", "smart_11_raw", "smart_192_raw", "smart_251_raw"],
+"svm_72.pkl":["smart_13_raw", "smart_184_raw", "smart_223_raw", "smart_240_raw", "smart_250_raw", "smart_251_raw", "smart_201_raw", "smart_196_raw", "smart_5_raw", "smart_4_raw"],
+"svm_27.pkl":["smart_189_raw", "smart_188_raw", "smart_255_raw", "smart_251_raw", "smart_240_raw", "smart_15_raw", "smart_9_raw", "smart_191_raw", "smart_226_raw", "smart_10_raw"],
+"svm_141.pkl":["smart_9_raw", "smart_191_raw", "smart_2_raw", "smart_226_raw", "smart_13_raw", "smart_22_raw", "smart_193_raw", "smart_222_raw", "smart_220_raw", "smart_225_raw", "smart_3_raw"],
+"svm_57.pkl":["smart_12_raw", "smart_252_raw", "smart_190_raw", "smart_226_raw", "smart_10_raw", "smart_189_raw", "smart_193_raw", "smart_2_raw", "smart_9_raw", "smart_223_raw"],
+"svm_236.pkl":["smart_200_raw", "smart_189_raw", "smart_226_raw", "smart_252_raw", "smart_250_raw", "smart_193_raw", "smart_13_raw", "smart_2_raw", "smart_254_raw", "smart_22_raw", "smart_9_raww"],
+"svm_208.pkl":["smart_223_raw", "smart_15_raw", "smart_251_raw", "smart_5_raw", "smart_198_raw", "smart_252_raw", "smart_4_raw", "smart_8_raw", "smart_220_raw", "smart_254_raw", "smart_193_raw"],
+"svm_230.pkl":["smart_184_raw", "smart_5_raw", "smart_191_raw", "smart_198_raw", "smart_11_raw", "smart_255_raw", "smart_189_raw", "smart_254_raw", "smart_196_raw", "smart_199_raw", "smart_223_raw"],
+"svm_134.pkl":["smart_8_raw", "smart_194_raw", "smart_4_raw", "smart_189_raw", "smart_223_raw", "smart_5_raw", "smart_187_raw", "smart_9_raw", "smart_192_raw", "smart_220_raw"],
+"svm_71.pkl":["smart_220_raw", "smart_13_raw", "smart_194_raw", "smart_197_raw", "smart_192_raw", "smart_22_raw", "smart_184_raw", "smart_199_raw", "smart_222_raw", "smart_183_raw"],
+"svm_109.pkl":["smart_224_raw", "smart_252_raw", "smart_2_raw", "smart_200_raw", "smart_5_raw", "smart_194_raw", "smart_222_raw", "smart_198_raw", "smart_4_raw", "smart_13_raw"]
+}
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_1.pkl b/src/pybind/mgr/diskprediction_local/models/svm_1.pkl
new file mode 100644
index 00000000..5eb30f30
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_1.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_10.pkl b/src/pybind/mgr/diskprediction_local/models/svm_10.pkl
new file mode 100644
index 00000000..9259c1e7
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_10.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_104.pkl b/src/pybind/mgr/diskprediction_local/models/svm_104.pkl
new file mode 100644
index 00000000..d5d5cf5b
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_104.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_105.pkl b/src/pybind/mgr/diskprediction_local/models/svm_105.pkl
new file mode 100644
index 00000000..4aadc3cf
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_105.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_109.pkl b/src/pybind/mgr/diskprediction_local/models/svm_109.pkl
new file mode 100644
index 00000000..c99c353b
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_109.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_112.pkl b/src/pybind/mgr/diskprediction_local/models/svm_112.pkl
new file mode 100644
index 00000000..367a3304
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_112.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_114.pkl b/src/pybind/mgr/diskprediction_local/models/svm_114.pkl
new file mode 100644
index 00000000..946d5cef
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_114.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_115.pkl b/src/pybind/mgr/diskprediction_local/models/svm_115.pkl
new file mode 100644
index 00000000..ff834929
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_115.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_118.pkl b/src/pybind/mgr/diskprediction_local/models/svm_118.pkl
new file mode 100644
index 00000000..eec8689e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_118.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_119.pkl b/src/pybind/mgr/diskprediction_local/models/svm_119.pkl
new file mode 100644
index 00000000..6a26c050
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_119.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_12.pkl b/src/pybind/mgr/diskprediction_local/models/svm_12.pkl
new file mode 100644
index 00000000..5cbe9775
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_12.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_120.pkl b/src/pybind/mgr/diskprediction_local/models/svm_120.pkl
new file mode 100644
index 00000000..d2041c26
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_120.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_123.pkl b/src/pybind/mgr/diskprediction_local/models/svm_123.pkl
new file mode 100644
index 00000000..0ab6187e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_123.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_124.pkl b/src/pybind/mgr/diskprediction_local/models/svm_124.pkl
new file mode 100644
index 00000000..8f9ea4ec
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_124.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_125.pkl b/src/pybind/mgr/diskprediction_local/models/svm_125.pkl
new file mode 100644
index 00000000..4d49900f
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_125.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_128.pkl b/src/pybind/mgr/diskprediction_local/models/svm_128.pkl
new file mode 100644
index 00000000..6a18726d
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_128.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_131.pkl b/src/pybind/mgr/diskprediction_local/models/svm_131.pkl
new file mode 100644
index 00000000..e6a55dca
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_131.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_134.pkl b/src/pybind/mgr/diskprediction_local/models/svm_134.pkl
new file mode 100644
index 00000000..51171e00
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_134.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_138.pkl b/src/pybind/mgr/diskprediction_local/models/svm_138.pkl
new file mode 100644
index 00000000..bc98e0c7
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_138.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_14.pkl b/src/pybind/mgr/diskprediction_local/models/svm_14.pkl
new file mode 100644
index 00000000..c4547dc6
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_14.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_141.pkl b/src/pybind/mgr/diskprediction_local/models/svm_141.pkl
new file mode 100644
index 00000000..86d9f38d
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_141.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_145.pkl b/src/pybind/mgr/diskprediction_local/models/svm_145.pkl
new file mode 100644
index 00000000..24ff9623
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_145.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_151.pkl b/src/pybind/mgr/diskprediction_local/models/svm_151.pkl
new file mode 100644
index 00000000..92bfd3f1
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_151.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_16.pkl b/src/pybind/mgr/diskprediction_local/models/svm_16.pkl
new file mode 100644
index 00000000..11664b3d
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_16.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_161.pkl b/src/pybind/mgr/diskprediction_local/models/svm_161.pkl
new file mode 100644
index 00000000..2d421685
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_161.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_168.pkl b/src/pybind/mgr/diskprediction_local/models/svm_168.pkl
new file mode 100644
index 00000000..12a811cf
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_168.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_169.pkl b/src/pybind/mgr/diskprediction_local/models/svm_169.pkl
new file mode 100644
index 00000000..0c51446c
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_169.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_174.pkl b/src/pybind/mgr/diskprediction_local/models/svm_174.pkl
new file mode 100644
index 00000000..d2945ce9
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_174.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_18.pkl b/src/pybind/mgr/diskprediction_local/models/svm_18.pkl
new file mode 100644
index 00000000..d05520cc
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_18.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_182.pkl b/src/pybind/mgr/diskprediction_local/models/svm_182.pkl
new file mode 100644
index 00000000..7fcfb3cb
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_182.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_185.pkl b/src/pybind/mgr/diskprediction_local/models/svm_185.pkl
new file mode 100644
index 00000000..785301c1
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_185.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_186.pkl b/src/pybind/mgr/diskprediction_local/models/svm_186.pkl
new file mode 100644
index 00000000..4ea83da7
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_186.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_195.pkl b/src/pybind/mgr/diskprediction_local/models/svm_195.pkl
new file mode 100644
index 00000000..12273f7c
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_195.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_201.pkl b/src/pybind/mgr/diskprediction_local/models/svm_201.pkl
new file mode 100644
index 00000000..c866cf00
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_201.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_204.pkl b/src/pybind/mgr/diskprediction_local/models/svm_204.pkl
new file mode 100644
index 00000000..8cf1c3aa
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_204.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_206.pkl b/src/pybind/mgr/diskprediction_local/models/svm_206.pkl
new file mode 100644
index 00000000..cba64e80
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_206.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_208.pkl b/src/pybind/mgr/diskprediction_local/models/svm_208.pkl
new file mode 100644
index 00000000..ba0df0ab
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_208.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_210.pkl b/src/pybind/mgr/diskprediction_local/models/svm_210.pkl
new file mode 100644
index 00000000..6b5bee21
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_210.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_212.pkl b/src/pybind/mgr/diskprediction_local/models/svm_212.pkl
new file mode 100644
index 00000000..11eafc64
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_212.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_213.pkl b/src/pybind/mgr/diskprediction_local/models/svm_213.pkl
new file mode 100644
index 00000000..0b8475c5
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_213.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_219.pkl b/src/pybind/mgr/diskprediction_local/models/svm_219.pkl
new file mode 100644
index 00000000..4a248c14
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_219.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_221.pkl b/src/pybind/mgr/diskprediction_local/models/svm_221.pkl
new file mode 100644
index 00000000..e37c6b4f
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_221.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_222.pkl b/src/pybind/mgr/diskprediction_local/models/svm_222.pkl
new file mode 100644
index 00000000..e5430386
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_222.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_223.pkl b/src/pybind/mgr/diskprediction_local/models/svm_223.pkl
new file mode 100644
index 00000000..8b208f4e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_223.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_225.pkl b/src/pybind/mgr/diskprediction_local/models/svm_225.pkl
new file mode 100644
index 00000000..3f2b6298
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_225.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_227.pkl b/src/pybind/mgr/diskprediction_local/models/svm_227.pkl
new file mode 100644
index 00000000..5e4fb56f
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_227.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_229.pkl b/src/pybind/mgr/diskprediction_local/models/svm_229.pkl
new file mode 100644
index 00000000..1e9c3359
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_229.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_230.pkl b/src/pybind/mgr/diskprediction_local/models/svm_230.pkl
new file mode 100644
index 00000000..36f8205c
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_230.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_234.pkl b/src/pybind/mgr/diskprediction_local/models/svm_234.pkl
new file mode 100644
index 00000000..199f9ba5
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_234.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_235.pkl b/src/pybind/mgr/diskprediction_local/models/svm_235.pkl
new file mode 100644
index 00000000..d986526e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_235.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_236.pkl b/src/pybind/mgr/diskprediction_local/models/svm_236.pkl
new file mode 100644
index 00000000..160e22fa
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_236.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_239.pkl b/src/pybind/mgr/diskprediction_local/models/svm_239.pkl
new file mode 100644
index 00000000..8d98572a
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_239.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_243.pkl b/src/pybind/mgr/diskprediction_local/models/svm_243.pkl
new file mode 100644
index 00000000..4fca95e1
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_243.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_27.pkl b/src/pybind/mgr/diskprediction_local/models/svm_27.pkl
new file mode 100644
index 00000000..011974ed
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_27.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_3.pkl b/src/pybind/mgr/diskprediction_local/models/svm_3.pkl
new file mode 100644
index 00000000..e5e97a88
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_3.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_33.pkl b/src/pybind/mgr/diskprediction_local/models/svm_33.pkl
new file mode 100644
index 00000000..e709d7b4
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_33.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_36.pkl b/src/pybind/mgr/diskprediction_local/models/svm_36.pkl
new file mode 100644
index 00000000..3d87b8bd
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_36.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_44.pkl b/src/pybind/mgr/diskprediction_local/models/svm_44.pkl
new file mode 100644
index 00000000..9abcece9
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_44.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_50.pkl b/src/pybind/mgr/diskprediction_local/models/svm_50.pkl
new file mode 100644
index 00000000..b7ce5eda
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_50.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_57.pkl b/src/pybind/mgr/diskprediction_local/models/svm_57.pkl
new file mode 100644
index 00000000..fe783289
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_57.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_59.pkl b/src/pybind/mgr/diskprediction_local/models/svm_59.pkl
new file mode 100644
index 00000000..76217777
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_59.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_6.pkl b/src/pybind/mgr/diskprediction_local/models/svm_6.pkl
new file mode 100644
index 00000000..4fb09d37
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_6.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_61.pkl b/src/pybind/mgr/diskprediction_local/models/svm_61.pkl
new file mode 100644
index 00000000..319fc5f4
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_61.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_62.pkl b/src/pybind/mgr/diskprediction_local/models/svm_62.pkl
new file mode 100644
index 00000000..25b21aed
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_62.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_67.pkl b/src/pybind/mgr/diskprediction_local/models/svm_67.pkl
new file mode 100644
index 00000000..1e6e7383
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_67.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_69.pkl b/src/pybind/mgr/diskprediction_local/models/svm_69.pkl
new file mode 100644
index 00000000..22d349a7
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_69.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_71.pkl b/src/pybind/mgr/diskprediction_local/models/svm_71.pkl
new file mode 100644
index 00000000..e0760add
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_71.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_72.pkl b/src/pybind/mgr/diskprediction_local/models/svm_72.pkl
new file mode 100644
index 00000000..5096aa8e
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_72.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_78.pkl b/src/pybind/mgr/diskprediction_local/models/svm_78.pkl
new file mode 100644
index 00000000..7958f3b6
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_78.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_79.pkl b/src/pybind/mgr/diskprediction_local/models/svm_79.pkl
new file mode 100644
index 00000000..2ed3a0fe
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_79.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_82.pkl b/src/pybind/mgr/diskprediction_local/models/svm_82.pkl
new file mode 100644
index 00000000..2e188409
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_82.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_85.pkl b/src/pybind/mgr/diskprediction_local/models/svm_85.pkl
new file mode 100644
index 00000000..88161af5
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_85.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_88.pkl b/src/pybind/mgr/diskprediction_local/models/svm_88.pkl
new file mode 100644
index 00000000..71563398
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_88.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_93.pkl b/src/pybind/mgr/diskprediction_local/models/svm_93.pkl
new file mode 100644
index 00000000..703429fe
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_93.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/models/svm_97.pkl b/src/pybind/mgr/diskprediction_local/models/svm_97.pkl
new file mode 100644
index 00000000..9653d20f
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/models/svm_97.pkl
Binary files differ
diff --git a/src/pybind/mgr/diskprediction_local/module.py b/src/pybind/mgr/diskprediction_local/module.py
new file mode 100644
index 00000000..7339c603
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/module.py
@@ -0,0 +1,266 @@
+"""
+diskprediction with local predictor
+"""
+import json
+import datetime
+import _strptime
+from threading import Event
+import time
+
+from mgr_module import MgrModule, CommandResult
+
+
+TIME_FORMAT = '%Y%m%d-%H%M%S'
+TIME_DAYS = 24*60*60
+TIME_WEEK = TIME_DAYS * 7
+
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'sleep_interval',
+ 'default': str(600),
+ },
+ {
+ 'name': 'predict_interval',
+ 'default': str(86400),
+ },
+ ]
+
+ COMMANDS = []
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ # options
+ for opt in self.MODULE_OPTIONS:
+ setattr(self, opt['name'], opt['default'])
+ # other
+ self._run = True
+ self._event = Event()
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+ if self.get_ceph_option('device_failure_prediction_mode') == 'local':
+ self._event.set()
+
+ def refresh_config(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+
+ def handle_command(self, _, cmd):
+ self.log.debug('handle_command cmd: %s', cmd)
+ raise NotImplementedError(cmd['prefix'])
+
+ def self_test(self):
+ ret, out, err = self.predict_all_devices()
+ assert ret == 0
+ return 0, 'self test succeed', ''
+
+ def serve(self):
+ self.log.info('Starting diskprediction local module')
+ self.config_notify()
+ last_predicted = None
+ ls = self.get_store('last_predicted')
+ if ls:
+ try:
+ last_predicted = datetime.datetime.strptime(ls, TIME_FORMAT)
+ except ValueError:
+ pass
+ self.log.debug('Last predicted %s', last_predicted)
+
+ while self._run:
+ self.refresh_config()
+ mode = self.get_ceph_option('device_failure_prediction_mode')
+ if mode == 'local':
+ now = datetime.datetime.utcnow()
+ if not last_predicted:
+ next_predicted = now
+ else:
+ predicted_frequency = int(self.predict_interval) or 86400
+ seconds = (last_predicted - datetime.datetime.utcfromtimestamp(0)).total_seconds()
+ seconds -= seconds % predicted_frequency
+ seconds += predicted_frequency
+ next_predicted = datetime.datetime.utcfromtimestamp(seconds)
+ if last_predicted:
+ self.log.debug('Last scrape %s, next scrape due %s',
+ last_predicted.strftime(TIME_FORMAT),
+ next_predicted.strftime(TIME_FORMAT))
+ else:
+ self.log.debug('Last scrape never, next scrape due %s',
+ next_predicted.strftime(TIME_FORMAT))
+ if now >= next_predicted:
+ self.predict_all_devices()
+ last_predicted = now
+ self.set_store('last_predicted', last_predicted.strftime(TIME_FORMAT))
+
+ sleep_interval = int(self.sleep_interval) or 60
+ self.log.debug('Sleeping for %d seconds', sleep_interval)
+ self._event.wait(sleep_interval)
+ self._event.clear()
+
+ def shutdown(self):
+ self.log.info('Stopping')
+ self._run = False
+ self._event.set()
+
+ @staticmethod
+ def _convert_timestamp(predicted_timestamp, life_expectancy_day):
+ """
+ :param predicted_timestamp: unit is nanoseconds
+ :param life_expectancy_day: unit is seconds
+ :return:
+ date format '%Y-%m-%d' ex. 2018-01-01
+ """
+ return datetime.datetime.fromtimestamp(
+ predicted_timestamp / (1000 ** 3) + life_expectancy_day).strftime('%Y-%m-%d')
+
+ def _predict_life_expentancy(self, devid):
+ predicted_result = ''
+ from .predictor import get_diskfailurepredictor_path, DiskFailurePredictor
+ health_data = {}
+ predict_datas = []
+ try:
+ r, outb, outs = self.remote('devicehealth', 'show_device_metrics', devid=devid, sample='')
+ if r != 0:
+ self.log.error('failed to get device %s health', devid)
+ health_data = {}
+ else:
+ health_data = json.loads(outb)
+ except Exception as e:
+ self.log.error('failed to get device %s health data due to %s', devid, str(e))
+
+ obj_predictor = DiskFailurePredictor()
+ obj_predictor.initialize("{}/models".format(get_diskfailurepredictor_path()))
+
+ if len(health_data) >= 6:
+ o_keys = sorted(health_data.keys(), reverse=True)
+ for o_key in o_keys:
+ dev_smart = {}
+ s_val = health_data[o_key]
+ ata_smart = s_val.get('ata_smart_attributes', {})
+ for attr in ata_smart.get('table', []):
+ if attr.get('raw', {}).get('string'):
+ if str(attr.get('raw', {}).get('string', '0')).isdigit():
+ dev_smart['smart_%s_raw' % attr.get('id')] = \
+ int(attr.get('raw', {}).get('string', '0'))
+ else:
+ if str(attr.get('raw', {}).get('string', '0')).split(' ')[0].isdigit():
+ dev_smart['smart_%s_raw' % attr.get('id')] = \
+ int(attr.get('raw', {}).get('string',
+ '0').split(' ')[0])
+ else:
+ dev_smart['smart_%s_raw' % attr.get('id')] = \
+ attr.get('raw', {}).get('value', 0)
+ if s_val.get('power_on_time', {}).get('hours') is not None:
+ dev_smart['smart_9_raw'] = int(s_val['power_on_time']['hours'])
+ if dev_smart:
+ predict_datas.append(dev_smart)
+ if len(predict_datas) >= 12:
+ break
+ else:
+ self.log.error('unable to predict device due to health data records less than 6 days')
+
+ if len(predict_datas) >= 6:
+ predicted_result = obj_predictor.predict(predict_datas)
+ return predicted_result
+
+ def predict_life_expectancy(self, devid):
+ result = self._predict_life_expentancy(devid)
+ if result.lower() == 'good':
+ return 0, '>6w', ''
+ elif result.lower() == 'warning':
+ return 0, '>=2w and <=6w', ''
+ elif result.lower() == 'bad':
+ return 0, '<2w', ''
+ else:
+ return 0, 'unknown', ''
+
+ def _reset_device_life_expectancy(self, device_id):
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device rm-life-expectancy',
+ 'devid': device_id
+ }), '')
+ ret, _, outs = result.wait()
+ if ret != 0:
+ self.log.error(
+ 'failed to reset device life expectancy, %s' % outs)
+ return ret
+
+ def _set_device_life_expectancy(self, device_id, from_date, to_date=None):
+ result = CommandResult('')
+
+ if to_date is None:
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device set-life-expectancy',
+ 'devid': device_id,
+ 'from': from_date
+ }), '')
+ else:
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'device set-life-expectancy',
+ 'devid': device_id,
+ 'from': from_date,
+ 'to': to_date
+ }), '')
+ ret, _, outs = result.wait()
+ if ret != 0:
+ self.log.error(
+ 'failed to set device life expectancy, %s' % outs)
+ return ret
+
+ def predict_all_devices(self):
+ devices = self.get('devices').get('devices', [])
+ for devInfo in devices:
+ if not devInfo.get('daemons'):
+ continue
+ if not devInfo.get('devid'):
+ continue
+ result = self._predict_life_expentancy(devInfo['devid'])
+ if result == 'unknown':
+ self._reset_device_life_expectancy(devInfo['devid'])
+ continue
+ predicted = int(time.time() * (1000 ** 3))
+
+ if result.lower() == 'good':
+ life_expectancy_day_min = (TIME_WEEK * 6) + TIME_DAYS
+ life_expectancy_day_max = None
+ elif result.lower() == 'warning':
+ life_expectancy_day_min = (TIME_WEEK * 2)
+ life_expectancy_day_max = (TIME_WEEK * 6)
+ elif result.lower() == 'bad':
+ life_expectancy_day_min = 0
+ life_expectancy_day_max = (TIME_WEEK * 2) - TIME_DAYS
+ else:
+ predicted = None
+ life_expectancy_day_min = None
+ life_expectancy_day_max = None
+
+ if predicted and devInfo['devid'] and life_expectancy_day_min:
+ from_date = None
+ to_date = None
+ try:
+ if life_expectancy_day_min:
+ from_date = self._convert_timestamp(predicted, life_expectancy_day_min)
+
+ if life_expectancy_day_max:
+ to_date = self._convert_timestamp(predicted, life_expectancy_day_max)
+
+ self._set_device_life_expectancy(devInfo['devid'], from_date, to_date)
+ self._logger.info(
+ 'succeed to set device {} life expectancy from: {}, to: {}'.format(
+ devInfo['devid'], from_date, to_date))
+ except Exception as e:
+ self._logger.error(
+ 'failed to set device {} life expectancy from: {}, to: {}, {}'.format(
+ devInfo['devid'], from_date, to_date, str(e)))
+ else:
+ self._reset_device_life_expectancy(devInfo['devid'])
+ return 0, 'succeed to predicted all devices', ''
diff --git a/src/pybind/mgr/diskprediction_local/predictor.py b/src/pybind/mgr/diskprediction_local/predictor.py
new file mode 100644
index 00000000..bf9b0d7d
--- /dev/null
+++ b/src/pybind/mgr/diskprediction_local/predictor.py
@@ -0,0 +1,265 @@
+"""Sample code for disk failure prediction.
+
+This sample code is a community version for anyone who is interested in Machine
+Learning and care about disk failure.
+
+This class provides a disk failure prediction module. Given models dirpath to
+initialize a predictor instance and then use 6 days data to predict. Predict
+function will return a string to indicate disk failure status: "Good",
+"Warning", "Bad", or "Unknown".
+
+An example code is as follows:
+
+>>> model = disk_failure_predictor.DiskFailurePredictor()
+>>> status = model.initialize("./models")
+>>> if status:
+>>> model.predict(disk_days)
+'Bad'
+
+
+Provided by ProphetStor Data Services Inc.
+http://www.prophetstor.com/
+
+"""
+
+from __future__ import print_function
+import os
+import json
+import pickle
+
+
+def get_diskfailurepredictor_path():
+ path = os.path.abspath(__file__)
+ dir_path = os.path.dirname(path)
+ return dir_path
+
+
+class DiskFailurePredictor(object):
+ """Disk failure prediction
+
+ This class implements a disk failure prediction module.
+ """
+
+ CONFIG_FILE = "config.json"
+ EXCLUDED_ATTRS = ['smart_9_raw', 'smart_241_raw', 'smart_242_raw']
+
+ def __init__(self):
+ """
+ This function may throw exception due to wrong file operation.
+ """
+
+ self.model_dirpath = ""
+ self.model_context = {}
+
+ def initialize(self, model_dirpath):
+ """
+ Initialize all models.
+
+ Args: None
+
+ Returns:
+ Error message. If all goes well, return an empty string.
+
+ Raises:
+ """
+
+ config_path = os.path.join(model_dirpath, self.CONFIG_FILE)
+ if not os.path.isfile(config_path):
+ return "Missing config file: " + config_path
+ else:
+ with open(config_path) as f_conf:
+ self.model_context = json.load(f_conf)
+
+ for model_name in self.model_context:
+ model_path = os.path.join(model_dirpath, model_name)
+
+ if not os.path.isfile(model_path):
+ return "Missing model file: " + model_path
+
+ self.model_dirpath = model_dirpath
+
+ def __preprocess(self, disk_days):
+ """
+ Preprocess disk attributes.
+
+ Args:
+ disk_days: Refer to function predict(...).
+
+ Returns:
+ new_disk_days: Processed disk days.
+ """
+
+ req_attrs = []
+ new_disk_days = []
+
+ attr_list = set.intersection(*[set(disk_day.keys())
+ for disk_day in disk_days])
+ for attr in attr_list:
+ if (attr.startswith('smart_') and attr.endswith('_raw')) and \
+ attr not in self.EXCLUDED_ATTRS:
+ req_attrs.append(attr)
+
+ for disk_day in disk_days:
+ new_disk_day = {}
+ for attr in req_attrs:
+ if float(disk_day[attr]) >= 0.0:
+ new_disk_day[attr] = disk_day[attr]
+
+ new_disk_days.append(new_disk_day)
+
+ return new_disk_days
+
+ @staticmethod
+ def __get_diff_attrs(disk_days):
+ """
+ Get 5 days differential attributes.
+
+ Args:
+ disk_days: Refer to function predict(...).
+
+ Returns:
+ attr_list: All S.M.A.R.T. attributes used in given disk. Here we
+ use intersection set of all disk days.
+
+ diff_disk_days: A list struct comprises 5 dictionaries, each
+ dictionary contains differential attributes.
+
+ Raises:
+ Exceptions of wrong list/dict operations.
+ """
+
+ all_attrs = [set(disk_day.keys()) for disk_day in disk_days]
+ attr_list = list(set.intersection(*all_attrs))
+ attr_list = disk_days[0].keys()
+ prev_days = disk_days[:-1]
+ curr_days = disk_days[1:]
+ diff_disk_days = []
+
+ for prev, cur in zip(prev_days, curr_days):
+ diff_disk_days.append({attr:(int(cur[attr]) - int(prev[attr]))
+ for attr in attr_list})
+
+ return attr_list, diff_disk_days
+
+ def __get_best_models(self, attr_list):
+ """
+ Find the best model from model list according to given attribute list.
+
+ Args:
+ attr_list: All S.M.A.R.T. attributes used in given disk.
+
+ Returns:
+ modelpath: The best model for the given attribute list.
+ model_attrlist: 'Ordered' attribute list of the returned model.
+ Must be aware that SMART attributes is in order.
+
+ Raises:
+ """
+
+ models = self.model_context.keys()
+
+ scores = []
+ for model_name in models:
+ scores.append(sum(attr in attr_list
+ for attr in self.model_context[model_name]))
+ max_score = max(scores)
+
+ # Skip if too few matched attributes.
+ if max_score < 3:
+ print("Too few matched attributes")
+ return None
+
+ best_models = {}
+ best_model_indices = [idx for idx, score in enumerate(scores)
+ if score > max_score - 2]
+ for model_idx in best_model_indices:
+ model_name = list(models)[model_idx]
+ model_path = os.path.join(self.model_dirpath, model_name)
+ model_attrlist = self.model_context[model_name]
+ best_models[model_path] = model_attrlist
+
+ return best_models
+ # return os.path.join(self.model_dirpath, model_name), model_attrlist
+
+ @staticmethod
+ def __get_ordered_attrs(disk_days, model_attrlist):
+ """
+ Return ordered attributes of given disk days.
+
+ Args:
+ disk_days: Unordered disk days.
+ model_attrlist: Model's ordered attribute list.
+
+ Returns:
+ ordered_attrs: Ordered disk days.
+
+ Raises: None
+ """
+
+ ordered_attrs = []
+
+ for one_day in disk_days:
+ one_day_attrs = []
+
+ for attr in model_attrlist:
+ if attr in one_day:
+ one_day_attrs.append(one_day[attr])
+ else:
+ one_day_attrs.append(0)
+
+ ordered_attrs.append(one_day_attrs)
+
+ return ordered_attrs
+
+ def predict(self, disk_days):
+ """
+ Predict using given 6-days disk S.M.A.R.T. attributes.
+
+ Args:
+ disk_days: A list struct comprises 6 dictionaries. These
+ dictionaries store 'consecutive' days of disk SMART
+ attributes.
+ Returns:
+ A string indicates prediction result. One of following four strings
+ will be returned according to disk failure status:
+ (1) Good : Disk is health
+ (2) Warning : Disk has some symptoms but may not fail immediately
+ (3) Bad : Disk is in danger and data backup is highly recommended
+ (4) Unknown : Not enough data for prediction.
+
+ Raises:
+ Pickle exceptions
+ """
+
+ all_pred = []
+
+ proc_disk_days = self.__preprocess(disk_days)
+ attr_list, diff_data = DiskFailurePredictor.__get_diff_attrs(proc_disk_days)
+ modellist = self.__get_best_models(attr_list)
+ if modellist is None:
+ return "Unknown"
+
+ for modelpath in modellist:
+ model_attrlist = modellist[modelpath]
+ ordered_data = DiskFailurePredictor.__get_ordered_attrs(
+ diff_data, model_attrlist)
+
+ try:
+ with open(modelpath, 'rb') as f_model:
+ clf = pickle.load(f_model)
+
+ except UnicodeDecodeError:
+ # Compatibility for python3
+ with open(modelpath, 'rb') as f_model:
+ clf = pickle.load(f_model, encoding='latin1')
+
+ pred = clf.predict(ordered_data)
+
+ all_pred.append(1 if any(pred) else 0)
+
+ score = 2 ** sum(all_pred) - len(modellist)
+ if score > 10:
+ return "Bad"
+ if score > 4:
+ return "Warning"
+ return "Good"
diff --git a/src/pybind/mgr/hello/__init__.py b/src/pybind/mgr/hello/__init__.py
new file mode 100644
index 00000000..129920c0
--- /dev/null
+++ b/src/pybind/mgr/hello/__init__.py
@@ -0,0 +1 @@
+from .module import Hello
diff --git a/src/pybind/mgr/hello/module.py b/src/pybind/mgr/hello/module.py
new file mode 100644
index 00000000..94d532ee
--- /dev/null
+++ b/src/pybind/mgr/hello/module.py
@@ -0,0 +1,82 @@
+
+"""
+A hello world module
+
+See doc/mgr/hello.rst for more info.
+"""
+
+from mgr_module import MgrModule, HandleCommandResult
+from threading import Event
+
+
+class Hello(MgrModule):
+ # these are CLI commands we implement
+ COMMANDS = [
+ {
+ "cmd": "hello "
+ "name=person_name,type=CephString,req=false",
+ "desc": "Prints hello world to mgr.x.log",
+ "perm": "r"
+ },
+ ]
+
+ # these are module options we understand. These can be set with
+ # 'ceph config set global mgr/hello/<name> <value>'. e.g.,
+ # 'ceph config set global mgr/hello/place Earth'
+ MODULE_OPTIONS = [
+ {
+ 'name': 'place',
+ 'default': 'world',
+ },
+ {
+ 'name': 'emphatic',
+ 'type': 'bool',
+ 'default': True,
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Hello, self).__init__(*args, **kwargs)
+
+ # set up some members to enable the serve() method and shutdown
+ self.run = True
+ self.event = Event()
+
+ def handle_command(self, inbuf, cmd):
+ self.log.info("hello_world_info")
+ self.log.debug("hello_world_debug")
+ self.log.error("hello_world_error")
+
+ status_code = 0
+ output_buffer = "Output buffer is for data results"
+ output_string = "Output string is for informative text"
+ if 'person_name' in cmd:
+ message = "Hello, " + cmd['person_name']
+ else:
+ message = "Hello " + self.get_module_option('place')
+ if self.get_module_option('emphatic'):
+ message += '!'
+
+ return HandleCommandResult(retval=status_code, stdout=output_buffer,
+ stderr=message + "\n" + output_string)
+
+ def serve(self):
+ """
+ This method is called by the mgr when the module starts and can be
+ used for any background activity.
+ """
+ self.log.info("Starting")
+ while self.run:
+ sleep_interval = 5
+ self.log.debug('Sleeping for %d seconds', sleep_interval)
+ ret = self.event.wait(sleep_interval)
+ self.event.clear()
+
+ def shutdown(self):
+ """
+ This method is called by the mgr when the module needs to shut
+ down (i.e., when the serve() function needs to exit.
+ """
+ self.log.info('Stopping')
+ self.run = False
+ self.event.set()
diff --git a/src/pybind/mgr/influx/__init__.py b/src/pybind/mgr/influx/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/influx/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/influx/module.py b/src/pybind/mgr/influx/module.py
new file mode 100644
index 00000000..f3b80041
--- /dev/null
+++ b/src/pybind/mgr/influx/module.py
@@ -0,0 +1,489 @@
+from contextlib import contextmanager
+from datetime import datetime
+from threading import Event, Thread
+from itertools import chain
+from six import next
+from six.moves import queue
+from six.moves import xrange as range
+import json
+import errno
+import six
+import time
+
+from mgr_module import MgrModule
+
+try:
+ from influxdb import InfluxDBClient
+ from influxdb.exceptions import InfluxDBClientError
+ from requests.exceptions import RequestException
+except ImportError:
+ InfluxDBClient = None
+
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {
+ 'name': 'hostname',
+ 'default': None
+ },
+ {
+ 'name': 'port',
+ 'default': 8086
+ },
+ {
+ 'name': 'database',
+ 'default': 'ceph'
+ },
+ {
+ 'name': 'username',
+ 'default': None
+ },
+ {
+ 'name': 'password',
+ 'default': None
+ },
+ {
+ 'name': 'interval',
+ 'default': 30
+ },
+ {
+ 'name': 'ssl',
+ 'default': 'false'
+ },
+ {
+ 'name': 'verify_ssl',
+ 'default': 'true'
+ },
+ {
+ 'name': 'threads',
+ 'default': 5
+ },
+ {
+ 'name': 'batch_size',
+ 'default': 5000
+ }
+ ]
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None))
+ for o in self.MODULE_OPTIONS)
+
+ COMMANDS = [
+ {
+ "cmd": "influx config-set name=key,type=CephString "
+ "name=value,type=CephString",
+ "desc": "Set a configuration value",
+ "perm": "rw"
+ },
+ {
+ "cmd": "influx config-show",
+ "desc": "Show current configuration",
+ "perm": "r"
+ },
+ {
+ "cmd": "influx send",
+ "desc": "Force sending data to Influx",
+ "perm": "rw"
+ }
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.event = Event()
+ self.run = True
+ self.config = dict()
+ self.workers = list()
+ self.queue = queue.Queue(maxsize=100)
+ self.health_checks = dict()
+
+ def get_fsid(self):
+ return self.get('mon_map')['fsid']
+
+ @staticmethod
+ def can_run():
+ if InfluxDBClient is not None:
+ return True, ""
+ else:
+ return False, "influxdb python module not found"
+
+ @staticmethod
+ def get_timestamp():
+ return datetime.utcnow().isoformat() + 'Z'
+
+ @staticmethod
+ def chunk(l, n):
+ try:
+ while True:
+ xs = []
+ for _ in range(n):
+ xs.append(next(l))
+ yield xs
+ except StopIteration:
+ yield xs
+
+ def queue_worker(self):
+ while True:
+ try:
+ points = self.queue.get()
+ if points is None:
+ self.log.debug('Worker shutting down')
+ break
+
+ start = time.time()
+ with self.get_influx_client() as client:
+ client.write_points(points, time_precision='ms')
+ runtime = time.time() - start
+ self.log.debug('Writing points %d to Influx took %.3f seconds',
+ len(points), runtime)
+ except RequestException as e:
+ self.log.exception("Failed to connect to Influx host %s:%d",
+ self.config['hostname'], self.config['port'])
+ self.health_checks.update({
+ 'MGR_INFLUX_SEND_FAILED': {
+ 'severity': 'warning',
+ 'summary': 'Failed to send data to InfluxDB server '
+ 'at %s:%d due to an connection error'
+ % (self.config['hostname'],
+ self.config['port']),
+ 'detail': [str(e)]
+ }
+ })
+ except InfluxDBClientError as e:
+ self.health_checks.update({
+ 'MGR_INFLUX_SEND_FAILED': {
+ 'severity': 'warning',
+ 'summary': 'Failed to send data to InfluxDB',
+ 'detail': [str(e)]
+ }
+ })
+ self.log.exception('Failed to send data to InfluxDB')
+ except queue.Empty:
+ continue
+ except:
+ self.log.exception('Unhandled Exception while sending to Influx')
+ finally:
+ self.queue.task_done()
+
+ def get_latest(self, daemon_type, daemon_name, stat):
+ data = self.get_counter(daemon_type, daemon_name, stat)[stat]
+ if data:
+ return data[-1][1]
+
+ return 0
+
+ def get_df_stats(self, now):
+ df = self.get("df")
+ data = []
+ pool_info = {}
+
+ df_types = [
+ 'stored',
+ 'kb_used',
+ 'dirty',
+ 'rd',
+ 'rd_bytes',
+ 'stored_raw',
+ 'wr',
+ 'wr_bytes',
+ 'objects',
+ 'max_avail',
+ 'quota_objects',
+ 'quota_bytes'
+ ]
+
+ for df_type in df_types:
+ for pool in df['pools']:
+ point = {
+ "measurement": "ceph_pool_stats",
+ "tags": {
+ "pool_name": pool['name'],
+ "pool_id": pool['id'],
+ "type_instance": df_type,
+ "fsid": self.get_fsid()
+ },
+ "time": now,
+ "fields": {
+ "value": pool['stats'][df_type],
+ }
+ }
+ data.append(point)
+ pool_info.update({str(pool['id']):pool['name']})
+ return data, pool_info
+
+ def get_pg_summary_osd(self, pool_info, now):
+ pg_sum = self.get('pg_summary')
+ osd_sum = pg_sum['by_osd']
+ for osd_id, stats in six.iteritems(osd_sum):
+ metadata = self.get_metadata('osd', "%s" % osd_id)
+ if not metadata:
+ continue
+
+ for stat in stats:
+ yield {
+ "measurement": "ceph_pg_summary_osd",
+ "tags": {
+ "ceph_daemon": "osd." + str(osd_id),
+ "type_instance": stat,
+ "host": metadata['hostname']
+ },
+ "time" : now,
+ "fields" : {
+ "value": stats[stat]
+ }
+ }
+
+ def get_pg_summary_pool(self, pool_info, now):
+ pool_sum = self.get('pg_summary')['by_pool']
+ for pool_id, stats in six.iteritems(pool_sum):
+ for stat in stats:
+ yield {
+ "measurement": "ceph_pg_summary_pool",
+ "tags": {
+ "pool_name" : pool_info[pool_id],
+ "pool_id" : pool_id,
+ "type_instance" : stat,
+ },
+ "time" : now,
+ "fields": {
+ "value" : stats[stat],
+ }
+ }
+
+ def get_daemon_stats(self, now):
+ for daemon, counters in six.iteritems(self.get_all_perf_counters()):
+ svc_type, svc_id = daemon.split(".", 1)
+ metadata = self.get_metadata(svc_type, svc_id)
+
+ for path, counter_info in counters.items():
+ if counter_info['type'] & self.PERFCOUNTER_HISTOGRAM:
+ continue
+
+ value = counter_info['value']
+
+ yield {
+ "measurement": "ceph_daemon_stats",
+ "tags": {
+ "ceph_daemon": daemon,
+ "type_instance": path,
+ "host": metadata['hostname'],
+ "fsid": self.get_fsid()
+ },
+ "time": now,
+ "fields": {
+ "value": value
+ }
+ }
+
+ def set_config_option(self, option, value):
+ if option not in self.config_keys.keys():
+ raise RuntimeError('{0} is a unknown configuration '
+ 'option'.format(option))
+
+ if option in ['port', 'interval', 'threads', 'batch_size']:
+ try:
+ value = int(value)
+ except (ValueError, TypeError):
+ raise RuntimeError('invalid {0} configured. Please specify '
+ 'a valid integer'.format(option))
+
+ if option == 'interval' and value < 5:
+ raise RuntimeError('interval should be set to at least 5 seconds')
+
+ if option in ['ssl', 'verify_ssl']:
+ value = value.lower() == 'true'
+
+ if option == 'threads':
+ if 1 > value > 32:
+ raise RuntimeError('threads should be in range 1-32')
+
+ self.config[option] = value
+
+ def init_module_config(self):
+ self.config['hostname'] = \
+ self.get_module_option("hostname", default=self.config_keys['hostname'])
+ self.config['port'] = \
+ int(self.get_module_option("port", default=self.config_keys['port']))
+ self.config['database'] = \
+ self.get_module_option("database", default=self.config_keys['database'])
+ self.config['username'] = \
+ self.get_module_option("username", default=self.config_keys['username'])
+ self.config['password'] = \
+ self.get_module_option("password", default=self.config_keys['password'])
+ self.config['interval'] = \
+ int(self.get_module_option("interval",
+ default=self.config_keys['interval']))
+ self.config['threads'] = \
+ int(self.get_module_option("threads",
+ default=self.config_keys['threads']))
+ self.config['batch_size'] = \
+ int(self.get_module_option("batch_size",
+ default=self.config_keys['batch_size']))
+ ssl = self.get_module_option("ssl", default=self.config_keys['ssl'])
+ self.config['ssl'] = ssl.lower() == 'true'
+ verify_ssl = \
+ self.get_module_option("verify_ssl", default=self.config_keys['verify_ssl'])
+ self.config['verify_ssl'] = verify_ssl.lower() == 'true'
+
+ def gather_statistics(self):
+ now = self.get_timestamp()
+ df_stats, pools = self.get_df_stats(now)
+ return chain(df_stats, self.get_daemon_stats(now),
+ self.get_pg_summary_osd(pools, now),
+ self.get_pg_summary_pool(pools, now))
+
+ @contextmanager
+ def get_influx_client(self):
+ client = InfluxDBClient(self.config['hostname'],
+ self.config['port'],
+ self.config['username'],
+ self.config['password'],
+ self.config['database'],
+ self.config['ssl'],
+ self.config['verify_ssl'])
+ try:
+ yield client
+ finally:
+ try:
+ client.close()
+ except AttributeError:
+ # influxdb older than v5.0.0
+ pass
+
+ def send_to_influx(self):
+ if not self.config['hostname']:
+ self.log.error("No Influx server configured, please set one using: "
+ "ceph influx config-set hostname <hostname>")
+
+ self.set_health_checks({
+ 'MGR_INFLUX_NO_SERVER': {
+ 'severity': 'warning',
+ 'summary': 'No InfluxDB server configured',
+ 'detail': ['Configuration option hostname not set']
+ }
+ })
+ return False
+
+ self.health_checks = dict()
+
+ self.log.debug("Sending data to Influx host: %s",
+ self.config['hostname'])
+ try:
+ with self.get_influx_client() as client:
+ databases = client.get_list_database()
+ if {'name': self.config['database']} not in databases:
+ self.log.info("Database '%s' not found, trying to create "
+ "(requires admin privs). You can also create "
+ "manually and grant write privs to user "
+ "'%s'", self.config['database'],
+ self.config['database'])
+ client.create_database(self.config['database'])
+ client.create_retention_policy(name='8_weeks',
+ duration='8w',
+ replication='1',
+ default=True,
+ database=self.config['database'])
+
+ self.log.debug('Gathering statistics')
+ points = self.gather_statistics()
+ for chunk in self.chunk(points, self.config['batch_size']):
+ self.queue.put(chunk, block=False)
+
+ self.log.debug('Queue currently contains %d items',
+ self.queue.qsize())
+ except queue.Full:
+ self.health_checks.update({
+ 'MGR_INFLUX_QUEUE_FULL': {
+ 'severity': 'warning',
+ 'summary': 'Failed to chunk to InfluxDB Queue',
+ 'detail': ['Queue is full. InfluxDB might be slow with '
+ 'processing data']
+ }
+ })
+ self.log.error('Queue is full, failed to add chunk')
+ except (RequestException, InfluxDBClientError) as e:
+ self.health_checks.update({
+ 'MGR_INFLUX_DB_LIST_FAILED': {
+ 'severity': 'warning',
+ 'summary': 'Failed to list/create InfluxDB database',
+ 'detail': [str(e)]
+ }
+ })
+ self.log.exception('Failed to list/create InfluxDB database')
+ return False
+ finally:
+ self.set_health_checks(self.health_checks)
+
+ def shutdown(self):
+ self.log.info('Stopping influx module')
+ self.run = False
+ self.event.set()
+ self.log.debug('Shutting down queue workers')
+
+ for _ in self.workers:
+ self.queue.put(None)
+
+ self.queue.join()
+
+ for worker in self.workers:
+ worker.join()
+
+ def self_test(self):
+ now = self.get_timestamp()
+ daemon_stats = list(self.get_daemon_stats(now))
+ assert len(daemon_stats)
+ df_stats, pools = self.get_df_stats(now)
+
+ result = {
+ 'daemon_stats': daemon_stats,
+ 'df_stats': df_stats
+ }
+
+ return json.dumps(result, indent=2)
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == 'influx config-show':
+ return 0, json.dumps(self.config), ''
+ elif cmd['prefix'] == 'influx config-set':
+ key = cmd['key']
+ value = cmd['value']
+ if not value:
+ return -errno.EINVAL, '', 'Value should not be empty or None'
+
+ self.log.debug('Setting configuration option %s to %s', key, value)
+ self.set_config_option(key, value)
+ self.set_module_option(key, value)
+ return 0, 'Configuration option {0} updated'.format(key), ''
+ elif cmd['prefix'] == 'influx send':
+ self.send_to_influx()
+ return 0, 'Sending data to Influx', ''
+
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(cmd['prefix']))
+
+ def serve(self):
+ if InfluxDBClient is None:
+ self.log.error("Cannot transmit statistics: influxdb python "
+ "module not found. Did you install it?")
+ return
+
+ self.log.info('Starting influx module')
+ self.init_module_config()
+ self.run = True
+
+ self.log.debug('Starting %d queue worker threads',
+ self.config['threads'])
+ for i in range(self.config['threads']):
+ worker = Thread(target=self.queue_worker, args=())
+ worker.setDaemon(True)
+ worker.start()
+ self.workers.append(worker)
+
+ while self.run:
+ start = time.time()
+ self.send_to_influx()
+ runtime = time.time() - start
+ self.log.debug('Finished sending data to Influx in %.3f seconds',
+ runtime)
+ self.log.debug("Sleeping for %d seconds", self.config['interval'])
+ self.event.wait(self.config['interval'])
diff --git a/src/pybind/mgr/insights/CMakeLists.txt b/src/pybind/mgr/insights/CMakeLists.txt
new file mode 100644
index 00000000..00722a99
--- /dev/null
+++ b/src/pybind/mgr/insights/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(MGR_INSIGHTS_VIRTUALENV ${CEPH_BUILD_VIRTUALENV}/mgr-insights-virtualenv)
+
+add_custom_target(mgr-insights-test-venv
+ COMMAND ${CMAKE_SOURCE_DIR}/src/tools/setup-virtualenv.sh --python=${MGR_PYTHON_EXECUTABLE} ${MGR_INSIGHTS_VIRTUALENV}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/insights
+ COMMENT "insights tests virtualenv is being created")
+add_dependencies(tests mgr-insights-test-venv)
diff --git a/src/pybind/mgr/insights/__init__.py b/src/pybind/mgr/insights/__init__.py
new file mode 100644
index 00000000..ea61a12f
--- /dev/null
+++ b/src/pybind/mgr/insights/__init__.py
@@ -0,0 +1,9 @@
+from __future__ import absolute_import
+import os
+
+if 'UNITTEST' not in os.environ:
+ from .module import Module
+else:
+ import sys
+ import mock
+ sys.modules['ceph_module'] = mock.Mock()
diff --git a/src/pybind/mgr/insights/health.py b/src/pybind/mgr/insights/health.py
new file mode 100644
index 00000000..5235ca84
--- /dev/null
+++ b/src/pybind/mgr/insights/health.py
@@ -0,0 +1,191 @@
+import json
+import six
+from collections import defaultdict
+import datetime
+
+# freq to write cached state to disk
+PERSIST_PERIOD = datetime.timedelta(seconds = 10)
+# on disk key prefix
+HEALTH_HISTORY_KEY_PREFIX = "health_history/"
+# apply on offset to "now": used for testing
+NOW_OFFSET = None
+
+class HealthEncoder(json.JSONEncoder):
+ def default(self, obj):
+ if isinstance(obj, set):
+ return list(obj)
+ return json.JSONEncoder.default(self, obj)
+
+class HealthCheckAccumulator(object):
+ """
+ Deuplicated storage of health checks.
+ """
+ def __init__(self, init_checks = None):
+ # check : severity : { summary, detail }
+ # summary and detail are deduplicated
+ self._checks = defaultdict(lambda:
+ defaultdict(lambda: {
+ "summary": set(),
+ "detail": set()
+ }))
+
+ if init_checks:
+ self._update(init_checks)
+
+ def __str__(self):
+ return "check count {}".format(len(self._checks))
+
+ def add(self, checks):
+ """
+ Add health checks to the current state
+
+ Returns:
+ bool: True if the state changed, False otherwise.
+ """
+ changed = False
+
+ for check, info in six.iteritems(checks):
+
+ # only keep the icky stuff
+ severity = info["severity"]
+ if severity == "HEALTH_OK":
+ continue
+
+ summary = info["summary"]["message"]
+ details = map(lambda d: d["message"], info["detail"])
+
+ if self._add_check(check, severity, [summary], details):
+ changed = True
+
+ return changed
+
+ def checks(self):
+ return self._checks
+
+ def merge(self, other):
+ assert isinstance(other, HealthCheckAccumulator)
+ self._update(other._checks)
+
+ def _update(self, checks):
+ """Merge checks with same structure. Does not set dirty bit"""
+ for check in checks:
+ for severity in checks[check]:
+ summaries = set(checks[check][severity]["summary"])
+ details = set(checks[check][severity]["detail"])
+ self._add_check(check, severity, summaries, details)
+
+ def _add_check(self, check, severity, summaries, details):
+ changed = False
+
+ for summary in summaries:
+ if summary not in self._checks[check][severity]["summary"]:
+ changed = True
+ self._checks[check][severity]["summary"].add(summary)
+
+ for detail in details:
+ if detail not in self._checks[check][severity]["detail"]:
+ changed = True
+ self._checks[check][severity]["detail"].add(detail)
+
+ return changed
+
+class HealthHistorySlot(object):
+ """
+ Manage the life cycle of a health history time slot.
+
+ A time slot is a fixed slice of wall clock time (e.g. every hours, from :00
+ to :59), and all health updates that occur during this time are deduplicated
+ together. A slot is initially in a clean state, and becomes dirty when a new
+ health check is observed. The state of a slot should be persisted when
+ need_flush returns true. Once the state has been flushed, reset the dirty
+ bit by calling mark_flushed.
+ """
+ def __init__(self, init_health = dict()):
+ self._checks = HealthCheckAccumulator(init_health.get("checks"))
+ self._slot = self._curr_slot()
+ self._next_flush = None
+
+ def __str__(self):
+ return "key {} next flush {} checks {}".format(
+ self.key(), self._next_flush, self._checks)
+
+ def health(self):
+ return dict(checks = self._checks.checks())
+
+ def key(self):
+ """Identifier in the persist store"""
+ return self._key(self._slot)
+
+ def expired(self):
+ """True if this slot is the current slot, False otherwise"""
+ return self._slot != self._curr_slot()
+
+ def need_flush(self):
+ """True if this slot needs to be flushed, False otherwise"""
+ now = HealthHistorySlot._now()
+ if self._next_flush is not None:
+ if self._next_flush <= now or self.expired():
+ return True
+ return False
+
+ def mark_flushed(self):
+ """Reset the dirty bit. Caller persists state"""
+ assert self._next_flush
+ self._next_flush = None
+
+ def add(self, health):
+ """
+ Add health to the underlying health accumulator. When the slot
+ transitions from clean to dirty a target flush time is computed.
+ """
+ changed = self._checks.add(health["checks"])
+ if changed and not self._next_flush:
+ self._next_flush = HealthHistorySlot._now() + PERSIST_PERIOD
+ return changed
+
+ def merge(self, other):
+ assert isinstance(other, HealthHistorySlot)
+ self._checks.merge(other._checks)
+
+ @staticmethod
+ def key_range(hours):
+ """Return the time slot keys for the past N hours"""
+ def inner(curr, hours):
+ slot = curr - datetime.timedelta(hours = hours)
+ return HealthHistorySlot._key(slot)
+ curr = HealthHistorySlot._curr_slot()
+ return map(lambda i: inner(curr, i), range(hours))
+
+ @staticmethod
+ def curr_key():
+ """Key for the current UTC time slot"""
+ return HealthHistorySlot._key(HealthHistorySlot._curr_slot())
+
+ @staticmethod
+ def key_to_time(key):
+ """Return key converted into datetime"""
+ timestr = key[len(HEALTH_HISTORY_KEY_PREFIX):]
+ return datetime.datetime.strptime(timestr, "%Y-%m-%d_%H")
+
+ @staticmethod
+ def _key(dt):
+ """Key format. Example: health_2018_11_05_00"""
+ return HEALTH_HISTORY_KEY_PREFIX + dt.strftime("%Y-%m-%d_%H")
+
+ @staticmethod
+ def _now():
+ """Control now time for easier testing"""
+ now = datetime.datetime.utcnow()
+ if NOW_OFFSET is not None:
+ now = now + NOW_OFFSET
+ return now
+
+ @staticmethod
+ def _curr_slot():
+ """Slot for the current UTC time"""
+ dt = HealthHistorySlot._now()
+ return datetime.datetime(
+ year = dt.year,
+ month = dt.month,
+ day = dt.day,
+ hour = dt.hour)
diff --git a/src/pybind/mgr/insights/module.py b/src/pybind/mgr/insights/module.py
new file mode 100644
index 00000000..052295a1
--- /dev/null
+++ b/src/pybind/mgr/insights/module.py
@@ -0,0 +1,322 @@
+import datetime
+import json
+import re
+import threading
+import six
+from mgr_module import MgrModule, CommandResult
+from . import health as health_util
+
+# hours of crash history to report
+CRASH_HISTORY_HOURS = 24
+# hours of health history to report
+HEALTH_HISTORY_HOURS = 24
+# how many hours of health history to keep
+HEALTH_RETENTION_HOURS = 30
+# health check name for insights health
+INSIGHTS_HEALTH_CHECK = "MGR_INSIGHTS_WARNING"
+# version tag for persistent data format
+ON_DISK_VERSION = 1
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "insights",
+ "desc": "Retrieve insights report",
+ "perm": "r",
+ "poll": "false",
+ },
+ {
+ 'cmd': 'insights prune-health name=hours,type=CephString',
+ 'desc': 'Remove health history older than <hours> hours',
+ 'perm': 'rw',
+ "poll": "false",
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+
+ self._shutdown = False
+ self._evt = threading.Event()
+
+ # health history tracking
+ self._pending_health = []
+ self._health_slot = None
+
+ def notify(self, ttype, ident):
+ """Queue updates for processing"""
+ if ttype == "health":
+ self.log.info("Received health check update {} pending".format(
+ len(self._pending_health)))
+ health = json.loads(self.get("health")["json"])
+ self._pending_health.append(health)
+ self._evt.set()
+
+ def serve(self):
+ self._health_reset()
+ while True:
+ self._evt.wait(health_util.PERSIST_PERIOD.total_seconds())
+ self._evt.clear()
+ if self._shutdown:
+ break
+
+ # when the current health slot expires, finalize it by flushing it to
+ # the store, and initializing a new empty slot.
+ if self._health_slot.expired():
+ self.log.info("Health history slot expired {}".format(
+ self._health_slot))
+ self._health_maybe_flush()
+ self._health_reset()
+ self._health_prune_history(HEALTH_RETENTION_HOURS)
+
+ # fold in pending health snapshots and flush
+ self.log.info("Applying {} health updates to slot {}".format(
+ len(self._pending_health), self._health_slot))
+ for health in self._pending_health:
+ self._health_slot.add(health)
+ self._pending_health = []
+ self._health_maybe_flush()
+
+ def shutdown(self):
+ self._shutdown = True
+ self._evt.set()
+
+ def _health_reset(self):
+ """Initialize the current health slot
+
+ The slot will be initialized with any state found to have already been
+ persisted, otherwise the slot will start empty.
+ """
+ key = health_util.HealthHistorySlot.curr_key()
+ data = self.get_store(key)
+ if data:
+ init_health = json.loads(data)
+ self._health_slot = health_util.HealthHistorySlot(init_health)
+ else:
+ self._health_slot = health_util.HealthHistorySlot()
+ self.log.info("Reset curr health slot {}".format(self._health_slot))
+
+ def _health_maybe_flush(self):
+ """Store the health for the current time slot if needed"""
+
+ self.log.info("Maybe flushing slot {} needed {}".format(
+ self._health_slot, self._health_slot.need_flush()))
+
+ if self._health_slot.need_flush():
+ key = self._health_slot.key()
+
+ # build store data entry
+ slot = self._health_slot.health()
+ assert "version" not in slot
+ slot.update(dict(version = ON_DISK_VERSION))
+ data = json.dumps(slot, cls=health_util.HealthEncoder)
+
+ self.log.debug("Storing health key {} data {}".format(
+ key, json.dumps(slot, indent=2, cls=health_util.HealthEncoder)))
+
+ self.set_store(key, data)
+ self._health_slot.mark_flushed()
+
+ def _health_filter(self, f):
+ """Filter hourly health reports timestamp"""
+ matches = filter(
+ lambda t: f(health_util.HealthHistorySlot.key_to_time(t[0])),
+ six.iteritems(self.get_store_prefix(health_util.HEALTH_HISTORY_KEY_PREFIX)))
+ return map(lambda t: t[0], matches)
+
+ def _health_prune_history(self, hours):
+ """Prune old health entries"""
+ cutoff = datetime.datetime.utcnow() - datetime.timedelta(hours = hours)
+ for key in self._health_filter(lambda ts: ts <= cutoff):
+ self.log.info("Removing old health slot key {}".format(key))
+ self.set_store(key, None)
+ if not hours:
+ self._health_slot = health_util.HealthHistorySlot()
+
+ def _health_report(self, hours):
+ """
+ Report a consolidated health report for the past N hours.
+ """
+ # roll up the past N hours of health info
+ collector = health_util.HealthHistorySlot()
+ keys = health_util.HealthHistorySlot.key_range(hours)
+ for key in keys:
+ data = self.get_store(key)
+ self.log.info("Reporting health key {} found {}".format(
+ key, bool(data)))
+ health = json.loads(data) if data else {}
+ slot = health_util.HealthHistorySlot(health)
+ collector.merge(slot)
+
+ # include history that hasn't yet been flushed
+ collector.merge(self._health_slot)
+
+ return dict(
+ current = json.loads(self.get("health")["json"]),
+ history = collector.health()
+ )
+
+ def _version_parse(self, version):
+ """
+ Return the components of a Ceph version string.
+
+ This returns nothing when the version string cannot be parsed into its
+ constituent components, such as when Ceph has been built with
+ ENABLE_GIT_VERSION=OFF.
+ """
+ r = r"ceph version (?P<release>\d+)\.(?P<major>\d+)\.(?P<minor>\d+)"
+ m = re.match(r, version)
+ ver = {} if not m else {
+ "release": m.group("release"),
+ "major": m.group("major"),
+ "minor": m.group("minor")
+ }
+ return { k:int(v) for k,v in six.iteritems(ver) }
+
+ def _crash_history(self, hours):
+ """
+ Load crash history for the past N hours from the crash module.
+ """
+ params = dict(
+ prefix = "crash json_report",
+ hours = hours
+ )
+
+ result = dict(
+ summary = {},
+ hours = params["hours"],
+ )
+
+ health_check_details = []
+
+ try:
+ _, _, crashes = self.remote("crash", "handle_command", "", params)
+ result["summary"] = json.loads(crashes)
+ except Exception as e:
+ errmsg = "failed to invoke crash module"
+ self.log.warning("{}: {}".format(errmsg, str(e)))
+ health_check_details.append(errmsg)
+ else:
+ self.log.debug("Crash module invocation succeeded {}".format(
+ json.dumps(result["summary"], indent=2)))
+
+ return result, health_check_details
+
+ def _apply_osd_stats(self, osd_map):
+ # map from osd id to its index in the map structure
+ osd_id_to_idx = {}
+ for idx in range(len(osd_map["osds"])):
+ osd_id_to_idx[osd_map["osds"][idx]["osd"]] = idx
+
+ # include stats, including space utilization performance counters.
+ # adapted from dashboard api controller
+ for s in self.get('osd_stats')['osd_stats']:
+ try:
+ idx = osd_id_to_idx[s["osd"]]
+ osd_map["osds"][idx].update({'osd_stats': s})
+ except KeyError as e:
+ self.log.warning("inconsistent api state: {}".format(str(e)))
+
+ for osd in osd_map["osds"]:
+ osd['stats'] = {}
+ for s in ['osd.numpg', 'osd.stat_bytes', 'osd.stat_bytes_used']:
+ osd['stats'][s.split('.')[1]] = self.get_latest('osd', str(osd["osd"]), s)
+
+
+ def _config_dump(self):
+ """Report cluster configuration
+
+ This report is the standard `config dump` report. It does not include
+ configuration defaults; these can be inferred from the version number.
+ """
+ result = CommandResult("")
+ args = dict(prefix = "config dump", format = "json")
+ self.send_command(result, "mon", "", json.dumps(args), "")
+ ret, outb, outs = result.wait()
+ if ret == 0:
+ return json.loads(outb), []
+ else:
+ self.log.warning("send_command 'config dump' failed. \
+ ret={}, outs=\"{}\"".format(ret, outs))
+ return [], ["Failed to read monitor config dump"]
+
+ def do_report(self, inbuf, command):
+ health_check_details = []
+ report = {}
+
+ report.update({
+ "version": dict(full = self.version,
+ **self._version_parse(self.version))
+ })
+
+ # crash history
+ crashes, health_details = self._crash_history(CRASH_HISTORY_HOURS)
+ report["crashes"] = crashes
+ health_check_details.extend(health_details)
+
+ # health history
+ report["health"] = self._health_report(HEALTH_HISTORY_HOURS)
+
+ # cluster configuration
+ config, health_details = self._config_dump()
+ report["config"] = config
+ health_check_details.extend(health_details)
+
+ osd_map = self.get("osd_map")
+ del osd_map['pg_temp']
+ self._apply_osd_stats(osd_map)
+ report["osd_dump"] = osd_map
+
+ report["df"] = self.get("df")
+ report["osd_tree"] = self.get("osd_map_tree")
+ report["fs_map"] = self.get("fs_map")
+ report["crush_map"] = self.get("osd_map_crush")
+ report["mon_map"] = self.get("mon_map")
+ report["service_map"] = self.get("service_map")
+ report["manager_map"] = self.get("mgr_map")
+ report["mon_status"] = json.loads(self.get("mon_status")["json"])
+ report["pg_summary"] = self.get("pg_summary")
+ report["osd_metadata"] = self.get("osd_metadata")
+
+ report.update({
+ "errors": health_check_details
+ })
+
+ if health_check_details:
+ self.set_health_checks({
+ INSIGHTS_HEALTH_CHECK: {
+ "severity": "warning",
+ "summary": "Generated incomplete Insights report",
+ "detail": health_check_details
+ }
+ })
+
+ return 0, json.dumps(report, indent=2, cls=health_util.HealthEncoder), ""
+
+ def do_prune_health(self, inbuf, command):
+ try:
+ hours = int(command['hours'])
+ except ValueError:
+ return errno.EINVAL, '', 'hours argument must be integer'
+
+ self._health_prune_history(hours)
+
+ return 0, "", ""
+
+ def testing_set_now_time_offset(self, hours):
+ """
+ Control what "now" time it is by applying an offset. This is called from
+ the selftest module to manage testing scenarios related to tracking
+ health history.
+ """
+ hours = long(hours)
+ health_util.NOW_OFFSET = datetime.timedelta(hours = hours)
+ self.log.warning("Setting now time offset {}".format(health_util.NOW_OFFSET))
+
+ def handle_command(self, inbuf, command):
+ if command["prefix"] == "insights":
+ return self.do_report(inbuf, command)
+ elif command["prefix"] == "insights prune-health":
+ return self.do_prune_health(inbuf, command)
+ else:
+ raise NotImplementedError(cmd["prefix"])
diff --git a/src/pybind/mgr/insights/run-tox.sh b/src/pybind/mgr/insights/run-tox.sh
new file mode 100644
index 00000000..7d621450
--- /dev/null
+++ b/src/pybind/mgr/insights/run-tox.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+function dump_envvars {
+ echo "WITH_PYTHON2: ->$WITH_PYTHON2<-"
+ echo "WITH_PYTHON3: ->$WITH_PYTHON3<-"
+ echo "TOX_PATH: ->$TOX_PATH<-"
+ echo "ENV_LIST: ->$ENV_LIST<-"
+}
+
+# run from ./ or from ../
+: ${MGR_INSIGHTS_VIRTUALENV:=$CEPH_BUILD_DIR/mgr-insights-virtualenv}
+: ${WITH_PYTHON2:=ON}
+: ${WITH_PYTHON3:=3}
+: ${CEPH_BUILD_DIR:=$PWD/.tox}
+test -d insights && cd insights
+
+if [ -e tox.ini ]; then
+ TOX_PATH=$(readlink -f tox.ini)
+else
+ TOX_PATH=$(readlink -f $(dirname $0)/tox.ini)
+fi
+
+# tox.ini will take care of this.
+unset PYTHONPATH
+export CEPH_BUILD_DIR=$CEPH_BUILD_DIR
+
+source ${MGR_INSIGHTS_VIRTUALENV}/bin/activate
+
+if [ "$WITH_PYTHON2" = "ON" ]; then
+ ENV_LIST+="py27,"
+fi
+# WITH_PYTHON3 might be set to "ON" or to the python3 RPM version number
+# prevailing on the system - e.g. "3", "36"
+if [[ "$WITH_PYTHON3" =~ (^3|^ON) ]]; then
+ ENV_LIST+="py3,"
+fi
+# use bash string manipulation to strip off any trailing comma
+ENV_LIST=${ENV_LIST%,}
+
+tox -c "${TOX_PATH}" -e "${ENV_LIST}" "$@"
+TOX_STATUS="$?"
+test "$TOX_STATUS" -ne "0" && dump_envvars
+exit $TOX_STATUS
diff --git a/src/pybind/mgr/insights/tests/__init__.py b/src/pybind/mgr/insights/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/insights/tests/__init__.py
diff --git a/src/pybind/mgr/insights/tests/test_health.py b/src/pybind/mgr/insights/tests/test_health.py
new file mode 100644
index 00000000..9b34786d
--- /dev/null
+++ b/src/pybind/mgr/insights/tests/test_health.py
@@ -0,0 +1,273 @@
+import unittest
+import mock
+from ..health import *
+
+class HealthChecksTest(unittest.TestCase):
+ def test_check_accum_empty(self):
+ # health checks accum initially empty reports empty
+ h = HealthCheckAccumulator()
+ self.assertEqual(h.checks(), {})
+
+ h = HealthCheckAccumulator({})
+ self.assertEqual(h.checks(), {})
+
+ def _get_init_checks(self):
+ return HealthCheckAccumulator({
+ "C0": {
+ "S0": {
+ "summary": ["s0", "s1"],
+ "detail": ("d0", "d1")
+ }
+ }
+ })
+
+ def test_check_init(self):
+ # initialization with lists and tuples is OK
+ h = self._get_init_checks()
+ self.assertEqual(h.checks(), {
+ "C0": {
+ "S0": {
+ "summary": set(["s0", "s1"]),
+ "detail": set(["d0", "d1"])
+ }
+ }
+ })
+
+ def _get_merged_checks(self):
+ h = self._get_init_checks()
+ h.merge(HealthCheckAccumulator({
+ "C0": {
+ "S0": {
+ "summary": ["s0", "s1", "s2"],
+ "detail": ("d2",)
+ },
+ "S1": {
+ "summary": ["s0", "s1", "s2"],
+ "detail": ()
+ }
+ },
+ "C1": {
+ "S0": {
+ "summary": [],
+ "detail": ("d0", "d1", "d2")
+ }
+ }
+ }))
+ return h
+
+ def test_check_merge(self):
+ # merging combines and de-duplicates
+ h = self._get_merged_checks()
+ self.assertEqual(h.checks(), {
+ "C0": {
+ "S0": {
+ "summary": set(["s0", "s1", "s2"]),
+ "detail": set(["d0", "d1", "d2"])
+ },
+ "S1": {
+ "summary": set(["s0", "s1", "s2"]),
+ "detail": set([])
+ }
+ },
+ "C1": {
+ "S0": {
+ "summary": set([]),
+ "detail": set(["d0", "d1", "d2"])
+ }
+ }
+ })
+
+ def test_check_add_no_change(self):
+ # returns false when nothing changes
+ h = self._get_merged_checks()
+
+ self.assertFalse(h.add({}))
+
+ self.assertFalse(h.add({
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s0" },
+ "detail": []
+ }
+ }))
+
+ self.assertFalse(h.add({
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s1" },
+ "detail": [{ "message": "d1" }]
+ }
+ }))
+
+ self.assertFalse(h.add({
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s0" },
+ "detail": [{ "message": "d1" }, { "message": "d2" }]
+ }
+ }))
+
+ def test_check_add_changed(self):
+ # new checks report change
+ h = self._get_merged_checks()
+
+ self.assertTrue(h.add({
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s3" },
+ "detail": []
+ }
+ }))
+
+ self.assertTrue(h.add({
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s1" },
+ "detail": [{ "message": "d4" }]
+ }
+ }))
+
+ self.assertTrue(h.add({
+ "C0": {
+ "severity": "S2",
+ "summary": { "message": "s0" },
+ "detail": [{ "message": "d0" }]
+ }
+ }))
+
+ self.assertTrue(h.add({
+ "C2": {
+ "severity": "S0",
+ "summary": { "message": "s0" },
+ "detail": [{ "message": "d0" }, { "message": "d1" }]
+ }
+ }))
+
+ self.assertEqual(h.checks(), {
+ "C0": {
+ "S0": {
+ "summary": set(["s0", "s1", "s2", "s3"]),
+ "detail": set(["d0", "d1", "d2", "d4"])
+ },
+ "S1": {
+ "summary": set(["s0", "s1", "s2"]),
+ "detail": set([])
+ },
+ "S2": {
+ "summary": set(["s0"]),
+ "detail": set(["d0"])
+ }
+ },
+ "C1": {
+ "S0": {
+ "summary": set([]),
+ "detail": set(["d0", "d1", "d2"])
+ }
+ },
+ "C2": {
+ "S0": {
+ "summary": set(["s0"]),
+ "detail": set(["d0", "d1"])
+ }
+ }
+ })
+
+class HealthHistoryTest(unittest.TestCase):
+ def _now(self):
+ # return some time truncated at 30 minutes past the hour. this lets us
+ # fiddle with time offsets without worrying about accidentally landing
+ # on exactly the top of the hour which is the edge of a time slot for
+ # tracking health history.
+ dt = datetime.datetime.utcnow()
+ return datetime.datetime(
+ year = dt.year,
+ month = dt.month,
+ day = dt.day,
+ hour = dt.hour,
+ minute = 30)
+
+ def test_empty_slot(self):
+ now = self._now()
+
+ HealthHistorySlot._now = mock.Mock(return_value=now)
+ h = HealthHistorySlot()
+
+ # reports no historical checks
+ self.assertEqual(h.health(), { "checks": {} })
+
+ # an empty slot doesn't need to be flushed
+ self.assertFalse(h.need_flush())
+
+ def test_expires(self):
+ now = self._now()
+
+ HealthHistorySlot._now = mock.Mock(return_value=now)
+ h = HealthHistorySlot()
+ self.assertFalse(h.expired())
+
+ # an hour from now it would be expired
+ future = now + datetime.timedelta(hours = 1)
+ HealthHistorySlot._now = mock.Mock(return_value=future)
+ self.assertTrue(h.expired())
+
+ def test_need_flush(self):
+ now = self._now()
+
+ HealthHistorySlot._now = mock.Mock(return_value=now)
+ h = HealthHistorySlot()
+ self.assertFalse(h.need_flush())
+
+ self.assertTrue(h.add(dict(checks = {
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s0" },
+ "detail": [{ "message": "d0" }]
+ }
+ })))
+ # no flush needed, yet...
+ self.assertFalse(h.need_flush())
+
+ # after persist period time elapses, a flush is needed
+ future = now + PERSIST_PERIOD
+ HealthHistorySlot._now = mock.Mock(return_value=future)
+ self.assertTrue(h.need_flush())
+
+ # mark flush resets
+ h.mark_flushed()
+ self.assertFalse(h.need_flush())
+
+ def test_need_flush_edge(self):
+ # test needs flush is true because it has expired, not because it has
+ # been dirty for the persistence period
+ dt = datetime.datetime.utcnow()
+ now = datetime.datetime(
+ year = dt.year,
+ month = dt.month,
+ day = dt.day,
+ hour = dt.hour,
+ minute = 59,
+ second = 59)
+ HealthHistorySlot._now = mock.Mock(return_value=now)
+ h = HealthHistorySlot()
+ self.assertFalse(h.expired())
+ self.assertFalse(h.need_flush())
+
+ # now it is dirty, but it doesn't need a flush
+ self.assertTrue(h.add(dict(checks = {
+ "C0": {
+ "severity": "S0",
+ "summary": { "message": "s0" },
+ "detail": [{ "message": "d0" }]
+ }
+ })))
+ self.assertFalse(h.expired())
+ self.assertFalse(h.need_flush())
+
+ # advance time past the hour so it expires, but not past the persistence
+ # period deadline for the last event that set the dirty bit
+ self.assertTrue(PERSIST_PERIOD.total_seconds() > 5)
+ future = now + datetime.timedelta(seconds = 5)
+ HealthHistorySlot._now = mock.Mock(return_value=future)
+
+ self.assertTrue(h.expired())
+ self.assertTrue(h.need_flush())
diff --git a/src/pybind/mgr/insights/tox.ini b/src/pybind/mgr/insights/tox.ini
new file mode 100644
index 00000000..c02393af
--- /dev/null
+++ b/src/pybind/mgr/insights/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = py27,py3
+skipsdist = true
+toxworkdir = {env:CEPH_BUILD_DIR}/insights
+minversion = 2.8.1
+
+[testenv]
+deps =
+ pytest
+ mock
+ six>=1.14.0
+setenv=
+ UNITTEST = true
+ py27: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.2
+ py3: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.3
+commands=
+ {envbindir}/py.test tests/
diff --git a/src/pybind/mgr/iostat/__init__.py b/src/pybind/mgr/iostat/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/iostat/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/iostat/module.py b/src/pybind/mgr/iostat/module.py
new file mode 100644
index 00000000..f5c3179d
--- /dev/null
+++ b/src/pybind/mgr/iostat/module.py
@@ -0,0 +1,73 @@
+
+from mgr_module import MgrModule
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "iostat",
+ "desc": "Get IO rates",
+ "perm": "r",
+ "poll": "true"
+ },
+ ]
+
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+
+ def self_test(self):
+ r = self.get('io_rate')
+ assert('pg_stats_delta' in r)
+ assert('stamp_delta' in r['pg_stats_delta'])
+ assert('stat_sum' in r['pg_stats_delta'])
+ assert('num_read_kb' in r['pg_stats_delta']['stat_sum'])
+ assert('num_write_kb' in r['pg_stats_delta']['stat_sum'])
+ assert('num_write' in r['pg_stats_delta']['stat_sum'])
+ assert('num_read' in r['pg_stats_delta']['stat_sum'])
+
+ def handle_command(self, inbuf, command):
+ rd = 0
+ wr = 0
+ total = 0
+ rd_ops = 0
+ wr_ops = 0
+ total_ops = 0
+ ret = ''
+
+ if command['prefix'] == 'iostat':
+ r = self.get('io_rate')
+
+ stamp_delta = float(r['pg_stats_delta']['stamp_delta'])
+ if (stamp_delta > 0):
+ rd = int(r['pg_stats_delta']['stat_sum']['num_read_kb']) / stamp_delta
+ wr = int(r['pg_stats_delta']['stat_sum']['num_write_kb']) / stamp_delta
+ # The values are in kB, but to_pretty_iec() requires them to be in bytes
+ rd = int(rd) << 10
+ wr = int(wr) << 10
+ total = rd + wr
+
+ rd_ops = int(r['pg_stats_delta']['stat_sum']['num_read']) / stamp_delta
+ wr_ops = int(r['pg_stats_delta']['stat_sum']['num_write']) / stamp_delta
+ total_ops = rd_ops + wr_ops
+
+ if 'width' in command:
+ width = command['width']
+ else:
+ width = 80
+
+ if command.get('print_header', False):
+ elems = ['Read', 'Write', 'Total', 'Read IOPS', 'Write IOPS', 'Total IOPS']
+ ret += self.get_pretty_header(elems, width)
+
+ elems = [
+ self.to_pretty_iec(rd) + 'B/s',
+ self.to_pretty_iec(wr) + 'B/s',
+ self.to_pretty_iec(total) + 'B/s',
+ int(rd_ops),
+ int(wr_ops),
+ int(total_ops)
+ ]
+ ret += self.get_pretty_row(elems, width)
+
+ return 0, '', ret
diff --git a/src/pybind/mgr/k8sevents/README.md b/src/pybind/mgr/k8sevents/README.md
new file mode 100644
index 00000000..7398096e
--- /dev/null
+++ b/src/pybind/mgr/k8sevents/README.md
@@ -0,0 +1,81 @@
+# Testing
+
+## To test the k8sevents module
+enable the module with `ceph mgr module enable k8sevents`
+check that it's working `ceph k8sevents status`, you should see something like this;
+```
+[root@ceph-mgr ~]# ceph k8sevents status
+Kubernetes
+- Hostname : https://localhost:30443
+- Namespace: ceph
+Tracker Health
+- EventProcessor : OK
+- CephConfigWatcher : OK
+- NamespaceWatcher : OK
+Tracked Events
+- namespace : 5
+- ceph events: 0
+
+```
+Now run some commands to generate healthchecks and admin level events;
+- ```ceph osd set noout```
+- ```ceph osd unset noout```
+- ```ceph osd pool create mypool 4 4 replicated```
+- ```ceph osd pool delete mypool mypool --yes-i-really-really-mean-it```
+
+In addition to tracking audit, healthchecks and configuration changes if you have the environment up for >1 hr you should also see and event that shows the clusters health and configuration overview.
+
+As well as status, you can use k8sevents to see event activity in the target kubernetes namespace
+```
+[root@rhcs4-3 kube]# ceph k8sevents ls
+Last Seen (UTC) Type Count Message Event Object Name
+2019/09/20 04:33:00 Normal 1 Pool 'mypool' has been removed from the cluster mgr.ConfigurationChangeql2hj
+2019/09/20 04:32:55 Normal 1 Client 'client.admin' issued: ceph osd pool delete mgr.audit.osd_pool_delete_
+2019/09/20 04:13:23 Normal 2 Client 'mds.rhcs4-2' issued: ceph osd blacklist mgr.audit.osd_blacklist_
+2019/09/20 04:08:28 Normal 1 Ceph log -> event tracking started mgr.k8sevents-moduleq74k7
+Total : 4
+```
+or, focus on the ceph specific events(audit & healthcheck) that are being tracked by the k8sevents module.
+```
+[root@rhcs4-3 kube]# ceph k8sevents ceph
+Last Seen (UTC) Type Count Message Event Object Name
+2019/09/20 04:32:55 Normal 1 Client 'client.admin' issued: ceph osd pool delete mgr.audit.osd_pool_delete_
+2019/09/20 04:13:23 Normal 2 Client 'mds.rhcs4-2' issued: ceph osd blacklist mgr.audit.osd_blacklist_
+Total : 2
+```
+
+## Sending events from a standalone Ceph cluster to remote Kubernetes cluster
+To test interaction from a standalone ceph cluster to a kubernetes environment, you need to make changes on the kubernetes cluster **and** on one of the mgr hosts.
+### kubernetes (minikube)
+We need some basic RBAC in place to define a serviceaccount(and token) that we can use to push events into kubernetes. The `rbac_sample.yaml` file provides a quick means to create the required resources. Create them with `kubectl create -f rbac_sample.yaml`
+
+Once the resources are defined inside kubernetes, we need a couple of things copied over to the Ceph mgr's filesystem.
+### ceph admin host
+We need to run some commands against the cluster, so you'll needs access to a ceph admin host. If you don't have a dedicated admin host, you can use a mon or mgr machine. We'll need the root ca.crt of the kubernetes API, and the token associated with the service account we're using to access the kubernetes API.
+
+1. Download/fetch the root ca.crt for the kubernetes cluster (on minikube this can be found at ~/minikube/ca.crt)
+2. Copy the ca.crt to your ceph admin host
+3. Extract the token from the service account we're going to use
+```
+kubectl -n ceph get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='ceph-mgr')].data.token}"|base64 -d > mytoken
+```
+4. Copy the token to your ceph admin host
+5. On the ceph admin host, enable the module with `ceph mgr module enable k8sevents`
+6. Set up the configuration
+```
+ceph k8sevents set-access cacrt -i <path to ca.crt file>
+ceph k8sevents set-access token -i <path to mytoken>
+ceph k8sevents set-config server https://<kubernetes api host>:<api_port>
+ceph k8sevents set-config namespace ceph
+```
+7. Restart the module with `ceph mgr module disable k8sevents && ceph mgr module enable k8sevents`
+8. Check state with the `ceph k8sevents status` command
+9. Remove the ca.crt and mytoken files from your admin host
+
+To remove the configuration keys used for external kubernetes access, run the following command
+```
+ceph k8sevents clear-config
+```
+
+## Networking
+You can use the above approach with a minikube based target from a standalone ceph cluster, but you'll need to have a tunnel/routing defined from the mgr host(s) to the minikube machine to make the kubernetes API accessible to the mgr/k8sevents module. This can just be a simple ssh tunnel.
diff --git a/src/pybind/mgr/k8sevents/__init__.py b/src/pybind/mgr/k8sevents/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/k8sevents/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/k8sevents/module.py b/src/pybind/mgr/k8sevents/module.py
new file mode 100644
index 00000000..e6568269
--- /dev/null
+++ b/src/pybind/mgr/k8sevents/module.py
@@ -0,0 +1,1460 @@
+# Integrate with the kubernetes events API.
+# This module sends events to Kubernetes, and also captures/tracks all events
+# in the rook-ceph namespace so kubernetes activity like pod restarts,
+# imagepulls etc can be seen from within the ceph cluster itself.
+#
+# To interact with the events API, the mgr service to access needs to be
+# granted additional permissions
+# e.g. kubectl -n rook-ceph edit clusterrole rook-ceph-mgr-cluster-rules
+#
+# These are the changes needed;
+# - apiGroups:
+# - ""
+# resources:
+# - events
+# verbs:
+# - create
+# - patch
+# - list
+# - get
+# - watch
+
+
+import os
+import re
+import sys
+import time
+import json
+import yaml
+import errno
+import socket
+import base64
+import logging
+import tempfile
+import threading
+
+try:
+ # python 3
+ from urllib.parse import urlparse
+except ImportError:
+ # python 2 fallback
+ from urlparse import urlparse
+
+from datetime import tzinfo, datetime, timedelta
+
+from urllib3.exceptions import MaxRetryError,ProtocolError
+from collections import OrderedDict
+
+import rados
+from mgr_module import MgrModule
+from mgr_util import verify_cacrt, ServerConfigException
+
+try:
+ import queue
+except ImportError:
+ # python 2.7.5
+ import Queue as queue
+finally:
+ # python 2.7.15 or python3
+ event_queue = queue.Queue()
+
+try:
+ from kubernetes import client, config, watch
+ from kubernetes.client.rest import ApiException
+except ImportError:
+ kubernetes_imported = False
+ client = None
+ config = None
+ watch = None
+else:
+ kubernetes_imported = True
+
+ # The watch.Watch.stream method can provide event objects that have involved_object = None
+ # which causes an exception in the generator. A workaround is discussed for a similar issue
+ # in https://github.com/kubernetes-client/python/issues/376 which has been used here
+ # pylint: disable=no-member
+ from kubernetes.client.models.v1_event import V1Event
+ def local_involved_object(self, involved_object):
+ if involved_object is None:
+ involved_object = client.V1ObjectReference(api_version="1")
+ self._involved_object = involved_object
+ V1Event.involved_object = V1Event.involved_object.setter(local_involved_object)
+
+log = logging.getLogger(__name__)
+
+# use a simple local class to represent UTC
+# datetime pkg modules vary between python2 and 3 and pytz is not available on older
+# ceph container images, so taking a pragmatic approach!
+class UTC(tzinfo):
+ def utcoffset(self, dt):
+ return timedelta(0)
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def dst(self, dt):
+ return timedelta(0)
+
+
+def text_suffix(num):
+ """Define a text suffix based on a value i.e. turn host into hosts"""
+ return '' if num == 1 else 's'
+
+
+def create_temp_file(fname, content, suffix=".tmp"):
+ """Create a temp file
+
+ Attempt to create an temporary file containing the given content
+
+ Returns:
+ str .. full path to the temporary file
+
+ Raises:
+ OSError: problems creating the file
+
+ """
+
+ if content is not None:
+ file_name = os.path.join(tempfile.gettempdir(), fname + suffix)
+
+ try:
+ with open(file_name, "w") as f:
+ f.write(content)
+ except OSError as e:
+ raise OSError("Unable to create temporary file : {}".format(str(e)))
+
+ return file_name
+
+
+class HealthCheck(object):
+ """Transform a healthcheck msg into it's component parts"""
+
+ def __init__(self, msg, msg_level):
+
+ # msg looks like
+ #
+ # Health check failed: Reduced data availability: 100 pgs inactive (PG_AVAILABILITY)
+ # Health check cleared: OSDMAP_FLAGS (was: nodown flag(s) set)
+ # Health check failed: nodown flag(s) set (OSDMAP_FLAGS)
+ #
+ self.msg = None
+ self.name = None
+ self.text = None
+ self.valid = False
+
+ if msg.lower().startswith('health check'):
+
+ self.valid = True
+ self.msg = msg
+ msg_tokens = self.msg.split()
+
+ if msg_level == 'INF':
+ self.text = ' '.join(msg_tokens[3:])
+ self.name = msg_tokens[3] # health check name e.g. OSDMAP_FLAGS
+ else: # WRN or ERR
+ self.text = ' '.join(msg_tokens[3:-1])
+ self.name = msg_tokens[-1][1:-1]
+
+
+class LogEntry(object):
+ """Generic 'log' object"""
+
+ reason_map = {
+ "audit": "Audit",
+ "cluster": "HealthCheck",
+ "config": "ClusterChange",
+ "heartbeat":"Heartbeat",
+ "startup": "Started"
+ }
+
+ def __init__(self, source, msg, msg_type, level, tstamp=None):
+
+ self.source = source
+ self.msg = msg
+ self.msg_type = msg_type
+ self.level = level
+ self.tstamp = tstamp
+ self.healthcheck = None
+
+ if 'health check ' in self.msg.lower():
+ self.healthcheck = HealthCheck(self.msg, self.level)
+
+
+ def __str__(self):
+ return "source={}, msg_type={}, msg={}, level={}, tstamp={}".format(self.source,
+ self.msg_type,
+ self.msg,
+ self.level,
+ self.tstamp)
+
+ @property
+ def cmd(self):
+ """Look at the msg string and extract the command content"""
+
+ # msg looks like 'from=\'client.205306 \' entity=\'client.admin\' cmd=\'[{"prefix": "osd set", "key": "nodown"}]\': finished'
+ if self.msg_type != 'audit':
+ return None
+ else:
+ _m=self.msg[:-10].replace("\'","").split("cmd=")
+ _s='"cmd":{}'.format(_m[1])
+ cmds_list = json.loads('{' + _s + '}')['cmd']
+
+ # TODO. Assuming only one command was issued for now
+ _c = cmds_list[0]
+ return "{} {}".format(_c['prefix'], _c.get('key', ''))
+
+ @property
+ def event_type(self):
+ return 'Normal' if self.level == 'INF' else 'Warning'
+
+ @property
+ def event_reason(self):
+ return self.reason_map[self.msg_type]
+
+ @property
+ def event_name(self):
+ if self.msg_type == 'heartbeat':
+ return 'mgr.Heartbeat'
+ elif self.healthcheck:
+ return 'mgr.health.{}'.format(self.healthcheck.name)
+ elif self.msg_type == 'audit':
+ return 'mgr.audit.{}'.format(self.cmd).replace(' ', '_')
+ elif self.msg_type == 'config':
+ return 'mgr.ConfigurationChange'
+ elif self.msg_type == 'startup':
+ return "mgr.k8sevents-module"
+ else:
+ return None
+
+ @property
+ def event_entity(self):
+ if self.msg_type == 'audit':
+ return self.msg.replace("\'","").split('entity=')[1].split(' ')[0]
+ else:
+ return None
+
+ @property
+ def event_msg(self):
+ if self.msg_type == 'audit':
+ return "Client '{}' issued: ceph {}".format(self.event_entity, self.cmd)
+
+ elif self.healthcheck:
+ return self.healthcheck.text
+ else:
+ return self.msg
+
+
+class BaseThread(threading.Thread):
+ health = 'OK'
+ reported = False
+ daemon = True
+
+
+def clean_event(event):
+ """ clean an event record """
+ if not event.first_timestamp:
+ log.error("first_timestamp is empty")
+ if event.metadata.creation_timestamp:
+ log.error("setting first_timestamp to the creation timestamp")
+ event.first_timestamp = event.metadata.creation_timestamp
+ else:
+ log.error("defaulting event first timestamp to current datetime")
+ event.first_timestamp = datetime.datetime.now()
+
+ if not event.last_timestamp:
+ log.error("setting event last timestamp to {}".format(event.first_timestamp))
+ event.last_timestamp = event.first_timestamp
+
+ if not event.count:
+ event.count = 1
+
+ return event
+
+
+class NamespaceWatcher(BaseThread):
+ """Watch events in a given namespace
+
+ Using the watch package we can listen to event traffic in the namespace to
+ get an idea of what kubernetes related events surround the ceph cluster. The
+ thing to bear in mind is that events have a TTL enforced by the kube-apiserver
+ so this stream will only really show activity inside this retention window.
+ """
+
+ def __init__(self, api_client_config, namespace=None):
+ super(NamespaceWatcher, self).__init__()
+
+ if api_client_config:
+ self.api = client.CoreV1Api(api_client_config)
+ else:
+ self.api = client.CoreV1Api()
+
+ self.namespace = namespace
+
+ self.events = OrderedDict()
+ self.lock = threading.Lock()
+ self.active = None
+ self.resource_version = None
+
+ def fetch(self):
+ # clear the cache on every call to fetch
+ self.events.clear()
+ try:
+ resp = self.api.list_namespaced_event(self.namespace)
+ # TODO - Perhaps test for auth problem to be more specific in the except clause?
+ except:
+ self.active = False
+ self.health = "Unable to access events API (list_namespaced_event call failed)"
+ log.warning(self.health)
+ else:
+ self.active = True
+ self.resource_version = resp.metadata.resource_version
+
+ for item in resp.items:
+ self.events[item.metadata.name] = clean_event(item)
+ log.info('Added {} events'.format(len(resp.items)))
+
+ def run(self):
+ self.fetch()
+ func = getattr(self.api, "list_namespaced_event")
+
+ if self.active:
+ log.info("Namespace event watcher started")
+
+
+ while True:
+
+ try:
+ w = watch.Watch()
+ # execute generator to continually watch resource for changes
+ for item in w.stream(func, namespace=self.namespace, resource_version=self.resource_version, watch=True):
+ obj = item['object']
+
+ with self.lock:
+
+ if item['type'] in ['ADDED', 'MODIFIED']:
+ self.events[obj.metadata.name] = clean_event(obj)
+
+ elif item['type'] == 'DELETED':
+ del self.events[obj.metadata.name]
+
+ # TODO test the exception for auth problem (403?)
+
+ # Attribute error is generated when urllib3 on the system is old and doesn't have a
+ # read_chunked method
+ except AttributeError as e:
+ self.health = ("Error: Unable to 'watch' events API in namespace '{}' - "
+ "urllib3 too old? ({})".format(self.namespace, e))
+ self.active = False
+ log.warning(self.health)
+ break
+
+ except ApiException as e:
+ # refresh the resource_version & watcher
+ log.warning("API exception caught in watcher ({})".format(e))
+ log.warning("Restarting namespace watcher")
+ self.fetch()
+
+ except ProtocolError as e:
+ log.warning("Namespace watcher hit protocolerror ({}) - restarting".format(e))
+ self.fetch()
+
+ except Exception:
+ self.health = "{} Exception at {}".format(
+ sys.exc_info()[0].__name__,
+ datetime.strftime(datetime.now(),"%Y/%m/%d %H:%M:%S")
+ )
+ log.exception(self.health)
+ self.active = False
+ break
+
+ log.warning("Namespace event watcher stopped")
+
+
+class KubernetesEvent(object):
+
+ def __init__(self, log_entry, unique_name=True, api_client_config=None, namespace=None):
+
+ if api_client_config:
+ self.api = client.CoreV1Api(api_client_config)
+ else:
+ self.api = client.CoreV1Api()
+
+ self.namespace = namespace
+
+ self.event_name = log_entry.event_name
+ self.message = log_entry.event_msg
+ self.event_type = log_entry.event_type
+ self.event_reason = log_entry.event_reason
+ self.unique_name = unique_name
+
+ self.host = os.environ.get('NODE_NAME', os.environ.get('HOSTNAME', 'UNKNOWN'))
+
+ self.api_status = 200
+ self.count = 1
+ self.first_timestamp = None
+ self.last_timestamp = None
+
+ @property
+ def type(self):
+ """provide a type property matching a V1Event object"""
+ return self.event_type
+
+ @property
+ def event_body(self):
+ if self.unique_name:
+ obj_meta = client.V1ObjectMeta(name="{}".format(self.event_name))
+ else:
+ obj_meta = client.V1ObjectMeta(generate_name="{}".format(self.event_name))
+
+ # field_path is needed to prevent problems in the namespacewatcher when
+ # deleted event are received
+ obj_ref = client.V1ObjectReference(kind="CephCluster",
+ field_path='spec.containers{mgr}',
+ name=self.event_name,
+ namespace=self.namespace)
+
+ event_source = client.V1EventSource(component="ceph-mgr",
+ host=self.host)
+ return client.V1Event(
+ involved_object=obj_ref,
+ metadata=obj_meta,
+ message=self.message,
+ count=self.count,
+ type=self.event_type,
+ reason=self.event_reason,
+ source=event_source,
+ first_timestamp=self.first_timestamp,
+ last_timestamp=self.last_timestamp
+ )
+
+ def write(self):
+
+ now=datetime.now(UTC())
+
+ self.first_timestamp = now
+ self.last_timestamp = now
+
+ try:
+ self.api.create_namespaced_event(self.namespace, self.event_body)
+ except (OSError, ProtocolError):
+ # unable to reach to the API server
+ log.error("Unable to reach API server")
+ self.api_status = 400
+ except MaxRetryError:
+ # k8s config has not be defined properly
+ log.error("multiple attempts to connect to the API have failed")
+ self.api_status = 403 # Forbidden
+ except ApiException as e:
+ log.debug("event.write status:{}".format(e.status))
+ self.api_status = e.status
+ if e.status == 409:
+ log.debug("attempting event update for an existing event")
+ # 409 means the event is there already, so read it back (v1Event object returned)
+ # this could happen if the event has been created, and then the k8sevent module
+ # disabled and reenabled - i.e. the internal event tracking no longer matches k8s
+ response = self.api.read_namespaced_event(self.event_name, self.namespace)
+ #
+ # response looks like
+ #
+ # {'action': None,
+ # 'api_version': 'v1',
+ # 'count': 1,
+ # 'event_time': None,
+ # 'first_timestamp': datetime.datetime(2019, 7, 18, 5, 24, 59, tzinfo=tzlocal()),
+ # 'involved_object': {'api_version': None,
+ # 'field_path': None,
+ # 'kind': 'CephCluster',
+ # 'name': 'ceph-mgr.k8sevent-module',
+ # 'namespace': 'rook-ceph',
+ # 'resource_version': None,
+ # 'uid': None},
+ # 'kind': 'Event',
+ # 'last_timestamp': datetime.datetime(2019, 7, 18, 5, 24, 59, tzinfo=tzlocal()),
+ # 'message': 'Ceph log -> event tracking started',
+ # 'metadata': {'annotations': None,
+ # 'cluster_name': None,
+ # 'creation_timestamp': datetime.datetime(2019, 7, 18, 5, 24, 59, tzinfo=tzlocal()),
+ # 'deletion_grace_period_seconds': None,
+ # 'deletion_timestamp': None,
+ # 'finalizers': None,
+ # 'generate_name': 'ceph-mgr.k8sevent-module',
+ # 'generation': None,
+ # 'initializers': None,
+ # 'labels': None,
+ # 'name': 'ceph-mgr.k8sevent-module5z7kq',
+ # 'namespace': 'rook-ceph',
+ # 'owner_references': None,
+ # 'resource_version': '1195832',
+ # 'self_link': '/api/v1/namespaces/rook-ceph/events/ceph-mgr.k8sevent-module5z7kq',
+ # 'uid': '62fde5f1-a91c-11e9-9c80-6cde63a9debf'},
+ # 'reason': 'Started',
+ # 'related': None,
+ # 'reporting_component': '',
+ # 'reporting_instance': '',
+ # 'series': None,
+ # 'source': {'component': 'ceph-mgr', 'host': 'minikube'},
+ # 'type': 'Normal'}
+
+ # conflict event already exists
+ # read it
+ # update : count and last_timestamp and msg
+
+ self.count = response.count + 1
+ self.first_timestamp = response.first_timestamp
+ try:
+ self.api.patch_namespaced_event(self.event_name, self.namespace, self.event_body)
+ except ApiException as e:
+ log.error("event.patch failed for {} with status code:{}".format(self.event_name, e.status))
+ self.api_status = e.status
+ else:
+ log.debug("event {} patched".format(self.event_name))
+ self.api_status = 200
+
+ else:
+ log.debug("event {} created successfully".format(self.event_name))
+ self.api_status = 200
+
+ @property
+ def api_success(self):
+ return self.api_status == 200
+
+ def update(self, log_entry):
+ self.message = log_entry.event_msg
+ self.event_type = log_entry.event_type
+ self.last_timestamp = datetime.now(UTC())
+ self.count += 1
+ log.debug("performing event update for {}".format(self.event_name))
+
+ try:
+ self.api.patch_namespaced_event(self.event_name, self.namespace, self.event_body)
+ except ApiException as e:
+ log.error("event patch call failed: {}".format(e.status))
+ if e.status == 404:
+ # tried to patch, but hit a 404. The event's TTL must have been reached, and
+ # pruned by the kube-apiserver
+ log.debug("event not found, so attempting to create it")
+ try:
+ self.api.create_namespaced_event(self.namespace, self.event_body)
+ except ApiException as e:
+ log.error("unable to create the event: {}".format(e.status))
+ self.api_status = e.status
+ else:
+ log.debug("event {} created successfully".format(self.event_name))
+ self.api_status = 200
+ else:
+ log.debug("event {} updated".format(self.event_name))
+ self.api_status = 200
+
+
+class EventProcessor(BaseThread):
+ """Handle a global queue used to track events we want to send/update to kubernetes"""
+
+ can_run = True
+
+ def __init__(self, config_watcher, event_retention_days, api_client_config, namespace):
+ super(EventProcessor, self).__init__()
+
+ self.events = dict()
+ self.config_watcher = config_watcher
+ self.event_retention_days = event_retention_days
+ self.api_client_config = api_client_config
+ self.namespace = namespace
+
+ def startup(self):
+ """Log an event to show we're active"""
+
+ event = KubernetesEvent(
+ LogEntry(
+ source='self',
+ msg='Ceph log -> event tracking started',
+ msg_type='startup',
+ level='INF',
+ tstamp=None
+ ),
+ unique_name=False,
+ api_client_config=self.api_client_config,
+ namespace=self.namespace
+ )
+
+ event.write()
+ return event.api_success
+
+ @property
+ def ok(self):
+ return self.startup()
+
+ def prune_events(self):
+ log.debug("prune_events - looking for old events to remove from cache")
+ oldest = datetime.now(UTC()) - timedelta(days=self.event_retention_days)
+ local_events = dict(self.events)
+
+ for event_name in sorted(local_events,
+ key = lambda name: local_events[name].last_timestamp):
+ event = local_events[event_name]
+ if event.last_timestamp >= oldest:
+ break
+ else:
+ # drop this event
+ log.debug("prune_events - removing old event : {}".format(event_name))
+ del self.events[event_name]
+
+ def process(self, log_object):
+
+ log.debug("log entry being processed : {}".format(str(log_object)))
+
+ event_out = False
+ unique_name = True
+
+ if log_object.msg_type == 'audit':
+ # audit traffic : operator commands
+ if log_object.msg.endswith('finished'):
+ log.debug("K8sevents received command finished msg")
+ event_out = True
+ else:
+ # NO OP - ignoring 'dispatch' log records
+ return
+
+ elif log_object.msg_type == 'cluster':
+ # cluster messages : health checks
+ if log_object.event_name:
+ event_out = True
+
+ elif log_object.msg_type == 'config':
+ # configuration checker messages
+ event_out = True
+ unique_name = False
+
+ elif log_object.msg_type == 'heartbeat':
+ # hourly health message summary from Ceph
+ event_out = True
+ unique_name = False
+ log_object.msg = str(self.config_watcher)
+
+ else:
+ log.warning("K8sevents received unknown msg_type - {}".format(log_object.msg_type))
+
+ if event_out:
+ log.debug("k8sevents sending event to kubernetes")
+ # we don't cache non-unique events like heartbeats or config changes
+ if not unique_name or log_object.event_name not in self.events.keys():
+ event = KubernetesEvent(log_entry=log_object,
+ unique_name=unique_name,
+ api_client_config=self.api_client_config,
+ namespace=self.namespace)
+ event.write()
+ log.debug("event(unique={}) creation ended : {}".format(unique_name, event.api_status))
+ if event.api_success and unique_name:
+ self.events[log_object.event_name] = event
+ else:
+ event = self.events[log_object.event_name]
+ event.update(log_object)
+ log.debug("event update ended : {}".format(event.api_status))
+
+ self.prune_events()
+
+ else:
+ log.debug("K8sevents ignored message : {}".format(log_object.msg))
+
+ def run(self):
+ log.info("Ceph event processing thread started, "
+ "event retention set to {} days".format(self.event_retention_days))
+
+ while True:
+
+ try:
+ log_object = event_queue.get(block=False)
+ except queue.Empty:
+ pass
+ else:
+ try:
+ self.process(log_object)
+ except Exception:
+ self.health = "{} Exception at {}".format(
+ sys.exc_info()[0].__name__,
+ datetime.strftime(datetime.now(),"%Y/%m/%d %H:%M:%S")
+ )
+ log.exception(self.health)
+ break
+
+ if not self.can_run:
+ break
+
+ time.sleep(0.5)
+
+ log.warning("Ceph event processing thread stopped")
+
+
+class ListDiff(object):
+ def __init__(self, before, after):
+ self.before = set(before)
+ self.after = set(after)
+
+ @property
+ def removed(self):
+ return list(self.before - self.after)
+
+ @property
+ def added(self):
+ return list(self.after - self.before)
+
+ @property
+ def is_equal(self):
+ return self.before == self.after
+
+
+class CephConfigWatcher(BaseThread):
+ """Detect configuration changes within the cluster and generate human readable events"""
+
+ def __init__(self, mgr):
+ super(CephConfigWatcher, self).__init__()
+ self.mgr = mgr
+ self.server_map = dict()
+ self.osd_map = dict()
+ self.pool_map = dict()
+ self.service_map = dict()
+
+ self.config_check_secs = mgr.config_check_secs
+
+ @property
+ def raw_capacity(self):
+ # Note. if the osd's are not online the capacity field will be 0
+ return sum([self.osd_map[osd]['capacity'] for osd in self.osd_map])
+
+ @property
+ def num_servers(self):
+ return len(self.server_map.keys())
+
+ @property
+ def num_osds(self):
+ return len(self.osd_map.keys())
+
+ @property
+ def num_pools(self):
+ return len(self.pool_map.keys())
+
+ def __str__(self):
+ s = ''
+
+ s += "{} : {:>3} host{}, {} pool{}, {} OSDs. Raw Capacity {}B".format(
+ json.loads(self.mgr.get('health')['json'])['status'],
+ self.num_servers,
+ text_suffix(self.num_servers),
+ self.num_pools,
+ text_suffix(self.num_pools),
+ self.num_osds,
+ MgrModule.to_pretty_iec(self.raw_capacity))
+ return s
+
+ def fetch_servers(self):
+ """Return a server summary, and service summary"""
+ servers = self.mgr.list_servers()
+ server_map = dict() # host -> services
+ service_map = dict() # service -> host
+ for server_info in servers:
+ services = dict()
+ for svc in server_info['services']:
+ if svc.get('type') in services.keys():
+ services[svc.get('type')].append(svc.get('id'))
+ else:
+ services[svc.get('type')] = list([svc.get('id')])
+ # maintain the service xref map service -> host and version
+ service_map[(svc.get('type'), str(svc.get('id')))] = server_info.get('hostname', '')
+ server_map[server_info.get('hostname')] = services
+
+ return server_map, service_map
+
+ def fetch_pools(self):
+ interesting = ["type", "size", "min_size"]
+ # pools = [{'pool': 1, 'pool_name': 'replicapool', 'flags': 1, 'flags_names': 'hashpspool',
+ # 'type': 1, 'size': 3, 'min_size': 1, 'crush_rule': 1, 'object_hash': 2, 'pg_autoscale_mode': 'warn',
+ # 'pg_num': 100, 'pg_placement_num': 100, 'pg_placement_num_target': 100, 'pg_num_target': 100, 'pg_num_pending': 100,
+ # 'last_pg_merge_meta': {'ready_epoch': 0, 'last_epoch_started': 0, 'last_epoch_clean': 0, 'source_pgid': '0.0',
+ # 'source_version': "0'0", 'target_version': "0'0"}, 'auid': 0, 'snap_mode': 'selfmanaged', 'snap_seq': 0, 'snap_epoch': 0,
+ # 'pool_snaps': [], 'quota_max_bytes': 0, 'quota_max_objects': 0, 'tiers': [], 'tier_of': -1, 'read_tier': -1,
+ # 'write_tier': -1, 'cache_mode': 'none', 'target_max_bytes': 0, 'target_max_objects': 0,
+ # 'cache_target_dirty_ratio_micro': 400000, 'cache_target_dirty_high_ratio_micro': 600000,
+ # 'cache_target_full_ratio_micro': 800000, 'cache_min_flush_age': 0, 'cache_min_evict_age': 0,
+ # 'erasure_code_profile': '', 'hit_set_params': {'type': 'none'}, 'hit_set_period': 0, 'hit_set_count': 0,
+ # 'use_gmt_hitset': True, 'min_read_recency_for_promote': 0, 'min_write_recency_for_promote': 0,
+ # 'hit_set_grade_decay_rate': 0, 'hit_set_search_last_n': 0, 'grade_table': [], 'stripe_width': 0,
+ # 'expected_num_objects': 0, 'fast_read': False, 'options': {}, 'application_metadata': {'rbd': {}},
+ # 'create_time': '2019-08-02 02:23:01.618519', 'last_change': '19', 'last_force_op_resend': '0',
+ # 'last_force_op_resend_prenautilus': '0', 'last_force_op_resend_preluminous': '0', 'removed_snaps': '[]'}]
+ pools = self.mgr.get('osd_map')['pools']
+ pool_map = dict()
+ for pool in pools:
+ pool_map[pool.get('pool_name')] = {k:pool.get(k) for k in interesting}
+ return pool_map
+
+
+ def fetch_osd_map(self, service_map):
+ """Create an osd map"""
+ stats = self.mgr.get('osd_stats')
+
+ osd_map = dict()
+
+ devices = self.mgr.get('osd_map_crush')['devices']
+ for dev in devices:
+ osd_id = str(dev['id'])
+ osd_map[osd_id] = dict(
+ deviceclass=dev.get('class'),
+ capacity=0,
+ hostname=service_map['osd', osd_id]
+ )
+
+ for osd_stat in stats['osd_stats']:
+ osd_id = str(osd_stat.get('osd'))
+ osd_map[osd_id]['capacity'] = osd_stat['statfs']['total']
+
+ return osd_map
+
+ def push_events(self, changes):
+ """Add config change to the global queue to generate an event in kubernetes"""
+ log.debug("{} events will be generated")
+ for change in changes:
+ event_queue.put(change)
+
+ def _generate_config_logentry(self, msg):
+ return LogEntry(
+ source="config",
+ msg_type="config",
+ msg=msg,
+ level='INF',
+ tstamp=None
+ )
+
+ def _check_hosts(self, server_map):
+ log.debug("K8sevents checking host membership")
+ changes = list()
+ servers = ListDiff(self.server_map.keys(), server_map.keys())
+ if servers.is_equal:
+ # no hosts have been added or removed
+ pass
+ else:
+ # host changes detected, find out what
+ host_msg = "Host '{}' has been {} the cluster"
+ for new_server in servers.added:
+ changes.append(self._generate_config_logentry(
+ msg=host_msg.format(new_server, 'added to'))
+ )
+
+ for removed_server in servers.removed:
+ changes.append(self._generate_config_logentry(
+ msg=host_msg.format(removed_server, 'removed from'))
+ )
+
+ return changes
+
+ def _check_osds(self,server_map, osd_map):
+ log.debug("K8sevents checking OSD configuration")
+ changes = list()
+ before_osds = list()
+ for svr in self.server_map:
+ before_osds.extend(self.server_map[svr].get('osd',[]))
+
+ after_osds = list()
+ for svr in server_map:
+ after_osds.extend(server_map[svr].get('osd',[]))
+
+ if set(before_osds) == set(after_osds):
+ # no change in osd id's
+ pass
+ else:
+ # osd changes detected
+ osd_msg = "Ceph OSD '{}' ({} @ {}B) has been {} host {}"
+
+ osds = ListDiff(before_osds, after_osds)
+ for new_osd in osds.added:
+ changes.append(self._generate_config_logentry(
+ msg=osd_msg.format(
+ new_osd,
+ osd_map[new_osd]['deviceclass'],
+ MgrModule.to_pretty_iec(osd_map[new_osd]['capacity']),
+ 'added to',
+ osd_map[new_osd]['hostname']))
+ )
+
+ for removed_osd in osds.removed:
+ changes.append(self._generate_config_logentry(
+ msg=osd_msg.format(
+ removed_osd,
+ osd_map[removed_osd]['deviceclass'],
+ MgrModule.to_pretty_iec(osd_map[removed_osd]['capacity']),
+ 'removed from',
+ osd_map[removed_osd]['hostname']))
+ )
+
+ return changes
+
+ def _check_pools(self, pool_map):
+ changes = list()
+ log.debug("K8sevents checking pool configurations")
+ if self.pool_map.keys() == pool_map.keys():
+ # no pools added/removed
+ pass
+ else:
+ # Pool changes
+ pools = ListDiff(self.pool_map.keys(), pool_map.keys())
+ pool_msg = "Pool '{}' has been {} the cluster"
+ for new_pool in pools.added:
+ changes.append(self._generate_config_logentry(
+ msg=pool_msg.format(new_pool, 'added to'))
+ )
+
+ for removed_pool in pools.removed:
+ changes.append(self._generate_config_logentry(
+ msg=pool_msg.format(removed_pool, 'removed from'))
+ )
+
+ # check pool configuration changes
+ for pool_name in pool_map:
+ if not self.pool_map.get(pool_name, dict()):
+ # pool didn't exist before so just skip the checks
+ continue
+
+ if pool_map[pool_name] == self.pool_map[pool_name]:
+ # no changes - dicts match in key and value
+ continue
+ else:
+ # determine the change and add it to the change list
+ size_diff = pool_map[pool_name]['size'] - self.pool_map[pool_name]['size']
+ if size_diff != 0:
+ if size_diff < 0:
+ msg = "Data protection level of pool '{}' reduced to {} copies".format(pool_name,
+ pool_map[pool_name]['size'])
+ level = 'WRN'
+ else:
+ msg = "Data protection level of pool '{}' increased to {} copies".format(pool_name,
+ pool_map[pool_name]['size'])
+ level = 'INF'
+
+ changes.append(LogEntry(source="config",
+ msg_type="config",
+ msg=msg,
+ level=level,
+ tstamp=None)
+ )
+
+ if pool_map[pool_name]['min_size'] != self.pool_map[pool_name]['min_size']:
+ changes.append(LogEntry(source="config",
+ msg_type="config",
+ msg="Minimum acceptable number of replicas in pool '{}' has changed".format(pool_name),
+ level='WRN',
+ tstamp=None)
+ )
+
+ return changes
+
+ def get_changes(self, server_map, osd_map, pool_map):
+ """Detect changes in maps between current observation and the last"""
+
+ changes = list()
+
+ changes.extend(self._check_hosts(server_map))
+ changes.extend(self._check_osds(server_map, osd_map))
+ changes.extend(self._check_pools(pool_map))
+
+ # FUTURE
+ # Could generate an event if a ceph daemon has moved hosts
+ # (assumes the ceph metadata host information is valid though!)
+
+ return changes
+
+ def run(self):
+ log.info("Ceph configuration watcher started, interval set to {}s".format(self.config_check_secs))
+
+ self.server_map, self.service_map = self.fetch_servers()
+ self.pool_map = self.fetch_pools()
+
+ self.osd_map = self.fetch_osd_map(self.service_map)
+
+ while True:
+
+ try:
+ start_time = time.time()
+ server_map, service_map = self.fetch_servers()
+ pool_map = self.fetch_pools()
+ osd_map = self.fetch_osd_map(service_map)
+
+ changes = self.get_changes(server_map, osd_map, pool_map)
+ if changes:
+ self.push_events(changes)
+
+ self.osd_map = osd_map
+ self.pool_map = pool_map
+ self.server_map = server_map
+ self.service_map = service_map
+
+ checks_duration = int(time.time() - start_time)
+
+ # check that the time it took to run the checks fits within the
+ # interval, and if not extend the interval and emit a log message
+ # to show that the runtime for the checks exceeded the desired
+ # interval
+ if checks_duration > self.config_check_secs:
+ new_interval = self.config_check_secs * 2
+ log.warning("K8sevents check interval warning. "
+ "Current checks took {}s, interval was {}s. "
+ "Increasing interval to {}s".format(int(checks_duration),
+ self.config_check_secs,
+ new_interval))
+ self.config_check_secs = new_interval
+
+ time.sleep(self.config_check_secs)
+
+ except Exception:
+ self.health = "{} Exception at {}".format(
+ sys.exc_info()[0].__name__,
+ datetime.strftime(datetime.now(),"%Y/%m/%d %H:%M:%S")
+ )
+ log.exception(self.health)
+ break
+
+ log.warning("Ceph configuration watcher stopped")
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "k8sevents status",
+ "desc": "Show the status of the data gathering threads",
+ "perm": "r"
+ },
+ {
+ "cmd": "k8sevents ls",
+ "desc": "List all current Kuberenetes events from the Ceph namespace",
+ "perm": "r"
+ },
+ {
+ "cmd": "k8sevents ceph",
+ "desc": "List Ceph events tracked & sent to the kubernetes cluster",
+ "perm": "r"
+ },
+ {
+ "cmd": "k8sevents set-access name=key,type=CephString",
+ "desc": "Set kubernetes access credentials. <key> must be cacrt or token and use -i <filename> syntax.\ne.g. ceph k8sevents set-access cacrt -i /root/ca.crt",
+ "perm": "rw"
+ },
+ {
+ "cmd": "k8sevents set-config name=key,type=CephString name=value,type=CephString",
+ "desc": "Set kubernetes config paramters. <key> must be server or namespace.\ne.g. ceph k8sevents set-config server https://localhost:30433",
+ "perm": "rw"
+ },
+ {
+ "cmd": "k8sevents clear-config",
+ "desc": "Clear external kubernetes configuration settings",
+ "perm": "rw"
+ },
+ ]
+ MODULE_OPTIONS = [
+ {'name': 'config_check_secs',
+ 'type': 'int',
+ 'default': 10,
+ 'min': 10,
+ 'desc': "interval (secs) to check for cluster configuration changes"},
+ {'name': 'ceph_event_retention_days',
+ 'type': 'int',
+ 'default': 7,
+ 'desc': "Days to hold ceph event information within local cache"}
+ ]
+
+ def __init__(self, *args, **kwargs):
+ self.run = True
+ self.kubernetes_control = 'POD_NAME' in os.environ
+ self.event_processor = None
+ self.config_watcher = None
+ self.ns_watcher = None
+ self.trackers = list()
+ self.error_msg = None
+ self._api_client_config = None
+ self._namespace = None
+
+ # Declare the module options we accept
+ self.config_check_secs = None
+ self.ceph_event_retention_days = None
+
+ self.k8s_config = dict(
+ cacrt = None,
+ token = None,
+ server = None,
+ namespace = None
+ )
+
+ super(Module, self).__init__(*args, **kwargs)
+
+ def k8s_ready(self):
+ """Validate the k8s_config dict
+
+ Returns:
+ - bool .... indicating whether the config is ready to use
+ - string .. variables that need to be defined before the module will function
+
+ """
+ missing = list()
+ ready = True
+ for k in self.k8s_config:
+ if not self.k8s_config[k]:
+ missing.append(k)
+ ready = False
+ return ready, missing
+
+ def config_notify(self):
+ """Apply runtime module options, and defaults from the modules KV store"""
+ self.log.debug("applying runtime module option settings")
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+
+ if not self.kubernetes_control:
+ # Populate the config
+ self.log.debug("loading config from KV store")
+ for k in self.k8s_config:
+ self.k8s_config[k] = self.get_store(k, default=None)
+
+ def fetch_events(self, limit=None):
+ """Interface to expose current events to another mgr module"""
+ # FUTURE: Implement this to provide k8s events to the dashboard?
+ raise NotImplementedError
+
+ def process_clog(self, log_message):
+ """Add log message to the event queue
+
+ :param log_message: dict from the cluster log (audit/cluster channels)
+ """
+ required_fields = ['channel', 'message', 'priority', 'stamp']
+ _message_attrs = log_message.keys()
+ if all(_field in _message_attrs for _field in required_fields):
+ self.log.debug("clog entry received - adding to the queue")
+ if log_message.get('message').startswith('overall HEALTH'):
+ m_type = 'heartbeat'
+ else:
+ m_type = log_message.get('channel')
+
+ event_queue.put(
+ LogEntry(
+ source='log',
+ msg_type=m_type,
+ msg=log_message.get('message'),
+ level=log_message.get('priority')[1:-1],
+ tstamp=log_message.get('stamp')
+ )
+ )
+
+ else:
+ self.log.warning("Unexpected clog message format received - skipped: {}".format(log_message))
+
+ def notify(self, notify_type, notify_id):
+ """
+ Called by the ceph-mgr service to notify the Python plugin
+ that new state is available.
+
+ :param notify_type: string indicating what kind of notification,
+ such as osd_map, mon_map, fs_map, mon_status,
+ health, pg_summary, command, service_map
+ :param notify_id: string (may be empty) that optionally specifies
+ which entity is being notified about. With
+ "command" notifications this is set to the tag
+ ``from send_command``.
+ """
+
+ # only interested in cluster log (clog) messages for now
+ if notify_type == 'clog':
+ self.log.debug("received a clog entry from mgr.notify")
+ if isinstance(notify_id, dict):
+ # create a log object to process
+ self.process_clog(notify_id)
+ else:
+ self.log.warning("Expected a 'dict' log record format, received {}".format(type(notify_type)))
+
+ def _show_events(self, events):
+
+ max_msg_length = max([len(events[k].message) for k in events])
+ fmt = "{:<20} {:<8} {:>5} {:<" + str(max_msg_length) + "} {}\n"
+ s = fmt.format("Last Seen (UTC)", "Type", "Count", "Message", "Event Object Name")
+
+ for event_name in sorted(events,
+ key = lambda name: events[name].last_timestamp,
+ reverse=True):
+
+ event = events[event_name]
+
+ s += fmt.format(
+ datetime.strftime(event.last_timestamp,"%Y/%m/%d %H:%M:%S"),
+ str(event.type),
+ str(event.count),
+ str(event.message),
+ str(event_name)
+ )
+ s += "Total : {:>3}\n".format(len(events))
+ return s
+
+ def show_events(self, events):
+ """Show events we're holding from the ceph namespace - most recent 1st"""
+
+ if len(events):
+ return 0, "", self._show_events(events)
+ else:
+ return 0, "", "No events emitted yet, local cache is empty"
+
+ def show_status(self):
+ s = "Kubernetes\n"
+ s += "- Hostname : {}\n".format(self.k8s_config['server'])
+ s += "- Namespace : {}\n".format(self._namespace)
+ s += "Tracker Health\n"
+ for t in self.trackers:
+ s += "- {:<20} : {}\n".format(t.__class__.__name__, t.health)
+ s += "Tracked Events\n"
+ s += "- namespace : {:>3}\n".format(len(self.ns_watcher.events))
+ s += "- ceph events : {:>3}\n".format(len(self.event_processor.events))
+ return 0, "", s
+
+ def _valid_server(self, server):
+ # must be a valid server url format
+ server = server.strip()
+
+ res = urlparse(server)
+ port = res.netloc.split(":")[-1]
+
+ if res.scheme != 'https':
+ return False, "Server URL must use https"
+
+ elif not res.hostname:
+ return False, "Invalid server URL format"
+
+ elif res.hostname:
+ try:
+ socket.gethostbyname(res.hostname)
+ except socket.gaierror:
+ return False, "Unresolvable server URL"
+
+ if not port.isdigit():
+ return False, "Server URL must end in a port number"
+
+ return True, ""
+
+ def _valid_cacrt(self, cacrt_data):
+ """use mgr_util.verify_cacrt to validate the CA file"""
+
+ cacrt_fname = create_temp_file("ca_file", cacrt_data)
+
+ try:
+ verify_cacrt(cacrt_fname)
+ except ServerConfigException as e:
+ return False, "Invalid CA certificate: {}".format(str(e))
+ else:
+ return True, ""
+
+ def _valid_token(self, token_data):
+ """basic checks on the token"""
+ if not token_data:
+ return False, "Token file is empty"
+
+ pattern = re.compile(r"[a-zA-Z0-9\-\.\_]+$")
+ if not pattern.match(token_data):
+ return False, "Token contains invalid characters"
+
+ return True, ""
+
+ def _valid_namespace(self, namespace):
+ # Simple check - name must be a string <= 253 in length, alphanumeric with '.' and '-' symbols
+
+ if len(namespace) > 253:
+ return False, "Name too long"
+ if namespace.isdigit():
+ return False, "Invalid name - must be alphanumeric"
+
+ pattern = re.compile(r"^[a-z][a-z0-9\-\.]+$")
+ if not pattern.match(namespace):
+ return False, "Invalid characters in the name"
+
+ return True, ""
+
+ def _config_set(self, key, val):
+ """Attempt to validate the content, then save to KV store"""
+
+ val = val.rstrip() # remove any trailing whitespace/newline
+
+ try:
+ checker = getattr(self, "_valid_" + key)
+ except AttributeError:
+ # no checker available, just let it pass
+ self.log.warning("Unable to validate '{}' parameter - checker not implemented".format(key))
+ valid = True
+ else:
+ valid, reason = checker(val)
+
+ if valid:
+ self.set_store(key, val)
+ self.log.info("Updated config KV Store item: " + key)
+ return 0, "", "Config updated for parameter '{}'".format(key)
+ else:
+ return -22, "", "Invalid value for '{}' :{}".format(key, reason)
+
+ def clear_config_settings(self):
+ for k in self.k8s_config:
+ self.set_store(k, None)
+ return 0,"","{} configuration keys removed".format(len(self.k8s_config.keys()))
+
+ def handle_command(self, inbuf, cmd):
+
+ access_options = ['cacrt', 'token']
+ config_options = ['server', 'namespace']
+
+ if cmd['prefix'] == 'k8sevents clear-config':
+ return self.clear_config_settings()
+
+ if cmd['prefix'] == 'k8sevents set-access':
+ if cmd['key'] not in access_options:
+ return -errno.EINVAL, "", "Unknown access option. Must be one of; {}".format(','.join(access_options))
+
+ if inbuf:
+ return self._config_set(cmd['key'], inbuf)
+ else:
+ return -errno.EINVAL, "", "Command must specify -i <filename>"
+
+ if cmd['prefix'] == 'k8sevents set-config':
+
+ if cmd['key'] not in config_options:
+ return -errno.EINVAL, "", "Unknown config option. Must be one of; {}".format(','.join(config_options))
+
+ return self._config_set(cmd['key'], cmd['value'])
+
+ # At this point the command is trying to interact with k8sevents, so intercept if the configuration is
+ # not ready
+ if self.error_msg:
+ _msg = "k8sevents unavailable: " + self.error_msg
+ ready, _ = self.k8s_ready()
+ if not self.kubernetes_control and not ready:
+ _msg += "\nOnce all variables have been defined, you must restart the k8sevents module for the changes to take effect"
+ return -errno.ENODATA, "", _msg
+
+ if cmd["prefix"] == "k8sevents status":
+ return self.show_status()
+
+ elif cmd["prefix"] == "k8sevents ls":
+ return self.show_events(self.ns_watcher.events)
+
+ elif cmd["prefix"] == "k8sevents ceph":
+ return self.show_events(self.event_processor.events)
+
+ else:
+ raise NotImplementedError(cmd["prefix"])
+
+ @staticmethod
+ def can_run():
+ """Determine whether the pre-reqs for the module are in place"""
+
+ if not kubernetes_imported:
+ return False, "kubernetes python client is not available"
+ return True, ""
+
+ def load_kubernetes_config(self):
+ """Load configuration for remote kubernetes API using KV store values
+
+ Attempt to create an API client configuration from settings stored in
+ KV store.
+
+ Returns:
+ client.ApiClient: kubernetes API client object
+
+ Raises:
+ OSError: unable to create the cacrt file
+ """
+
+ # the kubernetes setting Configuration.ssl_ca_cert is a path, so we have to create a
+ # temporary file containing the cert for the client to load from
+ try:
+ ca_crt_file = create_temp_file('cacrt', self.k8s_config['cacrt'])
+ except OSError as e:
+ self.log.error("Unable to create file to hold cacrt: {}".format(str(e)))
+ raise OSError(str(e))
+ else:
+ self.log.debug("CA certificate from KV store, written to {}".format(ca_crt_file))
+
+ configuration = client.Configuration()
+ configuration.host = self.k8s_config['server']
+ configuration.ssl_ca_cert = ca_crt_file
+ configuration.api_key = { "authorization": "Bearer " + self.k8s_config['token'] }
+ api_client = client.ApiClient(configuration)
+ self.log.info("API client created for remote kubernetes access using cacrt and token from KV store")
+
+ return api_client
+
+ def serve(self):
+ # apply options set by CLI to this module
+ self.config_notify()
+
+ if not kubernetes_imported:
+ self.error_msg = "Unable to start : python kubernetes package is missing"
+ else:
+ if self.kubernetes_control:
+ # running under rook-ceph
+ config.load_incluster_config()
+ self.k8s_config['server'] = "https://{}:{}".format(os.environ.get('KUBERNETES_SERVICE_HOST', 'UNKNOWN'),
+ os.environ.get('KUBERNETES_SERVICE_PORT_HTTPS', 'UNKNOWN'))
+ self._api_client_config = None
+ self._namespace = os.environ.get("POD_NAMESPACE", "rook-ceph")
+ else:
+ # running outside of rook-ceph, so we need additional settings to tell us
+ # how to connect to the kubernetes cluster
+ ready, errors = self.k8s_ready()
+ if not ready:
+ self.error_msg = "Required settings missing. Use ceph k8sevents set-access | set-config to define {}".format(",".join(errors))
+ else:
+ try:
+ self._api_client_config = self.load_kubernetes_config()
+ except OSError as e:
+ self.error_msg = str(e)
+ else:
+ self._namespace = self.k8s_config['namespace']
+ self.log.info("k8sevents configuration loaded from KV store")
+
+ if self.error_msg:
+ self.log.error(self.error_msg)
+ return
+
+ # All checks have passed
+ self.config_watcher = CephConfigWatcher(self)
+
+ self.event_processor = EventProcessor(self.config_watcher,
+ self.ceph_event_retention_days,
+ self._api_client_config,
+ self._namespace)
+
+ self.ns_watcher = NamespaceWatcher(api_client_config=self._api_client_config,
+ namespace=self._namespace)
+
+ if self.event_processor.ok:
+ log.info("Ceph Log processor thread starting")
+ self.event_processor.start() # start log consumer thread
+ log.info("Ceph config watcher thread starting")
+ self.config_watcher.start()
+ log.info("Rook-ceph namespace events watcher starting")
+ self.ns_watcher.start()
+
+ self.trackers.extend([self.event_processor, self.config_watcher, self.ns_watcher])
+
+ while True:
+ # stay alive
+ time.sleep(1)
+
+ trackers = self.trackers
+ for t in trackers:
+ if not t.is_alive() and not t.reported:
+ log.error("K8sevents tracker thread '{}' stopped: {}".format(t.__class__.__name__, t.health))
+ t.reported = True
+
+ else:
+ self.error_msg = "Unable to access kubernetes API. Is it accessible? Are RBAC rules for our token valid?"
+ log.warning(self.error_msg)
+ log.warning("k8sevents module exiting")
+ self.run = False
+
+ def shutdown(self):
+ self.run = False
+ log.info("Shutting down k8sevents module")
+ self.event_processor.can_run = False
+
+ if self._rados:
+ self._rados.shutdown()
diff --git a/src/pybind/mgr/k8sevents/rbac_sample.yaml b/src/pybind/mgr/k8sevents/rbac_sample.yaml
new file mode 100644
index 00000000..56392202
--- /dev/null
+++ b/src/pybind/mgr/k8sevents/rbac_sample.yaml
@@ -0,0 +1,45 @@
+---
+# Create a namespace to receive our test events
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: ceph
+---
+# Define the access rules to open the events API to k8sevents
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: ceph-mgr-events-rules
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - list
+ - watch
+ - patch
+ - get
+---
+# Define a service account to associate with our event stream
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: ceph-mgr
+ namespace: ceph
+---
+# Allow the ceph-mgr service account access to the events api
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: ceph-mgr
+ namespace: ceph
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: ceph-mgr-events-rules
+subjects:
+- kind: ServiceAccount
+ name: ceph-mgr
+ namespace: ceph
diff --git a/src/pybind/mgr/localpool/__init__.py b/src/pybind/mgr/localpool/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/localpool/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/localpool/module.py b/src/pybind/mgr/localpool/module.py
new file mode 100644
index 00000000..23ffeaa1
--- /dev/null
+++ b/src/pybind/mgr/localpool/module.py
@@ -0,0 +1,136 @@
+from mgr_module import MgrModule, CommandResult
+import json
+import threading
+
+class Module(MgrModule):
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'subtree',
+ 'type': 'str',
+ 'default': 'rack',
+ 'desc': 'CRUSH level for which to create a local pool',
+ 'runtime': True,
+ },
+ {
+ 'name': 'failure_domain',
+ 'type': 'str',
+ 'default': 'host',
+ 'desc': 'failure domain for any created local pool',
+ 'runtime': True,
+ },
+ {
+ 'name': 'min_size',
+ 'type': 'int',
+ 'desc': 'default min_size for any created local pool',
+ 'runtime': True,
+ },
+ {
+ 'name': 'num_rep',
+ 'type': 'int',
+ 'default': 3,
+ 'desc': 'default replica count for any created local pool',
+ 'runtime': True,
+ },
+ {
+ 'name': 'pg_num',
+ 'type': 'int',
+ 'default': 128,
+ 'desc': 'default pg_num for any created local pool',
+ 'runtime': True,
+ },
+ {
+ 'name': 'prefix',
+ 'type': 'str',
+ 'default': '',
+ 'desc': 'name prefix for any created local pool',
+ 'runtime': True,
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.serve_event = threading.Event()
+
+ def notify(self, notify_type, notify_id):
+ if notify_type == 'osd_map':
+ self.handle_osd_map()
+
+ def handle_osd_map(self):
+ """
+ Check pools on each OSDMap change
+ """
+ subtree_type = self.get_module_option('subtree')
+ failure_domain = self.get_module_option('failure_domain')
+ pg_num = self.get_module_option('pg_num')
+ num_rep = self.get_module_option('num_rep')
+ min_size = self.get_module_option('min_size')
+ prefix = self.get_module_option('prefix') or 'by-' + subtree_type + '-'
+
+ osdmap = self.get("osd_map")
+ lpools = []
+ for pool in osdmap['pools']:
+ if pool['pool_name'].find(prefix) == 0:
+ lpools.append(pool['pool_name'])
+
+ self.log.debug('localized pools = %s', lpools)
+ subtrees = []
+ tree = self.get('osd_map_tree')
+ for node in tree['nodes']:
+ if node['type'] == subtree_type:
+ subtrees.append(node['name'])
+ pool_name = prefix + node['name']
+ if pool_name not in lpools:
+ self.log.info('Creating localized pool %s', pool_name)
+ #
+ result = CommandResult("")
+ self.send_command(result, "mon", "", json.dumps({
+ "prefix": "osd crush rule create-replicated",
+ "format": "json",
+ "name": pool_name,
+ "root": node['name'],
+ "type": failure_domain,
+ }), "")
+ r, outb, outs = result.wait()
+
+ result = CommandResult("")
+ self.send_command(result, "mon", "", json.dumps({
+ "prefix": "osd pool create",
+ "format": "json",
+ "pool": pool_name,
+ 'rule': pool_name,
+ "pool_type": 'replicated',
+ 'pg_num': pg_num,
+ }), "")
+ r, outb, outs = result.wait()
+
+ result = CommandResult("")
+ self.send_command(result, "mon", "", json.dumps({
+ "prefix": "osd pool set",
+ "format": "json",
+ "pool": pool_name,
+ 'var': 'size',
+ "val": str(num_rep),
+ }), "")
+ r, outb, outs = result.wait()
+
+ if min_size:
+ result = CommandResult("")
+ self.send_command(result, "mon", "", json.dumps({
+ "prefix": "osd pool set",
+ "format": "json",
+ "pool": pool_name,
+ 'var': 'min_size',
+ "val": str(min_size),
+ }), "")
+ r, outb, outs = result.wait()
+
+ # TODO remove pools for hosts that don't exist?
+
+ def serve(self):
+ self.handle_osd_map()
+ self.serve_event.wait()
+ self.serve_event.clear()
+
+ def shutdown(self):
+ self.serve_event.set()
diff --git a/src/pybind/mgr/mgr_module.py b/src/pybind/mgr/mgr_module.py
new file mode 100644
index 00000000..79cbc950
--- /dev/null
+++ b/src/pybind/mgr/mgr_module.py
@@ -0,0 +1,1504 @@
+import ceph_module # noqa
+
+try:
+ from typing import Set, Tuple, Iterator, Any
+except ImportError:
+ # just for type checking
+ pass
+import errno
+import logging
+import json
+import six
+import threading
+from collections import defaultdict, namedtuple
+import rados
+import re
+import time
+
+ERROR_MSG_EMPTY_INPUT_FILE = 'Empty content: please add a password/secret to the file.'
+ERROR_MSG_NO_INPUT_FILE = 'Please specify the file containing the password/secret with "-i" option.'
+# Full list of strings in "osd_types.cc:pg_state_string()"
+PG_STATES = [
+ "active",
+ "clean",
+ "down",
+ "recovery_unfound",
+ "backfill_unfound",
+ "scrubbing",
+ "degraded",
+ "inconsistent",
+ "peering",
+ "repair",
+ "recovering",
+ "forced_recovery",
+ "backfill_wait",
+ "incomplete",
+ "stale",
+ "remapped",
+ "deep",
+ "backfilling",
+ "forced_backfill",
+ "backfill_toofull",
+ "recovery_wait",
+ "recovery_toofull",
+ "undersized",
+ "activating",
+ "peered",
+ "snaptrim",
+ "snaptrim_wait",
+ "snaptrim_error",
+ "creating",
+ "unknown",
+ "premerge",
+ "failed_repair",
+]
+
+
+class CPlusPlusHandler(logging.Handler):
+ def __init__(self, module_inst):
+ super(CPlusPlusHandler, self).__init__()
+ self._module = module_inst
+
+ def emit(self, record):
+ if record.levelno <= logging.DEBUG:
+ ceph_level = 20
+ elif record.levelno <= logging.INFO:
+ ceph_level = 4
+ elif record.levelno <= logging.WARNING:
+ ceph_level = 1
+ else:
+ ceph_level = 0
+
+ self._module._ceph_log(ceph_level, self.format(record))
+
+
+def configure_logger(module_inst, module_name):
+ """
+ Create and configure the logger with the specified module.
+
+ A handler will be added to the root logger which will redirect
+ the messages from all loggers (incl. 3rd party libraries) to the
+ Ceph log.
+
+ :param module_inst: The module instance.
+ :type module_inst: instance
+ :param module_name: The module name.
+ :type module_name: str
+ :return: Return the logger with the specified name.
+ """
+ logger = logging.getLogger(module_name)
+ # Don't filter any logs at the python level, leave it to C++.
+ # FIXME: We should learn the log level from C++ land, and then
+ # avoid calling the C++ level log when we know a message
+ # is of an insufficient level to be ultimately output.
+ logger.setLevel(logging.DEBUG) # Don't use NOTSET
+
+ root_logger = logging.getLogger()
+ # Add handler to the root logger, thus this module and all
+ # 3rd party libraries will log their messages to the Ceph log.
+ root_logger.addHandler(CPlusPlusHandler(module_inst))
+ # Set the log level to ``ERROR`` to ensure that we only get
+ # those message from 3rd party libraries (only effective if
+ # they use the default log level ``NOTSET``).
+ # Check https://docs.python.org/3/library/logging.html#logging.Logger.setLevel
+ # for more information about how the effective log level is
+ # determined.
+ root_logger.setLevel(logging.ERROR)
+
+ return logger
+
+
+def unconfigure_logger(module_name=None):
+ """
+ :param module_name: The module name. Defaults to ``None``.
+ :type module_name: str or None
+ """
+ logger = logging.getLogger(module_name)
+ rm_handlers = [
+ h for h in logger.handlers if isinstance(h, CPlusPlusHandler)]
+ for h in rm_handlers:
+ logger.removeHandler(h)
+
+
+class CommandResult(object):
+ """
+ Use with MgrModule.send_command
+ """
+
+ def __init__(self, tag=None):
+ self.ev = threading.Event()
+ self.outs = ""
+ self.outb = ""
+ self.r = 0
+
+ # This is just a convenience for notifications from
+ # C++ land, to avoid passing addresses around in messages.
+ self.tag = tag if tag else ""
+
+ def complete(self, r, outb, outs):
+ self.r = r
+ self.outb = outb
+ self.outs = outs
+ self.ev.set()
+
+ def wait(self):
+ self.ev.wait()
+ return self.r, self.outb, self.outs
+
+
+class HandleCommandResult(namedtuple('HandleCommandResult', ['retval', 'stdout', 'stderr'])):
+ def __new__(cls, retval=0, stdout="", stderr=""):
+ """
+ Tuple containing the result of `handle_command()`
+
+ Only write to stderr if there is an error, or in extraordinary circumstances
+
+ Avoid having `ceph foo bar` commands say "did foo bar" on success unless there
+ is critical information to include there.
+
+ Everything programmatically consumable should be put on stdout
+
+ :param retval: return code. E.g. 0 or -errno.EINVAL
+ :type retval: int
+ :param stdout: data of this result.
+ :type stdout: str
+ :param stderr: Typically used for error messages.
+ :type stderr: str
+ """
+ return super(HandleCommandResult, cls).__new__(cls, retval, stdout, stderr)
+
+
+class MonCommandFailed(RuntimeError): pass
+
+
+class OSDMap(ceph_module.BasePyOSDMap):
+ def get_epoch(self):
+ return self._get_epoch()
+
+ def get_crush_version(self):
+ return self._get_crush_version()
+
+ def dump(self):
+ return self._dump()
+
+ def get_pools(self):
+ # FIXME: efficient implementation
+ d = self._dump()
+ return dict([(p['pool'], p) for p in d['pools']])
+
+ def get_pools_by_name(self):
+ # FIXME: efficient implementation
+ d = self._dump()
+ return dict([(p['pool_name'], p) for p in d['pools']])
+
+ def new_incremental(self):
+ return self._new_incremental()
+
+ def apply_incremental(self, inc):
+ return self._apply_incremental(inc)
+
+ def get_crush(self):
+ return self._get_crush()
+
+ def get_pools_by_take(self, take):
+ return self._get_pools_by_take(take).get('pools', [])
+
+ def calc_pg_upmaps(self, inc,
+ max_deviation=.01, max_iterations=10, pools=None):
+ if pools is None:
+ pools = []
+ return self._calc_pg_upmaps(
+ inc,
+ max_deviation, max_iterations, pools)
+
+ def map_pool_pgs_up(self, poolid):
+ return self._map_pool_pgs_up(poolid)
+
+ def pg_to_up_acting_osds(self, pool_id, ps):
+ return self._pg_to_up_acting_osds(pool_id, ps)
+
+ def pool_raw_used_rate(self, pool_id):
+ return self._pool_raw_used_rate(pool_id)
+
+ def get_ec_profile(self, name):
+ # FIXME: efficient implementation
+ d = self._dump()
+ return d['erasure_code_profiles'].get(name, None)
+
+
+class OSDMapIncremental(ceph_module.BasePyOSDMapIncremental):
+ def get_epoch(self):
+ return self._get_epoch()
+
+ def dump(self):
+ return self._dump()
+
+ def set_osd_reweights(self, weightmap):
+ """
+ weightmap is a dict, int to float. e.g. { 0: .9, 1: 1.0, 3: .997 }
+ """
+ return self._set_osd_reweights(weightmap)
+
+ def set_crush_compat_weight_set_weights(self, weightmap):
+ """
+ weightmap is a dict, int to float. devices only. e.g.,
+ { 0: 3.4, 1: 3.3, 2: 3.334 }
+ """
+ return self._set_crush_compat_weight_set_weights(weightmap)
+
+
+class CRUSHMap(ceph_module.BasePyCRUSH):
+ ITEM_NONE = 0x7fffffff
+ DEFAULT_CHOOSE_ARGS = '-1'
+
+ def dump(self):
+ return self._dump()
+
+ def get_item_weight(self, item):
+ return self._get_item_weight(item)
+
+ def get_item_name(self, item):
+ return self._get_item_name(item)
+
+ def find_takes(self):
+ return self._find_takes().get('takes', [])
+
+ def get_take_weight_osd_map(self, root):
+ uglymap = self._get_take_weight_osd_map(root)
+ return {int(k): v for k, v in six.iteritems(uglymap.get('weights', {}))}
+
+ @staticmethod
+ def have_default_choose_args(dump):
+ return CRUSHMap.DEFAULT_CHOOSE_ARGS in dump.get('choose_args', {})
+
+ @staticmethod
+ def get_default_choose_args(dump):
+ return dump.get('choose_args').get(CRUSHMap.DEFAULT_CHOOSE_ARGS, [])
+
+ def get_rule(self, rule_name):
+ # TODO efficient implementation
+ for rule in self.dump()['rules']:
+ if rule_name == rule['rule_name']:
+ return rule
+
+ return None
+
+ def get_rule_by_id(self, rule_id):
+ for rule in self.dump()['rules']:
+ if rule['rule_id'] == rule_id:
+ return rule
+
+ return None
+
+ def get_rule_root(self, rule_name):
+ rule = self.get_rule(rule_name)
+ if rule is None:
+ return None
+
+ try:
+ first_take = [s for s in rule['steps'] if s['op'] == 'take'][0]
+ except IndexError:
+ self.log.warn("CRUSH rule '{0}' has no 'take' step".format(
+ rule_name))
+ return None
+ else:
+ return first_take['item']
+
+ def get_osds_under(self, root_id):
+ # TODO don't abuse dump like this
+ d = self.dump()
+ buckets = dict([(b['id'], b) for b in d['buckets']])
+
+ osd_list = []
+
+ def accumulate(b):
+ for item in b['items']:
+ if item['id'] >= 0:
+ osd_list.append(item['id'])
+ else:
+ try:
+ accumulate(buckets[item['id']])
+ except KeyError:
+ pass
+
+ accumulate(buckets[root_id])
+
+ return osd_list
+
+ def device_class_counts(self):
+ result = defaultdict(int)
+ # TODO don't abuse dump like this
+ d = self.dump()
+ for device in d['devices']:
+ cls = device.get('class', None)
+ result[cls] += 1
+
+ return dict(result)
+
+
+class CLICommand(object):
+ COMMANDS = {}
+
+ def __init__(self, prefix, args="", desc="", perm="rw"):
+ self.prefix = prefix
+ self.args = args
+ self.args_dict = {}
+ self.desc = desc
+ self.perm = perm
+ self.func = None
+ self._parse_args()
+
+ def _parse_args(self):
+ if not self.args:
+ return
+ args = self.args.split(" ")
+ for arg in args:
+ arg_desc = arg.strip().split(",")
+ arg_d = {}
+ for kv in arg_desc:
+ k, v = kv.split("=")
+ if k != "name":
+ arg_d[k] = v
+ else:
+ self.args_dict[v] = arg_d
+
+ def __call__(self, func):
+ self.func = func
+ self.COMMANDS[self.prefix] = self
+ return self.func
+
+ def call(self, mgr, cmd_dict, inbuf):
+ kwargs = {}
+ for a, d in self.args_dict.items():
+ if 'req' in d and d['req'] == "false" and a not in cmd_dict:
+ continue
+ kwargs[a.replace("-", "_")] = cmd_dict[a]
+ if inbuf:
+ kwargs['inbuf'] = inbuf
+ return self.func(mgr, **kwargs)
+
+ @classmethod
+ def dump_cmd_list(cls):
+ return [{
+ 'cmd': '{} {}'.format(cmd.prefix, cmd.args),
+ 'desc': cmd.desc,
+ 'perm': cmd.perm
+ } for _, cmd in cls.COMMANDS.items()]
+
+
+def CLIReadCommand(prefix, args="", desc=""):
+ return CLICommand(prefix, args, desc, "r")
+
+
+def CLIWriteCommand(prefix, args="", desc=""):
+ return CLICommand(prefix, args, desc, "w")
+
+
+def CLICheckNonemptyFileInput(func):
+ def check(*args, **kwargs):
+ if not 'inbuf' in kwargs:
+ return -errno.EINVAL, '', ERROR_MSG_NO_INPUT_FILE
+ if isinstance(kwargs['inbuf'], str):
+ # Delete new line separator at EOF (it may have been added by a text editor).
+ kwargs['inbuf'] = kwargs['inbuf'].rstrip('\r\n').rstrip('\n')
+ if not kwargs['inbuf']:
+ return -errno.EINVAL, '', ERROR_MSG_EMPTY_INPUT_FILE
+ return func(*args, **kwargs)
+ return check
+
+
+def _get_localized_key(prefix, key):
+ return '{}/{}'.format(prefix, key)
+
+
+class Option(dict):
+ """
+ Helper class to declare options for MODULE_OPTIONS list.
+
+ Caveat: it uses argument names matching Python keywords (type, min, max),
+ so any further processing should happen in a separate method.
+
+ TODO: type validation.
+ """
+
+ def __init__(
+ self, name,
+ default=None,
+ type='str',
+ desc=None, longdesc=None,
+ min=None, max=None,
+ enum_allowed=None,
+ see_also=None,
+ tags=None,
+ runtime=False,
+ ):
+ super(Option, self).__init__(
+ (k, v) for k, v in vars().items()
+ if k != 'self' and v is not None)
+
+class Command(dict):
+ """
+ Helper class to declare options for COMMANDS list.
+
+ It also allows to specify prefix and args separately, as well as storing a
+ handler callable.
+
+ Usage:
+ >>> Command(prefix="example",
+ ... args="name=arg,type=CephInt",
+ ... perm='w',
+ ... desc="Blah")
+ {'poll': False, 'cmd': 'example name=arg,type=CephInt', 'perm': 'w', 'desc': 'Blah'}
+ """
+
+ def __init__(
+ self,
+ prefix,
+ args=None,
+ perm="rw",
+ desc=None,
+ poll=False,
+ handler=None
+ ):
+ super(Command, self).__init__(
+ cmd=prefix + (' ' + args if args else ''),
+ perm=perm,
+ desc=desc,
+ poll=poll)
+ self.prefix = prefix
+ self.args = args
+ self.handler = handler
+
+ def register(self, instance=False):
+ """
+ Register a CLICommand handler. It allows an instance to register bound
+ methods. In that case, the mgr instance is not passed, and it's expected
+ to be available in the class instance.
+ It also uses HandleCommandResult helper to return a wrapped a tuple of 3
+ items.
+ """
+ return CLICommand(
+ prefix=self.prefix,
+ args=self.args,
+ desc=self['desc'],
+ perm=self['perm']
+ )(
+ func=lambda mgr, *args, **kwargs: HandleCommandResult(*self.handler(
+ *((instance or mgr,) + args), **kwargs))
+ )
+
+
+class MgrStandbyModule(ceph_module.BaseMgrStandbyModule):
+ """
+ Standby modules only implement a serve and shutdown method, they
+ are not permitted to implement commands and they do not receive
+ any notifications.
+
+ They only have access to the mgrmap (for accessing service URI info
+ from their active peer), and to configuration settings (read only).
+ """
+
+ MODULE_OPTIONS = []
+ MODULE_OPTION_DEFAULTS = {}
+
+ def __init__(self, module_name, capsule):
+ super(MgrStandbyModule, self).__init__(capsule)
+ self.module_name = module_name
+ self._logger = configure_logger(self, module_name)
+ # see also MgrModule.__init__()
+ for o in self.MODULE_OPTIONS:
+ if 'default' in o:
+ if 'type' in o:
+ self.MODULE_OPTION_DEFAULTS[o['name']] = o['default']
+ else:
+ self.MODULE_OPTION_DEFAULTS[o['name']] = str(o['default'])
+
+ def __del__(self):
+ unconfigure_logger()
+
+ @property
+ def log(self):
+ return self._logger
+
+ def serve(self):
+ """
+ The serve method is mandatory for standby modules.
+ :return:
+ """
+ raise NotImplementedError()
+
+ def get_mgr_id(self):
+ return self._ceph_get_mgr_id()
+
+ def get_module_option(self, key, default=None):
+ """
+ Retrieve the value of a persistent configuration setting
+
+ :param str key:
+ :param default: the default value of the config if it is not found
+ :return: str
+ """
+ r = self._ceph_get_module_option(key)
+ if r is None:
+ return self.MODULE_OPTION_DEFAULTS.get(key, default)
+ else:
+ return r
+
+ def get_ceph_option(self, key):
+ return self._ceph_get_option(key)
+
+ def get_store(self, key):
+ """
+ Retrieve the value of a persistent KV store entry
+
+ :param key: String
+ :return: Byte string or None
+ """
+ return self._ceph_get_store(key)
+
+ def get_active_uri(self):
+ return self._ceph_get_active_uri()
+
+ def get_localized_module_option(self, key, default=None):
+ r = self._ceph_get_module_option(key, self.get_mgr_id())
+ if r is None:
+ return self.MODULE_OPTION_DEFAULTS.get(key, default)
+ else:
+ return r
+
+
+class MgrModule(ceph_module.BaseMgrModule):
+ COMMANDS = []
+ MODULE_OPTIONS = []
+ MODULE_OPTION_DEFAULTS = {}
+
+ # Priority definitions for perf counters
+ PRIO_CRITICAL = 10
+ PRIO_INTERESTING = 8
+ PRIO_USEFUL = 5
+ PRIO_UNINTERESTING = 2
+ PRIO_DEBUGONLY = 0
+
+ # counter value types
+ PERFCOUNTER_TIME = 1
+ PERFCOUNTER_U64 = 2
+
+ # counter types
+ PERFCOUNTER_LONGRUNAVG = 4
+ PERFCOUNTER_COUNTER = 8
+ PERFCOUNTER_HISTOGRAM = 0x10
+ PERFCOUNTER_TYPE_MASK = ~3
+
+ # units supported
+ BYTES = 0
+ NONE = 1
+
+ # Cluster log priorities
+ CLUSTER_LOG_PRIO_DEBUG = 0
+ CLUSTER_LOG_PRIO_INFO = 1
+ CLUSTER_LOG_PRIO_SEC = 2
+ CLUSTER_LOG_PRIO_WARN = 3
+ CLUSTER_LOG_PRIO_ERROR = 4
+
+ def __init__(self, module_name, py_modules_ptr, this_ptr):
+ self.module_name = module_name
+
+ # If we're taking over from a standby module, let's make sure
+ # its logger was unconfigured before we hook ours up
+ unconfigure_logger()
+ self._logger = configure_logger(self, module_name)
+
+ super(MgrModule, self).__init__(py_modules_ptr, this_ptr)
+
+ self._version = self._ceph_get_version()
+
+ self._perf_schema_cache = None
+
+ # Keep a librados instance for those that need it.
+ self._rados = None
+
+ for o in self.MODULE_OPTIONS:
+ if 'default' in o:
+ if 'type' in o:
+ # we'll assume the declared type matches the
+ # supplied default value's type.
+ self.MODULE_OPTION_DEFAULTS[o['name']] = o['default']
+ else:
+ # module not declaring it's type, so normalize the
+ # default value to be a string for consistent behavior
+ # with default and user-supplied option values.
+ self.MODULE_OPTION_DEFAULTS[o['name']] = str(o['default'])
+
+ def __del__(self):
+ unconfigure_logger()
+
+ @classmethod
+ def _register_commands(cls):
+ cls.COMMANDS.extend(CLICommand.dump_cmd_list())
+
+ @property
+ def log(self):
+ return self._logger
+
+ def cluster_log(self, channel, priority, message):
+ """
+ :param channel: The log channel. This can be 'cluster', 'audit', ...
+ :type channel: str
+ :param priority: The log message priority. This can be
+ CLUSTER_LOG_PRIO_DEBUG, CLUSTER_LOG_PRIO_INFO,
+ CLUSTER_LOG_PRIO_SEC, CLUSTER_LOG_PRIO_WARN or
+ CLUSTER_LOG_PRIO_ERROR.
+ :type priority: int
+ :param message: The message to log.
+ :type message: str
+ """
+ self._ceph_cluster_log(channel, priority, message)
+
+ @property
+ def version(self):
+ return self._version
+
+ @property
+ def release_name(self):
+ """
+ Get the release name of the Ceph version, e.g. 'nautilus' or 'octopus'.
+ :return: Returns the release name of the Ceph version in lower case.
+ :rtype: str
+ """
+ return self._ceph_get_release_name()
+
+ def get_context(self):
+ """
+ :return: a Python capsule containing a C++ CephContext pointer
+ """
+ return self._ceph_get_context()
+
+ def notify(self, notify_type, notify_id):
+ """
+ Called by the ceph-mgr service to notify the Python plugin
+ that new state is available.
+
+ :param notify_type: string indicating what kind of notification,
+ such as osd_map, mon_map, fs_map, mon_status,
+ health, pg_summary, command, service_map
+ :param notify_id: string (may be empty) that optionally specifies
+ which entity is being notified about. With
+ "command" notifications this is set to the tag
+ ``from send_command``.
+ """
+ pass
+
+ def config_notify(self):
+ """
+ Called by the ceph-mgr service to notify the Python plugin
+ that the configuration may have changed. Modules will want to
+ refresh any configuration values stored in config variables.
+ """
+ pass
+
+ def serve(self):
+ """
+ Called by the ceph-mgr service to start any server that
+ is provided by this Python plugin. The implementation
+ of this function should block until ``shutdown`` is called.
+
+ You *must* implement ``shutdown`` if you implement ``serve``
+ """
+ pass
+
+ def shutdown(self):
+ """
+ Called by the ceph-mgr service to request that this
+ module drop out of its serve() function. You do not
+ need to implement this if you do not implement serve()
+
+ :return: None
+ """
+ if self._rados:
+ self._rados.shutdown()
+
+ def get(self, data_name):
+ """
+ Called by the plugin to fetch named cluster-wide objects from ceph-mgr.
+
+ :param str data_name: Valid things to fetch are osd_crush_map_text,
+ osd_map, osd_map_tree, osd_map_crush, config, mon_map, fs_map,
+ osd_metadata, pg_summary, io_rate, pg_dump, df, osd_stats,
+ health, mon_status, devices, device <devid>, pg_stats,
+ pool_stats, pg_ready, osd_ping_times.
+
+ Note:
+ All these structures have their own JSON representations: experiment
+ or look at the C++ ``dump()`` methods to learn about them.
+ """
+ return self._ceph_get(data_name)
+
+ def _stattype_to_str(self, stattype):
+
+ typeonly = stattype & self.PERFCOUNTER_TYPE_MASK
+ if typeonly == 0:
+ return 'gauge'
+ if typeonly == self.PERFCOUNTER_LONGRUNAVG:
+ # this lie matches the DaemonState decoding: only val, no counts
+ return 'counter'
+ if typeonly == self.PERFCOUNTER_COUNTER:
+ return 'counter'
+ if typeonly == self.PERFCOUNTER_HISTOGRAM:
+ return 'histogram'
+
+ return ''
+
+ def _perfpath_to_path_labels(self, daemon, path):
+ label_names = ("ceph_daemon",)
+ labels = (daemon,)
+
+ if daemon.startswith('rbd-mirror.'):
+ match = re.match(
+ r'^rbd_mirror_([^/]+)/(?:(?:([^/]+)/)?)(.*)\.(replay(?:_bytes|_latency)?)$',
+ path
+ )
+ if match:
+ path = 'rbd_mirror_' + match.group(4)
+ pool = match.group(1)
+ namespace = match.group(2) or ''
+ image = match.group(3)
+ label_names += ('pool', 'namespace', 'image')
+ labels += (pool, namespace, image)
+
+ return path, label_names, labels,
+
+ def _perfvalue_to_value(self, stattype, value):
+ if stattype & self.PERFCOUNTER_TIME:
+ # Convert from ns to seconds
+ return value / 1000000000.0
+ else:
+ return value
+
+ def _unit_to_str(self, unit):
+ if unit == self.NONE:
+ return "/s"
+ elif unit == self.BYTES:
+ return "B/s"
+
+ @staticmethod
+ def to_pretty_iec(n):
+ for bits, suffix in [(60, 'Ei'), (50, 'Pi'), (40, 'Ti'), (30, 'Gi'),
+ (20, 'Mi'), (10, 'Ki')]:
+ if n > 10 << bits:
+ return str(n >> bits) + ' ' + suffix
+ return str(n) + ' '
+
+ @staticmethod
+ def get_pretty_row(elems, width):
+ """
+ Takes an array of elements and returns a string with those elements
+ formatted as a table row. Useful for polling modules.
+
+ :param elems: the elements to be printed
+ :param width: the width of the terminal
+ """
+ n = len(elems)
+ column_width = int(width / n)
+
+ ret = '|'
+ for elem in elems:
+ ret += '{0:>{w}} |'.format(elem, w=column_width - 2)
+
+ return ret
+
+ def get_pretty_header(self, elems, width):
+ """
+ Like ``get_pretty_row`` but adds dashes, to be used as a table title.
+
+ :param elems: the elements to be printed
+ :param width: the width of the terminal
+ """
+ n = len(elems)
+ column_width = int(width / n)
+
+ # dash line
+ ret = '+'
+ for i in range(0, n):
+ ret += '-' * (column_width - 1) + '+'
+ ret += '\n'
+
+ # title
+ ret += self.get_pretty_row(elems, width)
+ ret += '\n'
+
+ # dash line
+ ret += '+'
+ for i in range(0, n):
+ ret += '-' * (column_width - 1) + '+'
+ ret += '\n'
+
+ return ret
+
+ def get_server(self, hostname):
+ """
+ Called by the plugin to fetch metadata about a particular hostname from
+ ceph-mgr.
+
+ This is information that ceph-mgr has gleaned from the daemon metadata
+ reported by daemons running on a particular server.
+
+ :param hostname: a hostname
+ """
+ return self._ceph_get_server(hostname)
+
+ def get_perf_schema(self, svc_type, svc_name):
+ """
+ Called by the plugin to fetch perf counter schema info.
+ svc_name can be nullptr, as can svc_type, in which case
+ they are wildcards
+
+ :param str svc_type:
+ :param str svc_name:
+ :return: list of dicts describing the counters requested
+ """
+ return self._ceph_get_perf_schema(svc_type, svc_name)
+
+ def get_counter(self, svc_type, svc_name, path):
+ """
+ Called by the plugin to fetch the latest performance counter data for a
+ particular counter on a particular service.
+
+ :param str svc_type:
+ :param str svc_name:
+ :param str path: a period-separated concatenation of the subsystem and the
+ counter name, for example "mds.inodes".
+ :return: A list of two-tuples of (timestamp, value) is returned. This may be
+ empty if no data is available.
+ """
+ return self._ceph_get_counter(svc_type, svc_name, path)
+
+ def get_latest_counter(self, svc_type, svc_name, path):
+ """
+ Called by the plugin to fetch only the newest performance counter data
+ pointfor a particular counter on a particular service.
+
+ :param str svc_type:
+ :param str svc_name:
+ :param str path: a period-separated concatenation of the subsystem and the
+ counter name, for example "mds.inodes".
+ :return: A list of two-tuples of (timestamp, value) is returned. This may be
+ empty if no data is available.
+ """
+ return self._ceph_get_latest_counter(svc_type, svc_name, path)
+
+ def list_servers(self):
+ """
+ Like ``get_server``, but gives information about all servers (i.e. all
+ unique hostnames that have been mentioned in daemon metadata)
+
+ :return: a list of information about all servers
+ :rtype: list
+ """
+ return self._ceph_get_server(None)
+
+ def get_metadata(self, svc_type, svc_id, default=None):
+ """
+ Fetch the daemon metadata for a particular service.
+
+ ceph-mgr fetches metadata asynchronously, so are windows of time during
+ addition/removal of services where the metadata is not available to
+ modules. ``None`` is returned if no metadata is available.
+
+ :param str svc_type: service type (e.g., 'mds', 'osd', 'mon')
+ :param str svc_id: service id. convert OSD integer IDs to strings when
+ calling this
+ :rtype: dict, or None if no metadata found
+ """
+ metadata = self._ceph_get_metadata(svc_type, svc_id)
+ if metadata is None:
+ return default
+ return metadata
+
+ def get_daemon_status(self, svc_type, svc_id):
+ """
+ Fetch the latest status for a particular service daemon.
+
+ This method may return ``None`` if no status information is
+ available, for example because the daemon hasn't fully started yet.
+
+ :param svc_type: string (e.g., 'rgw')
+ :param svc_id: string
+ :return: dict, or None if the service is not found
+ """
+ return self._ceph_get_daemon_status(svc_type, svc_id)
+
+ def check_mon_command(self, cmd_dict, inbuf=None):
+ """
+ Wrapper around :func:`~mgr_module.MgrModule.mon_command`, but raises,
+ if ``retval != 0``.
+ """
+
+ r = HandleCommandResult(*self.mon_command(cmd_dict, inbuf))
+ if r.retval:
+ raise MonCommandFailed(
+ '{} failed: {} retval: {}'.format(cmd_dict["prefix"], r.stderr, r.retval)
+ )
+ return r
+
+ def mon_command(self, cmd_dict, inbuf=None):
+ """
+ Helper for modules that do simple, synchronous mon command
+ execution.
+
+ See send_command for general case.
+
+ :return: status int, out std, err str
+ """
+
+ t1 = time.time()
+ result = CommandResult()
+ self.send_command(result, "mon", "", json.dumps(cmd_dict), "", inbuf)
+ r = result.wait()
+ t2 = time.time()
+
+ self.log.debug("mon_command: '{0}' -> {1} in {2:.3f}s".format(
+ cmd_dict['prefix'], r[0], t2 - t1
+ ))
+
+ return r
+
+ def send_command(
+ self,
+ result,
+ svc_type,
+ svc_id,
+ command,
+ tag,
+ inbuf=None):
+ """
+ Called by the plugin to send a command to the mon
+ cluster.
+
+ :param CommandResult result: an instance of the ``CommandResult``
+ class, defined in the same module as MgrModule. This acts as a
+ completion and stores the output of the command. Use
+ ``CommandResult.wait()`` if you want to block on completion.
+ :param str svc_type:
+ :param str svc_id:
+ :param str command: a JSON-serialized command. This uses the same
+ format as the ceph command line, which is a dictionary of command
+ arguments, with the extra ``prefix`` key containing the command
+ name itself. Consult MonCommands.h for available commands and
+ their expected arguments.
+ :param str tag: used for nonblocking operation: when a command
+ completes, the ``notify()`` callback on the MgrModule instance is
+ triggered, with notify_type set to "command", and notify_id set to
+ the tag of the command.
+ :param str inbuf: input buffer for sending additional data.
+ """
+ self._ceph_send_command(result, svc_type, svc_id, command, tag, inbuf)
+
+ def set_health_checks(self, checks):
+ """
+ Set the module's current map of health checks. Argument is a
+ dict of check names to info, in this form:
+
+ ::
+
+ {
+ 'CHECK_FOO': {
+ 'severity': 'warning', # or 'error'
+ 'summary': 'summary string',
+ 'detail': [ 'list', 'of', 'detail', 'strings' ],
+ },
+ 'CHECK_BAR': {
+ 'severity': 'error',
+ 'summary': 'bars are bad',
+ 'detail': [ 'too hard' ],
+ },
+ }
+
+ :param list: dict of health check dicts
+ """
+ self._ceph_set_health_checks(checks)
+
+ def _handle_command(self, inbuf, cmd):
+ if cmd['prefix'] not in CLICommand.COMMANDS:
+ return self.handle_command(inbuf, cmd)
+ return CLICommand.COMMANDS[cmd['prefix']].call(self, cmd, inbuf)
+
+ def handle_command(self, inbuf, cmd):
+ """
+ Called by ceph-mgr to request the plugin to handle one
+ of the commands that it declared in self.COMMANDS
+
+ Return a status code, an output buffer, and an
+ output string. The output buffer is for data results,
+ the output string is for informative text.
+
+ :param inbuf: content of any "-i <file>" supplied to ceph cli
+ :type inbuf: str
+ :param cmd: from Ceph's cmdmap_t
+ :type cmd: dict
+
+ :return: HandleCommandResult or a 3-tuple of (int, str, str)
+ """
+
+ # Should never get called if they didn't declare
+ # any ``COMMANDS``
+ raise NotImplementedError()
+
+ def get_mgr_id(self):
+ """
+ Retrieve the name of the manager daemon where this plugin
+ is currently being executed (i.e. the active manager).
+
+ :return: str
+ """
+ return self._ceph_get_mgr_id()
+
+ def get_ceph_option(self, key):
+ return self._ceph_get_option(key)
+
+ def _validate_module_option(self, key):
+ """
+ Helper: don't allow get/set config callers to
+ access config options that they didn't declare
+ in their schema.
+ """
+ if key not in [o['name'] for o in self.MODULE_OPTIONS]:
+ raise RuntimeError("Config option '{0}' is not in {1}.MODULE_OPTIONS".
+ format(key, self.__class__.__name__))
+
+ def _get_module_option(self, key, default, localized_prefix=""):
+ r = self._ceph_get_module_option(self.module_name, key,
+ localized_prefix)
+ if r is None:
+ return self.MODULE_OPTION_DEFAULTS.get(key, default)
+ else:
+ return r
+
+ def get_module_option(self, key, default=None):
+ """
+ Retrieve the value of a persistent configuration setting
+
+ :param str key:
+ :param str default:
+ :return: str
+ """
+ self._validate_module_option(key)
+ return self._get_module_option(key, default)
+
+ def get_module_option_ex(self, module, key, default=None):
+ """
+ Retrieve the value of a persistent configuration setting
+ for the specified module.
+
+ :param str module: The name of the module, e.g. 'dashboard'
+ or 'telemetry'.
+ :param str key: The configuration key, e.g. 'server_addr'.
+ :param str,None default: The default value to use when the
+ returned value is ``None``. Defaults to ``None``.
+ :return: str,int,bool,float,None
+ """
+ if module == self.module_name:
+ self._validate_module_option(key)
+ r = self._ceph_get_module_option(module, key)
+ return default if r is None else r
+
+ def get_store_prefix(self, key_prefix):
+ """
+ Retrieve a dict of KV store keys to values, where the keys
+ have the given prefix
+
+ :param str key_prefix:
+ :return: str
+ """
+ return self._ceph_get_store_prefix(key_prefix)
+
+ def _set_localized(self, key, val, setter):
+ return setter(_get_localized_key(self.get_mgr_id(), key), val)
+
+ def get_localized_module_option(self, key, default=None):
+ """
+ Retrieve localized configuration for this ceph-mgr instance
+ :param str key:
+ :param str default:
+ :return: str
+ """
+ self._validate_module_option(key)
+ return self._get_module_option(key, default, self.get_mgr_id())
+
+ def _set_module_option(self, key, val):
+ return self._ceph_set_module_option(self.module_name, key,
+ None if val is None else str(val))
+
+ def set_module_option(self, key, val):
+ """
+ Set the value of a persistent configuration setting
+
+ :param str key:
+ :type val: str | None
+ """
+ self._validate_module_option(key)
+ return self._set_module_option(key, val)
+
+ def set_module_option_ex(self, module, key, val):
+ """
+ Set the value of a persistent configuration setting
+ for the specified module.
+
+ :param str module:
+ :param str key:
+ :param str val:
+ """
+ if module == self.module_name:
+ self._validate_module_option(key)
+ return self._ceph_set_module_option(module, key, str(val))
+
+ def set_localized_module_option(self, key, val):
+ """
+ Set localized configuration for this ceph-mgr instance
+ :param str key:
+ :param str val:
+ :return: str
+ """
+ self._validate_module_option(key)
+ return self._set_localized(key, val, self._set_module_option)
+
+ def set_store(self, key, val):
+ """
+ Set a value in this module's persistent key value store.
+ If val is None, remove key from store
+
+ :param str key:
+ :param str val:
+ """
+ self._ceph_set_store(key, val)
+
+ def get_store(self, key, default=None):
+ """
+ Get a value from this module's persistent key value store
+ """
+ r = self._ceph_get_store(key)
+ if r is None:
+ return default
+ else:
+ return r
+
+ def get_localized_store(self, key, default=None):
+ r = self._ceph_get_store(_get_localized_key(self.get_mgr_id(), key))
+ if r is None:
+ r = self._ceph_get_store(key)
+ if r is None:
+ r = default
+ return r
+
+ def set_localized_store(self, key, val):
+ return self._set_localized(key, val, self.set_store)
+
+ def self_test(self):
+ """
+ Run a self-test on the module. Override this function and implement
+ a best as possible self-test for (automated) testing of the module
+
+ Indicate any failures by raising an exception. This does not have
+ to be pretty, it's mainly for picking up regressions during
+ development, rather than use in the field.
+
+ :return: None, or an advisory string for developer interest, such
+ as a json dump of some state.
+ """
+ pass
+
+ def get_osdmap(self):
+ """
+ Get a handle to an OSDMap. If epoch==0, get a handle for the latest
+ OSDMap.
+ :return: OSDMap
+ """
+ return self._ceph_get_osdmap()
+
+ def get_latest(self, daemon_type, daemon_name, counter):
+ data = self.get_latest_counter(
+ daemon_type, daemon_name, counter)[counter]
+ if data:
+ return data[1]
+ else:
+ return 0
+
+ def get_latest_avg(self, daemon_type, daemon_name, counter):
+ data = self.get_latest_counter(
+ daemon_type, daemon_name, counter)[counter]
+ if data:
+ return data[1], data[2]
+ else:
+ return 0, 0
+
+ def get_all_perf_counters(self, prio_limit=PRIO_USEFUL,
+ services=("mds", "mon", "osd",
+ "rbd-mirror", "rgw", "tcmu-runner")):
+ """
+ Return the perf counters currently known to this ceph-mgr
+ instance, filtered by priority equal to or greater than `prio_limit`.
+
+ The result is a map of string to dict, associating services
+ (like "osd.123") with their counters. The counter
+ dict for each service maps counter paths to a counter
+ info structure, which is the information from
+ the schema, plus an additional "value" member with the latest
+ value.
+ """
+
+ result = defaultdict(dict)
+
+ for server in self.list_servers():
+ for service in server['services']:
+ if service['type'] not in services:
+ continue
+
+ schema = self.get_perf_schema(service['type'], service['id'])
+ if not schema:
+ self.log.warn("No perf counter schema for {0}.{1}".format(
+ service['type'], service['id']
+ ))
+ continue
+
+ # Value is returned in a potentially-multi-service format,
+ # get just the service we're asking about
+ svc_full_name = "{0}.{1}".format(
+ service['type'], service['id'])
+ schema = schema[svc_full_name]
+
+ # Populate latest values
+ for counter_path, counter_schema in schema.items():
+ # self.log.debug("{0}: {1}".format(
+ # counter_path, json.dumps(counter_schema)
+ # ))
+ if counter_schema['priority'] < prio_limit:
+ continue
+
+ counter_info = dict(counter_schema)
+
+ # Also populate count for the long running avgs
+ if counter_schema['type'] & self.PERFCOUNTER_LONGRUNAVG:
+ v, c = self.get_latest_avg(
+ service['type'],
+ service['id'],
+ counter_path
+ )
+ counter_info['value'], counter_info['count'] = v, c
+ result[svc_full_name][counter_path] = counter_info
+ else:
+ counter_info['value'] = self.get_latest(
+ service['type'],
+ service['id'],
+ counter_path
+ )
+
+ result[svc_full_name][counter_path] = counter_info
+
+ self.log.debug("returning {0} counter".format(len(result)))
+
+ return result
+
+ def set_uri(self, uri):
+ """
+ If the module exposes a service, then call this to publish the
+ address once it is available.
+
+ :return: a string
+ """
+ return self._ceph_set_uri(uri)
+
+ def have_mon_connection(self):
+ """
+ Check whether this ceph-mgr daemon has an open connection
+ to a monitor. If it doesn't, then it's likely that the
+ information we have about the cluster is out of date,
+ and/or the monitor cluster is down.
+ """
+
+ return self._ceph_have_mon_connection()
+
+ def update_progress_event(self, evid, desc, progress):
+ return self._ceph_update_progress_event(str(evid), str(desc), float(progress))
+
+ def complete_progress_event(self, evid):
+ return self._ceph_complete_progress_event(str(evid))
+
+ def clear_all_progress_events(self):
+ return self._ceph_clear_all_progress_events()
+
+ @property
+ def rados(self):
+ """
+ A librados instance to be shared by any classes within
+ this mgr module that want one.
+ """
+ if self._rados:
+ return self._rados
+
+ ctx_capsule = self.get_context()
+ self._rados = rados.Rados(context=ctx_capsule)
+ self._rados.connect()
+
+ return self._rados
+
+ @staticmethod
+ def can_run():
+ """
+ Implement this function to report whether the module's dependencies
+ are met. For example, if the module needs to import a particular
+ dependency to work, then use a try/except around the import at
+ file scope, and then report here if the import failed.
+
+ This will be called in a blocking way from the C++ code, so do not
+ do any I/O that could block in this function.
+
+ :return a 2-tuple consisting of a boolean and explanatory string
+ """
+
+ return True, ""
+
+ def remote(self, module_name, method_name, *args, **kwargs):
+ """
+ Invoke a method on another module. All arguments, and the return
+ value from the other module must be serializable.
+
+ Limitation: Do not import any modules within the called method.
+ Otherwise you will get an error in Python 2::
+
+ RuntimeError('cannot unmarshal code objects in restricted execution mode',)
+
+
+
+ :param module_name: Name of other module. If module isn't loaded,
+ an ImportError exception is raised.
+ :param method_name: Method name. If it does not exist, a NameError
+ exception is raised.
+ :param args: Argument tuple
+ :param kwargs: Keyword argument dict
+ :raises RuntimeError: **Any** error raised within the method is converted to a RuntimeError
+ :raises ImportError: No such module
+ """
+ return self._ceph_dispatch_remote(module_name, method_name,
+ args, kwargs)
+
+ def add_osd_perf_query(self, query):
+ """
+ Register an OSD perf query. Argument is a
+ dict of the query parameters, in this form:
+
+ ::
+
+ {
+ 'key_descriptor': [
+ {'type': subkey_type, 'regex': regex_pattern},
+ ...
+ ],
+ 'performance_counter_descriptors': [
+ list, of, descriptor, types
+ ],
+ 'limit': {'order_by': performance_counter_type, 'max_count': n},
+ }
+
+ Valid subkey types:
+ 'client_id', 'client_address', 'pool_id', 'namespace', 'osd_id',
+ 'pg_id', 'object_name', 'snap_id'
+ Valid performance counter types:
+ 'ops', 'write_ops', 'read_ops', 'bytes', 'write_bytes', 'read_bytes',
+ 'latency', 'write_latency', 'read_latency'
+
+ :param object query: query
+ :rtype: int (query id)
+ """
+ return self._ceph_add_osd_perf_query(query)
+
+ def remove_osd_perf_query(self, query_id):
+ """
+ Unregister an OSD perf query.
+
+ :param int query_id: query ID
+ """
+ return self._ceph_remove_osd_perf_query(query_id)
+
+ def get_osd_perf_counters(self, query_id):
+ """
+ Get stats collected for an OSD perf query.
+
+ :param int query_id: query ID
+ """
+ return self._ceph_get_osd_perf_counters(query_id)
+
+ def is_authorized(self, arguments):
+ """
+ Verifies that the current session caps permit executing the py service
+ or current module with the provided arguments. This provides a generic
+ way to allow modules to restrict by more fine-grained controls (e.g.
+ pools).
+
+ :param arguments: dict of key/value arguments to test
+ """
+ return self._ceph_is_authorized(arguments)
+
+
+class PersistentStoreDict(object):
+ def __init__(self, mgr, prefix):
+ # type: (MgrModule, str) -> None
+ self.mgr = mgr
+ self.prefix = prefix + '.'
+
+ def _mk_store_key(self, key):
+ return self.prefix + key
+
+ def __missing__(self, key):
+ # KeyError won't work for the `in` operator.
+ # https://docs.python.org/3/reference/expressions.html#membership-test-details
+ raise IndexError('PersistentStoreDict: "{}" not found'.format(key))
+
+ def clear(self):
+ # Don't make any assumptions about the content of the values.
+ for item in six.iteritems(self.mgr.get_store_prefix(self.prefix)):
+ k, _ = item
+ self.mgr.set_store(k, None)
+
+ def __getitem__(self, item):
+ # type: (str) -> Any
+ key = self._mk_store_key(item)
+ try:
+ val = self.mgr.get_store(key)
+ if val is None:
+ self.__missing__(key)
+ return json.loads(val)
+ except (KeyError, AttributeError, IndexError, ValueError, TypeError):
+ logging.getLogger(__name__).exception('failed to deserialize')
+ self.mgr.set_store(key, None)
+ raise
+
+ def __setitem__(self, item, value):
+ # type: (str, Any) -> None
+ """
+ value=None is not allowed, as it will remove the key.
+ """
+ key = self._mk_store_key(item)
+ self.mgr.set_store(key, json.dumps(value) if value is not None else None)
+
+ def __delitem__(self, item):
+ self[item] = None
+
+ def __len__(self):
+ return len(self.keys())
+
+ def items(self):
+ # type: () -> Iterator[Tuple[str, Any]]
+ prefix_len = len(self.prefix)
+ try:
+ for item in six.iteritems(self.mgr.get_store_prefix(self.prefix)):
+ k, v = item
+ yield k[prefix_len:], json.loads(v)
+ except (KeyError, AttributeError, IndexError, ValueError, TypeError):
+ logging.getLogger(__name__).exception('failed to deserialize')
+ self.clear()
+
+ def keys(self):
+ # type: () -> Set[str]
+ return {item[0] for item in self.items()}
+
+ def __iter__(self):
+ return iter(self.keys())
diff --git a/src/pybind/mgr/mgr_util.py b/src/pybind/mgr/mgr_util.py
new file mode 100644
index 00000000..e337a618
--- /dev/null
+++ b/src/pybind/mgr/mgr_util.py
@@ -0,0 +1,300 @@
+import contextlib
+import os
+import socket
+import logging
+
+(
+ BLACK,
+ RED,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ GRAY
+) = range(8)
+
+RESET_SEQ = "\033[0m"
+COLOR_SEQ = "\033[1;%dm"
+COLOR_DARK_SEQ = "\033[0;%dm"
+BOLD_SEQ = "\033[1m"
+UNDERLINE_SEQ = "\033[4m"
+
+logger = logging.getLogger(__name__)
+
+
+def colorize(msg, color, dark=False):
+ """
+ Decorate `msg` with escape sequences to give the requested color
+ """
+ return (COLOR_DARK_SEQ if dark else COLOR_SEQ) % (30 + color) \
+ + msg + RESET_SEQ
+
+
+def bold(msg):
+ """
+ Decorate `msg` with escape sequences to make it appear bold
+ """
+ return BOLD_SEQ + msg + RESET_SEQ
+
+
+def format_units(n, width, colored, decimal):
+ """
+ Format a number without units, so as to fit into `width` characters, substituting
+ an appropriate unit suffix.
+
+ Use decimal for dimensionless things, use base 2 (decimal=False) for byte sizes/rates.
+ """
+
+ factor = 1000 if decimal else 1024
+ units = [' ', 'k', 'M', 'G', 'T', 'P', 'E']
+ unit = 0
+ while len("%s" % (int(n) // (factor**unit))) > width - 1:
+ unit += 1
+
+ if unit > 0:
+ truncated_float = ("%f" % (n / (float(factor) ** unit)))[0:width - 1]
+ if truncated_float[-1] == '.':
+ truncated_float = " " + truncated_float[0:-1]
+ else:
+ truncated_float = "%{wid}d".format(wid=width - 1) % n
+ formatted = "%s%s" % (truncated_float, units[unit])
+
+ if colored:
+ if n == 0:
+ color = BLACK, False
+ else:
+ color = YELLOW, False
+ return bold(colorize(formatted[0:-1], color[0], color[1])) \
+ + bold(colorize(formatted[-1], BLACK, False))
+ else:
+ return formatted
+
+
+def format_dimless(n, width, colored=False):
+ return format_units(n, width, colored, decimal=True)
+
+
+def format_bytes(n, width, colored=False):
+ return format_units(n, width, colored, decimal=False)
+
+
+def merge_dicts(*args):
+ # type: (dict) -> dict
+ """
+ >>> assert merge_dicts({1:2}, {3:4}) == {1:2, 3:4}
+ You can also overwrite keys:
+ >>> assert merge_dicts({1:2}, {1:4}) == {1:4}
+ :rtype: dict[str, Any]
+ """
+ ret = {}
+ for arg in args:
+ ret.update(arg)
+ return ret
+
+
+def get_default_addr():
+ def is_ipv6_enabled():
+ try:
+ sock = socket.socket(socket.AF_INET6)
+ with contextlib.closing(sock):
+ sock.bind(("::1", 0))
+ return True
+ except (AttributeError, socket.error) as e:
+ return False
+
+ try:
+ return get_default_addr.result
+ except AttributeError:
+ result = '::' if is_ipv6_enabled() else '0.0.0.0'
+ get_default_addr.result = result
+ return result
+
+
+class ServerConfigException(Exception):
+ pass
+
+def verify_cacrt(cert_fname):
+ """Basic validation of a ca cert"""
+
+ if not cert_fname:
+ raise ServerConfigException("CA cert not configured")
+ if not os.path.isfile(cert_fname):
+ raise ServerConfigException("Certificate {} does not exist".format(cert_fname))
+
+ from OpenSSL import crypto
+ try:
+ with open(cert_fname) as f:
+ x509 = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
+ if x509.has_expired():
+ logger.warning(
+ 'Certificate {} has expired'.format(cert_fname))
+ except (ValueError, crypto.Error) as e:
+ raise ServerConfigException(
+ 'Invalid certificate {}: {}'.format(cert_fname, str(e)))
+
+
+def verify_tls_files(cert_fname, pkey_fname):
+ """Basic checks for TLS certificate and key files
+
+ Do some validations to the private key and certificate:
+ - Check the type and format
+ - Check the certificate expiration date
+ - Check the consistency of the private key
+ - Check that the private key and certificate match up
+
+ :param cert_fname: Name of the certificate file
+ :param pkey_fname: name of the certificate public key file
+
+ :raises ServerConfigException: An error with a message
+
+ """
+
+ if not cert_fname or not pkey_fname:
+ raise ServerConfigException('no certificate configured')
+
+ verify_cacrt(cert_fname)
+
+ if not os.path.isfile(pkey_fname):
+ raise ServerConfigException('private key %s does not exist' % pkey_fname)
+
+ from OpenSSL import crypto, SSL
+
+ try:
+ with open(pkey_fname) as f:
+ pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read())
+ pkey.check()
+ except (ValueError, crypto.Error) as e:
+ raise ServerConfigException(
+ 'Invalid private key {}: {}'.format(pkey_fname, str(e)))
+ try:
+ context = SSL.Context(SSL.TLSv1_METHOD)
+ context.use_certificate_file(cert_fname, crypto.FILETYPE_PEM)
+ context.use_privatekey_file(pkey_fname, crypto.FILETYPE_PEM)
+ context.check_privatekey()
+ except crypto.Error as e:
+ logger.warning(
+ 'Private key {} and certificate {} do not match up: {}'.format(
+ pkey_fname, cert_fname, str(e)))
+
+def get_most_recent_rate(rates):
+ """ Get most recent rate from rates
+
+ :param rates: The derivative between all time series data points [time in seconds, value]
+ :type rates: list[tuple[int, float]]
+
+ :return: The last derivative or 0.0 if none exists
+ :rtype: float
+
+ >>> get_most_recent_rate(None)
+ 0.0
+ >>> get_most_recent_rate([])
+ 0.0
+ >>> get_most_recent_rate([(1, -2.0)])
+ -2.0
+ >>> get_most_recent_rate([(1, 2.0), (2, 1.5), (3, 5.0)])
+ 5.0
+ """
+ if not rates:
+ return 0.0
+ return rates[-1][1]
+
+def get_time_series_rates(data):
+ """ Rates from time series data
+
+ :param data: Time series data [time in seconds, value]
+ :type data: list[tuple[int, float]]
+
+ :return: The derivative between all time series data points [time in seconds, value]
+ :rtype: list[tuple[int, float]]
+
+ >>> logger.debug = lambda s,x,y: print(s % (x,y))
+ >>> get_time_series_rates([])
+ []
+ >>> get_time_series_rates([[0, 1], [1, 3]])
+ [(1, 2.0)]
+ >>> get_time_series_rates([[0, 2], [0, 3], [0, 1], [1, 2], [1, 3]])
+ Duplicate timestamp in time series data: [0, 2], [0, 3]
+ Duplicate timestamp in time series data: [0, 3], [0, 1]
+ Duplicate timestamp in time series data: [1, 2], [1, 3]
+ [(1, 2.0)]
+ >>> get_time_series_rates([[1, 1], [2, 3], [4, 11], [5, 16], [6, 22]])
+ [(2, 2.0), (4, 4.0), (5, 5.0), (6, 6.0)]
+ """
+ data = _filter_time_series(data)
+ if not data:
+ return []
+ return [(data2[0], _derivative(data1, data2)) for data1, data2 in
+ _pairwise(data)]
+
+def _filter_time_series(data):
+ """ Filters time series data
+
+ Filters out samples with the same timestamp in given time series data.
+ It also enforces the list to contain at least two samples.
+
+ All filtered values will be shown in the debug log. If values were filtered it's a bug in the
+ time series data collector, please report it.
+
+ :param data: Time series data [time in seconds, value]
+ :type data: list[tuple[int, float]]
+
+ :return: Filtered time series data [time in seconds, value]
+ :rtype: list[tuple[int, float]]
+
+ >>> logger.debug = lambda s,x,y: print(s % (x,y))
+ >>> _filter_time_series([])
+ []
+ >>> _filter_time_series([[1, 42]])
+ []
+ >>> _filter_time_series([[10, 2], [10, 3]])
+ Duplicate timestamp in time series data: [10, 2], [10, 3]
+ []
+ >>> _filter_time_series([[0, 1], [1, 2]])
+ [[0, 1], [1, 2]]
+ >>> _filter_time_series([[0, 2], [0, 3], [0, 1], [1, 2], [1, 3]])
+ Duplicate timestamp in time series data: [0, 2], [0, 3]
+ Duplicate timestamp in time series data: [0, 3], [0, 1]
+ Duplicate timestamp in time series data: [1, 2], [1, 3]
+ [[0, 1], [1, 3]]
+ >>> _filter_time_series([[1, 1], [2, 3], [4, 11], [5, 16], [6, 22]])
+ [[1, 1], [2, 3], [4, 11], [5, 16], [6, 22]]
+ """
+ filtered = []
+ for i in range(len(data) - 1):
+ if data[i][0] == data[i + 1][0]: # Same timestamp
+ logger.debug("Duplicate timestamp in time series data: %s, %s", data[i], data[i + 1])
+ continue
+ filtered.append(data[i])
+ if not filtered:
+ return []
+ filtered.append(data[-1])
+ return filtered
+
+def _derivative(p1, p2):
+ """ Derivative between two time series data points
+
+ :param p1: Time series data [time in seconds, value]
+ :type p1: tuple[int, float]
+ :param p2: Time series data [time in seconds, value]
+ :type p2: tuple[int, float]
+
+ :return: Derivative between both points
+ :rtype: float
+
+ >>> _derivative([0, 0], [2, 1])
+ 0.5
+ >>> _derivative([0, 1], [2, 0])
+ -0.5
+ >>> _derivative([0, 0], [3, 1])
+ 0.3333333333333333
+ """
+ return (p2[1] - p1[1]) / float(p2[0] - p1[0])
+
+def _pairwise(iterable):
+ it = iter(iterable)
+ a = next(it, None)
+
+ for b in it:
+ yield (a, b)
+ a = b
diff --git a/src/pybind/mgr/orchestrator.py b/src/pybind/mgr/orchestrator.py
new file mode 100644
index 00000000..ccf2c86f
--- /dev/null
+++ b/src/pybind/mgr/orchestrator.py
@@ -0,0 +1,1085 @@
+
+"""
+ceph-mgr orchestrator interface
+
+Please see the ceph-mgr module developer's guide for more information.
+"""
+import sys
+import time
+import fnmatch
+import uuid
+import datetime
+
+import six
+
+from mgr_module import MgrModule, PersistentStoreDict
+from mgr_util import format_bytes
+
+try:
+ from typing import TypeVar, Generic, List, Optional, Union, Tuple, Iterator
+
+ T = TypeVar('T')
+ G = Generic[T]
+except ImportError:
+ T, G = object, object
+
+
+class OrchestratorError(Exception):
+ """
+ General orchestrator specific error.
+
+ Used for deployment, configuration or user errors.
+
+ It's not intended for programming errors or orchestrator internal errors.
+ """
+
+
+class NoOrchestrator(OrchestratorError):
+ """
+ No orchestrator in configured.
+ """
+ def __init__(self, msg="No orchestrator configured (try `ceph orchestrator set backend`)"):
+ super(NoOrchestrator, self).__init__(msg)
+
+
+class OrchestratorValidationError(OrchestratorError):
+ """
+ Raised when an orchestrator doesn't support a specific feature.
+ """
+
+
+class _Completion(G):
+ @property
+ def result(self):
+ # type: () -> T
+ """
+ Return the result of the operation that we were waited
+ for. Only valid after calling Orchestrator.wait() on this
+ completion.
+ """
+ raise NotImplementedError()
+
+ @property
+ def exception(self):
+ # type: () -> Optional[Exception]
+ """
+ Holds an exception object.
+ """
+ try:
+ return self.__exception
+ except AttributeError:
+ return None
+
+ @exception.setter
+ def exception(self, value):
+ self.__exception = value
+
+ @property
+ def is_read(self):
+ # type: () -> bool
+ raise NotImplementedError()
+
+ @property
+ def is_complete(self):
+ # type: () -> bool
+ raise NotImplementedError()
+
+ @property
+ def is_errored(self):
+ # type: () -> bool
+ """
+ Has the completion failed. Default implementation looks for
+ self.exception. Can be overwritten.
+ """
+ return self.exception is not None
+
+ @property
+ def should_wait(self):
+ # type: () -> bool
+ raise NotImplementedError()
+
+
+def raise_if_exception(c):
+ # type: (_Completion) -> None
+ """
+ :raises OrchestratorError: Some user error or a config error.
+ :raises Exception: Some internal error
+ """
+ def copy_to_this_subinterpreter(r_obj):
+ # This is something like `return pickle.loads(pickle.dumps(r_obj))`
+ # Without importing anything.
+ r_cls = r_obj.__class__
+ if r_cls.__module__ == '__builtin__':
+ return r_obj
+ my_cls = getattr(sys.modules[r_cls.__module__], r_cls.__name__)
+ if id(my_cls) == id(r_cls):
+ return r_obj
+ my_obj = my_cls.__new__(my_cls)
+ for k,v in r_obj.__dict__.items():
+ setattr(my_obj, k, copy_to_this_subinterpreter(v))
+ return my_obj
+
+ if c.exception is not None:
+ raise copy_to_this_subinterpreter(c.exception)
+
+
+class ReadCompletion(_Completion):
+ """
+ ``Orchestrator`` implementations should inherit from this
+ class to implement their own handles to operations in progress, and
+ return an instance of their subclass from calls into methods.
+ """
+
+ def __init__(self):
+ pass
+
+ @property
+ def is_read(self):
+ return True
+
+ @property
+ def should_wait(self):
+ """Could the external operation be deemed as complete,
+ or should we wait?
+ We must wait for a read operation only if it is not complete.
+ """
+ return not self.is_complete
+
+
+class TrivialReadCompletion(ReadCompletion):
+ """
+ This is the trivial completion simply wrapping a result.
+ """
+ def __init__(self, result):
+ super(TrivialReadCompletion, self).__init__()
+ self._result = result
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_complete(self):
+ return True
+
+
+class WriteCompletion(_Completion):
+ """
+ ``Orchestrator`` implementations should inherit from this
+ class to implement their own handles to operations in progress, and
+ return an instance of their subclass from calls into methods.
+ """
+
+ def __init__(self):
+ self.progress_id = str(uuid.uuid4())
+
+ #: if a orchestrator module can provide a more detailed
+ #: progress information, it needs to also call ``progress.update()``.
+ self.progress = 0.5
+
+ def __str__(self):
+ """
+ ``__str__()`` is used for determining the message for progress events.
+ """
+ return super(WriteCompletion, self).__str__()
+
+ @property
+ def is_persistent(self):
+ # type: () -> bool
+ """
+ Has the operation updated the orchestrator's configuration
+ persistently? Typically this would indicate that an update
+ had been written to a manifest, but that the update
+ had not necessarily been pushed out to the cluster.
+ """
+ raise NotImplementedError()
+
+ @property
+ def is_effective(self):
+ """
+ Has the operation taken effect on the cluster? For example,
+ if we were adding a service, has it come up and appeared
+ in Ceph's cluster maps?
+ """
+ raise NotImplementedError()
+
+ @property
+ def is_complete(self):
+ return self.is_errored or (self.is_persistent and self.is_effective)
+
+ @property
+ def is_read(self):
+ return False
+
+ @property
+ def should_wait(self):
+ """Could the external operation be deemed as complete,
+ or should we wait?
+ We must wait for a write operation only if we know
+ it is not persistent yet.
+ """
+ return not self.is_persistent
+
+
+class Orchestrator(object):
+ """
+ Calls in this class may do long running remote operations, with time
+ periods ranging from network latencies to package install latencies and large
+ internet downloads. For that reason, all are asynchronous, and return
+ ``Completion`` objects.
+
+ Implementations are not required to start work on an operation until
+ the caller waits on the relevant Completion objects. Callers making
+ multiple updates should not wait on Completions until they're done
+ sending operations: this enables implementations to batch up a series
+ of updates when wait() is called on a set of Completion objects.
+
+ Implementations are encouraged to keep reasonably fresh caches of
+ the status of the system: it is better to serve a stale-but-recent
+ result read of e.g. device inventory than it is to keep the caller waiting
+ while you scan hosts every time.
+ """
+
+ def is_orchestrator_module(self):
+ """
+ Enable other modules to interrogate this module to discover
+ whether it's usable as an orchestrator module.
+
+ Subclasses do not need to override this.
+ """
+ return True
+
+ def available(self):
+ # type: () -> Tuple[bool, str]
+ """
+ Report whether we can talk to the orchestrator. This is the
+ place to give the user a meaningful message if the orchestrator
+ isn't running or can't be contacted.
+
+ This method may be called frequently (e.g. every page load
+ to conditionally display a warning banner), so make sure it's
+ not too expensive. It's okay to give a slightly stale status
+ (e.g. based on a periodic background ping of the orchestrator)
+ if that's necessary to make this method fast.
+
+ ..note:: `True` doesn't mean that the desired functionality
+ is actually available in the orchestrator. I.e. this
+ won't work as expected::
+
+ >>> if OrchestratorClientMixin().available()[0]: # wrong.
+ ... OrchestratorClientMixin().get_hosts()
+
+ :return: two-tuple of boolean, string
+ """
+ raise NotImplementedError()
+
+ def wait(self, completions):
+ """
+ Given a list of Completion instances, progress any which are
+ incomplete. Return a true if everything is done.
+
+ Callers should inspect the detail of each completion to identify
+ partial completion/progress information, and present that information
+ to the user.
+
+ For fast operations (e.g. reading from a database), implementations
+ may choose to do blocking IO in this call.
+
+ :rtype: bool
+ """
+ raise NotImplementedError()
+
+ def add_host(self, host):
+ # type: (str) -> WriteCompletion
+ """
+ Add a host to the orchestrator inventory.
+
+ :param host: hostname
+ """
+ raise NotImplementedError()
+
+ def remove_host(self, host):
+ # type: (str) -> WriteCompletion
+ """
+ Remove a host from the orchestrator inventory.
+
+ :param host: hostname
+ """
+ raise NotImplementedError()
+
+ def get_hosts(self):
+ # type: () -> ReadCompletion[List[InventoryNode]]
+ """
+ Report the hosts in the cluster.
+
+ The default implementation is extra slow.
+
+ :return: list of InventoryNodes
+ """
+ return self.get_inventory()
+
+ def get_inventory(self, node_filter=None, refresh=False):
+ # type: (InventoryFilter, bool) -> ReadCompletion[List[InventoryNode]]
+ """
+ Returns something that was created by `ceph-volume inventory`.
+
+ :return: list of InventoryNode
+ """
+ raise NotImplementedError()
+
+ def describe_service(self, service_type=None, service_id=None, node_name=None, refresh=False):
+ # type: (Optional[str], Optional[str], Optional[str], bool) -> ReadCompletion[List[ServiceDescription]]
+ """
+ Describe a service (of any kind) that is already configured in
+ the orchestrator. For example, when viewing an OSD in the dashboard
+ we might like to also display information about the orchestrator's
+ view of the service (like the kubernetes pod ID).
+
+ When viewing a CephFS filesystem in the dashboard, we would use this
+ to display the pods being currently run for MDS daemons.
+
+ :return: list of ServiceDescription objects.
+ """
+ raise NotImplementedError()
+
+ def service_action(self, action, service_type, service_name=None, service_id=None):
+ # type: (str, str, str, str) -> WriteCompletion
+ """
+ Perform an action (start/stop/reload) on a service.
+
+ Either service_name or service_id must be specified:
+
+ * If using service_name, perform the action on that entire logical
+ service (i.e. all daemons providing that named service).
+ * If using service_id, perform the action on a single specific daemon
+ instance.
+
+ :param action: one of "start", "stop", "reload"
+ :param service_type: e.g. "mds", "rgw", ...
+ :param service_name: name of logical service ("cephfs", "us-east", ...)
+ :param service_id: service daemon instance (usually a short hostname)
+ :rtype: WriteCompletion
+ """
+ assert action in ["start", "stop", "reload"]
+ assert service_name or service_id
+ assert not (service_name and service_id)
+ raise NotImplementedError()
+
+ def create_osds(self, drive_group, all_hosts):
+ # type: (DriveGroupSpec, List[str]) -> WriteCompletion
+ """
+ Create one or more OSDs within a single Drive Group.
+
+ The principal argument here is the drive_group member
+ of OsdSpec: other fields are advisory/extensible for any
+ finer-grained OSD feature enablement (choice of backing store,
+ compression/encryption, etc).
+
+ :param drive_group: DriveGroupSpec
+ :param all_hosts: TODO, this is required because the orchestrator methods are not composable
+ Probably this parameter can be easily removed because each orchestrator can use
+ the "get_inventory" method and the "drive_group.host_pattern" attribute
+ to obtain the list of hosts where to apply the operation
+ """
+ raise NotImplementedError()
+
+ def replace_osds(self, drive_group):
+ # type: (DriveGroupSpec) -> WriteCompletion
+ """
+ Like create_osds, but the osd_id_claims must be fully
+ populated.
+ """
+ raise NotImplementedError()
+
+ def remove_osds(self, osd_ids):
+ # type: (List[str]) -> WriteCompletion
+ """
+ :param osd_ids: list of OSD IDs
+
+ Note that this can only remove OSDs that were successfully
+ created (i.e. got an OSD ID).
+ """
+ raise NotImplementedError()
+
+ def update_mgrs(self, num, hosts):
+ # type: (int, List[str]) -> WriteCompletion
+ """
+ Update the number of cluster managers.
+
+ :param num: requested number of managers.
+ :param hosts: list of hosts (optional)
+ """
+ raise NotImplementedError()
+
+ def update_mons(self, num, hosts):
+ # type: (int, List[Tuple[str,str]]) -> WriteCompletion
+ """
+ Update the number of cluster monitors.
+
+ :param num: requested number of monitors.
+ :param hosts: list of hosts + network (optional)
+ """
+ raise NotImplementedError()
+
+ def add_stateless_service(self, service_type, spec):
+ # type: (str, StatelessServiceSpec) -> WriteCompletion
+ """
+ Installing and adding a completely new service to the cluster.
+
+ This is not about starting services.
+ """
+ raise NotImplementedError()
+
+ def update_stateless_service(self, service_type, spec):
+ # type: (str, StatelessServiceSpec) -> WriteCompletion
+ """
+ This is about changing / redeploying existing services. Like for
+ example changing the number of service instances.
+
+ :rtype: WriteCompletion
+ """
+ raise NotImplementedError()
+
+ def remove_stateless_service(self, service_type, id_):
+ # type: (str, str) -> WriteCompletion
+ """
+ Uninstalls an existing service from the cluster.
+
+ This is not about stopping services.
+ """
+ raise NotImplementedError()
+
+ def upgrade_start(self, upgrade_spec):
+ # type: (UpgradeSpec) -> WriteCompletion
+ raise NotImplementedError()
+
+ def upgrade_status(self):
+ # type: () -> ReadCompletion[UpgradeStatusSpec]
+ """
+ If an upgrade is currently underway, report on where
+ we are in the process, or if some error has occurred.
+
+ :return: UpgradeStatusSpec instance
+ """
+ raise NotImplementedError()
+
+ def upgrade_available(self):
+ # type: () -> ReadCompletion[List[str]]
+ """
+ Report on what versions are available to upgrade to
+
+ :return: List of strings
+ """
+ raise NotImplementedError()
+
+
+class UpgradeSpec(object):
+ # Request to orchestrator to initiate an upgrade to a particular
+ # version of Ceph
+ def __init__(self):
+ self.target_version = None
+
+
+class UpgradeStatusSpec(object):
+ # Orchestrator's report on what's going on with any ongoing upgrade
+ def __init__(self):
+ self.in_progress = False # Is an upgrade underway?
+ self.services_complete = [] # Which daemon types are fully updated?
+ self.message = "" # Freeform description
+
+
+class PlacementSpec(object):
+ """
+ For APIs that need to specify a node subset
+ """
+ def __init__(self):
+ self.label = None
+
+
+class ServiceDescription(object):
+ """
+ For responding to queries about the status of a particular service,
+ stateful or stateless.
+
+ This is not about health or performance monitoring of services: it's
+ about letting the orchestrator tell Ceph whether and where a
+ service is scheduled in the cluster. When an orchestrator tells
+ Ceph "it's running on node123", that's not a promise that the process
+ is literally up this second, it's a description of where the orchestrator
+ has decided the service should run.
+ """
+
+ def __init__(self, nodename=None, container_id=None, service=None, service_instance=None,
+ service_type=None, version=None, rados_config_location=None,
+ service_url=None, status=None, status_desc=None):
+ # Node is at the same granularity as InventoryNode
+ self.nodename = nodename
+
+ # Not everyone runs in containers, but enough people do to
+ # justify having this field here.
+ self.container_id = container_id
+
+ # Some services can be deployed in groups. For example, mds's can
+ # have an active and standby daemons, and nfs-ganesha can run daemons
+ # in parallel. This tag refers to a group of daemons as a whole.
+ #
+ # For instance, a cluster of mds' all service the same fs, and they
+ # will all have the same service value (which may be the
+ # Filesystem name in the FSMap).
+ #
+ # Single-instance services should leave this set to None
+ self.service = service
+
+ # The orchestrator will have picked some names for daemons,
+ # typically either based on hostnames or on pod names.
+ # This is the <foo> in mds.<foo>, the ID that will appear
+ # in the FSMap/ServiceMap.
+ self.service_instance = service_instance
+
+ # The type of service (osd, mon, mgr, etc.)
+ self.service_type = service_type
+
+ # Service version that was deployed
+ self.version = version
+
+ # Location of the service configuration when stored in rados
+ # object. Format: "rados://<pool>/[<namespace/>]<object>"
+ self.rados_config_location = rados_config_location
+
+ # If the service exposes REST-like API, this attribute should hold
+ # the URL.
+ self.service_url = service_url
+
+ # Service status: -1 error, 0 stopped, 1 running
+ self.status = status
+
+ # Service status description when status == -1.
+ self.status_desc = status_desc
+
+ def to_json(self):
+ out = {
+ 'nodename': self.nodename,
+ 'container_id': self.container_id,
+ 'service': self.service,
+ 'service_instance': self.service_instance,
+ 'service_type': self.service_type,
+ 'version': self.version,
+ 'rados_config_location': self.rados_config_location,
+ 'service_url': self.service_url,
+ 'status': self.status,
+ 'status_desc': self.status_desc,
+ }
+ return {k: v for (k, v) in out.items() if v is not None}
+
+ @classmethod
+ def from_json(cls, data):
+ return cls(**data)
+
+
+class DeviceSelection(object):
+ """
+ Used within :class:`myclass.DriveGroupSpec` to specify the devices
+ used by the Drive Group.
+
+ Any attributes (even none) can be included in the device
+ specification structure.
+ """
+
+ def __init__(self, paths=None, id_model=None, size=None, rotates=None, count=None):
+ # type: (List[str], str, str, bool, int) -> None
+ """
+ ephemeral drive group device specification
+
+ TODO: translate from the user interface (Drive Groups) to an actual list of devices.
+ """
+ if paths is None:
+ paths = []
+
+ #: List of absolute paths to the devices.
+ self.paths = paths # type: List[str]
+
+ #: A wildcard string. e.g: "SDD*"
+ self.id_model = id_model
+
+ #: Size specification of format LOW:HIGH.
+ #: Can also take the the form :HIGH, LOW:
+ #: or an exact value (as ceph-volume inventory reports)
+ self.size = size
+
+ #: is the drive rotating or not
+ self.rotates = rotates
+
+ #: if this is present limit the number of drives to this number.
+ self.count = count
+ self.validate()
+
+ def validate(self):
+ props = [self.id_model, self.size, self.rotates, self.count]
+ if self.paths and any(p is not None for p in props):
+ raise DriveGroupValidationError('DeviceSelection: `paths` and other parameters are mutually exclusive')
+ if not any(p is not None for p in [self.paths] + props):
+ raise DriveGroupValidationError('DeviceSelection cannot be empty')
+
+ @classmethod
+ def from_json(cls, device_spec):
+ return cls(**device_spec)
+
+
+class DriveGroupValidationError(Exception):
+ """
+ Defining an exception here is a bit problematic, cause you cannot properly catch it,
+ if it was raised in a different mgr module.
+ """
+
+ def __init__(self, msg):
+ super(DriveGroupValidationError, self).__init__('Failed to validate Drive Group: ' + msg)
+
+class DriveGroupSpec(object):
+ """
+ Describe a drive group in the same form that ceph-volume
+ understands.
+ """
+ def __init__(self, host_pattern, data_devices=None, db_devices=None, wal_devices=None, journal_devices=None,
+ data_directories=None, osds_per_device=None, objectstore='bluestore', encrypted=False,
+ db_slots=None, wal_slots=None):
+ # type: (str, Optional[DeviceSelection], Optional[DeviceSelection], Optional[DeviceSelection], Optional[DeviceSelection], Optional[List[str]], int, str, bool, int, int) -> None
+
+ # concept of applying a drive group to a (set) of hosts is tightly
+ # linked to the drive group itself
+ #
+ #: An fnmatch pattern to select hosts. Can also be a single host.
+ self.host_pattern = host_pattern
+
+ #: A :class:`orchestrator.DeviceSelection`
+ self.data_devices = data_devices
+
+ #: A :class:`orchestrator.DeviceSelection`
+ self.db_devices = db_devices
+
+ #: A :class:`orchestrator.DeviceSelection`
+ self.wal_devices = wal_devices
+
+ #: A :class:`orchestrator.DeviceSelection`
+ self.journal_devices = journal_devices
+
+ #: Number of osd daemons per "DATA" device.
+ #: To fully utilize nvme devices multiple osds are required.
+ self.osds_per_device = osds_per_device
+
+ #: A list of strings, containing paths which should back OSDs
+ self.data_directories = data_directories
+
+ #: ``filestore`` or ``bluestore``
+ self.objectstore = objectstore
+
+ #: ``true`` or ``false``
+ self.encrypted = encrypted
+
+ #: How many OSDs per DB device
+ self.db_slots = db_slots
+
+ #: How many OSDs per WAL device
+ self.wal_slots = wal_slots
+
+ # FIXME: needs ceph-volume support
+ #: Optional: mapping of drive to OSD ID, used when the
+ #: created OSDs are meant to replace previous OSDs on
+ #: the same node.
+ self.osd_id_claims = {}
+
+ @classmethod
+ def from_json(self, json_drive_group):
+ """
+ Initialize 'Drive group' structure
+
+ :param json_drive_group: A valid json string with a Drive Group
+ specification
+ """
+ args = {k: (DeviceSelection.from_json(v) if k.endswith('_devices') else v) for k, v in
+ json_drive_group.items()}
+ return DriveGroupSpec(**args)
+
+ def hosts(self, all_hosts):
+ return fnmatch.filter(all_hosts, self.host_pattern)
+
+ def validate(self, all_hosts):
+ if not isinstance(self.host_pattern, six.string_types):
+ raise DriveGroupValidationError('host_pattern must be of type string')
+
+ specs = [self.data_devices, self.db_devices, self.wal_devices, self.journal_devices]
+ for s in filter(None, specs):
+ s.validate()
+ if self.objectstore not in ('filestore', 'bluestore'):
+ raise DriveGroupValidationError("objectstore not in ('filestore', 'bluestore')")
+ if not self.hosts(all_hosts):
+ raise DriveGroupValidationError(
+ "host_pattern '{}' does not match any hosts".format(self.host_pattern))
+
+
+class StatelessServiceSpec(object):
+ # Request to orchestrator for a group of stateless services
+ # such as MDS, RGW, nfs gateway, iscsi gateway
+ """
+ Details of stateless service creation.
+
+ This is *not* supposed to contain all the configuration
+ of the services: it's just supposed to be enough information to
+ execute the binaries.
+ """
+
+ def __init__(self):
+ self.placement = PlacementSpec()
+
+ # Give this set of statelss services a name: typically it would
+ # be the name of a CephFS filesystem, RGW zone, etc. Must be unique
+ # within one ceph cluster.
+ self.name = ""
+
+ # Count of service instances
+ self.count = 1
+
+ # Arbitrary JSON-serializable object.
+ # Maybe you're using e.g. kubenetes and you want to pass through
+ # some replicaset special sauce for autoscaling?
+ self.extended = {}
+
+
+class InventoryFilter(object):
+ """
+ When fetching inventory, use this filter to avoid unnecessarily
+ scanning the whole estate.
+
+ Typical use: filter by node when presenting UI workflow for configuring
+ a particular server.
+ filter by label when not all of estate is Ceph servers,
+ and we want to only learn about the Ceph servers.
+ filter by label when we are interested particularly
+ in e.g. OSD servers.
+
+ """
+ def __init__(self, labels=None, nodes=None):
+ # type: (List[str], List[str]) -> None
+ self.labels = labels # Optional: get info about nodes matching labels
+ self.nodes = nodes # Optional: get info about certain named nodes only
+
+
+class InventoryDevice(object):
+ """
+ When fetching inventory, block devices are reported in this format.
+
+ Note on device identifiers: the format of this is up to the orchestrator,
+ but the same identifier must also work when passed into StatefulServiceSpec.
+ The identifier should be something meaningful like a device WWID or
+ stable device node path -- not something made up by the orchestrator.
+
+ "Extended" is for reporting any special configuration that may have
+ already been done out of band on the block device. For example, if
+ the device has already been configured for encryption, report that
+ here so that it can be indicated to the user. The set of
+ extended properties may differ between orchestrators. An orchestrator
+ is permitted to support no extended properties (only normal block
+ devices)
+ """
+ def __init__(self, blank=False, type=None, id=None, size=None,
+ rotates=False, available=False, dev_id=None, extended=None,
+ metadata_space_free=None):
+ # type: (bool, str, str, int, bool, bool, str, dict, bool) -> None
+
+ self.blank = blank
+
+ #: 'ssd', 'hdd', 'nvme'
+ self.type = type
+
+ #: unique within a node (or globally if you like).
+ self.id = id
+
+ #: byte integer.
+ self.size = size
+
+ #: indicates if it is a spinning disk
+ self.rotates = rotates
+
+ #: can be used to create a new OSD?
+ self.available = available
+
+ #: vendor/model
+ self.dev_id = dev_id
+
+ #: arbitrary JSON-serializable object
+ self.extended = extended if extended is not None else extended
+
+ # If this drive is not empty, but is suitable for appending
+ # additional journals, wals, or bluestore dbs, then report
+ # how much space is available.
+ self.metadata_space_free = metadata_space_free
+
+ def to_json(self):
+ return dict(type=self.type, blank=self.blank, id=self.id,
+ size=self.size, rotates=self.rotates,
+ available=self.available, dev_id=self.dev_id,
+ extended=self.extended)
+
+ @classmethod
+ def from_ceph_volume_inventory(cls, data):
+ # TODO: change InventoryDevice itself to mirror c-v inventory closely!
+
+ dev = InventoryDevice()
+ dev.id = data["path"]
+ dev.type = 'hdd' if data["sys_api"]["rotational"] == "1" else 'sdd/nvme'
+ dev.size = data["sys_api"]["size"]
+ dev.rotates = data["sys_api"]["rotational"] == "1"
+ dev.available = data["available"]
+ dev.dev_id = "%s/%s" % (data["sys_api"]["vendor"],
+ data["sys_api"]["model"])
+ dev.extended = data
+ return dev
+
+ @classmethod
+ def from_ceph_volume_inventory_list(cls, datas):
+ return [cls.from_ceph_volume_inventory(d) for d in datas]
+
+ def pretty_print(self, only_header=False):
+ """Print a human friendly line with the information of the device
+
+ :param only_header: Print only the name of the device attributes
+
+ Ex::
+
+ Device Path Type Size Rotates Available Model
+ /dev/sdc hdd 50.00 GB True True ATA/QEMU
+
+ """
+ row_format = " {0:<15} {1:>10} {2:>10} {3:>10} {4:>10} {5:<15}\n"
+ if only_header:
+ return row_format.format("Device Path", "Type", "Size", "Rotates",
+ "Available", "Model")
+ else:
+ return row_format.format(str(self.id), self.type if self.type is not None else "",
+ format_bytes(self.size if self.size is not None else 0, 5,
+ colored=False),
+ str(self.rotates), str(self.available),
+ self.dev_id if self.dev_id is not None else "")
+
+
+class InventoryNode(object):
+ """
+ When fetching inventory, all Devices are groups inside of an
+ InventoryNode.
+ """
+ def __init__(self, name, devices):
+ # type: (str, List[InventoryDevice]) -> None
+ assert isinstance(devices, list)
+ self.name = name # unique within cluster. For example a hostname.
+ self.devices = devices
+
+ def to_json(self):
+ return {'name': self.name, 'devices': [d.to_json() for d in self.devices]}
+
+ @classmethod
+ def from_nested_items(cls, hosts):
+ devs = InventoryDevice.from_ceph_volume_inventory_list
+ return [cls(item[0], devs(item[1].data)) for item in hosts]
+
+
+def _mk_orch_methods(cls):
+ # Needs to be defined outside of for.
+ # Otherwise meth is always bound to last key
+ def shim(method_name):
+ def inner(self, *args, **kwargs):
+ completion = self._oremote(method_name, args, kwargs)
+ self._update_completion_progress(completion, 0)
+ return completion
+ return inner
+
+ for meth in Orchestrator.__dict__:
+ if not meth.startswith('_') and meth not in ['is_orchestrator_module']:
+ setattr(cls, meth, shim(meth))
+ return cls
+
+
+@_mk_orch_methods
+class OrchestratorClientMixin(Orchestrator):
+ """
+ A module that inherents from `OrchestratorClientMixin` can directly call
+ all :class:`Orchestrator` methods without manually calling remote.
+
+ Every interface method from ``Orchestrator`` is converted into a stub method that internally
+ calls :func:`OrchestratorClientMixin._oremote`
+
+ >>> class MyModule(OrchestratorClientMixin):
+ ... def func(self):
+ ... completion = self.add_host('somehost') # calls `_oremote()`
+ ... self._orchestrator_wait([completion])
+ ... self.log.debug(completion.result)
+
+ """
+
+ def set_mgr(self, mgr):
+ # type: (MgrModule) -> None
+ """
+ Useable in the Dashbord that uses a global ``mgr``
+ """
+
+ self.__mgr = mgr # Make sure we're not overwriting any other `mgr` properties
+
+ def _oremote(self, meth, args, kwargs):
+ """
+ Helper for invoking `remote` on whichever orchestrator is enabled
+
+ :raises RuntimeError: If the remote method failed.
+ :raises OrchestratorError: orchestrator failed to perform
+ :raises ImportError: no `orchestrator_cli` module or backend not found.
+ """
+ try:
+ mgr = self.__mgr
+ except AttributeError:
+ mgr = self
+ try:
+ o = mgr._select_orchestrator()
+ except AttributeError:
+ o = mgr.remote('orchestrator_cli', '_select_orchestrator')
+
+ if o is None:
+ raise NoOrchestrator()
+
+ mgr.log.debug("_oremote {} -> {}.{}(*{}, **{})".format(mgr.module_name, o, meth, args, kwargs))
+ return mgr.remote(o, meth, *args, **kwargs)
+
+ def _update_completion_progress(self, completion, force_progress=None):
+ # type: (WriteCompletion, Optional[float]) -> None
+ try:
+ progress = force_progress if force_progress is not None else completion.progress
+ if completion.is_complete:
+ self.remote("progress", "complete", completion.progress_id)
+ else:
+ self.remote("progress", "update", completion.progress_id, str(completion), progress,
+ ["orchestrator"])
+ except AttributeError:
+ # No WriteCompletion. Ignore.
+ pass
+ except ImportError:
+ # If the progress module is disabled that's fine,
+ # they just won't see the output.
+ pass
+
+ def _orchestrator_wait(self, completions):
+ # type: (List[_Completion]) -> None
+ """
+ Wait for completions to complete (reads) or
+ become persistent (writes).
+
+ Waits for writes to be *persistent* but not *effective*.
+
+ :param completions: List of Completions
+ :raises NoOrchestrator:
+ :raises ImportError: no `orchestrator_cli` module or backend not found.
+ """
+ for c in completions:
+ self._update_completion_progress(c)
+ while not self.wait(completions):
+ if any(c.should_wait for c in completions):
+ time.sleep(5)
+ else:
+ break
+ for c in completions:
+ self._update_completion_progress(c)
+
+
+class OutdatableData(object):
+ DATEFMT = '%Y-%m-%d %H:%M:%S.%f'
+
+ def __init__(self, data=None, last_refresh=None):
+ # type: (Optional[dict], Optional[datetime.datetime]) -> None
+ self._data = data
+ if data is not None and last_refresh is None:
+ self.last_refresh = datetime.datetime.utcnow()
+ else:
+ self.last_refresh = last_refresh
+
+ def json(self):
+ if self.last_refresh is not None:
+ timestr = self.last_refresh.strftime(self.DATEFMT)
+ else:
+ timestr = None
+
+ return {
+ "data": self._data,
+ "last_refresh": timestr,
+ }
+
+ @property
+ def data(self):
+ return self._data
+
+ # @data.setter
+ # No setter, as it doesn't work as expected: It's not saved in store automatically
+
+ @classmethod
+ def time_from_string(cls, timestr):
+ if timestr is None:
+ return None
+ # drop the 'Z' timezone indication, it's always UTC
+ timestr = timestr.rstrip('Z')
+ return datetime.datetime.strptime(timestr, cls.DATEFMT)
+
+
+ @classmethod
+ def from_json(cls, data):
+ return cls(data['data'], cls.time_from_string(data['last_refresh']))
+
+ def outdated(self, timeout_min=None):
+ if timeout_min is None:
+ timeout_min = 10
+ if self.last_refresh is None:
+ return True
+ cutoff = datetime.datetime.utcnow() - datetime.timedelta(
+ minutes=timeout_min)
+ return self.last_refresh < cutoff
+
+ def __repr__(self):
+ return 'OutdatableData(data={}, last_refresh={})'.format(self._data, self.last_refresh)
+
+
+class OutdatableDictMixin(object):
+ """
+ Toolbox for implementing a cache. As every orchestrator has
+ different needs, we cannot implement any logic here.
+ """
+
+ def __getitem__(self, item):
+ # type: (str) -> OutdatableData
+ return OutdatableData.from_json(super(OutdatableDictMixin, self).__getitem__(item))
+
+ def __setitem__(self, key, value):
+ # type: (str, OutdatableData) -> None
+ val = None if value is None else value.json()
+ super(OutdatableDictMixin, self).__setitem__(key, val)
+
+ def items(self):
+ # type: () -> Iterator[Tuple[str, OutdatableData]]
+ for item in super(OutdatableDictMixin, self).items():
+ k, v = item
+ yield k, OutdatableData.from_json(v)
+
+ def items_filtered(self, keys=None):
+ if keys:
+ return [(host, self[host]) for host in keys]
+ else:
+ return list(self.items())
+
+ def any_outdated(self, timeout=None):
+ items = self.items()
+ if not list(items):
+ return True
+ return any([i[1].outdated(timeout) for i in items])
+
+ def remove_outdated(self):
+ outdated = [item[0] for item in self.items() if item[1].outdated()]
+ for o in outdated:
+ del self[o]
+
+class OutdatablePersistentDict(OutdatableDictMixin, PersistentStoreDict):
+ pass
+
+class OutdatableDict(OutdatableDictMixin, dict):
+ pass
diff --git a/src/pybind/mgr/orchestrator_cli/.gitignore b/src/pybind/mgr/orchestrator_cli/.gitignore
new file mode 100644
index 00000000..43a2d269
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/.gitignore
@@ -0,0 +1 @@
+wheelhouse*
diff --git a/src/pybind/mgr/orchestrator_cli/CMakeLists.txt b/src/pybind/mgr/orchestrator_cli/CMakeLists.txt
new file mode 100644
index 00000000..195b79ad
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(MGR_ORCHESTRATOR_CLI_VIRTUALENV ${CEPH_BUILD_VIRTUALENV}/mgr-orchestrator_cli-virtualenv)
+
+add_custom_target(mgr-orchestrator_cli-test-venv
+ COMMAND ${CMAKE_SOURCE_DIR}/src/tools/setup-virtualenv.sh --python=${MGR_PYTHON_EXECUTABLE} ${MGR_ORCHESTRATOR_CLI_VIRTUALENV}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/orchestrator_cli
+ COMMENT "orchestrator_cli tests virtualenv is being created")
+add_dependencies(tests mgr-orchestrator_cli-test-venv)
diff --git a/src/pybind/mgr/orchestrator_cli/README.md b/src/pybind/mgr/orchestrator_cli/README.md
new file mode 100644
index 00000000..e4cbcdfc
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/README.md
@@ -0,0 +1,16 @@
+# Orchestrator CLI
+
+See also [../../../doc/mgr/orchestrator_cli.rst](../../../doc/mgr/orchestrator_cli.rst).
+
+## Running the Teuthology tests
+
+To run the API tests against a real Ceph cluster, we leverage the Teuthology
+framework and the `test_orchestrator` backend.
+
+``source`` the script and run the tests manually::
+
+ $ pushd ../dashboard ; source ./run-backend-api-tests.sh ; popd
+ $ run_teuthology_tests tasks.mgr.test_orchestrator_cli
+ $ cleanup_teuthology
+
+ \ No newline at end of file
diff --git a/src/pybind/mgr/orchestrator_cli/__init__.py b/src/pybind/mgr/orchestrator_cli/__init__.py
new file mode 100644
index 00000000..07c29b47
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/__init__.py
@@ -0,0 +1,10 @@
+from __future__ import absolute_import
+import os
+
+if 'UNITTEST' not in os.environ:
+ from .module import OrchestratorCli
+else:
+ import sys
+ import mock
+ sys.path.append("..")
+ sys.modules['ceph_module'] = mock.Mock()
diff --git a/src/pybind/mgr/orchestrator_cli/module.py b/src/pybind/mgr/orchestrator_cli/module.py
new file mode 100644
index 00000000..6225b5ad
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/module.py
@@ -0,0 +1,437 @@
+import errno
+import json
+
+try:
+ from typing import Dict, List
+except ImportError:
+ pass # just for type checking.
+
+from functools import wraps
+
+from mgr_module import MgrModule, HandleCommandResult, CLICommand
+
+import orchestrator
+
+
+def handle_exception(prefix, cmd_args, desc, perm, func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except (orchestrator.OrchestratorError, ImportError) as e:
+ # Do not print Traceback for expected errors.
+ return HandleCommandResult(-errno.ENOENT, stderr=str(e))
+ except NotImplementedError:
+ msg = 'This Orchestrator does not support `{}`'.format(prefix)
+ return HandleCommandResult(-errno.ENOENT, stderr=msg)
+
+ return CLICommand(prefix, cmd_args, desc, perm)(wrapper)
+
+
+def _cli_command(perm):
+ def inner_cli_command(prefix, cmd_args="", desc=""):
+ return lambda func: handle_exception(prefix, cmd_args, desc, perm, func)
+ return inner_cli_command
+
+
+_read_cli = _cli_command('r')
+_write_cli = _cli_command('rw')
+
+class OrchestratorCli(orchestrator.OrchestratorClientMixin, MgrModule):
+ MODULE_OPTIONS = [
+ {'name': 'orchestrator'}
+ ]
+
+ def _select_orchestrator(self):
+ return self.get_module_option("orchestrator")
+
+ @_write_cli('orchestrator host add',
+ "name=host,type=CephString,req=true",
+ 'Add a host')
+ def _add_host(self, host):
+ completion = self.add_host(host)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult(stdout=str(completion.result))
+
+ @_write_cli('orchestrator host rm',
+ "name=host,type=CephString,req=true",
+ 'Remove a host')
+ def _remove_host(self, host):
+ completion = self.remove_host(host)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult(stdout=str(completion.result))
+
+ @_read_cli('orchestrator host ls',
+ desc='List hosts')
+ def _get_hosts(self):
+ completion = self.get_hosts()
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ result = "\n".join(map(lambda node: node.name, completion.result))
+ return HandleCommandResult(stdout=result)
+
+ @_read_cli('orchestrator device ls',
+ "name=host,type=CephString,n=N,req=false "
+ "name=format,type=CephChoices,strings=json|plain,req=false "
+ "name=refresh,type=CephBool,req=false",
+ 'List devices on a node')
+ def _list_devices(self, host=None, format='plain', refresh=False):
+ # type: (List[str], str, bool) -> HandleCommandResult
+ """
+ Provide information about storage devices present in cluster hosts
+
+ Note: this does not have to be completely synchronous. Slightly out of
+ date hardware inventory is fine as long as hardware ultimately appears
+ in the output of this command.
+ """
+ nf = orchestrator.InventoryFilter(nodes=host) if host else None
+
+ completion = self.get_inventory(node_filter=nf, refresh=refresh)
+
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+
+ if format == 'json':
+ data = [n.to_json() for n in completion.result]
+ return HandleCommandResult(stdout=json.dumps(data))
+ else:
+ # Return a human readable version
+ result = ""
+
+ for inventory_node in completion.result:
+ result += "Host {0}:\n".format(inventory_node.name)
+
+ if inventory_node.devices:
+ result += inventory_node.devices[0].pretty_print(only_header=True)
+ else:
+ result += "No storage devices found"
+
+ for d in inventory_node.devices:
+ result += d.pretty_print()
+ result += "\n"
+
+ return HandleCommandResult(stdout=result)
+
+ @_read_cli('orchestrator service ls',
+ "name=host,type=CephString,req=false "
+ "name=svc_type,type=CephChoices,strings=mon|mgr|osd|mds|iscsi|nfs|rgw|rbd-mirror,req=false "
+ "name=svc_id,type=CephString,req=false "
+ "name=format,type=CephChoices,strings=json|plain,req=false "
+ "name=refresh,type=CephBool,req=false",
+ 'List services known to orchestrator')
+ def _list_services(self, host=None, svc_type=None, svc_id=None, format='plain', refresh=False):
+ # XXX this is kind of confusing for people because in the orchestrator
+ # context the service ID for MDS is the filesystem ID, not the daemon ID
+
+ completion = self.describe_service(svc_type, svc_id, host, refresh=refresh)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ services = completion.result
+
+ # Sort the list for display
+ services.sort(key=lambda s: (s.service_type, s.nodename, s.service_instance))
+
+ if len(services) == 0:
+ return HandleCommandResult(stdout="No services reported")
+ elif format == 'json':
+ data = [s.to_json() for s in services]
+ return HandleCommandResult(stdout=json.dumps(data))
+ else:
+ lines = []
+ for s in services:
+ if s.service == None:
+ service_id = s.service_instance
+ else:
+ service_id = "{0}.{1}".format(s.service, s.service_instance)
+
+ lines.append("{0} {1} {2} {3} {4} {5}".format(
+ s.service_type,
+ service_id,
+ s.nodename,
+ s.container_id,
+ s.version,
+ s.rados_config_location))
+
+ return HandleCommandResult(stdout="\n".join(lines))
+
+ @_write_cli('orchestrator osd create',
+ "name=svc_arg,type=CephString,req=false",
+ 'Create an OSD service. Either --svc_arg=host:drives or -i <drive_group>')
+ def _create_osd(self, svc_arg=None, inbuf=None):
+ # type: (str, str) -> HandleCommandResult
+ """Create one or more OSDs"""
+
+ usage = """
+Usage:
+ ceph orchestrator osd create -i <json_file>
+ ceph orchestrator osd create host:device1,device2,...
+"""
+
+ if inbuf:
+ try:
+ drive_group = orchestrator.DriveGroupSpec.from_json(json.loads(inbuf))
+ except ValueError as e:
+ msg = 'Failed to read JSON input: {}'.format(str(e)) + usage
+ return HandleCommandResult(-errno.EINVAL, stderr=msg)
+
+ elif svc_arg:
+ try:
+ node_name, block_device = svc_arg.split(":")
+ block_devices = block_device.split(',')
+ except (TypeError, KeyError, ValueError):
+ msg = "Invalid host:device spec: '{}'".format(svc_arg) + usage
+ return HandleCommandResult(-errno.EINVAL, stderr=msg)
+
+ devs = orchestrator.DeviceSelection(paths=block_devices)
+ drive_group = orchestrator.DriveGroupSpec(node_name, data_devices=devs)
+ else:
+ return HandleCommandResult(-errno.EINVAL, stderr=usage)
+
+ # TODO: Remove this and make the orchestrator composable
+ # Like a future or so.
+ host_completion = self.get_hosts()
+ self._orchestrator_wait([host_completion])
+ orchestrator.raise_if_exception(host_completion)
+ all_hosts = [h.name for h in host_completion.result]
+
+ try:
+ drive_group.validate(all_hosts)
+ except orchestrator.DriveGroupValidationError as e:
+ return HandleCommandResult(-errno.EINVAL, stderr=str(e))
+
+ completion = self.create_osds(drive_group, all_hosts)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ self.log.warning(str(completion.result))
+ return HandleCommandResult(stdout=str(completion.result))
+
+ @_write_cli('orchestrator osd rm',
+ "name=svc_id,type=CephString,n=N",
+ 'Remove OSD services')
+ def _osd_rm(self, svc_id):
+ # type: (List[str]) -> HandleCommandResult
+ """
+ Remove OSD's
+ :cmd : Arguments for remove the osd
+ """
+ completion = self.remove_osds(svc_id)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult(stdout=str(completion.result))
+
+ def _add_stateless_svc(self, svc_type, spec):
+ completion = self.add_stateless_service(svc_type, spec)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult()
+
+ @_write_cli('orchestrator mds add',
+ "name=svc_arg,type=CephString",
+ 'Create an MDS service')
+ def _mds_add(self, svc_arg):
+ spec = orchestrator.StatelessServiceSpec()
+ spec.name = svc_arg
+ return self._add_stateless_svc("mds", spec)
+
+ @_write_cli('orchestrator rgw add',
+ "name=svc_arg,type=CephString",
+ 'Create an RGW service')
+ def _rgw_add(self, svc_arg):
+ spec = orchestrator.StatelessServiceSpec()
+ spec.name = svc_arg
+ return self._add_stateless_svc("rgw", spec)
+
+ @_write_cli('orchestrator nfs add',
+ "name=svc_arg,type=CephString "
+ "name=pool,type=CephString "
+ "name=namespace,type=CephString,req=false",
+ 'Create an NFS service')
+ def _nfs_add(self, svc_arg, pool, namespace=None):
+ spec = orchestrator.StatelessServiceSpec()
+ spec.name = svc_arg
+ spec.extended = { "pool":pool }
+ if namespace is not None:
+ spec.extended["namespace"] = namespace
+ return self._add_stateless_svc("nfs", spec)
+
+ def _rm_stateless_svc(self, svc_type, svc_id):
+ completion = self.remove_stateless_service(svc_type, svc_id)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult()
+
+ @_write_cli('orchestrator mds rm',
+ "name=svc_id,type=CephString",
+ 'Remove an MDS service')
+ def _mds_rm(self, svc_id):
+ return self._rm_stateless_svc("mds", svc_id)
+
+ @_write_cli('orchestrator rgw rm',
+ "name=svc_id,type=CephString",
+ 'Remove an RGW service')
+ def _rgw_rm(self, svc_id):
+ return self._rm_stateless_svc("rgw", svc_id)
+
+ @_write_cli('orchestrator nfs rm',
+ "name=svc_id,type=CephString",
+ 'Remove an NFS service')
+ def _nfs_rm(self, svc_id):
+ return self._rm_stateless_svc("nfs", svc_id)
+
+ @_write_cli('orchestrator nfs update',
+ "name=svc_id,type=CephString "
+ "name=num,type=CephInt",
+ 'Scale an NFS service')
+ def _nfs_update(self, svc_id, num):
+ spec = orchestrator.StatelessServiceSpec()
+ spec.name = svc_id
+ spec.count = num
+ completion = self.update_stateless_service("nfs", spec)
+ self._orchestrator_wait([completion])
+ return HandleCommandResult()
+
+ @_write_cli('orchestrator service',
+ "name=action,type=CephChoices,strings=start|stop|reload "
+ "name=svc_type,type=CephString "
+ "name=svc_name,type=CephString",
+ 'Start, stop or reload an entire service (i.e. all daemons)')
+ def _service_action(self, action, svc_type, svc_name):
+ completion = self.service_action(action, svc_type, service_name=svc_name)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult()
+
+ @_write_cli('orchestrator service-instance',
+ "name=action,type=CephChoices,strings=start|stop|reload "
+ "name=svc_type,type=CephString "
+ "name=svc_id,type=CephString",
+ 'Start, stop or reload a specific service instance')
+ def _service_instance_action(self, action, svc_type, svc_id):
+ completion = self.service_action(action, svc_type, service_id=svc_id)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult()
+
+ @_write_cli('orchestrator mgr update',
+ "name=num,type=CephInt,req=true "
+ "name=hosts,type=CephString,n=N,req=false",
+ 'Update the number of manager instances')
+ def _update_mgrs(self, num, hosts=None):
+ hosts = hosts if hosts is not None else []
+
+ if num <= 0:
+ return HandleCommandResult(-errno.EINVAL,
+ stderr="Invalid number of mgrs: require {} > 0".format(num))
+
+ completion = self.update_mgrs(num, hosts)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult(stdout=str(completion.result))
+
+ @_write_cli('orchestrator mon update',
+ "name=num,type=CephInt,req=true "
+ "name=hosts,type=CephString,n=N,req=false",
+ 'Update the number of monitor instances')
+ def _update_mons(self, num, hosts=None):
+ hosts = hosts if hosts is not None else []
+
+ if num <= 0:
+ return HandleCommandResult(-errno.EINVAL,
+ stderr="Invalid number of mons: require {} > 0".format(num))
+
+ def split_host(host):
+ """Split host into host and network parts"""
+ # TODO: stricter validation
+ parts = host.split(":")
+ if len(parts) == 1:
+ return (parts[0], None)
+ elif len(parts) == 2:
+ return (parts[0], parts[1])
+ else:
+ raise RuntimeError("Invalid host specification: "
+ "'{}'".format(host))
+
+ if hosts:
+ try:
+ hosts = list(map(split_host, hosts))
+ except Exception as e:
+ msg = "Failed to parse host list: '{}': {}".format(hosts, e)
+ return HandleCommandResult(-errno.EINVAL, stderr=msg)
+
+ completion = self.update_mons(num, hosts)
+ self._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ return HandleCommandResult(stdout=str(completion.result))
+
+ @_write_cli('orchestrator set backend',
+ "name=module_name,type=CephString,req=true",
+ 'Select orchestrator module backend')
+ def _set_backend(self, module_name):
+ """
+ We implement a setter command instead of just having the user
+ modify the setting directly, so that we can validate they're setting
+ it to a module that really exists and is enabled.
+
+ There isn't a mechanism for ensuring they don't *disable* the module
+ later, but this is better than nothing.
+ """
+ mgr_map = self.get("mgr_map")
+
+ if module_name is None or module_name == "":
+ self.set_module_option("orchestrator", None)
+ return HandleCommandResult()
+
+ for module in mgr_map['available_modules']:
+ if module['name'] != module_name:
+ continue
+
+ if not module['can_run']:
+ continue
+
+ enabled = module['name'] in mgr_map['modules']
+ if not enabled:
+ return HandleCommandResult(-errno.EINVAL,
+ stderr="Module '{module_name}' is not enabled. \n Run "
+ "`ceph mgr module enable {module_name}` "
+ "to enable.".format(module_name=module_name))
+
+ try:
+ is_orchestrator = self.remote(module_name,
+ "is_orchestrator_module")
+ except NameError:
+ is_orchestrator = False
+
+ if not is_orchestrator:
+ return HandleCommandResult(-errno.EINVAL,
+ stderr="'{0}' is not an orchestrator module".format(module_name))
+
+ self.set_module_option("orchestrator", module_name)
+
+ return HandleCommandResult()
+
+ return HandleCommandResult(-errno.EINVAL, stderr="Module '{0}' not found".format(module_name))
+
+ @_read_cli('orchestrator status',
+ desc='Report configured backend and its status')
+ def _status(self):
+ o = self._select_orchestrator()
+ if o is None:
+ raise orchestrator.NoOrchestrator()
+
+ avail, why = self.available()
+ if avail is None:
+ # The module does not report its availability
+ return HandleCommandResult(stdout="Backend: {0}".format(o))
+ else:
+ return HandleCommandResult(stdout="Backend: {0}\nAvailable: {1}{2}".format(
+ o, avail,
+ " ({0})".format(why) if not avail else ""
+ ))
+
+ def self_test(self):
+ old_orch = self._select_orchestrator()
+ self._set_backend('')
+ assert self._select_orchestrator() is None
+ self._set_backend(old_orch)
diff --git a/src/pybind/mgr/orchestrator_cli/requirements.txt b/src/pybind/mgr/orchestrator_cli/requirements.txt
new file mode 100644
index 00000000..e75b578d
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/requirements.txt
@@ -0,0 +1,2 @@
+tox==2.9.1
+importlib_metadata==2.1.0
diff --git a/src/pybind/mgr/orchestrator_cli/run-tox.sh b/src/pybind/mgr/orchestrator_cli/run-tox.sh
new file mode 100644
index 00000000..32b24f55
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/run-tox.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+function dump_envvars {
+ echo "WITH_PYTHON2: ->$WITH_PYTHON2<-"
+ echo "WITH_PYTHON3: ->$WITH_PYTHON3<-"
+ echo "TOX_PATH: ->$TOX_PATH<-"
+ echo "ENV_LIST: ->$ENV_LIST<-"
+}
+
+# run from ./ or from ../
+: ${MGR_ORCHESTRATOR_CLI_VIRTUALENV:=$CEPH_BUILD_DIR/mgr-orchestrator_cli-virtualenv}
+: ${WITH_PYTHON2:=ON}
+: ${WITH_PYTHON3:=3}
+: ${CEPH_BUILD_DIR:=$PWD/.tox}
+test -d orchestrator_cli && cd orchestrator_cli
+
+if [ -e tox.ini ]; then
+ TOX_PATH=$(readlink -f tox.ini)
+else
+ TOX_PATH=$(readlink -f $(dirname $0)/tox.ini)
+fi
+
+# tox.ini will take care of this.
+unset PYTHONPATH
+export CEPH_BUILD_DIR=$CEPH_BUILD_DIR
+
+if [ -f ${MGR_ORCHESTRATOR_CLI_VIRTUALENV}/bin/activate ]
+then
+ source ${MGR_ORCHESTRATOR_CLI_VIRTUALENV}/bin/activate
+fi
+
+if [ "$WITH_PYTHON2" = "ON" ]; then
+ ENV_LIST+="py27,"
+fi
+# WITH_PYTHON3 might be set to "ON" or to the python3 RPM version number
+# prevailing on the system - e.g. "3", "36"
+if [[ "$WITH_PYTHON3" =~ (^3|^ON) ]]; then
+ ENV_LIST+="py3,"
+fi
+# use bash string manipulation to strip off any trailing comma
+ENV_LIST=${ENV_LIST%,}
+
+tox -c "${TOX_PATH}" -e "${ENV_LIST}" "$@"
+TOX_STATUS="$?"
+test "$TOX_STATUS" -ne "0" && dump_envvars
+exit $TOX_STATUS
diff --git a/src/pybind/mgr/orchestrator_cli/test_orchestrator.py b/src/pybind/mgr/orchestrator_cli/test_orchestrator.py
new file mode 100644
index 00000000..834cd4d7
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/test_orchestrator.py
@@ -0,0 +1,48 @@
+from __future__ import absolute_import
+import pytest
+
+
+from orchestrator import DriveGroupSpec, DeviceSelection, DriveGroupValidationError, \
+ InventoryDevice, ReadCompletion, raise_if_exception
+
+
+def test_DriveGroup():
+ dg_json = {
+ 'host_pattern': 'hostname',
+ 'data_devices': {'paths': ['/dev/sda']}
+ }
+
+ dg = DriveGroupSpec.from_json(dg_json)
+ assert dg.hosts(['hostname']) == ['hostname']
+ assert dg.data_devices.paths == ['/dev/sda']
+
+
+def test_DriveGroup_fail():
+ with pytest.raises(TypeError):
+ DriveGroupSpec.from_json({})
+
+
+def test_drivegroup_pattern():
+ dg = DriveGroupSpec('node[1-3]', DeviceSelection())
+ assert dg.hosts(['node{}'.format(i) for i in range(10)]) == ['node1', 'node2', 'node3']
+
+
+def test_drive_selection():
+ devs = DeviceSelection(paths=['/dev/sda'])
+ spec = DriveGroupSpec('node_name', data_devices=devs)
+ assert spec.data_devices.paths == ['/dev/sda']
+
+ with pytest.raises(DriveGroupValidationError, match='exclusive'):
+ DeviceSelection(paths=['/dev/sda'], rotates=False)
+
+def test_inventory_device():
+ i_d = InventoryDevice()
+ s = i_d.pretty_print()
+ assert len(s)
+
+
+def test_raise():
+ c = ReadCompletion()
+ c.exception = ZeroDivisionError()
+ with pytest.raises(ZeroDivisionError):
+ raise_if_exception(c)
diff --git a/src/pybind/mgr/orchestrator_cli/tox.ini b/src/pybind/mgr/orchestrator_cli/tox.ini
new file mode 100644
index 00000000..94dd70dd
--- /dev/null
+++ b/src/pybind/mgr/orchestrator_cli/tox.ini
@@ -0,0 +1,18 @@
+[tox]
+envlist = py27,py3
+skipsdist = true
+toxworkdir = {env:CEPH_BUILD_DIR}/orchestrator_cli
+minversion = 2.5
+
+[testenv]
+deps =
+ pytest
+ mock
+ requests-mock
+setenv=
+ UNITTEST = true
+ py27: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.2
+ py3: PYTHONPATH = {env:CEPH_LIB}/cython_modules/lib.3
+
+commands=
+ {envbindir}/py.test .
diff --git a/src/pybind/mgr/osd_perf_query/__init__.py b/src/pybind/mgr/osd_perf_query/__init__.py
new file mode 100644
index 00000000..691ef4dd
--- /dev/null
+++ b/src/pybind/mgr/osd_perf_query/__init__.py
@@ -0,0 +1 @@
+from .module import OSDPerfQuery
diff --git a/src/pybind/mgr/osd_perf_query/module.py b/src/pybind/mgr/osd_perf_query/module.py
new file mode 100644
index 00000000..ee5c8ba8
--- /dev/null
+++ b/src/pybind/mgr/osd_perf_query/module.py
@@ -0,0 +1,194 @@
+
+"""
+osd_perf_query module
+"""
+
+from itertools import groupby
+from time import time
+import errno
+import prettytable
+
+from mgr_module import MgrModule
+
+def get_human_readable(bytes, precision=2):
+ suffixes = ['', 'Ki', 'Mi', 'Gi', 'Ti']
+ suffix_index = 0
+ while bytes > 1024 and suffix_index < 4:
+ # increment the index of the suffix
+ suffix_index += 1
+ # apply the division
+ bytes = bytes / 1024.0
+ return '%.*f%s' % (precision, bytes, suffixes[suffix_index])
+
+class OSDPerfQuery(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "osd perf query add "
+ "name=query,type=CephChoices,"
+ "strings=client_id|rbd_image_id|all_subkeys",
+ "desc": "add osd perf query",
+ "perm": "w"
+ },
+ {
+ "cmd": "osd perf query remove "
+ "name=query_id,type=CephInt,req=true",
+ "desc": "remove osd perf query",
+ "perm": "w"
+ },
+ {
+ "cmd": "osd perf counters get "
+ "name=query_id,type=CephInt,req=true",
+ "desc": "fetch osd perf counters",
+ "perm": "w"
+ },
+ ]
+
+ CLIENT_ID_QUERY = {
+ 'key_descriptor': [
+ {'type': 'client_id', 'regex': '^(.+)$'},
+ ],
+ 'performance_counter_descriptors': [
+ 'bytes', 'write_ops', 'read_ops', 'write_bytes', 'read_bytes',
+ 'write_latency', 'read_latency',
+ ],
+ 'limit': {'order_by': 'bytes', 'max_count': 10},
+ }
+
+ RBD_IMAGE_ID_QUERY = {
+ 'key_descriptor': [
+ {'type': 'pool_id', 'regex': '^(.+)$'},
+ {'type': 'object_name',
+ 'regex': '^(?:rbd|journal)_data\.(?:([0-9]+)\.)?([^.]+)\.'},
+ ],
+ 'performance_counter_descriptors': [
+ 'bytes', 'write_ops', 'read_ops', 'write_bytes', 'read_bytes',
+ 'write_latency', 'read_latency',
+ ],
+ 'limit': {'order_by': 'bytes', 'max_count': 10},
+ }
+
+ ALL_SUBKEYS_QUERY = {
+ 'key_descriptor': [
+ {'type': 'client_id', 'regex': '^(.*)$'},
+ {'type': 'client_address', 'regex': '^(.*)$'},
+ {'type': 'pool_id', 'regex': '^(.*)$'},
+ {'type': 'namespace', 'regex': '^(.*)$'},
+ {'type': 'osd_id', 'regex': '^(.*)$'},
+ {'type': 'pg_id', 'regex': '^(.*)$'},
+ {'type': 'object_name', 'regex': '^(.*)$'},
+ {'type': 'snap_id', 'regex': '^(.*)$'},
+ ],
+ 'performance_counter_descriptors': [
+ 'write_ops', 'read_ops',
+ ],
+ }
+
+ queries = {}
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == "osd perf query add":
+ if cmd['query'] == 'rbd_image_id':
+ query = self.RBD_IMAGE_ID_QUERY
+ elif cmd['query'] == 'client_id':
+ query = self.CLIENT_ID_QUERY
+ else:
+ query = self.ALL_SUBKEYS_QUERY
+ query_id = self.add_osd_perf_query(query)
+ if query_id is None:
+ return -errno.EINVAL, "", "Invalid query"
+ self.queries[query_id] = [query, time()]
+ return 0, str(query_id), "added query " + cmd['query'] + " with id " + str(query_id)
+ elif cmd['prefix'] == "osd perf query remove":
+ if cmd['query_id'] not in self.queries:
+ return -errno.ENOENT, "", "unknown query id " + str(cmd['query_id'])
+ self.remove_osd_perf_query(cmd['query_id'])
+ del self.queries[cmd['query_id']]
+ return 0, "", "removed query with id " + str(cmd['query_id'])
+ elif cmd['prefix'] == "osd perf counters get":
+ if cmd['query_id'] not in self.queries:
+ return -errno.ENOENT, "", "unknown query id " + str(cmd['query_id'])
+
+ query = self.queries[cmd['query_id']][0]
+ res = self.get_osd_perf_counters(cmd['query_id'])
+ now = time()
+ last_update = self.queries[cmd['query_id']][1]
+ descriptors = query['performance_counter_descriptors']
+
+ if query == self.RBD_IMAGE_ID_QUERY:
+ column_names = ["pool_id", "rbd image_id"]
+ else:
+ column_names = [sk['type'] for sk in query['key_descriptor']]
+ for d in descriptors:
+ desc = d
+ if d in ['bytes']:
+ continue
+ elif d in ['write_bytes', 'read_bytes']:
+ desc += '/sec'
+ elif d in ['write_latency', 'read_latency']:
+ desc += '(msec)'
+ column_names.append(desc)
+
+ table = prettytable.PrettyTable(tuple(column_names),
+ hrules=prettytable.FRAME)
+
+ if query == self.RBD_IMAGE_ID_QUERY:
+ # typical output:
+ # {'k': [['3'], ['', '16fe5b5a8435e']],
+ # 'c': [[1024, 0], [1, 0], ...]}
+ # pool id fixup: if the object_name regex has matched pool id
+ # use it as the image pool id
+ for c in res['counters']:
+ if c['k'][1][0]:
+ c['k'][0][0] = c['k'][1][0]
+ # group by (pool_id, image_id)
+ processed = []
+ res['counters'].sort(key=lambda c: [c['k'][0][0], c['k'][1][1]])
+ for key, group in groupby(res['counters'],
+ lambda c: [c['k'][0][0], c['k'][1][1]]):
+ counters = [[0, 0] for x in descriptors]
+ for c in group:
+ for i in range(len(counters)):
+ counters[i][0] += c['c'][i][0]
+ counters[i][1] += c['c'][i][1]
+ processed.append({'k' : key, 'c' : counters})
+ else:
+ # typical output:
+ # {'k': [['client.94348']], 'c': [[1024, 0], [1, 0], ...]}
+ processed = res['counters']
+
+ max_count = len(processed)
+ if 'limit' in query:
+ if 'max_count' in query['limit']:
+ max_count = query['limit']['max_count']
+ if 'order_by' in query['limit']:
+ i = descriptors.index(query['limit']['order_by'])
+ processed.sort(key=lambda x: x['c'][i][0], reverse=True)
+ for c in processed[:max_count]:
+ if query == self.RBD_IMAGE_ID_QUERY:
+ row = c['k']
+ else:
+ row = [sk[0] for sk in c['k']]
+ counters = c['c']
+ for i in range(len(descriptors)):
+ if descriptors[i] in ['bytes']:
+ continue
+ elif descriptors[i] in ['write_bytes', 'read_bytes']:
+ bps = counters[i][0] / (now - last_update)
+ row.append(get_human_readable(bps))
+ elif descriptors[i] in ['write_latency', 'read_latency']:
+ lat = 0
+ if counters[i][1] > 0:
+ lat = 1.0 * counters[i][0] / counters[i][1] / 1000000
+ row.append("%.2f" % lat)
+ else:
+ row.append("%d" % counters[i][0])
+ table.add_row(row)
+
+ msg = "counters for the query id %d for the last %d sec" % \
+ (cmd['query_id'], now - last_update)
+ self.queries[cmd['query_id']][1] = now
+
+ return 0, table.get_string() + "\n", msg
+ else:
+ raise NotImplementedError(cmd['prefix'])
+
diff --git a/src/pybind/mgr/pg_autoscaler/__init__.py b/src/pybind/mgr/pg_autoscaler/__init__.py
new file mode 100644
index 00000000..e7c7b8fc
--- /dev/null
+++ b/src/pybind/mgr/pg_autoscaler/__init__.py
@@ -0,0 +1 @@
+from .module import PgAutoscaler
diff --git a/src/pybind/mgr/pg_autoscaler/module.py b/src/pybind/mgr/pg_autoscaler/module.py
new file mode 100644
index 00000000..3d5d5175
--- /dev/null
+++ b/src/pybind/mgr/pg_autoscaler/module.py
@@ -0,0 +1,507 @@
+"""
+Automatically scale pg_num based on how much data is stored in each pool.
+"""
+
+import errno
+import json
+import mgr_util
+import threading
+import uuid
+from six import itervalues, iteritems
+from collections import defaultdict
+from prettytable import PrettyTable, PLAIN_COLUMNS
+
+from mgr_module import MgrModule
+
+"""
+Some terminology is made up for the purposes of this module:
+
+ - "raw pgs": pg count after applying replication, i.e. the real resource
+ consumption of a pool.
+ - "grow/shrink" - increase/decrease the pg_num in a pool
+ - "crush subtree" - non-overlapping domains in crush hierarchy: used as
+ units of resource management.
+"""
+
+INTERVAL = 5
+
+PG_NUM_MIN = 32 # unless specified on a per-pool basis
+
+def nearest_power_of_two(n):
+ v = int(n)
+
+ v -= 1
+ v |= v >> 1
+ v |= v >> 2
+ v |= v >> 4
+ v |= v >> 8
+ v |= v >> 16
+
+ # High bound power of two
+ v += 1
+
+ # Low bound power of tow
+ x = v >> 1
+
+ return x if (v - n) > (n - x) else v
+
+def effective_target_ratio(target_ratio, total_target_ratio, total_target_bytes, capacity):
+ """
+ Returns the target ratio after normalizing for ratios across pools and
+ adjusting for capacity reserved by pools that have target_size_bytes set.
+ """
+ target_ratio = float(target_ratio)
+ if total_target_ratio:
+ target_ratio = target_ratio / total_target_ratio
+
+ if total_target_bytes and capacity:
+ fraction_available = 1.0 - min(1.0, float(total_target_bytes) / capacity)
+ target_ratio *= fraction_available
+
+ return target_ratio
+
+
+class PgAdjustmentProgress(object):
+ """
+ Keeps the initial and target pg_num values
+ """
+ def __init__(self, pg_num, pg_num_target, ev_id, increase_decrease):
+ self._ev_id = ev_id
+ self._pg_num = pg_num
+ self._pg_num_target = pg_num_target
+ self._increase_decrease = increase_decrease
+
+
+class PgAutoscaler(MgrModule):
+ """
+ PG autoscaler.
+ """
+ COMMANDS = [
+ {
+ "cmd": "osd pool autoscale-status",
+ "desc": "report on pool pg_num sizing recommendation and intent",
+ "perm": "r"
+ },
+ ]
+
+ NATIVE_OPTIONS = [
+ 'mon_target_pg_per_osd',
+ 'mon_max_pg_per_osd',
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'sleep_interval',
+ 'default': str(60),
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(PgAutoscaler, self).__init__(*args, **kwargs)
+ self._shutdown = threading.Event()
+
+ # So much of what we do peeks at the osdmap that it's easiest
+ # to just keep a copy of the pythonized version.
+ self._osd_map = None
+
+ def config_notify(self):
+ for opt in self.NATIVE_OPTIONS:
+ setattr(self,
+ opt,
+ self.get_ceph_option(opt))
+ self.log.debug(' native option %s = %s', opt, getattr(self, opt))
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' mgr option %s = %s',
+ opt['name'], getattr(self, opt['name']))
+
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == "osd pool autoscale-status":
+ retval = self._command_autoscale_status(cmd)
+ else:
+ assert False # ceph-mgr should never pass us unknown cmds
+ return retval
+
+ def _command_autoscale_status(self, cmd):
+ osdmap = self.get_osdmap()
+ pools = osdmap.get_pools_by_name()
+ ps, root_map, pool_root = self._get_pool_status(osdmap, pools)
+
+ if cmd.get('format') == 'json' or cmd.get('format') == 'json-pretty':
+ return 0, json.dumps(ps, indent=2), ''
+ else:
+ table = PrettyTable(['POOL', 'SIZE', 'TARGET SIZE',
+ 'RATE', 'RAW CAPACITY',
+ 'RATIO', 'TARGET RATIO',
+ 'EFFECTIVE RATIO',
+ 'BIAS',
+ 'PG_NUM',
+# 'IDEAL',
+ 'NEW PG_NUM', 'AUTOSCALE'],
+ border=False)
+ table.left_padding_width = 0
+ table.right_padding_width = 1
+ table.align['POOL'] = 'l'
+ table.align['SIZE'] = 'r'
+ table.align['TARGET SIZE'] = 'r'
+ table.align['RATE'] = 'r'
+ table.align['RAW CAPACITY'] = 'r'
+ table.align['RATIO'] = 'r'
+ table.align['TARGET RATIO'] = 'r'
+ table.align['EFFECTIVE RATIO'] = 'r'
+ table.align['BIAS'] = 'r'
+ table.align['PG_NUM'] = 'r'
+# table.align['IDEAL'] = 'r'
+ table.align['NEW PG_NUM'] = 'r'
+ table.align['AUTOSCALE'] = 'l'
+ for p in ps:
+ if p['would_adjust']:
+ final = str(p['pg_num_final'])
+ else:
+ final = ''
+ if p['target_bytes'] > 0:
+ ts = mgr_util.format_bytes(p['target_bytes'], 6)
+ else:
+ ts = ''
+ if p['target_ratio'] > 0.0:
+ tr = '%.4f' % p['target_ratio']
+ else:
+ tr = ''
+ if p['effective_target_ratio'] > 0.0:
+ etr = '%.4f' % p['effective_target_ratio']
+ else:
+ etr = ''
+ table.add_row([
+ p['pool_name'],
+ mgr_util.format_bytes(p['logical_used'], 6),
+ ts,
+ p['raw_used_rate'],
+ mgr_util.format_bytes(p['subtree_capacity'], 6),
+ '%.4f' % p['capacity_ratio'],
+ tr,
+ etr,
+ p['bias'],
+ p['pg_num_target'],
+# p['pg_num_ideal'],
+ final,
+ p['pg_autoscale_mode'],
+ ])
+ return 0, table.get_string(), ''
+
+ def serve(self):
+ self.config_notify()
+ while not self._shutdown.is_set():
+ self._maybe_adjust()
+ self._shutdown.wait(timeout=int(self.sleep_interval))
+
+ def shutdown(self):
+ self.log.info('Stopping pg_autoscaler')
+ self._shutdown.set()
+
+ def get_subtree_resource_status(self, osdmap, crush):
+ """
+ For each CRUSH subtree of interest (i.e. the roots under which
+ we have pools), calculate the current resource usages and targets,
+ such as how many PGs there are, vs. how many PGs we would
+ like there to be.
+ """
+ result = {}
+ pool_root = {}
+ roots = []
+
+ class CrushSubtreeResourceStatus(object):
+ def __init__(self):
+ self.root_ids = []
+ self.osds = set()
+ self.osd_count = None # Number of OSDs
+ self.pg_target = None # Ideal full-capacity PG count?
+ self.pg_current = 0 # How many PGs already?
+ self.capacity = None # Total capacity of OSDs in subtree
+ self.pool_ids = []
+ self.pool_names = []
+ self.total_target_ratio = 0.0
+ self.total_target_bytes = 0 # including replication / EC overhead
+
+ # identify subtrees (note that they may overlap!)
+ for pool_id, pool in osdmap.get_pools().items():
+ cr_name = crush.get_rule_by_id(pool['crush_rule'])['rule_name']
+ root_id = int(crush.get_rule_root(cr_name))
+ pool_root[pool_id] = root_id
+ osds = set(crush.get_osds_under(root_id))
+
+ # do we intersect an existing root?
+ s = None
+ for prev in itervalues(result):
+ if osds & prev.osds:
+ s = prev
+ break
+ if not s:
+ s = CrushSubtreeResourceStatus()
+ roots.append(s)
+ result[root_id] = s
+ s.root_ids.append(root_id)
+ s.osds |= osds
+ s.pool_ids.append(int(pool_id))
+ s.pool_names.append(pool['pool_name'])
+ s.pg_current += pool['pg_num_target'] * pool['size']
+ target_ratio = pool['options'].get('target_size_ratio', 0.0)
+ if target_ratio:
+ s.total_target_ratio += target_ratio
+ else:
+ target_bytes = pool['options'].get('target_size_bytes', 0)
+ if target_bytes:
+ s.total_target_bytes += target_bytes * osdmap.pool_raw_used_rate(pool_id)
+
+ # finish subtrees
+ all_stats = self.get('osd_stats')
+ for s in roots:
+ s.osd_count = len(s.osds)
+ s.pg_target = s.osd_count * int(self.mon_target_pg_per_osd)
+
+ capacity = 0.0
+ for osd_stats in all_stats['osd_stats']:
+ if osd_stats['osd'] in s.osds:
+ # Intentionally do not apply the OSD's reweight to
+ # this, because we want to calculate PG counts based
+ # on the physical storage available, not how it is
+ # reweighted right now.
+ capacity += osd_stats['kb'] * 1024
+
+ s.capacity = capacity
+
+ self.log.debug('root_ids %s pools %s with %d osds, pg_target %d',
+ s.root_ids,
+ s.pool_ids,
+ s.osd_count,
+ s.pg_target)
+
+ return result, pool_root
+
+ def _get_pool_status(
+ self,
+ osdmap,
+ pools,
+ threshold=3.0,
+ ):
+ assert threshold >= 2.0
+
+ crush_map = osdmap.get_crush()
+
+ root_map, pool_root = self.get_subtree_resource_status(osdmap, crush_map)
+
+ df = self.get('df')
+ pool_stats = dict([(p['id'], p['stats']) for p in df['pools']])
+
+ ret = []
+
+ # iterate over all pools to determine how they should be sized
+ for pool_name, p in iteritems(pools):
+ pool_id = p['pool']
+ if pool_id not in pool_stats:
+ # race with pool deletion; skip
+ continue
+
+ # FIXME: we assume there is only one take per pool, but that
+ # may not be true.
+ cr_name = crush_map.get_rule_by_id(p['crush_rule'])['rule_name']
+ root_id = int(crush_map.get_rule_root(cr_name))
+ pool_root[pool_name] = root_id
+
+ capacity = root_map[root_id].capacity
+ if capacity == 0:
+ self.log.debug('skipping empty subtree %s', cr_name)
+ continue
+
+ raw_used_rate = osdmap.pool_raw_used_rate(pool_id)
+
+ pool_logical_used = pool_stats[pool_id]['stored']
+ bias = p['options'].get('pg_autoscale_bias', 1.0)
+ target_bytes = 0
+ # ratio takes precedence if both are set
+ if p['options'].get('target_size_ratio', 0.0) == 0.0:
+ target_bytes = p['options'].get('target_size_bytes', 0)
+
+ # What proportion of space are we using?
+ actual_raw_used = pool_logical_used * raw_used_rate
+ actual_capacity_ratio = float(actual_raw_used) / capacity
+
+ pool_raw_used = max(pool_logical_used, target_bytes) * raw_used_rate
+ capacity_ratio = float(pool_raw_used) / capacity
+
+ self.log.info("effective_target_ratio {0} {1} {2} {3}".format(
+ p['options'].get('target_size_ratio', 0.0),
+ root_map[root_id].total_target_ratio,
+ root_map[root_id].total_target_bytes,
+ capacity))
+ target_ratio = effective_target_ratio(p['options'].get('target_size_ratio', 0.0),
+ root_map[root_id].total_target_ratio,
+ root_map[root_id].total_target_bytes,
+ capacity)
+
+ final_ratio = max(capacity_ratio, target_ratio)
+
+ # So what proportion of pg allowance should we be using?
+ pool_pg_target = (final_ratio * root_map[root_id].pg_target) / p['size'] * bias
+
+ final_pg_target = max(p['options'].get('pg_num_min', PG_NUM_MIN),
+ nearest_power_of_two(pool_pg_target))
+
+ self.log.info("Pool '{0}' root_id {1} using {2} of space, bias {3}, "
+ "pg target {4} quantized to {5} (current {6})".format(
+ p['pool_name'],
+ root_id,
+ final_ratio,
+ bias,
+ pool_pg_target,
+ final_pg_target,
+ p['pg_num_target']
+ ))
+
+ adjust = False
+ if (final_pg_target > p['pg_num_target'] * threshold or \
+ final_pg_target <= p['pg_num_target'] / threshold) and \
+ final_ratio >= 0.0 and \
+ final_ratio <= 1.0:
+ adjust = True
+
+ ret.append({
+ 'pool_id': pool_id,
+ 'pool_name': p['pool_name'],
+ 'crush_root_id': root_id,
+ 'pg_autoscale_mode': p['pg_autoscale_mode'],
+ 'pg_num_target': p['pg_num_target'],
+ 'logical_used': pool_logical_used,
+ 'target_bytes': target_bytes,
+ 'raw_used_rate': raw_used_rate,
+ 'subtree_capacity': capacity,
+ 'actual_raw_used': actual_raw_used,
+ 'raw_used': pool_raw_used,
+ 'actual_capacity_ratio': actual_capacity_ratio,
+ 'capacity_ratio': capacity_ratio,
+ 'target_ratio': p['options'].get('target_size_ratio', 0.0),
+ 'effective_target_ratio': target_ratio,
+ 'pg_num_ideal': int(pool_pg_target),
+ 'pg_num_final': final_pg_target,
+ 'would_adjust': adjust,
+ 'bias': p.get('options', {}).get('pg_autoscale_bias', 1.0),
+ });
+
+ return (ret, root_map, pool_root)
+
+
+ def _maybe_adjust(self):
+ self.log.info('_maybe_adjust')
+ osdmap = self.get_osdmap()
+ pools = osdmap.get_pools_by_name()
+ ps, root_map, pool_root = self._get_pool_status(osdmap, pools)
+
+ # Anyone in 'warn', set the health message for them and then
+ # drop them from consideration.
+ too_few = []
+ too_many = []
+ bytes_and_ratio = []
+ health_checks = {}
+
+ total_bytes = dict([(r, 0) for r in iter(root_map)])
+ total_target_bytes = dict([(r, 0.0) for r in iter(root_map)])
+ target_bytes_pools = dict([(r, []) for r in iter(root_map)])
+
+ for p in ps:
+ pool_opts = pools[p['pool_name']]['options']
+ if pool_opts.get('target_size_ratio', 0) > 0 and pool_opts.get('target_size_bytes', 0) > 0:
+ bytes_and_ratio.append('Pool %s has target_size_bytes and target_size_ratio set' % p['pool_name'])
+ total_bytes[p['crush_root_id']] += max(
+ p['actual_raw_used'],
+ p['target_bytes'] * p['raw_used_rate'])
+ if p['target_bytes'] > 0:
+ total_target_bytes[p['crush_root_id']] += p['target_bytes'] * p['raw_used_rate']
+ target_bytes_pools[p['crush_root_id']].append(p['pool_name'])
+ if not p['would_adjust']:
+ continue
+ if p['pg_autoscale_mode'] == 'warn':
+ msg = 'Pool %s has %d placement groups, should have %d' % (
+ p['pool_name'],
+ p['pg_num_target'],
+ p['pg_num_final'])
+ if p['pg_num_final'] > p['pg_num_target']:
+ too_few.append(msg)
+ else:
+ too_many.append(msg)
+
+ if p['pg_autoscale_mode'] == 'on':
+ # Note that setting pg_num actually sets pg_num_target (see
+ # OSDMonitor.cc)
+ r = self.mon_command({
+ 'prefix': 'osd pool set',
+ 'pool': p['pool_name'],
+ 'var': 'pg_num',
+ 'val': str(p['pg_num_final'])
+ })
+
+ if r[0] != 0:
+ # FIXME: this is a serious and unexpected thing,
+ # we should expose it as a cluster log error once
+ # the hook for doing that from ceph-mgr modules is
+ # in.
+ self.log.error("pg_num adjustment on {0} to {1} failed: {2}"
+ .format(p['pool_name'],
+ p['pg_num_final'], r))
+
+ if too_few:
+ summary = "{0} pools have too few placement groups".format(
+ len(too_few))
+ health_checks['POOL_TOO_FEW_PGS'] = {
+ 'severity': 'warning',
+ 'summary': summary,
+ 'detail': too_few
+ }
+ if too_many:
+ summary = "{0} pools have too many placement groups".format(
+ len(too_many))
+ health_checks['POOL_TOO_MANY_PGS'] = {
+ 'severity': 'warning',
+ 'summary': summary,
+ 'detail': too_many
+ }
+
+ too_much_target_bytes = []
+ for root_id, total in iteritems(total_bytes):
+ total_target = total_target_bytes[root_id]
+ if total_target > 0 and total > root_map[root_id].capacity and root_map[root_id].capacity:
+ too_much_target_bytes.append(
+ 'Pools %s overcommit available storage by %.03fx due to '
+ 'target_size_bytes %s on pools %s' % (
+ root_map[root_id].pool_names,
+ total / root_map[root_id].capacity,
+ mgr_util.format_bytes(total_target, 5, colored=False),
+ target_bytes_pools[root_id]
+ )
+ )
+ elif total_target > root_map[root_id].capacity and root_map[root_id].capacity:
+ too_much_target_bytes.append(
+ 'Pools %s overcommit available storage by %.03fx due to '
+ 'collective target_size_bytes of %s' % (
+ root_map[root_id].pool_names,
+ total / root_map[root_id].capacity,
+ mgr_util.format_bytes(total_target, 5, colored=False),
+ )
+ )
+ if too_much_target_bytes:
+ health_checks['POOL_TARGET_SIZE_BYTES_OVERCOMMITTED'] = {
+ 'severity': 'warning',
+ 'summary': "%d subtrees have overcommitted pool target_size_bytes" % len(too_much_target_bytes),
+ 'detail': too_much_target_bytes,
+ }
+
+ if bytes_and_ratio:
+ health_checks['POOL_HAS_TARGET_SIZE_BYTES_AND_RATIO'] = {
+ 'severity': 'warning',
+ 'summary': "%d pools have both target_size_bytes and target_size_ratio set" % len(bytes_and_ratio),
+ 'count': len(bytes_and_ratio),
+ 'detail': bytes_and_ratio,
+ }
+
+ self.set_health_checks(health_checks)
diff --git a/src/pybind/mgr/progress/__init__.py b/src/pybind/mgr/progress/__init__.py
new file mode 100644
index 00000000..0f7dab55
--- /dev/null
+++ b/src/pybind/mgr/progress/__init__.py
@@ -0,0 +1,2 @@
+
+from .module import *
diff --git a/src/pybind/mgr/progress/module.py b/src/pybind/mgr/progress/module.py
new file mode 100644
index 00000000..f880bb6e
--- /dev/null
+++ b/src/pybind/mgr/progress/module.py
@@ -0,0 +1,693 @@
+from mgr_module import MgrModule
+import threading
+import datetime
+import uuid
+
+import json
+
+
+ENCODING_VERSION = 1
+
+# keep a global reference to the module so we can use it from Event methods
+_module = None
+
+
+class Event(object):
+ """
+ A generic "event" that has a start time, completion percentage,
+ and a list of "refs" that are (type, id) tuples describing which
+ objects (osds, pools) this relates to.
+ """
+
+ def __init__(self, message, refs):
+ self._message = message
+ self._refs = refs
+
+ self.started_at = datetime.datetime.utcnow()
+
+ self.id = None
+
+ def _refresh(self):
+ global _module
+ _module.log.debug('refreshing mgr for %s (%s) at %f' % (self.id, self._message,
+ self.progress))
+ _module.update_progress_event(self.id, self._message, self.progress)
+
+ @property
+ def message(self):
+ return self._message
+
+ @property
+ def refs(self):
+ return self._refs
+
+ @property
+ def progress(self):
+ raise NotImplementedError()
+
+ @property
+ def failed(self):
+ return False
+
+ @property
+ def failure_message(self):
+ return None
+
+ def summary(self):
+ return "{0} {1}".format(self.progress, self.message)
+
+ def _progress_str(self, width):
+ inner_width = width - 2
+ out = "["
+ done_chars = int(self.progress * inner_width)
+ out += done_chars * '='
+ out += (inner_width - done_chars) * '.'
+ out += "]"
+
+ return out
+
+ def twoline_progress(self):
+ """
+ e.g.
+
+ - Eating my delicious strudel
+ [===============..............]
+
+ """
+ return "{0}\n {1}".format(
+ self._message, self._progress_str(30))
+
+ def to_json(self):
+ return {
+ "id": self.id,
+ "message": self.message,
+ "refs": self._refs
+ }
+
+
+class GhostEvent(Event):
+ """
+ The ghost of a completed event: these are the fields that we persist
+ after the event is complete.
+ """
+
+ def __init__(self, my_id, message, refs,
+ failed=False, failure_message=None):
+ super(GhostEvent, self).__init__(message, refs)
+ self.id = my_id
+
+ if failed:
+ self._failed = True
+ self._failure_message = failure_message
+ else:
+ self._failed = False
+
+ @property
+ def progress(self):
+ return 1.0
+
+ @property
+ def failed(self):
+ return self._failed
+
+ @property
+ def failure_message(self):
+ return self._failure_message if self._failed else None
+
+ def to_json(self):
+ d = {
+ "id": self.id,
+ "message": self.message,
+ "refs": self._refs
+ }
+ if self._failed:
+ d["failed"] = True
+ d["failure_message"] = self._failure_message
+ return d
+
+
+class RemoteEvent(Event):
+ """
+ An event that was published by another module: we know nothing about
+ this, rely on the other module to continuously update us with
+ progress information as it emerges.
+ """
+
+ def __init__(self, my_id, message, refs):
+ super(RemoteEvent, self).__init__(message, refs)
+ self.id = my_id
+ self._progress = 0.0
+ self._failed = False
+ self._refresh()
+
+ def set_progress(self, progress):
+ self._progress = progress
+ self._refresh()
+
+ def set_failed(self, message):
+ self._progress = 1.0
+ self._failed = True
+ self._failure_message = message
+ self._refresh()
+
+ @property
+ def progress(self):
+ return self._progress
+
+ @property
+ def failed(self):
+ return self._failed
+
+ @property
+ def failure_message(self):
+ return self._failure_message if self._failed else None
+
+
+class PgRecoveryEvent(Event):
+ """
+ An event whose completion is determined by the recovery of a set of
+ PGs to a healthy state.
+
+ Always call update() immediately after construction.
+ """
+
+ def __init__(self, message, refs, which_pgs, evacuate_osds):
+ super(PgRecoveryEvent, self).__init__(message, refs)
+
+ self._pgs = which_pgs
+
+ self._evacuate_osds = evacuate_osds
+
+ self._original_pg_count = len(self._pgs)
+
+ self._original_bytes_recovered = None
+
+ self._progress = 0.0
+
+ self._start_epoch = _module.get_osdmap().get_epoch()
+
+ self.id = str(uuid.uuid4())
+ self._refresh()
+
+ @property
+ def evacuating_osds(self):
+ return self. _evacuate_osds
+
+ def pg_update(self, raw_pg_stats, pg_ready, log):
+ # FIXME: O(pg_num) in python
+ # FIXME: far more fields getting pythonized than we really care about
+ pg_to_state = dict([(p['pgid'], p) for p in raw_pg_stats['pg_stats']])
+ if self._original_bytes_recovered is None:
+ self._original_bytes_recovered = {}
+ missing_pgs = []
+ for pg in self._pgs:
+ pg_str = str(pg)
+ if pg_str in pg_to_state:
+ self._original_bytes_recovered[pg] = \
+ pg_to_state[pg_str]['stat_sum']['num_bytes_recovered']
+ else:
+ missing_pgs.append(pg)
+ if pg_ready:
+ for pg in missing_pgs:
+ self._pgs.remove(pg)
+
+ complete_accumulate = 0.0
+
+ # Calculating progress as the number of PGs recovered divided by the
+ # original where partially completed PGs count for something
+ # between 0.0-1.0. This is perhaps less faithful than looking at the
+ # total number of bytes recovered, but it does a better job of
+ # representing the work still to do if there are a number of very
+ # few-bytes PGs that still need the housekeeping of their recovery
+ # to be done. This is subjective...
+
+ complete = set()
+ for pg in self._pgs:
+ pg_str = str(pg)
+ try:
+ info = pg_to_state[pg_str]
+ except KeyError:
+ # The PG is gone! Probably a pool was deleted. Drop it.
+ complete.add(pg)
+ continue
+ # Only checks the state of each PGs when it's epoch >= the OSDMap's epoch
+ if int(info['reported_epoch']) < int(self._start_epoch):
+ continue
+
+ state = info['state']
+
+ states = state.split("+")
+
+ if "active" in states and "clean" in states:
+ complete.add(pg)
+ else:
+ if info['stat_sum']['num_bytes'] == 0:
+ # Empty PGs are considered 0% done until they are
+ # in the correct state.
+ pass
+ else:
+ recovered = info['stat_sum']['num_bytes_recovered']
+ total_bytes = info['stat_sum']['num_bytes']
+ if total_bytes > 0:
+ ratio = float(recovered -
+ self._original_bytes_recovered[pg]) / \
+ total_bytes
+ # Since the recovered bytes (over time) could perhaps
+ # exceed the contents of the PG (moment in time), we
+ # must clamp this
+ ratio = min(ratio, 1.0)
+
+ else:
+ # Dataless PGs (e.g. containing only OMAPs) count
+ # as half done.
+ ratio = 0.5
+ complete_accumulate += ratio
+
+ self._pgs = list(set(self._pgs) ^ complete)
+ completed_pgs = self._original_pg_count - len(self._pgs)
+ self._progress = (completed_pgs + complete_accumulate)\
+ / self._original_pg_count
+ self._refresh()
+
+ log.info("Updated progress to {0} ({1})".format(
+ self._progress, self._message
+ ))
+
+ @property
+ def progress(self):
+ return self._progress
+
+
+class PgId(object):
+ def __init__(self, pool_id, ps):
+ self.pool_id = pool_id
+ self.ps = ps
+
+ def __cmp__(self, other):
+ return (self.pool_id, self.ps) == (other.pool_id, other.ps)
+
+ def __lt__(self, other):
+ return (self.pool_id, self.ps) < (other.pool_id, other.ps)
+
+ def __str__(self):
+ return "{0}.{1:x}".format(self.pool_id, self.ps)
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {"cmd": "progress",
+ "desc": "Show progress of recovery operations",
+ "perm": "r"},
+ {"cmd": "progress json",
+ "desc": "Show machine readable progress information",
+ "perm": "r"},
+ {"cmd": "progress clear",
+ "desc": "Reset progress tracking",
+ "perm": "rw"},
+ {"cmd": "progress on",
+ "desc": "Enable progress tracking",
+ "perm": "rw"},
+ {"cmd": "progress off",
+ "desc": "Disable progress tracking",
+ "perm": "rw"}
+
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'max_completed_events',
+ 'default': 50,
+ 'type': 'int',
+ 'desc': 'number of past completed events to remember',
+ 'runtime': True,
+ },
+ {
+ 'name': 'persist_interval',
+ 'default': 5,
+ 'type': 'secs',
+ 'desc': 'how frequently to persist completed events',
+ 'runtime': True,
+ },
+ {
+ 'name': 'enabled',
+ 'default': True,
+ 'type': 'bool',
+ }
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+
+ self._events = {}
+ self._completed_events = []
+
+ self._old_osd_map = None
+
+ self._ready = threading.Event()
+ self._shutdown = threading.Event()
+
+ self._latest_osdmap = None
+
+ self._dirty = False
+
+ global _module
+ _module = self
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+
+ def _osd_in_out(self, old_map, old_dump, new_map, osd_id, marked):
+ # A function that will create or complete an event when an
+ # OSD is marked in or out according to the affected PGs
+ affected_pgs = []
+ unmoved_pgs = []
+ for pool in old_dump['pools']:
+ pool_id = pool['pool']
+ for ps in range(0, pool['pg_num']):
+
+ # Was this OSD affected by the OSD coming in/out?
+ # Compare old and new osds using
+ # data from the json dump
+ old_up_acting = old_map.pg_to_up_acting_osds(pool['pool'], ps)
+ old_osds = set(old_up_acting['acting'])
+
+ new_up_acting = new_map.pg_to_up_acting_osds(pool['pool'], ps)
+ new_osds = set(new_up_acting['acting'])
+
+ # Check the osd_id being in the acting set for both old
+ # and new maps to cover both out and in cases
+ was_on_out_or_in_osd = osd_id in old_osds or osd_id in new_osds
+ if not was_on_out_or_in_osd:
+ continue
+
+ self.log.debug("pool_id, ps = {0}, {1}".format(
+ pool_id, ps
+ ))
+
+ self.log.debug(
+ "old_up_acting: {0}".format(json.dumps(old_up_acting, indent=2)))
+
+ # Has this OSD been assigned a new location?
+ # (it might not be if there is no suitable place to move
+ # after an OSD is marked in/out)
+ if marked == "in":
+ is_relocated = len(old_osds - new_osds) > 0
+ else:
+ is_relocated = len(new_osds - old_osds) > 0
+
+ self.log.debug(
+ "new_up_acting: {0}".format(json.dumps(new_up_acting,
+ indent=2)))
+
+ if was_on_out_or_in_osd and is_relocated:
+ # This PG is now in motion, track its progress
+ affected_pgs.append(PgId(pool_id, ps))
+ elif not is_relocated:
+ # This PG didn't get a new location, we'll log it
+ unmoved_pgs.append(PgId(pool_id, ps))
+
+ # In the case that we ignored some PGs, log the reason why (we may
+ # not end up creating a progress event)
+ if len(unmoved_pgs):
+ self.log.warn("{0} PGs were on osd.{1}, but didn't get new locations".format(
+ len(unmoved_pgs), osd_id))
+
+ self.log.warn("{0} PGs affected by osd.{1} being marked {2}".format(
+ len(affected_pgs), osd_id, marked))
+
+
+ # In the case of the osd coming back in, we might need to cancel
+ # previous recovery event for that osd
+ if marked == "in":
+ for ev_id in list(self._events):
+ ev = self._events[ev_id]
+ if isinstance(ev, PgRecoveryEvent) and osd_id in ev.evacuating_osds:
+ self.log.info("osd.{0} came back in, cancelling event".format(
+ osd_id
+ ))
+ self._complete(ev)
+
+ if len(affected_pgs) > 0:
+ ev = PgRecoveryEvent(
+ "Rebalancing after osd.{0} marked {1}".format(osd_id, marked),
+ refs=[("osd", osd_id)],
+ which_pgs=affected_pgs,
+ evacuate_osds=[osd_id]
+ )
+ ev.pg_update(self.get("pg_dump"), self.get("pg_ready"), self.log)
+ self._events[ev.id] = ev
+
+ def _osdmap_changed(self, old_osdmap, new_osdmap):
+ old_dump = old_osdmap.dump()
+ new_dump = new_osdmap.dump()
+
+ old_osds = dict([(o['osd'], o) for o in old_dump['osds']])
+
+ for osd in new_dump['osds']:
+ osd_id = osd['osd']
+ new_weight = osd['in']
+ if osd_id in old_osds:
+ old_weight = old_osds[osd_id]['in']
+
+ if new_weight == 0.0 and old_weight > new_weight:
+ self.log.warn("osd.{0} marked out".format(osd_id))
+ self._osd_in_out(old_osdmap, old_dump, new_osdmap, osd_id, "out")
+ elif new_weight >= 1.0 and old_weight == 0.0:
+ # Only consider weight>=1.0 as "in" to avoid spawning
+ # individual recovery events on every adjustment
+ # in a gradual weight-in
+ self.log.warn("osd.{0} marked in".format(osd_id))
+ self._osd_in_out(old_osdmap, old_dump, new_osdmap, osd_id, "in")
+
+ def notify(self, notify_type, notify_data):
+ self._ready.wait()
+ if not self.enabled:
+ return
+ if notify_type == "osd_map":
+ old_osdmap = self._latest_osdmap
+ self._latest_osdmap = self.get_osdmap()
+
+ self.log.info("Processing OSDMap change {0}..{1}".format(
+ old_osdmap.get_epoch(), self._latest_osdmap.get_epoch()
+ ))
+ self._osdmap_changed(old_osdmap, self._latest_osdmap)
+ elif notify_type == "pg_summary":
+ # if there are no events we will skip this here to avoid
+ # expensive get calls
+ if len(self._events) == 0:
+ return
+ data = self.get("pg_stats")
+ ready = self.get("pg_ready")
+ for ev_id, ev in self._events.items():
+ if isinstance(ev, PgRecoveryEvent):
+ ev.pg_update(data, ready, self.log)
+ self.maybe_complete(ev)
+
+ def maybe_complete(self, event):
+ if event.progress >= 1.0:
+ self._complete(event)
+
+ def _save(self):
+ self.log.info("Writing back {0} completed events".format(
+ len(self._completed_events)
+ ))
+ # TODO: bound the number we store.
+ encoded = json.dumps({
+ "events": [ev.to_json() for ev in self._completed_events],
+ "version": ENCODING_VERSION,
+ "compat_version": ENCODING_VERSION
+ })
+ self.set_store("completed", encoded)
+
+ def _load(self):
+ stored = self.get_store("completed")
+
+ if stored is None:
+ self.log.info("No stored events to load")
+ return
+
+ decoded = json.loads(stored)
+ if decoded['compat_version'] > ENCODING_VERSION:
+ raise RuntimeError("Cannot decode version {0}".format(
+ decoded['compat_version']))
+
+ for ev in decoded['events']:
+ self._completed_events.append(GhostEvent(ev['id'], ev['message'],
+ ev['refs'],
+ ev.get('failed', False),
+ ev.get('failure_message')))
+
+ self._prune_completed_events()
+
+ def _prune_completed_events(self):
+ length = len(self._completed_events)
+ if length > self.max_completed_events:
+ self._completed_events = self._completed_events[length - self.max_completed_events : length]
+ self._dirty = True
+
+ def serve(self):
+ self.config_notify()
+ self.clear_all_progress_events()
+ self.log.info("Loading...")
+
+ self._load()
+ self.log.info("Loaded {0} historic events".format(self._completed_events))
+
+ self._latest_osdmap = self.get_osdmap()
+ self.log.info("Loaded OSDMap, ready.")
+
+ self._ready.set()
+
+ while not self._shutdown.is_set():
+ # Lazy periodic write back of completed events
+ if self._dirty:
+ self._save()
+ self._dirty = False
+
+ self._shutdown.wait(timeout=self.persist_interval)
+
+ self._shutdown.wait()
+
+ def shutdown(self):
+ self._shutdown.set()
+ self.clear_all_progress_events()
+
+ def update(self, ev_id, ev_msg, ev_progress, refs=None):
+ """
+ For calling from other mgr modules
+ """
+ if not self.enabled:
+ return
+
+ if refs is None:
+ refs = []
+ try:
+ ev = self._events[ev_id]
+ except KeyError:
+ ev = RemoteEvent(ev_id, ev_msg, refs)
+ self._events[ev_id] = ev
+ self.log.info("update: starting ev {0} ({1})".format(
+ ev_id, ev_msg))
+ else:
+ self.log.debug("update: {0} on {1}".format(
+ ev_progress, ev_msg))
+
+ ev.set_progress(ev_progress)
+ ev._refresh()
+
+ def _complete(self, ev):
+ duration = (datetime.datetime.utcnow() - ev.started_at)
+ self.log.info("Completed event {0} ({1}) in {2} seconds".format(
+ ev.id, ev.message, duration.seconds
+ ))
+ self.complete_progress_event(ev.id)
+
+ self._completed_events.append(
+ GhostEvent(ev.id, ev.message, ev.refs,
+ failed=ev.failed, failure_message=ev.failure_message))
+ del self._events[ev.id]
+ self._prune_completed_events()
+ self._dirty = True
+
+ def complete(self, ev_id):
+ """
+ For calling from other mgr modules
+ """
+ if not self.enabled:
+ return
+ try:
+ ev = self._events[ev_id]
+ ev.set_progress(1.0)
+ self.log.info("complete: finished ev {0} ({1})".format(ev_id,
+ ev.message))
+ self._complete(ev)
+ except KeyError:
+ self.log.warn("complete: ev {0} does not exist".format(ev_id))
+ pass
+
+ def fail(self, ev_id, message):
+ """
+ For calling from other mgr modules to mark an event as failed (and
+ complete)
+ """
+ try:
+ ev = self._events[ev_id]
+ ev.set_failed(message)
+ self.log.info("fail: finished ev {0} ({1}): {2}".format(ev_id,
+ ev.message,
+ message))
+ self._complete(ev)
+ except KeyError:
+ self.log.warn("fail: ev {0} does not exist".format(ev_id))
+
+ def on(self):
+ self.set_module_option('enabled', True)
+
+ def off(self):
+ self.set_module_option('enabled', False)
+
+ def _handle_ls(self):
+ if len(self._events) or len(self._completed_events):
+ out = ""
+ chrono_order = sorted(self._events.values(),
+ key=lambda x: x.started_at, reverse=True)
+ for ev in chrono_order:
+ out += ev.twoline_progress()
+ out += "\n"
+
+ if len(self._completed_events):
+ # TODO: limit number of completed events to show
+ out += "\n"
+ for ev in self._completed_events:
+ out += "[{0}]: {1}\n".format("Complete" if not ev.failed else "Failed",
+ ev.twoline_progress())
+
+ return 0, out, ""
+ else:
+ return 0, "", "Nothing in progress"
+
+ def _json(self):
+ return {
+ 'events': [ev.to_json() for ev in self._events.values()],
+ 'completed': [ev.to_json() for ev in self._completed_events]
+ }
+
+ def clear(self):
+ self._events = {}
+ self._completed_events = []
+ self._dirty = True
+ self._save()
+ self.clear_all_progress_events()
+
+ def _handle_clear(self):
+ self.clear()
+ return 0, "", ""
+
+ def handle_command(self, _, cmd):
+ if cmd['prefix'] == "progress":
+ return self._handle_ls()
+ elif cmd['prefix'] == "progress clear":
+ # The clear command isn't usually needed - it's to enable
+ # the admin to "kick" this module if it seems to have done
+ # something wrong (e.g. we have a bug causing a progress event
+ # that never finishes)
+ return self._handle_clear()
+ elif cmd['prefix'] == "progress json":
+ return 0, json.dumps(self._json(), indent=4, sort_keys=True), ""
+ elif cmd['prefix'] == "progress on":
+ if self.enabled:
+ return 0, "", "progress already enabled!"
+ self.on()
+ return 0, "", "progress enabled"
+ elif cmd['prefix'] == "progress off":
+ if not self.enabled:
+ return 0, "", "progress already disabled!"
+ self.off()
+ self.clear()
+ return 0, "", "progress disabled"
+ else:
+ raise NotImplementedError(cmd['prefix'])
diff --git a/src/pybind/mgr/prometheus/__init__.py b/src/pybind/mgr/prometheus/__init__.py
new file mode 100644
index 00000000..763a8426
--- /dev/null
+++ b/src/pybind/mgr/prometheus/__init__.py
@@ -0,0 +1,2 @@
+from .module import Module, StandbyModule
+
diff --git a/src/pybind/mgr/prometheus/module.py b/src/pybind/mgr/prometheus/module.py
new file mode 100644
index 00000000..16fd6f7f
--- /dev/null
+++ b/src/pybind/mgr/prometheus/module.py
@@ -0,0 +1,1324 @@
+import cherrypy
+from distutils.version import StrictVersion
+import json
+import errno
+import math
+import os
+import re
+import socket
+import threading
+import time
+from mgr_module import MgrModule, MgrStandbyModule, CommandResult, PG_STATES
+from mgr_util import get_default_addr
+from rbd import RBD
+from collections import namedtuple
+try:
+ from typing import Optional
+except:
+ pass
+
+# Defaults for the Prometheus HTTP server. Can also set in config-key
+# see https://github.com/prometheus/prometheus/wiki/Default-port-allocations
+# for Prometheus exporter port registry
+
+DEFAULT_PORT = 9283
+
+# When the CherryPy server in 3.2.2 (and later) starts it attempts to verify
+# that the ports its listening on are in fact bound. When using the any address
+# "::" it tries both ipv4 and ipv6, and in some environments (e.g. kubernetes)
+# ipv6 isn't yet configured / supported and CherryPy throws an uncaught
+# exception.
+if cherrypy is not None:
+ v = StrictVersion(cherrypy.__version__)
+ # the issue was fixed in 3.2.3. it's present in 3.2.2 (current version on
+ # centos:7) and back to at least 3.0.0.
+ if StrictVersion("3.1.2") <= v < StrictVersion("3.2.3"):
+ # https://github.com/cherrypy/cherrypy/issues/1100
+ from cherrypy.process import servers
+ servers.wait_for_occupied_port = lambda host, port: None
+
+# cherrypy likes to sys.exit on error. don't let it take us down too!
+def os_exit_noop(*args, **kwargs):
+ pass
+
+
+os._exit = os_exit_noop
+
+# to access things in class Module from subclass Root. Because
+# it's a dict, the writer doesn't need to declare 'global' for access
+
+_global_instance = None # type: Optional[Module]
+cherrypy.config.update({
+ 'response.headers.server': 'Ceph-Prometheus'
+})
+
+
+def health_status_to_number(status):
+ if status == 'HEALTH_OK':
+ return 0
+ elif status == 'HEALTH_WARN':
+ return 1
+ elif status == 'HEALTH_ERR':
+ return 2
+
+
+DF_CLUSTER = ['total_bytes', 'total_used_bytes', 'total_used_raw_bytes']
+
+DF_POOL = ['max_avail', 'stored', 'stored_raw', 'objects', 'dirty',
+ 'quota_bytes', 'quota_objects', 'rd', 'rd_bytes', 'wr', 'wr_bytes',
+ 'compress_bytes_used', 'compress_under_bytes']
+
+OSD_POOL_STATS = ('recovering_objects_per_sec', 'recovering_bytes_per_sec',
+ 'recovering_keys_per_sec', 'num_objects_recovered',
+ 'num_bytes_recovered', 'num_bytes_recovered')
+
+OSD_FLAGS = ('noup', 'nodown', 'noout', 'noin', 'nobackfill', 'norebalance',
+ 'norecover', 'noscrub', 'nodeep-scrub')
+
+FS_METADATA = ('data_pools', 'fs_id', 'metadata_pool', 'name')
+
+MDS_METADATA = ('ceph_daemon', 'fs_id', 'hostname', 'public_addr', 'rank',
+ 'ceph_version')
+
+MON_METADATA = ('ceph_daemon', 'hostname',
+ 'public_addr', 'rank', 'ceph_version')
+
+MGR_METADATA = ('ceph_daemon', 'hostname', 'ceph_version')
+
+MGR_STATUS = ('ceph_daemon',)
+
+MGR_MODULE_STATUS = ('name',)
+
+MGR_MODULE_CAN_RUN = ('name',)
+
+OSD_METADATA = ('back_iface', 'ceph_daemon', 'cluster_addr', 'device_class',
+ 'front_iface', 'hostname', 'objectstore', 'public_addr',
+ 'ceph_version')
+
+OSD_STATUS = ['weight', 'up', 'in']
+
+OSD_STATS = ['apply_latency_ms', 'commit_latency_ms']
+
+POOL_METADATA = ('pool_id', 'name')
+
+RGW_METADATA = ('ceph_daemon', 'hostname', 'ceph_version')
+
+RBD_MIRROR_METADATA = ('ceph_daemon', 'id', 'instance_id', 'hostname',
+ 'ceph_version')
+
+DISK_OCCUPATION = ('ceph_daemon', 'device', 'db_device',
+ 'wal_device', 'instance')
+
+NUM_OBJECTS = ['degraded', 'misplaced', 'unfound']
+
+alert_metric = namedtuple('alert_metric', 'name description')
+HEALTH_CHECKS = [
+ alert_metric('SLOW_OPS', 'OSD or Monitor requests taking a long time to process' ),
+]
+
+
+class Metric(object):
+ def __init__(self, mtype, name, desc, labels=None):
+ self.mtype = mtype
+ self.name = name
+ self.desc = desc
+ self.labelnames = labels # tuple if present
+ self.value = {} # indexed by label values
+
+ def clear(self):
+ self.value = {}
+
+ def set(self, value, labelvalues=None):
+ # labelvalues must be a tuple
+ labelvalues = labelvalues or ('',)
+ self.value[labelvalues] = value
+
+ def str_expfmt(self):
+
+ def promethize(path):
+ ''' replace illegal metric name characters '''
+ result = re.sub(r'[./\s]|::', '_', path).replace('+', '_plus')
+
+ # Hyphens usually turn into underscores, unless they are
+ # trailing
+ if result.endswith("-"):
+ result = result[0:-1] + "_minus"
+ else:
+ result = result.replace("-", "_")
+
+ return "ceph_{0}".format(result)
+
+ def floatstr(value):
+ ''' represent as Go-compatible float '''
+ if value == float('inf'):
+ return '+Inf'
+ if value == float('-inf'):
+ return '-Inf'
+ if math.isnan(value):
+ return 'NaN'
+ return repr(float(value))
+
+ name = promethize(self.name)
+ expfmt = '''
+# HELP {name} {desc}
+# TYPE {name} {mtype}'''.format(
+ name=name,
+ desc=self.desc,
+ mtype=self.mtype,
+ )
+
+ for labelvalues, value in self.value.items():
+ if self.labelnames:
+ labels = zip(self.labelnames, labelvalues)
+ labels = ','.join('%s="%s"' % (k, v) for k, v in labels)
+ else:
+ labels = ''
+ if labels:
+ fmtstr = '\n{name}{{{labels}}} {value}'
+ else:
+ fmtstr = '\n{name} {value}'
+ expfmt += fmtstr.format(
+ name=name,
+ labels=labels,
+ value=floatstr(value),
+ )
+ return expfmt
+
+
+class MetricCollectionThread(threading.Thread):
+ def __init__(self, module):
+ # type: (Module) -> None
+ self.mod = module
+ self.active = True
+ self.event = threading.Event()
+ super(MetricCollectionThread, self).__init__(target=self.collect)
+
+ def collect(self):
+ self.mod.log.info('starting metric collection thread')
+ while self.active:
+ self.mod.log.debug('collecting cache in thread')
+ if self.mod.have_mon_connection():
+ start_time = time.time()
+
+ try:
+ data = self.mod.collect()
+ except:
+ # Log any issues encountered during the data collection and continue
+ self.mod.log.exception("failed to collect metrics:")
+ self.event.wait(self.mod.scrape_interval)
+ continue
+
+ duration = time.time() - start_time
+
+ sleep_time = self.mod.scrape_interval - duration
+ if sleep_time < 0:
+ self.mod.log.warning(
+ 'Collecting data took more time than configured scrape interval. '
+ 'This possibly results in stale data. Please check the '
+ '`stale_cache_strategy` configuration option. '
+ 'Collecting data took {:.2f} seconds but scrape interval is configured '
+ 'to be {:.0f} seconds.'.format(
+ duration,
+ self.mod.scrape_interval,
+ )
+ )
+ sleep_time = 0
+
+ with self.mod.collect_lock:
+ self.mod.collect_cache = data
+ self.mod.collect_time = duration
+
+ self.event.wait(sleep_time)
+ else:
+ self.mod.log.error('No MON connection')
+ self.event.wait(self.mod.scrape_interval)
+
+ def stop(self):
+ self.active = False
+ self.event.set()
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "prometheus file_sd_config",
+ "desc": "Return file_sd compatible prometheus config for mgr cluster",
+ "perm": "r"
+ },
+ ]
+
+ MODULE_OPTIONS = [
+ {'name': 'server_addr'},
+ {'name': 'server_port'},
+ {'name': 'scrape_interval'},
+ {'name': 'stale_cache_strategy'},
+ {'name': 'rbd_stats_pools'},
+ {'name': 'rbd_stats_pools_refresh_interval', 'type': 'int', 'default': 300},
+ ]
+
+ STALE_CACHE_FAIL = 'fail'
+ STALE_CACHE_RETURN = 'return'
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.metrics = self._setup_static_metrics()
+ self.shutdown_event = threading.Event()
+ self.collect_lock = threading.Lock()
+ self.collect_time = 0
+ self.scrape_interval = 15.0
+ self.stale_cache_strategy = self.STALE_CACHE_FAIL
+ self.collect_cache = None
+ self.rbd_stats = {
+ 'pools': {},
+ 'pools_refresh_time': 0,
+ 'counters_info': {
+ 'write_ops': {'type': self.PERFCOUNTER_COUNTER,
+ 'desc': 'RBD image writes count'},
+ 'read_ops': {'type': self.PERFCOUNTER_COUNTER,
+ 'desc': 'RBD image reads count'},
+ 'write_bytes': {'type': self.PERFCOUNTER_COUNTER,
+ 'desc': 'RBD image bytes written'},
+ 'read_bytes': {'type': self.PERFCOUNTER_COUNTER,
+ 'desc': 'RBD image bytes read'},
+ 'write_latency': {'type': self.PERFCOUNTER_LONGRUNAVG,
+ 'desc': 'RBD image writes latency (msec)'},
+ 'read_latency': {'type': self.PERFCOUNTER_LONGRUNAVG,
+ 'desc': 'RBD image reads latency (msec)'},
+ },
+ }
+ global _global_instance
+ _global_instance = self
+ self.metrics_thread = MetricCollectionThread(_global_instance)
+
+ def _setup_static_metrics(self):
+ metrics = {}
+ metrics['health_status'] = Metric(
+ 'untyped',
+ 'health_status',
+ 'Cluster health status'
+ )
+ metrics['mon_quorum_status'] = Metric(
+ 'gauge',
+ 'mon_quorum_status',
+ 'Monitors in quorum',
+ ('ceph_daemon',)
+ )
+ metrics['fs_metadata'] = Metric(
+ 'untyped',
+ 'fs_metadata',
+ 'FS Metadata',
+ FS_METADATA
+ )
+ metrics['mds_metadata'] = Metric(
+ 'untyped',
+ 'mds_metadata',
+ 'MDS Metadata',
+ MDS_METADATA
+ )
+ metrics['mon_metadata'] = Metric(
+ 'untyped',
+ 'mon_metadata',
+ 'MON Metadata',
+ MON_METADATA
+ )
+ metrics['mgr_metadata'] = Metric(
+ 'gauge',
+ 'mgr_metadata',
+ 'MGR metadata',
+ MGR_METADATA
+ )
+ metrics['mgr_status'] = Metric(
+ 'gauge',
+ 'mgr_status',
+ 'MGR status (0=standby, 1=active)',
+ MGR_STATUS
+ )
+ metrics['mgr_module_status'] = Metric(
+ 'gauge',
+ 'mgr_module_status',
+ 'MGR module status (0=disabled, 1=enabled, 2=auto-enabled)',
+ MGR_MODULE_STATUS
+ )
+ metrics['mgr_module_can_run'] = Metric(
+ 'gauge',
+ 'mgr_module_can_run',
+ 'MGR module runnable state i.e. can it run (0=no, 1=yes)',
+ MGR_MODULE_CAN_RUN
+ )
+ metrics['osd_metadata'] = Metric(
+ 'untyped',
+ 'osd_metadata',
+ 'OSD Metadata',
+ OSD_METADATA
+ )
+
+ # The reason for having this separate to OSD_METADATA is
+ # so that we can stably use the same tag names that
+ # the Prometheus node_exporter does
+ metrics['disk_occupation'] = Metric(
+ 'untyped',
+ 'disk_occupation',
+ 'Associate Ceph daemon with disk used',
+ DISK_OCCUPATION
+ )
+
+ metrics['pool_metadata'] = Metric(
+ 'untyped',
+ 'pool_metadata',
+ 'POOL Metadata',
+ POOL_METADATA
+ )
+
+ metrics['rgw_metadata'] = Metric(
+ 'untyped',
+ 'rgw_metadata',
+ 'RGW Metadata',
+ RGW_METADATA
+ )
+
+ metrics['rbd_mirror_metadata'] = Metric(
+ 'untyped',
+ 'rbd_mirror_metadata',
+ 'RBD Mirror Metadata',
+ RBD_MIRROR_METADATA
+ )
+
+ metrics['pg_total'] = Metric(
+ 'gauge',
+ 'pg_total',
+ 'PG Total Count per Pool',
+ ('pool_id',)
+ )
+
+ metrics['scrape_duration_seconds'] = Metric(
+ 'gauge',
+ 'scrape_duration_secs',
+ 'Time taken to gather metrics from Ceph (secs)'
+ )
+
+ for flag in OSD_FLAGS:
+ path = 'osd_flag_{}'.format(flag)
+ metrics[path] = Metric(
+ 'untyped',
+ path,
+ 'OSD Flag {}'.format(flag)
+ )
+ for state in OSD_STATUS:
+ path = 'osd_{}'.format(state)
+ metrics[path] = Metric(
+ 'untyped',
+ path,
+ 'OSD status {}'.format(state),
+ ('ceph_daemon',)
+ )
+ for stat in OSD_STATS:
+ path = 'osd_{}'.format(stat)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ 'OSD stat {}'.format(stat),
+ ('ceph_daemon',)
+ )
+ for stat in OSD_POOL_STATS:
+ path = 'pool_{}'.format(stat)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ "OSD POOL STATS: {}".format(stat),
+ ('pool_id',)
+ )
+ for state in PG_STATES:
+ path = 'pg_{}'.format(state)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ 'PG {} per pool'.format(state),
+ ('pool_id',)
+ )
+ for state in DF_CLUSTER:
+ path = 'cluster_{}'.format(state)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ 'DF {}'.format(state),
+ )
+ for state in DF_POOL:
+ path = 'pool_{}'.format(state)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ 'DF pool {}'.format(state),
+ ('pool_id',)
+ )
+ for state in NUM_OBJECTS:
+ path = 'num_objects_{}'.format(state)
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ 'Number of {} objects'.format(state),
+ )
+
+ for check in HEALTH_CHECKS:
+ path = 'healthcheck_{}'.format(check.name.lower())
+ metrics[path] = Metric(
+ 'gauge',
+ path,
+ check.description,
+ )
+
+ return metrics
+
+ def get_health(self):
+
+ def _get_value(message, delim=' ', word_pos=0):
+ """Extract value from message (default is 1st field)"""
+ v_str = message.split(delim)[word_pos]
+ if v_str.isdigit():
+ return int(v_str), 0
+ return 0, 1
+
+ health = json.loads(self.get('health')['json'])
+ # set overall health
+ self.metrics['health_status'].set(
+ health_status_to_number(health['status'])
+ )
+
+ # Examine the health to see if any health checks triggered need to
+ # become a metric.
+ active_healthchecks = health.get('checks', {})
+ active_names = active_healthchecks.keys()
+
+ for check in HEALTH_CHECKS:
+ path = 'healthcheck_{}'.format(check.name.lower())
+
+ if path in self.metrics:
+
+ if check.name in active_names:
+ check_data = active_healthchecks[check.name]
+ message = check_data['summary'].get('message', '')
+ v, err = 0, 0
+
+ if check.name == "SLOW_OPS":
+ # 42 slow ops, oldest one blocked for 12 sec, daemons [osd.0, osd.3] have slow ops.
+ v, err = _get_value(message)
+
+ if err:
+ self.log.error("healthcheck {} message format is incompatible and has been dropped".format(check.name))
+ # drop the metric, so it's no longer emitted
+ del self.metrics[path]
+ continue
+ else:
+ self.metrics[path].set(v)
+ else:
+ # health check is not active, so give it a default of 0
+ self.metrics[path].set(0)
+
+ def get_pool_stats(self):
+ # retrieve pool stats to provide per pool recovery metrics
+ # (osd_pool_stats moved to mgr in Mimic)
+ pstats = self.get('osd_pool_stats')
+ for pool in pstats['pool_stats']:
+ for stat in OSD_POOL_STATS:
+ self.metrics['pool_{}'.format(stat)].set(
+ pool['recovery_rate'].get(stat, 0),
+ (pool['pool_id'],)
+ )
+
+ def get_df(self):
+ # maybe get the to-be-exported metrics from a config?
+ df = self.get('df')
+ for stat in DF_CLUSTER:
+ self.metrics['cluster_{}'.format(stat)].set(df['stats'][stat])
+
+ for pool in df['pools']:
+ for stat in DF_POOL:
+ self.metrics['pool_{}'.format(stat)].set(
+ pool['stats'][stat],
+ (pool['id'],)
+ )
+
+ def get_fs(self):
+ fs_map = self.get('fs_map')
+ servers = self.get_service_list()
+ active_daemons = []
+ for fs in fs_map['filesystems']:
+ # collect fs metadata
+ data_pools = ",".join([str(pool)
+ for pool in fs['mdsmap']['data_pools']])
+ self.metrics['fs_metadata'].set(1, (
+ data_pools,
+ fs['id'],
+ fs['mdsmap']['metadata_pool'],
+ fs['mdsmap']['fs_name']
+ ))
+ self.log.debug('mdsmap: {}'.format(fs['mdsmap']))
+ for gid, daemon in fs['mdsmap']['info'].items():
+ id_ = daemon['name']
+ host_version = servers.get((id_, 'mds'), ('', ''))
+ self.metrics['mds_metadata'].set(1, (
+ 'mds.{}'.format(id_), fs['id'],
+ host_version[0], daemon['addr'],
+ daemon['rank'], host_version[1]
+ ))
+
+ def get_quorum_status(self):
+ mon_status = json.loads(self.get('mon_status')['json'])
+ servers = self.get_service_list()
+ for mon in mon_status['monmap']['mons']:
+ rank = mon['rank']
+ id_ = mon['name']
+ host_version = servers.get((id_, 'mon'), ('', ''))
+ self.metrics['mon_metadata'].set(1, (
+ 'mon.{}'.format(id_), host_version[0],
+ mon['public_addr'].rsplit(':', 1)[0], rank,
+ host_version[1]
+ ))
+ in_quorum = int(rank in mon_status['quorum'])
+ self.metrics['mon_quorum_status'].set(in_quorum, (
+ 'mon.{}'.format(id_),
+ ))
+
+ def get_mgr_status(self):
+ mgr_map = self.get('mgr_map')
+ servers = self.get_service_list()
+
+ active = mgr_map['active_name']
+ standbys = [s.get('name') for s in mgr_map['standbys']]
+
+ all_mgrs = list(standbys)
+ all_mgrs.append(active)
+
+ all_modules = {module.get('name'):module.get('can_run') for module in mgr_map['available_modules']}
+
+ for mgr in all_mgrs:
+ host_version = servers.get((mgr, 'mgr'), ('', ''))
+ if mgr == active:
+ _state = 1
+ else:
+ _state = 0
+
+ self.metrics['mgr_metadata'].set(1, (
+ 'mgr.{}'.format(mgr), host_version[0],
+ host_version[1]
+ ))
+ self.metrics['mgr_status'].set(_state, (
+ 'mgr.{}'.format(mgr),
+ ))
+ always_on_modules = mgr_map['always_on_modules'].get(self.release_name, [])
+ active_modules = list(always_on_modules)
+ active_modules.extend(mgr_map['modules'])
+
+ for mod_name in all_modules.keys():
+
+ if mod_name in always_on_modules:
+ _state = 2
+ elif mod_name in active_modules:
+ _state = 1
+ else:
+ _state = 0
+
+ _can_run = 1 if all_modules[mod_name] else 0
+ self.metrics['mgr_module_status'].set(_state, (mod_name,))
+ self.metrics['mgr_module_can_run'].set(_can_run, (mod_name,))
+
+ def get_pg_status(self):
+
+ pg_summary = self.get('pg_summary')
+
+ for pool in pg_summary['by_pool']:
+ num_by_state = dict((state, 0) for state in PG_STATES)
+ num_by_state['total'] = 0
+
+ for state_name, count in pg_summary['by_pool'][pool].items():
+ for state in state_name.split('+'):
+ num_by_state[state] += count
+ num_by_state['total'] += count
+
+ for state, num in num_by_state.items():
+ try:
+ self.metrics["pg_{}".format(state)].set(num, (pool,))
+ except KeyError:
+ self.log.warn("skipping pg in unknown state {}".format(state))
+
+ def get_osd_stats(self):
+ osd_stats = self.get('osd_stats')
+ for osd in osd_stats['osd_stats']:
+ id_ = osd['osd']
+ for stat in OSD_STATS:
+ val = osd['perf_stat'][stat]
+ self.metrics['osd_{}'.format(stat)].set(val, (
+ 'osd.{}'.format(id_),
+ ))
+
+ def get_service_list(self):
+ ret = {}
+ for server in self.list_servers():
+ version = server.get('ceph_version', '')
+ host = server.get('hostname', '')
+ for service in server.get('services', []):
+ ret.update({(service['id'], service['type']): (host, version)})
+ return ret
+
+ def get_metadata_and_osd_status(self):
+ osd_map = self.get('osd_map')
+ osd_flags = osd_map['flags'].split(',')
+ for flag in OSD_FLAGS:
+ self.metrics['osd_flag_{}'.format(flag)].set(
+ int(flag in osd_flags)
+ )
+
+ osd_devices = self.get('osd_map_crush')['devices']
+ servers = self.get_service_list()
+ for osd in osd_map['osds']:
+ # id can be used to link osd metrics and metadata
+ id_ = osd['osd']
+ # collect osd metadata
+ p_addr = osd['public_addr'].rsplit(':', 1)[0]
+ c_addr = osd['cluster_addr'].rsplit(':', 1)[0]
+ if p_addr == "-" or c_addr == "-":
+ self.log.info(
+ "Missing address metadata for osd {0}, skipping occupation"
+ " and metadata records for this osd".format(id_)
+ )
+ continue
+
+ dev_class = None
+ for osd_device in osd_devices:
+ if osd_device['id'] == id_:
+ dev_class = osd_device.get('class', '')
+ break
+
+ if dev_class is None:
+ self.log.info(
+ "OSD {0} is missing from CRUSH map, skipping output".format(
+ id_))
+ continue
+
+ host_version = servers.get((str(id_), 'osd'), ('', ''))
+
+ # collect disk occupation metadata
+ osd_metadata = self.get_metadata("osd", str(id_))
+ if osd_metadata is None:
+ continue
+
+ obj_store = osd_metadata.get('osd_objectstore', '')
+ f_iface = osd_metadata.get('front_iface', '')
+ b_iface = osd_metadata.get('back_iface', '')
+
+ self.metrics['osd_metadata'].set(1, (
+ b_iface,
+ 'osd.{}'.format(id_),
+ c_addr,
+ dev_class,
+ f_iface,
+ host_version[0],
+ obj_store,
+ p_addr,
+ host_version[1]
+ ))
+
+ # collect osd status
+ for state in OSD_STATUS:
+ status = osd[state]
+ self.metrics['osd_{}'.format(state)].set(status, (
+ 'osd.{}'.format(id_),
+ ))
+
+ osd_dev_node = None
+ if obj_store == "filestore":
+ # collect filestore backend device
+ osd_dev_node = osd_metadata.get(
+ 'backend_filestore_dev_node', None)
+ # collect filestore journal device
+ osd_wal_dev_node = osd_metadata.get('osd_journal', '')
+ osd_db_dev_node = ''
+ elif obj_store == "bluestore":
+ # collect bluestore backend device
+ osd_dev_node = osd_metadata.get(
+ 'bluestore_bdev_dev_node', None)
+ # collect bluestore wal backend
+ osd_wal_dev_node = osd_metadata.get('bluefs_wal_dev_node', '')
+ # collect bluestore db backend
+ osd_db_dev_node = osd_metadata.get('bluefs_db_dev_node', '')
+ if osd_dev_node and osd_dev_node == "unknown":
+ osd_dev_node = None
+
+ osd_hostname = osd_metadata.get('hostname', None)
+ if osd_dev_node and osd_hostname:
+ self.log.debug("Got dev for osd {0}: {1}/{2}".format(
+ id_, osd_hostname, osd_dev_node))
+ self.metrics['disk_occupation'].set(1, (
+ "osd.{0}".format(id_),
+ osd_dev_node,
+ osd_db_dev_node,
+ osd_wal_dev_node,
+ osd_hostname
+ ))
+ else:
+ self.log.info("Missing dev node metadata for osd {0}, skipping "
+ "occupation record for this osd".format(id_))
+
+ pool_meta = []
+ for pool in osd_map['pools']:
+ self.metrics['pool_metadata'].set(
+ 1, (pool['pool'], pool['pool_name']))
+
+ # Populate other servers metadata
+ for key, value in servers.items():
+ service_id, service_type = key
+ if service_type == 'rgw':
+ hostname, version = value
+ self.metrics['rgw_metadata'].set(
+ 1,
+ ('{}.{}'.format(service_type, service_id), hostname, version)
+ )
+ elif service_type == 'rbd-mirror':
+ mirror_metadata = self.get_metadata('rbd-mirror', service_id)
+ if mirror_metadata is None:
+ continue
+ mirror_metadata['ceph_daemon'] = '{}.{}'.format(service_type,
+ service_id)
+ self.metrics['rbd_mirror_metadata'].set(
+ 1, (mirror_metadata.get(k, '')
+ for k in RBD_MIRROR_METADATA)
+ )
+
+ def get_num_objects(self):
+ pg_sum = self.get('pg_summary')['pg_stats_sum']['stat_sum']
+ for obj in NUM_OBJECTS:
+ stat = 'num_objects_{}'.format(obj)
+ self.metrics[stat].set(pg_sum[stat])
+
+ def get_rbd_stats(self):
+ # Per RBD image stats is collected by registering a dynamic osd perf
+ # stats query that tells OSDs to group stats for requests associated
+ # with RBD objects by pool, namespace, and image id, which are
+ # extracted from the request object names or other attributes.
+ # The RBD object names have the following prefixes:
+ # - rbd_data.{image_id}. (data stored in the same pool as metadata)
+ # - rbd_data.{pool_id}.{image_id}. (data stored in a dedicated data pool)
+ # - journal_data.{pool_id}.{image_id}. (journal if journaling is enabled)
+ # The pool_id in the object name is the id of the pool with the image
+ # metdata, and should be used in the image spec. If there is no pool_id
+ # in the object name, the image pool is the pool where the object is
+ # located.
+
+ # Parse rbd_stats_pools option, which is a comma or space separated
+ # list of pool[/namespace] entries. If no namespace is specifed the
+ # stats are collected for every namespace in the pool. The wildcard
+ # '*' can be used to indicate all pools or namespaces
+ pools_string = self.get_localized_module_option('rbd_stats_pools', '')
+ pool_keys = []
+ for x in re.split('[\s,]+', pools_string):
+ if not x:
+ continue
+
+ s = x.split('/', 2)
+ pool_name = s[0]
+ namespace_name = None
+ if len(s) == 2:
+ namespace_name = s[1]
+
+ if pool_name == "*":
+ # collect for all pools
+ osd_map = self.get('osd_map')
+ for pool in osd_map['pools']:
+ if 'rbd' not in pool.get('application_metadata', {}):
+ continue
+ pool_keys.append((pool['pool_name'], namespace_name))
+ else:
+ pool_keys.append((pool_name, namespace_name))
+
+ pools = {}
+ for pool_key in pool_keys:
+ pool_name = pool_key[0]
+ namespace_name = pool_key[1]
+ if not namespace_name or namespace_name == "*":
+ # empty set means collect for all namespaces
+ pools[pool_name] = set()
+ continue
+
+ if pool_name not in pools:
+ pools[pool_name] = set()
+ elif not pools[pool_name]:
+ continue
+ pools[pool_name].add(namespace_name)
+
+ rbd_stats_pools = {}
+ for pool_id in list(self.rbd_stats['pools']):
+ name = self.rbd_stats['pools'][pool_id]['name']
+ if name not in pools:
+ del self.rbd_stats['pools'][pool_id]
+ else:
+ rbd_stats_pools[name] = \
+ self.rbd_stats['pools'][pool_id]['ns_names']
+
+ pools_refreshed = False
+ if pools:
+ next_refresh = self.rbd_stats['pools_refresh_time'] + \
+ self.get_localized_module_option(
+ 'rbd_stats_pools_refresh_interval', 300)
+ if rbd_stats_pools != pools or time.time() >= next_refresh:
+ self.refresh_rbd_stats_pools(pools)
+ pools_refreshed = True
+
+ pool_ids = list(self.rbd_stats['pools'])
+ pool_ids.sort()
+ pool_id_regex = '^(' + '|'.join([str(x) for x in pool_ids]) + ')$'
+
+ nspace_names = []
+ for pool_id, pool in self.rbd_stats['pools'].items():
+ if pool['ns_names']:
+ nspace_names.extend(pool['ns_names'])
+ else:
+ nspace_names = []
+ break
+ if nspace_names:
+ namespace_regex = '^(' + \
+ "|".join([re.escape(x)
+ for x in set(nspace_names)]) + ')$'
+ else:
+ namespace_regex = '^(.*)$'
+
+ if 'query' in self.rbd_stats and \
+ (pool_id_regex != self.rbd_stats['query']['key_descriptor'][0]['regex'] or
+ namespace_regex != self.rbd_stats['query']['key_descriptor'][1]['regex']):
+ self.remove_osd_perf_query(self.rbd_stats['query_id'])
+ del self.rbd_stats['query_id']
+ del self.rbd_stats['query']
+
+ if not self.rbd_stats['pools']:
+ return
+
+ counters_info = self.rbd_stats['counters_info']
+
+ if 'query_id' not in self.rbd_stats:
+ query = {
+ 'key_descriptor': [
+ {'type': 'pool_id', 'regex': pool_id_regex},
+ {'type': 'namespace', 'regex': namespace_regex},
+ {'type': 'object_name',
+ 'regex': '^(?:rbd|journal)_data\.(?:([0-9]+)\.)?([^.]+)\.'},
+ ],
+ 'performance_counter_descriptors': list(counters_info),
+ }
+ query_id = self.add_osd_perf_query(query)
+ if query_id is None:
+ self.log.error('failed to add query %s' % query)
+ return
+ self.rbd_stats['query'] = query
+ self.rbd_stats['query_id'] = query_id
+
+ res = self.get_osd_perf_counters(self.rbd_stats['query_id'])
+ for c in res['counters']:
+ # if the pool id is not found in the object name use id of the
+ # pool where the object is located
+ if c['k'][2][0]:
+ pool_id = int(c['k'][2][0])
+ else:
+ pool_id = int(c['k'][0][0])
+ if pool_id not in self.rbd_stats['pools'] and not pools_refreshed:
+ self.refresh_rbd_stats_pools(pools)
+ pools_refreshed = True
+ if pool_id not in self.rbd_stats['pools']:
+ continue
+ pool = self.rbd_stats['pools'][pool_id]
+ nspace_name = c['k'][1][0]
+ if nspace_name not in pool['images']:
+ continue
+ image_id = c['k'][2][1]
+ if image_id not in pool['images'][nspace_name] and \
+ not pools_refreshed:
+ self.refresh_rbd_stats_pools(pools)
+ pool = self.rbd_stats['pools'][pool_id]
+ pools_refreshed = True
+ if image_id not in pool['images'][nspace_name]:
+ continue
+ counters = pool['images'][nspace_name][image_id]['c']
+ for i in range(len(c['c'])):
+ counters[i][0] += c['c'][i][0]
+ counters[i][1] += c['c'][i][1]
+
+ label_names = ("pool", "namespace", "image")
+ for pool_id, pool in self.rbd_stats['pools'].items():
+ pool_name = pool['name']
+ for nspace_name, images in pool['images'].items():
+ for image_id in images:
+ image_name = images[image_id]['n']
+ counters = images[image_id]['c']
+ i = 0
+ for key in counters_info:
+ counter_info = counters_info[key]
+ stattype = self._stattype_to_str(counter_info['type'])
+ labels = (pool_name, nspace_name, image_name)
+ if counter_info['type'] == self.PERFCOUNTER_COUNTER:
+ path = 'rbd_' + key
+ if path not in self.metrics:
+ self.metrics[path] = Metric(
+ stattype,
+ path,
+ counter_info['desc'],
+ label_names,
+ )
+ self.metrics[path].set(counters[i][0], labels)
+ elif counter_info['type'] == self.PERFCOUNTER_LONGRUNAVG:
+ path = 'rbd_' + key + '_sum'
+ if path not in self.metrics:
+ self.metrics[path] = Metric(
+ stattype,
+ path,
+ counter_info['desc'] + ' Total',
+ label_names,
+ )
+ self.metrics[path].set(counters[i][0], labels)
+ path = 'rbd_' + key + '_count'
+ if path not in self.metrics:
+ self.metrics[path] = Metric(
+ 'counter',
+ path,
+ counter_info['desc'] + ' Count',
+ label_names,
+ )
+ self.metrics[path].set(counters[i][1], labels)
+ i += 1
+
+ def refresh_rbd_stats_pools(self, pools):
+ self.log.debug('refreshing rbd pools %s' % (pools))
+
+ rbd = RBD()
+ counters_info = self.rbd_stats['counters_info']
+ for pool_name, cfg_ns_names in pools.items():
+ try:
+ pool_id = self.rados.pool_lookup(pool_name)
+ with self.rados.open_ioctx(pool_name) as ioctx:
+ if pool_id not in self.rbd_stats['pools']:
+ self.rbd_stats['pools'][pool_id] = {'images': {}}
+ pool = self.rbd_stats['pools'][pool_id]
+ pool['name'] = pool_name
+ pool['ns_names'] = cfg_ns_names
+ if cfg_ns_names:
+ nspace_names = list(cfg_ns_names)
+ else:
+ nspace_names = [''] + rbd.namespace_list(ioctx)
+ for nspace_name in pool['images']:
+ if nspace_name not in nspace_names:
+ del pool['images'][nspace_name]
+ for nspace_name in nspace_names:
+ if (nspace_name and
+ not rbd.namespace_exists(ioctx, nspace_name)):
+ self.log.debug('unknown namespace %s for pool %s' %
+ (nspace_name, pool_name))
+ continue
+ ioctx.set_namespace(nspace_name)
+ if nspace_name not in pool['images']:
+ pool['images'][nspace_name] = {}
+ namespace = pool['images'][nspace_name]
+ images = {}
+ for image_meta in RBD().list2(ioctx):
+ image = {'n': image_meta['name']}
+ image_id = image_meta['id']
+ if image_id in namespace:
+ image['c'] = namespace[image_id]['c']
+ else:
+ image['c'] = [[0, 0] for x in counters_info]
+ images[image_id] = image
+ pool['images'][nspace_name] = images
+ except Exception as e:
+ self.log.error('failed listing pool %s: %s' % (pool_name, e))
+ self.rbd_stats['pools_refresh_time'] = time.time()
+
+ def shutdown_rbd_stats(self):
+ if 'query_id' in self.rbd_stats:
+ self.remove_osd_perf_query(self.rbd_stats['query_id'])
+ del self.rbd_stats['query_id']
+ del self.rbd_stats['query']
+ self.rbd_stats['pools'].clear()
+
+ def collect(self):
+ # Clear the metrics before scraping
+ for k in self.metrics.keys():
+ self.metrics[k].clear()
+
+ _start_time = time.time()
+
+ self.get_health()
+ self.get_df()
+ self.get_pool_stats()
+ self.get_fs()
+ self.get_osd_stats()
+ self.get_quorum_status()
+ self.get_mgr_status()
+ self.get_metadata_and_osd_status()
+ self.get_pg_status()
+ self.get_num_objects()
+
+ for daemon, counters in self.get_all_perf_counters().items():
+ for path, counter_info in counters.items():
+ # Skip histograms, they are represented by long running avgs
+ stattype = self._stattype_to_str(counter_info['type'])
+ if not stattype or stattype == 'histogram':
+ self.log.debug('ignoring %s, type %s' % (path, stattype))
+ continue
+
+ path, label_names, labels = self._perfpath_to_path_labels(
+ daemon, path)
+
+ # Get the value of the counter
+ value = self._perfvalue_to_value(
+ counter_info['type'], counter_info['value'])
+
+ # Represent the long running avgs as sum/count pairs
+ if counter_info['type'] & self.PERFCOUNTER_LONGRUNAVG:
+ _path = path + '_sum'
+ if _path not in self.metrics:
+ self.metrics[_path] = Metric(
+ stattype,
+ _path,
+ counter_info['description'] + ' Total',
+ label_names,
+ )
+ self.metrics[_path].set(value, labels)
+
+ _path = path + '_count'
+ if _path not in self.metrics:
+ self.metrics[_path] = Metric(
+ 'counter',
+ _path,
+ counter_info['description'] + ' Count',
+ label_names,
+ )
+ self.metrics[_path].set(counter_info['count'], labels,)
+ else:
+ if path not in self.metrics:
+ self.metrics[path] = Metric(
+ stattype,
+ path,
+ counter_info['description'],
+ label_names,
+ )
+ self.metrics[path].set(value, labels)
+
+ self.get_rbd_stats()
+
+ _end_time = time.time()
+ self.metrics['scrape_duration_seconds'].set(_end_time - _start_time)
+
+ # Return formatted metrics and clear no longer used data
+ _metrics = [m.str_expfmt() for m in self.metrics.values()]
+ for k in self.metrics.keys():
+ self.metrics[k].clear()
+
+ return ''.join(_metrics) + '\n'
+
+ def get_file_sd_config(self):
+ servers = self.list_servers()
+ targets = []
+ for server in servers:
+ hostname = server.get('hostname', '')
+ for service in server.get('services', []):
+ if service['type'] != 'mgr':
+ continue
+ id_ = service['id']
+ # get port for prometheus module at mgr with id_
+ # TODO use get_config_prefix or get_config here once
+ # https://github.com/ceph/ceph/pull/20458 is merged
+ result = CommandResult("")
+ _global_instance.send_command(
+ result, "mon", '',
+ json.dumps({
+ "prefix": "config-key get",
+ 'key': "config/mgr/mgr/prometheus/{}/server_port".format(id_),
+ }),
+ "")
+ r, outb, outs = result.wait()
+ if r != 0:
+ _global_instance.log.error("Failed to retrieve port for mgr {}: {}".format(id_, outs))
+ targets.append('{}:{}'.format(hostname, DEFAULT_PORT))
+ else:
+ port = json.loads(outb)
+ targets.append('{}:{}'.format(hostname, port))
+
+ ret = [
+ {
+ "targets": targets,
+ "labels": {}
+ }
+ ]
+ return 0, json.dumps(ret), ""
+
+ def self_test(self):
+ self.collect()
+ self.get_file_sd_config()
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == 'prometheus file_sd_config':
+ return self.get_file_sd_config()
+ else:
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(cmd['prefix']))
+
+ def serve(self):
+
+ class Root(object):
+
+ # collapse everything to '/'
+ def _cp_dispatch(self, vpath):
+ cherrypy.request.path = ''
+ return self
+
+ @cherrypy.expose
+ def index(self):
+ return '''<!DOCTYPE html>
+<html>
+ <head><title>Ceph Exporter</title></head>
+ <body>
+ <h1>Ceph Exporter</h1>
+ <p><a href='/metrics'>Metrics</a></p>
+ </body>
+</html>'''
+
+ @cherrypy.expose
+ def metrics(self):
+ # Lock the function execution
+ with _global_instance.collect_lock:
+ return self._metrics(_global_instance)
+
+ @staticmethod
+ def _metrics(instance):
+ # Return cached data if available
+ if not instance.collect_cache:
+ raise cherrypy.HTTPError(503, 'No cached data available yet')
+
+ def respond():
+ cherrypy.response.headers['Content-Type'] = 'text/plain'
+ return instance.collect_cache
+
+ if instance.collect_time < instance.scrape_interval:
+ # Respond if cache isn't stale
+ return respond()
+
+ if instance.stale_cache_strategy == instance.STALE_CACHE_RETURN:
+ # Respond even if cache is stale
+ instance.log.info(
+ 'Gathering data took {:.2f} seconds, metrics are stale for {:.2f} seconds, '
+ 'returning metrics from stale cache.'.format(
+ instance.collect_time,
+ instance.collect_time - instance.scrape_interval
+ )
+ )
+ return respond()
+
+ if instance.stale_cache_strategy == instance.STALE_CACHE_FAIL:
+ # Fail if cache is stale
+ msg = (
+ 'Gathering data took {:.2f} seconds, metrics are stale for {:.2f} seconds, '
+ 'returning "service unavailable".'.format(
+ instance.collect_time,
+ instance.collect_time - instance.scrape_interval,
+ )
+ )
+ instance.log.error(msg)
+ raise cherrypy.HTTPError(503, msg)
+
+ # Make the cache timeout for collecting configurable
+ self.scrape_interval = float(self.get_localized_module_option('scrape_interval', 15.0))
+
+ self.stale_cache_strategy = self.get_localized_module_option('stale_cache_strategy', 'log')
+ if self.stale_cache_strategy not in [self.STALE_CACHE_FAIL,
+ self.STALE_CACHE_RETURN]:
+ self.stale_cache_strategy = self.STALE_CACHE_FAIL
+
+ server_addr = self.get_localized_module_option(
+ 'server_addr', get_default_addr())
+ server_port = self.get_localized_module_option(
+ 'server_port', DEFAULT_PORT)
+ self.log.info(
+ "server_addr: %s server_port: %s" %
+ (server_addr, server_port)
+ )
+
+ self.metrics_thread.start()
+
+ # Publish the URI that others may use to access the service we're
+ # about to start serving
+ self.set_uri('http://{0}:{1}/'.format(
+ socket.getfqdn() if server_addr in ['::', '0.0.0.0'] else server_addr,
+ server_port
+ ))
+
+ cherrypy.config.update({
+ 'server.socket_host': server_addr,
+ 'server.socket_port': int(server_port),
+ 'engine.autoreload.on': False
+ })
+ cherrypy.tree.mount(Root(), "/")
+ self.log.info('Starting engine...')
+ cherrypy.engine.start()
+ self.log.info('Engine started.')
+ # wait for the shutdown event
+ self.shutdown_event.wait()
+ self.shutdown_event.clear()
+ # tell metrics collection thread to stop collecting new metrics
+ self.metrics_thread.stop()
+ cherrypy.engine.stop()
+ self.log.info('Engine stopped.')
+ self.shutdown_rbd_stats()
+ # wait for the metrics collection thread to stop
+ self.metrics_thread.join()
+
+ def shutdown(self):
+ self.log.info('Stopping engine...')
+ self.shutdown_event.set()
+
+
+class StandbyModule(MgrStandbyModule):
+ def __init__(self, *args, **kwargs):
+ super(StandbyModule, self).__init__(*args, **kwargs)
+ self.shutdown_event = threading.Event()
+
+ def serve(self):
+ server_addr = self.get_localized_module_option(
+ 'server_addr', get_default_addr())
+ server_port = self.get_localized_module_option(
+ 'server_port', DEFAULT_PORT)
+ self.log.info("server_addr: %s server_port: %s" %
+ (server_addr, server_port))
+ cherrypy.config.update({
+ 'server.socket_host': server_addr,
+ 'server.socket_port': int(server_port),
+ 'engine.autoreload.on': False
+ })
+
+ module = self
+
+ class Root(object):
+ @cherrypy.expose
+ def index(self):
+ active_uri = module.get_active_uri()
+ return '''<!DOCTYPE html>
+<html>
+ <head><title>Ceph Exporter</title></head>
+ <body>
+ <h1>Ceph Exporter</h1>
+ <p><a href='{}metrics'>Metrics</a></p>
+ </body>
+</html>'''.format(active_uri)
+
+ @cherrypy.expose
+ def metrics(self):
+ cherrypy.response.headers['Content-Type'] = 'text/plain'
+ return ''
+
+ cherrypy.tree.mount(Root(), '/', {})
+ self.log.info('Starting engine...')
+ cherrypy.engine.start()
+ self.log.info('Engine started.')
+ # Wait for shutdown event
+ self.shutdown_event.wait()
+ self.shutdown_event.clear()
+ cherrypy.engine.stop()
+ self.log.info('Engine stopped.')
+
+ def shutdown(self):
+ self.log.info("Stopping engine...")
+ self.shutdown_event.set()
+ self.log.info("Stopped engine")
diff --git a/src/pybind/mgr/rbd_support/__init__.py b/src/pybind/mgr/rbd_support/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/rbd_support/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/rbd_support/module.py b/src/pybind/mgr/rbd_support/module.py
new file mode 100644
index 00000000..f8789339
--- /dev/null
+++ b/src/pybind/mgr/rbd_support/module.py
@@ -0,0 +1,1427 @@
+"""
+RBD support module
+"""
+
+import errno
+import json
+import rados
+import rbd
+import re
+import time
+import traceback
+import uuid
+
+from mgr_module import MgrModule
+
+from contextlib import contextmanager
+from datetime import datetime, timedelta
+from functools import partial, wraps
+from threading import Condition, Lock, Thread
+
+
+GLOBAL_POOL_KEY = (None, None)
+
+QUERY_POOL_ID = "pool_id"
+QUERY_POOL_ID_MAP = "pool_id_map"
+QUERY_IDS = "query_ids"
+QUERY_SUM_POOL_COUNTERS = "pool_counters"
+QUERY_RAW_POOL_COUNTERS = "raw_pool_counters"
+QUERY_LAST_REQUEST = "last_request"
+
+OSD_PERF_QUERY_REGEX_MATCH_ALL = '^(.*)$'
+OSD_PERF_QUERY_COUNTERS = ['write_ops',
+ 'read_ops',
+ 'write_bytes',
+ 'read_bytes',
+ 'write_latency',
+ 'read_latency']
+OSD_PERF_QUERY_COUNTERS_INDICES = {
+ OSD_PERF_QUERY_COUNTERS[i]: i for i in range(len(OSD_PERF_QUERY_COUNTERS))}
+
+OSD_PERF_QUERY_LATENCY_COUNTER_INDICES = [4, 5]
+OSD_PERF_QUERY_MAX_RESULTS = 256
+
+POOL_REFRESH_INTERVAL = timedelta(minutes=5)
+QUERY_EXPIRE_INTERVAL = timedelta(minutes=1)
+STATS_RATE_INTERVAL = timedelta(minutes=1)
+
+REPORT_MAX_RESULTS = 64
+
+RBD_TASK_OID = "rbd_task"
+
+TASK_SEQUENCE = "sequence"
+TASK_ID = "id"
+TASK_REFS = "refs"
+TASK_MESSAGE = "message"
+TASK_RETRY_ATTEMPTS = "retry_attempts"
+TASK_RETRY_TIME = "retry_time"
+TASK_RETRY_MESSAGE = "retry_message"
+TASK_IN_PROGRESS = "in_progress"
+TASK_PROGRESS = "progress"
+TASK_CANCELED = "canceled"
+
+TASK_REF_POOL_NAME = "pool_name"
+TASK_REF_POOL_NAMESPACE = "pool_namespace"
+TASK_REF_IMAGE_NAME = "image_name"
+TASK_REF_IMAGE_ID = "image_id"
+TASK_REF_ACTION = "action"
+
+TASK_REF_ACTION_FLATTEN = "flatten"
+TASK_REF_ACTION_REMOVE = "remove"
+TASK_REF_ACTION_TRASH_REMOVE = "trash remove"
+TASK_REF_ACTION_MIGRATION_EXECUTE = "migrate execute"
+TASK_REF_ACTION_MIGRATION_COMMIT = "migrate commit"
+TASK_REF_ACTION_MIGRATION_ABORT = "migrate abort"
+
+VALID_TASK_ACTIONS = [TASK_REF_ACTION_FLATTEN,
+ TASK_REF_ACTION_REMOVE,
+ TASK_REF_ACTION_TRASH_REMOVE,
+ TASK_REF_ACTION_MIGRATION_EXECUTE,
+ TASK_REF_ACTION_MIGRATION_COMMIT,
+ TASK_REF_ACTION_MIGRATION_ABORT]
+
+TASK_RETRY_INTERVAL = timedelta(seconds=30)
+TASK_MAX_RETRY_INTERVAL = timedelta(seconds=300)
+MAX_COMPLETED_TASKS = 50
+
+
+class NotAuthorizedError(Exception):
+ pass
+
+
+def is_authorized(module, pool, namespace):
+ return module.is_authorized({"pool": pool or '',
+ "namespace": namespace or ''})
+
+
+def authorize_request(module, pool, namespace):
+ if not is_authorized(module, pool, namespace):
+ raise NotAuthorizedError("not authorized on pool={}, namespace={}".format(
+ pool, namespace))
+
+
+def extract_pool_key(pool_spec):
+ if not pool_spec:
+ return GLOBAL_POOL_KEY
+
+ match = re.match(r'^([^/]+)(?:/([^/]+))?$', pool_spec)
+ if not match:
+ raise ValueError("Invalid pool spec: {}".format(pool_spec))
+ return (match.group(1), match.group(2) or '')
+
+
+def get_rbd_pools(module):
+ osd_map = module.get('osd_map')
+ return {pool['pool']: pool['pool_name'] for pool in osd_map['pools']
+ if 'rbd' in pool.get('application_metadata', {})}
+
+
+class PerfHandler:
+ user_queries = {}
+ image_cache = {}
+
+ lock = Lock()
+ query_condition = Condition(lock)
+ refresh_condition = Condition(lock)
+ thread = None
+
+ image_name_cache = {}
+ image_name_refresh_time = datetime.fromtimestamp(0)
+
+ @classmethod
+ def prepare_regex(cls, value):
+ return '^({})$'.format(value)
+
+ @classmethod
+ def prepare_osd_perf_query(cls, pool_id, namespace, counter_type):
+ pool_id_regex = OSD_PERF_QUERY_REGEX_MATCH_ALL
+ namespace_regex = OSD_PERF_QUERY_REGEX_MATCH_ALL
+ if pool_id:
+ pool_id_regex = cls.prepare_regex(pool_id)
+ if namespace:
+ namespace_regex = cls.prepare_regex(namespace)
+
+ return {
+ 'key_descriptor': [
+ {'type': 'pool_id', 'regex': pool_id_regex},
+ {'type': 'namespace', 'regex': namespace_regex},
+ {'type': 'object_name',
+ 'regex': '^(?:rbd|journal)_data\\.(?:([0-9]+)\\.)?([^.]+)\\.'},
+ ],
+ 'performance_counter_descriptors': OSD_PERF_QUERY_COUNTERS,
+ 'limit': {'order_by': counter_type,
+ 'max_count': OSD_PERF_QUERY_MAX_RESULTS},
+ }
+
+ @classmethod
+ def pool_spec_search_keys(cls, pool_key):
+ return [pool_key[0:len(pool_key) - x]
+ for x in range(0, len(pool_key) + 1)]
+
+ @classmethod
+ def submatch_pool_key(cls, pool_key, search_key):
+ return ((pool_key[1] == search_key[1] or not search_key[1])
+ and (pool_key[0] == search_key[0] or not search_key[0]))
+
+ def __init__(self, module):
+ self.module = module
+ self.log = module.log
+
+ self.thread = Thread(target=self.run)
+ self.thread.start()
+
+ def run(self):
+ try:
+ self.log.info("PerfHandler: starting")
+ while True:
+ with self.lock:
+ self.scrub_expired_queries()
+ self.process_raw_osd_perf_counters()
+ self.refresh_condition.notify()
+
+ stats_period = int(self.module.get_ceph_option("mgr_stats_period"))
+ self.query_condition.wait(stats_period)
+
+ self.log.debug("PerfHandler: tick")
+
+ except Exception as ex:
+ self.log.fatal("Fatal runtime error: {}\n{}".format(
+ ex, traceback.format_exc()))
+
+ def merge_raw_osd_perf_counters(self, pool_key, query, now_ts,
+ resolve_image_names):
+ pool_id_map = query[QUERY_POOL_ID_MAP]
+
+ # collect and combine the raw counters from all sort orders
+ raw_pool_counters = query.setdefault(QUERY_RAW_POOL_COUNTERS, {})
+ for query_id in query[QUERY_IDS]:
+ res = self.module.get_osd_perf_counters(query_id)
+ for counter in res['counters']:
+ # replace pool id from object name if it exists
+ k = counter['k']
+ pool_id = int(k[2][0]) if k[2][0] else int(k[0][0])
+ namespace = k[1][0]
+ image_id = k[2][1]
+
+ # ignore metrics from non-matching pools/namespaces
+ if pool_id not in pool_id_map:
+ continue
+ if pool_key[1] is not None and pool_key[1] != namespace:
+ continue
+
+ # flag the pool (and namespace) for refresh if we cannot find
+ # image name in the cache
+ resolve_image_key = (pool_id, namespace)
+ if image_id not in self.image_name_cache.get(resolve_image_key, {}):
+ resolve_image_names.add(resolve_image_key)
+
+ # copy the 'sum' counter values for each image (ignore count)
+ # if we haven't already processed it for this round
+ raw_namespaces = raw_pool_counters.setdefault(pool_id, {})
+ raw_images = raw_namespaces.setdefault(namespace, {})
+ raw_image = raw_images.setdefault(image_id, [None, None])
+
+ # save the last two perf counters for each image
+ if raw_image[0] and raw_image[0][0] < now_ts:
+ raw_image[1] = raw_image[0]
+ raw_image[0] = None
+ if not raw_image[0]:
+ raw_image[0] = [now_ts, [int(x[0]) for x in counter['c']]]
+
+ self.log.debug("merge_raw_osd_perf_counters: {}".format(raw_pool_counters))
+ return raw_pool_counters
+
+ def sum_osd_perf_counters(self, query, raw_pool_counters, now_ts):
+ # update the cumulative counters for each image
+ sum_pool_counters = query.setdefault(QUERY_SUM_POOL_COUNTERS, {})
+ for pool_id, raw_namespaces in raw_pool_counters.items():
+ sum_namespaces = sum_pool_counters.setdefault(pool_id, {})
+ for namespace, raw_images in raw_namespaces.items():
+ sum_namespace = sum_namespaces.setdefault(namespace, {})
+ for image_id, raw_image in raw_images.items():
+ # zero-out non-updated raw counters
+ if not raw_image[0]:
+ continue
+ elif raw_image[0][0] < now_ts:
+ raw_image[1] = raw_image[0]
+ raw_image[0] = [now_ts, [0 for x in raw_image[1][1]]]
+ continue
+
+ counters = raw_image[0][1]
+
+ # copy raw counters if this is a newly discovered image or
+ # increment existing counters
+ sum_image = sum_namespace.setdefault(image_id, None)
+ if sum_image:
+ for i in range(len(counters)):
+ sum_image[i] += counters[i]
+ else:
+ sum_namespace[image_id] = [x for x in counters]
+
+ self.log.debug("sum_osd_perf_counters: {}".format(sum_pool_counters))
+ return sum_pool_counters
+
+ def refresh_image_names(self, resolve_image_names):
+ for pool_id, namespace in resolve_image_names:
+ image_key = (pool_id, namespace)
+ images = self.image_name_cache.setdefault(image_key, {})
+ with self.module.rados.open_ioctx2(int(pool_id)) as ioctx:
+ ioctx.set_namespace(namespace)
+ for image_meta in rbd.RBD().list2(ioctx):
+ images[image_meta['id']] = image_meta['name']
+ self.log.debug("resolve_image_names: {}={}".format(image_key, images))
+
+ def scrub_missing_images(self):
+ for pool_key, query in self.user_queries.items():
+ raw_pool_counters = query.get(QUERY_RAW_POOL_COUNTERS, {})
+ sum_pool_counters = query.get(QUERY_SUM_POOL_COUNTERS, {})
+ for pool_id, sum_namespaces in sum_pool_counters.items():
+ raw_namespaces = raw_pool_counters.get(pool_id, {})
+ for namespace, sum_images in sum_namespaces.items():
+ raw_images = raw_namespaces.get(namespace, {})
+
+ image_key = (pool_id, namespace)
+ image_names = self.image_name_cache.get(image_key, {})
+ for image_id in list(sum_images.keys()):
+ # scrub image counters if we failed to resolve image name
+ if image_id not in image_names:
+ self.log.debug("scrub_missing_images: dropping {}/{}".format(
+ image_key, image_id))
+ del sum_images[image_id]
+ if image_id in raw_images:
+ del raw_images[image_id]
+
+ def process_raw_osd_perf_counters(self):
+ now = datetime.now()
+ now_ts = int(now.strftime("%s"))
+
+ # clear the image name cache if we need to refresh all active pools
+ if self.image_name_cache and \
+ self.image_name_refresh_time + POOL_REFRESH_INTERVAL < now:
+ self.log.debug("process_raw_osd_perf_counters: expiring image name cache")
+ self.image_name_cache = {}
+
+ resolve_image_names = set()
+ for pool_key, query in self.user_queries.items():
+ if not query[QUERY_IDS]:
+ continue
+
+ raw_pool_counters = self.merge_raw_osd_perf_counters(
+ pool_key, query, now_ts, resolve_image_names)
+ self.sum_osd_perf_counters(query, raw_pool_counters, now_ts)
+
+ if resolve_image_names:
+ self.image_name_refresh_time = now
+ self.refresh_image_names(resolve_image_names)
+ self.scrub_missing_images()
+ elif not self.image_name_cache:
+ self.scrub_missing_images()
+
+ def resolve_pool_id(self, pool_name):
+ pool_id = self.module.rados.pool_lookup(pool_name)
+ if not pool_id:
+ raise rados.ObjectNotFound("Pool '{}' not found".format(pool_name),
+ errno.ENOENT)
+ return pool_id
+
+ def scrub_expired_queries(self):
+ # perf counters need to be periodically refreshed to continue
+ # to be registered
+ expire_time = datetime.now() - QUERY_EXPIRE_INTERVAL
+ for pool_key in list(self.user_queries.keys()):
+ user_query = self.user_queries[pool_key]
+ if user_query[QUERY_LAST_REQUEST] < expire_time:
+ self.unregister_osd_perf_queries(pool_key, user_query[QUERY_IDS])
+ del self.user_queries[pool_key]
+
+ def register_osd_perf_queries(self, pool_id, namespace):
+ query_ids = []
+ try:
+ for counter in OSD_PERF_QUERY_COUNTERS:
+ query = self.prepare_osd_perf_query(pool_id, namespace, counter)
+ self.log.debug("register_osd_perf_queries: {}".format(query))
+
+ query_id = self.module.add_osd_perf_query(query)
+ if query_id is None:
+ raise RuntimeError('Failed to add OSD perf query: {}'.format(query))
+ query_ids.append(query_id)
+
+ except Exception:
+ for query_id in query_ids:
+ self.module.remove_osd_perf_query(query_id)
+ raise
+
+ return query_ids
+
+ def unregister_osd_perf_queries(self, pool_key, query_ids):
+ self.log.info("unregister_osd_perf_queries: pool_key={}, query_ids={}".format(
+ pool_key, query_ids))
+ for query_id in query_ids:
+ self.module.remove_osd_perf_query(query_id)
+ query_ids[:] = []
+
+ def register_query(self, pool_key):
+ if pool_key not in self.user_queries:
+ pool_id = None
+ if pool_key[0]:
+ pool_id = self.resolve_pool_id(pool_key[0])
+
+ user_query = {
+ QUERY_POOL_ID: pool_id,
+ QUERY_POOL_ID_MAP: {pool_id: pool_key[0]},
+ QUERY_IDS: self.register_osd_perf_queries(pool_id, pool_key[1]),
+ QUERY_LAST_REQUEST: datetime.now()
+ }
+
+ self.user_queries[pool_key] = user_query
+
+ # force an immediate stat pull if this is a new query
+ self.query_condition.notify()
+ self.refresh_condition.wait(5)
+
+ else:
+ user_query = self.user_queries[pool_key]
+
+ # ensure query doesn't expire
+ user_query[QUERY_LAST_REQUEST] = datetime.now()
+
+ if pool_key == GLOBAL_POOL_KEY:
+ # refresh the global pool id -> name map upon each
+ # processing period
+ user_query[QUERY_POOL_ID_MAP] = {
+ pool_id: pool_name for pool_id, pool_name
+ in get_rbd_pools(self.module).items()}
+
+ self.log.debug("register_query: pool_key={}, query_ids={}".format(
+ pool_key, user_query[QUERY_IDS]))
+
+ return user_query
+
+ def extract_stat(self, index, raw_image, sum_image):
+ # require two raw counters between a fixed time window
+ if not raw_image or not raw_image[0] or not raw_image[1]:
+ return 0
+
+ current_time = raw_image[0][0]
+ previous_time = raw_image[1][0]
+ if current_time <= previous_time or \
+ current_time - previous_time > STATS_RATE_INTERVAL.total_seconds():
+ return 0
+
+ current_value = raw_image[0][1][index]
+ instant_rate = float(current_value) / (current_time - previous_time)
+
+ # convert latencies from sum to average per op
+ ops_index = None
+ if OSD_PERF_QUERY_COUNTERS[index] == 'write_latency':
+ ops_index = OSD_PERF_QUERY_COUNTERS_INDICES['write_ops']
+ elif OSD_PERF_QUERY_COUNTERS[index] == 'read_latency':
+ ops_index = OSD_PERF_QUERY_COUNTERS_INDICES['read_ops']
+
+ if ops_index is not None:
+ ops = max(1, self.extract_stat(ops_index, raw_image, sum_image))
+ instant_rate /= ops
+
+ return instant_rate
+
+ def extract_counter(self, index, raw_image, sum_image):
+ if sum_image:
+ return sum_image[index]
+ return 0
+
+ def generate_report(self, query, sort_by, extract_data):
+ pool_id_map = query[QUERY_POOL_ID_MAP]
+ sum_pool_counters = query.setdefault(QUERY_SUM_POOL_COUNTERS, {})
+ raw_pool_counters = query.setdefault(QUERY_RAW_POOL_COUNTERS, {})
+
+ sort_by_index = OSD_PERF_QUERY_COUNTERS.index(sort_by)
+
+ # pre-sort and limit the response
+ results = []
+ for pool_id, sum_namespaces in sum_pool_counters.items():
+ if pool_id not in pool_id_map:
+ continue
+ raw_namespaces = raw_pool_counters.get(pool_id, {})
+ for namespace, sum_images in sum_namespaces.items():
+ raw_images = raw_namespaces.get(namespace, {})
+ for image_id, sum_image in sum_images.items():
+ raw_image = raw_images.get(image_id, [])
+
+ # always sort by recent IO activity
+ results.append([(pool_id, namespace, image_id),
+ self.extract_stat(sort_by_index, raw_image,
+ sum_image)])
+ results = sorted(results, key=lambda x: x[1], reverse=True)[:REPORT_MAX_RESULTS]
+
+ # build the report in sorted order
+ pool_descriptors = {}
+ counters = []
+ for key, _ in results:
+ pool_id = key[0]
+ pool_name = pool_id_map[pool_id]
+
+ namespace = key[1]
+ image_id = key[2]
+ image_names = self.image_name_cache.get((pool_id, namespace), {})
+ image_name = image_names[image_id]
+
+ raw_namespaces = raw_pool_counters.get(pool_id, {})
+ raw_images = raw_namespaces.get(namespace, {})
+ raw_image = raw_images.get(image_id, [])
+
+ sum_namespaces = sum_pool_counters[pool_id]
+ sum_images = sum_namespaces[namespace]
+ sum_image = sum_images.get(image_id, [])
+
+ pool_descriptor = pool_name
+ if namespace:
+ pool_descriptor += "/{}".format(namespace)
+ pool_index = pool_descriptors.setdefault(pool_descriptor,
+ len(pool_descriptors))
+ image_descriptor = "{}/{}".format(pool_index, image_name)
+ data = [extract_data(i, raw_image, sum_image)
+ for i in range(len(OSD_PERF_QUERY_COUNTERS))]
+
+ # skip if no data to report
+ if data == [0 for i in range(len(OSD_PERF_QUERY_COUNTERS))]:
+ continue
+
+ counters.append({image_descriptor: data})
+
+ return {idx: descriptor for descriptor, idx
+ in pool_descriptors.items()}, \
+ counters
+
+ def get_perf_data(self, report, pool_spec, sort_by, extract_data):
+ self.log.debug("get_perf_{}s: pool_spec={}, sort_by={}".format(
+ report, pool_spec, sort_by))
+ self.scrub_expired_queries()
+
+ pool_key = extract_pool_key(pool_spec)
+ authorize_request(self.module, pool_key[0], pool_key[1])
+
+ user_query = self.register_query(pool_key)
+
+ now = datetime.now()
+ pool_descriptors, counters = self.generate_report(
+ user_query, sort_by, extract_data)
+
+ report = {
+ 'timestamp': time.mktime(now.timetuple()),
+ '{}_descriptors'.format(report): OSD_PERF_QUERY_COUNTERS,
+ 'pool_descriptors': pool_descriptors,
+ '{}s'.format(report): counters
+ }
+
+ return 0, json.dumps(report), ""
+
+ def get_perf_stats(self, pool_spec, sort_by):
+ return self.get_perf_data(
+ "stat", pool_spec, sort_by, self.extract_stat)
+
+ def get_perf_counters(self, pool_spec, sort_by):
+ return self.get_perf_data(
+ "counter", pool_spec, sort_by, self.extract_counter)
+
+ def handle_command(self, inbuf, prefix, cmd):
+ with self.lock:
+ if prefix == 'image stats':
+ return self.get_perf_stats(cmd.get('pool_spec', None),
+ cmd.get('sort_by', OSD_PERF_QUERY_COUNTERS[0]))
+ elif prefix == 'image counters':
+ return self.get_perf_counters(cmd.get('pool_spec', None),
+ cmd.get('sort_by', OSD_PERF_QUERY_COUNTERS[0]))
+
+ raise NotImplementedError(cmd['prefix'])
+
+
+class Throttle:
+ def __init__(self, throttle_period):
+ self.throttle_period = throttle_period
+ self.time_of_last_call = datetime.min
+
+ def __call__(self, fn):
+ @wraps(fn)
+ def wrapper(*args, **kwargs):
+ now = datetime.now()
+ if self.time_of_last_call + self.throttle_period <= now:
+ self.time_of_last_call = now
+ return fn(*args, **kwargs)
+ return wrapper
+
+
+class Task:
+ def __init__(self, sequence, task_id, message, refs):
+ self.sequence = sequence
+ self.task_id = task_id
+ self.message = message
+ self.refs = refs
+ self.retry_message = None
+ self.retry_attempts = 0
+ self.retry_time = None
+ self.in_progress = False
+ self.progress = 0.0
+ self.canceled = False
+ self.failed = False
+ self.progress_posted = False
+
+ def __str__(self):
+ return self.to_json()
+
+ @property
+ def sequence_key(self):
+ return "{0:016X}".format(self.sequence)
+
+ def cancel(self):
+ self.canceled = True
+ self.fail("Operation canceled")
+
+ def fail(self, message):
+ self.failed = True
+ self.failure_message = message
+
+ def to_dict(self):
+ d = {TASK_SEQUENCE: self.sequence,
+ TASK_ID: self.task_id,
+ TASK_MESSAGE: self.message,
+ TASK_REFS: self.refs
+ }
+ if self.retry_message:
+ d[TASK_RETRY_MESSAGE] = self.retry_message
+ if self.retry_attempts:
+ d[TASK_RETRY_ATTEMPTS] = self.retry_attempts
+ if self.retry_time:
+ d[TASK_RETRY_TIME] = self.retry_time.isoformat()
+ if self.in_progress:
+ d[TASK_IN_PROGRESS] = True
+ d[TASK_PROGRESS] = self.progress
+ if self.canceled:
+ d[TASK_CANCELED] = True
+ return d
+
+ def to_json(self):
+ return str(json.dumps(self.to_dict()))
+
+ @classmethod
+ def from_json(cls, val):
+ try:
+ d = json.loads(val)
+ action = d.get(TASK_REFS, {}).get(TASK_REF_ACTION)
+ if action not in VALID_TASK_ACTIONS:
+ raise ValueError("Invalid task action: {}".format(action))
+
+ return Task(d[TASK_SEQUENCE], d[TASK_ID], d[TASK_MESSAGE], d[TASK_REFS])
+ except json.JSONDecodeError as e:
+ raise ValueError("Invalid JSON ({})".format(str(e)))
+ except KeyError as e:
+ raise ValueError("Invalid task format (missing key {})".format(str(e)))
+
+
+class TaskHandler:
+ lock = Lock()
+ condition = Condition(lock)
+ thread = None
+
+ in_progress_task = None
+ tasks_by_sequence = dict()
+ tasks_by_id = dict()
+
+ completed_tasks = []
+
+ sequence = 0
+
+ def __init__(self, module):
+ self.module = module
+ self.log = module.log
+
+ with self.lock:
+ self.init_task_queue()
+
+ self.thread = Thread(target=self.run)
+ self.thread.start()
+
+ @property
+ def default_pool_name(self):
+ return self.module.get_ceph_option("rbd_default_pool")
+
+ def extract_pool_spec(self, pool_spec):
+ pool_spec = extract_pool_key(pool_spec)
+ if pool_spec == GLOBAL_POOL_KEY:
+ pool_spec = (self.default_pool_name, '')
+ return pool_spec
+
+ def extract_image_spec(self, image_spec):
+ match = re.match(r'^(?:([^/]+)/(?:([^/]+)/)?)?([^/@]+)$',
+ image_spec or '')
+ if not match:
+ raise ValueError("Invalid image spec: {}".format(image_spec))
+ return (match.group(1) or self.default_pool_name, match.group(2) or '',
+ match.group(3))
+
+ def run(self):
+ try:
+ self.log.info("TaskHandler: starting")
+ while True:
+ with self.lock:
+ now = datetime.now()
+ for sequence in sorted([sequence for sequence, task
+ in self.tasks_by_sequence.items()
+ if not task.retry_time or task.retry_time <= now]):
+ self.execute_task(sequence)
+
+ self.condition.wait(5)
+ self.log.debug("TaskHandler: tick")
+
+ except Exception as ex:
+ self.log.fatal("Fatal runtime error: {}\n{}".format(
+ ex, traceback.format_exc()))
+
+ @contextmanager
+ def open_ioctx(self, spec):
+ try:
+ with self.module.rados.open_ioctx(spec[0]) as ioctx:
+ ioctx.set_namespace(spec[1])
+ yield ioctx
+ except rados.ObjectNotFound:
+ self.log.error("Failed to locate pool {}".format(spec[0]))
+ raise
+
+ @classmethod
+ def format_image_spec(cls, image_spec):
+ image = image_spec[2]
+ if image_spec[1]:
+ image = "{}/{}".format(image_spec[1], image)
+ if image_spec[0]:
+ image = "{}/{}".format(image_spec[0], image)
+ return image
+
+ def init_task_queue(self):
+ for pool_id, pool_name in get_rbd_pools(self.module).items():
+ try:
+ with self.module.rados.open_ioctx2(int(pool_id)) as ioctx:
+ self.load_task_queue(ioctx, pool_name)
+
+ try:
+ namespaces = rbd.RBD().namespace_list(ioctx)
+ except rbd.OperationNotSupported:
+ self.log.debug("Namespaces not supported")
+ continue
+
+ for namespace in namespaces:
+ ioctx.set_namespace(namespace)
+ self.load_task_queue(ioctx, pool_name)
+
+ except rados.ObjectNotFound:
+ # pool DNE
+ pass
+
+ if self.tasks_by_sequence:
+ self.sequence = list(sorted(self.tasks_by_sequence.keys()))[-1]
+
+ self.log.debug("sequence={}, tasks_by_sequence={}, tasks_by_id={}".format(
+ self.sequence, str(self.tasks_by_sequence), str(self.tasks_by_id)))
+
+ def load_task_queue(self, ioctx, pool_name):
+ pool_spec = pool_name
+ if ioctx.nspace:
+ pool_spec += "/{}".format(ioctx.nspace)
+
+ start_after = ''
+ try:
+ while True:
+ with rados.ReadOpCtx() as read_op:
+ self.log.info("load_task_task: {}, start_after={}".format(
+ pool_spec, start_after))
+ it, ret = ioctx.get_omap_vals(read_op, start_after, "", 128)
+ ioctx.operate_read_op(read_op, RBD_TASK_OID)
+
+ it = list(it)
+ for k, v in it:
+ start_after = k
+ v = v.decode()
+ self.log.info("load_task_task: task={}".format(v))
+
+ try:
+ task = Task.from_json(v)
+ self.append_task(task)
+ except ValueError:
+ self.log.error("Failed to decode task: pool_spec={}, task={}".format(pool_spec, v))
+
+ if not it:
+ break
+
+ except StopIteration:
+ pass
+ except rados.ObjectNotFound:
+ # rbd_task DNE
+ pass
+
+ def append_task(self, task):
+ self.tasks_by_sequence[task.sequence] = task
+ self.tasks_by_id[task.task_id] = task
+
+ def task_refs_match(self, task_refs, refs):
+ if TASK_REF_IMAGE_ID not in refs and TASK_REF_IMAGE_ID in task_refs:
+ task_refs = task_refs.copy()
+ del task_refs[TASK_REF_IMAGE_ID]
+
+ self.log.debug("task_refs_match: ref1={}, ref2={}".format(task_refs, refs))
+ return task_refs == refs
+
+ def find_task(self, refs):
+ self.log.debug("find_task: refs={}".format(refs))
+
+ # search for dups and return the original
+ for task_id in reversed(sorted(self.tasks_by_id.keys())):
+ task = self.tasks_by_id[task_id]
+ if self.task_refs_match(task.refs, refs):
+ return task
+
+ # search for a completed task (message replay)
+ for task in reversed(self.completed_tasks):
+ if self.task_refs_match(task.refs, refs):
+ return task
+
+ def add_task(self, ioctx, message, refs):
+ self.log.debug("add_task: message={}, refs={}".format(message, refs))
+
+ # ensure unique uuid across all pools
+ while True:
+ task_id = str(uuid.uuid4())
+ if task_id not in self.tasks_by_id:
+ break
+
+ self.sequence += 1
+ task = Task(self.sequence, task_id, message, refs)
+
+ # add the task to the rbd_task omap
+ task_json = task.to_json()
+ omap_keys = (task.sequence_key, )
+ omap_vals = (str.encode(task_json), )
+ self.log.info("adding task: {} {}".format(omap_keys[0], omap_vals[0]))
+
+ with rados.WriteOpCtx() as write_op:
+ ioctx.set_omap(write_op, omap_keys, omap_vals)
+ ioctx.operate_write_op(write_op, RBD_TASK_OID)
+ self.append_task(task)
+
+ self.condition.notify()
+ return task_json
+
+ def remove_task(self, ioctx, task, remove_in_memory=True):
+ self.log.info("remove_task: task={}".format(str(task)))
+ omap_keys = (task.sequence_key, )
+ try:
+ with rados.WriteOpCtx() as write_op:
+ ioctx.remove_omap_keys(write_op, omap_keys)
+ ioctx.operate_write_op(write_op, RBD_TASK_OID)
+ except rados.ObjectNotFound:
+ pass
+
+ if remove_in_memory:
+ try:
+ del self.tasks_by_id[task.task_id]
+ del self.tasks_by_sequence[task.sequence]
+
+ # keep a record of the last N tasks to help avoid command replay
+ # races
+ if not task.failed and not task.canceled:
+ self.log.debug("remove_task: moving to completed tasks")
+ self.completed_tasks.append(task)
+ self.completed_tasks = self.completed_tasks[-MAX_COMPLETED_TASKS:]
+
+ except KeyError:
+ pass
+
+ def execute_task(self, sequence):
+ task = self.tasks_by_sequence[sequence]
+ self.log.info("execute_task: task={}".format(str(task)))
+
+ pool_valid = False
+ try:
+ with self.open_ioctx((task.refs[TASK_REF_POOL_NAME],
+ task.refs[TASK_REF_POOL_NAMESPACE])) as ioctx:
+ pool_valid = True
+
+ action = task.refs[TASK_REF_ACTION]
+ execute_fn = {TASK_REF_ACTION_FLATTEN: self.execute_flatten,
+ TASK_REF_ACTION_REMOVE: self.execute_remove,
+ TASK_REF_ACTION_TRASH_REMOVE: self.execute_trash_remove,
+ TASK_REF_ACTION_MIGRATION_EXECUTE: self.execute_migration_execute,
+ TASK_REF_ACTION_MIGRATION_COMMIT: self.execute_migration_commit,
+ TASK_REF_ACTION_MIGRATION_ABORT: self.execute_migration_abort
+ }.get(action)
+ if not execute_fn:
+ self.log.error("Invalid task action: {}".format(action))
+ else:
+ task.in_progress = True
+ self.in_progress_task = task
+
+ self.lock.release()
+ try:
+ execute_fn(ioctx, task)
+
+ except rbd.OperationCanceled:
+ self.log.info("Operation canceled: task={}".format(
+ str(task)))
+
+ finally:
+ self.lock.acquire()
+
+ task.in_progress = False
+ self.in_progress_task = None
+
+ self.complete_progress(task)
+ self.remove_task(ioctx, task)
+
+ except rados.ObjectNotFound as e:
+ self.log.error("execute_task: {}".format(e))
+ if pool_valid:
+ task.retry_message = "{}".format(e)
+ self.update_progress(task, 0)
+ else:
+ # pool DNE -- remove the task
+ self.complete_progress(task)
+ self.remove_task(ioctx, task)
+
+ except (rados.Error, rbd.Error) as e:
+ self.log.error("execute_task: {}".format(e))
+ task.retry_message = "{}".format(e)
+ self.update_progress(task, 0)
+
+ finally:
+ task.in_progress = False
+ task.retry_attempts += 1
+ task.retry_time = datetime.now() + min(
+ TASK_RETRY_INTERVAL * task.retry_attempts,
+ TASK_MAX_RETRY_INTERVAL)
+
+ def progress_callback(self, task, current, total):
+ progress = float(current) / float(total)
+ self.log.debug("progress_callback: task={}, progress={}".format(
+ str(task), progress))
+
+ # avoid deadlocking when a new command comes in during a progress callback
+ if not self.lock.acquire(False):
+ return 0
+
+ try:
+ if not self.in_progress_task or self.in_progress_task.canceled:
+ return -rbd.ECANCELED
+ self.in_progress_task.progress = progress
+ finally:
+ self.lock.release()
+
+ if not task.progress_posted:
+ # delayed creation of progress event until first callback
+ self.post_progress(task, progress)
+ else:
+ self.throttled_update_progress(task, progress)
+
+ return 0
+
+ def execute_flatten(self, ioctx, task):
+ self.log.info("execute_flatten: task={}".format(str(task)))
+
+ try:
+ with rbd.Image(ioctx, task.refs[TASK_REF_IMAGE_NAME]) as image:
+ image.flatten(on_progress=partial(self.progress_callback, task))
+ except rbd.InvalidArgument:
+ task.fail("Image does not have parent")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def execute_remove(self, ioctx, task):
+ self.log.info("execute_remove: task={}".format(str(task)))
+
+ try:
+ rbd.RBD().remove(ioctx, task.refs[TASK_REF_IMAGE_NAME],
+ on_progress=partial(self.progress_callback, task))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def execute_trash_remove(self, ioctx, task):
+ self.log.info("execute_trash_remove: task={}".format(str(task)))
+
+ try:
+ rbd.RBD().trash_remove(ioctx, task.refs[TASK_REF_IMAGE_ID],
+ on_progress=partial(self.progress_callback, task))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def execute_migration_execute(self, ioctx, task):
+ self.log.info("execute_migration_execute: task={}".format(str(task)))
+
+ try:
+ rbd.RBD().migration_execute(ioctx, task.refs[TASK_REF_IMAGE_NAME],
+ on_progress=partial(self.progress_callback, task))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+ except rbd.InvalidArgument:
+ task.fail("Image is not migrating")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def execute_migration_commit(self, ioctx, task):
+ self.log.info("execute_migration_commit: task={}".format(str(task)))
+
+ try:
+ rbd.RBD().migration_commit(ioctx, task.refs[TASK_REF_IMAGE_NAME],
+ on_progress=partial(self.progress_callback, task))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+ except rbd.InvalidArgument:
+ task.fail("Image is not migrating or migration not executed")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def execute_migration_abort(self, ioctx, task):
+ self.log.info("execute_migration_abort: task={}".format(str(task)))
+
+ try:
+ rbd.RBD().migration_abort(ioctx, task.refs[TASK_REF_IMAGE_NAME],
+ on_progress=partial(self.progress_callback, task))
+ except rbd.ImageNotFound:
+ task.fail("Image does not exist")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+ except rbd.InvalidArgument:
+ task.fail("Image is not migrating")
+ self.log.info("{}: task={}".format(task.failure_message, str(task)))
+
+ def complete_progress(self, task):
+ if not task.progress_posted:
+ # ensure progress event exists before we complete/fail it
+ self.post_progress(task, 0)
+
+ self.log.debug("complete_progress: task={}".format(str(task)))
+ try:
+ if task.failed:
+ self.module.remote("progress", "fail", task.task_id,
+ task.failure_message)
+ else:
+ self.module.remote("progress", "complete", task.task_id)
+ except ImportError:
+ # progress module is disabled
+ pass
+
+ def _update_progress(self, task, progress):
+ self.log.debug("update_progress: task={}, progress={}".format(str(task), progress))
+ try:
+ refs = {"origin": "rbd_support"}
+ refs.update(task.refs)
+
+ self.module.remote("progress", "update", task.task_id,
+ task.message, progress, refs)
+ except ImportError:
+ # progress module is disabled
+ pass
+
+ def post_progress(self, task, progress):
+ self._update_progress(task, progress)
+ task.progress_posted = True
+
+ def update_progress(self, task, progress):
+ if task.progress_posted:
+ self._update_progress(task, progress)
+
+ @Throttle(timedelta(seconds=1))
+ def throttled_update_progress(self, task, progress):
+ self.update_progress(task, progress)
+
+ def queue_flatten(self, image_spec):
+ image_spec = self.extract_image_spec(image_spec)
+
+ authorize_request(self.module, image_spec[0], image_spec[1])
+ self.log.info("queue_flatten: {}".format(image_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_FLATTEN,
+ TASK_REF_POOL_NAME: image_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_spec[1],
+ TASK_REF_IMAGE_NAME: image_spec[2]}
+
+ with self.open_ioctx(image_spec) as ioctx:
+ try:
+ with rbd.Image(ioctx, image_spec[2]) as image:
+ refs[TASK_REF_IMAGE_ID] = image.id()
+
+ try:
+ parent_image_id = image.parent_id()
+ except rbd.ImageNotFound:
+ parent_image_id = None
+
+ except rbd.ImageNotFound:
+ pass
+
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ if TASK_REF_IMAGE_ID not in refs:
+ raise rbd.ImageNotFound("Image {} does not exist".format(
+ self.format_image_spec(image_spec)), errno=errno.ENOENT)
+ if not parent_image_id:
+ raise rbd.ImageNotFound("Image {} does not have a parent".format(
+ self.format_image_spec(image_spec)), errno=errno.ENOENT)
+
+ return 0, self.add_task(ioctx,
+ "Flattening image {}".format(
+ self.format_image_spec(image_spec)),
+ refs), ""
+
+ def queue_remove(self, image_spec):
+ image_spec = self.extract_image_spec(image_spec)
+
+ authorize_request(self.module, image_spec[0], image_spec[1])
+ self.log.info("queue_remove: {}".format(image_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_REMOVE,
+ TASK_REF_POOL_NAME: image_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_spec[1],
+ TASK_REF_IMAGE_NAME: image_spec[2]}
+
+ with self.open_ioctx(image_spec) as ioctx:
+ try:
+ with rbd.Image(ioctx, image_spec[2]) as image:
+ refs[TASK_REF_IMAGE_ID] = image.id()
+ snaps = list(image.list_snaps())
+
+ except rbd.ImageNotFound:
+ pass
+
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ if TASK_REF_IMAGE_ID not in refs:
+ raise rbd.ImageNotFound("Image {} does not exist".format(
+ self.format_image_spec(image_spec)), errno=errno.ENOENT)
+ if snaps:
+ raise rbd.ImageBusy("Image {} has snapshots".format(
+ self.format_image_spec(image_spec)), errno=errno.EBUSY)
+
+ return 0, self.add_task(ioctx,
+ "Removing image {}".format(
+ self.format_image_spec(image_spec)),
+ refs), ''
+
+ def queue_trash_remove(self, image_id_spec):
+ image_id_spec = self.extract_image_spec(image_id_spec)
+
+ authorize_request(self.module, image_id_spec[0], image_id_spec[1])
+ self.log.info("queue_trash_remove: {}".format(image_id_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_TRASH_REMOVE,
+ TASK_REF_POOL_NAME: image_id_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_id_spec[1],
+ TASK_REF_IMAGE_ID: image_id_spec[2]}
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ # verify that image exists in trash
+ with self.open_ioctx(image_id_spec) as ioctx:
+ rbd.RBD().trash_get(ioctx, image_id_spec[2])
+
+ return 0, self.add_task(ioctx,
+ "Removing image {} from trash".format(
+ self.format_image_spec(image_id_spec)),
+ refs), ''
+
+ def get_migration_status(self, ioctx, image_spec):
+ try:
+ return rbd.RBD().migration_status(ioctx, image_spec[2])
+ except (rbd.InvalidArgument, rbd.ImageNotFound):
+ return None
+
+ def validate_image_migrating(self, image_spec, migration_status):
+ if not migration_status:
+ raise rbd.InvalidArgument("Image {} is not migrating".format(
+ self.format_image_spec(image_spec)), errno=errno.EINVAL)
+
+ def resolve_pool_name(self, pool_id):
+ osd_map = self.module.get('osd_map')
+ for pool in osd_map['pools']:
+ if pool['pool'] == pool_id:
+ return pool['pool_name']
+ return '<unknown>'
+
+ def queue_migration_execute(self, image_spec):
+ image_spec = self.extract_image_spec(image_spec)
+
+ authorize_request(self.module, image_spec[0], image_spec[1])
+ self.log.info("queue_migration_execute: {}".format(image_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_MIGRATION_EXECUTE,
+ TASK_REF_POOL_NAME: image_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_spec[1],
+ TASK_REF_IMAGE_NAME: image_spec[2]}
+
+ with self.open_ioctx(image_spec) as ioctx:
+ status = self.get_migration_status(ioctx, image_spec)
+ if status:
+ refs[TASK_REF_IMAGE_ID] = status['dest_image_id']
+
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ self.validate_image_migrating(image_spec, status)
+ if status['state'] not in [rbd.RBD_IMAGE_MIGRATION_STATE_PREPARED,
+ rbd.RBD_IMAGE_MIGRATION_STATE_EXECUTING]:
+ raise rbd.InvalidArgument("Image {} is not in ready state".format(
+ self.format_image_spec(image_spec)), errno=errno.EINVAL)
+
+ source_pool = self.resolve_pool_name(status['source_pool_id'])
+ dest_pool = self.resolve_pool_name(status['dest_pool_id'])
+ return 0, self.add_task(ioctx,
+ "Migrating image {} to {}".format(
+ self.format_image_spec((source_pool,
+ status['source_pool_namespace'],
+ status['source_image_name'])),
+ self.format_image_spec((dest_pool,
+ status['dest_pool_namespace'],
+ status['dest_image_name']))),
+ refs), ''
+
+ def queue_migration_commit(self, image_spec):
+ image_spec = self.extract_image_spec(image_spec)
+
+ authorize_request(self.module, image_spec[0], image_spec[1])
+ self.log.info("queue_migration_commit: {}".format(image_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_MIGRATION_COMMIT,
+ TASK_REF_POOL_NAME: image_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_spec[1],
+ TASK_REF_IMAGE_NAME: image_spec[2]}
+
+ with self.open_ioctx(image_spec) as ioctx:
+ status = self.get_migration_status(ioctx, image_spec)
+ if status:
+ refs[TASK_REF_IMAGE_ID] = status['dest_image_id']
+
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ self.validate_image_migrating(image_spec, status)
+ if status['state'] != rbd.RBD_IMAGE_MIGRATION_STATE_EXECUTED:
+ raise rbd.InvalidArgument("Image {} has not completed migration".format(
+ self.format_image_spec(image_spec)), errno=errno.EINVAL)
+
+ return 0, self.add_task(ioctx,
+ "Committing image migration for {}".format(
+ self.format_image_spec(image_spec)),
+ refs), ''
+
+ def queue_migration_abort(self, image_spec):
+ image_spec = self.extract_image_spec(image_spec)
+
+ authorize_request(self.module, image_spec[0], image_spec[1])
+ self.log.info("queue_migration_abort: {}".format(image_spec))
+
+ refs = {TASK_REF_ACTION: TASK_REF_ACTION_MIGRATION_ABORT,
+ TASK_REF_POOL_NAME: image_spec[0],
+ TASK_REF_POOL_NAMESPACE: image_spec[1],
+ TASK_REF_IMAGE_NAME: image_spec[2]}
+
+ with self.open_ioctx(image_spec) as ioctx:
+ status = self.get_migration_status(ioctx, image_spec)
+ if status:
+ refs[TASK_REF_IMAGE_ID] = status['dest_image_id']
+
+ task = self.find_task(refs)
+ if task:
+ return 0, task.to_json(), ''
+
+ self.validate_image_migrating(image_spec, status)
+ return 0, self.add_task(ioctx,
+ "Aborting image migration for {}".format(
+ self.format_image_spec(image_spec)),
+ refs), ''
+
+ def task_cancel(self, task_id):
+ self.log.info("task_cancel: {}".format(task_id))
+
+ task = self.tasks_by_id.get(task_id)
+ if not task or not is_authorized(self.module,
+ task.refs[TASK_REF_POOL_NAME],
+ task.refs[TASK_REF_POOL_NAMESPACE]):
+ return -errno.ENOENT, '', "No such task {}".format(task_id)
+
+ task.cancel()
+
+ remove_in_memory = True
+ if self.in_progress_task and self.in_progress_task.task_id == task_id:
+ self.log.info("Attempting to cancel in-progress task: {}".format(str(self.in_progress_task)))
+ remove_in_memory = False
+
+ # complete any associated event in the progress module
+ self.complete_progress(task)
+
+ # remove from rbd_task omap
+ with self.open_ioctx((task.refs[TASK_REF_POOL_NAME],
+ task.refs[TASK_REF_POOL_NAMESPACE])) as ioctx:
+ self.remove_task(ioctx, task, remove_in_memory)
+
+ return 0, "", ""
+
+ def task_list(self, task_id):
+ self.log.info("task_list: {}".format(task_id))
+
+ if task_id:
+ task = self.tasks_by_id.get(task_id)
+ if not task or not is_authorized(self.module,
+ task.refs[TASK_REF_POOL_NAME],
+ task.refs[TASK_REF_POOL_NAMESPACE]):
+ return -errno.ENOENT, '', "No such task {}".format(task_id)
+
+ result = task.to_dict()
+ else:
+ result = []
+ for sequence in sorted(self.tasks_by_sequence.keys()):
+ task = self.tasks_by_sequence[sequence]
+ if is_authorized(self.module,
+ task.refs[TASK_REF_POOL_NAME],
+ task.refs[TASK_REF_POOL_NAMESPACE]):
+ result.append(task.to_dict())
+
+ return 0, json.dumps(result), ""
+
+ def handle_command(self, inbuf, prefix, cmd):
+ with self.lock:
+ if prefix == 'add flatten':
+ return self.queue_flatten(cmd['image_spec'])
+ elif prefix == 'add remove':
+ return self.queue_remove(cmd['image_spec'])
+ elif prefix == 'add trash remove':
+ return self.queue_trash_remove(cmd['image_id_spec'])
+ elif prefix == 'add migration execute':
+ return self.queue_migration_execute(cmd['image_spec'])
+ elif prefix == 'add migration commit':
+ return self.queue_migration_commit(cmd['image_spec'])
+ elif prefix == 'add migration abort':
+ return self.queue_migration_abort(cmd['image_spec'])
+ elif prefix == 'cancel':
+ return self.task_cancel(cmd['task_id'])
+ elif prefix == 'list':
+ return self.task_list(cmd.get('task_id'))
+
+ raise NotImplementedError(cmd['prefix'])
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "rbd perf image stats "
+ "name=pool_spec,type=CephString,req=false "
+ "name=sort_by,type=CephChoices,strings="
+ "write_ops|write_bytes|write_latency|"
+ "read_ops|read_bytes|read_latency,"
+ "req=false ",
+ "desc": "Retrieve current RBD IO performance stats",
+ "perm": "r"
+ },
+ {
+ "cmd": "rbd perf image counters "
+ "name=pool_spec,type=CephString,req=false "
+ "name=sort_by,type=CephChoices,strings="
+ "write_ops|write_bytes|write_latency|"
+ "read_ops|read_bytes|read_latency,"
+ "req=false ",
+ "desc": "Retrieve current RBD IO performance counters",
+ "perm": "r"
+ },
+ {
+ "cmd": "rbd task add flatten "
+ "name=image_spec,type=CephString",
+ "desc": "Flatten a cloned image asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task add remove "
+ "name=image_spec,type=CephString",
+ "desc": "Remove an image asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task add trash remove "
+ "name=image_id_spec,type=CephString",
+ "desc": "Remove an image from the trash asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task add migration execute "
+ "name=image_spec,type=CephString",
+ "desc": "Execute an image migration asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task add migration commit "
+ "name=image_spec,type=CephString",
+ "desc": "Commit an executed migration asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task add migration abort "
+ "name=image_spec,type=CephString",
+ "desc": "Abort a prepared migration asynchronously in the background",
+ "perm": "w"
+ },
+ {
+ "cmd": "rbd task cancel "
+ "name=task_id,type=CephString ",
+ "desc": "Cancel a pending or running asynchronous task",
+ "perm": "r"
+ },
+ {
+ "cmd": "rbd task list "
+ "name=task_id,type=CephString,req=false ",
+ "desc": "List pending or running asynchronous tasks",
+ "perm": "r"
+ }
+ ]
+ MODULE_OPTIONS = []
+
+ perf = None
+ task = None
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.perf = PerfHandler(self)
+ self.task = TaskHandler(self)
+
+ def handle_command(self, inbuf, cmd):
+ prefix = cmd['prefix']
+ try:
+ try:
+ if prefix.startswith('rbd perf '):
+ return self.perf.handle_command(inbuf, prefix[9:], cmd)
+ elif prefix.startswith('rbd task '):
+ return self.task.handle_command(inbuf, prefix[9:], cmd)
+
+ except NotAuthorizedError:
+ raise
+ except Exception as ex:
+ # log the full traceback but don't send it to the CLI user
+ self.log.fatal("Fatal runtime error: {}\n{}".format(
+ ex, traceback.format_exc()))
+ raise
+
+ except rados.Error as ex:
+ return -ex.errno, "", str(ex)
+ except rbd.OSError as ex:
+ return -ex.errno, "", str(ex)
+ except rbd.Error as ex:
+ return -errno.EINVAL, "", str(ex)
+ except KeyError as ex:
+ return -errno.ENOENT, "", str(ex)
+ except ValueError as ex:
+ return -errno.EINVAL, "", str(ex)
+ except NotAuthorizedError as ex:
+ return -errno.EACCES, "", str(ex)
+
+ raise NotImplementedError(cmd['prefix'])
diff --git a/src/pybind/mgr/restful/__init__.py b/src/pybind/mgr/restful/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/restful/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/restful/api/__init__.py b/src/pybind/mgr/restful/api/__init__.py
new file mode 100644
index 00000000..a105dfe8
--- /dev/null
+++ b/src/pybind/mgr/restful/api/__init__.py
@@ -0,0 +1,39 @@
+from pecan import expose
+from pecan.rest import RestController
+
+from .config import Config
+from .crush import Crush
+from .doc import Doc
+from .mon import Mon
+from .osd import Osd
+from .pool import Pool
+from .perf import Perf
+from .request import Request
+from .server import Server
+
+
+class Root(RestController):
+ config = Config()
+ crush = Crush()
+ doc = Doc()
+ mon = Mon()
+ osd = Osd()
+ perf = Perf()
+ pool = Pool()
+ request = Request()
+ server = Server()
+
+ @expose(template='json')
+ def get(self, **kwargs):
+ """
+ Show the basic information for the REST API
+ This includes values like api version or auth method
+ """
+ return {
+ 'api_version': 1,
+ 'auth':
+ 'Use "ceph restful create-key <key>" to create a key pair, '
+ 'pass it as HTTP Basic auth to authenticate',
+ 'doc': 'See /doc endpoint',
+ 'info': "Ceph Manager RESTful API server",
+ }
diff --git a/src/pybind/mgr/restful/api/config.py b/src/pybind/mgr/restful/api/config.py
new file mode 100644
index 00000000..565896c8
--- /dev/null
+++ b/src/pybind/mgr/restful/api/config.py
@@ -0,0 +1,86 @@
+from pecan import expose, request
+from pecan.rest import RestController
+
+from restful import common, context
+from restful.decorators import auth
+
+
+class ConfigOsd(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show OSD configuration options
+ """
+ flags = context.instance.get("osd_map")['flags']
+
+ # pause is a valid osd config command that sets pauserd,pausewr
+ flags = flags.replace('pauserd,pausewr', 'pause')
+
+ return flags.split(',')
+
+
+ @expose(template='json')
+ @auth
+ def patch(self, **kwargs):
+ """
+ Modify OSD configuration options
+ """
+ args = request.json
+
+ commands = []
+
+ valid_flags = set(args.keys()) & set(common.OSD_FLAGS)
+ invalid_flags = list(set(args.keys()) - valid_flags)
+ if invalid_flags:
+ context.instance.log.warn("%s not valid to set/unset", invalid_flags)
+
+ for flag in list(valid_flags):
+ if args[flag]:
+ mode = 'set'
+ else:
+ mode = 'unset'
+
+ commands.append({
+ 'prefix': 'osd ' + mode,
+ 'key': flag,
+ })
+
+ return context.instance.submit_request([commands], **kwargs)
+
+
+
+class ConfigClusterKey(RestController):
+ def __init__(self, key):
+ self.key = key
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show specific configuration option
+ """
+ return context.instance.get("config").get(self.key, None)
+
+
+
+class ConfigCluster(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show all cluster configuration options
+ """
+ return context.instance.get("config")
+
+
+ @expose()
+ def _lookup(self, key, *remainder):
+ return ConfigClusterKey(key), remainder
+
+
+
+class Config(RestController):
+ cluster = ConfigCluster()
+ osd = ConfigOsd()
diff --git a/src/pybind/mgr/restful/api/crush.py b/src/pybind/mgr/restful/api/crush.py
new file mode 100644
index 00000000..015c4949
--- /dev/null
+++ b/src/pybind/mgr/restful/api/crush.py
@@ -0,0 +1,26 @@
+from pecan import expose
+from pecan.rest import RestController
+
+from restful import common, context
+from collections import defaultdict
+
+from restful.decorators import auth
+
+
+class CrushRule(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show crush rules
+ """
+ crush = context.instance.get('osd_map_crush')
+ rules = crush['rules']
+
+ for rule in rules:
+ rule['osd_count'] = len(common.crush_rule_osds(crush['buckets'], rule))
+
+ return rules
+
+class Crush(RestController):
+ rule = CrushRule()
diff --git a/src/pybind/mgr/restful/api/doc.py b/src/pybind/mgr/restful/api/doc.py
new file mode 100644
index 00000000..f1038c21
--- /dev/null
+++ b/src/pybind/mgr/restful/api/doc.py
@@ -0,0 +1,15 @@
+from pecan import expose
+from pecan.rest import RestController
+
+from restful import context
+
+import restful
+
+
+class Doc(RestController):
+ @expose(template='json')
+ def get(self, **kwargs):
+ """
+ Show documentation information
+ """
+ return context.instance.get_doc_api(restful.api.Root)
diff --git a/src/pybind/mgr/restful/api/mon.py b/src/pybind/mgr/restful/api/mon.py
new file mode 100644
index 00000000..20d03360
--- /dev/null
+++ b/src/pybind/mgr/restful/api/mon.py
@@ -0,0 +1,40 @@
+from pecan import expose, response
+from pecan.rest import RestController
+
+from restful import context
+from restful.decorators import auth
+
+
+class MonName(RestController):
+ def __init__(self, name):
+ self.name = name
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for the monitor name
+ """
+ mon = [x for x in context.instance.get_mons()
+ if x['name'] == self.name]
+ if len(mon) != 1:
+ response.status = 500
+ return {'message': 'Failed to identify the monitor node "{}"'.format(self.name)}
+ return mon[0]
+
+
+
+class Mon(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for all the monitors
+ """
+ return context.instance.get_mons()
+
+
+ @expose()
+ def _lookup(self, name, *remainder):
+ return MonName(name), remainder
diff --git a/src/pybind/mgr/restful/api/osd.py b/src/pybind/mgr/restful/api/osd.py
new file mode 100644
index 00000000..8577fae9
--- /dev/null
+++ b/src/pybind/mgr/restful/api/osd.py
@@ -0,0 +1,135 @@
+from pecan import expose, request, response
+from pecan.rest import RestController
+
+from restful import common, context
+from restful.decorators import auth
+
+
+class OsdIdCommand(RestController):
+ def __init__(self, osd_id):
+ self.osd_id = osd_id
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show implemented commands for the OSD id
+ """
+ osd = context.instance.get_osd_by_id(self.osd_id)
+
+ if not osd:
+ response.status = 500
+ return {'message': 'Failed to identify the OSD id "{}"'.format(self.osd_id)}
+
+ if osd['up']:
+ return common.OSD_IMPLEMENTED_COMMANDS
+ else:
+ return []
+
+
+ @expose(template='json')
+ @auth
+ def post(self, **kwargs):
+ """
+ Run the implemented command for the OSD id
+ """
+ command = request.json.get('command', None)
+
+ osd = context.instance.get_osd_by_id(self.osd_id)
+
+ if not osd:
+ response.status = 500
+ return {'message': 'Failed to identify the OSD id "{}"'.format(self.osd_id)}
+
+ if not osd['up'] or command not in common.OSD_IMPLEMENTED_COMMANDS:
+ response.status = 500
+ return {'message': 'Command "{}" not available'.format(command)}
+
+ return context.instance.submit_request([[{
+ 'prefix': 'osd ' + command,
+ 'who': str(self.osd_id)
+ }]], **kwargs)
+
+
+
+class OsdId(RestController):
+ def __init__(self, osd_id):
+ self.osd_id = osd_id
+ self.command = OsdIdCommand(osd_id)
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for the OSD id
+ """
+ osd = context.instance.get_osds(ids=[str(self.osd_id)])
+ if len(osd) != 1:
+ response.status = 500
+ return {'message': 'Failed to identify the OSD id "{}"'.format(self.osd_id)}
+
+ return osd[0]
+
+
+ @expose(template='json')
+ @auth
+ def patch(self, **kwargs):
+ """
+ Modify the state (up, in) of the OSD id or reweight it
+ """
+ args = request.json
+
+ commands = []
+
+ if 'in' in args:
+ if args['in']:
+ commands.append({
+ 'prefix': 'osd in',
+ 'ids': [str(self.osd_id)]
+ })
+ else:
+ commands.append({
+ 'prefix': 'osd out',
+ 'ids': [str(self.osd_id)]
+ })
+
+ if 'up' in args:
+ if args['up']:
+ response.status = 500
+ return {'message': "It is not valid to set a down OSD to be up"}
+ else:
+ commands.append({
+ 'prefix': 'osd down',
+ 'ids': [str(self.osd_id)]
+ })
+
+ if 'reweight' in args:
+ commands.append({
+ 'prefix': 'osd reweight',
+ 'id': self.osd_id,
+ 'weight': args['reweight']
+ })
+
+ return context.instance.submit_request([commands], **kwargs)
+
+
+
+class Osd(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for all the OSDs
+ """
+ # Parse request args
+ # TODO Filter by ids
+ pool_id = kwargs.get('pool', None)
+
+ return context.instance.get_osds(pool_id)
+
+
+ @expose()
+ def _lookup(self, osd_id, *remainder):
+ return OsdId(int(osd_id)), remainder
diff --git a/src/pybind/mgr/restful/api/perf.py b/src/pybind/mgr/restful/api/perf.py
new file mode 100644
index 00000000..4224599f
--- /dev/null
+++ b/src/pybind/mgr/restful/api/perf.py
@@ -0,0 +1,27 @@
+from pecan import expose, request, response
+from pecan.rest import RestController
+
+from restful import context
+from restful.decorators import auth, lock, paginate
+
+import re
+
+class Perf(RestController):
+ @expose(template='json')
+ @paginate
+ @auth
+ def get(self, **kwargs):
+ """
+ List all the available performance counters
+
+ Options:
+ - 'daemon' -- filter by daemon, accepts Python regexp
+ """
+
+ counters = context.instance.get_all_perf_counters()
+
+ if 'daemon' in kwargs:
+ _re = re.compile(kwargs['daemon'])
+ counters = {k: v for k, v in counters.items() if _re.match(k)}
+
+ return counters
diff --git a/src/pybind/mgr/restful/api/pool.py b/src/pybind/mgr/restful/api/pool.py
new file mode 100644
index 00000000..40de54eb
--- /dev/null
+++ b/src/pybind/mgr/restful/api/pool.py
@@ -0,0 +1,140 @@
+from pecan import expose, request, response
+from pecan.rest import RestController
+
+from restful import common, context
+from restful.decorators import auth
+
+
+class PoolId(RestController):
+ def __init__(self, pool_id):
+ self.pool_id = pool_id
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for the pool id
+ """
+ pool = context.instance.get_pool_by_id(self.pool_id)
+
+ if not pool:
+ response.status = 500
+ return {'message': 'Failed to identify the pool id "{}"'.format(self.pool_id)}
+
+ # pgp_num is called pg_placement_num, deal with that
+ if 'pg_placement_num' in pool:
+ pool['pgp_num'] = pool.pop('pg_placement_num')
+ return pool
+
+
+ @expose(template='json')
+ @auth
+ def patch(self, **kwargs):
+ """
+ Modify the information for the pool id
+ """
+ try:
+ args = request.json
+ except ValueError:
+ response.status = 400
+ return {'message': 'Bad request: malformed JSON or wrong Content-Type'}
+
+ # Get the pool info for its name
+ pool = context.instance.get_pool_by_id(self.pool_id)
+ if not pool:
+ response.status = 500
+ return {'message': 'Failed to identify the pool id "{}"'.format(self.pool_id)}
+
+ # Check for invalid pool args
+ invalid = common.invalid_pool_args(args)
+ if invalid:
+ response.status = 500
+ return {'message': 'Invalid arguments found: "{}"'.format(invalid)}
+
+ # Schedule the update request
+ return context.instance.submit_request(common.pool_update_commands(pool['pool_name'], args), **kwargs)
+
+
+ @expose(template='json')
+ @auth
+ def delete(self, **kwargs):
+ """
+ Remove the pool data for the pool id
+ """
+ pool = context.instance.get_pool_by_id(self.pool_id)
+
+ if not pool:
+ response.status = 500
+ return {'message': 'Failed to identify the pool id "{}"'.format(self.pool_id)}
+
+ return context.instance.submit_request([[{
+ 'prefix': 'osd pool delete',
+ 'pool': pool['pool_name'],
+ 'pool2': pool['pool_name'],
+ 'yes_i_really_really_mean_it': True
+ }]], **kwargs)
+
+
+
+class Pool(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for all the pools
+ """
+ pools = context.instance.get('osd_map')['pools']
+
+ # pgp_num is called pg_placement_num, deal with that
+ for pool in pools:
+ if 'pg_placement_num' in pool:
+ pool['pgp_num'] = pool.pop('pg_placement_num')
+
+ return pools
+
+
+ @expose(template='json')
+ @auth
+ def post(self, **kwargs):
+ """
+ Create a new pool
+ Requires name and pg_num dict arguments
+ """
+ args = request.json
+
+ # Check for the required arguments
+ pool_name = args.pop('name', None)
+ if pool_name is None:
+ response.status = 500
+ return {'message': 'You need to specify the pool "name" argument'}
+
+ pg_num = args.pop('pg_num', None)
+ if pg_num is None:
+ response.status = 500
+ return {'message': 'You need to specify the "pg_num" argument'}
+
+ # Run the pool create command first
+ create_command = {
+ 'prefix': 'osd pool create',
+ 'pool': pool_name,
+ 'pg_num': pg_num
+ }
+
+ # Check for invalid pool args
+ invalid = common.invalid_pool_args(args)
+ if invalid:
+ response.status = 500
+ return {'message': 'Invalid arguments found: "{}"'.format(invalid)}
+
+ # Schedule the creation and update requests
+ return context.instance.submit_request(
+ [[create_command]] +
+ common.pool_update_commands(pool_name, args),
+ **kwargs
+ )
+
+
+ @expose()
+ def _lookup(self, pool_id, *remainder):
+ return PoolId(int(pool_id)), remainder
diff --git a/src/pybind/mgr/restful/api/request.py b/src/pybind/mgr/restful/api/request.py
new file mode 100644
index 00000000..67143ef5
--- /dev/null
+++ b/src/pybind/mgr/restful/api/request.py
@@ -0,0 +1,93 @@
+from pecan import expose, request, response
+from pecan.rest import RestController
+
+from restful import context
+from restful.decorators import auth, lock, paginate
+
+
+class RequestId(RestController):
+ def __init__(self, request_id):
+ self.request_id = request_id
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for the request id
+ """
+ request = [x for x in context.instance.requests
+ if x.id == self.request_id]
+ if len(request) != 1:
+ response.status = 500
+ return {'message': 'Unknown request id "{}"'.format(self.request_id)}
+ return request[0]
+
+
+ @expose(template='json')
+ @auth
+ @lock
+ def delete(self, **kwargs):
+ """
+ Remove the request id from the database
+ """
+ for index in range(len(context.instance.requests)):
+ if context.instance.requests[index].id == self.request_id:
+ return context.instance.requests.pop(index)
+
+ # Failed to find the job to cancel
+ response.status = 500
+ return {'message': 'No such request id'}
+
+
+
+class Request(RestController):
+ @expose(template='json')
+ @paginate
+ @auth
+ def get(self, **kwargs):
+ """
+ List all the available requests
+ """
+ return context.instance.requests
+
+
+ @expose(template='json')
+ @auth
+ @lock
+ def delete(self, **kwargs):
+ """
+ Remove all the finished requests
+ """
+ num_requests = len(context.instance.requests)
+
+ context.instance.requests = [x for x in context.instance.requests
+ if not x.is_finished()]
+ remaining = len(context.instance.requests)
+ # Return the job statistics
+ return {
+ 'cleaned': num_requests - remaining,
+ 'remaining': remaining,
+ }
+
+
+ @expose(template='json')
+ @auth
+ def post(self, **kwargs):
+ """
+ Pass through method to create any request
+ """
+ if isinstance(request.json, list):
+ if all(isinstance(element, list) for element in request.json):
+ return context.instance.submit_request(request.json, **kwargs)
+
+ # The request.json has wrong format
+ response.status = 500
+ return {'message': 'The request format should be [[{c1},{c2}]]'}
+
+ return context.instance.submit_request([[request.json]], **kwargs)
+
+
+ @expose()
+ def _lookup(self, request_id, *remainder):
+ return RequestId(request_id), remainder
diff --git a/src/pybind/mgr/restful/api/server.py b/src/pybind/mgr/restful/api/server.py
new file mode 100644
index 00000000..8ce63493
--- /dev/null
+++ b/src/pybind/mgr/restful/api/server.py
@@ -0,0 +1,35 @@
+from pecan import expose
+from pecan.rest import RestController
+
+from restful import context
+from restful.decorators import auth
+
+
+class ServerFqdn(RestController):
+ def __init__(self, fqdn):
+ self.fqdn = fqdn
+
+
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for the server fqdn
+ """
+ return context.instance.get_server(self.fqdn)
+
+
+
+class Server(RestController):
+ @expose(template='json')
+ @auth
+ def get(self, **kwargs):
+ """
+ Show the information for all the servers
+ """
+ return context.instance.list_servers()
+
+
+ @expose()
+ def _lookup(self, fqdn, *remainder):
+ return ServerFqdn(fqdn), remainder
diff --git a/src/pybind/mgr/restful/common.py b/src/pybind/mgr/restful/common.py
new file mode 100644
index 00000000..1b957d6b
--- /dev/null
+++ b/src/pybind/mgr/restful/common.py
@@ -0,0 +1,156 @@
+# List of valid osd flags
+OSD_FLAGS = [
+ 'pause', 'noup', 'nodown', 'noout', 'noin', 'nobackfill',
+ 'norecover', 'noscrub', 'nodeep-scrub',
+]
+
+# Implemented osd commands
+OSD_IMPLEMENTED_COMMANDS = [
+ 'scrub', 'deep-scrub', 'repair'
+]
+
+# Valid values for the 'var' argument to 'ceph osd pool set'
+POOL_PROPERTIES_1 = [
+ 'size', 'min_size', 'pg_num',
+ 'crush_rule', 'hashpspool',
+]
+
+POOL_PROPERTIES_2 = [
+ 'pgp_num'
+]
+
+POOL_PROPERTIES = POOL_PROPERTIES_1 + POOL_PROPERTIES_2
+
+# Valid values for the 'ceph osd pool set-quota' command
+POOL_QUOTA_PROPERTIES = [
+ ('quota_max_bytes', 'max_bytes'),
+ ('quota_max_objects', 'max_objects'),
+]
+
+POOL_ARGS = POOL_PROPERTIES + [x for x,_ in POOL_QUOTA_PROPERTIES]
+
+
+# Transform command to a human readable form
+def humanify_command(command):
+ out = [command['prefix']]
+
+ for arg, val in command.items():
+ if arg != 'prefix':
+ out.append("%s=%s" % (str(arg), str(val)))
+
+ return " ".join(out)
+
+
+def invalid_pool_args(args):
+ invalid = []
+ for arg in args:
+ if arg not in POOL_ARGS:
+ invalid.append(arg)
+
+ return invalid
+
+
+def pool_update_commands(pool_name, args):
+ commands = [[], []]
+
+ # We should increase pgp_num when we are re-setting pg_num
+ if 'pg_num' in args and 'pgp_num' not in args:
+ args['pgp_num'] = args['pg_num']
+
+ # Run the first pool set and quota properties in parallel
+ for var in POOL_PROPERTIES_1:
+ if var in args:
+ commands[0].append({
+ 'prefix': 'osd pool set',
+ 'pool': pool_name,
+ 'var': var,
+ 'val': args[var],
+ })
+
+ for (var, field) in POOL_QUOTA_PROPERTIES:
+ if var in args:
+ commands[0].append({
+ 'prefix': 'osd pool set-quota',
+ 'pool': pool_name,
+ 'field': field,
+ 'val': str(args[var]),
+ })
+
+ # The second pool set properties need to be run after the first wave
+ for var in POOL_PROPERTIES_2:
+ if var in args:
+ commands[1].append({
+ 'prefix': 'osd pool set',
+ 'pool': pool_name,
+ 'var': var,
+ 'val': args[var],
+ })
+
+ return commands
+
+def crush_rule_osds(node_buckets, rule):
+ nodes_by_id = dict((b['id'], b) for b in node_buckets)
+
+ def _gather_leaf_ids(node_id):
+ if node_id >= 0:
+ return set([node_id])
+
+ result = set()
+ for item in nodes_by_id[node_id]['items']:
+ result |= _gather_leaf_ids(item['id'])
+
+ return result
+
+ def _gather_descendent_ids(node, typ):
+ result = set()
+ for item in node['items']:
+ if item['id'] >= 0:
+ if typ == "osd":
+ result.add(item['id'])
+ else:
+ child_node = nodes_by_id[item['id']]
+ if child_node['type_name'] == typ:
+ result.add(child_node['id'])
+ elif 'items' in child_node:
+ result |= _gather_descendent_ids(child_node, typ)
+
+ return result
+
+ def _gather_osds(root, steps):
+ if root['id'] >= 0:
+ return set([root['id']])
+
+ osds = set()
+ step = steps[0]
+ if step['op'] == 'choose_firstn':
+ # Choose all descendents of the current node of type 'type'
+ descendent_ids = _gather_descendent_ids(root, step['type'])
+ for node_id in descendent_ids:
+ if node_id >= 0:
+ osds.add(node_id)
+ else:
+ osds |= _gather_osds(nodes_by_id[node_id], steps[1:])
+ elif step['op'] == 'chooseleaf_firstn':
+ # Choose all descendents of the current node of type 'type',
+ # and select all leaves beneath those
+ descendent_ids = _gather_descendent_ids(root, step['type'])
+ for node_id in descendent_ids:
+ if node_id >= 0:
+ osds.add(node_id)
+ else:
+ for desc_node in nodes_by_id[node_id]['items']:
+ # Short circuit another iteration to find the emit
+ # and assume anything we've done a chooseleaf on
+ # is going to be part of the selected set of osds
+ osds |= _gather_leaf_ids(desc_node['id'])
+ elif step['op'] == 'emit':
+ if root['id'] >= 0:
+ osds |= root['id']
+
+ return osds
+
+ osds = set()
+ for i, step in enumerate(rule['steps']):
+ if step['op'] == 'take':
+ osds |= _gather_osds(nodes_by_id[step['item']], rule['steps'][i + 1:])
+ return osds
diff --git a/src/pybind/mgr/restful/context.py b/src/pybind/mgr/restful/context.py
new file mode 100644
index 00000000..a05ea854
--- /dev/null
+++ b/src/pybind/mgr/restful/context.py
@@ -0,0 +1,2 @@
+# Global instance to share
+instance = None
diff --git a/src/pybind/mgr/restful/decorators.py b/src/pybind/mgr/restful/decorators.py
new file mode 100644
index 00000000..abf36e33
--- /dev/null
+++ b/src/pybind/mgr/restful/decorators.py
@@ -0,0 +1,79 @@
+from __future__ import absolute_import
+
+from pecan import request, response
+from base64 import b64decode
+from functools import wraps
+
+import traceback
+
+from . import context
+
+
+# Handle authorization
+def auth(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ if not request.authorization:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: No HTTP username/password'}
+
+ username, password = b64decode(request.authorization[1]).decode('utf-8').split(':')
+
+ # Check that the username exists
+ if username not in context.instance.keys:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: No such user'}
+
+ # Check the password
+ if context.instance.keys[username] != password:
+ response.status = 401
+ response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"'
+ return {'message': 'auth: Incorrect password'}
+
+ return f(*args, **kwargs)
+ return decorated
+
+
+# Helper function to lock the function
+def lock(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ with context.instance.requests_lock:
+ return f(*args, **kwargs)
+ return decorated
+
+
+# Support ?page=N argument
+def paginate(f):
+ @wraps(f)
+ def decorated(*args, **kwargs):
+ _out = f(*args, **kwargs)
+
+ # Do not modify anything without a specific request
+ if not 'page' in kwargs:
+ return _out
+
+ # A pass-through for errors, etc
+ if not isinstance(_out, list):
+ return _out
+
+ # Parse the page argument
+ _page = kwargs['page']
+ try:
+ _page = int(_page)
+ except ValueError:
+ response.status = 500
+ return {'message': 'The requested page is not an integer'}
+
+ # Raise _page so that 0 is the first page and -1 is the last
+ _page += 1
+
+ if _page > 0:
+ _page *= 100
+ else:
+ _page = len(_out) - (_page*100)
+
+ return _out[_page - 100: _page]
+ return decorated
diff --git a/src/pybind/mgr/restful/hooks.py b/src/pybind/mgr/restful/hooks.py
new file mode 100644
index 00000000..d677dcc2
--- /dev/null
+++ b/src/pybind/mgr/restful/hooks.py
@@ -0,0 +1,11 @@
+from __future__ import absolute_import
+
+from pecan.hooks import PecanHook
+
+import traceback
+
+from . import context
+
+class ErrorHook(PecanHook):
+ def on_error(self, stat, exc):
+ context.instance.log.error(str(traceback.format_exc()))
diff --git a/src/pybind/mgr/restful/module.py b/src/pybind/mgr/restful/module.py
new file mode 100644
index 00000000..bb113312
--- /dev/null
+++ b/src/pybind/mgr/restful/module.py
@@ -0,0 +1,610 @@
+"""
+A RESTful API for Ceph
+"""
+from __future__ import absolute_import
+
+import os
+import json
+import time
+import errno
+import inspect
+import tempfile
+import threading
+import traceback
+import six
+import socket
+import fcntl
+
+from . import common
+from . import context
+
+from uuid import uuid4
+from pecan import jsonify, make_app
+from OpenSSL import crypto
+from pecan.rest import RestController
+from six import iteritems
+from werkzeug.serving import make_server, make_ssl_devcert
+
+from .hooks import ErrorHook
+from mgr_module import MgrModule, CommandResult
+
+
+class CannotServe(Exception):
+ pass
+
+
+class CommandsRequest(object):
+ """
+ This class handles parallel as well as sequential execution of
+ commands. The class accept a list of iterables that should be
+ executed sequentially. Each iterable can contain several commands
+ that can be executed in parallel.
+
+ Example:
+ [[c1,c2],[c3,c4]]
+ - run c1 and c2 in parallel
+ - wait for them to finish
+ - run c3 and c4 in parallel
+ - wait for them to finish
+ """
+
+
+ def __init__(self, commands_arrays):
+ self.id = str(id(self))
+
+ # Filter out empty sub-requests
+ commands_arrays = [x for x in commands_arrays
+ if len(x) != 0]
+
+ self.running = []
+ self.waiting = commands_arrays[1:]
+ self.finished = []
+ self.failed = []
+
+ self.lock = threading.RLock()
+ if not len(commands_arrays):
+ # Nothing to run
+ return
+
+ # Process first iteration of commands_arrays in parallel
+ results = self.run(commands_arrays[0])
+
+ self.running.extend(results)
+
+
+ def run(self, commands):
+ """
+ A static method that will execute the given list of commands in
+ parallel and will return the list of command results.
+ """
+
+ # Gather the results (in parallel)
+ results = []
+ for index, command in enumerate(commands):
+ tag = '%s:%s:%d' % (__name__, self.id, index)
+
+ # Store the result
+ result = CommandResult(tag)
+ result.command = common.humanify_command(command)
+ results.append(result)
+
+ # Run the command
+ context.instance.send_command(result, 'mon', '', json.dumps(command), tag)
+
+ return results
+
+
+ def next(self):
+ with self.lock:
+ if not self.waiting:
+ # Nothing to run
+ return
+
+ # Run a next iteration of commands
+ commands = self.waiting[0]
+ self.waiting = self.waiting[1:]
+
+ self.running.extend(self.run(commands))
+
+
+ def finish(self, tag):
+ with self.lock:
+ for index in range(len(self.running)):
+ if self.running[index].tag == tag:
+ if self.running[index].r == 0:
+ self.finished.append(self.running.pop(index))
+ else:
+ self.failed.append(self.running.pop(index))
+ return True
+
+ # No such tag found
+ return False
+
+
+ def is_running(self, tag):
+ for result in self.running:
+ if result.tag == tag:
+ return True
+ return False
+
+
+ def is_ready(self):
+ with self.lock:
+ return not self.running and self.waiting
+
+
+ def is_waiting(self):
+ return bool(self.waiting)
+
+
+ def is_finished(self):
+ with self.lock:
+ return not self.running and not self.waiting
+
+
+ def has_failed(self):
+ return bool(self.failed)
+
+
+ def get_state(self):
+ with self.lock:
+ if not self.is_finished():
+ return "pending"
+
+ if self.has_failed():
+ return "failed"
+
+ return "success"
+
+
+ def __json__(self):
+ return {
+ 'id': self.id,
+ 'running': map(
+ lambda x: {
+ 'command': x.command,
+ 'outs': x.outs,
+ 'outb': x.outb,
+ },
+ self.running
+ ),
+ 'finished': map(
+ lambda x: {
+ 'command': x.command,
+ 'outs': x.outs,
+ 'outb': x.outb,
+ },
+ self.finished
+ ),
+ 'waiting': map(
+ lambda x: map(
+ lambda y: common.humanify_command(y),
+ x
+ ),
+ self.waiting
+ ),
+ 'failed': map(
+ lambda x: {
+ 'command': x.command,
+ 'outs': x.outs,
+ 'outb': x.outb,
+ },
+ self.failed
+ ),
+ 'is_waiting': self.is_waiting(),
+ 'is_finished': self.is_finished(),
+ 'has_failed': self.has_failed(),
+ 'state': self.get_state(),
+ }
+
+
+
+class Module(MgrModule):
+ MODULE_OPTIONS = [
+ {'name': 'server_addr'},
+ {'name': 'server_port'},
+ {'name': 'key_file'},
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "restful create-key name=key_name,type=CephString",
+ "desc": "Create an API key with this name",
+ "perm": "rw"
+ },
+ {
+ "cmd": "restful delete-key name=key_name,type=CephString",
+ "desc": "Delete an API key with this name",
+ "perm": "rw"
+ },
+ {
+ "cmd": "restful list-keys",
+ "desc": "List all API keys",
+ "perm": "r"
+ },
+ {
+ "cmd": "restful create-self-signed-cert",
+ "desc": "Create localized self signed certificate",
+ "perm": "rw"
+ },
+ {
+ "cmd": "restful restart",
+ "desc": "Restart API server",
+ "perm": "rw"
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ context.instance = self
+
+ self.requests = []
+ self.requests_lock = threading.RLock()
+
+ self.keys = {}
+ self.disable_auth = False
+
+ self.server = None
+
+ self.stop_server = False
+ self.serve_event = threading.Event()
+
+
+ def serve(self):
+ while not self.stop_server:
+ try:
+ self._serve()
+ self.server.socket.close()
+ except CannotServe as cs:
+ self.log.warn("server not running: %s", cs)
+ except:
+ self.log.error(str(traceback.format_exc()))
+
+ # Wait and clear the threading event
+ self.serve_event.wait()
+ self.serve_event.clear()
+
+ def refresh_keys(self):
+ self.keys = {}
+ rawkeys = self.get_store_prefix('keys/') or {}
+ for k, v in six.iteritems(rawkeys):
+ self.keys[k[5:]] = v # strip of keys/ prefix
+
+ def _serve(self):
+ # Load stored authentication keys
+ self.refresh_keys()
+
+ jsonify._instance = jsonify.GenericJSON(
+ sort_keys=True,
+ indent=4,
+ separators=(',', ': '),
+ )
+
+ server_addr = self.get_localized_module_option('server_addr', '::')
+ if server_addr is None:
+ raise CannotServe('no server_addr configured; try "ceph config-key set mgr/restful/server_addr <ip>"')
+
+ server_port = int(self.get_localized_module_option('server_port', '8003'))
+ self.log.info('server_addr: %s server_port: %d',
+ server_addr, server_port)
+
+ cert = self.get_localized_store("crt")
+ if cert is not None:
+ cert_tmp = tempfile.NamedTemporaryFile()
+ cert_tmp.write(cert.encode('utf-8'))
+ cert_tmp.flush()
+ cert_fname = cert_tmp.name
+ else:
+ cert_fname = self.get_localized_store('crt_file')
+
+ pkey = self.get_localized_store("key")
+ if pkey is not None:
+ pkey_tmp = tempfile.NamedTemporaryFile()
+ pkey_tmp.write(pkey.encode('utf-8'))
+ pkey_tmp.flush()
+ pkey_fname = pkey_tmp.name
+ else:
+ pkey_fname = self.get_localized_module_option('key_file')
+
+ if not cert_fname or not pkey_fname:
+ raise CannotServe('no certificate configured')
+ if not os.path.isfile(cert_fname):
+ raise CannotServe('certificate %s does not exist' % cert_fname)
+ if not os.path.isfile(pkey_fname):
+ raise CannotServe('private key %s does not exist' % pkey_fname)
+
+ # Publish the URI that others may use to access the service we're
+ # about to start serving
+ self.set_uri("https://{0}:{1}/".format(
+ socket.gethostname() if server_addr == "::" else server_addr,
+ server_port
+ ))
+
+ # Create the HTTPS werkzeug server serving pecan app
+ self.server = make_server(
+ host=server_addr,
+ port=server_port,
+ app=make_app(
+ root='restful.api.Root',
+ hooks = [ErrorHook()], # use a callable if pecan >= 0.3.2
+ ),
+ ssl_context=(cert_fname, pkey_fname),
+ )
+ sock_fd_flag = fcntl.fcntl(self.server.socket.fileno(), fcntl.F_GETFD)
+ if not (sock_fd_flag & fcntl.FD_CLOEXEC):
+ self.log.debug("set server socket close-on-exec")
+ fcntl.fcntl(self.server.socket.fileno(), fcntl.F_SETFD, sock_fd_flag | fcntl.FD_CLOEXEC)
+ if self.stop_server:
+ self.log.debug('made server, but stop flag set')
+ else:
+ self.log.debug('made server, serving forever')
+ self.server.serve_forever()
+
+
+ def shutdown(self):
+ try:
+ self.stop_server = True
+ if self.server:
+ self.server.shutdown()
+ self.serve_event.set()
+ except:
+ self.log.error(str(traceback.format_exc()))
+ raise
+
+
+ def restart(self):
+ try:
+ if self.server:
+ self.server.shutdown()
+ self.serve_event.set()
+ except:
+ self.log.error(str(traceback.format_exc()))
+
+
+ def notify(self, notify_type, tag):
+ try:
+ self._notify(notify_type, tag)
+ except:
+ self.log.error(str(traceback.format_exc()))
+
+
+ def _notify(self, notify_type, tag):
+ if notify_type != "command":
+ self.log.debug("Unhandled notification type '%s'", notify_type)
+ return
+ # we can safely skip all the sequential commands
+ if tag == 'seq':
+ return
+ try:
+ with self.requests_lock:
+ request = next(x for x in self.requests if x.is_running(tag))
+ request.finish(tag)
+ if request.is_ready():
+ request.next()
+ except StopIteration:
+ # the command was not issued by me
+ pass
+
+
+ def create_self_signed_cert(self):
+ # create a key pair
+ pkey = crypto.PKey()
+ pkey.generate_key(crypto.TYPE_RSA, 2048)
+
+ # create a self-signed cert
+ cert = crypto.X509()
+ cert.get_subject().O = "IT"
+ cert.get_subject().CN = "ceph-restful"
+ cert.set_serial_number(int(uuid4()))
+ cert.gmtime_adj_notBefore(0)
+ cert.gmtime_adj_notAfter(10*365*24*60*60)
+ cert.set_issuer(cert.get_subject())
+ cert.set_pubkey(pkey)
+ cert.sign(pkey, 'sha512')
+
+ return (
+ crypto.dump_certificate(crypto.FILETYPE_PEM, cert),
+ crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
+ )
+
+
+ def handle_command(self, inbuf, command):
+ self.log.warn("Handling command: '%s'" % str(command))
+ if command['prefix'] == "restful create-key":
+ if command['key_name'] in self.keys:
+ return 0, self.keys[command['key_name']], ""
+
+ else:
+ key = str(uuid4())
+ self.keys[command['key_name']] = key
+ self.set_store('keys/' + command['key_name'], key)
+
+ return (
+ 0,
+ self.keys[command['key_name']],
+ "",
+ )
+
+ elif command['prefix'] == "restful delete-key":
+ if command['key_name'] in self.keys:
+ del self.keys[command['key_name']]
+ self.set_store('keys/' + command['key_name'], None)
+
+ return (
+ 0,
+ "",
+ "",
+ )
+
+ elif command['prefix'] == "restful list-keys":
+ self.refresh_keys()
+ return (
+ 0,
+ json.dumps(self.keys, indent=2),
+ "",
+ )
+
+ elif command['prefix'] == "restful create-self-signed-cert":
+ cert, pkey = self.create_self_signed_cert()
+ self.set_store(self.get_mgr_id() + '/crt', cert.decode('utf-8'))
+ self.set_store(self.get_mgr_id() + '/key', pkey.decode('utf-8'))
+
+ self.restart()
+ return (
+ 0,
+ "Restarting RESTful API server...",
+ ""
+ )
+
+ elif command['prefix'] == 'restful restart':
+ self.restart();
+ return (
+ 0,
+ "Restarting RESTful API server...",
+ ""
+ )
+
+ else:
+ return (
+ -errno.EINVAL,
+ "",
+ "Command not found '{0}'".format(command['prefix'])
+ )
+
+
+ def get_doc_api(self, root, prefix=''):
+ doc = {}
+ for _obj in dir(root):
+ obj = getattr(root, _obj)
+
+ if isinstance(obj, RestController):
+ doc.update(self.get_doc_api(obj, prefix + '/' + _obj))
+
+ if getattr(root, '_lookup', None) and isinstance(root._lookup('0')[0], RestController):
+ doc.update(self.get_doc_api(root._lookup('0')[0], prefix + '/<arg>'))
+
+ prefix = prefix or '/'
+
+ doc[prefix] = {}
+ for method in 'get', 'post', 'patch', 'delete':
+ if getattr(root, method, None):
+ doc[prefix][method.upper()] = inspect.getdoc(getattr(root, method)).split('\n')
+
+ if len(doc[prefix]) == 0:
+ del doc[prefix]
+
+ return doc
+
+
+ def get_mons(self):
+ mon_map_mons = self.get('mon_map')['mons']
+ mon_status = json.loads(self.get('mon_status')['json'])
+
+ # Add more information
+ for mon in mon_map_mons:
+ mon['in_quorum'] = mon['rank'] in mon_status['quorum']
+ mon['server'] = self.get_metadata("mon", mon['name'])['hostname']
+ mon['leader'] = mon['rank'] == mon_status['quorum'][0]
+
+ return mon_map_mons
+
+
+ def get_osd_pools(self):
+ osds = dict(map(lambda x: (x['osd'], []), self.get('osd_map')['osds']))
+ pools = dict(map(lambda x: (x['pool'], x), self.get('osd_map')['pools']))
+ crush = self.get('osd_map_crush')
+ crush_rules = crush['rules']
+
+ osds_by_pool = {}
+ for pool_id, pool in pools.items():
+ pool_osds = None
+ for rule in [r for r in crush_rules if r['rule_id'] == pool['crush_rule']]:
+ if rule['min_size'] <= pool['size'] <= rule['max_size']:
+ pool_osds = common.crush_rule_osds(crush['buckets'], rule)
+
+ osds_by_pool[pool_id] = pool_osds
+
+ for pool_id in pools.keys():
+ for in_pool_id in osds_by_pool[pool_id]:
+ osds[in_pool_id].append(pool_id)
+
+ return osds
+
+
+ def get_osds(self, pool_id=None, ids=None):
+ # Get data
+ osd_map = self.get('osd_map')
+ osd_metadata = self.get('osd_metadata')
+
+ # Update the data with the additional info from the osd map
+ osds = osd_map['osds']
+
+ # Filter by osd ids
+ if ids is not None:
+ osds = [x for x in osds if str(x['osd']) in ids]
+
+ # Get list of pools per osd node
+ pools_map = self.get_osd_pools()
+
+ # map osd IDs to reweight
+ reweight_map = dict([
+ (x.get('id'), x.get('reweight', None))
+ for x in self.get('osd_map_tree')['nodes']
+ ])
+
+ # Build OSD data objects
+ for osd in osds:
+ osd['pools'] = pools_map[osd['osd']]
+ osd['server'] = osd_metadata.get(str(osd['osd']), {}).get('hostname', None)
+
+ osd['reweight'] = reweight_map.get(osd['osd'], 0.0)
+
+ if osd['up']:
+ osd['valid_commands'] = common.OSD_IMPLEMENTED_COMMANDS
+ else:
+ osd['valid_commands'] = []
+
+ # Filter by pool
+ if pool_id:
+ pool_id = int(pool_id)
+ osds = [x for x in osds if pool_id in x['pools']]
+
+ return osds
+
+
+ def get_osd_by_id(self, osd_id):
+ osd = [x for x in self.get('osd_map')['osds']
+ if x['osd'] == osd_id]
+
+ if len(osd) != 1:
+ return None
+
+ return osd[0]
+
+
+ def get_pool_by_id(self, pool_id):
+ pool = [x for x in self.get('osd_map')['pools']
+ if x['pool'] == pool_id]
+
+ if len(pool) != 1:
+ return None
+
+ return pool[0]
+
+
+ def submit_request(self, _request, **kwargs):
+ with self.requests_lock:
+ request = CommandsRequest(_request)
+ self.requests.append(request)
+ if kwargs.get('wait', 0):
+ while not request.is_finished():
+ time.sleep(0.001)
+ return request
+
+
+ def run_command(self, command):
+ # tag with 'seq' so that we can ignore these in notify function
+ result = CommandResult('seq')
+
+ self.send_command(result, 'mon', '', json.dumps(command), 'seq')
+ return result.wait()
diff --git a/src/pybind/mgr/rook/__init__.py b/src/pybind/mgr/rook/__init__.py
new file mode 100644
index 00000000..b9f08fc8
--- /dev/null
+++ b/src/pybind/mgr/rook/__init__.py
@@ -0,0 +1,2 @@
+
+from .module import RookOrchestrator
diff --git a/src/pybind/mgr/rook/module.py b/src/pybind/mgr/rook/module.py
new file mode 100644
index 00000000..4b49d681
--- /dev/null
+++ b/src/pybind/mgr/rook/module.py
@@ -0,0 +1,469 @@
+import threading
+import functools
+import os
+import uuid
+try:
+ from typing import List
+except ImportError:
+ pass # just for type checking
+
+try:
+ from kubernetes import client, config
+ from kubernetes.client.rest import ApiException
+
+ kubernetes_imported = True
+except ImportError:
+ kubernetes_imported = False
+ client = None
+ config = None
+
+from mgr_module import MgrModule
+import orchestrator
+
+from .rook_cluster import RookCluster
+
+
+all_completions = []
+
+
+class RookReadCompletion(orchestrator.ReadCompletion):
+ """
+ All reads are simply API calls: avoid spawning
+ huge numbers of threads by just running them
+ inline when someone calls wait()
+ """
+
+ def __init__(self, cb):
+ super(RookReadCompletion, self).__init__()
+ self.cb = cb
+ self._result = None
+ self._complete = False
+
+ self.message = "<read op>"
+
+ # XXX hacky global
+ global all_completions
+ all_completions.append(self)
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_complete(self):
+ return self._complete
+
+ def execute(self):
+ self._result = self.cb()
+ self._complete = True
+
+
+class RookWriteCompletion(orchestrator.WriteCompletion):
+ """
+ Writes are a two-phase thing, firstly sending
+ the write to the k8s API (fast) and then waiting
+ for the corresponding change to appear in the
+ Ceph cluster (slow)
+ """
+ # XXX kubernetes bindings call_api already usefully has
+ # a completion= param that uses threads. Maybe just
+ # use that?
+ def __init__(self, execute_cb, complete_cb, message):
+ super(RookWriteCompletion, self).__init__()
+ self.execute_cb = execute_cb
+ self.complete_cb = complete_cb
+
+ # Executed means I executed my k8s API call, it may or may
+ # not have succeeded
+ self.executed = False
+
+ # Result of k8s API call, this is set if executed==True
+ self._result = None
+
+ self.effective = False
+
+ self.id = str(uuid.uuid4())
+
+ self.message = message
+
+ self.error = None
+
+ # XXX hacky global
+ global all_completions
+ all_completions.append(self)
+
+ def __str__(self):
+ return self.message
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_persistent(self):
+ return (not self.is_errored) and self.executed
+
+ @property
+ def is_effective(self):
+ return self.effective
+
+ @property
+ def is_errored(self):
+ return self.error is not None
+
+ def execute(self):
+ if not self.executed:
+ self._result = self.execute_cb()
+ self.executed = True
+
+ if not self.effective:
+ # TODO: check self.result for API errors
+ if self.complete_cb is None:
+ self.effective = True
+ else:
+ self.effective = self.complete_cb()
+
+
+def deferred_read(f):
+ """
+ Decorator to make RookOrchestrator methods return
+ a completion object that executes themselves.
+ """
+
+ @functools.wraps(f)
+ def wrapper(*args, **kwargs):
+ return RookReadCompletion(lambda: f(*args, **kwargs))
+
+ return wrapper
+
+
+class RookEnv(object):
+ def __init__(self):
+ # POD_NAMESPACE already exist for Rook 0.9
+ self.namespace = os.environ.get('POD_NAMESPACE', 'rook-ceph')
+
+ # ROOK_CEPH_CLUSTER_CRD_NAME is new is Rook 1.0
+ self.cluster_name = os.environ.get('ROOK_CEPH_CLUSTER_CRD_NAME', self.namespace)
+
+ self.operator_namespace = os.environ.get('ROOK_OPERATOR_NAMESPACE', "rook-ceph-system")
+ self.crd_version = os.environ.get('ROOK_CEPH_CLUSTER_CRD_VERSION', 'v1')
+ self.api_name = "ceph.rook.io/" + self.crd_version
+
+ def api_version_match(self):
+ return self.crd_version == 'v1'
+
+ def has_namespace(self):
+ return 'POD_NAMESPACE' in os.environ
+
+
+class RookOrchestrator(MgrModule, orchestrator.Orchestrator):
+ MODULE_OPTIONS = [
+ # TODO: configure k8s API addr instead of assuming local
+ ]
+
+ def wait(self, completions):
+ self.log.info("wait: completions={0}".format(completions))
+
+ incomplete = False
+
+ # Our `wait` implementation is very simple because everything's
+ # just an API call.
+ for c in completions:
+ if not isinstance(c, RookReadCompletion) and \
+ not isinstance(c, RookWriteCompletion):
+ raise TypeError(
+ "wait() requires list of completions, not {0}".format(
+ c.__class__
+ ))
+
+ if c.is_complete:
+ continue
+
+ try:
+ c.execute()
+ except Exception as e:
+ if not isinstance(e, orchestrator.OrchestratorError):
+ self.log.exception("Completion {0} threw an exception:".format(
+ c.message
+ ))
+ c.exception = e
+ c._complete = True
+
+ if not c.is_complete:
+ incomplete = True
+
+ return not incomplete
+
+ @staticmethod
+ def can_run():
+ if not kubernetes_imported:
+ return False, "`kubernetes` python module not found"
+ if not RookEnv().api_version_match():
+ return False, "Rook version unsupported."
+ return True, ''
+
+ def available(self):
+ if not kubernetes_imported:
+ return False, "`kubernetes` python module not found"
+ elif not self._rook_env.has_namespace():
+ return False, "ceph-mgr not running in Rook cluster"
+
+ try:
+ self.k8s.list_namespaced_pod(self._rook_env.cluster_name)
+ except ApiException as e:
+ return False, "Cannot reach Kubernetes API: {}".format(e)
+ else:
+ return True, ""
+
+ def __init__(self, *args, **kwargs):
+ super(RookOrchestrator, self).__init__(*args, **kwargs)
+
+ self._initialized = threading.Event()
+ self._k8s = None
+ self._rook_cluster = None
+ self._rook_env = RookEnv()
+
+ self._shutdown = threading.Event()
+
+ def shutdown(self):
+ self._shutdown.set()
+
+ @property
+ def k8s(self):
+ self._initialized.wait()
+ return self._k8s
+
+ @property
+ def rook_cluster(self):
+ # type: () -> RookCluster
+ self._initialized.wait()
+ return self._rook_cluster
+
+ def serve(self):
+ # For deployed clusters, we should always be running inside
+ # a Rook cluster. For development convenience, also support
+ # running outside (reading ~/.kube config)
+
+ if self._rook_env.cluster_name:
+ config.load_incluster_config()
+ cluster_name = self._rook_env.cluster_name
+ else:
+ self.log.warning("DEVELOPMENT ONLY: Reading kube config from ~")
+ config.load_kube_config()
+
+ cluster_name = "rook-ceph"
+
+ # So that I can do port forwarding from my workstation - jcsp
+ from kubernetes.client import configuration
+ configuration.verify_ssl = False
+
+ self._k8s = client.CoreV1Api()
+
+ try:
+ # XXX mystery hack -- I need to do an API call from
+ # this context, or subsequent API usage from handle_command
+ # fails with SSLError('bad handshake'). Suspect some kind of
+ # thread context setup in SSL lib?
+ self._k8s.list_namespaced_pod(cluster_name)
+ except ApiException:
+ # Ignore here to make self.available() fail with a proper error message
+ pass
+
+ self._rook_cluster = RookCluster(
+ self._k8s,
+ self._rook_env)
+
+ self._initialized.set()
+
+ while not self._shutdown.is_set():
+ # XXX hack (or is it?) to kick all completions periodically,
+ # in case we had a caller that wait()'ed on them long enough
+ # to get persistence but not long enough to get completion
+
+ global all_completions
+ self.wait(all_completions)
+ all_completions = [c for c in all_completions if not c.is_complete]
+
+ self._shutdown.wait(5)
+
+ # TODO: watch Rook for config changes to complain/update if
+ # things look a bit out of sync?
+
+ @deferred_read
+ def get_inventory(self, node_filter=None, refresh=False):
+ node_list = None
+ if node_filter and node_filter.nodes:
+ # Explicit node list
+ node_list = node_filter.nodes
+ elif node_filter and node_filter.labels:
+ # TODO: query k8s API to resolve to node list, and pass
+ # it into RookCluster.get_discovered_devices
+ raise NotImplementedError()
+
+ devs = self.rook_cluster.get_discovered_devices(node_list)
+
+ result = []
+ for node_name, node_devs in devs.items():
+ devs = []
+ for d in node_devs:
+ dev = orchestrator.InventoryDevice()
+
+ # XXX CAUTION! https://github.com/rook/rook/issues/1716
+ # Passing this through for the sake of completeness but it
+ # is not trustworthy!
+ dev.blank = d['empty']
+ dev.type = 'hdd' if d['rotational'] else 'ssd'
+ dev.id = d['name']
+ dev.size = d['size']
+
+ if d['filesystem'] == "" and not d['rotational']:
+ # Empty or partitioned SSD
+ partitioned_space = sum(
+ [p['size'] for p in d['Partitions']])
+ dev.metadata_space_free = max(0, d[
+ 'size'] - partitioned_space)
+
+ devs.append(dev)
+
+ result.append(orchestrator.InventoryNode(node_name, devs))
+
+ return result
+
+ @deferred_read
+ def describe_service(self, service_type=None, service_id=None, node_name=None, refresh=False):
+
+ if service_type not in ("mds", "osd", "mgr", "mon", "nfs", None):
+ raise orchestrator.OrchestratorValidationError(service_type + " unsupported")
+
+ pods = self.rook_cluster.describe_pods(service_type, service_id, node_name)
+
+ result = []
+ for p in pods:
+ sd = orchestrator.ServiceDescription()
+ sd.nodename = p['nodename']
+ sd.container_id = p['name']
+ sd.service_type = p['labels']['app'].replace('rook-ceph-', '')
+
+ if sd.service_type == "osd":
+ sd.service_instance = "%s" % p['labels']["ceph-osd-id"]
+ elif sd.service_type == "mds":
+ sd.service = p['labels']['rook_file_system']
+ pfx = "{0}-".format(sd.service)
+ sd.service_instance = p['labels']['ceph_daemon_id'].replace(pfx, '', 1)
+ elif sd.service_type == "mon":
+ sd.service_instance = p['labels']["mon"]
+ elif sd.service_type == "mgr":
+ sd.service_instance = p['labels']["mgr"]
+ elif sd.service_type == "nfs":
+ sd.service = p['labels']['ceph_nfs']
+ sd.service_instance = p['labels']['instance']
+ sd.rados_config_location = self.rook_cluster.get_nfs_conf_url(sd.service, sd.service_instance)
+ elif sd.service_type == "rgw":
+ sd.service = p['labels']['rgw']
+ sd.service_instance = p['labels']['ceph_daemon_id']
+ else:
+ # Unknown type -- skip it
+ continue
+
+ result.append(sd)
+
+ return result
+
+ def _service_add_decorate(self, typename, spec, func):
+ return RookWriteCompletion(lambda: func(spec), None,
+ "Creating {0} services for {1}".format(typename, spec.name))
+
+ def add_stateless_service(self, service_type, spec):
+ # assert isinstance(spec, orchestrator.StatelessServiceSpec)
+ if service_type == "mds":
+ return self._service_add_decorate("Filesystem", spec,
+ self.rook_cluster.add_filesystem)
+ elif service_type == "rgw" :
+ return self._service_add_decorate("RGW", spec,
+ self.rook_cluster.add_objectstore)
+ elif service_type == "nfs" :
+ return self._service_add_decorate("NFS", spec,
+ self.rook_cluster.add_nfsgw)
+ else:
+ raise NotImplementedError(service_type)
+
+ def remove_stateless_service(self, service_type, service_id):
+ return RookWriteCompletion(
+ lambda: self.rook_cluster.rm_service(service_type, service_id), None,
+ "Removing {0} services for {1}".format(service_type, service_id))
+
+ def update_mons(self, num, hosts):
+ if hosts:
+ raise RuntimeError("Host list is not supported by rook.")
+
+ return RookWriteCompletion(
+ lambda: self.rook_cluster.update_mon_count(num), None,
+ "Updating mon count to {0}".format(num))
+
+ def update_stateless_service(self, svc_type, spec):
+ # only nfs is currently supported
+ if svc_type != "nfs":
+ raise NotImplementedError(svc_type)
+
+ num = spec.count
+ return RookWriteCompletion(
+ lambda: self.rook_cluster.update_nfs_count(spec.name, num), None,
+ "Updating NFS server count in {0} to {1}".format(spec.name, num))
+
+ def create_osds(self, drive_group, all_hosts):
+ # type: (orchestrator.DriveGroupSpec, List[str]) -> RookWriteCompletion
+
+ assert len(drive_group.hosts(all_hosts)) == 1
+ targets = []
+ if drive_group.data_devices:
+ targets += drive_group.data_devices.paths
+ if drive_group.data_directories:
+ targets += drive_group.data_directories
+
+ if not self.rook_cluster.node_exists(drive_group.hosts(all_hosts)[0]):
+ raise RuntimeError("Node '{0}' is not in the Kubernetes "
+ "cluster".format(drive_group.hosts(all_hosts)))
+
+ # Validate whether cluster CRD can accept individual OSD
+ # creations (i.e. not useAllDevices)
+ if not self.rook_cluster.can_create_osd():
+ raise RuntimeError("Rook cluster configuration does not "
+ "support OSD creation.")
+
+ def execute():
+ return self.rook_cluster.add_osds(drive_group, all_hosts)
+
+ def is_complete():
+ # Find OSD pods on this host
+ pod_osd_ids = set()
+ pods = self._k8s.list_namespaced_pod(self._rook_env.namespace,
+ label_selector="rook_cluster={},app=rook-ceph-osd".format(self._rook_env.cluster_name),
+ field_selector="spec.nodeName={0}".format(
+ drive_group.hosts(all_hosts)[0]
+ )).items
+ for p in pods:
+ pod_osd_ids.add(int(p.metadata.labels['ceph-osd-id']))
+
+ self.log.debug('pod_osd_ids={0}'.format(pod_osd_ids))
+
+ found = []
+ osdmap = self.get("osd_map")
+ for osd in osdmap['osds']:
+ osd_id = osd['osd']
+ if osd_id not in pod_osd_ids:
+ continue
+
+ metadata = self.get_metadata('osd', "%s" % osd_id)
+ if metadata and metadata['devices'] in targets:
+ found.append(osd_id)
+ else:
+ self.log.info("ignoring osd {0} {1}".format(
+ osd_id, metadata['devices']
+ ))
+
+ return found is not None
+
+ return RookWriteCompletion(execute, is_complete,
+ "Creating OSD on {0}:{1}".format(
+ drive_group.hosts(all_hosts)[0], targets
+ ))
diff --git a/src/pybind/mgr/rook/rook_cluster.py b/src/pybind/mgr/rook/rook_cluster.py
new file mode 100644
index 00000000..ef404075
--- /dev/null
+++ b/src/pybind/mgr/rook/rook_cluster.py
@@ -0,0 +1,442 @@
+"""
+This module wrap's Rook + Kubernetes APIs to expose the calls
+needed to implement an orchestrator module. While the orchestrator
+module exposes an async API, this module simply exposes blocking API
+call methods.
+
+This module is runnable outside of ceph-mgr, useful for testing.
+"""
+import logging
+import json
+from contextlib import contextmanager
+
+from six.moves.urllib.parse import urljoin # pylint: disable=import-error
+
+# Optional kubernetes imports to enable MgrModule.can_run
+# to behave cleanly.
+try:
+ from kubernetes.client.rest import ApiException
+except ImportError:
+ ApiException = None
+
+try:
+ import orchestrator
+ from rook.module import RookEnv
+ from typing import List
+except ImportError:
+ pass # just used for type checking.
+
+
+log = logging.getLogger(__name__)
+
+
+class ApplyException(Exception):
+ """
+ For failures to update the Rook CRDs, usually indicating
+ some kind of interference between our attempted update
+ and other conflicting activity.
+ """
+
+
+class RookCluster(object):
+ def __init__(self, k8s, rook_env):
+ self.rook_env = rook_env # type: RookEnv
+ self.k8s = k8s
+
+ def rook_url(self, path):
+ prefix = "/apis/ceph.rook.io/%s/namespaces/%s/" % (
+ self.rook_env.crd_version, self.rook_env.namespace)
+ return urljoin(prefix, path)
+
+ def rook_api_call(self, verb, path, **kwargs):
+ full_path = self.rook_url(path)
+ log.debug("[%s] %s" % (verb, full_path))
+
+ return self.k8s.api_client.call_api(
+ full_path,
+ verb,
+ auth_settings=['BearerToken'],
+ response_type="object",
+ _return_http_data_only=True,
+ _preload_content=True,
+ **kwargs)
+
+ def rook_api_get(self, path, **kwargs):
+ return self.rook_api_call("GET", path, **kwargs)
+
+ def rook_api_delete(self, path):
+ return self.rook_api_call("DELETE", path)
+
+ def rook_api_patch(self, path, **kwargs):
+ return self.rook_api_call("PATCH", path,
+ header_params={"Content-Type": "application/json-patch+json"},
+ **kwargs)
+
+ def rook_api_post(self, path, **kwargs):
+ return self.rook_api_call("POST", path, **kwargs)
+
+ def get_discovered_devices(self, nodenames=None):
+ # TODO: replace direct k8s calls with Rook API calls
+ # when they're implemented
+ label_selector = "app=rook-discover"
+ if nodenames is not None:
+ # FIXME: is there a practical or official limit on the
+ # number of entries in a label selector
+ label_selector += ", rook.io/node in ({0})".format(
+ ", ".join(nodenames))
+
+ try:
+ result = self.k8s.list_namespaced_config_map(
+ self.rook_env.operator_namespace,
+ label_selector=label_selector)
+ except ApiException as e:
+ log.exception("Failed to fetch device metadata: {0}".format(e))
+ raise
+
+ nodename_to_devices = {}
+ for i in result.items:
+ drives = json.loads(i.data['devices'])
+ nodename_to_devices[i.metadata.labels['rook.io/node']] = drives
+
+ return nodename_to_devices
+
+ def get_nfs_conf_url(self, nfs_cluster, instance):
+ #
+ # Fetch cephnfs object for "nfs_cluster" and then return a rados://
+ # URL for the instance within that cluster. If the fetch fails, just
+ # return None.
+ #
+ try:
+ ceph_nfs = self.rook_api_get("cephnfses/{0}".format(nfs_cluster))
+ except ApiException as e:
+ log.info("Unable to fetch cephnfs object: {}".format(e.status))
+ return None
+
+ pool = ceph_nfs['spec']['rados']['pool']
+ namespace = ceph_nfs['spec']['rados'].get('namespace', None)
+
+ if namespace == None:
+ url = "rados://{0}/conf-{1}.{2}".format(pool, nfs_cluster, instance)
+ else:
+ url = "rados://{0}/{1}/conf-{2}.{3}".format(pool, namespace, nfs_cluster, instance)
+ return url
+
+
+ def describe_pods(self, service_type, service_id, nodename):
+ # Go query the k8s API about deployment, containers related to this
+ # filesystem
+
+ # Inspect the Rook YAML, to decide whether this filesystem
+ # is Ceph-managed or Rook-managed
+ # TODO: extend Orchestrator interface to describe whether FS
+ # is manageable by us or not
+
+ # Example Rook Pod labels for a mgr daemon:
+ # Labels: app=rook-ceph-mgr
+ # pod-template-hash=2171958073
+ # rook_cluster=rook
+ # And MDS containers additionally have `rook_filesystem` label
+
+ # Label filter is rook_cluster=<cluster name>
+ # rook_file_system=<self.fs_name>
+
+ label_filter = "rook_cluster={0}".format(self.rook_env.cluster_name)
+ if service_type != None:
+ label_filter += ",app=rook-ceph-{0}".format(service_type)
+ if service_id != None:
+ if service_type == "mds":
+ label_filter += ",rook_file_system={0}".format(service_id)
+ elif service_type == "osd":
+ # Label added in https://github.com/rook/rook/pull/1698
+ label_filter += ",ceph-osd-id={0}".format(service_id)
+ elif service_type == "mon":
+ # label like mon=rook-ceph-mon0
+ label_filter += ",mon={0}".format(service_id)
+ elif service_type == "mgr":
+ label_filter += ",mgr={0}".format(service_id)
+ elif service_type == "nfs":
+ label_filter += ",ceph_nfs={0}".format(service_id)
+ elif service_type == "rgw":
+ # TODO: rgw
+ pass
+
+ field_filter = ""
+ if nodename != None:
+ field_filter = "spec.nodeName={0}".format(nodename)
+
+ pods = self.k8s.list_namespaced_pod(
+ self.rook_env.namespace,
+ label_selector=label_filter,
+ field_selector=field_filter)
+
+ # import json
+ # print json.dumps(pods.items[0])
+
+ pods_summary = []
+
+ for p in pods.items:
+ d = p.to_dict()
+ # p['metadata']['creationTimestamp']
+ # p['metadata']['nodeName']
+ pods_summary.append({
+ "name": d['metadata']['name'],
+ "nodename": d['spec']['node_name'],
+ "labels": d['metadata']['labels']
+ })
+ pass
+
+ return pods_summary
+
+ @contextmanager
+ def ignore_409(self, what):
+ try:
+ yield
+ except ApiException as e:
+ if e.status == 409:
+ # Idempotent, succeed.
+ log.info("{} already exists".format(what))
+ else:
+ raise
+
+ def add_filesystem(self, spec):
+ # TODO use spec.placement
+ # TODO warn if spec.extended has entries we don't kow how
+ # to action.
+
+ rook_fs = {
+ "apiVersion": self.rook_env.api_name,
+ "kind": "CephFilesystem",
+ "metadata": {
+ "name": spec.name,
+ "namespace": self.rook_env.namespace
+ },
+ "spec": {
+ "onlyManageDaemons": True,
+ "metadataServer": {
+ "activeCount": spec.count,
+ "activeStandby": True
+
+ }
+ }
+ }
+
+ with self.ignore_409("CephFilesystem '{0}' already exists".format(spec.name)):
+ self.rook_api_post("cephfilesystems/", body=rook_fs)
+
+ def add_nfsgw(self, spec):
+ # TODO use spec.placement
+ # TODO warn if spec.extended has entries we don't kow how
+ # to action.
+
+ rook_nfsgw = {
+ "apiVersion": self.rook_env.api_name,
+ "kind": "CephNFS",
+ "metadata": {
+ "name": spec.name,
+ "namespace": self.rook_env.namespace
+ },
+ "spec": {
+ "rados": {
+ "pool": spec.extended["pool"]
+ },
+ "server": {
+ "active": spec.count,
+ }
+ }
+ }
+
+ if "namespace" in spec.extended:
+ rook_nfsgw["spec"]["rados"]["namespace"] = spec.extended["namespace"]
+
+ with self.ignore_409("NFS cluster '{0}' already exists".format(spec.name)):
+ self.rook_api_post("cephnfses/", body=rook_nfsgw)
+
+ def add_objectstore(self, spec):
+ rook_os = {
+ "apiVersion": self.rook_env.api_name,
+ "kind": "CephObjectStore",
+ "metadata": {
+ "name": spec.name,
+ "namespace": self.rook_env.namespace
+ },
+ "spec": {
+ "metadataPool": {
+ "failureDomain": "host",
+ "replicated": {
+ "size": 1
+ }
+ },
+ "dataPool": {
+ "failureDomain": "osd",
+ "replicated": {
+ "size": 1
+ }
+ },
+ "gateway": {
+ "type": "s3",
+ "port": 80,
+ "instances": 1,
+ "allNodes": False
+ }
+ }
+ }
+
+ with self.ignore_409("CephObjectStore '{0}' already exists".format(spec.name)):
+ self.rook_api_post("cephobjectstores/", body=rook_os)
+
+ def rm_service(self, service_type, service_id):
+ assert service_type in ("mds", "rgw", "nfs")
+
+ if service_type == "mds":
+ rooktype = "cephfilesystems"
+ elif service_type == "rgw":
+ rooktype = "cephobjectstores"
+ elif service_type == "nfs":
+ rooktype = "cephnfses"
+
+ objpath = "{0}/{1}".format(rooktype, service_id)
+
+ try:
+ self.rook_api_delete(objpath)
+ except ApiException as e:
+ if e.status == 404:
+ log.info("{0} service '{1}' does not exist".format(service_type, service_id))
+ # Idempotent, succeed.
+ else:
+ raise
+
+ def can_create_osd(self):
+ current_cluster = self.rook_api_get(
+ "cephclusters/{0}".format(self.rook_env.cluster_name))
+ use_all_nodes = current_cluster['spec'].get('useAllNodes', False)
+
+ # If useAllNodes is set, then Rook will not be paying attention
+ # to anything we put in 'nodes', so can't do OSD creation.
+ return not use_all_nodes
+
+ def node_exists(self, node_name):
+ try:
+ self.k8s.read_node(node_name, exact=False, export=True)
+ except ApiException as e:
+ if e.status == 404:
+ return False
+ else:
+ raise
+ else:
+ return True
+
+ def update_mon_count(self, newcount):
+ patch = [{"op": "replace", "path": "/spec/mon/count", "value": newcount}]
+
+ try:
+ self.rook_api_patch(
+ "cephclusters/{0}".format(self.rook_env.cluster_name),
+ body=patch)
+ except ApiException as e:
+ log.exception("API exception: {0}".format(e))
+ raise ApplyException(
+ "Failed to update mon count in Cluster CRD: {0}".format(e))
+
+ return "Updated mon count to {0}".format(newcount)
+
+ def update_nfs_count(self, svc_id, newcount):
+ patch = [{"op": "replace", "path": "/spec/server/active", "value": newcount}]
+
+ try:
+ self.rook_api_patch(
+ "cephnfses/{0}".format(svc_id),
+ body=patch)
+ except ApiException as e:
+ log.exception("API exception: {0}".format(e))
+ raise ApplyException(
+ "Failed to update NFS server count for {0}: {1}".format(svc_id, e))
+ return "Updated NFS server count for {0} to {1}".format(svc_id, newcount)
+
+ def add_osds(self, drive_group, all_hosts):
+ # type: (orchestrator.DriveGroupSpec, List[str]) -> str
+ """
+ Rook currently (0.8) can only do single-drive OSDs, so we
+ treat all drive groups as just a list of individual OSDs.
+ """
+ block_devices = drive_group.data_devices.paths if drive_group.data_devices else None
+ directories = drive_group.data_directories
+
+ assert drive_group.objectstore in ("bluestore", "filestore")
+
+ # The CRD looks something like this:
+ # nodes:
+ # - name: "gravel1.rockery"
+ # devices:
+ # - name: "sdb"
+ # config:
+ # storeType: bluestore
+
+ current_cluster = self.rook_api_get(
+ "cephclusters/{0}".format(self.rook_env.cluster_name))
+
+ patch = []
+
+ # FIXME: this is all not really atomic, because jsonpatch doesn't
+ # let us do "test" operations that would check if items with
+ # matching names were in existing lists.
+
+ if 'nodes' not in current_cluster['spec']['storage']:
+ patch.append({
+ 'op': 'add', 'path': '/spec/storage/nodes', 'value': []
+ })
+
+ current_nodes = current_cluster['spec']['storage'].get('nodes', [])
+
+ if drive_group.hosts(all_hosts)[0] not in [n['name'] for n in current_nodes]:
+ pd = { "name": drive_group.hosts(all_hosts)[0],
+ "config": { "storeType": drive_group.objectstore }}
+
+ if block_devices:
+ pd["devices"] = [{'name': d} for d in block_devices]
+ if directories:
+ pd["directories"] = [{'path': p} for p in directories]
+
+ patch.append({ "op": "add", "path": "/spec/storage/nodes/-", "value": pd })
+ else:
+ # Extend existing node
+ node_idx = None
+ current_node = None
+ for i, c in enumerate(current_nodes):
+ if c['name'] == drive_group.hosts(all_hosts)[0]:
+ current_node = c
+ node_idx = i
+ break
+
+ assert node_idx is not None
+ assert current_node is not None
+
+ new_devices = list(set(block_devices) - set([d['name'] for d in current_node['devices']]))
+ for n in new_devices:
+ patch.append({
+ "op": "add",
+ "path": "/spec/storage/nodes/{0}/devices/-".format(node_idx),
+ "value": {'name': n}
+ })
+
+ new_dirs = list(set(directories) - set(current_node['directories']))
+ for p in new_dirs:
+ patch.append({
+ "op": "add",
+ "path": "/spec/storage/nodes/{0}/directories/-".format(node_idx),
+ "value": {'path': p}
+ })
+
+ if len(patch) == 0:
+ return "No change"
+
+ try:
+ self.rook_api_patch(
+ "cephclusters/{0}".format(self.rook_env.cluster_name),
+ body=patch)
+ except ApiException as e:
+ log.exception("API exception: {0}".format(e))
+ raise ApplyException(
+ "Failed to create OSD entries in Cluster CRD: {0}".format(
+ e))
+
+ return "Success"
diff --git a/src/pybind/mgr/selftest/__init__.py b/src/pybind/mgr/selftest/__init__.py
new file mode 100644
index 00000000..554aacbf
--- /dev/null
+++ b/src/pybind/mgr/selftest/__init__.py
@@ -0,0 +1,3 @@
+
+from .module import Module
+
diff --git a/src/pybind/mgr/selftest/module.py b/src/pybind/mgr/selftest/module.py
new file mode 100644
index 00000000..6aff2aa5
--- /dev/null
+++ b/src/pybind/mgr/selftest/module.py
@@ -0,0 +1,489 @@
+
+from mgr_module import MgrModule, CommandResult, PersistentStoreDict
+import threading
+import random
+import json
+import errno
+import six
+
+
+class Module(MgrModule):
+ """
+ This module is for testing the ceph-mgr python interface from within
+ a running ceph-mgr daemon.
+
+ It implements a sychronous self-test command for calling the functions
+ in the MgrModule interface one by one, and a background "workload"
+ command for causing the module to perform some thrashing-type
+ activities in its serve() thread.
+ """
+
+ # These workloads are things that can be requested to run inside the
+ # serve() function
+ WORKLOAD_COMMAND_SPAM = "command_spam"
+ WORKLOAD_THROW_EXCEPTION = "throw_exception"
+ SHUTDOWN = "shutdown"
+
+ WORKLOADS = (WORKLOAD_COMMAND_SPAM, WORKLOAD_THROW_EXCEPTION)
+
+ # The test code in qa/ relies on these options existing -- they
+ # are of course not really used for anything in the module
+ MODULE_OPTIONS = [
+ {'name': 'testkey'},
+ {'name': 'testlkey'},
+ {'name': 'testnewline'},
+ {'name': 'roption1'},
+ {'name': 'roption2', 'type': 'str', 'default': 'xyz'},
+ {'name': 'rwoption1'},
+ {'name': 'rwoption2', 'type': 'int'},
+ {'name': 'rwoption3', 'type': 'float'},
+ {'name': 'rwoption4', 'type': 'str'},
+ {'name': 'rwoption5', 'type': 'bool'},
+ {'name': 'rwoption6', 'type': 'bool', 'default': True}
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "mgr self-test run",
+ "desc": "Run mgr python interface tests",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test background start name=workload,type=CephString",
+ "desc": "Activate a background workload (one of {0})".format(
+ ", ".join(WORKLOADS)),
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test background stop",
+ "desc": "Stop background workload if any is running",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test config get name=key,type=CephString",
+ "desc": "Peek at a configuration value",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test config get_localized name=key,type=CephString",
+ "desc": "Peek at a configuration value (localized variant)",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test remote",
+ "desc": "Test inter-module calls",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test module name=module,type=CephString",
+ "desc": "Run another module's self_test() method",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test health set name=checks,type=CephString",
+ "desc": "Set a health check from a JSON-formatted description.",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test health clear name=checks,type=CephString,n=N,req=False",
+ "desc": "Clear health checks by name. If no names provided, clear all.",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test insights_set_now_offset name=hours,type=CephString",
+ "desc": "Set the now time for the insights module.",
+ "perm": "rw"
+ },
+ {
+ "cmd": "mgr self-test cluster-log name=channel,type=CephString "
+ "name=priority,type=CephString "
+ "name=message,type=CephString",
+ "desc": "Create an audit log record.",
+ "perm": "rw"
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self._event = threading.Event()
+ self._workload = None
+ self._health = {}
+
+ def handle_command(self, inbuf, command):
+ if command['prefix'] == 'mgr self-test run':
+ self._self_test()
+ return 0, '', 'Self-test succeeded'
+
+ elif command['prefix'] == 'mgr self-test background start':
+ if command['workload'] not in self.WORKLOADS:
+ return (-errno.EINVAL, '',
+ "Workload not found '{0}'".format(command['workload']))
+ self._workload = command['workload']
+ self._event.set()
+ return 0, '', 'Running `{0}` in background'.format(self._workload)
+
+ elif command['prefix'] == 'mgr self-test background stop':
+ if self._workload:
+ was_running = self._workload
+ self._workload = None
+ self._event.set()
+ return 0, '', 'Stopping background workload `{0}`'.format(
+ was_running)
+ else:
+ return 0, '', 'No background workload was running'
+ elif command['prefix'] == 'mgr self-test config get':
+ return 0, str(self.get_module_option(command['key'])), ''
+ elif command['prefix'] == 'mgr self-test config get_localized':
+ return 0, str(self.get_localized_module_option(command['key'])), ''
+ elif command['prefix'] == 'mgr self-test remote':
+ self._test_remote_calls()
+ return 0, '', 'Successfully called'
+ elif command['prefix'] == 'mgr self-test module':
+ try:
+ r = self.remote(command['module'], "self_test")
+ except RuntimeError as e:
+ return -1, '', "Test failed: {0}".format(e)
+ else:
+ return 0, str(r), "Self-test OK"
+ elif command['prefix'] == 'mgr self-test health set':
+ return self._health_set(inbuf, command)
+ elif command['prefix'] == 'mgr self-test health clear':
+ return self._health_clear(inbuf, command)
+ elif command['prefix'] == 'mgr self-test insights_set_now_offset':
+ return self._insights_set_now_offset(inbuf, command)
+ elif command['prefix'] == 'mgr self-test cluster-log':
+ priority_map = {
+ 'info': self.CLUSTER_LOG_PRIO_INFO,
+ 'security': self.CLUSTER_LOG_PRIO_SEC,
+ 'warning': self.CLUSTER_LOG_PRIO_WARN,
+ 'error': self.CLUSTER_LOG_PRIO_ERROR
+ }
+ self.cluster_log(command['channel'],
+ priority_map[command['priority']],
+ command['message'])
+ return 0, '', 'Successfully called'
+ else:
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(command['prefix']))
+
+ def _health_set(self, inbuf, command):
+ try:
+ checks = json.loads(command["checks"])
+ except Exception as e:
+ return -1, "", "Failed to decode JSON input: {}".format(e)
+
+ try:
+ for check, info in six.iteritems(checks):
+ self._health[check] = {
+ "severity": str(info["severity"]),
+ "summary": str(info["summary"]),
+ "detail": [str(m) for m in info["detail"]]
+ }
+ except Exception as e:
+ return -1, "", "Invalid health check format: {}".format(e)
+
+ self.set_health_checks(self._health)
+ return 0, "", ""
+
+ def _health_clear(self, inbuf, command):
+ if "checks" in command:
+ for check in command["checks"]:
+ if check in self._health:
+ del self._health[check]
+ else:
+ self._health = dict()
+
+ self.set_health_checks(self._health)
+ return 0, "", ""
+
+ def _insights_set_now_offset(self, inbuf, command):
+ try:
+ hours = int(command["hours"])
+ except Exception as e:
+ return -1, "", "Timestamp must be numeric: {}".format(e)
+
+ self.remote("insights", "testing_set_now_time_offset", hours)
+ return 0, "", ""
+
+ def _self_test(self):
+ self.log.info("Running self-test procedure...")
+
+ self._self_test_osdmap()
+ self._self_test_getters()
+ self._self_test_config()
+ self._self_test_store()
+ self._self_test_misc()
+ self._self_test_perf_counters()
+ self._self_persistent_store_dict()
+
+ def _self_test_getters(self):
+ self.version
+ self.get_context()
+ self.get_mgr_id()
+
+ # In this function, we will assume that the system is in a steady
+ # state, i.e. if a server/service appears in one call, it will
+ # not have gone by the time we call another function referring to it
+
+ objects = [
+ "fs_map",
+ "osdmap_crush_map_text",
+ "osd_map",
+ "config",
+ "mon_map",
+ "service_map",
+ "osd_metadata",
+ "pg_summary",
+ "pg_status",
+ "pg_dump",
+ "pg_ready",
+ "df",
+ "pg_stats",
+ "pool_stats",
+ "osd_stats",
+ "osd_ping_times",
+ "health",
+ "mon_status",
+ "mgr_map"
+ ]
+ for obj in objects:
+ assert self.get(obj) is not None
+
+ assert self.get("__OBJ_DNE__") is None
+
+ servers = self.list_servers()
+ for server in servers:
+ self.get_server(server['hostname'])
+
+ osdmap = self.get('osd_map')
+ for o in osdmap['osds']:
+ osd_id = o['osd']
+ self.get_metadata("osd", str(osd_id))
+
+ self.get_daemon_status("osd", "0")
+ #send_command
+
+ def _self_test_config(self):
+ # This is not a strong test (can't tell if values really
+ # persisted), it's just for the python interface bit.
+
+ self.set_module_option("testkey", "testvalue")
+ assert self.get_module_option("testkey") == "testvalue"
+
+ self.set_localized_module_option("testkey", "foo")
+ assert self.get_localized_module_option("testkey") == "foo"
+
+ # Must return the default value defined in MODULE_OPTIONS.
+ value = self.get_localized_module_option("rwoption6")
+ assert isinstance(value, bool)
+ assert value is True
+
+ # Use default value.
+ assert self.get_module_option("roption1") is None
+ assert self.get_module_option("roption1", "foobar") == "foobar"
+ assert self.get_module_option("roption2") == "xyz"
+ assert self.get_module_option("roption2", "foobar") == "xyz"
+
+ # Option type is not defined => return as string.
+ self.set_module_option("rwoption1", 8080)
+ value = self.get_module_option("rwoption1")
+ assert isinstance(value, str)
+ assert value == "8080"
+
+ # Option type is defined => return as integer.
+ self.set_module_option("rwoption2", 10)
+ value = self.get_module_option("rwoption2")
+ assert isinstance(value, int)
+ assert value == 10
+
+ # Option type is defined => return as float.
+ self.set_module_option("rwoption3", 1.5)
+ value = self.get_module_option("rwoption3")
+ assert isinstance(value, float)
+ assert value == 1.5
+
+ # Option type is defined => return as string.
+ self.set_module_option("rwoption4", "foo")
+ value = self.get_module_option("rwoption4")
+ assert isinstance(value, str)
+ assert value == "foo"
+
+ # Option type is defined => return as bool.
+ self.set_module_option("rwoption5", False)
+ value = self.get_module_option("rwoption5")
+ assert isinstance(value, bool)
+ assert value is False
+
+ # Specified module does not exist => return None.
+ assert self.get_module_option_ex("foo", "bar") is None
+
+ # Specified key does not exist => return None.
+ assert self.get_module_option_ex("dashboard", "bar") is None
+
+ self.set_module_option_ex("telemetry", "contact", "test@test.com")
+ assert self.get_module_option_ex("telemetry", "contact") == "test@test.com"
+
+ # No option default value, so use the specified one.
+ assert self.get_module_option_ex("dashboard", "password") is None
+ assert self.get_module_option_ex("dashboard", "password", "foobar") == "foobar"
+
+ # Option type is not defined => return as string.
+ self.set_module_option_ex("selftest", "rwoption1", 1234)
+ value = self.get_module_option_ex("selftest", "rwoption1")
+ assert isinstance(value, str)
+ assert value == "1234"
+
+ # Option type is defined => return as integer.
+ self.set_module_option_ex("telemetry", "interval", 60)
+ value = self.get_module_option_ex("telemetry", "interval")
+ assert isinstance(value, int)
+ assert value == 60
+
+ # Option type is defined => return as bool.
+ self.set_module_option_ex("telemetry", "leaderboard", True)
+ value = self.get_module_option_ex("telemetry", "leaderboard")
+ assert isinstance(value, bool)
+ assert value is True
+
+ def _self_test_store(self):
+ existing_keys = set(self.get_store_prefix("test").keys())
+ self.set_store("testkey", "testvalue")
+ assert self.get_store("testkey") == "testvalue"
+
+ assert sorted(self.get_store_prefix("test").keys()) == sorted(
+ list({"testkey"} | existing_keys))
+
+
+ def _self_test_perf_counters(self):
+ self.get_perf_schema("osd", "0")
+ self.get_counter("osd", "0", "osd.op")
+ #get_counter
+ #get_all_perf_coutners
+
+ def _self_test_misc(self):
+ self.set_uri("http://this.is.a.test.com")
+ self.set_health_checks({})
+
+ def _self_test_osdmap(self):
+ osdmap = self.get_osdmap()
+ osdmap.get_epoch()
+ osdmap.get_crush_version()
+ osdmap.dump()
+
+ inc = osdmap.new_incremental()
+ osdmap.apply_incremental(inc)
+ inc.get_epoch()
+ inc.dump()
+
+ crush = osdmap.get_crush()
+ crush.dump()
+ crush.get_item_name(-1)
+ crush.get_item_weight(-1)
+ crush.find_takes()
+ crush.get_take_weight_osd_map(-1)
+
+ #osdmap.get_pools_by_take()
+ #osdmap.calc_pg_upmaps()
+ #osdmap.map_pools_pgs_up()
+
+ #inc.set_osd_reweights
+ #inc.set_crush_compat_weight_set_weights
+
+ self.log.info("Finished self-test procedure.")
+
+ def _self_persistent_store_dict(self):
+ self.test_dict = PersistentStoreDict(self, 'test_dict')
+ for i in "abcde":
+ self.test_dict[i] = {i:1}
+ assert self.test_dict.keys() == set("abcde")
+ assert 'a' in self.test_dict
+ del self.test_dict['a']
+ assert self.test_dict.keys() == set("bcde"), self.test_dict.keys()
+ assert 'a' not in self.test_dict
+ self.test_dict.clear()
+ assert not self.test_dict, dict(self.test_dict.items())
+ self.set_store('test_dict.a', 'invalid json')
+ try:
+ self.test_dict['a']
+ assert False
+ except ValueError:
+ pass
+ assert not self.test_dict, dict(self.test_dict.items())
+
+ def _test_remote_calls(self):
+ # Test making valid call
+ self.remote("influx", "handle_command", "", {"prefix": "influx self-test"})
+
+ # Test calling module that exists but isn't enabled
+ # (arbitrarily pick a non-always-on module to use)
+ disabled_module = "telegraf"
+ mgr_map = self.get("mgr_map")
+ assert disabled_module not in mgr_map['modules']
+
+ # (This works until the Z release in about 2027)
+ latest_release = sorted(mgr_map['always_on_modules'].keys())[-1]
+ assert disabled_module not in mgr_map['always_on_modules'][latest_release]
+
+ try:
+ self.remote(disabled_module, "handle_command", {"prefix": "influx self-test"})
+ except ImportError:
+ pass
+ else:
+ raise RuntimeError("ImportError not raised for disabled module")
+
+ # Test calling module that doesn't exist
+ try:
+ self.remote("idontexist", "handle_command", {"prefix": "influx self-test"})
+ except ImportError:
+ pass
+ else:
+ raise RuntimeError("ImportError not raised for nonexistent module")
+
+ # Test calling method that doesn't exist
+ try:
+ self.remote("influx", "idontexist", {"prefix": "influx self-test"})
+ except NameError:
+ pass
+ else:
+ raise RuntimeError("KeyError not raised")
+
+
+ def shutdown(self):
+ self._workload = self.SHUTDOWN
+ self._event.set()
+
+ def _command_spam(self):
+ self.log.info("Starting command_spam workload...")
+ while not self._event.is_set():
+ osdmap = self.get_osdmap()
+ dump = osdmap.dump()
+ count = len(dump['osds'])
+ i = int(random.random() * count)
+ w = random.random()
+
+ result = CommandResult('')
+ self.send_command(result, 'mon', '', json.dumps({
+ 'prefix': 'osd reweight',
+ 'id': i,
+ 'weight': w
+ }), '')
+
+ crush = osdmap.get_crush().dump()
+ r, outb, outs = result.wait()
+
+ self._event.clear()
+ self.log.info("Ended command_spam workload...")
+
+ def serve(self):
+ while True:
+ if self._workload == self.WORKLOAD_COMMAND_SPAM:
+ self._command_spam()
+ elif self._workload == self.SHUTDOWN:
+ self.log.info("Shutting down...")
+ break
+ elif self._workload == self.WORKLOAD_THROW_EXCEPTION:
+ raise RuntimeError("Synthetic exception in serve")
+ else:
+ self.log.info("Waiting for workload request...")
+ self._event.wait()
+ self._event.clear()
diff --git a/src/pybind/mgr/ssh/.gitignore b/src/pybind/mgr/ssh/.gitignore
new file mode 100644
index 00000000..8000dd9d
--- /dev/null
+++ b/src/pybind/mgr/ssh/.gitignore
@@ -0,0 +1 @@
+.vagrant
diff --git a/src/pybind/mgr/ssh/README.md b/src/pybind/mgr/ssh/README.md
new file mode 100644
index 00000000..10f268cd
--- /dev/null
+++ b/src/pybind/mgr/ssh/README.md
@@ -0,0 +1,93 @@
+# dev environment setup
+
+1. start vms with _only_ the ceph packages installed
+
+In `src/pybind/mgr/ssh` run `vagrant up` to create a cluster with a monitor,
+manager, and osd nodes. The osd node will have two small extra disks attached.
+
+2. generate an `ssh_config` file for the vm hosts
+
+Execute `vagrant ssh-config > /path/to/ssh_config` to generate a ssh
+configuration file that contains hosts, usernames, and keys that will be used by
+the bootstrap cluster / ssh orchestrator to establish ssh connections to the
+vagrant vms.
+
+3. install ssh orchestrator dependencies
+
+The primary dependency is the `remoto` package that contains a Python SSH client
+for connecting to remote nodes and executing commands.
+
+Install with `dnf install python3-remoto`. The version must be >= 0.0.35. At the
+time of writing this version is being packaged and is not available. To install
+from source:
+
+```
+git clone https://github.com/ceph/remoto
+cd remoto
+python3 setup.py sdist
+pip3 install --prefix=/usr dist/remoto-0.0.35.tar.gz
+```
+
+4. start the bootstrap cluster (in this case a `vstart.sh` cluster)
+
+Start with a network binding to which the vms can route traffic:
+
+ `vstart.sh -n -i 192.168.121.1`
+
+The following is a manual method for finding this address. TODO: documenting a
+automated/deterministic method would be very helpful.
+
+First, ensure that your firewall settings permit each VM to communicate with the
+host. On Fedora, the `trusted` profile is sufficient: `firewall-cmd
+--set-default-zone trusted` and also allows traffic on Ceph ports. Then ssh into
+one of the vm nodes and ping the default gateway, which happens to be setup as
+the host machine.
+
+```
+[nwatkins@smash ssh]$ vagrant ssh mon0 -c "getent hosts gateway"
+192.168.121.1 gateway
+```
+
+5. setup the ssh orchestrator backend
+
+Enable and configure the ssh orchestrator as the active backend:
+
+```
+ceph mgr module enable ssh
+ceph orchestrator set backend ssh
+
+# optional: this document assumes the orchestrator CLI is enabled
+ceph mgr module enable orchestrator_cli
+```
+
+Configure the ssh orchestrator by setting the `ssh_config` option to point at
+the ssh configuration file generated above:
+
+```
+ceph config set mgr mgr/ssh/ssh_config_file /path/to/config
+```
+
+The setting can be confirmed by retrieving the configuration settings:
+
+```
+[nwatkins@smash build]$ ceph config get mgr.
+WHO MASK LEVEL OPTION VALUE RO
+mgr advanced mgr/orchestrator_cli/orchestrator ssh *
+mgr advanced mgr/ssh/ssh_config_file /home/nwatkins/src/ceph/src/pybind/mgr/ssh/config *
+```
+
+An SSH config file can also be provided through standard input that avoids the
+need to have an accessible file path. Use the following command:
+
+
+```
+ceph ssh set-ssh-config -i <path to ssh_config>
+```
+
+The next set of instructions we should move to the docs folder
+
+ceph orchestrator host add osd0
+ceph orchestrator host add mgr0
+ceph orchestrator host add mon0
+ceph orchestrator device ls
+ceph orchestrator mgr update 3 mgr0 mgr1
diff --git a/src/pybind/mgr/ssh/Vagrantfile b/src/pybind/mgr/ssh/Vagrantfile
new file mode 100644
index 00000000..0a2a6389
--- /dev/null
+++ b/src/pybind/mgr/ssh/Vagrantfile
@@ -0,0 +1,39 @@
+# vi: set ft=ruby :
+
+NUM_DAEMONS = ENV["NUM_DAEMONS"] ? ENV["NUM_DAEMONS"].to_i : 1
+
+Vagrant.configure("2") do |config|
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+ config.vm.network "private_network", type: "dhcp"
+ config.vm.box = "centos/7"
+
+ (0..NUM_DAEMONS - 1).each do |i|
+ config.vm.define "mon#{i}" do |mon|
+ mon.vm.hostname = "mon#{i}"
+ end
+ config.vm.define "mgr#{i}" do |mgr|
+ mgr.vm.hostname = "mgr#{i}"
+ end
+ config.vm.define "osd#{i}" do |osd|
+ osd.vm.hostname = "osd#{i}"
+ osd.vm.provider :libvirt do |libvirt|
+ libvirt.storage :file, :size => '5G'
+ libvirt.storage :file, :size => '5G'
+ end
+ end
+ end
+
+ config.vm.provision "shell" do |s|
+ ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
+ s.inline = "echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys"
+ end
+
+ config.vm.provision "shell", inline: <<-SHELL
+ sudo yum install -y yum-utils
+ sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+ sudo rpm --import 'https://download.ceph.com/keys/release.asc'
+ curl -L https://shaman.ceph.com/api/repos/ceph/master/latest/centos/7/repo/ | sudo tee /etc/yum.repos.d/shaman.repo
+ sudo yum install -y ceph python36
+ sudo ln -s /usr/bin/python36 /usr/bin/python3
+ SHELL
+end
diff --git a/src/pybind/mgr/ssh/__init__.py b/src/pybind/mgr/ssh/__init__.py
new file mode 100644
index 00000000..3f41e016
--- /dev/null
+++ b/src/pybind/mgr/ssh/__init__.py
@@ -0,0 +1 @@
+from .module import SSHOrchestrator
diff --git a/src/pybind/mgr/ssh/ceph.repo b/src/pybind/mgr/ssh/ceph.repo
new file mode 100644
index 00000000..6f710e7c
--- /dev/null
+++ b/src/pybind/mgr/ssh/ceph.repo
@@ -0,0 +1,23 @@
+[ceph]
+name=Ceph packages for $basearch
+baseurl=https://download.ceph.com/rpm-mimic/el7/$basearch
+enabled=1
+priority=2
+gpgcheck=1
+gpgkey=https://download.ceph.com/keys/release.asc
+
+[ceph-noarch]
+name=Ceph noarch packages
+baseurl=https://download.ceph.com/rpm-mimic/el7/noarch
+enabled=1
+priority=2
+gpgcheck=1
+gpgkey=https://download.ceph.com/keys/release.asc
+
+[ceph-source]
+name=Ceph source packages
+baseurl=https://download.ceph.com/rpm-mimic/el7/SRPMS
+enabled=0
+priority=2
+gpgcheck=1
+gpgkey=https://download.ceph.com/keys/release.asc
diff --git a/src/pybind/mgr/ssh/module.py b/src/pybind/mgr/ssh/module.py
new file mode 100644
index 00000000..73675e52
--- /dev/null
+++ b/src/pybind/mgr/ssh/module.py
@@ -0,0 +1,740 @@
+import json
+import errno
+import logging
+from functools import wraps
+
+import six
+import os
+import tempfile
+import multiprocessing.pool
+
+from mgr_module import MgrModule
+import orchestrator
+
+from . import remotes
+
+try:
+ import remoto
+ import remoto.process
+except ImportError as e:
+ remoto = None
+ remoto_import_error = str(e)
+
+logger = logging.getLogger(__name__)
+
+# high-level TODO:
+# - bring over some of the protections from ceph-deploy that guard against
+# multiple bootstrapping / initialization
+
+class SSHCompletionmMixin(object):
+ def __init__(self, result):
+ if isinstance(result, multiprocessing.pool.AsyncResult):
+ self._result = [result]
+ else:
+ self._result = result
+ assert isinstance(self._result, list)
+
+ @property
+ def result(self):
+ return list(map(lambda r: r.get(), self._result))
+
+class SSHReadCompletion(SSHCompletionmMixin, orchestrator.ReadCompletion):
+ @property
+ def is_complete(self):
+ return all(map(lambda r: r.ready(), self._result))
+
+
+class SSHWriteCompletion(SSHCompletionmMixin, orchestrator.WriteCompletion):
+
+ @property
+ def is_persistent(self):
+ return all(map(lambda r: r.ready(), self._result))
+
+ @property
+ def is_effective(self):
+ return all(map(lambda r: r.ready(), self._result))
+
+ @property
+ def is_errored(self):
+ for r in self._result:
+ if not r.ready():
+ return False
+ if not r.successful():
+ return True
+ return False
+
+class SSHWriteCompletionReady(SSHWriteCompletion):
+ def __init__(self, result):
+ orchestrator.WriteCompletion.__init__(self)
+ self._result = result
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_persistent(self):
+ return True
+
+ @property
+ def is_effective(self):
+ return True
+
+ @property
+ def is_errored(self):
+ return False
+
+class SSHConnection(object):
+ """
+ Tie tempfile lifetime (e.g. ssh_config) to a remoto connection.
+ """
+ def __init__(self):
+ self.conn = None
+ self.temp_file = None
+
+ # proxy to the remoto connection
+ def __getattr__(self, name):
+ return getattr(self.conn, name)
+
+
+def log_exceptions(f):
+ if six.PY3:
+ return f
+ else:
+ # Python 2 does no exception chaining, thus the
+ # real exception is lost
+ @wraps(f)
+ def wrapper(*args, **kwargs):
+ try:
+ return f(*args, **kwargs)
+ except Exception:
+ logger.exception('something went wrong.')
+ raise
+ return wrapper
+
+
+class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
+
+ _STORE_HOST_PREFIX = "host"
+ _DEFAULT_INVENTORY_CACHE_TIMEOUT_MIN = 10
+
+ MODULE_OPTIONS = [
+ {'name': 'ssh_config_file'},
+ {'name': 'inventory_cache_timeout_min'},
+ ]
+
+ COMMANDS = [
+ {
+ 'cmd': 'ssh set-ssh-config',
+ 'desc': 'Set the ssh_config file (use -i <ssh_config>)',
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'ssh clear-ssh-config',
+ 'desc': 'Clear the ssh_config file',
+ 'perm': 'rw'
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(SSHOrchestrator, self).__init__(*args, **kwargs)
+ self._cluster_fsid = None
+ self._worker_pool = multiprocessing.pool.ThreadPool(1)
+
+ # the keys in inventory_cache are authoritative.
+ # You must not call remove_outdated()
+ # The values are cached by instance.
+ # cache is invalidated by
+ # 1. timeout
+ # 2. refresh parameter
+ self.inventory_cache = orchestrator.OutdatablePersistentDict(self, self._STORE_HOST_PREFIX)
+
+ def handle_command(self, inbuf, command):
+ if command["prefix"] == "ssh set-ssh-config":
+ return self._set_ssh_config(inbuf, command)
+ elif command["prefix"] == "ssh clear-ssh-config":
+ return self._clear_ssh_config(inbuf, command)
+ else:
+ raise NotImplementedError(command["prefix"])
+
+ @staticmethod
+ def can_run():
+ if remoto is not None:
+ return True, ""
+ else:
+ return False, "loading remoto library:{}".format(
+ remoto_import_error)
+
+ def available(self):
+ """
+ The SSH orchestrator is always available.
+ """
+ return self.can_run()
+
+ def wait(self, completions):
+ self.log.info("wait: completions={}".format(completions))
+
+ complete = True
+ for c in completions:
+ if c.is_complete:
+ continue
+
+ if not isinstance(c, SSHReadCompletion) and \
+ not isinstance(c, SSHWriteCompletion):
+ raise TypeError("unexpected completion: {}".format(c.__class__))
+
+ complete = False
+
+ return complete
+
+ def _get_cluster_fsid(self):
+ """
+ Fetch and cache the cluster fsid.
+ """
+ if not self._cluster_fsid:
+ self._cluster_fsid = self.get("mon_map")["fsid"]
+ assert isinstance(self._cluster_fsid, six.string_types)
+ return self._cluster_fsid
+
+ def _require_hosts(self, hosts):
+ """
+ Raise an error if any of the given hosts are unregistered.
+ """
+ if isinstance(hosts, six.string_types):
+ hosts = [hosts]
+ keys = self.inventory_cache.keys()
+ unregistered_hosts = set(hosts) - keys
+ if unregistered_hosts:
+ logger.warning('keys = {}'.format(keys))
+ raise RuntimeError("Host(s) {} not registered".format(
+ ", ".join(map(lambda h: "'{}'".format(h),
+ unregistered_hosts))))
+
+ def _set_ssh_config(self, inbuf, command):
+ """
+ Set an ssh_config file provided from stdin
+
+ TODO:
+ - validation
+ """
+ if len(inbuf) == 0:
+ return errno.EINVAL, "", "empty ssh config provided"
+ self.set_store("ssh_config", inbuf)
+ return 0, "", ""
+
+ def _clear_ssh_config(self, inbuf, command):
+ """
+ Clear the ssh_config file provided from stdin
+ """
+ self.set_store("ssh_config", None)
+ self.ssh_config_tmp = None
+ return 0, "", ""
+
+ def _get_connection(self, host):
+ """
+ Setup a connection for running commands on remote host.
+ """
+ ssh_options = None
+
+ conn = SSHConnection()
+
+ ssh_config = self.get_store("ssh_config")
+ if ssh_config is not None:
+ conn.temp_file = tempfile.NamedTemporaryFile()
+ conn.temp_file.write(ssh_config.encode('utf-8'))
+ conn.temp_file.flush() # make visible to other processes
+ ssh_config_fname = conn.temp_file.name
+ else:
+ ssh_config_fname = self.get_localized_module_option("ssh_config_file")
+
+ if ssh_config_fname:
+ if not os.path.isfile(ssh_config_fname):
+ raise Exception("ssh_config \"{}\" does not exist".format(ssh_config_fname))
+ ssh_options = "-F {}".format(ssh_config_fname)
+
+ self.log.info("opening connection to host '{}' with ssh "
+ "options '{}'".format(host, ssh_options))
+
+ conn.conn = remoto.Connection(host,
+ logger=self.log,
+ detect_sudo=True,
+ ssh_options=ssh_options)
+
+ conn.conn.import_module(remotes)
+
+ return conn
+
+ def _executable_path(self, conn, executable):
+ """
+ Remote validator that accepts a connection object to ensure that a certain
+ executable is available returning its full path if so.
+
+ Otherwise an exception with thorough details will be raised, informing the
+ user that the executable was not found.
+ """
+ executable_path = conn.remote_module.which(executable)
+ if not executable_path:
+ raise RuntimeError("Executable '{}' not found on host '{}'".format(
+ executable, conn.hostname))
+ self.log.info("Found executable '{}' at path '{}'".format(executable,
+ executable_path))
+ return executable_path
+
+ def _build_ceph_conf(self):
+ """
+ Build a minimal `ceph.conf` containing the current monitor hosts.
+
+ Notes:
+ - ceph-volume complains if no section header (e.g. global) exists
+ - other ceph cli tools complained about no EOF newline
+
+ TODO:
+ - messenger v2 syntax?
+ """
+ mon_map = self.get("mon_map")
+ mon_addrs = map(lambda m: m["addr"], mon_map["mons"])
+ mon_hosts = ", ".join(mon_addrs)
+ return "[global]\nmon host = {}\n".format(mon_hosts)
+
+ def _ensure_ceph_conf(self, conn, network=False):
+ """
+ Install ceph.conf on remote node if it doesn't exist.
+ """
+ conf = self._build_ceph_conf()
+ if network:
+ conf += "public_network = {}\n".format(network)
+ conn.remote_module.write_conf("/etc/ceph/ceph.conf", conf)
+
+ def _get_bootstrap_key(self, service_type):
+ """
+ Fetch a bootstrap key for a service type.
+
+ :param service_type: name (e.g. mds, osd, mon, ...)
+ """
+ identity_dict = {
+ 'admin' : 'client.admin',
+ 'mds' : 'client.bootstrap-mds',
+ 'mgr' : 'client.bootstrap-mgr',
+ 'osd' : 'client.bootstrap-osd',
+ 'rgw' : 'client.bootstrap-rgw',
+ 'mon' : 'mon.'
+ }
+
+ identity = identity_dict[service_type]
+
+ ret, out, err = self.mon_command({
+ "prefix": "auth get",
+ "entity": identity
+ })
+
+ if ret == -errno.ENOENT:
+ raise RuntimeError("Entity '{}' not found: '{}'".format(identity, err))
+ elif ret != 0:
+ raise RuntimeError("Error retrieving key for '{}' ret {}: '{}'".format(
+ identity, ret, err))
+
+ return out
+
+ def _bootstrap_mgr(self, conn):
+ """
+ Bootstrap a manager.
+
+ 1. install a copy of ceph.conf
+ 2. install the manager bootstrap key
+
+ :param conn: remote host connection
+ """
+ self._ensure_ceph_conf(conn)
+ keyring = self._get_bootstrap_key("mgr")
+ keyring_path = "/var/lib/ceph/bootstrap-mgr/ceph.keyring"
+ conn.remote_module.write_keyring(keyring_path, keyring)
+ return keyring_path
+
+ def _bootstrap_osd(self, conn):
+ """
+ Bootstrap an osd.
+
+ 1. install a copy of ceph.conf
+ 2. install the osd bootstrap key
+
+ :param conn: remote host connection
+ """
+ self._ensure_ceph_conf(conn)
+ keyring = self._get_bootstrap_key("osd")
+ keyring_path = "/var/lib/ceph/bootstrap-osd/ceph.keyring"
+ conn.remote_module.write_keyring(keyring_path, keyring)
+ return keyring_path
+
+ def _get_hosts(self, wanted=None):
+ return self.inventory_cache.items_filtered(wanted)
+
+ def add_host(self, host):
+ """
+ Add a host to be managed by the orchestrator.
+
+ :param host: host name
+ """
+ @log_exceptions
+ def run(host):
+ self.inventory_cache[host] = orchestrator.OutdatableData()
+ return "Added host '{}'".format(host)
+
+ return SSHWriteCompletion(
+ self._worker_pool.apply_async(run, (host,)))
+
+ def remove_host(self, host):
+ """
+ Remove a host from orchestrator management.
+
+ :param host: host name
+ """
+ @log_exceptions
+ def run(host):
+ del self.inventory_cache[host]
+ return "Removed host '{}'".format(host)
+
+ return SSHWriteCompletion(
+ self._worker_pool.apply_async(run, (host,)))
+
+ def get_hosts(self):
+ """
+ Return a list of hosts managed by the orchestrator.
+
+ Notes:
+ - skip async: manager reads from cache.
+
+ TODO:
+ - InventoryNode probably needs to be able to report labels
+ """
+ nodes = [orchestrator.InventoryNode(host_name, []) for host_name in self.inventory_cache]
+ return orchestrator.TrivialReadCompletion(nodes)
+
+ def _get_device_inventory(self, host):
+ """
+ Query storage devices on a remote node.
+
+ :return: list of InventoryDevice
+ """
+ conn = self._get_connection(host)
+
+ try:
+ ceph_volume_executable = self._executable_path(conn, 'ceph-volume')
+ command = [
+ ceph_volume_executable,
+ "inventory",
+ "--format=json"
+ ]
+
+ out, err, code = remoto.process.check(conn, command)
+ host_devices = json.loads(out[0])
+ return host_devices
+
+ except Exception as ex:
+ self.log.exception(ex)
+ raise
+
+ finally:
+ conn.exit()
+
+ def get_inventory(self, node_filter=None, refresh=False):
+ """
+ Return the storage inventory of nodes matching the given filter.
+
+ :param node_filter: node filter
+
+ TODO:
+ - add filtering by label
+ """
+ if node_filter:
+ hosts = node_filter.nodes
+ self._require_hosts(hosts)
+ hosts = self._get_hosts(hosts)
+ else:
+ # this implies the returned hosts are registered
+ hosts = self._get_hosts()
+
+ @log_exceptions
+ def run(host, host_info):
+ # type: (str, orchestrator.OutdatableData) -> orchestrator.InventoryNode
+
+ timeout_min = int(self.get_module_option(
+ "inventory_cache_timeout_min",
+ self._DEFAULT_INVENTORY_CACHE_TIMEOUT_MIN))
+
+ if host_info.outdated(timeout_min) or refresh:
+ self.log.info("refresh stale inventory for '{}'".format(host))
+ data = self._get_device_inventory(host)
+ host_info = orchestrator.OutdatableData(data)
+ self.inventory_cache[host] = host_info
+ else:
+ self.log.debug("reading cached inventory for '{}'".format(host))
+
+ devices = orchestrator.InventoryDevice.from_ceph_volume_inventory_list(host_info.data)
+ return orchestrator.InventoryNode(host, devices)
+
+ results = []
+ for key, host_info in hosts:
+ result = self._worker_pool.apply_async(run, (key, host_info))
+ results.append(result)
+
+ return SSHReadCompletion(results)
+
+ @log_exceptions
+ def _create_osd(self, host, drive_group):
+ conn = self._get_connection(host)
+ try:
+ devices = drive_group.data_devices.paths
+ self._bootstrap_osd(conn)
+
+ for device in devices:
+ ceph_volume_executable = self._executable_path(conn, "ceph-volume")
+ command = [
+ ceph_volume_executable,
+ "lvm",
+ "create",
+ "--cluster-fsid", self._get_cluster_fsid(),
+ "--{}".format(drive_group.objectstore),
+ "--data", device
+ ]
+ remoto.process.run(conn, command)
+
+ return "Created osd on host '{}'".format(host)
+
+ except:
+ raise
+
+ finally:
+ conn.exit()
+
+ def create_osds(self, drive_group, all_hosts=None):
+ """
+ Create a new osd.
+
+ The orchestrator CLI currently handles a narrow form of drive
+ specification defined by a single block device using bluestore.
+
+ :param drive_group: osd specification
+
+ TODO:
+ - support full drive_group specification
+ - support batch creation
+ """
+ assert len(drive_group.hosts(all_hosts)) == 1
+ assert len(drive_group.data_devices.paths) > 0
+ assert all(map(lambda p: isinstance(p, six.string_types),
+ drive_group.data_devices.paths))
+
+ host = drive_group.hosts(all_hosts)[0]
+ self._require_hosts(host)
+
+ result = self._worker_pool.apply_async(self._create_osd, (host,
+ drive_group))
+
+ return SSHWriteCompletion(result)
+
+ def _create_mon(self, host, network):
+ """
+ Create a new monitor on the given host.
+ """
+ self.log.info("create_mon({}:{}): starting".format(host, network))
+
+ conn = self._get_connection(host)
+
+ try:
+ self._ensure_ceph_conf(conn, network)
+
+ uid = conn.remote_module.path_getuid("/var/lib/ceph")
+ gid = conn.remote_module.path_getgid("/var/lib/ceph")
+
+ # install client admin key on target mon host
+ admin_keyring = self._get_bootstrap_key("admin")
+ admin_keyring_path = '/etc/ceph/ceph.client.admin.keyring'
+ conn.remote_module.write_keyring(admin_keyring_path, admin_keyring, uid, gid)
+
+ mon_path = "/var/lib/ceph/mon/ceph-{name}".format(name=host)
+ conn.remote_module.create_mon_path(mon_path, uid, gid)
+
+ # bootstrap key
+ conn.remote_module.safe_makedirs("/var/lib/ceph/tmp")
+ monitor_keyring = self._get_bootstrap_key("mon")
+ mon_keyring_path = "/var/lib/ceph/tmp/ceph-{name}.mon.keyring".format(name=host)
+ conn.remote_module.write_file(
+ mon_keyring_path,
+ monitor_keyring,
+ 0o600,
+ None,
+ uid,
+ gid
+ )
+
+ # monitor map
+ monmap_path = "/var/lib/ceph/tmp/ceph.{name}.monmap".format(name=host)
+ remoto.process.run(conn,
+ ['ceph', 'mon', 'getmap', '-o', monmap_path],
+ )
+
+ user_args = []
+ if uid != 0:
+ user_args = user_args + [ '--setuser', str(uid) ]
+ if gid != 0:
+ user_args = user_args + [ '--setgroup', str(gid) ]
+
+ remoto.process.run(conn,
+ ['ceph-mon', '--mkfs', '-i', host,
+ '--monmap', monmap_path, '--keyring', mon_keyring_path
+ ] + user_args
+ )
+
+ remoto.process.run(conn,
+ ['systemctl', 'enable', 'ceph.target'],
+ timeout=7,
+ )
+
+ remoto.process.run(conn,
+ ['systemctl', 'enable', 'ceph-mon@{name}'.format(name=host)],
+ timeout=7,
+ )
+
+ remoto.process.run(conn,
+ ['systemctl', 'start', 'ceph-mon@{name}'.format(name=host)],
+ timeout=7,
+ )
+
+ return "Created mon on host '{}'".format(host)
+
+ except Exception as e:
+ self.log.error("create_mon({}:{}): error: {}".format(host, network, e))
+ raise
+
+ finally:
+ self.log.info("create_mon({}:{}): finished".format(host, network))
+ conn.exit()
+
+ def update_mons(self, num, hosts):
+ """
+ Adjust the number of cluster monitors.
+ """
+ # current support limited to adding monitors.
+ mon_map = self.get("mon_map")
+ num_mons = len(mon_map["mons"])
+ if num == num_mons:
+ return SSHWriteCompletionReady("The requested number of monitors exist.")
+ if num < num_mons:
+ raise NotImplementedError("Removing monitors is not supported.")
+
+ # check that all the hostnames are registered
+ self._require_hosts(map(lambda h: h[0], hosts))
+
+ # current support requires a network to be specified
+ for host, network in hosts:
+ if not network:
+ raise RuntimeError("Host '{}' missing network "
+ "part".format(host))
+
+ # explicit placement: enough hosts provided?
+ num_new_mons = num - num_mons
+ if len(hosts) < num_new_mons:
+ raise RuntimeError("Error: {} hosts provided, expected {}".format(
+ len(hosts), num_new_mons))
+
+ self.log.info("creating {} monitors on hosts: '{}'".format(
+ num_new_mons, ",".join(map(lambda h: ":".join(h), hosts))))
+
+ # TODO: we may want to chain the creation of the monitors so they join
+ # the quroum one at a time.
+ results = []
+ for host, network in hosts:
+ result = self._worker_pool.apply_async(self._create_mon, (host,
+ network))
+ results.append(result)
+
+ return SSHWriteCompletion(results)
+
+ def _create_mgr(self, host):
+ """
+ Create a new manager instance on a host.
+ """
+ self.log.info("create_mgr({}): starting".format(host))
+
+ conn = self._get_connection(host)
+
+ try:
+ bootstrap_keyring_path = self._bootstrap_mgr(conn)
+
+ mgr_path = "/var/lib/ceph/mgr/ceph-{name}".format(name=host)
+ conn.remote_module.safe_makedirs(mgr_path)
+ keyring_path = os.path.join(mgr_path, "keyring")
+
+ command = [
+ 'ceph',
+ '--name', 'client.bootstrap-mgr',
+ '--keyring', bootstrap_keyring_path,
+ 'auth', 'get-or-create', 'mgr.{name}'.format(name=host),
+ 'mon', 'allow profile mgr',
+ 'osd', 'allow *',
+ 'mds', 'allow *',
+ '-o',
+ keyring_path
+ ]
+
+ out, err, ret = remoto.process.check(conn, command)
+ if ret != 0:
+ raise Exception("oops")
+
+ remoto.process.run(conn,
+ ['systemctl', 'enable', 'ceph-mgr@{name}'.format(name=host)],
+ timeout=7
+ )
+
+ remoto.process.run(conn,
+ ['systemctl', 'start', 'ceph-mgr@{name}'.format(name=host)],
+ timeout=7
+ )
+
+ remoto.process.run(conn,
+ ['systemctl', 'enable', 'ceph.target'],
+ timeout=7
+ )
+
+ return "Created mgr on host '{}'".format(host)
+
+ except Exception as e:
+ self.log.error("create_mgr({}): error: {}".format(host, e))
+ raise
+
+ finally:
+ self.log.info("create_mgr({}): finished".format(host))
+ conn.exit()
+
+ def update_mgrs(self, num, hosts):
+ """
+ Adjust the number of cluster managers.
+ """
+ # current support limited to adding managers.
+ mgr_map = self.get("mgr_map")
+ num_mgrs = 1 if mgr_map["active_name"] else 0
+ num_mgrs += len(mgr_map["standbys"])
+ if num == num_mgrs:
+ return SSHWriteCompletionReady("The requested number of managers exist.")
+ if num < num_mgrs:
+ raise NotImplementedError("Removing managers is not supported")
+
+ # check that all the hosts are registered
+ self._require_hosts(hosts)
+
+ # we assume explicit placement by which there are the same number of
+ # hosts specified as the size of increase in number of daemons.
+ num_new_mgrs = num - num_mgrs
+ if len(hosts) < num_new_mgrs:
+ raise RuntimeError("Error: {} hosts provided, expected {}".format(
+ len(hosts), num_new_mgrs))
+
+ self.log.info("creating {} managers on hosts: '{}'".format(
+ num_new_mgrs, ",".join(hosts)))
+
+ results = []
+ for i in range(num_new_mgrs):
+ result = self._worker_pool.apply_async(self._create_mgr, (hosts[i],))
+ results.append(result)
+
+ return SSHWriteCompletion(results)
diff --git a/src/pybind/mgr/ssh/remotes.py b/src/pybind/mgr/ssh/remotes.py
new file mode 100644
index 00000000..da057e83
--- /dev/null
+++ b/src/pybind/mgr/ssh/remotes.py
@@ -0,0 +1,81 @@
+# ceph-deploy ftw
+import os
+import errno
+import tempfile
+import shutil
+
+def safe_makedirs(path, uid=-1, gid=-1):
+ """ create path recursively if it doesn't exist """
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ if e.errno == errno.EEXIST:
+ pass
+ else:
+ raise
+ else:
+ os.chown(path, uid, gid)
+
+def write_conf(path, conf):
+ if not os.path.exists(path):
+ dirpath = os.path.dirname(path)
+ if os.path.exists(dirpath):
+ with open(path, "w") as f:
+ f.write(conf)
+ os.chmod(path, 0o644)
+ else:
+ raise RuntimeError(
+ "{0} does not exist".format(dirpath))
+
+def write_keyring(path, key, overwrite=False, uid=-1, gid=-1):
+ dirname = os.path.dirname(path)
+ if not os.path.exists(dirname):
+ safe_makedirs(dirname, uid, gid)
+ if not overwrite and os.path.exists(path):
+ return
+ with open(path, "wb") as f:
+ f.write(key.encode('utf-8'))
+
+def create_mon_path(path, uid=-1, gid=-1):
+ """create the mon path if it does not exist"""
+ if not os.path.exists(path):
+ os.makedirs(path)
+ os.chown(path, uid, gid);
+
+def write_file(path, content, mode=0o644, directory=None, uid=-1, gid=-1):
+ if directory:
+ if path.startswith("/"):
+ path = path[1:]
+ path = os.path.join(directory, path)
+ if os.path.exists(path):
+ # Delete file in case we are changing its mode
+ os.unlink(path)
+ with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, mode), 'wb') as f:
+ f.write(content.encode('utf-8'))
+ os.chown(path, uid, gid)
+
+def path_getuid(path):
+ return os.stat(path).st_uid
+
+def path_getgid(path):
+ return os.stat(path).st_gid
+
+def which(executable):
+ """find the location of an executable"""
+ locations = (
+ '/usr/local/bin',
+ '/bin',
+ '/usr/bin',
+ '/usr/local/sbin',
+ '/usr/sbin',
+ '/sbin',
+ )
+
+ for location in locations:
+ executable_path = os.path.join(location, executable)
+ if os.path.exists(executable_path) and os.path.isfile(executable_path):
+ return executable_path
+
+if __name__ == '__channelexec__':
+ for item in channel:
+ channel.send(eval(item))
diff --git a/src/pybind/mgr/status/__init__.py b/src/pybind/mgr/status/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/status/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/status/module.py b/src/pybind/mgr/status/module.py
new file mode 100644
index 00000000..f8509296
--- /dev/null
+++ b/src/pybind/mgr/status/module.py
@@ -0,0 +1,261 @@
+
+"""
+High level status display commands
+"""
+
+from collections import defaultdict
+from prettytable import PrettyTable
+import errno
+import fnmatch
+import mgr_util
+import prettytable
+import six
+
+from mgr_module import MgrModule
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "fs status "
+ "name=fs,type=CephString,req=false",
+ "desc": "Show the status of a CephFS filesystem",
+ "perm": "r"
+ },
+ {
+ "cmd": "osd status "
+ "name=bucket,type=CephString,req=false",
+ "desc": "Show the status of OSDs within a bucket, or all",
+ "perm": "r"
+ },
+ ]
+
+
+ def get_latest(self, daemon_type, daemon_name, stat):
+ data = self.get_counter(daemon_type, daemon_name, stat)[stat]
+ #self.log.error("get_latest {0} data={1}".format(stat, data))
+ if data:
+ return data[-1][1]
+ else:
+ return 0
+
+ def get_rate(self, daemon_type, daemon_name, stat):
+ data = self.get_counter(daemon_type, daemon_name, stat)[stat]
+
+ #self.log.error("get_latest {0} data={1}".format(stat, data))
+ if data and len(data) > 1:
+ return (data[-1][1] - data[-2][1]) / float(data[-1][0] - data[-2][0])
+ else:
+ return 0
+
+ def handle_fs_status(self, cmd):
+ output = ""
+
+ fs_filter = cmd.get('fs', None)
+
+ mds_versions = defaultdict(list)
+
+ fsmap = self.get("fs_map")
+ for filesystem in fsmap['filesystems']:
+ if fs_filter and filesystem['mdsmap']['fs_name'] != fs_filter:
+ continue
+
+ rank_table = PrettyTable(
+ ("Rank", "State", "MDS", "Activity", "dns", "inos"),
+ hrules=prettytable.FRAME
+ )
+
+ mdsmap = filesystem['mdsmap']
+
+ client_count = 0
+
+ for rank in mdsmap["in"]:
+ up = "mds_{0}".format(rank) in mdsmap["up"]
+ if up:
+ gid = mdsmap['up']["mds_{0}".format(rank)]
+ info = mdsmap['info']['gid_{0}'.format(gid)]
+ dns = self.get_latest("mds", info['name'], "mds_mem.dn")
+ inos = self.get_latest("mds", info['name'], "mds_mem.ino")
+
+ if rank == 0:
+ client_count = self.get_latest("mds", info['name'],
+ "mds_sessions.session_count")
+ elif client_count == 0:
+ # In case rank 0 was down, look at another rank's
+ # sessionmap to get an indication of clients.
+ client_count = self.get_latest("mds", info['name'],
+ "mds_sessions.session_count")
+
+ laggy = "laggy_since" in info
+
+ state = info['state'].split(":")[1]
+ if laggy:
+ state += "(laggy)"
+ if state == "active" and not laggy:
+ c_state = mgr_util.colorize(state, mgr_util.GREEN)
+ else:
+ c_state = mgr_util.colorize(state, mgr_util.YELLOW)
+
+ # Populate based on context of state, e.g. client
+ # ops for an active daemon, replay progress, reconnect
+ # progress
+ activity = ""
+
+ if state == "active":
+ activity = "Reqs: " + mgr_util.format_dimless(
+ self.get_rate("mds", info['name'], "mds_server.handle_client_request"),
+ 5
+ ) + "/s"
+
+ defaults = defaultdict(lambda: None, {'version' : 'unknown'})
+ metadata = self.get_metadata('mds', info['name'], default=defaults)
+ mds_versions[metadata['ceph_version']].append(info['name'])
+ rank_table.add_row([
+ mgr_util.bold(rank.__str__()), c_state, info['name'],
+ activity,
+ mgr_util.format_dimless(dns, 5),
+ mgr_util.format_dimless(inos, 5)
+ ])
+
+ else:
+ rank_table.add_row([
+ rank, "failed", "", "", "", ""
+ ])
+
+ # Find the standby replays
+ for gid_str, daemon_info in six.iteritems(mdsmap['info']):
+ if daemon_info['state'] != "up:standby-replay":
+ continue
+
+ inos = self.get_latest("mds", daemon_info['name'], "mds_mem.ino")
+ dns = self.get_latest("mds", daemon_info['name'], "mds_mem.dn")
+
+ activity = "Evts: " + mgr_util.format_dimless(
+ self.get_rate("mds", daemon_info['name'], "mds_log.replayed"),
+ 5
+ ) + "/s"
+
+ defaults = defaultdict(lambda: None, {'version' : 'unknown'})
+ metadata = self.get_metadata('mds', daemon_info['name'], default=defaults)
+ mds_versions[metadata['ceph_version']].append(daemon_info['name'])
+
+ rank_table.add_row([
+ "{0}-s".format(daemon_info['rank']), "standby-replay",
+ daemon_info['name'], activity,
+ mgr_util.format_dimless(dns, 5),
+ mgr_util.format_dimless(inos, 5)
+ ])
+
+ df = self.get("df")
+ pool_stats = dict([(p['id'], p['stats']) for p in df['pools']])
+ osdmap = self.get("osd_map")
+ pools = dict([(p['pool'], p) for p in osdmap['pools']])
+ metadata_pool_id = mdsmap['metadata_pool']
+ data_pool_ids = mdsmap['data_pools']
+
+ pools_table = PrettyTable(["Pool", "type", "used", "avail"])
+ for pool_id in [metadata_pool_id] + data_pool_ids:
+ pool_type = "metadata" if pool_id == metadata_pool_id else "data"
+ stats = pool_stats[pool_id]
+ pools_table.add_row([
+ pools[pool_id]['pool_name'], pool_type,
+ mgr_util.format_bytes(stats['bytes_used'], 5),
+ mgr_util.format_bytes(stats['max_avail'], 5)
+ ])
+
+ output += "{0} - {1} clients\n".format(
+ mdsmap['fs_name'], client_count)
+ output += "=" * len(mdsmap['fs_name']) + "\n"
+ output += rank_table.get_string()
+ output += "\n" + pools_table.get_string() + "\n"
+
+ if not output and fs_filter is not None:
+ return errno.EINVAL, "", "Invalid filesystem: " + fs_filter
+
+ standby_table = PrettyTable(["Standby MDS"])
+ for standby in fsmap['standbys']:
+ defaults = defaultdict(lambda: None, {'version' : 'unknown'})
+ metadata = self.get_metadata('mds', standby['name'], default=defaults)
+ mds_versions[metadata['ceph_version']].append(standby['name'])
+
+ standby_table.add_row([standby['name']])
+
+ output += "\n" + standby_table.get_string() + "\n"
+
+ if len(mds_versions) == 1:
+ output += "MDS version: {0}".format(list(mds_versions)[0])
+ else:
+ version_table = PrettyTable(["version", "daemons"])
+ for version, daemons in six.iteritems(mds_versions):
+ version_table.add_row([
+ version,
+ ", ".join(daemons)
+ ])
+ output += version_table.get_string() + "\n"
+
+ return 0, output, ""
+
+ def handle_osd_status(self, cmd):
+ osd_table = PrettyTable(['id', 'host', 'used', 'avail', 'wr ops', 'wr data', 'rd ops', 'rd data', 'state'])
+ osdmap = self.get("osd_map")
+
+ filter_osds = set()
+ bucket_filter = None
+ if 'bucket' in cmd:
+ self.log.debug("Filtering to bucket '{0}'".format(cmd['bucket']))
+ bucket_filter = cmd['bucket']
+ crush = self.get("osd_map_crush")
+ found = False
+ for bucket in crush['buckets']:
+ if fnmatch.fnmatch(bucket['name'], bucket_filter):
+ found = True
+ filter_osds.update([i['id'] for i in bucket['items']])
+
+ if not found:
+ msg = "Bucket '{0}' not found".format(bucket_filter)
+ return errno.ENOENT, msg, ""
+
+ # Build dict of OSD ID to stats
+ osd_stats = dict([(o['osd'], o) for o in self.get("osd_stats")['osd_stats']])
+
+ for osd in osdmap['osds']:
+ osd_id = osd['osd']
+ if bucket_filter and osd_id not in filter_osds:
+ continue
+
+ hostname = ""
+ kb_used = 0
+ kb_avail = 0
+
+ if osd_id in osd_stats:
+ defaults = defaultdict(lambda: None, {'hostname' : ''})
+ metadata = self.get_metadata('osd', str(osd_id), default=defaults)
+ stats = osd_stats[osd_id]
+ hostname = metadata['hostname']
+ kb_used = stats['kb_used'] * 1024
+ kb_avail = stats['kb_avail'] * 1024
+
+ osd_table.add_row([osd_id, hostname,
+ mgr_util.format_bytes(kb_used, 5),
+ mgr_util.format_bytes(kb_avail, 5),
+ mgr_util.format_dimless(self.get_rate("osd", osd_id.__str__(), "osd.op_w") +
+ self.get_rate("osd", osd_id.__str__(), "osd.op_rw"), 5),
+ mgr_util.format_bytes(self.get_rate("osd", osd_id.__str__(), "osd.op_in_bytes"), 5),
+ mgr_util.format_dimless(self.get_rate("osd", osd_id.__str__(), "osd.op_r"), 5),
+ mgr_util.format_bytes(self.get_rate("osd", osd_id.__str__(), "osd.op_out_bytes"), 5),
+ ','.join(osd['state']),
+ ])
+
+ return 0, osd_table.get_string(), ""
+
+ def handle_command(self, inbuf, cmd):
+ self.log.error("handle_command")
+
+ if cmd['prefix'] == "fs status":
+ return self.handle_fs_status(cmd)
+ elif cmd['prefix'] == "osd status":
+ return self.handle_osd_status(cmd)
+ else:
+ # mgr should respect our self.COMMANDS and not call us for
+ # any prefix we don't advertise
+ raise NotImplementedError(cmd['prefix'])
diff --git a/src/pybind/mgr/telegraf/__init__.py b/src/pybind/mgr/telegraf/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/telegraf/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/telegraf/basesocket.py b/src/pybind/mgr/telegraf/basesocket.py
new file mode 100644
index 00000000..43599466
--- /dev/null
+++ b/src/pybind/mgr/telegraf/basesocket.py
@@ -0,0 +1,45 @@
+import socket
+
+
+class BaseSocket(object):
+ schemes = {
+ 'unixgram': (socket.AF_UNIX, socket.SOCK_DGRAM),
+ 'unix': (socket.AF_UNIX, socket.SOCK_STREAM),
+ 'tcp': (socket.AF_INET, socket.SOCK_STREAM),
+ 'tcp6': (socket.AF_INET6, socket.SOCK_STREAM),
+ 'udp': (socket.AF_INET, socket.SOCK_DGRAM),
+ 'udp6': (socket.AF_INET6, socket.SOCK_DGRAM),
+ }
+
+ def __init__(self, url):
+ self.url = url
+
+ try:
+ socket_family, socket_type = self.schemes[self.url.scheme]
+ except KeyError:
+ raise RuntimeError('Unsupported socket type: %s', self.url.scheme)
+
+ self.sock = socket.socket(family=socket_family, type=socket_type)
+ if self.sock.family == socket.AF_UNIX:
+ self.address = self.url.path
+ else:
+ self.address = (self.url.hostname, self.url.port)
+
+ def connect(self):
+ return self.sock.connect(self.address)
+
+ def close(self):
+ self.sock.close()
+
+ def send(self, data, flags=0):
+ return self.sock.send(data.encode('utf-8') + b'\n', flags)
+
+ def __del__(self):
+ self.sock.close()
+
+ def __enter__(self):
+ self.connect()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.close()
diff --git a/src/pybind/mgr/telegraf/module.py b/src/pybind/mgr/telegraf/module.py
new file mode 100644
index 00000000..8264fdf3
--- /dev/null
+++ b/src/pybind/mgr/telegraf/module.py
@@ -0,0 +1,301 @@
+import errno
+import json
+import itertools
+import six
+import socket
+import time
+from threading import Event
+
+from telegraf.basesocket import BaseSocket
+from telegraf.protocol import Line
+from mgr_module import MgrModule, PG_STATES
+
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urlparse import urlparse
+
+
+class Module(MgrModule):
+ COMMANDS = [
+ {
+ "cmd": "telegraf config-set name=key,type=CephString "
+ "name=value,type=CephString",
+ "desc": "Set a configuration value",
+ "perm": "rw"
+ },
+ {
+ "cmd": "telegraf config-show",
+ "desc": "Show current configuration",
+ "perm": "r"
+ },
+ {
+ "cmd": "telegraf send",
+ "desc": "Force sending data to Telegraf",
+ "perm": "rw"
+ },
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'address',
+ 'default': 'unixgram:///tmp/telegraf.sock',
+ },
+ {
+ 'name': 'interval',
+ 'type': 'secs',
+ 'default': 15
+ }
+ ]
+
+ ceph_health_mapping = {'HEALTH_OK': 0, 'HEALTH_WARN': 1, 'HEALTH_ERR': 2}
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None)) for o in self.MODULE_OPTIONS)
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.event = Event()
+ self.run = True
+ self.fsid = None
+ self.config = dict()
+
+ def get_fsid(self):
+ if not self.fsid:
+ self.fsid = self.get('mon_map')['fsid']
+
+ return self.fsid
+
+ def get_pool_stats(self):
+ df = self.get('df')
+
+ df_types = [
+ 'bytes_used',
+ 'kb_used',
+ 'dirty',
+ 'rd',
+ 'rd_bytes',
+ 'stored_raw',
+ 'wr',
+ 'wr_bytes',
+ 'objects',
+ 'max_avail',
+ 'quota_objects',
+ 'quota_bytes'
+ ]
+
+ for df_type in df_types:
+ for pool in df['pools']:
+ yield {
+ 'measurement': 'ceph_pool_stats',
+ 'tags': {
+ 'pool_name': pool['name'],
+ 'pool_id': pool['id'],
+ 'type_instance': df_type,
+ 'fsid': self.get_fsid()
+ },
+ 'value': pool['stats'][df_type],
+ }
+
+ def get_daemon_stats(self):
+ for daemon, counters in six.iteritems(self.get_all_perf_counters()):
+ svc_type, svc_id = daemon.split('.', 1)
+ metadata = self.get_metadata(svc_type, svc_id)
+ if not metadata:
+ continue
+
+ for path, counter_info in counters.items():
+ if counter_info['type'] & self.PERFCOUNTER_HISTOGRAM:
+ continue
+
+ yield {
+ 'measurement': 'ceph_daemon_stats',
+ 'tags': {
+ 'ceph_daemon': daemon,
+ 'type_instance': path,
+ 'host': metadata['hostname'],
+ 'fsid': self.get_fsid()
+ },
+ 'value': counter_info['value']
+ }
+
+ def get_pg_stats(self):
+ stats = dict()
+
+ pg_status = self.get('pg_status')
+ for key in ['bytes_total', 'data_bytes', 'bytes_used', 'bytes_avail',
+ 'num_pgs', 'num_objects', 'num_pools']:
+ stats[key] = pg_status[key]
+
+ for state in PG_STATES:
+ stats['num_pgs_{0}'.format(state)] = 0
+
+ stats['num_pgs'] = pg_status['num_pgs']
+ for state in pg_status['pgs_by_state']:
+ states = state['state_name'].split('+')
+ for s in PG_STATES:
+ key = 'num_pgs_{0}'.format(s)
+ if s in states:
+ stats[key] += state['count']
+
+ return stats
+
+ def get_cluster_stats(self):
+ stats = dict()
+
+ health = json.loads(self.get('health')['json'])
+ stats['health'] = self.ceph_health_mapping.get(health['status'])
+
+ mon_status = json.loads(self.get('mon_status')['json'])
+ stats['num_mon'] = len(mon_status['monmap']['mons'])
+
+ stats['mon_election_epoch'] = mon_status['election_epoch']
+ stats['mon_outside_quorum'] = len(mon_status['outside_quorum'])
+ stats['mon_quorum'] = len(mon_status['quorum'])
+
+ osd_map = self.get('osd_map')
+ stats['num_osd'] = len(osd_map['osds'])
+ stats['num_pg_temp'] = len(osd_map['pg_temp'])
+ stats['osd_epoch'] = osd_map['epoch']
+
+ mgr_map = self.get('mgr_map')
+ stats['mgr_available'] = int(mgr_map['available'])
+ stats['num_mgr_standby'] = len(mgr_map['standbys'])
+ stats['mgr_epoch'] = mgr_map['epoch']
+
+ num_up = 0
+ num_in = 0
+ for osd in osd_map['osds']:
+ if osd['up'] == 1:
+ num_up += 1
+
+ if osd['in'] == 1:
+ num_in += 1
+
+ stats['num_osd_up'] = num_up
+ stats['num_osd_in'] = num_in
+
+ fs_map = self.get('fs_map')
+ stats['num_mds_standby'] = len(fs_map['standbys'])
+ stats['num_fs'] = len(fs_map['filesystems'])
+ stats['mds_epoch'] = fs_map['epoch']
+
+ num_mds_up = 0
+ for fs in fs_map['filesystems']:
+ num_mds_up += len(fs['mdsmap']['up'])
+
+ stats['num_mds_up'] = num_mds_up
+ stats['num_mds'] = num_mds_up + stats['num_mds_standby']
+
+ stats.update(self.get_pg_stats())
+
+ for key, value in stats.items():
+ yield {
+ 'measurement': 'ceph_cluster_stats',
+ 'tags': {
+ 'type_instance': key,
+ 'fsid': self.get_fsid()
+ },
+ 'value': int(value)
+ }
+
+ def set_config_option(self, option, value):
+ if option not in self.config_keys.keys():
+ raise RuntimeError('{0} is a unknown configuration '
+ 'option'.format(option))
+
+ if option in ['interval']:
+ try:
+ value = int(value)
+ except (ValueError, TypeError):
+ raise RuntimeError('invalid {0} configured. Please specify '
+ 'a valid integer'.format(option))
+
+ if option == 'interval' and value < 5:
+ raise RuntimeError('interval should be set to at least 5 seconds')
+
+ self.config[option] = value
+
+ def init_module_config(self):
+ self.config['address'] = \
+ self.get_module_option("address", default=self.config_keys['address'])
+ self.config['interval'] = \
+ int(self.get_module_option("interval",
+ default=self.config_keys['interval']))
+
+ def now(self):
+ return int(round(time.time() * 1000000000))
+
+ def gather_measurements(self):
+ return itertools.chain(
+ self.get_pool_stats(),
+ self.get_daemon_stats(),
+ self.get_cluster_stats()
+ )
+
+ def send_to_telegraf(self):
+ url = urlparse(self.config['address'])
+
+ sock = BaseSocket(url)
+ self.log.debug('Sending data to Telegraf at %s', sock.address)
+ now = self.now()
+ try:
+ with sock as s:
+ for measurement in self.gather_measurements():
+ self.log.debug(measurement)
+ line = Line(measurement['measurement'],
+ measurement['value'],
+ measurement['tags'], now)
+ self.log.debug(line.to_line_protocol())
+ s.send(line.to_line_protocol())
+ except (socket.error, RuntimeError, IOError, OSError):
+ self.log.exception('Failed to send statistics to Telegraf:')
+ except FileNotFoundError:
+ self.log.exception('Failed to open Telegraf at: %s', url.geturl())
+
+ def shutdown(self):
+ self.log.info('Stopping Telegraf module')
+ self.run = False
+ self.event.set()
+
+ def handle_command(self, inbuf, cmd):
+ if cmd['prefix'] == 'telegraf config-show':
+ return 0, json.dumps(self.config), ''
+ elif cmd['prefix'] == 'telegraf config-set':
+ key = cmd['key']
+ value = cmd['value']
+ if not value:
+ return -errno.EINVAL, '', 'Value should not be empty or None'
+
+ self.log.debug('Setting configuration option %s to %s', key, value)
+ self.set_config_option(key, value)
+ self.set_module_option(key, value)
+ return 0, 'Configuration option {0} updated'.format(key), ''
+ elif cmd['prefix'] == 'telegraf send':
+ self.send_to_telegraf()
+ return 0, 'Sending data to Telegraf', ''
+
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(cmd['prefix']))
+
+ def self_test(self):
+ measurements = list(self.gather_measurements())
+ if len(measurements) == 0:
+ raise RuntimeError('No measurements found')
+
+ def serve(self):
+ self.log.info('Starting Telegraf module')
+ self.init_module_config()
+ self.run = True
+
+ self.log.debug('Waiting 10 seconds before starting')
+ self.event.wait(10)
+
+ while self.run:
+ start = self.now()
+ self.send_to_telegraf()
+ runtime = (self.now() - start) / 1000000
+ self.log.debug('Sending data to Telegraf took %d ms', runtime)
+ self.log.debug("Sleeping for %d seconds", self.config['interval'])
+ self.event.wait(self.config['interval'])
diff --git a/src/pybind/mgr/telegraf/protocol.py b/src/pybind/mgr/telegraf/protocol.py
new file mode 100644
index 00000000..d243e0c1
--- /dev/null
+++ b/src/pybind/mgr/telegraf/protocol.py
@@ -0,0 +1,44 @@
+from telegraf.utils import format_string, format_value
+
+
+class Line(object):
+ def __init__(self, measurement, values, tags=None, timestamp=None):
+ self.measurement = measurement
+ self.values = values
+ self.tags = tags
+ self.timestamp = timestamp
+
+ def get_output_measurement(self):
+ return format_string(self.measurement)
+
+ def get_output_values(self):
+ if not isinstance(self.values, dict):
+ metric_values = {'value': self.values}
+ else:
+ metric_values = self.values
+
+ sorted_values = sorted(metric_values.items())
+ sorted_values = [(k, v) for k, v in sorted_values if v is not None]
+
+ return u','.join(u'{0}={1}'.format(format_string(k), format_value(v)) for k, v in sorted_values)
+
+ def get_output_tags(self):
+ if not self.tags:
+ self.tags = dict()
+
+ sorted_tags = sorted(self.tags.items())
+
+ return u','.join(u'{0}={1}'.format(format_string(k), format_string(v)) for k, v in sorted_tags)
+
+ def get_output_timestamp(self):
+ return ' {0}'.format(self.timestamp) if self.timestamp else ''
+
+ def to_line_protocol(self):
+ tags = self.get_output_tags()
+
+ return u'{0}{1} {2}{3}'.format(
+ self.get_output_measurement(),
+ "," + tags if tags else '',
+ self.get_output_values(),
+ self.get_output_timestamp()
+ )
diff --git a/src/pybind/mgr/telegraf/utils.py b/src/pybind/mgr/telegraf/utils.py
new file mode 100644
index 00000000..4c7fd1ca
--- /dev/null
+++ b/src/pybind/mgr/telegraf/utils.py
@@ -0,0 +1,20 @@
+def format_string(key):
+ if isinstance(key, str):
+ key = key.replace(',', r'\,')
+ key = key.replace(' ', r'\ ')
+ key = key.replace('=', r'\=')
+ return key
+
+
+def format_value(value):
+ if isinstance(value, str):
+ value = value.replace('"', '\"')
+ value = u'"{0}"'.format(value)
+ elif isinstance(value, bool):
+ value = str(value)
+ elif isinstance(value, int):
+ value = "{0}i".format(value)
+ elif isinstance(value, float):
+ value = str(value)
+ return value
+
diff --git a/src/pybind/mgr/telemetry/__init__.py b/src/pybind/mgr/telemetry/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/telemetry/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/telemetry/module.py b/src/pybind/mgr/telemetry/module.py
new file mode 100644
index 00000000..c21e2340
--- /dev/null
+++ b/src/pybind/mgr/telemetry/module.py
@@ -0,0 +1,854 @@
+"""
+Telemetry module for ceph-mgr
+
+Collect statistics from Ceph cluster and send this back to the Ceph project
+when user has opted-in
+"""
+import errno
+import hashlib
+import json
+import rbd
+import re
+import requests
+import uuid
+import time
+from datetime import datetime, timedelta
+from threading import Event
+from collections import defaultdict
+
+from mgr_module import MgrModule
+
+
+ALL_CHANNELS = ['basic', 'ident', 'crash', 'device']
+
+LICENSE='sharing-1-0'
+LICENSE_NAME='Community Data License Agreement - Sharing - Version 1.0'
+LICENSE_URL='https://cdla.io/sharing-1-0/'
+
+# If the telemetry revision has changed since this point, re-require
+# an opt-in. This should happen each time we add new information to
+# the telemetry report.
+LAST_REVISION_RE_OPT_IN = 2
+
+# Latest revision of the telemetry report. Bump this each time we make
+# *any* change.
+REVISION = 3
+
+# History of revisions
+# --------------------
+#
+# Version 1:
+# Mimic and/or nautilus are lumped together here, since
+# we didn't track revisions yet.
+#
+# Version 2:
+# - added revision tracking, nagging, etc.
+# - added config option changes
+# - added channels
+# - added explicit license acknowledgement to the opt-in process
+#
+# Version 3:
+# - added device health metrics (i.e., SMART data, minus serial number)
+# - remove crush_rule
+# - added CephFS metadata (how many MDSs, fs features, how many data pools,
+# how much metadata is cached, rfiles, rbytes, rsnapshots)
+# - added more pool metadata (rep vs ec, cache tiering mode, ec profile)
+# - added host count, and counts for hosts with each of (mon, osd, mds, mgr)
+# - whether an OSD cluster network is in use
+# - rbd pool and image count, and rbd mirror mode (pool-level)
+# - rgw daemons, zones, zonegroups; which rgw frontends
+# - crush map stats
+
+class Module(MgrModule):
+ config = dict()
+
+ metadata_keys = [
+ "arch",
+ "ceph_version",
+ "os",
+ "cpu",
+ "kernel_description",
+ "kernel_version",
+ "distro_description",
+ "distro"
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'url',
+ 'type': 'str',
+ 'default': 'https://telemetry.ceph.com/report'
+ },
+ {
+ 'name': 'device_url',
+ 'type': 'str',
+ 'default': 'https://telemetry.ceph.com/device'
+ },
+ {
+ 'name': 'enabled',
+ 'type': 'bool',
+ 'default': False
+ },
+ {
+ 'name': 'last_opt_revision',
+ 'type': 'int',
+ 'default': 1,
+ },
+ {
+ 'name': 'leaderboard',
+ 'type': 'bool',
+ 'default': False
+ },
+ {
+ 'name': 'description',
+ 'type': 'str',
+ 'default': None
+ },
+ {
+ 'name': 'contact',
+ 'type': 'str',
+ 'default': None
+ },
+ {
+ 'name': 'organization',
+ 'type': 'str',
+ 'default': None
+ },
+ {
+ 'name': 'proxy',
+ 'type': 'str',
+ 'default': None
+ },
+ {
+ 'name': 'interval',
+ 'type': 'int',
+ 'default': 24,
+ 'min': 8
+ },
+ {
+ 'name': 'channel_basic',
+ 'type': 'bool',
+ 'default': True,
+ 'desc': 'Share basic cluster information (size, version)',
+ },
+ {
+ 'name': 'channel_ident',
+ 'type': 'bool',
+ 'default': False,
+ 'description': 'Share a user-provided description and/or contact email for the cluster',
+ },
+ {
+ 'name': 'channel_crash',
+ 'type': 'bool',
+ 'default': True,
+ 'description': 'Share metadata about Ceph daemon crashes (version, stack straces, etc)',
+ },
+ {
+ 'name': 'channel_device',
+ 'type': 'bool',
+ 'default': True,
+ 'description': 'Share device health metrics (e.g., SMART data, minus potentially identifying info like serial numbers)',
+ },
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "telemetry status",
+ "desc": "Show current configuration",
+ "perm": "r"
+ },
+ {
+ "cmd": "telemetry send "
+ "name=endpoint,type=CephChoices,strings=ceph|device,n=N,req=false "
+ "name=license,type=CephString,req=false",
+ "desc": "Force sending data to Ceph telemetry",
+ "perm": "rw"
+ },
+ {
+ "cmd": "telemetry show "
+ "name=channels,type=CephString,n=N,req=False",
+ "desc": "Show last report or report to be sent",
+ "perm": "r"
+ },
+ {
+ "cmd": "telemetry show-device",
+ "desc": "Show last device report or device report to be sent",
+ "perm": "r"
+ },
+ {
+ "cmd": "telemetry on name=license,type=CephString,req=false",
+ "desc": "Enable telemetry reports from this cluster",
+ "perm": "rw",
+ },
+ {
+ "cmd": "telemetry off",
+ "desc": "Disable telemetry reports from this cluster",
+ "perm": "rw",
+ },
+ ]
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None)) for o in self.MODULE_OPTIONS)
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.event = Event()
+ self.run = False
+ self.last_upload = None
+ self.last_report = dict()
+ self.report_id = None
+ self.salt = None
+
+ def config_notify(self):
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'],
+ self.get_module_option(opt['name']))
+ self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
+ # wake up serve() thread
+ self.event.set()
+
+ @staticmethod
+ def parse_timestamp(timestamp):
+ return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f')
+
+ def load(self):
+ self.last_upload = self.get_store('last_upload', None)
+ if self.last_upload is not None:
+ self.last_upload = int(self.last_upload)
+
+ self.report_id = self.get_store('report_id', None)
+ if self.report_id is None:
+ self.report_id = str(uuid.uuid4())
+ self.set_store('report_id', self.report_id)
+
+ self.salt = self.get_store('salt', None)
+ if not self.salt:
+ self.salt = str(uuid.uuid4())
+ self.set_store('salt', self.salt)
+
+ def gather_osd_metadata(self, osd_map):
+ keys = ["osd_objectstore", "rotational"]
+ keys += self.metadata_keys
+
+ metadata = dict()
+ for key in keys:
+ metadata[key] = defaultdict(int)
+
+ for osd in osd_map['osds']:
+ res = self.get_metadata('osd', str(osd['osd'])).items()
+ if res is None:
+ self.log.debug('Could not get metadata for osd.%s' % str(osd['osd']))
+ continue
+ for k, v in res:
+ if k not in keys:
+ continue
+
+ metadata[k][v] += 1
+
+ return metadata
+
+ def gather_mon_metadata(self, mon_map):
+ keys = list()
+ keys += self.metadata_keys
+
+ metadata = dict()
+ for key in keys:
+ metadata[key] = defaultdict(int)
+
+ for mon in mon_map['mons']:
+ res = self.get_metadata('mon', mon['name']).items()
+ if res is None:
+ self.log.debug('Could not get metadata for mon.%s' % (mon['name']))
+ continue
+ for k, v in res:
+ if k not in keys:
+ continue
+
+ metadata[k][v] += 1
+
+ return metadata
+
+ def gather_crush_info(self):
+ osdmap = self.get_osdmap()
+ crush_raw = osdmap.get_crush()
+ crush = crush_raw.dump()
+
+ def inc(d, k):
+ if k in d:
+ d[k] += 1
+ else:
+ d[k] = 1
+
+ device_classes = {}
+ for dev in crush['devices']:
+ inc(device_classes, dev.get('class', ''))
+
+ bucket_algs = {}
+ bucket_types = {}
+ bucket_sizes = {}
+ for bucket in crush['buckets']:
+ if '~' in bucket['name']: # ignore shadow buckets
+ continue
+ inc(bucket_algs, bucket['alg'])
+ inc(bucket_types, bucket['type_id'])
+ inc(bucket_sizes, len(bucket['items']))
+
+ return {
+ 'num_devices': len(crush['devices']),
+ 'num_types': len(crush['types']),
+ 'num_buckets': len(crush['buckets']),
+ 'num_rules': len(crush['rules']),
+ 'device_classes': list(device_classes.values()),
+ 'tunables': crush['tunables'],
+ 'compat_weight_set': '-1' in crush['choose_args'],
+ 'num_weight_sets': len(crush['choose_args']),
+ 'bucket_algs': bucket_algs,
+ 'bucket_sizes': bucket_sizes,
+ 'bucket_types': bucket_types,
+ }
+
+ def gather_configs(self):
+ # cluster config options
+ cluster = set()
+ r, outb, outs = self.mon_command({
+ 'prefix': 'config dump',
+ 'format': 'json'
+ });
+ if r != 0:
+ return {}
+ try:
+ dump = json.loads(outb)
+ except json.decoder.JSONDecodeError:
+ return {}
+ for opt in dump:
+ name = opt.get('name')
+ if name:
+ cluster.add(name)
+ # daemon-reported options (which may include ceph.conf)
+ active = set()
+ ls = self.get("modified_config_options");
+ for opt in ls.get('options', {}):
+ active.add(opt)
+ return {
+ 'cluster_changed': sorted(list(cluster)),
+ 'active_changed': sorted(list(active)),
+ }
+
+ def gather_crashinfo(self):
+ crashlist = list()
+ errno, crashids, err = self.remote('crash', 'ls')
+ if errno:
+ return ''
+ for crashid in crashids.split():
+ cmd = {'id': crashid}
+ errno, crashinfo, err = self.remote('crash', 'do_info', cmd, '')
+ if errno:
+ continue
+ c = json.loads(crashinfo)
+ del c['utsname_hostname']
+ # entity_name might have more than one '.', beware
+ (etype, eid) = c.get('entity_name', '').split('.', 1)
+ m = hashlib.sha1()
+ m.update(self.salt.encode('utf-8'))
+ m.update(eid.encode('utf-8'))
+ m.update(self.salt.encode('utf-8'))
+ c['entity_name'] = etype + '.' + m.hexdigest()
+ crashlist.append(c)
+ return crashlist
+
+ def get_active_channels(self):
+ r = []
+ if self.channel_basic:
+ r.append('basic')
+ if self.channel_crash:
+ r.append('crash')
+ if self.channel_device:
+ r.append('device')
+ return r
+
+ def gather_device_report(self):
+ try:
+ time_format = self.remote('devicehealth', 'get_time_format')
+ except:
+ return None
+ cutoff = datetime.utcnow() - timedelta(hours=self.interval * 2)
+ min_sample = cutoff.strftime(time_format)
+
+ devices = self.get('devices')['devices']
+
+ res = {} # anon-host-id -> anon-devid -> { timestamp -> record }
+ for d in devices:
+ devid = d['devid']
+ try:
+ # this is a map of stamp -> {device info}
+ m = self.remote('devicehealth', 'get_recent_device_metrics',
+ devid, min_sample)
+ except:
+ continue
+
+ # anonymize host id
+ try:
+ host = d['location'][0]['host']
+ except:
+ continue
+ anon_host = self.get_store('host-id/%s' % host)
+ if not anon_host:
+ anon_host = str(uuid.uuid1())
+ self.set_store('host-id/%s' % host, anon_host)
+ serial = None
+ for dev, rep in m.items():
+ rep['host_id'] = anon_host
+ if serial is None and 'serial_number' in rep:
+ serial = rep['serial_number']
+
+ # anonymize device id
+ anon_devid = self.get_store('devid-id/%s' % devid)
+ if not anon_devid:
+ # ideally devid is 'vendor_model_serial',
+ # but can also be 'model_serial', 'serial'
+ if '_' in devid:
+ anon_devid = devid[:devid.rfind('_')] + '_' + str(uuid.uuid1())
+ else:
+ anon_devid = str(uuid.uuid1())
+ self.set_store('devid-id/%s' % devid, anon_devid)
+ self.log.info('devid %s / %s, host %s / %s' % (devid, anon_devid,
+ host, anon_host))
+
+ # anonymize the smartctl report itself
+ if serial:
+ m_str = json.dumps(m)
+ m = json.loads(m_str.replace(serial, 'deleted'))
+
+ if anon_host not in res:
+ res[anon_host] = {}
+ res[anon_host][anon_devid] = m
+ return res
+
+ def get_latest(self, daemon_type, daemon_name, stat):
+ data = self.get_counter(daemon_type, daemon_name, stat)[stat]
+ #self.log.error("get_latest {0} data={1}".format(stat, data))
+ if data:
+ return data[-1][1]
+ else:
+ return 0
+
+ def compile_report(self, channels=[]):
+ if not channels:
+ channels = self.get_active_channels()
+ report = {
+ 'leaderboard': False,
+ 'report_version': 1,
+ 'report_timestamp': datetime.utcnow().isoformat(),
+ 'report_id': self.report_id,
+ 'channels': channels,
+ 'channels_available': ALL_CHANNELS,
+ 'license': LICENSE,
+ }
+
+ if 'ident' in channels:
+ if self.leaderboard:
+ report['leaderboard'] = True
+ for option in ['description', 'contact', 'organization']:
+ report[option] = getattr(self, option)
+
+ if 'basic' in channels:
+ mon_map = self.get('mon_map')
+ osd_map = self.get('osd_map')
+ service_map = self.get('service_map')
+ fs_map = self.get('fs_map')
+ df = self.get('df')
+
+ report['created'] = self.parse_timestamp(mon_map['created']).isoformat()
+
+ # mons
+ v1_mons = 0
+ v2_mons = 0
+ ipv4_mons = 0
+ ipv6_mons = 0
+ for mon in mon_map['mons']:
+ for a in mon['public_addrs']['addrvec']:
+ if a['type'] == 'v2':
+ v2_mons += 1
+ elif a['type'] == 'v1':
+ v1_mons += 1
+ if a['addr'].startswith('['):
+ ipv6_mons += 1
+ else:
+ ipv4_mons += 1
+ report['mon'] = {
+ 'count': len(mon_map['mons']),
+ 'features': mon_map['features'],
+ 'min_mon_release': mon_map['min_mon_release'],
+ 'v1_addr_mons': v1_mons,
+ 'v2_addr_mons': v2_mons,
+ 'ipv4_addr_mons': ipv4_mons,
+ 'ipv6_addr_mons': ipv6_mons,
+ }
+
+ report['config'] = self.gather_configs()
+
+ # pools
+ report['rbd'] = {
+ 'num_pools': 0,
+ 'num_images_by_pool': [],
+ 'mirroring_by_pool': [],
+ }
+ num_pg = 0
+ report['pools'] = list()
+ for pool in osd_map['pools']:
+ num_pg += pool['pg_num']
+ ec_profile = {}
+ if pool['erasure_code_profile']:
+ orig = osd_map['erasure_code_profiles'].get(
+ pool['erasure_code_profile'], {})
+ ec_profile = {
+ k: orig[k] for k in orig.keys()
+ if k in ['k', 'm', 'plugin', 'technique',
+ 'crush-failure-domain', 'l']
+ }
+ report['pools'].append(
+ {
+ 'pool': pool['pool'],
+ 'type': pool['type'],
+ 'pg_num': pool['pg_num'],
+ 'pgp_num': pool['pg_placement_num'],
+ 'size': pool['size'],
+ 'min_size': pool['min_size'],
+ 'pg_autoscale_mode': pool['pg_autoscale_mode'],
+ 'target_max_bytes': pool['target_max_bytes'],
+ 'target_max_objects': pool['target_max_objects'],
+ 'type': ['', 'replicated', '', 'erasure'][pool['type']],
+ 'erasure_code_profile': ec_profile,
+ 'cache_mode': pool['cache_mode'],
+ }
+ )
+ if 'rbd' in pool['application_metadata']:
+ report['rbd']['num_pools'] += 1
+ ioctx = self.rados.open_ioctx(pool['pool_name'])
+ report['rbd']['num_images_by_pool'].append(
+ sum(1 for _ in rbd.RBD().list2(ioctx)))
+ report['rbd']['mirroring_by_pool'].append(
+ rbd.RBD().mirror_mode_get(ioctx) != rbd.RBD_MIRROR_MODE_DISABLED)
+
+ # osds
+ cluster_network = False
+ for osd in osd_map['osds']:
+ if osd['up'] and not cluster_network:
+ front_ip = osd['public_addrs']['addrvec'][0]['addr'].split(':')[0]
+ back_ip = osd['cluster_addrs']['addrvec'][0]['addr'].split(':')[0]
+ if front_ip != back_ip:
+ cluster_network = True
+ report['osd'] = {
+ 'count': len(osd_map['osds']),
+ 'require_osd_release': osd_map['require_osd_release'],
+ 'require_min_compat_client': osd_map['require_min_compat_client'],
+ 'cluster_network': cluster_network,
+ }
+
+ # crush
+ report['crush'] = self.gather_crush_info()
+
+ # cephfs
+ report['fs'] = {
+ 'count': len(fs_map['filesystems']),
+ 'feature_flags': fs_map['feature_flags'],
+ 'num_standby_mds': len(fs_map['standbys']),
+ 'filesystems': [],
+ }
+ num_mds = len(fs_map['standbys'])
+ for fsm in fs_map['filesystems']:
+ fs = fsm['mdsmap']
+ num_sessions = 0
+ cached_ino = 0
+ cached_dn = 0
+ cached_cap = 0
+ subtrees = 0
+ rfiles = 0
+ rbytes = 0
+ rsnaps = 0
+ for gid, mds in fs['info'].items():
+ num_sessions += self.get_latest('mds', mds['name'],
+ 'mds_sessions.session_count')
+ cached_ino += self.get_latest('mds', mds['name'],
+ 'mds_mem.ino')
+ cached_dn += self.get_latest('mds', mds['name'],
+ 'mds_mem.dn')
+ cached_cap += self.get_latest('mds', mds['name'],
+ 'mds_mem.cap')
+ subtrees += self.get_latest('mds', mds['name'],
+ 'mds.subtrees')
+ if mds['rank'] == 0:
+ rfiles = self.get_latest('mds', mds['name'],
+ 'mds.root_rfiles')
+ rbytes = self.get_latest('mds', mds['name'],
+ 'mds.root_rbytes')
+ rsnaps = self.get_latest('mds', mds['name'],
+ 'mds.root_rsnaps')
+ report['fs']['filesystems'].append({
+ 'max_mds': fs['max_mds'],
+ 'ever_allowed_features': fs['ever_allowed_features'],
+ 'explicitly_allowed_features': fs['explicitly_allowed_features'],
+ 'num_in': len(fs['in']),
+ 'num_up': len(fs['up']),
+ 'num_standby_replay': len(
+ [mds for gid, mds in fs['info'].items()
+ if mds['state'] == 'up:standby-replay']),
+ 'num_mds': len(fs['info']),
+ 'num_sessions': num_sessions,
+ 'cached_inos': cached_ino,
+ 'cached_dns': cached_dn,
+ 'cached_caps': cached_cap,
+ 'cached_subtrees': subtrees,
+ 'balancer_enabled': len(fs['balancer']) > 0,
+ 'num_data_pools': len(fs['data_pools']),
+ 'standby_count_wanted': fs['standby_count_wanted'],
+ 'approx_ctime': fs['created'][0:7],
+ 'files': rfiles,
+ 'bytes': rbytes,
+ 'snaps': rsnaps,
+ })
+ num_mds += len(fs['info'])
+ report['fs']['total_num_mds'] = num_mds
+
+ # daemons
+ report['metadata'] = dict()
+ report['metadata']['osd'] = self.gather_osd_metadata(osd_map)
+ report['metadata']['mon'] = self.gather_mon_metadata(mon_map)
+
+ # host counts
+ servers = self.list_servers()
+ self.log.debug('servers %s' % servers)
+ report['hosts'] = {
+ 'num': len([h for h in servers if h['hostname']]),
+ }
+ for t in ['mon', 'mds', 'osd', 'mgr']:
+ report['hosts']['num_with_' + t] = len(
+ [h for h in servers
+ if len([s for s in h['services'] if s['type'] == t])]
+ )
+
+ report['usage'] = {
+ 'pools': len(df['pools']),
+ 'pg_num': num_pg,
+ 'total_used_bytes': df['stats']['total_used_bytes'],
+ 'total_bytes': df['stats']['total_bytes'],
+ 'total_avail_bytes': df['stats']['total_avail_bytes']
+ }
+
+ report['services'] = defaultdict(int)
+ for key, value in service_map['services'].items():
+ report['services'][key] += 1
+ if key == 'rgw':
+ report['rgw'] = {
+ 'count': 0,
+ }
+ zones = set()
+ realms = set()
+ zonegroups = set()
+ frontends = set()
+ d = value.get('daemons', dict())
+
+ for k,v in d.items():
+ if k == 'summary' and v:
+ report['rgw'][k] = v
+ elif isinstance(v, dict) and 'metadata' in v:
+ report['rgw']['count'] += 1
+ zones.add(v['metadata']['zone_id'])
+ zonegroups.add(v['metadata']['zonegroup_id'])
+ frontends.add(v['metadata']['frontend_type#0'])
+
+ # we could actually iterate over all the keys of
+ # the dict and check for how many frontends there
+ # are, but it is unlikely that one would be running
+ # more than 2 supported ones
+ f2 = v['metadata'].get('frontend_type#1', None)
+ if f2:
+ frontends.add(f2)
+
+ report['rgw']['zones'] = len(zones)
+ report['rgw']['zonegroups'] = len(zonegroups)
+ report['rgw']['frontends'] = list(frontends) # sets aren't json-serializable
+
+ try:
+ report['balancer'] = self.remote('balancer', 'gather_telemetry')
+ except ImportError:
+ report['balancer'] = {
+ 'active': False
+ }
+
+ if 'crash' in channels:
+ report['crashes'] = self.gather_crashinfo()
+
+ # NOTE: We do not include the 'device' channel in this report; it is
+ # sent to a different endpoint.
+
+ return report
+
+ def _try_post(self, what, url, report):
+ self.log.info('Sending %s to: %s' % (what, url))
+ proxies = dict()
+ if self.proxy:
+ self.log.info('Send using HTTP(S) proxy: %s', self.proxy)
+ proxies['http'] = self.proxy
+ proxies['https'] = self.proxy
+ try:
+ resp = requests.put(url=url, json=report, proxies=proxies)
+ resp.raise_for_status()
+ except Exception as e:
+ fail_reason = 'Failed to send %s to %s: %s' % (what, url, str(e))
+ self.log.error(fail_reason)
+ return fail_reason
+ return None
+
+ def send(self, report, endpoint=None):
+ if not endpoint:
+ endpoint = ['ceph', 'device']
+ failed = []
+ success = []
+ self.log.debug('Send endpoints %s' % endpoint)
+ for e in endpoint:
+ if e == 'ceph':
+ fail_reason = self._try_post('ceph report', self.url, report)
+ if fail_reason:
+ failed.append(fail_reason)
+ else:
+ now = int(time.time())
+ self.last_upload = now
+ self.set_store('last_upload', str(now))
+ success.append('Ceph report sent to {0}'.format(self.url))
+ self.log.info('Sent report to {0}'.format(self.url))
+ elif e == 'device':
+ if 'device' in self.get_active_channels():
+ devices = self.gather_device_report()
+ num_devs = 0
+ num_hosts = 0
+ for host, ls in devices.items():
+ self.log.debug('host %s devices %s' % (host, ls))
+ if not len(ls):
+ continue
+ fail_reason = self._try_post('devices', self.device_url,
+ ls)
+ if fail_reason:
+ failed.append(fail_reason)
+ else:
+ num_devs += len(ls)
+ num_hosts += 1
+ if num_devs:
+ success.append('Reported %d devices across %d hosts' % (
+ num_devs, len(devices)))
+ if failed:
+ return 1, '', '\n'.join(success + failed)
+ return 0, '', '\n'.join(success)
+
+ def handle_command(self, inbuf, command):
+ if command['prefix'] == 'telemetry status':
+ r = {}
+ for opt in self.MODULE_OPTIONS:
+ r[opt['name']] = getattr(self, opt['name'])
+ r['last_upload'] = time.ctime(self.last_upload) if self.last_upload else self.last_upload
+ return 0, json.dumps(r, indent=4), ''
+ elif command['prefix'] == 'telemetry on':
+ if command.get('license') != LICENSE:
+ return -errno.EPERM, '', "Telemetry data is licensed under the " + LICENSE_NAME + " (" + LICENSE_URL + ").\nTo enable, add '--license " + LICENSE + "' to the 'ceph telemetry on' command."
+ self.set_module_option('enabled', True)
+ self.set_module_option('last_opt_revision', REVISION)
+ return 0, '', ''
+ elif command['prefix'] == 'telemetry off':
+ self.set_module_option('enabled', False)
+ self.set_module_option('last_opt_revision', 1)
+ return 0, '', ''
+ elif command['prefix'] == 'telemetry send':
+ if self.last_opt_revision < LAST_REVISION_RE_OPT_IN and command.get('license') != LICENSE:
+ self.log.debug('A telemetry send attempt while opted-out. Asking for license agreement')
+ return -errno.EPERM, '', "Telemetry data is licensed under the " + LICENSE_NAME + " (" + LICENSE_URL + ").\nTo manually send telemetry data, add '--license " + LICENSE + "' to the 'ceph telemetry send' command.\nPlease consider enabling the telemetry module with 'ceph telemetry on'."
+ self.last_report = self.compile_report()
+ return self.send(self.last_report, command.get('endpoint'))
+
+ elif command['prefix'] == 'telemetry show':
+ report = self.compile_report(
+ channels=command.get('channels', None)
+ )
+ report = json.dumps(report, indent=4)
+ if self.channel_device:
+ report += '\n \nDevice report is generated separately. To see it run \'ceph telemetry show-device\'.'
+ return 0, report, ''
+ elif command['prefix'] == 'telemetry show-device':
+ return 0, json.dumps(self.gather_device_report(), indent=4, sort_keys=True), ''
+ else:
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(command['prefix']))
+
+ def self_test(self):
+ report = self.compile_report()
+ if len(report) == 0:
+ raise RuntimeError('Report is empty')
+
+ if 'report_id' not in report:
+ raise RuntimeError('report_id not found in report')
+
+ def shutdown(self):
+ self.run = False
+ self.event.set()
+
+ def refresh_health_checks(self):
+ health_checks = {}
+ if self.enabled and self.last_opt_revision < LAST_REVISION_RE_OPT_IN:
+ health_checks['TELEMETRY_CHANGED'] = {
+ 'severity': 'warning',
+ 'summary': 'Telemetry requires re-opt-in',
+ 'detail': [
+ 'telemetry report includes new information; must re-opt-in (or out)'
+ ]
+ }
+ self.set_health_checks(health_checks)
+
+ def serve(self):
+ self.load()
+ self.config_notify()
+ self.run = True
+
+ self.log.debug('Waiting for mgr to warm up')
+ self.event.wait(10)
+
+ while self.run:
+ self.event.clear()
+
+ self.refresh_health_checks()
+
+ if self.last_opt_revision < LAST_REVISION_RE_OPT_IN:
+ self.log.debug('Not sending report until user re-opts-in')
+ self.event.wait(1800)
+ continue
+ if not self.enabled:
+ self.log.debug('Not sending report until configured to do so')
+ self.event.wait(1800)
+ continue
+
+ now = int(time.time())
+ if not self.last_upload or (now - self.last_upload) > \
+ self.interval * 3600:
+ self.log.info('Compiling and sending report to %s',
+ self.url)
+
+ try:
+ self.last_report = self.compile_report()
+ except:
+ self.log.exception('Exception while compiling report:')
+
+ self.send(self.last_report)
+ else:
+ self.log.debug('Interval for sending new report has not expired')
+
+ sleep = 3600
+ self.log.debug('Sleeping for %d seconds', sleep)
+ self.event.wait(sleep)
+
+ def self_test(self):
+ self.compile_report()
+ return True
+
+ @staticmethod
+ def can_run():
+ return True, ''
diff --git a/src/pybind/mgr/test_orchestrator/__init__.py b/src/pybind/mgr/test_orchestrator/__init__.py
new file mode 100644
index 00000000..2c4d3097
--- /dev/null
+++ b/src/pybind/mgr/test_orchestrator/__init__.py
@@ -0,0 +1 @@
+from .module import TestOrchestrator
diff --git a/src/pybind/mgr/test_orchestrator/module.py b/src/pybind/mgr/test_orchestrator/module.py
new file mode 100644
index 00000000..0112ba4c
--- /dev/null
+++ b/src/pybind/mgr/test_orchestrator/module.py
@@ -0,0 +1,259 @@
+import json
+import re
+import os
+import threading
+import functools
+import uuid
+from subprocess import check_output, CalledProcessError
+
+from mgr_module import MgrModule, PersistentStoreDict
+
+import orchestrator
+
+
+
+
+class TestCompletionMixin(object):
+ all_completions = [] # Hacky global
+
+ def __init__(self, cb, message, *args, **kwargs):
+ super(TestCompletionMixin, self).__init__(*args, **kwargs)
+ self.cb = cb
+ self._result = None
+ self._complete = False
+
+ self.message = message
+ self.id = str(uuid.uuid4())
+
+ TestCompletionMixin.all_completions.append(self)
+
+ @property
+ def result(self):
+ return self._result
+
+ @property
+ def is_complete(self):
+ return self._complete
+
+ def execute(self):
+ self._result = self.cb()
+ self.executed = True
+ self._complete = True
+
+ def __str__(self):
+ return "{}(result={} message={}, exception={})".format(self.__class__.__name__, self.result,
+ self.message, self.exception)
+
+
+class TestReadCompletion(TestCompletionMixin, orchestrator.ReadCompletion):
+ def __init__(self, cb):
+ super(TestReadCompletion, self).__init__(cb, "<read op>")
+
+
+class TestWriteCompletion(TestCompletionMixin, orchestrator.WriteCompletion):
+ def __init__(self, cb, message):
+ super(TestWriteCompletion, self).__init__(cb, message)
+
+ @property
+ def is_persistent(self):
+ return (not self.is_errored) and self.executed
+
+ @property
+ def is_effective(self):
+ return self._complete
+
+
+def deferred_write(message):
+ def wrapper(f):
+ @functools.wraps(f)
+ def inner(*args, **kwargs):
+ return TestWriteCompletion(lambda: f(*args, **kwargs),
+ '{}, args={}, kwargs={}'.format(message, args, kwargs))
+ return inner
+ return wrapper
+
+
+def deferred_read(f):
+ """
+ Decorator to make TestOrchestrator methods return
+ a completion object that executes themselves.
+ """
+
+ @functools.wraps(f)
+ def wrapper(*args, **kwargs):
+ return TestReadCompletion(lambda: f(*args, **kwargs))
+
+ return wrapper
+
+
+class TestOrchestrator(MgrModule, orchestrator.Orchestrator):
+ """
+ This is an orchestrator implementation used for internal testing. It's meant for
+ development environments and integration testing.
+
+ It does not actually do anything.
+
+ The implementation is similar to the Rook orchestrator, but simpler.
+ """
+
+ def wait(self, completions):
+ self.log.info("wait: completions={0}".format(completions))
+
+ # Our `wait` implementation is very simple because everything's
+ # just an API call.
+ for c in completions:
+ if not isinstance(c, TestReadCompletion) and \
+ not isinstance(c, TestWriteCompletion):
+ raise TypeError(
+ "wait() requires list of completions, not {0}".format(
+ c.__class__
+ ))
+
+ if c.is_complete:
+ continue
+
+ try:
+ c.execute()
+ except Exception as e:
+ self.log.exception("Completion {0} threw an exception:".format(
+ c.message
+ ))
+ c.exception = e
+ c._complete = True
+
+ return all(c.is_complete for c in completions)
+
+ def available(self):
+ return True, ""
+
+ def __init__(self, *args, **kwargs):
+ super(TestOrchestrator, self).__init__(*args, **kwargs)
+
+ self._initialized = threading.Event()
+ self._shutdown = threading.Event()
+
+ def shutdown(self):
+ self._shutdown.set()
+
+ def serve(self):
+
+ self._initialized.set()
+
+ while not self._shutdown.is_set():
+ # XXX hack (or is it?) to kick all completions periodically,
+ # in case we had a caller that wait()'ed on them long enough
+ # to get persistence but not long enough to get completion
+
+ self.wait(TestCompletionMixin.all_completions)
+ TestCompletionMixin.all_completions = [c for c in TestCompletionMixin.all_completions if
+ not c.is_complete]
+
+ self._shutdown.wait(5)
+
+ @deferred_read
+ def get_inventory(self, node_filter=None, refresh=False):
+ """
+ There is no guarantee which devices are returned by get_inventory.
+ """
+ if node_filter and node_filter.nodes is not None:
+ assert isinstance(node_filter.nodes, list)
+ try:
+ c_v_out = check_output(['ceph-volume', 'inventory', '--format', 'json'])
+ except OSError:
+ cmd = """
+ . {tmpdir}/ceph-volume-virtualenv/bin/activate
+ ceph-volume inventory --format json
+ """
+ try:
+ c_v_out = check_output(cmd.format(tmpdir=os.environ.get('TMPDIR', '/tmp')), shell=True)
+ except (OSError, CalledProcessError):
+ c_v_out = check_output(cmd.format(tmpdir='.'),shell=True)
+
+ for out in c_v_out.splitlines():
+ self.log.error(out)
+ devs = []
+ for device in json.loads(out):
+ dev = orchestrator.InventoryDevice.from_ceph_volume_inventory(device)
+ devs.append(dev)
+ return [orchestrator.InventoryNode('localhost', devs)]
+ self.log.error('c-v failed: ' + str(c_v_out))
+ raise Exception('c-v failed')
+
+ @deferred_read
+ def describe_service(self, service_type=None, service_id=None, node_name=None, refresh=False):
+ """
+ There is no guarantee which daemons are returned by describe_service, except that
+ it returns the mgr we're running in.
+ """
+ if service_type:
+ assert service_type in ("mds", "osd", "mon", "rgw", "mgr"), service_type + " unsupported"
+
+ out = map(str, check_output(['ps', 'aux']).splitlines())
+ types = [service_type] if service_type else ("mds", "osd", "mon", "rgw", "mgr")
+ processes = [p for p in out if any([('ceph-' + t in p) for t in types])]
+
+ result = []
+ for p in processes:
+ sd = orchestrator.ServiceDescription()
+ sd.nodename = 'localhost'
+ sd.service_instance = re.search('ceph-[^ ]+', p).group()
+ result.append(sd)
+
+ return result
+
+ @deferred_write("Adding stateless service")
+ def add_stateless_service(self, service_type, spec):
+ pass
+
+ @deferred_write("create_osds")
+ def create_osds(self, drive_group, all_hosts):
+ drive_group.validate(all_hosts)
+
+ @deferred_write("remove_osds")
+ def remove_osds(self, osd_ids):
+ assert isinstance(osd_ids, list)
+
+ @deferred_write("service_action")
+ def service_action(self, action, service_type, service_name=None, service_id=None):
+ pass
+
+ @deferred_write("remove_stateless_service")
+ def remove_stateless_service(self, service_type, id_):
+ pass
+
+ @deferred_write("update_stateless_service")
+ def update_stateless_service(self, service_type, spec):
+ pass
+
+ @deferred_read
+ def get_hosts(self):
+ return [orchestrator.InventoryNode('localhost', [])]
+
+ @deferred_write("add_host")
+ def add_host(self, host):
+ if host == 'raise_no_support':
+ raise orchestrator.OrchestratorValidationError("MON count must be either 1, 3 or 5")
+ if host == 'raise_bug':
+ raise ZeroDivisionError()
+ if host == 'raise_not_implemented':
+ raise NotImplementedError()
+ if host == 'raise_no_orchestrator':
+ raise orchestrator.NoOrchestrator()
+ if host == 'raise_import_error':
+ raise ImportError("test_orchestrator not enabled")
+ assert isinstance(host, str)
+
+ @deferred_write("remove_host")
+ def remove_host(self, host):
+ assert isinstance(host, str)
+
+ @deferred_write("update_mgrs")
+ def update_mgrs(self, num, hosts):
+ assert not hosts or len(hosts) == num
+ assert all([isinstance(h, str) for h in hosts])
+
+ @deferred_write("update_mons")
+ def update_mons(self, num, hosts):
+ assert not hosts or len(hosts) == num
+ assert all([isinstance(h[0], str) for h in hosts])
+ assert all([isinstance(h[1], str) or h[1] is None for h in hosts])
diff --git a/src/pybind/mgr/volumes/__init__.py b/src/pybind/mgr/volumes/__init__.py
new file mode 100644
index 00000000..4c5b97ce
--- /dev/null
+++ b/src/pybind/mgr/volumes/__init__.py
@@ -0,0 +1,2 @@
+
+from .module import Module
diff --git a/src/pybind/mgr/volumes/fs/__init__.py b/src/pybind/mgr/volumes/fs/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/__init__.py
diff --git a/src/pybind/mgr/volumes/fs/async_cloner.py b/src/pybind/mgr/volumes/fs/async_cloner.py
new file mode 100644
index 00000000..0c5155e7
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/async_cloner.py
@@ -0,0 +1,345 @@
+import os
+import stat
+import time
+import errno
+import logging
+from contextlib import contextmanager
+
+import cephfs
+
+from .async_job import AsyncJobs
+from .exception import IndexException, MetadataMgrException, OpSmException, VolumeException
+from .fs_util import copy_file
+from .operations.versions.op_sm import SubvolumeOpSm
+from .operations.versions.subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeActions
+from .operations.resolver import resolve
+from .operations.volume import open_volume, open_volume_lockless
+from .operations.group import open_group
+from .operations.subvolume import open_subvol
+from .operations.clone_index import open_clone_index
+from .operations.template import SubvolumeOpType
+
+log = logging.getLogger(__name__)
+
+# helper for fetching a clone entry for a given volume
+def get_next_clone_entry(volume_client, volname, running_jobs):
+ log.debug("fetching clone entry for volume '{0}'".format(volname))
+
+ try:
+ with open_volume_lockless(volume_client, volname) as fs_handle:
+ try:
+ with open_clone_index(fs_handle, volume_client.volspec) as clone_index:
+ job = clone_index.get_oldest_clone_entry(running_jobs)
+ return 0, job
+ except IndexException as ve:
+ if ve.errno == -errno.ENOENT:
+ return 0, None
+ raise ve
+ except VolumeException as ve:
+ log.error("error fetching clone entry for volume '{0}' ({1})".format(volname, ve))
+ return ve.errno, None
+
+@contextmanager
+def open_at_volume(volume_client, volname, groupname, subvolname, op_type):
+ with open_volume(volume_client, volname) as fs_handle:
+ with open_group(fs_handle, volume_client.volspec, groupname) as group:
+ with open_subvol(volume_client.mgr, fs_handle, volume_client.volspec, group, subvolname, op_type) as subvolume:
+ yield subvolume
+
+@contextmanager
+def open_at_group(volume_client, fs_handle, groupname, subvolname, op_type):
+ with open_group(fs_handle, volume_client.volspec, groupname) as group:
+ with open_subvol(volume_client.mgr, fs_handle, volume_client.volspec, group, subvolname, op_type) as subvolume:
+ yield subvolume
+
+@contextmanager
+def open_at_group_unique(volume_client, fs_handle, s_groupname, s_subvolname, c_subvolume, c_groupname, c_subvolname, op_type):
+ # if a snapshot of a retained subvolume is being cloned to recreate the same subvolume, return
+ # the clone subvolume as the source subvolume
+ if s_groupname == c_groupname and s_subvolname == c_subvolname:
+ yield c_subvolume
+ else:
+ with open_at_group(volume_client, fs_handle, s_groupname, s_subvolname, op_type) as s_subvolume:
+ yield s_subvolume
+
+
+@contextmanager
+def open_clone_subvolume_pair(volume_client, fs_handle, volname, groupname, subvolname):
+ with open_at_group(volume_client, fs_handle, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as clone_subvolume:
+ s_volname, s_groupname, s_subvolname, s_snapname = get_clone_source(clone_subvolume)
+ if groupname == s_groupname and subvolname == s_subvolname:
+ # use the same subvolume to avoid metadata overwrites
+ yield (clone_subvolume, clone_subvolume, s_snapname)
+ else:
+ with open_at_group(volume_client, fs_handle, s_groupname, s_subvolname, SubvolumeOpType.CLONE_SOURCE) as source_subvolume:
+ yield (clone_subvolume, source_subvolume, s_snapname)
+
+def get_clone_state(volume_client, volname, groupname, subvolname):
+ with open_at_volume(volume_client, volname, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as subvolume:
+ return subvolume.state
+
+def set_clone_state(volume_client, volname, groupname, subvolname, state):
+ with open_at_volume(volume_client, volname, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as subvolume:
+ subvolume.state = (state, True)
+
+def get_clone_source(clone_subvolume):
+ source = clone_subvolume._get_clone_source()
+ return (source['volume'], source.get('group', None), source['subvolume'], source['snapshot'])
+
+def get_next_state_on_error(errnum):
+ if errnum == -errno.EINTR:
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_CANCELLED)
+ else:
+ # jump to failed state, on all other errors
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_FAILED)
+ return next_state
+
+def handle_clone_pending(volume_client, volname, index, groupname, subvolname, should_cancel):
+ try:
+ if should_cancel():
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_PENDING,
+ SubvolumeActions.ACTION_CANCELLED)
+ else:
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_PENDING,
+ SubvolumeActions.ACTION_SUCCESS)
+ except OpSmException as oe:
+ raise VolumeException(oe.errno, oe.error_str)
+ return (next_state, False)
+
+def sync_attrs(fs_handle, target_path, source_statx):
+ try:
+ fs_handle.lchown(target_path, int(source_statx["uid"]), int(source_statx["gid"]))
+ fs_handle.lutimes(target_path, (time.mktime(source_statx["atime"].timetuple()),
+ time.mktime(source_statx["mtime"].timetuple())))
+ except cephfs.Error as e:
+ log.warn("error synchronizing attrs for {0} ({1})".format(target_path, e))
+ raise e
+
+def bulk_copy(fs_handle, source_path, dst_path, should_cancel):
+ """
+ bulk copy data from source to destination -- only directories, symlinks
+ and regular files are synced.
+ """
+ log.info("copying data from {0} to {1}".format(source_path, dst_path))
+ def cptree(src_root_path, dst_root_path):
+ log.debug("cptree: {0} -> {1}".format(src_root_path, dst_root_path))
+ try:
+ with fs_handle.opendir(src_root_path) as dir_handle:
+ d = fs_handle.readdir(dir_handle)
+ while d and not should_cancel():
+ if d.d_name not in (b".", b".."):
+ log.debug("d={0}".format(d))
+ d_full_src = os.path.join(src_root_path, d.d_name)
+ d_full_dst = os.path.join(dst_root_path, d.d_name)
+ stx = fs_handle.statx(d_full_src, cephfs.CEPH_STATX_MODE |
+ cephfs.CEPH_STATX_UID |
+ cephfs.CEPH_STATX_GID |
+ cephfs.CEPH_STATX_ATIME |
+ cephfs.CEPH_STATX_MTIME |
+ cephfs.CEPH_STATX_SIZE,
+ cephfs.AT_SYMLINK_NOFOLLOW)
+ handled = True
+ mo = stx["mode"] & ~stat.S_IFMT(stx["mode"])
+ if stat.S_ISDIR(stx["mode"]):
+ log.debug("cptree: (DIR) {0}".format(d_full_src))
+ try:
+ fs_handle.mkdir(d_full_dst, mo)
+ except cephfs.Error as e:
+ if not e.args[0] == errno.EEXIST:
+ raise
+ cptree(d_full_src, d_full_dst)
+ elif stat.S_ISLNK(stx["mode"]):
+ log.debug("cptree: (SYMLINK) {0}".format(d_full_src))
+ target = fs_handle.readlink(d_full_src, 4096)
+ try:
+ fs_handle.symlink(target[:stx["size"]], d_full_dst)
+ except cephfs.Error as e:
+ if not e.args[0] == errno.EEXIST:
+ raise
+ elif stat.S_ISREG(stx["mode"]):
+ log.debug("cptree: (REG) {0}".format(d_full_src))
+ copy_file(fs_handle, d_full_src, d_full_dst, mo, cancel_check=should_cancel)
+ else:
+ handled = False
+ log.warn("cptree: (IGNORE) {0}".format(d_full_src))
+ if handled:
+ sync_attrs(fs_handle, d_full_dst, stx)
+ d = fs_handle.readdir(dir_handle)
+ stx_root = fs_handle.statx(src_root_path, cephfs.CEPH_STATX_ATIME |
+ cephfs.CEPH_STATX_MTIME,
+ cephfs.AT_SYMLINK_NOFOLLOW)
+ fs_handle.lutimes(dst_root_path, (time.mktime(stx_root["atime"].timetuple()),
+ time.mktime(stx_root["mtime"].timetuple())))
+ except cephfs.Error as e:
+ if not e.args[0] == errno.ENOENT:
+ raise VolumeException(-e.args[0], e.args[1])
+ cptree(source_path, dst_path)
+ if should_cancel():
+ raise VolumeException(-errno.EINTR, "clone operation interrupted")
+
+def do_clone(volume_client, volname, groupname, subvolname, should_cancel):
+ with open_volume_lockless(volume_client, volname) as fs_handle:
+ with open_clone_subvolume_pair(volume_client, fs_handle, volname, groupname, subvolname) as clone_volumes:
+ src_path = clone_volumes[1].snapshot_data_path(clone_volumes[2])
+ dst_path = clone_volumes[0].path
+ bulk_copy(fs_handle, src_path, dst_path, should_cancel)
+
+def handle_clone_in_progress(volume_client, volname, index, groupname, subvolname, should_cancel):
+ try:
+ do_clone(volume_client, volname, groupname, subvolname, should_cancel)
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_SUCCESS)
+ except VolumeException as ve:
+ next_state = get_next_state_on_error(ve.errno)
+ except OpSmException as oe:
+ raise VolumeException(oe.errno, oe.error_str)
+ return (next_state, False)
+
+def handle_clone_failed(volume_client, volname, index, groupname, subvolname, should_cancel):
+ try:
+ with open_volume(volume_client, volname) as fs_handle:
+ # detach source but leave the clone section intact for later inspection
+ with open_clone_subvolume_pair(volume_client, fs_handle, volname, groupname, subvolname) as clone_volumes:
+ clone_volumes[1].detach_snapshot(clone_volumes[2], index)
+ except (MetadataMgrException, VolumeException) as e:
+ log.error("failed to detach clone from snapshot: {0}".format(e))
+ return (None, True)
+
+def handle_clone_complete(volume_client, volname, index, groupname, subvolname, should_cancel):
+ try:
+ with open_volume(volume_client, volname) as fs_handle:
+ with open_clone_subvolume_pair(volume_client, fs_handle, volname, groupname, subvolname) as clone_volumes:
+ clone_volumes[1].detach_snapshot(clone_volumes[2], index)
+ clone_volumes[0].remove_clone_source(flush=True)
+ except (MetadataMgrException, VolumeException) as e:
+ log.error("failed to detach clone from snapshot: {0}".format(e))
+ return (None, True)
+
+def start_clone_sm(volume_client, volname, index, groupname, subvolname, state_table, should_cancel):
+ finished = False
+ current_state = None
+ try:
+ current_state = get_clone_state(volume_client, volname, groupname, subvolname)
+ log.debug("cloning ({0}, {1}, {2}) -- starting state \"{3}\"".format(volname, groupname, subvolname, current_state))
+ while not finished:
+ handler = state_table.get(current_state, None)
+ if not handler:
+ raise VolumeException(-errno.EINVAL, "invalid clone state: \"{0}\"".format(current_state))
+ (next_state, finished) = handler(volume_client, volname, index, groupname, subvolname, should_cancel)
+ if next_state:
+ log.debug("({0}, {1}, {2}) transition state [\"{3}\" => \"{4}\"]".format(volname, groupname, subvolname,\
+ current_state, next_state))
+ set_clone_state(volume_client, volname, groupname, subvolname, next_state)
+ current_state = next_state
+ except VolumeException as ve:
+ log.error("clone failed for ({0}, {1}, {2}) (current_state: {3}, reason: {4})".format(volname, groupname,\
+ subvolname, current_state, ve))
+
+def clone(volume_client, volname, index, clone_path, state_table, should_cancel):
+ log.info("cloning to subvolume path: {0}".format(clone_path))
+ resolved = resolve(volume_client.volspec, clone_path)
+
+ groupname = resolved[0]
+ subvolname = resolved[1]
+ log.debug("resolved to [group: {0}, subvolume: {1}]".format(groupname, subvolname))
+
+ try:
+ log.info("starting clone: ({0}, {1}, {2})".format(volname, groupname, subvolname))
+ start_clone_sm(volume_client, volname, index, groupname, subvolname, state_table, should_cancel)
+ log.info("finished clone: ({0}, {1}, {2})".format(volname, groupname, subvolname))
+ except VolumeException as ve:
+ log.error("clone failed for ({0}, {1}, {2}), reason: {3}".format(volname, groupname, subvolname, ve))
+
+class Cloner(AsyncJobs):
+ """
+ Asynchronous cloner: pool of threads to copy data from a snapshot to a subvolume.
+ this relies on a simple state machine (which mimics states from SubvolumeOpSm class) as
+ the driver. file types supported are directories, symbolic links and regular files.
+ """
+ def __init__(self, volume_client, tp_size):
+ self.vc = volume_client
+ self.state_table = {
+ SubvolumeStates.STATE_PENDING : handle_clone_pending,
+ SubvolumeStates.STATE_INPROGRESS : handle_clone_in_progress,
+ SubvolumeStates.STATE_COMPLETE : handle_clone_complete,
+ SubvolumeStates.STATE_FAILED : handle_clone_failed,
+ SubvolumeStates.STATE_CANCELED : handle_clone_failed,
+ }
+ super(Cloner, self).__init__(volume_client, "cloner", tp_size)
+
+ def reconfigure_max_concurrent_clones(self, tp_size):
+ super(Cloner, self).reconfigure_max_concurrent_clones("cloner", tp_size)
+
+ def is_clone_cancelable(self, clone_state):
+ return not (SubvolumeOpSm.is_complete_state(clone_state) or SubvolumeOpSm.is_failed_state(clone_state))
+
+ def get_clone_tracking_index(self, fs_handle, clone_subvolume):
+ with open_clone_index(fs_handle, self.vc.volspec) as index:
+ return index.find_clone_entry_index(clone_subvolume.base_path)
+
+ def _cancel_pending_clone(self, fs_handle, clone_subvolume, clone_subvolname, clone_groupname, status, track_idx):
+ clone_state = SubvolumeStates.from_value(status['state'])
+ assert self.is_clone_cancelable(clone_state)
+
+ s_groupname = status['source'].get('group', None)
+ s_subvolname = status['source']['subvolume']
+ s_snapname = status['source']['snapshot']
+
+ with open_at_group_unique(self.vc, fs_handle, s_groupname, s_subvolname, clone_subvolume, clone_groupname,
+ clone_subvolname, SubvolumeOpType.CLONE_SOURCE) as s_subvolume:
+ next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
+ clone_state,
+ SubvolumeActions.ACTION_CANCELLED)
+ clone_subvolume.state = (next_state, True)
+ s_subvolume.detach_snapshot(s_snapname, track_idx.decode('utf-8'))
+
+ def cancel_job(self, volname, job):
+ """
+ override base class `cancel_job`. interpret @job as (clone, group) tuple.
+ """
+ clonename = job[0]
+ groupname = job[1]
+ track_idx = None
+
+ try:
+ with open_volume(self.vc, volname) as fs_handle:
+ with open_group(fs_handle, self.vc.volspec, groupname) as group:
+ with open_subvol(self.vc.mgr, fs_handle, self.vc.volspec, group, clonename, SubvolumeOpType.CLONE_CANCEL) as clone_subvolume:
+ status = clone_subvolume.status
+ clone_state = SubvolumeStates.from_value(status['state'])
+ if not self.is_clone_cancelable(clone_state):
+ raise VolumeException(-errno.EINVAL, "cannot cancel -- clone finished (check clone status)")
+ track_idx = self.get_clone_tracking_index(fs_handle, clone_subvolume)
+ if not track_idx:
+ log.warn("cannot lookup clone tracking index for {0}".format(clone_subvolume.base_path))
+ raise VolumeException(-errno.EINVAL, "error canceling clone")
+ if SubvolumeOpSm.is_init_state(SubvolumeTypes.TYPE_CLONE, clone_state):
+ # clone has not started yet -- cancel right away.
+ self._cancel_pending_clone(fs_handle, clone_subvolume, clonename, groupname, status, track_idx)
+ return
+ # cancelling an on-going clone would persist "canceled" state in subvolume metadata.
+ # to persist the new state, async cloner accesses the volume in exclusive mode.
+ # accessing the volume in exclusive mode here would lead to deadlock.
+ assert track_idx is not None
+ with self.lock:
+ with open_volume_lockless(self.vc, volname) as fs_handle:
+ with open_group(fs_handle, self.vc.volspec, groupname) as group:
+ with open_subvol(self.vc.mgr, fs_handle, self.vc.volspec, group, clonename, SubvolumeOpType.CLONE_CANCEL) as clone_subvolume:
+ if not self._cancel_job(volname, (track_idx, clone_subvolume.base_path)):
+ raise VolumeException(-errno.EINVAL, "cannot cancel -- clone finished (check clone status)")
+ except (IndexException, MetadataMgrException) as e:
+ log.error("error cancelling clone {0}: ({1})".format(job, e))
+ raise VolumeException(-errno.EINVAL, "error canceling clone")
+
+ def get_next_job(self, volname, running_jobs):
+ return get_next_clone_entry(self.vc, volname, running_jobs)
+
+ def execute_job(self, volname, job, should_cancel):
+ clone(self.vc, volname, job[0].decode('utf-8'), job[1].decode('utf-8'), self.state_table, should_cancel)
diff --git a/src/pybind/mgr/volumes/fs/async_job.py b/src/pybind/mgr/volumes/fs/async_job.py
new file mode 100644
index 00000000..954e89c4
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/async_job.py
@@ -0,0 +1,279 @@
+import sys
+import time
+import logging
+import threading
+import traceback
+from collections import deque
+
+from .exception import NotImplementedException
+
+log = logging.getLogger(__name__)
+
+class JobThread(threading.Thread):
+ # this is "not" configurable and there is no need for it to be
+ # configurable. if a thread encounters an exception, we retry
+ # until it hits this many consecutive exceptions.
+ MAX_RETRIES_ON_EXCEPTION = 10
+
+ def __init__(self, async_job, volume_client, name):
+ self.vc = volume_client
+ self.async_job = async_job
+ # event object to cancel jobs
+ self.cancel_event = threading.Event()
+ threading.Thread.__init__(self, name=name)
+
+ def run(self):
+ retries = 0
+ thread_id = threading.currentThread()
+ assert isinstance(thread_id, JobThread)
+ thread_name = thread_id.getName()
+ log.debug("thread [{0}] starting".format(thread_name))
+
+ while retries < JobThread.MAX_RETRIES_ON_EXCEPTION:
+ vol_job = None
+ try:
+ # fetch next job to execute
+ with self.async_job.lock:
+ while True:
+ if self.should_reconfigure_num_threads():
+ log.info("thread [{0}] terminating due to reconfigure".format(thread_name))
+ self.async_job.threads.remove(self)
+ return
+ vol_job = self.async_job.get_job()
+ if vol_job:
+ break
+ self.async_job.cv.wait()
+ self.async_job.register_async_job(vol_job[0], vol_job[1], thread_id)
+
+ # execute the job (outside lock)
+ self.async_job.execute_job(vol_job[0], vol_job[1], should_cancel=lambda: thread_id.should_cancel())
+ retries = 0
+ except NotImplementedException:
+ raise
+ except Exception:
+ # unless the jobs fetching and execution routines are not implemented
+ # retry till we hit cap limit.
+ retries += 1
+ log.warning("thread [{0}] encountered fatal error: (attempt#" \
+ " {1}/{2})".format(thread_name, retries, JobThread.MAX_RETRIES_ON_EXCEPTION))
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ log.warning("traceback: {0}".format("".join(
+ traceback.format_exception(exc_type, exc_value, exc_traceback))))
+ finally:
+ # when done, unregister the job
+ if vol_job:
+ with self.async_job.lock:
+ self.async_job.unregister_async_job(vol_job[0], vol_job[1], thread_id)
+ time.sleep(1)
+ log.error("thread [{0}] reached exception limit, bailing out...".format(thread_name))
+ self.vc.cluster_log("thread {0} bailing out due to exception".format(thread_name))
+ with self.async_job.lock:
+ self.async_job.threads.remove(self)
+
+ def should_reconfigure_num_threads(self):
+ # reconfigure of max_concurrent_clones
+ return len(self.async_job.threads) > self.async_job.nr_concurrent_jobs
+
+ def cancel_job(self):
+ self.cancel_event.set()
+
+ def should_cancel(self):
+ return self.cancel_event.is_set()
+
+ def reset_cancel(self):
+ self.cancel_event.clear()
+
+class AsyncJobs(object):
+ """
+ Class providing asynchronous execution of jobs via worker threads.
+ `jobs` are grouped by `volume`, so a `volume` can have N number of
+ `jobs` executing concurrently (capped by number of concurrent jobs).
+
+ Usability is simple: subclass this and implement the following:
+ - get_next_job(volname, running_jobs)
+ - execute_job(volname, job, should_cancel)
+
+ ... and do not forget to invoke base class constructor.
+
+ Job cancelation is for a volume as a whole, i.e., all executing jobs
+ for a volume are canceled. Cancelation is poll based -- jobs need to
+ periodically check if cancelation is requested, after which the job
+ should return as soon as possible. Cancelation check is provided
+ via `should_cancel()` lambda passed to `execute_job()`.
+ """
+
+ def __init__(self, volume_client, name_pfx, nr_concurrent_jobs):
+ self.vc = volume_client
+ # queue of volumes for starting async jobs
+ self.q = deque()
+ # volume => job tracking
+ self.jobs = {}
+ # lock, cv for kickstarting jobs
+ self.lock = threading.Lock()
+ self.cv = threading.Condition(self.lock)
+ # cv for job cancelation
+ self.waiting = False
+ self.cancel_cv = threading.Condition(self.lock)
+ self.nr_concurrent_jobs = nr_concurrent_jobs
+
+ self.threads = []
+ for i in range(nr_concurrent_jobs):
+ self.threads.append(JobThread(self, volume_client, name="{0}.{1}".format(name_pfx, i)))
+ self.threads[-1].start()
+
+ def reconfigure_max_concurrent_clones(self, name_pfx, nr_concurrent_jobs):
+ """
+ reconfigure number of cloner threads
+ """
+ with self.lock:
+ self.nr_concurrent_jobs = nr_concurrent_jobs
+ # Decrease in concurrency. Notify threads which are waiting for a job to terminate.
+ if len(self.threads) > nr_concurrent_jobs:
+ self.cv.notifyAll()
+ # Increase in concurrency
+ if len(self.threads) < nr_concurrent_jobs:
+ for i in range(len(self.threads), nr_concurrent_jobs):
+ self.threads.append(JobThread(self, self.vc, name="{0}.{1}.{2}".format(name_pfx, time.time(), i)))
+ self.threads[-1].start()
+
+ def get_job(self):
+ log.debug("processing {0} volume entries".format(len(self.q)))
+ nr_vols = len(self.q)
+ to_remove = []
+ next_job = None
+ while nr_vols > 0:
+ volname = self.q[0]
+ # do this now so that the other thread pick up jobs for other volumes
+ self.q.rotate(1)
+ running_jobs = [j[0] for j in self.jobs[volname]]
+ (ret, job) = self.get_next_job(volname, running_jobs)
+ if job:
+ next_job = (volname, job)
+ break
+ # this is an optimization when for a given volume there are no more
+ # jobs and no jobs are in progress. in such cases we remove the volume
+ # from the tracking list so as to:
+ #
+ # a. not query the filesystem for jobs over and over again
+ # b. keep the filesystem connection idle so that it can be freed
+ # from the connection pool
+ #
+ # if at all there are jobs for a volume, the volume gets added again
+ # to the tracking list and the jobs get kickstarted.
+ # note that, we do not iterate the volume list fully if there is a
+ # jobs to process (that will take place eventually).
+ if ret == 0 and not job and not running_jobs:
+ to_remove.append(volname)
+ nr_vols -= 1
+ for vol in to_remove:
+ log.debug("auto removing volume '{0}' from tracked volumes".format(vol))
+ self.q.remove(vol)
+ self.jobs.pop(vol)
+ return next_job
+
+ def register_async_job(self, volname, job, thread_id):
+ log.debug("registering async job {0}.{1} with thread {2}".format(volname, job, thread_id))
+ self.jobs[volname].append((job, thread_id))
+
+ def unregister_async_job(self, volname, job, thread_id):
+ log.debug("unregistering async job {0}.{1} from thread {2}".format(volname, job, thread_id))
+ self.jobs[volname].remove((job, thread_id))
+
+ cancelled = thread_id.should_cancel()
+ thread_id.reset_cancel()
+
+ # wake up cancellation waiters if needed
+ if cancelled:
+ logging.info("waking up cancellation waiters")
+ self.cancel_cv.notifyAll()
+
+ def queue_job(self, volname):
+ """
+ queue a volume for asynchronous job execution.
+ """
+ log.info("queuing job for volume '{0}'".format(volname))
+ with self.lock:
+ if not volname in self.q:
+ self.q.append(volname)
+ self.jobs[volname] = []
+ self.cv.notifyAll()
+
+ def _cancel_jobs(self, volname):
+ """
+ cancel all jobs for the volume. do nothing is the no jobs are
+ executing for the given volume. this would wait until all jobs
+ get interrupted and finish execution.
+ """
+ log.info("cancelling jobs for volume '{0}'".format(volname))
+ try:
+ if not volname in self.q and not volname in self.jobs:
+ return
+ self.q.remove(volname)
+ # cancel in-progress operation and wait until complete
+ for j in self.jobs[volname]:
+ j[1].cancel_job()
+ # wait for cancellation to complete
+ while self.jobs[volname]:
+ log.debug("waiting for {0} in-progress jobs for volume '{1}' to " \
+ "cancel".format(len(self.jobs[volname]), volname))
+ self.cancel_cv.wait()
+ self.jobs.pop(volname)
+ except (KeyError, ValueError):
+ pass
+
+ def _cancel_job(self, volname, job):
+ """
+ cancel a executing job for a given volume. return True if canceled, False
+ otherwise (volume/job not found).
+ """
+ canceled = False
+ log.info("canceling job {0} for volume {1}".format(job, volname))
+ try:
+ if not volname in self.q and not volname in self.jobs and not job in self.jobs[volname]:
+ return canceled
+ for j in self.jobs[volname]:
+ if j[0] == job:
+ j[1].cancel_job()
+ # be safe against _cancel_jobs() running concurrently
+ while j in self.jobs.get(volname, []):
+ self.cancel_cv.wait()
+ canceled = True
+ break
+ except (KeyError, ValueError):
+ pass
+ return canceled
+
+ def cancel_job(self, volname, job):
+ with self.lock:
+ return self._cancel_job(volname, job)
+
+ def cancel_jobs(self, volname):
+ """
+ cancel all executing jobs for a given volume.
+ """
+ with self.lock:
+ self._cancel_jobs(volname)
+
+ def cancel_all_jobs(self):
+ """
+ call all executing jobs for all volumes.
+ """
+ with self.lock:
+ for volname in list(self.q):
+ self._cancel_jobs(volname)
+
+ def get_next_job(self, volname, running_jobs):
+ """
+ get the next job for asynchronous execution as (retcode, job) tuple. if no
+ jobs are available return (0, None) else return (0, job). on error return
+ (-ret, None). called under `self.lock`.
+ """
+ raise NotImplementedException()
+
+ def execute_job(self, volname, job, should_cancel):
+ """
+ execute a job for a volume. the job can block on I/O operations, sleep for long
+ hours and do all kinds of synchronous work. called outside `self.lock`.
+ """
+ raise NotImplementedException()
+
diff --git a/src/pybind/mgr/volumes/fs/exception.py b/src/pybind/mgr/volumes/fs/exception.py
new file mode 100644
index 00000000..4f903b99
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/exception.py
@@ -0,0 +1,63 @@
+class VolumeException(Exception):
+ def __init__(self, error_code, error_message):
+ self.errno = error_code
+ self.error_str = error_message
+
+ def to_tuple(self):
+ return self.errno, "", self.error_str
+
+ def __str__(self):
+ return "{0} ({1})".format(self.errno, self.error_str)
+
+class MetadataMgrException(Exception):
+ def __init__(self, error_code, error_message):
+ self.errno = error_code
+ self.error_str = error_message
+
+ def __str__(self):
+ return "{0} ({1})".format(self.errno, self.error_str)
+
+class IndexException(Exception):
+ def __init__(self, error_code, error_message):
+ self.errno = error_code
+ self.error_str = error_message
+
+ def __str__(self):
+ return "{0} ({1})".format(self.errno, self.error_str)
+
+class OpSmException(Exception):
+ def __init__(self, error_code, error_message):
+ self.errno = error_code
+ self.error_str = error_message
+
+ def __str__(self):
+ return "{0} ({1})".format(self.errno, self.error_str)
+
+class NotImplementedException(Exception):
+ pass
+
+class ClusterTimeout(Exception):
+ """
+ Exception indicating that we timed out trying to talk to the Ceph cluster,
+ either to the mons, or to any individual daemon that the mons indicate ought
+ to be up but isn't responding to us.
+ """
+ pass
+
+class ClusterError(Exception):
+ """
+ Exception indicating that the cluster returned an error to a command that
+ we thought should be successful based on our last knowledge of the cluster
+ state.
+ """
+ def __init__(self, action, result_code, result_str):
+ self._action = action
+ self._result_code = result_code
+ self._result_str = result_str
+
+ def __str__(self):
+ return "Error {0} (\"{1}\") while {2}".format(
+ self._result_code, self._result_str, self._action)
+
+class EvictionError(Exception):
+ pass
diff --git a/src/pybind/mgr/volumes/fs/fs_util.py b/src/pybind/mgr/volumes/fs/fs_util.py
new file mode 100644
index 00000000..6fe02f58
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/fs_util.py
@@ -0,0 +1,161 @@
+import os
+import errno
+import logging
+
+import cephfs
+import orchestrator
+
+from .exception import VolumeException
+
+log = logging.getLogger(__name__)
+
+def create_pool(mgr, pool_name, pg_num):
+ # create the given pool
+ command = {'prefix': 'osd pool create', 'pool': pool_name, 'pg_num': pg_num}
+ return mgr.mon_command(command)
+
+def remove_pool(mgr, pool_name):
+ command = {'prefix': 'osd pool rm', 'pool': pool_name, 'pool2': pool_name,
+ 'yes_i_really_really_mean_it': True}
+ return mgr.mon_command(command)
+
+def create_filesystem(mgr, fs_name, metadata_pool, data_pool):
+ command = {'prefix': 'fs new', 'fs_name': fs_name, 'metadata': metadata_pool,
+ 'data': data_pool}
+ return mgr.mon_command(command)
+
+def remove_filesystem(mgr, fs_name):
+ command = {'prefix': 'fs fail', 'fs_name': fs_name}
+ r, outb, outs = mgr.mon_command(command)
+ if r != 0:
+ return r, outb, outs
+
+ command = {'prefix': 'fs rm', 'fs_name': fs_name, 'yes_i_really_mean_it': True}
+ return mgr.mon_command(command)
+
+def create_mds(mgr, fs_name):
+ spec = orchestrator.StatelessServiceSpec()
+ spec.name = fs_name
+ try:
+ completion = mgr.add_stateless_service("mds", spec)
+ mgr._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ except (ImportError, orchestrator.OrchestratorError):
+ return 0, "", "Volume created successfully (no MDS daemons created)"
+ except Exception as e:
+ # Don't let detailed orchestrator exceptions (python backtraces)
+ # bubble out to the user
+ log.exception("Failed to create MDS daemons")
+ return -errno.EINVAL, "", str(e)
+ return 0, "", ""
+
+def volume_exists(mgr, fs_name):
+ fs_map = mgr.get('fs_map')
+ for fs in fs_map['filesystems']:
+ if fs['mdsmap']['fs_name'] == fs_name:
+ return True
+ return False
+
+def listdir(fs, dirpath):
+ """
+ Get the directory names (only dirs) for a given path
+ """
+ dirs = []
+ try:
+ with fs.opendir(dirpath) as dir_handle:
+ d = fs.readdir(dir_handle)
+ while d:
+ if (d.d_name not in (b".", b"..")) and d.is_dir():
+ dirs.append(d.d_name)
+ d = fs.readdir(dir_handle)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ return dirs
+
+def is_inherited_snap(snapname):
+ """
+ Returns True if the snapname is inherited else False
+ """
+ return snapname.startswith("_")
+
+def listsnaps(fs, volspec, snapdirpath, filter_inherited_snaps=False):
+ """
+ Get the snap names from a given snap directory path
+ """
+ if os.path.basename(snapdirpath) != volspec.snapshot_prefix.encode('utf-8'):
+ raise VolumeException(-errno.EINVAL, "Not a snap directory: {0}".format(snapdirpath))
+ snaps = []
+ try:
+ with fs.opendir(snapdirpath) as dir_handle:
+ d = fs.readdir(dir_handle)
+ while d:
+ if (d.d_name not in (b".", b"..")) and d.is_dir():
+ d_name = d.d_name.decode('utf-8')
+ if not is_inherited_snap(d_name):
+ snaps.append(d.d_name)
+ elif is_inherited_snap(d_name) and not filter_inherited_snaps:
+ snaps.append(d.d_name)
+ d = fs.readdir(dir_handle)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ return snaps
+
+def list_one_entry_at_a_time(fs, dirpath):
+ """
+ Get a directory entry (one entry a time)
+ """
+ try:
+ with fs.opendir(dirpath) as dir_handle:
+ d = fs.readdir(dir_handle)
+ while d:
+ if d.d_name not in (b".", b".."):
+ yield d
+ d = fs.readdir(dir_handle)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+def copy_file(fs, src, dst, mode, cancel_check=None):
+ """
+ Copy a regular file from @src to @dst. @dst is overwritten if it exists.
+ """
+ src_fd = dst_fd = None
+ try:
+ src_fd = fs.open(src, os.O_RDONLY);
+ dst_fd = fs.open(dst, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, mode)
+ except cephfs.Error as e:
+ if src_fd is not None:
+ fs.close(src_fd)
+ if dst_fd is not None:
+ fs.close(dst_fd)
+ raise VolumeException(-e.args[0], e.args[1])
+
+ IO_SIZE = 8 * 1024 * 1024
+ try:
+ while True:
+ if cancel_check and cancel_check():
+ raise VolumeException(-errno.EINTR, "copy operation interrupted")
+ data = fs.read(src_fd, -1, IO_SIZE)
+ if not len(data):
+ break
+ written = 0
+ while written < len(data):
+ written += fs.write(dst_fd, data[written:], -1)
+ fs.fsync(dst_fd, 0)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ finally:
+ fs.close(src_fd)
+ fs.close(dst_fd)
+
+def get_ancestor_xattr(fs, path, attr):
+ """
+ Helper for reading layout information: if this xattr is missing
+ on the requested path, keep checking parents until we find it.
+ """
+ try:
+ return fs.getxattr(path, attr).decode('utf-8')
+ except cephfs.NoData as e:
+ if path == "/":
+ raise VolumeException(-e.args[0], e.args[1])
+ else:
+ return get_ancestor_xattr(fs, os.path.split(path)[0], attr)
diff --git a/src/pybind/mgr/volumes/fs/operations/__init__.py b/src/pybind/mgr/volumes/fs/operations/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/__init__.py
diff --git a/src/pybind/mgr/volumes/fs/operations/access.py b/src/pybind/mgr/volumes/fs/operations/access.py
new file mode 100644
index 00000000..44430f59
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/access.py
@@ -0,0 +1,142 @@
+import errno
+import json
+try:
+ from typing import List
+except ImportError:
+ pass # For typing only
+
+def prepare_updated_caps_list(existing_caps, mds_cap_str, osd_cap_str, authorize=True):
+ caps_list = [] # type: List[str]
+ for k, v in existing_caps['caps'].items():
+ if k == 'mds' or k == 'osd':
+ continue
+ elif k == 'mon':
+ if not authorize and v == 'allow r':
+ continue
+ caps_list.extend((k,v))
+
+ if mds_cap_str:
+ caps_list.extend(('mds', mds_cap_str))
+ if osd_cap_str:
+ caps_list.extend(('osd', osd_cap_str))
+
+ if authorize and 'mon' not in caps_list:
+ caps_list.extend(('mon', 'allow r'))
+
+ return caps_list
+
+
+def allow_access(mgr, client_entity, want_mds_cap, want_osd_cap,
+ unwanted_mds_cap, unwanted_osd_cap, existing_caps):
+ if existing_caps is None:
+ ret, out, err = mgr.mon_command({
+ "prefix": "auth get-or-create",
+ "entity": client_entity,
+ "caps": ['mds', want_mds_cap, 'osd', want_osd_cap, 'mon', 'allow r'],
+ "format": "json"})
+ else:
+ cap = existing_caps[0]
+
+ def cap_update(
+ orig_mds_caps, orig_osd_caps, want_mds_cap,
+ want_osd_cap, unwanted_mds_cap, unwanted_osd_cap):
+
+ if not orig_mds_caps:
+ return want_mds_cap, want_osd_cap
+
+ mds_cap_tokens = [x.strip() for x in orig_mds_caps.split(",")]
+ osd_cap_tokens = [x.strip() for x in orig_osd_caps.split(",")]
+
+ if want_mds_cap in mds_cap_tokens:
+ return orig_mds_caps, orig_osd_caps
+
+ if unwanted_mds_cap in mds_cap_tokens:
+ mds_cap_tokens.remove(unwanted_mds_cap)
+ osd_cap_tokens.remove(unwanted_osd_cap)
+
+ mds_cap_tokens.append(want_mds_cap)
+ osd_cap_tokens.append(want_osd_cap)
+
+ return ",".join(mds_cap_tokens), ",".join(osd_cap_tokens)
+
+ orig_mds_caps = cap['caps'].get('mds', "")
+ orig_osd_caps = cap['caps'].get('osd', "")
+
+ mds_cap_str, osd_cap_str = cap_update(
+ orig_mds_caps, orig_osd_caps, want_mds_cap, want_osd_cap,
+ unwanted_mds_cap, unwanted_osd_cap)
+
+ caps_list = prepare_updated_caps_list(cap, mds_cap_str, osd_cap_str)
+ mgr.mon_command(
+ {
+ "prefix": "auth caps",
+ 'entity': client_entity,
+ 'caps': caps_list
+ })
+ ret, out, err = mgr.mon_command(
+ {
+ 'prefix': 'auth get',
+ 'entity': client_entity,
+ 'format': 'json'
+ })
+
+ # Result expected like this:
+ # [
+ # {
+ # "entity": "client.foobar",
+ # "key": "AQBY0\/pViX\/wBBAAUpPs9swy7rey1qPhzmDVGQ==",
+ # "caps": {
+ # "mds": "allow *",
+ # "mon": "allow *"
+ # }
+ # }
+ # ]
+
+ caps = json.loads(out)
+ assert len(caps) == 1
+ assert caps[0]['entity'] == client_entity
+ return caps[0]['key']
+
+def deny_access(mgr, client_entity, want_mds_caps, want_osd_caps):
+ ret, out, err = mgr.mon_command({
+ "prefix": "auth get",
+ "entity": client_entity,
+ "format": "json",
+ })
+
+ if ret == -errno.ENOENT:
+ # Already gone, great.
+ return
+
+ def cap_remove(orig_mds_caps, orig_osd_caps, want_mds_caps, want_osd_caps):
+ mds_cap_tokens = [x.strip() for x in orig_mds_caps.split(",")]
+ osd_cap_tokens = [x.strip() for x in orig_osd_caps.split(",")]
+
+ for want_mds_cap, want_osd_cap in zip(want_mds_caps, want_osd_caps):
+ if want_mds_cap in mds_cap_tokens:
+ mds_cap_tokens.remove(want_mds_cap)
+ osd_cap_tokens.remove(want_osd_cap)
+ break
+
+ return ",".join(mds_cap_tokens), ",".join(osd_cap_tokens)
+
+ cap = json.loads(out)[0]
+ orig_mds_caps = cap['caps'].get('mds', "")
+ orig_osd_caps = cap['caps'].get('osd', "")
+ mds_cap_str, osd_cap_str = cap_remove(orig_mds_caps, orig_osd_caps,
+ want_mds_caps, want_osd_caps)
+
+ caps_list = prepare_updated_caps_list(cap, mds_cap_str, osd_cap_str, authorize=False)
+ if not caps_list:
+ mgr.mon_command(
+ {
+ 'prefix': 'auth rm',
+ 'entity': client_entity
+ })
+ else:
+ mgr.mon_command(
+ {
+ "prefix": "auth caps",
+ 'entity': client_entity,
+ 'caps': caps_list
+ })
diff --git a/src/pybind/mgr/volumes/fs/operations/clone_index.py b/src/pybind/mgr/volumes/fs/operations/clone_index.py
new file mode 100644
index 00000000..a2b31f85
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/clone_index.py
@@ -0,0 +1,98 @@
+import os
+import uuid
+import stat
+import errno
+import logging
+from contextlib import contextmanager
+
+import cephfs
+
+from .index import Index
+from ..exception import IndexException, VolumeException
+from ..fs_util import list_one_entry_at_a_time
+
+log = logging.getLogger(__name__)
+
+class CloneIndex(Index):
+ SUB_GROUP_NAME = "clone"
+ PATH_MAX = 4096
+
+ @property
+ def path(self):
+ return os.path.join(super(CloneIndex, self).path, CloneIndex.SUB_GROUP_NAME.encode('utf-8'))
+
+ def _track(self, sink_path):
+ tracking_id = str(uuid.uuid4())
+ source_path = os.path.join(self.path, tracking_id.encode('utf-8'))
+ log.info("tracking-id {0} for path {1}".format(tracking_id, sink_path))
+
+ self.fs.symlink(sink_path, source_path)
+ return tracking_id
+
+ def track(self, sink_path):
+ try:
+ return self._track(sink_path)
+ except (VolumeException, cephfs.Error) as e:
+ if isinstance(e, cephfs.Error):
+ e = IndexException(-e.args[0], e.args[1])
+ elif isinstance(e, VolumeException):
+ e = IndexException(e.errno, e.error_str)
+ raise e
+
+ def untrack(self, tracking_id):
+ log.info("untracking {0}".format(tracking_id))
+ source_path = os.path.join(self.path, tracking_id.encode('utf-8'))
+ try:
+ self.fs.unlink(source_path)
+ except cephfs.Error as e:
+ raise IndexException(-e.args[0], e.args[1])
+
+ def get_oldest_clone_entry(self, exclude=[]):
+ min_ctime_entry = None
+ exclude_tracking_ids = [v[0] for v in exclude]
+ log.debug("excluded tracking ids: {0}".format(exclude_tracking_ids))
+ for entry in list_one_entry_at_a_time(self.fs, self.path):
+ dname = entry.d_name
+ dpath = os.path.join(self.path, dname)
+ st = self.fs.lstat(dpath)
+ if dname not in exclude_tracking_ids and stat.S_ISLNK(st.st_mode):
+ if min_ctime_entry is None or st.st_ctime < min_ctime_entry[1].st_ctime:
+ min_ctime_entry = (dname, st)
+ if min_ctime_entry:
+ try:
+ linklen = min_ctime_entry[1].st_size
+ sink_path = self.fs.readlink(os.path.join(self.path, min_ctime_entry[0]), CloneIndex.PATH_MAX)
+ return (min_ctime_entry[0], sink_path[:linklen])
+ except cephfs.Error as e:
+ raise IndexException(-e.args[0], e.args[1])
+ return None
+
+ def find_clone_entry_index(self, sink_path):
+ try:
+ for entry in list_one_entry_at_a_time(self.fs, self.path):
+ dname = entry.d_name
+ dpath = os.path.join(self.path, dname)
+ st = self.fs.lstat(dpath)
+ if stat.S_ISLNK(st.st_mode):
+ target_path = self.fs.readlink(dpath, CloneIndex.PATH_MAX)
+ if sink_path == target_path[:st.st_size]:
+ return dname
+ return None
+ except cephfs.Error as e:
+ raise IndexException(-e.args[0], e.args[1])
+
+def create_clone_index(fs, vol_spec):
+ clone_index = CloneIndex(fs, vol_spec)
+ try:
+ fs.mkdirs(clone_index.path, 0o700)
+ except cephfs.Error as e:
+ raise IndexException(-e.args[0], e.args[1])
+
+@contextmanager
+def open_clone_index(fs, vol_spec):
+ clone_index = CloneIndex(fs, vol_spec)
+ try:
+ fs.stat(clone_index.path)
+ except cephfs.Error as e:
+ raise IndexException(-e.args[0], e.args[1])
+ yield clone_index
diff --git a/src/pybind/mgr/volumes/fs/operations/group.py b/src/pybind/mgr/volumes/fs/operations/group.py
new file mode 100644
index 00000000..ae334563
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/group.py
@@ -0,0 +1,186 @@
+import os
+import errno
+import logging
+from contextlib import contextmanager
+
+import cephfs
+
+from .snapshot_util import mksnap, rmsnap
+from .template import GroupTemplate
+from ..fs_util import listdir, listsnaps, get_ancestor_xattr
+from ..exception import VolumeException
+
+log = logging.getLogger(__name__)
+
+class Group(GroupTemplate):
+ # Reserved subvolume group name which we use in paths for subvolumes
+ # that are not assigned to a group (i.e. created with group=None)
+ NO_GROUP_NAME = "_nogroup"
+
+ def __init__(self, fs, vol_spec, groupname):
+ assert groupname != Group.NO_GROUP_NAME
+ self.fs = fs
+ self.user_id = None
+ self.group_id = None
+ self.vol_spec = vol_spec
+ self.groupname = groupname if groupname else Group.NO_GROUP_NAME
+
+ @property
+ def path(self):
+ return os.path.join(self.vol_spec.base_dir.encode('utf-8'), self.groupname.encode('utf-8'))
+
+ @property
+ def group_name(self):
+ return self.groupname
+
+ @property
+ def uid(self):
+ return self.user_id
+
+ @uid.setter
+ def uid(self, val):
+ self.user_id = val
+
+ @property
+ def gid(self):
+ return self.group_id
+
+ @gid.setter
+ def gid(self, val):
+ self.group_id = val
+
+ def is_default_group(self):
+ return self.groupname == Group.NO_GROUP_NAME
+
+ def list_subvolumes(self):
+ try:
+ return listdir(self.fs, self.path)
+ except VolumeException as ve:
+ # listing a default group when it's not yet created
+ if ve.errno == -errno.ENOENT and self.is_default_group():
+ return []
+ raise
+
+ def create_snapshot(self, snapname):
+ snappath = os.path.join(self.path,
+ self.vol_spec.snapshot_dir_prefix.encode('utf-8'),
+ snapname.encode('utf-8'))
+ mksnap(self.fs, snappath)
+
+ def remove_snapshot(self, snapname):
+ snappath = os.path.join(self.path,
+ self.vol_spec.snapshot_dir_prefix.encode('utf-8'),
+ snapname.encode('utf-8'))
+ rmsnap(self.fs, snappath)
+
+ def list_snapshots(self):
+ try:
+ dirpath = os.path.join(self.path,
+ self.vol_spec.snapshot_dir_prefix.encode('utf-8'))
+ return listsnaps(self.fs, self.vol_spec, dirpath, filter_inherited_snaps=True)
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ return []
+ raise
+
+def create_group(fs, vol_spec, groupname, pool, mode, uid, gid):
+ """
+ create a subvolume group.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param groupname: subvolume group name
+ :param pool: the RADOS pool where the data objects of the subvolumes will be stored
+ :param mode: the user permissions
+ :param uid: the user identifier
+ :param gid: the group identifier
+ :return: None
+ """
+ group = Group(fs, vol_spec, groupname)
+ path = group.path
+ fs.mkdirs(path, mode)
+ try:
+ if not pool:
+ pool = get_ancestor_xattr(fs, path, "ceph.dir.layout.pool")
+ try:
+ fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
+ except cephfs.InvalidValue:
+ raise VolumeException(-errno.EINVAL,
+ "Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
+ if uid is None:
+ uid = 0
+ else:
+ try:
+ uid = int(uid)
+ if uid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid UID")
+ if gid is None:
+ gid = 0
+ else:
+ try:
+ gid = int(gid)
+ if gid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid GID")
+ fs.chown(path, uid, gid)
+ except (cephfs.Error, VolumeException) as e:
+ try:
+ # cleanup group path on best effort basis
+ log.debug("cleaning up subvolume group path: {0}".format(path))
+ fs.rmdir(path)
+ except cephfs.Error as ce:
+ log.debug("failed to clean up subvolume group {0} with path: {1} ({2})".format(groupname, path, ce))
+ if isinstance(e, cephfs.Error):
+ e = VolumeException(-e.args[0], e.args[1])
+ raise e
+
+def remove_group(fs, vol_spec, groupname):
+ """
+ remove a subvolume group.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param groupname: subvolume group name
+ :return: None
+ """
+ group = Group(fs, vol_spec, groupname)
+ try:
+ fs.rmdir(group.path)
+ except cephfs.Error as e:
+ if e.args[0] == errno.ENOENT:
+ raise VolumeException(-errno.ENOENT, "subvolume group '{0}' does not exist".format(groupname))
+ raise VolumeException(-e.args[0], e.args[1])
+
+@contextmanager
+def open_group(fs, vol_spec, groupname):
+ """
+ open a subvolume group. This API is to be used as a context manager.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param groupname: subvolume group name
+ :return: yields a group object (subclass of GroupTemplate)
+ """
+ group = Group(fs, vol_spec, groupname)
+ try:
+ st = fs.stat(group.path)
+ group.uid = int(st.st_uid)
+ group.gid = int(st.st_gid)
+ except cephfs.Error as e:
+ if e.args[0] == errno.ENOENT:
+ if not group.is_default_group():
+ raise VolumeException(-errno.ENOENT, "subvolume group '{0}' does not exist".format(groupname))
+ else:
+ raise VolumeException(-e.args[0], e.args[1])
+ yield group
+
+@contextmanager
+def open_group_unique(fs, vol_spec, groupname, c_group, c_groupname):
+ if groupname == c_groupname:
+ yield c_group
+ else:
+ with open_group(fs, vol_spec, groupname) as group:
+ yield group
diff --git a/src/pybind/mgr/volumes/fs/operations/index.py b/src/pybind/mgr/volumes/fs/operations/index.py
new file mode 100644
index 00000000..0e4296d7
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/index.py
@@ -0,0 +1,23 @@
+import errno
+import os
+
+from ..exception import VolumeException
+from .template import GroupTemplate
+
+class Index(GroupTemplate):
+ GROUP_NAME = "_index"
+
+ def __init__(self, fs, vol_spec):
+ self.fs = fs
+ self.vol_spec = vol_spec
+ self.groupname = Index.GROUP_NAME
+
+ @property
+ def path(self):
+ return os.path.join(self.vol_spec.base_dir.encode('utf-8'), self.groupname.encode('utf-8'))
+
+ def track(self, *args):
+ raise VolumeException(-errno.EINVAL, "operation not supported.")
+
+ def untrack(self, tracking_id):
+ raise VolumeException(-errno.EINVAL, "operation not supported.")
diff --git a/src/pybind/mgr/volumes/fs/operations/lock.py b/src/pybind/mgr/volumes/fs/operations/lock.py
new file mode 100644
index 00000000..ab5f1d04
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/lock.py
@@ -0,0 +1,42 @@
+from contextlib import contextmanager
+import logging
+from threading import Lock
+
+log = logging.getLogger(__name__)
+
+# singleton design pattern taken from http://www.aleax.it/5ep.html
+
+class GlobalLock(object):
+ """
+ Global lock to serialize operations in mgr/volumes. This lock
+ is currently held when accessing (opening) a volume to perform
+ group/subvolume operations. Since this is a big lock, it's rather
+ inefficient -- but right now it's ok since mgr/volumes does not
+ expect concurrent operations via its APIs.
+
+ As and when features get added (such as clone, where mgr/volumes
+ would maintain subvolume states in the filesystem), there might
+ be a need to allow concurrent operations. In that case it would
+ be nice to implement an efficient path based locking mechanism.
+
+ See: https://people.eecs.berkeley.edu/~kubitron/courses/cs262a-F14/projects/reports/project6_report.pdf
+ """
+ _shared_state = {
+ 'lock' : Lock(),
+ 'init' : False
+ }
+
+ def __init__(self):
+ with self._shared_state['lock']:
+ if not self._shared_state['init']:
+ self._shared_state['init'] = True
+ # share this state among all instances
+ self.__dict__ = self._shared_state
+
+ @contextmanager
+ def lock_op(self):
+ log.debug("entering global lock")
+ with self._shared_state['lock']:
+ log.debug("acquired global lock")
+ yield
+ log.debug("exited global lock")
diff --git a/src/pybind/mgr/volumes/fs/operations/rankevicter.py b/src/pybind/mgr/volumes/fs/operations/rankevicter.py
new file mode 100644
index 00000000..5b945c38
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/rankevicter.py
@@ -0,0 +1,114 @@
+import errno
+import json
+import logging
+import threading
+import time
+
+from .volume import get_mds_map
+from ..exception import ClusterTimeout, ClusterError
+
+log = logging.getLogger(__name__)
+
+class RankEvicter(threading.Thread):
+ """
+ Thread for evicting client(s) from a particular MDS daemon instance.
+
+ This is more complex than simply sending a command, because we have to
+ handle cases where MDS daemons might not be fully up yet, and/or might
+ be transiently unresponsive to commands.
+ """
+ class GidGone(Exception):
+ pass
+
+ POLL_PERIOD = 5
+
+ def __init__(self, mgr, fs, client_spec, volname, rank, gid, mds_map, ready_timeout):
+ """
+ :param client_spec: list of strings, used as filter arguments to "session evict"
+ pass ["id=123"] to evict a single client with session id 123.
+ """
+ self.volname = volname
+ self.rank = rank
+ self.gid = gid
+ self._mds_map = mds_map
+ self._client_spec = client_spec
+ self._fs = fs
+ self._ready_timeout = ready_timeout
+ self._ready_waited = 0
+ self.mgr = mgr
+
+ self.success = False
+ self.exception = None
+
+ super(RankEvicter, self).__init__()
+
+ def _ready_to_evict(self):
+ if self._mds_map['up'].get("mds_{0}".format(self.rank), None) != self.gid:
+ log.info("Evicting {0} from {1}/{2}: rank no longer associated with gid, done.".format(
+ self._client_spec, self.rank, self.gid
+ ))
+ raise RankEvicter.GidGone()
+
+ info = self._mds_map['info']["gid_{0}".format(self.gid)]
+ log.debug("_ready_to_evict: state={0}".format(info['state']))
+ return info['state'] in ["up:active", "up:clientreplay"]
+
+ def _wait_for_ready(self):
+ """
+ Wait for that MDS rank to reach an active or clientreplay state, and
+ not be laggy.
+ """
+ while not self._ready_to_evict():
+ if self._ready_waited > self._ready_timeout:
+ raise ClusterTimeout()
+
+ time.sleep(self.POLL_PERIOD)
+ self._ready_waited += self.POLL_PERIOD
+ self._mds_map = get_mds_map(self.mgr, self.volname)
+
+ def _evict(self):
+ """
+ Run the eviction procedure. Return true on success, false on errors.
+ """
+
+ # Wait til the MDS is believed by the mon to be available for commands
+ try:
+ self._wait_for_ready()
+ except self.GidGone:
+ return True
+
+ # Then send it an evict
+ ret = -errno.ETIMEDOUT
+ while ret == -errno.ETIMEDOUT:
+ log.debug("mds_command: {0}, {1}".format(
+ "%s" % self.gid, ["session", "evict"] + self._client_spec
+ ))
+ ret, outb, outs = self._fs.mds_command(
+ "%s" % self.gid,
+ json.dumps({
+ "prefix": "session evict",
+ "filters": self._client_spec
+ }), "")
+ log.debug("mds_command: complete {0} {1}".format(ret, outs))
+
+ # If we get a clean response, great, it's gone from that rank.
+ if ret == 0:
+ return True
+ elif ret == -errno.ETIMEDOUT:
+ # Oh no, the MDS went laggy (that's how libcephfs knows to emit this error)
+ self._mds_map = get_mds_map(self.mgr, self.volname)
+ try:
+ self._wait_for_ready()
+ except self.GidGone:
+ return True
+ else:
+ raise ClusterError("Sending evict to mds.{0}".format(self.gid), ret, outs)
+
+ def run(self):
+ try:
+ self._evict()
+ except Exception as e:
+ self.success = False
+ self.exception = e
+ else:
+ self.success = True
diff --git a/src/pybind/mgr/volumes/fs/operations/resolver.py b/src/pybind/mgr/volumes/fs/operations/resolver.py
new file mode 100644
index 00000000..a9543654
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/resolver.py
@@ -0,0 +1,26 @@
+import os
+
+from .group import Group
+
+def splitall(path):
+ if path == "/":
+ return ["/"]
+ s = os.path.split(path)
+ return splitall(s[0]) + [s[1]]
+
+def resolve(vol_spec, path):
+ parts = splitall(path)
+ if len(parts) != 4 or os.path.join(parts[0], parts[1]) != vol_spec.subvolume_prefix:
+ return None
+ groupname = None if parts[2] == Group.NO_GROUP_NAME else parts[2]
+ subvolname = parts[3]
+ return (groupname, subvolname)
+
+def resolve_trash(vol_spec, path):
+ parts = splitall(path)
+ if len(parts) != 6 or os.path.join(parts[0], parts[1]) != vol_spec.subvolume_prefix or \
+ parts[4] != '.trash':
+ return None
+ groupname = None if parts[2] == Group.NO_GROUP_NAME else parts[2]
+ subvolname = parts[3]
+ return (groupname, subvolname)
diff --git a/src/pybind/mgr/volumes/fs/operations/snapshot_util.py b/src/pybind/mgr/volumes/fs/operations/snapshot_util.py
new file mode 100644
index 00000000..2223c58e
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/snapshot_util.py
@@ -0,0 +1,30 @@
+import os
+import errno
+
+import cephfs
+
+from ..exception import VolumeException
+
+def mksnap(fs, snappath):
+ """
+ Create a snapshot, or do nothing if it already exists.
+ """
+ try:
+ # snap create does not accept mode -- use default
+ fs.mkdir(snappath, 0o755)
+ except cephfs.ObjectExists:
+ return
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+def rmsnap(fs, snappath):
+ """
+ Remove a snapshot
+ """
+ try:
+ fs.stat(snappath)
+ fs.rmdir(snappath)
+ except cephfs.ObjectNotFound:
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(os.path.basename(snappath)))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
diff --git a/src/pybind/mgr/volumes/fs/operations/subvolume.py b/src/pybind/mgr/volumes/fs/operations/subvolume.py
new file mode 100644
index 00000000..dc36477b
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/subvolume.py
@@ -0,0 +1,74 @@
+import os
+import errno
+from contextlib import contextmanager
+
+from ..exception import VolumeException
+from .template import SubvolumeOpType
+
+from .versions import loaded_subvolumes
+
+def create_subvol(mgr, fs, vol_spec, group, subvolname, size, isolate_nspace, pool, mode, uid, gid):
+ """
+ create a subvolume (create a subvolume with the max known version).
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param group: group object for the subvolume
+ :param size: In bytes, or None for no size limit
+ :param isolate_nspace: If true, use separate RADOS namespace for this subvolume
+ :param pool: the RADOS pool where the data objects of the subvolumes will be stored
+ :param mode: the user permissions
+ :param uid: the user identifier
+ :param gid: the group identifier
+ :return: None
+ """
+ subvolume = loaded_subvolumes.get_subvolume_object_max(mgr, fs, vol_spec, group, subvolname)
+ subvolume.create(size, isolate_nspace, pool, mode, uid, gid)
+
+def create_clone(mgr, fs, vol_spec, group, subvolname, pool, source_volume, source_subvolume, snapname):
+ """
+ create a cloned subvolume.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param group: group object for the clone
+ :param subvolname: clone subvolume nam
+ :param pool: the RADOS pool where the data objects of the cloned subvolume will be stored
+ :param source_volume: source subvolumes volume name
+ :param source_subvolume: source (parent) subvolume object
+ :param snapname: source subvolume snapshot
+ :return None
+ """
+ subvolume = loaded_subvolumes.get_subvolume_object_max(mgr, fs, vol_spec, group, subvolname)
+ subvolume.create_clone(pool, source_volume, source_subvolume, snapname)
+
+def remove_subvol(mgr, fs, vol_spec, group, subvolname, force=False, retainsnaps=False):
+ """
+ remove a subvolume.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param group: group object for the subvolume
+ :param subvolname: subvolume name
+ :param force: force remove subvolumes
+ :return: None
+ """
+ op_type = SubvolumeOpType.REMOVE if not force else SubvolumeOpType.REMOVE_FORCE
+ with open_subvol(mgr, fs, vol_spec, group, subvolname, op_type) as subvolume:
+ subvolume.remove(retainsnaps)
+
+@contextmanager
+def open_subvol(mgr, fs, vol_spec, group, subvolname, op_type):
+ """
+ open a subvolume. This API is to be used as a context manager.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :param group: group object for the subvolume
+ :param subvolname: subvolume name
+ :param op_type: operation type for which subvolume is being opened
+ :return: yields a subvolume object (subclass of SubvolumeTemplate)
+ """
+ subvolume = loaded_subvolumes.get_subvolume_object(mgr, fs, vol_spec, group, subvolname)
+ subvolume.open(op_type)
+ yield subvolume
diff --git a/src/pybind/mgr/volumes/fs/operations/template.py b/src/pybind/mgr/volumes/fs/operations/template.py
new file mode 100644
index 00000000..d35ad0de
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/template.py
@@ -0,0 +1,173 @@
+import errno
+
+from enum import Enum, unique
+
+from ..exception import VolumeException
+
+class GroupTemplate(object):
+ def list_subvolumes(self):
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def create_snapshot(self, snapname):
+ """
+ create a subvolume group snapshot.
+
+ :param: group snapshot name
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def remove_snapshot(self, snapname):
+ """
+ remove a subvolume group snapshot.
+
+ :param: group snapshot name
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def list_snapshots(self):
+ """
+ list all subvolume group snapshots.
+
+ :param: None
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+@unique
+class SubvolumeOpType(Enum):
+ CREATE = 'create'
+ REMOVE = 'rm'
+ REMOVE_FORCE = 'rm-force'
+ PIN = 'pin'
+ LIST = 'ls'
+ GETPATH = 'getpath'
+ INFO = 'info'
+ RESIZE = 'resize'
+ SNAP_CREATE = 'snap-create'
+ SNAP_REMOVE = 'snap-rm'
+ SNAP_LIST = 'snap-ls'
+ SNAP_INFO = 'snap-info'
+ SNAP_PROTECT = 'snap-protect'
+ SNAP_UNPROTECT = 'snap-unprotect'
+ CLONE_SOURCE = 'clone-source'
+ CLONE_CREATE = 'clone-create'
+ CLONE_STATUS = 'clone-status'
+ CLONE_CANCEL = 'clone-cancel'
+ CLONE_INTERNAL = 'clone_internal'
+ ALLOW_ACCESS = 'allow-access'
+ DENY_ACCESS = 'deny-access'
+ AUTH_LIST = 'auth-list'
+ EVICT = 'evict'
+
+class SubvolumeTemplate(object):
+ VERSION = None # type: int
+
+ @staticmethod
+ def version():
+ return SubvolumeTemplate.VERSION
+
+ def open(self, op_type):
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def status(self):
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def create(self, size, isolate_nspace, pool, mode, uid, gid):
+ """
+ set up metadata, pools and auth for a subvolume.
+
+ This function is idempotent. It is safe to call this again
+ for an already-created subvolume, even if it is in use.
+
+ :param size: In bytes, or None for no size limit
+ :param isolate_nspace: If true, use separate RADOS namespace for this subvolume
+ :param pool: the RADOS pool where the data objects of the subvolumes will be stored
+ :param mode: the user permissions
+ :param uid: the user identifier
+ :param gid: the group identifier
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def create_clone(self, pool, source_volname, source_subvolume, snapname):
+ """
+ prepare a subvolume to be cloned.
+
+ :param pool: the RADOS pool where the data objects of the cloned subvolume will be stored
+ :param source_volname: source volume of snapshot
+ :param source_subvolume: source subvolume of snapshot
+ :param snapname: snapshot name to be cloned from
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def remove(self):
+ """
+ make a subvolume inaccessible to guests.
+
+ This function is idempotent. It is safe to call this again
+
+ :param: None
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def resize(self, newsize, nshrink):
+ """
+ resize a subvolume
+
+ :param newsize: new size In bytes (or inf/infinite)
+ :return: new quota size and used bytes as a tuple
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def create_snapshot(self, snapname):
+ """
+ snapshot a subvolume.
+
+ :param: subvolume snapshot name
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def remove_snapshot(self, snapname):
+ """
+ remove a subvolume snapshot.
+
+ :param: subvolume snapshot name
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def list_snapshots(self):
+ """
+ list all subvolume snapshots.
+
+ :param: None
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def attach_snapshot(self, snapname, tgt_subvolume):
+ """
+ attach a snapshot to a target cloned subvolume. the target subvolume
+ should be an empty subvolume (type "clone") in "pending" state.
+
+ :param: snapname: snapshot to attach to a clone
+ :param: tgt_subvolume: target clone subvolume
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
+
+ def detach_snapshot(self, snapname, tgt_subvolume):
+ """
+ detach a snapshot from a target cloned subvolume. the target subvolume
+ should either be in "failed" or "completed" state.
+
+ :param: snapname: snapshot to detach from a clone
+ :param: tgt_subvolume: target clone subvolume
+ :return: None
+ """
+ raise VolumeException(-errno.ENOTSUP, "operation not supported.")
diff --git a/src/pybind/mgr/volumes/fs/operations/trash.py b/src/pybind/mgr/volumes/fs/operations/trash.py
new file mode 100644
index 00000000..66f1d71c
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/trash.py
@@ -0,0 +1,145 @@
+import os
+import uuid
+import logging
+from contextlib import contextmanager
+
+import cephfs
+
+from .template import GroupTemplate
+from ..fs_util import listdir
+from ..exception import VolumeException
+
+log = logging.getLogger(__name__)
+
+class Trash(GroupTemplate):
+ GROUP_NAME = "_deleting"
+
+ def __init__(self, fs, vol_spec):
+ self.fs = fs
+ self.vol_spec = vol_spec
+ self.groupname = Trash.GROUP_NAME
+
+ @property
+ def path(self):
+ return os.path.join(self.vol_spec.base_dir.encode('utf-8'), self.groupname.encode('utf-8'))
+
+ @property
+ def unique_trash_path(self):
+ """
+ return a unique trash directory entry path
+ """
+ return os.path.join(self.path, str(uuid.uuid4()).encode('utf-8'))
+
+ def _get_single_dir_entry(self, exclude_list=[]):
+ exclude_list.extend((b".", b".."))
+ try:
+ with self.fs.opendir(self.path) as d:
+ entry = self.fs.readdir(d)
+ while entry:
+ if entry.d_name not in exclude_list:
+ return entry.d_name
+ entry = self.fs.readdir(d)
+ return None
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def get_trash_entry(self, exclude_list):
+ """
+ get a trash entry excluding entries provided.
+
+ :praram exclude_list: entries to exclude
+ :return: trash entry
+ """
+ return self._get_single_dir_entry(exclude_list)
+
+ def purge(self, trashpath, should_cancel):
+ """
+ purge a trash entry.
+
+ :praram trash_entry: the trash entry to purge
+ :praram should_cancel: callback to check if the purge should be aborted
+ :return: None
+ """
+ def rmtree(root_path):
+ log.debug("rmtree {0}".format(root_path))
+ try:
+ with self.fs.opendir(root_path) as dir_handle:
+ d = self.fs.readdir(dir_handle)
+ while d and not should_cancel():
+ if d.d_name not in (b".", b".."):
+ d_full = os.path.join(root_path, d.d_name)
+ if d.is_dir():
+ rmtree(d_full)
+ else:
+ self.fs.unlink(d_full)
+ d = self.fs.readdir(dir_handle)
+ except cephfs.ObjectNotFound:
+ return
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ # remove the directory only if we were not asked to cancel
+ # (else we would fail to remove this anyway)
+ if not should_cancel():
+ self.fs.rmdir(root_path)
+
+ # catch any unlink errors
+ try:
+ rmtree(trashpath)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def dump(self, path):
+ """
+ move an filesystem entity to trash can.
+
+ :praram path: the filesystem path to be moved
+ :return: None
+ """
+ try:
+ self.fs.rename(path, self.unique_trash_path)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def link(self, path, bname):
+ pth = os.path.join(self.path, bname)
+ try:
+ self.fs.symlink(path, pth)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def delink(self, bname):
+ pth = os.path.join(self.path, bname)
+ try:
+ self.fs.unlink(pth)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+def create_trashcan(fs, vol_spec):
+ """
+ create a trash can.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :return: None
+ """
+ trashcan = Trash(fs, vol_spec)
+ try:
+ fs.mkdirs(trashcan.path, 0o700)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+@contextmanager
+def open_trashcan(fs, vol_spec):
+ """
+ open a trash can. This API is to be used as a context manager.
+
+ :param fs: ceph filesystem handle
+ :param vol_spec: volume specification
+ :return: yields a trash can object (subclass of GroupTemplate)
+ """
+ trashcan = Trash(fs, vol_spec)
+ try:
+ fs.stat(trashcan.path)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ yield trashcan
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/__init__.py b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py
new file mode 100644
index 00000000..3dcdd7c1
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py
@@ -0,0 +1,109 @@
+import errno
+import logging
+import importlib
+
+import cephfs
+
+from .subvolume_base import SubvolumeBase
+from .subvolume_attrs import SubvolumeTypes
+from .subvolume_v1 import SubvolumeV1
+from .subvolume_v2 import SubvolumeV2
+from .metadata_manager import MetadataManager
+from .op_sm import SubvolumeOpSm
+from ..template import SubvolumeOpType
+from ...exception import MetadataMgrException, OpSmException, VolumeException
+
+log = logging.getLogger(__name__)
+
+class SubvolumeLoader(object):
+ INVALID_VERSION = -1
+
+ SUPPORTED_MODULES = ['subvolume_v1.SubvolumeV1', 'subvolume_v2.SubvolumeV2']
+
+ def __init__(self):
+ self.max_version = SubvolumeLoader.INVALID_VERSION
+ self.versions = {}
+
+ def _load_module(self, mod_cls):
+ mod_name, cls_name = mod_cls.split('.')
+ mod = importlib.import_module('.versions.{0}'.format(mod_name), package='volumes.fs.operations')
+ return getattr(mod, cls_name)
+
+ def _load_supported_versions(self):
+ for mod_cls in SubvolumeLoader.SUPPORTED_MODULES:
+ cls = self._load_module(mod_cls)
+ log.info("loaded v{0} subvolume".format(cls.version()))
+ if self.max_version is not None or cls.version() > self.max_version:
+ self.max_version = cls.version()
+ self.versions[cls.version()] = cls
+ if self.max_version == SubvolumeLoader.INVALID_VERSION:
+ raise VolumeException(-errno.EINVAL, "no subvolume version available")
+ log.info("max subvolume version is v{0}".format(self.max_version))
+
+ def _get_subvolume_version(self, version):
+ try:
+ return self.versions[version]
+ except KeyError:
+ raise VolumeException(-errno.EINVAL, "subvolume class v{0} does not exist".format(version))
+
+ def get_subvolume_object_max(self, mgr, fs, vol_spec, group, subvolname):
+ return self._get_subvolume_version(self.max_version)(mgr, fs, vol_spec, group, subvolname)
+
+ def upgrade_to_v2_subvolume(self, subvolume):
+ # legacy mode subvolumes cannot be upgraded to v2
+ if subvolume.legacy_mode:
+ return
+
+ version = int(subvolume.metadata_mgr.get_global_option('version'))
+ if version >= SubvolumeV2.version():
+ return
+
+ v1_subvolume = self._get_subvolume_version(version)(subvolume.mgr, subvolume.fs, subvolume.vol_spec, subvolume.group, subvolume.subvolname)
+ try:
+ v1_subvolume.open(SubvolumeOpType.SNAP_LIST)
+ except VolumeException as ve:
+ # if volume is not ready for snapshot listing, do not upgrade at present
+ if ve.errno == -errno.EAGAIN:
+ return
+ raise
+
+ # v1 subvolumes with snapshots cannot be upgraded to v2
+ if v1_subvolume.list_snapshots():
+ return
+
+ subvolume.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_VERSION, SubvolumeV2.version())
+ subvolume.metadata_mgr.flush()
+
+ def upgrade_legacy_subvolume(self, fs, subvolume):
+ assert subvolume.legacy_mode
+ try:
+ fs.mkdirs(subvolume.legacy_dir, 0o700)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], "error accessing subvolume")
+ subvolume_type = SubvolumeTypes.TYPE_NORMAL
+ try:
+ initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
+ except OpSmException as oe:
+ raise VolumeException(-errno.EINVAL, "subvolume creation failed: internal error")
+ qpath = subvolume.base_path.decode('utf-8')
+ # legacy is only upgradable to v1
+ subvolume.init_config(SubvolumeV1.version(), subvolume_type, qpath, initial_state)
+
+ def get_subvolume_object(self, mgr, fs, vol_spec, group, subvolname, upgrade=True):
+ subvolume = SubvolumeBase(mgr, fs, vol_spec, group, subvolname)
+ try:
+ subvolume.discover()
+ self.upgrade_to_v2_subvolume(subvolume)
+ version = int(subvolume.metadata_mgr.get_global_option('version'))
+ return self._get_subvolume_version(version)(mgr, fs, vol_spec, group, subvolname, legacy=subvolume.legacy_mode)
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT and upgrade:
+ self.upgrade_legacy_subvolume(fs, subvolume)
+ return self.get_subvolume_object(mgr, fs, vol_spec, group, subvolname, upgrade=False)
+ else:
+ # log the actual error and generalize error string returned to user
+ log.error("error accessing subvolume metadata for '{0}' ({1})".format(subvolname, me))
+ raise VolumeException(-errno.EINVAL, "error accessing subvolume metadata")
+
+loaded_subvolumes = SubvolumeLoader()
+loaded_subvolumes._load_supported_versions()
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/auth_metadata.py b/src/pybind/mgr/volumes/fs/operations/versions/auth_metadata.py
new file mode 100644
index 00000000..259dcd0e
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/auth_metadata.py
@@ -0,0 +1,208 @@
+from contextlib import contextmanager
+import os
+import fcntl
+import json
+import logging
+import struct
+import uuid
+
+import cephfs
+
+from ..group import Group
+
+log = logging.getLogger(__name__)
+
+class AuthMetadataError(Exception):
+ pass
+
+class AuthMetadataManager(object):
+
+ # Current version
+ version = 6
+
+ # Filename extensions for meta files.
+ META_FILE_EXT = ".meta"
+ DEFAULT_VOL_PREFIX = "/volumes"
+
+ def __init__(self, fs):
+ self.fs = fs
+ self._id = struct.unpack(">Q", uuid.uuid1().bytes[0:8])[0]
+ self.volume_prefix = self.DEFAULT_VOL_PREFIX
+
+ def _to_bytes(self, param):
+ '''
+ Helper method that returns byte representation of the given parameter.
+ '''
+ if isinstance(param, str):
+ return param.encode('utf-8')
+ elif param is None:
+ return param
+ else:
+ return str(param).encode('utf-8')
+
+ def _subvolume_metadata_path(self, group_name, subvol_name):
+ return os.path.join(self.volume_prefix, "_{0}:{1}{2}".format(
+ group_name if group_name != Group.NO_GROUP_NAME else "",
+ subvol_name,
+ self.META_FILE_EXT))
+
+ def _check_compat_version(self, compat_version):
+ if self.version < compat_version:
+ msg = ("The current version of AuthMetadataManager, version {0} "
+ "does not support the required feature. Need version {1} "
+ "or greater".format(self.version, compat_version)
+ )
+ log.error(msg)
+ raise AuthMetadataError(msg)
+
+ def _metadata_get(self, path):
+ """
+ Return a deserialized JSON object, or None
+ """
+ fd = self.fs.open(path, "r")
+ # TODO iterate instead of assuming file < 4MB
+ read_bytes = self.fs.read(fd, 0, 4096 * 1024)
+ self.fs.close(fd)
+ if read_bytes:
+ return json.loads(read_bytes.decode())
+ else:
+ return None
+
+ def _metadata_set(self, path, data):
+ serialized = json.dumps(data)
+ fd = self.fs.open(path, "w")
+ try:
+ self.fs.write(fd, self._to_bytes(serialized), 0)
+ self.fs.fsync(fd, 0)
+ finally:
+ self.fs.close(fd)
+
+ def _lock(self, path):
+ @contextmanager
+ def fn():
+ while(1):
+ fd = self.fs.open(path, os.O_CREAT, 0o755)
+ self.fs.flock(fd, fcntl.LOCK_EX, self._id)
+
+ # The locked file will be cleaned up sometime. It could be
+ # unlinked by consumer e.g., an another manila-share service
+ # instance, before lock was applied on it. Perform checks to
+ # ensure that this does not happen.
+ try:
+ statbuf = self.fs.stat(path)
+ except cephfs.ObjectNotFound:
+ self.fs.close(fd)
+ continue
+
+ fstatbuf = self.fs.fstat(fd)
+ if statbuf.st_ino == fstatbuf.st_ino:
+ break
+
+ try:
+ yield
+ finally:
+ self.fs.flock(fd, fcntl.LOCK_UN, self._id)
+ self.fs.close(fd)
+
+ return fn()
+
+ def _auth_metadata_path(self, auth_id):
+ return os.path.join(self.volume_prefix, "${0}{1}".format(
+ auth_id, self.META_FILE_EXT))
+
+ def auth_lock(self, auth_id):
+ return self._lock(self._auth_metadata_path(auth_id))
+
+ def auth_metadata_get(self, auth_id):
+ """
+ Call me with the metadata locked!
+
+ Check whether a auth metadata structure can be decoded by the current
+ version of AuthMetadataManager.
+
+ Return auth metadata that the current version of AuthMetadataManager
+ can decode.
+ """
+ auth_metadata = self._metadata_get(self._auth_metadata_path(auth_id))
+
+ if auth_metadata:
+ self._check_compat_version(auth_metadata['compat_version'])
+
+ return auth_metadata
+
+ def auth_metadata_set(self, auth_id, data):
+ """
+ Call me with the metadata locked!
+
+ Fsync the auth metadata.
+
+ Add two version attributes to the auth metadata,
+ 'compat_version', the minimum AuthMetadataManager version that can
+ decode the metadata, and 'version', the AuthMetadataManager version
+ that encoded the metadata.
+ """
+ data['compat_version'] = 6
+ data['version'] = self.version
+ return self._metadata_set(self._auth_metadata_path(auth_id), data)
+
+ def create_subvolume_metadata_file(self, group_name, subvol_name):
+ """
+ Create a subvolume metadata file, if it does not already exist, to store
+ data about auth ids having access to the subvolume
+ """
+ fd = self.fs.open(self._subvolume_metadata_path(group_name, subvol_name),
+ os.O_CREAT, 0o755)
+ self.fs.close(fd)
+
+ def delete_subvolume_metadata_file(self, group_name, subvol_name):
+ vol_meta_path = self._subvolume_metadata_path(group_name, subvol_name)
+ try:
+ self.fs.unlink(vol_meta_path)
+ except cephfs.ObjectNotFound:
+ pass
+
+ def subvol_metadata_lock(self, group_name, subvol_name):
+ """
+ Return a ContextManager which locks the authorization metadata for
+ a particular subvolume, and persists a flag to the metadata indicating
+ that it is currently locked, so that we can detect dirty situations
+ during recovery.
+
+ This lock isn't just to make access to the metadata safe: it's also
+ designed to be used over the two-step process of checking the
+ metadata and then responding to an authorization request, to
+ ensure that at the point we respond the metadata hasn't changed
+ in the background. It's key to how we avoid security holes
+ resulting from races during that problem ,
+ """
+ return self._lock(self._subvolume_metadata_path(group_name, subvol_name))
+
+ def subvol_metadata_get(self, group_name, subvol_name):
+ """
+ Call me with the metadata locked!
+
+ Check whether a subvolume metadata structure can be decoded by the current
+ version of AuthMetadataManager.
+
+ Return a subvolume_metadata structure that the current version of
+ AuthMetadataManager can decode.
+ """
+ subvolume_metadata = self._metadata_get(self._subvolume_metadata_path(group_name, subvol_name))
+
+ if subvolume_metadata:
+ self._check_compat_version(subvolume_metadata['compat_version'])
+
+ return subvolume_metadata
+
+ def subvol_metadata_set(self, group_name, subvol_name, data):
+ """
+ Call me with the metadata locked!
+
+ Add two version attributes to the subvolume metadata,
+ 'compat_version', the minimum AuthMetadataManager version that can
+ decode the metadata and 'version', the AuthMetadataManager version
+ that encoded the metadata.
+ """
+ data['compat_version'] = 1
+ data['version'] = self.version
+ return self._metadata_set(self._subvolume_metadata_path(group_name, subvol_name), data)
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
new file mode 100644
index 00000000..1b6c4327
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py
@@ -0,0 +1,144 @@
+import os
+import errno
+import logging
+import sys
+
+if sys.version_info >= (3, 2):
+ import configparser
+else:
+ import ConfigParser as configparser
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+import cephfs
+
+from ...exception import MetadataMgrException
+
+log = logging.getLogger(__name__)
+
+class MetadataManager(object):
+ GLOBAL_SECTION = "GLOBAL"
+ GLOBAL_META_KEY_VERSION = "version"
+ GLOBAL_META_KEY_TYPE = "type"
+ GLOBAL_META_KEY_PATH = "path"
+ GLOBAL_META_KEY_STATE = "state"
+
+ MAX_IO_BYTES = 8 * 1024
+
+ def __init__(self, fs, config_path, mode):
+ self.fs = fs
+ self.mode = mode
+ self.config_path = config_path
+ if sys.version_info >= (3, 2):
+ self.config = configparser.ConfigParser()
+ else:
+ self.config = configparser.SafeConfigParser()
+
+ def refresh(self):
+ fd = None
+ conf_data = StringIO()
+ try:
+ log.debug("opening config {0}".format(self.config_path))
+ fd = self.fs.open(self.config_path, os.O_RDONLY)
+ while True:
+ data = self.fs.read(fd, -1, MetadataManager.MAX_IO_BYTES)
+ if not len(data):
+ break
+ conf_data.write(data.decode('utf-8'))
+ conf_data.seek(0)
+ self.config.readfp(conf_data)
+ except cephfs.ObjectNotFound:
+ raise MetadataMgrException(-errno.ENOENT, "metadata config '{0}' not found".format(self.config_path))
+ except cephfs.Error as e:
+ raise MetadataMgrException(-e.args[0], e.args[1])
+ finally:
+ if fd is not None:
+ self.fs.close(fd)
+
+ def flush(self):
+ # cull empty sections
+ for section in list(self.config.sections()):
+ if len(self.config.items(section)) == 0:
+ self.config.remove_section(section)
+
+ conf_data = StringIO()
+ self.config.write(conf_data)
+ conf_data.seek(0)
+
+ fd = None
+ try:
+ fd = self.fs.open(self.config_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, self.mode)
+ wrote = 0
+ while True:
+ data = conf_data.read()
+ if not len(data):
+ break
+ wrote += self.fs.write(fd, data.encode('utf-8'), -1)
+ self.fs.fsync(fd, 0)
+ log.info("wrote {0} bytes to config {1}".format(wrote, self.config_path))
+ except cephfs.Error as e:
+ raise MetadataMgrException(-e.args[0], e.args[1])
+ finally:
+ if fd is not None:
+ self.fs.close(fd)
+
+ def init(self, version, typ, path, state):
+ # you may init just once before refresh (helps to overwrite conf)
+ if self.config.has_section(MetadataManager.GLOBAL_SECTION):
+ raise MetadataMgrException(-errno.EINVAL, "init called on an existing config")
+
+ self.add_section(MetadataManager.GLOBAL_SECTION)
+ self.update_section_multi(
+ MetadataManager.GLOBAL_SECTION, {MetadataManager.GLOBAL_META_KEY_VERSION : str(version),
+ MetadataManager.GLOBAL_META_KEY_TYPE : str(typ),
+ MetadataManager.GLOBAL_META_KEY_PATH : str(path),
+ MetadataManager.GLOBAL_META_KEY_STATE : str(state)
+ })
+
+ def add_section(self, section):
+ try:
+ self.config.add_section(section)
+ except configparser.DuplicateSectionError:
+ return
+ except:
+ raise MetadataMgrException(-errno.EINVAL, "error adding section to config")
+
+ def remove_option(self, section, key):
+ if not self.config.has_section(section):
+ raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section))
+ self.config.remove_option(section, key)
+
+ def remove_section(self, section):
+ self.config.remove_section(section)
+
+ def update_section(self, section, key, value):
+ if not self.config.has_section(section):
+ raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section))
+ self.config.set(section, key, str(value))
+
+ def update_section_multi(self, section, dct):
+ if not self.config.has_section(section):
+ raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section))
+ for key,value in dct.items():
+ self.config.set(section, key, str(value))
+
+ def update_global_section(self, key, value):
+ self.update_section(MetadataManager.GLOBAL_SECTION, key, str(value))
+
+ def get_option(self, section, key):
+ if not self.config.has_section(section):
+ raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section))
+ if not self.config.has_option(section, key):
+ raise MetadataMgrException(-errno.ENOENT, "no config '{0}' in section '{1}'".format(key, section))
+ return self.config.get(section, key)
+
+ def get_global_option(self, key):
+ return self.get_option(MetadataManager.GLOBAL_SECTION, key)
+
+ def section_has_item(self, section, item):
+ if not self.config.has_section(section):
+ raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section))
+ return item in [v[1] for v in self.config.items(section)]
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/op_sm.py b/src/pybind/mgr/volumes/fs/operations/versions/op_sm.py
new file mode 100644
index 00000000..c2b5f582
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/op_sm.py
@@ -0,0 +1,114 @@
+import errno
+
+from enum import Enum, unique
+
+from ...exception import OpSmException
+from .subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeActions
+
+class TransitionKey(object):
+ def __init__(self, subvol_type, state, action_type):
+ self.transition_key = [subvol_type, state, action_type]
+
+ def __hash__(self):
+ return hash(tuple(self.transition_key))
+
+ def __eq__(self, other):
+ return self.transition_key == other.transition_key
+
+ def __neq__(self, other):
+ return not(self == other)
+
+class SubvolumeOpSm(object):
+ transition_table = {}
+
+ @staticmethod
+ def is_complete_state(state):
+ if not isinstance(state, SubvolumeStates):
+ raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
+ return state == SubvolumeStates.STATE_COMPLETE
+
+ @staticmethod
+ def is_failed_state(state):
+ if not isinstance(state, SubvolumeStates):
+ raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
+ return state == SubvolumeStates.STATE_FAILED or state == SubvolumeStates.STATE_CANCELED
+
+ @staticmethod
+ def is_init_state(stm_type, state):
+ if not isinstance(state, SubvolumeStates):
+ raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
+ return state == SubvolumeOpSm.get_init_state(stm_type)
+
+ @staticmethod
+ def get_init_state(stm_type):
+ if not isinstance(stm_type, SubvolumeTypes):
+ raise OpSmException(-errno.EINVAL, "unknown state machine '{0}'".format(stm_type))
+ init_state = SubvolumeOpSm.transition_table[TransitionKey(stm_type,
+ SubvolumeStates.STATE_INIT,
+ SubvolumeActions.ACTION_NONE)]
+ if not init_state:
+ raise OpSmException(-errno.ENOENT, "initial state for state machine '{0}' not found".format(stm_type))
+ return init_state
+
+ @staticmethod
+ def transition(stm_type, current_state, action):
+ if not isinstance(stm_type, SubvolumeTypes):
+ raise OpSmException(-errno.EINVAL, "unknown state machine '{0}'".format(stm_type))
+ if not isinstance(current_state, SubvolumeStates):
+ raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(current_state))
+ if not isinstance(action, SubvolumeActions):
+ raise OpSmException(-errno.EINVAL, "unknown action '{0}'".format(action))
+
+ transition = SubvolumeOpSm.transition_table[TransitionKey(stm_type, current_state, action)]
+ if not transition:
+ raise OpSmException(-errno.EINVAL, "invalid action '{0}' on current state {1} for state machine '{2}'".format(action, current_state, stm_type))
+
+ return transition
+
+SubvolumeOpSm.transition_table = {
+ # state transitions for state machine type TYPE_NORMAL
+ TransitionKey(SubvolumeTypes.TYPE_NORMAL,
+ SubvolumeStates.STATE_INIT,
+ SubvolumeActions.ACTION_NONE) : SubvolumeStates.STATE_COMPLETE,
+
+ TransitionKey(SubvolumeTypes.TYPE_NORMAL,
+ SubvolumeStates.STATE_COMPLETE,
+ SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,
+
+ # state transitions for state machine type TYPE_CLONE
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INIT,
+ SubvolumeActions.ACTION_NONE) : SubvolumeStates.STATE_PENDING,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_PENDING,
+ SubvolumeActions.ACTION_SUCCESS) : SubvolumeStates.STATE_INPROGRESS,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_PENDING,
+ SubvolumeActions.ACTION_CANCELLED) : SubvolumeStates.STATE_CANCELED,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_SUCCESS) : SubvolumeStates.STATE_COMPLETE,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_CANCELLED) : SubvolumeStates.STATE_CANCELED,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_INPROGRESS,
+ SubvolumeActions.ACTION_FAILED) : SubvolumeStates.STATE_FAILED,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_COMPLETE,
+ SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_CANCELED,
+ SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,
+
+ TransitionKey(SubvolumeTypes.TYPE_CLONE,
+ SubvolumeStates.STATE_FAILED,
+ SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,
+}
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_attrs.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_attrs.py
new file mode 100644
index 00000000..ec7138cb
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_attrs.py
@@ -0,0 +1,61 @@
+import errno
+from enum import Enum, unique
+
+from ...exception import VolumeException
+
+@unique
+class SubvolumeTypes(Enum):
+ TYPE_NORMAL = "subvolume"
+ TYPE_CLONE = "clone"
+
+ @staticmethod
+ def from_value(value):
+ if value == "subvolume":
+ return SubvolumeTypes.TYPE_NORMAL
+ if value == "clone":
+ return SubvolumeTypes.TYPE_CLONE
+
+ raise VolumeException(-errno.EINVAL, "invalid subvolume type '{0}'".format(value))
+
+@unique
+class SubvolumeStates(Enum):
+ STATE_INIT = 'init'
+ STATE_PENDING = 'pending'
+ STATE_INPROGRESS = 'in-progress'
+ STATE_FAILED = 'failed'
+ STATE_COMPLETE = 'complete'
+ STATE_CANCELED = 'canceled'
+ STATE_RETAINED = 'snapshot-retained'
+
+ @staticmethod
+ def from_value(value):
+ if value == "init":
+ return SubvolumeStates.STATE_INIT
+ if value == "pending":
+ return SubvolumeStates.STATE_PENDING
+ if value == "in-progress":
+ return SubvolumeStates.STATE_INPROGRESS
+ if value == "failed":
+ return SubvolumeStates.STATE_FAILED
+ if value == "complete":
+ return SubvolumeStates.STATE_COMPLETE
+ if value == "canceled":
+ return SubvolumeStates.STATE_CANCELED
+ if value == "snapshot-retained":
+ return SubvolumeStates.STATE_RETAINED
+
+ raise VolumeException(-errno.EINVAL, "invalid state '{0}'".format(value))
+
+@unique
+class SubvolumeActions(Enum):
+ ACTION_NONE = 0
+ ACTION_SUCCESS = 1
+ ACTION_FAILED = 2
+ ACTION_CANCELLED = 3
+ ACTION_RETAINED = 4
+
+@unique
+class SubvolumeFeatures(Enum):
+ FEATURE_SNAPSHOT_CLONE = "snapshot-clone"
+ FEATURE_SNAPSHOT_RETENTION = "snapshot-retention"
+ FEATURE_SNAPSHOT_AUTOPROTECT = "snapshot-autoprotect"
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
new file mode 100644
index 00000000..f193dabd
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
@@ -0,0 +1,331 @@
+import os
+import stat
+import uuid
+import errno
+import logging
+from hashlib import md5
+
+import cephfs
+
+from .subvolume_attrs import SubvolumeTypes, SubvolumeStates
+from .metadata_manager import MetadataManager
+from ..trash import create_trashcan, open_trashcan
+from ...fs_util import get_ancestor_xattr
+from ...exception import MetadataMgrException, VolumeException
+from .op_sm import SubvolumeOpSm
+from .auth_metadata import AuthMetadataManager
+
+log = logging.getLogger(__name__)
+
+class SubvolumeBase(object):
+ LEGACY_CONF_DIR = "_legacy"
+
+ def __init__(self, mgr, fs, vol_spec, group, subvolname, legacy=False):
+ self.mgr = mgr
+ self.fs = fs
+ self.auth_mdata_mgr = AuthMetadataManager(fs)
+ self.cmode = None
+ self.user_id = None
+ self.group_id = None
+ self.vol_spec = vol_spec
+ self.group = group
+ self.subvolname = subvolname
+ self.legacy_mode = legacy
+ self.load_config()
+
+ @property
+ def uid(self):
+ return self.user_id
+
+ @uid.setter
+ def uid(self, val):
+ self.user_id = val
+
+ @property
+ def gid(self):
+ return self.group_id
+
+ @gid.setter
+ def gid(self, val):
+ self.group_id = val
+
+ @property
+ def mode(self):
+ return self.cmode
+
+ @mode.setter
+ def mode(self, val):
+ self.cmode = val
+
+ @property
+ def base_path(self):
+ return os.path.join(self.group.path, self.subvolname.encode('utf-8'))
+
+ @property
+ def config_path(self):
+ return os.path.join(self.base_path, b".meta")
+
+ @property
+ def legacy_dir(self):
+ return os.path.join(self.vol_spec.base_dir.encode('utf-8'), SubvolumeBase.LEGACY_CONF_DIR.encode('utf-8'))
+
+ @property
+ def legacy_config_path(self):
+ m = md5()
+ m.update(self.base_path)
+ meta_config = "{0}.meta".format(m.hexdigest())
+ return os.path.join(self.legacy_dir, meta_config.encode('utf-8'))
+
+ @property
+ def namespace(self):
+ return "{0}{1}".format(self.vol_spec.fs_namespace, self.subvolname)
+
+ @property
+ def group_name(self):
+ return self.group.group_name
+
+ @property
+ def subvol_name(self):
+ return self.subvolname
+
+ @property
+ def legacy_mode(self):
+ return self.legacy
+
+ @legacy_mode.setter
+ def legacy_mode(self, mode):
+ self.legacy = mode
+
+ @property
+ def path(self):
+ """ Path to subvolume data directory """
+ raise NotImplementedError
+
+ @property
+ def features(self):
+ """ List of features supported by the subvolume, containing items from SubvolumeFeatures """
+ raise NotImplementedError
+
+ @property
+ def state(self):
+ """ Subvolume state, one of SubvolumeStates """
+ raise NotImplementedError
+
+ @property
+ def subvol_type(self):
+ return SubvolumeTypes.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_TYPE))
+
+ @property
+ def purgeable(self):
+ """ Boolean declaring if subvolume can be purged """
+ raise NotImplementedError
+
+ def load_config(self):
+ if self.legacy_mode:
+ self.metadata_mgr = MetadataManager(self.fs, self.legacy_config_path, 0o640)
+ else:
+ self.metadata_mgr = MetadataManager(self.fs, self.config_path, 0o640)
+
+ def get_attrs(self, pathname):
+ # get subvolume attributes
+ attrs = {}
+ stx = self.fs.statx(pathname,
+ cephfs.CEPH_STATX_UID | cephfs.CEPH_STATX_GID | cephfs.CEPH_STATX_MODE,
+ cephfs.AT_SYMLINK_NOFOLLOW)
+
+ attrs["uid"] = int(stx["uid"])
+ attrs["gid"] = int(stx["gid"])
+ attrs["mode"] = int(int(stx["mode"]) & ~stat.S_IFMT(stx["mode"]))
+
+ try:
+ attrs["data_pool"] = self.fs.getxattr(pathname, 'ceph.dir.layout.pool').decode('utf-8')
+ except cephfs.NoData:
+ attrs["data_pool"] = None
+
+ try:
+ attrs["pool_namespace"] = self.fs.getxattr(pathname, 'ceph.dir.layout.pool_namespace').decode('utf-8')
+ except cephfs.NoData:
+ attrs["pool_namespace"] = None
+
+ try:
+ attrs["quota"] = int(self.fs.getxattr(pathname, 'ceph.quota.max_bytes').decode('utf-8'))
+ except cephfs.NoData:
+ attrs["quota"] = None
+
+ return attrs
+
+ def set_attrs(self, path, attrs):
+ # set subvolume attributes
+ # set size
+ quota = attrs.get("quota")
+ if quota is not None:
+ try:
+ self.fs.setxattr(path, 'ceph.quota.max_bytes', str(quota).encode('utf-8'), 0)
+ except cephfs.InvalidValue as e:
+ raise VolumeException(-errno.EINVAL, "invalid size specified: '{0}'".format(quota))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ # set pool layout
+ data_pool = attrs.get("data_pool")
+ if data_pool is not None:
+ try:
+ self.fs.setxattr(path, 'ceph.dir.layout.pool', data_pool.encode('utf-8'), 0)
+ except cephfs.InvalidValue:
+ raise VolumeException(-errno.EINVAL,
+ "invalid pool layout '{0}' -- need a valid data pool".format(data_pool))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ # isolate namespace
+ xattr_key = xattr_val = None
+ pool_namespace = attrs.get("pool_namespace")
+ if pool_namespace is not None:
+ # enforce security isolation, use separate namespace for this subvolume
+ xattr_key = 'ceph.dir.layout.pool_namespace'
+ xattr_val = pool_namespace
+ elif not data_pool:
+ # If subvolume's namespace layout is not set, then the subvolume's pool
+ # layout remains unset and will undesirably change with ancestor's
+ # pool layout changes.
+ xattr_key = 'ceph.dir.layout.pool'
+ xattr_val = None
+ try:
+ self.fs.getxattr(path, 'ceph.dir.layout.pool').decode('utf-8')
+ except cephfs.NoData as e:
+ xattr_val = get_ancestor_xattr(self.fs, os.path.split(path)[0], "ceph.dir.layout.pool")
+ if xattr_key and xattr_val:
+ try:
+ self.fs.setxattr(path, xattr_key, xattr_val.encode('utf-8'), 0)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ # set uid/gid
+ uid = attrs.get("uid")
+ if uid is None:
+ uid = self.group.uid
+ else:
+ try:
+ uid = int(uid)
+ if uid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid UID")
+
+ gid = attrs.get("gid")
+ if gid is None:
+ gid = self.group.gid
+ else:
+ try:
+ gid = int(gid)
+ if gid < 0:
+ raise ValueError
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "invalid GID")
+
+ if uid is not None and gid is not None:
+ self.fs.chown(path, uid, gid)
+
+ def _resize(self, path, newsize, noshrink):
+ try:
+ newsize = int(newsize)
+ if newsize <= 0:
+ raise VolumeException(-errno.EINVAL, "Invalid subvolume size")
+ except ValueError:
+ newsize = newsize.lower()
+ if not (newsize == "inf" or newsize == "infinite"):
+ raise VolumeException(-errno.EINVAL, "invalid size option '{0}'".format(newsize))
+ newsize = 0
+ noshrink = False
+
+ try:
+ maxbytes = int(self.fs.getxattr(path, 'ceph.quota.max_bytes').decode('utf-8'))
+ except cephfs.NoData:
+ maxbytes = 0
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ subvolstat = self.fs.stat(path)
+ if newsize > 0 and newsize < subvolstat.st_size:
+ if noshrink:
+ raise VolumeException(-errno.EINVAL, "Can't resize the subvolume. The new size '{0}' would be lesser than the current "
+ "used size '{1}'".format(newsize, subvolstat.st_size))
+
+ if not newsize == maxbytes:
+ try:
+ self.fs.setxattr(path, 'ceph.quota.max_bytes', str(newsize).encode('utf-8'), 0)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], "Cannot set new size for the subvolume. '{0}'".format(e.args[1]))
+ return newsize, subvolstat.st_size
+
+ def init_config(self, version, subvolume_type, subvolume_path, subvolume_state):
+ self.metadata_mgr.init(version, subvolume_type.value, subvolume_path, subvolume_state.value)
+ self.metadata_mgr.flush()
+
+ def discover(self):
+ log.debug("discovering subvolume '{0}' [mode: {1}]".format(self.subvolname, "legacy" if self.legacy_mode else "new"))
+ try:
+ self.fs.stat(self.base_path)
+ self.metadata_mgr.refresh()
+ log.debug("loaded subvolume '{0}'".format(self.subvolname))
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT and not self.legacy_mode:
+ self.legacy_mode = True
+ self.load_config()
+ self.discover()
+ else:
+ raise
+ except cephfs.Error as e:
+ if e.args[0] == errno.ENOENT:
+ raise VolumeException(-errno.ENOENT, "subvolume '{0}' does not exist".format(self.subvolname))
+ raise VolumeException(-e.args[0], "error accessing subvolume '{0}'".format(self.subvolname))
+
+ def _trash_dir(self, path):
+ create_trashcan(self.fs, self.vol_spec)
+ with open_trashcan(self.fs, self.vol_spec) as trashcan:
+ trashcan.dump(path)
+ log.info("subvolume path '{0}' moved to trashcan".format(path))
+
+ def _link_dir(self, path, bname):
+ create_trashcan(self.fs, self.vol_spec)
+ with open_trashcan(self.fs, self.vol_spec) as trashcan:
+ trashcan.link(path, bname)
+ log.info("subvolume path '{0}' linked in trashcan bname {1}".format(path, bname))
+
+ def trash_base_dir(self):
+ if self.legacy_mode:
+ self.fs.unlink(self.legacy_config_path)
+ self._trash_dir(self.base_path)
+
+ def create_base_dir(self, mode):
+ try:
+ self.fs.mkdirs(self.base_path, mode)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def info (self):
+ subvolpath = self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_PATH)
+ etype = self.subvol_type
+ st = self.fs.statx(subvolpath, cephfs.CEPH_STATX_BTIME | cephfs.CEPH_STATX_SIZE |
+ cephfs.CEPH_STATX_UID | cephfs.CEPH_STATX_GID |
+ cephfs.CEPH_STATX_MODE | cephfs.CEPH_STATX_ATIME |
+ cephfs.CEPH_STATX_MTIME | cephfs.CEPH_STATX_CTIME,
+ cephfs.AT_SYMLINK_NOFOLLOW)
+ usedbytes = st["size"]
+ try:
+ nsize = int(self.fs.getxattr(subvolpath, 'ceph.quota.max_bytes').decode('utf-8'))
+ except cephfs.NoData:
+ nsize = 0
+
+ try:
+ data_pool = self.fs.getxattr(subvolpath, 'ceph.dir.layout.pool').decode('utf-8')
+ pool_namespace = self.fs.getxattr(subvolpath, 'ceph.dir.layout.pool_namespace').decode('utf-8')
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ return {'path': subvolpath, 'type': etype.value, 'uid': int(st["uid"]), 'gid': int(st["gid"]),
+ 'atime': str(st["atime"]), 'mtime': str(st["mtime"]), 'ctime': str(st["ctime"]),
+ 'mode': int(st["mode"]), 'data_pool': data_pool, 'created_at': str(st["btime"]),
+ 'bytes_quota': "infinite" if nsize == 0 else nsize, 'bytes_used': int(usedbytes),
+ 'bytes_pcent': "undefined" if nsize == 0 else '{0:.2f}'.format((float(usedbytes) / nsize) * 100.0),
+ 'pool_namespace': pool_namespace, 'features': self.features, 'state': self.state.value}
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
new file mode 100644
index 00000000..b4cca736
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py
@@ -0,0 +1,780 @@
+import os
+import sys
+import stat
+import uuid
+import errno
+import logging
+import json
+from datetime import datetime
+try:
+ from typing import List, Dict
+except ImportError:
+ pass # For typing only
+
+import cephfs
+
+from .metadata_manager import MetadataManager
+from .subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeFeatures
+from .op_sm import SubvolumeOpSm
+from .subvolume_base import SubvolumeBase
+from ..template import SubvolumeTemplate
+from ..snapshot_util import mksnap, rmsnap
+from ..access import allow_access, deny_access
+from ...exception import IndexException, OpSmException, VolumeException, MetadataMgrException, EvictionError
+from ...fs_util import listsnaps, is_inherited_snap
+from ..template import SubvolumeOpType
+from ..group import Group
+from ..rankevicter import RankEvicter
+from ..volume import get_mds_map
+
+from ..clone_index import open_clone_index, create_clone_index
+
+log = logging.getLogger(__name__)
+
+class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
+ """
+ Version 1 subvolumes creates a subvolume with path as follows,
+ volumes/<group-name>/<subvolume-name>/<uuid>/
+
+ - The directory under which user data resides is <uuid>
+ - Snapshots of the subvolume are taken within the <uuid> directory
+ - A meta file is maintained under the <subvolume-name> directory as a metadata store, typically storing,
+ - global information about the subvolume (version, path, type, state)
+ - snapshots attached to an ongoing clone operation
+ - clone snapshot source if subvolume is a clone of a snapshot
+ - It retains backward compatability with legacy subvolumes by creating the meta file for legacy subvolumes under
+ /volumes/_legacy/ (see legacy_config_path), thus allowing cloning of older legacy volumes that lack the <uuid>
+ component in the path.
+ """
+ VERSION = 1
+
+ @staticmethod
+ def version():
+ return SubvolumeV1.VERSION
+
+ @property
+ def path(self):
+ try:
+ # no need to stat the path -- open() does that
+ return self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_PATH).encode('utf-8')
+ except MetadataMgrException as me:
+ raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
+
+ @property
+ def features(self):
+ return [SubvolumeFeatures.FEATURE_SNAPSHOT_CLONE.value, SubvolumeFeatures.FEATURE_SNAPSHOT_AUTOPROTECT.value]
+
+ def mark_subvolume(self):
+ # set subvolume attr, on subvolume root, marking it as a CephFS subvolume
+ # subvolume root is where snapshots would be taken, and hence is the <uuid> dir for v1 subvolumes
+ try:
+ # MDS treats this as a noop for already marked subvolume
+ self.fs.setxattr(self.path, 'ceph.dir.subvolume', b'1', 0)
+ except cephfs.InvalidValue as e:
+ raise VolumeException(-errno.EINVAL, "invalid value specified for ceph.dir.subvolume")
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def snapshot_base_path(self):
+ """ Base path for all snapshots """
+ return os.path.join(self.path, self.vol_spec.snapshot_dir_prefix.encode('utf-8'))
+
+ def snapshot_path(self, snapname):
+ """ Path to a specific snapshot named 'snapname' """
+ return os.path.join(self.snapshot_base_path(), snapname.encode('utf-8'))
+
+ def snapshot_data_path(self, snapname):
+ """ Path to user data directory within a subvolume snapshot named 'snapname' """
+ return self.snapshot_path(snapname)
+
+ def create(self, size, isolate_nspace, pool, mode, uid, gid):
+ subvolume_type = SubvolumeTypes.TYPE_NORMAL
+ try:
+ initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
+ except OpSmException as oe:
+ raise VolumeException(-errno.EINVAL, "subvolume creation failed: internal error")
+
+ subvol_path = os.path.join(self.base_path, str(uuid.uuid4()).encode('utf-8'))
+ try:
+ # create directory and set attributes
+ self.fs.mkdirs(subvol_path, mode)
+ self.mark_subvolume()
+ attrs = {
+ 'uid': uid,
+ 'gid': gid,
+ 'data_pool': pool,
+ 'pool_namespace': self.namespace if isolate_nspace else None,
+ 'quota': size
+ }
+ self.set_attrs(subvol_path, attrs)
+
+ # persist subvolume metadata
+ qpath = subvol_path.decode('utf-8')
+ self.init_config(SubvolumeV1.VERSION, subvolume_type, qpath, initial_state)
+ except (VolumeException, MetadataMgrException, cephfs.Error) as e:
+ try:
+ log.info("cleaning up subvolume with path: {0}".format(self.subvolname))
+ self.remove()
+ except VolumeException as ve:
+ log.info("failed to cleanup subvolume '{0}' ({1})".format(self.subvolname, ve))
+
+ if isinstance(e, MetadataMgrException):
+ log.error("metadata manager exception: {0}".format(e))
+ e = VolumeException(-errno.EINVAL, "exception in subvolume metadata")
+ elif isinstance(e, cephfs.Error):
+ e = VolumeException(-e.args[0], e.args[1])
+ raise e
+
+ def add_clone_source(self, volname, subvolume, snapname, flush=False):
+ self.metadata_mgr.add_section("source")
+ self.metadata_mgr.update_section("source", "volume", volname)
+ if not subvolume.group.is_default_group():
+ self.metadata_mgr.update_section("source", "group", subvolume.group_name)
+ self.metadata_mgr.update_section("source", "subvolume", subvolume.subvol_name)
+ self.metadata_mgr.update_section("source", "snapshot", snapname)
+ if flush:
+ self.metadata_mgr.flush()
+
+ def remove_clone_source(self, flush=False):
+ self.metadata_mgr.remove_section("source")
+ if flush:
+ self.metadata_mgr.flush()
+
+ def create_clone(self, pool, source_volname, source_subvolume, snapname):
+ subvolume_type = SubvolumeTypes.TYPE_CLONE
+ try:
+ initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
+ except OpSmException as oe:
+ raise VolumeException(-errno.EINVAL, "clone failed: internal error")
+
+ subvol_path = os.path.join(self.base_path, str(uuid.uuid4()).encode('utf-8'))
+ try:
+ # source snapshot attrs are used to create clone subvolume.
+ # attributes of subvolume's content though, are synced during the cloning process.
+ attrs = source_subvolume.get_attrs(source_subvolume.snapshot_data_path(snapname))
+
+ # override snapshot pool setting, if one is provided for the clone
+ if pool is not None:
+ attrs["data_pool"] = pool
+ attrs["pool_namespace"] = None
+
+ # create directory and set attributes
+ self.fs.mkdirs(subvol_path, attrs.get("mode"))
+ self.mark_subvolume()
+ self.set_attrs(subvol_path, attrs)
+
+ # persist subvolume metadata and clone source
+ qpath = subvol_path.decode('utf-8')
+ self.metadata_mgr.init(SubvolumeV1.VERSION, subvolume_type.value, qpath, initial_state.value)
+ self.add_clone_source(source_volname, source_subvolume, snapname)
+ self.metadata_mgr.flush()
+ except (VolumeException, MetadataMgrException, cephfs.Error) as e:
+ try:
+ log.info("cleaning up subvolume with path: {0}".format(self.subvolname))
+ self.remove()
+ except VolumeException as ve:
+ log.info("failed to cleanup subvolume '{0}' ({1})".format(self.subvolname, ve))
+
+ if isinstance(e, MetadataMgrException):
+ log.error("metadata manager exception: {0}".format(e))
+ e = VolumeException(-errno.EINVAL, "exception in subvolume metadata")
+ elif isinstance(e, cephfs.Error):
+ e = VolumeException(-e.args[0], e.args[1])
+ raise e
+
+ def allowed_ops_by_type(self, vol_type):
+ if vol_type == SubvolumeTypes.TYPE_CLONE:
+ return {op_type for op_type in SubvolumeOpType}
+
+ if vol_type == SubvolumeTypes.TYPE_NORMAL:
+ return {op_type for op_type in SubvolumeOpType} - {SubvolumeOpType.CLONE_STATUS,
+ SubvolumeOpType.CLONE_CANCEL,
+ SubvolumeOpType.CLONE_INTERNAL}
+
+ return {}
+
+ def allowed_ops_by_state(self, vol_state):
+ if vol_state == SubvolumeStates.STATE_COMPLETE:
+ return {op_type for op_type in SubvolumeOpType}
+
+ return {SubvolumeOpType.REMOVE_FORCE,
+ SubvolumeOpType.CLONE_CREATE,
+ SubvolumeOpType.CLONE_STATUS,
+ SubvolumeOpType.CLONE_CANCEL,
+ SubvolumeOpType.CLONE_INTERNAL}
+
+ def open(self, op_type):
+ if not isinstance(op_type, SubvolumeOpType):
+ raise VolumeException(-errno.ENOTSUP, "operation {0} not supported on subvolume '{1}'".format(
+ op_type.value, self.subvolname))
+ try:
+ self.metadata_mgr.refresh()
+
+ etype = self.subvol_type
+ if op_type not in self.allowed_ops_by_type(etype):
+ raise VolumeException(-errno.ENOTSUP, "operation '{0}' is not allowed on subvolume '{1}' of type {2}".format(
+ op_type.value, self.subvolname, etype.value))
+
+ estate = self.state
+ if op_type not in self.allowed_ops_by_state(estate):
+ raise VolumeException(-errno.EAGAIN, "subvolume '{0}' is not ready for operation {1}".format(
+ self.subvolname, op_type.value))
+
+ subvol_path = self.path
+ log.debug("refreshed metadata, checking subvolume path '{0}'".format(subvol_path))
+ st = self.fs.stat(subvol_path)
+ # unconditionally mark as subvolume, to handle pre-existing subvolumes without the mark
+ self.mark_subvolume()
+
+ self.uid = int(st.st_uid)
+ self.gid = int(st.st_gid)
+ self.mode = int(st.st_mode & ~stat.S_IFMT(st.st_mode))
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT:
+ raise VolumeException(-errno.ENOENT, "subvolume '{0}' does not exist".format(self.subvolname))
+ raise VolumeException(me.args[0], me.args[1])
+ except cephfs.ObjectNotFound:
+ log.debug("missing subvolume path '{0}' for subvolume '{1}'".format(subvol_path, self.subvolname))
+ raise VolumeException(-errno.ENOENT, "mount path missing for subvolume '{0}'".format(self.subvolname))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def _recover_auth_meta(self, auth_id, auth_meta):
+ """
+ Call me after locking the auth meta file.
+ """
+ remove_subvolumes = []
+
+ for subvol, subvol_data in auth_meta['subvolumes'].items():
+ if not subvol_data['dirty']:
+ continue
+
+ (group_name, subvol_name) = subvol.split('/')
+ group_name = group_name if group_name != 'None' else Group.NO_GROUP_NAME
+ access_level = subvol_data['access_level']
+
+ with self.auth_mdata_mgr.subvol_metadata_lock(group_name, subvol_name):
+ subvol_meta = self.auth_mdata_mgr.subvol_metadata_get(group_name, subvol_name)
+
+ # No SVMeta update indicates that there was no auth update
+ # in Ceph either. So it's safe to remove corresponding
+ # partial update in AMeta.
+ if not subvol_meta or auth_id not in subvol_meta['auths']:
+ remove_subvolumes.append(subvol)
+ continue
+
+ want_auth = {
+ 'access_level': access_level,
+ 'dirty': False,
+ }
+ # SVMeta update looks clean. Ceph auth update must have been
+ # clean. Update the dirty flag and continue
+ if subvol_meta['auths'][auth_id] == want_auth:
+ auth_meta['subvolumes'][subvol]['dirty'] = False
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+ continue
+
+ client_entity = "client.{0}".format(auth_id)
+ ret, out, err = self.mgr.mon_command(
+ {
+ 'prefix': 'auth get',
+ 'entity': client_entity,
+ 'format': 'json'
+ })
+ if ret == 0:
+ existing_caps = json.loads(out)
+ elif ret == -errno.ENOENT:
+ existing_caps = None
+ else:
+ log.error(err)
+ raise VolumeException(ret, err)
+
+ self._authorize_subvolume(auth_id, access_level, existing_caps)
+
+ # Recovered from partial auth updates for the auth ID's access
+ # to a subvolume.
+ auth_meta['subvolumes'][subvol]['dirty'] = False
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ for subvol in remove_subvolumes:
+ del auth_meta['subvolumes'][subvol]
+
+ if not auth_meta['subvolumes']:
+ # Clean up auth meta file
+ self.fs.unlink(self.auth_mdata_mgr._auth_metadata_path(auth_id))
+ return
+
+ # Recovered from all partial auth updates for the auth ID.
+ auth_meta['dirty'] = False
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ def authorize(self, auth_id, access_level, tenant_id=None, allow_existing_id=False):
+ """
+ Get-or-create a Ceph auth identity for `auth_id` and grant them access
+ to
+ :param auth_id:
+ :param access_level:
+ :param tenant_id: Optionally provide a stringizable object to
+ restrict any created cephx IDs to other callers
+ passing the same tenant ID.
+ :allow_existing_id: Optionally authorize existing auth-ids not
+ created by ceph_volume_client.
+ :return:
+ """
+
+ with self.auth_mdata_mgr.auth_lock(auth_id):
+ client_entity = "client.{0}".format(auth_id)
+ ret, out, err = self.mgr.mon_command(
+ {
+ 'prefix': 'auth get',
+ 'entity': client_entity,
+ 'format': 'json'
+ })
+
+ if ret == 0:
+ existing_caps = json.loads(out)
+ elif ret == -errno.ENOENT:
+ existing_caps = None
+ else:
+ log.error(err)
+ raise VolumeException(ret, err)
+
+ # Existing meta, or None, to be updated
+ auth_meta = self.auth_mdata_mgr.auth_metadata_get(auth_id)
+
+ # subvolume data to be inserted
+ group_name = self.group.groupname if self.group.groupname != Group.NO_GROUP_NAME else None
+ group_subvol_id = "{0}/{1}".format(group_name, self.subvolname)
+ subvolume = {
+ group_subvol_id : {
+ # The access level at which the auth_id is authorized to
+ # access the volume.
+ 'access_level': access_level,
+ 'dirty': True,
+ }
+ }
+
+ if auth_meta is None:
+ if not allow_existing_id and existing_caps is not None:
+ msg = "auth ID: {0} exists and not created by mgr plugin. Not allowed to modify".format(auth_id)
+ log.error(msg)
+ raise VolumeException(-errno.EPERM, msg)
+
+ # non-existent auth IDs
+ sys.stderr.write("Creating meta for ID {0} with tenant {1}\n".format(
+ auth_id, tenant_id
+ ))
+ log.debug("Authorize: no existing meta")
+ auth_meta = {
+ 'dirty': True,
+ 'tenant_id': str(tenant_id) if tenant_id else None,
+ 'subvolumes': subvolume
+ }
+ else:
+ # Update 'volumes' key (old style auth metadata file) to 'subvolumes' key
+ if 'volumes' in auth_meta:
+ auth_meta['subvolumes'] = auth_meta.pop('volumes')
+
+ # Disallow tenants to share auth IDs
+ if str(auth_meta['tenant_id']) != str(tenant_id):
+ msg = "auth ID: {0} is already in use".format(auth_id)
+ log.error(msg)
+ raise VolumeException(-errno.EPERM, msg)
+
+ if auth_meta['dirty']:
+ self._recover_auth_meta(auth_id, auth_meta)
+
+ log.debug("Authorize: existing tenant {tenant}".format(
+ tenant=auth_meta['tenant_id']
+ ))
+ auth_meta['dirty'] = True
+ auth_meta['subvolumes'].update(subvolume)
+
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ with self.auth_mdata_mgr.subvol_metadata_lock(self.group.groupname, self.subvolname):
+ key = self._authorize_subvolume(auth_id, access_level, existing_caps)
+
+ auth_meta['dirty'] = False
+ auth_meta['subvolumes'][group_subvol_id]['dirty'] = False
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ if tenant_id:
+ return key
+ else:
+ # Caller wasn't multi-tenant aware: be safe and don't give
+ # them a key
+ return ""
+
+ def _authorize_subvolume(self, auth_id, access_level, existing_caps):
+ subvol_meta = self.auth_mdata_mgr.subvol_metadata_get(self.group.groupname, self.subvolname)
+
+ auth = {
+ auth_id: {
+ 'access_level': access_level,
+ 'dirty': True,
+ }
+ }
+
+ if subvol_meta is None:
+ subvol_meta = {
+ 'auths': auth
+ }
+ else:
+ subvol_meta['auths'].update(auth)
+ self.auth_mdata_mgr.subvol_metadata_set(self.group.groupname, self.subvolname, subvol_meta)
+
+ key = self._authorize(auth_id, access_level, existing_caps)
+
+ subvol_meta['auths'][auth_id]['dirty'] = False
+ self.auth_mdata_mgr.subvol_metadata_set(self.group.groupname, self.subvolname, subvol_meta)
+
+ return key
+
+ def _authorize(self, auth_id, access_level, existing_caps):
+ subvol_path = self.path
+ log.debug("Authorizing Ceph id '{0}' for path '{1}'".format(auth_id, subvol_path))
+
+ # First I need to work out what the data pool is for this share:
+ # read the layout
+ try:
+ pool = self.fs.getxattr(subvol_path, 'ceph.dir.layout.pool').decode('utf-8')
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ try:
+ namespace = self.fs.getxattr(subvol_path, 'ceph.dir.layout.pool_namespace').decode('utf-8')
+ except cephfs.NoData:
+ namespace = None
+
+ # Now construct auth capabilities that give the guest just enough
+ # permissions to access the share
+ client_entity = "client.{0}".format(auth_id)
+ want_mds_cap = "allow {0} path={1}".format(access_level, subvol_path.decode('utf-8'))
+ want_osd_cap = "allow {0} pool={1}{2}".format(
+ access_level, pool, " namespace={0}".format(namespace) if namespace else "")
+
+ # Construct auth caps that if present might conflict with the desired
+ # auth caps.
+ unwanted_access_level = 'r' if access_level is 'rw' else 'rw'
+ unwanted_mds_cap = 'allow {0} path={1}'.format(unwanted_access_level, subvol_path.decode('utf-8'))
+ unwanted_osd_cap = "allow {0} pool={1}{2}".format(
+ unwanted_access_level, pool, " namespace={0}".format(namespace) if namespace else "")
+
+ return allow_access(self.mgr, client_entity, want_mds_cap, want_osd_cap,
+ unwanted_mds_cap, unwanted_osd_cap, existing_caps)
+
+ def deauthorize(self, auth_id):
+ with self.auth_mdata_mgr.auth_lock(auth_id):
+ # Existing meta, or None, to be updated
+ auth_meta = self.auth_mdata_mgr.auth_metadata_get(auth_id)
+
+ if auth_meta is None:
+ msg = "auth ID: {0} doesn't exist".format(auth_id)
+ log.error(msg)
+ raise VolumeException(-errno.ENOENT, msg)
+
+ # Update 'volumes' key (old style auth metadata file) to 'subvolumes' key
+ if 'volumes' in auth_meta:
+ auth_meta['subvolumes'] = auth_meta.pop('volumes')
+
+ group_name = self.group.groupname if self.group.groupname != Group.NO_GROUP_NAME else None
+ group_subvol_id = "{0}/{1}".format(group_name, self.subvolname)
+ if (auth_meta is None) or (not auth_meta['subvolumes']):
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for subvolume '{subvolume}'".format(
+ auth_id=auth_id, subvolume=self.subvolname
+ ))
+ # Clean up the auth meta file of an auth ID
+ self.fs.unlink(self.auth_mdata_mgr._auth_metadata_path(auth_id))
+ return
+
+ if group_subvol_id not in auth_meta['subvolumes']:
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for subvolume '{subvolume}'".format(
+ auth_id=auth_id, subvolume=self.subvolname
+ ))
+ return
+
+ if auth_meta['dirty']:
+ self._recover_auth_meta(auth_id, auth_meta)
+
+ auth_meta['dirty'] = True
+ auth_meta['subvolumes'][group_subvol_id]['dirty'] = True
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ self._deauthorize_subvolume(auth_id)
+
+ # Filter out the volume we're deauthorizing
+ del auth_meta['subvolumes'][group_subvol_id]
+
+ # Clean up auth meta file
+ if not auth_meta['subvolumes']:
+ self.fs.unlink(self.auth_mdata_mgr._auth_metadata_path(auth_id))
+ return
+
+ auth_meta['dirty'] = False
+ self.auth_mdata_mgr.auth_metadata_set(auth_id, auth_meta)
+
+ def _deauthorize_subvolume(self, auth_id):
+ with self.auth_mdata_mgr.subvol_metadata_lock(self.group.groupname, self.subvolname):
+ subvol_meta = self.auth_mdata_mgr.subvol_metadata_get(self.group.groupname, self.subvolname)
+
+ if (subvol_meta is None) or (auth_id not in subvol_meta['auths']):
+ log.warning("deauthorized called for already-removed auth"
+ "ID '{auth_id}' for subvolume '{subvolume}'".format(
+ auth_id=auth_id, subvolume=self.subvolname
+ ))
+ return
+
+ subvol_meta['auths'][auth_id]['dirty'] = True
+ self.auth_mdata_mgr.subvol_metadata_set(self.group.groupname, self.subvolname, subvol_meta)
+
+ self._deauthorize(auth_id)
+
+ # Remove the auth_id from the metadata *after* removing it
+ # from ceph, so that if we crashed here, we would actually
+ # recreate the auth ID during recovery (i.e. end up with
+ # a consistent state).
+
+ # Filter out the auth we're removing
+ del subvol_meta['auths'][auth_id]
+ self.auth_mdata_mgr.subvol_metadata_set(self.group.groupname, self.subvolname, subvol_meta)
+
+ def _deauthorize(self, auth_id):
+ """
+ The volume must still exist.
+ """
+ client_entity = "client.{0}".format(auth_id)
+ subvol_path = self.path
+ try:
+ pool_name = self.fs.getxattr(subvol_path, 'ceph.dir.layout.pool').decode('utf-8')
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ try:
+ namespace = self.fs.getxattr(subvol_path, 'ceph.dir.layout.pool_namespace').decode('utf-8')
+ except cephfs.NoData:
+ namespace = None
+
+ # The auth_id might have read-only or read-write mount access for the
+ # subvolume path.
+ access_levels = ('r', 'rw')
+ want_mds_caps = ['allow {0} path={1}'.format(access_level, subvol_path.decode('utf-8'))
+ for access_level in access_levels]
+ want_osd_caps = ['allow {0} pool={1}{2}'.format(
+ access_level, pool_name, " namespace={0}".format(namespace) if namespace else "")
+ for access_level in access_levels]
+ deny_access(self.mgr, client_entity, want_mds_caps, want_osd_caps)
+
+ def authorized_list(self):
+ """
+ Expose a list of auth IDs that have access to a subvolume.
+
+ return: a list of (auth_id, access_level) tuples, where
+ the access_level can be 'r' , or 'rw'.
+ None if no auth ID is given access to the subvolume.
+ """
+ with self.auth_mdata_mgr.subvol_metadata_lock(self.group.groupname, self.subvolname):
+ meta = self.auth_mdata_mgr.subvol_metadata_get(self.group.groupname, self.subvolname)
+ auths = [] # type: List[Dict[str,str]]
+ if not meta or not meta['auths']:
+ return auths
+
+ for auth, auth_data in meta['auths'].items():
+ # Skip partial auth updates.
+ if not auth_data['dirty']:
+ auths.append({auth: auth_data['access_level']})
+
+ return auths
+
+ def evict(self, volname, auth_id, timeout=30):
+ """
+ Evict all clients based on the authorization ID and the subvolume path mounted.
+ Assumes that the authorization key has been revoked prior to calling this function.
+
+ This operation can throw an exception if the mon cluster is unresponsive, or
+ any individual MDS daemon is unresponsive for longer than the timeout passed in.
+ """
+
+ client_spec = ["auth_name={0}".format(auth_id), ]
+ client_spec.append("client_metadata.root={0}".
+ format(self.path.decode('utf-8')))
+
+ log.info("evict clients with {0}".format(', '.join(client_spec)))
+
+ mds_map = get_mds_map(self.mgr, volname)
+ if not mds_map:
+ raise VolumeException(-errno.ENOENT, "mdsmap for volume {0} not found".format(volname))
+
+ up = {}
+ for name, gid in mds_map['up'].items():
+ # Quirk of the MDSMap JSON dump: keys in the up dict are like "mds_0"
+ assert name.startswith("mds_")
+ up[int(name[4:])] = gid
+
+ # For all MDS ranks held by a daemon
+ # Do the parallelism in python instead of using "tell mds.*", because
+ # the latter doesn't give us per-mds output
+ threads = []
+ for rank, gid in up.items():
+ thread = RankEvicter(self.mgr, self.fs, client_spec, volname, rank, gid, mds_map, timeout)
+ thread.start()
+ threads.append(thread)
+
+ for t in threads:
+ t.join()
+
+ log.info("evict: joined all")
+
+ for t in threads:
+ if not t.success:
+ msg = ("Failed to evict client with {0} from mds {1}/{2}: {3}".
+ format(', '.join(client_spec), t.rank, t.gid, t.exception)
+ )
+ log.error(msg)
+ raise EvictionError(msg)
+
+ def _get_clone_source(self):
+ try:
+ clone_source = {
+ 'volume' : self.metadata_mgr.get_option("source", "volume"),
+ 'subvolume': self.metadata_mgr.get_option("source", "subvolume"),
+ 'snapshot' : self.metadata_mgr.get_option("source", "snapshot"),
+ }
+
+ try:
+ clone_source["group"] = self.metadata_mgr.get_option("source", "group")
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT:
+ pass
+ else:
+ raise
+ except MetadataMgrException as me:
+ raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
+ return clone_source
+
+ @property
+ def status(self):
+ state = SubvolumeStates.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE))
+ subvolume_type = self.subvol_type
+ subvolume_status = {
+ 'state' : state.value
+ }
+ if not SubvolumeOpSm.is_complete_state(state) and subvolume_type == SubvolumeTypes.TYPE_CLONE:
+ subvolume_status["source"] = self._get_clone_source()
+ return subvolume_status
+
+ @property
+ def state(self):
+ return SubvolumeStates.from_value(self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE))
+
+ @state.setter
+ def state(self, val):
+ state = val[0].value
+ flush = val[1]
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, state)
+ if flush:
+ self.metadata_mgr.flush()
+
+ def remove(self, retainsnaps=False):
+ if retainsnaps:
+ raise VolumeException(-errno.EINVAL, "subvolume '{0}' does not support snapshot retention on delete".format(self.subvolname))
+ if self.list_snapshots():
+ raise VolumeException(-errno.ENOTEMPTY, "subvolume '{0}' has snapshots".format(self.subvolname))
+ self.trash_base_dir()
+
+ def resize(self, newsize, noshrink):
+ subvol_path = self.path
+ return self._resize(subvol_path, newsize, noshrink)
+
+ def create_snapshot(self, snapname):
+ try:
+ group_snapshot_path = os.path.join(self.group.path,
+ self.vol_spec.snapshot_dir_prefix.encode('utf-8'),
+ snapname.encode('utf-8'))
+ self.fs.stat(group_snapshot_path)
+ except cephfs.Error as e:
+ if e.args[0] == errno.ENOENT:
+ snappath = self.snapshot_path(snapname)
+ mksnap(self.fs, snappath)
+ else:
+ raise VolumeException(-e.args[0], e.args[1])
+ else:
+ raise VolumeException(-errno.EINVAL, "subvolumegroup and subvolume snapshot name can't be same")
+
+ def has_pending_clones(self, snapname):
+ try:
+ return self.metadata_mgr.section_has_item('clone snaps', snapname)
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT:
+ return False
+ raise
+
+ def remove_snapshot(self, snapname):
+ if self.has_pending_clones(snapname):
+ raise VolumeException(-errno.EAGAIN, "snapshot '{0}' has pending clones".format(snapname))
+ snappath = self.snapshot_path(snapname)
+ rmsnap(self.fs, snappath)
+
+ def snapshot_info(self, snapname):
+ if is_inherited_snap(snapname):
+ raise VolumeException(-errno.EINVAL,
+ "snapshot name '{0}' is invalid".format(snapname))
+ snappath = self.snapshot_data_path(snapname)
+ snap_info = {}
+ try:
+ snap_attrs = {'created_at':'ceph.snap.btime', 'size':'ceph.dir.rbytes',
+ 'data_pool':'ceph.dir.layout.pool'}
+ for key, val in snap_attrs.items():
+ snap_info[key] = self.fs.getxattr(snappath, val)
+ return {'size': int(snap_info['size']),
+ 'created_at': str(datetime.fromtimestamp(float(snap_info['created_at']))),
+ 'data_pool': snap_info['data_pool'].decode('utf-8'),
+ 'has_pending_clones': "yes" if self.has_pending_clones(snapname) else "no"}
+ except cephfs.Error as e:
+ if e.errno == errno.ENOENT:
+ raise VolumeException(-errno.ENOENT,
+ "snapshot '{0}' does not exist".format(snapname))
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def list_snapshots(self):
+ try:
+ dirpath = self.snapshot_base_path()
+ return listsnaps(self.fs, self.vol_spec, dirpath, filter_inherited_snaps=True)
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ return []
+ raise
+
+ def _add_snap_clone(self, track_id, snapname):
+ self.metadata_mgr.add_section("clone snaps")
+ self.metadata_mgr.update_section("clone snaps", track_id, snapname)
+ self.metadata_mgr.flush()
+
+ def _remove_snap_clone(self, track_id):
+ self.metadata_mgr.remove_option("clone snaps", track_id)
+ self.metadata_mgr.flush()
+
+ def attach_snapshot(self, snapname, tgt_subvolume):
+ if not snapname.encode('utf-8') in self.list_snapshots():
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
+ try:
+ create_clone_index(self.fs, self.vol_spec)
+ with open_clone_index(self.fs, self.vol_spec) as index:
+ track_idx = index.track(tgt_subvolume.base_path)
+ self._add_snap_clone(track_idx, snapname)
+ except (IndexException, MetadataMgrException) as e:
+ log.warn("error creating clone index: {0}".format(e))
+ raise VolumeException(-errno.EINVAL, "error cloning subvolume")
+
+ def detach_snapshot(self, snapname, track_id):
+ if not snapname.encode('utf-8') in self.list_snapshots():
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
+ try:
+ with open_clone_index(self.fs, self.vol_spec) as index:
+ index.untrack(track_id)
+ self._remove_snap_clone(track_id)
+ except (IndexException, MetadataMgrException) as e:
+ log.warn("error delining snapshot from clone: {0}".format(e))
+ raise VolumeException(-errno.EINVAL, "error delinking snapshot from clone")
diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py
new file mode 100644
index 00000000..1dd6f3fe
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py
@@ -0,0 +1,370 @@
+import os
+import stat
+import uuid
+import errno
+import logging
+
+import cephfs
+
+from .metadata_manager import MetadataManager
+from .subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeFeatures
+from .op_sm import SubvolumeOpSm
+from .subvolume_v1 import SubvolumeV1
+from ..template import SubvolumeTemplate
+from ...exception import OpSmException, VolumeException, MetadataMgrException
+from ...fs_util import listdir
+from ..template import SubvolumeOpType
+
+log = logging.getLogger(__name__)
+
+class SubvolumeV2(SubvolumeV1):
+ """
+ Version 2 subvolumes creates a subvolume with path as follows,
+ volumes/<group-name>/<subvolume-name>/<uuid>/
+
+ The distinguishing feature of V2 subvolume as compared to V1 subvolumes is its ability to retain snapshots
+ of a subvolume on removal. This is done by creating snapshots under the <subvolume-name> directory,
+ rather than under the <uuid> directory, as is the case of V1 subvolumes.
+
+ - The directory under which user data resides is <uuid>
+ - Snapshots of the subvolume are taken within the <subvolume-name> directory
+ - A meta file is maintained under the <subvolume-name> directory as a metadata store, storing information similar
+ to V1 subvolumes
+ - On a request to remove subvolume but retain its snapshots, only the <uuid> directory is moved to trash, retaining
+ the rest of the subvolume and its meta file.
+ - The <uuid> directory, when present, is the current incarnation of the subvolume, which may have snapshots of
+ older incarnations of the same subvolume.
+ - V1 subvolumes that currently do not have any snapshots are upgraded to V2 subvolumes automatically, to support the
+ snapshot retention feature
+ """
+ VERSION = 2
+
+ @staticmethod
+ def version():
+ return SubvolumeV2.VERSION
+
+ @property
+ def features(self):
+ return [SubvolumeFeatures.FEATURE_SNAPSHOT_CLONE.value,
+ SubvolumeFeatures.FEATURE_SNAPSHOT_AUTOPROTECT.value,
+ SubvolumeFeatures.FEATURE_SNAPSHOT_RETENTION.value]
+
+ @property
+ def retained(self):
+ try:
+ self.metadata_mgr.refresh()
+ if self.state == SubvolumeStates.STATE_RETAINED:
+ return True
+ return False
+ except MetadataMgrException as me:
+ if me.errno != -errno.ENOENT:
+ raise VolumeException(me.errno, "internal error while processing subvolume '{0}'".format(self.subvolname))
+ return False
+
+ @property
+ def purgeable(self):
+ if not self.retained or self.list_snapshots() or self.has_pending_purges:
+ return False
+ return True
+
+ @property
+ def has_pending_purges(self):
+ try:
+ return not listdir(self.fs, self.trash_dir) == []
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ return False
+ raise
+
+ @property
+ def trash_dir(self):
+ return os.path.join(self.base_path, b".trash")
+
+ def create_trashcan(self):
+ """per subvolume trash directory"""
+ try:
+ self.fs.stat(self.trash_dir)
+ except cephfs.Error as e:
+ if e.args[0] == errno.ENOENT:
+ try:
+ self.fs.mkdir(self.trash_dir, 0o700)
+ except cephfs.Error as ce:
+ raise VolumeException(-ce.args[0], ce.args[1])
+ else:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def mark_subvolume(self):
+ # set subvolume attr, on subvolume root, marking it as a CephFS subvolume
+ # subvolume root is where snapshots would be taken, and hence is the base_path for v2 subvolumes
+ try:
+ # MDS treats this as a noop for already marked subvolume
+ self.fs.setxattr(self.base_path, 'ceph.dir.subvolume', b'1', 0)
+ except cephfs.InvalidValue as e:
+ raise VolumeException(-errno.EINVAL, "invalid value specified for ceph.dir.subvolume")
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ @staticmethod
+ def is_valid_uuid(uuid_str):
+ try:
+ uuid.UUID(uuid_str)
+ return True
+ except ValueError:
+ return False
+
+ def snapshot_base_path(self):
+ return os.path.join(self.base_path, self.vol_spec.snapshot_dir_prefix.encode('utf-8'))
+
+ def snapshot_data_path(self, snapname):
+ snap_base_path = self.snapshot_path(snapname)
+ uuid_str = None
+ try:
+ with self.fs.opendir(snap_base_path) as dir_handle:
+ d = self.fs.readdir(dir_handle)
+ while d:
+ if d.d_name not in (b".", b".."):
+ d_full_path = os.path.join(snap_base_path, d.d_name)
+ stx = self.fs.statx(d_full_path, cephfs.CEPH_STATX_MODE, cephfs.AT_SYMLINK_NOFOLLOW)
+ if stat.S_ISDIR(stx.get('mode')):
+ if self.is_valid_uuid(d.d_name.decode('utf-8')):
+ uuid_str = d.d_name
+ d = self.fs.readdir(dir_handle)
+ except cephfs.Error as e:
+ if e.errno == errno.ENOENT:
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
+ raise VolumeException(-e.args[0], e.args[1])
+
+ if not uuid_str:
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(snapname))
+
+ return os.path.join(snap_base_path, uuid_str)
+
+ def _remove_on_failure(self, subvol_path, retained):
+ if retained:
+ log.info("cleaning up subvolume incarnation with path: {0}".format(subvol_path))
+ try:
+ self.fs.rmdir(subvol_path)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+ else:
+ log.info("cleaning up subvolume with path: {0}".format(self.subvolname))
+ self.remove()
+
+ def _set_incarnation_metadata(self, subvolume_type, qpath, initial_state):
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_TYPE, subvolume_type.value)
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_PATH, qpath)
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, initial_state.value)
+
+ def create(self, size, isolate_nspace, pool, mode, uid, gid):
+ subvolume_type = SubvolumeTypes.TYPE_NORMAL
+ try:
+ initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
+ except OpSmException as oe:
+ raise VolumeException(-errno.EINVAL, "subvolume creation failed: internal error")
+
+ retained = self.retained
+ if retained and self.has_pending_purges:
+ raise VolumeException(-errno.EAGAIN, "asynchronous purge of subvolume in progress")
+ subvol_path = os.path.join(self.base_path, str(uuid.uuid4()).encode('utf-8'))
+ try:
+ self.fs.mkdirs(subvol_path, mode)
+ self.mark_subvolume()
+ attrs = {
+ 'uid': uid,
+ 'gid': gid,
+ 'data_pool': pool,
+ 'pool_namespace': self.namespace if isolate_nspace else None,
+ 'quota': size
+ }
+ self.set_attrs(subvol_path, attrs)
+
+ # persist subvolume metadata
+ qpath = subvol_path.decode('utf-8')
+ if retained:
+ self._set_incarnation_metadata(subvolume_type, qpath, initial_state)
+ self.metadata_mgr.flush()
+ else:
+ self.init_config(SubvolumeV2.VERSION, subvolume_type, qpath, initial_state)
+
+ # Create the subvolume metadata file which manages auth-ids if it doesn't exist
+ self.auth_mdata_mgr.create_subvolume_metadata_file(self.group.groupname, self.subvolname)
+ except (VolumeException, MetadataMgrException, cephfs.Error) as e:
+ try:
+ self._remove_on_failure(subvol_path, retained)
+ except VolumeException as ve:
+ log.info("failed to cleanup subvolume '{0}' ({1})".format(self.subvolname, ve))
+
+ if isinstance(e, MetadataMgrException):
+ log.error("metadata manager exception: {0}".format(e))
+ e = VolumeException(-errno.EINVAL, "exception in subvolume metadata")
+ elif isinstance(e, cephfs.Error):
+ e = VolumeException(-e.args[0], e.args[1])
+ raise e
+
+ def create_clone(self, pool, source_volname, source_subvolume, snapname):
+ subvolume_type = SubvolumeTypes.TYPE_CLONE
+ try:
+ initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
+ except OpSmException as oe:
+ raise VolumeException(-errno.EINVAL, "clone failed: internal error")
+
+ retained = self.retained
+ if retained and self.has_pending_purges:
+ raise VolumeException(-errno.EAGAIN, "asynchronous purge of subvolume in progress")
+ subvol_path = os.path.join(self.base_path, str(uuid.uuid4()).encode('utf-8'))
+ try:
+ # source snapshot attrs are used to create clone subvolume
+ # attributes of subvolume's content though, are synced during the cloning process.
+ attrs = source_subvolume.get_attrs(source_subvolume.snapshot_data_path(snapname))
+
+ # override snapshot pool setting, if one is provided for the clone
+ if pool is not None:
+ attrs["data_pool"] = pool
+ attrs["pool_namespace"] = None
+
+ # create directory and set attributes
+ self.fs.mkdirs(subvol_path, attrs.get("mode"))
+ self.mark_subvolume()
+ self.set_attrs(subvol_path, attrs)
+
+ # persist subvolume metadata and clone source
+ qpath = subvol_path.decode('utf-8')
+ if retained:
+ self._set_incarnation_metadata(subvolume_type, qpath, initial_state)
+ else:
+ self.metadata_mgr.init(SubvolumeV2.VERSION, subvolume_type.value, qpath, initial_state.value)
+ self.add_clone_source(source_volname, source_subvolume, snapname)
+ self.metadata_mgr.flush()
+ except (VolumeException, MetadataMgrException, cephfs.Error) as e:
+ try:
+ self._remove_on_failure(subvol_path, retained)
+ except VolumeException as ve:
+ log.info("failed to cleanup subvolume '{0}' ({1})".format(self.subvolname, ve))
+
+ if isinstance(e, MetadataMgrException):
+ log.error("metadata manager exception: {0}".format(e))
+ e = VolumeException(-errno.EINVAL, "exception in subvolume metadata")
+ elif isinstance(e, cephfs.Error):
+ e = VolumeException(-e.args[0], e.args[1])
+ raise e
+
+ def allowed_ops_by_type(self, vol_type):
+ if vol_type == SubvolumeTypes.TYPE_CLONE:
+ return {op_type for op_type in SubvolumeOpType}
+
+ if vol_type == SubvolumeTypes.TYPE_NORMAL:
+ return {op_type for op_type in SubvolumeOpType} - {SubvolumeOpType.CLONE_STATUS,
+ SubvolumeOpType.CLONE_CANCEL,
+ SubvolumeOpType.CLONE_INTERNAL}
+
+ return {}
+
+ def allowed_ops_by_state(self, vol_state):
+ if vol_state == SubvolumeStates.STATE_COMPLETE:
+ return {op_type for op_type in SubvolumeOpType}
+
+ if vol_state == SubvolumeStates.STATE_RETAINED:
+ return {
+ SubvolumeOpType.REMOVE,
+ SubvolumeOpType.REMOVE_FORCE,
+ SubvolumeOpType.LIST,
+ SubvolumeOpType.INFO,
+ SubvolumeOpType.SNAP_REMOVE,
+ SubvolumeOpType.SNAP_LIST,
+ SubvolumeOpType.SNAP_INFO,
+ SubvolumeOpType.SNAP_PROTECT,
+ SubvolumeOpType.SNAP_UNPROTECT,
+ SubvolumeOpType.CLONE_SOURCE
+ }
+
+ return {SubvolumeOpType.REMOVE_FORCE,
+ SubvolumeOpType.CLONE_CREATE,
+ SubvolumeOpType.CLONE_STATUS,
+ SubvolumeOpType.CLONE_CANCEL,
+ SubvolumeOpType.CLONE_INTERNAL,
+ SubvolumeOpType.CLONE_SOURCE}
+
+ def open(self, op_type):
+ if not isinstance(op_type, SubvolumeOpType):
+ raise VolumeException(-errno.ENOTSUP, "operation {0} not supported on subvolume '{1}'".format(
+ op_type.value, self.subvolname))
+ try:
+ self.metadata_mgr.refresh()
+ # unconditionally mark as subvolume, to handle pre-existing subvolumes without the mark
+ self.mark_subvolume()
+
+ etype = self.subvol_type
+ if op_type not in self.allowed_ops_by_type(etype):
+ raise VolumeException(-errno.ENOTSUP, "operation '{0}' is not allowed on subvolume '{1}' of type {2}".format(
+ op_type.value, self.subvolname, etype.value))
+
+ estate = self.state
+ if op_type not in self.allowed_ops_by_state(estate) and estate == SubvolumeStates.STATE_RETAINED:
+ raise VolumeException(-errno.ENOENT, "subvolume '{0}' is removed and has only snapshots retained".format(
+ self.subvolname))
+
+ if op_type not in self.allowed_ops_by_state(estate) and estate != SubvolumeStates.STATE_RETAINED:
+ raise VolumeException(-errno.EAGAIN, "subvolume '{0}' is not ready for operation {1}".format(
+ self.subvolname, op_type.value))
+
+ if estate != SubvolumeStates.STATE_RETAINED:
+ subvol_path = self.path
+ log.debug("refreshed metadata, checking subvolume path '{0}'".format(subvol_path))
+ st = self.fs.stat(subvol_path)
+
+ self.uid = int(st.st_uid)
+ self.gid = int(st.st_gid)
+ self.mode = int(st.st_mode & ~stat.S_IFMT(st.st_mode))
+ except MetadataMgrException as me:
+ if me.errno == -errno.ENOENT:
+ raise VolumeException(-errno.ENOENT, "subvolume '{0}' does not exist".format(self.subvolname))
+ raise VolumeException(me.args[0], me.args[1])
+ except cephfs.ObjectNotFound:
+ log.debug("missing subvolume path '{0}' for subvolume '{1}'".format(subvol_path, self.subvolname))
+ raise VolumeException(-errno.ENOENT, "mount path missing for subvolume '{0}'".format(self.subvolname))
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def trash_incarnation_dir(self):
+ """rename subvolume (uuid component) to trash"""
+ self.create_trashcan()
+ try:
+ bname = os.path.basename(self.path)
+ tpath = os.path.join(self.trash_dir, bname)
+ log.debug("trash: {0} -> {1}".format(self.path, tpath))
+ self.fs.rename(self.path, tpath)
+ self._link_dir(tpath, bname)
+ except cephfs.Error as e:
+ raise VolumeException(-e.args[0], e.args[1])
+
+ def remove(self, retainsnaps=False):
+ if self.list_snapshots():
+ if not retainsnaps:
+ raise VolumeException(-errno.ENOTEMPTY, "subvolume '{0}' has snapshots".format(self.subvolname))
+ else:
+ if not self.has_pending_purges:
+ self.trash_base_dir()
+ # Delete the volume meta file, if it's not already deleted
+ self.auth_mdata_mgr.delete_subvolume_metadata_file(self.group.groupname, self.subvolname)
+ return
+ if self.state != SubvolumeStates.STATE_RETAINED:
+ self.trash_incarnation_dir()
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_PATH, "")
+ self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, SubvolumeStates.STATE_RETAINED.value)
+ self.metadata_mgr.flush()
+ # Delete the volume meta file, if it's not already deleted
+ self.auth_mdata_mgr.delete_subvolume_metadata_file(self.group.groupname, self.subvolname)
+
+ def info(self):
+ if self.state != SubvolumeStates.STATE_RETAINED:
+ return super(SubvolumeV2, self).info()
+
+ return {'type': self.subvol_type.value, 'features': self.features, 'state': SubvolumeStates.STATE_RETAINED.value}
+
+ def remove_snapshot(self, snapname):
+ super(SubvolumeV2, self).remove_snapshot(snapname)
+ if self.purgeable:
+ self.trash_base_dir()
+ # tickle the volume purge job to purge this entry, using ESTALE
+ raise VolumeException(-errno.ESTALE, "subvolume '{0}' has been removed as the last retained snapshot is removed".format(self.subvolname))
+ # if not purgeable, subvol is not retained, or has snapshots, or already has purge jobs that will garbage collect this subvol
diff --git a/src/pybind/mgr/volumes/fs/operations/volume.py b/src/pybind/mgr/volumes/fs/operations/volume.py
new file mode 100644
index 00000000..410e5c44
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/operations/volume.py
@@ -0,0 +1,348 @@
+import time
+import errno
+import logging
+import sys
+
+try:
+ from typing import List
+except ImportError:
+ pass # For typing only
+
+from contextlib import contextmanager
+from threading import Lock, Condition
+
+if sys.version_info >= (3, 3):
+ from threading import Timer
+else:
+ from threading import _Timer as Timer
+
+import cephfs
+import orchestrator
+
+from .lock import GlobalLock
+from ..exception import VolumeException
+from ..fs_util import create_pool, remove_pool, create_filesystem, \
+ remove_filesystem, create_mds, volume_exists
+
+log = logging.getLogger(__name__)
+
+class ConnectionPool(object):
+ class Connection(object):
+ def __init__(self, mgr, fs_name):
+ self.fs = None
+ self.mgr = mgr
+ self.fs_name = fs_name
+ self.ops_in_progress = 0
+ self.last_used = time.time()
+ self.fs_id = self.get_fs_id()
+
+ def get_fs_id(self):
+ fs_map = self.mgr.get('fs_map')
+ for fs in fs_map['filesystems']:
+ if fs['mdsmap']['fs_name'] == self.fs_name:
+ return fs['id']
+ raise VolumeException(
+ -errno.ENOENT, "Volume '{0}' not found".format(self.fs_name))
+
+ def get_fs_handle(self):
+ self.last_used = time.time()
+ self.ops_in_progress += 1
+ return self.fs
+
+ def put_fs_handle(self, notify):
+ assert self.ops_in_progress > 0
+ self.ops_in_progress -= 1
+ if self.ops_in_progress == 0:
+ notify()
+
+ def del_fs_handle(self, waiter):
+ if waiter:
+ while self.ops_in_progress != 0:
+ waiter()
+ if self.is_connection_valid():
+ self.disconnect()
+ else:
+ self.abort()
+
+ def is_connection_valid(self):
+ fs_id = None
+ try:
+ fs_id = self.get_fs_id()
+ except:
+ # the filesystem does not exist now -- connection is not valid.
+ pass
+ log.debug("self.fs_id={0}, fs_id={1}".format(self.fs_id, fs_id))
+ return self.fs_id == fs_id
+
+ def is_connection_idle(self, timeout):
+ return (self.ops_in_progress == 0 and ((time.time() - self.last_used) >= timeout))
+
+ def connect(self):
+ assert self.ops_in_progress == 0
+ log.debug("Connecting to cephfs '{0}'".format(self.fs_name))
+ self.fs = cephfs.LibCephFS(rados_inst=self.mgr.rados)
+ log.debug("Setting user ID and group ID of CephFS mount as root...")
+ self.fs.conf_set("client_mount_uid", "0")
+ self.fs.conf_set("client_mount_gid", "0")
+ log.debug("CephFS initializing...")
+ self.fs.init()
+ log.debug("CephFS mounting...")
+ self.fs.mount(filesystem_name=self.fs_name.encode('utf-8'))
+ log.debug("Connection to cephfs '{0}' complete".format(self.fs_name))
+
+ def disconnect(self):
+ try:
+ assert self.fs
+ assert self.ops_in_progress == 0
+ log.info("disconnecting from cephfs '{0}'".format(self.fs_name))
+ self.fs.shutdown()
+ self.fs = None
+ except Exception as e:
+ log.debug("disconnect: ({0})".format(e))
+ raise
+
+ def abort(self):
+ assert self.fs
+ assert self.ops_in_progress == 0
+ log.info("aborting connection from cephfs '{0}'".format(self.fs_name))
+ self.fs.abort_conn()
+ log.info("abort done from cephfs '{0}'".format(self.fs_name))
+ self.fs = None
+
+ class RTimer(Timer):
+ """
+ recurring timer variant of Timer
+ """
+ def run(self):
+ try:
+ while not self.finished.is_set():
+ self.finished.wait(self.interval)
+ self.function(*self.args, **self.kwargs)
+ self.finished.set()
+ except Exception as e:
+ log.error("ConnectionPool.RTimer: %s", e)
+ raise
+
+ # TODO: make this configurable
+ TIMER_TASK_RUN_INTERVAL = 30.0 # seconds
+ CONNECTION_IDLE_INTERVAL = 60.0 # seconds
+
+ def __init__(self, mgr):
+ self.mgr = mgr
+ self.connections = {}
+ self.lock = Lock()
+ self.cond = Condition(self.lock)
+ self.timer_task = ConnectionPool.RTimer(ConnectionPool.TIMER_TASK_RUN_INTERVAL,
+ self.cleanup_connections)
+ self.timer_task.start()
+
+ def cleanup_connections(self):
+ with self.lock:
+ log.info("scanning for idle connections..")
+ idle_fs = [fs_name for fs_name,conn in self.connections.items()
+ if conn.is_connection_idle(ConnectionPool.CONNECTION_IDLE_INTERVAL)]
+ for fs_name in idle_fs:
+ log.info("cleaning up connection for '{}'".format(fs_name))
+ self._del_fs_handle(fs_name)
+
+ def get_fs_handle(self, fs_name):
+ with self.lock:
+ conn = None
+ try:
+ conn = self.connections.get(fs_name, None)
+ if conn:
+ if conn.is_connection_valid():
+ return conn.get_fs_handle()
+ else:
+ # filesystem id changed beneath us (or the filesystem does not exist).
+ # this is possible if the filesystem got removed (and recreated with
+ # same name) via "ceph fs rm/new" mon command.
+ log.warning("filesystem id changed for volume '{0}', reconnecting...".format(fs_name))
+ self._del_fs_handle(fs_name)
+ conn = ConnectionPool.Connection(self.mgr, fs_name)
+ conn.connect()
+ except cephfs.Error as e:
+ # try to provide a better error string if possible
+ if e.args[0] == errno.ENOENT:
+ raise VolumeException(
+ -errno.ENOENT, "Volume '{0}' not found".format(fs_name))
+ raise VolumeException(-e.args[0], e.args[1])
+ self.connections[fs_name] = conn
+ return conn.get_fs_handle()
+
+ def put_fs_handle(self, fs_name):
+ with self.lock:
+ conn = self.connections.get(fs_name, None)
+ if conn:
+ conn.put_fs_handle(notify=lambda: self.cond.notifyAll())
+
+ def _del_fs_handle(self, fs_name, wait=False):
+ conn = self.connections.pop(fs_name, None)
+ if conn:
+ conn.del_fs_handle(waiter=None if not wait else lambda: self.cond.wait())
+
+ def del_fs_handle(self, fs_name, wait=False):
+ with self.lock:
+ self._del_fs_handle(fs_name, wait)
+
+ def del_all_handles(self):
+ with self.lock:
+ for fs_name in list(self.connections.keys()):
+ log.info("waiting for pending ops for '{}'".format(fs_name))
+ self._del_fs_handle(fs_name, wait=True)
+ log.info("pending ops completed for '{}'".format(fs_name))
+ # no new connections should have been initialized since its
+ # guarded on shutdown.
+ assert len(self.connections) == 0
+
+def gen_pool_names(volname):
+ """
+ return metadata and data pool name (from a filesystem/volume name) as a tuple
+ """
+ return "cephfs.{}.meta".format(volname), "cephfs.{}.data".format(volname)
+
+def get_mds_map(mgr, volname):
+ """
+ return mdsmap for a volname
+ """
+ mds_map = None
+ fs_map = mgr.get("fs_map")
+ for f in fs_map['filesystems']:
+ if volname == f['mdsmap']['fs_name']:
+ return f['mdsmap']
+ return mds_map
+
+def get_pool_names(mgr, volname):
+ """
+ return metadata and data pools (list) names of volume as a tuple
+ """
+ fs_map = mgr.get("fs_map")
+ metadata_pool_id = None
+ data_pool_ids = [] # type: List[int]
+ for f in fs_map['filesystems']:
+ if volname == f['mdsmap']['fs_name']:
+ metadata_pool_id = f['mdsmap']['metadata_pool']
+ data_pool_ids = f['mdsmap']['data_pools']
+ break
+ if metadata_pool_id is None:
+ return None, None
+
+ osdmap = mgr.get("osd_map")
+ pools = dict([(p['pool'], p['pool_name']) for p in osdmap['pools']])
+ metadata_pool = pools[metadata_pool_id]
+ data_pools = [pools[id] for id in data_pool_ids]
+ return metadata_pool, data_pools
+
+def create_volume(mgr, volname):
+ """
+ create volume (pool, filesystem and mds)
+ """
+ metadata_pool, data_pool = gen_pool_names(volname)
+ # create pools
+ r, outs, outb = create_pool(mgr, metadata_pool, 16)
+ if r != 0:
+ return r, outb, outs
+ r, outb, outs = create_pool(mgr, data_pool, 8)
+ if r != 0:
+ #cleanup
+ remove_pool(mgr, metadata_pool)
+ return r, outb, outs
+ # create filesystem
+ r, outb, outs = create_filesystem(mgr, volname, metadata_pool, data_pool)
+ if r != 0:
+ log.error("Filesystem creation error: {0} {1} {2}".format(r, outb, outs))
+ #cleanup
+ remove_pool(mgr, data_pool)
+ remove_pool(mgr, metadata_pool)
+ return r, outb, outs
+ # create mds
+ return create_mds(mgr, volname)
+
+def delete_volume(mgr, volname, metadata_pool, data_pools):
+ """
+ delete the given module (tear down mds, remove filesystem, remove pools)
+ """
+ # Tear down MDS daemons
+ try:
+ completion = mgr.remove_stateless_service("mds", volname)
+ mgr._orchestrator_wait([completion])
+ orchestrator.raise_if_exception(completion)
+ except (ImportError, orchestrator.OrchestratorError):
+ log.warning("OrchestratorError, not tearing down MDS daemons")
+ except Exception as e:
+ # Don't let detailed orchestrator exceptions (python backtraces)
+ # bubble out to the user
+ log.exception("Failed to tear down MDS daemons")
+ return -errno.EINVAL, "", str(e)
+
+ # In case orchestrator didn't tear down MDS daemons cleanly, or
+ # there was no orchestrator, we force the daemons down.
+ if volume_exists(mgr, volname):
+ r, outb, outs = remove_filesystem(mgr, volname)
+ if r != 0:
+ return r, outb, outs
+ else:
+ err = "Filesystem not found for volume '{0}'".format(volname)
+ log.warning(err)
+ return -errno.ENOENT, "", err
+ r, outb, outs = remove_pool(mgr, metadata_pool)
+ if r != 0:
+ return r, outb, outs
+
+ for data_pool in data_pools:
+ r, outb, outs = remove_pool(mgr, data_pool)
+ if r != 0:
+ return r, outb, outs
+ result_str = "metadata pool: {0} data pool: {1} removed".format(metadata_pool, str(data_pools))
+ return r, result_str, ""
+
+def list_volumes(mgr):
+ """
+ list all filesystem volumes.
+
+ :param: None
+ :return: None
+ """
+ result = []
+ fs_map = mgr.get("fs_map")
+ for f in fs_map['filesystems']:
+ result.append({'name': f['mdsmap']['fs_name']})
+ return result
+
+@contextmanager
+def open_volume(vc, volname):
+ """
+ open a volume for exclusive access. This API is to be used as a context manager.
+
+ :param vc: volume client instance
+ :param volname: volume name
+ :return: yields a volume handle (ceph filesystem handle)
+ """
+ if vc.is_stopping():
+ raise VolumeException(-errno.ESHUTDOWN, "shutdown in progress")
+
+ g_lock = GlobalLock()
+ fs_handle = vc.connection_pool.get_fs_handle(volname)
+ try:
+ with g_lock.lock_op():
+ yield fs_handle
+ finally:
+ vc.connection_pool.put_fs_handle(volname)
+
+@contextmanager
+def open_volume_lockless(vc, volname):
+ """
+ open a volume with shared access. This API is to be used as a context manager.
+
+ :param vc: volume client instance
+ :param volname: volume name
+ :return: yields a volume handle (ceph filesystem handle)
+ """
+ if vc.is_stopping():
+ raise VolumeException(-errno.ESHUTDOWN, "shutdown in progress")
+
+ fs_handle = vc.connection_pool.get_fs_handle(volname)
+ try:
+ yield fs_handle
+ finally:
+ vc.connection_pool.put_fs_handle(volname)
diff --git a/src/pybind/mgr/volumes/fs/purge_queue.py b/src/pybind/mgr/volumes/fs/purge_queue.py
new file mode 100644
index 00000000..7c902572
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/purge_queue.py
@@ -0,0 +1,109 @@
+import errno
+import logging
+import os
+import stat
+
+import cephfs
+
+from .async_job import AsyncJobs
+from .exception import VolumeException
+from .operations.resolver import resolve_trash
+from .operations.template import SubvolumeOpType
+from .operations.group import open_group
+from .operations.subvolume import open_subvol
+from .operations.volume import open_volume, open_volume_lockless
+from .operations.trash import open_trashcan
+
+log = logging.getLogger(__name__)
+
+# helper for fetching a trash entry for a given volume
+def get_trash_entry_for_volume(volume_client, volname, running_jobs):
+ log.debug("fetching trash entry for volume '{0}'".format(volname))
+
+ try:
+ with open_volume_lockless(volume_client, volname) as fs_handle:
+ try:
+ with open_trashcan(fs_handle, volume_client.volspec) as trashcan:
+ path = trashcan.get_trash_entry(running_jobs)
+ return 0, path
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ return 0, None
+ raise ve
+ except VolumeException as ve:
+ log.error("error fetching trash entry for volume '{0}' ({1})".format(volname, ve))
+ return ve.errno, None
+
+def subvolume_purge(volume_client, volname, trashcan, subvolume_trash_entry, should_cancel):
+ groupname, subvolname = resolve_trash(volume_client.volspec, subvolume_trash_entry.decode('utf-8'))
+ log.debug("subvolume resolved to {0}/{1}".format(groupname, subvolname))
+
+ try:
+ with open_volume(volume_client, volname) as fs_handle:
+ with open_group(fs_handle, volume_client.volspec, groupname) as group:
+ with open_subvol(volume_client.mgr, fs_handle, volume_client.volspec, group, subvolname, SubvolumeOpType.REMOVE) as subvolume:
+ log.debug("subvolume.path={0}, purgeable={1}".format(subvolume.path, subvolume.purgeable))
+ if not subvolume.purgeable:
+ return
+ # this is fine under the global lock -- there are just a handful
+ # of entries in the subvolume to purge. moreover, the purge needs
+ # to be guarded since a create request might sneak in.
+ trashcan.purge(subvolume.base_path, should_cancel)
+ except VolumeException as ve:
+ if not ve.errno == -errno.ENOENT:
+ raise
+
+# helper for starting a purge operation on a trash entry
+def purge_trash_entry_for_volume(volume_client, volname, purge_entry, should_cancel):
+ log.debug("purging trash entry '{0}' for volume '{1}'".format(purge_entry, volname))
+
+ ret = 0
+ try:
+ with open_volume_lockless(volume_client, volname) as fs_handle:
+ with open_trashcan(fs_handle, volume_client.volspec) as trashcan:
+ try:
+ pth = os.path.join(trashcan.path, purge_entry)
+ stx = fs_handle.statx(pth, cephfs.CEPH_STATX_MODE | cephfs.CEPH_STATX_SIZE,
+ cephfs.AT_SYMLINK_NOFOLLOW)
+ if stat.S_ISLNK(stx['mode']):
+ tgt = fs_handle.readlink(pth, 4096)
+ tgt = tgt[:stx['size']]
+ log.debug("purging entry pointing to subvolume trash: {0}".format(tgt))
+ delink = True
+ try:
+ trashcan.purge(tgt, should_cancel)
+ except VolumeException as ve:
+ if not ve.errno == -errno.ENOENT:
+ delink = False
+ return ve.errno
+ finally:
+ if delink:
+ subvolume_purge(volume_client, volname, trashcan, tgt, should_cancel)
+ log.debug("purging trash link: {0}".format(purge_entry))
+ trashcan.delink(purge_entry)
+ else:
+ log.debug("purging entry pointing to trash: {0}".format(pth))
+ trashcan.purge(pth, should_cancel)
+ except cephfs.Error as e:
+ log.warn("failed to remove trash entry: {0}".format(e))
+ except VolumeException as ve:
+ ret = ve.errno
+ return ret
+
+class ThreadPoolPurgeQueueMixin(AsyncJobs):
+ """
+ Purge queue mixin class maintaining a pool of threads for purging trash entries.
+ Subvolumes are chosen from volumes in a round robin fashion. If some of the purge
+ entries (belonging to a set of volumes) have huge directory tree's (such as, lots
+ of small files in a directory w/ deep directory trees), this model may lead to
+ _all_ threads purging entries for one volume (starving other volumes).
+ """
+ def __init__(self, volume_client, tp_size):
+ self.vc = volume_client
+ super(ThreadPoolPurgeQueueMixin, self).__init__(volume_client, "puregejob", tp_size)
+
+ def get_next_job(self, volname, running_jobs):
+ return get_trash_entry_for_volume(self.vc, volname, running_jobs)
+
+ def execute_job(self, volname, job, should_cancel):
+ purge_trash_entry_for_volume(self.vc, volname, job, should_cancel)
diff --git a/src/pybind/mgr/volumes/fs/vol_spec.py b/src/pybind/mgr/volumes/fs/vol_spec.py
new file mode 100644
index 00000000..e18ab069
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/vol_spec.py
@@ -0,0 +1,37 @@
+import os
+
+class VolSpec(object):
+ """
+ specification of a "volume" -- base directory and various prefixes.
+ """
+
+ # where shall we (by default) create subvolumes
+ DEFAULT_SUBVOL_PREFIX = "/volumes"
+ # and the default namespace
+ DEFAULT_NS_PREFIX = "fsvolumens_"
+
+ def __init__(self, snapshot_prefix, subvolume_prefix=None, pool_ns_prefix=None):
+ self.snapshot_prefix = snapshot_prefix
+ self.subvolume_prefix = subvolume_prefix if subvolume_prefix else VolSpec.DEFAULT_SUBVOL_PREFIX
+ self.pool_ns_prefix = pool_ns_prefix if pool_ns_prefix else VolSpec.DEFAULT_NS_PREFIX
+
+ @property
+ def snapshot_dir_prefix(self):
+ """
+ Return the snapshot directory prefix
+ """
+ return self.snapshot_prefix
+
+ @property
+ def base_dir(self):
+ """
+ Return the top level directory under which subvolumes/groups are created
+ """
+ return self.subvolume_prefix
+
+ @property
+ def fs_namespace(self):
+ """
+ return a filesystem namespace by stashing pool namespace prefix and subvolume-id
+ """
+ return self.pool_ns_prefix
diff --git a/src/pybind/mgr/volumes/fs/volume.py b/src/pybind/mgr/volumes/fs/volume.py
new file mode 100644
index 00000000..ab287539
--- /dev/null
+++ b/src/pybind/mgr/volumes/fs/volume.py
@@ -0,0 +1,660 @@
+import json
+import errno
+import logging
+from threading import Event
+
+import cephfs
+
+from .fs_util import listdir
+
+from .operations.volume import ConnectionPool, open_volume, create_volume, \
+ delete_volume, list_volumes, get_pool_names
+from .operations.group import open_group, create_group, remove_group, open_group_unique
+from .operations.subvolume import open_subvol, create_subvol, remove_subvol, \
+ create_clone
+
+from .vol_spec import VolSpec
+from .exception import VolumeException, ClusterError, ClusterTimeout, EvictionError
+from .async_cloner import Cloner
+from .purge_queue import ThreadPoolPurgeQueueMixin
+from .operations.template import SubvolumeOpType
+
+log = logging.getLogger(__name__)
+
+ALLOWED_ACCESS_LEVELS = ('r', 'rw')
+
+
+def octal_str_to_decimal_int(mode):
+ try:
+ return int(mode, 8)
+ except ValueError:
+ raise VolumeException(-errno.EINVAL, "Invalid mode '{0}'".format(mode))
+
+def name_to_json(names):
+ """
+ convert the list of names to json
+ """
+ namedict = []
+ for i in range(len(names)):
+ namedict.append({'name': names[i].decode('utf-8')})
+ return json.dumps(namedict, indent=4, sort_keys=True)
+
+class VolumeClient(object):
+ def __init__(self, mgr):
+ self.mgr = mgr
+ self.stopping = Event()
+ # volume specification
+ self.volspec = VolSpec(mgr.rados.conf_get('client_snapdir'))
+ self.connection_pool = ConnectionPool(self.mgr)
+ self.cloner = Cloner(self, self.mgr.max_concurrent_clones)
+ self.purge_queue = ThreadPoolPurgeQueueMixin(self, 4)
+ # on startup, queue purge job for available volumes to kickstart
+ # purge for leftover subvolume entries in trash. note that, if the
+ # trash directory does not exist or if there are no purge entries
+ # available for a volume, the volume is removed from the purge
+ # job list.
+ fs_map = self.mgr.get('fs_map')
+ for fs in fs_map['filesystems']:
+ self.cloner.queue_job(fs['mdsmap']['fs_name'])
+ self.purge_queue.queue_job(fs['mdsmap']['fs_name'])
+
+ def is_stopping(self):
+ return self.stopping.is_set()
+
+ def shutdown(self):
+ log.info("shutting down")
+ # first, note that we're shutting down
+ self.stopping.set()
+ # second, ask purge threads to quit
+ self.purge_queue.cancel_all_jobs()
+ # third, delete all libcephfs handles from connection pool
+ self.connection_pool.del_all_handles()
+
+ def cluster_log(self, msg, lvl=None):
+ """
+ log to cluster log with default log level as WARN.
+ """
+ if not lvl:
+ lvl = self.mgr.CLUSTER_LOG_PRIO_WARN
+ self.mgr.cluster_log("cluster", lvl, msg)
+
+ def volume_exception_to_retval(self, ve):
+ """
+ return a tuple representation from a volume exception
+ """
+ return ve.to_tuple()
+
+ ### volume operations -- create, rm, ls
+
+ def create_fs_volume(self, volname):
+ if self.is_stopping():
+ return -errno.ESHUTDOWN, "", "shutdown in progress"
+ return create_volume(self.mgr, volname)
+
+ def delete_fs_volume(self, volname, confirm):
+ if self.is_stopping():
+ return -errno.ESHUTDOWN, "", "shutdown in progress"
+
+ if confirm != "--yes-i-really-mean-it":
+ return -errno.EPERM, "", "WARNING: this will *PERMANENTLY DESTROY* all data " \
+ "stored in the filesystem '{0}'. If you are *ABSOLUTELY CERTAIN* " \
+ "that is what you want, re-issue the command followed by " \
+ "--yes-i-really-mean-it.".format(volname)
+
+ ret, out, err = self.mgr.mon_command({
+ 'prefix': 'config get',
+ 'key': 'mon_allow_pool_delete',
+ 'who': 'mon.*',
+ 'format': 'json',
+ })
+ if ret != 0:
+ return ret, out, err
+ mon_allow_pool_delete = json.loads(out)
+ if not mon_allow_pool_delete:
+ return -errno.EPERM, "", "pool deletion is disabled; you must first " \
+ "set the mon_allow_pool_delete config option to true before volumes " \
+ "can be deleted"
+
+ metadata_pool, data_pools = get_pool_names(self.mgr, volname)
+ if not metadata_pool:
+ return -errno.ENOENT, "", "volume {0} doesn't exist".format(volname)
+ self.purge_queue.cancel_jobs(volname)
+ self.connection_pool.del_fs_handle(volname, wait=True)
+ return delete_volume(self.mgr, volname, metadata_pool, data_pools)
+
+ def list_fs_volumes(self):
+ if self.stopping.is_set():
+ return -errno.ESHUTDOWN, "", "shutdown in progress"
+ volumes = list_volumes(self.mgr)
+ return 0, json.dumps(volumes, indent=4, sort_keys=True), ""
+
+ ### subvolume operations
+
+ def _create_subvolume(self, fs_handle, volname, group, subvolname, **kwargs):
+ size = kwargs['size']
+ pool = kwargs['pool_layout']
+ uid = kwargs['uid']
+ gid = kwargs['gid']
+ mode = kwargs['mode']
+ isolate_nspace = kwargs['namespace_isolated']
+
+ oct_mode = octal_str_to_decimal_int(mode)
+ try:
+ create_subvol(
+ self.mgr, fs_handle, self.volspec, group, subvolname, size, isolate_nspace, pool, oct_mode, uid, gid)
+ except VolumeException as ve:
+ # kick the purge threads for async removal -- note that this
+ # assumes that the subvolume is moved to trashcan for cleanup on error.
+ self.purge_queue.queue_job(volname)
+ raise ve
+
+ def create_subvolume(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+ size = kwargs['size']
+ pool = kwargs['pool_layout']
+ uid = kwargs['uid']
+ gid = kwargs['gid']
+ isolate_nspace = kwargs['namespace_isolated']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ try:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.CREATE) as subvolume:
+ # idempotent creation -- valid. Attributes set is supported.
+ attrs = {
+ 'uid': uid if uid else subvolume.uid,
+ 'gid': gid if gid else subvolume.gid,
+ 'data_pool': pool,
+ 'pool_namespace': subvolume.namespace if isolate_nspace else None,
+ 'quota': size
+ }
+ subvolume.set_attrs(subvolume.path, attrs)
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ self._create_subvolume(fs_handle, volname, group, subvolname, **kwargs)
+ else:
+ raise
+ except VolumeException as ve:
+ # volume/group does not exist or subvolume creation failed
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def remove_subvolume(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+ force = kwargs['force']
+ retainsnaps = kwargs['retain_snapshots']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ remove_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, force, retainsnaps)
+ # kick the purge threads for async removal -- note that this
+ # assumes that the subvolume is moved to trash can.
+ # TODO: make purge queue as singleton so that trash can kicks
+ # the purge threads on dump.
+ self.purge_queue.queue_job(volname)
+ except VolumeException as ve:
+ if ve.errno == -errno.EAGAIN:
+ ve = VolumeException(ve.errno, ve.error_str + " (use --force to override)")
+ ret = self.volume_exception_to_retval(ve)
+ elif not (ve.errno == -errno.ENOENT and force):
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def authorize_subvolume(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ authid = kwargs['auth_id']
+ groupname = kwargs['group_name']
+ accesslevel = kwargs['access_level']
+ tenant_id = kwargs['tenant_id']
+ allow_existing_id = kwargs['allow_existing_id']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.ALLOW_ACCESS) as subvolume:
+ key = subvolume.authorize(authid, accesslevel, tenant_id, allow_existing_id)
+ ret = 0, key, ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def deauthorize_subvolume(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ authid = kwargs['auth_id']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.DENY_ACCESS) as subvolume:
+ subvolume.deauthorize(authid)
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def authorized_list(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.AUTH_LIST) as subvolume:
+ auths = subvolume.authorized_list()
+ ret = 0, json.dumps(auths, indent=4, sort_keys=True), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def evict(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ authid = kwargs['auth_id']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.EVICT) as subvolume:
+ key = subvolume.evict(volname, authid)
+ ret = 0, "", ""
+ except (VolumeException, ClusterTimeout, ClusterError, EvictionError) as e:
+ if isinstance(e, VolumeException):
+ ret = self.volume_exception_to_retval(e)
+ elif isinstance(e, ClusterTimeout):
+ ret = -errno.ETIMEDOUT , "", "Timedout trying to talk to ceph cluster"
+ elif isinstance(e, ClusterError):
+ ret = e._result_code , "", e._result_str
+ elif isinstance(e, EvictionError):
+ ret = -errno.EINVAL, "", str(e)
+ return ret
+
+ def resize_subvolume(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ newsize = kwargs['new_size']
+ noshrink = kwargs['no_shrink']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.RESIZE) as subvolume:
+ nsize, usedbytes = subvolume.resize(newsize, noshrink)
+ ret = 0, json.dumps(
+ [{'bytes_used': usedbytes},{'bytes_quota': nsize},
+ {'bytes_pcent': "undefined" if nsize == 0 else '{0:.2f}'.format((float(usedbytes) / nsize) * 100.0)}],
+ indent=4, sort_keys=True), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def subvolume_getpath(self, **kwargs):
+ ret = None
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.GETPATH) as subvolume:
+ subvolpath = subvolume.path
+ ret = 0, subvolpath.decode("utf-8"), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def subvolume_info(self, **kwargs):
+ ret = None
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.INFO) as subvolume:
+ mon_addr_lst = []
+ mon_map_mons = self.mgr.get('mon_map')['mons']
+ for mon in mon_map_mons:
+ ip_port = mon['addr'].split("/")[0]
+ mon_addr_lst.append(ip_port)
+
+ subvol_info_dict = subvolume.info()
+ subvol_info_dict["mon_addrs"] = mon_addr_lst
+ ret = 0, json.dumps(subvol_info_dict, indent=4, sort_keys=True), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def list_subvolumes(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ subvolumes = group.list_subvolumes()
+ ret = 0, name_to_json(subvolumes), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ ### subvolume snapshot
+
+ def create_subvolume_snapshot(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ snapname = kwargs['snap_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_CREATE) as subvolume:
+ subvolume.create_snapshot(snapname)
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def remove_subvolume_snapshot(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ snapname = kwargs['snap_name']
+ groupname = kwargs['group_name']
+ force = kwargs['force']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_REMOVE) as subvolume:
+ subvolume.remove_snapshot(snapname)
+ except VolumeException as ve:
+ # ESTALE serves as an error to state that subvolume is currently stale due to internal removal and,
+ # we should tickle the purge jobs to purge the same
+ if ve.errno == -errno.ESTALE:
+ self.purge_queue.queue_job(volname)
+ elif not (ve.errno == -errno.ENOENT and force):
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def subvolume_snapshot_info(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ snapname = kwargs['snap_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_INFO) as subvolume:
+ snap_info_dict = subvolume.snapshot_info(snapname)
+ ret = 0, json.dumps(snap_info_dict, indent=4, sort_keys=True), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def list_subvolume_snapshots(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_LIST) as subvolume:
+ snapshots = subvolume.list_snapshots()
+ ret = 0, name_to_json(snapshots), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def protect_subvolume_snapshot(self, **kwargs):
+ ret = 0, "", "Deprecation warning: 'snapshot protect' call is deprecated and will be removed in a future release"
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_PROTECT) as subvolume:
+ log.warning("snapshot protect call is deprecated and will be removed in a future release")
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def unprotect_subvolume_snapshot(self, **kwargs):
+ ret = 0, "", "Deprecation warning: 'snapshot unprotect' call is deprecated and will be removed in a future release"
+ volname = kwargs['vol_name']
+ subvolname = kwargs['sub_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, SubvolumeOpType.SNAP_UNPROTECT) as subvolume:
+ log.warning("snapshot unprotect call is deprecated and will be removed in a future release")
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def _prepare_clone_subvolume(self, fs_handle, volname, s_subvolume, s_snapname, t_group, t_subvolname, **kwargs):
+ t_pool = kwargs['pool_layout']
+ s_subvolname = kwargs['sub_name']
+ s_groupname = kwargs['group_name']
+ t_groupname = kwargs['target_group_name']
+
+ create_clone(self.mgr, fs_handle, self.volspec, t_group, t_subvolname, t_pool, volname, s_subvolume, s_snapname)
+ with open_subvol(self.mgr, fs_handle, self.volspec, t_group, t_subvolname, SubvolumeOpType.CLONE_INTERNAL) as t_subvolume:
+ try:
+ if t_groupname == s_groupname and t_subvolname == s_subvolname:
+ t_subvolume.attach_snapshot(s_snapname, t_subvolume)
+ else:
+ s_subvolume.attach_snapshot(s_snapname, t_subvolume)
+ self.cloner.queue_job(volname)
+ except VolumeException as ve:
+ try:
+ t_subvolume.remove()
+ self.purge_queue.queue_job(volname)
+ except Exception as e:
+ log.warning("failed to cleanup clone subvolume '{0}' ({1})".format(t_subvolname, e))
+ raise ve
+
+ def _clone_subvolume_snapshot(self, fs_handle, volname, s_group, s_subvolume, **kwargs):
+ s_snapname = kwargs['snap_name']
+ target_subvolname = kwargs['target_sub_name']
+ target_groupname = kwargs['target_group_name']
+ s_groupname = kwargs['group_name']
+
+ if not s_snapname.encode('utf-8') in s_subvolume.list_snapshots():
+ raise VolumeException(-errno.ENOENT, "snapshot '{0}' does not exist".format(s_snapname))
+
+ with open_group_unique(fs_handle, self.volspec, target_groupname, s_group, s_groupname) as target_group:
+ try:
+ with open_subvol(self.mgr, fs_handle, self.volspec, target_group, target_subvolname, SubvolumeOpType.CLONE_CREATE):
+ raise VolumeException(-errno.EEXIST, "subvolume '{0}' exists".format(target_subvolname))
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ self._prepare_clone_subvolume(fs_handle, volname, s_subvolume, s_snapname,
+ target_group, target_subvolname, **kwargs)
+ else:
+ raise
+
+ def clone_subvolume_snapshot(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ s_subvolname = kwargs['sub_name']
+ s_groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, s_groupname) as s_group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, s_group, s_subvolname, SubvolumeOpType.CLONE_SOURCE) as s_subvolume:
+ self._clone_subvolume_snapshot(fs_handle, volname, s_group, s_subvolume, **kwargs)
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def clone_status(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ clonename = kwargs['clone_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ with open_subvol(self.mgr, fs_handle, self.volspec, group, clonename, SubvolumeOpType.CLONE_STATUS) as subvolume:
+ ret = 0, json.dumps({'status' : subvolume.status}, indent=2), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def clone_cancel(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ clonename = kwargs['clone_name']
+ groupname = kwargs['group_name']
+
+ try:
+ self.cloner.cancel_job(volname, (clonename, groupname))
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ ### group operations
+
+ def create_subvolume_group(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+ pool = kwargs['pool_layout']
+ uid = kwargs['uid']
+ gid = kwargs['gid']
+ mode = kwargs['mode']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ try:
+ with open_group(fs_handle, self.volspec, groupname):
+ # idempotent creation -- valid.
+ pass
+ except VolumeException as ve:
+ if ve.errno == -errno.ENOENT:
+ oct_mode = octal_str_to_decimal_int(mode)
+ create_group(fs_handle, self.volspec, groupname, pool, oct_mode, uid, gid)
+ else:
+ raise
+ except VolumeException as ve:
+ # volume does not exist or subvolume group creation failed
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def remove_subvolume_group(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+ force = kwargs['force']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ remove_group(fs_handle, self.volspec, groupname)
+ except VolumeException as ve:
+ if not (ve.errno == -errno.ENOENT and force):
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def getpath_subvolume_group(self, **kwargs):
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ return 0, group.path.decode('utf-8'), ""
+ except VolumeException as ve:
+ return self.volume_exception_to_retval(ve)
+
+ def list_subvolume_groups(self, **kwargs):
+ volname = kwargs['vol_name']
+ ret = 0, '[]', ""
+ try:
+ with open_volume(self, volname) as fs_handle:
+ groups = listdir(fs_handle, self.volspec.base_dir)
+ ret = 0, name_to_json(groups), ""
+ except VolumeException as ve:
+ if not ve.errno == -errno.ENOENT:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ ### group snapshot
+
+ def create_subvolume_group_snapshot(self, **kwargs):
+ ret = -errno.ENOSYS, "", "subvolume group snapshots are not supported"
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+ # snapname = kwargs['snap_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ # as subvolumes are marked with the vxattr ceph.dir.subvolume deny snapshots
+ # at the subvolume group (see: https://tracker.ceph.com/issues/46074)
+ # group.create_snapshot(snapname)
+ pass
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def remove_subvolume_group_snapshot(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+ snapname = kwargs['snap_name']
+ force = kwargs['force']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ group.remove_snapshot(snapname)
+ except VolumeException as ve:
+ if not (ve.errno == -errno.ENOENT and force):
+ ret = self.volume_exception_to_retval(ve)
+ return ret
+
+ def list_subvolume_group_snapshots(self, **kwargs):
+ ret = 0, "", ""
+ volname = kwargs['vol_name']
+ groupname = kwargs['group_name']
+
+ try:
+ with open_volume(self, volname) as fs_handle:
+ with open_group(fs_handle, self.volspec, groupname) as group:
+ snapshots = group.list_snapshots()
+ ret = 0, name_to_json(snapshots), ""
+ except VolumeException as ve:
+ ret = self.volume_exception_to_retval(ve)
+ return ret
diff --git a/src/pybind/mgr/volumes/module.py b/src/pybind/mgr/volumes/module.py
new file mode 100644
index 00000000..3b9ed4a9
--- /dev/null
+++ b/src/pybind/mgr/volumes/module.py
@@ -0,0 +1,576 @@
+import errno
+import json
+import logging
+import traceback
+import threading
+
+from mgr_module import MgrModule
+import orchestrator
+
+from .fs.volume import VolumeClient
+
+log = logging.getLogger(__name__)
+
+class VolumesInfoWrapper():
+ def __init__(self, f, context):
+ self.f = f
+ self.context = context
+ def __enter__(self):
+ log.info("Starting {}".format(self.context))
+ def __exit__(self, exc_type, exc_value, tb):
+ if exc_type is not None:
+ log.error("Failed {}:\n{}".format(self.context, "".join(traceback.format_exception(exc_type, exc_value, tb))))
+ else:
+ log.info("Finishing {}".format(self.context))
+
+def mgr_cmd_wrap(f):
+ def wrap(self, inbuf, cmd):
+ astr = []
+ for k in cmd:
+ astr.append("{}:{}".format(k, cmd[k]))
+ context = "{}({}) < \"{}\"".format(f.__name__, ", ".join(astr), inbuf)
+ with VolumesInfoWrapper(f, context):
+ return f(self, inbuf, cmd)
+ return wrap
+
+class Module(orchestrator.OrchestratorClientMixin, MgrModule):
+ COMMANDS = [
+ {
+ 'cmd': 'fs volume ls',
+ 'desc': "List volumes",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs volume create '
+ 'name=name,type=CephString ',
+ 'desc': "Create a CephFS volume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs volume rm '
+ 'name=vol_name,type=CephString '
+ 'name=yes-i-really-mean-it,type=CephString,req=false ',
+ 'desc': "Delete a FS volume by passing --yes-i-really-mean-it flag",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolumegroup ls '
+ 'name=vol_name,type=CephString ',
+ 'desc': "List subvolumegroups",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolumegroup create '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString '
+ 'name=pool_layout,type=CephString,req=false '
+ 'name=uid,type=CephInt,req=false '
+ 'name=gid,type=CephInt,req=false '
+ 'name=mode,type=CephString,req=false ',
+ 'desc': "Create a CephFS subvolume group in a volume, and optionally, "
+ "with a specific data pool layout, and a specific numeric mode",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolumegroup rm '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString '
+ 'name=force,type=CephBool,req=false ',
+ 'desc': "Delete a CephFS subvolume group in a volume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume ls '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "List subvolumes",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolume create '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=size,type=CephInt,req=false '
+ 'name=group_name,type=CephString,req=false '
+ 'name=pool_layout,type=CephString,req=false '
+ 'name=uid,type=CephInt,req=false '
+ 'name=gid,type=CephInt,req=false '
+ 'name=mode,type=CephString,req=false '
+ 'name=namespace_isolated,type=CephBool,req=false ',
+ 'desc': "Create a CephFS subvolume in a volume, and optionally, "
+ "with a specific size (in bytes), a specific data pool layout, "
+ "a specific mode, in a specific subvolume group and in separate "
+ "RADOS namespace",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume rm '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=group_name,type=CephString,req=false '
+ 'name=force,type=CephBool,req=false '
+ 'name=retain_snapshots,type=CephBool,req=false ',
+ 'desc': "Delete a CephFS subvolume in a volume, and optionally, "
+ "in a specific subvolume group, force deleting a cancelled or failed "
+ "clone, and retaining existing subvolume snapshots",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume authorize '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=auth_id,type=CephString '
+ 'name=group_name,type=CephString,req=false '
+ 'name=access_level,type=CephString,req=false '
+ 'name=tenant_id,type=CephString,req=false '
+ 'name=allow_existing_id,type=CephBool,req=false ',
+ 'desc': "Allow a cephx auth ID access to a subvolume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume deauthorize '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=auth_id,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Deny a cephx auth ID access to a subvolume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume authorized_list '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "List auth IDs that have access to a subvolume",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolume evict '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=auth_id,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Evict clients based on auth IDs and subvolume mounted",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolumegroup getpath '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString ',
+ 'desc': "Get the mountpath of a CephFS subvolume group in a volume",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolume getpath '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Get the mountpath of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume info '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Get the metadata of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolumegroup snapshot ls '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString ',
+ 'desc': "List subvolumegroup snapshots",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolumegroup snapshot create '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString '
+ 'name=snap_name,type=CephString ',
+ 'desc': "Create a snapshot of a CephFS subvolume group in a volume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolumegroup snapshot rm '
+ 'name=vol_name,type=CephString '
+ 'name=group_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=force,type=CephBool,req=false ',
+ 'desc': "Delete a snapshot of a CephFS subvolume group in a volume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot ls '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "List subvolume snapshots",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot create '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Create a snapshot of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot info '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Get the metadata of a CephFS subvolume snapshot "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot rm '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=group_name,type=CephString,req=false '
+ 'name=force,type=CephBool,req=false ',
+ 'desc': "Delete a snapshot of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume resize '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=new_size,type=CephString,req=true '
+ 'name=group_name,type=CephString,req=false '
+ 'name=no_shrink,type=CephBool,req=false ',
+ 'desc': "Resize a CephFS subvolume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot protect '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "(deprecated) Protect snapshot of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot unprotect '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "(deprecated) Unprotect a snapshot of a CephFS subvolume in a volume, "
+ "and optionally, in a specific subvolume group",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs subvolume snapshot clone '
+ 'name=vol_name,type=CephString '
+ 'name=sub_name,type=CephString '
+ 'name=snap_name,type=CephString '
+ 'name=target_sub_name,type=CephString '
+ 'name=pool_layout,type=CephString,req=false '
+ 'name=group_name,type=CephString,req=false '
+ 'name=target_group_name,type=CephString,req=false ',
+ 'desc': "Clone a snapshot to target subvolume",
+ 'perm': 'rw'
+ },
+ {
+ 'cmd': 'fs clone status '
+ 'name=vol_name,type=CephString '
+ 'name=clone_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Get status on a cloned subvolume.",
+ 'perm': 'r'
+ },
+ {
+ 'cmd': 'fs clone cancel '
+ 'name=vol_name,type=CephString '
+ 'name=clone_name,type=CephString '
+ 'name=group_name,type=CephString,req=false ',
+ 'desc': "Cancel an pending or ongoing clone operation.",
+ 'perm': 'r'
+ },
+
+ # volume ls [recursive]
+ # subvolume ls <volume>
+ # volume authorize/deauthorize
+ # subvolume authorize/deauthorize
+
+ # volume describe (free space, etc)
+ # volume auth list (vc.get_authorized_ids)
+
+ # snapshots?
+
+ # FIXME: we're doing CephFSVolumeClient.recover on every
+ # path where we instantiate and connect a client. Perhaps
+ # keep clients alive longer, or just pass a "don't recover"
+ # flag in if it's the >1st time we connected a particular
+ # volume in the lifetime of this module instance.
+ ]
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'max_concurrent_clones',
+ 'type': 'int',
+ 'default': 4,
+ 'desc': 'Number of asynchronous cloner threads',
+ }
+ ]
+
+ def __init__(self, *args, **kwargs):
+ self.inited = False
+ # for mypy
+ self.max_concurrent_clones = None
+ self.lock = threading.Lock()
+ super(Module, self).__init__(*args, **kwargs)
+ # Initialize config option members
+ self.config_notify()
+ with self.lock:
+ self.vc = VolumeClient(self)
+ self.inited = True
+
+ def __del__(self):
+ self.vc.shutdown()
+
+ def shutdown(self):
+ self.vc.shutdown()
+
+ def config_notify(self):
+ """
+ This method is called whenever one of our config options is changed.
+ """
+ with self.lock:
+ for opt in self.MODULE_OPTIONS:
+ setattr(self,
+ opt['name'], # type: ignore
+ self.get_module_option(opt['name'])) # type: ignore
+ self.log.debug(' mgr option %s = %s',
+ opt['name'], getattr(self, opt['name'])) # type: ignore
+ if self.inited:
+ if opt['name'] == "max_concurrent_clones":
+ self.vc.cloner.reconfigure_max_concurrent_clones(self.max_concurrent_clones)
+
+ def handle_command(self, inbuf, cmd):
+ handler_name = "_cmd_" + cmd['prefix'].replace(" ", "_")
+ try:
+ handler = getattr(self, handler_name)
+ except AttributeError:
+ return -errno.EINVAL, "", "Unknown command"
+
+ return handler(inbuf, cmd)
+
+ @mgr_cmd_wrap
+ def _cmd_fs_volume_create(self, inbuf, cmd):
+ vol_id = cmd['name']
+ return self.vc.create_fs_volume(vol_id)
+
+ @mgr_cmd_wrap
+ def _cmd_fs_volume_rm(self, inbuf, cmd):
+ vol_name = cmd['vol_name']
+ confirm = cmd.get('yes-i-really-mean-it', None)
+ return self.vc.delete_fs_volume(vol_name, confirm)
+
+ @mgr_cmd_wrap
+ def _cmd_fs_volume_ls(self, inbuf, cmd):
+ return self.vc.list_fs_volumes()
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_create(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empty string(str), error message (str)
+ """
+ return self.vc.create_subvolume_group(
+ vol_name=cmd['vol_name'], group_name=cmd['group_name'],
+ pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755'),
+ uid=cmd.get('uid', None), gid=cmd.get('gid', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empty string(str), error message (str)
+ """
+ return self.vc.remove_subvolume_group(vol_name=cmd['vol_name'],
+ group_name=cmd['group_name'],
+ force=cmd.get('force', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_ls(self, inbuf, cmd):
+ return self.vc.list_subvolume_groups(vol_name=cmd['vol_name'])
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_create(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empty string(str), error message (str)
+ """
+ return self.vc.create_subvolume(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None),
+ size=cmd.get('size', None),
+ pool_layout=cmd.get('pool_layout', None),
+ uid=cmd.get('uid', None),
+ gid=cmd.get('gid', None),
+ mode=cmd.get('mode', '755'),
+ namespace_isolated=cmd.get('namespace_isolated', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_rm(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empty string(str), error message (str)
+ """
+ return self.vc.remove_subvolume(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None),
+ force=cmd.get('force', False),
+ retain_snapshots=cmd.get('retain_snapshots', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_authorize(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), secret key(str), error message (str)
+ """
+ return self.vc.authorize_subvolume(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ auth_id=cmd['auth_id'],
+ group_name=cmd.get('group_name', None),
+ access_level=cmd.get('access_level', 'rw'),
+ tenant_id=cmd.get('tenant_id', None),
+ allow_existing_id=cmd.get('allow_existing_id', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_deauthorize(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empty string(str), error message (str)
+ """
+ return self.vc.deauthorize_subvolume(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ auth_id=cmd['auth_id'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_authorized_list(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), list of authids(json), error message (str)
+ """
+ return self.vc.authorized_list(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_evict(self, inbuf, cmd):
+ """
+ :return: a 3-tuple of return code(int), empyt string(str), error message (str)
+ """
+ return self.vc.evict(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ auth_id=cmd['auth_id'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_ls(self, inbuf, cmd):
+ return self.vc.list_subvolumes(vol_name=cmd['vol_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_getpath(self, inbuf, cmd):
+ return self.vc.getpath_subvolume_group(
+ vol_name=cmd['vol_name'], group_name=cmd['group_name'])
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_getpath(self, inbuf, cmd):
+ return self.vc.subvolume_getpath(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_info(self, inbuf, cmd):
+ return self.vc.subvolume_info(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_snapshot_create(self, inbuf, cmd):
+ return self.vc.create_subvolume_group_snapshot(vol_name=cmd['vol_name'],
+ group_name=cmd['group_name'],
+ snap_name=cmd['snap_name'])
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_snapshot_rm(self, inbuf, cmd):
+ return self.vc.remove_subvolume_group_snapshot(vol_name=cmd['vol_name'],
+ group_name=cmd['group_name'],
+ snap_name=cmd['snap_name'],
+ force=cmd.get('force', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolumegroup_snapshot_ls(self, inbuf, cmd):
+ return self.vc.list_subvolume_group_snapshots(vol_name=cmd['vol_name'],
+ group_name=cmd['group_name'])
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_create(self, inbuf, cmd):
+ return self.vc.create_subvolume_snapshot(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ snap_name=cmd['snap_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_rm(self, inbuf, cmd):
+ return self.vc.remove_subvolume_snapshot(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ snap_name=cmd['snap_name'],
+ group_name=cmd.get('group_name', None),
+ force=cmd.get('force', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_info(self, inbuf, cmd):
+ return self.vc.subvolume_snapshot_info(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ snap_name=cmd['snap_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_ls(self, inbuf, cmd):
+ return self.vc.list_subvolume_snapshots(vol_name=cmd['vol_name'],
+ sub_name=cmd['sub_name'],
+ group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_resize(self, inbuf, cmd):
+ return self.vc.resize_subvolume(vol_name=cmd['vol_name'], sub_name=cmd['sub_name'],
+ new_size=cmd['new_size'], group_name=cmd.get('group_name', None),
+ no_shrink=cmd.get('no_shrink', False))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_protect(self, inbuf, cmd):
+ return self.vc.protect_subvolume_snapshot(vol_name=cmd['vol_name'], sub_name=cmd['sub_name'],
+ snap_name=cmd['snap_name'], group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_unprotect(self, inbuf, cmd):
+ return self.vc.unprotect_subvolume_snapshot(vol_name=cmd['vol_name'], sub_name=cmd['sub_name'],
+ snap_name=cmd['snap_name'], group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_subvolume_snapshot_clone(self, inbuf, cmd):
+ return self.vc.clone_subvolume_snapshot(
+ vol_name=cmd['vol_name'], sub_name=cmd['sub_name'], snap_name=cmd['snap_name'],
+ group_name=cmd.get('group_name', None), pool_layout=cmd.get('pool_layout', None),
+ target_sub_name=cmd['target_sub_name'], target_group_name=cmd.get('target_group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_clone_status(self, inbuf, cmd):
+ return self.vc.clone_status(
+ vol_name=cmd['vol_name'], clone_name=cmd['clone_name'], group_name=cmd.get('group_name', None))
+
+ @mgr_cmd_wrap
+ def _cmd_fs_clone_cancel(self, inbuf, cmd):
+ return self.vc.clone_cancel(
+ vol_name=cmd['vol_name'], clone_name=cmd['clone_name'], group_name=cmd.get('group_name', None))
diff --git a/src/pybind/mgr/zabbix/__init__.py b/src/pybind/mgr/zabbix/__init__.py
new file mode 100644
index 00000000..8f210ac9
--- /dev/null
+++ b/src/pybind/mgr/zabbix/__init__.py
@@ -0,0 +1 @@
+from .module import Module
diff --git a/src/pybind/mgr/zabbix/module.py b/src/pybind/mgr/zabbix/module.py
new file mode 100644
index 00000000..25d2f825
--- /dev/null
+++ b/src/pybind/mgr/zabbix/module.py
@@ -0,0 +1,380 @@
+"""
+Zabbix module for ceph-mgr
+
+Collect statistics from Ceph cluster and every X seconds send data to a Zabbix
+server using the zabbix_sender executable.
+"""
+import json
+import errno
+import re
+from subprocess import Popen, PIPE
+from threading import Event
+from mgr_module import MgrModule
+
+
+def avg(data):
+ if len(data):
+ return sum(data) / float(len(data))
+ else:
+ return 0
+
+
+class ZabbixSender(object):
+ def __init__(self, sender, host, port, log):
+ self.sender = sender
+ self.host = host
+ self.port = port
+ self.log = log
+
+ def send(self, hostname, data):
+ if len(data) == 0:
+ return
+
+ cmd = [self.sender, '-z', self.host, '-p', str(self.port), '-s',
+ hostname, '-vv', '-i', '-']
+
+ self.log.debug('Executing: %s', cmd)
+
+ proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+
+ for key, value in data.items():
+ proc.stdin.write('{0} ceph.{1} {2}\n'.format(hostname, key, value).encode('utf-8'))
+
+ stdout, stderr = proc.communicate()
+ if proc.returncode != 0:
+ raise RuntimeError('%s exited non-zero: %s' % (self.sender,
+ stderr))
+
+ self.log.debug('Zabbix Sender: %s', stdout.rstrip())
+
+
+class Module(MgrModule):
+ run = False
+ config = dict()
+ ceph_health_mapping = {'HEALTH_OK': 0, 'HEALTH_WARN': 1, 'HEALTH_ERR': 2}
+ _zabbix_hosts = list()
+
+ @property
+ def config_keys(self):
+ return dict((o['name'], o.get('default', None))
+ for o in self.MODULE_OPTIONS)
+
+ MODULE_OPTIONS = [
+ {
+ 'name': 'zabbix_sender',
+ 'default': '/usr/bin/zabbix_sender'
+ },
+ {
+ 'name': 'zabbix_host',
+ 'default': None
+ },
+ {
+ 'name': 'zabbix_port',
+ 'type': 'int',
+ 'default': 10051
+ },
+ {
+ 'name': 'identifier',
+ 'default': ""
+ },
+ {
+ 'name': 'interval',
+ 'type': 'secs',
+ 'default': 60
+ }
+ ]
+
+ COMMANDS = [
+ {
+ "cmd": "zabbix config-set name=key,type=CephString "
+ "name=value,type=CephString",
+ "desc": "Set a configuration value",
+ "perm": "rw"
+ },
+ {
+ "cmd": "zabbix config-show",
+ "desc": "Show current configuration",
+ "perm": "r"
+ },
+ {
+ "cmd": "zabbix send",
+ "desc": "Force sending data to Zabbix",
+ "perm": "rw"
+ },
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super(Module, self).__init__(*args, **kwargs)
+ self.event = Event()
+
+ def init_module_config(self):
+ self.fsid = self.get('mon_map')['fsid']
+ self.log.debug('Found Ceph fsid %s', self.fsid)
+
+ for key, default in self.config_keys.items():
+ self.set_config_option(key, self.get_module_option(key, default))
+
+ if self.config['zabbix_host']:
+ self._parse_zabbix_hosts()
+
+ def set_config_option(self, option, value):
+ if option not in self.config_keys.keys():
+ raise RuntimeError('{0} is a unknown configuration '
+ 'option'.format(option))
+
+ if option in ['zabbix_port', 'interval']:
+ try:
+ value = int(value)
+ except (ValueError, TypeError):
+ raise RuntimeError('invalid {0} configured. Please specify '
+ 'a valid integer'.format(option))
+
+ if option == 'interval' and value < 10:
+ raise RuntimeError('interval should be set to at least 10 seconds')
+
+ self.log.debug('Setting in-memory config option %s to: %s', option,
+ value)
+ self.config[option] = value
+ return True
+
+ def _parse_zabbix_hosts(self):
+ self._zabbix_hosts = list()
+ servers = self.config['zabbix_host'].split(",")
+ for server in servers:
+ uri = re.match("(?:(?:\[?)([a-z0-9-\.]+|[a-f0-9:\.]+)(?:\]?))(?:((?::))([0-9]{1,5}))?$", server)
+ if uri:
+ zabbix_host, sep, zabbix_port = uri.groups()
+ zabbix_port = zabbix_port if sep == ':' else self.config['zabbix_port']
+ self._zabbix_hosts.append({'zabbix_host': zabbix_host, 'zabbix_port': zabbix_port})
+ else:
+ self.log.error('Zabbix host "%s" is not valid', server)
+
+ self.log.error('Parsed Zabbix hosts: %s', self._zabbix_hosts)
+
+ def get_pg_stats(self):
+ stats = dict()
+
+ pg_states = ['active', 'peering', 'clean', 'scrubbing', 'undersized',
+ 'backfilling', 'recovering', 'degraded', 'inconsistent',
+ 'remapped', 'backfill_toofull', 'backfill_wait',
+ 'recovery_wait']
+
+ for state in pg_states:
+ stats['num_pg_{0}'.format(state)] = 0
+
+ pg_status = self.get('pg_status')
+
+ stats['num_pg'] = pg_status['num_pgs']
+
+ for state in pg_status['pgs_by_state']:
+ states = state['state_name'].split('+')
+ for s in pg_states:
+ key = 'num_pg_{0}'.format(s)
+ if s in states:
+ stats[key] += state['count']
+
+ return stats
+
+ def get_data(self):
+ data = dict()
+
+ health = json.loads(self.get('health')['json'])
+ # 'status' is luminous+, 'overall_status' is legacy mode.
+ data['overall_status'] = health.get('status',
+ health.get('overall_status'))
+ data['overall_status_int'] = \
+ self.ceph_health_mapping.get(data['overall_status'])
+
+ mon_status = json.loads(self.get('mon_status')['json'])
+ data['num_mon'] = len(mon_status['monmap']['mons'])
+
+ df = self.get('df')
+ data['num_pools'] = len(df['pools'])
+ data['total_used_bytes'] = df['stats']['total_used_bytes']
+ data['total_bytes'] = df['stats']['total_bytes']
+ data['total_avail_bytes'] = df['stats']['total_avail_bytes']
+
+ wr_ops = 0
+ rd_ops = 0
+ wr_bytes = 0
+ rd_bytes = 0
+
+ for pool in df['pools']:
+ wr_ops += pool['stats']['wr']
+ rd_ops += pool['stats']['rd']
+ wr_bytes += pool['stats']['wr_bytes']
+ rd_bytes += pool['stats']['rd_bytes']
+
+ data['wr_ops'] = wr_ops
+ data['rd_ops'] = rd_ops
+ data['wr_bytes'] = wr_bytes
+ data['rd_bytes'] = rd_bytes
+
+ osd_map = self.get('osd_map')
+ data['num_osd'] = len(osd_map['osds'])
+ data['osd_nearfull_ratio'] = osd_map['nearfull_ratio']
+ data['osd_full_ratio'] = osd_map['full_ratio']
+ data['osd_backfillfull_ratio'] = osd_map['backfillfull_ratio']
+
+ data['num_pg_temp'] = len(osd_map['pg_temp'])
+
+ num_up = 0
+ num_in = 0
+ for osd in osd_map['osds']:
+ if osd['up'] == 1:
+ num_up += 1
+
+ if osd['in'] == 1:
+ num_in += 1
+
+ data['num_osd_up'] = num_up
+ data['num_osd_in'] = num_in
+
+ osd_fill = list()
+ osd_pgs = list()
+ osd_apply_latency_ns = list()
+ osd_commit_latency_ns = list()
+
+ osd_stats = self.get('osd_stats')
+ for osd in osd_stats['osd_stats']:
+ if osd['kb'] == 0:
+ continue
+ osd_fill.append((float(osd['kb_used']) / float(osd['kb'])) * 100)
+ osd_pgs.append(osd['num_pgs'])
+ osd_apply_latency_ns.append(osd['perf_stat']['apply_latency_ns'])
+ osd_commit_latency_ns.append(osd['perf_stat']['commit_latency_ns'])
+
+ try:
+ data['osd_max_fill'] = max(osd_fill)
+ data['osd_min_fill'] = min(osd_fill)
+ data['osd_avg_fill'] = avg(osd_fill)
+ data['osd_max_pgs'] = max(osd_pgs)
+ data['osd_min_pgs'] = min(osd_pgs)
+ data['osd_avg_pgs'] = avg(osd_pgs)
+ except ValueError:
+ pass
+
+ try:
+ data['osd_latency_apply_max'] = max(osd_apply_latency_ns) / 1000000.0 # ns -> ms
+ data['osd_latency_apply_min'] = min(osd_apply_latency_ns) / 1000000.0 # ns -> ms
+ data['osd_latency_apply_avg'] = avg(osd_apply_latency_ns) / 1000000.0 # ns -> ms
+
+ data['osd_latency_commit_max'] = max(osd_commit_latency_ns) / 1000000.0 # ns -> ms
+ data['osd_latency_commit_min'] = min(osd_commit_latency_ns) / 1000000.0 # ns -> ms
+ data['osd_latency_commit_avg'] = avg(osd_commit_latency_ns) / 1000000.0 # ns -> ms
+ except ValueError:
+ pass
+
+ data.update(self.get_pg_stats())
+
+ return data
+
+ def send(self):
+ data = self.get_data()
+
+ identifier = self.config['identifier']
+ if identifier is None or len(identifier) == 0:
+ identifier = 'ceph-{0}'.format(self.fsid)
+
+ if not self.config['zabbix_host'] or not self._zabbix_hosts:
+ self.log.error('Zabbix server not set, please configure using: '
+ 'ceph zabbix config-set zabbix_host <zabbix_host>')
+ self.set_health_checks({
+ 'MGR_ZABBIX_NO_SERVER': {
+ 'severity': 'warning',
+ 'summary': 'No Zabbix server configured',
+ 'detail': ['Configuration value zabbix_host not configured']
+ }
+ })
+ return
+
+ result = True
+
+ for server in self._zabbix_hosts:
+ self.log.info(
+ 'Sending data to Zabbix server %s, port %s as host/identifier %s',
+ server['zabbix_host'], server['zabbix_port'], identifier)
+ self.log.debug(data)
+
+ try:
+ zabbix = ZabbixSender(self.config['zabbix_sender'],
+ server['zabbix_host'],
+ server['zabbix_port'], self.log)
+ zabbix.send(identifier, data)
+ except Exception as exc:
+ self.log.exception('Failed to send.')
+ self.set_health_checks({
+ 'MGR_ZABBIX_SEND_FAILED': {
+ 'severity': 'warning',
+ 'summary': 'Failed to send data to Zabbix',
+ 'detail': [str(exc)]
+ }
+ })
+ result = False
+
+ self.set_health_checks(dict())
+ return result
+
+ def handle_command(self, inbuf, command):
+ if command['prefix'] == 'zabbix config-show':
+ return 0, json.dumps(self.config), ''
+ elif command['prefix'] == 'zabbix config-set':
+ key = command['key']
+ value = command['value']
+ if not value:
+ return -errno.EINVAL, '', 'Value should not be empty or None'
+
+ self.log.debug('Setting configuration option %s to %s', key, value)
+ if self.set_config_option(key, value):
+ self.set_module_option(key, value)
+ if key == 'zabbix_host' or key == 'zabbix_port':
+ self._parse_zabbix_hosts()
+ return 0, 'Configuration option {0} updated'.format(key), ''
+
+ return 1,\
+ 'Failed to update configuration option {0}'.format(key), ''
+
+ elif command['prefix'] == 'zabbix send':
+ if self.send():
+ return 0, 'Sending data to Zabbix', ''
+
+ return 1, 'Failed to send data to Zabbix', ''
+ else:
+ return (-errno.EINVAL, '',
+ "Command not found '{0}'".format(command['prefix']))
+
+ def shutdown(self):
+ self.log.info('Stopping zabbix')
+ self.run = False
+ self.event.set()
+
+ def serve(self):
+ self.log.info('Zabbix module starting up')
+ self.run = True
+
+ self.init_module_config()
+
+ while self.run:
+ self.log.debug('Waking up for new iteration')
+
+ try:
+ self.send()
+ except Exception as exc:
+ # Shouldn't happen, but let's log it and retry next interval,
+ # rather than dying completely.
+ self.log.exception("Unexpected error during send():")
+
+ interval = self.config['interval']
+ self.log.debug('Sleeping for %d seconds', interval)
+ self.event.wait(interval)
+
+ def self_test(self):
+ data = self.get_data()
+
+ if data['overall_status'] not in self.ceph_health_mapping:
+ raise RuntimeError('No valid overall_status found in data')
+
+ int(data['overall_status_int'])
+
+ if data['num_mon'] < 1:
+ raise RuntimeError('num_mon is smaller than 1')
diff --git a/src/pybind/mgr/zabbix/zabbix_template.xml b/src/pybind/mgr/zabbix/zabbix_template.xml
new file mode 100644
index 00000000..d75d912e
--- /dev/null
+++ b/src/pybind/mgr/zabbix/zabbix_template.xml
@@ -0,0 +1,2569 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<zabbix_export>
+ <version>3.0</version>
+ <date>2017-10-24T07:00:13Z</date>
+ <groups>
+ <group>
+ <name>Templates</name>
+ </group>
+ </groups>
+ <templates>
+ <template>
+ <template>ceph-mgr Zabbix module</template>
+ <name>ceph-mgr Zabbix module</name>
+ <description/>
+ <groups>
+ <group>
+ <name>Templates</name>
+ </group>
+ </groups>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <items>
+ <item>
+ <name>Number of Monitors</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_mon</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Number of Monitors configured in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of OSDs</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_osd</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Number of OSDs in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of OSDs in state: IN</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_osd_in</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of IN OSDs in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of OSDs in state: UP</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_osd_up</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of UP OSDs in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Temporary state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_temp</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in pg_temp state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Active state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_active</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in active state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Clean state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_clean</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in clean state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Peering state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_peering</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in peering state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Scrubbing state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_scrubbing</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in scrubbing state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Undersized state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_undersized</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in undersized state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in Backfilling state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_backfilling</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in backfilling state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in degraded state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_degraded</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in degraded state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in inconsistent state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_inconsistent</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in inconsistent state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in remapped state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_remapped</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in remapped state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in recovering state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_recovering</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in recovering state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in backfill_toofull state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_backfill_toofull</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in backfill_toofull state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in backfill_wait state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_backfill_wait</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in backfill_wait state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Placement Groups in recovery_wait state</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pg_recovery_wait</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of Placement Groups in recovery_wait state</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Number of Pools</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.num_pools</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of pools in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD avg fill</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_avg_fill</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Average fill of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD max PGs</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_max_pgs</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Maximum amount of PGs on OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD min PGs</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_min_pgs</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Minimum amount of PGs on OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD avg PGs</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_avg_pgs</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Average amount of PGs on OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph backfill full ratio</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>1</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_backfillfull_ratio</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>100</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Backfill full ratio setting of Ceph cluster as configured on OSDMap</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph full ratio</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>1</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_full_ratio</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>100</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Full ratio setting of Ceph cluster as configured on OSDMap</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Apply latency Avg</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_apply_avg</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Average apply latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Apply latency Max</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_apply_max</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Maximum apply latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Apply latency Min</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_apply_min</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Miniumum apply latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Commit latency Avg</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_commit_avg</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Average commit latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Commit latency Max</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_commit_max</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Maximum commit latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD Commit latency Min</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_latency_commit_min</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Minimum commit latency of OSDs</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD max fill</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_max_fill</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Percentage fill of maximum filled OSD</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph OSD min fill</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_min_fill</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Percentage fill of minimum filled OSD</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph nearfull ratio</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>1</multiplier>
+ <snmp_oid/>
+ <key>ceph.osd_nearfull_ratio</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>0</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>100</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Near full ratio setting of Ceph cluster as configured on OSDMap</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Overall Ceph status</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.overall_status</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>0</trends>
+ <status>0</status>
+ <value_type>4</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Overall Ceph cluster status, eg HEALTH_OK, HEALTH_WARN of HEALTH_ERR</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Overal Ceph status (numeric)</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.overall_status_int</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Overal Ceph status in numeric value. OK: 0, WARN: 1, ERR: 2</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph Read bandwidth</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.rd_bytes</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units>b</units>
+ <delta>1</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Global read bandwidth</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph Read operations</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.rd_ops</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>1</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Global read operations per second</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Total bytes available</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.total_avail_bytes</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units>B</units>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total bytes available in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Total bytes</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.total_bytes</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units>B</units>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total (RAW) capacity of Ceph cluster in bytes</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Total number of objects</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.total_objects</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total number of objects in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Total bytes used</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.total_used_bytes</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units>B</units>
+ <delta>0</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Total bytes used in Ceph cluster</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph Write bandwidth</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.wr_bytes</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units>b</units>
+ <delta>1</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Global write bandwidth</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ <item>
+ <name>Ceph Write operations</name>
+ <type>2</type>
+ <snmp_community/>
+ <multiplier>0</multiplier>
+ <snmp_oid/>
+ <key>ceph.wr_ops</key>
+ <delay>0</delay>
+ <history>90</history>
+ <trends>365</trends>
+ <status>0</status>
+ <value_type>3</value_type>
+ <allowed_hosts/>
+ <units/>
+ <delta>1</delta>
+ <snmpv3_contextname/>
+ <snmpv3_securityname/>
+ <snmpv3_securitylevel>0</snmpv3_securitylevel>
+ <snmpv3_authprotocol>0</snmpv3_authprotocol>
+ <snmpv3_authpassphrase/>
+ <snmpv3_privprotocol>0</snmpv3_privprotocol>
+ <snmpv3_privpassphrase/>
+ <formula>1</formula>
+ <delay_flex/>
+ <params/>
+ <ipmi_sensor/>
+ <data_type>0</data_type>
+ <authtype>0</authtype>
+ <username/>
+ <password/>
+ <publickey/>
+ <privatekey/>
+ <port/>
+ <description>Global write operations per second</description>
+ <inventory_link>0</inventory_link>
+ <applications>
+ <application>
+ <name>Ceph</name>
+ </application>
+ </applications>
+ <valuemap/>
+ <logtimefmt/>
+ </item>
+ </items>
+ <discovery_rules/>
+ <macros/>
+ <templates/>
+ <screens>
+ <screen>
+ <name>Ceph</name>
+ <hsize>1</hsize>
+ <vsize>7</vsize>
+ <screen_items>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>500</width>
+ <height>100</height>
+ <x>0</x>
+ <y>0</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph storage overview</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>1</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph free space</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>2</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph health</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>3</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph bandwidth</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>4</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph I/O</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>5</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph OSD utilization</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ <screen_item>
+ <resourcetype>0</resourcetype>
+ <width>900</width>
+ <height>200</height>
+ <x>0</x>
+ <y>6</y>
+ <colspan>1</colspan>
+ <rowspan>1</rowspan>
+ <elements>0</elements>
+ <valign>0</valign>
+ <halign>0</halign>
+ <style>0</style>
+ <url/>
+ <dynamic>0</dynamic>
+ <sort_triggers>0</sort_triggers>
+ <resource>
+ <name>Ceph OSD latency</name>
+ <host>ceph-mgr Zabbix module</host>
+ </resource>
+ <max_columns>3</max_columns>
+ <application/>
+ </screen_item>
+ </screen_items>
+ </screen>
+ </screens>
+ </template>
+ </templates>
+ <triggers>
+ <trigger>
+ <expression>{ceph-mgr Zabbix module:ceph.overall_status_int.last()}=2</expression>
+ <name>Ceph cluster in ERR state</name>
+ <url/>
+ <status>0</status>
+ <priority>5</priority>
+ <description>Ceph cluster is in ERR state</description>
+ <type>0</type>
+ <dependencies/>
+ </trigger>
+ <trigger>
+ <expression>{ceph-mgr Zabbix module:ceph.overall_status_int.avg(1h)}=1</expression>
+ <name>Ceph cluster in WARN state</name>
+ <url/>
+ <status>0</status>
+ <priority>4</priority>
+ <description>Issue a trigger if Ceph cluster is in WARN state for &gt;1h</description>
+ <type>0</type>
+ <dependencies/>
+ </trigger>
+ <trigger>
+ <expression>{ceph-mgr Zabbix module:ceph.num_osd_in.change()}&gt;0</expression>
+ <name>Number of IN OSDs decreased</name>
+ <url/>
+ <status>0</status>
+ <priority>2</priority>
+ <description>Amount of OSDs in IN state decreased</description>
+ <type>0</type>
+ <dependencies/>
+ </trigger>
+ <trigger>
+ <expression>{ceph-mgr Zabbix module:ceph.num_osd_up.change()}&gt;0</expression>
+ <name>Number of UP OSDs decreased</name>
+ <url/>
+ <status>0</status>
+ <priority>2</priority>
+ <description>Amount of OSDs in UP state decreased</description>
+ <type>0</type>
+ <dependencies/>
+ </trigger>
+ </triggers>
+ <graphs>
+ <graph>
+ <name>Ceph bandwidth</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>100.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>1</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>0</ymin_type_1>
+ <ymax_type_1>0</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>1A7C11</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.rd_bytes</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>F63100</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.wr_bytes</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph free space</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>100.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>0</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>1</ymin_type_1>
+ <ymax_type_1>2</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.total_bytes</key>
+ </ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>00AA00</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.total_avail_bytes</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>DD0000</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.total_used_bytes</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph health</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>2.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>0</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>1</ymin_type_1>
+ <ymax_type_1>1</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>1A7C11</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>7</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.overall_status_int</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph I/O</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>100.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>1</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>1</ymin_type_1>
+ <ymax_type_1>0</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>1A7C11</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.rd_ops</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>F63100</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.wr_ops</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph OSD latency</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>100.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>0</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>0</ymin_type_1>
+ <ymax_type_1>0</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>1A7C11</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_apply_avg</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>F63100</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_commit_avg</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>2</sortorder>
+ <drawtype>0</drawtype>
+ <color>2774A4</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_apply_max</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>3</sortorder>
+ <drawtype>0</drawtype>
+ <color>A54F10</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_commit_max</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>4</sortorder>
+ <drawtype>0</drawtype>
+ <color>FC6EA3</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_apply_min</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>5</sortorder>
+ <drawtype>0</drawtype>
+ <color>6C59DC</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>4</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_latency_commit_min</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph OSD utilization</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>100.0000</yaxismax>
+ <show_work_period>1</show_work_period>
+ <show_triggers>1</show_triggers>
+ <type>0</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>1</ymin_type_1>
+ <ymax_type_1>1</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>0000CC</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_nearfull_ratio</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>F63100</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_full_ratio</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>2</sortorder>
+ <drawtype>0</drawtype>
+ <color>CC00CC</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_backfillfull_ratio</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>3</sortorder>
+ <drawtype>0</drawtype>
+ <color>A54F10</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_max_fill</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>4</sortorder>
+ <drawtype>0</drawtype>
+ <color>FC6EA3</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_avg_fill</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>5</sortorder>
+ <drawtype>0</drawtype>
+ <color>6C59DC</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.osd_min_fill</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ <graph>
+ <name>Ceph storage overview</name>
+ <width>900</width>
+ <height>200</height>
+ <yaxismin>0.0000</yaxismin>
+ <yaxismax>0.0000</yaxismax>
+ <show_work_period>0</show_work_period>
+ <show_triggers>0</show_triggers>
+ <type>2</type>
+ <show_legend>1</show_legend>
+ <show_3d>0</show_3d>
+ <percent_left>0.0000</percent_left>
+ <percent_right>0.0000</percent_right>
+ <ymin_type_1>0</ymin_type_1>
+ <ymax_type_1>0</ymax_type_1>
+ <ymin_item_1>0</ymin_item_1>
+ <ymax_item_1>0</ymax_item_1>
+ <graph_items>
+ <graph_item>
+ <sortorder>0</sortorder>
+ <drawtype>0</drawtype>
+ <color>F63100</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.total_used_bytes</key>
+ </item>
+ </graph_item>
+ <graph_item>
+ <sortorder>1</sortorder>
+ <drawtype>0</drawtype>
+ <color>00CC00</color>
+ <yaxisside>0</yaxisside>
+ <calc_fnc>2</calc_fnc>
+ <type>0</type>
+ <item>
+ <host>ceph-mgr Zabbix module</host>
+ <key>ceph.total_avail_bytes</key>
+ </item>
+ </graph_item>
+ </graph_items>
+ </graph>
+ </graphs>
+</zabbix_export>
diff --git a/src/pybind/rados/CMakeLists.txt b/src/pybind/rados/CMakeLists.txt
new file mode 100644
index 00000000..7b14c0e0
--- /dev/null
+++ b/src/pybind/rados/CMakeLists.txt
@@ -0,0 +1,3 @@
+distutils_add_cython_module(cython${PYTHON_VERSION}_rados ${CMAKE_CURRENT_SOURCE_DIR}/rados.pyx)
+add_dependencies(cython${PYTHON_VERSION}_rados rados)
+distutils_install_cython_module(cython${PYTHON_VERSION}_rados)
diff --git a/src/pybind/rados/MANIFEST.in b/src/pybind/rados/MANIFEST.in
new file mode 100644
index 00000000..79f1d9ce
--- /dev/null
+++ b/src/pybind/rados/MANIFEST.in
@@ -0,0 +1,2 @@
+include rados.pyx
+include rados.pxd
diff --git a/src/pybind/rados/rados.pxd b/src/pybind/rados/rados.pxd
new file mode 100644
index 00000000..d4dddb38
--- /dev/null
+++ b/src/pybind/rados/rados.pxd
@@ -0,0 +1,39 @@
+# cython: embedsignature=True
+#
+# Shared object for librbdpy
+#
+# Copyright 2016 Mehdi Abaakouk <sileht@redhat.com>
+
+
+cdef extern from "rados/librados.h" nogil:
+ ctypedef void* rados_t
+ ctypedef void* rados_config_t
+ ctypedef void* rados_ioctx_t
+
+
+cdef class Rados(object):
+ cdef:
+ rados_t cluster
+ public object state
+ public object monitor_callback
+ public object monitor_callback2
+ public object parsed_args
+ public object conf_defaults
+ public object conffile
+ public object rados_id
+
+
+cdef class Ioctx(object):
+ cdef:
+ rados_ioctx_t io
+ public object name
+ public object state
+ public object locator_key
+ public object nspace
+
+ # TODO(sileht): we need to track leaving completion objects
+ # I guess we can do that in a lighter ways, but keep code simple
+ # as before for now
+ public object safe_completions
+ public object complete_completions
+ public object lock
diff --git a/src/pybind/rados/rados.pyx b/src/pybind/rados/rados.pyx
new file mode 100644
index 00000000..c8e20b7c
--- /dev/null
+++ b/src/pybind/rados/rados.pyx
@@ -0,0 +1,4110 @@
+# cython: embedsignature=True
+"""
+This module is a thin wrapper around librados.
+
+Error codes from librados are turned into exceptions that subclass
+:class:`Error`. Almost all methods may raise :class:`Error(the base class of all rados exceptions), :class:`PermissionError`
+(the base class of all rados exceptions), :class:`PermissionError`
+and :class:`IOError`, in addition to those documented for the
+method.
+"""
+# Copyright 2011 Josh Durgin
+# Copyright 2011, Hannu Valtonen <hannu.valtonen@ormod.com>
+# Copyright 2015 Hector Martin <marcan@marcan.st>
+# Copyright 2016 Mehdi Abaakouk <sileht@redhat.com>
+
+from cpython cimport PyObject, ref
+from cpython.pycapsule cimport *
+from libc cimport errno
+from libc.stdint cimport *
+from libc.stdlib cimport malloc, realloc, free
+
+import sys
+import threading
+import time
+
+try:
+ from collections.abc import Callable
+except ImportError:
+ from collections import Callable
+from datetime import datetime
+from functools import partial, wraps
+from itertools import chain
+
+# Are we running Python 2.x
+if sys.version_info[0] < 3:
+ str_type = basestring
+else:
+ str_type = str
+
+
+cdef extern from "Python.h":
+ # These are in cpython/string.pxd, but use "object" types instead of
+ # PyObject*, which invokes assumptions in cpython that we need to
+ # legitimately break to implement zero-copy string buffers in Ioctx.read().
+ # This is valid use of the Python API and documented as a special case.
+ PyObject *PyBytes_FromStringAndSize(char *v, Py_ssize_t len) except NULL
+ char* PyBytes_AsString(PyObject *string) except NULL
+ int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
+ void PyEval_InitThreads()
+
+
+cdef extern from "time.h":
+ ctypedef long int time_t
+ ctypedef long int suseconds_t
+
+
+cdef extern from "sys/time.h":
+ cdef struct timeval:
+ time_t tv_sec
+ suseconds_t tv_usec
+
+
+cdef extern from "rados/rados_types.h" nogil:
+ cdef char* _LIBRADOS_ALL_NSPACES "LIBRADOS_ALL_NSPACES"
+
+
+cdef extern from "rados/librados.h" nogil:
+ enum:
+ _LIBRADOS_OP_FLAG_EXCL "LIBRADOS_OP_FLAG_EXCL"
+ _LIBRADOS_OP_FLAG_FAILOK "LIBRADOS_OP_FLAG_FAILOK"
+ _LIBRADOS_OP_FLAG_FADVISE_RANDOM "LIBRADOS_OP_FLAG_FADVISE_RANDOM"
+ _LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL "LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL"
+ _LIBRADOS_OP_FLAG_FADVISE_WILLNEED "LIBRADOS_OP_FLAG_FADVISE_WILLNEED"
+ _LIBRADOS_OP_FLAG_FADVISE_DONTNEED "LIBRADOS_OP_FLAG_FADVISE_DONTNEED"
+ _LIBRADOS_OP_FLAG_FADVISE_NOCACHE "LIBRADOS_OP_FLAG_FADVISE_NOCACHE"
+
+
+ enum:
+ _LIBRADOS_OPERATION_NOFLAG "LIBRADOS_OPERATION_NOFLAG"
+ _LIBRADOS_OPERATION_BALANCE_READS "LIBRADOS_OPERATION_BALANCE_READS"
+ _LIBRADOS_OPERATION_LOCALIZE_READS "LIBRADOS_OPERATION_LOCALIZE_READS"
+ _LIBRADOS_OPERATION_ORDER_READS_WRITES "LIBRADOS_OPERATION_ORDER_READS_WRITES"
+ _LIBRADOS_OPERATION_IGNORE_CACHE "LIBRADOS_OPERATION_IGNORE_CACHE"
+ _LIBRADOS_OPERATION_SKIPRWLOCKS "LIBRADOS_OPERATION_SKIPRWLOCKS"
+ _LIBRADOS_OPERATION_IGNORE_OVERLAY "LIBRADOS_OPERATION_IGNORE_OVERLAY"
+ _LIBRADOS_CREATE_EXCLUSIVE "LIBRADOS_CREATE_EXCLUSIVE"
+ _LIBRADOS_CREATE_IDEMPOTENT "LIBRADOS_CREATE_IDEMPOTENT"
+
+ cdef uint64_t _LIBRADOS_SNAP_HEAD "LIBRADOS_SNAP_HEAD"
+
+ ctypedef void* rados_xattrs_iter_t
+ ctypedef void* rados_omap_iter_t
+ ctypedef void* rados_list_ctx_t
+ ctypedef uint64_t rados_snap_t
+ ctypedef void *rados_write_op_t
+ ctypedef void *rados_read_op_t
+ ctypedef void *rados_completion_t
+ ctypedef void (*rados_callback_t)(rados_completion_t cb, void *arg)
+ ctypedef void (*rados_log_callback_t)(void *arg, const char *line, const char *who,
+ uint64_t sec, uint64_t nsec, uint64_t seq, const char *level, const char *msg)
+ ctypedef void (*rados_log_callback2_t)(void *arg, const char *line, const char *channel, const char *who, const char *name,
+ uint64_t sec, uint64_t nsec, uint64_t seq, const char *level, const char *msg)
+
+
+ cdef struct rados_cluster_stat_t:
+ uint64_t kb
+ uint64_t kb_used
+ uint64_t kb_avail
+ uint64_t num_objects
+
+ cdef struct rados_pool_stat_t:
+ uint64_t num_bytes
+ uint64_t num_kb
+ uint64_t num_objects
+ uint64_t num_object_clones
+ uint64_t num_object_copies
+ uint64_t num_objects_missing_on_primary
+ uint64_t num_objects_unfound
+ uint64_t num_objects_degraded
+ uint64_t num_rd
+ uint64_t num_rd_kb
+ uint64_t num_wr
+ uint64_t num_wr_kb
+
+ void rados_buffer_free(char *buf)
+
+ void rados_version(int *major, int *minor, int *extra)
+ int rados_create2(rados_t *pcluster, const char *const clustername,
+ const char * const name, uint64_t flags)
+ int rados_create_with_context(rados_t *cluster, rados_config_t cct)
+ int rados_connect(rados_t cluster)
+ void rados_shutdown(rados_t cluster)
+ uint64_t rados_get_instance_id(rados_t cluster)
+ int rados_conf_read_file(rados_t cluster, const char *path)
+ int rados_conf_parse_argv_remainder(rados_t cluster, int argc, const char **argv, const char **remargv)
+ int rados_conf_parse_env(rados_t cluster, const char *var)
+ int rados_conf_set(rados_t cluster, char *option, const char *value)
+ int rados_conf_get(rados_t cluster, char *option, char *buf, size_t len)
+
+ int rados_ioctx_pool_stat(rados_ioctx_t io, rados_pool_stat_t *stats)
+ int64_t rados_pool_lookup(rados_t cluster, const char *pool_name)
+ int rados_pool_reverse_lookup(rados_t cluster, int64_t id, char *buf, size_t maxlen)
+ int rados_pool_create(rados_t cluster, const char *pool_name)
+ int rados_pool_create_with_crush_rule(rados_t cluster, const char *pool_name, uint8_t crush_rule_num)
+ int rados_pool_get_base_tier(rados_t cluster, int64_t pool, int64_t *base_tier)
+ int rados_pool_list(rados_t cluster, char *buf, size_t len)
+ int rados_pool_delete(rados_t cluster, const char *pool_name)
+ int rados_inconsistent_pg_list(rados_t cluster, int64_t pool, char *buf, size_t len)
+
+ int rados_cluster_stat(rados_t cluster, rados_cluster_stat_t *result)
+ int rados_cluster_fsid(rados_t cluster, char *buf, size_t len)
+ int rados_blacklist_add(rados_t cluster, char *client_address, uint32_t expire_seconds)
+ int rados_getaddrs(rados_t cluster, char** addrs)
+ int rados_application_enable(rados_ioctx_t io, const char *app_name,
+ int force)
+ void rados_set_osdmap_full_try(rados_ioctx_t io)
+ void rados_unset_osdmap_full_try(rados_ioctx_t io)
+ int rados_application_list(rados_ioctx_t io, char *values,
+ size_t *values_len)
+ int rados_application_metadata_get(rados_ioctx_t io, const char *app_name,
+ const char *key, char *value,
+ size_t *value_len)
+ int rados_application_metadata_set(rados_ioctx_t io, const char *app_name,
+ const char *key, const char *value)
+ int rados_application_metadata_remove(rados_ioctx_t io,
+ const char *app_name, const char *key)
+ int rados_application_metadata_list(rados_ioctx_t io,
+ const char *app_name, char *keys,
+ size_t *key_len, char *values,
+ size_t *value_len)
+ int rados_ping_monitor(rados_t cluster, const char *mon_id, char **outstr, size_t *outstrlen)
+ int rados_mon_command(rados_t cluster, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen,
+ char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int rados_mgr_command(rados_t cluster, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen,
+ char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int rados_mon_command_target(rados_t cluster, const char *name, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen,
+ char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int rados_osd_command(rados_t cluster, int osdid, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen,
+ char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int rados_pg_command(rados_t cluster, const char *pgstr, const char **cmd, size_t cmdlen,
+ const char *inbuf, size_t inbuflen,
+ char **outbuf, size_t *outbuflen,
+ char **outs, size_t *outslen)
+ int rados_monitor_log(rados_t cluster, const char *level, rados_log_callback_t cb, void *arg)
+ int rados_monitor_log2(rados_t cluster, const char *level, rados_log_callback2_t cb, void *arg)
+
+ int rados_wait_for_latest_osdmap(rados_t cluster)
+
+ int rados_service_register(rados_t cluster, const char *service, const char *daemon, const char *metadata_dict)
+ int rados_service_update_status(rados_t cluster, const char *status_dict)
+
+ int rados_ioctx_create(rados_t cluster, const char *pool_name, rados_ioctx_t *ioctx)
+ int rados_ioctx_create2(rados_t cluster, int64_t pool_id, rados_ioctx_t *ioctx)
+ void rados_ioctx_destroy(rados_ioctx_t io)
+ void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key)
+ void rados_ioctx_set_namespace(rados_ioctx_t io, const char * nspace)
+
+ uint64_t rados_get_last_version(rados_ioctx_t io)
+ int rados_stat(rados_ioctx_t io, const char *o, uint64_t *psize, time_t *pmtime)
+ int rados_write(rados_ioctx_t io, const char *oid, const char *buf, size_t len, uint64_t off)
+ int rados_write_full(rados_ioctx_t io, const char *oid, const char *buf, size_t len)
+ int rados_append(rados_ioctx_t io, const char *oid, const char *buf, size_t len)
+ int rados_read(rados_ioctx_t io, const char *oid, char *buf, size_t len, uint64_t off)
+ int rados_remove(rados_ioctx_t io, const char *oid)
+ int rados_trunc(rados_ioctx_t io, const char *oid, uint64_t size)
+ int rados_getxattr(rados_ioctx_t io, const char *o, const char *name, char *buf, size_t len)
+ int rados_setxattr(rados_ioctx_t io, const char *o, const char *name, const char *buf, size_t len)
+ int rados_rmxattr(rados_ioctx_t io, const char *o, const char *name)
+ int rados_getxattrs(rados_ioctx_t io, const char *oid, rados_xattrs_iter_t *iter)
+ int rados_getxattrs_next(rados_xattrs_iter_t iter, const char **name, const char **val, size_t *len)
+ void rados_getxattrs_end(rados_xattrs_iter_t iter)
+
+ int rados_nobjects_list_open(rados_ioctx_t io, rados_list_ctx_t *ctx)
+ int rados_nobjects_list_next(rados_list_ctx_t ctx, const char **entry, const char **key, const char **nspace)
+ void rados_nobjects_list_close(rados_list_ctx_t ctx)
+
+ int rados_ioctx_pool_requires_alignment2(rados_ioctx_t io, int * requires)
+ int rados_ioctx_pool_required_alignment2(rados_ioctx_t io, uint64_t * alignment)
+
+ int rados_ioctx_snap_rollback(rados_ioctx_t io, const char * oid, const char * snapname)
+ int rados_ioctx_snap_create(rados_ioctx_t io, const char * snapname)
+ int rados_ioctx_snap_remove(rados_ioctx_t io, const char * snapname)
+ int rados_ioctx_snap_lookup(rados_ioctx_t io, const char * name, rados_snap_t * id)
+ int rados_ioctx_snap_get_name(rados_ioctx_t io, rados_snap_t id, char * name, int maxlen)
+ void rados_ioctx_snap_set_read(rados_ioctx_t io, rados_snap_t snap)
+ int rados_ioctx_snap_list(rados_ioctx_t io, rados_snap_t * snaps, int maxlen)
+ int rados_ioctx_snap_get_stamp(rados_ioctx_t io, rados_snap_t id, time_t * t)
+
+ int rados_ioctx_selfmanaged_snap_create(rados_ioctx_t io,
+ rados_snap_t *snapid)
+ int rados_ioctx_selfmanaged_snap_remove(rados_ioctx_t io,
+ rados_snap_t snapid)
+ int rados_ioctx_selfmanaged_snap_set_write_ctx(rados_ioctx_t io,
+ rados_snap_t snap_seq,
+ rados_snap_t *snap,
+ int num_snaps)
+ int rados_ioctx_selfmanaged_snap_rollback(rados_ioctx_t io, const char *oid,
+ rados_snap_t snapid)
+
+ int rados_lock_exclusive(rados_ioctx_t io, const char * oid, const char * name,
+ const char * cookie, const char * desc,
+ timeval * duration, uint8_t flags)
+ int rados_lock_shared(rados_ioctx_t io, const char * o, const char * name,
+ const char * cookie, const char * tag, const char * desc,
+ timeval * duration, uint8_t flags)
+ int rados_unlock(rados_ioctx_t io, const char * o, const char * name, const char * cookie)
+
+ rados_write_op_t rados_create_write_op()
+ void rados_release_write_op(rados_write_op_t write_op)
+
+ rados_read_op_t rados_create_read_op()
+ void rados_release_read_op(rados_read_op_t read_op)
+
+ int rados_aio_create_completion(void * cb_arg, rados_callback_t cb_complete, rados_callback_t cb_safe, rados_completion_t * pc)
+ void rados_aio_release(rados_completion_t c)
+ int rados_aio_stat(rados_ioctx_t io, const char *oid, rados_completion_t completion, uint64_t *psize, time_t *pmtime)
+ int rados_aio_write(rados_ioctx_t io, const char * oid, rados_completion_t completion, const char * buf, size_t len, uint64_t off)
+ int rados_aio_append(rados_ioctx_t io, const char * oid, rados_completion_t completion, const char * buf, size_t len)
+ int rados_aio_write_full(rados_ioctx_t io, const char * oid, rados_completion_t completion, const char * buf, size_t len)
+ int rados_aio_remove(rados_ioctx_t io, const char * oid, rados_completion_t completion)
+ int rados_aio_read(rados_ioctx_t io, const char * oid, rados_completion_t completion, char * buf, size_t len, uint64_t off)
+ int rados_aio_flush(rados_ioctx_t io)
+
+ int rados_aio_get_return_value(rados_completion_t c)
+ int rados_aio_wait_for_complete_and_cb(rados_completion_t c)
+ int rados_aio_wait_for_safe_and_cb(rados_completion_t c)
+ int rados_aio_wait_for_complete(rados_completion_t c)
+ int rados_aio_wait_for_safe(rados_completion_t c)
+ int rados_aio_is_complete(rados_completion_t c)
+ int rados_aio_is_safe(rados_completion_t c)
+
+ int rados_exec(rados_ioctx_t io, const char * oid, const char * cls, const char * method,
+ const char * in_buf, size_t in_len, char * buf, size_t out_len)
+ int rados_aio_exec(rados_ioctx_t io, const char * oid, rados_completion_t completion, const char * cls, const char * method,
+ const char * in_buf, size_t in_len, char * buf, size_t out_len)
+
+ int rados_write_op_operate(rados_write_op_t write_op, rados_ioctx_t io, const char * oid, time_t * mtime, int flags)
+ int rados_aio_write_op_operate(rados_write_op_t write_op, rados_ioctx_t io, rados_completion_t completion, const char *oid, time_t *mtime, int flags)
+ void rados_write_op_omap_set(rados_write_op_t write_op, const char * const* keys, const char * const* vals, const size_t * lens, size_t num)
+ void rados_write_op_omap_rm_keys(rados_write_op_t write_op, const char * const* keys, size_t keys_len)
+ void rados_write_op_omap_clear(rados_write_op_t write_op)
+ void rados_write_op_set_flags(rados_write_op_t write_op, int flags)
+
+ void rados_write_op_create(rados_write_op_t write_op, int exclusive, const char *category)
+ void rados_write_op_append(rados_write_op_t write_op, const char *buffer, size_t len)
+ void rados_write_op_write_full(rados_write_op_t write_op, const char *buffer, size_t len)
+ void rados_write_op_assert_version(rados_write_op_t write_op, uint64_t ver)
+ void rados_write_op_write(rados_write_op_t write_op, const char *buffer, size_t len, uint64_t offset)
+ void rados_write_op_remove(rados_write_op_t write_op)
+ void rados_write_op_truncate(rados_write_op_t write_op, uint64_t offset)
+ void rados_write_op_zero(rados_write_op_t write_op, uint64_t offset, uint64_t len)
+
+ void rados_read_op_omap_get_vals2(rados_read_op_t read_op, const char * start_after, const char * filter_prefix, uint64_t max_return, rados_omap_iter_t * iter, unsigned char *pmore, int * prval)
+ void rados_read_op_omap_get_keys2(rados_read_op_t read_op, const char * start_after, uint64_t max_return, rados_omap_iter_t * iter, unsigned char *pmore, int * prval)
+ void rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op, const char * const* keys, size_t keys_len, rados_omap_iter_t * iter, int * prval)
+ int rados_read_op_operate(rados_read_op_t read_op, rados_ioctx_t io, const char * oid, int flags)
+ int rados_aio_read_op_operate(rados_read_op_t read_op, rados_ioctx_t io, rados_completion_t completion, const char *oid, int flags)
+ void rados_read_op_set_flags(rados_read_op_t read_op, int flags)
+ int rados_omap_get_next(rados_omap_iter_t iter, const char * const* key, const char * const* val, size_t * len)
+ void rados_omap_get_end(rados_omap_iter_t iter)
+ int rados_notify2(rados_ioctx_t io, const char * o, const char *buf, int buf_len, uint64_t timeout_ms, char **reply_buffer, size_t *reply_buffer_len)
+
+
+LIBRADOS_OP_FLAG_EXCL = _LIBRADOS_OP_FLAG_EXCL
+LIBRADOS_OP_FLAG_FAILOK = _LIBRADOS_OP_FLAG_FAILOK
+LIBRADOS_OP_FLAG_FADVISE_RANDOM = _LIBRADOS_OP_FLAG_FADVISE_RANDOM
+LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL = _LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL
+LIBRADOS_OP_FLAG_FADVISE_WILLNEED = _LIBRADOS_OP_FLAG_FADVISE_WILLNEED
+LIBRADOS_OP_FLAG_FADVISE_DONTNEED = _LIBRADOS_OP_FLAG_FADVISE_DONTNEED
+LIBRADOS_OP_FLAG_FADVISE_NOCACHE = _LIBRADOS_OP_FLAG_FADVISE_NOCACHE
+
+LIBRADOS_SNAP_HEAD = _LIBRADOS_SNAP_HEAD
+
+LIBRADOS_OPERATION_NOFLAG = _LIBRADOS_OPERATION_NOFLAG
+LIBRADOS_OPERATION_BALANCE_READS = _LIBRADOS_OPERATION_BALANCE_READS
+LIBRADOS_OPERATION_LOCALIZE_READS = _LIBRADOS_OPERATION_LOCALIZE_READS
+LIBRADOS_OPERATION_ORDER_READS_WRITES = _LIBRADOS_OPERATION_ORDER_READS_WRITES
+LIBRADOS_OPERATION_IGNORE_CACHE = _LIBRADOS_OPERATION_IGNORE_CACHE
+LIBRADOS_OPERATION_SKIPRWLOCKS = _LIBRADOS_OPERATION_SKIPRWLOCKS
+LIBRADOS_OPERATION_IGNORE_OVERLAY = _LIBRADOS_OPERATION_IGNORE_OVERLAY
+
+LIBRADOS_ALL_NSPACES = _LIBRADOS_ALL_NSPACES.decode('utf-8')
+
+LIBRADOS_CREATE_EXCLUSIVE = _LIBRADOS_CREATE_EXCLUSIVE
+LIBRADOS_CREATE_IDEMPOTENT = _LIBRADOS_CREATE_IDEMPOTENT
+
+ANONYMOUS_AUID = 0xffffffffffffffff
+ADMIN_AUID = 0
+
+
+class Error(Exception):
+ """ `Error` class, derived from `Exception` """
+ def __init__(self, message, errno=None):
+ super(Exception, self).__init__(message)
+ self.errno = errno
+
+ def __str__(self):
+ msg = super(Exception, self).__str__()
+ if self.errno is None:
+ return msg
+ return '[errno {0}] {1}'.format(self.errno, msg)
+
+ def __reduce__(self):
+ return (self.__class__, (self.message, self.errno))
+
+class InvalidArgumentError(Error):
+ pass
+
+class OSError(Error):
+ """ `OSError` class, derived from `Error` """
+ pass
+
+class InterruptedOrTimeoutError(OSError):
+ """ `InterruptedOrTimeoutError` class, derived from `OSError` """
+ pass
+
+
+class PermissionError(OSError):
+ """ `PermissionError` class, derived from `OSError` """
+ pass
+
+
+class PermissionDeniedError(OSError):
+ """ deal with EACCES related. """
+ pass
+
+
+class ObjectNotFound(OSError):
+ """ `ObjectNotFound` class, derived from `OSError` """
+ pass
+
+
+class NoData(OSError):
+ """ `NoData` class, derived from `OSError` """
+ pass
+
+
+class ObjectExists(OSError):
+ """ `ObjectExists` class, derived from `OSError` """
+ pass
+
+
+class ObjectBusy(OSError):
+ """ `ObjectBusy` class, derived from `IOError` """
+ pass
+
+
+class IOError(OSError):
+ """ `ObjectBusy` class, derived from `OSError` """
+ pass
+
+
+class NoSpace(OSError):
+ """ `NoSpace` class, derived from `OSError` """
+ pass
+
+
+class RadosStateError(Error):
+ """ `RadosStateError` class, derived from `Error` """
+ pass
+
+
+class IoctxStateError(Error):
+ """ `IoctxStateError` class, derived from `Error` """
+ pass
+
+
+class ObjectStateError(Error):
+ """ `ObjectStateError` class, derived from `Error` """
+ pass
+
+
+class LogicError(Error):
+ """ `` class, derived from `Error` """
+ pass
+
+
+class TimedOut(OSError):
+ """ `TimedOut` class, derived from `OSError` """
+ pass
+
+
+IF UNAME_SYSNAME == "FreeBSD":
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.EBUSY : ObjectBusy,
+ errno.ENOATTR : NoData,
+ errno.EINTR : InterruptedOrTimeoutError,
+ errno.ETIMEDOUT : TimedOut,
+ errno.EACCES : PermissionDeniedError,
+ errno.EINVAL : InvalidArgumentError,
+ }
+ELSE:
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.EBUSY : ObjectBusy,
+ errno.ENODATA : NoData,
+ errno.EINTR : InterruptedOrTimeoutError,
+ errno.ETIMEDOUT : TimedOut,
+ errno.EACCES : PermissionDeniedError,
+ errno.EINVAL : InvalidArgumentError,
+ }
+
+
+cdef make_ex(ret, msg):
+ """
+ Translate a librados return code into an exception.
+
+ :param ret: the return code
+ :type ret: int
+ :param msg: the error message to use
+ :type msg: str
+ :returns: a subclass of :class:`Error`
+ """
+ ret = abs(ret)
+ if ret in errno_to_exception:
+ return errno_to_exception[ret](msg, errno=ret)
+ else:
+ return OSError(msg, errno=ret)
+
+
+# helper to specify an optional argument, where in addition to `cls`, `None`
+# is also acceptable
+def opt(cls):
+ return (cls, None)
+
+
+# validate argument types of an instance method
+# kwargs is an un-ordered dict, so use args instead
+def requires(*types):
+ def is_type_of(v, t):
+ if t is None:
+ return v is None
+ else:
+ return isinstance(v, t)
+
+ def check_type(val, arg_name, arg_type):
+ if isinstance(arg_type, tuple):
+ if any(is_type_of(val, t) for t in arg_type):
+ return
+ type_names = ' or '.join('None' if t is None else t.__name__
+ for t in arg_type)
+ raise TypeError('%s must be %s' % (arg_name, type_names))
+ else:
+ if is_type_of(val, arg_type):
+ return
+ assert(arg_type is not None)
+ raise TypeError('%s must be %s' % (arg_name, arg_type.__name__))
+
+ def wrapper(f):
+ # FIXME(sileht): this stop with
+ # AttributeError: 'method_descriptor' object has no attribute '__module__'
+ # @wraps(f)
+ def validate_func(*args, **kwargs):
+ # ignore the `self` arg
+ pos_args = zip(args[1:], types)
+ named_args = ((kwargs[name], (name, spec)) for name, spec in types
+ if name in kwargs)
+ for arg_val, (arg_name, arg_type) in chain(pos_args, named_args):
+ check_type(arg_val, arg_name, arg_type)
+ return f(*args, **kwargs)
+ return validate_func
+ return wrapper
+
+
+def cstr(val, name, encoding="utf-8", opt=False):
+ """
+ Create a byte string from a Python string
+
+ :param basestring val: Python string
+ :param str name: Name of the string parameter, for exceptions
+ :param str encoding: Encoding to use
+ :param bool opt: If True, None is allowed
+ :rtype: bytes
+ :raises: :class:`InvalidArgument`
+ """
+ if opt and val is None:
+ return None
+ if isinstance(val, bytes):
+ return val
+ elif isinstance(val, unicode):
+ return val.encode(encoding)
+ else:
+ raise TypeError('%s must be a string' % name)
+
+
+def cstr_list(list_str, name, encoding="utf-8"):
+ return [cstr(s, name) for s in list_str]
+
+
+def decode_cstr(val, encoding="utf-8"):
+ """
+ Decode a byte string into a Python string.
+
+ :param bytes val: byte string
+ :rtype: unicode or None
+ """
+ if val is None:
+ return None
+
+ return val.decode(encoding)
+
+
+cdef char* opt_str(s) except? NULL:
+ if s is None:
+ return NULL
+ return s
+
+
+cdef void* realloc_chk(void* ptr, size_t size) except NULL:
+ cdef void *ret = realloc(ptr, size)
+ if ret == NULL:
+ raise MemoryError("realloc failed")
+ return ret
+
+
+cdef size_t * to_csize_t_array(list_int):
+ cdef size_t *ret = <size_t *>malloc(len(list_int) * sizeof(size_t))
+ if ret == NULL:
+ raise MemoryError("malloc failed")
+ for i in range(len(list_int)):
+ ret[i] = <size_t>list_int[i]
+ return ret
+
+
+cdef char ** to_bytes_array(list_bytes):
+ cdef char **ret = <char **>malloc(len(list_bytes) * sizeof(char *))
+ if ret == NULL:
+ raise MemoryError("malloc failed")
+ for i in range(len(list_bytes)):
+ ret[i] = <char *>list_bytes[i]
+ return ret
+
+
+
+cdef int __monitor_callback(void *arg, const char *line, const char *who,
+ uint64_t sec, uint64_t nsec, uint64_t seq,
+ const char *level, const char *msg) with gil:
+ cdef object cb_info = <object>arg
+ cb_info[0](cb_info[1], line, who, sec, nsec, seq, level, msg)
+ return 0
+
+cdef int __monitor_callback2(void *arg, const char *line, const char *channel,
+ const char *who,
+ const char *name,
+ uint64_t sec, uint64_t nsec, uint64_t seq,
+ const char *level, const char *msg) with gil:
+ cdef object cb_info = <object>arg
+ cb_info[0](cb_info[1], line, channel, name, who, sec, nsec, seq, level, msg)
+ return 0
+
+
+class Version(object):
+ """ Version information """
+ def __init__(self, major, minor, extra):
+ self.major = major
+ self.minor = minor
+ self.extra = extra
+
+ def __str__(self):
+ return "%d.%d.%d" % (self.major, self.minor, self.extra)
+
+
+cdef class Rados(object):
+ """This class wraps librados functions"""
+ # NOTE(sileht): attributes declared in .pyd
+
+ def __init__(self, *args, **kwargs):
+ PyEval_InitThreads()
+ self.__setup(*args, **kwargs)
+
+ NO_CONF_FILE = -1
+ "special value that indicates no conffile should be read when creating a mount handle"
+ DEFAULT_CONF_FILES = -2
+ "special value that indicates the default conffiles should be read when creating a mount handle"
+
+ @requires(('rados_id', opt(str_type)), ('name', opt(str_type)),
+ ('clustername', opt(str_type)), ('conffile', (str_type, int)))
+ def __setup(self, rados_id=None, name=None, clustername=None,
+ conf_defaults=None, conffile=NO_CONF_FILE, conf=None, flags=0,
+ context=None):
+ self.monitor_callback = None
+ self.monitor_callback2 = None
+ self.parsed_args = []
+ self.conf_defaults = conf_defaults
+ self.conffile = conffile
+ self.rados_id = rados_id
+
+ if rados_id and name:
+ raise Error("Rados(): can't supply both rados_id and name")
+ elif rados_id:
+ name = 'client.' + rados_id
+ elif name is None:
+ name = 'client.admin'
+ if clustername is None:
+ clustername = ''
+
+ name = cstr(name, 'name')
+ clustername = cstr(clustername, 'clustername')
+ cdef:
+ char *_name = name
+ char *_clustername = clustername
+ int _flags = flags
+ int ret
+
+ if context:
+ # Unpack void* (aka rados_config_t) from capsule
+ rados_config = <rados_config_t> PyCapsule_GetPointer(context, NULL)
+ with nogil:
+ ret = rados_create_with_context(&self.cluster, rados_config)
+ else:
+ with nogil:
+ ret = rados_create2(&self.cluster, _clustername, _name, _flags)
+ if ret != 0:
+ raise Error("rados_initialize failed with error code: %d" % ret)
+
+ self.state = "configuring"
+ # order is important: conf_defaults, then conffile, then conf
+ if conf_defaults:
+ for key, value in conf_defaults.items():
+ self.conf_set(key, value)
+ if conffile in (self.NO_CONF_FILE, None):
+ pass
+ elif conffile in (self.DEFAULT_CONF_FILES, ''):
+ self.conf_read_file(None)
+ else:
+ self.conf_read_file(conffile)
+ if conf:
+ for key, value in conf.items():
+ self.conf_set(key, value)
+
+ def get_addrs(self):
+ """
+ Get associated client addresses with this RADOS session.
+ """
+ self.require_state("configuring", "connected")
+
+ cdef:
+ char* addrs = NULL
+
+ try:
+
+ with nogil:
+ ret = rados_getaddrs(self.cluster, &addrs)
+ if ret:
+ raise make_ex(ret, "error calling getaddrs")
+
+ return decode_cstr(addrs)
+ finally:
+ free(addrs)
+
+ def require_state(self, *args):
+ """
+ Checks if the Rados object is in a special state
+
+ :raises: :class:`RadosStateError`
+ """
+ if self.state in args:
+ return
+ raise RadosStateError("You cannot perform that operation on a \
+Rados object in state %s." % self.state)
+
+ def shutdown(self):
+ """
+ Disconnects from the cluster. Call this explicitly when a
+ Rados.connect()ed object is no longer used.
+ """
+ if self.state != "shutdown":
+ with nogil:
+ rados_shutdown(self.cluster)
+ self.state = "shutdown"
+
+ def __enter__(self):
+ self.connect()
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ self.shutdown()
+ return False
+
+ def version(self):
+ """
+ Get the version number of the ``librados`` C library.
+
+ :returns: a tuple of ``(major, minor, extra)`` components of the
+ librados version
+ """
+ cdef int major = 0
+ cdef int minor = 0
+ cdef int extra = 0
+ with nogil:
+ rados_version(&major, &minor, &extra)
+ return Version(major, minor, extra)
+
+ @requires(('path', opt(str_type)))
+ def conf_read_file(self, path=None):
+ """
+ Configure the cluster handle using a Ceph config file.
+
+ :param path: path to the config file
+ :type path: str
+ """
+ self.require_state("configuring", "connected")
+ path = cstr(path, 'path', opt=True)
+ cdef:
+ char *_path = opt_str(path)
+ with nogil:
+ ret = rados_conf_read_file(self.cluster, _path)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_read_file")
+
+ def conf_parse_argv(self, args):
+ """
+ Parse known arguments from args, and remove; returned
+ args contain only those unknown to ceph
+ """
+ self.require_state("configuring", "connected")
+ if not args:
+ return
+
+ cargs = cstr_list(args, 'args')
+ cdef:
+ int _argc = len(args)
+ char **_argv = to_bytes_array(cargs)
+ char **_remargv = NULL
+
+ try:
+ _remargv = <char **>malloc(_argc * sizeof(char *))
+ with nogil:
+ ret = rados_conf_parse_argv_remainder(self.cluster, _argc,
+ <const char**>_argv,
+ <const char**>_remargv)
+ if ret:
+ raise make_ex(ret, "error calling conf_parse_argv_remainder")
+
+ # _remargv was allocated with fixed argc; collapse return
+ # list to eliminate any missing args
+ retargs = [decode_cstr(a) for a in _remargv[:_argc]
+ if a != NULL]
+ self.parsed_args = args
+ return retargs
+ finally:
+ free(_argv)
+ free(_remargv)
+
+ def conf_parse_env(self, var='CEPH_ARGS'):
+ """
+ Parse known arguments from an environment variable, normally
+ CEPH_ARGS.
+ """
+ self.require_state("configuring", "connected")
+ if not var:
+ return
+
+ var = cstr(var, 'var')
+ cdef:
+ char *_var = var
+ with nogil:
+ ret = rados_conf_parse_env(self.cluster, _var)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_parse_env")
+
+ @requires(('option', str_type))
+ def conf_get(self, option):
+ """
+ Get the value of a configuration option
+
+ :param option: which option to read
+ :type option: str
+
+ :returns: str - value of the option or None
+ :raises: :class:`TypeError`
+ """
+ self.require_state("configuring", "connected")
+ option = cstr(option, 'option')
+ cdef:
+ char *_option = option
+ size_t length = 20
+ char *ret_buf = NULL
+
+ try:
+ while True:
+ ret_buf = <char *>realloc_chk(ret_buf, length)
+ with nogil:
+ ret = rados_conf_get(self.cluster, _option, ret_buf, length)
+ if ret == 0:
+ return decode_cstr(ret_buf)
+ elif ret == -errno.ENAMETOOLONG:
+ length = length * 2
+ elif ret == -errno.ENOENT:
+ return None
+ else:
+ raise make_ex(ret, "error calling conf_get")
+ finally:
+ free(ret_buf)
+
+ @requires(('option', str_type), ('val', str_type))
+ def conf_set(self, option, val):
+ """
+ Set the value of a configuration option
+
+ :param option: which option to set
+ :type option: str
+ :param option: value of the option
+ :type option: str
+
+ :raises: :class:`TypeError`, :class:`ObjectNotFound`
+ """
+ self.require_state("configuring", "connected")
+ option = cstr(option, 'option')
+ val = cstr(val, 'val')
+ cdef:
+ char *_option = option
+ char *_val = val
+
+ with nogil:
+ ret = rados_conf_set(self.cluster, _option, _val)
+ if ret != 0:
+ raise make_ex(ret, "error calling conf_set")
+
+ def ping_monitor(self, mon_id):
+ """
+ Ping a monitor to assess liveness
+
+ May be used as a simply way to assess liveness, or to obtain
+ information about the monitor in a simple way even in the
+ absence of quorum.
+
+ :param mon_id: the ID portion of the monitor's name (i.e., mon.<ID>)
+ :type mon_id: str
+ :returns: the string reply from the monitor
+ """
+
+ self.require_state("configuring", "connected")
+
+ mon_id = cstr(mon_id, 'mon_id')
+ cdef:
+ char *_mon_id = mon_id
+ size_t outstrlen = 0
+ char *outstr
+
+ with nogil:
+ ret = rados_ping_monitor(self.cluster, _mon_id, &outstr, &outstrlen)
+
+ if ret != 0:
+ raise make_ex(ret, "error calling ping_monitor")
+
+ if outstrlen:
+ my_outstr = outstr[:outstrlen]
+ rados_buffer_free(outstr)
+ return decode_cstr(my_outstr)
+
+ def connect(self, timeout=0):
+ """
+ Connect to the cluster. Use shutdown() to release resources.
+ """
+ self.require_state("configuring")
+ # NOTE(sileht): timeout was supported by old python API,
+ # but this is not something available in C API, so ignore
+ # for now and remove it later
+ with nogil:
+ ret = rados_connect(self.cluster)
+ if ret != 0:
+ raise make_ex(ret, "error connecting to the cluster")
+ self.state = "connected"
+
+ def get_instance_id(self):
+ """
+ Get a global id for current instance
+ """
+ self.require_state("connected")
+ with nogil:
+ ret = rados_get_instance_id(self.cluster)
+ return ret;
+
+ def get_cluster_stats(self):
+ """
+ Read usage info about the cluster
+
+ This tells you total space, space used, space available, and number
+ of objects. These are not updated immediately when data is written,
+ they are eventually consistent.
+
+ :returns: dict - contains the following keys:
+
+ - ``kb`` (int) - total space
+
+ - ``kb_used`` (int) - space used
+
+ - ``kb_avail`` (int) - free space available
+
+ - ``num_objects`` (int) - number of objects
+
+ """
+ cdef:
+ rados_cluster_stat_t stats
+
+ with nogil:
+ ret = rados_cluster_stat(self.cluster, &stats)
+
+ if ret < 0:
+ raise make_ex(
+ ret, "Rados.get_cluster_stats(%s): get_stats failed" % self.rados_id)
+ return {'kb': stats.kb,
+ 'kb_used': stats.kb_used,
+ 'kb_avail': stats.kb_avail,
+ 'num_objects': stats.num_objects}
+
+ @requires(('pool_name', str_type))
+ def pool_exists(self, pool_name):
+ """
+ Checks if a given pool exists.
+
+ :param pool_name: name of the pool to check
+ :type pool_name: str
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: bool - whether the pool exists, false otherwise.
+ """
+ self.require_state("connected")
+
+ pool_name = cstr(pool_name, 'pool_name')
+ cdef:
+ char *_pool_name = pool_name
+
+ with nogil:
+ ret = rados_pool_lookup(self.cluster, _pool_name)
+ if ret >= 0:
+ return True
+ elif ret == -errno.ENOENT:
+ return False
+ else:
+ raise make_ex(ret, "error looking up pool '%s'" % pool_name)
+
+ @requires(('pool_name', str_type))
+ def pool_lookup(self, pool_name):
+ """
+ Returns a pool's ID based on its name.
+
+ :param pool_name: name of the pool to look up
+ :type pool_name: str
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: int - pool ID, or None if it doesn't exist
+ """
+ self.require_state("connected")
+ pool_name = cstr(pool_name, 'pool_name')
+ cdef:
+ char *_pool_name = pool_name
+
+ with nogil:
+ ret = rados_pool_lookup(self.cluster, _pool_name)
+ if ret >= 0:
+ return int(ret)
+ elif ret == -errno.ENOENT:
+ return None
+ else:
+ raise make_ex(ret, "error looking up pool '%s'" % pool_name)
+
+ @requires(('pool_id', int))
+ def pool_reverse_lookup(self, pool_id):
+ """
+ Returns a pool's name based on its ID.
+
+ :param pool_id: ID of the pool to look up
+ :type pool_id: int
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: string - pool name, or None if it doesn't exist
+ """
+ self.require_state("connected")
+ cdef:
+ int64_t _pool_id = pool_id
+ size_t size = 512
+ char *name = NULL
+
+ try:
+ while True:
+ name = <char *>realloc_chk(name, size)
+ with nogil:
+ ret = rados_pool_reverse_lookup(self.cluster, _pool_id, name, size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE and size <= 4096:
+ size *= 2
+ elif ret == -errno.ENOENT:
+ return None
+ elif ret < 0:
+ raise make_ex(ret, "error reverse looking up pool '%s'" % pool_id)
+
+ return decode_cstr(name)
+
+ finally:
+ free(name)
+
+ @requires(('pool_name', str_type), ('crush_rule', opt(int)))
+ def create_pool(self, pool_name, crush_rule=None):
+ """
+ Create a pool:
+ - with default settings: if crush_rule=None
+ - with a specific CRUSH rule: crush_rule given
+
+ :param pool_name: name of the pool to create
+ :type pool_name: str
+ :param crush_rule: rule to use for placement in the new pool
+ :type crush_rule: int
+
+ :raises: :class:`TypeError`, :class:`Error`
+ """
+ self.require_state("connected")
+
+ pool_name = cstr(pool_name, 'pool_name')
+ cdef:
+ char *_pool_name = pool_name
+ uint8_t _crush_rule
+
+ if crush_rule is None:
+ with nogil:
+ ret = rados_pool_create(self.cluster, _pool_name)
+ else:
+ _crush_rule = crush_rule
+ with nogil:
+ ret = rados_pool_create_with_crush_rule(self.cluster, _pool_name, _crush_rule)
+ if ret < 0:
+ raise make_ex(ret, "error creating pool '%s'" % pool_name)
+
+ @requires(('pool_id', int))
+ def get_pool_base_tier(self, pool_id):
+ """
+ Get base pool
+
+ :returns: base pool, or pool_id if tiering is not configured for the pool
+ """
+ self.require_state("connected")
+ cdef:
+ int64_t base_tier = 0
+ int64_t _pool_id = pool_id
+
+ with nogil:
+ ret = rados_pool_get_base_tier(self.cluster, _pool_id, &base_tier)
+ if ret < 0:
+ raise make_ex(ret, "get_pool_base_tier(%d)" % pool_id)
+ return int(base_tier)
+
+ @requires(('pool_name', str_type))
+ def delete_pool(self, pool_name):
+ """
+ Delete a pool and all data inside it.
+
+ The pool is removed from the cluster immediately,
+ but the actual data is deleted in the background.
+
+ :param pool_name: name of the pool to delete
+ :type pool_name: str
+
+ :raises: :class:`TypeError`, :class:`Error`
+ """
+ self.require_state("connected")
+
+ pool_name = cstr(pool_name, 'pool_name')
+ cdef:
+ char *_pool_name = pool_name
+
+ with nogil:
+ ret = rados_pool_delete(self.cluster, _pool_name)
+ if ret < 0:
+ raise make_ex(ret, "error deleting pool '%s'" % pool_name)
+
+ @requires(('pool_id', int))
+ def get_inconsistent_pgs(self, pool_id):
+ """
+ List inconsistent placement groups in the given pool
+
+ :param pool_id: ID of the pool in which PGs are listed
+ :type pool_id: int
+ :returns: list - inconsistent placement groups
+ """
+ self.require_state("connected")
+ cdef:
+ int64_t pool = pool_id
+ size_t size = 512
+ char *pgs = NULL
+
+ try:
+ while True:
+ pgs = <char *>realloc_chk(pgs, size);
+ with nogil:
+ ret = rados_inconsistent_pg_list(self.cluster, pool,
+ pgs, size)
+ if ret > <int>size:
+ size *= 2
+ elif ret >= 0:
+ break
+ else:
+ raise make_ex(ret, "error calling inconsistent_pg_list")
+ return [pg for pg in decode_cstr(pgs[:ret]).split('\0') if pg]
+ finally:
+ free(pgs)
+
+ def list_pools(self):
+ """
+ Gets a list of pool names.
+
+ :returns: list - of pool names.
+ """
+ self.require_state("connected")
+ cdef:
+ size_t size = 512
+ char *c_names = NULL
+
+ try:
+ while True:
+ c_names = <char *>realloc_chk(c_names, size)
+ with nogil:
+ ret = rados_pool_list(self.cluster, c_names, size)
+ if ret > <int>size:
+ size *= 2
+ elif ret >= 0:
+ break
+ return [name for name in decode_cstr(c_names[:ret]).split('\0')
+ if name]
+ finally:
+ free(c_names)
+
+ def get_fsid(self):
+ """
+ Get the fsid of the cluster as a hexadecimal string.
+
+ :raises: :class:`Error`
+ :returns: str - cluster fsid
+ """
+ self.require_state("connected")
+ cdef:
+ char *ret_buf = NULL
+ size_t buf_len = 64
+
+ try:
+ while True:
+ ret_buf = <char *>realloc_chk(ret_buf, buf_len)
+ with nogil:
+ ret = rados_cluster_fsid(self.cluster, ret_buf, buf_len)
+ if ret == -errno.ERANGE:
+ buf_len = buf_len * 2
+ elif ret < 0:
+ raise make_ex(ret, "error getting cluster fsid")
+ else:
+ break
+ return decode_cstr(ret_buf)
+ finally:
+ free(ret_buf)
+
+ @requires(('ioctx_name', str_type))
+ def open_ioctx(self, ioctx_name):
+ """
+ Create an io context
+
+ The io context allows you to perform operations within a particular
+ pool.
+
+ :param ioctx_name: name of the pool
+ :type ioctx_name: str
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: Ioctx - Rados Ioctx object
+ """
+ self.require_state("connected")
+ ioctx_name = cstr(ioctx_name, 'ioctx_name')
+ cdef:
+ rados_ioctx_t ioctx
+ char *_ioctx_name = ioctx_name
+ with nogil:
+ ret = rados_ioctx_create(self.cluster, _ioctx_name, &ioctx)
+ if ret < 0:
+ raise make_ex(ret, "error opening pool '%s'" % ioctx_name)
+ io = Ioctx(ioctx_name)
+ io.io = ioctx
+ return io
+
+ @requires(('pool_id', int))
+ def open_ioctx2(self, pool_id):
+ """
+ Create an io context
+
+ The io context allows you to perform operations within a particular
+ pool.
+
+ :param pool_id: ID of the pool
+ :type pool_id: int
+
+ :raises: :class:`TypeError`, :class:`Error`
+ :returns: Ioctx - Rados Ioctx object
+ """
+ self.require_state("connected")
+ cdef:
+ rados_ioctx_t ioctx
+ int64_t _pool_id = pool_id
+ with nogil:
+ ret = rados_ioctx_create2(self.cluster, _pool_id, &ioctx)
+ if ret < 0:
+ raise make_ex(ret, "error opening pool id '%s'" % pool_id)
+ io = Ioctx(str(pool_id))
+ io.io = ioctx
+ return io
+
+ def mon_command(self, cmd, inbuf, timeout=0, target=None):
+ """
+ mon_command[_target](cmd, inbuf, outbuf, outbuflen, outs, outslen)
+ returns (int ret, string outbuf, string outs)
+ """
+ # NOTE(sileht): timeout is ignored because C API doesn't provide
+ # timeout argument, but we keep it for backward compat with old python binding
+
+ self.require_state("connected")
+ cmd = cstr_list(cmd, 'c')
+
+ if isinstance(target, int):
+ # NOTE(sileht): looks weird but test_monmap_dump pass int
+ target = str(target)
+
+ target = cstr(target, 'target', opt=True)
+ inbuf = cstr(inbuf, 'inbuf')
+
+ cdef:
+ char *_target = opt_str(target)
+ char **_cmd = to_bytes_array(cmd)
+ size_t _cmdlen = len(cmd)
+
+ char *_inbuf = inbuf
+ size_t _inbuf_len = len(inbuf)
+
+ char *_outbuf
+ size_t _outbuf_len
+ char *_outs
+ size_t _outs_len
+
+ try:
+ if target:
+ with nogil:
+ ret = rados_mon_command_target(self.cluster, _target,
+ <const char **>_cmd, _cmdlen,
+ <const char*>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+ else:
+ with nogil:
+ ret = rados_mon_command(self.cluster,
+ <const char **>_cmd, _cmdlen,
+ <const char*>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+
+ my_outs = decode_cstr(_outs[:_outs_len])
+ my_outbuf = _outbuf[:_outbuf_len]
+ if _outs_len:
+ rados_buffer_free(_outs)
+ if _outbuf_len:
+ rados_buffer_free(_outbuf)
+ return (ret, my_outbuf, my_outs)
+ finally:
+ free(_cmd)
+
+ def osd_command(self, osdid, cmd, inbuf, timeout=0):
+ """
+ osd_command(osdid, cmd, inbuf, outbuf, outbuflen, outs, outslen)
+ returns (int ret, string outbuf, string outs)
+ """
+ # NOTE(sileht): timeout is ignored because C API doesn't provide
+ # timeout argument, but we keep it for backward compat with old python binding
+ self.require_state("connected")
+
+ cmd = cstr_list(cmd, 'cmd')
+ inbuf = cstr(inbuf, 'inbuf')
+
+ cdef:
+ int _osdid = osdid
+ char **_cmd = to_bytes_array(cmd)
+ size_t _cmdlen = len(cmd)
+
+ char *_inbuf = inbuf
+ size_t _inbuf_len = len(inbuf)
+
+ char *_outbuf
+ size_t _outbuf_len
+ char *_outs
+ size_t _outs_len
+
+ try:
+ with nogil:
+ ret = rados_osd_command(self.cluster, _osdid,
+ <const char **>_cmd, _cmdlen,
+ <const char*>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+
+ my_outs = decode_cstr(_outs[:_outs_len])
+ my_outbuf = _outbuf[:_outbuf_len]
+ if _outs_len:
+ rados_buffer_free(_outs)
+ if _outbuf_len:
+ rados_buffer_free(_outbuf)
+ return (ret, my_outbuf, my_outs)
+ finally:
+ free(_cmd)
+
+ def mgr_command(self, cmd, inbuf, timeout=0):
+ """
+ returns (int ret, string outbuf, string outs)
+ """
+ # NOTE(sileht): timeout is ignored because C API doesn't provide
+ # timeout argument, but we keep it for backward compat with old python binding
+ self.require_state("connected")
+
+ cmd = cstr_list(cmd, 'cmd')
+ inbuf = cstr(inbuf, 'inbuf')
+
+ cdef:
+ char **_cmd = to_bytes_array(cmd)
+ size_t _cmdlen = len(cmd)
+
+ char *_inbuf = inbuf
+ size_t _inbuf_len = len(inbuf)
+
+ char *_outbuf
+ size_t _outbuf_len
+ char *_outs
+ size_t _outs_len
+
+ try:
+ with nogil:
+ ret = rados_mgr_command(self.cluster,
+ <const char **>_cmd, _cmdlen,
+ <const char*>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+
+ my_outs = decode_cstr(_outs[:_outs_len])
+ my_outbuf = _outbuf[:_outbuf_len]
+ if _outs_len:
+ rados_buffer_free(_outs)
+ if _outbuf_len:
+ rados_buffer_free(_outbuf)
+ return (ret, my_outbuf, my_outs)
+ finally:
+ free(_cmd)
+
+ def pg_command(self, pgid, cmd, inbuf, timeout=0):
+ """
+ pg_command(pgid, cmd, inbuf, outbuf, outbuflen, outs, outslen)
+ returns (int ret, string outbuf, string outs)
+ """
+ # NOTE(sileht): timeout is ignored because C API doesn't provide
+ # timeout argument, but we keep it for backward compat with old python binding
+ self.require_state("connected")
+
+ pgid = cstr(pgid, 'pgid')
+ cmd = cstr_list(cmd, 'cmd')
+ inbuf = cstr(inbuf, 'inbuf')
+
+ cdef:
+ char *_pgid = pgid
+ char **_cmd = to_bytes_array(cmd)
+ size_t _cmdlen = len(cmd)
+
+ char *_inbuf = inbuf
+ size_t _inbuf_len = len(inbuf)
+
+ char *_outbuf
+ size_t _outbuf_len
+ char *_outs
+ size_t _outs_len
+
+ try:
+ with nogil:
+ ret = rados_pg_command(self.cluster, _pgid,
+ <const char **>_cmd, _cmdlen,
+ <const char *>_inbuf, _inbuf_len,
+ &_outbuf, &_outbuf_len,
+ &_outs, &_outs_len)
+
+ my_outs = decode_cstr(_outs[:_outs_len])
+ my_outbuf = _outbuf[:_outbuf_len]
+ if _outs_len:
+ rados_buffer_free(_outs)
+ if _outbuf_len:
+ rados_buffer_free(_outbuf)
+ return (ret, my_outbuf, my_outs)
+ finally:
+ free(_cmd)
+
+ def wait_for_latest_osdmap(self):
+ self.require_state("connected")
+ with nogil:
+ ret = rados_wait_for_latest_osdmap(self.cluster)
+ return ret
+
+ def blacklist_add(self, client_address, expire_seconds=0):
+ """
+ Blacklist a client from the OSDs
+
+ :param client_address: client address
+ :type client_address: str
+ :param expire_seconds: number of seconds to blacklist
+ :type expire_seconds: int
+
+ :raises: :class:`Error`
+ """
+ self.require_state("connected")
+ client_address = cstr(client_address, 'client_address')
+ cdef:
+ uint32_t _expire_seconds = expire_seconds
+ char *_client_address = client_address
+
+ with nogil:
+ ret = rados_blacklist_add(self.cluster, _client_address, _expire_seconds)
+ if ret < 0:
+ raise make_ex(ret, "error blacklisting client '%s'" % client_address)
+
+ def monitor_log(self, level, callback, arg):
+ if level not in MONITOR_LEVELS:
+ raise LogicError("invalid monitor level " + level)
+ if callback is not None and not callable(callback):
+ raise LogicError("callback must be a callable function or None")
+
+ level = cstr(level, 'level')
+ cdef char *_level = level
+
+ if callback is None:
+ with nogil:
+ r = rados_monitor_log(self.cluster, <const char*>_level, NULL, NULL)
+ self.monitor_callback = None
+ self.monitor_callback2 = None
+ return
+
+ cb = (callback, arg)
+ cdef PyObject* _arg = <PyObject*>cb
+ with nogil:
+ r = rados_monitor_log(self.cluster, <const char*>_level,
+ <rados_log_callback_t>&__monitor_callback, _arg)
+
+ if r:
+ raise make_ex(r, 'error calling rados_monitor_log')
+ # NOTE(sileht): Prevents the callback method from being garbage collected
+ self.monitor_callback = cb
+ self.monitor_callback2 = None
+
+ def monitor_log2(self, level, callback, arg):
+ if level not in MONITOR_LEVELS:
+ raise LogicError("invalid monitor level " + level)
+ if callback is not None and not callable(callback):
+ raise LogicError("callback must be a callable function or None")
+
+ level = cstr(level, 'level')
+ cdef char *_level = level
+
+ if callback is None:
+ with nogil:
+ r = rados_monitor_log2(self.cluster, <const char*>_level, NULL, NULL)
+ self.monitor_callback = None
+ self.monitor_callback2 = None
+ return
+
+ cb = (callback, arg)
+ cdef PyObject* _arg = <PyObject*>cb
+ with nogil:
+ r = rados_monitor_log2(self.cluster, <const char*>_level,
+ <rados_log_callback2_t>&__monitor_callback2, _arg)
+
+ if r:
+ raise make_ex(r, 'error calling rados_monitor_log')
+ # NOTE(sileht): Prevents the callback method from being garbage collected
+ self.monitor_callback = None
+ self.monitor_callback2 = cb
+
+ @requires(('service', str_type), ('daemon', str_type), ('metadata', dict))
+ def service_daemon_register(self, service, daemon, metadata):
+ """
+ :param str service: service name (e.g. "rgw")
+ :param str daemon: daemon name (e.g. "gwfoo")
+ :param dict metadata: static metadata about the register daemon
+ (e.g., the version of Ceph, the kernel version.)
+ """
+ service = cstr(service, 'service')
+ daemon = cstr(daemon, 'daemon')
+ metadata_dict = '\0'.join(chain.from_iterable(metadata.items()))
+ metadata_dict += '\0'
+ cdef:
+ char *_service = service
+ char *_daemon = daemon
+ char *_metadata = metadata_dict
+
+ with nogil:
+ ret = rados_service_register(self.cluster, _service, _daemon, _metadata)
+ if ret != 0:
+ raise make_ex(ret, "error calling service_register()")
+
+ @requires(('metadata', dict))
+ def service_daemon_update(self, status):
+ status_dict = '\0'.join(chain.from_iterable(status.items()))
+ status_dict += '\0'
+ cdef:
+ char *_status = status_dict
+
+ with nogil:
+ ret = rados_service_update_status(self.cluster, _status)
+ if ret != 0:
+ raise make_ex(ret, "error calling service_daemon_update()")
+
+
+cdef class OmapIterator(object):
+ """Omap iterator"""
+
+ cdef public Ioctx ioctx
+ cdef rados_omap_iter_t ctx
+
+ def __cinit__(self, Ioctx ioctx):
+ self.ioctx = ioctx
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Get the next key-value pair in the object
+ :returns: next rados.OmapItem
+ """
+ cdef:
+ char *key_ = NULL
+ char *val_ = NULL
+ size_t len_
+
+ with nogil:
+ ret = rados_omap_get_next(self.ctx, &key_, &val_, &len_)
+
+ if ret != 0:
+ raise make_ex(ret, "error iterating over the omap")
+ if key_ == NULL:
+ raise StopIteration()
+ key = decode_cstr(key_)
+ val = None
+ if val_ != NULL:
+ val = val_[:len_]
+ return (key, val)
+
+ def __dealloc__(self):
+ with nogil:
+ rados_omap_get_end(self.ctx)
+
+
+cdef class ObjectIterator(object):
+ """rados.Ioctx Object iterator"""
+
+ cdef rados_list_ctx_t ctx
+
+ cdef public object ioctx
+
+ def __cinit__(self, Ioctx ioctx):
+ self.ioctx = ioctx
+
+ with nogil:
+ ret = rados_nobjects_list_open(ioctx.io, &self.ctx)
+ if ret < 0:
+ raise make_ex(ret, "error iterating over the objects in ioctx '%s'"
+ % self.ioctx.name)
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Get the next object name and locator in the pool
+
+ :raises: StopIteration
+ :returns: next rados.Ioctx Object
+ """
+ cdef:
+ const char *key_ = NULL
+ const char *locator_ = NULL
+ const char *nspace_ = NULL
+
+ with nogil:
+ ret = rados_nobjects_list_next(self.ctx, &key_, &locator_, &nspace_)
+
+ if ret < 0:
+ raise StopIteration()
+
+ key = decode_cstr(key_)
+ locator = decode_cstr(locator_) if locator_ != NULL else None
+ nspace = decode_cstr(nspace_) if nspace_ != NULL else None
+ return Object(self.ioctx, key, locator, nspace)
+
+ def __dealloc__(self):
+ with nogil:
+ rados_nobjects_list_close(self.ctx)
+
+
+cdef class XattrIterator(object):
+ """Extended attribute iterator"""
+
+ cdef rados_xattrs_iter_t it
+ cdef char* _oid
+
+ cdef public Ioctx ioctx
+ cdef public object oid
+
+ def __cinit__(self, Ioctx ioctx, oid):
+ self.ioctx = ioctx
+ self.oid = cstr(oid, 'oid')
+ self._oid = self.oid
+
+ with nogil:
+ ret = rados_getxattrs(ioctx.io, self._oid, &self.it)
+ if ret != 0:
+ raise make_ex(ret, "Failed to get rados xattrs for object %r" % oid)
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Get the next xattr on the object
+
+ :raises: StopIteration
+ :returns: pair - of name and value of the next Xattr
+ """
+ cdef:
+ const char *name_ = NULL
+ const char *val_ = NULL
+ size_t len_ = 0
+
+ with nogil:
+ ret = rados_getxattrs_next(self.it, &name_, &val_, &len_)
+ if ret != 0:
+ raise make_ex(ret, "error iterating over the extended attributes \
+in '%s'" % self.oid)
+ if name_ == NULL:
+ raise StopIteration()
+ name = decode_cstr(name_)
+ val = val_[:len_]
+ return (name, val)
+
+ def __dealloc__(self):
+ with nogil:
+ rados_getxattrs_end(self.it)
+
+
+cdef class SnapIterator(object):
+ """Snapshot iterator"""
+
+ cdef public Ioctx ioctx
+
+ cdef rados_snap_t *snaps
+ cdef int max_snap
+ cdef int cur_snap
+
+ def __cinit__(self, Ioctx ioctx):
+ self.ioctx = ioctx
+ # We don't know how big a buffer we need until we've called the
+ # function. So use the exponential doubling strategy.
+ cdef int num_snaps = 10
+ while True:
+ self.snaps = <rados_snap_t*>realloc_chk(self.snaps,
+ num_snaps *
+ sizeof(rados_snap_t))
+
+ with nogil:
+ ret = rados_ioctx_snap_list(ioctx.io, self.snaps, num_snaps)
+ if ret >= 0:
+ self.max_snap = ret
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, "error calling rados_snap_list for \
+ioctx '%s'" % self.ioctx.name)
+ num_snaps = num_snaps * 2
+ self.cur_snap = 0
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """
+ Get the next Snapshot
+
+ :raises: :class:`Error`, StopIteration
+ :returns: Snap - next snapshot
+ """
+ if self.cur_snap >= self.max_snap:
+ raise StopIteration
+
+ cdef:
+ rados_snap_t snap_id = self.snaps[self.cur_snap]
+ int name_len = 10
+ char *name = NULL
+
+ try:
+ while True:
+ name = <char *>realloc_chk(name, name_len)
+ with nogil:
+ ret = rados_ioctx_snap_get_name(self.ioctx.io, snap_id, name, name_len)
+ if ret == 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, "rados_snap_get_name error")
+ else:
+ name_len = name_len * 2
+
+ snap = Snap(self.ioctx, decode_cstr(name[:name_len]).rstrip('\0'), snap_id)
+ self.cur_snap = self.cur_snap + 1
+ return snap
+ finally:
+ free(name)
+
+
+cdef class Snap(object):
+ """Snapshot object"""
+ cdef public Ioctx ioctx
+ cdef public object name
+
+ # NOTE(sileht): old API was storing the ctypes object
+ # instead of the value ....
+ cdef public rados_snap_t snap_id
+
+ def __cinit__(self, Ioctx ioctx, object name, rados_snap_t snap_id):
+ self.ioctx = ioctx
+ self.name = name
+ self.snap_id = snap_id
+
+ def __str__(self):
+ return "rados.Snap(ioctx=%s,name=%s,snap_id=%d)" \
+ % (str(self.ioctx), self.name, self.snap_id)
+
+ def get_timestamp(self):
+ """
+ Find when a snapshot in the current pool occurred
+
+ :raises: :class:`Error`
+ :returns: datetime - the data and time the snapshot was created
+ """
+ cdef time_t snap_time
+
+ with nogil:
+ ret = rados_ioctx_snap_get_stamp(self.ioctx.io, self.snap_id, &snap_time)
+ if ret != 0:
+ raise make_ex(ret, "rados_ioctx_snap_get_stamp error")
+ return datetime.fromtimestamp(snap_time)
+
+
+cdef class Completion(object):
+ """completion object"""
+
+ cdef public:
+ Ioctx ioctx
+ object oncomplete
+ object onsafe
+
+ cdef:
+ rados_callback_t complete_cb
+ rados_callback_t safe_cb
+ rados_completion_t rados_comp
+ PyObject* buf
+
+ def __cinit__(self, Ioctx ioctx, object oncomplete, object onsafe):
+ self.oncomplete = oncomplete
+ self.onsafe = onsafe
+ self.ioctx = ioctx
+
+ def is_safe(self):
+ """
+ Is an asynchronous operation safe?
+
+ This does not imply that the safe callback has finished.
+
+ :returns: True if the operation is safe
+ """
+ with nogil:
+ ret = rados_aio_is_safe(self.rados_comp)
+ return ret == 1
+
+ def is_complete(self):
+ """
+ Has an asynchronous operation completed?
+
+ This does not imply that the safe callback has finished.
+
+ :returns: True if the operation is completed
+ """
+ with nogil:
+ ret = rados_aio_is_complete(self.rados_comp)
+ return ret == 1
+
+ def wait_for_safe(self):
+ """
+ Wait for an asynchronous operation to be marked safe
+
+ This does not imply that the safe callback has finished.
+ """
+ with nogil:
+ rados_aio_wait_for_safe(self.rados_comp)
+
+ def wait_for_complete(self):
+ """
+ Wait for an asynchronous operation to complete
+
+ This does not imply that the complete callback has finished.
+ """
+ with nogil:
+ rados_aio_wait_for_complete(self.rados_comp)
+
+ def wait_for_safe_and_cb(self):
+ """
+ Wait for an asynchronous operation to be marked safe and for
+ the safe callback to have returned
+ """
+ with nogil:
+ rados_aio_wait_for_safe_and_cb(self.rados_comp)
+
+ def wait_for_complete_and_cb(self):
+ """
+ Wait for an asynchronous operation to complete and for the
+ complete callback to have returned
+
+ :returns: whether the operation is completed
+ """
+ with nogil:
+ ret = rados_aio_wait_for_complete_and_cb(self.rados_comp)
+ return ret
+
+ def get_return_value(self):
+ """
+ Get the return value of an asychronous operation
+
+ The return value is set when the operation is complete or safe,
+ whichever comes first.
+
+ :returns: int - return value of the operation
+ """
+ with nogil:
+ ret = rados_aio_get_return_value(self.rados_comp)
+ return ret
+
+ def __dealloc__(self):
+ """
+ Release a completion
+
+ Call this when you no longer need the completion. It may not be
+ freed immediately if the operation is not acked and committed.
+ """
+ ref.Py_XDECREF(self.buf)
+ self.buf = NULL
+ if self.rados_comp != NULL:
+ with nogil:
+ rados_aio_release(self.rados_comp)
+ self.rados_comp = NULL
+
+ def _complete(self):
+ self.oncomplete(self)
+ with self.ioctx.lock:
+ if self.oncomplete:
+ self.ioctx.complete_completions.remove(self)
+
+ def _safe(self):
+ self.onsafe(self)
+ with self.ioctx.lock:
+ if self.onsafe:
+ self.ioctx.safe_completions.remove(self)
+
+ def _cleanup(self):
+ with self.ioctx.lock:
+ if self.oncomplete:
+ self.ioctx.complete_completions.remove(self)
+ if self.onsafe:
+ self.ioctx.safe_completions.remove(self)
+
+
+class OpCtx(object):
+ def __enter__(self):
+ return self.create()
+
+ def __exit__(self, type, msg, traceback):
+ self.release()
+
+
+cdef class WriteOp(object):
+ cdef rados_write_op_t write_op
+
+ def create(self):
+ with nogil:
+ self.write_op = rados_create_write_op()
+ return self
+
+ def release(self):
+ with nogil:
+ rados_release_write_op(self.write_op)
+
+ @requires(('exclusive', opt(int)))
+ def new(self, exclusive=None):
+ """
+ Create the object.
+ """
+
+ cdef:
+ int _exclusive = exclusive
+
+ with nogil:
+ rados_write_op_create(self.write_op, _exclusive, NULL)
+
+
+ def remove(self):
+ """
+ Remove object.
+ """
+ with nogil:
+ rados_write_op_remove(self.write_op)
+
+ @requires(('flags', int))
+ def set_flags(self, flags=LIBRADOS_OPERATION_NOFLAG):
+ """
+ Set flags for the last operation added to this write_op.
+ :para flags: flags to apply to the last operation
+ :type flags: int
+ """
+
+ cdef:
+ int _flags = flags
+
+ with nogil:
+ rados_write_op_set_flags(self.write_op, _flags)
+
+ @requires(('to_write', bytes))
+ def append(self, to_write):
+ """
+ Append data to an object synchronously
+ :param to_write: data to write
+ :type to_write: bytes
+ """
+
+ cdef:
+ char *_to_write = to_write
+ size_t length = len(to_write)
+
+ with nogil:
+ rados_write_op_append(self.write_op, _to_write, length)
+
+ @requires(('to_write', bytes))
+ def write_full(self, to_write):
+ """
+ Write whole object, atomically replacing it.
+ :param to_write: data to write
+ :type to_write: bytes
+ """
+
+ cdef:
+ char *_to_write = to_write
+ size_t length = len(to_write)
+
+ with nogil:
+ rados_write_op_write_full(self.write_op, _to_write, length)
+
+ @requires(('to_write', bytes), ('offset', int))
+ def write(self, to_write, offset=0):
+ """
+ Write to offset.
+ :param to_write: data to write
+ :type to_write: bytes
+ :param offset: byte offset in the object to begin writing at
+ :type offset: int
+ """
+
+ cdef:
+ char *_to_write = to_write
+ size_t length = len(to_write)
+ uint64_t _offset = offset
+
+ with nogil:
+ rados_write_op_write(self.write_op, _to_write, length, _offset)
+
+ @requires(('version', int))
+ def assert_version(self, version):
+ """
+ Check if object's version is the expected one.
+ :param version: expected version of the object
+ :param type: int
+ """
+ cdef:
+ uint64_t _version = version
+
+ with nogil:
+ rados_write_op_assert_version(self.write_op, _version)
+
+ @requires(('offset', int), ('length', int))
+ def zero(self, offset, length):
+ """
+ Zero part of an object.
+ :param offset: byte offset in the object to begin writing at
+ :type offset: int
+ :param offset: number of zero to write
+ :type offset: int
+ """
+
+ cdef:
+ size_t _length = length
+ uint64_t _offset = offset
+
+ with nogil:
+ rados_write_op_zero(self.write_op, _length, _offset)
+
+ @requires(('offset', int))
+ def truncate(self, offset):
+ """
+ Truncate an object.
+ :param offset: byte offset in the object to begin truncating at
+ :type offset: int
+ """
+
+ cdef:
+ uint64_t _offset = offset
+
+ with nogil:
+ rados_write_op_truncate(self.write_op, _offset)
+
+
+class WriteOpCtx(WriteOp, OpCtx):
+ """write operation context manager"""
+
+
+cdef class ReadOp(object):
+ cdef rados_read_op_t read_op
+
+ def create(self):
+ with nogil:
+ self.read_op = rados_create_read_op()
+ return self
+
+ def release(self):
+ with nogil:
+ rados_release_read_op(self.read_op)
+
+ @requires(('flags', int))
+ def set_flags(self, flags=LIBRADOS_OPERATION_NOFLAG):
+ """
+ Set flags for the last operation added to this read_op.
+ :para flags: flags to apply to the last operation
+ :type flags: int
+ """
+
+ cdef:
+ int _flags = flags
+
+ with nogil:
+ rados_read_op_set_flags(self.read_op, _flags)
+
+
+class ReadOpCtx(ReadOp, OpCtx):
+ """read operation context manager"""
+
+
+cdef int __aio_safe_cb(rados_completion_t completion, void *args) with gil:
+ """
+ Callback to onsafe() for asynchronous operations
+ """
+ cdef object cb = <object>args
+ cb._safe()
+ return 0
+
+
+cdef int __aio_complete_cb(rados_completion_t completion, void *args) with gil:
+ """
+ Callback to oncomplete() for asynchronous operations
+ """
+ cdef object cb = <object>args
+ cb._complete()
+ return 0
+
+
+cdef class Ioctx(object):
+ """rados.Ioctx object"""
+ # NOTE(sileht): attributes declared in .pyd
+
+ def __init__(self, name):
+ self.name = name
+ self.state = "open"
+
+ self.locator_key = ""
+ self.nspace = ""
+ self.lock = threading.Lock()
+ self.safe_completions = []
+ self.complete_completions = []
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ self.close()
+ return False
+
+ def __dealloc__(self):
+ self.close()
+
+ def __track_completion(self, completion_obj):
+ if completion_obj.oncomplete:
+ with self.lock:
+ self.complete_completions.append(completion_obj)
+ if completion_obj.onsafe:
+ with self.lock:
+ self.safe_completions.append(completion_obj)
+
+ def __get_completion(self, oncomplete, onsafe):
+ """
+ Constructs a completion to use with asynchronous operations
+
+ :param oncomplete: what to do when the write is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the write is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ completion_obj = Completion(self, oncomplete, onsafe)
+
+ cdef:
+ rados_callback_t complete_cb = NULL
+ rados_callback_t safe_cb = NULL
+ rados_completion_t completion
+ PyObject* p_completion_obj= <PyObject*>completion_obj
+
+ if oncomplete:
+ complete_cb = <rados_callback_t>&__aio_complete_cb
+ if onsafe:
+ safe_cb = <rados_callback_t>&__aio_safe_cb
+
+ with nogil:
+ ret = rados_aio_create_completion(p_completion_obj, complete_cb, safe_cb,
+ &completion)
+ if ret < 0:
+ raise make_ex(ret, "error getting a completion")
+
+ completion_obj.rados_comp = completion
+ return completion_obj
+
+ @requires(('object_name', str_type), ('oncomplete', opt(Callable)))
+ def aio_stat(self, object_name, oncomplete):
+ """
+ Asynchronously get object stats (size/mtime)
+
+ oncomplete will be called with the returned size and mtime
+ as well as the completion:
+
+ oncomplete(completion, size, mtime)
+
+ :param object_name: the name of the object to get stats from
+ :type object_name: str
+ :param oncomplete: what to do when the stat is complete
+ :type oncomplete: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char *_object_name = object_name
+ uint64_t psize
+ time_t pmtime
+
+ def oncomplete_(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ if return_value >= 0:
+ return oncomplete(_completion_v, psize, time.localtime(pmtime))
+ else:
+ return oncomplete(_completion_v, None, None)
+
+ completion = self.__get_completion(oncomplete_, None)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_stat(self.io, _object_name, completion.rados_comp,
+ &psize, &pmtime)
+
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error stating %s" % object_name)
+ return completion
+
+ @requires(('object_name', str_type), ('to_write', bytes), ('offset', int),
+ ('oncomplete', opt(Callable)), ('onsafe', opt(Callable)))
+ def aio_write(self, object_name, to_write, offset=0,
+ oncomplete=None, onsafe=None):
+ """
+ Write data to an object asynchronously
+
+ Queues the write and returns.
+
+ :param object_name: name of the object
+ :type object_name: str
+ :param to_write: data to write
+ :type to_write: bytes
+ :param offset: byte offset in the object to begin writing at
+ :type offset: int
+ :param oncomplete: what to do when the write is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the write is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char* _object_name = object_name
+ char* _to_write = to_write
+ size_t size = len(to_write)
+ uint64_t _offset = offset
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_write(self.io, _object_name, completion.rados_comp,
+ _to_write, size, _offset)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error writing object %s" % object_name)
+ return completion
+
+ @requires(('object_name', str_type), ('to_write', bytes), ('oncomplete', opt(Callable)),
+ ('onsafe', opt(Callable)))
+ def aio_write_full(self, object_name, to_write,
+ oncomplete=None, onsafe=None):
+ """
+ Asynchronously write an entire object
+
+ The object is filled with the provided data. If the object exists,
+ it is atomically truncated and then written.
+ Queues the write and returns.
+
+ :param object_name: name of the object
+ :type object_name: str
+ :param to_write: data to write
+ :type to_write: str
+ :param oncomplete: what to do when the write is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the write is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char* _object_name = object_name
+ char* _to_write = to_write
+ size_t size = len(to_write)
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_write_full(self.io, _object_name,
+ completion.rados_comp,
+ _to_write, size)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error writing object %s" % object_name)
+ return completion
+
+ @requires(('object_name', str_type), ('to_append', bytes), ('oncomplete', opt(Callable)),
+ ('onsafe', opt(Callable)))
+ def aio_append(self, object_name, to_append, oncomplete=None, onsafe=None):
+ """
+ Asynchronously append data to an object
+
+ Queues the write and returns.
+
+ :param object_name: name of the object
+ :type object_name: str
+ :param to_append: data to append
+ :type to_append: str
+ :param offset: byte offset in the object to begin writing at
+ :type offset: int
+ :param oncomplete: what to do when the write is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the write is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char* _object_name = object_name
+ char* _to_append = to_append
+ size_t size = len(to_append)
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_append(self.io, _object_name,
+ completion.rados_comp,
+ _to_append, size)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error appending object %s" % object_name)
+ return completion
+
+ def aio_flush(self):
+ """
+ Block until all pending writes in an io context are safe
+
+ :raises: :class:`Error`
+ """
+ with nogil:
+ ret = rados_aio_flush(self.io)
+ if ret < 0:
+ raise make_ex(ret, "error flushing")
+
+ @requires(('object_name', str_type), ('length', int), ('offset', int),
+ ('oncomplete', opt(Callable)))
+ def aio_read(self, object_name, length, offset, oncomplete):
+ """
+ Asynchronously read data from an object
+
+ oncomplete will be called with the returned read value as
+ well as the completion:
+
+ oncomplete(completion, data_read)
+
+ :param object_name: name of the object to read from
+ :type object_name: str
+ :param length: the number of bytes to read
+ :type length: int
+ :param offset: byte offset in the object to begin reading from
+ :type offset: int
+ :param oncomplete: what to do when the read is complete
+ :type oncomplete: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char* _object_name = object_name
+ uint64_t _offset = offset
+
+ char *ref_buf
+ size_t _length = length
+
+ def oncomplete_(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ if return_value > 0 and return_value != length:
+ _PyBytes_Resize(&_completion_v.buf, return_value)
+ return oncomplete(_completion_v, <object>_completion_v.buf if return_value >= 0 else None)
+
+ completion = self.__get_completion(oncomplete_, None)
+ completion.buf = PyBytes_FromStringAndSize(NULL, length)
+ ret_buf = PyBytes_AsString(completion.buf)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_read(self.io, _object_name, completion.rados_comp,
+ ret_buf, _length, _offset)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error reading %s" % object_name)
+ return completion
+
+ @requires(('object_name', str_type), ('cls', str_type), ('method', str_type),
+ ('data', bytes), ('length', int),
+ ('oncomplete', opt(Callable)), ('onsafe', opt(Callable)))
+ def aio_execute(self, object_name, cls, method, data,
+ length=8192, oncomplete=None, onsafe=None):
+ """
+ Asynchronously execute an OSD class method on an object.
+
+ oncomplete and onsafe will be called with the data returned from
+ the plugin as well as the completion:
+
+ oncomplete(completion, data)
+ onsafe(completion, data)
+
+ :param object_name: name of the object
+ :type object_name: str
+ :param cls: name of the object class
+ :type cls: str
+ :param method: name of the method
+ :type method: str
+ :param data: input data
+ :type data: bytes
+ :param length: size of output buffer in bytes (default=8192)
+ :type length: int
+ :param oncomplete: what to do when the execution is complete
+ :type oncomplete: completion
+ :param onsafe: what to do when the execution is safe and complete
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ object_name = cstr(object_name, 'object_name')
+ cls = cstr(cls, 'cls')
+ method = cstr(method, 'method')
+ cdef:
+ Completion completion
+ char *_object_name = object_name
+ char *_cls = cls
+ char *_method = method
+ char *_data = data
+ size_t _data_len = len(data)
+
+ char *ref_buf
+ size_t _length = length
+
+ def oncomplete_(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ if return_value > 0 and return_value != length:
+ _PyBytes_Resize(&_completion_v.buf, return_value)
+ return oncomplete(_completion_v, <object>_completion_v.buf if return_value >= 0 else None)
+
+ def onsafe_(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ return onsafe(_completion_v, <object>_completion_v.buf if return_value >= 0 else None)
+
+ completion = self.__get_completion(oncomplete_ if oncomplete else None, onsafe_ if onsafe else None)
+ completion.buf = PyBytes_FromStringAndSize(NULL, length)
+ ret_buf = PyBytes_AsString(completion.buf)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_exec(self.io, _object_name, completion.rados_comp,
+ _cls, _method, _data, _data_len, ret_buf, _length)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error executing %s::%s on %s" % (cls, method, object_name))
+ return completion
+
+ @requires(('object_name', str_type), ('oncomplete', opt(Callable)), ('onsafe', opt(Callable)))
+ def aio_remove(self, object_name, oncomplete=None, onsafe=None):
+ """
+ Asynchronously remove an object
+
+ :param object_name: name of the object to remove
+ :type object_name: str
+ :param oncomplete: what to do when the remove is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the remove is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+ object_name = cstr(object_name, 'object_name')
+
+ cdef:
+ Completion completion
+ char* _object_name = object_name
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+ with nogil:
+ ret = rados_aio_remove(self.io, _object_name,
+ completion.rados_comp)
+ if ret < 0:
+ completion._cleanup()
+ raise make_ex(ret, "error removing %s" % object_name)
+ return completion
+
+ def require_ioctx_open(self):
+ """
+ Checks if the rados.Ioctx object state is 'open'
+
+ :raises: IoctxStateError
+ """
+ if self.state != "open":
+ raise IoctxStateError("The pool is %s" % self.state)
+
+ @requires(('loc_key', str_type))
+ def set_locator_key(self, loc_key):
+ """
+ Set the key for mapping objects to pgs within an io context.
+
+ The key is used instead of the object name to determine which
+ placement groups an object is put in. This affects all subsequent
+ operations of the io context - until a different locator key is
+ set, all objects in this io context will be placed in the same pg.
+
+ :param loc_key: the key to use as the object locator, or NULL to discard
+ any previously set key
+ :type loc_key: str
+
+ :raises: :class:`TypeError`
+ """
+ self.require_ioctx_open()
+ cloc_key = cstr(loc_key, 'loc_key')
+ cdef char *_loc_key = cloc_key
+ with nogil:
+ rados_ioctx_locator_set_key(self.io, _loc_key)
+ self.locator_key = loc_key
+
+ def get_locator_key(self):
+ """
+ Get the locator_key of context
+
+ :returns: locator_key
+ """
+ return self.locator_key
+
+ @requires(('snap_id', long))
+ def set_read(self, snap_id):
+ """
+ Set the snapshot for reading objects.
+
+ To stop to read from snapshot, use set_read(LIBRADOS_SNAP_HEAD)
+
+ :param snap_id: the snapshot Id
+ :type snap_id: int
+
+ :raises: :class:`TypeError`
+ """
+ self.require_ioctx_open()
+ cdef rados_snap_t _snap_id = snap_id
+ with nogil:
+ rados_ioctx_snap_set_read(self.io, _snap_id)
+
+ @requires(('nspace', str_type))
+ def set_namespace(self, nspace):
+ """
+ Set the namespace for objects within an io context.
+
+ The namespace in addition to the object name fully identifies
+ an object. This affects all subsequent operations of the io context
+ - until a different namespace is set, all objects in this io context
+ will be placed in the same namespace.
+
+ :param nspace: the namespace to use, or None/"" for the default namespace
+ :type nspace: str
+
+ :raises: :class:`TypeError`
+ """
+ self.require_ioctx_open()
+ if nspace is None:
+ nspace = ""
+ cnspace = cstr(nspace, 'nspace')
+ cdef char *_nspace = cnspace
+ with nogil:
+ rados_ioctx_set_namespace(self.io, _nspace)
+ self.nspace = nspace
+
+ def get_namespace(self):
+ """
+ Get the namespace of context
+
+ :returns: namespace
+ """
+ return self.nspace
+
+ def close(self):
+ """
+ Close a rados.Ioctx object.
+
+ This just tells librados that you no longer need to use the io context.
+ It may not be freed immediately if there are pending asynchronous
+ requests on it, but you should not use an io context again after
+ calling this function on it.
+ """
+ if self.state == "open":
+ self.require_ioctx_open()
+ with nogil:
+ rados_ioctx_destroy(self.io)
+ self.state = "closed"
+
+
+ @requires(('key', str_type), ('data', bytes))
+ def write(self, key, data, offset=0):
+ """
+ Write data to an object synchronously
+
+ :param key: name of the object
+ :type key: str
+ :param data: data to write
+ :type data: bytes
+ :param offset: byte offset in the object to begin writing at
+ :type offset: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`LogicError`
+ :returns: int - 0 on success
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ char *_data = data
+ size_t length = len(data)
+ uint64_t _offset = offset
+
+ with nogil:
+ ret = rados_write(self.io, _key, _data, length, _offset)
+ if ret == 0:
+ return ret
+ elif ret < 0:
+ raise make_ex(ret, "Ioctx.write(%s): failed to write %s"
+ % (self.name, key))
+ else:
+ raise LogicError("Ioctx.write(%s): rados_write \
+returned %d, but should return zero on success." % (self.name, ret))
+
+ @requires(('key', str_type), ('data', bytes))
+ def write_full(self, key, data):
+ """
+ Write an entire object synchronously.
+
+ The object is filled with the provided data. If the object exists,
+ it is atomically truncated and then written.
+
+ :param key: name of the object
+ :type key: str
+ :param data: data to write
+ :type data: bytes
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: int - 0 on success
+ """
+ self.require_ioctx_open()
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ char *_data = data
+ size_t length = len(data)
+
+ with nogil:
+ ret = rados_write_full(self.io, _key, _data, length)
+ if ret == 0:
+ return ret
+ elif ret < 0:
+ raise make_ex(ret, "Ioctx.write_full(%s): failed to write %s"
+ % (self.name, key))
+ else:
+ raise LogicError("Ioctx.write_full(%s): rados_write_full \
+returned %d, but should return zero on success." % (self.name, ret))
+
+ @requires(('key', str_type), ('data', bytes))
+ def append(self, key, data):
+ """
+ Append data to an object synchronously
+
+ :param key: name of the object
+ :type key: str
+ :param data: data to write
+ :type data: bytes
+
+ :raises: :class:`TypeError`
+ :raises: :class:`LogicError`
+ :returns: int - 0 on success
+ """
+ self.require_ioctx_open()
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ char *_data = data
+ size_t length = len(data)
+
+ with nogil:
+ ret = rados_append(self.io, _key, _data, length)
+ if ret == 0:
+ return ret
+ elif ret < 0:
+ raise make_ex(ret, "Ioctx.append(%s): failed to append %s"
+ % (self.name, key))
+ else:
+ raise LogicError("Ioctx.append(%s): rados_append \
+returned %d, but should return zero on success." % (self.name, ret))
+
+ @requires(('key', str_type))
+ def read(self, key, length=8192, offset=0):
+ """
+ Read data from an object synchronously
+
+ :param key: name of the object
+ :type key: str
+ :param length: the number of bytes to read (default=8192)
+ :type length: int
+ :param offset: byte offset in the object to begin reading at
+ :type offset: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: str - data read from object
+ """
+ self.require_ioctx_open()
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ char *ret_buf
+ uint64_t _offset = offset
+ size_t _length = length
+ PyObject* ret_s = NULL
+
+ ret_s = PyBytes_FromStringAndSize(NULL, length)
+ try:
+ ret_buf = PyBytes_AsString(ret_s)
+ with nogil:
+ ret = rados_read(self.io, _key, ret_buf, _length, _offset)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.read(%s): failed to read %s" % (self.name, key))
+
+ if ret != length:
+ _PyBytes_Resize(&ret_s, ret)
+
+ return <object>ret_s
+ finally:
+ # We DECREF unconditionally: the cast to object above will have
+ # INCREFed if necessary. This also takes care of exceptions,
+ # including if _PyString_Resize fails (that will free the string
+ # itself and set ret_s to NULL, hence XDECREF).
+ ref.Py_XDECREF(ret_s)
+
+ @requires(('key', str_type), ('cls', str_type), ('method', str_type), ('data', bytes))
+ def execute(self, key, cls, method, data, length=8192):
+ """
+ Execute an OSD class method on an object.
+
+ :param key: name of the object
+ :type key: str
+ :param cls: name of the object class
+ :type cls: str
+ :param method: name of the method
+ :type method: str
+ :param data: input data
+ :type data: bytes
+ :param length: size of output buffer in bytes (default=8192)
+ :type length: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: (ret, method output)
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ cls = cstr(cls, 'cls')
+ method = cstr(method, 'method')
+ cdef:
+ char *_key = key
+ char *_cls = cls
+ char *_method = method
+ char *_data = data
+ size_t _data_len = len(data)
+
+ char *ref_buf
+ size_t _length = length
+ PyObject* ret_s = NULL
+
+ ret_s = PyBytes_FromStringAndSize(NULL, length)
+ try:
+ ret_buf = PyBytes_AsString(ret_s)
+ with nogil:
+ ret = rados_exec(self.io, _key, _cls, _method, _data,
+ _data_len, ret_buf, _length)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.read(%s): failed to read %s" % (self.name, key))
+
+ if ret != length:
+ _PyBytes_Resize(&ret_s, ret)
+
+ return ret, <object>ret_s
+ finally:
+ # We DECREF unconditionally: the cast to object above will have
+ # INCREFed if necessary. This also takes care of exceptions,
+ # including if _PyString_Resize fails (that will free the string
+ # itself and set ret_s to NULL, hence XDECREF).
+ ref.Py_XDECREF(ret_s)
+
+ def get_stats(self):
+ """
+ Get pool usage statistics
+
+ :returns: dict - contains the following keys:
+
+ - ``num_bytes`` (int) - size of pool in bytes
+
+ - ``num_kb`` (int) - size of pool in kbytes
+
+ - ``num_objects`` (int) - number of objects in the pool
+
+ - ``num_object_clones`` (int) - number of object clones
+
+ - ``num_object_copies`` (int) - number of object copies
+
+ - ``num_objects_missing_on_primary`` (int) - number of objets
+ missing on primary
+
+ - ``num_objects_unfound`` (int) - number of unfound objects
+
+ - ``num_objects_degraded`` (int) - number of degraded objects
+
+ - ``num_rd`` (int) - bytes read
+
+ - ``num_rd_kb`` (int) - kbytes read
+
+ - ``num_wr`` (int) - bytes written
+
+ - ``num_wr_kb`` (int) - kbytes written
+ """
+ self.require_ioctx_open()
+ cdef rados_pool_stat_t stats
+ with nogil:
+ ret = rados_ioctx_pool_stat(self.io, &stats)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.get_stats(%s): get_stats failed" % self.name)
+ return {'num_bytes': stats.num_bytes,
+ 'num_kb': stats.num_kb,
+ 'num_objects': stats.num_objects,
+ 'num_object_clones': stats.num_object_clones,
+ 'num_object_copies': stats.num_object_copies,
+ "num_objects_missing_on_primary": stats.num_objects_missing_on_primary,
+ "num_objects_unfound": stats.num_objects_unfound,
+ "num_objects_degraded": stats.num_objects_degraded,
+ "num_rd": stats.num_rd,
+ "num_rd_kb": stats.num_rd_kb,
+ "num_wr": stats.num_wr,
+ "num_wr_kb": stats.num_wr_kb}
+
+ @requires(('key', str_type))
+ def remove_object(self, key):
+ """
+ Delete an object
+
+ This does not delete any snapshots of the object.
+
+ :param key: the name of the object to delete
+ :type key: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: bool - True on success
+ """
+ self.require_ioctx_open()
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+
+ with nogil:
+ ret = rados_remove(self.io, _key)
+ if ret < 0:
+ raise make_ex(ret, "Failed to remove '%s'" % key)
+ return True
+
+ @requires(('key', str_type))
+ def trunc(self, key, size):
+ """
+ Resize an object
+
+ If this enlarges the object, the new area is logically filled with
+ zeroes. If this shrinks the object, the excess data is removed.
+
+ :param key: the name of the object to resize
+ :type key: str
+ :param size: the new size of the object in bytes
+ :type size: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: int - 0 on success, otherwise raises error
+ """
+
+ self.require_ioctx_open()
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ uint64_t _size = size
+
+ with nogil:
+ ret = rados_trunc(self.io, _key, _size)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.trunc(%s): failed to truncate %s" % (self.name, key))
+ return ret
+
+ @requires(('key', str_type))
+ def stat(self, key):
+ """
+ Get object stats (size/mtime)
+
+ :param key: the name of the object to get stats from
+ :type key: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: (size,timestamp)
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ uint64_t psize
+ time_t pmtime
+
+ with nogil:
+ ret = rados_stat(self.io, _key, &psize, &pmtime)
+ if ret < 0:
+ raise make_ex(ret, "Failed to stat %r" % key)
+ return psize, time.localtime(pmtime)
+
+ @requires(('key', str_type), ('xattr_name', str_type))
+ def get_xattr(self, key, xattr_name):
+ """
+ Get the value of an extended attribute on an object.
+
+ :param key: the name of the object to get xattr from
+ :type key: str
+ :param xattr_name: which extended attribute to read
+ :type xattr_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: str - value of the xattr
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ xattr_name = cstr(xattr_name, 'xattr_name')
+ cdef:
+ char *_key = key
+ char *_xattr_name = xattr_name
+ size_t ret_length = 4096
+ char *ret_buf = NULL
+
+ try:
+ while ret_length < 4096 * 1024 * 1024:
+ ret_buf = <char *>realloc_chk(ret_buf, ret_length)
+ with nogil:
+ ret = rados_getxattr(self.io, _key, _xattr_name, ret_buf, ret_length)
+ if ret == -errno.ERANGE:
+ ret_length *= 2
+ elif ret < 0:
+ raise make_ex(ret, "Failed to get xattr %r" % xattr_name)
+ else:
+ break
+ return ret_buf[:ret]
+ finally:
+ free(ret_buf)
+
+ @requires(('oid', str_type))
+ def get_xattrs(self, oid):
+ """
+ Start iterating over xattrs on an object.
+
+ :param oid: the name of the object to get xattrs from
+ :type oid: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: XattrIterator
+ """
+ self.require_ioctx_open()
+ return XattrIterator(self, oid)
+
+ @requires(('key', str_type), ('xattr_name', str_type), ('xattr_value', bytes))
+ def set_xattr(self, key, xattr_name, xattr_value):
+ """
+ Set an extended attribute on an object.
+
+ :param key: the name of the object to set xattr to
+ :type key: str
+ :param xattr_name: which extended attribute to set
+ :type xattr_name: str
+ :param xattr_value: the value of the extended attribute
+ :type xattr_value: bytes
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: bool - True on success, otherwise raise an error
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ xattr_name = cstr(xattr_name, 'xattr_name')
+ cdef:
+ char *_key = key
+ char *_xattr_name = xattr_name
+ char *_xattr_value = xattr_value
+ size_t _xattr_value_len = len(xattr_value)
+
+ with nogil:
+ ret = rados_setxattr(self.io, _key, _xattr_name,
+ _xattr_value, _xattr_value_len)
+ if ret < 0:
+ raise make_ex(ret, "Failed to set xattr %r" % xattr_name)
+ return True
+
+ @requires(('key', str_type), ('xattr_name', str_type))
+ def rm_xattr(self, key, xattr_name):
+ """
+ Removes an extended attribute on from an object.
+
+ :param key: the name of the object to remove xattr from
+ :type key: str
+ :param xattr_name: which extended attribute to remove
+ :type xattr_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: bool - True on success, otherwise raise an error
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ xattr_name = cstr(xattr_name, 'xattr_name')
+ cdef:
+ char *_key = key
+ char *_xattr_name = xattr_name
+
+ with nogil:
+ ret = rados_rmxattr(self.io, _key, _xattr_name)
+ if ret < 0:
+ raise make_ex(ret, "Failed to delete key %r xattr %r" %
+ (key, xattr_name))
+ return True
+
+ @requires(('obj', str_type), ('msg', str_type), ('timeout_ms', int))
+ def notify(self, obj, msg='', timeout_ms=5000):
+ """
+ Send a rados notification to an object.
+
+ :param obj: the name of the object to notify
+ :type obj: str
+ :param msg: optional message to send in the notification
+ :type msg: str
+ :param timeout_ms: notify timeout (in ms)
+ :type timeout_ms: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: bool - True on success, otherwise raise an error
+ """
+ self.require_ioctx_open()
+
+ msglen = len(msg)
+ obj = cstr(obj, 'obj')
+ msg = cstr(msg, 'msg')
+ cdef:
+ char *_obj = obj
+ char *_msg = msg
+ int _msglen = msglen
+ uint64_t _timeout_ms = timeout_ms
+
+ with nogil:
+ ret = rados_notify2(self.io, _obj, _msg, _msglen, _timeout_ms,
+ NULL, NULL)
+ if ret < 0:
+ raise make_ex(ret, "Failed to notify %r" % (obj))
+ return True
+
+ def list_objects(self):
+ """
+ Get ObjectIterator on rados.Ioctx object.
+
+ :returns: ObjectIterator
+ """
+ self.require_ioctx_open()
+ return ObjectIterator(self)
+
+ def list_snaps(self):
+ """
+ Get SnapIterator on rados.Ioctx object.
+
+ :returns: SnapIterator
+ """
+ self.require_ioctx_open()
+ return SnapIterator(self)
+
+ @requires(('snap_name', str_type))
+ def create_snap(self, snap_name):
+ """
+ Create a pool-wide snapshot
+
+ :param snap_name: the name of the snapshot
+ :type snap_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ snap_name = cstr(snap_name, 'snap_name')
+ cdef char *_snap_name = snap_name
+
+ with nogil:
+ ret = rados_ioctx_snap_create(self.io, _snap_name)
+ if ret != 0:
+ raise make_ex(ret, "Failed to create snap %s" % snap_name)
+
+ @requires(('snap_name', str_type))
+ def remove_snap(self, snap_name):
+ """
+ Removes a pool-wide snapshot
+
+ :param snap_name: the name of the snapshot
+ :type snap_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ snap_name = cstr(snap_name, 'snap_name')
+ cdef char *_snap_name = snap_name
+
+ with nogil:
+ ret = rados_ioctx_snap_remove(self.io, _snap_name)
+ if ret != 0:
+ raise make_ex(ret, "Failed to remove snap %s" % snap_name)
+
+ @requires(('snap_name', str_type))
+ def lookup_snap(self, snap_name):
+ """
+ Get the id of a pool snapshot
+
+ :param snap_name: the name of the snapshot to lookop
+ :type snap_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ :returns: Snap - on success
+ """
+ self.require_ioctx_open()
+ csnap_name = cstr(snap_name, 'snap_name')
+ cdef:
+ char *_snap_name = csnap_name
+ rados_snap_t snap_id
+
+ with nogil:
+ ret = rados_ioctx_snap_lookup(self.io, _snap_name, &snap_id)
+ if ret != 0:
+ raise make_ex(ret, "Failed to lookup snap %s" % snap_name)
+ return Snap(self, snap_name, int(snap_id))
+
+ @requires(('oid', str_type), ('snap_name', str_type))
+ def snap_rollback(self, oid, snap_name):
+ """
+ Rollback an object to a snapshot
+
+ :param oid: the name of the object
+ :type oid: str
+ :param snap_name: the name of the snapshot
+ :type snap_name: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ oid = cstr(oid, 'oid')
+ snap_name = cstr(snap_name, 'snap_name')
+ cdef:
+ char *_snap_name = snap_name
+ char *_oid = oid
+
+ with nogil:
+ ret = rados_ioctx_snap_rollback(self.io, _oid, _snap_name)
+ if ret != 0:
+ raise make_ex(ret, "Failed to rollback %s" % oid)
+
+ def create_self_managed_snap(self):
+ """
+ Creates a self-managed snapshot
+
+ :returns: snap id on success
+
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ cdef:
+ rados_snap_t _snap_id
+ with nogil:
+ ret = rados_ioctx_selfmanaged_snap_create(self.io, &_snap_id)
+ if ret != 0:
+ raise make_ex(ret, "Failed to create self-managed snapshot")
+ return int(_snap_id)
+
+ @requires(('snap_id', int))
+ def remove_self_managed_snap(self, snap_id):
+ """
+ Removes a self-managed snapshot
+
+ :param snap_id: the name of the snapshot
+ :type snap_id: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ cdef:
+ rados_snap_t _snap_id = snap_id
+ with nogil:
+ ret = rados_ioctx_selfmanaged_snap_remove(self.io, _snap_id)
+ if ret != 0:
+ raise make_ex(ret, "Failed to remove self-managed snapshot")
+
+ def set_self_managed_snap_write(self, snaps):
+ """
+ Updates the write context to the specified self-managed
+ snapshot ids.
+
+ :param snaps: all associated self-managed snapshot ids
+ :type snaps: list
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ sorted_snaps = []
+ snap_seq = 0
+ if snaps:
+ sorted_snaps = sorted([int(x) for x in snaps], reverse=True)
+ snap_seq = sorted_snaps[0]
+
+ cdef:
+ rados_snap_t _snap_seq = snap_seq
+ rados_snap_t *_snaps = NULL
+ int _num_snaps = len(sorted_snaps)
+ try:
+ _snaps = <rados_snap_t *>malloc(_num_snaps * sizeof(rados_snap_t))
+ for i in range(len(sorted_snaps)):
+ _snaps[i] = sorted_snaps[i]
+ with nogil:
+ ret = rados_ioctx_selfmanaged_snap_set_write_ctx(self.io,
+ _snap_seq,
+ _snaps,
+ _num_snaps)
+ if ret != 0:
+ raise make_ex(ret, "Failed to update snapshot write context")
+ finally:
+ free(_snaps)
+
+ @requires(('oid', str_type), ('snap_id', int))
+ def rollback_self_managed_snap(self, oid, snap_id):
+ """
+ Rolls an specific object back to a self-managed snapshot revision
+
+ :param oid: the name of the object
+ :type oid: str
+ :param snap_id: the name of the snapshot
+ :type snap_id: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+ oid = cstr(oid, 'oid')
+ cdef:
+ char *_oid = oid
+ rados_snap_t _snap_id = snap_id
+ with nogil:
+ ret = rados_ioctx_selfmanaged_snap_rollback(self.io, _oid, _snap_id)
+ if ret != 0:
+ raise make_ex(ret, "Failed to rollback %s" % oid)
+
+ def get_last_version(self):
+ """
+ Return the version of the last object read or written to.
+
+ This exposes the internal version number of the last object read or
+ written via this io context
+
+ :returns: version of the last object used
+ """
+ self.require_ioctx_open()
+ with nogil:
+ ret = rados_get_last_version(self.io)
+ return int(ret)
+
+ def create_write_op(self):
+ """
+ create write operation object.
+ need call release_write_op after use
+ """
+ return WriteOp().create()
+
+ def create_read_op(self):
+ """
+ create read operation object.
+ need call release_read_op after use
+ """
+ return ReadOp().create()
+
+ def release_write_op(self, write_op):
+ """
+ release memory alloc by create_write_op
+ """
+ write_op.release()
+
+ def release_read_op(self, read_op):
+ """
+ release memory alloc by create_read_op
+ :para read_op: read_op object
+ :type: int
+ """
+ read_op.release()
+
+ @requires(('write_op', WriteOp), ('keys', tuple), ('values', tuple))
+ def set_omap(self, write_op, keys, values):
+ """
+ set keys values to write_op
+ :para write_op: write_operation object
+ :type write_op: WriteOp
+ :para keys: a tuple of keys
+ :type keys: tuple
+ :para values: a tuple of values
+ :type values: tuple
+ """
+
+ if len(keys) != len(values):
+ raise Error("Rados(): keys and values must have the same number of items")
+
+ keys = cstr_list(keys, 'keys')
+ values = cstr_list(values, 'values')
+ lens = [len(v) for v in values]
+ cdef:
+ WriteOp _write_op = write_op
+ size_t key_num = len(keys)
+ char **_keys = to_bytes_array(keys)
+ char **_values = to_bytes_array(values)
+ size_t *_lens = to_csize_t_array(lens)
+
+ try:
+ with nogil:
+ rados_write_op_omap_set(_write_op.write_op,
+ <const char**>_keys,
+ <const char**>_values,
+ <const size_t*>_lens, key_num)
+ finally:
+ free(_keys)
+ free(_values)
+ free(_lens)
+
+ @requires(('write_op', WriteOp), ('oid', str_type), ('mtime', opt(int)), ('flags', opt(int)))
+ def operate_write_op(self, write_op, oid, mtime=0, flags=LIBRADOS_OPERATION_NOFLAG):
+ """
+ execute the real write operation
+ :para write_op: write operation object
+ :type write_op: WriteOp
+ :para oid: object name
+ :type oid: str
+ :para mtime: the time to set the mtime to, 0 for the current time
+ :type mtime: int
+ :para flags: flags to apply to the entire operation
+ :type flags: int
+ """
+
+ oid = cstr(oid, 'oid')
+ cdef:
+ WriteOp _write_op = write_op
+ char *_oid = oid
+ time_t _mtime = mtime
+ int _flags = flags
+
+ with nogil:
+ ret = rados_write_op_operate(_write_op.write_op, self.io, _oid, &_mtime, _flags)
+ if ret != 0:
+ raise make_ex(ret, "Failed to operate write op for oid %s" % oid)
+
+ @requires(('write_op', WriteOp), ('oid', str_type), ('oncomplete', opt(Callable)), ('onsafe', opt(Callable)), ('mtime', opt(int)), ('flags', opt(int)))
+ def operate_aio_write_op(self, write_op, oid, oncomplete=None, onsafe=None, mtime=0, flags=LIBRADOS_OPERATION_NOFLAG):
+ """
+ execute the real write operation asynchronously
+ :para write_op: write operation object
+ :type write_op: WriteOp
+ :para oid: object name
+ :type oid: str
+ :param oncomplete: what to do when the remove is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the remove is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+ :para mtime: the time to set the mtime to, 0 for the current time
+ :type mtime: int
+ :para flags: flags to apply to the entire operation
+ :type flags: int
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ oid = cstr(oid, 'oid')
+ cdef:
+ WriteOp _write_op = write_op
+ char *_oid = oid
+ Completion completion
+ time_t _mtime = mtime
+ int _flags = flags
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+
+ with nogil:
+ ret = rados_aio_write_op_operate(_write_op.write_op, self.io, completion.rados_comp, _oid,
+ &_mtime, _flags)
+ if ret != 0:
+ completion._cleanup()
+ raise make_ex(ret, "Failed to operate aio write op for oid %s" % oid)
+ return completion
+
+ @requires(('read_op', ReadOp), ('oid', str_type), ('flag', opt(int)))
+ def operate_read_op(self, read_op, oid, flag=LIBRADOS_OPERATION_NOFLAG):
+ """
+ execute the real read operation
+ :para read_op: read operation object
+ :type read_op: ReadOp
+ :para oid: object name
+ :type oid: str
+ :para flag: flags to apply to the entire operation
+ :type flag: int
+ """
+ oid = cstr(oid, 'oid')
+ cdef:
+ ReadOp _read_op = read_op
+ char *_oid = oid
+ int _flag = flag
+
+ with nogil:
+ ret = rados_read_op_operate(_read_op.read_op, self.io, _oid, _flag)
+ if ret != 0:
+ raise make_ex(ret, "Failed to operate read op for oid %s" % oid)
+
+ @requires(('read_op', ReadOp), ('oid', str_type), ('oncomplete', opt(Callable)), ('onsafe', opt(Callable)), ('flag', opt(int)))
+ def operate_aio_read_op(self, read_op, oid, oncomplete=None, onsafe=None, flag=LIBRADOS_OPERATION_NOFLAG):
+ """
+ execute the real read operation
+ :para read_op: read operation object
+ :type read_op: ReadOp
+ :para oid: object name
+ :type oid: str
+ :param oncomplete: what to do when the remove is safe and complete in memory
+ on all replicas
+ :type oncomplete: completion
+ :param onsafe: what to do when the remove is safe and complete on storage
+ on all replicas
+ :type onsafe: completion
+ :para flag: flags to apply to the entire operation
+ :type flag: int
+ """
+ oid = cstr(oid, 'oid')
+ cdef:
+ ReadOp _read_op = read_op
+ char *_oid = oid
+ Completion completion
+ int _flag = flag
+
+ completion = self.__get_completion(oncomplete, onsafe)
+ self.__track_completion(completion)
+
+ with nogil:
+ ret = rados_aio_read_op_operate(_read_op.read_op, self.io, completion.rados_comp, _oid, _flag)
+ if ret != 0:
+ completion._cleanup()
+ raise make_ex(ret, "Failed to operate aio read op for oid %s" % oid)
+ return completion
+
+ @requires(('read_op', ReadOp), ('start_after', str_type), ('filter_prefix', str_type), ('max_return', int))
+ def get_omap_vals(self, read_op, start_after, filter_prefix, max_return):
+ """
+ get the omap values
+ :para read_op: read operation object
+ :type read_op: ReadOp
+ :para start_after: list keys starting after start_after
+ :type start_after: str
+ :para filter_prefix: list only keys beginning with filter_prefix
+ :type filter_prefix: str
+ :para max_return: list no more than max_return key/value pairs
+ :type max_return: int
+ :returns: an iterator over the requested omap values, return value from this action
+ """
+
+ start_after = cstr(start_after, 'start_after') if start_after else None
+ filter_prefix = cstr(filter_prefix, 'filter_prefix') if filter_prefix else None
+ cdef:
+ char *_start_after = opt_str(start_after)
+ char *_filter_prefix = opt_str(filter_prefix)
+ ReadOp _read_op = read_op
+ rados_omap_iter_t iter_addr = NULL
+ int _max_return = max_return
+
+ with nogil:
+ rados_read_op_omap_get_vals2(_read_op.read_op, _start_after, _filter_prefix,
+ _max_return, &iter_addr, NULL, NULL)
+ it = OmapIterator(self)
+ it.ctx = iter_addr
+ return it, 0 # 0 is meaningless; there for backward-compat
+
+ @requires(('read_op', ReadOp), ('start_after', str_type), ('max_return', int))
+ def get_omap_keys(self, read_op, start_after, max_return):
+ """
+ get the omap keys
+ :para read_op: read operation object
+ :type read_op: ReadOp
+ :para start_after: list keys starting after start_after
+ :type start_after: str
+ :para max_return: list no more than max_return key/value pairs
+ :type max_return: int
+ :returns: an iterator over the requested omap values, return value from this action
+ """
+ start_after = cstr(start_after, 'start_after') if start_after else None
+ cdef:
+ char *_start_after = opt_str(start_after)
+ ReadOp _read_op = read_op
+ rados_omap_iter_t iter_addr = NULL
+ int _max_return = max_return
+
+ with nogil:
+ rados_read_op_omap_get_keys2(_read_op.read_op, _start_after,
+ _max_return, &iter_addr, NULL, NULL)
+ it = OmapIterator(self)
+ it.ctx = iter_addr
+ return it, 0 # 0 is meaningless; there for backward-compat
+
+ @requires(('read_op', ReadOp), ('keys', tuple))
+ def get_omap_vals_by_keys(self, read_op, keys):
+ """
+ get the omap values by keys
+ :para read_op: read operation object
+ :type read_op: ReadOp
+ :para keys: input key tuple
+ :type keys: tuple
+ :returns: an iterator over the requested omap values, return value from this action
+ """
+ keys = cstr_list(keys, 'keys')
+ cdef:
+ ReadOp _read_op = read_op
+ rados_omap_iter_t iter_addr
+ char **_keys = to_bytes_array(keys)
+ size_t key_num = len(keys)
+
+ try:
+ with nogil:
+ rados_read_op_omap_get_vals_by_keys(_read_op.read_op,
+ <const char**>_keys,
+ key_num, &iter_addr, NULL)
+ it = OmapIterator(self)
+ it.ctx = iter_addr
+ return it, 0 # 0 is meaningless; there for backward-compat
+ finally:
+ free(_keys)
+
+ @requires(('write_op', WriteOp), ('keys', tuple))
+ def remove_omap_keys(self, write_op, keys):
+ """
+ remove omap keys specifiled
+ :para write_op: write operation object
+ :type write_op: WriteOp
+ :para keys: input key tuple
+ :type keys: tuple
+ """
+
+ keys = cstr_list(keys, 'keys')
+ cdef:
+ WriteOp _write_op = write_op
+ size_t key_num = len(keys)
+ char **_keys = to_bytes_array(keys)
+
+ try:
+ with nogil:
+ rados_write_op_omap_rm_keys(_write_op.write_op, <const char**>_keys, key_num)
+ finally:
+ free(_keys)
+
+ @requires(('write_op', WriteOp))
+ def clear_omap(self, write_op):
+ """
+ Remove all key/value pairs from an object
+ :para write_op: write operation object
+ :type write_op: WriteOp
+ """
+
+ cdef:
+ WriteOp _write_op = write_op
+
+ with nogil:
+ rados_write_op_omap_clear(_write_op.write_op)
+
+ @requires(('key', str_type), ('name', str_type), ('cookie', str_type), ('desc', str_type),
+ ('duration', opt(int)), ('flags', int))
+ def lock_exclusive(self, key, name, cookie, desc="", duration=None, flags=0):
+
+ """
+ Take an exclusive lock on an object
+
+ :param key: name of the object
+ :type key: str
+ :param name: name of the lock
+ :type name: str
+ :param cookie: cookie of the lock
+ :type cookie: str
+ :param desc: description of the lock
+ :type desc: str
+ :param duration: duration of the lock in seconds
+ :type duration: int
+ :param flags: flags
+ :type flags: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ name = cstr(name, 'name')
+ cookie = cstr(cookie, 'cookie')
+ desc = cstr(desc, 'desc')
+
+ cdef:
+ char* _key = key
+ char* _name = name
+ char* _cookie = cookie
+ char* _desc = desc
+ uint8_t _flags = flags
+ timeval _duration
+
+ if duration is None:
+ with nogil:
+ ret = rados_lock_exclusive(self.io, _key, _name, _cookie, _desc,
+ NULL, _flags)
+ else:
+ _duration.tv_sec = duration
+ with nogil:
+ ret = rados_lock_exclusive(self.io, _key, _name, _cookie, _desc,
+ &_duration, _flags)
+
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.rados_lock_exclusive(%s): failed to set lock %s on %s" % (self.name, name, key))
+
+ @requires(('key', str_type), ('name', str_type), ('cookie', str_type), ('tag', str_type),
+ ('desc', str_type), ('duration', opt(int)), ('flags', int))
+ def lock_shared(self, key, name, cookie, tag, desc="", duration=None, flags=0):
+
+ """
+ Take a shared lock on an object
+
+ :param key: name of the object
+ :type key: str
+ :param name: name of the lock
+ :type name: str
+ :param cookie: cookie of the lock
+ :type cookie: str
+ :param tag: tag of the lock
+ :type tag: str
+ :param desc: description of the lock
+ :type desc: str
+ :param duration: duration of the lock in seconds
+ :type duration: int
+ :param flags: flags
+ :type flags: int
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ tag = cstr(tag, 'tag')
+ name = cstr(name, 'name')
+ cookie = cstr(cookie, 'cookie')
+ desc = cstr(desc, 'desc')
+
+ cdef:
+ char* _key = key
+ char* _tag = tag
+ char* _name = name
+ char* _cookie = cookie
+ char* _desc = desc
+ uint8_t _flags = flags
+ timeval _duration
+
+ if duration is None:
+ with nogil:
+ ret = rados_lock_shared(self.io, _key, _name, _cookie, _tag, _desc,
+ NULL, _flags)
+ else:
+ _duration.tv_sec = duration
+ with nogil:
+ ret = rados_lock_shared(self.io, _key, _name, _cookie, _tag, _desc,
+ &_duration, _flags)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.rados_lock_exclusive(%s): failed to set lock %s on %s" % (self.name, name, key))
+
+ @requires(('key', str_type), ('name', str_type), ('cookie', str_type))
+ def unlock(self, key, name, cookie):
+
+ """
+ Release a shared or exclusive lock on an object
+
+ :param key: name of the object
+ :type key: str
+ :param name: name of the lock
+ :type name: str
+ :param cookie: cookie of the lock
+ :type cookie: str
+
+ :raises: :class:`TypeError`
+ :raises: :class:`Error`
+ """
+ self.require_ioctx_open()
+
+ key = cstr(key, 'key')
+ name = cstr(name, 'name')
+ cookie = cstr(cookie, 'cookie')
+
+ cdef:
+ char* _key = key
+ char* _name = name
+ char* _cookie = cookie
+
+ with nogil:
+ ret = rados_unlock(self.io, _key, _name, _cookie)
+ if ret < 0:
+ raise make_ex(ret, "Ioctx.rados_lock_exclusive(%s): failed to set lock %s on %s" % (self.name, name, key))
+
+ def set_osdmap_full_try(self):
+ """
+ Set global osdmap_full_try label to true
+ """
+ with nogil:
+ rados_set_osdmap_full_try(self.io)
+
+ def unset_osdmap_full_try(self):
+ """
+ Unset
+ """
+ with nogil:
+ rados_unset_osdmap_full_try(self.io)
+
+ def application_enable(self, app_name, force=False):
+ """
+ Enable an application on an OSD pool
+
+ :param app_name: application name
+ :type app_name: str
+ :param force: False if only a single app should exist per pool
+ :type expire_seconds: boool
+
+ :raises: :class:`Error`
+ """
+ app_name = cstr(app_name, 'app_name')
+ cdef:
+ char *_app_name = app_name
+ int _force = (1 if force else 0)
+
+ with nogil:
+ ret = rados_application_enable(self.io, _app_name, _force)
+ if ret < 0:
+ raise make_ex(ret, "error enabling application")
+
+ def application_list(self):
+ """
+ Returns a list of enabled applications
+
+ :returns: list of app name string
+ """
+ cdef:
+ size_t length = 128
+ char *apps = NULL
+
+ try:
+ while True:
+ apps = <char *>realloc_chk(apps, length)
+ with nogil:
+ ret = rados_application_list(self.io, apps, &length)
+ if ret == 0:
+ return [decode_cstr(app) for app in
+ apps[:length].split(b'\0') if app]
+ elif ret == -errno.ENOENT:
+ return None
+ elif ret == -errno.ERANGE:
+ pass
+ else:
+ raise make_ex(ret, "error listing applications")
+ finally:
+ free(apps)
+
+ def application_metadata_set(self, app_name, key, value):
+ """
+ Sets application metadata on an OSD pool
+
+ :param app_name: application name
+ :type app_name: str
+ :param key: metadata key
+ :type key: str
+ :param value: metadata value
+ :type value: str
+
+ :raises: :class:`Error`
+ """
+ app_name = cstr(app_name, 'app_name')
+ key = cstr(key, 'key')
+ value = cstr(value, 'value')
+ cdef:
+ char *_app_name = app_name
+ char *_key = key
+ char *_value = value
+
+ with nogil:
+ ret = rados_application_metadata_set(self.io, _app_name, _key,
+ _value)
+ if ret < 0:
+ raise make_ex(ret, "error setting application metadata")
+
+ def application_metadata_remove(self, app_name, key):
+ """
+ Remove application metadata from an OSD pool
+
+ :param app_name: application name
+ :type app_name: str
+ :param key: metadata key
+ :type key: str
+
+ :raises: :class:`Error`
+ """
+ app_name = cstr(app_name, 'app_name')
+ key = cstr(key, 'key')
+ cdef:
+ char *_app_name = app_name
+ char *_key = key
+
+ with nogil:
+ ret = rados_application_metadata_remove(self.io, _app_name, _key)
+ if ret < 0:
+ raise make_ex(ret, "error removing application metadata")
+
+ def application_metadata_list(self, app_name):
+ """
+ Returns a list of enabled applications
+
+ :param app_name: application name
+ :type app_name: str
+ :returns: list of key/value tuples
+ """
+ app_name = cstr(app_name, 'app_name')
+ cdef:
+ char *_app_name = app_name
+ size_t key_length = 128
+ size_t val_length = 128
+ char *c_keys = NULL
+ char *c_vals = NULL
+
+ try:
+ while True:
+ c_keys = <char *>realloc_chk(c_keys, key_length)
+ c_vals = <char *>realloc_chk(c_vals, val_length)
+ with nogil:
+ ret = rados_application_metadata_list(self.io, _app_name,
+ c_keys, &key_length,
+ c_vals, &val_length)
+ if ret == 0:
+ keys = [decode_cstr(key) for key in
+ c_keys[:key_length].split(b'\0')]
+ vals = [decode_cstr(val) for val in
+ c_vals[:val_length].split(b'\0')]
+ return zip(keys, vals)[:-1]
+ elif ret == -errno.ERANGE:
+ pass
+ else:
+ raise make_ex(ret, "error listing application metadata")
+ finally:
+ free(c_keys)
+ free(c_vals)
+
+ def alignment(self):
+ """
+ Returns pool alignment
+
+ :returns:
+ Number of alignment bytes required by the current pool, or None if
+ alignment is not required.
+ """
+ cdef:
+ int requires = 0
+ uint64_t _alignment
+
+ with nogil:
+ ret = rados_ioctx_pool_requires_alignment2(self.io, &requires)
+ if ret != 0:
+ raise make_ex(ret, "error checking alignment")
+
+ alignment = None
+ if requires:
+ with nogil:
+ ret = rados_ioctx_pool_required_alignment2(self.io, &_alignment)
+ if ret != 0:
+ raise make_ex(ret, "error querying alignment")
+ alignment = _alignment
+ return alignment
+
+
+def set_object_locator(func):
+ def retfunc(self, *args, **kwargs):
+ if self.locator_key is not None:
+ old_locator = self.ioctx.get_locator_key()
+ self.ioctx.set_locator_key(self.locator_key)
+ retval = func(self, *args, **kwargs)
+ self.ioctx.set_locator_key(old_locator)
+ return retval
+ else:
+ return func(self, *args, **kwargs)
+ return retfunc
+
+
+def set_object_namespace(func):
+ def retfunc(self, *args, **kwargs):
+ if self.nspace is None:
+ raise LogicError("Namespace not set properly in context")
+ old_nspace = self.ioctx.get_namespace()
+ self.ioctx.set_namespace(self.nspace)
+ retval = func(self, *args, **kwargs)
+ self.ioctx.set_namespace(old_nspace)
+ return retval
+ return retfunc
+
+
+class Object(object):
+ """Rados object wrapper, makes the object look like a file"""
+ def __init__(self, ioctx, key, locator_key=None, nspace=None):
+ self.key = key
+ self.ioctx = ioctx
+ self.offset = 0
+ self.state = "exists"
+ self.locator_key = locator_key
+ self.nspace = "" if nspace is None else nspace
+
+ def __str__(self):
+ return "rados.Object(ioctx=%s,key=%s,nspace=%s,locator=%s)" % \
+ (str(self.ioctx), self.key, "--default--"
+ if self.nspace is "" else self.nspace, self.locator_key)
+
+ def require_object_exists(self):
+ if self.state != "exists":
+ raise ObjectStateError("The object is %s" % self.state)
+
+ @set_object_locator
+ @set_object_namespace
+ def read(self, length=1024 * 1024):
+ self.require_object_exists()
+ ret = self.ioctx.read(self.key, length, self.offset)
+ self.offset += len(ret)
+ return ret
+
+ @set_object_locator
+ @set_object_namespace
+ def write(self, string_to_write):
+ self.require_object_exists()
+ ret = self.ioctx.write(self.key, string_to_write, self.offset)
+ if ret == 0:
+ self.offset += len(string_to_write)
+ return ret
+
+ @set_object_locator
+ @set_object_namespace
+ def remove(self):
+ self.require_object_exists()
+ self.ioctx.remove_object(self.key)
+ self.state = "removed"
+
+ @set_object_locator
+ @set_object_namespace
+ def stat(self):
+ self.require_object_exists()
+ return self.ioctx.stat(self.key)
+
+ def seek(self, position):
+ self.require_object_exists()
+ self.offset = position
+
+ @set_object_locator
+ @set_object_namespace
+ def get_xattr(self, xattr_name):
+ self.require_object_exists()
+ return self.ioctx.get_xattr(self.key, xattr_name)
+
+ @set_object_locator
+ @set_object_namespace
+ def get_xattrs(self):
+ self.require_object_exists()
+ return self.ioctx.get_xattrs(self.key)
+
+ @set_object_locator
+ @set_object_namespace
+ def set_xattr(self, xattr_name, xattr_value):
+ self.require_object_exists()
+ return self.ioctx.set_xattr(self.key, xattr_name, xattr_value)
+
+ @set_object_locator
+ @set_object_namespace
+ def rm_xattr(self, xattr_name):
+ self.require_object_exists()
+ return self.ioctx.rm_xattr(self.key, xattr_name)
+
+MONITOR_LEVELS = [
+ "debug",
+ "info",
+ "warn", "warning",
+ "err", "error",
+ "sec",
+ ]
+
+
+class MonitorLog(object):
+ # NOTE(sileht): Keep this class for backward compat
+ # method moved to Rados.monitor_log()
+ """
+ For watching cluster log messages. Instantiate an object and keep
+ it around while callback is periodically called. Construct with
+ 'level' to monitor 'level' messages (one of MONITOR_LEVELS).
+ arg will be passed to the callback.
+
+ callback will be called with:
+ arg (given to __init__)
+ line (the full line, including timestamp, who, level, msg)
+ who (which entity issued the log message)
+ timestamp_sec (sec of a struct timespec)
+ timestamp_nsec (sec of a struct timespec)
+ seq (sequence number)
+ level (string representing the level of the log message)
+ msg (the message itself)
+ callback's return value is ignored
+ """
+ def __init__(self, cluster, level, callback, arg):
+ self.level = level
+ self.callback = callback
+ self.arg = arg
+ self.cluster = cluster
+ self.cluster.monitor_log(level, callback, arg)
+
diff --git a/src/pybind/rados/setup.py b/src/pybind/rados/setup.py
new file mode 100755
index 00000000..75081df7
--- /dev/null
+++ b/src/pybind/rados/setup.py
@@ -0,0 +1,215 @@
+from __future__ import print_function
+
+import os
+import pkgutil
+import shutil
+import subprocess
+import sys
+import tempfile
+import textwrap
+
+if not pkgutil.find_loader('setuptools'):
+ from distutils.core import setup
+ from distutils.extension import Extension
+else:
+ from setuptools import setup
+ from setuptools.extension import Extension
+
+from distutils.ccompiler import new_compiler
+from distutils.errors import CompileError, LinkError
+import distutils.sysconfig
+
+unwrapped_customize = distutils.sysconfig.customize_compiler
+
+clang = False
+
+def filter_unsupported_flags(flags):
+ if clang:
+ return [f for f in flags if not (f == '-mcet' or
+ f.startswith('-fcf-protection'))]
+ else:
+ return flags
+
+def monkey_with_compiler(compiler):
+ unwrapped_customize(compiler)
+ if compiler.compiler_type == 'unix':
+ if compiler.compiler[0].find('clang') != -1:
+ global clang
+ clang = True
+ compiler.compiler = filter_unsupported_flags(compiler.compiler)
+ compiler.compiler_so = filter_unsupported_flags(
+ compiler.compiler_so)
+
+distutils.sysconfig.customize_compiler = monkey_with_compiler
+
+# PEP 440 versioning of the Rados package on PyPI
+# Bump this version, after every changeset
+__version__ = '2.0.0'
+
+
+def get_python_flags():
+ cflags = {'I': [], 'extras': []}
+ ldflags = {'l': [], 'L': [], 'extras': []}
+
+ if os.environ.get('VIRTUAL_ENV', None):
+ python = "python"
+ else:
+ python = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
+
+ python_config = python + '-config'
+
+ for cflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--cflags"]).strip().decode('utf-8').split()):
+ if cflag.startswith('-I'):
+ cflags['I'].append(cflag.replace('-I', ''))
+ else:
+ cflags['extras'].append(cflag)
+
+ for ldflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--ldflags"]).strip().decode('utf-8').split()):
+ if ldflag.startswith('-l'):
+ ldflags['l'].append(ldflag.replace('-l', ''))
+ if ldflag.startswith('-L'):
+ ldflags['L'].append(ldflag.replace('-L', ''))
+ else:
+ ldflags['extras'].append(ldflag)
+
+ return {
+ 'cflags': cflags,
+ 'ldflags': ldflags
+ }
+
+
+def check_sanity():
+ """
+ Test if development headers and library for rados is available by compiling a dummy C program.
+ """
+ CEPH_SRC_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..',
+ '..'
+ )
+
+ tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__)))
+ tmp_file = os.path.join(tmp_dir, 'rados_dummy.c')
+
+ with open(tmp_file, 'w') as fp:
+ dummy_prog = textwrap.dedent("""
+ #include <rados/librados.h>
+
+ int main(void) {
+ rados_t cluster;
+ rados_create(&cluster, NULL);
+ return 0;
+ }
+ """)
+ fp.write(dummy_prog)
+
+ compiler = new_compiler()
+ distutils.sysconfig.customize_compiler(compiler)
+
+ if {'MAKEFLAGS', 'MAKELEVEL'}.issubset(set(os.environ.keys())):
+ # The setup.py has been invoked by a top-level Ceph make.
+ # Set the appropriate CFLAGS and LDFLAGS
+
+ compiler.set_include_dirs([os.path.join(CEPH_SRC_DIR, 'include')])
+ compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')])
+
+ try:
+ link_objects = compiler.compile(
+ sources=[tmp_file],
+ output_dir=tmp_dir
+ )
+ compiler.link_executable(
+ objects=link_objects,
+ output_progname=os.path.join(tmp_dir, 'rados_dummy'),
+ libraries=['rados'],
+ output_dir=tmp_dir,
+ )
+
+ except CompileError:
+ print('\nCompile Error: RADOS development headers not found', file=sys.stderr)
+ return False
+ except LinkError:
+ print('\nLink Error: RADOS library not found', file=sys.stderr)
+ return False
+ else:
+ return True
+ finally:
+ shutil.rmtree(tmp_dir)
+
+
+if 'BUILD_DOC' in os.environ.keys():
+ pass
+elif check_sanity():
+ pass
+else:
+ sys.exit(1)
+
+cmdclass = {}
+try:
+ from Cython.Build import cythonize
+ from Cython.Distutils import build_ext
+
+ cmdclass = {'build_ext': build_ext}
+except ImportError:
+ print("WARNING: Cython is not installed.")
+
+ if not os.path.isfile('rados.c'):
+ print('ERROR: Cannot find Cythonized file rados.c', file=sys.stderr)
+ sys.exit(1)
+ else:
+ def cythonize(x, **kwargs):
+ return x
+
+ source = "rados.c"
+else:
+ source = "rados.pyx"
+
+# Disable cythonification if we're not really building anything
+if (len(sys.argv) >= 2 and
+ any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version')
+ )):
+ def cythonize(x, **kwargs):
+ return x
+
+flags = get_python_flags()
+
+setup(
+ name='rados',
+ version=__version__,
+ description="Python bindings for the Ceph librados library",
+ long_description=(
+ "This package contains Python bindings for interacting with Ceph's "
+ "RADOS library. RADOS is a reliable, autonomic distributed object "
+ "storage cluster developed as part of the Ceph distributed storage "
+ "system. This is a shared library allowing applications to access "
+ "the distributed object store using a simple file-like interface."
+ ),
+ url='https://github.com/ceph/ceph/tree/master/src/pybind/rados',
+ license='LGPLv2+',
+ platforms='Linux',
+ ext_modules=cythonize(
+ [
+ Extension(
+ "rados",
+ [source],
+ include_dirs=flags['cflags']['I'],
+ library_dirs=flags['ldflags']['L'],
+ libraries=["rados"] + flags['ldflags']['l'],
+ extra_compile_args=flags['cflags']['extras'] + flags['ldflags']['extras'],
+ )
+ ], build_dir=os.environ.get("CYTHON_BUILD_DIR", None)
+ ),
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Cython',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5'
+ ],
+ cmdclass=cmdclass,
+)
diff --git a/src/pybind/rbd/CMakeLists.txt b/src/pybind/rbd/CMakeLists.txt
new file mode 100644
index 00000000..fee56ec4
--- /dev/null
+++ b/src/pybind/rbd/CMakeLists.txt
@@ -0,0 +1,3 @@
+distutils_add_cython_module(cython${PYTHON_VERSION}_rbd ${CMAKE_CURRENT_SOURCE_DIR}/rbd.pyx)
+add_dependencies(cython${PYTHON_VERSION}_rbd librbd)
+distutils_install_cython_module(cython${PYTHON_VERSION}_rbd)
diff --git a/src/pybind/rbd/MANIFEST.in b/src/pybind/rbd/MANIFEST.in
new file mode 100644
index 00000000..895882de
--- /dev/null
+++ b/src/pybind/rbd/MANIFEST.in
@@ -0,0 +1 @@
+include rbd.pyx
diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx
new file mode 100644
index 00000000..264c91fb
--- /dev/null
+++ b/src/pybind/rbd/rbd.pyx
@@ -0,0 +1,5348 @@
+# cython: embedsignature=True
+"""
+This module is a thin wrapper around librbd.
+
+It currently provides all the synchronous methods of librbd that do
+not use callbacks.
+
+Error codes from librbd are turned into exceptions that subclass
+:class:`Error`. Almost all methods may raise :class:`Error`
+(the base class of all rbd exceptions), :class:`PermissionError`
+and :class:`IOError`, in addition to those documented for the
+method.
+"""
+# Copyright 2011 Josh Durgin
+# Copyright 2015 Hector Martin <marcan@marcan.st>
+
+import cython
+import sys
+
+from cpython cimport PyObject, ref, exc
+from libc cimport errno
+from libc.stdint cimport *
+from libc.stdlib cimport realloc, free
+from libc.string cimport strdup
+
+try:
+ from collections.abc import Iterable
+except ImportError:
+ from collections import Iterable
+from datetime import datetime
+from itertools import chain
+import time
+
+cimport rados
+
+
+cdef extern from "Python.h":
+ # These are in cpython/string.pxd, but use "object" types instead of
+ # PyObject*, which invokes assumptions in cpython that we need to
+ # legitimately break to implement zero-copy string buffers in Image.read().
+ # This is valid use of the Python API and documented as a special case.
+ PyObject *PyBytes_FromStringAndSize(char *v, Py_ssize_t len) except NULL
+ char* PyBytes_AsString(PyObject *string) except NULL
+ int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
+
+cdef extern from "time.h":
+ ctypedef long int time_t
+ cdef struct timespec:
+ time_t tv_sec
+ long tv_nsec
+
+cdef extern from "<errno.h>" nogil:
+ enum:
+ _ECANCELED "ECANCELED"
+
+cdef extern from "rados/librados.h":
+ enum:
+ _LIBRADOS_SNAP_HEAD "LIBRADOS_SNAP_HEAD"
+
+cdef extern from "rbd/librbd.h":
+ ctypedef int (*librbd_progress_fn_t)(uint64_t offset, uint64_t total, void* ptr)
+
+cdef extern from "rbd/librbd.h" nogil:
+ enum:
+ _RBD_FEATURE_LAYERING "RBD_FEATURE_LAYERING"
+ _RBD_FEATURE_STRIPINGV2 "RBD_FEATURE_STRIPINGV2"
+ _RBD_FEATURE_EXCLUSIVE_LOCK "RBD_FEATURE_EXCLUSIVE_LOCK"
+ _RBD_FEATURE_OBJECT_MAP "RBD_FEATURE_OBJECT_MAP"
+ _RBD_FEATURE_FAST_DIFF "RBD_FEATURE_FAST_DIFF"
+ _RBD_FEATURE_DEEP_FLATTEN "RBD_FEATURE_DEEP_FLATTEN"
+ _RBD_FEATURE_JOURNALING "RBD_FEATURE_JOURNALING"
+ _RBD_FEATURE_DATA_POOL "RBD_FEATURE_DATA_POOL"
+ _RBD_FEATURE_OPERATIONS "RBD_FEATURE_OPERATIONS"
+ _RBD_FEATURE_MIGRATING "RBD_FEATURE_MIGRATING"
+
+ _RBD_FEATURES_INCOMPATIBLE "RBD_FEATURES_INCOMPATIBLE"
+ _RBD_FEATURES_RW_INCOMPATIBLE "RBD_FEATURES_RW_INCOMPATIBLE"
+ _RBD_FEATURES_MUTABLE "RBD_FEATURES_MUTABLE"
+ _RBD_FEATURES_SINGLE_CLIENT "RBD_FEATURES_SINGLE_CLIENT"
+ _RBD_FEATURES_ALL "RBD_FEATURES_ALL"
+
+ _RBD_OPERATION_FEATURE_CLONE_PARENT "RBD_OPERATION_FEATURE_CLONE_PARENT"
+ _RBD_OPERATION_FEATURE_CLONE_CHILD "RBD_OPERATION_FEATURE_CLONE_CHILD"
+ _RBD_OPERATION_FEATURE_GROUP "RBD_OPERATION_FEATURE_GROUP"
+ _RBD_OPERATION_FEATURE_SNAP_TRASH "RBD_OPERATION_FEATURE_SNAP_TRASH"
+
+ _RBD_FLAG_OBJECT_MAP_INVALID "RBD_FLAG_OBJECT_MAP_INVALID"
+ _RBD_FLAG_FAST_DIFF_INVALID "RBD_FLAG_FAST_DIFF_INVALID"
+
+ _RBD_IMAGE_OPTION_FORMAT "RBD_IMAGE_OPTION_FORMAT"
+ _RBD_IMAGE_OPTION_FEATURES "RBD_IMAGE_OPTION_FEATURES"
+ _RBD_IMAGE_OPTION_ORDER "RBD_IMAGE_OPTION_ORDER"
+ _RBD_IMAGE_OPTION_STRIPE_UNIT "RBD_IMAGE_OPTION_STRIPE_UNIT"
+ _RBD_IMAGE_OPTION_STRIPE_COUNT "RBD_IMAGE_OPTION_STRIPE_COUNT"
+ _RBD_IMAGE_OPTION_DATA_POOL "RBD_IMAGE_OPTION_DATA_POOL"
+
+ RBD_MAX_BLOCK_NAME_SIZE
+ RBD_MAX_IMAGE_NAME_SIZE
+
+ ctypedef void* rados_t
+ ctypedef void* rados_ioctx_t
+ ctypedef void* rbd_image_t
+ ctypedef void* rbd_image_options_t
+ ctypedef void* rbd_pool_stats_t
+ ctypedef void *rbd_completion_t
+
+ ctypedef struct rbd_image_info_t:
+ uint64_t size
+ uint64_t obj_size
+ uint64_t num_objs
+ int order
+ char block_name_prefix[RBD_MAX_BLOCK_NAME_SIZE]
+ uint64_t parent_pool
+ char parent_name[RBD_MAX_IMAGE_NAME_SIZE]
+
+ ctypedef struct rbd_snap_info_t:
+ uint64_t id
+ uint64_t size
+ char *name
+
+ ctypedef struct rbd_snap_group_namespace_t:
+ int64_t group_pool
+ char *group_name
+ char *group_snap_name
+
+ ctypedef struct rbd_group_info_t:
+ char *name
+ int64_t pool
+
+ ctypedef struct rbd_image_spec_t:
+ char *id
+ char *name
+
+ ctypedef struct rbd_linked_image_spec_t:
+ int64_t pool_id
+ char *pool_name
+ char *pool_namespace
+ char *image_id
+ char *image_name
+ bint trash
+
+ ctypedef enum rbd_snap_namespace_type_t:
+ _RBD_SNAP_NAMESPACE_TYPE_USER "RBD_SNAP_NAMESPACE_TYPE_USER"
+ _RBD_SNAP_NAMESPACE_TYPE_GROUP "RBD_SNAP_NAMESPACE_TYPE_GROUP"
+ _RBD_SNAP_NAMESPACE_TYPE_TRASH "RBD_SNAP_NAMESPACE_TYPE_TRASH"
+
+ ctypedef struct rbd_snap_spec_t:
+ uint64_t id
+ rbd_snap_namespace_type_t namespace_type
+ char *name
+
+ ctypedef enum rbd_mirror_mode_t:
+ _RBD_MIRROR_MODE_DISABLED "RBD_MIRROR_MODE_DISABLED"
+ _RBD_MIRROR_MODE_IMAGE "RBD_MIRROR_MODE_IMAGE"
+ _RBD_MIRROR_MODE_POOL "RBD_MIRROR_MODE_POOL"
+
+ ctypedef enum rbd_mirror_peer_direction_t:
+ _RBD_MIRROR_PEER_DIRECTION_RX "RBD_MIRROR_PEER_DIRECTION_RX"
+ _RBD_MIRROR_PEER_DIRECTION_TX "RBD_MIRROR_PEER_DIRECTION_TX"
+ _RBD_MIRROR_PEER_DIRECTION_RX_TX "RBD_MIRROR_PEER_DIRECTION_RX_TX"
+
+ ctypedef struct rbd_mirror_peer_t:
+ char *uuid
+ char *cluster_name
+ char *client_name
+
+ cdef char* _RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST "RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST"
+ cdef char* _RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY "RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY"
+
+ ctypedef enum rbd_mirror_image_state_t:
+ _RBD_MIRROR_IMAGE_DISABLING "RBD_MIRROR_IMAGE_DISABLING"
+ _RBD_MIRROR_IMAGE_ENABLED "RBD_MIRROR_IMAGE_ENABLED"
+ _RBD_MIRROR_IMAGE_DISABLED "RBD_MIRROR_IMAGE_DISABLED"
+
+ ctypedef struct rbd_mirror_image_info_t:
+ char *global_id
+ rbd_mirror_image_state_t state
+ bint primary
+
+ ctypedef enum rbd_mirror_image_status_state_t:
+ _MIRROR_IMAGE_STATUS_STATE_UNKNOWN "MIRROR_IMAGE_STATUS_STATE_UNKNOWN"
+ _MIRROR_IMAGE_STATUS_STATE_ERROR "MIRROR_IMAGE_STATUS_STATE_ERROR"
+ _MIRROR_IMAGE_STATUS_STATE_SYNCING "MIRROR_IMAGE_STATUS_STATE_SYNCING"
+ _MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY "MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY"
+ _MIRROR_IMAGE_STATUS_STATE_REPLAYING "MIRROR_IMAGE_STATUS_STATE_REPLAYING"
+ _MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY "MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY"
+ _MIRROR_IMAGE_STATUS_STATE_STOPPED "MIRROR_IMAGE_STATUS_STATE_STOPPED"
+
+ ctypedef struct rbd_mirror_image_status_t:
+ char *name
+ rbd_mirror_image_info_t info
+ rbd_mirror_image_status_state_t state
+ char *description
+ time_t last_update
+ bint up
+
+ ctypedef enum rbd_lock_mode_t:
+ _RBD_LOCK_MODE_EXCLUSIVE "RBD_LOCK_MODE_EXCLUSIVE"
+ _RBD_LOCK_MODE_SHARED "RBD_LOCK_MODE_SHARED"
+
+ ctypedef enum rbd_trash_image_source_t:
+ _RBD_TRASH_IMAGE_SOURCE_USER "RBD_TRASH_IMAGE_SOURCE_USER",
+ _RBD_TRASH_IMAGE_SOURCE_MIRRORING "RBD_TRASH_IMAGE_SOURCE_MIRRORING",
+ _RBD_TRASH_IMAGE_SOURCE_MIGRATION "RBD_TRASH_IMAGE_SOURCE_MIGRATION"
+ _RBD_TRASH_IMAGE_SOURCE_REMOVING "RBD_TRASH_IMAGE_SOURCE_REMOVING"
+
+ ctypedef struct rbd_trash_image_info_t:
+ char *id
+ char *name
+ rbd_trash_image_source_t source
+ time_t deletion_time
+ time_t deferment_end_time
+
+ ctypedef struct rbd_image_watcher_t:
+ char *addr
+ int64_t id
+ uint64_t cookie
+
+ ctypedef enum rbd_group_image_state_t:
+ _RBD_GROUP_IMAGE_STATE_ATTACHED "RBD_GROUP_IMAGE_STATE_ATTACHED"
+ _RBD_GROUP_IMAGE_STATE_INCOMPLETE "RBD_GROUP_IMAGE_STATE_INCOMPLETE"
+
+ ctypedef struct rbd_group_image_info_t:
+ char *name
+ int64_t pool
+ rbd_group_image_state_t state
+
+ ctypedef enum rbd_group_snap_state_t:
+ _RBD_GROUP_SNAP_STATE_INCOMPLETE "RBD_GROUP_SNAP_STATE_INCOMPLETE"
+ _RBD_GROUP_SNAP_STATE_COMPLETE "RBD_GROUP_SNAP_STATE_COMPLETE"
+
+ ctypedef struct rbd_group_snap_info_t:
+ char *name
+ rbd_group_snap_state_t state
+
+ ctypedef enum rbd_image_migration_state_t:
+ _RBD_IMAGE_MIGRATION_STATE_UNKNOWN "RBD_IMAGE_MIGRATION_STATE_UNKNOWN"
+ _RBD_IMAGE_MIGRATION_STATE_ERROR "RBD_IMAGE_MIGRATION_STATE_ERROR"
+ _RBD_IMAGE_MIGRATION_STATE_PREPARING "RBD_IMAGE_MIGRATION_STATE_PREPARING"
+ _RBD_IMAGE_MIGRATION_STATE_PREPARED "RBD_IMAGE_MIGRATION_STATE_PREPARED"
+ _RBD_IMAGE_MIGRATION_STATE_EXECUTING "RBD_IMAGE_MIGRATION_STATE_EXECUTING"
+ _RBD_IMAGE_MIGRATION_STATE_EXECUTED "RBD_IMAGE_MIGRATION_STATE_EXECUTED"
+ _RBD_IMAGE_MIGRATION_STATE_ABORTING "RBD_IMAGE_MIGRATION_STATE_ABORTING"
+
+ ctypedef struct rbd_image_migration_status_t:
+ int64_t source_pool_id
+ char *source_pool_namespace
+ char *source_image_name
+ char *source_image_id
+ int64_t dest_pool_id
+ char *dest_pool_namespace
+ char *dest_image_name
+ char *dest_image_id
+ rbd_image_migration_state_t state
+ char *state_description
+
+ ctypedef enum rbd_config_source_t:
+ _RBD_CONFIG_SOURCE_CONFIG "RBD_CONFIG_SOURCE_CONFIG"
+ _RBD_CONFIG_SOURCE_POOL "RBD_CONFIG_SOURCE_POOL"
+ _RBD_CONFIG_SOURCE_IMAGE "RBD_CONFIG_SOURCE_IMAGE"
+
+ ctypedef struct rbd_config_option_t:
+ char *name
+ char *value
+ rbd_config_source_t source
+
+ ctypedef enum rbd_pool_stat_option_t:
+ _RBD_POOL_STAT_OPTION_IMAGES "RBD_POOL_STAT_OPTION_IMAGES"
+ _RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES"
+ _RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES"
+ _RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS "RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS"
+ _RBD_POOL_STAT_OPTION_TRASH_IMAGES "RBD_POOL_STAT_OPTION_TRASH_IMAGES"
+ _RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES"
+ _RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES "RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES"
+ _RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS "RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS"
+
+ ctypedef void (*rbd_callback_t)(rbd_completion_t cb, void *arg)
+
+ void rbd_version(int *major, int *minor, int *extra)
+
+ void rbd_image_spec_list_cleanup(rbd_image_spec_t *image, size_t num_images)
+ void rbd_linked_image_spec_cleanup(rbd_linked_image_spec_t *image)
+ void rbd_linked_image_spec_list_cleanup(rbd_linked_image_spec_t *images,
+ size_t num_images)
+ void rbd_snap_spec_cleanup(rbd_snap_spec_t *snap)
+
+ void rbd_image_options_create(rbd_image_options_t* opts)
+ void rbd_image_options_destroy(rbd_image_options_t opts)
+ int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
+ const char* optval)
+ int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
+ uint64_t optval)
+ int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
+ char* optval, size_t maxlen)
+ int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
+ uint64_t* optval)
+ int rbd_image_options_unset(rbd_image_options_t opts, int optname)
+ void rbd_image_options_clear(rbd_image_options_t opts)
+ int rbd_image_options_is_empty(rbd_image_options_t opts)
+
+ int rbd_list(rados_ioctx_t io, char *names, size_t *size)
+ int rbd_list2(rados_ioctx_t io, rbd_image_spec_t *images,
+ size_t *num_images)
+ int rbd_create(rados_ioctx_t io, const char *name, uint64_t size,
+ int *order)
+ int rbd_create4(rados_ioctx_t io, const char *name, uint64_t size,
+ rbd_image_options_t opts)
+ int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
+ const char *p_snapname, rados_ioctx_t c_ioctx,
+ const char *c_name, rbd_image_options_t c_opts)
+ int rbd_remove_with_progress(rados_ioctx_t io, const char *name,
+ librbd_progress_fn_t cb, void *cbdata)
+ int rbd_rename(rados_ioctx_t src_io_ctx, const char *srcname,
+ const char *destname)
+
+ int rbd_trash_move(rados_ioctx_t io, const char *name, uint64_t delay)
+ int rbd_trash_get(rados_ioctx_t io, const char *id,
+ rbd_trash_image_info_t *info)
+ void rbd_trash_get_cleanup(rbd_trash_image_info_t *info)
+ int rbd_trash_list(rados_ioctx_t io, rbd_trash_image_info_t *trash_entries,
+ size_t *num_entries)
+ void rbd_trash_list_cleanup(rbd_trash_image_info_t *trash_entries,
+ size_t num_entries)
+ int rbd_trash_purge(rados_ioctx_t io, time_t expire_ts, float threshold)
+ int rbd_trash_remove_with_progress(rados_ioctx_t io, const char *id,
+ int force, librbd_progress_fn_t cb,
+ void *cbdata)
+ int rbd_trash_restore(rados_ioctx_t io, const char *id, const char *name)
+
+ int rbd_migration_prepare(rados_ioctx_t io_ctx, const char *image_name,
+ rados_ioctx_t dest_io_ctx,
+ const char *dest_image_name,
+ rbd_image_options_t opts)
+ int rbd_migration_execute_with_progress(rados_ioctx_t io_ctx,
+ const char *image_name,
+ librbd_progress_fn_t cb,
+ void *cbdata)
+ int rbd_migration_commit_with_progress(rados_ioctx_t io_ctx,
+ const char *image_name,
+ librbd_progress_fn_t cb,
+ void *cbdata)
+ int rbd_migration_abort_with_progress(rados_ioctx_t io_ctx,
+ const char *image_name,
+ librbd_progress_fn_t cb, void *cbdata)
+ int rbd_migration_status(rados_ioctx_t io_ctx, const char *image_name,
+ rbd_image_migration_status_t *status,
+ size_t status_size)
+ void rbd_migration_status_cleanup(rbd_image_migration_status_t *status)
+
+ int rbd_mirror_site_name_get(rados_t cluster, char *name, size_t *max_len)
+ int rbd_mirror_site_name_set(rados_t cluster, const char *name)
+
+ int rbd_mirror_mode_get(rados_ioctx_t io, rbd_mirror_mode_t *mirror_mode)
+ int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode)
+
+ int rbd_mirror_peer_bootstrap_create(rados_ioctx_t io_ctx, char *token,
+ size_t *max_len)
+ int rbd_mirror_peer_bootstrap_import(
+ rados_ioctx_t io_ctx, rbd_mirror_peer_direction_t direction,
+ const char *token)
+
+ int rbd_mirror_peer_add(rados_ioctx_t io, char *uuid,
+ size_t uuid_max_length, const char *cluster_name,
+ const char *client_name)
+ int rbd_mirror_peer_remove(rados_ioctx_t io, const char *uuid)
+ int rbd_mirror_peer_list(rados_ioctx_t io_ctx, rbd_mirror_peer_t *peers,
+ int *max_peers)
+ void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers, int max_peers)
+ int rbd_mirror_peer_set_client(rados_ioctx_t io, const char *uuid,
+ const char *client_name)
+ int rbd_mirror_peer_set_cluster(rados_ioctx_t io_ctx, const char *uuid,
+ const char *cluster_name)
+ int rbd_mirror_peer_get_attributes(rados_ioctx_t io_ctx, const char *uuid,
+ char *keys, size_t *max_key_len,
+ char *values, size_t *max_val_length,
+ size_t *key_value_count)
+ int rbd_mirror_peer_set_attributes(rados_ioctx_t io_ctx, const char *uuid,
+ const char *keys, const char *values,
+ size_t count)
+
+ int rbd_mirror_image_status_list(rados_ioctx_t io, const char *start_id,
+ size_t max, char **image_ids,
+ rbd_mirror_image_status_t *images,
+ size_t *len)
+ void rbd_mirror_image_status_list_cleanup(char **image_ids,
+ rbd_mirror_image_status_t *images,
+ size_t len)
+ int rbd_mirror_image_status_summary(rados_ioctx_t io,
+ rbd_mirror_image_status_state_t *states,
+ int *counts, size_t *maxlen)
+ int rbd_mirror_image_instance_id_list(rados_ioctx_t io_ctx,
+ const char *start_id,
+ size_t max, char **image_ids,
+ char **instance_ids,
+ size_t *len)
+ void rbd_mirror_image_instance_id_list_cleanup(char **image_ids,
+ char **instance_ids,
+ size_t len)
+
+ int rbd_pool_metadata_get(rados_ioctx_t io_ctx, const char *key,
+ char *value, size_t *val_len)
+ int rbd_pool_metadata_set(rados_ioctx_t io_ctx, const char *key,
+ const char *value)
+ int rbd_pool_metadata_remove(rados_ioctx_t io_ctx, const char *key)
+ int rbd_pool_metadata_list(rados_ioctx_t io_ctx, const char *start,
+ uint64_t max, char *keys, size_t *key_len,
+ char *values, size_t *vals_len)
+
+ int rbd_config_pool_list(rados_ioctx_t io_ctx, rbd_config_option_t *options,
+ int *max_options)
+ void rbd_config_pool_list_cleanup(rbd_config_option_t *options,
+ int max_options)
+
+ int rbd_open(rados_ioctx_t io, const char *name,
+ rbd_image_t *image, const char *snap_name)
+ int rbd_open_by_id(rados_ioctx_t io, const char *image_id,
+ rbd_image_t *image, const char *snap_name)
+ int rbd_open_read_only(rados_ioctx_t io, const char *name,
+ rbd_image_t *image, const char *snap_name)
+ int rbd_open_by_id_read_only(rados_ioctx_t io, const char *image_id,
+ rbd_image_t *image, const char *snap_name)
+ int rbd_close(rbd_image_t image)
+ int rbd_resize2(rbd_image_t image, uint64_t size, bint allow_shrink,
+ librbd_progress_fn_t cb, void *cbdata)
+ int rbd_stat(rbd_image_t image, rbd_image_info_t *info, size_t infosize)
+ int rbd_get_old_format(rbd_image_t image, uint8_t *old)
+ int rbd_get_size(rbd_image_t image, uint64_t *size)
+ int rbd_get_features(rbd_image_t image, uint64_t *features)
+ int rbd_update_features(rbd_image_t image, uint64_t features,
+ uint8_t enabled)
+ int rbd_get_op_features(rbd_image_t image, uint64_t *op_features)
+ int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
+ int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
+ int rbd_get_create_timestamp(rbd_image_t image, timespec *timestamp)
+ int rbd_get_access_timestamp(rbd_image_t image, timespec *timestamp)
+ int rbd_get_modify_timestamp(rbd_image_t image, timespec *timestamp)
+ int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
+ int rbd_get_name(rbd_image_t image, char *name, size_t *name_len)
+ int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
+ int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
+ size_t prefix_len)
+ int64_t rbd_get_data_pool_id(rbd_image_t image)
+ int rbd_get_parent(rbd_image_t image,
+ rbd_linked_image_spec_t *parent_image,
+ rbd_snap_spec_t *parent_snap)
+ int rbd_get_flags(rbd_image_t image, uint64_t *flags)
+ int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
+ size_t group_info_size)
+
+ ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len,
+ char *buf, int op_flags)
+ ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len,
+ const char *buf, int op_flags)
+ int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
+ int rbd_write_zeroes(rbd_image_t image, uint64_t ofs, uint64_t len,
+ int zero_flags, int op_flags)
+ int rbd_copy3(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+ const char *destname, rbd_image_options_t dest_opts)
+ int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+ const char *destname, rbd_image_options_t dest_opts)
+ int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
+ int *max_snaps)
+ void rbd_snap_list_end(rbd_snap_info_t *snaps)
+ int rbd_snap_create(rbd_image_t image, const char *snapname)
+ int rbd_snap_remove(rbd_image_t image, const char *snapname)
+ int rbd_snap_remove2(rbd_image_t image, const char *snapname, uint32_t flags,
+ librbd_progress_fn_t cb, void *cbdata)
+ int rbd_snap_remove_by_id(rbd_image_t image, uint64_t snap_id)
+ int rbd_snap_rollback(rbd_image_t image, const char *snapname)
+ int rbd_snap_rename(rbd_image_t image, const char *snapname,
+ const char* dstsnapsname)
+ int rbd_snap_protect(rbd_image_t image, const char *snap_name)
+ int rbd_snap_unprotect(rbd_image_t image, const char *snap_name)
+ int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
+ int *is_protected)
+ int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit)
+ int rbd_snap_set_limit(rbd_image_t image, uint64_t limit)
+ int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, timespec *timestamp)
+ int rbd_snap_set(rbd_image_t image, const char *snapname)
+ int rbd_snap_set_by_id(rbd_image_t image, uint64_t snap_id)
+ int rbd_snap_get_namespace_type(rbd_image_t image,
+ uint64_t snap_id,
+ rbd_snap_namespace_type_t *namespace_type)
+ int rbd_snap_get_group_namespace(rbd_image_t image, uint64_t snap_id,
+ rbd_snap_group_namespace_t *group_info,
+ size_t snap_group_namespace_size)
+ void rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_spec,
+ size_t snap_group_namespace_size)
+ int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
+ char *original_name, size_t max_length)
+
+ int rbd_flatten_with_progress(rbd_image_t image, librbd_progress_fn_t cb,
+ void *cbdata)
+ int rbd_sparsify(rbd_image_t image, size_t sparse_size)
+ int rbd_rebuild_object_map(rbd_image_t image, librbd_progress_fn_t cb,
+ void *cbdata)
+ int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *children,
+ size_t *max_children)
+ int rbd_list_descendants(rbd_image_t image,
+ rbd_linked_image_spec_t *descendants,
+ size_t *max_descendants)
+
+ ssize_t rbd_list_lockers(rbd_image_t image, int *exclusive,
+ char *tag, size_t *tag_len,
+ char *clients, size_t *clients_len,
+ char *cookies, size_t *cookies_len,
+ char *addrs, size_t *addrs_len)
+ int rbd_lock_exclusive(rbd_image_t image, const char *cookie)
+ int rbd_lock_shared(rbd_image_t image, const char *cookie,
+ const char *tag)
+ int rbd_unlock(rbd_image_t image, const char *cookie)
+ int rbd_break_lock(rbd_image_t image, const char *client,
+ const char *cookie)
+
+ int rbd_is_exclusive_lock_owner(rbd_image_t image, int *is_owner)
+ int rbd_lock_acquire(rbd_image_t image, rbd_lock_mode_t lock_mode)
+ int rbd_lock_release(rbd_image_t image)
+ int rbd_lock_get_owners(rbd_image_t image, rbd_lock_mode_t *lock_mode,
+ char **lock_owners, size_t *max_lock_owners)
+ void rbd_lock_get_owners_cleanup(char **lock_owners,
+ size_t lock_owner_count)
+ int rbd_lock_break(rbd_image_t image, rbd_lock_mode_t lock_mode,
+ char *lock_owner)
+
+ # We use -9000 to propagate Python exceptions. We use except? to make sure
+ # things still work as intended if -9000 happens to be a valid errno value
+ # somewhere.
+ int rbd_diff_iterate2(rbd_image_t image, const char *fromsnapname,
+ uint64_t ofs, uint64_t len,
+ uint8_t include_parent, uint8_t whole_object,
+ int (*cb)(uint64_t, size_t, int, void *)
+ nogil except? -9000,
+ void *arg) except? -9000
+
+ int rbd_flush(rbd_image_t image)
+ int rbd_invalidate_cache(rbd_image_t image)
+
+ int rbd_mirror_image_enable(rbd_image_t image)
+ int rbd_mirror_image_disable(rbd_image_t image, bint force)
+ int rbd_mirror_image_promote(rbd_image_t image, bint force)
+ int rbd_mirror_image_demote(rbd_image_t image)
+ int rbd_mirror_image_resync(rbd_image_t image)
+ int rbd_mirror_image_get_info(rbd_image_t image,
+ rbd_mirror_image_info_t *mirror_image_info,
+ size_t info_size)
+ int rbd_mirror_image_get_status(rbd_image_t image,
+ rbd_mirror_image_status_t *mirror_image_status,
+ size_t status_size)
+ int rbd_mirror_image_get_instance_id(rbd_image_t image, char *instance_id,
+ size_t *id_max_length)
+
+ int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
+ const char *buf, rbd_completion_t c, int op_flags)
+ int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
+ char *buf, rbd_completion_t c, int op_flags)
+ int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
+ rbd_completion_t c)
+ int rbd_aio_write_zeroes(rbd_image_t image, uint64_t off, uint64_t len,
+ rbd_completion_t c, int zero_flags, int op_flags)
+
+ int rbd_aio_create_completion(void *cb_arg, rbd_callback_t complete_cb,
+ rbd_completion_t *c)
+ int rbd_aio_is_complete(rbd_completion_t c)
+ int rbd_aio_wait_for_complete(rbd_completion_t c)
+ ssize_t rbd_aio_get_return_value(rbd_completion_t c)
+ void rbd_aio_release(rbd_completion_t c)
+ int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
+
+ int rbd_metadata_get(rbd_image_t image, const char *key, char *value,
+ size_t *val_len)
+ int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
+ int rbd_metadata_remove(rbd_image_t image, const char *key)
+ int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
+ char *keys, size_t *key_len, char *values,
+ size_t *vals_len)
+ int rbd_group_create(rados_ioctx_t p, const char *name)
+ int rbd_group_remove(rados_ioctx_t p, const char *name)
+ int rbd_group_list(rados_ioctx_t p, char *names, size_t *size)
+ int rbd_group_rename(rados_ioctx_t p, const char *src, const char *dest)
+ void rbd_group_info_cleanup(rbd_group_info_t *group_info,
+ size_t group_info_size)
+ int rbd_group_image_add(rados_ioctx_t group_p, const char *group_name,
+ rados_ioctx_t image_p, const char *image_name)
+ int rbd_group_image_remove(rados_ioctx_t group_p, const char *group_name,
+ rados_ioctx_t image_p, const char *image_name)
+
+ int rbd_group_image_list(rados_ioctx_t group_p,
+ const char *group_name,
+ rbd_group_image_info_t *images,
+ size_t group_image_info_size,
+ size_t *image_size)
+ void rbd_group_image_list_cleanup(rbd_group_image_info_t *images,
+ size_t group_image_info_size, size_t len)
+
+ int rbd_group_snap_create(rados_ioctx_t group_p, const char *group_name,
+ const char *snap_name)
+
+ int rbd_group_snap_remove(rados_ioctx_t group_p, const char *group_name,
+ const char *snap_name)
+
+ int rbd_group_snap_rename(rados_ioctx_t group_p, const char *group_name,
+ const char *old_snap_name,
+ const char *new_snap_name)
+
+ int rbd_group_snap_list(rados_ioctx_t group_p,
+ const char *group_name,
+ rbd_group_snap_info_t *snaps,
+ size_t group_snap_info_size,
+ size_t *snaps_size)
+
+ void rbd_group_snap_list_cleanup(rbd_group_snap_info_t *snaps,
+ size_t group_snap_info_size, size_t len)
+ int rbd_group_snap_rollback(rados_ioctx_t group_p, const char *group_name,
+ const char *snap_name)
+
+ int rbd_watchers_list(rbd_image_t image, rbd_image_watcher_t *watchers,
+ size_t *max_watchers)
+ void rbd_watchers_list_cleanup(rbd_image_watcher_t *watchers,
+ size_t num_watchers)
+
+ int rbd_config_image_list(rbd_image_t image, rbd_config_option_t *options,
+ int *max_options)
+ void rbd_config_image_list_cleanup(rbd_config_option_t *options,
+ int max_options)
+
+ int rbd_namespace_create(rados_ioctx_t io, const char *namespace_name)
+ int rbd_namespace_remove(rados_ioctx_t io, const char *namespace_name)
+ int rbd_namespace_list(rados_ioctx_t io, char *namespace_names,
+ size_t *size)
+ int rbd_namespace_exists(rados_ioctx_t io, const char *namespace_name,
+ bint *exists)
+
+ int rbd_pool_init(rados_ioctx_t, bint force)
+
+ void rbd_pool_stats_create(rbd_pool_stats_t *stats)
+ void rbd_pool_stats_destroy(rbd_pool_stats_t stats)
+ int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
+ int stat_option, uint64_t* stat_val)
+ int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats)
+
+ECANCELED = _ECANCELED
+
+RBD_FEATURE_LAYERING = _RBD_FEATURE_LAYERING
+RBD_FEATURE_STRIPINGV2 = _RBD_FEATURE_STRIPINGV2
+RBD_FEATURE_EXCLUSIVE_LOCK = _RBD_FEATURE_EXCLUSIVE_LOCK
+RBD_FEATURE_OBJECT_MAP = _RBD_FEATURE_OBJECT_MAP
+RBD_FEATURE_FAST_DIFF = _RBD_FEATURE_FAST_DIFF
+RBD_FEATURE_DEEP_FLATTEN = _RBD_FEATURE_DEEP_FLATTEN
+RBD_FEATURE_JOURNALING = _RBD_FEATURE_JOURNALING
+RBD_FEATURE_DATA_POOL = _RBD_FEATURE_DATA_POOL
+RBD_FEATURE_OPERATIONS = _RBD_FEATURE_OPERATIONS
+RBD_FEATURE_MIGRATING = _RBD_FEATURE_MIGRATING
+
+RBD_FEATURES_INCOMPATIBLE = _RBD_FEATURES_INCOMPATIBLE
+RBD_FEATURES_RW_INCOMPATIBLE = _RBD_FEATURES_RW_INCOMPATIBLE
+RBD_FEATURES_MUTABLE = _RBD_FEATURES_MUTABLE
+RBD_FEATURES_SINGLE_CLIENT = _RBD_FEATURES_SINGLE_CLIENT
+RBD_FEATURES_ALL = _RBD_FEATURES_ALL
+
+RBD_OPERATION_FEATURE_CLONE_PARENT = _RBD_OPERATION_FEATURE_CLONE_PARENT
+RBD_OPERATION_FEATURE_CLONE_CHILD = _RBD_OPERATION_FEATURE_CLONE_CHILD
+RBD_OPERATION_FEATURE_GROUP = _RBD_OPERATION_FEATURE_GROUP
+RBD_OPERATION_FEATURE_SNAP_TRASH = _RBD_OPERATION_FEATURE_SNAP_TRASH
+
+RBD_FLAG_OBJECT_MAP_INVALID = _RBD_FLAG_OBJECT_MAP_INVALID
+RBD_FLAG_FAST_DIFF_INVALID = _RBD_FLAG_FAST_DIFF_INVALID
+
+RBD_MIRROR_MODE_DISABLED = _RBD_MIRROR_MODE_DISABLED
+RBD_MIRROR_MODE_IMAGE = _RBD_MIRROR_MODE_IMAGE
+RBD_MIRROR_MODE_POOL = _RBD_MIRROR_MODE_POOL
+
+RBD_MIRROR_PEER_DIRECTION_RX = _RBD_MIRROR_PEER_DIRECTION_RX
+RBD_MIRROR_PEER_DIRECTION_TX = _RBD_MIRROR_PEER_DIRECTION_TX
+RBD_MIRROR_PEER_DIRECTION_RX_TX = _RBD_MIRROR_PEER_DIRECTION_RX_TX
+
+RBD_MIRROR_IMAGE_DISABLING = _RBD_MIRROR_IMAGE_DISABLING
+RBD_MIRROR_IMAGE_ENABLED = _RBD_MIRROR_IMAGE_ENABLED
+RBD_MIRROR_IMAGE_DISABLED = _RBD_MIRROR_IMAGE_DISABLED
+
+MIRROR_IMAGE_STATUS_STATE_UNKNOWN = _MIRROR_IMAGE_STATUS_STATE_UNKNOWN
+MIRROR_IMAGE_STATUS_STATE_ERROR = _MIRROR_IMAGE_STATUS_STATE_ERROR
+MIRROR_IMAGE_STATUS_STATE_SYNCING = _MIRROR_IMAGE_STATUS_STATE_SYNCING
+MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY = _MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY
+MIRROR_IMAGE_STATUS_STATE_REPLAYING = _MIRROR_IMAGE_STATUS_STATE_REPLAYING
+MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY = _MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY
+MIRROR_IMAGE_STATUS_STATE_STOPPED = _MIRROR_IMAGE_STATUS_STATE_STOPPED
+
+RBD_LOCK_MODE_EXCLUSIVE = _RBD_LOCK_MODE_EXCLUSIVE
+RBD_LOCK_MODE_SHARED = _RBD_LOCK_MODE_SHARED
+
+RBD_IMAGE_OPTION_FORMAT = _RBD_IMAGE_OPTION_FORMAT
+RBD_IMAGE_OPTION_FEATURES = _RBD_IMAGE_OPTION_FEATURES
+RBD_IMAGE_OPTION_ORDER = _RBD_IMAGE_OPTION_ORDER
+RBD_IMAGE_OPTION_STRIPE_UNIT = _RBD_IMAGE_OPTION_STRIPE_UNIT
+RBD_IMAGE_OPTION_STRIPE_COUNT = _RBD_IMAGE_OPTION_STRIPE_COUNT
+RBD_IMAGE_OPTION_DATA_POOL = _RBD_IMAGE_OPTION_DATA_POOL
+
+RBD_SNAP_NAMESPACE_TYPE_USER = _RBD_SNAP_NAMESPACE_TYPE_USER
+RBD_SNAP_NAMESPACE_TYPE_GROUP = _RBD_SNAP_NAMESPACE_TYPE_GROUP
+RBD_SNAP_NAMESPACE_TYPE_TRASH = _RBD_SNAP_NAMESPACE_TYPE_TRASH
+
+RBD_GROUP_IMAGE_STATE_ATTACHED = _RBD_GROUP_IMAGE_STATE_ATTACHED
+RBD_GROUP_IMAGE_STATE_INCOMPLETE = _RBD_GROUP_IMAGE_STATE_INCOMPLETE
+
+RBD_GROUP_SNAP_STATE_INCOMPLETE = _RBD_GROUP_SNAP_STATE_INCOMPLETE
+RBD_GROUP_SNAP_STATE_COMPLETE = _RBD_GROUP_SNAP_STATE_COMPLETE
+
+RBD_IMAGE_MIGRATION_STATE_UNKNOWN = _RBD_IMAGE_MIGRATION_STATE_UNKNOWN
+RBD_IMAGE_MIGRATION_STATE_ERROR = _RBD_IMAGE_MIGRATION_STATE_ERROR
+RBD_IMAGE_MIGRATION_STATE_PREPARING = _RBD_IMAGE_MIGRATION_STATE_PREPARING
+RBD_IMAGE_MIGRATION_STATE_PREPARED = _RBD_IMAGE_MIGRATION_STATE_PREPARED
+RBD_IMAGE_MIGRATION_STATE_EXECUTING = _RBD_IMAGE_MIGRATION_STATE_EXECUTING
+RBD_IMAGE_MIGRATION_STATE_EXECUTED = _RBD_IMAGE_MIGRATION_STATE_EXECUTED
+RBD_IMAGE_MIGRATION_STATE_ABORTING = _RBD_IMAGE_MIGRATION_STATE_ABORTING
+
+RBD_CONFIG_SOURCE_CONFIG = _RBD_CONFIG_SOURCE_CONFIG
+RBD_CONFIG_SOURCE_POOL = _RBD_CONFIG_SOURCE_POOL
+RBD_CONFIG_SOURCE_IMAGE = _RBD_CONFIG_SOURCE_IMAGE
+
+RBD_POOL_STAT_OPTION_IMAGES = _RBD_POOL_STAT_OPTION_IMAGES
+RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES
+RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES
+RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS = _RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS
+RBD_POOL_STAT_OPTION_TRASH_IMAGES = _RBD_POOL_STAT_OPTION_TRASH_IMAGES
+RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES
+RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES = _RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES
+RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS = _RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS
+
+
+class Error(Exception):
+ pass
+
+
+class OSError(Error):
+ """ `OSError` class, derived from `Error` """
+ def __init__(self, message, errno=None):
+ super(OSError, self).__init__(message)
+ self.errno = errno
+
+ def __str__(self):
+ msg = super(OSError, self).__str__()
+ if self.errno is None:
+ return msg
+ return '[errno {0}] {1}'.format(self.errno, msg)
+
+ def __reduce__(self):
+ return (self.__class__, (self.message, self.errno))
+
+class PermissionError(OSError):
+ pass
+
+
+class ImageNotFound(OSError):
+ pass
+
+class ObjectNotFound(OSError):
+ pass
+
+class ImageExists(OSError):
+ pass
+
+class ObjectExists(OSError):
+ pass
+
+
+class IOError(OSError):
+ pass
+
+
+class NoSpace(OSError):
+ pass
+
+
+class IncompleteWriteError(OSError):
+ pass
+
+
+class InvalidArgument(OSError):
+ pass
+
+
+class LogicError(Error):
+ pass
+
+
+class ReadOnlyImage(OSError):
+ pass
+
+
+class ImageBusy(OSError):
+ pass
+
+
+class ImageHasSnapshots(OSError):
+ pass
+
+
+class FunctionNotSupported(OSError):
+ pass
+
+
+class ArgumentOutOfRange(OSError):
+ pass
+
+
+class ConnectionShutdown(OSError):
+ pass
+
+
+class Timeout(OSError):
+ pass
+
+class DiskQuotaExceeded(OSError):
+ pass
+
+class OperationNotSupported(OSError):
+ def __init__(self, message, errno=None):
+ super(OperationNotSupported, self).__init__(
+ "RBD operation not supported (%s)" % message, errno)
+
+class OperationCanceled(OSError):
+ def __init__(self, message, errno=None):
+ super(OperationCanceled, self).__init__(
+ "RBD operation canceled (%s)" % message, errno)
+
+cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ImageNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ImageExists,
+ errno.EINVAL : InvalidArgument,
+ errno.EROFS : ReadOnlyImage,
+ errno.EBUSY : ImageBusy,
+ errno.ENOTEMPTY : ImageHasSnapshots,
+ errno.ENOSYS : FunctionNotSupported,
+ errno.EDOM : ArgumentOutOfRange,
+ errno.ESHUTDOWN : ConnectionShutdown,
+ errno.ETIMEDOUT : Timeout,
+ errno.EDQUOT : DiskQuotaExceeded,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ ECANCELED : OperationCanceled,
+}
+
+cdef group_errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.EINVAL : InvalidArgument,
+ errno.EROFS : ReadOnlyImage,
+ errno.EBUSY : ImageBusy,
+ errno.ENOTEMPTY : ImageHasSnapshots,
+ errno.ENOSYS : FunctionNotSupported,
+ errno.EDOM : ArgumentOutOfRange,
+ errno.ESHUTDOWN : ConnectionShutdown,
+ errno.ETIMEDOUT : Timeout,
+ errno.EDQUOT : DiskQuotaExceeded,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ ECANCELED : OperationCanceled,
+}
+
+cdef make_ex(ret, msg, exception_map=errno_to_exception):
+ """
+ Translate a librbd return code into an exception.
+
+ :param ret: the return code
+ :type ret: int
+ :param msg: the error message to use
+ :type msg: str
+ :returns: a subclass of :class:`Error`
+ """
+ ret = abs(ret)
+ if ret in exception_map:
+ return exception_map[ret](msg, errno=ret)
+ else:
+ return OSError(msg, errno=ret)
+
+
+cdef rados_t convert_rados(rados.Rados rados) except? NULL:
+ return <rados_t>rados.cluster
+
+cdef rados_ioctx_t convert_ioctx(rados.Ioctx ioctx) except? NULL:
+ return <rados_ioctx_t>ioctx.io
+
+cdef int progress_callback(uint64_t offset, uint64_t total, void* ptr) with gil:
+ return (<object>ptr)(offset, total)
+
+cdef int no_op_progress_callback(uint64_t offset, uint64_t total, void* ptr):
+ return 0
+
+def cstr(val, name, encoding="utf-8", opt=False):
+ """
+ Create a byte string from a Python string
+
+ :param basestring val: Python string
+ :param str name: Name of the string parameter, for exceptions
+ :param str encoding: Encoding to use
+ :param bool opt: If True, None is allowed
+ :rtype: bytes
+ :raises: :class:`InvalidArgument`
+ """
+ if opt and val is None:
+ return None
+ if isinstance(val, bytes):
+ return val
+ elif isinstance(val, str):
+ return val.encode(encoding)
+ elif sys.version_info < (3, 0) and isinstance(val, unicode):
+ return val.encode(encoding)
+ else:
+ raise InvalidArgument('%s must be a string' % name)
+
+def decode_cstr(val, encoding="utf-8"):
+ """
+ Decode a byte string into a Python string.
+
+ :param bytes val: byte string
+ :rtype: unicode or None
+ """
+ if val is None:
+ return None
+
+ return val.decode(encoding)
+
+
+cdef char* opt_str(s) except? NULL:
+ if s is None:
+ return NULL
+ return s
+
+cdef void* realloc_chk(void* ptr, size_t size) except NULL:
+ cdef void *ret = realloc(ptr, size)
+ if ret == NULL:
+ raise MemoryError("realloc failed")
+ return ret
+
+RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST = decode_cstr(_RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST)
+RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY = decode_cstr(_RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY)
+
+cdef class Completion
+
+cdef void __aio_complete_cb(rbd_completion_t completion, void *args) with gil:
+ """
+ Callback to oncomplete() for asynchronous operations
+ """
+ cdef Completion cb = <Completion>args
+ cb._complete()
+
+
+cdef class Completion(object):
+ """completion object"""
+
+ cdef:
+ object image
+ object oncomplete
+ rbd_completion_t rbd_comp
+ PyObject* buf
+ bint persisted
+ object exc_info
+
+ def __cinit__(self, image, object oncomplete):
+ self.oncomplete = oncomplete
+ self.image = image
+ self.persisted = False
+
+ def is_complete(self):
+ """
+ Has an asynchronous operation completed?
+
+ This does not imply that the callback has finished.
+
+ :returns: True if the operation is completed
+ """
+ with nogil:
+ ret = rbd_aio_is_complete(self.rbd_comp)
+ return ret == 1
+
+ def wait_for_complete_and_cb(self):
+ """
+ Wait for an asynchronous operation to complete
+
+ This method waits for the callback to execute, if one was provided.
+ It will also re-raise any exceptions raised by the callback. You
+ should call this to "reap" asynchronous completions and ensure that
+ any exceptions in the callbacks are handled, as an exception internal
+ to this module may have occurred.
+ """
+ with nogil:
+ rbd_aio_wait_for_complete(self.rbd_comp)
+
+ if self.exc_info:
+ raise self.exc_info[0], self.exc_info[1], self.exc_info[2]
+
+ def get_return_value(self):
+ """
+ Get the return value of an asychronous operation
+
+ The return value is set when the operation is complete.
+
+ :returns: int - return value of the operation
+ """
+ with nogil:
+ ret = rbd_aio_get_return_value(self.rbd_comp)
+ return ret
+
+ def __dealloc__(self):
+ """
+ Release a completion
+
+ This is automatically called when the completion object is freed.
+ """
+ ref.Py_XDECREF(self.buf)
+ self.buf = NULL
+ if self.rbd_comp != NULL:
+ with nogil:
+ rbd_aio_release(self.rbd_comp)
+ self.rbd_comp = NULL
+
+ cdef void _complete(self):
+ try:
+ self.__unpersist()
+ if self.oncomplete:
+ self.oncomplete(self)
+ # In the event that something raises an exception during the next 2
+ # lines of code, we will not be able to catch it, and this may result
+ # in the app not noticing a failed callback. However, this should only
+ # happen in extreme circumstances (OOM, etc.). KeyboardInterrupt
+ # should not be a problem because the callback thread from librbd
+ # ought to have SIGINT blocked.
+ except:
+ self.exc_info = sys.exc_info()
+
+ cdef __persist(self):
+ if self.oncomplete is not None and not self.persisted:
+ # Increment our own reference count to make sure the completion
+ # is not freed until the callback is called. The completion is
+ # allowed to be freed if there is no callback.
+ ref.Py_INCREF(self)
+ self.persisted = True
+
+ cdef __unpersist(self):
+ if self.persisted:
+ ref.Py_DECREF(self)
+ self.persisted = False
+
+
+class RBD(object):
+ """
+ This class wraps librbd CRUD functions.
+ """
+ def version(self):
+ """
+ Get the version number of the ``librbd`` C library.
+
+ :returns: a tuple of ``(major, minor, extra)`` components of the
+ librbd version
+ """
+ cdef int major = 0
+ cdef int minor = 0
+ cdef int extra = 0
+ rbd_version(&major, &minor, &extra)
+ return (major, minor, extra)
+
+ def create(self, ioctx, name, size, order=None, old_format=False,
+ features=None, stripe_unit=None, stripe_count=None,
+ data_pool=None):
+ """
+ Create an rbd image.
+
+ :param ioctx: the context in which to create the image
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: what the image is called
+ :type name: str
+ :param size: how big the image is in bytes
+ :type size: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param old_format: whether to create an old-style image that
+ is accessible by old clients, but can't
+ use more advanced features like layering.
+ :type old_format: bool
+ :param features: bitmask of features to enable
+ :type features: int
+ :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :param data_pool: optional separate pool for data blocks
+ :type data_pool: str
+ :raises: :class:`ImageExists`
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ name = cstr(name, 'name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_name = name
+ uint64_t _size = size
+ int _order = 0
+ rbd_image_options_t opts
+ if order is not None:
+ _order = order
+ if old_format:
+ if (features or
+ ((stripe_unit is not None) and stripe_unit != 0) or
+ ((stripe_count is not None) and stripe_count != 0) or
+ data_pool):
+ raise InvalidArgument('format 1 images do not support feature '
+ 'masks, non-default striping, nor data '
+ 'pool')
+ with nogil:
+ ret = rbd_create(_ioctx, _name, _size, &_order)
+ else:
+ rbd_image_options_create(&opts)
+ try:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FORMAT,
+ 1 if old_format else 2)
+ if features is not None:
+ rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_FEATURES,
+ features)
+ if order is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+ _order)
+ if stripe_unit is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+ stripe_unit)
+ if stripe_count is not None:
+ rbd_image_options_set_uint64(opts,
+ RBD_IMAGE_OPTION_STRIPE_COUNT,
+ stripe_count)
+ if data_pool is not None:
+ rbd_image_options_set_string(opts,
+ RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool)
+ with nogil:
+ ret = rbd_create4(_ioctx, _name, _size, opts)
+ finally:
+ rbd_image_options_destroy(opts)
+ if ret < 0:
+ raise make_ex(ret, 'error creating image')
+
+ def clone(self, p_ioctx, p_name, p_snapname, c_ioctx, c_name,
+ features=None, order=None, stripe_unit=None, stripe_count=None,
+ data_pool=None):
+ """
+ Clone a parent rbd snapshot into a COW sparse child.
+
+ :param p_ioctx: the parent context that represents the parent snap
+ :type ioctx: :class:`rados.Ioctx`
+ :param p_name: the parent image name
+ :type name: str
+ :param p_snapname: the parent image snapshot name
+ :type name: str
+ :param c_ioctx: the child context that represents the new clone
+ :type ioctx: :class:`rados.Ioctx`
+ :param c_name: the clone (child) name
+ :type name: str
+ :param features: bitmask of features to enable; if set, must include layering
+ :type features: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :param data_pool: optional separate pool for data blocks
+ :type data_pool: str
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`ImageExists`
+ :raises: :class:`FunctionNotSupported`
+ :raises: :class:`ArgumentOutOfRange`
+ """
+ p_snapname = cstr(p_snapname, 'p_snapname')
+ p_name = cstr(p_name, 'p_name')
+ c_name = cstr(c_name, 'c_name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
+ cdef:
+ rados_ioctx_t _p_ioctx = convert_ioctx(p_ioctx)
+ rados_ioctx_t _c_ioctx = convert_ioctx(c_ioctx)
+ char *_p_name = p_name
+ char *_p_snapname = p_snapname
+ char *_c_name = c_name
+ rbd_image_options_t opts
+
+ rbd_image_options_create(&opts)
+ try:
+ if features is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FEATURES,
+ features)
+ if order is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+ order)
+ if stripe_unit is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+ stripe_unit)
+ if stripe_count is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_COUNT,
+ stripe_count)
+ if data_pool is not None:
+ rbd_image_options_set_string(opts, RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool)
+ with nogil:
+ ret = rbd_clone3(_p_ioctx, _p_name, _p_snapname,
+ _c_ioctx, _c_name, opts)
+ finally:
+ rbd_image_options_destroy(opts)
+ if ret < 0:
+ raise make_ex(ret, 'error creating clone')
+
+ def list(self, ioctx):
+ """
+ List image names.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: list -- a list of image names
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ size_t size = 512
+ char *c_names = NULL
+ try:
+ while True:
+ c_names = <char *>realloc_chk(c_names, size)
+ with nogil:
+ ret = rbd_list(_ioctx, c_names, &size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing images')
+ return [decode_cstr(name) for name in c_names[:ret].split(b'\0')
+ if name]
+ finally:
+ free(c_names)
+
+ def list2(self, ioctx):
+ """
+ Iterate over the images in the pool.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`ImageIterator`
+ """
+ return ImageIterator(ioctx)
+
+ def remove(self, ioctx, name, on_progress=None):
+ """
+ Delete an RBD image. This may take a long time, since it does
+ not return until every object that comprises the image has
+ been deleted. Note that all snapshots must be deleted before
+ the image can be removed. If there are snapshots left,
+ :class:`ImageHasSnapshots` is raised. If the image is still
+ open, or the watch from a crashed client has not expired,
+ :class:`ImageBusy` is raised.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image to remove
+ :type name: str
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ :raises: :class:`ImageNotFound`, :class:`ImageBusy`,
+ :class:`ImageHasSnapshots`
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_name = name
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_remove_with_progress(_ioctx, _name, _prog_cb, _prog_arg)
+ if ret != 0:
+ raise make_ex(ret, 'error removing image')
+
+ def rename(self, ioctx, src, dest):
+ """
+ Rename an RBD image.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param src: the current name of the image
+ :type src: str
+ :param dest: the new name of the image
+ :type dest: str
+ :raises: :class:`ImageNotFound`, :class:`ImageExists`
+ """
+ src = cstr(src, 'src')
+ dest = cstr(dest, 'dest')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_src = src
+ char *_dest = dest
+ with nogil:
+ ret = rbd_rename(_ioctx, _src, _dest)
+ if ret != 0:
+ raise make_ex(ret, 'error renaming image')
+
+ def trash_move(self, ioctx, name, delay=0):
+ """
+ Move an RBD image to the trash.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image to remove
+ :type name: str
+ :param delay: time delay in seconds before the image can be deleted
+ from trash
+ :type delay: int
+ :raises: :class:`ImageNotFound`
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_name = name
+ uint64_t _delay = delay
+ with nogil:
+ ret = rbd_trash_move(_ioctx, _name, _delay)
+ if ret != 0:
+ raise make_ex(ret, 'error moving image to trash')
+
+ def trash_purge(self, ioctx, expire_ts=None, threshold=-1):
+ """
+ Delete RBD images from trash in bulk.
+
+ By default it removes images with deferment end time less than now.
+
+ The timestamp is configurable, e.g. delete images that have expired a
+ week ago.
+
+ If the threshold is used it deletes images until X% pool usage is met.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param expire_ts: timestamp for images to be considered as expired (UTC)
+ :type expire_ts: datetime
+ :param threshold: percentage of pool usage to be met (0 to 1)
+ :type threshold: float
+ """
+ if expire_ts:
+ expire_epoch_ts = time.mktime(expire_ts.timetuple())
+ else:
+ expire_epoch_ts = 0
+
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ time_t _expire_ts = expire_epoch_ts
+ float _threshold = threshold
+ with nogil:
+ ret = rbd_trash_purge(_ioctx, _expire_ts, _threshold)
+ if ret != 0:
+ raise make_ex(ret, 'error purging images from trash')
+
+ def trash_remove(self, ioctx, image_id, force=False, on_progress=None):
+ """
+ Delete an RBD image from trash. If image deferment time has not
+ expired :class:`PermissionError` is raised.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_id: the id of the image to remove
+ :type image_id: str
+ :param force: force remove even if deferment time has not expired
+ :type force: bool
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ :raises: :class:`ImageNotFound`, :class:`PermissionError`
+ """
+ image_id = cstr(image_id, 'image_id')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_id = image_id
+ int _force = force
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_trash_remove_with_progress(_ioctx, _image_id, _force,
+ _prog_cb, _prog_arg)
+ if ret != 0:
+ raise make_ex(ret, 'error deleting image from trash')
+
+ def trash_get(self, ioctx, image_id):
+ """
+ Retrieve RBD image info from trash.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_id: the id of the image to restore
+ :type image_id: str
+ :returns: dict - contains the following keys:
+
+ * ``id`` (str) - image id
+
+ * ``name`` (str) - image name
+
+ * ``source`` (str) - source of deletion
+
+ * ``deletion_time`` (datetime) - time of deletion
+
+ * ``deferment_end_time`` (datetime) - time that an image is allowed
+ to be removed from trash
+
+ :raises: :class:`ImageNotFound`
+ """
+ image_id = cstr(image_id, 'image_id')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_id = image_id
+ rbd_trash_image_info_t c_info
+ with nogil:
+ ret = rbd_trash_get(_ioctx, _image_id, &c_info)
+ if ret != 0:
+ raise make_ex(ret, 'error retrieving image from trash')
+
+ __source_string = ['USER', 'MIRRORING', 'MIGRATION', 'REMOVING']
+ info = {
+ 'id' : decode_cstr(c_info.id),
+ 'name' : decode_cstr(c_info.name),
+ 'source' : __source_string[c_info.source],
+ 'deletion_time' : datetime.utcfromtimestamp(c_info.deletion_time),
+ 'deferment_end_time' : datetime.utcfromtimestamp(c_info.deferment_end_time)
+ }
+ rbd_trash_get_cleanup(&c_info)
+ return info
+
+ def trash_list(self, ioctx):
+ """
+ List all entries from trash.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`TrashIterator`
+ """
+ return TrashIterator(ioctx)
+
+ def trash_restore(self, ioctx, image_id, name):
+ """
+ Restore an RBD image from trash.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_id: the id of the image to restore
+ :type image_id: str
+ :param name: the new name of the restored image
+ :type name: str
+ :raises: :class:`ImageNotFound`
+ """
+ image_id = cstr(image_id, 'image_id')
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_id = image_id
+ char *_name = name
+ with nogil:
+ ret = rbd_trash_restore(_ioctx, _image_id, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error restoring image from trash')
+
+ def migration_prepare(self, ioctx, image_name, dest_ioctx, dest_image_name,
+ features=None, order=None, stripe_unit=None, stripe_count=None,
+ data_pool=None):
+ """
+ Prepare an RBD image migration.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_name: the current name of the image
+ :type src: str
+ :param dest_ioctx: determines which pool to migration into
+ :type dest_ioctx: :class:`rados.Ioctx`
+ :param dest_image_name: the name of the destination image (may be the same image)
+ :type dest_image_name: str
+ :param features: bitmask of features to enable; if set, must include layering
+ :type features: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :param data_pool: optional separate pool for data blocks
+ :type data_pool: str
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`ImageExists`
+ :raises: :class:`FunctionNotSupported`
+ :raises: :class:`ArgumentOutOfRange`
+ """
+ image_name = cstr(image_name, 'image_name')
+ dest_image_name = cstr(dest_image_name, 'dest_image_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_name = image_name
+ rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
+ char *_dest_image_name = dest_image_name
+ rbd_image_options_t opts
+
+ rbd_image_options_create(&opts)
+ try:
+ if features is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FEATURES,
+ features)
+ if order is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+ order)
+ if stripe_unit is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+ stripe_unit)
+ if stripe_count is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_COUNT,
+ stripe_count)
+ if data_pool is not None:
+ rbd_image_options_set_string(opts, RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool)
+ with nogil:
+ ret = rbd_migration_prepare(_ioctx, _image_name, _dest_ioctx,
+ _dest_image_name, opts)
+ finally:
+ rbd_image_options_destroy(opts)
+ if ret < 0:
+ raise make_ex(ret, 'error migrating image %s' % (image_name))
+
+ def migration_execute(self, ioctx, image_name, on_progress=None):
+ """
+ Execute a prepared RBD image migration.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_name: the name of the image
+ :type image_name: str
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ :raises: :class:`ImageNotFound`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_name = image_name
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_migration_execute_with_progress(_ioctx, _image_name,
+ _prog_cb, _prog_arg)
+ if ret != 0:
+ raise make_ex(ret, 'error aborting migration')
+
+ def migration_commit(self, ioctx, image_name, on_progress=None):
+ """
+ Commit an executed RBD image migration.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_name: the name of the image
+ :type image_name: str
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ :raises: :class:`ImageNotFound`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_name = image_name
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_migration_commit_with_progress(_ioctx, _image_name,
+ _prog_cb, _prog_arg)
+ if ret != 0:
+ raise make_ex(ret, 'error aborting migration')
+
+ def migration_abort(self, ioctx, image_name, on_progress=None):
+ """
+ Cancel a previously started but interrupted migration.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_name: the name of the image
+ :type image_name: str
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ :raises: :class:`ImageNotFound`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_name = image_name
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_migration_abort_with_progress(_ioctx, _image_name,
+ _prog_cb, _prog_arg)
+ if ret != 0:
+ raise make_ex(ret, 'error aborting migration')
+
+ def migration_status(self, ioctx, image_name):
+ """
+ Return RBD image migration status.
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param image_name: the name of the image
+ :type image_name: str
+ :returns: dict - contains the following keys:
+
+ * ``source_pool_id`` (int) - source image pool id
+
+ * ``source_pool_namespace`` (str) - source image pool namespace
+
+ * ``source_image_name`` (str) - source image name
+
+ * ``source_image_id`` (str) - source image id
+
+ * ``dest_pool_id`` (int) - destination image pool id
+
+ * ``dest_pool_namespace`` (str) - destination image pool namespace
+
+ * ``dest_image_name`` (str) - destination image name
+
+ * ``dest_image_id`` (str) - destination image id
+
+ * ``state`` (int) - current migration state
+
+ * ``state_description`` (str) - migration state description
+
+ :raises: :class:`ImageNotFound`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_image_name = image_name
+ rbd_image_migration_status_t c_status
+ with nogil:
+ ret = rbd_migration_status(_ioctx, _image_name, &c_status,
+ sizeof(c_status))
+ if ret != 0:
+ raise make_ex(ret, 'error getting migration status')
+
+ status = {
+ 'source_pool_id' : c_status.source_pool_id,
+ 'source_pool_namespace' : decode_cstr(c_status.source_pool_namespace),
+ 'source_image_name' : decode_cstr(c_status.source_image_name),
+ 'source_image_id' : decode_cstr(c_status.source_image_id),
+ 'dest_pool_id' : c_status.source_pool_id,
+ 'dest_pool_namespace' : decode_cstr(c_status.dest_pool_namespace),
+ 'dest_image_name' : decode_cstr(c_status.dest_image_name),
+ 'dest_image_id' : decode_cstr(c_status.dest_image_id),
+ 'state' : c_status.state,
+ 'state_description' : decode_cstr(c_status.state_description)
+ }
+
+ rbd_migration_status_cleanup(&c_status)
+
+ return status
+
+ def mirror_site_name_get(self, rados):
+ """
+ Get the local cluster's friendly site name
+
+ :param rados: cluster connection
+ :type rados: :class: rados.Rados
+ :returns: str - local site name
+ """
+ cdef:
+ rados_t _rados = convert_rados(rados)
+ char *_site_name = NULL
+ size_t _max_size = 512
+ try:
+ while True:
+ _site_name = <char *>realloc_chk(_site_name, _max_size)
+ with nogil:
+ ret = rbd_mirror_site_name_get(_rados, _site_name,
+ &_max_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error getting site name')
+ return decode_cstr(_site_name)
+ finally:
+ free(_site_name)
+
+ def mirror_site_name_set(self, rados, site_name):
+ """
+ Set the local cluster's friendly site name
+
+ :param rados: cluster connection
+ :type rados: :class: rados.Rados
+ :param site_name: friendly site name
+ :type str:
+ """
+ site_name = cstr(site_name, 'site_name')
+ cdef:
+ rados_t _rados = convert_rados(rados)
+ char *_site_name = site_name
+ with nogil:
+ ret = rbd_mirror_site_name_set(_rados, _site_name)
+ if ret != 0:
+ raise make_ex(ret, 'error setting mirror site name')
+
+ def mirror_mode_get(self, ioctx):
+ """
+ Get pool mirror mode.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: int - pool mirror mode
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ rbd_mirror_mode_t mirror_mode
+ with nogil:
+ ret = rbd_mirror_mode_get(_ioctx, &mirror_mode)
+ if ret != 0:
+ raise make_ex(ret, 'error getting mirror mode')
+ return mirror_mode
+
+ def mirror_mode_set(self, ioctx, mirror_mode):
+ """
+ Set pool mirror mode.
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param mirror_mode: mirror mode to set
+ :type mirror_mode: int
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ rbd_mirror_mode_t _mirror_mode = mirror_mode
+ with nogil:
+ ret = rbd_mirror_mode_set(_ioctx, _mirror_mode)
+ if ret != 0:
+ raise make_ex(ret, 'error setting mirror mode')
+
+ def mirror_peer_bootstrap_create(self, ioctx):
+ """
+ Creates a new RBD mirroring bootstrap token for an
+ external cluster.
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: str - bootstrap token
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_token = NULL
+ size_t _max_size = 512
+ try:
+ while True:
+ _token = <char *>realloc_chk(_token, _max_size)
+ with nogil:
+ ret = rbd_mirror_peer_bootstrap_create(_ioctx, _token,
+ &_max_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error creating bootstrap token')
+ return decode_cstr(_token)
+ finally:
+ free(_token)
+
+ def mirror_peer_bootstrap_import(self, ioctx, direction, token):
+ """
+ Import a bootstrap token from an external cluster to
+ auto-configure the mirror peer.
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param direction: mirror peer direction
+ :type direction: int
+ :param token: bootstrap token
+ :type token: str
+ """
+ token = cstr(token, 'token')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ rbd_mirror_peer_direction_t _direction = direction
+ char *_token = token
+ with nogil:
+ ret = rbd_mirror_peer_bootstrap_import(_ioctx, _direction, _token)
+ if ret != 0:
+ raise make_ex(ret, 'error importing bootstrap token')
+
+ def mirror_peer_add(self, ioctx, cluster_name, client_name):
+ """
+ Add mirror peer.
+
+ :param ioctx: determines which RADOS pool is used
+ :type ioctx: :class:`rados.Ioctx`
+ :param cluster_name: mirror peer cluster name
+ :type cluster_name: str
+ :param client_name: mirror peer client name
+ :type client_name: str
+ :returns: str - peer uuid
+ """
+ cluster_name = cstr(cluster_name, 'cluster_name')
+ client_name = cstr(client_name, 'client_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = NULL
+ size_t _uuid_max_length = 512
+ char *_cluster_name = cluster_name
+ char *_client_name = client_name
+ try:
+ _uuid = <char *>realloc_chk(_uuid, _uuid_max_length)
+ ret = rbd_mirror_peer_add(_ioctx, _uuid, _uuid_max_length,
+ _cluster_name, _client_name)
+ if ret != 0:
+ raise make_ex(ret, 'error adding mirror peer')
+ return decode_cstr(_uuid)
+ finally:
+ free(_uuid)
+
+ def mirror_peer_remove(self, ioctx, uuid):
+ """
+ Remove mirror peer.
+
+ :param ioctx: determines which RADOS pool is used
+ :type ioctx: :class:`rados.Ioctx`
+ :param uuid: peer uuid
+ :type uuid: str
+ """
+ uuid = cstr(uuid, 'uuid')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = uuid
+ with nogil:
+ ret = rbd_mirror_peer_remove(_ioctx, _uuid)
+ if ret != 0:
+ raise make_ex(ret, 'error removing mirror peer')
+
+ def mirror_peer_list(self, ioctx):
+ """
+ Iterate over the peers of a pool.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`MirrorPeerIterator`
+ """
+ return MirrorPeerIterator(ioctx)
+
+ def mirror_peer_set_client(self, ioctx, uuid, client_name):
+ """
+ Set mirror peer client name
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param uuid: uuid of the mirror peer
+ :type uuid: str
+ :param client_name: client name of the mirror peer to set
+ :type client_name: str
+ """
+ uuid = cstr(uuid, 'uuid')
+ client_name = cstr(client_name, 'client_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = uuid
+ char *_client_name = client_name
+ with nogil:
+ ret = rbd_mirror_peer_set_client(_ioctx, _uuid, _client_name)
+ if ret != 0:
+ raise make_ex(ret, 'error setting mirror peer client')
+
+ def mirror_peer_set_cluster(self, ioctx, uuid, cluster_name):
+ """
+ Set mirror peer cluster name
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param uuid: uuid of the mirror peer
+ :type uuid: str
+ :param cluster_name: cluster name of the mirror peer to set
+ :type cluster_name: str
+ """
+ uuid = cstr(uuid, 'uuid')
+ cluster_name = cstr(cluster_name, 'cluster_name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = uuid
+ char *_cluster_name = cluster_name
+ with nogil:
+ ret = rbd_mirror_peer_set_cluster(_ioctx, _uuid, _cluster_name)
+ if ret != 0:
+ raise make_ex(ret, 'error setting mirror peer cluster')
+
+ def mirror_peer_get_attributes(self, ioctx, uuid):
+ """
+ Get optional mirror peer attributes
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param uuid: uuid of the mirror peer
+ :type uuid: str
+
+ :returns: dict - contains the following keys:
+
+ * ``mon_host`` (str) - monitor addresses
+
+ * ``key`` (str) - CephX key
+ """
+ uuid = cstr(uuid, 'uuid')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = uuid
+ char *_keys = NULL
+ char *_vals = NULL
+ size_t _keys_size = 512
+ size_t _vals_size = 512
+ size_t _count = 0
+ try:
+ while True:
+ _keys = <char *>realloc_chk(_keys, _keys_size)
+ _vals = <char *>realloc_chk(_vals, _vals_size)
+ with nogil:
+ ret = rbd_mirror_peer_get_attributes(_ioctx, _uuid, _keys,
+ &_keys_size, _vals,
+ &_vals_size, &_count)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error getting mirror peer attributes')
+ keys = [decode_cstr(x) for x in _keys[:_keys_size].split(b'\0')[:-1]]
+ vals = [decode_cstr(x) for x in _vals[:_vals_size].split(b'\0')[:-1]]
+ return dict(zip(keys, vals))
+ finally:
+ free(_keys)
+ free(_vals)
+
+ def mirror_peer_set_attributes(self, ioctx, uuid, attributes):
+ """
+ Set optional mirror peer attributes
+
+ :param ioctx: determines which RADOS pool is written
+ :type ioctx: :class:`rados.Ioctx`
+ :param uuid: uuid of the mirror peer
+ :type uuid: str
+ :param attributes: 'mon_host' and 'key' attributes
+ :type attributes: dict
+ """
+ uuid = cstr(uuid, 'uuid')
+ keys_str = b'\0'.join([cstr(x[0], 'key') for x in attributes.items()])
+ vals_str = b'\0'.join([cstr(x[1], 'val') for x in attributes.items()])
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_uuid = uuid
+ char *_keys = keys_str
+ char *_vals = vals_str
+ size_t _count = len(attributes)
+
+ with nogil:
+ ret = rbd_mirror_peer_set_attributes(_ioctx, _uuid, _keys, _vals,
+ _count)
+ if ret != 0:
+ raise make_ex(ret, 'error setting mirror peer attributes')
+
+ def mirror_image_status_list(self, ioctx):
+ """
+ Iterate over the mirror image statuses of a pool.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`MirrorImageStatusIterator`
+ """
+ return MirrorImageStatusIterator(ioctx)
+
+ def mirror_image_status_summary(self, ioctx):
+ """
+ Get mirror image status summary of a pool.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: list - a list of (state, count) tuples
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ rbd_mirror_image_status_state_t *states = NULL
+ int *counts = NULL
+ size_t maxlen = 32
+ try:
+ states = <rbd_mirror_image_status_state_t *>realloc_chk(states,
+ sizeof(rbd_mirror_image_status_state_t) * maxlen)
+ counts = <int *>realloc_chk(counts, sizeof(int) * maxlen)
+ with nogil:
+ ret = rbd_mirror_image_status_summary(_ioctx, states, counts,
+ &maxlen)
+ if ret < 0:
+ raise make_ex(ret, 'error getting mirror image status summary')
+ return [(states[i], counts[i]) for i in range(maxlen)]
+ finally:
+ free(states)
+ free(counts)
+
+ def mirror_image_instance_id_list(self, ioctx):
+ """
+ Iterate over the mirror image instance ids of a pool.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`MirrorImageInstanceIdIterator`
+ """
+ return MirrorImageInstanceIdIterator(ioctx)
+
+ def pool_metadata_get(self, ioctx, key):
+ """
+ Get pool metadata for the given key.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :param key: metadata key
+ :type key: str
+ :returns: str - metadata value
+ """
+ key = cstr(key, 'key')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_key = key
+ size_t size = 4096
+ char *value = NULL
+ int ret
+ try:
+ while True:
+ value = <char *>realloc_chk(value, size)
+ with nogil:
+ ret = rbd_pool_metadata_get(_ioctx, _key, value, &size)
+ if ret != -errno.ERANGE:
+ break
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s' % (key))
+ if ret != 0:
+ raise make_ex(ret, 'error getting metadata %s' % (key))
+ return decode_cstr(value)
+ finally:
+ free(value)
+
+ def pool_metadata_set(self, ioctx, key, value):
+ """
+ Set pool metadata for the given key.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :param key: metadata key
+ :type key: str
+ :param value: metadata value
+ :type value: str
+ """
+ key = cstr(key, 'key')
+ value = cstr(value, 'value')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_key = key
+ char *_value = value
+ with nogil:
+ ret = rbd_pool_metadata_set(_ioctx, _key, _value)
+
+ if ret != 0:
+ raise make_ex(ret, 'error setting metadata %s' % (key))
+
+ def pool_metadata_remove(self, ioctx, key):
+ """
+ Remove pool metadata for the given key.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :param key: metadata key
+ :type key: str
+ :returns: str - metadata value
+ """
+ key = cstr(key, 'key')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_key = key
+ with nogil:
+ ret = rbd_pool_metadata_remove(_ioctx, _key)
+
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s' % (key))
+ if ret != 0:
+ raise make_ex(ret, 'error removing metadata %s' % (key))
+
+ def pool_metadata_list(self, ioctx):
+ """
+ List pool metadata.
+
+ :returns: :class:`PoolMetadataIterator`
+ """
+ return PoolMetadataIterator(ioctx)
+
+ def config_list(self, ioctx):
+ """
+ List pool-level config overrides.
+
+ :returns: :class:`ConfigPoolIterator`
+ """
+ return ConfigPoolIterator(ioctx)
+
+ def group_create(self, ioctx, name):
+ """
+ Create a group.
+
+ :param ioctx: determines which RADOS pool is used
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the group
+ :type name: str
+ :raises: :class:`ObjectExists`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ name = cstr(name, 'name')
+ cdef:
+ char *_name = name
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ with nogil:
+ ret = rbd_group_create(_ioctx, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error creating group %s' % name, group_errno_to_exception)
+
+ def group_remove(self, ioctx, name):
+ """
+ Delete an RBD group. This may take a long time, since it does
+ not return until every image in the group has been removed
+ from the group.
+
+ :param ioctx: determines which RADOS pool the group is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the group to remove
+ :type name: str
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_name = name
+ with nogil:
+ ret = rbd_group_remove(_ioctx, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error removing group', group_errno_to_exception)
+
+ def group_list(self, ioctx):
+ """
+ List groups.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: list -- a list of groups names
+ :raises: :class:`FunctionNotSupported`
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ size_t size = 512
+ char *c_names = NULL
+ try:
+ while True:
+ c_names = <char *>realloc_chk(c_names, size)
+ with nogil:
+ ret = rbd_group_list(_ioctx, c_names, &size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing groups', group_errno_to_exception)
+ return [decode_cstr(name) for name in c_names[:ret].split(b'\0')
+ if name]
+ finally:
+ free(c_names)
+
+ def group_rename(self, ioctx, src, dest):
+ """
+ Rename an RBD group.
+
+ :param ioctx: determines which RADOS pool the group is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param src: the current name of the group
+ :type src: str
+ :param dest: the new name of the group
+ :type dest: str
+ :raises: :class:`ObjectExists`
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ src = cstr(src, 'src')
+ dest = cstr(dest, 'dest')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_src = src
+ char *_dest = dest
+ with nogil:
+ ret = rbd_group_rename(_ioctx, _src, _dest)
+ if ret != 0:
+ raise make_ex(ret, 'error renaming group')
+
+ def namespace_create(self, ioctx, name):
+ """
+ Create an RBD namespace within a pool
+
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: namespace name
+ :type name: str
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ const char *_name = name
+ with nogil:
+ ret = rbd_namespace_create(_ioctx, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error creating namespace')
+
+ def namespace_remove(self, ioctx, name):
+ """
+ Remove an RBD namespace from a pool
+
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: namespace name
+ :type name: str
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ const char *_name = name
+ with nogil:
+ ret = rbd_namespace_remove(_ioctx, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error removing namespace')
+
+ def namespace_exists(self, ioctx, name):
+ """
+ Verifies if a namespace exists within a pool
+
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: namespace name
+ :type name: str
+ :returns: bool - true if namespace exists
+ """
+ name = cstr(name, 'name')
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ const char *_name = name
+ bint _exists = False
+ with nogil:
+ ret = rbd_namespace_exists(_ioctx, _name, &_exists)
+ if ret != 0:
+ raise make_ex(ret, 'error verifying namespace')
+ return bool(_exists != 0)
+
+ def namespace_list(self, ioctx):
+ """
+ List all namespaces within a pool
+
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: list - collection of namespace names
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_names = NULL
+ size_t _size = 512
+ try:
+ while True:
+ _names = <char *>realloc_chk(_names, _size)
+ with nogil:
+ ret = rbd_namespace_list(_ioctx, _names, &_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing namespaces')
+ return [decode_cstr(name) for name in _names[:_size].split(b'\0')
+ if name]
+ finally:
+ free(_names)
+
+ def pool_init(self, ioctx, force):
+ """
+ Initialize an RBD pool
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :param force: force init
+ :type force: bool
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ bint _force = force
+ with nogil:
+ ret = rbd_pool_init(_ioctx, _force)
+ if ret != 0:
+ raise make_ex(ret, 'error initializing pool')
+
+ def pool_stats_get(self, ioctx):
+ """
+ Return RBD pool stats
+
+ :param ioctx: determines which RADOS pool
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: dict - contains the following keys:
+
+ * ``image_count`` (int) - image count
+
+ * ``image_provisioned_bytes`` (int) - image total HEAD provisioned bytes
+
+ * ``image_max_provisioned_bytes`` (int) - image total max provisioned bytes
+
+ * ``image_snap_count`` (int) - image snap count
+
+ * ``trash_count`` (int) - trash image count
+
+ * ``trash_provisioned_bytes`` (int) - trash total HEAD provisioned bytes
+
+ * ``trash_max_provisioned_bytes`` (int) - trash total max provisioned bytes
+
+ * ``trash_snap_count`` (int) - trash snap count
+
+ """
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ uint64_t _image_count = 0
+ uint64_t _image_provisioned_bytes = 0
+ uint64_t _image_max_provisioned_bytes = 0
+ uint64_t _image_snap_count = 0
+ uint64_t _trash_count = 0
+ uint64_t _trash_provisioned_bytes = 0
+ uint64_t _trash_max_provisioned_bytes = 0
+ uint64_t _trash_snap_count = 0
+ rbd_pool_stats_t _stats
+
+ rbd_pool_stats_create(&_stats)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGES,
+ &_image_count)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES,
+ &_image_provisioned_bytes)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES,
+ &_image_max_provisioned_bytes)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS,
+ &_image_snap_count)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_IMAGES,
+ &_trash_count)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES,
+ &_trash_provisioned_bytes)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES,
+ &_trash_max_provisioned_bytes)
+ rbd_pool_stats_option_add_uint64(_stats, RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS,
+ &_trash_snap_count)
+ try:
+ with nogil:
+ ret = rbd_pool_stats_get(_ioctx, _stats)
+ if ret != 0:
+ raise make_ex(ret, 'error retrieving pool stats')
+ else:
+ return {'image_count': _image_count,
+ 'image_provisioned_bytes': _image_provisioned_bytes,
+ 'image_max_provisioned_bytes': _image_max_provisioned_bytes,
+ 'image_snap_count': _image_snap_count,
+ 'trash_count': _trash_count,
+ 'trash_provisioned_bytes': _trash_provisioned_bytes,
+ 'trash_max_provisioned_bytes': _trash_max_provisioned_bytes,
+ 'trash_snap_count': _trash_snap_count}
+ finally:
+ rbd_pool_stats_destroy(_stats)
+
+
+cdef class MirrorPeerIterator(object):
+ """
+ Iterator over mirror peer info for a pool.
+
+ Yields a dictionary containing information about a peer.
+
+ Keys are:
+
+ * ``uuid`` (str) - uuid of the peer
+
+ * ``cluster_name`` (str) - cluster name of the peer
+
+ * ``client_name`` (str) - client name of the peer
+ """
+
+ cdef:
+ rbd_mirror_peer_t *peers
+ int num_peers
+
+ def __init__(self, ioctx):
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ self.peers = NULL
+ self.num_peers = 10
+ while True:
+ self.peers = <rbd_mirror_peer_t *>realloc_chk(
+ self.peers, self.num_peers * sizeof(rbd_mirror_peer_t))
+ with nogil:
+ ret = rbd_mirror_peer_list(_ioctx, self.peers, &self.num_peers)
+ if ret < 0:
+ if ret == -errno.ERANGE:
+ continue
+ self.num_peers = 0
+ raise make_ex(ret, 'error listing peers')
+ break
+
+ def __iter__(self):
+ for i in range(self.num_peers):
+ yield {
+ 'uuid' : decode_cstr(self.peers[i].uuid),
+ 'cluster_name' : decode_cstr(self.peers[i].cluster_name),
+ 'client_name' : decode_cstr(self.peers[i].client_name),
+ }
+
+ def __dealloc__(self):
+ if self.peers:
+ rbd_mirror_peer_list_cleanup(self.peers, self.num_peers)
+ free(self.peers)
+
+cdef class MirrorImageStatusIterator(object):
+ """
+ Iterator over mirror image status for a pool.
+
+ Yields a dictionary containing mirror status of an image.
+
+ Keys are:
+
+ * ``name`` (str) - mirror image name
+
+ * ``id`` (str) - mirror image id
+
+ * `info` (dict) - mirror image info
+
+ * `state` (int) - mirror state
+
+ * `description` (str) - status description
+
+ * `last_update` (datetime) - last status update time
+
+ * ``up`` (bool) - is mirroring agent up
+ """
+
+ cdef:
+ rados_ioctx_t ioctx
+ size_t max_read
+ char *last_read
+ char **image_ids
+ rbd_mirror_image_status_t *images
+ size_t size
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.max_read = 1024
+ self.last_read = strdup("")
+ self.image_ids = <char **>realloc_chk(NULL,
+ sizeof(char *) * self.max_read)
+ self.images = <rbd_mirror_image_status_t *>realloc_chk(NULL,
+ sizeof(rbd_mirror_image_status_t) * self.max_read)
+ self.size = 0
+ self.get_next_chunk()
+
+ def __iter__(self):
+ while self.size > 0:
+ for i in range(self.size):
+ yield {
+ 'name' : decode_cstr(self.images[i].name),
+ 'id' : decode_cstr(self.image_ids[i]),
+ 'info' : {
+ 'global_id' : decode_cstr(self.images[i].info.global_id),
+ 'state' : self.images[i].info.state,
+ },
+ 'state' : self.images[i].state,
+ 'description' : decode_cstr(self.images[i].description),
+ 'last_update' : datetime.utcfromtimestamp(self.images[i].last_update),
+ 'up' : self.images[i].up,
+ }
+ if self.size < self.max_read:
+ break
+ self.get_next_chunk()
+
+ def __dealloc__(self):
+ rbd_mirror_image_status_list_cleanup(self.image_ids, self.images,
+ self.size)
+ if self.last_read:
+ free(self.last_read)
+ if self.image_ids:
+ free(self.image_ids)
+ if self.images:
+ free(self.images)
+
+ def get_next_chunk(self):
+ if self.size > 0:
+ rbd_mirror_image_status_list_cleanup(self.image_ids, self.images,
+ self.size)
+ self.size = 0
+ with nogil:
+ ret = rbd_mirror_image_status_list(self.ioctx, self.last_read,
+ self.max_read, self.image_ids,
+ self.images, &self.size)
+ if ret < 0:
+ raise make_ex(ret, 'error listing mirror images status')
+ if self.size > 0:
+ last_read = cstr(self.image_ids[self.size - 1], 'last_read')
+ free(self.last_read)
+ self.last_read = strdup(last_read)
+ else:
+ free(self.last_read)
+ self.last_read = strdup("")
+
+cdef class MirrorImageInstanceIdIterator(object):
+ """
+ Iterator over mirror image instance id for a pool.
+
+ Yields ``(image_id, instance_id)`` tuple.
+ """
+
+ cdef:
+ rados_ioctx_t ioctx
+ size_t max_read
+ char *last_read
+ char **image_ids
+ char **instance_ids
+ size_t size
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.max_read = 1024
+ self.last_read = strdup("")
+ self.image_ids = <char **>realloc_chk(NULL,
+ sizeof(char *) * self.max_read)
+ self.instance_ids = <char **>realloc_chk(NULL,
+ sizeof(char *) * self.max_read)
+ self.size = 0
+ self.get_next_chunk()
+
+ def __iter__(self):
+ while self.size > 0:
+ for i in range(self.size):
+ yield (decode_cstr(self.image_ids[i]),
+ decode_cstr(self.instance_ids[i]))
+ if self.size < self.max_read:
+ break
+ self.get_next_chunk()
+
+ def __dealloc__(self):
+ rbd_mirror_image_instance_id_list_cleanup(self.image_ids,
+ self.instance_ids, self.size)
+ if self.last_read:
+ free(self.last_read)
+ if self.image_ids:
+ free(self.image_ids)
+ if self.instance_ids:
+ free(self.instance_ids)
+
+ def get_next_chunk(self):
+ if self.size > 0:
+ rbd_mirror_image_instance_id_list_cleanup(self.image_ids,
+ self.instance_ids,
+ self.size)
+ self.size = 0
+ with nogil:
+ ret = rbd_mirror_image_instance_id_list(self.ioctx, self.last_read,
+ self.max_read,
+ self.image_ids,
+ self.instance_ids,
+ &self.size)
+ if ret < 0:
+ raise make_ex(ret, 'error listing mirror images instance ids')
+ if self.size > 0:
+ last_read = cstr(self.image_ids[self.size - 1], 'last_read')
+ free(self.last_read)
+ self.last_read = strdup(last_read)
+ else:
+ free(self.last_read)
+ self.last_read = strdup("")
+
+cdef class PoolMetadataIterator(object):
+ """
+ Iterator over pool metadata list.
+
+ Yields ``(key, value)`` tuple.
+
+ * ``key`` (str) - metadata key
+ * ``value`` (str) - metadata value
+ """
+
+ cdef:
+ rados_ioctx_t ioctx
+ char *last_read
+ uint64_t max_read
+ object next_chunk
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.last_read = strdup("")
+ self.max_read = 32
+ self.get_next_chunk()
+
+ def __iter__(self):
+ while len(self.next_chunk) > 0:
+ for pair in self.next_chunk:
+ yield pair
+ if len(self.next_chunk) < self.max_read:
+ break
+ self.get_next_chunk()
+
+ def __dealloc__(self):
+ if self.last_read:
+ free(self.last_read)
+
+ def get_next_chunk(self):
+ cdef:
+ char *c_keys = NULL
+ size_t keys_size = 4096
+ char *c_vals = NULL
+ size_t vals_size = 4096
+ try:
+ while True:
+ c_keys = <char *>realloc_chk(c_keys, keys_size)
+ c_vals = <char *>realloc_chk(c_vals, vals_size)
+ with nogil:
+ ret = rbd_pool_metadata_list(self.ioctx, self.last_read,
+ self.max_read, c_keys,
+ &keys_size, c_vals, &vals_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing metadata')
+ keys = [decode_cstr(key) for key in
+ c_keys[:keys_size].split(b'\0') if key]
+ vals = [decode_cstr(val) for val in
+ c_vals[:vals_size].split(b'\0') if val]
+ if len(keys) > 0:
+ last_read = cstr(keys[-1], 'last_read')
+ free(self.last_read)
+ self.last_read = strdup(last_read)
+ self.next_chunk = list(zip(keys, vals))
+ finally:
+ free(c_keys)
+ free(c_vals)
+
+cdef class ConfigPoolIterator(object):
+ """
+ Iterator over pool-level overrides for a pool.
+
+ Yields a dictionary containing information about an override.
+
+ Keys are:
+
+ * ``name`` (str) - override name
+
+ * ``value`` (str) - override value
+
+ * ``source`` (str) - override source
+ """
+
+ cdef:
+ rbd_config_option_t *options
+ int num_options
+
+ def __init__(self, ioctx):
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ self.options = NULL
+ self.num_options = 32
+ while True:
+ self.options = <rbd_config_option_t *>realloc_chk(
+ self.options, self.num_options * sizeof(rbd_config_option_t))
+ with nogil:
+ ret = rbd_config_pool_list(_ioctx, self.options, &self.num_options)
+ if ret < 0:
+ if ret == -errno.ERANGE:
+ continue
+ self.num_options = 0
+ raise make_ex(ret, 'error listing config options')
+ break
+
+ def __iter__(self):
+ for i in range(self.num_options):
+ yield {
+ 'name' : decode_cstr(self.options[i].name),
+ 'value' : decode_cstr(self.options[i].value),
+ 'source' : self.options[i].source,
+ }
+
+ def __dealloc__(self):
+ if self.options:
+ rbd_config_pool_list_cleanup(self.options, self.num_options)
+ free(self.options)
+
+cdef int diff_iterate_cb(uint64_t offset, size_t length, int write, void *cb) \
+ except? -9000 with gil:
+ # Make sure that if we wound up with an exception from a previous callback,
+ # we stop calling back (just in case librbd ever fails to bail out on the
+ # first negative return, as older versions did)
+ if exc.PyErr_Occurred():
+ return -9000
+ ret = (<object>cb)(offset, length, bool(write))
+ if ret is None:
+ return 0
+ return ret
+
+cdef class Group(object):
+ """
+ This class represents an RBD group. It is used to interact with
+ snapshots and images members.
+ """
+
+ cdef object name
+ cdef char *_name
+ cdef object ioctx
+
+ cdef rados_ioctx_t _ioctx
+
+ def __init__(self, ioctx, name):
+ name = cstr(name, 'name')
+ self.name = name
+
+ self._ioctx = convert_ioctx(ioctx)
+ self._name = name
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ return False
+
+ def add_image(self, image_ioctx, image_name):
+ """
+ Add an image to a group.
+
+ :param image_ioctx: determines which RADOS pool the image belongs to.
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image to add
+ :type name: str
+
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`ObjectExists`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _image_ioctx = convert_ioctx(image_ioctx)
+ char *_image_name = image_name
+ with nogil:
+ ret = rbd_group_image_add(self._ioctx, self._name, _image_ioctx, _image_name)
+ if ret != 0:
+ raise make_ex(ret, 'error adding image to group', group_errno_to_exception)
+
+ def remove_image(self, image_ioctx, image_name):
+ """
+ Remove an image from a group.
+
+ :param image_ioctx: determines which RADOS pool the image belongs to.
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image to remove
+ :type name: str
+
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ image_name = cstr(image_name, 'image_name')
+ cdef:
+ rados_ioctx_t _image_ioctx = convert_ioctx(image_ioctx)
+ char *_image_name = image_name
+ with nogil:
+ ret = rbd_group_image_remove(self._ioctx, self._name, _image_ioctx, _image_name)
+ if ret != 0:
+ raise make_ex(ret, 'error removing image from group', group_errno_to_exception)
+
+
+ def list_images(self):
+ """
+ Iterate over the images of a group.
+
+ :returns: :class:`GroupImageIterator`
+ """
+ return GroupImageIterator(self)
+
+ def create_snap(self, snap_name):
+ """
+ Create a snapshot for the group.
+
+ :param snap_name: the name of the snapshot to create
+ :type name: str
+
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`ObjectExists`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ snap_name = cstr(snap_name, 'snap_name')
+ cdef:
+ char *_snap_name = snap_name
+ with nogil:
+ ret = rbd_group_snap_create(self._ioctx, self._name, _snap_name)
+ if ret != 0:
+ raise make_ex(ret, 'error creating group snapshot', group_errno_to_exception)
+
+ def remove_snap(self, snap_name):
+ """
+ Remove a snapshot from the group.
+
+ :param snap_name: the name of the snapshot to remove
+ :type name: str
+
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+ snap_name = cstr(snap_name, 'snap_name')
+ cdef:
+ char *_snap_name = snap_name
+ with nogil:
+ ret = rbd_group_snap_remove(self._ioctx, self._name, _snap_name)
+ if ret != 0:
+ raise make_ex(ret, 'error removing group snapshot', group_errno_to_exception)
+
+ def rename_snap(self, old_snap_name, new_snap_name):
+ """
+ Rename group's snapshot.
+
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`ObjectExists`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`FunctionNotSupported`
+ """
+
+ old_snap_name = cstr(old_snap_name, 'old_snap_name')
+ new_snap_name = cstr(new_snap_name, 'new_snap_name')
+ cdef:
+ char *_old_snap_name = old_snap_name
+ char *_new_snap_name = new_snap_name
+ with nogil:
+ ret = rbd_group_snap_rename(self._ioctx, self._name, _old_snap_name,
+ _new_snap_name)
+ if ret != 0:
+ raise make_ex(ret, 'error renaming group snapshot',
+ group_errno_to_exception)
+
+ def list_snaps(self):
+ """
+ Iterate over the images of a group.
+
+ :returns: :class:`GroupSnapIterator`
+ """
+ return GroupSnapIterator(self)
+
+ def rollback_to_snap(self, name):
+ """
+ Rollback group to snapshot.
+
+ :param name: the group snapshot to rollback to
+ :type name: str
+ :raises: :class:`ObjectNotFound`
+ :raises: :class:`IOError`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_group_snap_rollback(self._ioctx, self._name, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error rolling back group to snapshot', group_errno_to_exception)
+
+def requires_not_closed(f):
+ def wrapper(self, *args, **kwargs):
+ self.require_not_closed()
+ return f(self, *args, **kwargs)
+
+ return wrapper
+
+cdef class Image(object):
+ """
+ This class represents an RBD image. It is used to perform I/O on
+ the image and interact with snapshots.
+
+ **Note**: Any method of this class may raise :class:`ImageNotFound`
+ if the image has been deleted.
+ """
+ cdef rbd_image_t image
+ cdef bint closed
+ cdef object name
+ cdef object ioctx
+ cdef rados_ioctx_t _ioctx
+
+ def __init__(self, ioctx, name=None, snapshot=None,
+ read_only=False, image_id=None):
+ """
+ Open the image at the given snapshot.
+ Specify either name or id, otherwise :class:`InvalidArgument` is raised.
+
+ If a snapshot is specified, the image will be read-only, unless
+ :func:`Image.set_snap` is called later.
+
+ If read-only mode is used, metadata for the :class:`Image`
+ object (such as which snapshots exist) may become obsolete. See
+ the C api for more details.
+
+ To clean up from opening the image, :func:`Image.close` should
+ be called. For ease of use, this is done automatically when
+ an :class:`Image` is used as a context manager (see :pep:`343`).
+
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image
+ :type name: str
+ :param snapshot: which snapshot to read from
+ :type snaphshot: str
+ :param read_only: whether to open the image in read-only mode
+ :type read_only: bool
+ :param image_id: the id of the image
+ :type image_id: str
+ """
+ name = cstr(name, 'name', opt=True)
+ image_id = cstr(image_id, 'image_id', opt=True)
+ snapshot = cstr(snapshot, 'snapshot', opt=True)
+ self.closed = True
+ if name is not None and image_id is not None:
+ raise InvalidArgument("only need to specify image name or image id")
+ elif name is None and image_id is None:
+ raise InvalidArgument("image name or image id was not specified")
+ elif name is not None:
+ self.name = name
+ else:
+ self.name = image_id
+ # Keep around a reference to the ioctx, so it won't get deleted
+ self.ioctx = ioctx
+ cdef:
+ rados_ioctx_t _ioctx = convert_ioctx(ioctx)
+ char *_name = opt_str(name)
+ char *_image_id = opt_str(image_id)
+ char *_snapshot = opt_str(snapshot)
+ if read_only:
+ with nogil:
+ if name is not None:
+ ret = rbd_open_read_only(_ioctx, _name, &self.image, _snapshot)
+ else:
+ ret = rbd_open_by_id_read_only(_ioctx, _image_id, &self.image, _snapshot)
+ else:
+ with nogil:
+ if name is not None:
+ ret = rbd_open(_ioctx, _name, &self.image, _snapshot)
+ else:
+ ret = rbd_open_by_id(_ioctx, _image_id, &self.image, _snapshot)
+ if ret != 0:
+ raise make_ex(ret, 'error opening image %s at snapshot %s' % (self.name, snapshot))
+ self.closed = False
+ if name is None:
+ self.name = self.get_name()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ """
+ Closes the image. See :func:`close`
+ """
+ self.close()
+ return False
+
+ def __get_completion(self, oncomplete):
+ """
+ Constructs a completion to use with asynchronous operations
+
+ :param oncomplete: callback for the completion
+
+ :raises: :class:`Error`
+ :returns: completion object
+ """
+
+ completion_obj = Completion(self, oncomplete)
+
+ cdef:
+ rbd_completion_t completion
+ PyObject* p_completion_obj= <PyObject*>completion_obj
+
+ with nogil:
+ ret = rbd_aio_create_completion(p_completion_obj, __aio_complete_cb,
+ &completion)
+ if ret < 0:
+ raise make_ex(ret, "error getting a completion")
+
+ completion_obj.rbd_comp = completion
+ return completion_obj
+
+ def require_not_closed(self):
+ """
+ Checks if the Image is not closed
+
+ :raises: :class:`InvalidArgument`
+ """
+ if self.closed:
+ raise InvalidArgument("image is closed")
+
+ def close(self):
+ """
+ Release the resources used by this image object.
+
+ After this is called, this object should not be used.
+ """
+ if not self.closed:
+ self.closed = True
+ with nogil:
+ ret = rbd_close(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error while closing image %s' % (
+ self.name,))
+
+ def __dealloc__(self):
+ self.close()
+
+ def __repr__(self):
+ return "rbd.Image(ioctx, %r)" % self.name
+
+ @requires_not_closed
+ def resize(self, size, allow_shrink=True):
+ """
+ Change the size of the image, allow shrink.
+
+ :param size: the new size of the image
+ :type size: int
+ :param allow_shrink: permit shrinking
+ :type allow_shrink: bool
+ """
+ old_size = self.size()
+ if old_size == size:
+ return
+ if not allow_shrink and old_size > size:
+ raise InvalidArgument("error allow_shrink is False but old_size > new_size")
+ cdef:
+ uint64_t _size = size
+ bint _allow_shrink = allow_shrink
+ librbd_progress_fn_t prog_cb = &no_op_progress_callback
+ with nogil:
+ ret = rbd_resize2(self.image, _size, _allow_shrink, prog_cb, NULL)
+ if ret < 0:
+ raise make_ex(ret, 'error resizing image %s' % self.name)
+
+ @requires_not_closed
+ def stat(self):
+ """
+ Get information about the image. Currently parent pool and
+ parent name are always -1 and ''.
+
+ :returns: dict - contains the following keys:
+
+ * ``size`` (int) - the size of the image in bytes
+
+ * ``obj_size`` (int) - the size of each object that comprises the
+ image
+
+ * ``num_objs`` (int) - the number of objects in the image
+
+ * ``order`` (int) - log_2(object_size)
+
+ * ``block_name_prefix`` (str) - the prefix of the RADOS objects used
+ to store the image
+
+ * ``parent_pool`` (int) - deprecated
+
+ * ``parent_name`` (str) - deprecated
+
+ See also :meth:`format` and :meth:`features`.
+
+ """
+ cdef rbd_image_info_t info
+ with nogil:
+ ret = rbd_stat(self.image, &info, sizeof(info))
+ if ret != 0:
+ raise make_ex(ret, 'error getting info for image %s' % self.name)
+ return {
+ 'size' : info.size,
+ 'obj_size' : info.obj_size,
+ 'num_objs' : info.num_objs,
+ 'order' : info.order,
+ 'block_name_prefix' : decode_cstr(info.block_name_prefix),
+ 'parent_pool' : info.parent_pool,
+ 'parent_name' : info.parent_name
+ }
+
+ @requires_not_closed
+ def get_name(self):
+ """
+ Get the RBD image name
+
+ :returns: str - image name
+ """
+ cdef:
+ int ret = -errno.ERANGE
+ size_t size = 64
+ char *image_name = NULL
+ try:
+ while ret == -errno.ERANGE:
+ image_name = <char *>realloc_chk(image_name, size)
+ with nogil:
+ ret = rbd_get_name(self.image, image_name, &size)
+
+ if ret != 0:
+ raise make_ex(ret, 'error getting name for image %s' % self.name)
+ return decode_cstr(image_name)
+ finally:
+ free(image_name)
+
+ @requires_not_closed
+ def id(self):
+ """
+ Get the RBD v2 internal image id
+
+ :returns: str - image id
+ """
+ cdef:
+ int ret = -errno.ERANGE
+ size_t size = 32
+ char *image_id = NULL
+ try:
+ while ret == -errno.ERANGE and size <= 4096:
+ image_id = <char *>realloc_chk(image_id, size)
+ with nogil:
+ ret = rbd_get_id(self.image, image_id, size)
+ if ret == -errno.ERANGE:
+ size *= 2
+
+ if ret != 0:
+ raise make_ex(ret, 'error getting id for image %s' % self.name)
+ return decode_cstr(image_id)
+ finally:
+ free(image_id)
+
+ @requires_not_closed
+ def block_name_prefix(self):
+ """
+ Get the RBD block name prefix
+
+ :returns: str - block name prefix
+ """
+ cdef:
+ int ret = -errno.ERANGE
+ size_t size = 32
+ char *prefix = NULL
+ try:
+ while ret == -errno.ERANGE and size <= 4096:
+ prefix = <char *>realloc_chk(prefix, size)
+ with nogil:
+ ret = rbd_get_block_name_prefix(self.image, prefix, size)
+ if ret == -errno.ERANGE:
+ size *= 2
+
+ if ret != 0:
+ raise make_ex(ret, 'error getting block name prefix for image %s' % self.name)
+ return decode_cstr(prefix)
+ finally:
+ free(prefix)
+
+ @requires_not_closed
+ def data_pool_id(self):
+ """
+ Get the pool id of the pool where the data of this RBD image is stored.
+
+ :returns: int - the pool id
+ """
+ return rbd_get_data_pool_id(self.image)
+
+ @requires_not_closed
+ def get_parent_image_spec(self):
+ """
+ Get spec of the cloned image's parent
+
+ :returns: dict - contains the following keys:
+ * ``pool_name`` (str) - parent pool name
+ * ``pool_namespace`` (str) - parent pool namespace
+ * ``image_name`` (str) - parent image name
+ * ``snap_name`` (str) - parent snapshot name
+
+ :raises: :class:`ImageNotFound` if the image doesn't have a parent
+ """
+ cdef:
+ rbd_linked_image_spec_t parent_spec
+ rbd_snap_spec_t snap_spec
+ with nogil:
+ ret = rbd_get_parent(self.image, &parent_spec, &snap_spec)
+ if ret != 0:
+ raise make_ex(ret, 'error getting parent info for image %s' % self.name)
+
+ result = {'pool_name': decode_cstr(parent_spec.pool_name),
+ 'pool_namespace': decode_cstr(parent_spec.pool_namespace),
+ 'image_name': decode_cstr(parent_spec.image_name),
+ 'snap_name': decode_cstr(snap_spec.name)}
+
+ rbd_linked_image_spec_cleanup(&parent_spec)
+ rbd_snap_spec_cleanup(&snap_spec)
+ return result
+
+ @requires_not_closed
+ def parent_info(self):
+ """
+ Deprecated. Use `get_parent_image_spec` instead.
+
+ Get information about a cloned image's parent (if any)
+
+ :returns: tuple - ``(pool name, image name, snapshot name)`` components
+ of the parent image
+ :raises: :class:`ImageNotFound` if the image doesn't have a parent
+ """
+ parent = self.get_parent_image_spec()
+ return (parent['pool_name'], parent['image_name'], parent['snap_name'])
+
+ @requires_not_closed
+ def parent_id(self):
+ """
+ Get image id of a cloned image's parent (if any)
+
+ :returns: str - the parent id
+ :raises: :class:`ImageNotFound` if the image doesn't have a parent
+ """
+ cdef:
+ rbd_linked_image_spec_t parent_spec
+ rbd_snap_spec_t snap_spec
+ with nogil:
+ ret = rbd_get_parent(self.image, &parent_spec, &snap_spec)
+ if ret != 0:
+ raise make_ex(ret, 'error getting parent info for image %s' % self.name)
+
+ result = decode_cstr(parent_spec.image_id)
+
+ rbd_linked_image_spec_cleanup(&parent_spec)
+ rbd_snap_spec_cleanup(&snap_spec)
+ return result
+
+ @requires_not_closed
+ def old_format(self):
+ """
+ Find out whether the image uses the old RBD format.
+
+ :returns: bool - whether the image uses the old RBD format
+ """
+ cdef uint8_t old
+ with nogil:
+ ret = rbd_get_old_format(self.image, &old)
+ if ret != 0:
+ raise make_ex(ret, 'error getting old_format for image %s' % (self.name))
+ return old != 0
+
+ @requires_not_closed
+ def size(self):
+ """
+ Get the size of the image. If open to a snapshot, returns the
+ size of that snapshot.
+
+ :returns: int - the size of the image in bytes
+ """
+ cdef uint64_t image_size
+ with nogil:
+ ret = rbd_get_size(self.image, &image_size)
+ if ret != 0:
+ raise make_ex(ret, 'error getting size for image %s' % (self.name))
+ return image_size
+
+ @requires_not_closed
+ def features(self):
+ """
+ Get the features bitmask of the image.
+
+ :returns: int - the features bitmask of the image
+ """
+ cdef uint64_t features
+ with nogil:
+ ret = rbd_get_features(self.image, &features)
+ if ret != 0:
+ raise make_ex(ret, 'error getting features for image %s' % (self.name))
+ return features
+
+ @requires_not_closed
+ def update_features(self, features, enabled):
+ """
+ Update the features bitmask of the image by enabling/disabling
+ a single feature. The feature must support the ability to be
+ dynamically enabled/disabled.
+
+ :param features: feature bitmask to enable/disable
+ :type features: int
+ :param enabled: whether to enable/disable the feature
+ :type enabled: bool
+ :raises: :class:`InvalidArgument`
+ """
+ cdef:
+ uint64_t _features = features
+ uint8_t _enabled = bool(enabled)
+ with nogil:
+ ret = rbd_update_features(self.image, _features, _enabled)
+ if ret != 0:
+ raise make_ex(ret, 'error updating features for image %s' %
+ (self.name))
+
+ @requires_not_closed
+ def op_features(self):
+ """
+ Get the op features bitmask of the image.
+
+ :returns: int - the op features bitmask of the image
+ """
+ cdef uint64_t op_features
+ with nogil:
+ ret = rbd_get_op_features(self.image, &op_features)
+ if ret != 0:
+ raise make_ex(ret, 'error getting op features for image %s' % (self.name))
+ return op_features
+
+ @requires_not_closed
+ def overlap(self):
+ """
+ Get the number of overlapping bytes between the image and its parent
+ image. If open to a snapshot, returns the overlap between the snapshot
+ and the parent image.
+
+ :returns: int - the overlap in bytes
+ :raises: :class:`ImageNotFound` if the image doesn't have a parent
+ """
+ cdef uint64_t overlap
+ with nogil:
+ ret = rbd_get_overlap(self.image, &overlap)
+ if ret != 0:
+ raise make_ex(ret, 'error getting overlap for image %s' % (self.name))
+ return overlap
+
+ @requires_not_closed
+ def flags(self):
+ """
+ Get the flags bitmask of the image.
+
+ :returns: int - the flags bitmask of the image
+ """
+ cdef uint64_t flags
+ with nogil:
+ ret = rbd_get_flags(self.image, &flags)
+ if ret != 0:
+ raise make_ex(ret, 'error getting flags for image %s' % (self.name))
+ return flags
+
+ @requires_not_closed
+ def group(self):
+ """
+ Get information about the image's group.
+
+ :returns: dict - contains the following keys:
+
+ * ``pool`` (int) - id of the group pool
+
+ * ``name`` (str) - name of the group
+
+ """
+ cdef rbd_group_info_t info
+ with nogil:
+ ret = rbd_get_group(self.image, &info, sizeof(info))
+ if ret != 0:
+ raise make_ex(ret, 'error getting group for image %s' % self.name)
+ result = {
+ 'pool' : info.pool,
+ 'name' : decode_cstr(info.name)
+ }
+ rbd_group_info_cleanup(&info, sizeof(info))
+ return result
+
+ @requires_not_closed
+ def is_exclusive_lock_owner(self):
+ """
+ Get the status of the image exclusive lock.
+
+ :returns: bool - true if the image is exclusively locked
+ """
+ cdef int owner
+ with nogil:
+ ret = rbd_is_exclusive_lock_owner(self.image, &owner)
+ if ret != 0:
+ raise make_ex(ret, 'error getting lock status for image %s' % (self.name))
+ return owner == 1
+
+ @requires_not_closed
+ def copy(self, dest_ioctx, dest_name, features=None, order=None,
+ stripe_unit=None, stripe_count=None, data_pool=None):
+ """
+ Copy the image to another location.
+
+ :param dest_ioctx: determines which pool to copy into
+ :type dest_ioctx: :class:`rados.Ioctx`
+ :param dest_name: the name of the copy
+ :type dest_name: str
+ :param features: bitmask of features to enable; if set, must include layering
+ :type features: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :param data_pool: optional separate pool for data blocks
+ :type data_pool: str
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`ImageExists`
+ :raises: :class:`FunctionNotSupported`
+ :raises: :class:`ArgumentOutOfRange`
+ """
+ dest_name = cstr(dest_name, 'dest_name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
+ cdef:
+ rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
+ char *_dest_name = dest_name
+ rbd_image_options_t opts
+
+ rbd_image_options_create(&opts)
+ try:
+ if features is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FEATURES,
+ features)
+ if order is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+ order)
+ if stripe_unit is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+ stripe_unit)
+ if stripe_count is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_COUNT,
+ stripe_count)
+ if data_pool is not None:
+ rbd_image_options_set_string(opts, RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool)
+ with nogil:
+ ret = rbd_copy3(self.image, _dest_ioctx, _dest_name, opts)
+ finally:
+ rbd_image_options_destroy(opts)
+ if ret < 0:
+ raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
+
+ @requires_not_closed
+ def deep_copy(self, dest_ioctx, dest_name, features=None, order=None,
+ stripe_unit=None, stripe_count=None, data_pool=None):
+ """
+ Deep copy the image to another location.
+
+ :param dest_ioctx: determines which pool to copy into
+ :type dest_ioctx: :class:`rados.Ioctx`
+ :param dest_name: the name of the copy
+ :type dest_name: str
+ :param features: bitmask of features to enable; if set, must include layering
+ :type features: int
+ :param order: the image is split into (2**order) byte objects
+ :type order: int
+ :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+ :type stripe_unit: int
+ :param stripe_count: objects to stripe over before looping
+ :type stripe_count: int
+ :param data_pool: optional separate pool for data blocks
+ :type data_pool: str
+ :raises: :class:`TypeError`
+ :raises: :class:`InvalidArgument`
+ :raises: :class:`ImageExists`
+ :raises: :class:`FunctionNotSupported`
+ :raises: :class:`ArgumentOutOfRange`
+ """
+ dest_name = cstr(dest_name, 'dest_name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
+ cdef:
+ rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
+ char *_dest_name = dest_name
+ rbd_image_options_t opts
+
+ rbd_image_options_create(&opts)
+ try:
+ if features is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FEATURES,
+ features)
+ if order is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+ order)
+ if stripe_unit is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+ stripe_unit)
+ if stripe_count is not None:
+ rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_COUNT,
+ stripe_count)
+ if data_pool is not None:
+ rbd_image_options_set_string(opts, RBD_IMAGE_OPTION_DATA_POOL,
+ data_pool)
+ with nogil:
+ ret = rbd_deep_copy(self.image, _dest_ioctx, _dest_name, opts)
+ finally:
+ rbd_image_options_destroy(opts)
+ if ret < 0:
+ raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
+
+ @requires_not_closed
+ def list_snaps(self):
+ """
+ Iterate over the snapshots of an image.
+
+ :returns: :class:`SnapIterator`
+ """
+ return SnapIterator(self)
+
+ @requires_not_closed
+ def create_snap(self, name):
+ """
+ Create a snapshot of the image.
+
+ :param name: the name of the snapshot
+ :type name: str
+ :raises: :class:`ImageExists`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_snap_create(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error creating snapshot %s from %s' % (name, self.name))
+
+ @requires_not_closed
+ def rename_snap(self, srcname, dstname):
+ """
+ rename a snapshot of the image.
+
+ :param srcname: the src name of the snapshot
+ :type srcname: str
+ :param dstname: the dst name of the snapshot
+ :type dstname: str
+ :raises: :class:`ImageExists`
+ """
+ srcname = cstr(srcname, 'srcname')
+ dstname = cstr(dstname, 'dstname')
+ cdef:
+ char *_srcname = srcname
+ char *_dstname = dstname
+ with nogil:
+ ret = rbd_snap_rename(self.image, _srcname, _dstname)
+ if ret != 0:
+ raise make_ex(ret, 'error renaming snapshot of %s from %s to %s' % (self.name, srcname, dstname))
+
+ @requires_not_closed
+ def remove_snap(self, name):
+ """
+ Delete a snapshot of the image.
+
+ :param name: the name of the snapshot
+ :type name: str
+ :raises: :class:`IOError`, :class:`ImageBusy`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_snap_remove(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error removing snapshot %s from %s' % (name, self.name))
+
+ @requires_not_closed
+ def remove_snap2(self, name, flags):
+ """
+ Delete a snapshot of the image.
+
+ :param name: the name of the snapshot
+ :param flags: the flags for removal
+ :type name: str
+ :raises: :class:`IOError`, :class:`ImageBusy`
+ """
+ self.require_not_closed()
+
+ name = cstr(name, 'name')
+ cdef:
+ char *_name = name
+ uint32_t _flags = flags
+ librbd_progress_fn_t prog_cb = &no_op_progress_callback
+ with nogil:
+ ret = rbd_snap_remove2(self.image, _name, _flags, prog_cb, NULL)
+ if ret != 0:
+ raise make_ex(ret, 'error removing snapshot %s from %s with flags %llx' % (name, self.name, flags))
+
+ @requires_not_closed
+ def remove_snap_by_id(self, snap_id):
+ """
+ Delete a snapshot of the image by its id.
+
+ :param id: the id of the snapshot
+ :type name: int
+ :raises: :class:`IOError`, :class:`ImageBusy`
+ """
+ cdef:
+ uint64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_remove_by_id(self.image, _snap_id)
+ if ret != 0:
+ raise make_ex(ret, 'error removing snapshot %s from %s' % (snap_id, self.name))
+
+ @requires_not_closed
+ def rollback_to_snap(self, name):
+ """
+ Revert the image to its contents at a snapshot. This is a
+ potentially expensive operation, since it rolls back each
+ object individually.
+
+ :param name: the snapshot to rollback to
+ :type name: str
+ :raises: :class:`IOError`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_snap_rollback(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error rolling back image %s to snapshot %s' % (self.name, name))
+
+ @requires_not_closed
+ def protect_snap(self, name):
+ """
+ Mark a snapshot as protected. This means it can't be deleted
+ until it is unprotected.
+
+ :param name: the snapshot to protect
+ :type name: str
+ :raises: :class:`IOError`, :class:`ImageNotFound`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_snap_protect(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error protecting snapshot %s@%s' % (self.name, name))
+
+ @requires_not_closed
+ def unprotect_snap(self, name):
+ """
+ Mark a snapshot unprotected. This allows it to be deleted if
+ it was protected.
+
+ :param name: the snapshot to unprotect
+ :type name: str
+ :raises: :class:`IOError`, :class:`ImageNotFound`
+ """
+ name = cstr(name, 'name')
+ cdef char *_name = name
+ with nogil:
+ ret = rbd_snap_unprotect(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error unprotecting snapshot %s@%s' % (self.name, name))
+
+ @requires_not_closed
+ def is_protected_snap(self, name):
+ """
+ Find out whether a snapshot is protected from deletion.
+
+ :param name: the snapshot to check
+ :type name: str
+ :returns: bool - whether the snapshot is protected
+ :raises: :class:`IOError`, :class:`ImageNotFound`
+ """
+ name = cstr(name, 'name')
+ cdef:
+ char *_name = name
+ int is_protected
+ with nogil:
+ ret = rbd_snap_is_protected(self.image, _name, &is_protected)
+ if ret != 0:
+ raise make_ex(ret, 'error checking if snapshot %s@%s is protected' % (self.name, name))
+ return is_protected == 1
+
+ @requires_not_closed
+ def get_snap_limit(self):
+ """
+ Get the snapshot limit for an image.
+
+ :returns: int - the snapshot limit for an image
+ """
+ cdef:
+ uint64_t limit
+ with nogil:
+ ret = rbd_snap_get_limit(self.image, &limit)
+ if ret != 0:
+ raise make_ex(ret, 'error getting snapshot limit for %s' % self.name)
+ return limit
+
+ @requires_not_closed
+ def set_snap_limit(self, limit):
+ """
+ Set the snapshot limit for an image.
+
+ :param limit: the new limit to set
+ """
+ cdef:
+ uint64_t _limit = limit
+ with nogil:
+ ret = rbd_snap_set_limit(self.image, _limit)
+ if ret != 0:
+ raise make_ex(ret, 'error setting snapshot limit for %s' % self.name)
+ return ret
+
+ @requires_not_closed
+ def get_snap_timestamp(self, snap_id):
+ """
+ Get the snapshot timestamp for an image.
+ :param snap_id: the snapshot id of a snap shot
+ :returns: datetime - the snapshot timestamp for an image
+ """
+ cdef:
+ timespec timestamp
+ uint64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_get_timestamp(self.image, _snap_id, &timestamp)
+ if ret != 0:
+ raise make_ex(ret, 'error getting snapshot timestamp for image: %s, snap_id: %d' % (self.name, snap_id))
+ return datetime.utcfromtimestamp(timestamp.tv_sec)
+
+ @requires_not_closed
+ def remove_snap_limit(self):
+ """
+ Remove the snapshot limit for an image, essentially setting
+ the limit to the maximum size allowed by the implementation.
+ """
+ with nogil:
+ ret = rbd_snap_set_limit(self.image, UINT64_MAX)
+ if ret != 0:
+ raise make_ex(ret, 'error removing snapshot limit for %s' % self.name)
+ return ret
+
+ @requires_not_closed
+ def set_snap(self, name):
+ """
+ Set the snapshot to read from. Writes will raise ReadOnlyImage
+ while a snapshot is set. Pass None to unset the snapshot
+ (reads come from the current image) , and allow writing again.
+
+ :param name: the snapshot to read from, or None to unset the snapshot
+ :type name: str or None
+ """
+ name = cstr(name, 'name', opt=True)
+ cdef char *_name = opt_str(name)
+ with nogil:
+ ret = rbd_snap_set(self.image, _name)
+ if ret != 0:
+ raise make_ex(ret, 'error setting image %s to snapshot %s' % (self.name, name))
+
+ @requires_not_closed
+ def set_snap_by_id(self, snap_id):
+ """
+ Set the snapshot to read from. Writes will raise ReadOnlyImage
+ while a snapshot is set. Pass None to unset the snapshot
+ (reads come from the current image) , and allow writing again.
+
+ :param snap_id: the snapshot to read from, or None to unset the snapshot
+ :type snap_id: int
+ """
+ if not snap_id:
+ snap_id = _LIBRADOS_SNAP_HEAD
+ cdef int64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_set_by_id(self.image, _snap_id)
+ if ret != 0:
+ raise make_ex(ret, 'error setting image %s to snapshot %d' % (self.name, snap_id))
+
+ @requires_not_closed
+ def read(self, offset, length, fadvise_flags=0):
+ """
+ Read data from the image. Raises :class:`InvalidArgument` if
+ part of the range specified is outside the image.
+
+ :param offset: the offset to start reading at
+ :type offset: int
+ :param length: how many bytes to read
+ :type length: int
+ :param fadvise_flags: fadvise flags for this read
+ :type fadvise_flags: int
+ :returns: str - the data read
+ :raises: :class:`InvalidArgument`, :class:`IOError`
+ """
+
+ # This usage of the Python API allows us to construct a string
+ # that librbd directly reads into, avoiding an extra copy. Although
+ # strings are normally immutable, this usage is explicitly supported
+ # for freshly created string objects.
+ cdef:
+ char *ret_buf
+ uint64_t _offset = offset
+ size_t _length = length
+ int _fadvise_flags = fadvise_flags
+ PyObject* ret_s = NULL
+ ret_s = PyBytes_FromStringAndSize(NULL, length)
+ try:
+ ret_buf = PyBytes_AsString(ret_s)
+ with nogil:
+ ret = rbd_read2(self.image, _offset, _length, ret_buf,
+ _fadvise_flags)
+ if ret < 0:
+ raise make_ex(ret, 'error reading %s %ld~%ld' % (self.name, offset, length))
+
+ if ret != <ssize_t>length:
+ _PyBytes_Resize(&ret_s, ret)
+
+ return <object>ret_s
+ finally:
+ # We DECREF unconditionally: the cast to object above will have
+ # INCREFed if necessary. This also takes care of exceptions,
+ # including if _PyString_Resize fails (that will free the string
+ # itself and set ret_s to NULL, hence XDECREF).
+ ref.Py_XDECREF(ret_s)
+
+ @requires_not_closed
+ def diff_iterate(self, offset, length, from_snapshot, iterate_cb,
+ include_parent = True, whole_object = False):
+ """
+ Iterate over the changed extents of an image.
+
+ This will call iterate_cb with three arguments:
+
+ (offset, length, exists)
+
+ where the changed extent starts at offset bytes, continues for
+ length bytes, and is full of data (if exists is True) or zeroes
+ (if exists is False).
+
+ If from_snapshot is None, it is interpreted as the beginning
+ of time and this generates all allocated extents.
+
+ The end version is whatever is currently selected (via set_snap)
+ for the image.
+
+ iterate_cb may raise an exception, which will abort the diff and will be
+ propagated to the caller.
+
+ Raises :class:`InvalidArgument` if from_snapshot is after
+ the currently set snapshot.
+
+ Raises :class:`ImageNotFound` if from_snapshot is not the name
+ of a snapshot of the image.
+
+ :param offset: start offset in bytes
+ :type offset: int
+ :param length: size of region to report on, in bytes
+ :type length: int
+ :param from_snapshot: starting snapshot name, or None
+ :type from_snapshot: str or None
+ :param iterate_cb: function to call for each extent
+ :type iterate_cb: function acception arguments for offset,
+ length, and exists
+ :param include_parent: True if full history diff should include parent
+ :type include_parent: bool
+ :param whole_object: True if diff extents should cover whole object
+ :type whole_object: bool
+ :raises: :class:`InvalidArgument`, :class:`IOError`,
+ :class:`ImageNotFound`
+ """
+ from_snapshot = cstr(from_snapshot, 'from_snapshot', opt=True)
+ cdef:
+ char *_from_snapshot = opt_str(from_snapshot)
+ uint64_t _offset = offset, _length = length
+ uint8_t _include_parent = include_parent
+ uint8_t _whole_object = whole_object
+ with nogil:
+ ret = rbd_diff_iterate2(self.image, _from_snapshot, _offset,
+ _length, _include_parent, _whole_object,
+ &diff_iterate_cb, <void *>iterate_cb)
+ if ret < 0:
+ msg = 'error generating diff from snapshot %s' % from_snapshot
+ raise make_ex(ret, msg)
+
+ @requires_not_closed
+ def write(self, data, offset, fadvise_flags=0):
+ """
+ Write data to the image. Raises :class:`InvalidArgument` if
+ part of the write would fall outside the image.
+
+ :param data: the data to be written
+ :type data: bytes
+ :param offset: where to start writing data
+ :type offset: int
+ :param fadvise_flags: fadvise flags for this write
+ :type fadvise_flags: int
+ :returns: int - the number of bytes written
+ :raises: :class:`IncompleteWriteError`, :class:`LogicError`,
+ :class:`InvalidArgument`, :class:`IOError`
+ """
+ if not isinstance(data, bytes):
+ raise TypeError('data must be a byte string')
+ cdef:
+ uint64_t _offset = offset, length = len(data)
+ char *_data = data
+ int _fadvise_flags = fadvise_flags
+ with nogil:
+ ret = rbd_write2(self.image, _offset, length, _data, _fadvise_flags)
+
+ if ret == <ssize_t>length:
+ return ret
+ elif ret < 0:
+ raise make_ex(ret, "error writing to %s" % self.name)
+ elif ret < <ssize_t>length:
+ raise IncompleteWriteError("Wrote only %ld out of %ld bytes" % (ret, length))
+ else:
+ raise LogicError("logic error: rbd_write(%s) \
+returned %d, but %d was the maximum number of bytes it could have \
+written." % (self.name, ret, length))
+
+ @requires_not_closed
+ def discard(self, offset, length):
+ """
+ Trim the range from the image. It will be logically filled
+ with zeroes.
+ """
+ cdef uint64_t _offset = offset, _length = length
+ with nogil:
+ ret = rbd_discard(self.image, _offset, _length)
+ if ret < 0:
+ msg = 'error discarding region %d~%d' % (offset, length)
+ raise make_ex(ret, msg)
+
+ @requires_not_closed
+ def write_zeroes(self, offset, length, zero_flags = 0):
+ """
+ Zero the range from the image. By default it will attempt to
+ discard/unmap as much space as possible but any unaligned
+ extent segments will still be zeroed.
+ """
+ cdef:
+ uint64_t _offset = offset, _length = length
+ int _zero_flags = zero_flags
+ with nogil:
+ ret = rbd_write_zeroes(self.image, _offset, _length,
+ _zero_flags, 0)
+ if ret < 0:
+ msg = 'error zeroing region %d~%d' % (offset, length)
+ raise make_ex(ret, msg)
+
+ @requires_not_closed
+ def flush(self):
+ """
+ Block until all writes are fully flushed if caching is enabled.
+ """
+ with nogil:
+ ret = rbd_flush(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error flushing image')
+
+ @requires_not_closed
+ def invalidate_cache(self):
+ """
+ Drop any cached data for the image.
+ """
+ with nogil:
+ ret = rbd_invalidate_cache(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error invalidating cache')
+
+ @requires_not_closed
+ def stripe_unit(self):
+ """
+ Return the stripe unit used for the image.
+ """
+ cdef uint64_t stripe_unit
+ with nogil:
+ ret = rbd_get_stripe_unit(self.image, &stripe_unit)
+ if ret != 0:
+ raise make_ex(ret, 'error getting stripe unit for image %s' % (self.name))
+ return stripe_unit
+
+ @requires_not_closed
+ def stripe_count(self):
+ """
+ Return the stripe count used for the image.
+ """
+ cdef uint64_t stripe_count
+ with nogil:
+ ret = rbd_get_stripe_count(self.image, &stripe_count)
+ if ret != 0:
+ raise make_ex(ret, 'error getting stripe count for image %s' % (self.name))
+ return stripe_count
+
+ @requires_not_closed
+ def create_timestamp(self):
+ """
+ Return the create timestamp for the image.
+ """
+ cdef:
+ timespec timestamp
+ with nogil:
+ ret = rbd_get_create_timestamp(self.image, &timestamp)
+ if ret != 0:
+ raise make_ex(ret, 'error getting create timestamp for image: %s' % (self.name))
+ return datetime.utcfromtimestamp(timestamp.tv_sec)
+
+ @requires_not_closed
+ def access_timestamp(self):
+ """
+ Return the access timestamp for the image.
+ """
+ cdef:
+ timespec timestamp
+ with nogil:
+ ret = rbd_get_access_timestamp(self.image, &timestamp)
+ if ret != 0:
+ raise make_ex(ret, 'error getting access timestamp for image: %s' % (self.name))
+ return datetime.fromtimestamp(timestamp.tv_sec)
+
+ @requires_not_closed
+ def modify_timestamp(self):
+ """
+ Return the modify timestamp for the image.
+ """
+ cdef:
+ timespec timestamp
+ with nogil:
+ ret = rbd_get_modify_timestamp(self.image, &timestamp)
+ if ret != 0:
+ raise make_ex(ret, 'error getting modify timestamp for image: %s' % (self.name))
+ return datetime.fromtimestamp(timestamp.tv_sec)
+
+ @requires_not_closed
+ def flatten(self, on_progress=None):
+ """
+ Flatten clone image (copy all blocks from parent to child)
+ :param on_progress: optional progress callback function
+ :type on_progress: callback function
+ """
+ cdef:
+ librbd_progress_fn_t _prog_cb = &no_op_progress_callback
+ void *_prog_arg = NULL
+ if on_progress:
+ _prog_cb = &progress_callback
+ _prog_arg = <void *>on_progress
+ with nogil:
+ ret = rbd_flatten_with_progress(self.image, _prog_cb, _prog_arg)
+ if ret < 0:
+ raise make_ex(ret, "error flattening %s" % self.name)
+
+ @requires_not_closed
+ def sparsify(self, sparse_size):
+ """
+ Reclaim space for zeroed image extents
+ """
+ cdef:
+ size_t _sparse_size = sparse_size
+ with nogil:
+ ret = rbd_sparsify(self.image, _sparse_size)
+ if ret < 0:
+ raise make_ex(ret, "error sparsifying %s" % self.name)
+
+ @requires_not_closed
+ def rebuild_object_map(self):
+ """
+ Rebuild the object map for the image HEAD or currently set snapshot
+ """
+ cdef librbd_progress_fn_t prog_cb = &no_op_progress_callback
+ with nogil:
+ ret = rbd_rebuild_object_map(self.image, prog_cb, NULL)
+ if ret < 0:
+ raise make_ex(ret, "error rebuilding object map %s" % self.name)
+
+ @requires_not_closed
+ def list_children(self):
+ """
+ List children of the currently set snapshot (set via set_snap()).
+
+ :returns: list - a list of (pool name, image name) tuples
+ """
+ cdef:
+ rbd_linked_image_spec_t *children = NULL
+ size_t num_children = 10
+
+ try:
+ while True:
+ children = <rbd_linked_image_spec_t*>realloc_chk(
+ children, num_children * sizeof(rbd_linked_image_spec_t))
+ with nogil:
+ ret = rbd_list_children3(self.image, children,
+ &num_children)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing children.')
+
+ return [(decode_cstr(x.pool_name), decode_cstr(x.image_name)) for x
+ in children[:num_children] if not x.trash]
+ finally:
+ if children:
+ rbd_linked_image_spec_list_cleanup(children, num_children)
+ free(children)
+
+ @requires_not_closed
+ def list_children2(self):
+ """
+ Iterate over the children of the image or its snapshot.
+
+ :returns: :class:`ChildIterator`
+ """
+ return ChildIterator(self)
+
+ @requires_not_closed
+ def list_descendants(self):
+ """
+ Iterate over the descendants of the image.
+
+ :returns: :class:`ChildIterator`
+ """
+ return ChildIterator(self, True)
+
+ @requires_not_closed
+ def list_lockers(self):
+ """
+ List clients that have locked the image and information
+ about the lock.
+
+ :returns: dict - contains the following keys:
+
+ * ``tag`` - the tag associated with the lock (every
+ additional locker must use the same tag)
+ * ``exclusive`` - boolean indicating whether the
+ lock is exclusive or shared
+ * ``lockers`` - a list of (client, cookie, address)
+ tuples
+ """
+ cdef:
+ size_t clients_size = 512, cookies_size = 512
+ size_t addrs_size = 512, tag_size = 512
+ int exclusive = 0
+ char *c_clients = NULL
+ char *c_cookies = NULL
+ char *c_addrs = NULL
+ char *c_tag = NULL
+
+ try:
+ while True:
+ c_clients = <char *>realloc_chk(c_clients, clients_size)
+ c_cookies = <char *>realloc_chk(c_cookies, cookies_size)
+ c_addrs = <char *>realloc_chk(c_addrs, addrs_size)
+ c_tag = <char *>realloc_chk(c_tag, tag_size)
+ with nogil:
+ ret = rbd_list_lockers(self.image, &exclusive,
+ c_tag, &tag_size,
+ c_clients, &clients_size,
+ c_cookies, &cookies_size,
+ c_addrs, &addrs_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing images')
+ if ret == 0:
+ return []
+ clients = map(decode_cstr, c_clients[:clients_size - 1].split(b'\0'))
+ cookies = map(decode_cstr, c_cookies[:cookies_size - 1].split(b'\0'))
+ addrs = map(decode_cstr, c_addrs[:addrs_size - 1].split(b'\0'))
+ return {
+ 'tag' : decode_cstr(c_tag),
+ 'exclusive' : exclusive == 1,
+ 'lockers' : list(zip(clients, cookies, addrs)),
+ }
+ finally:
+ free(c_clients)
+ free(c_cookies)
+ free(c_addrs)
+ free(c_tag)
+
+ @requires_not_closed
+ def lock_acquire(self, lock_mode):
+ """
+ Acquire a managed lock on the image.
+
+ :param lock_mode: lock mode to set
+ :type lock_mode: int
+ :raises: :class:`ImageBusy` if the lock could not be acquired
+ """
+ cdef:
+ rbd_lock_mode_t _lock_mode = lock_mode
+ with nogil:
+ ret = rbd_lock_acquire(self.image, _lock_mode)
+ if ret < 0:
+ raise make_ex(ret, 'error acquiring lock on image')
+
+ @requires_not_closed
+ def lock_release(self):
+ """
+ Release a managed lock on the image that was previously acquired.
+ """
+ with nogil:
+ ret = rbd_lock_release(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error releasing lock on image')
+
+ @requires_not_closed
+ def lock_get_owners(self):
+ """
+ Iterate over the lock owners of an image.
+
+ :returns: :class:`LockOwnerIterator`
+ """
+ return LockOwnerIterator(self)
+
+ @requires_not_closed
+ def lock_break(self, lock_mode, lock_owner):
+ """
+ Break the image lock held by a another client.
+
+ :param lock_owner: the owner of the lock to break
+ :type lock_owner: str
+ """
+ lock_owner = cstr(lock_owner, 'lock_owner')
+ cdef:
+ rbd_lock_mode_t _lock_mode = lock_mode
+ char *_lock_owner = lock_owner
+ with nogil:
+ ret = rbd_lock_break(self.image, _lock_mode, _lock_owner)
+ if ret < 0:
+ raise make_ex(ret, 'error breaking lock on image')
+
+ @requires_not_closed
+ def lock_exclusive(self, cookie):
+ """
+ Take an exclusive lock on the image.
+
+ :raises: :class:`ImageBusy` if a different client or cookie locked it
+ :class:`ImageExists` if the same client and cookie locked it
+ """
+ cookie = cstr(cookie, 'cookie')
+ cdef char *_cookie = cookie
+ with nogil:
+ ret = rbd_lock_exclusive(self.image, _cookie)
+ if ret < 0:
+ raise make_ex(ret, 'error acquiring exclusive lock on image')
+
+ @requires_not_closed
+ def lock_shared(self, cookie, tag):
+ """
+ Take a shared lock on the image. The tag must match
+ that of the existing lockers, if any.
+
+ :raises: :class:`ImageBusy` if a different client or cookie locked it
+ :class:`ImageExists` if the same client and cookie locked it
+ """
+ cookie = cstr(cookie, 'cookie')
+ tag = cstr(tag, 'tag')
+ cdef:
+ char *_cookie = cookie
+ char *_tag = tag
+ with nogil:
+ ret = rbd_lock_shared(self.image, _cookie, _tag)
+ if ret < 0:
+ raise make_ex(ret, 'error acquiring shared lock on image')
+
+ @requires_not_closed
+ def unlock(self, cookie):
+ """
+ Release a lock on the image that was locked by this rados client.
+ """
+ cookie = cstr(cookie, 'cookie')
+ cdef char *_cookie = cookie
+ with nogil:
+ ret = rbd_unlock(self.image, _cookie)
+ if ret < 0:
+ raise make_ex(ret, 'error unlocking image')
+
+ @requires_not_closed
+ def break_lock(self, client, cookie):
+ """
+ Release a lock held by another rados client.
+ """
+ client = cstr(client, 'client')
+ cookie = cstr(cookie, 'cookie')
+ cdef:
+ char *_client = client
+ char *_cookie = cookie
+ with nogil:
+ ret = rbd_break_lock(self.image, _client, _cookie)
+ if ret < 0:
+ raise make_ex(ret, 'error unlocking image')
+
+ @requires_not_closed
+ def mirror_image_enable(self):
+ """
+ Enable mirroring for the image.
+ """
+ with nogil:
+ ret = rbd_mirror_image_enable(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error enabling mirroring for image %s' % self.name)
+
+ @requires_not_closed
+ def mirror_image_disable(self, force):
+ """
+ Disable mirroring for the image.
+
+ :param force: force disabling
+ :type force: bool
+ """
+ cdef bint c_force = force
+ with nogil:
+ ret = rbd_mirror_image_disable(self.image, c_force)
+ if ret < 0:
+ raise make_ex(ret, 'error disabling mirroring for image %s' % self.name)
+
+ @requires_not_closed
+ def mirror_image_promote(self, force):
+ """
+ Promote the image to primary for mirroring.
+
+ :param force: force promoting
+ :type force: bool
+ """
+ cdef bint c_force = force
+ with nogil:
+ ret = rbd_mirror_image_promote(self.image, c_force)
+ if ret < 0:
+ raise make_ex(ret, 'error promoting image %s to primary' % self.name)
+
+ @requires_not_closed
+ def mirror_image_demote(self):
+ """
+ Demote the image to secondary for mirroring.
+ """
+ with nogil:
+ ret = rbd_mirror_image_demote(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error demoting image %s to secondary' % self.name)
+
+ @requires_not_closed
+ def mirror_image_resync(self):
+ """
+ Flag the image to resync.
+ """
+ with nogil:
+ ret = rbd_mirror_image_resync(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error to resync image %s' % self.name)
+
+ @requires_not_closed
+ def mirror_image_get_info(self):
+ """
+ Get mirror info for the image.
+
+ :returns: dict - contains the following keys:
+
+ * ``global_id`` (str) - image global id
+
+ * ``state`` (int) - mirror state
+
+ * ``primary`` (bool) - is image primary
+ """
+ cdef rbd_mirror_image_info_t c_info
+ with nogil:
+ ret = rbd_mirror_image_get_info(self.image, &c_info, sizeof(c_info))
+ if ret != 0:
+ raise make_ex(ret, 'error getting mirror info for image %s' % self.name)
+ info = {
+ 'global_id' : decode_cstr(c_info.global_id),
+ 'state' : int(c_info.state),
+ 'primary' : c_info.primary,
+ }
+ free(c_info.global_id)
+ return info
+
+ @requires_not_closed
+ def mirror_image_get_status(self):
+ """
+ Get mirror status for the image.
+
+ :returns: dict - contains the following keys:
+
+ * ``name`` (str) - mirror image name
+
+ * ``id`` (str) - mirror image id
+
+ * `info` (dict) - mirror image info
+
+ * ``state`` (int) - status mirror state
+
+ * ``description`` (str) - status description
+
+ * ``last_update`` (datetime) - last status update time
+
+ * ``up`` (bool) - is mirroring agent up
+ """
+ cdef rbd_mirror_image_status_t c_status
+ with nogil:
+ ret = rbd_mirror_image_get_status(self.image, &c_status,
+ sizeof(c_status))
+ if ret != 0:
+ raise make_ex(ret, 'error getting mirror status for image %s' % self.name)
+ status = {
+ 'name' : decode_cstr(c_status.name),
+ 'id' : self.id(),
+ 'info' : {
+ 'global_id' : decode_cstr(c_status.info.global_id),
+ 'state' : int(c_status.info.state),
+ 'primary' : c_status.info.primary,
+ },
+ 'state' : c_status.state,
+ 'description' : decode_cstr(c_status.description),
+ 'last_update' : datetime.utcfromtimestamp(c_status.last_update),
+ 'up' : c_status.up,
+ }
+ free(c_status.name)
+ free(c_status.info.global_id)
+ free(c_status.description)
+ return status
+
+ @requires_not_closed
+ def mirror_image_get_instance_id(self):
+ """
+ Get mirror instance id for the image.
+
+ :returns: str - instance id
+ """
+ cdef:
+ int ret = -errno.ERANGE
+ size_t size = 32
+ char *instance_id = NULL
+ try:
+ while ret == -errno.ERANGE and size <= 4096:
+ instance_id = <char *>realloc_chk(instance_id, size)
+ with nogil:
+ ret = rbd_mirror_image_get_instance_id(self.image,
+ instance_id, &size)
+ if ret != 0:
+ raise make_ex(ret,
+ 'error getting mirror instance id for image %s' %
+ self.name)
+ return decode_cstr(instance_id)
+ finally:
+ free(instance_id)
+
+ @requires_not_closed
+ def aio_read(self, offset, length, oncomplete, fadvise_flags=0):
+ """
+ Asynchronously read data from the image
+
+ Raises :class:`InvalidArgument` if part of the range specified is
+ outside the image.
+
+ oncomplete will be called with the returned read value as
+ well as the completion:
+
+ oncomplete(completion, data_read)
+
+ :param offset: the offset to start reading at
+ :type offset: int
+ :param length: how many bytes to read
+ :type length: int
+ :param oncomplete: what to do when the read is complete
+ :type oncomplete: completion
+ :param fadvise_flags: fadvise flags for this read
+ :type fadvise_flags: int
+ :returns: :class:`Completion` - the completion object
+ :raises: :class:`InvalidArgument`, :class:`IOError`
+ """
+ cdef:
+ char *ret_buf
+ uint64_t _offset = offset
+ size_t _length = length
+ int _fadvise_flags = fadvise_flags
+ Completion completion
+
+ def oncomplete_(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ if return_value > 0 and return_value != length:
+ _PyBytes_Resize(&_completion_v.buf, return_value)
+ return oncomplete(_completion_v, <object>_completion_v.buf if return_value >= 0 else None)
+
+ completion = self.__get_completion(oncomplete_)
+ completion.buf = PyBytes_FromStringAndSize(NULL, length)
+ ret_buf = PyBytes_AsString(completion.buf)
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_read2(self.image, _offset, _length, ret_buf,
+ completion.rbd_comp, _fadvise_flags)
+ if ret < 0:
+ raise make_ex(ret, 'error reading %s %ld~%ld' %
+ (self.name, offset, length))
+ except:
+ completion.__unpersist()
+ raise
+
+ return completion
+
+ @requires_not_closed
+ def aio_write(self, data, offset, oncomplete, fadvise_flags=0):
+ """
+ Asynchronously write data to the image
+
+ Raises :class:`InvalidArgument` if part of the write would fall outside
+ the image.
+
+ oncomplete will be called with the completion:
+
+ oncomplete(completion)
+
+ :param data: the data to be written
+ :type data: bytes
+ :param offset: the offset to start writing at
+ :type offset: int
+ :param oncomplete: what to do when the write is complete
+ :type oncomplete: completion
+ :param fadvise_flags: fadvise flags for this write
+ :type fadvise_flags: int
+ :returns: :class:`Completion` - the completion object
+ :raises: :class:`InvalidArgument`, :class:`IOError`
+ """
+ cdef:
+ uint64_t _offset = offset
+ char *_data = data
+ size_t _length = len(data)
+ int _fadvise_flags = fadvise_flags
+ Completion completion
+
+ completion = self.__get_completion(oncomplete)
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_write2(self.image, _offset, _length, _data,
+ completion.rbd_comp, _fadvise_flags)
+ if ret < 0:
+ raise make_ex(ret, 'error writing %s %ld~%ld' %
+ (self.name, offset, _length))
+ except:
+ completion.__unpersist()
+ raise
+
+ return completion
+
+ @requires_not_closed
+ def aio_discard(self, offset, length, oncomplete):
+ """
+ Asynchronously trim the range from the image. It will be logically
+ filled with zeroes.
+ """
+ cdef:
+ uint64_t _offset = offset
+ size_t _length = length
+ Completion completion
+
+ completion = self.__get_completion(oncomplete)
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_discard(self.image, _offset, _length,
+ completion.rbd_comp)
+ if ret < 0:
+ raise make_ex(ret, 'error discarding %s %ld~%ld' %
+ (self.name, offset, _length))
+ except:
+ completion.__unpersist()
+ raise
+
+ return completion
+
+ @requires_not_closed
+ def aio_write_zeroes(self, offset, length, oncomplete, zero_flags = 0):
+ """
+ Asynchronously Zero the range from the image. By default it will attempt
+ to discard/unmap as much space as possible but any unaligned extent
+ segments will still be zeroed.
+ """
+ cdef:
+ uint64_t _offset = offset
+ size_t _length = length
+ int _zero_flags = zero_flags
+ Completion completion
+
+ completion = self.__get_completion(oncomplete)
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_write_zeroes(self.image, _offset, _length,
+ completion.rbd_comp, _zero_flags, 0)
+ if ret < 0:
+ raise make_ex(ret, 'error zeroing %s %ld~%ld' %
+ (self.name, offset, length))
+ except:
+ completion.__unpersist()
+ raise
+
+ return completion
+
+ @requires_not_closed
+ def aio_flush(self, oncomplete):
+ """
+ Asynchronously wait until all writes are fully flushed if caching is
+ enabled.
+ """
+ cdef Completion completion = self.__get_completion(oncomplete)
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_flush(self.image, completion.rbd_comp)
+ if ret < 0:
+ raise make_ex(ret, 'error flushing')
+ except:
+ completion.__unpersist()
+ raise
+
+ return completion
+
+ @requires_not_closed
+ def metadata_get(self, key):
+ """
+ Get image metadata for the given key.
+
+ :param key: metadata key
+ :type key: str
+ :returns: str - metadata value
+ """
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ size_t size = 4096
+ char *value = NULL
+ int ret
+ try:
+ while True:
+ value = <char *>realloc_chk(value, size)
+ with nogil:
+ ret = rbd_metadata_get(self.image, _key, value, &size)
+ if ret != -errno.ERANGE:
+ break
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s for image %s' % (key, self.name))
+ if ret != 0:
+ raise make_ex(ret, 'error getting metadata %s for image %s' %
+ (key, self.name))
+ return decode_cstr(value)
+ finally:
+ free(value)
+
+ @requires_not_closed
+ def metadata_set(self, key, value):
+ """
+ Set image metadata for the given key.
+
+ :param key: metadata key
+ :type key: str
+ :param value: metadata value
+ :type value: str
+ """
+ key = cstr(key, 'key')
+ value = cstr(value, 'value')
+ cdef:
+ char *_key = key
+ char *_value = value
+ with nogil:
+ ret = rbd_metadata_set(self.image, _key, _value)
+
+ if ret != 0:
+ raise make_ex(ret, 'error setting metadata %s for image %s' %
+ (key, self.name))
+
+ @requires_not_closed
+ def metadata_remove(self, key):
+ """
+ Remove image metadata for the given key.
+
+ :param key: metadata key
+ :type key: str
+ """
+ key = cstr(key, 'key')
+ cdef:
+ char *_key = key
+ with nogil:
+ ret = rbd_metadata_remove(self.image, _key)
+
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s for image %s' % (key, self.name))
+ if ret != 0:
+ raise make_ex(ret, 'error removing metadata %s for image %s' %
+ (key, self.name))
+
+ @requires_not_closed
+ def metadata_list(self):
+ """
+ List image metadata.
+
+ :returns: :class:`MetadataIterator`
+ """
+ return MetadataIterator(self)
+
+ @requires_not_closed
+ def watchers_list(self):
+ """
+ List image watchers.
+
+ :returns: :class:`WatcherIterator`
+ """
+ return WatcherIterator(self)
+
+ @requires_not_closed
+ def config_list(self):
+ """
+ List image-level config overrides.
+
+ :returns: :class:`ConfigPoolIterator`
+ """
+ return ConfigImageIterator(self)
+
+ @requires_not_closed
+ def snap_get_namespace_type(self, snap_id):
+ """
+ Get the snapshot namespace type.
+ :param snap_id: the snapshot id of a snap shot
+ :type key: int
+ """
+ cdef:
+ rbd_snap_namespace_type_t namespace_type
+ uint64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_get_namespace_type(self.image, _snap_id, &namespace_type)
+ if ret != 0:
+ raise make_ex(ret, 'error getting snapshot namespace type for image: %s, snap_id: %d' % (self.name, snap_id))
+
+ return namespace_type
+
+ @requires_not_closed
+ def snap_get_group_namespace(self, snap_id):
+ """
+ get the group namespace details.
+ :param snap_id: the snapshot id of the group snapshot
+ :type key: int
+ :returns: dict - contains the following keys:
+
+ * ``pool`` (int) - pool id
+
+ * ``name`` (str) - group name
+
+ * ``snap_name`` (str) - group snap name
+ """
+ cdef:
+ rbd_snap_group_namespace_t group_namespace
+ uint64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_get_group_namespace(self.image, _snap_id,
+ &group_namespace,
+ sizeof(rbd_snap_group_namespace_t))
+ if ret != 0:
+ raise make_ex(ret, 'error getting snapshot group namespace for image: %s, snap_id: %d' % (self.name, snap_id))
+
+ info = {
+ 'pool' : group_namespace.group_pool,
+ 'name' : decode_cstr(group_namespace.group_name),
+ 'snap_name' : decode_cstr(group_namespace.group_snap_name)
+ }
+ rbd_snap_group_namespace_cleanup(&group_namespace,
+ sizeof(rbd_snap_group_namespace_t))
+ return info
+
+ @requires_not_closed
+ def snap_get_trash_namespace(self, snap_id):
+ """
+ get the trash namespace details.
+ :param snap_id: the snapshot id of the trash snapshot
+ :type key: int
+ :returns: dict - contains the following keys:
+
+ * ``original_name`` (str) - original snap name
+ """
+ cdef:
+ uint64_t _snap_id = snap_id
+ size_t _size = 512
+ char *_name = NULL
+ try:
+ while True:
+ _name = <char*>realloc_chk(_name, _size);
+ with nogil:
+ ret = rbd_snap_get_trash_namespace(self.image, _snap_id,
+ _name, _size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error getting snapshot trash '
+ 'namespace image: %s, snap_id: %d' % (self.name, snap_id))
+ return {
+ 'original_name' : decode_cstr(_name)
+ }
+ finally:
+ free(_name)
+
+
+cdef class ImageIterator(object):
+ """
+ Iterator over RBD images in a pool
+
+ Yields a dictionary containing information about the images
+
+ Keys are:
+
+ * ``id`` (str) - image id
+
+ * ``name`` (str) - image name
+ """
+ cdef rados_ioctx_t ioctx
+ cdef rbd_image_spec_t *images
+ cdef size_t num_images
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.images = NULL
+ self.num_images = 1024
+ while True:
+ self.images = <rbd_image_spec_t*>realloc_chk(
+ self.images, self.num_images * sizeof(rbd_image_spec_t))
+ with nogil:
+ ret = rbd_list2(self.ioctx, self.images, &self.num_images)
+ if ret >= 0:
+ break
+ elif ret == -errno.ERANGE:
+ self.num_images *= 2
+ else:
+ raise make_ex(ret, 'error listing images.')
+
+ def __iter__(self):
+ for i in range(self.num_images):
+ yield {
+ 'id' : decode_cstr(self.images[i].id),
+ 'name' : decode_cstr(self.images[i].name)
+ }
+
+ def __dealloc__(self):
+ if self.images:
+ rbd_image_spec_list_cleanup(self.images, self.num_images)
+ free(self.images)
+
+
+cdef class LockOwnerIterator(object):
+ """
+ Iterator over managed lock owners for an image
+
+ Yields a dictionary containing information about the image's lock
+
+ Keys are:
+
+ * ``mode`` (int) - active lock mode
+
+ * ``owner`` (str) - lock owner name
+ """
+
+ cdef:
+ rbd_lock_mode_t lock_mode
+ char **lock_owners
+ size_t num_lock_owners
+ object image
+
+ def __init__(self, Image image):
+ image.require_not_closed()
+
+ self.image = image
+ self.lock_owners = NULL
+ self.num_lock_owners = 8
+ while True:
+ self.lock_owners = <char**>realloc_chk(self.lock_owners,
+ self.num_lock_owners *
+ sizeof(char*))
+ with nogil:
+ ret = rbd_lock_get_owners(image.image, &self.lock_mode,
+ self.lock_owners,
+ &self.num_lock_owners)
+ if ret >= 0:
+ break
+ elif ret == -errno.ENOENT:
+ self.num_lock_owners = 0
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing lock owners for image %s' % image.name)
+
+ def __iter__(self):
+ for i in range(self.num_lock_owners):
+ yield {
+ 'mode' : int(self.lock_mode),
+ 'owner' : decode_cstr(self.lock_owners[i]),
+ }
+
+ def __dealloc__(self):
+ if self.lock_owners:
+ rbd_lock_get_owners_cleanup(self.lock_owners, self.num_lock_owners)
+ free(self.lock_owners)
+
+cdef class MetadataIterator(object):
+ """
+ Iterator over metadata list for an image.
+
+ Yields ``(key, value)`` tuple.
+
+ * ``key`` (str) - metadata key
+ * ``value`` (str) - metadata value
+ """
+
+ cdef:
+ cdef object image
+ rbd_image_t c_image
+ char *last_read
+ uint64_t max_read
+ object next_chunk
+
+ def __init__(self, Image image):
+ image.require_not_closed()
+
+ self.image = image
+ self.c_image = image.image
+ self.last_read = strdup("")
+ self.max_read = 32
+ self.get_next_chunk()
+
+ def __iter__(self):
+ while len(self.next_chunk) > 0:
+ for pair in self.next_chunk:
+ yield pair
+ if len(self.next_chunk) < self.max_read:
+ break
+ self.get_next_chunk()
+
+ def __dealloc__(self):
+ if self.last_read:
+ free(self.last_read)
+
+ def get_next_chunk(self):
+ self.image.require_not_closed()
+
+ cdef:
+ char *c_keys = NULL
+ size_t keys_size = 4096
+ char *c_vals = NULL
+ size_t vals_size = 4096
+ try:
+ while True:
+ c_keys = <char *>realloc_chk(c_keys, keys_size)
+ c_vals = <char *>realloc_chk(c_vals, vals_size)
+ with nogil:
+ ret = rbd_metadata_list(self.c_image, self.last_read,
+ self.max_read, c_keys, &keys_size,
+ c_vals, &vals_size)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing metadata for image %s' %
+ self.image.name)
+ keys = [decode_cstr(key) for key in
+ c_keys[:keys_size].split(b'\0') if key]
+ vals = [decode_cstr(val) for val in
+ c_vals[:vals_size].split(b'\0') if val]
+ if len(keys) > 0:
+ last_read = cstr(keys[-1], 'last_read')
+ free(self.last_read)
+ self.last_read = strdup(last_read)
+ self.next_chunk = list(zip(keys, vals))
+ finally:
+ free(c_keys)
+ free(c_vals)
+
+cdef class SnapIterator(object):
+ """
+ Iterator over snapshot info for an image.
+
+ Yields a dictionary containing information about a snapshot.
+
+ Keys are:
+
+ * ``id`` (int) - numeric identifier of the snapshot
+
+ * ``size`` (int) - size of the image at the time of snapshot (in bytes)
+
+ * ``name`` (str) - name of the snapshot
+
+ * ``namespace`` (int) - enum for snap namespace
+
+ * ``group`` (dict) - optional for group namespace snapshots
+
+ * ``trash`` (dict) - optional for trash namespace snapshots
+ """
+
+ cdef rbd_snap_info_t *snaps
+ cdef int num_snaps
+ cdef object image
+
+ def __init__(self, Image image):
+ image.require_not_closed()
+
+ self.image = image
+ self.snaps = NULL
+ self.num_snaps = 10
+ while True:
+ self.snaps = <rbd_snap_info_t*>realloc_chk(self.snaps,
+ self.num_snaps *
+ sizeof(rbd_snap_info_t))
+ with nogil:
+ ret = rbd_snap_list(image.image, self.snaps, &self.num_snaps)
+ if ret >= 0:
+ self.num_snaps = ret
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing snapshots for image %s' % image.name)
+
+ def __iter__(self):
+ for i in range(self.num_snaps):
+ s = {
+ 'id' : self.snaps[i].id,
+ 'size' : self.snaps[i].size,
+ 'name' : decode_cstr(self.snaps[i].name),
+ 'namespace' : self.image.snap_get_namespace_type(self.snaps[i].id)
+ }
+ if s['namespace'] == RBD_SNAP_NAMESPACE_TYPE_GROUP:
+ try:
+ group = self.image.snap_get_group_namespace(self.snaps[i].id)
+ except:
+ group = None
+ s['group'] = group
+ elif s['namespace'] == RBD_SNAP_NAMESPACE_TYPE_TRASH:
+ try:
+ trash = self.image.snap_get_trash_namespace(self.snaps[i].id)
+ except:
+ trash = None
+ s['trash'] = trash
+ yield s
+
+ def __dealloc__(self):
+ if self.snaps:
+ rbd_snap_list_end(self.snaps)
+ free(self.snaps)
+
+cdef class TrashIterator(object):
+ """
+ Iterator over trash entries.
+
+ Yields a dictionary containing trash info of an image.
+
+ Keys are:
+
+ * `id` (str) - image id
+
+ * `name` (str) - image name
+
+ * `source` (str) - source of deletion
+
+ * `deletion_time` (datetime) - time of deletion
+
+ * `deferment_end_time` (datetime) - time that an image is allowed to be
+ removed from trash
+ """
+
+ cdef:
+ rados_ioctx_t ioctx
+ size_t num_entries
+ rbd_trash_image_info_t *entries
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.num_entries = 1024
+ self.entries = NULL
+ while True:
+ self.entries = <rbd_trash_image_info_t*>realloc_chk(self.entries,
+ self.num_entries *
+ sizeof(rbd_trash_image_info_t))
+ with nogil:
+ ret = rbd_trash_list(self.ioctx, self.entries, &self.num_entries)
+ if ret >= 0:
+ self.num_entries = ret
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing trash entries')
+
+ __source_string = ['USER', 'MIRRORING']
+
+ def __iter__(self):
+ for i in range(self.num_entries):
+ yield {
+ 'id' : decode_cstr(self.entries[i].id),
+ 'name' : decode_cstr(self.entries[i].name),
+ 'source' : TrashIterator.__source_string[self.entries[i].source],
+ 'deletion_time' : datetime.utcfromtimestamp(self.entries[i].deletion_time),
+ 'deferment_end_time' : datetime.utcfromtimestamp(self.entries[i].deferment_end_time)
+ }
+
+ def __dealloc__(self):
+ rbd_trash_list_cleanup(self.entries, self.num_entries)
+ if self.entries:
+ free(self.entries)
+
+cdef class ChildIterator(object):
+ """
+ Iterator over child info for the image or its snapshot.
+
+ Yields a dictionary containing information about a child.
+
+ Keys are:
+
+ * ``pool`` (str) - name of the pool
+
+ * ``pool_namespace`` (str) - namespace of the pool
+
+ * ``image`` (str) - name of the child
+
+ * ``id`` (str) - id of the child
+
+ * ``trash`` (bool) - True if child is in trash bin
+ """
+
+ cdef rbd_linked_image_spec_t *children
+ cdef size_t num_children
+ cdef object image
+
+ def __init__(self, Image image, descendants=False):
+ image.require_not_closed()
+
+ self.image = image
+ self.children = NULL
+ self.num_children = 10
+ while True:
+ self.children = <rbd_linked_image_spec_t*>realloc_chk(
+ self.children, self.num_children * sizeof(rbd_linked_image_spec_t))
+ if descendants:
+ with nogil:
+ ret = rbd_list_descendants(image.image, self.children,
+ &self.num_children)
+ else:
+ with nogil:
+ ret = rbd_list_children3(image.image, self.children,
+ &self.num_children)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing children.')
+
+ def __iter__(self):
+ for i in range(self.num_children):
+ yield {
+ 'pool' : decode_cstr(self.children[i].pool_name),
+ 'pool_namespace' : decode_cstr(self.children[i].pool_namespace),
+ 'image' : decode_cstr(self.children[i].image_name),
+ 'id' : decode_cstr(self.children[i].image_id),
+ 'trash' : self.children[i].trash
+ }
+
+ def __dealloc__(self):
+ if self.children:
+ rbd_linked_image_spec_list_cleanup(self.children, self.num_children)
+ free(self.children)
+
+cdef class WatcherIterator(object):
+ """
+ Iterator over watchers of an image.
+
+ Yields a dictionary containing information about a watcher.
+
+ Keys are:
+
+ * ``addr`` (str) - address of the watcher
+
+ * ``id`` (int) - id of the watcher
+
+ * ``cookie`` (int) - the watcher's cookie
+ """
+
+ cdef rbd_image_watcher_t *watchers
+ cdef size_t num_watchers
+ cdef object image
+
+ def __init__(self, Image image):
+ image.require_not_closed()
+
+ self.image = image
+ self.watchers = NULL
+ self.num_watchers = 10
+ while True:
+ self.watchers = <rbd_image_watcher_t*>realloc_chk(self.watchers,
+ self.num_watchers *
+ sizeof(rbd_image_watcher_t))
+ with nogil:
+ ret = rbd_watchers_list(image.image, self.watchers, &self.num_watchers)
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing watchers.')
+
+ def __iter__(self):
+ for i in range(self.num_watchers):
+ yield {
+ 'addr' : decode_cstr(self.watchers[i].addr),
+ 'id' : self.watchers[i].id,
+ 'cookie' : self.watchers[i].cookie
+ }
+
+ def __dealloc__(self):
+ if self.watchers:
+ rbd_watchers_list_cleanup(self.watchers, self.num_watchers)
+ free(self.watchers)
+
+cdef class ConfigImageIterator(object):
+ """
+ Iterator over image-level overrides for an image.
+
+ Yields a dictionary containing information about an override.
+
+ Keys are:
+
+ * ``name`` (str) - override name
+
+ * ``value`` (str) - override value
+
+ * ``source`` (str) - override source
+ """
+
+ cdef:
+ rbd_config_option_t *options
+ int num_options
+
+ def __init__(self, Image image):
+ image.require_not_closed()
+
+ self.options = NULL
+ self.num_options = 32
+ while True:
+ self.options = <rbd_config_option_t *>realloc_chk(
+ self.options, self.num_options * sizeof(rbd_config_option_t))
+ with nogil:
+ ret = rbd_config_image_list(image.image, self.options,
+ &self.num_options)
+ if ret < 0:
+ if ret == -errno.ERANGE:
+ continue
+ self.num_options = 0
+ raise make_ex(ret, 'error listing config options')
+ break
+
+ def __iter__(self):
+ for i in range(self.num_options):
+ yield {
+ 'name' : decode_cstr(self.options[i].name),
+ 'value' : decode_cstr(self.options[i].value),
+ 'source' : self.options[i].source,
+ }
+
+ def __dealloc__(self):
+ if self.options:
+ rbd_config_image_list_cleanup(self.options, self.num_options)
+ free(self.options)
+
+cdef class GroupImageIterator(object):
+ """
+ Iterator over image info for a group.
+
+ Yields a dictionary containing information about an image.
+
+ Keys are:
+
+ * ``name`` (str) - name of the image
+
+ * ``pool`` (int) - id of the pool this image belongs to
+
+ * ``state`` (int) - state of the image
+ """
+
+ cdef rbd_group_image_info_t *images
+ cdef size_t num_images
+ cdef object group
+
+ def __init__(self, Group group):
+ self.group = group
+ self.images = NULL
+ self.num_images = 10
+ while True:
+ self.images = <rbd_group_image_info_t*>realloc_chk(self.images,
+ self.num_images *
+ sizeof(rbd_group_image_info_t))
+ with nogil:
+ ret = rbd_group_image_list(group._ioctx, group._name,
+ self.images,
+ sizeof(rbd_group_image_info_t),
+ &self.num_images)
+
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing images for group %s' % group.name, group_errno_to_exception)
+
+ def __iter__(self):
+ for i in range(self.num_images):
+ yield {
+ 'name' : decode_cstr(self.images[i].name),
+ 'pool' : self.images[i].pool,
+ 'state' : self.images[i].state,
+ }
+
+ def __dealloc__(self):
+ if self.images:
+ rbd_group_image_list_cleanup(self.images,
+ sizeof(rbd_group_image_info_t),
+ self.num_images)
+ free(self.images)
+
+cdef class GroupSnapIterator(object):
+ """
+ Iterator over snaps specs for a group.
+
+ Yields a dictionary containing information about a snapshot.
+
+ Keys are:
+
+ * ``name`` (str) - name of the snapshot
+
+ * ``state`` (int) - state of the snapshot
+ """
+
+ cdef rbd_group_snap_info_t *snaps
+ cdef size_t num_snaps
+ cdef object group
+
+ def __init__(self, Group group):
+ self.group = group
+ self.snaps = NULL
+ self.num_snaps = 10
+ while True:
+ self.snaps = <rbd_group_snap_info_t*>realloc_chk(self.snaps,
+ self.num_snaps *
+ sizeof(rbd_group_snap_info_t))
+ with nogil:
+ ret = rbd_group_snap_list(group._ioctx, group._name, self.snaps,
+ sizeof(rbd_group_snap_info_t),
+ &self.num_snaps)
+
+ if ret >= 0:
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing snapshots for group %s' % group.name, group_errno_to_exception)
+
+ def __iter__(self):
+ for i in range(self.num_snaps):
+ yield {
+ 'name' : decode_cstr(self.snaps[i].name),
+ 'state' : self.snaps[i].state,
+ }
+
+ def __dealloc__(self):
+ if self.snaps:
+ rbd_group_snap_list_cleanup(self.snaps,
+ sizeof(rbd_group_snap_info_t),
+ self.num_snaps)
+ free(self.snaps)
diff --git a/src/pybind/rbd/setup.py b/src/pybind/rbd/setup.py
new file mode 100755
index 00000000..8dd5c12a
--- /dev/null
+++ b/src/pybind/rbd/setup.py
@@ -0,0 +1,223 @@
+from __future__ import print_function
+
+import os
+import pkgutil
+import shutil
+import subprocess
+import sys
+import tempfile
+import textwrap
+from distutils.ccompiler import new_compiler
+from distutils.errors import CompileError, LinkError
+import distutils.sysconfig
+
+unwrapped_customize = distutils.sysconfig.customize_compiler
+
+clang = False
+
+def filter_unsupported_flags(flags):
+ if clang:
+ return [f for f in flags if not (f == '-mcet' or
+ f.startswith('-fcf-protection'))]
+ else:
+ return flags
+
+def monkey_with_compiler(compiler):
+ unwrapped_customize(compiler)
+ if compiler.compiler_type == 'unix':
+ if compiler.compiler[0].find('clang') != -1:
+ global clang
+ clang = True
+ compiler.compiler = filter_unsupported_flags(compiler.compiler)
+ compiler.compiler_so = filter_unsupported_flags(
+ compiler.compiler_so)
+
+distutils.sysconfig.customize_compiler = monkey_with_compiler
+
+if not pkgutil.find_loader('setuptools'):
+ from distutils.core import setup
+ from distutils.extension import Extension
+else:
+ from setuptools import setup
+ from setuptools.extension import Extension
+
+# PEP 440 versioning of the RBD package on PyPI
+# Bump this version, after every changeset
+
+__version__ = '2.0.0'
+
+
+def get_python_flags():
+ cflags = {'I': [], 'extras': []}
+ ldflags = {'l': [], 'L': [], 'extras': []}
+
+ if os.environ.get('VIRTUAL_ENV', None):
+ python = "python"
+ else:
+ python = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
+
+ python_config = python + '-config'
+
+ for cflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--cflags"]).strip().decode('utf-8').split()):
+ if cflag.startswith('-I'):
+ cflags['I'].append(cflag.replace('-I', ''))
+ else:
+ cflags['extras'].append(cflag)
+
+ for ldflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--ldflags"]).strip().decode('utf-8').split()):
+ if ldflag.startswith('-l'):
+ ldflags['l'].append(ldflag.replace('-l', ''))
+ if ldflag.startswith('-L'):
+ ldflags['L'].append(ldflag.replace('-L', ''))
+ else:
+ ldflags['extras'].append(ldflag)
+
+ return {
+ 'cflags': cflags,
+ 'ldflags': ldflags
+ }
+
+
+def check_sanity():
+ """
+ Test if development headers and library for rbd is available by compiling a dummy C program.
+ """
+ CEPH_SRC_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..',
+ '..'
+ )
+
+ tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__)))
+ tmp_file = os.path.join(tmp_dir, 'rbd_dummy.c')
+
+ with open(tmp_file, 'w') as fp:
+ dummy_prog = textwrap.dedent("""
+ #include <stddef.h>
+ #include <rbd/librbd.h>
+ int main(void) {
+ rados_t cluster;
+ rados_create(&cluster, NULL);
+ return 0;
+ }
+ """)
+ fp.write(dummy_prog)
+
+ compiler = new_compiler()
+ distutils.sysconfig.customize_compiler(compiler)
+
+ if {'MAKEFLAGS', 'MFLAGS', 'MAKELEVEL'}.issubset(set(os.environ.keys())):
+ # The setup.py has been invoked by a top-level Ceph make.
+ # Set the appropriate CFLAGS and LDFLAGS
+
+ compiler.set_include_dirs([os.path.join(CEPH_SRC_DIR, 'include')])
+ compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')])
+
+ try:
+ compiler.define_macro('_FILE_OFFSET_BITS', '64')
+
+ link_objects = compiler.compile(
+ sources=[tmp_file],
+ output_dir=tmp_dir
+ )
+
+ compiler.link_executable(
+ objects=link_objects,
+ output_progname=os.path.join(tmp_dir, 'rbd_dummy'),
+ libraries=['rbd', 'rados'],
+ output_dir=tmp_dir,
+ )
+
+ except CompileError:
+ print('\nCompile Error: RBD development headers not found', file=sys.stderr)
+ return False
+ except LinkError:
+ print('\nLink Error: RBD library not found', file=sys.stderr)
+ return False
+ else:
+ return True
+ finally:
+ shutil.rmtree(tmp_dir)
+
+
+if 'BUILD_DOC' in os.environ.keys():
+ pass
+elif check_sanity():
+ pass
+else:
+ sys.exit(1)
+
+cmdclass = {}
+try:
+ from Cython.Build import cythonize
+ from Cython.Distutils import build_ext
+
+ cmdclass = {'build_ext': build_ext}
+except ImportError:
+ print("WARNING: Cython is not installed.")
+
+ if not os.path.isfile('rbd.c'):
+ print('ERROR: Cannot find Cythonized file rbd.c', file=sys.stderr)
+ sys.exit(1)
+ else:
+ def cythonize(x, **kwargs):
+ return x
+
+ source = "rbd.c"
+else:
+ source = "rbd.pyx"
+
+# Disable cythonification if we're not really building anything
+if (len(sys.argv) >= 2 and
+ any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version')
+ )):
+ def cythonize(x, **kwargs):
+ return x
+
+flags = get_python_flags()
+
+setup(
+ name='rbd',
+ version=__version__,
+ description="Python bindings for the RBD library",
+ long_description=(
+ "This package contains Python bindings for interacting with the "
+ "RADOS Block Device (RBD) library. rbd is a utility for manipulating "
+ "rados block device images, used by the Linux rbd driver and the rbd "
+ "storage driver for QEMU/KVM. RBD images are simple block devices that "
+ "are striped over objects and stored in a RADOS object store. The size "
+ "of the objects the image is striped over must be a power of two."
+ ),
+ url='https://github.com/ceph/ceph/tree/master/src/pybind/rbd',
+ license='LGPLv2+',
+ platforms='Linux',
+ ext_modules=cythonize(
+ [
+ Extension(
+ "rbd",
+ [source],
+ include_dirs=flags['cflags']['I'],
+ library_dirs=flags['ldflags']['L'],
+ libraries=['rbd', 'rados'] + flags['ldflags']['l'],
+ extra_compile_args=flags['cflags']['extras'] + flags['ldflags']['extras'],
+ )
+ ],
+ build_dir=os.environ.get("CYTHON_BUILD_DIR", None),
+ include_path=[
+ os.path.join(os.path.dirname(__file__), "..", "rados")
+ ]
+ ),
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Cython',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5'
+ ],
+ cmdclass=cmdclass,
+)
diff --git a/src/pybind/rgw/CMakeLists.txt b/src/pybind/rgw/CMakeLists.txt
new file mode 100644
index 00000000..da2cdcdf
--- /dev/null
+++ b/src/pybind/rgw/CMakeLists.txt
@@ -0,0 +1,3 @@
+distutils_add_cython_module(cython${PYTHON_VERSION}_rgw ${CMAKE_CURRENT_SOURCE_DIR}/rgw.pyx)
+add_dependencies(cython${PYTHON_VERSION}_rgw rgw)
+distutils_install_cython_module(cython${PYTHON_VERSION}_rgw)
diff --git a/src/pybind/rgw/MANIFEST.in b/src/pybind/rgw/MANIFEST.in
new file mode 100644
index 00000000..330f3fd1
--- /dev/null
+++ b/src/pybind/rgw/MANIFEST.in
@@ -0,0 +1 @@
+include rgw.pyx
diff --git a/src/pybind/rgw/rgw.pyx b/src/pybind/rgw/rgw.pyx
new file mode 100644
index 00000000..d5db7f5d
--- /dev/null
+++ b/src/pybind/rgw/rgw.pyx
@@ -0,0 +1,694 @@
+"""
+This module is a thin wrapper around rgw_file.
+"""
+
+
+from cpython cimport PyObject, ref, exc, array
+from libc.stdint cimport *
+from libcpp cimport bool
+from libc.stdlib cimport malloc, realloc, free
+
+cimport rados
+
+from collections import namedtuple
+from datetime import datetime
+import errno
+
+
+cdef extern from "Python.h":
+ # These are in cpython/string.pxd, but use "object" types instead of
+ # PyObject*, which invokes assumptions in cpython that we need to
+ # legitimately break to implement zero-copy string buffers in Image.read().
+ # This is valid use of the Python API and documented as a special case.
+ PyObject *PyBytes_FromStringAndSize(char *v, Py_ssize_t len) except NULL
+ char* PyBytes_AsString(PyObject *string) except NULL
+ int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
+ void PyEval_InitThreads()
+
+
+cdef extern from "time.h":
+ ctypedef long int time_t
+
+
+cdef extern from "sys/stat.h":
+ cdef struct stat:
+ unsigned long st_dev
+ unsigned long st_ino
+ unsigned long st_nlink
+ unsigned int st_mode
+ unsigned int st_uid
+ unsigned int st_gid
+ int __pad0
+ unsigned long st_rdev
+ long int st_size
+ long int st_blksize
+ long int st_blocks
+ time_t st_atime
+ time_t st_mtime
+ time_t st_ctime
+
+
+cdef extern from "rados/librgw.h" nogil:
+ ctypedef void* librgw_t
+
+ int librgw_create(librgw_t *rgw, int argc, char **argv)
+ void librgw_shutdown(librgw_t rgw)
+
+
+cdef extern from "rados/rgw_file.h" nogil:
+ enum:
+ RGW_FS_TYPE_FILE
+ RGW_FS_TYPE_DIRECTORY
+
+ RGW_LOOKUP_FLAG_CREATE
+
+ RGW_SETATTR_MODE
+ RGW_SETATTR_UID
+ RGW_SETATTR_GID
+ RGW_SETATTR_MTIME
+ RGW_SETATTR_ATIME
+ RGW_SETATTR_SIZE
+ RGW_SETATTR_CTIME
+
+ RGW_READDIR_FLAG_NONE
+ RGW_READDIR_FLAG_DOTDOT
+
+ RGW_OPEN_FLAG_CREATE
+ RGW_OPEN_FLAG_V3 # ops have v3 semantics
+ RGW_OPEN_FLAG_STATELESS # alias it
+
+ RGW_CLOSE_FLAG_RELE
+
+
+ ctypedef void *rgw_fh_hk
+ cdef struct rgw_file_handle:
+ pass
+
+ cdef struct rgw_fs:
+ librgw_t rgw
+ void *fs_private
+ void *root_fh
+
+ # mount info hypothetical--emulate Unix, support at least UUID-length fsid
+ cdef struct rgw_statvfs:
+ uint64_t f_bsize # file system block size
+ uint64_t f_frsize # fragment size
+ uint64_t f_blocks # size of fs in f_frsize units
+ uint64_t f_bfree # free blocks
+ uint64_t f_bavail # free blocks for unprivileged users
+ uint64_t f_files # inodes
+ uint64_t f_ffree # free inodes
+ uint64_t f_favail # free inodes for unprivileged users
+ uint64_t f_fsid[2] # /* file system ID
+ uint64_t f_flag # mount flags
+ uint64_t f_namemax # maximum filename length
+
+ void rgwfile_version(int *major, int *minor, int *extra)
+
+ int rgw_lookup(rgw_fs *fs,
+ rgw_file_handle *parent_fh, const char *path,
+ rgw_file_handle **fh, stat* st, uint32_t st_mask,
+ uint32_t flags)
+
+ int rgw_lookup_handle(rgw_fs *fs, rgw_fh_hk *fh_hk,
+ rgw_file_handle **fh, uint32_t flags)
+
+ int rgw_fh_rele(rgw_fs *fs, rgw_file_handle *fh,
+ uint32_t flags)
+
+ int rgw_mount(librgw_t rgw, const char *uid, const char *key,
+ const char *secret, rgw_fs **fs, uint32_t flags)
+
+ int rgw_umount(rgw_fs *fs, uint32_t flags)
+
+ int rgw_statfs(rgw_fs *fs, rgw_file_handle *parent_fh,
+ rgw_statvfs *vfs_st, uint32_t flags)
+
+ int rgw_create(rgw_fs *fs, rgw_file_handle *parent_fh,
+ const char *name, stat *st, uint32_t mask,
+ rgw_file_handle **fh, uint32_t posix_flags,
+ uint32_t flags)
+
+ int rgw_mkdir(rgw_fs *fs,
+ rgw_file_handle *parent_fh,
+ const char *name, stat *st, uint32_t mask,
+ rgw_file_handle **fh, uint32_t flags)
+
+ int rgw_rename(rgw_fs *fs,
+ rgw_file_handle *olddir, const char* old_name,
+ rgw_file_handle *newdir, const char* new_name,
+ uint32_t flags)
+
+ int rgw_unlink(rgw_fs *fs,
+ rgw_file_handle *parent_fh, const char* path,
+ uint32_t flags)
+
+ int rgw_readdir(rgw_fs *fs,
+ rgw_file_handle *parent_fh, uint64_t *offset,
+ bool (*cb)(const char *name, void *arg, uint64_t offset, stat *st, uint32_t st_mask, uint32_t flags) nogil except? -9000,
+ void *cb_arg, bool *eof, uint32_t flags) except? -9000
+
+ int rgw_getattr(rgw_fs *fs,
+ rgw_file_handle *fh, stat *st,
+ uint32_t flags)
+
+ int rgw_setattr(rgw_fs *fs, rgw_file_handle *fh, stat *st,
+ uint32_t mask, uint32_t flags)
+
+ int rgw_truncate(rgw_fs *fs, rgw_file_handle *fh, uint64_t size, uint32_t flags)
+
+ int rgw_open(rgw_fs *fs, rgw_file_handle *parent_fh,
+ uint32_t posix_flags, uint32_t flags)
+
+ int rgw_close(rgw_fs *fs, rgw_file_handle *fh,
+ uint32_t flags)
+
+ int rgw_read(rgw_fs *fs,
+ rgw_file_handle *fh, uint64_t offset,
+ size_t length, size_t *bytes_read, void *buffer,
+ uint32_t flags)
+
+ int rgw_write(rgw_fs *fs,
+ rgw_file_handle *fh, uint64_t offset,
+ size_t length, size_t *bytes_written, void *buffer,
+ uint32_t flags)
+
+ int rgw_fsync(rgw_fs *fs, rgw_file_handle *fh,
+ uint32_t flags)
+
+ int rgw_commit(rgw_fs *fs, rgw_file_handle *fh,
+ uint64_t offset, uint64_t length, uint32_t flags)
+
+
+class Error(Exception):
+ pass
+
+
+class OSError(Error):
+ """ `OSError` class, derived from `Error` """
+ def __init__(self, errno, strerror):
+ self.errno = errno
+ self.strerror = strerror
+
+ def __str__(self):
+ return '[Errno {0}] {1}'.format(self.errno, self.strerror)
+
+
+class PermissionError(OSError):
+ pass
+
+
+class ObjectNotFound(OSError):
+ pass
+
+
+class NoData(Error):
+ pass
+
+
+class ObjectExists(Error):
+ pass
+
+
+class IOError(OSError):
+ pass
+
+
+class NoSpace(Error):
+ pass
+
+
+class InvalidValue(Error):
+ pass
+
+
+class OperationNotSupported(Error):
+ pass
+
+
+class IncompleteWriteError(Error):
+ pass
+
+
+class LibCephFSStateError(Error):
+ pass
+
+class WouldBlock(Error):
+ pass
+
+class OutOfRange(Error):
+ pass
+
+IF UNAME_SYSNAME == "FreeBSD":
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.ENOATTR : NoData,
+ errno.EINVAL : InvalidValue,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ errno.ERANGE : OutOfRange,
+ errno.EWOULDBLOCK: WouldBlock,
+ }
+ELSE:
+ cdef errno_to_exception = {
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ObjectNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ObjectExists,
+ errno.ENODATA : NoData,
+ errno.EINVAL : InvalidValue,
+ errno.EOPNOTSUPP : OperationNotSupported,
+ errno.ERANGE : OutOfRange,
+ errno.EWOULDBLOCK: WouldBlock,
+ }
+
+
+cdef class FileHandle(object):
+ cdef rgw_file_handle *handler
+
+
+StatResult = namedtuple('StatResult',
+ ["st_dev", "st_ino", "st_mode", "st_nlink", "st_uid",
+ "st_gid", "st_rdev", "st_size", "st_blksize",
+ "st_blocks", "st_atime", "st_mtime", "st_ctime"])
+
+
+def cstr(val, name, encoding="utf-8", opt=False):
+ """
+ Create a byte string from a Python string
+
+ :param basestring val: Python string
+ :param str name: Name of the string parameter, for exceptions
+ :param str encoding: Encoding to use
+ :param bool opt: If True, None is allowed
+ :rtype: bytes
+ :raises: :class:`InvalidArgument`
+ """
+ if opt and val is None:
+ return None
+ if isinstance(val, bytes):
+ return val
+ elif isinstance(val, unicode):
+ return val.encode(encoding)
+ else:
+ raise TypeError('%s must be a string' % name)
+
+
+cdef make_ex(ret, msg):
+ """
+ Translate a librados return code into an exception.
+
+ :param ret: the return code
+ :type ret: int
+ :param msg: the error message to use
+ :type msg: str
+ :returns: a subclass of :class:`Error`
+ """
+ ret = abs(ret)
+ if ret in errno_to_exception:
+ return errno_to_exception[ret](ret, msg)
+ else:
+ return Error(msg + (": error code %d" % ret))
+
+
+cdef bool readdir_cb(const char *name, void *arg, uint64_t offset, stat *st, uint32_t st_mask, uint32_t flags) \
+except? -9000 with gil:
+ if exc.PyErr_Occurred():
+ return False
+ (<object>arg)(name, offset, flags)
+ return True
+
+
+class LibCephFSStateError(Error):
+ pass
+
+
+cdef class LibRGWFS(object):
+ """librgwfs python wrapper"""
+
+ cdef public object state
+ cdef public object uid
+ cdef public object key
+ cdef public object secret
+ cdef librgw_t cluster
+ cdef rgw_fs *fs
+
+ def require_state(self, *args):
+ if self.state in args:
+ return
+ raise LibCephFSStateError("You cannot perform that operation on a "
+ "RGWFS object in state %s." % (self.state))
+
+ def __cinit__(self, uid, key, secret):
+ PyEval_InitThreads()
+ self.state = "umounted"
+ ret = librgw_create(&self.cluster, 0, NULL)
+ if ret != 0:
+ raise make_ex(ret, "error calling librgw_create")
+ self.uid = cstr(uid, "uid")
+ self.key = cstr(key, "key")
+ self.secret = cstr(secret, "secret")
+
+ def shutdown(self):
+ """
+ Unmount and destroy the ceph mount handle.
+ """
+ if self.state in ["mounted"]:
+ with nogil:
+ ret = rgw_umount(self.fs, 0);
+ if ret != 0:
+ raise make_ex(ret, "error calling rgw_unmount")
+ self.state = "shutdown"
+
+ def __enter__(self):
+ self.mount()
+ return self
+
+ def __exit__(self, type_, value, traceback):
+ self.shutdown()
+
+ def __dealloc__(self):
+ self.shutdown()
+
+ def version(self):
+ """
+ Get the version number of the ``librgwfile`` C library.
+
+ :returns: a tuple of ``(major, minor, extra)`` components of the
+ libcephfs version
+ """
+ cdef:
+ int major = 0
+ int minor = 0
+ int extra = 0
+ with nogil:
+ rgwfile_version(&major, &minor, &extra)
+ return (major, minor, extra)
+
+ def mount(self):
+ self.require_state("umounted")
+ cdef:
+ char *_uid = self.uid
+ char *_key = self.key
+ char *_secret = self.secret
+ with nogil:
+ ret = rgw_mount(self.cluster, <const char*>_uid, <const char*>_key,
+ <const char*>_secret, &self.fs, 0)
+ if ret != 0:
+ raise make_ex(ret, "error calling rgw_mount")
+ self.state = "mounted"
+ dir_handler = FileHandle()
+ dir_handler.handler = <rgw_file_handle*>self.fs.root_fh
+ return dir_handler
+
+ def unmount(self):
+ self.require_state("mounted")
+ with nogil:
+ ret = rgw_umount(self.fs, 0)
+ if ret != 0:
+ raise make_ex(ret, "error calling rgw_umount")
+ self.state = "umounted"
+
+ def statfs(self):
+ self.require_state("mounted")
+ cdef:
+ rgw_statvfs statbuf
+
+ with nogil:
+ ret = rgw_statfs(self.fs, <rgw_file_handle*>self.fs.root_fh, &statbuf, 0)
+ if ret < 0:
+ raise make_ex(ret, "statfs failed")
+ cdef uint64_t[:] fsid = statbuf.f_fsid
+ return {'f_bsize': statbuf.f_bsize,
+ 'f_frsize': statbuf.f_frsize,
+ 'f_blocks': statbuf.f_blocks,
+ 'f_bfree': statbuf.f_bfree,
+ 'f_bavail': statbuf.f_bavail,
+ 'f_files': statbuf.f_files,
+ 'f_ffree': statbuf.f_ffree,
+ 'f_favail': statbuf.f_favail,
+ 'f_fsid': fsid,
+ 'f_flag': statbuf.f_flag,
+ 'f_namemax': statbuf.f_namemax}
+
+
+ def create(self, FileHandle dir_handler, filename, flags = 0):
+ self.require_state("mounted")
+
+ if not isinstance(flags, int):
+ raise TypeError("flags must be an integer")
+
+ filename = cstr(filename, 'filename')
+
+ cdef:
+ rgw_file_handle *_dir_handler = <rgw_file_handle*>dir_handler.handler
+ rgw_file_handle *_file_handler
+ int _flags = flags
+ char* _filename = filename
+ stat statbuf
+
+ with nogil:
+ ret = rgw_create(self.fs, _dir_handler, _filename, &statbuf, 0,
+ &_file_handler, 0, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in create '%s'" % filename)
+ with nogil:
+ ret = rgw_open(self.fs, _file_handler, 0, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in open '%s'" % filename)
+
+ file_handler = FileHandle()
+ file_handler.handler = _file_handler
+ return file_handler
+
+ def mkdir(self, FileHandle dir_handler, dirname, flags = 0):
+ self.require_state("mounted")
+ dirname = cstr(dirname, 'dirname')
+ new_dir_handler = FileHandle()
+ cdef:
+ rgw_file_handle *_dir_handler = <rgw_file_handle*>dir_handler.handler
+ rgw_file_handle *_new_dir_handler
+ char* _dirname = dirname
+ int _flags = flags
+ stat statbuf
+ with nogil:
+ ret = rgw_mkdir(self.fs, _dir_handler, _dirname, &statbuf,
+ 0, &_new_dir_handler, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in mkdir '%s'" % dirname)
+ new_dir_handler.handler = _new_dir_handler
+ return new_dir_handler
+
+ def rename(self, FileHandle src_handler, src_name, FileHandle dst_handler, dst_name, flags = 0):
+ self.require_state("mounted")
+
+ src_name = cstr(src_name, 'src_name')
+ dst_name = cstr(dst_name, 'dst_name')
+
+ cdef:
+ rgw_file_handle *_src_dir_handler = <rgw_file_handle*>src_handler.handler
+ rgw_file_handle *_dst_dir_handler = <rgw_file_handle*>dst_handler.handler
+ char* _src_name = src_name
+ char* _dst_name = dst_name
+ int _flags = flags
+
+ with nogil:
+ ret = rgw_rename(self.fs, _src_dir_handler, _src_name,
+ _dst_dir_handler, _dst_name, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in rename '%s' to '%s'" % (src_name,
+ dst_name))
+ return ret
+
+ def unlink(self, FileHandle handler, name, flags = 0):
+ self.require_state("mounted")
+ name = cstr(name, 'name')
+ cdef:
+ rgw_file_handle *_handler = <rgw_file_handle*>handler.handler
+ int _flags = flags
+ char* _name = name
+ with nogil:
+ ret = rgw_unlink(self.fs, _handler, _name, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in unlink")
+ return ret
+
+ def readdir(self, FileHandle dir_handler, iterate_cb, offset, flags = 0):
+ self.require_state("mounted")
+
+ cdef:
+ rgw_file_handle *_dir_handler = <rgw_file_handle*>dir_handler.handler
+ uint64_t _offset = offset
+ bool _eof
+ uint32_t _flags = flags
+ with nogil:
+ ret = rgw_readdir(self.fs, _dir_handler, &_offset, &readdir_cb,
+ <void *>iterate_cb, &_eof, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in readdir")
+
+ return (_offset, _eof)
+
+ def fstat(self, FileHandle file_handler):
+ self.require_state("mounted")
+
+ cdef:
+ rgw_file_handle *_file_handler = <rgw_file_handle*>file_handler.handler
+ stat statbuf
+
+ with nogil:
+ ret = rgw_getattr(self.fs, _file_handler, &statbuf, 0)
+ if ret < 0:
+ raise make_ex(ret, "error in getattr")
+ return StatResult(st_dev=statbuf.st_dev, st_ino=statbuf.st_ino,
+ st_mode=statbuf.st_mode, st_nlink=statbuf.st_nlink,
+ st_uid=statbuf.st_uid, st_gid=statbuf.st_gid,
+ st_rdev=statbuf.st_rdev, st_size=statbuf.st_size,
+ st_blksize=statbuf.st_blksize,
+ st_blocks=statbuf.st_blocks,
+ st_atime=datetime.fromtimestamp(statbuf.st_atime),
+ st_mtime=datetime.fromtimestamp(statbuf.st_mtime),
+ st_ctime=datetime.fromtimestamp(statbuf.st_ctime))
+
+ def opendir(self, FileHandle dir_handler, dirname, flags = 0):
+ self.require_state("mounted")
+
+ if not isinstance(flags, int):
+ raise TypeError("flags must be an integer")
+
+ dirname = cstr(dirname, 'dirname')
+
+ cdef:
+ rgw_file_handle *_dir_handler = <rgw_file_handle*>dir_handler.handler
+ rgw_file_handle *_file_handler
+ int _flags = flags
+ char* _dirname = dirname
+ stat st
+ uint32_t st_mask = 0
+
+ with nogil:
+ ret = rgw_lookup(self.fs, _dir_handler, _dirname,
+ &_file_handler, &st, st_mask, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in open '%s'" % dirname)
+
+ file_handler = FileHandle()
+ file_handler.handler = _file_handler
+ return file_handler
+
+ def open(self, FileHandle dir_handler, filename, flags = 0):
+ self.require_state("mounted")
+
+ if not isinstance(flags, int):
+ raise TypeError("flags must be an integer")
+
+ filename = cstr(filename, 'filename')
+
+ cdef:
+ rgw_file_handle *_dir_handler = <rgw_file_handle*>dir_handler.handler
+ rgw_file_handle *_file_handler
+ int _flags = flags
+ char* _filename = filename
+ stat st
+ uint32_t st_mask = 0
+
+ with nogil:
+ ret = rgw_lookup(self.fs, _dir_handler, _filename,
+ &_file_handler, &st, st_mask, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in open '%s'" % filename)
+ with nogil:
+ ret = rgw_open(self.fs, _file_handler, 0, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in open '%s'" % filename)
+
+ file_handler = FileHandle()
+ file_handler.handler = _file_handler
+ return file_handler
+
+ def close(self, FileHandle file_handler, flags = 0):
+ self.require_state("mounted")
+ cdef:
+ rgw_file_handle *_file_handler = <rgw_file_handle*>file_handler.handler
+ int _flags = flags
+ with nogil:
+ ret = rgw_close(self.fs, _file_handler, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in close")
+
+ def read(self, FileHandle file_handler, offset, l, flags = 0):
+ self.require_state("mounted")
+ if not isinstance(offset, int):
+ raise TypeError('offset must be an int')
+ if not isinstance(l, int):
+ raise TypeError('l must be an int')
+ cdef:
+ rgw_file_handle *_file_handler = <rgw_file_handle*>file_handler.handler
+ int64_t _offset = offset
+ size_t _length = l
+ size_t _got
+ int _flags = flags
+
+ char *ret_buf
+ PyObject* ret_s = NULL
+
+ ret_s = PyBytes_FromStringAndSize(NULL, _length)
+ try:
+ ret_buf = PyBytes_AsString(ret_s)
+ with nogil:
+ ret = rgw_read(self.fs, _file_handler, _offset, _length,
+ &_got, ret_buf, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in read")
+
+ if _got < _length:
+ _PyBytes_Resize(&ret_s, _got)
+
+ return <object>ret_s
+ finally:
+ # We DECREF unconditionally: the cast to object above will have
+ # INCREFed if necessary. This also takes care of exceptions,
+ # including if _PyString_Resize fails (that will free the string
+ # itself and set ret_s to NULL, hence XDECREF).
+ ref.Py_XDECREF(ret_s)
+
+
+ def write(self, FileHandle file_handler, offset, buf, flags = 0):
+ self.require_state("mounted")
+ if not isinstance(buf, bytes):
+ raise TypeError('buf must be a bytes')
+ if not isinstance(offset, int):
+ raise TypeError('offset must be an int')
+
+ cdef:
+ rgw_file_handle *_file_handler = <rgw_file_handle*>file_handler.handler
+ char *_data = buf
+ int64_t _offset = offset
+
+ size_t length = len(buf)
+ int _flags = flags
+ size_t _written
+
+ with nogil:
+ ret = rgw_write(self.fs, _file_handler, _offset, length, &_written,
+ _data, _flags)
+ if ret < 0:
+ raise make_ex(ret, "error in write")
+ return ret
+
+
+ def fsync(self, FileHandle handler, flags = 0):
+ self.require_state("mounted")
+
+ cdef:
+ rgw_file_handle *_file_handler = <rgw_file_handle*>handler.handler
+ int _flags = flags
+ with nogil:
+ ret = rgw_fsync(self.fs, _file_handler, _flags)
+
+ if ret < 0:
+ raise make_ex(ret, "fsync failed")
diff --git a/src/pybind/rgw/setup.py b/src/pybind/rgw/setup.py
new file mode 100755
index 00000000..4ee4f491
--- /dev/null
+++ b/src/pybind/rgw/setup.py
@@ -0,0 +1,224 @@
+from __future__ import print_function
+
+import os
+import pkgutil
+import shutil
+import subprocess
+import sys
+import tempfile
+import textwrap
+from distutils.ccompiler import new_compiler
+from distutils.errors import CompileError, LinkError
+import distutils.sysconfig
+
+unwrapped_customize = distutils.sysconfig.customize_compiler
+
+clang = False
+
+def filter_unsupported_flags(flags):
+ if clang:
+ return [f for f in flags if not (f == '-mcet' or
+ f.startswith('-fcf-protection'))]
+ return flags
+
+def monkey_with_compiler(compiler):
+ unwrapped_customize(compiler)
+ if compiler.compiler_type == 'unix':
+ if compiler.compiler[0].find('clang') != -1:
+ global clang
+ clang = True
+ compiler.compiler = filter_unsupported_flags(compiler.compiler)
+ compiler.compiler_so = filter_unsupported_flags(
+ compiler.compiler_so)
+
+# See what you made me do?
+
+distutils.sysconfig.customize_compiler = monkey_with_compiler
+
+import distutils.core
+
+if not pkgutil.find_loader('setuptools'):
+ from distutils.core import setup
+ from distutils.extension import Extension
+else:
+ from setuptools import setup
+ from setuptools.extension import Extension
+
+# PEP 440 versioning of the RGW package on PyPI
+# Bump this version, after every changeset
+
+__version__ = '2.0.0'
+
+def get_python_flags():
+ cflags = {'I': [], 'extras': []}
+ ldflags = {'l': [], 'L': [], 'extras': []}
+
+ if os.environ.get('VIRTUAL_ENV', None):
+ python = "python"
+ else:
+ python = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
+
+ python_config = python + '-config'
+
+ for cflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--cflags"]).strip().decode('utf-8').split()):
+ if cflag.startswith('-I'):
+ cflags['I'].append(cflag.replace('-I', ''))
+ else:
+ cflags['extras'].append(cflag)
+
+ for ldflag in filter_unsupported_flags(subprocess.check_output(
+ [python_config, "--ldflags"]).strip().decode('utf-8').split()):
+ if ldflag.startswith('-l'):
+ ldflags['l'].append(ldflag.replace('-l', ''))
+ if ldflag.startswith('-L'):
+ ldflags['L'].append(ldflag.replace('-L', ''))
+ else:
+ ldflags['extras'].append(ldflag)
+
+ return {
+ 'cflags': cflags,
+ 'ldflags': ldflags
+ }
+
+
+def check_sanity():
+ """
+ Test if development headers and library for rgw is available by compiling a dummy C program.
+ """
+ CEPH_SRC_DIR = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ '..',
+ '..'
+ )
+
+ tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__)))
+ tmp_file = os.path.join(tmp_dir, 'rgw_dummy.c')
+
+ with open(tmp_file, 'w') as fp:
+ dummy_prog = textwrap.dedent("""
+ #include <stddef.h>
+ #include "rados/rgw_file.h"
+
+ int main(void) {
+ rgwfile_version(NULL, NULL, NULL);
+ return 0;
+ }
+ """)
+ fp.write(dummy_prog)
+
+ compiler = new_compiler()
+ distutils.sysconfig.customize_compiler(compiler)
+
+ if {'MAKEFLAGS', 'MFLAGS', 'MAKELEVEL'}.issubset(set(os.environ.keys())):
+ # The setup.py has been invoked by a top-level Ceph make.
+ # Set the appropriate CFLAGS and LDFLAGS
+
+ compiler.set_include_dirs([os.path.join(CEPH_SRC_DIR, 'include')])
+ compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')])
+
+ try:
+ compiler.define_macro('_FILE_OFFSET_BITS', '64')
+
+ link_objects = compiler.compile(
+ sources=[tmp_file],
+ output_dir=tmp_dir,
+ )
+
+ compiler.link_executable(
+ objects=link_objects,
+ output_progname=os.path.join(tmp_dir, 'rgw_dummy'),
+ libraries=['rgw', 'rados'],
+ output_dir=tmp_dir,
+ )
+
+ except CompileError:
+ print('\nCompile Error: RGW development headers not found', file=sys.stderr)
+ return False
+ except LinkError:
+ print('\nLink Error: RGW library not found', file=sys.stderr)
+ return False
+ else:
+ return True
+ finally:
+ shutil.rmtree(tmp_dir)
+
+
+if 'BUILD_DOC' in os.environ.keys():
+ pass
+elif check_sanity():
+ pass
+else:
+ sys.exit(1)
+
+cmdclass = {}
+try:
+ from Cython.Build import cythonize
+ from Cython.Distutils import build_ext
+
+ cmdclass = {'build_ext': build_ext}
+except ImportError:
+ print("WARNING: Cython is not installed.")
+
+ if not os.path.isfile('rgw.c'):
+ print('ERROR: Cannot find Cythonized file rgw.c', file=sys.stderr)
+ sys.exit(1)
+ else:
+ def cythonize(x, **kwargs):
+ return x
+
+ source = "rgw.c"
+else:
+ source = "rgw.pyx"
+
+# Disable cythonification if we're not really building anything
+if (len(sys.argv) >= 2 and
+ any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version')
+ )):
+ def cythonize(x, **kwargs):
+ return x
+
+flags = get_python_flags()
+
+setup(
+ name='rgw',
+ version=__version__,
+ description="Python bindings for the RGW library",
+ long_description=(
+ "This package contains Python bindings for interacting with the "
+ "RGW library. RGW is a Object Storage Gateway "
+ "that uses a Ceph Storage Cluster to store its data. The "
+ "Ceph Object Storage support S3 and Swift APIs, "
+ "and file operations."
+ ),
+ url='https://github.com/ceph/ceph/tree/master/src/pybind/rgw',
+ license='LGPLv2+',
+ platforms='Linux',
+ ext_modules=cythonize(
+ [
+ Extension(
+ "rgw",
+ [source],
+ include_dirs=flags['cflags']['I'],
+ library_dirs=flags['ldflags']['L'],
+ libraries=['rados', 'rgw'] + flags['ldflags']['l'],
+ extra_compile_args=flags['cflags']['extras'] + flags['ldflags']['extras'],
+ )
+ ],
+ build_dir=os.environ.get("CYTHON_BUILD_DIR", None),
+ include_path=[
+ os.path.join(os.path.dirname(__file__), "..", "rados")
+ ]
+ ),
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Cython',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5'
+ ],
+ cmdclass=cmdclass,
+)
diff --git a/src/pybind/tox.ini b/src/pybind/tox.ini
new file mode 100644
index 00000000..1882b6da
--- /dev/null
+++ b/src/pybind/tox.ini
@@ -0,0 +1,2 @@
+[pep8]
+ignore = E123,E203